summaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/.scm-settings112
-rw-r--r--include/Makefile.kmk286
-rw-r--r--include/VBox/AssertGuest.h1781
-rw-r--r--include/VBox/ExtPack/ExtPack.h647
-rw-r--r--include/VBox/Graphics/HGSMI.h251
-rw-r--r--include/VBox/Graphics/HGSMIBase.h60
-rw-r--r--include/VBox/Graphics/HGSMIChSetup.h88
-rw-r--r--include/VBox/Graphics/HGSMIChannels.h77
-rw-r--r--include/VBox/Graphics/HGSMIContext.h114
-rw-r--r--include/VBox/Graphics/HGSMIDefs.h128
-rw-r--r--include/VBox/Graphics/HGSMIHostCmd.h59
-rw-r--r--include/VBox/Graphics/HGSMIMemAlloc.h113
-rw-r--r--include/VBox/Graphics/Makefile.kup0
-rw-r--r--include/VBox/Graphics/VBoxUhgsmi.h145
-rw-r--r--include/VBox/Graphics/VBoxVideo.h1490
-rw-r--r--include/VBox/Graphics/VBoxVideo3D.h186
-rw-r--r--include/VBox/Graphics/VBoxVideoErr.h76
-rw-r--r--include/VBox/Graphics/VBoxVideoGuest.h185
-rw-r--r--include/VBox/Graphics/VBoxVideoIPRT.h114
-rw-r--r--include/VBox/Graphics/VBoxVideoVBE.h107
-rw-r--r--include/VBox/Graphics/VBoxVideoVBEPrivate.h245
-rw-r--r--include/VBox/GuestHost/DragAndDrop.h350
-rw-r--r--include/VBox/GuestHost/DragAndDropDefs.h112
-rw-r--r--include/VBox/GuestHost/GuestControl.h236
-rw-r--r--include/VBox/GuestHost/HGCMMock.h804
-rw-r--r--include/VBox/GuestHost/HGCMMockUtils.h428
-rw-r--r--include/VBox/GuestHost/Makefile.kup0
-rw-r--r--include/VBox/GuestHost/SharedClipboard-transfers.h993
-rw-r--r--include/VBox/GuestHost/SharedClipboard-win.h419
-rw-r--r--include/VBox/GuestHost/SharedClipboard-x11.h187
-rw-r--r--include/VBox/GuestHost/SharedClipboard.h354
-rw-r--r--include/VBox/GuestHost/clipboard-helper.h250
-rw-r--r--include/VBox/HostServices/DragAndDropSvc.h1198
-rw-r--r--include/VBox/HostServices/GuestControlSvc.h1500
-rw-r--r--include/VBox/HostServices/GuestPropertySvc.h553
-rw-r--r--include/VBox/HostServices/Makefile.kup0
-rw-r--r--include/VBox/HostServices/Service.h358
-rw-r--r--include/VBox/HostServices/VBoxClipboardExt.h66
-rw-r--r--include/VBox/HostServices/VBoxClipboardSvc.h1220
-rw-r--r--include/VBox/HostServices/VBoxHostChannel.h229
-rw-r--r--include/VBox/Makefile.kup0
-rw-r--r--include/VBox/RemoteDesktop/Makefile.kup0
-rw-r--r--include/VBox/RemoteDesktop/VRDE.h1615
-rw-r--r--include/VBox/RemoteDesktop/VRDEImage.h256
-rw-r--r--include/VBox/RemoteDesktop/VRDEInput.h234
-rw-r--r--include/VBox/RemoteDesktop/VRDEMousePtr.h82
-rw-r--r--include/VBox/RemoteDesktop/VRDEOrders.h310
-rw-r--r--include/VBox/RemoteDesktop/VRDESCard.h528
-rw-r--r--include/VBox/RemoteDesktop/VRDETSMF.h154
-rw-r--r--include/VBox/RemoteDesktop/VRDEVideoIn.h1093
-rw-r--r--include/VBox/SUPDrvMangling.h48
-rw-r--r--include/VBox/SUPR0StackWrapper.mac180
-rw-r--r--include/VBox/VBoxAuth.h209
-rw-r--r--include/VBox/VBoxCocoa.h89
-rw-r--r--include/VBox/VBoxCryptoIf.h320
-rw-r--r--include/VBox/VBoxDrvCfg-win.h91
-rw-r--r--include/VBox/VBoxGL2D.h390
-rw-r--r--include/VBox/VBoxGuest.h1012
-rw-r--r--include/VBox/VBoxGuestCoreTypes.h238
-rw-r--r--include/VBox/VBoxGuestLib.h1405
-rw-r--r--include/VBox/VBoxGuestLibSharedFolders.h131
-rw-r--r--include/VBox/VBoxGuestLibSharedFoldersInline.h1612
-rw-r--r--include/VBox/VBoxGuestMangling.h49
-rw-r--r--include/VBox/VBoxKeyboard.h56
-rw-r--r--include/VBox/VBoxNetCfg-win.h147
-rw-r--r--include/VBox/VBoxNetCmn-win.h163
-rw-r--r--include/VBox/VBoxOGL.h70
-rw-r--r--include/VBox/VBoxPktDmp.h186
-rw-r--r--include/VBox/VBoxTpG.h455
-rw-r--r--include/VBox/VDEPlug.h74
-rw-r--r--include/VBox/VDEPlugSymDefs.h73
-rw-r--r--include/VBox/VMMDev.h2034
-rw-r--r--include/VBox/VMMDevCoreTypes.h556
-rw-r--r--include/VBox/VMMDevTesting.h272
-rw-r--r--include/VBox/VMMDevTesting.mac148
-rw-r--r--include/VBox/apic.h493
-rw-r--r--include/VBox/apic.mac213
-rw-r--r--include/VBox/asmdefs.mac785
-rw-r--r--include/VBox/ata.h222
-rw-r--r--include/VBox/bios.h56
-rw-r--r--include/VBox/bios.mac44
-rw-r--r--include/VBox/bioslogo.h108
-rw-r--r--include/VBox/cdefs.h493
-rw-r--r--include/VBox/com/AutoLock.h704
-rw-r--r--include/VBox/com/ErrorInfo.h545
-rw-r--r--include/VBox/com/EventQueue.h151
-rw-r--r--include/VBox/com/Guid.h526
-rw-r--r--include/VBox/com/Makefile.kup0
-rw-r--r--include/VBox/com/MultiResult.h278
-rw-r--r--include/VBox/com/NativeEventQueue.h161
-rw-r--r--include/VBox/com/VirtualBox.h71
-rw-r--r--include/VBox/com/array.h1833
-rw-r--r--include/VBox/com/assert.h135
-rw-r--r--include/VBox/com/com.h102
-rw-r--r--include/VBox/com/defs.h606
-rw-r--r--include/VBox/com/errorprint.h401
-rw-r--r--include/VBox/com/list.h223
-rw-r--r--include/VBox/com/listeners.h194
-rw-r--r--include/VBox/com/microatl.h1408
-rw-r--r--include/VBox/com/mtlist.h220
-rw-r--r--include/VBox/com/ptr.h569
-rw-r--r--include/VBox/com/string.h1494
-rw-r--r--include/VBox/com/utils.h132
-rw-r--r--include/VBox/dbg.h1222
-rw-r--r--include/VBox/dbggui.h191
-rw-r--r--include/VBox/dbus-calls.h180
-rw-r--r--include/VBox/dbus.h139
-rw-r--r--include/VBox/dis.h912
-rw-r--r--include/VBox/disopcode.h1469
-rw-r--r--include/VBox/err.h3148
-rw-r--r--include/VBox/err.mac1230
-rw-r--r--include/VBox/err.sed66
-rw-r--r--include/VBox/hgcmsvc.h745
-rw-r--r--include/VBox/intnet.h1348
-rw-r--r--include/VBox/intnetinline.h837
-rw-r--r--include/VBox/iommu-amd.h2718
-rw-r--r--include/VBox/iommu-intel.h2915
-rw-r--r--include/VBox/log.h1239
-rw-r--r--include/VBox/msi.h287
-rw-r--r--include/VBox/nasm.mac44
-rw-r--r--include/VBox/ostypes.h305
-rw-r--r--include/VBox/param.h229
-rw-r--r--include/VBox/param.mac98
-rw-r--r--include/VBox/pci.h827
-rw-r--r--include/VBox/rawpci.h618
-rw-r--r--include/VBox/scsi.h339
-rw-r--r--include/VBox/scsiinline.h246
-rw-r--r--include/VBox/settings.h1539
-rw-r--r--include/VBox/shflsvc.h2151
-rw-r--r--include/VBox/sup.h2832
-rw-r--r--include/VBox/sup.mac157
-rw-r--r--include/VBox/types.h1258
-rw-r--r--include/VBox/usb.h280
-rw-r--r--include/VBox/usbfilter.h271
-rw-r--r--include/VBox/usblib-darwin.h72
-rw-r--r--include/VBox/usblib-solaris.h288
-rw-r--r--include/VBox/usblib-win.h309
-rw-r--r--include/VBox/usblib.h196
-rw-r--r--include/VBox/various.sed148
-rw-r--r--include/VBox/vd-cache-backend.h332
-rw-r--r--include/VBox/vd-common.h76
-rw-r--r--include/VBox/vd-filter-backend.h122
-rw-r--r--include/VBox/vd-ifs-internal.h710
-rw-r--r--include/VBox/vd-ifs.h1765
-rw-r--r--include/VBox/vd-image-backend.h617
-rw-r--r--include/VBox/vd-plugin.h106
-rw-r--r--include/VBox/vd.h1847
-rw-r--r--include/VBox/vdmedia.h226
-rw-r--r--include/VBox/version.h166
-rw-r--r--include/VBox/vmm/Makefile.kup0
-rw-r--r--include/VBox/vmm/apic.h107
-rw-r--r--include/VBox/vmm/cfgm.h245
-rw-r--r--include/VBox/vmm/cpuidcall.h107
-rw-r--r--include/VBox/vmm/cpuidcall.mac55
-rw-r--r--include/VBox/vmm/cpum.h3248
-rw-r--r--include/VBox/vmm/cpum.mac275
-rw-r--r--include/VBox/vmm/cpumctx-v1_6.h263
-rw-r--r--include/VBox/vmm/cpumctx.h1116
-rw-r--r--include/VBox/vmm/cpumdis.h61
-rw-r--r--include/VBox/vmm/dbgf.h3192
-rw-r--r--include/VBox/vmm/dbgfcorefmt.h188
-rw-r--r--include/VBox/vmm/dbgfflowtrace.h400
-rw-r--r--include/VBox/vmm/dbgfsel.h117
-rw-r--r--include/VBox/vmm/dbgftrace.h168
-rw-r--r--include/VBox/vmm/em.h345
-rw-r--r--include/VBox/vmm/gcm.h95
-rw-r--r--include/VBox/vmm/gim.h218
-rw-r--r--include/VBox/vmm/gmm.h828
-rw-r--r--include/VBox/vmm/gvm.h351
-rw-r--r--include/VBox/vmm/gvm.mac118
-rw-r--r--include/VBox/vmm/gvmm.h364
-rw-r--r--include/VBox/vmm/hm.h336
-rw-r--r--include/VBox/vmm/hm_svm.h1169
-rw-r--r--include/VBox/vmm/hm_vmx.h4644
-rw-r--r--include/VBox/vmm/hm_vmx.mac163
-rw-r--r--include/VBox/vmm/hmvmxinline.h1172
-rw-r--r--include/VBox/vmm/iem.h422
-rw-r--r--include/VBox/vmm/iom.h550
-rw-r--r--include/VBox/vmm/mm.h244
-rw-r--r--include/VBox/vmm/nem.h256
-rw-r--r--include/VBox/vmm/pdm.h54
-rw-r--r--include/VBox/vmm/pdmapi.h393
-rw-r--r--include/VBox/vmm/pdmasynccompletion.h160
-rw-r--r--include/VBox/vmm/pdmasynctask.h74
-rw-r--r--include/VBox/vmm/pdmaudiohostenuminline.h463
-rw-r--r--include/VBox/vmm/pdmaudioifs.h1567
-rw-r--r--include/VBox/vmm/pdmaudioinline.h1507
-rw-r--r--include/VBox/vmm/pdmblkcache.h432
-rw-r--r--include/VBox/vmm/pdmcardreaderinfs.h136
-rw-r--r--include/VBox/vmm/pdmcommon.h192
-rw-r--r--include/VBox/vmm/pdmcritsect.h143
-rw-r--r--include/VBox/vmm/pdmcritsectrw.h111
-rw-r--r--include/VBox/vmm/pdmdev.h9690
-rw-r--r--include/VBox/vmm/pdmdrv.h2497
-rw-r--r--include/VBox/vmm/pdmifs.h2366
-rw-r--r--include/VBox/vmm/pdmins.h99
-rw-r--r--include/VBox/vmm/pdmnetifs.h456
-rw-r--r--include/VBox/vmm/pdmnetinline.h724
-rw-r--r--include/VBox/vmm/pdmnetshaper.h93
-rw-r--r--include/VBox/vmm/pdmpci.h408
-rw-r--r--include/VBox/vmm/pdmpcidev.h803
-rw-r--r--include/VBox/vmm/pdmpcidevint.h238
-rw-r--r--include/VBox/vmm/pdmqueue.h169
-rw-r--r--include/VBox/vmm/pdmserialifs.h249
-rw-r--r--include/VBox/vmm/pdmsrv.h350
-rw-r--r--include/VBox/vmm/pdmstorageifs.h1059
-rw-r--r--include/VBox/vmm/pdmtask.h162
-rw-r--r--include/VBox/vmm/pdmthread.h311
-rw-r--r--include/VBox/vmm/pdmtpmifs.h163
-rw-r--r--include/VBox/vmm/pdmusb.h1502
-rw-r--r--include/VBox/vmm/pdmwebcaminfs.h156
-rw-r--r--include/VBox/vmm/pgm.h1129
-rw-r--r--include/VBox/vmm/selm.h114
-rw-r--r--include/VBox/vmm/ssm.h1354
-rw-r--r--include/VBox/vmm/stam.h1376
-rw-r--r--include/VBox/vmm/stam.mac392
-rw-r--r--include/VBox/vmm/tm.h322
-rw-r--r--include/VBox/vmm/trpm.h102
-rw-r--r--include/VBox/vmm/trpm.mac57
-rw-r--r--include/VBox/vmm/uvm.h195
-rw-r--r--include/VBox/vmm/vm.h1519
-rw-r--r--include/VBox/vmm/vm.mac187
-rw-r--r--include/VBox/vmm/vmapi.h485
-rw-r--r--include/VBox/vmm/vmcc.h148
-rw-r--r--include/VBox/vmm/vmcpuset.h124
-rw-r--r--include/VBox/vmm/vmm.h639
-rw-r--r--include/VBox/vmm/vmmr3vtable-def.h711
-rw-r--r--include/VBox/vmm/vmmr3vtable.h140
-rw-r--r--include/VBox/vrdpusb.h135
-rw-r--r--include/VBox/vscsi.h488
-rw-r--r--include/VBox/vusb.h1472
-rw-r--r--include/VBox/xrandr-calls.h80
-rw-r--r--include/VBox/xrandr.h125
-rw-r--r--include/iprt/Makefile.kup0
-rw-r--r--include/iprt/alloc.h46
-rw-r--r--include/iprt/alloca.h110
-rw-r--r--include/iprt/asm-amd64-x86-watcom-16.h831
-rw-r--r--include/iprt/asm-amd64-x86-watcom-32.h737
-rw-r--r--include/iprt/asm-amd64-x86.h3447
-rw-r--r--include/iprt/asm-arm.h321
-rw-r--r--include/iprt/asm-math.h445
-rw-r--r--include/iprt/asm-watcom-x86-16.h983
-rw-r--r--include/iprt/asm-watcom-x86-32.h741
-rw-r--r--include/iprt/asm.h8132
-rw-r--r--include/iprt/asmdefs.mac1379
-rw-r--r--include/iprt/asn1-generator-asn1-decoder.h40
-rw-r--r--include/iprt/asn1-generator-core.h50
-rw-r--r--include/iprt/asn1-generator-init.h48
-rw-r--r--include/iprt/asn1-generator-internal-header.h39
-rw-r--r--include/iprt/asn1-generator-pass.h1757
-rw-r--r--include/iprt/asn1-generator-sanity.h38
-rw-r--r--include/iprt/asn1.h2368
-rw-r--r--include/iprt/assert.h2893
-rw-r--r--include/iprt/assertcompile.h263
-rw-r--r--include/iprt/avl.h1195
-rw-r--r--include/iprt/base64.h353
-rw-r--r--include/iprt/bignum.h197
-rw-r--r--include/iprt/bldprog-strtab-template.cpp.h1335
-rw-r--r--include/iprt/bldprog-strtab.h259
-rw-r--r--include/iprt/buildconfig.h138
-rw-r--r--include/iprt/cdefs.h4901
-rw-r--r--include/iprt/cdrom.h195
-rw-r--r--include/iprt/cidr.h76
-rw-r--r--include/iprt/circbuf.h165
-rw-r--r--include/iprt/condvar.h297
-rw-r--r--include/iprt/coredumper.h105
-rw-r--r--include/iprt/cpp/Makefile.kup0
-rw-r--r--include/iprt/cpp/autores.h216
-rw-r--r--include/iprt/cpp/exception.h118
-rw-r--r--include/iprt/cpp/hardavlrange.h1284
-rw-r--r--include/iprt/cpp/hardavlslaballocator.h218
-rw-r--r--include/iprt/cpp/list.h1143
-rw-r--r--include/iprt/cpp/lock.h179
-rw-r--r--include/iprt/cpp/meta.h125
-rw-r--r--include/iprt/cpp/ministring.h1638
-rw-r--r--include/iprt/cpp/mtlist.h185
-rw-r--r--include/iprt/cpp/path.h249
-rw-r--r--include/iprt/cpp/restanyobject.h139
-rw-r--r--include/iprt/cpp/restarray.h463
-rw-r--r--include/iprt/cpp/restbase.h1106
-rw-r--r--include/iprt/cpp/restclient.h826
-rw-r--r--include/iprt/cpp/restoutput.h280
-rw-r--r--include/iprt/cpp/reststringmap.h499
-rw-r--r--include/iprt/cpp/utils.h149
-rw-r--r--include/iprt/cpp/xml.h1247
-rw-r--r--include/iprt/cpuset.h353
-rw-r--r--include/iprt/crc.h250
-rw-r--r--include/iprt/critsect.h768
-rw-r--r--include/iprt/crypto/Makefile.kup0
-rw-r--r--include/iprt/crypto/applecodesign.h290
-rw-r--r--include/iprt/crypto/cipher.h156
-rw-r--r--include/iprt/crypto/digest.h331
-rw-r--r--include/iprt/crypto/key.h126
-rw-r--r--include/iprt/crypto/misc.h76
-rw-r--r--include/iprt/crypto/pem.h304
-rw-r--r--include/iprt/crypto/pkcs7.h709
-rw-r--r--include/iprt/crypto/pkix.h582
-rw-r--r--include/iprt/crypto/rc4.h73
-rw-r--r--include/iprt/crypto/rsa.h166
-rw-r--r--include/iprt/crypto/spc.h533
-rw-r--r--include/iprt/crypto/ssl.h143
-rw-r--r--include/iprt/crypto/store.h410
-rw-r--r--include/iprt/crypto/taf.h202
-rw-r--r--include/iprt/crypto/tsp.h148
-rw-r--r--include/iprt/crypto/x509.h1180
-rw-r--r--include/iprt/ctype.h251
-rw-r--r--include/iprt/dbg.h2034
-rw-r--r--include/iprt/dir.h894
-rw-r--r--include/iprt/dvm.h639
-rw-r--r--include/iprt/efi.h299
-rw-r--r--include/iprt/env.h473
-rw-r--r--include/iprt/err.h2823
-rw-r--r--include/iprt/err.mac1201
-rw-r--r--include/iprt/err.sed55
-rw-r--r--include/iprt/errcore.h947
-rw-r--r--include/iprt/errno.h441
-rw-r--r--include/iprt/expreval.h159
-rw-r--r--include/iprt/file.h1826
-rw-r--r--include/iprt/formats/Makefile.kup0
-rw-r--r--include/iprt/formats/apfs.h244
-rw-r--r--include/iprt/formats/asn1.h107
-rw-r--r--include/iprt/formats/bmp.h192
-rw-r--r--include/iprt/formats/codeview.h870
-rw-r--r--include/iprt/formats/cpio.h210
-rw-r--r--include/iprt/formats/dwarf.h542
-rw-r--r--include/iprt/formats/dwarf.mac471
-rw-r--r--include/iprt/formats/efi-common.h102
-rw-r--r--include/iprt/formats/efi-fat.h92
-rw-r--r--include/iprt/formats/efi-fv.h131
-rw-r--r--include/iprt/formats/efi-signature.h138
-rw-r--r--include/iprt/formats/efi-varstore.h160
-rw-r--r--include/iprt/formats/elf-amd64.h131
-rw-r--r--include/iprt/formats/elf-common.h348
-rw-r--r--include/iprt/formats/elf-i386.h134
-rw-r--r--include/iprt/formats/elf.h98
-rw-r--r--include/iprt/formats/elf32.h200
-rw-r--r--include/iprt/formats/elf64.h199
-rw-r--r--include/iprt/formats/ext.h998
-rw-r--r--include/iprt/formats/fat.h759
-rw-r--r--include/iprt/formats/hfs.h691
-rw-r--r--include/iprt/formats/iso9660.h1516
-rw-r--r--include/iprt/formats/lx.h510
-rw-r--r--include/iprt/formats/mach-o.h860
-rw-r--r--include/iprt/formats/mz.h77
-rw-r--r--include/iprt/formats/mz.mac66
-rw-r--r--include/iprt/formats/ntfs.h782
-rw-r--r--include/iprt/formats/omf.h260
-rw-r--r--include/iprt/formats/pe.mac732
-rw-r--r--include/iprt/formats/pecoff.h2610
-rw-r--r--include/iprt/formats/riff.h247
-rw-r--r--include/iprt/formats/tpm.h313
-rw-r--r--include/iprt/formats/tracelog.h239
-rw-r--r--include/iprt/formats/udf.h2232
-rw-r--r--include/iprt/formats/wim.h160
-rw-r--r--include/iprt/formats/xar.h90
-rw-r--r--include/iprt/formats/xfs.h721
-rw-r--r--include/iprt/fs.h668
-rw-r--r--include/iprt/fsisomaker.h826
-rw-r--r--include/iprt/fsvfs.h204
-rw-r--r--include/iprt/ftp.h390
-rw-r--r--include/iprt/fuzz.h971
-rw-r--r--include/iprt/getopt.h564
-rw-r--r--include/iprt/handle.h81
-rw-r--r--include/iprt/handletable.h259
-rw-r--r--include/iprt/heap.h369
-rw-r--r--include/iprt/http-common.h286
-rw-r--r--include/iprt/http-server.h244
-rw-r--r--include/iprt/http.h746
-rw-r--r--include/iprt/inifile.h150
-rw-r--r--include/iprt/initterm.h291
-rw-r--r--include/iprt/ioqueue.h405
-rw-r--r--include/iprt/json.h384
-rw-r--r--include/iprt/krnlmod.h202
-rw-r--r--include/iprt/latin1.h404
-rw-r--r--include/iprt/ldr.h1340
-rw-r--r--include/iprt/ldrlazy.h122
-rw-r--r--include/iprt/linux/Makefile.kup0
-rw-r--r--include/iprt/linux/symvers.h89
-rw-r--r--include/iprt/linux/sysfs.h487
-rw-r--r--include/iprt/linux/version.h205
-rw-r--r--include/iprt/list-off32.h514
-rw-r--r--include/iprt/list.h560
-rw-r--r--include/iprt/locale.h113
-rw-r--r--include/iprt/localipc.h354
-rw-r--r--include/iprt/lockvalidator.h1143
-rw-r--r--include/iprt/log.h2869
-rw-r--r--include/iprt/mangling.h4320
-rw-r--r--include/iprt/manifest.h560
-rw-r--r--include/iprt/md2.h139
-rw-r--r--include/iprt/md4.h142
-rw-r--r--include/iprt/md5.h148
-rw-r--r--include/iprt/mem.h1239
-rw-r--r--include/iprt/memcache.h170
-rw-r--r--include/iprt/memobj.h795
-rw-r--r--include/iprt/mempool.h178
-rw-r--r--include/iprt/memsafer.h270
-rw-r--r--include/iprt/memtracker.h257
-rw-r--r--include/iprt/message.h394
-rw-r--r--include/iprt/mp.h521
-rw-r--r--include/iprt/net.h1064
-rw-r--r--include/iprt/nocrt/Makefile.kup0
-rw-r--r--include/iprt/nocrt/algorithm164
-rw-r--r--include/iprt/nocrt/amd64/Makefile.kup0
-rw-r--r--include/iprt/nocrt/amd64/math.h115
-rw-r--r--include/iprt/nocrt/assert.h57
-rw-r--r--include/iprt/nocrt/cassert49
-rw-r--r--include/iprt/nocrt/compiler/compiler.h52
-rw-r--r--include/iprt/nocrt/compiler/gcc.h134
-rw-r--r--include/iprt/nocrt/compiler/msc.h62
-rw-r--r--include/iprt/nocrt/compiler/watcom.h108
-rw-r--r--include/iprt/nocrt/cstddef52
-rw-r--r--include/iprt/nocrt/cstdlib47
-rw-r--r--include/iprt/nocrt/ctype.h61
-rw-r--r--include/iprt/nocrt/direct.h43
-rw-r--r--include/iprt/nocrt/errno.h56
-rw-r--r--include/iprt/nocrt/exception90
-rw-r--r--include/iprt/nocrt/fcntl.h90
-rw-r--r--include/iprt/nocrt/fenv.h49
-rw-r--r--include/iprt/nocrt/float.h131
-rw-r--r--include/iprt/nocrt/fstream206
-rw-r--r--include/iprt/nocrt/inttypes.h75
-rw-r--r--include/iprt/nocrt/io.h48
-rw-r--r--include/iprt/nocrt/iomanip166
-rw-r--r--include/iprt/nocrt/ios525
-rw-r--r--include/iprt/nocrt/iosfwd81
-rw-r--r--include/iprt/nocrt/iostream53
-rw-r--r--include/iprt/nocrt/limits494
-rw-r--r--include/iprt/nocrt/limits.h109
-rw-r--r--include/iprt/nocrt/malloc.h49
-rw-r--r--include/iprt/nocrt/math.h859
-rw-r--r--include/iprt/nocrt/memory108
-rw-r--r--include/iprt/nocrt/new118
-rw-r--r--include/iprt/nocrt/ostream280
-rw-r--r--include/iprt/nocrt/process.h43
-rw-r--r--include/iprt/nocrt/setjmp.h68
-rw-r--r--include/iprt/nocrt/signal.h43
-rw-r--r--include/iprt/nocrt/stdarg.h45
-rw-r--r--include/iprt/nocrt/stdbool.h58
-rw-r--r--include/iprt/nocrt/stddef.h48
-rw-r--r--include/iprt/nocrt/stdint.h46
-rw-r--r--include/iprt/nocrt/stdio.h226
-rw-r--r--include/iprt/nocrt/stdlib.h227
-rw-r--r--include/iprt/nocrt/string322
-rw-r--r--include/iprt/nocrt/string.h254
-rw-r--r--include/iprt/nocrt/sys/stat.h138
-rw-r--r--include/iprt/nocrt/sys/types.h66
-rw-r--r--include/iprt/nocrt/time.h107
-rw-r--r--include/iprt/nocrt/type_traits88
-rw-r--r--include/iprt/nocrt/unistd.h125
-rw-r--r--include/iprt/nocrt/vector398
-rw-r--r--include/iprt/nocrt/x86/Makefile.kup0
-rw-r--r--include/iprt/nocrt/x86/fenv-x86-amd64.h219
-rw-r--r--include/iprt/nocrt/x86/math.h114
-rw-r--r--include/iprt/nt/Makefile.kup0
-rw-r--r--include/iprt/nt/dispmprt.h61
-rw-r--r--include/iprt/nt/hyperv.h1768
-rw-r--r--include/iprt/nt/miniport.h61
-rw-r--r--include/iprt/nt/ndis.h61
-rw-r--r--include/iprt/nt/nt-and-windows.h68
-rw-r--r--include/iprt/nt/nt-structures.h146
-rw-r--r--include/iprt/nt/nt.h3824
-rw-r--r--include/iprt/nt/ntddk.h83
-rw-r--r--include/iprt/nt/rx.h65
-rw-r--r--include/iprt/nt/tdikrnl.h50
-rw-r--r--include/iprt/nt/vid.h313
-rw-r--r--include/iprt/nt/video.h59
-rw-r--r--include/iprt/nt/wdm.h81
-rw-r--r--include/iprt/once.h231
-rw-r--r--include/iprt/param.h137
-rw-r--r--include/iprt/path.h1674
-rw-r--r--include/iprt/pipe.h293
-rw-r--r--include/iprt/poll.h265
-rw-r--r--include/iprt/power.h125
-rw-r--r--include/iprt/process.h479
-rw-r--r--include/iprt/queueatomic.h137
-rw-r--r--include/iprt/rand.h330
-rw-r--r--include/iprt/req.h643
-rw-r--r--include/iprt/runtime-loader.h189
-rw-r--r--include/iprt/runtime.h99
-rw-r--r--include/iprt/s3.h283
-rw-r--r--include/iprt/sanitized/intrin.h62
-rw-r--r--include/iprt/sanitized/iterator60
-rw-r--r--include/iprt/sanitized/sstream62
-rw-r--r--include/iprt/sanitized/string61
-rw-r--r--include/iprt/semaphore.h1450
-rw-r--r--include/iprt/serialport.h377
-rw-r--r--include/iprt/setjmp-without-sigmask.h64
-rw-r--r--include/iprt/sg.h460
-rw-r--r--include/iprt/sha.h593
-rw-r--r--include/iprt/shmem.h180
-rw-r--r--include/iprt/socket.h430
-rw-r--r--include/iprt/solaris/kmoddeps.mac193
-rw-r--r--include/iprt/sort.h141
-rw-r--r--include/iprt/spinlock.h105
-rw-r--r--include/iprt/stdarg.h79
-rw-r--r--include/iprt/stdint.h349
-rw-r--r--include/iprt/strcache.h201
-rw-r--r--include/iprt/stream.h542
-rw-r--r--include/iprt/string.h3725
-rw-r--r--include/iprt/symlink.h189
-rw-r--r--include/iprt/system.h379
-rw-r--r--include/iprt/table.h726
-rw-r--r--include/iprt/tar.h184
-rw-r--r--include/iprt/tcp.h514
-rw-r--r--include/iprt/test.h1485
-rw-r--r--include/iprt/thread.h1023
-rw-r--r--include/iprt/time.h1352
-rw-r--r--include/iprt/timer.h400
-rw-r--r--include/iprt/tpm.h156
-rw-r--r--include/iprt/trace.h228
-rw-r--r--include/iprt/tracelog.h706
-rw-r--r--include/iprt/types.h3890
-rw-r--r--include/iprt/udp.h191
-rw-r--r--include/iprt/uint128.h1479
-rw-r--r--include/iprt/uint256.h1241
-rw-r--r--include/iprt/uint32.h1068
-rw-r--r--include/iprt/uint64.h1343
-rw-r--r--include/iprt/uni.h491
-rw-r--r--include/iprt/uri.h380
-rw-r--r--include/iprt/utf16.h1527
-rw-r--r--include/iprt/uuid.h198
-rw-r--r--include/iprt/vector.h389
-rw-r--r--include/iprt/vfs.h2021
-rw-r--r--include/iprt/vfslowlevel.h1588
-rw-r--r--include/iprt/win/Makefile.kup0
-rw-r--r--include/iprt/win/audioclient.h59
-rw-r--r--include/iprt/win/commctrl.h61
-rw-r--r--include/iprt/win/context-amd64.mac118
-rw-r--r--include/iprt/win/context-x86.mac101
-rw-r--r--include/iprt/win/credentialprovider.h58
-rw-r--r--include/iprt/win/d3d8.h60
-rw-r--r--include/iprt/win/d3d9.h68
-rw-r--r--include/iprt/win/d3dkmthk.h61
-rw-r--r--include/iprt/win/dbghelp.h61
-rw-r--r--include/iprt/win/dshow.h56
-rw-r--r--include/iprt/win/endpointvolume.h58
-rw-r--r--include/iprt/win/imagehlp.h61
-rw-r--r--include/iprt/win/intsafe.h77
-rw-r--r--include/iprt/win/iphlpapi.h50
-rw-r--r--include/iprt/win/ks.h54
-rw-r--r--include/iprt/win/lazy-dbghelp.h151
-rw-r--r--include/iprt/win/mmreg.h53
-rw-r--r--include/iprt/win/netioapi.h46
-rw-r--r--include/iprt/win/ntdddisk.h50
-rw-r--r--include/iprt/win/ntddndis.h50
-rw-r--r--include/iprt/win/ntverp.h50
-rw-r--r--include/iprt/win/objbase.h69
-rw-r--r--include/iprt/win/objidl.h63
-rw-r--r--include/iprt/win/rpcproxy.h75
-rw-r--r--include/iprt/win/setupapi.h59
-rw-r--r--include/iprt/win/shlobj.h67
-rw-r--r--include/iprt/win/shlwapi.h53
-rw-r--r--include/iprt/win/windef.h65
-rw-r--r--include/iprt/win/windows.h110
-rw-r--r--include/iprt/win/winsock.h64
-rw-r--r--include/iprt/win/winsock2.h74
-rw-r--r--include/iprt/win/ws2tcpip.h67
-rw-r--r--include/iprt/x86-helpers.h261
-rw-r--r--include/iprt/x86.h4860
-rw-r--r--include/iprt/x86.mac1409
-rw-r--r--include/iprt/x86extra.mac225
-rw-r--r--include/iprt/zero.h67
-rw-r--r--include/iprt/zip.h533
563 files changed, 304582 insertions, 0 deletions
diff --git a/include/.scm-settings b/include/.scm-settings
new file mode 100644
index 00000000..48ca6339
--- /dev/null
+++ b/include/.scm-settings
@@ -0,0 +1,112 @@
+# $Id: .scm-settings $
+## @file
+# Source code massager settings for the includes.
+#
+
+#
+# Copyright (C) 2010-2022 Oracle and/or its affiliates.
+#
+# This file is part of VirtualBox base platform packages, as
+# available from https://www.virtualbox.org.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation, in version 3 of the
+# License.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <https://www.gnu.org/licenses>.
+#
+# SPDX-License-Identifier: GPL-3.0-only
+#
+
+
+# Default license for headers is dual GPL and CDDL.
+--license-ose-dual
+
+# Only the headers should be dual.
+/Makefile.kmk: --license-ose-gpl
+/.scm-settings: --license-ose-gpl
+
+# /iprt/nocrt/* C++ style header files
+/iprt/nocrt/algorithm: --treat-as h
+/iprt/nocrt/cassert: --treat-as h
+/iprt/nocrt/cstddef: --treat-as h
+/iprt/nocrt/cstdlib: --treat-as h
+/iprt/nocrt/exception: --treat-as h
+/iprt/nocrt/fstream: --treat-as h
+/iprt/nocrt/iomanip: --treat-as h
+/iprt/nocrt/ios: --treat-as h
+/iprt/nocrt/iosfwd: --treat-as h
+/iprt/nocrt/iostream: --treat-as h
+/iprt/nocrt/limits: --treat-as h
+/iprt/nocrt/memory: --treat-as h
+/iprt/nocrt/new: --treat-as h
+/iprt/nocrt/ostream: --treat-as h
+/iprt/nocrt/string: --treat-as h
+/iprt/nocrt/type_traits: --treat-as h
+/iprt/nocrt/vector: --treat-as h
+
+# These three have no Oracle license or copyright stuff for some reason.
+/iprt/formats/elf-amd64.h: --no-update-license --no-update-copyright-year
+/iprt/formats/elf-common.h: --no-update-license --no-update-copyright-year
+/iprt/formats/elf-i386.h: --no-update-license --no-update-copyright-year
+/iprt/formats/elf-i386.h: --no-update-license --no-update-copyright-year
+
+# external copyright
+/iprt/formats/lx.h: --external-copyright
+
+# This is using LGPL (from WINE) with Oracle disclaimer.
+/VBox/VBoxKeyboard.h: --external-copyright --lgpl-disclaimer
+
+# Some of the graphics stuff is using MIT.
+/VBox/Graphics/HGSMI.h: --license-mit
+/VBox/Graphics/HGSMIBase.h: --license-mit
+/VBox/Graphics/HGSMIChannels.h: --license-mit
+/VBox/Graphics/HGSMIChSetup.h: --license-mit
+/VBox/Graphics/HGSMIContext.h: --license-mit
+/VBox/Graphics/HGSMIDefs.h: --license-mit
+/VBox/Graphics/VBoxVideo.h: --license-mit
+/VBox/Graphics/VBoxVideoErr.h: --license-mit
+/VBox/Graphics/VBoxVideoGuest.h: --license-mit
+/VBox/Graphics/VBoxVideoVBE.h: --license-mit
+/VBox/Graphics/VBoxVideoVBEPrivate.h: --license-mit
+
+# And so are some files used by the shared folder guest code.
+/VBox/shflsvc.h: --license-mit
+/VBox/VBoxGuest.h: --license-mit
+/VBox/VBoxGuestCoreTypes.h: --license-mit
+/VBox/VBoxGuestLib.h: --license-mit
+/VBox/VBoxGuestLibSharedFolders.h: --license-mit
+/VBox/VBoxGuestLibSharedFoldersInline.h: --license-mit
+/VBox/VMMDev.h: --license-mit
+/VBox/VMMDevCoreTypes.h: --license-mit
+
+/VBox/HostServices/glext.h: --external-copyright --no-convert-tabs --no-strip-trailing-blanks
+/VBox/HostServices/glxext.h: --external-copyright --no-convert-tabs --no-strip-trailing-blanks
+/VBox/HostServices/wglext.h: --external-copyright --no-convert-tabs --no-strip-trailing-blanks
+
+# Some headers actually shouldn't have include guards:
+/VBox/dbus-calls.h: --no-fix-header-guards
+/VBox/xrandr-calls.h: --no-fix-header-guards
+/VBox/VDEPlugSymDefs.h: --no-fix-header-guards
+/VBox/vmm/vmmr3vtable-def.h: --no-fix-header-guards
+/iprt/asn1-generator-core.h: --no-fix-header-guards
+/iprt/asn1-generator-pass.h: --no-fix-header-guards
+/iprt/asn1-generator-sanity.h: --no-fix-header-guards
+/iprt/asn1-generator-internal-header.h: --no-fix-header-guards
+/iprt/asn1-generator-asn1-decoder.h: --no-fix-header-guards
+/iprt/asn1-generator-init.h: --no-fix-header-guards
+/iprt/runtime-loader.h: --no-fix-header-guards
+/iprt/bldprog-strtab-template.cpp.h: --no-fix-header-guards
+/iprt/asm*watcom*.h: --no-pragma-once
+
+/iprt/*.h: --guard-relative-to-dir iprt --guard-prefix IPRT_INCLUDED_
+/VBox/*.h: --guard-relative-to-dir VBox --guard-prefix VBOX_INCLUDED_
+/iprt/sanitized/*: --guard-relative-to-dir iprt --guard-prefix IPRT_INCLUDED_ --treat-as h
+
diff --git a/include/Makefile.kmk b/include/Makefile.kmk
new file mode 100644
index 00000000..4a9e615c
--- /dev/null
+++ b/include/Makefile.kmk
@@ -0,0 +1,286 @@
+# $Id: Makefile.kmk $
+## @file
+# Some hacks to allow syntax and prerequisite include checking of headers.
+# This makefile doesn't and shouldn't build successfully.
+#
+
+#
+# Copyright (C) 2006-2022 Oracle and/or its affiliates.
+#
+# This file is part of VirtualBox base platform packages, as
+# available from https://www.virtualbox.org.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation, in version 3 of the
+# License.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <https://www.gnu.org/licenses>.
+#
+# SPDX-License-Identifier: GPL-3.0-only
+#
+
+SUB_DEPTH = ..
+include $(KBUILD_PATH)/subheader.kmk
+
+LIBRARIES += SyntaxVBoxIncludeR3 SyntaxVBoxIncludeR0
+
+# Omit headers that are using C++ features and upsets gcc.
+VBOX_HDRS_CPP_FEATURES := \
+ VBox/vmm/hm.h \
+ VBox/vmm/hm_vmx.h \
+ VBox/vmm/pdmaudioinline.h \
+ VBox/vmm/pdmaudiohostenuminline.h \
+ VBox/HostServices/GuestControlSvc.h \
+ VBox/HostServices/DragAndDropSvc.h \
+ VBox/HostServices/Service.h \
+ VBox/GuestHost/GuestControl.h \
+ VBox/GuestHost/DragAndDrop.h \
+ VBox/GuestHost/SharedClipboard-transfers.h \
+ VBox/dbus.h \
+ VBox/xrandr.h \
+ VBox/VBoxCrHgsmi.h \
+ VBox/VBoxGuestLibSharedFoldersInline.h \
+ VBox/VBoxPktDmp.h \
+ VBox/VBoxUhgsmi.h \
+ iprt/cpp/%
+
+# Omit headers that are C++ and ring-3.
+VBOX_HDRS_R3_CPP := \
+ VBox/dbggui.h \
+ VBox/settings.h \
+ VBox/com/Guid.h \
+ VBox/vmm/vmmr3vtable.h \
+ iprt/cpp/% \
+ VBox/com/% \
+ $(subst $(PATH_SUB_CURRENT)/,,$(wildcard $(PATH_SUB_CURRENT)/iprt/*_cpp.h))
+
+# Ring-3 only headers.
+VBOX_HDRS_R3_ONLY := \
+ VBox/vrdpapi.h \
+ VBox/vrdpusb.h \
+ VBox/VBoxHDD.h \
+ VBox/VBoxHDD-Plugin.h \
+ VBox/VBoxCrHgsmi.h \
+ VBox/VBoxUhgsmi.h \
+ VBox/VBoxNetCfg-win.h \
+ VBox/VBoxDrvCfg-win.h \
+ VBox/dbus.h \
+ VBox/xrandr.h \
+ $(if-expr "$(KBUILD_TARGET)" == "win",VBox/usblib.h,) \
+ VBox/usblib-win.h \
+ VBox/vd.h \
+ VBox/vd-cache-backend.h \
+ VBox/vd-ifs.h \
+ VBox/vd-ifs-internal.h \
+ VBox/vd-image-backend.h \
+ VBox/vd-plugin.h \
+ VBox/vd-filter-backend.h \
+ VBox/vddbg.h \
+ VBox/vmm/uvm.h \
+ VBox/vmm/dbgfflowtrace.h \
+ VBox/vscsi.h \
+ VBox/ExtPack/% \
+ VBox/GuestHost/SharedClipboard-transfers.h \
+ VBox/GuestHost/SharedClipboard-win.h \
+ VBox/GuestHost/SharedClipboard-x11.h \
+ VBox/GuestHost/DragAndDrop.h \
+ VBox/HostServices/Service.h \
+ iprt/win/% \
+ iprt/alloca.h \
+ iprt/tcp.h \
+ iprt/localipc.h \
+ iprt/linux/sysfs.h \
+ iprt/socket.h \
+ iprt/udp.h \
+ iprt/fuzz.h \
+ iprt/linux/symvers.h
+
+# Ring-0 driver only headers.
+VBOX_HDRS_R0DRV_ONLY := \
+ VBox/VBoxGuestLibSharedFolders.h \
+ VBox/VBoxGuestLibSharedFoldersInline.h \
+ iprt/linux/version.h
+
+# GCC only headers.
+VBOX_HDRS_GCC_ONLY := \
+ iprt/nocrt/fenv.h \
+ iprt/nocrt/math.h
+
+# Headers to omit all together.
+VBOX_HDRS_OMIT := \
+ VBox/HostServices/glext.h \
+ VBox/HostServices/glxext.h \
+ VBox/HostServices/wglext.h \
+ VBox/VBoxGL2D.h \
+ $(if-expr "$(KBUILD_TARGET)" != "linux", \
+ VBox/GuestHost/SharedClipboard-x11.h \
+ ,)\
+ $(if-expr "$(KBUILD_TARGET)" != "solaris", \
+ VBox/usblib-solaris.h \
+ ,)\
+ VBox/VDEPlug.h \
+ VBox/VDEPlugSymDefs.h \
+ VBox/VBoxNetCmn-win.h \
+ $(if-expr "$(KBUILD_TARGET)" != "win", \
+ VBox/com/microatl.h \
+ VBox/GuestHost/SharedClipboard-win.h \
+ VBox/usblib-win.h \
+ VBox/VBoxDrvCfg-win.h \
+ VBox/VBoxNetCfg-win.h \
+ iprt/sanitized/intrin.h \
+ ,$(VBOX_HDRS_GCC_ONLY)) \
+ \
+ VBox/dbus-calls.h \
+ VBox/xrandr-calls.h \
+ VBox/VBoxKeyboard.h \
+ VBox/vmm/pdmpcidevint.h \
+ VBox/vmm/vmmr3vtable-def.h \
+ iprt/runtime-loader.h \
+ iprt/mangling.h \
+ $(subst $(PATH_SUB_CURRENT)/,,$(wildcard $(PATH_SUB_CURRENT)/iprt/asm*watcom*.h)) \
+ iprt/asn1-generator% \
+ iprt/win/% \
+ iprt/nt/% \
+ \
+ $(foreach os,$(filter-out $(KBUILD_TARGET),$(KBUILD_OSES)),iprt/$(os)/% VBox/$(os)/%) \
+ $(foreach arch,$(KBUILD_ARCHES),iprt/nocrt/$(arch)/%)
+
+# AMD64 only headers.
+ifneq ($(KBUILD_TARGET_ARCH),amd64)
+VBOX_HDRS_OMIT += \
+ VBox/vmm/cpumctx.h \
+ VBox/vmm/cpumctx-v1_6.h \
+ VBox/vmm/dbgfcorefmt.h
+endif
+# ARM only headers.
+ifn1of ($(KBUILD_TARGET_ARCH), arm32 arm64)
+VBOX_HDRS_OMIT += \
+ iprt/asm-arm.h
+endif
+
+
+# We omit a few headers which have platform specific issues or are templates.
+VBOX_HDRS_ALL := $(filter-out $(VBOX_HDRS_OMIT), \
+ $(subst $(PATH_SUB_CURRENT)/,,$(wildcard \
+ $(PATH_SUB_CURRENT)/VBox/*.h \
+ $(PATH_SUB_CURRENT)/VBox/*/*.h \
+ $(PATH_SUB_CURRENT)/iprt/*.h \
+ $(PATH_SUB_CURRENT)/iprt/*/*.h \
+)))
+
+# ring-3, ring-0 and raw-mode context specific exclusions.
+VBOX_HDRS_ALL_R3 := $(filter-out $(VBOX_HDRS_R0DRV_ONLY), $(VBOX_HDRS_ALL))
+if "$(intersects $(KBUILD_TARGET_ARCH),$(VBOX_SUPPORTED_HOST_ARCHS))" == ""
+ ifeq ($(KBUILD_TARGET),win)
+VBOX_HDRS_ALL_R3 := $(filter-out VBox/com/VirtualBox.h VBox/com/listeners.h VBox/settings.h,$(VBOX_HDRS_ALL_R3))
+ else
+VBOX_HDRS_ALL_R3 := $(filter-out VBox/com/% VBox/settings.h,$(VBOX_HDRS_ALL_R3))
+ endif
+endif
+VBOX_HDRS_ALL_R3_C := $(filter-out $(VBOX_HDRS_CPP_FEATURES) $(VBOX_HDRS_R3_CPP), $(VBOX_HDRS_ALL_R3))
+VBOX_HDRS_ALL_R0 := $(filter-out $(VBOX_HDRS_R3_CPP) $(VBOX_HDRS_R3_ONLY) $(VBOX_HDRS_R0DRV_ONLY), $(VBOX_HDRS_ALL))
+VBOX_HDRS_ALL_R0_C := $(filter-out $(VBOX_HDRS_CPP_FEATURES), $(VBOX_HDRS_ALL_R0))
+VBOX_HDRS_ALL_R0DRV := $(filter-out $(VBOX_HDRS_R3_CPP) $(VBOX_HDRS_R3_ONLY), $(VBOX_HDRS_ALL))
+VBOX_HDRS_ALL_R0DRV_C := $(filter-out $(VBOX_HDRS_CPP_FEATURES), $(VBOX_HDRS_ALL_R0DRV))
+VBOX_HDRS_ALL_RC := $(filter-out \
+ VBox/VBoxGuestLib.h \
+ VBox/vmm/gvm.h \
+ iprt/thread.h \
+ iprt/mem.h \
+ iprt/memsafer.h \
+ iprt/alloc.h \
+ iprt/vector.h \
+ $(VBOX_HDRS_R3_CPP) \
+ $(VBOX_HDRS_R3_ONLY) \
+ $(VBOX_HDRS_R0DRV_ONLY) \
+ , $(VBOX_HDRS_ALL))
+VBOX_HDRS_ALL_RC_C := $(filter-out $(VBOX_HDRS_CPP_FEATURES), $(VBOX_HDRS_ALL_RC))
+#$(error $(subst $(SP),$(NLTAB),$(strip $(sort $(VBOX_HDRS_ALL_RC_C)))))
+
+if1of ($(KBUILD_TARGET_ARCH), $(VBOX_SUPPORTED_HOST_ARCHS))
+SyntaxVBoxIncludeR3_TEMPLATE = VBOXMAINEXE
+SyntaxVBoxIncludeR3_DEFS = VBOX_WITH_HGCM
+else
+SyntaxVBoxIncludeR3_TEMPLATE = VBOXR3EXE
+SyntaxVBoxIncludeR3_SDKS.win = ReorderCompilerIncs $(VBOX_WINPSDK) $(VBOX_WINDDK)
+endif
+SyntaxVBoxIncludeR3_DEFS += USING_VMM_COMMON_DEFS
+SyntaxVBoxIncludeR3_CDEFS = IPRT_WITHOUT_NAMED_UNIONS_AND_STRUCTS
+SyntaxVBoxIncludeR3_SOURCES := \
+ $(addprefix $(PATH_OBJ)/include/c/, $(addsuffix .c, $(basename $(VBOX_HDRS_ALL_R3_C)))) \
+ $(addprefix $(PATH_OBJ)/include/cpp/,$(addsuffix .cpp,$(basename $(VBOX_HDRS_ALL_R3))))
+SyntaxVBoxIncludeR3_CLEAN = $(SyntaxVBoxIncludeR3_SOURCES)
+#$(error $(subst $(SP),$(NLTAB),$(strip $(sort $(SyntaxVBoxIncludeR3_SOURCES)))))
+
+SyntaxVBoxIncludeR0_TEMPLATE = VBoxR0
+SyntaxVBoxIncludeR0_DEFS = VBOX_WITH_HGCM USING_VMM_COMMON_DEFS
+SyntaxVBoxIncludeR0_CDEFS = IPRT_WITHOUT_NAMED_UNIONS_AND_STRUCTS
+SyntaxVBoxIncludeR0_SOURCES := \
+ $(addprefix $(PATH_OBJ)/include/c/, $(addsuffix .c, $(basename $(VBOX_HDRS_ALL_R0_C)))) \
+ $(addprefix $(PATH_OBJ)/include/cpp/,$(addsuffix .cpp,$(basename $(VBOX_HDRS_ALL_R0))))
+SyntaxVBoxIncludeR0_CLEAN = $(SyntaxVBoxIncludeR0_SOURCES)
+
+if1of ($(KBUILD_TARGET), darwin os2 solaris win)
+LIBRARIES += SyntaxVBoxIncludeR0Drv
+SyntaxVBoxIncludeR0Drv_TEMPLATE = VBoxR0DrvLib
+SyntaxVBoxIncludeR0Drv_SDKS.win = ReorderCompilerIncs $(VBOX_WINDDK) $(VBOX_WINPSDK_INCS)
+SyntaxVBoxIncludeR0Drv_DEFS = VBOX_WITH_HGCM USING_VMM_COMMON_DEFS
+SyntaxVBoxIncludeR0Drv_CDEFS = IPRT_WITHOUT_NAMED_UNIONS_AND_STRUCTS
+SyntaxVBoxIncludeR0Drv_SOURCES := \
+ $(addprefix $(PATH_OBJ)/include/c/, $(addsuffix .c, $(basename $(VBOX_HDRS_ALL_R0DRV_C)))) \
+ $(addprefix $(PATH_OBJ)/include/cpp/,$(addsuffix .cpp,$(basename $(VBOX_HDRS_ALL_R0DRV))))
+SyntaxVBoxIncludeR0Drv_CLEAN = $(SyntaxVBoxIncludeR0Drv_SOURCES)
+endif
+
+ifdef VBOX_WITH_RAW_MODE
+LIBRARIES += SyntaxVBoxIncludeRC
+SyntaxVBoxIncludeRC_TEMPLATE = VBoxRc
+SyntaxVBoxIncludeRC_DEFS = VBOX_WITH_HGCM USING_VMM_COMMON_DEFS
+SyntaxVBoxIncludeRC_CDEFS = IPRT_WITHOUT_NAMED_UNIONS_AND_STRUCTS
+SyntaxVBoxIncludeRC_SOURCES := \
+ $(addprefix $(PATH_OBJ)/include/c/, $(addsuffix .c, $(basename $(VBOX_HDRS_ALL_RC_C)))) \
+ $(addprefix $(PATH_OBJ)/include/cpp/,$(addsuffix .cpp,$(basename $(VBOX_HDRS_ALL_RC))))
+SyntaxVBoxIncludeRC_CLEAN = $(SyntaxVBoxIncludeRC_SOURCES)
+endif
+
+
+# Headers that must only be included once.
+VBOX_HDRS_ONLY_ONCE := \
+ iprt/bldprog-strtab-template.cpp.h
+
+
+# Generate the files we compile.
+define def_hdr
+ $(eval functioname := $(translate $(basename $(hdr)),-./,___))
+
+ $$(PATH_OBJ)/include/c/$(basename $(hdr)).c: | $$$$(dir $$$$@)
+ $(QUIET)$$(APPEND) -t -n $$@ \
+ '#include <$(hdr)>' \
+ $(if-expr $(intersects $(hdr),$(VBOX_HDRS_ONLY_ONCE)),, '#include <$(hdr)>') \
+ 'extern int $(functioname)_c(void);' \
+ 'int $(functioname)_c(void) { return 0;}'
+
+ $$(PATH_OBJ)/include/cpp/$(basename $(hdr)).cpp: | $$$$(dir $$$$@)
+ $(QUIET)$$(APPEND) -t -n $$@ \
+ '#include <$(hdr)>' \
+ $(if-expr $(intersects $(hdr),$(VBOX_HDRS_ONLY_ONCE)),, '#include <$(hdr)>') \
+ 'extern int $(functioname)_cpp(void);' \
+ 'int $(functioname)_cpp(void) { return 0;}'
+
+endef
+
+$(foreach hdr,$(VBOX_HDRS_ALL), $(eval $(def_hdr)))
+
+# Tell kBuild to generate rules for making the directories for the generated files.
+VBOX_HDR_DIRS := $(sort $(dir $(VBOX_HDRS_ALL)))
+BLDDIRS += $(addprefix $(PATH_OBJ)/include/c/,$(VBOX_HDR_DIRS)) $(addprefix $(PATH_OBJ)/include/cpp/,$(VBOX_HDR_DIRS))
+
+
+include $(FILE_KBUILD_SUB_FOOTER)
diff --git a/include/VBox/AssertGuest.h b/include/VBox/AssertGuest.h
new file mode 100644
index 00000000..c4946ff0
--- /dev/null
+++ b/include/VBox/AssertGuest.h
@@ -0,0 +1,1781 @@
+/** @file
+ * VirtualBox - Guest input assertions.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_AssertGuest_h
+#define VBOX_INCLUDED_AssertGuest_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/cdefs.h>
+#include <iprt/assert.h>
+
+
+/** @defgroup grp_vbox_assert_guest VBox Guest Input Assertion Macros
+ * @{
+ */
+
+
+/** @name Guest input assertions
+ *
+ * These assertions will only trigger when VBOX_STRICT_GUEST is defined. When
+ * it is undefined they will all be no-ops and generate no code, unless they
+ * have other side effected (i.e. the _RETURN, _STMT, _BREAK variations).
+ *
+ * The assertions build on top of the functions in iprt/assert.h.
+ *
+ * @{
+ */
+
+
+/** @def ASSERT_GUEST_PANIC()
+ * If VBOX_STRICT_GUEST is defined this macro will invoke RTAssertDoPanic if
+ * RTAssertShouldPanic returns true. If VBOX_STRICT_GUEST isn't defined it won't
+ * do any thing.
+ */
+#if defined(VBOX_STRICT_GUEST) && !defined(VBOX_STRICT_GUEST_DONT_PANIC)
+# define ASSERT_GUEST_PANIC() do { if (RTAssertShouldPanic()) RTAssertDoPanic(); } while (0)
+#else
+# define ASSERT_GUEST_PANIC() do { } while (0)
+#endif
+
+/** Wrapper around RTAssertMsg1Weak that prefixes the expression. */
+#define ASSERT_GUEST_MSG1(szExpr, iLine, pszFile, pszFunction) \
+ RTAssertMsg1Weak("guest-input: " szExpr, iLine, pszFile, pszFunction)
+
+
+/** @def ASSERT_GUEST
+ * Assert that an expression is true. If false, hit breakpoint.
+ * @param a_Expr Expression which should be true.
+ */
+#ifdef VBOX_STRICT_GUEST
+# define ASSERT_GUEST(a_Expr) \
+ do { \
+ if (RT_LIKELY(!!(a_Expr))) \
+ { /* likely */ } \
+ else \
+ { \
+ ASSERT_GUEST_MSG1(#a_Expr, __LINE__, __FILE__, RT_GCC_EXTENSION __PRETTY_FUNCTION__); \
+ ASSERT_GUEST_PANIC(); \
+ } \
+ } while (0)
+#else
+# define ASSERT_GUEST(a_Expr) do { } while (0)
+#endif
+
+
+/** @def ASSERT_GUEST_STMT
+ * Assert that an expression is true. If false, hit breakpoint and execute the
+ * statement.
+ * @param a_Expr Expression which should be true.
+ * @param a_Stmt Statement to execute on failure.
+ */
+#ifdef VBOX_STRICT_GUEST
+# define ASSERT_GUEST_STMT(a_Expr, a_Stmt) \
+ do { \
+ if (RT_LIKELY(!!(a_Expr))) \
+ { /* likely */ } \
+ else \
+ { \
+ ASSERT_GUEST_MSG1(#a_Expr, __LINE__, __FILE__, RT_GCC_EXTENSION __PRETTY_FUNCTION__); \
+ ASSERT_GUEST_PANIC(); \
+ a_Stmt; \
+ } \
+ } while (0)
+#else
+# define ASSERT_GUEST_STMT(a_Expr, a_Stmt) \
+ do { \
+ if (RT_LIKELY(!!(a_Expr))) \
+ { /* likely */ } \
+ else \
+ { \
+ a_Stmt; \
+ } \
+ } while (0)
+#endif
+
+
+/** @def ASSERT_GUEST_RETURN
+ * Assert that an expression is true and returns if it isn't.
+ * In VBOX_STRICT_GUEST mode it will hit a breakpoint before returning.
+ *
+ * @param a_Expr Expression which should be true.
+ * @param a_rc What is to be presented to return.
+ */
+#ifdef VBOX_STRICT_GUEST
+# define ASSERT_GUEST_RETURN(a_Expr, a_rc) \
+ do { \
+ if (RT_LIKELY(!!(a_Expr))) \
+ { /* likely */ } \
+ else \
+ { \
+ ASSERT_GUEST_MSG1(#a_Expr, __LINE__, __FILE__, RT_GCC_EXTENSION __PRETTY_FUNCTION__); \
+ ASSERT_GUEST_PANIC(); \
+ return (a_rc); \
+ } \
+ } while (0)
+#else
+# define ASSERT_GUEST_RETURN(a_Expr, a_rc) \
+ do { \
+ if (RT_LIKELY(!!(a_Expr))) \
+ { /* likely */ } \
+ else \
+ return (a_rc); \
+ } while (0)
+#endif
+
+/** @def ASSERT_GUEST_STMT_RETURN
+ * Assert that an expression is true, if it isn't execute the given statement
+ * and return rc.
+ *
+ * In VBOX_STRICT_GUEST mode it will hit a breakpoint before executing the statement and
+ * returning.
+ *
+ * @param a_Expr Expression which should be true.
+ * @param a_Stmt Statement to execute before returning on failure.
+ * @param a_rc What is to be presented to return.
+ */
+#ifdef VBOX_STRICT_GUEST
+# define ASSERT_GUEST_STMT_RETURN(a_Expr, a_Stmt, a_rc) \
+ do { \
+ if (RT_LIKELY(!!(a_Expr))) \
+ { /* likely */ } \
+ else \
+ { \
+ ASSERT_GUEST_MSG1(#a_Expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+ ASSERT_GUEST_PANIC(); \
+ a_Stmt; \
+ return (a_rc); \
+ } \
+ } while (0)
+#else
+# define ASSERT_GUEST_STMT_RETURN(a_Expr, a_Stmt, a_rc) \
+ do { \
+ if (RT_LIKELY(!!(a_Expr))) \
+ { /* likely */ } \
+ else \
+ { \
+ a_Stmt; \
+ return (a_rc); \
+ } \
+ } while (0)
+#endif
+
+/** @def ASSERT_GUEST_RETURN_VOID
+ * Assert that an expression is true and returns if it isn't.
+ * In VBOX_STRICT_GUEST mode it will hit a breakpoint before returning.
+ *
+ * @param a_Expr Expression which should be true.
+ */
+#ifdef VBOX_STRICT_GUEST
+# define ASSERT_GUEST_RETURN_VOID(a_Expr) \
+ do { \
+ if (RT_LIKELY(!!(a_Expr))) \
+ { /* likely */ } \
+ else \
+ { \
+ ASSERT_GUEST_MSG1(#a_Expr, __LINE__, __FILE__, RT_GCC_EXTENSION __PRETTY_FUNCTION__); \
+ ASSERT_GUEST_PANIC(); \
+ return; \
+ } \
+ } while (0)
+#else
+# define ASSERT_GUEST_RETURN_VOID(a_Expr) \
+ do { \
+ if (RT_LIKELY(!!(a_Expr))) \
+ { /* likely */ } \
+ else \
+ return; \
+ } while (0)
+#endif
+
+/** @def ASSERT_GUEST_STMT_RETURN_VOID
+ * Assert that an expression is true, if it isn't execute the given statement
+ * and return.
+ *
+ * In VBOX_STRICT_GUEST mode it will hit a breakpoint before returning.
+ *
+ * @param a_Expr Expression which should be true.
+ * @param a_Stmt Statement to execute before returning on failure.
+ */
+#ifdef VBOX_STRICT_GUEST
+# define ASSERT_GUEST_STMT_RETURN_VOID(a_Expr, a_Stmt) \
+ do { \
+ if (RT_LIKELY(!!(a_Expr))) \
+ { /* likely */ } \
+ else \
+ { \
+ ASSERT_GUEST_MSG1(#a_Expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+ ASSERT_GUEST_PANIC(); \
+ a_Stmt; \
+ return; \
+ } \
+ } while (0)
+#else
+# define ASSERT_GUEST_STMT_RETURN_VOID(a_Expr, a_Stmt) \
+ do { \
+ if (RT_LIKELY(!!(a_Expr))) \
+ { /* likely */ } \
+ else \
+ { \
+ a_Stmt; \
+ return; \
+ } \
+ } while (0)
+#endif
+
+
+/** @def ASSERT_GUEST_BREAK
+ * Assert that an expression is true and breaks if it isn't.
+ * In VBOX_STRICT_GUEST mode it will hit a breakpoint before breaking.
+ *
+ * @param a_Expr Expression which should be true.
+ */
+#ifdef VBOX_STRICT_GUEST
+# define ASSERT_GUEST_BREAK(a_Expr) \
+ if (RT_LIKELY(!!(a_Expr))) \
+ { /* likely */ } \
+ else if (1) \
+ { \
+ ASSERT_GUEST_MSG1(#a_Expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+ ASSERT_GUEST_PANIC(); \
+ break; \
+ } else \
+ break
+#else
+# define ASSERT_GUEST_BREAK(a_Expr) \
+ if (RT_LIKELY(!!(a_Expr))) \
+ { /* likely */ } \
+ else \
+ break
+#endif
+
+/** @def ASSERT_GUEST_CONTINUE
+ * Assert that an expression is true and continue if it isn't.
+ * In VBOX_STRICT_GUEST mode it will hit a breakpoint before continuing.
+ *
+ * @param a_Expr Expression which should be true.
+ */
+#ifdef VBOX_STRICT_GUEST
+# define ASSERT_GUEST_CONTINUE(a_Expr) \
+ if (RT_LIKELY(!!(a_Expr))) \
+ { /* likely */ } \
+ else if (1) \
+ { \
+ ASSERT_GUEST_MSG1(#a_Expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+ ASSERT_GUEST_PANIC(); \
+ continue; \
+ } else do {} while (0)
+#else
+# define ASSERT_GUEST_CONTINUE(a_Expr) \
+ if (RT_LIKELY(!!(a_Expr))) \
+ { /* likely */ } \
+ else \
+ continue
+#endif
+
+/** @def ASSERT_GUEST_STMT_BREAK
+ * Assert that an expression is true and breaks if it isn't.
+ * In VBOX_STRICT_GUEST mode it will hit a breakpoint before doing break.
+ *
+ * @param a_Expr Expression which should be true.
+ * @param a_Stmt Statement to execute before break in case of a failed assertion.
+ */
+#ifdef VBOX_STRICT_GUEST
+# define ASSERT_GUEST_STMT_BREAK(a_Expr, a_Stmt) \
+ if (RT_LIKELY(!!(a_Expr))) \
+ { /* likely */ } \
+ else if (1) \
+ { \
+ ASSERT_GUEST_MSG1(#a_Expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+ ASSERT_GUEST_PANIC(); \
+ a_Stmt; \
+ break; \
+ } else do {} while (0)
+#else
+# define ASSERT_GUEST_STMT_BREAK(a_Expr, a_Stmt) \
+ if (RT_LIKELY(!!(a_Expr))) \
+ { /* likely */ } \
+ else if (1) \
+ { \
+ a_Stmt; \
+ break; \
+ } else do {} while (0)
+#endif
+
+
+/** @def ASSERT_GUEST_MSG
+ * Assert that an expression is true. If it's not print message and hit breakpoint.
+ * @param a_Expr Expression which should be true.
+ * @param a printf argument list (in parenthesis).
+ */
+#ifdef VBOX_STRICT_GUEST
+# define ASSERT_GUEST_MSG(a_Expr, a) \
+ do { \
+ if (RT_LIKELY(!!(a_Expr))) \
+ { /* likely */ } \
+ else \
+ { \
+ ASSERT_GUEST_MSG1(#a_Expr, __LINE__, __FILE__, RT_GCC_EXTENSION __PRETTY_FUNCTION__); \
+ RTAssertMsg2Weak a; \
+ ASSERT_GUEST_PANIC(); \
+ } \
+ } while (0)
+#else
+# define ASSERT_GUEST_MSG(a_Expr, a) do { } while (0)
+#endif
+
+/** @def ASSERT_GUEST_MSG_STMT
+ * Assert that an expression is true. If it's not print message and hit
+ * breakpoint and execute the statement.
+ *
+ * @param a_Expr Expression which should be true.
+ * @param a printf argument list (in parenthesis).
+ * @param a_Stmt Statement to execute in case of a failed assertion.
+ *
+ * @remarks The expression and statement will be evaluated in all build types.
+ */
+#ifdef VBOX_STRICT_GUEST
+# define ASSERT_GUEST_MSG_STMT(a_Expr, a, a_Stmt) \
+ do { \
+ if (RT_LIKELY(!!(a_Expr))) \
+ { /* likely */ } \
+ else \
+ { \
+ ASSERT_GUEST_MSG1(#a_Expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+ RTAssertMsg2Weak a; \
+ ASSERT_GUEST_PANIC(); \
+ a_Stmt; \
+ } \
+ } while (0)
+#else
+# define ASSERT_GUEST_MSG_STMT(a_Expr, a, a_Stmt) \
+ do { \
+ if (RT_LIKELY(!!(a_Expr))) \
+ { /* likely */ } \
+ else \
+ { \
+ a_Stmt; \
+ } \
+ } while (0)
+#endif
+
+/** @def ASSERT_GUEST_MSG_RETURN
+ * Assert that an expression is true and returns if it isn't.
+ * In VBOX_STRICT_GUEST mode it will hit a breakpoint before returning.
+ *
+ * @param a_Expr Expression which should be true.
+ * @param a printf argument list (in parenthesis).
+ * @param a_rc What is to be presented to return.
+ */
+#ifdef VBOX_STRICT_GUEST
+# define ASSERT_GUEST_MSG_RETURN(a_Expr, a, a_rc) \
+ do { \
+ if (RT_LIKELY(!!(a_Expr))) \
+ { /* likely */ } \
+ else \
+ { \
+ ASSERT_GUEST_MSG1(#a_Expr, __LINE__, __FILE__, RT_GCC_EXTENSION __PRETTY_FUNCTION__); \
+ RTAssertMsg2Weak a; \
+ ASSERT_GUEST_PANIC(); \
+ return (a_rc); \
+ } \
+ } while (0)
+#else
+# define ASSERT_GUEST_MSG_RETURN(a_Expr, a, a_rc) \
+ do { \
+ if (RT_LIKELY(!!(a_Expr))) \
+ { /* likely */ } \
+ else \
+ return (a_rc); \
+ } while (0)
+#endif
+
+/** @def ASSERT_GUEST_MSG_STMT_RETURN
+ * Assert that an expression is true, if it isn't execute the statement and
+ * return.
+ *
+ * In VBOX_STRICT_GUEST mode it will hit a breakpoint before returning.
+ *
+ * @param a_Expr Expression which should be true.
+ * @param a printf argument list (in parenthesis).
+ * @param a_Stmt Statement to execute before returning in case of a failed
+ * assertion.
+ * @param a_rc What is to be presented to return.
+ */
+#ifdef VBOX_STRICT_GUEST
+# define ASSERT_GUEST_MSG_STMT_RETURN(a_Expr, a, a_Stmt, a_rc) \
+ do { \
+ if (RT_LIKELY(!!(a_Expr))) \
+ { /* likely */ } \
+ else \
+ { \
+ ASSERT_GUEST_MSG1(#a_Expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+ RTAssertMsg2Weak a; \
+ ASSERT_GUEST_PANIC(); \
+ a_Stmt; \
+ return (a_rc); \
+ } \
+ } while (0)
+#else
+# define ASSERT_GUEST_MSG_STMT_RETURN(a_Expr, a, a_Stmt, a_rc) \
+ do { \
+ if (RT_LIKELY(!!(a_Expr))) \
+ { /* likely */ } \
+ else \
+ { \
+ a_Stmt; \
+ return (a_rc); \
+ } \
+ } while (0)
+#endif
+
+/** @def ASSERT_GUEST_MSG_RETURN_VOID
+ * Assert that an expression is true and returns if it isn't.
+ * In VBOX_STRICT_GUEST mode it will hit a breakpoint before returning.
+ *
+ * @param a_Expr Expression which should be true.
+ * @param a printf argument list (in parenthesis).
+ */
+#ifdef VBOX_STRICT_GUEST
+# define ASSERT_GUEST_MSG_RETURN_VOID(a_Expr, a) \
+ do { \
+ if (RT_LIKELY(!!(a_Expr))) \
+ { /* likely */ } \
+ else \
+ { \
+ ASSERT_GUEST_MSG1(#a_Expr, __LINE__, __FILE__, RT_GCC_EXTENSION __PRETTY_FUNCTION__); \
+ RTAssertMsg2Weak a; \
+ ASSERT_GUEST_PANIC(); \
+ return; \
+ } \
+ } while (0)
+#else
+# define ASSERT_GUEST_MSG_RETURN_VOID(a_Expr, a) \
+ do { \
+ if (RT_LIKELY(!!(a_Expr))) \
+ { /* likely */ } \
+ else \
+ return; \
+ } while (0)
+#endif
+
+/** @def ASSERT_GUEST_MSG_STMT_RETURN_VOID
+ * Assert that an expression is true, if it isn't execute the statement and
+ * return.
+ *
+ * In VBOX_STRICT_GUEST mode it will hit a breakpoint before returning.
+ *
+ * @param a_Expr Expression which should be true.
+ * @param a printf argument list (in parenthesis).
+ * @param a_Stmt Statement to execute before return in case of a failed assertion.
+ */
+#ifdef VBOX_STRICT_GUEST
+# define ASSERT_GUEST_MSG_STMT_RETURN_VOID(a_Expr, a, a_Stmt) \
+ do { \
+ if (RT_LIKELY(!!(a_Expr))) \
+ { /* likely */ } \
+ else \
+ { \
+ ASSERT_GUEST_MSG1(#a_Expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+ RTAssertMsg2Weak a; \
+ ASSERT_GUEST_PANIC(); \
+ a_Stmt; \
+ return; \
+ } \
+ } while (0)
+#else
+# define ASSERT_GUEST_MSG_STMT_RETURN_VOID(a_Expr, a, a_Stmt) \
+ do { \
+ if (RT_LIKELY(!!(a_Expr))) \
+ { /* likely */ } \
+ else \
+ { \
+ a_Stmt; \
+ return; \
+ } \
+ } while (0)
+#endif
+
+
+/** @def ASSERT_GUEST_MSG_BREAK
+ * Assert that an expression is true and breaks if it isn't.
+ * In VBOX_STRICT_GUEST mode it will hit a breakpoint before returning.
+ *
+ * @param a_Expr Expression which should be true.
+ * @param a printf argument list (in parenthesis).
+ */
+#ifdef VBOX_STRICT_GUEST
+# define ASSERT_GUEST_MSG_BREAK(a_Expr, a) \
+ if (RT_LIKELY(!!(a_Expr))) \
+ { /* likely */ } \
+ else if (1) \
+ { \
+ ASSERT_GUEST_MSG1(#a_Expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+ RTAssertMsg2Weak a; \
+ ASSERT_GUEST_PANIC(); \
+ break; \
+ } else \
+ break
+#else
+# define ASSERT_GUEST_MSG_BREAK(a_Expr, a) \
+ if (RT_LIKELY(!!(a_Expr))) \
+ { /* likely */ } \
+ else \
+ break
+#endif
+
+/** @def ASSERT_GUEST_MSG_STMT_BREAK
+ * Assert that an expression is true and breaks if it isn't.
+ * In VBOX_STRICT_GUEST mode it will hit a breakpoint before doing break.
+ *
+ * @param a_Expr Expression which should be true.
+ * @param a printf argument list (in parenthesis).
+ * @param a_Stmt Statement to execute before break in case of a failed assertion.
+ */
+#ifdef VBOX_STRICT_GUEST
+# define ASSERT_GUEST_MSG_STMT_BREAK(a_Expr, a, a_Stmt) \
+ if (RT_LIKELY(!!(a_Expr))) \
+ { /* likely */ } \
+ else if (1) \
+ { \
+ ASSERT_GUEST_MSG1(#a_Expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+ RTAssertMsg2Weak a; \
+ ASSERT_GUEST_PANIC(); \
+ a_Stmt; \
+ break; \
+ } else \
+ break
+#else
+# define ASSERT_GUEST_MSG_STMT_BREAK(a_Expr, a, a_Stmt) \
+ if (RT_LIKELY(!!(a_Expr))) \
+ { /* likely */ } \
+ else if (1) \
+ { \
+ a_Stmt; \
+ break; \
+ } else \
+ break
+#endif
+
+/** @def ASSERT_GUEST_FAILED
+ * An assertion failed, hit breakpoint.
+ */
+#ifdef VBOX_STRICT_GUEST
+# define ASSERT_GUEST_FAILED() \
+ do { \
+ ASSERT_GUEST_MSG1("failed", __LINE__, __FILE__, RT_GCC_EXTENSION __PRETTY_FUNCTION__); \
+ ASSERT_GUEST_PANIC(); \
+ } while (0)
+#else
+# define ASSERT_GUEST_FAILED() do { } while (0)
+#endif
+
+/** @def ASSERT_GUEST_FAILED_STMT
+ * An assertion failed, hit breakpoint and execute statement.
+ */
+#ifdef VBOX_STRICT_GUEST
+# define ASSERT_GUEST_FAILED_STMT(a_Stmt) \
+ do { \
+ ASSERT_GUEST_MSG1("failed", __LINE__, __FILE__, RT_GCC_EXTENSION __PRETTY_FUNCTION__); \
+ ASSERT_GUEST_PANIC(); \
+ a_Stmt; \
+ } while (0)
+#else
+# define ASSERT_GUEST_FAILED_STMT(a_Stmt) do { a_Stmt; } while (0)
+#endif
+
+/** @def ASSERT_GUEST_FAILED_RETURN
+ * An assertion failed, hit breakpoint (VBOX_STRICT_GUEST mode only) and return.
+ *
+ * @param a_rc The a_rc to return.
+ */
+#ifdef VBOX_STRICT_GUEST
+# define ASSERT_GUEST_FAILED_RETURN(a_rc) \
+ do { \
+ ASSERT_GUEST_MSG1("failed", __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+ ASSERT_GUEST_PANIC(); \
+ return (a_rc); \
+ } while (0)
+#else
+# define ASSERT_GUEST_FAILED_RETURN(a_rc) \
+ do { \
+ return (a_rc); \
+ } while (0)
+#endif
+
+/** @def ASSERT_GUEST_FAILED_STMT_RETURN
+ * An assertion failed, hit breakpoint (VBOX_STRICT_GUEST mode only), execute a
+ * statement and return a value.
+ *
+ * @param a_Stmt The statement to execute before returning.
+ * @param a_rc The value to return.
+ */
+#ifdef VBOX_STRICT_GUEST
+# define ASSERT_GUEST_FAILED_STMT_RETURN(a_Stmt, a_rc) \
+ do { \
+ ASSERT_GUEST_MSG1("failed", __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+ ASSERT_GUEST_PANIC(); \
+ a_Stmt; \
+ return (a_rc); \
+ } while (0)
+#else
+# define ASSERT_GUEST_FAILED_STMT_RETURN(a_Stmt, a_rc) \
+ do { \
+ a_Stmt; \
+ return (a_rc); \
+ } while (0)
+#endif
+
+/** @def ASSERT_GUEST_FAILED_RETURN_VOID
+ * An assertion failed, hit breakpoint (VBOX_STRICT_GUEST mode only) and return.
+ */
+#ifdef VBOX_STRICT_GUEST
+# define ASSERT_GUEST_FAILED_RETURN_VOID() \
+ do { \
+ ASSERT_GUEST_MSG1("failed", __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+ ASSERT_GUEST_PANIC(); \
+ return; \
+ } while (0)
+#else
+# define ASSERT_GUEST_FAILED_RETURN_VOID() \
+ do { \
+ return; \
+ } while (0)
+#endif
+
+/** @def ASSERT_GUEST_FAILED_STMT_RETURN_VOID
+ * An assertion failed, hit breakpoint (VBOX_STRICT_GUEST mode only), execute a
+ * statement and return.
+ *
+ * @param a_Stmt The statement to execute before returning.
+ */
+#ifdef VBOX_STRICT_GUEST
+# define ASSERT_GUEST_FAILED_STMT_RETURN_VOID(a_Stmt) \
+ do { \
+ ASSERT_GUEST_MSG1("failed", __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+ ASSERT_GUEST_PANIC(); \
+ a_Stmt; \
+ return; \
+ } while (0)
+#else
+# define ASSERT_GUEST_FAILED_STMT_RETURN_VOID(a_Stmt) \
+ do { \
+ a_Stmt; \
+ return; \
+ } while (0)
+#endif
+
+
+/** @def ASSERT_GUEST_FAILED_BREAK
+ * An assertion failed, hit breakpoint (VBOX_STRICT_GUEST mode only) and break.
+ */
+#ifdef VBOX_STRICT_GUEST
+# define ASSERT_GUEST_FAILED_BREAK() \
+ if (1) { \
+ ASSERT_GUEST_MSG1("failed", __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+ ASSERT_GUEST_PANIC(); \
+ break; \
+ } else \
+ break
+#else
+# define ASSERT_GUEST_FAILED_BREAK() \
+ if (1) \
+ break; \
+ else \
+ break
+#endif
+
+/** @def ASSERT_GUEST_FAILED_STMT_BREAK
+ * An assertion failed, hit breakpoint (VBOX_STRICT_GUEST mode only), execute
+ * the given statement and break.
+ *
+ * @param a_Stmt Statement to execute before break.
+ */
+#ifdef VBOX_STRICT_GUEST
+# define ASSERT_GUEST_FAILED_STMT_BREAK(a_Stmt) \
+ if (1) { \
+ ASSERT_GUEST_MSG1("failed", __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+ ASSERT_GUEST_PANIC(); \
+ a_Stmt; \
+ break; \
+ } else \
+ break
+#else
+# define ASSERT_GUEST_FAILED_STMT_BREAK(a_Stmt) \
+ if (1) { \
+ a_Stmt; \
+ break; \
+ } else \
+ break
+#endif
+
+
+/** @def ASSERT_GUEST_MSG_FAILED
+ * An assertion failed print a message and a hit breakpoint.
+ *
+ * @param a printf argument list (in parenthesis).
+ */
+#ifdef VBOX_STRICT_GUEST
+# define ASSERT_GUEST_MSG_FAILED(a) \
+ do { \
+ ASSERT_GUEST_MSG1("failed", __LINE__, __FILE__, RT_GCC_EXTENSION __PRETTY_FUNCTION__); \
+ RTAssertMsg2Weak a; \
+ ASSERT_GUEST_PANIC(); \
+ } while (0)
+#else
+# define ASSERT_GUEST_MSG_FAILED(a) do { } while (0)
+#endif
+
+/** @def ASSERT_GUEST_MSG_FAILED_RETURN
+ * An assertion failed, hit breakpoint with message (VBOX_STRICT_GUEST mode only) and return.
+ *
+ * @param a printf argument list (in parenthesis).
+ * @param a_rc What is to be presented to return.
+ */
+#ifdef VBOX_STRICT_GUEST
+# define ASSERT_GUEST_MSG_FAILED_RETURN(a, a_rc) \
+ do { \
+ ASSERT_GUEST_MSG1("failed", __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+ RTAssertMsg2Weak a; \
+ ASSERT_GUEST_PANIC(); \
+ return (a_rc); \
+ } while (0)
+#else
+# define ASSERT_GUEST_MSG_FAILED_RETURN(a, a_rc) \
+ do { \
+ return (a_rc); \
+ } while (0)
+#endif
+
+/** @def ASSERT_GUEST_MSG_FAILED_RETURN_VOID
+ * An assertion failed, hit breakpoint with message (VBOX_STRICT_GUEST mode only) and return.
+ *
+ * @param a printf argument list (in parenthesis).
+ */
+#ifdef VBOX_STRICT_GUEST
+# define ASSERT_GUEST_MSG_FAILED_RETURN_VOID(a) \
+ do { \
+ ASSERT_GUEST_MSG1("failed", __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+ RTAssertMsg2Weak a; \
+ ASSERT_GUEST_PANIC(); \
+ return; \
+ } while (0)
+#else
+# define ASSERT_GUEST_MSG_FAILED_RETURN_VOID(a) \
+ do { \
+ return; \
+ } while (0)
+#endif
+
+
+/** @def ASSERT_GUEST_MSG_FAILED_BREAK
+ * An assertion failed, hit breakpoint with message (VBOX_STRICT_GUEST mode only) and break.
+ *
+ * @param a printf argument list (in parenthesis).
+ */
+#ifdef VBOX_STRICT_GUEST
+# define ASSERT_GUEST_MSG_FAILED_BREAK(a) \
+ if (1) { \
+ ASSERT_GUEST_MSG1("failed", __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+ RTAssertMsg2Weak a; \
+ ASSERT_GUEST_PANIC(); \
+ break; \
+ } else \
+ break
+#else
+# define ASSERT_GUEST_MSG_FAILED_BREAK(a) \
+ if (1) \
+ break; \
+ else \
+ break
+#endif
+
+/** @def ASSERT_GUEST_MSG_FAILED_STMT_BREAK
+ * An assertion failed, hit breakpoint (VBOX_STRICT_GUEST mode only), execute
+ * the given statement and break.
+ *
+ * @param a printf argument list (in parenthesis).
+ * @param a_Stmt Statement to execute before break.
+ */
+#ifdef VBOX_STRICT_GUEST
+# define ASSERT_GUEST_MSG_FAILED_STMT_BREAK(a, a_Stmt) \
+ if (1) { \
+ ASSERT_GUEST_MSG1("failed", __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+ RTAssertMsg2Weak a; \
+ ASSERT_GUEST_PANIC(); \
+ a_Stmt; \
+ break; \
+ } else \
+ break
+#else
+# define ASSERT_GUEST_MSG_FAILED_STMT_BREAK(a, a_Stmt) \
+ if (1) { \
+ a_Stmt; \
+ break; \
+ } else \
+ break
+#endif
+
+/** @} */
+
+
+
+/** @name Guest input release log assertions
+ *
+ * These assertions will work like normal strict assertion when VBOX_STRICT_GUEST is
+ * defined and LogRel statements when VBOX_STRICT_GUEST is undefined. Typically
+ * used for important guest input that it would be helpful to find in VBox.log
+ * if the guest doesn't get it right.
+ *
+ * @{
+ */
+
+
+/** @def ASSERT_GUEST_LOGREL_MSG1
+ * RTAssertMsg1Weak (strict builds) / LogRel wrapper (non-strict).
+ */
+#ifdef VBOX_STRICT_GUEST
+# define ASSERT_GUEST_LOGREL_MSG1(szExpr, iLine, pszFile, pszFunction) \
+ RTAssertMsg1Weak("guest-input: " szExpr, iLine, pszFile, pszFunction)
+#else
+# define ASSERT_GUEST_LOGREL_MSG1(szExpr, iLine, pszFile, pszFunction) \
+ LogRel(("ASSERT_GUEST_LOGREL %s(%d) %s: %s\n", (pszFile), (iLine), (pszFunction), (szExpr) ))
+#endif
+
+/** @def ASSERT_GUEST_LOGREL_MSG2
+ * RTAssertMsg2Weak (strict builds) / LogRel wrapper (non-strict).
+ */
+#ifdef VBOX_STRICT_GUEST
+# define ASSERT_GUEST_LOGREL_MSG2(a) RTAssertMsg2Weak a
+#else
+# define ASSERT_GUEST_LOGREL_MSG2(a) LogRel(a)
+#endif
+
+/** @def ASSERT_GUEST_LOGREL
+ * Assert that an expression is true.
+ * Strict builds will hit a breakpoint, non-strict will only do LogRel.
+ *
+ * @param a_Expr Expression which should be true.
+ */
+#define ASSERT_GUEST_LOGREL(a_Expr) \
+ do { \
+ if (RT_LIKELY(!!(a_Expr))) \
+ { /* likely */ } \
+ else \
+ { \
+ ASSERT_GUEST_LOGREL_MSG1(#a_Expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+ ASSERT_GUEST_PANIC(); \
+ } \
+ } while (0)
+
+/** @def ASSERT_GUEST_LOGREL_RETURN
+ * Assert that an expression is true, return \a a_rc if it isn't.
+ * Strict builds will hit a breakpoint, non-strict will only do LogRel.
+ *
+ * @param a_Expr Expression which should be true.
+ * @param a_rc What is to be presented to return.
+ */
+#define ASSERT_GUEST_LOGREL_RETURN(a_Expr, a_rc) \
+ do { \
+ if (RT_LIKELY(!!(a_Expr))) \
+ { /* likely */ } \
+ else \
+ { \
+ ASSERT_GUEST_LOGREL_MSG1(#a_Expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+ ASSERT_GUEST_PANIC(); \
+ return (a_rc); \
+ } \
+ } while (0)
+
+/** @def ASSERT_GUEST_LOGREL_RETURN_VOID
+ * 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 a_Expr Expression which should be true.
+ */
+#define ASSERT_GUEST_LOGREL_RETURN_VOID(a_Expr) \
+ do { \
+ if (RT_LIKELY(!!(a_Expr))) \
+ { /* likely */ } \
+ else \
+ { \
+ ASSERT_GUEST_LOGREL_MSG1(#a_Expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+ ASSERT_GUEST_PANIC(); \
+ return; \
+ } \
+ } while (0)
+
+/** @def ASSERT_GUEST_LOGREL_BREAK
+ * Assert that an expression is true, break if it isn't.
+ * Strict builds will hit a breakpoint, non-strict will only do LogRel.
+ *
+ * @param a_Expr Expression which should be true.
+ */
+#define ASSERT_GUEST_LOGREL_BREAK(a_Expr) \
+ if (RT_LIKELY(!!(a_Expr))) \
+ { /* likely */ } \
+ else if (1) \
+ { \
+ ASSERT_GUEST_LOGREL_MSG1(#a_Expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+ ASSERT_GUEST_PANIC(); \
+ break; \
+ } \
+ else \
+ break
+
+/** @def ASSERT_GUEST_LOGREL_STMT_BREAK
+ * Assert that an expression is true, execute \a a_Stmt and break if it isn't.
+ * Strict builds will hit a breakpoint, non-strict will only do LogRel.
+ *
+ * @param a_Expr Expression which should be true.
+ * @param a_Stmt Statement to execute before break in case of a failed assertion.
+ */
+#define ASSERT_GUEST_LOGREL_STMT_BREAK(a_Expr, a_Stmt) \
+ if (RT_LIKELY(!!(a_Expr))) \
+ { /* likely */ } \
+ else if (1) \
+ { \
+ ASSERT_GUEST_LOGREL_MSG1(#a_Expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+ ASSERT_GUEST_PANIC(); \
+ a_Stmt; \
+ break; \
+ } else \
+ break
+
+/** @def ASSERT_GUEST_LOGREL_MSG
+ * Assert that an expression is true.
+ * Strict builds will hit a breakpoint, non-strict will only do LogRel.
+ *
+ * @param a_Expr Expression which should be true.
+ * @param a printf argument list (in parenthesis).
+ */
+#define ASSERT_GUEST_LOGREL_MSG(a_Expr, a) \
+ do { \
+ if (RT_LIKELY(!!(a_Expr))) \
+ { /* likely */ } \
+ else\
+ { \
+ ASSERT_GUEST_LOGREL_MSG1(#a_Expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+ ASSERT_GUEST_LOGREL_MSG2(a); \
+ ASSERT_GUEST_PANIC(); \
+ } \
+ } while (0)
+
+/** @def ASSERT_GUEST_LOGREL_MSG_STMT
+ * Assert that an expression is true, execute \a a_Stmt and break if it isn't
+ * Strict builds will hit a breakpoint, non-strict will only do LogRel.
+ *
+ * @param a_Expr Expression which should be true.
+ * @param a printf argument list (in parenthesis).
+ * @param a_Stmt Statement to execute in case of a failed assertion.
+ */
+#define ASSERT_GUEST_LOGREL_MSG_STMT(a_Expr, a, a_Stmt) \
+ do { \
+ if (RT_LIKELY(!!(a_Expr))) \
+ { /* likely */ } \
+ else\
+ { \
+ ASSERT_GUEST_LOGREL_MSG1(#a_Expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+ ASSERT_GUEST_LOGREL_MSG2(a); \
+ ASSERT_GUEST_PANIC(); \
+ a_Stmt; \
+ } \
+ } while (0)
+
+/** @def ASSERT_GUEST_LOGREL_MSG_RETURN
+ * Assert that an expression is true, return \a a_rc if it isn't.
+ * Strict builds will hit a breakpoint, non-strict will only do LogRel.
+ *
+ * @param a_Expr Expression which should be true.
+ * @param a printf argument list (in parenthesis).
+ * @param a_rc What is to be presented to return.
+ */
+#define ASSERT_GUEST_LOGREL_MSG_RETURN(a_Expr, a, a_rc) \
+ do { \
+ if (RT_LIKELY(!!(a_Expr))) \
+ { /* likely */ } \
+ else\
+ { \
+ ASSERT_GUEST_LOGREL_MSG1(#a_Expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+ ASSERT_GUEST_LOGREL_MSG2(a); \
+ ASSERT_GUEST_PANIC(); \
+ return (a_rc); \
+ } \
+ } while (0)
+
+/** @def ASSERT_GUEST_LOGREL_MSG_STMT_RETURN
+ * Assert that an expression is true, execute @a a_Stmt and return @a rcRet if it
+ * isn't.
+ * Strict builds will hit a breakpoint, non-strict will only do LogRel.
+ *
+ * @param a_Expr Expression which should be true.
+ * @param a printf argument list (in parenthesis).
+ * @param a_Stmt Statement to execute before returning in case of a failed
+ * assertion.
+ * @param rcRet What is to be presented to return.
+ */
+#define ASSERT_GUEST_LOGREL_MSG_STMT_RETURN(a_Expr, a, a_Stmt, rcRet) \
+ do { \
+ if (RT_LIKELY(!!(a_Expr))) \
+ { /* likely */ } \
+ else\
+ { \
+ ASSERT_GUEST_LOGREL_MSG1(#a_Expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+ ASSERT_GUEST_LOGREL_MSG2(a); \
+ ASSERT_GUEST_PANIC(); \
+ a_Stmt; \
+ return (rcRet); \
+ } \
+ } while (0)
+
+/** @def ASSERT_GUEST_LOGREL_MSG_RETURN_VOID
+ * 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 a_Expr Expression which should be true.
+ * @param a printf argument list (in parenthesis).
+ */
+#define ASSERT_GUEST_LOGREL_MSG_RETURN_VOID(a_Expr, a) \
+ do { \
+ if (RT_LIKELY(!!(a_Expr))) \
+ { /* likely */ } \
+ else\
+ { \
+ ASSERT_GUEST_LOGREL_MSG1(#a_Expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+ ASSERT_GUEST_LOGREL_MSG2(a); \
+ ASSERT_GUEST_PANIC(); \
+ return; \
+ } \
+ } while (0)
+
+/** @def ASSERT_GUEST_LOGREL_MSG_BREAK
+ * Assert that an expression is true, break if it isn't.
+ * Strict builds will hit a breakpoint, non-strict will only do LogRel.
+ *
+ * @param a_Expr Expression which should be true.
+ * @param a printf argument list (in parenthesis).
+ */
+#define ASSERT_GUEST_LOGREL_MSG_BREAK(a_Expr, a) \
+ if (RT_LIKELY(!!(a_Expr))) \
+ { /* likely */ } \
+ else if (1) \
+ { \
+ ASSERT_GUEST_LOGREL_MSG1(#a_Expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+ ASSERT_GUEST_LOGREL_MSG2(a); \
+ ASSERT_GUEST_PANIC(); \
+ break; \
+ } \
+ else \
+ break
+
+/** @def ASSERT_GUEST_LOGREL_MSG_STMT_BREAK
+ * Assert that an expression is true, execute \a a_Stmt and break if it isn't.
+ * Strict builds will hit a breakpoint, non-strict will only do LogRel.
+ *
+ * @param a_Expr Expression which should be true.
+ * @param a printf argument list (in parenthesis).
+ * @param a_Stmt Statement to execute before break in case of a failed assertion.
+ */
+#define ASSERT_GUEST_LOGREL_MSG_STMT_BREAK(a_Expr, a, a_Stmt) \
+ if (RT_LIKELY(!!(a_Expr))) \
+ { /* likely */ } \
+ else if (1) \
+ { \
+ ASSERT_GUEST_LOGREL_MSG1(#a_Expr, __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+ ASSERT_GUEST_LOGREL_MSG2(a); \
+ ASSERT_GUEST_PANIC(); \
+ a_Stmt; \
+ break; \
+ } else \
+ break
+
+/** @def ASSERT_GUEST_LOGREL_FAILED
+ * An assertion failed.
+ * Strict builds will hit a breakpoint, non-strict will only do LogRel.
+ */
+#define ASSERT_GUEST_LOGREL_FAILED() \
+ do { \
+ ASSERT_GUEST_LOGREL_MSG1("failed", __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+ ASSERT_GUEST_PANIC(); \
+ } while (0)
+
+/** @def ASSERT_GUEST_LOGREL_FAILED_RETURN
+ * An assertion failed.
+ * Strict builds will hit a breakpoint, non-strict will only do LogRel.
+ *
+ * @param a_rc What is to be presented to return.
+ */
+#define ASSERT_GUEST_LOGREL_FAILED_RETURN(a_rc) \
+ do { \
+ ASSERT_GUEST_LOGREL_MSG1("failed", __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+ ASSERT_GUEST_PANIC(); \
+ return (a_rc); \
+ } while (0)
+
+/** @def ASSERT_GUEST_LOGREL_FAILED_RETURN_VOID
+ * An assertion failed, hit a breakpoint and return.
+ * Strict builds will hit a breakpoint, non-strict will only do LogRel.
+ */
+#define ASSERT_GUEST_LOGREL_FAILED_RETURN_VOID() \
+ do { \
+ ASSERT_GUEST_LOGREL_MSG1("failed", __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+ ASSERT_GUEST_PANIC(); \
+ return; \
+ } while (0)
+
+/** @def ASSERT_GUEST_LOGREL_FAILED_BREAK
+ * An assertion failed, break.
+ * Strict builds will hit a breakpoint, non-strict will only do LogRel.
+ */
+#define ASSERT_GUEST_LOGREL_FAILED_BREAK() \
+ if (1) \
+ { \
+ ASSERT_GUEST_LOGREL_MSG1("failed", __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+ ASSERT_GUEST_PANIC(); \
+ break; \
+ } else \
+ break
+
+/** @def ASSERT_GUEST_LOGREL_FAILED_STMT_BREAK
+ * An assertion failed, execute \a a_Stmt and break.
+ * Strict builds will hit a breakpoint, non-strict will only do LogRel.
+ *
+ * @param a_Stmt Statement to execute before break.
+ */
+#define ASSERT_GUEST_LOGREL_FAILED_STMT_BREAK(a_Stmt) \
+ if (1) \
+ { \
+ ASSERT_GUEST_LOGREL_MSG1("failed", __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+ ASSERT_GUEST_PANIC(); \
+ a_Stmt; \
+ break; \
+ } else \
+ break
+
+/** @def ASSERT_GUEST_LOGREL_MSG_FAILED
+ * An assertion failed.
+ * Strict builds will hit a breakpoint, non-strict will only do LogRel.
+ *
+ * @param a printf argument list (in parenthesis).
+ */
+#define ASSERT_GUEST_LOGREL_MSG_FAILED(a) \
+ do { \
+ ASSERT_GUEST_LOGREL_MSG1("failed", __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+ ASSERT_GUEST_LOGREL_MSG2(a); \
+ ASSERT_GUEST_PANIC(); \
+ } while (0)
+
+/** @def ASSERT_GUEST_LOGREL_MSG_FAILED_STMT
+ * An assertion failed, execute @a 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 a_Stmt Statement to execute after raising/logging the assertion.
+ */
+#define ASSERT_GUEST_LOGREL_MSG_FAILED_STMT(a, a_Stmt) \
+ do { \
+ ASSERT_GUEST_LOGREL_MSG1("failed", __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+ ASSERT_GUEST_LOGREL_MSG2(a); \
+ ASSERT_GUEST_PANIC(); \
+ a_Stmt; \
+ } while (0)
+
+/** @def ASSERT_GUEST_LOGREL_MSG_FAILED_RETURN
+ * An assertion failed, return \a a_rc.
+ * Strict builds will hit a breakpoint, non-strict will only do LogRel.
+ *
+ * @param a printf argument list (in parenthesis).
+ * @param a_rc What is to be presented to return.
+ */
+#define ASSERT_GUEST_LOGREL_MSG_FAILED_RETURN(a, a_rc) \
+ do { \
+ ASSERT_GUEST_LOGREL_MSG1("failed", __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+ ASSERT_GUEST_LOGREL_MSG2(a); \
+ ASSERT_GUEST_PANIC(); \
+ return (a_rc); \
+ } while (0)
+
+/** @def ASSERT_GUEST_LOGREL_MSG_FAILED_STMT_RETURN
+ * An assertion failed, execute @a a_Stmt and return @a a_rc.
+ * Strict builds will hit a breakpoint, non-strict will only do LogRel.
+ *
+ * @param a printf argument list (in parenthesis).
+ * @param a_Stmt Statement to execute before returning in case of a failed
+ * assertion.
+ * @param a_rc What is to be presented to return.
+ */
+#define ASSERT_GUEST_LOGREL_MSG_FAILED_STMT_RETURN(a, a_Stmt, a_rc) \
+ do { \
+ ASSERT_GUEST_LOGREL_MSG1("failed", __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+ ASSERT_GUEST_LOGREL_MSG2(a); \
+ ASSERT_GUEST_PANIC(); \
+ a_Stmt; \
+ return (a_rc); \
+ } while (0)
+
+/** @def ASSERT_GUEST_LOGREL_MSG_FAILED_RETURN_VOID
+ * 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 ASSERT_GUEST_LOGREL_MSG_FAILED_RETURN_VOID(a) \
+ do { \
+ ASSERT_GUEST_LOGREL_MSG1("failed", __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+ ASSERT_GUEST_LOGREL_MSG2(a); \
+ ASSERT_GUEST_PANIC(); \
+ return; \
+ } while (0)
+
+/** @def ASSERT_GUEST_LOGREL_MSG_FAILED_STMT_RETURN_VOID
+ * An assertion failed, execute @a 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 a_Stmt Statement to execute before returning in case of a failed
+ * assertion.
+ */
+#define ASSERT_GUEST_LOGREL_MSG_FAILED_STMT_RETURN_VOID(a, a_Stmt) \
+ do { \
+ ASSERT_GUEST_LOGREL_MSG1("failed", __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+ ASSERT_GUEST_LOGREL_MSG2(a); \
+ ASSERT_GUEST_PANIC(); \
+ a_Stmt; \
+ return; \
+ } while (0)
+
+/** @def ASSERT_GUEST_LOGREL_MSG_FAILED_BREAK
+ * An assertion failed, break.
+ * Strict builds will hit a breakpoint, non-strict will only do LogRel.
+ *
+ * @param a printf argument list (in parenthesis).
+ */
+#define ASSERT_GUEST_LOGREL_MSG_FAILED_BREAK(a) \
+ if (1)\
+ { \
+ ASSERT_GUEST_LOGREL_MSG1("failed", __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+ ASSERT_GUEST_LOGREL_MSG2(a); \
+ ASSERT_GUEST_PANIC(); \
+ break; \
+ } else \
+ break
+
+/** @def ASSERT_GUEST_LOGREL_MSG_FAILED_STMT_BREAK
+ * An assertion failed, execute \a a_Stmt and break.
+ * Strict builds will hit a breakpoint, non-strict will only do LogRel.
+ *
+ * @param a printf argument list (in parenthesis).
+ * @param a_Stmt Statement to execute before break.
+ */
+#define ASSERT_GUEST_LOGREL_MSG_FAILED_STMT_BREAK(a, a_Stmt) \
+ if (1) \
+ { \
+ ASSERT_GUEST_LOGREL_MSG1("failed", __LINE__, __FILE__, __PRETTY_FUNCTION__); \
+ ASSERT_GUEST_LOGREL_MSG2(a); \
+ ASSERT_GUEST_PANIC(); \
+ a_Stmt; \
+ break; \
+ } else \
+ break
+
+/** @} */
+
+
+/** @name Convenience Assertions Macros
+ * @{
+ */
+
+/** @def ASSERT_GUEST_RC
+ * 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 ASSERT_GUEST_RC(rc) ASSERT_GUEST_MSG_RC(rc, ("%Rra\n", (rc)))
+
+/** @def ASSERT_GUEST_RC_STMT
+ * 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 ASSERT_GUEST_RC_STMT(rc, stmt) ASSERT_GUEST_MSG_RC_STMT(rc, ("%Rra\n", (rc)), stmt)
+
+/** @def ASSERT_GUEST_RC_RETURN
+ * 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 ASSERT_GUEST_RC_RETURN(rc, rcRet) ASSERT_GUEST_MSG_RC_RETURN(rc, ("%Rra\n", (rc)), rcRet)
+
+/** @def ASSERT_GUEST_RC_STMT_RETURN
+ * 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 ASSERT_GUEST_RC_STMT_RETURN(rc, stmt, rcRet) ASSERT_GUEST_MSG_RC_STMT_RETURN(rc, ("%Rra\n", (rc)), stmt, rcRet)
+
+/** @def ASSERT_GUEST_RC_RETURN_VOID
+ * 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 ASSERT_GUEST_RC_RETURN_VOID(rc) ASSERT_GUEST_MSG_RC_RETURN_VOID(rc, ("%Rra\n", (rc)))
+
+/** @def ASSERT_GUEST_RC_STMT_RETURN_VOID
+ * 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 ASSERT_GUEST_RC_STMT_RETURN_VOID(rc, stmt) ASSERT_GUEST_MSG_RC_STMT_RETURN_VOID(rc, ("%Rra\n", (rc)), stmt)
+
+/** @def ASSERT_GUEST_RC_BREAK
+ * 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 ASSERT_GUEST_RC_BREAK(rc) ASSERT_GUEST_MSG_RC_BREAK(rc, ("%Rra\n", (rc)))
+
+/** @def ASSERT_GUEST_RC_STMT_BREAK
+ * 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 ASSERT_GUEST_RC_STMT_BREAK(rc, stmt) ASSERT_GUEST_MSG_RC_STMT_BREAK(rc, ("%Rra\n", (rc)), stmt)
+
+/** @def ASSERT_GUEST_MSG_RC
+ * 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 ASSERT_GUEST_MSG_RC(rc, msg) \
+ do { ASSERT_GUEST_MSG(RT_SUCCESS_NP(rc), msg); NOREF(rc); } while (0)
+
+/** @def ASSERT_GUEST_MSG_RC_STMT
+ * 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 ASSERT_GUEST_MSG_RC_STMT(rc, msg, stmt) \
+ do { ASSERT_GUEST_MSG_STMT(RT_SUCCESS_NP(rc), msg, stmt); NOREF(rc); } while (0)
+
+/** @def ASSERT_GUEST_MSG_RC_RETURN
+ * 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 ASSERT_GUEST_MSG_RC_RETURN(rc, msg, rcRet) \
+ do { ASSERT_GUEST_MSG_RETURN(RT_SUCCESS_NP(rc), msg, rcRet); NOREF(rc); } while (0)
+
+/** @def ASSERT_GUEST_MSG_RC_STMT_RETURN
+ * 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 ASSERT_GUEST_MSG_RC_STMT_RETURN(rc, msg, stmt, rcRet) \
+ do { ASSERT_GUEST_MSG_STMT_RETURN(RT_SUCCESS_NP(rc), msg, stmt, rcRet); NOREF(rc); } while (0)
+
+/** @def ASSERT_GUEST_MSG_RC_RETURN_VOID
+ * 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 ASSERT_GUEST_MSG_RC_RETURN_VOID(rc, msg) \
+ do { ASSERT_GUEST_MSG_RETURN_VOID(RT_SUCCESS_NP(rc), msg); NOREF(rc); } while (0)
+
+/** @def ASSERT_GUEST_MSG_RC_STMT_RETURN_VOID
+ * 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 ASSERT_GUEST_MSG_RC_STMT_RETURN_VOID(rc, msg, stmt) \
+ do { ASSERT_GUEST_MSG_STMT_RETURN_VOID(RT_SUCCESS_NP(rc), msg, stmt); NOREF(rc); } while (0)
+
+/** @def ASSERT_GUEST_MSG_RC_BREAK
+ * 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 ASSERT_GUEST_MSG_RC_BREAK(rc, msg) \
+ if (1) { ASSERT_GUEST_MSG_BREAK(RT_SUCCESS(rc), msg); NOREF(rc); } else do {} while (0)
+
+/** @def ASSERT_GUEST_MSG_RC_STMT_BREAK
+ * 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 ASSERT_GUEST_MSG_RC_STMT_BREAK(rc, msg, stmt) \
+ if (1) { ASSERT_GUEST_MSG_STMT_BREAK(RT_SUCCESS_NP(rc), msg, stmt); NOREF(rc); } else do {} while (0)
+
+/** @def ASSERT_GUEST_RC_SUCCESS
+ * 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 ASSERT_GUEST_RC_SUCCESS(rc) do { ASSERT_GUEST_MSG((rc) == VINF_SUCCESS, ("%Rra\n", (rc))); NOREF(rc); } while (0)
+
+/** @def ASSERT_GUEST_RC_SUCCESS_RETURN
+ * 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 ASSERT_GUEST_RC_SUCCESS_RETURN(rc, rcRet) ASSERT_GUEST_MSG_RETURN((rc) == VINF_SUCCESS, ("%Rra\n", (rc)), rcRet)
+
+/** @def ASSERT_GUEST_RC_SUCCESS_RETURN_VOID
+ * 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 ASSERT_GUEST_RC_SUCCESS_RETURN_VOID(rc) ASSERT_GUEST_MSG_RETURN_VOID((rc) == VINF_SUCCESS, ("%Rra\n", (rc)))
+
+/** @def ASSERT_GUEST_RC_SUCCESS_BREAK
+ * 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 ASSERT_GUEST_RC_SUCCESS_BREAK(rc) ASSERT_GUEST_MSG_BREAK((rc) == VINF_SUCCESS, ("%Rra\n", (rc)))
+
+/** @def ASSERT_GUEST_RC_SUCCESS_STMT_BREAK
+ * 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 ASSERT_GUEST_RC_SUCCESS_STMT_BREAK(rc, stmt) ASSERT_GUEST_MSG_STMT_BREAK((rc) == VINF_SUCCESS, ("%Rra\n", (rc)), stmt)
+
+/** @def ASSERT_GUEST_GCPHYS32
+ * Asserts that the high dword of a physical address is zero
+ *
+ * @param GCPhys The address (RTGCPHYS).
+ */
+#define ASSERT_GUEST_GCPHYS32(GCPhys) ASSERT_GUEST_MSG(VALID_PHYS32(GCPhys), ("%RGp\n", (RTGCPHYS)(GCPhys)))
+
+
+/** @def ASSERT_GUEST_RC
+ * 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 ASSERT_GUEST_LOGREL_RC(rc) ASSERT_GUEST_LOGREL_MSG_RC(rc, ("%Rra\n", (rc)))
+
+/** @def ASSERT_GUEST_LOGREL_RC_STMT
+ * 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 ASSERT_GUEST_LOGREL_RC_STMT(rc, stmt) ASSERT_GUEST_LOGREL_MSG_RC_STMT(rc, ("%Rra\n", (rc)), stmt)
+
+/** @def ASSERT_GUEST_LOGREL_RC_RETURN
+ * 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 ASSERT_GUEST_LOGREL_RC_RETURN(rc, rcRet) ASSERT_GUEST_LOGREL_MSG_RC_RETURN(rc, ("%Rra\n", (rc)), rcRet)
+
+/** @def ASSERT_GUEST_LOGREL_RC_STMT_RETURN
+ * 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 ASSERT_GUEST_LOGREL_RC_STMT_RETURN(rc, stmt, rcRet) ASSERT_GUEST_LOGREL_MSG_RC_STMT_RETURN(rc, ("%Rra\n", (rc)), stmt, rcRet)
+
+/** @def ASSERT_GUEST_LOGREL_RC_RETURN_VOID
+ * 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 ASSERT_GUEST_LOGREL_RC_RETURN_VOID(rc) ASSERT_GUEST_LOGREL_MSG_RC_RETURN_VOID(rc, ("%Rra\n", (rc)))
+
+/** @def ASSERT_GUEST_LOGREL_RC_STMT_RETURN_VOID
+ * 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 ASSERT_GUEST_LOGREL_RC_STMT_RETURN_VOID(rc, stmt) ASSERT_GUEST_LOGREL_MSG_RC_STMT_RETURN_VOID(rc, ("%Rra\n", (rc)), stmt)
+
+/** @def ASSERT_GUEST_LOGREL_RC_BREAK
+ * 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 ASSERT_GUEST_LOGREL_RC_BREAK(rc) ASSERT_GUEST_LOGREL_MSG_RC_BREAK(rc, ("%Rra\n", (rc)))
+
+/** @def ASSERT_GUEST_LOGREL_RC_STMT_BREAK
+ * 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 ASSERT_GUEST_LOGREL_RC_STMT_BREAK(rc, stmt) ASSERT_GUEST_LOGREL_MSG_RC_STMT_BREAK(rc, ("%Rra\n", (rc)), stmt)
+
+/** @def ASSERT_GUEST_LOGREL_MSG_RC
+ * 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 ASSERT_GUEST_LOGREL_MSG_RC(rc, msg) \
+ do { ASSERT_GUEST_LOGREL_MSG(RT_SUCCESS_NP(rc), msg); NOREF(rc); } while (0)
+
+/** @def ASSERT_GUEST_LOGREL_MSG_RC_STMT
+ * 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 ASSERT_GUEST_LOGREL_MSG_RC_STMT(rc, msg, stmt) \
+ do { ASSERT_GUEST_LOGREL_MSG_STMT(RT_SUCCESS_NP(rc), msg, stmt); NOREF(rc); } while (0)
+
+/** @def ASSERT_GUEST_LOGREL_MSG_RC_RETURN
+ * 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 ASSERT_GUEST_LOGREL_MSG_RC_RETURN(rc, msg, rcRet) \
+ do { ASSERT_GUEST_LOGREL_MSG_RETURN(RT_SUCCESS_NP(rc), msg, rcRet); NOREF(rc); } while (0)
+
+/** @def ASSERT_GUEST_LOGREL_MSG_RC_STMT_RETURN
+ * 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 ASSERT_GUEST_LOGREL_MSG_RC_STMT_RETURN(rc, msg, stmt, rcRet) \
+ do { ASSERT_GUEST_LOGREL_MSG_STMT_RETURN(RT_SUCCESS_NP(rc), msg, stmt, rcRet); NOREF(rc); } while (0)
+
+/** @def ASSERT_GUEST_LOGREL_MSG_RC_RETURN_VOID
+ * 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 ASSERT_GUEST_LOGREL_MSG_RC_RETURN_VOID(rc, msg) \
+ do { ASSERT_GUEST_LOGREL_MSG_RETURN_VOID(RT_SUCCESS_NP(rc), msg); NOREF(rc); } while (0)
+
+/** @def ASSERT_GUEST_LOGREL_MSG_RC_STMT_RETURN_VOID
+ * 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 ASSERT_GUEST_LOGREL_MSG_RC_STMT_RETURN_VOID(rc, msg, stmt) \
+ do { ASSERT_GUEST_LOGREL_MSG_STMT_RETURN_VOID(RT_SUCCESS_NP(rc), msg, stmt); NOREF(rc); } while (0)
+
+/** @def ASSERT_GUEST_LOGREL_MSG_RC_BREAK
+ * 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 ASSERT_GUEST_LOGREL_MSG_RC_BREAK(rc, msg) \
+ if (1) { ASSERT_GUEST_LOGREL_MSG_BREAK(RT_SUCCESS(rc), msg); NOREF(rc); } else do {} while (0)
+
+/** @def ASSERT_GUEST_LOGREL_MSG_RC_STMT_BREAK
+ * 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 ASSERT_GUEST_LOGREL_MSG_RC_STMT_BREAK(rc, msg, stmt) \
+ if (1) { ASSERT_GUEST_LOGREL_MSG_STMT_BREAK(RT_SUCCESS_NP(rc), msg, stmt); NOREF(rc); } else do {} while (0)
+
+/** @def ASSERT_GUEST_LOGREL_RC_SUCCESS
+ * 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 ASSERT_GUEST_LOGREL_RC_SUCCESS(rc) do { ASSERT_GUEST_LOGREL_MSG((rc) == VINF_SUCCESS, ("%Rra\n", (rc))); NOREF(rc); } while (0)
+
+/** @def ASSERT_GUEST_LOGREL_RC_SUCCESS_RETURN
+ * 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 ASSERT_GUEST_LOGREL_RC_SUCCESS_RETURN(rc, rcRet) ASSERT_GUEST_LOGREL_MSG_RETURN((rc) == VINF_SUCCESS, ("%Rra\n", (rc)), rcRet)
+
+/** @def ASSERT_GUEST_LOGREL_RC_SUCCESS_RETURN_VOID
+ * 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 ASSERT_GUEST_LOGREL_RC_SUCCESS_RETURN_VOID(rc) ASSERT_GUEST_LOGREL_MSG_RETURN_VOID((rc) == VINF_SUCCESS, ("%Rra\n", (rc)))
+
+/** @def ASSERT_GUEST_LOGREL_RC_SUCCESS_BREAK
+ * 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 ASSERT_GUEST_LOGREL_RC_SUCCESS_BREAK(rc) ASSERT_GUEST_LOGREL_MSG_BREAK((rc) == VINF_SUCCESS, ("%Rra\n", (rc)))
+
+/** @def ASSERT_GUEST_LOGREL_RC_SUCCESS_STMT_BREAK
+ * 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 ASSERT_GUEST_LOGREL_RC_SUCCESS_STMT_BREAK(rc, stmt) ASSERT_GUEST_LOGREL_MSG_STMT_BREAK((rc) == VINF_SUCCESS, ("%Rra\n", (rc)), stmt)
+
+/** @def ASSERT_GUEST_LOGREL_GCPHYS32
+ * Asserts that the high dword of a physical address is zero
+ *
+ * @param GCPhys The address (RTGCPHYS).
+ */
+#define ASSERT_GUEST_LOGREL_GCPHYS32(GCPhys) ASSERT_GUEST_LOGREL_MSG(VALID_PHYS32(GCPhys), ("%RGp\n", (RTGCPHYS)(GCPhys)))
+
+
+/** @} */
+
+
+/** @} */
+
+#endif /* !VBOX_INCLUDED_AssertGuest_h */
+
diff --git a/include/VBox/ExtPack/ExtPack.h b/include/VBox/ExtPack/ExtPack.h
new file mode 100644
index 00000000..61f415c3
--- /dev/null
+++ b/include/VBox/ExtPack/ExtPack.h
@@ -0,0 +1,647 @@
+/** @file
+ * VirtualBox - Extension Pack Interface.
+ */
+
+/*
+ * Copyright (C) 2010-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_ExtPack_ExtPack_h
+#define VBOX_INCLUDED_ExtPack_ExtPack_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/types.h>
+
+/** @def VBOXEXTPACK_IF_CS
+ * Selects 'class' on 'struct' for interface references.
+ * @param I The interface name
+ */
+#if defined(__cplusplus) && !defined(RT_OS_WINDOWS)
+# define VBOXEXTPACK_IF_CS(I) class I
+#else
+# define VBOXEXTPACK_IF_CS(I) struct I
+#endif
+
+VBOXEXTPACK_IF_CS(IUnknown);
+VBOXEXTPACK_IF_CS(IConsole);
+VBOXEXTPACK_IF_CS(IMachine);
+VBOXEXTPACK_IF_CS(IVirtualBox);
+VBOXEXTPACK_IF_CS(IProgress);
+VBOXEXTPACK_IF_CS(IEvent);
+VBOXEXTPACK_IF_CS(IVetoEvent);
+VBOXEXTPACK_IF_CS(IEventSource);
+
+/**
+ * Module kind for use with VBOXEXTPACKHLP::pfnFindModule.
+ */
+typedef enum VBOXEXTPACKMODKIND
+{
+ /** Zero is invalid as always. */
+ VBOXEXTPACKMODKIND_INVALID = 0,
+ /** Raw-mode context module. */
+ VBOXEXTPACKMODKIND_RC,
+ /** Ring-0 context module. */
+ VBOXEXTPACKMODKIND_R0,
+ /** Ring-3 context module. */
+ VBOXEXTPACKMODKIND_R3,
+ /** End of the valid values (exclusive). */
+ VBOXEXTPACKMODKIND_END,
+ /** The usual 32-bit type hack. */
+ VBOXEXTPACKMODKIND_32BIT_HACK = 0x7fffffff
+} VBOXEXTPACKMODKIND;
+
+/**
+ * Contexts returned by VBOXEXTPACKHLP::pfnGetContext.
+ */
+typedef enum VBOXEXTPACKCTX
+{
+ /** Zero is invalid as always. */
+ VBOXEXTPACKCTX_INVALID = 0,
+ /** The per-user daemon process (VBoxSVC). */
+ VBOXEXTPACKCTX_PER_USER_DAEMON,
+ /** A VM process. */
+ VBOXEXTPACKCTX_VM_PROCESS,
+ /** An API client process.
+ * @remarks This will not be returned by VirtualBox yet. */
+ VBOXEXTPACKCTX_CLIENT_PROCESS,
+ /** End of the valid values (exclusive). */
+ VBOXEXTPACKCTX_END,
+ /** The usual 32-bit type hack. */
+ VBOXEXTPACKCTX_32BIT_HACK = 0x7fffffff
+} VBOXEXTPACKCTX;
+
+
+/** Pointer to const helpers passed to the VBoxExtPackRegister() call. */
+typedef const struct VBOXEXTPACKHLP *PCVBOXEXTPACKHLP;
+/**
+ * Extension pack helpers passed to VBoxExtPackRegister().
+ *
+ * This will be valid until the module is unloaded.
+ */
+typedef struct VBOXEXTPACKHLP
+{
+ /** Interface version.
+ * This is set to VBOXEXTPACKHLP_VERSION. */
+ uint32_t u32Version;
+
+ /** The VirtualBox full version (see VBOX_FULL_VERSION). */
+ uint32_t uVBoxFullVersion;
+ /** The VirtualBox subversion tree revision. */
+ uint32_t uVBoxInternalRevision;
+ /** Explicit alignment padding, must be zero. */
+ uint32_t u32Padding;
+ /** Pointer to the version string (read-only). */
+ const char *pszVBoxVersion;
+
+ /**
+ * Finds a module belonging to this extension pack.
+ *
+ * @returns VBox status code.
+ * @param pHlp Pointer to this helper structure.
+ * @param pszName The module base name.
+ * @param pszExt The extension. If NULL the default ring-3
+ * library extension will be used.
+ * @param enmKind The kind of module to locate.
+ * @param pszFound Where to return the path to the module on
+ * success.
+ * @param cbFound The size of the buffer @a pszFound points to.
+ * @param pfNative Where to return the native/agnostic indicator.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnFindModule,(PCVBOXEXTPACKHLP pHlp, const char *pszName, const char *pszExt,
+ VBOXEXTPACKMODKIND enmKind,
+ char *pszFound, size_t cbFound, bool *pfNative));
+
+ /**
+ * Gets the path to a file belonging to this extension pack.
+ *
+ * @returns VBox status code.
+ * @retval VERR_INVALID_POINTER if any of the pointers are invalid.
+ * @retval VERR_BUFFER_OVERFLOW if the buffer is too small. The buffer
+ * will contain nothing.
+ *
+ * @param pHlp Pointer to this helper structure.
+ * @param pszFilename The filename.
+ * @param pszPath Where to return the path to the file on
+ * success.
+ * @param cbPath The size of the buffer @a pszPath.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnGetFilePath,(PCVBOXEXTPACKHLP pHlp, const char *pszFilename, char *pszPath, size_t cbPath));
+
+ /**
+ * Gets the context the extension pack is operating in.
+ *
+ * @returns The context.
+ * @retval VBOXEXTPACKCTX_INVALID if @a pHlp is invalid.
+ *
+ * @param pHlp Pointer to this helper structure.
+ */
+ DECLR3CALLBACKMEMBER(VBOXEXTPACKCTX, pfnGetContext,(PCVBOXEXTPACKHLP pHlp));
+
+ /**
+ * Loads a HGCM service provided by an extension pack.
+ *
+ * @returns VBox status code.
+ * @param pHlp Pointer to this helper structure.
+ * @param pConsole Pointer to the VM's console object.
+ * @param pszServiceLibrary Name of the library file containing the
+ * service implementation, without extension.
+ * @param pszServiceName Name of HGCM service.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnLoadHGCMService,(PCVBOXEXTPACKHLP pHlp, VBOXEXTPACK_IF_CS(IConsole) *pConsole,
+ const char *pszServiceLibrary, const char *pszServiceName));
+
+ /**
+ * Loads a VD plugin provided by an extension pack.
+ *
+ * This makes sense only in the context of the per-user service (VBoxSVC).
+ *
+ * @returns VBox status code.
+ * @param pHlp Pointer to this helper structure.
+ * @param pVirtualBox Pointer to the VirtualBox object.
+ * @param pszPluginLibrary Name of the library file containing the plugin
+ * implementation, without extension.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnLoadVDPlugin,(PCVBOXEXTPACKHLP pHlp, VBOXEXTPACK_IF_CS(IVirtualBox) *pVirtualBox,
+ const char *pszPluginLibrary));
+
+ /**
+ * Unloads a VD plugin provided by an extension pack.
+ *
+ * This makes sense only in the context of the per-user service (VBoxSVC).
+ *
+ * @returns VBox status code.
+ * @param pHlp Pointer to this helper structure.
+ * @param pVirtualBox Pointer to the VirtualBox object.
+ * @param pszPluginLibrary Name of the library file containing the plugin
+ * implementation, without extension.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnUnloadVDPlugin,(PCVBOXEXTPACKHLP pHlp, VBOXEXTPACK_IF_CS(IVirtualBox) *pVirtualBox,
+ const char *pszPluginLibrary));
+
+ /**
+ * Creates an IProgress object instance for a long running extension
+ * pack provided API operation which is executed asynchronously.
+ *
+ * This implicitly creates a cancellable progress object, since anything
+ * else is user unfriendly. You need to design your code to handle
+ * cancellation with reasonable response time.
+ *
+ * @returns COM status code.
+ * @param pHlp Pointer to this helper structure.
+ * @param pInitiator Pointer to the initiating object.
+ * @param pcszDescription Description of the overall task.
+ * @param cOperations Number of operations for this task.
+ * @param uTotalOperationsWeight Overall weight for the entire task.
+ * @param pcszFirstOperationDescription Description of the first operation.
+ * @param uFirstOperationWeight Weight for the first operation.
+ * @param ppProgressOut Output parameter for the IProgress object reference.
+ */
+ DECLR3CALLBACKMEMBER(uint32_t, pfnCreateProgress,(PCVBOXEXTPACKHLP pHlp, VBOXEXTPACK_IF_CS(IUnknown) *pInitiator,
+ const char *pcszDescription, uint32_t cOperations,
+ uint32_t uTotalOperationsWeight, const char *pcszFirstOperationDescription,
+ uint32_t uFirstOperationWeight, VBOXEXTPACK_IF_CS(IProgress) **ppProgressOut));
+
+ /**
+ * Checks if the Progress object is marked as canceled.
+ *
+ * @returns COM status code.
+ * @param pHlp Pointer to this helper structure.
+ * @param pProgress Pointer to the IProgress object reference returned
+ * by pfnCreateProgress.
+ * @param pfCanceled @c true if canceled, @c false otherwise.
+ */
+ DECLR3CALLBACKMEMBER(uint32_t, pfnGetCanceledProgress,(PCVBOXEXTPACKHLP pHlp, VBOXEXTPACK_IF_CS(IProgress) *pProgress,
+ bool *pfCanceled));
+
+ /**
+ * Updates the percentage value of the current operation of the
+ * Progress object.
+ *
+ * @returns COM status code.
+ * @param pHlp Pointer to this helper structure.
+ * @param pProgress Pointer to the IProgress object reference returned
+ * by pfnCreateProgress.
+ * @param uPercent Result of the overall task.
+ */
+ DECLR3CALLBACKMEMBER(uint32_t, pfnUpdateProgress,(PCVBOXEXTPACKHLP pHlp, VBOXEXTPACK_IF_CS(IProgress) *pProgress,
+ uint32_t uPercent));
+
+ /**
+ * Signals that the current operation is successfully completed and
+ * advances to the next operation. The operation percentage is reset
+ * to 0.
+ *
+ * If the operation count is exceeded this returns an error.
+ *
+ * @returns COM status code.
+ * @param pHlp Pointer to this helper structure.
+ * @param pProgress Pointer to the IProgress object reference returned
+ * by pfnCreateProgress.
+ * @param pcszNextOperationDescription Description of the next operation.
+ * @param uNextOperationWeight Weight for the next operation.
+ */
+ DECLR3CALLBACKMEMBER(uint32_t, pfnNextOperationProgress,(PCVBOXEXTPACKHLP pHlp, VBOXEXTPACK_IF_CS(IProgress) *pProgress,
+ const char *pcszNextOperationDescription,
+ uint32_t uNextOperationWeight));
+
+ /**
+ * Waits until the other task is completed (including all sub-operations)
+ * and forward all changes from the other progress to this progress. This
+ * means sub-operation number, description, percent and so on.
+ *
+ * The caller is responsible for having at least the same count of
+ * sub-operations in this progress object as there are in the other
+ * progress object.
+ *
+ * If the other progress object supports cancel and this object gets any
+ * cancel request (when here enabled as well), it will be forwarded to
+ * the other progress object.
+ *
+ * Error information is automatically preserved (by transferring it to
+ * the current thread's error information). If the caller wants to set it
+ * as the completion state of this progress it needs to be done separately.
+ *
+ * @returns COM status code.
+ * @param pHlp Pointer to this helper structure.
+ * @param pProgress Pointer to the IProgress object reference returned
+ * by pfnCreateProgress.
+ * @param pProgressOther Pointer to an IProgress object reference, the one
+ * to be waited for.
+ * @param cTimeoutMS Timeout in milliseconds, 0 for indefinite wait.
+ */
+ DECLR3CALLBACKMEMBER(uint32_t, pfnWaitOtherProgress,(PCVBOXEXTPACKHLP pHlp, VBOXEXTPACK_IF_CS(IProgress) *pProgress,
+ VBOXEXTPACK_IF_CS(IProgress) *pProgressOther,
+ uint32_t cTimeoutMS));
+
+ /**
+ * Marks the whole task as complete and sets the result code.
+ *
+ * If the result code indicates a failure then this method will store
+ * the currently set COM error info from the current thread in the
+ * the errorInfo attribute of this Progress object instance. If there
+ * is no error information available then an error is returned.
+ *
+ * If the result code indicates success then the task is terminated,
+ * without paying attention to the current operation being the last.
+ *
+ * Note that this must be called only once for the given Progress
+ * object. Subsequent calls will return errors.
+ *
+ * @returns COM status code.
+ * @param pHlp Pointer to this helper structure.
+ * @param pProgress Pointer to the IProgress object reference returned
+ * by pfnCreateProgress.
+ * @param uResultCode Result of the overall task.
+ */
+ DECLR3CALLBACKMEMBER(uint32_t, pfnCompleteProgress,(PCVBOXEXTPACKHLP pHlp, VBOXEXTPACK_IF_CS(IProgress) *pProgress,
+ uint32_t uResultCode));
+
+
+ DECLR3CALLBACKMEMBER(uint32_t, pfnCreateEvent,(PCVBOXEXTPACKHLP pHlp,
+ VBOXEXTPACK_IF_CS(IEventSource) *aSource,
+ /* VBoxEventType_T */ uint32_t aType, bool aWaitable,
+ VBOXEXTPACK_IF_CS(IEvent) **ppEventOut));
+
+ DECLR3CALLBACKMEMBER(uint32_t, pfnCreateVetoEvent,(PCVBOXEXTPACKHLP pHlp,
+ VBOXEXTPACK_IF_CS(IEventSource) *aSource,
+ /* VBoxEventType_T */ uint32_t aType,
+ VBOXEXTPACK_IF_CS(IVetoEvent) **ppEventOut));
+
+ /**
+ * Translate the string using registered translation files.
+ *
+ * Translation files are excluded from translation engine. Although
+ * the already loaded translation remains in the translation cache the new
+ * translation will not be loaded after returning from the function if the
+ * user changes the language.
+ *
+ * @returns Translated string on success the pszSourceText otherwise.
+ * @param pHlp Pointer to this helper structure.
+ * @param aComponent Translation context e.g. class name
+ * @param pszSourceText String to translate
+ * @param pszComment Comment to the string to resolve possible ambiguities
+ * (NULL means no comment).
+ * @param aNum Number used to define plural form of the translation
+ */
+ DECLR3CALLBACKMEMBER(const char *, pfnTranslate,(PCVBOXEXTPACKHLP pHlp,
+ const char *pszComponent,
+ const char *pszSourceText,
+ const char *pszComment,
+ const size_t aNum));
+
+ DECLR3CALLBACKMEMBER(int, pfnReserved1,(PCVBOXEXTPACKHLP pHlp)); /**< Reserved for minor structure revisions. */
+ DECLR3CALLBACKMEMBER(int, pfnReserved2,(PCVBOXEXTPACKHLP pHlp)); /**< Reserved for minor structure revisions. */
+ DECLR3CALLBACKMEMBER(int, pfnReserved3,(PCVBOXEXTPACKHLP pHlp)); /**< Reserved for minor structure revisions. */
+ DECLR3CALLBACKMEMBER(int, pfnReserved4,(PCVBOXEXTPACKHLP pHlp)); /**< Reserved for minor structure revisions. */
+ DECLR3CALLBACKMEMBER(int, pfnReserved5,(PCVBOXEXTPACKHLP pHlp)); /**< Reserved for minor structure revisions. */
+ DECLR3CALLBACKMEMBER(int, pfnReserved6,(PCVBOXEXTPACKHLP pHlp)); /**< Reserved for minor structure revisions. */
+
+ /** Reserved for minor structure revisions. */
+ uint32_t uReserved7;
+
+ /** End of structure marker (VBOXEXTPACKHLP_VERSION). */
+ uint32_t u32EndMarker;
+} VBOXEXTPACKHLP;
+/** Current version of the VBOXEXTPACKHLP structure. */
+#define VBOXEXTPACKHLP_VERSION RT_MAKE_U32(0, 5)
+
+
+/** Pointer to the extension pack callback table. */
+typedef struct VBOXEXTPACKREG const *PCVBOXEXTPACKREG;
+/**
+ * Callback table returned by VBoxExtPackRegister.
+ *
+ * All the callbacks are called the context of the per-user service (VBoxSVC).
+ *
+ * This must be valid until the extension pack main module is unloaded.
+ */
+typedef struct VBOXEXTPACKREG
+{
+ /** Interface version.
+ * This is set to VBOXEXTPACKREG_VERSION. */
+ uint32_t u32Version;
+ /** The VirtualBox version this extension pack was built against. */
+ uint32_t uVBoxVersion;
+ /** Translation files base name. Set to NULL if no translation files. */
+ const char *pszNlsBaseName;
+
+ /**
+ * Hook for doing setups after the extension pack was installed.
+ *
+ * @returns VBox status code.
+ * @retval VERR_EXTPACK_UNSUPPORTED_HOST_UNINSTALL if the extension pack
+ * requires some different host version or a prerequisite is
+ * missing from the host. Automatic uninstall will be attempted.
+ * Must set error info.
+ *
+ * @param pThis Pointer to this structure.
+ * @param pVirtualBox The VirtualBox interface.
+ * @param pErrInfo Where to return extended error information.
+ */
+ DECLCALLBACKMEMBER(int, pfnInstalled,(PCVBOXEXTPACKREG pThis, VBOXEXTPACK_IF_CS(IVirtualBox) *pVirtualBox,
+ PRTERRINFO pErrInfo));
+
+ /**
+ * Hook for cleaning up before the extension pack is uninstalled.
+ *
+ * @returns VBox status code.
+ * @param pThis Pointer to this structure.
+ * @param pVirtualBox The VirtualBox interface.
+ *
+ * @todo This is currently called holding locks making pVirtualBox
+ * relatively unusable.
+ */
+ DECLCALLBACKMEMBER(int, pfnUninstall,(PCVBOXEXTPACKREG pThis, VBOXEXTPACK_IF_CS(IVirtualBox) *pVirtualBox));
+
+ /**
+ * Hook for doing work after the VirtualBox object is ready.
+ *
+ * @param pThis Pointer to this structure.
+ * @param pVirtualBox The VirtualBox interface.
+ */
+ DECLCALLBACKMEMBER(void, pfnVirtualBoxReady,(PCVBOXEXTPACKREG pThis, VBOXEXTPACK_IF_CS(IVirtualBox) *pVirtualBox));
+
+ /**
+ * Hook for doing work before unloading.
+ *
+ * @param pThis Pointer to this structure.
+ *
+ * @remarks The helpers are not available at this point in time.
+ * @remarks This is not called on uninstall, then pfnUninstall will be the
+ * last callback.
+ */
+ DECLCALLBACKMEMBER(void, pfnUnload,(PCVBOXEXTPACKREG pThis));
+
+ /**
+ * Hook for changing the default VM configuration upon creation.
+ *
+ * @returns VBox status code.
+ * @param pThis Pointer to this structure.
+ * @param pVirtualBox The VirtualBox interface.
+ * @param pMachine The machine interface.
+ */
+ DECLCALLBACKMEMBER(int, pfnVMCreated,(PCVBOXEXTPACKREG pThis, VBOXEXTPACK_IF_CS(IVirtualBox) *pVirtualBox,
+ VBOXEXTPACK_IF_CS(IMachine) *pMachine));
+
+ /**
+ * Query the IUnknown interface to an object in the main module.
+ *
+ * @returns IUnknown pointer (referenced) on success, NULL on failure.
+ * @param pThis Pointer to this structure.
+ * @param pObjectId Pointer to the object ID (UUID).
+ */
+ DECLCALLBACKMEMBER(void *, pfnQueryObject,(PCVBOXEXTPACKREG pThis, PCRTUUID pObjectId));
+
+ DECLR3CALLBACKMEMBER(int, pfnReserved1,(PCVBOXEXTPACKREG pThis)); /**< Reserved for minor structure revisions. */
+ DECLR3CALLBACKMEMBER(int, pfnReserved2,(PCVBOXEXTPACKREG pThis)); /**< Reserved for minor structure revisions. */
+ DECLR3CALLBACKMEMBER(int, pfnReserved3,(PCVBOXEXTPACKREG pThis)); /**< Reserved for minor structure revisions. */
+ DECLR3CALLBACKMEMBER(int, pfnReserved4,(PCVBOXEXTPACKREG pThis)); /**< Reserved for minor structure revisions. */
+ DECLR3CALLBACKMEMBER(int, pfnReserved5,(PCVBOXEXTPACKREG pThis)); /**< Reserved for minor structure revisions. */
+ DECLR3CALLBACKMEMBER(int, pfnReserved6,(PCVBOXEXTPACKREG pThis)); /**< Reserved for minor structure revisions. */
+
+ /** Reserved for minor structure revisions. */
+ uint32_t uReserved7;
+
+ /** End of structure marker (VBOXEXTPACKREG_VERSION). */
+ uint32_t u32EndMarker;
+} VBOXEXTPACKREG;
+/** Current version of the VBOXEXTPACKREG structure. */
+#define VBOXEXTPACKREG_VERSION RT_MAKE_U32(0, 3)
+
+
+/**
+ * The VBoxExtPackRegister callback function.
+ *
+ * The Main API (as in VBoxSVC) will invoke this function after loading an
+ * extension pack Main module. Its job is to do version compatibility checking
+ * and returning the extension pack registration structure.
+ *
+ * @returns VBox status code.
+ * @param pHlp Pointer to the extension pack helper function
+ * table. This is valid until the module is unloaded.
+ * @param ppReg Where to return the pointer to the registration
+ * structure containing all the hooks. This structure
+ * be valid and unchanged until the module is unloaded
+ * (i.e. use some static const data for it).
+ * @param pErrInfo Where to return extended error information.
+ */
+typedef DECLCALLBACKTYPE(int, FNVBOXEXTPACKREGISTER,(PCVBOXEXTPACKHLP pHlp, PCVBOXEXTPACKREG *ppReg, PRTERRINFO pErrInfo));
+/** Pointer to a FNVBOXEXTPACKREGISTER. */
+typedef FNVBOXEXTPACKREGISTER *PFNVBOXEXTPACKREGISTER;
+
+/** The name of the main module entry point. */
+#define VBOX_EXTPACK_MAIN_MOD_ENTRY_POINT "VBoxExtPackRegister"
+
+
+/** Pointer to the extension pack VM callback table. */
+typedef struct VBOXEXTPACKVMREG const *PCVBOXEXTPACKVMREG;
+/**
+ * Callback table returned by VBoxExtPackVMRegister.
+ *
+ * All the callbacks are called the context of a VM process.
+ *
+ * This must be valid until the extension pack main VM module is unloaded.
+ */
+typedef struct VBOXEXTPACKVMREG
+{
+ /** Interface version.
+ * This is set to VBOXEXTPACKVMREG_VERSION. */
+ uint32_t u32Version;
+ /** The VirtualBox version this extension pack was built against. */
+ uint32_t uVBoxVersion;
+ /** Translation files base name. Set to NULL if no translation files. */
+ const char *pszNlsBaseName;
+
+ /**
+ * Hook for doing work after the Console object is ready.
+ *
+ * @param pThis Pointer to this structure.
+ * @param pConsole The Console interface.
+ */
+ DECLCALLBACKMEMBER(void, pfnConsoleReady,(PCVBOXEXTPACKVMREG pThis, VBOXEXTPACK_IF_CS(IConsole) *pConsole));
+
+ /**
+ * Hook for doing work before unloading.
+ *
+ * @param pThis Pointer to this structure.
+ *
+ * @remarks The helpers are not available at this point in time.
+ */
+ DECLCALLBACKMEMBER(void, pfnUnload,(PCVBOXEXTPACKVMREG pThis));
+
+ /**
+ * Hook for configuring the VMM for a VM.
+ *
+ * @returns VBox status code.
+ * @param pThis Pointer to this structure.
+ * @param pConsole The console interface.
+ * @param pVM The cross context VM structure.
+ * @param pVMM The VMM function table.
+ */
+ DECLCALLBACKMEMBER(int, pfnVMConfigureVMM,(PCVBOXEXTPACKVMREG pThis, VBOXEXTPACK_IF_CS(IConsole) *pConsole,
+ PVM pVM, PCVMMR3VTABLE pVMM));
+
+ /**
+ * Hook for doing work right before powering on the VM.
+ *
+ * @returns VBox status code.
+ * @param pThis Pointer to this structure.
+ * @param pConsole The console interface.
+ * @param pVM The cross context VM structure.
+ * @param pVMM The VMM function table.
+ */
+ DECLCALLBACKMEMBER(int, pfnVMPowerOn,(PCVBOXEXTPACKVMREG pThis, VBOXEXTPACK_IF_CS(IConsole) *pConsole,
+ PVM pVM, PCVMMR3VTABLE pVMM));
+
+ /**
+ * Hook for doing work after powering off the VM.
+ *
+ * @param pThis Pointer to this structure.
+ * @param pConsole The console interface.
+ * @param pVM The cross context VM structure. Can be NULL.
+ * @param pVMM The VMM function table.
+ */
+ DECLCALLBACKMEMBER(void, pfnVMPowerOff,(PCVBOXEXTPACKVMREG pThis, VBOXEXTPACK_IF_CS(IConsole) *pConsole,
+ PVM pVM, PCVMMR3VTABLE pVMM));
+
+ /**
+ * Query the IUnknown interface to an object in the main VM module.
+ *
+ * @returns IUnknown pointer (referenced) on success, NULL on failure.
+ * @param pThis Pointer to this structure.
+ * @param pObjectId Pointer to the object ID (UUID).
+ */
+ DECLCALLBACKMEMBER(void *, pfnQueryObject,(PCVBOXEXTPACKVMREG pThis, PCRTUUID pObjectId));
+
+ DECLR3CALLBACKMEMBER(int, pfnReserved1,(PCVBOXEXTPACKVMREG pThis)); /**< Reserved for minor structure revisions. */
+ DECLR3CALLBACKMEMBER(int, pfnReserved2,(PCVBOXEXTPACKVMREG pThis)); /**< Reserved for minor structure revisions. */
+ DECLR3CALLBACKMEMBER(int, pfnReserved3,(PCVBOXEXTPACKVMREG pThis)); /**< Reserved for minor structure revisions. */
+ DECLR3CALLBACKMEMBER(int, pfnReserved4,(PCVBOXEXTPACKVMREG pThis)); /**< Reserved for minor structure revisions. */
+ DECLR3CALLBACKMEMBER(int, pfnReserved5,(PCVBOXEXTPACKVMREG pThis)); /**< Reserved for minor structure revisions. */
+ DECLR3CALLBACKMEMBER(int, pfnReserved6,(PCVBOXEXTPACKVMREG pThis)); /**< Reserved for minor structure revisions. */
+
+ /** Reserved for minor structure revisions. */
+ uint32_t uReserved7;
+
+ /** End of structure marker (VBOXEXTPACKVMREG_VERSION). */
+ uint32_t u32EndMarker;
+} VBOXEXTPACKVMREG;
+/** Current version of the VBOXEXTPACKVMREG structure. */
+#define VBOXEXTPACKVMREG_VERSION RT_MAKE_U32(1, 0)
+
+
+/**
+ * The VBoxExtPackVMRegister callback function.
+ *
+ * The Main API (in a VM process) will invoke this function after loading an
+ * extension pack VM module. Its job is to do version compatibility checking
+ * and returning the extension pack registration structure for a VM.
+ *
+ * @returns VBox status code.
+ * @param pHlp Pointer to the extension pack helper function
+ * table. This is valid until the module is unloaded.
+ * @param ppReg Where to return the pointer to the registration
+ * structure containing all the hooks. This structure
+ * be valid and unchanged until the module is unloaded
+ * (i.e. use some static const data for it).
+ * @param pErrInfo Where to return extended error information.
+ */
+typedef DECLCALLBACKTYPE(int, FNVBOXEXTPACKVMREGISTER,(PCVBOXEXTPACKHLP pHlp, PCVBOXEXTPACKVMREG *ppReg, PRTERRINFO pErrInfo));
+/** Pointer to a FNVBOXEXTPACKVMREGISTER. */
+typedef FNVBOXEXTPACKVMREGISTER *PFNVBOXEXTPACKVMREGISTER;
+
+/** The name of the main VM module entry point. */
+#define VBOX_EXTPACK_MAIN_VM_MOD_ENTRY_POINT "VBoxExtPackVMRegister"
+
+
+/**
+ * Checks if extension pack interface version is compatible.
+ *
+ * @returns true if the do, false if they don't.
+ * @param u32Provider The provider version.
+ * @param u32User The user version.
+ */
+#define VBOXEXTPACK_IS_VER_COMPAT(u32Provider, u32User) \
+ ( VBOXEXTPACK_IS_MAJOR_VER_EQUAL(u32Provider, u32User) \
+ && (int32_t)RT_LOWORD(u32Provider) >= (int32_t)RT_LOWORD(u32User) ) /* stupid casts to shut up gcc */
+
+/**
+ * Check if two extension pack interface versions has the same major version.
+ *
+ * @returns true if the do, false if they don't.
+ * @param u32Ver1 The first version number.
+ * @param u32Ver2 The second version number.
+ */
+#define VBOXEXTPACK_IS_MAJOR_VER_EQUAL(u32Ver1, u32Ver2) (RT_HIWORD(u32Ver1) == RT_HIWORD(u32Ver2))
+
+#endif /* !VBOX_INCLUDED_ExtPack_ExtPack_h */
+
diff --git a/include/VBox/Graphics/HGSMI.h b/include/VBox/Graphics/HGSMI.h
new file mode 100644
index 00000000..da485add
--- /dev/null
+++ b/include/VBox/Graphics/HGSMI.h
@@ -0,0 +1,251 @@
+/* $Id: HGSMI.h $ */
+/** @file
+ * VBox Host Guest Shared Memory Interface (HGSMI) - Host/Guest shared part.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef VBOX_INCLUDED_Graphics_HGSMI_h
+#define VBOX_INCLUDED_Graphics_HGSMI_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include "VBoxVideoIPRT.h"
+
+#include "HGSMIDefs.h"
+#include "HGSMIChannels.h"
+#include "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.
+ *
+ * @returns stuff
+ * @param pvHandler Value specified when registring.
+ * @param u16ChannelInfo Command code.
+ * @param pvBuffer HGSMI buffer with command data. This is shared with
+ * the guest. Consider untrusted and volatile!
+ * @param cbBuffer Size of command data.
+ * @thread EMT on the host side.
+ */
+typedef DECLCALLBACKTYPE(int, FNHGSMICHANNELHANDLER,(void *pvHandler, uint16_t u16ChannelInfo,
+ RT_UNTRUSTED_VOLATILE_HSTGST void *pvBuffer, HGSMISIZE cbBuffer));
+/** Pointer to a channel handler callback. */
+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
+{
+ /** Channel handlers indexed by the channel id.
+ * The array is accessed under the instance lock. */
+ HGSMICHANNEL Channels[HGSMI_NUMBER_OF_CHANNELS];
+} HGSMICHANNELINFO;
+
+
+RT_C_DECLS_BEGIN
+
+DECLINLINE(HGSMIBUFFERHEADER *) HGSMIBufferHeaderFromPtr(void RT_UNTRUSTED_VOLATILE_HSTGST *pvBuffer)
+{
+ return (HGSMIBUFFERHEADER *)pvBuffer;
+}
+
+DECLINLINE(uint8_t RT_UNTRUSTED_VOLATILE_HSTGST *) HGSMIBufferDataFromPtr(void RT_UNTRUSTED_VOLATILE_HSTGST *pvBuffer)
+{
+ return (uint8_t RT_UNTRUSTED_VOLATILE_HSTGST *)pvBuffer + sizeof(HGSMIBUFFERHEADER);
+}
+
+DECLINLINE(HGSMIBUFFERTAIL RT_UNTRUSTED_VOLATILE_HSTGST *)
+HGSMIBufferTailFromPtr(void RT_UNTRUSTED_VOLATILE_HSTGST *pvBuffer, uint32_t u32DataSize)
+{
+ return (HGSMIBUFFERTAIL RT_UNTRUSTED_VOLATILE_HSTGST *)(HGSMIBufferDataFromPtr(pvBuffer) + u32DataSize);
+}
+
+DECLINLINE(HGSMISIZE) HGSMIBufferMinimumSize(void)
+{
+ return sizeof(HGSMIBUFFERHEADER) + sizeof(HGSMIBUFFERTAIL);
+}
+
+DECLINLINE(HGSMIBUFFERHEADER RT_UNTRUSTED_VOLATILE_HSTGST *) HGSMIBufferHeaderFromData(const void RT_UNTRUSTED_VOLATILE_HSTGST *pvData)
+{
+ return (HGSMIBUFFERHEADER RT_UNTRUSTED_VOLATILE_HSTGST *)((uint8_t *)pvData - sizeof(HGSMIBUFFERHEADER));
+}
+
+DECLINLINE(HGSMISIZE) HGSMIBufferRequiredSize(uint32_t u32DataSize)
+{
+ return HGSMIBufferMinimumSize() + u32DataSize;
+}
+
+DECLINLINE(HGSMIOFFSET) HGSMIPointerToOffset(const HGSMIAREA *pArea, const void RT_UNTRUSTED_VOLATILE_HSTGST *pv)
+{
+ return pArea->offBase + (HGSMIOFFSET)((uint8_t *)pv - pArea->pu8Base);
+}
+
+DECLINLINE(void RT_UNTRUSTED_VOLATILE_HSTGST *) HGSMIOffsetToPointer(const HGSMIAREA *pArea, HGSMIOFFSET offBuffer)
+{
+ return pArea->pu8Base + (offBuffer - pArea->offBase);
+}
+
+DECLINLINE(uint8_t RT_UNTRUSTED_VOLATILE_HSTGST*) HGSMIBufferDataFromOffset(const HGSMIAREA *pArea, HGSMIOFFSET offBuffer)
+{
+ void RT_UNTRUSTED_VOLATILE_HSTGST *pvBuffer = HGSMIOffsetToPointer(pArea, offBuffer);
+ return HGSMIBufferDataFromPtr(pvBuffer);
+}
+
+DECLINLINE(HGSMIOFFSET) HGSMIBufferOffsetFromData(const HGSMIAREA *pArea, void RT_UNTRUSTED_VOLATILE_HSTGST *pvData)
+{
+ HGSMIBUFFERHEADER RT_UNTRUSTED_VOLATILE_HSTGST *pHeader = HGSMIBufferHeaderFromData(pvData);
+ return HGSMIPointerToOffset(pArea, pHeader);
+}
+
+DECLINLINE(uint8_t RT_UNTRUSTED_VOLATILE_HSTGST *) HGSMIBufferDataAndChInfoFromOffset(const HGSMIAREA *pArea,
+ HGSMIOFFSET offBuffer,
+ uint16_t *pu16ChannelInfo)
+{
+ HGSMIBUFFERHEADER RT_UNTRUSTED_VOLATILE_HSTGST *pHeader =
+ (HGSMIBUFFERHEADER RT_UNTRUSTED_VOLATILE_HSTGST *)HGSMIOffsetToPointer(pArea, offBuffer);
+ *pu16ChannelInfo = pHeader->u16ChannelInfo;
+ return HGSMIBufferDataFromPtr(pHeader);
+}
+
+uint32_t HGSMIChecksum(HGSMIOFFSET offBuffer, const HGSMIBUFFERHEADER RT_UNTRUSTED_VOLATILE_HSTGST *pHeader,
+ const HGSMIBUFFERTAIL RT_UNTRUSTED_VOLATILE_HSTGST *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 RT_UNTRUSTED_VOLATILE_HSTGST *pv)
+{
+ return (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 RT_UNTRUSTED_VOLATILE_HSTGST *HGSMIHeapBufferAlloc(HGSMIHEAP *pHeap, HGSMISIZE cbBuffer);
+void HGSMIHeapBufferFree(HGSMIHEAP *pHeap, void RT_UNTRUSTED_VOLATILE_HSTGST *pvBuf);
+
+void RT_UNTRUSTED_VOLATILE_HOST *HGSMIHeapAlloc(HGSMIHEAP *pHeap,
+ HGSMISIZE cbData,
+ uint8_t u8Channel,
+ uint16_t u16ChannelInfo);
+
+void HGSMIHeapFree(HGSMIHEAP *pHeap, void RT_UNTRUSTED_VOLATILE_HSTGST *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 RT_UNTRUSTED_VOLATILE_HOST *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_INCLUDED_Graphics_HGSMI_h */
+
diff --git a/include/VBox/Graphics/HGSMIBase.h b/include/VBox/Graphics/HGSMIBase.h
new file mode 100644
index 00000000..aad0bfbe
--- /dev/null
+++ b/include/VBox/Graphics/HGSMIBase.h
@@ -0,0 +1,60 @@
+/* $Id: HGSMIBase.h $ */
+/** @file
+ * VBox Host Guest Shared Memory Interface (HGSMI) - buffer management.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef VBOX_INCLUDED_Graphics_HGSMIBase_h
+#define VBOX_INCLUDED_Graphics_HGSMIBase_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include "HGSMI.h"
+#include "HGSMIContext.h"
+#include "VBoxVideoIPRT.h"
+
+RT_C_DECLS_BEGIN
+
+/** @name Base HGSMI Buffer APIs
+ * @{ */
+
+/** Acknowlege an IRQ. */
+DECLINLINE(void) VBoxHGSMIClearIrq(PHGSMIHOSTCOMMANDCONTEXT pCtx)
+{
+ VBVO_PORT_WRITE_U32(pCtx->port, HGSMIOFFSET_VOID);
+}
+
+DECLHIDDEN(void RT_UNTRUSTED_VOLATILE_HOST *) VBoxHGSMIBufferAlloc(PHGSMIGUESTCOMMANDCONTEXT pCtx, HGSMISIZE cbData,
+ uint8_t u8Ch, uint16_t u16Op);
+DECLHIDDEN(void) VBoxHGSMIBufferFree(PHGSMIGUESTCOMMANDCONTEXT pCtx, void RT_UNTRUSTED_VOLATILE_HOST *pvBuffer);
+DECLHIDDEN(int) VBoxHGSMIBufferSubmit(PHGSMIGUESTCOMMANDCONTEXT pCtx, void RT_UNTRUSTED_VOLATILE_HOST *pvBuffer);
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !VBOX_INCLUDED_Graphics_HGSMIBase_h */
diff --git a/include/VBox/Graphics/HGSMIChSetup.h b/include/VBox/Graphics/HGSMIChSetup.h
new file mode 100644
index 00000000..0e11b580
--- /dev/null
+++ b/include/VBox/Graphics/HGSMIChSetup.h
@@ -0,0 +1,88 @@
+/* $Id: HGSMIChSetup.h $ */
+/** @file
+ * VBox Host Guest Shared Memory Interface (HGSMI), Host/Guest shared part.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef VBOX_INCLUDED_Graphics_HGSMIChSetup_h
+#define VBOX_INCLUDED_Graphics_HGSMIChSetup_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include "HGSMIDefs.h"
+
+/* HGSMI setup and configuration channel commands and data structures. */
+/*
+ * Tell the host the location of hgsmi_host_flags 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.
+ */
+#define HGSMI_CC_HOST_FLAGS_LOCATION 0
+
+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(0x01)
+/* IRQ is fired, should be accessed under VGAState::lock only */
+#define HGSMIHOSTFLAGS_IRQ UINT32_C(0x02)
+#ifdef VBOX_WITH_WDDM
+/* one or more guest commands is completed, should be accessed under FIFO lock only */
+# define HGSMIHOSTFLAGS_GCOMMAND_COMPLETED UINT32_C(0x04)
+#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 completing
+ * HGSMI 3D and Video Accel respectively, EMT thread when dealing with
+ * HGSMI command processing, etc.
+ * Besides settings/cleaning flags atomically, some flags have their
+ * own special sync restrictions, see comments for flags above.
+ */
+ volatile uint32_t u32HostFlags;
+ uint32_t au32Reserved[3];
+} HGSMIHOSTFLAGS;
+AssertCompileSize(HGSMIHOSTFLAGS, 16);
+
+#endif /* !VBOX_INCLUDED_Graphics_HGSMIChSetup_h */
diff --git a/include/VBox/Graphics/HGSMIChannels.h b/include/VBox/Graphics/HGSMIChannels.h
new file mode 100644
index 00000000..c957040b
--- /dev/null
+++ b/include/VBox/Graphics/HGSMIChannels.h
@@ -0,0 +1,77 @@
+/* $Id: HGSMIChannels.h $ */
+/** @file
+ *
+ * VBox Host Guest Shared Memory Interface (HGSMI).
+ * Host/Guest shared part.
+ * Channel identifiers.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef VBOX_INCLUDED_Graphics_HGSMIChannels_h
+#define VBOX_INCLUDED_Graphics_HGSMIChannels_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+
+/*
+ * 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. */
+/* A reserved channel value */
+#define HGSMI_CH_RESERVED 0x00
+/* HGCMI: setup and configuration */
+#define HGSMI_CH_HGSMI 0x01
+/* Graphics: VBVA */
+#define HGSMI_CH_VBVA 0x02
+/* Graphics: Seamless with a single guest region */
+#define HGSMI_CH_SEAMLESS 0x03
+/* Graphics: Seamless with separate host windows */
+#define HGSMI_CH_SEAMLESS2 0x04
+/* Graphics: OpenGL HW acceleration */
+#define HGSMI_CH_OPENGL 0x05
+
+
+/* Dynamically allocated channel identifiers. */
+/* The first channel index to be used for string mappings (inclusive) */
+#define HGSMI_CH_STRING_FIRST 0x20
+/* The last channel index for string mappings (inclusive) */
+#define HGSMI_CH_STRING_LAST 0xff
+
+
+/* Check whether the channel identifier is allocated for a dynamic channel */
+#define HGSMI_IS_DYNAMIC_CHANNEL(_channel) (((uint8_t)(_channel) & 0xE0) != 0)
+
+
+#endif /* !VBOX_INCLUDED_Graphics_HGSMIChannels_h */
diff --git a/include/VBox/Graphics/HGSMIContext.h b/include/VBox/Graphics/HGSMIContext.h
new file mode 100644
index 00000000..23e810c0
--- /dev/null
+++ b/include/VBox/Graphics/HGSMIContext.h
@@ -0,0 +1,114 @@
+/* $Id: HGSMIContext.h $ */
+/** @file
+ * VBox Host Guest Shared Memory Interface (HGSMI) - command contexts.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef VBOX_INCLUDED_Graphics_HGSMIContext_h
+#define VBOX_INCLUDED_Graphics_HGSMIContext_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include "HGSMI.h"
+#include "HGSMIChSetup.h"
+#include "VBoxVideoIPRT.h"
+
+#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;
+
+/** @name HGSMI context initialisation APIs.
+ * @{ */
+
+/** @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) VBoxHGSMISetupHostContext(PHGSMIHOSTCOMMANDCONTEXT pCtx,
+ void *pvBaseMapping,
+ uint32_t offHostFlags,
+ void *pvHostAreaMapping,
+ uint32_t offVRAMHostArea,
+ uint32_t cbHostArea);
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !VBOX_INCLUDED_Graphics_HGSMIContext_h */
+
diff --git a/include/VBox/Graphics/HGSMIDefs.h b/include/VBox/Graphics/HGSMIDefs.h
new file mode 100644
index 00000000..adbceafe
--- /dev/null
+++ b/include/VBox/Graphics/HGSMIDefs.h
@@ -0,0 +1,128 @@
+/* $Id: HGSMIDefs.h $ */
+/** @file
+ * VBox Host Guest Shared Memory Interface (HGSMI) - shared part - types and defines.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef VBOX_INCLUDED_Graphics_HGSMIDefs_h
+#define VBOX_INCLUDED_Graphics_HGSMIDefs_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include "VBoxVideoIPRT.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) /** @todo not necessary. use AssertCompileSize instead. */
+/* 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_INCLUDED_Graphics_HGSMIDefs_h */
+
diff --git a/include/VBox/Graphics/HGSMIHostCmd.h b/include/VBox/Graphics/HGSMIHostCmd.h
new file mode 100644
index 00000000..9c8b0b9e
--- /dev/null
+++ b/include/VBox/Graphics/HGSMIHostCmd.h
@@ -0,0 +1,59 @@
+/* $Id: HGSMIHostCmd.h $ */
+/** @file
+ * VBox Host Guest Shared Memory Interface (HGSMI) - buffer management.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_Graphics_HGSMIHostCmd_h
+#define VBOX_INCLUDED_Graphics_HGSMIHostCmd_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include "HGSMI.h"
+#include "HGSMIContext.h"
+#include "VBoxVideoIPRT.h"
+
+RT_C_DECLS_BEGIN
+
+/** @name Base HGSMI host command APIs.
+ * @{ */
+
+DECLHIDDEN(void) VBoxHGSMIHostCmdComplete(PHGSMIHOSTCOMMANDCONTEXT pCtx, void RT_UNTRUSTED_VOLATILE_HOST *pvMem);
+DECLHIDDEN(void) VBoxHGSMIProcessHostQueue(PHGSMIHOSTCOMMANDCONTEXT pCtx);
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !VBOX_INCLUDED_Graphics_HGSMIHostCmd_h */
diff --git a/include/VBox/Graphics/HGSMIMemAlloc.h b/include/VBox/Graphics/HGSMIMemAlloc.h
new file mode 100644
index 00000000..a837dc34
--- /dev/null
+++ b/include/VBox/Graphics/HGSMIMemAlloc.h
@@ -0,0 +1,113 @@
+/* $Id: HGSMIMemAlloc.h $ */
+/** @file
+ * VBox Host Guest Shared Memory Interface (HGSMI) - Memory allocator.
+ */
+
+/*
+ * Copyright (C) 2014-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_Graphics_HGSMIMemAlloc_h
+#define VBOX_INCLUDED_Graphics_HGSMIMemAlloc_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include "HGSMIDefs.h"
+#include "VBoxVideoIPRT.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 RT_UNTRUSTED_VOLATILE_HSTGST *HGSMIMAAlloc(HGSMIMADATA *pMA, HGSMISIZE cb);
+void HGSMIMAFree(HGSMIMADATA *pMA, void RT_UNTRUSTED_VOLATILE_GUEST *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;
+#ifdef HGSMI_STRICT
+ Assert(HGSMIMAOrder2Size(order) == cb);
+#endif
+ return order;
+}
+
+RT_C_DECLS_END
+
+#endif /* !VBOX_INCLUDED_Graphics_HGSMIMemAlloc_h */
diff --git a/include/VBox/Graphics/Makefile.kup b/include/VBox/Graphics/Makefile.kup
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/include/VBox/Graphics/Makefile.kup
diff --git a/include/VBox/Graphics/VBoxUhgsmi.h b/include/VBox/Graphics/VBoxUhgsmi.h
new file mode 100644
index 00000000..8f1328e2
--- /dev/null
+++ b/include/VBox/Graphics/VBoxUhgsmi.h
@@ -0,0 +1,145 @@
+/* $Id: VBoxUhgsmi.h $ */
+/** @file
+ * Document me, pretty please.
+ */
+
+/*
+ * Copyright (C) 2010-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_Graphics_VBoxUhgsmi_h
+#define VBOX_INCLUDED_Graphics_VBoxUhgsmi_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+
+typedef struct VBOXUHGSMI *PVBOXUHGSMI;
+
+typedef struct VBOXUHGSMI_BUFFER *PVBOXUHGSMI_BUFFER;
+
+typedef union VBOXUHGSMI_BUFFER_TYPE_FLAGS
+{
+ uint32_t Value;
+ struct
+ {
+ uint32_t fCommand : 1;
+ uint32_t Reserved : 31;
+ } s;
+} VBOXUHGSMI_BUFFER_TYPE_FLAGS;
+
+typedef union VBOXUHGSMI_BUFFER_LOCK_FLAGS
+{
+ uint32_t Value;
+ struct
+ {
+ uint32_t fReadOnly : 1;
+ uint32_t fWriteOnly : 1;
+ uint32_t fDonotWait : 1;
+ uint32_t fDiscard : 1;
+ uint32_t fLockEntire : 1;
+ uint32_t Reserved : 27;
+ } s;
+} VBOXUHGSMI_BUFFER_LOCK_FLAGS;
+
+typedef union VBOXUHGSMI_BUFFER_SUBMIT_FLAGS
+{
+ uint32_t Value;
+ struct
+ {
+ uint32_t fHostReadOnly : 1;
+ uint32_t fHostWriteOnly : 1;
+ uint32_t fDoNotRetire : 1; /**< the buffer will be used in a subsequent command */
+ uint32_t fEntireBuffer : 1;
+ uint32_t Reserved : 28;
+ } s;
+} VBOXUHGSMI_BUFFER_SUBMIT_FLAGS, *PVBOXUHGSMI_BUFFER_SUBMIT_FLAGS;
+
+/* the caller can specify NULL as a hSynch and specify a valid enmSynchType to make UHGSMI create a proper object itself,
+ * */
+typedef DECLCALLBACKTYPE(int, FNVBOXUHGSMI_BUFFER_CREATE,(PVBOXUHGSMI pHgsmi, uint32_t cbBuf, VBOXUHGSMI_BUFFER_TYPE_FLAGS fType,
+ PVBOXUHGSMI_BUFFER* ppBuf));
+typedef FNVBOXUHGSMI_BUFFER_CREATE *PFNVBOXUHGSMI_BUFFER_CREATE;
+
+typedef struct VBOXUHGSMI_BUFFER_SUBMIT
+{
+ PVBOXUHGSMI_BUFFER pBuf;
+ uint32_t offData;
+ uint32_t cbData;
+ VBOXUHGSMI_BUFFER_SUBMIT_FLAGS fFlags;
+} VBOXUHGSMI_BUFFER_SUBMIT, *PVBOXUHGSMI_BUFFER_SUBMIT;
+
+typedef DECLCALLBACKTYPE(int, FNVBOXUHGSMI_BUFFER_SUBMIT,(PVBOXUHGSMI pHgsmi, PVBOXUHGSMI_BUFFER_SUBMIT aBuffers,
+ uint32_t cBuffers));
+typedef FNVBOXUHGSMI_BUFFER_SUBMIT *PFNVBOXUHGSMI_BUFFER_SUBMIT;
+
+typedef DECLCALLBACKTYPE(int, FNVBOXUHGSMI_BUFFER_DESTROY,(PVBOXUHGSMI_BUFFER pBuf));
+typedef FNVBOXUHGSMI_BUFFER_DESTROY *PFNVBOXUHGSMI_BUFFER_DESTROY;
+
+typedef DECLCALLBACKTYPE(int, FNVBOXUHGSMI_BUFFER_LOCK,(PVBOXUHGSMI_BUFFER pBuf, uint32_t offLock, uint32_t cbLock,
+ VBOXUHGSMI_BUFFER_LOCK_FLAGS fFlags, void**pvLock));
+typedef FNVBOXUHGSMI_BUFFER_LOCK *PFNVBOXUHGSMI_BUFFER_LOCK;
+
+typedef DECLCALLBACKTYPE(int, FNVBOXUHGSMI_BUFFER_UNLOCK,(PVBOXUHGSMI_BUFFER pBuf));
+typedef FNVBOXUHGSMI_BUFFER_UNLOCK *PFNVBOXUHGSMI_BUFFER_UNLOCK;
+
+typedef struct VBOXUHGSMI
+{
+ PFNVBOXUHGSMI_BUFFER_CREATE pfnBufferCreate;
+ PFNVBOXUHGSMI_BUFFER_SUBMIT pfnBufferSubmit;
+ /** User custom data. */
+ void *pvUserData;
+} VBOXUHGSMI;
+
+typedef struct VBOXUHGSMI_BUFFER
+{
+ PFNVBOXUHGSMI_BUFFER_LOCK pfnLock;
+ PFNVBOXUHGSMI_BUFFER_UNLOCK pfnUnlock;
+ PFNVBOXUHGSMI_BUFFER_DESTROY pfnDestroy;
+
+ /* r/o data added for ease of access and simplicity
+ * modifying it leads to unpredictable behavior */
+ VBOXUHGSMI_BUFFER_TYPE_FLAGS fType;
+ uint32_t cbBuffer;
+ /** User custom data. */
+ void *pvUserData;
+} VBOXUHGSMI_BUFFER;
+
+#define VBoxUhgsmiBufferCreate(_pUhgsmi, _cbBuf, _fType, _ppBuf) ((_pUhgsmi)->pfnBufferCreate(_pUhgsmi, _cbBuf, _fType, _ppBuf))
+#define VBoxUhgsmiBufferSubmit(_pUhgsmi, _aBuffers, _cBuffers) ((_pUhgsmi)->pfnBufferSubmit(_pUhgsmi, _aBuffers, _cBuffers))
+
+#define VBoxUhgsmiBufferLock(_pBuf, _offLock, _cbLock, _fFlags, _pvLock) ((_pBuf)->pfnLock(_pBuf, _offLock, _cbLock, _fFlags, _pvLock))
+#define VBoxUhgsmiBufferUnlock(_pBuf) ((_pBuf)->pfnUnlock(_pBuf))
+#define VBoxUhgsmiBufferDestroy(_pBuf) ((_pBuf)->pfnDestroy(_pBuf))
+
+#endif /* !VBOX_INCLUDED_Graphics_VBoxUhgsmi_h */
+
diff --git a/include/VBox/Graphics/VBoxVideo.h b/include/VBox/Graphics/VBoxVideo.h
new file mode 100644
index 00000000..ca779315
--- /dev/null
+++ b/include/VBox/Graphics/VBoxVideo.h
@@ -0,0 +1,1490 @@
+/* $Id: VBoxVideo.h $ */
+/** @file
+ * VirtualBox Video interface.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef VBOX_INCLUDED_Graphics_VBoxVideo_h
+#define VBOX_INCLUDED_Graphics_VBoxVideo_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include "VBoxVideoIPRT.h"
+
+/* 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
+
+/*
+ * 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
+
+/**
+ * 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);
+
+/* 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 UINT32_C(0x00010000)
+/** asynch completion is performed by issuing the event */
+#define VBOXVHWACMD_FLAG_GH_ASYNCH_EVENT UINT32_C(0x00000001)
+/** issue interrupt on asynch completion */
+#define VBOXVHWACMD_FLAG_GH_ASYNCH_IRQ UINT32_C(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 UINT32_C(0x00000004)
+/** the host has copied the VBOXVHWACMD_FLAG_GH_ASYNCH_NOCOMPLETION command and returned it to the guest */
+#define VBOXVHWACMD_FLAG_HG_ASYNCH_RETURNED UINT32_C(0x00020000)
+/** this is the host->host cmd, i.e. a configuration command posted by the host to the framebuffer */
+#define VBOXVHWACMD_FLAG_HH_CMD UINT32_C(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(a_cbBody) (VBOXVHWACMD_HEADSIZE() + (a_cbBody))
+#define VBOXVHWACMD_SIZE(a_tTypeCmd) (VBOXVHWACMD_SIZE_FROMBODYSIZE(sizeof(a_tTypeCmd)))
+typedef unsigned int VBOXVHWACMD_LENGTH;
+typedef uint64_t VBOXVHWA_SURFHANDLE;
+#define VBOXVHWA_SURFHANDLE_INVALID UINT64_C(0)
+#define VBOXVHWACMD_BODY(a_pHdr, a_TypeBody) ( (a_TypeBody RT_UNTRUSTED_VOLATILE_HSTGST *)&(a_pHdr)->body[0] )
+#if !defined(IN_GUEST) && defined(IN_RING3)
+# define VBOXVHWACMD_BODY_HOST_HEAP(a_pHdr, a_TypeBody) ( (a_TypeBody *)&(a_pHdr)->body[0] )
+#endif
+#define VBOXVHWACMD_HEAD(a_pBody)\
+ ( (VBOXVHWACMD RT_UNTRUSTED_VOLATILE_HSTGST *)((uint8_t *)(a_pBody) - 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_UOFFSETOF_DYN(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 DECLCALLBACKTYPE(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
+/** Enables or disables VBVA. Enabling VBVA without disabling it before
+ * causes a complete screen update. */
+#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(a_cb) (sizeof(VBVAHOSTCMD) + (a_cb))
+#define VBVAHOSTCMD_BODY(a_pCmd, a_TypeBody) ((a_TypeBody RT_UNTRUSTED_VOLATILE_HSTGST *)&(a_pCmd)->body[0])
+#define VBVAHOSTCMD_HDR(a_pBody) \
+ ( (VBVAHOSTCMD RT_UNTRUSTED_VOLATILE_HSTGST *)( (uint8_t *)(a_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;
+
+/** Reserved for historical reasons. */
+#define VBOX_VBVA_CURSOR_CAPABILITY_RESERVED0 RT_BIT(0)
+/** Guest cursor capability: can the host show a hardware cursor at the host
+ * pointer location? */
+#define VBOX_VBVA_CURSOR_CAPABILITY_HARDWARE RT_BIT(1)
+/** Reserved for historical reasons. */
+#define VBOX_VBVA_CURSOR_CAPABILITY_RESERVED2 RT_BIT(2)
+/** Reserved for historical reasons. Must always be unset. */
+#define VBOX_VBVA_CURSOR_CAPABILITY_RESERVED3 RT_BIT(3)
+/** Reserved for historical reasons. */
+#define VBOX_VBVA_CURSOR_CAPABILITY_RESERVED4 RT_BIT(4)
+/** Reserved for historical reasons. */
+#define VBOX_VBVA_CURSOR_CAPABILITY_RESERVED5 RT_BIT(5)
+
+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 using width, height, etc values from the VBVAINFOSCREEN request. */
+#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;
+
+/** @name VBVAMOUSEPOINTERSHAPE::fu32Flags
+ * @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)
+/** @} */
+
+/* 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, particularly
+ * when the cursor is captured and the guest does not support switching to a
+ * software cursor. After every mode switch the guest must signal that it
+ * supports sending position information by sending an event with
+ * @a fReportPosition set to false.
+ * @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 RT_UNTRUSTED_VOLATILE_GUEST *)
+VBoxSHGSMIBufferData(const VBOXSHGSMIHEADER RT_UNTRUSTED_VOLATILE_GUEST *pHeader)
+{
+ return (uint8_t RT_UNTRUSTED_VOLATILE_GUEST *)pHeader + sizeof(VBOXSHGSMIHEADER);
+}
+
+#define VBoxSHGSMIBufferHeaderSize() (sizeof(VBOXSHGSMIHEADER))
+
+DECLINLINE(VBOXSHGSMIHEADER RT_UNTRUSTED_VOLATILE_GUEST *) VBoxSHGSMIBufferHeader(const void RT_UNTRUSTED_VOLATILE_GUEST *pvData)
+{
+ return (VBOXSHGSMIHEADER RT_UNTRUSTED_VOLATILE_GUEST *)((uintptr_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_END
+} VBOXVDMA_CTL_TYPE;
+
+typedef struct VBOXVDMA_CTL
+{
+ VBOXVDMA_CTL_TYPE enmCtl;
+ uint32_t u32Offset;
+ int32_t i32Result;
+} VBOXVDMA_CTL;
+
+/* 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(a_pCmd, a_TailType) \
+ ( (a_TailType RT_UNTRUSTED_VOLATILE_HSTGST *)( ((uint8_t*)(a_pCmd)) + sizeof(VBOXVDMACBUF_DR)) )
+#define VBOXVDMACBUF_DR_FROM_TAIL(a_pCmd) \
+ ( (VBOXVDMACBUF_DR RT_UNTRUSTED_VOLATILE_HSTGST *)( ((uint8_t*)(a_pCmd)) - sizeof(VBOXVDMACBUF_DR)) )
+
+typedef struct VBOXVDMACMD
+{
+ VBOXVDMACMD_TYPE enmType;
+ uint32_t u32CmdSpecific;
+} VBOXVDMACMD;
+
+#define VBOXVDMACMD_HEADER_SIZE() sizeof(VBOXVDMACMD)
+#define VBOXVDMACMD_SIZE_FROMBODYSIZE(_s) ((uint32_t)(VBOXVDMACMD_HEADER_SIZE() + (_s)))
+#define VBOXVDMACMD_SIZE(_t) (VBOXVDMACMD_SIZE_FROMBODYSIZE(sizeof(_t)))
+#define VBOXVDMACMD_BODY(a_pCmd, a_TypeBody) \
+ ( (a_TypeBody RT_UNTRUSTED_VOLATILE_HSTGST *)( ((uint8_t *)(a_pCmd)) + VBOXVDMACMD_HEADER_SIZE()) )
+#define VBOXVDMACMD_BODY_SIZE(_s) ( (_s) - VBOXVDMACMD_HEADER_SIZE() )
+#define VBOXVDMACMD_FROM_BODY(a_pBody) \
+ ( (VBOXVDMACMD RT_UNTRUSTED_VOLATILE_HSTGST *)( ((uint8_t *)(a_pBody)) - VBOXVDMACMD_HEADER_SIZE()) )
+#define VBOXVDMACMD_BODY_FIELD_OFFSET(_ot, _t, _f) ( (_ot)(uintptr_t)( VBOXVDMACMD_BODY(0, uint8_t) + RT_UOFFSETOF_DYN(_t, _f) ) )
+
+# pragma pack()
+#endif /* #ifdef VBOX_WITH_VDMA */
+
+
+#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;
+
+#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)]
+
+#endif /* !VBOX_INCLUDED_Graphics_VBoxVideo_h */
+
diff --git a/include/VBox/Graphics/VBoxVideo3D.h b/include/VBox/Graphics/VBoxVideo3D.h
new file mode 100644
index 00000000..b1545d6f
--- /dev/null
+++ b/include/VBox/Graphics/VBoxVideo3D.h
@@ -0,0 +1,186 @@
+/* $Id: VBoxVideo3D.h $ */
+/** @file
+ * VirtualBox 3D common tooling
+ */
+
+/*
+ * Copyright (C) 2011-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_Graphics_VBoxVideo3D_h
+#define VBOX_INCLUDED_Graphics_VBoxVideo3D_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cdefs.h>
+#include <iprt/asm.h>
+#ifndef VBoxTlsRefGetImpl
+# ifdef VBoxTlsRefSetImpl
+# error "VBoxTlsRefSetImpl is defined, unexpected!"
+# endif
+# include <iprt/thread.h>
+# define VBoxTlsRefGetImpl(_tls) (RTTlsGet((RTTLS)(_tls)))
+# define VBoxTlsRefSetImpl(_tls, _val) (RTTlsSet((RTTLS)(_tls), (_val)))
+#else
+# ifndef VBoxTlsRefSetImpl
+# error "VBoxTlsRefSetImpl is NOT defined, unexpected!"
+# endif
+#endif
+
+#ifndef VBoxTlsRefAssertImpl
+# define VBoxTlsRefAssertImpl(_a) do {} while (0)
+#endif
+
+typedef DECLCALLBACKTYPE(void, FNVBOXTLSREFDTOR,(void *));
+typedef FNVBOXTLSREFDTOR *PFNVBOXTLSREFDTOR;
+
+typedef enum {
+ VBOXTLSREFDATA_STATE_UNDEFINED = 0,
+ VBOXTLSREFDATA_STATE_INITIALIZED,
+ VBOXTLSREFDATA_STATE_TOBE_DESTROYED,
+ VBOXTLSREFDATA_STATE_DESTROYING,
+ VBOXTLSREFDATA_STATE_32BIT_HACK = 0x7fffffff
+} VBOXTLSREFDATA_STATE;
+
+#define VBOXTLSREFDATA \
+ volatile int32_t cTlsRefs; \
+ VBOXTLSREFDATA_STATE enmTlsRefState; \
+ PFNVBOXTLSREFDTOR pfnTlsRefDtor; \
+
+struct VBOXTLSREFDATA_DUMMY
+{
+ VBOXTLSREFDATA
+};
+
+#define VBOXTLSREFDATA_OFFSET(_t) RT_OFFSETOF(_t, cTlsRefs)
+#define VBOXTLSREFDATA_ASSERT_OFFSET(_t) RTASSERT_OFFSET_OF(_t, cTlsRefs)
+#define VBOXTLSREFDATA_SIZE() (sizeof (struct VBOXTLSREFDATA_DUMMY))
+#define VBOXTLSREFDATA_COPY(_pDst, _pSrc) do { \
+ (_pDst)->cTlsRefs = (_pSrc)->cTlsRefs; \
+ (_pDst)->enmTlsRefState = (_pSrc)->enmTlsRefState; \
+ (_pDst)->pfnTlsRefDtor = (_pSrc)->pfnTlsRefDtor; \
+ } while (0)
+
+#define VBOXTLSREFDATA_EQUAL(_pDst, _pSrc) ( \
+ (_pDst)->cTlsRefs == (_pSrc)->cTlsRefs \
+ && (_pDst)->enmTlsRefState == (_pSrc)->enmTlsRefState \
+ && (_pDst)->pfnTlsRefDtor == (_pSrc)->pfnTlsRefDtor \
+ )
+
+
+#define VBoxTlsRefInit(_p, _pfnDtor) do { \
+ (_p)->cTlsRefs = 1; \
+ (_p)->enmTlsRefState = VBOXTLSREFDATA_STATE_INITIALIZED; \
+ (_p)->pfnTlsRefDtor = (_pfnDtor); \
+ } while (0)
+
+#define VBoxTlsRefIsFunctional(_p) (!!((_p)->enmTlsRefState == VBOXTLSREFDATA_STATE_INITIALIZED))
+
+#define VBoxTlsRefAddRef(_p) do { \
+ int cRefs = ASMAtomicIncS32(&(_p)->cTlsRefs); \
+ VBoxTlsRefAssertImpl(cRefs > 1 || (_p)->enmTlsRefState == VBOXTLSREFDATA_STATE_DESTROYING); \
+ RT_NOREF(cRefs); \
+ } while (0)
+
+#define VBoxTlsRefCountGet(_p) (ASMAtomicReadS32(&(_p)->cTlsRefs))
+
+#define VBoxTlsRefRelease(_p) do { \
+ int cRefs = ASMAtomicDecS32(&(_p)->cTlsRefs); \
+ VBoxTlsRefAssertImpl(cRefs >= 0); \
+ if (!cRefs && (_p)->enmTlsRefState != VBOXTLSREFDATA_STATE_DESTROYING /* <- avoid recursion if VBoxTlsRefAddRef/Release is called from dtor */) { \
+ (_p)->enmTlsRefState = VBOXTLSREFDATA_STATE_DESTROYING; \
+ (_p)->pfnTlsRefDtor((_p)); \
+ } \
+ } while (0)
+
+#define VBoxTlsRefMarkDestroy(_p) do { \
+ (_p)->enmTlsRefState = VBOXTLSREFDATA_STATE_TOBE_DESTROYED; \
+ } while (0)
+
+#define VBoxTlsRefGetCurrent(_t, _Tsd) ((_t*) VBoxTlsRefGetImpl((_Tsd)))
+
+#define VBoxTlsRefGetCurrentFunctional(_val, _t, _Tsd) do { \
+ _t * cur = VBoxTlsRefGetCurrent(_t, _Tsd); \
+ if (!cur || VBoxTlsRefIsFunctional(cur)) { \
+ (_val) = cur; \
+ } else { \
+ VBoxTlsRefSetCurrent(_t, _Tsd, NULL); \
+ (_val) = NULL; \
+ } \
+ } while (0)
+
+#define VBoxTlsRefSetCurrent(_t, _Tsd, _p) do { \
+ _t * oldCur = VBoxTlsRefGetCurrent(_t, _Tsd); \
+ if (oldCur != (_p)) { \
+ VBoxTlsRefSetImpl((_Tsd), (_p)); \
+ if (oldCur) { \
+ VBoxTlsRefRelease(oldCur); \
+ } \
+ if ((_p)) { \
+ VBoxTlsRefAddRef((_t*)(_p)); \
+ } \
+ } \
+ } while (0)
+
+
+/* host 3D->Fe[/Qt] notification mechanism defines */
+typedef enum
+{
+ VBOX3D_NOTIFY_TYPE_TEST_FUNCTIONAL = 3,
+ VBOX3D_NOTIFY_TYPE_3DDATA_VISIBLE = 4,
+ VBOX3D_NOTIFY_TYPE_3DDATA_HIDDEN = 5,
+
+ VBOX3D_NOTIFY_TYPE_HW_SCREEN_FIRST = 100,
+ VBOX3D_NOTIFY_TYPE_HW_SCREEN_IS_SUPPORTED = 100,
+ VBOX3D_NOTIFY_TYPE_HW_SCREEN_CREATED = 101,
+ VBOX3D_NOTIFY_TYPE_HW_SCREEN_DESTROYED = 102,
+ VBOX3D_NOTIFY_TYPE_HW_SCREEN_UPDATE_BEGIN = 103,
+ VBOX3D_NOTIFY_TYPE_HW_SCREEN_UPDATE_END = 104,
+ VBOX3D_NOTIFY_TYPE_HW_SCREEN_BIND_SURFACE = 105,
+ VBOX3D_NOTIFY_TYPE_HW_SCREEN_LAST = 105,
+
+ VBOX3D_NOTIFY_TYPE_HW_OVERLAY_CREATED = 200,
+ VBOX3D_NOTIFY_TYPE_HW_OVERLAY_DESTROYED = 201,
+ VBOX3D_NOTIFY_TYPE_HW_OVERLAY_GET_ID = 202,
+
+ VBOX3D_NOTIFY_TYPE_32BIT_HACK = 0x7fffffff
+} VBOX3D_NOTIFY_TYPE;
+
+typedef struct VBOX3DNOTIFY
+{
+ VBOX3D_NOTIFY_TYPE enmNotification;
+ int32_t iDisplay;
+ uint32_t u32Reserved;
+ uint32_t cbData;
+ uint8_t au8Data[sizeof(uint64_t)];
+} VBOX3DNOTIFY;
+
+#endif /* !VBOX_INCLUDED_Graphics_VBoxVideo3D_h */
diff --git a/include/VBox/Graphics/VBoxVideoErr.h b/include/VBox/Graphics/VBoxVideoErr.h
new file mode 100644
index 00000000..a934d16a
--- /dev/null
+++ b/include/VBox/Graphics/VBoxVideoErr.h
@@ -0,0 +1,76 @@
+/* $Id: VBoxVideoErr.h $ */
+/** @file
+ * VirtualBox Video driver, common code - iprt and VirtualBox macros and
+ * definitions.
+ */
+
+/*
+ * Copyright (C) 2017-2022 Oracle and/or its affiliates.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef VBOX_INCLUDED_Graphics_VBoxVideoErr_h
+#define VBOX_INCLUDED_Graphics_VBoxVideoErr_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+/** @name VirtualBox error macros
+ * @{ */
+
+#define VINF_SUCCESS 0
+#define VERR_INVALID_PARAMETER (-2)
+#define VERR_INVALID_POINTER (-6)
+#define VERR_NO_MEMORY (-8)
+#define VERR_NOT_IMPLEMENTED (-12)
+#define VERR_INVALID_FUNCTION (-36)
+#define VERR_NOT_SUPPORTED (-37)
+#define VERR_TOO_MUCH_DATA (-42)
+#define VERR_NOT_FOUND (-78)
+#define VERR_INVALID_STATE (-79)
+#define VERR_OUT_OF_RESOURCES (-80)
+#define VERR_ALREADY_EXISTS (-105)
+#define VERR_INTERNAL_ERROR (-225)
+
+#define RT_SUCCESS_NP(rc) ( (int)(rc) >= VINF_SUCCESS )
+#define RT_SUCCESS(rc) ( likely(RT_SUCCESS_NP(rc)) )
+#define RT_FAILURE(rc) ( unlikely(!RT_SUCCESS_NP(rc)) )
+
+/** @} */
+
+/** @name VirtualBox assertions
+ * @{ */
+
+/* Unlike BUILD_BUG_ON(), these can be used outside of functions. */
+extern int vbox_assert_var[1];
+#define assert_compile(expr) \
+ extern int vbox_assert_var[1] __attribute__((__unused__)), \
+ vbox_assert_var[(expr) ? 1 : 0] __attribute__((__unused__))
+#define assert_compile_size(type, size) \
+ assert_compile(sizeof(type) == (size))
+#define assert_ptr_return(ptr,ret) \
+ do { if (unlikely(!(ptr))) { WARN_ON_ONCE(!(ptr)); return ret; } } while (0)
+
+/** @} */
+
+#endif /* !VBOX_INCLUDED_Graphics_VBoxVideoErr_h */
diff --git a/include/VBox/Graphics/VBoxVideoGuest.h b/include/VBox/Graphics/VBoxVideoGuest.h
new file mode 100644
index 00000000..82018737
--- /dev/null
+++ b/include/VBox/Graphics/VBoxVideoGuest.h
@@ -0,0 +1,185 @@
+/* $Id: VBoxVideoGuest.h $ */
+/** @file
+ * VBox Host Guest Shared Memory Interface (HGSMI) - OS-independent guest structures.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef VBOX_INCLUDED_Graphics_VBoxVideoGuest_h
+#define VBOX_INCLUDED_Graphics_VBoxVideoGuest_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include "VBoxVideoIPRT.h"
+#include "HGSMIBase.h"
+#include "VBoxVideo.h"
+
+RT_C_DECLS_BEGIN
+
+/**
+ * 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 Base HGSMI APIs
+ * @{ */
+
+DECLHIDDEN(bool) VBoxHGSMIIsSupported(void);
+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);
+DECLHIDDEN(void) VBoxHGSMIGetHostAreaMapping(PHGSMIGUESTCOMMANDCONTEXT pCtx,
+ uint32_t cbVRAM,
+ uint32_t offVRAMBaseMapping,
+ uint32_t *poffVRAMHostArea,
+ uint32_t *pcbHostArea);
+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(bool) VBoxVGACfgAvailable(void);
+DECLHIDDEN(bool) VBoxVGACfgQuery(uint16_t u16Id, uint32_t *pu32Value, uint32_t u32DefValue);
+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 DECLCALLBACKTYPE(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 /* !VBOX_INCLUDED_Graphics_VBoxVideoGuest_h */
+
diff --git a/include/VBox/Graphics/VBoxVideoIPRT.h b/include/VBox/Graphics/VBoxVideoIPRT.h
new file mode 100644
index 00000000..b1533e72
--- /dev/null
+++ b/include/VBox/Graphics/VBoxVideoIPRT.h
@@ -0,0 +1,114 @@
+/* $Id: VBoxVideoIPRT.h $ */
+/** @file
+ * VirtualBox Video driver, common code - iprt and VirtualBox macros and definitions.
+ */
+
+/*
+ * Copyright (C) 2017-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_Graphics_VBoxVideoIPRT_h
+#define VBOX_INCLUDED_Graphics_VBoxVideoIPRT_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#if !defined(RT_OS_OS2) || !defined(__IBMC__) /* IBM VACpp 3.08 doesn't properly eliminate unused inline functions */
+# include <iprt/asm.h>
+# include <iprt/string.h>
+#endif
+#include <iprt/assert.h>
+#include <iprt/cdefs.h>
+#include <iprt/err.h>
+#include <iprt/list.h>
+#include <iprt/stdarg.h>
+#include <iprt/stdint.h>
+#include <iprt/types.h>
+
+#if !defined(VBOX_XPDM_MINIPORT) && !defined(RT_OS_OS2) && (defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86))
+# include <iprt/asm-amd64-x86.h>
+#endif
+
+#ifdef VBOX_XPDM_MINIPORT
+# include <iprt/nt/miniport.h>
+# include <ntddvdeo.h> /* sdk, clean */
+# include <iprt/nt/Video.h>
+#endif
+
+/** @name Port I/O helpers
+ * @{ */
+
+#ifdef VBOX_XPDM_MINIPORT
+
+/** Write an 8-bit value to an I/O port. */
+# define VBVO_PORT_WRITE_U8(Port, Value) \
+ VideoPortWritePortUchar((PUCHAR)Port, Value)
+/** Write a 16-bit value to an I/O port. */
+# define VBVO_PORT_WRITE_U16(Port, Value) \
+ VideoPortWritePortUshort((PUSHORT)Port, Value)
+/** Write a 32-bit value to an I/O port. */
+# define VBVO_PORT_WRITE_U32(Port, Value) \
+ VideoPortWritePortUlong((PULONG)Port, Value)
+/** Read an 8-bit value from an I/O port. */
+# define VBVO_PORT_READ_U8(Port) \
+ VideoPortReadPortUchar((PUCHAR)Port)
+/** Read a 16-bit value from an I/O port. */
+# define VBVO_PORT_READ_U16(Port) \
+ VideoPortReadPortUshort((PUSHORT)Port)
+/** Read a 32-bit value from an I/O port. */
+# define VBVO_PORT_READ_U32(Port) \
+ VideoPortReadPortUlong((PULONG)Port)
+
+#else /** @todo make these explicit */
+
+/** Write an 8-bit value to an I/O port. */
+# define VBVO_PORT_WRITE_U8(Port, Value) \
+ ASMOutU8(Port, Value)
+/** Write a 16-bit value to an I/O port. */
+# define VBVO_PORT_WRITE_U16(Port, Value) \
+ ASMOutU16(Port, Value)
+/** Write a 32-bit value to an I/O port. */
+# define VBVO_PORT_WRITE_U32(Port, Value) \
+ ASMOutU32(Port, Value)
+/** Read an 8-bit value from an I/O port. */
+# define VBVO_PORT_READ_U8(Port) \
+ ASMInU8(Port)
+/** Read a 16-bit value from an I/O port. */
+# define VBVO_PORT_READ_U16(Port) \
+ ASMInU16(Port)
+/** Read a 32-bit value from an I/O port. */
+# define VBVO_PORT_READ_U32(Port) \
+ ASMInU32(Port)
+#endif
+
+/** @} */
+
+#endif /* !VBOX_INCLUDED_Graphics_VBoxVideoIPRT_h */
+
diff --git a/include/VBox/Graphics/VBoxVideoVBE.h b/include/VBox/Graphics/VBoxVideoVBE.h
new file mode 100644
index 00000000..fb1c6808
--- /dev/null
+++ b/include/VBox/Graphics/VBoxVideoVBE.h
@@ -0,0 +1,107 @@
+/* $Id: VBoxVideoVBE.h $ */
+/** @file
+ * VirtualBox graphics card port I/O definitions
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef VBOX_INCLUDED_Graphics_VBoxVideoVBE_h
+#define VBOX_INCLUDED_Graphics_VBoxVideoVBE_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+/* 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
+
+/* Cross reference with src/VBox/Devices/Graphics/DevVGA.h */
+#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_INDEX_CFG 0xc
+
+#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_ID_CFG 0xBE03 /* VBE_DISPI_INDEX_CFG is available. */
+
+#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
+
+/* VBE_DISPI_INDEX_CFG content. */
+#define VBE_DISPI_CFG_MASK_ID 0x0FFF /* Identifier of a configuration value. */
+#define VBE_DISPI_CFG_MASK_SUPPORT 0x1000 /* Query whether the identifier is supported. */
+#define VBE_DISPI_CFG_MASK_RESERVED 0xE000 /* For future extensions. Must be 0. */
+
+/* VBE_DISPI_INDEX_CFG values. */
+#define VBE_DISPI_CFG_ID_VERSION 0x0000 /* Version of the configuration interface. */
+#define VBE_DISPI_CFG_ID_VRAM_SIZE 0x0001 /* VRAM size. */
+#define VBE_DISPI_CFG_ID_3D 0x0002 /* 3D support. */
+#define VBE_DISPI_CFG_ID_VMSVGA 0x0003 /* VMSVGA FIFO and ports are available. */
+#define VBE_DISPI_CFG_ID_VMSVGA_DX 0x0004 /* VGPU10 is enabled. */
+
+#define VGA_PORT_HGSMI_HOST 0x3b0
+#define VGA_PORT_HGSMI_GUEST 0x3d0
+
+#endif /* !VBOX_INCLUDED_Graphics_VBoxVideoVBE_h */
+
diff --git a/include/VBox/Graphics/VBoxVideoVBEPrivate.h b/include/VBox/Graphics/VBoxVideoVBEPrivate.h
new file mode 100644
index 00000000..40f8bfa4
--- /dev/null
+++ b/include/VBox/Graphics/VBoxVideoVBEPrivate.h
@@ -0,0 +1,245 @@
+/** @file
+ * VirtualBox graphics card definitions, private interface for firmware
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef VBOX_INCLUDED_Graphics_VBoxVideoVBEPrivate_h
+#define VBOX_INCLUDED_Graphics_VBoxVideoVBEPrivate_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#ifdef VBE
+# include <stdint.h>
+#else
+# include <iprt/types.h>
+#endif
+
+/* VBE Mode Numbers */
+#define VBE_MODE_VESA_DEFINED 0x0100
+#define VBE_MODE_REFRESH_RATE_USE_CRTC 0x0800
+#define VBE_MODE_LINEAR_FRAME_BUFFER 0x4000
+#define VBE_MODE_PRESERVE_DISPLAY_MEMORY 0x8000
+
+/* VBE GFX Mode Number */
+#define VBE_VESA_MODE_640X400X8 0x100
+#define VBE_VESA_MODE_640X480X8 0x101
+#define VBE_VESA_MODE_800X600X4 0x102
+#define VBE_VESA_MODE_800X600X8 0x103
+#define VBE_VESA_MODE_1024X768X4 0x104
+#define VBE_VESA_MODE_1024X768X8 0x105
+#define VBE_VESA_MODE_1280X1024X4 0x106
+#define VBE_VESA_MODE_1280X1024X8 0x107
+#define VBE_VESA_MODE_320X200X1555 0x10D
+#define VBE_VESA_MODE_320X200X565 0x10E
+#define VBE_VESA_MODE_320X200X888 0x10F
+#define VBE_VESA_MODE_640X480X1555 0x110
+#define VBE_VESA_MODE_640X480X565 0x111
+#define VBE_VESA_MODE_640X480X888 0x112
+#define VBE_VESA_MODE_800X600X1555 0x113
+#define VBE_VESA_MODE_800X600X565 0x114
+#define VBE_VESA_MODE_800X600X888 0x115
+#define VBE_VESA_MODE_1024X768X1555 0x116
+#define VBE_VESA_MODE_1024X768X565 0x117
+#define VBE_VESA_MODE_1024X768X888 0x118
+#define VBE_VESA_MODE_1280X1024X1555 0x119
+#define VBE_VESA_MODE_1280X1024X565 0x11A
+#define VBE_VESA_MODE_1280X1024X888 0x11B
+#define VBE_VESA_MODE_1600X1200X8 0x11C
+#define VBE_VESA_MODE_1600X1200X1555 0x11D
+#define VBE_VESA_MODE_1600X1200X565 0x11E
+#define VBE_VESA_MODE_1600X1200X888 0x11F
+
+/* BOCHS/PLEX86 'own' mode numbers */
+#define VBE_OWN_MODE_320X200X8888 0x140
+#define VBE_OWN_MODE_640X400X8888 0x141
+#define VBE_OWN_MODE_640X480X8888 0x142
+#define VBE_OWN_MODE_800X600X8888 0x143
+#define VBE_OWN_MODE_1024X768X8888 0x144
+#define VBE_OWN_MODE_1280X1024X8888 0x145
+#define VBE_OWN_MODE_320X200X8 0x146
+#define VBE_OWN_MODE_1600X1200X8888 0x147
+#define VBE_OWN_MODE_1152X864X8 0x148
+#define VBE_OWN_MODE_1152X864X1555 0x149
+#define VBE_OWN_MODE_1152X864X565 0x14a
+#define VBE_OWN_MODE_1152X864X888 0x14b
+#define VBE_OWN_MODE_1152X864X8888 0x14c
+
+/* VirtualBox 'own' mode numbers */
+#define VBE_VBOX_MODE_CUSTOM1 0x160
+#define VBE_VBOX_MODE_CUSTOM2 0x161
+#define VBE_VBOX_MODE_CUSTOM3 0x162
+#define VBE_VBOX_MODE_CUSTOM4 0x163
+#define VBE_VBOX_MODE_CUSTOM5 0x164
+#define VBE_VBOX_MODE_CUSTOM6 0x165
+#define VBE_VBOX_MODE_CUSTOM7 0x166
+#define VBE_VBOX_MODE_CUSTOM8 0x167
+#define VBE_VBOX_MODE_CUSTOM9 0x168
+#define VBE_VBOX_MODE_CUSTOM10 0x169
+#define VBE_VBOX_MODE_CUSTOM11 0x16a
+#define VBE_VBOX_MODE_CUSTOM12 0x16b
+#define VBE_VBOX_MODE_CUSTOM13 0x16c
+#define VBE_VBOX_MODE_CUSTOM14 0x16d
+#define VBE_VBOX_MODE_CUSTOM15 0x16e
+#define VBE_VBOX_MODE_CUSTOM16 0x16f
+
+#define VBE_VESA_MODE_END_OF_LIST 0xFFFF
+
+/* Capabilities */
+#define VBE_CAPABILITY_8BIT_DAC 0x0001
+#define VBE_CAPABILITY_NOT_VGA_COMPATIBLE 0x0002
+#define VBE_CAPABILITY_RAMDAC_USE_BLANK_BIT 0x0004
+#define VBE_CAPABILITY_STEREOSCOPIC_SUPPORT 0x0008
+#define VBE_CAPABILITY_STEREO_VIA_VESA_EVC 0x0010
+
+/* Mode Attributes */
+#define VBE_MODE_ATTRIBUTE_SUPPORTED 0x0001
+#define VBE_MODE_ATTRIBUTE_EXTENDED_INFORMATION_AVAILABLE 0x0002
+#define VBE_MODE_ATTRIBUTE_TTY_BIOS_SUPPORT 0x0004
+#define VBE_MODE_ATTRIBUTE_COLOR_MODE 0x0008
+#define VBE_MODE_ATTRIBUTE_GRAPHICS_MODE 0x0010
+#define VBE_MODE_ATTRIBUTE_NOT_VGA_COMPATIBLE 0x0020
+#define VBE_MODE_ATTRIBUTE_NO_VGA_COMPATIBLE_WINDOW 0x0040
+#define VBE_MODE_ATTRIBUTE_LINEAR_FRAME_BUFFER_MODE 0x0080
+#define VBE_MODE_ATTRIBUTE_DOUBLE_SCAN_MODE 0x0100
+#define VBE_MODE_ATTRIBUTE_INTERLACE_MODE 0x0200
+#define VBE_MODE_ATTRIBUTE_HARDWARE_TRIPLE_BUFFER 0x0400
+#define VBE_MODE_ATTRIBUTE_HARDWARE_STEREOSCOPIC_DISPLAY 0x0800
+#define VBE_MODE_ATTRIBUTE_DUAL_DISPLAY_START_ADDRESS 0x1000
+
+#define VBE_MODE_ATTTRIBUTE_LFB_ONLY ( VBE_MODE_ATTRIBUTE_NO_VGA_COMPATIBLE_WINDOW | VBE_MODE_ATTRIBUTE_LINEAR_FRAME_BUFFER_MODE )
+
+/* Window attributes */
+#define VBE_WINDOW_ATTRIBUTE_RELOCATABLE 0x01
+#define VBE_WINDOW_ATTRIBUTE_READABLE 0x02
+#define VBE_WINDOW_ATTRIBUTE_WRITEABLE 0x04
+
+/* Memory model */
+#define VBE_MEMORYMODEL_TEXT_MODE 0x00
+#define VBE_MEMORYMODEL_CGA_GRAPHICS 0x01
+#define VBE_MEMORYMODEL_HERCULES_GRAPHICS 0x02
+#define VBE_MEMORYMODEL_PLANAR 0x03
+#define VBE_MEMORYMODEL_PACKED_PIXEL 0x04
+#define VBE_MEMORYMODEL_NON_CHAIN_4_256 0x05
+#define VBE_MEMORYMODEL_DIRECT_COLOR 0x06
+#define VBE_MEMORYMODEL_YUV 0x07
+
+/* DirectColorModeInfo */
+#define VBE_DIRECTCOLOR_COLOR_RAMP_PROGRAMMABLE 0x01
+#define VBE_DIRECTCOLOR_RESERVED_BITS_AVAILABLE 0x02
+
+/* Video memory */
+#define VGAMEM_GRAPH 0xA000
+
+/**
+ * VBE Bios Extra Data structure.
+ */
+typedef struct VBEHeader
+{
+ /** Signature (VBEHEADER_MAGIC). */
+ uint16_t u16Signature;
+ /** Data size. */
+ uint16_t cbData;
+} VBEHeader;
+
+/** The value of the VBEHeader::u16Signature field. */
+#define VBEHEADER_MAGIC 0x77CC
+
+/** The extra port which is used to read the mode list. */
+#define VBE_EXTRA_PORT 0x3b6
+
+/** The extra port which is used for debug printf. */
+#define VBE_PRINTF_PORT 0x3b7
+
+/**
+ * This one is for compactly storing a list of mode info blocks
+ */
+#pragma pack(1) /* pack(1) is important! (you'll get a byte extra for each of the u8 fields elsewise...)
+ * bird: Load of non-sense. You'll get two extra bytes before MaxPixelClock if you don't pack it. */
+typedef struct ModeInfoBlockCompact
+{
+ /* Mandatory information for all VBE revisions */
+ uint16_t ModeAttributes;
+ uint8_t WinAAttributes;
+ uint8_t WinBAttributes;
+ uint16_t WinGranularity;
+ uint16_t WinSize;
+ uint16_t WinASegment;
+ uint16_t WinBSegment;
+ uint32_t WinFuncPtr;
+ uint16_t BytesPerScanLine;
+ /* Mandatory information for VBE 1.2 and above */
+ uint16_t XResolution;
+ uint16_t YResolution;
+ uint8_t XCharSize;
+ uint8_t YCharSize;
+ uint8_t NumberOfPlanes;
+ uint8_t BitsPerPixel;
+ uint8_t NumberOfBanks;
+ uint8_t MemoryModel;
+ uint8_t BankSize;
+ uint8_t NumberOfImagePages;
+ uint8_t Reserved_page;
+ /* Direct Color fields (required for direct/6 and YUV/7 memory models) */
+ uint8_t RedMaskSize;
+ uint8_t RedFieldPosition;
+ uint8_t GreenMaskSize;
+ uint8_t GreenFieldPosition;
+ uint8_t BlueMaskSize;
+ uint8_t BlueFieldPosition;
+ uint8_t RsvdMaskSize;
+ uint8_t RsvdFieldPosition;
+ uint8_t DirectColorModeInfo;
+ /* Mandatory information for VBE 2.0 and above */
+ uint32_t PhysBasePtr;
+ uint32_t OffScreenMemOffset;
+ uint16_t OffScreenMemSize;
+ /* Mandatory information for VBE 3.0 and above */
+ uint16_t LinBytesPerScanLine;
+ uint8_t BnkNumberOfPages;
+ uint8_t LinNumberOfPages;
+ uint8_t LinRedMaskSize;
+ uint8_t LinRedFieldPosition;
+ uint8_t LinGreenMaskSize;
+ uint8_t LinGreenFieldPosition;
+ uint8_t LinBlueMaskSize;
+ uint8_t LinBlueFieldPosition;
+ uint8_t LinRsvdMaskSize;
+ uint8_t LinRsvdFieldPosition;
+ uint32_t MaxPixelClock;
+} ModeInfoBlockCompact;
+#pragma pack()
+
+typedef struct ModeInfoListItem
+{
+ uint16_t mode;
+ ModeInfoBlockCompact info;
+} ModeInfoListItem;
+
+
+#endif /* !VBOX_INCLUDED_Graphics_VBoxVideoVBEPrivate_h */
+
diff --git a/include/VBox/GuestHost/DragAndDrop.h b/include/VBox/GuestHost/DragAndDrop.h
new file mode 100644
index 00000000..a9722c59
--- /dev/null
+++ b/include/VBox/GuestHost/DragAndDrop.h
@@ -0,0 +1,350 @@
+/* $Id: DragAndDrop.h $ */
+/** @file
+ * DnD - Shared functions between host and guest.
+ */
+
+/*
+ * Copyright (C) 2014-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_GuestHost_DragAndDrop_h
+#define VBOX_INCLUDED_GuestHost_DragAndDrop_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/assert.h>
+#include <iprt/fs.h>
+#include <iprt/list.h>
+
+#include <VBox/GuestHost/DragAndDropDefs.h>
+
+/** DnDURIDroppedFiles flags. */
+typedef uint32_t DNDURIDROPPEDFILEFLAGS;
+
+/** No flags specified. */
+#define DNDURIDROPPEDFILE_FLAGS_NONE 0
+
+/**
+ * Structure for keeping a DnD dropped files entry.
+ */
+typedef struct DNDDROPPEDFILESENTRY
+{
+ RTLISTNODE Node;
+ char *pszPath;
+} DNDDROPPEDFILESENTRY;
+/** Pointer to a DnD dropped files entry. */
+typedef DNDDROPPEDFILESENTRY *PDNDDROPPEDFILESENTRY;
+
+/**
+ * Structure for maintaining a "dropped files" directory
+ * on the host or guest. This will contain all received files & directories
+ * for a single drag and drop operation.
+ *
+ * In case of a failed drag and drop operation this can also
+ * perform a gentle rollback if required.
+ */
+typedef struct DNDDROPPEDFILES
+{
+ /** Open flags. */
+ uint32_t m_fOpen;
+ /** Directory handle for drop directory. */
+ RTDIR m_hDir;
+ /** Absolute path to drop directory. */
+ char *pszPathAbs;
+ /** List for holding created directories in the case of a rollback. */
+ RTLISTANCHOR m_lstDirs;
+ /** List for holding created files in the case of a rollback. */
+ RTLISTANCHOR m_lstFiles;
+} DNDDROPPEDFILES;
+/** Pointer to a DnD dropped files directory. */
+typedef DNDDROPPEDFILES *PDNDDROPPEDFILES;
+
+int DnDDroppedFilesInit(PDNDDROPPEDFILES pDF);
+int DnDDroppedFilesInitEx(PDNDDROPPEDFILES pDF, const char *pszPath, DNDURIDROPPEDFILEFLAGS fFlags);
+void DnDDroppedFilesDestroy(PDNDDROPPEDFILES pDF);
+int DnDDroppedFilesAddFile(PDNDDROPPEDFILES pDF, const char *pszFile);
+int DnDDroppedFilesAddDir(PDNDDROPPEDFILES pDF, const char *pszDir);
+int DnDDroppedFilesClose(PDNDDROPPEDFILES pDF);
+bool DnDDroppedFilesIsOpen(PDNDDROPPEDFILES pDF);
+int DnDDroppedFilesOpenEx(PDNDDROPPEDFILES pDF, const char *pszPath, DNDURIDROPPEDFILEFLAGS fFlags);
+int DnDDroppedFilesOpenTemp(PDNDDROPPEDFILES pDF, DNDURIDROPPEDFILEFLAGS fFlags);
+const char *DnDDroppedFilesGetDirAbs(PDNDDROPPEDFILES pDF);
+int DnDDroppedFilesReopen(PDNDDROPPEDFILES pDF);
+int DnDDroppedFilesReset(PDNDDROPPEDFILES pDF, bool fDelete);
+int DnDDroppedFilesRollback(PDNDDROPPEDFILES pDF);
+
+const char *DnDHostMsgToStr(uint32_t uMsg);
+const char *DnDGuestMsgToStr(uint32_t uMsg);
+const char *DnDActionToStr(VBOXDNDACTION uAction);
+ char *DnDActionListToStrA(VBOXDNDACTIONLIST fActionList);
+const char *DnDStateToStr(VBOXDNDSTATE enmState);
+
+bool DnDMIMEHasFileURLs(const char *pcszFormat, size_t cchFormatMax);
+bool DnDMIMENeedsDropDir(const char *pcszFormat, size_t cchFormatMax);
+
+int DnDPathValidate(const char *pcszPath, bool fMustExist);
+
+/** DnD path conversion flags. */
+typedef uint32_t DNDPATHCONVERTFLAGS;
+
+/** No flags specified.
+ * This will convert the path to the universal tansport style. */
+#define DNDPATHCONVERT_FLAGS_TRANSPORT 0
+/** Converts the path to a OS-dependent path. */
+#define DNDPATHCONVERT_FLAGS_TO_DOS RT_BIT(0)
+
+/** Mask of all valid DnD path conversion flags. */
+#define DNDPATHCONVERT_FLAGS_VALID_MASK UINT32_C(0x1)
+
+int DnDPathConvert(char *pszPath, size_t cbPath, DNDPATHCONVERTFLAGS fFlags);
+int DnDPathSanitizeFileName(char *pszPath, size_t cbPath);
+int DnDPathRebase(const char *pcszPathAbs, const char *pcszBaseOld, const char *pcszBaseNew, char **ppszPath);
+
+/** DnDTransferObject flags. */
+typedef uint32_t DNDTRANSFEROBJECTFLAGS;
+
+/** No flags specified. */
+#define DNDTRANSFEROBJECT_FLAGS_NONE 0
+
+/** Mask of all valid DnD transfer object flags. */
+#define DNDTRANSFEROBJECT_FLAGS_VALID_MASK UINT32_C(0x0)
+
+/**
+ * Enumeration for specifying a transfer object type.
+ */
+typedef enum DNDTRANSFEROBJTYPE
+{
+ /** Unknown type, do not use. */
+ DNDTRANSFEROBJTYPE_UNKNOWN = 0,
+ /** Object is a file. */
+ DNDTRANSFEROBJTYPE_FILE,
+ /** Object is a directory. */
+ DNDTRANSFEROBJTYPE_DIRECTORY,
+ /** The usual 32-bit hack. */
+ DNDTRANSFEROBJTYPE_32BIT_HACK = 0x7fffffff
+} DNDTRANSFEROBJTYPE;
+
+/**
+ * Enumeration for specifying a path style.
+ */
+typedef enum DNDTRANSFEROBJPATHSTYLE
+{
+ /** Transport style (UNIX-y), the default. */
+ DNDTRANSFEROBJPATHSTYLE_TRANSPORT = 0,
+ /** DOS style, containing back slashes. */
+ DNDTRANSFEROBJPATHSTYLE_DOS,
+ /** The usual 32-bit hack. */
+ DNDTRANSFEROBJPATHSTYLE_32BIT_HACK = 0x7fffffff
+} DNDTRANSFEROBJPATHSTYLE;
+
+/**
+ * Structure for keeping a DnD transfer object.
+ */
+typedef struct DNDTRANSFEROBJECT
+{
+ RTLISTNODE Node;
+ /** The object's type. */
+ DNDTRANSFEROBJTYPE enmType;
+ /** Index (in characters, UTF-8) at which the first destination segment starts. */
+ uint16_t idxDst;
+ /** Allocated path. Includdes the absolute source path (if any) + destination segments.
+ * Transport (IPRT) style. */
+ char *pszPath;
+
+ /** Union containing data depending on the object's type. */
+ union
+ {
+ /** Structure containing members for objects that
+ * are files. */
+ struct
+ {
+ /** File handle. */
+ RTFILE hFile;
+ /** File system object information of this file. */
+ RTFSOBJINFO objInfo;
+ /** Bytes to proces for reading/writing. */
+ uint64_t cbToProcess;
+ /** Bytes processed reading/writing. */
+ uint64_t cbProcessed;
+ } File;
+ struct
+ {
+ /** Directory handle. */
+ RTDIR hDir;
+ /** File system object information of this directory. */
+ RTFSOBJINFO objInfo;
+ } Dir;
+ } u;
+} DNDTRANSFEROBJECT;
+/** Pointer to a DnD transfer object. */
+typedef DNDTRANSFEROBJECT *PDNDTRANSFEROBJECT;
+
+int DnDTransferObjectInit(PDNDTRANSFEROBJECT pObj);
+int DnDTransferObjectInitEx(PDNDTRANSFEROBJECT pObj, DNDTRANSFEROBJTYPE enmType, const char *pcszPathSrcAbs, const char *pcszPathDst);
+void DnDTransferObjectDestroy(PDNDTRANSFEROBJECT pObj);
+int DnDTransferObjectClose(PDNDTRANSFEROBJECT pObj);
+void DnDTransferObjectReset(PDNDTRANSFEROBJECT pObj);
+const char *DnDTransferObjectGetSourcePath(PDNDTRANSFEROBJECT pObj);
+const char *DnDTransferObjectGetDestPath(PDNDTRANSFEROBJECT pObj);
+int DnDTransferObjectGetDestPathEx(PDNDTRANSFEROBJECT pObj, DNDTRANSFEROBJPATHSTYLE enmStyle, char *pszBuf, size_t cbBuf);
+RTFMODE DnDTransferObjectGetMode(PDNDTRANSFEROBJECT pObj);
+uint64_t DnDTransferObjectGetProcessed(PDNDTRANSFEROBJECT pObj);
+uint64_t DnDTransferObjectGetSize(PDNDTRANSFEROBJECT pObj);
+DNDTRANSFEROBJTYPE DnDTransferObjectGetType(PDNDTRANSFEROBJECT pObj);
+int DnDTransferObjectSetSize(PDNDTRANSFEROBJECT pObj, uint64_t cbSize);
+bool DnDTransferObjectIsComplete(PDNDTRANSFEROBJECT pObj);
+bool DnDTransferObjectIsOpen(PDNDTRANSFEROBJECT pObj);
+int DnDTransferObjectOpen(PDNDTRANSFEROBJECT pObj, uint64_t fOpen, RTFMODE fMode, DNDTRANSFEROBJECTFLAGS fFlags);
+int DnDTransferObjectQueryInfo(PDNDTRANSFEROBJECT pObj);
+int DnDTransferObjectRead(PDNDTRANSFEROBJECT pObj, void *pvBuf, size_t cbBuf, uint32_t *pcbRead);
+int DnDTransferObjectWrite(PDNDTRANSFEROBJECT pObj, const void *pvBuf, size_t cbBuf, uint32_t *pcbWritten);
+
+/** Defines the default chunk size of DnD data transfers.
+ * Supported on all (older) Guest Additions which also support DnD. */
+#define DND_DEFAULT_CHUNK_SIZE _64K
+
+/** Separator for a formats list. */
+#define DND_FORMATS_SEPARATOR_STR "\r\n"
+
+/** Default URI list path separator, if not specified otherwise.
+ *
+ * This is there for hysterical raisins, to not break older Guest Additions.
+ ** @todo Get rid of this. */
+#define DND_PATH_SEPARATOR_STR "\r\n"
+
+/** DnDTransferList flags. */
+typedef uint32_t DNDTRANSFERLISTFLAGS;
+
+/** No flags specified. */
+#define DNDTRANSFERLIST_FLAGS_NONE 0
+/** Enables recurisve directory handling. */
+#define DNDTRANSFERLIST_FLAGS_RECURSIVE RT_BIT(0)
+/** Resolve all symlinks. Currently not supported and will be ignored. */
+#define DNDTRANSFERLIST_FLAGS_RESOLVE_SYMLINKS RT_BIT(1)
+/** Keep the files + directory entries open while
+ * being in this list. */
+#define DNDTRANSFERLIST_FLAGS_KEEP_OPEN RT_BIT(2)
+/** Lazy loading: Only enumerate sub directories when needed. Not implemented yet.
+ ** @todo Implement lazy loading. */
+#define DNDTRANSFERLIST_FLAGS_LAZY RT_BIT(3)
+
+/** Mask of all valid DnD transfer list flags. */
+#define DNDTRANSFERLIST_FLAGS_VALID_MASK UINT32_C(0xF)
+
+/**
+ * Enumeration for specifying a transfer list format.
+ */
+typedef enum DNDTRANSFERLISTFMT
+{
+ /** Unknown format, do not use. */
+ DNDTRANSFERLISTFMT_UNKNOWN = 0,
+ /** Native format. */
+ DNDTRANSFERLISTFMT_NATIVE,
+ /** URI format. */
+ DNDTRANSFERLISTFMT_URI,
+ /** The usual 32-bit hack. */
+ DNDTRANSFERLISTFMT_32BIT_HACK = 0x7fffffff
+} DNDTRANSFERLISTFMT;
+
+/**
+ * Structure for keeping a DnD transfer list root entry.
+ *
+ * A root entry always is relative to the parent list maintaining it.
+ */
+typedef struct DNDTRANSFERLISTROOT
+{
+ /** List node. */
+ RTLISTNODE Node;
+ /** Pointer to the allocated root path.
+ * - Relative to the list's root path
+ * - Always ends with a trailing slash
+ * - Always stored in transport style (UNIX-y). */
+ char *pszPathRoot;
+} DNDTRANSFERLISTROOT;
+/** Pointer to a DnD list root entry. */
+typedef DNDTRANSFERLISTROOT *PDNDTRANSFERLISTROOT;
+
+/**
+ * Struct for keeping a DnD transfer list.
+ *
+ * All entries must share a common (absolute) root path. For different root paths another transfer list is needed.
+ */
+typedef struct DNDTRANSFERLIST
+{
+ /** Absolute root path of this transfer list, in native path style.
+ * Always ends with a separator. */
+ char *pszPathRootAbs;
+ /** List of all relative (to \a pszPathRootAbs) top-level file/directory entries, of type DNDTRANSFERLISTROOT.
+ * Note: All paths are stored internally in transport style (UNIX paths) for
+ * easier conversion/handling! */
+ RTLISTANCHOR lstRoot;
+ /** Total number of all transfer root entries. */
+ uint64_t cRoots;
+ /** List of all transfer objects added, of type DNDTRANSFEROBJECT.
+ *
+ * The order of objects being added is crucial for traversing the tree.
+ * In other words, sub directories must come first before its contents. */
+ RTLISTANCHOR lstObj;
+ /** Total number of all transfer objects. */
+ uint64_t cObj;
+ /** Total size of all transfer objects, that is, the file
+ * size of all objects (in bytes).
+ * Note: Do *not* size_t here, as we also want to support large files
+ * on 32-bit guests. */
+ uint64_t cbObjTotal;
+} DNDTRANSFERLIST;
+/** Pointer to a DNDTRANSFERLIST struct. */
+typedef DNDTRANSFERLIST *PDNDTRANSFERLIST;
+
+int DnDTransferListInit(PDNDTRANSFERLIST pList);
+int DnDTransferListInitEx(PDNDTRANSFERLIST pList, const char *pcszRootPathAbs, DNDTRANSFERLISTFMT enmFmt);
+void DnDTransferListDestroy(PDNDTRANSFERLIST pList);
+void DnDTransferListReset(PDNDTRANSFERLIST pList);
+
+int DnDTransferListAppendPath(PDNDTRANSFERLIST pList, DNDTRANSFERLISTFMT enmFmt, const char *pszPath, DNDTRANSFERLISTFLAGS fFlags);
+int DnDTransferListAppendPathsFromBuffer(PDNDTRANSFERLIST pList, DNDTRANSFERLISTFMT enmFmt, const char *pszPaths, size_t cbPaths, const char *pcszSeparator, DNDTRANSFERLISTFLAGS fFlags);
+int DnDTransferListAppendPathsFromArray(PDNDTRANSFERLIST pList, DNDTRANSFERLISTFMT enmFmt, const char * const *papcszPaths, size_t cPaths, DNDTRANSFERLISTFLAGS fFlags);
+int DnDTransferListAppendRootsFromBuffer(PDNDTRANSFERLIST pList, DNDTRANSFERLISTFMT enmFmt, const char *pszPaths, size_t cbPaths, const char *pcszSeparator, DNDTRANSFERLISTFLAGS fFlags);
+int DnDTransferListAppendRootsFromArray(PDNDTRANSFERLIST pList, DNDTRANSFERLISTFMT enmFmt, const char * const *papcszPaths, size_t cPaths, DNDTRANSFERLISTFLAGS fFlags);
+
+int DnDTransferListGetRootsEx(PDNDTRANSFERLIST pList, DNDTRANSFERLISTFMT enmFmt, const char *pcszPathBase, const char *pcszSeparator, char **ppszBuffer, size_t *pcbBuffer);
+int DnDTransferListGetRoots(PDNDTRANSFERLIST pList, DNDTRANSFERLISTFMT enmFmt, char **ppszBuffer, size_t *pcbBuffer);
+uint64_t DnDTransferListGetRootCount(PDNDTRANSFERLIST pList);
+const char *DnDTransferListGetRootPathAbs(PDNDTRANSFERLIST pList);
+
+PDNDTRANSFEROBJECT DnDTransferListObjGetFirst(PDNDTRANSFERLIST pList);
+void DnDTransferListObjRemove(PDNDTRANSFERLIST pList, PDNDTRANSFEROBJECT pObj);
+void DnDTransferListObjRemoveFirst(PDNDTRANSFERLIST pList);
+uint64_t DnDTransferListObjCount(PDNDTRANSFERLIST pList);
+uint64_t DnDTransferListObjTotalBytes(PDNDTRANSFERLIST pList);
+
+#endif /* !VBOX_INCLUDED_GuestHost_DragAndDrop_h */
+
diff --git a/include/VBox/GuestHost/DragAndDropDefs.h b/include/VBox/GuestHost/DragAndDropDefs.h
new file mode 100644
index 00000000..0968fa8a
--- /dev/null
+++ b/include/VBox/GuestHost/DragAndDropDefs.h
@@ -0,0 +1,112 @@
+/** @file
+ * Drag and Drop definitions - Common header for host service and guest clients.
+ */
+
+/*
+ * Copyright (C) 2018-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_GuestHost_DragAndDropDefs_h
+#define VBOX_INCLUDED_GuestHost_DragAndDropDefs_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+
+/*
+ * The mode of operations.
+ */
+#define VBOX_DRAG_AND_DROP_MODE_OFF 0
+#define VBOX_DRAG_AND_DROP_MODE_HOST_TO_GUEST 1
+#define VBOX_DRAG_AND_DROP_MODE_GUEST_TO_HOST 2
+#define VBOX_DRAG_AND_DROP_MODE_BIDIRECTIONAL 3
+
+#define VBOX_DND_ACTION_IGNORE UINT32_C(0)
+#define VBOX_DND_ACTION_COPY RT_BIT_32(0)
+#define VBOX_DND_ACTION_MOVE RT_BIT_32(1)
+#define VBOX_DND_ACTION_LINK RT_BIT_32(2)
+
+/** A single DnD action. */
+typedef uint32_t VBOXDNDACTION;
+/** A list of (OR'ed) DnD actions. */
+typedef uint32_t VBOXDNDACTIONLIST;
+
+#define hasDnDCopyAction(a) ((a) & VBOX_DND_ACTION_COPY)
+#define hasDnDMoveAction(a) ((a) & VBOX_DND_ACTION_MOVE)
+#define hasDnDLinkAction(a) ((a) & VBOX_DND_ACTION_LINK)
+
+#define isDnDIgnoreAction(a) ((a) == VBOX_DND_ACTION_IGNORE)
+#define isDnDCopyAction(a) ((a) == VBOX_DND_ACTION_COPY)
+#define isDnDMoveAction(a) ((a) == VBOX_DND_ACTION_MOVE)
+#define isDnDLinkAction(a) ((a) == VBOX_DND_ACTION_LINK)
+
+/** @def VBOX_DND_FORMATS_DEFAULT
+ * Default drag'n drop formats.
+ * Note: If you add new entries here, make sure you test those
+ * with all supported guest OSes!
+ */
+#define VBOX_DND_FORMATS_DEFAULT \
+ "text/uri-list", \
+ /* Text. */ \
+ "text/html", \
+ "text/plain;charset=utf-8", \
+ "text/plain;charset=utf-16", \
+ "text/plain", \
+ "text/richtext", \
+ "UTF8_STRING", \
+ "TEXT", \
+ "STRING", \
+ /* OpenOffice formats. */ \
+ /* See: https://wiki.openoffice.org/wiki/Documentation/DevGuide/OfficeDev/Common_Application_Features#OpenOffice.org_Clipboard_Data_Formats */ \
+ "application/x-openoffice-embed-source-xml;windows_formatname=\"Star Embed Source (XML)\"", \
+ "application/x-openoffice;windows_formatname=\"Bitmap\""
+
+/**
+ * Enumeration for keeping a DnD state.
+ */
+typedef enum
+{
+ VBOXDNDSTATE_UNKNOWN = 0,
+ VBOXDNDSTATE_ENTERED,
+ VBOXDNDSTATE_LEFT,
+ VBOXDNDSTATE_QUERY_FORMATS,
+ VBOXDNDSTATE_QUERY_STATUS,
+ VBOXDNDSTATE_DRAGGING,
+ VBOXDNDSTATE_DROP_STARTED,
+ VBOXDNDSTATE_DROP_ENDED,
+ VBOXDNDSTATE_CANCELLED,
+ VBOXDNDSTATE_ERROR
+} VBOXDNDSTATE;
+/** Pointer to a DnD state. */
+typedef VBOXDNDSTATE *PVBOXDNDSTATE;
+
+#endif /* !VBOX_INCLUDED_GuestHost_DragAndDropDefs_h */
+
diff --git a/include/VBox/GuestHost/GuestControl.h b/include/VBox/GuestHost/GuestControl.h
new file mode 100644
index 00000000..3ecbc0a3
--- /dev/null
+++ b/include/VBox/GuestHost/GuestControl.h
@@ -0,0 +1,236 @@
+/* $Id: GuestControl.h $ */
+/** @file
+ * Guest Control - Common Guest and Host Code.
+ *
+ * @todo r=bird: Just merge this with GuestControlSvc.h!
+ */
+
+/*
+ * Copyright (C) 2016-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_GuestHost_GuestControl_h
+#define VBOX_INCLUDED_GuestHost_GuestControl_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+
+/* Everything defined in this file lives in this namespace. */
+namespace guestControl {
+
+/**
+ * Process status when executed in the guest.
+ */
+enum eProcessStatus
+{
+ /** Process is in an undefined state. */
+ PROC_STS_UNDEFINED = 0,
+ /** Process has been started. */
+ PROC_STS_STARTED = 1,
+ /** Process terminated normally. */
+ PROC_STS_TEN = 2,
+ /** Process terminated via signal. */
+ PROC_STS_TES = 3,
+ /** Process terminated abnormally. */
+ PROC_STS_TEA = 4,
+ /** Process timed out and was killed. */
+ PROC_STS_TOK = 5,
+ /** Process timed out and was not killed successfully. */
+ PROC_STS_TOA = 6,
+ /** Service/OS is stopping, process was killed. */
+ PROC_STS_DWN = 7,
+ /** Something went wrong (error code in flags). */
+ PROC_STS_ERROR = 8
+};
+
+/**
+ * Input flags, set by the host. This is needed for
+ * handling flags on the guest side.
+ * Note: Has to match Main's ProcessInputFlag_* flags!
+ */
+#define GUEST_PROC_IN_FLAG_NONE 0x0
+#define GUEST_PROC_IN_FLAG_EOF RT_BIT(0)
+
+/**
+ * Guest session creation flags.
+ * Only handled internally at the moment.
+ */
+#define SESSIONCREATIONFLAG_NONE 0x0
+
+/** @name DIRREMOVEREC_FLAG_XXX - Guest directory removement flags.
+ * Essentially using what IPRT's RTDIRRMREC_F_
+ * defines have to offer.
+ * @{
+ */
+/** No remove flags specified. */
+#define DIRREMOVEREC_FLAG_NONE UINT32_C(0x0)
+/** Recursively deletes the directory contents. */
+#define DIRREMOVEREC_FLAG_RECURSIVE RT_BIT(0)
+/** Delete the content of the directory and the directory itself. */
+#define DIRREMOVEREC_FLAG_CONTENT_AND_DIR RT_BIT(1)
+/** Only delete the content of the directory, omit the directory it self. */
+#define DIRREMOVEREC_FLAG_CONTENT_ONLY RT_BIT(2)
+/** Mask of valid flags. */
+#define DIRREMOVEREC_FLAG_VALID_MASK UINT32_C(0x00000007)
+/** @} */
+
+/** @name GUEST_PROC_CREATE_FLAG_XXX - Guest process creation flags.
+ * @note Has to match Main's ProcessCreateFlag_* flags!
+ * @{
+ */
+#define GUEST_PROC_CREATE_FLAG_NONE UINT32_C(0x0)
+#define GUEST_PROC_CREATE_FLAG_WAIT_START RT_BIT(0)
+#define GUEST_PROC_CREATE_FLAG_IGNORE_ORPHANED RT_BIT(1)
+#define GUEST_PROC_CREATE_FLAG_HIDDEN RT_BIT(2)
+#define GUEST_PROC_CREATE_FLAG_PROFILE RT_BIT(3)
+#define GUEST_PROC_CREATE_FLAG_WAIT_STDOUT RT_BIT(4)
+#define GUEST_PROC_CREATE_FLAG_WAIT_STDERR RT_BIT(5)
+#define GUEST_PROC_CREATE_FLAG_EXPAND_ARGUMENTS RT_BIT(6)
+#define GUEST_PROC_CREATE_FLAG_UNQUOTED_ARGS RT_BIT(7)
+/** @} */
+
+/** @name GUEST_PROC_OUT_H_XXX - Pipe handle IDs used internally for referencing
+ * to a certain pipe buffer.
+ * @{
+ */
+#define GUEST_PROC_OUT_H_STDOUT_DEPRECATED 0 /**< Needed for VBox hosts < 4.1.0. */
+#define GUEST_PROC_OUT_H_STDOUT 1
+#define GUEST_PROC_OUT_H_STDERR 2
+/** @} */
+
+/** @name PATHRENAME_FLAG_XXX - Guest path rename flags.
+ * Essentially using what IPRT's RTPATHRENAME_FLAGS_XXX have to offer.
+ * @{
+ */
+/** Do not replace anything. */
+#define PATHRENAME_FLAG_NO_REPLACE UINT32_C(0)
+/** This will replace attempt any target which isn't a directory. */
+#define PATHRENAME_FLAG_REPLACE RT_BIT(0)
+/** Don't allow symbolic links as part of the path. */
+#define PATHRENAME_FLAG_NO_SYMLINKS RT_BIT(1)
+/** Mask of valid flags. */
+#define PATHRENAME_FLAG_VALID_MASK UINT32_C(0x00000003)
+/** @} */
+
+/** @name GUEST_SHUTDOWN_FLAG_XXX - Guest shutdown flags.
+ * Must match Main's GuestShutdownFlag_ definitions.
+ * @{
+ */
+#define GUEST_SHUTDOWN_FLAG_NONE UINT32_C(0)
+#define GUEST_SHUTDOWN_FLAG_POWER_OFF RT_BIT(0)
+#define GUEST_SHUTDOWN_FLAG_REBOOT RT_BIT(1)
+#define GUEST_SHUTDOWN_FLAG_FORCE RT_BIT(2)
+/** @} */
+
+/** @name Defines for default (initial) guest process buffer lengths.
+ * Note: These defaults were the maximum values before; so be careful when raising those in order to
+ * not break running with older Guest Additions.
+ * @{
+ */
+#define GUEST_PROC_DEF_CMD_LEN _1K
+#define GUEST_PROC_DEF_ARGS_LEN _1K
+#define GUEST_PROC_DEF_ENV_LEN _1K
+#define GUEST_PROC_DEF_USER_LEN 128
+#define GUEST_PROC_DEF_PASSWORD_LEN 128
+#define GUEST_PROC_DEF_DOMAIN_LEN 256
+/** @} */
+
+/** @name Defines for maximum guest process buffer lengths.
+ * @{
+ */
+#define GUEST_PROC_MAX_CMD_LEN _1M
+#define GUEST_PROC_MAX_ARGS_LEN _2M
+#define GUEST_PROC_MAX_ENV_LEN _4M
+#define GUEST_PROC_MAX_USER_LEN _64K
+#define GUEST_PROC_MAX_PASSWORD_LEN _64K
+#define GUEST_PROC_MAX_DOMAIN_LEN _64K
+/** @} */
+
+/** @name Internal tools built into VBoxService which are used in order
+ * to accomplish tasks host<->guest.
+ * @{
+ */
+#define VBOXSERVICE_TOOL_CAT "vbox_cat"
+#define VBOXSERVICE_TOOL_LS "vbox_ls"
+#define VBOXSERVICE_TOOL_RM "vbox_rm"
+#define VBOXSERVICE_TOOL_MKDIR "vbox_mkdir"
+#define VBOXSERVICE_TOOL_MKTEMP "vbox_mktemp"
+#define VBOXSERVICE_TOOL_STAT "vbox_stat"
+/** @} */
+
+/** Special process exit codes for "vbox_cat". */
+typedef enum VBOXSERVICETOOLBOX_CAT_EXITCODE
+{
+ VBOXSERVICETOOLBOX_CAT_EXITCODE_ACCESS_DENIED = RTEXITCODE_END,
+ VBOXSERVICETOOLBOX_CAT_EXITCODE_FILE_NOT_FOUND,
+ VBOXSERVICETOOLBOX_CAT_EXITCODE_PATH_NOT_FOUND,
+ VBOXSERVICETOOLBOX_CAT_EXITCODE_SHARING_VIOLATION,
+ VBOXSERVICETOOLBOX_CAT_EXITCODE_IS_A_DIRECTORY,
+ /** The usual 32-bit type hack. */
+ VBOXSERVICETOOLBOX_CAT_32BIT_HACK = 0x7fffffff
+} VBOXSERVICETOOLBOX_CAT_EXITCODE;
+
+/** Special process exit codes for "vbox_stat". */
+typedef enum VBOXSERVICETOOLBOX_STAT_EXITCODE
+{
+ VBOXSERVICETOOLBOX_STAT_EXITCODE_ACCESS_DENIED = RTEXITCODE_END,
+ VBOXSERVICETOOLBOX_STAT_EXITCODE_FILE_NOT_FOUND,
+ VBOXSERVICETOOLBOX_STAT_EXITCODE_PATH_NOT_FOUND,
+ VBOXSERVICETOOLBOX_STAT_EXITCODE_NET_PATH_NOT_FOUND,
+ VBOXSERVICETOOLBOX_STAT_EXITCODE_INVALID_NAME,
+ /** The usual 32-bit type hack. */
+ VBOXSERVICETOOLBOX_STAT_32BIT_HACK = 0x7fffffff
+} VBOXSERVICETOOLBOX_STAT_EXITCODE;
+
+/**
+ * Input status, reported by the client.
+ */
+enum eInputStatus
+{
+ /** Input is in an undefined state. */
+ INPUT_STS_UNDEFINED = 0,
+ /** Input was written (partially, see cbProcessed). */
+ INPUT_STS_WRITTEN = 1,
+ /** Input failed with an error (see flags for rc). */
+ INPUT_STS_ERROR = 20,
+ /** Process has abandoned / terminated input handling. */
+ INPUT_STS_TERMINATED = 21,
+ /** Too much input data. */
+ INPUT_STS_OVERFLOW = 30
+};
+
+
+
+} /* namespace guestControl */
+
+#endif /* !VBOX_INCLUDED_GuestHost_GuestControl_h */
+
diff --git a/include/VBox/GuestHost/HGCMMock.h b/include/VBox/GuestHost/HGCMMock.h
new file mode 100644
index 00000000..3aabed57
--- /dev/null
+++ b/include/VBox/GuestHost/HGCMMock.h
@@ -0,0 +1,804 @@
+/* $Id: HGCMMock.h $ */
+/** @file
+ * HGCMMock.h: Mocking framework for testing HGCM-based host services +
+ * Vbgl code on the host side.
+ *
+ * Goal is to run host service + Vbgl code as unmodified as
+ * possible as part of testcases to gain test coverage which
+ * otherwise wouldn't possible for heavily user-centric features
+ * like Shared Clipboard or drag'n drop (DnD).
+ */
+
+/*
+ * Copyright (C) 2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_GuestHost_HGCMMock_h
+#define VBOX_INCLUDED_GuestHost_HGCMMock_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+
+#include <iprt/asm.h>
+#include <iprt/assert.h>
+#include <iprt/list.h>
+#include <iprt/mem.h>
+#include <iprt/rand.h>
+#include <iprt/semaphore.h>
+#include <iprt/test.h>
+#include <iprt/time.h>
+#include <iprt/thread.h>
+#include <iprt/utf16.h>
+
+#include <VBox/err.h>
+#include <VBox/VBoxGuestLib.h>
+#include <VBox/hgcmsvc.h>
+
+
+/*********************************************************************************************************************************
+* Definitions. *
+*********************************************************************************************************************************/
+
+#if defined(IN_RING3) /* Only R3 parts implemented so far. */
+
+RT_C_DECLS_BEGIN
+
+DECLCALLBACK(DECLEXPORT(int)) VBoxHGCMSvcLoad(VBOXHGCMSVCFNTABLE *ptable);
+
+RT_C_DECLS_END
+
+# define VBGLR3DECL(type) DECL_HIDDEN_NOTHROW(type) VBOXCALL
+
+/** Simple call handle structure for the guest call completion callback. */
+typedef struct VBOXHGCMCALLHANDLE_TYPEDEF
+{
+ /** Where to store the result code on call completion. */
+ int32_t rc;
+} VBOXHGCMCALLHANDLE_TYPEDEF;
+
+/**
+ * Enumeration for a HGCM mock function type.
+ */
+typedef enum TSTHGCMMOCKFNTYPE
+{
+ TSTHGCMMOCKFNTYPE_NONE = 0,
+ TSTHGCMMOCKFNTYPE_CONNECT,
+ TSTHGCMMOCKFNTYPE_DISCONNECT,
+ TSTHGCMMOCKFNTYPE_CALL,
+ TSTHGCMMOCKFNTYPE_HOST_CALL
+} TSTHGCMMOCKFNTYPE;
+
+/** Pointer to a mock HGCM service. */
+typedef struct TSTHGCMMOCKSVC *PTSTHGCMMOCKSVC;
+
+/**
+ * Structure for mocking a server-side HGCM client.
+ */
+typedef struct TSTHGCMMOCKCLIENT
+{
+ /** Pointer to to mock service instance this client belongs to. */
+ PTSTHGCMMOCKSVC pSvc;
+ /** Assigned HGCM client ID. */
+ uint32_t idClient;
+ /** Opaque pointer to service-specific client data.
+ * Can be NULL if not being used. */
+ void *pvClient;
+ /** Size (in bytes) of \a pvClient. */
+ size_t cbClient;
+ /** The client's current HGCM call handle. */
+ VBOXHGCMCALLHANDLE_TYPEDEF hCall;
+ /** Whether the current client call has an asynchronous
+ * call pending or not. */
+ bool fAsyncExec;
+ /** Event semaphore to signal call completion. */
+ RTSEMEVENT hEvent;
+} TSTHGCMMOCKCLIENT;
+/** Pointer to a mock HGCM client. */
+typedef TSTHGCMMOCKCLIENT *PTSTHGCMMOCKCLIENT;
+
+/**
+ * Structure for keeping HGCM mock function parameters.
+ */
+typedef struct TSTHGCMMOCKFN
+{
+ /** List node for storing this struct into a queue. */
+ RTLISTNODE Node;
+ /** Function type. */
+ TSTHGCMMOCKFNTYPE enmType;
+ /** Pointer to associated client. */
+ PTSTHGCMMOCKCLIENT pClient;
+ /** Union keeping function-specific parameters,
+ * depending on \a enmType. */
+ union
+ {
+ struct
+ {
+ int32_t iFunc;
+ uint32_t cParms;
+ PVBOXHGCMSVCPARM pParms;
+ VBOXHGCMCALLHANDLE hCall;
+ } Call;
+ struct
+ {
+ int32_t iFunc;
+ uint32_t cParms;
+ PVBOXHGCMSVCPARM pParms;
+ } HostCall;
+ } u;
+} TSTHGCMMOCKFN;
+/** Pointer to a HGCM mock function parameters structure. */
+typedef TSTHGCMMOCKFN *PTSTHGCMMOCKFN;
+
+/**
+ * Structure for keeping a HGCM mock service instance.
+ */
+typedef struct TSTHGCMMOCKSVC
+{
+ /** HGCM helper table to use. */
+ VBOXHGCMSVCHELPERS fnHelpers;
+ /** HGCM service function table to use. */
+ VBOXHGCMSVCFNTABLE fnTable;
+ /** Next HGCM client ID to assign.
+ * 0 is considered as being invalid. */
+ HGCMCLIENTID uNextClientId;
+ /** Size (in bytes) of opaque pvClient area to reserve
+ * for a connected client. */
+ size_t cbClient;
+ /** Array of connected HGCM mock clients.
+ * Currently limited to 4 clients maximum. */
+ TSTHGCMMOCKCLIENT aHgcmClient[4];
+ /** Thread handle for the service's main loop. */
+ RTTHREAD hThread;
+ /** Event semaphore for signalling a message
+ * queue change. */
+ RTSEMEVENT hEventQueue;
+ /** Event semaphore for clients connecting to the server. */
+ RTSEMEVENT hEventConnect;
+ /** Number of current host calls being served.
+ * Currently limited to one call at a time. */
+ uint8_t cHostCallers;
+ /** Result code of last returned host call. */
+ int rcHostCall;
+ /** Event semaphore for host calls. */
+ RTSEMEVENT hEventHostCall;
+ /** List (queue) of function calls to process. */
+ RTLISTANCHOR lstCall;
+ /** Shutdown indicator flag. */
+ volatile bool fShutdown;
+} TSTHGCMMOCKSVC;
+
+/** Static HGCM service to mock. */
+static TSTHGCMMOCKSVC s_tstHgcmSvc;
+
+/*********************************************************************************************************************************
+* Prototypes. *
+*********************************************************************************************************************************/
+PTSTHGCMMOCKSVC TstHgcmMockSvcInst(void);
+PTSTHGCMMOCKCLIENT TstHgcmMockSvcWaitForConnectEx(PTSTHGCMMOCKSVC pSvc, RTMSINTERVAL msTimeout);
+PTSTHGCMMOCKCLIENT TstHgcmMockSvcWaitForConnect(PTSTHGCMMOCKSVC pSvc);
+int TstHgcmMockSvcCreate(PTSTHGCMMOCKSVC pSvc, size_t cbClient);
+int TstHgcmMockSvcDestroy(PTSTHGCMMOCKSVC pSvc);
+int TstHgcmMockSvcStart(PTSTHGCMMOCKSVC pSvc);
+int TstHgcmMockSvcStop(PTSTHGCMMOCKSVC pSvc);
+
+int TstHgcmMockSvcHostCall(PTSTHGCMMOCKSVC pSvc, void *pvService, int32_t function, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
+
+VBGLR3DECL(int) VbglR3HGCMConnect(const char *pszServiceName, HGCMCLIENTID *pidClient);
+VBGLR3DECL(int) VbglR3HGCMDisconnect(HGCMCLIENTID idClient);
+VBGLR3DECL(int) VbglR3HGCMCall(PVBGLIOCHGCMCALL pInfo, size_t cbInfo);
+
+
+
+/*********************************************************************************************************************************
+* Internal functions *
+*********************************************************************************************************************************/
+
+/**
+ * Initializes a HGCM mock client.
+ *
+ * @return VBox status code.
+ * @param pClient Client instance to initialize.
+ * @param idClient HGCM client ID to assign.
+ * @param cbClient Size (in bytes) of service-specific (opaque) client data to allocate.
+ */
+static int tstHgcmMockClientInit(PTSTHGCMMOCKCLIENT pClient, uint32_t idClient, size_t cbClient)
+{
+ RT_BZERO(pClient, sizeof(TSTHGCMMOCKCLIENT));
+
+ pClient->idClient = idClient;
+ if (cbClient)
+ {
+ pClient->pvClient = RTMemAllocZ(cbClient);
+ AssertPtrReturn(pClient->pvClient, VERR_NO_MEMORY);
+ pClient->cbClient = cbClient;
+ }
+
+ return RTSemEventCreate(&pClient->hEvent);
+}
+
+/**
+ * Destroys a HGCM mock client.
+ *
+ * @return VBox status code.
+ * @param pClient Client instance to destroy.
+ */
+static int tstHgcmMockClientDestroy(PTSTHGCMMOCKCLIENT pClient)
+{
+ int rc = RTSemEventDestroy(pClient->hEvent);
+ if (RT_SUCCESS(rc))
+ {
+ if (pClient->pvClient)
+ {
+ Assert(pClient->cbClient);
+ RTMemFree(pClient->pvClient);
+ pClient->pvClient = NULL;
+ pClient->cbClient = 0;
+ }
+
+ pClient->hEvent = NIL_RTSEMEVENT;
+ }
+
+ return rc;
+}
+
+/* @copydoc VBOXHGCMSVCFNTABLE::pfnConnect */
+static DECLCALLBACK(int) tstHgcmMockSvcConnect(PTSTHGCMMOCKSVC pSvc, void *pvService, uint32_t *pidClient)
+{
+ RT_NOREF(pvService);
+
+ PTSTHGCMMOCKFN pFn = (PTSTHGCMMOCKFN)RTMemAllocZ(sizeof(TSTHGCMMOCKFN));
+ AssertPtrReturn(pFn, VERR_NO_MEMORY);
+
+ PTSTHGCMMOCKCLIENT pClient = &pSvc->aHgcmClient[pSvc->uNextClientId];
+
+ int rc = tstHgcmMockClientInit(pClient, pSvc->uNextClientId, pSvc->cbClient);
+ if (RT_FAILURE(rc))
+ return rc;
+
+ pFn->enmType = TSTHGCMMOCKFNTYPE_CONNECT;
+ pFn->pClient = pClient;
+
+ RTListAppend(&pSvc->lstCall, &pFn->Node);
+ pFn = NULL; /* Thread takes ownership now. */
+
+ int rc2 = RTSemEventSignal(pSvc->hEventQueue);
+ AssertRCReturn(rc2, rc2);
+ rc2 = RTSemEventWait(pClient->hEvent, RT_MS_30SEC);
+ AssertRCReturn(rc2, rc2);
+
+ ASMAtomicIncU32(&pSvc->uNextClientId);
+
+ rc2 = RTSemEventSignal(pSvc->hEventConnect);
+ AssertRCReturn(rc2, rc2);
+
+ *pidClient = pClient->idClient;
+
+ return VINF_SUCCESS;
+}
+
+/* @copydoc VBOXHGCMSVCFNTABLE::pfnDisconnect */
+static DECLCALLBACK(int) tstHgcmMockSvcDisconnect(PTSTHGCMMOCKSVC pSvc, void *pvService, uint32_t idClient)
+{
+ RT_NOREF(pvService);
+
+ PTSTHGCMMOCKCLIENT pClient = &pSvc->aHgcmClient[idClient];
+
+ PTSTHGCMMOCKFN pFn = (PTSTHGCMMOCKFN)RTMemAllocZ(sizeof(TSTHGCMMOCKFN));
+ AssertPtrReturn(pFn, VERR_NO_MEMORY);
+
+ pFn->enmType = TSTHGCMMOCKFNTYPE_DISCONNECT;
+ pFn->pClient = pClient;
+
+ RTListAppend(&pSvc->lstCall, &pFn->Node);
+ pFn = NULL; /* Thread takes ownership now. */
+
+ int rc2 = RTSemEventSignal(pSvc->hEventQueue);
+ AssertRCReturn(rc2, rc2);
+
+ rc2 = RTSemEventWait(pClient->hEvent, RT_MS_30SEC);
+ AssertRCReturn(rc2, rc2);
+
+ return tstHgcmMockClientDestroy(pClient);
+}
+
+/* @copydoc VBOXHGCMSVCFNTABLE::pfnCall */
+static DECLCALLBACK(int) tstHgcmMockSvcCall(PTSTHGCMMOCKSVC pSvc, void *pvService, VBOXHGCMCALLHANDLE callHandle, uint32_t idClient, void *pvClient,
+ int32_t function, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
+{
+ RT_NOREF(pvService, pvClient);
+
+ PTSTHGCMMOCKCLIENT pClient = &pSvc->aHgcmClient[idClient];
+
+ PTSTHGCMMOCKFN pFn = (PTSTHGCMMOCKFN)RTMemAllocZ(sizeof(TSTHGCMMOCKFN));
+ AssertPtrReturn(pFn, VERR_NO_MEMORY);
+
+ const size_t cbParms = cParms * sizeof(VBOXHGCMSVCPARM);
+
+ pFn->enmType = TSTHGCMMOCKFNTYPE_CALL;
+ pFn->pClient = pClient;
+
+ pFn->u.Call.hCall = callHandle;
+ pFn->u.Call.iFunc = function;
+ pFn->u.Call.pParms = (PVBOXHGCMSVCPARM)RTMemDup(paParms, cbParms);
+ AssertPtrReturn(pFn->u.Call.pParms, VERR_NO_MEMORY);
+ pFn->u.Call.cParms = cParms;
+
+ RTListAppend(&pSvc->lstCall, &pFn->Node);
+
+ int rc2 = RTSemEventSignal(pSvc->hEventQueue);
+ AssertRCReturn(rc2, rc2);
+
+ rc2 = RTSemEventWait(pClient->hEvent, RT_INDEFINITE_WAIT);
+ AssertRCReturn(rc2, rc2);
+
+ memcpy(paParms, pFn->u.Call.pParms, cbParms);
+
+ return VINF_SUCCESS; /** @todo Return host call rc */
+}
+
+/* @copydoc VBOXHGCMSVCFNTABLE::pfnHostCall */
+/** Note: Public for also being able to test host calls via testcases. */
+int TstHgcmMockSvcHostCall(PTSTHGCMMOCKSVC pSvc, void *pvService, int32_t function, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
+{
+ RT_NOREF(pvService);
+ AssertReturn(pSvc->cHostCallers == 0, VERR_WRONG_ORDER); /* Only one host call at a time. */
+
+ pSvc->cHostCallers++;
+
+ PTSTHGCMMOCKFN pFn = (PTSTHGCMMOCKFN)RTMemAllocZ(sizeof(TSTHGCMMOCKFN));
+ AssertPtrReturn(pFn, VERR_INVALID_POINTER);
+
+ pFn->enmType = TSTHGCMMOCKFNTYPE_HOST_CALL;
+ pFn->u.HostCall.iFunc = function;
+ if (cParms)
+ {
+ pFn->u.HostCall.pParms = (PVBOXHGCMSVCPARM)RTMemDup(paParms, cParms * sizeof(VBOXHGCMSVCPARM));
+ AssertPtrReturn(pFn->u.HostCall.pParms, VERR_NO_MEMORY);
+ pFn->u.HostCall.cParms = cParms;
+ }
+
+ RTListAppend(&pSvc->lstCall, &pFn->Node);
+ pFn = NULL; /* Thread takes ownership now. */
+
+ int rc2 = RTSemEventSignal(pSvc->hEventQueue);
+ AssertRC(rc2);
+
+ rc2 = RTSemEventWait(pSvc->hEventHostCall, RT_INDEFINITE_WAIT);
+ AssertRCReturn(rc2, rc2);
+
+ Assert(pSvc->cHostCallers);
+ pSvc->cHostCallers--;
+
+ return pSvc->rcHostCall;
+}
+
+/**
+ * Call completion callback for guest calls.
+ *
+ * @return VBox status code.
+ * @param callHandle Call handle to complete.
+ * @param rc Return code to return to the caller.
+ */
+static DECLCALLBACK(int) tstHgcmMockSvcCallComplete(VBOXHGCMCALLHANDLE callHandle, int32_t rc)
+{
+ PTSTHGCMMOCKSVC pSvc = TstHgcmMockSvcInst();
+
+ size_t i = 0;
+ for (; RT_ELEMENTS(pSvc->aHgcmClient); i++)
+ {
+ PTSTHGCMMOCKCLIENT pClient = &pSvc->aHgcmClient[i];
+ if (&pClient->hCall == callHandle) /* Slow, but works for now. */
+ {
+ if (rc == VINF_HGCM_ASYNC_EXECUTE)
+ {
+ Assert(pClient->fAsyncExec == false);
+ }
+ else /* Complete call + notify client. */
+ {
+ callHandle->rc = rc;
+
+ int rc2 = RTSemEventSignal(pClient->hEvent);
+ AssertRCReturn(rc2, rc2);
+ }
+
+ return VINF_SUCCESS;
+ }
+ }
+
+ return VERR_NOT_FOUND;
+}
+
+/**
+ * Main thread of HGCM mock service.
+ *
+ * @return VBox status code.
+ * @param hThread Thread handle.
+ * @param pvUser User-supplied data of type PTSTHGCMMOCKSVC.
+ */
+static DECLCALLBACK(int) tstHgcmMockSvcThread(RTTHREAD hThread, void *pvUser)
+{
+ RT_NOREF(hThread);
+ PTSTHGCMMOCKSVC pSvc = (PTSTHGCMMOCKSVC)pvUser;
+
+ pSvc->uNextClientId = 0;
+
+ pSvc->fnTable.cbSize = sizeof(pSvc->fnTable);
+ pSvc->fnTable.u32Version = VBOX_HGCM_SVC_VERSION;
+
+ RT_ZERO(pSvc->fnHelpers);
+ pSvc->fnHelpers.pfnCallComplete = tstHgcmMockSvcCallComplete;
+ pSvc->fnTable.pHelpers = &pSvc->fnHelpers;
+
+ int rc = VBoxHGCMSvcLoad(&pSvc->fnTable);
+ if (RT_SUCCESS(rc))
+ {
+ RTThreadUserSignal(hThread);
+
+ for (;;)
+ {
+ rc = RTSemEventWait(pSvc->hEventQueue, 10 /* ms */);
+ if (ASMAtomicReadBool(&pSvc->fShutdown))
+ {
+ rc = VINF_SUCCESS;
+ break;
+ }
+ if (rc == VERR_TIMEOUT)
+ continue;
+
+ PTSTHGCMMOCKFN pFn = RTListGetFirst(&pSvc->lstCall, TSTHGCMMOCKFN, Node);
+ if (pFn)
+ {
+ switch (pFn->enmType)
+ {
+ case TSTHGCMMOCKFNTYPE_CONNECT:
+ {
+ rc = pSvc->fnTable.pfnConnect(pSvc->fnTable.pvService,
+ pFn->pClient->idClient, pFn->pClient->pvClient,
+ VMMDEV_REQUESTOR_USR_NOT_GIVEN /* fRequestor */, false /* fRestoring */);
+
+ int rc2 = RTSemEventSignal(pFn->pClient->hEvent);
+ AssertRC(rc2);
+ break;
+ }
+
+ case TSTHGCMMOCKFNTYPE_DISCONNECT:
+ {
+ rc = pSvc->fnTable.pfnDisconnect(pSvc->fnTable.pvService,
+ pFn->pClient->idClient, pFn->pClient->pvClient);
+
+ int rc2 = RTSemEventSignal(pFn->pClient->hEvent);
+ AssertRC(rc2);
+ break;
+ }
+
+ case TSTHGCMMOCKFNTYPE_CALL:
+ {
+ pSvc->fnTable.pfnCall(NULL, pFn->u.Call.hCall, pFn->pClient->idClient, pFn->pClient->pvClient,
+ pFn->u.Call.iFunc, pFn->u.Call.cParms, pFn->u.Call.pParms, RTTimeMilliTS());
+
+ /* Note: Call will be completed in the call completion callback. */
+ break;
+ }
+
+ case TSTHGCMMOCKFNTYPE_HOST_CALL:
+ {
+ pSvc->rcHostCall = pSvc->fnTable.pfnHostCall(NULL, pFn->u.HostCall.iFunc, pFn->u.HostCall.cParms, pFn->u.HostCall.pParms);
+
+ int rc2 = RTSemEventSignal(pSvc->hEventHostCall);
+ AssertRC(rc2);
+ break;
+ }
+
+ default:
+ AssertFailed();
+ break;
+ }
+ RTListNodeRemove(&pFn->Node);
+ RTMemFree(pFn);
+ }
+ }
+ }
+
+ return rc;
+}
+
+
+/*********************************************************************************************************************************
+* Public functions *
+*********************************************************************************************************************************/
+
+/**
+ * Returns the pointer to the HGCM mock service instance.
+ *
+ * @return Pointer to HGCM mock service instance.
+ */
+PTSTHGCMMOCKSVC TstHgcmMockSvcInst(void)
+{
+ return &s_tstHgcmSvc;
+}
+
+/**
+ * Waits for a HGCM mock client to connect, extended version.
+ *
+ * @return Pointer to connected client, or NULL if ran into timeout.
+ * @param pSvc HGCM mock service instance.
+ * @param msTimeout Timeout (in ms) to wait for connection.
+ */
+PTSTHGCMMOCKCLIENT TstHgcmMockSvcWaitForConnectEx(PTSTHGCMMOCKSVC pSvc, RTMSINTERVAL msTimeout)
+{
+ int rc = RTSemEventWait(pSvc->hEventConnect, msTimeout);
+ if (RT_SUCCESS(rc))
+ {
+ Assert(pSvc->uNextClientId);
+ return &pSvc->aHgcmClient[pSvc->uNextClientId - 1];
+ }
+ return NULL;
+}
+
+/**
+ * Waits for a HGCM mock client to connect.
+ *
+ * @return Pointer to connected client, or NULL if waiting for connection was aborted.
+ * @param pSvc HGCM mock service instance.
+ */
+PTSTHGCMMOCKCLIENT TstHgcmMockSvcWaitForConnect(PTSTHGCMMOCKSVC pSvc)
+{
+ return TstHgcmMockSvcWaitForConnectEx(pSvc, RT_MS_30SEC);
+}
+
+/**
+ * Creates a HGCM mock service instance.
+ *
+ * @return VBox status code.
+ * @param pSvc HGCM mock service instance to create.
+ * @param cbClient Size (in bytes) of service-specific client data to
+ * allocate for a HGCM mock client.
+ */
+int TstHgcmMockSvcCreate(PTSTHGCMMOCKSVC pSvc, size_t cbClient)
+{
+ AssertReturn(cbClient, VERR_INVALID_PARAMETER);
+
+ RT_ZERO(pSvc->aHgcmClient);
+ pSvc->fShutdown = false;
+ int rc = RTSemEventCreate(&pSvc->hEventQueue);
+ if (RT_SUCCESS(rc))
+ {
+ rc = RTSemEventCreate(&pSvc->hEventHostCall);
+ if (RT_SUCCESS(rc))
+ {
+ rc = RTSemEventCreate(&pSvc->hEventConnect);
+ if (RT_SUCCESS(rc))
+ {
+ RTListInit(&pSvc->lstCall);
+
+ pSvc->cbClient = cbClient;
+ }
+ }
+ }
+
+ return rc;
+}
+
+/**
+ * Destroys a HGCM mock service instance.
+ *
+ * @return VBox status code.
+ * @param pSvc HGCM mock service instance to destroy.
+ */
+int TstHgcmMockSvcDestroy(PTSTHGCMMOCKSVC pSvc)
+{
+ int rc = RTSemEventDestroy(pSvc->hEventQueue);
+ if (RT_SUCCESS(rc))
+ {
+ rc = RTSemEventDestroy(pSvc->hEventHostCall);
+ if (RT_SUCCESS(rc))
+ RTSemEventDestroy(pSvc->hEventConnect);
+ }
+ return rc;
+}
+
+/**
+ * Starts a HGCM mock service instance.
+ *
+ * @return VBox status code.
+ * @param pSvc HGCM mock service instance to start.
+ */
+int TstHgcmMockSvcStart(PTSTHGCMMOCKSVC pSvc)
+{
+ int rc = RTThreadCreate(&pSvc->hThread, tstHgcmMockSvcThread, pSvc, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE,
+ "MockSvc");
+ if (RT_SUCCESS(rc))
+ rc = RTThreadUserWait(pSvc->hThread, RT_MS_30SEC);
+
+ return rc;
+}
+
+/**
+ * Stops a HGCM mock service instance.
+ *
+ * @return VBox status code.
+ * @param pSvc HGCM mock service instance to stop.
+ */
+int TstHgcmMockSvcStop(PTSTHGCMMOCKSVC pSvc)
+{
+ ASMAtomicWriteBool(&pSvc->fShutdown, true);
+
+ int rcThread;
+ int rc = RTThreadWait(pSvc->hThread, RT_MS_30SEC, &rcThread);
+ if (RT_SUCCESS(rc))
+ rc = rcThread;
+ if (RT_SUCCESS(rc))
+ {
+ pSvc->hThread = NIL_RTTHREAD;
+ }
+
+ return rc;
+}
+
+
+/*********************************************************************************************************************************
+* VbglR3 stubs *
+*********************************************************************************************************************************/
+
+/**
+ * Connects to an HGCM mock service.
+ *
+ * @returns VBox status code
+ * @param pszServiceName Name of the host service.
+ * @param pidClient Where to put the client ID on success. The client ID
+ * must be passed to all the other calls to the service.
+ */
+VBGLR3DECL(int) VbglR3HGCMConnect(const char *pszServiceName, HGCMCLIENTID *pidClient)
+{
+ RT_NOREF(pszServiceName);
+
+ PTSTHGCMMOCKSVC pSvc = TstHgcmMockSvcInst();
+
+ return tstHgcmMockSvcConnect(pSvc, pSvc->fnTable.pvService, pidClient);
+}
+
+/**
+ * Disconnect from an HGCM mock service.
+ *
+ * @returns VBox status code.
+ * @param idClient The client id returned by VbglR3HGCMConnect().
+ */
+VBGLR3DECL(int) VbglR3HGCMDisconnect(HGCMCLIENTID idClient)
+{
+ PTSTHGCMMOCKSVC pSvc = TstHgcmMockSvcInst();
+
+ return tstHgcmMockSvcDisconnect(pSvc, pSvc->fnTable.pvService, idClient);
+}
+
+/**
+ * Makes a fully prepared HGCM call to an HGCM mock service.
+ *
+ * @returns VBox status code.
+ * @param pInfo Fully prepared HGCM call info.
+ * @param cbInfo Size of the info. This may sometimes be larger than
+ * what the parameter count indicates because of
+ * parameter changes between versions and such.
+ */
+VBGLR3DECL(int) VbglR3HGCMCall(PVBGLIOCHGCMCALL pInfo, size_t cbInfo)
+{
+ RT_NOREF(cbInfo);
+
+ AssertMsg(pInfo->Hdr.cbIn == cbInfo, ("cbIn=%#x cbInfo=%#zx\n", pInfo->Hdr.cbIn, cbInfo));
+ AssertMsg(pInfo->Hdr.cbOut == cbInfo, ("cbOut=%#x cbInfo=%#zx\n", pInfo->Hdr.cbOut, cbInfo));
+ Assert(sizeof(*pInfo) + pInfo->cParms * sizeof(HGCMFunctionParameter) <= cbInfo);
+
+ HGCMFunctionParameter *offSrcParms = VBGL_HGCM_GET_CALL_PARMS(pInfo);
+ PVBOXHGCMSVCPARM paDstParms = (PVBOXHGCMSVCPARM)RTMemAlloc(pInfo->cParms * sizeof(VBOXHGCMSVCPARM));
+
+ uint16_t i = 0;
+ for (; i < pInfo->cParms; i++)
+ {
+ switch (offSrcParms->type)
+ {
+ case VMMDevHGCMParmType_32bit:
+ {
+ paDstParms[i].type = VBOX_HGCM_SVC_PARM_32BIT;
+ paDstParms[i].u.uint32 = offSrcParms->u.value32;
+ break;
+ }
+
+ case VMMDevHGCMParmType_64bit:
+ {
+ paDstParms[i].type = VBOX_HGCM_SVC_PARM_64BIT;
+ paDstParms[i].u.uint64 = offSrcParms->u.value64;
+ break;
+ }
+
+ case VMMDevHGCMParmType_LinAddr:
+ {
+ paDstParms[i].type = VBOX_HGCM_SVC_PARM_PTR;
+ paDstParms[i].u.pointer.addr = (void *)offSrcParms->u.LinAddr.uAddr;
+ paDstParms[i].u.pointer.size = offSrcParms->u.LinAddr.cb;
+ break;
+ }
+
+ default:
+ AssertFailed();
+ break;
+ }
+
+ offSrcParms++;
+ }
+
+ PTSTHGCMMOCKSVC const pSvc = TstHgcmMockSvcInst();
+
+ int rc2 = tstHgcmMockSvcCall(pSvc, pSvc->fnTable.pvService, &pSvc->aHgcmClient[pInfo->u32ClientID].hCall,
+ pInfo->u32ClientID, pSvc->aHgcmClient[pInfo->u32ClientID].pvClient,
+ pInfo->u32Function, pInfo->cParms, paDstParms);
+ if (RT_SUCCESS(rc2))
+ {
+ offSrcParms = VBGL_HGCM_GET_CALL_PARMS(pInfo);
+
+ for (i = 0; i < pInfo->cParms; i++)
+ {
+ paDstParms[i].type = offSrcParms->type;
+ switch (paDstParms[i].type)
+ {
+ case VMMDevHGCMParmType_32bit:
+ offSrcParms->u.value32 = paDstParms[i].u.uint32;
+ break;
+
+ case VMMDevHGCMParmType_64bit:
+ offSrcParms->u.value64 = paDstParms[i].u.uint64;
+ break;
+
+ case VMMDevHGCMParmType_LinAddr:
+ {
+ offSrcParms->u.LinAddr.cb = paDstParms[i].u.pointer.size;
+ break;
+ }
+
+ default:
+ AssertFailed();
+ break;
+ }
+
+ offSrcParms++;
+ }
+ }
+
+ RTMemFree(paDstParms);
+
+ if (RT_SUCCESS(rc2))
+ rc2 = pSvc->aHgcmClient[pInfo->u32ClientID].hCall.rc;
+
+ return rc2;
+}
+
+#endif /* IN_RING3 */
+
+#endif /* !VBOX_INCLUDED_GuestHost_HGCMMock_h */
diff --git a/include/VBox/GuestHost/HGCMMockUtils.h b/include/VBox/GuestHost/HGCMMockUtils.h
new file mode 100644
index 00000000..8eb9f943
--- /dev/null
+++ b/include/VBox/GuestHost/HGCMMockUtils.h
@@ -0,0 +1,428 @@
+/* $Id */
+/** @file
+ * HGCMMockUtils.h: Utility functions for the HGCM Mocking framework.
+ *
+ * The utility functions are optional to the actual HGCM Mocking framework and
+ * can support testcases which require a more advanced setup.
+ *
+ * With this one can setup host and guest side threads, which in turn can simulate
+ * specific host (i.e. HGCM service) + guest (i.e. like in the Guest Addditions
+ * via VbglR3) scenarios.
+ *
+ * Glossary:
+ *
+ * Host thread:
+ * - The host thread is used as part of the actual HGCM service being tested and
+ * provides callbacks (@see TSTHGCMUTILSHOSTCALLBACKS) for the unit test.
+ * Guest thread:
+ * - The guest thread is used as part of the guest side and mimics
+ * VBoxClient / VBoxTray / VBoxService parts. (i.e. for VbglR3 calls).
+ * Task:
+ * - A task is the simplest unit of test execution and used between the guest
+ * and host mocking threads.
+ *
+ ** @todo Add TstHGCMSimpleHost / TstHGCMSimpleGuest wrappers along those lines:
+ * Callback.pfnOnClientConnected = tstOnHostClientConnected()
+ * TstHGCMSimpleHostInitAndStart(&Callback)
+ * Callback.pfnOnConnected = tstOnGuestConnected()
+ * TstHGCMSimpleClientInitAndStart(&Callback)
+ */
+
+/*
+ * Copyright (C) 2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_GuestHost_HGCMMockUtils_h
+#define VBOX_INCLUDED_GuestHost_HGCMMockUtils_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/err.h>
+#include <iprt/semaphore.h>
+#include <iprt/thread.h>
+#include <iprt/types.h>
+
+
+#include <VBox/GuestHost/HGCMMock.h>
+#include <VBox/VBoxGuestLib.h>
+
+
+#if defined(IN_RING3) /* Only R3 parts implemented so far. */
+
+/** Pointer to a HGCM Mock utils context. */
+typedef struct TSTHGCMUTILSCTX *PTSTHGCMUTILSCTX;
+
+/**
+ * Structure for keeping a HGCM Mock utils host service callback table.
+ */
+typedef struct TSTHGCMUTILSHOSTCALLBACKS
+{
+ DECLCALLBACKMEMBER(int, pfnOnClientConnected,(PTSTHGCMUTILSCTX pCtx, PTSTHGCMMOCKCLIENT pClient, void *pvUser));
+} TSTHGCMUTILSHOSTCALLBACKS;
+/** Pointer to a HGCM Mock utils host callbacks table. */
+typedef TSTHGCMUTILSHOSTCALLBACKS *PTSTHGCMUTILSHOSTCALLBACKS;
+
+/**
+ * Structure for keeping a generic HGCM Mock utils task.
+ *
+ * A task is a single test unit / entity.
+ */
+typedef struct TSTHGCMUTILSTASK
+{
+ /** Completion event. */
+ RTSEMEVENT hEvent;
+ /** Completion rc.
+ * Set to VERR_IPE_UNINITIALIZED_STATUS if not completed yet. */
+ int rcCompleted;
+ /** Expected completion rc. */
+ int rcExpected;
+ /** Pointer to opaque (testcase-specific) task parameters.
+ * Might be NULL if not needed / used. */
+ void *pvUser;
+} TSTHGCMUTILSTASK;
+/** Pointer to a HGCM Mock utils task. */
+typedef TSTHGCMUTILSTASK *PTSTHGCMUTILSTASK;
+
+/** Callback function for HGCM Mock utils threads. */
+typedef DECLCALLBACKTYPE(int, FNTSTHGCMUTILSTHREAD,(PTSTHGCMUTILSCTX pCtx, void *pvUser));
+/** Pointer to a HGCM Mock utils guest thread callback. */
+typedef FNTSTHGCMUTILSTHREAD *PFNTSTHGCMUTILSTHREAD;
+
+/**
+ * Structure for keeping a HGCM Mock utils context.
+ */
+typedef struct TSTHGCMUTILSCTX
+{
+ /** Pointer to the HGCM Mock service instance to use. */
+ PTSTHGCMMOCKSVC pSvc;
+ /** Currently we only support one task at a time. */
+ TSTHGCMUTILSTASK Task;
+ struct
+ {
+ RTTHREAD hThread;
+ volatile bool fShutdown;
+ PFNTSTHGCMUTILSTHREAD pfnThread;
+ void *pvUser;
+ } Guest;
+ struct
+ {
+ RTTHREAD hThread;
+ volatile bool fShutdown;
+ TSTHGCMUTILSHOSTCALLBACKS Callbacks;
+ void *pvUser;
+ } Host;
+} TSTHGCMUTILSCTX;
+
+
+/*********************************************************************************************************************************
+* Prototypes. *
+*********************************************************************************************************************************/
+/** @name Context handling.
+ * @{ */
+void TstHGCMUtilsCtxInit(PTSTHGCMUTILSCTX pCtx, PTSTHGCMMOCKSVC pSvc);
+/** @} */
+
+/** @name Task handling.
+ * @{ */
+PTSTHGCMUTILSTASK TstHGCMUtilsTaskGetCurrent(PTSTHGCMUTILSCTX pCtx);
+int TstHGCMUtilsTaskInit(PTSTHGCMUTILSTASK pTask);
+void TstHGCMUtilsTaskDestroy(PTSTHGCMUTILSTASK pTask);
+int TstHGCMUtilsTaskWait(PTSTHGCMUTILSTASK pTask, RTMSINTERVAL msTimeout);
+bool TstHGCMUtilsTaskOk(PTSTHGCMUTILSTASK pTask);
+bool TstHGCMUtilsTaskCompleted(PTSTHGCMUTILSTASK pTask);
+void TstHGCMUtilsTaskSignal(PTSTHGCMUTILSTASK pTask, int rc);
+/** @} */
+
+/** @name Threading.
+ * @{ */
+int TstHGCMUtilsGuestThreadStart(PTSTHGCMUTILSCTX pCtx, PFNTSTHGCMUTILSTHREAD pFnThread, void *pvUser);
+int TstHGCMUtilsGuestThreadStop(PTSTHGCMUTILSCTX pCtx);
+int TstHGCMUtilsHostThreadStart(PTSTHGCMUTILSCTX pCtx, PTSTHGCMUTILSHOSTCALLBACKS pCallbacks, void *pvUser);
+int TstHGCMUtilsHostThreadStop(PTSTHGCMUTILSCTX pCtx);
+/** @} */
+
+
+/*********************************************************************************************************************************
+ * Context *
+ ********************************************************************************************************************************/
+/**
+ * Initializes a HGCM Mock utils context.
+ *
+ * @param pCtx Context to intiialize.
+ * @param pSvc HGCM Mock service instance to use.
+ */
+void TstHGCMUtilsCtxInit(PTSTHGCMUTILSCTX pCtx, PTSTHGCMMOCKSVC pSvc)
+{
+ RT_BZERO(pCtx, sizeof(TSTHGCMUTILSCTX));
+
+ pCtx->pSvc = pSvc;
+}
+
+
+/*********************************************************************************************************************************
+ * Tasks *
+ ********************************************************************************************************************************/
+/**
+ * Returns the current task of a HGCM Mock utils context.
+ *
+ * @returns Current task of a HGCM Mock utils context. NULL if no current task found.
+ * @param pCtx HGCM Mock utils context.
+ */
+PTSTHGCMUTILSTASK TstHGCMUtilsTaskGetCurrent(PTSTHGCMUTILSCTX pCtx)
+{
+ /* Currently we only support one task at a time. */
+ return &pCtx->Task;
+}
+
+/**
+ * Initializes a HGCM Mock utils task.
+ *
+ * @returns VBox status code.
+ * @param pTask Task to initialize.
+ */
+int TstHGCMUtilsTaskInit(PTSTHGCMUTILSTASK pTask)
+{
+ pTask->pvUser = NULL;
+ pTask->rcCompleted = pTask->rcExpected = VERR_IPE_UNINITIALIZED_STATUS;
+ return RTSemEventCreate(&pTask->hEvent);
+}
+
+/**
+ * Destroys a HGCM Mock utils task.
+ *
+ * @returns VBox status code.
+ * @param pTask Task to destroy.
+ */
+void TstHGCMUtilsTaskDestroy(PTSTHGCMUTILSTASK pTask)
+{
+ RTSemEventDestroy(pTask->hEvent);
+}
+
+/**
+ * Waits for a HGCM Mock utils task to complete.
+ *
+ * @returns VBox status code.
+ * @param pTask Task to wait for.
+ * @param msTimeout Timeout (in ms) to wait.
+ */
+int TstHGCMUtilsTaskWait(PTSTHGCMUTILSTASK pTask, RTMSINTERVAL msTimeout)
+{
+ return RTSemEventWait(pTask->hEvent, msTimeout);
+}
+
+/**
+ * Returns if the HGCM Mock utils task has been completed successfully.
+ *
+ * @returns \c true if successful, \c false if not.
+ * @param pTask Task to check.
+ */
+bool TstHGCMUtilsTaskOk(PTSTHGCMUTILSTASK pTask)
+{
+ return pTask->rcCompleted == pTask->rcExpected;
+}
+
+/**
+ * Returns if the HGCM Mock utils task has been completed (failed or succeeded).
+ *
+ * @returns \c true if completed, \c false if (still) running.
+ * @param pTask Task to check.
+ */
+bool TstHGCMUtilsTaskCompleted(PTSTHGCMUTILSTASK pTask)
+{
+ return pTask->rcCompleted != VERR_IPE_UNINITIALIZED_STATUS;
+}
+
+/**
+ * Signals a HGCM Mock utils task to complete its operation.
+ *
+ * @param pTask Task to complete.
+ * @param rc Task result to set for completion.
+ */
+void TstHGCMUtilsTaskSignal(PTSTHGCMUTILSTASK pTask, int rc)
+{
+ AssertMsg(pTask->rcCompleted == VERR_IPE_UNINITIALIZED_STATUS, ("Task already completed\n"));
+ pTask->rcCompleted = rc;
+ int rc2 = RTSemEventSignal(pTask->hEvent);
+ AssertRC(rc2);
+}
+
+
+/*********************************************************************************************************************************
+ * Threading *
+ ********************************************************************************************************************************/
+
+/**
+ * Thread worker for the guest side thread.
+ *
+ * @returns VBox status code.
+ * @param hThread Thread handle.
+ * @param pvUser Pointer of type PTSTHGCMUTILSCTX.
+ *
+ * @note Runs in the guest thread.
+ */
+static DECLCALLBACK(int) tstHGCMUtilsGuestThread(RTTHREAD hThread, void *pvUser)
+{
+ RT_NOREF(hThread);
+ PTSTHGCMUTILSCTX pCtx = (PTSTHGCMUTILSCTX)pvUser;
+ AssertPtr(pCtx);
+
+ RTThreadUserSignal(hThread);
+
+ if (pCtx->Guest.pfnThread)
+ return pCtx->Guest.pfnThread(pCtx, pCtx->Guest.pvUser);
+
+ return VINF_SUCCESS;
+}
+
+/**
+ * Starts the guest side thread.
+ *
+ * @returns VBox status code.
+ * @param pCtx HGCM Mock utils context to start guest thread for.
+ * @param pFnThread Pointer to custom thread worker function to call within the guest side thread.
+ * @param pvUser User-supplied pointer to guest thread context data. Optional and can be NULL.
+ */
+int TstHGCMUtilsGuestThreadStart(PTSTHGCMUTILSCTX pCtx, PFNTSTHGCMUTILSTHREAD pFnThread, void *pvUser)
+{
+ pCtx->Guest.pfnThread = pFnThread;
+ pCtx->Guest.pvUser = pvUser;
+
+ int rc = RTThreadCreate(&pCtx->Guest.hThread, tstHGCMUtilsGuestThread, pCtx, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE,
+ "tstShClGst");
+ if (RT_SUCCESS(rc))
+ rc = RTThreadUserWait(pCtx->Guest.hThread, RT_MS_30SEC);
+
+ return rc;
+}
+
+/**
+ * Stops the guest side thread.
+ *
+ * @returns VBox status code.
+ * @param pCtx HGCM Mock utils context to stop guest thread for.
+ */
+int TstHGCMUtilsGuestThreadStop(PTSTHGCMUTILSCTX pCtx)
+{
+ ASMAtomicWriteBool(&pCtx->Guest.fShutdown, true);
+
+ int rcThread;
+ int rc = RTThreadWait(pCtx->Guest.hThread, RT_MS_30SEC, &rcThread);
+ if (RT_SUCCESS(rc))
+ rc = rcThread;
+ if (RT_SUCCESS(rc))
+ pCtx->Guest.hThread = NIL_RTTHREAD;
+
+ return rc;
+}
+
+/**
+ * Thread worker function for the host side HGCM service.
+ *
+ * @returns VBox status code.
+ * @param hThread Thread handle.
+ * @param pvUser Pointer of type PTSTHGCMUTILSCTX.
+ *
+ * @note Runs in the host service thread.
+ */
+static DECLCALLBACK(int) tstHGCMUtilsHostThreadWorker(RTTHREAD hThread, void *pvUser)
+{
+ RT_NOREF(hThread);
+ PTSTHGCMUTILSCTX pCtx = (PTSTHGCMUTILSCTX)pvUser;
+ AssertPtr(pCtx);
+
+ int rc = VINF_SUCCESS;
+
+ RTThreadUserSignal(hThread);
+
+ PTSTHGCMMOCKSVC const pSvc = TstHgcmMockSvcInst();
+
+ for (;;)
+ {
+ if (ASMAtomicReadBool(&pCtx->Host.fShutdown))
+ break;
+
+ /* Wait for a new (mock) HGCM client to connect. */
+ PTSTHGCMMOCKCLIENT pMockClient = TstHgcmMockSvcWaitForConnectEx(pSvc, 100 /* ms */);
+ if (pMockClient) /* Might be NULL when timed out. */
+ {
+ if (pCtx->Host.Callbacks.pfnOnClientConnected)
+ /* ignore rc */ pCtx->Host.Callbacks.pfnOnClientConnected(pCtx, pMockClient, pCtx->Host.pvUser);
+ }
+ }
+
+ return rc;
+}
+
+/**
+ * Starts the host side thread.
+ *
+ * @returns VBox status code.
+ * @param pCtx HGCM Mock utils context to start host thread for.
+ * @param pCallbacks Pointer to host callback table to use.
+ * @param pvUser User-supplied pointer to reach into the host thread callbacks.
+ */
+int TstHGCMUtilsHostThreadStart(PTSTHGCMUTILSCTX pCtx, PTSTHGCMUTILSHOSTCALLBACKS pCallbacks, void *pvUser)
+{
+ memcpy(&pCtx->Host.Callbacks, pCallbacks, sizeof(TSTHGCMUTILSHOSTCALLBACKS));
+ pCtx->Host.pvUser = pvUser;
+
+ int rc = RTThreadCreate(&pCtx->Host.hThread, tstHGCMUtilsHostThreadWorker, pCtx, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE,
+ "tstShClHst");
+ if (RT_SUCCESS(rc))
+ rc = RTThreadUserWait(pCtx->Host.hThread, RT_MS_30SEC);
+
+ return rc;
+}
+
+/**
+ * Stops the host side thread.
+ *
+ * @returns VBox status code.
+ * @param pCtx HGCM Mock utils context to stop host thread for.
+ */
+int TstHGCMUtilsHostThreadStop(PTSTHGCMUTILSCTX pCtx)
+{
+ ASMAtomicWriteBool(&pCtx->Host.fShutdown, true);
+
+ int rcThread;
+ int rc = RTThreadWait(pCtx->Host.hThread, RT_MS_30SEC, &rcThread);
+ if (RT_SUCCESS(rc))
+ rc = rcThread;
+ if (RT_SUCCESS(rc))
+ pCtx->Host.hThread = NIL_RTTHREAD;
+
+ return rc;
+}
+
+#endif /* IN_RING3 */
+
+#endif /* !VBOX_INCLUDED_GuestHost_HGCMMockUtils_h */
+
diff --git a/include/VBox/GuestHost/Makefile.kup b/include/VBox/GuestHost/Makefile.kup
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/include/VBox/GuestHost/Makefile.kup
diff --git a/include/VBox/GuestHost/SharedClipboard-transfers.h b/include/VBox/GuestHost/SharedClipboard-transfers.h
new file mode 100644
index 00000000..32e5b814
--- /dev/null
+++ b/include/VBox/GuestHost/SharedClipboard-transfers.h
@@ -0,0 +1,993 @@
+/* $Id: SharedClipboard-transfers.h $ */
+/** @file
+ * Shared Clipboard - Shared transfer functions between host and guest.
+ */
+
+/*
+ * Copyright (C) 2019-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_GuestHost_SharedClipboard_transfers_h
+#define VBOX_INCLUDED_GuestHost_SharedClipboard_transfers_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <map>
+
+#include <iprt/assert.h>
+#include <iprt/critsect.h>
+#include <iprt/fs.h>
+#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS_HTTP
+# include <iprt/http-server.h>
+#endif
+#include <iprt/list.h>
+
+#include <iprt/cpp/list.h>
+#include <iprt/cpp/ministring.h>
+
+#include <VBox/GuestHost/SharedClipboard.h>
+#include <VBox/HostServices/VBoxClipboardSvc.h>
+
+
+struct SHCLTRANSFER;
+/** Pointer to a single shared clipboard transfer */
+typedef struct SHCLTRANSFER *PSHCLTRANSFER;
+
+
+/** @name Shared Clipboard transfer definitions.
+ * @{
+ */
+
+/** Defines the maximum length (in chars) a Shared Clipboard transfer path can have. */
+#define SHCL_TRANSFER_PATH_MAX RTPATH_MAX
+
+/**
+ * Defines the transfer status codes.
+ */
+typedef enum
+{
+ /** No status set. */
+ SHCLTRANSFERSTATUS_NONE = 0,
+ /** The transfer has been initialized but is not running yet. */
+ SHCLTRANSFERSTATUS_INITIALIZED,
+ /** The transfer is active and running. */
+ SHCLTRANSFERSTATUS_STARTED,
+ /** The transfer has been stopped. */
+ SHCLTRANSFERSTATUS_STOPPED,
+ /** The transfer has been canceled. */
+ SHCLTRANSFERSTATUS_CANCELED,
+ /** The transfer has been killed. */
+ SHCLTRANSFERSTATUS_KILLED,
+ /** The transfer ran into an unrecoverable error. */
+ SHCLTRANSFERSTATUS_ERROR,
+ /** The usual 32-bit hack. */
+ SHCLTRANSFERSTATUS_32BIT_SIZE_HACK = 0x7fffffff
+} SHCLTRANSFERSTATUSENUM;
+
+/** Defines a transfer status. */
+typedef uint32_t SHCLTRANSFERSTATUS;
+
+/** @} */
+
+/** @name Shared Clipboard handles.
+ * @{
+ */
+
+/** A Shared Clipboard list handle. */
+typedef uint64_t SHCLLISTHANDLE;
+/** Pointer to a Shared Clipboard list handle. */
+typedef SHCLLISTHANDLE *PSHCLLISTHANDLE;
+/** Specifies an invalid Shared Clipboard list handle.
+ * @todo r=bird: The convention is NIL_SHCLLISTHANDLE. */
+#define SHCLLISTHANDLE_INVALID ((SHCLLISTHANDLE)UINT64_MAX)
+
+/** A Shared Clipboard object handle. */
+typedef uint64_t SHCLOBJHANDLE;
+/** Pointer to a Shared Clipboard object handle. */
+typedef SHCLOBJHANDLE *PSHCLOBJHANDLE;
+/** Specifies an invalid Shared Clipboard object handle.
+ * @todo r=bird: The convention is NIL_SHCLOBJHANDLE. */
+#define SHCLOBJHANDLE_INVALID ((SHCLOBJHANDLE)UINT64_MAX)
+
+/** @} */
+
+/** @name Shared Clipboard open/create flags.
+ * @{
+ */
+/** No flags. Initialization value. */
+#define SHCL_OBJ_CF_NONE UINT32_C(0x00000000)
+
+#if 0 /* These probably won't be needed either */
+/** Lookup only the object, do not return a handle. All other flags are ignored. */
+#define SHCL_OBJ_CF_LOOKUP UINT32_C(0x00000001)
+/** Create/open a directory. */
+#define SHCL_OBJ_CF_DIRECTORY UINT32_C(0x00000004)
+#endif
+
+/** Read/write requested access for the object. */
+#define SHCL_OBJ_CF_ACCESS_MASK_RW UINT32_C(0x00001000)
+/** No access requested. */
+#define SHCL_OBJ_CF_ACCESS_NONE UINT32_C(0x00000000)
+/** Read access requested. */
+#define SHCL_OBJ_CF_ACCESS_READ UINT32_C(0x00001000)
+
+/** Requested share access for the object. */
+#define SHCL_OBJ_CF_ACCESS_MASK_DENY UINT32_C(0x00008000)
+/** Allow any access. */
+#define SHCL_OBJ_CF_ACCESS_DENYNONE UINT32_C(0x00000000)
+/** Do not allow write. */
+#define SHCL_OBJ_CF_ACCESS_DENYWRITE UINT32_C(0x00008000)
+
+/** Requested access to attributes of the object. */
+#define SHCL_OBJ_CF_ACCESS_MASK_ATTR UINT32_C(0x00010000)
+/** No access requested. */
+#define SHCL_OBJ_CF_ACCESS_ATTR_NONE UINT32_C(0x00000000)
+/** Read access requested. */
+#define SHCL_OBJ_CF_ACCESS_ATTR_READ UINT32_C(0x00010000)
+
+/** Valid bits. */
+#define SHCL_OBJ_CF_VALID_MASK UINT32_C(0x00019000)
+/** @} */
+
+/**
+ * The available additional information in a SHCLFSOBJATTR object.
+ * @sa RTFSOBJATTRADD
+ */
+typedef enum _SHCLFSOBJATTRADD
+{
+ /** No additional information is available / requested. */
+ SHCLFSOBJATTRADD_NOTHING = 1,
+ /** The additional unix attributes (SHCLFSOBJATTR::u::Unix) are
+ * available / requested. */
+ SHCLFSOBJATTRADD_UNIX,
+ /** The additional extended attribute size (SHCLFSOBJATTR::u::EASize) is
+ * available / requested. */
+ SHCLFSOBJATTRADD_EASIZE,
+ /** The last valid item (inclusive).
+ * The valid range is SHCLFSOBJATTRADD_NOTHING thru
+ * SHCLFSOBJATTRADD_LAST. */
+ SHCLFSOBJATTRADD_LAST = SHCLFSOBJATTRADD_EASIZE,
+ /** The usual 32-bit hack. */
+ SHCLFSOBJATTRADD_32BIT_SIZE_HACK = 0x7fffffff
+} SHCLFSOBJATTRADD;
+
+
+/* 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 Clipboard filesystem object attributes.
+ *
+ * @sa RTFSOBJATTR
+ */
+typedef struct _SHCLFSOBJATTR
+{
+ /** 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. */
+ SHCLFSOBJATTRADD enmAdditional;
+
+ /**
+ * Additional attributes.
+ *
+ * Unless explicitly specified to an API, the API can provide additional
+ * data as it is provided by the underlying OS.
+ */
+ union SHCLFSOBJATTRUNION
+ {
+ /** Additional Unix Attributes
+ * These are available when SHCLFSOBJATTRADD is set in fUnix.
+ */
+ struct SHCLFSOBJATTRUNIX
+ {
+ /** 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 SHCLFSOBJATTREASIZE
+ {
+ /** Size of EAs. */
+ RTFOFF cb;
+ } EASize;
+
+ /** Padding the structure to a multiple of 8 bytes. */
+ uint64_t au64Padding[5];
+ } u;
+} SHCLFSOBJATTR;
+AssertCompileSize(SHCLFSOBJATTR, 48);
+/** Pointer to a Shared Clipboard filesystem object attributes structure. */
+typedef SHCLFSOBJATTR *PSHCLFSOBJATTR;
+/** Pointer to a const Shared Clipboard filesystem object attributes structure. */
+typedef const SHCLFSOBJATTR *PCSHCLFSOBJATTR;
+
+/**
+ * Shared Clipboard file system object information structure.
+ *
+ * @sa RTFSOBJINFO
+ */
+typedef struct _SHCLFSOBJINFO
+{
+ /** 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. */
+ SHCLFSOBJATTR Attr;
+
+} SHCLFSOBJINFO;
+AssertCompileSize(SHCLFSOBJINFO, 96);
+/** Pointer to a Shared Clipboard filesystem object information structure. */
+typedef SHCLFSOBJINFO *PSHCLFSOBJINFO;
+/** Pointer to a const Shared Clipboard filesystem object information
+ * structure. */
+typedef const SHCLFSOBJINFO *PCSHCLFSOBJINFO;
+
+/**
+ * Structure for keeping object open/create parameters.
+ */
+typedef struct _SHCLOBJOPENCREATEPARMS
+{
+ /** Path to object to open / create. */
+ char *pszPath;
+ /** Size (in bytes) of path to to object. */
+ uint32_t cbPath;
+ /** SHCL_OBJ_CF_* */
+ uint32_t fCreate;
+ /**
+ * Attributes of object to open/create and
+ * returned actual attributes of opened/created object.
+ */
+ SHCLFSOBJINFO ObjInfo;
+} SHCLOBJOPENCREATEPARMS, *PSHCLOBJOPENCREATEPARMS;
+
+/**
+ * Structure for keeping a reply message.
+ */
+typedef struct _SHCLREPLY
+{
+ /** Message type of type VBOX_SHCL_REPLYMSGTYPE_XXX. */
+ uint32_t uType;
+ /** IPRT result of overall operation. Note: int vs. uint32! */
+ uint32_t rc;
+ union
+ {
+ struct
+ {
+ SHCLTRANSFERSTATUS uStatus;
+ } TransferStatus;
+ struct
+ {
+ SHCLLISTHANDLE uHandle;
+ } ListOpen;
+ struct
+ {
+ SHCLLISTHANDLE uHandle;
+ } ListClose;
+ struct
+ {
+ SHCLOBJHANDLE uHandle;
+ } ObjOpen;
+ struct
+ {
+ SHCLOBJHANDLE uHandle;
+ } ObjClose;
+ } u;
+ /** Pointer to optional payload. */
+ void *pvPayload;
+ /** Payload size (in bytes). */
+ uint32_t cbPayload;
+} SHCLREPLY, *PSHCLREPLY;
+
+struct _SHCLLISTENTRY;
+typedef _SHCLLISTENTRY SHCLLISTENTRY;
+
+/** Defines a single root list entry. Currently the same as a regular list entry. */
+typedef SHCLLISTENTRY SHCLROOTLISTENTRY;
+/** Defines a pointer to a single root list entry. Currently the same as a regular list entry pointer. */
+typedef SHCLROOTLISTENTRY *PSHCLROOTLISTENTRY;
+
+/**
+ * Structure for keeping Shared Clipboard root list headers.
+ */
+typedef struct _SHCLROOTLISTHDR
+{
+ /** Roots listing flags; unused at the moment. */
+ uint32_t fRoots;
+ /** Number of root list entries. */
+ uint32_t cRoots;
+} SHCLROOTLISTHDR, *PSHCLROOTLISTHDR;
+
+/**
+ * Structure for maintaining a Shared Clipboard root list.
+ */
+typedef struct _SHCLROOTLIST
+{
+ /** Root list header. */
+ SHCLROOTLISTHDR Hdr;
+ /** Root list entries. */
+ SHCLROOTLISTENTRY *paEntries;
+} SHCLROOTLIST, *PSHCLROOTLIST;
+
+/**
+ * Structure for maintaining Shared Clipboard list open paramters.
+ */
+typedef struct _SHCLLISTOPENPARMS
+{
+ /** Listing flags (see VBOX_SHCL_LIST_FLAG_XXX). */
+ uint32_t fList;
+ /** Size (in bytes) of the filter string. */
+ uint32_t cbFilter;
+ /** Filter string. DOS wilcard-style. */
+ char *pszFilter;
+ /** Size (in bytes) of the listing path. */
+ uint32_t cbPath;
+ /** Listing path (absolute). If empty or NULL the listing's root path will be opened. */
+ char *pszPath;
+} SHCLLISTOPENPARMS, *PSHCLLISTOPENPARMS;
+
+/**
+ * Structure for keeping a Shared Clipboard list header.
+ */
+typedef struct _SHCLLISTHDR
+{
+ /** Feature flag(s). Not being used atm. */
+ uint32_t fFeatures;
+ /** Total objects returned. */
+ uint64_t cTotalObjects;
+ /** Total size (in bytes) returned. */
+ uint64_t cbTotalSize;
+} SHCLLISTHDR, *PSHCLLISTHDR;
+
+/**
+ * Structure for a Shared Clipboard list entry.
+ */
+typedef struct _SHCLLISTENTRY
+{
+ /** Entry name. */
+ char *pszName;
+ /** Size (in bytes) of entry name. */
+ uint32_t cbName;
+ /** Information flag(s). */
+ uint32_t fInfo;
+ /** Size (in bytes) of the actual list entry. */
+ uint32_t cbInfo;
+ /** Data of the actual list entry. */
+ void *pvInfo;
+} SHCLLISTENTRY, *PSHCLLISTENTRY;
+
+/** Maximum length (in UTF-8 characters) of a list entry name. */
+#define SHCLLISTENTRY_MAX_NAME RTPATH_MAX /** @todo Improve this to be more dynamic. */
+
+/**
+ * Structure for maintaining a Shared Clipboard list.
+ */
+typedef struct _SHCLLIST
+{
+ /** List header. */
+ SHCLLISTHDR Hdr;
+ /** List entries. */
+ SHCLROOTLISTENTRY *paEntries;
+} SHCLLIST, *PSHCLLIST;
+
+/**
+ * Structure for keeping a Shared Clipboard object data chunk.
+ */
+typedef struct _SHCLOBJDATACHUNK
+{
+ /** Handle of object this data chunk is related to. */
+ uint64_t uHandle;
+ /** Pointer to actual data chunk. */
+ void *pvData;
+ /** Size (in bytes) of data chunk. */
+ uint32_t cbData;
+} SHCLOBJDATACHUNK, *PSHCLOBJDATACHUNK;
+
+/**
+ * Structure for handling a single transfer object context.
+ */
+typedef struct _SHCLCLIENTTRANSFEROBJCTX
+{
+ SHCLTRANSFER *pTransfer;
+ SHCLOBJHANDLE uHandle;
+} SHCLCLIENTTRANSFEROBJCTX, *PSHCLCLIENTTRANSFEROBJCTX;
+
+typedef struct _SHCLTRANSFEROBJSTATE
+{
+ /** How many bytes were processed (read / write) so far. */
+ uint64_t cbProcessed;
+} SHCLTRANSFEROBJSTATE, *PSHCLTRANSFEROBJSTATE;
+
+typedef struct _SHCLTRANSFEROBJ
+{
+ SHCLOBJHANDLE uHandle;
+ char *pszPathAbs;
+ SHCLFSOBJINFO objInfo;
+ SHCLSOURCE enmSource;
+ SHCLTRANSFEROBJSTATE State;
+} SHCLTRANSFEROBJ, *PSHCLTRANSFEROBJ;
+
+/**
+ * Enumeration for specifying a Shared Clipboard object type.
+ */
+typedef enum _SHCLOBJTYPE
+{
+ /** Invalid object type. */
+ SHCLOBJTYPE_INVALID = 0,
+ /** Object is a directory. */
+ SHCLOBJTYPE_DIRECTORY,
+ /** Object is a file. */
+ SHCLOBJTYPE_FILE,
+ /** Object is a symbolic link. */
+ SHCLOBJTYPE_SYMLINK,
+ /** The usual 32-bit hack. */
+ SHCLOBJTYPE_32BIT_SIZE_HACK = 0x7fffffff
+} SHCLOBJTYPE;
+
+/**
+ * Structure for keeping transfer list handle information.
+ * This is using to map own (local) handles to the underlying file system.
+ */
+typedef struct _SHCLLISTHANDLEINFO
+{
+ /** The list node. */
+ RTLISTNODE Node;
+ /** The list's handle. */
+ SHCLLISTHANDLE hList;
+ /** Type of list handle. */
+ SHCLOBJTYPE enmType;
+ /** Absolute local path of the list object. */
+ char *pszPathLocalAbs;
+ union
+ {
+ /** Local data, based on enmType. */
+ struct
+ {
+ union
+ {
+ RTDIR hDir;
+ RTFILE hFile;
+ };
+ } Local;
+ } u;
+} SHCLLISTHANDLEINFO, *PSHCLLISTHANDLEINFO;
+
+/**
+ * Structure for keeping transfer object handle information.
+ * This is using to map own (local) handles to the underlying file system.
+ */
+typedef struct _SHCLOBJHANDLEINFO
+{
+ /** The list node. */
+ RTLISTNODE Node;
+ /** The object's handle. */
+ SHCLOBJHANDLE hObj;
+ /** Type of object handle. */
+ SHCLOBJTYPE enmType;
+ /** Absolute local path of the object. */
+ char *pszPathLocalAbs;
+ union
+ {
+ /** Local data, based on enmType. */
+ struct
+ {
+ union
+ {
+ RTDIR hDir;
+ RTFILE hFile;
+ };
+ } Local;
+ } u;
+} SHCLOBJHANDLEINFO, *PSHCLOBJHANDLEINFO;
+
+/**
+ * Structure for keeping a single root list entry.
+ */
+typedef struct _SHCLLISTROOT
+{
+ /** The list node. */
+ RTLISTNODE Node;
+ /** Absolute path of entry. */
+ char *pszPathAbs;
+} SHCLLISTROOT, *PSHCLLISTROOT;
+
+/**
+ * Structure for maintaining an Shared Clipboard transfer state.
+ * Everything in here will be part of a saved state (later).
+ */
+typedef struct _SHCLTRANSFERSTATE
+{
+ /** The transfer's (local) ID. */
+ SHCLTRANSFERID uID;
+ /** The transfer's current status. */
+ SHCLTRANSFERSTATUS enmStatus;
+ /** The transfer's direction, seen from the perspective who created the transfer. */
+ SHCLTRANSFERDIR enmDir;
+ /** The transfer's source, seen from the perspective who created the transfer. */
+ SHCLSOURCE enmSource;
+} SHCLTRANSFERSTATE, *PSHCLTRANSFERSTATE;
+
+/**
+ * Structure maintaining clipboard transfer provider context data.
+ * This is handed in to the provider interface implementations.
+ */
+typedef struct _SHCLTXPROVIDERCTX
+{
+ /** Pointer to the related Shared Clipboard transfer. */
+ PSHCLTRANSFER pTransfer;
+ /** User-defined data pointer. Can be NULL if not needed. */
+ void *pvUser;
+ /** Size (in bytes) of data at user pointer. */
+ size_t cbUser;
+} SHCLTXPROVIDERCTX, *PSHCLTXPROVIDERCTX;
+
+struct SHCLTRANSFERCTX;
+typedef struct SHCLTRANSFERCTX *PSHCLTRANSFERCTX;
+
+/**
+ * Shared Clipboard transfer provider interface table.
+ *
+ * A transfer provider inteface implementation realizes all low level functions
+ * needed for making a Shared Clipboard transfer happen.
+ */
+typedef struct _SHCLTXPROVIDERIFACE
+{
+ DECLCALLBACKMEMBER(int, pfnRootsGet,(PSHCLTXPROVIDERCTX pCtx, PSHCLROOTLIST *ppRootList));
+ DECLCALLBACKMEMBER(int, pfnListOpen,(PSHCLTXPROVIDERCTX pCtx, PSHCLLISTOPENPARMS pOpenParms, PSHCLLISTHANDLE phList));
+ DECLCALLBACKMEMBER(int, pfnListClose,(PSHCLTXPROVIDERCTX pCtx, SHCLLISTHANDLE hList));
+ DECLCALLBACKMEMBER(int, pfnListHdrRead,(PSHCLTXPROVIDERCTX pCtx, SHCLLISTHANDLE hList, PSHCLLISTHDR pListHdr));
+ DECLCALLBACKMEMBER(int, pfnListHdrWrite,(PSHCLTXPROVIDERCTX pCtx, SHCLLISTHANDLE hList, PSHCLLISTHDR pListHdr));
+ DECLCALLBACKMEMBER(int, pfnListEntryRead,(PSHCLTXPROVIDERCTX pCtx, SHCLLISTHANDLE hList, PSHCLLISTENTRY pEntry));
+ DECLCALLBACKMEMBER(int, pfnListEntryWrite,(PSHCLTXPROVIDERCTX pCtx, SHCLLISTHANDLE hList, PSHCLLISTENTRY pEntry));
+ DECLCALLBACKMEMBER(int, pfnObjOpen,(PSHCLTXPROVIDERCTX pCtx, PSHCLOBJOPENCREATEPARMS pCreateParms, PSHCLOBJHANDLE phObj));
+ DECLCALLBACKMEMBER(int, pfnObjClose,(PSHCLTXPROVIDERCTX pCtx, SHCLOBJHANDLE hObj));
+ DECLCALLBACKMEMBER(int, pfnObjRead,(PSHCLTXPROVIDERCTX pCtx, SHCLOBJHANDLE hObj, void *pvData, uint32_t cbData,
+ uint32_t fFlags, uint32_t *pcbRead));
+ DECLCALLBACKMEMBER(int, pfnObjWrite,(PSHCLTXPROVIDERCTX pCtx, SHCLOBJHANDLE hObj, void *pvData, uint32_t cbData,
+ uint32_t fFlags, uint32_t *pcbWritten));
+} SHCLTXPROVIDERIFACE, *PSHCLTXPROVIDERIFACE;
+
+/**
+ * Structure for the Shared Clipboard transfer provider creation context.
+ */
+typedef struct _SHCLTXPROVIDERCREATIONCTX
+{
+ /** Specifies what the source of the provider is. */
+ SHCLSOURCE enmSource;
+ /** The provider interface table. */
+ SHCLTXPROVIDERIFACE Interface;
+ /** User-provided callback data. */
+ void *pvUser;
+ /** Size (in bytes) of data at user pointer. */
+ size_t cbUser;
+} SHCLTXPROVIDERCREATIONCTX, *PSHCLTXPROVIDERCREATIONCTX;
+
+/**
+ * Structure maintaining clipboard transfer callback context data.
+ */
+typedef struct _SHCLTRANSFERCALLBACKCTX
+{
+ /** Pointer to the related Shared Clipboard transfer. */
+ PSHCLTRANSFER pTransfer;
+ /** User-defined data pointer. Can be NULL if not needed. */
+ void *pvUser;
+ /** Size (in bytes) of data at user pointer. */
+ size_t cbUser;
+} SHCLTRANSFERCALLBACKCTX, *PSHCLTRANSFERCALLBACKCTX;
+
+/**
+ * Shared Clipboard transfer callback table.
+ *
+ * All callbacks are optional and can provide additional information / feedback to a frontend.
+ */
+typedef struct _SHCLTRANSFERCALLBACKTABLE
+{
+ /**
+ * Called when the transfer gets initialized.
+ *
+ * @param pCbCtx Pointer to callback context to use.
+ */
+ DECLCALLBACKMEMBER(int, pfnOnInitialize,(PSHCLTRANSFERCALLBACKCTX pCbCtx));
+ /**
+ * Called before the transfer will be started.
+ *
+ * @param pCbCtx Pointer to callback context to use.
+ */
+ DECLCALLBACKMEMBER(int, pfnOnStart,(PSHCLTRANSFERCALLBACKCTX pCbCtx));
+ /**
+ * Called when the transfer has been complete.
+ *
+ * @param pCbCtx Pointer to callback context to use.
+ * @param rcCompletion Completion result.
+ * VERR_CANCELED if transfer has been canceled.
+ */
+ DECLCALLBACKMEMBER(void, pfnOnCompleted,(PSHCLTRANSFERCALLBACKCTX pCbCtx, int rcCompletion));
+ /**
+ * Called when transfer resulted in an unrecoverable error.
+ *
+ * @param pCbCtx Pointer to callback context to use.
+ * @param rcError Error reason, IPRT-style.
+ */
+ DECLCALLBACKMEMBER(void, pfnOnError,(PSHCLTRANSFERCALLBACKCTX pCbCtx, int rcError));
+ /**
+ * Called when transfer got registered to a transfer context.
+ *
+ * @param pCbCtx Pointer to callback context to use.
+ * @param pTransferCtx Transfer context transfer was registered to.
+ */
+ DECLCALLBACKMEMBER(void, pfnOnRegistered,(PSHCLTRANSFERCALLBACKCTX pCbCtx, PSHCLTRANSFERCTX pTransferCtx));
+ /**
+ * Called when transfer got unregistered from a transfer context.
+ *
+ * @param pCbCtx Pointer to callback context to use.
+ * @param pTransferCtx Transfer context transfer was unregistered from.
+ */
+ DECLCALLBACKMEMBER(void, pfnOnUnregistered,(PSHCLTRANSFERCALLBACKCTX pCbCtx, PSHCLTRANSFERCTX pTransferCtx));
+
+ /** User-provided callback data. Can be NULL if not used. */
+ void *pvUser;
+ /** Size (in bytes) of data pointer at \a pvUser. */
+ size_t cbUser;
+} SHCLTRANSFERCALLBACKTABLE, *PSHCLTRANSFERCALLBACKTABLE;
+
+/**
+ * Structure for thread-related members for a single Shared Clipboard transfer.
+ */
+typedef struct _SHCLTRANSFERTHREAD
+{
+ /** Thread handle for the reading / writing thread.
+ * Can be NIL_RTTHREAD if not being used. */
+ RTTHREAD hThread;
+ /** Thread started indicator. */
+ volatile bool fStarted;
+ /** Thread stop flag. */
+ volatile bool fStop;
+ /** Thread cancelled flag / indicator. */
+ volatile bool fCancelled;
+} SHCLTRANSFERTHREAD, *PSHCLTRANSFERTHREAD;
+
+/**
+ * A single Shared Clipboard transfer.
+ *
+ ** @todo Not yet thread safe.
+ */
+typedef struct SHCLTRANSFER
+{
+ /** The node member for using this struct in a RTList. */
+ RTLISTNODE Node;
+ /** The transfer's state (for SSM, later). */
+ SHCLTRANSFERSTATE State;
+ /** Absolute path to root entries. */
+ char *pszPathRootAbs;
+ /** Timeout (in ms) for waiting of events. Default is 30s. */
+ RTMSINTERVAL uTimeoutMs;
+ /** Maximum data chunk size (in bytes) to transfer. Default is 64K. */
+ uint32_t cbMaxChunkSize;
+ /** The transfer's own event source. */
+ SHCLEVENTSOURCE Events;
+ /** Current number of concurrent list handles. */
+ uint32_t cListHandles;
+ /** Maximum number of concurrent list handles. */
+ uint32_t cMaxListHandles;
+ /** Next upcoming list handle. */
+ SHCLLISTHANDLE uListHandleNext;
+ /** List of all list handles elated to this transfer. */
+ RTLISTANCHOR lstList;
+ /** Number of root entries in list. */
+ uint64_t cRoots;
+ /** List of root entries of this transfer. */
+ RTLISTANCHOR lstRoots;
+ /** Current number of concurrent object handles. */
+ uint32_t cObjHandles;
+ /** Maximum number of concurrent object handles. */
+ uint32_t cMaxObjHandles;
+ /** Next upcoming object handle. */
+ SHCLOBJHANDLE uObjHandleNext;
+ /** Map of all objects handles related to this transfer. */
+ RTLISTANCHOR lstObj;
+ /** The transfer's own provider context. */
+ SHCLTXPROVIDERCTX ProviderCtx;
+ /** The transfer's provider interface. */
+ SHCLTXPROVIDERIFACE ProviderIface;
+ /** The transfer's callback context. */
+ SHCLTRANSFERCALLBACKCTX CallbackCtx;
+ /** The transfer's callback table. */
+ SHCLTRANSFERCALLBACKTABLE Callbacks;
+ /** Opaque pointer to implementation-specific parameters. */
+ void *pvUser;
+ /** Size (in bytes) of implementation-specific parameters. */
+ size_t cbUser;
+ /** Contains thread-related attributes. */
+ SHCLTRANSFERTHREAD Thread;
+ /** Critical section for serializing access. */
+ RTCRITSECT CritSect;
+} SHCLTRANSFER, *PSHCLTRANSFER;
+
+/**
+ * Structure for keeping an Shared Clipboard transfer status report.
+ */
+typedef struct _SHCLTRANSFERREPORT
+{
+ /** Actual status to report. */
+ SHCLTRANSFERSTATUS uStatus;
+ /** Result code (rc) to report; might be unused / invalid, based on enmStatus. */
+ int rc;
+ /** Reporting flags. Currently unused and must be 0. */
+ uint32_t fFlags;
+} SHCLTRANSFERREPORT, *PSHCLTRANSFERREPORT;
+
+#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS_HTTP
+typedef struct _SHCLHTTPSERVER
+{
+ /** Critical section for serializing access. */
+ RTCRITSECT CritSect;
+ /** Handle of the HTTP server instance. */
+ RTHTTPSERVER hHTTPServer;
+ /** Port number the HTTP server is running on. 0 if not running. */
+ uint16_t uPort;
+ /** List of registered HTTP transfers. */
+ RTLISTANCHOR lstTransfers;
+ /** Number of registered HTTP transfers. */
+ uint32_t cTransfers;
+ /** Cached response data. */
+ RTHTTPSERVERRESP Resp;
+} SHCLHTTPSERVER;
+typedef SHCLHTTPSERVER *PSHCLHTTPSERVER;
+
+typedef struct _SHCLHTTPCONTEXT
+{
+ /** HTTP server instance data. */
+ SHCLHTTPSERVER HttpServer;
+} SHCLHTTPCONTEXT;
+typedef SHCLHTTPCONTEXT *PSHCLHTTPCONTEXT;
+
+#endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS_HTTP */
+
+/**
+ * Structure for keeping Shared Clipboard transfer context around.
+ */
+struct SHCLTRANSFERCTX
+{
+ /** Critical section for serializing access. */
+ RTCRITSECT CritSect;
+ /** List of transfers. */
+ RTLISTANCHOR List;
+ /** Transfer ID allocation bitmap; clear bits are free, set bits are busy. */
+ uint64_t bmTransferIds[VBOX_SHCL_MAX_TRANSFERS / sizeof(uint64_t) / 8];
+ /** Number of running (concurrent) transfers. */
+ uint16_t cRunning;
+ /** Maximum Number of running (concurrent) transfers. */
+ uint16_t cMaxRunning;
+ /** Number of total transfers (in list). */
+ uint16_t cTransfers;
+#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS_HTTP
+ /** HTTP server instance for this transfer context. */
+ SHCLHTTPSERVER HttpServer;
+#endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS_HTTP */
+};
+
+int ShClTransferObjCtxInit(PSHCLCLIENTTRANSFEROBJCTX pObjCtx);
+void ShClTransferObjCtxDestroy(PSHCLCLIENTTRANSFEROBJCTX pObjCtx);
+bool ShClTransferObjCtxIsValid(PSHCLCLIENTTRANSFEROBJCTX pObjCtx);
+
+int ShClTransferObjHandleInfoInit(PSHCLOBJHANDLEINFO pInfo);
+void ShClTransferObjHandleInfoDestroy(PSHCLOBJHANDLEINFO pInfo);
+
+int ShClTransferObjOpenParmsInit(PSHCLOBJOPENCREATEPARMS pParms);
+int ShClTransferObjOpenParmsCopy(PSHCLOBJOPENCREATEPARMS pParmsDst, PSHCLOBJOPENCREATEPARMS pParmsSrc);
+void ShClTransferObjOpenParmsDestroy(PSHCLOBJOPENCREATEPARMS pParms);
+
+int ShClTransferObjOpen(PSHCLTRANSFER pTransfer, PSHCLOBJOPENCREATEPARMS pOpenCreateParms, PSHCLOBJHANDLE phObj);
+int ShClTransferObjClose(PSHCLTRANSFER pTransfer, SHCLOBJHANDLE hObj);
+int ShClTransferObjRead(PSHCLTRANSFER pTransfer, SHCLOBJHANDLE hObj, void *pvBuf, uint32_t cbBuf, uint32_t fFlags, uint32_t *pcbRead);
+int ShClTransferObjWrite(PSHCLTRANSFER pTransfer, SHCLOBJHANDLE hObj, void *pvBuf, uint32_t cbBuf, uint32_t fFlags, uint32_t *pcbWritten);
+
+PSHCLOBJDATACHUNK ShClTransferObjDataChunkDup(PSHCLOBJDATACHUNK pDataChunk);
+void ShClTransferObjDataChunkDestroy(PSHCLOBJDATACHUNK pDataChunk);
+void ShClTransferObjDataChunkFree(PSHCLOBJDATACHUNK pDataChunk);
+
+int ShClTransferCreate(PSHCLTRANSFER *ppTransfer);
+int ShClTransferInit(PSHCLTRANSFER pTransfer, SHCLTRANSFERDIR enmDir, SHCLSOURCE enmSource);
+int ShClTransferDestroy(PSHCLTRANSFER pTransfer);
+
+int ShClTransferListOpen(PSHCLTRANSFER pTransfer, PSHCLLISTOPENPARMS pOpenParms, PSHCLLISTHANDLE phList);
+int ShClTransferListClose(PSHCLTRANSFER pTransfer, SHCLLISTHANDLE hList);
+int ShClTransferListGetHeader(PSHCLTRANSFER pTransfer, SHCLLISTHANDLE hList, PSHCLLISTHDR pHdr);
+PSHCLTRANSFEROBJ ShClTransferListGetObj(PSHCLTRANSFER pTransfer, SHCLLISTHANDLE hList, uint64_t uIdx);
+int ShClTransferListRead(PSHCLTRANSFER pTransfer, SHCLLISTHANDLE hList, PSHCLLISTENTRY pEntry);
+int ShClTransferListWrite(PSHCLTRANSFER pTransfer, SHCLLISTHANDLE hList, PSHCLLISTENTRY pEntry);
+bool ShClTransferListHandleIsValid(PSHCLTRANSFER pTransfer, SHCLLISTHANDLE hList);
+
+int ShClPathSanitizeFilename(char *pszPath, size_t cbPath);
+int ShClPathSanitize(char *pszPath, size_t cbPath);
+
+PSHCLROOTLIST ShClTransferRootListAlloc(void);
+void ShClTransferRootListFree(PSHCLROOTLIST pRootList);
+
+PSHCLROOTLISTHDR ShClTransferRootListHdrDup(PSHCLROOTLISTHDR pRoots);
+int ShClTransferRootListHdrInit(PSHCLROOTLISTHDR pRoots);
+void ShClTransferRootListHdrDestroy(PSHCLROOTLISTHDR pRoots);
+
+int ShClTransferRootListEntryCopy(PSHCLROOTLISTENTRY pDst, PSHCLROOTLISTENTRY pSrc);
+int ShClTransferRootListEntryInit(PSHCLROOTLISTENTRY pRootListEntry);
+void ShClTransferRootListEntryDestroy(PSHCLROOTLISTENTRY pRootListEntry);
+PSHCLROOTLISTENTRY ShClTransferRootListEntryDup(PSHCLROOTLISTENTRY pRootListEntry);
+
+int ShClTransferListHandleInfoInit(PSHCLLISTHANDLEINFO pInfo);
+void ShClTransferListHandleInfoDestroy(PSHCLLISTHANDLEINFO pInfo);
+
+int ShClTransferListHdrAlloc(PSHCLLISTHDR *ppListHdr);
+void ShClTransferListHdrFree(PSHCLLISTHDR pListHdr);
+PSHCLLISTHDR ShClTransferListHdrDup(PSHCLLISTHDR pListHdr);
+int ShClTransferListHdrInit(PSHCLLISTHDR pListHdr);
+void ShClTransferListHdrDestroy(PSHCLLISTHDR pListHdr);
+void ShClTransferListHdrReset(PSHCLLISTHDR pListHdr);
+bool ShClTransferListHdrIsValid(PSHCLLISTHDR pListHdr);
+
+int ShClTransferListOpenParmsCopy(PSHCLLISTOPENPARMS pDst, PSHCLLISTOPENPARMS pSrc);
+PSHCLLISTOPENPARMS ShClTransferListOpenParmsDup(PSHCLLISTOPENPARMS pParms);
+int ShClTransferListOpenParmsInit(PSHCLLISTOPENPARMS pParms);
+void ShClTransferListOpenParmsDestroy(PSHCLLISTOPENPARMS pParms);
+
+int ShClTransferListEntryAlloc(PSHCLLISTENTRY *ppListEntry);
+void ShClTransferListEntryFree(PSHCLLISTENTRY pListEntry);
+int ShClTransferListEntryCopy(PSHCLLISTENTRY pDst, PSHCLLISTENTRY pSrc);
+PSHCLLISTENTRY ShClTransferListEntryDup(PSHCLLISTENTRY pListEntry);
+int ShClTransferListEntryInit(PSHCLLISTENTRY pListEntry);
+void ShClTransferListEntryDestroy(PSHCLLISTENTRY pListEntry);
+bool ShClTransferListEntryIsValid(PSHCLLISTENTRY pListEntry);
+
+void ShClTransferCopyCallbacks(PSHCLTRANSFERCALLBACKTABLE pCallbacksDst, PSHCLTRANSFERCALLBACKTABLE pCallbacksSrc);
+void ShClTransferSetCallbacks(PSHCLTRANSFER pTransfer, PSHCLTRANSFERCALLBACKTABLE pCallbacks);
+int ShClTransferSetProviderIface(PSHCLTRANSFER pTransfer, PSHCLTXPROVIDERCREATIONCTX pCreationCtx);
+int ShClTransferRootsSet(PSHCLTRANSFER pTransfer, const char *pszRoots, size_t cbRoots);
+void ShClTransferReset(PSHCLTRANSFER pTransfer);
+
+uint32_t ShClTransferRootsCount(PSHCLTRANSFER pTransfer);
+int ShClTransferRootsEntry(PSHCLTRANSFER pTransfer, uint64_t uIndex, PSHCLROOTLISTENTRY pEntry);
+int ShClTransferRootsGet(PSHCLTRANSFER pTransfer, PSHCLROOTLIST *ppRootList);
+
+SHCLTRANSFERID ShClTransferGetID(PSHCLTRANSFER pTransfer);
+SHCLTRANSFERDIR ShClTransferGetDir(PSHCLTRANSFER pTransfer);
+SHCLSOURCE ShClTransferGetSource(PSHCLTRANSFER pTransfer);
+SHCLTRANSFERSTATUS ShClTransferGetStatus(PSHCLTRANSFER pTransfer);
+int ShClTransferRun(PSHCLTRANSFER pTransfer, PFNRTTHREAD pfnThreadFunc, void *pvUser);
+int ShClTransferStart(PSHCLTRANSFER pTransfer);
+
+int ShClTransferCtxInit(PSHCLTRANSFERCTX pTransferCtx);
+void ShClTransferCtxDestroy(PSHCLTRANSFERCTX pTransferCtx);
+void ShClTransferCtxReset(PSHCLTRANSFERCTX pTransferCtx);
+PSHCLTRANSFER ShClTransferCtxGetTransferById(PSHCLTRANSFERCTX pTransferCtx, uint32_t uID);
+PSHCLTRANSFER ShClTransferCtxGetTransferByIndex(PSHCLTRANSFERCTX pTransferCtx, uint32_t uIdx);
+uint32_t ShClTransferCtxGetRunningTransfers(PSHCLTRANSFERCTX pTransferCtx);
+uint32_t ShClTransferCtxGetTotalTransfers(PSHCLTRANSFERCTX pTransferCtx);
+void ShClTransferCtxCleanup(PSHCLTRANSFERCTX pTransferCtx);
+bool ShClTransferCtxTransfersMaximumReached(PSHCLTRANSFERCTX pTransferCtx);
+int ShClTransferCtxTransferRegister(PSHCLTRANSFERCTX pTransferCtx, PSHCLTRANSFER pTransfer, SHCLTRANSFERID *pidTransfer);
+int ShClTransferCtxTransferRegisterById(PSHCLTRANSFERCTX pTransferCtx, PSHCLTRANSFER pTransfer, SHCLTRANSFERID idTransfer);
+int ShClTransferCtxTransferUnregister(PSHCLTRANSFERCTX pTransferCtx, SHCLTRANSFERID idTransfer);
+
+#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS_HTTP
+int ShClHttpTransferRegister(PSHCLHTTPCONTEXT pCtx, PSHCLTRANSFER pTransfer);
+int ShClHttpTransferUnregister(PSHCLHTTPCONTEXT pCtx, PSHCLTRANSFER pTransfer);
+
+int ShClTransferHttpServerCreate(PSHCLHTTPSERVER pSrv, uint16_t *puPort);
+int ShClTransferHttpServerCreateEx(PSHCLHTTPSERVER pSrv, uint16_t uPort);
+int ShClTransferHttpServerDestroy(PSHCLHTTPSERVER pSrv);
+void ShClTransferHttpServerInit(PSHCLHTTPSERVER pSrv);
+int ShClTransferHttpServerRegisterTransfer(PSHCLHTTPSERVER pSrv, PSHCLTRANSFER pTransfer);
+int ShClTransferHttpServerUnregisterTransfer(PSHCLHTTPSERVER pSrv, PSHCLTRANSFER pTransfer);
+bool ShClTransferHttpServerHasTransfer(PSHCLHTTPSERVER pSrv, SHCLTRANSFERID idTransfer);
+uint16_t ShClTransferHttpServerGetPort(PSHCLHTTPSERVER pSrv);
+uint32_t ShClTransferHttpServerGetTransferCount(PSHCLHTTPSERVER pSrv);
+char *ShClTransferHttpServerGetAddressA(PSHCLHTTPSERVER pSrv);
+char *ShClTransferHttpServerGetUrlA(PSHCLHTTPSERVER pSrv, SHCLTRANSFERID idTransfer);
+bool ShClTransferHttpServerIsRunning(PSHCLHTTPSERVER pSrv);
+#endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS_HTTP */
+
+void ShClFsObjFromIPRT(PSHCLFSOBJINFO pDst, PCRTFSOBJINFO pSrc);
+
+bool ShClMIMEHasFileURLs(const char *pcszFormat, size_t cchFormatMax);
+bool ShClMIMENeedsCache(const char *pcszFormat, size_t cchFormatMax);
+
+const char *ShClTransferStatusToStr(SHCLTRANSFERSTATUS enmStatus);
+
+#endif /* !VBOX_INCLUDED_GuestHost_SharedClipboard_transfers_h */
diff --git a/include/VBox/GuestHost/SharedClipboard-win.h b/include/VBox/GuestHost/SharedClipboard-win.h
new file mode 100644
index 00000000..0e35b409
--- /dev/null
+++ b/include/VBox/GuestHost/SharedClipboard-win.h
@@ -0,0 +1,419 @@
+/** @file
+ * Shared Clipboard - Common Guest and Host Code, for Windows OSes.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_GuestHost_SharedClipboard_win_h
+#define VBOX_INCLUDED_GuestHost_SharedClipboard_win_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/critsect.h>
+#include <iprt/types.h>
+#include <iprt/win/windows.h>
+
+#include <VBox/GuestHost/SharedClipboard.h>
+
+# ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
+# include <vector>
+
+# include <iprt/cpp/ministring.h> /* For RTCString. */
+# include <iprt/win/shlobj.h> /* For DROPFILES and friends. */
+# include <VBox/com/string.h> /* For Utf8Str. */
+# include <oleidl.h>
+
+# include <VBox/GuestHost/SharedClipboard-transfers.h>
+
+using namespace com;
+# endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS */
+
+#ifndef WM_CLIPBOARDUPDATE
+# define WM_CLIPBOARDUPDATE 0x031D
+#endif
+
+#define SHCL_WIN_WNDCLASS_NAME "VBoxSharedClipboardClass"
+
+/** See: https://docs.microsoft.com/en-us/windows/desktop/dataxchg/html-clipboard-format
+ * Do *not* change the name, as this will break compatbility with other (legacy) applications! */
+#define SHCL_WIN_REGFMT_HTML "HTML Format"
+
+/** Default timeout (in ms) for passing down messages down the clipboard chain. */
+#define SHCL_WIN_CBCHAIN_TIMEOUT_MS 5000
+
+/** Reports clipboard formats. */
+#define SHCL_WIN_WM_REPORT_FORMATS WM_USER
+/** Reads data from the clipboard and sends it to the destination. */
+#define SHCL_WIN_WM_READ_DATA WM_USER + 1
+#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
+/** Starts a transfer on the guest.
+ * This creates the necessary IDataObject in the matching window thread. */
+# define SHCL_WIN_WM_TRANSFER_START WM_USER + 2
+#endif
+
+/* Dynamically load clipboard functions from User32.dll. */
+typedef BOOL WINAPI FNADDCLIPBOARDFORMATLISTENER(HWND);
+typedef FNADDCLIPBOARDFORMATLISTENER *PFNADDCLIPBOARDFORMATLISTENER;
+
+typedef BOOL WINAPI FNREMOVECLIPBOARDFORMATLISTENER(HWND);
+typedef FNREMOVECLIPBOARDFORMATLISTENER *PFNREMOVECLIPBOARDFORMATLISTENER;
+
+/**
+ * Structure for keeping function pointers for the new clipboard API.
+ * If the new API is not available, those function pointer are NULL.
+ */
+typedef struct _SHCLWINAPINEW
+{
+ PFNADDCLIPBOARDFORMATLISTENER pfnAddClipboardFormatListener;
+ PFNREMOVECLIPBOARDFORMATLISTENER pfnRemoveClipboardFormatListener;
+} SHCLWINAPINEW, *PSHCLWINAPINEW;
+
+/**
+ * Structure for keeping variables which are needed to drive the old clipboard API.
+ */
+typedef struct _SHCLWINAPIOLD
+{
+ /** Timer ID for the refresh timer. */
+ UINT timerRefresh;
+ /** Whether "pinging" the clipboard chain currently is in progress or not. */
+ bool fCBChainPingInProcess;
+} SHCLWINAPIOLD, *PSHCLWINAPIOLD;
+
+/**
+ * Structure for maintaining a Shared Clipboard context on Windows platforms.
+ */
+typedef struct _SHCLWINCTX
+{
+ /** Critical section to serialize access. */
+ RTCRITSECT CritSect;
+ /** Window handle of our (invisible) clipbaord window. */
+ HWND hWnd;
+ /** Window handle which is next to us in the clipboard chain. */
+ HWND hWndNextInChain;
+ /** Window handle of the clipboard owner *if* we are the owner.
+ * @todo r=bird: Ignore the misleading statement above. This is only set to
+ * NULL by the initialization code and then it's set to the clipboard owner
+ * after we announce data to the clipboard. So, essentially this will be our
+ * windows handle or NULL. End of story. */
+ HWND hWndClipboardOwnerUs;
+ /** Structure for maintaining the new clipboard API. */
+ SHCLWINAPINEW newAPI;
+ /** Structure for maintaining the old clipboard API. */
+ SHCLWINAPIOLD oldAPI;
+} SHCLWINCTX, *PSHCLWINCTX;
+
+int SharedClipboardWinOpen(HWND hWnd);
+int SharedClipboardWinClose(void);
+int SharedClipboardWinClear(void);
+
+int SharedClipboardWinCtxInit(PSHCLWINCTX pWinCtx);
+void SharedClipboardWinCtxDestroy(PSHCLWINCTX pWinCtx);
+
+int SharedClipboardWinCheckAndInitNewAPI(PSHCLWINAPINEW pAPI);
+bool SharedClipboardWinIsNewAPI(PSHCLWINAPINEW pAPI);
+
+int SharedClipboardWinDataWrite(UINT cfFormat, void *pvData, uint32_t cbData);
+
+int SharedClipboardWinChainAdd(PSHCLWINCTX pCtx);
+int SharedClipboardWinChainRemove(PSHCLWINCTX pCtx);
+VOID CALLBACK SharedClipboardWinChainPingProc(HWND hWnd, UINT uMsg, ULONG_PTR dwData, LRESULT lResult) RT_NOTHROW_DEF;
+LRESULT SharedClipboardWinChainPassToNext(PSHCLWINCTX pWinCtx, UINT msg, WPARAM wParam, LPARAM lParam);
+
+SHCLFORMAT SharedClipboardWinClipboardFormatToVBox(UINT uFormat);
+int SharedClipboardWinGetFormats(PSHCLWINCTX pCtx, PSHCLFORMATS pfFormats);
+
+#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
+int SharedClipboardWinGetRoots(PSHCLWINCTX pWinCtx, PSHCLTRANSFER pTransfer);
+int SharedClipboardWinDropFilesToStringList(DROPFILES *pDropFiles, char **papszList, uint32_t *pcbList);
+#endif
+
+int SharedClipboardWinGetCFHTMLHeaderValue(const char *pszSrc, const char *pszOption, uint32_t *puValue);
+bool SharedClipboardWinIsCFHTML(const char *pszSource);
+int SharedClipboardWinConvertCFHTMLToMIME(const char *pszSource, const uint32_t cch, char **ppszOutput, uint32_t *pcbOutput);
+int SharedClipboardWinConvertMIMEToCFHTML(const char *pszSource, size_t cb, char **ppszOutput, uint32_t *pcbOutput);
+
+LRESULT SharedClipboardWinHandleWMChangeCBChain(PSHCLWINCTX pWinCtx, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
+int SharedClipboardWinHandleWMDestroy(PSHCLWINCTX pWinCtx);
+int SharedClipboardWinHandleWMRenderAllFormats(PSHCLWINCTX pWinCtx, HWND hWnd);
+int SharedClipboardWinHandleWMTimer(PSHCLWINCTX pWinCtx);
+
+int SharedClipboardWinClearAndAnnounceFormats(PSHCLWINCTX pWinCtx, SHCLFORMATS fFormats, HWND hWnd);
+#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
+int SharedClipboardWinTransferCreate(PSHCLWINCTX pWinCtx, PSHCLTRANSFER pTransfer);
+void SharedClipboardWinTransferDestroy(PSHCLWINCTX pWinCtx, PSHCLTRANSFER pTransfer);
+#endif
+
+# ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
+class SharedClipboardTransferList;
+# ifndef FILEGROUPDESCRIPTOR
+class FILEGROUPDESCRIPTOR;
+# endif
+
+class SharedClipboardWinDataObject : public IDataObject //, public IDataObjectAsyncCapability
+{
+public:
+
+ enum Status
+ {
+ /** The object is uninitialized (not ready). */
+ Uninitialized = 0,
+ /** The object is initialized and ready to use. */
+ Initialized,
+ /** The operation has been successfully completed. */
+ Completed,
+ /** The operation has been canceled. */
+ Canceled,
+ /** An (unrecoverable) error occurred. */
+ Error
+ };
+
+public:
+
+ SharedClipboardWinDataObject(PSHCLTRANSFER pTransfer,
+ LPFORMATETC pFormatEtc = NULL, LPSTGMEDIUM pStgMed = NULL, ULONG cFormats = 0);
+ virtual ~SharedClipboardWinDataObject(void);
+
+public: /* IUnknown methods. */
+
+ STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject);
+ STDMETHOD_(ULONG, AddRef)(void);
+ STDMETHOD_(ULONG, Release)(void);
+
+public: /* IDataObject methods. */
+
+ STDMETHOD(GetData)(LPFORMATETC pFormatEtc, LPSTGMEDIUM pMedium);
+ STDMETHOD(GetDataHere)(LPFORMATETC pFormatEtc, LPSTGMEDIUM pMedium);
+ STDMETHOD(QueryGetData)(LPFORMATETC pFormatEtc);
+ STDMETHOD(GetCanonicalFormatEtc)(LPFORMATETC pFormatEct, LPFORMATETC pFormatEtcOut);
+ STDMETHOD(SetData)(LPFORMATETC pFormatEtc, LPSTGMEDIUM pMedium, BOOL fRelease);
+ STDMETHOD(EnumFormatEtc)(DWORD dwDirection, IEnumFORMATETC **ppEnumFormatEtc);
+ STDMETHOD(DAdvise)(LPFORMATETC pFormatEtc, DWORD advf, IAdviseSink *pAdvSink, DWORD *pdwConnection);
+ STDMETHOD(DUnadvise)(DWORD dwConnection);
+ STDMETHOD(EnumDAdvise)(IEnumSTATDATA **ppEnumAdvise);
+
+#ifdef VBOX_WITH_SHARED_CLIPBOARD_WIN_ASYNC
+public: /* IDataObjectAsyncCapability methods. */
+
+ STDMETHOD(EndOperation)(HRESULT hResult, IBindCtx* pbcReserved, DWORD dwEffects);
+ STDMETHOD(GetAsyncMode)(BOOL* pfIsOpAsync);
+ STDMETHOD(InOperation)(BOOL* pfInAsyncOp);
+ STDMETHOD(SetAsyncMode)(BOOL fDoOpAsync);
+ STDMETHOD(StartOperation)(IBindCtx* pbcReserved);
+#endif /* VBOX_WITH_SHARED_CLIPBOARD_WIN_ASYNC */
+
+public:
+
+ int Init(void);
+ void OnTransferComplete(int rc = VINF_SUCCESS);
+ void OnTransferCanceled();
+
+public:
+
+ static DECLCALLBACK(int) readThread(RTTHREAD ThreadSelf, void *pvUser);
+
+ static void logFormat(CLIPFORMAT fmt);
+
+protected:
+
+ static int Thread(RTTHREAD hThread, void *pvUser);
+
+ int readDir(PSHCLTRANSFER pTransfer, const Utf8Str &strPath);
+
+ int copyToHGlobal(const void *pvData, size_t cbData, UINT fFlags, HGLOBAL *phGlobal);
+ int createFileGroupDescriptorFromTransfer(PSHCLTRANSFER pTransfer,
+ bool fUnicode, HGLOBAL *phGlobal);
+
+ bool lookupFormatEtc(LPFORMATETC pFormatEtc, ULONG *puIndex);
+ void registerFormat(LPFORMATETC pFormatEtc, CLIPFORMAT clipFormat, TYMED tyMed = TYMED_HGLOBAL,
+ LONG lindex = -1, DWORD dwAspect = DVASPECT_CONTENT, DVTARGETDEVICE *pTargetDevice = NULL);
+protected:
+
+ /**
+ * Structure for keeping a single file system object entry.
+ */
+ struct FSOBJENTRY
+ {
+ /** Relative path of the object. */
+ Utf8Str strPath;
+ /** Related (cached) object information. */
+ SHCLFSOBJINFO objInfo;
+ };
+
+ /** Vector containing file system objects with its (cached) objection information. */
+ typedef std::vector<FSOBJENTRY> FsObjEntryList;
+
+ /** The object's current status. */
+ Status m_enmStatus;
+ /** The object's current reference count. */
+ LONG m_lRefCount;
+ /** How many formats have been registered. */
+ ULONG m_cFormats;
+ LPFORMATETC m_pFormatEtc;
+ LPSTGMEDIUM m_pStgMedium;
+ /** Pointer to the associated transfer object being handled. */
+ PSHCLTRANSFER m_pTransfer;
+ /** Current stream object being used. */
+ IStream *m_pStream;
+ /** Current object index being handled by the data object.
+ * This is needed to create the next IStream object for e.g. the next upcoming file/dir/++ in the transfer. */
+ ULONG m_uObjIdx;
+ /** List of (cached) file system objects. */
+ FsObjEntryList m_lstEntries;
+ /** Whether the transfer thread is running. */
+ bool m_fRunning;
+ /** Event being triggered when reading the transfer list been completed. */
+ RTSEMEVENT m_EventListComplete;
+ /** Event being triggered when the transfer has been completed. */
+ RTSEMEVENT m_EventTransferComplete;
+ /** Registered format for CFSTR_FILEDESCRIPTORA. */
+ UINT m_cfFileDescriptorA;
+ /** Registered format for CFSTR_FILEDESCRIPTORW. */
+ UINT m_cfFileDescriptorW;
+ /** Registered format for CFSTR_FILECONTENTS. */
+ UINT m_cfFileContents;
+ /** Registered format for CFSTR_PERFORMEDDROPEFFECT. */
+ UINT m_cfPerformedDropEffect;
+};
+
+class SharedClipboardWinEnumFormatEtc : public IEnumFORMATETC
+{
+public:
+
+ SharedClipboardWinEnumFormatEtc(LPFORMATETC pFormatEtc, ULONG cFormats);
+ virtual ~SharedClipboardWinEnumFormatEtc(void);
+
+public: /* IUnknown methods. */
+
+ STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject);
+ STDMETHOD_(ULONG, AddRef)(void);
+ STDMETHOD_(ULONG, Release)(void);
+
+public: /* IEnumFORMATETC methods. */
+
+ STDMETHOD(Next)(ULONG cFormats, LPFORMATETC pFormatEtc, ULONG *pcFetched);
+ STDMETHOD(Skip)(ULONG cFormats);
+ STDMETHOD(Reset)(void);
+ STDMETHOD(Clone)(IEnumFORMATETC **ppEnumFormatEtc);
+
+public:
+
+ static void CopyFormat(LPFORMATETC pFormatDest, LPFORMATETC pFormatSource);
+ static HRESULT CreateEnumFormatEtc(UINT cFormats, LPFORMATETC pFormatEtc, IEnumFORMATETC **ppEnumFormatEtc);
+
+private:
+
+ LONG m_lRefCount;
+ ULONG m_nIndex;
+ ULONG m_nNumFormats;
+ LPFORMATETC m_pFormatEtc;
+};
+
+/**
+ * Own IStream implementation to implement file-based clipboard operations
+ * through HGCM. Needed on Windows hosts and guests.
+ */
+class SharedClipboardWinStreamImpl : public IStream
+{
+public:
+
+ SharedClipboardWinStreamImpl(SharedClipboardWinDataObject *pParent, PSHCLTRANSFER pTransfer,
+ const Utf8Str &strPath, PSHCLFSOBJINFO pObjInfo);
+ virtual ~SharedClipboardWinStreamImpl(void);
+
+public: /* IUnknown methods. */
+
+ STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject);
+ STDMETHOD_(ULONG, AddRef)(void);
+ STDMETHOD_(ULONG, Release)(void);
+
+public: /* IStream methods. */
+
+ STDMETHOD(Clone)(IStream** ppStream);
+ STDMETHOD(Commit)(DWORD dwFrags);
+ STDMETHOD(CopyTo)(IStream* pDestStream, ULARGE_INTEGER nBytesToCopy, ULARGE_INTEGER* nBytesRead, ULARGE_INTEGER* nBytesWritten);
+ STDMETHOD(LockRegion)(ULARGE_INTEGER nStart, ULARGE_INTEGER nBytes,DWORD dwFlags);
+ STDMETHOD(Read)(void* pvBuffer, ULONG nBytesToRead, ULONG* nBytesRead);
+ STDMETHOD(Revert)(void);
+ STDMETHOD(Seek)(LARGE_INTEGER nMove, DWORD dwOrigin, ULARGE_INTEGER* nNewPos);
+ STDMETHOD(SetSize)(ULARGE_INTEGER nNewSize);
+ STDMETHOD(Stat)(STATSTG* statstg, DWORD dwFlags);
+ STDMETHOD(UnlockRegion)(ULARGE_INTEGER nStart, ULARGE_INTEGER nBytes, DWORD dwFlags);
+ STDMETHOD(Write)(const void* pvBuffer, ULONG nBytesToRead, ULONG* nBytesRead);
+
+public: /* Own methods. */
+
+ static HRESULT Create(SharedClipboardWinDataObject *pParent, PSHCLTRANSFER pTransfer, const Utf8Str &strPath,
+ PSHCLFSOBJINFO pObjInfo, IStream **ppStream);
+private:
+
+ /** Pointer to the parent data object. */
+ SharedClipboardWinDataObject *m_pParent;
+ /** The stream object's current reference count. */
+ LONG m_lRefCount;
+ /** Pointer to the associated Shared Clipboard transfer. */
+ PSHCLTRANSFER m_pTransfer;
+ /** The object handle to use. */
+ SHCLOBJHANDLE m_hObj;
+ /** Object path. */
+ Utf8Str m_strPath;
+ /** (Cached) object information. */
+ SHCLFSOBJINFO m_objInfo;
+ /** Number of bytes already processed. */
+ uint64_t m_cbProcessed;
+ /** Whether this object already is in completed state or not. */
+ bool m_fIsComplete;
+};
+
+/**
+ * Class for Windows-specifics for maintaining a single Shared Clipboard transfer.
+ * Set as pvUser / cbUser in SHCLTRANSFERCTX.
+ */
+class SharedClipboardWinTransferCtx
+{
+public:
+ SharedClipboardWinTransferCtx()
+ : pDataObj(NULL) { }
+
+ virtual ~SharedClipboardWinTransferCtx()
+ {
+ if (pDataObj)
+ delete pDataObj;
+ }
+
+ /** Pointer to data object to use for this transfer.
+ * Can be NULL if not being used. */
+ SharedClipboardWinDataObject *pDataObj;
+};
+# endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS */
+#endif /* !VBOX_INCLUDED_GuestHost_SharedClipboard_win_h */
+
diff --git a/include/VBox/GuestHost/SharedClipboard-x11.h b/include/VBox/GuestHost/SharedClipboard-x11.h
new file mode 100644
index 00000000..c06f2dd2
--- /dev/null
+++ b/include/VBox/GuestHost/SharedClipboard-x11.h
@@ -0,0 +1,187 @@
+/** @file
+ * Shared Clipboard - Common X11 code.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_GuestHost_SharedClipboard_x11_h
+#define VBOX_INCLUDED_GuestHost_SharedClipboard_x11_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <X11/Intrinsic.h>
+
+#include <iprt/thread.h>
+
+#include <VBox/GuestHost/SharedClipboard.h>
+#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
+# include <VBox/GuestHost/SharedClipboard-transfers.h>
+#endif
+
+/**
+ * The maximum number of simultaneous connections to shared clipboard service.
+ * This constant limits amount of GUEST -> HOST connections to shared clipboard host service
+ * for X11 host only. Once amount of connections reaches this number, all the
+ * further attempts to CONNECT will be dropped on an early stage. Possibility to connect
+ * is available again after one of existing connections is closed by DISCONNECT call.
+ */
+#define VBOX_SHARED_CLIPBOARD_X11_CONNECTIONS_MAX (20)
+
+/** Enables the Xt busy / update handling. */
+#define VBOX_WITH_SHARED_CLIPBOARD_XT_BUSY 1
+
+/**
+ * Enumeration for all clipboard formats which we support on X11.
+ */
+typedef enum _SHCLX11FMT
+{
+ SHCLX11FMT_INVALID = 0,
+ SHCLX11FMT_TARGETS,
+ SHCLX11FMT_TEXT, /* Treat this as UTF-8, but it may really be ascii */
+ SHCLX11FMT_UTF8,
+ SHCLX11FMT_BMP,
+ SHCLX11FMT_HTML
+#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
+ , SHCLX11FMT_URI_LIST
+#endif
+} SHCLX11FMT;
+
+/**
+ * The table maps X11 names to data formats
+ * and to the corresponding VBox clipboard formats.
+ */
+typedef struct SHCLX11FMTTABLE
+{
+ /** The X11 atom name of the format (several names can match one format). */
+ const char *pcszAtom;
+ /** The format corresponding to the name. */
+ SHCLX11FMT enmFmtX11;
+ /** The corresponding VBox clipboard format. */
+ SHCLFORMAT uFmtVBox;
+} SHCLX11FMTTABLE;
+
+#define NIL_CLIPX11FORMAT 0
+
+/** Defines an index of the X11 clipboad format table. */
+typedef unsigned SHCLX11FMTIDX;
+
+/**
+ * Structure for maintaining a Shared Clipboard context on X11 platforms.
+ */
+typedef struct _SHCLX11CTX
+{
+ /** Opaque data structure describing the front-end. */
+ PSHCLCONTEXT pFrontend;
+ /** Our callback table to use. */
+ SHCLCALLBACKS Callbacks;
+ /** Is an X server actually available? */
+ bool fHaveX11;
+ /** The X Toolkit application context structure. */
+ XtAppContext pAppContext;
+ /** We have a separate thread to wait for window and clipboard events. */
+ RTTHREAD Thread;
+ /** Flag indicating that the thread is in a started state. */
+ bool fThreadStarted;
+ /** The X Toolkit widget which we use as our clipboard client. It is never made visible. */
+ Widget pWidget;
+ /** Should we try to grab the clipboard on startup? */
+ bool fGrabClipboardOnStart;
+ /** The best text format X11 has to offer, as an index into the formats table. */
+ SHCLX11FMTIDX idxFmtText;
+ /** The best bitmap format X11 has to offer, as an index into the formats table. */
+ SHCLX11FMTIDX idxFmtBmp;
+ /** The best HTML format X11 has to offer, as an index into the formats table. */
+ SHCLX11FMTIDX idxFmtHTML;
+#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
+ /** The best HTML format X11 has to offer, as an index into the formats table. */
+ SHCLX11FMTIDX idxFmtURI;
+# ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS_HTTP
+ /** HTTP transfer context data. */
+ SHCLHTTPCONTEXT HttpCtx;
+# endif
+#endif
+ /** What kind of formats does VBox have to offer? */
+ SHCLFORMATS vboxFormats;
+ /** Cache of the last unicode data that we received. */
+ void *pvUnicodeCache;
+ /** Size of the unicode data in the cache. */
+ uint32_t cbUnicodeCache;
+ /** When we wish the clipboard to exit, we have to wake up the event
+ * loop. We do this by writing into a pipe. This end of the pipe is
+ * the end that another thread can write to. */
+ int wakeupPipeWrite;
+ /** The reader end of the pipe. */
+ int wakeupPipeRead;
+ /** A pointer to the XFixesSelectSelectionInput function. */
+ void (*fixesSelectInput)(Display *, Window, Atom, unsigned long);
+ /** The first XFixes event number. */
+ int fixesEventBase;
+#ifdef VBOX_WITH_SHARED_CLIPBOARD_XT_BUSY
+ /** XtGetSelectionValue on some versions of libXt isn't re-entrant
+ * so block overlapping requests on this flag. */
+ bool fXtBusy;
+ /** If a request is blocked on the previous flag, set this flag to request
+ * an update later - the first callback should check and clear this flag
+ * before processing the callback event. */
+ bool fXtNeedsUpdate;
+#endif
+} SHCLX11CTX, *PSHCLX11CTX;
+
+/**
+ * Structure for keeping a X11 read data request.
+ */
+typedef struct _SHCLX11READDATAREQ
+{
+ /** Actual read request to handle. */
+ CLIPREADCBREQ *pReq;
+ /** Result code of the operation on completion. */
+ int rcCompletion;
+} SHCLX11READDATAREQ;
+/** Pointer to a send data request. */
+typedef SHCLX11READDATAREQ *PSHCLX11READDATAREQ;
+
+/** @name Shared Clipboard APIs for X11.
+ * @{
+ */
+int ShClX11Init(PSHCLX11CTX pCtx, PSHCLCALLBACKS pCallbacks, PSHCLCONTEXT pParent, bool fHeadless);
+void ShClX11Destroy(PSHCLX11CTX pCtx);
+int ShClX11ThreadStart(PSHCLX11CTX pCtx, bool grab);
+int ShClX11ThreadStartEx(PSHCLX11CTX pCtx, const char *pszName, bool fGrab);
+int ShClX11ThreadStop(PSHCLX11CTX pCtx);
+int ShClX11ReportFormatsToX11(PSHCLX11CTX pCtx, SHCLFORMATS vboxFormats);
+int ShClX11ReadDataFromX11(PSHCLX11CTX pCtx, SHCLFORMATS vboxFormat, CLIPREADCBREQ *pReq);
+void ShClX11SetCallbacks(PSHCLX11CTX pCtx, PSHCLCALLBACKS pCallbacks);
+/** @} */
+
+#endif /* !VBOX_INCLUDED_GuestHost_SharedClipboard_x11_h */
+
diff --git a/include/VBox/GuestHost/SharedClipboard.h b/include/VBox/GuestHost/SharedClipboard.h
new file mode 100644
index 00000000..ef61bc6c
--- /dev/null
+++ b/include/VBox/GuestHost/SharedClipboard.h
@@ -0,0 +1,354 @@
+/** @file
+ * Shared Clipboard - Common guest and host Code.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_GuestHost_SharedClipboard_h
+#define VBOX_INCLUDED_GuestHost_SharedClipboard_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/critsect.h>
+#include <iprt/types.h>
+#include <iprt/list.h>
+
+/** @name VBOX_SHCL_FMT_XXX - Data formats (flags) for Shared Clipboard.
+ * @{
+ */
+/** No format set. */
+#define VBOX_SHCL_FMT_NONE 0
+/** Shared Clipboard format is an Unicode text. */
+#define VBOX_SHCL_FMT_UNICODETEXT RT_BIT(0)
+/** Shared Clipboard format is bitmap (BMP / DIB). */
+#define VBOX_SHCL_FMT_BITMAP RT_BIT(1)
+/** Shared Clipboard format is HTML. */
+#define VBOX_SHCL_FMT_HTML RT_BIT(2)
+#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
+/** Shared Clipboard format is a transfer list. */
+# define VBOX_SHCL_FMT_URI_LIST RT_BIT(3)
+#endif
+/** @} */
+
+
+/** A single Shared Clipboard format (VBOX_SHCL_FMT_XXX). */
+typedef uint32_t SHCLFORMAT;
+/** Pointer to a single Shared Clipboard format (VBOX_SHCL_FMT_XXX). */
+typedef SHCLFORMAT *PSHCLFORMAT;
+
+/** Bit map (flags) of Shared Clipboard formats (VBOX_SHCL_FMT_XXX). */
+typedef uint32_t SHCLFORMATS;
+/** Pointer to a bit map of Shared Clipboard formats (VBOX_SHCL_FMT_XXX). */
+typedef SHCLFORMATS *PSHCLFORMATS;
+
+
+/**
+ * Shared Clipboard transfer direction.
+ */
+typedef enum SHCLTRANSFERDIR
+{
+ /** Unknown transfer directory. */
+ SHCLTRANSFERDIR_UNKNOWN = 0,
+ /** Read transfer (from source). */
+ SHCLTRANSFERDIR_FROM_REMOTE,
+ /** Write transfer (to target). */
+ SHCLTRANSFERDIR_TO_REMOTE,
+ /** The usual 32-bit hack. */
+ SHCLTRANSFERDIR_32BIT_HACK = 0x7fffffff
+} SHCLTRANSFERDIR;
+/** Pointer to a shared clipboard transfer direction. */
+typedef SHCLTRANSFERDIR *PSHCLTRANSFERDIR;
+
+
+/**
+ * Shared Clipboard data read request.
+ */
+typedef struct SHCLDATAREQ
+{
+ /** In which format the data needs to be sent. */
+ SHCLFORMAT uFmt;
+ /** Read flags; currently unused. */
+ uint32_t fFlags;
+ /** Maximum data (in byte) can be sent. */
+ uint32_t cbSize;
+} SHCLDATAREQ;
+/** Pointer to a shared clipboard data request. */
+typedef SHCLDATAREQ *PSHCLDATAREQ;
+
+/**
+ * Shared Clipboard event payload (optional).
+ */
+typedef struct SHCLEVENTPAYLOAD
+{
+ /** Payload ID; currently unused. */
+ uint32_t uID;
+ /** Size (in bytes) of actual payload data. */
+ uint32_t cbData;
+ /** Pointer to actual payload data. */
+ void *pvData;
+} SHCLEVENTPAYLOAD;
+/** Pointer to a shared clipboard event payload. */
+typedef SHCLEVENTPAYLOAD *PSHCLEVENTPAYLOAD;
+
+/** A shared clipboard event source ID. */
+typedef uint16_t SHCLEVENTSOURCEID;
+/** Pointer to a shared clipboard event source ID. */
+typedef SHCLEVENTSOURCEID *PSHCLEVENTSOURCEID;
+
+/** A shared clipboard session ID. */
+typedef uint16_t SHCLSESSIONID;
+/** Pointer to a shared clipboard session ID. */
+typedef SHCLSESSIONID *PSHCLSESSIONID;
+/** NIL shared clipboard session ID. */
+#define NIL_SHCLSESSIONID UINT16_MAX
+
+/** A shared clipboard transfer ID. */
+typedef uint16_t SHCLTRANSFERID;
+/** Pointer to a shared clipboard transfer ID. */
+typedef SHCLTRANSFERID *PSHCLTRANSFERID;
+/** NIL shared clipboardtransfer ID. */
+#define NIL_SHCLTRANSFERID UINT16_MAX
+
+/** A shared clipboard event ID. */
+typedef uint32_t SHCLEVENTID;
+/** Pointer to a shared clipboard event source ID. */
+typedef SHCLEVENTID *PSHCLEVENTID;
+/** NIL shared clipboard event ID. */
+#define NIL_SHCLEVENTID UINT32_MAX
+
+/** Pointer to a shared clipboard event source.
+ * Forward declaration, needed for SHCLEVENT. */
+typedef struct SHCLEVENTSOURCE *PSHCLEVENTSOURCE;
+
+/**
+ * Shared Clipboard event.
+ */
+typedef struct SHCLEVENT
+{
+ /** List node. */
+ RTLISTNODE Node;
+ /** Parent (source) this event belongs to. */
+ PSHCLEVENTSOURCE pParent;
+ /** The event's ID, for self-reference. */
+ SHCLEVENTID idEvent;
+ /** Reference count to this event. */
+ uint32_t cRefs;
+ /** Event semaphore for signalling the event. */
+ RTSEMEVENTMULTI hEvtMulSem;
+ /** Payload to this event, optional (NULL). */
+ PSHCLEVENTPAYLOAD pPayload;
+} SHCLEVENT;
+/** Pointer to a shared clipboard event. */
+typedef SHCLEVENT *PSHCLEVENT;
+
+/**
+ * Shared Clipboard event source.
+ *
+ * Each event source maintains an own counter for events, so that it can be used
+ * in different contexts.
+ */
+typedef struct SHCLEVENTSOURCE
+{
+ /** The event source ID. */
+ SHCLEVENTSOURCEID uID;
+ /** Critical section for serializing access. */
+ RTCRITSECT CritSect;
+ /** Next upcoming event ID. */
+ SHCLEVENTID idNextEvent;
+ /** List of events (PSHCLEVENT). */
+ RTLISTANCHOR lstEvents;
+} SHCLEVENTSOURCE;
+
+/** @name Shared Clipboard data payload functions.
+ * @{
+ */
+int ShClPayloadAlloc(uint32_t uID, const void *pvData, uint32_t cbData, PSHCLEVENTPAYLOAD *ppPayload);
+void ShClPayloadFree(PSHCLEVENTPAYLOAD pPayload);
+/** @} */
+
+/** @name Shared Clipboard event source functions.
+ * @{
+ */
+int ShClEventSourceCreate(PSHCLEVENTSOURCE pSource, SHCLEVENTSOURCEID idEvtSrc);
+int ShClEventSourceDestroy(PSHCLEVENTSOURCE pSource);
+void ShClEventSourceReset(PSHCLEVENTSOURCE pSource);
+int ShClEventSourceGenerateAndRegisterEvent(PSHCLEVENTSOURCE pSource, PSHCLEVENT *ppEvent);
+PSHCLEVENT ShClEventSourceGetFromId(PSHCLEVENTSOURCE pSource, SHCLEVENTID idEvent);
+PSHCLEVENT ShClEventSourceGetLast(PSHCLEVENTSOURCE pSource);
+/** @} */
+
+/** @name Shared Clipboard event functions.
+ * @{
+ */
+uint32_t ShClEventGetRefs(PSHCLEVENT pEvent);
+uint32_t ShClEventRetain(PSHCLEVENT pEvent);
+uint32_t ShClEventRelease(PSHCLEVENT pEvent);
+int ShClEventSignal(PSHCLEVENT pEvent, PSHCLEVENTPAYLOAD pPayload);
+int ShClEventWait(PSHCLEVENT pEvent, RTMSINTERVAL uTimeoutMs, PSHCLEVENTPAYLOAD *ppPayload);
+/** @} */
+
+/**
+ * Shared Clipboard transfer source type.
+ * @note Part of saved state!
+ */
+typedef enum SHCLSOURCE
+{
+ /** Invalid source type. */
+ SHCLSOURCE_INVALID = 0,
+ /** Source is local. */
+ SHCLSOURCE_LOCAL,
+ /** Source is remote. */
+ SHCLSOURCE_REMOTE,
+ /** The usual 32-bit hack. */
+ SHCLSOURCE_32BIT_HACK = 0x7fffffff
+} SHCLSOURCE;
+
+/** Opaque data structure for the X11/VBox frontend/glue code.
+ * @{ */
+struct SHCLCONTEXT;
+typedef struct SHCLCONTEXT SHCLCONTEXT;
+/** @} */
+/** Pointer to opaque data structure the X11/VBox frontend/glue code. */
+typedef SHCLCONTEXT *PSHCLCONTEXT;
+
+/**
+ * @name Shared Clipboard callback table.
+ *
+ * This table gets used by
+ * - the backends on the host (where required)
+ * - guest side implementations (e.g. VBoxClient)
+ * - by the underlying core code (e.g. X11 backend -> X11 common code -> callback)
+ *
+ * Some clipboard mechanisms (e.g. X11) require asynchronous and/or event-driven handling
+ * of clipboard data, making it hard to control our program flow when testing stuff.
+ *
+ * So overriding required callbacks on runtime for testing purposes makes this approach much
+ * more flexible without implementing separate code paths for production code and test units.
+ *
+ * @{
+ */
+typedef struct _SHCLCALLBACKS
+{
+ /**
+ * Callback for reporting supported clipoard formats of current clipboard data.
+ *
+ * @note On X11:
+ * Runs in Xt event thread for the X11 code.
+ *
+ * @returns VBox status code.
+ * @param pCtx Opaque context pointer for the glue code.
+ * @param fFormats The formats available.
+ * @param pvUser Implementation-dependent pointer to data for fullfilling the request.
+ * Optional and can be NULL.
+ */
+ DECLCALLBACKMEMBER(int, pfnReportFormats, (PSHCLCONTEXT pCtx, SHCLFORMATS fFormats, void *pvUser));
+
+ /**
+ * Callback for reading data from the clipboard.
+ * Optional and can be NULL.
+ *
+ * @note Used for testing X11 clipboard code.
+ *
+ * @returns VBox status code.
+ * @param pCtx Opaque context pointer for the glue code.
+ * @param uFmt The format in which the data should be read
+ * (VBOX_SHCL_FMT_XXX).
+ * @param ppv Returns an allocated buffer with data from on success.
+ * Needs to be free'd with RTMemFree() by the caller.
+ * @param pcb Returns the amount of data read (in bytes) on success.
+ * @param pvUser Implementation-dependent pointer to data for fullfilling the request.
+ * Optional and can be NULL.
+ */
+ DECLCALLBACKMEMBER(int, pfnOnClipboardRead, (PSHCLCONTEXT pCtx, SHCLFORMAT uFmt, void **ppv, size_t *pcb, void *pvUser));
+
+ /**
+ * Callback for writing data to the clipboard.
+ * Optional and can be NULL.
+ *
+ * @note Used for testing X11 clipboard code.
+ *
+ * @returns VBox status code.
+ * @param pCtx Opaque context pointer for the glue code.
+ * @param uFmt The format in which the data should be written as
+ * (VBOX_SHCL_FMT_XXX).
+ * @param pv The clipboard data to write.
+ * @param cb The size of the data in @a pv.
+ * @param pvUser Implementation-dependent pointer to data for fullfilling the request.
+ * Optional and can be NULL.
+ */
+ DECLCALLBACKMEMBER(int, pfnOnClipboardWrite, (PSHCLCONTEXT pCtx, SHCLFORMAT uFmt, void *pv, size_t cb, void *pvUser));
+
+ /**
+ * Callback for requesting clipboard data from the source.
+ *
+ * @note On X11:
+ * The function will be invoked for every single target the clipboard requests.
+ * Runs in Xt event thread for the X11 code.
+ *
+ * @returns VBox status code. VERR_NO_DATA if no data available.
+ * @param pCtx Opaque context pointer for the glue code.
+ * @param uFmt The format in which the data should be transferred
+ * (VBOX_SHCL_FMT_XXX).
+ * @param ppv Returns an allocated buffer with data read from the guest on success.
+ * Needs to be free'd with RTMemFree() by the caller.
+ * @param pcb Returns the amount of data read (in bytes) on success.
+ * @param pvUser Implementation-dependent pointer to data for fullfilling the request.
+ * Optional and can be NULL.
+ * On X11: Of type PSHCLX11READDATAREQ; We RTMemFree() this in this function.
+ */
+ DECLCALLBACKMEMBER(int, pfnOnRequestDataFromSource, (PSHCLCONTEXT pCtx, SHCLFORMAT uFmt, void **ppv, uint32_t *pcb, void *pvUser));
+
+ /**
+ * Callback for sending clipboard data to the destination.
+ *
+ * @returns VBox status code.
+ * @param pCtx Opaque context pointer for the glue code.
+ * @param pv The clipboard data returned if the request succeeded.
+ * @param cb The size of the data in @a pv.
+ * @param pvUser Implementation-dependent pointer to data for fullfilling the request.
+ * Optional and can be NUL
+ * On X11: Of type PSHCLX11READDATAREQ.
+ */
+ DECLCALLBACKMEMBER(int, pfnOnSendDataToDest, (PSHCLCONTEXT pCtx, void *pv, uint32_t cb, void *pvUser));
+} SHCLCALLBACKS;
+typedef SHCLCALLBACKS *PSHCLCALLBACKS;
+/** @} */
+
+/** Opaque request structure for X11 clipboard data.
+ * @{ */
+struct CLIPREADCBREQ;
+typedef struct CLIPREADCBREQ CLIPREADCBREQ;
+/** @} */
+
+#endif /* !VBOX_INCLUDED_GuestHost_SharedClipboard_h */
+
diff --git a/include/VBox/GuestHost/clipboard-helper.h b/include/VBox/GuestHost/clipboard-helper.h
new file mode 100644
index 00000000..e1c4ad9d
--- /dev/null
+++ b/include/VBox/GuestHost/clipboard-helper.h
@@ -0,0 +1,250 @@
+/* $Id: clipboard-helper.h $ */
+/** @file
+ * Shared Clipboard - Some helper function for converting between the various EOLs.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_GuestHost_clipboard_helper_h
+#define VBOX_INCLUDED_GuestHost_clipboard_helper_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/string.h>
+
+#include <VBox/GuestHost/SharedClipboard.h>
+
+/** Constants needed for string conversions done by the Linux/Mac clipboard code. */
+enum
+{
+ /** In Linux, lines end with a linefeed character. */
+ VBOX_SHCL_LINEFEED = 0xa,
+ /** In Windows, lines end with a carriage return and a linefeed character. */
+ VBOX_SHCL_CARRIAGERETURN = 0xd,
+ /** Little endian "real" UTF-16 strings start with this marker. */
+ VBOX_SHCL_UTF16LEMARKER = 0xfeff,
+ /** Big endian "real" UTF-16 strings start with this marker. */
+ VBOX_SHCL_UTF16BEMARKER = 0xfffe
+};
+
+/**
+ * Returns the length (in UTF-8 characters) of an UTF-16 string with LF EOL.
+ *
+ * @returns VBox status code.
+ * @param pcwszSrc UTF-16 string to return size for.
+ * @param cwcSrc Length of the string in RTUTF16 units.
+ * @param pchLen Where to return the length (in UTF-8 characters).
+ * Does not include terminator.
+ */
+int ShClUtf16LFLenUtf8(PCRTUTF16 pcwszSrc, size_t cwcSrc, size_t *pchLen);
+
+/**
+ * Returns the length (in UTF-8 characters) of an UTF-16 string with CRLF EOL.
+ *
+ * @returns VBox status code.
+ * @param pcwszSrc UTF-16 string to return size for.
+ * @param cwcSrc Length of the source string in RTUTF16 units.
+ * @param pchLen Where to return the length (in UTF-8 characters).
+ * Does not include terminator.
+ */
+int ShClUtf16CRLFLenUtf8(PCRTUTF16 pcwszSrc, size_t cwcSrc, size_t *pchLen);
+
+/**
+ * Returns the length (in characters) of an UTF-16 string, including terminator.
+ *
+ * @returns VBox status code.
+ * @param pcwszSrc UTF-16 string to return size for.
+ * @param cwcSrc Length of the source string in RTUTF16 units.
+ * @param pchLen Where to return the length (in UTF-8 characters).
+ * Does not include terminator.
+ */
+int ShClUtf16LenUtf8(PCRTUTF16 pcwszSrc, size_t cwcSrc, size_t *pchLen);
+
+/**
+ * Converts an UTF-16 string with LF EOL to an UTF-16 string with CRLF EOL.
+ *
+ * @returns VBox status code.
+ * @param pcwszSrc UTF-16 string to convert.
+ * @param cwcSrc Size of the string int RTUTF16 units.
+ * @param pwszDst Buffer to store the converted string to.
+ * @param cwcDst The size of \a pwszDst in RTUTF16 units.
+ */
+int ShClConvUtf16LFToCRLF(PCRTUTF16 pcwszSrc, size_t cwcSrc, PRTUTF16 pwszDst, size_t cwcDst);
+
+/**
+ * Converts an UTF-16 string with LF EOL to an UTF-16 string with CRLF EOL.
+ *
+ * Convenience function which returns the allocated + converted string on success.
+ *
+ * @returns VBox status code.
+ * @param pcwszSrc UTF-16 string to convert.
+ * @param cwcSrc Size of the string int RTUTF16 units.
+ * @param ppwszDst Where to return the allocated converted string. Must be free'd by the caller.
+ * @param pcwDst Where to return the size of the converted string in RTUTF16 units.
+ * Does not include the terminator.
+ */
+int ShClConvUtf16LFToCRLFA(PCRTUTF16 pcwszSrc, size_t cwcSrc, PRTUTF16 *ppwszDst, size_t *pcwDst);
+
+/**
+ * Converts an UTF-16 string with CRLF EOL to an UTF-16 string with LF EOL.
+ *
+ * @returns VBox status code.
+ * @param pcwszSrc UTF-16 string to convert.
+ * @param cwcSrc Size of the string in RTUTF16 units.
+ * @param pwszDst Where to store the converted string to.
+ * @param cwcDst The size of \a pwszDst in RTUTF16 units.
+ */
+int ShClConvUtf16CRLFToLF(PCRTUTF16 pcwszSrc, size_t cwcSrc, PRTUTF16 pwszDst, size_t cwcDst);
+
+/**
+ * Converts an UTF-16 string with CRLF EOL to UTF-8 LF.
+ *
+ * @returns VBox status code. Will return VERR_NO_DATA if no data was converted.
+ * @param pcwszSrc UTF-16 string to convert.
+ * @param cbSrc Length of @a pwszSrc (in bytes).
+ * @param pszBuf Where to write the converted string.
+ * @param cbBuf The size of the buffer pointed to by @a pszBuf.
+ * @param pcbLen Where to store the size (in bytes) of the converted string.
+ * Does not include terminator.
+ */
+int ShClConvUtf16CRLFToUtf8LF(PCRTUTF16 pcwszSrc, size_t cbSrc, char *pszBuf, size_t cbBuf, size_t *pcbLen);
+
+/**
+* Converts an HTML string from UTF-16 into UTF-8.
+*
+* @returns VBox status code.
+* @param pcwszSrc UTF-16 string to convert.
+* @param cwcSrc Length (in RTUTF16 units) of the source text.
+* @param ppszDst Where to store the converted result on success.
+* @param pcbDst Where to store the number of bytes written.
+*/
+int ShClConvUtf16ToUtf8HTML(PCRTUTF16 pcwszSrc, size_t cwcSrc, char **ppszDst, size_t *pcbDst);
+
+/**
+ * Converts an UTF-8 string with LF EOL into UTF-16 CRLF.
+ *
+ * @returns VBox status code.
+ * @param pcszSrc UTF-8 string to convert.
+ * @param cbSrc Size of UTF-8 string to convert (in bytes), not counting the terminating zero.
+ * @param ppwszDst Where to return the allocated buffer on success.
+ * @param pcwDst Where to return the size (in RTUTF16 units) of the allocated buffer on success.
+ * Does not include terminator.
+ */
+int ShClConvUtf8LFToUtf16CRLF(const char *pcszSrc, size_t cbSrc, PRTUTF16 *ppwszDst, size_t *pcwDst);
+
+/**
+ * Converts a Latin-1 string with LF EOL into UTF-16 CRLF.
+ *
+ * @returns VBox status code.
+ * @param pcszSrc UTF-8 string to convert.
+ * @param cbSrc Size of string (in bytes), not counting the terminating zero.
+ * @param ppwszDst Where to return the allocated buffer on success.
+ * @param pcwDst Where to return the size (in RTUTF16 units) of the allocated buffer on success.
+ * Does not include terminator.
+ */
+int ShClConvLatin1LFToUtf16CRLF(const char *pcszSrc, size_t cbSrc, PRTUTF16 *ppwszDst, size_t *pcwDst);
+
+/**
+ * Convert CF_DIB data to full BMP data by prepending the BM header.
+ * Allocates with RTMemAlloc.
+ *
+ * @returns VBox status code.
+ * @param pvSrc DIB data to convert
+ * @param cbSrc Size of the DIB data to convert in bytes
+ * @param ppvDst Where to store the pointer to the buffer for the
+ * destination data
+ * @param pcbDst Pointer to the size of the buffer for the destination
+ * data in bytes.
+ */
+int ShClDibToBmp(const void *pvSrc, size_t cbSrc, void **ppvDst, size_t *pcbDst);
+
+/**
+ * Get the address and size of CF_DIB data in a full BMP data in the input buffer.
+ * Does not do any allocation.
+ *
+ * @returns VBox status code.
+ * @param pvSrc BMP data to convert
+ * @param cbSrc Size of the BMP data to convert in bytes
+ * @param ppvDst Where to store the pointer to the destination data
+ * @param pcbDst Pointer to the size of the destination data in bytes
+ */
+int ShClBmpGetDib(const void *pvSrc, size_t cbSrc, const void **ppvDst, size_t *pcbDst);
+
+#ifdef LOG_ENABLED
+/**
+ * Dumps HTML data to the debug log.
+ *
+ * @returns VBox status code.
+ * @param pszSrc HTML data to dump.
+ * @param cbSrc Size (in bytes) of HTML data to dump.
+ */
+int ShClDbgDumpHtml(const char *pszSrc, size_t cbSrc);
+
+/**
+ * Dumps data using a specified clipboard format.
+ *
+ * @param pv Pointer to data to dump.
+ * @param cb Size (in bytes) of data to dump.
+ * @param u32Format Clipboard format to use for dumping.
+ */
+void ShClDbgDumpData(const void *pv, size_t cb, SHCLFORMAT u32Format);
+#endif /* LOG_ENABLED */
+
+/**
+ * Translates a Shared Clipboard host function number to a string.
+ *
+ * @returns Function ID string name.
+ * @param uFn The function to translate.
+ */
+const char *ShClHostFunctionToStr(uint32_t uFn);
+
+/**
+ * Translates a Shared Clipboard host message enum to a string.
+ *
+ * @returns Message ID string name.
+ * @param uMsg The message to translate.
+ */
+const char *ShClHostMsgToStr(uint32_t uMsg);
+
+/**
+ * Translates a Shared Clipboard guest message enum to a string.
+ *
+ * @returns Message ID string name.
+ * @param uMsg The message to translate.
+ */
+const char *ShClGuestMsgToStr(uint32_t uMsg);
+
+char *ShClFormatsToStrA(SHCLFORMATS fFormats);
+
+#endif /* !VBOX_INCLUDED_GuestHost_clipboard_helper_h */
+
diff --git a/include/VBox/HostServices/DragAndDropSvc.h b/include/VBox/HostServices/DragAndDropSvc.h
new file mode 100644
index 00000000..ba42cdef
--- /dev/null
+++ b/include/VBox/HostServices/DragAndDropSvc.h
@@ -0,0 +1,1198 @@
+/* $Id: DragAndDropSvc.h $ */
+/** @file
+ * Drag and Drop service - Common header for host service and guest clients.
+ */
+
+/*
+ * Copyright (C) 2011-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+/**
+ * Protocol handling and notes:
+ * All client/server components should be backwards compatible.
+ *
+ ******************************************************************************
+ *
+ * Protocol changelog:
+ *
+ * Protocol v1 (VBox < 5.0, deprecated):
+ * | Initial implementation which only implemented host to guest transfers.
+ * | For file transfers all file information such as the file name and file size were
+ * transferred with every file data chunk being sent.
+ *
+ * Protocol v2 (VBox 5.0 - VBox 5.0.8, deprecated):
+ * + Added support for guest to host transfers.
+ * + Added protocol version support through VBOXDNDCONNECTMSG. The host takes the installed
+ * Guest Additions version as indicator which protocol to use for communicating with the guest.
+ * The guest itself uses VBOXDNDCONNECTMSG to report its supported protocol version to the DnD service.
+ *
+ * Protocol v3 (VBox 5.0.10 and up, deprecated):
+ * + Added VBOXDNDDISCONNECTMSG for being able to track client disconnects on host side (Main).
+ * + Added context IDs for every HGCM message. Not used yet and must be 0.
+ * + Added VBOXDNDSNDDATAHDR and VBOXDNDCBSNDDATAHDRDATA to support (simple) accounting of objects
+ * being transferred, along with supplying separate meta data size (which is part of the total size being sent).
+ * + Added new HOST_DND_FN_HG_SND_DATA_HDR + GUEST_DND_FN_GH_SND_DATA_HDR commands which now allow specifying an optional
+ * compression type and defining a checksum for the overall data transfer.
+ * + Enhannced VBOXDNDGHSENDDATAMSG to support (rolling) checksums for the supplied data block.
+ * + VBOXDNDHGSENDDATAMSG and VBOXDNDGHSENDDATAMSG can now contain an optional checksum for the current data block.
+ * | VBOXDNDHGSENDFILEDATAMSG and VBOXDNDGHSENDFILEDATAMSG are now sharing the same HGCM mesasge.
+ * - Removed unused HOST_DND_FN_GH_RECV_DIR, HOST_DND_FN_GH_RECV_FILE_DATA and HOST_DND_FN_GH_RECV_FILE_HDR commands.
+ *
+ * VBox 6.1.x and up, current:
+ * + Added GUEST_DND_FN_QUERY_FEATURES + GUEST_DND_FN_REPORT_FEATURES.
+ * - Protocol versioning support in VBOXDNDCONNECTMSG is now marked as being deprecated.
+ *
+ ** @todo:
+ * - Split up messages which use VBOXDNDHGACTIONMSG into own functions and remove parameters which
+ * are not actually needed / used by a function. Why does HOST_DND_FN_HG_EVT_MOVE need all the format stuff, for example?
+ */
+
+#ifndef VBOX_INCLUDED_HostServices_DragAndDropSvc_h
+#define VBOX_INCLUDED_HostServices_DragAndDropSvc_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/hgcmsvc.h>
+#include <VBox/VMMDevCoreTypes.h>
+#include <VBox/VBoxGuestCoreTypes.h>
+
+#include <VBox/GuestHost/DragAndDropDefs.h>
+
+namespace DragAndDropSvc {
+
+/******************************************************************************
+* Typedefs, constants and inlines *
+******************************************************************************/
+
+/**
+ * The service functions which are callable by host.
+ * Note: When adding new functions to this table, make sure that the actual ID
+ * does *not* overlap with the eGuestFn enumeration below!
+ */
+enum eHostFn
+{
+ /** The host sets a new DnD mode. */
+ HOST_DND_FN_SET_MODE = 100,
+ /** The host requests to cancel the current DnD operation on
+ * the guest side. This can happen on user request on the host's
+ * UI side or due to some host error which has happened.
+ *
+ * Note: This is a fire-and-forget message, as the host should
+ * not rely on an answer from the guest side in order to
+ * properly cancel the operation. */
+ HOST_DND_FN_CANCEL = 204,
+
+ /*
+ * Host -> Guest messages
+ */
+
+ /** The host enters the VM window for starting an actual
+ * DnD operation. */
+ HOST_DND_FN_HG_EVT_ENTER = 200,
+ /** The host's DnD cursor moves within the VM window. */
+ HOST_DND_FN_HG_EVT_MOVE = 201,
+ /** The host leaves the guest VM window. */
+ HOST_DND_FN_HG_EVT_LEAVE = 202,
+ /** The host issues a "drop" event, meaning that the host is
+ * ready to transfer data over to the guest. */
+ HOST_DND_FN_HG_EVT_DROPPED = 203,
+ /** The host sends the data header at the beginning of a (new)
+ * data transfer. */
+ HOST_DND_FN_HG_SND_DATA_HDR = 210,
+ /**
+ * The host sends the actual meta data, based on
+ * the format(s) specified by HOST_DND_FN_HG_EVT_ENTER.
+ *
+ * Protocol v1/v2: If the guest supplied buffer too small to send
+ * the actual data, the host will send a HOST_DND_FN_HG_SND_MORE_DATA
+ * message as follow-up.
+ * Protocol v3+: The incoming meta data size is specified upfront in the
+ * HOST_DND_FN_HG_SND_DATA_HDR message and must be handled accordingly.
+ */
+ HOST_DND_FN_HG_SND_DATA = 205,
+ /** The host sends more data in case the data did not entirely fit in
+ * the HOST_DND_FN_HG_SND_DATA message. */
+ /** @todo Deprecated function; do not use anymore. */
+ HOST_DND_FN_HG_SND_MORE_DATA = 206,
+ /** The host sends a directory entry to the guest. */
+ HOST_DND_FN_HG_SND_DIR = 207,
+ /** The host sends a file data chunk to the guest. */
+ HOST_DND_FN_HG_SND_FILE_DATA = 208,
+ /** The host sends a file header to the guest.
+ * Note: Only for protocol version 2 and up (>= VBox 5.0). */
+ HOST_DND_FN_HG_SND_FILE_HDR = 209,
+
+ /*
+ * Guest -> Host messages
+ */
+
+ /** The host asks the guest whether a DnD operation
+ * is in progress when the mouse leaves the guest window. */
+ HOST_DND_FN_GH_REQ_PENDING = 600,
+ /** The host informs the guest that a DnD drop operation
+ * has been started and that the host wants the data in
+ * a specific MIME type. */
+ HOST_DND_FN_GH_EVT_DROPPED = 601,
+ /** Blow the type up to 32-bit. */
+ HOST_DND_FN_32BIT_HACK = 0x7fffffff
+};
+
+/**
+ * The service functions which are called by guest.
+ * Note: When adding new functions to this table, make sure that the actual ID
+ * does *not* overlap with the eHostFn enumeration above!
+ */
+enum eGuestFn
+{
+ /**
+ * The guest sends a connection request to the HGCM service,
+ * along with some additional information like supported
+ * protocol version and flags.
+ * Note: New since protocol version 2. */
+ GUEST_DND_FN_CONNECT = 10,
+
+ /** The guest client disconnects from the HGCM service. */
+ GUEST_DND_FN_DISCONNECT = 11,
+
+ /** Report guest side feature flags and retrieve the host ones.
+ *
+ * Two 64-bit parameters are passed in from the guest with the guest features
+ * (VBOX_DND_GF_XXX), the host replies by replacing the parameter values with
+ * the host ones (VBOX_DND_HF_XXX).
+ *
+ * @retval VINF_SUCCESS on success.
+ * @retval VERR_INVALID_CLIENT_ID
+ * @retval VERR_WRONG_PARAMETER_COUNT
+ * @retval VERR_WRONG_PARAMETER_TYPE
+ * @since 6.1.x
+ */
+ GUEST_DND_FN_REPORT_FEATURES = 12,
+
+ /** Query the host ones feature masks.
+ *
+ * That way the guest (client) can get hold of the features from the host.
+ * Again, it is prudent to set the 127 bit and observe it being cleared on
+ * success, as older hosts might return success without doing anything.
+ *
+ * @retval VINF_SUCCESS on success.
+ * @retval VERR_INVALID_CLIENT_ID
+ * @retval VERR_WRONG_PARAMETER_COUNT
+ * @retval VERR_WRONG_PARAMETER_TYPE
+ * @since 6.1.x
+ */
+ GUEST_DND_FN_QUERY_FEATURES = 13,
+
+ /**
+ * The guest waits for a new message the host wants to process
+ * on the guest side. This can be a blocking call.
+ */
+ GUEST_DND_FN_GET_NEXT_HOST_MSG = 300,
+
+ /** Reports back an error to the host.
+ *
+ * Note: Don't change the ID to also support older hosts
+ * (was GUEST_DND_FN_GH_EVT_ERROR before < 7.0, only for G->H transfers).
+ *
+ * This was changed to GUEST_DND_FN_EVT_ERROR to be a generic event
+ * that also can be used for H->G transfers.
+ *
+ * @retval VINF_SUCCESS on success.
+ * @retval VERR_INVALID_CLIENT_ID
+ * @retval VERR_WRONG_PARAMETER_COUNT
+ * @retval VERR_WRONG_PARAMETER_TYPE
+ * @since 7.0.x
+ */
+ GUEST_DND_FN_EVT_ERROR = 502,
+
+ /*
+ * Host -> Guest operation messages.
+ */
+
+ /** The guest acknowledges that a pending DnD operation from the host
+ * can be dropped on the currently selected area on the guest. */
+ GUEST_DND_FN_HG_ACK_OP = 400,
+ /** The guest requests the actual DnD data to be sent from the host. */
+ GUEST_DND_FN_HG_REQ_DATA = 401,
+ /** The guest reports back its progress back to the host. */
+ GUEST_DND_FN_HG_EVT_PROGRESS = 402,
+
+ /*
+ * Guest -> Host operation messages.
+ */
+
+ /**
+ * The guests acknowledges that it currently has a drag'n drop
+ * operation in progress on the guest, which eventually could be
+ * dragged over to the host.
+ */
+ GUEST_DND_FN_GH_ACK_PENDING = 500,
+ /** The guest sends the data header at the beginning of a (new)
+ * data transfer. */
+ GUEST_DND_FN_GH_SND_DATA_HDR = 503,
+ /**
+ * The guest sends data of the requested format to the host. There can
+ * be more than one message if the actual data does not fit
+ * into one.
+ */
+ GUEST_DND_FN_GH_SND_DATA = 501,
+ /** The guest sends a directory entry to the host. */
+ GUEST_DND_FN_GH_SND_DIR = 700,
+ /** The guest sends file data to the host.
+ * Note: On protocol version 1 this also contains the file name
+ * and other attributes. */
+ GUEST_DND_FN_GH_SND_FILE_DATA = 701,
+ /** The guest sends a file header to the host, marking the
+ * beginning of a (new) file transfer.
+ * Note: Available since protocol version 2 (VBox 5.0). */
+ GUEST_DND_FN_GH_SND_FILE_HDR = 702,
+ /** Blow the type up to 32-bit. */
+ GUEST_DND_FN_32BIT_HACK = 0x7fffffff
+};
+
+/** @name VBOX_DND_GF_XXX - Guest features.
+ * @sa GUEST_DND_FN_REPORT_FEATURES
+ * @{ */
+/** No flags set. */
+#define VBOX_DND_GF_NONE 0
+/** Bit that must be set in the 2nd parameter, will be cleared if the host reponds
+ * correctly (old hosts might not). */
+#define VBOX_DND_GF_1_MUST_BE_ONE RT_BIT_64(63)
+/** @} */
+
+/** @name VBOX_DND_HF_XXX - Host features.
+ * @sa DND_GUEST_REPORT_FEATURES
+ * @{ */
+/** No flags set. */
+#define VBOX_DND_HF_NONE 0
+/** @} */
+
+/**
+ * DnD operation progress states.
+ */
+typedef enum DNDPROGRESS
+{
+ DND_PROGRESS_UNKNOWN = 0,
+ DND_PROGRESS_RUNNING = 1,
+ DND_PROGRESS_COMPLETE,
+ DND_PROGRESS_CANCELLED,
+ DND_PROGRESS_ERROR,
+ /** Blow the type up to 32-bit. */
+ DND_PROGRESS_32BIT_HACK = 0x7fffffff
+} DNDPROGRESS, *PDNDPROGRESS;
+
+#pragma pack (1)
+
+/*
+ * Host events
+ */
+
+/**
+ * Action message for telling the guest about the currently ongoing
+ * drag and drop action when entering the guest's area, moving around in it
+ * and dropping content into it from the host.
+ *
+ * Used by:
+ * HOST_DND_FN_HG_EVT_ENTER
+ * HOST_DND_FN_HG_EVT_MOVE
+ * HOST_DND_FN_HG_EVT_DROPPED
+ */
+typedef struct HGCMMsgHGAction
+{
+ VBGLIOCHGCMCALL hdr;
+
+ union
+ {
+ struct
+ {
+ HGCMFunctionParameter uScreenId; /* OUT uint32_t */
+ HGCMFunctionParameter uX; /* OUT uint32_t */
+ HGCMFunctionParameter uY; /* OUT uint32_t */
+ HGCMFunctionParameter uDefAction; /* OUT uint32_t */
+ HGCMFunctionParameter uAllActions; /* OUT uint32_t */
+ HGCMFunctionParameter pvFormats; /* OUT ptr */
+ HGCMFunctionParameter cbFormats; /* OUT uint32_t */
+ } v1;
+ struct
+ {
+ /** Context ID. */
+ HGCMFunctionParameter uContext;
+ HGCMFunctionParameter uScreenId; /* OUT uint32_t */
+ HGCMFunctionParameter uX; /* OUT uint32_t */
+ HGCMFunctionParameter uY; /* OUT uint32_t */
+ HGCMFunctionParameter uDefAction; /* OUT uint32_t */
+ HGCMFunctionParameter uAllActions; /* OUT uint32_t */
+ HGCMFunctionParameter pvFormats; /* OUT ptr */
+ HGCMFunctionParameter cbFormats; /* OUT uint32_t */
+ } v3;
+ } u;
+} HGCMMsgHGAction;
+
+/**
+ * Tells the guest that the host has left its drag and drop area on the guest.
+ *
+ * Used by:
+ * HOST_DND_FN_HG_EVT_LEAVE
+ */
+typedef struct HGCMMsgHGLeave
+{
+ VBGLIOCHGCMCALL hdr;
+ union
+ {
+ struct
+ {
+ /** Context ID. */
+ HGCMFunctionParameter uContext;
+ } v3;
+ } u;
+} HGCMMsgHGLeave;
+
+/**
+ * Tells the guest that the host wants to cancel the current drag and drop operation.
+ *
+ * Used by:
+ * HOST_DND_FN_HG_EVT_CANCEL
+ */
+typedef struct HGCMMsgHGCancel
+{
+ VBGLIOCHGCMCALL hdr;
+ union
+ {
+ struct
+ {
+ /** Context ID. */
+ HGCMFunctionParameter uContext;
+ } v3;
+ } u;
+} HGCMMsgHGCancel;
+
+/**
+ * Sends the header of an incoming (meta) data block.
+ *
+ * Used by:
+ * HOST_DND_FN_HG_SND_DATA_HDR
+ * GUEST_DND_FN_GH_SND_DATA_HDR
+ *
+ * New since protocol v3.
+ */
+typedef struct HGCMMsgHGSendDataHdr
+{
+ VBGLIOCHGCMCALL hdr;
+
+ /** Context ID. Unused at the moment. */
+ HGCMFunctionParameter uContext; /* OUT uint32_t */
+ /** Data transfer flags. Not yet used and must be 0. */
+ HGCMFunctionParameter uFlags; /* OUT uint32_t */
+ /** Screen ID where the data originates from. */
+ HGCMFunctionParameter uScreenId; /* OUT uint32_t */
+ /** Total size (in bytes) to transfer. */
+ HGCMFunctionParameter cbTotal; /* OUT uint64_t */
+ /**
+ * Total meta data size (in bytes) to transfer.
+ * This size also is part of cbTotal already, so:
+ *
+ * cbTotal = cbMeta + additional size for files etc.
+ */
+ HGCMFunctionParameter cbMeta; /* OUT uint64_t */
+ /** Meta data format. */
+ HGCMFunctionParameter pvMetaFmt; /* OUT ptr */
+ /** Size (in bytes) of meta data format. */
+ HGCMFunctionParameter cbMetaFmt; /* OUT uint32_t */
+ /* Number of objects (files/directories) to transfer. */
+ HGCMFunctionParameter cObjects; /* OUT uint64_t */
+ /** Compression type. */
+ HGCMFunctionParameter enmCompression; /* OUT uint32_t */
+ /** Checksum type. */
+ HGCMFunctionParameter enmChecksumType; /* OUT uint32_t */
+ /** Checksum buffer for the entire data to be transferred. */
+ HGCMFunctionParameter pvChecksum; /* OUT ptr */
+ /** Size (in bytes) of checksum. */
+ HGCMFunctionParameter cbChecksum; /* OUT uint32_t */
+} HGCMMsgHGSendDataHdr;
+
+/**
+ * Sends a (meta) data block to the guest.
+ *
+ * Used by:
+ * HOST_DND_FN_HG_SND_DATA
+ */
+typedef struct HGCMMsgHGSendData
+{
+ VBGLIOCHGCMCALL hdr;
+
+ union
+ {
+ struct
+ {
+ HGCMFunctionParameter uScreenId; /* OUT uint32_t */
+ HGCMFunctionParameter pvFormat; /* OUT ptr */
+ HGCMFunctionParameter cbFormat; /* OUT uint32_t */
+ HGCMFunctionParameter pvData; /* OUT ptr */
+ HGCMFunctionParameter cbData; /* OUT uint32_t */
+ } v1;
+ /* No changes in v2. */
+ struct
+ {
+ /** Context ID. Unused at the moment. */
+ HGCMFunctionParameter uContext; /* OUT uint32_t */
+ /** Data block to send. */
+ HGCMFunctionParameter pvData; /* OUT ptr */
+ /** Size (in bytes) of data block to send. */
+ HGCMFunctionParameter cbData; /* OUT uint32_t */
+ /** Checksum of data block, based on the checksum
+ * type in the data header. Optional. */
+ HGCMFunctionParameter pvChecksum; /* OUT ptr */
+ /** Size (in bytes) of checksum to send. */
+ HGCMFunctionParameter cbChecksum; /* OUT uint32_t */
+ } v3;
+ } u;
+} HGCMMsgHGSendData;
+
+/**
+ * Sends more (meta) data in case the data didn't fit
+ * into the current XXX_DND_HG_SND_DATA message.
+ *
+ ** @todo Deprecated since protocol v3. Don't use! Will be removed.
+ *
+ * Used by:
+ * HOST_DND_FN_HG_SND_MORE_DATA
+ */
+typedef struct HGCMMsgHGSendMoreData
+{
+ VBGLIOCHGCMCALL hdr;
+
+ HGCMFunctionParameter pvData; /* OUT ptr */
+ HGCMFunctionParameter cbData; /* OUT uint32_t */
+} HGCMMsgHGSendMoreData;
+
+/**
+ * Directory entry event.
+ *
+ * Used by:
+ * HOST_DND_FN_HG_SND_DIR
+ * GUEST_DND_FN_GH_SND_DIR
+ */
+typedef struct HGCMMsgHGSendDir
+{
+ VBGLIOCHGCMCALL hdr;
+
+ union
+ {
+ struct
+ {
+ /** Directory name. */
+ HGCMFunctionParameter pvName; /* OUT ptr */
+ /** Size (in bytes) of directory name. */
+ HGCMFunctionParameter cbName; /* OUT uint32_t */
+ /** Directory mode. */
+ HGCMFunctionParameter fMode; /* OUT uint32_t */
+ } v1;
+ struct
+ {
+ /** Context ID. Unused at the moment. */
+ HGCMFunctionParameter uContext; /* OUT uint32_t */
+ /** Directory name. */
+ HGCMFunctionParameter pvName; /* OUT ptr */
+ /** Size (in bytes) of directory name. */
+ HGCMFunctionParameter cbName; /* OUT uint32_t */
+ /** Directory mode. */
+ HGCMFunctionParameter fMode; /* OUT uint32_t */
+ } v3;
+ } u;
+} HGCMMsgHGSendDir;
+
+/**
+ * File header message, marking the start of transferring a new file.
+ * Note: Only for protocol version 2 and up.
+ *
+ * Used by:
+ * HOST_DND_FN_HG_SND_FILE_HDR
+ * GUEST_DND_FN_GH_SND_FILE_HDR
+ */
+typedef struct HGCMMsgHGSendFileHdr
+{
+ VBGLIOCHGCMCALL hdr;
+
+ /** Context ID. Unused at the moment. */
+ HGCMFunctionParameter uContext; /* OUT uint32_t */
+ /** File path. */
+ HGCMFunctionParameter pvName; /* OUT ptr */
+ /** Size (in bytes) of file path. */
+ HGCMFunctionParameter cbName; /* OUT uint32_t */
+ /** Optional flags; unused at the moment. */
+ HGCMFunctionParameter uFlags; /* OUT uint32_t */
+ /** File creation mode. */
+ HGCMFunctionParameter fMode; /* OUT uint32_t */
+ /** Total size (in bytes). */
+ HGCMFunctionParameter cbTotal; /* OUT uint64_t */
+} HGCMMsgHGSendFileHdr;
+
+/**
+ * HG: File data (chunk) event.
+ *
+ * Used by:
+ * HOST_DND_FN_HG_SND_FILE
+ */
+typedef struct HGCMMsgHGSendFileData
+{
+ VBGLIOCHGCMCALL hdr;
+
+ union
+ {
+ /* Note: Protocol v1 sends the file name + file mode
+ * every time a file data chunk is being sent. */
+ struct
+ {
+ /** File name. */
+ HGCMFunctionParameter pvName; /* OUT ptr */
+ /** Size (in bytes) of file name. */
+ HGCMFunctionParameter cbName; /* OUT uint32_t */
+ /** Current data chunk. */
+ HGCMFunctionParameter pvData; /* OUT ptr */
+ /** Size (in bytes) of current data chunk. */
+ HGCMFunctionParameter cbData; /* OUT uint32_t */
+ /** File mode. */
+ HGCMFunctionParameter fMode; /* OUT uint32_t */
+ } v1;
+ struct
+ {
+ /** Note: pvName is now part of the VBOXDNDHGSENDFILEHDRMSG message. */
+ /** Note: cbName is now part of the VBOXDNDHGSENDFILEHDRMSG message. */
+ /** Context ID. Unused at the moment. */
+ HGCMFunctionParameter uContext; /* OUT uint32_t */
+ /** Current data chunk. */
+ HGCMFunctionParameter pvData; /* OUT ptr */
+ /** Size (in bytes) of current data chunk. */
+ HGCMFunctionParameter cbData; /* OUT uint32_t */
+ /** Note: fMode is now part of the VBOXDNDHGSENDFILEHDRMSG message. */
+ } v2;
+ struct
+ {
+ /** Context ID. Unused at the moment. */
+ HGCMFunctionParameter uContext; /* OUT uint32_t */
+ /** Current data chunk. */
+ HGCMFunctionParameter pvData; /* OUT ptr */
+ /** Size (in bytes) of current data chunk. */
+ HGCMFunctionParameter cbData; /* OUT uint32_t */
+ /** Checksum of data block, based on the checksum
+ * type in the data header. Optional. */
+ HGCMFunctionParameter pvChecksum; /* OUT ptr */
+ /** Size (in bytes) of curren data chunk checksum. */
+ HGCMFunctionParameter cbChecksum; /* OUT uint32_t */
+ } v3;
+ } u;
+} HGCMMsgHGSendFileData;
+
+/**
+ * Asks the guest if a guest->host DnD operation is in progress.
+ *
+ * Used by:
+ * HOST_DND_FN_GH_REQ_PENDING
+ */
+typedef struct HGCMMsgGHReqPending
+{
+ VBGLIOCHGCMCALL hdr;
+
+ union
+ {
+ struct
+ {
+ /** Screen ID. */
+ HGCMFunctionParameter uScreenId; /* OUT uint32_t */
+ } v1;
+ struct
+ {
+ /** Context ID. Unused at the moment. */
+ HGCMFunctionParameter uContext; /* OUT uint32_t */
+ /** Screen ID. */
+ HGCMFunctionParameter uScreenId; /* OUT uint32_t */
+ } v3;
+ } u;
+} HGCMMsgGHReqPending;
+
+/**
+ * Tells the guest that the host has dropped the ongoing guest->host
+ * DnD operation on a valid target on the host.
+ *
+ * Used by:
+ * HOST_DND_FN_GH_EVT_DROPPED
+ */
+typedef struct HGCMMsgGHDropped
+{
+ VBGLIOCHGCMCALL hdr;
+
+ union
+ {
+ struct
+ {
+ /** Requested format for sending the data. */
+ HGCMFunctionParameter pvFormat; /* OUT ptr */
+ /** Size (in bytes) of requested format. */
+ HGCMFunctionParameter cbFormat; /* OUT uint32_t */
+ /** Drop action peformed on the host. */
+ HGCMFunctionParameter uAction; /* OUT uint32_t */
+ } v1;
+ struct
+ {
+ /** Context ID. Unused at the moment. */
+ HGCMFunctionParameter uContext; /* OUT uint32_t */
+ /** Requested format for sending the data. */
+ HGCMFunctionParameter pvFormat; /* OUT ptr */
+ /** Size (in bytes) of requested format. */
+ HGCMFunctionParameter cbFormat; /* OUT uint32_t */
+ /** Drop action peformed on the host. */
+ HGCMFunctionParameter uAction; /* OUT uint32_t */
+ } v3;
+ } u;
+} HGCMMsgGHDropped;
+
+/*
+ * Guest events
+ */
+
+/**
+ * Asks the host for the next command to process, along
+ * with the needed amount of parameters and an optional blocking
+ * flag.
+ *
+ * Used by:
+ * GUEST_DND_FN_GET_NEXT_HOST_MSG
+ */
+typedef struct HGCMMsgGetNext
+{
+ VBGLIOCHGCMCALL hdr;
+
+ /** Message ID. */
+ HGCMFunctionParameter uMsg; /* OUT uint32_t */
+ /** Number of parameters the message needs. */
+ HGCMFunctionParameter cParms; /* OUT uint32_t */
+ /** Whether or not to block (wait) for a
+ * new message to arrive. */
+ HGCMFunctionParameter fBlock; /* OUT uint32_t */
+} HGCMMsgGetNext;
+
+/**
+ * Guest connection request. Used to tell the DnD protocol
+ * version to the (host) service.
+ *
+ * Used by:
+ * GUEST_DND_FN_CONNECT
+ */
+typedef struct HGCMMsgConnect
+{
+ VBGLIOCHGCMCALL hdr;
+
+ union
+ {
+ struct
+ {
+ /** Protocol version to use.
+ * Deprecated since VBox 6.1.x. Do not use / rely on it anymore. */
+ HGCMFunctionParameter uProtocol; /* OUT uint32_t */
+ /** Connection flags. Optional. */
+ HGCMFunctionParameter uFlags; /* OUT uint32_t */
+ } v2;
+ struct
+ {
+ /** Context ID. Unused at the moment. */
+ HGCMFunctionParameter uContext; /* OUT uint32_t */
+ /** Protocol version to use.
+ * Deprecated since VBox 6.1.x. Do not use / rely on it anymore. */
+ HGCMFunctionParameter uProtocol; /* OUT uint32_t */
+ /** Connection flags. Optional. */
+ HGCMFunctionParameter uFlags; /* OUT uint32_t */
+ } v3;
+ } u;
+} HGCMMsgConnect;
+
+/**
+ * Acknowledges a host operation along with the allowed
+ * action(s) on the guest.
+ *
+ * Used by:
+ * GUEST_DND_FN_HG_ACK_OP
+ */
+typedef struct HGCMMsgHGAck
+{
+ VBGLIOCHGCMCALL hdr;
+
+ union
+ {
+ struct
+ {
+ HGCMFunctionParameter uAction; /* OUT uint32_t */
+ } v1;
+ struct
+ {
+ /** Context ID. Unused at the moment. */
+ HGCMFunctionParameter uContext; /* OUT uint32_t */
+ HGCMFunctionParameter uAction; /* OUT uint32_t */
+ } v3;
+ } u;
+} HGCMMsgHGAck;
+
+/**
+ * Requests data to be sent to the guest.
+ *
+ * Used by:
+ * GUEST_DND_FN_HG_REQ_DATA
+ */
+typedef struct HGCMMsgHGReqData
+{
+ VBGLIOCHGCMCALL hdr;
+
+ union
+ {
+ struct
+ {
+ HGCMFunctionParameter pvFormat; /* OUT ptr */
+ } v1;
+ struct
+ {
+ /** Context ID. Unused at the moment. */
+ HGCMFunctionParameter uContext; /* OUT uint32_t */
+ HGCMFunctionParameter pvFormat; /* OUT ptr */
+ HGCMFunctionParameter cbFormat; /* OUT uint32_t */
+ } v3;
+ } u;
+} HGCMMsgHGReqData;
+
+typedef struct HGCMMsgHGProgress
+{
+ VBGLIOCHGCMCALL hdr;
+
+ union
+ {
+ struct
+ {
+ HGCMFunctionParameter uStatus; /* OUT uint32_t */
+ HGCMFunctionParameter uPercent; /* OUT uint32_t */
+ HGCMFunctionParameter rc; /* OUT uint32_t */
+ } v1;
+ struct
+ {
+ /** Context ID. Unused at the moment. */
+ HGCMFunctionParameter uContext; /* OUT uint32_t */
+ HGCMFunctionParameter uStatus; /* OUT uint32_t */
+ HGCMFunctionParameter uPercent; /* OUT uint32_t */
+ HGCMFunctionParameter rc; /* OUT uint32_t */
+ } v3;
+ } u;
+} HGCMMsgHGProgress;
+
+/**
+ * Acknowledges a pending guest drag and drop event to the host.
+ *
+ * Used by:
+ * GUEST_DND_FN_GH_ACK_PENDING
+ */
+typedef struct HGCMMsgGHAckPending
+{
+ VBGLIOCHGCMCALL hdr;
+
+ union
+ {
+ struct
+ {
+ HGCMFunctionParameter uDefAction; /* OUT uint32_t */
+ HGCMFunctionParameter uAllActions; /* OUT uint32_t */
+ HGCMFunctionParameter pvFormats; /* OUT ptr */
+ } v1;
+ struct
+ {
+ /** Context ID. Unused at the moment. */
+ HGCMFunctionParameter uContext; /* OUT uint32_t */
+ HGCMFunctionParameter uDefAction; /* OUT uint32_t */
+ HGCMFunctionParameter uAllActions; /* OUT uint32_t */
+ HGCMFunctionParameter pvFormats; /* OUT ptr */
+ HGCMFunctionParameter cbFormats; /* OUT uint32_t */
+ } v3;
+ } u;
+} HGCMMsgGHAckPending;
+
+/**
+ * Sends the header of an incoming data block
+ * to the host.
+ *
+ * Used by:
+ * GUEST_DND_FN_GH_SND_DATA_HDR
+ *
+ * New since protocol v3.
+ */
+typedef struct HGCMMsgHGSendDataHdr HGCMMsgGHSendDataHdr;
+
+/**
+ * Sends a (meta) data block to the host.
+ *
+ * Used by:
+ * GUEST_DND_FN_GH_SND_DATA
+ */
+typedef struct HGCMMsgGHSendData
+{
+ VBGLIOCHGCMCALL hdr;
+
+ union
+ {
+ struct
+ {
+ HGCMFunctionParameter pvData; /* OUT ptr */
+ /** Total bytes to send. This can be more than
+ * the data block specified in pvData above, e.g.
+ * when sending over file objects afterwards. */
+ HGCMFunctionParameter cbTotalBytes; /* OUT uint32_t */
+ } v1;
+ struct
+ {
+ /** Context ID. Unused at the moment. */
+ HGCMFunctionParameter uContext; /* OUT uint32_t */
+ /** Data block to send. */
+ HGCMFunctionParameter pvData; /* OUT ptr */
+ /** Size (in bytes) of data block to send. */
+ HGCMFunctionParameter cbData; /* OUT uint32_t */
+ /** (Rolling) Checksum, based on checksum type in data header. */
+ HGCMFunctionParameter pvChecksum; /* OUT ptr */
+ /** Size (in bytes) of checksum. */
+ HGCMFunctionParameter cbChecksum; /* OUT uint32_t */
+ } v3;
+ } u;
+} HGCMMsgGHSendData;
+
+/**
+ * Sends a directory entry to the host.
+ *
+ * Used by:
+ * GUEST_DND_FN_GH_SND_DIR
+ */
+typedef struct HGCMMsgHGSendDir HGCMMsgGHSendDir;
+
+/**
+ * Sends a file header to the host.
+ *
+ * Used by:
+ * GUEST_DND_FN_GH_SND_FILE_HDR
+ *
+ * New since protocol v2.
+ */
+typedef struct HGCMMsgHGSendFileHdr HGCMMsgGHSendFileHdr;
+
+/**
+ * Sends file data to the host.
+ *
+ * Used by:
+ * GUEST_DND_FN_GH_SND_FILE_DATA
+ */
+typedef struct HGCMMsgHGSendFileData HGCMMsgGHSendFileData;
+
+/**
+ * Sends a guest error event to the host.
+ *
+ * Used by:
+ * GUEST_DND_FN_GH_EVT_ERROR
+ */
+typedef struct HGCMMsgGHError
+{
+ VBGLIOCHGCMCALL hdr;
+
+ union
+ {
+ struct
+ {
+ HGCMFunctionParameter rc; /* OUT uint32_t */
+ } v1;
+ struct
+ {
+ /** Context ID. Unused at the moment. */
+ HGCMFunctionParameter uContext; /* OUT uint32_t */
+ HGCMFunctionParameter rc; /* OUT uint32_t */
+ } v3;
+ } u;
+} HGCMMsgGHError;
+
+#pragma pack()
+
+/** Builds a callback magic out of the function ID and the version
+ * of the callback data. */
+#define VBOX_DND_CB_MAGIC_MAKE(uFn, uVer) \
+ RT_MAKE_U32(uVer, uFn)
+
+/*
+ * Callback magics.
+ */
+enum eDnDCallbackMagics
+{
+ CB_MAGIC_DND_CONNECT = VBOX_DND_CB_MAGIC_MAKE(GUEST_DND_FN_CONNECT, 0),
+ CB_MAGIC_DND_REPORT_FEATURES = VBOX_DND_CB_MAGIC_MAKE(GUEST_DND_FN_REPORT_FEATURES, 0),
+ CB_MAGIC_DND_EVT_ERROR = VBOX_DND_CB_MAGIC_MAKE(GUEST_DND_FN_EVT_ERROR, 0),
+ CB_MAGIC_DND_HG_GET_NEXT_HOST_MSG = VBOX_DND_CB_MAGIC_MAKE(GUEST_DND_FN_GET_NEXT_HOST_MSG, 0),
+ CB_MAGIC_DND_HG_ACK_OP = VBOX_DND_CB_MAGIC_MAKE(GUEST_DND_FN_HG_ACK_OP, 0),
+ CB_MAGIC_DND_HG_REQ_DATA = VBOX_DND_CB_MAGIC_MAKE(GUEST_DND_FN_HG_REQ_DATA, 0),
+ CB_MAGIC_DND_HG_EVT_PROGRESS = VBOX_DND_CB_MAGIC_MAKE(GUEST_DND_FN_HG_EVT_PROGRESS, 0),
+ CB_MAGIC_DND_GH_ACK_PENDING = VBOX_DND_CB_MAGIC_MAKE(GUEST_DND_FN_GH_ACK_PENDING, 0),
+ CB_MAGIC_DND_GH_SND_DATA = VBOX_DND_CB_MAGIC_MAKE(GUEST_DND_FN_GH_SND_DATA, 0),
+ CB_MAGIC_DND_GH_SND_DATA_HDR = VBOX_DND_CB_MAGIC_MAKE(GUEST_DND_FN_GH_SND_DATA_HDR, 0),
+ CB_MAGIC_DND_GH_SND_DIR = VBOX_DND_CB_MAGIC_MAKE(GUEST_DND_FN_GH_SND_DIR, 0),
+ CB_MAGIC_DND_GH_SND_FILE_HDR = VBOX_DND_CB_MAGIC_MAKE(GUEST_DND_FN_GH_SND_FILE_HDR, 0),
+ CB_MAGIC_DND_GH_SND_FILE_DATA = VBOX_DND_CB_MAGIC_MAKE(GUEST_DND_FN_GH_SND_FILE_DATA, 0)
+};
+
+typedef struct VBOXDNDCBHEADERDATA
+{
+ /** Magic number to identify the structure. */
+ uint32_t uMagic;
+ /** Context ID to identify callback data. */
+ uint32_t uContextID;
+} VBOXDNDCBHEADERDATA, *PVBOXDNDCBHEADERDATA;
+
+typedef struct VBOXDNDCBCONNECTDATA
+{
+ /** Callback data header. */
+ VBOXDNDCBHEADERDATA hdr;
+ /** Protocol version to use.
+ * Deprecated since VBox 6.1.x. Do not use / rely on it anymore. */
+ uint32_t uProtocolVersion;
+ /** Connection flags; currently unused. */
+ uint32_t fFlags;
+} VBOXDNDCBCONNECTDATA, *PVBOXDNDCBCONNECTDATA;
+
+typedef struct VBOXDNDCBREPORTFEATURESDATA
+{
+ /** Callback data header. */
+ VBOXDNDCBHEADERDATA hdr;
+ uint32_t fGuestFeatures0;
+} VBOXDNDCBREPORTFEATURESDATA, *PVBOXDNDCBREPORTFEATURESDATA;
+
+typedef struct VBOXDNDCBDISCONNECTMSGDATA
+{
+ /** Callback data header. */
+ VBOXDNDCBHEADERDATA hdr;
+} VBOXDNDCBDISCONNECTMSGDATA, *PVBOXDNDCBDISCONNECTMSGDATA;
+
+typedef struct VBOXDNDCBHGGETNEXTHOSTMSG
+{
+ /** Callback data header. */
+ VBOXDNDCBHEADERDATA hdr;
+ uint32_t uMsg;
+ uint32_t cParms;
+} VBOXDNDCBHGGETNEXTHOSTMSG, *PVBOXDNDCBHGGETNEXTHOSTMSG;
+
+typedef struct VBOXDNDCBHGGETNEXTHOSTMSGDATA
+{
+ /** Callback data header. */
+ VBOXDNDCBHEADERDATA hdr;
+ uint32_t uMsg;
+ uint32_t cParms;
+ PVBOXHGCMSVCPARM paParms;
+} VBOXDNDCBHGGETNEXTHOSTMSGDATA, *PVBOXDNDCBHGGETNEXTHOSTMSGDATA;
+
+typedef struct VBOXDNDCBHGACKOPDATA
+{
+ /** Callback data header. */
+ VBOXDNDCBHEADERDATA hdr;
+ uint32_t uAction;
+} VBOXDNDCBHGACKOPDATA, *PVBOXDNDCBHGACKOPDATA;
+
+typedef struct VBOXDNDCBHGREQDATADATA
+{
+ /** Callback data header. */
+ VBOXDNDCBHEADERDATA hdr;
+ char *pszFormat;
+ uint32_t cbFormat;
+} VBOXDNDCBHGREQDATADATA, *PVBOXDNDCBHGREQDATADATA;
+
+typedef struct VBOXDNDCBHGEVTPROGRESSDATA
+{
+ /** Callback data header. */
+ VBOXDNDCBHEADERDATA hdr;
+ uint32_t uPercentage;
+ uint32_t uStatus;
+ uint32_t rc;
+} VBOXDNDCBHGEVTPROGRESSDATA, *PVBOXDNDCBHGEVTPROGRESSDATA;
+
+typedef struct VBOXDNDCBGHACKPENDINGDATA
+{
+ /** Callback data header. */
+ VBOXDNDCBHEADERDATA hdr;
+ uint32_t uDefAction;
+ uint32_t uAllActions;
+ char *pszFormat;
+ uint32_t cbFormat;
+} VBOXDNDCBGHACKPENDINGDATA, *PVBOXDNDCBGHACKPENDINGDATA;
+
+/**
+ * Data header.
+ * New since protocol v3.
+ */
+typedef struct VBOXDNDDATAHDR
+{
+ /** Data transfer flags. Not yet used and must be 0. */
+ uint32_t uFlags;
+ /** Screen ID where the data originates from. */
+ uint32_t uScreenId;
+ /** Total size (in bytes) to transfer. */
+ uint64_t cbTotal;
+ /** Meta data size (in bytes) to transfer.
+ * This size also is part of cbTotal already. */
+ uint32_t cbMeta;
+ /** Meta format buffer. */
+ void *pvMetaFmt;
+ /** Size (in bytes) of meta format buffer. */
+ uint32_t cbMetaFmt;
+ /** Number of objects (files/directories) to transfer. */
+ uint64_t cObjects;
+ /** Compression type. Currently unused, so specify 0.
+ **@todo Add IPRT compression type enumeration as soon as it's available. */
+ uint32_t enmCompression;
+ /** Checksum type. Currently unused, so specify RTDIGESTTYPE_INVALID. */
+ RTDIGESTTYPE enmChecksumType;
+ /** The actual checksum buffer for the entire data to be transferred,
+ * based on enmChksumType. If RTDIGESTTYPE_INVALID is specified,
+ * no checksum is being used and pvChecksum will be NULL. */
+ void *pvChecksum;
+ /** Size (in bytes) of checksum. */
+ uint32_t cbChecksum;
+} VBOXDNDDATAHDR, *PVBOXDNDSNDDATAHDR;
+
+/* New since protocol v3. */
+typedef struct VBOXDNDCBSNDDATAHDRDATA
+{
+ /** Callback data header. */
+ VBOXDNDCBHEADERDATA hdr;
+ /** Actual header data. */
+ VBOXDNDDATAHDR data;
+} VBOXDNDCBSNDDATAHDRDATA, *PVBOXDNDCBSNDDATAHDRDATA;
+
+typedef struct VBOXDNDSNDDATA
+{
+ union
+ {
+ struct
+ {
+ /** Data block buffer. */
+ void *pvData;
+ /** Size (in bytes) of data block. */
+ uint32_t cbData;
+ /** Total metadata size (in bytes). This is transmitted
+ * with every message because the size can change. */
+ uint32_t cbTotalSize;
+ } v1;
+ /* Protocol v2: No changes. */
+ struct
+ {
+ /** Data block buffer. */
+ void *pvData;
+ /** Size (in bytes) of data block. */
+ uint32_t cbData;
+ /** (Rolling) Checksum. Not yet implemented. */
+ void *pvChecksum;
+ /** Size (in bytes) of checksum. Not yet implemented. */
+ uint32_t cbChecksum;
+ } v3;
+ } u;
+} VBOXDNDSNDDATA, *PVBOXDNDSNDDATA;
+
+typedef struct VBOXDNDCBSNDDATADATA
+{
+ /** Callback data header. */
+ VBOXDNDCBHEADERDATA hdr;
+ /** Actual data. */
+ VBOXDNDSNDDATA data;
+} VBOXDNDCBSNDDATADATA, *PVBOXDNDCBSNDDATADATA;
+
+typedef struct VBOXDNDCBSNDDIRDATA
+{
+ /** Callback data header. */
+ VBOXDNDCBHEADERDATA hdr;
+ /** Directory path. */
+ char *pszPath;
+ /** Size (in bytes) of path. */
+ uint32_t cbPath;
+ /** Directory creation mode. */
+ uint32_t fMode;
+} VBOXDNDCBSNDDIRDATA, *PVBOXDNDCBSNDDIRDATA;
+
+/* Note: Only for protocol version 2 and up (>= VBox 5.0). */
+typedef struct VBOXDNDCBSNDFILEHDRDATA
+{
+ /** Callback data header. */
+ VBOXDNDCBHEADERDATA hdr;
+ /** File path (name). */
+ char *pszFilePath;
+ /** Size (in bytes) of file path. */
+ uint32_t cbFilePath;
+ /** Total size (in bytes) of this file. */
+ uint64_t cbSize;
+ /** File (creation) mode. */
+ uint32_t fMode;
+ /** Additional flags. Not used at the moment. */
+ uint32_t fFlags;
+} VBOXDNDCBSNDFILEHDRDATA, *PVBOXDNDCBSNDFILEHDRDATA;
+
+typedef struct VBOXDNDCBSNDFILEDATADATA
+{
+ /** Callback data header. */
+ VBOXDNDCBHEADERDATA hdr;
+ /** Current file data chunk. */
+ void *pvData;
+ /** Size (in bytes) of current data chunk. */
+ uint32_t cbData;
+ union
+ {
+ struct
+ {
+ /** File path (name). */
+ char *pszFilePath;
+ /** Size (in bytes) of file path. */
+ uint32_t cbFilePath;
+ /** File (creation) mode. */
+ uint32_t fMode;
+ } v1;
+ /* Protocol v2 + v3: Have the file attributes (name, size, mode, ...)
+ in the VBOXDNDCBSNDFILEHDRDATA structure. */
+ struct
+ {
+ /** Checksum for current file data chunk. */
+ void *pvChecksum;
+ /** Size (in bytes) of current data chunk. */
+ uint32_t cbChecksum;
+ } v3;
+ } u;
+} VBOXDNDCBSNDFILEDATADATA, *PVBOXDNDCBSNDFILEDATADATA;
+
+typedef struct VBOXDNDCBEVTERRORDATA
+{
+ /** Callback data header. */
+ VBOXDNDCBHEADERDATA hdr;
+ int32_t rc;
+} VBOXDNDCBEVTERRORDATA, *PVBOXDNDCBEVTERRORDATA;
+
+} /* namespace DragAndDropSvc */
+
+#endif /* !VBOX_INCLUDED_HostServices_DragAndDropSvc_h */
+
diff --git a/include/VBox/HostServices/GuestControlSvc.h b/include/VBox/HostServices/GuestControlSvc.h
new file mode 100644
index 00000000..8ed0b2ba
--- /dev/null
+++ b/include/VBox/HostServices/GuestControlSvc.h
@@ -0,0 +1,1500 @@
+/* $Id: GuestControlSvc.h $ */
+/** @file
+ * Guest control service - Common header for host service and guest clients.
+ */
+
+/*
+ * Copyright (C) 2011-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_HostServices_GuestControlSvc_h
+#define VBOX_INCLUDED_HostServices_GuestControlSvc_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/VMMDevCoreTypes.h>
+#include <VBox/VBoxGuestCoreTypes.h>
+#include <VBox/hgcmsvc.h>
+#include <iprt/assert.h>
+
+/* Everything defined in this file lives in this namespace. */
+namespace guestControl {
+
+/******************************************************************************
+* Typedefs, constants and inlines *
+******************************************************************************/
+
+#define HGCMSERVICE_NAME "VBoxGuestControlSvc"
+
+/** Maximum number of concurrent guest sessions a VM can have. */
+#define VBOX_GUESTCTRL_MAX_SESSIONS 32
+/** Maximum number of concurrent guest objects (processes, files, ...)
+ * a guest session can have. */
+#define VBOX_GUESTCTRL_MAX_OBJECTS _2K
+/** Maximum of callback contexts a guest process can have. */
+#define VBOX_GUESTCTRL_MAX_CONTEXTS _64K
+
+/** Base (start) of guest control session IDs. Session
+ * ID 0 is reserved for the root process which
+ * hosts all other guest session processes. */
+#define VBOX_GUESTCTRL_SESSION_ID_BASE 1
+
+/** Builds a context ID out of the session ID, object ID and an
+ * increasing count. */
+#define VBOX_GUESTCTRL_CONTEXTID_MAKE(uSession, uObject, uCount) \
+ ( (uint32_t)((uSession) & 0x1f) << 27 \
+ | (uint32_t)((uObject) & 0x7ff) << 16 \
+ | (uint32_t)((uCount) & 0xffff) \
+ )
+/** Creates a context ID out of a session ID. */
+#define VBOX_GUESTCTRL_CONTEXTID_MAKE_SESSION(uSession) \
+ ((uint32_t)((uSession) & 0x1f) << 27)
+/** Gets the session ID out of a context ID. */
+#define VBOX_GUESTCTRL_CONTEXTID_GET_SESSION(uContextID) \
+ (((uContextID) >> 27) & 0x1f)
+/** Gets the process ID out of a context ID. */
+#define VBOX_GUESTCTRL_CONTEXTID_GET_OBJECT(uContextID) \
+ (((uContextID) >> 16) & 0x7ff)
+/** Gets the context count of a process out of a context ID. */
+#define VBOX_GUESTCTRL_CONTEXTID_GET_COUNT(uContextID) \
+ ((uContextID) & 0xffff)
+/** Filter context IDs by session. Can be used in conjunction
+ * with VbglR3GuestCtrlMsgFilterSet(). */
+#define VBOX_GUESTCTRL_FILTER_BY_SESSION(uSession) \
+ (VBOX_GUESTCTRL_CONTEXTID_MAKE_SESSION(uSession) | 0xF8000000)
+
+/**
+ * Structure keeping the context of a host callback.
+ */
+typedef struct VBOXGUESTCTRLHOSTCBCTX
+{
+ /** HGCM message number. */
+ uint32_t uMessage;
+ /** The context ID. */
+ uint32_t uContextID;
+ /** Protocol version of this guest session. Might
+ * be 0 if not supported. */
+ uint32_t uProtocol;
+} VBOXGUESTCTRLHOSTCBCTX, *PVBOXGUESTCTRLHOSTCBCTX;
+
+/**
+ * Structure for low level HGCM host callback from
+ * the guest. No deep copy. */
+typedef struct VBOXGUESTCTRLHOSTCALLBACK
+{
+ /** Number of HGCM parameters. */
+ uint32_t mParms;
+ /** Actual HGCM parameters. */
+ PVBOXHGCMSVCPARM mpaParms;
+} VBOXGUESTCTRLHOSTCALLBACK, *PVBOXGUESTCTRLHOSTCALLBACK;
+
+/** @name Host message destination flags.
+ *
+ * This is ORed into the context ID parameter Main after extending it to 64-bit.
+ *
+ * @internal Host internal.
+ * @{ */
+#define VBOX_GUESTCTRL_DST_ROOT_SVC RT_BIT_64(63)
+#define VBOX_GUESTCTRL_DST_SESSION RT_BIT_64(62)
+#define VBOX_GUESTCTRL_DST_BOTH ( VBOX_GUESTCTRL_DST_ROOT_SVC | VBOX_GUESTCTRL_DST_SESSION )
+/** @} */
+
+
+/**
+ * The service messages which are callable by host.
+ */
+enum eHostMsg
+{
+ /**
+ * The host asks the client to cancel all pending waits and exit.
+ */
+ HOST_MSG_CANCEL_PENDING_WAITS = 0,
+ /**
+ * The host wants to create a guest session.
+ */
+ HOST_MSG_SESSION_CREATE = 20,
+ /**
+ * The host wants to close a guest session.
+ */
+ HOST_MSG_SESSION_CLOSE = 21,
+ /**
+ * The host wants to execute something in the guest. This can be a command
+ * line or starting a program.
+ */
+ HOST_MSG_EXEC_CMD = 100,
+ /**
+ * Sends input data for stdin to a running process executed by HOST_EXEC_CMD.
+ */
+ HOST_MSG_EXEC_SET_INPUT = 101,
+ /**
+ * Gets the current status of a running process, e.g.
+ * new data on stdout/stderr, process terminated etc.
+ */
+ HOST_MSG_EXEC_GET_OUTPUT = 102,
+ /**
+ * Terminates a running guest process.
+ */
+ HOST_MSG_EXEC_TERMINATE = 110,
+ /**
+ * Waits for a certain event to happen. This can be an input, output
+ * or status event.
+ */
+ HOST_MSG_EXEC_WAIT_FOR = 120,
+ /**
+ * Opens a guest file.
+ */
+ HOST_MSG_FILE_OPEN = 240,
+ /**
+ * Closes a guest file.
+ */
+ HOST_MSG_FILE_CLOSE,
+ /**
+ * Reads from an opened guest file.
+ */
+ HOST_MSG_FILE_READ = 250,
+ /**
+ * Reads from an opened guest file at a specified offset.
+ */
+ HOST_MSG_FILE_READ_AT,
+ /**
+ * Write to an opened guest file.
+ */
+ HOST_MSG_FILE_WRITE = 260,
+ /**
+ * Write to an opened guest file at a specified offset.
+ */
+ HOST_MSG_FILE_WRITE_AT,
+ /**
+ * Changes the read & write position of an opened guest file.
+ */
+ HOST_MSG_FILE_SEEK = 270,
+ /**
+ * Gets the current file position of an opened guest file.
+ */
+ HOST_MSG_FILE_TELL,
+ /**
+ * Changes the file size.
+ */
+ HOST_MSG_FILE_SET_SIZE,
+ /**
+ * Removes a directory on the guest.
+ */
+ HOST_MSG_DIR_REMOVE = 320,
+ /**
+ * Renames a path on the guest.
+ */
+ HOST_MSG_PATH_RENAME = 330,
+ /**
+ * Retrieves the user's documents directory.
+ */
+ HOST_MSG_PATH_USER_DOCUMENTS,
+ /**
+ * Retrieves the user's home directory.
+ */
+ HOST_MSG_PATH_USER_HOME,
+ /**
+ * Issues a shutdown / reboot of the guest OS.
+ */
+ HOST_MSG_SHUTDOWN,
+
+ /** Blow the type up to 32-bits. */
+ HOST_MSG_32BIT_HACK = 0x7fffffff
+};
+
+
+/**
+ * Translates a guest control host message enum to a string.
+ *
+ * @returns Enum string name.
+ * @param enmMsg The message to translate.
+ */
+DECLINLINE(const char *) GstCtrlHostMsgtoStr(enum eHostMsg enmMsg)
+{
+ switch (enmMsg)
+ {
+ RT_CASE_RET_STR(HOST_MSG_CANCEL_PENDING_WAITS);
+ RT_CASE_RET_STR(HOST_MSG_SESSION_CREATE);
+ RT_CASE_RET_STR(HOST_MSG_SESSION_CLOSE);
+ RT_CASE_RET_STR(HOST_MSG_EXEC_CMD);
+ RT_CASE_RET_STR(HOST_MSG_EXEC_SET_INPUT);
+ RT_CASE_RET_STR(HOST_MSG_EXEC_GET_OUTPUT);
+ RT_CASE_RET_STR(HOST_MSG_EXEC_TERMINATE);
+ RT_CASE_RET_STR(HOST_MSG_EXEC_WAIT_FOR);
+ RT_CASE_RET_STR(HOST_MSG_FILE_OPEN);
+ RT_CASE_RET_STR(HOST_MSG_FILE_CLOSE);
+ RT_CASE_RET_STR(HOST_MSG_FILE_READ);
+ RT_CASE_RET_STR(HOST_MSG_FILE_READ_AT);
+ RT_CASE_RET_STR(HOST_MSG_FILE_WRITE);
+ RT_CASE_RET_STR(HOST_MSG_FILE_WRITE_AT);
+ RT_CASE_RET_STR(HOST_MSG_FILE_SEEK);
+ RT_CASE_RET_STR(HOST_MSG_FILE_TELL);
+ RT_CASE_RET_STR(HOST_MSG_FILE_SET_SIZE);
+ RT_CASE_RET_STR(HOST_MSG_DIR_REMOVE);
+ RT_CASE_RET_STR(HOST_MSG_PATH_RENAME);
+ RT_CASE_RET_STR(HOST_MSG_PATH_USER_DOCUMENTS);
+ RT_CASE_RET_STR(HOST_MSG_PATH_USER_HOME);
+ RT_CASE_RET_STR(HOST_MSG_SHUTDOWN);
+ RT_CASE_RET_STR(HOST_MSG_32BIT_HACK);
+ }
+ return "Unknown";
+}
+
+
+/**
+ * The service messages which are callable by the guest.
+ *
+ * @note The message numbers cannot be changed. Please use the first non-zero
+ * number that's not in use when adding new messages.
+ *
+ * @note Remember to update service.cpp when adding new messages for Main,
+ * as it validates all incoming messages before passing them on.
+ */
+enum eGuestMsg
+{
+ /** Guest waits for a new message the host wants to process on the guest side.
+ * This is a blocking call and can be deferred.
+ *
+ * @note This message is rather odd. The above description isn't really
+ * correct. Yes, it (1) waits for a new message and will return the
+ * mesage number and parameter count when one is available. However, it
+ * is also (2) used to retrieve the message parameters. For some weird
+ * reasons it was decided that it should always return VERR_TOO_MUCH_DATA
+ * when used in the first capacity.
+ *
+ * @note Has a problem if the guest kernel module cancels the HGCM call, as the
+ * guest cannot resume waiting till the host issues a message for it and
+ * the cancelled call returns. The new message may potentially end up in
+ * /dev/null depending and hang the message conversation between the guest
+ * and the host (SIGCHLD).
+ *
+ * @deprecated Replaced by GUEST_MSG_PEEK_WAIT, GUEST_MSG_GET and
+ * GUEST_MSG_CANCEL.
+ */
+ GUEST_MSG_WAIT = 1,
+ /** Cancels pending calls for this client session.
+ *
+ * This should be used if a GUEST_MSG_PEEK_WAIT or GUEST_MSG_WAIT call gets
+ * interrupted on the client end, so as to prevent being rebuffed with
+ * VERR_RESOURCE_BUSY when restarting the call.
+ *
+ * @retval VINF_SUCCESS if cancelled any calls.
+ * @retval VWRN_NOT_FOUND if no callers.
+ * @retval VERR_INVALID_CLIENT_ID
+ * @retval VERR_WRONG_PARAMETER_COUNT
+ * @since 6.0
+ */
+ GUEST_MSG_CANCEL = 2,
+ /** Guest disconnected (terminated normally or due to a crash HGCM
+ * detected when calling service::clientDisconnect().
+ *
+ * @note This is a host side notification message that has no business in this
+ * enum. The guest cannot use this message number, host will reject it.
+ */
+ GUEST_MSG_DISCONNECTED = 3,
+ /** Sets a message filter to only get messages which have a certain
+ * context ID scheme (that is, a specific session, object etc).
+ * Since VBox 4.3+.
+ * @deprecated Replaced by GUEST_SESSION_ACCEPT.
+ */
+ GUEST_MSG_FILTER_SET = 4,
+ /** Unsets (and resets) a previously set message filter.
+ * @retval VERR_NOT_IMPLEMENTED since 6.0.
+ * @deprecated Never needed or used,
+ */
+ GUEST_MSG_FILTER_UNSET = 5,
+ /** Peeks at the next message, returning immediately.
+ *
+ * Returns two 32-bit parameters, first is the message ID and the second the
+ * parameter count. May optionally return additional 32-bit parameters with the
+ * sizes of respective message parameters. To distinguish buffer sizes from
+ * integer parameters, the latter gets their sizes inverted (uint32_t is ~4U,
+ * uint64_t is ~8U).
+ *
+ * Does also support the VM restore checking as in GUEST_MSG_PEEK_WAIT (64-bit
+ * param \# 0), see documentation there.
+ *
+ * @retval VINF_SUCCESS if a message was pending and is being returned.
+ * @retval VERR_TRY_AGAIN if no message pending.
+ * @retval VERR_VM_RESTORED if first parameter is a non-zero 64-bit value that
+ * does not match VbglR3GetSessionId() any more. The new value is
+ * returned.
+ * @retval VERR_INVALID_CLIENT_ID
+ * @retval VERR_WRONG_PARAMETER_COUNT
+ * @retval VERR_WRONG_PARAMETER_TYPE
+ * @since 6.0
+ */
+ GUEST_MSG_PEEK_NOWAIT = 6,
+ /** Peeks at the next message, waiting for one to arrive.
+ *
+ * Returns two 32-bit parameters, first is the message ID and the second the
+ * parameter count. May optionally return additional 32-bit parameters with the
+ * sizes of respective message parameters. To distinguish buffer sizes from
+ * integer parameters, the latter gets their sizes inverted (uint32_t is ~4U,
+ * uint64_t is ~8U).
+ *
+ * To facilitate VM restore checking, the first parameter can be a 64-bit
+ * integer holding the VbglR3GetSessionId() value the guest knowns. The
+ * function will then check this before going to sleep and return
+ * VERR_VM_RESTORED if it doesn't match, same thing happens when the VM is
+ * restored.
+ *
+ * @retval VINF_SUCCESS if info about an pending message is being returned.
+ * @retval VINF_TRY_AGAIN and message set to HOST_CANCEL_PENDING_WAITS if
+ * cancelled by GUEST_MSG_CANCEL.
+ * @retval VERR_RESOURCE_BUSY if another thread already made a waiting call.
+ * @retval VERR_VM_RESTORED if first parameter is a non-zero 64-bit value that
+ * does not match VbglR3GetSessionId() any more. The new value is
+ * returned.
+ * @retval VERR_INVALID_CLIENT_ID
+ * @retval VERR_WRONG_PARAMETER_COUNT
+ * @retval VERR_WRONG_PARAMETER_TYPE
+ * @note This replaces GUEST_MSG_WAIT.
+ * @since 6.0
+ */
+ GUEST_MSG_PEEK_WAIT = 7,
+ /** Gets the next message, returning immediately.
+ *
+ * All parameters are specific to the message being retrieved, however if the
+ * first one is an integer value it shall be an input parameter holding the
+ * ID of the message being retrieved. While it would be nice to add a separate
+ * parameter for this purpose, this is difficult without breaking GUEST_MSG_WAIT
+ * compatibility.
+ *
+ * @retval VINF_SUCCESS if message retrieved and removed from the pending queue.
+ * @retval VERR_TRY_AGAIN if no message pending.
+ * @retval VERR_MISMATCH if the incoming message ID does not match the pending.
+ * @retval VERR_BUFFER_OVERFLOW if a parmeter buffer is too small. The buffer
+ * size was updated to reflect the required size.
+ * @retval VERR_INVALID_CLIENT_ID
+ * @retval VERR_WRONG_PARAMETER_COUNT
+ * @retval VERR_WRONG_PARAMETER_TYPE
+ * @note This replaces GUEST_MSG_WAIT.
+ * @since 6.0
+ */
+ GUEST_MSG_GET = 8,
+ /** Skip message.
+ *
+ * This skips the current message, replying to the main backend as best it can.
+ * Takes between zero and two parameters. The first parameter is the 32-bit
+ * VBox status code to pass onto Main when skipping the message, defaults to
+ * VERR_NOT_SUPPORTED. The second parameter is the 32-bit message ID of the
+ * message to skip, by default whatever is first in the queue is removed. This
+ * is also the case if UINT32_MAX is specified.
+ *
+ * @retval VINF_SUCCESS on success.
+ * @retval VERR_NOT_FOUND if no message pending.
+ * @retval VERR_MISMATCH if the specified message ID didn't match.
+ * @retval VERR_INVALID_CLIENT_ID
+ * @retval VERR_WRONG_PARAMETER_COUNT
+ * @since 6.0
+ */
+ GUEST_MSG_SKIP = 9,
+ /**
+ * Skips the current assigned message returned by GUEST_MSG_WAIT.
+ * Needed for telling the host service to not keep stale
+ * host messages in the queue.
+ * @deprecated Replaced by GUEST_MSG_SKIP.
+ */
+ GUEST_MSG_SKIP_OLD = 10,
+ /** General reply to a host message.
+ * Only contains basic data along with a simple payload.
+ * @todo proper docs.
+ */
+ GUEST_MSG_REPLY = 11,
+ /** General message for updating a pending progress for a long task.
+ * @todo proper docs.
+ */
+ GUEST_MSG_PROGRESS_UPDATE = 12,
+ /** Sets the caller as the master.
+ *
+ * Called by the root VBoxService to explicitly tell the host that's the master
+ * service. Required to use main VBoxGuest device node. No parameters.
+ *
+ * @retval VINF_SUCCESS on success.
+ * @retval VERR_ACCESS_DENIED if not using main VBoxGuest device not
+ * @retval VERR_RESOURCE_BUSY if there is already a master.
+ * @retval VERR_VERSION_MISMATCH if VBoxGuest didn't supply requestor info.
+ * @retval VERR_INVALID_CLIENT_ID
+ * @retval VERR_WRONG_PARAMETER_COUNT
+ * @since 6.0
+ */
+ GUEST_MSG_MAKE_ME_MASTER = 13,
+ /** Prepares the starting of a session.
+ *
+ * VBoxService makes this call before spawning a session process (must be
+ * master). The first parameter is the session ID and the second is a one time
+ * key for identifying the right session process. First parameter is a 32-bit
+ * session ID with a value between 1 and 0xfff0. The second parameter is a byte
+ * buffer containing a key that GUEST_SESSION_ACCEPT checks against, minimum
+ * length is 64 bytes, maximum 16384 bytes.
+ *
+ * @retval VINF_SUCCESS on success.
+ * @retval VERR_OUT_OF_RESOURCES if too many pending sessions hanging around.
+ * @retval VERR_OUT_OF_RANGE if the session ID outside the allowed range.
+ * @retval VERR_BUFFER_OVERFLOW if key too large.
+ * @retval VERR_BUFFER_UNDERFLOW if key too small.
+ * @retval VERR_ACCESS_DENIED if not master or in legacy mode.
+ * @retval VERR_DUPLICATE if the session ID has been prepared already.
+ * @retval VERR_INVALID_CLIENT_ID
+ * @retval VERR_WRONG_PARAMETER_COUNT
+ * @retval VERR_WRONG_PARAMETER_TYPE
+ * @since 6.0
+ */
+ GUEST_MSG_SESSION_PREPARE = 14,
+ /** Cancels a prepared session.
+ *
+ * VBoxService makes this call to clean up after spawning a session process
+ * failed. One parameter, 32-bit session ID. If UINT32_MAX is passed, all
+ * prepared sessions are cancelled.
+ *
+ * @retval VINF_SUCCESS on success.
+ * @retval VWRN_NOT_FOUND if no session with the specified ID.
+ * @retval VERR_ACCESS_DENIED if not master or in legacy mode.
+ * @retval VERR_INVALID_CLIENT_ID
+ * @retval VERR_WRONG_PARAMETER_COUNT
+ * @retval VERR_WRONG_PARAMETER_TYPE
+ * @since 6.0
+ */
+ GUEST_MSG_SESSION_CANCEL_PREPARED = 15,
+ /** Accepts a prepared session.
+ *
+ * The session processes makes this call to accept a prepared session. The
+ * session ID is then uniquely associated with the HGCM client ID of the caller.
+ * The parameters must be identical to the matching GUEST_SESSION_PREPARE call.
+ *
+ * @retval VINF_SUCCESS on success.
+ * @retval VERR_NOT_FOUND if the specified session ID wasn't found.
+ * @retval VERR_OUT_OF_RANGE if the session ID outside the allowed range.
+ * @retval VERR_BUFFER_OVERFLOW if key too large.
+ * @retval VERR_BUFFER_UNDERFLOW if key too small.
+ * @retval VERR_ACCESS_DENIED if we're in legacy mode or is master.
+ * @retval VERR_RESOURCE_BUSY if the client is already associated with a session.
+ * @retval VERR_MISMATCH if the key didn't match.
+ * @retval VERR_INVALID_CLIENT_ID
+ * @retval VERR_WRONG_PARAMETER_COUNT
+ * @retval VERR_WRONG_PARAMETER_TYPE
+ * @since 6.0
+ */
+ GUEST_MSG_SESSION_ACCEPT = 16,
+ /**
+ * Guest reports back a guest session status.
+ * @todo proper docs.
+ */
+ GUEST_MSG_SESSION_NOTIFY = 20,
+ /**
+ * Guest wants to close a specific guest session.
+ * @todo proper docs.
+ */
+ GUEST_MSG_SESSION_CLOSE = 21,
+
+ /** Report guest side feature flags and retrieve the host ones.
+ *
+ * VBoxService makes this call right after becoming master to indicate to the
+ * host what features it support in addition. In return the host will return
+ * features the host supports. Two 64-bit parameters are passed in from the
+ * guest with the guest features (VBOX_GUESTCTRL_GF_XXX), the host replies by
+ * replacing the parameter values with the host ones (VBOX_GUESTCTRL_HF_XXX).
+ *
+ * @retval VINF_SUCCESS on success.
+ * @retval VERR_ACCESS_DENIED it not master.
+ * @retval VERR_INVALID_CLIENT_ID
+ * @retval VERR_WRONG_PARAMETER_COUNT
+ * @retval VERR_WRONG_PARAMETER_TYPE
+ * @since 6.0.10, 5.2.32
+ */
+ GUEST_MSG_REPORT_FEATURES,
+ /** Query the host ones feature masks.
+ *
+ * This is for the session sub-process so that it can get hold of the features
+ * from the host. Again, it is prudent to set the 127 bit and observe it being
+ * cleared on success, as older hosts might return success without doing
+ * anything.
+ *
+ * @retval VINF_SUCCESS on success.
+ * @retval VERR_INVALID_CLIENT_ID
+ * @retval VERR_WRONG_PARAMETER_COUNT
+ * @retval VERR_WRONG_PARAMETER_TYPE
+ * @since 6.0.10, 5.2.32
+ */
+ GUEST_MSG_QUERY_FEATURES,
+
+ /**
+ * Guests sends output from an executed process.
+ * @todo proper docs.
+ */
+ GUEST_MSG_EXEC_OUTPUT = 100,
+ /**
+ * Guest sends a status update of an executed process to the host.
+ * @todo proper docs.
+ */
+ GUEST_MSG_EXEC_STATUS = 101,
+ /**
+ * Guests sends an input status notification to the host.
+ * @todo proper docs.
+ */
+ GUEST_MSG_EXEC_INPUT_STATUS = 102,
+ /**
+ * Guest notifies the host about some I/O event. This can be
+ * a stdout, stderr or a stdin event. The actual event only tells
+ * how many data is available / can be sent without actually
+ * transmitting the data.
+ * @todo proper docs.
+ */
+ GUEST_MSG_EXEC_IO_NOTIFY = 210,
+ /**
+ * Guest notifies the host about some directory event.
+ * @todo proper docs.
+ */
+ GUEST_MSG_DIR_NOTIFY = 230,
+ /**
+ * Guest notifies the host about some file event.
+ * @todo proper docs.
+ */
+ GUEST_MSG_FILE_NOTIFY = 240
+};
+
+/**
+ * Translates a guest control guest message enum to a string.
+ *
+ * @returns Enum string name.
+ * @param enmMsg The message to translate.
+ */
+DECLINLINE(const char *) GstCtrlGuestMsgToStr(enum eGuestMsg enmMsg)
+{
+ switch (enmMsg)
+ {
+ RT_CASE_RET_STR(GUEST_MSG_WAIT);
+ RT_CASE_RET_STR(GUEST_MSG_CANCEL);
+ RT_CASE_RET_STR(GUEST_MSG_DISCONNECTED);
+ RT_CASE_RET_STR(GUEST_MSG_FILTER_SET);
+ RT_CASE_RET_STR(GUEST_MSG_FILTER_UNSET);
+ RT_CASE_RET_STR(GUEST_MSG_PEEK_NOWAIT);
+ RT_CASE_RET_STR(GUEST_MSG_PEEK_WAIT);
+ RT_CASE_RET_STR(GUEST_MSG_GET);
+ RT_CASE_RET_STR(GUEST_MSG_SKIP_OLD);
+ RT_CASE_RET_STR(GUEST_MSG_REPLY);
+ RT_CASE_RET_STR(GUEST_MSG_PROGRESS_UPDATE);
+ RT_CASE_RET_STR(GUEST_MSG_SKIP);
+ RT_CASE_RET_STR(GUEST_MSG_MAKE_ME_MASTER);
+ RT_CASE_RET_STR(GUEST_MSG_SESSION_PREPARE);
+ RT_CASE_RET_STR(GUEST_MSG_SESSION_CANCEL_PREPARED);
+ RT_CASE_RET_STR(GUEST_MSG_SESSION_ACCEPT);
+ RT_CASE_RET_STR(GUEST_MSG_SESSION_NOTIFY);
+ RT_CASE_RET_STR(GUEST_MSG_SESSION_CLOSE);
+ RT_CASE_RET_STR(GUEST_MSG_REPORT_FEATURES);
+ RT_CASE_RET_STR(GUEST_MSG_QUERY_FEATURES);
+ RT_CASE_RET_STR(GUEST_MSG_EXEC_OUTPUT);
+ RT_CASE_RET_STR(GUEST_MSG_EXEC_STATUS);
+ RT_CASE_RET_STR(GUEST_MSG_EXEC_INPUT_STATUS);
+ RT_CASE_RET_STR(GUEST_MSG_EXEC_IO_NOTIFY);
+ RT_CASE_RET_STR(GUEST_MSG_DIR_NOTIFY);
+ RT_CASE_RET_STR(GUEST_MSG_FILE_NOTIFY);
+ }
+ return "Unknown";
+}
+
+
+/**
+ * Guest session notification types.
+ * @sa HGCMMsgSessionNotify.
+ */
+enum GUEST_SESSION_NOTIFYTYPE
+{
+ GUEST_SESSION_NOTIFYTYPE_UNDEFINED = 0,
+ /** Something went wrong (see rc). */
+ GUEST_SESSION_NOTIFYTYPE_ERROR = 1,
+ /** Guest session has been started. */
+ GUEST_SESSION_NOTIFYTYPE_STARTED = 11,
+ /** Guest session terminated normally. */
+ GUEST_SESSION_NOTIFYTYPE_TEN = 20,
+ /** Guest session terminated via signal. */
+ GUEST_SESSION_NOTIFYTYPE_TES = 30,
+ /** Guest session terminated abnormally. */
+ GUEST_SESSION_NOTIFYTYPE_TEA = 40,
+ /** Guest session timed out and was killed. */
+ GUEST_SESSION_NOTIFYTYPE_TOK = 50,
+ /** Guest session timed out and was not killed successfully. */
+ GUEST_SESSION_NOTIFYTYPE_TOA = 60,
+ /** Service/OS is stopping, process was killed. */
+ GUEST_SESSION_NOTIFYTYPE_DWN = 150
+};
+
+/**
+ * Guest directory notification types.
+ * @sa HGCMMsgDirNotify.
+ */
+enum GUEST_DIR_NOTIFYTYPE
+{
+ GUEST_DIR_NOTIFYTYPE_UNKNOWN = 0,
+ /** Something went wrong (see rc). */
+ GUEST_DIR_NOTIFYTYPE_ERROR = 1,
+ /** Guest directory opened. */
+ GUEST_DIR_NOTIFYTYPE_OPEN = 10,
+ /** Guest directory closed. */
+ GUEST_DIR_NOTIFYTYPE_CLOSE = 20,
+ /** Information about an open guest directory. */
+ GUEST_DIR_NOTIFYTYPE_INFO = 40,
+ /** Guest directory created. */
+ GUEST_DIR_NOTIFYTYPE_CREATE = 70,
+ /** Guest directory deleted. */
+ GUEST_DIR_NOTIFYTYPE_REMOVE = 80
+};
+
+/**
+ * Guest file notification types.
+ * @sa HGCMMsgFileNotify.
+ */
+enum GUEST_FILE_NOTIFYTYPE
+{
+ GUEST_FILE_NOTIFYTYPE_UNKNOWN = 0,
+ GUEST_FILE_NOTIFYTYPE_ERROR = 1,
+ GUEST_FILE_NOTIFYTYPE_OPEN = 10,
+ GUEST_FILE_NOTIFYTYPE_CLOSE = 20,
+ GUEST_FILE_NOTIFYTYPE_READ = 30,
+ GUEST_FILE_NOTIFYTYPE_READ_OFFSET, /**< @since 6.0.10, 5.2.32 - VBOX_GUESTCTRL_HF_0_NOTIFY_RDWR_OFFSET */
+ GUEST_FILE_NOTIFYTYPE_WRITE = 40,
+ GUEST_FILE_NOTIFYTYPE_WRITE_OFFSET, /**< @since 6.0.10, 5.2.32 - VBOX_GUESTCTRL_HF_0_NOTIFY_RDWR_OFFSET */
+ GUEST_FILE_NOTIFYTYPE_SEEK = 50,
+ GUEST_FILE_NOTIFYTYPE_TELL = 60,
+ GUEST_FILE_NOTIFYTYPE_SET_SIZE
+};
+
+/**
+ * Guest file seeking types. Has to match FileSeekType in Main.
+ *
+ * @note This is not compatible with RTFileSeek, which is an unncessary pain.
+ */
+enum GUEST_FILE_SEEKTYPE
+{
+ GUEST_FILE_SEEKTYPE_BEGIN = 1,
+ GUEST_FILE_SEEKTYPE_CURRENT = 4,
+ GUEST_FILE_SEEKTYPE_END = 8
+};
+
+/** @name VBOX_GUESTCTRL_GF_XXX - Guest features.
+ * @sa GUEST_MSG_REPORT_FEATURES
+ * @{ */
+/** Supports HOST_MSG_FILE_SET_SIZE. */
+#define VBOX_GUESTCTRL_GF_0_SET_SIZE RT_BIT_64(0)
+/** Supports passing process arguments starting at argv[0] rather than argv[1].
+ * Guest additions which doesn't support this feature will instead use the
+ * executable image path as argv[0].
+ * @sa VBOX_GUESTCTRL_HF_0_PROCESS_ARGV0
+ * @since 6.1.6 */
+#define VBOX_GUESTCTRL_GF_0_PROCESS_ARGV0 RT_BIT_64(1)
+/** Supports passing cmd / arguments / environment blocks bigger than
+ * GUESTPROCESS_DEFAULT_CMD_LEN / GUESTPROCESS_DEFAULT_ARGS_LEN / GUESTPROCESS_DEFAULT_ENV_LEN (bytes, in total). */
+#define VBOX_GUESTCTRL_GF_0_PROCESS_DYNAMIC_SIZES RT_BIT_64(2)
+/** Supports shutting down / rebooting the guest. */
+#define VBOX_GUESTCTRL_GF_0_SHUTDOWN RT_BIT_64(3)
+/** Bit that must be set in the 2nd parameter, will be cleared if the host reponds
+ * correctly (old hosts might not). */
+#define VBOX_GUESTCTRL_GF_1_MUST_BE_ONE RT_BIT_64(63)
+/** @} */
+
+/** @name VBOX_GUESTCTRL_HF_XXX - Host features.
+ * @sa GUEST_MSG_REPORT_FEATURES
+ * @{ */
+/** Host supports the GUEST_FILE_NOTIFYTYPE_READ_OFFSET and
+ * GUEST_FILE_NOTIFYTYPE_WRITE_OFFSET notification types. */
+#define VBOX_GUESTCTRL_HF_0_NOTIFY_RDWR_OFFSET RT_BIT_64(0)
+/** Host supports process passing arguments starting at argv[0] rather than
+ * argv[1], when the guest additions reports VBOX_GUESTCTRL_GF_0_PROCESS_ARGV0.
+ * @since 6.1.6 */
+#define VBOX_GUESTCTRL_HF_0_PROCESS_ARGV0 RT_BIT_64(1)
+/** @} */
+
+
+/*
+ * HGCM parameter structures.
+ */
+#pragma pack (1)
+
+/**
+ * Waits for a host message to arrive. The structure then contains the
+ * actual message type + required number of parameters needed to successfully
+ * retrieve that host message (in a next round).
+ */
+typedef struct HGCMMsgWaitFor
+{
+ VBGLIOCHGCMCALL hdr;
+ /** The returned message the host wants to run on the guest. */
+ HGCMFunctionParameter msg; /* OUT uint32_t */
+ /** Number of parameters the message needs. */
+ HGCMFunctionParameter num_parms; /* OUT uint32_t */
+} HGCMMsgWaitFor;
+
+/**
+ * Asks the guest control host service to set a message
+ * filter for this client. This filter will then only
+ * deliver messages to the client which match the
+ * wanted context ID (ranges).
+ */
+typedef struct HGCMMsgFilterSet
+{
+ VBGLIOCHGCMCALL hdr;
+ /** Value to filter for after filter mask was applied. */
+ HGCMFunctionParameter value; /* IN uint32_t */
+ /** Mask to add to the current set filter. */
+ HGCMFunctionParameter mask_add; /* IN uint32_t */
+ /** Mask to remove from the current set filter. */
+ HGCMFunctionParameter mask_remove; /* IN uint32_t */
+ /** Filter flags; currently unused. */
+ HGCMFunctionParameter flags; /* IN uint32_t */
+} HGCMMsgFilterSet;
+
+/**
+ * Asks the guest control host service to disable
+ * a previously set message filter again.
+ */
+typedef struct HGCMMsgFilterUnset
+{
+ VBGLIOCHGCMCALL hdr;
+ /** Unset flags; currently unused. */
+ HGCMFunctionParameter flags; /* IN uint32_t */
+} HGCMMsgFilterUnset;
+
+/**
+ * Asks the guest control host service to skip the
+ * currently assigned host message returned by
+ * VbglR3GuestCtrlMsgWaitFor().
+ */
+typedef struct HGCMMsgSkip
+{
+ VBGLIOCHGCMCALL hdr;
+ /** Skip flags; currently unused. */
+ HGCMFunctionParameter flags; /* IN uint32_t */
+} HGCMMsgSkip;
+
+/**
+ * Asks the guest control host service to cancel all pending (outstanding)
+ * waits which were not processed yet. This is handy for a graceful shutdown.
+ */
+typedef struct HGCMMsgCancelPendingWaits
+{
+ VBGLIOCHGCMCALL hdr;
+} HGCMMsgCancelPendingWaits;
+
+typedef struct HGCMMsgReply
+{
+ VBGLIOCHGCMCALL hdr;
+ /** Context ID. */
+ HGCMFunctionParameter context;
+ /** Message type. */
+ HGCMFunctionParameter type;
+ /** IPRT result of overall operation. */
+ HGCMFunctionParameter rc;
+ /** Optional payload to this reply. */
+ HGCMFunctionParameter payload;
+} HGCMMsgReply;
+
+/**
+ * Creates a guest session.
+ */
+typedef struct HGCMMsgSessionOpen
+{
+ VBGLIOCHGCMCALL hdr;
+ /** Context ID. */
+ HGCMFunctionParameter context;
+ /** The guest control protocol version this
+ * session is about to use. */
+ HGCMFunctionParameter protocol;
+ /** The user name to run the guest session under. */
+ HGCMFunctionParameter username;
+ /** The user's password. */
+ HGCMFunctionParameter password;
+ /** The domain to run the guest session under. */
+ HGCMFunctionParameter domain;
+ /** Session creation flags. */
+ HGCMFunctionParameter flags;
+} HGCMMsgSessionOpen;
+
+/**
+ * Terminates (closes) a guest session.
+ */
+typedef struct HGCMMsgSessionClose
+{
+ VBGLIOCHGCMCALL hdr;
+ /** Context ID. */
+ HGCMFunctionParameter context;
+ /** Session termination flags. */
+ HGCMFunctionParameter flags;
+} HGCMMsgSessionClose;
+
+/**
+ * Reports back a guest session's status.
+ */
+typedef struct HGCMMsgSessionNotify
+{
+ VBGLIOCHGCMCALL hdr;
+ /** Context ID. */
+ HGCMFunctionParameter context;
+ /** Notification type. */
+ HGCMFunctionParameter type;
+ /** Notification result. */
+ HGCMFunctionParameter result;
+} HGCMMsgSessionNotify;
+
+typedef struct HGCMMsgPathRename
+{
+ VBGLIOCHGCMCALL hdr;
+ /** UInt32: Context ID. */
+ HGCMFunctionParameter context;
+ /** Source to rename. */
+ HGCMFunctionParameter source;
+ /** Destination to rename source to. */
+ HGCMFunctionParameter dest;
+ /** UInt32: Rename flags. */
+ HGCMFunctionParameter flags;
+} HGCMMsgPathRename;
+
+typedef struct HGCMMsgPathUserDocuments
+{
+ VBGLIOCHGCMCALL hdr;
+ /** UInt32: Context ID. */
+ HGCMFunctionParameter context;
+} HGCMMsgPathUserDocuments;
+
+typedef struct HGCMMsgPathUserHome
+{
+ VBGLIOCHGCMCALL hdr;
+ /** UInt32: Context ID. */
+ HGCMFunctionParameter context;
+} HGCMMsgPathUserHome;
+
+/**
+ * Shuts down / reboots the guest.
+ */
+typedef struct HGCMMsgShutdown
+{
+ VBGLIOCHGCMCALL hdr;
+ /** UInt32: Context ID. */
+ HGCMFunctionParameter context;
+ /** UInt32: Action flags. */
+ HGCMFunctionParameter action;
+} HGCMMsgShutdown;
+
+/**
+ * Executes a command inside the guest.
+ */
+typedef struct HGCMMsgProcExec
+{
+ VBGLIOCHGCMCALL hdr;
+ /** Context ID. */
+ HGCMFunctionParameter context;
+ /** The command to execute on the guest. */
+ HGCMFunctionParameter cmd;
+ /** Execution flags (see IGuest::ProcessCreateFlag_*). */
+ HGCMFunctionParameter flags;
+ /** Number of arguments. */
+ HGCMFunctionParameter num_args;
+ /** The actual arguments. */
+ HGCMFunctionParameter args;
+ /** Number of environment value pairs. */
+ HGCMFunctionParameter num_env;
+ /** Size (in bytes) of environment block, including terminating zeros. */
+ HGCMFunctionParameter cb_env;
+ /** The actual environment block. */
+ HGCMFunctionParameter env;
+ union
+ {
+ struct
+ {
+ /** The user name to run the executed command under.
+ * Only for VBox < 4.3 hosts. */
+ HGCMFunctionParameter username;
+ /** The user's password.
+ * Only for VBox < 4.3 hosts. */
+ HGCMFunctionParameter password;
+ /** Timeout (in msec) which either specifies the
+ * overall lifetime of the process or how long it
+ * can take to bring the process up and running -
+ * (depends on the IGuest::ProcessCreateFlag_*). */
+ HGCMFunctionParameter timeout;
+ } v1;
+ struct
+ {
+ /** Timeout (in ms) which either specifies the
+ * overall lifetime of the process or how long it
+ * can take to bring the process up and running -
+ * (depends on the IGuest::ProcessCreateFlag_*). */
+ HGCMFunctionParameter timeout;
+ /** Process priority. */
+ HGCMFunctionParameter priority;
+ /** Number of process affinity blocks. */
+ HGCMFunctionParameter num_affinity;
+ /** Pointer to process affinity blocks (uint64_t). */
+ HGCMFunctionParameter affinity;
+ } v2;
+ } u;
+} HGCMMsgProcExec;
+
+/**
+ * Sends input to a guest process via stdin.
+ */
+typedef struct HGCMMsgProcInput
+{
+ VBGLIOCHGCMCALL hdr;
+ /** Context ID. */
+ HGCMFunctionParameter context;
+ /** The process ID (PID) to send the input to. */
+ HGCMFunctionParameter pid;
+ /** Input flags (see IGuest::ProcessInputFlag_*). */
+ HGCMFunctionParameter flags;
+ /** Data buffer. */
+ HGCMFunctionParameter data;
+ /** Actual size of data (in bytes). */
+ HGCMFunctionParameter size;
+} HGCMMsgProcInput;
+
+/**
+ * Retrieves ouptut from a previously executed process
+ * from stdout/stderr.
+ */
+typedef struct HGCMMsgProcOutput
+{
+ VBGLIOCHGCMCALL hdr;
+ /** Context ID. */
+ HGCMFunctionParameter context;
+ /** The process ID (PID). */
+ HGCMFunctionParameter pid;
+ /** The pipe handle ID (stdout/stderr). */
+ HGCMFunctionParameter handle;
+ /** Optional flags. */
+ HGCMFunctionParameter flags;
+ /** Data buffer. */
+ HGCMFunctionParameter data;
+} HGCMMsgProcOutput;
+
+/**
+ * Reports the current status of a guest process.
+ */
+typedef struct HGCMMsgProcStatus
+{
+ VBGLIOCHGCMCALL hdr;
+ /** Context ID. */
+ HGCMFunctionParameter context;
+ /** The process ID (PID). */
+ HGCMFunctionParameter pid;
+ /** The process status. */
+ HGCMFunctionParameter status;
+ /** Optional flags (based on status). */
+ HGCMFunctionParameter flags;
+ /** Optional data buffer (not used atm). */
+ HGCMFunctionParameter data;
+} HGCMMsgProcStatus;
+
+/**
+ * Reports back the status of data written to a process.
+ */
+typedef struct HGCMMsgProcStatusInput
+{
+ VBGLIOCHGCMCALL hdr;
+ /** Context ID. */
+ HGCMFunctionParameter context;
+ /** The process ID (PID). */
+ HGCMFunctionParameter pid;
+ /** Status of the operation. */
+ HGCMFunctionParameter status;
+ /** Optional flags. */
+ HGCMFunctionParameter flags;
+ /** Data written. */
+ HGCMFunctionParameter written;
+} HGCMMsgProcStatusInput;
+
+/*
+ * Guest control 2.0 messages.
+ */
+
+/**
+ * Terminates a guest process.
+ */
+typedef struct HGCMMsgProcTerminate
+{
+ VBGLIOCHGCMCALL hdr;
+ /** Context ID. */
+ HGCMFunctionParameter context;
+ /** The process ID (PID). */
+ HGCMFunctionParameter pid;
+} HGCMMsgProcTerminate;
+
+/**
+ * Waits for certain events to happen.
+ */
+typedef struct HGCMMsgProcWaitFor
+{
+ VBGLIOCHGCMCALL hdr;
+ /** Context ID. */
+ HGCMFunctionParameter context;
+ /** The process ID (PID). */
+ HGCMFunctionParameter pid;
+ /** Wait (event) flags. */
+ HGCMFunctionParameter flags;
+ /** Timeout (in ms). */
+ HGCMFunctionParameter timeout;
+} HGCMMsgProcWaitFor;
+
+typedef struct HGCMMsgDirRemove
+{
+ VBGLIOCHGCMCALL hdr;
+ /** UInt32: Context ID. */
+ HGCMFunctionParameter context;
+ /** Directory to remove. */
+ HGCMFunctionParameter path;
+ /** UInt32: Removement flags. */
+ HGCMFunctionParameter flags;
+} HGCMMsgDirRemove;
+
+/**
+ * Opens a guest file.
+ */
+typedef struct HGCMMsgFileOpen
+{
+ VBGLIOCHGCMCALL hdr;
+ /** UInt32: Context ID. */
+ HGCMFunctionParameter context;
+ /** File to open. */
+ HGCMFunctionParameter filename;
+ /** Open mode. */
+ HGCMFunctionParameter openmode;
+ /** Disposition mode. */
+ HGCMFunctionParameter disposition;
+ /** Sharing mode. */
+ HGCMFunctionParameter sharing;
+ /** UInt32: Creation mode. */
+ HGCMFunctionParameter creationmode;
+ /** UInt64: Initial offset. */
+ HGCMFunctionParameter offset;
+} HGCMMsgFileOpen;
+
+/**
+ * Closes a guest file.
+ */
+typedef struct HGCMMsgFileClose
+{
+ VBGLIOCHGCMCALL hdr;
+ /** Context ID. */
+ HGCMFunctionParameter context;
+ /** File handle to close. */
+ HGCMFunctionParameter handle;
+} HGCMMsgFileClose;
+
+/**
+ * Reads from a guest file.
+ */
+typedef struct HGCMMsgFileRead
+{
+ VBGLIOCHGCMCALL hdr;
+ /** Context ID. */
+ HGCMFunctionParameter context;
+ /** File handle to read from. */
+ HGCMFunctionParameter handle;
+ /** Size (in bytes) to read. */
+ HGCMFunctionParameter size;
+} HGCMMsgFileRead;
+
+/**
+ * Reads at a specified offset from a guest file.
+ */
+typedef struct HGCMMsgFileReadAt
+{
+ VBGLIOCHGCMCALL hdr;
+ /** Context ID. */
+ HGCMFunctionParameter context;
+ /** File handle to read from. */
+ HGCMFunctionParameter handle;
+ /** Offset where to start reading from. */
+ HGCMFunctionParameter offset;
+ /** Actual size of data (in bytes). */
+ HGCMFunctionParameter size;
+} HGCMMsgFileReadAt;
+
+/**
+ * Writes to a guest file.
+ */
+typedef struct HGCMMsgFileWrite
+{
+ VBGLIOCHGCMCALL hdr;
+ /** Context ID. */
+ HGCMFunctionParameter context;
+ /** File handle to write to. */
+ HGCMFunctionParameter handle;
+ /** Actual size of data (in bytes). */
+ HGCMFunctionParameter size;
+ /** Data buffer to write to the file. */
+ HGCMFunctionParameter data;
+} HGCMMsgFileWrite;
+
+/**
+ * Writes at a specified offset to a guest file.
+ */
+typedef struct HGCMMsgFileWriteAt
+{
+ VBGLIOCHGCMCALL hdr;
+ /** Context ID. */
+ HGCMFunctionParameter context;
+ /** File handle to write to. */
+ HGCMFunctionParameter handle;
+ /** Offset where to start reading from. */
+ HGCMFunctionParameter offset;
+ /** Actual size of data (in bytes). */
+ HGCMFunctionParameter size;
+ /** Data buffer to write to the file. */
+ HGCMFunctionParameter data;
+} HGCMMsgFileWriteAt;
+
+/**
+ * Seeks the read/write position of a guest file.
+ */
+typedef struct HGCMMsgFileSeek
+{
+ VBGLIOCHGCMCALL hdr;
+ /** Context ID. */
+ HGCMFunctionParameter context;
+ /** File handle to seek. */
+ HGCMFunctionParameter handle;
+ /** The seeking method. */
+ HGCMFunctionParameter method;
+ /** The seeking offset. */
+ HGCMFunctionParameter offset;
+} HGCMMsgFileSeek;
+
+/**
+ * Tells the current read/write position of a guest file.
+ */
+typedef struct HGCMMsgFileTell
+{
+ VBGLIOCHGCMCALL hdr;
+ /** Context ID. */
+ HGCMFunctionParameter context;
+ /** File handle to get the current position for. */
+ HGCMFunctionParameter handle;
+} HGCMMsgFileTell;
+
+/**
+ * Changes the file size.
+ */
+typedef struct HGCMMsgFileSetSize
+{
+ VBGLIOCHGCMCALL Hdr;
+ /** Context ID. */
+ HGCMFunctionParameter id32Context;
+ /** File handle to seek. */
+ HGCMFunctionParameter id32Handle;
+ /** The new file size. */
+ HGCMFunctionParameter cb64NewSize;
+} HGCMMsgFileSetSize;
+
+
+/******************************************************************************
+* HGCM replies from the guest. These are handled in Main's low-level HGCM *
+* callbacks and dispatched to the appropriate guest object. *
+******************************************************************************/
+
+typedef struct HGCMReplyFileNotify
+{
+ VBGLIOCHGCMCALL hdr;
+ /** Context ID. */
+ HGCMFunctionParameter context;
+ /** Notification type. */
+ HGCMFunctionParameter type;
+ /** IPRT result of overall operation. */
+ HGCMFunctionParameter rc;
+ union
+ {
+ struct
+ {
+ /** Guest file handle. */
+ HGCMFunctionParameter handle;
+ } open;
+ /** Note: Close does not have any additional data (yet). */
+ struct
+ {
+ /** Actual data read (if any). */
+ HGCMFunctionParameter data;
+ } read;
+ struct
+ {
+ /** Actual data read (if any). */
+ HGCMFunctionParameter pvData;
+ /** The new file offset (signed). Negative value if non-seekable files. */
+ HGCMFunctionParameter off64New;
+ } ReadOffset;
+ struct
+ {
+ /** How much data (in bytes) have been successfully written. */
+ HGCMFunctionParameter written;
+ } write;
+ struct
+ {
+ /** Number of bytes that was successfully written. */
+ HGCMFunctionParameter cb32Written;
+ /** The new file offset (signed). Negative value if non-seekable files. */
+ HGCMFunctionParameter off64New;
+ } WriteOffset;
+ struct
+ {
+ HGCMFunctionParameter offset;
+ } seek;
+ struct
+ {
+ HGCMFunctionParameter offset;
+ } tell;
+ struct
+ {
+ HGCMFunctionParameter cb64Size;
+ } SetSize;
+ } u;
+} HGCMReplyFileNotify;
+
+typedef struct HGCMReplyDirNotify
+{
+ VBGLIOCHGCMCALL hdr;
+ /** Context ID. */
+ HGCMFunctionParameter context;
+ /** Notification type. */
+ HGCMFunctionParameter type;
+ /** IPRT result of overall operation. */
+ HGCMFunctionParameter rc;
+ union
+ {
+ struct
+ {
+ /** Directory information. */
+ HGCMFunctionParameter objInfo;
+ } info;
+ struct
+ {
+ /** Guest directory handle. */
+ HGCMFunctionParameter handle;
+ } open;
+ struct
+ {
+ /** Current read directory entry. */
+ HGCMFunctionParameter entry;
+ /** Extended entry object information. Optional. */
+ HGCMFunctionParameter objInfo;
+ } read;
+ } u;
+} HGCMReplyDirNotify;
+
+#pragma pack ()
+
+/******************************************************************************
+* Callback data structures. *
+******************************************************************************/
+
+/**
+ * The guest control callback data header. Must come first
+ * on each callback structure defined below this struct.
+ */
+typedef struct CALLBACKDATA_HEADER
+{
+ /** Context ID to identify callback data. This is
+ * and *must* be the very first parameter in this
+ * structure to still be backwards compatible. */
+ uint32_t uContextID;
+} CALLBACKDATA_HEADER, *PCALLBACKDATA_HEADER;
+
+/*
+ * These structures make up the actual low level HGCM callback data sent from
+ * the guest back to the host.
+ */
+
+typedef struct CALLBACKDATA_CLIENT_DISCONNECTED
+{
+ /** Callback data header. */
+ CALLBACKDATA_HEADER hdr;
+} CALLBACKDATA_CLIENT_DISCONNECTED, *PCALLBACKDATA_CLIENT_DISCONNECTED;
+
+typedef struct CALLBACKDATA_MSG_REPLY
+{
+ /** Callback data header. */
+ CALLBACKDATA_HEADER hdr;
+ /** Notification type. */
+ uint32_t uType;
+ /** Notification result. Note: int vs. uint32! */
+ uint32_t rc;
+ /** Pointer to optional payload. */
+ void *pvPayload;
+ /** Payload size (in bytes). */
+ uint32_t cbPayload;
+} CALLBACKDATA_MSG_REPLY, *PCALLBACKDATA_MSG_REPLY;
+
+typedef struct CALLBACKDATA_SESSION_NOTIFY
+{
+ /** Callback data header. */
+ CALLBACKDATA_HEADER hdr;
+ /** Notification type. */
+ uint32_t uType;
+ /** Notification result. Note: int vs. uint32! */
+ uint32_t uResult;
+} CALLBACKDATA_SESSION_NOTIFY, *PCALLBACKDATA_SESSION_NOTIFY;
+
+typedef struct CALLBACKDATA_PROC_STATUS
+{
+ /** Callback data header. */
+ CALLBACKDATA_HEADER hdr;
+ /** The process ID (PID). */
+ uint32_t uPID;
+ /** The process status. */
+ uint32_t uStatus;
+ /** Optional flags, varies, based on u32Status. */
+ uint32_t uFlags;
+ /** Optional data buffer (not used atm). */
+ void *pvData;
+ /** Size of optional data buffer (not used atm). */
+ uint32_t cbData;
+} CALLBACKDATA_PROC_STATUS, *PCALLBACKDATA_PROC_STATUS;
+
+typedef struct CALLBACKDATA_PROC_OUTPUT
+{
+ /** Callback data header. */
+ CALLBACKDATA_HEADER hdr;
+ /** The process ID (PID). */
+ uint32_t uPID;
+ /** The handle ID (stdout/stderr). */
+ uint32_t uHandle;
+ /** Optional flags (not used atm). */
+ uint32_t uFlags;
+ /** Optional data buffer. */
+ void *pvData;
+ /** Size (in bytes) of optional data buffer. */
+ uint32_t cbData;
+} CALLBACKDATA_PROC_OUTPUT, *PCALLBACKDATA_PROC_OUTPUT;
+
+typedef struct CALLBACKDATA_PROC_INPUT
+{
+ /** Callback data header. */
+ CALLBACKDATA_HEADER hdr;
+ /** The process ID (PID). */
+ uint32_t uPID;
+ /** Current input status. */
+ uint32_t uStatus;
+ /** Optional flags. */
+ uint32_t uFlags;
+ /** Size (in bytes) of processed input data. */
+ uint32_t uProcessed;
+} CALLBACKDATA_PROC_INPUT, *PCALLBACKDATA_PROC_INPUT;
+
+/**
+ * General guest directory notification callback.
+ */
+typedef struct CALLBACKDATA_DIR_NOTIFY
+{
+ /** Callback data header. */
+ CALLBACKDATA_HEADER hdr;
+ /** Notification type. */
+ uint32_t uType;
+ /** IPRT result of overall operation. */
+ uint32_t rc;
+ union
+ {
+ struct
+ {
+ /** Size (in bytes) of directory information. */
+ uint32_t cbObjInfo;
+ /** Pointer to directory information. */
+ void *pvObjInfo;
+ } info;
+ struct
+ {
+ /** Guest directory handle. */
+ uint32_t uHandle;
+ } open;
+ /** Note: Close does not have any additional data (yet). */
+ struct
+ {
+ /** Size (in bytes) of directory entry information. */
+ uint32_t cbEntry;
+ /** Pointer to directory entry information. */
+ void *pvEntry;
+ /** Size (in bytes) of directory entry object information. */
+ uint32_t cbObjInfo;
+ /** Pointer to directory entry object information. */
+ void *pvObjInfo;
+ } read;
+ } u;
+} CALLBACKDATA_DIR_NOTIFY, *PCALLBACKDATA_DIR_NOTIFY;
+
+/**
+ * General guest file notification callback.
+ */
+typedef struct CALLBACKDATA_FILE_NOTIFY
+{
+ /** Callback data header. */
+ CALLBACKDATA_HEADER hdr;
+ /** Notification type. */
+ uint32_t uType;
+ /** IPRT result of overall operation. */
+ uint32_t rc;
+ union
+ {
+ struct
+ {
+ /** Guest file handle. */
+ uint32_t uHandle;
+ } open;
+ /** Note: Close does not have any additional data (yet). */
+ struct
+ {
+ /** How much data (in bytes) have been read. */
+ uint32_t cbData;
+ /** Actual data read (if any). */
+ void *pvData;
+ } read;
+ struct
+ {
+ /** How much data (in bytes) have been successfully written. */
+ uint32_t cbWritten;
+ } write;
+ struct
+ {
+ /** New file offset after successful seek. */
+ uint64_t uOffActual;
+ } seek;
+ struct
+ {
+ /** New file offset after successful tell. */
+ uint64_t uOffActual;
+ } tell;
+ struct
+ {
+ /** The new file siz.e */
+ uint64_t cbSize;
+ } SetSize;
+ } u;
+} CALLBACKDATA_FILE_NOTIFY, *PCALLBACKDATA_FILE_NOTIFY;
+
+} /* namespace guestControl */
+
+#endif /* !VBOX_INCLUDED_HostServices_GuestControlSvc_h */
+
diff --git a/include/VBox/HostServices/GuestPropertySvc.h b/include/VBox/HostServices/GuestPropertySvc.h
new file mode 100644
index 00000000..806ba306
--- /dev/null
+++ b/include/VBox/HostServices/GuestPropertySvc.h
@@ -0,0 +1,553 @@
+/** @file
+ * Guest property service - Common header for host service and guest clients.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_HostServices_GuestPropertySvc_h
+#define VBOX_INCLUDED_HostServices_GuestPropertySvc_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/VMMDevCoreTypes.h>
+#include <VBox/VBoxGuestCoreTypes.h>
+#include <VBox/log.h>
+#include <iprt/err.h>
+#include <iprt/assertcompile.h>
+#include <iprt/string.h>
+
+
+/** Maximum size for property names (including the terminator). */
+#define GUEST_PROP_MAX_NAME_LEN 64
+/** Maximum size for property values (including the terminator). */
+#define GUEST_PROP_MAX_VALUE_LEN 1024
+/** Maximum number of properties per guest. */
+#define GUEST_PROP_MAX_PROPS 256
+/** Maximum size for enumeration patterns (including the terminators). */
+#define GUEST_PROP_MAX_PATTERN_LEN 1024
+/** Maximum number of changes we remember for guest notifications. */
+#define GUEST_PROP_MAX_GUEST_NOTIFICATIONS 256
+/** Maximum number of current pending waits per client. */
+#define GUEST_PROP_MAX_GUEST_CONCURRENT_WAITS 16
+
+
+/** @name GUEST_PROP_F_XXX - The guest property flag values which are currently accepted.
+ * @{
+ */
+#define GUEST_PROP_F_NILFLAG UINT32_C(0)
+/** Transient until VM gets shut down. */
+#define GUEST_PROP_F_TRANSIENT RT_BIT_32(1)
+#define GUEST_PROP_F_RDONLYGUEST RT_BIT_32(2)
+#define GUEST_PROP_F_RDONLYHOST RT_BIT_32(3)
+/** Transient until VM gets a reset / restarts.
+ * Implies TRANSIENT. */
+#define GUEST_PROP_F_TRANSRESET RT_BIT_32(4)
+#define GUEST_PROP_F_READONLY (GUEST_PROP_F_RDONLYGUEST | GUEST_PROP_F_RDONLYHOST)
+#define GUEST_PROP_F_ALLFLAGS (GUEST_PROP_F_TRANSIENT | GUEST_PROP_F_READONLY | GUEST_PROP_F_TRANSRESET)
+/** @} */
+
+/**
+ * Check that a string fits our criteria for a property name.
+ *
+ * @returns IPRT status code
+ * @param pszName The string to check, must be valid Utf8
+ * @param cbName The number of bytes @a pszName points to, including the
+ * terminating character.
+ */
+DECLINLINE(int) GuestPropValidateName(const char *pszName, size_t cbName)
+{
+ /* Property name is expected to be at least 1 charecter long plus terminating character. */
+ AssertReturn(cbName >= 2, VERR_INVALID_PARAMETER);
+ AssertReturn(cbName <= GUEST_PROP_MAX_NAME_LEN, VERR_INVALID_PARAMETER);
+
+ AssertPtrReturn(pszName, VERR_INVALID_POINTER);
+
+ AssertReturn(memchr(pszName, '*', cbName) == NULL, VERR_INVALID_PARAMETER);
+ AssertReturn(memchr(pszName, '?', cbName) == NULL, VERR_INVALID_PARAMETER);
+ AssertReturn(memchr(pszName, '|', cbName) == NULL, VERR_INVALID_PARAMETER);
+
+ return VINF_SUCCESS;
+}
+
+/**
+ * Check a string fits our criteria for the value of a guest property.
+ *
+ * @returns IPRT status code
+ * @retval VINF_SUCCESS if guest property value corresponds to all criteria.
+ * @retval VERR_TOO_MUCH_DATA if guest property value size exceeds limits.
+ * @retval VERR_INVALID_PARAMETER if guest property does not correspond to all other criteria.
+ * @param pszValue The string to check, must be valid utf-8.
+ * @param cbValue The size of of @a pszValue in bytes, including the
+ * terminator.
+ * @thread HGCM
+ */
+DECLINLINE(int) GuestPropValidateValue(const char *pszValue, size_t cbValue)
+{
+ AssertPtrReturn(pszValue, VERR_INVALID_POINTER);
+
+ /* Zero-length values are possible, however buffer should contain terminating character at least. */
+ AssertReturn(cbValue > 0, VERR_INVALID_PARAMETER);
+ AssertReturn(cbValue <= GUEST_PROP_MAX_VALUE_LEN, VERR_TOO_MUCH_DATA);
+
+ return VINF_SUCCESS;
+}
+
+/**
+ * Get the name of a flag as a string.
+ * @returns the name, or NULL if fFlag is invalid.
+ * @param fFlag The flag, GUEST_PROP_F_XXX.
+ * @param pcchName Where to return the name length.
+ */
+DECLINLINE(const char *) GuestPropFlagNameAndLen(uint32_t fFlag, size_t *pcchName)
+{
+ switch (fFlag)
+ {
+ case GUEST_PROP_F_TRANSIENT:
+ *pcchName = sizeof("TRANSIENT") - 1;
+ return "TRANSIENT";
+ case GUEST_PROP_F_RDONLYGUEST:
+ *pcchName = sizeof("RDONLYGUEST") - 1;
+ return "RDONLYGUEST";
+ case GUEST_PROP_F_RDONLYHOST:
+ *pcchName = sizeof("RDONLYHOST") - 1;
+ return "RDONLYHOST";
+ case GUEST_PROP_F_READONLY:
+ *pcchName = sizeof("READONLY") - 1;
+ return "READONLY";
+ case GUEST_PROP_F_TRANSRESET:
+ *pcchName = sizeof("TRANSRESET") - 1;
+ return "TRANSRESET";
+ default:
+ *pcchName = 0;
+ return NULL;
+ }
+}
+
+/**
+ * Maximum length for the property flags field. We only ever return one of
+ * RDONLYGUEST, RDONLYHOST and RDONLY
+ */
+#define GUEST_PROP_MAX_FLAGS_LEN sizeof("TRANSIENT, RDONLYGUEST, TRANSRESET")
+
+/**
+ * Parse a guest properties flags string for flag names and make sure that
+ * there is no junk text in the string.
+ *
+ * @returns IPRT status code
+ * @retval VERR_INVALID_PARAMETER if the flag string is not valid
+ * @param pcszFlags the flag string to parse
+ * @param pfFlags where to store the parse result. May not be NULL.
+ * @note This function is also inline because it must be accessible from
+ * several modules and it does not seem reasonable to put it into
+ * its own library.
+ */
+DECLINLINE(int) GuestPropValidateFlags(const char *pcszFlags, uint32_t *pfFlags)
+{
+ static const uint32_t s_aFlagList[] =
+ {
+ GUEST_PROP_F_TRANSIENT, GUEST_PROP_F_READONLY, GUEST_PROP_F_RDONLYGUEST, GUEST_PROP_F_RDONLYHOST, GUEST_PROP_F_TRANSRESET
+ };
+ const char *pcszNext = pcszFlags;
+ int rc = VINF_SUCCESS;
+ uint32_t fFlags = 0;
+ AssertLogRelReturn(RT_VALID_PTR(pfFlags), VERR_INVALID_POINTER);
+
+ if (pcszFlags)
+ {
+ while (*pcszNext == ' ')
+ ++pcszNext;
+ while ((*pcszNext != '\0') && RT_SUCCESS(rc))
+ {
+ unsigned i;
+ rc = VERR_PARSE_ERROR;
+ for (i = 0; i < RT_ELEMENTS(s_aFlagList); ++i)
+ {
+ size_t cchFlagName;
+ const char *pszFlagName = GuestPropFlagNameAndLen(s_aFlagList[i], &cchFlagName);
+ if (RTStrNICmpAscii(pcszNext, pszFlagName, cchFlagName) == 0)
+ {
+ char ch;
+ fFlags |= s_aFlagList[i];
+ pcszNext += cchFlagName;
+ while ((ch = *pcszNext) == ' ')
+ ++pcszNext;
+ rc = VINF_SUCCESS;
+ if (ch == ',')
+ {
+ ++pcszNext;
+ while (*pcszNext == ' ')
+ ++pcszNext;
+ }
+ else if (ch != '\0')
+ rc = VERR_PARSE_ERROR;
+ break;
+ }
+ }
+ }
+ }
+ if (RT_SUCCESS(rc))
+ *pfFlags = fFlags;
+ return rc;
+}
+
+
+/**
+ * Write out flags to a string.
+ * @returns IPRT status code
+ * @param fFlags the flags to write out
+ * @param pszFlags where to write the flags string. This must point to
+ * a buffer of size (at least) GUEST_PROP_MAX_FLAGS_LEN.
+ */
+DECLINLINE(int) GuestPropWriteFlags(uint32_t fFlags, char *pszFlags)
+{
+ /* Putting READONLY before the other RDONLY flags keeps the result short. */
+ static const uint32_t s_aFlagList[] =
+ {
+ GUEST_PROP_F_TRANSIENT, GUEST_PROP_F_READONLY, GUEST_PROP_F_RDONLYGUEST, GUEST_PROP_F_RDONLYHOST, GUEST_PROP_F_TRANSRESET
+ };
+ int rc = VINF_SUCCESS;
+
+ AssertLogRelReturn(RT_VALID_PTR(pszFlags), VERR_INVALID_POINTER);
+ if ((fFlags & ~GUEST_PROP_F_ALLFLAGS) == GUEST_PROP_F_NILFLAG)
+ {
+ char *pszNext;
+ unsigned i;
+
+ /* TRANSRESET implies TRANSIENT. For compatability with old clients we
+ always set TRANSIENT when TRANSRESET appears. */
+ if (fFlags & GUEST_PROP_F_TRANSRESET)
+ fFlags |= GUEST_PROP_F_TRANSIENT;
+
+ pszNext = pszFlags;
+ for (i = 0; i < RT_ELEMENTS(s_aFlagList); ++i)
+ {
+ if (s_aFlagList[i] == (fFlags & s_aFlagList[i]))
+ {
+ size_t cchFlagName;
+ const char *pszFlagName = GuestPropFlagNameAndLen(s_aFlagList[i], &cchFlagName);
+ memcpy(pszNext, pszFlagName, cchFlagName);
+ pszNext += cchFlagName;
+ fFlags &= ~s_aFlagList[i];
+ if (fFlags != GUEST_PROP_F_NILFLAG)
+ {
+ *pszNext++ = ',';
+ *pszNext++ = ' ';
+ }
+ }
+ }
+ *pszNext = '\0';
+
+ Assert((uintptr_t)(pszNext - pszFlags) < GUEST_PROP_MAX_FLAGS_LEN);
+ Assert(fFlags == GUEST_PROP_F_NILFLAG); /* bad s_aFlagList */
+ }
+ else
+ rc = VERR_INVALID_PARAMETER;
+ return rc;
+}
+
+
+/** @name The service functions which are callable by host.
+ * @{
+ */
+/** Set properties in a block.
+ * The parameters are pointers to NULL-terminated arrays containing the
+ * parameters. These are, in order, name, value, timestamp, flags. Strings are
+ * stored as pointers to mutable utf8 data. All parameters must be supplied. */
+#define GUEST_PROP_FN_HOST_SET_PROPS 1
+/** Get the value attached to a guest property.
+ * The parameter format matches that of GET_PROP. */
+#define GUEST_PROP_FN_HOST_GET_PROP 2
+/** Set the value attached to a guest property.
+ * The parameter format matches that of SET_PROP. */
+#define GUEST_PROP_FN_HOST_SET_PROP 3
+/** Set the value attached to a guest property.
+ * The parameter format matches that of SET_PROP_VALUE. */
+#define GUEST_PROP_FN_HOST_SET_PROP_VALUE 4
+/** Remove a guest property.
+ * The parameter format matches that of DEL_PROP. */
+#define GUEST_PROP_FN_HOST_DEL_PROP 5
+/** Enumerate guest properties.
+ * The parameter format matches that of ENUM_PROPS. */
+#define GUEST_PROP_FN_HOST_ENUM_PROPS 6
+/** Set global flags for the service.
+ * Currently RDONLYGUEST is supported. Takes one 32-bit unsigned integer
+ * parameter for the flags. */
+#define GUEST_PROP_FN_HOST_SET_GLOBAL_FLAGS 7
+/** @} */
+
+
+/** @name The service functions which are called by guest.
+ *
+ * @note The numbers may not change!
+ * @{
+ */
+/** Get a guest property */
+#define GUEST_PROP_FN_GET_PROP 1
+/** Set a guest property */
+#define GUEST_PROP_FN_SET_PROP 2
+/** Set just the value of a guest property */
+#define GUEST_PROP_FN_SET_PROP_VALUE 3
+/** Delete a guest property */
+#define GUEST_PROP_FN_DEL_PROP 4
+/** Enumerate guest properties */
+#define GUEST_PROP_FN_ENUM_PROPS 5
+/** Poll for guest notifications */
+#define GUEST_PROP_FN_GET_NOTIFICATION 6
+/** @} */
+
+
+/**
+ * Data structure to pass to the service extension callback.
+ * We use this to notify the host of changes to properties.
+ */
+typedef struct GUESTPROPHOSTCALLBACKDATA
+{
+ /** Magic number to identify the structure (GUESTPROPHOSTCALLBACKDATA_MAGIC). */
+ uint32_t u32Magic;
+ /** The name of the property that was changed */
+ const char *pcszName;
+ /** The new property value, or NULL if the property was deleted */
+ const char *pcszValue;
+ /** The timestamp of the modification */
+ uint64_t u64Timestamp;
+ /** The flags field of the modified property */
+ const char *pcszFlags;
+} GUESTPROPHOSTCALLBACKDATA;
+/** Poitner to a data structure to pass to the service extension callback. */
+typedef GUESTPROPHOSTCALLBACKDATA *PGUESTPROPHOSTCALLBACKDATA;
+
+/** Magic number for sanity checking the HOSTCALLBACKDATA structure */
+#define GUESTPROPHOSTCALLBACKDATA_MAGIC UINT32_C(0x69c87a78)
+
+/**
+ * HGCM parameter structures. Packing is explicitly defined as this is a wire format.
+ */
+/** The guest is requesting the value of a property */
+typedef struct GuestPropMsgGetProperty
+{
+ VBGLIOCHGCMCALL hdr;
+
+ /**
+ * The property name (IN pointer)
+ * This must fit to a number of criteria, namely
+ * - Only Utf8 strings are allowed
+ * - Less than or equal to MAX_NAME_LEN bytes in length
+ * - Zero terminated
+ */
+ HGCMFunctionParameter name;
+
+ /**
+ * The returned string data will be placed here. (OUT pointer)
+ * This call returns two null-terminated strings which will be placed one
+ * after another: value and flags.
+ */
+ HGCMFunctionParameter buffer;
+
+ /**
+ * The property timestamp. (OUT uint64_t)
+ */
+ HGCMFunctionParameter timestamp;
+
+ /**
+ * If the buffer provided was large enough this will contain the size of
+ * the returned data. Otherwise it will contain the size of the buffer
+ * needed to hold the data and VERR_BUFFER_OVERFLOW will be returned.
+ * (OUT uint32_t)
+ */
+ HGCMFunctionParameter size;
+} GuestPropMsgGetProperty;
+AssertCompileSize(GuestPropMsgGetProperty, 40 + 4 * (ARCH_BITS == 64 ? 16 : 12));
+
+/** The guest is requesting to change a property */
+typedef struct GuestPropMsgSetProperty
+{
+ VBGLIOCHGCMCALL hdr;
+
+ /**
+ * The property name. (IN pointer)
+ * This must fit to a number of criteria, namely
+ * - Only Utf8 strings are allowed
+ * - Less than or equal to MAX_NAME_LEN bytes in length
+ * - Zero terminated
+ */
+ HGCMFunctionParameter name;
+
+ /**
+ * The value of the property (IN pointer)
+ * Criteria as for the name parameter, but with length less than or equal to
+ * MAX_VALUE_LEN.
+ */
+ HGCMFunctionParameter value;
+
+ /**
+ * The property flags (IN pointer)
+ * This is a comma-separated list of the format flag=value
+ * The length must be less than or equal to GUEST_PROP_MAX_FLAGS_LEN and only
+ * known flag names and values will be accepted.
+ */
+ HGCMFunctionParameter flags;
+} GuestPropMsgSetProperty;
+AssertCompileSize(GuestPropMsgSetProperty, 40 + 3 * (ARCH_BITS == 64 ? 16 : 12));
+
+/** The guest is requesting to change the value of a property */
+typedef struct GuestPropMsgSetPropertyValue
+{
+ VBGLIOCHGCMCALL hdr;
+
+ /**
+ * The property name. (IN pointer)
+ * This must fit to a number of criteria, namely
+ * - Only Utf8 strings are allowed
+ * - Less than or equal to MAX_NAME_LEN bytes in length
+ * - Zero terminated
+ */
+ HGCMFunctionParameter name;
+
+ /**
+ * The value of the property (IN pointer)
+ * Criteria as for the name parameter, but with length less than or equal to
+ * MAX_VALUE_LEN.
+ */
+ HGCMFunctionParameter value;
+} GuestPropMsgSetPropertyValue;
+AssertCompileSize(GuestPropMsgSetPropertyValue, 40 + 2 * (ARCH_BITS == 64 ? 16 : 12));
+
+/** The guest is requesting to remove a property */
+typedef struct GuestPropMsgDelProperty
+{
+ VBGLIOCHGCMCALL hdr;
+
+ /**
+ * The property name. This must fit to a number of criteria, namely
+ * - Only Utf8 strings are allowed
+ * - Less than or equal to MAX_NAME_LEN bytes in length
+ * - Zero terminated
+ */
+ HGCMFunctionParameter name;
+} GuestPropMsgDelProperty;
+AssertCompileSize(GuestPropMsgDelProperty, 40 + 1 * (ARCH_BITS == 64 ? 16 : 12));
+
+/** The guest is requesting to enumerate properties */
+typedef struct GuestPropMsgEnumProperties
+{
+ VBGLIOCHGCMCALL hdr;
+
+ /**
+ * Array of patterns to match the properties against, separated by '|'
+ * characters. For backwards compatibility, '\\0' is also accepted
+ * as a separater.
+ * (IN pointer)
+ * If only a single, empty pattern is given then match all.
+ */
+ HGCMFunctionParameter patterns;
+ /**
+ * On success, null-separated array of strings in which the properties are
+ * returned. (OUT pointer)
+ * The number of strings in the array is always a multiple of four,
+ * and in sequences of name, value, timestamp (hexadecimal string) and the
+ * flags as a comma-separated list in the format "name=value". The list
+ * is terminated by an empty string after a "flags" entry (or at the
+ * start).
+ */
+ HGCMFunctionParameter strings;
+ /**
+ * On success, the size of the returned data. If the buffer provided is
+ * too small, the size of buffer needed. (OUT uint32_t)
+ */
+ HGCMFunctionParameter size;
+} GuestPropMsgEnumProperties;
+AssertCompileSize(GuestPropMsgEnumProperties, 40 + 3 * (ARCH_BITS == 64 ? 16 : 12));
+
+/**
+ * The guest is polling for notifications on changes to properties, specifying
+ * a set of patterns to match the names of changed properties against and
+ * optionally the timestamp of the last notification seen.
+ * On success, VINF_SUCCESS will be returned and the buffer will contain
+ * details of a property notification. If no new notification is available
+ * which matches one of the specified patterns, the call will block until one
+ * is.
+ * If the last notification could not be found by timestamp, VWRN_NOT_FOUND
+ * will be returned and the oldest available notification will be returned.
+ * If a zero timestamp is specified, the call will always wait for a new
+ * notification to arrive.
+ * If the buffer supplied was not large enough to hold the notification,
+ * VERR_BUFFER_OVERFLOW will be returned and the size parameter will contain
+ * the size of the buffer needed.
+ *
+ * The protocol for a guest to obtain notifications is to call
+ * GET_NOTIFICATION in a loop. On the first call, the ingoing timestamp
+ * parameter should be set to zero. On subsequent calls, it should be set to
+ * the outgoing timestamp from the previous call.
+ */
+typedef struct GuestPropMsgGetNotification
+{
+ VBGLIOCHGCMCALL hdr;
+
+ /**
+ * A list of patterns to match the guest event name against, separated by
+ * vertical bars (|) (IN pointer)
+ * An empty string means match all.
+ */
+ HGCMFunctionParameter patterns;
+ /**
+ * The timestamp of the last change seen (IN uint64_t)
+ * This may be zero, in which case the oldest available change will be
+ * sent. If the service does not remember an event matching the
+ * timestamp, then VWRN_NOT_FOUND will be returned, and the guest should
+ * assume that it has missed a certain number of notifications.
+ *
+ * The timestamp of the change being notified of (OUT uint64_t)
+ * Undefined on failure.
+ */
+ HGCMFunctionParameter timestamp;
+
+ /**
+ * The returned data, if any, will be placed here. (OUT pointer)
+ * This call returns three null-terminated strings which will be placed
+ * one after another: name, value and flags. For a delete notification,
+ * value and flags will be empty strings. Undefined on failure.
+ */
+ HGCMFunctionParameter buffer;
+
+ /**
+ * On success, the size of the returned data. (OUT uint32_t)
+ * On buffer overflow, the size of the buffer needed to hold the data.
+ * Undefined on failure.
+ */
+ HGCMFunctionParameter size;
+} GuestPropMsgGetNotification;
+AssertCompileSize(GuestPropMsgGetNotification, 40 + 4 * (ARCH_BITS == 64 ? 16 : 12));
+
+
+#endif /* !VBOX_INCLUDED_HostServices_GuestPropertySvc_h */
+
diff --git a/include/VBox/HostServices/Makefile.kup b/include/VBox/HostServices/Makefile.kup
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/include/VBox/HostServices/Makefile.kup
diff --git a/include/VBox/HostServices/Service.h b/include/VBox/HostServices/Service.h
new file mode 100644
index 00000000..d45512cb
--- /dev/null
+++ b/include/VBox/HostServices/Service.h
@@ -0,0 +1,358 @@
+/** @file
+ * Base class for an host-guest service.
+ */
+
+/*
+ * Copyright (C) 2011-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_HostServices_Service_h
+#define VBOX_INCLUDED_HostServices_Service_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/log.h>
+#include <VBox/hgcmsvc.h>
+
+#include <iprt/assert.h>
+#include <iprt/alloc.h>
+#include <iprt/cpp/utils.h>
+
+#include <new>
+
+
+namespace HGCM
+{
+
+/**
+ * Structure for keeping a HGCM service context.
+ */
+typedef struct VBOXHGCMSVCTX
+{
+ /** HGCM helper functions. */
+ PVBOXHGCMSVCHELPERS pHelpers;
+ /**
+ * Callback function supplied by the host for notification of updates
+ * to properties.
+ */
+ PFNHGCMSVCEXT pfnHostCallback;
+ /** User data pointer to be supplied to the host callback function. */
+ void *pvHostData;
+} VBOXHGCMSVCTX, *PVBOXHGCMSVCTX;
+
+/**
+ * Base class encapsulating and working with a HGCM message.
+ */
+class Message
+{
+public:
+ Message(void);
+ Message(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM aParms[]);
+ virtual ~Message(void);
+
+ uint32_t GetParamCount(void) const RT_NOEXCEPT;
+ int GetData(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM aParms[]) const RT_NOEXCEPT;
+ int GetParmU32(uint32_t uParm, uint32_t *pu32Info) const RT_NOEXCEPT;
+ int GetParmU64(uint32_t uParm, uint64_t *pu64Info) const RT_NOEXCEPT;
+ int GetParmPtr(uint32_t uParm, void **ppvAddr, uint32_t *pcbSize) const RT_NOEXCEPT;
+ uint32_t GetType(void) const RT_NOEXCEPT;
+
+public:
+ static int CopyParms(PVBOXHGCMSVCPARM paParmsDst, uint32_t cParmsDst,
+ PVBOXHGCMSVCPARM paParmsSrc, uint32_t cParmsSrc,
+ bool fDeepCopy) RT_NOEXCEPT;
+
+protected:
+ int initData(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM aParms[]) RT_NOEXCEPT;
+ void reset() RT_NOEXCEPT;
+
+protected:
+
+ /** Stored message type. */
+ uint32_t m_uMsg;
+ /** Number of stored HGCM parameters. */
+ uint32_t m_cParms;
+ /** Stored HGCM parameters. */
+ PVBOXHGCMSVCPARM m_paParms;
+};
+
+/**
+ * Class for keeping and tracking a HGCM client.
+ */
+class Client
+{
+public:
+ Client(uint32_t idClient);
+ virtual ~Client(void);
+
+public:
+ int Complete(VBOXHGCMCALLHANDLE hHandle, int rcOp = VINF_SUCCESS) RT_NOEXCEPT;
+ int CompleteDeferred(int rcOp = VINF_SUCCESS) RT_NOEXCEPT;
+ uint32_t GetClientID(void) const RT_NOEXCEPT;
+ VBOXHGCMCALLHANDLE GetHandle(void) const RT_NOEXCEPT;
+ uint32_t GetMsgType(void) const RT_NOEXCEPT;
+ uint32_t GetMsgParamCount(void) const RT_NOEXCEPT;
+ bool IsDeferred(void) const RT_NOEXCEPT;
+ void SetDeferred(VBOXHGCMCALLHANDLE hHandle, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[]) RT_NOEXCEPT;
+ void SetSvcContext(const VBOXHGCMSVCTX &SvcCtx) RT_NOEXCEPT;
+
+public:
+ int SetDeferredMsgInfo(uint32_t uMsg, uint32_t cParms) RT_NOEXCEPT;
+ int SetDeferredMsgInfo(const Message *pMessage) RT_NOEXCEPT;
+
+protected:
+ int completeInternal(VBOXHGCMCALLHANDLE hHandle, int rcOp) RT_NOEXCEPT;
+ void reset(void) RT_NOEXCEPT;
+
+protected:
+ /** The client's HGCM client ID. */
+ uint32_t m_idClient;
+ /** The HGCM service context this client is bound to. */
+ VBOXHGCMSVCTX m_SvcCtx;
+ /** Flag indicating whether this client currently is deferred mode,
+ * meaning that it did not return to the caller yet. */
+ bool m_fDeferred;
+ /** Structure for keeping the client's deferred state.
+ * A client is in a deferred state when it asks for the next HGCM message,
+ * but the service can't provide it yet. That way a client will block (on the guest side, does not return)
+ * until the service can complete the call. */
+ struct
+ {
+ /** The client's HGCM call handle. Needed for completing a deferred call. */
+ VBOXHGCMCALLHANDLE hHandle;
+ /** Message type (function number) to use when completing the deferred call.
+ * @todo r=bird: uType or uMsg? Make up your mind (Message::m_uMsg). */
+ uint32_t uType;
+ /** Parameter count to use when completing the deferred call. */
+ uint32_t cParms;
+ /** Parameters to use when completing the deferred call. */
+ PVBOXHGCMSVCPARM paParms;
+ } m_Deferred;
+};
+
+template <class T>
+class AbstractService : public RTCNonCopyable
+{
+public:
+ /**
+ * @copydoc FNVBOXHGCMSVCLOAD
+ */
+ static DECLCALLBACK(int) svcLoad(VBOXHGCMSVCFNTABLE *pTable)
+ {
+ LogFlowFunc(("ptable = %p\n", pTable));
+ int rc = VINF_SUCCESS;
+
+ if (!RT_VALID_PTR(pTable))
+ rc = VERR_INVALID_PARAMETER;
+ else
+ {
+ LogFlowFunc(("ptable->cbSize = %d, ptable->u32Version = 0x%08X\n", pTable->cbSize, pTable->u32Version));
+
+ if ( pTable->cbSize != sizeof (VBOXHGCMSVCFNTABLE)
+ || pTable->u32Version != VBOX_HGCM_SVC_VERSION)
+ rc = VERR_VERSION_MISMATCH;
+ else
+ {
+ AbstractService *pService = NULL;
+ /* No exceptions may propagate outside (callbacks like this one are nothrow/noexcept). */
+ try { pService = new T(pTable->pHelpers); }
+ catch (std::bad_alloc &) { rc = VERR_NO_MEMORY; }
+ catch (...) { rc = VERR_UNEXPECTED_EXCEPTION; }
+ if (RT_SUCCESS(rc))
+ {
+ /* We don't need an additional client data area on the host,
+ because we're a class which can have members for that :-). */
+ /** @todo r=bird: What the comment above says is that we can duplicate the
+ * work of associating data with a client ID already done by the HGCM and create
+ * additional bugs because we think that's cool. It's not. Utterly
+ * appalling as well as inefficient. Just a structure with a pointer to a
+ * client base class would go a long way here. */
+ pTable->cbClient = 0;
+
+ /* These functions are mandatory */
+ pTable->pfnUnload = svcUnload;
+ pTable->pfnConnect = svcConnect;
+ pTable->pfnDisconnect = svcDisconnect;
+ pTable->pfnCall = svcCall;
+ /* Clear obligatory functions. */
+ pTable->pfnHostCall = NULL;
+ pTable->pfnSaveState = NULL;
+ pTable->pfnLoadState = NULL;
+ pTable->pfnRegisterExtension = NULL;
+
+ /* Let the service itself initialize. */
+ rc = pService->init(pTable);
+ if (RT_SUCCESS(rc))
+ pTable->pvService = pService;
+ else
+ delete pService;
+ }
+ }
+ }
+
+ LogFlowFunc(("returning %Rrc\n", rc));
+ return rc;
+ }
+ virtual ~AbstractService() {};
+
+protected:
+ explicit AbstractService(PVBOXHGCMSVCHELPERS pHelpers)
+ {
+ RT_ZERO(m_SvcCtx);
+ m_SvcCtx.pHelpers = pHelpers;
+ }
+ virtual int init(VBOXHGCMSVCFNTABLE *ptable) RT_NOEXCEPT
+ { RT_NOREF1(ptable); return VINF_SUCCESS; }
+ virtual int uninit() RT_NOEXCEPT
+ { return VINF_SUCCESS; }
+ virtual int clientConnect(uint32_t idClient, void *pvClient) RT_NOEXCEPT = 0;
+ virtual int clientDisconnect(uint32_t idClient, void *pvClient) RT_NOEXCEPT = 0;
+ virtual void guestCall(VBOXHGCMCALLHANDLE callHandle, uint32_t idClient, void *pvClient, uint32_t eFunction,
+ uint32_t cParms, VBOXHGCMSVCPARM paParms[]) RT_NOEXCEPT = 0;
+ virtual int hostCall(uint32_t eFunction, uint32_t cParms, VBOXHGCMSVCPARM paParms[]) RT_NOEXCEPT
+ { RT_NOREF3(eFunction, cParms, paParms); return VINF_SUCCESS; }
+
+ /** Type definition for use in callback functions. */
+ typedef AbstractService SELF;
+ /** The HGCM service context this service is bound to. */
+ VBOXHGCMSVCTX m_SvcCtx;
+
+ /**
+ * @copydoc VBOXHGCMSVCFNTABLE::pfnUnload
+ * Simply deletes the service object
+ */
+ static DECLCALLBACK(int) svcUnload(void *pvService)
+ {
+ AssertLogRelReturn(RT_VALID_PTR(pvService), VERR_INVALID_PARAMETER);
+ SELF *pSelf = reinterpret_cast<SELF *>(pvService);
+ int rc = pSelf->uninit();
+ AssertRC(rc);
+ if (RT_SUCCESS(rc))
+ delete pSelf;
+ return rc;
+ }
+
+ /**
+ * @copydoc VBOXHGCMSVCFNTABLE::pfnConnect
+ * Stub implementation of pfnConnect and pfnDisconnect.
+ */
+ static DECLCALLBACK(int) svcConnect(void *pvService,
+ uint32_t idClient,
+ void *pvClient,
+ uint32_t fRequestor,
+ bool fRestoring)
+ {
+ RT_NOREF(fRequestor, fRestoring);
+ AssertLogRelReturn(RT_VALID_PTR(pvService), VERR_INVALID_PARAMETER);
+ LogFlowFunc(("pvService=%p, idClient=%u, pvClient=%p\n", pvService, idClient, pvClient));
+ SELF *pSelf = reinterpret_cast<SELF *>(pvService);
+ int rc = pSelf->clientConnect(idClient, pvClient);
+ LogFlowFunc(("rc=%Rrc\n", rc));
+ return rc;
+ }
+
+ /**
+ * @copydoc VBOXHGCMSVCFNTABLE::pfnConnect
+ * Stub implementation of pfnConnect and pfnDisconnect.
+ */
+ static DECLCALLBACK(int) svcDisconnect(void *pvService,
+ uint32_t idClient,
+ void *pvClient)
+ {
+ AssertLogRelReturn(RT_VALID_PTR(pvService), VERR_INVALID_PARAMETER);
+ LogFlowFunc(("pvService=%p, idClient=%u, pvClient=%p\n", pvService, idClient, pvClient));
+ SELF *pSelf = reinterpret_cast<SELF *>(pvService);
+ int rc = pSelf->clientDisconnect(idClient, pvClient);
+ LogFlowFunc(("rc=%Rrc\n", rc));
+ return rc;
+ }
+
+ /**
+ * @copydoc VBOXHGCMSVCFNTABLE::pfnCall
+ * Wraps to the call member function
+ */
+ static DECLCALLBACK(void) svcCall(void *pvService,
+ VBOXHGCMCALLHANDLE callHandle,
+ uint32_t idClient,
+ void *pvClient,
+ uint32_t u32Function,
+ uint32_t cParms,
+ VBOXHGCMSVCPARM paParms[],
+ uint64_t tsArrival)
+ {
+ AssertLogRelReturnVoid(RT_VALID_PTR(pvService));
+ LogFlowFunc(("pvService=%p, callHandle=%p, idClient=%u, pvClient=%p, u32Function=%u, cParms=%u, paParms=%p\n",
+ pvService, callHandle, idClient, pvClient, u32Function, cParms, paParms));
+ SELF *pSelf = reinterpret_cast<SELF *>(pvService);
+ pSelf->guestCall(callHandle, idClient, pvClient, u32Function, cParms, paParms);
+ LogFlowFunc(("returning\n"));
+ RT_NOREF_PV(tsArrival);
+ }
+
+ /**
+ * @copydoc VBOXHGCMSVCFNTABLE::pfnHostCall
+ * Wraps to the hostCall member function
+ */
+ static DECLCALLBACK(int) svcHostCall(void *pvService,
+ uint32_t u32Function,
+ uint32_t cParms,
+ VBOXHGCMSVCPARM paParms[])
+ {
+ AssertLogRelReturn(RT_VALID_PTR(pvService), VERR_INVALID_PARAMETER);
+ LogFlowFunc(("pvService=%p, u32Function=%u, cParms=%u, paParms=%p\n", pvService, u32Function, cParms, paParms));
+ SELF *pSelf = reinterpret_cast<SELF *>(pvService);
+ int rc = pSelf->hostCall(u32Function, cParms, paParms);
+ LogFlowFunc(("rc=%Rrc\n", rc));
+ return rc;
+ }
+
+ /**
+ * @copydoc VBOXHGCMSVCFNTABLE::pfnRegisterExtension
+ * Installs a host callback for notifications of property changes.
+ */
+ static DECLCALLBACK(int) svcRegisterExtension(void *pvService,
+ PFNHGCMSVCEXT pfnExtension,
+ void *pvExtension)
+ {
+ AssertLogRelReturn(RT_VALID_PTR(pvService), VERR_INVALID_PARAMETER);
+ LogFlowFunc(("pvService=%p, pfnExtension=%p, pvExtention=%p\n", pvService, pfnExtension, pvExtension));
+ SELF *pSelf = reinterpret_cast<SELF *>(pvService);
+ pSelf->m_SvcCtx.pfnHostCallback = pfnExtension;
+ pSelf->m_SvcCtx.pvHostData = pvExtension;
+ return VINF_SUCCESS;
+ }
+
+ DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP(AbstractService);
+};
+
+}
+#endif /* !VBOX_INCLUDED_HostServices_Service_h */
+
diff --git a/include/VBox/HostServices/VBoxClipboardExt.h b/include/VBox/HostServices/VBoxClipboardExt.h
new file mode 100644
index 00000000..d93acf23
--- /dev/null
+++ b/include/VBox/HostServices/VBoxClipboardExt.h
@@ -0,0 +1,66 @@
+/** @file
+ * Shared Clipboard - Common header for the service extension.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_HostServices_VBoxClipboardExt_h
+#define VBOX_INCLUDED_HostServices_VBoxClipboardExt_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/types.h>
+#ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
+# include <VBox/GuestHost/SharedClipboard-transfers.h>
+#endif
+
+#define VBOX_CLIPBOARD_EXT_FN_SET_CALLBACK (0)
+#define VBOX_CLIPBOARD_EXT_FN_FORMAT_ANNOUNCE (1)
+#define VBOX_CLIPBOARD_EXT_FN_DATA_READ (2)
+#define VBOX_CLIPBOARD_EXT_FN_DATA_WRITE (3)
+
+typedef DECLCALLBACKTYPE(int, FNVRDPCLIPBOARDEXTCALLBACK,(uint32_t u32Function, uint32_t u32Format, void *pvData, uint32_t cbData));
+typedef FNVRDPCLIPBOARDEXTCALLBACK *PFNVRDPCLIPBOARDEXTCALLBACK;
+
+typedef struct _SHCLEXTPARMS
+{
+ uint32_t uFormat;
+ union
+ {
+ void *pvData;
+ PFNVRDPCLIPBOARDEXTCALLBACK pfnCallback;
+ } u;
+ uint32_t cbData;
+} SHCLEXTPARMS;
+
+#endif /* !VBOX_INCLUDED_HostServices_VBoxClipboardExt_h */
diff --git a/include/VBox/HostServices/VBoxClipboardSvc.h b/include/VBox/HostServices/VBoxClipboardSvc.h
new file mode 100644
index 00000000..45bb954a
--- /dev/null
+++ b/include/VBox/HostServices/VBoxClipboardSvc.h
@@ -0,0 +1,1220 @@
+/** @file
+ * Shared Clipboard - Common header for host service and guest clients.
+ *
+ * Protocol history notes (incomplete):
+ *
+ * - VirtualBox 6.1.0 betas: Started work on adding support for copying &
+ * pasting files and directories, refactoring the protocol in the process.
+ * - Adds guest/host feature flags.
+ * - Adds context IDs (via guest feature flags).
+ * - Borrowed the message handling from guest controls.
+ * - Adds a multitude of functions and messages for dealing with file & dir
+ * copying, most inte
+ *
+ * - VirtualBox x.x.x: Missing a lot of gradual improvements here.
+ *
+ * - VirtualBox 1.3.2 (r17182): Initial implementation, supporting text.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_HostServices_VBoxClipboardSvc_h
+#define VBOX_INCLUDED_HostServices_VBoxClipboardSvc_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/VMMDevCoreTypes.h>
+#include <VBox/VBoxGuestCoreTypes.h>
+#include <VBox/hgcmsvc.h>
+
+
+/** @name VBOX_SHCL_MODE_XXX - The Shared Clipboard modes of operation.
+ * @{
+ */
+/** Shared Clipboard is disabled completely. */
+#define VBOX_SHCL_MODE_OFF 0
+/** Only transfers from host to the guest are possible. */
+#define VBOX_SHCL_MODE_HOST_TO_GUEST 1
+/** Only transfers from guest to the host are possible. */
+#define VBOX_SHCL_MODE_GUEST_TO_HOST 2
+/** Bidirectional transfers between guest and host are possible. */
+#define VBOX_SHCL_MODE_BIDIRECTIONAL 3
+/** @} */
+
+/** @name VBOX_SHCL_TRANSFER_MODE_XXX - The Shared Clipboard file transfer mode (bit field).
+ * @{
+ */
+/** Shared Clipboard file transfers are disabled. */
+#define VBOX_SHCL_TRANSFER_MODE_DISABLED UINT32_C(0)
+/** Shared Clipboard file transfers are enabled. */
+#define VBOX_SHCL_TRANSFER_MODE_ENABLED RT_BIT(0)
+/** Shared Clipboard file transfer mode valid mask. */
+#define VBOX_SHCL_TRANSFER_MODE_VALID_MASK UINT32_C(0x1)
+/** @} */
+
+
+/** @name VBOX_SHCL_HOST_FN_XXX - The service functions which are callable by host.
+ * @note These are not sacred and can be modified at will as long as all host
+ * clients are updated accordingly (probably just Main).
+ * @{
+ */
+/** Sets the current Shared Clipboard operation mode. */
+#define VBOX_SHCL_HOST_FN_SET_MODE 1
+/** Sets the current Shared Clipboard (file) transfers mode.
+ * Operates on the VBOX_SHCL_TRANSFERS_XXX defines.
+ * @since 6.1 */
+#define VBOX_SHCL_HOST_FN_SET_TRANSFER_MODE 2
+/** Run headless on the host, i.e. do not touch the host clipboard. */
+#define VBOX_SHCL_HOST_FN_SET_HEADLESS 3
+
+/** Reports cancellation of the current operation to the guest.
+ * @since 6.1 - still a todo */
+#define VBOX_SHCL_HOST_FN_CANCEL 4
+/** Reports an error to the guest.
+ * @since 6.1 - still a todo */
+#define VBOX_SHCL_HOST_FN_ERROR 5
+/** @} */
+
+
+/** @name VBOX_SHCL_HOST_MSG_XXX - The host messages for the guest.
+ * @{
+ */
+/** Returned only when the HGCM client session is closed (by different thread).
+ *
+ * This can require no futher host interaction since the session has been
+ * closed.
+ *
+ * @since 1.3.2
+ */
+#define VBOX_SHCL_HOST_MSG_QUIT 1
+/** Request data for a specific format from the guest.
+ *
+ * Two parameters, first the 32-bit message ID followed by a 32-bit format bit
+ * (VBOX_SHCL_FMT_XXX). The guest will respond by issuing a
+ * VBOX_SHCL_GUEST_FN_DATA_WRITE.
+ *
+ * @note The host may sometimes incorrectly set more than one format bit, in
+ * which case it's up to the guest to pick which to write back.
+ * @since 1.3.2
+ */
+#define VBOX_SHCL_HOST_MSG_READ_DATA 2
+/** Reports available clipboard format on the host to the guest.
+ *
+ * Two parameters, first the 32-bit message ID followed by a 32-bit format mask
+ * containing zero or more VBOX_SHCL_FMT_XXX flags. The guest is not require to
+ * respond to the host when receiving this message.
+ *
+ * @since 1.3.2
+ */
+#define VBOX_SHCL_HOST_MSG_FORMATS_REPORT 3
+/** Message PEEK or GET operation was canceled, try again.
+ *
+ * This is returned by VBOX_SHCL_GUEST_FN_MSG_PEEK_WAIT and
+ * VBOX_SHCL_GUEST_FN_MSG_OLD_GET_WAIT in response to the guest calling
+ * VBOX_SHCL_GUEST_FN_MSG_CANCEL. The 2nd parameter is set to zero (be it
+ * thought of as a parameter count or a format mask).
+ *
+ * @since 6.1.0
+ */
+#define VBOX_SHCL_HOST_MSG_CANCELED 4
+
+/** Request data for a specific format from the guest with context ID.
+ *
+ * This is send instead of the VBOX_SHCL_HOST_MSG_READ_DATA message to guest
+ * that advertises VBOX_SHCL_GF_0_CONTEXT_ID. The first parameter is a 64-bit
+ * context ID which is to be used when issuing VBOX_SHCL_GUEST_F_DATA_WRITE, and
+ * the second parameter is a 32-bit format bit (VBOX_SHCL_FMT_XXX). The guest
+ * will respond by issuing a VBOX_SHCL_GUEST_F_DATA_WRITE.
+ *
+ * @note The host may sometimes incorrectly set more than one format bit, in
+ * which case it's up to the guest to pick which to write back.
+ * @since 6.1.2
+ */
+#define VBOX_SHCL_HOST_MSG_READ_DATA_CID 5
+
+/** Sends a transfer status to the guest side.
+ * @since 6.1.?
+ */
+#define VBOX_SHCL_HOST_MSG_TRANSFER_STATUS 50
+/** Reads the root list header from the guest.
+ * @since 6.1.?
+ */
+#define VBOX_SHCL_HOST_MSG_TRANSFER_ROOT_LIST_HDR_READ 51
+/** Writes the root list header to the guest.
+ * @since 6.1.?
+ */
+#define VBOX_SHCL_HOST_MSG_TRANSFER_ROOT_LIST_HDR_WRITE 52
+/** Reads a root list entry from the guest.
+ * @since 6.1.?
+ */
+#define VBOX_SHCL_HOST_MSG_TRANSFER_ROOT_LIST_ENTRY_READ 53
+/** Writes a root list entry to the guest.
+ * @since 6.1.?
+ */
+#define VBOX_SHCL_HOST_MSG_TRANSFER_ROOT_LIST_ENTRY_WRITE 54
+/** Open a transfer list on the guest side.
+ * @since 6.1.?
+ */
+#define VBOX_SHCL_HOST_MSG_TRANSFER_LIST_OPEN 55
+/** Closes a formerly opened transfer list on the guest side.
+ * @since 6.1.?
+ */
+#define VBOX_SHCL_HOST_MSG_TRANSFER_LIST_CLOSE 56
+/** Reads a list header from the guest.
+ * @since 6.1.?
+ */
+#define VBOX_SHCL_HOST_MSG_TRANSFER_LIST_HDR_READ 57
+/** Writes a list header to the guest.
+ * @since 6.1.?
+ */
+#define VBOX_SHCL_HOST_MSG_TRANSFER_LIST_HDR_WRITE 58
+/** Reads a list entry from the guest.
+ * @since 6.1.?
+ */
+#define VBOX_SHCL_HOST_MSG_TRANSFER_LIST_ENTRY_READ 59
+/** Writes a list entry to the guest.
+ * @since 6.1.?
+ */
+#define VBOX_SHCL_HOST_MSG_TRANSFER_LIST_ENTRY_WRITE 60
+/** Open a transfer object on the guest side.
+ * @since 6.1.?
+ */
+#define VBOX_SHCL_HOST_MSG_TRANSFER_OBJ_OPEN 61
+/** Closes a formerly opened transfer object on the guest side.
+ * @since 6.1.?
+ */
+#define VBOX_SHCL_HOST_MSG_TRANSFER_OBJ_CLOSE 62
+/** Reads from an object on the guest side.
+ * @since 6.1.?
+ */
+#define VBOX_SHCL_HOST_MSG_TRANSFER_OBJ_READ 63
+/** Writes to an object on the guest side.
+ * @since 6.1.?
+ */
+#define VBOX_SHCL_HOST_MSG_TRANSFER_OBJ_WRITE 64
+/** Indicates that the host has canceled a transfer.
+ * @since 6.1.?
+ */
+#define VBOX_SHCL_HOST_MSG_TRANSFER_CANCEL 65
+/** Indicates that the an unrecoverable error on the host occurred.
+ * @since 6.1.?
+ */
+#define VBOX_SHCL_HOST_MSG_TRANSFER_ERROR 66
+/** @} */
+
+
+/** @name VBOX_SHCL_GUEST_FN_XXX - The service functions which are called by guest.
+ * @{
+ */
+/** Calls the host and waits (blocking) for an host event VBOX_SHCL_HOST_MSG_XXX.
+ *
+ * @deprecated Replaced by VBOX_SHCL_GUEST_FN_MSG_PEEK_WAIT,
+ * VBOX_SHCL_GUEST_FN_MSG_GET, VBOX_SHCL_GUEST_FN_MSG_CANCEL.
+ * @since 1.3.2
+ */
+#define VBOX_SHCL_GUEST_FN_MSG_OLD_GET_WAIT 1
+/** Sends a list of available formats to the host.
+ *
+ * This function takes a single parameter, a 32-bit set of formats
+ * (VBOX_SHCL_FMT_XXX), this can be zero if the clipboard is empty or previously
+ * reported formats are no longer avaible (logout, shutdown, whatever).
+ *
+ * There was a period during 6.1 development where it would take three
+ * parameters, a 64-bit context ID preceeded the formats and a 32-bit MBZ flags
+ * parameter was appended. This is still accepted, though deprecated.
+ *
+ * @returns May return informational statuses indicating partial success, just
+ * ignore it.
+ * @retval VINF_SUCCESS on success.
+ * @retval VERR_INVALID_CLIENT_ID
+ * @retval VERR_WRONG_PARAMETER_COUNT
+ * @retval VERR_WRONG_PARAMETER_TYPE
+ * @retval VERR_NOT_SUPPORTED if all the formats are unsupported, host
+ * clipboard will be empty.
+ * @since 1.3.2
+ */
+#define VBOX_SHCL_GUEST_FN_REPORT_FORMATS 2
+/** Reads data in specified format from the host.
+ *
+ * This function takes three parameters, a 32-bit format bit
+ * (VBOX_SHCL_FMT_XXX), a buffer and 32-bit number of bytes read (output).
+ *
+ * There was a period during 6.1 development where it would take five parameters
+ * when VBOX_SHCL_GF_0_CONTEXT_ID was reported by the guest. A 64-bit context
+ * ID (ignored as purpose undefined), a 32-bit unused flag (MBZ), then the
+ * 32-bit format bits, number of bytes read (output), and the buffer. This
+ * format is still accepted.
+ *
+ * @retval VINF_SUCCESS on success.
+ * @retval VINF_BUFFER_OVERLFLOW (VBox >= 6.1 only) if not enough buffer space
+ * has been given to retrieve the actual data, no data actually copied.
+ * The call then must be repeated with a buffer size returned from the
+ * host in cbData.
+ * @retval VERR_INVALID_CLIENT_ID
+ * @retval VERR_WRONG_PARAMETER_COUNT
+ * @retval VERR_WRONG_PARAMETER_TYPE
+ * @since 1.3.2
+ */
+#define VBOX_SHCL_GUEST_FN_DATA_READ 3
+/** Writes requested data to the host.
+ *
+ * This function takes either 2 or 3 parameters. The last two parameters are a
+ * 32-bit format bit (VBOX_SHCL_FMT_XXX) and a data buffer holding the related
+ * data. The three parameter variant have a context ID first, which shall be a
+ * copy of the ID in the data request message.
+ *
+ * There was a period during 6.1 development where there would be a 5 parameter
+ * version of this, inserting an unused flags parameter between the context ID
+ * and the format bit, as well as a 32-bit data buffer size repate between the
+ * format bit and the data buffer. This format is still accepted, though
+ * deprecated.
+ *
+ * @retval VINF_SUCCESS on success.
+ * @retval VERR_INVALID_CLIENT_ID
+ * @retval VERR_WRONG_PARAMETER_COUNT
+ * @retval VERR_WRONG_PARAMETER_TYPE
+ * @retval VERR_INVALID_CONTEXT if the context ID didn't match up.
+ * @since 1.3.2
+ */
+#define VBOX_SHCL_GUEST_FN_DATA_WRITE 4
+
+/** This is a left-over from the 6.1 dev cycle and will always fail.
+ *
+ * It used to take three 32-bit parameters, only one of which was actually used.
+ *
+ * It was replaced by VBOX_SHCL_GUEST_FN_REPORT_FEATURES and
+ * VBOX_SHCL_GUEST_FN_NEGOTIATE_CHUNK_SIZE.
+ *
+ * @retval VERR_NOT_IMPLEMENTED
+ * @since 6.1
+ */
+#define VBOX_SHCL_GUEST_FN_CONNECT 5
+/** Report guest side feature flags and retrieve the host ones.
+ *
+ * Two 64-bit parameters are passed in from the guest with the guest features
+ * (VBOX_SHCL_GF_XXX), the host replies by replacing the parameter values with
+ * the host ones (VBOX_SHCL_HF_XXX).
+ *
+ * @retval VINF_SUCCESS on success.
+ * @retval VERR_INVALID_CLIENT_ID
+ * @retval VERR_WRONG_PARAMETER_COUNT
+ * @retval VERR_WRONG_PARAMETER_TYPE
+ * @since 6.1.0
+ */
+#define VBOX_SHCL_GUEST_FN_REPORT_FEATURES 6
+/** Query the host ones feature masks.
+ *
+ * That way the guest (client) can get hold of the features from the host.
+ * Again, it is prudent to set the 127 bit and observe it being cleared on
+ * success, as older hosts might return success without doing anything.
+ *
+ * @retval VINF_SUCCESS on success.
+ * @retval VERR_INVALID_CLIENT_ID
+ * @retval VERR_WRONG_PARAMETER_COUNT
+ * @retval VERR_WRONG_PARAMETER_TYPE
+ * @since 6.1.0
+ */
+#define VBOX_SHCL_GUEST_FN_QUERY_FEATURES 7
+/** Peeks at the next message, returning immediately.
+ *
+ * Returns two 32-bit parameters, first is the message ID and the second the
+ * parameter count. May optionally return additional 32-bit parameters with the
+ * sizes of respective message parameters. To distinguish buffer sizes from
+ * integer parameters, the latter gets their sizes inverted (uint32_t is ~4U,
+ * uint64_t is ~8U).
+ *
+ * Does also support the VM restore checking as in VBOX_SHCL_GUEST_FN_MSG_PEEK_WAIT
+ * (64-bit param \# 0), see documentation there.
+ *
+ * @retval VINF_SUCCESS if a message was pending and is being returned.
+ * @retval VERR_TRY_AGAIN if no message pending.
+ * @retval VERR_VM_RESTORED if first parameter is a non-zero 64-bit value that
+ * does not match VbglR3GetSessionId() any more. The new value is
+ * returned.
+ * @retval VERR_INVALID_CLIENT_ID
+ * @retval VERR_WRONG_PARAMETER_COUNT
+ * @retval VERR_WRONG_PARAMETER_TYPE
+ * @since 6.1.0
+ */
+#define VBOX_SHCL_GUEST_FN_MSG_PEEK_NOWAIT 8
+/** Peeks at the next message, waiting for one to arrive.
+ *
+ * Returns two 32-bit parameters, first is the message ID and the second the
+ * parameter count. May optionally return additional 32-bit parameters with the
+ * sizes of respective message parameters. To distinguish buffer sizes from
+ * integer parameters, the latter gets their sizes inverted (uint32_t is ~4U,
+ * uint64_t is ~8U).
+ *
+ * To facilitate VM restore checking, the first parameter can be a 64-bit
+ * integer holding the VbglR3GetSessionId() value the guest knowns. The
+ * function will then check this before going to sleep and return
+ * VERR_VM_RESTORED if it doesn't match, same thing happens when the VM is
+ * restored.
+ *
+ * @retval VINF_SUCCESS if info about an pending message is being returned.
+ * @retval VINF_TRY_AGAIN and message set to VBOX_SHCL_HOST_MSG_CANCELED if
+ * cancelled by VBOX_SHCL_GUEST_FN_MSG_CANCEL.
+ * @retval VERR_RESOURCE_BUSY if another thread already made a waiting call.
+ * @retval VERR_VM_RESTORED if first parameter is a non-zero 64-bit value that
+ * does not match VbglR3GetSessionId() any more. The new value is
+ * returned.
+ * @retval VERR_INVALID_CLIENT_ID
+ * @retval VERR_WRONG_PARAMETER_COUNT
+ * @retval VERR_WRONG_PARAMETER_TYPE
+ * @note This replaces VBOX_SHCL_GUEST_FN_MSG_OLD_GET_WAIT.
+ * @since 6.1.0
+ */
+#define VBOX_SHCL_GUEST_FN_MSG_PEEK_WAIT 9
+/** Gets the next message, returning immediately.
+ *
+ * All parameters are specific to the message being retrieved, however if the
+ * first one is an integer value it shall be an input parameter holding the
+ * ID of the message being retrieved. While it would be nice to add a separate
+ * parameter for this purpose, this is done so because the code was liften from
+ * Guest Controls which had backwards compatibilities to consider and we just
+ * kept it like that.
+ *
+ * @retval VINF_SUCCESS if message retrieved and removed from the pending queue.
+ * @retval VERR_TRY_AGAIN if no message pending.
+ * @retval VERR_MISMATCH if the incoming message ID does not match the pending.
+ * @retval VERR_BUFFER_OVERFLOW if a parmeter buffer is too small. The buffer
+ * size was updated to reflect the required size.
+ * @retval VERR_INVALID_CLIENT_ID
+ * @retval VERR_WRONG_PARAMETER_COUNT
+ * @retval VERR_WRONG_PARAMETER_TYPE
+ * @note This replaces VBOX_SHCL_GUEST_FN_MSG_OLD_GET_WAIT.
+ * @since 6.1.0
+ */
+#define VBOX_SHCL_GUEST_FN_MSG_GET 10
+/** Cancels pending calls for this client session.
+ *
+ * This should be used if a VBOX_SHCL_GUEST_FN__MSG_PEEK_WAIT or
+ * VBOX_SHCL_GUEST_FN_MSG_OLD_GET_WAIT call gets interrupted on the client end,
+ * so as to prevent being rebuffed with VERR_RESOURCE_BUSY when restarting the
+ * call.
+ *
+ * @retval VINF_SUCCESS if cancelled any calls.
+ * @retval VWRN_NOT_FOUND if no callers.
+ * @retval VERR_INVALID_CLIENT_ID
+ * @retval VERR_WRONG_PARAMETER_COUNT
+ * @since 6.1.0
+ */
+#define VBOX_SHCL_GUEST_FN_MSG_CANCEL 26
+
+/** Replies to a function from the host.
+ *
+ * @retval VINF_SUCCESS on success.
+ * @retval VERR_INVALID_CLIENT_ID
+ * @retval VERR_WRONG_PARAMETER_COUNT
+ * @retval VERR_WRONG_PARAMETER_TYPE
+ * @since 6.1.x
+ */
+#define VBOX_SHCL_GUEST_FN_REPLY 11
+/** Gets the root list header from the host.
+ *
+ * @retval VINF_SUCCESS on success.
+ * @retval VERR_INVALID_CLIENT_ID
+ * @retval VERR_WRONG_PARAMETER_COUNT
+ * @retval VERR_WRONG_PARAMETER_TYPE
+ * @since 6.1.x
+ */
+#define VBOX_SHCL_GUEST_FN_ROOT_LIST_HDR_READ 12
+/** Sends the root list header to the host.
+ *
+ * @retval VINF_SUCCESS on success.
+ * @retval VERR_INVALID_CLIENT_ID
+ * @retval VERR_WRONG_PARAMETER_COUNT
+ * @retval VERR_WRONG_PARAMETER_TYPE
+ * @since 6.1.x
+ */
+#define VBOX_SHCL_GUEST_FN_ROOT_LIST_HDR_WRITE 13
+/** Gets a root list root entry from the host.
+ *
+ * @retval VINF_SUCCESS on success.
+ * @retval VERR_INVALID_CLIENT_ID
+ * @retval VERR_WRONG_PARAMETER_COUNT
+ * @retval VERR_WRONG_PARAMETER_TYPE
+ * @since 6.1.x
+ */
+#define VBOX_SHCL_GUEST_FN_ROOT_LIST_ENTRY_READ 14
+/** Sends a root list root entry to the host.
+ *
+ * @retval VINF_SUCCESS on success.
+ * @retval VERR_INVALID_CLIENT_ID
+ * @retval VERR_WRONG_PARAMETER_COUNT
+ * @retval VERR_WRONG_PARAMETER_TYPE
+ * @since 6.1.x
+ */
+#define VBOX_SHCL_GUEST_FN_ROOT_LIST_ENTRY_WRITE 15
+/** Opens / gets a list handle from the host.
+ *
+ * @retval VINF_SUCCESS on success.
+ * @retval VERR_INVALID_CLIENT_ID
+ * @retval VERR_WRONG_PARAMETER_COUNT
+ * @retval VERR_WRONG_PARAMETER_TYPE
+ * @since 6.1.x
+ */
+#define VBOX_SHCL_GUEST_FN_LIST_OPEN 16
+/** Closes a list handle from the host.
+ *
+ * @retval VINF_SUCCESS on success.
+ * @retval VERR_INVALID_CLIENT_ID
+ * @retval VERR_WRONG_PARAMETER_COUNT
+ * @retval VERR_WRONG_PARAMETER_TYPE
+ * @since 6.1.x
+ */
+#define VBOX_SHCL_GUEST_FN_LIST_CLOSE 17
+/** Reads a list header from the host.
+ *
+ * @retval VINF_SUCCESS on success.
+ * @retval VERR_INVALID_CLIENT_ID
+ * @retval VERR_WRONG_PARAMETER_COUNT
+ * @retval VERR_WRONG_PARAMETER_TYPE
+ * @since 6.1.x
+ */
+#define VBOX_SHCL_GUEST_FN_LIST_HDR_READ 18
+/** Writes a list header to the host.
+ *
+ * @retval VINF_SUCCESS on success.
+ * @retval VERR_INVALID_CLIENT_ID
+ * @retval VERR_WRONG_PARAMETER_COUNT
+ * @retval VERR_WRONG_PARAMETER_TYPE
+ * @since 6.1.x
+ */
+#define VBOX_SHCL_GUEST_FN_LIST_HDR_WRITE 19
+/** Reads a list entry from the host.
+ *
+ * @retval VINF_SUCCESS on success.
+ * @retval VERR_INVALID_CLIENT_ID
+ * @retval VERR_WRONG_PARAMETER_COUNT
+ * @retval VERR_WRONG_PARAMETER_TYPE
+ * @since 6.1.x
+ */
+#define VBOX_SHCL_GUEST_FN_LIST_ENTRY_READ 20
+/** Sends a list entry to the host.
+ *
+ * @retval VINF_SUCCESS on success.
+ * @retval VERR_INVALID_CLIENT_ID
+ * @retval VERR_WRONG_PARAMETER_COUNT
+ * @retval VERR_WRONG_PARAMETER_TYPE
+ * @since 6.1.x
+ */
+#define VBOX_SHCL_GUEST_FN_LIST_ENTRY_WRITE 21
+/** Opens an object on the host.
+ *
+ * @retval VINF_SUCCESS on success.
+ * @retval VERR_INVALID_CLIENT_ID
+ * @retval VERR_WRONG_PARAMETER_COUNT
+ * @retval VERR_WRONG_PARAMETER_TYPE
+ * @since 6.1.x
+ */
+#define VBOX_SHCL_GUEST_FN_OBJ_OPEN 22
+/** Closes an object on the host.
+ *
+ * @retval VINF_SUCCESS on success.
+ * @retval VERR_INVALID_CLIENT_ID
+ * @retval VERR_WRONG_PARAMETER_COUNT
+ * @retval VERR_WRONG_PARAMETER_TYPE
+ * @since 6.1.x
+ */
+#define VBOX_SHCL_GUEST_FN_OBJ_CLOSE 23
+/** Reads from an object on the host.
+ *
+ * @retval VINF_SUCCESS on success.
+ * @retval VERR_INVALID_CLIENT_ID
+ * @retval VERR_WRONG_PARAMETER_COUNT
+ * @retval VERR_WRONG_PARAMETER_TYPE
+ * @since 6.1.x
+ */
+#define VBOX_SHCL_GUEST_FN_OBJ_READ 24
+/** Writes to an object on the host.
+ *
+ * @retval VINF_SUCCESS on success.
+ * @retval VERR_INVALID_CLIENT_ID
+ * @retval VERR_WRONG_PARAMETER_COUNT
+ * @retval VERR_WRONG_PARAMETER_TYPE
+ * @since 6.1.x
+ */
+#define VBOX_SHCL_GUEST_FN_OBJ_WRITE 25
+/** Reports an error to the host.
+ *
+ * @todo r=bird: Smells like GUEST_MSG_SKIP
+ *
+ * @retval VINF_SUCCESS on success.
+ * @retval VERR_INVALID_CLIENT_ID
+ * @retval VERR_WRONG_PARAMETER_COUNT
+ * @retval VERR_WRONG_PARAMETER_TYPE
+ * @since 6.1
+ */
+#define VBOX_SHCL_GUEST_FN_ERROR 27
+
+/** For negotiating a chunk size between the guest and host.
+ *
+ * Takes two 32-bit parameters both being byte counts, the first one gives the
+ * maximum chunk size the guest can handle and the second the preferred choice
+ * of the guest. Upon return, the host will have updated both of them to
+ * reflect the maximum and default chunk sizes this client connect. The guest
+ * may set the 2nd value to zero and let the host choose.
+ *
+ * @retval VINF_SUCCESS on success.
+ * @retval VERR_INVALID_CLIENT_ID
+ * @retval VERR_WRONG_PARAMETER_COUNT
+ * @retval VERR_WRONG_PARAMETER_TYPE
+ * @retval VERR_INVALID_PARAMETER if the 2nd parameter is larger than the
+ * first one
+ * @since 6.1
+ */
+#define VBOX_SHCL_GUEST_FN_NEGOTIATE_CHUNK_SIZE 28
+
+/** The last function number (used for validation/sanity). */
+#define VBOX_SHCL_GUEST_FN_LAST VBOX_SHCL_GUEST_FN_NEGOTIATE_CHUNK_SIZE
+/** @} */
+
+
+/** Maximum chunk size for a single data transfer. */
+#define VBOX_SHCL_MAX_CHUNK_SIZE VMMDEV_MAX_HGCM_DATA_SIZE - _4K
+/** Default chunk size for a single data transfer. */
+#define VBOX_SHCL_DEFAULT_CHUNK_SIZE RT_MIN(_64K, VBOX_SHCL_MAX_CHUNK_SIZE);
+
+
+/** @name VBOX_SHCL_GF_XXX - Guest features.
+ * @sa VBOX_SHCL_GUEST_FN_REPORT_FEATURES
+ * @{ */
+/** No flags set. */
+#define VBOX_SHCL_GF_NONE 0
+/** The guest can handle context IDs where applicable. */
+#define VBOX_SHCL_GF_0_CONTEXT_ID RT_BIT_64(0)
+/** The guest can copy & paste files and directories.
+ * @since 6.x */
+#define VBOX_SHCL_GF_0_TRANSFERS RT_BIT_64(1)
+/** The guest supports a (guest OS-)native frontend for showing and handling file transfers.
+ * If not set, the host will show a modal progress dialog instead and transferring file to
+ * a guest-specific temporary location first.
+ * Currently only supported for Windows guests (integrated into Windows Explorer via IDataObject). */
+#define VBOX_SHCL_GF_0_TRANSFERS_FRONTEND RT_BIT_64(2)
+/** Bit that must be set in the 2nd parameter, will be cleared if the host reponds
+ * correctly (old hosts might not). */
+#define VBOX_SHCL_GF_1_MUST_BE_ONE RT_BIT_64(63)
+/** @} */
+
+/** @name VBOX_GUESTCTRL_HF_XXX - Host features.
+ * @sa VBOX_SHCL_GUEST_FN_REPORT_FEATURES
+ * @{ */
+/** No flags set. */
+#define VBOX_SHCL_HF_NONE 0
+/** The host can handle context IDs where applicable as well as the new
+ * message handling functions. */
+#define VBOX_SHCL_HF_0_CONTEXT_ID RT_BIT_64(0)
+/** The host can copy & paste files and directories.
+ * This includes messages like
+ * @since 6.1.? */
+#define VBOX_SHCL_HF_0_TRANSFERS RT_BIT_64(1)
+/** @} */
+
+/** @name Context ID related macros and limits
+ * @{ */
+/**
+ * Creates a context ID out of a client ID, a transfer ID and an event ID (count).
+ */
+#define VBOX_SHCL_CONTEXTID_MAKE(a_idSession, a_idTransfer, a_idEvent) \
+ ( ((uint64_t)((a_idSession) & 0xffff) << 48) \
+ | ((uint64_t)((a_idTransfer) & 0xffff) << 32) \
+ | ((uint32_t) (a_idEvent)) \
+ )
+/** Creates a context ID out of a session ID. */
+#define VBOX_SHCL_CONTEXTID_MAKE_SESSION(a_idSession) VBOX_SHCL_CONTEXTID_MAKE(a_idSession, 0, 0)
+/** Gets the session ID out of a context ID. */
+#define VBOX_SHCL_CONTEXTID_GET_SESSION(a_idContext) ( (uint16_t)(((a_idContext) >> 48) & UINT16_MAX) )
+/** Gets the transfer ID out of a context ID. */
+#define VBOX_SHCL_CONTEXTID_GET_TRANSFER(a_idContext) ( (uint16_t)(((a_idContext) >> 32) & UINT16_MAX) )
+/** Gets the transfer event out of a context ID. */
+#define VBOX_SHCL_CONTEXTID_GET_EVENT(a_idContext) ( (uint32_t)( (a_idContext) & UINT32_MAX) )
+
+/** Maximum number of concurrent Shared Clipboard client sessions a VM can have. */
+#define VBOX_SHCL_MAX_SESSIONS (UINT16_MAX - 1)
+/** Maximum number of concurrent Shared Clipboard transfers a single client can have. */
+#define VBOX_SHCL_MAX_TRANSFERS (UINT16_MAX - 1)
+/** Maximum number of events a single Shared Clipboard transfer can have. */
+#define VBOX_SHCL_MAX_EVENTS (UINT32_MAX - 1)
+/** @} */
+
+
+/*
+ * HGCM parameter structures.
+ */
+/** @todo r=bird: These structures are mostly pointless, as they're only
+ * ever used by the VbglR3 part. The host service does not use these
+ * structures for decoding guest requests, instead it's all hardcoded. */
+#pragma pack(1)
+/**
+ * Waits (blocking) for a new host message to arrive.
+ * Deprecated; do not use anymore.
+ * Kept for maintaining compatibility with older Guest Additions.
+ */
+typedef struct _VBoxShClGetHostMsgOld
+{
+ VBGLIOCHGCMCALL hdr;
+
+ /** uint32_t, out: Host message type. */
+ HGCMFunctionParameter msg;
+ /** uint32_t, out: VBOX_SHCL_FMT_*, depends on the 'msg'.
+ * r=andy This actual can have *different* meanings, depending on the host message type. */
+ HGCMFunctionParameter formats; /* OUT uint32_t */
+} VBoxShClGetHostMsgOld;
+
+#define VBOX_SHCL_CPARMS_GET_HOST_MSG_OLD 2
+
+/** @name VBOX_SHCL_GUEST_FN_REPORT_FORMATS
+ * @{ */
+/** VBOX_SHCL_GUEST_FN_REPORT_FORMATS parameters. */
+typedef struct VBoxShClParmReportFormats
+{
+ /** uint32_t, int: Zero or more VBOX_SHCL_FMT_XXX bits. */
+ HGCMFunctionParameter f32Formats;
+} VBoxShClParmReportFormats;
+
+#define VBOX_SHCL_CPARMS_REPORT_FORMATS 1 /**< The parameter count for VBOX_SHCL_GUEST_FN_REPORT_FORMATS. */
+#define VBOX_SHCL_CPARMS_REPORT_FORMATS_61B 3 /**< The 6.1 dev cycle variant, see VBOX_SHCL_GUEST_FN_REPORT_FORMATS. */
+/** @} */
+
+/** @name VBOX_SHCL_GUEST_FN_DATA_READ
+ * @{ */
+/** VBOX_SHCL_GUEST_FN_DATA_READ parameters. */
+typedef struct VBoxShClParmDataRead
+{
+ /** uint32_t, in: Requested format (VBOX_SHCL_FMT_XXX). */
+ HGCMFunctionParameter f32Format;
+ /** ptr, out: The data buffer to put the data in on success. */
+ HGCMFunctionParameter pData;
+ /** uint32_t, out: Size of returned data, if larger than the buffer, then no
+ * data was actually transferred and the guest must repeat the call. */
+ HGCMFunctionParameter cb32Needed;
+} VBoxShClParmDataRead;
+
+#define VBOX_SHCL_CPARMS_DATA_READ 3 /**< The parameter count for VBOX_SHCL_GUEST_FN_DATA_READ. */
+#define VBOX_SHCL_CPARMS_DATA_READ_61B 5 /**< The 6.1 dev cycle variant, see VBOX_SHCL_GUEST_FN_DATA_READ. */
+/** @} */
+
+/** @name
+ * @{ */
+
+/** VBOX_SHCL_GUEST_FN_DATA_WRITE parameters. */
+typedef struct VBoxShClParmDataWrite
+{
+ /** uint64_t, in: Context ID from VBOX_SHCL_HOST_MSG_READ_DATA. */
+ HGCMFunctionParameter id64Context;
+ /** uint32_t, in: The data format (VBOX_SHCL_FMT_XXX). */
+ HGCMFunctionParameter f32Format;
+ /** ptr, in: The data. */
+ HGCMFunctionParameter pData;
+} VBoxShClParmDataWrite;
+
+/** Old VBOX_SHCL_GUEST_FN_DATA_WRITE parameters. */
+typedef struct VBoxShClParmDataWriteOld
+{
+ /** uint32_t, in: The data format (VBOX_SHCL_FMT_XXX). */
+ HGCMFunctionParameter f32Format;
+ /** ptr, in: The data. */
+ HGCMFunctionParameter pData;
+} VBoxShClParmDataWriteOld;
+
+#define VBOX_SHCL_CPARMS_DATA_WRITE 3 /**< The variant used when VBOX_SHCL_GF_0_CONTEXT_ID is reported. */
+#define VBOX_SHCL_CPARMS_DATA_WRITE_OLD 2 /**< The variant used when VBOX_SHCL_GF_0_CONTEXT_ID isn't reported. */
+#define VBOX_SHCL_CPARMS_DATA_WRITE_61B 5 /**< The 6.1 dev cycle variant, see VBOX_SHCL_GUEST_FN_DATA_WRITE. */
+/** @} */
+
+/**
+ * Reports a transfer status.
+ */
+typedef struct _VBoxShClTransferStatusMsg
+{
+ VBGLIOCHGCMCALL hdr;
+
+ /** uint64_t, out: Context ID. */
+ HGCMFunctionParameter uContext;
+ /** uint32_t, out: Direction of transfer; of type SHCLTRANSFERDIR_. */
+ HGCMFunctionParameter enmDir;
+ /** uint32_t, out: Status to report; of type SHCLTRANSFERSTATUS_. */
+ HGCMFunctionParameter enmStatus;
+ /** uint32_t, out: Result code to report. Optional. */
+ HGCMFunctionParameter rc;
+ /** uint32_t, out: Reporting flags. Currently unused and must be 0. */
+ HGCMFunctionParameter fFlags;
+} VBoxShClTransferStatusMsg;
+
+#define VBOX_SHCL_CPARMS_TRANSFER_STATUS 5
+
+/**
+ * Asks the host for the next command to process, along
+ * with the needed amount of parameters and an optional blocking
+ * flag.
+ *
+ * Used by: VBOX_SHCL_GUEST_FN_GET_HOST_MSG
+ *
+ */
+typedef struct _VBoxShClGetHostMsg
+{
+ VBGLIOCHGCMCALL hdr;
+
+ /** uint32_t, out: Message ID. */
+ HGCMFunctionParameter uMsg;
+ /** uint32_t, out: Number of parameters the message needs. */
+ HGCMFunctionParameter cParms;
+ /** uint32_t, in: Whether or not to block (wait) for a new message to arrive. */
+ HGCMFunctionParameter fBlock;
+} VBoxShClPeekMsg;
+
+#define VBOX_SHCL_CPARMS_GET_HOST_MSG 3
+
+/** No listing flags specified. */
+#define VBOX_SHCL_LIST_FLAG_NONE 0
+/** Only returns one entry per read. */
+#define VBOX_SHCL_LIST_FLAG_RETURN_ONE RT_BIT(0)
+/** Restarts reading a list from the beginning. */
+#define VBOX_SHCL_LIST_FLAG_RESTART RT_BIT(1)
+
+#define VBOX_SHCL_LISTHDR_FLAG_NONE 0
+
+/** No additional information provided. */
+#define VBOX_SHCL_INFO_FLAG_NONE 0
+/** Get object information of type SHCLFSOBJINFO. */
+#define VBOX_SHCL_INFO_FLAG_FSOBJINFO RT_BIT(0)
+
+/**
+ * Status message for lists and objects.
+ */
+typedef struct _VBoxShClStatusMsg
+{
+ VBGLIOCHGCMCALL hdr;
+
+ /** uint64_t, in: Context ID. */
+ HGCMFunctionParameter uContext;
+ /** uint32_t, in: Transfer status of type SHCLTRANSFERSTATUS. */
+ HGCMFunctionParameter uStatus;
+ /** pointer, in: Optional payload of this status, based on the status type. */
+ HGCMFunctionParameter pvPayload;
+} VBoxShClStatusMsg;
+
+#define VBOX_SHCL_CPARMS_STATUS 3
+
+/** Invalid message type, do not use. */
+#define VBOX_SHCL_REPLYMSGTYPE_INVALID 0
+/** Replies a transfer status. */
+#define VBOX_SHCL_REPLYMSGTYPE_TRANSFER_STATUS 1
+/** Replies a list open status. */
+#define VBOX_SHCL_REPLYMSGTYPE_LIST_OPEN 2
+/** Replies a list close status. */
+#define VBOX_SHCL_REPLYMSGTYPE_LIST_CLOSE 3
+/** Replies an object open status. */
+#define VBOX_SHCL_REPLYMSGTYPE_OBJ_OPEN 4
+/** Replies an object close status. */
+#define VBOX_SHCL_REPLYMSGTYPE_OBJ_CLOSE 5
+
+/**
+ * Generic reply message.
+ */
+typedef struct _VBoxShClReplyMsg
+{
+ VBGLIOCHGCMCALL hdr;
+
+ /** uint64_t, out: Context ID. */
+ HGCMFunctionParameter uContext;
+ /** uint32_t, out: Message type of type VBOX_SHCL_REPLYMSGTYPE_XXX. */
+ HGCMFunctionParameter enmType;
+ /** uint32_t, out: IPRT result of overall operation. */
+ HGCMFunctionParameter rc;
+ /** pointer, out: Optional payload of this reply, based on the message type. */
+ HGCMFunctionParameter pvPayload;
+ union
+ {
+ struct
+ {
+ HGCMFunctionParameter enmStatus;
+ } TransferStatus;
+ struct
+ {
+ HGCMFunctionParameter uHandle;
+ } ListOpen;
+ struct
+ {
+ HGCMFunctionParameter uHandle;
+ } ObjOpen;
+ struct
+ {
+ HGCMFunctionParameter uHandle;
+ } ObjClose;
+ } u;
+} VBoxShClReplyMsg;
+
+/** Minimum parameters (HGCM function parameters minus the union) a reply message must have. */
+#define VBOX_SHCL_CPARMS_REPLY_MIN 4
+
+/**
+ * Structure for keeping root list message parameters.
+ */
+typedef struct _VBoxShClRootListParms
+{
+ /** uint64_t, in: Context ID. */
+ HGCMFunctionParameter uContext;
+ /** uint32_t, in: Roots listing flags; unused at the moment. */
+ HGCMFunctionParameter fRoots;
+} VBoxShClRootListParms;
+
+#define VBOX_SHCL_CPARMS_ROOT_LIST 2
+
+/**
+ * Requests to read the root list header.
+ */
+typedef struct _VBoxShClRootListReadReqMsg
+{
+ VBGLIOCHGCMCALL hdr;
+
+ VBoxShClRootListParms ReqParms;
+} VBoxShClRootListReadReqMsg;
+
+#define VBOX_SHCL_CPARMS_ROOT_LIST_HDR_READ_REQ VBOX_SHCL_CPARMS_ROOT_LIST
+
+/**
+ * Reads / Writes a root list header.
+ */
+typedef struct _VBoxShClRootListHdrMsg
+{
+ VBGLIOCHGCMCALL hdr;
+
+ VBoxShClRootListParms ReqParms;
+ /** uint64_t, in/out: Number of total root list entries. */
+ HGCMFunctionParameter cRoots;
+} VBoxShClRootListHdrMsg;
+
+#define VBOX_SHCL_CPARMS_ROOT_LIST_HDR_READ VBOX_SHCL_CPARMS_ROOT_LIST + 1
+#define VBOX_SHCL_CPARMS_ROOT_LIST_HDR_WRITE VBOX_SHCL_CPARMS_ROOT_LIST + 1
+
+/**
+ * Structure for keeping list entry message parameters.
+ */
+typedef struct _VBoxShClRootListEntryParms
+{
+ /** uint64_t, in: Context ID. */
+ HGCMFunctionParameter uContext;
+ /** uint32_t, in: VBOX_SHCL_INFO_FLAG_XXX. */
+ HGCMFunctionParameter fInfo;
+ /** uint32_t, in: Index of root list entry to get (zero-based). */
+ HGCMFunctionParameter uIndex;
+} VBoxShClRootListEntryParms;
+
+#define VBOX_SHCL_CPARMS_ROOT_LIST_ENTRY 3
+
+/**
+ * Request to read a list root entry.
+ */
+typedef struct _VBoxShClRootListEntryReadReqMsg
+{
+ VBGLIOCHGCMCALL hdr;
+
+ /** in: Request parameters. */
+ VBoxShClRootListEntryParms Parms;
+} VBoxShClRootListEntryReadReqMsg;
+
+#define VBOX_SHCL_CPARMS_ROOT_LIST_ENTRY_READ_REQ VBOX_SHCL_CPARMS_ROOT_LIST_ENTRY
+
+/**
+ * Reads / Writes a root list entry.
+ */
+typedef struct _VBoxShClRootListEntryMsg
+{
+ VBGLIOCHGCMCALL hdr;
+
+ /** in/out: Request parameters. */
+ VBoxShClRootListEntryParms Parms;
+ /** pointer, in/out: Entry name. */
+ HGCMFunctionParameter szName;
+ /** uint32_t, out: Bytes to be used for information/How many bytes were used. */
+ HGCMFunctionParameter cbInfo;
+ /** pointer, in/out: Information to be set/get (SHCLFSOBJINFO only currently).
+ * Do not forget to set the SHCLFSOBJINFO::Attr::enmAdditional for Get operation as well. */
+ HGCMFunctionParameter pvInfo;
+} VBoxShClRootListEntryMsg;
+
+#define VBOX_SHCL_CPARMS_ROOT_LIST_ENTRY_READ VBOX_SHCL_CPARMS_ROOT_LIST_ENTRY + 3
+#define VBOX_SHCL_CPARMS_ROOT_LIST_ENTRY_WRITE VBOX_SHCL_CPARMS_ROOT_LIST_ENTRY + 3
+
+/**
+ * Opens a list.
+ */
+typedef struct _VBoxShClListOpenMsg
+{
+ VBGLIOCHGCMCALL hdr;
+
+ /** uint64_t, in: Context ID. */
+ HGCMFunctionParameter uContext;
+ /** uint32_t, in: Listing flags (see VBOX_SHCL_LIST_FLAG_XXX). */
+ HGCMFunctionParameter fList;
+ /** pointer, in: Filter string. */
+ HGCMFunctionParameter pvFilter;
+ /** pointer, in: Listing poth. If empty or NULL the listing's root path will be opened. */
+ HGCMFunctionParameter pvPath;
+ /** uint64_t, out: List handle. */
+ HGCMFunctionParameter uHandle;
+} VBoxShClListOpenMsg;
+
+#define VBOX_SHCL_CPARMS_LIST_OPEN 5
+
+/**
+ * Closes a list.
+ */
+typedef struct _VBoxShClListCloseMsg
+{
+ VBGLIOCHGCMCALL hdr;
+
+ /** uint64_t, in/out: Context ID. */
+ HGCMFunctionParameter uContext;
+ /** uint64_t, in: List handle. */
+ HGCMFunctionParameter uHandle;
+} VBoxShClListCloseMsg;
+
+#define VBOX_SHCL_CPARMS_LIST_CLOSE 2
+
+typedef struct _VBoxShClListHdrReqParms
+{
+ /** uint64_t, in: Context ID. */
+ HGCMFunctionParameter uContext;
+ /** uint64_t, in: List handle. */
+ HGCMFunctionParameter uHandle;
+ /** uint32_t, in: Flags of type VBOX_SHCL_LISTHDR_FLAG_XXX. */
+ HGCMFunctionParameter fFlags;
+} VBoxShClListHdrReqParms;
+
+#define VBOX_SHCL_CPARMS_LIST_HDR_REQ 3
+
+/**
+ * Request to read a list header.
+ */
+typedef struct _VBoxShClListHdrReadReqMsg
+{
+ VBGLIOCHGCMCALL hdr;
+
+ VBoxShClListHdrReqParms ReqParms;
+} VBoxShClListHdrReadReqMsg;
+
+#define VBOX_SHCL_CPARMS_LIST_HDR_READ_REQ VBOX_SHCL_CPARMS_LIST_HDR_REQ
+
+/**
+ * Reads / Writes a list header.
+ */
+typedef struct _VBoxShClListHdrMsg
+{
+ VBGLIOCHGCMCALL hdr;
+
+ VBoxShClListHdrReqParms ReqParms;
+ /** uint32_t, in/out: Feature flags (see VBOX_SHCL_FEATURE_FLAG_XXX). */
+ HGCMFunctionParameter fFeatures;
+ /** uint64_t, in/out: Number of total objects to transfer. */
+ HGCMFunctionParameter cTotalObjects;
+ /** uint64_t, in/out: Number of total bytes to transfer. */
+ HGCMFunctionParameter cbTotalSize;
+} VBoxShClListHdrMsg;
+
+#define VBOX_SHCL_CPARMS_LIST_HDR VBOX_SHCL_CPARMS_LIST_HDR_REQ + 3
+
+typedef struct _VBoxShClListEntryReqParms
+{
+ /** uint64_t, in: Context ID. */
+ HGCMFunctionParameter uContext;
+ /** uint64_t, in: List handle. */
+ HGCMFunctionParameter uHandle;
+ /** uint32_t, in: VBOX_SHCL_INFO_FLAG_XXX. */
+ HGCMFunctionParameter fInfo;
+} VBoxShClListEntryReqParms;
+
+#define VBOX_SHCL_CPARMS_LIST_ENTRY_REQ 3
+
+/**
+ * Request to read a list entry.
+ */
+typedef struct _VBoxShClListEntryReadReqMsg
+{
+ VBGLIOCHGCMCALL hdr;
+
+ VBoxShClListEntryReqParms ReqParms;
+} VBoxShClListEntryReadReqMsg;
+
+#define VBOX_SHCL_CPARMS_LIST_ENTRY_READ VBOX_SHCL_CPARMS_LIST_ENTRY_REQ
+
+/**
+ * Reads / Writes a list entry.
+ */
+typedef struct _VBoxShClListEntryMsg
+{
+ VBGLIOCHGCMCALL hdr;
+
+ /** in/out: Request parameters. */
+ VBoxShClListEntryReqParms ReqParms;
+ /** pointer, in/out: Entry name. */
+ HGCMFunctionParameter szName;
+ /** uint32_t, out: Bytes to be used for information/How many bytes were used. */
+ HGCMFunctionParameter cbInfo;
+ /** pointer, in/out: Information to be set/get (SHCLFSOBJINFO only currently).
+ * Do not forget to set the SHCLFSOBJINFO::Attr::enmAdditional for Get operation as well. */
+ HGCMFunctionParameter pvInfo;
+} VBoxShClListEntryMsg;
+
+#define VBOX_SHCL_CPARMS_LIST_ENTRY VBOX_SHCL_CPARMS_LIST_ENTRY_REQ + 3
+
+/**
+ * Opens a Shared Clipboard object.
+ */
+typedef struct _VBoxShClObjOpenMsg
+{
+ VBGLIOCHGCMCALL hdr;
+
+ /** uint64_t, in/out: Context ID. */
+ HGCMFunctionParameter uContext;
+ /** uint64_t, out: Object handle. */
+ HGCMFunctionParameter uHandle;
+ /** pointer, in: Absoulte path of object to open/create. */
+ HGCMFunctionParameter szPath;
+ /** uint32_t in: Open / Create flags of type SHCL_OBJ_CF_. */
+ HGCMFunctionParameter fCreate;
+} VBoxShClObjOpenMsg;
+
+#define VBOX_SHCL_CPARMS_OBJ_OPEN 4
+
+/**
+ * Closes a Shared Clipboard object.
+ */
+typedef struct _VBoxShClObjCloseMsg
+{
+ VBGLIOCHGCMCALL hdr;
+
+ /** uint64_t, in/out: Context ID. */
+ HGCMFunctionParameter uContext;
+ /** uint64_t, in: SHCLOBJHANDLE of object to close. */
+ HGCMFunctionParameter uHandle;
+} VBoxShClObjCloseMsg;
+
+#define VBOX_SHCL_CPARMS_OBJ_CLOSE 2
+
+/**
+ * Structure for keeping read parameters of a Shared Clipboard object.
+ */
+typedef struct _VBoxShClObjReadReqParms
+{
+ /** uint64_t, in: Context ID. */
+ HGCMFunctionParameter uContext;
+ /** uint64_t, in: SHCLOBJHANDLE of object to write to. */
+ HGCMFunctionParameter uHandle;
+ /** uint32_t, in: How many bytes to read. */
+ HGCMFunctionParameter cbToRead;
+ /** uint32_t, in: Read flags. Currently unused and must be 0. */
+ HGCMFunctionParameter fRead;
+} VBoxShClObjReadReqParms;
+
+/**
+ * Reads from a Shared Clipboard object.
+ */
+typedef struct _VBoxShClObjReadReqMsg
+{
+ VBGLIOCHGCMCALL hdr;
+
+ VBoxShClObjReadReqParms ReqParms;
+} VBoxShClObjReadReqMsg;
+
+#define VBOX_SHCL_CPARMS_OBJ_READ_REQ 4
+
+/**
+ * Reads / writes data of / to an object.
+ *
+ * Used by:
+ * VBOX_SHCL_FN_OBJ_READ
+ * VBOX_SHCL_FN_OBJ_WRITE
+ */
+typedef struct _VBoxShClObjReadWriteMsg
+{
+ VBGLIOCHGCMCALL hdr;
+
+ /** uint64_t, in/out: Context ID. */
+ HGCMFunctionParameter uContext;
+ /** uint64_t, in/out: SHCLOBJHANDLE of object to write to. */
+ HGCMFunctionParameter uHandle;
+ /** uint32_t, out: Size (in bytes) read/written. */
+ HGCMFunctionParameter cbData;
+ /** pointer, in/out: Current data chunk. */
+ HGCMFunctionParameter pvData;
+ /** uint32_t, in/out: Size (in bytes) of current data chunk checksum. */
+ HGCMFunctionParameter cbChecksum;
+ /** pointer, in/out: Checksum of data block, based on the checksum
+ * type in the data header. Optional. */
+ HGCMFunctionParameter pvChecksum;
+} VBoxShClObjReadWriteMsg;
+
+#define VBOX_SHCL_CPARMS_OBJ_READ 6
+#define VBOX_SHCL_CPARMS_OBJ_WRITE 6
+
+/**
+ * Sends an error event.
+ *
+ * Used by:
+ * VBOX_SHCL_FN_WRITE_ERROR
+ */
+typedef struct _VBoxShClErrorMsg
+{
+ VBGLIOCHGCMCALL hdr;
+
+ /** uint64_t, in: Context ID. */
+ HGCMFunctionParameter uContext;
+ /** uint32_t, in: The error code (IPRT-style). */
+ HGCMFunctionParameter rc;
+} VBoxShClWriteErrorMsg;
+
+#define VBOX_SHCL_CPARMS_ERROR 2
+
+/** @name VBOX_SHCL_GUEST_FN_NEGOTIATE_CHUNK_SIZE
+ * @{ */
+/** VBOX_SHCL_GUEST_FN_NEGOTIATE_CHUNK_SIZE parameters. */
+typedef struct _VBoxShClParmNegotiateChunkSize
+{
+ VBGLIOCHGCMCALL hdr;
+
+ /** uint32_t, in: Maximum chunk size. */
+ HGCMFunctionParameter cb32MaxChunkSize;
+ /** uint32_t, in: Default chunk size. */
+ HGCMFunctionParameter cb32ChunkSize;
+} VBoxShClParmNegotiateChunkSize;
+
+#define VBOX_SHCL_CPARMS_NEGOTIATE_CHUNK_SIZE 2
+/** @} */
+
+#pragma pack()
+
+#endif /* !VBOX_INCLUDED_HostServices_VBoxClipboardSvc_h */
+
diff --git a/include/VBox/HostServices/VBoxHostChannel.h b/include/VBox/HostServices/VBoxHostChannel.h
new file mode 100644
index 00000000..7ac452de
--- /dev/null
+++ b/include/VBox/HostServices/VBoxHostChannel.h
@@ -0,0 +1,229 @@
+/** @file
+ *
+ * Host Channel: the service definition.
+ */
+
+/*
+ * Copyright (C) 2012-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_HostServices_VBoxHostChannel_h
+#define VBOX_INCLUDED_HostServices_VBoxHostChannel_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/VMMDevCoreTypes.h>
+#include <VBox/VBoxGuestCoreTypes.h>
+#include <VBox/hgcmsvc.h>
+
+/*
+ * Host calls.
+ */
+#define VBOX_HOST_CHANNEL_HOST_FN_REGISTER 1
+#define VBOX_HOST_CHANNEL_HOST_FN_UNREGISTER 2
+
+/*
+ * Guest calls.
+ */
+#define VBOX_HOST_CHANNEL_FN_ATTACH 1 /* Attach to a channel. */
+#define VBOX_HOST_CHANNEL_FN_DETACH 2 /* Detach from the channel. */
+#define VBOX_HOST_CHANNEL_FN_SEND 3 /* Send data to the host. */
+#define VBOX_HOST_CHANNEL_FN_RECV 4 /* Receive data from the host. */
+#define VBOX_HOST_CHANNEL_FN_CONTROL 5 /* Generic data exchange using a channel instance. */
+#define VBOX_HOST_CHANNEL_FN_EVENT_WAIT 6 /* Blocking wait for a host event. */
+#define VBOX_HOST_CHANNEL_FN_EVENT_CANCEL 7 /* Cancel the blocking wait. */
+#define VBOX_HOST_CHANNEL_FN_QUERY 8 /* Generic data exchange using a channel name. */
+
+/*
+ * The host event ids for the guest.
+ */
+#define VBOX_HOST_CHANNEL_EVENT_CANCELLED 0 /* Event was cancelled by FN_EVENT_CANCEL. */
+#define VBOX_HOST_CHANNEL_EVENT_UNREGISTERED 1 /* Channel was unregistered on host. */
+#define VBOX_HOST_CHANNEL_EVENT_RECV 2 /* Data is available for receiving. */
+#define VBOX_HOST_CHANNEL_EVENT_USER 1000 /* Base of channel specific events. */
+
+/*
+ * The common control code ids for the VBOX_HOST_CHANNEL_FN_[CONTROL|QUERY]
+ */
+#define VBOX_HOST_CHANNEL_CTRL_EXISTS 0 /* Whether the channel instance or provider exists. */
+#define VBOX_HOST_CHANNEL_CTRL_USER 1000 /* Base of channel specific events. */
+
+#pragma pack(1)
+
+/* Parameter of VBOX_HOST_CHANNEL_EVENT_RECV */
+typedef struct VBOXHOSTCHANNELEVENTRECV
+{
+ uint32_t u32SizeAvailable; /* How many bytes can be read from the channel. */
+} VBOXHOSTCHANNELEVENTRECV;
+
+/*
+ * Guest calls.
+ */
+
+typedef struct VBoxHostChannelAttach
+{
+ VBGLIOCHGCMCALL hdr;
+ HGCMFunctionParameter name; /* IN linear ptr: Channel name utf8 nul terminated. */
+ HGCMFunctionParameter flags; /* IN uint32_t: Channel specific flags. */
+ HGCMFunctionParameter handle; /* OUT uint32_t: The channel handle. */
+} VBoxHostChannelAttach;
+
+typedef struct VBoxHostChannelDetach
+{
+ VBGLIOCHGCMCALL hdr;
+ HGCMFunctionParameter handle; /* IN uint32_t: The channel handle. */
+} VBoxHostChannelDetach;
+
+typedef struct VBoxHostChannelSend
+{
+ VBGLIOCHGCMCALL hdr;
+ HGCMFunctionParameter handle; /* IN uint32_t: The channel handle. */
+ HGCMFunctionParameter data; /* IN linear pointer: Data to be sent. */
+} VBoxHostChannelSend;
+
+typedef struct VBoxHostChannelRecv
+{
+ VBGLIOCHGCMCALL hdr;
+ HGCMFunctionParameter handle; /* IN uint32_t: The channel handle. */
+ HGCMFunctionParameter data; /* OUT linear pointer: Buffer for data to be received. */
+ HGCMFunctionParameter sizeReceived; /* OUT uint32_t: Bytes received. */
+ HGCMFunctionParameter sizeRemaining; /* OUT uint32_t: Bytes remaining in the channel. */
+} VBoxHostChannelRecv;
+
+typedef struct VBoxHostChannelControl
+{
+ VBGLIOCHGCMCALL hdr;
+ HGCMFunctionParameter handle; /* IN uint32_t: The channel handle. */
+ HGCMFunctionParameter code; /* IN uint32_t: The channel specific control code. */
+ HGCMFunctionParameter parm; /* IN linear pointer: Parameters of the function. */
+ HGCMFunctionParameter data; /* OUT linear pointer: Buffer for results. */
+ HGCMFunctionParameter sizeDataReturned; /* OUT uint32_t: Bytes returned in the 'data' buffer. */
+} VBoxHostChannelControl;
+
+typedef struct VBoxHostChannelEventWait
+{
+ VBGLIOCHGCMCALL hdr;
+ HGCMFunctionParameter handle; /* OUT uint32_t: The channel which generated the event. */
+ HGCMFunctionParameter id; /* OUT uint32_t: The event VBOX_HOST_CHANNEL_EVENT_*. */
+ HGCMFunctionParameter parm; /* OUT linear pointer: Parameters of the event. */
+ HGCMFunctionParameter sizeReturned; /* OUT uint32_t: Size of the parameters. */
+} VBoxHostChannelEventWait;
+
+typedef struct VBoxHostChannelEventCancel
+{
+ VBGLIOCHGCMCALL hdr;
+} VBoxHostChannelEventCancel;
+
+typedef struct VBoxHostChannelQuery
+{
+ VBGLIOCHGCMCALL hdr;
+ HGCMFunctionParameter name; /* IN linear ptr: Channel name utf8 nul terminated. */
+ HGCMFunctionParameter code; /* IN uint32_t: The control code. */
+ HGCMFunctionParameter parm; /* IN linear pointer: Parameters of the function. */
+ HGCMFunctionParameter data; /* OUT linear pointer: Buffer for results. */
+ HGCMFunctionParameter sizeDataReturned; /* OUT uint32_t: Bytes returned in the 'data' buffer. */
+} VBoxHostChannelQuery;
+
+
+/*
+ * Host calls
+ */
+
+typedef struct VBoxHostChannelHostRegister
+{
+ VBOXHGCMSVCPARM name; /* IN ptr: Channel name utf8 nul terminated. */
+ VBOXHGCMSVCPARM iface; /* IN ptr: VBOXHOSTCHANNELINTERFACE. */
+} VBoxHostChannelHostRegister;
+
+typedef struct VBoxHostChannelHostUnregister
+{
+ VBOXHGCMSVCPARM name; /* IN ptr: Channel name utf8 nul terminated */
+} VBoxHostChannelHostUnregister;
+
+/* The channel provider will invoke this callback to report channel events. */
+typedef struct VBOXHOSTCHANNELCALLBACKS
+{
+ /* A channel event occured.
+ *
+ * @param pvCallbacks The callback context specified in HostChannelAttach.
+ * @param pvChannel The channel instance returned by HostChannelAttach.
+ * @param u32Id The event id.
+ * @param pvEvent The event parameters.
+ * @param cbEvent The size of event parameters.
+ */
+ DECLR3CALLBACKMEMBER(void, HostChannelCallbackEvent, (void *pvCallbacks, void *pvChannel,
+ uint32_t u32Id, const void *pvEvent, uint32_t cbEvent));
+
+ /* The channel has been deleted by the provider. pvCallback will not be used anymore.
+ *
+ * @param pvCallbacks The callback context specified in HostChannelAttach.
+ * @param pvChannel The channel instance returned by HostChannelAttach.
+ */
+ DECLR3CALLBACKMEMBER(void, HostChannelCallbackDeleted, (void *pvCallbacks, void *pvChannel));
+} VBOXHOSTCHANNELCALLBACKS;
+
+typedef struct VBOXHOSTCHANNELINTERFACE
+{
+ /* The channel provider context. */
+ void *pvProvider;
+
+ /* A new channel is requested.
+ *
+ * @param pvProvider The provider context VBOXHOSTCHANNELINTERFACE::pvProvider.
+ * @param ppvChannel Where to store pointer to the channel instance created by the provider.
+ * @param u32Flags Channel specific flags.
+ * @param pCallbacks Callbacks to be invoked by the channel provider.
+ * @param pvCallbacks The context of callbacks.
+ */
+ DECLR3CALLBACKMEMBER(int, HostChannelAttach, (void *pvProvider, void **ppvChannel, uint32_t u32Flags,
+ VBOXHOSTCHANNELCALLBACKS *pCallbacks, void *pvCallbacks));
+
+ /* The channel is closed. */
+ DECLR3CALLBACKMEMBER(void, HostChannelDetach, (void *pvChannel));
+
+ /* The guest sends data to the channel. */
+ DECLR3CALLBACKMEMBER(int, HostChannelSend, (void *pvChannel, const void *pvData, uint32_t cbData));
+
+ /* The guest reads data from the channel. */
+ DECLR3CALLBACKMEMBER(int, HostChannelRecv, (void *pvChannel, void *pvData, uint32_t cbData,
+ uint32_t *pcbReceived, uint32_t *pcbRemaining));
+
+ /* The guest talks to the provider of the channel.
+ * @param pvChannel The channel instance. NULL if the target is the provider, rather than a channel.
+ */
+ DECLR3CALLBACKMEMBER(int, HostChannelControl, (void *pvChannel, uint32_t u32Code,
+ const void *pvParm, uint32_t cbParm,
+ const void *pvData, uint32_t cbData, uint32_t *pcbDataReturned));
+} VBOXHOSTCHANNELINTERFACE;
+
+#pragma pack()
+
+#endif /* !VBOX_INCLUDED_HostServices_VBoxHostChannel_h */
diff --git a/include/VBox/Makefile.kup b/include/VBox/Makefile.kup
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/include/VBox/Makefile.kup
diff --git a/include/VBox/RemoteDesktop/Makefile.kup b/include/VBox/RemoteDesktop/Makefile.kup
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/include/VBox/RemoteDesktop/Makefile.kup
diff --git a/include/VBox/RemoteDesktop/VRDE.h b/include/VBox/RemoteDesktop/VRDE.h
new file mode 100644
index 00000000..56c03226
--- /dev/null
+++ b/include/VBox/RemoteDesktop/VRDE.h
@@ -0,0 +1,1615 @@
+/** @file
+ * VBox Remote Desktop Extension (VRDE) - Public APIs.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_RemoteDesktop_VRDE_h
+#define VBOX_INCLUDED_RemoteDesktop_VRDE_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+
+/** @defgroup grp_vrdp VRDE
+ * VirtualBox Remote Desktop Extension (VRDE) interface that lets to use
+ * a Remote Desktop server like RDP.
+ * @{
+ */
+
+RT_C_DECLS_BEGIN
+
+/* Forward declaration of the VRDE server instance handle.
+ * This is an opaque pointer for VirtualBox.
+ * The VRDE library uses it as a pointer to some internal data.
+ */
+#ifdef __cplusplus
+class VRDEServer;
+typedef class VRDEServerType *HVRDESERVER;
+#else
+struct VRDEServer;
+typedef struct VRDEServerType *HVRDESERVER;
+#endif /* !__cplusplus */
+
+/* Callback based VRDE server interface declarations. */
+
+/** The color mouse pointer information. */
+typedef struct _VRDECOLORPOINTER
+{
+ uint16_t u16HotX;
+ uint16_t u16HotY;
+ uint16_t u16Width;
+ uint16_t u16Height;
+ uint16_t u16MaskLen;
+ uint16_t u16DataLen;
+ /* The 1BPP mask and the 24BPP bitmap follow. */
+} VRDECOLORPOINTER;
+
+/** Audio format information packed in a 32 bit value. */
+typedef uint32_t VRDEAUDIOFORMAT;
+
+/** Constructs 32 bit value for given frequency, number of channel and bits per sample. */
+#define VRDE_AUDIO_FMT_MAKE(freq, c, bps, s) ((((s) & 0x1) << 28) + (((bps) & 0xFF) << 20) + (((c) & 0xF) << 16) + ((freq) & 0xFFFF))
+
+/** Decode frequency. */
+#define VRDE_AUDIO_FMT_SAMPLE_FREQ(a) ((a) & 0xFFFF)
+/** Decode number of channels. */
+#define VRDE_AUDIO_FMT_CHANNELS(a) (((a) >> 16) & 0xF)
+/** Decode number signess. */
+#define VRDE_AUDIO_FMT_SIGNED(a) (((a) >> 28) & 0x1)
+/** Decode number of bits per sample. */
+#define VRDE_AUDIO_FMT_BITS_PER_SAMPLE(a) (((a) >> 20) & 0xFF)
+/** Decode number of bytes per sample. */
+#define VRDE_AUDIO_FMT_BYTES_PER_SAMPLE(a) ((VRDE_AUDIO_FMT_BITS_PER_SAMPLE(a) + 7) / 8)
+
+
+/*
+ * Audio input.
+ */
+
+/* Audio input notifications. */
+#define VRDE_AUDIOIN_BEGIN 1
+#define VRDE_AUDIOIN_DATA 2
+#define VRDE_AUDIOIN_END 3
+
+typedef struct VRDEAUDIOINBEGIN
+{
+ VRDEAUDIOFORMAT fmt; /* Actual format of data, which will be sent in VRDE_AUDIOIN_DATA events. */
+} VRDEAUDIOINBEGIN, *PVRDEAUDIOINBEGIN;
+
+
+/*
+ * Remote USB protocol.
+ */
+
+/* The initial version 1. */
+#define VRDE_USB_VERSION_1 (1)
+/* Version 2: look for VRDE_USB_VERSION_2 comments in the code. */
+#define VRDE_USB_VERSION_2 (2)
+/* Version 3: look for VRDE_USB_VERSION_3 comments in the code. */
+#define VRDE_USB_VERSION_3 (3)
+
+/* The default VRDE server version of Remote USB Protocol. */
+#define VRDE_USB_VERSION VRDE_USB_VERSION_3
+
+
+/** USB backend operations. */
+#define VRDE_USB_REQ_OPEN (0)
+#define VRDE_USB_REQ_CLOSE (1)
+#define VRDE_USB_REQ_RESET (2)
+#define VRDE_USB_REQ_SET_CONFIG (3)
+#define VRDE_USB_REQ_CLAIM_INTERFACE (4)
+#define VRDE_USB_REQ_RELEASE_INTERFACE (5)
+#define VRDE_USB_REQ_INTERFACE_SETTING (6)
+#define VRDE_USB_REQ_QUEUE_URB (7)
+#define VRDE_USB_REQ_REAP_URB (8)
+#define VRDE_USB_REQ_CLEAR_HALTED_EP (9)
+#define VRDE_USB_REQ_CANCEL_URB (10)
+
+/** USB service operations. */
+#define VRDE_USB_REQ_DEVICE_LIST (11)
+#define VRDE_USB_REQ_NEGOTIATE (12)
+
+/** An operation completion status is a byte. */
+typedef uint8_t VRDEUSBSTATUS;
+
+/** USB device identifier is an 32 bit value. */
+typedef uint32_t VRDEUSBDEVID;
+
+/** Status codes. */
+#define VRDE_USB_STATUS_SUCCESS ((VRDEUSBSTATUS)0)
+#define VRDE_USB_STATUS_ACCESS_DENIED ((VRDEUSBSTATUS)1)
+#define VRDE_USB_STATUS_DEVICE_REMOVED ((VRDEUSBSTATUS)2)
+
+/*
+ * Data structures to use with VRDEUSBRequest.
+ * The *RET* structures always represent the layout of VRDE data.
+ * The *PARM* structures normally the same as VRDE layout.
+ * However the VRDE_USB_REQ_QUEUE_URB_PARM has a pointer to
+ * URB data in place where actual data will be in VRDE layout.
+ *
+ * Since replies (*RET*) are asynchronous, the 'success'
+ * replies are not required for operations which return
+ * only the status code (VRDEUSBREQRETHDR only):
+ * VRDE_USB_REQ_OPEN
+ * VRDE_USB_REQ_RESET
+ * VRDE_USB_REQ_SET_CONFIG
+ * VRDE_USB_REQ_CLAIM_INTERFACE
+ * VRDE_USB_REQ_RELEASE_INTERFACE
+ * VRDE_USB_REQ_INTERFACE_SETTING
+ * VRDE_USB_REQ_CLEAR_HALTED_EP
+ *
+ */
+
+/* VRDE layout has no alignments. */
+#pragma pack(1)
+/* Common header for all VRDE USB packets. After the reply hdr follows *PARM* or *RET* data. */
+typedef struct _VRDEUSBPKTHDR
+{
+ /* Total length of the reply NOT including the 'length' field. */
+ uint32_t length;
+ /* The operation code for which the reply was sent by the client. */
+ uint8_t code;
+} VRDEUSBPKTHDR;
+
+/* Common header for all return structures. */
+typedef struct _VRDEUSBREQRETHDR
+{
+ /* Device status. */
+ VRDEUSBSTATUS status;
+ /* Device id. */
+ VRDEUSBDEVID id;
+} VRDEUSBREQRETHDR;
+
+
+/* VRDE_USB_REQ_OPEN
+ */
+typedef struct _VRDE_USB_REQ_OPEN_PARM
+{
+ uint8_t code;
+ VRDEUSBDEVID id;
+} VRDE_USB_REQ_OPEN_PARM;
+
+typedef struct _VRDE_USB_REQ_OPEN_RET
+{
+ VRDEUSBREQRETHDR hdr;
+} VRDE_USB_REQ_OPEN_RET;
+
+
+/* VRDE_USB_REQ_CLOSE
+ */
+typedef struct _VRDE_USB_REQ_CLOSE_PARM
+{
+ uint8_t code;
+ VRDEUSBDEVID id;
+} VRDE_USB_REQ_CLOSE_PARM;
+
+/* The close request has no returned data. */
+
+
+/* VRDE_USB_REQ_RESET
+ */
+typedef struct _VRDE_USB_REQ_RESET_PARM
+{
+ uint8_t code;
+ VRDEUSBDEVID id;
+} VRDE_USB_REQ_RESET_PARM;
+
+typedef struct _VRDE_USB_REQ_RESET_RET
+{
+ VRDEUSBREQRETHDR hdr;
+} VRDE_USB_REQ_RESET_RET;
+
+
+/* VRDE_USB_REQ_SET_CONFIG
+ */
+typedef struct _VRDE_USB_REQ_SET_CONFIG_PARM
+{
+ uint8_t code;
+ VRDEUSBDEVID id;
+ uint8_t configuration;
+} VRDE_USB_REQ_SET_CONFIG_PARM;
+
+typedef struct _VRDE_USB_REQ_SET_CONFIG_RET
+{
+ VRDEUSBREQRETHDR hdr;
+} VRDE_USB_REQ_SET_CONFIG_RET;
+
+
+/* VRDE_USB_REQ_CLAIM_INTERFACE
+ */
+typedef struct _VRDE_USB_REQ_CLAIM_INTERFACE_PARM
+{
+ uint8_t code;
+ VRDEUSBDEVID id;
+ uint8_t iface;
+} VRDE_USB_REQ_CLAIM_INTERFACE_PARM;
+
+typedef struct _VRDE_USB_REQ_CLAIM_INTERFACE_RET
+{
+ VRDEUSBREQRETHDR hdr;
+} VRDE_USB_REQ_CLAIM_INTERFACE_RET;
+
+
+/* VRDE_USB_REQ_RELEASE_INTERFACE
+ */
+typedef struct _VRDE_USB_REQ_RELEASE_INTERFACE_PARM
+{
+ uint8_t code;
+ VRDEUSBDEVID id;
+ uint8_t iface;
+} VRDE_USB_REQ_RELEASE_INTERFACE_PARM;
+
+typedef struct _VRDE_USB_REQ_RELEASE_INTERFACE_RET
+{
+ VRDEUSBREQRETHDR hdr;
+} VRDE_USB_REQ_RELEASE_INTERFACE_RET;
+
+
+/* VRDE_USB_REQ_INTERFACE_SETTING
+ */
+typedef struct _VRDE_USB_REQ_INTERFACE_SETTING_PARM
+{
+ uint8_t code;
+ VRDEUSBDEVID id;
+ uint8_t iface;
+ uint8_t setting;
+} VRDE_USB_REQ_INTERFACE_SETTING_PARM;
+
+typedef struct _VRDE_USB_REQ_INTERFACE_SETTING_RET
+{
+ VRDEUSBREQRETHDR hdr;
+} VRDE_USB_REQ_INTERFACE_SETTING_RET;
+
+
+/* VRDE_USB_REQ_QUEUE_URB
+ */
+
+#define VRDE_USB_TRANSFER_TYPE_CTRL (0)
+#define VRDE_USB_TRANSFER_TYPE_ISOC (1)
+#define VRDE_USB_TRANSFER_TYPE_BULK (2)
+#define VRDE_USB_TRANSFER_TYPE_INTR (3)
+#define VRDE_USB_TRANSFER_TYPE_MSG (4)
+
+#define VRDE_USB_DIRECTION_SETUP (0)
+#define VRDE_USB_DIRECTION_IN (1)
+#define VRDE_USB_DIRECTION_OUT (2)
+
+typedef struct _VRDE_USB_REQ_QUEUE_URB_PARM
+{
+ uint8_t code;
+ VRDEUSBDEVID id;
+ uint32_t handle; /* Distinguishes that particular URB. Later used in CancelURB and returned by ReapURB */
+ uint8_t type;
+ uint8_t ep;
+ uint8_t direction;
+ uint32_t urblen; /* Length of the URB. */
+ uint32_t datalen; /* Length of the data. */
+ void *data; /* In RDP layout the data follow. */
+} VRDE_USB_REQ_QUEUE_URB_PARM;
+
+/* The queue URB has no explicit return. The reap URB reply will be
+ * eventually the indirect result.
+ */
+
+
+/* VRDE_USB_REQ_REAP_URB
+ * Notificationg from server to client that server expects an URB
+ * from any device.
+ * Only sent if negotiated URB return method is polling.
+ * Normally, the client will send URBs back as soon as they are ready.
+ */
+typedef struct _VRDE_USB_REQ_REAP_URB_PARM
+{
+ uint8_t code;
+} VRDE_USB_REQ_REAP_URB_PARM;
+
+
+#define VRDE_USB_XFER_OK (0)
+#define VRDE_USB_XFER_STALL (1)
+#define VRDE_USB_XFER_DNR (2)
+#define VRDE_USB_XFER_CRC (3)
+/* VRDE_USB_VERSION_2: New error codes. OHCI Completion Codes. */
+#define VRDE_USB_XFER_BS (4) /* BitStuffing */
+#define VRDE_USB_XFER_DTM (5) /* DataToggleMismatch */
+#define VRDE_USB_XFER_PCF (6) /* PIDCheckFailure */
+#define VRDE_USB_XFER_UPID (7) /* UnexpectedPID */
+#define VRDE_USB_XFER_DO (8) /* DataOverrun */
+#define VRDE_USB_XFER_DU (9) /* DataUnderrun */
+#define VRDE_USB_XFER_BO (10) /* BufferOverrun */
+#define VRDE_USB_XFER_BU (11) /* BufferUnderrun */
+#define VRDE_USB_XFER_ERR (12) /* VBox protocol error. */
+
+#define VRDE_USB_REAP_FLAG_CONTINUED (0x0)
+#define VRDE_USB_REAP_FLAG_LAST (0x1)
+/* VRDE_USB_VERSION_3: Fragmented URBs. */
+#define VRDE_USB_REAP_FLAG_FRAGMENT (0x2)
+
+#define VRDE_USB_REAP_VALID_FLAGS (VRDE_USB_REAP_FLAG_LAST)
+/* VRDE_USB_VERSION_3: Fragmented URBs. */
+#define VRDE_USB_REAP_VALID_FLAGS_3 (VRDE_USB_REAP_FLAG_LAST | VRDE_USB_REAP_FLAG_FRAGMENT)
+
+typedef struct _VRDEUSBREQREAPURBBODY
+{
+ VRDEUSBDEVID id; /* From which device the URB arrives. */
+ uint8_t flags; /* VRDE_USB_REAP_FLAG_* */
+ uint8_t error; /* VRDE_USB_XFER_* */
+ uint32_t handle; /* Handle of returned URB. Not 0. */
+ uint32_t len; /* Length of data actually transferred. */
+ /* 'len' bytes of data follow if direction of this URB was VRDE_USB_DIRECTION_IN. */
+} VRDEUSBREQREAPURBBODY;
+
+typedef struct _VRDE_USB_REQ_REAP_URB_RET
+{
+ /* The REAP URB has no header, only completed URBs are returned. */
+ VRDEUSBREQREAPURBBODY body;
+ /* Another body may follow, depending on flags. */
+} VRDE_USB_REQ_REAP_URB_RET;
+
+
+/* VRDE_USB_REQ_CLEAR_HALTED_EP
+ */
+typedef struct _VRDE_USB_REQ_CLEAR_HALTED_EP_PARM
+{
+ uint8_t code;
+ VRDEUSBDEVID id;
+ uint8_t ep;
+} VRDE_USB_REQ_CLEAR_HALTED_EP_PARM;
+
+typedef struct _VRDE_USB_REQ_CLEAR_HALTED_EP_RET
+{
+ VRDEUSBREQRETHDR hdr;
+} VRDE_USB_REQ_CLEAR_HALTED_EP_RET;
+
+
+/* VRDE_USB_REQ_CANCEL_URB
+ */
+typedef struct _VRDE_USB_REQ_CANCEL_URB_PARM
+{
+ uint8_t code;
+ VRDEUSBDEVID id;
+ uint32_t handle;
+} VRDE_USB_REQ_CANCEL_URB_PARM;
+
+/* The cancel URB request has no return. */
+
+
+/* VRDE_USB_REQ_DEVICE_LIST
+ *
+ * Server polls USB devices on client by sending this request
+ * periodically. Client sends back a list of all devices
+ * connected to it. Each device is assigned with an identifier,
+ * that is used to distinguish the particular device.
+ */
+typedef struct _VRDE_USB_REQ_DEVICE_LIST_PARM
+{
+ uint8_t code;
+} VRDE_USB_REQ_DEVICE_LIST_PARM;
+
+/* Data is a list of the following variable length structures. */
+typedef struct _VRDEUSBDEVICEDESC
+{
+ /* Offset of the next structure. 0 if last. */
+ uint16_t oNext;
+
+ /* Identifier of the device assigned by client. */
+ VRDEUSBDEVID id;
+
+ /** USB version number. */
+ uint16_t bcdUSB;
+ /** Device class. */
+ uint8_t bDeviceClass;
+ /** Device subclass. */
+ uint8_t bDeviceSubClass;
+ /** Device protocol */
+ uint8_t bDeviceProtocol;
+ /** Vendor ID. */
+ uint16_t idVendor;
+ /** Product ID. */
+ uint16_t idProduct;
+ /** Revision, integer part. */
+ uint16_t bcdRev;
+ /** Offset of the UTF8 manufacturer string relative to the structure start. */
+ uint16_t oManufacturer;
+ /** Offset of the UTF8 product string relative to the structure start. */
+ uint16_t oProduct;
+ /** Offset of the UTF8 serial number string relative to the structure start. */
+ uint16_t oSerialNumber;
+ /** Physical USB port the device is connected to. */
+ uint16_t idPort;
+
+} VRDEUSBDEVICEDESC;
+
+#define VRDE_USBDEVICESPEED_UNKNOWN 0 /* Unknown. */
+#define VRDE_USBDEVICESPEED_LOW 1 /* Low speed (1.5 Mbit/s). */
+#define VRDE_USBDEVICESPEED_FULL 2 /* Full speed (12 Mbit/s). */
+#define VRDE_USBDEVICESPEED_HIGH 3 /* High speed (480 Mbit/s). */
+#define VRDE_USBDEVICESPEED_VARIABLE 4 /* Variable speed - USB 2.5 / wireless. */
+#define VRDE_USBDEVICESPEED_SUPERSPEED 5 /* Super Speed - USB 3.0 */
+
+typedef struct _VRDEUSBDEVICEDESCEXT
+{
+ VRDEUSBDEVICEDESC desc;
+
+ /* Extended info.
+ */
+
+ /** The USB device speed: VRDE_USBDEVICESPEED_*. */
+ uint16_t u16DeviceSpeed;
+} VRDEUSBDEVICEDESCEXT;
+
+typedef struct _VRDE_USB_REQ_DEVICE_LIST_RET
+{
+ VRDEUSBDEVICEDESC body;
+ /* Other devices may follow.
+ * The list ends with (uint16_t)0,
+ * which means that an empty list consists of 2 zero bytes.
+ */
+} VRDE_USB_REQ_DEVICE_LIST_RET;
+
+typedef struct _VRDE_USB_REQ_DEVICE_LIST_EXT_RET
+{
+ VRDEUSBDEVICEDESCEXT body;
+ /* Other devices may follow.
+ * The list ends with (uint16_t)0,
+ * which means that an empty list consists of 2 zero bytes.
+ */
+} VRDE_USB_REQ_DEVICE_LIST_EXT_RET;
+
+/* The server requests the version of the port the device is attached to.
+ * The client must use VRDEUSBDEVICEDESCEXT structure.
+ */
+#define VRDE_USB_SERVER_CAPS_PORT_VERSION 0x0001
+
+typedef struct _VRDEUSBREQNEGOTIATEPARM
+{
+ uint8_t code;
+
+ /* Remote USB Protocol version. */
+ /* VRDE_USB_VERSION_3: the 32 bit field is splitted to 16 bit version and 16 bit flags.
+ * Version 1 and 2 servers therefore have 'flags' == 0.
+ * Version 3+ servers can send some capabilities in this field, this way it is possible to add
+ * a new capability without increasing the protocol version.
+ */
+ uint16_t version;
+ uint16_t flags; /* See VRDE_USB_SERVER_CAPS_* */
+
+} VRDEUSBREQNEGOTIATEPARM;
+
+/* VRDEUSBREQNEGOTIATERET flags. */
+#define VRDE_USB_CAPS_FLAG_ASYNC (0x0)
+#define VRDE_USB_CAPS_FLAG_POLL (0x1)
+/* VRDE_USB_VERSION_2: New flag. */
+#define VRDE_USB_CAPS2_FLAG_VERSION (0x2) /* The client is negotiating the protocol version. */
+/* VRDE_USB_VERSION_3: New flag. */
+#define VRDE_USB_CAPS3_FLAG_EXT (0x4) /* The client is negotiating the extended flags.
+ * If this flag is set, then the VRDE_USB_CAPS2_FLAG_VERSION
+ * must also be set.
+ */
+
+
+#define VRDE_USB_CAPS_VALID_FLAGS (VRDE_USB_CAPS_FLAG_POLL)
+/* VRDE_USB_VERSION_2: A set of valid flags. */
+#define VRDE_USB_CAPS2_VALID_FLAGS (VRDE_USB_CAPS_FLAG_POLL | VRDE_USB_CAPS2_FLAG_VERSION)
+/* VRDE_USB_VERSION_3: A set of valid flags. */
+#define VRDE_USB_CAPS3_VALID_FLAGS (VRDE_USB_CAPS_FLAG_POLL | VRDE_USB_CAPS2_FLAG_VERSION | VRDE_USB_CAPS3_FLAG_EXT)
+
+typedef struct _VRDEUSBREQNEGOTIATERET
+{
+ uint8_t flags;
+} VRDEUSBREQNEGOTIATERET;
+
+typedef struct _VRDEUSBREQNEGOTIATERET_2
+{
+ uint8_t flags;
+ uint32_t u32Version; /* This field presents only if the VRDE_USB_CAPS2_FLAG_VERSION flag is set. */
+} VRDEUSBREQNEGOTIATERET_2;
+
+/* The server requests the version of the port the device is attached to.
+ * The client must use VRDEUSBDEVICEDESCEXT structure.
+ */
+#define VRDE_USB_CLIENT_CAPS_PORT_VERSION 0x00000001
+
+typedef struct _VRDEUSBREQNEGOTIATERET_3
+{
+ uint8_t flags;
+ uint32_t u32Version; /* This field presents only if the VRDE_USB_CAPS2_FLAG_VERSION flag is set. */
+ uint32_t u32Flags; /* This field presents only if both VRDE_USB_CAPS2_FLAG_VERSION and
+ * VRDE_USB_CAPS2_FLAG_EXT flag are set.
+ * See VRDE_USB_CLIENT_CAPS_*
+ */
+} VRDEUSBREQNEGOTIATERET_3;
+#pragma pack()
+
+#define VRDE_CLIPBOARD_FORMAT_NULL (0x0)
+#define VRDE_CLIPBOARD_FORMAT_UNICODE_TEXT (0x1)
+#define VRDE_CLIPBOARD_FORMAT_BITMAP (0x2)
+#define VRDE_CLIPBOARD_FORMAT_HTML (0x4)
+
+#define VRDE_CLIPBOARD_FUNCTION_FORMAT_ANNOUNCE (0)
+#define VRDE_CLIPBOARD_FUNCTION_DATA_READ (1)
+#define VRDE_CLIPBOARD_FUNCTION_DATA_WRITE (2)
+
+
+/** Indexes of information values. */
+
+/** Whether a client is connected at the moment.
+ * uint32_t
+ */
+#define VRDE_QI_ACTIVE (0)
+
+/** How many times a client connected up to current moment.
+ * uint32_t
+ */
+#define VRDE_QI_NUMBER_OF_CLIENTS (1)
+
+/** When last connection was established.
+ * int64_t time in milliseconds since 1970-01-01 00:00:00 UTC
+ */
+#define VRDE_QI_BEGIN_TIME (2)
+
+/** When last connection was terminated or current time if connection still active.
+ * int64_t time in milliseconds since 1970-01-01 00:00:00 UTC
+ */
+#define VRDE_QI_END_TIME (3)
+
+/** How many bytes were sent in last (current) connection.
+ * uint64_t
+ */
+#define VRDE_QI_BYTES_SENT (4)
+
+/** How many bytes were sent in all connections.
+ * uint64_t
+ */
+#define VRDE_QI_BYTES_SENT_TOTAL (5)
+
+/** How many bytes were received in last (current) connection.
+ * uint64_t
+ */
+#define VRDE_QI_BYTES_RECEIVED (6)
+
+/** How many bytes were received in all connections.
+ * uint64_t
+ */
+#define VRDE_QI_BYTES_RECEIVED_TOTAL (7)
+
+/** Login user name supplied by the client.
+ * UTF8 nul terminated string.
+ */
+#define VRDE_QI_USER (8)
+
+/** Login domain supplied by the client.
+ * UTF8 nul terminated string.
+ */
+#define VRDE_QI_DOMAIN (9)
+
+/** The client name supplied by the client.
+ * UTF8 nul terminated string.
+ */
+#define VRDE_QI_CLIENT_NAME (10)
+
+/** IP address of the client.
+ * UTF8 nul terminated string.
+ */
+#define VRDE_QI_CLIENT_IP (11)
+
+/** The client software version number.
+ * uint32_t.
+ */
+#define VRDE_QI_CLIENT_VERSION (12)
+
+/** Public key exchange method used when connection was established.
+ * Values: 0 - RDP4 public key exchange scheme.
+ * 1 - X509 sertificates were sent to client.
+ * uint32_t.
+ */
+#define VRDE_QI_ENCRYPTION_STYLE (13)
+
+/** TCP port where the server listens.
+ * Values: 0 - VRDE server failed to start.
+ * -1 - .
+ * int32_t.
+ */
+#define VRDE_QI_PORT (14)
+
+
+/** Hints what has been intercepted by the application. */
+#define VRDE_CLIENT_INTERCEPT_AUDIO RT_BIT(0)
+#define VRDE_CLIENT_INTERCEPT_USB RT_BIT(1)
+#define VRDE_CLIENT_INTERCEPT_CLIPBOARD RT_BIT(2)
+#define VRDE_CLIENT_INTERCEPT_AUDIO_INPUT RT_BIT(3)
+
+
+/** The version of the VRDE server interface. */
+#define VRDE_INTERFACE_VERSION_1 (1)
+#define VRDE_INTERFACE_VERSION_2 (2)
+#define VRDE_INTERFACE_VERSION_3 (3)
+#define VRDE_INTERFACE_VERSION_4 (4)
+
+/** The header that does not change when the interface changes. */
+typedef struct _VRDEINTERFACEHDR
+{
+ /** The version of the interface. */
+ uint64_t u64Version;
+
+ /** The size of the structure. */
+ uint64_t u64Size;
+
+} VRDEINTERFACEHDR;
+
+/** The VRDE server entry points. Interface version 1. */
+typedef struct _VRDEENTRYPOINTS_1
+{
+ /** The header. */
+ VRDEINTERFACEHDR header;
+
+ /** Destroy the server instance.
+ *
+ * @param hServer The server instance handle.
+ *
+ * @return IPRT status code.
+ */
+ DECLR3CALLBACKMEMBER(void, VRDEDestroy,(HVRDESERVER hServer));
+
+ /** The server should start to accept clients connections.
+ *
+ * @param hServer The server instance handle.
+ * @param fEnable Whether to enable or disable client connections.
+ * When is false, all existing clients are disconnected.
+ *
+ * @return IPRT status code.
+ */
+ DECLR3CALLBACKMEMBER(int, VRDEEnableConnections,(HVRDESERVER hServer,
+ bool fEnable));
+
+ /** The server should disconnect the client.
+ *
+ * @param hServer The server instance handle.
+ * @param u32ClientId The client identifier.
+ * @param fReconnect Whether to send a "REDIRECT to the same server" packet to the
+ * client before disconnecting.
+ *
+ * @return IPRT status code.
+ */
+ DECLR3CALLBACKMEMBER(void, VRDEDisconnect,(HVRDESERVER hServer,
+ uint32_t u32ClientId,
+ bool fReconnect));
+
+ /**
+ * Inform the server that the display was resized.
+ * The server will query information about display
+ * from the application via callbacks.
+ *
+ * @param hServer Handle of VRDE server instance.
+ */
+ DECLR3CALLBACKMEMBER(void, VRDEResize,(HVRDESERVER hServer));
+
+ /**
+ * Send a update.
+ *
+ * Note: the server must access the framebuffer bitmap only when VRDEUpdate is called.
+ * If the have to access the bitmap later or from another thread, then
+ * it must used an intermediate buffer and copy the framebuffer data to the
+ * intermediate buffer in VRDEUpdate.
+ *
+ * @param hServer Handle of VRDE server instance.
+ * @param uScreenId The screen index.
+ * @param pvUpdate Pointer to VRDEOrders.h::VRDEORDERHDR structure with extra data.
+ * @param cbUpdate Size of the update data.
+ */
+ DECLR3CALLBACKMEMBER(void, VRDEUpdate,(HVRDESERVER hServer,
+ unsigned uScreenId,
+ void *pvUpdate,
+ uint32_t cbUpdate));
+
+ /**
+ * Set the mouse pointer shape.
+ *
+ * @param hServer Handle of VRDE server instance.
+ * @param pPointer The pointer shape information.
+ */
+ DECLR3CALLBACKMEMBER(void, VRDEColorPointer,(HVRDESERVER hServer,
+ const VRDECOLORPOINTER *pPointer));
+
+ /**
+ * Hide the mouse pointer.
+ *
+ * @param hServer Handle of VRDE server instance.
+ */
+ DECLR3CALLBACKMEMBER(void, VRDEHidePointer,(HVRDESERVER hServer));
+
+ /**
+ * Queues the samples to be sent to clients.
+ *
+ * @param hServer Handle of VRDE server instance.
+ * @param pvSamples Address of samples to be sent.
+ * @param cSamples Number of samples.
+ * @param format Encoded audio format for these samples.
+ *
+ * @note Initialized to NULL when the application audio callbacks are NULL.
+ */
+ DECLR3CALLBACKMEMBER(void, VRDEAudioSamples,(HVRDESERVER hServer,
+ const void *pvSamples,
+ uint32_t cSamples,
+ VRDEAUDIOFORMAT format));
+
+ /**
+ * Sets the sound volume on clients.
+ *
+ * @param hServer Handle of VRDE server instance.
+ * @param left 0..0xFFFF volume level for left channel.
+ * @param right 0..0xFFFF volume level for right channel.
+ *
+ * @note Initialized to NULL when the application audio callbacks are NULL.
+ */
+ DECLR3CALLBACKMEMBER(void, VRDEAudioVolume,(HVRDESERVER hServer,
+ uint16_t u16Left,
+ uint16_t u16Right));
+
+ /**
+ * Sends a USB request.
+ *
+ * @param hServer Handle of VRDE server instance.
+ * @param u32ClientId An identifier that allows the server to find the corresponding client.
+ * The identifier is always passed by the server as a parameter
+ * of the FNVRDEUSBCALLBACK. Note that the value is the same as
+ * in the VRDESERVERCALLBACK functions.
+ * @param pvParm Function specific parameters buffer.
+ * @param cbParm Size of the buffer.
+ *
+ * @note Initialized to NULL when the application USB callbacks are NULL.
+ */
+ DECLR3CALLBACKMEMBER(void, VRDEUSBRequest,(HVRDESERVER hServer,
+ uint32_t u32ClientId,
+ void *pvParm,
+ uint32_t cbParm));
+
+ /**
+ * Called by the application when (VRDE_CLIPBOARD_FUNCTION_*):
+ * - (0) guest announces available clipboard formats;
+ * - (1) guest requests clipboard data;
+ * - (2) guest responds to the client's request for clipboard data.
+ *
+ * @param hServer The VRDE server handle.
+ * @param u32Function The cause of the call.
+ * @param u32Format Bitmask of announced formats or the format of data.
+ * @param pvData Points to: (1) buffer to be filled with clients data;
+ * (2) data from the host.
+ * @param cbData Size of 'pvData' buffer in bytes.
+ * @param pcbActualRead Size of the copied data in bytes.
+ *
+ * @note Initialized to NULL when the application clipboard callbacks are NULL.
+ */
+ DECLR3CALLBACKMEMBER(void, VRDEClipboard,(HVRDESERVER hServer,
+ uint32_t u32Function,
+ uint32_t u32Format,
+ void *pvData,
+ uint32_t cbData,
+ uint32_t *pcbActualRead));
+
+ /**
+ * Query various information from the VRDE server.
+ *
+ * @param hServer The VRDE server handle.
+ * @param index VRDE_QI_* identifier of information to be returned.
+ * @param pvBuffer Address of memory buffer to which the information must be written.
+ * @param cbBuffer Size of the memory buffer in bytes.
+ * @param pcbOut Size in bytes of returned information value.
+ *
+ * @remark The caller must check the *pcbOut. 0 there means no information was returned.
+ * A value greater than cbBuffer means that information is too big to fit in the
+ * buffer, in that case no information was placed to the buffer.
+ */
+ DECLR3CALLBACKMEMBER(void, VRDEQueryInfo,(HVRDESERVER hServer,
+ uint32_t index,
+ void *pvBuffer,
+ uint32_t cbBuffer,
+ uint32_t *pcbOut));
+} VRDEENTRYPOINTS_1;
+
+/** The VRDE server entry points. Interface version 2.
+ * A new entry point VRDERedirect has been added relative to version 1.
+ */
+typedef struct _VRDEENTRYPOINTS_2
+{
+ /** The header. */
+ VRDEINTERFACEHDR header;
+
+ /** Destroy the server instance.
+ *
+ * @param hServer The server instance handle.
+ *
+ * @return IPRT status code.
+ */
+ DECLR3CALLBACKMEMBER(void, VRDEDestroy,(HVRDESERVER hServer));
+
+ /** The server should start to accept clients connections.
+ *
+ * @param hServer The server instance handle.
+ * @param fEnable Whether to enable or disable client connections.
+ * When is false, all existing clients are disconnected.
+ *
+ * @return IPRT status code.
+ */
+ DECLR3CALLBACKMEMBER(int, VRDEEnableConnections,(HVRDESERVER hServer,
+ bool fEnable));
+
+ /** The server should disconnect the client.
+ *
+ * @param hServer The server instance handle.
+ * @param u32ClientId The client identifier.
+ * @param fReconnect Whether to send a "REDIRECT to the same server" packet to the
+ * client before disconnecting.
+ *
+ * @return IPRT status code.
+ */
+ DECLR3CALLBACKMEMBER(void, VRDEDisconnect,(HVRDESERVER hServer,
+ uint32_t u32ClientId,
+ bool fReconnect));
+
+ /**
+ * Inform the server that the display was resized.
+ * The server will query information about display
+ * from the application via callbacks.
+ *
+ * @param hServer Handle of VRDE server instance.
+ */
+ DECLR3CALLBACKMEMBER(void, VRDEResize,(HVRDESERVER hServer));
+
+ /**
+ * Send a update.
+ *
+ * Note: the server must access the framebuffer bitmap only when VRDEUpdate is called.
+ * If the have to access the bitmap later or from another thread, then
+ * it must used an intermediate buffer and copy the framebuffer data to the
+ * intermediate buffer in VRDEUpdate.
+ *
+ * @param hServer Handle of VRDE server instance.
+ * @param uScreenId The screen index.
+ * @param pvUpdate Pointer to VRDEOrders.h::VRDEORDERHDR structure with extra data.
+ * @param cbUpdate Size of the update data.
+ */
+ DECLR3CALLBACKMEMBER(void, VRDEUpdate,(HVRDESERVER hServer,
+ unsigned uScreenId,
+ void *pvUpdate,
+ uint32_t cbUpdate));
+
+ /**
+ * Set the mouse pointer shape.
+ *
+ * @param hServer Handle of VRDE server instance.
+ * @param pPointer The pointer shape information.
+ */
+ DECLR3CALLBACKMEMBER(void, VRDEColorPointer,(HVRDESERVER hServer,
+ const VRDECOLORPOINTER *pPointer));
+
+ /**
+ * Hide the mouse pointer.
+ *
+ * @param hServer Handle of VRDE server instance.
+ */
+ DECLR3CALLBACKMEMBER(void, VRDEHidePointer,(HVRDESERVER hServer));
+
+ /**
+ * Queues the samples to be sent to clients.
+ *
+ * @param hServer Handle of VRDE server instance.
+ * @param pvSamples Address of samples to be sent.
+ * @param cSamples Number of samples.
+ * @param format Encoded audio format for these samples.
+ *
+ * @note Initialized to NULL when the application audio callbacks are NULL.
+ */
+ DECLR3CALLBACKMEMBER(void, VRDEAudioSamples,(HVRDESERVER hServer,
+ const void *pvSamples,
+ uint32_t cSamples,
+ VRDEAUDIOFORMAT format));
+
+ /**
+ * Sets the sound volume on clients.
+ *
+ * @param hServer Handle of VRDE server instance.
+ * @param left 0..0xFFFF volume level for left channel.
+ * @param right 0..0xFFFF volume level for right channel.
+ *
+ * @note Initialized to NULL when the application audio callbacks are NULL.
+ */
+ DECLR3CALLBACKMEMBER(void, VRDEAudioVolume,(HVRDESERVER hServer,
+ uint16_t u16Left,
+ uint16_t u16Right));
+
+ /**
+ * Sends a USB request.
+ *
+ * @param hServer Handle of VRDE server instance.
+ * @param u32ClientId An identifier that allows the server to find the corresponding client.
+ * The identifier is always passed by the server as a parameter
+ * of the FNVRDEUSBCALLBACK. Note that the value is the same as
+ * in the VRDESERVERCALLBACK functions.
+ * @param pvParm Function specific parameters buffer.
+ * @param cbParm Size of the buffer.
+ *
+ * @note Initialized to NULL when the application USB callbacks are NULL.
+ */
+ DECLR3CALLBACKMEMBER(void, VRDEUSBRequest,(HVRDESERVER hServer,
+ uint32_t u32ClientId,
+ void *pvParm,
+ uint32_t cbParm));
+
+ /**
+ * Called by the application when (VRDE_CLIPBOARD_FUNCTION_*):
+ * - (0) guest announces available clipboard formats;
+ * - (1) guest requests clipboard data;
+ * - (2) guest responds to the client's request for clipboard data.
+ *
+ * @param hServer The VRDE server handle.
+ * @param u32Function The cause of the call.
+ * @param u32Format Bitmask of announced formats or the format of data.
+ * @param pvData Points to: (1) buffer to be filled with clients data;
+ * (2) data from the host.
+ * @param cbData Size of 'pvData' buffer in bytes.
+ * @param pcbActualRead Size of the copied data in bytes.
+ *
+ * @note Initialized to NULL when the application clipboard callbacks are NULL.
+ */
+ DECLR3CALLBACKMEMBER(void, VRDEClipboard,(HVRDESERVER hServer,
+ uint32_t u32Function,
+ uint32_t u32Format,
+ void *pvData,
+ uint32_t cbData,
+ uint32_t *pcbActualRead));
+
+ /**
+ * Query various information from the VRDE server.
+ *
+ * @param hServer The VRDE server handle.
+ * @param index VRDE_QI_* identifier of information to be returned.
+ * @param pvBuffer Address of memory buffer to which the information must be written.
+ * @param cbBuffer Size of the memory buffer in bytes.
+ * @param pcbOut Size in bytes of returned information value.
+ *
+ * @remark The caller must check the *pcbOut. 0 there means no information was returned.
+ * A value greater than cbBuffer means that information is too big to fit in the
+ * buffer, in that case no information was placed to the buffer.
+ */
+ DECLR3CALLBACKMEMBER(void, VRDEQueryInfo,(HVRDESERVER hServer,
+ uint32_t index,
+ void *pvBuffer,
+ uint32_t cbBuffer,
+ uint32_t *pcbOut));
+
+ /**
+ * The server should redirect the client to the specified server.
+ *
+ * @param hServer The server instance handle.
+ * @param u32ClientId The client identifier.
+ * @param pszServer The server to redirect the client to.
+ * @param pszUser The username to use for the redirection.
+ * Can be NULL.
+ * @param pszDomain The domain. Can be NULL.
+ * @param pszPassword The password. Can be NULL.
+ * @param u32SessionId The ID of the session to redirect to.
+ * @param pszCookie The routing token used by a load balancer to
+ * route the redirection. Can be NULL.
+ */
+ DECLR3CALLBACKMEMBER(void, VRDERedirect,(HVRDESERVER hServer,
+ uint32_t u32ClientId,
+ const char *pszServer,
+ const char *pszUser,
+ const char *pszDomain,
+ const char *pszPassword,
+ uint32_t u32SessionId,
+ const char *pszCookie));
+} VRDEENTRYPOINTS_2;
+
+/** The VRDE server entry points. Interface version 3.
+ * New entry points VRDEAudioInOpen and VRDEAudioInClose has been added relative to version 2.
+ */
+typedef struct _VRDEENTRYPOINTS_3
+{
+ /* The header. */
+ VRDEINTERFACEHDR header;
+
+ /*
+ * Same as version 2. See comment in VRDEENTRYPOINTS_2.
+ */
+
+ DECLR3CALLBACKMEMBER(void, VRDEDestroy,(HVRDESERVER hServer));
+
+ DECLR3CALLBACKMEMBER(int, VRDEEnableConnections,(HVRDESERVER hServer,
+ bool fEnable));
+
+ DECLR3CALLBACKMEMBER(void, VRDEDisconnect,(HVRDESERVER hServer,
+ uint32_t u32ClientId,
+ bool fReconnect));
+
+ DECLR3CALLBACKMEMBER(void, VRDEResize,(HVRDESERVER hServer));
+
+ DECLR3CALLBACKMEMBER(void, VRDEUpdate,(HVRDESERVER hServer,
+ unsigned uScreenId,
+ void *pvUpdate,
+ uint32_t cbUpdate));
+
+ DECLR3CALLBACKMEMBER(void, VRDEColorPointer,(HVRDESERVER hServer,
+ const VRDECOLORPOINTER *pPointer));
+
+ DECLR3CALLBACKMEMBER(void, VRDEHidePointer,(HVRDESERVER hServer));
+
+ DECLR3CALLBACKMEMBER(void, VRDEAudioSamples,(HVRDESERVER hServer,
+ const void *pvSamples,
+ uint32_t cSamples,
+ VRDEAUDIOFORMAT format));
+
+ DECLR3CALLBACKMEMBER(void, VRDEAudioVolume,(HVRDESERVER hServer,
+ uint16_t u16Left,
+ uint16_t u16Right));
+
+ DECLR3CALLBACKMEMBER(void, VRDEUSBRequest,(HVRDESERVER hServer,
+ uint32_t u32ClientId,
+ void *pvParm,
+ uint32_t cbParm));
+
+ DECLR3CALLBACKMEMBER(void, VRDEClipboard,(HVRDESERVER hServer,
+ uint32_t u32Function,
+ uint32_t u32Format,
+ void *pvData,
+ uint32_t cbData,
+ uint32_t *pcbActualRead));
+
+ DECLR3CALLBACKMEMBER(void, VRDEQueryInfo,(HVRDESERVER hServer,
+ uint32_t index,
+ void *pvBuffer,
+ uint32_t cbBuffer,
+ uint32_t *pcbOut));
+
+ DECLR3CALLBACKMEMBER(void, VRDERedirect,(HVRDESERVER hServer,
+ uint32_t u32ClientId,
+ const char *pszServer,
+ const char *pszUser,
+ const char *pszDomain,
+ const char *pszPassword,
+ uint32_t u32SessionId,
+ const char *pszCookie));
+
+ /*
+ * New for version 3.
+ */
+
+ /**
+ * Audio input open request.
+ *
+ * @param hServer Handle of VRDE server instance.
+ * @param pvCtx To be used in VRDECallbackAudioIn.
+ * @param u32ClientId An identifier that allows the server to find the corresponding client.
+ * @param audioFormat Preferred format of audio data.
+ * @param u32SamplesPerBlock Preferred number of samples in one block of audio input data.
+ *
+ * @note Initialized to NULL when the VRDECallbackAudioIn callback is NULL.
+ */
+ DECLR3CALLBACKMEMBER(void, VRDEAudioInOpen,(HVRDESERVER hServer,
+ void *pvCtx,
+ uint32_t u32ClientId,
+ VRDEAUDIOFORMAT audioFormat,
+ uint32_t u32SamplesPerBlock));
+
+ /**
+ * Audio input close request.
+ *
+ * @param hServer Handle of VRDE server instance.
+ * @param u32ClientId An identifier that allows the server to find the corresponding client.
+ *
+ * @note Initialized to NULL when the VRDECallbackAudioIn callback is NULL.
+ */
+ DECLR3CALLBACKMEMBER(void, VRDEAudioInClose,(HVRDESERVER hServer,
+ uint32_t u32ClientId));
+} VRDEENTRYPOINTS_3;
+
+
+/* Indexes for VRDECallbackProperty.
+ * *_QP_* queries a property.
+ * *_SP_* sets a property.
+ */
+#define VRDE_QP_NETWORK_PORT (1) /* Obsolete. Use VRDE_QP_NETWORK_PORT_RANGE instead. */
+#define VRDE_QP_NETWORK_ADDRESS (2) /* UTF8 string. Host network interface IP address to bind to. */
+#define VRDE_QP_NUMBER_MONITORS (3) /* 32 bit. Number of monitors in the VM. */
+#define VRDE_QP_NETWORK_PORT_RANGE (4) /* UTF8 string. List of ports. The server must bind to one of
+ * free ports from the list. Example: "3000,3010-3012,4000",
+ * which tells the server to bind to either of ports:
+ * 3000, 3010, 3011, 3012, 4000.
+ */
+#define VRDE_QP_VIDEO_CHANNEL (5)
+#define VRDE_QP_VIDEO_CHANNEL_QUALITY (6)
+#define VRDE_QP_VIDEO_CHANNEL_SUNFLSH (7)
+#define VRDE_QP_FEATURE (8) /* VRDEFEATURE structure. Generic interface to query named VRDE properties. */
+#define VRDE_QP_UNIX_SOCKET_PATH (9) /* Path to a UNIX Socket for incoming connections */
+
+#define VRDE_SP_BASE 0x1000
+#define VRDE_SP_NETWORK_BIND_PORT (VRDE_SP_BASE + 1) /* 32 bit. The port number actually used by the server.
+ * If VRDECreateServer fails, it should set the port to 0.
+ * If VRDECreateServer succeeds, then the port must be set
+ * in VRDEEnableConnections to the actually used value.
+ * VRDEDestroy must set the port to 0xFFFFFFFF.
+ */
+#define VRDE_SP_CLIENT_STATUS (VRDE_SP_BASE + 2) /* UTF8 string. The change of the generic client status:
+ * "ATTACH" - the client is attached;
+ * "DETACH" - the client is detached;
+ * "NAME=..." - the client name changes.
+ * Can be used for other notifications.
+ */
+
+#pragma pack(1)
+/* VRDE_QP_FEATURE data. */
+typedef struct _VRDEFEATURE
+{
+ uint32_t u32ClientId;
+ char achInfo[1]; /* UTF8 property input name and output value. */
+} VRDEFEATURE;
+
+/* VRDE_SP_CLIENT_STATUS data. */
+typedef struct VRDECLIENTSTATUS
+{
+ uint32_t u32ClientId;
+ uint32_t cbStatus;
+ char achStatus[1]; /* UTF8 status string. */
+} VRDECLIENTSTATUS;
+
+/* A framebuffer description. */
+typedef struct _VRDEFRAMEBUFFERINFO
+{
+ const uint8_t *pu8Bits;
+ int xOrigin;
+ int yOrigin;
+ unsigned cWidth;
+ unsigned cHeight;
+ unsigned cBitsPerPixel;
+ unsigned cbLine;
+} VRDEFRAMEBUFFERINFO;
+
+#define VRDE_INPUT_SCANCODE 0
+#define VRDE_INPUT_POINT 1
+#define VRDE_INPUT_CAD 2
+#define VRDE_INPUT_RESET 3
+#define VRDE_INPUT_SYNCH 4
+
+typedef struct _VRDEINPUTSCANCODE
+{
+ unsigned uScancode;
+} VRDEINPUTSCANCODE;
+
+#define VRDE_INPUT_POINT_BUTTON1 0x01
+#define VRDE_INPUT_POINT_BUTTON2 0x02
+#define VRDE_INPUT_POINT_BUTTON3 0x04
+#define VRDE_INPUT_POINT_WHEEL_UP 0x08
+#define VRDE_INPUT_POINT_WHEEL_DOWN 0x10
+
+typedef struct _VRDEINPUTPOINT
+{
+ int x;
+ int y;
+ unsigned uButtons;
+} VRDEINPUTPOINT;
+
+#define VRDE_INPUT_SYNCH_SCROLL 0x01
+#define VRDE_INPUT_SYNCH_NUMLOCK 0x02
+#define VRDE_INPUT_SYNCH_CAPITAL 0x04
+
+typedef struct _VRDEINPUTSYNCH
+{
+ unsigned uLockStatus;
+} VRDEINPUTSYNCH;
+#pragma pack()
+
+/** The VRDE server callbacks. Interface version 1. */
+typedef struct _VRDECALLBACKS_1
+{
+ /** The header. */
+ VRDEINTERFACEHDR header;
+
+ /**
+ * Query or set various information, on how the VRDE server operates, from or to the application.
+ * Queries for properties will always return success, and if the key is not known or has no
+ * value associated with it an empty string is returned.
+ *
+ *
+ * @param pvCallback The callback specific pointer.
+ * @param index VRDE_[Q|S]P_* identifier of information to be returned or set.
+ * @param pvBuffer Address of memory buffer to which the information must be written or read.
+ * @param cbBuffer Size of the memory buffer in bytes.
+ * @param pcbOut Size in bytes of returned information value.
+ *
+ * @return IPRT status code. VINF_BUFFER_OVERFLOW if the buffer is too small for the value.
+ */
+ DECLR3CALLBACKMEMBER(int, VRDECallbackProperty,(void *pvCallback,
+ uint32_t index,
+ void *pvBuffer,
+ uint32_t cbBuffer,
+ uint32_t *pcbOut));
+
+ /* A client is logging in, the application must decide whether
+ * to let to connect the client. The server will drop the connection,
+ * when an error code is returned by the callback.
+ *
+ * @param pvCallback The callback specific pointer.
+ * @param u32ClientId An unique client identifier generated by the server.
+ * @param pszUser The username.
+ * @param pszPassword The password.
+ * @param pszDomain The domain.
+ *
+ * @return IPRT status code.
+ */
+ DECLR3CALLBACKMEMBER(int, VRDECallbackClientLogon,(void *pvCallback,
+ uint32_t u32ClientId,
+ const char *pszUser,
+ const char *pszPassword,
+ const char *pszDomain));
+
+ /* The client has been successfully connected. That is logon was successful and the
+ * remote desktop protocol connection completely established.
+ *
+ * @param pvCallback The callback specific pointer.
+ * @param u32ClientId An unique client identifier generated by the server.
+ */
+ DECLR3CALLBACKMEMBER(void, VRDECallbackClientConnect,(void *pvCallback,
+ uint32_t u32ClientId));
+
+ /* The client has been disconnected.
+ *
+ * @param pvCallback The callback specific pointer.
+ * @param u32ClientId An unique client identifier generated by the server.
+ * @param fu32Intercepted What was intercepted by the client (VRDE_CLIENT_INTERCEPT_*).
+ */
+ DECLR3CALLBACKMEMBER(void, VRDECallbackClientDisconnect,(void *pvCallback,
+ uint32_t u32ClientId,
+ uint32_t fu32Intercepted));
+ /* The client supports one of RDP channels.
+ *
+ * @param pvCallback The callback specific pointer.
+ * @param u32ClientId An unique client identifier generated by the server.
+ * @param fu32Intercept What the client wants to intercept. One of VRDE_CLIENT_INTERCEPT_* flags.
+ * @param ppvIntercept The value to be passed to the channel specific callback.
+ *
+ * @return IPRT status code.
+ */
+ DECLR3CALLBACKMEMBER(int, VRDECallbackIntercept,(void *pvCallback,
+ uint32_t u32ClientId,
+ uint32_t fu32Intercept,
+ void **ppvIntercept));
+
+ /**
+ * Called by the server when a reply is received from a client.
+ *
+ * @param pvCallback The callback specific pointer.
+ * @param ppvIntercept The value returned by VRDECallbackIntercept for the VRDE_CLIENT_INTERCEPT_USB.
+ * @param u32ClientId Identifies the client that sent the reply.
+ * @param u8Code The operation code VRDE_USB_REQ_*.
+ * @param pvRet Points to data received from the client.
+ * @param cbRet Size of the data in bytes.
+ *
+ * @return IPRT status code.
+ */
+ DECLR3CALLBACKMEMBER(int, VRDECallbackUSB,(void *pvCallback,
+ void *pvIntercept,
+ uint32_t u32ClientId,
+ uint8_t u8Code,
+ const void *pvRet,
+ uint32_t cbRet));
+
+ /**
+ * Called by the server when (VRDE_CLIPBOARD_FUNCTION_*):
+ * - (0) client announces available clipboard formats;
+ * - (1) client requests clipboard data.
+ *
+ * @param pvCallback The callback specific pointer.
+ * @param ppvIntercept The value returned by VRDECallbackIntercept for the VRDE_CLIENT_INTERCEPT_CLIPBOARD.
+ * @param u32ClientId Identifies the RDP client that sent the reply.
+ * @param u32Function The cause of the callback.
+ * @param u32Format Bitmask of reported formats or the format of received data.
+ * @param pvData Reserved.
+ * @param cbData Reserved.
+ *
+ * @return IPRT status code.
+ */
+ DECLR3CALLBACKMEMBER(int, VRDECallbackClipboard,(void *pvCallback,
+ void *pvIntercept,
+ uint32_t u32ClientId,
+ uint32_t u32Function,
+ uint32_t u32Format,
+ const void *pvData,
+ uint32_t cbData));
+
+ /* The framebuffer information is queried.
+ *
+ * @param pvCallback The callback specific pointer.
+ * @param uScreenId The framebuffer index.
+ * @param pInfo The information structure to ber filled.
+ *
+ * @return Whether the framebuffer is available.
+ */
+ DECLR3CALLBACKMEMBER(bool, VRDECallbackFramebufferQuery,(void *pvCallback,
+ unsigned uScreenId,
+ VRDEFRAMEBUFFERINFO *pInfo));
+
+ /* Request the exclusive access to the framebuffer bitmap.
+ * Currently not used because VirtualBox makes sure that the framebuffer is available
+ * when VRDEUpdate is called.
+ *
+ * @param pvCallback The callback specific pointer.
+ * @param uScreenId The framebuffer index.
+ */
+ DECLR3CALLBACKMEMBER(void, VRDECallbackFramebufferLock,(void *pvCallback,
+ unsigned uScreenId));
+
+ /* Release the exclusive access to the framebuffer bitmap.
+ * Currently not used because VirtualBox makes sure that the framebuffer is available
+ * when VRDEUpdate is called.
+ *
+ * @param pvCallback The callback specific pointer.
+ * @param uScreenId The framebuffer index.
+ */
+ DECLR3CALLBACKMEMBER(void, VRDECallbackFramebufferUnlock,(void *pvCallback,
+ unsigned uScreenId));
+
+ /* Input from the client.
+ *
+ * @param pvCallback The callback specific pointer.
+ * @param pvInput The input information.
+ * @param cbInput The size of the input information.
+ */
+ DECLR3CALLBACKMEMBER(void, VRDECallbackInput,(void *pvCallback,
+ int type,
+ const void *pvInput,
+ unsigned cbInput));
+
+ /* Video mode hint from the client.
+ *
+ * @param pvCallback The callback specific pointer.
+ * @param cWidth Requested width.
+ * @param cHeight Requested height.
+ * @param cBitsPerPixel Requested color depth.
+ * @param uScreenId The framebuffer index.
+ */
+ DECLR3CALLBACKMEMBER(void, VRDECallbackVideoModeHint,(void *pvCallback,
+ unsigned cWidth,
+ unsigned cHeight,
+ unsigned cBitsPerPixel,
+ unsigned uScreenId));
+
+} VRDECALLBACKS_1;
+
+/* Callbacks are the same for the version 1 and version 2 interfaces. */
+typedef VRDECALLBACKS_1 VRDECALLBACKS_2;
+
+/** The VRDE server callbacks. Interface version 3. */
+typedef struct _VRDECALLBACKS_3
+{
+ /* The header. */
+ VRDEINTERFACEHDR header;
+
+ /*
+ * Same as in version 1 and 2. See comment in VRDECALLBACKS_1.
+ */
+ DECLR3CALLBACKMEMBER(int, VRDECallbackProperty,(void *pvCallback,
+ uint32_t index,
+ void *pvBuffer,
+ uint32_t cbBuffer,
+ uint32_t *pcbOut));
+
+ DECLR3CALLBACKMEMBER(int, VRDECallbackClientLogon,(void *pvCallback,
+ uint32_t u32ClientId,
+ const char *pszUser,
+ const char *pszPassword,
+ const char *pszDomain));
+
+ DECLR3CALLBACKMEMBER(void, VRDECallbackClientConnect,(void *pvCallback,
+ uint32_t u32ClientId));
+
+ DECLR3CALLBACKMEMBER(void, VRDECallbackClientDisconnect,(void *pvCallback,
+ uint32_t u32ClientId,
+ uint32_t fu32Intercepted));
+ DECLR3CALLBACKMEMBER(int, VRDECallbackIntercept,(void *pvCallback,
+ uint32_t u32ClientId,
+ uint32_t fu32Intercept,
+ void **ppvIntercept));
+
+ DECLR3CALLBACKMEMBER(int, VRDECallbackUSB,(void *pvCallback,
+ void *pvIntercept,
+ uint32_t u32ClientId,
+ uint8_t u8Code,
+ const void *pvRet,
+ uint32_t cbRet));
+
+ DECLR3CALLBACKMEMBER(int, VRDECallbackClipboard,(void *pvCallback,
+ void *pvIntercept,
+ uint32_t u32ClientId,
+ uint32_t u32Function,
+ uint32_t u32Format,
+ const void *pvData,
+ uint32_t cbData));
+
+ DECLR3CALLBACKMEMBER(bool, VRDECallbackFramebufferQuery,(void *pvCallback,
+ unsigned uScreenId,
+ VRDEFRAMEBUFFERINFO *pInfo));
+
+ DECLR3CALLBACKMEMBER(void, VRDECallbackFramebufferLock,(void *pvCallback,
+ unsigned uScreenId));
+
+ DECLR3CALLBACKMEMBER(void, VRDECallbackFramebufferUnlock,(void *pvCallback,
+ unsigned uScreenId));
+
+ DECLR3CALLBACKMEMBER(void, VRDECallbackInput,(void *pvCallback,
+ int type,
+ const void *pvInput,
+ unsigned cbInput));
+
+ DECLR3CALLBACKMEMBER(void, VRDECallbackVideoModeHint,(void *pvCallback,
+ unsigned cWidth,
+ unsigned cHeight,
+ unsigned cBitsPerPixel,
+ unsigned uScreenId));
+
+ /*
+ * New for version 3.
+ */
+
+ /**
+ * Called by the server when something happens with audio input.
+ *
+ * @param pvCallback The callback specific pointer.
+ * @param pvCtx The value passed in VRDEAudioInOpen.
+ * @param u32ClientId Identifies the client that sent the reply.
+ * @param u32Event The event code VRDE_AUDIOIN_*.
+ * @param pvData Points to data received from the client.
+ * @param cbData Size of the data in bytes.
+ */
+ DECLR3CALLBACKMEMBER(void, VRDECallbackAudioIn,(void *pvCallback,
+ void *pvCtx,
+ uint32_t u32ClientId,
+ uint32_t u32Event,
+ const void *pvData,
+ uint32_t cbData));
+} VRDECALLBACKS_3;
+
+/** The VRDE server entry points. Interface version 4.
+ * New entry point VRDEGetInterface has been added relative to version 3.
+ */
+typedef struct _VRDEENTRYPOINTS_4
+{
+ /* The header. */
+ VRDEINTERFACEHDR header;
+
+ /*
+ * Same as version 3. See comment in VRDEENTRYPOINTS_3.
+ */
+
+ DECLR3CALLBACKMEMBER(void, VRDEDestroy,(HVRDESERVER hServer));
+ DECLR3CALLBACKMEMBER(int, VRDEEnableConnections,(HVRDESERVER hServer, bool fEnable));
+ DECLR3CALLBACKMEMBER(void, VRDEDisconnect,(HVRDESERVER hServer, uint32_t u32ClientId, bool fReconnect));
+ DECLR3CALLBACKMEMBER(void, VRDEResize,(HVRDESERVER hServer));
+ DECLR3CALLBACKMEMBER(void, VRDEUpdate,(HVRDESERVER hServer, unsigned uScreenId, void *pvUpdate,
+ uint32_t cbUpdate));
+ DECLR3CALLBACKMEMBER(void, VRDEColorPointer,(HVRDESERVER hServer, const VRDECOLORPOINTER *pPointer));
+ DECLR3CALLBACKMEMBER(void, VRDEHidePointer,(HVRDESERVER hServer));
+ DECLR3CALLBACKMEMBER(void, VRDEAudioSamples,(HVRDESERVER hServer, const void *pvSamples, uint32_t cSamples,
+ VRDEAUDIOFORMAT format));
+ DECLR3CALLBACKMEMBER(void, VRDEAudioVolume,(HVRDESERVER hServer, uint16_t u16Left, uint16_t u16Right));
+ DECLR3CALLBACKMEMBER(void, VRDEUSBRequest,(HVRDESERVER hServer, uint32_t u32ClientId, void *pvParm,
+ uint32_t cbParm));
+ DECLR3CALLBACKMEMBER(void, VRDEClipboard,(HVRDESERVER hServer, uint32_t u32Function, uint32_t u32Format,
+ void *pvData, uint32_t cbData, uint32_t *pcbActualRead));
+ DECLR3CALLBACKMEMBER(void, VRDEQueryInfo,(HVRDESERVER hServer, uint32_t index, void *pvBuffer, uint32_t cbBuffer,
+ uint32_t *pcbOut));
+ DECLR3CALLBACKMEMBER(void, VRDERedirect,(HVRDESERVER hServer, uint32_t u32ClientId, const char *pszServer,
+ const char *pszUser, const char *pszDomain, const char *pszPassword,
+ uint32_t u32SessionId, const char *pszCookie));
+ DECLR3CALLBACKMEMBER(void, VRDEAudioInOpen,(HVRDESERVER hServer, void *pvCtx, uint32_t u32ClientId,
+ VRDEAUDIOFORMAT audioFormat, uint32_t u32SamplesPerBlock));
+ DECLR3CALLBACKMEMBER(void, VRDEAudioInClose,(HVRDESERVER hServer, uint32_t u32ClientId));
+
+ /**
+ * Generic interface query. An interface is a set of entry points and callbacks.
+ * It is not a reference counted interface.
+ *
+ * @param hServer Handle of VRDE server instance.
+ * @param pszId String identifier of the interface, like uuid.
+ * @param pInterface The interface structure to be initialized by the VRDE server.
+ * Only VRDEINTERFACEHDR is initialized by the caller.
+ * @param pCallbacks Callbacks required by the interface. The server makes a local copy.
+ * VRDEINTERFACEHDR version must correspond to the requested interface version.
+ * @param pvContext The context to be used in callbacks.
+ */
+
+ DECLR3CALLBACKMEMBER(int, VRDEGetInterface, (HVRDESERVER hServer,
+ const char *pszId,
+ VRDEINTERFACEHDR *pInterface,
+ const VRDEINTERFACEHDR *pCallbacks,
+ void *pvContext));
+} VRDEENTRYPOINTS_4;
+
+/* Callbacks are the same for the version 3 and version 4 interfaces. */
+typedef VRDECALLBACKS_3 VRDECALLBACKS_4;
+
+/**
+ * Create a new VRDE server instance. The instance is fully functional but refuses
+ * client connections until the entry point VRDEEnableConnections is called by the application.
+ *
+ * The caller prepares the VRDECALLBACKS_* structure. The header.u64Version field of the
+ * structure must be initialized with the version of the interface to use.
+ * The server will return pointer to VRDEENTRYPOINTS_* table in *ppEntryPoints
+ * to match the requested interface.
+ * That is if pCallbacks->header.u64Version == VRDE_INTERFACE_VERSION_1, then the server
+ * expects pCallbacks to point to VRDECALLBACKS_1 and will return a pointer to VRDEENTRYPOINTS_1.
+ *
+ * @param pCallback Pointer to the application callbacks which let the server to fetch
+ * the configuration data and to access the desktop.
+ * @param pvCallback The callback specific pointer to be passed back to the application.
+ * @param ppEntryPoints Where to store the pointer to the VRDE entry points structure.
+ * @param phServer Pointer to the created server instance handle.
+ *
+ * @return IPRT status code.
+ */
+DECLEXPORT(int) VRDECreateServer (const VRDEINTERFACEHDR *pCallbacks,
+ void *pvCallback,
+ VRDEINTERFACEHDR **ppEntryPoints,
+ HVRDESERVER *phServer);
+
+typedef DECLCALLBACKTYPE(int, FNVRDECREATESERVER,(const VRDEINTERFACEHDR *pCallbacks,
+ void *pvCallback,
+ VRDEINTERFACEHDR **ppEntryPoints,
+ HVRDESERVER *phServer));
+typedef FNVRDECREATESERVER *PFNVRDECREATESERVER;
+
+/**
+ * List of names of the VRDE properties, which are recognized by the VRDE.
+ *
+ * For example VRDESupportedProperties should return gapszProperties declared as:
+ *
+ * static const char * const gapszProperties[] =
+ * {
+ * "TCP/Ports",
+ * "TCP/Address",
+ * NULL
+ * };
+ *
+ * @returns pointer to array of pointers to name strings (UTF8).
+ */
+DECLEXPORT(const char * const *) VRDESupportedProperties (void);
+
+typedef DECLCALLBACKTYPE(const char * const *, FNVRDESUPPORTEDPROPERTIES,(void));
+typedef FNVRDESUPPORTEDPROPERTIES *PFNVRDESUPPORTEDPROPERTIES;
+
+RT_C_DECLS_END
+
+/** @} */
+
+#endif /* !VBOX_INCLUDED_RemoteDesktop_VRDE_h */
diff --git a/include/VBox/RemoteDesktop/VRDEImage.h b/include/VBox/RemoteDesktop/VRDEImage.h
new file mode 100644
index 00000000..54cd674e
--- /dev/null
+++ b/include/VBox/RemoteDesktop/VRDEImage.h
@@ -0,0 +1,256 @@
+/** @file
+ * VBox Remote Desktop Extension (VRDE) - Image updates interface.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_RemoteDesktop_VRDEImage_h
+#define VBOX_INCLUDED_RemoteDesktop_VRDEImage_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/RemoteDesktop/VRDE.h>
+
+/*
+ * Generic interface for external image updates with a clipping region to be sent
+ * to the client.
+ *
+ * Async callbacks are used for reporting errors, providing feedback, etc.
+ */
+
+#define VRDE_IMAGE_INTERFACE_NAME "IMAGE"
+
+#ifdef __cplusplus
+class VRDEImage;
+typedef class VRDEImage *HVRDEIMAGE;
+#else
+struct VRDEImage;
+typedef struct VRDEImage *HVRDEIMAGE;
+#endif /* __cplusplus */
+
+/*
+ * Format description structures for VRDEImageHandleCreate.
+ */
+typedef struct VRDEIMAGEFORMATBITMAP
+{
+ uint32_t u32BytesPerPixel; /** @todo impl */
+} VRDEIMAGEFORMATBITMAP;
+
+typedef struct VRDEIMAGEBITMAP
+{
+ uint32_t cWidth; /* The width of the bitmap in pixels. */
+ uint32_t cHeight; /* The height of the bitmap in pixels. */
+ const void *pvData; /* Address of pixel buffer. */
+ uint32_t cbData; /* Size of pixel buffer. */
+ const void *pvScanLine0; /* Address of first scanline. */
+ int32_t iScanDelta; /* Difference between two scanlines. */
+} VRDEIMAGEBITMAP;
+
+/*
+ * Image update handle creation flags.
+ */
+#define VRDE_IMAGE_F_CREATE_DEFAULT 0x00000000
+#define VRDE_IMAGE_F_CREATE_CONTENT_3D 0x00000001 /* Input image data is a rendered 3d scene. */
+#define VRDE_IMAGE_F_CREATE_CONTENT_VIDEO 0x00000002 /* Input image data is a sequence of video frames. */
+#define VRDE_IMAGE_F_CREATE_WINDOW 0x00000004 /* pRect parameter is the image update area. */
+
+/*
+ * Completion flags for image update handle creation.
+ */
+#define VRDE_IMAGE_F_COMPLETE_DEFAULT 0x00000000 /* The handle has been created. */
+#define VRDE_IMAGE_F_COMPLETE_ASYNC 0x00000001 /* The server will call VRDEImageCbNotify when the handle is ready. */
+
+/*
+ * Supported input image formats.
+ *
+ * The identifiers are arbitrary and new formats can be introduced later.
+ *
+ */
+#define VRDE_IMAGE_FMT_ID_BITMAP_BGRA8 "BITMAP_BGRA8.07e46a64-e93e-41d4-a845-204094f5ccf1"
+
+/** The VRDE server external image updates interface entry points. Interface version 1. */
+typedef struct VRDEIMAGEINTERFACE
+{
+ /** The header. */
+ VRDEINTERFACEHDR header;
+
+ /** Create image updates handle.
+ *
+ * The server can setup a context which will speed up further updates.
+ *
+ * A failure is returned if the server either does not support requested updates
+ * or it failed to create a handle.
+ *
+ * A success means that the server was able to create an internal context for
+ * the updates.
+ *
+ * @param hServer The server instance handle.
+ * @param phImage The returned image updates handle.
+ * @param pvUser The caller context of the call.
+ * @param u32ScreenId Updates are for this screen in a multimonitor config.
+ * @param fu32Flags VRDE_IMAGE_F_CREATE_* flags, which describe input data.
+ * @param pRect If VRDE_IMAGE_F_CREATE_WINDOW is set, this is the area of expected updates.
+ * Otherwise the entire screen will be used for updates.
+ * @param pvFormat Format specific data.
+ * @param cbFormat Size of format specific data.
+ * @param *pfu32CompletionFlags VRDE_IMAGE_F_COMPLETE_* flags. Async handle creation, etc.
+ *
+ * @return IPRT status code.
+ */
+ DECLR3CALLBACKMEMBER(int, VRDEImageHandleCreate, (HVRDESERVER hServer,
+ HVRDEIMAGE *phImage,
+ void *pvUser,
+ uint32_t u32ScreenId,
+ uint32_t fu32Flags,
+ const RTRECT *pRect,
+ const char *pszFormatId,
+ const void *pvFormat,
+ uint32_t cbFormat,
+ uint32_t *pfu32CompletionFlags));
+
+ /** Create image updates handle.
+ *
+ * @param hImage The image updates handle, which the caller will not use anymore.
+ *
+ * @return IPRT status code.
+ */
+ DECLR3CALLBACKMEMBER(void, VRDEImageHandleClose, (HVRDEIMAGE hImage));
+
+ /** Set a clipping region for a particular screen.
+ *
+ * @param hImage The image updates handle.
+ * @param cRects How many rectangles. 0 clears region for this screen.
+ * @param paRects Rectangles in the screen coordinates.
+ *
+ * @return IPRT status code.
+ */
+ DECLR3CALLBACKMEMBER(int, VRDEImageRegionSet, (HVRDEIMAGE hImage,
+ uint32_t cRects,
+ const RTRECT *paRects));
+
+ /** Set the new position of the update area. Only works if the image handle
+ * has been created with VRDE_IMAGE_F_CREATE_WINDOW.
+ *
+ * @param hImage The image updates handle.
+ * @param pRect New area rectangle in the screen coordinates.
+ *
+ * @return IPRT status code.
+ */
+ DECLR3CALLBACKMEMBER(int, VRDEImageGeometrySet, (HVRDEIMAGE hImage,
+ const RTRECT *pRect));
+
+ /** Set a configuration parameter.
+ *
+ * @param hImage The image updates handle.
+ * @param pszName The parameter name.
+ * @param pszValue The parameter value.
+ *
+ * @return IPRT status code.
+ */
+ DECLR3CALLBACKMEMBER(int, VRDEImagePropertySet, (HVRDEIMAGE hImage,
+ const char *pszName,
+ const char *pszValue));
+
+ /** Query a configuration parameter.
+ *
+ * @param hImage The image updates handle.
+ * @param pszName The parameter name.
+ * @param pszValue The parameter value.
+ * @param cbValueIn The size of pszValue buffer.
+ * @param pcbValueOut The length of data returned in pszValue buffer.
+ *
+ * Properties names:
+ * "ID" - an unique string for this hImage.
+ *
+ * @return IPRT status code.
+ */
+ DECLR3CALLBACKMEMBER(int, VRDEImagePropertyQuery, (HVRDEIMAGE hImage,
+ const char *pszName,
+ char *pszValue,
+ uint32_t cbValueIn,
+ uint32_t *pcbValueOut));
+
+ /** Data for an image update.
+ *
+ * @param hImage The image updates handle.
+ * @param i32TargetX Target x.
+ * @param i32TargetY Target y.
+ * @param i32TargetW Target width.
+ * @param i32TargetH Target height.
+ * @param pvImageData Format specific image data (for example VRDEIMAGEBITMAP).
+ * @param cbImageData Size of format specific image data.
+ */
+ DECLR3CALLBACKMEMBER(void, VRDEImageUpdate, (HVRDEIMAGE hImage,
+ int32_t i32TargetX,
+ int32_t i32TargetY,
+ uint32_t u32TargetW,
+ uint32_t u32TargetH,
+ const void *pvImageData,
+ uint32_t cbImageData));
+} VRDEIMAGEINTERFACE;
+
+/*
+ * Notifications.
+ * u32Id parameter of VRDEIMAGECALLBACKS::VRDEImageCbNotify.
+ */
+#define VRDE_IMAGE_NOTIFY_HANDLE_CREATE 1 /* Async result of VRDEImageHandleCreate.
+ * pvData: uint32_t = 0 if stream was not created,
+ * a non zero value otherwise.
+ */
+
+typedef struct VRDEIMAGECALLBACKS
+{
+ /** The header. */
+ VRDEINTERFACEHDR header;
+
+ /** Generic notification callback.
+ *
+ * @param hServer The server instance handle.
+ * @param pvContext The callbacks context specified in VRDEGetInterface.
+ * @param pvUser The pvUser parameter of VRDEImageHandleCreate.
+ * @param hImage The handle, same as returned by VRDEImageHandleCreate.
+ * @param u32Id The notification identifier: VRDE_IMAGE_NOTIFY_*.
+ * @param pvData The callback specific data.
+ * @param cbData The size of buffer pointed by pvData.
+ *
+ * @return IPRT status code.
+ */
+ DECLR3CALLBACKMEMBER(int, VRDEImageCbNotify,(void *pvContext,
+ void *pvUser,
+ HVRDEIMAGE hVideo,
+ uint32_t u32Id,
+ void *pvData,
+ uint32_t cbData));
+} VRDEIMAGECALLBACKS;
+
+#endif /* !VBOX_INCLUDED_RemoteDesktop_VRDEImage_h */
diff --git a/include/VBox/RemoteDesktop/VRDEInput.h b/include/VBox/RemoteDesktop/VRDEInput.h
new file mode 100644
index 00000000..378520ec
--- /dev/null
+++ b/include/VBox/RemoteDesktop/VRDEInput.h
@@ -0,0 +1,234 @@
+/** @file
+ * VBox Remote Desktop Extension (VRDE) - Input interface.
+ */
+
+/*
+ * Copyright (C) 2013-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_RemoteDesktop_VRDEInput_h
+#define VBOX_INCLUDED_RemoteDesktop_VRDEInput_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/RemoteDesktop/VRDE.h>
+
+/*
+ * Interface for receiving input events from the client.
+ */
+
+/* All structures in this file are packed.
+ * Everything is little-endian.
+ */
+#pragma pack(1)
+
+/*
+ * The application interface between VirtualBox and the VRDE server.
+ */
+
+#define VRDE_INPUT_INTERFACE_NAME "VRDE::INPUT"
+
+/*
+ * Supported input methods.
+ */
+#define VRDE_INPUT_METHOD_TOUCH 1
+
+/*
+ * fu32Flags for VRDEInputSetup
+ */
+#define VRDE_INPUT_F_ENABLE 1
+
+/* The interface entry points. Interface version 1. */
+typedef struct VRDEINPUTINTERFACE
+{
+ /* The header. */
+ VRDEINTERFACEHDR header;
+
+ /* Tell the server that an input method will be used or disabled, etc.
+ * VRDECallbackInputSetup will be called with a result.
+ *
+ * @param hServer The VRDE server instance.
+ * @param u32Method The method VRDE_INPUT_METHOD_*.
+ * @param fu32Flags What to do with the method VRDE_INPUT_F_*.
+ * @param pvSetup Method specific parameters (optional).
+ * @param cbSetup Size of method specific parameters (optional).
+ */
+ DECLR3CALLBACKMEMBER(void, VRDEInputSetup, (HVRDESERVER hServer,
+ uint32_t u32Method,
+ uint32_t fu32Flags,
+ const void *pvSetup,
+ uint32_t cbSetup));
+} VRDEINPUTINTERFACE;
+
+
+/* Interface callbacks. */
+typedef struct VRDEINPUTCALLBACKS
+{
+ /* The header. */
+ VRDEINTERFACEHDR header;
+
+ /* VRDPInputSetup async result.
+ *
+ * @param pvCallback The callbacks context specified in VRDEGetInterface.
+ * @param rcSetup The result code of the request.
+ * @param u32Method The method VRDE_INPUT_METHOD_*.
+ * @param pvResult The result information.
+ * @param cbResult The size of buffer pointed by pvResult.
+ */
+ DECLR3CALLBACKMEMBER(void, VRDECallbackInputSetup,(void *pvCallback,
+ int rcRequest,
+ uint32_t u32Method,
+ const void *pvResult,
+ uint32_t cbResult));
+
+ /* Input event.
+ *
+ * @param pvCallback The callbacks context specified in VRDEGetInterface.
+ * @param u32Method The method VRDE_INPUT_METHOD_*.
+ * @param pvEvent The event data.
+ * @param cbEvent The size of buffer pointed by pvEvent.
+ */
+ DECLR3CALLBACKMEMBER(void, VRDECallbackInputEvent,(void *pvCallback,
+ uint32_t u32Method,
+ const void *pvEvent,
+ uint32_t cbEvent));
+} VRDEINPUTCALLBACKS;
+
+
+/*
+ * Touch input definitions VRDE_INPUT_METHOD_TOUCH.
+ */
+
+/* pvResult is not used */
+
+/* RDPINPUT_HEADER */
+typedef struct VRDEINPUTHEADER
+{
+ uint16_t u16EventId;
+ uint32_t u32PDULength;
+} VRDEINPUTHEADER;
+
+/* VRDEINPUTHEADER::u16EventId */
+#define VRDEINPUT_EVENTID_SC_READY 0x0001
+#define VRDEINPUT_EVENTID_CS_READY 0x0002
+#define VRDEINPUT_EVENTID_TOUCH 0x0003
+#define VRDEINPUT_EVENTID_SUSPEND_TOUCH 0x0004
+#define VRDEINPUT_EVENTID_RESUME_TOUCH 0x0005
+#define VRDEINPUT_EVENTID_DISMISS_HOVERING_CONTACT 0x0006
+
+/* RDPINPUT_SC_READY_PDU */
+typedef struct VRDEINPUT_SC_READY_PDU
+{
+ VRDEINPUTHEADER header;
+ uint32_t u32ProtocolVersion;
+} VRDEINPUT_SC_READY_PDU;
+
+#define VRDEINPUT_PROTOCOL_V1 0x00010000
+#define VRDEINPUT_PROTOCOL_V101 0x00010001
+
+/* RDPINPUT_CS_READY_PDU */
+typedef struct VRDEINPUT_CS_READY_PDU
+{
+ VRDEINPUTHEADER header;
+ uint32_t u32Flags;
+ uint32_t u32ProtocolVersion;
+ uint16_t u16MaxTouchContacts;
+} VRDEINPUT_CS_READY_PDU;
+
+#define VRDEINPUT_READY_FLAGS_SHOW_TOUCH_VISUALS 0x00000001
+#define VRDEINPUT_READY_FLAGS_DISABLE_TIMESTAMP_INJECTION 0x00000002
+
+/* RDPINPUT_CONTACT_DATA */
+typedef struct VRDEINPUT_CONTACT_DATA
+{
+ uint8_t u8ContactId;
+ uint16_t u16FieldsPresent;
+ int32_t i32X;
+ int32_t i32Y;
+ uint32_t u32ContactFlags;
+ int16_t i16ContactRectLeft;
+ int16_t i16ContactRectTop;
+ int16_t i16ContactRectRight;
+ int16_t i16ContactRectBottom;
+ uint32_t u32Orientation;
+ uint32_t u32Pressure;
+} VRDEINPUT_CONTACT_DATA;
+
+#define VRDEINPUT_CONTACT_DATA_CONTACTRECT_PRESENT 0x0001
+#define VRDEINPUT_CONTACT_DATA_ORIENTATION_PRESENT 0x0002
+#define VRDEINPUT_CONTACT_DATA_PRESSURE_PRESENT 0x0004
+
+#define VRDEINPUT_CONTACT_FLAG_DOWN 0x0001
+#define VRDEINPUT_CONTACT_FLAG_UPDATE 0x0002
+#define VRDEINPUT_CONTACT_FLAG_UP 0x0004
+#define VRDEINPUT_CONTACT_FLAG_INRANGE 0x0008
+#define VRDEINPUT_CONTACT_FLAG_INCONTACT 0x0010
+#define VRDEINPUT_CONTACT_FLAG_CANCELED 0x0020
+
+/* RDPINPUT_TOUCH_FRAME */
+typedef struct VRDEINPUT_TOUCH_FRAME
+{
+ uint16_t u16ContactCount;
+ uint64_t u64FrameOffset;
+ VRDEINPUT_CONTACT_DATA aContacts[1];
+} VRDEINPUT_TOUCH_FRAME;
+
+/* RDPINPUT_TOUCH_EVENT_PDU */
+typedef struct VRDEINPUT_TOUCH_EVENT_PDU
+{
+ VRDEINPUTHEADER header;
+ uint32_t u32EncodeTime;
+ uint16_t u16FrameCount;
+ VRDEINPUT_TOUCH_FRAME aFrames[1];
+} VRDEINPUT_TOUCH_EVENT_PDU;
+
+/* RDPINPUT_SUSPEND_TOUCH_PDU */
+typedef struct VRDEINPUT_SUSPEND_TOUCH_PDU
+{
+ VRDEINPUTHEADER header;
+} VRDEINPUT_SUSPEND_TOUCH_PDU;
+
+/* RDPINPUT_RESUME_TOUCH_PDU */
+typedef struct VRDEINPUT_RESUME_TOUCH_PDU
+{
+ VRDEINPUTHEADER header;
+} VRDEINPUT_RESUME_TOUCH_PDU;
+
+/* RDPINPUT_DISMISS_HOVERING_CONTACT_PDU */
+typedef struct VRDEINPUT_DISMISS_HOVERING_CONTACT_PDU
+{
+ VRDEINPUTHEADER header;
+ uint8_t u8ContactId;
+} VRDEINPUT_DISMISS_HOVERING_CONTACT_PDU;
+
+#pragma pack()
+
+#endif /* !VBOX_INCLUDED_RemoteDesktop_VRDEInput_h */
diff --git a/include/VBox/RemoteDesktop/VRDEMousePtr.h b/include/VBox/RemoteDesktop/VRDEMousePtr.h
new file mode 100644
index 00000000..e62bc708
--- /dev/null
+++ b/include/VBox/RemoteDesktop/VRDEMousePtr.h
@@ -0,0 +1,82 @@
+/** @file
+ * VBox Remote Desktop Extension (VRDE) - Mouse pointer updates interface.
+ */
+
+/*
+ * Copyright (C) 2012-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_RemoteDesktop_VRDEMousePtr_h
+#define VBOX_INCLUDED_RemoteDesktop_VRDEMousePtr_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/RemoteDesktop/VRDE.h>
+
+/*
+ * Interface for mouse pointer updates.
+ */
+
+#define VRDE_MOUSEPTR_INTERFACE_NAME "MOUSEPTR"
+
+#pragma pack(1)
+/* The color mouse pointer information: maximum allowed pointer size is 256x256. */
+typedef struct VRDEMOUSEPTRDATA
+{
+ uint16_t u16HotX;
+ uint16_t u16HotY;
+ uint16_t u16Width;
+ uint16_t u16Height;
+ uint16_t u16MaskLen; /* 0 for 32BPP pointers with alpha channel. */
+ uint32_t u32DataLen;
+ /* uint8_t au8Mask[u16MaskLen]; The 1BPP mask. Optional: does not exist if u16MaskLen == 0. */
+ /* uint8_t au8Data[u16DataLen]; The color bitmap, 32 bits color depth. */
+} VRDEMOUSEPTRDATA;
+#pragma pack()
+
+/** The VRDE server external mouse pointer updates interface entry points. Interface version 1. */
+typedef struct VRDEMOUSEPTRINTERFACE
+{
+ /** The header. */
+ VRDEINTERFACEHDR header;
+
+ /** Set the mouse pointer.
+ *
+ * @param hServer The server instance handle.
+ * @param pPointer The mouse pointer description.
+ *
+ */
+ DECLR3CALLBACKMEMBER(void, VRDEMousePtr, (HVRDESERVER hServer,
+ const VRDEMOUSEPTRDATA *pPointer));
+
+} VRDEMOUSEPTRINTERFACE;
+
+#endif /* !VBOX_INCLUDED_RemoteDesktop_VRDEMousePtr_h */
diff --git a/include/VBox/RemoteDesktop/VRDEOrders.h b/include/VBox/RemoteDesktop/VRDEOrders.h
new file mode 100644
index 00000000..06428fe0
--- /dev/null
+++ b/include/VBox/RemoteDesktop/VRDEOrders.h
@@ -0,0 +1,310 @@
+/** @file
+ * VBox Remote Desktop Extension (VRDE) - Graphics Orders Structures.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_RemoteDesktop_VRDEOrders_h
+#define VBOX_INCLUDED_RemoteDesktop_VRDEOrders_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+
+/*
+ * VRDE gets an information about a graphical update as a pointer
+ * to a memory block and the size of the memory block.
+ * The memory block layout is:
+ * VRDEORDERHDR - Describes the affected rectangle.
+ * Then VRDE orders follow:
+ * VRDEORDERCODE;
+ * a VRDEORDER* structure.
+ *
+ * If size of the memory block is equal to the VRDEORDERHDR, then a bitmap
+ * update is assumed.
+ */
+
+/* VRDE order codes. Must be >= 0, because the VRDE internally
+ * uses negative values to mark some operations.
+ */
+#define VRDE_ORDER_DIRTY_RECT (0)
+#define VRDE_ORDER_SOLIDRECT (1)
+#define VRDE_ORDER_SOLIDBLT (2)
+#define VRDE_ORDER_DSTBLT (3)
+#define VRDE_ORDER_SCREENBLT (4)
+#define VRDE_ORDER_PATBLTBRUSH (5)
+#define VRDE_ORDER_MEMBLT (6)
+#define VRDE_ORDER_CACHED_BITMAP (7)
+#define VRDE_ORDER_DELETED_BITMAP (8)
+#define VRDE_ORDER_LINE (9)
+#define VRDE_ORDER_BOUNDS (10)
+#define VRDE_ORDER_REPEAT (11)
+#define VRDE_ORDER_POLYLINE (12)
+#define VRDE_ORDER_ELLIPSE (13)
+#define VRDE_ORDER_SAVESCREEN (14)
+#define VRDE_ORDER_TEXT (15)
+
+/* 128 bit bitmap hash. */
+typedef uint8_t VRDEBITMAPHASH[16];
+
+#pragma pack(1)
+typedef struct _VRDEORDERHDR
+{
+ /** Coordinates of the affected rectangle. */
+ int16_t x;
+ int16_t y;
+ uint16_t w;
+ uint16_t h;
+} VRDEORDERHDR;
+
+typedef struct _VRDEORDERCODE
+{
+ uint32_t u32Code;
+} VRDEORDERCODE;
+
+typedef struct _VRDEORDERPOINT
+{
+ int16_t x;
+ int16_t y;
+} VRDEORDERPOINT;
+
+typedef struct _VRDEORDERPOLYPOINTS
+{
+ uint8_t c;
+ VRDEORDERPOINT a[16];
+} VRDEORDERPOLYPOINTS;
+
+typedef struct _VRDEORDERAREA
+{
+ int16_t x;
+ int16_t y;
+ uint16_t w;
+ uint16_t h;
+} VRDEORDERAREA;
+
+typedef struct _VRDEORDERRECT
+{
+ int16_t left;
+ int16_t top;
+ int16_t right;
+ int16_t bottom;
+} VRDEORDERRECT;
+
+
+typedef struct _VRDEORDERBOUNDS
+{
+ VRDEORDERPOINT pt1;
+ VRDEORDERPOINT pt2;
+} VRDEORDERBOUNDS;
+
+typedef struct _VRDEORDERREPEAT
+{
+ VRDEORDERBOUNDS bounds;
+} VRDEORDERREPEAT;
+
+
+/* Header for bitmap bits. */
+typedef struct _VRDEDATABITS
+{
+ uint32_t cb; /* Size of bitmap data without the header. */
+ int16_t x;
+ int16_t y;
+ uint16_t cWidth;
+ uint16_t cHeight;
+ uint8_t cbPixel;
+ /* Bitmap data follow. */
+} VRDEDATABITS;
+
+typedef struct _VRDEORDERSOLIDRECT
+{
+ int16_t x;
+ int16_t y;
+ uint16_t w;
+ uint16_t h;
+ uint32_t rgb;
+} VRDEORDERSOLIDRECT;
+
+typedef struct _VRDEORDERSOLIDBLT
+{
+ int16_t x;
+ int16_t y;
+ uint16_t w;
+ uint16_t h;
+ uint32_t rgb;
+ uint8_t rop;
+} VRDEORDERSOLIDBLT;
+
+typedef struct _VRDEORDERDSTBLT
+{
+ int16_t x;
+ int16_t y;
+ uint16_t w;
+ uint16_t h;
+ uint8_t rop;
+} VRDEORDERDSTBLT;
+
+typedef struct _VRDEORDERSCREENBLT
+{
+ int16_t x;
+ int16_t y;
+ uint16_t w;
+ uint16_t h;
+ int16_t xSrc;
+ int16_t ySrc;
+ uint8_t rop;
+} VRDEORDERSCREENBLT;
+
+typedef struct _VRDEORDERPATBLTBRUSH
+{
+ int16_t x;
+ int16_t y;
+ uint16_t w;
+ uint16_t h;
+ int8_t xSrc;
+ int8_t ySrc;
+ uint32_t rgbFG;
+ uint32_t rgbBG;
+ uint8_t rop;
+ uint8_t pattern[8];
+} VRDEORDERPATBLTBRUSH;
+
+typedef struct _VRDEORDERMEMBLT
+{
+ int16_t x;
+ int16_t y;
+ uint16_t w;
+ uint16_t h;
+ int16_t xSrc;
+ int16_t ySrc;
+ uint8_t rop;
+ VRDEBITMAPHASH hash;
+} VRDEORDERMEMBLT;
+
+typedef struct _VRDEORDERCACHEDBITMAP
+{
+ VRDEBITMAPHASH hash;
+ /* VRDEDATABITS and the bitmap data follow. */
+} VRDEORDERCACHEDBITMAP;
+
+typedef struct _VRDEORDERDELETEDBITMAP
+{
+ VRDEBITMAPHASH hash;
+} VRDEORDERDELETEDBITMAP;
+
+typedef struct _VRDEORDERLINE
+{
+ int16_t x1;
+ int16_t y1;
+ int16_t x2;
+ int16_t y2;
+ int16_t xBounds1;
+ int16_t yBounds1;
+ int16_t xBounds2;
+ int16_t yBounds2;
+ uint8_t mix;
+ uint32_t rgb;
+} VRDEORDERLINE;
+
+typedef struct _VRDEORDERPOLYLINE
+{
+ VRDEORDERPOINT ptStart;
+ uint8_t mix;
+ uint32_t rgb;
+ VRDEORDERPOLYPOINTS points;
+} VRDEORDERPOLYLINE;
+
+typedef struct _VRDEORDERELLIPSE
+{
+ VRDEORDERPOINT pt1;
+ VRDEORDERPOINT pt2;
+ uint8_t mix;
+ uint8_t fillMode;
+ uint32_t rgb;
+} VRDEORDERELLIPSE;
+
+typedef struct _VRDEORDERSAVESCREEN
+{
+ VRDEORDERPOINT pt1;
+ VRDEORDERPOINT pt2;
+ uint8_t ident;
+ uint8_t restore;
+} VRDEORDERSAVESCREEN;
+
+typedef struct _VRDEORDERGLYPH
+{
+ uint32_t o32NextGlyph;
+ uint64_t u64Handle;
+
+ /* The glyph origin position on the screen. */
+ int16_t x;
+ int16_t y;
+
+ /* The glyph bitmap dimensions. Note w == h == 0 for the space character. */
+ uint16_t w;
+ uint16_t h;
+
+ /* The character origin in the bitmap. */
+ int16_t xOrigin;
+ int16_t yOrigin;
+
+ /* 1BPP bitmap. Rows are byte aligned. Size is (((w + 7)/8) * h + 3) & ~3. */
+ uint8_t au8Bitmap[1];
+} VRDEORDERGLYPH;
+
+typedef struct _VRDEORDERTEXT
+{
+ uint32_t cbOrder;
+
+ int16_t xBkGround;
+ int16_t yBkGround;
+ uint16_t wBkGround;
+ uint16_t hBkGround;
+
+ int16_t xOpaque;
+ int16_t yOpaque;
+ uint16_t wOpaque;
+ uint16_t hOpaque;
+
+ uint16_t u16MaxGlyph;
+
+ uint8_t u8Glyphs;
+ uint8_t u8Flags;
+ uint16_t u8CharInc;
+ uint32_t u32FgRGB;
+ uint32_t u32BgRGB;
+
+ /* u8Glyphs glyphs follow. Size of each glyph structure may vary. */
+} VRDEORDERTEXT;
+#pragma pack()
+
+#endif /* !VBOX_INCLUDED_RemoteDesktop_VRDEOrders_h */
diff --git a/include/VBox/RemoteDesktop/VRDESCard.h b/include/VBox/RemoteDesktop/VRDESCard.h
new file mode 100644
index 00000000..9281ebed
--- /dev/null
+++ b/include/VBox/RemoteDesktop/VRDESCard.h
@@ -0,0 +1,528 @@
+/** @file
+ * VBox Remote Desktop Extension (VRDE) - SmartCard interface.
+ */
+
+/*
+ * Copyright (C) 2011-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_RemoteDesktop_VRDESCard_h
+#define VBOX_INCLUDED_RemoteDesktop_VRDESCard_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/RemoteDesktop/VRDE.h>
+
+/*
+ * Interface for accessing the smart card reader devices on the client.
+ *
+ * Async callbacks are used for providing feedback, reporting errors, etc.
+ *
+ * The caller prepares a VRDESCARD*REQ structure and submits it.
+ */
+
+#define VRDE_SCARD_INTERFACE_NAME "SCARD"
+
+/** The VRDE server smart card access interface entry points. Interface version 1. */
+typedef struct VRDESCARDINTERFACE
+{
+ /** The header. */
+ VRDEINTERFACEHDR header;
+
+ /** Submit an async IO request to the client.
+ *
+ * @param hServer The VRDE server instance.
+ * @param pvUser The callers context of this request.
+ * @param u32Function The function: VRDE_SCARD_FN_*.
+ * @param pvData Function specific data: VRDESCARD*REQ.
+ * @param cbData Size of data.
+ *
+ * @return IPRT status code.
+ */
+ DECLR3CALLBACKMEMBER(int, VRDESCardRequest, (HVRDESERVER hServer,
+ void *pvUser,
+ uint32_t u32Function,
+ const void *pvData,
+ uint32_t cbData));
+
+} VRDESCARDINTERFACE;
+
+/* Smartcard interface callbacks. */
+typedef struct VRDESCARDCALLBACKS
+{
+ /** The header. */
+ VRDEINTERFACEHDR header;
+
+ /** Notifications.
+ *
+ * @param pvContext The callbacks context specified in VRDEGetInterface.
+ * @param u32Id The notification identifier: VRDE_SCARD_NOTIFY_*.
+ * @param pvData The notification specific data.
+ * @param cbData The size of buffer pointed by pvData.
+ *
+ * @return IPRT status code.
+ */
+ DECLR3CALLBACKMEMBER(int, VRDESCardCbNotify, (void *pvContext,
+ uint32_t u32Id,
+ void *pvData,
+ uint32_t cbData));
+
+ /** IO response.
+ *
+ * @param pvContext The callbacks context specified in VRDEGetInterface.
+ * @param rcRequest The IPRT status code for the request.
+ * @param pvUser The pvUser parameter of VRDESCardRequest.
+ * @param u32Function The completed function: VRDE_SCARD_FN_*.
+ * @param pvData Function specific response data: VRDESCARD*RSP.
+ * @param cbData The size of the buffer pointed by pvData.
+ *
+ * @return IPRT status code.
+ */
+ DECLR3CALLBACKMEMBER(int, VRDESCardCbResponse, (void *pvContext,
+ int rcRequest,
+ void *pvUser,
+ uint32_t u32Function,
+ void *pvData,
+ uint32_t cbData));
+} VRDESCARDCALLBACKS;
+
+
+/*
+ * Notifications.
+ * u32Id parameter of VRDESCARDCALLBACKS::VRDESCardCbNotify.
+ */
+
+#define VRDE_SCARD_NOTIFY_ATTACH 1 /* A SCARD RDPDR device has been attached. */
+#define VRDE_SCARD_NOTIFY_DETACH 2 /* A SCARD RDPDR device has been detached. */
+
+/*
+ * Notifications.
+ * Data structures: pvData of VRDESCARDCALLBACKS::VRDESCardCbNotify.
+ */
+typedef struct VRDESCARDNOTIFYATTACH
+{
+ uint32_t u32ClientId;
+ uint32_t u32DeviceId;
+} VRDESCARDNOTIFYATTACH;
+
+typedef struct VRDESCARDNOTIFYDETACH
+{
+ uint32_t u32ClientId;
+ uint32_t u32DeviceId;
+} VRDESCARDNOTIFYDETACH;
+
+
+/*
+ * IO request codes.
+ * Must be not 0, which is used internally.
+ */
+
+#define VRDE_SCARD_FN_ESTABLISHCONTEXT 1
+#define VRDE_SCARD_FN_LISTREADERS 2
+#define VRDE_SCARD_FN_RELEASECONTEXT 3
+#define VRDE_SCARD_FN_GETSTATUSCHANGE 4
+#define VRDE_SCARD_FN_CANCEL 5
+#define VRDE_SCARD_FN_CONNECT 6
+#define VRDE_SCARD_FN_RECONNECT 7
+#define VRDE_SCARD_FN_DISCONNECT 8
+#define VRDE_SCARD_FN_BEGINTRANSACTION 9
+#define VRDE_SCARD_FN_ENDTRANSACTION 10
+#define VRDE_SCARD_FN_STATE 11
+#define VRDE_SCARD_FN_STATUS 12
+#define VRDE_SCARD_FN_TRANSMIT 13
+#define VRDE_SCARD_FN_CONTROL 14
+#define VRDE_SCARD_FN_GETATTRIB 15
+#define VRDE_SCARD_FN_SETATTRIB 16
+
+#define VRDE_SCARD_MAX_READERS 10
+#define VRDE_SCARD_MAX_ATR_LENGTH 36
+#define VRDE_SCARD_MAX_PCI_DATA 1024
+
+#define VRDE_SCARD_S_SUCCESS 0x00000000
+#define VRDE_SCARD_F_INTERNAL_ERROR 0x80100001
+#define VRDE_SCARD_E_CANCELLED 0x80100002
+#define VRDE_SCARD_E_INVALID_HANDLE 0x80100003
+#define VRDE_SCARD_E_INVALID_PARAMETER 0x80100004
+#define VRDE_SCARD_E_INVALID_TARGET 0x80100005
+#define VRDE_SCARD_E_NO_MEMORY 0x80100006
+#define VRDE_SCARD_F_WAITED_TOO_LONG 0x80100007
+#define VRDE_SCARD_E_INSUFFICIENT_BUFFER 0x80100008
+#define VRDE_SCARD_E_UNKNOWN_READER 0x80100009
+#define VRDE_SCARD_E_TIMEOUT 0x8010000A
+#define VRDE_SCARD_E_SHARING_VIOLATION 0x8010000B
+#define VRDE_SCARD_E_NO_SMARTCARD 0x8010000C
+#define VRDE_SCARD_E_UNKNOWN_CARD 0x8010000D
+#define VRDE_SCARD_E_CANT_DISPOSE 0x8010000E
+#define VRDE_SCARD_E_PROTO_MISMATCH 0x8010000F
+#define VRDE_SCARD_E_NOT_READY 0x80100010
+#define VRDE_SCARD_E_INVALID_VALUE 0x80100011
+#define VRDE_SCARD_E_SYSTEM_CANCELLED 0x80100012
+#define VRDE_SCARD_F_COMM_ERROR 0x80100013
+#define VRDE_SCARD_F_UNKNOWN_ERROR 0x80100014
+#define VRDE_SCARD_E_INVALID_ATR 0x80100015
+#define VRDE_SCARD_E_NOT_TRANSACTED 0x80100016
+#define VRDE_SCARD_E_READER_UNAVAILABLE 0x80100017
+#define VRDE_SCARD_P_SHUTDOWN 0x80100018
+#define VRDE_SCARD_E_PCI_TOO_SMALL 0x80100019
+#define VRDE_SCARD_E_ICC_INSTALLATION 0x80100020
+#define VRDE_SCARD_E_ICC_CREATEORDER 0x80100021
+#define VRDE_SCARD_E_UNSUPPORTED_FEATURE 0x80100022
+#define VRDE_SCARD_E_DIR_NOT_FOUND 0x80100023
+#define VRDE_SCARD_E_FILE_NOT_FOUND 0x80100024
+#define VRDE_SCARD_E_NO_DIR 0x80100025
+#define VRDE_SCARD_E_READER_UNSUPPORTED 0x8010001A
+#define VRDE_SCARD_E_DUPLICATE_READER 0x8010001B
+#define VRDE_SCARD_E_CARD_UNSUPPORTED 0x8010001C
+#define VRDE_SCARD_E_NO_SERVICE 0x8010001D
+#define VRDE_SCARD_E_SERVICE_STOPPED 0x8010001E
+#define VRDE_SCARD_E_UNEXPECTED 0x8010001F
+#define VRDE_SCARD_E_NO_FILE 0x80100026
+#define VRDE_SCARD_E_NO_ACCESS 0x80100027
+#define VRDE_SCARD_E_WRITE_TOO_MANY 0x80100028
+#define VRDE_SCARD_E_BAD_SEEK 0x80100029
+#define VRDE_SCARD_E_INVALID_CHV 0x8010002A
+#define VRDE_SCARD_E_UNKNOWN_RES_MSG 0x8010002B
+#define VRDE_SCARD_E_NO_SUCH_CERTIFICATE 0x8010002C
+#define VRDE_SCARD_E_CERTIFICATE_UNAVAILABLE 0x8010002D
+#define VRDE_SCARD_E_NO_READERS_AVAILABLE 0x8010002E
+#define VRDE_SCARD_E_COMM_DATA_LOST 0x8010002F
+#define VRDE_SCARD_E_NO_KEY_CONTAINER 0x80100030
+#define VRDE_SCARD_E_SERVER_TOO_BUSY 0x80100031
+#define VRDE_SCARD_E_PIN_CACHE_EXPIRED 0x80100032
+#define VRDE_SCARD_E_NO_PIN_CACHE 0x80100033
+#define VRDE_SCARD_E_READ_ONLY_CARD 0x80100034
+#define VRDE_SCARD_W_UNSUPPORTED_CARD 0x80100065
+#define VRDE_SCARD_W_UNRESPONSIVE_CARD 0x80100066
+#define VRDE_SCARD_W_UNPOWERED_CARD 0x80100067
+#define VRDE_SCARD_W_RESET_CARD 0x80100068
+#define VRDE_SCARD_W_REMOVED_CARD 0x80100069
+#define VRDE_SCARD_W_SECURITY_VIOLATION 0x8010006A
+#define VRDE_SCARD_W_WRONG_CHV 0x8010006B
+#define VRDE_SCARD_W_CHV_BLOCKED 0x8010006C
+#define VRDE_SCARD_W_EOF 0x8010006D
+#define VRDE_SCARD_W_CANCELLED_BY_USER 0x8010006E
+#define VRDE_SCARD_W_CARD_NOT_AUTHENTICATED 0x8010006F
+#define VRDE_SCARD_W_CACHE_ITEM_NOT_FOUND 0x80100070
+#define VRDE_SCARD_W_CACHE_ITEM_STALE 0x80100071
+#define VRDE_SCARD_W_CACHE_ITEM_TOO_BIG 0x80100072
+
+#define VRDE_SCARD_STATE_UNAWARE 0x0000
+#define VRDE_SCARD_STATE_IGNORE 0x0001
+#define VRDE_SCARD_STATE_CHANGED 0x0002
+#define VRDE_SCARD_STATE_UNKNOWN 0x0004
+#define VRDE_SCARD_STATE_UNAVAILABLE 0x0008
+#define VRDE_SCARD_STATE_EMPTY 0x0010
+#define VRDE_SCARD_STATE_PRESENT 0x0020
+#define VRDE_SCARD_STATE_ATRMATCH 0x0040
+#define VRDE_SCARD_STATE_EXCLUSIVE 0x0080
+#define VRDE_SCARD_STATE_INUSE 0x0100
+#define VRDE_SCARD_STATE_MUTE 0x0200
+#define VRDE_SCARD_STATE_UNPOWERED 0x0400
+#define VRDE_SCARD_STATE_MASK UINT32_C(0x0000FFFF)
+#define VRDE_SCARD_STATE_COUNT_MASK UINT32_C(0xFFFF0000)
+
+#define VRDE_SCARD_PROTOCOL_UNDEFINED 0x00000000
+#define VRDE_SCARD_PROTOCOL_T0 0x00000001
+#define VRDE_SCARD_PROTOCOL_T1 0x00000002
+#define VRDE_SCARD_PROTOCOL_Tx 0x00000003
+#define VRDE_SCARD_PROTOCOL_RAW 0x00010000
+
+#define VRDE_SCARD_PROTOCOL_DEFAULT 0x80000000
+#define VRDE_SCARD_PROTOCOL_OPTIMAL 0x00000000
+
+#define VRDE_SCARD_SHARE_EXCLUSIVE 0x00000001
+#define VRDE_SCARD_SHARE_SHARED 0x00000002
+#define VRDE_SCARD_SHARE_DIRECT 0x00000003
+
+/* u32Initialization, u32Disposition */
+#define VRDE_SCARD_LEAVE_CARD 0x00000000
+#define VRDE_SCARD_RESET_CARD 0x00000001
+#define VRDE_SCARD_UNPOWER_CARD 0x00000002
+#define VRDE_SCARD_EJECT_CARD 0x00000003
+
+/* VRDESCARDSTATUSRSP::u32State */
+#define VRDE_SCARD_UNKNOWN 0x00000000
+#define VRDE_SCARD_ABSENT 0x00000001
+#define VRDE_SCARD_PRESENT 0x00000002
+#define VRDE_SCARD_SWALLOWED 0x00000003
+#define VRDE_SCARD_POWERED 0x00000004
+#define VRDE_SCARD_NEGOTIABLE 0x00000005
+#define VRDE_SCARD_SPECIFICMODE 0x00000006
+
+
+/*
+ * IO request data structures.
+ */
+typedef struct VRDESCARDCONTEXT
+{
+ uint32_t u32ContextSize;
+ uint8_t au8Context[16];
+} VRDESCARDCONTEXT;
+
+typedef struct VRDESCARDHANDLE
+{
+ VRDESCARDCONTEXT Context;
+ uint32_t u32HandleSize;
+ uint8_t au8Handle[16];
+} VRDESCARDHANDLE;
+
+typedef struct VRDESCARDREADERSTATECALL
+{
+ char *pszReader; /* UTF8 */
+ uint32_t u32CurrentState; /* VRDE_SCARD_STATE_* */
+} VRDESCARDREADERSTATECALL;
+
+typedef struct VRDESCARDREADERSTATERETURN
+{
+ uint32_t u32CurrentState; /* VRDE_SCARD_STATE_* */
+ uint32_t u32EventState; /* VRDE_SCARD_STATE_* */
+ uint32_t u32AtrLength;
+ uint8_t au8Atr[VRDE_SCARD_MAX_ATR_LENGTH];
+} VRDESCARDREADERSTATERETURN;
+
+typedef struct VRDESCARDPCI
+{
+ uint32_t u32Protocol; /* VRDE_SCARD_PROTOCOL_* */
+ uint32_t u32PciLength; /* Includes u32Protocol and u32PciLength fields. 8 if no data in au8PciData. */
+ uint8_t au8PciData[VRDE_SCARD_MAX_PCI_DATA];
+} VRDESCARDPCI;
+
+typedef struct VRDESCARDESTABLISHCONTEXTREQ
+{
+ uint32_t u32ClientId;
+ uint32_t u32DeviceId;
+} VRDESCARDESTABLISHCONTEXTREQ;
+
+typedef struct VRDESCARDESTABLISHCONTEXTRSP
+{
+ uint32_t u32ReturnCode;
+ VRDESCARDCONTEXT Context;
+} VRDESCARDESTABLISHCONTEXTRSP;
+
+typedef struct VRDESCARDLISTREADERSREQ
+{
+ VRDESCARDCONTEXT Context;
+} VRDESCARDLISTREADERSREQ;
+
+typedef struct VRDESCARDLISTREADERSRSP
+{
+ uint32_t u32ReturnCode;
+ uint32_t cReaders;
+ char *apszNames[VRDE_SCARD_MAX_READERS]; /* UTF8 */
+} VRDESCARDLISTREADERSRSP;
+
+typedef struct VRDESCARDRELEASECONTEXTREQ
+{
+ VRDESCARDCONTEXT Context;
+} VRDESCARDRELEASECONTEXTREQ;
+
+typedef struct VRDESCARDRELEASECONTEXTRSP
+{
+ uint32_t u32ReturnCode;
+} VRDESCARDRELEASECONTEXTRSP;
+
+typedef struct VRDESCARDGETSTATUSCHANGEREQ
+{
+ VRDESCARDCONTEXT Context;
+ uint32_t u32Timeout; /* Milliseconds. 0xFFFFFFFF = INFINITE */
+ uint32_t cReaders;
+ VRDESCARDREADERSTATECALL aReaderStates[VRDE_SCARD_MAX_READERS];
+} VRDESCARDGETSTATUSCHANGEREQ;
+
+typedef struct VRDESCARDGETSTATUSCHANGERSP
+{
+ uint32_t u32ReturnCode;
+ uint32_t cReaders;
+ VRDESCARDREADERSTATERETURN aReaderStates[VRDE_SCARD_MAX_READERS];
+} VRDESCARDGETSTATUSCHANGERSP;
+
+typedef struct VRDESCARDCANCELREQ
+{
+ VRDESCARDCONTEXT Context;
+} VRDESCARDCANCELREQ;
+
+typedef struct VRDESCARDCANCELRSP
+{
+ uint32_t u32ReturnCode;
+} VRDESCARDCANCELRSP;
+
+typedef struct VRDESCARDCONNECTREQ
+{
+ VRDESCARDCONTEXT Context;
+ char *pszReader; /* UTF8 */
+ uint32_t u32ShareMode; /* VRDE_SCARD_SHARE_* */
+ uint32_t u32PreferredProtocols;
+} VRDESCARDCONNECTREQ;
+
+typedef struct VRDESCARDCONNECTRSP
+{
+ uint32_t u32ReturnCode;
+ VRDESCARDHANDLE hCard;
+ uint32_t u32ActiveProtocol;
+} VRDESCARDCONNECTRSP;
+
+typedef struct VRDESCARDRECONNECTREQ
+{
+ VRDESCARDHANDLE hCard;
+ uint32_t u32ShareMode;
+ uint32_t u32PreferredProtocols;
+ uint32_t u32Initialization;
+} VRDESCARDRECONNECTREQ;
+
+typedef struct VRDESCARDRECONNECTRSP
+{
+ uint32_t u32ReturnCode;
+ uint32_t u32ActiveProtocol;
+} VRDESCARDRECONNECTRSP;
+
+typedef struct VRDESCARDDISCONNECTREQ
+{
+ VRDESCARDHANDLE hCard;
+ uint32_t u32Disposition;
+} VRDESCARDDISCONNECTREQ;
+
+typedef struct VRDESCARDDISCONNECTRSP
+{
+ uint32_t u32ReturnCode;
+} VRDESCARDDISCONNECTRSP;
+
+typedef struct VRDESCARDBEGINTRANSACTIONREQ
+{
+ VRDESCARDHANDLE hCard;
+ uint32_t u32Disposition;
+} VRDESCARDBEGINTRANSACTIONREQ;
+
+typedef struct VRDESCARDBEGINTRANSACTIONRSP
+{
+ uint32_t u32ReturnCode;
+} VRDESCARDBEGINTRANSACTIONRSP;
+
+typedef struct VRDESCARDENDTRANSACTIONREQ
+{
+ VRDESCARDHANDLE hCard;
+ uint32_t u32Disposition;
+} VRDESCARDENDTRANSACTIONREQ;
+
+typedef struct VRDESCARDENDTRANSACTIONRSP
+{
+ uint32_t u32ReturnCode;
+} VRDESCARDENDTRANSACTIONRSP;
+
+typedef struct VRDESCARDSTATEREQ
+{
+ VRDESCARDHANDLE hCard;
+} VRDESCARDSTATEREQ;
+
+typedef struct VRDESCARDSTATERSP
+{
+ uint32_t u32ReturnCode;
+ uint32_t u32State;
+ uint32_t u32Protocol;
+ uint32_t u32AtrLength;
+ uint8_t au8Atr[VRDE_SCARD_MAX_ATR_LENGTH];
+} VRDESCARDSTATERSP;
+
+typedef struct VRDESCARDSTATUSREQ
+{
+ VRDESCARDHANDLE hCard;
+} VRDESCARDSTATUSREQ;
+
+typedef struct VRDESCARDSTATUSRSP
+{
+ uint32_t u32ReturnCode;
+ char *szReader;
+ uint32_t u32State;
+ uint32_t u32Protocol;
+ uint32_t u32AtrLength;
+ uint8_t au8Atr[VRDE_SCARD_MAX_ATR_LENGTH];
+} VRDESCARDSTATUSRSP;
+
+typedef struct VRDESCARDTRANSMITREQ
+{
+ VRDESCARDHANDLE hCard;
+ VRDESCARDPCI ioSendPci;
+ uint32_t u32SendLength;
+ uint8_t *pu8SendBuffer;
+ uint32_t u32RecvLength;
+} VRDESCARDTRANSMITREQ;
+
+typedef struct VRDESCARDTRANSMITRSP
+{
+ uint32_t u32ReturnCode;
+ VRDESCARDPCI ioRecvPci;
+ uint32_t u32RecvLength;
+ uint8_t *pu8RecvBuffer;
+} VRDESCARDTRANSMITRSP;
+
+typedef struct VRDESCARDCONTROLREQ
+{
+ VRDESCARDHANDLE hCard;
+ uint32_t u32ControlCode;
+ uint32_t u32InBufferSize;
+ uint8_t *pu8InBuffer;
+ uint32_t u32OutBufferSize;
+} VRDESCARDCONTROLREQ;
+
+typedef struct VRDESCARDCONTROLRSP
+{
+ uint32_t u32ReturnCode;
+ uint32_t u32OutBufferSize;
+ uint8_t *pu8OutBuffer;
+} VRDESCARDCONTROLRSP;
+
+typedef struct VRDESCARDGETATTRIBREQ
+{
+ VRDESCARDHANDLE hCard;
+ uint32_t u32AttrId;
+ uint32_t u32AttrLen;
+} VRDESCARDGETATTRIBREQ;
+
+typedef struct VRDESCARDGETATTRIBRSP
+{
+ uint32_t u32ReturnCode;
+ uint32_t u32AttrLength;
+ uint8_t *pu8Attr;
+} VRDESCARDGETATTRIBRSP;
+
+typedef struct VRDESCARDSETATTRIBREQ
+{
+ VRDESCARDHANDLE hCard;
+ uint32_t u32AttrId;
+ uint32_t u32AttrLen;
+ uint8_t *pu8Attr;
+} VRDESCARDSETATTRIBREQ;
+
+typedef struct VRDESCARDSETATTRIBRSP
+{
+ uint32_t u32ReturnCode;
+} VRDESCARDSETATTRIBRSP;
+
+#endif /* !VBOX_INCLUDED_RemoteDesktop_VRDESCard_h */
diff --git a/include/VBox/RemoteDesktop/VRDETSMF.h b/include/VBox/RemoteDesktop/VRDETSMF.h
new file mode 100644
index 00000000..40fb9d5b
--- /dev/null
+++ b/include/VBox/RemoteDesktop/VRDETSMF.h
@@ -0,0 +1,154 @@
+/* @file
+ * VBox Remote Desktop Extension (VRDE) - raw TSMF dynamic channel interface.
+ */
+
+/*
+ * Copyright (C) 2012-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_RemoteDesktop_VRDETSMF_h
+#define VBOX_INCLUDED_RemoteDesktop_VRDETSMF_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/RemoteDesktop/VRDE.h>
+
+/*
+ * Interface creating a TSMF dynamic channel instances and sending/receving data.
+ *
+ * Async callbacks are used for providing feedback, reporting errors, etc.
+ */
+
+#define VRDE_TSMF_INTERFACE_NAME "TSMFRAW"
+
+/* The VRDE server TSMF interface entry points. Interface version 1. */
+typedef struct VRDETSMFINTERFACE
+{
+ /* The header. */
+ VRDEINTERFACEHDR header;
+
+ /* Create a new TSMF channel instance.
+ * The channel is created only for one client, which is connected to the server.
+ * The client is the first which supports dynamic RDP channels.
+ *
+ * If this method return success then the server will use the VRDE_TSMF_N_CREATE_*
+ * notification to report the channel handle.
+ *
+ * @param hServer The VRDE server instance.
+ * @param pvChannel A context to be associated with the channel.
+ * @param u32Flags VRDE_TSMF_F_*
+ *
+ * @return IPRT status code.
+ */
+ DECLR3CALLBACKMEMBER(int, VRDETSMFChannelCreate, (HVRDESERVER hServer,
+ void *pvChannel,
+ uint32_t u32Flags));
+
+ /* Close a TSMF channel instance.
+ *
+ * @param hServer The VRDE server instance.
+ * @param u32ChannelHandle Which channel to close.
+ *
+ * @return IPRT status code.
+ */
+ DECLR3CALLBACKMEMBER(int, VRDETSMFChannelClose, (HVRDESERVER hServer,
+ uint32_t u32ChannelHandle));
+
+ /* Send data to the TSMF channel instance.
+ *
+ * @param hServer The VRDE server instance.
+ * @param u32ChannelHandle Channel to send data.
+ * @param pvData Raw data to be sent, the format depends on which
+ * u32Flags were specified in Create: TSMF message,
+ * or channel header + TSMF message.
+ * @param cbData Size of data.
+ *
+ * @return IPRT status code.
+ */
+ DECLR3CALLBACKMEMBER(int, VRDETSMFChannelSend, (HVRDESERVER hServer,
+ uint32_t u32ChannelHandle,
+ const void *pvData,
+ uint32_t cbData));
+} VRDETSMFINTERFACE;
+
+/* TSMF interface callbacks. */
+typedef struct VRDETSMFCALLBACKS
+{
+ /* The header. */
+ VRDEINTERFACEHDR header;
+
+ /* Channel event notification.
+ *
+ * @param pvContext The callbacks context specified in VRDEGetInterface.
+ * @param u32Notification The kind of the notification: VRDE_TSMF_N_*.
+ * @param pvChannel A context which was used in VRDETSMFChannelCreate.
+ * @param pvParm The notification specific data.
+ * @param cbParm The size of buffer pointed by pvParm.
+ *
+ * @return IPRT status code.
+ */
+ DECLR3CALLBACKMEMBER(void, VRDETSMFCbNotify, (void *pvContext,
+ uint32_t u32Notification,
+ void *pvChannel,
+ const void *pvParm,
+ uint32_t cbParm));
+} VRDETSMFCALLBACKS;
+
+
+/* VRDETSMFChannelCreate::u32Flags */
+#define VRDE_TSMF_F_CHANNEL_HEADER 0x00000001
+
+
+/* VRDETSMFCbNotify::u32Notification */
+#define VRDE_TSMF_N_CREATE_ACCEPTED 1
+#define VRDE_TSMF_N_CREATE_DECLINED 2
+#define VRDE_TSMF_N_DATA 3 /* Data received. */
+#define VRDE_TSMF_N_DISCONNECTED 4 /* The channel is not connected anymore. */
+
+
+/*
+ * Notification parameters.
+ */
+
+/* VRDE_TSMF_N_CREATE_ACCEPTED */
+typedef struct VRDETSMFNOTIFYCREATEACCEPTED
+{
+ uint32_t u32ChannelHandle;
+} VRDETSMFNOTIFYCREATEACCEPTED;
+
+/* VRDE_TSMF_N_EVENT_DATA */
+typedef struct VRDETSMFNOTIFYDATA
+{
+ const void *pvData;
+ uint32_t cbData; /* How many bytes available. */
+} VRDETSMFNOTIFYDATA;
+
+#endif /* !VBOX_INCLUDED_RemoteDesktop_VRDETSMF_h */
diff --git a/include/VBox/RemoteDesktop/VRDEVideoIn.h b/include/VBox/RemoteDesktop/VRDEVideoIn.h
new file mode 100644
index 00000000..07c45579
--- /dev/null
+++ b/include/VBox/RemoteDesktop/VRDEVideoIn.h
@@ -0,0 +1,1093 @@
+/** @file
+ * VBox Remote Desktop Extension (VRDE) - Video Input interface.
+ */
+
+/*
+ * Copyright (C) 2012-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_RemoteDesktop_VRDEVideoIn_h
+#define VBOX_INCLUDED_RemoteDesktop_VRDEVideoIn_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+
+/* Define VRDE_VIDEOIN_WITH_VRDEINTERFACE to include the server VRDE interface parts. */
+
+#ifdef VRDE_VIDEOIN_WITH_VRDEINTERFACE
+# include <VBox/RemoteDesktop/VRDE.h>
+#endif /* VRDE_VIDEOIN_WITH_VRDEINTERFACE */
+
+#ifdef AssertCompileSize
+# define ASSERTSIZE(type, size) AssertCompileSize(type, size);
+#else
+# define ASSERTSIZE(type, size)
+#endif /* AssertCompileSize */
+
+#include <iprt/types.h>
+
+
+/*
+ * Interface for accessing a video camera device on the client.
+ *
+ * Async callbacks are used for providing feedback, reporting errors, etc.
+ *
+ * Initial version supports: Camera + Processing Unit + Streaming Control.
+ *
+ * There are 2 modes:
+ * 1) The virtual WebCam is already attached to the guest.
+ * 2) The virtual WebCam will be attached when the client has it.
+ *
+ * Initially the mode 1 is supported.
+ *
+ * Mode 1 details:
+ * The WebCam has some fixed functionality, according to the descriptors,
+ * which has been already read by the guest. So some of functions will
+ * not work if the client does not support them.
+ *
+ * Mode 2 details:
+ * Virtual WebCam descriptors are built from the client capabilities.
+ *
+ * Similarly to the smartcard, the server will inform the ConsoleVRDE that there is a WebCam.
+ * ConsoleVRDE creates a VRDEVIDEOIN handle and forwards virtual WebCam requests to it.
+ *
+ * Interface with VBox.
+ *
+ * Virtual WebCam ConsoleVRDE VRDE
+ *
+ * Negotiate <->
+ * <- VideoInDeviceNotify(Attached, DeviceId)
+ * -> GetDeviceDesc
+ * <- DeviceDesc
+ * 2 <- CreateCamera
+ * 2 CameraCreated ->
+ *
+ * CameraRequest -> Request ->
+ * Response <- <- Response <- Response
+ * Frame <- <- Frame <- Frame
+ * <- VideoInDeviceNotify(Detached, DeviceId)
+ *
+ * Unsupported requests fail.
+ * The Device Description received from the client may be used to validate WebCam requests
+ * in the ConsoleVRDE code, for example filter out unsupported requests.
+ *
+ */
+
+/* All structures in this file are packed.
+ * Everything is little-endian.
+ */
+#pragma pack(1)
+
+/*
+ * The interface supports generic video input descriptors, capabilities and controls:
+ * * Descriptors
+ * + Interface
+ * - Input, Camera Terminal
+ * - Processing Unit
+ * + Video Streaming
+ * - Input Header
+ * - Payload Format
+ * - Video Frame
+ * - Still Image Frame
+ * * Video Control requests
+ * + Interface
+ * - Power Mode
+ * + Unit and Terminal
+ * camera
+ * - Scanning Mode (interlaced, progressive)
+ * - Auto-Exposure Mode
+ * - Auto-Exposure Priority
+ * - Exposure Time Absolute, Relative
+ * - Focus Absolute, Relative, Auto
+ * - Iris Absolute, Relative
+ * - Zoom Absolute, Relative
+ * - PanTilt Absolute, Relative
+ * - Roll Absolute, Relative
+ * - Privacy
+ * processing
+ * - Backlight Compensation
+ * - Brightness
+ * - Contrast
+ * - Gain
+ * - Power Line Frequency
+ * - Hue Manual, Auto
+ * - Saturation
+ * - Sharpness
+ * - Gamma
+ * - White Balance Temperature Manual, Auto
+ * - White Balance Component Manual, Auto
+ * - Digital Multiplier
+ * - Digital Multiplier Limit
+ * * Video Streaming requests
+ * + Interface
+ * - Synch Delay
+ * - Still Image Trigger
+ * - Generate Key Frame
+ * - Update Frame Segment
+ * - Stream Error Code
+ *
+ *
+ * Notes:
+ * * still capture uses a method similar to method 2, because the still frame will
+ * be send instead of video over the channel.
+ * Also the method 2 can be in principle emulated by both 1 and 3 on the client.
+ * However the client can initiate a still frame transfer, similar to hardware button trigger.
+ * * all control changes are async.
+ * * probe/commit are not used. The server can select a supported format/frame from the list.
+ * * no color matching. sRGB is the default.
+ * * most of constants are the same as in USB Video Class spec, but they are not the same and
+ * should be always converted.
+ */
+
+/*
+ * The DEVICEDEC describes the device and provides a list of supported formats:
+ * VRDEVIDEOINDEVICEDESC
+ * VRDEVIDEOINFORMATDESC[0];
+ * VRDEVIDEOINFRAMEDESC[0..N-1]
+ * VRDEVIDEOINFORMATDESC[1];
+ * VRDEVIDEOINFRAMEDESC[0..M-1]
+ * ...
+ */
+
+typedef struct VRDEVIDEOINDEVICEDESC
+{
+ uint16_t u16ObjectiveFocalLengthMin;
+ uint16_t u16ObjectiveFocalLengthMax;
+ uint16_t u16OcularFocalLength;
+ uint16_t u16MaxMultiplier;
+ uint32_t fu32CameraControls; /* VRDE_VIDEOIN_F_CT_CTRL_* */
+ uint32_t fu32ProcessingControls; /* VRDE_VIDEOIN_F_PU_CTRL_* */
+ uint8_t fu8DeviceCaps; /* VRDE_VIDEOIN_F_DEV_CAP_* */
+ uint8_t u8NumFormats; /* Number of following VRDEVIDEOINFORMATDESC structures. */
+ uint16_t cbExt; /* Size of the optional extended description. */
+ /* An extended description may follow. */
+ /* An array of VRDEVIDEOINFORMATDESC follows. */
+} VRDEVIDEOINDEVICEDESC;
+
+/* VRDEVIDEOINDEVICEDESC::fu32CameraControls */
+#define VRDE_VIDEOIN_F_CT_CTRL_SCANNING_MODE 0x00000001 /* D0: Scanning Mode */
+#define VRDE_VIDEOIN_F_CT_CTRL_AE_MODE 0x00000002 /* D1: Auto-Exposure Mode */
+#define VRDE_VIDEOIN_F_CT_CTRL_AE_PRIORITY 0x00000004 /* D2: Auto-Exposure Priority */
+#define VRDE_VIDEOIN_F_CT_CTRL_EXPOSURE_TIME_ABSOLUTE 0x00000008 /* D3: Exposure Time (Absolute) */
+#define VRDE_VIDEOIN_F_CT_CTRL_EXPOSURE_TIME_RELATIVE 0x00000010 /* D4: Exposure Time (Relative) */
+#define VRDE_VIDEOIN_F_CT_CTRL_FOCUS_ABSOLUTE 0x00000020 /* D5: Focus (Absolute) */
+#define VRDE_VIDEOIN_F_CT_CTRL_FOCUS_RELATIVE 0x00000040 /* D6: Focus (Relative) */
+#define VRDE_VIDEOIN_F_CT_CTRL_IRIS_ABSOLUTE 0x00000080 /* D7: Iris (Absolute) */
+#define VRDE_VIDEOIN_F_CT_CTRL_IRIS_RELATIVE 0x00000100 /* D8: Iris (Relative) */
+#define VRDE_VIDEOIN_F_CT_CTRL_ZOOM_ABSOLUTE 0x00000200 /* D9: Zoom (Absolute) */
+#define VRDE_VIDEOIN_F_CT_CTRL_ZOOM_RELATIVE 0x00000400 /* D10: Zoom (Relative) */
+#define VRDE_VIDEOIN_F_CT_CTRL_PANTILT_ABSOLUTE 0x00000800 /* D11: PanTilt (Absolute) */
+#define VRDE_VIDEOIN_F_CT_CTRL_PANTILT_RELATIVE 0x00001000 /* D12: PanTilt (Relative) */
+#define VRDE_VIDEOIN_F_CT_CTRL_ROLL_ABSOLUTE 0x00002000 /* D13: Roll (Absolute) */
+#define VRDE_VIDEOIN_F_CT_CTRL_ROLL_RELATIVE 0x00004000 /* D14: Roll (Relative) */
+#define VRDE_VIDEOIN_F_CT_CTRL_RESERVED1 0x00008000 /* D15: Reserved */
+#define VRDE_VIDEOIN_F_CT_CTRL_RESERVED2 0x00010000 /* D16: Reserved */
+#define VRDE_VIDEOIN_F_CT_CTRL_FOCUS_AUTO 0x00020000 /* D17: Focus, Auto */
+#define VRDE_VIDEOIN_F_CT_CTRL_PRIVACY 0x00040000 /* D18: Privacy */
+
+/* VRDEVIDEOINDEVICEDESC::fu32ProcessingControls */
+#define VRDE_VIDEOIN_F_PU_CTRL_BRIGHTNESS 0x00000001 /* D0: Brightness */
+#define VRDE_VIDEOIN_F_PU_CTRL_CONTRAST 0x00000002 /* D1: Contrast */
+#define VRDE_VIDEOIN_F_PU_CTRL_HUE 0x00000004 /* D2: Hue */
+#define VRDE_VIDEOIN_F_PU_CTRL_SATURATION 0x00000008 /* D3: Saturation */
+#define VRDE_VIDEOIN_F_PU_CTRL_SHARPNESS 0x00000010 /* D4: Sharpness */
+#define VRDE_VIDEOIN_F_PU_CTRL_GAMMA 0x00000020 /* D5: Gamma */
+#define VRDE_VIDEOIN_F_PU_CTRL_WHITE_BALANCE_TEMPERATURE 0x00000040 /* D6: White Balance Temperature */
+#define VRDE_VIDEOIN_F_PU_CTRL_WHITE_BALANCE_COMPONENT 0x00000080 /* D7: White Balance Component */
+#define VRDE_VIDEOIN_F_PU_CTRL_BACKLIGHT_COMPENSATION 0x00000100 /* D8: Backlight Compensation */
+#define VRDE_VIDEOIN_F_PU_CTRL_GAIN 0x00000200 /* D9: Gain */
+#define VRDE_VIDEOIN_F_PU_CTRL_POWER_LINE_FREQUENCY 0x00000400 /* D10: Power Line Frequency */
+#define VRDE_VIDEOIN_F_PU_CTRL_HUE_AUTO 0x00000800 /* D11: Hue, Auto */
+#define VRDE_VIDEOIN_F_PU_CTRL_WHITE_BALANCE_TEMPERATURE_AUTO 0x00001000 /* D12: White Balance Temperature, Auto */
+#define VRDE_VIDEOIN_F_PU_CTRL_WHITE_BALANCE_COMPONENT_AUTO 0x00002000 /* D13: White Balance Component, Auto */
+#define VRDE_VIDEOIN_F_PU_CTRL_DIGITAL_MULTIPLIER 0x00004000 /* D14: Digital Multiplier */
+#define VRDE_VIDEOIN_F_PU_CTRL_DIGITAL_MULTIPLIER_LIMIT 0x00008000 /* D15: Digital Multiplier Limit */
+
+/* VRDEVIDEOINDEVICEDESC::fu8DeviceCaps */
+#define VRDE_VIDEOIN_F_DEV_CAP_DYNAMICCHANGE 0x01 /* Whether dynamic format change is supported. */
+#define VRDE_VIDEOIN_F_DEV_CAP_TRIGGER 0x02 /* Whether hardware triggering is supported. */
+#define VRDE_VIDEOIN_F_DEV_CAP_TRIGGER_USAGE 0x04 /* 0 - still image, 1 - generic button event.*/
+
+/* VRDEVIDEOINDEVICEDESC extended description. */
+typedef struct VRDEVIDEOINDEVICEEXT
+{
+ uint32_t fu32Fields;
+ /* One or more VRDEVIDEOINDEVICEFIELD follow. */
+} VRDEVIDEOINDEVICEEXT;
+
+typedef struct VRDEVIDEOINDEVICEFIELDHDR
+{
+ uint16_t cbField; /* Number of bytes reserved for this field. */
+} VRDEVIDEOINDEVICEFIELDHDR;
+
+/* VRDEVIDEOINDEVICEDESC::fu32Fields */
+#define VRDE_VIDEOIN_F_DEV_EXT_NAME 0x00000001 /* Utf8 device name. */
+#define VRDE_VIDEOIN_F_DEV_EXT_SERIAL 0x00000002 /* Utf8 device serial number. */
+
+/* The video format descriptor. */
+typedef struct VRDEVIDEOINFORMATDESC
+{
+ uint16_t cbFormat; /* Size of the structure including cbFormat and format specific data. */
+ uint8_t u8FormatId; /* The unique identifier of the format on the client. */
+ uint8_t u8FormatType; /* MJPEG etc. VRDE_VIDEOIN_FORMAT_* */
+ uint8_t u8FormatFlags; /* VRDE_VIDEOIN_F_FMT_* */
+ uint8_t u8NumFrames; /* Number of following VRDEVIDEOINFRAMEDESC structures. */
+ uint16_t u16Reserved; /* Must be set to 0. */
+ /* Other format specific data may follow. */
+ /* An array of VRDEVIDEOINFRAMEDESC follows. */
+} VRDEVIDEOINFORMATDESC;
+
+/* VRDEVIDEOINFORMATDESC::u8FormatType */
+#define VRDE_VIDEOIN_FORMAT_UNCOMPRESSED 0x04
+#define VRDE_VIDEOIN_FORMAT_MJPEG 0x06
+#define VRDE_VIDEOIN_FORMAT_MPEG2TS 0x0A
+#define VRDE_VIDEOIN_FORMAT_DV 0x0C
+#define VRDE_VIDEOIN_FORMAT_FRAME_BASED 0x10
+#define VRDE_VIDEOIN_FORMAT_STREAM_BASED 0x12
+
+/* VRDEVIDEOINFORMATDESC::u8FormatFlags. */
+#define VRDE_VIDEOIN_F_FMT_GENERATEKEYFRAME 0x01 /* Supports Generate Key Frame */
+#define VRDE_VIDEOIN_F_FMT_UPDATEFRAMESEGMENT 0x02 /* Supports Update Frame Segment */
+#define VRDE_VIDEOIN_F_FMT_COPYPROTECT 0x04 /* If duplication should be restricted. */
+#define VRDE_VIDEOIN_F_FMT_COMPQUALITY 0x08 /* If the format supports an adjustable compression quality. */
+
+typedef struct VRDEVIDEOINFRAMEDESC
+{
+ uint16_t cbFrame; /* Size of the structure including cbFrame and frame specific data. */
+ uint8_t u8FrameId; /* The unique identifier of the frame for the corresponding format on the client. */
+ uint8_t u8FrameFlags;
+ uint16_t u16Width;
+ uint16_t u16Height;
+ uint32_t u32NumFrameIntervals; /* The number of supported frame intervals. */
+ uint32_t u32MinFrameInterval; /* Shortest frame interval supported (at highest frame rate), in 100ns units. */
+ uint32_t u32MaxFrameInterval; /* Longest frame interval supported (at lowest frame rate), in 100ns units. */
+ /* Supported frame intervals (in 100ns units) follow if VRDE_VIDEOIN_F_FRM_DISCRETE_INTERVALS is set.
+ * uint32_t au32FrameIntervals[u32NumFrameIntervals];
+ */
+ /* Supported min and max bitrate in bits per second follow if VRDE_VIDEOIN_F_FRM_BITRATE is set.
+ * uint32_t u32MinBitRate;
+ * uint32_t u32MaxBitRate;
+ */
+ /* Other frame specific data may follow. */
+} VRDEVIDEOINFRAMEDESC;
+
+/* VRDEVIDEOINFRAMEDESC::u8FrameFlags. */
+#define VRDE_VIDEOIN_F_FRM_STILL 0x01 /* If still images are supported for this frame. */
+#define VRDE_VIDEOIN_F_FRM_DISCRETE_INTERVALS 0x02 /* If the discrete intervals list is included. */
+#define VRDE_VIDEOIN_F_FRM_BITRATE 0x04 /* If the bitrate fields are included. */
+#define VRDE_VIDEOIN_F_FRM_SIZE_OF_FIELDS 0x08 /* If the all optional fields start with 16 bit field size. */
+
+/*
+ * Controls.
+ *
+ * The same structures are used for both SET and GET requests.
+ * Requests are async. A callback is invoked, when the client returns a reply.
+ * A control change notification also uses these structures.
+ *
+ * If a control request can not be fulfilled, then VRDE_VIDEOIN_CTRLHDR_F_FAIL
+ * will be set and u8Status contains the error code. This replaces the VC_REQUEST_ERROR_CODE_CONTROL.
+ *
+ * If the client receives an unsupported control, then the client must ignore it.
+ * That is the control request must not affect the client in any way.
+ * The client may send a VRDEVIDEOINCTRLHDR response for the unsupported control with:
+ * u16ControlSelector = the received value;
+ * u16RequestType = the received value;
+ * u16ParmSize = 0;
+ * u8Flags = VRDE_VIDEOIN_CTRLHDR_F_FAIL;
+ * u8Status = VRDE_VIDEOIN_CTRLHDR_STATUS_INVALIDCONTROL;
+ */
+
+typedef struct VRDEVIDEOINCTRLHDR
+{
+ uint16_t u16ControlSelector; /* VRDE_VIDEOIN_CTRLSEL_* */
+ uint16_t u16RequestType; /* VRDE_VIDEOIN_CTRLREQ_* */
+ uint16_t u16ParmSize; /* The size of the control specific parameters. */
+ uint8_t u8Flags; /* VRDE_VIDEOIN_CTRLHDR_F_* */
+ uint8_t u8Status; /* VRDE_VIDEOIN_CTRLHDR_STATUS_* */
+ /* Control specific data follows. */
+} VRDEVIDEOINCTRLHDR;
+
+/* Control request types: VRDEVIDEOINCTRLHDR::u16RequestType. */
+#define VRDE_VIDEOIN_CTRLREQ_UNDEFINED 0x00
+#define VRDE_VIDEOIN_CTRLREQ_SET_CUR 0x01
+#define VRDE_VIDEOIN_CTRLREQ_GET_CUR 0x81
+#define VRDE_VIDEOIN_CTRLREQ_GET_MIN 0x82
+#define VRDE_VIDEOIN_CTRLREQ_GET_MAX 0x83
+#define VRDE_VIDEOIN_CTRLREQ_GET_RES 0x84
+#define VRDE_VIDEOIN_CTRLREQ_GET_LEN 0x85
+#define VRDE_VIDEOIN_CTRLREQ_GET_INFO 0x86
+#define VRDE_VIDEOIN_CTRLREQ_GET_DEF 0x87
+
+/* VRDEVIDEOINCTRLHDR::u8Flags */
+#define VRDE_VIDEOIN_CTRLHDR_F_NOTIFY 0x01 /* Control change notification, the attribute is derived from u16RequestType and F_FAIL. */
+#define VRDE_VIDEOIN_CTRLHDR_F_FAIL 0x02 /* The operation failed. Error code is in u8Status. */
+
+/* VRDEVIDEOINCTRLHDR::u8Status if the VRDE_VIDEOIN_CTRLHDR_F_FAIL is set. */
+#define VRDE_VIDEOIN_CTRLHDR_STATUS_SUCCESS 0x00 /**/
+#define VRDE_VIDEOIN_CTRLHDR_STATUS_NOTREADY 0x01 /* Not ready */
+#define VRDE_VIDEOIN_CTRLHDR_STATUS_WRONGSTATE 0x02 /* Wrong state */
+#define VRDE_VIDEOIN_CTRLHDR_STATUS_POWER 0x03 /* Power */
+#define VRDE_VIDEOIN_CTRLHDR_STATUS_OUTOFRANGE 0x04 /* Out of range */
+#define VRDE_VIDEOIN_CTRLHDR_STATUS_INVALIDUNIT 0x05 /* Invalid unit */
+#define VRDE_VIDEOIN_CTRLHDR_STATUS_INVALIDCONTROL 0x06 /* Invalid control */
+#define VRDE_VIDEOIN_CTRLHDR_STATUS_INVALIDREQUEST 0x07 /* Invalid request */
+#define VRDE_VIDEOIN_CTRLHDR_STATUS_UNKNOWN 0xFF /* Unknown */
+
+/* Control selectors. 16 bit. High byte is the category. Low byte is the identifier.*/
+#ifdef RT_MAKE_U16
+#define VRDE_VIDEOIN_CTRLSEL_MAKE(Lo, Hi) RT_MAKE_U16(Lo, Hi)
+#else
+#define VRDE_VIDEOIN_CTRLSEL_MAKE(Lo, Hi) ((uint16_t)( (uint16_t)((uint8_t)(Hi)) << 8 | (uint8_t)(Lo) ))
+#endif
+
+#define VRDE_VIDEOIN_CTRLSEL_VC(a) VRDE_VIDEOIN_CTRLSEL_MAKE(a, 0x01)
+#define VRDE_VIDEOIN_CTRLSEL_CT(a) VRDE_VIDEOIN_CTRLSEL_MAKE(a, 0x02)
+#define VRDE_VIDEOIN_CTRLSEL_PU(a) VRDE_VIDEOIN_CTRLSEL_MAKE(a, 0x03)
+#define VRDE_VIDEOIN_CTRLSEL_VS(a) VRDE_VIDEOIN_CTRLSEL_MAKE(a, 0x04)
+#define VRDE_VIDEOIN_CTRLSEL_HW(a) VRDE_VIDEOIN_CTRLSEL_MAKE(a, 0x05)
+#define VRDE_VIDEOIN_CTRLSEL_PROT(a) VRDE_VIDEOIN_CTRLSEL_MAKE(a, 0x06)
+
+#define VRDE_VIDEOIN_CTRLSEL_VC_VIDEO_POWER_MODE_CONTROL VRDE_VIDEOIN_CTRLSEL_VC(0x01)
+
+#define VRDE_VIDEOIN_CTRLSEL_CT_UNDEFINED VRDE_VIDEOIN_CTRLSEL_CT(0x00)
+#define VRDE_VIDEOIN_CTRLSEL_CT_SCANNING_MODE VRDE_VIDEOIN_CTRLSEL_CT(0x01)
+#define VRDE_VIDEOIN_CTRLSEL_CT_AE_MODE VRDE_VIDEOIN_CTRLSEL_CT(0x02)
+#define VRDE_VIDEOIN_CTRLSEL_CT_AE_PRIORITY VRDE_VIDEOIN_CTRLSEL_CT(0x03)
+#define VRDE_VIDEOIN_CTRLSEL_CT_EXPOSURE_TIME_ABSOLUTE VRDE_VIDEOIN_CTRLSEL_CT(0x04)
+#define VRDE_VIDEOIN_CTRLSEL_CT_EXPOSURE_TIME_RELATIVE VRDE_VIDEOIN_CTRLSEL_CT(0x05)
+#define VRDE_VIDEOIN_CTRLSEL_CT_FOCUS_ABSOLUTE VRDE_VIDEOIN_CTRLSEL_CT(0x06)
+#define VRDE_VIDEOIN_CTRLSEL_CT_FOCUS_RELATIVE VRDE_VIDEOIN_CTRLSEL_CT(0x07)
+#define VRDE_VIDEOIN_CTRLSEL_CT_FOCUS_AUTO VRDE_VIDEOIN_CTRLSEL_CT(0x08)
+#define VRDE_VIDEOIN_CTRLSEL_CT_IRIS_ABSOLUTE VRDE_VIDEOIN_CTRLSEL_CT(0x09)
+#define VRDE_VIDEOIN_CTRLSEL_CT_IRIS_RELATIVE VRDE_VIDEOIN_CTRLSEL_CT(0x0A)
+#define VRDE_VIDEOIN_CTRLSEL_CT_ZOOM_ABSOLUTE VRDE_VIDEOIN_CTRLSEL_CT(0x0B)
+#define VRDE_VIDEOIN_CTRLSEL_CT_ZOOM_RELATIVE VRDE_VIDEOIN_CTRLSEL_CT(0x0C)
+#define VRDE_VIDEOIN_CTRLSEL_CT_PANTILT_ABSOLUTE VRDE_VIDEOIN_CTRLSEL_CT(0x0D)
+#define VRDE_VIDEOIN_CTRLSEL_CT_PANTILT_RELATIVE VRDE_VIDEOIN_CTRLSEL_CT(0x0E)
+#define VRDE_VIDEOIN_CTRLSEL_CT_ROLL_ABSOLUTE VRDE_VIDEOIN_CTRLSEL_CT(0x0F)
+#define VRDE_VIDEOIN_CTRLSEL_CT_ROLL_RELATIVE VRDE_VIDEOIN_CTRLSEL_CT(0x10)
+#define VRDE_VIDEOIN_CTRLSEL_CT_PRIVACY VRDE_VIDEOIN_CTRLSEL_CT(0x11)
+
+#define VRDE_VIDEOIN_CTRLSEL_PU_UNDEFINED VRDE_VIDEOIN_CTRLSEL_PU(0x00)
+#define VRDE_VIDEOIN_CTRLSEL_PU_BACKLIGHT_COMPENSATION VRDE_VIDEOIN_CTRLSEL_PU(0x01)
+#define VRDE_VIDEOIN_CTRLSEL_PU_BRIGHTNESS VRDE_VIDEOIN_CTRLSEL_PU(0x02)
+#define VRDE_VIDEOIN_CTRLSEL_PU_CONTRAST VRDE_VIDEOIN_CTRLSEL_PU(0x03)
+#define VRDE_VIDEOIN_CTRLSEL_PU_GAIN VRDE_VIDEOIN_CTRLSEL_PU(0x04)
+#define VRDE_VIDEOIN_CTRLSEL_PU_POWER_LINE_FREQUENCY VRDE_VIDEOIN_CTRLSEL_PU(0x05)
+#define VRDE_VIDEOIN_CTRLSEL_PU_HUE VRDE_VIDEOIN_CTRLSEL_PU(0x06)
+#define VRDE_VIDEOIN_CTRLSEL_PU_SATURATION VRDE_VIDEOIN_CTRLSEL_PU(0x07)
+#define VRDE_VIDEOIN_CTRLSEL_PU_SHARPNESS VRDE_VIDEOIN_CTRLSEL_PU(0x08)
+#define VRDE_VIDEOIN_CTRLSEL_PU_GAMMA VRDE_VIDEOIN_CTRLSEL_PU(0x09)
+#define VRDE_VIDEOIN_CTRLSEL_PU_WHITE_BALANCE_TEMPERATURE VRDE_VIDEOIN_CTRLSEL_PU(0x0A)
+#define VRDE_VIDEOIN_CTRLSEL_PU_WHITE_BALANCE_TEMPERATURE_AUTO VRDE_VIDEOIN_CTRLSEL_PU(0x0B)
+#define VRDE_VIDEOIN_CTRLSEL_PU_WHITE_BALANCE_COMPONENT VRDE_VIDEOIN_CTRLSEL_PU(0x0C)
+#define VRDE_VIDEOIN_CTRLSEL_PU_WHITE_BALANCE_COMPONENT_AUTO VRDE_VIDEOIN_CTRLSEL_PU(0x0D)
+#define VRDE_VIDEOIN_CTRLSEL_PU_DIGITAL_MULTIPLIER VRDE_VIDEOIN_CTRLSEL_PU(0x0E)
+#define VRDE_VIDEOIN_CTRLSEL_PU_DIGITAL_MULTIPLIER_LIMIT VRDE_VIDEOIN_CTRLSEL_PU(0x0F)
+#define VRDE_VIDEOIN_CTRLSEL_PU_HUE_AUTO VRDE_VIDEOIN_CTRLSEL_PU(0x10)
+#define VRDE_VIDEOIN_CTRLSEL_PU_ANALOG_VIDEO_STANDARD VRDE_VIDEOIN_CTRLSEL_PU(0x11)
+#define VRDE_VIDEOIN_CTRLSEL_PU_ANALOG_LOCK_STATUS VRDE_VIDEOIN_CTRLSEL_PU(0x12)
+
+#define VRDE_VIDEOIN_CTRLSEL_VS_UNDEFINED VRDE_VIDEOIN_CTRLSEL_VS(0x00)
+#define VRDE_VIDEOIN_CTRLSEL_VS_SETUP VRDE_VIDEOIN_CTRLSEL_VS(0x01)
+#define VRDE_VIDEOIN_CTRLSEL_VS_OFF VRDE_VIDEOIN_CTRLSEL_VS(0x02)
+#define VRDE_VIDEOIN_CTRLSEL_VS_ON VRDE_VIDEOIN_CTRLSEL_VS(0x03)
+#define VRDE_VIDEOIN_CTRLSEL_VS_STILL_IMAGE_TRIGGER VRDE_VIDEOIN_CTRLSEL_VS(0x05)
+#define VRDE_VIDEOIN_CTRLSEL_VS_STREAM_ERROR_CODE VRDE_VIDEOIN_CTRLSEL_VS(0x06)
+#define VRDE_VIDEOIN_CTRLSEL_VS_GENERATE_KEY_FRAME VRDE_VIDEOIN_CTRLSEL_VS(0x07)
+#define VRDE_VIDEOIN_CTRLSEL_VS_UPDATE_FRAME_SEGMENT VRDE_VIDEOIN_CTRLSEL_VS(0x08)
+#define VRDE_VIDEOIN_CTRLSEL_VS_SYNCH_DELAY VRDE_VIDEOIN_CTRLSEL_VS(0x09)
+
+#define VRDE_VIDEOIN_CTRLSEL_HW_BUTTON VRDE_VIDEOIN_CTRLSEL_HW(0x01)
+
+#define VRDE_VIDEOIN_CTRLSEL_PROT_PING VRDE_VIDEOIN_CTRLSEL_PROT(0x01)
+#define VRDE_VIDEOIN_CTRLSEL_PROT_SAMPLING VRDE_VIDEOIN_CTRLSEL_PROT(0x02)
+#define VRDE_VIDEOIN_CTRLSEL_PROT_FRAMES VRDE_VIDEOIN_CTRLSEL_PROT(0x03)
+
+typedef struct VRDEVIDEOINCTRL_VIDEO_POWER_MODE
+{
+ VRDEVIDEOINCTRLHDR hdr;
+ uint8_t u8DevicePowerMode;
+} VRDEVIDEOINCTRL_VIDEO_POWER_MODE;
+
+typedef struct VRDEVIDEOINCTRL_CT_SCANNING_MODE
+{
+ VRDEVIDEOINCTRLHDR hdr;
+ uint8_t u8ScanningMode;
+} VRDEVIDEOINCTRL_CT_SCANNING_MODE;
+
+typedef struct VRDEVIDEOINCTRL_CT_AE_MODE
+{
+ VRDEVIDEOINCTRLHDR hdr;
+ uint8_t u8AutoExposureMode;
+} VRDEVIDEOINCTRL_CT_AE_MODE;
+
+typedef struct VRDEVIDEOINCTRL_CT_AE_PRIORITY
+{
+ VRDEVIDEOINCTRLHDR hdr;
+ uint8_t u8AutoExposurePriority;
+} VRDEVIDEOINCTRL_CT_AE_PRIORITY;
+
+typedef struct VRDEVIDEOINCTRL_CT_EXPOSURE_TIME_ABSOLUTE
+{
+ VRDEVIDEOINCTRLHDR hdr;
+ uint32_t u32ExposureTimeAbsolute;
+} VRDEVIDEOINCTRL_CT_EXPOSURE_TIME_ABSOLUTE;
+
+typedef struct VRDEVIDEOINCTRL_CT_EXPOSURE_TIME_RELATIVE
+{
+ VRDEVIDEOINCTRLHDR hdr;
+ uint8_t u8ExposureTimeRelative;
+} VRDEVIDEOINCTRL_CT_EXPOSURE_TIME_RELATIVE;
+
+typedef struct VRDEVIDEOINCTRL_CT_FOCUS_ABSOLUTE
+{
+ VRDEVIDEOINCTRLHDR hdr;
+ uint16_t u16FocusAbsolute;
+} VRDEVIDEOINCTRL_CT_FOCUS_ABSOLUTE;
+
+typedef struct VRDEVIDEOINCTRL_CT_FOCUS_RELATIVE
+{
+ VRDEVIDEOINCTRLHDR hdr;
+ uint8_t u8FocusRelative;
+ uint8_t u8Speed;
+} VRDEVIDEOINCTRL_CT_FOCUS_RELATIVE;
+
+typedef struct VRDEVIDEOINCTRL_CT_FOCUS_AUTO
+{
+ VRDEVIDEOINCTRLHDR hdr;
+ uint8_t u8FocusAuto;
+} VRDEVIDEOINCTRL_CT_FOCUS_AUTO;
+
+typedef struct VRDEVIDEOINCTRL_CT_IRIS_ABSOLUTE
+{
+ VRDEVIDEOINCTRLHDR hdr;
+ uint16_t u16IrisAbsolute;
+} VRDEVIDEOINCTRL_CT_IRIS_ABSOLUTE;
+
+typedef struct VRDEVIDEOINCTRL_CT_IRIS_RELATIVE
+{
+ VRDEVIDEOINCTRLHDR hdr;
+ uint8_t u8IrisRelative;
+} VRDEVIDEOINCTRL_CT_IRIS_RELATIVE;
+
+typedef struct VRDEVIDEOINCTRL_CT_ZOOM_ABSOLUTE
+{
+ VRDEVIDEOINCTRLHDR hdr;
+ uint16_t u16ZoomAbsolute;
+} VRDEVIDEOINCTRL_CT_ZOOM_ABSOLUTE;
+
+typedef struct VRDEVIDEOINCTRL_CT_ZOOM_RELATIVE
+{
+ VRDEVIDEOINCTRLHDR hdr;
+ uint8_t u8Zoom;
+ uint8_t u8DigitalZoom;
+ uint8_t u8Speed;
+} VRDEVIDEOINCTRL_CT_ZOOM_RELATIVE;
+
+typedef struct VRDEVIDEOINCTRL_CT_PANTILT_ABSOLUTE
+{
+ VRDEVIDEOINCTRLHDR hdr;
+ uint32_t u32PanAbsolute;
+ uint32_t u32TiltAbsolute;
+} VRDEVIDEOINCTRL_CT_PANTILT_ABSOLUTE;
+
+typedef struct VRDEVIDEOINCTRL_CT_PANTILT_RELATIVE
+{
+ VRDEVIDEOINCTRLHDR hdr;
+ uint8_t u8PanRelative;
+ uint8_t u8PanSpeed;
+ uint8_t u8TiltRelative;
+ uint8_t u8TiltSpeed;
+} VRDEVIDEOINCTRL_CT_PANTILT_RELATIVE;
+
+typedef struct VRDEVIDEOINCTRL_CT_ROLL_ABSOLUTE
+{
+ VRDEVIDEOINCTRLHDR hdr;
+ uint16_t u16RollAbsolute;
+} VRDEVIDEOINCTRL_CT_ROLL_ABSOLUTE;
+
+typedef struct VRDEVIDEOINCTRL_CT_ROLL_RELATIVE
+{
+ VRDEVIDEOINCTRLHDR hdr;
+ uint8_t u8RollRelative;
+ uint8_t u8Speed;
+} VRDEVIDEOINCTRL_CT_ROLL_RELATIVE;
+
+typedef struct VRDEVIDEOINCTRL_CT_PRIVACY_MODE
+{
+ VRDEVIDEOINCTRLHDR hdr;
+ uint8_t u8Privacy;
+} VRDEVIDEOINCTRL_CT_PRIVACY_MODE;
+
+typedef struct VRDEVIDEOINCTRL_PU_BACKLIGHT_COMPENSATION
+{
+ VRDEVIDEOINCTRLHDR hdr;
+ uint16_t u16BacklightCompensation;
+} VRDEVIDEOINCTRL_PU_BACKLIGHT_COMPENSATION;
+
+typedef struct VRDEVIDEOINCTRL_PU_BRIGHTNESS
+{
+ VRDEVIDEOINCTRLHDR hdr;
+ uint16_t u16Brightness;
+} VRDEVIDEOINCTRL_PU_BRIGHTNESS;
+
+typedef struct VRDEVIDEOINCTRL_PU_CONTRAST
+{
+ VRDEVIDEOINCTRLHDR hdr;
+ uint16_t u16Contrast;
+} VRDEVIDEOINCTRL_PU_CONTRAST;
+
+typedef struct VRDEVIDEOINCTRL_PU_GAIN
+{
+ VRDEVIDEOINCTRLHDR hdr;
+ uint16_t u16Gain;
+} VRDEVIDEOINCTRL_PU_GAIN;
+
+typedef struct VRDEVIDEOINCTRL_PU_POWER_LINE_FREQUENCY
+{
+ VRDEVIDEOINCTRLHDR hdr;
+ uint16_t u16PowerLineFrequency;
+} VRDEVIDEOINCTRL_PU_POWER_LINE_FREQUENCY;
+
+typedef struct VRDEVIDEOINCTRL_PU_HUE
+{
+ VRDEVIDEOINCTRLHDR hdr;
+ uint16_t u16Hue;
+} VRDEVIDEOINCTRL_PU_HUE;
+
+typedef struct VRDEVIDEOINCTRL_PU_HUE_AUTO
+{
+ VRDEVIDEOINCTRLHDR hdr;
+ uint8_t u8HueAuto;
+} VRDEVIDEOINCTRL_PU_HUE_AUTO;
+
+typedef struct VRDEVIDEOINCTRL_PU_SATURATION
+{
+ VRDEVIDEOINCTRLHDR hdr;
+ uint16_t u16Saturation;
+} VRDEVIDEOINCTRL_PU_SATURATION;
+
+typedef struct VRDEVIDEOINCTRL_PU_SHARPNESS
+{
+ VRDEVIDEOINCTRLHDR hdr;
+ uint16_t u16Sharpness;
+} VRDEVIDEOINCTRL_PU_SHARPNESS;
+
+typedef struct VRDEVIDEOINCTRL_PU_GAMMA
+{
+ VRDEVIDEOINCTRLHDR hdr;
+ uint16_t u16Gamma;
+} VRDEVIDEOINCTRL_PU_GAMMA;
+
+typedef struct VRDEVIDEOINCTRL_PU_WHITE_BALANCE_TEMPERATURE
+{
+ VRDEVIDEOINCTRLHDR hdr;
+ uint16_t u16WhiteBalanceTemperature;
+} VRDEVIDEOINCTRL_PU_WHITE_BALANCE_TEMPERATURE;
+
+typedef struct VRDEVIDEOINCTRL_PU_WHITE_BALANCE_TEMPERATURE_AUTO
+{
+ VRDEVIDEOINCTRLHDR hdr;
+ uint8_t u8WhiteBalanceTemperatureAuto;
+} VRDEVIDEOINCTRL_PU_WHITE_BALANCE_TEMPERATURE_AUTO;
+
+typedef struct VRDEVIDEOINCTRL_PU_WHITE_BALANCE_COMPONENT
+{
+ VRDEVIDEOINCTRLHDR hdr;
+ uint16_t u16WhiteBalanceBlue;
+ uint16_t u16WhiteBalanceRed;
+} VRDEVIDEOINCTRL_PU_WHITE_BALANCE_COMPONENT;
+
+typedef struct VRDEVIDEOINCTRL_PU_WHITE_BALANCE_COMPONENT_AUTO
+{
+ VRDEVIDEOINCTRLHDR hdr;
+ uint8_t u8WhiteBalanceComponentAuto;
+} VRDEVIDEOINCTRL_PU_WHITE_BALANCE_COMPONENT_AUTO;
+
+typedef struct VRDEVIDEOINCTRL_PU_DIGITAL_MULTIPLIER
+{
+ VRDEVIDEOINCTRLHDR hdr;
+ uint16_t u16MultiplierStep;
+} VRDEVIDEOINCTRL_PU_DIGITAL_MULTIPLIER;
+
+typedef struct VRDEVIDEOINCTRL_PU_DIGITAL_MULTIPLIER_LIMIT
+{
+ VRDEVIDEOINCTRLHDR hdr;
+ uint16_t u16MultiplierLimit;
+} VRDEVIDEOINCTRL_PU_DIGITAL_MULTIPLIER_LIMIT;
+
+typedef struct VRDEVIDEOINCTRL_PU_ANALOG_VIDEO_STANDARD
+{
+ VRDEVIDEOINCTRLHDR hdr;
+ uint8_t u8VideoStandard;
+} VRDEVIDEOINCTRL_PU_ANALOG_VIDEO_STANDARD;
+
+typedef struct VRDEVIDEOINCTRL_PU_ANALOG_LOCK_STATUS
+{
+ VRDEVIDEOINCTRLHDR hdr;
+ uint8_t u8Status;
+} VRDEVIDEOINCTRL_PU_ANALOG_LOCK_STATUS;
+
+/* Set streaming parameters. The actual streaming will be enabled by VS_ON. */
+#define VRDEVIDEOINCTRL_F_VS_SETUP_FID 0x01
+#define VRDEVIDEOINCTRL_F_VS_SETUP_EOF 0x02
+
+typedef struct VRDEVIDEOINCTRL_VS_SETUP
+{
+ VRDEVIDEOINCTRLHDR hdr;
+ uint8_t u8FormatId; /* The format id on the client: VRDEVIDEOINFORMATDESC::u8FormatId. */
+ uint8_t u8FramingInfo; /* VRDEVIDEOINCTRL_F_VS_SETUP_*. Set by the client. */
+ uint16_t u16Width;
+ uint16_t u16Height;
+ uint32_t u32FrameInterval; /* Frame interval in 100 ns units, 0 means a still image capture.
+ * The client may choose a different interval if this value is
+ * not supported.
+ */
+ uint16_t u16CompQuality; /* 0 .. 10000 = 0 .. 100%.
+ * Applicable if the format has VRDE_VIDEOIN_F_FMT_COMPQUALITY,
+ * otherwise this field is ignored.
+ */
+ uint16_t u16Delay; /* Latency in ms from video data capture to presentation on the channel.
+ * Set by the client, read by the server.
+ */
+ uint32_t u32ClockFrequency; /* @todo just all clocks in 100ns units? */
+} VRDEVIDEOINCTRL_VS_SETUP;
+
+/* Stop sending video frames. */
+typedef struct VRDEVIDEOINCTRL_VS_OFF
+{
+ VRDEVIDEOINCTRLHDR hdr;
+} VRDEVIDEOINCTRL_VS_OFF;
+
+/* Start sending video frames with parameters set by VS_SETUP. */
+typedef struct VRDEVIDEOINCTRL_VS_ON
+{
+ VRDEVIDEOINCTRLHDR hdr;
+} VRDEVIDEOINCTRL_VS_ON;
+
+typedef struct VRDEVIDEOINCTRL_VS_STILL_IMAGE_TRIGGER
+{
+ VRDEVIDEOINCTRLHDR hdr;
+ uint8_t u8Trigger;
+} VRDEVIDEOINCTRL_VS_STILL_IMAGE_TRIGGER;
+
+typedef struct VRDEVIDEOINCTRL_VS_STREAM_ERROR_CODE
+{
+ VRDEVIDEOINCTRLHDR hdr;
+ uint8_t u8StreamErrorCode;
+} VRDEVIDEOINCTRL_VS_STREAM_ERROR_CODE;
+
+typedef struct VRDEVIDEOINCTRL_VS_GENERATE_KEY_FRAME
+{
+ VRDEVIDEOINCTRLHDR hdr;
+ uint8_t u8GenerateKeyFrame;
+} VRDEVIDEOINCTRL_VS_GENERATE_KEY_FRAME;
+
+typedef struct VRDEVIDEOINCTRL_VS_UPDATE_FRAME_SEGMENT
+{
+ VRDEVIDEOINCTRLHDR hdr;
+ uint8_t u8StartFrameSegment;
+ uint8_t u8EndFrameSegment;
+} VRDEVIDEOINCTRL_VS_UPDATE_FRAME_SEGMENT;
+
+typedef struct VRDEVIDEOINCTRL_VS_SYNCH_DELAY
+{
+ VRDEVIDEOINCTRLHDR hdr;
+ uint16_t u16Delay;
+} VRDEVIDEOINCTRL_VS_SYNCH_DELAY;
+
+/* A hardware button was pressed/released on the device. */
+typedef struct VRDEVIDEOINCTRL_HW_BUTTON
+{
+ VRDEVIDEOINCTRLHDR hdr;
+ uint8_t u8Pressed;
+} VRDEVIDEOINCTRL_HW_BUTTON;
+
+typedef struct VRDEVIDEOINCTRL_PROT_PING
+{
+ VRDEVIDEOINCTRLHDR hdr;
+ uint32_t u32Timestamp; /* Set in the request and the same value must be send back in the response. */
+} VRDEVIDEOINCTRL_PROT_PING;
+
+typedef struct VRDEVIDEOINCTRL_PROT_SAMPLING
+{
+ VRDEVIDEOINCTRLHDR hdr;
+ uint32_t fu32SampleStart; /* Which parameters must be sampled VRDEVIDEOINCTRL_F_PROT_SAMPLING_*. */
+ uint32_t fu32SampleStop; /* Which parameters to disable VRDEVIDEOINCTRL_F_PROT_SAMPLING_*.
+ * If both Start and Stop is set, then restart the sampling.
+ */
+ uint32_t u32PeriodMS; /* Sampling period in milliseconds. Applies to all samples in fu32SampleStart.
+ * Not mandatory, the actual sampling period may be different.
+ */
+} VRDEVIDEOINCTRL_PROT_SAMPLING;
+
+#define VRDEVIDEOINCTRL_F_PROT_SAMPLING_FRAMES_SOURCE 0x00000001 /* Periodic VRDEVIDEOINCTRL_PROT_FRAMES samples */
+#define VRDEVIDEOINCTRL_F_PROT_SAMPLING_FRAMES_CLIENT_OUT 0x00000002 /* Periodic VRDEVIDEOINCTRL_PROT_FRAMES samples */
+
+typedef struct VRDEVIDEOINCTRL_PROT_FRAMES
+{
+ VRDEVIDEOINCTRLHDR hdr; /* Note: the message should be sent as VRDE_VIDEOIN_FN_CONTROL_NOTIFY. */
+ uint32_t u32Sample; /* Which sample is this, one of VRDEVIDEOINCTRL_F_PROT_SAMPLING_*. */
+ uint32_t u32TimestampMS; /* When the period started, milliseconds since the start of sampling. */
+ uint32_t u32PeriodMS; /* Actual period during which the frames were counted in milliseconds.
+ * This may be different from VRDEVIDEOINCTRL_PROT_SAMPLING::u32PeriodMS.
+ */
+ uint32_t u32FramesCount; /* How many frames per u32PeriodMS milliseconds. */
+} VRDEVIDEOINCTRL_PROT_FRAMES;
+
+
+/*
+ * Payload transfers. How frames are sent to the server:
+ * the client send a PAYLOAD packet, which has the already set format.
+ * The server enables the transfers by sending VRDEVIDEOINCTRL_VS_ON.
+ */
+
+/* Payload header */
+typedef struct VRDEVIDEOINPAYLOADHDR
+{
+ uint8_t u8HeaderLength; /* Entire header. */
+ uint8_t u8HeaderInfo; /* VRDE_VIDEOIN_PAYLOAD_F_* */
+ uint32_t u32PresentationTime; /* @todo define this */
+ uint32_t u32SourceTimeClock; /* @todo At the moment when the frame was sent to the channel.
+ * Allows the server to measure clock drift.
+ */
+ uint16_t u16Reserved; /* @todo */
+} VRDEVIDEOINPAYLOADHDR;
+
+/* VRDEVIDEOINPAYLOADHDR::u8HeaderInfo */
+#define VRDE_VIDEOIN_PAYLOAD_F_FID 0x01 /* Frame ID */
+#define VRDE_VIDEOIN_PAYLOAD_F_EOF 0x02 /* End of Frame */
+#define VRDE_VIDEOIN_PAYLOAD_F_PTS 0x04 /* Presentation Time */
+#define VRDE_VIDEOIN_PAYLOAD_F_SCR 0x08 /* Source Clock Reference */
+#define VRDE_VIDEOIN_PAYLOAD_F_RES 0x10 /* Reserved */
+#define VRDE_VIDEOIN_PAYLOAD_F_STI 0x20 /* Still Image */
+#define VRDE_VIDEOIN_PAYLOAD_F_ERR 0x40 /* Error */
+#define VRDE_VIDEOIN_PAYLOAD_F_EOH 0x80 /* End of header */
+
+
+/*
+ * The network channel specification.
+ */
+
+/*
+ * The protocol uses a dynamic RDP channel.
+ * Everything is little-endian.
+ */
+
+/* The dynamic RDP channel name. */
+#define VRDE_VIDEOIN_CHANNEL "RVIDEOIN"
+
+/* Major functions. */
+#define VRDE_VIDEOIN_FN_NEGOTIATE 0x0000 /* Version and capabilities check. */
+#define VRDE_VIDEOIN_FN_NOTIFY 0x0001 /* Device attach/detach from the client. */
+#define VRDE_VIDEOIN_FN_DEVICEDESC 0x0002 /* Query device description. */
+#define VRDE_VIDEOIN_FN_CONTROL 0x0003 /* Control the device and start/stop video input.
+ * This function is used for sending a request and
+ * the corresponding response.
+ */
+#define VRDE_VIDEOIN_FN_CONTROL_NOTIFY 0x0004 /* The client reports a control change, etc.
+ * This function indicated that the message is
+ * not a response to a CONTROL request.
+ */
+#define VRDE_VIDEOIN_FN_FRAME 0x0005 /* Frame from the client. */
+
+/* Status codes. */
+#define VRDE_VIDEOIN_STATUS_SUCCESS 0 /* Function completed successfully. */
+#define VRDE_VIDEOIN_STATUS_FAILED 1 /* Failed for some reason. */
+
+typedef struct VRDEVIDEOINMSGHDR
+{
+ uint32_t u32Length; /* The length of the message in bytes, including the header. */
+ uint32_t u32DeviceId; /* The client's device id. */
+ uint32_t u32MessageId; /* Unique id assigned by the server. The client must send a reply with the same id.
+ * If the client initiates a request, then this must be set to 0, because there is
+ * currently no client requests, which would require a response from the server.
+ */
+ uint16_t u16FunctionId; /* VRDE_VIDEOIN_FN_* */
+ uint16_t u16Status; /* The result of a request. VRDE_VIDEOIN_STATUS_*. */
+} VRDEVIDEOINMSGHDR;
+ASSERTSIZE(VRDEVIDEOINMSGHDR, 16)
+
+/*
+ * VRDE_VIDEOIN_FN_NEGOTIATE
+ *
+ * Sent by the server when the channel is established and the client replies with its capabilities.
+ */
+#define VRDE_VIDEOIN_NEGOTIATE_VERSION 1
+
+/* VRDEVIDEOINMSG_NEGOTIATE::fu32Capabilities */
+#define VRDE_VIDEOIN_NEGOTIATE_CAP_VOID 0x00000000
+#define VRDE_VIDEOIN_NEGOTIATE_CAP_PROT 0x00000001 /* Supports VRDE_VIDEOIN_CTRLSEL_PROT_* controls. */
+
+typedef struct VRDEVIDEOINMSG_NEGOTIATE
+{
+ VRDEVIDEOINMSGHDR hdr;
+ uint32_t u32Version; /* VRDE_VIDEOIN_NEGOTIATE_VERSION */
+ uint32_t fu32Capabilities; /* VRDE_VIDEOIN_NEGOTIATE_CAP_* */
+} VRDEVIDEOINMSG_NEGOTIATE;
+
+/*
+ * VRDE_VIDEOIN_FN_NOTIFY
+ *
+ * Sent by the client when a webcam is attached or detached.
+ * The client must send the ATTACH notification for each webcam, which is
+ * already connected to the client when the VIDEOIN channel is established.
+ */
+#define VRDE_VIDEOIN_NOTIFY_EVENT_ATTACH 0
+#define VRDE_VIDEOIN_NOTIFY_EVENT_DETACH 1
+#define VRDE_VIDEOIN_NOTIFY_EVENT_NEGOTIATE 2 /* Negotiate again with the client. */
+
+typedef struct VRDEVIDEOINMSG_NOTIFY
+{
+ VRDEVIDEOINMSGHDR hdr;
+ uint32_t u32NotifyEvent; /* VRDE_VIDEOIN_NOTIFY_EVENT_* */
+ /* Event specific data may follow. The underlying protocol provides the length of the message. */
+} VRDEVIDEOINMSG_NOTIFY;
+
+/*
+ * VRDE_VIDEOIN_FN_DEVICEDESC
+ *
+ * The server queries the description of a device.
+ */
+typedef struct VRDEVIDEOINMSG_DEVICEDESC_REQ
+{
+ VRDEVIDEOINMSGHDR hdr;
+} VRDEVIDEOINMSG_DEVICEDESC_REQ;
+
+typedef struct VRDEVIDEOINMSG_DEVICEDESC_RSP
+{
+ VRDEVIDEOINMSGHDR hdr;
+ VRDEVIDEOINDEVICEDESC Device;
+ /*
+ * VRDEVIDEOINFORMATDESC[0]
+ * VRDEVIDEOINFRAMEDESC[0]
+ * ...
+ * VRDEVIDEOINFRAMEDESC[n]
+ * VRDEVIDEOINFORMATDESC[1]
+ * VRDEVIDEOINFRAMEDESC[0]
+ * ...
+ * VRDEVIDEOINFRAMEDESC[m]
+ * ...
+ */
+} VRDEVIDEOINMSG_DEVICEDESC_RSP;
+
+/*
+ * VRDE_VIDEOIN_FN_CONTROL
+ * VRDE_VIDEOIN_FN_CONTROL_NOTIFY
+ *
+ * Either sent by the server or by the client as a notification/response.
+ * If sent by the client as a notification, then hdr.u32MessageId must be 0.
+ */
+typedef struct VRDEVIDEOINMSG_CONTROL
+{
+ VRDEVIDEOINMSGHDR hdr;
+ VRDEVIDEOINCTRLHDR Control;
+ /* Control specific data may follow. */
+} VRDEVIDEOINMSG_CONTROL;
+
+/*
+ * VRDE_VIDEOIN_FN_FRAME
+ *
+ * The client sends a video/still frame in the already specified format.
+ * hdr.u32MessageId must be 0.
+ */
+typedef struct VRDEVIDEOINMSG_FRAME
+{
+ VRDEVIDEOINMSGHDR hdr;
+ VRDEVIDEOINPAYLOADHDR Payload;
+ /* The frame data follow. */
+} VRDEVIDEOINMSG_FRAME;
+
+
+#ifdef VRDE_VIDEOIN_WITH_VRDEINTERFACE
+/*
+ * The application interface between VirtualBox and the VRDE server.
+ */
+
+#define VRDE_VIDEOIN_INTERFACE_NAME "VIDEOIN"
+
+typedef struct VRDEVIDEOINDEVICEHANDLE
+{
+ uint32_t u32ClientId;
+ uint32_t u32DeviceId;
+} VRDEVIDEOINDEVICEHANDLE;
+
+/* The VRDE server video input interface entry points. Interface version 1. */
+typedef struct VRDEVIDEOININTERFACE
+{
+ /* The header. */
+ VRDEINTERFACEHDR header;
+
+ /* Tell the server that this device will be used and associate a context with the device.
+ *
+ * @param hServer The VRDE server instance.
+ * @param pDeviceHandle The device reported by ATTACH notification.
+ * @param pvDeviceCtx The caller context associated with the pDeviceHandle.
+ *
+ * @return IPRT status code.
+ */
+ DECLR3CALLBACKMEMBER(int, VRDEVideoInDeviceAttach, (HVRDESERVER hServer,
+ const VRDEVIDEOINDEVICEHANDLE *pDeviceHandle,
+ void *pvDeviceCtx));
+
+ /* This device will be not be used anymore. The device context must not be used by the server too.
+ *
+ * @param hServer The VRDE server instance.
+ * @param pDeviceHandle The device reported by ATTACH notification.
+ *
+ * @return IPRT status code.
+ */
+ DECLR3CALLBACKMEMBER(int, VRDEVideoInDeviceDetach, (HVRDESERVER hServer,
+ const VRDEVIDEOINDEVICEHANDLE *pDeviceHandle));
+
+ /* Get a device description.
+ *
+ * @param hServer The VRDE server instance.
+ * @param pvUser The callers context of this request.
+ * @param pDeviceHandle The device reported by ATTACH notification.
+ *
+ * @return IPRT status code.
+ */
+ DECLR3CALLBACKMEMBER(int, VRDEVideoInGetDeviceDesc, (HVRDESERVER hServer,
+ void *pvUser,
+ const VRDEVIDEOINDEVICEHANDLE *pDeviceHandle));
+
+ /* Submit a set/get control request.
+ *
+ * @param hServer The VRDE server instance.
+ * @param pvUser The callers context of this request.
+ * @param pDeviceHandle The device reported by ATTACH notification.
+ * @param pReq The request.
+ * @param cbReq Size of the request.
+ *
+ * @return IPRT status code.
+ */
+ DECLR3CALLBACKMEMBER(int, VRDEVideoInControl, (HVRDESERVER hServer,
+ void *pvUser,
+ const VRDEVIDEOINDEVICEHANDLE *pDeviceHandle,
+ const VRDEVIDEOINCTRLHDR *pReq,
+ uint32_t cbReq));
+
+} VRDEVIDEOININTERFACE;
+
+
+/*
+ * Notifications.
+ * Data structures: pvData of VRDEVIDEOINCALLBACKS::VRDECallbackVideoInNotify.
+ */
+typedef struct VRDEVIDEOINNOTIFYATTACH
+{
+ VRDEVIDEOINDEVICEHANDLE deviceHandle;
+ uint32_t u32Version; /* VRDE_VIDEOIN_NEGOTIATE_VERSION */
+ uint32_t fu32Capabilities; /* VRDE_VIDEOIN_NEGOTIATE_CAP_* */
+} VRDEVIDEOINNOTIFYATTACH;
+
+typedef struct VRDEVIDEOINNOTIFYDETACH
+{
+ VRDEVIDEOINDEVICEHANDLE deviceHandle;
+} VRDEVIDEOINNOTIFYDETACH;
+
+/* Notification codes, */
+#define VRDE_VIDEOIN_NOTIFY_ID_ATTACH 0
+#define VRDE_VIDEOIN_NOTIFY_ID_DETACH 1
+
+
+/* Video input interface callbacks. */
+typedef struct VRDEVIDEOINCALLBACKS
+{
+ /* The header. */
+ VRDEINTERFACEHDR header;
+
+ /* Notifications.
+ *
+ * @param pvCallback The callbacks context specified in VRDEGetInterface.
+ * @param u32EventId The notification identifier: VRDE_VIDEOIN_NOTIFY_*.
+ * @param pvData The notification specific data.
+ * @param cbData The size of buffer pointed by pvData.
+ */
+ DECLR3CALLBACKMEMBER(void, VRDECallbackVideoInNotify,(void *pvCallback,
+ uint32_t u32Id,
+ const void *pvData,
+ uint32_t cbData));
+
+ /* Device description received from the client.
+ *
+ * @param pvCallback The callbacks context specified in VRDEGetInterface.
+ * @param rcRequest The result code of the request.
+ * @param pDeviceCtx The device context associated with the device in VRDEVideoInGetDeviceDesc.
+ * @param pvUser The pvUser parameter of VRDEVideoInGetDeviceDesc.
+ * @param pDeviceDesc The device description.
+ * @param cbDeviceDesc The size of buffer pointed by pDevice.
+ */
+ DECLR3CALLBACKMEMBER(void, VRDECallbackVideoInDeviceDesc,(void *pvCallback,
+ int rcRequest,
+ void *pDeviceCtx,
+ void *pvUser,
+ const VRDEVIDEOINDEVICEDESC *pDeviceDesc,
+ uint32_t cbDeviceDesc));
+
+ /* Control response or notification.
+ *
+ * @param pvCallback The callbacks context specified in VRDEGetInterface.
+ * @param rcRequest The result code of the request.
+ * @param pDeviceCtx The device context associated with the device in VRDEVideoInGetDeviceDesc.
+ * @param pvUser The pvUser parameter of VRDEVideoInControl. NULL if this is a notification.
+ * @param pControl The control information.
+ * @param cbControl The size of buffer pointed by pControl.
+ */
+ DECLR3CALLBACKMEMBER(void, VRDECallbackVideoInControl,(void *pvCallback,
+ int rcRequest,
+ void *pDeviceCtx,
+ void *pvUser,
+ const VRDEVIDEOINCTRLHDR *pControl,
+ uint32_t cbControl));
+
+ /* Frame which was received from the client.
+ *
+ * @param pvCallback The callbacks context specified in VRDEGetInterface.
+ * @param rcRequest The result code of the request.
+ * @param pDeviceCtx The device context associated with the device in VRDEVideoInGetDeviceDesc.
+ * @param pFrame The frame data.
+ * @param cbFrame The size of buffer pointed by pFrame.
+ */
+ DECLR3CALLBACKMEMBER(void, VRDECallbackVideoInFrame,(void *pvCallback,
+ int rcRequest,
+ void *pDeviceCtx,
+ const VRDEVIDEOINPAYLOADHDR *pFrame,
+ uint32_t cbFrame));
+
+} VRDEVIDEOINCALLBACKS;
+#endif /* VRDE_VIDEOIN_WITH_VRDEINTERFACE */
+
+#pragma pack()
+
+#endif /* !VBOX_INCLUDED_RemoteDesktop_VRDEVideoIn_h */
diff --git a/include/VBox/SUPDrvMangling.h b/include/VBox/SUPDrvMangling.h
new file mode 100644
index 00000000..40934528
--- /dev/null
+++ b/include/VBox/SUPDrvMangling.h
@@ -0,0 +1,48 @@
+/** @file
+ * SUPDrv - Mangling of IPRT symbols for host 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-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_SUPDrvMangling_h
+#define VBOX_INCLUDED_SUPDrvMangling_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#define RT_MANGLER(symbol) VBoxHost_##symbol
+#include <iprt/mangling.h>
+
+#endif /* !VBOX_INCLUDED_SUPDrvMangling_h */
diff --git a/include/VBox/SUPR0StackWrapper.mac b/include/VBox/SUPR0StackWrapper.mac
new file mode 100644
index 00000000..152da635
--- /dev/null
+++ b/include/VBox/SUPR0StackWrapper.mac
@@ -0,0 +1,180 @@
+; $Id: SUPR0StackWrapper.mac $
+;; @file
+; SUP - Support Library, ring-0 stack switching wrappers.
+;
+
+;
+; Copyright (C) 2006-2022 Oracle and/or its affiliates.
+;
+; This file is part of VirtualBox base platform packages, as
+; available from https://www.virtualbox.org.
+;
+; This program is free software; you can redistribute it and/or
+; modify it under the terms of the GNU General Public License
+; as published by the Free Software Foundation, in version 3 of the
+; License.
+;
+; This program is distributed in the hope that it will be useful, but
+; WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with this program; if not, see <https://www.gnu.org/licenses>.
+;
+; The contents of this file may alternatively be used under the terms
+; of the Common Development and Distribution License Version 1.0
+; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+; in the VirtualBox 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.
+;
+; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+;
+
+%ifndef ___VBox_SUPR0StackWrapper_mac
+%define ___VBox_SUPR0StackWrapper_mac
+
+%include "VBox/asmdefs.mac"
+
+;; VBox's own Stack
+%define SUPR0STACKINFO_MAGIC0 0786f4256h ; VBox
+%define SUPR0STACKINFO_MAGIC1 06f207327h ; 's o
+%define SUPR0STACKINFO_MAGIC2 053206e77h ; wn S
+%define SUPR0STACKINFO_MAGIC3 06b636174h ; tack
+
+;;
+; Stack info located before the start of the stack, at the top of the page.
+;
+struc SUPR0STACKINFO
+ .magic0 resd 1
+ .magic1 resd 1
+ .magic2 resd 1
+ .magic3 resd 1
+ .pResumeKernelStack resq 1
+ .pSelf resq 1
+endstruc
+
+;;
+; Number of parameters in GPRs and the spill area size.
+%ifdef RT_ARCH_AMD64
+ %ifdef ASM_CALL64_MSC
+ %define SUPR0_GRP_PARAMS 4
+ %define SUPR0_SPILL_AREA 4
+ %else
+ %define SUPR0_GRP_PARAMS 6
+ %define SUPR0_SPILL_AREA 0
+ %endif
+%else
+ %define SUPR0_GRP_PARAMS 0
+ %define SUPR0_SPILL_AREA 0
+%endif
+
+;;
+; Generic stack switching wrapper.
+;
+; @param %1 The name
+; @param %2 Number of arguments.
+;
+%macro SUPR0StackWrapperGeneric 2
+BEGINCODE
+extern NAME(StkBack_ %+ %1)
+
+BEGINPROC %1
+%ifdef RT_ARCH_AMD64 ; Only for amd64 for now.
+ ;
+ ; Check for the stack info.
+ ;
+ mov rax, rsp
+ or rax, 0fffh
+ sub rax, SUPR0STACKINFO_size - 1
+
+ ; Check for the magic.
+ cmp dword [rax + SUPR0STACKINFO.magic0], SUPR0STACKINFO_MAGIC0
+ jne .regular
+ cmp dword [rax + SUPR0STACKINFO.magic1], SUPR0STACKINFO_MAGIC1
+ jne .regular
+ cmp dword [rax + SUPR0STACKINFO.magic2], SUPR0STACKINFO_MAGIC2
+ jne .regular
+ cmp dword [rax + SUPR0STACKINFO.magic3], SUPR0STACKINFO_MAGIC3
+ jne .regular
+
+ ; Verify the self pointer.
+ cmp [rax + SUPR0STACKINFO.pSelf], rax
+ jne .regular
+
+ ;
+ ; Perform a stack switch. We set up a RBP frame on the old stack so we
+ ; can use leave to restore the incoming stack upon return.
+ ;
+ push rbp
+ mov rbp, rsp
+
+ ; The actual switch.
+ mov r10, 0ffffffffffffffe0h ; shuts up warning on 'and rsp, 0ffffffffffffffe0h'
+ and r10, [rax + SUPR0STACKINFO.pResumeKernelStack]
+ mov rsp, r10
+
+ ;
+ ; Copy over stack arguments.
+ ;
+ ; Note! We always copy 2-3 extra arguments (%2 + 2) just in case someone got
+ ; the argument count wrong.
+ ;
+%if (%2 + 2) > SUPR0_GRP_PARAMS + 18
+ %error too many parameters
+ %fatal too many parameters
+%endif
+%if (%2 + 2) > SUPR0_GRP_PARAMS + 16
+ push qword [rbp + 98h]
+ push qword [rbp + 90h]
+%endif
+%if (%2 + 2) > SUPR0_GRP_PARAMS + 14
+ push qword [rbp + 88h]
+ push qword [rbp + 80h]
+%endif
+%if (%2 + 2) > SUPR0_GRP_PARAMS + 12
+ push qword [rbp + 78h]
+ push qword [rbp + 70h]
+%endif
+%if (%2 + 2) > SUPR0_GRP_PARAMS + 10
+ push qword [rbp + 68h]
+ push qword [rbp + 60h]
+%endif
+%if (%2 + 2) > SUPR0_GRP_PARAMS + 8
+ push qword [rbp + 58h]
+ push qword [rbp + 50h]
+%endif
+%if (%2 + 2) > SUPR0_GRP_PARAMS + 6
+ push qword [rbp + 48h]
+ push qword [rbp + 40h]
+%endif
+%if (%2 + 2) > SUPR0_GRP_PARAMS + 4
+ push qword [rbp + 38h]
+ push qword [rbp + 30h]
+%endif
+%if ((%2 + 2) > SUPR0_GRP_PARAMS + 2) || (SUPR0_SPILL_AREA > 2)
+ push qword [rbp + 28h]
+ push qword [rbp + 20h]
+%endif
+%if ((%2 + 2) > SUPR0_GRP_PARAMS) || (SUPR0_SPILL_AREA > 0)
+ push qword [rbp + 18h]
+ push qword [rbp + 10h]
+%endif
+
+ call NAME(StkBack_ %+ %1)
+
+ leave
+ ret
+
+.regular:
+%endif ; RT_ARCH_AMD64
+ jmp NAME(StkBack_ %+ %1)
+ENDPROC %1
+%endmacro
+
+
+%endif
+
diff --git a/include/VBox/VBoxAuth.h b/include/VBox/VBoxAuth.h
new file mode 100644
index 00000000..c10b1e8e
--- /dev/null
+++ b/include/VBox/VBoxAuth.h
@@ -0,0 +1,209 @@
+/** @file
+ * VirtualBox External Authentication Library Interface.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_VBoxAuth_h
+#define VBOX_INCLUDED_VBoxAuth_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+/** @defgroup grp_vboxauth VirtualBox External Authentication Library Interface
+ * @{
+ */
+
+/* The following 2 enums are 32 bits values.*/
+typedef enum AuthResult
+{
+ AuthResultAccessDenied = 0,
+ AuthResultAccessGranted = 1,
+ AuthResultDelegateToGuest = 2,
+ AuthResultSizeHack = 0x7fffffff
+} AuthResult;
+
+typedef enum AuthGuestJudgement
+{
+ AuthGuestNotAsked = 0,
+ AuthGuestAccessDenied = 1,
+ AuthGuestNoJudgement = 2,
+ AuthGuestAccessGranted = 3,
+ AuthGuestNotReacted = 4,
+ AuthGuestSizeHack = 0x7fffffff
+} AuthGuestJudgement;
+
+/** UUID memory representation. Array of 16 bytes.
+ *
+ * @note VirtualBox uses a consistent binary representation of UUIDs on all platforms. For this reason
+ * the integer fields comprising the UUID are stored as little endian values. If you want to pass such
+ * UUIDs to code which assumes that the integer fields are big endian (often also called network byte
+ * order), you need to adjust the contents of the UUID to e.g. achieve the same string representation.
+ *
+ * The required changes are:
+ * - reverse the order of byte 0, 1, 2 and 3
+ * - reverse the order of byte 4 and 5
+ * - reverse the order of byte 6 and 7.
+ *
+ * Using this conversion you will get identical results when converting the binary UUID to the string
+ * representation.
+ */
+typedef unsigned char AUTHUUID[16];
+typedef AUTHUUID *PAUTHUUID;
+
+/** The library entry point calling convention. */
+#ifdef _MSC_VER
+# define AUTHCALL __cdecl
+#elif defined(__GNUC__)
+# define AUTHCALL
+#else
+# error "Unsupported compiler"
+#endif
+
+
+/**
+ * Authentication library entry point.
+ *
+ * @param pUuid Pointer to the UUID of the accessed virtual machine. Can be NULL.
+ * @param guestJudgement Result of the guest authentication.
+ * @param pszUser User name passed in by the client (UTF8).
+ * @param pszPassword Password passed in by the client (UTF8).
+ * @param pszDomain Domain passed in by the client (UTF8).
+ *
+ * Return code:
+ *
+ * @retval AuthAccessDenied Client access has been denied.
+ * @retval AuthAccessGranted Client has the right to use the virtual machine.
+ * @retval AuthDelegateToGuest Guest operating system must
+ * authenticate the client and the
+ * library must be called again with
+ * the result of the guest
+ * authentication.
+ */
+typedef AuthResult AUTHCALL FNAUTHENTRY(PAUTHUUID pUuid,
+ AuthGuestJudgement guestJudgement,
+ const char *pszUser,
+ const char *pszPassword,
+ const char *pszDomain);
+/** Pointer to a FNAUTHENTRY function. */
+typedef FNAUTHENTRY *PFNAUTHENTRY;
+/** @deprecated */
+typedef FNAUTHENTRY AUTHENTRY;
+/** @deprecated */
+typedef PFNAUTHENTRY PAUTHENTRY;
+/** Name of the FNAUTHENTRY entry point. */
+#define AUTHENTRY_NAME "VRDPAuth"
+
+/**
+ * Authentication library entry point version 2.
+ *
+ * @param pUuid Pointer to the UUID of the accessed virtual machine. Can be NULL.
+ * @param guestJudgement Result of the guest authentication.
+ * @param pszUser User name passed in by the client (UTF8).
+ * @param pszPassword Password passed in by the client (UTF8).
+ * @param pszDomain Domain passed in by the client (UTF8).
+ * @param fLogon Boolean flag. Indicates whether the entry point is
+ * called for a client logon or the client disconnect.
+ * @param clientId Server side unique identifier of the client.
+ *
+ * @retval AuthAccessDenied Client access has been denied.
+ * @retval AuthAccessGranted Client has the right to use the virtual machine.
+ * @retval AuthDelegateToGuest Guest operating system must
+ * authenticate the client and the
+ * library must be called again with
+ * the result of the guest authentication.
+ *
+ * @note When @a fLogon is 0, only @a pUuid and @a clientId are valid and the
+ * return code is ignored.
+ */
+typedef AuthResult AUTHCALL FNAUTHENTRY2(PAUTHUUID pUuid,
+ AuthGuestJudgement guestJudgement,
+ const char *pszUser,
+ const char *pszPassword,
+ const char *pszDomain,
+ int fLogon,
+ unsigned clientId);
+/** Pointer to a FNAUTHENTRY2 function. */
+typedef FNAUTHENTRY2 *PFNAUTHENTRY2;
+/** @deprecated */
+typedef FNAUTHENTRY2 AUTHENTRY2;
+/** @deprecated */
+typedef PFNAUTHENTRY2 PAUTHENTRY2;
+/** Name of the FNAUTHENTRY2 entry point. */
+#define AUTHENTRY2_NAME "VRDPAuth2"
+
+/**
+ * Authentication library entry point version 3.
+ *
+ * @param pszCaller The name of the component which calls the library (UTF8).
+ * @param pUuid Pointer to the UUID of the accessed virtual machine. Can be NULL.
+ * @param guestJudgement Result of the guest authentication.
+ * @param pszUser User name passed in by the client (UTF8).
+ * @param pszPassword Password passed in by the client (UTF8).
+ * @param pszDomain Domain passed in by the client (UTF8).
+ * @param fLogon Boolean flag. Indicates whether the entry point is
+ * called for a client logon or the client disconnect.
+ * @param clientId Server side unique identifier of the client.
+ *
+ * @retval AuthResultAccessDenied Client access has been denied.
+ * @retval AuthResultAccessGranted Client has the right to use the
+ * virtual machine.
+ * @retval AuthResultDelegateToGuest Guest operating system must
+ * authenticate the client and the
+ * library must be called again with
+ * the result of the guest
+ * authentication.
+ *
+ * @note When @a fLogon is 0, only @a pszCaller, @a pUuid and @a clientId are
+ * valid and the return code is ignored.
+ */
+typedef AuthResult AUTHCALL FNAUTHENTRY3(const char *pszCaller,
+ PAUTHUUID pUuid,
+ AuthGuestJudgement guestJudgement,
+ const char *pszUser,
+ const char *pszPassword,
+ const char *pszDomain,
+ int fLogon,
+ unsigned clientId);
+/** Pointer to a FNAUTHENTRY3 function. */
+typedef FNAUTHENTRY3 *PFNAUTHENTRY3;
+/** @deprecated */
+typedef FNAUTHENTRY3 AUTHENTRY3;
+/** @deprecated */
+typedef PFNAUTHENTRY3 PAUTHENTRY3;
+
+/** Name of the FNAUTHENTRY3 entry point. */
+#define AUTHENTRY3_NAME "AuthEntry"
+
+/** @} */
+
+#endif /* !VBOX_INCLUDED_VBoxAuth_h */
diff --git a/include/VBox/VBoxCocoa.h b/include/VBox/VBoxCocoa.h
new file mode 100644
index 00000000..6409555e
--- /dev/null
+++ b/include/VBox/VBoxCocoa.h
@@ -0,0 +1,89 @@
+/** @file
+ * VBoxCocoa Helper
+ */
+
+/*
+ * Copyright (C) 2009-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_VBoxCocoa_h
+#define VBOX_INCLUDED_VBoxCocoa_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+/** Macro which add a typedef of the given Cocoa class in an appropriate form
+ * for the current context. This means void* in the C/CPP context and
+ * NSWhatever* in the ObjC/ObjCPP context. Use
+ * NativeNSWhateverRef/ConstNativeNSWhateverRef when you reference the Cocoa
+ * type somewhere. The use of this prevents extensive casting of void* to the
+ * right type in the Cocoa context. */
+#ifdef __OBJC__
+# define ADD_COCOA_NATIVE_REF(CocoaClass) \
+ @class CocoaClass; \
+ typedef CocoaClass *Native##CocoaClass##Ref; \
+ typedef const CocoaClass *ConstNative##CocoaClass##Ref
+#else /* !__OBJC__ */
+# define ADD_COCOA_NATIVE_REF(CocoaClass) \
+ typedef void *Native##CocoaClass##Ref; \
+ typedef const void *ConstNative##CocoaClass##Ref
+#endif /* !__OBJC__ */
+
+
+/*
+ * Objective-C++ Helpers.
+ */
+#if defined(__OBJC__) && defined (__cplusplus)
+
+/* Global includes */
+# import <Foundation/NSAutoreleasePool.h>
+
+/** Helper class for automatic creation & destroying of a cocoa auto release
+ * pool. */
+class CocoaAutoreleasePool
+{
+public:
+ inline CocoaAutoreleasePool()
+ {
+ mPool = [[NSAutoreleasePool alloc] init];
+ }
+ inline ~CocoaAutoreleasePool()
+ {
+ [mPool release];
+ }
+
+private:
+ NSAutoreleasePool *mPool;
+};
+
+#endif /* __OBJC__ && __cplusplus */
+
+#endif /* !VBOX_INCLUDED_VBoxCocoa_h */
+
diff --git a/include/VBox/VBoxCryptoIf.h b/include/VBox/VBoxCryptoIf.h
new file mode 100644
index 00000000..8e687d38
--- /dev/null
+++ b/include/VBox/VBoxCryptoIf.h
@@ -0,0 +1,320 @@
+/** @file
+ * VirtualBox - Cryptographic support functions Interface.
+ */
+
+/*
+ * Copyright (C) 2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_VBoxCryptoIf_h
+#define VBOX_INCLUDED_VBoxCryptoIf_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/vfs.h>
+#include <VBox/types.h>
+
+/** An opaque VBox cryptographic context handle. */
+typedef struct VBOXCRYPTOCTXINT *VBOXCRYPTOCTX;
+/**Pointer to an opaque VBox cryptographic context handle. */
+typedef VBOXCRYPTOCTX *PVBOXCRYPTOCTX;
+
+/** Magic identifying the cryptographic interface (Charles Babbage). */
+#define VBOXCRYPTOIF_MAGIC UINT32_C(0x17911226)
+
+/** Pointer to const cryptographic interface. */
+typedef const struct VBOXCRYPTOIF *PCVBOXCRYPTOIF;
+/**
+ * The main cryptographic callbacks interface table.
+ */
+typedef struct VBOXCRYPTOIF
+{
+ /** Interface magic, set to VBOXCRYPTOIF_MAGIC. */
+ uint32_t u32Magic;
+ /** Interface version.
+ * This is set to VBOXCRYPTOIF_VERSION. */
+ uint32_t u32Version;
+ /** Description string. */
+ const char *pszDesc;
+
+ /** @name Generic crytographic context operations.
+ * @{ */
+
+ /**
+ * Creates a new cryptographic context for encryption.
+ *
+ * @returns VBox status code.
+ * @param pszCipher The identifier of the cipher to use.
+ * @param pszPassword Password for encrypting the context.
+ * @param phCryptoCtx Where to store the handle to the crypto context on success.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnCryptoCtxCreate, (const char *pszCipher, const char *pszPassword,
+ PVBOXCRYPTOCTX phCryptoCtx));
+
+ /**
+ * Creates a new cryptographic context for decryption from the given base-64 encoded context.
+ *
+ * @returns VBox status code.
+ * @param pszStoredCtx The base-64 encoded context to decrypt with the given password.
+ * @param pszPassword Password for encrypting the context.
+ * @param phCryptoCtx Where to store the handle to the crypto context on success.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnCryptoCtxLoad, (const char *pszStoredCtx, const char *pszPassword,
+ PVBOXCRYPTOCTX phCryptoCtx));
+
+ /**
+ * Destroys a previously created cryptographic context.
+ *
+ * @returns VBox status code.
+ * @param hCryptoCtx Handle of crpytographic context to destroy.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnCryptoCtxDestroy, (VBOXCRYPTOCTX hCryptoCtx));
+
+ /**
+ * Returns the given cryptographic context as a base-64 encoded string.
+ *
+ * @returns VBox status code.
+ * @param hCryptoCtx Handle of crpytographic context.
+ * @param ppszStoredCtx Where to store the base-64 encoded cryptographic context on success.
+ * Must be freed with RTMemFree() when not required anymore.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnCryptoCtxSave, (VBOXCRYPTOCTX hCryptoCtx, char **ppszStoredCtx));
+
+ /**
+ * Changes the encryption password for the given context.
+ *
+ * @returns VBox status code.
+ * @param hCryptoCtx Handle of crpytographic context.
+ * @param pszPassword New password used for encrypting the DEK.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnCryptoCtxPasswordChange, (VBOXCRYPTOCTX hCryptoCtx, const char *pszPassword));
+
+ /**
+ * Queries the required size of the output buffer for encrypted data. Depends on the cipher.
+ *
+ * @returns VBox status code.
+ * @param hCryptoCtx Handle of crpytographic context.
+ * @param cbPlainText The size of the data to be encrypted.
+ * @param pcbEncrypted Where to store the size in bytes of the encrypted data on success.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnCryptoCtxQueryEncryptedSize, (VBOXCRYPTOCTX hCryptoCtx, size_t cbPlaintext,
+ size_t *pcbEncrypted));
+
+ /**
+ * Queries the required size of the output buffer for decrypted data. Depends on the cipher.
+ *
+ * @returns VBox status code.
+ * @param hCryptoCtx Handle of crpytographic context.
+ * @param cbEncrypted The size of the encrypted chunk before decryption.
+ * @param pcbPlaintext Where to store the size in bytes of the decrypted data on success.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnCryptoCtxQueryDecryptedSize, (VBOXCRYPTOCTX hCryptoCtx, size_t cbEncrypted,
+ size_t *pcbPlaintext));
+
+ /**
+ * Encrypts data.
+ *
+ * @returns VBox status code.
+ * @param hCryptoCtx Handle of crpytographic context.
+ * @param fPartial Only part of data to be encrypted is specified. The encryption
+ * cipher context will not be closed. Set to false for last piece
+ * of data, or if data is specified completely.
+ * Only CTR mode supports partial encryption.
+ * @param pvIV Pointer to IV. If null it will be generated.
+ * @param cbIV Size of the IV.
+ * @param pvPlainText Data to encrypt.
+ * @param cbPlainText Size of the data in the pvPlainText.
+ * @param pvAuthData Data used for authenticate the pvPlainText
+ * @param cbAuthData Size of the pvAuthData
+ * @param pvEncrypted Buffer to store encrypted data
+ * @param cbEncrypted Size of the buffer in pvEncrypted
+ * @param pcbEncrypted Placeholder where the size of the encrypted data returned.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnCryptoCtxEncrypt, (VBOXCRYPTOCTX hCryptoCtx, bool fPartial, void const *pvIV, size_t cbIV,
+ void const *pvPlainText, size_t cbPlainText,
+ void const *pvAuthData, size_t cbAuthData,
+ void *pvEncrypted, size_t cbEncrypted,
+ size_t *pcbEncrypted));
+
+ /**
+ * Decrypts data.
+ *
+ * @returns VBox status code.
+ * @param hCryptoCtx Handle of crpytographic context.
+ * @param fPartial Only part of data to be encrypted is specified. The encryption
+ * cipher context will not be closed. Set to false for last piece
+ * of data, or if data is specified completely.
+ * Only CTR mode supports partial encryption.
+ * @param pvEncrypted Data to decrypt.
+ * @param cbEncrypted Size of the data in the pvEncrypted.
+ * @param pvAuthData Data used for authenticate the pvEncrypted
+ * @param cbAuthData Size of the pvAuthData
+ * @param pvPlainText Buffer to store decrypted data
+ * @param cbPlainText Size of the buffer in pvPlainText
+ * @param pcbPlainText Placeholder where the size of the decrypted data returned.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnCryptoCtxDecrypt, (VBOXCRYPTOCTX hCryptoCtx, bool fPartial,
+ void const *pvEncrypted, size_t cbEncrypted,
+ void const *pvAuthData, size_t cbAuthData,
+ void *pvPlainText, size_t cbPlainText, size_t *pcbPlainText));
+ /** @} */
+
+ /** @name File based cryptographic operations.
+ * @{ */
+ /**
+ * Creates a new VFS file handle for an encrypted or to be encrypted file handle.
+ *
+ * @returns VBox status code.
+ * @param hVfsFile The input file handle, a new reference is retained upon success.
+ * @param pszKeyStore The key store containing the DEK used for encryption.
+ * @param pszPassword Password encrypting the DEK.
+ * @param phVfsFile Where to store the handle to the VFS file on success.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnCryptoFileFromVfsFile, (RTVFSFILE hVfsFile, const char *pszKeyStore, const char *pszPassword,
+ PRTVFSFILE phVfsFile));
+
+ /**
+ * Opens a new encryption I/O stream.
+ *
+ * @returns VBox status code.
+ * @param hVfsIosDst The encrypted output stream (must be writeable).
+ * The reference is not consumed, instead another
+ * one is retained.
+ * @param pszKeyStore The key store containing the DEK used for encryption.
+ * @param pszPassword Password encrypting the DEK.
+ * @param phVfsIosCrypt Where to return the crypting input I/O stream handle
+ * (you write to this).
+ */
+ DECLR3CALLBACKMEMBER(int, pfnCryptoIoStrmFromVfsIoStrmEncrypt, (RTVFSIOSTREAM hVfsIosDst, const char *pszKeyStore,
+ const char *pszPassword, PRTVFSIOSTREAM phVfsIosCrypt));
+
+ /**
+ * Opens a new decryption I/O stream.
+ *
+ * @returns VBox status code.
+ * @param hVfsIosIn The encrypted input stream (must be readable).
+ * The reference is not consumed, instead another
+ * one is retained.
+ * @param pszKeyStore The key store containing the DEK used for encryption.
+ * @param pszPassword Password encrypting the DEK.
+ * @param phVfsIosOut Where to return the handle to the decrypted I/O stream (read).
+ */
+ DECLR3CALLBACKMEMBER(int, pfnCryptoIoStrmFromVfsIoStrmDecrypt, (RTVFSIOSTREAM hVfsIosIn, const char *pszKeyStore,
+ const char *pszPassword, PRTVFSIOSTREAM phVfsIosOut));
+ /** @} */
+
+ /** @name Keystore related functions.
+ * @{ */
+ /**
+ * Return the encryption parameters and DEK from the base64 encoded key store data.
+ *
+ * @returns VBox status code.
+ * @param pszEnc The base64 encoded key store data.
+ * @param pszPassword The password to use for key decryption.
+ * If the password is NULL only the cipher is returned.
+ * @param ppbKey Where to store the DEK on success.
+ * Must be freed with RTMemSaferFree().
+ * @param pcbKey Where to store the DEK size in bytes on success.
+ * @param ppszCipher Where to store the used cipher for the decrypted DEK.
+ * Must be freed with RTStrFree().
+ */
+ DECLR3CALLBACKMEMBER(int, pfnCryptoKeyStoreGetDekFromEncoded, (const char *pszEnc, const char *pszPassword,
+ uint8_t **ppbKey, size_t *pcbKey, char **ppszCipher));
+
+ /**
+ * Stores the given DEK in a key store protected by the given password.
+ *
+ * @returns VBox status code.
+ * @param pszPassword The password to protect the DEK.
+ * @param pbKey The DEK to protect.
+ * @param cbKey Size of the DEK to protect.
+ * @param pszCipher The cipher string associated with the DEK.
+ * @param ppszEnc Where to store the base64 encoded key store data on success.
+ * Must be freed with RTMemFree().
+ */
+ DECLR3CALLBACKMEMBER(int, pfnCryptoKeyStoreCreate, (const char *pszPassword, const uint8_t *pbKey, size_t cbKey,
+ const char *pszCipher, char **ppszEnc));
+ /** @} */
+
+ DECLR3CALLBACKMEMBER(int, pfnReserved1,(void)); /**< Reserved for minor structure revisions. */
+ DECLR3CALLBACKMEMBER(int, pfnReserved2,(void)); /**< Reserved for minor structure revisions. */
+ DECLR3CALLBACKMEMBER(int, pfnReserved3,(void)); /**< Reserved for minor structure revisions. */
+ DECLR3CALLBACKMEMBER(int, pfnReserved4,(void)); /**< Reserved for minor structure revisions. */
+ DECLR3CALLBACKMEMBER(int, pfnReserved5,(void)); /**< Reserved for minor structure revisions. */
+ DECLR3CALLBACKMEMBER(int, pfnReserved6,(void)); /**< Reserved for minor structure revisions. */
+
+ /** Reserved for minor structure revisions. */
+ uint32_t uReserved7;
+
+ /** End of structure marker (VBOXCRYPTOIF_VERSION). */
+ uint32_t u32EndMarker;
+} VBOXCRYPTOIF;
+/** Current version of the VBOXCRYPTOIF structure. */
+#define VBOXCRYPTOIF_VERSION RT_MAKE_U32(0, 1)
+
+
+/**
+ * The VBoxCrypto entry callback function.
+ *
+ * @returns VBox status code.
+ * @param ppCryptoIf Where to store the pointer to the crypto module interface callback table
+ * on success.
+ */
+typedef DECLCALLBACKTYPE(int, FNVBOXCRYPTOENTRY,(PCVBOXCRYPTOIF *ppCryptoIf));
+/** Pointer to a FNVBOXCRYPTOENTRY. */
+typedef FNVBOXCRYPTOENTRY *PFNVBOXCRYPTOENTRY;
+
+/** The name of the crypto module entry point. */
+#define VBOX_CRYPTO_MOD_ENTRY_POINT "VBoxCryptoEntry"
+
+
+/**
+ * Checks if cryptographic interface version is compatible.
+ *
+ * @returns true if the do, false if they don't.
+ * @param u32Provider The provider version.
+ * @param u32User The user version.
+ */
+#define VBOXCRYPTO_IS_VER_COMPAT(u32Provider, u32User) \
+ ( VBOXCRYPTO_IS_MAJOR_VER_EQUAL(u32Provider, u32User) \
+ && (int32_t)RT_LOWORD(u32Provider) >= (int32_t)RT_LOWORD(u32User) ) /* stupid casts to shut up gcc */
+
+/**
+ * Check if two cryptographic interface versions have the same major version.
+ *
+ * @returns true if the do, false if they don't.
+ * @param u32Ver1 The first version number.
+ * @param u32Ver2 The second version number.
+ */
+#define VBOXCRYPTO_IS_MAJOR_VER_EQUAL(u32Ver1, u32Ver2) (RT_HIWORD(u32Ver1) == RT_HIWORD(u32Ver2))
+
+#endif /* !VBOX_INCLUDED_VBoxCryptoIf_h */
+
diff --git a/include/VBox/VBoxDrvCfg-win.h b/include/VBox/VBoxDrvCfg-win.h
new file mode 100644
index 00000000..5ac12ae1
--- /dev/null
+++ b/include/VBox/VBoxDrvCfg-win.h
@@ -0,0 +1,91 @@
+/* $Id: VBoxDrvCfg-win.h $ */
+/** @file
+ * Windows Driver Manipulation API.
+ */
+
+/*
+ * Copyright (C) 2011-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_VBoxDrvCfg_win_h
+#define VBOX_INCLUDED_VBoxDrvCfg_win_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/win/windows.h>
+#include <VBox/cdefs.h>
+
+RT_C_DECLS_BEGIN
+
+#if 0
+/* enable this in case we include this in a dll*/
+# ifdef IN_VBOXDRVCFG
+# define VBOXDRVCFG_DECL(a_Type) DECLEXPORT(a_Type)
+# else
+# define VBOXDRVCFG_DECL(a_Type) DECLIMPORT(a_Type)
+# endif
+#else
+/*enable this in case we include this in a static lib*/
+# define VBOXDRVCFG_DECL(a_Type) a_Type VBOXCALL
+#endif
+
+typedef enum
+{
+ VBOXDRVCFG_LOG_SEVERITY_FLOW = 1,
+ VBOXDRVCFG_LOG_SEVERITY_REGULAR,
+ VBOXDRVCFG_LOG_SEVERITY_REL
+} VBOXDRVCFG_LOG_SEVERITY_T;
+
+typedef DECLCALLBACKTYPE(void, FNVBOXDRVCFGLOG,(VBOXDRVCFG_LOG_SEVERITY_T enmSeverity, char *pszMsg, void *pvContext));
+typedef FNVBOXDRVCFGLOG *PFNVBOXDRVCFGLOG;
+
+VBOXDRVCFG_DECL(void) VBoxDrvCfgLoggerSet(PFNVBOXDRVCFGLOG pfnLog, void *pvLog);
+
+typedef DECLCALLBACKTYPE(void, FNVBOXDRVCFGPANIC,(void *pvPanic));
+typedef FNVBOXDRVCFGPANIC *PFNVBOXDRVCFGPANIC;
+VBOXDRVCFG_DECL(void) VBoxDrvCfgPanicSet(PFNVBOXDRVCFGPANIC pfnPanic, void *pvPanic);
+
+/* Driver package API*/
+VBOXDRVCFG_DECL(HRESULT) VBoxDrvCfgInfInstall(IN LPCWSTR pwszInfPath);
+VBOXDRVCFG_DECL(HRESULT) VBoxDrvCfgInfUninstall(IN LPCWSTR pwszInfPath, IN DWORD fFlags);
+VBOXDRVCFG_DECL(HRESULT) VBoxDrvCfgInfUninstallAllSetupDi(IN const GUID * pGuidClass, IN LPCWSTR pwszClassName,
+ IN LPCWSTR pwszPnPId, IN DWORD fFlags);
+VBOXDRVCFG_DECL(HRESULT) VBoxDrvCfgInfUninstallAllF(IN LPCWSTR pwszClassName, IN LPCWSTR pwszPnPId, IN DWORD fFlags);
+
+/* Service API */
+VBOXDRVCFG_DECL(HRESULT) VBoxDrvCfgSvcStart(LPCWSTR pwszSvcName);
+
+HRESULT VBoxDrvCfgDrvUpdate(LPCWSTR pszwHwId, LPCWSTR psxwInf, BOOL *pfRebootRequired);
+
+RT_C_DECLS_END
+
+#endif /* !VBOX_INCLUDED_VBoxDrvCfg_win_h */
+
diff --git a/include/VBox/VBoxGL2D.h b/include/VBox/VBoxGL2D.h
new file mode 100644
index 00000000..c0a9a4aa
--- /dev/null
+++ b/include/VBox/VBoxGL2D.h
@@ -0,0 +1,390 @@
+/** @file
+ *
+ * VBox frontends: Qt GUI ("VirtualBox"):
+ * OpenGL support info used for 2D support detection
+ */
+
+/*
+ * Copyright (C) 2009-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_VBoxGL2D_h
+#define VBOX_INCLUDED_VBoxGL2D_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+
+typedef char GLchar;
+
+#ifndef GL_COMPILE_STATUS
+# define GL_COMPILE_STATUS 0x8b81
+#endif
+#ifndef GL_LINK_STATUS
+# define GL_LINK_STATUS 0x8b82
+#endif
+#ifndef GL_FRAGMENT_SHADER
+# define GL_FRAGMENT_SHADER 0x8b30
+#endif
+#ifndef GL_VERTEX_SHADER
+# define GL_VERTEX_SHADER 0x8b31
+#endif
+
+/* GL_ARB_multitexture */
+#ifndef GL_TEXTURE0
+# define GL_TEXTURE0 0x84c0
+#endif
+#ifndef GL_TEXTURE1
+# define GL_TEXTURE1 0x84c1
+#endif
+#ifndef GL_MAX_TEXTURE_COORDS
+# define GL_MAX_TEXTURE_COORDS 0x8871
+#endif
+#ifndef GL_MAX_TEXTURE_IMAGE_UNITS
+# define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872
+#endif
+
+#ifndef APIENTRY
+# define APIENTRY
+#endif
+
+typedef GLvoid (APIENTRY *PFNVBOXVHWA_ACTIVE_TEXTURE) (GLenum texture);
+typedef GLvoid (APIENTRY *PFNVBOXVHWA_MULTI_TEX_COORD2I) (GLenum texture, GLint v0, GLint v1);
+typedef GLvoid (APIENTRY *PFNVBOXVHWA_MULTI_TEX_COORD2F) (GLenum texture, GLfloat v0, GLfloat v1);
+typedef GLvoid (APIENTRY *PFNVBOXVHWA_MULTI_TEX_COORD2D) (GLenum texture, GLdouble v0, GLdouble v1);
+
+/* GL_ARB_texture_rectangle */
+#ifndef GL_TEXTURE_RECTANGLE
+# define GL_TEXTURE_RECTANGLE 0x84F5
+#endif
+
+/* GL_ARB_shader_objects */
+/* GL_ARB_fragment_shader */
+
+typedef GLuint (APIENTRY *PFNVBOXVHWA_CREATE_SHADER) (GLenum type);
+typedef GLvoid (APIENTRY *PFNVBOXVHWA_SHADER_SOURCE) (GLuint shader, GLsizei count, const GLchar **string, const GLint *length);
+typedef GLvoid (APIENTRY *PFNVBOXVHWA_COMPILE_SHADER) (GLuint shader);
+typedef GLvoid (APIENTRY *PFNVBOXVHWA_DELETE_SHADER) (GLuint shader);
+
+typedef GLuint (APIENTRY *PFNVBOXVHWA_CREATE_PROGRAM) ();
+typedef GLvoid (APIENTRY *PFNVBOXVHWA_ATTACH_SHADER) (GLuint program, GLuint shader);
+typedef GLvoid (APIENTRY *PFNVBOXVHWA_DETACH_SHADER) (GLuint program, GLuint shader);
+typedef GLvoid (APIENTRY *PFNVBOXVHWA_LINK_PROGRAM) (GLuint program);
+typedef GLvoid (APIENTRY *PFNVBOXVHWA_USE_PROGRAM) (GLuint program);
+typedef GLvoid (APIENTRY *PFNVBOXVHWA_DELETE_PROGRAM) (GLuint program);
+
+typedef GLboolean (APIENTRY *PFNVBOXVHWA_IS_SHADER) (GLuint shader);
+typedef GLvoid (APIENTRY *PFNVBOXVHWA_GET_SHADERIV) (GLuint shader, GLenum pname, GLint *params);
+typedef GLboolean (APIENTRY *PFNVBOXVHWA_IS_PROGRAM) (GLuint program);
+typedef GLvoid (APIENTRY *PFNVBOXVHWA_GET_PROGRAMIV) (GLuint program, GLenum pname, GLint *params);
+typedef GLvoid (APIENTRY *PFNVBOXVHWA_GET_ATTACHED_SHADERS) (GLuint program, GLsizei maxCount, GLsizei *count, GLuint *shaders);
+typedef GLvoid (APIENTRY *PFNVBOXVHWA_GET_SHADER_INFO_LOG) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+typedef GLvoid (APIENTRY *PFNVBOXVHWA_GET_PROGRAM_INFO_LOG) (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+typedef GLint (APIENTRY *PFNVBOXVHWA_GET_UNIFORM_LOCATION) (GLint programObj, const GLchar *name);
+
+typedef GLvoid (APIENTRY *PFNVBOXVHWA_UNIFORM1F)(GLint location, GLfloat v0);
+typedef GLvoid (APIENTRY *PFNVBOXVHWA_UNIFORM2F)(GLint location, GLfloat v0, GLfloat v1);
+typedef GLvoid (APIENTRY *PFNVBOXVHWA_UNIFORM3F)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+typedef GLvoid (APIENTRY *PFNVBOXVHWA_UNIFORM4F)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+
+typedef GLvoid (APIENTRY *PFNVBOXVHWA_UNIFORM1I)(GLint location, GLint v0);
+typedef GLvoid (APIENTRY *PFNVBOXVHWA_UNIFORM2I)(GLint location, GLint v0, GLint v1);
+typedef GLvoid (APIENTRY *PFNVBOXVHWA_UNIFORM3I)(GLint location, GLint v0, GLint v1, GLint v2);
+typedef GLvoid (APIENTRY *PFNVBOXVHWA_UNIFORM4I)(GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+
+/* GL_ARB_pixel_buffer_object*/
+#ifndef Q_WS_MAC
+/* apears to be defined on mac */
+typedef ptrdiff_t GLsizeiptr;
+#endif
+
+#ifndef GL_READ_ONLY
+# define GL_READ_ONLY 0x88B8
+#endif
+#ifndef GL_WRITE_ONLY
+# define GL_WRITE_ONLY 0x88B9
+#endif
+#ifndef GL_READ_WRITE
+# define GL_READ_WRITE 0x88BA
+#endif
+#ifndef GL_STREAM_DRAW
+# define GL_STREAM_DRAW 0x88E0
+#endif
+#ifndef GL_STREAM_READ
+# define GL_STREAM_READ 0x88E1
+#endif
+#ifndef GL_STREAM_COPY
+# define GL_STREAM_COPY 0x88E2
+#endif
+#ifndef GL_DYNAMIC_DRAW
+# define GL_DYNAMIC_DRAW 0x88E8
+#endif
+
+#ifndef GL_PIXEL_PACK_BUFFER
+# define GL_PIXEL_PACK_BUFFER 0x88EB
+#endif
+#ifndef GL_PIXEL_UNPACK_BUFFER
+# define GL_PIXEL_UNPACK_BUFFER 0x88EC
+#endif
+#ifndef GL_PIXEL_PACK_BUFFER_BINDING
+# define GL_PIXEL_PACK_BUFFER_BINDING 0x88ED
+#endif
+#ifndef GL_PIXEL_UNPACK_BUFFER_BINDING
+# define GL_PIXEL_UNPACK_BUFFER_BINDING 0x88EF
+#endif
+
+typedef GLvoid (APIENTRY *PFNVBOXVHWA_GEN_BUFFERS)(GLsizei n, GLuint *buffers);
+typedef GLvoid (APIENTRY *PFNVBOXVHWA_DELETE_BUFFERS)(GLsizei n, const GLuint *buffers);
+typedef GLvoid (APIENTRY *PFNVBOXVHWA_BIND_BUFFER)(GLenum target, GLuint buffer);
+typedef GLvoid (APIENTRY *PFNVBOXVHWA_BUFFER_DATA)(GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage);
+typedef GLvoid* (APIENTRY *PFNVBOXVHWA_MAP_BUFFER)(GLenum target, GLenum access);
+typedef GLboolean (APIENTRY *PFNVBOXVHWA_UNMAP_BUFFER)(GLenum target);
+
+/* GL_EXT_framebuffer_object */
+#ifndef GL_FRAMEBUFFER
+# define GL_FRAMEBUFFER 0x8D40
+#endif
+#ifndef GL_COLOR_ATTACHMENT0
+# define GL_COLOR_ATTACHMENT0 0x8CE0
+#endif
+
+typedef GLboolean (APIENTRY *PFNVBOXVHWA_IS_FRAMEBUFFER)(GLuint framebuffer);
+typedef GLvoid (APIENTRY *PFNVBOXVHWA_BIND_FRAMEBUFFER)(GLenum target, GLuint framebuffer);
+typedef GLvoid (APIENTRY *PFNVBOXVHWA_DELETE_FRAMEBUFFERS)(GLsizei n, const GLuint *framebuffers);
+typedef GLvoid (APIENTRY *PFNVBOXVHWA_GEN_FRAMEBUFFERS)(GLsizei n, GLuint *framebuffers);
+typedef GLenum (APIENTRY *PFNVBOXVHWA_CHECK_FRAMEBUFFER_STATUS)(GLenum target);
+typedef GLvoid (APIENTRY *PFNVBOXVHWA_FRAMEBUFFER_TEXTURE1D)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef GLvoid (APIENTRY *PFNVBOXVHWA_FRAMEBUFFER_TEXTURE2D)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef GLvoid (APIENTRY *PFNVBOXVHWA_FRAMEBUFFER_TEXTURE3D)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
+typedef GLvoid (APIENTRY *PFNVBOXVHWA_GET_FRAMEBUFFER_ATTACHMENT_PARAMETRIV)(GLenum target, GLenum attachment, GLenum pname, GLint *params);
+
+
+/*****************/
+
+/* functions */
+
+/* @todo: move those to VBoxGLInfo class instance members ??? */
+extern PFNVBOXVHWA_ACTIVE_TEXTURE vboxglActiveTexture;
+extern PFNVBOXVHWA_MULTI_TEX_COORD2I vboxglMultiTexCoord2i;
+extern PFNVBOXVHWA_MULTI_TEX_COORD2D vboxglMultiTexCoord2d;
+extern PFNVBOXVHWA_MULTI_TEX_COORD2F vboxglMultiTexCoord2f;
+
+
+extern PFNVBOXVHWA_CREATE_SHADER vboxglCreateShader;
+extern PFNVBOXVHWA_SHADER_SOURCE vboxglShaderSource;
+extern PFNVBOXVHWA_COMPILE_SHADER vboxglCompileShader;
+extern PFNVBOXVHWA_DELETE_SHADER vboxglDeleteShader;
+
+extern PFNVBOXVHWA_CREATE_PROGRAM vboxglCreateProgram;
+extern PFNVBOXVHWA_ATTACH_SHADER vboxglAttachShader;
+extern PFNVBOXVHWA_DETACH_SHADER vboxglDetachShader;
+extern PFNVBOXVHWA_LINK_PROGRAM vboxglLinkProgram;
+extern PFNVBOXVHWA_USE_PROGRAM vboxglUseProgram;
+extern PFNVBOXVHWA_DELETE_PROGRAM vboxglDeleteProgram;
+
+extern PFNVBOXVHWA_IS_SHADER vboxglIsShader;
+extern PFNVBOXVHWA_GET_SHADERIV vboxglGetShaderiv;
+extern PFNVBOXVHWA_IS_PROGRAM vboxglIsProgram;
+extern PFNVBOXVHWA_GET_PROGRAMIV vboxglGetProgramiv;
+extern PFNVBOXVHWA_GET_ATTACHED_SHADERS vboxglGetAttachedShaders;
+extern PFNVBOXVHWA_GET_SHADER_INFO_LOG vboxglGetShaderInfoLog;
+extern PFNVBOXVHWA_GET_PROGRAM_INFO_LOG vboxglGetProgramInfoLog;
+
+extern PFNVBOXVHWA_GET_UNIFORM_LOCATION vboxglGetUniformLocation;
+
+extern PFNVBOXVHWA_UNIFORM1F vboxglUniform1f;
+extern PFNVBOXVHWA_UNIFORM2F vboxglUniform2f;
+extern PFNVBOXVHWA_UNIFORM3F vboxglUniform3f;
+extern PFNVBOXVHWA_UNIFORM4F vboxglUniform4f;
+
+extern PFNVBOXVHWA_UNIFORM1I vboxglUniform1i;
+extern PFNVBOXVHWA_UNIFORM2I vboxglUniform2i;
+extern PFNVBOXVHWA_UNIFORM3I vboxglUniform3i;
+extern PFNVBOXVHWA_UNIFORM4I vboxglUniform4i;
+
+extern PFNVBOXVHWA_GEN_BUFFERS vboxglGenBuffers;
+extern PFNVBOXVHWA_DELETE_BUFFERS vboxglDeleteBuffers;
+extern PFNVBOXVHWA_BIND_BUFFER vboxglBindBuffer;
+extern PFNVBOXVHWA_BUFFER_DATA vboxglBufferData;
+extern PFNVBOXVHWA_MAP_BUFFER vboxglMapBuffer;
+extern PFNVBOXVHWA_UNMAP_BUFFER vboxglUnmapBuffer;
+
+extern PFNVBOXVHWA_IS_FRAMEBUFFER vboxglIsFramebuffer;
+extern PFNVBOXVHWA_BIND_FRAMEBUFFER vboxglBindFramebuffer;
+extern PFNVBOXVHWA_DELETE_FRAMEBUFFERS vboxglDeleteFramebuffers;
+extern PFNVBOXVHWA_GEN_FRAMEBUFFERS vboxglGenFramebuffers;
+extern PFNVBOXVHWA_CHECK_FRAMEBUFFER_STATUS vboxglCheckFramebufferStatus;
+extern PFNVBOXVHWA_FRAMEBUFFER_TEXTURE1D vboxglFramebufferTexture1D;
+extern PFNVBOXVHWA_FRAMEBUFFER_TEXTURE2D vboxglFramebufferTexture2D;
+extern PFNVBOXVHWA_FRAMEBUFFER_TEXTURE3D vboxglFramebufferTexture3D;
+extern PFNVBOXVHWA_GET_FRAMEBUFFER_ATTACHMENT_PARAMETRIV vboxglGetFramebufferAttachmentParameteriv;
+
+
+/*
+ * Glossing over qt 5 vs 6 differences.
+ *
+ * Note! We could use the qt6 classes in 5, but we probably don't have the
+ * necessary modules in our current qt builds.
+ */
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+class QOpenGLWidget;
+class QOpenGLContext;
+# define MY_QOpenGLWidget QOpenGLWidget
+# define MY_QOpenGLContext QOpenGLContext
+#else
+class QGLWidget;
+class QGLContext;
+# define MY_QOpenGLWidget QGLWidget
+# define MY_QOpenGLContext QGLContext
+#endif
+
+
+class VBoxGLInfo
+{
+public:
+ VBoxGLInfo() :
+ mGLVersion(0),
+ mFragmentShaderSupported(false),
+ mTextureRectangleSupported(false),
+ mTextureNP2Supported(false),
+ mPBOSupported(false),
+ mFBOSupported(false),
+ mMultiTexNumSupported(1), /* 1 would mean it is not supported */
+ m_GL_ARB_multitexture(false),
+ m_GL_ARB_shader_objects(false),
+ m_GL_ARB_fragment_shader(false),
+ m_GL_ARB_pixel_buffer_object(false),
+ m_GL_ARB_texture_rectangle(false),
+ m_GL_EXT_texture_rectangle(false),
+ m_GL_NV_texture_rectangle(false),
+ m_GL_ARB_texture_non_power_of_two(false),
+ m_GL_EXT_framebuffer_object(false),
+ mInitialized(false)
+ {}
+
+ void init(const MY_QOpenGLContext *pContext);
+
+ bool isInitialized() const { return mInitialized; }
+
+ int getGLVersion() const { return mGLVersion; }
+ bool isFragmentShaderSupported() const { return mFragmentShaderSupported; }
+ bool isTextureRectangleSupported() const { return mTextureRectangleSupported; }
+ bool isTextureNP2Supported() const { return mTextureNP2Supported; }
+ bool isPBOSupported() const { return mPBOSupported; }
+ /* some ATI drivers do not seem to support non-zero offsets when dealing with PBOs
+ * @todo: add a check for that, always unsupported currently */
+ bool isPBOOffsetSupported() const { return false; }
+ bool isFBOSupported() const { return mFBOSupported; }
+ /* 1 would mean it is not supported */
+ int getMultiTexNumSupported() const { return mMultiTexNumSupported; }
+
+ static int parseVersion(const GLubyte * ver);
+private:
+ void initExtSupport(const MY_QOpenGLContext &context);
+
+ int mGLVersion;
+ bool mFragmentShaderSupported;
+ bool mTextureRectangleSupported;
+ bool mTextureNP2Supported;
+ bool mPBOSupported;
+ bool mFBOSupported;
+ int mMultiTexNumSupported; /* 1 would mean it is not supported */
+
+ bool m_GL_ARB_multitexture;
+ bool m_GL_ARB_shader_objects;
+ bool m_GL_ARB_fragment_shader;
+ bool m_GL_ARB_pixel_buffer_object;
+ bool m_GL_ARB_texture_rectangle;
+ bool m_GL_EXT_texture_rectangle;
+ bool m_GL_NV_texture_rectangle;
+ bool m_GL_ARB_texture_non_power_of_two;
+ bool m_GL_EXT_framebuffer_object;
+
+ bool mInitialized;
+};
+
+class VBoxGLTmpContext
+{
+public:
+ VBoxGLTmpContext();
+ ~VBoxGLTmpContext();
+
+ const MY_QOpenGLContext *makeCurrent();
+private:
+ MY_QOpenGLWidget *mWidget;
+};
+
+
+#define VBOXQGL_MAKEFOURCC(ch0, ch1, ch2, ch3) \
+ ((uint32_t)(uint8_t)(ch0) | ((uint32_t)(uint8_t)(ch1) << 8) | \
+ ((uint32_t)(uint8_t)(ch2) << 16) | ((uint32_t)(uint8_t)(ch3) << 24 ))
+
+#define FOURCC_AYUV VBOXQGL_MAKEFOURCC('A', 'Y', 'U', 'V')
+#define FOURCC_UYVY VBOXQGL_MAKEFOURCC('U', 'Y', 'V', 'Y')
+#define FOURCC_YUY2 VBOXQGL_MAKEFOURCC('Y', 'U', 'Y', '2')
+#define FOURCC_YV12 VBOXQGL_MAKEFOURCC('Y', 'V', '1', '2')
+#define VBOXVHWA_NUMFOURCC 4
+
+class VBoxVHWAInfo
+{
+public:
+ VBoxVHWAInfo() :
+ mFourccSupportedCount(0),
+ mInitialized(false)
+ {}
+
+ VBoxVHWAInfo(const VBoxGLInfo & glInfo) :
+ mglInfo(glInfo),
+ mFourccSupportedCount(0),
+ mInitialized(false)
+ {}
+
+ void init(const MY_QOpenGLContext *pContext);
+
+ bool isInitialized() const { return mInitialized; }
+
+ const VBoxGLInfo & getGlInfo() const { return mglInfo; }
+
+ bool isVHWASupported() const;
+
+ int getFourccSupportedCount() const { return mFourccSupportedCount; }
+ const uint32_t * getFourccSupportedList() const { return mFourccSupportedList; }
+
+ static bool checkVHWASupport();
+private:
+ VBoxGLInfo mglInfo;
+ uint32_t mFourccSupportedList[VBOXVHWA_NUMFOURCC];
+ int mFourccSupportedCount;
+
+ bool mInitialized;
+};
+
+#endif /* !VBOX_INCLUDED_VBoxGL2D_h */
diff --git a/include/VBox/VBoxGuest.h b/include/VBox/VBoxGuest.h
new file mode 100644
index 00000000..ddd78327
--- /dev/null
+++ b/include/VBox/VBoxGuest.h
@@ -0,0 +1,1012 @@
+/** @file
+ * VBoxGuest - VirtualBox Guest Additions Driver Interface. (ADD,DEV)
+ *
+ * @note This file is used by 16-bit compilers too (OpenWatcom).
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef VBOX_INCLUDED_VBoxGuest_h
+#define VBOX_INCLUDED_VBoxGuest_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/types.h>
+#include <iprt/assertcompile.h>
+#include <VBox/VMMDevCoreTypes.h>
+#include <VBox/VBoxGuestCoreTypes.h>
+
+
+
+/** @defgroup grp_vboxguest VirtualBox Guest Additions Device Driver
+ *
+ * Also know as VBoxGuest.
+ *
+ * @{
+ */
+
+/** @defgroup grp_vboxguest_ioc VirtualBox Guest Additions Driver Interface
+ *
+ * @note This is considered internal in ring-3, please use the VbglR3 functions.
+ *
+ * - I/O controls for user and/or kernel mode starts at 0.
+ * - IDC specific requests descends from 63.
+ * - Bits 7 and 6 are currently reserved for future hacks.
+ *
+ * @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(IN_RC) && !defined(IN_RING0_AGNOSTIC)
+
+/** 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(RT_OS_WINDOWS)
+# ifndef CTL_CODE
+# include <iprt/win/windows.h>
+# endif
+ /* Automatic buffering, size not encoded. */
+# define VBGL_IOCTL_CODE_SIZE(Function, Size) CTL_CODE(FILE_DEVICE_UNKNOWN, 2048 + (Function), METHOD_BUFFERED, FILE_WRITE_ACCESS)
+# define VBGL_IOCTL_CODE_BIG(Function) CTL_CODE(FILE_DEVICE_UNKNOWN, 2048 + (Function), METHOD_BUFFERED, FILE_WRITE_ACCESS)
+# define VBGL_IOCTL_CODE_FAST(Function) CTL_CODE(FILE_DEVICE_UNKNOWN, 2048 + (Function), METHOD_NEITHER, FILE_WRITE_ACCESS)
+# define VBGL_IOCTL_CODE_STRIPPED(a_uIOCtl) (a_uIOCtl)
+# 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_OS2)
+ /* No automatic buffering, size not encoded. */
+# define VBGL_IOCTL_CATEGORY 0xc2
+# define VBGL_IOCTL_CODE_SIZE(Function, Size) ((unsigned char)(Function))
+# define VBGL_IOCTL_CODE_BIG(Function) ((unsigned char)(Function))
+# define VBGL_IOCTL_CATEGORY_FAST 0xc3 /**< Also defined in VBoxGuestA-os2.asm. */
+# define VBGL_IOCTL_CODE_FAST(Function) ((unsigned char)(Function))
+# define VBGL_IOCTL_CODE_STRIPPED(a_uIOCtl) (a_uIOCtl)
+# define VBOXGUEST_DEVICE_NAME "\\Dev\\VBoxGst$"
+/** Short device name for AttachDD.
+ * @note Case sensitive. Must match what VBoxGuestA-os2.asm says! */
+# define VBOXGUEST_DEVICE_NAME_SHORT "vboxgst$"
+
+#elif defined(RT_OS_SOLARIS)
+ /* No automatic buffering, size limited to 255 bytes => use VBGLBIGREQ for everything. */
+# include <sys/ioccom.h>
+# define VBGL_IOCTL_CODE_SIZE(Function, Size) ((uintptr_t)(_IOWRN('V', (Function), sizeof(VBGLREQHDR))))
+# define VBGL_IOCTL_CODE_BIG(Function) _IOWRN('V', (Function), sizeof(VBGLREQHDR))
+# define VBGL_IOCTL_CODE_FAST(Function) _IO( 'F', (Function))
+# define VBGL_IOCTL_CODE_STRIPPED(a_uIOCtl) (a_uIOCtl)
+# define VBGL_IOCTL_IS_FAST(a_uIOCtl) ( ((a_uIOCtl) & 0x0000ff00) == ('F' << 8) )
+
+#elif defined(RT_OS_LINUX)
+ /* No automatic buffering, size limited to 16KB. */
+# include <linux/ioctl.h>
+# define VBGL_IOCTL_CODE_SIZE(Function, Size) _IOC(_IOC_READ | _IOC_WRITE, 'V', (Function), (Size))
+# define VBGL_IOCTL_CODE_BIG(Function) _IO('V', (Function))
+# define VBGL_IOCTL_CODE_FAST(Function) _IO('F', (Function))
+# define VBGL_IOCTL_CODE_STRIPPED(a_uIOCtl) _IOC_NR((a_uIOCtl))
+# define VBOXGUEST_USER_DEVICE_NAME "/dev/vboxuser"
+
+#elif defined(RT_OS_HAIKU)
+ /* No automatic buffering, size not encoded. */
+ /** @todo do something better */
+# define VBGL_IOCTL_CODE_SIZE(Function, Size) (0x56420000 | (Function))
+# define VBGL_IOCTL_CODE_BIG(Function) (0x56420000 | (Function))
+# define VBGL_IOCTL_CODE_FAST(Function) (0x56420000 | (Function))
+# define VBGL_IOCTL_CODE_STRIPPED(a_uIOCtl) (a_uIOCtl)
+# define VBOXGUEST_DEVICE_NAME "/dev/misc/vboxguest"
+
+#else /* BSD Like */
+ /* Automatic buffering, size limited to 4KB on *BSD and 8KB on Darwin - commands the limit, 4KB. */
+# include <sys/ioccom.h>
+# define VBGL_IOCTL_CODE_SIZE(Function, Size) _IOC(IOC_INOUT, 'V', (Function), (Size))
+# define VBGL_IOCTL_CODE_BIG(Function) _IO('V', (Function))
+# define VBGL_IOCTL_CODE_FAST(Function) _IO('F', (Function))
+# define VBGL_IOCTL_CODE_STRIPPED(a_uIOCtl) ((a_uIOCtl) & ~(_IOC(0,0,0,IOCPARM_MASK)))
+# define VBGL_IOCTL_IS_FAST(a_uIOCtl) ( IOCGROUP(a_uIOCtl) == 'F' )
+# if defined(RT_OS_DARWIN)
+# define VBOXGUEST_DEVICE_NAME "/dev/vboxguest"
+# define VBOXGUEST_USER_DEVICE_NAME "/dev/vboxguestu"
+# endif
+
+#endif
+
+/** @todo It would be nice if we could have two defines without paths. */
+
+/** @def VBOXGUEST_DEVICE_NAME
+ * The support device name. */
+#ifndef VBOXGUEST_DEVICE_NAME /* PORTME */
+# define VBOXGUEST_DEVICE_NAME "/dev/vboxguest"
+#endif
+
+/** @def VBOXGUEST_USER_DEVICE_NAME
+ * The support device name of the user accessible device node. */
+#ifndef VBOXGUEST_USER_DEVICE_NAME
+# define VBOXGUEST_USER_DEVICE_NAME VBOXGUEST_DEVICE_NAME
+#endif
+
+
+/**
+ * The VBoxGuest I/O control version.
+ *
+ * As usual, the high word contains the major version and changes to it
+ * signifies incompatible changes.
+ *
+ * The lower word is the minor version number, it is increased when new
+ * functions are added or existing changed in a backwards compatible manner.
+ */
+#define VBGL_IOC_VERSION UINT32_C(0x00010000)
+
+
+
+/** @name VBGL_IOCTL_DRIVER_INFO
+ * Adjust and get driver information.
+ *
+ * @note May switch the session to a backwards compatible interface version if
+ * uClientVersion indicates older client code.
+ *
+ * @{
+ */
+#define VBGL_IOCTL_DRIVER_VERSION_INFO VBGL_IOCTL_CODE_SIZE(0, VBGL_IOCTL_DRIVER_VERSION_INFO_SIZE)
+#define VBGL_IOCTL_DRIVER_VERSION_INFO_SIZE sizeof(VBGLIOCDRIVERVERSIONINFO)
+#define VBGL_IOCTL_DRIVER_VERSION_INFO_SIZE_IN RT_UOFFSET_AFTER(VBGLIOCDRIVERVERSIONINFO, u.In)
+#define VBGL_IOCTL_DRIVER_VERSION_INFO_SIZE_OUT sizeof(VBGLIOCDRIVERVERSIONINFO)
+typedef struct VBGLIOCDRIVERVERSIONINFO
+{
+ /** The header. */
+ VBGLREQHDR Hdr;
+ union
+ {
+ struct
+ {
+ /** The requested interface version number (VBGL_IOC_VERSION). */
+ uint32_t uReqVersion;
+ /** The minimum interface version number
+ * (typically the major version part of VBGL_IOC_VERSION). */
+ uint32_t uMinVersion;
+ /** Reserved, MBZ. */
+ uint32_t uReserved1;
+ /** Reserved, MBZ. */
+ uint32_t uReserved2;
+ } In;
+ struct
+ {
+ /** Interface version for this session (typically VBGL_IOC_VERSION). */
+ uint32_t uSessionVersion;
+ /** The version of the IDC interface (VBGL_IOC_VERSION). */
+ uint32_t uDriverVersion;
+ /** The SVN revision of the driver.
+ * This will be set to 0 if not compiled into the driver. */
+ uint32_t uDriverRevision;
+ /** Reserved \#1 (will be returned as zero until defined). */
+ uint32_t uReserved1;
+ /** Reserved \#2 (will be returned as zero until defined). */
+ uint32_t uReserved2;
+ } Out;
+ } u;
+} VBGLIOCDRIVERVERSIONINFO, RT_FAR *PVBGLIOCDRIVERVERSIONINFO;
+AssertCompileSize(VBGLIOCDRIVERVERSIONINFO, 24 + 20);
+#if !defined(__GNUC__) /* Some GCC versions can't handle the complicated RT_UOFFSET_AFTER macro, it seems. */ \
+ && (!defined(RT_OS_OS2) || (!defined(__IBMC__) && !defined(__IBMCPP__) && (!defined(__WATCOMC__) || !defined(__cplusplus))))
+AssertCompile(VBGL_IOCTL_DRIVER_VERSION_INFO_SIZE_IN == 24 + 16);
+#endif
+/** @} */
+
+
+/** @name VBGL_IOCTL_GET_PORT_INFO
+ * Query VMMDev I/O port region and MMIO mapping address.
+ * @remarks Ring-0 only.
+ * @{
+ */
+#define VBGL_IOCTL_GET_VMMDEV_IO_INFO VBGL_IOCTL_CODE_SIZE(1, VBGL_IOCTL_GET_VMMDEV_IO_INFO_SIZE)
+#define VBGL_IOCTL_GET_VMMDEV_IO_INFO_SIZE sizeof(VBGLIOCGETVMMDEVIOINFO)
+#define VBGL_IOCTL_GET_VMMDEV_IO_INFO_SIZE_IN sizeof(VBGLREQHDR)
+#define VBGL_IOCTL_GET_VMMDEV_IO_INFO_SIZE_OUT sizeof(VBGLIOCGETVMMDEVIOINFO)
+typedef struct VBGLIOCGETVMMDEVIOINFO
+{
+ /** The header. */
+ VBGLREQHDR Hdr;
+ union
+ {
+ struct
+ {
+ /** The MMIO mapping. NULL if no MMIO region. */
+ struct VMMDevMemory volatile RT_FAR *pvVmmDevMapping;
+ /** The I/O port address. */
+ RTIOPORT IoPort;
+ /** Padding, ignore. */
+ RTIOPORT auPadding[HC_ARCH_BITS == 64 ? 3 : 1];
+ } Out;
+ } u;
+} VBGLIOCGETVMMDEVIOINFO, RT_FAR *PVBGLIOCGETVMMDEVIOINFO;
+AssertCompileSize(VBGLIOCGETVMMDEVIOINFO, 24 + (HC_ARCH_BITS == 64 ? 16 : 8));
+/** @} */
+
+
+/** @name VBGL_IOCTL_VMMDEV_REQUEST
+ * IOCTL to VBoxGuest to perform a VMM Device request less than 1KB in size.
+ * @{
+ */
+#define VBGL_IOCTL_VMMDEV_REQUEST(a_cb) VBGL_IOCTL_CODE_SIZE(2, (a_cb))
+/** @} */
+
+
+/** @name VBGL_IOCTL_VMMDEV_REQUEST_BIG
+ * IOCTL to VBoxGuest to perform a VMM Device request that can 1KB or larger.
+ * @{
+ */
+#define VBGL_IOCTL_VMMDEV_REQUEST_BIG VBGL_IOCTL_CODE_BIG(3)
+/** @} */
+
+#ifdef VBOX_WITH_HGCM
+
+/** @name VBGL_IOCTL_HGCM_CONNECT
+ * Connect to a HGCM service.
+ * @{ */
+# define VBGL_IOCTL_HGCM_CONNECT VBGL_IOCTL_CODE_SIZE(4, VBGL_IOCTL_HGCM_CONNECT_SIZE)
+# define VBGL_IOCTL_HGCM_CONNECT_SIZE sizeof(VBGLIOCHGCMCONNECT)
+# define VBGL_IOCTL_HGCM_CONNECT_SIZE_IN sizeof(VBGLIOCHGCMCONNECT)
+# define VBGL_IOCTL_HGCM_CONNECT_SIZE_OUT RT_UOFFSET_AFTER(VBGLIOCHGCMCONNECT, u.Out)
+typedef struct VBGLIOCHGCMCONNECT
+{
+ /** The header. */
+ VBGLREQHDR Hdr;
+ union
+ {
+ struct
+ {
+ HGCMServiceLocation Loc;
+ } In;
+ struct
+ {
+ uint32_t idClient;
+ } Out;
+ } u;
+} VBGLIOCHGCMCONNECT, RT_FAR *PVBGLIOCHGCMCONNECT;
+AssertCompileSize(VBGLIOCHGCMCONNECT, 24 + 132);
+#if !defined(__GNUC__) /* Some GCC versions can't handle the complicated RT_UOFFSET_AFTER macro, it seems. */ \
+ && (!defined(RT_OS_OS2) || (!defined(__IBMC__) && !defined(__IBMCPP__) && (!defined(__WATCOMC__) || !defined(__cplusplus))))
+AssertCompile(VBGL_IOCTL_HGCM_CONNECT_SIZE_OUT == 24 + 4);
+#endif
+/** @} */
+
+
+/** @name VBGL_IOCTL_HGCM_DISCONNECT
+ * Disconnect from a HGCM service.
+ * @{ */
+# define VBGL_IOCTL_HGCM_DISCONNECT VBGL_IOCTL_CODE_SIZE(5, VBGL_IOCTL_HGCM_DISCONNECT_SIZE)
+# define VBGL_IOCTL_HGCM_DISCONNECT_SIZE sizeof(VBGLIOCHGCMDISCONNECT)
+# define VBGL_IOCTL_HGCM_DISCONNECT_SIZE_IN sizeof(VBGLIOCHGCMDISCONNECT)
+# define VBGL_IOCTL_HGCM_DISCONNECT_SIZE_OUT sizeof(VBGLREQHDR)
+/** @note This is also used by a VbglR0 API. */
+typedef struct VBGLIOCHGCMDISCONNECT
+{
+ /** The header. */
+ VBGLREQHDR Hdr;
+ union
+ {
+ struct
+ {
+ uint32_t idClient;
+ } In;
+ } u;
+} VBGLIOCHGCMDISCONNECT, RT_FAR *PVBGLIOCHGCMDISCONNECT;
+AssertCompileSize(VBGLIOCHGCMDISCONNECT, 24 + 4);
+/** @} */
+
+
+/** @name VBGL_IOCTL_HGCM_CALL, VBGL_IOCTL_HGCM_CALL_WITH_USER_DATA
+ *
+ * Make a call to a HGCM service. There are several variations here.
+ *
+ * The VBGL_IOCTL_HGCM_CALL_WITH_USER_DATA variation is for other drivers (like
+ * the graphics ones) passing on requests from user land that contains user
+ * data. These calls are always interruptible.
+ *
+ * @{ */
+# define VBGL_IOCTL_HGCM_CALL_32(a_cb) VBGL_IOCTL_CODE_SIZE(6, (a_cb))
+# define VBGL_IOCTL_HGCM_CALL_64(a_cb) VBGL_IOCTL_CODE_SIZE(7, (a_cb))
+# if ARCH_BITS == 64
+# define VBGL_IOCTL_HGCM_CALL(a_cb) VBGL_IOCTL_HGCM_CALL_64(a_cb)
+# else
+# define VBGL_IOCTL_HGCM_CALL(a_cb) VBGL_IOCTL_HGCM_CALL_32(a_cb)
+# endif
+# define VBGL_IOCTL_HGCM_CALL_WITH_USER_DATA(a_cb) VBGL_IOCTL_CODE_SIZE(8, (a_cb))
+/** @} */
+
+
+/** @name VBGL_IOCTL_IDC_HGCM_FAST_CALL
+ *
+ * Variant of VBGL_IOCTL_HGCM_CALL for drivers that submits the request as-is to
+ * the host and handles the waiting, the caller does all the rest.
+ *
+ * @note ring-0 only.
+ * @note Size is not encoded in the I/O control code.
+ * @{
+ */
+#define VBGL_IOCTL_IDC_HGCM_FAST_CALL VBGL_IOCTL_CODE_SIZE(61, sizeof(VBGLIOCIDCHGCMFASTCALL))
+#define VBGL_IOCTL_IDC_HGCM_FAST_CALL_SIZE(a_cb) (a_cb)
+#define VBGL_IOCTL_IDC_HGCM_FAST_CALL_SIZE_IN(a_cb) (a_cb)
+#define VBGL_IOCTL_IDC_HGCM_FAST_CALL_SIZE_OUT(a_cb) (a_cb)
+#pragma pack(4) /* Want it to fit nicely with the 44 byte VMMDevHGCMCall and optimally align 64-bit parameters structures. */
+typedef struct VBGLIOCIDCHGCMFASTCALL
+{
+ /** The header. */
+ VBGLREQHDR Hdr;
+ /** The physical address of the following VMMDevHGCMCall structure. */
+ RTGCPHYS32 GCPhysReq;
+ /** Set if interruptible. */
+ bool fInterruptible;
+ /** Reserved. */
+ uint8_t abReserved0[3];
+ uint64_t uTimestamp[2];
+ uint8_t abReserved1[4];
+ /* After this structure follows a VMMDevHGCMCall strcuture (44 bytes), then
+ zero or more HGCMFunctionParameter structures (12 or 16 bytes), and finally
+ page lists and embedded buffers. */
+} VBGLIOCIDCHGCMFASTCALL, RT_FAR *PVBGLIOCIDCHGCMFASTCALL;
+#pragma pack()
+AssertCompileSize(VBGLIOCIDCHGCMFASTCALL, /* 24 + 4 + 1 + 3 + 2*8 + 4 = 0x34 (52) = */ 0x34);
+
+/**
+ * Macro for initializing VBGLIOCIDCHGCMFASTCALL and the following
+ * VMMDevHGCMCall structures.
+ *
+ * @param a_pHdr The request header to initialize.
+ * @param a_HdrPhys The 32-bit physical address corresponding to @a a_pHdr.
+ * @param a_pCall Pointer to the VMMDevHGCMCall structure.
+ * @param a_idClient The HGCM client ID.
+ * @param a_uFunction The HGCM function number.
+ * @param a_cParms The number of parameters following @a a_pCall.
+ * @param a_cbReq The size of the whole request.
+ */
+#define VBGLIOCIDCHGCMFASTCALL_INIT(a_pHdr, a_HdrPhys, a_pCall, a_idClient, a_uFunction, a_cParms, a_cbReq) \
+ do { \
+ Assert((uintptr_t)(a_pHdr) + sizeof(VBGLIOCIDCHGCMFASTCALL) == (uintptr_t)(a_pCall)); \
+ VBGLREQHDR_INIT_EX(&(a_pHdr)->Hdr, a_cbReq, a_cbReq); \
+ pReq->Hdr.GCPhysReq = (a_HdrPhys) + sizeof(VBGLIOCIDCHGCMFASTCALL); \
+ pReq->Hdr.fInterruptible = false; \
+ \
+ (a_pCall)->header.header.size = (a_cbReq) - sizeof(VBGLIOCIDCHGCMFASTCALL); \
+ (a_pCall)->header.header.version = VBGLREQHDR_VERSION; \
+ (a_pCall)->header.header.requestType= (ARCH_BITS == 64 ? VMMDevReq_HGCMCall64 : VMMDevReq_HGCMCall32); \
+ (a_pCall)->header.header.rc = VERR_INTERNAL_ERROR; \
+ (a_pCall)->header.header.reserved1 = 0; \
+ (a_pCall)->header.header.fRequestor = VMMDEV_REQUESTOR_KERNEL | VMMDEV_REQUESTOR_USR_DRV_OTHER \
+ | VMMDEV_REQUESTOR_CON_DONT_KNOW | VMMDEV_REQUESTOR_TRUST_NOT_GIVEN; \
+ (a_pCall)->header.fu32Flags = 0; \
+ (a_pCall)->header.result = VERR_INTERNAL_ERROR; \
+ (a_pCall)->u32ClientID = (a_idClient); \
+ (a_pCall)->u32Function = (a_uFunction); \
+ (a_pCall)->cParms = (a_cParms); \
+ } while (0)
+
+
+/** @} */
+
+#endif /* VBOX_WITH_HGCM */
+
+
+/** @name VBGL_IOCTL_LOG
+ * IOCTL to VBoxGuest to perform backdoor logging.
+ * @{ */
+#define VBOXGUEST_IOCTL_LOG(Size)
+#define VBGL_IOCTL_LOG(a_cchMsg) VBGL_IOCTL_CODE_BIG(9)
+#define VBGL_IOCTL_LOG_SIZE(a_cchMsg) (sizeof(VBGLREQHDR) + (a_cchMsg) + 1)
+#define VBGL_IOCTL_LOG_SIZE_IN(a_cchMsg) (sizeof(VBGLREQHDR) + (a_cchMsg) + 1)
+#define VBGL_IOCTL_LOG_SIZE_OUT sizeof(VBGLREQHDR)
+typedef struct VBGLIOCLOG
+{
+ /** The header. */
+ VBGLREQHDR Hdr;
+ union
+ {
+ struct
+ {
+ /** The log message.
+ * The length is determined from the input size and zero termination. */
+ char szMsg[RT_FLEXIBLE_ARRAY_IN_NESTED_UNION];
+ } In;
+ } u;
+} VBGLIOCLOG, RT_FAR *PVBGLIOCLOG;
+/** @} */
+
+
+/** @name VBGL_IOCTL_WAIT_FOR_EVENTS
+ * Wait for a VMMDev host event notification.
+ * @{
+ */
+#define VBGL_IOCTL_WAIT_FOR_EVENTS VBGL_IOCTL_CODE_SIZE(10, VBGL_IOCTL_WAIT_FOR_EVENTS_SIZE)
+#define VBGL_IOCTL_WAIT_FOR_EVENTS_SIZE sizeof(VBGLIOCWAITFOREVENTS)
+#define VBGL_IOCTL_WAIT_FOR_EVENTS_SIZE_IN sizeof(VBGLIOCWAITFOREVENTS)
+#define VBGL_IOCTL_WAIT_FOR_EVENTS_SIZE_OUT RT_UOFFSET_AFTER(VBGLIOCWAITFOREVENTS, u.Out)
+typedef struct VBGLIOCWAITFOREVENTS
+{
+ /** The header. */
+ VBGLREQHDR Hdr;
+ union
+ {
+ struct
+ {
+ /** Timeout in milliseconds. */
+ uint32_t cMsTimeOut;
+ /** Events to wait for. */
+ uint32_t fEvents;
+ } In;
+ struct
+ {
+ /** Events that occurred. */
+ uint32_t fEvents;
+ } Out;
+ } u;
+} VBGLIOCWAITFOREVENTS, RT_FAR *PVBGLIOCWAITFOREVENTS;
+AssertCompileSize(VBGLIOCWAITFOREVENTS, 24 + 8);
+/** @} */
+
+
+/** @name VBGL_IOCTL_INTERRUPT_ALL_WAIT_FOR_EVENTS
+ * IOCTL to VBoxGuest to interrupt (cancel) any pending
+ * VBGL_IOCTL_WAIT_FOR_EVENTS and return.
+ *
+ * Handled inside the guest additions and not seen by the host at all.
+ * After calling this, VBGL_IOCTL_WAIT_FOR_EVENTS should no longer be called in
+ * the same session. At the time of writing this is not enforced; at the time
+ * of reading it may be.
+ * @see VBGL_IOCTL_WAIT_FOR_EVENTS
+ *
+ * @{
+ */
+#define VBGL_IOCTL_INTERRUPT_ALL_WAIT_FOR_EVENTS VBGL_IOCTL_CODE_SIZE(11, VBGL_IOCTL_INTERRUPT_ALL_WAIT_FOR_EVENTS_SIZE)
+#define VBGL_IOCTL_INTERRUPT_ALL_WAIT_FOR_EVENTS_SIZE sizeof(VBGLREQHDR)
+#define VBGL_IOCTL_INTERRUPT_ALL_WAIT_FOR_EVENTS_SIZE_IN sizeof(VBGLREQHDR)
+#define VBGL_IOCTL_INTERRUPT_ALL_WAIT_FOR_EVENTS_SIZE_OUT sizeof(VBGLREQHDR)
+/** @} */
+
+
+/** @name VBGL_IOCTL_CHANGE_FILTER_MASK
+ * IOCTL to VBoxGuest to control the event filter mask.
+ * @{ */
+#define VBGL_IOCTL_CHANGE_FILTER_MASK VBGL_IOCTL_CODE_SIZE(12, VBGL_IOCTL_CHANGE_FILTER_MASK_SIZE)
+#define VBGL_IOCTL_CHANGE_FILTER_MASK_SIZE sizeof(VBGLIOCCHANGEFILTERMASK)
+#define VBGL_IOCTL_CHANGE_FILTER_MASK_SIZE_IN sizeof(VBGLIOCCHANGEFILTERMASK)
+#define VBGL_IOCTL_CHANGE_FILTER_MASK_SIZE_OUT sizeof(VBGLREQHDR)
+typedef struct VBGLIOCCHANGEFILTERMASK
+{
+ /** The header. */
+ VBGLREQHDR Hdr;
+ union
+ {
+ struct
+ {
+ /** Flags to set. */
+ uint32_t fOrMask;
+ /** Flags to remove. */
+ uint32_t fNotMask;
+ } In;
+ } u;
+} VBGLIOCCHANGEFILTERMASK, RT_FAR *PVBGLIOCCHANGEFILTERMASK;
+AssertCompileSize(VBGLIOCCHANGEFILTERMASK, 24 + 8);
+/** @} */
+
+
+/** @name VBGL_IOCTL_ACQUIRE_GUEST_CAPABILITIES
+ * IOCTL to for acquiring and releasing guest capabilities.
+ *
+ * This is used for multiple purposes:
+ * 1. By doing @a acquire r3 client application (e.g. VBoxTray) claims it will
+ * use the given session for performing operations like @a seamless or
+ * @a 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.
+ *
+ *
+ * VERR_RESOURCE_BUSY is returned if any capabilities in the fOrMask are
+ * currently acquired by some other VBoxGuest session.
+ *
+ * @todo Rename to VBGL_IOCTL_ACQUIRE_GUEST_CAPS
+ * @{
+ */
+#define VBGL_IOCTL_ACQUIRE_GUEST_CAPABILITIES VBGL_IOCTL_CODE_SIZE(13, VBGL_IOCTL_ACQUIRE_GUEST_CAPABILITIES_SIZE)
+#define VBGL_IOCTL_ACQUIRE_GUEST_CAPABILITIES_SIZE sizeof(VBGLIOCACQUIREGUESTCAPS)
+#define VBGL_IOCTL_ACQUIRE_GUEST_CAPABILITIES_SIZE_IN sizeof(VBGLIOCACQUIREGUESTCAPS)
+#define VBGL_IOCTL_ACQUIRE_GUEST_CAPABILITIES_SIZE_OUT sizeof(VBGLREQHDR)
+
+/** Default operation (full acquire/release). */
+#define VBGL_IOC_AGC_FLAGS_DEFAULT UINT32_C(0x00000000)
+/** Configures VBoxGuest to use the specified caps in Acquire mode, w/o making
+ * any caps acquisition/release. This is only possible to set acquire mode for
+ * caps, but not clear it, so fNotMask is ignored when this flag is set. */
+#define VBGL_IOC_AGC_FLAGS_CONFIG_ACQUIRE_MODE UINT32_C(0x00000001)
+/** Valid flag mask. */
+#define VBGL_IOC_AGC_FLAGS_VALID_MASK UINT32_C(0x00000001)
+
+typedef struct VBGLIOCACQUIREGUESTCAPS
+{
+ /** The header. */
+ VBGLREQHDR Hdr;
+ union
+ {
+ struct
+ {
+ /** Acquire flags (VBGL_IOC_AGC_FLAGS_XXX). */
+ uint32_t fFlags;
+ /** Guest capabilities to acquire (VMMDEV_GUEST_SUPPORTS_XXX). */
+ uint32_t fOrMask;
+ /** Guest capabilities to release (VMMDEV_GUEST_SUPPORTS_XXX). */
+ uint32_t fNotMask;
+ } In;
+ } u;
+} VBGLIOCACQUIREGUESTCAPS, RT_FAR *PVBGLIOCACQUIREGUESTCAPS;
+AssertCompileSize(VBGLIOCACQUIREGUESTCAPS, 24 + 12);
+/** @} */
+
+
+/** @name VBGL_IOCTL_CHANGE_GUEST_CAPABILITIES
+ * IOCTL to VBoxGuest to set guest capabilities.
+ * @{ */
+#define VBGL_IOCTL_CHANGE_GUEST_CAPABILITIES VBGL_IOCTL_CODE_SIZE(14, VBGL_IOCTL_CHANGE_GUEST_CAPABILITIES_SIZE)
+#define VBGL_IOCTL_CHANGE_GUEST_CAPABILITIES_SIZE sizeof(VBGLIOCSETGUESTCAPS)
+#define VBGL_IOCTL_CHANGE_GUEST_CAPABILITIES_SIZE_IN sizeof(VBGLIOCSETGUESTCAPS)
+#define VBGL_IOCTL_CHANGE_GUEST_CAPABILITIES_SIZE_OUT sizeof(VBGLIOCSETGUESTCAPS)
+typedef struct VBGLIOCSETGUESTCAPS
+{
+ /** The header. */
+ VBGLREQHDR Hdr;
+ union
+ {
+ struct
+ {
+ /** The capabilities to set (VMMDEV_GUEST_SUPPORTS_XXX). */
+ uint32_t fOrMask;
+ /** The capabilities to drop (VMMDEV_GUEST_SUPPORTS_XXX). */
+ uint32_t fNotMask;
+ } In;
+ struct
+ {
+ /** The capabilities held by the session after the call (VMMDEV_GUEST_SUPPORTS_XXX). */
+ uint32_t fSessionCaps;
+ /** The capabilities for all the sessions after the call (VMMDEV_GUEST_SUPPORTS_XXX). */
+ uint32_t fGlobalCaps;
+ } Out;
+ } u;
+} VBGLIOCSETGUESTCAPS, RT_FAR *PVBGLIOCSETGUESTCAPS;
+AssertCompileSize(VBGLIOCSETGUESTCAPS, 24 + 8);
+typedef VBGLIOCSETGUESTCAPS VBoxGuestSetCapabilitiesInfo;
+/** @} */
+
+
+/** @name VBGL_IOCTL_SET_MOUSE_STATUS
+ * IOCTL to VBoxGuest to update the mouse status features.
+ * @{ */
+#define VBGL_IOCTL_SET_MOUSE_STATUS VBGL_IOCTL_CODE_SIZE(15, VBGL_IOCTL_SET_MOUSE_STATUS_SIZE)
+#define VBGL_IOCTL_SET_MOUSE_STATUS_SIZE sizeof(VBGLIOCSETMOUSESTATUS)
+#define VBGL_IOCTL_SET_MOUSE_STATUS_SIZE_IN sizeof(VBGLIOCSETMOUSESTATUS)
+#define VBGL_IOCTL_SET_MOUSE_STATUS_SIZE_OUT sizeof(VBGLREQHDR)
+typedef struct VBGLIOCSETMOUSESTATUS
+{
+ /** The header. */
+ VBGLREQHDR Hdr;
+ union
+ {
+ struct
+ {
+ /** Mouse status flags (VMMDEV_MOUSE_XXX). */
+ uint32_t fStatus;
+ } In;
+ } u;
+} VBGLIOCSETMOUSESTATUS, RT_FAR *PVBGLIOCSETMOUSESTATUS;
+/** @} */
+
+
+/** @name VBGL_IOCTL_SET_MOUSE_NOTIFY_CALLBACK
+ *
+ * IOCTL to for setting the mouse driver callback.
+ * @note The callback will be called in interrupt context with the VBoxGuest
+ * device event spinlock held.
+ * @note ring-0 only.
+ *
+ * @{ */
+#define VBGL_IOCTL_SET_MOUSE_NOTIFY_CALLBACK VBGL_IOCTL_CODE_SIZE(16, VBGL_IOCTL_SET_MOUSE_NOTIFY_CALLBACK_SIZE)
+#define VBGL_IOCTL_SET_MOUSE_NOTIFY_CALLBACK_SIZE sizeof(VBGLIOCSETMOUSENOTIFYCALLBACK)
+#define VBGL_IOCTL_SET_MOUSE_NOTIFY_CALLBACK_SIZE_IN sizeof(VBGLIOCSETMOUSENOTIFYCALLBACK)
+#define VBGL_IOCTL_SET_MOUSE_NOTIFY_CALLBACK_SIZE_OUT sizeof(VBGLREQHDR)
+typedef struct VBGLIOCSETMOUSENOTIFYCALLBACK
+{
+ /** The header. */
+ VBGLREQHDR Hdr;
+ union
+ {
+ struct
+ {
+ /** Mouse notification callback function. */
+ PFNVBOXGUESTMOUSENOTIFY pfnNotify;
+ /** The callback argument. */
+ void RT_FAR *pvUser;
+ } In;
+ } u;
+} VBGLIOCSETMOUSENOTIFYCALLBACK, RT_FAR *PVBGLIOCSETMOUSENOTIFYCALLBACK;
+/** @} */
+
+
+/** @name VBGL_IOCTL_CHECK_BALLOON
+ * 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 (VBGL_IOCTL_CHANGE_BALLOON).
+ * @{ */
+#define VBGL_IOCTL_CHECK_BALLOON VBGL_IOCTL_CODE_SIZE(17, VBGL_IOCTL_CHECK_BALLOON_SIZE)
+#define VBGL_IOCTL_CHECK_BALLOON_SIZE sizeof(VBGLIOCCHECKBALLOON)
+#define VBGL_IOCTL_CHECK_BALLOON_SIZE_IN sizeof(VBGLREQHDR)
+#define VBGL_IOCTL_CHECK_BALLOON_SIZE_OUT sizeof(VBGLIOCCHECKBALLOON)
+typedef struct VBGLIOCCHECKBALLOON
+{
+ /** The header. */
+ VBGLREQHDR Hdr;
+ union
+ {
+ struct
+ {
+ /** 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. */
+ bool fHandleInR3;
+ /** Explicit padding, please ignore. */
+ bool afPadding[3];
+ } Out;
+ } u;
+} VBGLIOCCHECKBALLOON, RT_FAR *PVBGLIOCCHECKBALLOON;
+AssertCompileSize(VBGLIOCCHECKBALLOON, 24 + 8);
+typedef VBGLIOCCHECKBALLOON VBoxGuestCheckBalloonInfo;
+/** @} */
+
+
+/** @name VBGL_IOCTL_CHANGE_BALLOON
+ * 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 VBGL_IOCTL_CHANGE_BALLOON VBGL_IOCTL_CODE_SIZE(18, VBGL_IOCTL_CHANGE_BALLOON_SIZE)
+#define VBGL_IOCTL_CHANGE_BALLOON_SIZE sizeof(VBGLIOCCHANGEBALLOON)
+#define VBGL_IOCTL_CHANGE_BALLOON_SIZE_IN sizeof(VBGLIOCCHANGEBALLOON)
+#define VBGL_IOCTL_CHANGE_BALLOON_SIZE_OUT sizeof(VBGLREQHDR)
+typedef struct VBGLIOCCHANGEBALLOON
+{
+ /** The header. */
+ VBGLREQHDR Hdr;
+ union
+ {
+ struct
+ {
+ /** Address of the chunk (user space address). */
+ RTR3PTR pvChunk;
+ /** Explicit alignment padding, MBZ. */
+ uint8_t abPadding[ARCH_BITS == 64 ? 0 + 7 : 4 + 7];
+ /** true = inflate, false = deflate. */
+ bool fInflate;
+ } In;
+ } u;
+} VBGLIOCCHANGEBALLOON, RT_FAR *PVBGLIOCCHANGEBALLOON;
+AssertCompileSize(VBGLIOCCHANGEBALLOON, 24+16);
+/** @} */
+
+
+/** @name VBGL_IOCTL_WRITE_CORE_DUMP
+ * IOCTL to VBoxGuest to write guest core.
+ * @{ */
+#define VBGL_IOCTL_WRITE_CORE_DUMP VBGL_IOCTL_CODE_SIZE(19, VBGL_IOCTL_WRITE_CORE_DUMP_SIZE)
+#define VBGL_IOCTL_WRITE_CORE_DUMP_SIZE sizeof(VBGLIOCWRITECOREDUMP)
+#define VBGL_IOCTL_WRITE_CORE_DUMP_SIZE_IN sizeof(VBGLIOCWRITECOREDUMP)
+#define VBGL_IOCTL_WRITE_CORE_DUMP_SIZE_OUT sizeof(VBGLREQHDR)
+typedef struct VBGLIOCWRITECOREDUMP
+{
+ /** The header. */
+ VBGLREQHDR Hdr;
+ union
+ {
+ struct
+ {
+ /** Flags (reserved, MBZ). */
+ uint32_t fFlags;
+ } In;
+ } u;
+} VBGLIOCWRITECOREDUMP, RT_FAR *PVBGLIOCWRITECOREDUMP;
+AssertCompileSize(VBGLIOCWRITECOREDUMP, 24 + 4);
+typedef VBGLIOCWRITECOREDUMP VBoxGuestWriteCoreDump;
+/** @} */
+
+
+#ifdef VBOX_WITH_DPC_LATENCY_CHECKER
+/** @name VBGL_IOCTL_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 VBGL_IOCTL_DPC_LATENCY_CHECKER VBGL_IOCTL_CODE_SIZE(20, VBGL_IOCTL_DPC_LATENCY_CHECKER_SIZE)
+# define VBGL_IOCTL_DPC_LATENCY_CHECKER_SIZE sizeof(VBGLREQHDR)
+# define VBGL_IOCTL_DPC_LATENCY_CHECKER_SIZE_IN sizeof(VBGLREQHDR)
+# define VBGL_IOCTL_DPC_LATENCY_CHECKER_SIZE_OUT sizeof(VBGLREQHDR)
+/** @} */
+#endif
+
+
+#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 VBGLOS2ATTACHDD
+{
+ /** VBGL_IOC_VERSION. */
+ uint32_t u32Version;
+ /** Opaque session handle. */
+ uint32_t u32Session;
+
+ /**
+ * The 32-bit service entry point.
+ *
+ * @returns VBox status code.
+ * @param u32Session The session handle (PVBOXGUESTSESSION).
+ * @param iFunction The requested function.
+ * @param pReqHdr 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 cbReq The size of the data buffer.
+ */
+# if ARCH_BITS == 32 || defined(DOXYGEN_RUNNING)
+ DECLCALLBACKMEMBER(int, pfnServiceEP,(uint32_t u32Session, unsigned iFunction, PVBGLREQHDR pReqHdr, size_t cbReq));
+# else
+ uint32_t pfnServiceEP;
+#endif
+
+ /** 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,
+ * PVBGLREQHDR fpvData, uint16_t cbData);
+ * @endcode
+ */
+# if ARCH_BITS == 16 || defined(DOXYGEN_RUNNING)
+ DECLCALLBACKMEMBER(int, fpfnServiceEP,(uint32_t u32Session, uint16_t iFunction, PVBGLREQHDR fpvData, uint16_t cbData));
+# else
+ RTFAR16 fpfnServiceEP;
+# endif
+
+ /** 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;
+} VBGLOS2ATTACHDD;
+/** Pointer to VBOXGUESTOS2IDCCONNECT buffer. */
+typedef VBGLOS2ATTACHDD RT_FAR *PVBGLOS2ATTACHDD;
+
+/**
+ * Prototype for the 16-bit callback returned by AttachDD on OS/2.
+ * @param pAttachInfo Pointer to structure to fill in.
+ */
+# if defined(__IBMC__) || defined(__IBMCPP__)
+typedef void (* __cdecl RT_FAR_CODE PFNVBGLOS2ATTACHDD)(PVBGLOS2ATTACHDD pAttachInfo);
+# else
+typedef void (__cdecl RT_FAR_CODE *PFNVBGLOS2ATTACHDD)(PVBGLOS2ATTACHDD pAttachInfo);
+# endif
+#endif /* RT_OS_OS2 */
+
+
+/** @name VBGL_IOCL_IDC_CONNECT
+ * IDC client connect request.
+ *
+ * On platforms other than Windows and OS/2, this will also create a kernel
+ * session for the caller.
+ *
+ * @note ring-0 only.
+ * @{
+ */
+#define VBGL_IOCTL_IDC_CONNECT VBGL_IOCTL_CODE_SIZE(63, VBGL_IOCTL_IDC_CONNECT_SIZE)
+#define VBGL_IOCTL_IDC_CONNECT_SIZE sizeof(VBGLIOCIDCCONNECT)
+#define VBGL_IOCTL_IDC_CONNECT_SIZE_IN RT_UOFFSET_AFTER(VBGLIOCIDCCONNECT, u.In)
+#define VBGL_IOCTL_IDC_CONNECT_SIZE_OUT sizeof(VBGLIOCIDCCONNECT)
+typedef struct VBGLIOCIDCCONNECT
+{
+ /** The header. */
+ VBGLREQHDR Hdr;
+ /** The payload union. */
+ union
+ {
+ struct
+ {
+ /** VBGL_IOCTL_IDC_CONNECT_MAGIC_COOKIE. */
+ uint32_t u32MagicCookie;
+ /** The desired version of the I/O control interface (VBGL_IOC_VERSION). */
+ uint32_t uReqVersion;
+ /** The minimum version of the I/O control interface (VBGL_IOC_VERSION). */
+ uint32_t uMinVersion;
+ /** Reserved, MBZ. */
+ uint32_t uReserved;
+ } In;
+ struct
+ {
+ /** The session handle (opaque). */
+#if ARCH_BITS >= 32
+ void RT_FAR *pvSession;
+#else
+ uint32_t pvSession;
+#endif
+ /** The version of the I/O control interface for this session
+ * (typically VBGL_IOC_VERSION). */
+ uint32_t uSessionVersion;
+ /** The I/O control interface version for of the driver (VBGL_IOC_VERSION). */
+ uint32_t uDriverVersion;
+ /** The SVN revision of the driver.
+ * This will be set to 0 if not compiled into the driver. */
+ uint32_t uDriverRevision;
+ /** Reserved \#1 (will be returned as zero until defined). */
+ uint32_t uReserved1;
+ /** Reserved \#2 (will be returned as NULL until defined). */
+ void RT_FAR *pvReserved2;
+ } Out;
+ } u;
+} VBGLIOCIDCCONNECT, RT_FAR *PVBGLIOCIDCCONNECT;
+AssertCompileSize(VBGLIOCIDCCONNECT, 24 + 16 + (ARCH_BITS == 64 ? 8 : 4) * 2);
+#if !defined(__GNUC__) /* Some GCC versions can't handle the complicated RT_UOFFSET_AFTER macro, it seems. */ \
+ && (!defined(RT_OS_OS2) || (!defined(__IBMC__) && !defined(__IBMCPP__) && (!defined(__WATCOMC__) || !defined(__cplusplus))))
+AssertCompile(VBGL_IOCTL_IDC_CONNECT_SIZE_IN == 24 + 16);
+#endif
+#define VBGL_IOCTL_IDC_CONNECT_MAGIC_COOKIE UINT32_C(0x55aa4d5a) /**< Magic value for doing an IDC connect. */
+/** @} */
+
+
+/** @name VBGL_IOCL_IDC_DISCONNECT
+ * IDC client disconnect request.
+ *
+ * This will destroy the kernel session associated with the IDC connection.
+ *
+ * @note ring-0 only.
+ * @{
+ */
+#define VBGL_IOCTL_IDC_DISCONNECT VBGL_IOCTL_CODE_SIZE(62, VBGL_IOCTL_IDC_DISCONNECT_SIZE)
+#define VBGL_IOCTL_IDC_DISCONNECT_SIZE sizeof(VBGLIOCIDCDISCONNECT)
+#define VBGL_IOCTL_IDC_DISCONNECT_SIZE_IN sizeof(VBGLIOCIDCDISCONNECT)
+#define VBGL_IOCTL_IDC_DISCONNECT_SIZE_OUT sizeof(VBGLREQHDR)
+typedef struct VBGLIOCIDCDISCONNECT
+{
+ /** The header. */
+ VBGLREQHDR Hdr;
+ union
+ {
+ struct
+ {
+ /** The session handle for platforms where this is needed. */
+#if ARCH_BITS >= 32
+ void RT_FAR *pvSession;
+#else
+ uint32_t pvSession;
+#endif
+ } In;
+ } u;
+} VBGLIOCIDCDISCONNECT, RT_FAR *PVBGLIOCIDCDISCONNECT;
+AssertCompileSize(VBGLIOCIDCDISCONNECT, 24 + (ARCH_BITS == 64 ? 8 : 4));
+/** @} */
+
+
+#if !defined(RT_OS_WINDOWS) && !defined(RT_OS_OS2)
+RT_C_DECLS_BEGIN
+/**
+ * The VBoxGuest IDC entry point.
+ *
+ * @returns VBox status code.
+ * @param pvSession The session.
+ * @param uReq The request code.
+ * @param pReqHdr The request.
+ * @param cbReq The request size.
+ */
+int VBOXCALL VBoxGuestIDC(void RT_FAR *pvSession, uintptr_t uReq, PVBGLREQHDR pReqHdr, size_t cbReq);
+RT_C_DECLS_END
+#endif
+
+
+#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 /* !VBOX_INCLUDED_VBoxGuest_h */
+
diff --git a/include/VBox/VBoxGuestCoreTypes.h b/include/VBox/VBoxGuestCoreTypes.h
new file mode 100644
index 00000000..0d820aab
--- /dev/null
+++ b/include/VBox/VBoxGuestCoreTypes.h
@@ -0,0 +1,238 @@
+/** @file
+ * VBoxGuest - VirtualBox Guest Additions, Core Types.
+ *
+ * This contains types that are used both in the VBoxGuest I/O control interface
+ * and the VBoxGuestLib. The goal is to avoid having to include VBoxGuest.h
+ * everwhere VBoxGuestLib.h is used.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef VBOX_INCLUDED_VBoxGuestCoreTypes_h
+#define VBOX_INCLUDED_VBoxGuestCoreTypes_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+#include <iprt/assertcompile.h>
+
+/** @addtogroup grp_vboxguest
+ * @{ */
+
+/**
+ * Common in/out header.
+ *
+ * This is a copy/mirror of VMMDevRequestHeader to prevent duplicating data and
+ * needing to verify things multiple times. For that reason this differs a bit
+ * from SUPREQHDR.
+ *
+ * @sa VMMDevRequestHeader
+ */
+typedef struct VBGLREQHDR
+{
+ /** IN: The request input size, and output size if cbOut is zero.
+ * @sa VMMDevRequestHeader::size */
+ uint32_t cbIn;
+ /** IN: Structure version (VBGLREQHDR_VERSION)
+ * @sa VMMDevRequestHeader::version */
+ uint32_t uVersion;
+ /** IN: The VMMDev request type, set to VBGLREQHDR_TYPE_DEFAULT unless this is a
+ * kind of VMMDev request.
+ * @sa VMMDevRequestType, VMMDevRequestHeader::requestType */
+ uint32_t uType;
+ /** OUT: The VBox status code of the operation, out direction only. */
+ int32_t rc;
+ /** IN: The output size. This is optional - set to zero to use cbIn as the
+ * output size. */
+ uint32_t cbOut;
+ /** Reserved / filled in by kernel, MBZ.
+ * @sa VMMDevRequestHeader::fRequestor */
+ uint32_t uReserved;
+} VBGLREQHDR;
+AssertCompileSize(VBGLREQHDR, 24);
+/** Pointer to a IOC header. */
+typedef VBGLREQHDR RT_FAR *PVBGLREQHDR;
+
+/** Version of VMMDevRequestHeader structure. */
+#define VBGLREQHDR_VERSION UINT32_C(0x10001)
+/** Default request type. Use this for non-VMMDev requests. */
+#define VBGLREQHDR_TYPE_DEFAULT UINT32_C(0)
+
+/** Initialize a VBGLREQHDR structure for a fixed size I/O control call.
+ * @param a_pHdr Pointer to the header to initialize.
+ * @param a_IOCtl The base I/O control name, no VBGL_IOCTL_ prefix. We
+ * have to skip the prefix to avoid it getting expanded
+ * before we append _SIZE_IN and _SIZE_OUT to it.
+ */
+#define VBGLREQHDR_INIT(a_pHdr, a_IOCtl) \
+ VBGLREQHDR_INIT_EX(a_pHdr, RT_CONCAT3(VBGL_IOCTL_,a_IOCtl,_SIZE_IN), RT_CONCAT3(VBGL_IOCTL_,a_IOCtl,_SIZE_OUT))
+/** Initialize a VBGLREQHDR structure, extended version. */
+#define VBGLREQHDR_INIT_EX(a_pHdr, a_cbIn, a_cbOut) \
+ do { \
+ (a_pHdr)->cbIn = (uint32_t)(a_cbIn); \
+ (a_pHdr)->uVersion = VBGLREQHDR_VERSION; \
+ (a_pHdr)->uType = VBGLREQHDR_TYPE_DEFAULT; \
+ (a_pHdr)->rc = VERR_INTERNAL_ERROR; \
+ (a_pHdr)->cbOut = (uint32_t)(a_cbOut); \
+ (a_pHdr)->uReserved = 0; \
+ } while (0)
+/** Initialize a VBGLREQHDR structure for a VMMDev request.
+ * Same as VMMDEV_REQ_HDR_INIT(). */
+#define VBGLREQHDR_INIT_VMMDEV(a_pHdr, a_cb, a_enmType) \
+ do { \
+ (a_pHdr)->cbIn = (a_cb); \
+ (a_pHdr)->uVersion = VBGLREQHDR_VERSION; \
+ (a_pHdr)->uType = (a_enmType); \
+ (a_pHdr)->rc = VERR_INTERNAL_ERROR; \
+ (a_pHdr)->cbOut = 0; \
+ (a_pHdr)->uReserved = 0; \
+ } while (0)
+
+
+/**
+ * For VBGL_IOCTL_HGCM_CALL and VBGL_IOCTL_HGCM_CALL_WITH_USER_DATA.
+ *
+ * @note This is used by alot of HGCM call structures.
+ */
+typedef struct VBGLIOCHGCMCALL
+{
+ /** Common header. */
+ VBGLREQHDR Hdr;
+ /** Input: The id of the caller. */
+ uint32_t u32ClientID;
+ /** Input: Function number. */
+ uint32_t u32Function;
+ /** Input: How long to wait (milliseconds) for completion before cancelling the
+ * call. This is ignored if not a VBGL_IOCTL_HGCM_CALL_TIMED or
+ * VBGL_IOCTL_HGCM_CALL_TIMED_32 request. */
+ uint32_t cMsTimeout;
+ /** Input: Whether a timed call is interruptible (ring-0 only). This is ignored
+ * if not a VBGL_IOCTL_HGCM_CALL_TIMED or VBGL_IOCTL_HGCM_CALL_TIMED_32
+ * request, or if made from user land. */
+ bool fInterruptible;
+ /** Explicit padding, MBZ. */
+ uint8_t bReserved;
+ /** Input: How many parameters following this structure.
+ *
+ * The parameters are either HGCMFunctionParameter64 or HGCMFunctionParameter32,
+ * depending on whether we're receiving a 64-bit or 32-bit request.
+ *
+ * The current maximum is 61 parameters (given a 1KB max request size,
+ * and a 64-bit parameter size of 16 bytes).
+ *
+ * @note This information is duplicated by Hdr.cbIn, but it's currently too much
+ * work to eliminate this. */
+ uint16_t cParms;
+ /* Parameters follow in form HGCMFunctionParameter aParms[cParms] */
+} VBGLIOCHGCMCALL, RT_FAR *PVBGLIOCHGCMCALL;
+AssertCompileSize(VBGLIOCHGCMCALL, 24 + 16);
+typedef VBGLIOCHGCMCALL const RT_FAR *PCVBGLIOCHGCMCALL;
+
+/**
+ * Initialize a HGCM header (VBGLIOCHGCMCALL) for a non-timed call.
+ *
+ * @param a_pHdr The header to initalize.
+ * @param a_idClient The client connection ID to call thru.
+ * @param a_idFunction The function we're calling
+ * @param a_cParameters Number of parameters.
+ */
+# define VBGL_HGCM_HDR_INIT(a_pHdr, a_idClient, a_idFunction, a_cParameters) \
+ do { \
+ VBGLREQHDR_INIT_EX(&(a_pHdr)->Hdr, \
+ sizeof(VBGLIOCHGCMCALL) + (a_cParameters) * sizeof(HGCMFunctionParameter), \
+ sizeof(VBGLIOCHGCMCALL) + (a_cParameters) * sizeof(HGCMFunctionParameter)); \
+ (a_pHdr)->u32ClientID = (a_idClient); \
+ (a_pHdr)->u32Function = (a_idFunction); \
+ (a_pHdr)->cMsTimeout = RT_INDEFINITE_WAIT; \
+ (a_pHdr)->fInterruptible = true; \
+ (a_pHdr)->bReserved = 0; \
+ (a_pHdr)->cParms = (a_cParameters); \
+ } while (0)
+
+/**
+ * Initialize a HGCM header (VBGLIOCHGCMCALL) for a non-timed call, custom size.
+ *
+ * This is usually only needed when appending page lists to the call.
+ *
+ * @param a_pHdr The header to initalize.
+ * @param a_idClient The client connection ID to call thru.
+ * @param a_idFunction The function we're calling
+ * @param a_cParameters Number of parameters.
+ * @param a_cbReq The request size.
+ */
+# define VBGL_HGCM_HDR_INIT_EX(a_pHdr, a_idClient, a_idFunction, a_cParameters, a_cbReq) \
+ do { \
+ Assert((a_cbReq) >= sizeof(VBGLIOCHGCMCALL) + (a_cParameters) * sizeof(HGCMFunctionParameter)); \
+ VBGLREQHDR_INIT_EX(&(a_pHdr)->Hdr, (a_cbReq), (a_cbReq)); \
+ (a_pHdr)->u32ClientID = (a_idClient); \
+ (a_pHdr)->u32Function = (a_idFunction); \
+ (a_pHdr)->cMsTimeout = RT_INDEFINITE_WAIT; \
+ (a_pHdr)->fInterruptible = true; \
+ (a_pHdr)->bReserved = 0; \
+ (a_pHdr)->cParms = (a_cParameters); \
+ } while (0)
+
+/**
+ * Initialize a HGCM header (VBGLIOCHGCMCALL), with timeout (interruptible).
+ *
+ * @param a_pHdr The header to initalize.
+ * @param a_idClient The client connection ID to call thru.
+ * @param a_idFunction The function we're calling
+ * @param a_cParameters Number of parameters.
+ * @param a_cMsTimeout The timeout in milliseconds.
+ */
+# define VBGL_HGCM_HDR_INIT_TIMED(a_pHdr, a_idClient, a_idFunction, a_cParameters, a_cMsTimeout) \
+ do { \
+ VBGLREQHDR_INIT_EX(&(a_pHdr)->Hdr, \
+ sizeof(VBGLIOCHGCMCALL) + (a_cParameters) * sizeof(HGCMFunctionParameter), \
+ sizeof(VBGLIOCHGCMCALL) + (a_cParameters) * sizeof(HGCMFunctionParameter)); \
+ (a_pHdr)->u32ClientID = (a_idClient); \
+ (a_pHdr)->u32Function = (a_idFunction); \
+ (a_pHdr)->cMsTimeout = (a_cMsTimeout); \
+ (a_pHdr)->fInterruptible = true; \
+ (a_pHdr)->bReserved = 0; \
+ (a_pHdr)->cParms = (a_cParameters); \
+ } while (0)
+
+/** Get the pointer to the first HGCM parameter. */
+# define VBGL_HGCM_GET_CALL_PARMS(a_pInfo) ( (HGCMFunctionParameter *)((uint8_t *)(a_pInfo) + sizeof(VBGLIOCHGCMCALL)) )
+/** Get the pointer to the first HGCM parameter in a 32-bit request. */
+# define VBGL_HGCM_GET_CALL_PARMS32(a_pInfo) ( (HGCMFunctionParameter32 *)((uint8_t *)(a_pInfo) + sizeof(VBGLIOCHGCMCALL)) )
+
+
+/**
+ * Mouse event noticification callback function.
+ * @param pvUser Argument given when setting the callback.
+ */
+typedef DECLCALLBACKTYPE(void, FNVBOXGUESTMOUSENOTIFY,(void *pvUser));
+/** Pointer to a mouse event notification callback function. */
+typedef FNVBOXGUESTMOUSENOTIFY *PFNVBOXGUESTMOUSENOTIFY; /**< @todo fix type prefix */
+
+/** @} */
+
+#endif /* !VBOX_INCLUDED_VBoxGuestCoreTypes_h */
+
diff --git a/include/VBox/VBoxGuestLib.h b/include/VBox/VBoxGuestLib.h
new file mode 100644
index 00000000..10a92428
--- /dev/null
+++ b/include/VBox/VBoxGuestLib.h
@@ -0,0 +1,1405 @@
+/** @file
+ * VBoxGuestLib - VirtualBox Guest Additions Library.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef VBOX_INCLUDED_VBoxGuestLib_h
+#define VBOX_INCLUDED_VBoxGuestLib_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/types.h>
+#include <VBox/VMMDev.h>
+#include <VBox/VBoxGuestCoreTypes.h>
+# ifdef VBOX_WITH_DRAG_AND_DROP
+# include <VBox/GuestHost/DragAndDrop.h>
+# include <VBox/GuestHost/DragAndDropDefs.h>
+# endif
+# ifdef VBOX_WITH_SHARED_CLIPBOARD
+# include <VBox/GuestHost/SharedClipboard.h>
+# ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
+# include <VBox/GuestHost/SharedClipboard-transfers.h>
+# endif
+# endif /* VBOX_WITH_SHARED_CLIPBOARD */
+
+/** @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.
+ * @{
+ */
+#ifdef IN_RING0
+/** @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(DECL_NOTHROW(type)) VBOXCALL
+# else
+# define DECLR0VBGL(type) DECL_NOTHROW(type) VBOXCALL
+# endif
+# define DECLVBGL(type) DECLR0VBGL(type)
+
+
+/**
+ * The library initialization function to be used by the main VBoxGuest driver.
+ *
+ * @return VBox status code.
+ */
+DECLR0VBGL(int) VbglR0InitPrimary(RTIOPORT portVMMDev, VMMDevMemory *pVMMDevMemory, uint32_t *pfFeatures);
+
+/**
+ * The library termination function to be used by the main VBoxGuest driver.
+ *
+ * @author bird (2017-08-23)
+ */
+DECLR0VBGL(void) VbglR0TerminatePrimary(void);
+
+/**
+ * The library initialization function to be used by all drivers
+ * other than the main VBoxGuest system driver.
+ *
+ * @return VBox status code.
+ */
+DECLR0VBGL(int) VbglR0InitClient(void);
+
+/**
+ * The library termination function.
+ */
+DECLR0VBGL(void) VbglR0TerminateClient(void);
+
+/**
+ * Query the host feature mask.
+ *
+ * @returns VBox status code.
+ * @param pfHostFeatures Where to return the host feature mask,
+ * VMMDEV_HVF_XXX.
+ * @note Client only. May fail we're unable to connect VBoxGuest.
+ */
+DECLR0VBGL(int) VbglR0QueryHostFeatures(uint32_t *pfHostFeatures);
+
+
+/** @name The IDC Client Interface
+ * @{
+ */
+
+/**
+ * Inter-Driver Communication Handle.
+ */
+typedef union VBGLIDCHANDLE
+{
+ /** Padding for opaque usage.
+ * Must be greater or equal in size than the private struct. */
+ void *apvPadding[4];
+#ifdef VBGLIDCHANDLEPRIVATE_DECLARED
+ /** The private view. */
+ struct VBGLIDCHANDLEPRIVATE s;
+#endif
+} VBGLIDCHANDLE;
+/** Pointer to a handle. */
+typedef VBGLIDCHANDLE *PVBGLIDCHANDLE;
+
+DECLR0VBGL(int) VbglR0IdcOpen(PVBGLIDCHANDLE pHandle, uint32_t uReqVersion, uint32_t uMinVersion,
+ uint32_t *puSessionVersion, uint32_t *puDriverVersion, uint32_t *puDriverRevision);
+struct VBGLREQHDR;
+DECLR0VBGL(int) VbglR0IdcCallRaw(PVBGLIDCHANDLE pHandle, uintptr_t uReq, struct VBGLREQHDR *pReqHdr, uint32_t cbReq);
+DECLR0VBGL(int) VbglR0IdcCall(PVBGLIDCHANDLE pHandle, uintptr_t uReq, struct VBGLREQHDR *pReqHdr, uint32_t cbReq);
+DECLR0VBGL(int) VbglR0IdcClose(PVBGLIDCHANDLE pHandle);
+
+/** @} */
+
+
+/** @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.
+ */
+# if defined(VBOX_INCLUDED_VMMDev_h) || defined(DOXYGEN_RUNNING)
+DECLR0VBGL(int) VbglR0GRAlloc(struct VMMDevRequestHeader **ppReq, size_t cbReq, VMMDevRequestType enmReqType);
+# else
+DECLR0VBGL(int) VbglR0GRAlloc(struct VMMDevRequestHeader **ppReq, size_t cbReq, int32_t enmReqType);
+# endif
+
+/**
+ * Perform the generic request.
+ *
+ * @param pReq pointer the request structure.
+ *
+ * @return VBox status code.
+ */
+DECLR0VBGL(int) VbglR0GRPerform(struct VMMDevRequestHeader *pReq);
+
+/**
+ * Free the generic request memory.
+ *
+ * @param pReq pointer the request structure.
+ *
+ * @return VBox status code.
+ */
+DECLR0VBGL(void) VbglR0GRFree(struct 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.
+ */
+DECLR0VBGL(int) VbglGR0Verify(const struct VMMDevRequestHeader *pReq, size_t cbReq);
+
+/** @} */
+
+# ifdef VBOX_WITH_HGCM
+struct VBGLIOCHGCMCALL;
+struct VBGLIOCIDCHGCMFASTCALL;
+
+# 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 DECLCALLBACKTYPE(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 pLoc The service to connect to.
+ * @param fRequestor VMMDEV_REQUESTOR_XXX.
+ * @param pidClient Where to return the client ID on success.
+ * @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(HGCMServiceLocation const *pLoc, uint32_t fRequestor, HGCMCLIENTID *pidClient,
+ 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 idClient The client ID to disconnect.
+ * @param fRequestor VMMDEV_REQUESTOR_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) VbglR0HGCMInternalDisconnect(HGCMCLIENTID idClient, uint32_t fRequestor,
+ 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 fRequestor VMMDEV_REQUESTOR_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(struct VBGLIOCHGCMCALL *pCallInfo, uint32_t cbCallInfo, uint32_t fFlags, uint32_t fRequestor,
+ 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 fRequestor VMMDEV_REQUESTOR_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(struct VBGLIOCHGCMCALL *pCallInfo, uint32_t cbCallInfo, uint32_t fFlags, uint32_t fRequestor,
+ 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 */
+
+#ifndef VBGL_VBOXGUEST
+/** @internal */
+typedef struct VBGLHGCMHANDLEDATA
+{
+ uint32_t fAllocated;
+ VBGLIDCHANDLE IdcHandle;
+} VBGLHGCMHANDLEDATA;
+#else
+struct VBGLHGCMHANDLEDATA;
+#endif
+
+typedef struct VBGLHGCMHANDLEDATA *VBGLHGCMHANDLE;
+
+/** @name HGCM functions
+ * @{
+ */
+
+/**
+ * Initializes HGCM in the R0 guest library. Must be called before any HGCM
+ * connections are made. Is called by VbglInitClient().
+ *
+ * @return VBox status code.
+ */
+DECLR0VBGL(int) VbglR0HGCMInit(void);
+
+/**
+ * Terminates HGCM in the R0 guest library. Is called by VbglTerminate().
+ *
+ * @return VBox status code.
+ */
+DECLR0VBGL(int) VbglR0HGCMTerminate(void);
+
+/**
+ * Connect to a service.
+ *
+ * @param pHandle Pointer to variable that will hold a handle to be used
+ * further in VbglHGCMCall and VbglHGCMClose.
+ * @param pszServiceName The service to connect to.
+ * @param pidClient Where to return the client ID for the connection.
+ *
+ * @return VBox status code.
+ *
+ * @todo consider baking the client Id into the handle.
+ */
+DECLR0VBGL(int) VbglR0HGCMConnect(VBGLHGCMHANDLE *pHandle, const char *pszServiceName, HGCMCLIENTID *pidClient);
+
+/**
+ * Connect to a service.
+ *
+ * @param handle Handle of the connection.
+ * @param idClient The ID of the client connection.
+ *
+ * @return VBox status code.
+ *
+ * @todo consider baking the client Id into the handle.
+ */
+DECLR0VBGL(int) VbglR0HGCMDisconnect(VBGLHGCMHANDLE handle, HGCMCLIENTID idClient);
+
+/**
+ * Call to a service, returning only the I/O control status code.
+ *
+ * @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.
+ */
+DECLR0VBGL(int) VbglR0HGCMCallRaw(VBGLHGCMHANDLE handle, struct VBGLIOCHGCMCALL *pData, uint32_t cbData);
+
+/**
+ * Call to a service, returning the HGCM status code.
+ *
+ * @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. Either the I/O control status code if that failed,
+ * or the HGCM status code (pData->Hdr.rc).
+ */
+DECLR0VBGL(int) VbglR0HGCMCall(VBGLHGCMHANDLE handle, struct VBGLIOCHGCMCALL *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.
+ */
+DECLR0VBGL(int) VbglR0HGCMCallUserDataRaw(VBGLHGCMHANDLE handle, struct VBGLIOCHGCMCALL *pData, uint32_t cbData);
+
+/**
+ * Call to a service, w/o any repacking and buffer locking in VBoxGuest,
+ * returning the only request related status code (not HGCM).
+ *
+ * The driver only submits the request and waits for completion, nothing else.
+ *
+ * @param hHandle The connection handle.
+ * @param pCallReq The call request. Will be passed directly to the host.
+ * @param cbCallReq The size of the whole call request.
+ *
+ * @return VBox status code.
+ *
+ * @remarks The result of the HGCM call is found in
+ * @a pCallReq->HgcmCallReq.header.result on a successful return. The
+ * @a pCallReq->Hdr.rc and @a pCallReq->HgcmCallReq.header.header.rc
+ * fields are the same as the return value and can safely be ignored.
+ */
+DECLR0VBGL(int) VbglR0HGCMFastCall(VBGLHGCMHANDLE hHandle, struct VBGLIOCIDCHGCMFASTCALL *pCallReq, uint32_t cbCallReq);
+
+/** @} */
+
+/** @name Undocumented helpers for talking to the Chromium OpenGL Host Service
+ * @{ */
+typedef VBGLHGCMHANDLE VBGLCRCTLHANDLE;
+DECLR0VBGL(int) VbglR0CrCtlCreate(VBGLCRCTLHANDLE *phCtl);
+DECLR0VBGL(int) VbglR0CrCtlDestroy(VBGLCRCTLHANDLE hCtl);
+DECLR0VBGL(int) VbglR0CrCtlConConnect(VBGLCRCTLHANDLE hCtl, HGCMCLIENTID *pidClient);
+DECLR0VBGL(int) VbglR0CrCtlConDisconnect(VBGLCRCTLHANDLE hCtl, HGCMCLIENTID idClient);
+struct VBGLIOCHGCMCALL;
+DECLR0VBGL(int) VbglR0CrCtlConCallRaw(VBGLCRCTLHANDLE hCtl, struct VBGLIOCHGCMCALL *pCallInfo, int cbCallInfo);
+DECLR0VBGL(int) VbglR0CrCtlConCall(VBGLCRCTLHANDLE hCtl, struct VBGLIOCHGCMCALL *pCallInfo, int cbCallInfo);
+DECLR0VBGL(int) VbglR0CrCtlConCallUserDataRaw(VBGLCRCTLHANDLE hCtl, struct VBGLIOCHGCMCALL *pCallInfo, int cbCallInfo);
+/** @} */
+
+# endif /* !VBGL_VBOXGUEST */
+
+# endif /* VBOX_WITH_HGCM */
+
+
+/**
+ * Initialize the heap.
+ *
+ * @returns VBox status code.
+ */
+DECLR0VBGL(int) VbglR0PhysHeapInit(void);
+
+/**
+ * Shutdown the heap.
+ */
+DECLR0VBGL(void) VbglR0PhysHeapTerminate(void);
+
+/**
+ * Allocate a memory block.
+ *
+ * @returns Virtual address of the allocated memory block.
+ * @param cb Number of bytes to allocate.
+ */
+DECLR0VBGL(void *) VbglR0PhysHeapAlloc(uint32_t cb);
+
+/**
+ * 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. Zero is returned if @a pv
+ * isn't valid.
+ */
+DECLR0VBGL(uint32_t) VbglR0PhysHeapGetPhysAddr(void *pv);
+
+# ifdef IN_TESTCASE
+DECLVBGL(size_t) VbglR0PhysHeapGetFreeSize(void);
+# endif
+
+/**
+ * Free a memory block.
+ *
+ * @param pv Virtual address of memory block.
+ */
+DECLR0VBGL(void) VbglR0PhysHeapFree(void *pv);
+
+DECLR0VBGL(int) VbglR0QueryVMMDevMemory(struct VMMDevMemory **ppVMMDevMemory);
+DECLR0VBGL(bool) VbglR0CanUsePhysPageList(void);
+
+# ifndef VBOX_GUEST
+/** @name Mouse
+ * @{ */
+DECLR0VBGL(int) VbglR0SetMouseNotifyCallback(PFNVBOXGUESTMOUSENOTIFY pfnNotify, void *pvUser);
+DECLR0VBGL(int) VbglR0GetMouseStatus(uint32_t *pfFeatures, uint32_t *px, uint32_t *py);
+DECLR0VBGL(int) VbglR0SetMouseStatus(uint32_t fFeatures);
+/** @} */
+# endif /* VBOX_GUEST */
+
+#endif /* IN_RING0 */
+
+/** @} */
+
+
+/** @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) DECL_HIDDEN_NOTHROW(type) VBOXCALL
+
+/** @name General-purpose functions
+ * @{ */
+VBGLR3DECL(int) VbglR3Init(void);
+VBGLR3DECL(int) VbglR3InitUser(void);
+VBGLR3DECL(void) VbglR3Term(void);
+# ifdef IPRT_INCLUDED_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) VbglR3AcquireGuestCaps(uint32_t fOr, uint32_t fNot, bool fConfig);
+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);
+
+/** @} */
+
+# ifdef VBOX_WITH_SHARED_CLIPBOARD
+/** @name Shared Clipboard
+ * @{ */
+
+# ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
+/**
+ * Structure for maintaining a VbglR3 Shared Clipboard transfer context.
+ */
+typedef struct VBGLR3SHCLTRANSFERCMDCTX
+{
+ /** Default chunk size (in bytes).
+ * This is set by VbglR3ClipboardConnectEx(). */
+ uint32_t cbChunkSize;
+ /** Max chunk size (in bytes).
+ * This is set by VbglR3ClipboardConnectEx(). */
+ uint32_t cbMaxChunkSize;
+ /** Optional callbacks to invoke. */
+ SHCLTRANSFERCALLBACKTABLE Callbacks;
+} VBGLR3SHCLTRANSFERCTX;
+/** Pointer to a Shared Clipboard transfer context. */
+typedef VBGLR3SHCLTRANSFERCMDCTX *PVBGLR3SHCLTRANSFERCMDCTX;
+# endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS */
+
+/**
+ * The context required for either retrieving or sending a HGCM shared clipboard
+ * commands from or to the host.
+ *
+ * @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.
+ */
+typedef struct VBGLR3SHCLCMDCTX
+{
+ /** HGCM client ID to use for communication.
+ * This is set by VbglR3ClipboardConnectEx(). */
+ uint32_t idClient;
+ /** This is @c false if both VBOX_SHCL_HF_0_CONTEXT_ID and
+ * VBOX_SHCL_GF_0_CONTEXT_ID are set, otherwise @c true and only the old
+ * protocol (< 6.1) should be used.
+ * This is set by VbglR3ClipboardConnectEx(). */
+ bool fUseLegacyProtocol;
+ /** Host feature flags (VBOX_SHCL_HF_XXX).
+ * This is set by VbglR3ClipboardConnectEx(). */
+ uint64_t fHostFeatures;
+ /** The guest feature flags reported to the host (VBOX_SHCL_GF_XXX).
+ * This is set by VbglR3ClipboardConnectEx(). */
+ uint64_t fGuestFeatures;
+ /** The context ID - input or/and output depending on the operation. */
+ uint64_t idContext;
+ /** OUT: Number of parameters retrieved.
+ * This is set by ??. */
+ uint32_t cParmsRecived;
+# ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
+ /** Data related to Shared Clipboard file transfers. */
+ VBGLR3SHCLTRANSFERCMDCTX Transfers;
+# endif
+} VBGLR3SHCLCMDCTX;
+/** Pointer to a shared clipboard context for Vbgl. */
+typedef VBGLR3SHCLCMDCTX *PVBGLR3SHCLCMDCTX;
+
+/**
+ * Enumeration specifying a Shared Clipboard event type.
+ * @todo r=bird: Surely, this isn't necessary?!
+ */
+typedef enum _VBGLR3CLIPBOARDEVENTTYPE
+{
+ /** No event needed / defined. */
+ VBGLR3CLIPBOARDEVENTTYPE_NONE = 0,
+ /** Host reports available clipboard formats to the guest. */
+ VBGLR3CLIPBOARDEVENTTYPE_REPORT_FORMATS,
+ /** Host wants to read Shared Clipboard data from the guest. */
+ VBGLR3CLIPBOARDEVENTTYPE_READ_DATA,
+ /** Terminates the Shared Clipboard service. */
+ VBGLR3CLIPBOARDEVENTTYPE_QUIT,
+# ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
+ /** Reports a transfer status to the guest. */
+ VBGLR3CLIPBOARDEVENTTYPE_TRANSFER_STATUS,
+# endif
+ /** Blow the type up to 32-bit. */
+ VBGLR3CLIPBOARDEVENTTYPE_32BIT_HACK = 0x7fffffff
+} VBGLR3CLIPBOARDEVENTTYPE;
+
+/**
+ * Structure for keeping a Shared Clipboard VbglR3 event.
+ */
+typedef struct _VBGLR3CLIPBOARDEVENT
+{
+ /** The event type the union contains. */
+ VBGLR3CLIPBOARDEVENTTYPE enmType;
+ /** Command context bound to this event. */
+ VBGLR3SHCLCMDCTX cmdCtx;
+ union
+ {
+ /** Reports available formats from the host. */
+ SHCLFORMATS fReportedFormats;
+ /** Reports that data needs to be read from the guest. */
+ SHCLFORMAT fReadData;
+# ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
+ /** Reports a transfer status to the guest. */
+ struct
+ {
+ /** ID of the trnasfer. */
+ SHCLTRANSFERID uID;
+ /** Transfer direction. */
+ SHCLTRANSFERDIR enmDir;
+ /** Additional reproting information. */
+ SHCLTRANSFERREPORT Report;
+ } TransferStatus;
+# endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS */
+ } u;
+} VBGLR3CLIPBOARDEVENT, *PVBGLR3CLIPBOARDEVENT;
+typedef const PVBGLR3CLIPBOARDEVENT CPVBGLR3CLIPBOARDEVENT;
+
+/** @todo r=bird: I'm not sure it is appropriate for the VbglR3 to use types
+ * from VBox/GuestHost/SharedClipboard*.h, doesn't seem clean to me. */
+
+VBGLR3DECL(int) VbglR3ClipboardConnect(HGCMCLIENTID *pidClient);
+VBGLR3DECL(int) VbglR3ClipboardDisconnect(HGCMCLIENTID idClient);
+VBGLR3DECL(int) VbglR3ClipboardGetHostMsgOld(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) VbglR3ClipboardReadDataEx(PVBGLR3SHCLCMDCTX pCtx, SHCLFORMAT uFormat, void *pvData, uint32_t cbData, uint32_t *pcbRead);
+VBGLR3DECL(int) VbglR3ClipboardWriteData(HGCMCLIENTID idClient, uint32_t fFormat, void *pv, uint32_t cb);
+VBGLR3DECL(int) VbglR3ClipboardWriteDataEx(PVBGLR3SHCLCMDCTX pCtx, SHCLFORMAT fFormat, void *pvData, uint32_t cbData);
+VBGLR3DECL(int) VbglR3ClipboardReportFormats(HGCMCLIENTID idClient, uint32_t fFormats);
+
+VBGLR3DECL(int) VbglR3ClipboardConnectEx(PVBGLR3SHCLCMDCTX pCtx, uint64_t fGuestFeatures);
+VBGLR3DECL(int) VbglR3ClipboardDisconnectEx(PVBGLR3SHCLCMDCTX pCtx);
+
+VBGLR3DECL(int) VbglR3ClipboardReportFeatures(uint32_t idClient, uint64_t fGuestFeatures, uint64_t *pfHostFeatures);
+VBGLR3DECL(int) VbglR3ClipboardQueryFeatures(uint32_t idClient, uint64_t *pfHostFeatures);
+VBGLR3DECL(int) VbglR3ClipboardMsgPeekWait(PVBGLR3SHCLCMDCTX pCtx, uint32_t *pidMsg, uint32_t *pcParameters, uint64_t *pidRestoreCheck);
+VBGLR3DECL(int) VbglR3ClipboardEventGetNext(uint32_t idMsg, uint32_t cParms, PVBGLR3SHCLCMDCTX pCtx, PVBGLR3CLIPBOARDEVENT pEvent);
+VBGLR3DECL(void) VbglR3ClipboardEventFree(PVBGLR3CLIPBOARDEVENT pEvent);
+
+VBGLR3DECL(int) VbglR3ClipboardWriteError(HGCMCLIENTID idClient, int rcErr);
+
+# ifdef VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS
+VBGLR3DECL(void) VbglR3ClipboardTransferSetCallbacks(PSHCLTRANSFERCALLBACKTABLE pCallbacks);
+VBGLR3DECL(int) VbglR3ClipboardEventGetNextEx(uint32_t idMsg, uint32_t cParms, PVBGLR3SHCLCMDCTX pCtx, PSHCLTRANSFERCTX pTransferCtx, PVBGLR3CLIPBOARDEVENT pEvent);
+
+VBGLR3DECL(int) VbglR3ClipboardTransferStatusReply(PVBGLR3SHCLCMDCTX pCtx, PSHCLTRANSFER pTransfer, SHCLTRANSFERSTATUS uStatus);
+
+VBGLR3DECL(int) VbglR3ClipboardRootListRead(PVBGLR3SHCLCMDCTX pCtx, PSHCLROOTLIST *ppRootList);
+
+VBGLR3DECL(int) VbglR3ClipboardRootListHdrReadReq(PVBGLR3SHCLCMDCTX pCtx, uint32_t *pfRoots);
+VBGLR3DECL(int) VbglR3ClipboardRootListHdrReadReply(PVBGLR3SHCLCMDCTX pCtx, PSHCLROOTLIST pRootList);
+VBGLR3DECL(int) VbglR3ClipboardRootsWrite(PVBGLR3SHCLCMDCTX pCtx, PSHCLROOTLISTHDR pRoots);
+
+VBGLR3DECL(int) VbglR3ClipboardListOpenSend(PVBGLR3SHCLCMDCTX pCtx, PSHCLLISTOPENPARMS pOpenParms, PSHCLLISTHANDLE phList);
+VBGLR3DECL(int) VbglR3ClipboardListOpenRecv(PVBGLR3SHCLCMDCTX pCtx, PSHCLLISTOPENPARMS pOpenParms);
+VBGLR3DECL(int) VbglR3ClipboardListOpenReply(PVBGLR3SHCLCMDCTX pCtx, int rcReply, SHCLLISTHANDLE hList);
+
+VBGLR3DECL(int) VbglR3ClipboardListCloseSend(PVBGLR3SHCLCMDCTX pCtx, SHCLLISTHANDLE hList);
+VBGLR3DECL(int) VbglR3ClipboardListCloseRecv(PVBGLR3SHCLCMDCTX pCtx, PSHCLLISTHANDLE phList);
+
+VBGLR3DECL(int) VbglR3ClipboardListHdrWrite(PVBGLR3SHCLCMDCTX pCtx, SHCLLISTHANDLE hList, PSHCLLISTHDR pListHdr);
+VBGLR3DECL(int) VbglR3ClipboardListEntryWrite(PVBGLR3SHCLCMDCTX pCtx, SHCLLISTHANDLE hList, PSHCLLISTENTRY pListEntry);
+
+VBGLR3DECL(int) VbglR3ClipboardObjOpenRecv(PVBGLR3SHCLCMDCTX pCtx, PSHCLOBJOPENCREATEPARMS pCreateParms);
+VBGLR3DECL(int) VbglR3ClipboardObjOpenReply(PVBGLR3SHCLCMDCTX pCtx, int rcReply, SHCLOBJHANDLE hObj);
+VBGLR3DECL(int) VbglR3ClipboardObjOpenSend(PVBGLR3SHCLCMDCTX pCtx, PSHCLOBJOPENCREATEPARMS pCreateParms,
+ PSHCLOBJHANDLE phObj);
+
+VBGLR3DECL(int) VbglR3ClipboardObjCloseRecv(PVBGLR3SHCLCMDCTX pCtx, PSHCLOBJHANDLE phObj);
+VBGLR3DECL(int) VbglR3ClipboardObjCloseReply(PVBGLR3SHCLCMDCTX pCtx, int rcReply, SHCLOBJHANDLE hObj);
+VBGLR3DECL(int) VbglR3ClipboardObjCloseSend(PVBGLR3SHCLCMDCTX pCtx, SHCLOBJHANDLE hObj);
+
+VBGLR3DECL(int) VbglR3ClipboardObjReadRecv(PVBGLR3SHCLCMDCTX pCtx, PSHCLOBJHANDLE phObj, uint32_t pcbToRead,
+ uint32_t *pfFlags);
+VBGLR3DECL(int) VbglR3ClipboardObjReadSend(PVBGLR3SHCLCMDCTX pCtx, SHCLOBJHANDLE hObj, void *pvBuf, uint32_t cbBuf,
+ uint32_t *pcbRead);
+VBGLR3DECL(int) VbglR3ClipboardObjWriteSend(PVBGLR3SHCLCMDCTX pCtx, SHCLOBJHANDLE hObj, void *pvBuf, uint32_t cbBuf,
+ uint32_t *pcbWritten);
+# endif /* VBOX_WITH_SHARED_CLIPBOARD_TRANSFERS */
+/** @} */
+# endif /* VBOX_WITH_SHARED_CLIPBOARD */
+
+/** @name Seamless mode
+ * @{ */
+VBGLR3DECL(int) VbglR3SeamlessSetCap(bool fState);
+VBGLR3DECL(int) VbglR3SeamlessWaitEvent(VMMDevSeamlessMode *pMode);
+VBGLR3DECL(int) VbglR3SeamlessSendRects(uint32_t cRects, PRTRECT pRects);
+VBGLR3DECL(int) VbglR3SeamlessSendMonitorPositions(uint32_t cPositions, PRTPOINT pPositions);
+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(int) VbglR3GetDisplayChangeRequestMulti(uint32_t cDisplaysIn, uint32_t *pcDisplaysOut,
+ VMMDevDisplayDef *paDisplays, 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 VRDP
+ * @{ */
+VBGLR3DECL(int) VbglR3VrdpGetChangeRequest(bool *pfActive, uint32_t *puExperienceLevel);
+/** @} */
+
+/** @name VM Statistics
+ * @{ */
+VBGLR3DECL(int) VbglR3StatQueryInterval(uint32_t *pu32Interval);
+# if defined(VBOX_INCLUDED_VMMDev_h) || defined(DOXYGEN_RUNNING)
+VBGLR3DECL(int) VbglR3StatReport(VMMDevReportGuestStats *pReq);
+# endif
+/** @} */
+
+/** @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);
+
+/** @} */
+
+/** @name DRM client handling
+ * @{ */
+/** Guest property names pattern which is used by Guest Additions DRM services. */
+# define VBGLR3DRMPROPPTR "/VirtualBox/GuestAdd/DRM*"
+/** Guest property that defines if the DRM IPC server access should be restricted to a specific user group. */
+# define VBGLR3DRMIPCPROPRESTRICT "/VirtualBox/GuestAdd/DRMIpcRestricted"
+
+VBGLR3DECL(bool) VbglR3DrmClientIsNeeded(void);
+VBGLR3DECL(bool) VbglR3DrmRestrictedIpcAccessIsNeeded(void);
+VBGLR3DECL(bool) VbglR3DrmClientIsRunning(void);
+VBGLR3DECL(int) VbglR3DrmClientStart(void);
+VBGLR3DECL(int) VbglR3DrmLegacyClientStart(void);
+VBGLR3DECL(int) VbglR3DrmLegacyX11AgentStart(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(bool) VbglR3GuestPropExist(uint32_t idClient, const char *pszPropName);
+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) VbglR3GuestPropReadEx(uint32_t u32ClientId,
+ const char *pszPropName, char **ppszValue, char **ppszFlags, uint64_t *puTimestamp);
+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, bool *pfWasDeleted);
+/** @} */
+
+/** @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); /**< @todo r=bird: GET functions return the value, not a status code!*/
+VBGLR3DECL(int) VbglR3SharedFolderQueryFolderInfo(HGCMCLIENTID idClient, uint32_t idRoot, uint64_t fQueryFlags,
+ char **ppszName, char **ppszMountPoint,
+ uint64_t *pfFlags, uint32_t *puRootIdVersion);
+VBGLR3DECL(int) VbglR3SharedFolderWaitForMappingsChanges(HGCMCLIENTID idClient, uint32_t uPrevVersion, uint32_t *puCurVersion);
+VBGLR3DECL(int) VbglR3SharedFolderCancelMappingsChangesWaits(HGCMCLIENTID idClient);
+
+VBGLR3DECL(int) VbglR3SharedFolderGetMountPrefix(char **ppszPrefix); /**< @todo r=bird: GET functions return the value, not a status code! */
+VBGLR3DECL(int) VbglR3SharedFolderGetMountDir(char **ppszDir); /**< @todo r=bird: GET functions return the value, not a status code! */
+/** @} */
+# 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;
+
+/**
+ * Structure holding information for starting a guest
+ * session.
+ */
+typedef struct VBGLR3GUESTCTRLSESSIONSTARTUPINFO
+{
+ /** The session's protocol version to use. */
+ uint32_t uProtocol;
+ /** The session's ID. */
+ uint32_t uSessionID;
+ /** User name (account) to start the guest session under. */
+ char *pszUser;
+ /** Size (in bytes) of allocated pszUser. */
+ uint32_t cbUser;
+ /** Password of specified user name (account). */
+ char *pszPassword;
+ /** Size (in bytes) of allocated pszPassword. */
+ uint32_t cbPassword;
+ /** Domain of the user account. */
+ char *pszDomain;
+ /** Size (in bytes) of allocated pszDomain. */
+ uint32_t cbDomain;
+ /** Session creation flags.
+ * @sa VBOXSERVICECTRLSESSIONSTARTUPFLAG_* flags. */
+ uint32_t fFlags;
+} VBGLR3GUESTCTRLSESSIONSTARTUPINFO;
+/** Pointer to a guest session startup info. */
+typedef VBGLR3GUESTCTRLSESSIONSTARTUPINFO *PVBGLR3GUESTCTRLSESSIONSTARTUPINFO;
+
+/**
+ * Structure holding information for starting a guest
+ * process.
+ */
+typedef struct VBGLR3GUESTCTRLPROCSTARTUPINFO
+{
+ /** Full qualified path of process to start (without arguments).
+ * Note: This is *not* argv[0]! */
+ char *pszCmd;
+ /** Size (in bytes) of allocated pszCmd. */
+ uint32_t cbCmd;
+ /** Process execution flags. @sa */
+ uint32_t fFlags;
+ /** Command line arguments. */
+ char *pszArgs;
+ /** Size (in bytes) of allocated pszArgs. */
+ uint32_t cbArgs;
+ /** Number of arguments specified in pszArgs. */
+ uint32_t cArgs;
+ /** String of environment variables ("FOO=BAR") to pass to the process
+ * to start. */
+ char *pszEnv;
+ /** Size (in bytes) of environment variables block. */
+ uint32_t cbEnv;
+ /** Number of environment variables specified in pszEnv. */
+ uint32_t cEnvVars;
+ /** User name (account) to start the process under. */
+ char *pszUser;
+ /** Size (in bytes) of allocated pszUser. */
+ uint32_t cbUser;
+ /** Password of specified user name (account). */
+ char *pszPassword;
+ /** Size (in bytes) of allocated pszPassword. */
+ uint32_t cbPassword;
+ /** Domain to be used for authenticating the specified user name (account). */
+ char *pszDomain;
+ /** Size (in bytes) of allocated pszDomain. */
+ uint32_t cbDomain;
+ /** Time limit (in ms) of the process' life time. */
+ uint32_t uTimeLimitMS;
+ /** Process priority. */
+ uint32_t uPriority;
+ /** Process affinity block. At the moment we support
+ * up to 4 blocks, that is, 4 * 64 = 256 CPUs total. */
+ uint64_t uAffinity[4];
+ /** Number of used process affinity blocks. */
+ uint32_t cAffinity;
+} VBGLR3GUESTCTRLPROCSTARTUPINFO;
+/** Pointer to a guest process startup info. */
+typedef VBGLR3GUESTCTRLPROCSTARTUPINFO *PVBGLR3GUESTCTRLPROCSTARTUPINFO;
+
+/* General message handling on the guest. */
+VBGLR3DECL(int) VbglR3GuestCtrlConnect(uint32_t *pidClient);
+VBGLR3DECL(int) VbglR3GuestCtrlDisconnect(uint32_t idClient);
+VBGLR3DECL(bool) VbglR3GuestCtrlSupportsOptimizations(uint32_t idClient);
+VBGLR3DECL(int) VbglR3GuestCtrlMakeMeMaster(uint32_t idClient);
+VBGLR3DECL(int) VbglR3GuestCtrlReportFeatures(uint32_t idClient, uint64_t fGuestFeatures, uint64_t *pfHostFeatures);
+VBGLR3DECL(int) VbglR3GuestCtrlQueryFeatures(uint32_t idClient, uint64_t *pfHostFeatures);
+VBGLR3DECL(int) VbglR3GuestCtrlMsgFilterSet(uint32_t uClientId, uint32_t uValue, uint32_t uMaskAdd, uint32_t uMaskRemove);
+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 idClient, int rcSkip, uint32_t idMsg);
+VBGLR3DECL(int) VbglR3GuestCtrlMsgSkipOld(uint32_t uClientId);
+VBGLR3DECL(int) VbglR3GuestCtrlMsgPeekWait(uint32_t idClient, uint32_t *pidMsg, uint32_t *pcParameters, uint64_t *pidRestoreCheck);
+VBGLR3DECL(int) VbglR3GuestCtrlCancelPendingWaits(HGCMCLIENTID idClient);
+/* Guest session handling. */
+VBGLR3DECL(int) VbglR3GuestCtrlSessionStartupInfoInit(PVBGLR3GUESTCTRLSESSIONSTARTUPINFO pStartupInfo);
+VBGLR3DECL(int) VbglR3GuestCtrlSessionStartupInfoInitEx(PVBGLR3GUESTCTRLSESSIONSTARTUPINFO pStartupInfo, size_t cbUser, size_t cbPassword, size_t cbDomain);
+VBGLR3DECL(void) VbglR3GuestCtrlSessionStartupInfoDestroy(PVBGLR3GUESTCTRLSESSIONSTARTUPINFO pStartupInfo);
+VBGLR3DECL(void) VbglR3GuestCtrlSessionStartupInfoFree(PVBGLR3GUESTCTRLSESSIONSTARTUPINFO pStartupInfo);
+VBGLR3DECL(PVBGLR3GUESTCTRLSESSIONSTARTUPINFO) VbglR3GuestCtrlSessionStartupInfoDup(PVBGLR3GUESTCTRLSESSIONSTARTUPINFO pStartupInfo);
+VBGLR3DECL(int) VbglR3GuestCtrlSessionPrepare(uint32_t idClient, uint32_t idSession, void const *pvKey, uint32_t cbKey);
+VBGLR3DECL(int) VbglR3GuestCtrlSessionAccept(uint32_t idClient, uint32_t idSession, void const *pvKey, uint32_t cbKey);
+VBGLR3DECL(int) VbglR3GuestCtrlSessionCancelPrepared(uint32_t idClient, uint32_t idSession);
+VBGLR3DECL(int) VbglR3GuestCtrlSessionHasChanged(uint32_t idClient, uint64_t idNewControlSession);
+VBGLR3DECL(int) VbglR3GuestCtrlSessionClose(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t fFlags);
+VBGLR3DECL(int) VbglR3GuestCtrlSessionNotify(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t uType, int32_t iResult);
+VBGLR3DECL(int) VbglR3GuestCtrlSessionGetOpen(PVBGLR3GUESTCTRLCMDCTX pCtx, PVBGLR3GUESTCTRLSESSIONSTARTUPINFO *ppStartupInfo);
+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);
+VBGLR3DECL(int) VbglR3GuestCtrlPathGetUserDocuments(PVBGLR3GUESTCTRLCMDCTX pCtx);
+VBGLR3DECL(int) VbglR3GuestCtrlPathGetUserHome(PVBGLR3GUESTCTRLCMDCTX pCtx);
+VBGLR3DECL(int) VbglR3GuestCtrlGetShutdown(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *pfAction);
+/* Guest process execution. */
+VBGLR3DECL(int) VbglR3GuestCtrlProcStartupInfoInit(PVBGLR3GUESTCTRLPROCSTARTUPINFO pStartupInfo);
+VBGLR3DECL(int) VbglR3GuestCtrlProcStartupInfoInitEx(PVBGLR3GUESTCTRLPROCSTARTUPINFO pStartupInfo, size_t cbCmd, size_t cbUser, size_t cbPassword, size_t cbDomain, size_t cbArgs, size_t cbEnv);
+VBGLR3DECL(void) VbglR3GuestCtrlProcStartupInfoDestroy(PVBGLR3GUESTCTRLPROCSTARTUPINFO pStartupInfo);
+VBGLR3DECL(void) VbglR3GuestCtrlProcStartupInfoFree(PVBGLR3GUESTCTRLPROCSTARTUPINFO pStartupInfo);
+VBGLR3DECL(PVBGLR3GUESTCTRLPROCSTARTUPINFO) VbglR3GuestCtrlProcStartupInfoDup(PVBGLR3GUESTCTRLPROCSTARTUPINFO pStartupInfo);
+VBGLR3DECL(int) VbglR3GuestCtrlProcGetStart(PVBGLR3GUESTCTRLCMDCTX pCtx, PVBGLR3GUESTCTRLPROCSTARTUPINFO *ppStartupInfo);
+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);
+VBGLR3DECL(int) VbglR3GuestCtrlFileGetSetSize(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *puHandle, uint64_t *pcbNew);
+
+/* 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) VbglR3GuestCtrlFileCbReadOffset(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t uRc,
+ void *pvData, uint32_t cbData, int64_t offNew);
+VBGLR3DECL(int) VbglR3GuestCtrlFileCbWrite(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t uRc, uint32_t cbWritten);
+VBGLR3DECL(int) VbglR3GuestCtrlFileCbWriteOffset(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t uRc, uint32_t cbWritten, int64_t offNew);
+
+VBGLR3DECL(int) VbglR3GuestCtrlFileCbSeek(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t uRc, uint64_t offCurrent);
+VBGLR3DECL(int) VbglR3GuestCtrlFileCbTell(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t uRc, uint64_t offCurrent);
+VBGLR3DECL(int) VbglR3GuestCtrlFileCbSetSize(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t uRc, uint64_t cbNew);
+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
+ * @{ */
+struct VMMDEVSHAREDREGIONDESC;
+VBGLR3DECL(int) VbglR3RegisterSharedModule(char *pszModuleName, char *pszVersion, RTGCPTR64 GCBaseAddr, uint32_t cbModule,
+ unsigned cRegions, struct 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.
+ * Deprecated; do not used / rely on it anymore. */
+ uint32_t uProtocolDeprecated;
+ /** Host feature flags (VBOX_DND_HF_XXX).
+ * This is set by VbglR3DnDConnect(). */
+ uint64_t fHostFeatures;
+ /** The guest feature flags reported to the host (VBOX_DND_GF_XXX).
+ * This is set by VbglR3DnDConnect(). */
+ uint64_t fGuestFeatures;
+ /** Number of parameters retrieved for the current command. */
+ uint32_t uNumParms;
+ /** Max chunk size (in bytes) for data transfers. */
+ uint32_t cbMaxChunkSize;
+} VBGLR3GUESTDNDCMDCTX, *PVBGLR3GUESTDNDCMDCTX;
+
+/**
+ * Enumeration for specifying the DnD meta data type.
+ */
+typedef enum VBGLR3GUESTDNDMETADATATYPE
+{
+ /** Unknown meta data type; don't use. */
+ VBGLR3GUESTDNDMETADATATYPE_UNKNOWN = 0,
+ /** Raw meta data; can be everything. */
+ VBGLR3GUESTDNDMETADATATYPE_RAW,
+ /** Meta data is a transfer list, specifying objects. */
+ VBGLR3GUESTDNDMETADATATYPE_URI_LIST,
+ /** Blow the type up to 32-bit. */
+ VBGLR3GUESTDNDMETADATATYPE_32BIT_HACK = 0x7fffffff
+} VBGLR3GUESTDNDMETADATATYPE;
+
+/**
+ * Structure for keeping + handling DnD meta data.
+ */
+typedef struct VBGLR3GUESTDNDMETADATA
+{
+ /** The meta data type the union contains. */
+ VBGLR3GUESTDNDMETADATATYPE enmType;
+ /** Union based on \a enmType. */
+ union
+ {
+ struct
+ {
+ /** Pointer to actual meta data. */
+ void *pvMeta;
+ /** Size (in bytes) of meta data. */
+ uint32_t cbMeta;
+ } Raw;
+ struct
+ {
+ DNDTRANSFERLIST Transfer;
+ } URI;
+ } u;
+} VBGLR3GUESTDNDMETADATA;
+
+/** Pointer to VBGLR3GUESTDNDMETADATA. */
+typedef VBGLR3GUESTDNDMETADATA *PVBGLR3GUESTDNDMETADATA;
+
+/** Const pointer to VBGLR3GUESTDNDMETADATA. */
+typedef const PVBGLR3GUESTDNDMETADATA CPVBGLR3GUESTDNDMETADATA;
+
+/**
+ * Enumeration specifying a DnD event type.
+ */
+typedef enum VBGLR3DNDEVENTTYPE
+{
+ VBGLR3DNDEVENTTYPE_INVALID = 0,
+ VBGLR3DNDEVENTTYPE_CANCEL,
+ VBGLR3DNDEVENTTYPE_HG_ERROR,
+ VBGLR3DNDEVENTTYPE_HG_ENTER,
+ VBGLR3DNDEVENTTYPE_HG_MOVE,
+ VBGLR3DNDEVENTTYPE_HG_LEAVE,
+ VBGLR3DNDEVENTTYPE_HG_DROP,
+ VBGLR3DNDEVENTTYPE_HG_RECEIVE,
+# ifdef VBOX_WITH_DRAG_AND_DROP_GH
+ VBGLR3DNDEVENTTYPE_GH_ERROR,
+ VBGLR3DNDEVENTTYPE_GH_REQ_PENDING,
+ VBGLR3DNDEVENTTYPE_GH_DROP,
+# endif
+ /** Tells the caller that it has to quit operation. */
+ VBGLR3DNDEVENTTYPE_QUIT,
+ /** Blow the type up to 32-bit. */
+ VBGLR3DNDEVENTTYPE_32BIT_HACK = 0x7fffffff
+} VBGLR3DNDEVENTTYPE;
+
+typedef struct VBGLR3DNDEVENT
+{
+ /** The event type the union contains. */
+ VBGLR3DNDEVENTTYPE enmType;
+ union
+ {
+ struct
+ {
+ /** Screen ID this request belongs to. */
+ uint32_t uScreenID;
+ /** Format list (UTF-8, \r\n separated). */
+ char *pszFormats;
+ /** Size (in bytes) of pszFormats (\0 included). */
+ uint32_t cbFormats;
+ /** List of allowed DnD actions. */
+ VBOXDNDACTIONLIST dndLstActionsAllowed;
+ } HG_Enter;
+ struct
+ {
+ /** Absolute X position of guest screen. */
+ uint32_t uXpos;
+ /** Absolute Y position of guest screen. */
+ uint32_t uYpos;
+ /** Default DnD action. */
+ VBOXDNDACTION dndActionDefault;
+ } HG_Move;
+ struct
+ {
+ /** Absolute X position of guest screen. */
+ uint32_t uXpos;
+ /** Absolute Y position of guest screen. */
+ uint32_t uYpos;
+ /** Default DnD action. */
+ VBOXDNDACTION dndActionDefault;
+ } HG_Drop;
+ struct
+ {
+ /** Meta data for the operation. */
+ VBGLR3GUESTDNDMETADATA Meta;
+ } HG_Received;
+ struct
+ {
+ /** IPRT-style error code. */
+ int rc;
+ } HG_Error;
+# ifdef VBOX_WITH_DRAG_AND_DROP_GH
+ struct
+ {
+ /** Screen ID this request belongs to. */
+ uint32_t uScreenID;
+ } GH_IsPending;
+ struct
+ {
+ /** Requested format by the host. */
+ char *pszFormat;
+ /** Size (in bytes) of pszFormat (\0 included). */
+ uint32_t cbFormat;
+ /** Requested DnD action. */
+ VBOXDNDACTION dndActionRequested;
+ } GH_Drop;
+# endif
+ } u;
+} VBGLR3DNDEVENT;
+typedef VBGLR3DNDEVENT *PVBGLR3DNDEVENT;
+typedef const PVBGLR3DNDEVENT CPVBGLR3DNDEVENT;
+
+VBGLR3DECL(int) VbglR3DnDConnect(PVBGLR3GUESTDNDCMDCTX pCtx);
+VBGLR3DECL(int) VbglR3DnDDisconnect(PVBGLR3GUESTDNDCMDCTX pCtx);
+
+VBGLR3DECL(int) VbglR3DnDReportFeatures(uint32_t idClient, uint64_t fGuestFeatures, uint64_t *pfHostFeatures);
+VBGLR3DECL(int) VbglR3DnDSendError(PVBGLR3GUESTDNDCMDCTX pCtx, int rcOp);
+
+VBGLR3DECL(int) VbglR3DnDEventGetNext(PVBGLR3GUESTDNDCMDCTX pCtx, PVBGLR3DNDEVENT *ppEvent);
+VBGLR3DECL(void) VbglR3DnDEventFree(PVBGLR3DNDEVENT pEvent);
+
+VBGLR3DECL(int) VbglR3DnDHGSendAckOp(PVBGLR3GUESTDNDCMDCTX pCtx, VBOXDNDACTION dndAction);
+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, VBOXDNDACTION dndActionDefault, VBOXDNDACTIONLIST dndLstActionsAllowed, const char* pcszFormats, uint32_t cbFormats);
+VBGLR3DECL(int) VbglR3DnDGHSendData(PVBGLR3GUESTDNDCMDCTX pCtx, const char *pszFormat, void *pvData, uint32_t cbData);
+# endif /* VBOX_WITH_DRAG_AND_DROP_GH */
+/** @} */
+# endif /* VBOX_WITH_DRAG_AND_DROP */
+
+/* Generic Host Channel Service. */
+VBGLR3DECL(int) VbglR3HostChannelInit(uint32_t *pidClient);
+VBGLR3DECL(void) VbglR3HostChannelTerm(uint32_t idClient);
+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);
+struct VBGLIOCHGCMCALL;
+VBGLR3DECL(int) VbglR3HGCMCall(struct VBGLIOCHGCMCALL *pInfo, size_t cbInfo);
+/** @} */
+
+#endif /* IN_RING3 */
+/** @} */
+
+RT_C_DECLS_END
+
+/** @} */
+
+#endif /* !VBOX_INCLUDED_VBoxGuestLib_h */
diff --git a/include/VBox/VBoxGuestLibSharedFolders.h b/include/VBox/VBoxGuestLibSharedFolders.h
new file mode 100644
index 00000000..c227cc39
--- /dev/null
+++ b/include/VBox/VBoxGuestLibSharedFolders.h
@@ -0,0 +1,131 @@
+/* $Id: VBoxGuestLibSharedFolders.h $ */
+/** @file
+ * VBoxGuestLib - Central calls header.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef VBOX_INCLUDED_VBoxGuestLibSharedFolders_h
+#define VBOX_INCLUDED_VBoxGuestLibSharedFolders_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/VBoxGuestLib.h>
+#include <VBox/shflsvc.h>
+
+#ifndef IN_RING0
+# error "ring-0 only"
+#endif
+
+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 /* !VBOX_INCLUDED_VBoxGuestLibSharedFolders_h */
+
diff --git a/include/VBox/VBoxGuestLibSharedFoldersInline.h b/include/VBox/VBoxGuestLibSharedFoldersInline.h
new file mode 100644
index 00000000..7d67ffea
--- /dev/null
+++ b/include/VBox/VBoxGuestLibSharedFoldersInline.h
@@ -0,0 +1,1612 @@
+/* $Id: VBoxGuestLibSharedFoldersInline.h $ */
+/** @file
+ * VBoxGuestLib - Shared Folders Host Request Helpers (ring-0).
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef VBOX_INCLUDED_VBoxGuestLibSharedFoldersInline_h
+#define VBOX_INCLUDED_VBoxGuestLibSharedFoldersInline_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+#include <iprt/assert.h>
+#include <VBox/VBoxGuest.h>
+#include <VBox/VBoxGuestLib.h>
+#include <VBox/VBoxGuestLibSharedFolders.h>
+#include <VBox/VMMDev.h>
+#include <VBox/shflsvc.h>
+#include <iprt/err.h>
+
+
+/** @defgroup grp_vboxguest_lib_r0_sf_inline Shared Folders Host Request Helpers
+ * @ingroup grp_vboxguest_lib_r0
+ *
+ * @note Using inline functions to avoid wasting precious ring-0 stack space on
+ * passing parameters that ends up in the structure @a pReq points to. It
+ * is also safe to assume that it's faster too. It's worth a few bytes
+ * larger code section in the resulting shared folders driver.
+ *
+ * @note This currently requires a C++ compiler or a C compiler capable of
+ * mixing code and variables (i.e. C99).
+ *
+ * @{
+ */
+
+/** VMMDEV_HVF_XXX (set during init). */
+extern uint32_t g_fHostFeatures;
+extern VBGLSFCLIENT g_SfClient; /**< Move this into the parameters? */
+
+/** Request structure for VbglR0SfHostReqQueryFeatures. */
+typedef struct VBOXSFQUERYFEATURES
+{
+ VBGLIOCIDCHGCMFASTCALL Hdr;
+ VMMDevHGCMCall Call;
+ VBoxSFParmQueryFeatures Parms;
+} VBOXSFQUERYFEATURES;
+
+/**
+ * SHFL_FN_QUERY_FEATURES request.
+ */
+DECLINLINE(int) VbglR0SfHostReqQueryFeatures(VBOXSFQUERYFEATURES *pReq)
+{
+ VBGLIOCIDCHGCMFASTCALL_INIT(&pReq->Hdr, VbglR0PhysHeapGetPhysAddr(pReq), &pReq->Call, g_SfClient.idClient,
+ SHFL_FN_QUERY_FEATURES, SHFL_CPARMS_QUERY_FEATURES, sizeof(*pReq));
+
+ pReq->Parms.f64Features.type = VMMDevHGCMParmType_64bit;
+ pReq->Parms.f64Features.u.value64 = 0;
+
+ pReq->Parms.u32LastFunction.type = VMMDevHGCMParmType_32bit;
+ pReq->Parms.u32LastFunction.u.value32 = 0;
+
+ int vrc = VbglR0HGCMFastCall(g_SfClient.handle, &pReq->Hdr, sizeof(*pReq));
+ if (RT_SUCCESS(vrc))
+ vrc = pReq->Call.header.result;
+
+ /*
+ * Provide fallback values based on g_fHostFeatures to simplify
+ * compatibility with older hosts and avoid duplicating this logic.
+ */
+ if (RT_FAILURE(vrc))
+ {
+ pReq->Parms.f64Features.u.value64 = 0;
+ pReq->Parms.u32LastFunction.u.value32 = g_fHostFeatures & VMMDEV_HVF_HGCM_NO_BOUNCE_PAGE_LIST
+ ? SHFL_FN_SET_FILE_SIZE : SHFL_FN_SET_SYMLINKS;
+ if (vrc == VERR_NOT_SUPPORTED)
+ vrc = VINF_NOT_SUPPORTED;
+ }
+ return vrc;
+}
+
+/**
+ * SHFL_FN_QUERY_FEATURES request, simplified version.
+ */
+DECLINLINE(int) VbglR0SfHostReqQueryFeaturesSimple(uint64_t *pfFeatures, uint32_t *puLastFunction)
+{
+ VBOXSFQUERYFEATURES *pReq = (VBOXSFQUERYFEATURES *)VbglR0PhysHeapAlloc(sizeof(*pReq));
+ if (pReq)
+ {
+ int rc = VbglR0SfHostReqQueryFeatures(pReq);
+ if (pfFeatures)
+ *pfFeatures = pReq->Parms.f64Features.u.value64;
+ if (puLastFunction)
+ *puLastFunction = pReq->Parms.u32LastFunction.u.value32;
+
+ VbglR0PhysHeapFree(pReq);
+ return rc;
+ }
+ return VERR_NO_MEMORY;
+}
+
+
+/** Request structure for VbglR0SfHostReqSetUtf8 and VbglR0SfHostReqSetSymlink. */
+typedef struct VBOXSFNOPARMS
+{
+ VBGLIOCIDCHGCMFASTCALL Hdr;
+ VMMDevHGCMCall Call;
+ /* no parameters */
+} VBOXSFNOPARMS;
+
+/**
+ * Worker for request without any parameters.
+ */
+DECLINLINE(int) VbglR0SfHostReqNoParms(VBOXSFNOPARMS *pReq, uint32_t uFunction, uint32_t cParms)
+{
+ VBGLIOCIDCHGCMFASTCALL_INIT(&pReq->Hdr, VbglR0PhysHeapGetPhysAddr(pReq), &pReq->Call, g_SfClient.idClient,
+ uFunction, cParms, sizeof(*pReq));
+ int vrc = VbglR0HGCMFastCall(g_SfClient.handle, &pReq->Hdr, sizeof(*pReq));
+ if (RT_SUCCESS(vrc))
+ vrc = pReq->Call.header.result;
+ return vrc;
+}
+
+/**
+ * Worker for request without any parameters, simplified.
+ */
+DECLINLINE(int) VbglR0SfHostReqNoParmsSimple(uint32_t uFunction, uint32_t cParms)
+{
+ VBOXSFNOPARMS *pReq = (VBOXSFNOPARMS *)VbglR0PhysHeapAlloc(sizeof(*pReq));
+ if (pReq)
+ {
+ int vrc = VbglR0SfHostReqNoParms(pReq, uFunction, cParms);
+ VbglR0PhysHeapFree(pReq);
+ return vrc;
+ }
+ return VERR_NO_MEMORY;
+}
+
+
+/**
+ * SHFL_F_SET_UTF8 request.
+ */
+DECLINLINE(int) VbglR0SfHostReqSetUtf8(VBOXSFNOPARMS *pReq)
+{
+ return VbglR0SfHostReqNoParms(pReq, SHFL_FN_SET_UTF8, SHFL_CPARMS_SET_UTF8);
+}
+
+/**
+ * SHFL_F_SET_UTF8 request, simplified version.
+ */
+DECLINLINE(int) VbglR0SfHostReqSetUtf8Simple(void)
+{
+ return VbglR0SfHostReqNoParmsSimple(SHFL_FN_SET_UTF8, SHFL_CPARMS_SET_UTF8);
+}
+
+
+/**
+ * SHFL_F_SET_SYMLINKS request.
+ */
+DECLINLINE(int) VbglR0SfHostReqSetSymlinks(VBOXSFNOPARMS *pReq)
+{
+ return VbglR0SfHostReqNoParms(pReq, SHFL_FN_SET_SYMLINKS, SHFL_CPARMS_SET_SYMLINKS);
+}
+
+/**
+ * SHFL_F_SET_SYMLINKS request, simplified version.
+ */
+DECLINLINE(int) VbglR0SfHostReqSetSymlinksSimple(void)
+{
+ return VbglR0SfHostReqNoParmsSimple(SHFL_FN_SET_SYMLINKS, SHFL_CPARMS_SET_SYMLINKS);
+}
+
+
+/** Request structure for VbglR0SfHostReqSetErrorStyle. */
+typedef struct VBOXSFSETERRORSTYLE
+{
+ VBGLIOCIDCHGCMFASTCALL Hdr;
+ VMMDevHGCMCall Call;
+ VBoxSFParmSetErrorStyle Parms;
+} VBOXSFSETERRORSTYLE;
+
+/**
+ * SHFL_FN_QUERY_FEATURES request.
+ */
+DECLINLINE(int) VbglR0SfHostReqSetErrorStyle(VBOXSFSETERRORSTYLE *pReq, SHFLERRORSTYLE enmStyle)
+{
+ VBGLIOCIDCHGCMFASTCALL_INIT(&pReq->Hdr, VbglR0PhysHeapGetPhysAddr(pReq), &pReq->Call, g_SfClient.idClient,
+ SHFL_FN_SET_ERROR_STYLE, SHFL_CPARMS_SET_ERROR_STYLE, sizeof(*pReq));
+
+ pReq->Parms.u32Style.type = VMMDevHGCMParmType_32bit;
+ pReq->Parms.u32Style.u.value32 = (uint32_t)enmStyle;
+
+ pReq->Parms.u32Reserved.type = VMMDevHGCMParmType_32bit;
+ pReq->Parms.u32Reserved.u.value32 = 0;
+
+ int vrc = VbglR0HGCMFastCall(g_SfClient.handle, &pReq->Hdr, sizeof(*pReq));
+ if (RT_SUCCESS(vrc))
+ vrc = pReq->Call.header.result;
+ return vrc;
+}
+
+/**
+ * SHFL_FN_QUERY_FEATURES request, simplified version.
+ */
+DECLINLINE(int) VbglR0SfHostReqSetErrorStyleSimple(SHFLERRORSTYLE enmStyle)
+{
+ VBOXSFSETERRORSTYLE *pReq = (VBOXSFSETERRORSTYLE *)VbglR0PhysHeapAlloc(sizeof(*pReq));
+ if (pReq)
+ {
+ int rc = VbglR0SfHostReqSetErrorStyle(pReq, enmStyle);
+ VbglR0PhysHeapFree(pReq);
+ return rc;
+ }
+ return VERR_NO_MEMORY;
+}
+
+
+/** Request structure for VbglR0SfHostReqMapFolderWithBuf. */
+typedef struct VBOXSFMAPFOLDERWITHBUFREQ
+{
+ VBGLIOCIDCHGCMFASTCALL Hdr;
+ VMMDevHGCMCall Call;
+ VBoxSFParmMapFolder Parms;
+ HGCMPageListInfo PgLst;
+} VBOXSFMAPFOLDERWITHBUFREQ;
+
+
+/**
+ * SHFL_FN_MAP_FOLDER request.
+ */
+DECLINLINE(int) VbglR0SfHostReqMapFolderWithContig(VBOXSFMAPFOLDERWITHBUFREQ *pReq, PSHFLSTRING pStrName, RTGCPHYS64 PhysStrName,
+ RTUTF16 wcDelimiter, bool fCaseSensitive)
+{
+ VBGLIOCIDCHGCMFASTCALL_INIT(&pReq->Hdr, VbglR0PhysHeapGetPhysAddr(pReq), &pReq->Call, g_SfClient.idClient,
+ SHFL_FN_MAP_FOLDER, SHFL_CPARMS_MAP_FOLDER, sizeof(*pReq));
+
+ pReq->Parms.id32Root.type = VMMDevHGCMParmType_32bit;
+ pReq->Parms.id32Root.u.value32 = SHFL_ROOT_NIL;
+
+ pReq->Parms.uc32Delimiter.type = VMMDevHGCMParmType_32bit;
+ pReq->Parms.uc32Delimiter.u.value32 = wcDelimiter;
+
+ pReq->Parms.fCaseSensitive.type = VMMDevHGCMParmType_32bit;
+ pReq->Parms.fCaseSensitive.u.value32 = fCaseSensitive;
+
+ if (g_fHostFeatures & VMMDEV_HVF_HGCM_CONTIGUOUS_PAGE_LIST)
+ {
+ pReq->Parms.pStrName.type = VMMDevHGCMParmType_PageList;
+ pReq->Parms.pStrName.u.PageList.size = SHFLSTRING_HEADER_SIZE + pStrName->u16Size;
+ pReq->Parms.pStrName.u.PageList.offset = RT_UOFFSETOF(VBOXSFMAPFOLDERWITHBUFREQ, PgLst) - sizeof(VBGLIOCIDCHGCMFASTCALL);
+ pReq->PgLst.flags = VBOX_HGCM_F_PARM_DIRECTION_BOTH;
+ pReq->PgLst.offFirstPage = (uint16_t)PhysStrName & (uint16_t)(PAGE_OFFSET_MASK);
+ pReq->PgLst.aPages[0] = PhysStrName & ~(RTGCPHYS64)PAGE_OFFSET_MASK;
+ pReq->PgLst.cPages = 1;
+ }
+ else
+ {
+ pReq->Parms.pStrName.type = VMMDevHGCMParmType_LinAddr_In;
+ pReq->Parms.pStrName.u.LinAddr.cb = SHFLSTRING_HEADER_SIZE + pStrName->u16Size;
+ pReq->Parms.pStrName.u.LinAddr.uAddr = (uintptr_t)pStrName;
+ }
+
+ int vrc = VbglR0HGCMFastCall(g_SfClient.handle, &pReq->Hdr, sizeof(*pReq));
+ if (RT_SUCCESS(vrc))
+ vrc = pReq->Call.header.result;
+ return vrc;
+}
+
+/**
+ * SHFL_FN_MAP_FOLDER request.
+ */
+DECLINLINE(int) VbglR0SfHostReqMapFolderWithContigSimple(PSHFLSTRING pStrName, RTGCPHYS64 PhysStrName,
+ RTUTF16 wcDelimiter, bool fCaseSensitive, SHFLROOT *pidRoot)
+{
+ VBOXSFMAPFOLDERWITHBUFREQ *pReq = (VBOXSFMAPFOLDERWITHBUFREQ *)VbglR0PhysHeapAlloc(sizeof(*pReq));
+ if (pReq)
+ {
+ int rc = VbglR0SfHostReqMapFolderWithContig(pReq, pStrName, PhysStrName, wcDelimiter, fCaseSensitive);
+ *pidRoot = RT_SUCCESS(rc) ? pReq->Parms.id32Root.u.value32 : SHFL_ROOT_NIL;
+ VbglR0PhysHeapFree(pReq);
+ return rc;
+ }
+ *pidRoot = SHFL_ROOT_NIL;
+ return VERR_NO_MEMORY;
+}
+
+
+/**
+ * SHFL_FN_MAP_FOLDER request.
+ */
+DECLINLINE(int) VbglR0SfHostReqMapFolderWithBuf(VBOXSFMAPFOLDERWITHBUFREQ *pReq, PSHFLSTRING pStrName,
+ RTUTF16 wcDelimiter, bool fCaseSensitive)
+{
+ return VbglR0SfHostReqMapFolderWithContig(pReq, pStrName, VbglR0PhysHeapGetPhysAddr(pStrName), wcDelimiter, fCaseSensitive);
+}
+
+
+
+/** Request structure used by vboxSfOs2HostReqUnmapFolder. */
+typedef struct VBOXSFUNMAPFOLDERREQ
+{
+ VBGLIOCIDCHGCMFASTCALL Hdr;
+ VMMDevHGCMCall Call;
+ VBoxSFParmUnmapFolder Parms;
+} VBOXSFUNMAPFOLDERREQ;
+
+
+/**
+ * SHFL_FN_UNMAP_FOLDER request.
+ */
+DECLINLINE(int) VbglR0SfHostReqUnmapFolderSimple(uint32_t idRoot)
+{
+ VBOXSFUNMAPFOLDERREQ *pReq = (VBOXSFUNMAPFOLDERREQ *)VbglR0PhysHeapAlloc(sizeof(*pReq));
+ if (pReq)
+ {
+ pReq->Parms.id32Root.type = VMMDevHGCMParmType_32bit;
+ pReq->Parms.id32Root.u.value32 = idRoot;
+
+ VBGLIOCIDCHGCMFASTCALL_INIT(&pReq->Hdr, VbglR0PhysHeapGetPhysAddr(pReq), &pReq->Call, g_SfClient.idClient,
+ SHFL_FN_UNMAP_FOLDER, SHFL_CPARMS_UNMAP_FOLDER, sizeof(*pReq));
+
+ int vrc = VbglR0HGCMFastCall(g_SfClient.handle, &pReq->Hdr, sizeof(*pReq));
+ if (RT_SUCCESS(vrc))
+ vrc = pReq->Call.header.result;
+
+ VbglR0PhysHeapFree(pReq);
+ return vrc;
+ }
+ return VERR_NO_MEMORY;
+}
+
+
+/** Request structure for VbglR0SfHostReqCreate. */
+typedef struct VBOXSFCREATEREQ
+{
+ VBGLIOCIDCHGCMFASTCALL Hdr;
+ VMMDevHGCMCall Call;
+ VBoxSFParmCreate Parms;
+ SHFLCREATEPARMS CreateParms;
+ SHFLSTRING StrPath;
+} VBOXSFCREATEREQ;
+
+/**
+ * SHFL_FN_CREATE request.
+ */
+DECLINLINE(int) VbglR0SfHostReqCreate(SHFLROOT idRoot, VBOXSFCREATEREQ *pReq)
+{
+ uint32_t const cbReq = g_fHostFeatures & VMMDEV_HVF_HGCM_EMBEDDED_BUFFERS
+ ? RT_UOFFSETOF(VBOXSFCREATEREQ, StrPath.String) + pReq->StrPath.u16Size
+ : RT_UOFFSETOF(VBOXSFCREATEREQ, CreateParms);
+ VBGLIOCIDCHGCMFASTCALL_INIT(&pReq->Hdr, VbglR0PhysHeapGetPhysAddr(pReq), &pReq->Call, g_SfClient.idClient,
+ SHFL_FN_CREATE, SHFL_CPARMS_CREATE, cbReq);
+
+ pReq->Parms.id32Root.type = VMMDevHGCMParmType_32bit;
+ pReq->Parms.id32Root.u.value32 = idRoot;
+
+ if (g_fHostFeatures & VMMDEV_HVF_HGCM_EMBEDDED_BUFFERS)
+ {
+ pReq->Parms.pStrPath.type = VMMDevHGCMParmType_Embedded;
+ pReq->Parms.pStrPath.u.Embedded.cbData = SHFLSTRING_HEADER_SIZE + pReq->StrPath.u16Size;
+ pReq->Parms.pStrPath.u.Embedded.offData = RT_UOFFSETOF(VBOXSFCREATEREQ, StrPath) - sizeof(VBGLIOCIDCHGCMFASTCALL);
+ pReq->Parms.pStrPath.u.Embedded.fFlags = VBOX_HGCM_F_PARM_DIRECTION_TO_HOST;
+
+ pReq->Parms.pCreateParms.type = VMMDevHGCMParmType_Embedded;
+ pReq->Parms.pCreateParms.u.Embedded.cbData = sizeof(pReq->CreateParms);
+ pReq->Parms.pCreateParms.u.Embedded.offData = RT_UOFFSETOF(VBOXSFCREATEREQ, CreateParms) - sizeof(VBGLIOCIDCHGCMFASTCALL);
+ pReq->Parms.pCreateParms.u.Embedded.fFlags = VBOX_HGCM_F_PARM_DIRECTION_BOTH;
+ }
+ else
+ {
+ pReq->Parms.pStrPath.type = VMMDevHGCMParmType_LinAddr_In;
+ pReq->Parms.pStrPath.u.LinAddr.cb = SHFLSTRING_HEADER_SIZE + pReq->StrPath.u16Size;
+ pReq->Parms.pStrPath.u.LinAddr.uAddr = (uintptr_t)&pReq->StrPath;
+
+ pReq->Parms.pCreateParms.type = VMMDevHGCMParmType_LinAddr;
+ pReq->Parms.pCreateParms.u.LinAddr.cb = sizeof(pReq->CreateParms);
+ pReq->Parms.pCreateParms.u.LinAddr.uAddr = (uintptr_t)&pReq->CreateParms;
+ }
+
+ int vrc = VbglR0HGCMFastCall(g_SfClient.handle, &pReq->Hdr, cbReq);
+ if (RT_SUCCESS(vrc))
+ vrc = pReq->Call.header.result;
+ return vrc;
+}
+
+
+/** Request structure for VbglR0SfHostReqClose. */
+typedef struct VBOXSFCLOSEREQ
+{
+ VBGLIOCIDCHGCMFASTCALL Hdr;
+ VMMDevHGCMCall Call;
+ VBoxSFParmClose Parms;
+} VBOXSFCLOSEREQ;
+
+/**
+ * SHFL_FN_CLOSE request.
+ */
+DECLINLINE(int) VbglR0SfHostReqClose(SHFLROOT idRoot, VBOXSFCLOSEREQ *pReq, uint64_t hHostFile)
+{
+ VBGLIOCIDCHGCMFASTCALL_INIT(&pReq->Hdr, VbglR0PhysHeapGetPhysAddr(pReq), &pReq->Call, g_SfClient.idClient,
+ SHFL_FN_CLOSE, SHFL_CPARMS_CLOSE, sizeof(*pReq));
+
+ pReq->Parms.id32Root.type = VMMDevHGCMParmType_32bit;
+ pReq->Parms.id32Root.u.value32 = idRoot;
+
+ pReq->Parms.u64Handle.type = VMMDevHGCMParmType_64bit;
+ pReq->Parms.u64Handle.u.value64 = hHostFile;
+
+ int vrc = VbglR0HGCMFastCall(g_SfClient.handle, &pReq->Hdr, sizeof(*pReq));
+ if (RT_SUCCESS(vrc))
+ vrc = pReq->Call.header.result;
+ return vrc;
+}
+
+/**
+ * SHFL_FN_CLOSE request, allocate request buffer.
+ */
+DECLINLINE(int) VbglR0SfHostReqCloseSimple(SHFLROOT idRoot, uint64_t hHostFile)
+{
+ VBOXSFCLOSEREQ *pReq = (VBOXSFCLOSEREQ *)VbglR0PhysHeapAlloc(sizeof(*pReq));
+ if (pReq)
+ {
+ int vrc = VbglR0SfHostReqClose(idRoot, pReq, hHostFile);
+ VbglR0PhysHeapFree(pReq);
+ return vrc;
+ }
+ return VERR_NO_MEMORY;
+}
+
+
+/** Request structure for VbglR0SfHostReqQueryVolInfo. */
+typedef struct VBOXSFVOLINFOREQ
+{
+ VBGLIOCIDCHGCMFASTCALL Hdr;
+ VMMDevHGCMCall Call;
+ VBoxSFParmInformation Parms;
+ SHFLVOLINFO VolInfo;
+} VBOXSFVOLINFOREQ;
+
+/**
+ * SHFL_FN_INFORMATION[SHFL_INFO_VOLUME | SHFL_INFO_GET] request.
+ */
+DECLINLINE(int) VbglR0SfHostReqQueryVolInfo(SHFLROOT idRoot, VBOXSFVOLINFOREQ *pReq, uint64_t hHostFile)
+{
+ uint32_t const cbReq = g_fHostFeatures & VMMDEV_HVF_HGCM_EMBEDDED_BUFFERS
+ ? sizeof(*pReq) : RT_UOFFSETOF(VBOXSFVOLINFOREQ, VolInfo);
+ VBGLIOCIDCHGCMFASTCALL_INIT(&pReq->Hdr, VbglR0PhysHeapGetPhysAddr(pReq), &pReq->Call, g_SfClient.idClient,
+ SHFL_FN_INFORMATION, SHFL_CPARMS_INFORMATION, cbReq);
+
+ pReq->Parms.id32Root.type = VMMDevHGCMParmType_32bit;
+ pReq->Parms.id32Root.u.value32 = idRoot;
+
+ pReq->Parms.u64Handle.type = VMMDevHGCMParmType_64bit;
+ pReq->Parms.u64Handle.u.value64 = hHostFile;
+
+ pReq->Parms.f32Flags.type = VMMDevHGCMParmType_32bit;
+ pReq->Parms.f32Flags.u.value32 = SHFL_INFO_VOLUME | SHFL_INFO_GET;
+
+ pReq->Parms.cb32.type = VMMDevHGCMParmType_32bit;
+ pReq->Parms.cb32.u.value32 = sizeof(pReq->VolInfo);
+
+ if (g_fHostFeatures & VMMDEV_HVF_HGCM_EMBEDDED_BUFFERS)
+ {
+ pReq->Parms.pInfo.type = VMMDevHGCMParmType_Embedded;
+ pReq->Parms.pInfo.u.Embedded.cbData = sizeof(pReq->VolInfo);
+ pReq->Parms.pInfo.u.Embedded.offData = RT_UOFFSETOF(VBOXSFVOLINFOREQ, VolInfo) - sizeof(VBGLIOCIDCHGCMFASTCALL);
+ pReq->Parms.pInfo.u.Embedded.fFlags = VBOX_HGCM_F_PARM_DIRECTION_FROM_HOST;
+ }
+ else
+ {
+ pReq->Parms.pInfo.type = VMMDevHGCMParmType_LinAddr_Out;
+ pReq->Parms.pInfo.u.LinAddr.cb = sizeof(pReq->VolInfo);
+ pReq->Parms.pInfo.u.LinAddr.uAddr = (uintptr_t)&pReq->VolInfo;
+ }
+
+ int vrc = VbglR0HGCMFastCall(g_SfClient.handle, &pReq->Hdr, cbReq);
+ if (RT_SUCCESS(vrc))
+ vrc = pReq->Call.header.result;
+ return vrc;
+}
+
+
+/** Request structure for VbglR0SfHostReqSetObjInfo & VbglR0SfHostReqQueryObjInfo. */
+typedef struct VBOXSFOBJINFOREQ
+{
+ VBGLIOCIDCHGCMFASTCALL Hdr;
+ VMMDevHGCMCall Call;
+ VBoxSFParmInformation Parms;
+ SHFLFSOBJINFO ObjInfo;
+} VBOXSFOBJINFOREQ;
+
+/**
+ * SHFL_FN_INFORMATION[SHFL_INFO_GET | SHFL_INFO_FILE] request.
+ */
+DECLINLINE(int) VbglR0SfHostReqQueryObjInfo(SHFLROOT idRoot, VBOXSFOBJINFOREQ *pReq, uint64_t hHostFile)
+{
+ uint32_t const cbReq = g_fHostFeatures & VMMDEV_HVF_HGCM_EMBEDDED_BUFFERS
+ ? sizeof(*pReq) : RT_UOFFSETOF(VBOXSFOBJINFOREQ, ObjInfo);
+ VBGLIOCIDCHGCMFASTCALL_INIT(&pReq->Hdr, VbglR0PhysHeapGetPhysAddr(pReq), &pReq->Call, g_SfClient.idClient,
+ SHFL_FN_INFORMATION, SHFL_CPARMS_INFORMATION, cbReq);
+
+ pReq->Parms.id32Root.type = VMMDevHGCMParmType_32bit;
+ pReq->Parms.id32Root.u.value32 = idRoot;
+
+ pReq->Parms.u64Handle.type = VMMDevHGCMParmType_64bit;
+ pReq->Parms.u64Handle.u.value64 = hHostFile;
+
+ pReq->Parms.f32Flags.type = VMMDevHGCMParmType_32bit;
+ pReq->Parms.f32Flags.u.value32 = SHFL_INFO_GET | SHFL_INFO_FILE;
+
+ pReq->Parms.cb32.type = VMMDevHGCMParmType_32bit;
+ pReq->Parms.cb32.u.value32 = sizeof(pReq->ObjInfo);
+
+ if (g_fHostFeatures & VMMDEV_HVF_HGCM_EMBEDDED_BUFFERS)
+ {
+ pReq->Parms.pInfo.type = VMMDevHGCMParmType_Embedded;
+ pReq->Parms.pInfo.u.Embedded.cbData = sizeof(pReq->ObjInfo);
+ pReq->Parms.pInfo.u.Embedded.offData = RT_UOFFSETOF(VBOXSFOBJINFOREQ, ObjInfo) - sizeof(VBGLIOCIDCHGCMFASTCALL);
+ pReq->Parms.pInfo.u.Embedded.fFlags = VBOX_HGCM_F_PARM_DIRECTION_FROM_HOST;
+ }
+ else
+ {
+ pReq->Parms.pInfo.type = VMMDevHGCMParmType_LinAddr_Out;
+ pReq->Parms.pInfo.u.LinAddr.cb = sizeof(pReq->ObjInfo);
+ pReq->Parms.pInfo.u.LinAddr.uAddr = (uintptr_t)&pReq->ObjInfo;
+ }
+
+ int vrc = VbglR0HGCMFastCall(g_SfClient.handle, &pReq->Hdr, cbReq);
+ if (RT_SUCCESS(vrc))
+ vrc = pReq->Call.header.result;
+ return vrc;
+}
+
+
+/**
+ * SHFL_FN_INFORMATION[SHFL_INFO_SET | SHFL_INFO_FILE] request.
+ */
+DECLINLINE(int) VbglR0SfHostReqSetObjInfo(SHFLROOT idRoot, VBOXSFOBJINFOREQ *pReq, uint64_t hHostFile)
+{
+ uint32_t const cbReq = g_fHostFeatures & VMMDEV_HVF_HGCM_EMBEDDED_BUFFERS
+ ? sizeof(*pReq) : RT_UOFFSETOF(VBOXSFOBJINFOREQ, ObjInfo);
+ VBGLIOCIDCHGCMFASTCALL_INIT(&pReq->Hdr, VbglR0PhysHeapGetPhysAddr(pReq), &pReq->Call, g_SfClient.idClient,
+ SHFL_FN_INFORMATION, SHFL_CPARMS_INFORMATION, cbReq);
+
+ pReq->Parms.id32Root.type = VMMDevHGCMParmType_32bit;
+ pReq->Parms.id32Root.u.value32 = idRoot;
+
+ pReq->Parms.u64Handle.type = VMMDevHGCMParmType_64bit;
+ pReq->Parms.u64Handle.u.value64 = hHostFile;
+
+ pReq->Parms.f32Flags.type = VMMDevHGCMParmType_32bit;
+ pReq->Parms.f32Flags.u.value32 = SHFL_INFO_SET | SHFL_INFO_FILE;
+
+ pReq->Parms.cb32.type = VMMDevHGCMParmType_32bit;
+ pReq->Parms.cb32.u.value32 = sizeof(pReq->ObjInfo);
+
+ if (g_fHostFeatures & VMMDEV_HVF_HGCM_EMBEDDED_BUFFERS)
+ {
+ pReq->Parms.pInfo.type = VMMDevHGCMParmType_Embedded;
+ pReq->Parms.pInfo.u.Embedded.cbData = sizeof(pReq->ObjInfo);
+ pReq->Parms.pInfo.u.Embedded.offData = RT_UOFFSETOF(VBOXSFOBJINFOREQ, ObjInfo) - sizeof(VBGLIOCIDCHGCMFASTCALL);
+ pReq->Parms.pInfo.u.Embedded.fFlags = VBOX_HGCM_F_PARM_DIRECTION_BOTH;
+ }
+ else
+ {
+ pReq->Parms.pInfo.type = VMMDevHGCMParmType_LinAddr;
+ pReq->Parms.pInfo.u.LinAddr.cb = sizeof(pReq->ObjInfo);
+ pReq->Parms.pInfo.u.LinAddr.uAddr = (uintptr_t)&pReq->ObjInfo;
+ }
+
+ int vrc = VbglR0HGCMFastCall(g_SfClient.handle, &pReq->Hdr, cbReq);
+ if (RT_SUCCESS(vrc))
+ vrc = pReq->Call.header.result;
+ return vrc;
+}
+
+
+/**
+ * SHFL_FN_INFORMATION[SHFL_INFO_SET | SHFL_INFO_SIZE] request.
+ */
+DECLINLINE(int) VbglR0SfHostReqSetFileSizeOld(SHFLROOT idRoot, VBOXSFOBJINFOREQ *pReq, uint64_t hHostFile)
+{
+ uint32_t const cbReq = g_fHostFeatures & VMMDEV_HVF_HGCM_EMBEDDED_BUFFERS
+ ? sizeof(*pReq) : RT_UOFFSETOF(VBOXSFOBJINFOREQ, ObjInfo);
+ VBGLIOCIDCHGCMFASTCALL_INIT(&pReq->Hdr, VbglR0PhysHeapGetPhysAddr(pReq), &pReq->Call, g_SfClient.idClient,
+ SHFL_FN_INFORMATION, SHFL_CPARMS_INFORMATION, cbReq);
+
+ pReq->Parms.id32Root.type = VMMDevHGCMParmType_32bit;
+ pReq->Parms.id32Root.u.value32 = idRoot;
+
+ pReq->Parms.u64Handle.type = VMMDevHGCMParmType_64bit;
+ pReq->Parms.u64Handle.u.value64 = hHostFile;
+
+ pReq->Parms.f32Flags.type = VMMDevHGCMParmType_32bit;
+ pReq->Parms.f32Flags.u.value32 = SHFL_INFO_SET | SHFL_INFO_SIZE;
+
+ pReq->Parms.cb32.type = VMMDevHGCMParmType_32bit;
+ pReq->Parms.cb32.u.value32 = sizeof(pReq->ObjInfo);
+
+ if (g_fHostFeatures & VMMDEV_HVF_HGCM_EMBEDDED_BUFFERS)
+ {
+ pReq->Parms.pInfo.type = VMMDevHGCMParmType_Embedded;
+ pReq->Parms.pInfo.u.Embedded.cbData = sizeof(pReq->ObjInfo);
+ pReq->Parms.pInfo.u.Embedded.offData = RT_UOFFSETOF(VBOXSFOBJINFOREQ, ObjInfo) - sizeof(VBGLIOCIDCHGCMFASTCALL);
+ pReq->Parms.pInfo.u.Embedded.fFlags = VBOX_HGCM_F_PARM_DIRECTION_BOTH;
+ }
+ else
+ {
+ pReq->Parms.pInfo.type = VMMDevHGCMParmType_LinAddr;
+ pReq->Parms.pInfo.u.LinAddr.cb = sizeof(pReq->ObjInfo);
+ pReq->Parms.pInfo.u.LinAddr.uAddr = (uintptr_t)&pReq->ObjInfo;
+ }
+
+ int vrc = VbglR0HGCMFastCall(g_SfClient.handle, &pReq->Hdr, cbReq);
+ if (RT_SUCCESS(vrc))
+ vrc = pReq->Call.header.result;
+ return vrc;
+}
+
+
+/** Request structure for VbglR0SfHostReqSetObjInfo. */
+typedef struct VBOXSFOBJINFOWITHBUFREQ
+{
+ VBGLIOCIDCHGCMFASTCALL Hdr;
+ VMMDevHGCMCall Call;
+ VBoxSFParmInformation Parms;
+ HGCMPageListInfo PgLst;
+} VBOXSFOBJINFOWITHBUFREQ;
+
+/**
+ * SHFL_FN_INFORMATION[SHFL_INFO_SET | SHFL_INFO_FILE] request, with separate
+ * buffer (on the physical heap).
+ */
+DECLINLINE(int) VbglR0SfHostReqSetObjInfoWithBuf(SHFLROOT idRoot, VBOXSFOBJINFOWITHBUFREQ *pReq, uint64_t hHostFile,
+ PSHFLFSOBJINFO pObjInfo, uint32_t offObjInfoInAlloc)
+{
+ VBGLIOCIDCHGCMFASTCALL_INIT(&pReq->Hdr, VbglR0PhysHeapGetPhysAddr(pReq), &pReq->Call, g_SfClient.idClient,
+ SHFL_FN_INFORMATION, SHFL_CPARMS_INFORMATION, sizeof(*pReq));
+
+ pReq->Parms.id32Root.type = VMMDevHGCMParmType_32bit;
+ pReq->Parms.id32Root.u.value32 = idRoot;
+
+ pReq->Parms.u64Handle.type = VMMDevHGCMParmType_64bit;
+ pReq->Parms.u64Handle.u.value64 = hHostFile;
+
+ pReq->Parms.f32Flags.type = VMMDevHGCMParmType_32bit;
+ pReq->Parms.f32Flags.u.value32 = SHFL_INFO_SET | SHFL_INFO_FILE;
+
+ pReq->Parms.cb32.type = VMMDevHGCMParmType_32bit;
+ pReq->Parms.cb32.u.value32 = sizeof(*pObjInfo);
+
+ if (g_fHostFeatures & VMMDEV_HVF_HGCM_CONTIGUOUS_PAGE_LIST)
+ {
+ pReq->Parms.pInfo.type = VMMDevHGCMParmType_ContiguousPageList;
+ pReq->Parms.pInfo.u.PageList.size = sizeof(*pObjInfo);
+ pReq->Parms.pInfo.u.PageList.offset = RT_UOFFSETOF(VBOXSFOBJINFOREQ, ObjInfo) - sizeof(VBGLIOCIDCHGCMFASTCALL);
+ pReq->PgLst.flags = VBOX_HGCM_F_PARM_DIRECTION_BOTH;
+ pReq->PgLst.aPages[0] = VbglR0PhysHeapGetPhysAddr((uint8_t *)pObjInfo - offObjInfoInAlloc) + offObjInfoInAlloc;
+ pReq->PgLst.offFirstPage = (uint16_t)(pReq->PgLst.aPages[0] & PAGE_OFFSET_MASK);
+ pReq->PgLst.aPages[0] &= ~(RTGCPHYS)PAGE_OFFSET_MASK;
+ pReq->PgLst.cPages = 1;
+ }
+ else
+ {
+ pReq->Parms.pInfo.type = VMMDevHGCMParmType_LinAddr;
+ pReq->Parms.pInfo.u.LinAddr.cb = sizeof(*pObjInfo);
+ pReq->Parms.pInfo.u.LinAddr.uAddr = (uintptr_t)pObjInfo;
+ }
+
+ int vrc = VbglR0HGCMFastCall(g_SfClient.handle, &pReq->Hdr, sizeof(*pReq));
+ if (RT_SUCCESS(vrc))
+ vrc = pReq->Call.header.result;
+ return vrc;
+}
+
+
+/** Request structure for VbglR0SfHostReqRemove. */
+typedef struct VBOXSFREMOVEREQ
+{
+ VBGLIOCIDCHGCMFASTCALL Hdr;
+ VMMDevHGCMCall Call;
+ VBoxSFParmRemove Parms;
+ SHFLSTRING StrPath;
+} VBOXSFREMOVEREQ;
+
+/**
+ * SHFL_FN_REMOVE request.
+ */
+DECLINLINE(int) VbglR0SfHostReqRemove(SHFLROOT idRoot, VBOXSFREMOVEREQ *pReq, uint32_t fFlags)
+{
+ uint32_t const cbReq = RT_UOFFSETOF(VBOXSFREMOVEREQ, StrPath.String)
+ + (g_fHostFeatures & VMMDEV_HVF_HGCM_EMBEDDED_BUFFERS ? pReq->StrPath.u16Size : 0);
+ VBGLIOCIDCHGCMFASTCALL_INIT(&pReq->Hdr, VbglR0PhysHeapGetPhysAddr(pReq), &pReq->Call, g_SfClient.idClient,
+ SHFL_FN_REMOVE, SHFL_CPARMS_REMOVE, cbReq);
+
+ pReq->Parms.id32Root.type = VMMDevHGCMParmType_32bit;
+ pReq->Parms.id32Root.u.value32 = idRoot;
+
+ if (g_fHostFeatures & VMMDEV_HVF_HGCM_EMBEDDED_BUFFERS)
+ {
+ pReq->Parms.pStrPath.type = VMMDevHGCMParmType_Embedded;
+ pReq->Parms.pStrPath.u.Embedded.cbData = SHFLSTRING_HEADER_SIZE + pReq->StrPath.u16Size;
+ pReq->Parms.pStrPath.u.Embedded.offData = RT_UOFFSETOF(VBOXSFREMOVEREQ, StrPath) - sizeof(VBGLIOCIDCHGCMFASTCALL);
+ pReq->Parms.pStrPath.u.Embedded.fFlags = VBOX_HGCM_F_PARM_DIRECTION_TO_HOST;
+ }
+ else
+ {
+ pReq->Parms.pStrPath.type = VMMDevHGCMParmType_LinAddr_In;
+ pReq->Parms.pStrPath.u.LinAddr.cb = SHFLSTRING_HEADER_SIZE + pReq->StrPath.u16Size;
+ pReq->Parms.pStrPath.u.LinAddr.uAddr = (uintptr_t)&pReq->StrPath;
+ }
+
+ pReq->Parms.f32Flags.type = VMMDevHGCMParmType_32bit;
+ pReq->Parms.f32Flags.u.value32 = fFlags;
+
+ int vrc = VbglR0HGCMFastCall(g_SfClient.handle, &pReq->Hdr, cbReq);
+ if (RT_SUCCESS(vrc))
+ vrc = pReq->Call.header.result;
+ return vrc;
+}
+
+
+/** Request structure for VbglR0SfHostReqCloseAndRemove. */
+typedef struct VBOXSFCLOSEANDREMOVEREQ
+{
+ VBGLIOCIDCHGCMFASTCALL Hdr;
+ VMMDevHGCMCall Call;
+ VBoxSFParmCloseAndRemove Parms;
+ SHFLSTRING StrPath;
+} VBOXSFCLOSEANDREMOVEREQ;
+
+/**
+ * SHFL_FN_CLOSE_AND_REMOVE request.
+ */
+DECLINLINE(int) VbglR0SfHostReqCloseAndRemove(SHFLROOT idRoot, VBOXSFCLOSEANDREMOVEREQ *pReq, uint32_t fFlags, SHFLHANDLE hToClose)
+{
+ uint32_t const cbReq = RT_UOFFSETOF(VBOXSFCLOSEANDREMOVEREQ, StrPath.String)
+ + (g_fHostFeatures & VMMDEV_HVF_HGCM_EMBEDDED_BUFFERS ? pReq->StrPath.u16Size : 0);
+ VBGLIOCIDCHGCMFASTCALL_INIT(&pReq->Hdr, VbglR0PhysHeapGetPhysAddr(pReq), &pReq->Call, g_SfClient.idClient,
+ SHFL_FN_CLOSE_AND_REMOVE, SHFL_CPARMS_CLOSE_AND_REMOVE, cbReq);
+
+ pReq->Parms.id32Root.type = VMMDevHGCMParmType_32bit;
+ pReq->Parms.id32Root.u.value32 = idRoot;
+
+ if (g_fHostFeatures & VMMDEV_HVF_HGCM_EMBEDDED_BUFFERS)
+ {
+ pReq->Parms.pStrPath.type = VMMDevHGCMParmType_Embedded;
+ pReq->Parms.pStrPath.u.Embedded.cbData = SHFLSTRING_HEADER_SIZE + pReq->StrPath.u16Size;
+ pReq->Parms.pStrPath.u.Embedded.offData = RT_UOFFSETOF(VBOXSFCLOSEANDREMOVEREQ, StrPath) - sizeof(VBGLIOCIDCHGCMFASTCALL);
+ pReq->Parms.pStrPath.u.Embedded.fFlags = VBOX_HGCM_F_PARM_DIRECTION_TO_HOST;
+ }
+ else
+ {
+ pReq->Parms.pStrPath.type = VMMDevHGCMParmType_LinAddr_In;
+ pReq->Parms.pStrPath.u.LinAddr.cb = SHFLSTRING_HEADER_SIZE + pReq->StrPath.u16Size;
+ pReq->Parms.pStrPath.u.LinAddr.uAddr = (uintptr_t)&pReq->StrPath;
+ }
+
+ pReq->Parms.f32Flags.type = VMMDevHGCMParmType_32bit;
+ pReq->Parms.f32Flags.u.value32 = fFlags;
+
+ pReq->Parms.u64Handle.type = VMMDevHGCMParmType_64bit;
+ pReq->Parms.u64Handle.u.value64 = hToClose;
+
+ int vrc = VbglR0HGCMFastCall(g_SfClient.handle, &pReq->Hdr, cbReq);
+ if (RT_SUCCESS(vrc))
+ vrc = pReq->Call.header.result;
+ return vrc;
+}
+
+
+/** Request structure for VbglR0SfHostReqRenameWithSrcContig and
+ * VbglR0SfHostReqRenameWithSrcBuf. */
+typedef struct VBOXSFRENAMEWITHSRCBUFREQ
+{
+ VBGLIOCIDCHGCMFASTCALL Hdr;
+ VMMDevHGCMCall Call;
+ VBoxSFParmRename Parms;
+ HGCMPageListInfo PgLst;
+ SHFLSTRING StrDstPath;
+} VBOXSFRENAMEWITHSRCBUFREQ;
+
+
+/**
+ * SHFL_FN_REMOVE request.
+ */
+DECLINLINE(int) VbglR0SfHostReqRenameWithSrcContig(SHFLROOT idRoot, VBOXSFRENAMEWITHSRCBUFREQ *pReq,
+ PSHFLSTRING pSrcStr, RTGCPHYS64 PhysSrcStr, uint32_t fFlags)
+{
+ uint32_t const cbReq = RT_UOFFSETOF(VBOXSFRENAMEWITHSRCBUFREQ, StrDstPath.String)
+ + (g_fHostFeatures & VMMDEV_HVF_HGCM_EMBEDDED_BUFFERS ? pReq->StrDstPath.u16Size : 0);
+ VBGLIOCIDCHGCMFASTCALL_INIT(&pReq->Hdr, VbglR0PhysHeapGetPhysAddr(pReq), &pReq->Call, g_SfClient.idClient,
+ SHFL_FN_RENAME, SHFL_CPARMS_RENAME, cbReq);
+
+ pReq->Parms.id32Root.type = VMMDevHGCMParmType_32bit;
+ pReq->Parms.id32Root.u.value32 = idRoot;
+
+ if (g_fHostFeatures & VMMDEV_HVF_HGCM_CONTIGUOUS_PAGE_LIST)
+ {
+ pReq->Parms.pStrSrcPath.type = VMMDevHGCMParmType_ContiguousPageList;
+ pReq->Parms.pStrSrcPath.u.PageList.size = SHFLSTRING_HEADER_SIZE + pSrcStr->u16Size;
+ pReq->Parms.pStrSrcPath.u.PageList.offset = RT_UOFFSETOF(VBOXSFRENAMEWITHSRCBUFREQ, PgLst)
+ - sizeof(VBGLIOCIDCHGCMFASTCALL);
+ pReq->PgLst.flags = VBOX_HGCM_F_PARM_DIRECTION_TO_HOST;
+ pReq->PgLst.offFirstPage = (uint16_t)PhysSrcStr & (uint16_t)(PAGE_OFFSET_MASK);
+ pReq->PgLst.aPages[0] = PhysSrcStr & ~(RTGCPHYS64)PAGE_OFFSET_MASK;
+ pReq->PgLst.cPages = 1;
+ }
+ else
+ {
+ pReq->Parms.pStrSrcPath.type = VMMDevHGCMParmType_LinAddr_In;
+ pReq->Parms.pStrSrcPath.u.LinAddr.cb = SHFLSTRING_HEADER_SIZE + pSrcStr->u16Size;
+ pReq->Parms.pStrSrcPath.u.LinAddr.uAddr = (uintptr_t)pSrcStr;
+ }
+
+ if (g_fHostFeatures & VMMDEV_HVF_HGCM_EMBEDDED_BUFFERS)
+ {
+ pReq->Parms.pStrDstPath.type = VMMDevHGCMParmType_Embedded;
+ pReq->Parms.pStrDstPath.u.Embedded.cbData = SHFLSTRING_HEADER_SIZE + pReq->StrDstPath.u16Size;
+ pReq->Parms.pStrDstPath.u.Embedded.offData = RT_UOFFSETOF(VBOXSFRENAMEWITHSRCBUFREQ, StrDstPath)
+ - sizeof(VBGLIOCIDCHGCMFASTCALL);
+ pReq->Parms.pStrDstPath.u.Embedded.fFlags = VBOX_HGCM_F_PARM_DIRECTION_TO_HOST;
+ }
+ else
+ {
+ pReq->Parms.pStrDstPath.type = VMMDevHGCMParmType_LinAddr_In;
+ pReq->Parms.pStrDstPath.u.LinAddr.cb = SHFLSTRING_HEADER_SIZE + pReq->StrDstPath.u16Size;
+ pReq->Parms.pStrDstPath.u.LinAddr.uAddr = (uintptr_t)&pReq->StrDstPath;
+ }
+
+ pReq->Parms.f32Flags.type = VMMDevHGCMParmType_32bit;
+ pReq->Parms.f32Flags.u.value32 = fFlags;
+
+ int vrc = VbglR0HGCMFastCall(g_SfClient.handle, &pReq->Hdr, cbReq);
+ if (RT_SUCCESS(vrc))
+ vrc = pReq->Call.header.result;
+ return vrc;
+}
+
+
+/**
+ * SHFL_FN_REMOVE request.
+ */
+DECLINLINE(int) VbglR0SfHostReqRenameWithSrcBuf(SHFLROOT idRoot, VBOXSFRENAMEWITHSRCBUFREQ *pReq,
+ PSHFLSTRING pSrcStr, uint32_t fFlags)
+{
+ return VbglR0SfHostReqRenameWithSrcContig(idRoot, pReq, pSrcStr, VbglR0PhysHeapGetPhysAddr(pSrcStr), fFlags);
+}
+
+
+/** Request structure for VbglR0SfHostReqFlush. */
+typedef struct VBOXSFFLUSHREQ
+{
+ VBGLIOCIDCHGCMFASTCALL Hdr;
+ VMMDevHGCMCall Call;
+ VBoxSFParmFlush Parms;
+} VBOXSFFLUSHREQ;
+
+/**
+ * SHFL_FN_FLUSH request.
+ */
+DECLINLINE(int) VbglR0SfHostReqFlush(SHFLROOT idRoot, VBOXSFFLUSHREQ *pReq, uint64_t hHostFile)
+{
+ VBGLIOCIDCHGCMFASTCALL_INIT(&pReq->Hdr, VbglR0PhysHeapGetPhysAddr(pReq), &pReq->Call, g_SfClient.idClient,
+ SHFL_FN_FLUSH, SHFL_CPARMS_FLUSH, sizeof(*pReq));
+
+ pReq->Parms.id32Root.type = VMMDevHGCMParmType_32bit;
+ pReq->Parms.id32Root.u.value32 = idRoot;
+
+ pReq->Parms.u64Handle.type = VMMDevHGCMParmType_64bit;
+ pReq->Parms.u64Handle.u.value64 = hHostFile;
+
+ int vrc = VbglR0HGCMFastCall(g_SfClient.handle, &pReq->Hdr, sizeof(*pReq));
+ if (RT_SUCCESS(vrc))
+ vrc = pReq->Call.header.result;
+ return vrc;
+}
+
+/**
+ * SHFL_FN_FLUSH request, allocate request buffer.
+ */
+DECLINLINE(int) VbglR0SfHostReqFlushSimple(SHFLROOT idRoot, uint64_t hHostFile)
+{
+ VBOXSFFLUSHREQ *pReq = (VBOXSFFLUSHREQ *)VbglR0PhysHeapAlloc(sizeof(*pReq));
+ if (pReq)
+ {
+ int vrc = VbglR0SfHostReqFlush(idRoot, pReq, hHostFile);
+ VbglR0PhysHeapFree(pReq);
+ return vrc;
+ }
+ return VERR_NO_MEMORY;
+}
+
+
+/** Request structure for VbglR0SfHostReqSetFileSize. */
+typedef struct VBOXSFSETFILESIZEREQ
+{
+ VBGLIOCIDCHGCMFASTCALL Hdr;
+ VMMDevHGCMCall Call;
+ VBoxSFParmSetFileSize Parms;
+} VBOXSFSETFILESIZEREQ;
+
+/**
+ * SHFL_FN_SET_FILE_SIZE request.
+ */
+DECLINLINE(int) VbglR0SfHostReqSetFileSize(SHFLROOT idRoot, VBOXSFSETFILESIZEREQ *pReq, uint64_t hHostFile, uint64_t cbNewSize)
+{
+ VBGLIOCIDCHGCMFASTCALL_INIT(&pReq->Hdr, VbglR0PhysHeapGetPhysAddr(pReq), &pReq->Call, g_SfClient.idClient,
+ SHFL_FN_SET_FILE_SIZE, SHFL_CPARMS_SET_FILE_SIZE, sizeof(*pReq));
+
+ pReq->Parms.id32Root.type = VMMDevHGCMParmType_32bit;
+ pReq->Parms.id32Root.u.value32 = idRoot;
+
+ pReq->Parms.u64Handle.type = VMMDevHGCMParmType_64bit;
+ pReq->Parms.u64Handle.u.value64 = hHostFile;
+
+ pReq->Parms.cb64NewSize.type = VMMDevHGCMParmType_64bit;
+ pReq->Parms.cb64NewSize.u.value64 = cbNewSize;
+
+ int vrc = VbglR0HGCMFastCall(g_SfClient.handle, &pReq->Hdr, sizeof(*pReq));
+ if (RT_SUCCESS(vrc))
+ vrc = pReq->Call.header.result;
+ return vrc;
+}
+
+/**
+ * SHFL_FN_SET_FILE_SIZE request, allocate request buffer.
+ */
+DECLINLINE(int) VbglR0SfHostReqSetFileSizeSimple(SHFLROOT idRoot, uint64_t hHostFile, uint64_t cbNewSize)
+{
+ VBOXSFSETFILESIZEREQ *pReq = (VBOXSFSETFILESIZEREQ *)VbglR0PhysHeapAlloc(sizeof(*pReq));
+ if (pReq)
+ {
+ int vrc = VbglR0SfHostReqSetFileSize(idRoot, pReq, hHostFile, cbNewSize);
+ VbglR0PhysHeapFree(pReq);
+ return vrc;
+ }
+ return VERR_NO_MEMORY;
+}
+
+
+/** Request structure for VbglR0SfHostReqReadEmbedded. */
+typedef struct VBOXSFREADEMBEDDEDREQ
+{
+ VBGLIOCIDCHGCMFASTCALL Hdr;
+ VMMDevHGCMCall Call;
+ VBoxSFParmRead Parms;
+ RT_FLEXIBLE_ARRAY_EXTENSION
+ uint8_t abData[RT_FLEXIBLE_ARRAY];
+} VBOXSFREADEMBEDDEDREQ;
+
+/**
+ * SHFL_FN_READ request using embedded data buffer.
+ */
+DECLINLINE(int) VbglR0SfHostReqReadEmbedded(SHFLROOT idRoot, VBOXSFREADEMBEDDEDREQ *pReq, uint64_t hHostFile,
+ uint64_t offRead, uint32_t cbToRead)
+{
+ uint32_t const cbReq = RT_UOFFSETOF(VBOXSFREADEMBEDDEDREQ, abData[0])
+ + (g_fHostFeatures & VMMDEV_HVF_HGCM_EMBEDDED_BUFFERS ? cbToRead : 0);
+ VBGLIOCIDCHGCMFASTCALL_INIT(&pReq->Hdr, VbglR0PhysHeapGetPhysAddr(pReq), &pReq->Call, g_SfClient.idClient,
+ SHFL_FN_READ, SHFL_CPARMS_READ, cbReq);
+
+ pReq->Parms.id32Root.type = VMMDevHGCMParmType_32bit;
+ pReq->Parms.id32Root.u.value32 = idRoot;
+
+ pReq->Parms.u64Handle.type = VMMDevHGCMParmType_64bit;
+ pReq->Parms.u64Handle.u.value64 = hHostFile;
+
+ pReq->Parms.off64Read.type = VMMDevHGCMParmType_64bit;
+ pReq->Parms.off64Read.u.value64 = offRead;
+
+ pReq->Parms.cb32Read.type = VMMDevHGCMParmType_32bit;
+ pReq->Parms.cb32Read.u.value32 = cbToRead;
+
+ if (g_fHostFeatures & VMMDEV_HVF_HGCM_EMBEDDED_BUFFERS)
+ {
+ pReq->Parms.pBuf.type = VMMDevHGCMParmType_Embedded;
+ pReq->Parms.pBuf.u.Embedded.cbData = cbToRead;
+ pReq->Parms.pBuf.u.Embedded.offData = RT_UOFFSETOF(VBOXSFREADEMBEDDEDREQ, abData[0]) - sizeof(VBGLIOCIDCHGCMFASTCALL);
+ pReq->Parms.pBuf.u.Embedded.fFlags = VBOX_HGCM_F_PARM_DIRECTION_FROM_HOST;
+ }
+ else
+ {
+ pReq->Parms.pBuf.type = VMMDevHGCMParmType_LinAddr_Out;
+ pReq->Parms.pBuf.u.LinAddr.cb = cbToRead;
+ pReq->Parms.pBuf.u.LinAddr.uAddr = (uintptr_t)&pReq->abData[0];
+ }
+
+ int vrc = VbglR0HGCMFastCall(g_SfClient.handle, &pReq->Hdr, cbReq);
+ if (RT_SUCCESS(vrc))
+ vrc = pReq->Call.header.result;
+ return vrc;
+}
+
+
+/** Request structure for vboxSfOs2HostReqRead & VbglR0SfHostReqReadContig. */
+typedef struct VBOXSFREADPGLSTREQ
+{
+ VBGLIOCIDCHGCMFASTCALL Hdr;
+ VMMDevHGCMCall Call;
+ VBoxSFParmRead Parms;
+ HGCMPageListInfo PgLst;
+} VBOXSFREADPGLSTREQ;
+
+/**
+ * SHFL_FN_READ request using page list for data buffer (caller populated).
+ */
+DECLINLINE(int) VbglR0SfHostReqReadPgLst(SHFLROOT idRoot, VBOXSFREADPGLSTREQ *pReq, uint64_t hHostFile,
+ uint64_t offRead, uint32_t cbToRead, uint32_t cPages)
+{
+ VBGLIOCIDCHGCMFASTCALL_INIT(&pReq->Hdr, VbglR0PhysHeapGetPhysAddr(pReq), &pReq->Call, g_SfClient.idClient,
+ SHFL_FN_READ, SHFL_CPARMS_READ,
+ RT_UOFFSETOF_DYN(VBOXSFREADPGLSTREQ, PgLst.aPages[cPages]));
+
+ pReq->Parms.id32Root.type = VMMDevHGCMParmType_32bit;
+ pReq->Parms.id32Root.u.value32 = idRoot;
+
+ pReq->Parms.u64Handle.type = VMMDevHGCMParmType_64bit;
+ pReq->Parms.u64Handle.u.value64 = hHostFile;
+
+ pReq->Parms.off64Read.type = VMMDevHGCMParmType_64bit;
+ pReq->Parms.off64Read.u.value64 = offRead;
+
+ pReq->Parms.cb32Read.type = VMMDevHGCMParmType_32bit;
+ pReq->Parms.cb32Read.u.value32 = cbToRead;
+
+ pReq->Parms.pBuf.type = g_fHostFeatures & VMMDEV_HVF_HGCM_NO_BOUNCE_PAGE_LIST
+ ? VMMDevHGCMParmType_NoBouncePageList : VMMDevHGCMParmType_PageList;
+ pReq->Parms.pBuf.u.PageList.size = cbToRead;
+ pReq->Parms.pBuf.u.PageList.offset = RT_UOFFSETOF(VBOXSFREADPGLSTREQ, PgLst) - sizeof(VBGLIOCIDCHGCMFASTCALL);
+ pReq->PgLst.flags = VBOX_HGCM_F_PARM_DIRECTION_FROM_HOST;
+ pReq->PgLst.cPages = (uint16_t)cPages;
+ AssertReturn(cPages <= UINT16_MAX, VERR_OUT_OF_RANGE);
+ /* caller sets offset */
+
+ int vrc = VbglR0HGCMFastCall(g_SfClient.handle, &pReq->Hdr,
+ RT_UOFFSETOF_DYN(VBOXSFREADPGLSTREQ, PgLst.aPages[cPages]));
+ if (RT_SUCCESS(vrc))
+ vrc = pReq->Call.header.result;
+ return vrc;
+}
+
+
+/**
+ * SHFL_FN_READ request using a physically contiguous buffer.
+ */
+DECLINLINE(int) VbglR0SfHostReqReadContig(SHFLROOT idRoot, VBOXSFREADPGLSTREQ *pReq, uint64_t hHostFile,
+ uint64_t offRead, uint32_t cbToRead, void *pvBuffer, RTGCPHYS64 PhysBuffer)
+{
+ VBGLIOCIDCHGCMFASTCALL_INIT(&pReq->Hdr, VbglR0PhysHeapGetPhysAddr(pReq), &pReq->Call, g_SfClient.idClient,
+ SHFL_FN_READ, SHFL_CPARMS_READ, RT_UOFFSETOF_DYN(VBOXSFREADPGLSTREQ, PgLst.aPages[1]));
+
+ pReq->Parms.id32Root.type = VMMDevHGCMParmType_32bit;
+ pReq->Parms.id32Root.u.value32 = idRoot;
+
+ pReq->Parms.u64Handle.type = VMMDevHGCMParmType_64bit;
+ pReq->Parms.u64Handle.u.value64 = hHostFile;
+
+ pReq->Parms.off64Read.type = VMMDevHGCMParmType_64bit;
+ pReq->Parms.off64Read.u.value64 = offRead;
+
+ pReq->Parms.cb32Read.type = VMMDevHGCMParmType_32bit;
+ pReq->Parms.cb32Read.u.value32 = cbToRead;
+
+ if (g_fHostFeatures & VMMDEV_HVF_HGCM_CONTIGUOUS_PAGE_LIST)
+ {
+ pReq->Parms.pBuf.type = VMMDevHGCMParmType_ContiguousPageList;
+ pReq->Parms.pBuf.u.PageList.size = cbToRead;
+ pReq->Parms.pBuf.u.PageList.offset = RT_UOFFSETOF(VBOXSFREADPGLSTREQ, PgLst) - sizeof(VBGLIOCIDCHGCMFASTCALL);
+ pReq->PgLst.flags = VBOX_HGCM_F_PARM_DIRECTION_FROM_HOST;
+ pReq->PgLst.offFirstPage = (uint16_t)(PhysBuffer & PAGE_OFFSET_MASK);
+ pReq->PgLst.cPages = 1;
+ pReq->PgLst.aPages[0] = PhysBuffer & ~(RTGCPHYS64)PAGE_OFFSET_MASK;
+ }
+ else
+ {
+ pReq->Parms.pBuf.type = VMMDevHGCMParmType_LinAddr_Out;
+ pReq->Parms.pBuf.u.LinAddr.cb = cbToRead;
+ pReq->Parms.pBuf.u.LinAddr.uAddr = (uintptr_t)pvBuffer;
+ }
+
+ int vrc = VbglR0HGCMFastCall(g_SfClient.handle, &pReq->Hdr, RT_UOFFSETOF_DYN(VBOXSFREADPGLSTREQ, PgLst.aPages[1]));
+ if (RT_SUCCESS(vrc))
+ vrc = pReq->Call.header.result;
+ return vrc;
+}
+
+
+
+/** Request structure for VbglR0SfHostReqWriteEmbedded. */
+typedef struct VBOXSFWRITEEMBEDDEDREQ
+{
+ VBGLIOCIDCHGCMFASTCALL Hdr;
+ VMMDevHGCMCall Call;
+ VBoxSFParmWrite Parms;
+ RT_FLEXIBLE_ARRAY_EXTENSION
+ uint8_t abData[RT_FLEXIBLE_ARRAY];
+} VBOXSFWRITEEMBEDDEDREQ;
+
+/**
+ * SHFL_FN_WRITE request using embedded data buffer.
+ */
+DECLINLINE(int) VbglR0SfHostReqWriteEmbedded(SHFLROOT idRoot, VBOXSFWRITEEMBEDDEDREQ *pReq, uint64_t hHostFile,
+ uint64_t offWrite, uint32_t cbToWrite)
+{
+ uint32_t const cbReq = RT_UOFFSETOF(VBOXSFWRITEEMBEDDEDREQ, abData[0])
+ + (g_fHostFeatures & VMMDEV_HVF_HGCM_EMBEDDED_BUFFERS ? cbToWrite : 0);
+ VBGLIOCIDCHGCMFASTCALL_INIT(&pReq->Hdr, VbglR0PhysHeapGetPhysAddr(pReq), &pReq->Call, g_SfClient.idClient,
+ SHFL_FN_WRITE, SHFL_CPARMS_WRITE, cbReq);
+
+ pReq->Parms.id32Root.type = VMMDevHGCMParmType_32bit;
+ pReq->Parms.id32Root.u.value32 = idRoot;
+
+ pReq->Parms.u64Handle.type = VMMDevHGCMParmType_64bit;
+ pReq->Parms.u64Handle.u.value64 = hHostFile;
+
+ pReq->Parms.off64Write.type = VMMDevHGCMParmType_64bit;
+ pReq->Parms.off64Write.u.value64 = offWrite;
+
+ pReq->Parms.cb32Write.type = VMMDevHGCMParmType_32bit;
+ pReq->Parms.cb32Write.u.value32 = cbToWrite;
+
+ if (g_fHostFeatures & VMMDEV_HVF_HGCM_EMBEDDED_BUFFERS)
+ {
+ pReq->Parms.pBuf.type = VMMDevHGCMParmType_Embedded;
+ pReq->Parms.pBuf.u.Embedded.cbData = cbToWrite;
+ pReq->Parms.pBuf.u.Embedded.offData = RT_UOFFSETOF(VBOXSFWRITEEMBEDDEDREQ, abData[0]) - sizeof(VBGLIOCIDCHGCMFASTCALL);
+ pReq->Parms.pBuf.u.Embedded.fFlags = VBOX_HGCM_F_PARM_DIRECTION_TO_HOST;
+ }
+ else
+ {
+ pReq->Parms.pBuf.type = VMMDevHGCMParmType_LinAddr_In;
+ pReq->Parms.pBuf.u.LinAddr.cb = cbToWrite;
+ pReq->Parms.pBuf.u.LinAddr.uAddr = (uintptr_t)&pReq->abData[0];
+ }
+
+ int vrc = VbglR0HGCMFastCall(g_SfClient.handle, &pReq->Hdr, cbReq);
+ if (RT_SUCCESS(vrc))
+ vrc = pReq->Call.header.result;
+ return vrc;
+}
+
+
+/** Request structure for vboxSfOs2HostReqWrite and VbglR0SfHostReqWriteContig. */
+typedef struct VBOXSFWRITEPGLSTREQ
+{
+ VBGLIOCIDCHGCMFASTCALL Hdr;
+ VMMDevHGCMCall Call;
+ VBoxSFParmWrite Parms;
+ HGCMPageListInfo PgLst;
+} VBOXSFWRITEPGLSTREQ;
+
+/**
+ * SHFL_FN_WRITE request using page list for data buffer (caller populated).
+ */
+DECLINLINE(int) VbglR0SfHostReqWritePgLst(SHFLROOT idRoot, VBOXSFWRITEPGLSTREQ *pReq, uint64_t hHostFile,
+ uint64_t offWrite, uint32_t cbToWrite, uint32_t cPages)
+{
+ VBGLIOCIDCHGCMFASTCALL_INIT(&pReq->Hdr, VbglR0PhysHeapGetPhysAddr(pReq), &pReq->Call, g_SfClient.idClient,
+ SHFL_FN_WRITE, SHFL_CPARMS_WRITE,
+ RT_UOFFSETOF_DYN(VBOXSFWRITEPGLSTREQ, PgLst.aPages[cPages]));
+
+ pReq->Parms.id32Root.type = VMMDevHGCMParmType_32bit;
+ pReq->Parms.id32Root.u.value32 = idRoot;
+
+ pReq->Parms.u64Handle.type = VMMDevHGCMParmType_64bit;
+ pReq->Parms.u64Handle.u.value64 = hHostFile;
+
+ pReq->Parms.off64Write.type = VMMDevHGCMParmType_64bit;
+ pReq->Parms.off64Write.u.value64 = offWrite;
+
+ pReq->Parms.cb32Write.type = VMMDevHGCMParmType_32bit;
+ pReq->Parms.cb32Write.u.value32 = cbToWrite;
+
+ pReq->Parms.pBuf.type = g_fHostFeatures & VMMDEV_HVF_HGCM_NO_BOUNCE_PAGE_LIST
+ ? VMMDevHGCMParmType_NoBouncePageList : VMMDevHGCMParmType_PageList;;
+ pReq->Parms.pBuf.u.PageList.size = cbToWrite;
+ pReq->Parms.pBuf.u.PageList.offset = RT_UOFFSETOF(VBOXSFWRITEPGLSTREQ, PgLst) - sizeof(VBGLIOCIDCHGCMFASTCALL);
+ pReq->PgLst.flags = VBOX_HGCM_F_PARM_DIRECTION_TO_HOST;
+ pReq->PgLst.cPages = (uint16_t)cPages;
+ AssertReturn(cPages <= UINT16_MAX, VERR_OUT_OF_RANGE);
+ /* caller sets offset */
+
+ int vrc = VbglR0HGCMFastCall(g_SfClient.handle, &pReq->Hdr,
+ RT_UOFFSETOF_DYN(VBOXSFWRITEPGLSTREQ, PgLst.aPages[cPages]));
+ if (RT_SUCCESS(vrc))
+ vrc = pReq->Call.header.result;
+ return vrc;
+}
+
+
+/**
+ * SHFL_FN_WRITE request using a physically contiguous buffer.
+ */
+DECLINLINE(int) VbglR0SfHostReqWriteContig(SHFLROOT idRoot, VBOXSFWRITEPGLSTREQ *pReq, uint64_t hHostFile,
+ uint64_t offWrite, uint32_t cbToWrite, void const *pvBuffer, RTGCPHYS64 PhysBuffer)
+{
+ VBGLIOCIDCHGCMFASTCALL_INIT(&pReq->Hdr, VbglR0PhysHeapGetPhysAddr(pReq), &pReq->Call, g_SfClient.idClient,
+ SHFL_FN_WRITE, SHFL_CPARMS_WRITE, RT_UOFFSETOF_DYN(VBOXSFWRITEPGLSTREQ, PgLst.aPages[1]));
+
+ pReq->Parms.id32Root.type = VMMDevHGCMParmType_32bit;
+ pReq->Parms.id32Root.u.value32 = idRoot;
+
+ pReq->Parms.u64Handle.type = VMMDevHGCMParmType_64bit;
+ pReq->Parms.u64Handle.u.value64 = hHostFile;
+
+ pReq->Parms.off64Write.type = VMMDevHGCMParmType_64bit;
+ pReq->Parms.off64Write.u.value64 = offWrite;
+
+ pReq->Parms.cb32Write.type = VMMDevHGCMParmType_32bit;
+ pReq->Parms.cb32Write.u.value32 = cbToWrite;
+
+ if (g_fHostFeatures & VMMDEV_HVF_HGCM_CONTIGUOUS_PAGE_LIST)
+ {
+ pReq->Parms.pBuf.type = VMMDevHGCMParmType_ContiguousPageList;
+ pReq->Parms.pBuf.u.PageList.size = cbToWrite;
+ pReq->Parms.pBuf.u.PageList.offset = RT_UOFFSETOF(VBOXSFWRITEPGLSTREQ, PgLst) - sizeof(VBGLIOCIDCHGCMFASTCALL);
+ pReq->PgLst.flags = VBOX_HGCM_F_PARM_DIRECTION_TO_HOST;
+ pReq->PgLst.offFirstPage = (uint16_t)(PhysBuffer & PAGE_OFFSET_MASK);
+ pReq->PgLst.cPages = 1;
+ pReq->PgLst.aPages[0] = PhysBuffer & ~(RTGCPHYS64)PAGE_OFFSET_MASK;
+ }
+ else
+ {
+ pReq->Parms.pBuf.type = VMMDevHGCMParmType_LinAddr_In;
+ pReq->Parms.pBuf.u.LinAddr.cb = cbToWrite;
+ pReq->Parms.pBuf.u.LinAddr.uAddr = (uintptr_t)pvBuffer;
+ }
+
+ int vrc = VbglR0HGCMFastCall(g_SfClient.handle, &pReq->Hdr, RT_UOFFSETOF_DYN(VBOXSFWRITEPGLSTREQ, PgLst.aPages[1]));
+ if (RT_SUCCESS(vrc))
+ vrc = pReq->Call.header.result;
+ return vrc;
+}
+
+
+/** Request structure for VbglR0SfHostReqCopyFilePart. */
+typedef struct VBOXSFCOPYFILEPARTREQ
+{
+ VBGLIOCIDCHGCMFASTCALL Hdr;
+ VMMDevHGCMCall Call;
+ VBoxSFParmCopyFilePart Parms;
+} VBOXSFCOPYFILEPARTREQ;
+
+/**
+ * SHFL_FN_CREATE request.
+ */
+DECLINLINE(int) VbglR0SfHostReqCopyFilePart(SHFLROOT idRootSrc, SHFLHANDLE hHostFileSrc, uint64_t offSrc,
+ SHFLROOT idRootDst, SHFLHANDLE hHostFileDst, uint64_t offDst,
+ uint64_t cbToCopy, uint32_t fFlags, VBOXSFCOPYFILEPARTREQ *pReq)
+{
+ VBGLIOCIDCHGCMFASTCALL_INIT(&pReq->Hdr, VbglR0PhysHeapGetPhysAddr(pReq), &pReq->Call, g_SfClient.idClient,
+ SHFL_FN_COPY_FILE_PART, SHFL_CPARMS_COPY_FILE_PART, sizeof(*pReq));
+
+ pReq->Parms.id32RootSrc.type = VMMDevHGCMParmType_32bit;
+ pReq->Parms.id32RootSrc.u.value32 = idRootSrc;
+
+ pReq->Parms.u64HandleSrc.type = VMMDevHGCMParmType_64bit;
+ pReq->Parms.u64HandleSrc.u.value64 = hHostFileSrc;
+
+ pReq->Parms.off64Src.type = VMMDevHGCMParmType_64bit;
+ pReq->Parms.off64Src.u.value64 = offSrc;
+
+ pReq->Parms.id32RootDst.type = VMMDevHGCMParmType_32bit;
+ pReq->Parms.id32RootDst.u.value32 = idRootDst;
+
+ pReq->Parms.u64HandleDst.type = VMMDevHGCMParmType_64bit;
+ pReq->Parms.u64HandleDst.u.value64 = hHostFileDst;
+
+ pReq->Parms.off64Dst.type = VMMDevHGCMParmType_64bit;
+ pReq->Parms.off64Dst.u.value64 = offDst;
+
+ pReq->Parms.cb64ToCopy.type = VMMDevHGCMParmType_64bit;
+ pReq->Parms.cb64ToCopy.u.value64 = cbToCopy;
+
+ pReq->Parms.f32Flags.type = VMMDevHGCMParmType_32bit;
+ pReq->Parms.f32Flags.u.value32 = fFlags;
+
+ int vrc = VbglR0HGCMFastCall(g_SfClient.handle, &pReq->Hdr, sizeof(*pReq));
+ if (RT_SUCCESS(vrc))
+ vrc = pReq->Call.header.result;
+ return vrc;
+}
+
+
+
+/** Request structure for VbglR0SfHostReqListDirContig2x() and
+ * VbglR0SfHostReqListDir(). */
+typedef struct VBOXSFLISTDIRREQ
+{
+ VBGLIOCIDCHGCMFASTCALL Hdr;
+ VMMDevHGCMCall Call;
+ VBoxSFParmList Parms;
+ HGCMPageListInfo StrPgLst;
+ HGCMPageListInfo BufPgLst;
+} VBOXSFLISTDIRREQ;
+
+/**
+ * SHFL_FN_LIST request with separate string buffer and buffers for entries,
+ * both physically contiguous allocations.
+ */
+DECLINLINE(int) VbglR0SfHostReqListDirContig2x(SHFLROOT idRoot, VBOXSFLISTDIRREQ *pReq, uint64_t hHostDir,
+ PSHFLSTRING pFilter, RTGCPHYS64 PhysFilter, uint32_t fFlags,
+ PSHFLDIRINFO pBuffer, RTGCPHYS64 PhysBuffer, uint32_t cbBuffer)
+{
+ VBGLIOCIDCHGCMFASTCALL_INIT(&pReq->Hdr, VbglR0PhysHeapGetPhysAddr(pReq), &pReq->Call, g_SfClient.idClient,
+ SHFL_FN_LIST, SHFL_CPARMS_LIST, sizeof(*pReq));
+
+ pReq->Parms.id32Root.type = VMMDevHGCMParmType_32bit;
+ pReq->Parms.id32Root.u.value32 = idRoot;
+
+ pReq->Parms.u64Handle.type = VMMDevHGCMParmType_64bit;
+ pReq->Parms.u64Handle.u.value64 = hHostDir;
+
+ pReq->Parms.f32Flags.type = VMMDevHGCMParmType_32bit;
+ pReq->Parms.f32Flags.u.value32 = fFlags;
+
+ pReq->Parms.cb32Buffer.type = VMMDevHGCMParmType_32bit;
+ pReq->Parms.cb32Buffer.u.value32 = cbBuffer;
+
+ if (g_fHostFeatures & VMMDEV_HVF_HGCM_CONTIGUOUS_PAGE_LIST)
+ {
+ pReq->Parms.pStrFilter.type = VMMDevHGCMParmType_ContiguousPageList;
+ pReq->Parms.pStrFilter.u.PageList.offset = RT_UOFFSETOF(VBOXSFLISTDIRREQ, StrPgLst) - sizeof(VBGLIOCIDCHGCMFASTCALL);
+ pReq->StrPgLst.flags = VBOX_HGCM_F_PARM_DIRECTION_TO_HOST;
+ pReq->StrPgLst.cPages = 1;
+ if (pFilter)
+ {
+ pReq->Parms.pStrFilter.u.PageList.size = SHFLSTRING_HEADER_SIZE + pFilter->u16Size;
+ uint32_t const offFirstPage = (uint32_t)PhysFilter & PAGE_OFFSET_MASK;
+ pReq->StrPgLst.offFirstPage = (uint16_t)offFirstPage;
+ pReq->StrPgLst.aPages[0] = PhysFilter - offFirstPage;
+ }
+ else
+ {
+ pReq->Parms.pStrFilter.u.PageList.size = 0;
+ pReq->StrPgLst.offFirstPage = 0;
+ pReq->StrPgLst.aPages[0] = NIL_RTGCPHYS64;
+ }
+
+ pReq->Parms.pBuffer.type = VMMDevHGCMParmType_ContiguousPageList;
+ pReq->Parms.pBuffer.u.PageList.offset = RT_UOFFSETOF(VBOXSFLISTDIRREQ, BufPgLst) - sizeof(VBGLIOCIDCHGCMFASTCALL);
+ pReq->Parms.pBuffer.u.PageList.size = cbBuffer;
+ pReq->BufPgLst.flags = VBOX_HGCM_F_PARM_DIRECTION_FROM_HOST;
+ pReq->BufPgLst.cPages = 1;
+ uint32_t const offFirstPage = (uint32_t)PhysBuffer & PAGE_OFFSET_MASK;
+ pReq->BufPgLst.offFirstPage = (uint16_t)offFirstPage;
+ pReq->BufPgLst.aPages[0] = PhysBuffer - offFirstPage;
+ }
+ else
+ {
+ pReq->Parms.pStrFilter.type = VMMDevHGCMParmType_LinAddr_In;
+ pReq->Parms.pStrFilter.u.LinAddr.cb = pFilter ? SHFLSTRING_HEADER_SIZE + pFilter->u16Size : 0;
+ pReq->Parms.pStrFilter.u.LinAddr.uAddr = (uintptr_t)pFilter;
+
+ pReq->Parms.pBuffer.type = VMMDevHGCMParmType_LinAddr_Out;
+ pReq->Parms.pBuffer.u.LinAddr.cb = cbBuffer;
+ pReq->Parms.pBuffer.u.LinAddr.uAddr = (uintptr_t)pBuffer;
+ }
+
+ pReq->Parms.f32More.type = VMMDevHGCMParmType_32bit;
+ pReq->Parms.f32More.u.value32 = 0;
+
+ pReq->Parms.c32Entries.type = VMMDevHGCMParmType_32bit;
+ pReq->Parms.c32Entries.u.value32 = 0;
+
+ int vrc = VbglR0HGCMFastCall(g_SfClient.handle, &pReq->Hdr, sizeof(*pReq));
+ if (RT_SUCCESS(vrc))
+ vrc = pReq->Call.header.result;
+ return vrc;
+}
+
+/**
+ * SHFL_FN_LIST request with separate string buffer and buffers for entries,
+ * both allocated on the physical heap.
+ */
+DECLINLINE(int) VbglR0SfHostReqListDir(SHFLROOT idRoot, VBOXSFLISTDIRREQ *pReq, uint64_t hHostDir,
+ PSHFLSTRING pFilter, uint32_t fFlags, PSHFLDIRINFO pBuffer, uint32_t cbBuffer)
+{
+ return VbglR0SfHostReqListDirContig2x(idRoot,
+ pReq,
+ hHostDir,
+ pFilter,
+ pFilter ? VbglR0PhysHeapGetPhysAddr(pFilter) : NIL_RTGCPHYS64,
+ fFlags,
+ pBuffer,
+ VbglR0PhysHeapGetPhysAddr(pBuffer),
+ cbBuffer);
+}
+
+
+/** Request structure for VbglR0SfHostReqReadLink. */
+typedef struct VBOXSFREADLINKREQ
+{
+ VBGLIOCIDCHGCMFASTCALL Hdr;
+ VMMDevHGCMCall Call;
+ VBoxSFParmReadLink Parms;
+ HGCMPageListInfo PgLst;
+ SHFLSTRING StrPath;
+} VBOXSFREADLINKREQ;
+
+/**
+ * SHFL_FN_READLINK request.
+ *
+ * @note Buffer contains UTF-8 characters on success, regardless of the
+ * UTF-8/UTF-16 setting of the connection.
+ */
+DECLINLINE(int) VbglR0SfHostReqReadLinkContig(SHFLROOT idRoot, void *pvBuffer, RTGCPHYS64 PhysBuffer, uint32_t cbBuffer,
+ VBOXSFREADLINKREQ *pReq)
+{
+ uint32_t const cbReq = g_fHostFeatures & VMMDEV_HVF_HGCM_EMBEDDED_BUFFERS
+ ? RT_UOFFSETOF(VBOXSFREADLINKREQ, StrPath.String) + pReq->StrPath.u16Size
+ : cbBuffer <= PAGE_SIZE - (PhysBuffer & PAGE_OFFSET_MASK)
+ || (g_fHostFeatures & VMMDEV_HVF_HGCM_CONTIGUOUS_PAGE_LIST)
+ ? RT_UOFFSETOF(VBOXSFREADLINKREQ, StrPath.String)
+ : RT_UOFFSETOF(VBOXSFREADLINKREQ, PgLst);
+ VBGLIOCIDCHGCMFASTCALL_INIT(&pReq->Hdr, VbglR0PhysHeapGetPhysAddr(pReq), &pReq->Call, g_SfClient.idClient,
+ SHFL_FN_READLINK, SHFL_CPARMS_READLINK, cbReq);
+
+ pReq->Parms.id32Root.type = VMMDevHGCMParmType_32bit;
+ pReq->Parms.id32Root.u.value32 = idRoot;
+
+ if (g_fHostFeatures & VMMDEV_HVF_HGCM_EMBEDDED_BUFFERS)
+ {
+ pReq->Parms.pStrPath.type = VMMDevHGCMParmType_Embedded;
+ pReq->Parms.pStrPath.u.Embedded.cbData = SHFLSTRING_HEADER_SIZE + pReq->StrPath.u16Size;
+ pReq->Parms.pStrPath.u.Embedded.offData = RT_UOFFSETOF(VBOXSFREADLINKREQ, StrPath)
+ - sizeof(VBGLIOCIDCHGCMFASTCALL);
+ pReq->Parms.pStrPath.u.Embedded.fFlags = VBOX_HGCM_F_PARM_DIRECTION_TO_HOST;
+ }
+ else
+ {
+ pReq->Parms.pStrPath.type = VMMDevHGCMParmType_LinAddr_In;
+ pReq->Parms.pStrPath.u.LinAddr.cb = SHFLSTRING_HEADER_SIZE + pReq->StrPath.u16Size;
+ pReq->Parms.pStrPath.u.LinAddr.uAddr = (uintptr_t)&pReq->StrPath;
+ }
+
+ if ( cbBuffer <= PAGE_SIZE - (PhysBuffer & PAGE_OFFSET_MASK)
+ || (g_fHostFeatures & VMMDEV_HVF_HGCM_CONTIGUOUS_PAGE_LIST))
+ {
+ pReq->Parms.pBuffer.type = cbBuffer <= PAGE_SIZE - (PhysBuffer & PAGE_OFFSET_MASK)
+ ? VMMDevHGCMParmType_PageList
+ : VMMDevHGCMParmType_ContiguousPageList;
+ pReq->Parms.pBuffer.u.PageList.size = cbBuffer;
+ pReq->Parms.pBuffer.u.PageList.offset = RT_UOFFSETOF(VBOXSFREADLINKREQ, PgLst)
+ - sizeof(VBGLIOCIDCHGCMFASTCALL);
+ pReq->PgLst.flags = VBOX_HGCM_F_PARM_DIRECTION_FROM_HOST;
+ pReq->PgLst.offFirstPage = (uint16_t)PhysBuffer & (uint16_t)(PAGE_OFFSET_MASK);
+ pReq->PgLst.aPages[0] = PhysBuffer & ~(RTGCPHYS64)PAGE_OFFSET_MASK;
+ pReq->PgLst.cPages = 1;
+ }
+ else
+ {
+ pReq->Parms.pBuffer.type = VMMDevHGCMParmType_LinAddr_Out;
+ pReq->Parms.pBuffer.u.LinAddr.cb = cbBuffer;
+ pReq->Parms.pBuffer.u.LinAddr.uAddr = (uintptr_t)pvBuffer;
+ }
+
+ int vrc = VbglR0HGCMFastCall(g_SfClient.handle, &pReq->Hdr, cbReq);
+ if (RT_SUCCESS(vrc))
+ vrc = pReq->Call.header.result;
+ return vrc;
+}
+
+/**
+ * SHFL_FN_READLINK request, simplified version.
+ *
+ *
+ * @note Buffer contains UTF-8 characters on success, regardless of the
+ * UTF-8/UTF-16 setting of the connection.
+ */
+DECLINLINE(int) VbglR0SfHostReqReadLinkContigSimple(SHFLROOT idRoot, const char *pszPath, size_t cchPath, void *pvBuf,
+ RTGCPHYS64 PhysBuffer, uint32_t cbBuffer)
+{
+ if (cchPath < _64K - 1)
+ {
+ VBOXSFREADLINKREQ *pReq = (VBOXSFREADLINKREQ *)VbglR0PhysHeapAlloc(RT_UOFFSETOF(VBOXSFREADLINKREQ, StrPath.String)
+ + SHFLSTRING_HEADER_SIZE + (uint32_t)cchPath);
+ if (pReq)
+ {
+ pReq->StrPath.u16Length = (uint16_t)cchPath;
+ pReq->StrPath.u16Size = (uint16_t)cchPath + 1;
+ memcpy(pReq->StrPath.String.ach, pszPath, cchPath);
+ pReq->StrPath.String.ach[cchPath] = '\0';
+
+ {
+ int vrc = VbglR0SfHostReqReadLinkContig(idRoot, pvBuf, PhysBuffer, cbBuffer, pReq);
+ VbglR0PhysHeapFree(pReq);
+ return vrc;
+ }
+ }
+ return VERR_NO_MEMORY;
+ }
+ return VERR_FILENAME_TOO_LONG;
+}
+
+
+/** Request structure for VbglR0SfHostReqCreateSymlink. */
+typedef struct VBOXSFCREATESYMLINKREQ
+{
+ VBGLIOCIDCHGCMFASTCALL Hdr;
+ VMMDevHGCMCall Call;
+ VBoxSFParmCreateSymlink Parms;
+ HGCMPageListInfo PgLstTarget;
+ SHFLFSOBJINFO ObjInfo;
+ SHFLSTRING StrSymlinkPath;
+} VBOXSFCREATESYMLINKREQ;
+
+/**
+ * SHFL_FN_SYMLINK request.
+ *
+ * Caller fills in the symlink string and supplies a physical contiguous
+ * target string
+ */
+DECLINLINE(int) VbglR0SfHostReqCreateSymlinkContig(SHFLROOT idRoot, PCSHFLSTRING pStrTarget, RTGCPHYS64 PhysTarget,
+ VBOXSFCREATESYMLINKREQ *pReq)
+{
+ uint32_t const cbTarget = SHFLSTRING_HEADER_SIZE + pStrTarget->u16Size;
+ uint32_t const cbReq = g_fHostFeatures & VMMDEV_HVF_HGCM_EMBEDDED_BUFFERS
+ ? RT_UOFFSETOF(VBOXSFCREATESYMLINKREQ, StrSymlinkPath.String) + pReq->StrSymlinkPath.u16Size
+ : RT_UOFFSETOF(VBOXSFCREATESYMLINKREQ, ObjInfo) /*simplified*/;
+ VBGLIOCIDCHGCMFASTCALL_INIT(&pReq->Hdr, VbglR0PhysHeapGetPhysAddr(pReq), &pReq->Call, g_SfClient.idClient,
+ SHFL_FN_SYMLINK, SHFL_CPARMS_SYMLINK, cbReq);
+
+ pReq->Parms.id32Root.type = VMMDevHGCMParmType_32bit;
+ pReq->Parms.id32Root.u.value32 = idRoot;
+
+ if (g_fHostFeatures & VMMDEV_HVF_HGCM_EMBEDDED_BUFFERS)
+ {
+ pReq->Parms.pStrSymlink.type = VMMDevHGCMParmType_Embedded;
+ pReq->Parms.pStrSymlink.u.Embedded.cbData = SHFLSTRING_HEADER_SIZE + pReq->StrSymlinkPath.u16Size;
+ pReq->Parms.pStrSymlink.u.Embedded.offData = RT_UOFFSETOF(VBOXSFCREATESYMLINKREQ, StrSymlinkPath)
+ - sizeof(VBGLIOCIDCHGCMFASTCALL);
+ pReq->Parms.pStrSymlink.u.Embedded.fFlags = VBOX_HGCM_F_PARM_DIRECTION_TO_HOST;
+ }
+ else
+ {
+ pReq->Parms.pStrSymlink.type = VMMDevHGCMParmType_LinAddr_In;
+ pReq->Parms.pStrSymlink.u.LinAddr.cb = SHFLSTRING_HEADER_SIZE + pReq->StrSymlinkPath.u16Size;
+ pReq->Parms.pStrSymlink.u.LinAddr.uAddr = (uintptr_t)&pReq->StrSymlinkPath;
+ }
+
+ if ( cbTarget <= PAGE_SIZE - (PhysTarget & PAGE_OFFSET_MASK)
+ || (g_fHostFeatures & VMMDEV_HVF_HGCM_CONTIGUOUS_PAGE_LIST))
+ {
+ pReq->Parms.pStrTarget.type = cbTarget <= PAGE_SIZE - (PhysTarget & PAGE_OFFSET_MASK)
+ ? VMMDevHGCMParmType_PageList
+ : VMMDevHGCMParmType_ContiguousPageList;
+ pReq->Parms.pStrTarget.u.PageList.size = cbTarget;
+ pReq->Parms.pStrTarget.u.PageList.offset = RT_UOFFSETOF(VBOXSFCREATESYMLINKREQ, PgLstTarget)
+ - sizeof(VBGLIOCIDCHGCMFASTCALL);
+ pReq->PgLstTarget.flags = VBOX_HGCM_F_PARM_DIRECTION_TO_HOST;
+ pReq->PgLstTarget.offFirstPage = (uint16_t)PhysTarget & (uint16_t)(PAGE_OFFSET_MASK);
+ pReq->PgLstTarget.aPages[0] = PhysTarget & ~(RTGCPHYS64)PAGE_OFFSET_MASK;
+ pReq->PgLstTarget.cPages = 1;
+ }
+ else
+ {
+ pReq->Parms.pStrTarget.type = VMMDevHGCMParmType_LinAddr_In;
+ pReq->Parms.pStrTarget.u.LinAddr.cb = cbTarget;
+ pReq->Parms.pStrTarget.u.LinAddr.uAddr = (uintptr_t)pStrTarget;
+ }
+
+ if (g_fHostFeatures & VMMDEV_HVF_HGCM_EMBEDDED_BUFFERS)
+ {
+ pReq->Parms.pInfo.type = VMMDevHGCMParmType_Embedded;
+ pReq->Parms.pInfo.u.Embedded.cbData = sizeof(pReq->ObjInfo);
+ pReq->Parms.pInfo.u.Embedded.offData = RT_UOFFSETOF(VBOXSFCREATESYMLINKREQ, ObjInfo)
+ - sizeof(VBGLIOCIDCHGCMFASTCALL);
+ pReq->Parms.pInfo.u.Embedded.fFlags = VBOX_HGCM_F_PARM_DIRECTION_FROM_HOST;
+ }
+ else
+ {
+ pReq->Parms.pInfo.type = VMMDevHGCMParmType_LinAddr_Out;
+ pReq->Parms.pInfo.u.LinAddr.cb = sizeof(pReq->ObjInfo);
+ pReq->Parms.pInfo.u.LinAddr.uAddr = (uintptr_t)&pReq->ObjInfo;
+ }
+
+ int vrc = VbglR0HGCMFastCall(g_SfClient.handle, &pReq->Hdr, cbReq);
+ if (RT_SUCCESS(vrc))
+ vrc = pReq->Call.header.result;
+ return vrc;
+}
+
+/** @} */
+
+#endif /* !VBOX_INCLUDED_VBoxGuestLibSharedFoldersInline_h */
+
diff --git a/include/VBox/VBoxGuestMangling.h b/include/VBox/VBoxGuestMangling.h
new file mode 100644
index 00000000..2049051d
--- /dev/null
+++ b/include/VBox/VBoxGuestMangling.h
@@ -0,0 +1,49 @@
+/** @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-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_VBoxGuestMangling_h
+#define VBOX_INCLUDED_VBoxGuestMangling_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#define RT_MANGLER(symbol) VBoxGuest_##symbol
+#include <iprt/mangling.h>
+
+#endif /* !VBOX_INCLUDED_VBoxGuestMangling_h */
+
diff --git a/include/VBox/VBoxKeyboard.h b/include/VBox/VBoxKeyboard.h
new file mode 100644
index 00000000..c39bf522
--- /dev/null
+++ b/include/VBox/VBoxKeyboard.h
@@ -0,0 +1,56 @@
+/** @file
+ * Frontends/Common - X11 keyboard driver interface.
+ */
+
+/*
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+/*
+ * Oracle LGPL Disclaimer: For the avoidance of doubt, except that if any license choice
+ * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
+ * the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where
+ * a choice of LGPL license versions is made available with the language indicating
+ * that LGPLv2 or any later version may be used, or where a choice of which version
+ * of the LGPL is applied is otherwise unspecified.
+ */
+
+#ifndef VBOX_INCLUDED_VBoxKeyboard_h
+#define VBOX_INCLUDED_VBoxKeyboard_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <X11/Xlib.h>
+
+/* Exported definitions */
+#undef CCALL
+#ifdef __cplusplus
+# define CCALL "C"
+#else
+# define CCALL
+#endif
+#ifdef VBOX_HAVE_VISIBILITY_HIDDEN
+extern CCALL __attribute__((visibility("default"))) unsigned *X11DRV_getKeyc2scan(void);
+extern CCALL __attribute__((visibility("default"))) unsigned X11DRV_InitKeyboard(Display *dpy, unsigned *byLayoutOK, unsigned *byTypeOK, unsigned *byXkbOK, int (*remapScancodes)[2]);
+extern CCALL __attribute__((visibility("default"))) unsigned X11DRV_KeyEvent(Display *dpy, KeyCode code);
+#else
+extern CCALL unsigned *X11DRV_getKeyc2scan(void);
+extern CCALL unsigned X11DRV_InitKeyboard(Display *dpy, unsigned *byLayoutOK, unsigned *byTypeOK, unsigned *byXkbOK, int (*remapScancodes)[2]);
+extern CCALL unsigned X11DRV_KeyEvent(Display *dpy, KeyCode code);
+#endif
+
+#endif /* !VBOX_INCLUDED_VBoxKeyboard_h */
+
diff --git a/include/VBox/VBoxNetCfg-win.h b/include/VBox/VBoxNetCfg-win.h
new file mode 100644
index 00000000..8a1dc671
--- /dev/null
+++ b/include/VBox/VBoxNetCfg-win.h
@@ -0,0 +1,147 @@
+/* $Id: VBoxNetCfg-win.h $ */
+/** @file
+ * Network Configuration API for Windows platforms.
+ */
+
+/*
+ * Copyright (C) 2011-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_VBoxNetCfg_win_h
+#define VBOX_INCLUDED_VBoxNetCfg_win_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+/*
+ * Defining VBOXNETCFG_DELAYEDRENAME postpones renaming of host-only adapter
+ * connection during adapter creation after it has been assigned with an
+ * IP address. This hopefully prevents collisions that may happen when we
+ * attempt to rename a connection too early, while its configuration is
+ * still being 'committed' by the network setup engine.
+ */
+#define VBOXNETCFG_DELAYEDRENAME
+
+#include <iprt/win/winsock2.h>
+#include <iprt/win/windows.h>
+#include <Netcfgn.h>
+#include <iprt/win/Setupapi.h>
+#include <VBox/cdefs.h>
+#include <iprt/types.h>
+
+/** @defgroup grp_vboxnetcfgwin The Windows Network Configration Library
+ * @{ */
+
+/** @def VBOXNETCFGWIN_DECL
+ * The usual declaration wrapper.
+ */
+#if 0
+/* enable this in case we include this in a dll*/
+# ifdef IN_VBOXDDU
+# define VBOXNETCFGWIN_DECL(a_Type) DECLEXPORT(a_Type)
+# else
+# define VBOXNETCFGWIN_DECL(a_Type) DECLIMPORT(a_Type)
+# endif
+#else
+/*enable this in case we include this in a static lib*/
+# define VBOXNETCFGWIN_DECL(a_Type) a_Type VBOXCALL
+#endif
+
+RT_C_DECLS_BEGIN
+
+VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinQueryINetCfg(OUT INetCfg **ppNetCfg,
+ IN BOOL fGetWriteLock,
+ IN LPCWSTR pszwClientDescription,
+ IN DWORD cmsTimeout,
+ OUT LPWSTR *ppszwClientDescription);
+VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinReleaseINetCfg(IN INetCfg *pNetCfg, IN BOOL fHasWriteLock);
+VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinGetComponentByGuid(IN INetCfg *pNc, IN const GUID *pguidClass,
+ IN const GUID * pComponentGuid, OUT INetCfgComponent **ppncc);
+
+VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinNetFltInstall(IN INetCfg *pNc, IN LPCWSTR const *pwszInfFullPaths, IN UINT cInfFullPaths);
+VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinNetFltUninstall(IN INetCfg *pNc);
+VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinNetLwfInstall(IN INetCfg *pNc, IN LPCWSTR const pwszInfFullPath);
+VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinNetLwfUninstall(IN INetCfg *pNc);
+
+VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinNetAdpUninstall(IN INetCfg *pNc, IN LPCWSTR pwszId);
+VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinNetAdpInstall(IN INetCfg *pNc,IN LPCWSTR const pwszInfFullPath);
+
+#ifndef VBOXNETCFG_DELAYEDRENAME
+VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinCreateHostOnlyNetworkInterface(IN LPCWSTR pwszInfPath, IN bool fIsInfPathFile,
+ IN BSTR pBstrDesiredName,
+ OUT GUID *pGuid, OUT BSTR *pBstrName, OUT BSTR *pErrMsg);
+#else /* VBOXNETCFG_DELAYEDRENAME */
+VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinCreateHostOnlyNetworkInterface(IN LPCWSTR pwszInfPath, IN bool fIsInfPathFile,
+ IN BSTR pBstrDesiredName,
+ OUT GUID *pGuid, OUT BSTR *pBstrId, OUT BSTR *pErrMsg);
+VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinRenameHostOnlyConnection(IN const GUID *pGuid, IN LPCWSTR pszId, OUT BSTR *pDevName);
+#endif /* VBOXNETCFG_DELAYEDRENAME */
+VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinUpdateHostOnlyNetworkInterface(LPCWSTR pcsxwInf, BOOL *pfRebootRequired, LPCWSTR pcsxwId);
+VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinRemoveHostOnlyNetworkInterface(IN const GUID *pGUID, OUT BSTR *pErrMsg);
+VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinRemoveAllNetDevicesOfId(IN LPCWSTR lpszPnPId);
+
+VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinGenHostonlyConnectionName(IN PCWSTR pwszDevName, OUT WCHAR *pwszBuf,
+ IN ULONG cwcBuf, OUT PULONG pcwcNeeded);
+VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinRenameConnection(IN LPWSTR pwszGuid, IN PCWSTR pwszNewName);
+
+typedef enum VBOXNECTFGWINPROPCHANGE_TYPE_T
+{
+ VBOXNECTFGWINPROPCHANGE_TYPE_UNDEFINED = 0,
+ VBOXNECTFGWINPROPCHANGE_TYPE_DISABLE,
+ VBOXNECTFGWINPROPCHANGE_TYPE_ENABLE
+} VBOXNECTFGWINPROPCHANGE_TYPE_T;
+
+VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinPropChangeAllNetDevicesOfId(IN LPCWSTR lpszPnPId, VBOXNECTFGWINPROPCHANGE_TYPE_T enmPcType);
+
+VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinGenHostOnlyNetworkNetworkIp(OUT PULONG pNetIp, OUT PULONG pNetMask);
+
+typedef struct ADAPTER_SETTINGS
+{
+ ULONG ip;
+ ULONG mask;
+ BOOL bDhcp;
+} ADAPTER_SETTINGS, *PADAPTER_SETTINGS; /**< I'm not prefixed */
+
+VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinEnableStaticIpConfig(IN const GUID *pGuid, IN ULONG ip, IN ULONG mask);
+VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinGetAdapterSettings(IN const GUID * pGuid, OUT PADAPTER_SETTINGS pSettings);
+VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinEnableDynamicIpConfig(IN const GUID *pGuid);
+VBOXNETCFGWIN_DECL(HRESULT) VBoxNetCfgWinDhcpRediscover(IN const GUID *pGuid);
+
+
+typedef DECLCALLBACKTYPE(void, FNVBOXNETCFGLOGGER,(const char *pszString));
+typedef FNVBOXNETCFGLOGGER *PFNVBOXNETCFGLOGGER;
+VBOXNETCFGWIN_DECL(void) VBoxNetCfgWinSetLogging(IN PFNVBOXNETCFGLOGGER pfnLogger);
+
+RT_C_DECLS_END
+
+/** @} */
+
+#endif /* !VBOX_INCLUDED_VBoxNetCfg_win_h */
+
diff --git a/include/VBox/VBoxNetCmn-win.h b/include/VBox/VBoxNetCmn-win.h
new file mode 100644
index 00000000..e1e0e643
--- /dev/null
+++ b/include/VBox/VBoxNetCmn-win.h
@@ -0,0 +1,163 @@
+/* $Id: VBoxNetCmn-win.h $ */
+/** @file
+ * VBoxNetCmn-win.h - NDIS6 Networking Driver Common Definitions, Windows-specific code.
+ */
+
+/*
+ * Copyright (C) 2014-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_VBoxNetCmn_win_h
+#define VBOX_INCLUDED_VBoxNetCmn_win_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/log.h> /* for LOG_ENABLED */
+
+
+DECLHIDDEN(void) vboxNetCmnWinDumpOidRequest(const char *pcszFunction, PNDIS_OID_REQUEST pRequest)
+{
+# ifdef LOG_ENABLED
+ const char *pszType;
+ const char *pszOid = "unknown";
+
+ switch (pRequest->RequestType)
+ {
+ case NdisRequestSetInformation: pszType = "set"; break;
+ case NdisRequestMethod: pszType = "method"; break;
+ case NdisRequestQueryInformation: pszType = "query info"; break;
+ case NdisRequestQueryStatistics: pszType = "query stats"; break;
+ default: pszType = "unknown";
+ }
+ switch (pRequest->DATA.SET_INFORMATION.Oid)
+ {
+ case OID_GEN_MAX_LINK_SPEED: pszOid = "OID_GEN_MAX_LINK_SPEED"; break;
+ case OID_GEN_LINK_STATE: pszOid = "OID_GEN_LINK_STATE"; break;
+ case OID_GEN_LINK_PARAMETERS: pszOid = "OID_GEN_LINK_PARAMETERS"; break;
+ case OID_GEN_MINIPORT_RESTART_ATTRIBUTES: pszOid = "OID_GEN_MINIPORT_RESTART_ATTRIBUTES"; break;
+ case OID_GEN_ENUMERATE_PORTS: pszOid = "OID_GEN_ENUMERATE_PORTS"; break;
+ case OID_GEN_PORT_STATE: pszOid = "OID_GEN_PORT_STATE"; break;
+ case OID_GEN_PORT_AUTHENTICATION_PARAMETERS: pszOid = "OID_GEN_PORT_AUTHENTICATION_PARAMETERS"; break;
+ case OID_GEN_INTERRUPT_MODERATION: pszOid = "OID_GEN_INTERRUPT_MODERATION"; break;
+ case OID_GEN_PHYSICAL_MEDIUM_EX: pszOid = "OID_GEN_PHYSICAL_MEDIUM_EX"; break;
+ case OID_GEN_SUPPORTED_LIST: pszOid = "OID_GEN_SUPPORTED_LIST"; break;
+ case OID_GEN_HARDWARE_STATUS: pszOid = "OID_GEN_HARDWARE_STATUS"; break;
+ case OID_GEN_MEDIA_SUPPORTED: pszOid = "OID_GEN_MEDIA_SUPPORTED"; break;
+ case OID_GEN_MEDIA_IN_USE: pszOid = "OID_GEN_MEDIA_IN_USE"; break;
+ case OID_GEN_MAXIMUM_LOOKAHEAD: pszOid = "OID_GEN_MAXIMUM_LOOKAHEAD"; break;
+ case OID_GEN_MAXIMUM_FRAME_SIZE: pszOid = "OID_GEN_MAXIMUM_FRAME_SIZE"; break;
+ case OID_GEN_LINK_SPEED: pszOid = "OID_GEN_LINK_SPEED"; break;
+ case OID_GEN_TRANSMIT_BUFFER_SPACE: pszOid = "OID_GEN_TRANSMIT_BUFFER_SPACE"; break;
+ case OID_GEN_RECEIVE_BUFFER_SPACE: pszOid = "OID_GEN_RECEIVE_BUFFER_SPACE"; break;
+ case OID_GEN_TRANSMIT_BLOCK_SIZE: pszOid = "OID_GEN_TRANSMIT_BLOCK_SIZE"; break;
+ case OID_GEN_RECEIVE_BLOCK_SIZE: pszOid = "OID_GEN_RECEIVE_BLOCK_SIZE"; break;
+ case OID_GEN_VENDOR_ID: pszOid = "OID_GEN_VENDOR_ID"; break;
+ case OID_GEN_VENDOR_DESCRIPTION: pszOid = "OID_GEN_VENDOR_DESCRIPTION"; break;
+ case OID_GEN_VENDOR_DRIVER_VERSION: pszOid = "OID_GEN_VENDOR_DRIVER_VERSION"; break;
+ case OID_GEN_CURRENT_PACKET_FILTER: pszOid = "OID_GEN_CURRENT_PACKET_FILTER"; break;
+ case OID_GEN_CURRENT_LOOKAHEAD: pszOid = "OID_GEN_CURRENT_LOOKAHEAD"; break;
+ case OID_GEN_DRIVER_VERSION: pszOid = "OID_GEN_DRIVER_VERSION"; break;
+ case OID_GEN_MAXIMUM_TOTAL_SIZE: pszOid = "OID_GEN_MAXIMUM_TOTAL_SIZE"; break;
+ case OID_GEN_PROTOCOL_OPTIONS: pszOid = "OID_GEN_PROTOCOL_OPTIONS"; break;
+ case OID_GEN_MAC_OPTIONS: pszOid = "OID_GEN_MAC_OPTIONS"; break;
+ case OID_GEN_MEDIA_CONNECT_STATUS: pszOid = "OID_GEN_MEDIA_CONNECT_STATUS"; break;
+ case OID_GEN_MAXIMUM_SEND_PACKETS: pszOid = "OID_GEN_MAXIMUM_SEND_PACKETS"; break;
+ case OID_GEN_SUPPORTED_GUIDS: pszOid = "OID_GEN_SUPPORTED_GUIDS"; break;
+ case OID_GEN_NETWORK_LAYER_ADDRESSES: pszOid = "OID_GEN_NETWORK_LAYER_ADDRESSES"; break;
+ case OID_GEN_TRANSPORT_HEADER_OFFSET: pszOid = "OID_GEN_TRANSPORT_HEADER_OFFSET"; break;
+ case OID_GEN_PHYSICAL_MEDIUM: pszOid = "OID_GEN_PHYSICAL_MEDIUM"; break;
+ case OID_GEN_MACHINE_NAME: pszOid = "OID_GEN_MACHINE_NAME"; break;
+ case OID_GEN_VLAN_ID: pszOid = "OID_GEN_VLAN_ID"; break;
+ case OID_GEN_RNDIS_CONFIG_PARAMETER: pszOid = "OID_GEN_RNDIS_CONFIG_PARAMETER"; break;
+ case OID_GEN_NDIS_RESERVED_1: pszOid = "OID_GEN_NDIS_RESERVED_1"; break;
+ case OID_GEN_NDIS_RESERVED_2: pszOid = "OID_GEN_NDIS_RESERVED_2"; break;
+ case OID_GEN_NDIS_RESERVED_5: pszOid = "OID_GEN_NDIS_RESERVED_5"; break;
+ case OID_GEN_MEDIA_CAPABILITIES: pszOid = "OID_GEN_MEDIA_CAPABILITIES"; break;
+ case OID_GEN_DEVICE_PROFILE: pszOid = "OID_GEN_DEVICE_PROFILE"; break;
+ case OID_GEN_FRIENDLY_NAME: pszOid = "OID_GEN_FRIENDLY_NAME"; break;
+ case OID_802_3_ADD_MULTICAST_ADDRESS: pszOid = "OID_802_3_ADD_MULTICAST_ADDRESS"; break;
+ case OID_802_3_DELETE_MULTICAST_ADDRESS: pszOid = "OID_802_3_DELETE_MULTICAST_ADDRESS"; break;
+ case OID_802_3_PERMANENT_ADDRESS: pszOid = "OID_802_3_PERMANENT_ADDRESS"; break;
+ case OID_802_3_CURRENT_ADDRESS: pszOid = "OID_802_3_CURRENT_ADDRESS"; break;
+ case OID_802_3_MULTICAST_LIST: pszOid = "OID_802_3_MULTICAST_LIST"; break;
+ case OID_802_3_MAXIMUM_LIST_SIZE: pszOid = "OID_802_3_MAXIMUM_LIST_SIZE"; break;
+ case OID_802_3_MAC_OPTIONS: pszOid = "OID_802_3_MAC_OPTIONS"; break;
+ case OID_TCP_TASK_OFFLOAD: pszOid = "OID_TCP_TASK_OFFLOAD"; break;
+ case OID_TCP_TASK_IPSEC_ADD_SA: pszOid = "OID_TCP_TASK_IPSEC_ADD_SA"; break;
+ case OID_TCP_TASK_IPSEC_ADD_UDPESP_SA: pszOid = "OID_TCP_TASK_IPSEC_ADD_UDPESP_SA"; break;
+ case OID_TCP_TASK_IPSEC_DELETE_SA: pszOid = "OID_TCP_TASK_IPSEC_DELETE_SA"; break;
+ case OID_TCP_TASK_IPSEC_DELETE_UDPESP_SA: pszOid = "OID_TCP_TASK_IPSEC_DELETE_UDPESP_SA"; break;
+
+ case OID_GEN_STATISTICS: pszOid = "OID_GEN_STATISTICS"; break;
+ case OID_GEN_BYTES_RCV: pszOid = "OID_GEN_BYTES_RCV"; break;
+ case OID_GEN_BYTES_XMIT: pszOid = "OID_GEN_BYTES_XMIT"; break;
+ case OID_GEN_RCV_DISCARDS: pszOid = "OID_GEN_RCV_DISCARDS"; break;
+ case OID_GEN_XMIT_DISCARDS: pszOid = "OID_GEN_XMIT_DISCARDS"; break;
+ case OID_GEN_XMIT_OK: pszOid = "OID_GEN_XMIT_OK"; break;
+ case OID_GEN_RCV_OK: pszOid = "OID_GEN_RCV_OK"; break;
+ case OID_GEN_XMIT_ERROR: pszOid = "OID_GEN_XMIT_ERROR"; break;
+ case OID_GEN_RCV_ERROR: pszOid = "OID_GEN_RCV_ERROR"; break;
+ case OID_GEN_RCV_NO_BUFFER: pszOid = "OID_GEN_RCV_NO_BUFFER"; break;
+ case OID_GEN_DIRECTED_BYTES_XMIT: pszOid = "OID_GEN_DIRECTED_BYTES_XMIT"; break;
+ case OID_GEN_DIRECTED_FRAMES_XMIT: pszOid = "OID_GEN_DIRECTED_FRAMES_XMIT"; break;
+ case OID_GEN_MULTICAST_BYTES_XMIT: pszOid = "OID_GEN_MULTICAST_BYTES_XMIT"; break;
+ case OID_GEN_MULTICAST_FRAMES_XMIT: pszOid = "OID_GEN_MULTICAST_FRAMES_XMIT"; break;
+ case OID_GEN_BROADCAST_BYTES_XMIT: pszOid = "OID_GEN_BROADCAST_BYTES_XMIT"; break;
+ case OID_GEN_BROADCAST_FRAMES_XMIT: pszOid = "OID_GEN_BROADCAST_FRAMES_XMIT"; break;
+ case OID_GEN_DIRECTED_BYTES_RCV: pszOid = "OID_GEN_DIRECTED_BYTES_RCV"; break;
+ case OID_GEN_DIRECTED_FRAMES_RCV: pszOid = "OID_GEN_DIRECTED_FRAMES_RCV"; break;
+ case OID_GEN_MULTICAST_BYTES_RCV: pszOid = "OID_GEN_MULTICAST_BYTES_RCV"; break;
+ case OID_GEN_MULTICAST_FRAMES_RCV: pszOid = "OID_GEN_MULTICAST_FRAMES_RCV"; break;
+ case OID_GEN_BROADCAST_BYTES_RCV: pszOid = "OID_GEN_BROADCAST_BYTES_RCV"; break;
+ case OID_GEN_BROADCAST_FRAMES_RCV: pszOid = "OID_GEN_BROADCAST_FRAMES_RCV"; break;
+ case OID_GEN_RCV_CRC_ERROR: pszOid = "OID_GEN_RCV_CRC_ERROR"; break;
+ case OID_GEN_TRANSMIT_QUEUE_LENGTH: pszOid = "OID_GEN_TRANSMIT_QUEUE_LENGTH"; break;
+ case OID_GEN_INIT_TIME_MS: pszOid = "OID_GEN_INIT_TIME_MS"; break;
+ case OID_GEN_RESET_COUNTS: pszOid = "OID_GEN_RESET_COUNTS"; break;
+ case OID_GEN_MEDIA_SENSE_COUNTS: pszOid = "OID_GEN_MEDIA_SENSE_COUNTS"; break;
+
+ case OID_PNP_CAPABILITIES: pszOid = "OID_PNP_CAPABILITIES"; break;
+ case OID_PNP_SET_POWER: pszOid = "OID_PNP_SET_POWER"; break;
+ case OID_PNP_QUERY_POWER: pszOid = "OID_PNP_QUERY_POWER"; break;
+ case OID_PNP_ADD_WAKE_UP_PATTERN: pszOid = "OID_PNP_ADD_WAKE_UP_PATTERN"; break;
+ case OID_PNP_REMOVE_WAKE_UP_PATTERN: pszOid = "OID_PNP_REMOVE_WAKE_UP_PATTERN"; break;
+ case OID_PNP_WAKE_UP_PATTERN_LIST: pszOid = "OID_PNP_WAKE_UP_PATTERN_LIST"; break;
+ case OID_PNP_ENABLE_WAKE_UP: pszOid = "OID_PNP_ENABLE_WAKE_UP"; break;
+ case OID_PNP_WAKE_UP_OK: pszOid = "OID_PNP_WAKE_UP_OK"; break;
+ case OID_PNP_WAKE_UP_ERROR: pszOid = "OID_PNP_WAKE_UP_ERROR"; break;
+ }
+ Log(("%s: %s(0x%x) %s(0x%x)\n", pcszFunction, pszType, pRequest->RequestType, pszOid, pRequest->DATA.SET_INFORMATION.Oid));
+# else
+ RT_NOREF2(pcszFunction, pRequest);
+# endif
+}
+
+#endif /* !VBOX_INCLUDED_VBoxNetCmn_win_h */
diff --git a/include/VBox/VBoxOGL.h b/include/VBox/VBoxOGL.h
new file mode 100644
index 00000000..df7e27dd
--- /dev/null
+++ b/include/VBox/VBoxOGL.h
@@ -0,0 +1,70 @@
+/* $Id: VBoxOGL.h $ */
+/** @file
+ * VBox 3D Support API
+ */
+/*
+ * Copyright (C) 2012-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_VBoxOGL_h
+#define VBOX_INCLUDED_VBoxOGL_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+
+RT_C_DECLS_BEGIN
+
+/* GUI and VBox OpenGL code require scaling factor value to be stored in container
+ * of type of 'double'. Communication between them is done via Main. In the same time,
+ * currently, Main does not like type of 'double' to be used for an interface method parameter.
+ * An integer type should be used instead. This value is used in order to specify scaling factor in type
+ * of 'integer' units. It is assumed that GUI feeds Main with its internal scaling factor value
+ * (which is originally of type of 'double') multiplied by this constant and converted resulting
+ * value to type of 'uint32_t'. Then Main provides this data to OpenGL HGCM thread. Finally, VBox OpenGL
+ * code divides received scalar by this constant and converts result to type of 'double'.
+ * This constant can be increased (multiplied by 10^n) in order to get better precision
+ * for scaling factor manipulations. */
+#define VBOX_OGL_SCALE_FACTOR_MULTIPLIER 10000.0
+
+/* 3D content scale factor range bounds. */
+#define VBOX_OGL_SCALE_FACTOR_MIN 0.01
+#define VBOX_OGL_SCALE_FACTOR_MAX 10.0
+
+bool RTCALL VBoxOglIsOfflineRenderingAppropriate(void);
+bool RTCALL VBoxOglIs3DAccelerationSupported(void);
+
+DECLEXPORT(int) VBoxOglSetScaleFactor(uint32_t idScreen, double dScaleFactorW, double dScaleFactorH);
+
+RT_C_DECLS_END
+
+#endif /* !VBOX_INCLUDED_VBoxOGL_h */
diff --git a/include/VBox/VBoxPktDmp.h b/include/VBox/VBoxPktDmp.h
new file mode 100644
index 00000000..ea6e3303
--- /dev/null
+++ b/include/VBox/VBoxPktDmp.h
@@ -0,0 +1,186 @@
+/* $Id: VBoxPktDmp.h $ */
+/** @file
+ * VBoxPktDmp.h - Dump Ethernet frame into debug log.
+ */
+
+/*
+ * Copyright (C) 2016-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_VBoxPktDmp_h
+#define VBOX_INCLUDED_VBoxPktDmp_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/net.h>
+#include <iprt/log.h>
+#if defined(LOG_ENABLED) && !defined(VBOX_DEVICE_STRUCT_TESTCASE)
+# include <iprt/asm.h>
+#endif
+
+
+DECLINLINE(const char *) vboxEthTypeStr(uint16_t uType)
+{
+ switch (uType)
+ {
+ case RTNET_ETHERTYPE_IPV4: return "IP";
+ case RTNET_ETHERTYPE_IPV6: return "IPv6";
+ case RTNET_ETHERTYPE_ARP: return "ARP";
+ }
+ return "unknown";
+}
+
+
+DECLINLINE(void) vboxEthPacketDump(const char *pcszInstance, const char *pcszText, const uint8_t *pcPacket, uint32_t cb)
+{
+#if defined(LOG_ENABLED) && !defined(VBOX_DEVICE_STRUCT_TESTCASE)
+ AssertReturnVoid(cb >= 14);
+
+ const uint8_t *pHdr = pcPacket;
+ const uint8_t *pEnd = pcPacket + cb;
+ AssertReturnVoid(pEnd - pHdr >= 14);
+ uint16_t uEthType = RT_N2H_U16(*(uint16_t*)(pHdr+12));
+ Log2(("%s: %s (%d bytes), %RTmac => %RTmac, EthType=%s(0x%x)\n", pcszInstance,
+ pcszText, cb, pHdr+6, pHdr, vboxEthTypeStr(uEthType), uEthType));
+ pHdr += sizeof(RTNETETHERHDR);
+ if (uEthType == RTNET_ETHERTYPE_VLAN)
+ {
+ AssertReturnVoid(pEnd - pHdr >= 4);
+ uEthType = RT_N2H_U16(*(uint16_t*)(pHdr+2));
+ Log2((" + VLAN: id=%d EthType=%s(0x%x)\n", RT_N2H_U16(*(uint16_t*)(pHdr)) & 0xFFF,
+ vboxEthTypeStr(uEthType), uEthType));
+ pHdr += 2 * sizeof(uint16_t);
+ }
+ uint8_t uProto = 0xFF;
+ switch (uEthType)
+ {
+ case RTNET_ETHERTYPE_IPV6:
+ AssertReturnVoid(pEnd - pHdr >= 40);
+ uProto = pHdr[6];
+ Log2((" + IPv6: %RTnaipv6 => %RTnaipv6\n", pHdr+8, pHdr+24));
+ pHdr += 40;
+ break;
+ case RTNET_ETHERTYPE_IPV4:
+ AssertReturnVoid(pEnd - pHdr >= 20);
+ uProto = pHdr[9];
+ Log2((" + IP: %RTnaipv4 => %RTnaipv4\n", *(uint32_t*)(pHdr+12), *(uint32_t*)(pHdr+16)));
+ pHdr += (pHdr[0] & 0xF) * 4;
+ break;
+ case RTNET_ETHERTYPE_ARP:
+ AssertReturnVoid(pEnd - pHdr >= 28);
+ AssertReturnVoid(RT_N2H_U16(*(uint16_t*)(pHdr+2)) == RTNET_ETHERTYPE_IPV4);
+ switch (RT_N2H_U16(*(uint16_t*)(pHdr+6)))
+ {
+ case 1: /* ARP request */
+ Log2((" + ARP-REQ: who-has %RTnaipv4 tell %RTnaipv4\n",
+ *(uint32_t*)(pHdr+24), *(uint32_t*)(pHdr+14)));
+ break;
+ case 2: /* ARP reply */
+ Log2((" + ARP-RPL: %RTnaipv4 is-at %RTmac\n",
+ *(uint32_t*)(pHdr+14), pHdr+8));
+ break;
+ default:
+ Log2((" + ARP: unknown op %d\n", RT_N2H_U16(*(uint16_t*)(pHdr+6))));
+ break;
+ }
+ break;
+ /* There is no default case as uProto is initialized with 0xFF */
+ }
+ while (uProto != 0xFF)
+ {
+ switch (uProto)
+ {
+ case 0: /* IPv6 Hop-by-Hop option*/
+ case 60: /* IPv6 Destination option*/
+ case 43: /* IPv6 Routing option */
+ case 44: /* IPv6 Fragment option */
+ Log2((" + IPv6 option (%d): <not implemented>\n", uProto));
+ uProto = pHdr[0];
+ pHdr += pHdr[1] * 8 + 8; /* Skip to the next extension/protocol */
+ break;
+ case 51: /* IPv6 IPsec AH */
+ Log2((" + IPv6 IPsec AH: <not implemented>\n"));
+ uProto = pHdr[0];
+ pHdr += (pHdr[1] + 2) * 4; /* Skip to the next extension/protocol */
+ break;
+ case 50: /* IPv6 IPsec ESP */
+ /* Cannot decode IPsec, fall through */
+ Log2((" + IPv6 IPsec ESP: <not implemented>\n"));
+ uProto = 0xFF;
+ break;
+ case 59: /* No Next Header */
+ Log2((" + IPv6 No Next Header\n"));
+ uProto = 0xFF;
+ break;
+ case 58: /* IPv6-ICMP */
+ switch (pHdr[0])
+ {
+ case 1: Log2((" + IPv6-ICMP: destination unreachable, code %d\n", pHdr[1])); break;
+ case 128: Log2((" + IPv6-ICMP: echo request\n")); break;
+ case 129: Log2((" + IPv6-ICMP: echo reply\n")); break;
+ default: Log2((" + IPv6-ICMP: unknown type %d, code %d\n", pHdr[0], pHdr[1])); break;
+ }
+ uProto = 0xFF;
+ break;
+ case 1: /* ICMP */
+ switch (pHdr[0])
+ {
+ case 0: Log2((" + ICMP: echo reply\n")); break;
+ case 8: Log2((" + ICMP: echo request\n")); break;
+ case 3: Log2((" + ICMP: destination unreachable, code %d\n", pHdr[1])); break;
+ default: Log2((" + ICMP: unknown type %d, code %d\n", pHdr[0], pHdr[1])); break;
+ }
+ uProto = 0xFF;
+ break;
+ case 6: /* TCP */
+ Log2((" + TCP: src=%d dst=%d seq=%x ack=%x\n",
+ RT_N2H_U16(*(uint16_t*)(pHdr)), RT_N2H_U16(*(uint16_t*)(pHdr+2)),
+ RT_N2H_U32(*(uint32_t*)(pHdr+4)), RT_N2H_U32(*(uint32_t*)(pHdr+8))));
+ uProto = 0xFF;
+ break;
+ case 17: /* UDP */
+ Log2((" + UDP: src=%d dst=%d\n",
+ RT_N2H_U16(*(uint16_t*)(pHdr)), RT_N2H_U16(*(uint16_t*)(pHdr+2))));
+ uProto = 0xFF;
+ break;
+ default:
+ Log2((" + Unknown: proto=0x%x\n", uProto));
+ uProto = 0xFF;
+ break;
+ }
+ }
+ Log3(("%.*Rhxd\n", cb, pcPacket));
+#else
+ RT_NOREF4(pcszInstance, pcszText, pcPacket, cb);
+#endif
+}
+
+#endif /* !VBOX_INCLUDED_VBoxPktDmp_h */
diff --git a/include/VBox/VBoxTpG.h b/include/VBox/VBoxTpG.h
new file mode 100644
index 00000000..0105ee52
--- /dev/null
+++ b/include/VBox/VBoxTpG.h
@@ -0,0 +1,455 @@
+/* $Id: VBoxTpG.h $ */
+/** @file
+ * VBox Tracepoint Generator Structures.
+ */
+
+/*
+ * Copyright (C) 2012-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_VBoxTpG_h
+#define VBOX_INCLUDED_VBoxTpG_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+#include <iprt/assert.h>
+
+RT_C_DECLS_BEGIN
+
+/**
+ * 32-bit probe location.
+ */
+typedef struct VTGPROBELOC32
+{
+ uint32_t uLine : 31;
+ uint32_t fEnabled : 1;
+ uint32_t idProbe;
+ uint32_t pszFunction;
+ uint32_t pProbe;
+} VTGPROBELOC32;
+AssertCompileSize(VTGPROBELOC32, 16);
+/** Pointer to a 32-bit probe location. */
+typedef VTGPROBELOC32 *PVTGPROBELOC32;
+/** Pointer to a const 32-bit probe location. */
+typedef VTGPROBELOC32 const *PCVTGPROBELOC32;
+
+/**
+ * 64-bit probe location.
+ */
+typedef struct VTGPROBELOC64
+{
+ uint32_t uLine : 31;
+ uint32_t fEnabled : 1;
+ uint32_t idProbe;
+ uint64_t pszFunction;
+ uint64_t pProbe;
+ uint64_t uAlignment;
+} VTGPROBELOC64;
+AssertCompileSize(VTGPROBELOC64, 32);
+/** Pointer to a 64-bit probe location. */
+typedef VTGPROBELOC64 *PVTGPROBELOC64;
+/** Pointer to a const 64-bit probe location. */
+typedef VTGPROBELOC64 const *PCVTGPROBELOC64;
+
+
+/**
+ * Probe location.
+ */
+typedef struct VTGPROBELOC
+{
+ uint32_t uLine : 31;
+ uint32_t fEnabled : 1;
+ uint32_t idProbe;
+ const char *pszFunction;
+ struct VTGDESCPROBE *pProbe;
+#if ARCH_BITS == 64
+ uintptr_t uAlignment;
+#endif
+} VTGPROBELOC;
+AssertCompileSizeAlignment(VTGPROBELOC, 16);
+/** Pointer to a probe location. */
+typedef VTGPROBELOC *PVTGPROBELOC;
+/** Pointer to a const probe location. */
+typedef VTGPROBELOC const *PCVTGPROBELOC;
+
+/** @def VTG_OBJ_SECT
+ * The name of the section containing the other probe data provided by the
+ * assembly / object generated by VBoxTpG. */
+/** @def VTG_LOC_SECT
+ * The name of the section containing the VTGPROBELOC structures. This is
+ * filled by the probe macros, @see VTG_DECL_VTGPROBELOC. */
+/** @def VTG_DECL_VTGPROBELOC
+ * Declares a static variable, @a a_VarName, of type VTGPROBELOC in the section
+ * indicated by VTG_LOC_SECT. */
+#if defined(RT_OS_WINDOWS)
+# define VTG_OBJ_SECT "VTGObj"
+# define VTG_LOC_SECT "VTGPrLc.Data"
+# ifdef _MSC_VER
+# define VTG_DECL_VTGPROBELOC(a_VarName) \
+ __declspec(allocate(VTG_LOC_SECT)) static VTGPROBELOC a_VarName
+# elif defined(__GNUC__) || defined(DOXYGEN_RUNNING)
+# define VTG_DECL_VTGPROBELOC(a_VarName) \
+ static VTGPROBELOC __attribute__((section(VTG_LOC_SECT))) a_VarName
+# else
+# error "Unsupported Windows compiler!"
+# endif
+
+#elif defined(RT_OS_DARWIN)
+# define VTG_OBJ_SECT "__VTGObj"
+# define VTG_LOC_SECT "__VTGPrLc"
+# define VTG_LOC_SEG "__VTG"
+# if defined(__GNUC__) || defined(DOXYGEN_RUNNING)
+# define VTG_DECL_VTGPROBELOC(a_VarName) \
+ static VTGPROBELOC __attribute__((section(VTG_LOC_SEG "," VTG_LOC_SECT ",regular")/*, aligned(16)*/)) a_VarName
+# else
+# error "Unsupported Darwin compiler!"
+# endif
+
+#elif defined(RT_OS_OS2) /** @todo This doesn't actually work, but it makes the code compile. */
+# define VTG_OBJ_SECT "__DATA"
+# define VTG_LOC_SECT "__VTGPrLc"
+# define VTG_LOC_SET "__VTGPrLcSet"
+# if defined(__GNUC__) || defined(DOXYGEN_RUNNING)
+# define VTG_DECL_VTGPROBELOC(a_VarName) \
+ static VTGPROBELOC a_VarName; \
+ __asm__ (".stabs \"__VTGPrLcSet\", 23, 0, 0, _" #a_VarName );
+
+# else
+# error "Unsupported Darwin compiler!"
+# endif
+
+#else /* Assume the rest uses ELF. */
+# define VTG_OBJ_SECT ".VTGObj"
+# define VTG_LOC_SECT ".VTGPrLc"
+# if defined(__GNUC__) || defined(DOXYGEN_RUNNING)
+# define VTG_DECL_VTGPROBELOC(a_VarName) \
+ static VTGPROBELOC __attribute__((section(VTG_LOC_SECT))) a_VarName
+# else
+# error "Unsupported compiler!"
+# endif
+#endif
+
+/** VTG string table offset. */
+typedef uint32_t VTGSTROFF;
+
+
+/** @name VTG type flags
+ * @{ */
+/** Masking out the fixed size if given. */
+#define VTG_TYPE_SIZE_MASK UINT32_C(0x000000ff)
+/** Indicates that VTG_TYPE_SIZE_MASK can be applied, UNSIGNED or SIGNED is
+ * usually set as well, so may PHYS. */
+#define VTG_TYPE_FIXED_SIZED RT_BIT_32(8)
+/** It's a pointer type, the size is given by the context the probe fired in. */
+#define VTG_TYPE_POINTER RT_BIT_32(9)
+/** A context specfic pointer or address, consult VTG_TYPE_CTX_XXX. */
+#define VTG_TYPE_CTX_POINTER RT_BIT_32(10)
+/** The type has the same size as the host architecture. */
+#define VTG_TYPE_HC_ARCH_SIZED RT_BIT_32(11)
+/** Const char pointer, requires casting in wrapper headers. */
+#define VTG_TYPE_CONST_CHAR_PTR RT_BIT_32(12)
+/** The type applies to ring-3 context. */
+#define VTG_TYPE_CTX_R3 RT_BIT_32(24)
+/** The type applies to ring-0 context. */
+#define VTG_TYPE_CTX_R0 RT_BIT_32(25)
+/** The type applies to raw-mode context. */
+#define VTG_TYPE_CTX_RC RT_BIT_32(26)
+/** The type applies to guest context. */
+#define VTG_TYPE_CTX_GST RT_BIT_32(27)
+/** The type context mask. */
+#define VTG_TYPE_CTX_MASK UINT32_C(0x0f000000)
+/** The type is automatically converted to a ring-0 pointer. */
+#define VTG_TYPE_AUTO_CONV_PTR RT_BIT_32(28)
+/** The type is a physical address. */
+#define VTG_TYPE_PHYS RT_BIT_32(29)
+/** The type is unsigned. */
+#define VTG_TYPE_UNSIGNED RT_BIT_32(30)
+/** The type is signed. */
+#define VTG_TYPE_SIGNED RT_BIT_32(31)
+/** Mask of valid bits (for simple validation). */
+#define VTG_TYPE_VALID_MASK UINT32_C(0xff001fff)
+/** @} */
+
+/**
+ * Checks if the VTG type flags indicates a large fixed size argument.
+ */
+#define VTG_TYPE_IS_LARGE(a_fType) \
+ ( ((a_fType) & VTG_TYPE_SIZE_MASK) > 4 && ((a_fType) & VTG_TYPE_FIXED_SIZED) )
+
+
+/**
+ * VTG argument descriptor.
+ */
+typedef struct VTGDESCARG
+{
+ VTGSTROFF offType;
+ uint32_t fType;
+} VTGDESCARG;
+/** Pointer to an argument descriptor. */
+typedef VTGDESCARG *PVTGDESCARG;
+/** Pointer to a const argument descriptor. */
+typedef VTGDESCARG const *PCVTGDESCARG;
+
+
+/**
+ * VTG argument list descriptor.
+ */
+typedef struct VTGDESCARGLIST
+{
+ uint8_t cArgs;
+ uint8_t fHaveLargeArgs;
+ uint8_t abReserved[2];
+ VTGDESCARG aArgs[1];
+} VTGDESCARGLIST;
+/** Pointer to a VTG argument list descriptor. */
+typedef VTGDESCARGLIST *PVTGDESCARGLIST;
+/** Pointer to a const VTG argument list descriptor. */
+typedef VTGDESCARGLIST const *PCVTGDESCARGLIST;
+
+
+/**
+ * VTG probe descriptor.
+ */
+typedef struct VTGDESCPROBE
+{
+ VTGSTROFF offName;
+ uint32_t offArgList;
+ uint16_t idxEnabled;
+ uint16_t idxProvider;
+ /** The distance from this structure to the VTG object header. */
+ int32_t offObjHdr;
+} VTGDESCPROBE;
+AssertCompileSize(VTGDESCPROBE, 16);
+/** Pointer to a VTG probe descriptor. */
+typedef VTGDESCPROBE *PVTGDESCPROBE;
+/** Pointer to a const VTG probe descriptor. */
+typedef VTGDESCPROBE const *PCVTGDESCPROBE;
+
+
+/**
+ * Code/data stability.
+ */
+typedef enum kVTGStability
+{
+ kVTGStability_Invalid = 0,
+ kVTGStability_Internal,
+ kVTGStability_Private,
+ kVTGStability_Obsolete,
+ kVTGStability_External,
+ kVTGStability_Unstable,
+ kVTGStability_Evolving,
+ kVTGStability_Stable,
+ kVTGStability_Standard,
+ kVTGStability_End
+} kVTGStability;
+
+/**
+ * Data dependency.
+ */
+typedef enum kVTGClass
+{
+ kVTGClass_Invalid = 0,
+ kVTGClass_Unknown,
+ kVTGClass_Cpu,
+ kVTGClass_Platform,
+ kVTGClass_Group,
+ kVTGClass_Isa,
+ kVTGClass_Common,
+ kVTGClass_End
+} kVTGClass;
+
+
+/**
+ * VTG attributes.
+ */
+typedef struct VTGDESCATTR
+{
+ uint8_t u8Code;
+ uint8_t u8Data;
+ uint8_t u8DataDep;
+} VTGDESCATTR;
+AssertCompileSize(VTGDESCATTR, 3);
+/** Pointer to a const VTG attribute. */
+typedef VTGDESCATTR const *PCVTGDESCATTR;
+
+
+/**
+ * VTG provider descriptor.
+ */
+typedef struct VTGDESCPROVIDER
+{
+ VTGSTROFF offName;
+ uint16_t iFirstProbe;
+ uint16_t cProbes;
+ VTGDESCATTR AttrSelf;
+ VTGDESCATTR AttrModules;
+ VTGDESCATTR AttrFunctions;
+ VTGDESCATTR AttrNames;
+ VTGDESCATTR AttrArguments;
+ uint8_t bReserved;
+ uint32_t volatile cProbesEnabled;
+ /** This increases every time a probe is enabled or disabled.
+ * Can be used in non-ring-3 context via PROVIDER_GET_SETTINGS_SEQ_NO() in
+ * order to only configure probes related stuff when actually required. */
+ uint32_t volatile uSettingsSerialNo;
+} VTGDESCPROVIDER;
+AssertCompileSize(VTGDESCPROVIDER, 32);
+/** Pointer to a VTG provider descriptor. */
+typedef VTGDESCPROVIDER *PVTGDESCPROVIDER;
+/** Pointer to a const VTG provider descriptor. */
+typedef VTGDESCPROVIDER const *PCVTGDESCPROVIDER;
+
+
+/**
+ * VTG data object header.
+ */
+typedef struct VTGOBJHDR
+{
+ /** Magic value (VTGOBJHDR_MAGIC). */
+ char szMagic[24];
+ /** The bitness of the structures.
+ * This only affects the probe location pointers and structures. */
+ uint32_t cBits;
+ /** The size of the VTG object. This excludes the probe locations. */
+ uint32_t cbObj;
+
+ /** @name Area Descriptors
+ * @remarks The offsets are relative to the header. The members are
+ * ordered by ascending offset (maybe with the exception of the
+ * probe locations). No overlaps, though there might be zero
+ * filled gaps between them due to alignment.
+ * @{ */
+ /* 32: */
+ /** Offset of the string table (char) relative to this header. */
+ uint32_t offStrTab;
+ /** The size of the string table, in bytes. */
+ uint32_t cbStrTab;
+ /** Offset of the argument lists (VTGDESCARGLIST - variable size) relative
+ * to this header. */
+ uint32_t offArgLists;
+ /** The size of the argument lists, in bytes. */
+ uint32_t cbArgLists;
+ /* 48: */
+ /** Offset of the probe array (VTGDESCPROBE) relative to this header. */
+ uint32_t offProbes;
+ /** The size of the probe array, in bytes. */
+ uint32_t cbProbes;
+ /** Offset of the provider array (VTGDESCPROVIDER) relative to this
+ * header. */
+ uint32_t offProviders;
+ /** The size of the provider array, in bytes. */
+ uint32_t cbProviders;
+ /* 64: */
+ /** Offset of the probe-enabled array (uint32_t) relative to this
+ * header. */
+ uint32_t offProbeEnabled;
+ /** The size of the probe-enabled array, in bytes. */
+ uint32_t cbProbeEnabled;
+ /** Offset of the probe location array (VTGPROBELOC) relative to this
+ * header.
+ * @remarks This is filled in by the first VTG user using uProbeLocs. */
+ int32_t offProbeLocs;
+ /** The size of the probe location array, in bytes.
+ * @remarks This is filled in by the first VTG user using uProbeLocs. */
+ uint32_t cbProbeLocs;
+ /** @} */
+ /* 80: */
+ /**
+ * The probe location array is generated by C code and lives in a
+ * different section/subsection/segment than the rest of the data.
+ *
+ * The assembler cannot generate offsets across sections for most (if not
+ * all) object formats, so we have to store pointers here. The first user
+ * of the data will convert these two members into offset and size and fill
+ * in the offProbeLocs and cbProbeLocs members above.
+ *
+ * @remarks Converting these members to offset+size and reusing the members
+ * to store the converted values isn't possible because of
+ * raw-mode context modules having relocations associated with the
+ * fields.
+ */
+ union
+ {
+ PVTGPROBELOC p;
+ uintptr_t uPtr;
+ uint32_t u32;
+ uint64_t u64;
+ }
+ /** Pointer to the probe location array. */
+ uProbeLocs,
+ /** Pointer to the end of the probe location array. */
+ uProbeLocsEnd;
+ /** UUID for making sharing ring-0 structures for the same ring-3
+ * modules easier. */
+ RTUUID Uuid;
+ /** Mac 10.6.x load workaround.
+ * The linker or/and load messes up the uProbeLocs and uProbeLocsEnd fields
+ * so that they will be link addresses instead of load addresses. To be
+ * able to work around it we store the start address of the __VTGObj section
+ * here and uses it to validate the probe location addresses. */
+ uint64_t u64VtgObjSectionStart;
+ /** Reserved / alignment. */
+ uint32_t au32Reserved1[2];
+} VTGOBJHDR;
+AssertCompileSize(VTGOBJHDR, 128);
+AssertCompileMemberAlignment(VTGOBJHDR, uProbeLocs, 8);
+AssertCompileMemberAlignment(VTGOBJHDR, uProbeLocsEnd, 8);
+/** Pointer to a VTG data object header. */
+typedef VTGOBJHDR *PVTGOBJHDR;
+/** Pointer to a const VTG data object header. */
+typedef VTGOBJHDR const *PCVTGOBJHDR;
+
+/** The current VTGOBJHDR::szMagic value. */
+#define VTGOBJHDR_MAGIC "VTG Object Header v1.7\0"
+
+/** The name of the VTG data object header symbol in the object file. */
+extern VTGOBJHDR g_VTGObjHeader;
+
+
+/** @name Macros for converting typical pointer arguments to ring-0 pointers.
+ * @{ */
+#ifdef IN_RING0
+# define VTG_VM_TO_R0(a_pVM) (a_pVM)
+# define VTG_VMCPU_TO_R0(a_pVCpu) (a_pVCpu)
+# define VTG_CPUMCTX_TO_R0(a_pVCpu, a_pCtx) (a_pCtx)
+#else
+# define VTG_VM_TO_R0(a_pVM) ((a_pVM) ? (a_pVM)->pVMR0ForCall : NIL_RTR0PTR)
+# define VTG_VMCPU_TO_R0(a_pVCpu) ((a_pVCpu) ? (a_pVCpu)->pVCpuR0ForVtg : NIL_RTR0PTR)
+# define VTG_CPUMCTX_TO_R0(a_pVCpu, a_pCtx) ((a_pVCpu) ? (a_pVCpu)->pVCpuR0ForVtg + ((uintptr_t)(a_pCtx) - (uintptr_t)(a_pVCpu)) : NIL_RTR0PTR)
+#endif
+/** @} */
+
+
+RT_C_DECLS_END
+
+#endif /* !VBOX_INCLUDED_VBoxTpG_h */
+
diff --git a/include/VBox/VDEPlug.h b/include/VBox/VDEPlug.h
new file mode 100644
index 00000000..4463d4fe
--- /dev/null
+++ b/include/VBox/VDEPlug.h
@@ -0,0 +1,74 @@
+/** @file
+ * libvdeplug header and dynamic symbol loader.
+ */
+
+/*
+ * Copyright (C) 2008-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_VDEPlug_h
+#define VBOX_INCLUDED_VDEPlug_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <stddef.h>
+#include <sys/types.h>
+
+#define LIBVDEPLUG_INTERFACE_VERSION 1
+
+#define vde_open(vde_switch, descr, open_args) \
+ vde_open_real((vde_switch), (descr), LIBVDEPLUG_INTERFACE_VERSION, (open_args))
+
+/** Opaque connection type */
+struct vdeconn;
+typedef struct vdeconn VDECONN;
+
+/** Structure to be passed to the open function describing the connection.
+ * All members can be left zero to use the default values. */
+struct vde_open_args
+{
+ /** The port of the switch to connect to. */
+ int port;
+ /** The group to set ownership of the port socket to. */
+ char *group;
+ /** The file mode to set the port socket to. */
+ mode_t mode;
+};
+
+/* Declarations of the functions that we need from the library */
+#define VDEPLUG_GENERATE_HEADER
+
+#include <VBox/VDEPlugSymDefs.h>
+
+#undef VDEPLUG_GENERATE_HEADER
+
+#endif /* !VBOX_INCLUDED_VDEPlug_h */
+/* vi: set tabstop=4 shiftwidth=4 expandtab: */
diff --git a/include/VBox/VDEPlugSymDefs.h b/include/VBox/VDEPlugSymDefs.h
new file mode 100644
index 00000000..beaa73cc
--- /dev/null
+++ b/include/VBox/VDEPlugSymDefs.h
@@ -0,0 +1,73 @@
+/** @file
+ * Symbols from libvdeplug.so to be loaded at runtime for DrvVDE.cpp
+ */
+
+/*
+ * Copyright (C) 2008-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+/** The file name of the DBus library */
+#define VBOX_LIB_VDE_PLUG_NAME "libvdeplug.so"
+#define RT_RUNTIME_LOADER_LIB_NAME VBOX_LIB_VDE_PLUG_NAME
+
+/** The name of the loader function */
+#define RT_RUNTIME_LOADER_FUNCTION DrvVDELoadVDEPlug
+
+/** The following are the symbols which we need from the library. */
+#define RT_RUNTIME_LOADER_INSERT_SYMBOLS \
+ RT_PROXY_STUB(vde_open_real, VDECONN *, \
+ (const char *vde_switch, const char *descr, int interface_version, struct vde_open_args *open_args), \
+ (vde_switch, descr, interface_version, open_args)) \
+ RT_PROXY_STUB(vde_recv, size_t, \
+ (VDECONN *conn, void *buf,size_t len, int flags), \
+ (conn, buf, len, flags)) \
+ RT_PROXY_STUB(vde_send, size_t, \
+ (VDECONN *conn, const void *buf, size_t len, int flags), \
+ (conn, buf, len, flags)) \
+ RT_PROXY_STUB(vde_datafd, int, (VDECONN *conn), (conn)) \
+ RT_PROXY_STUB(vde_close, void, (VDECONN *conn), (conn))
+
+#ifdef VDEPLUG_GENERATE_HEADER
+# define RT_RUNTIME_LOADER_GENERATE_HEADER
+# define RT_RUNTIME_LOADER_GENERATE_DECLS
+# include <iprt/runtime-loader.h>
+# undef RT_RUNTIME_LOADER_GENERATE_HEADER
+# undef RT_RUNTIME_LOADER_GENERATE_DECLS
+#elif defined (VDEPLUG_GENERATE_BODY)
+# define RT_RUNTIME_LOADER_GENERATE_BODY_STUBS
+# include <iprt/runtime-loader.h>
+# undef RT_RUNTIME_LOADER_GENERATE_BODY_STUBS
+#else
+# error This file should only be included to generate stubs for loading the libvdeplug library at runtime
+#endif
+
+#undef RT_RUNTIME_LOADER_LIB_NAME
+#undef RT_RUNTIME_LOADER_INSERT_SYMBOLS
+
diff --git a/include/VBox/VMMDev.h b/include/VBox/VMMDev.h
new file mode 100644
index 00000000..69618cce
--- /dev/null
+++ b/include/VBox/VMMDev.h
@@ -0,0 +1,2034 @@
+/** @file
+ * Virtual Device for Guest <-> VMM/Host communication (ADD,DEV).
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef VBOX_INCLUDED_VMMDev_h
+#define VBOX_INCLUDED_VMMDev_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/cdefs.h>
+#include <VBox/param.h> /* for the PCI IDs. */
+#include <VBox/types.h>
+#include <VBox/ostypes.h>
+#include <VBox/VMMDevCoreTypes.h>
+#include <iprt/assertcompile.h>
+#include <iprt/errcore.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
+/** Port for requests that can be handled w/o going to ring-3 (relative offset).
+ * This works like VMMDevReq_AcknowledgeEvents when read. */
+#define VMMDEV_PORT_OFF_REQUEST_FAST 8
+
+
+/** @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.
+ * @note This used to be 1024, which is kind of insane. Was changed to 32,
+ * given that (guest) user land can only pass 61 anyway.
+ * See comments on VBGLIOCHGCMCALL::cParms. */
+#define VMMDEV_MAX_HGCM_PARMS 32
+/** Maximum total size of hgcm buffers in one call.
+ * @note Used to be 2G, since reduced to 128MB. */
+#define VMMDEV_MAX_HGCM_DATA_SIZE _128M
+
+/**
+ * VMMDev request types.
+ * @note when updating this, adjust vmmdevGetRequestSize() as well
+ */
+typedef enum VMMDevRequestType
+{
+ 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 */
+ VMMDevReq_GetDisplayChangeRequestMulti = 81,
+#ifdef VBOX_WITH_HGCM
+ VMMDevReq_HGCMConnect = 60,
+ VMMDevReq_HGCMDisconnect = 61,
+ VMMDevReq_HGCMCall32 = 62,
+ VMMDevReq_HGCMCall64 = 63,
+# ifdef IN_GUEST
+# if ARCH_BITS == 64
+ VMMDevReq_HGCMCall = VMMDevReq_HGCMCall64,
+# elif ARCH_BITS == 32 || ARCH_BITS == 16
+ VMMDevReq_HGCMCall = VMMDevReq_HGCMCall32,
+# else
+# error "Unsupported ARCH_BITS"
+# endif
+# endif
+ 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_NtBugCheck = 221,
+ VMMDevReq_VideoUpdateMonitorPositions= 222,
+ VMMDevReq_GetMouseStatusEx = 223,
+ VMMDevReq_SizeHack = 0x7fffffff
+} VMMDevRequestType;
+
+/** Version of VMMDevRequestHeader structure. */
+#define VMMDEV_REQUEST_HEADER_VERSION (0x10001)
+
+
+/**
+ * Generic VMMDev request header.
+ *
+ * This structure is copied/mirrored by VBGLREQHDR in the VBoxGuest I/O control
+ * interface. Changes there needs to be mirrored in it.
+ *
+ * @sa VBGLREQHDR
+ */
+typedef struct VMMDevRequestHeader
+{
+ /** IN: Size of the structure in bytes (including body).
+ * (VBGLREQHDR uses this for input size and output if reserved1 is zero). */
+ uint32_t size;
+ /** IN: Version of the structure. */
+ uint32_t version;
+ /** IN: Type of the request.
+ * @note VBGLREQHDR uses this for optional output size. */
+ VMMDevRequestType requestType;
+ /** OUT: VBox status code. */
+ int32_t rc;
+ /** Reserved field no.1. MBZ.
+ * @note VBGLREQHDR uses this for optional output size, however never for a
+ * real VMMDev request, only in the I/O control interface. */
+ uint32_t reserved1;
+ /** IN: Requestor information (VMMDEV_REQUESTOR_XXX) when
+ * VBOXGSTINFO2_F_REQUESTOR_INFO is set, otherwise ignored by the host. */
+ uint32_t fRequestor;
+} VMMDevRequestHeader;
+AssertCompileSize(VMMDevRequestHeader, 24);
+
+/** @name VMMDEV_REQUESTOR_XXX - Requestor information.
+ *
+ * This is information provided to the host by the VBoxGuest device driver, so
+ * the host can implemented fine grained access to functionality if it likes.
+ * @bugref{9105}
+ *
+ * @{ */
+/** Requestor user not given. */
+#define VMMDEV_REQUESTOR_USR_NOT_GIVEN UINT32_C(0x00000000)
+/** The kernel driver (VBoxGuest) is the requestor. */
+#define VMMDEV_REQUESTOR_USR_DRV UINT32_C(0x00000001)
+/** Some other kernel driver is the requestor. */
+#define VMMDEV_REQUESTOR_USR_DRV_OTHER UINT32_C(0x00000002)
+/** The root or a admin user is the requestor. */
+#define VMMDEV_REQUESTOR_USR_ROOT UINT32_C(0x00000003)
+/** Requestor is the windows system user (SID S-1-5-18). */
+#define VMMDEV_REQUESTOR_USR_SYSTEM UINT32_C(0x00000004)
+/** Reserved requestor user \#1, treat like VMMDEV_REQUESTOR_USR_USER. */
+#define VMMDEV_REQUESTOR_USR_RESERVED1 UINT32_C(0x00000005)
+/** Regular joe user is making the request. */
+#define VMMDEV_REQUESTOR_USR_USER UINT32_C(0x00000006)
+/** Requestor is a guest user (or in a guest user group). */
+#define VMMDEV_REQUESTOR_USR_GUEST UINT32_C(0x00000007)
+/** User classification mask. */
+#define VMMDEV_REQUESTOR_USR_MASK UINT32_C(0x00000007)
+
+/** Kernel mode request.
+ * @note This is zero, so test for VMMDEV_REQUESTOR_USERMODE instead. */
+#define VMMDEV_REQUESTOR_KERNEL UINT32_C(0x00000000)
+/** User mode request. */
+#define VMMDEV_REQUESTOR_USERMODE UINT32_C(0x00000008)
+
+/** Don't know the physical console association of the requestor. */
+#define VMMDEV_REQUESTOR_CON_DONT_KNOW UINT32_C(0x00000000)
+/** The request originates with a process that is NOT associated with the
+ * physical console. */
+#define VMMDEV_REQUESTOR_CON_NO UINT32_C(0x00000010)
+/** Requestor process DOES is associated with the physical console. */
+#define VMMDEV_REQUESTOR_CON_YES UINT32_C(0x00000020)
+/** Requestor process belongs to user on the physical console, but cannot
+ * ascertain that it is associated with that login. */
+#define VMMDEV_REQUESTOR_CON_USER UINT32_C(0x00000030)
+/** Mask the physical console state of the request. */
+#define VMMDEV_REQUESTOR_CON_MASK UINT32_C(0x00000030)
+
+/** Requestor is member of special VirtualBox user group (not on windows). */
+#define VMMDEV_REQUESTOR_GRP_VBOX UINT32_C(0x00000080)
+/** Requestor is member of wheel / administrators group (SID S-1-5-32-544). */
+#define VMMDEV_REQUESTOR_GRP_WHEEL UINT32_C(0x00000100)
+
+/** Requestor trust level: Unspecified */
+#define VMMDEV_REQUESTOR_TRUST_NOT_GIVEN UINT32_C(0x00000000)
+/** Requestor trust level: Untrusted (SID S-1-16-0) */
+#define VMMDEV_REQUESTOR_TRUST_UNTRUSTED UINT32_C(0x00001000)
+/** Requestor trust level: Untrusted (SID S-1-16-4096) */
+#define VMMDEV_REQUESTOR_TRUST_LOW UINT32_C(0x00002000)
+/** Requestor trust level: Medium (SID S-1-16-8192) */
+#define VMMDEV_REQUESTOR_TRUST_MEDIUM UINT32_C(0x00003000)
+/** Requestor trust level: Medium plus (SID S-1-16-8448) */
+#define VMMDEV_REQUESTOR_TRUST_MEDIUM_PLUS UINT32_C(0x00004000)
+/** Requestor trust level: High (SID S-1-16-12288) */
+#define VMMDEV_REQUESTOR_TRUST_HIGH UINT32_C(0x00005000)
+/** Requestor trust level: System (SID S-1-16-16384) */
+#define VMMDEV_REQUESTOR_TRUST_SYSTEM UINT32_C(0x00006000)
+/** Requestor trust level: Protected or higher (SID S-1-16-20480, S-1-16-28672)
+ * @note To avoid wasting an unnecessary bit, we combine the two top most
+ * mandatory security labels on Windows (protected and secure). */
+#define VMMDEV_REQUESTOR_TRUST_PROTECTED UINT32_C(0x00007000)
+/** Requestor trust level mask.
+ * The higher the value, the more the guest trusts the process. */
+#define VMMDEV_REQUESTOR_TRUST_MASK UINT32_C(0x00007000)
+
+/** Requestor is using the less trusted user device node (/dev/vboxuser). */
+#define VMMDEV_REQUESTOR_USER_DEVICE UINT32_C(0x00008000)
+/** There is no user device node (/dev/vboxuser). */
+#define VMMDEV_REQUESTOR_NO_USER_DEVICE UINT32_C(0x00010000)
+
+/** Legacy value for when VBOXGSTINFO2_F_REQUESTOR_INFO is clear.
+ * @internal Host only. */
+#define VMMDEV_REQUESTOR_LEGACY UINT32_MAX
+/** Lowest conceivable trust level, for error situations of getters.
+ * @internal Host only. */
+#define VMMDEV_REQUESTOR_LOWEST ( VMMDEV_REQUESTOR_TRUST_UNTRUSTED | VMMDEV_REQUESTOR_USER_DEVICE \
+ | VMMDEV_REQUESTOR_CON_NO | VMMDEV_REQUESTOR_USERMODE \
+ | VMMDEV_REQUESTOR_USR_GUEST)
+/** Used on the host to check whether a requestor value is present or not. */
+#define VMMDEV_REQUESTOR_IS_PRESENT(a_fRequestor) ((a_fRequestor) != VMMDEV_REQUESTOR_LEGACY)
+/** @} */
+
+/** Initialize a VMMDevRequestHeader structure.
+ * Same as VBGLREQHDR_INIT_VMMDEV(). */
+#define VMMDEV_REQ_HDR_INIT(a_pHdr, a_cb, a_enmType) \
+ do { \
+ (a_pHdr)->size = (a_cb); \
+ (a_pHdr)->version = VMMDEV_REQUEST_HEADER_VERSION; \
+ (a_pHdr)->requestType = (a_enmType); \
+ (a_pHdr)->rc = VERR_INTERNAL_ERROR; \
+ (a_pHdr)->reserved1 = 0; \
+ (a_pHdr)->fRequestor = 0; \
+ } while (0)
+
+
+/**
+ * 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 buttons state bits for VMMDevReqMouseStatusEx::fButtons (identical to PDMIMOUSEPORT_BUTTON_XXX).
+ * @{ */
+/** Left mouse button pressed. */
+#define VMMDEV_MOUSE_BUTTON_LEFT RT_BIT(0)
+/** Right mouse button pressed. */
+#define VMMDEV_MOUSE_BUTTON_RIGHT RT_BIT(1)
+/** Middle mouse button pressed. */
+#define VMMDEV_MOUSE_BUTTON_MIDDLE RT_BIT(2)
+/** X1 mouse button pressed. */
+#define VMMDEV_MOUSE_BUTTON_X1 RT_BIT(3)
+/** X2 mouse button pressed. */
+#define VMMDEV_MOUSE_BUTTON_X2 RT_BIT(4)
+/** @} */
+
+
+/**
+ * Extended mouse status request structure.
+ *
+ * Used by VMMDevReq_GetMouseStatusEx.
+ */
+typedef struct
+{
+ /** Legacy mouse status request structure. */
+ VMMDevReqMouseStatus Core;
+ /** Mouse wheel vertical mvement. */
+ int32_t dz;
+ /** Mouse wheel horizontal movement. */
+ int32_t dw;
+ /** Mouse buttons state. */
+ uint32_t fButtons;
+} VMMDevReqMouseStatusEx;
+AssertCompileSize(VMMDevReqMouseStatusEx, 24+24);
+
+
+/** @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 guest can read VMMDev events to find out about full mouse state */
+#define VMMDEV_MOUSE_GUEST_USES_FULL_STATE_PROTOCOL RT_BIT(7)
+/** The host can provide full mouse state over VMMDev events */
+#define VMMDEV_MOUSE_HOST_USES_FULL_STATE_PROTOCOL RT_BIT(8)
+/** The mask of all VMMDEV_MOUSE_* flags */
+#define VMMDEV_MOUSE_MASK UINT32_C(0x000001ff)
+/** 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 | VMMDEV_MOUSE_GUEST_USES_FULL_STATE_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 \
+ | VMMDEV_MOUSE_HOST_USES_FULL_STATE_PROTOCOL)
+/** @} */
+
+/** @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 from VBox/Graphics/VBoxVideo.h. */
+ 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_UOFFSETOF(VMMDevReqMousePointer, pointerData[0]);
+ size_t cbMask = (width + 7) / 8 * height;
+ size_t cbArgb = width * height * 4;
+ return RT_MAX(cbBase + ((cbMask + 3) & ~(size_t)3) + cbArgb,
+ sizeof(VMMDevReqMousePointer));
+}
+
+
+/**
+ * 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 VMMDEV_HVF_XXX - VMMDevReqHostVersion::features
+ * @{ */
+/** Physical page lists are supported by HGCM. */
+#define VMMDEV_HVF_HGCM_PHYS_PAGE_LIST RT_BIT_32(0)
+/** HGCM supports the embedded buffer parameter type. */
+#define VMMDEV_HVF_HGCM_EMBEDDED_BUFFERS RT_BIT_32(1)
+/** HGCM supports the contiguous page list parameter type. */
+#define VMMDEV_HVF_HGCM_CONTIGUOUS_PAGE_LIST RT_BIT_32(2)
+/** HGCM supports the no-bounce page list parameter type. */
+#define VMMDEV_HVF_HGCM_NO_BOUNCE_PAGE_LIST RT_BIT_32(3)
+/** VMMDev supports fast IRQ acknowledgements. */
+#define VMMDEV_HVF_FAST_IRQ_ACK RT_BIT_32(31)
+/** @} */
+
+
+/**
+ * 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);
+
+
+/**
+ * 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, VBOXGSTINFO2_F_XXX. */
+ 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);
+
+/** @name VBOXGSTINFO2_F_XXX - Features
+ * @{ */
+/** Request header carries requestor information. */
+#define VBOXGSTINFO2_F_REQUESTOR_INFO RT_BIT_32(0)
+/** @} */
+
+
+/**
+ * Guest information report, version 2.
+ *
+ * Used by VMMDevReq_ReportGuestInfo2.
+ */
+typedef struct
+{
+ /** Header. */
+ VMMDevRequestHeader header;
+ /** Guest information. */
+ VBoxGuestInfo2 guestInfo;
+} VMMDevReportGuestInfo2;
+AssertCompileSize(VMMDevReportGuestInfo2, 24+144);
+
+
+/**
+ * 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);
+
+
+/**
+ * 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);
+
+
+/**
+ * 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);
+
+
+/** Flags for VMMDevDisplayDef::fDisplayFlags */
+#define VMMDEV_DISPLAY_PRIMARY UINT32_C(0x00000001) /**< Primary display. */
+#define VMMDEV_DISPLAY_DISABLED UINT32_C(0x00000002) /**< Display is disabled. */
+#define VMMDEV_DISPLAY_ORIGIN UINT32_C(0x00000004) /**< Change position of the diplay. */
+#define VMMDEV_DISPLAY_CX UINT32_C(0x00000008) /**< Change the horizontal resolution of the display. */
+#define VMMDEV_DISPLAY_CY UINT32_C(0x00000010) /**< Change the vertical resolution of the display. */
+#define VMMDEV_DISPLAY_BPP UINT32_C(0x00000020) /**< Change the color depth of the display. */
+
+/** Definition of one monitor. Used by VMMDevReq_GetDisplayChangeRequestMulti. */
+typedef struct VMMDevDisplayDef
+{
+ uint32_t fDisplayFlags; /**< VMMDEV_DISPLAY_* flags. */
+ uint32_t idDisplay; /**< The display number. */
+ int32_t xOrigin; /**< New OriginX of the guest screen. */
+ int32_t yOrigin; /**< New OriginY of the guest screen. */
+ uint32_t cx; /**< Horizontal pixel resolution. */
+ uint32_t cy; /**< Vertical pixel resolution. */
+ uint32_t cBitsPerPixel; /**< Bits per pixel. */
+} VMMDevDisplayDef;
+AssertCompileSize(VMMDevDisplayDef, 28);
+
+/** Multimonitor display change request structure. Used by VMMDevReq_GetDisplayChangeRequestMulti. */
+typedef struct VMMDevDisplayChangeRequestMulti
+{
+ VMMDevRequestHeader header; /**< Header. */
+ uint32_t eventAck; /**< 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 cDisplays; /**< Number of monitors. In: how many the guest expects.
+ * Out: how many the host provided. */
+ VMMDevDisplayDef aDisplays[1]; /**< Layout of monitors. */
+} VMMDevDisplayChangeRequestMulti;
+AssertCompileSize(VMMDevDisplayChangeRequestMulti, 24+8+28);
+
+
+/**
+ * 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);
+
+/**
+ * VBVA monitor positions update request structure.
+ *
+ * Used by VMMDevReq_VideoUpdateMonitorPositions.
+ */
+typedef struct
+{
+ /** Header. */
+ VMMDevRequestHeader header;
+ /** Number of monitor positions (monitors) */
+ uint32_t cPositions;
+ /** Positions array.*/
+ RTPOINT aPositions[1];
+} VMMDevVideoUpdateMonitorPositions;
+AssertCompileSize(RTPOINT, 8);
+AssertCompileSize(VMMDevVideoUpdateMonitorPositions, 24+4+8);
+
+/**
+ * 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);
+
+
+AssertCompileSize(VMMDEVSHAREDREGIONDESC, 16); /* structure was promoted to VBox/types.h. */
+
+#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);
+
+
+/**
+ * NT bug check report.
+ * Used by VMMDevReq_NtBugCheck.
+ * @remarks Can be issued with just the header if no more data is available.
+ */
+typedef struct
+{
+ /** Header. */
+ VMMDevRequestHeader header;
+ /** The bug check number (P0). */
+ uint64_t uBugCheck;
+ /** The four bug check parameters. */
+ uint64_t auParameters[4];
+} VMMDevReqNtBugCheck;
+AssertCompileSize(VMMDevReqNtBugCheck, 24+40);
+
+
+
+#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 call request structure.
+ *
+ * Used by 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)
+#define VBOX_HGCM_F_PARM_DIRECTION_MASK 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_MASK) \
+ && !((fFlags) & ~VBOX_HGCM_F_PARM_DIRECTION_MASK) )
+/** @} */
+
+/**
+ * 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_GetMouseStatusEx:
+ return sizeof(VMMDevReqMouseStatusEx);
+ 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_GetDisplayChangeRequestMulti:
+ return RT_UOFFSETOF(VMMDevDisplayChangeRequestMulti, aDisplays[0]);
+ 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);
+ case VMMDevReq_HGCMCall32:
+ return sizeof(VMMDevHGCMCall);
+# ifdef VBOX_WITH_64_BITS_GUESTS
+ case VMMDevReq_HGCMCall64:
+ return sizeof(VMMDevHGCMCall);
+# endif
+ 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);
+ case VMMDevReq_VideoUpdateMonitorPositions:
+ return sizeof(VMMDevVideoUpdateMonitorPositions);
+ 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->fRequestor = 0;
+ return VINF_SUCCESS;
+}
+
+
+/** @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 VMMDEV_VBVA_RING_BUFFER_SIZE (_4M - _1K)
+#define VMMDEV_VBVA_RING_BUFFER_THRESHOLD (4 * _1K)
+
+#define VMMDEV_VBVA_MAX_RECORDS (64)
+/** @} */
+
+/**
+ * VBVA record.
+ */
+typedef struct VMMDEVVBVARECORD
+{
+ /** The length of the record. Changed by guest. */
+ uint32_t cbRecord;
+} VMMDEVVBVARECORD;
+AssertCompileSize(VMMDEVVBVARECORD, 4);
+
+#if ARCH_BITS >= 32
+
+/**
+ * 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[VMMDEV_VBVA_RING_BUFFER_SIZE];
+
+ /** The queue of record descriptions. */
+ VMMDEVVBVARECORD aRecords[VMMDEV_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)
+
+#endif /* ARCH_BITS >= 32 */
+
+/** @} */
+
+/** @} */
+RT_C_DECLS_END
+#pragma pack()
+
+#endif /* !VBOX_INCLUDED_VMMDev_h */
diff --git a/include/VBox/VMMDevCoreTypes.h b/include/VBox/VMMDevCoreTypes.h
new file mode 100644
index 00000000..e1d8aef3
--- /dev/null
+++ b/include/VBox/VMMDevCoreTypes.h
@@ -0,0 +1,556 @@
+/** @file
+ * Virtual Device for Guest <-> VMM/Host communication, Core Types. (ADD,DEV)
+ *
+ * These types are needed by several headers VBoxGuestLib.h and are kept
+ * separate to avoid having to include the whole VMMDev.h fun.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef VBOX_INCLUDED_VMMDevCoreTypes_h
+#define VBOX_INCLUDED_VMMDevCoreTypes_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/assertcompile.h>
+#include <iprt/types.h>
+#ifdef __cplusplus
+# include <iprt/assert.h>
+# include <iprt/errcore.h>
+#endif
+
+
+/** @addtogroup grp_vmmdev
+ * @{
+ */
+
+/* Helpful forward declarations: */
+struct VMMDevRequestHeader;
+struct VMMDevReqMousePointer;
+struct VMMDevMemory;
+
+
+/** @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)
+/** @} */
+
+
+/** @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)
+/** @} */
+
+
+/**
+ * Seamless mode.
+ *
+ * Used by VbglR3SeamlessWaitEvent
+ *
+ * @ingroup grp_vmmdev_req
+ */
+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. */
+ VMMDev_Seamless_SizeHack = 0x7fffffff
+} VMMDevSeamlessMode;
+AssertCompileSize(VMMDevSeamlessMode, 4);
+
+
+/**
+ * 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;
+AssertCompileSize(VMMDevCpuEventType, 4);
+
+
+/** @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)
+/** @} */
+
+
+/**
+ * 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_MonitorAttach = 1101,
+ 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 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);
+
+
+
+/**
+ * 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);
+
+
+/**
+ * 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 - for VBoxGuest, not host. */
+ VMMDevHGCMParmType_LinAddr_Locked_In = 8, /**< Locked In (read; host<-guest) - for VBoxGuest, not host. */
+ VMMDevHGCMParmType_LinAddr_Locked_Out = 9, /**< Locked Out (write; host->guest) - for VBoxGuest, not host. */
+ VMMDevHGCMParmType_PageList = 10, /**< Physical addresses of locked pages for a buffer. */
+ VMMDevHGCMParmType_Embedded = 11, /**< Small buffer embedded in request. */
+ VMMDevHGCMParmType_ContiguousPageList = 12, /**< Like PageList but with physically contiguous memory, so only one page entry. */
+ VMMDevHGCMParmType_NoBouncePageList = 13, /**< Like PageList but host function requires no bounce buffering. */
+ VMMDevHGCMParmType_SizeHack = 0x7fffffff
+} HGCMFunctionParameterType;
+AssertCompileSize(HGCMFunctionParameterType, 4);
+
+
+# ifdef VBOX_WITH_64_BITS_GUESTS
+/**
+ * HGCM function parameter, 32-bit client.
+ */
+# pragma pack(4) /* We force structure dword packing here for hysterical raisins. Saves us 4 bytes, at the cost of
+ misaligning the value64 member of every other parameter structure. */
+typedef struct HGCMFunctionParameter32
+{
+ HGCMFunctionParameterType type;
+ union
+ {
+ uint32_t value32;
+ uint64_t value64;
+ struct
+ {
+ uint32_t size;
+
+ union
+ {
+ RTGCPHYS32 physAddr;
+ RTGCPTR32 linearAddr;
+ } u;
+ } Pointer;
+ struct
+ {
+ uint32_t cb;
+ RTGCPTR32 uAddr;
+ } LinAddr; /**< Shorter version of the above Pointer structure. */
+ struct
+ {
+ uint32_t size; /**< Size of the buffer described by the page list. */
+ uint32_t offset; /**< Relative to the request header of a HGCMPageListInfo structure, valid if size != 0. */
+ } PageList;
+ struct
+ {
+ uint32_t fFlags : 8; /**< VBOX_HGCM_F_PARM_*. */
+ uint32_t offData : 24; /**< Relative to the request header, valid if cb != 0. */
+ uint32_t cbData; /**< The buffer size. */
+ } Embedded;
+ } 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 RT_FAR *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 RT_FAR *pu64)
+ {
+ if (type == VMMDevHGCMParmType_64bit)
+ {
+ *pu64 = u.value64;
+ return VINF_SUCCESS;
+ }
+ return VERR_INVALID_PARAMETER;
+ }
+
+ void SetPtr(void RT_FAR *pv, uint32_t cb)
+ {
+ type = VMMDevHGCMParmType_LinAddr;
+ u.Pointer.size = cb;
+ u.Pointer.u.linearAddr = (RTGCPTR32)(uintptr_t)pv;
+ }
+# endif /* __cplusplus */
+} HGCMFunctionParameter32;
+# pragma pack()
+AssertCompileSize(HGCMFunctionParameter32, 4+8);
+
+/**
+ * HGCM function parameter, 64-bit client.
+ */
+# pragma pack(4)/* We force structure dword packing here for hysterical raisins. Saves us 4 bytes,
+ at the cost of misaligning the value64 members. */
+typedef struct HGCMFunctionParameter64
+{
+ HGCMFunctionParameterType type;
+ union
+ {
+ uint32_t value32;
+ uint64_t value64;
+ struct
+ {
+ uint32_t size;
+
+ union
+ {
+ RTGCPHYS64 physAddr;
+ RTGCPTR64 linearAddr;
+ } u;
+ } Pointer;
+ struct
+ {
+ uint32_t cb;
+ RTGCPTR64 uAddr;
+ } LinAddr; /**< Shorter version of the above Pointer structure. */
+ 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;
+ struct
+ {
+ uint32_t fFlags : 8; /**< VBOX_HGCM_F_PARM_*. */
+ uint32_t offData : 24; /**< Relative to the request header, valid if cb != 0. */
+ uint32_t cbData; /**< The buffer size. */
+ } Embedded;
+ } 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 RT_FAR *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 RT_FAR *pu64)
+ {
+ if (type == VMMDevHGCMParmType_64bit)
+ {
+ *pu64 = u.value64;
+ return VINF_SUCCESS;
+ }
+ return VERR_INVALID_PARAMETER;
+ }
+
+ void SetPtr(void RT_FAR *pv, uint32_t cb)
+ {
+ type = VMMDevHGCMParmType_LinAddr;
+ u.Pointer.size = cb;
+ u.Pointer.u.linearAddr = (uintptr_t)pv;
+ }
+# endif /** __cplusplus */
+} HGCMFunctionParameter64;
+# pragma pack()
+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 || ARCH_BITS == 16
+# 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?
+ */
+# pragma pack(4) /* We force structure dword packing here for hysterical raisins. Saves us 4 bytes, at the cost of
+ misaligning the value64 member of every other parameter structure. */
+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 cb;
+ RTGCPTR32 uAddr;
+ } LinAddr; /**< Shorter version of the above Pointer structure. */
+ 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;
+ struct
+ {
+ uint32_t fFlags : 8; /**< VBOX_HGCM_F_PARM_*. */
+ uint32_t offData : 24; /**< Relative to the request header (must be a valid offset even if cbData is zero). */
+ uint32_t cbData; /**< The buffer size. */
+ } Embedded;
+ } 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)
+ {
+ AssertMsgReturnStmt(type == VMMDevHGCMParmType_32bit, ("type=-%d\n", type),
+ *pu32 = UINT32_MAX /* shut up gcc */, VERR_WRONG_PARAMETER_TYPE)
+ *pu32 = u.value32;
+ return VINF_SUCCESS;
+ }
+
+ void SetUInt64(uint64_t u64)
+ {
+ type = VMMDevHGCMParmType_64bit;
+ u.value64 = u64;
+ }
+
+ int GetUInt64(uint64_t *pu64)
+ {
+ AssertMsgReturnStmt(type == VMMDevHGCMParmType_64bit, ("type=%d\n", type),
+ *pu64 = UINT32_MAX /* shut up gcc */, VERR_WRONG_PARAMETER_TYPE);
+ *pu64 = u.value64;
+ return VINF_SUCCESS;
+ }
+
+ void SetPtr(void *pv, uint32_t cb)
+ {
+ type = VMMDevHGCMParmType_LinAddr;
+ u.Pointer.size = cb;
+ u.Pointer.u.linearAddr = (uintptr_t)pv;
+ }
+# endif /* __cplusplus */
+} HGCMFunctionParameter;
+# pragma pack()
+AssertCompileSize(HGCMFunctionParameter, 4+8);
+# endif /* !VBOX_WITH_64_BITS_GUESTS */
+
+/** @} */
+
+#endif /* !VBOX_INCLUDED_VMMDevCoreTypes_h */
+
diff --git a/include/VBox/VMMDevTesting.h b/include/VBox/VMMDevTesting.h
new file mode 100644
index 00000000..d68d9c1b
--- /dev/null
+++ b/include/VBox/VMMDevTesting.h
@@ -0,0 +1,272 @@
+/* $Id: VMMDevTesting.h $ */
+/** @file
+ * VMMDev - Testing Extensions.
+ */
+
+/*
+ * Copyright (C) 2010-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_VMMDevTesting_h
+#define VBOX_INCLUDED_VMMDevTesting_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/types.h>
+
+
+/** @defgroup grp_vmmdev_testing VMM Device Testing
+ * @ingroup grp_vmmdev
+ * @{
+ */
+
+/** The base address of the MMIO range used for testing.
+ * @remarks This used to be at 0x101000 but moved to 0xdf000 so that it would
+ * work better with prototype NEM code. This also means enabling A20
+ * is not a requirement. */
+#define VMMDEV_TESTING_MMIO_BASE UINT32_C(0x000df000)
+/** The size of the MMIO range used for testing. */
+#define VMMDEV_TESTING_MMIO_SIZE UINT32_C(0x00001000)
+
+/** MMIO offset: The NOP register - 1248 RW. */
+#define VMMDEV_TESTING_MMIO_OFF_NOP (0x000)
+/** MMIO offset: The go-to-ring-3-NOP register - 1248 RW. */
+#define VMMDEV_TESTING_MMIO_OFF_NOP_R3 (0x008)
+/** MMIO offset: The readback registers - 64 bytes of read/write "memory". */
+#define VMMDEV_TESTING_MMIO_OFF_READBACK (0x040)
+/** MMIO offset: Readback register view that always goes to ring-3. */
+#define VMMDEV_TESTING_MMIO_OFF_READBACK_R3 (0x080)
+/** The size of the MMIO readback registers. */
+#define VMMDEV_TESTING_READBACK_SIZE (0x40)
+
+/** Default address of VMMDEV_TESTING_MMIO_OFF_NOP. */
+#define VMMDEV_TESTING_MMIO_NOP (VMMDEV_TESTING_MMIO_BASE + VMMDEV_TESTING_MMIO_OFF_NOP)
+/** Default address of VMMDEV_TESTING_MMIO_OFF_NOP_R3. */
+#define VMMDEV_TESTING_MMIO_NOP_R3 (VMMDEV_TESTING_MMIO_BASE + VMMDEV_TESTING_MMIO_OFF_NOP_R3)
+/** Default address of VMMDEV_TESTING_MMIO_OFF_READBACK. */
+#define VMMDEV_TESTING_MMIO_READBACK (VMMDEV_TESTING_MMIO_BASE + VMMDEV_TESTING_MMIO_OFF_READBACK)
+/** Default address of VMMDEV_TESTING_MMIO_OFF_READBACK_R3. */
+#define VMMDEV_TESTING_MMIO_READBACK_R3 (VMMDEV_TESTING_MMIO_BASE + VMMDEV_TESTING_MMIO_OFF_READBACK_R3)
+
+/** The real mode selector to use. */
+#define VMMDEV_TESTING_MMIO_RM_SEL 0xdf00
+/** Calculate the real mode offset of a MMIO register. */
+#define VMMDEV_TESTING_MMIO_RM_OFF(val) ((val) - VMMDEV_TESTING_MMIO_BASE)
+/** Calculate the real mode offset of a MMIO register offset. */
+#define VMMDEV_TESTING_MMIO_RM_OFF2(off) (off)
+
+/** The base port of the I/O range used for testing. */
+#define VMMDEV_TESTING_IOPORT_BASE 0x0510
+/** The number of I/O ports reserved for testing. */
+#define VMMDEV_TESTING_IOPORT_COUNT 0x0010
+/** The NOP I/O port - 1,2,4 RW. */
+#define VMMDEV_TESTING_IOPORT_NOP (VMMDEV_TESTING_IOPORT_BASE + 0)
+/** The low nanosecond timestamp - 4 RO. */
+#define VMMDEV_TESTING_IOPORT_TS_LOW (VMMDEV_TESTING_IOPORT_BASE + 1)
+/** The high nanosecond timestamp - 4 RO. Read this after the low one! */
+#define VMMDEV_TESTING_IOPORT_TS_HIGH (VMMDEV_TESTING_IOPORT_BASE + 2)
+/** Command register usually used for preparing the data register - 4/2 WO. */
+#define VMMDEV_TESTING_IOPORT_CMD (VMMDEV_TESTING_IOPORT_BASE + 3)
+/** Data register which use depends on the current command - 1s, 4 WO. */
+#define VMMDEV_TESTING_IOPORT_DATA (VMMDEV_TESTING_IOPORT_BASE + 4)
+/** The go-to-ring-3-NOP I/O port - 1,2,4 RW. */
+#define VMMDEV_TESTING_IOPORT_NOP_R3 (VMMDEV_TESTING_IOPORT_BASE + 5)
+/** Take the VMMDev lock in arrival context and return - 1,2,4 RW.
+ * Writing configures counter action by a thread taking the lock to trigger
+ * contention:
+ * - bits 15:0: Number of microseconds thread should hold lock.
+ * - bits 31:16: Number of microseconds thread should wait before locking
+ * again. */
+#define VMMDEV_TESTING_IOPORT_LOCKED_LO (VMMDEV_TESTING_IOPORT_BASE + 6)
+/** Take the VMMDev lock in arrival context and return - 1,2,4 RW.
+ * Writing configures counter action by a thread taking the lock to trigger
+ * contention:
+ * - bits 19:0: Number of kilo (1024) ticks the EMT should hold lock.
+ * - bits 25:20: Reserved, must be zero.
+ * - bit 26: Thread takes lock in shared mode when set, exclusive when clear.
+ * - bit 27: EMT takes lock in shared mode when set, exclusive when clear.
+ * - bit 28: Use read/write critical section when set, device section if clear.
+ * - bit 29: EMT passes VINF_SUCCESS as rcBusy when set.
+ * - bit 30: Makes thread poke all EMTs before release lock.
+ * - bit 31: Enables the thread. */
+#define VMMDEV_TESTING_IOPORT_LOCKED_HI (VMMDEV_TESTING_IOPORT_BASE + 7)
+
+/** @name Commands.
+ * @{ */
+/** Initialize test, sending name (zero terminated string). (RTTestCreate) */
+#define VMMDEV_TESTING_CMD_INIT UINT32_C(0xcab1e000)
+/** Test done, sending 32-bit total error count with it. (RTTestSummaryAndDestroy) */
+#define VMMDEV_TESTING_CMD_TERM UINT32_C(0xcab1e001)
+/** Start a new sub-test, sending name (zero terminated string). (RTTestSub) */
+#define VMMDEV_TESTING_CMD_SUB_NEW UINT32_C(0xcab1e002)
+/** Sub-test is done, sending 32-bit error count for it. (RTTestDone) */
+#define VMMDEV_TESTING_CMD_SUB_DONE UINT32_C(0xcab1e003)
+/** Report a failure, sending reason (zero terminated string). (RTTestFailed) */
+#define VMMDEV_TESTING_CMD_FAILED UINT32_C(0xcab1e004)
+/** Report a value, sending the 64-bit value (2x4), the 32-bit unit (4), and
+ * finally the name (zero terminated string). (RTTestValue) */
+#define VMMDEV_TESTING_CMD_VALUE UINT32_C(0xcab1e005)
+/** Report a failure, sending reason (zero terminated string). (RTTestSkipped) */
+#define VMMDEV_TESTING_CMD_SKIPPED UINT32_C(0xcab1e006)
+/** Report a value found in a VMM register, sending a string on the form
+ * "value-name:register-name". */
+#define VMMDEV_TESTING_CMD_VALUE_REG UINT32_C(0xcab1e007)
+/** Print string, sending a string including newline. (RTTestPrintf) */
+#define VMMDEV_TESTING_CMD_PRINT UINT32_C(0xcab1e008)
+/** Query a config value, sending a 16-bit word (VMMDEV_TESTING_CFG_XXX) to the
+ * DATA port and reading back the result. */
+#define VMMDEV_TESTING_CMD_QUERY_CFG UINT32_C(0xcab1e009)
+
+/** The magic part of the command. */
+#define VMMDEV_TESTING_CMD_MAGIC UINT32_C(0xcab1e000)
+/** The magic part of the command. */
+#define VMMDEV_TESTING_CMD_MAGIC_MASK UINT32_C(0xffffff00)
+/** The magic high word automatically supplied to 16-bit CMD writes. */
+#define VMMDEV_TESTING_CMD_MAGIC_HI_WORD UINT32_C(0xcab10000)
+/** @} */
+
+/** @name Value units
+ * @note Same as RTTESTUNIT, see rules here for adding new units.
+ * @{ */
+#define VMMDEV_TESTING_UNIT_PCT UINT8_C(0x01) /**< Percentage. */
+#define VMMDEV_TESTING_UNIT_BYTES UINT8_C(0x02) /**< Bytes. */
+#define VMMDEV_TESTING_UNIT_BYTES_PER_SEC UINT8_C(0x03) /**< Bytes per second. */
+#define VMMDEV_TESTING_UNIT_KILOBYTES UINT8_C(0x04) /**< Kilobytes. */
+#define VMMDEV_TESTING_UNIT_KILOBYTES_PER_SEC UINT8_C(0x05) /**< Kilobytes per second. */
+#define VMMDEV_TESTING_UNIT_MEGABYTES UINT8_C(0x06) /**< Megabytes. */
+#define VMMDEV_TESTING_UNIT_MEGABYTES_PER_SEC UINT8_C(0x07) /**< Megabytes per second. */
+#define VMMDEV_TESTING_UNIT_PACKETS UINT8_C(0x08) /**< Packets. */
+#define VMMDEV_TESTING_UNIT_PACKETS_PER_SEC UINT8_C(0x09) /**< Packets per second. */
+#define VMMDEV_TESTING_UNIT_FRAMES UINT8_C(0x0a) /**< Frames. */
+#define VMMDEV_TESTING_UNIT_FRAMES_PER_SEC UINT8_C(0x0b) /**< Frames per second. */
+#define VMMDEV_TESTING_UNIT_OCCURRENCES UINT8_C(0x0c) /**< Occurrences. */
+#define VMMDEV_TESTING_UNIT_OCCURRENCES_PER_SEC UINT8_C(0x0d) /**< Occurrences per second. */
+#define VMMDEV_TESTING_UNIT_CALLS UINT8_C(0x0e) /**< Calls. */
+#define VMMDEV_TESTING_UNIT_CALLS_PER_SEC UINT8_C(0x0f) /**< Calls per second. */
+#define VMMDEV_TESTING_UNIT_ROUND_TRIP UINT8_C(0x10) /**< Round trips. */
+#define VMMDEV_TESTING_UNIT_SECS UINT8_C(0x11) /**< Seconds. */
+#define VMMDEV_TESTING_UNIT_MS UINT8_C(0x12) /**< Milliseconds. */
+#define VMMDEV_TESTING_UNIT_NS UINT8_C(0x13) /**< Nanoseconds. */
+#define VMMDEV_TESTING_UNIT_NS_PER_CALL UINT8_C(0x14) /**< Nanoseconds per call. */
+#define VMMDEV_TESTING_UNIT_NS_PER_FRAME UINT8_C(0x15) /**< Nanoseconds per frame. */
+#define VMMDEV_TESTING_UNIT_NS_PER_OCCURRENCE UINT8_C(0x16) /**< Nanoseconds per occurrence. */
+#define VMMDEV_TESTING_UNIT_NS_PER_PACKET UINT8_C(0x17) /**< Nanoseconds per frame. */
+#define VMMDEV_TESTING_UNIT_NS_PER_ROUND_TRIP UINT8_C(0x18) /**< Nanoseconds per round trip. */
+#define VMMDEV_TESTING_UNIT_INSTRS UINT8_C(0x19) /**< Instructions. */
+#define VMMDEV_TESTING_UNIT_INSTRS_PER_SEC UINT8_C(0x1a) /**< Instructions per second. */
+#define VMMDEV_TESTING_UNIT_NONE UINT8_C(0x1b) /**< No unit. */
+#define VMMDEV_TESTING_UNIT_PP1K UINT8_C(0x1c) /**< Parts per thousand (10^-3). */
+#define VMMDEV_TESTING_UNIT_PP10K UINT8_C(0x1d) /**< Parts per ten thousand (10^-4). */
+#define VMMDEV_TESTING_UNIT_PPM UINT8_C(0x1e) /**< Parts per million (10^-6). */
+#define VMMDEV_TESTING_UNIT_PPB UINT8_C(0x1f) /**< Parts per billion (10^-9). */
+#define VMMDEV_TESTING_UNIT_TICKS UINT8_C(0x20) /**< CPU ticks. */
+#define VMMDEV_TESTING_UNIT_TICKS_PER_CALL UINT8_C(0x21) /**< CPU ticks per call. */
+#define VMMDEV_TESTING_UNIT_TICKS_PER_OCCURENCE UINT8_C(0x22) /**< CPU ticks per occurence. */
+#define VMMDEV_TESTING_UNIT_PAGES UINT8_C(0x23) /**< Page count. */
+#define VMMDEV_TESTING_UNIT_PAGES_PER_SEC UINT8_C(0x24) /**< Pages per second. */
+#define VMMDEV_TESTING_UNIT_TICKS_PER_PAGE UINT8_C(0x25) /**< CPU ticks per page. */
+#define VMMDEV_TESTING_UNIT_NS_PER_PAGE UINT8_C(0x26) /**< Nanoseconds per page. */
+#define VMMDEV_TESTING_UNIT_PS UINT8_C(0x27) /**< Picoseconds. */
+#define VMMDEV_TESTING_UNIT_PS_PER_CALL UINT8_C(0x28) /**< Picoseconds per call. */
+#define VMMDEV_TESTING_UNIT_PS_PER_FRAME UINT8_C(0x29) /**< Picoseconds per frame. */
+#define VMMDEV_TESTING_UNIT_PS_PER_OCCURRENCE UINT8_C(0x2a) /**< Picoseconds per occurrence. */
+#define VMMDEV_TESTING_UNIT_PS_PER_PACKET UINT8_C(0x2b) /**< Picoseconds per frame. */
+#define VMMDEV_TESTING_UNIT_PS_PER_ROUND_TRIP UINT8_C(0x2c) /**< Picoseconds per round trip. */
+#define VMMDEV_TESTING_UNIT_PS_PER_PAGE UINT8_C(0x2d) /**< Picoseconds per page. */
+/** @} */
+
+/** What the NOP accesses returns. */
+#define VMMDEV_TESTING_NOP_RET UINT32_C(0x64726962) /* bird */
+
+/** @name Low and High Locking Control Dwords
+ * @{ */
+/** Low Locking Control: Thread lock hold interval in microseconds. */
+#define VMMDEV_TESTING_LOCKED_LO_HOLD_MASK UINT32_C(0x0000ffff)
+/** Low Locking Control: Thread wait time in microseconds between locking
+ * attempts. */
+#define VMMDEV_TESTING_LOCKED_LO_WAIT_MASK UINT32_C(0xffff0000)
+/** Low Locking Control: Thread wait time shift count. */
+#define VMMDEV_TESTING_LOCKED_LO_WAIT_SHIFT 16
+/** High Locking Control: Kilo (1024) ticks the EMT should hold the lock. */
+#define VMMDEV_TESTING_LOCKED_HI_TICKS_MASK UINT32_C(0x000fffff)
+/** High Locking Control: Must be zero. */
+#define VMMDEV_TESTING_LOCKED_HI_MBZ_MASK UINT32_C(0x03f00000)
+/** High Locking Control: Thread takes lock in shared mode when set, exclusive
+ * when clear. */
+#define VMMDEV_TESTING_LOCKED_HI_THREAD_SHARED UINT32_C(0x04000000)
+/** High Locking Control: EMT takes lock in shared mode when set, exclusive
+ * when clear. */
+#define VMMDEV_TESTING_LOCKED_HI_EMT_SHARED UINT32_C(0x08000000)
+/** High Locking Control: Use read/write critical section instead of regular. */
+#define VMMDEV_TESTING_LOCKED_HI_TYPE_RW UINT32_C(0x10000000)
+/** High Locking Control: EMT takes lock with rcBusy set to VINF_SUCCESS. */
+#define VMMDEV_TESTING_LOCKED_HI_BUSY_SUCCESS UINT32_C(0x20000000)
+/** High Locking Control: Thread pokes EMTs before releasing lock. */
+#define VMMDEV_TESTING_LOCKED_HI_POKE UINT32_C(0x40000000)
+/** High Locking Control: Thread enabled. */
+#define VMMDEV_TESTING_LOCKED_HI_ENABLED UINT32_C(0x80000000)
+/** @} */
+
+/** @name VMMDEV_TESTING_CFG_XXX - Configuration values that can be queried.
+ * @{ */
+/** Generic 32-bit value \#0 - testcase defined meaning. */
+#define VMMDEV_TESTING_CFG_DWORD0 UINT16_C(0x0000)
+/** Generic 32-bit value \#1 - testcase defined meaning. */
+#define VMMDEV_TESTING_CFG_DWORD1 UINT16_C(0x0001)
+/** Generic 32-bit value \#2 - testcase defined meaning. */
+#define VMMDEV_TESTING_CFG_DWORD2 UINT16_C(0x0002)
+/** Generic 32-bit value \#3 - testcase defined meaning. */
+#define VMMDEV_TESTING_CFG_DWORD3 UINT16_C(0x0003)
+/** Generic 32-bit value \#4 - testcase defined meaning. */
+#define VMMDEV_TESTING_CFG_DWORD4 UINT16_C(0x0004)
+/** Generic 32-bit value \#5 - testcase defined meaning. */
+#define VMMDEV_TESTING_CFG_DWORD5 UINT16_C(0x0005)
+/** Generic 32-bit value \#6 - testcase defined meaning. */
+#define VMMDEV_TESTING_CFG_DWORD6 UINT16_C(0x0006)
+/** Generic 32-bit value \#7 - testcase defined meaning. */
+#define VMMDEV_TESTING_CFG_DWORD7 UINT16_C(0x0007)
+/** Generic 32-bit value \#8 - testcase defined meaning. */
+#define VMMDEV_TESTING_CFG_DWORD8 UINT16_C(0x0008)
+/** Generic 32-bit value \#9 - testcase defined meaning. */
+#define VMMDEV_TESTING_CFG_DWORD9 UINT16_C(0x0009)
+
+/** Boolean (8-bit): Running in NEM on Linux? */
+#define VMMDEV_TESTING_CFG_IS_NEM_LINUX UINT16_C(0x0100)
+/** Boolean (8-bit): Running in NEM on Windows? */
+#define VMMDEV_TESTING_CFG_IS_NEM_WINDOWS UINT16_C(0x0101)
+/** Boolean (8-bit): Running in NEM on Darwin? */
+#define VMMDEV_TESTING_CFG_IS_NEM_DARWIN UINT16_C(0x0102)
+/** @} */
+
+/** @} */
+
+#endif /* !VBOX_INCLUDED_VMMDevTesting_h */
+
diff --git a/include/VBox/VMMDevTesting.mac b/include/VBox/VMMDevTesting.mac
new file mode 100644
index 00000000..79434866
--- /dev/null
+++ b/include/VBox/VMMDevTesting.mac
@@ -0,0 +1,148 @@
+; $Id: VMMDevTesting.mac $ ;/
+;; @file
+; VMMDev - Testing Extensions.
+; Automatically generated by various.sed. DO NOT EDIT!
+
+;
+; Copyright (C) 2010-2022 Oracle and/or its affiliates.
+;
+; This file is part of VirtualBox base platform packages, as
+; available from https://www.virtualbox.org.
+;
+; This program is free software; you can redistribute it and/or
+; modify it under the terms of the GNU General Public License
+; as published by the Free Software Foundation, in version 3 of the
+; License.
+;
+; This program is distributed in the hope that it will be useful, but
+; WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with this program; if not, see <https://www.gnu.org/licenses>.
+;
+; The contents of this file may alternatively be used under the terms
+; of the Common Development and Distribution License Version 1.0
+; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+; in the VirtualBox 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.
+;
+; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+;
+
+%ifndef VBOX_INCLUDED_VMMDevTesting_h
+%define VBOX_INCLUDED_VMMDevTesting_h
+%ifndef RT_WITHOUT_PRAGMA_ONCE
+%endif
+%define VMMDEV_TESTING_MMIO_BASE 0x000df000
+%define VMMDEV_TESTING_MMIO_SIZE 0x00001000
+%define VMMDEV_TESTING_MMIO_OFF_NOP (0x000)
+%define VMMDEV_TESTING_MMIO_OFF_NOP_R3 (0x008)
+%define VMMDEV_TESTING_MMIO_OFF_READBACK (0x040)
+%define VMMDEV_TESTING_MMIO_OFF_READBACK_R3 (0x080)
+%define VMMDEV_TESTING_READBACK_SIZE (0x40)
+%define VMMDEV_TESTING_MMIO_NOP (VMMDEV_TESTING_MMIO_BASE + VMMDEV_TESTING_MMIO_OFF_NOP)
+%define VMMDEV_TESTING_MMIO_NOP_R3 (VMMDEV_TESTING_MMIO_BASE + VMMDEV_TESTING_MMIO_OFF_NOP_R3)
+%define VMMDEV_TESTING_MMIO_READBACK (VMMDEV_TESTING_MMIO_BASE + VMMDEV_TESTING_MMIO_OFF_READBACK)
+%define VMMDEV_TESTING_MMIO_READBACK_R3 (VMMDEV_TESTING_MMIO_BASE + VMMDEV_TESTING_MMIO_OFF_READBACK_R3)
+%define VMMDEV_TESTING_MMIO_RM_SEL 0xdf00
+%define VMMDEV_TESTING_MMIO_RM_OFF(val) ((val) - VMMDEV_TESTING_MMIO_BASE)
+%define VMMDEV_TESTING_MMIO_RM_OFF2(off) (off)
+%define VMMDEV_TESTING_IOPORT_BASE 0x0510
+%define VMMDEV_TESTING_IOPORT_COUNT 0x0010
+%define VMMDEV_TESTING_IOPORT_NOP (VMMDEV_TESTING_IOPORT_BASE + 0)
+%define VMMDEV_TESTING_IOPORT_TS_LOW (VMMDEV_TESTING_IOPORT_BASE + 1)
+%define VMMDEV_TESTING_IOPORT_TS_HIGH (VMMDEV_TESTING_IOPORT_BASE + 2)
+%define VMMDEV_TESTING_IOPORT_CMD (VMMDEV_TESTING_IOPORT_BASE + 3)
+%define VMMDEV_TESTING_IOPORT_DATA (VMMDEV_TESTING_IOPORT_BASE + 4)
+%define VMMDEV_TESTING_IOPORT_NOP_R3 (VMMDEV_TESTING_IOPORT_BASE + 5)
+%define VMMDEV_TESTING_IOPORT_LOCKED_LO (VMMDEV_TESTING_IOPORT_BASE + 6)
+%define VMMDEV_TESTING_IOPORT_LOCKED_HI (VMMDEV_TESTING_IOPORT_BASE + 7)
+%define VMMDEV_TESTING_CMD_INIT 0xcab1e000
+%define VMMDEV_TESTING_CMD_TERM 0xcab1e001
+%define VMMDEV_TESTING_CMD_SUB_NEW 0xcab1e002
+%define VMMDEV_TESTING_CMD_SUB_DONE 0xcab1e003
+%define VMMDEV_TESTING_CMD_FAILED 0xcab1e004
+%define VMMDEV_TESTING_CMD_VALUE 0xcab1e005
+%define VMMDEV_TESTING_CMD_SKIPPED 0xcab1e006
+%define VMMDEV_TESTING_CMD_VALUE_REG 0xcab1e007
+%define VMMDEV_TESTING_CMD_PRINT 0xcab1e008
+%define VMMDEV_TESTING_CMD_QUERY_CFG 0xcab1e009
+%define VMMDEV_TESTING_CMD_MAGIC 0xcab1e000
+%define VMMDEV_TESTING_CMD_MAGIC_MASK 0xffffff00
+%define VMMDEV_TESTING_CMD_MAGIC_HI_WORD 0xcab10000
+%define VMMDEV_TESTING_UNIT_PCT 0x01
+%define VMMDEV_TESTING_UNIT_BYTES 0x02
+%define VMMDEV_TESTING_UNIT_BYTES_PER_SEC 0x03
+%define VMMDEV_TESTING_UNIT_KILOBYTES 0x04
+%define VMMDEV_TESTING_UNIT_KILOBYTES_PER_SEC 0x05
+%define VMMDEV_TESTING_UNIT_MEGABYTES 0x06
+%define VMMDEV_TESTING_UNIT_MEGABYTES_PER_SEC 0x07
+%define VMMDEV_TESTING_UNIT_PACKETS 0x08
+%define VMMDEV_TESTING_UNIT_PACKETS_PER_SEC 0x09
+%define VMMDEV_TESTING_UNIT_FRAMES 0x0a
+%define VMMDEV_TESTING_UNIT_FRAMES_PER_SEC 0x0b
+%define VMMDEV_TESTING_UNIT_OCCURRENCES 0x0c
+%define VMMDEV_TESTING_UNIT_OCCURRENCES_PER_SEC 0x0d
+%define VMMDEV_TESTING_UNIT_CALLS 0x0e
+%define VMMDEV_TESTING_UNIT_CALLS_PER_SEC 0x0f
+%define VMMDEV_TESTING_UNIT_ROUND_TRIP 0x10
+%define VMMDEV_TESTING_UNIT_SECS 0x11
+%define VMMDEV_TESTING_UNIT_MS 0x12
+%define VMMDEV_TESTING_UNIT_NS 0x13
+%define VMMDEV_TESTING_UNIT_NS_PER_CALL 0x14
+%define VMMDEV_TESTING_UNIT_NS_PER_FRAME 0x15
+%define VMMDEV_TESTING_UNIT_NS_PER_OCCURRENCE 0x16
+%define VMMDEV_TESTING_UNIT_NS_PER_PACKET 0x17
+%define VMMDEV_TESTING_UNIT_NS_PER_ROUND_TRIP 0x18
+%define VMMDEV_TESTING_UNIT_INSTRS 0x19
+%define VMMDEV_TESTING_UNIT_INSTRS_PER_SEC 0x1a
+%define VMMDEV_TESTING_UNIT_NONE 0x1b
+%define VMMDEV_TESTING_UNIT_PP1K 0x1c
+%define VMMDEV_TESTING_UNIT_PP10K 0x1d
+%define VMMDEV_TESTING_UNIT_PPM 0x1e
+%define VMMDEV_TESTING_UNIT_PPB 0x1f
+%define VMMDEV_TESTING_UNIT_TICKS 0x20
+%define VMMDEV_TESTING_UNIT_TICKS_PER_CALL 0x21
+%define VMMDEV_TESTING_UNIT_TICKS_PER_OCCURENCE 0x22
+%define VMMDEV_TESTING_UNIT_PAGES 0x23
+%define VMMDEV_TESTING_UNIT_PAGES_PER_SEC 0x24
+%define VMMDEV_TESTING_UNIT_TICKS_PER_PAGE 0x25
+%define VMMDEV_TESTING_UNIT_NS_PER_PAGE 0x26
+%define VMMDEV_TESTING_UNIT_PS 0x27
+%define VMMDEV_TESTING_UNIT_PS_PER_CALL 0x28
+%define VMMDEV_TESTING_UNIT_PS_PER_FRAME 0x29
+%define VMMDEV_TESTING_UNIT_PS_PER_OCCURRENCE 0x2a
+%define VMMDEV_TESTING_UNIT_PS_PER_PACKET 0x2b
+%define VMMDEV_TESTING_UNIT_PS_PER_ROUND_TRIP 0x2c
+%define VMMDEV_TESTING_UNIT_PS_PER_PAGE 0x2d
+%define VMMDEV_TESTING_NOP_RET 0x64726962
+%define VMMDEV_TESTING_LOCKED_LO_HOLD_MASK 0x0000ffff
+%define VMMDEV_TESTING_LOCKED_LO_WAIT_MASK 0xffff0000
+%define VMMDEV_TESTING_LOCKED_LO_WAIT_SHIFT 16
+%define VMMDEV_TESTING_LOCKED_HI_TICKS_MASK 0x000fffff
+%define VMMDEV_TESTING_LOCKED_HI_MBZ_MASK 0x03f00000
+%define VMMDEV_TESTING_LOCKED_HI_THREAD_SHARED 0x04000000
+%define VMMDEV_TESTING_LOCKED_HI_EMT_SHARED 0x08000000
+%define VMMDEV_TESTING_LOCKED_HI_TYPE_RW 0x10000000
+%define VMMDEV_TESTING_LOCKED_HI_BUSY_SUCCESS 0x20000000
+%define VMMDEV_TESTING_LOCKED_HI_POKE 0x40000000
+%define VMMDEV_TESTING_LOCKED_HI_ENABLED 0x80000000
+%define VMMDEV_TESTING_CFG_DWORD0 0x0000
+%define VMMDEV_TESTING_CFG_DWORD1 0x0001
+%define VMMDEV_TESTING_CFG_DWORD2 0x0002
+%define VMMDEV_TESTING_CFG_DWORD3 0x0003
+%define VMMDEV_TESTING_CFG_DWORD4 0x0004
+%define VMMDEV_TESTING_CFG_DWORD5 0x0005
+%define VMMDEV_TESTING_CFG_DWORD6 0x0006
+%define VMMDEV_TESTING_CFG_DWORD7 0x0007
+%define VMMDEV_TESTING_CFG_DWORD8 0x0008
+%define VMMDEV_TESTING_CFG_DWORD9 0x0009
+%define VMMDEV_TESTING_CFG_IS_NEM_LINUX 0x0100
+%define VMMDEV_TESTING_CFG_IS_NEM_WINDOWS 0x0101
+%define VMMDEV_TESTING_CFG_IS_NEM_DARWIN 0x0102
+%endif
diff --git a/include/VBox/apic.h b/include/VBox/apic.h
new file mode 100644
index 00000000..e6f213f4
--- /dev/null
+++ b/include/VBox/apic.h
@@ -0,0 +1,493 @@
+/** @file
+ * X86 (and AMD64) Local APIC registers (VMM,++).
+ *
+ * apic.mac is generated from this file by running 'kmk incs' in the root.
+ */
+
+/*
+ * Copyright (C) 2010-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_apic_h
+#define VBOX_INCLUDED_apic_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+#include <iprt/x86.h>
+
+/** @todo These are defines used by CPUM and perhaps some assembly code. Remove
+ * these and use the XAPIC counterpart defines below later. */
+#define APIC_REG_VERSION 0x0030
+#define APIC_REG_VERSION_GET_VER(u32) (u32 & 0xff)
+#define APIC_REG_VERSION_GET_MAX_LVT(u32) ((u32 & 0xff0000) >> 16)
+
+/* Defines according to Figure 10-8 of the Intel Software Developers Manual Vol 3A */
+#define APIC_REG_LVT_LINT0 0x0350
+#define APIC_REG_LVT_LINT1 0x0360
+#define APIC_REG_LVT_ERR 0x0370
+#define APIC_REG_LVT_PC 0x0340
+#define APIC_REG_LVT_THMR 0x0330
+#define APIC_REG_LVT_CMCI 0x02F0
+#define APIC_REG_EILVT0 0x0500
+#define APIC_REG_EILVT1 0x0510
+#define APIC_REG_EILVT2 0x0520
+#define APIC_REG_EILVT3 0x0530
+#define APIC_REG_LVT_MODE_MASK (RT_BIT(8) | RT_BIT(9) | RT_BIT(10))
+#define APIC_REG_LVT_MODE_FIXED 0
+#define APIC_REG_LVT_MODE_NMI RT_BIT(10)
+#define APIC_REG_LVT_MODE_EXTINT (RT_BIT(8) | RT_BIT(9) | RT_BIT(10))
+#define APIC_REG_LVT_PIN_POLARIY RT_BIT(13)
+#define APIC_REG_LVT_REMOTE_IRR RT_BIT(14)
+#define APIC_REG_LVT_LEVEL_TRIGGER RT_BIT(15)
+#define APIC_REG_LVT_MASKED RT_BIT(16)
+
+/** The APIC hardware version number for Pentium 4. */
+#define XAPIC_HARDWARE_VERSION_P4 UINT8_C(0x14)
+/** Maximum number of LVT entries for Pentium 4. */
+#define XAPIC_MAX_LVT_ENTRIES_P4 UINT8_C(6)
+/** Size of the APIC ID bits for Pentium 4. */
+#define XAPIC_APIC_ID_BIT_COUNT_P4 UINT8_C(8)
+
+/** The APIC hardware version number for Pentium 6. */
+#define XAPIC_HARDWARE_VERSION_P6 UINT8_C(0x10)
+/** Maximum number of LVT entries for Pentium 6. */
+#define XAPIC_MAX_LVT_ENTRIES_P6 UINT8_C(4)
+/** Size of the APIC ID bits for Pentium 6. */
+#define XAPIC_APIC_ID_BIT_COUNT_P6 UINT8_C(4)
+
+/** Illegal APIC vector value start. */
+#define XAPIC_ILLEGAL_VECTOR_START UINT8_C(0)
+/** Illegal APIC vector value end (inclusive). */
+#define XAPIC_ILLEGAL_VECTOR_END UINT8_C(15)
+/** Reserved APIC vector value start. */
+#define XAPIC_RSVD_VECTOR_START UINT8_C(16)
+/** Reserved APIC vector value end (inclusive). */
+#define XAPIC_RSVD_VECTOR_END UINT8_C(31)
+
+/** ESR - Send checksum error for Pentium 6. */
+# define XAPIC_ESR_SEND_CHKSUM_ERROR_P6 RT_BIT(0)
+/** ESR - Send accept error for Pentium 6. */
+# define XAPIC_ESR_RECV_CHKSUM_ERROR_P6 RT_BIT(1)
+/** ESR - Send accept error for Pentium 6. */
+# define XAPIC_ESR_SEND_ACCEPT_ERROR_P6 RT_BIT(2)
+/** ESR - Receive accept error for Pentium 6. */
+# define XAPIC_ESR_RECV_ACCEPT_ERROR_P6 RT_BIT(3)
+
+/** ESR - Redirectable IPI. */
+#define XAPIC_ESR_REDIRECTABLE_IPI RT_BIT(4)
+/** ESR - Send accept error. */
+#define XAPIC_ESR_SEND_ILLEGAL_VECTOR RT_BIT(5)
+/** ESR - Send accept error. */
+#define XAPIC_ESR_RECV_ILLEGAL_VECTOR RT_BIT(6)
+/** ESR - Send accept error. */
+#define XAPIC_ESR_ILLEGAL_REG_ADDRESS RT_BIT(7)
+/** ESR - Valid write-only bits. */
+#define XAPIC_ESR_WO_VALID UINT32_C(0x0)
+
+/** TPR - Valid bits. */
+#define XAPIC_TPR_VALID UINT32_C(0xff)
+/** TPR - Task-priority class. */
+#define XAPIC_TPR_TP UINT32_C(0xf0)
+/** TPR - Task-priority subclass. */
+#define XAPIC_TPR_TP_SUBCLASS UINT32_C(0x0f)
+/** TPR - Gets the task-priority class. */
+#define XAPIC_TPR_GET_TP(a_Tpr) ((a_Tpr) & XAPIC_TPR_TP)
+/** TPR - Gets the task-priority subclass. */
+#define XAPIC_TPR_GET_TP_SUBCLASS(a_Tpr) ((a_Tpr) & XAPIC_TPR_TP_SUBCLASS)
+
+/** PPR - Valid bits. */
+#define XAPIC_PPR_VALID UINT32_C(0xff)
+/** PPR - Processor-priority class. */
+#define XAPIC_PPR_PP UINT32_C(0xf0)
+/** PPR - Processor-priority subclass. */
+#define XAPIC_PPR_PP_SUBCLASS UINT32_C(0x0f)
+/** PPR - Get the processor-priority class. */
+#define XAPIC_PPR_GET_PP(a_Ppr) ((a_Ppr) & XAPIC_PPR_PP)
+/** PPR - Get the processor-priority subclass. */
+#define XAPIC_PPR_GET_PP_SUBCLASS(a_Ppr) ((a_Ppr) & XAPIC_PPR_PP_SUBCLASS)
+
+/** Timer mode - One-shot. */
+#define XAPIC_TIMER_MODE_ONESHOT UINT32_C(0)
+/** Timer mode - Periodic. */
+#define XAPIC_TIMER_MODE_PERIODIC UINT32_C(1)
+/** Timer mode - TSC deadline. */
+#define XAPIC_TIMER_MODE_TSC_DEADLINE UINT32_C(2)
+
+/** LVT - The vector. */
+#define XAPIC_LVT_VECTOR UINT32_C(0xff)
+/** LVT - Gets the vector from an LVT entry. */
+#define XAPIC_LVT_GET_VECTOR(a_Lvt) ((a_Lvt) & XAPIC_LVT_VECTOR)
+/** LVT - The mask. */
+#define XAPIC_LVT_MASK RT_BIT(16)
+/** LVT - Is the LVT masked? */
+#define XAPIC_LVT_IS_MASKED(a_Lvt) RT_BOOL((a_Lvt) & XAPIC_LVT_MASK)
+/** LVT - Timer mode. */
+#define XAPIC_LVT_TIMER_MODE RT_BIT(17)
+/** LVT - Timer TSC-deadline timer mode. */
+#define XAPIC_LVT_TIMER_TSCDEADLINE RT_BIT(18)
+/** LVT - Gets the timer mode. */
+#define XAPIC_LVT_GET_TIMER_MODE(a_Lvt) (XAPICTIMERMODE)(((a_Lvt) >> 17) & UINT32_C(3))
+/** LVT - Delivery mode. */
+#define XAPIC_LVT_DELIVERY_MODE (RT_BIT(8) | RT_BIT(9) | RT_BIT(10))
+/** LVT - Gets the delivery mode. */
+#define XAPIC_LVT_GET_DELIVERY_MODE(a_Lvt) (XAPICDELIVERYMODE)(((a_Lvt) >> 8) & UINT32_C(7))
+/** LVT - Delivery status. */
+#define XAPIC_LVT_DELIVERY_STATUS RT_BIT(12)
+/** LVT - Trigger mode. */
+#define XAPIC_LVT_TRIGGER_MODE RT_BIT(15)
+/** LVT - Gets the trigger mode. */
+#define XAPIC_LVT_GET_TRIGGER_MODE(a_Lvt) (XAPICTRIGGERMODE)(((a_Lvt) >> 15) & UINT32_C(1))
+/** LVT - Remote IRR. */
+#define XAPIC_LVT_REMOTE_IRR RT_BIT(14)
+/** LVT - Gets the Remote IRR. */
+#define XAPIC_LVT_GET_REMOTE_IRR(a_Lvt) (((a_Lvt) >> 14) & 1)
+/** LVT - Interrupt Input Pin Polarity. */
+#define XAPIC_LVT_POLARITY RT_BIT(13)
+/** LVT - Gets the Interrupt Input Pin Polarity. */
+#define XAPIC_LVT_GET_POLARITY(a_Lvt) (((a_Lvt) >> 13) & 1)
+/** LVT - Valid bits common to all LVTs. */
+#define XAPIC_LVT_COMMON_VALID (XAPIC_LVT_VECTOR | XAPIC_LVT_DELIVERY_STATUS | XAPIC_LVT_MASK)
+/** LVT CMCI - Valid bits. */
+#define XAPIC_LVT_CMCI_VALID (XAPIC_LVT_COMMON_VALID | XAPIC_LVT_DELIVERY_MODE)
+/** LVT Timer - Valid bits. */
+#define XAPIC_LVT_TIMER_VALID (XAPIC_LVT_COMMON_VALID | XAPIC_LVT_TIMER_MODE | XAPIC_LVT_TIMER_TSCDEADLINE)
+/** LVT Thermal - Valid bits. */
+#define XAPIC_LVT_THERMAL_VALID (XAPIC_LVT_COMMON_VALID | XAPIC_LVT_DELIVERY_MODE)
+/** LVT Perf - Valid bits. */
+#define XAPIC_LVT_PERF_VALID (XAPIC_LVT_COMMON_VALID | XAPIC_LVT_DELIVERY_MODE)
+/** LVT LINTx - Valid bits. */
+#define XAPIC_LVT_LINT_VALID ( XAPIC_LVT_COMMON_VALID | XAPIC_LVT_DELIVERY_MODE | XAPIC_LVT_DELIVERY_STATUS \
+ | XAPIC_LVT_POLARITY | XAPIC_LVT_REMOTE_IRR | XAPIC_LVT_TRIGGER_MODE)
+/** LVT Error - Valid bits. */
+#define XAPIC_LVT_ERROR_VALID (XAPIC_LVT_COMMON_VALID)
+
+/** SVR - The vector. */
+#define XAPIC_SVR_VECTOR UINT32_C(0xff)
+/** SVR - APIC Software enable. */
+#define XAPIC_SVR_SOFTWARE_ENABLE RT_BIT(8)
+/** SVR - Supress EOI broadcast. */
+#define XAPIC_SVR_SUPRESS_EOI_BROADCAST RT_BIT(12)
+/** SVR - Valid bits for Pentium 4. */
+# define XAPIC_SVR_VALID_P4 (XAPIC_SVR_VECTOR | XAPIC_SVR_SOFTWARE_ENABLE)
+/** @todo SVR - Valid bits for Pentium 6. */
+
+/** DFR - Valid bits. */
+#define XAPIC_DFR_VALID UINT32_C(0xf0000000)
+/** DFR - Reserved bits that must always remain set. */
+#define XAPIC_DFR_RSVD_MB1 UINT32_C(0x0fffffff)
+/** DFR - The model. */
+#define XAPIC_DFR_MODEL UINT32_C(0xf)
+/** DFR - Gets the destination model. */
+#define XAPIC_DFR_GET_MODEL(a_uReg) (((a_uReg) >> 28) & XAPIC_DFR_MODEL)
+
+/** LDR - Valid bits. */
+#define XAPIC_LDR_VALID UINT32_C(0xff000000)
+/** LDR - Cluster ID mask (x2APIC). */
+#define X2APIC_LDR_CLUSTER_ID UINT32_C(0xffff0000)
+/** LDR - Mask of the LDR cluster ID (x2APIC). */
+#define X2APIC_LDR_GET_CLUSTER_ID(a_uReg) ((a_uReg) & X2APIC_LDR_CLUSTER_ID)
+/** LDR - Mask of the LDR logical ID (x2APIC). */
+#define X2APIC_LDR_LOGICAL_ID UINT32_C(0x0000ffff)
+
+/** LDR - Flat mode logical ID mask. */
+#define XAPIC_LDR_FLAT_LOGICAL_ID UINT32_C(0xff)
+/** LDR - Clustered mode cluster ID mask. */
+#define XAPIC_LDR_CLUSTERED_CLUSTER_ID UINT32_C(0xf0)
+/** LDR - Clustered mode logical ID mask. */
+#define XAPIC_LDR_CLUSTERED_LOGICAL_ID UINT32_C(0x0f)
+/** LDR - Gets the clustered mode cluster ID. */
+#define XAPIC_LDR_CLUSTERED_GET_CLUSTER_ID(a_uReg) ((a_uReg) & XAPIC_LDR_CLUSTERED_CLUSTER_ID)
+
+
+/** EOI - Valid write-only bits. */
+#define XAPIC_EOI_WO_VALID UINT32_C(0x0)
+/** Timer ICR - Valid bits. */
+#define XAPIC_TIMER_ICR_VALID UINT32_C(0xffffffff)
+/** Timer DCR - Valid bits. */
+#define XAPIC_TIMER_DCR_VALID (RT_BIT(0) | RT_BIT(1) | RT_BIT(3))
+
+/** Self IPI - Valid bits. */
+#define XAPIC_SELF_IPI_VALID UINT32_C(0xff)
+/** Self IPI - The vector. */
+#define XAPIC_SELF_IPI_VECTOR UINT32_C(0xff)
+/** Self IPI - Gets the vector. */
+#define XAPIC_SELF_IPI_GET_VECTOR(a_uReg) ((a_uReg) & XAPIC_SELF_IPI_VECTOR)
+
+/** ICR Low - The Vector. */
+#define XAPIC_ICR_LO_VECTOR UINT32_C(0xff)
+/** ICR Low - Gets the vector. */
+#define XAPIC_ICR_LO_GET_VECTOR(a_uIcr) ((a_uIcr) & XAPIC_ICR_LO_VECTOR)
+/** ICR Low - The delivery mode. */
+#define XAPIC_ICR_LO_DELIVERY_MODE (RT_BIT(8) | RT_BIT(9) | RT_BIT(10))
+/** ICR Low - The destination mode. */
+#define XAPIC_ICR_LO_DEST_MODE RT_BIT(11)
+/** ICR Low - The delivery status. */
+#define XAPIC_ICR_LO_DELIVERY_STATUS RT_BIT(12)
+/** ICR Low - The level. */
+#define XAPIC_ICR_LO_LEVEL RT_BIT(14)
+/** ICR Low - The trigger mode. */
+#define XAPIC_ICR_TRIGGER_MODE RT_BIT(15)
+/** ICR Low - The destination shorthand. */
+#define XAPIC_ICR_LO_DEST_SHORTHAND (RT_BIT(18) | RT_BIT(19))
+/** ICR Low - Valid write bits. */
+#define XAPIC_ICR_LO_WR_VALID ( XAPIC_ICR_LO_VECTOR | XAPIC_ICR_LO_DELIVERY_MODE | XAPIC_ICR_LO_DEST_MODE \
+ | XAPIC_ICR_LO_LEVEL | XAPIC_ICR_TRIGGER_MODE | XAPIC_ICR_LO_DEST_SHORTHAND)
+
+/** ICR High - The destination field. */
+#define XAPIC_ICR_HI_DEST UINT32_C(0xff000000)
+/** ICR High - Get the destination field. */
+#define XAPIC_ICR_HI_GET_DEST(a_u32IcrHi) (((a_u32IcrHi) >> 24) & XAPIC_ICR_HI_DEST)
+/** ICR High - Valid write bits in xAPIC mode. */
+#define XAPIC_ICR_HI_WR_VALID XAPIC_ICR_HI_DEST
+
+/** APIC ID broadcast mask - x2APIC mode. */
+#define X2APIC_ID_BROADCAST_MASK UINT32_C(0xffffffff)
+/** APIC ID broadcast mask - xAPIC mode for Pentium 4. */
+# define XAPIC_ID_BROADCAST_MASK_P4 UINT32_C(0xff)
+/** @todo Broadcast mask for Pentium 6. */
+
+/** Get an xAPIC page offset for an x2APIC MSR value. */
+#define X2APIC_GET_XAPIC_OFF(a_uMsr) ((((a_uMsr) - MSR_IA32_X2APIC_START) << 4) & UINT32_C(0xff0))
+/** Get an x2APIC MSR for an xAPIC page offset. */
+#define XAPIC_GET_X2APIC_MSR(a_offReg) ((((a_offReg) & UINT32_C(0xff0)) >> 4) | MSR_IA32_X2APIC_START)
+
+/** @name xAPIC and x2APIC register offsets.
+ * See Intel spec. 10.4.1 "The Local APIC Block Diagram".
+ * @{ */
+/** Offset of APIC ID Register. */
+#define XAPIC_OFF_ID 0x020
+/** Offset of APIC Version Register. */
+#define XAPIC_OFF_VERSION 0x030
+/** Offset of Task Priority Register. */
+#define XAPIC_OFF_TPR 0x080
+/** Offset of Arbitrartion Priority register. */
+#define XAPIC_OFF_APR 0x090
+/** Offset of Processor Priority register. */
+#define XAPIC_OFF_PPR 0x0A0
+/** Offset of End Of Interrupt register. */
+#define XAPIC_OFF_EOI 0x0B0
+/** Offset of Remote Read Register. */
+#define XAPIC_OFF_RRD 0x0C0
+/** Offset of Logical Destination Register. */
+#define XAPIC_OFF_LDR 0x0D0
+/** Offset of Destination Format Register. */
+#define XAPIC_OFF_DFR 0x0E0
+/** Offset of Spurious Interrupt Vector Register. */
+#define XAPIC_OFF_SVR 0x0F0
+/** Offset of In-service Register (bits 31:0). */
+#define XAPIC_OFF_ISR0 0x100
+/** Offset of In-service Register (bits 63:32). */
+#define XAPIC_OFF_ISR1 0x110
+/** Offset of In-service Register (bits 95:64). */
+#define XAPIC_OFF_ISR2 0x120
+/** Offset of In-service Register (bits 127:96). */
+#define XAPIC_OFF_ISR3 0x130
+/** Offset of In-service Register (bits 159:128). */
+#define XAPIC_OFF_ISR4 0x140
+/** Offset of In-service Register (bits 191:160). */
+#define XAPIC_OFF_ISR5 0x150
+/** Offset of In-service Register (bits 223:192). */
+#define XAPIC_OFF_ISR6 0x160
+/** Offset of In-service Register (bits 255:224). */
+#define XAPIC_OFF_ISR7 0x170
+/** Offset of Trigger Mode Register (bits 31:0). */
+#define XAPIC_OFF_TMR0 0x180
+/** Offset of Trigger Mode Register (bits 63:32). */
+#define XAPIC_OFF_TMR1 0x190
+/** Offset of Trigger Mode Register (bits 95:64). */
+#define XAPIC_OFF_TMR2 0x1A0
+/** Offset of Trigger Mode Register (bits 127:96). */
+#define XAPIC_OFF_TMR3 0x1B0
+/** Offset of Trigger Mode Register (bits 159:128). */
+#define XAPIC_OFF_TMR4 0x1C0
+/** Offset of Trigger Mode Register (bits 191:160). */
+#define XAPIC_OFF_TMR5 0x1D0
+/** Offset of Trigger Mode Register (bits 223:192). */
+#define XAPIC_OFF_TMR6 0x1E0
+/** Offset of Trigger Mode Register (bits 255:224). */
+#define XAPIC_OFF_TMR7 0x1F0
+/** Offset of Interrupt Request Register (bits 31:0). */
+#define XAPIC_OFF_IRR0 0x200
+/** Offset of Interrupt Request Register (bits 63:32). */
+#define XAPIC_OFF_IRR1 0x210
+/** Offset of Interrupt Request Register (bits 95:64). */
+#define XAPIC_OFF_IRR2 0x220
+/** Offset of Interrupt Request Register (bits 127:96). */
+#define XAPIC_OFF_IRR3 0x230
+/** Offset of Interrupt Request Register (bits 159:128). */
+#define XAPIC_OFF_IRR4 0x240
+/** Offset of Interrupt Request Register (bits 191:160). */
+#define XAPIC_OFF_IRR5 0x250
+/** Offset of Interrupt Request Register (bits 223:192). */
+#define XAPIC_OFF_IRR6 0x260
+/** Offset of Interrupt Request Register (bits 255:224). */
+#define XAPIC_OFF_IRR7 0x270
+/** Offset of Error Status Register. */
+#define XAPIC_OFF_ESR 0x280
+/** Offset of LVT CMCI Register. */
+#define XAPIC_OFF_LVT_CMCI 0x2F0
+/** Offset of Interrupt Command Register - Lo. */
+#define XAPIC_OFF_ICR_LO 0x300
+/** Offset of Interrupt Command Register - Hi. */
+#define XAPIC_OFF_ICR_HI 0x310
+/** Offset of LVT Timer Register. */
+#define XAPIC_OFF_LVT_TIMER 0x320
+/** Offset of LVT Thermal Sensor Register. */
+#define XAPIC_OFF_LVT_THERMAL 0x330
+/** Offset of LVT Performance Counter Register. */
+#define XAPIC_OFF_LVT_PERF 0x340
+/** Offset of LVT LINT0 Register. */
+#define XAPIC_OFF_LVT_LINT0 0x350
+/** Offset of LVT LINT1 Register. */
+#define XAPIC_OFF_LVT_LINT1 0x360
+/** Offset of LVT Error Register . */
+#define XAPIC_OFF_LVT_ERROR 0x370
+/** Offset of Timer Initial Count Register. */
+#define XAPIC_OFF_TIMER_ICR 0x380
+/** Offset of Timer Current Count Register. */
+#define XAPIC_OFF_TIMER_CCR 0x390
+/** Offset of Timer Divide Configuration Register. */
+#define XAPIC_OFF_TIMER_DCR 0x3E0
+/** Offset of Self-IPI Register (x2APIC only). */
+#define X2APIC_OFF_SELF_IPI 0x3F0
+
+/** Offset of LVT range start. */
+#define XAPIC_OFF_LVT_START XAPIC_OFF_LVT_TIMER
+/** Offset of LVT range end (inclusive). */
+#define XAPIC_OFF_LVT_END XAPIC_OFF_LVT_ERROR
+/** Offset of LVT extended range start. */
+#define XAPIC_OFF_LVT_EXT_START XAPIC_OFF_LVT_CMCI
+/** Offset of LVT extended range end (inclusive). */
+#define XAPIC_OFF_LVT_EXT_END XAPIC_OFF_LVT_CMCI
+/** Offset of the last register (incl. reserved) in the xAPIC/x2APIC range. */
+#define XAPIC_OFF_END 0x3F0
+/** @} */
+
+/** @name xAPIC Destination Format Register bits.
+ * See Intel spec. 10.6.2.2 "Logical Destination Mode".
+ * @{ */
+typedef enum XAPICDESTFORMAT
+{
+ XAPICDESTFORMAT_FLAT = 0xf,
+ XAPICDESTFORMAT_CLUSTER = 0
+} XAPICDESTFORMAT;
+/** @} */
+
+/** @name xAPIC Timer Mode bits.
+ * See Intel spec. 10.5.1 "Local Vector Table".
+ * @{ */
+typedef enum XAPICTIMERMODE
+{
+ XAPICTIMERMODE_ONESHOT = XAPIC_TIMER_MODE_ONESHOT,
+ XAPICTIMERMODE_PERIODIC = XAPIC_TIMER_MODE_PERIODIC,
+ XAPICTIMERMODE_TSC_DEADLINE = XAPIC_TIMER_MODE_TSC_DEADLINE
+} XAPICTIMERMODE;
+/** @} */
+
+/** @name xAPIC Interrupt Command Register bits.
+ * See Intel spec. 10.6.1 "Interrupt Command Register (ICR)".
+ * See Intel spec. 10.5.1 "Local Vector Table".
+ * @{ */
+/**
+ * xAPIC destination shorthand.
+ */
+typedef enum XAPICDESTSHORTHAND
+{
+ XAPICDESTSHORTHAND_NONE = 0,
+ XAPICDESTSHORTHAND_SELF,
+ XAPIDDESTSHORTHAND_ALL_INCL_SELF,
+ XAPICDESTSHORTHAND_ALL_EXCL_SELF
+} XAPICDESTSHORTHAND;
+
+/**
+ * xAPIC INIT level de-assert delivery mode.
+ */
+typedef enum XAPICINITLEVEL
+{
+ XAPICINITLEVEL_DEASSERT = 0,
+ XAPICINITLEVEL_ASSERT
+} XAPICLEVEL;
+
+/**
+ * xAPIC destination mode.
+ */
+typedef enum XAPICDESTMODE
+{
+ XAPICDESTMODE_PHYSICAL = 0,
+ XAPICDESTMODE_LOGICAL
+} XAPICDESTMODE;
+
+/**
+ * xAPIC delivery mode type.
+ */
+typedef enum XAPICDELIVERYMODE
+{
+ XAPICDELIVERYMODE_FIXED = 0,
+ XAPICDELIVERYMODE_LOWEST_PRIO = 1,
+ XAPICDELIVERYMODE_SMI = 2,
+ XAPICDELIVERYMODE_NMI = 4,
+ XAPICDELIVERYMODE_INIT = 5,
+ XAPICDELIVERYMODE_STARTUP = 6,
+ XAPICDELIVERYMODE_EXTINT = 7
+} XAPICDELIVERYMODE;
+
+/**
+ * xAPIC trigger mode.
+ */
+typedef enum XAPICTRIGGERMODE
+{
+ XAPICTRIGGERMODE_EDGE = 0,
+ XAPICTRIGGERMODE_LEVEL
+} XAPICTRIGGERMODE;
+/** @} */
+
+
+DECLINLINE(uint32_t) ApicRegRead(void *pvBase, uint32_t offReg)
+{
+ return *(const volatile uint32_t *)((uintptr_t)pvBase + offReg);
+}
+
+
+#ifdef IPRT_INCLUDED_asm_amd64_x86_h
+/**
+ * Reads an X2APIC register.
+ *
+ * @param offReg MMIO offset, APIC_REG_XXX.
+ */
+DECLINLINE(uint32_t) ApicX2RegRead32(uint32_t offReg)
+{
+ return ASMRdMsr((offReg >> 4) + MSR_IA32_X2APIC_START);
+}
+#endif
+
+#endif /* !VBOX_INCLUDED_apic_h */
+
diff --git a/include/VBox/apic.mac b/include/VBox/apic.mac
new file mode 100644
index 00000000..db4ba7d7
--- /dev/null
+++ b/include/VBox/apic.mac
@@ -0,0 +1,213 @@
+;; @file
+; X86 (and AMD64) Local APIC registers (VMM,++).
+;
+; Automatically generated by various.sed. DO NOT EDIT!
+;
+
+;
+; Copyright (C) 2010-2022 Oracle and/or its affiliates.
+;
+; This file is part of VirtualBox base platform packages, as
+; available from https://www.virtualbox.org.
+;
+; This program is free software; you can redistribute it and/or
+; modify it under the terms of the GNU General Public License
+; as published by the Free Software Foundation, in version 3 of the
+; License.
+;
+; This program is distributed in the hope that it will be useful, but
+; WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with this program; if not, see <https://www.gnu.org/licenses>.
+;
+; The contents of this file may alternatively be used under the terms
+; of the Common Development and Distribution License Version 1.0
+; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+; in the VirtualBox 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.
+;
+; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+;
+
+%ifndef VBOX_INCLUDED_apic_h
+%define VBOX_INCLUDED_apic_h
+%ifndef RT_WITHOUT_PRAGMA_ONCE
+%endif
+%define APIC_REG_VERSION 0x0030
+%define APIC_REG_VERSION_GET_VER(u32) (u32 & 0xff)
+%define APIC_REG_VERSION_GET_MAX_LVT(u32) ((u32 & 0xff0000) >> 16)
+%define APIC_REG_LVT_LINT0 0x0350
+%define APIC_REG_LVT_LINT1 0x0360
+%define APIC_REG_LVT_ERR 0x0370
+%define APIC_REG_LVT_PC 0x0340
+%define APIC_REG_LVT_THMR 0x0330
+%define APIC_REG_LVT_CMCI 0x02F0
+%define APIC_REG_EILVT0 0x0500
+%define APIC_REG_EILVT1 0x0510
+%define APIC_REG_EILVT2 0x0520
+%define APIC_REG_EILVT3 0x0530
+%define APIC_REG_LVT_MODE_MASK (RT_BIT(8) | RT_BIT(9) | RT_BIT(10))
+%define APIC_REG_LVT_MODE_FIXED 0
+%define APIC_REG_LVT_MODE_NMI RT_BIT(10)
+%define APIC_REG_LVT_MODE_EXTINT (RT_BIT(8) | RT_BIT(9) | RT_BIT(10))
+%define APIC_REG_LVT_PIN_POLARIY RT_BIT(13)
+%define APIC_REG_LVT_REMOTE_IRR RT_BIT(14)
+%define APIC_REG_LVT_LEVEL_TRIGGER RT_BIT(15)
+%define APIC_REG_LVT_MASKED RT_BIT(16)
+%define XAPIC_HARDWARE_VERSION_P4 0x14
+%define XAPIC_MAX_LVT_ENTRIES_P4 6
+%define XAPIC_APIC_ID_BIT_COUNT_P4 8
+%define XAPIC_HARDWARE_VERSION_P6 0x10
+%define XAPIC_MAX_LVT_ENTRIES_P6 4
+%define XAPIC_APIC_ID_BIT_COUNT_P6 4
+%define XAPIC_ILLEGAL_VECTOR_START 0
+%define XAPIC_ILLEGAL_VECTOR_END 15
+%define XAPIC_RSVD_VECTOR_START 16
+%define XAPIC_RSVD_VECTOR_END 31
+ %define XAPIC_ESR_SEND_CHKSUM_ERROR_P6 RT_BIT(0)
+ %define XAPIC_ESR_RECV_CHKSUM_ERROR_P6 RT_BIT(1)
+ %define XAPIC_ESR_SEND_ACCEPT_ERROR_P6 RT_BIT(2)
+ %define XAPIC_ESR_RECV_ACCEPT_ERROR_P6 RT_BIT(3)
+%define XAPIC_ESR_REDIRECTABLE_IPI RT_BIT(4)
+%define XAPIC_ESR_SEND_ILLEGAL_VECTOR RT_BIT(5)
+%define XAPIC_ESR_RECV_ILLEGAL_VECTOR RT_BIT(6)
+%define XAPIC_ESR_ILLEGAL_REG_ADDRESS RT_BIT(7)
+%define XAPIC_ESR_WO_VALID 0x0
+%define XAPIC_TPR_VALID 0xff
+%define XAPIC_TPR_TP 0xf0
+%define XAPIC_TPR_TP_SUBCLASS 0x0f
+%define XAPIC_TPR_GET_TP(a_Tpr) ((a_Tpr) & XAPIC_TPR_TP)
+%define XAPIC_TPR_GET_TP_SUBCLASS(a_Tpr) ((a_Tpr) & XAPIC_TPR_TP_SUBCLASS)
+%define XAPIC_PPR_VALID 0xff
+%define XAPIC_PPR_PP 0xf0
+%define XAPIC_PPR_PP_SUBCLASS 0x0f
+%define XAPIC_PPR_GET_PP(a_Ppr) ((a_Ppr) & XAPIC_PPR_PP)
+%define XAPIC_PPR_GET_PP_SUBCLASS(a_Ppr) ((a_Ppr) & XAPIC_PPR_PP_SUBCLASS)
+%define XAPIC_TIMER_MODE_ONESHOT 0
+%define XAPIC_TIMER_MODE_PERIODIC 1
+%define XAPIC_TIMER_MODE_TSC_DEADLINE 2
+%define XAPIC_LVT_VECTOR 0xff
+%define XAPIC_LVT_GET_VECTOR(a_Lvt) ((a_Lvt) & XAPIC_LVT_VECTOR)
+%define XAPIC_LVT_MASK RT_BIT(16)
+%define XAPIC_LVT_IS_MASKED(a_Lvt) RT_BOOL((a_Lvt) & XAPIC_LVT_MASK)
+%define XAPIC_LVT_TIMER_MODE RT_BIT(17)
+%define XAPIC_LVT_TIMER_TSCDEADLINE RT_BIT(18)
+%define XAPIC_LVT_GET_TIMER_MODE(a_Lvt) (XAPICTIMERMODE)(((a_Lvt) >> 17) & 3)
+%define XAPIC_LVT_DELIVERY_MODE (RT_BIT(8) | RT_BIT(9) | RT_BIT(10))
+%define XAPIC_LVT_GET_DELIVERY_MODE(a_Lvt) (XAPICDELIVERYMODE)(((a_Lvt) >> 8) & 7)
+%define XAPIC_LVT_DELIVERY_STATUS RT_BIT(12)
+%define XAPIC_LVT_TRIGGER_MODE RT_BIT(15)
+%define XAPIC_LVT_GET_TRIGGER_MODE(a_Lvt) (XAPICTRIGGERMODE)(((a_Lvt) >> 15) & 1)
+%define XAPIC_LVT_REMOTE_IRR RT_BIT(14)
+%define XAPIC_LVT_GET_REMOTE_IRR(a_Lvt) (((a_Lvt) >> 14) & 1)
+%define XAPIC_LVT_POLARITY RT_BIT(13)
+%define XAPIC_LVT_GET_POLARITY(a_Lvt) (((a_Lvt) >> 13) & 1)
+%define XAPIC_LVT_COMMON_VALID (XAPIC_LVT_VECTOR | XAPIC_LVT_DELIVERY_STATUS | XAPIC_LVT_MASK)
+%define XAPIC_LVT_CMCI_VALID (XAPIC_LVT_COMMON_VALID | XAPIC_LVT_DELIVERY_MODE)
+%define XAPIC_LVT_TIMER_VALID (XAPIC_LVT_COMMON_VALID | XAPIC_LVT_TIMER_MODE | XAPIC_LVT_TIMER_TSCDEADLINE)
+%define XAPIC_LVT_THERMAL_VALID (XAPIC_LVT_COMMON_VALID | XAPIC_LVT_DELIVERY_MODE)
+%define XAPIC_LVT_PERF_VALID (XAPIC_LVT_COMMON_VALID | XAPIC_LVT_DELIVERY_MODE)
+%define XAPIC_LVT_LINT_VALID ( XAPIC_LVT_COMMON_VALID | XAPIC_LVT_DELIVERY_MODE | XAPIC_LVT_DELIVERY_STATUS \
+ | XAPIC_LVT_POLARITY | XAPIC_LVT_REMOTE_IRR | XAPIC_LVT_TRIGGER_MODE)
+%define XAPIC_LVT_ERROR_VALID (XAPIC_LVT_COMMON_VALID)
+%define XAPIC_SVR_VECTOR 0xff
+%define XAPIC_SVR_SOFTWARE_ENABLE RT_BIT(8)
+%define XAPIC_SVR_SUPRESS_EOI_BROADCAST RT_BIT(12)
+ %define XAPIC_SVR_VALID_P4 (XAPIC_SVR_VECTOR | XAPIC_SVR_SOFTWARE_ENABLE)
+%define XAPIC_DFR_VALID 0xf0000000
+%define XAPIC_DFR_RSVD_MB1 0x0fffffff
+%define XAPIC_DFR_MODEL 0xf
+%define XAPIC_DFR_GET_MODEL(a_uReg) (((a_uReg) >> 28) & XAPIC_DFR_MODEL)
+%define XAPIC_LDR_VALID 0xff000000
+%define X2APIC_LDR_CLUSTER_ID 0xffff0000
+%define X2APIC_LDR_GET_CLUSTER_ID(a_uReg) ((a_uReg) & X2APIC_LDR_CLUSTER_ID)
+%define X2APIC_LDR_LOGICAL_ID 0x0000ffff
+%define XAPIC_LDR_FLAT_LOGICAL_ID 0xff
+%define XAPIC_LDR_CLUSTERED_CLUSTER_ID 0xf0
+%define XAPIC_LDR_CLUSTERED_LOGICAL_ID 0x0f
+%define XAPIC_LDR_CLUSTERED_GET_CLUSTER_ID(a_uReg) ((a_uReg) & XAPIC_LDR_CLUSTERED_CLUSTER_ID)
+%define XAPIC_EOI_WO_VALID 0x0
+%define XAPIC_TIMER_ICR_VALID 0xffffffff
+%define XAPIC_TIMER_DCR_VALID (RT_BIT(0) | RT_BIT(1) | RT_BIT(3))
+%define XAPIC_SELF_IPI_VALID 0xff
+%define XAPIC_SELF_IPI_VECTOR 0xff
+%define XAPIC_SELF_IPI_GET_VECTOR(a_uReg) ((a_uReg) & XAPIC_SELF_IPI_VECTOR)
+%define XAPIC_ICR_LO_VECTOR 0xff
+%define XAPIC_ICR_LO_GET_VECTOR(a_uIcr) ((a_uIcr) & XAPIC_ICR_LO_VECTOR)
+%define XAPIC_ICR_LO_DELIVERY_MODE (RT_BIT(8) | RT_BIT(9) | RT_BIT(10))
+%define XAPIC_ICR_LO_DEST_MODE RT_BIT(11)
+%define XAPIC_ICR_LO_DELIVERY_STATUS RT_BIT(12)
+%define XAPIC_ICR_LO_LEVEL RT_BIT(14)
+%define XAPIC_ICR_TRIGGER_MODE RT_BIT(15)
+%define XAPIC_ICR_LO_DEST_SHORTHAND (RT_BIT(18) | RT_BIT(19))
+%define XAPIC_ICR_LO_WR_VALID ( XAPIC_ICR_LO_VECTOR | XAPIC_ICR_LO_DELIVERY_MODE | XAPIC_ICR_LO_DEST_MODE \
+ | XAPIC_ICR_LO_LEVEL | XAPIC_ICR_TRIGGER_MODE | XAPIC_ICR_LO_DEST_SHORTHAND)
+%define XAPIC_ICR_HI_DEST 0xff000000
+%define XAPIC_ICR_HI_GET_DEST(a_u32IcrHi) (((a_u32IcrHi) >> 24) & XAPIC_ICR_HI_DEST)
+%define XAPIC_ICR_HI_WR_VALID XAPIC_ICR_HI_DEST
+%define X2APIC_ID_BROADCAST_MASK 0xffffffff
+ %define XAPIC_ID_BROADCAST_MASK_P4 0xff
+%define X2APIC_GET_XAPIC_OFF(a_uMsr) ((((a_uMsr) - MSR_IA32_X2APIC_START) << 4) & 0xff0)
+%define XAPIC_GET_X2APIC_MSR(a_offReg) ((((a_offReg) & 0xff0) >> 4) | MSR_IA32_X2APIC_START)
+%define XAPIC_OFF_ID 0x020
+%define XAPIC_OFF_VERSION 0x030
+%define XAPIC_OFF_TPR 0x080
+%define XAPIC_OFF_APR 0x090
+%define XAPIC_OFF_PPR 0x0A0
+%define XAPIC_OFF_EOI 0x0B0
+%define XAPIC_OFF_RRD 0x0C0
+%define XAPIC_OFF_LDR 0x0D0
+%define XAPIC_OFF_DFR 0x0E0
+%define XAPIC_OFF_SVR 0x0F0
+%define XAPIC_OFF_ISR0 0x100
+%define XAPIC_OFF_ISR1 0x110
+%define XAPIC_OFF_ISR2 0x120
+%define XAPIC_OFF_ISR3 0x130
+%define XAPIC_OFF_ISR4 0x140
+%define XAPIC_OFF_ISR5 0x150
+%define XAPIC_OFF_ISR6 0x160
+%define XAPIC_OFF_ISR7 0x170
+%define XAPIC_OFF_TMR0 0x180
+%define XAPIC_OFF_TMR1 0x190
+%define XAPIC_OFF_TMR2 0x1A0
+%define XAPIC_OFF_TMR3 0x1B0
+%define XAPIC_OFF_TMR4 0x1C0
+%define XAPIC_OFF_TMR5 0x1D0
+%define XAPIC_OFF_TMR6 0x1E0
+%define XAPIC_OFF_TMR7 0x1F0
+%define XAPIC_OFF_IRR0 0x200
+%define XAPIC_OFF_IRR1 0x210
+%define XAPIC_OFF_IRR2 0x220
+%define XAPIC_OFF_IRR3 0x230
+%define XAPIC_OFF_IRR4 0x240
+%define XAPIC_OFF_IRR5 0x250
+%define XAPIC_OFF_IRR6 0x260
+%define XAPIC_OFF_IRR7 0x270
+%define XAPIC_OFF_ESR 0x280
+%define XAPIC_OFF_LVT_CMCI 0x2F0
+%define XAPIC_OFF_ICR_LO 0x300
+%define XAPIC_OFF_ICR_HI 0x310
+%define XAPIC_OFF_LVT_TIMER 0x320
+%define XAPIC_OFF_LVT_THERMAL 0x330
+%define XAPIC_OFF_LVT_PERF 0x340
+%define XAPIC_OFF_LVT_LINT0 0x350
+%define XAPIC_OFF_LVT_LINT1 0x360
+%define XAPIC_OFF_LVT_ERROR 0x370
+%define XAPIC_OFF_TIMER_ICR 0x380
+%define XAPIC_OFF_TIMER_CCR 0x390
+%define XAPIC_OFF_TIMER_DCR 0x3E0
+%define X2APIC_OFF_SELF_IPI 0x3F0
+%define XAPIC_OFF_LVT_START XAPIC_OFF_LVT_TIMER
+%define XAPIC_OFF_LVT_END XAPIC_OFF_LVT_ERROR
+%define XAPIC_OFF_LVT_EXT_START XAPIC_OFF_LVT_CMCI
+%define XAPIC_OFF_LVT_EXT_END XAPIC_OFF_LVT_CMCI
+%define XAPIC_OFF_END 0x3F0
+%ifdef IPRT_INCLUDED_asm_amd64_x86_h
+%endif
+%endif
diff --git a/include/VBox/asmdefs.mac b/include/VBox/asmdefs.mac
new file mode 100644
index 00000000..0e167033
--- /dev/null
+++ b/include/VBox/asmdefs.mac
@@ -0,0 +1,785 @@
+;; @file
+; VirtualBox YASM/NASM macros, structs, etc.
+;
+
+;
+; Copyright (C) 2006-2022 Oracle and/or its affiliates.
+;
+; This file is part of VirtualBox base platform packages, as
+; available from https://www.virtualbox.org.
+;
+; This program is free software; you can redistribute it and/or
+; modify it under the terms of the GNU General Public License
+; as published by the Free Software Foundation, in version 3 of the
+; License.
+;
+; This program is distributed in the hope that it will be useful, but
+; WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with this program; if not, see <https://www.gnu.org/licenses>.
+;
+; The contents of this file may alternatively be used under the terms
+; of the Common Development and Distribution License Version 1.0
+; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+; in the VirtualBox 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.
+;
+; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+;
+
+%ifndef ___VBox_asmdefs_mac
+%define ___VBox_asmdefs_mac
+
+;; @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
+
+%include "iprt/asmdefs.mac"
+
+;; @def VBOX_STRICT
+; Enables strict checks in the VBox code.
+; This is enabled by default in all debug builds and when RT_STRICT is enabled.
+%ifndef VBOX_STRICT
+ %ifdef DEBUG
+ %define VBOX_STRICT
+ %endif
+ %ifdef RT_STRICT
+ %define VBOX_STRICT
+ %endif
+%endif
+
+
+%ifndef VBOX_UART_BASE
+ %ifndef IPRT_UART_BASE
+ %define VBOX_UART_BASE 3f8h ; COM1 (see src/VBox/Runtime/common/log/logcom.cpp)
+ %else
+ %define VBOX_UART_BASE IPRT_UART_BASE
+ %endif
+%endif
+%ifndef VBOX_UART_RATE
+ %define VBOX_UART_RATE 12 ; 9600 bps
+%endif
+%ifndef VBOX_UART_PARAMS
+ %define VBOX_UART_PARAMS 00000011b ; 8n1
+%endif
+
+
+;;
+; Initializes the com port to 9600 baud 8n1.
+; al and dx are wasted.
+; @todo comport init doesn't quite work - therefore we no longer use this! :-/
+; @todo test again, it might work now...
+%macro COM_INIT 0
+ push eax
+ push edx
+
+ mov dx, VBOX_UART_BASE + 2
+ mov al, 0
+ out dx, al ; Disable the fifos (old software relies on it)
+
+ mov dx, VBOX_UART_BASE + 3
+ mov al, 80h
+ out dx, al ; make DL register accessible
+
+ mov dx, VBOX_UART_BASE
+ mov ax, VBOX_UART_RATE
+ out dx, al ; write low bps rate divisor
+
+ mov dx, VBOX_UART_BASE+1
+ xchg al, ah
+ out dx, al ; write high bps rate divisor
+
+ mov dx, VBOX_UART_BASE + 3
+ mov al, VBOX_UART_PARAMS
+ out dx, al ; write parameters & lock divisor
+
+ mov dx, VBOX_UART_BASE + 4 ; disconnect the UART from the int line
+ mov al, 0
+ out dx, al
+
+ mov dx, VBOX_UART_BASE + 1 ; disable UART ints
+ out dx, al
+
+ mov dx, VBOX_UART_BASE
+ in al, dx ; clear receiver
+ mov dx, VBOX_UART_BASE + 5
+ in al, dx ; clear line status
+ inc dx
+ in al, dx ; clear modem status
+ mov dx, VBOX_UART_BASE + 2
+ in al, dx ; clear interrupts (IIR)
+
+ pop edx
+ pop eax
+%endmacro
+
+
+;;
+; writes string to comport
+; trashes nothing (uses stack though)
+
+%macro COM32_S_PRINT 1+
+ push esi
+ push ecx
+ push eax
+ mov ecx, edx
+ shl ecx, 16
+
+ call %%stringend
+%%string: db %1
+%%stringend:
+ pop esi
+ mov cx, %%stringend - %%string
+%%status:
+ mov dx, VBOX_UART_BASE + 5
+ in al, dx
+ test al, 20h
+ jz short %%status
+
+ mov al, [esi]
+ mov dx, VBOX_UART_BASE
+ out dx, al
+ inc esi
+ dec cx
+ jnz short %%status
+
+%%status2:
+ mov dx, VBOX_UART_BASE + 5
+ in al, dx
+ test al, 20h
+ jz short %%status2
+
+ shr ecx, 16
+ mov dx, cx
+ pop eax
+ pop ecx
+ pop esi
+%endmacro
+
+%macro COM64_S_PRINT 1+
+ push rsi
+ push rdx
+ push rcx
+ push rax
+
+ jmp %%stringend
+%%string: db %1
+%%stringend:
+ lea rsi, [%%string wrt rip]
+ mov cx, %%stringend - %%string
+%%status:
+ mov dx, VBOX_UART_BASE + 5
+ in al, dx
+ test al, 20h
+ jz short %%status
+
+ mov al, [rsi]
+ mov dx, VBOX_UART_BASE
+ out dx, al
+ inc rsi
+ dec cx
+ jnz short %%status
+
+%%status2:
+ mov dx, VBOX_UART_BASE + 5
+ in al, dx
+ test al, 20h
+ jz short %%status2
+
+ pop rax
+ pop rcx
+ pop rdx
+ pop rsi
+%endmacro
+
+%macro COM_S_PRINT 1+
+%ifdef RT_ARCH_AMD64
+ COM64_S_PRINT %1
+%else
+ COM32_S_PRINT %1
+%endif
+%endmacro
+
+
+;; Write char.
+; trashes esi
+%macro COM_CHAR 1
+ mov esi, eax
+ shl esi, 16
+ mov si, dx
+
+%%status:
+ mov dx, VBOX_UART_BASE + 5
+ in al, dx
+ test al, 20h
+ jz short %%status
+
+ mov al, %1
+ mov dx, VBOX_UART_BASE
+ out dx, al
+
+%%status2:
+ mov dx, VBOX_UART_BASE + 5
+ in al, dx
+ test al, 20h
+ jz short %%status2
+
+ mov dx, si
+ shr esi, 16
+ mov ax, si
+%endmacro
+
+
+;; Write char.
+; trashes nothing (uses stack though)
+
+%macro COM32_S_CHAR 1
+ push eax
+ push edx
+
+%%status:
+ mov dx, VBOX_UART_BASE + 5
+ in al, dx
+ test al, 20h
+ jz short %%status
+
+ mov al, %1
+ mov dx, VBOX_UART_BASE
+ out dx, al
+
+%%status2:
+ mov dx, VBOX_UART_BASE + 5
+ in al, dx
+ test al, 20h
+ jz short %%status2
+
+ pop edx
+ pop eax
+%endmacro
+
+%macro COM64_S_CHAR 1
+ push rax
+ push rdx
+
+%%status:
+ mov dx, VBOX_UART_BASE + 5
+ in al, dx
+ test al, 20h
+ jz short %%status
+
+ mov al, %1
+ mov dx, VBOX_UART_BASE
+ out dx, al
+
+%%status2:
+ mov dx, VBOX_UART_BASE + 5
+ in al, dx
+ test al, 20h
+ jz short %%status2
+
+ pop rdx
+ pop rax
+%endmacro
+
+%macro COM_S_CHAR 1
+%ifdef RT_ARCH_AMD64
+ COM64_S_CHAR %1
+%else
+ COM32_S_CHAR %1
+%endif
+%endmacro
+
+
+;; Writes newline
+; trashes esi
+%macro COM_NEWLINE 0
+ mov esi, eax
+ shl esi, 16
+ mov si, dx
+
+%%status1:
+ mov dx, VBOX_UART_BASE + 5
+ in al, dx
+ test al, 20h
+ jz short %%status1
+
+ mov al, 13
+ mov dx, VBOX_UART_BASE
+ out dx, al
+
+%%status2:
+ mov dx, VBOX_UART_BASE + 5
+ in al, dx
+ test al, 20h
+ jz short %%status2
+
+ mov al, 10
+ mov dx, VBOX_UART_BASE
+ out dx, al
+
+%%status3:
+ mov dx, VBOX_UART_BASE + 5
+ in al, dx
+ test al, 20h
+ jz short %%status3
+
+ mov dx, si
+ shr esi, 16
+ mov ax, si
+%endmacro
+
+
+;; Writes newline
+; trashes nothing (uses stack though)
+
+%macro COM32_S_NEWLINE 0
+ push edx
+ push eax
+
+%%status1:
+ mov dx, VBOX_UART_BASE + 5
+ in al, dx
+ test al, 20h
+ jz short %%status1
+
+ mov al, 13
+ mov dx, VBOX_UART_BASE
+ out dx, al
+
+%%status2:
+ mov dx, VBOX_UART_BASE + 5
+ in al, dx
+ test al, 20h
+ jz short %%status2
+
+ mov al, 10
+ mov dx, VBOX_UART_BASE
+ out dx, al
+
+%%status3:
+ mov dx, VBOX_UART_BASE + 5
+ in al, dx
+ test al, 20h
+ jz short %%status3
+
+ pop eax
+ pop edx
+%endmacro
+
+%macro COM64_S_NEWLINE 0
+ push rdx
+ push rax
+
+%%status1:
+ mov dx, VBOX_UART_BASE + 5
+ in al, dx
+ test al, 20h
+ jz short %%status1
+
+ mov al, 13
+ mov dx, VBOX_UART_BASE
+ out dx, al
+
+%%status2:
+ mov dx, VBOX_UART_BASE + 5
+ in al, dx
+ test al, 20h
+ jz short %%status2
+
+ mov al, 10
+ mov dx, VBOX_UART_BASE
+ out dx, al
+
+%%status3:
+ mov dx, VBOX_UART_BASE + 5
+ in al, dx
+ test al, 20h
+ jz short %%status3
+
+ pop rax
+ pop rdx
+%endmacro
+
+%macro COM_S_NEWLINE 0
+%ifdef RT_ARCH_AMD64
+ COM64_S_NEWLINE
+%else
+ COM32_S_NEWLINE
+%endif
+%endmacro
+
+
+;; Writes a dword from register to com port.
+; trashes esi, edi
+; edi cannot be used as input register
+%macro COM_DWORD_REG 1
+ mov edi, ebx ; save ebx
+ mov ebx, %1 ; get value we're supposed to print
+ mov esi, eax ; save ax
+ shl esi, 16 ; save dx
+ mov si, dx
+
+ mov ah, 8 ; loop counter.
+%%daloop:
+ rol ebx, 4 ; shift next digit to the front
+
+%%status0:
+ mov dx, VBOX_UART_BASE + 5
+ in al, dx
+ test al, 20h
+ jz short %%status0
+
+ mov al, bl ; get next char
+ and al, 0fh
+ cmp al, 10
+ jae short %%hex ; yasm BUG! It sometimes generate a near jump here. YASMCHECK!
+ add al, '0'
+ jmp short %%print
+%%hex:
+ add al, 'a' - 10
+%%print:
+ mov dx, VBOX_UART_BASE
+ out dx, al
+
+ dec ah
+ jnz short %%daloop ; loop
+
+ mov dx, si ; restore dx
+ shr esi, 16
+ mov ax, si ; restore ax
+ mov ebx, edi ; restore ebx
+%endmacro
+
+
+;; Writes a dword from register to com port.
+; trashes nothing (uses stack though)
+
+%macro COM32_S_DWORD_REG 1
+ push edx
+ push eax
+ push ebx
+
+ mov ebx, %1 ; get value we're supposed to print
+
+ mov ah, 8 ; loop counter.
+%%daloop:
+ rol ebx, 4 ; shift next digit to the front
+
+%%status0:
+ mov dx, VBOX_UART_BASE + 5
+ in al, dx
+ test al, 20h
+ jz short %%status0
+
+ mov al, bl ; get next char
+ and al, 0fh
+ cmp al, 10
+ jae short %%hex ; yasm BUG! It sometimes generate a near jump here. YASMCHECK!
+ add al, '0'
+ jmp short %%print
+%%hex:
+ add al, 'a' - 10
+%%print:
+ mov dx, VBOX_UART_BASE
+ out dx, al
+
+ dec ah
+ jnz short %%daloop ; loop
+
+ pop ebx
+ pop eax
+ pop edx
+%endmacro
+
+%macro COM64_S_DWORD_REG 1
+ push rdx
+ push rax
+ push rbx
+
+ mov ebx, %1 ; get value we're supposed to print
+
+ mov ah, 8 ; loop counter.
+%%daloop:
+ rol ebx, 4 ; shift next digit to the front
+
+%%status0:
+ mov dx, VBOX_UART_BASE + 5
+ in al, dx
+ test al, 20h
+ jz short %%status0
+
+ mov al, bl ; get next char
+ and al, 0fh
+ cmp al, 10
+ jae short %%hex ; yasm BUG! It sometimes generate a near jump here. YASMCHECK!
+ add al, '0'
+ jmp short %%print
+%%hex:
+ add al, 'a' - 10
+%%print:
+ mov dx, VBOX_UART_BASE
+ out dx, al
+
+ dec ah
+ jnz short %%daloop ; loop
+
+ pop rbx
+ pop rax
+ pop rdx
+%endmacro
+
+%macro COM_S_DWORD_REG 1
+%ifdef RT_ARCH_AMD64
+ COM64_S_DWORD_REG %1
+%else
+ COM32_S_DWORD_REG %1
+%endif
+%endmacro
+
+
+;; Writes a qword from register to com port.
+; trashes nothing (uses stack though)
+%macro COM64_S_QWORD_REG 1
+ push rdx
+ push rax
+ push rbx
+
+ mov rbx, %1 ; get value we're supposed to print
+
+ mov ah, 16 ; loop counter.
+%%daloop:
+ rol rbx, 4 ; shift next digit to the front
+
+%%status0:
+ mov dx, VBOX_UART_BASE + 5
+ in al, dx
+ test al, 20h
+ jz short %%status0
+
+ mov al, bl ; get next char
+ and al, 0fh
+ cmp al, 10
+ jae short %%hex ; yasm BUG! It sometimes generate a near jump here. YASMCHECK!
+ add al, '0'
+ jmp short %%print
+%%hex:
+ add al, 'a' - 10
+%%print:
+ mov dx, VBOX_UART_BASE
+ out dx, al
+
+ dec ah
+ jnz short %%daloop ; loop
+
+ pop rbx
+ pop rax
+ pop rdx
+%endmacro
+
+
+;; Writes a byte from register to com port.
+; trashes nothing (uses stack though)
+
+%macro COM32_S_BYTE_REG 1
+ push edx
+ push eax
+ push ebx
+
+ mov ebx, %1 ; get value we're supposed to print
+
+ mov ah, 2 ; loop counter.
+ ror ebx, 8 ; shift next digit to the front
+%%daloop:
+ rol ebx, 4 ; shift next digit to the front
+
+%%status0:
+ mov dx, VBOX_UART_BASE + 5
+ in al, dx
+ test al, 20h
+ jz short %%status0
+
+ mov al, bl ; get next char
+ and al, 0fh
+ cmp al, 10
+ jae short %%hex ; yasm BUG! It sometimes generate a near jump here. YASMCHECK!
+ add al, '0'
+ jmp short %%print
+%%hex:
+ add al, 'a' - 10
+%%print:
+ mov dx, VBOX_UART_BASE
+ out dx, al
+
+ dec ah
+ jnz short %%daloop ; loop
+
+ pop ebx
+ pop eax
+ pop edx
+%endmacro
+
+%macro COM64_S_BYTE_REG 1
+ push rdx
+ push rax
+ push rbx
+
+ mov ebx, %1 ; get value we're supposed to print
+
+ mov ah, 2 ; loop counter.
+ ror ebx, 8 ; shift next digit to the front
+%%daloop:
+ rol ebx, 4 ; shift next digit to the front
+
+%%status0:
+ mov dx, VBOX_UART_BASE + 5
+ in al, dx
+ test al, 20h
+ jz short %%status0
+
+ mov al, bl ; get next char
+ and al, 0fh
+ cmp al, 10
+ jae short %%hex ; yasm BUG! It sometimes generate a near jump here. YASMCHECK!
+ add al, '0'
+ jmp short %%print
+%%hex:
+ add al, 'a' - 10
+%%print:
+ mov dx, VBOX_UART_BASE
+ out dx, al
+
+ dec ah
+ jnz short %%daloop ; loop
+
+ pop rbx
+ pop rax
+ pop rdx
+%endmacro
+
+%macro COM_S_BYTE_REG 1
+%ifdef RT_ARCH_AMD64
+ COM64_S_BYTE_REG %1
+%else
+ COM32_S_BYTE_REG %1
+%endif
+%endmacro
+
+
+
+;; Writes a single hex digit from register to com port.
+; trashes nothing (uses stack though)
+
+%macro COM32_S_DIGIT_REG 1
+ push edx
+ push eax
+ push ebx
+
+ mov ebx, %1 ; get value we're supposed to print
+%%status0:
+ mov dx, VBOX_UART_BASE + 5
+ in al, dx
+ test al, 20h
+ jz short %%status0
+
+ mov al, bl ; get next char
+ and al, 0fh
+ cmp al, 10
+ jae short %%hex ; yasm BUG! It sometimes generate a near jump here. YASMCHECK!
+ add al, '0'
+ jmp short %%print
+%%hex:
+ add al, 'a' - 10
+%%print:
+ mov dx, VBOX_UART_BASE
+ out dx, al
+
+ pop ebx
+ pop eax
+ pop edx
+%endmacro
+
+%macro COM64_S_DIGIT_REG 1
+ push rdx
+ push rax
+ push rbx
+
+ mov ebx, %1 ; get value we're supposed to print
+%%status0:
+ mov dx, VBOX_UART_BASE + 5
+ in al, dx
+ test al, 20h
+ jz short %%status0
+
+ mov al, bl ; get next char
+ and al, 0fh
+ cmp al, 10
+ jae short %%hex ; yasm BUG! It sometimes generate a near jump here. YASMCHECK!
+ add al, '0'
+ jmp short %%print
+%%hex:
+ add al, 'a' - 10
+%%print:
+ mov dx, VBOX_UART_BASE
+ out dx, al
+
+ pop rbx
+ pop rax
+ pop rdx
+%endmacro
+
+%macro COM_S_DIGIT_REG 1
+%ifdef RT_ARCH_AMD64
+ COM64_S_DIGIT_REG %1
+%else
+ COM32_S_DIGIT_REG %1
+%endif
+%endmacro
+
+
+;;
+; Loops for a while.
+; ecx is trashed.
+%macro LOOP_A_WHILE 0
+
+ xor ecx, ecx
+ dec ecx
+ shr ecx, 1
+%%looplabel:
+ nop
+ nop
+ nop
+ dec ecx
+ jnz short %%looplabel
+
+%endmacro
+
+
+;;
+; Loops for a short while.
+; ecx is trashed.
+%macro LOOP_SHORT_WHILE 0
+
+ xor ecx, ecx
+ dec ecx
+ shr ecx, 4
+%%looplabel:
+ nop
+ nop
+ dec ecx
+ jnz short %%looplabel
+
+%endmacro
+
+%endif
+
diff --git a/include/VBox/ata.h b/include/VBox/ata.h
new file mode 100644
index 00000000..3a8be20f
--- /dev/null
+++ b/include/VBox/ata.h
@@ -0,0 +1,222 @@
+/* $Id: ata.h $ */
+/** @file
+ * VBox storage devices: ATA/ATAPI declarations
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_ata_h
+#define VBOX_INCLUDED_ata_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+
+/* Bits of HD_STATUS */
+#define ATA_STAT_ERR 0x01
+#define ATA_STAT_INDEX 0x02
+#define ATA_STAT_ECC 0x04 /* Corrected error */
+#define ATA_STAT_DRQ 0x08
+#define ATA_STAT_SEEK 0x10
+#define ATA_STAT_SRV 0x10
+#define ATA_STAT_WRERR 0x20
+#define ATA_STAT_READY 0x40
+#define ATA_STAT_BUSY 0x80
+
+/* Bits for HD_ERROR */
+#define MARK_ERR 0x01 /* Bad address mark */
+#define TRK0_ERR 0x02 /* couldn't find track 0 */
+#define ABRT_ERR 0x04 /* Command aborted */
+#define MCR_ERR 0x08 /* media change request */
+#define ID_ERR 0x10 /* ID field not found */
+#define MC_ERR 0x20 /* media changed */
+#define ECC_ERR 0x40 /* Uncorrectable ECC error */
+#define BBD_ERR 0x80 /* pre-EIDE meaning: block marked bad */
+#define ICRC_ERR 0x80 /* new meaning: CRC error during transfer */
+
+/* Bits for uATARegDevCtl. */
+#define ATA_DEVCTL_DISABLE_IRQ 0x02
+#define ATA_DEVCTL_RESET 0x04
+#define ATA_DEVCTL_HOB 0x80
+
+
+/* ATA/ATAPI Commands (as of ATA/ATAPI-8 draft T13/1699D Revision 3a).
+ * Please keep this in sync with g_apszATACmdNames. */
+typedef enum ATACMD
+{
+ ATA_NOP = 0x00,
+ ATA_CFA_REQUEST_EXTENDED_ERROR_CODE = 0x03,
+ ATA_DATA_SET_MANAGEMENT = 0x06,
+ ATA_DEVICE_RESET = 0x08,
+ ATA_RECALIBRATE = 0x10,
+ ATA_READ_SECTORS = 0x20,
+ ATA_READ_SECTORS_WITHOUT_RETRIES = 0x21,
+ ATA_READ_LONG = 0x22,
+ ATA_READ_LONG_WITHOUT_RETRIES = 0x23,
+ ATA_READ_SECTORS_EXT = 0x24,
+ ATA_READ_DMA_EXT = 0x25,
+ ATA_READ_DMA_QUEUED_EXT = 0x26,
+ ATA_READ_NATIVE_MAX_ADDRESS_EXT = 0x27,
+ ATA_READ_MULTIPLE_EXT = 0x29,
+ ATA_READ_STREAM_DMA_EXT = 0x2a,
+ ATA_READ_STREAM_EXT = 0x2b,
+ ATA_READ_LOG_EXT = 0x2f,
+ ATA_WRITE_SECTORS = 0x30,
+ ATA_WRITE_SECTORS_WITHOUT_RETRIES = 0x31,
+ ATA_WRITE_LONG = 0x32,
+ ATA_WRITE_LONG_WITHOUT_RETRIES = 0x33,
+ ATA_WRITE_SECTORS_EXT = 0x34,
+ ATA_WRITE_DMA_EXT = 0x35,
+ ATA_WRITE_DMA_QUEUED_EXT = 0x36,
+ ATA_SET_MAX_ADDRESS_EXT = 0x37,
+ ATA_CFA_WRITE_SECTORS_WITHOUT_ERASE = 0x38,
+ ATA_WRITE_MULTIPLE_EXT = 0x39,
+ ATA_WRITE_STREAM_DMA_EXT = 0x3a,
+ ATA_WRITE_STREAM_EXT = 0x3b,
+ ATA_WRITE_VERIFY = 0x3c,
+ ATA_WRITE_DMA_FUA_EXT = 0x3d,
+ ATA_WRITE_DMA_QUEUED_FUA_EXT = 0x3e,
+ ATA_WRITE_LOG_EXT = 0x3f,
+ ATA_READ_VERIFY_SECTORS = 0x40,
+ ATA_READ_VERIFY_SECTORS_WITHOUT_RETRIES = 0x41,
+ ATA_READ_VERIFY_SECTORS_EXT = 0x42,
+ ATA_WRITE_UNCORRECTABLE_EXT = 0x45,
+ ATA_READ_LOG_DMA_EXT = 0x47,
+ ATA_FORMAT_TRACK = 0x50,
+ ATA_CONFIGURE_STREAM = 0x51,
+ ATA_WRITE_LOG_DMA_EXT = 0x57,
+ ATA_TRUSTED_RECEIVE = 0x5c,
+ ATA_TRUSTED_RECEIVE_DMA = 0x5d,
+ ATA_TRUSTED_SEND = 0x5e,
+ ATA_TRUSTED_SEND_DMA = 0x5f,
+ ATA_READ_FPDMA_QUEUED = 0x60,
+ ATA_WRITE_FPDMA_QUEUED = 0x61,
+ ATA_SEEK = 0x70,
+ ATA_CFA_TRANSLATE_SECTOR = 0x87,
+ ATA_EXECUTE_DEVICE_DIAGNOSTIC = 0x90,
+ ATA_INITIALIZE_DEVICE_PARAMETERS = 0x91,
+ ATA_DOWNLOAD_MICROCODE = 0x92,
+ ATA_STANDBY_IMMEDIATE__ALT = 0x94,
+ ATA_IDLE_IMMEDIATE__ALT = 0x95,
+ ATA_STANDBY__ALT = 0x96,
+ ATA_IDLE__ALT = 0x97,
+ ATA_CHECK_POWER_MODE__ALT = 0x98,
+ ATA_SLEEP__ALT = 0x99,
+ ATA_PACKET = 0xa0,
+ ATA_IDENTIFY_PACKET_DEVICE = 0xa1,
+ ATA_SERVICE = 0xa2,
+ ATA_SMART = 0xb0,
+ ATA_DEVICE_CONFIGURATION_OVERLAY = 0xb1,
+ ATA_NV_CACHE = 0xb6,
+ ATA_CFA_ERASE_SECTORS = 0xc0,
+ ATA_READ_MULTIPLE = 0xc4,
+ ATA_WRITE_MULTIPLE = 0xc5,
+ ATA_SET_MULTIPLE_MODE = 0xc6,
+ ATA_READ_DMA_QUEUED = 0xc7,
+ ATA_READ_DMA = 0xc8,
+ ATA_READ_DMA_WITHOUT_RETRIES = 0xc9,
+ ATA_WRITE_DMA = 0xca,
+ ATA_WRITE_DMA_WITHOUT_RETRIES = 0xcb,
+ ATA_WRITE_DMA_QUEUED = 0xcc,
+ ATA_CFA_WRITE_MULTIPLE_WITHOUT_ERASE = 0xcd,
+ ATA_WRITE_MULTIPLE_FUA_EXT = 0xce,
+ ATA_CHECK_MEDIA_CARD_TYPE = 0xd1,
+ ATA_GET_MEDIA_STATUS = 0xda,
+ ATA_ACKNOWLEDGE_MEDIA_CHANGE = 0xdb,
+ ATA_BOOT_POST_BOOT = 0xdc,
+ ATA_BOOT_PRE_BOOT = 0xdd,
+ ATA_MEDIA_LOCK = 0xde,
+ ATA_MEDIA_UNLOCK = 0xdf,
+ ATA_STANDBY_IMMEDIATE = 0xe0,
+ ATA_IDLE_IMMEDIATE = 0xe1,
+ ATA_STANDBY = 0xe2,
+ ATA_IDLE = 0xe3,
+ ATA_READ_BUFFER = 0xe4,
+ ATA_CHECK_POWER_MODE = 0xe5,
+ ATA_SLEEP = 0xe6,
+ ATA_FLUSH_CACHE = 0xe7,
+ ATA_WRITE_BUFFER = 0xe8,
+ ATA_WRITE_SAME = 0xe9,
+ ATA_FLUSH_CACHE_EXT = 0xea,
+ ATA_IDENTIFY_DEVICE = 0xec,
+ ATA_MEDIA_EJECT = 0xed,
+ ATA_IDENTIFY_DMA = 0xee,
+ ATA_SET_FEATURES = 0xef,
+ ATA_SECURITY_SET_PASSWORD = 0xf1,
+ ATA_SECURITY_UNLOCK = 0xf2,
+ ATA_SECURITY_ERASE_PREPARE = 0xf3,
+ ATA_SECURITY_ERASE_UNIT = 0xf4,
+ ATA_SECURITY_FREEZE_LOCK = 0xf5,
+ ATA_SECURITY_DISABLE_PASSWORD = 0xf6,
+ ATA_READ_NATIVE_MAX_ADDRESS = 0xf8,
+ ATA_SET_MAX = 0xf9
+} ATACMD;
+
+
+#define ATA_MODE_MDMA 0x20
+#define ATA_MODE_UDMA 0x40
+
+
+#define ATA_TRANSFER_ID(thismode, maxspeed, currmode) \
+ ( ((1 << (maxspeed + 1)) - 1) \
+ | ((((thismode ^ currmode) & 0xf8) == 0) ? 1 << ((currmode & 0x07) + 8) : 0))
+
+/**
+ * Length of the ATA VPD data (without termination)
+ */
+#define ATA_SERIAL_NUMBER_LENGTH 20
+#define ATA_FIRMWARE_REVISION_LENGTH 8
+#define ATA_MODEL_NUMBER_LENGTH 40
+
+/** Mask to get the LBA value from a LBA range. */
+#define ATA_RANGE_LBA_MASK UINT64_C(0xffffffffffff)
+/** Mas to get the length value from a LBA range. */
+#define ATA_RANGE_LENGTH_MASK UINT64_C(0xffff000000000000)
+/** Returns the length of the range in sectors. */
+#define ATA_RANGE_LENGTH_GET(val) (((val) & ATA_RANGE_LENGTH_MASK) >> 48)
+
+/* ATAPI defines */
+
+#define ATAPI_PACKET_SIZE 12
+
+
+#define ATAPI_INT_REASON_CD 0x01 /* 0 = data transfer */
+#define ATAPI_INT_REASON_IO 0x02 /* 1 = transfer to the host */
+#define ATAPI_INT_REASON_REL 0x04
+#define ATAPI_INT_REASON_TAG_MASK 0xf8
+
+#if defined(LOG_ENABLED) && defined(IN_RING3)
+const char * ATACmdText(uint8_t uCmd);
+#endif
+
+#endif /* !VBOX_INCLUDED_ata_h */
+
diff --git a/include/VBox/bios.h b/include/VBox/bios.h
new file mode 100644
index 00000000..9b75ab3f
--- /dev/null
+++ b/include/VBox/bios.h
@@ -0,0 +1,56 @@
+/** @file
+ * X86 (and AMD64) Local APIC registers (VMM,++).
+ *
+ * bios.mac is generated from this file by running 'kmk -f Maintenance.kmk incs'.
+ */
+
+/*
+ * Copyright (C) 2017-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_bios_h
+#define VBOX_INCLUDED_bios_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+/** The BIOS shutdown port.
+ * You write "Shutdown" byte by byte to shutdown the VM.
+ * @sa VBOX_BIOS_OLD_SHUTDOWN_PORT */
+#define VBOX_BIOS_SHUTDOWN_PORT 0x040f
+
+/** The old shutdown port number.
+ * Older versions of VirtualBox uses this as does Bochs.
+ * @sa VBOX_BIOS_SHUTDOWN_PORT */
+#define VBOX_BIOS_OLD_SHUTDOWN_PORT 0x8900
+
+
+#endif /* !VBOX_INCLUDED_bios_h */
+
diff --git a/include/VBox/bios.mac b/include/VBox/bios.mac
new file mode 100644
index 00000000..a38627ad
--- /dev/null
+++ b/include/VBox/bios.mac
@@ -0,0 +1,44 @@
+;; @file
+; X86 (and AMD64) Local APIC registers (VMM,++).
+;
+; Automatically generated by various.sed. DO NOT EDIT!
+;
+
+;
+; Copyright (C) 2017-2022 Oracle and/or its affiliates.
+;
+; This file is part of VirtualBox base platform packages, as
+; available from https://www.virtualbox.org.
+;
+; This program is free software; you can redistribute it and/or
+; modify it under the terms of the GNU General Public License
+; as published by the Free Software Foundation, in version 3 of the
+; License.
+;
+; This program is distributed in the hope that it will be useful, but
+; WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with this program; if not, see <https://www.gnu.org/licenses>.
+;
+; The contents of this file may alternatively be used under the terms
+; of the Common Development and Distribution License Version 1.0
+; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+; in the VirtualBox 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.
+;
+; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+;
+
+%ifndef VBOX_INCLUDED_bios_h
+%define VBOX_INCLUDED_bios_h
+%ifndef RT_WITHOUT_PRAGMA_ONCE
+%endif
+%define VBOX_BIOS_SHUTDOWN_PORT 0x040f
+%define VBOX_BIOS_OLD_SHUTDOWN_PORT 0x8900
+%endif
diff --git a/include/VBox/bioslogo.h b/include/VBox/bioslogo.h
new file mode 100644
index 00000000..4738f1ef
--- /dev/null
+++ b/include/VBox/bioslogo.h
@@ -0,0 +1,108 @@
+/* $Id: bioslogo.h $ */
+/** @file
+ * BiosLogo - The Private BIOS Logo Interface. (DEV)
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_bioslogo_h
+#define VBOX_INCLUDED_bioslogo_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#ifndef VBOX_PC_BIOS
+# include <iprt/types.h>
+# include <iprt/assert.h>
+#endif
+
+/** @defgroup grp_bios_logo The Private BIOS Logo Interface.
+ * @ingroup grp_devdrv
+ * @internal
+ *
+ * @remark All this is currently duplicated in logo.c.
+ *
+ * @{
+ */
+
+/** The extra port which is used to show the BIOS logo. */
+#define LOGO_IO_PORT 0x3b8
+
+/** The BIOS logo fade in/fade out steps. */
+#define LOGO_SHOW_STEPS 16
+
+/** @name The BIOS logo commands.
+ * @{
+ */
+#define LOGO_CMD_NOP 0
+#define LOGO_CMD_SET_OFFSET 0x100
+#define LOGO_CMD_SHOW_BMP 0x200
+/** @} */
+
+/**
+ * PC Bios logo data structure.
+ */
+typedef struct LOGOHDR
+{
+ /** Signature (LOGO_HDR_MAGIC/0x66BB). */
+ uint16_t u16Signature;
+ /** Logo time (msec). */
+ uint16_t u16LogoMillies;
+ /** Fade in - boolean. */
+ uint8_t fu8FadeIn;
+ /** Fade out - boolean. */
+ uint8_t fu8FadeOut;
+ /** Show setup - boolean. */
+ uint8_t fu8ShowBootMenu;
+ /** Reserved / padding. */
+ uint8_t u8Reserved;
+ /** Logo file size. */
+ uint32_t cbLogo;
+} LOGOHDR;
+#ifndef VBOX_PC_BIOS
+AssertCompileSize(LOGOHDR, 12);
+#endif
+/** Pointer to a PC BIOS logo header. */
+typedef LOGOHDR *PLOGOHDR;
+/** Pointer to a const PC BIOS logo header. */
+typedef LOGOHDR const *PCLOGOHDR;
+
+/** The value of the LOGOHDR::u16Signature field. */
+#define LOGO_HDR_MAGIC 0x66BB
+
+/** The value which will switch you the default logo. */
+#define LOGO_DEFAULT_LOGO 0xFFFF
+
+/** @} */
+
+#endif /* !VBOX_INCLUDED_bioslogo_h */
+
diff --git a/include/VBox/cdefs.h b/include/VBox/cdefs.h
new file mode 100644
index 00000000..a77389d6
--- /dev/null
+++ b/include/VBox/cdefs.h
@@ -0,0 +1,493 @@
+/** @file
+ * VirtualBox - Common C and C++ definition.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_cdefs_h
+#define VBOX_INCLUDED_cdefs_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cdefs.h>
+
+
+/** @defgroup grp_vbox_cdefs 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
+
+/** @def VBOX_STRICT_GUEST
+ * Be strict on guest input. This can be overriden on the compiler command line
+ * or per source file by defining VBOX_NO_STRICT_GUEST.
+ *
+ * @sa VBox/assert.h and its ASSERT_GUEST_XXXX macros.
+ */
+#ifndef VBOX_STRICT_GUEST
+# ifdef VBOX_STRICT
+# define VBOX_STRICT_GUEST
+# endif
+#endif
+/** @def VBOX_NO_STRICT_GUEST
+ * Define to override VBOX_STRICT_GUEST, disabling asserting on guest input. */
+#ifdef VBOX_NO_STRICT_GUEST
+# undef VBOX_STRICT_GUEST
+#endif
+
+
+/*
+ * Shut up DOXYGEN warnings and guide it properly thru the code.
+ */
+#ifdef DOXYGEN_RUNNING
+#define VBOX_WITH_STATISTICS
+#define VBOX_STRICT
+#define VBOX_STRICT_GUEST
+#define VBOX_NO_STRICT_GUEST
+#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) DECL_HIDDEN_NOTHROW(type) VBOXCALL
+# else
+# define DISDECL(type) DECL_EXPORT_NOTHROW(type) VBOXCALL
+# endif
+#else
+# define DISDECL(type) DECL_IMPORT_NOTHROW(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) DECL_EXPORT_NOTHROW(type) VBOXCALL
+#else
+# define DBGDECL(type) DECL_IMPORT_NOTHROW(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) DECL_EXPORT_NOTHROW(type) VBOXCALL
+#else
+# define INTNETR3DECL(type) DECL_IMPORT_NOTHROW(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) DECL_EXPORT_NOTHROW(type) VBOXCALL
+#else
+# define INTNETR0DECL(type) DECL_IMPORT_NOTHROW(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) DECL_EXPORT_NOTHROW(type) VBOXCALL
+#else
+# define PCIRAWR3DECL(type) DECL_IMPORT_NOTHROW(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) DECL_EXPORT_NOTHROW(type) VBOXCALL
+#else
+# define PCIRAWR0DECL(type) DECL_IMPORT_NOTHROW(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) DECL_EXPORT_NOTHROW(type) VBOXCALL
+#else
+# define REMR3DECL(type) DECL_IMPORT_NOTHROW(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) DECL_HIDDEN_NOTHROW(type) VBOXCALL
+# else
+# define SUPR3DECL(type) DECL_EXPORT_NOTHROW(type) VBOXCALL
+# endif
+#else
+# ifdef IN_SUP_STATIC
+# define SUPR3DECL(type) DECL_HIDDEN_NOTHROW(type) VBOXCALL
+# else
+# define SUPR3DECL(type) DECL_IMPORT_NOTHROW(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) DECL_HIDDEN_NOTHROW(type) VBOXCALL
+# else
+# define SUPR0DECL(type) DECL_EXPORT_NOTHROW(type) VBOXCALL
+# endif
+#else
+# ifdef IN_SUP_STATIC
+# define SUPR0DECL(type) DECL_HIDDEN_NOTHROW(type) VBOXCALL
+# else
+# define SUPR0DECL(type) DECL_IMPORT_NOTHROW(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) DECL_EXPORT_NOTHROW(type) VBOXCALL
+#else
+# define SUPRCDECL(type) DECL_IMPORT_NOTHROW(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) DECL_EXPORT_NOTHROW(type) VBOXCALL
+#else
+# define SUPDECL(type) DECL_IMPORT_NOTHROW(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) DECL_EXPORT_NOTHROW(type) VBOXCALL
+#else
+# define USBLIB_DECL(type) DECL_IMPORT_NOTHROW(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) DECL_HIDDEN_NOTHROW(type) VBOXCALL
+# else
+# define VMMR3DECL(type) DECL_EXPORT_NOTHROW(type) VBOXCALL
+# endif
+#elif defined(IN_RING3)
+# ifdef IN_VMM_STATIC
+# define VMMR3DECL(type) DECL_HIDDEN_NOTHROW(type) VBOXCALL
+# else
+# define VMMR3DECL(type) DECL_IMPORT_NOTHROW(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) DECL_EXPORT_NOTHROW(type) VBOXCALL
+#elif defined(IN_RING0)
+# define VMMR0DECL(type) DECL_IMPORT_NOTHROW(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) DECL_EXPORT_NOTHROW(type) VBOXCALL
+#elif defined(IN_RC)
+# define VMMRCDECL(type) DECL_IMPORT_NOTHROW(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) DECL_EXPORT_NOTHROW(type) VBOXCALL
+#elif defined(IN_RING0) || defined(IN_RZ)
+# define VMMRZDECL(type) DECL_IMPORT_NOTHROW(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) DECL_HIDDEN_NOTHROW(type) VBOXCALL
+#elif defined(IN_VMM_R3) || defined(IN_VMM_R0) || defined(IN_VMM_RC)
+# define VMMDECL(type) DECL_EXPORT_NOTHROW(type) VBOXCALL
+#else
+# define VMMDECL(type) DECL_IMPORT_NOTHROW(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) DECL_HIDDEN_NOTHROW(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) DECL_HIDDEN_NOTHROW(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) DECL_HIDDEN_NOTHROW(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) DECL_HIDDEN_NOTHROW(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) DECL_HIDDEN_NOTHROW(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) DECL_EXPORT_NOTHROW(type) VBOXCALL
+# endif
+#else
+# define VBOXDDU_DECL(type) DECL_IMPORT_NOTHROW(type) VBOXCALL
+#endif
+
+/** @} */
+
+
+/** @defgroup grp_devdrv Device Emulations and Drivers
+ * @{ */
+/** @} */
+
+#endif /* !VBOX_INCLUDED_cdefs_h */
+
diff --git a/include/VBox/com/AutoLock.h b/include/VBox/com/AutoLock.h
new file mode 100644
index 00000000..344c4a29
--- /dev/null
+++ b/include/VBox/com/AutoLock.h
@@ -0,0 +1,704 @@
+/** @file
+ * MS COM / XPCOM Abstraction Layer - Automatic locks, implementation.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_com_AutoLock_h
+#define VBOX_INCLUDED_com_AutoLock_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+
+
+/** @defgroup grp_com_autolock Automatic Locks
+ * @ingroup grp_com
+ * @{
+ */
+
+// macros for automatic lock validation; these will amount to nothing
+// unless lock validation is enabled for the runtime
+#if defined(RT_LOCK_STRICT)
+# define VBOX_WITH_MAIN_LOCK_VALIDATION
+# define COMMA_LOCKVAL_SRC_POS , RT_SRC_POS
+# define LOCKVAL_SRC_POS_DECL RT_SRC_POS_DECL
+# define COMMA_LOCKVAL_SRC_POS_DECL , RT_SRC_POS_DECL
+# define LOCKVAL_SRC_POS_ARGS RT_SRC_POS_ARGS
+# define COMMA_LOCKVAL_SRC_POS_ARGS , RT_SRC_POS_ARGS
+#else
+# define COMMA_LOCKVAL_SRC_POS
+# define LOCKVAL_SRC_POS_DECL
+# define COMMA_LOCKVAL_SRC_POS_DECL
+# define LOCKVAL_SRC_POS_ARGS
+# define COMMA_LOCKVAL_SRC_POS_ARGS
+#endif
+
+namespace util
+{
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Order classes for lock validation
+//
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * IPRT now has a sophisticated system of run-time locking classes to validate
+ * locking order. Since the Main code is handled by simpler minds, we want
+ * compile-time constants for simplicity, and we'll look up the run-time classes
+ * in AutoLock.cpp transparently. These are passed to the constructors of the
+ * LockHandle classes.
+ */
+enum VBoxLockingClass
+{
+ LOCKCLASS_NONE = 0,
+ LOCKCLASS_WEBSERVICE = 1, // highest order: webservice locks
+ LOCKCLASS_VIRTUALBOXOBJECT = 2, // highest order within Main itself: VirtualBox object lock
+ LOCKCLASS_HOSTOBJECT = 3, // Host object lock
+ LOCKCLASS_LISTOFMACHINES = 4, // list of machines in VirtualBox object
+ LOCKCLASS_MACHINEOBJECT = 5, // Machine object lock
+ LOCKCLASS_SNAPSHOTOBJECT = 6, // snapshot object locks
+ // (the snapshots tree, including the child pointers in Snapshot,
+ // is protected by the normal Machine object lock)
+ LOCKCLASS_MEDIUMQUERY = 7, // lock used to protect Machine::queryInfo
+ LOCKCLASS_LISTOFMEDIA = 8, // list of media (hard disks, DVDs, floppies) in VirtualBox object
+ LOCKCLASS_LISTOFOTHEROBJECTS = 9, // any other list of objects
+ LOCKCLASS_OTHEROBJECT = 10, // any regular object member variable lock
+ LOCKCLASS_PROGRESSLIST = 11, // list of progress objects in VirtualBox; no other object lock
+ // may be held after this!
+ LOCKCLASS_OBJECTSTATE = 12, // object state lock (handled by AutoCaller classes)
+ LOCKCLASS_TRANSLATOR = 13 // translator internal lock
+};
+
+void InitAutoLockSystem();
+
+/**
+ * Check whether the current thread holds any locks in the given class
+ *
+ * @return true if any such locks are held, false otherwise. If the lock
+ * validator is not compiled in, always returns false.
+ * @param lockClass Which lock class to check.
+ */
+bool AutoLockHoldsLocksInClass(VBoxLockingClass lockClass);
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// LockHandle and friends
+//
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Abstract base class for semaphore handles (RWLockHandle and WriteLockHandle).
+ * Don't use this directly, but this implements lock validation for them.
+ */
+class LockHandle
+{
+public:
+ LockHandle()
+ {}
+
+ virtual ~LockHandle()
+ {}
+
+ /**
+ * Returns @c true if the current thread holds a write lock on this
+ * read/write semaphore. Intended for debugging only.
+ */
+ virtual bool isWriteLockOnCurrentThread() const = 0;
+
+ /**
+ * Returns @c true if the current thread holds a read lock on this
+ * read/write semaphore. Intended for debugging only as it isn't always
+ * accurate given @a fWannaHear.
+ */
+ virtual bool isReadLockedOnCurrentThread(bool fWannaHear = true) const = 0;
+
+ /**
+ * Returns the current write lock level of this semaphore. The lock level
+ * determines the number of nested #lockWrite() calls on the given
+ * semaphore handle.
+ *
+ * Note that this call is valid only when the current thread owns a write
+ * lock on the given semaphore handle and will assert otherwise.
+ */
+ virtual uint32_t writeLockLevel() const = 0;
+
+ virtual void lockWrite(LOCKVAL_SRC_POS_DECL) = 0;
+ virtual void unlockWrite() = 0;
+ virtual void lockRead(LOCKVAL_SRC_POS_DECL) = 0;
+ virtual void unlockRead() = 0;
+
+#ifdef VBOX_WITH_MAIN_LOCK_VALIDATION
+ virtual const char* describe() const = 0;
+#endif
+
+private:
+ // prohibit copy + assignment
+ LockHandle(const LockHandle&);
+ LockHandle& operator=(const LockHandle&);
+};
+
+/**
+ * Full-featured read/write semaphore handle implementation.
+ *
+ * This is an auxiliary base class for classes that need full-featured
+ * read/write locking as described in the AutoWriteLock class documentation.
+ * Instances of classes inherited from this class can be passed as arguments to
+ * the AutoWriteLock and AutoReadLock constructors.
+ */
+class RWLockHandle : public LockHandle
+{
+public:
+ RWLockHandle(VBoxLockingClass lockClass);
+ virtual ~RWLockHandle();
+
+ virtual bool isWriteLockOnCurrentThread() const;
+ virtual bool isReadLockedOnCurrentThread(bool fWannaHear = true) const;
+
+ virtual void lockWrite(LOCKVAL_SRC_POS_DECL);
+ virtual void unlockWrite();
+ virtual void lockRead(LOCKVAL_SRC_POS_DECL);
+ virtual void unlockRead();
+
+ virtual uint32_t writeLockLevel() const;
+
+#ifdef VBOX_WITH_MAIN_LOCK_VALIDATION
+ virtual const char* describe() const;
+#endif
+
+private:
+ struct Data;
+ Data *m;
+
+ DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP(RWLockHandle); /* Shuts up MSC warning C4625. */
+};
+
+/**
+ * Write-only semaphore handle implementation.
+ *
+ * This is an auxiliary base class for classes that need write-only (exclusive)
+ * locking and do not need read (shared) locking. This implementation uses a
+ * cheap and fast critical section for both lockWrite() and lockRead() methods
+ * which makes a lockRead() call fully equivalent to the lockWrite() call and
+ * therefore makes it pointless to use instahces of this class with
+ * AutoReadLock instances -- shared locking will not be possible anyway and
+ * any call to lock() will block if there are lock owners on other threads.
+ *
+ * Use with care only when absolutely sure that shared locks are not necessary.
+ */
+class WriteLockHandle : public LockHandle
+{
+public:
+ WriteLockHandle(VBoxLockingClass lockClass);
+ virtual ~WriteLockHandle();
+ virtual bool isWriteLockOnCurrentThread() const;
+ virtual bool isReadLockedOnCurrentThread(bool fWannaHear = true) const;
+
+ virtual void lockWrite(LOCKVAL_SRC_POS_DECL);
+ virtual void unlockWrite();
+ virtual void lockRead(LOCKVAL_SRC_POS_DECL);
+ virtual void unlockRead();
+ virtual uint32_t writeLockLevel() const;
+
+#ifdef VBOX_WITH_MAIN_LOCK_VALIDATION
+ virtual const char* describe() const;
+#endif
+
+private:
+ struct Data;
+ Data *m;
+
+ DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP(WriteLockHandle); /* Shuts up MSC warning C4625. */
+};
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Lockable
+//
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Lockable interface.
+ *
+ * This is an abstract base for classes that need read/write locking. Unlike
+ * RWLockHandle and other classes that makes the read/write semaphore a part of
+ * class data, this class allows subclasses to decide which semaphore handle to
+ * use.
+ */
+class Lockable
+{
+public:
+ virtual ~Lockable() { } /* To make VC++ 2019 happy. */
+
+ /**
+ * Returns a pointer to a LockHandle used by AutoWriteLock/AutoReadLock
+ * for locking. Subclasses are allowed to return @c NULL -- in this case,
+ * the AutoWriteLock/AutoReadLock object constructed using an instance of
+ * such subclass will simply turn into no-op.
+ */
+ virtual LockHandle *lockHandle() const = 0;
+
+ /**
+ * Equivalent to <tt>#lockHandle()->isWriteLockOnCurrentThread()</tt>.
+ * Returns @c false if lockHandle() returns @c NULL.
+ */
+ bool isWriteLockOnCurrentThread()
+ {
+ LockHandle *h = lockHandle();
+ return h ? h->isWriteLockOnCurrentThread() : false;
+ }
+
+ /**
+ * Equivalent to <tt>#lockHandle()->isReadLockedOnCurrentThread()</tt>.
+ * Returns @c false if lockHandle() returns @c NULL.
+ * @note Use with care, simple debug assertions and similar only.
+ */
+ bool isReadLockedOnCurrentThread(bool fWannaHear = true) const
+ {
+ LockHandle *h = lockHandle();
+ return h ? h->isReadLockedOnCurrentThread(fWannaHear) : false;
+ }
+};
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// AutoLockBase
+//
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Abstract base class for all autolocks.
+ *
+ * This cannot be used directly. Use AutoReadLock or AutoWriteLock or AutoMultiWriteLock2/3
+ * which directly and indirectly derive from this.
+ *
+ * In the implementation, the instance data contains a list of lock handles.
+ * The class provides some utility functions to help locking and unlocking
+ * them.
+ */
+
+class AutoLockBase
+{
+protected:
+ AutoLockBase(uint32_t cHandles
+ COMMA_LOCKVAL_SRC_POS_DECL);
+ AutoLockBase(uint32_t cHandles,
+ LockHandle *pHandle
+ COMMA_LOCKVAL_SRC_POS_DECL);
+ virtual ~AutoLockBase();
+
+ struct Data;
+ Data *m;
+
+ virtual void callLockImpl(LockHandle &l) = 0;
+ virtual void callUnlockImpl(LockHandle &l) = 0;
+
+ void callLockOnAllHandles();
+ void callUnlockOnAllHandles();
+
+ void cleanup();
+
+public:
+ void acquire();
+ void release();
+
+private:
+ // prohibit copy + assignment
+ AutoLockBase(const AutoLockBase&);
+ AutoLockBase& operator=(const AutoLockBase&);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// AutoReadLock
+//
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Automatic read lock. Use this with a RWLockHandle to request a read/write
+ * semaphore in read mode. You can also use this with a WriteLockHandle but
+ * that makes little sense since they treat read mode like write mode.
+ *
+ * If constructed with a RWLockHandle or an instance of Lockable (which in
+ * practice means any VirtualBoxBase derivative), it autoamtically requests
+ * the lock in read mode and releases the read lock in the destructor.
+ */
+class AutoReadLock : public AutoLockBase
+{
+public:
+
+ /**
+ * Constructs a null instance that does not manage any read/write
+ * semaphore.
+ *
+ * Note that all method calls on a null instance are no-ops. This allows to
+ * have the code where lock protection can be selected (or omitted) at
+ * runtime.
+ */
+ AutoReadLock(LOCKVAL_SRC_POS_DECL)
+ : AutoLockBase(1,
+ NULL
+ COMMA_LOCKVAL_SRC_POS_ARGS)
+ { }
+
+ /**
+ * Constructs a new instance that will start managing the given read/write
+ * semaphore by requesting a read lock.
+ */
+ AutoReadLock(LockHandle *aHandle
+ COMMA_LOCKVAL_SRC_POS_DECL)
+ : AutoLockBase(1,
+ aHandle
+ COMMA_LOCKVAL_SRC_POS_ARGS)
+ {
+ acquire();
+ }
+
+ /**
+ * Constructs a new instance that will start managing the given read/write
+ * semaphore by requesting a read lock.
+ */
+ AutoReadLock(LockHandle &aHandle
+ COMMA_LOCKVAL_SRC_POS_DECL)
+ : AutoLockBase(1,
+ &aHandle
+ COMMA_LOCKVAL_SRC_POS_ARGS)
+ {
+ acquire();
+ }
+
+ /**
+ * Constructs a new instance that will start managing the given read/write
+ * semaphore by requesting a read lock.
+ */
+ AutoReadLock(const Lockable &aLockable
+ COMMA_LOCKVAL_SRC_POS_DECL)
+ : AutoLockBase(1,
+ aLockable.lockHandle()
+ COMMA_LOCKVAL_SRC_POS_ARGS)
+ {
+ acquire();
+ }
+
+ /**
+ * Constructs a new instance that will start managing the given read/write
+ * semaphore by requesting a read lock.
+ */
+ AutoReadLock(const Lockable *aLockable
+ COMMA_LOCKVAL_SRC_POS_DECL)
+ : AutoLockBase(1,
+ aLockable ? aLockable->lockHandle() : NULL
+ COMMA_LOCKVAL_SRC_POS_ARGS)
+ {
+ acquire();
+ }
+
+ virtual ~AutoReadLock();
+
+ virtual void callLockImpl(LockHandle &l);
+ virtual void callUnlockImpl(LockHandle &l);
+
+private:
+ DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP(AutoReadLock); /* Shuts up MSC warning C4625. */
+};
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// AutoWriteLockBase
+//
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Base class for all auto write locks.
+ *
+ * This cannot be used directly. Use AutoWriteLock or AutoMultiWriteLock2/3
+ * which derive from this.
+ *
+ * It has some utility methods for subclasses.
+ */
+class AutoWriteLockBase : public AutoLockBase
+{
+protected:
+ AutoWriteLockBase(uint32_t cHandles
+ COMMA_LOCKVAL_SRC_POS_DECL)
+ : AutoLockBase(cHandles
+ COMMA_LOCKVAL_SRC_POS_ARGS)
+ { }
+
+ AutoWriteLockBase(uint32_t cHandles,
+ LockHandle *pHandle
+ COMMA_LOCKVAL_SRC_POS_DECL)
+ : AutoLockBase(cHandles,
+ pHandle
+ COMMA_LOCKVAL_SRC_POS_ARGS)
+ { }
+
+ virtual ~AutoWriteLockBase()
+ { }
+
+ virtual void callLockImpl(LockHandle &l);
+ virtual void callUnlockImpl(LockHandle &l);
+
+private:
+ DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP(AutoWriteLockBase); /* Shuts up MSC warning C4625. */
+};
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// AutoWriteLock
+//
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Automatic write lock. Use this with a RWLockHandle to request a read/write
+ * semaphore in write mode. There can only ever be one writer of a read/write
+ * semaphore: while the lock is held in write mode, no other writer or reader
+ * can request the semaphore and will block.
+ *
+ * If constructed with a RWLockHandle or an instance of Lockable (which in
+ * practice means any VirtualBoxBase derivative), it autoamtically requests
+ * the lock in write mode and releases the write lock in the destructor.
+ *
+ * When used with a WriteLockHandle, it requests the semaphore contained therein
+ * exclusively.
+ */
+class AutoWriteLock : public AutoWriteLockBase
+{
+public:
+
+ /**
+ * Constructs a null instance that does not manage any read/write
+ * semaphore.
+ *
+ * Note that all method calls on a null instance are no-ops. This allows to
+ * have the code where lock protection can be selected (or omitted) at
+ * runtime.
+ */
+ AutoWriteLock(LOCKVAL_SRC_POS_DECL)
+ : AutoWriteLockBase(1,
+ NULL
+ COMMA_LOCKVAL_SRC_POS_ARGS)
+ { }
+
+ /**
+ * Constructs a new instance that will start managing the given read/write
+ * semaphore by requesting a write lock.
+ */
+ AutoWriteLock(LockHandle *aHandle
+ COMMA_LOCKVAL_SRC_POS_DECL)
+ : AutoWriteLockBase(1,
+ aHandle
+ COMMA_LOCKVAL_SRC_POS_ARGS)
+ {
+ acquire();
+ }
+
+ /**
+ * Constructs a new instance that will start managing the given read/write
+ * semaphore by requesting a write lock.
+ */
+ AutoWriteLock(LockHandle &aHandle
+ COMMA_LOCKVAL_SRC_POS_DECL)
+ : AutoWriteLockBase(1,
+ &aHandle
+ COMMA_LOCKVAL_SRC_POS_ARGS)
+ {
+ acquire();
+ }
+
+ /**
+ * Constructs a new instance that will start managing the given read/write
+ * semaphore by requesting a write lock.
+ */
+ AutoWriteLock(const Lockable &aLockable
+ COMMA_LOCKVAL_SRC_POS_DECL)
+ : AutoWriteLockBase(1,
+ aLockable.lockHandle()
+ COMMA_LOCKVAL_SRC_POS_ARGS)
+ {
+ acquire();
+ }
+
+ /**
+ * Constructs a new instance that will start managing the given read/write
+ * semaphore by requesting a write lock.
+ */
+ AutoWriteLock(const Lockable *aLockable
+ COMMA_LOCKVAL_SRC_POS_DECL)
+ : AutoWriteLockBase(1,
+ aLockable ? aLockable->lockHandle() : NULL
+ COMMA_LOCKVAL_SRC_POS_ARGS)
+ {
+ acquire();
+ }
+
+ /**
+ * Constructs a new instance that will start managing the given read/write
+ * semaphore by requesting a write lock.
+ */
+ AutoWriteLock(uint32_t cHandles,
+ LockHandle** pHandles
+ COMMA_LOCKVAL_SRC_POS_DECL);
+
+ /**
+ * Release all write locks acquired by this instance through the #acquire()
+ * call and destroys the instance.
+ *
+ * Note that if there there are nested #acquire() calls without the
+ * corresponding number of #release() calls when the destructor is called, it
+ * will assert. This is because having an unbalanced number of nested locks
+ * is a program logic error which must be fixed.
+ */
+ virtual ~AutoWriteLock()
+ {
+ cleanup();
+ }
+
+ void attach(LockHandle *aHandle);
+
+ /** @see attach (LockHandle *) */
+ void attach(LockHandle &aHandle)
+ {
+ attach(&aHandle);
+ }
+
+ /** @see attach (LockHandle *) */
+ void attach(const Lockable &aLockable)
+ {
+ attach(aLockable.lockHandle());
+ }
+
+ /** @see attach (LockHandle *) */
+ void attach(const Lockable *aLockable)
+ {
+ attach(aLockable ? aLockable->lockHandle() : NULL);
+ }
+
+ bool isWriteLockOnCurrentThread() const;
+ uint32_t writeLockLevel() const;
+
+ bool isReadLockedOnCurrentThread(bool fWannaHear = true) const;
+
+private:
+ DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP(AutoWriteLock); /* Shuts up MSC warning C4625. */
+};
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// AutoMultiWriteLock*
+//
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * A multi-write-lock containing two other write locks.
+ *
+ */
+class AutoMultiWriteLock2 : public AutoWriteLockBase
+{
+public:
+ AutoMultiWriteLock2(Lockable *pl1,
+ Lockable *pl2
+ COMMA_LOCKVAL_SRC_POS_DECL);
+ AutoMultiWriteLock2(LockHandle *pl1,
+ LockHandle *pl2
+ COMMA_LOCKVAL_SRC_POS_DECL);
+
+ virtual ~AutoMultiWriteLock2()
+ {
+ cleanup();
+ }
+
+private:
+ DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP(AutoMultiWriteLock2); /* Shuts up MSC warning C4625. */
+};
+
+/**
+ * A multi-write-lock containing three other write locks.
+ *
+ */
+class AutoMultiWriteLock3 : public AutoWriteLockBase
+{
+public:
+ AutoMultiWriteLock3(Lockable *pl1,
+ Lockable *pl2,
+ Lockable *pl3
+ COMMA_LOCKVAL_SRC_POS_DECL);
+ AutoMultiWriteLock3(LockHandle *pl1,
+ LockHandle *pl2,
+ LockHandle *pl3
+ COMMA_LOCKVAL_SRC_POS_DECL);
+
+ virtual ~AutoMultiWriteLock3()
+ {
+ cleanup();
+ }
+
+private:
+ DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP(AutoMultiWriteLock3); /* Shuts up MSC warning C4625. */
+};
+
+/**
+ * A multi-write-lock containing four other write locks.
+ *
+ */
+class AutoMultiWriteLock4 : public AutoWriteLockBase
+{
+public:
+ AutoMultiWriteLock4(Lockable *pl1,
+ Lockable *pl2,
+ Lockable *pl3,
+ Lockable *pl4
+ COMMA_LOCKVAL_SRC_POS_DECL);
+ AutoMultiWriteLock4(LockHandle *pl1,
+ LockHandle *pl2,
+ LockHandle *pl3,
+ LockHandle *pl4
+ COMMA_LOCKVAL_SRC_POS_DECL);
+
+ virtual ~AutoMultiWriteLock4()
+ {
+ cleanup();
+ }
+
+private:
+ DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP(AutoMultiWriteLock4); /* Shuts up MSC warning C4625. */
+};
+
+} /* namespace util */
+
+/** @} */
+
+#endif /* !VBOX_INCLUDED_com_AutoLock_h */
+
+/* vi: set tabstop=4 shiftwidth=4 expandtab: */
diff --git a/include/VBox/com/ErrorInfo.h b/include/VBox/com/ErrorInfo.h
new file mode 100644
index 00000000..fd6e786c
--- /dev/null
+++ b/include/VBox/com/ErrorInfo.h
@@ -0,0 +1,545 @@
+/** @file
+ * MS COM / XPCOM Abstraction Layer - ErrorInfo class declaration.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_com_ErrorInfo_h
+#define VBOX_INCLUDED_com_ErrorInfo_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include "VBox/com/ptr.h"
+#include "VBox/com/string.h"
+#include "VBox/com/Guid.h"
+#include "VBox/com/assert.h"
+
+
+/** @defgroup grp_com_errinfo ErrorInfo Classes
+ * @ingroup grp_com
+ * @{
+ */
+
+COM_STRUCT_OR_CLASS(IProgress);
+COM_STRUCT_OR_CLASS(IVirtualBoxErrorInfo);
+
+namespace com
+{
+
+/**
+ * General discussion:
+ *
+ * In COM all errors are stored on a per thread basis. In general this means
+ * only _one_ active error is possible per thread. A new error will overwrite
+ * the previous one. To prevent this use MultiResult or ErrorInfoKeeper (see
+ * below). The implementations in MSCOM/XPCOM differ slightly, but the details
+ * are handled by this glue code.
+ *
+ * We have different classes which are involved in the error management. I try
+ * to describe them separately to make clear what they are there for.
+ *
+ * ErrorInfo:
+ *
+ * This class is able to retrieve the per thread error and store it into its
+ * member variables. This class can also handle non-VirtualBox errors (like
+ * standard COM errors).
+ *
+ * ProgressErrorInfo:
+ *
+ * This is just a simple wrapper class to get the ErrorInfo stored within an
+ * IProgress object. That is the error which was stored when the progress
+ * object was in use and not an error produced by IProgress itself.
+ *
+ * IVirtualBoxErrorInfo:
+ *
+ * The VirtualBox interface class for accessing error information from Main
+ * clients. This class is also used for storing the error information in the
+ * thread context.
+ *
+ * ErrorInfoKeeper:
+ *
+ * A helper class which stores the current per thread info internally. After
+ * calling methods which may produce other errors it is possible to restore
+ * the previous error and therefore restore the situation before calling the
+ * other methods.
+ *
+ * MultiResult:
+ *
+ * Creating an instance of MultiResult turns error chain saving on. All errors
+ * which follow will be saved in a chain for later access.
+ *
+ * COMErrorInfo (Qt/Gui only):
+ *
+ * The Qt GUI does some additional work for saving errors. Because we create
+ * wrappers for _every_ COM call, it is possible to automatically save the
+ * error info after the execution. This allow some additional info like saving
+ * the callee. Please note that this error info is saved on the client side
+ * and therefore locally to the object instance. See COMBaseWithEI,
+ * COMErrorInfo and the generated COMWrappers.cpp in the GUI.
+ *
+ * Errors itself are set in VirtualBoxBase::setErrorInternal. First a
+ * IVirtualBoxErrorInfo object is created and the given error is saved within.
+ * If MultiResult is active the current per thread error is fetched and
+ * attached to the new created IVirtualBoxErrorInfo object. Next this object is
+ * set as the new per thread error.
+ *
+ * Some general hints:
+ *
+ * - Always use setError, especially when you are working in an asynchronous thread
+ * to indicate an error. Otherwise the error information itself will not make
+ * it into the client.
+ *
+ */
+
+/**
+ * The ErrorInfo class provides a convenient way to retrieve error
+ * information set by the most recent interface method, that was invoked on
+ * the current thread and returned an unsuccessful result code.
+ *
+ * Once the instance of this class is created, the error information for
+ * the current thread is cleared.
+ *
+ * There is no sense to use instances of this class after the last
+ * invoked interface method returns a success.
+ *
+ * The class usage pattern is as follows:
+ * <code>
+ * IFoo *foo;
+ * ...
+ * HRESULT rc = foo->SomeMethod();
+ * if (FAILED(rc)) {
+ * ErrorInfo info(foo);
+ * if (info.isFullAvailable()) {
+ * printf("error message = %ls\n", info.getText().raw());
+ * }
+ * }
+ * </code>
+ *
+ * This class fetches error information using the IErrorInfo interface on
+ * Win32 (MS COM) or the nsIException interface on other platforms (XPCOM),
+ * or the extended IVirtualBoxErrorInfo interface when when it is available
+ * (i.e. a given IErrorInfo or nsIException instance implements it).
+ * Currently, IVirtualBoxErrorInfo is only available for VirtualBox components.
+ *
+ * ErrorInfo::isFullAvailable() and ErrorInfo::isBasicAvailable() determine
+ * what level of error information is available. If #isBasicAvailable()
+ * returns true, it means that only IErrorInfo or nsIException is available as
+ * the source of information (depending on the platform), but not
+ * IVirtualBoxErrorInfo. If #isFullAvailable() returns true, it means that all
+ * three interfaces are available. If both methods return false, no error info
+ * is available at all.
+ *
+ * Here is a table of correspondence between this class methods and
+ * and IErrorInfo/nsIException/IVirtualBoxErrorInfo attributes/methods:
+ *
+ * ErrorInfo IErrorInfo nsIException IVirtualBoxErrorInfo
+ * --------------------------------------------------------------------
+ * getResultCode -- result resultCode
+ * getIID GetGUID -- interfaceID
+ * getComponent GetSource -- component
+ * getText GetDescription message text
+ *
+ * '--' means that this interface does not provide the corresponding portion
+ * of information, therefore it is useless to query it if only
+ * #isBasicAvailable() returns true. As it can be seen, the amount of
+ * information provided at the basic level, depends on the platform
+ * (MS COM or XPCOM).
+ */
+class ErrorInfo
+{
+public:
+
+ /**
+ * Constructs a new, "interfaceless" ErrorInfo instance that takes
+ * the error information possibly set on the current thread by an
+ * interface method of some COM component or by the COM subsystem.
+ *
+ * This constructor is useful, for example, after an unsuccessful attempt
+ * to instantiate (create) a component, so there is no any valid interface
+ * pointer available.
+ */
+ explicit ErrorInfo()
+ : mIsBasicAvailable(false),
+ mIsFullAvailable(false),
+ mResultCode(S_OK),
+ mResultDetail(0),
+ m_pNext(NULL)
+ {
+ init();
+ }
+
+ ErrorInfo(IUnknown *pObj, const GUID &aIID)
+ : mIsBasicAvailable(false),
+ mIsFullAvailable(false),
+ mResultCode(S_OK),
+ mResultDetail(0),
+ m_pNext(NULL)
+ {
+ init(pObj, aIID);
+ }
+
+ /** Specialization for the IVirtualBoxErrorInfo smart pointer */
+ ErrorInfo(const ComPtr<IVirtualBoxErrorInfo> &aPtr)
+ : mIsBasicAvailable(false), mIsFullAvailable(false)
+ , mResultCode(S_OK), mResultDetail(0)
+ { init(aPtr); }
+
+ /**
+ * Constructs a new ErrorInfo instance from the IVirtualBoxErrorInfo
+ * interface pointer. If this pointer is not NULL, both #isFullAvailable()
+ * and #isBasicAvailable() will return |true|.
+ *
+ * @param aInfo pointer to the IVirtualBoxErrorInfo interface that
+ * holds error info to be fetched by this instance
+ */
+ ErrorInfo(IVirtualBoxErrorInfo *aInfo)
+ : mIsBasicAvailable(false), mIsFullAvailable(false)
+ , mResultCode(S_OK), mResultDetail(0)
+ { init(aInfo); }
+
+ ErrorInfo(const ErrorInfo &x)
+ {
+ copyFrom(x);
+ }
+
+ virtual ~ErrorInfo()
+ {
+ cleanup();
+ }
+
+ ErrorInfo& operator=(const ErrorInfo& x)
+ {
+ cleanup();
+ copyFrom(x);
+ return *this;
+ }
+
+ /**
+ * Returns whether basic error info is actually available for the current
+ * thread. If the instance was created from an interface pointer that
+ * supports basic error info and successfully provided it, or if it is an
+ * "interfaceless" instance and there is some error info for the current
+ * thread, the returned value will be true.
+ *
+ * See the class description for details about the basic error info level.
+ *
+ * The appropriate methods of this class provide meaningful info only when
+ * this method returns true (otherwise they simply return NULL-like values).
+ */
+ bool isBasicAvailable() const
+ {
+ return mIsBasicAvailable;
+ }
+
+ /**
+ * Returns whether full error info is actually available for the current
+ * thread. If the instance was created from an interface pointer that
+ * supports full error info and successfully provided it, or if it is an
+ * "interfaceless" instance and there is some error info for the current
+ * thread, the returned value will be true.
+ *
+ * See the class description for details about the full error info level.
+ *
+ * The appropriate methods of this class provide meaningful info only when
+ * this method returns true (otherwise they simply return NULL-like values).
+ */
+ bool isFullAvailable() const
+ {
+ return mIsFullAvailable;
+ }
+
+ /**
+ * Returns the COM result code of the failed operation.
+ */
+ HRESULT getResultCode() const
+ {
+ return mResultCode;
+ }
+
+ /**
+ * Returns the (optional) result detail code of the failed operation.
+ */
+ LONG getResultDetail() const
+ {
+ return mResultDetail;
+ }
+
+ /**
+ * Returns the IID of the interface that defined the error.
+ */
+ const Guid& getInterfaceID() const
+ {
+ return mInterfaceID;
+ }
+
+ /**
+ * Returns the name of the component that generated the error.
+ */
+ const Bstr& getComponent() const
+ {
+ return mComponent;
+ }
+
+ /**
+ * Returns the textual description of the error.
+ */
+ const Bstr& getText() const
+ {
+ return mText;
+ }
+
+ /**
+ * Returns the next error information object or @c NULL if there is none.
+ */
+ const ErrorInfo* getNext() const
+ {
+ return m_pNext;
+ }
+
+ /**
+ * Returns the name of the interface that defined the error
+ */
+ const Bstr& getInterfaceName() const
+ {
+ return mInterfaceName;
+ }
+
+ /**
+ * Returns the IID of the interface that returned the error.
+ *
+ * This method returns a non-null IID only if the instance was created
+ * using template \<class I\> ErrorInfo(I *i) or
+ * template \<class I\> ErrorInfo(const ComPtr<I> &i) constructor.
+ *
+ * @todo broken ErrorInfo documentation links, possibly misleading.
+ */
+ const Guid& getCalleeIID() const
+ {
+ return mCalleeIID;
+ }
+
+ /**
+ * Returns the name of the interface that returned the error
+ *
+ * This method returns a non-null name only if the instance was created
+ * using template \<class I\> ErrorInfo(I *i) or
+ * template \<class I\> ErrorInfo(const ComPtr<I> &i) constructor.
+ *
+ * @todo broken ErrorInfo documentation links, possibly misleading.
+ */
+ const Bstr& getCalleeName() const
+ {
+ return mCalleeName;
+ }
+
+ HRESULT getVirtualBoxErrorInfo(ComPtr<IVirtualBoxErrorInfo> &pVirtualBoxErrorInfo);
+
+ /**
+ * Resets all collected error information. #isBasicAvailable() and
+ * #isFullAvailable will return @c true after this method is called.
+ */
+ void setNull()
+ {
+ cleanup();
+ }
+
+protected:
+
+ ErrorInfo(bool /* aDummy */)
+ : mIsBasicAvailable(false),
+ mIsFullAvailable(false),
+ mResultCode(S_OK),
+ m_pNext(NULL)
+ { }
+
+ void copyFrom(const ErrorInfo &x);
+ void cleanup();
+
+ void init(bool aKeepObj = false);
+ void init(IUnknown *aUnk, const GUID &aIID, bool aKeepObj = false);
+ void init(IVirtualBoxErrorInfo *aInfo);
+
+ bool mIsBasicAvailable : 1;
+ bool mIsFullAvailable : 1;
+
+ HRESULT mResultCode;
+ LONG mResultDetail;
+ Guid mInterfaceID;
+ Bstr mComponent;
+ Bstr mText;
+
+ ErrorInfo *m_pNext;
+
+ Bstr mInterfaceName;
+ Guid mCalleeIID;
+ Bstr mCalleeName;
+
+ ComPtr<IUnknown> mErrorInfo;
+};
+
+/**
+ * A convenience subclass of ErrorInfo that, given an IProgress interface
+ * pointer, reads its errorInfo attribute and uses the returned
+ * IVirtualBoxErrorInfo instance to construct itself.
+ */
+class ProgressErrorInfo : public ErrorInfo
+{
+public:
+
+ /**
+ * Constructs a new instance by fetching error information from the
+ * IProgress interface pointer. If the progress object is not NULL,
+ * its completed attribute is true, resultCode represents a failure,
+ * and the errorInfo attribute returns a valid IVirtualBoxErrorInfo pointer,
+ * both #isFullAvailable() and #isBasicAvailable() will return true.
+ *
+ * @param progress the progress object representing a failed operation
+ */
+ ProgressErrorInfo(IProgress *progress);
+};
+
+/**
+ * A convenience subclass of ErrorInfo that allows to preserve the current
+ * error info. Instances of this class fetch an error info object set on the
+ * current thread and keep a reference to it, which allows to restore it
+ * later using the #restore() method. This is useful to preserve error
+ * information returned by some method for the duration of making another COM
+ * call that may set its own error info and overwrite the existing
+ * one. Preserving and restoring error information makes sense when some
+ * method wants to return error information set by other call as its own
+ * error information while it still needs to make another call before return.
+ *
+ * Instead of calling #restore() explicitly you may let the object destructor
+ * do it for you, if you correctly limit the object's lifetime.
+ *
+ * The usage pattern is:
+ * <code>
+ * rc = foo->method();
+ * if (FAILED(rc))
+ * {
+ * ErrorInfoKeeper eik;
+ * ...
+ * // bar may return error info as well
+ * bar->method();
+ * ...
+ * // no need to call #restore() explicitly here because the eik's
+ * // destructor will restore error info fetched after the failed
+ * // call to foo before returning to the caller
+ * return rc;
+ * }
+ * </code>
+ */
+class ErrorInfoKeeper : public ErrorInfo
+{
+public:
+
+ /**
+ * Constructs a new instance that will fetch the current error info if
+ * @a aIsNull is @c false (by default) or remain uninitialized (null)
+ * otherwise.
+ *
+ * @param aIsNull @c true to prevent fetching error info and leave
+ * the instance uninitialized.
+ */
+ ErrorInfoKeeper(bool aIsNull = false)
+ : ErrorInfo(false), mForgot(aIsNull)
+ {
+ if (!aIsNull)
+ init(true /* aKeepObj */);
+ }
+
+ /**
+ * Constructs a new instance from an ErrorInfo object, to inject a full
+ * error info created elsewhere.
+ *
+ * @param aInfo @c true to prevent fetching error info and leave
+ * the instance uninitialized.
+ */
+ ErrorInfoKeeper(const ErrorInfo &aInfo)
+ : ErrorInfo(false), mForgot(false)
+ {
+ copyFrom(aInfo);
+ }
+
+ /**
+ * Destroys this instance and automatically calls #restore() which will
+ * either restore error info fetched by the constructor or do nothing
+ * if #forget() was called before destruction.
+ */
+ ~ErrorInfoKeeper() { if (!mForgot) restore(); }
+
+ /**
+ * Tries to (re-)fetch error info set on the current thread. On success,
+ * the previous error information, if any, will be overwritten with the
+ * new error information. On failure, or if there is no error information
+ * available, this instance will be reset to null.
+ */
+ void fetch()
+ {
+ setNull();
+ mForgot = false;
+ init(true /* aKeepObj */);
+ }
+
+ /**
+ * Restores error info fetched by the constructor and forgets it
+ * afterwards. Does nothing if the error info was forgotten by #forget().
+ *
+ * @return COM result of the restore operation.
+ */
+ HRESULT restore();
+
+ /**
+ * Forgets error info fetched by the constructor to prevent it from
+ * being restored by #restore() or by the destructor.
+ */
+ void forget() { mForgot = true; }
+
+ /**
+ * Forgets error info fetched by the constructor to prevent it from
+ * being restored by #restore() or by the destructor, and returns the
+ * stored error info object to the caller.
+ */
+ ComPtr<IUnknown> takeError() { mForgot = true; return mErrorInfo; }
+
+private:
+
+ bool mForgot : 1;
+};
+
+} /* namespace com */
+
+/** @} */
+
+#endif /* !VBOX_INCLUDED_com_ErrorInfo_h */
+
diff --git a/include/VBox/com/EventQueue.h b/include/VBox/com/EventQueue.h
new file mode 100644
index 00000000..ef101377
--- /dev/null
+++ b/include/VBox/com/EventQueue.h
@@ -0,0 +1,151 @@
+/* $Id: EventQueue.h $ */
+/** @file
+ * MS COM / XPCOM Abstraction Layer - Event queue class declaration.
+ */
+
+/*
+ * Copyright (C) 2013-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_com_EventQueue_h
+#define VBOX_INCLUDED_com_EventQueue_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <list>
+
+#include <iprt/asm.h>
+#include <iprt/critsect.h>
+
+#include <VBox/com/defs.h>
+#include <VBox/com/assert.h>
+
+
+/** @defgroup grp_com_evtqueue Event Queue Classes
+ * @ingroup grp_com
+ * @{
+ */
+
+namespace com
+{
+
+class EventQueue;
+
+/**
+ * Base class for all events. Intended to be subclassed to introduce new
+ * events and handlers for them.
+ *
+ * Subclasses usually reimplement virtual #handler() (that does nothing by
+ * default) and add new data members describing the event.
+ */
+class Event
+{
+public:
+
+ Event(void) :
+ mRefCount(0) { }
+ virtual ~Event(void) { AssertMsg(!mRefCount,
+ ("Reference count of event=%p not 0 on destruction (is %RU32)\n",
+ this, mRefCount)); }
+public:
+
+ uint32_t AddRef(void) { return ASMAtomicIncU32(&mRefCount); }
+ void Release(void)
+ {
+ Assert(mRefCount);
+ uint32_t cRefs = ASMAtomicDecU32(&mRefCount);
+ if (!cRefs)
+ delete this;
+ }
+
+protected:
+
+ /**
+ * Event handler. Called in the context of the event queue's thread.
+ * Always reimplemented by subclasses
+ *
+ * @return reserved, should be NULL.
+ */
+ virtual void *handler(void) { return NULL; }
+
+ friend class EventQueue;
+
+protected:
+
+ /** The event's reference count. */
+ uint32_t mRefCount;
+};
+
+typedef std::list< Event* > EventQueueList;
+typedef std::list< Event* >::iterator EventQueueListIterator;
+typedef std::list< Event* >::const_iterator EventQueueListIteratorConst;
+
+/**
+ * Simple event queue.
+ */
+class EventQueue
+{
+public:
+
+ EventQueue(void);
+ virtual ~EventQueue(void);
+
+public:
+
+ BOOL postEvent(Event *event);
+ int processEventQueue(RTMSINTERVAL cMsTimeout);
+ int processPendingEvents(size_t cNumEvents);
+ int interruptEventQueueProcessing();
+
+private:
+
+ /** Critical section for serializing access to this
+ * event queue. */
+ RTCRITSECT mCritSect;
+ /** Number of concurrent users. At the moment we
+ * only support one concurrent user at a time when
+ calling processEventQueue(). */
+ uint32_t mUserCnt;
+ /** Event semaphore for getting notified on new
+ * events being handled. */
+ RTSEMEVENT mSemEvent;
+ /** The actual event queue, implemented as a list. */
+ EventQueueList mEvents;
+ /** Shutdown indicator. */
+ bool mShutdown;
+};
+
+} /* namespace com */
+
+/** @} */
+
+#endif /* !VBOX_INCLUDED_com_EventQueue_h */
+
diff --git a/include/VBox/com/Guid.h b/include/VBox/com/Guid.h
new file mode 100644
index 00000000..42663323
--- /dev/null
+++ b/include/VBox/com/Guid.h
@@ -0,0 +1,526 @@
+/* $Id: Guid.h $ */
+/** @file
+ * MS COM / XPCOM Abstraction Layer - Guid class declaration.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_com_Guid_h
+#define VBOX_INCLUDED_com_Guid_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+/* Make sure all the stdint.h macros are included - must come first! */
+#ifndef __STDC_LIMIT_MACROS
+# define __STDC_LIMIT_MACROS
+#endif
+#ifndef __STDC_CONSTANT_MACROS
+# define __STDC_CONSTANT_MACROS
+#endif
+
+#include "VBox/com/string.h"
+
+#include <iprt/uuid.h>
+
+
+/** @defgroup grp_com_guid GUID Class
+ * @ingroup grp_com
+ * @{
+ */
+
+namespace com
+{
+
+typedef enum GuidState_t
+{
+ GUID_ZERO,
+ GUID_NORMAL,
+ GUID_INVALID
+} GuidState_t;
+
+/**
+ * Helper class that represents the UUID type and hides platform-specific
+ * implementation details.
+ */
+class Guid
+{
+public:
+
+ Guid()
+ {
+ clear();
+ }
+
+ Guid(const Guid &that)
+ {
+ mUuid = that.mUuid;
+ mGuidState = that.mGuidState;
+ dbg_refresh();
+ }
+
+ Guid(const RTUUID &that)
+ {
+ mUuid = that;
+ updateState();
+ dbg_refresh();
+ }
+
+ Guid(const GUID &that)
+ {
+ AssertCompileSize(GUID, sizeof(RTUUID));
+ ::memcpy(&mUuid, &that, sizeof(GUID));
+ updateState();
+ dbg_refresh();
+ }
+
+ /**
+ * Construct a GUID from a string.
+ *
+ * @param that The UUID string. Can be with or without the curly
+ * brackets. Empty strings are translated to a zero
+ * GUID, and strings which are not confirming to
+ * valid GUID string representations are marked as
+ * invalid.
+ */
+ Guid(const char *that)
+ {
+ initString(that);
+ }
+
+ /**
+ * Construct a GUID from a BSTR.
+ *
+ * @param that The UUID BSTR. Can be with or without the curly
+ * brackets. Empty strings are translated to a zero
+ * GUID, and strings which are not confirming to
+ * valid GUID string representations are marked as
+ * invalid.
+ */
+ Guid(CBSTR that)
+ {
+ initBSTR(that);
+ }
+
+ /**
+ * Construct a GUID from a Utf8Str.
+ *
+ * @param that The UUID Utf8Str. Can be with or without the curly
+ * brackets. Empty strings are translated to a zero
+ * GUID, and strings which are not confirming to
+ * valid GUID string representations are marked as
+ */
+ Guid(const Utf8Str &that)
+ {
+ initString(that.c_str());
+ }
+
+ /**
+ * Construct a GUID from a RTCString.
+ *
+ * @param that The UUID RTCString. Can be with or without the curly
+ * brackets. Empty strings are translated to a zero
+ * GUID, and strings which are not confirming to
+ * valid GUID string representations are marked as
+ */
+ Guid(const RTCString &that)
+ {
+ initString(that.c_str());
+ }
+
+ /**
+ * Construct a GUID from a Bstr.
+ *
+ * @param that The UUID Bstr. Can be with or without the curly
+ * brackets. Empty strings are translated to a zero
+ * GUID, and strings which are not confirming to
+ * valid GUID string representations are marked as
+ */
+ Guid(const Bstr &that)
+ {
+ initBSTR(that.raw());
+ }
+
+ Guid& operator=(const Guid &that)
+ {
+ mUuid = that.mUuid;
+ mGuidState = that.mGuidState;
+ dbg_refresh();
+ return *this;
+ }
+
+ Guid& operator=(const RTUUID &guid)
+ {
+ mUuid = guid;
+ updateState();
+ dbg_refresh();
+ return *this;
+ }
+
+ Guid& operator=(const GUID &guid)
+ {
+ AssertCompileSize(GUID, sizeof(RTUUID));
+ ::memcpy(&mUuid, &guid, sizeof(GUID));
+ updateState();
+ dbg_refresh();
+ return *this;
+ }
+
+ Guid& operator=(const char *str)
+ {
+ initString(str);
+ return *this;
+ }
+
+ Guid& operator=(CBSTR str)
+ {
+ initBSTR(str);
+ return *this;
+ }
+
+ Guid& operator=(const Utf8Str &str)
+ {
+ return operator=(str.c_str());
+ }
+
+ Guid& operator=(const RTCString &str)
+ {
+ return operator=(str.c_str());
+ }
+
+ Guid& operator=(const Bstr &str)
+ {
+ return operator=(str.raw());
+ }
+
+ void create()
+ {
+ ::RTUuidCreate(&mUuid);
+ mGuidState = GUID_NORMAL;
+ dbg_refresh();
+ }
+
+ void clear()
+ {
+ makeClear();
+ dbg_refresh();
+ }
+
+ /**
+ * Convert the GUID to a string.
+ *
+ * @returns String object containing the formatted GUID.
+ * @throws std::bad_alloc
+ */
+ Utf8Str toString() const
+ {
+ if (mGuidState == GUID_INVALID)
+ {
+ /* What to return in case of wrong Guid */
+ return Utf8Str("00000000-0000-0000-0000-00000000000");
+ }
+
+ char buf[RTUUID_STR_LENGTH];
+ ::memset(buf, '\0', sizeof(buf));
+ ::RTUuidToStr(&mUuid, buf, sizeof(buf));
+
+ return Utf8Str(buf);
+ }
+
+ /**
+ * Like toString, but encloses the returned string in curly brackets.
+ *
+ * @returns String object containing the formatted GUID in curly brackets.
+ * @throws std::bad_alloc
+ */
+ Utf8Str toStringCurly() const
+ {
+ if (mGuidState == GUID_INVALID)
+ {
+ /* What to return in case of wrong Guid */
+ return Utf8Str("{00000000-0000-0000-0000-00000000000}");
+ }
+
+ char buf[RTUUID_STR_LENGTH + 2];
+ ::memset(buf, '\0', sizeof(buf));
+ ::RTUuidToStr(&mUuid, buf + 1, sizeof(buf) - 2);
+ buf[0] = '{';
+ buf[sizeof(buf) - 2] = '}';
+
+ return Utf8Str(buf);
+ }
+
+ /**
+ * Convert the GUID to a string.
+ *
+ * @returns Bstr object containing the formatted GUID.
+ * @throws std::bad_alloc
+ */
+ Bstr toUtf16() const
+ {
+ if (mGuidState == GUID_INVALID)
+ {
+ /* What to return in case of wrong Guid */
+ return Bstr("00000000-0000-0000-0000-00000000000");
+ }
+
+ RTUTF16 buf[RTUUID_STR_LENGTH];
+ ::memset(buf, '\0', sizeof(buf));
+ ::RTUuidToUtf16(&mUuid, buf, RT_ELEMENTS(buf));
+
+ return Bstr(buf);
+ }
+
+ /**
+ * Convert the GUID to a C string.
+ *
+ * @returns See RTUuidToStr.
+ * @param pszUuid The output buffer
+ * @param cbUuid The size of the output buffer. Should be at least
+ * RTUUID_STR_LENGTH in length.
+ */
+ int toString(char *pszUuid, size_t cbUuid) const
+ {
+ return ::RTUuidToStr(mGuidState != GUID_INVALID ? &mUuid : &Empty.mUuid, pszUuid, cbUuid);
+ }
+
+ bool isValid() const
+ {
+ return mGuidState != GUID_INVALID;
+ }
+
+ bool isZero() const
+ {
+ return mGuidState == GUID_ZERO;
+ }
+
+ bool operator==(const Guid &that) const { return ::RTUuidCompare(&mUuid, &that.mUuid) == 0; }
+ bool operator==(const RTUUID &guid) const { return ::RTUuidCompare(&mUuid, &guid) == 0; }
+ bool operator==(const GUID &guid) const { return ::RTUuidCompare(&mUuid, (PRTUUID)&guid) == 0; }
+ bool operator!=(const Guid &that) const { return !operator==(that); }
+ bool operator!=(const GUID &guid) const { return !operator==(guid); }
+ bool operator!=(const RTUUID &guid) const { return !operator==(guid); }
+ bool operator<(const Guid &that) const { return ::RTUuidCompare(&mUuid, &that.mUuid) < 0; }
+ bool operator<(const GUID &guid) const { return ::RTUuidCompare(&mUuid, (PRTUUID)&guid) < 0; }
+ bool operator<(const RTUUID &guid) const { return ::RTUuidCompare(&mUuid, &guid) < 0; }
+
+ /** Compare with a UUID string representation.
+ * @note Not an operator as that could lead to confusion. */
+ bool equalsString(const char *pszUuid2) const { return ::RTUuidCompareStr(&mUuid, pszUuid2) == 0; }
+
+ /**
+ * To directly copy the contents to a GUID, or for passing it as an input
+ * parameter of type (const GUID *), the compiler converts. */
+ const GUID &ref() const
+ {
+ return *(const GUID *)&mUuid;
+ }
+
+ /**
+ * To pass instances to printf-like functions.
+ */
+ PCRTUUID raw() const
+ {
+ return (PCRTUUID)&mUuid;
+ }
+
+#if !defined(VBOX_WITH_XPCOM)
+
+ /** To assign instances to OUT_GUID parameters from within the interface
+ * method. */
+ const Guid &cloneTo(GUID *pguid) const
+ {
+ if (pguid)
+ ::memcpy(pguid, &mUuid, sizeof(GUID));
+ return *this;
+ }
+
+ /** To pass instances as OUT_GUID parameters to interface methods. */
+ GUID *asOutParam()
+ {
+ return (GUID *)&mUuid;
+ }
+
+#else
+
+ /** To assign instances to OUT_GUID parameters from within the
+ * interface method */
+ const Guid &cloneTo(nsID **ppGuid) const
+ {
+ if (ppGuid)
+ *ppGuid = (nsID *)nsMemory::Clone(&mUuid, sizeof(nsID));
+
+ return *this;
+ }
+
+ /**
+ * Internal helper class for asOutParam().
+ *
+ * This takes a GUID reference in the constructor and copies the mUuid from
+ * the method to that instance in its destructor.
+ */
+ class GuidOutParam
+ {
+ GuidOutParam(Guid &guid)
+ : ptr(0),
+ outer(guid)
+ {
+ outer.clear();
+ }
+
+ nsID *ptr;
+ Guid &outer;
+ GuidOutParam(const GuidOutParam &that); // disabled
+ GuidOutParam &operator=(const GuidOutParam &that); // disabled
+ public:
+ operator nsID**() { return &ptr; }
+ ~GuidOutParam()
+ {
+ if (ptr && outer.isZero())
+ {
+ outer = *ptr;
+ outer.dbg_refresh();
+ nsMemory::Free(ptr);
+ }
+ }
+ friend class Guid;
+ };
+
+ /** to pass instances as OUT_GUID parameters to interface methods */
+ GuidOutParam asOutParam() { return GuidOutParam(*this); }
+
+#endif
+
+ /**
+ * Static immutable empty (zero) object. May be used for comparison purposes.
+ */
+ static const Guid Empty;
+
+private:
+ void makeClear()
+ {
+ ::RTUuidClear(&mUuid);
+ mGuidState = GUID_ZERO;
+ }
+
+ void makeInvalid()
+ {
+ ::RTUuidClear(&mUuid);
+ mGuidState = GUID_INVALID;
+ }
+
+ void updateState()
+ {
+ if (::RTUuidIsNull(&mUuid))
+ mGuidState = GUID_ZERO;
+ else
+ mGuidState = GUID_NORMAL;
+ }
+
+ void initString(const char *that)
+ {
+ if (!that || !*that)
+ {
+ makeClear();
+ }
+ else
+ {
+ int rc = ::RTUuidFromStr(&mUuid, that);
+ if (RT_SUCCESS(rc))
+ updateState();
+ else
+ makeInvalid();
+ }
+ dbg_refresh();
+ }
+
+ void initBSTR(CBSTR that)
+ {
+ if (!that || !*that)
+ {
+ makeClear();
+ }
+ else
+ {
+ int rc = ::RTUuidFromUtf16(&mUuid, that);
+ if (RT_SUCCESS(rc))
+ updateState();
+ else
+ makeInvalid();
+ }
+ dbg_refresh();
+ }
+
+ /**
+ * Refresh the debug-only UUID string.
+ *
+ * In debug code, refresh the UUID string representatino for debugging;
+ * must be called every time the internal uuid changes; compiles to nothing
+ * in release code.
+ */
+ inline void dbg_refresh()
+ {
+#ifdef DEBUG
+ switch (mGuidState)
+ {
+ case GUID_ZERO:
+ case GUID_NORMAL:
+ ::RTUuidToStr(&mUuid, mszUuid, RTUUID_STR_LENGTH);
+ break;
+ default:
+ ::memset(mszUuid, '\0', sizeof(mszUuid));
+ ::RTStrCopy(mszUuid, sizeof(mszUuid), "INVALID");
+ break;
+ }
+ m_pcszUUID = mszUuid;
+#endif
+ }
+
+ /** The UUID. */
+ RTUUID mUuid;
+
+ GuidState_t mGuidState;
+
+#ifdef DEBUG
+ /** String representation of mUuid for printing in the debugger. */
+ char mszUuid[RTUUID_STR_LENGTH];
+ /** Another string variant for the debugger, points to szUUID. */
+ const char *m_pcszUUID;
+#endif
+};
+
+} /* namespace com */
+
+/** @} */
+
+#endif /* !VBOX_INCLUDED_com_Guid_h */
+
diff --git a/include/VBox/com/Makefile.kup b/include/VBox/com/Makefile.kup
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/include/VBox/com/Makefile.kup
diff --git a/include/VBox/com/MultiResult.h b/include/VBox/com/MultiResult.h
new file mode 100644
index 00000000..c64ad58c
--- /dev/null
+++ b/include/VBox/com/MultiResult.h
@@ -0,0 +1,278 @@
+/* $Id: MultiResult.h $ */
+/** @file
+ * MS COM / XPCOM Abstraction Layer - MultiResult class declarations.
+ */
+
+/*
+ * Copyright (C) 2008-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_com_MultiResult_h
+#define VBOX_INCLUDED_com_MultiResult_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include "VBox/com/defs.h"
+#include "VBox/com/string.h"
+
+#include <stdarg.h>
+
+/** @defgroup grp_com_mr MultiResult Classes
+ * @ingroup grp_com
+ * @{
+ */
+
+namespace com
+{
+
+/**
+ * "First worst" result type.
+ *
+ * Variables of this class are used instead of HRESULT variables when it is
+ * desirable to memorize the "first worst" result code instead of the last
+ * assigned one. In other words, an assignment operation to a variable of this
+ * class will succeed only if the result code to assign has worse severity. The
+ * following table demonstrate this (the first column lists the previous result
+ * code stored in the variable, the first row lists the new result code being
+ * assigned, 'A' means the assignment will take place, '> S_OK' means a warning
+ * result code):
+ *
+ * {{{
+ * FAILED > S_OK S_OK
+ * FAILED - - -
+ * > S_OK A - -
+ * S_OK A A -
+ *
+ * }}}
+ *
+ * In practice, you will need to use a FWResult variable when you call some COM
+ * method B after another COM method A fails and want to return the result code
+ * of A even if B also fails, but want to return the failed result code of B if
+ * A issues a warning or succeeds.
+ */
+class FWResult
+{
+
+public:
+
+ /**
+ * Constructs a new variable. Note that by default this constructor sets the
+ * result code to E_FAIL to make sure a failure is returned to the caller if
+ * the variable is never assigned another value (which is considered as the
+ * improper use of this class).
+ */
+ FWResult (HRESULT aRC = E_FAIL) : mRC (aRC) {}
+
+ FWResult &operator= (HRESULT aRC)
+ {
+ if ((FAILED (aRC) && !FAILED (mRC)) ||
+ (mRC == S_OK && aRC != S_OK))
+ mRC = aRC;
+
+ return *this;
+ }
+
+ operator HRESULT() const { return mRC; }
+
+ HRESULT *operator&() { return &mRC; }
+
+private:
+
+ HRESULT mRC;
+};
+
+/**
+ * The MultiResult class is a com::FWResult enhancement that also acts as a
+ * switch to turn on multi-error mode for VirtualBoxBase::setError() and
+ * VirtualBoxBase::setWarning() calls.
+ *
+ * When an instance of this class is created, multi-error mode is turned on
+ * for the current thread and the turn-on counter is increased by one. In
+ * multi-error mode, a call to setError() or setWarning() does not
+ * overwrite the current error or warning info object possibly set on the
+ * current thread by other method calls, but instead it stores this old
+ * object in the IVirtualBoxErrorInfo::next attribute of the new error
+ * object being set.
+ *
+ * This way, error/warning objects are stacked together and form a chain of
+ * errors where the most recent error is the first one retrieved by the
+ * calling party, the preceding error is what the
+ * IVirtualBoxErrorInfo::next attribute of the first error points to, and so
+ * on, up to the first error or warning occurred which is the last in the
+ * chain. See IVirtualBoxErrorInfo documentation for more info.
+ *
+ * When the instance of the MultiResult class goes out of scope and gets
+ * destroyed, it automatically decreases the turn-on counter by one. If
+ * the counter drops to zero, multi-error mode for the current thread is
+ * turned off and the thread switches back to single-error mode where every
+ * next error or warning object overwrites the previous one.
+ *
+ * Note that the caller of a COM method uses a non-S_OK result code to
+ * decide if the method has returned an error (negative codes) or a warning
+ * (positive non-zero codes) and will query extended error info only in
+ * these two cases. However, since multi-error mode implies that the method
+ * doesn't return control return to the caller immediately after the first
+ * error or warning but continues its execution, the functionality provided
+ * by the base com::FWResult class becomes very useful because it allows to
+ * preserve the error or the warning result code even if it is later assigned
+ * a S_OK value multiple times. See com::FWResult for details.
+ *
+ * Here is the typical usage pattern:
+ * @code
+ HRESULT Bar::method()
+ {
+ // assume multi-errors are turned off here...
+
+ if (something)
+ {
+ // Turn on multi-error mode and make sure severity is preserved
+ MultiResult rc = foo->method1();
+
+ // return on fatal error, but continue on warning or on success
+ CheckComRCReturnRC (rc);
+
+ rc = foo->method2();
+ // no matter what result, stack it and continue
+
+ // ...
+
+ // return the last worst result code (it will be preserved even if
+ // foo->method2() returns S_OK.
+ return rc;
+ }
+
+ // multi-errors are turned off here again...
+
+ return S_OK;
+ }
+ * @endcode
+ *
+ * @note This class is intended to be instantiated on the stack, therefore
+ * You cannot create them using new(). Although it is possible to copy
+ * instances of MultiResult or return them by value, please never do
+ * that as it is breaks the class semantics (and will assert);
+ */
+class MultiResult : public FWResult
+{
+public:
+
+ /**
+ * @copydoc FWResult::FWResult()
+ */
+ MultiResult (HRESULT aRC = E_FAIL) : FWResult (aRC) { incCounter(); }
+
+ MultiResult (const MultiResult &aThat) : FWResult (aThat)
+ {
+ /* We need this copy constructor only for GCC that wants to have
+ * it in case of expressions like |MultiResult rc = E_FAIL;|. But
+ * we assert since the optimizer should actually avoid the
+ * temporary and call the other constructor directly instead. */
+ AssertFailed();
+ }
+
+ ~MultiResult() { decCounter(); }
+
+ MultiResult &operator= (HRESULT aRC)
+ {
+ FWResult::operator= (aRC);
+ return *this;
+ }
+
+ MultiResult &operator= (const MultiResult & /* aThat */)
+ {
+ /* We need this copy constructor only for GCC that wants to have
+ * it in case of expressions like |MultiResult rc = E_FAIL;|. But
+ * we assert since the optimizer should actually avoid the
+ * temporary and call the other constructor directly instead. */
+ AssertFailed();
+ return *this;
+ }
+
+ /**
+ * Returns true if multi-mode is enabled for the current thread (i.e. at
+ * least one MultiResult instance exists on the stack somewhere).
+ * @return
+ */
+ static bool isMultiEnabled();
+
+private:
+
+ DECLARE_CLS_NEW_DELETE_NOOP(MultiResult);
+
+ static void incCounter();
+ static void decCounter();
+
+ static RTTLS sCounter;
+
+ friend class MultiResultRef;
+};
+
+/**
+ * The MultiResultRef class is equivalent to MultiResult except that it takes
+ * a reference to the existing HRESULT variable instead of maintaining its own
+ * one.
+ */
+class MultiResultRef
+{
+public:
+
+ MultiResultRef (HRESULT &aRC) : mRC (aRC) { MultiResult::incCounter(); }
+
+ ~MultiResultRef() { MultiResult::decCounter(); }
+
+ MultiResultRef &operator= (HRESULT aRC)
+ {
+ /* Copied from FWResult */
+ if ((FAILED (aRC) && !FAILED (mRC)) ||
+ (mRC == S_OK && aRC != S_OK))
+ mRC = aRC;
+
+ return *this;
+ }
+
+ operator HRESULT() const { return mRC; }
+
+ HRESULT *operator&() { return &mRC; }
+
+private:
+
+ DECLARE_CLS_NEW_DELETE_NOOP(MultiResultRef);
+
+ HRESULT &mRC;
+};
+
+
+} /* namespace com */
+
+/** @} */
+
+#endif /* !VBOX_INCLUDED_com_MultiResult_h */
+
diff --git a/include/VBox/com/NativeEventQueue.h b/include/VBox/com/NativeEventQueue.h
new file mode 100644
index 00000000..240acfa3
--- /dev/null
+++ b/include/VBox/com/NativeEventQueue.h
@@ -0,0 +1,161 @@
+/** @file
+ * MS COM / XPCOM Abstraction Layer - Event and EventQueue class declaration.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_com_NativeEventQueue_h
+#define VBOX_INCLUDED_com_NativeEventQueue_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#ifndef VBOX_WITH_XPCOM
+# include <iprt/win/windows.h>
+#else
+# include <nsEventQueueUtils.h>
+#endif
+
+#include <VBox/com/defs.h>
+#include <VBox/com/assert.h>
+
+
+/** @defgroup grp_com_evt Event and EventQueue Classes
+ * @ingroup grp_com
+ * @{
+ */
+
+namespace com
+{
+
+class MainEventQueue;
+
+/**
+ * Base class for all events. Intended to be subclassed to introduce new
+ * events and handlers for them.
+ *
+ * Subclasses usually reimplement virtual #handler() (that does nothing by
+ * default) and add new data members describing the event.
+ */
+class NativeEvent
+{
+public:
+
+ NativeEvent() {}
+ virtual ~NativeEvent() {};
+
+protected:
+
+ /**
+ * Event handler. Called in the context of the event queue's thread.
+ * Always reimplemented by subclasses
+ *
+ * @return reserved, should be NULL.
+ */
+ virtual void *handler() { return NULL; }
+
+ friend class NativeEventQueue;
+};
+
+/**
+ * Simple event queue.
+ *
+ * When using XPCOM, this will map onto the default XPCOM queue for the thread.
+ * So, if a queue is created on the main thread, it automatically processes
+ * XPCOM/IPC events while waiting.
+ *
+ * When using Windows, Darwin and OS/2, this will map onto the native thread
+ * queue/runloop. So, windows messages and what not will be processed while
+ * waiting for events.
+ *
+ * @note It is intentional that there is no way to retrieve arbitrary
+ * events and controlling their processing. There is no use case which
+ * warrants introducing the complexity of platform independent events.
+ */
+class NativeEventQueue
+{
+public:
+
+ NativeEventQueue();
+ virtual ~NativeEventQueue();
+
+ BOOL postEvent(NativeEvent *event);
+ int processEventQueue(RTMSINTERVAL cMsTimeout);
+ int interruptEventQueueProcessing();
+ int getSelectFD();
+ static int init();
+ static int uninit();
+ static NativeEventQueue *getMainEventQueue();
+
+#ifdef VBOX_WITH_XPCOM
+ already_AddRefed<nsIEventQueue> getIEventQueue()
+ {
+ return mEventQ.get();
+ }
+#else
+ static int dispatchMessageOnWindows(MSG const *pMsg, int rc);
+#endif
+
+private:
+ static NativeEventQueue *sMainQueue;
+
+#ifndef VBOX_WITH_XPCOM
+
+ /** The thread which the queue belongs to. */
+ DWORD mThreadId;
+ /** Duplicated thread handle for MsgWaitForMultipleObjects. */
+ HANDLE mhThread;
+
+#else // VBOX_WITH_XPCOM
+
+ /** Whether it was created (and thus needs destroying) or if a queue already
+ * associated with the thread was used. */
+ bool mEQCreated;
+
+ /** Whether event processing should be interrupted. */
+ bool mInterrupted;
+
+ nsCOMPtr <nsIEventQueue> mEventQ;
+ nsCOMPtr <nsIEventQueueService> mEventQService;
+
+ static void *PR_CALLBACK plEventHandler(PLEvent *self);
+ static void PR_CALLBACK plEventDestructor(PLEvent *self);
+
+#endif // VBOX_WITH_XPCOM
+};
+
+} /* namespace com */
+
+/** @} */
+
+#endif /* !VBOX_INCLUDED_com_NativeEventQueue_h */
+
diff --git a/include/VBox/com/VirtualBox.h b/include/VBox/com/VirtualBox.h
new file mode 100644
index 00000000..ffaede31
--- /dev/null
+++ b/include/VBox/com/VirtualBox.h
@@ -0,0 +1,71 @@
+/** @file
+ * MS COM / XPCOM Abstraction Layer - VirtualBox COM Library definitions.
+ *
+ * @note This is the main header file that COM/XPCOM clients include; however,
+ * it is only a wrapper around another platform-dependent include file
+ * that contains the real COM/XPCOM interface declarations. That other
+ * include file is generated automatically at build time from
+ * /src/VBox/Main/idl/VirtualBox.xidl, which contains all the VirtualBox
+ * interfaces; the include file is called VirtualBox.h on Windows hosts
+ * and VirtualBox_XPCOM.h on Linux hosts. The build process places it in
+ * out/{platform}/bin/sdk/include, from where it gets
+ * included by the rest of the VirtualBox code.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_com_VirtualBox_h
+#define VBOX_INCLUDED_com_VirtualBox_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+/* For XPCOM/C++ enum hack checks. */
+#include <iprt/assertcompile.h>
+
+/* Generated VirtualBox COM library definition file. */
+#if !defined(VBOXCOM_NOINCLUDE)
+# if !defined(VBOX_WITH_XPCOM)
+# include <iprt/win/windows.h> /* Included by VirtualBox.h via rpc.h, so include our wrapper with cleanups. */
+# include <VirtualBox.h>
+# else
+# define VBOX_WITH_XPCOM_CPP_ENUM_HACK
+# include <VirtualBox_XPCOM.h>
+# endif
+#endif
+
+/* For convenience. */
+#include "VBox/com/defs.h"
+#include "VBox/com/ptr.h"
+
+#endif /* !VBOX_INCLUDED_com_VirtualBox_h */
+
diff --git a/include/VBox/com/array.h b/include/VBox/com/array.h
new file mode 100644
index 00000000..33fc34e3
--- /dev/null
+++ b/include/VBox/com/array.h
@@ -0,0 +1,1833 @@
+/** @file
+ * MS COM / XPCOM Abstraction Layer - Safe array helper class declaration.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_com_array_h
+#define VBOX_INCLUDED_com_array_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+
+/** @defgroup grp_com_arrays COM/XPCOM Arrays
+ * @ingroup grp_com
+ * @{
+ *
+ * The COM/XPCOM array support layer provides a cross-platform way to pass
+ * arrays to and from COM interface methods and consists of the com::SafeArray
+ * template and a set of ComSafeArray* macros part of which is defined in
+ * VBox/com/defs.h.
+ *
+ * This layer works with interface attributes and method parameters that have
+ * the 'safearray="yes"' attribute in the XIDL definition:
+ * @code
+
+ <interface name="ISomething" ...>
+
+ <method name="testArrays">
+ <param name="inArr" type="long" dir="in" safearray="yes"/>
+ <param name="outArr" type="long" dir="out" safearray="yes"/>
+ <param name="retArr" type="long" dir="return" safearray="yes"/>
+ </method>
+
+ </interface>
+
+ * @endcode
+ *
+ * Methods generated from this and similar definitions are implemented in
+ * component classes using the following declarations:
+ * @code
+
+ STDMETHOD(TestArrays)(ComSafeArrayIn(LONG, aIn),
+ ComSafeArrayOut(LONG, aOut),
+ ComSafeArrayOut(LONG, aRet));
+
+ * @endcode
+ *
+ * And the following function bodies:
+ * @code
+
+ STDMETHODIMP Component::TestArrays(ComSafeArrayIn(LONG, aIn),
+ ComSafeArrayOut(LONG, aOut),
+ ComSafeArrayOut(LONG, aRet))
+ {
+ if (ComSafeArrayInIsNull(aIn))
+ return E_INVALIDARG;
+ if (ComSafeArrayOutIsNull(aOut))
+ return E_POINTER;
+ if (ComSafeArrayOutIsNull(aRet))
+ return E_POINTER;
+
+ // Use SafeArray to access the input array parameter
+
+ com::SafeArray<LONG> in(ComSafeArrayInArg(aIn));
+
+ for (size_t i = 0; i < in.size(); ++ i)
+ LogFlow(("*** in[%u]=%d\n", i, in[i]));
+
+ // Use SafeArray to create the return array (the same technique is used
+ // for output array parameters)
+
+ SafeArray<LONG> ret(in.size() * 2);
+ for (size_t i = 0; i < in.size(); ++ i)
+ {
+ ret[i] = in[i];
+ ret[i + in.size()] = in[i] * 10;
+ }
+
+ ret.detachTo(ComSafeArrayOutArg(aRet));
+
+ return S_OK;
+ }
+
+ * @endcode
+ *
+ * Such methods can be called from the client code using the following pattern:
+ * @code
+
+ ComPtr<ISomething> component;
+
+ // ...
+
+ com::SafeArray<LONG> in(3);
+ in[0] = -1;
+ in[1] = -2;
+ in[2] = -3;
+
+ com::SafeArray<LONG> out;
+ com::SafeArray<LONG> ret;
+
+ HRESULT rc = component->TestArrays(ComSafeArrayAsInParam(in),
+ ComSafeArrayAsOutParam(out),
+ ComSafeArrayAsOutParam(ret));
+
+ if (SUCCEEDED(rc))
+ for (size_t i = 0; i < ret.size(); ++ i)
+ printf("*** ret[%u]=%d\n", i, ret[i]);
+
+ * @endcode
+ *
+ * For interoperability with standard C++ containers, there is a template
+ * constructor that takes such a container as argument and performs a deep copy
+ * of its contents. This can be used in method implementations like this:
+ * @code
+
+ STDMETHODIMP Component::COMGETTER(Values)(ComSafeArrayOut(int, aValues))
+ {
+ // ... assume there is a |std::list<int> mValues| data member
+
+ com::SafeArray<int> values(mValues);
+ values.detachTo(ComSafeArrayOutArg(aValues));
+
+ return S_OK;
+ }
+
+ * @endcode
+ *
+ * The current implementation of the SafeArray layer supports all types normally
+ * allowed in XIDL as array element types (including 'wstring' and 'uuid').
+ * However, 'pointer-to-...' types (e.g. 'long *', 'wstring *') are not
+ * supported and therefore cannot be used as element types.
+ *
+ * Note that for GUID arrays you should use SafeGUIDArray and
+ * SafeConstGUIDArray, customized SafeArray<> specializations.
+ *
+ * Also note that in order to pass input BSTR array parameters declared
+ * using the ComSafeArrayIn(IN_BSTR, aParam) macro to the SafeArray<>
+ * constructor using the ComSafeArrayInArg() macro, you should use IN_BSTR
+ * as the SafeArray<> template argument, not just BSTR.
+ *
+ * Arrays of interface pointers are also supported but they require to use a
+ * special SafeArray implementation, com::SafeIfacePointer, which takes the
+ * interface class name as a template argument (e.g.
+ * com::SafeIfacePointer\<IUnknown\>). This implementation functions
+ * identically to com::SafeArray.
+ */
+
+#ifdef VBOX_WITH_XPCOM
+# include <nsMemory.h>
+#endif
+
+#include "VBox/com/defs.h"
+
+#if RT_GNUC_PREREQ(4, 6) || (defined(_MSC_VER) && (_MSC_VER >= 1600))
+/** @def VBOX_WITH_TYPE_TRAITS
+ * Type traits are a C++ 11 feature, so not available everywhere (yet).
+ * Only GCC 4.6 or newer and MSVC++ 16.0 (Visual Studio 2010) or newer.
+ */
+# define VBOX_WITH_TYPE_TRAITS
+#endif
+
+#ifdef VBOX_WITH_TYPE_TRAITS
+# include <type_traits>
+#endif
+
+#include "VBox/com/ptr.h"
+#include "VBox/com/assert.h"
+#include "iprt/cpp/list.h"
+
+/** @def ComSafeArrayAsInParam
+ * Wraps the given com::SafeArray instance to generate an expression that is
+ * suitable for passing it to functions that take input safearray parameters
+ * declared using the ComSafeArrayIn macro.
+ *
+ * @param aArray com::SafeArray instance to pass as an input parameter.
+ */
+
+/** @def ComSafeArrayAsOutParam
+ * Wraps the given com::SafeArray instance to generate an expression that is
+ * suitable for passing it to functions that take output safearray parameters
+ * declared using the ComSafeArrayOut macro.
+ *
+ * @param aArray com::SafeArray instance to pass as an output parameter.
+ */
+
+/** @def ComSafeArrayNullInParam
+ * Helper for passing a NULL array parameter to a COM / XPCOM method.
+ */
+
+#ifdef VBOX_WITH_XPCOM
+
+# define ComSafeArrayAsInParam(aArray) \
+ (PRUint32)(aArray).size(), (aArray).__asInParam_Arr((aArray).raw())
+
+# define ComSafeArrayAsOutParam(aArray) \
+ (aArray).__asOutParam_Size(), (aArray).__asOutParam_Arr()
+
+# define ComSafeArrayNullInParam() 0, NULL
+
+#else /* !VBOX_WITH_XPCOM */
+
+# define ComSafeArrayAsInParam(aArray) (aArray).__asInParam()
+
+# define ComSafeArrayAsOutParam(aArray) (aArray).__asOutParam()
+
+# define ComSafeArrayNullInParam() (NULL)
+
+#endif /* !VBOX_WITH_XPCOM */
+
+/**
+ *
+ */
+namespace com
+{
+
+/** Used for dummy element access in com::SafeArray, avoiding crashes. */
+extern const char Zeroes[16];
+
+
+#ifdef VBOX_WITH_XPCOM
+
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Provides various helpers for SafeArray.
+ *
+ * @param T Type of array elements.
+ */
+template<typename T>
+struct SafeArrayTraits
+{
+protected:
+
+ /** Initializes memory for aElem. */
+ static void Init(T &aElem) { aElem = (T)0; }
+
+ /** Initializes memory occupied by aElem. */
+ static void Uninit(T &aElem) { RT_NOREF(aElem); }
+
+ /** Creates a deep copy of aFrom and stores it in aTo. */
+ static void Copy(const T &aFrom, T &aTo) { aTo = aFrom; }
+
+public:
+
+ /* Magic to workaround strict rules of par. 4.4.4 of the C++ standard (that
+ * in particular forbid casts of 'char **' to 'const char **'). Then initial
+ * reason for this magic is that XPIDL declares input strings
+ * (char/PRUnichar pointers) as const but doesn't do so for pointers to
+ * arrays. */
+ static T *__asInParam_Arr(T *aArr) { return aArr; }
+ static T *__asInParam_Arr(const T *aArr) { return const_cast<T *>(aArr); }
+};
+
+template<typename T>
+struct SafeArrayTraits<T *>
+{
+ // Arbitrary pointers are not supported
+};
+
+template<>
+struct SafeArrayTraits<PRUnichar *>
+{
+protected:
+
+ static void Init(PRUnichar * &aElem) { aElem = NULL; }
+
+ static void Uninit(PRUnichar * &aElem)
+ {
+ if (aElem)
+ {
+ ::SysFreeString(aElem);
+ aElem = NULL;
+ }
+ }
+
+ static void Copy(const PRUnichar * aFrom, PRUnichar * &aTo)
+ {
+ AssertCompile(sizeof(PRUnichar) == sizeof(OLECHAR));
+ aTo = aFrom ? ::SysAllocString((const OLECHAR *)aFrom) : NULL;
+ }
+
+public:
+
+ /* Magic to workaround strict rules of par. 4.4.4 of the C++ standard */
+ static const PRUnichar **__asInParam_Arr(PRUnichar **aArr)
+ {
+ return const_cast<const PRUnichar **>(aArr);
+ }
+ static const PRUnichar **__asInParam_Arr(const PRUnichar **aArr) { return aArr; }
+};
+
+template<>
+struct SafeArrayTraits<const PRUnichar *>
+{
+protected:
+
+ static void Init(const PRUnichar * &aElem) { aElem = NULL; }
+ static void Uninit(const PRUnichar * &aElem)
+ {
+ if (aElem)
+ {
+ ::SysFreeString(const_cast<PRUnichar *>(aElem));
+ aElem = NULL;
+ }
+ }
+
+ static void Copy(const PRUnichar * aFrom, const PRUnichar * &aTo)
+ {
+ AssertCompile(sizeof(PRUnichar) == sizeof(OLECHAR));
+ aTo = aFrom ? ::SysAllocString((const OLECHAR *)aFrom) : NULL;
+ }
+
+public:
+
+ /* Magic to workaround strict rules of par. 4.4.4 of the C++ standard */
+ static const PRUnichar **__asInParam_Arr(const PRUnichar **aArr) { return aArr; }
+};
+
+template<>
+struct SafeArrayTraits<nsID *>
+{
+protected:
+
+ static void Init(nsID * &aElem) { aElem = NULL; }
+
+ static void Uninit(nsID * &aElem)
+ {
+ if (aElem)
+ {
+ ::nsMemory::Free(aElem);
+ aElem = NULL;
+ }
+ }
+
+ static void Copy(const nsID * aFrom, nsID * &aTo)
+ {
+ if (aFrom)
+ {
+ aTo = (nsID *) ::nsMemory::Alloc(sizeof(nsID));
+ if (aTo)
+ *aTo = *aFrom;
+ }
+ else
+ aTo = NULL;
+ }
+
+ /* This specification is also reused for SafeConstGUIDArray, so provide a
+ * no-op Init() and Uninit() which are necessary for SafeArray<> but should
+ * be never called in context of SafeConstGUIDArray. */
+
+ static void Init(const nsID * &aElem) { NOREF(aElem); AssertFailed(); }
+ static void Uninit(const nsID * &aElem) { NOREF(aElem); AssertFailed(); }
+
+public:
+
+ /** Magic to workaround strict rules of par. 4.4.4 of the C++ standard. */
+ static const nsID **__asInParam_Arr(nsID **aArr)
+ {
+ return const_cast<const nsID **>(aArr);
+ }
+ static const nsID **__asInParam_Arr(const nsID **aArr) { return aArr; }
+};
+
+#else /* !VBOX_WITH_XPCOM */
+
+////////////////////////////////////////////////////////////////////////////////
+
+struct SafeArrayTraitsBase
+{
+protected:
+
+ static SAFEARRAY *CreateSafeArray(VARTYPE aVarType, SAFEARRAYBOUND *aBound)
+ { return SafeArrayCreate(aVarType, 1, aBound); }
+};
+
+/**
+ * Provides various helpers for SafeArray.
+ *
+ * @param T Type of array elements.
+ *
+ * Specializations of this template must provide the following methods:
+ *
+ // Returns the VARTYPE of COM SafeArray elements to be used for T
+ static VARTYPE VarType();
+
+ // Returns the number of VarType() elements necessary for aSize
+ // elements of T
+ static ULONG VarCount(size_t aSize);
+
+ // Returns the number of elements of T that fit into the given number of
+ // VarType() elements (opposite to VarCount(size_t aSize)).
+ static size_t Size(ULONG aVarCount);
+
+ // Creates a deep copy of aFrom and stores it in aTo
+ static void Copy(ULONG aFrom, ULONG &aTo);
+ */
+template<typename T>
+struct SafeArrayTraits : public SafeArrayTraitsBase
+{
+protected:
+
+ // Arbitrary types are treated as passed by value and each value is
+ // represented by a number of VT_Ix type elements where VT_Ix has the
+ // biggest possible bitness necessary to represent T w/o a gap. COM enums
+ // fall into this category.
+
+ static VARTYPE VarType()
+ {
+#ifdef VBOX_WITH_TYPE_TRAITS
+ if ( std::is_integral<T>::value
+ && !std::is_signed<T>::value)
+ {
+ if (sizeof(T) % 8 == 0) return VT_UI8;
+ if (sizeof(T) % 4 == 0) return VT_UI4;
+ if (sizeof(T) % 2 == 0) return VT_UI2;
+ return VT_UI1;
+ }
+#endif
+ if (sizeof(T) % 8 == 0) return VT_I8;
+ if (sizeof(T) % 4 == 0) return VT_I4;
+ if (sizeof(T) % 2 == 0) return VT_I2;
+ return VT_I1;
+ }
+
+ /*
+ * Fallback method in case type traits (VBOX_WITH_TYPE_TRAITS)
+ * are not available. Always returns unsigned types.
+ */
+ static VARTYPE VarTypeUnsigned()
+ {
+ if (sizeof(T) % 8 == 0) return VT_UI8;
+ if (sizeof(T) % 4 == 0) return VT_UI4;
+ if (sizeof(T) % 2 == 0) return VT_UI2;
+ return VT_UI1;
+ }
+
+ static ULONG VarCount(size_t aSize)
+ {
+ if (sizeof(T) % 8 == 0) return (ULONG)((sizeof(T) / 8) * aSize);
+ if (sizeof(T) % 4 == 0) return (ULONG)((sizeof(T) / 4) * aSize);
+ if (sizeof(T) % 2 == 0) return (ULONG)((sizeof(T) / 2) * aSize);
+ return (ULONG)(sizeof(T) * aSize);
+ }
+
+ static size_t Size(ULONG aVarCount)
+ {
+ if (sizeof(T) % 8 == 0) return (size_t)(aVarCount * 8) / sizeof(T);
+ if (sizeof(T) % 4 == 0) return (size_t)(aVarCount * 4) / sizeof(T);
+ if (sizeof(T) % 2 == 0) return (size_t)(aVarCount * 2) / sizeof(T);
+ return (size_t) aVarCount / sizeof(T);
+ }
+
+ static void Copy(T aFrom, T &aTo) { aTo = aFrom; }
+};
+
+template<typename T>
+struct SafeArrayTraits<T *>
+{
+ // Arbitrary pointer types are not supported
+};
+
+/* Although the generic SafeArrayTraits template would work for all integers,
+ * we specialize it for some of them in order to use the correct VT_ type */
+
+template<>
+struct SafeArrayTraits<LONG> : public SafeArrayTraitsBase
+{
+protected:
+
+ static VARTYPE VarType() { return VT_I4; }
+ static ULONG VarCount(size_t aSize) { return (ULONG)aSize; }
+ static size_t Size(ULONG aVarCount) { return (size_t)aVarCount; }
+
+ static void Copy(LONG aFrom, LONG &aTo) { aTo = aFrom; }
+};
+
+template<>
+struct SafeArrayTraits<ULONG> : public SafeArrayTraitsBase
+{
+protected:
+
+ static VARTYPE VarType() { return VT_UI4; }
+ static ULONG VarCount(size_t aSize) { return (ULONG)aSize; }
+ static size_t Size(ULONG aVarCount) { return (size_t)aVarCount; }
+
+ static void Copy(ULONG aFrom, ULONG &aTo) { aTo = aFrom; }
+};
+
+template<>
+struct SafeArrayTraits<LONG64> : public SafeArrayTraitsBase
+{
+protected:
+
+ static VARTYPE VarType() { return VT_I8; }
+ static ULONG VarCount(size_t aSize) { return (ULONG)aSize; }
+ static size_t Size(ULONG aVarCount) { return (size_t)aVarCount; }
+
+ static void Copy(LONG64 aFrom, LONG64 &aTo) { aTo = aFrom; }
+};
+
+template<>
+struct SafeArrayTraits<ULONG64> : public SafeArrayTraitsBase
+{
+protected:
+
+ static VARTYPE VarType() { return VT_UI8; }
+ static ULONG VarCount(size_t aSize) { return (ULONG)aSize; }
+ static size_t Size(ULONG aVarCount) { return (size_t)aVarCount; }
+
+ static void Copy(ULONG64 aFrom, ULONG64 &aTo) { aTo = aFrom; }
+};
+
+template<>
+struct SafeArrayTraits<BSTR> : public SafeArrayTraitsBase
+{
+protected:
+
+ static VARTYPE VarType() { return VT_BSTR; }
+ static ULONG VarCount(size_t aSize) { return (ULONG)aSize; }
+ static size_t Size(ULONG aVarCount) { return (size_t)aVarCount; }
+
+ static void Copy(BSTR aFrom, BSTR &aTo)
+ {
+ aTo = aFrom ? ::SysAllocString((const OLECHAR *)aFrom) : NULL;
+ }
+};
+
+template<>
+struct SafeArrayTraits<GUID> : public SafeArrayTraitsBase
+{
+protected:
+
+ /* Use the 64-bit unsigned integer type for GUID */
+ static VARTYPE VarType() { return VT_UI8; }
+
+ /* GUID is 128 bit, so we need two VT_UI8 */
+ static ULONG VarCount(size_t aSize)
+ {
+ AssertCompileSize(GUID, 16);
+ return (ULONG)(aSize * 2);
+ }
+
+ static size_t Size(ULONG aVarCount) { return (size_t)aVarCount / 2; }
+
+ static void Copy(GUID aFrom, GUID &aTo) { aTo = aFrom; }
+};
+
+/**
+ * Helper for SafeArray::__asOutParam() that automatically updates m.raw after a
+ * non-NULL m.arr assignment.
+ */
+class OutSafeArrayDipper
+{
+ OutSafeArrayDipper(SAFEARRAY **aArr, void **aRaw)
+ : arr(aArr), raw(aRaw) { Assert(*aArr == NULL && *aRaw == NULL); }
+
+ SAFEARRAY **arr;
+ void **raw;
+
+ template<class, class> friend class SafeArray;
+
+public:
+
+ ~OutSafeArrayDipper()
+ {
+ if (*arr != NULL)
+ {
+ HRESULT rc = SafeArrayAccessData(*arr, raw);
+ AssertComRC(rc);
+ }
+ }
+
+ operator SAFEARRAY **() { return arr; }
+};
+
+#endif /* !VBOX_WITH_XPCOM */
+
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * The SafeArray class represents the safe array type used in COM to pass arrays
+ * to/from interface methods.
+ *
+ * This helper class hides all MSCOM/XPCOM specific implementation details and,
+ * together with ComSafeArrayIn, ComSafeArrayOut and ComSafeArrayRet macros,
+ * provides a platform-neutral way to handle safe arrays in the method
+ * implementation.
+ *
+ * When an instance of this class is destroyed, it automatically frees all
+ * resources occupied by individual elements of the array as well as by the
+ * array itself. However, when the value of an element is manually changed
+ * using #operator[] or by accessing array data through the #raw() pointer, it is
+ * the caller's responsibility to free resources occupied by the previous
+ * element's value.
+ *
+ * Also, objects of this class do not support copy and assignment operations and
+ * therefore cannot be returned from functions by value. In other words, this
+ * class is just a temporary storage for handling interface method calls and not
+ * intended to be used to store arrays as data members and such -- you should
+ * use normal list/vector classes for that.
+ *
+ * @note The current implementation supports only one-dimensional arrays.
+ *
+ * @note This class is not thread-safe.
+ */
+template<typename T, class Traits = SafeArrayTraits<T> >
+class SafeArray : public Traits
+{
+public:
+
+ /**
+ * Creates a null array.
+ */
+ SafeArray() { }
+
+ /**
+ * Creates a new array of the given size. All elements of the newly created
+ * array initialized with null values.
+ *
+ * @param aSize Initial number of elements in the array.
+ *
+ * @note If this object remains null after construction it means that there
+ * was not enough memory for creating an array of the requested size.
+ * The constructor will also assert in this case.
+ */
+ SafeArray(size_t aSize) { resize(aSize); }
+
+ /**
+ * Weakly attaches this instance to the existing array passed in a method
+ * parameter declared using the ComSafeArrayIn macro. When using this call,
+ * always wrap the parameter name in the ComSafeArrayInArg macro call like
+ * this:
+ * <pre>
+ * SafeArray safeArray(ComSafeArrayInArg(aArg));
+ * </pre>
+ *
+ * Note that this constructor doesn't take the ownership of the array. In
+ * particular, it means that operations that operate on the ownership (e.g.
+ * #detachTo()) are forbidden and will assert.
+ *
+ * @param aArg Input method parameter to attach to.
+ */
+ SafeArray(ComSafeArrayIn(T, aArg))
+ {
+ if (aArg)
+ {
+#ifdef VBOX_WITH_XPCOM
+
+ m.size = aArgSize;
+ m.arr = aArg;
+ m.isWeak = true;
+
+#else /* !VBOX_WITH_XPCOM */
+
+ SAFEARRAY *arg = aArg;
+
+ AssertReturnVoid(arg->cDims == 1);
+
+ VARTYPE vt;
+ HRESULT rc = SafeArrayGetVartype(arg, &vt);
+ AssertComRCReturnVoid(rc);
+# ifndef VBOX_WITH_TYPE_TRAITS
+ AssertMsgReturnVoid(
+ vt == VarType()
+ || vt == VarTypeUnsigned(),
+ ("Expected vartype %d or %d, got %d.\n",
+ VarType(), VarTypeUnsigned(), vt));
+# else /* !VBOX_WITH_TYPE_TRAITS */
+ AssertMsgReturnVoid(
+ vt == VarType(),
+ ("Expected vartype %d, got %d.\n",
+ VarType(), vt));
+# endif
+ rc = SafeArrayAccessData(arg, (void HUGEP **)&m.raw);
+ AssertComRCReturnVoid(rc);
+
+ m.arr = arg;
+ m.isWeak = true;
+
+#endif /* !VBOX_WITH_XPCOM */
+ }
+ }
+
+ /**
+ * Creates a deep copy of the given standard C++ container that stores
+ * T objects.
+ *
+ * @param aCntr Container object to copy.
+ *
+ * @tparam C Standard C++ container template class (normally deduced from
+ * @c aCntr).
+ */
+ template<template<typename, typename> class C, class A>
+ SafeArray(const C<T, A> & aCntr)
+ {
+ resize(aCntr.size());
+ AssertReturnVoid(!isNull());
+
+ size_t i = 0;
+ for (typename C<T, A>::const_iterator it = aCntr.begin();
+ it != aCntr.end(); ++ it, ++ i)
+#ifdef VBOX_WITH_XPCOM
+ SafeArray::Copy(*it, m.arr[i]);
+#else
+ Copy(*it, m.raw[i]);
+#endif
+ }
+
+ /**
+ * Creates a deep copy of the given standard C++ map that stores T objects
+ * as values.
+ *
+ * @param aMap Map object to copy.
+ *
+ * @tparam C Standard C++ map template class (normally deduced from
+ * @a aMap).
+ * @tparam L Standard C++ compare class (deduced from @a aMap).
+ * @tparam A Standard C++ allocator class (deduced from @a aMap).
+ * @tparam K Map key class (deduced from @a aMap).
+ */
+ template<template<typename, typename, typename, typename>
+ class C, class L, class A, class K>
+ SafeArray(const C<K, T, L, A> & aMap)
+ {
+ typedef C<K, T, L, A> Map;
+
+ resize(aMap.size());
+ AssertReturnVoid(!isNull());
+
+ size_t i = 0;
+ for (typename Map::const_iterator it = aMap.begin();
+ it != aMap.end(); ++ it, ++ i)
+#ifdef VBOX_WITH_XPCOM
+ Copy(it->second, m.arr[i]);
+#else
+ Copy(it->second, m.raw[i]);
+#endif
+ }
+
+ /**
+ * Destroys this instance after calling #setNull() to release allocated
+ * resources. See #setNull() for more details.
+ */
+ virtual ~SafeArray() { setNull(); }
+
+ /**
+ * Returns @c true if this instance represents a null array.
+ */
+ bool isNull() const { return m.arr == NULL; }
+
+ /**
+ * Returns @c true if this instance does not represents a null array.
+ */
+ bool isNotNull() const { return m.arr != NULL; }
+
+ /**
+ * Resets this instance to null and, if this instance is not a weak one,
+ * releases any resources occupied by the array data.
+ *
+ * @note This method destroys (cleans up) all elements of the array using
+ * the corresponding cleanup routine for the element type before the
+ * array itself is destroyed.
+ */
+ virtual void setNull() { m.uninit(); }
+
+ /**
+ * Returns @c true if this instance is weak. A weak instance doesn't own the
+ * array data and therefore operations manipulating the ownership (e.g.
+ * #detachTo()) are forbidden and will assert.
+ */
+ bool isWeak() const { return m.isWeak; }
+
+ /** Number of elements in the array. */
+ size_t size() const
+ {
+#ifdef VBOX_WITH_XPCOM
+ if (m.arr)
+ return m.size;
+ return 0;
+#else
+ if (m.arr)
+ return Size(m.arr->rgsabound[0].cElements);
+ return 0;
+#endif
+ }
+
+ /**
+ * Appends a copy of the given element at the end of the array.
+ *
+ * The array size is increased by one by this method and the additional
+ * space is allocated as needed.
+ *
+ * This method is handy in cases where you want to assign a copy of the
+ * existing value to the array element, for example:
+ * <tt>Bstr string; array.push_back(string);</tt>. If you create a string
+ * just to put it in the array, you may find #appendedRaw() more useful.
+ *
+ * @param aElement Element to append.
+ *
+ * @return @c true on success and @c false if there is not enough
+ * memory for resizing.
+ */
+ bool push_back(const T &aElement)
+ {
+ if (!ensureCapacity(size() + 1))
+ return false;
+
+#ifdef VBOX_WITH_XPCOM
+ SafeArray::Copy(aElement, m.arr[m.size]);
+ ++ m.size;
+#else
+ Copy(aElement, m.raw[size() - 1]);
+#endif
+ return true;
+ }
+
+ /**
+ * Appends an empty element at the end of the array and returns a raw
+ * pointer to it suitable for assigning a raw value (w/o constructing a
+ * copy).
+ *
+ * The array size is increased by one by this method and the additional
+ * space is allocated as needed.
+ *
+ * Note that in case of raw assignment, value ownership (for types with
+ * dynamically allocated data and for interface pointers) is transferred to
+ * the safe array object.
+ *
+ * This method is handy for operations like
+ * <tt>Bstr("foo").detachTo(array.appendedRaw());</tt>. Don't use it as
+ * an l-value (<tt>array.appendedRaw() = SysAllocString(L"tralala");</tt>)
+ * since this doesn't check for a NULL condition; use #resize() instead. If
+ * you need to assign a copy of the existing value instead of transferring
+ * the ownership, look at #push_back().
+ *
+ * @return Raw pointer to the added element or NULL if no memory.
+ */
+ T *appendedRaw()
+ {
+ if (!ensureCapacity(size() + 1))
+ return NULL;
+
+#ifdef VBOX_WITH_XPCOM
+ SafeArray::Init(m.arr[m.size]);
+ ++ m.size;
+ return &m.arr[m.size - 1];
+#else
+ /* nothing to do here, SafeArrayCreate() has performed element
+ * initialization */
+ return &m.raw[size() - 1];
+#endif
+ }
+
+ /**
+ * Resizes the array preserving its contents when possible. If the new size
+ * is larger than the old size, new elements are initialized with null
+ * values. If the new size is less than the old size, the contents of the
+ * array beyond the new size is lost.
+ *
+ * @param aNewSize New number of elements in the array.
+ * @return @c true on success and @c false if there is not enough
+ * memory for resizing.
+ */
+ bool resize(size_t aNewSize)
+ {
+ if (!ensureCapacity(aNewSize))
+ return false;
+
+#ifdef VBOX_WITH_XPCOM
+
+ if (m.size < aNewSize)
+ {
+ /* initialize the new elements */
+ for (size_t i = m.size; i < aNewSize; ++ i)
+ SafeArray::Init(m.arr[i]);
+ }
+
+ /** @todo Fix this! */
+ m.size = (PRUint32)aNewSize;
+#else
+ /* nothing to do here, SafeArrayCreate() has performed element
+ * initialization */
+#endif
+ return true;
+ }
+
+ /**
+ * Reinitializes this instance by preallocating space for the given number
+ * of elements. The previous array contents is lost.
+ *
+ * @param aNewSize New number of elements in the array.
+ * @return @c true on success and @c false if there is not enough
+ * memory for resizing.
+ */
+ bool reset(size_t aNewSize)
+ {
+ m.uninit();
+ return resize(aNewSize);
+ }
+
+ /**
+ * Returns a pointer to the raw array data. Use this raw pointer with care
+ * as no type or bound checking is done for you in this case.
+ *
+ * @note This method returns @c NULL when this instance is null.
+ * @see #operator[]
+ */
+ T *raw()
+ {
+#ifdef VBOX_WITH_XPCOM
+ return m.arr;
+#else
+ return m.raw;
+#endif
+ }
+
+ /**
+ * Const version of #raw().
+ */
+ const T *raw() const
+ {
+#ifdef VBOX_WITH_XPCOM
+ return m.arr;
+#else
+ return m.raw;
+#endif
+ }
+
+ /**
+ * Array access operator that returns an array element by reference. A bit
+ * safer than #raw(): asserts and returns a reference to a static zero
+ * element (const, i.e. writes will fail) if this instance is null or
+ * if the index is out of bounds.
+ *
+ * @note For weak instances, this call will succeed but the behavior of
+ * changing the contents of an element of the weak array instance is
+ * undefined and may lead to a program crash on some platforms.
+ */
+ T &operator[] (size_t aIdx)
+ {
+ /** @todo r=klaus should do this as a AssertCompile, but cannot find a way which works. */
+ Assert(sizeof(T) <= sizeof(Zeroes));
+ AssertReturn(m.arr != NULL, *(T *)&Zeroes[0]);
+ AssertReturn(aIdx < size(), *(T *)&Zeroes[0]);
+#ifdef VBOX_WITH_XPCOM
+ return m.arr[aIdx];
+#else
+ AssertReturn(m.raw != NULL, *(T *)&Zeroes[0]);
+ return m.raw[aIdx];
+#endif
+ }
+
+ /**
+ * Const version of #operator[] that returns an array element by value.
+ */
+ const T operator[] (size_t aIdx) const
+ {
+ AssertReturn(m.arr != NULL, *(const T *)&Zeroes[0]);
+ AssertReturn(aIdx < size(), *(const T *)&Zeroes[0]);
+#ifdef VBOX_WITH_XPCOM
+ return m.arr[aIdx];
+#else
+ AssertReturn(m.raw != NULL, *(const T *)&Zeroes[0]);
+ return m.raw[aIdx];
+#endif
+ }
+
+ /**
+ * Creates a copy of this array and stores it in a method parameter declared
+ * using the ComSafeArrayOut macro. When using this call, always wrap the
+ * parameter name in the ComSafeArrayOutArg macro call like this:
+ * <pre>
+ * safeArray.cloneTo(ComSafeArrayOutArg(aArg));
+ * </pre>
+ *
+ * @note It is assumed that the ownership of the returned copy is
+ * transferred to the caller of the method and he is responsible to free the
+ * array data when it is no longer needed.
+ *
+ * @param aArg Output method parameter to clone to.
+ */
+ virtual const SafeArray &cloneTo(ComSafeArrayOut(T, aArg)) const
+ {
+ /// @todo Implement me!
+#ifdef VBOX_WITH_XPCOM
+ NOREF(aArgSize);
+ NOREF(aArg);
+#else
+ NOREF(aArg);
+#endif
+ AssertFailedReturn(*this);
+ }
+
+ HRESULT cloneTo(SafeArray<T>& aOther) const
+ {
+ aOther.reset(size());
+ return aOther.initFrom(*this);
+ }
+
+
+ /**
+ * Transfers the ownership of this array's data to the specified location
+ * declared using the ComSafeArrayOut macro and makes this array a null
+ * array. When using this call, always wrap the parameter name in the
+ * ComSafeArrayOutArg macro call like this:
+ * <pre>
+ * safeArray.detachTo(ComSafeArrayOutArg(aArg));
+ * </pre>
+ *
+ * Detaching the null array is also possible in which case the location will
+ * receive NULL.
+ *
+ * @note Since the ownership of the array data is transferred to the
+ * caller of the method, he is responsible to free the array data when it is
+ * no longer needed.
+ *
+ * @param aArg Location to detach to.
+ */
+ virtual SafeArray &detachTo(ComSafeArrayOut(T, aArg))
+ {
+ AssertReturn(!m.isWeak, *this);
+
+#ifdef VBOX_WITH_XPCOM
+
+ AssertReturn(aArgSize != NULL, *this);
+ AssertReturn(aArg != NULL, *this);
+
+ *aArgSize = m.size;
+ *aArg = m.arr;
+
+ m.isWeak = false;
+ m.size = 0;
+ m.arr = NULL;
+
+#else /* !VBOX_WITH_XPCOM */
+
+ AssertReturn(aArg != NULL, *this);
+ *aArg = m.arr;
+
+ if (m.raw)
+ {
+ HRESULT rc = SafeArrayUnaccessData(m.arr);
+ AssertComRCReturn(rc, *this);
+ m.raw = NULL;
+ }
+
+ m.isWeak = false;
+ m.arr = NULL;
+
+#endif /* !VBOX_WITH_XPCOM */
+
+ return *this;
+ }
+
+ /**
+ * Returns a copy of this SafeArray as RTCList<T>.
+ */
+ RTCList<T> toList()
+ {
+ RTCList<T> list(size());
+ for (size_t i = 0; i < size(); ++i)
+#ifdef VBOX_WITH_XPCOM
+ list.append(m.arr[i]);
+#else
+ list.append(m.raw[i]);
+#endif
+ return list;
+ }
+
+ inline HRESULT initFrom(const com::SafeArray<T> & aRef);
+ inline HRESULT initFrom(const T* aPtr, size_t aSize);
+
+ // Public methods for internal purposes only.
+
+#ifdef VBOX_WITH_XPCOM
+
+ /** Internal function. Never call it directly. */
+ PRUint32 *__asOutParam_Size() { setNull(); return &m.size; }
+
+ /** Internal function Never call it directly. */
+ T **__asOutParam_Arr() { Assert(isNull()); return &m.arr; }
+
+#else /* !VBOX_WITH_XPCOM */
+
+ /** Internal function Never call it directly. */
+ SAFEARRAY * __asInParam() { return m.arr; }
+
+ /** Internal function Never call it directly. */
+ OutSafeArrayDipper __asOutParam()
+ { setNull(); return OutSafeArrayDipper(&m.arr, (void **)&m.raw); }
+
+#endif /* !VBOX_WITH_XPCOM */
+
+ static const SafeArray Null;
+
+protected:
+
+ DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP(SafeArray);
+
+ /**
+ * Ensures that the array is big enough to contain aNewSize elements.
+ *
+ * If the new size is greater than the current capacity, a new array is
+ * allocated and elements from the old array are copied over. The size of
+ * the array doesn't change, only the capacity increases (which is always
+ * greater than the size). Note that the additionally allocated elements are
+ * left uninitialized by this method.
+ *
+ * If the new size is less than the current size, the existing array is
+ * truncated to the specified size and the elements outside the new array
+ * boundary are freed.
+ *
+ * If the new size is the same as the current size, nothing happens.
+ *
+ * @param aNewSize New size of the array.
+ *
+ * @return @c true on success and @c false if not enough memory.
+ */
+ bool ensureCapacity(size_t aNewSize)
+ {
+ AssertReturn(!m.isWeak, false);
+
+#ifdef VBOX_WITH_XPCOM
+
+ /* Note: we distinguish between a null array and an empty (zero
+ * elements) array. Therefore we never use zero in malloc (even if
+ * aNewSize is zero) to make sure we get a non-null pointer. */
+
+ if (m.size == aNewSize && m.arr != NULL)
+ return true;
+
+ /* Allocate in 16-byte pieces. */
+ size_t newCapacity = RT_MAX((aNewSize + 15) / 16 * 16, 16);
+
+ if (m.capacity != newCapacity)
+ {
+ T *newArr = (T *)nsMemory::Alloc(RT_MAX(newCapacity, 1) * sizeof(T));
+ AssertReturn(newArr != NULL, false);
+
+ if (m.arr != NULL)
+ {
+ if (m.size > aNewSize)
+ {
+ /* Truncation takes place, uninit exceeding elements and
+ * shrink the size. */
+ for (size_t i = aNewSize; i < m.size; ++ i)
+ SafeArray::Uninit(m.arr[i]);
+
+ /** @todo Fix this! */
+ m.size = (PRUint32)aNewSize;
+ }
+
+ /* Copy the old contents. */
+ memcpy(newArr, m.arr, m.size * sizeof(T));
+ nsMemory::Free((void *)m.arr);
+ }
+
+ m.arr = newArr;
+ }
+ else
+ {
+ if (m.size > aNewSize)
+ {
+ /* Truncation takes place, uninit exceeding elements and
+ * shrink the size. */
+ for (size_t i = aNewSize; i < m.size; ++ i)
+ SafeArray::Uninit(m.arr[i]);
+
+ /** @todo Fix this! */
+ m.size = (PRUint32)aNewSize;
+ }
+ }
+
+ /** @todo Fix this! */
+ m.capacity = (PRUint32)newCapacity;
+
+#else
+
+ SAFEARRAYBOUND bound = { VarCount(aNewSize), 0 };
+ HRESULT rc;
+
+ if (m.arr == NULL)
+ {
+ m.arr = CreateSafeArray(VarType(), &bound);
+ AssertReturn(m.arr != NULL, false);
+ }
+ else
+ {
+ SafeArrayUnaccessData(m.arr);
+
+ rc = SafeArrayRedim(m.arr, &bound);
+ AssertComRCReturn(rc == S_OK, false);
+ }
+
+ rc = SafeArrayAccessData(m.arr, (void HUGEP **)&m.raw);
+ AssertComRCReturn(rc, false);
+
+#endif
+ return true;
+ }
+
+ struct Data
+ {
+ Data()
+ : isWeak(false)
+#ifdef VBOX_WITH_XPCOM
+ , capacity(0), size(0), arr(NULL)
+#else
+ , arr(NULL), raw(NULL)
+#endif
+ {}
+
+ ~Data() { uninit(); }
+
+ void uninit()
+ {
+#ifdef VBOX_WITH_XPCOM
+
+ if (arr)
+ {
+ if (!isWeak)
+ {
+ for (size_t i = 0; i < size; ++ i)
+ SafeArray::Uninit(arr[i]);
+
+ nsMemory::Free((void *)arr);
+ }
+ else
+ isWeak = false;
+
+ arr = NULL;
+ }
+
+ size = capacity = 0;
+
+#else /* !VBOX_WITH_XPCOM */
+
+ if (arr)
+ {
+ if (raw)
+ {
+ SafeArrayUnaccessData(arr);
+ raw = NULL;
+ }
+
+ if (!isWeak)
+ {
+ HRESULT rc = SafeArrayDestroy(arr);
+ AssertComRCReturnVoid(rc);
+ }
+ else
+ isWeak = false;
+
+ arr = NULL;
+ }
+
+#endif /* !VBOX_WITH_XPCOM */
+ }
+
+ bool isWeak : 1;
+
+#ifdef VBOX_WITH_XPCOM
+ PRUint32 capacity;
+ PRUint32 size;
+ T *arr;
+#else
+ SAFEARRAY *arr;
+ T *raw;
+#endif
+ };
+
+ Data m;
+};
+
+/* Few fast specializations for primitive array types */
+template<>
+inline HRESULT com::SafeArray<BYTE>::initFrom(const com::SafeArray<BYTE> & aRef)
+{
+ size_t sSize = aRef.size();
+ if (resize(sSize))
+ {
+ ::memcpy(raw(), aRef.raw(), sSize);
+ return S_OK;
+ }
+ return E_OUTOFMEMORY;
+}
+template<>
+inline HRESULT com::SafeArray<BYTE>::initFrom(const BYTE *aPtr, size_t aSize)
+{
+ if (resize(aSize))
+ {
+ ::memcpy(raw(), aPtr, aSize);
+ return S_OK;
+ }
+ return E_OUTOFMEMORY;
+}
+
+
+template<>
+inline HRESULT com::SafeArray<SHORT>::initFrom(const com::SafeArray<SHORT> & aRef)
+{
+ size_t sSize = aRef.size();
+ if (resize(sSize))
+ {
+ ::memcpy(raw(), aRef.raw(), sSize * sizeof(SHORT));
+ return S_OK;
+ }
+ return E_OUTOFMEMORY;
+}
+template<>
+inline HRESULT com::SafeArray<SHORT>::initFrom(const SHORT *aPtr, size_t aSize)
+{
+ if (resize(aSize))
+ {
+ ::memcpy(raw(), aPtr, aSize * sizeof(SHORT));
+ return S_OK;
+ }
+ return E_OUTOFMEMORY;
+}
+
+template<>
+inline HRESULT com::SafeArray<USHORT>::initFrom(const com::SafeArray<USHORT> & aRef)
+{
+ size_t sSize = aRef.size();
+ if (resize(sSize))
+ {
+ ::memcpy(raw(), aRef.raw(), sSize * sizeof(USHORT));
+ return S_OK;
+ }
+ return E_OUTOFMEMORY;
+}
+template<>
+inline HRESULT com::SafeArray<USHORT>::initFrom(const USHORT *aPtr, size_t aSize)
+{
+ if (resize(aSize))
+ {
+ ::memcpy(raw(), aPtr, aSize * sizeof(USHORT));
+ return S_OK;
+ }
+ return E_OUTOFMEMORY;
+}
+
+template<>
+inline HRESULT com::SafeArray<LONG>::initFrom(const com::SafeArray<LONG> & aRef)
+{
+ size_t sSize = aRef.size();
+ if (resize(sSize))
+ {
+ ::memcpy(raw(), aRef.raw(), sSize * sizeof(LONG));
+ return S_OK;
+ }
+ return E_OUTOFMEMORY;
+}
+template<>
+inline HRESULT com::SafeArray<LONG>::initFrom(const LONG *aPtr, size_t aSize)
+{
+ if (resize(aSize))
+ {
+ ::memcpy(raw(), aPtr, aSize * sizeof(LONG));
+ return S_OK;
+ }
+ return E_OUTOFMEMORY;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+
+#ifdef VBOX_WITH_XPCOM
+
+/**
+ * Version of com::SafeArray for arrays of GUID.
+ *
+ * In MS COM, GUID arrays store GUIDs by value and therefore input arrays are
+ * represented using |GUID *| and out arrays -- using |GUID **|. In XPCOM,
+ * GUID arrays store pointers to nsID so that input arrays are |const nsID **|
+ * and out arrays are |nsID ***|. Due to this difference, it is impossible to
+ * work with arrays of GUID on both platforms by simply using com::SafeArray
+ * <GUID>. This class is intended to provide some level of cross-platform
+ * behavior.
+ *
+ * The basic usage pattern is basically similar to com::SafeArray<> except that
+ * you use ComSafeGUIDArrayIn* and ComSafeGUIDArrayOut* macros instead of
+ * ComSafeArrayIn* and ComSafeArrayOut*. Another important nuance is that the
+ * raw() array type is different (nsID **, or GUID ** on XPCOM and GUID * on MS
+ * COM) so it is recommended to use operator[] instead which always returns a
+ * GUID by value.
+ *
+ * Note that due to const modifiers, you cannot use SafeGUIDArray for input GUID
+ * arrays. Please use SafeConstGUIDArray for this instead.
+ *
+ * Other than mentioned above, the functionality of this class is equivalent to
+ * com::SafeArray<>. See the description of that template and its methods for
+ * more information.
+ *
+ * Output GUID arrays are handled by a separate class, SafeGUIDArrayOut, since
+ * this class cannot handle them because of const modifiers.
+ */
+class SafeGUIDArray : public SafeArray<nsID *>
+{
+public:
+
+ typedef SafeArray<nsID *> Base;
+
+ class nsIDRef
+ {
+ public:
+
+ nsIDRef(nsID * &aVal) : mVal(aVal) { AssertCompile(sizeof(nsID) <= sizeof(Zeroes)); }
+
+ operator const nsID &() const { return mVal ? *mVal : *(const nsID *)&Zeroes[0]; }
+ operator nsID() const { return mVal ? *mVal : *(nsID *)&Zeroes[0]; }
+
+ const nsID *operator&() const { return mVal ? mVal : (const nsID *)&Zeroes[0]; }
+
+ nsIDRef &operator= (const nsID &aThat)
+ {
+ if (mVal == NULL)
+ Copy(&aThat, mVal);
+ else
+ *mVal = aThat;
+ return *this;
+ }
+
+ private:
+
+ nsID * &mVal;
+
+ friend class SafeGUIDArray;
+ };
+
+ /** See SafeArray<>::SafeArray(). */
+ SafeGUIDArray() {}
+
+ /** See SafeArray<>::SafeArray(size_t). */
+ SafeGUIDArray(size_t aSize) : Base(aSize) {}
+
+ /**
+ * Array access operator that returns an array element by reference. As a
+ * special case, the return value of this operator on XPCOM is an nsID (GUID)
+ * reference, instead of an nsID pointer (the actual SafeArray template
+ * argument), for compatibility with the MS COM version.
+ *
+ * The rest is equivalent to SafeArray<>::operator[].
+ */
+ nsIDRef operator[] (size_t aIdx)
+ {
+ Assert(m.arr != NULL);
+ Assert(aIdx < size());
+ return nsIDRef(m.arr[aIdx]);
+ }
+
+ /**
+ * Const version of #operator[] that returns an array element by value.
+ */
+ const nsID &operator[] (size_t aIdx) const
+ {
+ Assert(m.arr != NULL);
+ Assert(aIdx < size());
+ return m.arr[aIdx] ? *m.arr[aIdx] : *(const nsID *)&Zeroes[0];
+ }
+};
+
+/**
+ * Version of com::SafeArray for const arrays of GUID.
+ *
+ * This class is used to work with input GUID array parameters in method
+ * implementations. See SafeGUIDArray for more details.
+ */
+class SafeConstGUIDArray : public SafeArray<const nsID *,
+ SafeArrayTraits<nsID *> >
+{
+public:
+
+ typedef SafeArray<const nsID *, SafeArrayTraits<nsID *> > Base;
+
+ /** See SafeArray<>::SafeArray(). */
+ SafeConstGUIDArray() { AssertCompile(sizeof(nsID) <= sizeof(Zeroes)); }
+
+ /* See SafeArray<>::SafeArray(ComSafeArrayIn(T, aArg)). */
+ SafeConstGUIDArray(ComSafeGUIDArrayIn(aArg))
+ : Base(ComSafeGUIDArrayInArg(aArg)) {}
+
+ /**
+ * Array access operator that returns an array element by reference. As a
+ * special case, the return value of this operator on XPCOM is nsID (GUID)
+ * instead of nsID *, for compatibility with the MS COM version.
+ *
+ * The rest is equivalent to SafeArray<>::operator[].
+ */
+ const nsID &operator[] (size_t aIdx) const
+ {
+ AssertReturn(m.arr != NULL, *(const nsID *)&Zeroes[0]);
+ AssertReturn(aIdx < size(), *(const nsID *)&Zeroes[0]);
+ return *m.arr[aIdx];
+ }
+
+private:
+
+ /* These are disabled because of const. */
+ bool reset(size_t aNewSize) { NOREF(aNewSize); return false; }
+};
+
+#else /* !VBOX_WITH_XPCOM */
+
+typedef SafeArray<GUID> SafeGUIDArray;
+typedef SafeArray<const GUID, SafeArrayTraits<GUID> > SafeConstGUIDArray;
+
+#endif /* !VBOX_WITH_XPCOM */
+
+////////////////////////////////////////////////////////////////////////////////
+
+#ifdef VBOX_WITH_XPCOM
+
+template<class I>
+struct SafeIfaceArrayTraits
+{
+protected:
+
+ static void Init(I * &aElem) { aElem = NULL; }
+ static void Uninit(I * &aElem)
+ {
+ if (aElem)
+ {
+ aElem->Release();
+ aElem = NULL;
+ }
+ }
+
+ static void Copy(I * aFrom, I * &aTo)
+ {
+ if (aFrom != NULL)
+ {
+ aTo = aFrom;
+ aTo->AddRef();
+ }
+ else
+ aTo = NULL;
+ }
+
+public:
+
+ /* Magic to workaround strict rules of par. 4.4.4 of the C++ standard. */
+ static I **__asInParam_Arr(I **aArr) { return aArr; }
+ static I **__asInParam_Arr(const I **aArr) { return const_cast<I **>(aArr); }
+};
+
+#else /* !VBOX_WITH_XPCOM */
+
+template<class I>
+struct SafeIfaceArrayTraits
+{
+protected:
+
+ static VARTYPE VarType() { return VT_DISPATCH; }
+ static ULONG VarCount(size_t aSize) { return (ULONG)aSize; }
+ static size_t Size(ULONG aVarCount) { return (size_t)aVarCount; }
+
+ static void Copy(I * aFrom, I * &aTo)
+ {
+ if (aFrom != NULL)
+ {
+ aTo = aFrom;
+ aTo->AddRef();
+ }
+ else
+ aTo = NULL;
+ }
+
+ static SAFEARRAY *CreateSafeArray(VARTYPE aVarType, SAFEARRAYBOUND *aBound)
+ {
+ NOREF(aVarType);
+ return SafeArrayCreateEx(VT_DISPATCH, 1, aBound, (PVOID)&COM_IIDOF(I));
+ }
+};
+
+#endif /* !VBOX_WITH_XPCOM */
+
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Version of com::SafeArray for arrays of interface pointers.
+ *
+ * Except that it manages arrays of interface pointers, the usage of this class
+ * is identical to com::SafeArray.
+ *
+ * @param I Interface class (no asterisk).
+ */
+template<class I>
+class SafeIfaceArray : public SafeArray<I *, SafeIfaceArrayTraits<I> >
+{
+public:
+
+ typedef SafeArray<I *, SafeIfaceArrayTraits<I> > Base;
+
+ /**
+ * Creates a null array.
+ */
+ SafeIfaceArray() {}
+
+ /**
+ * Creates a new array of the given size. All elements of the newly created
+ * array initialized with null values.
+ *
+ * @param aSize Initial number of elements in the array. Must be greater
+ * than 0.
+ *
+ * @note If this object remains null after construction it means that there
+ * was not enough memory for creating an array of the requested size.
+ * The constructor will also assert in this case.
+ */
+ SafeIfaceArray(size_t aSize) { Base::resize(aSize); }
+
+ /**
+ * Weakly attaches this instance to the existing array passed in a method
+ * parameter declared using the ComSafeArrayIn macro. When using this call,
+ * always wrap the parameter name in the ComSafeArrayOutArg macro call like
+ * this:
+ * <pre>
+ * SafeArray safeArray(ComSafeArrayInArg(aArg));
+ * </pre>
+ *
+ * Note that this constructor doesn't take the ownership of the array. In
+ * particular, this means that operations that operate on the ownership
+ * (e.g. #detachTo()) are forbidden and will assert.
+ *
+ * @param aArg Input method parameter to attach to.
+ */
+ SafeIfaceArray(ComSafeArrayIn(I *, aArg))
+ {
+ if (aArg)
+ {
+#ifdef VBOX_WITH_XPCOM
+
+ Base::m.size = aArgSize;
+ Base::m.arr = aArg;
+ Base::m.isWeak = true;
+
+#else /* !VBOX_WITH_XPCOM */
+
+ SAFEARRAY *arg = aArg;
+
+ AssertReturnVoid(arg->cDims == 1);
+
+ VARTYPE vt;
+ HRESULT rc = SafeArrayGetVartype(arg, &vt);
+ AssertComRCReturnVoid(rc);
+ AssertMsgReturnVoid(vt == VT_UNKNOWN || vt == VT_DISPATCH,
+ ("Expected vartype VT_UNKNOWN or VT_DISPATCH, got %d.\n",
+ vt));
+ GUID guid;
+ rc = SafeArrayGetIID(arg, &guid);
+ AssertComRCReturnVoid(rc);
+ AssertMsgReturnVoid(InlineIsEqualGUID(COM_IIDOF(I), guid) || arg->rgsabound[0].cElements == 0 /* IDispatch if empty */,
+ ("Expected IID {%RTuuid}, got {%RTuuid}.\n", &COM_IIDOF(I), &guid));
+
+ rc = SafeArrayAccessData(arg, (void HUGEP **)&m.raw);
+ AssertComRCReturnVoid(rc);
+
+ m.arr = arg;
+ m.isWeak = true;
+
+#endif /* !VBOX_WITH_XPCOM */
+ }
+ }
+
+ /**
+ * Creates a deep copy of the given standard C++ container that stores
+ * interface pointers as objects of the ComPtr\<I\> class.
+ *
+ * @param aCntr Container object to copy.
+ *
+ * @tparam C Standard C++ container template class (normally deduced from
+ * @c aCntr).
+ * @tparam A Standard C++ allocator class (deduced from @c aCntr).
+ * @tparam OI Argument to the ComPtr template (deduced from @c aCntr).
+ */
+ template<template<typename, typename> class C, class A, class OI>
+ SafeIfaceArray(const C<ComPtr<OI>, A> & aCntr)
+ {
+ typedef C<ComPtr<OI>, A> List;
+
+ Base::resize(aCntr.size());
+ AssertReturnVoid(!Base::isNull());
+
+ size_t i = 0;
+ for (typename List::const_iterator it = aCntr.begin();
+ it != aCntr.end(); ++ it, ++ i)
+#ifdef VBOX_WITH_XPCOM
+ this->Copy(*it, Base::m.arr[i]);
+#else
+ Copy(*it, Base::m.raw[i]);
+#endif
+ }
+
+ /**
+ * Creates a deep copy of the given standard C++ container that stores
+ * interface pointers as objects of the ComObjPtr\<I\> class.
+ *
+ * @param aCntr Container object to copy.
+ *
+ * @tparam C Standard C++ container template class (normally deduced from
+ * @c aCntr).
+ * @tparam A Standard C++ allocator class (deduced from @c aCntr).
+ * @tparam OI Argument to the ComObjPtr template (deduced from @c aCntr).
+ */
+ template<template<typename, typename> class C, class A, class OI>
+ SafeIfaceArray(const C<ComObjPtr<OI>, A> & aCntr)
+ {
+ typedef C<ComObjPtr<OI>, A> List;
+
+ Base::resize(aCntr.size());
+ AssertReturnVoid(!Base::isNull());
+
+ size_t i = 0;
+ for (typename List::const_iterator it = aCntr.begin();
+ it != aCntr.end(); ++ it, ++ i)
+#ifdef VBOX_WITH_XPCOM
+ SafeIfaceArray::Copy(*it, Base::m.arr[i]);
+#else
+ Copy(*it, Base::m.raw[i]);
+#endif
+ }
+
+ /**
+ * Creates a deep copy of the given standard C++ map whose values are
+ * interface pointers stored as objects of the ComPtr\<I\> class.
+ *
+ * @param aMap Map object to copy.
+ *
+ * @tparam C Standard C++ map template class (normally deduced from
+ * @c aCntr).
+ * @tparam L Standard C++ compare class (deduced from @c aCntr).
+ * @tparam A Standard C++ allocator class (deduced from @c aCntr).
+ * @tparam K Map key class (deduced from @c aCntr).
+ * @tparam OI Argument to the ComPtr template (deduced from @c aCntr).
+ */
+ template<template<typename, typename, typename, typename>
+ class C, class L, class A, class K, class OI>
+ SafeIfaceArray(const C<K, ComPtr<OI>, L, A> & aMap)
+ {
+ typedef C<K, ComPtr<OI>, L, A> Map;
+
+ Base::resize(aMap.size());
+ AssertReturnVoid(!Base::isNull());
+
+ size_t i = 0;
+ for (typename Map::const_iterator it = aMap.begin();
+ it != aMap.end(); ++ it, ++ i)
+#ifdef VBOX_WITH_XPCOM
+ SafeIfaceArray::Copy(it->second, Base::m.arr[i]);
+#else
+ Copy(it->second, Base::m.raw[i]);
+#endif
+ }
+
+ /**
+ * Creates a deep copy of the given standard C++ map whose values are
+ * interface pointers stored as objects of the ComObjPtr\<I\> class.
+ *
+ * @param aMap Map object to copy.
+ *
+ * @tparam C Standard C++ map template class (normally deduced from
+ * @c aCntr).
+ * @tparam L Standard C++ compare class (deduced from @c aCntr).
+ * @tparam A Standard C++ allocator class (deduced from @c aCntr).
+ * @tparam K Map key class (deduced from @c aCntr).
+ * @tparam OI Argument to the ComObjPtr template (deduced from @c aCntr).
+ */
+ template<template<typename, typename, typename, typename>
+ class C, class L, class A, class K, class OI>
+ SafeIfaceArray(const C<K, ComObjPtr<OI>, L, A> & aMap)
+ {
+ typedef C<K, ComObjPtr<OI>, L, A> Map;
+
+ Base::resize(aMap.size());
+ AssertReturnVoid(!Base::isNull());
+
+ size_t i = 0;
+ for (typename Map::const_iterator it = aMap.begin();
+ it != aMap.end(); ++ it, ++ i)
+#ifdef VBOX_WITH_XPCOM
+ SafeIfaceArray::Copy(it->second, Base::m.arr[i]);
+#else
+ Copy(it->second, Base::m.raw[i]);
+#endif
+ }
+
+ void setElement(size_t iIdx, I* obj)
+ {
+#ifdef VBOX_WITH_XPCOM
+ SafeIfaceArray::Copy(obj, Base::m.arr[iIdx]);
+#else
+ Copy(obj, Base::m.raw[iIdx]);
+#endif
+ }
+};
+
+} /* namespace com */
+
+/** @} */
+
+#endif /* !VBOX_INCLUDED_com_array_h */
+
diff --git a/include/VBox/com/assert.h b/include/VBox/com/assert.h
new file mode 100644
index 00000000..f70f474d
--- /dev/null
+++ b/include/VBox/com/assert.h
@@ -0,0 +1,135 @@
+/** @file
+ * MS COM / XPCOM Abstraction Layer - Assertion macros for COM/XPCOM.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_com_assert_h
+#define VBOX_INCLUDED_com_assert_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/assert.h>
+
+/** @defgroup grp_com_assert Assertion Macros for COM/XPCOM
+ * @ingroup grp_com
+ * @{
+ */
+
+
+/**
+ * Asserts that the COM result code is succeeded in strict builds.
+ * In non-strict builds the result code will be NOREF'ed to kill compiler warnings.
+ *
+ * @param hrc The COM result code
+ */
+#define AssertComRC(hrc) \
+ do { AssertMsg(SUCCEEDED(hrc), ("COM RC = %Rhrc (0x%08X)\n", hrc, hrc)); NOREF(hrc); } while (0)
+
+/**
+ * Same as AssertComRC, except the caller already knows we failed.
+ *
+ * @param hrc The COM result code
+ */
+#define AssertComRCFailed(hrc) \
+ do { AssertMsgFailed(("COM RC = %Rhrc (0x%08X)\n", hrc, hrc)); NOREF(hrc); } while (0)
+
+/**
+ * A special version of AssertComRC that returns the given expression
+ * if the result code is failed.
+ *
+ * @param hrc The COM result code
+ * @param RetExpr The expression to return
+ */
+#define AssertComRCReturn(hrc, RetExpr) \
+ AssertMsgReturn(SUCCEEDED(hrc), ("COM RC = %Rhrc (0x%08X)\n", hrc, hrc), RetExpr)
+
+/**
+ * A special version of AssertComRC that returns the given result code
+ * if it is failed.
+ *
+ * @param hrc The COM result code
+ */
+#define AssertComRCReturnRC(hrc) \
+ AssertMsgReturn(SUCCEEDED(hrc), ("COM RC = %Rhrc (0x%08X)\n", hrc, hrc), hrc)
+
+/**
+ * A special version of AssertComRC that returns if the result code is failed.
+ *
+ * @param hrc The COM result code
+ */
+#define AssertComRCReturnVoid(hrc) \
+ AssertMsgReturnVoid(SUCCEEDED(hrc), ("COM RC = %Rhrc (0x%08X)\n", hrc, hrc))
+
+/**
+ * A special version of AssertComRC that evaluates the given expression and
+ * breaks if the result code is failed.
+ *
+ * @param hrc The COM result code
+ * @param PreBreakExpr The expression to evaluate on failure.
+ */
+#define AssertComRCBreak(hrc, PreBreakExpr) \
+ if (!SUCCEEDED(hrc)) { AssertComRCFailed(hrc); PreBreakExpr; break; } else do {} while (0)
+
+/**
+ * A special version of AssertComRC that evaluates the given expression and
+ * throws it if the result code is failed.
+ *
+ * @param hrc The COM result code
+ * @param ThrowMeExpr The expression which result to be thrown on failure.
+ */
+#define AssertComRCThrow(hrc, ThrowMeExpr) \
+ do { if (SUCCEEDED(hrc)) { /*likely*/} else { AssertComRCFailed(hrc); throw (ThrowMeExpr); } } while (0)
+
+/**
+ * A special version of AssertComRC that just breaks if the result code is
+ * failed.
+ *
+ * @param hrc The COM result code
+ */
+#define AssertComRCBreakRC(hrc) \
+ if (!SUCCEEDED(hrc)) { AssertComRCFailed(hrc); break; } else do {} while (0)
+
+/**
+ * A special version of AssertComRC that just throws @a hrc if the result code
+ * is failed.
+ *
+ * @param hrc The COM result code
+ */
+#define AssertComRCThrowRC(hrc) \
+ do { if (SUCCEEDED(hrc)) { /*likely*/ } else { AssertComRCFailed(hrc); throw hrc; } } while (0)
+
+/** @} */
+
+#endif /* !VBOX_INCLUDED_com_assert_h */
+
diff --git a/include/VBox/com/com.h b/include/VBox/com/com.h
new file mode 100644
index 00000000..946122b1
--- /dev/null
+++ b/include/VBox/com/com.h
@@ -0,0 +1,102 @@
+/** @file
+ * MS COM / XPCOM Abstraction Layer - COM initialization / shutdown.
+ */
+
+/*
+ * Copyright (C) 2005-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_com_com_h
+#define VBOX_INCLUDED_com_com_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include "VBox/com/defs.h"
+#include "VBox/com/utils.h"
+
+/** @defgroup grp_com MS COM / XPCOM Abstraction Layer
+ * @{
+ */
+
+namespace com
+{
+
+/** @name VBOX_COM_INIT_F_XXX - flags for com::Initialize().
+ * @{ */
+/** Windows: Caller is the GUI and needs a STA rather than MTA apartment. */
+#define VBOX_COM_INIT_F_GUI RT_BIT_32(0)
+/** Windows: Auto registration updating, if privileged enough. */
+#define VBOX_COM_INIT_F_AUTO_REG_UPDATE RT_BIT_32(1)
+/** Windows: Opt-out of COM patching (client code should do this). */
+#define VBOX_COM_INIT_F_NO_COM_PATCHING RT_BIT_32(2)
+/** The default flags. */
+#define VBOX_COM_INIT_F_DEFAULT (VBOX_COM_INIT_F_AUTO_REG_UPDATE)
+/** @} */
+
+/**
+ * Initializes the COM runtime.
+ *
+ * Must be called on the main thread, before any COM activity in any thread, and by any thread
+ * willing to perform COM operations.
+ *
+ * @return COM result code
+ */
+HRESULT Initialize(uint32_t fInitFlags = VBOX_COM_INIT_F_DEFAULT);
+
+/**
+ * Shuts down the COM runtime.
+ *
+ * Must be called on the main thread before termination.
+ * No COM calls may be made in any thread after this method returns.
+ */
+HRESULT Shutdown();
+
+/**
+ * Resolves a given interface ID to a string containing the interface name.
+ *
+ * If, for some reason, the given IID cannot be resolved to a name, a NULL
+ * string is returned. A non-NULL string returned by this function must be
+ * freed using SysFreeString().
+ *
+ * @param aIID ID of the interface to get a name for
+ * @param aName Resolved interface name or @c NULL on error
+ */
+void GetInterfaceNameByIID(const GUID &aIID, BSTR *aName);
+
+#ifdef RT_OS_WINDOWS
+void PatchComBugs(void);
+#endif
+
+} /* namespace com */
+
+/** @} */
+#endif /* !VBOX_INCLUDED_com_com_h */
+
diff --git a/include/VBox/com/defs.h b/include/VBox/com/defs.h
new file mode 100644
index 00000000..86b7b101
--- /dev/null
+++ b/include/VBox/com/defs.h
@@ -0,0 +1,606 @@
+/** @file
+ * MS COM / XPCOM Abstraction Layer - Common Definitions.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_com_defs_h
+#define VBOX_INCLUDED_com_defs_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+/* Make sure all the stdint.h macros are included - must come first! */
+#ifndef __STDC_LIMIT_MACROS
+# define __STDC_LIMIT_MACROS
+#endif
+#ifndef __STDC_CONSTANT_MACROS
+# define __STDC_CONSTANT_MACROS
+#endif
+
+#if defined (RT_OS_OS2)
+
+# if defined(RT_MAX) && RT_MAX != 22
+# undef RT_MAX
+# define REDEFINE_RT_MAX
+# endif
+# undef RT_MAX
+
+/* Make sure OS/2 Toolkit headers are pulled in to have BOOL/ULONG/etc. typedefs
+ * already defined in order to be able to redefine them using #define. */
+# define INCL_BASE
+# define INCL_PM
+# include <os2.h>
+
+/* OS/2 Toolkit defines TRUE and FALSE */
+# undef FALSE
+# undef TRUE
+
+/* */
+# undef RT_MAX
+# ifdef REDEFINE_RT_MAX
+# define RT_MAX(Value1, Value2) ( (Value1) >= (Value2) ? (Value1) : (Value2) )
+# endif
+
+#endif /* defined(RT_OS_OS2) */
+
+/* Include iprt/types.h (which also includes iprt/types.h) now to make sure iprt
+ * gets to stdint.h first, otherwise a system/xpcom header might beat us and
+ * we'll be without the macros that are optional in C++. */
+#include <iprt/types.h>
+
+
+
+/** @defgroup grp_com_defs Common Definitions
+ * @ingroup grp_com
+ * @{
+ */
+
+#if !defined(VBOX_WITH_XPCOM)
+
+#ifdef RT_OS_WINDOWS
+
+// Windows COM
+/////////////////////////////////////////////////////////////////////////////
+
+# include <iprt/win/objbase.h>
+# ifndef VBOX_COM_NO_ATL
+
+/* Do not use actual ATL, just provide a superficial lookalike ourselves. */
+# include <VBox/com/microatl.h>
+# endif /* VBOX_COM_NO_ATL */
+
+# define NS_DECL_ISUPPORTS
+# define NS_IMPL_ISUPPORTS1_CI(a, b)
+
+/* these are XPCOM only, one for every interface implemented */
+# define NS_DECL_ISUPPORTS
+
+/** Returns @c true if @a rc represents a warning result code */
+# define SUCCEEDED_WARNING(rc) (SUCCEEDED(rc) && (rc) != S_OK)
+
+/** Tests is a COM result code indicates that the process implementing the
+ * interface is dead.
+ *
+ * COM status codes:
+ * 0x800706ba - RPC_S_SERVER_UNAVAILABLE. Killed before call was made.
+ * 0x800706be - RPC_S_CALL_FAILED. Killed after call was made.
+ * 0x800706bf - RPC_S_CALL_FAILED_DNE. Not observed, but should be
+ * matter of timing.
+ * 0x80010108 - RPC_E_DISCONNECTED. Observed deregistering
+ * python event listener.
+ * 0x800706b5 - RPC_S_UNKNOWN_IF. Observed deregistering python
+ * event listener
+ */
+#define FAILED_DEAD_INTERFACE(rc) \
+ ( (rc) == HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE) \
+ || (rc) == HRESULT_FROM_WIN32(RPC_S_CALL_FAILED) \
+ || (rc) == HRESULT_FROM_WIN32(RPC_S_CALL_FAILED_DNE) \
+ || (rc) == RPC_E_DISCONNECTED \
+ )
+
+/** Immutable BSTR string */
+typedef const OLECHAR *CBSTR;
+
+/** Input BSTR argument of interface method declaration. */
+#define IN_BSTR BSTR
+
+/** Input GUID argument of interface method declaration. */
+#define IN_GUID GUID
+/** Output GUID argument of interface method declaration. */
+#define OUT_GUID GUID *
+
+/** Makes the name of the getter interface function (n must be capitalized). */
+#define COMGETTER(n) get_##n
+/** Makes the name of the setter interface function (n must be capitalized). */
+#define COMSETTER(n) put_##n
+
+/**
+ * Declares an input safearray parameter in the COM method implementation. Also
+ * used to declare the COM attribute setter parameter. Corresponds to either of
+ * the following XIDL definitions:
+ * <pre>
+ * <param name="arg" ... dir="in" safearray="yes"/>
+ * ...
+ * <attribute name="arg" ... safearray="yes"/>
+ * </pre>
+ *
+ * The method implementation should use the com::SafeArray helper class to work
+ * with parameters declared using this define.
+ *
+ * @param aType Array element type.
+ * @param aArg Parameter/attribute name.
+ */
+#define ComSafeArrayIn(aType, aArg) SAFEARRAY *aArg
+
+/**
+ * Expands to @c true if the given input safearray parameter is a "null pointer"
+ * which makes it impossible to use it for reading safearray data.
+ */
+#define ComSafeArrayInIsNull(aArg) ((aArg) == NULL)
+
+/**
+ * Wraps the given parameter name to generate an expression that is suitable for
+ * passing the parameter to functions that take input safearray parameters
+ * declared using the ComSafeArrayIn macro.
+ *
+ * @param aArg Parameter name to wrap. The given parameter must be declared
+ * within the calling function using the ComSafeArrayIn macro.
+ */
+#define ComSafeArrayInArg(aArg) aArg
+
+/**
+ * Declares an output safearray parameter in the COM method implementation. Also
+ * used to declare the COM attribute getter parameter. Corresponds to either of
+ * the following XIDL definitions:
+ * <pre>
+ * <param name="arg" ... dir="out" safearray="yes"/>
+ * <param name="arg" ... dir="return" safearray="yes"/>
+ * ...
+ * <attribute name="arg" ... safearray="yes"/>
+ * </pre>
+ *
+ * The method implementation should use the com::SafeArray helper class to work
+ * with parameters declared using this define.
+ *
+ * @param aType Array element type.
+ * @param aArg Parameter/attribute name.
+ */
+#define ComSafeArrayOut(aType, aArg) SAFEARRAY **aArg
+
+/**
+ * Expands to @c true if the given output safearray parameter is a "null
+ * pointer" which makes it impossible to use it for returning a safearray.
+ */
+#define ComSafeArrayOutIsNull(aArg) ((aArg) == NULL)
+
+/**
+ * Wraps the given parameter name to generate an expression that is suitable for
+ * passing the parameter to functions that take output safearray parameters
+ * declared using the ComSafeArrayOut marco.
+ *
+ * @param aArg Parameter name to wrap. The given parameter must be declared
+ * within the calling function using the ComSafeArrayOut macro.
+ */
+#define ComSafeArrayOutArg(aArg) aArg
+
+/**
+ * Version of ComSafeArrayIn for GUID.
+ * @param aArg Parameter name to wrap.
+ */
+#define ComSafeGUIDArrayIn(aArg) SAFEARRAY *aArg
+
+/**
+ * Version of ComSafeArrayInIsNull for GUID.
+ * @param aArg Parameter name to wrap.
+ */
+#define ComSafeGUIDArrayInIsNull(aArg) ComSafeArrayInIsNull(aArg)
+
+/**
+ * Version of ComSafeArrayInArg for GUID.
+ * @param aArg Parameter name to wrap.
+ */
+#define ComSafeGUIDArrayInArg(aArg) ComSafeArrayInArg(aArg)
+
+/**
+ * Version of ComSafeArrayOut for GUID.
+ * @param aArg Parameter name to wrap.
+ */
+#define ComSafeGUIDArrayOut(aArg) SAFEARRAY **aArg
+
+/**
+ * Version of ComSafeArrayOutIsNull for GUID.
+ * @param aArg Parameter name to wrap.
+ */
+#define ComSafeGUIDArrayOutIsNull(aArg) ComSafeArrayOutIsNull(aArg)
+
+/**
+ * Version of ComSafeArrayOutArg for GUID.
+ * @param aArg Parameter name to wrap.
+ */
+#define ComSafeGUIDArrayOutArg(aArg) ComSafeArrayOutArg(aArg)
+
+/**
+ * Gets size of safearray parameter.
+ * @param aArg Parameter name.
+ */
+#define ComSafeArraySize(aArg) ((aArg) == NULL ? 0 : (aArg)->rgsabound[0].cElements)
+
+/**
+ * Apply RT_NOREF_PV to a safearray parameter.
+ * @param aArg Parameter name.
+ */
+#define ComSafeArrayNoRef(aArg) RT_NOREF_PV(aArg)
+
+/**
+ * Returns the const reference to the IID (i.e., |const GUID &|) of the given
+ * interface.
+ *
+ * @param I interface class
+ */
+#define COM_IIDOF(I) __uuidof(I)
+
+/**
+ * For using interfaces before including the interface definitions. This will
+ * deal with XPCOM using 'class' and COM using 'struct' when defining
+ * interfaces.
+ *
+ * @param I interface name.
+ */
+#define COM_STRUCT_OR_CLASS(I) struct I
+
+#else /* defined(RT_OS_WINDOWS) */
+
+#error "VBOX_WITH_XPCOM must be defined on a platform other than Windows!"
+
+#endif /* defined(RT_OS_WINDOWS) */
+
+#else /* !defined(VBOX_WITH_XPCOM) */
+
+// XPCOM
+/////////////////////////////////////////////////////////////////////////////
+
+#if defined(RT_OS_DARWIN) || (defined(QT_VERSION) && (QT_VERSION >= 0x040000))
+ /* CFBase.h defines these &
+ * qglobal.h from Qt4 defines these */
+# undef FALSE
+# undef TRUE
+#endif /* RT_OS_DARWIN || QT_VERSION */
+
+#include <nsID.h>
+
+#define HRESULT nsresult
+#define SUCCEEDED NS_SUCCEEDED
+#define FAILED NS_FAILED
+
+#define SUCCEEDED_WARNING(rc) (NS_SUCCEEDED(rc) && (rc) != NS_OK)
+
+#define FAILED_DEAD_INTERFACE(rc) ( (rc) == NS_ERROR_ABORT \
+ || (rc) == NS_ERROR_CALL_FAILED \
+ )
+
+#define IUnknown nsISupports
+
+#define BOOL PRBool
+#define BYTE PRUint8
+#define SHORT PRInt16
+#define USHORT PRUint16
+#define LONG PRInt32
+#define ULONG PRUint32
+#define LONG64 PRInt64
+#define ULONG64 PRUint64
+/* XPCOM has only 64bit floats */
+#define FLOAT PRFloat64
+#define DOUBLE PRFloat64
+
+#define FALSE PR_FALSE
+#define TRUE PR_TRUE
+
+#define OLECHAR wchar_t
+
+/* note: typedef to semantically match BSTR on Win32 */
+typedef PRUnichar *BSTR;
+typedef const PRUnichar *CBSTR;
+typedef BSTR *LPBSTR;
+
+/** Input BSTR argument the interface method declaration. */
+#define IN_BSTR CBSTR
+
+/**
+ * Type to define a raw GUID variable (for members use the com::Guid class
+ * instead).
+ */
+#define GUID nsID
+/** Input GUID argument the interface method declaration. */
+#define IN_GUID const nsID &
+/** Output GUID argument the interface method declaration. */
+#define OUT_GUID nsID **
+
+/** Makes the name of the getter interface function (n must be capitalized). */
+#define COMGETTER(n) Get##n
+/** Makes the name of the setter interface function (n must be capitalized). */
+#define COMSETTER(n) Set##n
+
+/* safearray input parameter macros */
+#define ComSafeArrayIn(aType, aArg) PRUint32 aArg##Size, aType *aArg
+#define ComSafeArrayInIsNull(aArg) ((aArg) == NULL)
+#define ComSafeArrayInArg(aArg) aArg##Size, aArg
+
+/* safearray output parameter macros */
+#define ComSafeArrayOut(aType, aArg) PRUint32 *aArg##Size, aType **aArg
+#define ComSafeArrayOutIsNull(aArg) ((aArg) == NULL)
+#define ComSafeArrayOutArg(aArg) aArg##Size, aArg
+
+/* safearray input parameter macros for GUID */
+#define ComSafeGUIDArrayIn(aArg) PRUint32 aArg##Size, const nsID **aArg
+#define ComSafeGUIDArrayInIsNull(aArg) ComSafeArrayInIsNull(aArg)
+#define ComSafeGUIDArrayInArg(aArg) ComSafeArrayInArg(aArg)
+
+/* safearray output parameter macros for GUID */
+#define ComSafeGUIDArrayOut(aArg) PRUint32 *aArg##Size, nsID ***aArg
+#define ComSafeGUIDArrayOutIsNull(aArg) ComSafeArrayOutIsNull(aArg)
+#define ComSafeGUIDArrayOutArg(aArg) ComSafeArrayOutArg(aArg)
+
+/** safearray size */
+#define ComSafeArraySize(aArg) ((aArg) == NULL ? 0 : (aArg##Size))
+
+/** NOREF a COM safe array argument. */
+#define ComSafeArrayNoRef(aArg) RT_NOREF2(aArg, aArg##Size)
+
+/* CLSID and IID for compatibility with Win32 */
+typedef nsCID CLSID;
+typedef nsIID IID;
+
+/* OLE error codes */
+#define S_OK ((nsresult)NS_OK)
+#define S_FALSE ((nsresult)1)
+#define E_UNEXPECTED NS_ERROR_UNEXPECTED
+#define E_NOTIMPL NS_ERROR_NOT_IMPLEMENTED
+#define E_OUTOFMEMORY NS_ERROR_OUT_OF_MEMORY
+#define E_INVALIDARG NS_ERROR_INVALID_ARG
+#define E_NOINTERFACE NS_ERROR_NO_INTERFACE
+#define E_POINTER NS_ERROR_NULL_POINTER
+#define E_ABORT NS_ERROR_ABORT
+#define E_FAIL NS_ERROR_FAILURE
+/* Note: a better analog for E_ACCESSDENIED would probably be
+ * NS_ERROR_NOT_AVAILABLE, but we want binary compatibility for now. */
+#define E_ACCESSDENIED ((nsresult)0x80070005L)
+
+#define STDMETHOD(a) NS_IMETHOD a
+#define STDMETHODIMP NS_IMETHODIMP
+#define STDMETHOD_(ret, meth) NS_IMETHOD_(ret) meth
+
+#define COM_IIDOF(I) NS_GET_IID(I)
+
+#define COM_STRUCT_OR_CLASS(I) class I
+
+/* helper functions */
+extern "C"
+{
+BSTR SysAllocString(const OLECHAR *sz);
+BSTR SysAllocStringByteLen(char const *psz, unsigned int len);
+BSTR SysAllocStringLen(const OLECHAR *pch, unsigned int cch);
+void SysFreeString(BSTR bstr);
+int SysReAllocString(BSTR *pbstr, const OLECHAR *psz);
+int SysReAllocStringLen(BSTR *pbstr, const OLECHAR *psz, unsigned int cch);
+unsigned int SysStringByteLen(BSTR bstr);
+unsigned int SysStringLen(BSTR bstr);
+}
+
+#ifndef VBOX_COM_NO_ATL
+
+namespace ATL
+{
+
+#define ATL_NO_VTABLE
+#define DECLARE_CLASSFACTORY(a)
+#define DECLARE_CLASSFACTORY_SINGLETON(a)
+#define DECLARE_REGISTRY_RESOURCEID(a)
+#define DECLARE_NOT_AGGREGATABLE(a)
+#define DECLARE_PROTECT_FINAL_CONSTRUCT()
+#define BEGIN_COM_MAP(a)
+#define COM_INTERFACE_ENTRY(a)
+#define COM_INTERFACE_ENTRY2(a,b)
+#define END_COM_MAP() NS_DECL_ISUPPORTS
+#define COM_INTERFACE_ENTRY_AGGREGATE(a,b)
+
+/* A few very simple ATL emulator classes to provide
+ * FinalConstruct()/FinalRelease() functionality with XPCOM. */
+
+class CComMultiThreadModel
+{
+};
+
+template <class DummyThreadModel> class CComObjectRootEx
+{
+public:
+ HRESULT FinalConstruct()
+ {
+ return S_OK;
+ }
+ void FinalRelease()
+ {
+ }
+};
+
+template <class Base> class CComObject : public Base
+{
+public:
+ virtual ~CComObject() { this->FinalRelease(); }
+};
+
+} /* namespace ATL */
+
+
+/**
+ * 'Constructor' for the component class.
+ * This constructor, as opposed to NS_GENERIC_FACTORY_CONSTRUCTOR,
+ * assumes that the component class is derived from the CComObjectRootEx<>
+ * template, so it calls FinalConstruct() right after object creation
+ * and ensures that FinalRelease() will be called right before destruction.
+ * The result from FinalConstruct() is returned to the caller.
+ */
+#define NS_GENERIC_FACTORY_CONSTRUCTOR_WITH_RC(_InstanceClass) \
+static NS_IMETHODIMP \
+_InstanceClass##Constructor(nsISupports *aOuter, REFNSIID aIID, \
+ void **aResult) \
+{ \
+ nsresult rv; \
+ \
+ *aResult = NULL; \
+ if (NULL != aOuter) { \
+ rv = NS_ERROR_NO_AGGREGATION; \
+ return rv; \
+ } \
+ \
+ ATL::CComObject<_InstanceClass> *inst = new ATL::CComObject<_InstanceClass>(); \
+ if (NULL == inst) { \
+ rv = NS_ERROR_OUT_OF_MEMORY; \
+ return rv; \
+ } \
+ \
+ NS_ADDREF(inst); /* protect FinalConstruct() */ \
+ rv = inst->FinalConstruct(); \
+ if (NS_SUCCEEDED(rv)) \
+ rv = inst->QueryInterface(aIID, aResult); \
+ NS_RELEASE(inst); \
+ \
+ return rv; \
+}
+
+/**
+ * 'Constructor' that uses an existing getter function that gets a singleton.
+ * The getter function must have the following prototype:
+ * nsresult _GetterProc(_InstanceClass **inst)
+ * This constructor, as opposed to NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR,
+ * lets the getter function return a result code that is passed back to the
+ * caller that tries to instantiate the object.
+ * NOTE: assumes that getter does an AddRef - so additional AddRef is not done.
+ */
+#define NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR_WITH_RC(_InstanceClass, _GetterProc) \
+static NS_IMETHODIMP \
+_InstanceClass##Constructor(nsISupports *aOuter, REFNSIID aIID, \
+ void **aResult) \
+{ \
+ nsresult rv; \
+ \
+ _InstanceClass *inst = NULL; /* initialized to shut up gcc */ \
+ \
+ *aResult = NULL; \
+ if (NULL != aOuter) { \
+ rv = NS_ERROR_NO_AGGREGATION; \
+ return rv; \
+ } \
+ \
+ rv = _GetterProc(&inst); \
+ if (NS_FAILED(rv)) \
+ return rv; \
+ \
+ /* sanity check */ \
+ if (NULL == inst) \
+ return NS_ERROR_OUT_OF_MEMORY; \
+ \
+ /* NS_ADDREF(inst); */ \
+ if (NS_SUCCEEDED(rv)) { \
+ rv = inst->QueryInterface(aIID, aResult); \
+ } \
+ NS_RELEASE(inst); \
+ \
+ return rv; \
+}
+
+#endif /* !VBOX_COM_NO_ATL */
+
+#endif /* !defined(VBOX_WITH_XPCOM) */
+
+/**
+ * Declares a wchar_t string literal from the argument.
+ * Necessary to overcome MSC / GCC differences.
+ * @param s expression to stringify
+ */
+#if defined(_MSC_VER)
+# define WSTR_LITERAL(s) L#s
+#elif defined(__GNUC__)
+# define WSTR_LITERAL(s) L""#s
+#else
+# error "Unsupported compiler!"
+#endif
+
+namespace com
+{
+
+#ifndef VBOX_COM_NO_ATL
+
+// use this macro to implement scriptable interfaces
+#ifdef RT_OS_WINDOWS
+#define VBOX_SCRIPTABLE_IMPL(iface) \
+ public ATL::IDispatchImpl<iface, &IID_##iface, &LIBID_VirtualBox, \
+ kTypeLibraryMajorVersion, kTypeLibraryMinorVersion>
+
+#define VBOX_SCRIPTABLE_DISPATCH_IMPL(iface) \
+ STDMETHOD(QueryInterface)(REFIID riid, void **ppObj) \
+ { \
+ if (riid == IID_##iface) \
+ { \
+ *ppObj = (iface *)this; \
+ AddRef(); \
+ return S_OK; \
+ } \
+ if (riid == IID_IUnknown) \
+ { \
+ *ppObj = (IUnknown *)this; \
+ AddRef(); \
+ return S_OK; \
+ } \
+ if (riid == IID_IDispatch) \
+ { \
+ *ppObj = (IDispatch *)this; \
+ AddRef(); \
+ return S_OK; \
+ } \
+ *ppObj = NULL; \
+ return E_NOINTERFACE; \
+ }
+#else
+#define VBOX_SCRIPTABLE_IMPL(iface) \
+ public iface
+#define VBOX_SCRIPTABLE_DISPATCH_IMPL(iface)
+#endif
+
+#endif /* !VBOX_COM_NO_ATL */
+
+} /* namespace com */
+
+/** @} */
+
+#endif /* !VBOX_INCLUDED_com_defs_h */
+
diff --git a/include/VBox/com/errorprint.h b/include/VBox/com/errorprint.h
new file mode 100644
index 00000000..037b1ff4
--- /dev/null
+++ b/include/VBox/com/errorprint.h
@@ -0,0 +1,401 @@
+/** @file
+ * MS COM / XPCOM Abstraction Layer - Error Reporting.
+ *
+ * Error printing macros using shared functions defined in shared glue code.
+ * Use these CHECK_* macros for efficient error checking around calling COM
+ * methods.
+ */
+
+/*
+ * Copyright (C) 2009-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_com_errorprint_h
+#define VBOX_INCLUDED_com_errorprint_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/com/ErrorInfo.h>
+
+
+/** @defgroup grp_com_error_reporting Error Reporting
+ * @ingroup grp_com
+ * @{
+ */
+
+namespace com
+{
+
+// shared prototypes; these are defined in shared glue code and are
+// compiled only once for all front-ends
+void GluePrintErrorInfo(const com::ErrorInfo &info);
+void GluePrintErrorContext(const char *pcszContext, const char *pcszSourceFile, uint32_t uLine, bool fWarning = false);
+void GluePrintRCMessage(HRESULT rc);
+void GlueHandleComError(ComPtr<IUnknown> iface, const char *pcszContext, HRESULT rc, const char *pcszSourceFile, uint32_t uLine);
+void GlueHandleComErrorNoCtx(ComPtr<IUnknown> iface, HRESULT rc);
+void GlueHandleComErrorProgress(ComPtr<IProgress> progress, const char *pcszContext, HRESULT rc,
+ const char *pcszSourceFile, uint32_t uLine);
+
+/**
+ * Extended macro that implements all the other CHECK_ERROR2XXX macros.
+ *
+ * Calls the method of the given interface and checks the return status code.
+ * If the status indicates failure, as much information as possible is reported
+ * about the error, including current source file and line.
+ *
+ * After reporting an error, the statement |stmtError| is executed.
+ *
+ * This macro family is intended for command line tools like VBoxManage, but
+ * could also be handy for debugging.
+ *
+ * @param type For defining @a hrc locally inside the the macro
+ * expansion, pass |HRESULT| otherwise |RT_NOTHING|.
+ * @param hrc Name of the HRESULT variable to assign the result of the
+ * method call to.
+ * @param iface The interface pointer (can be a smart pointer object).
+ * @param method The method to invoke together with the parameters.
+ * @param stmtError Statement to be executed after reporting failures. This
+ * can be a |break| or |return| statement, if so desired.
+ *
+ * @remarks Unlike CHECK_ERROR, CHECK_ERROR_RET and family, this macro family
+ * does not presuppose a |rc| variable but instead either let the user
+ * specify the variable to use or employs a local variable |hrcCheck|
+ * within its own scope.
+ *
+ * @sa CHECK_ERROR2, CHECK_ERROR2I, CHECK_ERROR2_STMT, CHECK_ERROR2I_STMT,
+ * CHECK_ERROR2_BREAK, CHECK_ERROR2I_BREAK, CHECK_ERROR2_RET,
+ * CHECK_ERROR2I_RET
+ */
+#define CHECK_ERROR2_EX(type, hrc, iface, method, stmtError) \
+ if (1) { \
+ type hrc = iface->method; \
+ if (SUCCEEDED(hrc) && !SUCCEEDED_WARNING(hrc)) \
+ { /*likely*/ } \
+ else \
+ { \
+ com::GlueHandleComError(iface, #method, (hrc), __FILE__, __LINE__); \
+ if (!SUCCEEDED_WARNING(hrc)) \
+ { \
+ stmtError; \
+ } \
+ } \
+ } else do { /* nothing */ } while (0)
+
+
+/**
+ * Calls the given method of the given interface and then checks if the return
+ * value (COM result code) indicates a failure. If so, prints the failed
+ * function/line/file, the description of the result code and attempts to
+ * query the extended error information on the current thread (using
+ * com::ErrorInfo) if the interface reports that it supports error information.
+ *
+ * Used by command line tools or for debugging and assumes the |HRESULT rc|
+ * variable is accessible for assigning in the current scope.
+ * @sa CHECK_ERROR2, CHECK_ERROR2I
+ */
+#define CHECK_ERROR(iface, method) \
+ do { \
+ hrc = iface->method; \
+ if (FAILED(hrc) || SUCCEEDED_WARNING(hrc)) \
+ com::GlueHandleComError(iface, #method, hrc, __FILE__, __LINE__); \
+ } while (0)
+/**
+ * Simplified version of CHECK_ERROR2_EX, no error statement or type necessary.
+ *
+ * @param hrc Name of the HRESULT variable to assign the result of the
+ * method call to.
+ * @param iface The interface pointer (can be a smart pointer object).
+ * @param method The method to invoke together with the parameters.
+ * @sa CHECK_ERROR2I, CHECK_ERROR2_EX
+ */
+#define CHECK_ERROR2(hrc, iface, method) CHECK_ERROR2_EX(RT_NOTHING, hrc, iface, method, (void)1)
+/**
+ * Simplified version of CHECK_ERROR2_EX that uses an internal variable
+ * |hrcCheck| for holding the result and have no error statement.
+ *
+ * @param iface The interface pointer (can be a smart pointer object).
+ * @param method The method to invoke together with the parameters.
+ * @sa CHECK_ERROR2, CHECK_ERROR2_EX
+ */
+#define CHECK_ERROR2I(iface, method) CHECK_ERROR2_EX(HRESULT, hrcCheck, iface, method, (void)1)
+
+
+/**
+ * Same as CHECK_ERROR except that it also executes the statement |stmt| on
+ * failure.
+ * @sa CHECK_ERROR2_STMT, CHECK_ERROR2I_STMT
+ */
+#define CHECK_ERROR_STMT(iface, method, stmt) \
+ do { \
+ hrc = iface->method; \
+ if (FAILED(hrc) || SUCCEEDED_WARNING(hrc)) \
+ { \
+ com::GlueHandleComError(iface, #method, hrc, __FILE__, __LINE__); \
+ if (!SUCCEEDED_WARNING(hrc) \
+ { \
+ stmt; \
+ } \
+ } \
+ } while (0)
+/**
+ * Simplified version of CHECK_ERROR2_EX (no @a hrc type).
+ *
+ * @param hrc Name of the HRESULT variable to assign the result of the
+ * method call to.
+ * @param iface The interface pointer (can be a smart pointer object).
+ * @param method The method to invoke together with the parameters.
+ * @param stmt Statement to be executed after reporting failures.
+ * @sa CHECK_ERROR2I_STMT, CHECK_ERROR2_EX
+ */
+#define CHECK_ERROR2_STMT(hrc, iface, method, stmt) CHECK_ERROR2_EX(RT_NOTHING, hrc, iface, method, stmt)
+/**
+ * Simplified version of CHECK_ERROR2_EX that uses an internal variable
+ * |hrcCheck| for holding the result.
+ *
+ * @param iface The interface pointer (can be a smart pointer object).
+ * @param method The method to invoke together with the parameters.
+ * @param stmt Statement to be executed after reporting failures.
+ * @sa CHECK_ERROR2_STMT, CHECK_ERROR2_EX
+ */
+#define CHECK_ERROR2I_STMT(iface, method, stmt) CHECK_ERROR2_EX(HRESULT, hrcCheck, iface, method, stmt)
+
+
+/**
+ * Does the same as CHECK_ERROR(), but executes the |break| statement on
+ * failure.
+ * @sa CHECK_ERROR2_BREAK, CHECK_ERROR2I_BREAK
+ */
+#ifdef __GNUC__
+# define CHECK_ERROR_BREAK(iface, method) \
+ __extension__ \
+ ({ \
+ hrc = iface->method; \
+ if (FAILED(hrc) || SUCCEEDED_WARNING(hrc)) \
+ { \
+ com::GlueHandleComError(iface, #method, hrc, __FILE__, __LINE__); \
+ if (!SUCCEEDED_WARNING(hrc)) \
+ break; \
+ } \
+ })
+#else
+# define CHECK_ERROR_BREAK(iface, method) \
+ if (1) \
+ { \
+ hrc = iface->method; \
+ if (FAILED(hrc)) \
+ { \
+ com::GlueHandleComError(iface, #method, hrc, __FILE__, __LINE__); \
+ if (!SUCCEEDED_WARNING(hrc)) \
+ break; \
+ } \
+ } \
+ else do {} while (0)
+#endif
+/**
+ * Simplified version of CHECK_ERROR2_EX that executes the |break| statement
+ * after error reporting (no @a hrc type).
+ *
+ * @param hrc The result variable (type HRESULT).
+ * @param iface The interface pointer (can be a smart pointer object).
+ * @param method The method to invoke together with the parameters.
+ * @sa CHECK_ERROR2I_BREAK, CHECK_ERROR2_EX
+ */
+#define CHECK_ERROR2_BREAK(hrc, iface, method) CHECK_ERROR2_EX(RT_NOTHING, hrc, iface, method, break)
+/**
+ * Simplified version of CHECK_ERROR2_EX that executes the |break| statement
+ * after error reporting and that uses an internal variable |hrcCheck| for
+ * holding the result.
+ *
+ * @param iface The interface pointer (can be a smart pointer object).
+ * @param method The method to invoke together with the parameters.
+ * @sa CHECK_ERROR2_BREAK, CHECK_ERROR2_EX
+ */
+#define CHECK_ERROR2I_BREAK(iface, method) CHECK_ERROR2_EX(HRESULT, hrcCheck, iface, method, break)
+/**
+ * Simplified version of CHECK_ERROR2_EX that executes the |stmt;break|
+ * statements after error reporting and that uses an internal variable
+ * |hrcCheck| for holding the result.
+ *
+ * @param iface The interface pointer (can be a smart pointer object).
+ * @param method The method to invoke together with the parameters.
+ * @param stmt Statement to be executed after reporting failures.
+ * @sa CHECK_ERROR2_BREAK, CHECK_ERROR2_EX
+ */
+#define CHECK_ERROR2I_BREAK_STMT(iface, method, stmt) CHECK_ERROR2_EX(HRESULT, hrcCheck, iface, method, stmt; break)
+
+
+/**
+ * Does the same as CHECK_ERROR(), but executes the |return ret| statement on
+ * failure.
+ * @sa CHECK_ERROR2_RET, CHECK_ERROR2I_RET
+ */
+#define CHECK_ERROR_RET(iface, method, ret) \
+ do { \
+ hrc = iface->method; \
+ if (FAILED(hrc) || SUCCEEDED_WARNING(hrc)) \
+ { \
+ com::GlueHandleComError(iface, #method, hrc, __FILE__, __LINE__); \
+ if (!SUCCEEDED_WARNING(hrc)) \
+ return (ret); \
+ } \
+ } while (0)
+/**
+ * Simplified version of CHECK_ERROR2_EX that executes the |return (rcRet)|
+ * statement after error reporting.
+ *
+ * @param hrc The result variable (type HRESULT).
+ * @param iface The interface pointer (can be a smart pointer object).
+ * @param method The method to invoke together with the parameters.
+ * @param rcRet What to return on failure.
+ */
+#define CHECK_ERROR2_RET(hrc, iface, method, rcRet) CHECK_ERROR2_EX(RT_NOTHING, hrc, iface, method, return (rcRet))
+/**
+ * Simplified version of CHECK_ERROR2_EX that executes the |return (rcRet)|
+ * statement after error reporting and that uses an internal variable |hrcCheck|
+ * for holding the result.
+ *
+ * @param iface The interface pointer (can be a smart pointer object).
+ * @param method The method to invoke together with the parameters.
+ * @param rcRet What to return on failure. Use |hrcCheck| to return
+ * the status code of the method call.
+ */
+#define CHECK_ERROR2I_RET(iface, method, rcRet) CHECK_ERROR2_EX(HRESULT, hrcCheck, iface, method, return (rcRet))
+
+
+/**
+ * Check the progress object for an error and if there is one print out the
+ * extended error information.
+ * @remarks Requires HRESULT variable named @a rc.
+ */
+#define CHECK_PROGRESS_ERROR(progress, msg) \
+ do { \
+ LONG iRc; \
+ hrc = progress->COMGETTER(ResultCode)(&iRc); \
+ if (FAILED(hrc) || FAILED(iRc)) \
+ { \
+ if (SUCCEEDED(hrc)) hrc = iRc; else iRc = hrc; \
+ RTMsgError msg; \
+ com::GlueHandleComErrorProgress(progress, __PRETTY_FUNCTION__, iRc, __FILE__, __LINE__); \
+ } \
+ } while (0)
+
+/**
+ * Does the same as CHECK_PROGRESS_ERROR(), but executes the |break| statement
+ * on failure.
+ * @remarks Requires HRESULT variable named @a rc.
+ */
+#ifdef __GNUC__
+# define CHECK_PROGRESS_ERROR_BREAK(progress, msg) \
+ __extension__ \
+ ({ \
+ LONG iRc; \
+ hrc = progress->COMGETTER(ResultCode)(&iRc); \
+ if (FAILED(hrc) || FAILED(iRc)) \
+ { \
+ if (SUCCEEDED(hrc)) hrc = iRc; else iRc = hrc; \
+ RTMsgError msg; \
+ com::GlueHandleComErrorProgress(progress, __PRETTY_FUNCTION__, iRc, __FILE__, __LINE__); \
+ break; \
+ } \
+ })
+#else
+# define CHECK_PROGRESS_ERROR_BREAK(progress, msg) \
+ if (1) \
+ { \
+ LONG iRc; \
+ hrc = progress->COMGETTER(ResultCode)(&iRc); \
+ if (FAILED(hrc) || FAILED(iRc)) \
+ { \
+ if (SUCCEEDED(hrc)) hrc = iRc; else iRc = hrc; \
+ RTMsgError msg; \
+ com::GlueHandleComErrorProgress(progress, __PRETTY_FUNCTION__, iRc, __FILE__, __LINE__); \
+ break; \
+ } \
+ } \
+ else do {} while (0)
+#endif
+
+/**
+ * Does the same as CHECK_PROGRESS_ERROR(), but executes the |return ret|
+ * statement on failure.
+ */
+#define CHECK_PROGRESS_ERROR_RET(progress, msg, ret) \
+ do { \
+ LONG iRc; \
+ HRESULT hrcCheck = progress->COMGETTER(ResultCode)(&iRc); \
+ if (SUCCEEDED(hrcCheck) && SUCCEEDED(iRc)) \
+ { /* likely */ } \
+ else \
+ { \
+ RTMsgError msg; \
+ com::GlueHandleComErrorProgress(progress, __PRETTY_FUNCTION__, \
+ SUCCEEDED(hrcCheck) ? iRc : hrcCheck, __FILE__, __LINE__); \
+ return (ret); \
+ } \
+ } while (0)
+
+/**
+ * Asserts the given expression is true. When the expression is false, prints
+ * a line containing the failed function/line/file; otherwise does nothing.
+ */
+#define ASSERT(expr) \
+ do { \
+ if (!(expr)) \
+ { \
+ RTPrintf ("[!] ASSERTION FAILED at line %d: %s\n", __LINE__, #expr); \
+ Log (("[!] ASSERTION FAILED at line %d: %s\n", __LINE__, #expr)); \
+ } \
+ } while (0)
+
+
+/**
+ * Does the same as ASSERT(), but executes the |return ret| statement if the
+ * expression to assert is false;
+ * @remarks WARNING! @a expr is evalutated TWICE!
+ */
+#define ASSERT_RET(expr, ret) \
+ do { ASSERT(expr); if (!(expr)) return (ret); } while (0)
+
+/**
+ * Does the same as ASSERT(), but executes the |break| statement if the
+ * expression to assert is false;
+ * @remarks WARNING! @a expr is evalutated TWICE!
+ */
+#define ASSERT_BREAK(expr, ret) \
+ if (1) { ASSERT(expr); if (!(expr)) break; } else do {} while (0)
+
+} /* namespace com */
+
+
+/** @} */
+
+#endif /* !VBOX_INCLUDED_com_errorprint_h */
+
diff --git a/include/VBox/com/list.h b/include/VBox/com/list.h
new file mode 100644
index 00000000..e898e15b
--- /dev/null
+++ b/include/VBox/com/list.h
@@ -0,0 +1,223 @@
+/* $Id: list.h $ */
+/** @file
+ * MS COM / XPCOM Abstraction Layer - List classes declaration.
+ */
+
+/*
+ * Copyright (C) 2011-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_com_list_h
+#define VBOX_INCLUDED_com_list_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/com/ptr.h>
+#include <VBox/com/string.h>
+#include <VBox/com/array.h>
+#include <iprt/cpp/list.h>
+
+
+/** @defgroup grp_com_list List Classes
+ * @ingroup grp_com
+ * @{
+ */
+
+/**
+ * Specialized list class for using with com::ComPtr<C>
+ *
+ * @note This is necessary cause ComPtr<IFACE> has a size of 8.
+ */
+template <typename C>
+class RTCList< ComPtr<C> >: public RTCListBase< ComPtr<C>, ComPtr<C>*, false>
+{
+ /* Traits */
+ typedef ComPtr<C> T;
+ typedef T *ITYPE;
+ static const bool MT = false;
+ typedef RTCListBase<T, ITYPE, MT> BASE;
+
+public:
+ /**
+ * Creates a new list.
+ *
+ * This preallocates @a cCapacity elements within the list.
+ *
+ * @param cCapacity The initial capacity the list has.
+ * @throws std::bad_alloc
+ */
+ RTCList(size_t cCapacity = BASE::kDefaultCapacity)
+ : BASE(cCapacity) {}
+
+ /* Define our own new and delete. */
+ RTMEMEF_NEW_AND_DELETE_OPERATORS();
+};
+
+/**
+ * Specialized list class for using with com::ComObjPtr<C>
+ *
+ * @note: This is necessary cause ComObjPtr<IFACE> has a size of 8.
+ */
+template <typename C>
+class RTCList< ComObjPtr<C> >: public RTCListBase< ComObjPtr<C>, ComObjPtr<C>*, false>
+{
+ /* Traits */
+ typedef ComObjPtr<C> T;
+ typedef T *ITYPE;
+ static const bool MT = false;
+ typedef RTCListBase<T, ITYPE, MT> BASE;
+
+public:
+ /**
+ * Creates a new list.
+ *
+ * This preallocates @a cCapacity elements within the list.
+ *
+ * @param cCapacity The initial capacity the list has.
+ * @throws std::bad_alloc
+ */
+ RTCList(size_t cCapacity = BASE::kDefaultCapacity)
+ : BASE(cCapacity) {}
+
+ /* Define our own new and delete. */
+ RTMEMEF_NEW_AND_DELETE_OPERATORS();
+};
+
+/**
+ * Specialized list class for using with com::Utf8Str.
+ *
+ * The class offers methods for importing com::SafeArray's of com::Bstr's.
+ */
+template <>
+class RTCList<com::Utf8Str>: public RTCListBase<com::Utf8Str, com::Utf8Str*, false>
+{
+ /* Traits */
+ typedef com::Utf8Str T;
+ typedef T *ITYPE;
+ static const bool MT = false;
+ typedef RTCListBase<T, ITYPE, MT> BASE;
+
+public:
+ /**
+ * Creates a new list.
+ *
+ * This preallocates @a cCapacity elements within the list.
+ *
+ * @param cCapacity The initial capacity the list has.
+ * @throws std::bad_alloc
+ */
+ RTCList(size_t cCapacity = BASE::kDefaultCapacity)
+ : BASE(cCapacity) {}
+
+ /**
+ * Creates a copy of another list.
+ *
+ * The other list will be fully copied and the capacity will be the same as
+ * the size of the other list. The com::Bstr's are silently converted to
+ * com::Utf8Str's.
+ *
+ * @param other The list to copy.
+ * @throws std::bad_alloc
+ */
+ RTCList(ComSafeArrayIn(IN_BSTR, other))
+ {
+ com::SafeArray<IN_BSTR> sfaOther(ComSafeArrayInArg(other));
+ size_t const cElementsOther = sfaOther.size();
+ resizeArray(cElementsOther);
+ m_cElements = cElementsOther;
+ for (size_t i = 0; i < cElementsOther; ++i)
+ RTCListHelper<T, ITYPE>::set(m_pArray, i, T(sfaOther[i]));
+ }
+
+ /**
+ * Creates a copy of another list.
+ *
+ * The other list will be fully copied and the capacity will be the same as
+ * the size of the other list. The com::Bstr's are silently converted to
+ * com::Utf8Str's.
+ *
+ * @param other The list to copy.
+ * @throws std::bad_alloc
+ */
+ RTCList(const com::SafeArray<IN_BSTR> &other)
+ : BASE(other.size())
+ {
+ for (size_t i = 0; i < m_cElements; ++i)
+ RTCListHelper<T, ITYPE>::set(m_pArray, i, T(other[i]));
+ }
+
+ /**
+ * Copy the items of the other list into this list. All previous items of
+ * this list are deleted.
+ *
+ * @param other The list to copy.
+ * @return a reference to this list.
+ * @throws std::bad_alloc
+ */
+ RTCListBase<T, ITYPE, MT> &operator=(const com::SafeArray<IN_BSTR> &other)
+ {
+ m_guard.enterWrite();
+
+ /* Values cleanup */
+ RTCListHelper<T, ITYPE>::eraseRange(m_pArray, 0, m_cElements);
+
+ /* Copy */
+ size_t cElementsOther = other.size();
+ if (cElementsOther != m_cCapacity)
+ resizeArrayNoErase(cElementsOther);
+ m_cElements = cElementsOther;
+ for (size_t i = 0; i < cElementsOther; ++i)
+ RTCListHelper<T, ITYPE>::set(m_pArray, i, T(other[i]));
+
+ m_guard.leaveWrite();
+ return *this;
+ }
+
+ /**
+ * Implicit conversion to a RTCString list.
+ *
+ * This allows the usage of the RTCString::join method with this list type.
+ *
+ * @return a converted const reference to this list.
+ */
+ operator const RTCList<RTCString, RTCString*>&()
+ {
+ return *reinterpret_cast<RTCList<RTCString, RTCString*> *>(this);
+ }
+
+ /* Define our own new and delete. */
+ RTMEMEF_NEW_AND_DELETE_OPERATORS();
+};
+
+/** @} */
+
+#endif /* !VBOX_INCLUDED_com_list_h */
+
diff --git a/include/VBox/com/listeners.h b/include/VBox/com/listeners.h
new file mode 100644
index 00000000..06f35ebf
--- /dev/null
+++ b/include/VBox/com/listeners.h
@@ -0,0 +1,194 @@
+/* $Id: listeners.h $ */
+/** @file
+ * MS COM / XPCOM Abstraction Layer - Listener helpers.
+ */
+
+/*
+ * Copyright (C) 2010-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_com_listeners_h
+#define VBOX_INCLUDED_com_listeners_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/com/com.h>
+#include <VBox/com/VirtualBox.h>
+
+
+/** @defgroup grp_com_listeners Listener Helpers
+ * @ingroup grp_com
+ * @{
+ */
+
+
+#ifdef VBOX_WITH_XPCOM
+# define NS_IMPL_QUERY_HEAD_INLINE() \
+NS_IMETHODIMP QueryInterface(REFNSIID aIID, void **aInstancePtr) \
+{ \
+ NS_ASSERTION(aInstancePtr, "QueryInterface requires a non-NULL destination!"); \
+ nsISupports *foundInterface;
+
+# define NS_INTERFACE_MAP_BEGIN_INLINE() NS_IMPL_QUERY_HEAD_INLINE()
+
+# define NS_IMPL_QUERY_INTERFACE1_INLINE(a_i1) \
+ NS_INTERFACE_MAP_BEGIN_INLINE() \
+ NS_INTERFACE_MAP_ENTRY(a_i1) \
+ NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, a_i1) \
+ NS_INTERFACE_MAP_END
+#endif
+
+template <class T, class TParam = void *>
+class ListenerImpl :
+ public ATL::CComObjectRootEx<ATL::CComMultiThreadModel>,
+ VBOX_SCRIPTABLE_IMPL(IEventListener)
+{
+ T* mListener;
+
+#ifdef RT_OS_WINDOWS
+ /* FTM stuff */
+ ComPtr<IUnknown> m_pUnkMarshaler;
+#else
+ nsAutoRefCnt mRefCnt;
+ NS_DECL_OWNINGTHREAD
+#endif
+
+public:
+ ListenerImpl()
+ {
+ }
+
+ virtual ~ListenerImpl()
+ {
+ }
+
+ HRESULT init(T* aListener, TParam param)
+ {
+ mListener = aListener;
+ return mListener->init(param);
+ }
+
+ HRESULT init(T* aListener)
+ {
+ mListener = aListener;
+ return mListener->init();
+ }
+
+ void uninit()
+ {
+ if (mListener)
+ {
+ mListener->uninit();
+ delete mListener;
+ mListener = 0;
+ }
+ }
+
+ HRESULT FinalConstruct()
+ {
+#ifdef RT_OS_WINDOWS
+ return CoCreateFreeThreadedMarshaler(this, &m_pUnkMarshaler.m_p);
+#else
+ return S_OK;
+#endif
+ }
+
+ void FinalRelease()
+ {
+ uninit();
+#ifdef RT_OS_WINDOWS
+ m_pUnkMarshaler.setNull();
+#endif
+ }
+
+ T* getWrapped()
+ {
+ return mListener;
+ }
+
+ DECLARE_NOT_AGGREGATABLE(ListenerImpl)
+
+ DECLARE_PROTECT_FINAL_CONSTRUCT()
+
+#ifdef RT_OS_WINDOWS
+ BEGIN_COM_MAP(ListenerImpl)
+ COM_INTERFACE_ENTRY(IEventListener)
+ COM_INTERFACE_ENTRY2(IDispatch, IEventListener)
+ COM_INTERFACE_ENTRY_AGGREGATE(IID_IMarshal, m_pUnkMarshaler.m_p)
+ END_COM_MAP()
+#else
+ NS_IMETHOD_(nsrefcnt) AddRef(void)
+ {
+ NS_PRECONDITION(PRInt32(mRefCnt) >= 0, "illegal refcnt");
+ nsrefcnt count;
+ count = PR_AtomicIncrement((PRInt32*)&mRefCnt);
+ NS_LOG_ADDREF(this, count, "ListenerImpl", sizeof(*this));
+ return count;
+ }
+
+ NS_IMETHOD_(nsrefcnt) Release(void)
+ {
+ nsrefcnt count;
+ NS_PRECONDITION(0 != mRefCnt, "dup release");
+ count = PR_AtomicDecrement((PRInt32 *)&mRefCnt);
+ NS_LOG_RELEASE(this, count, "ListenerImpl");
+ if (0 == count) {
+ mRefCnt = 1; /* stabilize */
+ /* enable this to find non-threadsafe destructors: */
+ /* NS_ASSERT_OWNINGTHREAD(_class); */
+ NS_DELETEXPCOM(this);
+ return 0;
+ }
+ return count;
+ }
+
+ NS_IMPL_QUERY_INTERFACE1_INLINE(IEventListener)
+#endif
+
+
+ STDMETHOD(HandleEvent)(IEvent * aEvent)
+ {
+ VBoxEventType_T aType = VBoxEventType_Invalid;
+ HRESULT hrc = aEvent->COMGETTER(Type)(&aType);
+ AssertMsg(SUCCEEDED(hrc), ("hrc=%Rhrc\n", hrc)); RT_NOREF(hrc);
+ return mListener->HandleEvent(aType, aEvent);
+ }
+};
+
+#ifdef VBOX_WITH_XPCOM
+# define VBOX_LISTENER_DECLARE(klazz) NS_DECL_CLASSINFO(klazz)
+#else
+# define VBOX_LISTENER_DECLARE(klazz)
+#endif
+
+/** @} */
+#endif /* !VBOX_INCLUDED_com_listeners_h */
+
diff --git a/include/VBox/com/microatl.h b/include/VBox/com/microatl.h
new file mode 100644
index 00000000..7066ed02
--- /dev/null
+++ b/include/VBox/com/microatl.h
@@ -0,0 +1,1408 @@
+/** @file
+ * ATL lookalike, just the tiny subset we actually need.
+ */
+
+/*
+ * Copyright (C) 2016-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_com_microatl_h
+#define VBOX_INCLUDED_com_microatl_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/cdefs.h> /* VBOX_STRICT */
+#include <iprt/assert.h>
+#include <iprt/critsect.h>
+#include <iprt/errcore.h> /* RT_FAILURE() */
+
+#include <iprt/win/windows.h>
+
+#include <new>
+
+
+namespace ATL
+{
+
+#define ATL_NO_VTABLE __declspec(novtable)
+
+class CAtlModule;
+__declspec(selectany) CAtlModule *_pAtlModule = NULL;
+
+class CComModule;
+__declspec(selectany) CComModule *_pModule = NULL;
+
+typedef HRESULT (WINAPI FNCREATEINSTANCE)(void *pv, REFIID riid, void **ppv);
+typedef FNCREATEINSTANCE *PFNCREATEINSTANCE;
+typedef HRESULT (WINAPI FNINTERFACEMAPHELPER)(void *pv, REFIID riid, void **ppv, DWORD_PTR dw);
+typedef FNINTERFACEMAPHELPER *PFNINTERFACEMAPHELPER;
+typedef void (__stdcall FNATLTERMFUNC)(void *pv);
+typedef FNATLTERMFUNC *PFNATLTERMFUNC;
+
+struct _ATL_TERMFUNC_ELEM
+{
+ PFNATLTERMFUNC pfn;
+ void *pv;
+ _ATL_TERMFUNC_ELEM *pNext;
+};
+
+struct _ATL_INTMAP_ENTRY
+{
+ const IID *piid; // interface ID
+ DWORD_PTR dw;
+ PFNINTERFACEMAPHELPER pFunc; // NULL: end of array, 1: offset based map entry, other: function pointer
+};
+
+#define COM_SIMPLEMAPENTRY ((ATL::PFNINTERFACEMAPHELPER)1)
+
+#define DECLARE_CLASSFACTORY_EX(c) typedef ATL::CComCreator<ATL::CComObjectNoLock<c> > _ClassFactoryCreatorClass;
+#define DECLARE_CLASSFACTORY() DECLARE_CLASSFACTORY_EX(ATL::CComClassFactory)
+#define DECLARE_CLASSFACTORY_SINGLETON(o) DECLARE_CLASSFACTORY_EX(ATL::CComClassFactorySingleton<o>)
+#define DECLARE_AGGREGATABLE(c) \
+public: \
+ typedef ATL::CComCreator2<ATL::CComCreator<ATL::CComObject<c> >, ATL::CComCreator<ATL::CComAggObject<c> > > _CreatorClass;
+#define DECLARE_NOT_AGGREGATABLE(c) \
+public: \
+ typedef ATL::CComCreator2<ATL::CComCreator<ATL::CComObject<c> >, ATL::CComFailCreator<CLASS_E_NOAGGREGATION> > _CreatorClass;
+
+#define DECLARE_PROTECT_FINAL_CONSTRUCT() \
+ void InternalFinalConstructAddRef() \
+ { \
+ InternalAddRef(); \
+ } \
+ void InternalFinalConstructRelease() \
+ { \
+ InternalRelease(); \
+ }
+
+#define BEGIN_COM_MAP(c) \
+public: \
+ typedef c _ComClass; \
+ HRESULT _InternalQueryInterface(REFIID iid, void **ppvObj) throw() \
+ { \
+ return InternalQueryInterface(this, _GetEntries(), iid, ppvObj); \
+ } \
+ const static ATL::_ATL_INTMAP_ENTRY *WINAPI _GetEntries() throw() \
+ { \
+ static const ATL::_ATL_INTMAP_ENTRY _aInterfaces[] = \
+ {
+
+#define COM_INTERFACE_ENTRY(c) \
+ { &__uuidof(c), (DWORD_PTR)(static_cast<c *>((_ComClass *)8))-8, COM_SIMPLEMAPENTRY },
+
+#define COM_INTERFACE_ENTRY2(c, c2) \
+ { &__uuidof(c), (DWORD_PTR)(static_cast<c *>(static_cast<c2 *>((_ComClass *)8)))-8, COM_SIMPLEMAPENTRY },
+
+#define COM_INTERFACE_ENTRY_AGGREGATE(iid, pUnk) \
+ { &iid, (DWORD_PTR)RT_UOFFSETOF(_ComClass, pUnk), _Delegate},
+
+#define END_COM_MAP() \
+ { NULL, 0, NULL} \
+ }; \
+ return _aInterfaces; \
+ } \
+ virtual ULONG STDMETHODCALLTYPE AddRef(void) throw() = 0; \
+ virtual ULONG STDMETHODCALLTYPE Release(void) throw() = 0; \
+ STDMETHOD(QueryInterface)(REFIID, void **) throw() = 0;
+
+struct _ATL_OBJMAP_ENTRY
+{
+ const CLSID *pclsid;
+ PFNCREATEINSTANCE pfnGetClassObject;
+ PFNCREATEINSTANCE pfnCreateInstance;
+ IUnknown *pCF;
+ DWORD dwRegister;
+};
+
+#define BEGIN_OBJECT_MAP(o) static ATL::_ATL_OBJMAP_ENTRY o[] = {
+#define END_OBJECT_MAP() {NULL, NULL, NULL, NULL, 0}};
+#define OBJECT_ENTRY(clsid, c) {&clsid, c::_ClassFactoryCreatorClass::CreateInstance, c::_CreatorClass::CreateInstance, NULL, 0 },
+
+
+class CComCriticalSection
+{
+public:
+ CComCriticalSection() throw()
+ {
+ memset(&m_CritSect, 0, sizeof(m_CritSect));
+ }
+ ~CComCriticalSection()
+ {
+ }
+ HRESULT Lock() throw()
+ {
+ RTCritSectEnter(&m_CritSect);
+ return S_OK;
+ }
+ HRESULT Unlock() throw()
+ {
+ RTCritSectLeave(&m_CritSect);
+ return S_OK;
+ }
+ HRESULT Init() throw()
+ {
+ HRESULT hrc = S_OK;
+ if (RT_FAILURE(RTCritSectInit(&m_CritSect)))
+ hrc = E_FAIL;
+ return hrc;
+ }
+
+ HRESULT Term() throw()
+ {
+ RTCritSectDelete(&m_CritSect);
+ return S_OK;
+ }
+
+ RTCRITSECT m_CritSect;
+};
+
+template<class TLock>
+class CComCritSectLockManual
+{
+public:
+ CComCritSectLockManual(CComCriticalSection &cs)
+ : m_cs(cs)
+ , m_fLocked(false)
+ {
+ }
+
+ ~CComCritSectLockManual() throw()
+ {
+ if (m_fLocked)
+ Unlock();
+ }
+
+ HRESULT Lock()
+ {
+ Assert(!m_fLocked);
+ HRESULT hrc = m_cs.Lock();
+ if (FAILED(hrc))
+ return hrc;
+ m_fLocked = true;
+ return S_OK;
+ }
+
+ void Unlock() throw()
+ {
+ Assert(m_fLocked);
+ m_cs.Unlock();
+ m_fLocked = false;
+ }
+
+
+private:
+ TLock &m_cs;
+ bool m_fLocked;
+
+ CComCritSectLockManual(const CComCritSectLockManual&) throw(); // Do not call.
+ CComCritSectLockManual &operator=(const CComCritSectLockManual &) throw(); // Do not call.
+};
+
+
+#ifdef RT_EXCEPTIONS_ENABLED
+/** This is called CComCritSecLock in real ATL... */
+template<class TLock>
+class CComCritSectLock : public CComCritSectLockManual<TLock>
+{
+public:
+ CComCritSectLock(CComCriticalSection &cs, bool fInitialLock = true)
+ : CComCritSectLockManual(cs)
+ {
+ if (fInitialLock)
+ {
+ HRESULT hrc = Lock();
+ if (FAILED(hrc))
+ throw hrc;
+ }
+ }
+
+private:
+ CComCritSectLock(const CComCritSectLock&) throw(); // Do not call.
+ CComCritSectLock &operator=(const CComCritSectLock &) throw(); // Do not call.
+};
+#endif
+
+class CComFakeCriticalSection
+{
+public:
+ HRESULT Lock() throw()
+ {
+ return S_OK;
+ }
+ HRESULT Unlock() throw()
+ {
+ return S_OK;
+ }
+ HRESULT Init() throw()
+ {
+ return S_OK;
+ }
+ HRESULT Term() throw()
+ {
+ return S_OK;
+ }
+};
+
+class CComAutoCriticalSection : public CComCriticalSection
+{
+public:
+ CComAutoCriticalSection()
+ {
+ HRESULT hrc = CComCriticalSection::Init();
+ if (FAILED(hrc))
+ throw hrc;
+ }
+ ~CComAutoCriticalSection() throw()
+ {
+ CComCriticalSection::Term();
+ }
+private :
+ HRESULT Init() throw(); // Do not call.
+ HRESULT Term() throw(); // Do not call.
+};
+
+class CComAutoDeleteCriticalSection : public CComCriticalSection
+{
+public:
+ CComAutoDeleteCriticalSection(): m_fInit(false)
+ {
+ }
+
+ ~CComAutoDeleteCriticalSection() throw()
+ {
+ if (!m_fInit)
+ return;
+ m_fInit = false;
+ CComCriticalSection::Term();
+ }
+
+ HRESULT Init() throw()
+ {
+ Assert(!m_fInit);
+ HRESULT hrc = CComCriticalSection::Init();
+ if (SUCCEEDED(hrc))
+ m_fInit = true;
+ return hrc;
+ }
+
+ HRESULT Lock()
+ {
+ Assert(m_fInit);
+ return CComCriticalSection::Lock();
+ }
+
+ HRESULT Unlock()
+ {
+ Assert(m_fInit);
+ return CComCriticalSection::Unlock();
+ }
+
+private:
+ HRESULT Term() throw();
+ bool m_fInit;
+};
+
+
+class CComMultiThreadModelNoCS
+{
+public:
+ static ULONG WINAPI Increment(LONG *pL) throw()
+ {
+ return InterlockedIncrement(pL);
+ }
+ static ULONG WINAPI Decrement(LONG *pL) throw()
+ {
+ return InterlockedDecrement(pL);
+ }
+ typedef CComFakeCriticalSection AutoCriticalSection;
+ typedef CComFakeCriticalSection AutoDeleteCriticalSection;
+ typedef CComMultiThreadModelNoCS ThreadModelNoCS;
+};
+
+class CComMultiThreadModel
+{
+public:
+ static ULONG WINAPI Increment(LONG *pL) throw()
+ {
+ return InterlockedIncrement(pL);
+ }
+ static ULONG WINAPI Decrement(LONG *pL) throw()
+ {
+ return InterlockedDecrement(pL);
+ }
+ typedef CComAutoCriticalSection AutoCriticalSection;
+ typedef CComAutoDeleteCriticalSection AutoDeleteCriticalSection;
+ typedef CComMultiThreadModelNoCS ThreadModelNoCS;
+};
+
+class ATL_NO_VTABLE CAtlModule
+{
+public:
+ static GUID m_LibID;
+ CComCriticalSection m_csStaticDataInitAndTypeInfo;
+
+ CAtlModule() throw()
+ {
+ // One instance only per linking namespace!
+ AssertMsg(!_pAtlModule, ("CAtlModule: trying to create more than one instance per linking namespace\n"));
+
+ fInit = false;
+
+ m_cLock = 0;
+ m_pTermFuncs = NULL;
+ _pAtlModule = this;
+
+ if (FAILED(m_csStaticDataInitAndTypeInfo.Init()))
+ {
+ AssertMsgFailed(("CAtlModule: failed to init critsect\n"));
+ return;
+ }
+ fInit = true;
+ }
+
+ void Term() throw()
+ {
+ if (!fInit)
+ return;
+
+ // Call all term functions.
+ if (m_pTermFuncs)
+ {
+ _ATL_TERMFUNC_ELEM *p = m_pTermFuncs;
+ _ATL_TERMFUNC_ELEM *pNext;
+ while (p)
+ {
+ p->pfn(p->pv);
+ pNext = p->pNext;
+ delete p;
+ p = pNext;
+ }
+ m_pTermFuncs = NULL;
+ }
+ m_csStaticDataInitAndTypeInfo.Term();
+ fInit = false;
+ }
+
+ virtual ~CAtlModule() throw()
+ {
+ Term();
+ }
+
+ virtual LONG Lock() throw()
+ {
+ return CComMultiThreadModel::Increment(&m_cLock);
+ }
+
+ virtual LONG Unlock() throw()
+ {
+ return CComMultiThreadModel::Decrement(&m_cLock);
+ }
+
+ virtual LONG GetLockCount() throw()
+ {
+ return m_cLock;
+ }
+
+ HRESULT AddTermFunc(PFNATLTERMFUNC pfn, void *pv)
+ {
+ _ATL_TERMFUNC_ELEM *pNew = new(std::nothrow) _ATL_TERMFUNC_ELEM;
+ if (!pNew)
+ return E_OUTOFMEMORY;
+ pNew->pfn = pfn;
+ pNew->pv = pv;
+ CComCritSectLockManual<CComCriticalSection> lock(m_csStaticDataInitAndTypeInfo);
+ HRESULT hrc = lock.Lock();
+ if (SUCCEEDED(hrc))
+ {
+ pNew->pNext = m_pTermFuncs;
+ m_pTermFuncs = pNew;
+ }
+ else
+ {
+ delete pNew;
+ AssertMsgFailed(("CComModule::AddTermFunc: failed to lock critsect\n"));
+ }
+ return hrc;
+ }
+
+protected:
+ bool fInit;
+ LONG m_cLock;
+ _ATL_TERMFUNC_ELEM *m_pTermFuncs;
+};
+
+__declspec(selectany) GUID CAtlModule::m_LibID = {0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} };
+
+struct _ATL_COM_MODULE
+{
+ HINSTANCE m_hInstTypeLib;
+ CComCriticalSection m_csObjMap;
+};
+
+#ifndef _delayimp_h
+extern "C" IMAGE_DOS_HEADER __ImageBase;
+#endif
+
+class CAtlComModule : public _ATL_COM_MODULE
+{
+public:
+ static bool m_fInitFailed;
+ CAtlComModule() throw()
+ {
+ m_hInstTypeLib = reinterpret_cast<HINSTANCE>(&__ImageBase);
+
+ if (FAILED(m_csObjMap.Init()))
+ {
+ AssertMsgFailed(("CAtlComModule: critsect init failed\n"));
+ m_fInitFailed = true;
+ return;
+ }
+ }
+
+ ~CAtlComModule()
+ {
+ Term();
+ }
+
+ void Term()
+ {
+ m_csObjMap.Term();
+ }
+};
+
+__declspec(selectany) bool CAtlComModule::m_fInitFailed = false;
+__declspec(selectany) CAtlComModule _AtlComModule;
+
+template <class T> class ATL_NO_VTABLE CAtlModuleT : public CAtlModule
+{
+public:
+ CAtlModuleT() throw()
+ {
+ T::InitLibId();
+ }
+
+ static void InitLibId() throw()
+ {
+ }
+};
+
+/**
+ *
+ * This class not _not_ be statically instantiated as a global variable! It may
+ * use VBoxRT before it's initialized otherwise, messing up logging and whatnot.
+ *
+ * When possible create the instance inside the TrustedMain() or main() as a
+ * stack variable. In DLLs use 'new' to instantiate it in the DllMain function.
+ */
+class CComModule : public CAtlModuleT<CComModule>
+{
+public:
+ CComModule()
+ {
+ // One instance only per linking namespace!
+ AssertMsg(!_pModule, ("CComModule: trying to create more than one instance per linking namespace\n"));
+ _pModule = this;
+ m_pObjMap = NULL;
+ }
+
+ ~CComModule()
+ {
+ }
+
+ _ATL_OBJMAP_ENTRY *m_pObjMap;
+ HRESULT Init(_ATL_OBJMAP_ENTRY *p, HINSTANCE h, const GUID *pLibID = NULL) throw()
+ {
+ RT_NOREF1(h);
+
+ if (pLibID)
+ m_LibID = *pLibID;
+
+ // Go over the object map to do some sanity checking, making things
+ // crash early if something is seriously busted.
+ _ATL_OBJMAP_ENTRY *pEntry;
+ if (p != (_ATL_OBJMAP_ENTRY *)-1)
+ {
+ m_pObjMap = p;
+ if (m_pObjMap)
+ {
+ pEntry = m_pObjMap;
+ while (pEntry->pclsid)
+ pEntry++;
+ }
+ }
+ return S_OK;
+ }
+
+ void Term() throw()
+ {
+ _ATL_OBJMAP_ENTRY *pEntry;
+ if (m_pObjMap)
+ {
+ pEntry = m_pObjMap;
+ while (pEntry->pclsid)
+ {
+ if (pEntry->pCF)
+ pEntry->pCF->Release();
+ pEntry->pCF = NULL;
+ pEntry++;
+ }
+ }
+
+ CAtlModuleT<CComModule>::Term();
+ }
+
+ HRESULT GetClassObject(REFCLSID rclsid, REFIID riid, void **ppv) throw()
+ {
+ *ppv = NULL;
+ HRESULT hrc = S_OK;
+
+ if (m_pObjMap)
+ {
+ const _ATL_OBJMAP_ENTRY *pEntry = m_pObjMap;
+
+ while (pEntry->pclsid)
+ {
+ if (pEntry->pfnGetClassObject && rclsid == *pEntry->pclsid)
+ {
+ if (!pEntry->pCF)
+ {
+ CComCritSectLockManual<CComCriticalSection> lock(_AtlComModule.m_csObjMap);
+ hrc = lock.Lock();
+ if (FAILED(hrc))
+ {
+ AssertMsgFailed(("CComModule::GetClassObject: failed to lock critsect\n"));
+ break;
+ }
+
+ if (!pEntry->pCF)
+ {
+ hrc = pEntry->pfnGetClassObject(pEntry->pfnCreateInstance, __uuidof(IUnknown), (void **)&pEntry->pCF);
+ }
+ }
+
+ if (pEntry->pCF)
+ {
+ hrc = pEntry->pCF->QueryInterface(riid, ppv);
+ }
+ break;
+ }
+ pEntry++;
+ }
+ }
+
+ return hrc;
+ }
+
+ // For EXE only: register all class factories with COM.
+ HRESULT RegisterClassObjects(DWORD dwClsContext, DWORD dwFlags) throw()
+ {
+ HRESULT hrc = S_OK;
+ _ATL_OBJMAP_ENTRY *pEntry;
+ if (m_pObjMap)
+ {
+ pEntry = m_pObjMap;
+ while (pEntry->pclsid && SUCCEEDED(hrc))
+ {
+ if (pEntry->pfnGetClassObject)
+ {
+ IUnknown *p;
+ hrc = pEntry->pfnGetClassObject(pEntry->pfnCreateInstance, __uuidof(IUnknown), (void **)&p);
+ if (SUCCEEDED(hrc))
+ hrc = CoRegisterClassObject(*(pEntry->pclsid), p, dwClsContext, dwFlags, &pEntry->dwRegister);
+ if (p)
+ p->Release();
+ }
+ pEntry++;
+ }
+ }
+ return hrc;
+ }
+ // For EXE only: revoke all class factories with COM.
+ HRESULT RevokeClassObjects() throw()
+ {
+ HRESULT hrc = S_OK;
+ _ATL_OBJMAP_ENTRY *pEntry;
+ if (m_pObjMap != NULL)
+ {
+ pEntry = m_pObjMap;
+ while (pEntry->pclsid && SUCCEEDED(hrc))
+ {
+ if (pEntry->dwRegister)
+ hrc = CoRevokeClassObject(pEntry->dwRegister);
+ pEntry++;
+ }
+ }
+ return hrc;
+ }
+};
+
+
+template <class T> class CComCreator
+{
+public:
+ static HRESULT WINAPI CreateInstance(void *pv, REFIID riid, void **ppv)
+ {
+ AssertReturn(ppv, E_POINTER);
+ *ppv = NULL;
+ HRESULT hrc = E_OUTOFMEMORY;
+ T *p = new(std::nothrow) T(pv);
+ if (p)
+ {
+ p->SetVoid(pv);
+ p->InternalFinalConstructAddRef();
+ hrc = p->_AtlInitialConstruct();
+ if (SUCCEEDED(hrc))
+ hrc = p->FinalConstruct();
+ p->InternalFinalConstructRelease();
+ if (SUCCEEDED(hrc))
+ hrc = p->QueryInterface(riid, ppv);
+ if (FAILED(hrc))
+ delete p;
+ }
+ return hrc;
+ }
+};
+
+template <HRESULT hrc> class CComFailCreator
+{
+public:
+ static HRESULT WINAPI CreateInstance(void *, REFIID, void **ppv)
+ {
+ AssertReturn(ppv, E_POINTER);
+ *ppv = NULL;
+
+ return hrc;
+ }
+};
+
+template <class T1, class T2> class CComCreator2
+{
+public:
+ static HRESULT WINAPI CreateInstance(void *pv, REFIID riid, void **ppv)
+ {
+ AssertReturn(ppv, E_POINTER);
+
+ return !pv ? T1::CreateInstance(NULL, riid, ppv) : T2::CreateInstance(pv, riid, ppv);
+ }
+};
+
+template <class Base> class CComObjectCached : public Base
+{
+public:
+ CComObjectCached(void * = NULL)
+ {
+ }
+ virtual ~CComObjectCached()
+ {
+ // Catch refcount screwups by setting refcount to -(LONG_MAX/2).
+ m_iRef = -(LONG_MAX/2);
+ FinalRelease();
+ }
+ STDMETHOD_(ULONG, AddRef)() throw()
+ {
+ // If you get errors about undefined InternalAddRef then Base does not
+ // derive from CComObjectRootEx.
+ ULONG l = InternalAddRef();
+ if (l == 2)
+ {
+ AssertMsg(_pAtlModule, ("ATL: referring to ATL module without having one declared in this linking namespace\n"));
+ _pAtlModule->Lock();
+ }
+ return l;
+ }
+ STDMETHOD_(ULONG, Release)() throw()
+ {
+ // If you get errors about undefined InternalRelease then Base does not
+ // derive from CComObjectRootEx.
+ ULONG l = InternalRelease();
+ if (l == 0)
+ delete this;
+ else if (l == 1)
+ {
+ AssertMsg(_pAtlModule, ("ATL: referring to ATL module without having one declared in this linking namespace\n"));
+ _pAtlModule->Unlock();
+ }
+ return l;
+ }
+ STDMETHOD(QueryInterface)(REFIID iid, void **ppvObj) throw()
+ {
+ // If you get errors about undefined _InternalQueryInterface then
+ // double check BEGIN_COM_MAP in the class definition.
+ return _InternalQueryInterface(iid, ppvObj);
+ }
+ static HRESULT WINAPI CreateInstance(CComObjectCached<Base> **pp) throw()
+ {
+ AssertReturn(pp, E_POINTER);
+ *pp = NULL;
+
+ HRESULT hrc = E_OUTOFMEMORY;
+ CComObjectCached<Base> *p = new(std::nothrow) CComObjectCached<Base>();
+ if (p)
+ {
+ p->SetVoid(NULL);
+ p->InternalFinalConstructAddRef();
+ hrc = p->_AtlInitialConstruct();
+ if (SUCCEEDED(hrc))
+ hrc = p->FinalConstruct();
+ p->InternalFinalConstructRelease();
+ if (FAILED(hrc))
+ delete p;
+ else
+ *pp = p;
+ }
+ return hrc;
+ }
+};
+
+template <class Base> class CComObjectNoLock : public Base
+{
+public:
+ CComObjectNoLock(void * = NULL)
+ {
+ }
+ virtual ~CComObjectNoLock()
+ {
+ // Catch refcount screwups by setting refcount to -(LONG_MAX/2).
+ m_iRef = -(LONG_MAX/2);
+ FinalRelease();
+ }
+ STDMETHOD_(ULONG, AddRef)() throw()
+ {
+ // If you get errors about undefined InternalAddRef then Base does not
+ // derive from CComObjectRootEx.
+ return InternalAddRef();
+ }
+ STDMETHOD_(ULONG, Release)() throw()
+ {
+ // If you get errors about undefined InternalRelease then Base does not
+ // derive from CComObjectRootEx.
+ ULONG l = InternalRelease();
+ if (l == 0)
+ delete this;
+ return l;
+ }
+ STDMETHOD(QueryInterface)(REFIID iid, void **ppvObj) throw()
+ {
+ // If you get errors about undefined _InternalQueryInterface then
+ // double check BEGIN_COM_MAP in the class definition.
+ return _InternalQueryInterface(iid, ppvObj);
+ }
+};
+
+class CComTypeInfoHolder
+{
+ /** @todo implement type info caching, making stuff more efficient - would we benefit? */
+public:
+ const GUID *m_pGUID;
+ const GUID *m_pLibID;
+ WORD m_iMajor;
+ WORD m_iMinor;
+ ITypeInfo *m_pTInfo;
+
+ HRESULT GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
+ {
+ if (iTInfo != 0)
+ return DISP_E_BADINDEX;
+ return GetTI(lcid, ppTInfo);
+ }
+ HRESULT GetIDsOfNames(REFIID riid, LPOLESTR *pwszNames, UINT cNames, LCID lcid, DISPID *pDispID)
+ {
+ RT_NOREF1(riid); /* should be IID_NULL */
+ HRESULT hrc = FetchTI(lcid);
+ if (m_pTInfo)
+ hrc = m_pTInfo->GetIDsOfNames(pwszNames, cNames, pDispID);
+ return hrc;
+ }
+ HRESULT Invoke(IDispatch *p, DISPID DispID, REFIID riid, LCID lcid, WORD iFlags, DISPPARAMS *pDispParams,
+ VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
+ {
+ RT_NOREF1(riid); /* should be IID_NULL */
+ HRESULT hrc = FetchTI(lcid);
+ if (m_pTInfo)
+ hrc = m_pTInfo->Invoke(p, DispID, iFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
+ return hrc;
+ }
+private:
+ static void __stdcall Cleanup(void *pv)
+ {
+ AssertReturnVoid(pv);
+ CComTypeInfoHolder *p = (CComTypeInfoHolder *)pv;
+ if (p->m_pTInfo != NULL)
+ p->m_pTInfo->Release();
+ p->m_pTInfo = NULL;
+ }
+
+ HRESULT GetTI(LCID lcid)
+ {
+ AssertMsg(_pAtlModule, ("ATL: referring to ATL module without having one declared in this linking namespace\n"));
+ Assert(m_pLibID && m_pGUID);
+ if (m_pTInfo)
+ return S_OK;
+
+ CComCritSectLockManual<CComCriticalSection> lock(_pAtlModule->m_csStaticDataInitAndTypeInfo);
+ HRESULT hrc = lock.Lock();
+ if (SUCCEEDED(hrc))
+ {
+ ITypeLib *pTypeLib = NULL;
+ Assert(*m_pLibID != GUID_NULL);
+ hrc = LoadRegTypeLib(*m_pLibID, m_iMajor, m_iMinor, lcid, &pTypeLib);
+ if (SUCCEEDED(hrc))
+ {
+ ITypeInfo *pTypeInfo;
+ hrc = pTypeLib->GetTypeInfoOfGuid(*m_pGUID, &pTypeInfo);
+ if (SUCCEEDED(hrc))
+ {
+ ITypeInfo2 *pTypeInfo2;
+ if (SUCCEEDED(pTypeInfo->QueryInterface(__uuidof(ITypeInfo2), (void **)&pTypeInfo2)))
+ {
+ pTypeInfo->Release();
+ pTypeInfo = pTypeInfo2;
+ }
+ m_pTInfo = pTypeInfo;
+ _pAtlModule->AddTermFunc(Cleanup, (void *)this);
+ }
+ pTypeLib->Release();
+ }
+ }
+ return hrc;
+ }
+ HRESULT GetTI(LCID lcid, ITypeInfo **ppTInfo)
+ {
+ AssertReturn(ppTInfo, E_POINTER);
+ HRESULT hrc = S_OK;
+ if (!m_pTInfo)
+ hrc = GetTI(lcid);
+ if (m_pTInfo)
+ {
+ m_pTInfo->AddRef();
+ hrc = S_OK;
+ }
+ *ppTInfo = m_pTInfo;
+ return hrc;
+ }
+ HRESULT FetchTI(LCID lcid)
+ {
+ if (!m_pTInfo)
+ return GetTI(lcid);
+ return S_OK;
+ }
+};
+
+template <class ThreadModel> class CComObjectRootEx
+{
+public:
+ typedef ThreadModel _ThreadModel;
+ CComObjectRootEx()
+ {
+ m_iRef = 0L;
+ }
+ ~CComObjectRootEx()
+ {
+ }
+ ULONG InternalAddRef()
+ {
+ Assert(m_iRef != -1L);
+ return ThreadModel::Increment(&m_iRef);
+ }
+ ULONG InternalRelease()
+ {
+#ifdef VBOX_STRICT
+ LONG c = ThreadModel::Decrement(&m_iRef);
+ AssertMsg(c >= -(LONG_MAX / 2), /* See ~CComObjectNoLock, ~CComObject & ~CComAggObject. */
+ ("Release called on object which has been already destroyed!\n"));
+ return c;
+#else
+ return ThreadModel::Decrement(&m_iRef);
+#endif
+ }
+ ULONG OuterAddRef()
+ {
+ return m_pOuterUnknown->AddRef();
+ }
+ ULONG OuterRelease()
+ {
+ return m_pOuterUnknown->Release();
+ }
+ HRESULT OuterQueryInterface(REFIID iid, void **ppvObject)
+ {
+ return m_pOuterUnknown->QueryInterface(iid, ppvObject);
+ }
+ HRESULT _AtlInitialConstruct()
+ {
+ return m_CritSect.Init();
+ }
+ void Lock()
+ {
+ m_CritSect.Lock();
+ }
+ void Unlock()
+ {
+ m_CritSect.Unlock();
+ }
+ void SetVoid(void *)
+ {
+ }
+ void InternalFinalConstructAddRef()
+ {
+ }
+ void InternalFinalConstructRelease()
+ {
+ Assert(m_iRef == 0);
+ }
+ HRESULT FinalConstruct()
+ {
+ return S_OK;
+ }
+ void FinalRelease()
+ {
+ }
+ static HRESULT WINAPI InternalQueryInterface(void *pThis, const _ATL_INTMAP_ENTRY *pEntries, REFIID iid, void **ppvObj)
+ {
+ AssertReturn(pThis, E_INVALIDARG);
+ AssertReturn(pEntries, E_INVALIDARG);
+ AssertReturn(ppvObj, E_POINTER);
+ *ppvObj = NULL;
+ if (iid == IID_IUnknown)
+ {
+ // For IUnknown use first interface, must be simple map entry.
+ Assert(pEntries->pFunc == COM_SIMPLEMAPENTRY);
+ IUnknown *pObj = (IUnknown *)((INT_PTR)pThis + pEntries->dw);
+ pObj->AddRef();
+ *ppvObj = pObj;
+ return S_OK;
+ }
+ while (pEntries->pFunc)
+ {
+ if (iid == *pEntries->piid)
+ {
+ if (pEntries->pFunc == COM_SIMPLEMAPENTRY)
+ {
+ IUnknown *pObj = (IUnknown *)((INT_PTR)pThis + pEntries->dw);
+ pObj->AddRef();
+ *ppvObj = pObj;
+ return S_OK;
+ }
+ else
+ return pEntries->pFunc(pThis, iid, ppvObj, pEntries->dw);
+ }
+ pEntries++;
+ }
+ return E_NOINTERFACE;
+ }
+ static HRESULT WINAPI _Delegate(void *pThis, REFIID iid, void **ppvObj, DWORD_PTR dw)
+ {
+ AssertPtrReturn(pThis, E_NOINTERFACE);
+ IUnknown *pObj = *(IUnknown **)((DWORD_PTR)pThis + dw);
+ // If this assertion fails then the object has a delegation with a NULL
+ // object pointer, which is highly unusual often means that the pointer
+ // was not set up correctly. Check the COM interface map of the class
+ // for bugs with initializing.
+ AssertPtrReturn(pObj, E_NOINTERFACE);
+ return pObj->QueryInterface(iid, ppvObj);
+ }
+
+ union
+ {
+ LONG m_iRef;
+ IUnknown *m_pOuterUnknown;
+ };
+private:
+ typename ThreadModel::AutoDeleteCriticalSection m_CritSect;
+};
+
+template <class Base> class CComObject : public Base
+{
+public:
+ CComObject(void * = NULL) throw()
+ {
+ AssertMsg(_pAtlModule, ("ATL: referring to ATL module without having one declared in this linking namespace\n"));
+ _pAtlModule->Lock();
+ }
+ virtual ~CComObject() throw()
+ {
+ AssertMsg(_pAtlModule, ("ATL: referring to ATL module without having one declared in this linking namespace\n"));
+ // Catch refcount screwups by setting refcount to -(LONG_MAX/2).
+ m_iRef = -(LONG_MAX/2);
+ FinalRelease();
+ _pAtlModule->Unlock();
+ }
+ STDMETHOD_(ULONG, AddRef)()
+ {
+ // If you get errors about undefined InternalAddRef then Base does not
+ // derive from CComObjectRootEx.
+ return InternalAddRef();
+ }
+ STDMETHOD_(ULONG, Release)()
+ {
+ // If you get errors about undefined InternalRelease then Base does not
+ // derive from CComObjectRootEx.
+ ULONG l = InternalRelease();
+ if (l == 0)
+ delete this;
+ return l;
+ }
+ STDMETHOD(QueryInterface)(REFIID iid, void **ppvObj) throw()
+ {
+ // If you get errors about undefined _InternalQueryInterface then
+ // double check BEGIN_COM_MAP in the class definition.
+ return _InternalQueryInterface(iid, ppvObj);
+ }
+
+ static HRESULT WINAPI CreateInstance(CComObject<Base> **pp) throw()
+ {
+ AssertReturn(pp, E_POINTER);
+ *pp = NULL;
+
+ HRESULT hrc = E_OUTOFMEMORY;
+ CComObject<Base> *p = NULL;
+ try
+ {
+ p = new CComObject<Base>();
+ }
+ catch (std::bad_alloc &)
+ {
+ p = NULL;
+ }
+ if (p)
+ {
+ p->InternalFinalConstructAddRef();
+ try
+ {
+ hrc = p->_AtlInitialConstruct();
+ if (SUCCEEDED(hrc))
+ hrc = p->FinalConstruct();
+ }
+ catch (std::bad_alloc &)
+ {
+ hrc = E_OUTOFMEMORY;
+ }
+ p->InternalFinalConstructRelease();
+ if (FAILED(hrc))
+ {
+ delete p;
+ p = NULL;
+ }
+ }
+ *pp = p;
+ return hrc;
+ }
+};
+
+template <class T, const IID *piid, const GUID *pLibID, WORD iMajor = 1, WORD iMinor = 0> class ATL_NO_VTABLE IDispatchImpl : public T
+{
+public:
+ // IDispatch
+ STDMETHOD(GetTypeInfoCount)(UINT *pcTInfo)
+ {
+ if (!pcTInfo)
+ return E_POINTER;
+ *pcTInfo = 1;
+ return S_OK;
+ }
+ STDMETHOD(GetTypeInfo)(UINT cTInfo, LCID lcid, ITypeInfo **ppTInfo)
+ {
+ return tih.GetTypeInfo(cTInfo, lcid, ppTInfo);
+ }
+ STDMETHOD(GetIDsOfNames)(REFIID riid, LPOLESTR *pwszNames, UINT cNames, LCID lcid, DISPID *pDispID)
+ {
+ return tih.GetIDsOfNames(riid, pwszNames, cNames, lcid, pDispID);
+ }
+ STDMETHOD(Invoke)(DISPID DispID, REFIID riid, LCID lcid, WORD iFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
+ {
+ return tih.Invoke((IDispatch *)this, DispID, riid, lcid, iFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
+ }
+protected:
+ static CComTypeInfoHolder tih;
+ static HRESULT GetTI(LCID lcid, ITypeInfo **ppTInfo)
+ {
+ return tih.GetTI(lcid, ppTInfo);
+ }
+};
+
+template <class T, const IID *piid, const GUID *pLibID, WORD iMajor, WORD iMinor> CComTypeInfoHolder IDispatchImpl<T, piid, pLibID, iMajor, iMinor>::tih = { piid, pLibID, iMajor, iMinor, NULL };
+
+
+template <class Base> class CComContainedObject : public Base
+{
+public:
+ CComContainedObject(void *pv)
+ {
+ m_pOuterUnknown = (IUnknown *)pv;
+ }
+
+ STDMETHOD_(ULONG, AddRef)() throw()
+ {
+ return OuterAddRef();
+ }
+ STDMETHOD_(ULONG, Release)() throw()
+ {
+ return OuterRelease();
+ }
+ STDMETHOD(QueryInterface)(REFIID iid, void **ppvObj) throw()
+ {
+ return OuterQueryInterface(iid, ppvObj);
+ }
+};
+
+template <class Aggregated> class CComAggObject :
+ public IUnknown,
+ public CComObjectRootEx<typename Aggregated::_ThreadModel::ThreadModelNoCS>
+{
+public:
+ CComAggObject(void *pv) :
+ m_Aggregated(pv)
+ {
+ AssertMsg(_pAtlModule, ("ATL: referring to ATL module without having one declared in this linking namespace\n"));
+ _pAtlModule->Lock();
+ }
+ virtual ~CComAggObject()
+ {
+ AssertMsg(_pAtlModule, ("ATL: referring to ATL module without having one declared in this linking namespace\n"));
+ // Catch refcount screwups by setting refcount to -(LONG_MAX/2).
+ m_iRef = -(LONG_MAX/2);
+ FinalRelease();
+ _pAtlModule->Unlock();
+ }
+ HRESULT _AtlInitialConstruct()
+ {
+ HRESULT hrc = m_Aggregated._AtlInitialConstruct();
+ if (SUCCEEDED(hrc))
+ {
+ hrc = CComObjectRootEx<typename Aggregated::_ThreadModel::ThreadModelNoCS>::_AtlInitialConstruct();
+ }
+ return hrc;
+ }
+ HRESULT FinalConstruct()
+ {
+ CComObjectRootEx<Aggregated::_ThreadModel::ThreadModelNoCS>::FinalConstruct();
+ return m_Aggregated.FinalConstruct();
+ }
+ void FinalRelease()
+ {
+ CComObjectRootEx<Aggregated::_ThreadModel::ThreadModelNoCS>::FinalRelease();
+ m_Aggregated.FinalRelease();
+ }
+
+ STDMETHOD_(ULONG, AddRef)()
+ {
+ return InternalAddRef();
+ }
+ STDMETHOD_(ULONG, Release)()
+ {
+ ULONG l = InternalRelease();
+ if (l == 0)
+ delete this;
+ return l;
+ }
+ STDMETHOD(QueryInterface)(REFIID iid, void **ppvObj)
+ {
+ AssertReturn(ppvObj, E_POINTER);
+ *ppvObj = NULL;
+
+ HRESULT hrc = S_OK;
+ if (iid == __uuidof(IUnknown))
+ {
+ *ppvObj = (void *)(IUnknown *)this;
+ AddRef();
+ }
+ else
+ hrc = m_Aggregated._InternalQueryInterface(iid, ppvObj);
+ return hrc;
+ }
+ static HRESULT WINAPI CreateInstance(LPUNKNOWN pUnkOuter, CComAggObject<Aggregated> **pp)
+ {
+ AssertReturn(pp, E_POINTER);
+ *pp = NULL;
+
+ HRESULT hrc = E_OUTOFMEMORY;
+ CComAggObject<Aggregated> *p = new(std::nothrow) CComAggObject<Aggregated>(pUnkOuter);
+ if (p)
+ {
+ p->SetVoid(NULL);
+ p->InternalFinalConstructAddRef();
+ hrc = p->_AtlInitialConstruct();
+ if (SUCCEEDED(hrc))
+ hrc = p->FinalConstruct();
+ p->InternalFinalConstructRelease();
+ if (FAILED(hrc))
+ delete p;
+ else
+ *pp = p;
+ }
+ return hrc;
+ }
+
+ CComContainedObject<Aggregated> m_Aggregated;
+};
+
+class CComClassFactory:
+ public IClassFactory,
+ public CComObjectRootEx<CComMultiThreadModel>
+{
+public:
+ BEGIN_COM_MAP(CComClassFactory)
+ COM_INTERFACE_ENTRY(IClassFactory)
+ END_COM_MAP()
+
+ virtual ~CComClassFactory()
+ {
+ }
+
+ // IClassFactory
+ STDMETHOD(CreateInstance)(LPUNKNOWN pUnkOuter, REFIID riid, void **ppvObj)
+ {
+ Assert(m_pfnCreateInstance);
+ HRESULT hrc = E_POINTER;
+ if (ppvObj)
+ {
+ *ppvObj = NULL;
+ if (pUnkOuter && riid != __uuidof(IUnknown))
+ {
+ AssertMsgFailed(("CComClassFactory: cannot create an aggregated object other than IUnknown\n"));
+ hrc = CLASS_E_NOAGGREGATION;
+ }
+ else
+ hrc = m_pfnCreateInstance(pUnkOuter, riid, ppvObj);
+ }
+ return hrc;
+ }
+
+ STDMETHOD(LockServer)(BOOL fLock)
+ {
+ AssertMsg(_pAtlModule, ("ATL: referring to ATL module without having one declared in this linking namespace\n"));
+ if (fLock)
+ _pAtlModule->Lock();
+ else
+ _pAtlModule->Unlock();
+ return S_OK;
+ }
+
+ // Set creator for use by the factory.
+ void SetVoid(void *pv)
+ {
+ m_pfnCreateInstance = (PFNCREATEINSTANCE)pv;
+ }
+
+ PFNCREATEINSTANCE m_pfnCreateInstance;
+};
+
+template <class T> class CComClassFactorySingleton : public CComClassFactory
+{
+public:
+ CComClassFactorySingleton() :
+ m_hrc(S_OK),
+ m_pObj(NULL)
+ {
+ }
+ virtual ~CComClassFactorySingleton()
+ {
+ if (m_pObj)
+ m_pObj->Release();
+ }
+ // IClassFactory
+ STDMETHOD(CreateInstance)(LPUNKNOWN pUnkOuter, REFIID riid, void **pvObj)
+ {
+ HRESULT hrc = E_POINTER;
+ if (ppvObj)
+ {
+ *ppvObj = NULL;
+ // Singleton factories do not support aggregation.
+ AssertReturn(!pUnkOuter, CLASS_E_NOAGGREGATION);
+
+ // Test if singleton is already created. Do it outside the lock,
+ // relying on atomic checks. Remember the inherent race!
+ if (SUCCEEDED(m_hrc) && !m_pObj)
+ {
+ Lock();
+ // Make sure that the module is in use, otherwise the
+ // module can terminate while we're creating a new
+ // instance, which leads to strange errors.
+ LockServer(true);
+ __try
+ {
+ // Repeat above test to avoid races when multiple threads
+ // want to create a singleton simultaneously.
+ if (SUCCEEDED(m_hrc) && !m_pObj)
+ {
+ CComObjectCached<T> *p;
+ m_hrc = CComObjectCached<T>::CreateInstance(&p);
+ if (SUCCEEDED(m_hrc))
+ {
+ m_hrc = p->QueryInterface(IID_IUnknown, (void **)&m_pObj);
+ if (FAILED(m_hrc))
+ {
+ delete p;
+ }
+ }
+ }
+ }
+ __finally
+ {
+ Unlock();
+ LockServer(false);
+ }
+ }
+ if (SUCCEEDED(m_hrc))
+ {
+ hrc = m_pObj->QueryInterface(riid, ppvObj);
+ }
+ else
+ {
+ hrc = m_hrc;
+ }
+ }
+ return hrc;
+ }
+ HRESULT m_hrc;
+ IUnknown *m_pObj;
+};
+
+
+template <class T, const CLSID *pClsID = &CLSID_NULL> class CComCoClass
+{
+public:
+ DECLARE_CLASSFACTORY()
+ DECLARE_AGGREGATABLE(T)
+ static const CLSID& WINAPI GetObjectCLSID()
+ {
+ return *pClsID;
+ }
+ template <class Q>
+ static HRESULT CreateInstance(Q **pp)
+ {
+ return T::_CreatorClass::CreateInstance(NULL, __uuidof(Q), (void **)pp);
+ }
+};
+
+} /* namespace ATL */
+
+#endif /* !VBOX_INCLUDED_com_microatl_h */
+
diff --git a/include/VBox/com/mtlist.h b/include/VBox/com/mtlist.h
new file mode 100644
index 00000000..0ff79bb1
--- /dev/null
+++ b/include/VBox/com/mtlist.h
@@ -0,0 +1,220 @@
+/* $Id: mtlist.h $ */
+/** @file
+ * MS COM / XPCOM Abstraction Layer - Thread-safe list classes declaration.
+ */
+
+/*
+ * Copyright (C) 2011-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_com_mtlist_h
+#define VBOX_INCLUDED_com_mtlist_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/com/ptr.h>
+#include <VBox/com/string.h>
+#include <VBox/com/array.h>
+#include <iprt/cpp/mtlist.h>
+
+
+/** @defgroup grp_com_mtlist Thread-safe List Classes
+ * @ingroup grp_com
+ * @{
+ */
+
+/**
+ * Specialized thread-safe list class for using with com::ComPtr<C>
+ *
+ * @note: This is necessary cause ComPtr<IFACE> has a size of 8.
+ */
+template <typename C>
+class RTCMTList< ComPtr<C> >: public RTCListBase< ComPtr<C>, ComPtr<C>*, true>
+{
+ /* Traits */
+ typedef ComPtr<C> T;
+ typedef T *ITYPE;
+ static const bool MT = true;
+ typedef RTCListBase<T, ITYPE, MT> BASE;
+
+public:
+ /**
+ * Creates a new list.
+ *
+ * This preallocates @a cCapacity elements within the list.
+ *
+ * @param cCapacity The initial capacity the list has.
+ * @throws std::bad_alloc
+ */
+ RTCMTList(size_t cCapacity = BASE::kDefaultCapacity)
+ : BASE(cCapacity) {}
+
+ /* Define our own new and delete. */
+ RTMEMEF_NEW_AND_DELETE_OPERATORS();
+};
+
+/**
+ * Specialized thread-safe list class for using with com::ComObjPtr<C>
+ *
+ * @note: This is necessary cause ComObjPtr<IFACE> has a size of 8.
+ */
+template <typename C>
+class RTCMTList< ComObjPtr<C> >: public RTCListBase< ComObjPtr<C>, ComObjPtr<C>*, true>
+{
+ /* Traits */
+ typedef ComObjPtr<C> T;
+ typedef T *ITYPE;
+ static const bool MT = true;
+ typedef RTCListBase<T, ITYPE, MT> BASE;
+
+public:
+ /**
+ * Creates a new list.
+ *
+ * This preallocates @a cCapacity elements within the list.
+ *
+ * @param cCapacity The initial capacity the list has.
+ * @throws std::bad_alloc
+ */
+ RTCMTList(size_t cCapacity = BASE::kDefaultCapacity)
+ : BASE(cCapacity) {}
+
+ /* Define our own new and delete. */
+ RTMEMEF_NEW_AND_DELETE_OPERATORS();
+};
+
+/**
+ * Specialized thread-safe list class for using with com::Utf8Str.
+ *
+ * The class offers methods for importing com::SafeArray's of com::Bstr's.
+ */
+template <>
+class RTCMTList<com::Utf8Str>: public RTCListBase<com::Utf8Str, com::Utf8Str *, true>
+{
+ /* Traits */
+ typedef com::Utf8Str T;
+ typedef T *ITYPE;
+ static const bool MT = true;
+ typedef RTCListBase<T, ITYPE, MT> BASE;
+
+public:
+ /**
+ * Creates a new list.
+ *
+ * This preallocates @a cCapacity elements within the list.
+ *
+ * @param cCapacity The initial capacity the list has.
+ * @throws std::bad_alloc
+ */
+ RTCMTList(size_t cCapacity = BASE::kDefaultCapacity)
+ : BASE(cCapacity) {}
+
+ /**
+ * Creates a copy of another list.
+ *
+ * The other list will be fully copied and the capacity will be the same as
+ * the size of the other list. The com::Bstr's are silently converted to
+ * com::Utf8Str's.
+ *
+ * @param other The list to copy.
+ * @throws std::bad_alloc
+ */
+ RTCMTList(ComSafeArrayIn(IN_BSTR, other))
+ {
+ com::SafeArray<IN_BSTR> sfaOther(ComSafeArrayInArg(other));
+ size_t const cElementsOther = sfaOther.size();
+ resizeArray(cElementsOther);
+ m_cElements = cElementsOther;
+ for (size_t i = 0; i < cElementsOther; ++i)
+ RTCListHelper<T, ITYPE>::set(m_pArray, i, T(sfaOther[i]));
+ }
+
+ /**
+ * Creates a copy of another list.
+ *
+ * The other list will be fully copied and the capacity will be the same as
+ * the size of the other list. The com::Bstr's are silently converted to
+ * com::Utf8Str's.
+ *
+ * @param other The list to copy.
+ * @throws std::bad_alloc
+ */
+ RTCMTList(const com::SafeArray<IN_BSTR> &other)
+ : BASE(other.size())
+ {
+ for (size_t i = 0; i < m_cElements; ++i)
+ RTCListHelper<T, ITYPE>::set(m_pArray, i, T(other[i]));
+ }
+
+ /**
+ * Copy the items of the other list into this list. All previous items of
+ * this list are deleted.
+ *
+ * @param other The list to copy.
+ * @return a reference to this list.
+ * @throws std::bad_alloc
+ */
+ RTCListBase<T, ITYPE, MT> &operator=(const com::SafeArray<IN_BSTR> &other)
+ {
+ m_guard.enterWrite();
+ /* Values cleanup */
+ RTCListHelper<T, ITYPE>::eraseRange(m_pArray, 0, m_cElements);
+ /* Copy */
+ if (other.size() != m_cCapacity)
+ resizeArrayNoErase(other.size());
+ m_cElements = other.size();
+ for (size_t i = 0; i < other.size(); ++i)
+ RTCListHelper<T, ITYPE>::set(m_pArray, i, T(other[i]));
+ m_guard.leaveWrite();
+
+ return *this;
+ }
+
+ /**
+ * Implicit conversion to a RTCString list.
+ *
+ * This allows the usage of the RTCString::join method with this list type.
+ *
+ * @return a converted const reference to this list.
+ */
+ operator const RTCMTList<RTCString, RTCString*>&()
+ {
+ return *reinterpret_cast<RTCMTList<RTCString, RTCString*> *>(this);
+ }
+
+ /* Define our own new and delete. */
+ RTMEMEF_NEW_AND_DELETE_OPERATORS();
+};
+
+/** @} */
+
+#endif /* !VBOX_INCLUDED_com_mtlist_h */
+
diff --git a/include/VBox/com/ptr.h b/include/VBox/com/ptr.h
new file mode 100644
index 00000000..613d2d08
--- /dev/null
+++ b/include/VBox/com/ptr.h
@@ -0,0 +1,569 @@
+/** @file
+ * MS COM / XPCOM Abstraction Layer - Smart COM pointer classes declaration.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_com_ptr_h
+#define VBOX_INCLUDED_com_ptr_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+/* Make sure all the stdint.h macros are included - must come first! */
+#ifndef __STDC_LIMIT_MACROS
+# define __STDC_LIMIT_MACROS
+#endif
+#ifndef __STDC_CONSTANT_MACROS
+# define __STDC_CONSTANT_MACROS
+#endif
+
+#ifdef VBOX_WITH_XPCOM
+# include <nsISupportsUtils.h>
+#endif /* VBOX_WITH_XPCOM */
+
+#include <VBox/com/defs.h>
+#include <new> /* For bad_alloc. */
+
+
+/** @defgroup grp_com_ptr Smart COM Pointer Classes
+ * @ingroup grp_com
+ * @{
+ */
+
+#ifdef VBOX_WITH_XPCOM
+
+namespace com
+{
+// declare a couple of XPCOM helper methods (defined in glue/com.cpp)
+// so we don't have to include a ton of XPCOM implementation headers here
+HRESULT GlueCreateObjectOnServer(const CLSID &clsid,
+ const char *serverName,
+ const nsIID &id,
+ void **ppobj);
+HRESULT GlueCreateInstance(const CLSID &clsid,
+ const nsIID &id,
+ void **ppobj);
+}
+
+#endif // VBOX_WITH_XPCOM
+
+/**
+ * COM autopointer class which takes care of all required reference counting.
+ *
+ * This automatically calls the required basic COM methods on COM pointers
+ * given to it:
+ *
+ * -- AddRef() gets called automatically whenever a new COM pointer is assigned
+ * to the ComPtr instance (either in the copy constructor or by assignment);
+ *
+ * -- Release() gets called automatically by the destructor and when an existing
+ * object gets released in assignment;
+ *
+ * -- QueryInterface() gets called automatically when COM pointers get converted
+ * from one interface to another.
+ *
+ * Example usage:
+ *
+ * @code
+ *
+ * {
+ * ComPtr<IMachine> pMachine = findMachine("blah"); // calls AddRef()
+ * ComPtr<IUnknown> pUnknown = pMachine; // calls QueryInterface()
+ * } # ComPtr destructor of both instances calls Release()
+ *
+ * @endcode
+ */
+template <class T>
+class ComPtr
+{
+public:
+
+ /**
+ * Default constructor, sets up a NULL pointer.
+ */
+ ComPtr()
+ : m_p(NULL)
+ { }
+
+ /**
+ * Destructor. Calls Release() on the contained COM object.
+ */
+ ~ComPtr()
+ {
+ cleanup();
+ }
+
+ /**
+ * Copy constructor from another ComPtr of any interface.
+ *
+ * This calls QueryInterface(T) and can result in a NULL pointer if the input
+ * pointer p does not support the ComPtr interface T.
+ *
+ * Does not call AddRef explicitly because if QueryInterface succeeded, then
+ * the refcount will have been increased by one already.
+ */
+ template <class T2>
+ ComPtr(const ComPtr<T2> &that)
+ {
+ m_p = NULL;
+ if (!that.isNull())
+ that->QueryInterface(COM_IIDOF(T), (void **)&m_p);
+ }
+
+ /**
+ * Specialization: copy constructor from another ComPtr<T>. Calls AddRef().
+ */
+ ComPtr(const ComPtr &that)
+ {
+ copyFrom(that.m_p);
+ }
+
+ /**
+ * Copy constructor from another interface pointer of any interface.
+ *
+ * This calls QueryInterface(T) and can result in a NULL pointer if the input
+ * pointer p does not support the ComPtr interface T.
+ *
+ * Does not call AddRef explicitly because if QueryInterface succeeded, then
+ * the refcount will have been increased by one already.
+ */
+ template <class T2>
+ ComPtr(T2 *p)
+ {
+ m_p = NULL;
+ if (p)
+ p->QueryInterface(COM_IIDOF(T), (void **)&m_p);
+ }
+
+ /**
+ * Specialization: copy constructor from a plain T * pointer. Calls AddRef().
+ */
+ ComPtr(T *that_p)
+ {
+ copyFrom(that_p);
+ }
+
+ /**
+ * Assignment from another ComPtr of any interface.
+ *
+ * This calls QueryInterface(T) and can result in a NULL pointer if the input
+ * pointer p does not support the ComPtr interface T.
+ *
+ * Does not call AddRef explicitly because if QueryInterface succeeded, then
+ * the refcount will have been increased by one already.
+ */
+ template <class T2>
+ ComPtr& operator=(const ComPtr<T2> &that)
+ {
+ return operator=((T2 *)that);
+ }
+
+ /**
+ * Specialization of the previous: assignment from another ComPtr<T>.
+ * Calls Release() on the previous member pointer, if any, and AddRef() on the new one.
+ */
+ ComPtr& operator=(const ComPtr &that)
+ {
+ return operator=((T *)that);
+ }
+
+ /**
+ * Assignment from another interface pointer of any interface.
+ *
+ * This calls QueryInterface(T) and can result in a NULL pointer if the input
+ * pointer p does not support the ComPtr interface T.
+ *
+ * Does not call AddRef explicitly because if QueryInterface succeeded, then
+ * the refcount will have been increased by one already.
+ */
+ template <class T2>
+ ComPtr& operator=(T2 *p)
+ {
+ cleanup();
+ if (p)
+ p->QueryInterface(COM_IIDOF(T), (void **)&m_p);
+ return *this;
+ }
+
+ /**
+ * Specialization of the previous: assignment from a plain T * pointer.
+ * Calls Release() on the previous member pointer, if any, and AddRef() on the new one.
+ */
+ ComPtr& operator=(T *p)
+ {
+ cleanup();
+ copyFrom(p);
+ return *this;
+ }
+
+ /**
+ * Resets the ComPtr to NULL. Works like a NULL assignment except it avoids the templates.
+ */
+ void setNull()
+ {
+ cleanup();
+ }
+
+ /**
+ * Returns true if the pointer is NULL.
+ */
+ bool isNull() const
+ {
+ return (m_p == NULL);
+ }
+
+ /**
+ * Returns true if the pointer is not NULL.
+ */
+ bool isNotNull() const
+ {
+ return (m_p != NULL);
+ }
+
+ bool operator<(T *p) const
+ {
+ return m_p < p;
+ }
+
+ /**
+ * Conversion operator, most often used to pass ComPtr instances as
+ * parameters to COM method calls.
+ */
+ operator T *() const
+ {
+ return m_p;
+ }
+
+ /**
+ * Dereferences the instance (redirects the -> operator to the managed
+ * pointer).
+ */
+ T *operator->() const
+ {
+ return m_p;
+ }
+
+ /**
+ * Special method which allows using a ComPtr as an output argument of a COM method.
+ * The ComPtr will then accept the method's interface pointer without calling AddRef()
+ * itself, since by COM convention this must has been done by the method which created
+ * the object that is being accepted.
+ *
+ * The ComPtr destructor will then still invoke Release() so that the returned object
+ * can get cleaned up properly.
+ */
+ T **asOutParam()
+ {
+ cleanup();
+ return &m_p;
+ }
+
+ /**
+ * Converts the contained pointer to a different interface
+ * by calling QueryInterface() on it.
+ * @param pp
+ * @return
+ */
+ template <class T2>
+ HRESULT queryInterfaceTo(T2 **pp) const
+ {
+ if (pp)
+ {
+ if (m_p)
+ return m_p->QueryInterface(COM_IIDOF(T2), (void **)pp);
+ *pp = NULL;
+ return S_OK;
+ }
+ return E_INVALIDARG;
+ }
+
+ /**
+ * Equality test operator. By COM definition, two COM objects are considered
+ * equal if their IUnknown interface pointers are equal.
+ */
+ template <class T2>
+ bool operator==(T2 *p)
+ {
+ IUnknown *p1 = NULL;
+ bool fNeedsRelease1 = false;
+ if (m_p)
+ fNeedsRelease1 = (SUCCEEDED(m_p->QueryInterface(COM_IIDOF(IUnknown), (void **)&p1)));
+
+ IUnknown *p2 = NULL;
+ bool fNeedsRelease2 = false;
+ if (p)
+ fNeedsRelease2 = (SUCCEEDED(p->QueryInterface(COM_IIDOF(IUnknown), (void **)&p2)));
+
+ bool f = p1 == p2;
+ if (fNeedsRelease1)
+ p1->Release();
+ if (fNeedsRelease2)
+ p2->Release();
+ return f;
+ }
+
+ /**
+ * Creates an in-process object of the given class ID and starts to
+ * manage a reference to the created object in case of success.
+ */
+ HRESULT createInprocObject(const CLSID &clsid)
+ {
+ HRESULT rc;
+ T *obj = NULL;
+#ifndef VBOX_WITH_XPCOM
+ rc = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, COM_IIDOF(T),
+ (void **)&obj);
+#else /* VBOX_WITH_XPCOM */
+ using namespace com;
+ rc = GlueCreateInstance(clsid, NS_GET_IID(T), (void **)&obj);
+#endif /* VBOX_WITH_XPCOM */
+ *this = obj;
+ if (SUCCEEDED(rc))
+ obj->Release();
+ return rc;
+ }
+
+ /**
+ * Creates a local (out-of-process) object of the given class ID and starts
+ * to manage a reference to the created object in case of success.
+ *
+ * Note: In XPCOM, the out-of-process functionality is currently emulated
+ * through in-process wrapper objects (that start a dedicated process and
+ * redirect all object requests to that process). For this reason, this
+ * method is fully equivalent to #createInprocObject() for now.
+ */
+ HRESULT createLocalObject(const CLSID &clsid)
+ {
+#ifndef VBOX_WITH_XPCOM
+ HRESULT rc;
+ T *obj = NULL;
+ rc = CoCreateInstance(clsid, NULL, CLSCTX_LOCAL_SERVER, COM_IIDOF(T),
+ (void **)&obj);
+ *this = obj;
+ if (SUCCEEDED(rc))
+ obj->Release();
+ return rc;
+#else /* VBOX_WITH_XPCOM */
+ return createInprocObject(clsid);
+#endif /* VBOX_WITH_XPCOM */
+ }
+
+#ifdef VBOX_WITH_XPCOM
+ /**
+ * Creates an object of the given class ID on the specified server and
+ * starts to manage a reference to the created object in case of success.
+ *
+ * @param serverName Name of the server to create an object within.
+ */
+ HRESULT createObjectOnServer(const CLSID &clsid, const char *serverName)
+ {
+ T *obj = NULL;
+ HRESULT rc = GlueCreateObjectOnServer(clsid, serverName, NS_GET_IID(T), (void **)&obj);
+ *this = obj;
+ if (SUCCEEDED(rc))
+ obj->Release();
+ return rc;
+ }
+#endif
+
+protected:
+ void copyFrom(T *p)
+ {
+ m_p = p;
+ if (m_p)
+ m_p->AddRef();
+ }
+
+ void cleanup()
+ {
+ if (m_p)
+ {
+ m_p->Release();
+ m_p = NULL;
+ }
+ }
+
+public:
+ // Do NOT access this member unless you really know what you're doing!
+ T *m_p;
+};
+
+/**
+ * ComObjPtr is a more specialized variant of ComPtr designed to be used for implementation
+ * objects. For example, use ComPtr<IMachine> for a client pointer that calls the interface
+ * but ComObjPtr<Machine> for a pointer to an implementation object.
+ *
+ * The methods behave the same except that ComObjPtr has the additional createObject()
+ * method which allows for instantiating a new implementation object.
+ *
+ * Note: To convert a ComObjPtr<InterfaceImpl> to a ComObj<IInterface> you have
+ * to query the interface. See the following example code for the IProgress
+ * interface:
+ *
+ * @code
+ *
+ * {
+ * ComObjPtr<Progress> pProgress; // create the server side object
+ * pProgress.createObject(); // ...
+ * pProgress->init(...); // ...
+ * ComPtr<IProgress> pProgress2; // create an interface pointer
+ * pProgress.queryInterfaceTo(pProgress2.asOutParam()); // transfer the interface
+ * }
+ *
+ * @endcode
+ */
+template <class T>
+class ComObjPtr : public ComPtr<T>
+{
+public:
+
+ ComObjPtr()
+ : ComPtr<T>()
+ {}
+
+ ComObjPtr(const ComObjPtr &that)
+ : ComPtr<T>(that)
+ {}
+
+ ComObjPtr(T *that_p)
+ : ComPtr<T>(that_p)
+ {}
+
+ ComObjPtr& operator=(const ComObjPtr &that)
+ {
+ ComPtr<T>::operator=(that);
+ return *this;
+ }
+
+ ComObjPtr& operator=(T *that_p)
+ {
+ ComPtr<T>::operator=(that_p);
+ return *this;
+ }
+
+ /**
+ * Creates a new server-side object of the given component class and
+ * immediately starts to manage a pointer to the created object (the
+ * previous pointer, if any, is of course released when appropriate).
+ *
+ * @note Win32: when VBOX_COM_OUTOFPROC_MODULE is defined, the created
+ * object doesn't increase the lock count of the server module, as it
+ * does otherwise.
+ *
+ * @note In order to make it easier to use, this method does _not_ throw
+ * bad_alloc, but instead returns E_OUTOFMEMORY.
+ */
+ HRESULT createObject()
+ {
+ HRESULT hrc;
+#ifndef VBOX_WITH_XPCOM
+# ifdef VBOX_COM_OUTOFPROC_MODULE
+ ATL::CComObjectNoLock<T> *obj = NULL;
+ try
+ {
+ obj = new ATL::CComObjectNoLock<T>();
+ }
+ catch (std::bad_alloc &)
+ {
+ obj = NULL;
+ }
+ if (obj)
+ {
+ obj->InternalFinalConstructAddRef();
+ try
+ {
+ hrc = obj->FinalConstruct();
+ }
+ catch (std::bad_alloc &)
+ {
+ hrc = E_OUTOFMEMORY;
+ }
+ obj->InternalFinalConstructRelease();
+ if (FAILED(hrc))
+ {
+ delete obj;
+ obj = NULL;
+ }
+ }
+ else
+ hrc = E_OUTOFMEMORY;
+# else
+ ATL::CComObject<T> *obj = NULL;
+ hrc = ATL::CComObject<T>::CreateInstance(&obj);
+# endif
+#else /* VBOX_WITH_XPCOM */
+ ATL::CComObject<T> *obj;
+# ifndef RT_EXCEPTIONS_ENABLED
+ obj = new ATL::CComObject<T>();
+# else
+ try
+ {
+ obj = new ATL::CComObject<T>();
+ }
+ catch (std::bad_alloc &)
+ {
+ obj = NULL;
+ }
+# endif
+ if (obj)
+ {
+# ifndef RT_EXCEPTIONS_ENABLED
+ hrc = obj->FinalConstruct();
+# else
+ try
+ {
+ hrc = obj->FinalConstruct();
+ }
+ catch (std::bad_alloc &)
+ {
+ hrc = E_OUTOFMEMORY;
+ }
+# endif
+ if (FAILED(hrc))
+ {
+ delete obj;
+ obj = NULL;
+ }
+ }
+ else
+ hrc = E_OUTOFMEMORY;
+#endif /* VBOX_WITH_XPCOM */
+ *this = obj;
+ return hrc;
+ }
+};
+
+/** @} */
+
+#endif /* !VBOX_INCLUDED_com_ptr_h */
+
diff --git a/include/VBox/com/string.h b/include/VBox/com/string.h
new file mode 100644
index 00000000..62d5abc1
--- /dev/null
+++ b/include/VBox/com/string.h
@@ -0,0 +1,1494 @@
+/* $Id: string.h $ */
+/** @file
+ * MS COM / XPCOM Abstraction Layer - Smart string classes declaration.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_com_string_h
+#define VBOX_INCLUDED_com_string_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+/* Make sure all the stdint.h macros are included - must come first! */
+#ifndef __STDC_LIMIT_MACROS
+# define __STDC_LIMIT_MACROS
+#endif
+#ifndef __STDC_CONSTANT_MACROS
+# define __STDC_CONSTANT_MACROS
+#endif
+
+#if defined(VBOX_WITH_XPCOM)
+# include <nsMemory.h>
+#endif
+
+#include "VBox/com/defs.h"
+#include "VBox/com/assert.h"
+
+#include <iprt/mem.h>
+#include <iprt/utf16.h>
+#include <iprt/cpp/ministring.h>
+
+
+/** @defgroup grp_com_str Smart String Classes
+ * @ingroup grp_com
+ * @{
+ */
+
+namespace com
+{
+
+class Utf8Str;
+
+// global constant in glue/string.cpp that represents an empty BSTR
+extern const BSTR g_bstrEmpty;
+
+/**
+ * String class used universally in Main for COM-style Utf-16 strings.
+ *
+ * Unfortunately COM on Windows uses UTF-16 everywhere, requiring conversions
+ * back and forth since most of VirtualBox and our libraries use UTF-8.
+ *
+ * To make things more obscure, on Windows, a COM-style BSTR is not just a
+ * pointer to a null-terminated wide character array, but the four bytes (32
+ * bits) BEFORE the memory that the pointer points to are a length DWORD. One
+ * must therefore avoid pointer arithmetic and always use SysAllocString and
+ * the like to deal with BSTR pointers, which manage that DWORD correctly.
+ *
+ * For platforms other than Windows, we provide our own versions of the Sys*
+ * functions in Main/xpcom/helpers.cpp which do NOT use length prefixes though
+ * to be compatible with how XPCOM allocates string parameters to public
+ * functions.
+ *
+ * The Bstr class hides all this handling behind a std::string-like interface
+ * and also provides automatic conversions to RTCString and Utf8Str instances.
+ *
+ * The one advantage of using the SysString* routines is that this makes it
+ * possible to use it as a type of member variables of COM/XPCOM components and
+ * pass their values to callers through component methods' output parameters
+ * using the #cloneTo() operation. Also, the class can adopt (take ownership
+ * of) string buffers returned in output parameters of COM methods using the
+ * #asOutParam() operation and correctly free them afterwards.
+ *
+ * Starting with VirtualBox 3.2, like Utf8Str, Bstr no longer differentiates
+ * between NULL strings and empty strings. In other words, Bstr("") and
+ * Bstr(NULL) behave the same. In both cases, Bstr allocates no memory,
+ * reports a zero length and zero allocated bytes for both, and returns an
+ * empty C wide string from raw().
+ *
+ * @note All Bstr methods ASSUMES valid UTF-16 or UTF-8 input strings.
+ * The VirtualBox policy in this regard is to validate strings coming
+ * from external sources before passing them to Bstr or Utf8Str.
+ */
+class Bstr
+{
+public:
+
+ Bstr()
+ : m_bstr(NULL)
+ { }
+
+ Bstr(const Bstr &that)
+ {
+ copyFrom((const OLECHAR *)that.m_bstr);
+ }
+
+ Bstr(CBSTR that)
+ {
+ copyFrom((const OLECHAR *)that);
+ }
+
+#if defined(VBOX_WITH_XPCOM)
+ Bstr(const wchar_t *that)
+ {
+ AssertCompile(sizeof(wchar_t) == sizeof(OLECHAR));
+ copyFrom((const OLECHAR *)that);
+ }
+#endif
+
+ Bstr(const RTCString &that)
+ {
+ copyFrom(that.c_str());
+ }
+
+ Bstr(const char *that)
+ {
+ copyFrom(that);
+ }
+
+ Bstr(const char *a_pThat, size_t a_cchMax)
+ {
+ copyFromN(a_pThat, a_cchMax);
+ }
+
+ ~Bstr()
+ {
+ setNull();
+ }
+
+ Bstr &operator=(const Bstr &that)
+ {
+ cleanupAndCopyFrom((const OLECHAR *)that.m_bstr);
+ return *this;
+ }
+
+ Bstr &operator=(CBSTR that)
+ {
+ cleanupAndCopyFrom((const OLECHAR *)that);
+ return *this;
+ }
+
+#if defined(VBOX_WITH_XPCOM)
+ Bstr &operator=(const wchar_t *that)
+ {
+ cleanupAndCopyFrom((const OLECHAR *)that);
+ return *this;
+ }
+#endif
+
+ Bstr &setNull()
+ {
+ cleanup();
+ return *this;
+ }
+
+ /**
+ * Extended assignment method that returns a COM status code instead of an
+ * exception on failure.
+ *
+ * @returns S_OK or E_OUTOFMEMORY.
+ * @param a_rSrcStr The source string
+ */
+ HRESULT assignEx(const Bstr &a_rSrcStr) RT_NOEXCEPT
+ {
+ return cleanupAndCopyFromEx((const OLECHAR *)a_rSrcStr.m_bstr);
+ }
+
+ /**
+ * Extended assignment method that returns a COM status code instead of an
+ * exception on failure.
+ *
+ * @returns S_OK or E_OUTOFMEMORY.
+ * @param a_pSrcStr The source string
+ */
+ HRESULT assignEx(CBSTR a_pSrcStr) RT_NOEXCEPT
+ {
+ return cleanupAndCopyFromEx((const OLECHAR *)a_pSrcStr);
+ }
+
+ /**
+ * Assign the value of a RTCString/Utf8Str string, no exceptions.
+ *
+ * @returns S_OK or E_OUTOFMEMORY.
+ * @param a_rSrcStr The source string
+ */
+ HRESULT assignEx(RTCString const &a_rSrcStr) RT_NOEXCEPT
+ {
+ return cleanupAndCopyFromNoThrow(a_rSrcStr.c_str(), a_rSrcStr.length());
+ }
+
+ /**
+ * Assign the value of a RTCString/Utf8Str substring, no exceptions.
+ *
+ * @returns S_OK, E_OUTOFMEMORY or E_INVALIDARG.
+ * @param a_rSrcStr The source string
+ * @param a_offSrc The character (byte) offset of the substring.
+ * @param a_cchSrc The number of characters (bytes) to copy from the source
+ * string.
+ */
+ HRESULT assignEx(RTCString const &a_rSrcStr, size_t a_offSrc, size_t a_cchSrc) RT_NOEXCEPT
+ {
+ size_t const cchTmp = a_rSrcStr.length();
+ if ( a_offSrc + a_cchSrc < cchTmp
+ && a_offSrc < cchTmp)
+ return cleanupAndCopyFromNoThrow(a_rSrcStr.c_str() + a_offSrc, a_cchSrc);
+ return E_INVALIDARG;
+ }
+
+ /**
+ * Assign the value of a zero terminated UTF-8 string, no exceptions.
+ *
+ * @returns S_OK or E_OUTOFMEMORY.
+ * @param a_pszSrcStr The source string.
+ */
+ HRESULT assignEx(const char *a_pszSrcStr) RT_NOEXCEPT
+ {
+ return cleanupAndCopyFromNoThrow(a_pszSrcStr, RTSTR_MAX);
+ }
+
+ /**
+ * Assign the value of a UTF-8 substring, no exceptions.
+ *
+ * @returns S_OK or E_OUTOFMEMORY.
+ * @param a_pszSrcStr The source string.
+ * @param a_cchSrc The number of characters (bytes) to copy from the source
+ * string.
+ */
+ HRESULT assignEx(const char *a_pszSrcStr, size_t a_cchSrc) RT_NOEXCEPT
+ {
+ return cleanupAndCopyFromNoThrow(a_pszSrcStr, a_cchSrc);
+ }
+
+#ifdef _MSC_VER
+# if _MSC_VER >= 1400
+ RTMEMEF_NEW_AND_DELETE_OPERATORS();
+# endif
+#else
+ RTMEMEF_NEW_AND_DELETE_OPERATORS();
+#endif
+
+ /** Case sensitivity selector. */
+ enum CaseSensitivity
+ {
+ CaseSensitive,
+ CaseInsensitive
+ };
+
+ /**
+ * Compares the member string to str.
+ * @param str
+ * @param cs Whether comparison should be case-sensitive.
+ * @return
+ */
+ int compare(CBSTR str, CaseSensitivity cs = CaseSensitive) const
+ {
+ if (cs == CaseSensitive)
+ return ::RTUtf16Cmp((PRTUTF16)m_bstr, (PRTUTF16)str);
+ return ::RTUtf16LocaleICmp((PRTUTF16)m_bstr, (PRTUTF16)str);
+ }
+
+ int compare(BSTR str, CaseSensitivity cs = CaseSensitive) const
+ {
+ return compare((CBSTR)str, cs);
+ }
+
+ int compare(const Bstr &that, CaseSensitivity cs = CaseSensitive) const
+ {
+ return compare(that.m_bstr, cs);
+ }
+
+ bool operator==(const Bstr &that) const { return !compare(that.m_bstr); }
+ bool operator==(CBSTR that) const { return !compare(that); }
+ bool operator==(BSTR that) const { return !compare(that); }
+ bool operator!=(const Bstr &that) const { return !!compare(that.m_bstr); }
+ bool operator!=(CBSTR that) const { return !!compare(that); }
+ bool operator!=(BSTR that) const { return !!compare(that); }
+ bool operator<(const Bstr &that) const { return compare(that.m_bstr) < 0; }
+ bool operator<(CBSTR that) const { return compare(that) < 0; }
+ bool operator<(BSTR that) const { return compare(that) < 0; }
+ bool operator<=(const Bstr &that) const { return compare(that.m_bstr) <= 0; }
+ bool operator<=(CBSTR that) const { return compare(that) <= 0; }
+ bool operator<=(BSTR that) const { return compare(that) <= 0; }
+ bool operator>(const Bstr &that) const { return compare(that.m_bstr) > 0; }
+ bool operator>(CBSTR that) const { return compare(that) > 0; }
+ bool operator>(BSTR that) const { return compare(that) > 0; }
+ bool operator>=(const Bstr &that) const { return compare(that.m_bstr) >= 0; }
+ bool operator>=(CBSTR that) const { return compare(that) >= 0; }
+ bool operator>=(BSTR that) const { return compare(that) >= 0; }
+
+ /**
+ * Compares this string to an UTF-8 C style string.
+ *
+ * @retval 0 if equal
+ * @retval -1 if this string is smaller than the UTF-8 one.
+ * @retval 1 if the UTF-8 string is smaller than this.
+ *
+ * @param a_pszRight The string to compare with.
+ * @param a_enmCase Whether comparison should be case-sensitive.
+ */
+ int compareUtf8(const char *a_pszRight, CaseSensitivity a_enmCase = CaseSensitive) const;
+
+ /** Java style compare method.
+ * @returns true if @a a_pszRight equals this string.
+ * @param a_pszRight The (UTF-8) string to compare with. */
+ bool equals(const char *a_pszRight) const { return compareUtf8(a_pszRight, CaseSensitive) == 0; }
+
+ /** Java style case-insensitive compare method.
+ * @returns true if @a a_pszRight equals this string.
+ * @param a_pszRight The (UTF-8) string to compare with. */
+ bool equalsIgnoreCase(const char *a_pszRight) const { return compareUtf8(a_pszRight, CaseInsensitive) == 0; }
+
+ /** Java style compare method.
+ * @returns true if @a a_rThat equals this string.
+ * @param a_rThat The other Bstr instance to compare with. */
+ bool equals(const Bstr &a_rThat) const { return compare(a_rThat.m_bstr, CaseSensitive) == 0; }
+ /** Java style case-insensitive compare method.
+ * @returns true if @a a_rThat equals this string.
+ * @param a_rThat The other Bstr instance to compare with. */
+ bool equalsIgnoreCase(const Bstr &a_rThat) const { return compare(a_rThat.m_bstr, CaseInsensitive) == 0; }
+
+ /** Java style compare method.
+ * @returns true if @a a_pThat equals this string.
+ * @param a_pThat The native const BSTR to compare with. */
+ bool equals(CBSTR a_pThat) const { return compare(a_pThat, CaseSensitive) == 0; }
+ /** Java style case-insensitive compare method.
+ * @returns true if @a a_pThat equals this string.
+ * @param a_pThat The native const BSTR to compare with. */
+ bool equalsIgnoreCase(CBSTR a_pThat) const { return compare(a_pThat, CaseInsensitive) == 0; }
+
+ /** Java style compare method.
+ * @returns true if @a a_pThat equals this string.
+ * @param a_pThat The native BSTR to compare with. */
+ bool equals(BSTR a_pThat) const { return compare(a_pThat, CaseSensitive) == 0; }
+ /** Java style case-insensitive compare method.
+ * @returns true if @a a_pThat equals this string.
+ * @param a_pThat The native BSTR to compare with. */
+ bool equalsIgnoreCase(BSTR a_pThat) const { return compare(a_pThat, CaseInsensitive) == 0; }
+
+ /**
+ * Checks if the string starts with @a a_rStart.
+ */
+ bool startsWith(Bstr const &a_rStart) const;
+ /**
+ * Checks if the string starts with @a a_rStart.
+ */
+ bool startsWith(RTCString const &a_rStart) const;
+ /**
+ * Checks if the string starts with @a a_pszStart.
+ */
+ bool startsWith(const char *a_pszStart) const;
+
+ /**
+ * Returns true if the member string has no length.
+ * This is true for instances created from both NULL and "" input strings.
+ *
+ * @note Always use this method to check if an instance is empty. Do not
+ * use length() because that may need to run through the entire string
+ * (Bstr does not cache string lengths).
+ */
+ bool isEmpty() const { return m_bstr == NULL || *m_bstr == 0; }
+
+ /**
+ * Returns true if the member string has a length of one or more.
+ *
+ * @returns true if not empty, false if empty (NULL or "").
+ */
+ bool isNotEmpty() const { return m_bstr != NULL && *m_bstr != 0; }
+
+ size_t length() const { return isEmpty() ? 0 : ::RTUtf16Len((PRTUTF16)m_bstr); }
+
+ /**
+ * Assigns the output of the string format operation (RTStrPrintf).
+ *
+ * @param pszFormat Pointer to the format string,
+ * @see pg_rt_str_format.
+ * @param ... Ellipsis containing the arguments specified by
+ * the format string.
+ *
+ * @throws std::bad_alloc On allocation error. Object state is undefined.
+ *
+ * @returns Reference to the object.
+ */
+ Bstr &printf(const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(1, 2);
+
+ /**
+ * Assigns the output of the string format operation (RTStrPrintf).
+ *
+ * @param pszFormat Pointer to the format string,
+ * @see pg_rt_str_format.
+ * @param ... Ellipsis containing the arguments specified by
+ * the format string.
+ *
+ * @returns S_OK, E_OUTOFMEMORY or E_INVAL (bad encoding).
+ */
+ HRESULT printfNoThrow(const char *pszFormat, ...) RT_NOEXCEPT RT_IPRT_FORMAT_ATTR(1, 2);
+
+ /**
+ * Assigns the output of the string format operation (RTStrPrintfV).
+ *
+ * @param pszFormat Pointer to the format string,
+ * @see pg_rt_str_format.
+ * @param va Argument vector containing the arguments
+ * specified by the format string.
+ *
+ * @throws std::bad_alloc On allocation error. Object state is undefined.
+ *
+ * @returns Reference to the object.
+ */
+ Bstr &printfV(const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(1, 0);
+
+ /**
+ * Assigns the output of the string format operation (RTStrPrintfV).
+ *
+ * @param pszFormat Pointer to the format string,
+ * @see pg_rt_str_format.
+ * @param va Argument vector containing the arguments
+ * specified by the format string.
+ *
+ * @returns S_OK, E_OUTOFMEMORY or E_INVAL (bad encoding).
+ */
+ HRESULT printfVNoThrow(const char *pszFormat, va_list va) RT_NOEXCEPT RT_IPRT_FORMAT_ATTR(1, 0);
+
+ /** @name Append methods and operators
+ * @{ */
+
+ /**
+ * Appends the string @a that to @a rThat.
+ *
+ * @param rThat The string to append.
+ * @throws std::bad_alloc On allocation error. The object is left unchanged.
+ * @returns Reference to the object.
+ */
+ Bstr &append(const Bstr &rThat);
+
+ /**
+ * Appends the string @a that to @a rThat.
+ *
+ * @param rThat The string to append.
+ * @returns S_OK, E_OUTOFMEMORY or E_INVAL (bad encoding).
+ */
+ HRESULT appendNoThrow(const Bstr &rThat) RT_NOEXCEPT;
+
+ /**
+ * Appends the UTF-8 string @a that to @a rThat.
+ *
+ * @param rThat The string to append.
+ * @throws std::bad_alloc On allocation error. The object is left unchanged.
+ * @returns Reference to the object.
+ */
+ Bstr &append(const RTCString &rThat);
+
+ /**
+ * Appends the UTF-8 string @a that to @a rThat.
+ *
+ * @param rThat The string to append.
+ * @returns S_OK, E_OUTOFMEMORY or E_INVAL (bad encoding).
+ */
+ HRESULT appendNoThrow(const RTCString &rThat) RT_NOEXCEPT;
+
+ /**
+ * Appends the UTF-16 string @a pszSrc to @a this.
+ *
+ * @param pwszSrc The C-style UTF-16 string to append.
+ * @throws std::bad_alloc On allocation error. The object is left unchanged.
+ * @returns Reference to the object.
+ */
+ Bstr &append(CBSTR pwszSrc);
+
+ /**
+ * Appends the UTF-16 string @a pszSrc to @a this.
+ *
+ * @param pwszSrc The C-style UTF-16 string to append.
+ * @returns S_OK, E_OUTOFMEMORY or E_INVAL (bad encoding).
+ */
+ HRESULT appendNoThrow(CBSTR pwszSrc) RT_NOEXCEPT;
+
+ /**
+ * Appends the UTF-8 string @a pszSrc to @a this.
+ *
+ * @param pszSrc The C-style string to append.
+ * @throws std::bad_alloc On allocation error. The object is left unchanged.
+ * @returns Reference to the object.
+ */
+ Bstr &append(const char *pszSrc);
+
+ /**
+ * Appends the UTF-8 string @a pszSrc to @a this.
+ *
+ * @param pszSrc The C-style string to append.
+ * @returns S_OK, E_OUTOFMEMORY or E_INVAL (bad encoding).
+ */
+ HRESULT appendNoThrow(const char *pszSrc) RT_NOEXCEPT;
+
+ /**
+ * Appends the a substring from @a rThat to @a this.
+ *
+ * @param rThat The string to append a substring from.
+ * @param offStart The start of the substring to append (UTF-16
+ * offset, not codepoint).
+ * @param cwcMax The maximum number of UTF-16 units to append.
+ * @throws std::bad_alloc On allocation error. The object is left unchanged.
+ * @returns Reference to the object.
+ */
+ Bstr &append(const Bstr &rThat, size_t offStart, size_t cwcMax = RTSTR_MAX);
+
+ /**
+ * Appends the a substring from @a rThat to @a this.
+ *
+ * @param rThat The string to append a substring from.
+ * @param offStart The start of the substring to append (UTF-16
+ * offset, not codepoint).
+ * @param cwcMax The maximum number of UTF-16 units to append.
+ * @returns S_OK, E_OUTOFMEMORY or E_INVAL (bad encoding).
+ */
+ HRESULT appendNoThrow(const Bstr &rThat, size_t offStart, size_t cwcMax = RTSTR_MAX) RT_NOEXCEPT;
+
+ /**
+ * Appends the a substring from UTF-8 @a rThat to @a this.
+ *
+ * @param rThat The string to append a substring from.
+ * @param offStart The start of the substring to append (byte offset,
+ * not codepoint).
+ * @param cchMax The maximum number of bytes to append.
+ * @throws std::bad_alloc On allocation error. The object is left unchanged.
+ * @returns Reference to the object.
+ */
+ Bstr &append(const RTCString &rThat, size_t offStart, size_t cchMax = RTSTR_MAX);
+
+ /**
+ * Appends the a substring from UTF-8 @a rThat to @a this.
+ *
+ * @param rThat The string to append a substring from.
+ * @param offStart The start of the substring to append (byte offset,
+ * not codepoint).
+ * @param cchMax The maximum number of bytes to append.
+ * @returns S_OK, E_OUTOFMEMORY or E_INVAL (bad encoding).
+ */
+ HRESULT appendNoThrow(const RTCString &rThat, size_t offStart, size_t cchMax = RTSTR_MAX) RT_NOEXCEPT;
+
+ /**
+ * Appends the first @a cchMax chars from UTF-16 string @a pszThat to @a this.
+ *
+ * @param pwszThat The C-style UTF-16 string to append.
+ * @param cchMax The maximum number of bytes to append.
+ * @throws std::bad_alloc On allocation error. The object is left unchanged.
+ * @returns Reference to the object.
+ */
+ Bstr &append(CBSTR pwszThat, size_t cchMax);
+
+ /**
+ * Appends the first @a cchMax chars from UTF-16 string @a pszThat to @a this.
+ *
+ * @param pwszThat The C-style UTF-16 string to append.
+ * @param cchMax The maximum number of bytes to append.
+ * @returns S_OK, E_OUTOFMEMORY or E_INVAL (bad encoding).
+ */
+ HRESULT appendNoThrow(CBSTR pwszThat, size_t cchMax) RT_NOEXCEPT;
+
+ /**
+ * Appends the first @a cchMax chars from string @a pszThat to @a this.
+ *
+ * @param pszThat The C-style string to append.
+ * @param cchMax The maximum number of bytes to append.
+ * @throws std::bad_alloc On allocation error. The object is left unchanged.
+ * @returns Reference to the object.
+ */
+ Bstr &append(const char *pszThat, size_t cchMax);
+
+ /**
+ * Appends the first @a cchMax chars from string @a pszThat to @a this.
+ *
+ * @param pszThat The C-style string to append.
+ * @param cchMax The maximum number of bytes to append.
+ * @returns S_OK, E_OUTOFMEMORY or E_INVAL (bad encoding).
+ */
+ HRESULT appendNoThrow(const char *pszThat, size_t cchMax) RT_NOEXCEPT;
+
+ /**
+ * Appends the given character to @a this.
+ *
+ * @param ch The character to append.
+ * @throws std::bad_alloc On allocation error. The object is left unchanged.
+ * @returns Reference to the object.
+ */
+ Bstr &append(char ch);
+
+ /**
+ * Appends the given character to @a this.
+ *
+ * @param ch The character to append.
+ * @returns S_OK, E_OUTOFMEMORY or E_INVAL (bad encoding).
+ */
+ HRESULT appendNoThrow(char ch) RT_NOEXCEPT;
+
+ /**
+ * Appends the given unicode code point to @a this.
+ *
+ * @param uc The unicode code point to append.
+ * @throws std::bad_alloc On allocation error. The object is left unchanged.
+ * @returns Reference to the object.
+ */
+ Bstr &appendCodePoint(RTUNICP uc);
+
+ /**
+ * Appends the given unicode code point to @a this.
+ *
+ * @param uc The unicode code point to append.
+ * @returns S_OK, E_OUTOFMEMORY or E_INVAL (bad encoding).
+ */
+ HRESULT appendCodePointNoThrow(RTUNICP uc) RT_NOEXCEPT;
+
+ /**
+ * Appends the output of the string format operation (RTStrPrintf).
+ *
+ * @param pszFormat Pointer to the format string,
+ * @see pg_rt_str_format.
+ * @param ... Ellipsis containing the arguments specified by
+ * the format string.
+ *
+ * @throws std::bad_alloc On allocation error. Object state is undefined.
+ *
+ * @returns Reference to the object.
+ */
+ Bstr &appendPrintf(const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(1, 2);
+
+ /**
+ * Appends the output of the string format operation (RTStrPrintf).
+ *
+ * @param pszFormat Pointer to the format string,
+ * @see pg_rt_str_format.
+ * @param ... Ellipsis containing the arguments specified by
+ * the format string.
+ *
+ * @returns S_OK, E_OUTOFMEMORY or E_INVAL (bad encoding).
+ */
+ HRESULT appendPrintfNoThrow(const char *pszFormat, ...) RT_NOEXCEPT RT_IPRT_FORMAT_ATTR(1, 2);
+
+ /**
+ * Appends the output of the string format operation (RTStrPrintfV).
+ *
+ * @param pszFormat Pointer to the format string,
+ * @see pg_rt_str_format.
+ * @param va Argument vector containing the arguments
+ * specified by the format string.
+ *
+ * @throws std::bad_alloc On allocation error. Object state is undefined.
+ *
+ * @returns Reference to the object.
+ */
+ Bstr &appendPrintfV(const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(1, 0);
+
+ /**
+ * Appends the output of the string format operation (RTStrPrintfV).
+ *
+ * @param pszFormat Pointer to the format string,
+ * @see pg_rt_str_format.
+ * @param va Argument vector containing the arguments
+ * specified by the format string.
+ *
+ * @returns S_OK, E_OUTOFMEMORY or E_INVAL (bad encoding).
+ */
+ HRESULT appendPrintfVNoThrow(const char *pszFormat, va_list va) RT_NOEXCEPT RT_IPRT_FORMAT_ATTR(1, 0);
+
+ /**
+ * Shortcut to append(), Bstr variant.
+ *
+ * @param rThat The string to append.
+ * @returns Reference to the object.
+ */
+ Bstr &operator+=(const Bstr &rThat)
+ {
+ return append(rThat);
+ }
+
+ /**
+ * Shortcut to append(), RTCString variant.
+ *
+ * @param rThat The string to append.
+ * @returns Reference to the object.
+ */
+ Bstr &operator+=(const RTCString &rThat)
+ {
+ return append(rThat);
+ }
+
+ /**
+ * Shortcut to append(), CBSTR variant.
+ *
+ * @param pwszThat The C-style string to append.
+ * @returns Reference to the object.
+ */
+ Bstr &operator+=(CBSTR pwszThat)
+ {
+ return append(pwszThat);
+ }
+
+ /**
+ * Shortcut to append(), const char * variant.
+ *
+ * @param pszThat The C-style string to append.
+ * @returns Reference to the object.
+ */
+ Bstr &operator+=(const char *pszThat)
+ {
+ return append(pszThat);
+ }
+
+ /**
+ * Shortcut to append(), char variant.
+ *
+ * @param ch The character to append.
+ *
+ * @returns Reference to the object.
+ */
+ Bstr &operator+=(char ch)
+ {
+ return append(ch);
+ }
+
+ /** @} */
+
+ /**
+ * Erases a sequence from the string.
+ *
+ * @returns Reference to the object.
+ * @param offStart Where in @a this string to start erasing (UTF-16
+ * units, not codepoints).
+ * @param cwcLength How much following @a offStart to erase (UTF-16
+ * units, not codepoints).
+ */
+ Bstr &erase(size_t offStart = 0, size_t cwcLength = RTSTR_MAX) RT_NOEXCEPT;
+
+
+ /** @name BASE64 related methods
+ * @{ */
+ /**
+ * Encodes the given data as BASE64.
+ *
+ * @returns S_OK or E_OUTOFMEMORY.
+ * @param pvData Pointer to the data to encode.
+ * @param cbData Number of bytes to encode.
+ * @param fLineBreaks Whether to add line breaks (true) or just encode it
+ * as a continuous string.
+ * @sa RTBase64EncodeUtf16
+ */
+ HRESULT base64Encode(const void *pvData, size_t cbData, bool fLineBreaks = false);
+
+ /**
+ * Decodes the string as BASE64.
+ *
+ * @returns IPRT status code, see RTBase64DecodeUtf16Ex.
+ * @param pvData Where to return the decoded bytes.
+ * @param cbData Size of the @a pvData return buffer.
+ * @param pcbActual Where to return number of bytes actually decoded.
+ * This is optional and if not specified, the request
+ * will fail unless @a cbData matches the data size
+ * exactly.
+ * @param ppwszEnd Where to return pointer to the first non-base64
+ * character following the encoded data. This is
+ * optional and if NULL, the request will fail if there
+ * are anything trailing the encoded bytes in the
+ * string.
+ * @sa base64DecodedSize, RTBase64DecodeUtf16
+ */
+ int base64Decode(void *pvData, size_t cbData, size_t *pcbActual = NULL, PRTUTF16 *ppwszEnd = NULL);
+
+ /**
+ * Determins the size of the BASE64 encoded data in the string.
+ *
+ * @returns The length in bytes. -1 if the encoding is bad.
+ *
+ * @param ppwszEnd If not NULL, this will point to the first char
+ * following the Base64 encoded text block. If
+ * NULL the entire string is assumed to be Base64.
+ * @sa base64Decode, RTBase64DecodedUtf16Size
+ */
+ ssize_t base64DecodedSize(PRTUTF16 *ppwszEnd = NULL);
+ /** @} */
+
+#if defined(VBOX_WITH_XPCOM)
+ /**
+ * Returns a pointer to the raw member UTF-16 string. If the member string is empty,
+ * returns a pointer to a global variable containing an empty BSTR with a proper zero
+ * length prefix so that Windows is happy.
+ */
+ CBSTR raw() const
+ {
+ if (m_bstr)
+ return m_bstr;
+
+ return g_bstrEmpty;
+ }
+#else
+ /**
+ * Windows-only hack, as the automatically generated headers use BSTR.
+ * So if we don't want to cast like crazy we have to be more loose than
+ * on XPCOM.
+ *
+ * Returns a pointer to the raw member UTF-16 string. If the member string is empty,
+ * returns a pointer to a global variable containing an empty BSTR with a proper zero
+ * length prefix so that Windows is happy.
+ */
+ BSTR raw() const
+ {
+ if (m_bstr)
+ return m_bstr;
+
+ return g_bstrEmpty;
+ }
+#endif
+
+ /**
+ * Returns a non-const raw pointer that allows modifying the string directly.
+ *
+ * @note As opposed to raw(), this DOES return NULL if the member string is
+ * empty because we cannot return a mutable pointer to the global variable
+ * with the empty string.
+ *
+ * @note If modifying the string size (only shrinking it is allows), #jolt() or
+ * #joltNoThrow() must be called!
+ *
+ * @note Do not modify memory beyond the #length() of the string!
+ *
+ * @sa joltNoThrow(), mutalbleRaw(), reserve(), reserveNoThrow()
+ */
+ BSTR mutableRaw() { return m_bstr; }
+
+ /**
+ * Correct the embedded length after using mutableRaw().
+ *
+ * This is needed on COM (Windows) to update the embedded string length. It is
+ * a stub on hosts using XPCOM.
+ *
+ * @param cwcNew The new string length, if handy, otherwise a negative
+ * number.
+ * @sa joltNoThrow(), mutalbleRaw(), reserve(), reserveNoThrow()
+ */
+#ifndef VBOX_WITH_XPCOM
+ void jolt(ssize_t cwcNew = -1);
+#else
+ void jolt(ssize_t cwcNew = -1)
+ {
+ Assert(cwcNew < 0 || (cwcNew == 0 && !m_bstr) || m_bstr[cwcNew] == '\0'); RT_NOREF(cwcNew);
+ }
+#endif
+
+ /**
+ * Correct the embedded length after using mutableRaw().
+ *
+ * This is needed on COM (Windows) to update the embedded string length. It is
+ * a stub on hosts using XPCOM.
+ *
+ * @returns S_OK on success, E_OUTOFMEMORY if shrinking the string failed.
+ * @param cwcNew The new string length, if handy, otherwise a negative
+ * number.
+ * @sa jolt(), mutalbleRaw(), reserve(), reserveNoThrow()
+ */
+#ifndef VBOX_WITH_XPCOM
+ HRESULT joltNoThrow(ssize_t cwcNew = -1) RT_NOEXCEPT;
+#else
+ HRESULT joltNoThrow(ssize_t cwcNew = -1) RT_NOEXCEPT
+ {
+ Assert(cwcNew < 0 || (cwcNew == 0 && !m_bstr) || m_bstr[cwcNew] == '\0'); RT_NOREF(cwcNew);
+ return S_OK;
+ }
+#endif
+
+ /**
+ * Make sure at that least @a cwc of buffer space is reserved.
+ *
+ * Requests that the contained memory buffer have at least cb bytes allocated.
+ * This may expand or shrink the string's storage, but will never truncate the
+ * contained string. In other words, cb will be ignored if it's smaller than
+ * length() + 1.
+ *
+ * @param cwcMin The new minimum string length that the can be stored. This
+ * does not include the terminator.
+ * @param fForce Force this size.
+ *
+ * @throws std::bad_alloc On allocation error. The object is left unchanged.
+ */
+ void reserve(size_t cwcMin, bool fForce = false);
+
+ /**
+ * A C like version of the #reserve() method, i.e. return code instead of throw.
+ *
+ * @returns S_OK or E_OUTOFMEMORY.
+ * @param cwcMin The new minimum string length that the can be stored. This
+ * does not include the terminator.
+ * @param fForce Force this size.
+ */
+ HRESULT reserveNoThrow(size_t cwcMin, bool fForce = false) RT_NOEXCEPT;
+
+ /**
+ * Intended to assign copies of instances to |BSTR| out parameters from
+ * within the interface method. Transfers the ownership of the duplicated
+ * string to the caller.
+ *
+ * If the member string is empty, this allocates an empty BSTR in *pstr
+ * (i.e. makes it point to a new buffer with a null byte).
+ *
+ * @deprecated Use cloneToEx instead to avoid throwing exceptions.
+ */
+ void cloneTo(BSTR *pstr) const
+ {
+ if (pstr)
+ {
+ *pstr = ::SysAllocString((const OLECHAR *)raw()); // raw() returns a pointer to "" if empty
+#ifdef RT_EXCEPTIONS_ENABLED
+ if (!*pstr)
+ throw std::bad_alloc();
+#endif
+ }
+ }
+
+ /**
+ * A version of cloneTo that does not throw any out of memory exceptions, but
+ * returns E_OUTOFMEMORY intead.
+ * @returns S_OK or E_OUTOFMEMORY.
+ */
+ HRESULT cloneToEx(BSTR *pstr) const
+ {
+ if (!pstr)
+ return S_OK;
+ *pstr = ::SysAllocString((const OLECHAR *)raw()); // raw() returns a pointer to "" if empty
+ return pstr ? S_OK : E_OUTOFMEMORY;
+ }
+
+ /**
+ * Intended to assign instances to |BSTR| out parameters from within the
+ * interface method. Transfers the ownership of the original string to the
+ * caller and resets the instance to null.
+ *
+ * As opposed to cloneTo(), this method doesn't create a copy of the
+ * string.
+ *
+ * If the member string is empty, this allocates an empty BSTR in *pstr
+ * (i.e. makes it point to a new buffer with a null byte).
+ *
+ * @param pbstrDst The BSTR variable to detach the string to.
+ *
+ * @throws std::bad_alloc if we failed to allocate a new empty string.
+ */
+ void detachTo(BSTR *pbstrDst)
+ {
+ if (m_bstr)
+ {
+ *pbstrDst = m_bstr;
+ m_bstr = NULL;
+ }
+ else
+ {
+ // allocate null BSTR
+ *pbstrDst = ::SysAllocString((const OLECHAR *)g_bstrEmpty);
+#ifdef RT_EXCEPTIONS_ENABLED
+ if (!*pbstrDst)
+ throw std::bad_alloc();
+#endif
+ }
+ }
+
+ /**
+ * A version of detachTo that does not throw exceptions on out-of-memory
+ * conditions, but instead returns E_OUTOFMEMORY.
+ *
+ * @param pbstrDst The BSTR variable to detach the string to.
+ * @returns S_OK or E_OUTOFMEMORY.
+ */
+ HRESULT detachToEx(BSTR *pbstrDst)
+ {
+ if (m_bstr)
+ {
+ *pbstrDst = m_bstr;
+ m_bstr = NULL;
+ }
+ else
+ {
+ // allocate null BSTR
+ *pbstrDst = ::SysAllocString((const OLECHAR *)g_bstrEmpty);
+ if (!*pbstrDst)
+ return E_OUTOFMEMORY;
+ }
+ return S_OK;
+ }
+
+ /**
+ * Intended to pass instances as |BSTR| out parameters to methods.
+ * Takes the ownership of the returned data.
+ */
+ BSTR *asOutParam()
+ {
+ cleanup();
+ return &m_bstr;
+ }
+
+ /**
+ * Static immutable empty-string object. May be used for comparison purposes.
+ */
+ static const Bstr Empty;
+
+protected:
+
+ void cleanup();
+
+ /**
+ * Protected internal helper to copy a string. This ignores the previous object
+ * state, so either call this from a constructor or call cleanup() first.
+ *
+ * This variant copies from a zero-terminated UTF-16 string (which need not
+ * be a BSTR, i.e. need not have a length prefix).
+ *
+ * If the source is empty, this sets the member string to NULL.
+ *
+ * @param a_bstrSrc The source string. The caller guarantees
+ * that this is valid UTF-16.
+ *
+ * @throws std::bad_alloc - the object is representing an empty string.
+ */
+ void copyFrom(const OLECHAR *a_bstrSrc);
+
+ /** cleanup() + copyFrom() - for assignment operators. */
+ void cleanupAndCopyFrom(const OLECHAR *a_bstrSrc);
+
+ /**
+ * Protected internal helper to copy a string, implying cleanup().
+ *
+ * This variant copies from a zero-terminated UTF-16 string (which need not be a
+ * BSTR, i.e. need not have a length prefix).
+ *
+ * If the source is empty, this sets the member string to NULL.
+ *
+ * @param a_bstrSrc The source string. The caller guarantees
+ * that this is valid UTF-16.
+ * @returns S_OK or E_OUTOFMEMORY
+ */
+ HRESULT cleanupAndCopyFromEx(const OLECHAR *a_bstrSrc) RT_NOEXCEPT;
+
+ /**
+ * Protected internal helper to copy a string. This ignores the previous object
+ * state, so either call this from a constructor or call cleanup() first.
+ *
+ * This variant copies and converts from a zero-terminated UTF-8 string.
+ *
+ * If the source is empty, this sets the member string to NULL.
+ *
+ * @param a_pszSrc The source string. The caller guarantees
+ * that this is valid UTF-8.
+ *
+ * @throws std::bad_alloc - the object is representing an empty string.
+ */
+ void copyFrom(const char *a_pszSrc)
+ {
+ copyFromN(a_pszSrc, RTSTR_MAX);
+ }
+
+ /**
+ * Variant of copyFrom for sub-string constructors.
+ *
+ * @param a_pszSrc The source string. The caller guarantees
+ * that this is valid UTF-8.
+ * @param a_cchSrc The maximum number of chars (not codepoints) to
+ * copy. If you pass RTSTR_MAX it'll be exactly
+ * like copyFrom().
+ *
+ * @throws std::bad_alloc - the object is representing an empty string.
+ */
+ void copyFromN(const char *a_pszSrc, size_t a_cchSrc);
+
+ /** cleanup() + non-throwing copyFromN(). */
+ HRESULT cleanupAndCopyFromNoThrow(const char *a_pszSrc, size_t a_cchMax) RT_NOEXCEPT;
+
+ Bstr &appendWorkerUtf16(PCRTUTF16 pwszSrc, size_t cwcSrc);
+ Bstr &appendWorkerUtf8(const char *pszSrc, size_t cchSrc);
+ HRESULT appendWorkerUtf16NoThrow(PCRTUTF16 pwszSrc, size_t cwcSrc) RT_NOEXCEPT;
+ HRESULT appendWorkerUtf8NoThrow(const char *pszSrc, size_t cchSrc) RT_NOEXCEPT;
+
+ static DECLCALLBACK(size_t) printfOutputCallbackNoThrow(void *pvArg, const char *pachChars, size_t cbChars) RT_NOEXCEPT;
+
+ BSTR m_bstr;
+
+ friend class Utf8Str; /* to access our raw_copy() */
+};
+
+/* symmetric compare operators */
+inline bool operator==(CBSTR l, const Bstr &r) { return r.operator==(l); }
+inline bool operator!=(CBSTR l, const Bstr &r) { return r.operator!=(l); }
+inline bool operator==(BSTR l, const Bstr &r) { return r.operator==(l); }
+inline bool operator!=(BSTR l, const Bstr &r) { return r.operator!=(l); }
+
+
+
+
+/**
+ * String class used universally in Main for UTF-8 strings.
+ *
+ * This is based on RTCString, to which some functionality has been
+ * moved. Here we keep things that are specific to Main, such as conversions
+ * with UTF-16 strings (Bstr).
+ *
+ * Like RTCString, Utf8Str does not differentiate between NULL strings
+ * and empty strings. In other words, Utf8Str("") and Utf8Str(NULL) behave the
+ * same. In both cases, RTCString allocates no memory, reports
+ * a zero length and zero allocated bytes for both, and returns an empty
+ * C string from c_str().
+ *
+ * @note All Utf8Str methods ASSUMES valid UTF-8 or UTF-16 input strings.
+ * The VirtualBox policy in this regard is to validate strings coming
+ * from external sources before passing them to Utf8Str or Bstr.
+ */
+class Utf8Str : public RTCString
+{
+public:
+
+ Utf8Str() {}
+
+ Utf8Str(const RTCString &that)
+ : RTCString(that)
+ {}
+
+ Utf8Str(const char *that)
+ : RTCString(that)
+ {}
+
+ Utf8Str(const Bstr &that)
+ {
+ copyFrom(that.raw());
+ }
+
+ Utf8Str(CBSTR that, size_t a_cwcSize = RTSTR_MAX)
+ {
+ copyFrom(that, a_cwcSize);
+ }
+
+ Utf8Str(const char *a_pszSrc, size_t a_cchSrc)
+ : RTCString(a_pszSrc, a_cchSrc)
+ {
+ }
+
+ /**
+ * Constructs a new string given the format string and the list of the
+ * arguments for the format string.
+ *
+ * @param a_pszFormat Pointer to the format string (UTF-8),
+ * @see pg_rt_str_format.
+ * @param a_va Argument vector containing the arguments
+ * specified by the format string.
+ * @sa RTCString::printfV
+ */
+ Utf8Str(const char *a_pszFormat, va_list a_va) RT_IPRT_FORMAT_ATTR(1, 0)
+ : RTCString(a_pszFormat, a_va)
+ {
+ }
+
+ Utf8Str& operator=(const RTCString &that)
+ {
+ RTCString::operator=(that);
+ return *this;
+ }
+
+ Utf8Str& operator=(const char *that)
+ {
+ RTCString::operator=(that);
+ return *this;
+ }
+
+ Utf8Str& operator=(const Bstr &that)
+ {
+ cleanup();
+ copyFrom(that.raw());
+ return *this;
+ }
+
+ Utf8Str& operator=(CBSTR that)
+ {
+ cleanup();
+ copyFrom(that);
+ return *this;
+ }
+
+ /**
+ * Extended assignment method that returns a COM status code instead of an
+ * exception on failure.
+ *
+ * @returns S_OK or E_OUTOFMEMORY.
+ * @param a_rSrcStr The source string
+ */
+ HRESULT assignEx(Utf8Str const &a_rSrcStr)
+ {
+ return copyFromExNComRC(a_rSrcStr.m_psz, 0, a_rSrcStr.m_cch);
+ }
+
+ /**
+ * Extended assignment method that returns a COM status code instead of an
+ * exception on failure.
+ *
+ * @returns S_OK, E_OUTOFMEMORY or E_INVALIDARG.
+ * @param a_rSrcStr The source string
+ * @param a_offSrc The character (byte) offset of the substring.
+ * @param a_cchSrc The number of characters (bytes) to copy from the source
+ * string.
+ */
+ HRESULT assignEx(Utf8Str const &a_rSrcStr, size_t a_offSrc, size_t a_cchSrc)
+ {
+ if ( a_offSrc + a_cchSrc > a_rSrcStr.m_cch
+ || a_offSrc > a_rSrcStr.m_cch)
+ return E_INVALIDARG;
+ return copyFromExNComRC(a_rSrcStr.m_psz, a_offSrc, a_cchSrc);
+ }
+
+ /**
+ * Extended assignment method that returns a COM status code instead of an
+ * exception on failure.
+ *
+ * @returns S_OK or E_OUTOFMEMORY.
+ * @param a_pcszSrc The source string
+ */
+ HRESULT assignEx(const char *a_pcszSrc)
+ {
+ return copyFromExNComRC(a_pcszSrc, 0, a_pcszSrc ? strlen(a_pcszSrc) : 0);
+ }
+
+ /**
+ * Extended assignment method that returns a COM status code instead of an
+ * exception on failure.
+ *
+ * @returns S_OK or E_OUTOFMEMORY.
+ * @param a_pcszSrc The source string
+ * @param a_cchSrc The number of characters (bytes) to copy from the source
+ * string.
+ */
+ HRESULT assignEx(const char *a_pcszSrc, size_t a_cchSrc)
+ {
+ return copyFromExNComRC(a_pcszSrc, 0, a_cchSrc);
+ }
+
+ RTMEMEF_NEW_AND_DELETE_OPERATORS();
+
+#if defined(VBOX_WITH_XPCOM)
+ /**
+ * Intended to assign instances to |char *| out parameters from within the
+ * interface method. Transfers the ownership of the duplicated string to the
+ * caller.
+ *
+ * This allocates a single 0 byte in the target if the member string is empty.
+ *
+ * This uses XPCOM memory allocation and thus only works on XPCOM. MSCOM doesn't
+ * like char* strings anyway.
+ */
+ void cloneTo(char **pstr) const;
+
+ /**
+ * A version of cloneTo that does not throw allocation errors but returns
+ * E_OUTOFMEMORY instead.
+ * @returns S_OK or E_OUTOFMEMORY (COM status codes).
+ */
+ HRESULT cloneToEx(char **pstr) const;
+#endif
+
+ /**
+ * Intended to assign instances to |BSTR| out parameters from within the
+ * interface method. Transfers the ownership of the duplicated string to the
+ * caller.
+ */
+ void cloneTo(BSTR *pstr) const
+ {
+ if (pstr)
+ {
+ Bstr bstr(*this);
+ bstr.cloneTo(pstr);
+ }
+ }
+
+ /**
+ * A version of cloneTo that does not throw allocation errors but returns
+ * E_OUTOFMEMORY instead.
+ *
+ * @param pbstr Where to store a clone of the string.
+ * @returns S_OK or E_OUTOFMEMORY (COM status codes).
+ */
+ HRESULT cloneToEx(BSTR *pbstr) const RT_NOEXCEPT;
+
+ /**
+ * Safe assignment from BSTR.
+ *
+ * @param pbstrSrc The source string.
+ * @returns S_OK or E_OUTOFMEMORY (COM status codes).
+ */
+ HRESULT cloneEx(CBSTR pbstrSrc)
+ {
+ cleanup();
+ return copyFromEx(pbstrSrc);
+ }
+
+ /**
+ * Removes a trailing slash from the member string, if present.
+ * Calls RTPathStripTrailingSlash() without having to mess with mutableRaw().
+ */
+ Utf8Str& stripTrailingSlash();
+
+ /**
+ * Removes a trailing filename from the member string, if present.
+ * Calls RTPathStripFilename() without having to mess with mutableRaw().
+ */
+ Utf8Str& stripFilename();
+
+ /**
+ * Removes the path component from the member string, if present.
+ * Calls RTPathFilename() without having to mess with mutableRaw().
+ */
+ Utf8Str& stripPath();
+
+ /**
+ * Removes a trailing file name suffix from the member string, if present.
+ * Calls RTPathStripSuffix() without having to mess with mutableRaw().
+ */
+ Utf8Str& stripSuffix();
+
+ /**
+ * Parses key=value pairs.
+ *
+ * @returns offset of the @a a_rPairSeparator following the returned value.
+ * @retval npos is returned if there are no more key/value pairs.
+ *
+ * @param a_rKey Reference to variable that should receive
+ * the key substring. This is set to null if
+ * no key/value found. (It's also possible the
+ * key is an empty string, so be careful.)
+ * @param a_rValue Reference to variable that should receive
+ * the value substring. This is set to null if
+ * no key/value found. (It's also possible the
+ * value is an empty string, so be careful.)
+ * @param a_offStart The offset to start searching from. This is
+ * typically 0 for the first call, and the
+ * return value of the previous call for the
+ * subsequent ones.
+ * @param a_rPairSeparator The pair separator string. If this is an
+ * empty string, the whole string will be
+ * considered as a single key/value pair.
+ * @param a_rKeyValueSeparator The key/value separator string.
+ */
+ size_t parseKeyValue(Utf8Str &a_rKey, Utf8Str &a_rValue, size_t a_offStart = 0,
+ const Utf8Str &a_rPairSeparator = ",", const Utf8Str &a_rKeyValueSeparator = "=") const;
+
+ /**
+ * Static immutable empty-string object. May be used for comparison purposes.
+ */
+ static const Utf8Str Empty;
+protected:
+
+ void copyFrom(CBSTR a_pbstr, size_t a_cwcMax = RTSTR_MAX);
+ HRESULT copyFromEx(CBSTR a_pbstr);
+ HRESULT copyFromExNComRC(const char *a_pcszSrc, size_t a_offSrc, size_t a_cchSrc);
+
+ friend class Bstr; /* to access our raw_copy() */
+};
+
+/**
+ * Class with RTCString::printf as constructor for your convenience.
+ *
+ * Constructing a Utf8Str string object from a format string and a variable
+ * number of arguments can easily be confused with the other Utf8Str
+ * constructures, thus this child class.
+ *
+ * The usage of this class is like the following:
+ * @code
+ Utf8StrFmt strName("program name = %s", argv[0]);
+ @endcode
+ *
+ * @note Do not use in assignments to Utf8Str variables. Instead use
+ * RTCString::printf directly on the variable! This avoid an extra
+ * temporary Utf8Str instance and assignment operation.
+ */
+class Utf8StrFmt : public Utf8Str
+{
+public:
+
+ /**
+ * Constructs a new string given the format string and the list of the
+ * arguments for the format string.
+ *
+ * @param a_pszFormat Pointer to the format string (UTF-8),
+ * @see pg_rt_str_format.
+ * @param ... Ellipsis containing the arguments specified by
+ * the format string.
+ */
+ explicit Utf8StrFmt(const char *a_pszFormat, ...) RT_IPRT_FORMAT_ATTR(1, 2)
+ {
+ va_list va;
+ va_start(va, a_pszFormat);
+ printfV(a_pszFormat, va);
+ va_end(va);
+ }
+
+ RTMEMEF_NEW_AND_DELETE_OPERATORS();
+
+protected:
+ Utf8StrFmt()
+ { }
+
+private:
+};
+
+/**
+ * Class with Bstr::printf as constructor for your convenience.
+ */
+class BstrFmt : public Bstr
+{
+public:
+
+ /**
+ * Constructs a new string given the format string and the list of the
+ * arguments for the format string.
+ *
+ * @param a_pszFormat printf-like format string (in UTF-8 encoding), see
+ * iprt/string.h for details.
+ * @param ... List of the arguments for the format string.
+ */
+ explicit BstrFmt(const char *a_pszFormat, ...) RT_IPRT_FORMAT_ATTR(1, 2)
+ {
+ va_list va;
+ va_start(va, a_pszFormat);
+ printfV(a_pszFormat, va);
+ va_end(va);
+ }
+
+ RTMEMEF_NEW_AND_DELETE_OPERATORS();
+
+protected:
+ BstrFmt()
+ { }
+};
+
+/**
+ * Class with Bstr::printfV as constructor for your convenience.
+ */
+class BstrFmtVA : public Bstr
+{
+public:
+
+ /**
+ * Constructs a new string given the format string and the list of the
+ * arguments for the format string.
+ *
+ * @param a_pszFormat printf-like format string (in UTF-8 encoding), see
+ * iprt/string.h for details.
+ * @param a_va List of arguments for the format string
+ */
+ BstrFmtVA(const char *a_pszFormat, va_list a_va) RT_IPRT_FORMAT_ATTR(1, 0)
+ {
+ printfV(a_pszFormat, a_va);
+ }
+
+ RTMEMEF_NEW_AND_DELETE_OPERATORS();
+
+protected:
+ BstrFmtVA()
+ { }
+};
+
+} /* namespace com */
+
+/** @} */
+
+#endif /* !VBOX_INCLUDED_com_string_h */
+
diff --git a/include/VBox/com/utils.h b/include/VBox/com/utils.h
new file mode 100644
index 00000000..e47b4129
--- /dev/null
+++ b/include/VBox/com/utils.h
@@ -0,0 +1,132 @@
+/** @file
+ * MS COM / XPCOM Abstraction Layer - COM initialization / shutdown.
+ */
+
+/*
+ * Copyright (C) 2005-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_com_utils_h
+#define VBOX_INCLUDED_com_utils_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include "iprt/types.h"
+
+/** @addtogroup grp_com
+ * @{
+ */
+
+namespace com
+{
+
+/**
+ * Returns the VirtualBox user home directory.
+ *
+ * On failure, this function will return a path that caused a failure (or
+ * NULL if the failure is not path-related).
+ *
+ * On success, this function will try to create the returned directory if it
+ * doesn't exist yet. This may also fail with the corresponding status code.
+ *
+ * If @a aDirLen is smaller than RTPATH_MAX then there is a great chance that
+ * this method will return VERR_BUFFER_OVERFLOW.
+ *
+ * @param aDir Buffer to store the directory string in UTF-8 encoding.
+ * @param aDirLen Length of the supplied buffer including space for the
+ * terminating null character, in bytes.
+ * @param fCreateDir Flag whether to create the returned directory on success
+ * if it doesn't exist.
+ * @returns VBox status code.
+ */
+int GetVBoxUserHomeDirectory(char *aDir, size_t aDirLen, bool fCreateDir = true);
+
+/**
+ * Creates a release log file, used both in VBoxSVC and in API clients.
+ *
+ * @param pszEntity Human readable name of the program.
+ * @param pszLogFile Name of the release log file.
+ * @param fFlags Logger instance flags.
+ * @param pszGroupSettings Group logging settings.
+ * @param pszEnvVarBase Base environment variable name for the logger.
+ * @param fDestFlags Logger destination flags.
+ * @param cMaxEntriesPerGroup Limit for log entries per group. UINT32_MAX for no limit.
+ * @param cHistory Number of old log files to keep.
+ * @param uHistoryFileTime Maximum amount of time to put in a log file.
+ * @param uHistoryFileSize Maximum size of a log file before rotating.
+ * @param pErrInfo Where to return extended error information.
+ * Optional.
+ *
+ * @returns VBox status code.
+ */
+int VBoxLogRelCreate(const char *pszEntity, const char *pszLogFile,
+ uint32_t fFlags, const char *pszGroupSettings,
+ const char *pszEnvVarBase, uint32_t fDestFlags,
+ uint32_t cMaxEntriesPerGroup, uint32_t cHistory,
+ uint32_t uHistoryFileTime, uint64_t uHistoryFileSize,
+ PRTERRINFO pErrInfo);
+
+/**
+ * Creates a release log file, used both in VBoxSVC and in API clients.
+ *
+ * @param pszEntity Human readable name of the program.
+ * @param pszLogFile Name of the release log file.
+ * @param fFlags Logger instance flags.
+ * @param pszGroupSettings Group logging settings.
+ * @param pszEnvVarBase Base environment variable name for the logger.
+ * @param fDestFlags Logger destination flags.
+ * @param cMaxEntriesPerGroup Limit for log entries per group. UINT32_MAX for no limit.
+ * @param cHistory Number of old log files to keep.
+ * @param uHistoryFileTime Maximum amount of time to put in a log file.
+ * @param uHistoryFileSize Maximum size of a log file before rotating.
+ * @param pOutputIf The optional file output interface, can be NULL which will
+ * make use of the default one.
+ * @param pvOutputIfUser The opaque user data to pass to the callbacks in the output interface.
+ * @param pErrInfo Where to return extended error information.
+ * Optional.
+ *
+ * @returns VBox status code.
+ *
+ * @note Can't include log.h here because of precompiled header fun, hence pOutputIf is void *...
+ */
+int VBoxLogRelCreateEx(const char *pszEntity, const char *pszLogFile,
+ uint32_t fFlags, const char *pszGroupSettings,
+ const char *pszEnvVarBase, uint32_t fDestFlags,
+ uint32_t cMaxEntriesPerGroup, uint32_t cHistory,
+ uint32_t uHistoryFileTime, uint64_t uHistoryFileSize,
+ const void *pOutputIf, void *pvOutputIfUser,
+ PRTERRINFO pErrInfo);
+
+} /* namespace com */
+
+/** @} */
+#endif /* !VBOX_INCLUDED_com_utils_h */
+
diff --git a/include/VBox/dbg.h b/include/VBox/dbg.h
new file mode 100644
index 00000000..901b72da
--- /dev/null
+++ b/include/VBox/dbg.h
@@ -0,0 +1,1222 @@
+/** @file
+ * Debugger Interfaces. (VBoxDbg)
+ *
+ * This header covers all external interfaces of the Debugger module.
+ * However, it does not cover the DBGF interface since that part of the
+ * VMM. Use dbgf.h for that.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_dbg_h
+#define VBOX_INCLUDED_dbg_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/cdefs.h>
+#include <VBox/types.h>
+#include <VBox/vmm/dbgf.h>
+
+#include <iprt/stdarg.h>
+#ifdef IN_RING3
+# include <iprt/errcore.h>
+#endif
+
+RT_C_DECLS_BEGIN
+
+
+
+/** @defgroup grp_dbg The VirtualBox Debugger
+ * @{
+ */
+
+#ifdef IN_RING3 /* The debugger stuff is ring-3 only. */
+
+/** @defgroup grp_dbgc The Debugger Console API
+ * @{
+ */
+
+/** @def VBOX_WITH_DEBUGGER
+ * The build is with debugger module. Test if this is defined before registering
+ * external debugger commands. This is normally defined in Config.kmk.
+ */
+#ifdef DOXYGEN_RUNNING
+# define VBOX_WITH_DEBUGGER
+#endif
+
+
+/**
+ * DBGC variable category.
+ *
+ * Used to describe an argument to a command or function and a functions
+ * return value.
+ */
+typedef enum DBGCVARCAT
+{
+ /** Any type is fine. */
+ DBGCVAR_CAT_ANY = 0,
+ /** Any kind of pointer or number. */
+ DBGCVAR_CAT_POINTER_NUMBER,
+ /** Any kind of pointer or number, no range. */
+ DBGCVAR_CAT_POINTER_NUMBER_NO_RANGE,
+ /** Any kind of pointer. */
+ DBGCVAR_CAT_POINTER,
+ /** Any kind of pointer with no range option. */
+ DBGCVAR_CAT_POINTER_NO_RANGE,
+ /** GC pointer. */
+ DBGCVAR_CAT_GC_POINTER,
+ /** GC pointer with no range option. */
+ DBGCVAR_CAT_GC_POINTER_NO_RANGE,
+ /** Numeric argument. */
+ DBGCVAR_CAT_NUMBER,
+ /** Numeric argument with no range option. */
+ DBGCVAR_CAT_NUMBER_NO_RANGE,
+ /** String. */
+ DBGCVAR_CAT_STRING,
+ /** Symbol. */
+ DBGCVAR_CAT_SYMBOL,
+ /** Option. */
+ DBGCVAR_CAT_OPTION,
+ /** Option + string. */
+ DBGCVAR_CAT_OPTION_STRING,
+ /** Option + number. */
+ DBGCVAR_CAT_OPTION_NUMBER
+} DBGCVARCAT;
+
+
+/**
+ * DBGC variable type.
+ */
+typedef enum DBGCVARTYPE
+{
+ /** unknown... */
+ DBGCVAR_TYPE_UNKNOWN = 0,
+ /** Flat GC pointer. */
+ DBGCVAR_TYPE_GC_FLAT,
+ /** Segmented GC pointer. */
+ DBGCVAR_TYPE_GC_FAR,
+ /** Physical GC pointer. */
+ DBGCVAR_TYPE_GC_PHYS,
+ /** Flat HC pointer. */
+ DBGCVAR_TYPE_HC_FLAT,
+ /** Physical HC pointer. */
+ DBGCVAR_TYPE_HC_PHYS,
+ /** Number. */
+ DBGCVAR_TYPE_NUMBER,
+ /** String. */
+ DBGCVAR_TYPE_STRING,
+ /** Symbol. */
+ DBGCVAR_TYPE_SYMBOL,
+ /** Special type used when querying symbols. */
+ DBGCVAR_TYPE_ANY
+} DBGCVARTYPE;
+
+/** @todo Rename to DBGCVAR_IS_xyz. */
+
+/** Checks if the specified variable type is of a pointer persuasion. */
+#define DBGCVAR_ISPOINTER(enmType) ((enmType) >= DBGCVAR_TYPE_GC_FLAT && enmType <= DBGCVAR_TYPE_HC_PHYS)
+/** Checks if the specified variable type is of a pointer persuasion. */
+#define DBGCVAR_IS_FAR_PTR(enmType) ((enmType) == DBGCVAR_TYPE_GC_FAR)
+/** Checks if the specified variable type is of a pointer persuasion and of the guest context sort. */
+#define DBGCVAR_ISGCPOINTER(enmType) ((enmType) >= DBGCVAR_TYPE_GC_FLAT && (enmType) <= DBGCVAR_TYPE_GC_PHYS)
+/** Checks if the specified variable type is of a pointer persuasion and of the host context sort. */
+#define DBGCVAR_ISHCPOINTER(enmType) ((enmType) >= DBGCVAR_TYPE_HC_FLAT && (enmType) <= DBGCVAR_TYPE_HC_PHYS)
+
+
+/**
+ * DBGC variable range type.
+ */
+typedef enum DBGCVARRANGETYPE
+{
+ /** No range appliable or no range specified. */
+ DBGCVAR_RANGE_NONE = 0,
+ /** Number of elements. */
+ DBGCVAR_RANGE_ELEMENTS,
+ /** Number of bytes. */
+ DBGCVAR_RANGE_BYTES
+} DBGCVARRANGETYPE;
+
+
+/**
+ * Variable descriptor.
+ */
+typedef struct DBGCVARDESC
+{
+ /** The minimal number of times this argument may occur.
+ * Use 0 here to inidicate that the argument is optional. */
+ unsigned cTimesMin;
+ /** Maximum number of occurrences.
+ * Use ~0 here to indicate infinite. */
+ unsigned cTimesMax;
+ /** Argument category. */
+ DBGCVARCAT enmCategory;
+ /** Flags, DBGCVD_FLAGS_* */
+ unsigned fFlags;
+ /** Argument name. */
+ const char *pszName;
+ /** Argument name. */
+ const char *pszDescription;
+} DBGCVARDESC;
+/** Pointer to an argument descriptor. */
+typedef DBGCVARDESC *PDBGCVARDESC;
+/** Pointer to a const argument descriptor. */
+typedef const DBGCVARDESC *PCDBGCVARDESC;
+
+/** Variable descriptor flags.
+ * @{ */
+/** Indicates that the variable depends on the previous being present. */
+#define DBGCVD_FLAGS_DEP_PREV RT_BIT(1)
+/** @} */
+
+
+/**
+ * DBGC variable.
+ */
+typedef struct DBGCVAR
+{
+ /** Pointer to the argument descriptor. */
+ PCDBGCVARDESC pDesc;
+ /** Pointer to the next argument. */
+ struct DBGCVAR *pNext;
+
+ /** Argument type. */
+ DBGCVARTYPE enmType;
+ /** Type specific. */
+ union
+ {
+ /** Flat GC Address. (DBGCVAR_TYPE_GC_FLAT) */
+ RTGCPTR GCFlat;
+ /** Far (16:32) GC Address. (DBGCVAR_TYPE_GC_FAR) */
+ RTFAR32 GCFar;
+ /** Physical GC Address. (DBGCVAR_TYPE_GC_PHYS) */
+ RTGCPHYS GCPhys;
+ /** Flat HC Address. (DBGCVAR_TYPE_HC_FLAT) */
+ void *pvHCFlat;
+ /** Physical GC Address. (DBGCVAR_TYPE_HC_PHYS) */
+ RTHCPHYS HCPhys;
+ /** String. (DBGCVAR_TYPE_STRING)
+ * The basic idea is the the this is a pointer to the expression we're
+ * parsing, so no messing with freeing. */
+ const char *pszString;
+ /** Number. (DBGCVAR_TYPE_NUMBER) */
+ uint64_t u64Number;
+ } u;
+
+ /** Range type. */
+ DBGCVARRANGETYPE enmRangeType;
+ /** Range. The use of the content depends on the enmRangeType. */
+ uint64_t u64Range;
+} DBGCVAR;
+/** Pointer to a command argument. */
+typedef DBGCVAR *PDBGCVAR;
+/** Pointer to a const command argument. */
+typedef const DBGCVAR *PCDBGCVAR;
+
+
+/**
+ * Macro for initializing a DBGC variable with defaults.
+ * The result is an unknown variable type without any range.
+ */
+#define DBGCVAR_INIT(pVar) \
+ do { \
+ (pVar)->pDesc = NULL;\
+ (pVar)->pNext = NULL; \
+ (pVar)->enmType = DBGCVAR_TYPE_UNKNOWN; \
+ (pVar)->u.u64Number = 0; \
+ (pVar)->enmRangeType = DBGCVAR_RANGE_NONE; \
+ (pVar)->u64Range = 0; \
+ } while (0)
+
+/**
+ * Macro for initializing a DBGC variable with a HC physical address.
+ */
+#define DBGCVAR_INIT_HC_PHYS(pVar, Phys) \
+ do { \
+ DBGCVAR_INIT(pVar); \
+ (pVar)->enmType = DBGCVAR_TYPE_HC_PHYS; \
+ (pVar)->u.HCPhys = (Phys); \
+ } while (0)
+
+/**
+ * Macro for initializing a DBGC variable with a HC flat address.
+ */
+#define DBGCVAR_INIT_HC_FLAT(pVar, Flat) \
+ do { \
+ DBGCVAR_INIT(pVar); \
+ (pVar)->enmType = DBGCVAR_TYPE_HC_FLAT; \
+ (pVar)->u.pvHCFlat = (Flat); \
+ } while (0)
+
+/**
+ * Macro for initializing a DBGC variable with a GC physical address.
+ */
+#define DBGCVAR_INIT_GC_PHYS(pVar, Phys) \
+ do { \
+ DBGCVAR_INIT(pVar); \
+ (pVar)->enmType = DBGCVAR_TYPE_GC_PHYS; \
+ (pVar)->u.GCPhys = (Phys); \
+ } while (0)
+
+/**
+ * Macro for initializing a DBGC variable with a GC flat address.
+ */
+#define DBGCVAR_INIT_GC_FLAT(pVar, Flat) \
+ do { \
+ DBGCVAR_INIT(pVar); \
+ (pVar)->enmType = DBGCVAR_TYPE_GC_FLAT; \
+ (pVar)->u.GCFlat = (Flat); \
+ } while (0)
+
+/**
+ * Macro for initializing a DBGC variable with a GC flat address.
+ */
+#define DBGCVAR_INIT_GC_FLAT_BYTE_RANGE(pVar, Flat, cbRange) \
+ do { \
+ DBGCVAR_INIT(pVar); \
+ (pVar)->enmType = DBGCVAR_TYPE_GC_FLAT; \
+ (pVar)->u.GCFlat = (Flat); \
+ DBGCVAR_SET_RANGE(pVar, DBGCVAR_RANGE_BYTES, cbRange); \
+ } while (0)
+
+/**
+ * Macro for initializing a DBGC variable with a GC far address.
+ */
+#define DBGCVAR_INIT_GC_FAR(pVar, _sel, _off) \
+ do { \
+ DBGCVAR_INIT(pVar); \
+ (pVar)->enmType = DBGCVAR_TYPE_GC_FAR; \
+ (pVar)->u.GCFar.sel = (_sel); \
+ (pVar)->u.GCFar.off = (_off); \
+ } while (0)
+
+/**
+ * Macro for initializing a DBGC variable with a number.
+ */
+#define DBGCVAR_INIT_NUMBER(pVar, Value) \
+ do { \
+ DBGCVAR_INIT(pVar); \
+ (pVar)->enmType = DBGCVAR_TYPE_NUMBER; \
+ (pVar)->u.u64Number = (Value); \
+ } while (0)
+
+/**
+ * Macro for initializing a DBGC variable with a string.
+ */
+#define DBGCVAR_INIT_STRING(pVar, a_pszString) \
+ do { \
+ DBGCVAR_INIT(pVar); \
+ (pVar)->enmType = DBGCVAR_TYPE_STRING; \
+ (pVar)->enmRangeType = DBGCVAR_RANGE_BYTES; \
+ (pVar)->u.pszString = (a_pszString); \
+ (pVar)->u64Range = strlen(a_pszString); \
+ } while (0)
+
+
+/**
+ * Macro for initializing a DBGC variable with a symbol.
+ */
+#define DBGCVAR_INIT_SYMBOL(pVar, a_pszSymbol) \
+ do { \
+ DBGCVAR_INIT(pVar); \
+ (pVar)->enmType = DBGCVAR_TYPE_SYMBOL; \
+ (pVar)->enmRangeType = DBGCVAR_RANGE_BYTES; \
+ (pVar)->u.pszString = (a_pszSymbol); \
+ (pVar)->u64Range = strlen(a_pszSymbol); \
+ } while (0)
+
+
+/**
+ * Macro for setting the range of a DBGC variable.
+ * @param pVar The variable.
+ * @param _enmRangeType The range type.
+ * @param Value The range length value.
+ */
+#define DBGCVAR_SET_RANGE(pVar, _enmRangeType, Value) \
+ do { \
+ (pVar)->enmRangeType = (_enmRangeType); \
+ (pVar)->u64Range = (Value); \
+ } while (0)
+
+
+/**
+ * Macro for setting the range of a DBGC variable.
+ * @param a_pVar The variable.
+ * @param a_cbRange The range, in bytes.
+ */
+#define DBGCVAR_SET_BYTE_RANGE(a_pVar, a_cbRange) \
+ DBGCVAR_SET_RANGE(a_pVar, DBGCVAR_RANGE_BYTES, a_cbRange)
+
+
+/**
+ * Macro for resetting the range a DBGC variable.
+ * @param a_pVar The variable.
+ */
+#define DBGCVAR_ZAP_RANGE(a_pVar) \
+ do { \
+ (a_pVar)->enmRangeType = DBGCVAR_RANGE_NONE; \
+ (a_pVar)->u64Range = 0; \
+ } while (0)
+
+
+/**
+ * Macro for assigning one DBGC variable to another.
+ * @param a_pResult The result (target) variable.
+ * @param a_pVar The source variable.
+ */
+#define DBGCVAR_ASSIGN(a_pResult, a_pVar) \
+ do { \
+ *(a_pResult) = *(a_pVar); \
+ } while (0)
+
+
+/** Pointer to a command descriptor. */
+typedef struct DBGCCMD *PDBGCCMD;
+/** Pointer to a const command descriptor. */
+typedef const struct DBGCCMD *PCDBGCCMD;
+
+/** Pointer to a function descriptor. */
+typedef struct DBGCFUNC *PDBGCFUNC;
+/** Pointer to a const function descriptor. */
+typedef const struct DBGCFUNC *PCDBGCFUNC;
+
+/** Pointer to helper functions for commands. */
+typedef struct DBGCCMDHLP *PDBGCCMDHLP;
+
+
+/**
+ * Helper functions for commands.
+ */
+typedef struct DBGCCMDHLP
+{
+ /** Magic value (DBGCCMDHLP_MAGIC). */
+ uint32_t u32Magic;
+
+ /**
+ * Command helper for writing formatted text to the debug console.
+ *
+ * @returns VBox status.
+ * @param pCmdHlp Pointer to the command callback structure.
+ * @param pcbWritten Where to store the number of bytes written.
+ * This is optional.
+ * @param pszFormat The format string. This may use all IPRT extensions as
+ * well as the debugger ones.
+ * @param ... Arguments specified in the format string.
+ */
+ DECLCALLBACKMEMBER(int, pfnPrintf,(PDBGCCMDHLP pCmdHlp, size_t *pcbWritten,
+ const char *pszFormat, ...)) RT_IPRT_FORMAT_ATTR(3, 4);
+
+ /**
+ * Command helper for writing formatted text to the debug console.
+ *
+ * @returns VBox status.
+ * @param pCmdHlp Pointer to the command callback structure.
+ * @param pcbWritten Where to store the number of bytes written.
+ * This is optional.
+ * @param pszFormat The format string. This may use all IPRT extensions as
+ * well as the debugger ones.
+ * @param args Arguments specified in the format string.
+ */
+ DECLCALLBACKMEMBER(int, pfnPrintfV,(PDBGCCMDHLP pCmdHlp, size_t *pcbWritten,
+ const char *pszFormat, va_list args)) RT_IPRT_FORMAT_ATTR(3, 0);
+
+ /**
+ * Command helper for formatting a string with debugger format specifiers.
+ *
+ * @returns The number of bytes written.
+ * @param pCmdHlp Pointer to the command callback structure.
+ * @param pszBuf The output buffer.
+ * @param cbBuf The size of the output buffer.
+ * @param pszFormat The format string. This may use all IPRT extensions as
+ * well as the debugger ones.
+ * @param ... Arguments specified in the format string.
+ */
+ DECLCALLBACKMEMBER(size_t, pfnStrPrintf,(PDBGCCMDHLP pCmdHlp, char *pszBuf, size_t cbBuf,
+ const char *pszFormat, ...)) RT_IPRT_FORMAT_ATTR(4, 5);
+
+ /**
+ * Command helper for formatting a string with debugger format specifiers.
+ *
+ * @returns The number of bytes written.
+ * @param pCmdHlp Pointer to the command callback structure.
+ * @param pszBuf The output buffer.
+ * @param cbBuf The size of the output buffer.
+ * @param pszFormat The format string. This may use all IPRT extensions as
+ * well as the debugger ones.
+ * @param va Arguments specified in the format string.
+ */
+ DECLCALLBACKMEMBER(size_t, pfnStrPrintfV,(PDBGCCMDHLP pCmdHlp, char *pszBuf, size_t cbBuf,
+ const char *pszFormat, va_list va)) RT_IPRT_FORMAT_ATTR(4, 0);
+
+ /**
+ * Command helper for formatting and error message for a VBox status code.
+ *
+ * @returns VBox status code appropriate to return from a command.
+ * @param pCmdHlp Pointer to the command callback structure.
+ * @param rc The VBox status code.
+ * @param pszFormat Format string for additional messages. Can be NULL.
+ * @param ... Format arguments, optional.
+ */
+ DECLCALLBACKMEMBER(int, pfnVBoxError,(PDBGCCMDHLP pCmdHlp, int rc, const char *pszFormat, ...)) RT_IPRT_FORMAT_ATTR(3, 4);
+
+ /**
+ * Command helper for formatting and error message for a VBox status code.
+ *
+ * @returns VBox status code appropriate to return from a command.
+ * @param pCmdHlp Pointer to the command callback structure.
+ * @param rc The VBox status code.
+ * @param pszFormat Format string for additional messages. Can be NULL.
+ * @param args Format arguments, optional.
+ */
+ DECLCALLBACKMEMBER(int, pfnVBoxErrorV,(PDBGCCMDHLP pCmdHlp, int rc,
+ const char *pszFormat, va_list args)) RT_IPRT_FORMAT_ATTR(3, 0);
+
+ /**
+ * Command helper for reading memory specified by a DBGC variable.
+ *
+ * @returns VBox status code appropriate to return from a command.
+ * @param pCmdHlp Pointer to the command callback structure.
+ * @param pvBuffer Where to store the read data.
+ * @param cbRead Number of bytes to read.
+ * @param pVarPointer DBGC variable specifying where to start reading.
+ * @param pcbRead Where to store the number of bytes actually read.
+ * This optional, but it's useful when read GC virtual memory where a
+ * page in the requested range might not be present.
+ * If not specified not-present failure or end of a HC physical page
+ * will cause failure.
+ */
+ DECLCALLBACKMEMBER(int, pfnMemRead,(PDBGCCMDHLP pCmdHlp, void *pvBuffer, size_t cbRead, PCDBGCVAR pVarPointer, size_t *pcbRead));
+
+ /**
+ * Command helper for writing memory specified by a DBGC variable.
+ *
+ * @returns VBox status code appropriate to return from a command.
+ * @param pCmdHlp Pointer to the command callback structure.
+ * @param pvBuffer What to write.
+ * @param cbWrite Number of bytes to write.
+ * @param pVarPointer DBGC variable specifying where to start reading.
+ * @param pcbWritten Where to store the number of bytes written.
+ * This is optional. If NULL be aware that some of the buffer
+ * might have been written to the specified address.
+ */
+ DECLCALLBACKMEMBER(int, pfnMemWrite,(PDBGCCMDHLP pCmdHlp, const void *pvBuffer, size_t cbWrite, PCDBGCVAR pVarPointer, size_t *pcbWritten));
+
+ /**
+ * Executes command an expression.
+ * (Hopefully the parser and functions are fully reentrant.)
+ *
+ * @returns VBox status code appropriate to return from a command.
+ * @param pCmdHlp Pointer to the command callback structure.
+ * @param pszExpr The expression. Format string with the format DBGC extensions.
+ * @param ... Format arguments.
+ */
+ DECLCALLBACKMEMBER(int, pfnExec,(PDBGCCMDHLP pCmdHlp, const char *pszExpr, ...)) RT_IPRT_FORMAT_ATTR(2, 3);
+
+ /**
+ * Evaluates an expression.
+ * (Hopefully the parser and functions are fully reentrant.)
+ *
+ * @returns VBox status code appropriate to return from a command.
+ * @param pCmdHlp Pointer to the command callback structure.
+ * @param pResult Where to store the result.
+ * @param pszExpr The expression. Format string with the format DBGC extensions.
+ * @param va Format arguments.
+ */
+ DECLCALLBACKMEMBER(int, pfnEvalV,(PDBGCCMDHLP pCmdHlp, PDBGCVAR pResult,
+ const char *pszExpr, va_list va)) RT_IPRT_FORMAT_ATTR(3, 0);
+
+ /**
+ * Print an error and fail the current command.
+ *
+ * @returns VBox status code to pass upwards.
+ *
+ * @param pCmdHlp Pointer to the command callback structure.
+ * @param pCmd The failing command.
+ * @param pszFormat The error message format string.
+ * @param va Format arguments.
+ */
+ DECLCALLBACKMEMBER(int, pfnFailV,(PDBGCCMDHLP pCmdHlp, PCDBGCCMD pCmd,
+ const char *pszFormat, va_list va)) RT_IPRT_FORMAT_ATTR(3, 0);
+
+ /**
+ * Print an error and fail the current command.
+ *
+ * @returns VBox status code to pass upwards.
+ *
+ * @param pCmdHlp Pointer to the command callback structure.
+ * @param pCmd The failing command.
+ * @param rc The status code indicating the failure. This will
+ * be appended to the message after a colon (': ').
+ * @param pszFormat The error message format string.
+ * @param va Format arguments.
+ *
+ * @see DBGCCmdHlpFailRc
+ */
+ DECLCALLBACKMEMBER(int, pfnFailRcV,(PDBGCCMDHLP pCmdHlp, PCDBGCCMD pCmd, int rc,
+ const char *pszFormat, va_list va)) RT_IPRT_FORMAT_ATTR(4, 0);
+
+ /**
+ * Parser error.
+ *
+ * @returns VBox status code to pass upwards.
+ *
+ * @param pCmdHlp Pointer to the command callback structure.
+ * @param pCmd The failing command, can be NULL but shouldn't.
+ * @param iArg The offending argument, -1 when lazy.
+ * @param pszExpr The expression.
+ * @param iLine The line number.
+ */
+ DECLCALLBACKMEMBER(int, pfnParserError,(PDBGCCMDHLP pCmdHlp, PCDBGCCMD pCmd, int iArg, const char *pszExpr, unsigned iLine));
+
+ /**
+ * Converts a DBGC variable to a DBGF address structure.
+ *
+ * @returns VBox status code.
+ * @param pCmdHlp Pointer to the command callback structure.
+ * @param pVar The variable to convert.
+ * @param pAddress The target address.
+ */
+ DECLCALLBACKMEMBER(int, pfnVarToDbgfAddr,(PDBGCCMDHLP pCmdHlp, PCDBGCVAR pVar, PDBGFADDRESS pAddress));
+
+ /**
+ * Converts a DBGF address structure to a DBGC variable.
+ *
+ * @returns VBox status code.
+ * @param pCmdHlp Pointer to the command callback structure.
+ * @param pAddress The source address.
+ * @param pResult The result variable.
+ */
+ DECLCALLBACKMEMBER(int, pfnVarFromDbgfAddr,(PDBGCCMDHLP pCmdHlp, PCDBGFADDRESS pAddress, PDBGCVAR pResult));
+
+ /**
+ * Converts a DBGC variable to a 64-bit number.
+ *
+ * @returns VBox status code.
+ * @param pCmdHlp Pointer to the command callback structure.
+ * @param pVar The variable to convert.
+ * @param pu64Number Where to store the number.
+ */
+ DECLCALLBACKMEMBER(int, pfnVarToNumber,(PDBGCCMDHLP pCmdHlp, PCDBGCVAR pVar, uint64_t *pu64Number));
+
+ /**
+ * Converts a DBGC variable to a boolean.
+ *
+ * @returns VBox status code.
+ * @param pCmdHlp Pointer to the command callback structure.
+ * @param pVar The variable to convert.
+ * @param pf Where to store the boolean.
+ */
+ DECLCALLBACKMEMBER(int, pfnVarToBool,(PDBGCCMDHLP pCmdHlp, PCDBGCVAR pVar, bool *pf));
+
+ /**
+ * Get the range of a variable in bytes, resolving symbols if necessary.
+ *
+ * @returns VBox status code.
+ * @param pCmdHlp Pointer to the command callback structure.
+ * @param pVar The variable to convert.
+ * @param cbElement Conversion factor for element ranges.
+ * @param cbDefault The default range.
+ * @param pcbRange The length of the range.
+ */
+ DECLCALLBACKMEMBER(int, pfnVarGetRange,(PDBGCCMDHLP pCmdHlp, PCDBGCVAR pVar, uint64_t cbElement, uint64_t cbDefault,
+ uint64_t *pcbRange));
+
+ /**
+ * Converts a variable to one with the specified type.
+ *
+ * This preserves the range.
+ *
+ * @returns VBox status code.
+ * @param pCmdHlp Pointer to the command callback structure.
+ * @param pVar The variable to convert.
+ * @param enmToType The target type.
+ * @param fConvSyms If @c true, then attempt to resolve symbols.
+ * @param pResult The output variable. Can be the same as @a pVar.
+ */
+ DECLCALLBACKMEMBER(int, pfnVarConvert,(PDBGCCMDHLP pCmdHlp, PCDBGCVAR pVar, DBGCVARTYPE enmToType, bool fConvSyms,
+ PDBGCVAR pResult));
+
+ /**
+ * Gets a DBGF output helper that directs the output to the debugger
+ * console.
+ *
+ * @returns Pointer to the helper structure.
+ * @param pCmdHlp Pointer to the command callback structure.
+ */
+ DECLCALLBACKMEMBER(PCDBGFINFOHLP, pfnGetDbgfOutputHlp,(PDBGCCMDHLP pCmdHlp));
+
+ /**
+ * Gets the ID currently selected CPU.
+ *
+ * @returns Current CPU ID.
+ * @param pCmdHlp Pointer to the command callback structure.
+ */
+ DECLCALLBACKMEMBER(VMCPUID, pfnGetCurrentCpu,(PDBGCCMDHLP pCmdHlp));
+
+ /**
+ * Gets the mode the currently selected CPU is running in, in the current
+ * context.
+ *
+ * @returns Current CPU mode.
+ * @param pCmdHlp Pointer to the command callback structure.
+ */
+ DECLCALLBACKMEMBER(CPUMMODE, pfnGetCpuMode,(PDBGCCMDHLP pCmdHlp));
+
+ /**
+ * Prints the register set of the given CPU.
+ *
+ * @returns VBox status code.
+ * @param pCmdHlp Pointer to the command callback structure.
+ * @param idCpu The CPU ID to print the register set of.
+ * @param f64BitMode True to dump 64-bit state, false to dump 32-bit state,
+ * -1 to use the current CPU mode.
+ * @param fTerse Flag to indicate whether to dump the complete register set.
+ */
+ DECLCALLBACKMEMBER(int, pfnRegPrintf, (PDBGCCMDHLP pCmdHlp, VMCPUID idCpu, int f64BitMode, bool fTerse));
+
+ /** End marker (DBGCCMDHLP_MAGIC). */
+ uint32_t u32EndMarker;
+} DBGCCMDHLP;
+
+/** Magic value for DBGCCMDHLP::u32Magic. (Fyodor Mikhaylovich Dostoyevsky) */
+#define DBGCCMDHLP_MAGIC UINT32_C(18211111)
+
+
+#if defined(IN_RING3) || defined(IN_SLICKEDIT)
+
+/**
+ * Command helper for writing formatted text to the debug console.
+ *
+ * @returns VBox status.
+ * @param pCmdHlp Pointer to the command callback structure.
+ * @param pszFormat The format string. This may use all IPRT extensions as
+ * well as the debugger ones.
+ * @param ... Arguments specified in the format string.
+ */
+DECLINLINE(int) RT_IPRT_FORMAT_ATTR(2, 3) DBGCCmdHlpPrintf(PDBGCCMDHLP pCmdHlp, const char *pszFormat, ...)
+{
+ va_list va;
+ int rc;
+
+ va_start(va, pszFormat);
+ rc = pCmdHlp->pfnPrintfV(pCmdHlp, NULL, pszFormat, va);
+ va_end(va);
+
+ return rc;
+}
+
+/**
+ * Command helper for writing formatted text to the debug console.
+ *
+ * @returns VBox status.
+ * @param pCmdHlp Pointer to the command callback structure.
+ * @param pcbWritten Where to store the amount of written characters on success.
+ * @param pszFormat The format string. This may use all IPRT extensions as
+ * well as the debugger ones.
+ * @param ... Arguments specified in the format string.
+ */
+DECLINLINE(int) RT_IPRT_FORMAT_ATTR(3, 4) DBGCCmdHlpPrintfEx(PDBGCCMDHLP pCmdHlp, size_t *pcbWritten,
+ const char *pszFormat, ...)
+{
+ va_list va;
+ int rc;
+
+ va_start(va, pszFormat);
+ rc = pCmdHlp->pfnPrintfV(pCmdHlp, pcbWritten, pszFormat, va);
+ va_end(va);
+
+ return rc;
+}
+
+/**
+ * Command helper for writing formatted text to the debug console.
+ *
+ * @returns Number of bytes written.
+ * @param pCmdHlp Pointer to the command callback structure.
+ * @param pszFormat The format string. This may use all IPRT extensions as
+ * well as the debugger ones.
+ * @param ... Arguments specified in the format string.
+ */
+DECLINLINE(size_t) RT_IPRT_FORMAT_ATTR(2, 3) DBGCCmdHlpPrintfLen(PDBGCCMDHLP pCmdHlp, const char *pszFormat, ...)
+{
+ va_list va;
+ int rc;
+ size_t cbWritten = 0;
+
+ va_start(va, pszFormat);
+ rc = pCmdHlp->pfnPrintfV(pCmdHlp, &cbWritten, pszFormat, va);
+ va_end(va);
+
+ return RT_SUCCESS(rc) ? cbWritten : 0;
+}
+
+/**
+ * @copydoc DBGCCMDHLP::pfnStrPrintf
+ */
+DECLINLINE(size_t) RT_IPRT_FORMAT_ATTR(4, 5) DBGCCmdHlpStrPrintf(PDBGCCMDHLP pCmdHlp, char *pszBuf, size_t cbBuf,
+ const char *pszFormat, ...)
+{
+ va_list va;
+ size_t cch;
+
+ va_start(va, pszFormat);
+ cch = pCmdHlp->pfnStrPrintfV(pCmdHlp, pszBuf, cbBuf, pszFormat, va);
+ va_end(va);
+
+ return cch;
+}
+
+/**
+ * @copydoc DBGCCMDHLP::pfnVBoxError
+ */
+DECLINLINE(int) RT_IPRT_FORMAT_ATTR(3, 4) DBGCCmdHlpVBoxError(PDBGCCMDHLP pCmdHlp, int rc, const char *pszFormat, ...)
+{
+ va_list va;
+
+ va_start(va, pszFormat);
+ rc = pCmdHlp->pfnVBoxErrorV(pCmdHlp, rc, pszFormat, va);
+ va_end(va);
+
+ return rc;
+}
+
+/**
+ * @copydoc DBGCCMDHLP::pfnMemRead
+ */
+DECLINLINE(int) DBGCCmdHlpMemRead(PDBGCCMDHLP pCmdHlp, void *pvBuffer, size_t cbRead, PCDBGCVAR pVarPointer, size_t *pcbRead)
+{
+ return pCmdHlp->pfnMemRead(pCmdHlp, pvBuffer, cbRead, pVarPointer, pcbRead);
+}
+
+/**
+ * Evaluates an expression.
+ * (Hopefully the parser and functions are fully reentrant.)
+ *
+ * @returns VBox status code appropriate to return from a command.
+ * @param pCmdHlp Pointer to the command callback structure.
+ * @param pResult Where to store the result.
+ * @param pszExpr The expression. Format string with the format DBGC extensions.
+ * @param ... Format arguments.
+ */
+DECLINLINE(int) RT_IPRT_FORMAT_ATTR(3, 4) DBGCCmdHlpEval(PDBGCCMDHLP pCmdHlp, PDBGCVAR pResult, const char *pszExpr, ...)
+{
+ va_list va;
+ int rc;
+
+ va_start(va, pszExpr);
+ rc = pCmdHlp->pfnEvalV(pCmdHlp, pResult, pszExpr, va);
+ va_end(va);
+
+ return rc;
+}
+
+/**
+ * Print an error and fail the current command.
+ *
+ * @returns VBox status code to pass upwards.
+ *
+ * @param pCmdHlp Pointer to the command callback structure.
+ * @param pCmd The failing command.
+ * @param pszFormat The error message format string.
+ * @param ... Format arguments.
+ */
+DECLINLINE(int) RT_IPRT_FORMAT_ATTR(3, 4) DBGCCmdHlpFail(PDBGCCMDHLP pCmdHlp, PCDBGCCMD pCmd, const char *pszFormat, ...)
+{
+ va_list va;
+ int rc;
+
+ va_start(va, pszFormat);
+ rc = pCmdHlp->pfnFailV(pCmdHlp, pCmd, pszFormat, va);
+ va_end(va);
+
+ return rc;
+}
+
+/**
+ * Print an error and fail the current command.
+ *
+ * Usage example:
+ * @code
+ int rc = VMMR3Something(pVM);
+ if (RT_FAILURE(rc))
+ return DBGCCmdHlpFailRc(pCmdHlp, pCmd, rc, "VMMR3Something");
+ return VINF_SUCCESS;
+ * @endcode
+ *
+ * @returns VBox status code to pass upwards.
+ *
+ * @param pCmdHlp Pointer to the command callback structure.
+ * @param pCmd The failing command.
+ * @param rc The status code indicating the failure.
+ * @param pszFormat The error message format string.
+ * @param ... Format arguments.
+ */
+DECLINLINE(int) RT_IPRT_FORMAT_ATTR(4, 5) DBGCCmdHlpFailRc(PDBGCCMDHLP pCmdHlp, PCDBGCCMD pCmd, int rc,
+ const char *pszFormat, ...)
+{
+ va_list va;
+
+ va_start(va, pszFormat);
+ rc = pCmdHlp->pfnFailRcV(pCmdHlp, pCmd, rc, pszFormat, va);
+ va_end(va);
+
+ return rc;
+}
+
+/**
+ * @copydoc DBGCCMDHLP::pfnParserError
+ */
+DECLINLINE(int) DBGCCmdHlpParserError(PDBGCCMDHLP pCmdHlp, PCDBGCCMD pCmd, int iArg, const char *pszExpr, unsigned iLine)
+{
+ return pCmdHlp->pfnParserError(pCmdHlp, pCmd, iArg, pszExpr, iLine);
+}
+
+/** Assert+return like macro for checking parser sanity.
+ * Returns with failure if the precodition is not met. */
+#define DBGC_CMDHLP_ASSERT_PARSER_RET(pCmdHlp, pCmd, iArg, expr) \
+ do { \
+ if (!(expr)) \
+ return DBGCCmdHlpParserError(pCmdHlp, pCmd, iArg, #expr, __LINE__); \
+ } while (0)
+
+/** Assert+return like macro that the VM handle is present.
+ * Returns with failure if the VM handle is NIL. */
+#define DBGC_CMDHLP_REQ_UVM_RET(pCmdHlp, pCmd, pUVM) \
+ do { \
+ if (!(pUVM)) \
+ return DBGCCmdHlpFail(pCmdHlp, pCmd, "No VM selected"); \
+ } while (0)
+
+/**
+ * @copydoc DBGCCMDHLP::pfnVarToDbgfAddr
+ */
+DECLINLINE(int) DBGCCmdHlpVarToDbgfAddr(PDBGCCMDHLP pCmdHlp, PCDBGCVAR pVar, PDBGFADDRESS pAddress)
+{
+ return pCmdHlp->pfnVarToDbgfAddr(pCmdHlp, pVar, pAddress);
+}
+
+/**
+ * @copydoc DBGCCMDHLP::pfnVarFromDbgfAddr
+ */
+DECLINLINE(int) DBGCCmdHlpVarFromDbgfAddr(PDBGCCMDHLP pCmdHlp, PCDBGFADDRESS pAddress, PDBGCVAR pResult)
+{
+ return pCmdHlp->pfnVarFromDbgfAddr(pCmdHlp, pAddress, pResult);
+}
+
+/**
+ * Converts an variable to a flat address.
+ *
+ * @returns VBox status code.
+ * @param pCmdHlp Pointer to the command callback structure.
+ * @param pVar The variable to convert.
+ * @param pFlatPtr Where to store the flat address.
+ */
+DECLINLINE(int) DBGCCmdHlpVarToFlatAddr(PDBGCCMDHLP pCmdHlp, PCDBGCVAR pVar, PRTGCPTR pFlatPtr)
+{
+ DBGFADDRESS Addr;
+ int rc = pCmdHlp->pfnVarToDbgfAddr(pCmdHlp, pVar, &Addr);
+ if (RT_SUCCESS(rc))
+ *pFlatPtr = Addr.FlatPtr;
+ return rc;
+}
+
+/**
+ * @copydoc DBGCCMDHLP::pfnVarToNumber
+ */
+DECLINLINE(int) DBGCCmdHlpVarToNumber(PDBGCCMDHLP pCmdHlp, PCDBGCVAR pVar, uint64_t *pu64Number)
+{
+ return pCmdHlp->pfnVarToNumber(pCmdHlp, pVar, pu64Number);
+}
+
+/**
+ * @copydoc DBGCCMDHLP::pfnVarToBool
+ */
+DECLINLINE(int) DBGCCmdHlpVarToBool(PDBGCCMDHLP pCmdHlp, PCDBGCVAR pVar, bool *pf)
+{
+ return pCmdHlp->pfnVarToBool(pCmdHlp, pVar, pf);
+}
+
+/**
+ * @copydoc DBGCCMDHLP::pfnVarGetRange
+ */
+DECLINLINE(int) DBGCCmdHlpVarGetRange(PDBGCCMDHLP pCmdHlp, PCDBGCVAR pVar, uint64_t cbElement, uint64_t cbDefault, uint64_t *pcbRange)
+{
+ return pCmdHlp->pfnVarGetRange(pCmdHlp, pVar, cbElement, cbDefault, pcbRange);
+}
+
+/**
+ * @copydoc DBGCCMDHLP::pfnVarConvert
+ */
+DECLINLINE(int) DBGCCmdHlpConvert(PDBGCCMDHLP pCmdHlp, PCDBGCVAR pVar, DBGCVARTYPE enmToType, bool fConvSyms, PDBGCVAR pResult)
+{
+ return pCmdHlp->pfnVarConvert(pCmdHlp, pVar, enmToType, fConvSyms, pResult);
+}
+
+/**
+ * @copydoc DBGCCMDHLP::pfnGetDbgfOutputHlp
+ */
+DECLINLINE(PCDBGFINFOHLP) DBGCCmdHlpGetDbgfOutputHlp(PDBGCCMDHLP pCmdHlp)
+{
+ return pCmdHlp->pfnGetDbgfOutputHlp(pCmdHlp);
+}
+
+/**
+ * @copydoc DBGCCMDHLP::pfnGetCurrentCpu
+ */
+DECLINLINE(VMCPUID) DBGCCmdHlpGetCurrentCpu(PDBGCCMDHLP pCmdHlp)
+{
+ return pCmdHlp->pfnGetCurrentCpu(pCmdHlp);
+}
+
+/**
+ * @copydoc DBGCCMDHLP::pfnGetCpuMode
+ */
+DECLINLINE(CPUMMODE) DBGCCmdHlpGetCpuMode(PDBGCCMDHLP pCmdHlp)
+{
+ return pCmdHlp->pfnGetCpuMode(pCmdHlp);
+}
+
+/**
+ * @copydoc DBGCCMDHLP::pfnRegPrintf
+ */
+DECLINLINE(int) DBGCCmdHlpRegPrintf(PDBGCCMDHLP pCmdHlp, VMCPUID idCpu, int f64BitMode, bool fTerse)
+{
+ return pCmdHlp->pfnRegPrintf(pCmdHlp, idCpu, f64BitMode, fTerse);
+}
+
+#endif /* IN_RING3 */
+
+
+
+/**
+ * Command handler.
+ *
+ * The console will call the handler for a command once it's finished
+ * parsing the user input. The command handler function is responsible
+ * for executing the command itself.
+ *
+ * @returns VBox status.
+ * @param pCmd Pointer to the command descriptor (as registered).
+ * @param pCmdHlp Pointer to command helper functions.
+ * @param pUVM The user mode VM handle, can in theory be NULL.
+ * @param paArgs Pointer to (readonly) array of arguments.
+ * @param cArgs Number of arguments in the array.
+ */
+typedef DECLCALLBACKTYPE(int, FNDBGCCMD,(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs));
+/** Pointer to a FNDBGCCMD() function. */
+typedef FNDBGCCMD *PFNDBGCCMD;
+
+/**
+ * DBGC command descriptor.
+ */
+typedef struct DBGCCMD
+{
+ /** Command string. */
+ const char *pszCmd;
+ /** Minimum number of arguments. */
+ unsigned cArgsMin;
+ /** Max number of arguments. */
+ unsigned cArgsMax;
+ /** Argument descriptors (array). */
+ PCDBGCVARDESC paArgDescs;
+ /** Number of argument descriptors. */
+ unsigned cArgDescs;
+ /** flags. (reserved for now) */
+ unsigned fFlags;
+ /** Handler function. */
+ PFNDBGCCMD pfnHandler;
+ /** Command syntax. */
+ const char *pszSyntax;
+ /** Command description. */
+ const char *pszDescription;
+} DBGCCMD;
+
+/** DBGCCMD Flags.
+ * @{
+ */
+/** @} */
+
+
+/**
+ * Function handler.
+ *
+ * The console will call the handler for a command once it's finished
+ * parsing the user input. The command handler function is responsible
+ * for executing the command itself.
+ *
+ * @returns VBox status.
+ * @param pFunc Pointer to the function descriptor (as registered).
+ * @param pCmdHlp Pointer to command helper functions.
+ * @param pUVM The user mode VM handle, can in theory be NULL.
+ * @param paArgs Pointer to (readonly) array of arguments.
+ * @param cArgs Number of arguments in the array.
+ * @param pResult Where to return the result.
+ */
+typedef DECLCALLBACKTYPE(int, FNDBGCFUNC,(PCDBGCFUNC pFunc, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs,
+ PDBGCVAR pResult));
+/** Pointer to a FNDBGCFUNC() function. */
+typedef FNDBGCFUNC *PFNDBGCFUNC;
+
+/**
+ * DBGC function descriptor.
+ */
+typedef struct DBGCFUNC
+{
+ /** Command string. */
+ const char *pszFuncNm;
+ /** Minimum number of arguments. */
+ unsigned cArgsMin;
+ /** Max number of arguments. */
+ unsigned cArgsMax;
+ /** Argument descriptors (array). */
+ PCDBGCVARDESC paArgDescs;
+ /** Number of argument descriptors. */
+ unsigned cArgDescs;
+ /** flags. (reserved for now) */
+ unsigned fFlags;
+ /** Handler function. */
+ PFNDBGCFUNC pfnHandler;
+ /** Function syntax. */
+ const char *pszSyntax;
+ /** Function description. */
+ const char *pszDescription;
+} DBGCFUNC;
+
+
+/** Pointer to a const I/O callback table. */
+typedef const struct DBGCIO *PCDBGCIO;
+
+/**
+ * I/O callback table.
+ */
+typedef struct DBGCIO
+{
+ /**
+ * Destroys the given I/O instance.
+ *
+ * @returns nothing.
+ * @param pIo Pointer to the I/O structure supplied by the I/O provider.
+ */
+ DECLCALLBACKMEMBER(void, pfnDestroy, (PCDBGCIO pIo));
+
+ /**
+ * Wait for input available for reading.
+ *
+ * @returns Flag whether there is input ready upon return.
+ * @retval true if there is input ready.
+ * @retval false if there not input ready.
+ * @param pIo Pointer to the I/O structure supplied by
+ * the I/O provider. The backend can use this to find it's instance data.
+ * @param cMillies Number of milliseconds to wait on input data.
+ */
+ DECLCALLBACKMEMBER(bool, pfnInput, (PCDBGCIO pIo, uint32_t cMillies));
+
+ /**
+ * Read input.
+ *
+ * @returns VBox status code.
+ * @param pIo Pointer to the I/O structure supplied by
+ * the I/O provider. The backend can use this to find it's instance data.
+ * @param pvBuf Where to put the bytes we read.
+ * @param cbBuf Maximum nymber of bytes to read.
+ * @param pcbRead Where to store the number of bytes actually read.
+ * If NULL the entire buffer must be filled for a
+ * successful return.
+ */
+ DECLCALLBACKMEMBER(int, pfnRead, (PCDBGCIO pIo, void *pvBuf, size_t cbBuf, size_t *pcbRead));
+
+ /**
+ * Write (output).
+ *
+ * @returns VBox status code.
+ * @param pIo Pointer to the I/O structure supplied by
+ * the I/O provider. The backend can use this to find it's instance data.
+ * @param pvBuf What to write.
+ * @param cbBuf Number of bytes to write.
+ * @param pcbWritten Where to store the number of bytes actually written.
+ * If NULL the entire buffer must be successfully written.
+ */
+ DECLCALLBACKMEMBER(int, pfnWrite, (PCDBGCIO pIo, const void *pvBuf, size_t cbBuf, size_t *pcbWritten));
+
+ /**
+ * Marks the beginning of a new packet being sent - optional.
+ *
+ * @returns VBox status code.
+ * @param pIo Pointer to the I/O structure supplied by
+ * the I/O provider. The backend can use this to find it's instance data.
+ * @param cbPktHint Size of the packet in bytes, serves as a hint for the I/O provider to arrange buffers.
+ * Give 0 if size is unknown upfront.
+ */
+ DECLCALLBACKMEMBER(int, pfnPktBegin, (PCDBGCIO pIo, size_t cbPktHint));
+
+ /**
+ * Marks the end of the packet - optional.
+ *
+ * @returns VBox status code.
+ * @param pIo Pointer to the I/O structure supplied by
+ * the I/O provider. The backend can use this to find it's instance data.
+ *
+ * @note Some I/O providers might decide to send data only when this is called not in the
+ * DBGCIO::pfnWrite callback.
+ */
+ DECLCALLBACKMEMBER(int, pfnPktEnd, (PCDBGCIO pIo));
+
+ /**
+ * Ready / busy notification.
+ *
+ * @returns nothing.
+ * @param pIo Pointer to the I/O structure supplied by
+ * the I/O provider. The backend can use this to find it's instance data.
+ * @param fReady Whether it's ready (true) or busy (false).
+ */
+ DECLCALLBACKMEMBER(void, pfnSetReady, (PCDBGCIO pIo, bool fReady));
+
+} DBGCIO;
+/** Pointer to an I/O callback table. */
+typedef DBGCIO *PDBGCIO;
+
+
+DBGDECL(int) DBGCCreate(PUVM pUVM, PCDBGCIO pIo, unsigned fFlags);
+DBGDECL(int) DBGCRegisterCommands(PCDBGCCMD paCommands, unsigned cCommands);
+DBGDECL(int) DBGCDeregisterCommands(PCDBGCCMD paCommands, unsigned cCommands);
+
+DBGDECL(int) DBGCIoCreate(PUVM pUVM, void **ppvData);
+DBGDECL(int) DBGCIoTerminate(PUVM pUVM, void *pvData);
+
+/** @} */
+
+#endif /* IN_RING3 */
+
+/** @} */
+RT_C_DECLS_END
+
+#endif /* !VBOX_INCLUDED_dbg_h */
diff --git a/include/VBox/dbggui.h b/include/VBox/dbggui.h
new file mode 100644
index 00000000..88c0b46d
--- /dev/null
+++ b/include/VBox/dbggui.h
@@ -0,0 +1,191 @@
+/** @file
+ * DBGGUI - The VirtualBox Debugger GUI. (VBoxDbg)
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_dbggui_h
+#define VBOX_INCLUDED_dbggui_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/types.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_dbggui VirtualBox Debugger GUI
+ * @ingroup grp_dbg
+ * @{
+ */
+
+#ifdef RT_OS_WINDOWS
+struct ISession;
+#else
+class ISession;
+#endif
+
+/** Pointer to the debugger GUI instance structure. */
+typedef struct DBGGUI *PDBGGUI;
+
+/** Virtual method table for the debugger GUI. */
+typedef struct DBGGUIVT
+{
+ /** The version. (DBGGUIVT_VERSION) */
+ uint32_t u32Version;
+ /** @copydoc DBGGuiDestroy */
+ DECLCALLBACKMEMBER(int, pfnDestroy,(PDBGGUI pGui));
+ /** @copydoc DBGGuiAdjustRelativePos */
+ DECLCALLBACKMEMBER(void, pfnAdjustRelativePos,(PDBGGUI pGui, int x, int y, unsigned cx, unsigned cy));
+ /** @copydoc DBGGuiShowStatistics */
+ DECLCALLBACKMEMBER(int, pfnShowStatistics,(PDBGGUI pGui, const char *pszFilter, const char *pszExpand));
+ /** @copydoc DBGGuiShowCommandLine */
+ DECLCALLBACKMEMBER(int, pfnShowCommandLine,(PDBGGUI pGui));
+ /** @copydoc DBGGuiSetParent */
+ DECLCALLBACKMEMBER(void, pfnSetParent,(PDBGGUI pGui, void *pvParent));
+ /** @copydoc DBGGuiSetMenu */
+ DECLCALLBACKMEMBER(void, pfnSetMenu,(PDBGGUI pGui, void *pvMenu));
+ /** The end version. (DBGGUIVT_VERSION) */
+ uint32_t u32EndVersion;
+} DBGGUIVT;
+/** Pointer to the virtual method table for the debugger GUI. */
+typedef DBGGUIVT const *PCDBGGUIVT;
+/** The u32Version value.
+ * The first byte is the minor version, the 2nd byte is major version number.
+ * The high 16-bit word is a magic. */
+#define DBGGUIVT_VERSION UINT32_C(0xbead0200)
+/** Macro for determining whether two versions are compatible or not.
+ * @returns boolean result.
+ * @param uVer1 The first version number.
+ * @param uVer2 The second version number.
+ */
+#define DBGGUIVT_ARE_VERSIONS_COMPATIBLE(uVer1, uVer2) \
+ ( ((uVer1) & UINT32_C(0xffffff00)) == ((uVer2) & UINT32_C(0xffffff00)) )
+
+
+/**
+ * Creates the debugger GUI.
+ *
+ * @returns VBox status code.
+ * @param pSession The VirtualBox session.
+ * @param ppGui Where to store the pointer to the debugger instance.
+ * @param ppGuiVT Where to store the virtual method table pointer.
+ * Optional.
+ */
+DBGDECL(int) DBGGuiCreate(ISession *pSession, PDBGGUI *ppGui, PCDBGGUIVT *ppGuiVT);
+/** @copydoc DBGGuiCreate */
+typedef DECLCALLBACKTYPE(int, FNDBGGUICREATE,(ISession *pSession, PDBGGUI *ppGui, PCDBGGUIVT *ppGuiVT));
+/** Pointer to DBGGuiCreate. */
+typedef FNDBGGUICREATE *PFNDBGGUICREATE;
+
+/**
+ * Creates the debugger GUI given a VM handle.
+ *
+ * @returns VBox status code.
+ * @param pUVM The VM handle.
+ * @param pVMM The VMM function table.
+ * @param ppGui Where to store the pointer to the debugger instance.
+ * @param ppGuiVT Where to store the virtual method table pointer.
+ * Optional.
+ */
+DBGDECL(int) DBGGuiCreateForVM(PUVM pUVM, PCVMMR3VTABLE pVMM, PDBGGUI *ppGui, PCDBGGUIVT *ppGuiVT);
+/** @copydoc DBGGuiCreateForVM */
+typedef DECLCALLBACKTYPE(int, FNDBGGUICREATEFORVM,(PUVM pUVM, PCVMMR3VTABLE pVMM, PDBGGUI *ppGui, PCDBGGUIVT *ppGuiVT));
+/** Pointer to DBGGuiCreateForVM. */
+typedef FNDBGGUICREATEFORVM *PFNDBGGUICREATEFORVM;
+
+/**
+ * Destroys the debugger GUI.
+ *
+ * @returns VBox status code.
+ * @param pGui The instance returned by DBGGuiCreate().
+ */
+DBGDECL(int) DBGGuiDestroy(PDBGGUI pGui);
+
+/**
+ * Notifies the debugger GUI that the console window (or whatever) has changed
+ * size or position.
+ *
+ * @param pGui The instance returned by DBGGuiCreate().
+ * @param x The x-coordinate of the window the debugger is relative to.
+ * @param y The y-coordinate of the window the debugger is relative to.
+ * @param cx The width of the window the debugger is relative to.
+ * @param cy The height of the window the debugger is relative to.
+ */
+DBGDECL(void) DBGGuiAdjustRelativePos(PDBGGUI pGui, int x, int y, unsigned cx, unsigned cy);
+
+/**
+ * Shows the default statistics window.
+ *
+ * @returns VBox status code.
+ * @param pGui The instance returned by DBGGuiCreate().
+ * @param pszFilter Filter pattern.
+ * @param pszExpand Expand pattern.
+ */
+DBGDECL(int) DBGGuiShowStatistics(PDBGGUI pGui, const char *pszFilter, const char *pszExpand);
+
+/**
+ * Shows the default command line window.
+ *
+ * @returns VBox status code.
+ * @param pGui The instance returned by DBGGuiCreate().
+ */
+DBGDECL(int) DBGGuiShowCommandLine(PDBGGUI pGui);
+
+/**
+ * Sets the parent windows.
+ *
+ * @param pGui The instance returned by DBGGuiCreate().
+ * @param pvParent Pointer to a QWidget object.
+ *
+ * @remarks This will no affect any existing windows, so call it right after
+ * creating the thing.
+ */
+DBGDECL(void) DBGGuiSetParent(PDBGGUI pGui, void *pvParent);
+
+/**
+ * Sets the debug menu object.
+ *
+ * @param pGui The instance returned by DBGGuiCreate().
+ * @param pvMenu Pointer to a QMenu object.
+ *
+ * @remarks Call right after creation or risk losing menu item.
+ */
+DBGDECL(void) DBGGuiSetMenu(PDBGGUI pGui, void *pvMenu);
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !VBOX_INCLUDED_dbggui_h */
+
diff --git a/include/VBox/dbus-calls.h b/include/VBox/dbus-calls.h
new file mode 100644
index 00000000..4b9cfadb
--- /dev/null
+++ b/include/VBox/dbus-calls.h
@@ -0,0 +1,180 @@
+/** @file
+ * Stubs for dynamically loading libdbus-1 and the symbols which are needed by
+ * VirtualBox.
+ */
+
+/*
+ * Copyright (C) 2008-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+/** The file name of the DBus library */
+#define RT_RUNTIME_LOADER_LIB_NAME "libdbus-1.so.3"
+
+/** The name of the loader function */
+#define RT_RUNTIME_LOADER_FUNCTION RTDBusLoadLib
+
+/** The following are the symbols which we need from the DBus library. */
+#define RT_RUNTIME_LOADER_INSERT_SYMBOLS \
+ RT_PROXY_STUB(dbus_error_init, void, (DBusError *error), \
+ (error)) \
+ RT_PROXY_STUB(dbus_error_is_set, dbus_bool_t, (const DBusError *error), \
+ (error)) \
+ RT_PROXY_STUB(dbus_bus_get, DBusConnection *, \
+ (DBusBusType type, DBusError *error), (type, error)) \
+ RT_PROXY_STUB(dbus_bus_get_private, DBusConnection *, \
+ (DBusBusType type, DBusError *error), (type, error)) \
+ RT_PROXY_STUB(dbus_error_free, void, (DBusError *error), \
+ (error)) \
+ RT_PROXY_STUB(dbus_free_string_array, void, (char **str_array), \
+ (str_array)) \
+ RT_PROXY_STUB(dbus_connection_ref, DBusConnection *, (DBusConnection *connection), \
+ (connection)) \
+ RT_PROXY_STUB(dbus_connection_unref, void, (DBusConnection *connection), \
+ (connection)) \
+ RT_PROXY_STUB(dbus_connection_close, void, (DBusConnection *connection), \
+ (connection)) \
+ RT_PROXY_STUB(dbus_connection_send, dbus_bool_t, \
+ (DBusConnection *connection, DBusMessage *message, dbus_uint32_t *serial), \
+ (connection, message, serial)) \
+ RT_PROXY_STUB(dbus_connection_flush, void, (DBusConnection *connection), \
+ (connection)) \
+ RT_PROXY_STUB(dbus_connection_set_exit_on_disconnect, void, \
+ (DBusConnection *connection, dbus_bool_t boolean), \
+ (connection, boolean)) \
+ RT_PROXY_STUB(dbus_bus_name_has_owner, dbus_bool_t, \
+ (DBusConnection *connection, const char *string, DBusError *error), \
+ (connection, string, error)) \
+ RT_PROXY_STUB(dbus_bus_add_match, void, \
+ (DBusConnection *connection, const char *string, \
+ DBusError *error), \
+ (connection, string, error)) \
+ RT_PROXY_STUB(dbus_bus_remove_match, void, \
+ (DBusConnection *connection, const char *string, \
+ DBusError *error), \
+ (connection, string, error)) \
+ RT_PROXY_STUB(dbus_message_append_args_valist, dbus_bool_t, \
+ (DBusMessage *message, int first_arg_type, va_list var_args), \
+ (message, first_arg_type, var_args)) \
+ RT_PROXY_STUB(dbus_message_get_args_valist, dbus_bool_t, \
+ (DBusMessage *message, DBusError *error, int first_arg_type, va_list var_args), \
+ (message, error, first_arg_type, var_args)) \
+ RT_PROXY_STUB(dbus_message_get_type, int, \
+ (DBusMessage *message), \
+ (message)) \
+ RT_PROXY_STUB(dbus_message_iter_open_container, dbus_bool_t, \
+ (DBusMessageIter *iter, int type, const char *contained_signature, DBusMessageIter *sub), \
+ (iter, type, contained_signature, sub)) \
+ RT_PROXY_STUB(dbus_message_iter_close_container, dbus_bool_t, \
+ (DBusMessageIter *iter, DBusMessageIter *sub), \
+ (iter, sub)) \
+ RT_PROXY_STUB(dbus_message_iter_append_fixed_array, dbus_bool_t, \
+ (DBusMessageIter *iter, int element_type, const void *value, int n_elements), \
+ (iter, element_type, value, n_elements)) \
+ RT_PROXY_STUB(dbus_message_unref, void, (DBusMessage *message), \
+ (message)) \
+ RT_PROXY_STUB(dbus_message_new_method_call, DBusMessage*, \
+ (const char *string1, const char *string2, const char *string3, \
+ const char *string4), \
+ (string1, string2, string3, string4)) \
+ RT_PROXY_STUB(dbus_message_iter_init_append, void, \
+ (DBusMessage *message, DBusMessageIter *iter), \
+ (message, iter)) \
+ RT_PROXY_STUB(dbus_message_iter_append_basic, dbus_bool_t, \
+ (DBusMessageIter *iter, int val, const void *string), \
+ (iter, val, string)) \
+ RT_PROXY_STUB(dbus_connection_send_with_reply_and_block, DBusMessage *, \
+ (DBusConnection *connection, DBusMessage *message, int val, \
+ DBusError *error), \
+ (connection, message, val, error)) \
+ RT_PROXY_STUB(dbus_message_iter_init, dbus_bool_t, \
+ (DBusMessage *message, DBusMessageIter *iter), \
+ (message, iter)) \
+ RT_PROXY_STUB(dbus_message_get_signature, char *, (DBusMessage *message), \
+ (message)) \
+ RT_PROXY_STUB(dbus_message_iter_get_signature, char *, (DBusMessageIter *iter), \
+ (iter)) \
+ RT_PROXY_STUB(dbus_message_iter_get_arg_type, int, (DBusMessageIter *iter), \
+ (iter)) \
+ RT_PROXY_STUB(dbus_message_iter_get_element_type, int, \
+ (DBusMessageIter *iter), (iter)) \
+ RT_PROXY_STUB(dbus_message_iter_recurse, void, \
+ (DBusMessageIter *iter1, DBusMessageIter *iter2), \
+ (iter1, iter2)) \
+ RT_PROXY_STUB(dbus_message_iter_get_basic, void, \
+ (DBusMessageIter *iter, void *pvoid), (iter, pvoid)) \
+ RT_PROXY_STUB(dbus_message_iter_has_next, dbus_bool_t, \
+ (DBusMessageIter *iter), (iter)) \
+ RT_PROXY_STUB(dbus_message_iter_next, dbus_bool_t, (DBusMessageIter *iter), \
+ (iter)) \
+ RT_PROXY_STUB(dbus_message_iter_abandon_container_if_open, void, \
+ (DBusMessageIter *iter, DBusMessageIter *sub), (iter, sub)) \
+ RT_PROXY_STUB(dbus_connection_add_filter, dbus_bool_t, \
+ (DBusConnection *connection, \
+ DBusHandleMessageFunction function1, void *pvoid, \
+ DBusFreeFunction function2), \
+ (connection, function1, pvoid, function2)) \
+ RT_PROXY_STUB(dbus_connection_remove_filter, void, \
+ (DBusConnection *connection, \
+ DBusHandleMessageFunction function, void *pvoid), \
+ (connection, function, pvoid)) \
+ RT_PROXY_STUB(dbus_connection_read_write, dbus_bool_t, \
+ (DBusConnection *connection, int val), (connection, val)) \
+ RT_PROXY_STUB(dbus_connection_read_write_dispatch, dbus_bool_t, \
+ (DBusConnection *connection, int val), (connection, val)) \
+ RT_PROXY_STUB(dbus_message_is_signal, dbus_bool_t, \
+ (DBusMessage *message, const char *string1, \
+ const char *string2), \
+ (message, string1, string2)) \
+ RT_PROXY_STUB(dbus_connection_pop_message, DBusMessage *, \
+ (DBusConnection *connection), (connection)) \
+ RT_PROXY_STUB(dbus_set_error_from_message, dbus_bool_t, \
+ (DBusError *error, DBusMessage *message), (error, message)) \
+ RT_PROXY_STUB(dbus_free, void, \
+ (void *memory), (memory))
+
+#ifdef VBOX_DBUS_GENERATE_HEADER
+# define RT_RUNTIME_LOADER_GENERATE_HEADER
+# define RT_RUNTIME_LOADER_GENERATE_DECLS
+# include <iprt/runtime-loader.h>
+# undef RT_RUNTIME_LOADER_GENERATE_HEADER
+# undef RT_RUNTIME_LOADER_GENERATE_DECLS
+
+#elif defined(VBOX_DBUS_GENERATE_BODY)
+# define RT_RUNTIME_LOADER_GENERATE_BODY_STUBS
+# include <iprt/runtime-loader.h>
+# undef RT_RUNTIME_LOADER_GENERATE_BODY_STUBS
+
+#else
+# error This file should only be included to generate stubs for loading the DBus library at runtime
+#endif
+
+#undef RT_RUNTIME_LOADER_LIB_NAME
+#undef RT_RUNTIME_LOADER_INSERT_SYMBOLS
+
diff --git a/include/VBox/dbus.h b/include/VBox/dbus.h
new file mode 100644
index 00000000..1b3993c1
--- /dev/null
+++ b/include/VBox/dbus.h
@@ -0,0 +1,139 @@
+/** @file
+ * Module to dynamically load libdbus and load all symbols which are needed by
+ * VirtualBox.
+ */
+
+/*
+ * Copyright (C) 2008-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_dbus_h
+#define VBOX_INCLUDED_dbus_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+#include <iprt/stdarg.h>
+
+#ifndef __cplusplus
+# error "This header requires C++ to avoid name clashes."
+#endif
+
+/** Types and defines from the dbus header files which we need. These are
+ * taken more or less verbatim from the DBus public interface header files. */
+struct DBusError
+{
+ const char *name;
+ const char *message;
+ unsigned int dummy1 : 1;
+ unsigned int dummy2 : 1;
+ unsigned int dummy3 : 1;
+ unsigned int dummy4 : 1;
+ unsigned int dummy5 : 1;
+ void *padding1;
+};
+typedef struct DBusError DBusError;
+
+struct DBusConnection;
+typedef struct DBusConnection DBusConnection;
+
+typedef uint32_t dbus_bool_t;
+typedef uint32_t dbus_uint32_t;
+typedef enum { DBUS_BUS_SESSION, DBUS_BUS_SYSTEM, DBUS_BUS_STARTER } DBusBusType;
+
+struct DBusMessage;
+typedef struct DBusMessage DBusMessage;
+
+struct DBusMessageIter
+{
+ void *dummy1;
+ void *dummy2;
+ dbus_uint32_t dummy3;
+ int dummy4;
+ int dummy5;
+ int dummy6;
+ int dummy7;
+ int dummy8;
+ int dummy9;
+ int dummy10;
+ int dummy11;
+ int pad1;
+ int pad2;
+ void *pad3;
+};
+typedef struct DBusMessageIter DBusMessageIter;
+
+#define DBUS_ERROR_NO_MEMORY "org.freedesktop.DBus.Error.NoMemory"
+
+/* Message types. */
+#define DBUS_MESSAGE_TYPE_INVALID 0
+#define DBUS_MESSAGE_TYPE_METHOD_CALL 1
+#define DBUS_MESSAGE_TYPE_METHOD_RETURN 2
+#define DBUS_MESSAGE_TYPE_ERROR 3
+#define DBUS_MESSAGE_TYPE_SIGNAL 4
+
+/* Primitive types. */
+#define DBUS_TYPE_INVALID ((int) '\0')
+#define DBUS_TYPE_BOOLEAN ((int) 'b')
+#define DBUS_TYPE_INT32 ((int) 'i')
+#define DBUS_TYPE_UINT32 ((int) 'u')
+#define DBUS_TYPE_DOUBLE ((int) 'd')
+#define DBUS_TYPE_STRING ((int) 's')
+#define DBUS_TYPE_STRING_AS_STRING "s"
+
+/* Compound types. */
+#define DBUS_TYPE_OBJECT_PATH ((int) 'o')
+#define DBUS_TYPE_ARRAY ((int) 'a')
+#define DBUS_TYPE_ARRAY_AS_STRING "a"
+#define DBUS_TYPE_DICT_ENTRY ((int) 'e')
+#define DBUS_TYPE_DICT_ENTRY_AS_STRING "e"
+#define DBUS_TYPE_STRUCT ((int) 'r')
+
+typedef enum
+{
+ DBUS_HANDLER_RESULT_HANDLED,
+ DBUS_HANDLER_RESULT_NOT_YET_HANDLED,
+ DBUS_HANDLER_RESULT_NEED_MEMORY
+} DBusHandlerResult;
+
+typedef DBusHandlerResult (* DBusHandleMessageFunction)(DBusConnection *,
+ DBusMessage *, void *);
+typedef void (* DBusFreeFunction) (void *);
+
+/* Declarations of the functions that we need from libdbus-1 */
+#define VBOX_DBUS_GENERATE_HEADER
+
+#include <VBox/dbus-calls.h>
+
+#undef VBOX_DBUS_GENERATE_HEADER
+
+#endif /* !VBOX_INCLUDED_dbus_h */
+
diff --git a/include/VBox/dis.h b/include/VBox/dis.h
new file mode 100644
index 00000000..f20c895e
--- /dev/null
+++ b/include/VBox/dis.h
@@ -0,0 +1,912 @@
+/** @file
+ * DIS - The VirtualBox Disassembler.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_dis_h
+#define VBOX_INCLUDED_dis_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/types.h>
+#include <VBox/disopcode.h>
+#include <iprt/assert.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_dis VBox Disassembler
+ * @{ */
+
+/** @name Prefix byte flags (DISSTATE::fPrefix).
+ * @{
+ */
+#define DISPREFIX_NONE UINT8_C(0x00)
+/** non-default address size. */
+#define DISPREFIX_ADDRSIZE UINT8_C(0x01)
+/** non-default operand size. */
+#define DISPREFIX_OPSIZE UINT8_C(0x02)
+/** lock prefix. */
+#define DISPREFIX_LOCK UINT8_C(0x04)
+/** segment prefix. */
+#define DISPREFIX_SEG UINT8_C(0x08)
+/** rep(e) prefix (not a prefix, but we'll treat is as one). */
+#define DISPREFIX_REP UINT8_C(0x10)
+/** rep(e) prefix (not a prefix, but we'll treat is as one). */
+#define DISPREFIX_REPNE UINT8_C(0x20)
+/** REX prefix (64 bits) */
+#define DISPREFIX_REX UINT8_C(0x40)
+/** @} */
+
+/** @name VEX.Lvvvv prefix destination register flag.
+ * @{
+ */
+#define VEX_LEN256 UINT8_C(0x01)
+#define VEXREG_IS256B(x) ((x) & VEX_LEN256)
+/* Convert second byte of VEX prefix to internal format */
+#define VEX_2B2INT(x) ((((x) >> 2) & 0x1f))
+#define VEX_HAS_REX_R(x) (!((x) & 0x80))
+
+#define DISPREFIX_VEX_FLAG_W UINT8_C(0x01)
+ /** @} */
+
+/** @name 64 bits prefix byte flags (DISSTATE::fRexPrefix).
+ * Requires VBox/disopcode.h.
+ * @{
+ */
+#define DISPREFIX_REX_OP_2_FLAGS(a) (a - OP_PARM_REX_START)
+/*#define DISPREFIX_REX_FLAGS DISPREFIX_REX_OP_2_FLAGS(OP_PARM_REX) - 0, which is no flag */
+#define DISPREFIX_REX_FLAGS_B DISPREFIX_REX_OP_2_FLAGS(OP_PARM_REX_B)
+#define DISPREFIX_REX_FLAGS_X DISPREFIX_REX_OP_2_FLAGS(OP_PARM_REX_X)
+#define DISPREFIX_REX_FLAGS_XB DISPREFIX_REX_OP_2_FLAGS(OP_PARM_REX_XB)
+#define DISPREFIX_REX_FLAGS_R DISPREFIX_REX_OP_2_FLAGS(OP_PARM_REX_R)
+#define DISPREFIX_REX_FLAGS_RB DISPREFIX_REX_OP_2_FLAGS(OP_PARM_REX_RB)
+#define DISPREFIX_REX_FLAGS_RX DISPREFIX_REX_OP_2_FLAGS(OP_PARM_REX_RX)
+#define DISPREFIX_REX_FLAGS_RXB DISPREFIX_REX_OP_2_FLAGS(OP_PARM_REX_RXB)
+#define DISPREFIX_REX_FLAGS_W DISPREFIX_REX_OP_2_FLAGS(OP_PARM_REX_W)
+#define DISPREFIX_REX_FLAGS_WB DISPREFIX_REX_OP_2_FLAGS(OP_PARM_REX_WB)
+#define DISPREFIX_REX_FLAGS_WX DISPREFIX_REX_OP_2_FLAGS(OP_PARM_REX_WX)
+#define DISPREFIX_REX_FLAGS_WXB DISPREFIX_REX_OP_2_FLAGS(OP_PARM_REX_WXB)
+#define DISPREFIX_REX_FLAGS_WR DISPREFIX_REX_OP_2_FLAGS(OP_PARM_REX_WR)
+#define DISPREFIX_REX_FLAGS_WRB DISPREFIX_REX_OP_2_FLAGS(OP_PARM_REX_WRB)
+#define DISPREFIX_REX_FLAGS_WRX DISPREFIX_REX_OP_2_FLAGS(OP_PARM_REX_WRX)
+#define DISPREFIX_REX_FLAGS_WRXB DISPREFIX_REX_OP_2_FLAGS(OP_PARM_REX_WRXB)
+/** @} */
+AssertCompile(RT_IS_POWER_OF_TWO(DISPREFIX_REX_FLAGS_B));
+AssertCompile(RT_IS_POWER_OF_TWO(DISPREFIX_REX_FLAGS_X));
+AssertCompile(RT_IS_POWER_OF_TWO(DISPREFIX_REX_FLAGS_W));
+AssertCompile(RT_IS_POWER_OF_TWO(DISPREFIX_REX_FLAGS_R));
+
+/** @name Operand type (DISOPCODE::fOpType).
+ * @{
+ */
+#define DISOPTYPE_INVALID RT_BIT_32(0)
+#define DISOPTYPE_HARMLESS RT_BIT_32(1)
+#define DISOPTYPE_CONTROLFLOW RT_BIT_32(2)
+#define DISOPTYPE_POTENTIALLY_DANGEROUS RT_BIT_32(3)
+#define DISOPTYPE_DANGEROUS RT_BIT_32(4)
+#define DISOPTYPE_PORTIO RT_BIT_32(5)
+#define DISOPTYPE_PRIVILEGED RT_BIT_32(6)
+#define DISOPTYPE_PRIVILEGED_NOTRAP RT_BIT_32(7)
+#define DISOPTYPE_UNCOND_CONTROLFLOW RT_BIT_32(8)
+#define DISOPTYPE_RELATIVE_CONTROLFLOW RT_BIT_32(9)
+#define DISOPTYPE_COND_CONTROLFLOW RT_BIT_32(10)
+#define DISOPTYPE_INTERRUPT RT_BIT_32(11)
+#define DISOPTYPE_ILLEGAL RT_BIT_32(12)
+#define DISOPTYPE_RRM_DANGEROUS RT_BIT_32(14) /**< Some additional dangerous ones when recompiling raw r0. */
+#define DISOPTYPE_RRM_DANGEROUS_16 RT_BIT_32(15) /**< Some additional dangerous ones when recompiling 16-bit raw r0. */
+#define DISOPTYPE_RRM_MASK (DISOPTYPE_RRM_DANGEROUS | DISOPTYPE_RRM_DANGEROUS_16)
+#define DISOPTYPE_INHIBIT_IRQS RT_BIT_32(16) /**< Will or can inhibit irqs (sti, pop ss, mov ss) */
+#define DISOPTYPE_PORTIO_READ RT_BIT_32(17)
+#define DISOPTYPE_PORTIO_WRITE RT_BIT_32(18)
+#define DISOPTYPE_INVALID_64 RT_BIT_32(19) /**< Invalid in 64 bits mode */
+#define DISOPTYPE_ONLY_64 RT_BIT_32(20) /**< Only valid in 64 bits mode */
+#define DISOPTYPE_DEFAULT_64_OP_SIZE RT_BIT_32(21) /**< Default 64 bits operand size */
+#define DISOPTYPE_FORCED_64_OP_SIZE RT_BIT_32(22) /**< Forced 64 bits operand size; regardless of prefix bytes */
+#define DISOPTYPE_REXB_EXTENDS_OPREG RT_BIT_32(23) /**< REX.B extends the register field in the opcode byte */
+#define DISOPTYPE_MOD_FIXED_11 RT_BIT_32(24) /**< modrm.mod is always 11b */
+#define DISOPTYPE_FORCED_32_OP_SIZE_X86 RT_BIT_32(25) /**< Forced 32 bits operand size; regardless of prefix bytes (only in 16 & 32 bits mode!) */
+#define DISOPTYPE_AVX RT_BIT_32(28) /**< AVX,AVX2,++ instruction. Not implemented yet! */
+#define DISOPTYPE_SSE RT_BIT_32(29) /**< SSE,SSE2,SSE3,SSE4,++ instruction. Not implemented yet! */
+#define DISOPTYPE_MMX RT_BIT_32(30) /**< MMX,MMXExt,3DNow,++ instruction. Not implemented yet! */
+#define DISOPTYPE_FPU RT_BIT_32(31) /**< FPU instruction. Not implemented yet! */
+#define DISOPTYPE_ALL UINT32_C(0xffffffff)
+/** @} */
+
+/** @name Parameter usage flags.
+ * @{
+ */
+#define DISUSE_BASE RT_BIT_64(0)
+#define DISUSE_INDEX RT_BIT_64(1)
+#define DISUSE_SCALE RT_BIT_64(2)
+#define DISUSE_REG_GEN8 RT_BIT_64(3)
+#define DISUSE_REG_GEN16 RT_BIT_64(4)
+#define DISUSE_REG_GEN32 RT_BIT_64(5)
+#define DISUSE_REG_GEN64 RT_BIT_64(6)
+#define DISUSE_REG_FP RT_BIT_64(7)
+#define DISUSE_REG_MMX RT_BIT_64(8)
+#define DISUSE_REG_XMM RT_BIT_64(9)
+#define DISUSE_REG_YMM RT_BIT_64(10)
+#define DISUSE_REG_CR RT_BIT_64(11)
+#define DISUSE_REG_DBG RT_BIT_64(12)
+#define DISUSE_REG_SEG RT_BIT_64(13)
+#define DISUSE_REG_TEST RT_BIT_64(14)
+#define DISUSE_DISPLACEMENT8 RT_BIT_64(15)
+#define DISUSE_DISPLACEMENT16 RT_BIT_64(16)
+#define DISUSE_DISPLACEMENT32 RT_BIT_64(17)
+#define DISUSE_DISPLACEMENT64 RT_BIT_64(18)
+#define DISUSE_RIPDISPLACEMENT32 RT_BIT_64(19)
+#define DISUSE_IMMEDIATE8 RT_BIT_64(20)
+#define DISUSE_IMMEDIATE8_REL RT_BIT_64(21)
+#define DISUSE_IMMEDIATE16 RT_BIT_64(22)
+#define DISUSE_IMMEDIATE16_REL RT_BIT_64(23)
+#define DISUSE_IMMEDIATE32 RT_BIT_64(24)
+#define DISUSE_IMMEDIATE32_REL RT_BIT_64(25)
+#define DISUSE_IMMEDIATE64 RT_BIT_64(26)
+#define DISUSE_IMMEDIATE64_REL RT_BIT_64(27)
+#define DISUSE_IMMEDIATE_ADDR_0_32 RT_BIT_64(28)
+#define DISUSE_IMMEDIATE_ADDR_16_32 RT_BIT_64(29)
+#define DISUSE_IMMEDIATE_ADDR_0_16 RT_BIT_64(30)
+#define DISUSE_IMMEDIATE_ADDR_16_16 RT_BIT_64(31)
+/** DS:ESI */
+#define DISUSE_POINTER_DS_BASED RT_BIT_64(32)
+/** ES:EDI */
+#define DISUSE_POINTER_ES_BASED RT_BIT_64(33)
+#define DISUSE_IMMEDIATE16_SX8 RT_BIT_64(34)
+#define DISUSE_IMMEDIATE32_SX8 RT_BIT_64(35)
+#define DISUSE_IMMEDIATE64_SX8 RT_BIT_64(36)
+
+/** Mask of immediate use flags. */
+#define DISUSE_IMMEDIATE ( DISUSE_IMMEDIATE8 \
+ | DISUSE_IMMEDIATE16 \
+ | DISUSE_IMMEDIATE32 \
+ | DISUSE_IMMEDIATE64 \
+ | DISUSE_IMMEDIATE8_REL \
+ | DISUSE_IMMEDIATE16_REL \
+ | DISUSE_IMMEDIATE32_REL \
+ | DISUSE_IMMEDIATE64_REL \
+ | DISUSE_IMMEDIATE_ADDR_0_32 \
+ | DISUSE_IMMEDIATE_ADDR_16_32 \
+ | DISUSE_IMMEDIATE_ADDR_0_16 \
+ | DISUSE_IMMEDIATE_ADDR_16_16 \
+ | DISUSE_IMMEDIATE16_SX8 \
+ | DISUSE_IMMEDIATE32_SX8 \
+ | DISUSE_IMMEDIATE64_SX8)
+/** Check if the use flags indicates an effective address. */
+#define DISUSE_IS_EFFECTIVE_ADDR(a_fUseFlags) (!!( (a_fUseFlags) \
+ & ( DISUSE_BASE \
+ | DISUSE_INDEX \
+ | DISUSE_DISPLACEMENT32 \
+ | DISUSE_DISPLACEMENT64 \
+ | DISUSE_DISPLACEMENT16 \
+ | DISUSE_DISPLACEMENT8 \
+ | DISUSE_RIPDISPLACEMENT32) ))
+/** @} */
+
+/** @name 64-bit general register indexes.
+ * This matches the AMD64 register encoding. It is found used in
+ * DISOPPARAM::Base.idxGenReg and DISOPPARAM::Index.idxGenReg.
+ * @note Safe to assume same values as the 16-bit and 32-bit general registers.
+ * @{
+ */
+#define DISGREG_RAX UINT8_C(0)
+#define DISGREG_RCX UINT8_C(1)
+#define DISGREG_RDX UINT8_C(2)
+#define DISGREG_RBX UINT8_C(3)
+#define DISGREG_RSP UINT8_C(4)
+#define DISGREG_RBP UINT8_C(5)
+#define DISGREG_RSI UINT8_C(6)
+#define DISGREG_RDI UINT8_C(7)
+#define DISGREG_R8 UINT8_C(8)
+#define DISGREG_R9 UINT8_C(9)
+#define DISGREG_R10 UINT8_C(10)
+#define DISGREG_R11 UINT8_C(11)
+#define DISGREG_R12 UINT8_C(12)
+#define DISGREG_R13 UINT8_C(13)
+#define DISGREG_R14 UINT8_C(14)
+#define DISGREG_R15 UINT8_C(15)
+/** @} */
+
+/** @name 32-bit general register indexes.
+ * This matches the AMD64 register encoding. It is found used in
+ * DISOPPARAM::Base.idxGenReg and DISOPPARAM::Index.idxGenReg.
+ * @note Safe to assume same values as the 16-bit and 64-bit general registers.
+ * @{
+ */
+#define DISGREG_EAX UINT8_C(0)
+#define DISGREG_ECX UINT8_C(1)
+#define DISGREG_EDX UINT8_C(2)
+#define DISGREG_EBX UINT8_C(3)
+#define DISGREG_ESP UINT8_C(4)
+#define DISGREG_EBP UINT8_C(5)
+#define DISGREG_ESI UINT8_C(6)
+#define DISGREG_EDI UINT8_C(7)
+#define DISGREG_R8D UINT8_C(8)
+#define DISGREG_R9D UINT8_C(9)
+#define DISGREG_R10D UINT8_C(10)
+#define DISGREG_R11D UINT8_C(11)
+#define DISGREG_R12D UINT8_C(12)
+#define DISGREG_R13D UINT8_C(13)
+#define DISGREG_R14D UINT8_C(14)
+#define DISGREG_R15D UINT8_C(15)
+/** @} */
+
+/** @name 16-bit general register indexes.
+ * This matches the AMD64 register encoding. It is found used in
+ * DISOPPARAM::Base.idxGenReg and DISOPPARAM::Index.idxGenReg.
+ * @note Safe to assume same values as the 32-bit and 64-bit general registers.
+ * @{
+ */
+#define DISGREG_AX UINT8_C(0)
+#define DISGREG_CX UINT8_C(1)
+#define DISGREG_DX UINT8_C(2)
+#define DISGREG_BX UINT8_C(3)
+#define DISGREG_SP UINT8_C(4)
+#define DISGREG_BP UINT8_C(5)
+#define DISGREG_SI UINT8_C(6)
+#define DISGREG_DI UINT8_C(7)
+#define DISGREG_R8W UINT8_C(8)
+#define DISGREG_R9W UINT8_C(9)
+#define DISGREG_R10W UINT8_C(10)
+#define DISGREG_R11W UINT8_C(11)
+#define DISGREG_R12W UINT8_C(12)
+#define DISGREG_R13W UINT8_C(13)
+#define DISGREG_R14W UINT8_C(14)
+#define DISGREG_R15W UINT8_C(15)
+/** @} */
+
+/** @name 8-bit general register indexes.
+ * This mostly (?) matches the AMD64 register encoding. It is found used in
+ * DISOPPARAM::Base.idxGenReg and DISOPPARAM::Index.idxGenReg.
+ * @{
+ */
+#define DISGREG_AL UINT8_C(0)
+#define DISGREG_CL UINT8_C(1)
+#define DISGREG_DL UINT8_C(2)
+#define DISGREG_BL UINT8_C(3)
+#define DISGREG_AH UINT8_C(4)
+#define DISGREG_CH UINT8_C(5)
+#define DISGREG_DH UINT8_C(6)
+#define DISGREG_BH UINT8_C(7)
+#define DISGREG_R8B UINT8_C(8)
+#define DISGREG_R9B UINT8_C(9)
+#define DISGREG_R10B UINT8_C(10)
+#define DISGREG_R11B UINT8_C(11)
+#define DISGREG_R12B UINT8_C(12)
+#define DISGREG_R13B UINT8_C(13)
+#define DISGREG_R14B UINT8_C(14)
+#define DISGREG_R15B UINT8_C(15)
+#define DISGREG_SPL UINT8_C(16)
+#define DISGREG_BPL UINT8_C(17)
+#define DISGREG_SIL UINT8_C(18)
+#define DISGREG_DIL UINT8_C(19)
+/** @} */
+
+/** @name Segment registerindexes.
+ * This matches the AMD64 register encoding. It is found used in
+ * DISOPPARAM::Base.idxSegReg.
+ * @{
+ */
+typedef enum
+{
+ DISSELREG_ES = 0,
+ DISSELREG_CS = 1,
+ DISSELREG_SS = 2,
+ DISSELREG_DS = 3,
+ DISSELREG_FS = 4,
+ DISSELREG_GS = 5,
+ /** End of the valid register index values. */
+ DISSELREG_END,
+ /** The usual 32-bit paranoia. */
+ DIS_SEGREG_32BIT_HACK = 0x7fffffff
+} DISSELREG;
+/** @} */
+
+/** @name FPU register indexes.
+ * This matches the AMD64 register encoding. It is found used in
+ * DISOPPARAM::Base.idxFpuReg.
+ * @{
+ */
+#define DISFPREG_ST0 UINT8_C(0)
+#define DISFPREG_ST1 UINT8_C(1)
+#define DISFPREG_ST2 UINT8_C(2)
+#define DISFPREG_ST3 UINT8_C(3)
+#define DISFPREG_ST4 UINT8_C(4)
+#define DISFPREG_ST5 UINT8_C(5)
+#define DISFPREG_ST6 UINT8_C(6)
+#define DISFPREG_ST7 UINT8_C(7)
+/** @} */
+
+/** @name Control register indexes.
+ * This matches the AMD64 register encoding. It is found used in
+ * DISOPPARAM::Base.idxCtrlReg.
+ * @{
+ */
+#define DISCREG_CR0 UINT8_C(0)
+#define DISCREG_CR1 UINT8_C(1)
+#define DISCREG_CR2 UINT8_C(2)
+#define DISCREG_CR3 UINT8_C(3)
+#define DISCREG_CR4 UINT8_C(4)
+#define DISCREG_CR8 UINT8_C(8)
+/** @} */
+
+/** @name Debug register indexes.
+ * This matches the AMD64 register encoding. It is found used in
+ * DISOPPARAM::Base.idxDbgReg.
+ * @{
+ */
+#define DISDREG_DR0 UINT8_C(0)
+#define DISDREG_DR1 UINT8_C(1)
+#define DISDREG_DR2 UINT8_C(2)
+#define DISDREG_DR3 UINT8_C(3)
+#define DISDREG_DR4 UINT8_C(4)
+#define DISDREG_DR5 UINT8_C(5)
+#define DISDREG_DR6 UINT8_C(6)
+#define DISDREG_DR7 UINT8_C(7)
+/** @} */
+
+/** @name MMX register indexes.
+ * This matches the AMD64 register encoding. It is found used in
+ * DISOPPARAM::Base.idxMmxReg.
+ * @{
+ */
+#define DISMREG_MMX0 UINT8_C(0)
+#define DISMREG_MMX1 UINT8_C(1)
+#define DISMREG_MMX2 UINT8_C(2)
+#define DISMREG_MMX3 UINT8_C(3)
+#define DISMREG_MMX4 UINT8_C(4)
+#define DISMREG_MMX5 UINT8_C(5)
+#define DISMREG_MMX6 UINT8_C(6)
+#define DISMREG_MMX7 UINT8_C(7)
+/** @} */
+
+/** @name SSE register indexes.
+ * This matches the AMD64 register encoding. It is found used in
+ * DISOPPARAM::Base.idxXmmReg.
+ * @{
+ */
+#define DISXREG_XMM0 UINT8_C(0)
+#define DISXREG_XMM1 UINT8_C(1)
+#define DISXREG_XMM2 UINT8_C(2)
+#define DISXREG_XMM3 UINT8_C(3)
+#define DISXREG_XMM4 UINT8_C(4)
+#define DISXREG_XMM5 UINT8_C(5)
+#define DISXREG_XMM6 UINT8_C(6)
+#define DISXREG_XMM7 UINT8_C(7)
+/** @} */
+
+
+/**
+ * Opcode parameter (operand) details.
+ */
+typedef struct DISOPPARAM
+{
+ /** A combination of DISUSE_XXX. */
+ uint64_t fUse;
+ /** Immediate value or address, applicable if any of the flags included in
+ * DISUSE_IMMEDIATE are set in fUse. */
+ uint64_t uValue;
+ /** Disposition. */
+ union
+ {
+ /** 64-bit displacement, applicable if DISUSE_DISPLACEMENT64 is set in fUse. */
+ int64_t i64;
+ uint64_t u64;
+ /** 32-bit displacement, applicable if DISUSE_DISPLACEMENT32 or
+ * DISUSE_RIPDISPLACEMENT32 is set in fUse. */
+ int32_t i32;
+ uint32_t u32;
+ /** 16-bit displacement, applicable if DISUSE_DISPLACEMENT16 is set in fUse. */
+ int32_t i16;
+ uint32_t u16;
+ /** 8-bit displacement, applicable if DISUSE_DISPLACEMENT8 is set in fUse. */
+ int32_t i8;
+ uint32_t u8;
+ } uDisp;
+ /** The base register from ModR/M or SIB, applicable if DISUSE_BASE is
+ * set in fUse. */
+ union
+ {
+ /** General register index (DISGREG_XXX), applicable if DISUSE_REG_GEN8,
+ * DISUSE_REG_GEN16, DISUSE_REG_GEN32 or DISUSE_REG_GEN64 is set in fUse. */
+ uint8_t idxGenReg;
+ /** FPU stack register index (DISFPREG_XXX), applicable if DISUSE_REG_FP is
+ * set in fUse. 1:1 indexes. */
+ uint8_t idxFpuReg;
+ /** MMX register index (DISMREG_XXX), applicable if DISUSE_REG_MMX is
+ * set in fUse. 1:1 indexes. */
+ uint8_t idxMmxReg;
+ /** SSE register index (DISXREG_XXX), applicable if DISUSE_REG_XMM is
+ * set in fUse. 1:1 indexes. */
+ uint8_t idxXmmReg;
+ /** SSE2 register index (DISYREG_XXX), applicable if DISUSE_REG_YMM is
+ * set in fUse. 1:1 indexes. */
+ uint8_t idxYmmReg;
+ /** Segment register index (DISSELREG_XXX), applicable if DISUSE_REG_SEG is
+ * set in fUse. */
+ uint8_t idxSegReg;
+ /** Test register, TR0-TR7, present on early IA32 CPUs, applicable if
+ * DISUSE_REG_TEST is set in fUse. No index defines for these. */
+ uint8_t idxTestReg;
+ /** Control register index (DISCREG_XXX), applicable if DISUSE_REG_CR is
+ * set in fUse. 1:1 indexes. */
+ uint8_t idxCtrlReg;
+ /** Debug register index (DISDREG_XXX), applicable if DISUSE_REG_DBG is
+ * set in fUse. 1:1 indexes. */
+ uint8_t idxDbgReg;
+ } Base;
+ /** The SIB index register meaning, applicable if DISUSE_INDEX is
+ * set in fUse. */
+ union
+ {
+ /** General register index (DISGREG_XXX), applicable if DISUSE_REG_GEN8,
+ * DISUSE_REG_GEN16, DISUSE_REG_GEN32 or DISUSE_REG_GEN64 is set in fUse. */
+ uint8_t idxGenReg;
+ /** XMM register index (DISXREG_XXX), applicable if DISUSE_REG_XMM
+ * is set in fUse. */
+ uint8_t idxXmmReg;
+ /** YMM register index (DISXREG_XXX), applicable if DISUSE_REG_YMM
+ * is set in fUse. */
+ uint8_t idxYmmReg;
+ } Index;
+ /** 2, 4 or 8, if DISUSE_SCALE is set in fUse. */
+ uint8_t uScale;
+ /** Parameter size. */
+ uint8_t cb;
+ /** Copy of the corresponding DISOPCODE::fParam1 / DISOPCODE::fParam2 /
+ * DISOPCODE::fParam3. */
+ uint32_t fParam;
+} DISOPPARAM;
+AssertCompileSize(DISOPPARAM, 32);
+/** Pointer to opcode parameter. */
+typedef DISOPPARAM *PDISOPPARAM;
+/** Pointer to opcode parameter. */
+typedef const DISOPPARAM *PCDISOPPARAM;
+
+
+#if (defined(RT_ARCH_X86) || defined(RT_ARCH_AMD64)) && defined(DIS_CORE_ONLY)
+# define DISOPCODE_BITFIELD(a_cBits) : a_cBits
+#else
+# define DISOPCODE_BITFIELD(a_cBits)
+#endif
+
+/**
+ * Opcode descriptor.
+ */
+#if !defined(DIS_CORE_ONLY) || defined(DOXYGEN_RUNNING)
+typedef struct DISOPCODE
+{
+# define DISOPCODE_FORMAT 0
+ /** Mnemonic and operand formatting. */
+ const char *pszOpcode;
+ /** Parameter \#1 parser index. */
+ uint8_t idxParse1;
+ /** Parameter \#2 parser index. */
+ uint8_t idxParse2;
+ /** Parameter \#3 parser index. */
+ uint8_t idxParse3;
+ /** Parameter \#4 parser index. */
+ uint8_t idxParse4;
+ /** The opcode identifier. This DIS specific, @see grp_dis_opcodes and
+ * VBox/disopcode.h. */
+ uint16_t uOpcode;
+ /** Parameter \#1 info, @see grp_dis_opparam. */
+ uint16_t fParam1;
+ /** Parameter \#2 info, @see grp_dis_opparam. */
+ uint16_t fParam2;
+ /** Parameter \#3 info, @see grp_dis_opparam. */
+ uint16_t fParam3;
+ /** Parameter \#4 info, @see grp_dis_opparam. */
+ uint16_t fParam4;
+ /** padding unused */
+ uint16_t uPadding;
+ /** Operand type flags, DISOPTYPE_XXX. */
+ uint32_t fOpType;
+} DISOPCODE;
+#else
+# pragma pack(1)
+typedef struct DISOPCODE
+{
+#if 1 /*!defined(RT_ARCH_X86) && !defined(RT_ARCH_AMD64) - probably not worth it for ~4K, costs 2-3% speed. */
+ /* 16 bytes (trick is to make sure the bitfields doesn't cross dwords): */
+# define DISOPCODE_FORMAT 16
+ uint32_t fOpType;
+ uint16_t uOpcode;
+ uint8_t idxParse1;
+ uint8_t idxParse2;
+ uint32_t fParam1 : 12; /* 1st dword: 12+12+8 = 0x20 (32) */
+ uint32_t fParam2 : 12;
+ uint32_t idxParse3 : 8;
+ uint32_t fParam3 : 12; /* 2nd dword: 12+12+8 = 0x20 (32) */
+ uint32_t fParam4 : 12;
+ uint32_t idxParse4 : 8;
+#else /* 15 bytes: */
+# define DISOPCODE_FORMAT 15
+ uint64_t uOpcode : 10; /* 1st qword: 10+12+12+12+6+6+6 = 0x40 (64) */
+ uint64_t idxParse1 : 6;
+ uint64_t idxParse2 : 6;
+ uint64_t idxParse3 : 6;
+ uint64_t fParam1 : 12;
+ uint64_t fParam2 : 12;
+ uint64_t fParam3 : 12;
+ uint32_t fOpType;
+ uint16_t fParam4;
+ uint8_t idxParse4;
+#endif
+} DISOPCODE;
+# pragma pack()
+AssertCompile(sizeof(DISOPCODE) == DISOPCODE_FORMAT);
+#endif
+AssertCompile(DISOPCODE_FORMAT != 15); /* Needs fixing before use as disopcode.h now has more than 1024 opcode values. */
+/** Pointer to const opcode. */
+typedef const struct DISOPCODE *PCDISOPCODE;
+
+
+/**
+ * Callback for reading instruction bytes.
+ *
+ * @returns VBox status code, bytes in DISSTATE::abInstr and byte count in
+ * DISSTATE::cbCachedInstr.
+ * @param pDis Pointer to the disassembler state. The user
+ * argument can be found in DISSTATE::pvUser if needed.
+ * @param offInstr The offset relative to the start of the instruction.
+ *
+ * To get the source address, add this to
+ * DISSTATE::uInstrAddr.
+ *
+ * To calculate the destination buffer address, use it
+ * as an index into DISSTATE::abInstr.
+ *
+ * @param cbMinRead The minimum number of bytes to read.
+ * @param cbMaxRead The maximum number of bytes that may be read.
+ */
+typedef DECLCALLBACKTYPE(int, FNDISREADBYTES,(PDISSTATE pDis, uint8_t offInstr, uint8_t cbMinRead, uint8_t cbMaxRead));
+/** Pointer to a opcode byte reader. */
+typedef FNDISREADBYTES *PFNDISREADBYTES;
+
+/** Parser callback.
+ * @remark no DECLCALLBACK() here because it's considered to be internal and
+ * there is no point in enforcing CDECL. */
+typedef size_t FNDISPARSE(size_t offInstr, PCDISOPCODE pOp, PDISSTATE pDis, PDISOPPARAM pParam);
+/** Pointer to a disassembler parser function. */
+typedef FNDISPARSE *PFNDISPARSE;
+/** Pointer to a const disassembler parser function pointer. */
+typedef PFNDISPARSE const *PCPFNDISPARSE;
+
+/**
+ * The diassembler state and result.
+ */
+typedef struct DISSTATE
+{
+ /** The number of valid bytes in abInstr. */
+ uint8_t cbCachedInstr;
+ /** SIB fields. */
+ union
+ {
+ /** Bitfield view */
+ struct
+ {
+ uint8_t Base;
+ uint8_t Index;
+ uint8_t Scale;
+ } Bits;
+ } SIB;
+ /** ModRM fields. */
+ union
+ {
+ /** Bitfield view */
+ struct
+ {
+ uint8_t Rm;
+ uint8_t Reg;
+ uint8_t Mod;
+ } Bits;
+ } ModRM;
+ /** The CPU mode (DISCPUMODE). */
+ uint8_t uCpuMode;
+ /** The addressing mode (DISCPUMODE). */
+ uint8_t uAddrMode;
+ /** The operand mode (DISCPUMODE). */
+ uint8_t uOpMode;
+ /** Per instruction prefix settings. */
+ uint8_t fPrefix;
+ /** REX prefix value (64 bits only). */
+ uint8_t fRexPrefix;
+ /** Segment prefix value (DISSELREG). */
+ uint8_t idxSegPrefix;
+ /** Last prefix byte (for SSE2 extension tables). */
+ uint8_t bLastPrefix;
+ /** Last significant opcode byte of instruction. */
+ uint8_t bOpCode;
+ /** The size of the prefix bytes. */
+ uint8_t cbPrefix;
+ /** The instruction size. */
+ uint8_t cbInstr;
+ /** VEX presence flag, destination register and size
+ * @todo r=bird: There is no VEX presence flage here, just ~vvvv and L. */
+ uint8_t bVexDestReg;
+ /** VEX.W flag */
+ uint8_t bVexWFlag;
+ /** Unused bytes. */
+ uint8_t abUnused[1];
+ /** Internal: instruction filter */
+ uint32_t fFilter;
+ /** Internal: pointer to disassembly function table */
+ PCPFNDISPARSE pfnDisasmFnTable;
+#if ARCH_BITS == 32
+ uint32_t uPtrPadding1;
+#endif
+ /** Pointer to the current instruction. */
+ PCDISOPCODE pCurInstr;
+#if ARCH_BITS == 32
+ uint32_t uPtrPadding2;
+#endif
+ /** The instruction bytes. */
+ uint8_t abInstr[16];
+ /** SIB displacment. */
+ int32_t i32SibDisp;
+
+ /** Return code set by a worker function like the opcode bytes readers. */
+ int32_t rc;
+ /** The address of the instruction. */
+ RTUINTPTR uInstrAddr;
+ /** Optional read function */
+ PFNDISREADBYTES pfnReadBytes;
+#if ARCH_BITS == 32
+ uint32_t uPadding3;
+#endif
+ /** User data supplied as an argument to the APIs. */
+ void *pvUser;
+#if ARCH_BITS == 32
+ uint32_t uPadding4;
+#endif
+ /** Parameters. */
+ DISOPPARAM Param1;
+ DISOPPARAM Param2;
+ DISOPPARAM Param3;
+ DISOPPARAM Param4;
+} DISSTATE;
+AssertCompileSize(DISSTATE, 0xd8);
+
+/** @deprecated Use DISSTATE and change Cpu and DisState to Dis. */
+typedef DISSTATE DISCPUSTATE;
+
+
+
+DISDECL(int) DISInstrToStr(void const *pvInstr, DISCPUMODE enmCpuMode,
+ PDISSTATE pDis, uint32_t *pcbInstr, char *pszOutput, size_t cbOutput);
+DISDECL(int) DISInstrToStrWithReader(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, PFNDISREADBYTES pfnReadBytes, void *pvUser,
+ PDISSTATE pDis, uint32_t *pcbInstr, char *pszOutput, size_t cbOutput);
+DISDECL(int) DISInstrToStrEx(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode,
+ PFNDISREADBYTES pfnReadBytes, void *pvUser, uint32_t uFilter,
+ PDISSTATE pDis, uint32_t *pcbInstr, char *pszOutput, size_t cbOutput);
+
+DISDECL(int) DISInstr(void const *pvInstr, DISCPUMODE enmCpuMode, PDISSTATE pDis, uint32_t *pcbInstr);
+DISDECL(int) DISInstrWithReader(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, PFNDISREADBYTES pfnReadBytes, void *pvUser,
+ PDISSTATE pDis, uint32_t *pcbInstr);
+DISDECL(int) DISInstrEx(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, uint32_t uFilter,
+ PFNDISREADBYTES pfnReadBytes, void *pvUser,
+ PDISSTATE pDis, uint32_t *pcbInstr);
+DISDECL(int) DISInstrWithPrefetchedBytes(RTUINTPTR uInstrAddr, DISCPUMODE enmCpuMode, uint32_t fFilter,
+ void const *pvPrefetched, size_t cbPretched,
+ PFNDISREADBYTES pfnReadBytes, void *pvUser,
+ PDISSTATE pDis, uint32_t *pcbInstr);
+
+DISDECL(uint8_t) DISGetParamSize(PCDISSTATE pDis, PCDISOPPARAM pParam);
+#if 0 /* unused */
+DISDECL(DISSELREG) DISDetectSegReg(PCDISSTATE pDis, PCDISOPPARAM pParam);
+DISDECL(uint8_t) DISQuerySegPrefixByte(PCDISSTATE pDis);
+#endif
+
+#if 0 /* Needs refactoring if we want to use this again, CPUMCTXCORE is history. */
+/** @name Flags returned by DISQueryParamVal (DISQPVPARAMVAL::flags).
+ * @{
+ */
+#define DISQPV_FLAG_8 UINT8_C(0x01)
+#define DISQPV_FLAG_16 UINT8_C(0x02)
+#define DISQPV_FLAG_32 UINT8_C(0x04)
+#define DISQPV_FLAG_64 UINT8_C(0x08)
+#define DISQPV_FLAG_FARPTR16 UINT8_C(0x10)
+#define DISQPV_FLAG_FARPTR32 UINT8_C(0x20)
+/** @} */
+
+/** @name Types returned by DISQueryParamVal (DISQPVPARAMVAL::flags).
+ * @{ */
+#define DISQPV_TYPE_REGISTER UINT8_C(1)
+#define DISQPV_TYPE_ADDRESS UINT8_C(2)
+#define DISQPV_TYPE_IMMEDIATE UINT8_C(3)
+/** @} */
+
+typedef struct
+{
+ union
+ {
+ uint8_t val8;
+ uint16_t val16;
+ uint32_t val32;
+ uint64_t val64;
+
+ int8_t i8;
+ int16_t i16;
+ int32_t i32;
+ int64_t i64;
+
+ struct
+ {
+ uint16_t sel;
+ uint32_t offset;
+ } farptr;
+ } val;
+
+ uint8_t type;
+ uint8_t size;
+ uint8_t flags;
+} DISQPVPARAMVAL;
+/** Pointer to opcode parameter value. */
+typedef DISQPVPARAMVAL *PDISQPVPARAMVAL;
+
+/** Indicates which parameter DISQueryParamVal should operate on. */
+typedef enum DISQPVWHICH
+{
+ DISQPVWHICH_DST = 1,
+ DISQPVWHICH_SRC,
+ DISQPVWHAT_32_BIT_HACK = 0x7fffffff
+} DISQPVWHICH;
+DISDECL(int) DISQueryParamVal(PCPUMCTXCORE pCtx, PCDISSTATE pDis, PCDISOPPARAM pParam, PDISQPVPARAMVAL pParamVal, DISQPVWHICH parmtype);
+DISDECL(int) DISQueryParamRegPtr(PCPUMCTXCORE pCtx, PCDISSTATE pDis, PCDISOPPARAM pParam, void **ppReg, size_t *pcbSize);
+
+DISDECL(int) DISFetchReg8(PCCPUMCTXCORE pCtx, unsigned reg8, uint8_t *pVal);
+DISDECL(int) DISFetchReg16(PCCPUMCTXCORE pCtx, unsigned reg16, uint16_t *pVal);
+DISDECL(int) DISFetchReg32(PCCPUMCTXCORE pCtx, unsigned reg32, uint32_t *pVal);
+DISDECL(int) DISFetchReg64(PCCPUMCTXCORE pCtx, unsigned reg64, uint64_t *pVal);
+DISDECL(int) DISFetchRegSeg(PCCPUMCTXCORE pCtx, DISSELREG sel, RTSEL *pVal);
+DISDECL(int) DISWriteReg8(PCPUMCTXCORE pRegFrame, unsigned reg8, uint8_t val8);
+DISDECL(int) DISWriteReg16(PCPUMCTXCORE pRegFrame, unsigned reg32, uint16_t val16);
+DISDECL(int) DISWriteReg32(PCPUMCTXCORE pRegFrame, unsigned reg32, uint32_t val32);
+DISDECL(int) DISWriteReg64(PCPUMCTXCORE pRegFrame, unsigned reg64, uint64_t val64);
+DISDECL(int) DISWriteRegSeg(PCPUMCTXCORE pCtx, DISSELREG sel, RTSEL val);
+DISDECL(int) DISPtrReg8(PCPUMCTXCORE pCtx, unsigned reg8, uint8_t **ppReg);
+DISDECL(int) DISPtrReg16(PCPUMCTXCORE pCtx, unsigned reg16, uint16_t **ppReg);
+DISDECL(int) DISPtrReg32(PCPUMCTXCORE pCtx, unsigned reg32, uint32_t **ppReg);
+DISDECL(int) DISPtrReg64(PCPUMCTXCORE pCtx, unsigned reg64, uint64_t **ppReg);
+#endif /* obsolete */
+
+
+/**
+ * Try resolve an address into a symbol name.
+ *
+ * For use with DISFormatYasmEx(), DISFormatMasmEx() and DISFormatGasEx().
+ *
+ * @returns VBox status code.
+ * @retval VINF_SUCCESS on success, pszBuf contains the full symbol name.
+ * @retval VINF_BUFFER_OVERFLOW if pszBuf is too small the symbol name. The
+ * content of pszBuf is truncated and zero terminated.
+ * @retval VERR_SYMBOL_NOT_FOUND if no matching symbol was found for the address.
+ *
+ * @param pDis Pointer to the disassembler CPU state.
+ * @param u32Sel The selector value. Use DIS_FMT_SEL_IS_REG, DIS_FMT_SEL_GET_VALUE,
+ * DIS_FMT_SEL_GET_REG to access this.
+ * @param uAddress The segment address.
+ * @param pszBuf Where to store the symbol name
+ * @param cchBuf The size of the buffer.
+ * @param poff If not a perfect match, then this is where the offset from the return
+ * symbol to the specified address is returned.
+ * @param pvUser The user argument.
+ */
+typedef DECLCALLBACKTYPE(int, FNDISGETSYMBOL,(PCDISSTATE pDis, uint32_t u32Sel, RTUINTPTR uAddress, char *pszBuf, size_t cchBuf,
+ RTINTPTR *poff, void *pvUser));
+/** Pointer to a FNDISGETSYMBOL(). */
+typedef FNDISGETSYMBOL *PFNDISGETSYMBOL;
+
+/**
+ * Checks if the FNDISGETSYMBOL argument u32Sel is a register or not.
+ */
+#define DIS_FMT_SEL_IS_REG(u32Sel) ( !!((u32Sel) & RT_BIT(31)) )
+
+/**
+ * Extracts the selector value from the FNDISGETSYMBOL argument u32Sel.
+ * @returns Selector value.
+ */
+#define DIS_FMT_SEL_GET_VALUE(u32Sel) ( (RTSEL)(u32Sel) )
+
+/**
+ * Extracts the register number from the FNDISGETSYMBOL argument u32Sel.
+ * @returns USE_REG_CS, USE_REG_SS, USE_REG_DS, USE_REG_ES, USE_REG_FS or USE_REG_FS.
+ */
+#define DIS_FMT_SEL_GET_REG(u32Sel) ( ((u32Sel) >> 16) & 0xf )
+
+/** @internal */
+#define DIS_FMT_SEL_FROM_REG(uReg) ( ((uReg) << 16) | RT_BIT(31) | 0xffff )
+/** @internal */
+#define DIS_FMT_SEL_FROM_VALUE(Sel) ( (Sel) & 0xffff )
+
+
+/** @name Flags for use with DISFormatYasmEx(), DISFormatMasmEx() and DISFormatGasEx().
+ * @{
+ */
+/** Put the address to the right. */
+#define DIS_FMT_FLAGS_ADDR_RIGHT RT_BIT_32(0)
+/** Put the address to the left. */
+#define DIS_FMT_FLAGS_ADDR_LEFT RT_BIT_32(1)
+/** Put the address in comments.
+ * For some assemblers this implies placing it to the right. */
+#define DIS_FMT_FLAGS_ADDR_COMMENT RT_BIT_32(2)
+/** Put the instruction bytes to the right of the disassembly. */
+#define DIS_FMT_FLAGS_BYTES_RIGHT RT_BIT_32(3)
+/** Put the instruction bytes to the left of the disassembly. */
+#define DIS_FMT_FLAGS_BYTES_LEFT RT_BIT_32(4)
+/** Put the instruction bytes in comments.
+ * For some assemblers this implies placing the bytes to the right. */
+#define DIS_FMT_FLAGS_BYTES_COMMENT RT_BIT_32(5)
+/** Put the bytes in square brackets. */
+#define DIS_FMT_FLAGS_BYTES_BRACKETS RT_BIT_32(6)
+/** Put spaces between the bytes. */
+#define DIS_FMT_FLAGS_BYTES_SPACED RT_BIT_32(7)
+/** Display the relative +/- offset of branch instructions that uses relative addresses,
+ * and put the target address in parenthesis. */
+#define DIS_FMT_FLAGS_RELATIVE_BRANCH RT_BIT_32(8)
+/** Strict assembly. The assembly should, when ever possible, make the
+ * assembler reproduce the exact same binary. (Refers to the yasm
+ * strict keyword.) */
+#define DIS_FMT_FLAGS_STRICT RT_BIT_32(9)
+/** Checks if the given flags are a valid combination. */
+#define DIS_FMT_FLAGS_IS_VALID(fFlags) \
+ ( !((fFlags) & ~UINT32_C(0x000003ff)) \
+ && ((fFlags) & (DIS_FMT_FLAGS_ADDR_RIGHT | DIS_FMT_FLAGS_ADDR_LEFT)) != (DIS_FMT_FLAGS_ADDR_RIGHT | DIS_FMT_FLAGS_ADDR_LEFT) \
+ && ( !((fFlags) & DIS_FMT_FLAGS_ADDR_COMMENT) \
+ || (fFlags & (DIS_FMT_FLAGS_ADDR_RIGHT | DIS_FMT_FLAGS_ADDR_LEFT)) ) \
+ && ((fFlags) & (DIS_FMT_FLAGS_BYTES_RIGHT | DIS_FMT_FLAGS_BYTES_LEFT)) != (DIS_FMT_FLAGS_BYTES_RIGHT | DIS_FMT_FLAGS_BYTES_LEFT) \
+ && ( !((fFlags) & (DIS_FMT_FLAGS_BYTES_COMMENT | DIS_FMT_FLAGS_BYTES_BRACKETS)) \
+ || (fFlags & (DIS_FMT_FLAGS_BYTES_RIGHT | DIS_FMT_FLAGS_BYTES_LEFT)) ) \
+ )
+/** @} */
+
+DISDECL(size_t) DISFormatYasm( PCDISSTATE pDis, char *pszBuf, size_t cchBuf);
+DISDECL(size_t) DISFormatYasmEx(PCDISSTATE pDis, char *pszBuf, size_t cchBuf, uint32_t fFlags, PFNDISGETSYMBOL pfnGetSymbol, void *pvUser);
+DISDECL(size_t) DISFormatMasm( PCDISSTATE pDis, char *pszBuf, size_t cchBuf);
+DISDECL(size_t) DISFormatMasmEx(PCDISSTATE pDis, char *pszBuf, size_t cchBuf, uint32_t fFlags, PFNDISGETSYMBOL pfnGetSymbol, void *pvUser);
+DISDECL(size_t) DISFormatGas( PCDISSTATE pDis, char *pszBuf, size_t cchBuf);
+DISDECL(size_t) DISFormatGasEx( PCDISSTATE pDis, char *pszBuf, size_t cchBuf, uint32_t fFlags, PFNDISGETSYMBOL pfnGetSymbol, void *pvUser);
+
+/** @todo DISAnnotate(PCDISSTATE pDis, char *pszBuf, size_t cchBuf, register
+ * reader, memory reader); */
+
+DISDECL(bool) DISFormatYasmIsOddEncoding(PDISSTATE pDis);
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !VBOX_INCLUDED_dis_h */
+
diff --git a/include/VBox/disopcode.h b/include/VBox/disopcode.h
new file mode 100644
index 00000000..5732f5c5
--- /dev/null
+++ b/include/VBox/disopcode.h
@@ -0,0 +1,1469 @@
+/** @file
+ * Disassembler - Opcodes
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_disopcode_h
+#define VBOX_INCLUDED_disopcode_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/assert.h>
+
+#define MODRM_MOD(a) (a>>6)
+#define MODRM_REG(a) ((a>>3)&0x7)
+#define MODRM_RM(a) (a&0x7)
+#define MAKE_MODRM(mod, reg, rm) (((mod&3) << 6) | ((reg&7) << 3) | (rm&7))
+
+#define SIB_SCALE(a) (a>>6)
+#define SIB_INDEX(a) ((a>>3)&0x7)
+#define SIB_BASE(a) (a&0x7)
+
+
+/** @defgroup grp_dis_opcodes Opcodes (DISOPCODE::uOpCode)
+ * @ingroup grp_dis
+ * @{
+ */
+enum OPCODES
+{
+/** @name Full Intel X86 opcode list
+ * @{ */
+ OP_INVALID = 0,
+ OP_OPSIZE,
+ OP_ADDRSIZE,
+ OP_SEG,
+ OP_REPNE,
+ OP_REPE,
+ OP_REX,
+ OP_LOCK,
+#ifndef IN_SLICKEDIT
+ OP_LAST_PREFIX = OP_LOCK, /**< Last prefix for disassembler. */
+#else
+ OP_LAST_PREFIX = 7, /**< Last prefix for disassembler. */
+#endif
+ OP_AND,
+ OP_OR,
+ OP_DAA,
+ OP_SUB,
+ OP_DAS,
+ OP_XOR,
+ OP_AAA,
+ OP_CMP,
+ OP_IMM_GRP1,
+ OP_AAS,
+ OP_INC,
+ OP_DEC,
+ OP_PUSHA,
+ OP_POPA,
+ OP_BOUND,
+ OP_ARPL,
+ OP_PUSH,
+ OP_POP,
+ OP_IMUL,
+ OP_INSB,
+ OP_INSWD,
+ OP_OUTSB,
+ OP_OUTSWD,
+ OP_JO,
+ OP_JNO,
+ OP_JC,
+ OP_JNC,
+ OP_JE,
+ OP_JNE,
+ OP_JBE,
+ OP_JNBE,
+ OP_JS,
+ OP_JNS,
+ OP_JP,
+ OP_JNP,
+ OP_JL,
+ OP_JNL,
+ OP_JLE,
+ OP_JNLE,
+ OP_ADD,
+ OP_TEST,
+ OP_XCHG,
+ OP_MOV,
+ OP_LEA,
+ OP_NOP,
+ OP_CBW,
+ OP_CWD,
+ OP_CALL,
+ OP_WAIT,
+ OP_PUSHF,
+ OP_POPF,
+ OP_SAHF,
+ OP_LAHF,
+ OP_MOVSB,
+ OP_MOVSWD,
+ OP_CMPSB,
+ OP_CMPWD,
+ OP_STOSB,
+ OP_STOSWD,
+ OP_LODSB,
+ OP_LODSWD,
+ OP_SCASB,
+ OP_SCASWD,
+ OP_SHIFT_GRP2,
+ OP_RETN,
+ OP_LES,
+ OP_LDS,
+ OP_ENTER,
+ OP_LEAVE,
+ OP_RETF,
+ OP_INT1,
+ OP_INT3,
+ OP_INT,
+ OP_INTO,
+ OP_IRET,
+ OP_AAM,
+ OP_AAD,
+ OP_SALC,
+ OP_XLAT,
+ OP_ESCF0,
+ OP_ESCF1,
+ OP_ESCF2,
+ OP_ESCF3,
+ OP_ESCF4,
+ OP_ESCF5,
+ OP_ESCF6,
+ OP_ESCF7,
+ OP_LOOPNE,
+ OP_LOOPE,
+ OP_LOOP,
+ OP_JECXZ,
+ OP_IN,
+ OP_OUT,
+ OP_JMP,
+ OP_2B_ESC,
+ OP_ADC,
+ OP_SBB,
+ OP_HLT,
+ OP_CMC,
+ OP_UNARY_GRP3,
+ OP_CLC,
+ OP_STC,
+ OP_CLI,
+ OP_STI,
+ OP_CLD,
+ OP_STD,
+ OP_INC_GRP4,
+ OP_IND_GRP5,
+ OP_GRP6,
+ OP_GRP7,
+ OP_LAR,
+ OP_LSL,
+ OP_SYSCALL,
+ OP_CLTS,
+ OP_SYSRET,
+ OP_INVD,
+ OP_WBINVD,
+ OP_ILLUD2,
+ OP_FEMMS,
+ OP_3DNOW,
+ OP_MOVUPS,
+ OP_MOVLPS,
+ OP_MOVHLPS = OP_MOVLPS, /**< @todo OP_MOVHLPS */
+ OP_UNPCKLPS,
+ OP_MOVHPS,
+ OP_MOVLHPS = OP_MOVHPS, /**< @todo OP_MOVLHPS */
+ OP_UNPCKHPS,
+ OP_PREFETCH_GRP16,
+ OP_MOV_CR,
+ OP_MOVAPS,
+ OP_CVTPI2PS,
+ OP_MOVNTPS,
+ OP_CVTTPS2PI,
+ OP_CVTPS2PI,
+ OP_UCOMISS,
+ OP_COMISS,
+ OP_WRMSR,
+ OP_RDTSC,
+ OP_RDTSCP,
+ OP_RDMSR,
+ OP_RDPMC,
+ OP_SYSENTER,
+ OP_SYSEXIT,
+ OP_GETSEC,
+ OP_PAUSE,
+ OP_CMOVO,
+ OP_CMOVNO,
+ OP_CMOVC,
+ OP_CMOVNC,
+ OP_CMOVZ,
+ OP_CMOVNZ,
+ OP_CMOVBE,
+ OP_CMOVNBE,
+ OP_CMOVS,
+ OP_CMOVNS,
+ OP_CMOVP,
+ OP_CMOVNP,
+ OP_CMOVL,
+ OP_CMOVNL,
+ OP_CMOVLE,
+ OP_CMOVNLE,
+ OP_MOVMSKPS,
+ OP_SQRTPS,
+ OP_RSQRTPS,
+ OP_RCPPS,
+ OP_ANDPS,
+ OP_ANDNPS,
+ OP_ORPS,
+ OP_XORPS,
+ OP_ADDPS,
+ OP_MULPS,
+ OP_CVTPS2PD,
+ OP_CVTDQ2PS,
+ OP_SUBPS,
+ OP_MINPS,
+ OP_DIVPS,
+ OP_MAXPS,
+ OP_PUNPCKLBW,
+ OP_PUNPCKLWD,
+ OP_PUNPCKLDQ,
+ OP_PACKSSWB,
+ OP_PCMPGTB,
+ OP_PCMPGTW,
+ OP_PCMPGTD,
+ OP_PCMPGTQ,
+ OP_PACKUSWB,
+ OP_PUNPCKHBW,
+ OP_PUNPCKHWD,
+ OP_PUNPCKHDQ,
+ OP_PACKSSDW,
+ OP_MOVD,
+ OP_MOVQ,
+ OP_PSHUFW,
+ OP_3B_ESC4,
+ OP_3B_ESC5,
+ OP_PCMPEQB,
+ OP_PCMPEQW,
+ OP_PCMPEQD,
+ OP_PCMPEQQ,
+ OP_SETO,
+ OP_SETNO,
+ OP_SETC,
+ OP_SETNC,
+ OP_SETE,
+ OP_SETNE,
+ OP_SETBE,
+ OP_SETNBE,
+ OP_SETS,
+ OP_SETNS,
+ OP_SETP,
+ OP_SETNP,
+ OP_SETL,
+ OP_SETNL,
+ OP_SETLE,
+ OP_SETNLE,
+ OP_CPUID,
+ OP_BT,
+ OP_SHLD,
+ OP_RSM,
+ OP_BTS,
+ OP_SHRD,
+ OP_GRP15,
+ OP_CMPXCHG,
+ OP_LSS,
+ OP_BTR,
+ OP_LFS,
+ OP_LGS,
+ OP_MOVZX,
+ OP_GRP10_INV,
+ OP_GRP8,
+ OP_BTC,
+ OP_BSF,
+ OP_BSR,
+ OP_MOVSX,
+ OP_XADD,
+ OP_CMPPS,
+ OP_MOVNTI,
+ OP_PINSRW,
+ OP_PEXTRW,
+ OP_SHUFPS,
+ OP_GRP9,
+ OP_BSWAP,
+ OP_ADDSUBPS,
+ OP_ADDSUBPD,
+ OP_PSRLW,
+ OP_PSRLD,
+ OP_PSRLQ,
+ OP_PADDQ,
+ OP_PMULLW,
+ OP_PMOVMSKB,
+ OP_PSUBUSB,
+ OP_PSUBUSW,
+ OP_PMINUB,
+ OP_PAND,
+ OP_PADDUSB,
+ OP_PADDUSW,
+ OP_PMAXUB,
+ OP_PANDN,
+ OP_PAVGB,
+ OP_PSRAW,
+ OP_PSRAD,
+ OP_PAVGW,
+ OP_PMULHUW,
+ OP_PMULHW,
+ OP_MOVNTQ,
+ OP_PSUBSB,
+ OP_PSUBSW,
+ OP_PMINSW,
+ OP_POR,
+ OP_PADDSB,
+ OP_PADDSW,
+ OP_PMAXSW,
+ OP_PXOR,
+ OP_LDDQU,
+ OP_PSLLW,
+ OP_PSLLD,
+ OP_PSSQ,
+ OP_PMULUDQ,
+ OP_PMADDWD,
+ OP_PSADBW,
+ OP_MASKMOVQ,
+ OP_PSUBB,
+ OP_PSUBW,
+ OP_PSUBD,
+ OP_PSUBQ,
+ OP_PADDB,
+ OP_PADDW,
+ OP_PADDD,
+ OP_MOVUPD,
+ OP_MOVLPD,
+ OP_UNPCKLPD,
+ OP_UNPCKHPD,
+ OP_MOVHPD,
+ OP_MOVAPD,
+ OP_CVTPI2PD,
+ OP_MOVNTPD,
+ OP_CVTTPD2PI,
+ OP_CVTPD2PI,
+ OP_UCOMISD,
+ OP_COMISD,
+ OP_MOVMSKPD,
+ OP_SQRTPD,
+ OP_ANDPD,
+ OP_ANDNPD,
+ OP_ORPD,
+ OP_XORPD,
+ OP_ADDPD,
+ OP_MULPD,
+ OP_CVTPD2PS,
+ OP_CVTPS2DQ,
+ OP_SUBPD,
+ OP_MINPD,
+ OP_DIVPD,
+ OP_MAXPD,
+ OP_GRP12,
+ OP_GRP13,
+ OP_GRP14,
+ OP_GRP17,
+ OP_EMMS,
+ OP_MMX_UD78,
+ OP_MMX_UD79,
+ OP_MMX_UD7A,
+ OP_MMX_UD7B,
+ OP_MMX_UD7C,
+ OP_MMX_UD7D,
+ OP_PUNPCKLQDQ,
+ OP_PUNPCKHQDQ,
+ OP_MOVDQA,
+ OP_PSHUFD,
+ OP_CMPPD,
+ OP_SHUFPD,
+ OP_CVTTPD2DQ,
+ OP_MOVNTDQ,
+ OP_MOVNTDQA,
+ OP_PACKUSDW,
+ OP_PSHUFB,
+ OP_PHADDW,
+ OP_PHADDD,
+ OP_PHADDSW,
+ OP_HADDPS,
+ OP_HADDPD,
+ OP_PMADDUBSW,
+ OP_PHSUBW,
+ OP_PHSUBD,
+ OP_PHSUBSW,
+ OP_HSUBPS,
+ OP_HSUBPD,
+ OP_PSIGNB,
+ OP_PSIGNW,
+ OP_PSIGND,
+ OP_PMULHRSW,
+ OP_PERMILPS,
+ OP_PERMILPD,
+ OP_TESTPS,
+ OP_TESTPD,
+ OP_PBLENDVB,
+ OP_CVTPH2PS,
+ OP_BLENDVPS,
+ OP_BLENDVPD,
+ OP_PERMPS,
+ OP_PERMD,
+ OP_PTEST,
+ OP_BROADCASTSS,
+ OP_BROADCASTSD,
+ OP_BROADCASTF128,
+ OP_PABSB,
+ OP_PABSW,
+ OP_PABSD,
+ OP_PMOVSXBW,
+ OP_PMOVSXBD,
+ OP_PMOVSXBQ,
+ OP_PMOVSXWD,
+ OP_PMOVSXWQ,
+ OP_PMOVSXDQ,
+ OP_PMOVZXBW,
+ OP_PMOVZXBD,
+ OP_PMOVZXBQ,
+ OP_PMOVZXWD,
+ OP_PMOVZXWQ,
+ OP_PMOVZXDQ,
+ OP_PMULDQ,
+ OP_PMINSB,
+ OP_PMINSD,
+ OP_PMINUW,
+ OP_PMINUD,
+ OP_PMAXSB,
+ OP_PMAXSD,
+ OP_PMAXUW,
+ OP_PMAXUD,
+ OP_PMULLD,
+ OP_PHMINPOSUW,
+ OP_PSRLVD,
+ OP_PSRAVD,
+ OP_PSLLVD,
+ OP_PBROADCASTD,
+ OP_PBROADCASTQ,
+ OP_PBROADCASTI128,
+ OP_PBROADCASTB,
+ OP_PBROADCASTW,
+ OP_PMASKMOVD,
+ OP_GATHER,
+ OP_FMADDSUB132PS,
+ OP_FMSUBADD132PS,
+ OP_FMADD132PS,
+ OP_FMADD132SS,
+ OP_FMSUB132PS,
+ OP_FMSUB132SS,
+ OP_FNMADD132PS,
+ OP_FNMADD132SS,
+ OP_FNMSUB132PS,
+ OP_FNMSUB132SS,
+ OP_FMADDSUB213PS,
+ OP_FMSUBADD213PS,
+ OP_FMADD213PS,
+ OP_FMADD213SS,
+ OP_FMSUB213PS,
+ OP_FMSUB213SS,
+ OP_FNMADD213PS,
+ OP_FNMADD213SS,
+ OP_FNMSUB213PS,
+ OP_FNMSUB213SS,
+ OP_FMADDSUB231PS,
+ OP_FMSUBADD231PS,
+ OP_FMADD231PS,
+ OP_FMADD231SS,
+ OP_FMSUB231PS,
+ OP_FMSUB231SS,
+ OP_FNMADD231PS,
+ OP_FNMADD231SS,
+ OP_FNMSUB231PS,
+ OP_FNMSUB231SS,
+ OP_AESIMC,
+ OP_AESENC,
+ OP_AESENCLAST,
+ OP_AESDEC,
+ OP_AESDECLAST,
+ OP_MOVBEGM,
+ OP_MOVBEMG,
+ OP_CRC32,
+ OP_POPCNT,
+ OP_TZCNT,
+ OP_LZCNT,
+ OP_ADCX,
+ OP_ADOX,
+ OP_ANDN,
+ OP_BZHI,
+ OP_BEXTR,
+ OP_BLSR,
+ OP_BLSMSK,
+ OP_BLSI,
+ OP_PEXT,
+ OP_PDEP,
+ OP_SHLX,
+ OP_SHRX,
+ OP_SARX,
+ OP_MULX,
+ OP_MASKMOVDQU,
+ OP_MASKMOVPS,
+ OP_MASKMOVPD,
+ OP_MOVSD,
+ OP_CVTSI2SD,
+ OP_CVTTSD2SI,
+ OP_CVTSD2SI,
+ OP_SQRTSD,
+ OP_ADDSD,
+ OP_MULSD,
+ OP_CVTSD2SS,
+ OP_SUBSD,
+ OP_MINSD,
+ OP_DIVSD,
+ OP_MAXSD,
+ OP_PSHUFLW,
+ OP_CMPSD,
+ OP_MOVDQ2Q,
+ OP_CVTPD2DQ,
+ OP_MOVSS,
+ OP_MOVSLDUP,
+ OP_MOVDDUP,
+ OP_MOVSHDUP,
+ OP_CVTSI2SS,
+ OP_CVTTSS2SI,
+ OP_CVTSS2SI,
+ OP_CVTSS2SD,
+ OP_SQRTSS,
+ OP_RSQRTSS,
+ OP_RCPSS,
+ OP_ADDSS,
+ OP_MULSS,
+ OP_CVTTPS2DQ,
+ OP_SUBSS,
+ OP_MINSS,
+ OP_DIVSS,
+ OP_MAXSS,
+ OP_MOVDQU,
+ OP_PSHUFHW,
+ OP_CMPSS,
+ OP_MOVQ2DQ,
+ OP_CVTDQ2PD,
+ OP_PERMQ,
+ OP_PERMPD,
+ OP_PBLENDD,
+ OP_PERM2F128,
+ OP_ROUNDPS,
+ OP_ROUNDPD,
+ OP_ROUNDSS,
+ OP_ROUNDSD,
+ OP_BLENDPS,
+ OP_BLENDPD,
+ OP_PBLENDW,
+ OP_PALIGNR,
+ OP_PEXTRB,
+ OP_PEXTRD,
+ OP_PEXTRQ,
+ OP_EXTRACTPS,
+ OP_INSERTF128,
+ OP_EXTRACTF128,
+ OP_CVTPS2PH,
+ OP_PINSRB,
+ OP_PINSRD,
+ OP_PINSRQ,
+ OP_INSERTPS,
+ OP_INSERTI128,
+ OP_EXTRACTI128,
+ OP_DPPS,
+ OP_DPPD,
+ OP_MPSADBW,
+ OP_PCLMULQDQ,
+ OP_PERM2I128,
+ OP_PCMPESTRM,
+ OP_PCMPESTRI,
+ OP_PCMPISTRM,
+ OP_PCMPISTRI,
+ OP_AESKEYGEN,
+ OP_RORX,
+ OP_RDRAND,
+ OP_RDSEED,
+ OP_MOVBE,
+ OP_VEX3B,
+ OP_VEX2B,
+/** @} */
+
+/** @name Floating point ops
+ * @{ */
+ OP_FADD,
+ OP_FMUL,
+ OP_FCOM,
+ OP_FCOMP,
+ OP_FSUB,
+ OP_FSUBR,
+ OP_FDIV,
+ OP_FDIVR,
+ OP_FLD,
+ OP_FST,
+ OP_FSTP,
+ OP_FLDENV,
+ OP_FSTENV,
+ OP_FSTCW,
+ OP_FXCH,
+ OP_FNOP,
+ OP_FCHS,
+ OP_FABS,
+ OP_FLD1,
+ OP_FLDL2T,
+ OP_FLDL2E,
+ OP_FLDPI,
+ OP_FLDLG2,
+ OP_FLDLN2,
+ OP_FLDZ,
+ OP_F2XM1,
+ OP_FYL2X,
+ OP_FPTAN,
+ OP_FPATAN,
+ OP_FXTRACT,
+ OP_FREM1,
+ OP_FDECSTP,
+ OP_FINCSTP,
+ OP_FPREM,
+ OP_FYL2XP1,
+ OP_FSQRT,
+ OP_FSINCOS,
+ OP_FRNDINT,
+ OP_FSCALE,
+ OP_FSIN,
+ OP_FCOS,
+ OP_FIADD,
+ OP_FIMUL,
+ OP_FISUB,
+ OP_FISUBR,
+ OP_FIDIV,
+ OP_FIDIVR,
+ OP_FCMOVB,
+ OP_FCMOVE,
+ OP_FCMOVBE,
+ OP_FCMOVU,
+ OP_FUCOMPP,
+ OP_FILD,
+ OP_FIST,
+ OP_FISTP,
+ OP_FCMOVNB,
+ OP_FCMOVNE,
+ OP_FCMOVNBE,
+ OP_FCMOVNU,
+ OP_FCLEX,
+ OP_FINIT,
+ OP_FUCOMI,
+ OP_FCOMI,
+ OP_FRSTOR,
+ OP_FSAVE,
+ OP_FNSTSW,
+ OP_FFREE,
+ OP_FUCOM,
+ OP_FUCOMP,
+ OP_FICOM,
+ OP_FICOMP,
+ OP_FADDP,
+ OP_FMULP,
+ OP_FCOMPP,
+ OP_FSUBRP,
+ OP_FSUBP,
+ OP_FDIVRP,
+ OP_FDIVP,
+ OP_FBLD,
+ OP_FBSTP,
+ OP_FCOMIP,
+ OP_FUCOMIP,
+/** @} */
+
+/** @name 3DNow!
+ * @{ */
+ OP_PI2FW,
+ OP_PI2FD,
+ OP_PF2IW,
+ OP_PF2ID,
+ OP_PFPNACC,
+ OP_PFCMPGE,
+ OP_PFMIN,
+ OP_PFRCP,
+ OP_PFRSQRT,
+ OP_PFSUB,
+ OP_PFADD,
+ OP_PFCMPGT,
+ OP_PFMAX,
+ OP_PFRCPIT1,
+ OP_PFRSQRTIT1,
+ OP_PFSUBR,
+ OP_PFACC,
+ OP_PFCMPEQ,
+ OP_PFMUL,
+ OP_PFRCPIT2,
+ OP_PFMULHRW,
+ OP_PFSWAPD,
+ OP_PAVGUSB,
+ OP_PFNACC,
+/** @} */
+ OP_ROL,
+ OP_ROR,
+ OP_RCL,
+ OP_RCR,
+ OP_SHL,
+ OP_SHR,
+ OP_SAR,
+ OP_NOT,
+ OP_NEG,
+ OP_MUL,
+ OP_DIV,
+ OP_IDIV,
+ OP_SLDT,
+ OP_STR,
+ OP_LLDT,
+ OP_LTR,
+ OP_VERR,
+ OP_VERW,
+ OP_SGDT,
+ OP_LGDT,
+ OP_SIDT,
+ OP_LIDT,
+ OP_SMSW,
+ OP_LMSW,
+ OP_INVLPG,
+ OP_CMPXCHG8B,
+ OP_PSLLQ,
+ OP_PSRLDQ,
+ OP_PSLLDQ,
+ OP_FXSAVE,
+ OP_FXRSTOR,
+ OP_LDMXCSR,
+ OP_STMXCSR,
+ OP_XSAVE,
+ OP_XSAVEOPT,
+ OP_XRSTOR,
+ OP_XGETBV,
+ OP_XSETBV,
+ OP_RDFSBASE,
+ OP_RDGSBASE,
+ OP_WRFSBASE,
+ OP_WRGSBASE,
+ OP_LFENCE,
+ OP_MFENCE,
+ OP_SFENCE,
+ OP_PREFETCH,
+ OP_MONITOR,
+ OP_MWAIT,
+ OP_CLFLUSH,
+ OP_CLFLUSHOPT,
+ OP_MOV_DR,
+ OP_MOV_TR,
+ OP_SWAPGS,
+ OP_UD1,
+ OP_UD2,
+/** @name VT-x instructions
+ * @{ */
+ OP_VMREAD,
+ OP_VMWRITE,
+ OP_VMCALL,
+ OP_VMXON,
+ OP_VMXOFF,
+ OP_VMCLEAR,
+ OP_VMLAUNCH,
+ OP_VMRESUME,
+ OP_VMPTRLD,
+ OP_VMPTRST,
+ OP_INVEPT,
+ OP_INVVPID,
+ OP_INVPCID,
+ OP_VMFUNC,
+/** @} */
+/** @name AMD-V instructions
+ * @{ */
+ OP_VMMCALL,
+ OP_VMRUN,
+ OP_VMLOAD,
+ OP_VMSAVE,
+ OP_CLGI,
+ OP_STGI,
+ OP_INVLPGA,
+ OP_SKINIT,
+/** @} */
+/** @name 64 bits instruction
+ * @{ */
+ OP_MOVSXD,
+/** @} */
+/** @name AVX instructions
+ * @{ */
+ /* Manual */
+ OP_VSTMXCSR,
+ OP_VLDMXCSR,
+ OP_VPACKUSDW,
+
+ /* Generated from tables: */
+ OP_VADDPD,
+ OP_VADDPS,
+ OP_VADDSD,
+ OP_VADDSS,
+ OP_VADDSUBPD,
+ OP_VADDSUBPS,
+ OP_VAESDEC,
+ OP_VAESDECLAST,
+ OP_VAESENC,
+ OP_VAESENCLAST,
+ OP_VAESIMC,
+ OP_VAESKEYGEN,
+ OP_VANDNPD,
+ OP_VANDNPS,
+ OP_VANDPD,
+ OP_VANDPS,
+ OP_VBLENDPD,
+ OP_VBLENDPS,
+ OP_VBLENDVPD,
+ OP_VBLENDVPS,
+ OP_VBROADCASTF128,
+ OP_VBROADCASTSD,
+ OP_VBROADCASTSS,
+ OP_VCMPSD,
+ OP_VCMPSS,
+ OP_VCOMISD,
+ OP_VCOMISS,
+ OP_VCVTDQ2PD,
+ OP_VCVTDQ2PS,
+ OP_VCVTPD2DQ,
+ OP_VCVTPD2PS,
+ OP_VCVTPH2PS,
+ OP_VCVTPS2DQ,
+ OP_VCVTPS2PD,
+ OP_VCVTPS2PH,
+ OP_VCVTSD2SS,
+ OP_VCVTSI2SS,
+ OP_VCVTSS2SD,
+ OP_VCVTSS2SI,
+ OP_VCVTTPD2DQ,
+ OP_VCVTTPS2DQ,
+ OP_VCVTTSS2SI,
+ OP_VDIVPD,
+ OP_VDIVPS,
+ OP_VDIVSD,
+ OP_VDIVSS,
+ OP_VDPPD,
+ OP_VDPPS,
+ OP_VEXTRACTF128,
+ OP_VEXTRACTI128,
+ OP_VEXTRACTPS,
+ OP_VFMADD132PS,
+ OP_VFMADD132SS,
+ OP_VFMADD213PS,
+ OP_VFMADD213SS,
+ OP_VFMADD231PS,
+ OP_VFMADD231SS,
+ OP_VFMADDSUB132PS,
+ OP_VFMADDSUB213PS,
+ OP_VFMADDSUB231PS,
+ OP_VFMSUB132PS,
+ OP_VFMSUB132SS,
+ OP_VFMSUB213PS,
+ OP_VFMSUB213SS,
+ OP_VFMSUB231PS,
+ OP_VFMSUB231SS,
+ OP_VFMSUBADD132PS,
+ OP_VFMSUBADD213PS,
+ OP_VFMSUBADD231PS,
+ OP_VFNMADD132PS,
+ OP_VFNMADD132SS,
+ OP_VFNMADD213PS,
+ OP_VFNMADD213SS,
+ OP_VFNMADD231PS,
+ OP_VFNMADD231SS,
+ OP_VFNMSUB132PS,
+ OP_VFNMSUB132SS,
+ OP_VFNMSUB213PS,
+ OP_VFNMSUB213SS,
+ OP_VFNMSUB231PS,
+ OP_VFNMSUB231SS,
+ OP_VGATHER,
+ OP_VHADDPD,
+ OP_VHADDPS,
+ OP_VHSUBPD,
+ OP_VHSUBPS,
+ OP_VINSERTF128,
+ OP_VINSERTI128,
+ OP_VINSERTPS,
+ OP_VLDDQU,
+ OP_VMASKMOVDQU,
+ OP_VMASKMOVPD,
+ OP_VMASKMOVPS,
+ OP_VMAXPD,
+ OP_VMAXPS,
+ OP_VMAXSD,
+ OP_VMAXSS,
+ OP_VMINPD,
+ OP_VMINPS,
+ OP_VMINSD,
+ OP_VMINSS,
+ OP_VMOVAPD,
+ OP_VMOVAPS,
+ OP_VMOVD,
+ OP_VMOVDDUP,
+ OP_VMOVDQA,
+ OP_VMOVDQU,
+ OP_VMOVHPD,
+ OP_VMOVHPS,
+ OP_VMOVLHPS = OP_VMOVHPS, /**< @todo OP_VMOVHPS */
+ OP_VMOVLPD,
+ OP_VMOVLPS,
+ OP_VMOVHLPS = OP_VMOVLPS, /**< @todo OP_VMOVLPS */
+ OP_VMOVMSKPD,
+ OP_VMOVMSKPS,
+ OP_VMOVNTDQ,
+ OP_VMOVNTDQA,
+ OP_VMOVNTPD,
+ OP_VMOVNTPS,
+ OP_VMOVQ,
+ OP_VMOVSD,
+ OP_VMOVSHDUP,
+ OP_VMOVSLDUP,
+ OP_VMOVSS,
+ OP_VMOVUPD,
+ OP_VMOVUPS,
+ OP_VMPSADBW,
+ OP_VMULPD,
+ OP_VMULPS,
+ OP_VMULSD,
+ OP_VMULSS,
+ OP_VORPD,
+ OP_VORPS,
+ OP_VPABSB,
+ OP_VPABSD,
+ OP_VPABSW,
+ OP_VPACKSSDW,
+ OP_VPACKSSWB,
+ OP_VPACKUSWB,
+ OP_VPADDB,
+ OP_VPADDD,
+ OP_VPADDQ,
+ OP_VPADDSB,
+ OP_VPADDSW,
+ OP_VPADDUSB,
+ OP_VPADDUSW,
+ OP_VPADDW,
+ OP_VPALIGNR,
+ OP_VPAND,
+ OP_VPANDN,
+ OP_VPAVGB,
+ OP_VPAVGW,
+ OP_VPBLENDD,
+ OP_VPBLENDVB,
+ OP_VPBLENDW,
+ OP_VPBROADCASTB,
+ OP_VPBROADCASTD,
+ OP_VPBROADCASTI128,
+ OP_VPBROADCASTQ,
+ OP_VPBROADCASTW,
+ OP_VPCLMULQDQ,
+ OP_VPCMPEQB,
+ OP_VPCMPEQD,
+ OP_VPCMPEQQ,
+ OP_VPCMPEQW,
+ OP_VPCMPESTRI,
+ OP_VPCMPESTRM,
+ OP_VPCMPGTB,
+ OP_VPCMPGTD,
+ OP_VPCMPGTQ,
+ OP_VPCMPGTW,
+ OP_VPCMPISTRI,
+ OP_VPCMPISTRM,
+ OP_VPERM2F128,
+ OP_VPERM2I128,
+ OP_VPERMD,
+ OP_VPERMILPD,
+ OP_VPERMILPS,
+ OP_VPERMPD,
+ OP_VPERMPS,
+ OP_VPERMQ,
+ OP_VPEXTRB,
+ OP_VPEXTRD,
+ OP_VPEXTRW,
+ OP_VPEXTRQ,
+ OP_VPHADDD,
+ OP_VPHADDSW,
+ OP_VPHADDW,
+ OP_VPHMINPOSUW,
+ OP_VPHSUBD,
+ OP_VPHSUBSW,
+ OP_VPHSUBW,
+ OP_VPINSRB,
+ OP_VPINSRD,
+ OP_VPINSRW,
+ OP_VPINSRQ,
+ OP_VPMADDUBSW,
+ OP_VPMADDWD,
+ OP_VPMASKMOVD,
+ OP_VPMAXSB,
+ OP_VPMAXSD,
+ OP_VPMAXSW,
+ OP_VPMAXUB,
+ OP_VPMAXUD,
+ OP_VPMAXUW,
+ OP_VPMINSB,
+ OP_VPMINSD,
+ OP_VPMINSW,
+ OP_VPMINUB,
+ OP_VPMINUD,
+ OP_VPMINUW,
+ OP_VPMOVMSKB,
+ OP_VPMOVSXBW,
+ OP_VPMOVSXBD,
+ OP_VPMOVSXBQ,
+ OP_VPMOVSXWD,
+ OP_VPMOVSXWQ,
+ OP_VPMOVSXDQ,
+ OP_VPMOVZXBW,
+ OP_VPMOVZXBD,
+ OP_VPMOVZXBQ,
+ OP_VPMOVZXWD,
+ OP_VPMOVZXWQ,
+ OP_VPMOVZXDQ,
+ OP_VPMULDQ,
+ OP_VPMULHRSW,
+ OP_VPMULHUW,
+ OP_VPMULHW,
+ OP_VPMULLD,
+ OP_VPMULLW,
+ OP_VPMULUDQ,
+ OP_VPOR,
+ OP_VPSADBW,
+ OP_VPSHUFB,
+ OP_VPSHUFD,
+ OP_VPSHUFHW,
+ OP_VPSHUFLW,
+ OP_VPSIGNB,
+ OP_VPSIGND,
+ OP_VPSIGNW,
+ OP_VPSLLD,
+ OP_VPSLLQ,
+ OP_VPSLLVD,
+ OP_VPSLLW,
+ OP_VPSRAD,
+ OP_VPSRAVD,
+ OP_VPSRAW,
+ OP_VPSRLD,
+ OP_VPSRLQ,
+ OP_VPSRLVD,
+ OP_VPSRLW,
+ OP_VPSUBB,
+ OP_VPSUBD,
+ OP_VPSUBQ,
+ OP_VPSUBSB,
+ OP_VPSUBSW,
+ OP_VPSUBUSB,
+ OP_VPSUBUSW,
+ OP_VPSUBW,
+ OP_VPTEST,
+ OP_VPUNPCKHBW,
+ OP_VPUNPCKHDQ,
+ OP_VPUNPCKHQDQ,
+ OP_VPUNPCKHWD,
+ OP_VPUNPCKLBW,
+ OP_VPUNPCKLDQ,
+ OP_VPUNPCKLQDQ,
+ OP_VPUNPCKLWD,
+ OP_VPXOR,
+ OP_VRCPPS,
+ OP_VRCPSS,
+ OP_VROUNDPD,
+ OP_VROUNDPS,
+ OP_VROUNDSD,
+ OP_VROUNDSS,
+ OP_VRSQRTPS,
+ OP_VRSQRTSS,
+ OP_VSHUFPD,
+ OP_VSHUFPS,
+ OP_VSQRTPD,
+ OP_VSQRTPS,
+ OP_VSQRTSD,
+ OP_VSQRTSS,
+ OP_VSUBPD,
+ OP_VSUBPS,
+ OP_VSUBSD,
+ OP_VSUBSS,
+ OP_VTESTPD,
+ OP_VTESTPS,
+ OP_VUCOMISD,
+ OP_VUCOMISS,
+ OP_VUNPCKHPD,
+ OP_VUNPCKHPS,
+ OP_VUNPCKLPD,
+ OP_VUNPCKLPS,
+ OP_VVPACKUSDW,
+ OP_VXORPD,
+ OP_VXORPS,
+ OP_VZEROALL,
+
+/** @} */
+ OP_END_OF_OPCODES
+};
+AssertCompile(OP_LOCK == 7);
+#if 0
+AssertCompile(OP_END_OF_OPCODES < 1024 /* see 15 byte DISOPCODE variant */);
+#endif
+/** @} */
+
+
+/** @defgroup grp_dis_opparam Opcode parameters (DISOPCODE::fParam1,
+ * DISOPCODE::fParam2, DISOPCODE::fParam3)
+ * @ingroup grp_dis
+ * @{
+ */
+
+/**
+ * @remarks Register order is important for translations!!
+ */
+enum OP_PARM
+{
+ OP_PARM_NONE,
+
+ OP_PARM_REG_EAX,
+ OP_PARM_REG_GEN32_START = OP_PARM_REG_EAX,
+ OP_PARM_REG_ECX,
+ OP_PARM_REG_EDX,
+ OP_PARM_REG_EBX,
+ OP_PARM_REG_ESP,
+ OP_PARM_REG_EBP,
+ OP_PARM_REG_ESI,
+ OP_PARM_REG_EDI,
+ OP_PARM_REG_GEN32_END = OP_PARM_REG_EDI,
+
+ OP_PARM_REG_ES,
+ OP_PARM_REG_SEG_START = OP_PARM_REG_ES,
+ OP_PARM_REG_CS,
+ OP_PARM_REG_SS,
+ OP_PARM_REG_DS,
+ OP_PARM_REG_FS,
+ OP_PARM_REG_GS,
+ OP_PARM_REG_SEG_END = OP_PARM_REG_GS,
+
+ OP_PARM_REG_AX,
+ OP_PARM_REG_GEN16_START = OP_PARM_REG_AX,
+ OP_PARM_REG_CX,
+ OP_PARM_REG_DX,
+ OP_PARM_REG_BX,
+ OP_PARM_REG_SP,
+ OP_PARM_REG_BP,
+ OP_PARM_REG_SI,
+ OP_PARM_REG_DI,
+ OP_PARM_REG_GEN16_END = OP_PARM_REG_DI,
+
+ OP_PARM_REG_AL,
+ OP_PARM_REG_GEN8_START = OP_PARM_REG_AL,
+ OP_PARM_REG_CL,
+ OP_PARM_REG_DL,
+ OP_PARM_REG_BL,
+ OP_PARM_REG_AH,
+ OP_PARM_REG_CH,
+ OP_PARM_REG_DH,
+ OP_PARM_REG_BH,
+ OP_PARM_REG_GEN8_END = OP_PARM_REG_BH,
+
+ OP_PARM_REGFP_0,
+ OP_PARM_REG_FP_START = OP_PARM_REGFP_0,
+ OP_PARM_REGFP_1,
+ OP_PARM_REGFP_2,
+ OP_PARM_REGFP_3,
+ OP_PARM_REGFP_4,
+ OP_PARM_REGFP_5,
+ OP_PARM_REGFP_6,
+ OP_PARM_REGFP_7,
+ OP_PARM_REG_FP_END = OP_PARM_REGFP_7,
+
+ OP_PARM_NTA,
+ OP_PARM_T0,
+ OP_PARM_T1,
+ OP_PARM_T2,
+ OP_PARM_1,
+
+ OP_PARM_REX,
+ OP_PARM_REX_START = OP_PARM_REX,
+ OP_PARM_REX_B,
+ OP_PARM_REX_X,
+ OP_PARM_REX_XB,
+ OP_PARM_REX_R,
+ OP_PARM_REX_RB,
+ OP_PARM_REX_RX,
+ OP_PARM_REX_RXB,
+ OP_PARM_REX_W,
+ OP_PARM_REX_WB,
+ OP_PARM_REX_WX,
+ OP_PARM_REX_WXB,
+ OP_PARM_REX_WR,
+ OP_PARM_REX_WRB,
+ OP_PARM_REX_WRX,
+ OP_PARM_REX_WRXB,
+
+ OP_PARM_REG_RAX,
+ OP_PARM_REG_GEN64_START = OP_PARM_REG_RAX,
+ OP_PARM_REG_RCX,
+ OP_PARM_REG_RDX,
+ OP_PARM_REG_RBX,
+ OP_PARM_REG_RSP,
+ OP_PARM_REG_RBP,
+ OP_PARM_REG_RSI,
+ OP_PARM_REG_RDI,
+ OP_PARM_REG_R8,
+ OP_PARM_REG_R9,
+ OP_PARM_REG_R10,
+ OP_PARM_REG_R11,
+ OP_PARM_REG_R12,
+ OP_PARM_REG_R13,
+ OP_PARM_REG_R14,
+ OP_PARM_REG_R15,
+ OP_PARM_REG_GEN64_END = OP_PARM_REG_R15
+};
+
+
+/* 8-bit GRP aliases (for IEM). */
+#define OP_PARM_AL OP_PARM_REG_AL
+
+/* GPR aliases for op-size specified register sizes (for IEM). */
+#define OP_PARM_rAX OP_PARM_REG_EAX
+#define OP_PARM_rCX OP_PARM_REG_ECX
+#define OP_PARM_rDX OP_PARM_REG_EDX
+#define OP_PARM_rBX OP_PARM_REG_EBX
+#define OP_PARM_rSP OP_PARM_REG_ESP
+#define OP_PARM_rBP OP_PARM_REG_EBP
+#define OP_PARM_rSI OP_PARM_REG_ESI
+#define OP_PARM_rDI OP_PARM_REG_EDI
+
+/* SREG aliases (for IEM). */
+#define OP_PARM_ES OP_PARM_REG_ES
+#define OP_PARM_CS OP_PARM_REG_CS
+#define OP_PARM_SS OP_PARM_REG_SS
+#define OP_PARM_DS OP_PARM_REG_DS
+#define OP_PARM_FS OP_PARM_REG_FS
+#define OP_PARM_GS OP_PARM_REG_GS
+
+/*
+ * Note! We don't document anything here if we can help it, because it we love
+ * wasting other peoples time figuring out crypting crap. The new VEX
+ * stuff of course uphelds this vexing tradition. Aaaaaaaaaaaaaaaaaaarg!
+ */
+
+#define OP_PARM_VTYPE(a) ((unsigned)a & 0xFE0)
+#define OP_PARM_VSUBTYPE(a) ((unsigned)a & 0x01F)
+
+#define OP_PARM_A 0x100
+#define OP_PARM_VARIABLE OP_PARM_A
+#define OP_PARM_E 0x120
+#define OP_PARM_F 0x140
+#define OP_PARM_G 0x160
+#define OP_PARM_I 0x180
+#define OP_PARM_J 0x1A0
+#define OP_PARM_M 0x1C0
+#define OP_PARM_O 0x1E0
+#define OP_PARM_R 0x200
+#define OP_PARM_X 0x220
+#define OP_PARM_Y 0x240
+
+/* Grouped rare parameters for optimization purposes */
+#define IS_OP_PARM_RARE(a) ((a & 0xF00) >= 0x300)
+#define OP_PARM_C 0x300 /* control register */
+#define OP_PARM_D 0x320 /* debug register */
+#define OP_PARM_S 0x340 /* segment register */
+#define OP_PARM_T 0x360 /* test register */
+#define OP_PARM_Q 0x380
+#define OP_PARM_P 0x3A0 /* mmx register */
+#define OP_PARM_W 0x3C0 /* xmm register */
+#define OP_PARM_V 0x3E0
+#define OP_PARM_U 0x400 /* The R/M field of the ModR/M byte selects XMM/YMM register. */
+#define OP_PARM_B 0x420 /* VEX.vvvv field select general purpose register. */
+#define OP_PARM_H 0x440
+#define OP_PARM_L 0x460
+
+#define OP_PARM_NONE 0
+#define OP_PARM_a 0x1 /**< Operand to bound instruction. */
+#define OP_PARM_b 0x2 /**< Byte (always). */
+#define OP_PARM_d 0x3 /**< Double word (always). */
+#define OP_PARM_dq 0x4 /**< Double quad word (always). */
+#define OP_PARM_p 0x5 /**< Far pointer (subject to opsize). */
+#define OP_PARM_pd 0x6 /**< 128-bit or 256-bit double precision floating point data. */
+#define OP_PARM_pi 0x7 /**< Quad word MMX register. */
+#define OP_PARM_ps 0x8 /**< 128-bit or 256-bit single precision floating point data. */
+#define OP_PARM_q 0xA /**< Quad word (always). */
+#define OP_PARM_s 0xB /**< Descriptor table size (SIDT/LIDT/SGDT/LGDT). */
+#define OP_PARM_sd 0xC /**< Scalar element of 128-bit double precision floating point data. */
+#define OP_PARM_ss 0xD /**< Scalar element of 128-bit single precision floating point data. */
+#define OP_PARM_v 0xE /**< Word, double word, or quad word depending on opsize. */
+#define OP_PARM_w 0xF /**< Word (always). */
+#define OP_PARM_x 0x10 /**< Double quad word (dq) or quad quad word (qq) depending on opsize. */
+#define OP_PARM_y 0x11 /**< Double word or quad word depending on opsize. */
+#define OP_PARM_z 0x12 /**< Word (16-bit opsize) or double word (32-bit/64-bit opsize). */
+#define OP_PARM_qq 0x13 /**< Quad quad word. */
+
+
+#define OP_PARM_Ap (OP_PARM_A+OP_PARM_p)
+#define OP_PARM_By (OP_PARM_B+OP_PARM_y)
+#define OP_PARM_Cd (OP_PARM_C+OP_PARM_d)
+#define OP_PARM_Dd (OP_PARM_D+OP_PARM_d)
+#define OP_PARM_Eb (OP_PARM_E+OP_PARM_b)
+#define OP_PARM_Ed (OP_PARM_E+OP_PARM_d)
+#define OP_PARM_Ep (OP_PARM_E+OP_PARM_p)
+#define OP_PARM_Ev (OP_PARM_E+OP_PARM_v)
+#define OP_PARM_Ew (OP_PARM_E+OP_PARM_w)
+#define OP_PARM_Ey (OP_PARM_E+OP_PARM_y)
+#define OP_PARM_Fv (OP_PARM_F+OP_PARM_v)
+#define OP_PARM_Gb (OP_PARM_G+OP_PARM_b)
+#define OP_PARM_Gd (OP_PARM_G+OP_PARM_d)
+#define OP_PARM_Gv (OP_PARM_G+OP_PARM_v)
+#define OP_PARM_Gw (OP_PARM_G+OP_PARM_w)
+#define OP_PARM_Gy (OP_PARM_G+OP_PARM_y)
+#define OP_PARM_Hq (OP_PARM_H+OP_PARM_q)
+#define OP_PARM_Hps (OP_PARM_H+OP_PARM_ps)
+#define OP_PARM_Hpd (OP_PARM_H+OP_PARM_pd)
+#define OP_PARM_Hdq (OP_PARM_H+OP_PARM_dq)
+#define OP_PARM_Hqq (OP_PARM_H+OP_PARM_qq)
+#define OP_PARM_Hsd (OP_PARM_H+OP_PARM_sd)
+#define OP_PARM_Hss (OP_PARM_H+OP_PARM_ss)
+#define OP_PARM_Hx (OP_PARM_H+OP_PARM_x)
+#define OP_PARM_Ib (OP_PARM_I+OP_PARM_b)
+#define OP_PARM_Id (OP_PARM_I+OP_PARM_d)
+#define OP_PARM_Iq (OP_PARM_I+OP_PARM_q)
+#define OP_PARM_Iw (OP_PARM_I+OP_PARM_w)
+#define OP_PARM_Iv (OP_PARM_I+OP_PARM_v)
+#define OP_PARM_Iz (OP_PARM_I+OP_PARM_z)
+#define OP_PARM_Jb (OP_PARM_J+OP_PARM_b)
+#define OP_PARM_Jv (OP_PARM_J+OP_PARM_v)
+#define OP_PARM_Ma (OP_PARM_M+OP_PARM_a)
+#define OP_PARM_Mb (OP_PARM_M+OP_PARM_b)
+#define OP_PARM_Mw (OP_PARM_M+OP_PARM_w)
+#define OP_PARM_Md (OP_PARM_M+OP_PARM_d)
+#define OP_PARM_Mp (OP_PARM_M+OP_PARM_p)
+#define OP_PARM_Mq (OP_PARM_M+OP_PARM_q)
+#define OP_PARM_Mdq (OP_PARM_M+OP_PARM_dq)
+#define OP_PARM_Ms (OP_PARM_M+OP_PARM_s)
+#define OP_PARM_Mx (OP_PARM_M+OP_PARM_x)
+#define OP_PARM_My (OP_PARM_M+OP_PARM_y)
+#define OP_PARM_Mps (OP_PARM_M+OP_PARM_ps)
+#define OP_PARM_Mpd (OP_PARM_M+OP_PARM_pd)
+#define OP_PARM_Ob (OP_PARM_O+OP_PARM_b)
+#define OP_PARM_Ov (OP_PARM_O+OP_PARM_v)
+#define OP_PARM_Pq (OP_PARM_P+OP_PARM_q)
+#define OP_PARM_Pd (OP_PARM_P+OP_PARM_d)
+#define OP_PARM_Qd (OP_PARM_Q+OP_PARM_d)
+#define OP_PARM_Qq (OP_PARM_Q+OP_PARM_q)
+#define OP_PARM_Rd (OP_PARM_R+OP_PARM_d)
+#define OP_PARM_Rw (OP_PARM_R+OP_PARM_w)
+#define OP_PARM_Ry (OP_PARM_R+OP_PARM_y)
+#define OP_PARM_Sw (OP_PARM_S+OP_PARM_w)
+#define OP_PARM_Td (OP_PARM_T+OP_PARM_d)
+#define OP_PARM_Ux (OP_PARM_U+OP_PARM_x)
+#define OP_PARM_Vq (OP_PARM_V+OP_PARM_q)
+#define OP_PARM_Vx (OP_PARM_V+OP_PARM_x)
+#define OP_PARM_Vy (OP_PARM_V+OP_PARM_y)
+#define OP_PARM_Wq (OP_PARM_W+OP_PARM_q)
+/*#define OP_PARM_Ws (OP_PARM_W+OP_PARM_s) - wtf? Same as lgdt (OP_PARM_Ms)?*/
+#define OP_PARM_Wx (OP_PARM_W+OP_PARM_x)
+#define OP_PARM_Xb (OP_PARM_X+OP_PARM_b)
+#define OP_PARM_Xv (OP_PARM_X+OP_PARM_v)
+#define OP_PARM_Yb (OP_PARM_Y+OP_PARM_b)
+#define OP_PARM_Yv (OP_PARM_Y+OP_PARM_v)
+
+#define OP_PARM_Vps (OP_PARM_V+OP_PARM_ps)
+#define OP_PARM_Vss (OP_PARM_V+OP_PARM_ss)
+#define OP_PARM_Vpd (OP_PARM_V+OP_PARM_pd)
+#define OP_PARM_Vdq (OP_PARM_V+OP_PARM_dq)
+#define OP_PARM_Wps (OP_PARM_W+OP_PARM_ps)
+#define OP_PARM_Wpd (OP_PARM_W+OP_PARM_pd)
+#define OP_PARM_Wss (OP_PARM_W+OP_PARM_ss)
+#define OP_PARM_Ww (OP_PARM_W+OP_PARM_w)
+#define OP_PARM_Wd (OP_PARM_W+OP_PARM_d)
+#define OP_PARM_Wq (OP_PARM_W+OP_PARM_q)
+#define OP_PARM_Wdq (OP_PARM_W+OP_PARM_dq)
+#define OP_PARM_Wqq (OP_PARM_W+OP_PARM_qq)
+#define OP_PARM_Ppi (OP_PARM_P+OP_PARM_pi)
+#define OP_PARM_Qpi (OP_PARM_Q+OP_PARM_pi)
+#define OP_PARM_Qdq (OP_PARM_Q+OP_PARM_dq)
+#define OP_PARM_Vsd (OP_PARM_V+OP_PARM_sd)
+#define OP_PARM_Wsd (OP_PARM_W+OP_PARM_sd)
+#define OP_PARM_Vqq (OP_PARM_V+OP_PARM_qq)
+#define OP_PARM_Pdq (OP_PARM_P+OP_PARM_dq)
+#define OP_PARM_Ups (OP_PARM_U+OP_PARM_ps)
+#define OP_PARM_Upd (OP_PARM_U+OP_PARM_pd)
+#define OP_PARM_Udq (OP_PARM_U+OP_PARM_dq)
+#define OP_PARM_Lx (OP_PARM_L+OP_PARM_x)
+
+/* For making IEM / bs3-cpu-generated-1 happy: */
+#define OP_PARM_Ed_WO OP_PARM_Ed /**< Annotates write only operand. */
+#define OP_PARM_Eq (OP_PARM_E+OP_PARM_q)
+#define OP_PARM_Eq_WO OP_PARM_Eq /**< Annotates write only operand. */
+#define OP_PARM_Gv_RO OP_PARM_Gv /**< Annotates read only first operand (default is readwrite). */
+#define OP_PARM_HssHi OP_PARM_Hx /**< Register referenced by VEX.vvvv, bits [127:32]. */
+#define OP_PARM_HsdHi OP_PARM_Hx /**< Register referenced by VEX.vvvv, bits [127:64]. */
+#define OP_PARM_HqHi OP_PARM_Hx /**< Register referenced by VEX.vvvv, bits [127:64]. */
+#define OP_PARM_M_RO OP_PARM_M /**< Annotates read only memory of variable operand size (xrstor). */
+#define OP_PARM_M_RW OP_PARM_M /**< Annotates read-write memory of variable operand size (xsave). */
+#define OP_PARM_Mb_RO OP_PARM_Mb /**< Annotates read only memory byte operand. */
+#define OP_PARM_Md_RO OP_PARM_Md /**< Annotates read only memory operand. */
+#define OP_PARM_Md_WO OP_PARM_Md /**< Annotates write only memory operand. */
+#define OP_PARM_Mdq_WO OP_PARM_Mdq /**< Annotates write only memory operand. */
+#define OP_PARM_Mq_WO OP_PARM_Mq /**< Annotates write only memory quad word operand. */
+#define OP_PARM_Mps_WO OP_PARM_Mps /**< Annotates write only memory operand. */
+#define OP_PARM_Mpd_WO OP_PARM_Mpd /**< Annotates write only memory operand. */
+#define OP_PARM_Mx_WO OP_PARM_Mx /**< Annotates write only memory operand. */
+#define OP_PARM_PdZx_WO OP_PARM_Pd /**< Annotates write only operand and zero extends to 64-bit. */
+#define OP_PARM_Pq_WO OP_PARM_Pq /**< Annotates write only operand. */
+#define OP_PARM_Qq_WO OP_PARM_Qq /**< Annotates write only operand. */
+#define OP_PARM_Nq OP_PARM_Qq /**< Missing 'N' class (MMX reg selected by modrm.mem) in disasm. */
+#define OP_PARM_Uq (OP_PARM_U+OP_PARM_q)
+#define OP_PARM_UqHi (OP_PARM_U+OP_PARM_dq)
+#define OP_PARM_Uss (OP_PARM_U+OP_PARM_ss)
+#define OP_PARM_Uss_WO OP_PARM_Uss /**< Annotates write only operand. */
+#define OP_PARM_Usd (OP_PARM_U+OP_PARM_sd)
+#define OP_PARM_Usd_WO OP_PARM_Usd /**< Annotates write only operand. */
+#define OP_PARM_Vd (OP_PARM_V+OP_PARM_d)
+#define OP_PARM_Vd_WO OP_PARM_Vd /**< Annotates write only operand. */
+#define OP_PARM_VdZx_WO OP_PARM_Vd /**< Annotates that the registers get their upper bits cleared */
+#define OP_PARM_Vdq_WO OP_PARM_Vdq /**< Annotates that only YMM/XMM[127:64] are accessed. */
+#define OP_PARM_Vpd_WO OP_PARM_Vpd /**< Annotates write only operand. */
+#define OP_PARM_Vps_WO OP_PARM_Vps /**< Annotates write only operand. */
+#define OP_PARM_Vq_WO OP_PARM_Vq /**< Annotates write only operand. */
+#define OP_PARM_VqHi OP_PARM_Vdq /**< Annotates that only YMM/XMM[127:64] are accessed. */
+#define OP_PARM_VqHi_WO OP_PARM_Vdq /**< Annotates that only YMM/XMM[127:64] are written. */
+#define OP_PARM_VqZx_WO OP_PARM_Vq /**< Annotates that the registers get their upper bits cleared */
+#define OP_PARM_VsdZx_WO OP_PARM_Vsd /**< Annotates that the registers get their upper bits cleared. */
+#define OP_PARM_VssZx_WO OP_PARM_Vss /**< Annotates that the registers get their upper bits cleared. */
+#define OP_PARM_Vss_WO OP_PARM_Vss /**< Annotates write only operand. */
+#define OP_PARM_Vsd_WO OP_PARM_Vsd /**< Annotates write only operand. */
+#define OP_PARM_Vx_WO OP_PARM_Vx /**< Annotates write only operand. */
+#define OP_PARM_Wpd_WO OP_PARM_Wpd /**< Annotates write only operand. */
+#define OP_PARM_Wps_WO OP_PARM_Wps /**< Annotates write only operand. */
+#define OP_PARM_Wq_WO OP_PARM_Wq /**< Annotates write only operand. */
+#define OP_PARM_WqZxReg_WO OP_PARM_Wq /**< Annotates that register targets get their upper bits cleared. */
+#define OP_PARM_Wss_WO OP_PARM_Wss /**< Annotates write only operand. */
+#define OP_PARM_Wsd_WO OP_PARM_Wsd /**< Annotates write only operand. */
+#define OP_PARM_Wx_WO OP_PARM_Wx /**< Annotates write only operand. */
+
+/** @} */
+
+#endif /* !VBOX_INCLUDED_disopcode_h */
+
diff --git a/include/VBox/err.h b/include/VBox/err.h
new file mode 100644
index 00000000..983d9454
--- /dev/null
+++ b/include/VBox/err.h
@@ -0,0 +1,3148 @@
+/** @file
+ * VirtualBox Status Codes.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_err_h
+#define VBOX_INCLUDED_err_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#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)
+/** Essential fields in the shared VM structure doesn't match the global one. */
+#define VERR_INCONSISTENT_VM_HANDLE (-1024)
+/** The VM has been restored. */
+#define VERR_VM_RESTORED (-1025)
+/** The requested feature is not supported by NEM. */
+#define VERR_NOT_SUP_BY_NEM (-1026)
+/** @} */
+
+
+/** @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 (HM/NEM).
+ * 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
+/** 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)
+/** Reason for leaving RZ: Pending ring-3 IN instruction. */
+#define VINF_EM_PENDING_R3_IOPORT_READ 1159
+/** Reason for leaving RZ: Pending ring-3 OUT instruction. */
+#define VINF_EM_PENDING_R3_IOPORT_WRITE 1160
+/** Trick for resuming EMHistoryExec after a VMCPU_FF_IOM is handled. */
+#define VINF_EM_RESUME_R3_HISTORY_EXEC 1161
+/** Emulate split-lock access on SMP. */
+#define VINF_EM_EMULATE_SPLIT_LOCK 1162
+/** @} */
+
+
+/** @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 VM or CPU that was already halted. */
+#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)
+/** Internal processing error \#1 in the DBGF event tracing code. */
+#define VERR_DBGF_TRACER_IPE_1 (-1221)
+/** Tried to resume a VM or CPU that is already fully running. */
+#define VWRN_DBGF_ALREADY_RUNNING (-1222)
+/** Internal processing error \#1 in the DBGF core code. */
+#define VERR_DBGF_IPE_1 (-1223)
+/** Returned by a breakpoint callback when guest execution should be suspended
+ * and the VM should be dropped into the debugger. */
+#define VINF_DBGF_BP_HALT (1224)
+/** The breakpoint owner handle is still used by one or more breakpoints. */
+#define VERR_DBGF_OWNER_BUSY (-1225)
+/** Number of tries to add an int3 breakpoint table to the lookup tables reached. */
+#define VERR_DBGF_BP_INT3_ADD_TRIES_REACHED (-1226)
+/** Internal processing error \#1 in the DBGF breakpoint manager code. */
+#define VERR_DBGF_BP_IPE_1 (-1227)
+/** Internal processing error \#2 in the DBGF breakpoint manager code. */
+#define VERR_DBGF_BP_IPE_2 (-1228)
+/** Internal processing error \#3 in the DBGF breakpoint manager code. */
+#define VERR_DBGF_BP_IPE_3 (-1229)
+/** Internal processing error \#4 in the DBGF breakpoint manager code. */
+#define VERR_DBGF_BP_IPE_4 (-1230)
+/** Internal processing error \#5 in the DBGF breakpoint manager code. */
+#define VERR_DBGF_BP_IPE_5 (-1231)
+/** Internal processing error \#6 in the DBGF breakpoint manager code. */
+#define VERR_DBGF_BP_IPE_6 (-1232)
+/** Internal processing error \#7 in the DBGF breakpoint manager code. */
+#define VERR_DBGF_BP_IPE_7 (-1233)
+/** Internal processing error \#8 in the DBGF breakpoint manager code. */
+#define VERR_DBGF_BP_IPE_8 (-1234)
+/** Internal processing error \#9 in the DBGF breakpoint manager code. */
+#define VERR_DBGF_BP_IPE_9 (-1235)
+/** Level 2 lookup failed because the L1 lookup table is corrupted. */
+#define VERR_DBGF_BP_L1_LOOKUP_FAILED (-1236)
+/** Level 2 lookup failed because the L2 lookup table is corrupted. */
+#define VERR_DBGF_BP_L2_LOOKUP_FAILED (-1237)
+/** The DBGF has no more free breakpoint owner handles. */
+#define VERR_DBGF_BP_OWNER_NO_MORE_HANDLES (-1238)
+/** Reason for leaving RZ: Defer the owner callback invocation to Ring-3. */
+#define VINF_DBGF_R3_BP_OWNER_DEFER 1239
+/** The breakpoint owner callback returned an invalid status code. */
+#define VERR_DBGF_BP_OWNER_CALLBACK_WRONG_STATUS (-1240)
+/** The operation was cancelled. */
+#define VERR_DBGF_CANCELLED (-1241)
+/** @} */
+
+
+/** @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 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
+/** 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)
+/** Mode table internal error. */
+#define VERR_PGM_MODE_IPE (-1686)
+/** Shadow mode 'none' internal error. */
+#define VERR_PGM_SHW_NONE_IPE (-1687)
+/** One or more PAE PDPEs are invalid due to reserved bits being set. */
+#define VERR_PGM_PAE_PDPE_RSVD (-1688)
+/** Attemted illegal operation in simplified memory management mode. */
+#define VERR_PGM_NOT_SUPPORTED_FOR_NEM_MODE (-1689)
+/** @} */
+
+
+/** @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)
+/** Invalid/unsupported nested hardware virtualization configuration. */
+#define VERR_CPUM_INVALID_HWVIRT_CONFIG (-1767)
+/** Invalid nested hardware virtualization feature combination. */
+#define VERR_CPUM_INVALID_HWVIRT_FEAT_COMBO (-1768)
+/** @} */
+
+
+/** @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 value is not a zero terminated password string. */
+#define VERR_CFGM_NOT_PASSWORD (-2110)
+/** 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)
+/** Max timer limit reached. */
+#define VERR_TM_TOO_MANY_TIMERS (-2212)
+/** Invalid timer queue number. */
+#define VERR_TM_INVALID_TIMER_QUEUE (-2213)
+/** The timer queue is not longer allowed to grow. */
+#define VERR_TM_TIMER_QUEUE_CANNOT_GROW (-2214)
+/** TM internal processing error \#1. */
+#define VERR_TM_IPE_1 (-2291)
+/** TM internal processing error \#2. */
+#define VERR_TM_IPE_2 (-2292)
+/** TM internal processing error \#3. */
+#define VERR_TM_IPE_3 (-2293)
+/** TM internal processing error \#4. */
+#define VERR_TM_IPE_4 (-2294)
+/** TM internal processing error \#5. */
+#define VERR_TM_IPE_5 (-2295)
+/** TM internal processing error \#6. */
+#define VERR_TM_IPE_6 (-2296)
+/** TM internal processing error \#7. */
+#define VERR_TM_IPE_7 (-2297)
+/** TM internal processing error \#8. */
+#define VERR_TM_IPE_8 (-2298)
+/** TM internal processing error \#9. */
+#define VERR_TM_IPE_9 (-2299)
+/** @} */
+
+
+/** @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)
+/** Bad TRPM_TRAP_IN_OP. */
+#define VERR_TRPM_BAD_TRAP_IN_OP (-2405)
+/** Internal processing error \#1 in TRPM. */
+#define VERR_TRPM_IPE_1 (-2406)
+/** Internal processing error \#2 in TRPM. */
+#define VERR_TRPM_IPE_2 (-2407)
+/** Internal processing error \#3 in TRPM. */
+#define VERR_TRPM_IPE_3 (-2408)
+/** Got into a part of TRPM that is not used when HM (VT-x/AMD-V) is enabled. */
+#define VERR_TRPM_HM_IPE (-2409)
+/** @} */
+
+
+/** @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)
+
+/** Too many I/O port registrations. */
+#define VERR_IOM_TOO_MANY_IOPORT_REGISTRATIONS (-2650)
+/** Invalid I/O port handle. */
+#define VERR_IOM_INVALID_IOPORT_HANDLE (-2651)
+/** I/O ports are already mapped. */
+#define VERR_IOM_IOPORTS_ALREADY_MAPPED (-2652)
+/** I/O ports are not mapped. */
+#define VERR_IOM_IOPORTS_NOT_MAPPED (-2653)
+
+/** Too many MMIO registrations. */
+#define VERR_IOM_TOO_MANY_MMIO_REGISTRATIONS (-2660)
+/** Invalid MMIO handle. */
+#define VERR_IOM_INVALID_MMIO_HANDLE (-2661)
+/** MMIO region is already mapped. */
+#define VERR_IOM_MMIO_REGION_ALREADY_MAPPED (-2662)
+/** MMIO region is not mapped. */
+#define VERR_IOM_MMIO_REGION_NOT_MAPPED (-2663)
+/** @} */
+
+
+/** @name Virtual Machine Monitor (VMM) Status Codes
+ * @{
+ */
+/** 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 long jump error. */
+#define VERR_VMM_LONG_JMP_ERROR (-2709)
+/** 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)
+/** NEM returned in the wrong state. */
+#define VERR_VMM_WRONG_NEM_VMCPU_STATE (-2718)
+/** Got back from vmmR0CallRing3SetJmp with the context hook still enabled. */
+#define VERR_VMM_CONTEXT_HOOK_STILL_ENABLED (-2719)
+/** Cannot block in ring-0. */
+#define VERR_VMM_CANNOT_BLOCK (-2720)
+/** @} */
+
+
+/** @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_DEVHLP_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)
+
+/** Returned by PCI config space callbacks to indicate taking default action. */
+#define VINF_PDM_PCI_DO_DEFAULT (7200)
+/** Failed to abort entering a critical section in ring-0. */
+#define VERR_PDM_CRITSECT_ABORT_FAILED (-7201)
+/** Too many readers on read/write critical section. */
+#define VERR_PDM_CRITSECTRW_TOO_MANY_READERS (-7202)
+/** Too many writes on read/write critical section. */
+#define VERR_PDM_CRITSECTRW_TOO_MANY_WRITERS (-7203)
+/** Too many write or write/read recursions on read/write critical section. */
+#define VERR_PDM_CRITSECTRW_TOO_MANY_RECURSIONS (-7204)
+/** Internal error in read-write critical section. */
+#define VERR_PDM_CRITSECTRW_IPE (-7205)
+/** Misaligned read/write critical section. */
+#define VERR_PDM_CRITSECTRW_MISALIGNED (-7206)
+/** @} */
+
+
+/** @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)
+/** Too many clients for the service. */
+#define VERR_HGCM_TOO_MANY_CLIENTS (-2908)
+/** Too many calls to the service from a client. */
+#define VERR_HGCM_TOO_MANY_CLIENT_CALLS (-2909)
+/** @} */
+
+
+/** @name Network Address Translation Driver (DrvNAT) Status Codes
+ * @{
+ */
+/** 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)
+/** Reducing the size is not supported */
+#define VERR_VD_SHRINK_NOT_SUPPORTED (-3290)
+/** @} */
+
+
+/** @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)
+/** Unexpected PCI region change during VGA saved state loading. */
+#define VERR_VGA_UNEXPECTED_PCI_REGION_LOAD_CHANGE (-3502)
+/** Unabled to locate or load the OpenGL library. */
+#define VERR_VGA_GL_LOAD_FAILURE (-3503)
+/** Unabled to locate an OpenGL symbol. */
+#define VERR_VGA_GL_SYMBOL_NOT_FOUND (-3504)
+/** @} */
+
+
+/** @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)
+
+/** Raw-mode is unavailable courtesy of Hyper-V. */
+#define VERR_SUPDRV_NO_RAW_MODE_HYPER_V_ROOT (-7000)
+/** @} */
+
+
+/** @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
+ * @{
+ */
+/** 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)
+/** VMX CPU extension not available in hardware. */
+#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)
+/** VT-x VMCS field cache invalid. */
+#define VERR_VMX_VMCS_FIELD_CACHE_INVALID (-4030)
+/** Failed to set VMXON enable bit while enabling VT-x through the MSR. */
+#define VERR_VMX_MSR_VMX_ENABLE_FAILED (-4031)
+/** Failed to enable VMXON-in-SMX bit while enabling VT-x through the MSR. */
+#define VERR_VMX_MSR_SMX_VMX_ENABLE_FAILED (-4032)
+/** An operation caused a nested-guest VM-exit. */
+#define VINF_VMX_VMEXIT 4033
+/** Generic VM-entry failure. */
+#define VERR_VMX_VMENTRY_FAILED (-4033)
+/** Generic VM-exit failure. */
+#define VERR_VMX_VMEXIT_FAILED (-4034)
+/** The requested nested-guest VMX intercept is not active or not in
+ * nested-guest execution mode. */
+#define VINF_VMX_INTERCEPT_NOT_ACTIVE 4035
+/** The behavior of the instruction/operation is modified/needs modification
+ * in VMX non-root mode. */
+#define VINF_VMX_MODIFIES_BEHAVIOR 4036
+/** VMLAUNCH/VMRESUME succeeded, can enter nested-guest execution. */
+#define VINF_VMX_VMLAUNCH_VMRESUME 4037
+/** VT-x VMCS launch state invalid. */
+#define VERR_VMX_INVALID_VMCS_LAUNCH_STATE (-4038)
+/** Precodition no 0 in hmR0VMXStartVm failed. */
+#define VERR_VMX_STARTVM_PRECOND_0 (-4039)
+/** Precodition no 1 in hmR0VMXStartVm failed. */
+#define VERR_VMX_STARTVM_PRECOND_1 (-4040)
+/** Precodition no 2 in hmR0VMXStartVm failed. */
+#define VERR_VMX_STARTVM_PRECOND_2 (-4041)
+/** Precodition no 3 in hmR0VMXStartVm failed. */
+#define VERR_VMX_STARTVM_PRECOND_3 (-4042)
+/** @} */
+
+
+/** @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
+/** VMRUN emulation succeeded, ready to immediately enter the nested-guest. */
+#define VINF_SVM_VMRUN 4068
+/** The requested nested-guest SVM intercept is not active or not in
+ * nested-guest execution mode. */
+#define VINF_SVM_INTERCEPT_NOT_ACTIVE 4069
+/** Precodition no 0 in hmR0SvmVmRun failed. */
+#define VERR_SVM_VMRUN_PRECOND_0 (-4070)
+/** Precodition no 1 in hmR0SvmVmRun failed. */
+#define VERR_SVM_VMRUN_PRECOND_1 (-4071)
+/** Precodition no 2 in hmR0SvmVmRun failed. */
+#define VERR_SVM_VMRUN_PRECOND_2 (-4072)
+/** Precodition no 3 in hmR0SvmVmRun failed. */
+#define VERR_SVM_VMRUN_PRECOND_3 (-4073)
+/** @} */
+
+
+/** @name VBox HM Status Codes
+ * @{
+ */
+/** Host is about to go into suspend mode. */
+#define VERR_HM_SUSPEND_PENDING (-4100)
+/** 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
+/** Pending exception; continue guest execution. */
+#define VINF_HM_PENDING_XCPT 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 Bus & Passthrough 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)
+
+/** Special return code from a PCI I/O region mapping handler that tells the BUS
+ * that it has done the mapping already. */
+#define VINF_PCI_MAPPING_DONE 5150
+/** @} */
+
+
+/** @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)
+/** Cannot destroy VM because not all other EMTs have deregistered. */
+#define VERR_GVMM_NOT_ALL_EMTS_DEREGISTERED (-5205)
+/** @} */
+
+
+/** @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)
+/** NtQueryObject/Type failed. */
+#define VERR_SUP_VP_QUERY_HANDLE_TYPE (-5677)
+/** NtSetInformationObject/NoInherit failed. */
+#define VERR_SUP_VP_SET_HANDLE_NOINHERIT (-5678)
+
+/** We are in driverless mode. */
+#define VERR_SUP_DRIVERLESS (-5699)
+/** We are in driverless mode. */
+#define VINF_SUP_DRIVERLESS 5699
+/** @} */
+
+/** @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)
+/** Maximum (context ID) sessions have been reached. */
+#define VERR_GSTCTL_MAX_CID_SESSIONS_REACHED (-6222)
+/** Maximum (context ID) objects have been reached. */
+#define VERR_GSTCTL_MAX_CID_OBJECTS_REACHED (-6223)
+/** Maximum (context ID object) count has been reached. */
+#define VERR_GSTCTL_MAX_CID_COUNT_REACHED (-6224)
+/** Started guest process terminated with an exit code <> 0. */
+#define VERR_GSTCTL_PROCESS_EXIT_CODE (-6225)
+/** @} */
+
+
+/** @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_DND_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 host backend attached / available. */
+#define VERR_AUDIO_BACKEND_NOT_ATTACHED (-6601)
+/** No free input streams. */
+#define VERR_AUDIO_NO_FREE_INPUT_STREAMS (-6602)
+/** No free output streams. */
+#define VERR_AUDIO_NO_FREE_OUTPUT_STREAMS (-6603)
+/** Pending stream disable operation in progress. */
+#define VERR_AUDIO_STREAM_PENDING_DISABLE (-6604)
+/** 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 (6605)
+/** Stream is not ready for requested operation. */
+#define VERR_AUDIO_STREAM_NOT_READY (-6605)
+/** Stream could not be created.
+ * This might due to missing host (backend) drivers or a host not having the
+ * required hardware, or that the requested stream configuration
+ * is not supported by the host backend. */
+#define VERR_AUDIO_STREAM_COULD_NOT_CREATE (-6606)
+/** Generic audio device enumeration error. */
+#define VERR_AUDIO_ENUMERATION_FAILED (-6607)
+/** Asynchronous stream initialization still on-going. */
+#define VERR_AUDIO_STREAM_INIT_IN_PROGRESS (-6608)
+/** Special PDMIHOSTAUDIO::pfnStreamCreate return value for triggering
+ * calling of PDMIHOSTAUDIO::pfnStreamInitAsync on a worker thread. */
+#define VINF_AUDIO_STREAM_ASYNC_INIT_NEEDED (6609)
+/** @} */
+
+
+/** @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)
+/** @} */
+
+/** @name NEM Status Codes
+ * @{
+ */
+/** NEM is not enabled. */
+#define VERR_NEM_NOT_ENABLED (-6800)
+/** NEM is not available. */
+#define VERR_NEM_NOT_AVAILABLE (-6801)
+/** NEM init failed. */
+#define VERR_NEM_INIT_FAILED (-6802)
+/** NEM init failed because of missing kernel API (\#1). */
+#define VERR_NEM_MISSING_KERNEL_API_1 (-6803)
+/** NEM can only operate from ring-3. */
+#define VERR_NEM_RING3_ONLY (-6804)
+/** NEM failed to create a native VM instance. */
+#define VERR_NEM_VM_CREATE_FAILED (-6805)
+/** NEM failed to map page(s) into the VM. */
+#define VERR_NEM_MAP_PAGES_FAILED (-6806)
+/** NEM failed to unmap page(s) into the VM. */
+#define VERR_NEM_UNMAP_PAGES_FAILED (-6807)
+/** NEM failed to get registers. */
+#define VERR_NEM_GET_REGISTERS_FAILED (-6808)
+/** NEM failed to set registers. */
+#define VERR_NEM_SET_REGISTERS_FAILED (-6809)
+/** Get register caller must flush the TLB (not an error). */
+#define VERR_NEM_FLUSH_TLB (-6810)
+/** Get register caller must flush the TLB. */
+#define VINF_NEM_FLUSH_TLB (6810)
+/** NEM failed to set TSC. */
+#define VERR_NEM_SET_TSC (-6811)
+/** NEM init failed because of missing kernel API (\#2). */
+#define VERR_NEM_MISSING_KERNEL_API_2 (-6812)
+/** NEM init failed because of missing kernel API (\#3). */
+#define VERR_NEM_MISSING_KERNEL_API_3 (-6813)
+/** NEM init failed because of missing kernel API (\#4). */
+#define VERR_NEM_MISSING_KERNEL_API_4 (-6814)
+/** NEM init failed because of missing kernel API (\#5). */
+#define VERR_NEM_MISSING_KERNEL_API_5 (-6815)
+/** NEM failed to query dirty page bitmap. */
+#define VERR_NEM_QUERY_DIRTY_BITMAP_FAILED (-6816)
+/** NEM is missing a require feature in the host API. */
+#define VERR_NEM_MISSING_FEATURE (-6817)
+
+/** NEM internal processing error \#0. */
+#define VERR_NEM_IPE_0 (-6890)
+/** NEM internal processing error \#1. */
+#define VERR_NEM_IPE_1 (-6891)
+/** NEM internal processing error \#2. */
+#define VERR_NEM_IPE_2 (-6892)
+/** NEM internal processing error \#3. */
+#define VERR_NEM_IPE_3 (-6893)
+/** NEM internal processing error \#4. */
+#define VERR_NEM_IPE_4 (-6894)
+/** NEM internal processing error \#5. */
+#define VERR_NEM_IPE_5 (-6895)
+/** NEM internal processing error \#6. */
+#define VERR_NEM_IPE_6 (-6896)
+/** NEM internal processing error \#7. */
+#define VERR_NEM_IPE_7 (-6897)
+/** NEM internal processing error \#8. */
+#define VERR_NEM_IPE_8 (-6898)
+/** NEM internal processing error \#9. */
+#define VERR_NEM_IPE_9 (-6899)
+/** @} */
+
+/** @name Recording Status Codes
+ * @{
+ */
+/** Codec was not found. */
+#define VERR_RECORDING_CODEC_NOT_FOUND (-6900)
+/** Codec initialization failed. */
+#define VERR_RECORDING_CODEC_INIT_FAILED (-6902)
+/** Codec is not supported. */
+#define VERR_RECORDING_CODEC_NOT_SUPPORTED (-6903)
+/** Format not supported by the codec. */
+#define VERR_RECORDING_FORMAT_NOT_SUPPORTED (-6904)
+/** Recording is not possible due to a set restriction. */
+#define VERR_RECORDING_RESTRICTED (-6905)
+/** Recording limit (time, size, ...) has been reached. */
+#define VINF_RECORDING_LIMIT_REACHED (6906)
+/** Recording limit (time, size, ...) has been reached. */
+#define VERR_RECORDING_LIMIT_REACHED (-6906)
+/** Recording has been throttled due to current settings.
+ * This e.g. can happen when submitting more video frames than
+ * the current FPS setting allows. */
+#define VINF_RECORDING_THROTTLED (6907)
+/** Recording has been throttled due to current settings.
+ * This e.g. can happen when submitting more video frames than
+ * the current FPS setting allows. */
+#define VERR_RECORDING_THROTTLED (-6907)
+/** Encoding data failed. */
+#define VERR_RECORDING_ENCODING_FAILED (-6908)
+/** @} */
+
+/** @name Shared Clipboard Status Codes
+ * @{
+ */
+/** Maximum of concurrent clipboard transfers has been reached. */
+#define VERR_SHCLPB_MAX_TRANSFERS_REACHED (-7100)
+/** Maximum number of Shared Clipboard objects has been reached. */
+#define VERR_SHCLPB_MAX_OBJECTS_REACHED (-7101)
+/** Maximum number of Shared Clipboard lists has been reached. */
+#define VERR_SHCLPB_MAX_LISTS_REACHED (-7102)
+/** A Shared Clipboard list handle is invalid. */
+#define VERR_SHCLPB_LIST_HANDLE_INVALID (-7103)
+/** A Shared Clipboard objects handle is invalid. */
+#define VERR_SHCLPB_OBJ_HANDLE_INVALID (-7104)
+/** Shared Clipboard event ID not found. */
+#define VERR_SHCLPB_EVENT_ID_NOT_FOUND (-7105)
+/** Maximum number of Shared Clipboard events for an event source has been reached. */
+#define VERR_SHCLPB_MAX_EVENTS_REACHED (-7106)
+/** Shared Clipboard transfer ID not found. */
+#define VERR_SHCLPB_TRANSFER_ID_NOT_FOUND (-7150)
+/** @} */
+
+/** @name Virtual IOMMU Status Codes
+ * @{
+ */
+/** Failed to read the device table entry from guest memory. */
+#define VERR_IOMMU_DTE_READ_FAILED (-7300)
+/** Failed to read the device table entry due to an invalid offset. */
+#define VERR_IOMMU_DTE_BAD_OFFSET (-7301)
+/** Address translation failed. */
+#define VERR_IOMMU_ADDR_TRANSLATION_FAILED (-7302)
+/** Access denied for the address. */
+#define VERR_IOMMU_ADDR_ACCESS_DENIED (-7303)
+/** Remapping failed for the interrupt. */
+#define VERR_IOMMU_INTR_REMAP_FAILED (-7304)
+/** Remapping denied for the interrupt (might have caused a PCI target abort). */
+#define VERR_IOMMU_INTR_REMAP_DENIED (-7305)
+/** Command not supported. */
+#define VERR_IOMMU_CMD_NOT_SUPPORTED (-7306)
+/** Command format (or reserved bits) invalid. */
+#define VERR_IOMMU_CMD_INVALID_FORMAT (-7307)
+/** Command hardware failure. */
+#define VERR_IOMMU_CMD_HW_ERROR (-7308)
+/** IOMMU device is not present. */
+#define VERR_IOMMU_NOT_PRESENT (-7309)
+/** IOMMU instance cannot call itself (for remapping interrupts or translating
+ * addresses). */
+#define VERR_IOMMU_CANNOT_CALL_SELF (-7310)
+/** Address translation disabled (but permission bits apply). */
+#define VINF_IOMMU_ADDR_TRANSLATION_DISABLED 7311
+
+/** IOMMU Internal processing error \#0. */
+#define VERR_IOMMU_IPE_0 (-7390)
+/** IOMMU Internal processing error \#1. */
+#define VERR_IOMMU_IPE_1 (-7391)
+/** IOMMU Internal processing error \#2. */
+#define VERR_IOMMU_IPE_2 (-7392)
+/** IOMMU Internal processing error \#3. */
+#define VERR_IOMMU_IPE_3 (-7393)
+/** IOMMU Internal processing error \#4. */
+#define VERR_IOMMU_IPE_4 (-7394)
+/** IOMMU Internal processing error \#5. */
+#define VERR_IOMMU_IPE_5 (-7395)
+/** IOMMU Internal processing error \#6. */
+#define VERR_IOMMU_IPE_6 (-7396)
+/** IOMMU Internal processing error \#7. */
+#define VERR_IOMMU_IPE_7 (-7397)
+/** IOMMU Internal processing error \#8. */
+#define VERR_IOMMU_IPE_8 (-7398)
+/** IOMMU Internal processing error \#9. */
+#define VERR_IOMMU_IPE_9 (-7399)
+/** @} */
+
+/* SED-END */
+
+/** @} */
+
+
+#endif /* !VBOX_INCLUDED_err_h */
+
diff --git a/include/VBox/err.mac b/include/VBox/err.mac
new file mode 100644
index 00000000..14f39cb1
--- /dev/null
+++ b/include/VBox/err.mac
@@ -0,0 +1,1230 @@
+;; @file
+; VirtualBox Status Codes.
+;
+; Automatically generated by err.sed. DO NOT EDIT!
+;
+
+;
+; Copyright (C) 2006-2022 Oracle and/or its affiliates.
+;
+; This file is part of VirtualBox base platform packages, as
+; available from https://www.virtualbox.org.
+;
+; This program is free software; you can redistribute it and/or
+; modify it under the terms of the GNU General Public License
+; as published by the Free Software Foundation, in version 3 of the
+; License.
+;
+; This program is distributed in the hope that it will be useful, but
+; WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with this program; if not, see <https://www.gnu.org/licenses>.
+;
+; The contents of this file may alternatively be used under the terms
+; of the Common Development and Distribution License Version 1.0
+; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+; in the VirtualBox 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.
+;
+; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+;
+
+%define VERR_NO_VM_MEMORY (-1000)
+%define VERR_DONT_PANIC (-1001)
+%define VERR_UNSUPPORTED_CPU (-1002)
+%define VERR_UNSUPPORTED_CPU_MODE (-1003)
+%define VERR_PAGE_NOT_PRESENT (-1004)
+%define VERR_CFG_INVALID_FORMAT (-1005)
+%define VERR_CFG_NO_VALUE (-1006)
+%define VERR_SELECTOR_NOT_PRESENT (-1007)
+%define VERR_NOT_CODE_SELECTOR (-1008)
+%define VERR_NOT_DATA_SELECTOR (-1009)
+%define VERR_OUT_OF_SELECTOR_BOUNDS (-1010)
+%define VERR_INVALID_SELECTOR (-1011)
+%define VERR_INVALID_RPL (-1012)
+%define VERR_PAGE_MAP_LEVEL4_NOT_PRESENT (-1013)
+%define VERR_PAGE_DIRECTORY_PTR_NOT_PRESENT (-1014)
+%define VERR_RAW_MODE_INVALID_SMP (-1015)
+%define VERR_INVALID_VM_HANDLE (-1016)
+%define VERR_INVALID_VMCPU_HANDLE (-1017)
+%define VERR_INVALID_CPU_ID (-1018)
+%define VERR_TOO_MANY_CPUS (-1019)
+%define VERR_SERVICE_DISABLED (-1020)
+%define VERR_NOT_SUP_IN_RAW_MODE (-1021)
+%define VERR_INVALID_CPU_INDEX (-1022)
+%define VERR_RAW_MODE_NOT_SUPPORTED (-1023)
+%define VERR_INCONSISTENT_VM_HANDLE (-1024)
+%define VERR_VM_RESTORED (-1025)
+%define VERR_NOT_SUP_BY_NEM (-1026)
+%define VINF_EM_FIRST 1100
+%define VINF_EM_TERMINATE 1100
+%define VINF_EM_DBG_HYPER_STEPPED 1101
+%define VINF_EM_DBG_HYPER_BREAKPOINT 1102
+%define VINF_EM_DBG_HYPER_ASSERTION 1103
+%define VINF_EM_DBG_EVENT 1104
+%define VINF_EM_DBG_STOP 1105
+%define VINF_EM_DBG_STEPPED 1106
+%define VINF_EM_DBG_BREAKPOINT 1107
+%define VINF_EM_DBG_STEP 1108
+%define VINF_EM_OFF 1109
+%define VINF_EM_SUSPEND 1110
+%define VINF_EM_RESET 1111
+%define VINF_EM_HALT 1112
+%define VINF_EM_RESUME 1113
+%define VINF_EM_NO_MEMORY 1114
+%define VERR_EM_NO_MEMORY (-1114)
+%define VINF_EM_RESCHEDULE_REM 1115
+%define VINF_EM_RESCHEDULE_HM 1116
+%define VINF_EM_RESCHEDULE_RAW 1117
+%define VINF_EM_RESCHEDULE 1118
+%define VINF_EM_RESCHEDULE_PARAV 1119
+%define VINF_EM_WAIT_SIPI 1120
+%define VINF_EM_LAST 1120
+%define VINF_EM_RAW_GUEST_TRAP 1121
+%define VINF_EM_RAW_INTERRUPT 1122
+%define VINF_EM_RAW_INTERRUPT_HYPER 1123
+%define VINF_EM_RAW_RING_SWITCH 1124
+%define VINF_EM_RAW_RING_SWITCH_INT 1125
+%define VINF_EM_RAW_EXCEPTION_PRIVILEGED 1126
+%define VINF_EM_RAW_EMULATE_INSTR 1127
+%define VINF_EM_RAW_EMULATE_INSTR_TSS_FAULT 1128
+%define VINF_EM_RAW_EMULATE_INSTR_LDT_FAULT 1129
+%define VINF_EM_RAW_EMULATE_INSTR_IDT_FAULT 1130
+%define VINF_EM_RAW_EMULATE_INSTR_GDT_FAULT 1131
+%define VERR_EM_RAW_PATCH_CONFLICT (-1133)
+%define VINF_EM_RAW_TO_R3 1135
+%define VINF_EM_RAW_TIMER_PENDING 1136
+%define VINF_EM_RAW_INTERRUPT_PENDING 1137
+%define VINF_EM_RAW_STALE_SELECTOR 1138
+%define VINF_EM_RAW_IRET_TRAP 1139
+%define VERR_EM_INTERPRETER (-1148)
+%define VERR_EM_INTERNAL_ERROR (-1149)
+%define VINF_EM_PENDING_REQUEST 1150
+%define VINF_EM_RAW_EMULATE_DBG_STEP 1151
+%define VINF_EM_HM_PATCH_TPR_INSTR 1152
+%define VERR_EM_UNEXPECTED_MAPPING_CONFLICT (-1154)
+%define VINF_EM_TRIPLE_FAULT 1155
+%define VERR_EM_CANNOT_EXEC_GUEST (-1156)
+%define VINF_EM_RAW_INJECT_TRPM_EVENT 1157
+%define VERR_EM_GUEST_CPU_HANG (-1158)
+%define VINF_EM_PENDING_R3_IOPORT_READ 1159
+%define VINF_EM_PENDING_R3_IOPORT_WRITE 1160
+%define VINF_EM_RESUME_R3_HISTORY_EXEC 1161
+%define VINF_EM_EMULATE_SPLIT_LOCK 1162
+%define VERR_DBGF_NOT_ATTACHED (-1200)
+%define VERR_DBGF_ALREADY_ATTACHED (-1201)
+%define VWRN_DBGF_ALREADY_HALTED 1202
+%define VERR_DBGF_NO_MORE_BP_SLOTS (-1203)
+%define VERR_DBGF_BP_NOT_FOUND (-1204)
+%define VINF_DBGF_BP_ALREADY_ENABLED 1205
+%define VINF_DBGF_BP_ALREADY_DISABLED 1206
+%define VINF_DBGF_BP_ALREADY_EXIST 1207
+%define VERR_DBGF_MEM_NOT_FOUND (-1208)
+%define VERR_DBGF_OS_NOT_DETCTED (-1209)
+%define VINF_DBGF_OS_NOT_DETCTED 1209
+%define VERR_DBGF_REGISTER_NOT_FOUND (-1210)
+%define VINF_DBGF_TRUNCATED_REGISTER 1211
+%define VINF_DBGF_ZERO_EXTENDED_REGISTER 1212
+%define VERR_DBGF_UNSUPPORTED_CAST (-1213)
+%define VERR_DBGF_READ_ONLY_REGISTER (-1214)
+%define VERR_DBGF_REG_IPE_1 (-1215)
+%define VERR_DBGF_REG_IPE_2 (-1216)
+%define VERR_DBGF_HYPER_DB_XCPT (-1217)
+%define VERR_DBGF_STACK_IPE_1 (-1218)
+%define VERR_DBGF_STACK_IPE_2 (-1219)
+%define VERR_DBGF_NO_TRACE_BUFFER (-1220)
+%define VERR_DBGF_TRACER_IPE_1 (-1221)
+%define VWRN_DBGF_ALREADY_RUNNING (-1222)
+%define VERR_DBGF_IPE_1 (-1223)
+%define VINF_DBGF_BP_HALT (1224)
+%define VERR_DBGF_OWNER_BUSY (-1225)
+%define VERR_DBGF_BP_INT3_ADD_TRIES_REACHED (-1226)
+%define VERR_DBGF_BP_IPE_1 (-1227)
+%define VERR_DBGF_BP_IPE_2 (-1228)
+%define VERR_DBGF_BP_IPE_3 (-1229)
+%define VERR_DBGF_BP_IPE_4 (-1230)
+%define VERR_DBGF_BP_IPE_5 (-1231)
+%define VERR_DBGF_BP_IPE_6 (-1232)
+%define VERR_DBGF_BP_IPE_7 (-1233)
+%define VERR_DBGF_BP_IPE_8 (-1234)
+%define VERR_DBGF_BP_IPE_9 (-1235)
+%define VERR_DBGF_BP_L1_LOOKUP_FAILED (-1236)
+%define VERR_DBGF_BP_L2_LOOKUP_FAILED (-1237)
+%define VERR_DBGF_BP_OWNER_NO_MORE_HANDLES (-1238)
+%define VINF_DBGF_R3_BP_OWNER_DEFER 1239
+%define VERR_DBGF_BP_OWNER_CALLBACK_WRONG_STATUS (-1240)
+%define VERR_DBGF_CANCELLED (-1241)
+%define VWRN_CONTINUE_ANALYSIS 1400
+%define VWRN_CONTINUE_RECOMPILE VWRN_CONTINUE_ANALYSIS
+%define VWRN_PATM_CONTINUE_SEARCH VWRN_CONTINUE_ANALYSIS
+%define VERR_PATCHING_REFUSED (-1401)
+%define VERR_PATCH_NOT_FOUND (-1402)
+%define VERR_PATCH_DISABLED (-1403)
+%define VWRN_PATCH_ENABLED 1404
+%define VERR_PATCH_ALREADY_DISABLED (-1405)
+%define VERR_PATCH_ALREADY_ENABLED (-1406)
+%define VWRN_PATCH_REMOVED 1407
+%define VINF_PATM_PATCH_TRAP_GP 1408
+%define VINF_PATM_LEAVE_RC_FIRST VINF_PATM_PATCH_TRAP_GP
+%define VINF_PATM_PATCH_TRAP_PF 1409
+%define VINF_PATM_PATCH_INT3 1410
+%define VINF_PATM_CHECK_PATCH_PAGE 1411
+%define VINF_PATM_DUPLICATE_FUNCTION 1412
+%define VINF_PATCH_EMULATE_INSTR 1413
+%define VINF_PATM_HC_MMIO_PATCH_WRITE 1414
+%define VINF_PATM_HC_MMIO_PATCH_READ 1415
+%define VINF_PATM_PENDING_IRQ_AFTER_IRET 1416
+%define VINF_PATM_LEAVE_RC_LAST VINF_PATM_PENDING_IRQ_AFTER_IRET
+%define VERR_PATCH_NO_CONFLICT (-1425)
+%define VERR_PATM_UNSAFE_CODE (-1426)
+%define VWRN_PATCH_END_BRANCH 1427
+%define VERR_PATM_ALREADY_PATCHED (-1428)
+%define VINF_PATM_SPINLOCK_FAILED (1429)
+%define VINF_PATCH_CONTINUE (1430)
+%define VERR_PATM_HM_IPE (-1431)
+%define VERR_PATM_IPE_TRAP_IN_PATCH_CODE (-1432)
+%define VWRN_CSAM_TRAP_NOT_HANDLED 1500
+%define VWRN_CSAM_INSTRUCTION_PATCHED 1501
+%define VWRN_CSAM_PAGE_NOT_FOUND 1502
+%define VINF_CSAM_PENDING_ACTION 1503
+%define VERR_CSAM_HM_IPE (-1504)
+%define VERR_PGM_MAPPING_CONFLICT (-1600)
+%define VERR_PGM_HANDLER_PHYSICAL_NO_RAM_RANGE (-1601)
+%define VERR_PGM_HANDLER_VIRTUAL_CONFLICT (-1602)
+%define VERR_PGM_HANDLER_PHYSICAL_CONFLICT (-1603)
+%define VERR_PGM_INVALID_PAGE_DIRECTORY (-1604)
+%define VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS (-1605)
+%define VERR_PGM_INVALID_GC_PHYSICAL_RANGE (-1606)
+%define VERR_PGM_HANDLER_NOT_FOUND (-1607)
+%define VERR_PGM_RAM_CONFLICT (-1608)
+%define VERR_PGM_MAPPINGS_FIXED (-1609)
+%define VERR_PGM_MAPPINGS_FIX_CONFLICT (-1610)
+%define VERR_PGM_MAPPINGS_FIX_REJECTED (-1611)
+%define VERR_PGM_MAPPINGS_FIX_TOO_SMALL (-1612)
+%define VINF_PGM_SYNC_CR3 1613
+%define VINF_PGM_NO_DIRTY_BIT_TRACKING 1614
+%define VINF_PGM_HANDLED_DIRTY_BIT_FAULT 1615
+%define VINF_PGM_HANDLER_DO_DEFAULT 1616
+%define VERR_PGM_UNSUPPORTED_HOST_PAGING_MODE (-1617)
+%define VERR_PGM_PHYS_PAGE_RESERVED (-1618)
+%define VERR_PGM_NO_HYPERVISOR_ADDRESS (-1619)
+%define VINF_PGM_CACHED_PAGE 1622
+%define VINF_PGM_GCPHYS_ALIASED 1623
+%define VINF_PGM_SYNCPAGE_MODIFIED_PDE 1625
+%define VERR_PGM_GCPHYS_RANGE_CROSSES_BOUNDARY (-1626)
+%define VERR_PGM_INTERMEDIATE_PAGING_CONFLICT (-1627)
+%define VERR_PGM_UNSUPPORTED_SHADOW_PAGING_MODE (-1628)
+%define VERR_PGM_DYNMAP_FAILED (-1629)
+%define VERR_PGM_DYNMAP_FULL_SET (-1630)
+%define VERR_PGM_DYNMAP_SETUP_ERROR (-1631)
+%define VERR_PGM_DYNMAP_EXPAND_ERROR (-1632)
+%define VERR_PGM_PHYS_TLB_UNASSIGNED (-1633)
+%define VERR_PGM_PHYS_TLB_CATCH_ALL (-1634)
+%define VINF_PGM_PHYS_TLB_CATCH_WRITE 1635
+%define VERR_PGM_PHYS_TLB_CATCH_WRITE (-1635)
+%define VERR_PGM_NO_CR3_SHADOW_ROOT (-1636)
+%define VERR_PGM_PHYS_INVALID_PAGE_ID (-1637)
+%define VERR_PGM_PHYS_WR_HIT_HANDLER (-1638)
+%define VERR_PGM_PHYS_NOT_RAM (-1639)
+%define VERR_PGM_PHYS_NOT_ROM (-1640)
+%define VERR_PGM_PHYS_NOT_MMIO (-1641)
+%define VERR_PGM_PHYS_NOT_MMIO2 (-1642)
+%define VERR_PGM_HANDLER_ALREADY_ALIASED (-1643)
+%define VINF_PGM_HANDLER_ALREADY_ALIASED (1643)
+%define VINF_PGM_POOL_FLUSH_PENDING (1644)
+%define VERR_PGM_INVALID_LARGE_PAGE_RANGE (-1645)
+%define VERR_PGM_PHYS_PAGE_BALLOONED (-1646)
+%define VERR_PGM_HANDLER_IPE_1 (-1647)
+%define VERR_PGM_MAP_MMIO2_ALIAS_MMIO (-1651)
+%define VERR_PGM_MAPPINGS_DISABLED (-1652)
+%define VERR_PGM_MAPPINGS_SMP (-1653)
+%define VERR_PGM_INVALID_SAVED_PAGE_STATE (-1654)
+%define VERR_PGM_LOAD_UNEXPECTED_PAGE_TYPE (-1655)
+%define VERR_PGM_UNEXPECTED_PAGE_STATE (-1656)
+%define VERR_PGM_SAVED_MMIO2_RANGE_NOT_FOUND (-1657)
+%define VERR_PGM_SAVED_MMIO2_PAGE_NOT_FOUND (-1658)
+%define VERR_PGM_SAVED_ROM_RANGE_NOT_FOUND (-1659)
+%define VERR_PGM_SAVED_ROM_PAGE_NOT_FOUND (-1660)
+%define VERR_PGM_SAVED_ROM_PAGE_PROT (-1661)
+%define VERR_PGM_SAVED_REC_TYPE (-1662)
+%define VERR_PGM_DYNMAP_IPE (-1663)
+%define VERR_PGM_HANDY_PAGE_IPE (-1664)
+%define VERR_PGM_PML4_MAPPING (-1665)
+%define VERR_PGM_POOL_GET_PAGE_FAILED (-1666)
+%define VERR_PGM_NOT_USED_IN_MODE (-1667)
+%define VERR_PGM_INVALID_CR3_ADDR (-1668)
+%define VERR_PGM_INVALID_PDPE_ADDR (-1669)
+%define VERR_PGM_PHYS_HANDLER_IPE (-1670)
+%define VERR_PGM_PHYS_PAGE_MAP_IPE_1 (-1671)
+%define VERR_PGM_PHYS_PAGE_MAP_IPE_2 (-1672)
+%define VERR_PGM_PHYS_PAGE_MAP_IPE_3 (-1673)
+%define VERR_PGM_PHYS_PAGE_MAP_IPE_4 (-1674)
+%define VERR_PGM_POOL_TOO_MANY_LOOPS (-1675)
+%define VERR_PGM_MAPPING_IPE (-1676)
+%define VERR_PGM_POOL_MAXED_OUT_ALREADY (-1677)
+%define VERR_PGM_POOL_IPE (-1678)
+%define VERR_PGM_WRITE_MONITOR_ENGAGED (-1679)
+%define VERR_PGM_PHYS_PAGE_GET_IPE (-1680)
+%define VERR_PGM_PHYS_NULL_PAGE_PARAM (-1681)
+%define VERR_PGM_PCI_PASSTHRU_MISCONFIG (-1682)
+%define VERR_PGM_TOO_MANY_MMIO2_RANGES (-1683)
+%define VERR_PGM_PHYS_PAGE_MAP_MMIO2_IPE (-1684)
+%define VERR_PGM_PHYS_MMIO_EX_IPE (-1685)
+%define VERR_PGM_MODE_IPE (-1686)
+%define VERR_PGM_SHW_NONE_IPE (-1687)
+%define VERR_PGM_PAE_PDPE_RSVD (-1688)
+%define VERR_PGM_NOT_SUPPORTED_FOR_NEM_MODE (-1689)
+%define VERR_MM_RAM_CONFLICT (-1700)
+%define VERR_MM_HYPER_NO_MEMORY (-1701)
+%define VERR_MM_BAD_TRAP_TYPE_IPE (-1702)
+%define VERR_CPUM_RAISE_GP_0 (-1750)
+%define VERR_CPUM_INCOMPATIBLE_CONFIG (-1751)
+%define VERR_CPUM_HIDDEN_CS_LOAD_ERROR (-1752)
+%define VERR_CPUM_TOO_MANY_CPUID_SUBLEAVES (-1753)
+%define VERR_CPUM_IPE_1 (-1754)
+%define VERR_CPUM_IPE_2 (-1755)
+%define VERR_CPUM_DB_CPU_NOT_FOUND (-1756)
+%define VERR_CPUM_MSR_BAD_CPUMCPU_OFFSET (-1757)
+%define VINF_CPUM_R3_MSR_READ (1758)
+%define VINF_CPUM_R3_MSR_WRITE (1759)
+%define VERR_TOO_MANY_CPUID_LEAVES (-1760)
+%define VERR_CPUM_INVALID_CONFIG_VALUE (-1761)
+%define VERR_CPUM_INCOMPATIBLE_XSAVE_COMP_MASK (-1762)
+%define VERR_CPUM_INVALID_XSAVE_COMP_MASK (-1763)
+%define VERR_CPUM_INVALID_XSAVE_HDR (-1764)
+%define VERR_CPUM_INVALID_XCR0 (-1765)
+%define VINF_CPUM_HOST_CR0_MODIFIED (1766)
+%define VERR_CPUM_INVALID_HWVIRT_CONFIG (-1767)
+%define VERR_CPUM_INVALID_HWVIRT_FEAT_COMBO (-1768)
+%define VERR_SSM_UNIT_EXISTS (-1800)
+%define VERR_SSM_UNIT_NOT_FOUND (-1801)
+%define VERR_SSM_UNIT_NOT_OWNER (-1802)
+%define VERR_SSM_INTEGRITY (-1810)
+%define VERR_SSM_INTEGRITY_MAGIC (-1811)
+%define VERR_SSM_INTEGRITY_VERSION (-1812)
+%define VERR_SSM_INTEGRITY_SIZE (-1813)
+%define VERR_SSM_INTEGRITY_CRC (-1814)
+%define VERR_SMM_INTEGRITY_MACHINE (-1815)
+%define VERR_SSM_INTEGRITY_HEADER (-1816)
+%define VERR_SSM_INTEGRITY_UNIT (-1817)
+%define VERR_SSM_INTEGRITY_UNIT_MAGIC (-1818)
+%define VERR_SSM_INTEGRITY_UNIT_NOT_FOUND (-1819)
+%define VERR_SSM_INTEGRITY_VBOX_VERSION (-1820)
+%define VERR_SSM_INTEGRITY_FOOTER (-1821)
+%define VERR_SSM_INTEGRITY_REC_HDR (-1822)
+%define VERR_SSM_INTEGRITY_REC_TERM (-1823)
+%define VERR_SSM_INTEGRITY_REC_TERM_CRC (-1824)
+%define VERR_SSM_INTEGRITY_DECOMPRESSION (-1825)
+%define VERR_SSM_INTEGRITY_DIR (-1826)
+%define VERR_SSM_INTEGRITY_DIR_MAGIC (-1827)
+%define VERR_SSM_NO_LOAD_EXEC (-1830)
+%define VERR_SSM_LOADED_TOO_MUCH (-1831)
+%define VERR_SSM_INVALID_STATE (-1832)
+%define VERR_SSM_LOADED_TOO_LITTLE (-1833)
+%define VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION (-1840)
+%define VERR_SSM_DATA_UNIT_FORMAT_CHANGED (-1841)
+%define VERR_SSM_LOAD_CPUID_MISMATCH (-1842)
+%define VERR_SSM_LOAD_MEMORY_SIZE_MISMATCH (-1843)
+%define VERR_SSM_LOAD_CONFIG_MISMATCH (-1844)
+%define VERR_SSM_VIRTUAL_CLOCK_HZ (-1845)
+%define VERR_SSM_IDE_ASYNC_TIMEOUT (-1846)
+%define VERR_SSM_STRUCTURE_MAGIC (-1847)
+%define VERR_SSM_UNEXPECTED_DATA (-1848)
+%define VERR_SSM_GCPHYS_OVERFLOW (-1849)
+%define VERR_SSM_GCPTR_OVERFLOW (-1850)
+%define VINF_SSM_VOTE_FOR_ANOTHER_PASS 1851
+%define VINF_SSM_VOTE_DONE_DONT_CALL_AGAIN 1852
+%define VERR_SSM_VOTE_FOR_GIVING_UP (-1853)
+%define VINF_SSM_DONT_CALL_AGAIN 1854
+%define VERR_SSM_TOO_MANY_PASSES (-1855)
+%define VERR_SSM_STATE_GREW_TOO_BIG (-1856)
+%define VERR_SSM_LOW_ON_DISK_SPACE (-1857)
+%define VERR_SSM_CANCELLED (-1858)
+%define VERR_SSM_NO_PENDING_OPERATION (-1859)
+%define VERR_SSM_ALREADY_CANCELLED (-1860)
+%define VERR_SSM_LIVE_POWERED_OFF (-1861)
+%define VERR_SSM_LIVE_GURU_MEDITATION (-1862)
+%define VERR_SSM_LIVE_FATAL_ERROR (-1863)
+%define VINF_SSM_LIVE_SUSPENDED 1864
+%define VERR_SSM_FIELD_COMPLEX (-1864)
+%define VERR_SSM_FIELD_INVALID_SIZE (-1865)
+%define VERR_SSM_FIELD_OUT_OF_BOUNDS (-1866)
+%define VERR_SSM_FIELD_NOT_CONSECUTIVE (-1867)
+%define VERR_SSM_FIELD_INVALID_CALLBACK (-1868)
+%define VERR_SSM_FIELD_INVALID_PADDING_SIZE (-1869)
+%define VERR_SSM_FIELD_INVALID_VALUE (-1870)
+%define VERR_SSM_STREAM_ERROR (-1871)
+%define VERR_SSM_UNEXPECTED_PASS (-1872)
+%define VERR_SSM_SKIP_BACKWARDS (-1873)
+%define VERR_SSM_MEM_TOO_BIG (-1874)
+%define VERR_SSM_BAD_REC_TYPE (-1875)
+%define VERR_SSM_IPE_1 (-1876)
+%define VERR_SSM_IPE_2 (-1877)
+%define VERR_SSM_IPE_3 (-1878)
+%define VERR_SSM_FIELD_LOAD_ONLY_TRANSFORMATION (-1879)
+%define VERR_VM_ATRESET_NOT_FOUND (-1900)
+%define VERR_VM_REQUEST_INVALID_TYPE (-1901)
+%define VERR_VM_REQUEST_STATE (-1902)
+%define VERR_VM_REQUEST_INVALID_PACKAGE (-1903)
+%define VERR_VM_REQUEST_STATUS_STILL_PENDING (-1904)
+%define VERR_VM_REQUEST_STATUS_FREED (-1905)
+%define VERR_VM_THREAD_NOT_EMT (-1906)
+%define VERR_VM_INVALID_VM_STATE (-1907)
+%define VERR_VM_DRIVER_NOT_INSTALLED (-1908)
+%define VERR_VM_DRIVER_NOT_ACCESSIBLE (-1909)
+%define VERR_VM_DRIVER_LOAD_ERROR (-1910)
+%define VERR_VM_DRIVER_OPEN_ERROR (-1911)
+%define VERR_VM_DRIVER_VERSION_MISMATCH (-1912)
+%define VERR_VM_SAVE_STATE_NOT_ALLOWED (-1913)
+%define VERR_VM_THREAD_IS_EMT (-1914)
+%define VERR_VM_UNEXPECTED_VM_STATE (-1915)
+%define VERR_VM_UNEXPECTED_UNSTABLE_STATE (-1916)
+%define VERR_VM_REQUEST_TOO_MANY_ARGS_IPE (-1917)
+%define VERR_VM_FATAL_WAIT_ERROR (-1918)
+%define VERR_VM_REQUEST_KILLED (-1919)
+%define VINF_VRDP_SUCCESS VINF_SUCCESS
+%define VERR_VRDP_TIMEOUT VERR_TIMEOUT
+%define VERR_VRDP_ISO_UNSUPPORTED (-2000)
+%define VERR_VRDP_SEC_ENGINE_FAIL (-2001)
+%define VERR_VRDP_PROTOCOL_ERROR (-2002)
+%define VERR_VRDP_NOT_SUPPORTED (-2003)
+%define VERR_VRDP_INSUFFICIENT_DATA (-2004)
+%define VERR_VRDP_INVALID_MODE (-2005)
+%define VERR_VRDP_NO_MEMORY (-2006)
+%define VERR_VRDP_ACCESS_DENIED (-2007)
+%define VWRN_VRDP_PDU_NOT_SUPPORTED 2008
+%define VINF_VRDP_PROCESS_PDU 2009
+%define VINF_VRDP_OPERATION_COMPLETED 2010
+%define VINF_VRDP_THREAD_STARTED 2011
+%define VINF_VRDP_RESIZE_REQUESTED 2012
+%define VINF_VRDP_OUTPUT_ENABLE 2013
+%define VERR_CFGM_INTEGER_TOO_BIG (-2100)
+%define VERR_CFGM_CHILD_NOT_FOUND (-2101)
+%define VERR_CFGM_INVALID_CHILD_PATH (-2102)
+%define VERR_CFGM_VALUE_NOT_FOUND (-2103)
+%define VERR_CFGM_NO_PARENT (-2104)
+%define VERR_CFGM_NO_NODE (-2105)
+%define VERR_CFGM_NOT_INTEGER (-2106)
+%define VERR_CFGM_NOT_STRING (-2107)
+%define VERR_CFGM_NOT_BYTES (-2108)
+%define VERR_CFGM_NOT_ENOUGH_SPACE (-2109)
+%define VERR_CFGM_NOT_PASSWORD (-2110)
+%define VERR_CFGM_INVALID_NODE_PATH (-2160)
+%define VERR_CFGM_NODE_EXISTS (-2161)
+%define VERR_CFGM_LEAF_EXISTS (-2162)
+%define VERR_CFGM_CONFIG_UNKNOWN_VALUE (-2163)
+%define VERR_CFGM_CONFIG_UNKNOWN_NODE (-2164)
+%define VERR_CFGM_IPE_1 (-2165)
+%define VERR_TM_LOAD_STATE (-2200)
+%define VERR_TM_INVALID_STATE (-2201)
+%define VERR_TM_UNKNOWN_STATE (-2202)
+%define VERR_TM_UNSTABLE_STATE (-2203)
+%define VERR_TM_GIP_REQUIRED (-2204)
+%define VERR_TM_GIP_VERSION (-2205)
+%define VERR_TM_GIP_UPDATE_INTERVAL_TOO_BIG (-2206)
+%define VERR_TM_TIMER_BAD_CLOCK (-2207)
+%define VERR_TM_TIMER_UNSTABLE_STATE (-2208)
+%define VERR_TM_TSC_ALREADY_TICKING (-2209)
+%define VERR_TM_TSC_ALREADY_PAUSED (-2210)
+%define VERR_TM_VIRTUAL_TICKING_IPE (-2211)
+%define VERR_TM_TOO_MANY_TIMERS (-2212)
+%define VERR_TM_INVALID_TIMER_QUEUE (-2213)
+%define VERR_TM_TIMER_QUEUE_CANNOT_GROW (-2214)
+%define VERR_TM_IPE_1 (-2291)
+%define VERR_TM_IPE_2 (-2292)
+%define VERR_TM_IPE_3 (-2293)
+%define VERR_TM_IPE_4 (-2294)
+%define VERR_TM_IPE_5 (-2295)
+%define VERR_TM_IPE_6 (-2296)
+%define VERR_TM_IPE_7 (-2297)
+%define VERR_TM_IPE_8 (-2298)
+%define VERR_TM_IPE_9 (-2299)
+%define VERR_REM_VIRTUAL_HARDWARE_ERROR (-2300)
+%define VERR_REM_VIRTUAL_CPU_ERROR (-2301)
+%define VINF_REM_INTERRUPED_FF 2302
+%define VERR_REM_TOO_MANY_TRAPS (-2304)
+%define VERR_REM_NO_MORE_BP_SLOTS (-2305)
+%define VERR_REM_BP_NOT_FOUND (-2306)
+%define VERR_TRPM_NO_ACTIVE_TRAP (-2400)
+%define VERR_TRPM_ACTIVE_TRAP (-2401)
+%define VERR_TRPM_SHADOW_IDT_WRITE (-2402)
+%define VERR_TRPM_DONT_PANIC (-2403)
+%define VERR_TRPM_PANIC (-2404)
+%define VERR_TRPM_BAD_TRAP_IN_OP (-2405)
+%define VERR_TRPM_IPE_1 (-2406)
+%define VERR_TRPM_IPE_2 (-2407)
+%define VERR_TRPM_IPE_3 (-2408)
+%define VERR_TRPM_HM_IPE (-2409)
+%define VERR_SELM_SHADOW_GDT_WRITE (-2500)
+%define VERR_SELM_SHADOW_LDT_WRITE (-2501)
+%define VERR_SELM_SHADOW_TSS_WRITE (-2502)
+%define VINF_SELM_SYNC_GDT 2503
+%define VERR_SELM_NO_TSS (-2504)
+%define VERR_SELM_INVALID_LDT (-2505)
+%define VERR_SELM_LDT_OUT_OF_BOUNDS (-2506)
+%define VERR_SELM_GDT_READ_ERROR (-2507)
+%define VERR_SELM_GDT_TOO_FULL (-2508)
+%define VERR_SELM_HM_IPE (-2509)
+%define VERR_IOM_INVALID_IOPORT_RANGE (-2600)
+%define VERR_IOM_NO_R3_IOPORT_RANGE (-2601)
+%define VERR_IOM_IOPORT_RANGE_CONFLICT (-2602)
+%define VERR_IOM_IOPORT_RANGE_NOT_FOUND (-2603)
+%define VERR_IOM_NOT_IOPORT_RANGE_OWNER (-2604)
+%define VERR_IOM_INVALID_MMIO_RANGE (-2605)
+%define VERR_IOM_NO_R3_MMIO_RANGE (-2606)
+%define VERR_IOM_NOT_MMIO_RANGE_OWNER (-2607)
+%define VERR_IOM_MMIO_RANGE_CONFLICT (-2608)
+%define VERR_IOM_MMIO_RANGE_NOT_FOUND (-2609)
+%define VERR_IOM_INCOMPLETE_MMIO_RANGE (-2610)
+%define VERR_IOM_INVALID_IOPORT_SIZE (-2611)
+%define VERR_IOM_MMIO_HANDLER_BOGUS_CALL (-2612)
+%define VERR_IOM_MMIO_HANDLER_DISASM_ERROR (-2613)
+%define VERR_IOM_IOPORT_UNUSED (-2614)
+%define VINF_IOM_MMIO_UNUSED_00 2615
+%define VINF_IOM_MMIO_UNUSED_FF 2616
+%define VINF_IOM_R3_IOPORT_READ 2620
+%define VINF_IOM_R3_IOPORT_WRITE 2621
+%define VINF_IOM_R3_IOPORT_COMMIT_WRITE 2622
+%define VINF_IOM_R3_MMIO_READ 2623
+%define VINF_IOM_R3_MMIO_WRITE 2624
+%define VINF_IOM_R3_MMIO_READ_WRITE 2625
+%define VINF_IOM_R3_MMIO_COMMIT_WRITE 2626
+%define VERR_IOM_IOPORT_UNKNOWN_OPCODE (-2630)
+%define VERR_IOM_IOPORT_IPE_1 (-2631)
+%define VERR_IOM_IOPORT_IPE_2 (-2632)
+%define VERR_IOM_IOPORT_IPE_3 (-2633)
+%define VERR_IOM_MMIO_IPE_1 (-2634)
+%define VERR_IOM_MMIO_IPE_2 (-2635)
+%define VERR_IOM_MMIO_IPE_3 (-2636)
+%define VERR_IOM_HM_IPE (-2637)
+%define VERR_IOM_FF_STATUS_IPE (-2638)
+%define VERR_IOM_TOO_MANY_IOPORT_REGISTRATIONS (-2650)
+%define VERR_IOM_INVALID_IOPORT_HANDLE (-2651)
+%define VERR_IOM_IOPORTS_ALREADY_MAPPED (-2652)
+%define VERR_IOM_IOPORTS_NOT_MAPPED (-2653)
+%define VERR_IOM_TOO_MANY_MMIO_REGISTRATIONS (-2660)
+%define VERR_IOM_INVALID_MMIO_HANDLE (-2661)
+%define VERR_IOM_MMIO_REGION_ALREADY_MAPPED (-2662)
+%define VERR_IOM_MMIO_REGION_NOT_MAPPED (-2663)
+%define VERR_VMM_RING0_ASSERTION (-2701)
+%define VERR_VMM_HYPER_CR3_MISMATCH (-2702)
+%define VERR_VMM_RING3_CALL_DISABLED (-2703)
+%define VERR_VMM_R0_VERSION_MISMATCH (-2704)
+%define VERR_VMM_RC_VERSION_MISMATCH (-2705)
+%define VERR_VMM_LONG_JMP_ERROR (-2709)
+%define VINF_VMM_CALL_TRACER (2712)
+%define VERR_VMM_SWITCHER_IPE_1 (-2713)
+%define VINF_VMM_UNKNOWN_RING3_CALL (2714)
+%define VERR_VMM_SWITCHER_STUB (-2715)
+%define VERR_VMM_WRONG_HM_VMCPU_STATE (-2716)
+%define VERR_VMM_SMAP_BUT_AC_CLEAR (-2717)
+%define VERR_VMM_WRONG_NEM_VMCPU_STATE (-2718)
+%define VERR_VMM_CONTEXT_HOOK_STILL_ENABLED (-2719)
+%define VERR_VMM_CANNOT_BLOCK (-2720)
+%define VERR_PDM_NO_SUCH_LUN (-2800)
+%define VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES (-2801)
+%define VERR_PDM_MISSING_INTERFACE_ABOVE (-2802)
+%define VERR_PDM_MISSING_INTERFACE_BELOW (-2803)
+%define VERR_PDM_MISSING_INTERFACE (-2804)
+%define VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES (-2805)
+%define VERR_PDM_TOO_PCI_MANY_DEVICES (-2806)
+%define VERR_PDM_NO_QUEUE_ITEMS (-2807)
+%define VERR_PDM_DRVINS_NO_ATTACH (-2808)
+%define VERR_PDM_DEVINS_NO_ATTACH (-2809)
+%define VERR_PDM_NO_ATTACHED_DRIVER (-2810)
+%define VERR_PDM_GEOMETRY_NOT_SET (-2811)
+%define VERR_PDM_TRANSLATION_NOT_SET (-2812)
+%define VERR_PDM_MEDIA_NOT_MOUNTED (-2813)
+%define VERR_PDM_MEDIA_MOUNTED (-2814)
+%define VERR_PDM_MEDIA_LOCKED (-2815)
+%define VERR_PDM_BLOCK_NO_TYPE (-2816)
+%define VERR_PDM_BLOCK_UNKNOWN_TYPE (-2817)
+%define VERR_PDM_BLOCK_UNKNOWN_TRANSLATION (-2818)
+%define VERR_PDM_UNSUPPORTED_BLOCK_TYPE (-2819)
+%define VERR_PDM_DRIVER_ALREADY_ATTACHED (-2820)
+%define VERR_PDM_NO_DRIVER_ATTACHED (-2821)
+%define VERR_PDM_CFG_MISSING_DRIVER_NAME (-2822)
+%define VERR_PDM_DRIVER_NOT_FOUND (-2823)
+%define VINF_PDM_ALREADY_LOADED (2824)
+%define VERR_PDM_MODULE_NAME_CLASH (-2825)
+%define VERR_PDM_NO_REGISTRATION_EXPORT (-2826)
+%define VERR_PDM_MODULE_NAME_TOO_LONG (-2827)
+%define VERR_PDM_DRIVER_NAME_CLASH (-2828)
+%define VERR_PDM_UNKNOWN_DRVREG_VERSION (-2829)
+%define VERR_PDM_INVALID_DRIVER_REGISTRATION (-2830)
+%define VERR_PDM_INVALID_DRIVER_HOST_BITS (-2831)
+%define VERR_PDM_DRIVER_DETACH_NOT_POSSIBLE (-2832)
+%define VERR_PDM_NO_PCI_BUS (-2833)
+%define VERR_PDM_NOT_PCI_DEVICE (-2834)
+%define VERR_PDM_UNKNOWN_DEVREG_VERSION (-2835)
+%define VERR_PDM_INVALID_DEVICE_REGISTRATION (-2836)
+%define VERR_PDM_INVALID_DEVICE_GUEST_BITS (-2837)
+%define VERR_PDM_INVALID_DEVICE_HOST_BITS (-2838)
+%define VERR_PDM_DEVICE_NAME_CLASH (-2839)
+%define VERR_PDM_DEVICE_NOT_FOUND (-2840)
+%define VERR_PDM_DEVICE_INSTANCE_NOT_FOUND (-2841)
+%define VERR_PDM_DEVICE_INSTANCE_NO_IBASE (-2842)
+%define VERR_PDM_DEVICE_INSTANCE_LUN_NOT_FOUND (-2843)
+%define VERR_PDM_DRIVER_INSTANCE_NOT_FOUND (-2844)
+%define VERR_PDM_LUN_NOT_FOUND (-2845)
+%define VERR_PDM_NO_DRIVER_ATTACHED_TO_LUN (-2846)
+%define VINF_PDM_NO_DRIVER_ATTACHED_TO_LUN 2846
+%define VERR_PDM_NO_PIC_INSTANCE (-2847)
+%define VERR_PDM_NO_APIC_INSTANCE (-2848)
+%define VERR_PDM_NO_DMAC_INSTANCE (-2849)
+%define VERR_PDM_NO_RTC_INSTANCE (-2850)
+%define VERR_PDM_HIF_SHARING_VIOLATION (-2851)
+%define VERR_PDM_HIF_OPEN_FAILED (-2852)
+%define VERR_PDM_DEVICE_NO_RT_ATTACH (-2853)
+%define VERR_PDM_DRIVER_NO_RT_ATTACH (-2854)
+%define VERR_PDM_HIF_INVALID_VERSION (-2855)
+%define VERR_PDM_UNKNOWN_USBREG_VERSION (-2856)
+%define VERR_PDM_INVALID_USB_REGISTRATION (-2857)
+%define VERR_PDM_USB_NAME_CLASH (-2858)
+%define VERR_PDM_USB_HUB_EXISTS (-2859)
+%define VERR_PDM_NO_USB_HUBS (-2860)
+%define VERR_PDM_NO_USB_PORTS (-2861)
+%define VERR_PDM_NO_USBPROXY (-2862)
+%define VERR_PDM_ASYNC_TEMPLATE_BUSY (-2863)
+%define VERR_PDM_ASYNC_COMPLETION_ALREADY_SUSPENDED (-2864)
+%define VERR_PDM_ASYNC_COMPLETION_NOT_SUSPENDED (-2865)
+%define VERR_PDM_DRIVER_INVALID_PROPERTIES (-2866)
+%define VERR_PDM_TOO_MANY_DEVICE_INSTANCES (-2867)
+%define VERR_PDM_TOO_MANY_DRIVER_INSTANCES (-2868)
+%define VERR_PDM_TOO_MANY_USB_DEVICE_INSTANCES (-2869)
+%define VERR_PDM_DEVINS_VERSION_MISMATCH (-2870)
+%define VERR_PDM_DEVHLP_VERSION_MISMATCH (-2871)
+%define VERR_PDM_USBINS_VERSION_MISMATCH (-2872)
+%define VERR_PDM_USBHLPR3_VERSION_MISMATCH (-2873)
+%define VERR_PDM_DRVINS_VERSION_MISMATCH (-2874)
+%define VERR_PDM_DRVHLPR3_VERSION_MISMATCH (-2875)
+%define VERR_PDM_DEVICE_VERSION_MISMATCH (-2876)
+%define VERR_PDM_USBDEV_VERSION_MISMATCH (-2877)
+%define VERR_PDM_DRIVER_VERSION_MISMATCH (-2878)
+%define VERR_PDM_DEV_HEAP_R3_TO_GCPHYS (-2879)
+%define VERR_PDM_HPET_LEGACY_NOTIFY_MISSING (-2880)
+%define VERR_PDM_CRITSECT_IPE (-2881)
+%define VERR_PDM_CRITSECT_NOT_FOUND (-2882)
+%define VERR_PDM_THREAD_INVALID_CALLER (-2883)
+%define VERR_PDM_THREAD_IPE_1 (-2884)
+%define VERR_PDM_THREAD_IPE_2 (-2885)
+%define VERR_PDM_ONE_PCI_FUNCTION_PER_DEVICE (-2886)
+%define VERR_PDM_BAD_PCI_CONFIG (-2887)
+%define VERR_PDM_DEV_IPE_1 (-2888)
+%define VERR_PDM_MISCONFIGURED_DRV_TRANSFORMATION (-2889)
+%define VERR_PDM_CANNOT_TRANSFORM_REMOVED_DRIVER (-2890)
+%define VERR_PDM_NOT_PCI_BUS_MASTER (-2891)
+%define VERR_PDM_HM_IPE (-2892)
+%define VERR_PDM_MEDIAEX_IOREQ_CANCELED (-2893)
+%define VERR_PDM_MEDIAEX_IOBUF_OVERFLOW (-2894)
+%define VERR_PDM_MEDIAEX_IOBUF_UNDERRUN (-2895)
+%define VERR_PDM_MEDIAEX_IOREQID_CONFLICT (-2896)
+%define VERR_PDM_MEDIAEX_IOREQID_NOT_FOUND (-2897)
+%define VINF_PDM_MEDIAEX_IOREQ_IN_PROGRESS 2898
+%define VERR_PDM_MEDIAEX_IOREQ_INVALID_STATE (-2899)
+%define VINF_PDM_PCI_DO_DEFAULT (7200)
+%define VERR_PDM_CRITSECT_ABORT_FAILED (-7201)
+%define VERR_PDM_CRITSECTRW_TOO_MANY_READERS (-7202)
+%define VERR_PDM_CRITSECTRW_TOO_MANY_WRITERS (-7203)
+%define VERR_PDM_CRITSECTRW_TOO_MANY_RECURSIONS (-7204)
+%define VERR_PDM_CRITSECTRW_IPE (-7205)
+%define VERR_PDM_CRITSECTRW_MISALIGNED (-7206)
+%define VERR_HGCM_SERVICE_NOT_FOUND (-2900)
+%define VINF_HGCM_CLIENT_REJECTED 2901
+%define VERR_HGCM_INVALID_CMD_ADDRESS (-2902)
+%define VINF_HGCM_ASYNC_EXECUTE 2903
+%define VERR_HGCM_INTERNAL (-2904)
+%define VERR_HGCM_INVALID_CLIENT_ID (-2905)
+%define VINF_HGCM_SAVE_STATE (2906)
+%define VERR_HGCM_SERVICE_EXISTS (-2907)
+%define VERR_HGCM_TOO_MANY_CLIENTS (-2908)
+%define VERR_HGCM_TOO_MANY_CLIENT_CALLS (-2909)
+%define VERR_NAT_REDIR_GUEST_IP (-3001)
+%define VERR_NAT_REDIR_SETUP (-3002)
+%define VERR_HOSTIF_INIT_FAILED (-3100)
+%define VERR_HOSTIF_DEVICE_NAME_TOO_LONG (-3101)
+%define VERR_HOSTIF_IOCTL (-3102)
+%define VERR_HOSTIF_BLOCKING (-3103)
+%define VERR_HOSTIF_FD_AND_INIT_TERM (-3104)
+%define VERR_HOSTIF_TERM_FAILED (-3105)
+%define VERR_VD_INVALID_TYPE (-3200)
+%define VERR_VD_INVALID_STATE (-3201)
+%define VERR_VD_VALUE_NOT_FOUND (-3202)
+%define VERR_VD_NOT_OPENED (-3203)
+%define VERR_VD_IMAGE_NOT_FOUND (-3204)
+%define VERR_VD_IMAGE_READ_ONLY (-3205)
+%define VERR_VD_GEOMETRY_NOT_SET (-3206)
+%define VERR_VD_BLOCK_FREE (-3207)
+%define VERR_VD_UUID_MISMATCH (-3208)
+%define VINF_VD_ASYNC_IO_FINISHED 3209
+%define VERR_VD_ASYNC_IO_IN_PROGRESS (-3210)
+%define VERR_VD_INVALID_SIZE (-3211)
+%define VERR_VD_UNKNOWN_CFG_VALUES (-3212)
+%define VERR_VD_UNKNOWN_INTERFACE (-3213)
+%define VERR_VD_DEK_MISSING (-3214)
+%define VERR_VD_PASSWORD_INCORRECT (-3215)
+%define VERR_VD_GEN_INVALID_HEADER (-3220)
+%define VERR_VD_VDI_INVALID_HEADER (-3230)
+%define VERR_VD_VDI_INVALID_SIGNATURE (-3231)
+%define VERR_VD_VDI_UNSUPPORTED_VERSION (-3232)
+%define VERR_VD_VDI_COMMENT_TOO_LONG (-3233)
+%define VERR_VD_VMDK_INVALID_HEADER (-3240)
+%define VERR_VD_VMDK_UNSUPPORTED_VERSION (-3241)
+%define VERR_VD_VMDK_VALUE_NOT_FOUND (-3242)
+%define VERR_VD_VMDK_INVALID_STATE (-3243)
+%define VERR_VD_VMDK_INVALID_FORMAT (-3244)
+%define VERR_VD_VMDK_INVALID_WRITE (-3245)
+%define VERR_VD_ISCSI_INVALID_HEADER (-3250)
+%define VERR_VD_ISCSI_INVALID_STATE (-3251)
+%define VERR_VD_ISCSI_INVALID_TYPE (-3252)
+%define VERR_VD_ISCSI_SECRET_ENCRYPTED (-3253)
+%define VERR_VD_VHD_INVALID_HEADER (-3260)
+%define VERR_VD_PARALLELS_INVALID_HEADER (-3265)
+%define VERR_VD_DMG_INVALID_HEADER (-3267)
+%define VERR_VD_RAW_INVALID_HEADER (-3270)
+%define VERR_VD_RAW_INVALID_TYPE (-3271)
+%define VERR_VD_NOT_ENOUGH_METADATA (-3272)
+%define VERR_VD_IOCTX_HALT (-3273)
+%define VERR_VD_CACHE_ALREADY_EXISTS (-3274)
+%define VERR_VD_CACHE_NOT_FOUND (-3275)
+%define VERR_VD_CACHE_NOT_UP_TO_DATE (-3276)
+%define VERR_VD_DISCARD_ALIGNMENT_NOT_MET (-3277)
+%define VERR_VD_DISCARD_NOT_SUPPORTED (-3278)
+%define VERR_VD_IMAGE_CORRUPTED (-3279)
+%define VERR_VD_IMAGE_REPAIR_NOT_SUPPORTED (-3280)
+%define VERR_VD_IMAGE_REPAIR_IMPOSSIBLE (-3281)
+%define VERR_VD_READ_OUT_OF_RANGE (-3282)
+%define VINF_VD_NEW_ZEROED_BLOCK 3283
+%define VERR_VD_DMG_XML_PARSE_ERROR (-3284)
+%define VERR_VD_DMG_NOT_FOUND_INSIDE_XAR (-3285)
+%define VERR_VD_RAW_SIZE_MODULO_512 (-3286)
+%define VERR_VD_RAW_SIZE_MODULO_2048 (-3287)
+%define VERR_VD_RAW_SIZE_OPTICAL_TOO_SMALL (-3288)
+%define VERR_VD_RAW_SIZE_FLOPPY_TOO_BIG (-3289)
+%define VERR_VD_SHRINK_NOT_SUPPORTED (-3290)
+%define VERR_VBGL_NOT_INITIALIZED (-3300)
+%define VERR_VBGL_INVALID_ADDR (-3301)
+%define VERR_VBGL_IOCTL_FAILED (-3302)
+%define VERR_VUSB_NO_PORTS (-3400)
+%define VERR_VUSB_DEVICE_NOT_ATTACHED (-3401)
+%define VERR_VUSB_NO_URB_MEMORY (-3402)
+%define VERR_VUSB_FAILED_TO_QUEUE_URB (-3403)
+%define VERR_VUSB_DEVICE_NAME_NOT_FOUND (-3404)
+%define VERR_VUSB_USBFS_PERMISSION (-3405)
+%define VERR_VUSB_DEVICE_IS_RESETTING (-3406)
+%define VERR_VUSB_DEVICE_IS_SUSPENDED (-3407)
+%define VERR_VUSB_USB_DEVICE_PERMISSION (-3408)
+%define VERR_VGA_INVALID_CUSTOM_MODE (-3500)
+%define VINF_VGA_RESIZE_IN_PROGRESS (3501)
+%define VERR_VGA_UNEXPECTED_PCI_REGION_LOAD_CHANGE (-3502)
+%define VERR_VGA_GL_LOAD_FAILURE (-3503)
+%define VERR_VGA_GL_SYMBOL_NOT_FOUND (-3504)
+%define VERR_INTNET_FLT_IF_NOT_FOUND (-3600)
+%define VERR_INTNET_FLT_IF_BUSY (-3601)
+%define VERR_INTNET_FLT_IF_FAILED (-3602)
+%define VERR_INTNET_INCOMPATIBLE_TRUNK (-3603)
+%define VERR_INTNET_INCOMPATIBLE_FLAGS (-3604)
+%define VERR_INTNET_FLT_VNIC_CREATE_FAILED (-3605)
+%define VERR_INTNET_FLT_VNIC_LINK_ID_NOT_FOUND (-3606)
+%define VERR_INTNET_FLT_VNIC_INIT_FAILED (-3607)
+%define VERR_INTNET_FLT_VNIC_OPEN_FAILED (-3608)
+%define VERR_INTNET_FLT_LOWER_LINK_INFO_NOT_FOUND (-3609)
+%define VERR_INTNET_FLT_LOWER_LINK_OPEN_FAILED (-3610)
+%define VERR_INTNET_FLT_LOWER_LINK_ID_NOT_FOUND (-3611)
+%define VERR_SUPDRV_COMPONENT_NOT_FOUND (-3700)
+%define VERR_SUPDRV_INTERFACE_NOT_SUPPORTED (-3701)
+%define VERR_SUPDRV_SERVICE_NOT_FOUND (-3702)
+%define VERR_SUPDRV_KERNEL_TOO_OLD_FOR_VTX (-3703)
+%define VERR_SUPDRV_VTG_MAGIC (-3704)
+%define VERR_SUPDRV_VTG_BITS (-3705)
+%define VERR_SUPDRV_VTG_BAD_HDR_MISC (-3706)
+%define VERR_SUPDRV_VTG_BAD_HDR_OFF (-3707)
+%define VERR_SUPDRV_VTG_BAD_HDR_PTR (-3708)
+%define VERR_SUPDRV_VTG_BAD_HDR_TOO_FEW (-3709)
+%define VERR_SUPDRV_VTG_BAD_HDR_TOO_MUCH (-3710)
+%define VERR_SUPDRV_VTG_BAD_HDR_NOT_MULTIPLE (-3711)
+%define VERR_SUPDRV_VTG_STRTAB_OFF (-3712)
+%define VERR_SUPDRV_VTG_BAD_STRING (-3713)
+%define VERR_SUPDRV_VTG_STRING_TOO_LONG (-3714)
+%define VERR_SUPDRV_VTG_BAD_ATTR (-3715)
+%define VERR_SUPDRV_VTG_BAD_PROVIDER (-3716)
+%define VERR_SUPDRV_VTG_BAD_PROBE (-3717)
+%define VERR_SUPDRV_VTG_BAD_ARGLIST (-3718)
+%define VERR_SUPDRV_VTG_BAD_PROBE_ENABLED (-3719)
+%define VERR_SUPDRV_VTG_BAD_PROBE_LOC (-3720)
+%define VERR_SUPDRV_VTG_ALREADY_REGISTERED (-3721)
+%define VERR_SUPDRV_VTG_ONLY_ONCE_PER_SESSION (-3722)
+%define VERR_SUPDRV_TRACER_ALREADY_REGISTERED (-3723)
+%define VERR_SUPDRV_TRACER_NOT_REGISTERED (-3724)
+%define VERR_SUPDRV_TRACER_ALREADY_OPENED (-3725)
+%define VERR_SUPDRV_TRACER_NOT_OPENED (-3726)
+%define VERR_SUPDRV_TRACER_NOT_PRESENT (-3727)
+%define VERR_SUPDRV_TRACER_UNLOADING (-3728)
+%define VERR_SUPDRV_TRACER_SESSION_BUSY (-3729)
+%define VERR_SUPDRV_TRACER_CANNOT_OPEN_SELF (-3730)
+%define VERR_SUPDRV_TRACER_BAD_ARG_FLAGS (-3731)
+%define VERR_SUPDRV_TRACER_TOO_MANY_PROVIDERS (-3732)
+%define VERR_SUPDRV_TRACER_TOO_LARGE (-3733)
+%define VERR_SUPDRV_TRACER_UMOD_NOT_ADJACENT (-3734)
+%define VERR_SUPDRV_TRACER_UMOD_TOO_MANY_PROBES (-3735)
+%define VERR_SUPDRV_TRACER_UMOD_STRTAB_TOO_BIG (-3736)
+%define VERR_SUPDRV_TRACER_UMOD_STRTAB_OFF_BAD (-3737)
+%define VERR_SUPDRV_HARDENING_EVIL_HANDLE (-3738)
+%define VERR_SUPDRV_APIPORT_OPEN_ERROR (-3739)
+%define VERR_SUPDRV_SESSION_PROCESS_ENUM_ERROR (-3740)
+%define VERR_SUPDRV_CSRSS_NOT_FOUND (-3741)
+%define VERR_SUPDRV_APIPORT_OPEN_ERROR_TYPE (-3742)
+%define VERR_SUPDRV_TSC_DELTA_MEASUREMENT_FAILED (-3743)
+%define VERR_SUPDRV_TSC_FREQ_MEASUREMENT_FAILED (-3744)
+%define VERR_SUPDRV_TSC_READ_FAILED (-3745)
+%define VWRN_SUPDRV_TSC_DELTA_MEASUREMENT_FAILED 3746
+%define VERR_SUPDRV_TSC_DELTA_MEASUREMENT_BUSY (-3747)
+%define VERR_SUPDRV_NOT_BUDDING_VM_PROCESS_1 (-3748)
+%define VERR_SUPDRV_NOT_BUDDING_VM_PROCESS_2 (-3749)
+%define VERR_SUPDRV_NO_RAW_MODE_HYPER_V_ROOT (-7000)
+%define VERR_SUPLIB_PATH_NOT_ABSOLUTE (-3750)
+%define VERR_SUPLIB_PATH_NOT_CLEAN (-3751)
+%define VERR_SUPLIB_PATH_TOO_LONG (-3752)
+%define VERR_SUPLIB_PATH_TOO_SHORT (-3753)
+%define VERR_SUPLIB_PATH_TOO_MANY_COMPONENTS (-3754)
+%define VERR_SUPLIB_PATH_IS_ROOT (-3755)
+%define VERR_SUPLIB_DIR_ENUM_FAILED (-3756)
+%define VERR_SUPLIB_STAT_ENUM_FAILED (-3757)
+%define VERR_SUPLIB_STAT_FAILED (-3758)
+%define VERR_SUPLIB_FSTAT_FAILED (-3759)
+%define VERR_SUPLIB_SYMLINKS_ARE_NOT_PERMITTED (-3760)
+%define VERR_SUPLIB_NOT_DIR_NOT_FILE (-3761)
+%define VERR_SUPLIB_IS_DIRECTORY (-3762)
+%define VERR_SUPLIB_IS_FILE (-3763)
+%define VERR_SUPLIB_NOT_SAME_OBJECT (-3764)
+%define VERR_SUPLIB_OWNER_NOT_ROOT (-3765)
+%define VERR_SUPLIB_WRITE_NON_SYS_GROUP (-3766)
+%define VERR_SUPLIB_WORLD_WRITABLE (-3767)
+%define VERR_SUPLIB_INVALID_ARGV0_INTERNAL (-3768)
+%define VERR_SUPLIB_INVALID_INTERNAL_APP_DIR (-3769)
+%define VERR_SUPLIB_NT_PROCESS_UNTRUSTED_0 (-3770)
+%define VERR_SUPLIB_NT_PROCESS_UNTRUSTED_1 (-3771)
+%define VERR_SUPLIB_NT_PROCESS_UNTRUSTED_2 (-3772)
+%define VERR_SUPLIB_NT_PROCESS_UNTRUSTED_3 (-3773)
+%define VERR_SUPLIB_NT_PROCESS_UNTRUSTED_4 (-3774)
+%define VERR_SUPLIB_NT_PROCESS_UNTRUSTED_5 (-3775)
+%define VERR_SUPLIB_TEXT_NOT_WRITEABLE (-3776)
+%define VERR_SUPLIB_TEXT_NOT_SEALED (-3777)
+%define VERR_SUPLIB_UNEXPECTED_INSTRUCTION (-3778)
+%define VERR_GMM_OUT_OF_MEMORY (-3801)
+%define VERR_GMM_HIT_GLOBAL_LIMIT (-3802)
+%define VERR_GMM_HIT_VM_ACCOUNT_LIMIT (-3803)
+%define VERR_GMM_ATTEMPT_TO_FREE_TOO_MUCH (-3804)
+%define VERR_GMM_ATTEMPT_TO_DEFLATE_TOO_MUCH (-3805)
+%define VERR_GMM_PAGE_NOT_FOUND (-3806)
+%define VERR_GMM_PAGE_NOT_PRIVATE (-3807)
+%define VERR_GMM_PAGE_NOT_SHARED (-3808)
+%define VERR_GMM_PAGE_ALREADY_FREE (-3809)
+%define VERR_GMM_NOT_PAGE_OWNER (-3810)
+%define VERR_GMM_CHUNK_NOT_FOUND (-3811)
+%define VERR_GMM_CHUNK_ALREADY_MAPPED (-3812)
+%define VERR_GMM_CHUNK_NOT_MAPPED (-3813)
+%define VERR_GMM_TOO_MANY_CHUNK_MAPPINGS (-3814)
+%define VERR_GMM_MEMORY_RESERVATION_DECLINED (-3815)
+%define VERR_GMM_IS_NOT_SANE (-3816)
+%define VERR_GMM_CHUNK_INSERT (-3817)
+%define VERR_GMM_INSTANCE (-3818)
+%define VERR_GMM_MTX_FLAGS (-3819)
+%define VERR_GMM_ALLOC_PAGES_IPE (-3820)
+%define VERR_GMM_ACTUAL_PAGES_IPE (-3821)
+%define VERR_GMM_MODULE_NAME_TOO_LONG (-3822)
+%define VERR_GMM_MODULE_VERSION_TOO_LONG (-3823)
+%define VERR_GMM_TOO_MANY_REGIONS (-3824)
+%define VERR_GMM_TOO_MANY_PER_VM_MODULES (-3825)
+%define VERR_GMM_TOO_MANY_GLOBAL_MODULES (-3826)
+%define VINF_GMM_SHARED_MODULE_ALREADY_REGISTERED (3827)
+%define VERR_GMM_SHARED_MODULE_ADDRESS_CLASH (-3828)
+%define VERR_GMM_SHARED_MODULE_NOT_FOUND (-3829)
+%define VERR_GMM_BAD_SHARED_MODULE_SIZE (-3830)
+%define VERR_GMM_SHARED_MODULE_BAD_REGIONS_SIZE (-3831)
+%define VERR_GVM_TOO_MANY_VMS (-3900)
+%define VINF_GVM_NOT_BLOCKED 3901
+%define VINF_GVM_NOT_BUSY_IN_GC 3902
+%define VINF_GVM_YIELDED 3903
+%define VERR_VMX_VMXON_FAILED (-4000)
+%define VERR_VMX_INVALID_VMCS_PTR (-4001)
+%define VERR_VMX_INVALID_VMCS_FIELD (-4002)
+%define VERR_VMX_RESERVED (-4003)
+%define VERR_VMX_INVALID_VMXON_PTR (-4004)
+%define VERR_VMX_UNABLE_TO_START_VM (-4005)
+%define VERR_VMX_INVALID_HOST_STATE (-4006)
+%define VERR_VMX_NO_VMX (-4009)
+%define VERR_VMX_IN_VMX_ROOT_MODE (-4011)
+%define VERR_VMX_X86_CR4_VMXE_CLEARED (-4012)
+%define VERR_VMX_MSR_LOCKING_FAILED (-4013)
+%define VERR_VMX_INVALID_GUEST_STATE (-4014)
+%define VERR_VMX_UNEXPECTED_EXIT (-4015)
+%define VERR_VMX_UNEXPECTED_EXCEPTION (-4016)
+%define VERR_VMX_UNEXPECTED_INTERRUPTION_EXIT_TYPE (-4017)
+%define VERR_VMX_NOT_IN_VMX_ROOT_MODE (-4018)
+%define VERR_VMX_UNDEFINED_EXIT_CODE (-4019)
+%define VERR_VMX_VMPTRLD_FAILED (-4021)
+%define VERR_VMX_INVALID_VMCS_PTR_TO_START_VM (-4022)
+%define VERR_VMX_IPE_1 (-4023)
+%define VERR_VMX_IPE_2 (-4024)
+%define VERR_VMX_IPE_3 (-4025)
+%define VERR_VMX_IPE_4 (-4026)
+%define VERR_VMX_IPE_5 (-4027)
+%define VERR_VMX_MSR_ALL_VMX_DISABLED (-4028)
+%define VERR_VMX_MSR_VMX_DISABLED (-4029)
+%define VERR_VMX_VMCS_FIELD_CACHE_INVALID (-4030)
+%define VERR_VMX_MSR_VMX_ENABLE_FAILED (-4031)
+%define VERR_VMX_MSR_SMX_VMX_ENABLE_FAILED (-4032)
+%define VINF_VMX_VMEXIT 4033
+%define VERR_VMX_VMENTRY_FAILED (-4033)
+%define VERR_VMX_VMEXIT_FAILED (-4034)
+%define VINF_VMX_INTERCEPT_NOT_ACTIVE 4035
+%define VINF_VMX_MODIFIES_BEHAVIOR 4036
+%define VINF_VMX_VMLAUNCH_VMRESUME 4037
+%define VERR_VMX_INVALID_VMCS_LAUNCH_STATE (-4038)
+%define VERR_VMX_STARTVM_PRECOND_0 (-4039)
+%define VERR_VMX_STARTVM_PRECOND_1 (-4040)
+%define VERR_VMX_STARTVM_PRECOND_2 (-4041)
+%define VERR_VMX_STARTVM_PRECOND_3 (-4042)
+%define VERR_SVM_UNABLE_TO_START_VM (-4050)
+%define VERR_SVM_ILLEGAL_EFER_MSR (-4051)
+%define VERR_SVM_NO_SVM (-4052)
+%define VERR_SVM_DISABLED (-4053)
+%define VERR_SVM_IN_USE (-4054)
+%define VERR_SVM_INVALID_PVMCB (-4055)
+%define VERR_SVM_UNEXPECTED_EXIT (-4056)
+%define VERR_SVM_UNEXPECTED_XCPT_EXIT (-4057)
+%define VERR_SVM_UNEXPECTED_PATCH_TYPE (-4058)
+%define VERR_SVM_INVALID_GUEST_STATE (-4059)
+%define VERR_SVM_UNKNOWN_EXIT (-4060)
+%define VERR_SVM_IPE_1 (-4061)
+%define VERR_SVM_IPE_2 (-4062)
+%define VERR_SVM_IPE_3 (-4063)
+%define VERR_SVM_IPE_4 (-4064)
+%define VERR_SVM_IPE_5 (-4065)
+%define VERR_SVM_VMEXIT_FAILED (-4066)
+%define VINF_SVM_VMEXIT 4067
+%define VINF_SVM_VMRUN 4068
+%define VINF_SVM_INTERCEPT_NOT_ACTIVE 4069
+%define VERR_SVM_VMRUN_PRECOND_0 (-4070)
+%define VERR_SVM_VMRUN_PRECOND_1 (-4071)
+%define VERR_SVM_VMRUN_PRECOND_2 (-4072)
+%define VERR_SVM_VMRUN_PRECOND_3 (-4073)
+%define VERR_HM_SUSPEND_PENDING (-4100)
+%define VERR_HM_CONFIG_MISMATCH (-4103)
+%define VERR_HM_ALREADY_ENABLED_IPE (-4104)
+%define VERR_HM_UNEXPECTED_LD_ST_MSR (-4105)
+%define VERR_HM_NO_32_TO_64_SWITCHER (-4106)
+%define VERR_HM_WRONG_CPU (-4107)
+%define VERR_HM_IPE_1 (-4108)
+%define VERR_HM_IPE_2 (-4109)
+%define VERR_HM_WRONG_SWITCHER (-4110)
+%define VERR_HM_UNKNOWN_IO_INSTRUCTION (-4111)
+%define VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO (-4112)
+%define VERR_HM_IPE_3 (-4113)
+%define VERR_HM_IPE_4 (-4114)
+%define VERR_HM_IPE_5 (-4115)
+%define VERR_HM_INVALID_HM64ON32OP (-4116)
+%define VINF_HM_DOUBLE_FAULT 4117
+%define VINF_HM_PENDING_XCPT 4118
+%define VERR_DIS_INVALID_OPCODE (-4200)
+%define VERR_DIS_GEN_FAILURE (-4201)
+%define VERR_DIS_NO_READ_CALLBACK (-4202)
+%define VERR_DIS_INVALID_MODRM (-4203)
+%define VERR_DIS_INVALID_PARAMETER (-4204)
+%define VERR_DIS_TOO_LONG_INSTR (-4206)
+%define VERR_WEB_NOT_AUTHENTICATED (-4300)
+%define VERR_WEB_INVALID_MANAGED_OBJECT_REFERENCE (-4301)
+%define VERR_WEB_INVALID_SESSION_ID (-4302)
+%define VERR_WEB_INVALID_OBJECT_ID (-4303)
+%define VERR_WEB_UNSUPPORTED_INTERFACE (-4304)
+%define VINF_PARAV_SWITCH_TO_HOST 4400
+%define VINF_VHWA_CMD_PENDING 4500
+%define VERR_COM_UNEXPECTED (-4600)
+%define VERR_COM_VBOX_LOWEST (-4699)
+%define VERR_COM_OBJECT_NOT_FOUND (VERR_COM_VBOX_LOWEST + 1)
+%define VERR_COM_INVALID_VM_STATE (VERR_COM_VBOX_LOWEST + 2)
+%define VERR_COM_VM_ERROR (VERR_COM_VBOX_LOWEST + 3)
+%define VERR_COM_FILE_ERROR (VERR_COM_VBOX_LOWEST + 4)
+%define VERR_COM_IPRT_ERROR (VERR_COM_VBOX_LOWEST + 5)
+%define VERR_COM_PDM_ERROR (VERR_COM_VBOX_LOWEST + 6)
+%define VERR_COM_INVALID_OBJECT_STATE (VERR_COM_VBOX_LOWEST + 7)
+%define VERR_COM_HOST_ERROR (VERR_COM_VBOX_LOWEST + 8)
+%define VERR_COM_NOT_SUPPORTED (VERR_COM_VBOX_LOWEST + 9)
+%define VERR_COM_XML_ERROR (VERR_COM_VBOX_LOWEST + 10)
+%define VERR_COM_INVALID_SESSION_STATE (VERR_COM_VBOX_LOWEST + 11)
+%define VERR_COM_OBJECT_IN_USE (VERR_COM_VBOX_LOWEST + 12)
+%define VERR_COM_DONT_CALL_AGAIN (VERR_COM_VBOX_LOWEST + 13)
+%define VERR_VMMDEV_CPU_HOTPLUG_NOT_MONITORED_BY_GUEST (-4700)
+%define VINF_AIO_TASK_PENDING 4800
+%define VERR_VSCSI_LUN_TYPE_NOT_SUPPORTED (-4900)
+%define VERR_VSCSI_LUN_ATTACHED_TO_DEVICE (-4901)
+%define VERR_VSCSI_LUN_INVALID (-4902)
+%define VERR_VSCSI_LUN_NOT_ATTACHED (-4903)
+%define VERR_VSCSI_LUN_BUSY (-4904)
+%define VERR_FAM_OPEN_FAILED (-5000)
+%define VERR_FAM_MONITOR_FILE_FAILED (-5001)
+%define VERR_FAM_MONITOR_DIRECTORY_FAILED (-5002)
+%define VERR_FAM_CONNECTION_LOST (-5003)
+%define VERR_PCI_PASSTHROUGH_NO_RAM_PREALLOC (-5100)
+%define VERR_PCI_PASSTHROUGH_NO_HM (-5101)
+%define VERR_PCI_PASSTHROUGH_NO_NESTED_PAGING (-5102)
+%define VINF_PCI_MAPPING_DONE 5150
+%define VERR_GVMM_INSTANCE (-5200)
+%define VERR_GVMM_HOST_CPU_RANGE (-5201)
+%define VERR_GVMM_BROKEN_IPRT (-5202)
+%define VERR_GVMM_IPE_1 (-5203)
+%define VERR_GVMM_IPE_2 (-5204)
+%define VERR_GVMM_NOT_ALL_EMTS_DEREGISTERED (-5205)
+%define VERR_IEM_INSTR_NOT_IMPLEMENTED (-5300)
+%define VERR_IEM_INVALID_OPERAND_SIZE (-5301)
+%define VERR_IEM_INVALID_ADDRESS_MODE (-5302)
+%define VERR_IEM_INVALID_EFF_SEG (-5303)
+%define VERR_IEM_INVALID_INSTR_LENGTH (-5304)
+%define VINF_IEM_SELECTOR_NOT_OK (5305)
+%define VERR_IEM_RESTART_INSTRUCTION (-5389)
+%define VERR_IEM_ASPECT_NOT_IMPLEMENTED (-5390)
+%define VERR_IEM_IPE_1 (-5391)
+%define VERR_IEM_IPE_2 (-5392)
+%define VERR_IEM_IPE_3 (-5393)
+%define VERR_IEM_IPE_4 (-5394)
+%define VERR_IEM_IPE_5 (-5395)
+%define VERR_IEM_IPE_6 (-5396)
+%define VERR_IEM_IPE_7 (-5397)
+%define VERR_IEM_IPE_8 (-5398)
+%define VERR_IEM_IPE_9 (-5399)
+%define VERR_DBGC_QUIT (-5400)
+%define VWRN_DBGC_CMD_PENDING 5401
+%define VWRN_DBGC_ALREADY_REGISTERED 5402
+%define VERR_DBGC_COMMANDS_NOT_REGISTERED (-5403)
+%define VERR_DBGC_BP_NOT_FOUND (-5404)
+%define VERR_DBGC_BP_EXISTS (-5405)
+%define VINF_DBGC_BP_NO_COMMAND 5406
+%define VERR_DBGC_COMMAND_FAILED (-5407)
+%define VERR_DBGC_IPE (-5408)
+%define VERR_DBGC_PARSE_LOWEST (-5499)
+%define VERR_DBGC_PARSE_TOO_FEW_ARGUMENTS (VERR_DBGC_PARSE_LOWEST + 0)
+%define VERR_DBGC_PARSE_TOO_MANY_ARGUMENTS (VERR_DBGC_PARSE_LOWEST + 1)
+%define VERR_DBGC_PARSE_ARGUMENT_OVERFLOW (VERR_DBGC_PARSE_LOWEST + 2)
+%define VERR_DBGC_PARSE_EXPECTED_BINARY_OP (VERR_DBGC_PARSE_LOWEST + 3)
+%define VERR_DBGC_PARSE_NO_RANGE_ALLOWED (VERR_DBGC_PARSE_LOWEST + 5)
+%define VERR_DBGC_PARSE_UNBALANCED_QUOTE (VERR_DBGC_PARSE_LOWEST + 6)
+%define VERR_DBGC_PARSE_UNBALANCED_PARENTHESIS (VERR_DBGC_PARSE_LOWEST + 7)
+%define VERR_DBGC_PARSE_EMPTY_ARGUMENT (VERR_DBGC_PARSE_LOWEST + 8)
+%define VERR_DBGC_PARSE_UNEXPECTED_OPERATOR (VERR_DBGC_PARSE_LOWEST + 9)
+%define VERR_DBGC_PARSE_INVALID_NUMBER (VERR_DBGC_PARSE_LOWEST + 10)
+%define VERR_DBGC_PARSE_NUMBER_TOO_BIG (VERR_DBGC_PARSE_LOWEST + 11)
+%define VERR_DBGC_PARSE_INVALID_OPERATION (VERR_DBGC_PARSE_LOWEST + 12)
+%define VERR_DBGC_PARSE_FUNCTION_NOT_FOUND (VERR_DBGC_PARSE_LOWEST + 13)
+%define VERR_DBGC_PARSE_NOT_A_FUNCTION (VERR_DBGC_PARSE_LOWEST + 14)
+%define VERR_DBGC_PARSE_NO_SCRATCH (VERR_DBGC_PARSE_LOWEST + 15)
+%define VERR_DBGC_PARSE_NO_MEMORY (VERR_DBGC_PARSE_LOWEST + 16)
+%define VERR_DBGC_PARSE_INCORRECT_ARG_TYPE (VERR_DBGC_PARSE_LOWEST + 17)
+%define VERR_DBGC_PARSE_VARIABLE_NOT_FOUND (VERR_DBGC_PARSE_LOWEST + 18)
+%define VERR_DBGC_PARSE_CONVERSION_FAILED (VERR_DBGC_PARSE_LOWEST + 19)
+%define VERR_DBGC_PARSE_NOT_IMPLEMENTED (VERR_DBGC_PARSE_LOWEST + 20)
+%define VERR_DBGC_PARSE_BAD_RESULT_TYPE (VERR_DBGC_PARSE_LOWEST + 21)
+%define VERR_DBGC_PARSE_WRITEONLY_SYMBOL (VERR_DBGC_PARSE_LOWEST + 22)
+%define VERR_DBGC_PARSE_INVALD_COMMAND_NAME (VERR_DBGC_PARSE_LOWEST + 23)
+%define VERR_DBGC_PARSE_COMMAND_NOT_FOUND (VERR_DBGC_PARSE_LOWEST + 24)
+%define VERR_DBGC_PARSE_BUG (VERR_DBGC_PARSE_LOWEST + 25)
+%define VERR_SUP_VP_MEMORY_VS_FILE_MISMATCH (-5600)
+%define VERR_SUP_VP_SECTION_PROTECTION_MISMATCH (-5601)
+%define VERR_SUP_VP_SECTION_NOT_MAPPED (-5602)
+%define VERR_SUP_VP_SECTION_NOT_FULLY_MAPPED (-5603)
+%define VERR_SUP_VP_BAD_FILE_ALIGNMENT_VALUE (-5604)
+%define VERR_SUP_VP_BAD_IMAGE_BASE (-5605)
+%define VERR_SUP_VP_BAD_IMAGE_SIGNATURE (-5606)
+%define VERR_SUP_VP_BAD_IMAGE_SIZE (-5607)
+%define VERR_SUP_VP_BAD_MZ_OFFSET (-5608)
+%define VERR_SUP_VP_BAD_OPTIONAL_HEADER (-5609)
+%define VERR_SUP_VP_BAD_SECTION_ALIGNMENT_VALUE (-5610)
+%define VERR_SUP_VP_BAD_SECTION_FILE_SIZE (-5611)
+%define VERR_SUP_VP_BAD_SECTION_RVA (-5612)
+%define VERR_SUP_VP_BAD_SECTION_VIRTUAL_SIZE (-5613)
+%define VERR_SUP_VP_BAD_SIZE_OF_HEADERS (-5614)
+%define VERR_SUP_VP_DEBUGGED (-5615)
+%define VERR_SUP_VP_DUPLICATE_DLL_MAPPING (-5616)
+%define VERR_SUP_VP_EMPTY_REGION_TOO_LARGE (-5617)
+%define VERR_SUP_VP_EXE_VS_PROC_NAME_MISMATCH (-5618)
+%define VERR_SUP_VP_FOUND_EXEC_MEMORY (-5619)
+%define VERR_SUP_VP_FOUND_MORE_THAN_ONE_EXE_MAPPING (-5620)
+%define VERR_SUP_VP_IMAGE_FILE_CLOSE_ERROR (-5621)
+%define VERR_SUP_VP_IMAGE_FILE_OPEN_ERROR (-5622)
+%define VERR_SUP_VP_IMAGE_HDR_READ_ERROR (-5623)
+%define VERR_SUP_VP_IMAGE_MAPPING_BASE_ERROR (-5624)
+%define VERR_SUP_VP_MEMORY_READ_ERROR (-5625)
+%define VERR_SUP_VP_NO_FOUND_NO_EXE_MAPPING (-5626)
+%define VERR_SUP_VP_NO_IMAGE_MAPPING_NAME (-5627)
+%define VERR_SUP_VP_NO_KERNEL32_MAPPING (-5628)
+%define VERR_SUP_VP_NO_MEMORY (-5629)
+%define VERR_SUP_VP_NO_MEMORY_STATE (-5630)
+%define VERR_SUP_VP_NO_NTDLL_MAPPING (-5631)
+%define VERR_SUP_VP_NON_SYSTEM32_DLL (-5632)
+%define VERR_SUP_VP_NOT_KNOWN_DLL_OR_EXE (-5633)
+%define VERR_SUP_VP_NT_MAPPING_NAME_CHANGED (-5634)
+%define VERR_SUP_VP_NT_QI_PROCESS_NM_ERROR (-5635)
+%define VERR_SUP_VP_NT_QI_THREAD_ERROR (-5636)
+%define VERR_SUP_VP_NT_QI_VIRTUAL_MEMORY_ERROR (-5637)
+%define VERR_SUP_VP_NT_QI_VIRTUAL_MEMORY_NM_ERROR (-5638)
+%define VERR_SUP_VP_SYSTEM32_PATH (-5639)
+%define VERR_SUP_VP_THREAD_NOT_ALONE (-5640)
+%define VERR_SUP_VP_TOO_HIGH_REGION_RVA (-5641)
+%define VERR_SUP_VP_TOO_LARGE_REGION (-5642)
+%define VERR_SUP_VP_TOO_MANY_DLLS_LOADED (-5643)
+%define VERR_SUP_VP_TOO_MANY_IMAGE_REGIONS (-5644)
+%define VERR_SUP_VP_TOO_MANY_MEMORY_REGIONS (-5645)
+%define VERR_SUP_VP_TOO_MANY_SECTIONS (-5646)
+%define VERR_SUP_VP_UNEXPECTED_IMAGE_MACHINE (-5647)
+%define VERR_SUP_VP_UNEXPECTED_SECTION_FLAGS (-5648)
+%define VERR_SUP_VP_EXE_MISSING_FORCE_INTEGRITY (-5649)
+%define VERR_SUP_VP_EXE_MISSING_DYNAMIC_BASE (-5650)
+%define VERR_SUP_VP_EXE_MISSING_NX_COMPAT (-5651)
+%define VERR_SUP_VP_DLL_CHARECTERISTICS_MISMATCH (-5652)
+%define VERR_SUP_VP_IMAGE_CHARECTERISTICS_MISMATCH (-5653)
+%define VERR_SUP_VP_NT_QI_PROCESS_IMG_INFO_ERROR (-5654)
+%define VERR_SUP_VP_NT_QI_PROCESS_DBG_PORT_ERROR (-5655)
+%define VERR_SUP_VP_WINTRUST_CAT_FAILURE (-5656)
+%define VERR_SUP_VP_NOT_SIGNED_WITH_BUILD_CERT (-5657)
+%define VERR_SUP_VP_NOT_BUILD_CERT_IPE (-5658)
+%define VERR_SUP_VP_NOT_VALID_KERNEL_CODE_SIGNATURE (-5659)
+%define VERR_SUP_VP_UNEXPECTED_VALID_PATH_COUNT (-5660)
+%define VERR_SUP_VP_SIGNATURE_CHECKS_NOT_ENFORCED (-5661)
+%define VERR_SUP_VP_SYSFER_DLL (-5662)
+%define VERR_SUP_VP_KERNEL32_ALREADY_MAPPED (-5663)
+%define VERR_SUP_VP_FREE_VIRTUAL_MEMORY_FAILED (-5664)
+%define VERR_SUP_VP_UNMAP_AND_PROTECT_FAILED (-5665)
+%define VERR_SUP_VP_UNKOWN_MEM_TYPE (-5666)
+%define VERR_SUP_VP_NOT_OWNED_BY_TRUSTED_INSTALLER (-5667)
+%define VERR_SUP_VP_IMAGE_TOO_BIG (-5668)
+%define VERR_SUP_VP_STUB_NOT_FOUND (-5669)
+%define VERR_SUP_VP_STUB_OPEN_ERROR (-5670)
+%define VERR_SUP_VP_STUB_THREAD_NOT_FOUND (-5671)
+%define VERR_SUP_VP_STUB_THREAD_OPEN_ERROR (-5672)
+%define VERR_SUP_VP_REPLACE_VIRTUAL_MEMORY_FAILED (-5673)
+%define VERR_SUP_VP_FILE_MODE_ERROR (-5674)
+%define VERR_SUP_VP_CREATE_READ_EVT_SEM_FAILED (-5675)
+%define VERR_SUP_VP_UNDESIRABLE_MODULE (-5676)
+%define VERR_SUP_DRIVERLESS (-5699)
+%define VINF_SUP_DRIVERLESS 5699
+%define VERR_EXTPACK_UNSUPPORTED_HOST_UNINSTALL (-6000)
+%define VERR_EXTPACK_VBOX_VERSION_MISMATCH (-6001)
+%define VERR_GSTCTL_GUEST_ERROR (-6200)
+%define VWRN_GSTCTL_OBJECTSTATE_CHANGED 6220
+%define VERR_GSTCTL_PROCESS_WRONG_STATE (-6221)
+%define VERR_GSTCTL_MAX_CID_SESSIONS_REACHED (-6222)
+%define VERR_GSTCTL_MAX_CID_OBJECTS_REACHED (-6223)
+%define VERR_GSTCTL_MAX_CID_COUNT_REACHED (-6224)
+%define VERR_GSTCTL_PROCESS_EXIT_CODE (-6225)
+%define VERR_GIM_NOT_ENABLED (-6300)
+%define VERR_GIM_IPE_1 (-6301)
+%define VERR_GIM_IPE_2 (-6302)
+%define VERR_GIM_IPE_3 (-6303)
+%define VERR_GIM_PVTSC_NOT_AVAILABLE (-6304)
+%define VERR_GIM_PVTSC_NOT_ENABLED (-6305)
+%define VERR_GIM_INVALID_PROVIDER (-6306)
+%define VERR_GIM_OPERATION_FAILED (-6307)
+%define VERR_GIM_HYPERCALLS_NOT_AVAILABLE (-6308)
+%define VERR_GIM_HYPERCALLS_NOT_ENABLED (-6309)
+%define VERR_GIM_DEVICE_NOT_REGISTERED (-6310)
+%define VERR_GIM_HYPERCALL_ACCESS_DENIED (-6311)
+%define VERR_GIM_HYPERCALL_MEMORY_READ_FAILED (-6312)
+%define VERR_GIM_HYPERCALL_MEMORY_WRITE_FAILED (-6313)
+%define VERR_GIM_HYPERCALL_FAILED (-6314)
+%define VERR_GIM_NO_DEBUG_CONNECTION (-6315)
+%define VINF_GIM_R3_HYPERCALL 6316
+%define VINF_GIM_HYPERCALL_CONTINUING 6317
+%define VERR_GIM_INVALID_HYPERCALL_INSTR (-6318)
+%define VERR_MAIN_CONFIG_CONSTRUCTOR_COM_ERROR (-6400)
+%define VERR_MAIN_CONFIG_CONSTRUCTOR_IPE (-6401)
+%define VERR_GSTDND_GUEST_ERROR (-6500)
+%define VERR_AUDIO_BACKEND_INIT_FAILED (-6600)
+%define VERR_AUDIO_BACKEND_NOT_ATTACHED (-6601)
+%define VERR_AUDIO_NO_FREE_INPUT_STREAMS (-6602)
+%define VERR_AUDIO_NO_FREE_OUTPUT_STREAMS (-6603)
+%define VERR_AUDIO_STREAM_PENDING_DISABLE (-6604)
+%define VINF_AUDIO_MORE_DATA_AVAILABLE (6605)
+%define VERR_AUDIO_STREAM_NOT_READY (-6605)
+%define VERR_AUDIO_STREAM_COULD_NOT_CREATE (-6606)
+%define VERR_AUDIO_ENUMERATION_FAILED (-6607)
+%define VERR_AUDIO_STREAM_INIT_IN_PROGRESS (-6608)
+%define VINF_AUDIO_STREAM_ASYNC_INIT_NEEDED (6609)
+%define VERR_APIC_INTR_NOT_PENDING (-6700)
+%define VERR_APIC_INTR_MASKED_BY_TPR (-6701)
+%define VERR_APIC_INTR_DISCARDED (-6702)
+%define VERR_NEM_NOT_ENABLED (-6800)
+%define VERR_NEM_NOT_AVAILABLE (-6801)
+%define VERR_NEM_INIT_FAILED (-6802)
+%define VERR_NEM_MISSING_KERNEL_API_1 (-6803)
+%define VERR_NEM_RING3_ONLY (-6804)
+%define VERR_NEM_VM_CREATE_FAILED (-6805)
+%define VERR_NEM_MAP_PAGES_FAILED (-6806)
+%define VERR_NEM_UNMAP_PAGES_FAILED (-6807)
+%define VERR_NEM_GET_REGISTERS_FAILED (-6808)
+%define VERR_NEM_SET_REGISTERS_FAILED (-6809)
+%define VERR_NEM_FLUSH_TLB (-6810)
+%define VINF_NEM_FLUSH_TLB (6810)
+%define VERR_NEM_SET_TSC (-6811)
+%define VERR_NEM_MISSING_KERNEL_API_2 (-6812)
+%define VERR_NEM_MISSING_KERNEL_API_3 (-6813)
+%define VERR_NEM_MISSING_KERNEL_API_4 (-6814)
+%define VERR_NEM_MISSING_KERNEL_API_5 (-6815)
+%define VERR_NEM_QUERY_DIRTY_BITMAP_FAILED (-6816)
+%define VERR_NEM_MISSING_FEATURE (-6817)
+%define VERR_NEM_IPE_0 (-6890)
+%define VERR_NEM_IPE_1 (-6891)
+%define VERR_NEM_IPE_2 (-6892)
+%define VERR_NEM_IPE_3 (-6893)
+%define VERR_NEM_IPE_4 (-6894)
+%define VERR_NEM_IPE_5 (-6895)
+%define VERR_NEM_IPE_6 (-6896)
+%define VERR_NEM_IPE_7 (-6897)
+%define VERR_NEM_IPE_8 (-6898)
+%define VERR_NEM_IPE_9 (-6899)
+%define VERR_RECORDING_CODEC_NOT_FOUND (-6900)
+%define VERR_RECORDING_CODEC_INIT_FAILED (-6902)
+%define VERR_RECORDING_CODEC_NOT_SUPPORTED (-6903)
+%define VERR_RECORDING_FORMAT_NOT_SUPPORTED (-6904)
+%define VERR_RECORDING_RESTRICTED (-6905)
+%define VINF_RECORDING_LIMIT_REACHED (6906)
+%define VERR_RECORDING_LIMIT_REACHED (-6906)
+%define VINF_RECORDING_THROTTLED (6907)
+%define VERR_RECORDING_THROTTLED (-6907)
+%define VERR_RECORDING_ENCODING_FAILED (-6908)
+%define VERR_SHCLPB_MAX_TRANSFERS_REACHED (-7100)
+%define VERR_SHCLPB_MAX_OBJECTS_REACHED (-7101)
+%define VERR_SHCLPB_MAX_LISTS_REACHED (-7102)
+%define VERR_SHCLPB_LIST_HANDLE_INVALID (-7103)
+%define VERR_SHCLPB_OBJ_HANDLE_INVALID (-7104)
+%define VERR_SHCLPB_EVENT_ID_NOT_FOUND (-7105)
+%define VERR_SHCLPB_MAX_EVENTS_REACHED (-7106)
+%define VERR_SHCLPB_TRANSFER_ID_NOT_FOUND (-7150)
+%define VERR_IOMMU_DTE_READ_FAILED (-7300)
+%define VERR_IOMMU_DTE_BAD_OFFSET (-7301)
+%define VERR_IOMMU_ADDR_TRANSLATION_FAILED (-7302)
+%define VERR_IOMMU_ADDR_ACCESS_DENIED (-7303)
+%define VERR_IOMMU_INTR_REMAP_FAILED (-7304)
+%define VERR_IOMMU_INTR_REMAP_DENIED (-7305)
+%define VERR_IOMMU_CMD_NOT_SUPPORTED (-7306)
+%define VERR_IOMMU_CMD_INVALID_FORMAT (-7307)
+%define VERR_IOMMU_CMD_HW_ERROR (-7308)
+%define VERR_IOMMU_NOT_PRESENT (-7309)
+%define VERR_IOMMU_CANNOT_CALL_SELF (-7310)
+%define VINF_IOMMU_ADDR_TRANSLATION_DISABLED 7311
+%define VERR_IOMMU_IPE_0 (-7390)
+%define VERR_IOMMU_IPE_1 (-7391)
+%define VERR_IOMMU_IPE_2 (-7392)
+%define VERR_IOMMU_IPE_3 (-7393)
+%define VERR_IOMMU_IPE_4 (-7394)
+%define VERR_IOMMU_IPE_5 (-7395)
+%define VERR_IOMMU_IPE_6 (-7396)
+%define VERR_IOMMU_IPE_7 (-7397)
+%define VERR_IOMMU_IPE_8 (-7398)
+%define VERR_IOMMU_IPE_9 (-7399)
+%include "iprt/err.mac"
diff --git a/include/VBox/err.sed b/include/VBox/err.sed
new file mode 100644
index 00000000..3d659927
--- /dev/null
+++ b/include/VBox/err.sed
@@ -0,0 +1,66 @@
+## @file
+# SED script for converting VBox/err.h to .mac.
+#
+
+#
+# Copyright (C) 2006-2022 Oracle and/or its affiliates.
+#
+# This file is part of VirtualBox base platform packages, as
+# available from https://www.virtualbox.org.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation, in version 3 of the
+# License.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <https://www.gnu.org/licenses>.
+#
+# The contents of this file may alternatively be used under the terms
+# of the Common Development and Distribution License Version 1.0
+# (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+# in the VirtualBox 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.
+#
+# SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+#
+
+# Pass thru the file header and copyright.
+1,/^\#ifndef/{
+/^\#ifndef/b next
+s/^[/ ]//
+s/^\*\//;/
+s/\*/;/g
+3s/^.*$/;\n; Automatically generated by err.sed. DO NOT EDIT!\n;/
+b end
+}
+:next
+
+# Handle text inside the markers.
+/SED-START/,/SED-END/{
+
+# if (#define) goto defines
+/^[[:space:]]*#[[:space:]]*define/b defines
+
+}
+
+# Everything else is deleted!
+d
+b end
+
+##
+# Convert the defines
+:defines
+s/^[[:space:]]*#[[:space:]]*define[[:space:]]*\([[:alnum:]_]*\)[[:space:]]*\(.*\)[[:space:]]*$/%define \1 \2/
+b end
+
+# next expression
+:end
diff --git a/include/VBox/hgcmsvc.h b/include/VBox/hgcmsvc.h
new file mode 100644
index 00000000..eba36f40
--- /dev/null
+++ b/include/VBox/hgcmsvc.h
@@ -0,0 +1,745 @@
+/** @file
+ * Host-Guest Communication Manager (HGCM) - Service library definitions.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_hgcmsvc_h
+#define VBOX_INCLUDED_hgcmsvc_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/assert.h>
+#include <iprt/stdarg.h>
+#include <iprt/string.h>
+#include <VBox/cdefs.h>
+#include <VBox/types.h>
+#include <iprt/err.h>
+#ifdef IN_RING3
+# include <iprt/mem.h>
+# include <VBox/err.h>
+# include <VBox/vmm/stam.h>
+# include <VBox/vmm/dbgf.h>
+# include <VBox/vmm/ssm.h>
+#endif
+#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
+ * 5.1->6.1 Because pfnCall got a new parameter. Also new helpers. (VBox 6.0)
+ * 6.1->6.2 Because pfnCallComplete starts returning a status code (VBox 6.0).
+ * 6.2->6.3 Because pfnGetRequestor was added (VBox 6.0).
+ * 6.3->6.4 Because pfnConnect got an additional parameter (VBox 6.0).
+ * 6.4->6.5 Because pfnGetVMMDevSessionId was added pfnLoadState got the version
+ * parameter (VBox 6.0).
+ * 6.5->7.1 Because pfnNotify was added (VBox 6.0).
+ * 7.1->8.1 Because pfnCancelled & pfnIsCallCancelled were added (VBox 6.0).
+ * 8.1->9.1 Because pfnDisconnectClient was (temporarily) removed, and
+ * acMaxClients and acMaxCallsPerClient added (VBox 6.1.26).
+ * 9.1->10.1 Because pfnDisconnectClient was added back (VBox 6.1.28).
+ * 10.1->11.1 Because pVMM added to pfnSaveState & pfnLoadState (VBox 7.0).
+ */
+#define VBOX_HGCM_SVC_VERSION_MAJOR (0x000b)
+#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(int, pfnCallComplete, (VBOXHGCMCALLHANDLE callHandle, int32_t rc));
+
+ void *pvInstance;
+
+ /**
+ * The service disconnects the client.
+ *
+ * This can only be used during VBOXHGCMSVCFNTABLE::pfnConnect or
+ * VBOXHGCMSVCFNTABLE::pfnDisconnect and will fail if called out side that
+ * context. Using this on the new client during VBOXHGCMSVCFNTABLE::pfnConnect
+ * is not advisable, it would be better to just return a failure status for that
+ * and it will be done automatically. (It is not possible to call this method
+ * on a client passed to VBOXHGCMSVCFNTABLE::pfnDisconnect.)
+ *
+ * There will be no VBOXHGCMSVCFNTABLE::pfnDisconnect callback for a client
+ * disconnected in this manner.
+ *
+ * @returns VBox status code.
+ * @retval VERR_NOT_FOUND if the client ID was not found.
+ * @retval VERR_INVALID_CONTEXT if not called during connect or disconnect.
+ *
+ * @remarks Used by external parties, so don't remove just because we don't use
+ * it ourselves.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnDisconnectClient, (void *pvInstance, uint32_t idClient));
+
+ /**
+ * Check if the @a callHandle is for a call restored and re-submitted from saved state.
+ *
+ * @returns true if restored, false if not.
+ * @param callHandle The call we're checking up on.
+ */
+ DECLR3CALLBACKMEMBER(bool, pfnIsCallRestored, (VBOXHGCMCALLHANDLE callHandle));
+
+ /**
+ * Check if the @a callHandle is for a cancelled call.
+ *
+ * @returns true if cancelled, false if not.
+ * @param callHandle The call we're checking up on.
+ */
+ DECLR3CALLBACKMEMBER(bool, pfnIsCallCancelled, (VBOXHGCMCALLHANDLE callHandle));
+
+ /** Access to STAMR3RegisterV. */
+ DECLR3CALLBACKMEMBER(int, pfnStamRegisterV,(void *pvInstance, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility,
+ STAMUNIT enmUnit, const char *pszDesc, const char *pszName, va_list va)
+ RT_IPRT_FORMAT_ATTR(7, 0));
+ /** Access to STAMR3DeregisterV. */
+ DECLR3CALLBACKMEMBER(int, pfnStamDeregisterV,(void *pvInstance, const char *pszPatFmt, va_list va) RT_IPRT_FORMAT_ATTR(2, 0));
+
+ /** Access to DBGFR3InfoRegisterExternal. */
+ DECLR3CALLBACKMEMBER(int, pfnInfoRegister,(void *pvInstance, const char *pszName, const char *pszDesc,
+ PFNDBGFHANDLEREXT pfnHandler, void *pvUser));
+ /** Access to DBGFR3InfoDeregisterExternal. */
+ DECLR3CALLBACKMEMBER(int, pfnInfoDeregister,(void *pvInstance, const char *pszName));
+
+ /**
+ * Retrieves the VMMDevRequestHeader::fRequestor value.
+ *
+ * @returns The field value, VMMDEV_REQUESTOR_LEGACY if not supported by the
+ * guest, VMMDEV_REQUESTOR_LOWEST if invalid call.
+ * @param hCall The call we're checking up on.
+ */
+ DECLR3CALLBACKMEMBER(uint32_t, pfnGetRequestor, (VBOXHGCMCALLHANDLE hCall));
+
+ /**
+ * Retrieves VMMDevState::idSession.
+ *
+ * @returns current VMMDev session ID value.
+ */
+ DECLR3CALLBACKMEMBER(uint64_t, pfnGetVMMDevSessionId, (void *pvInstance));
+
+} VBOXHGCMSVCHELPERS;
+
+typedef VBOXHGCMSVCHELPERS *PVBOXHGCMSVCHELPERS;
+
+#if defined(IN_RING3) || defined(IN_SLICKEDIT)
+
+/** Wrapper around STAMR3RegisterF. */
+DECLINLINE(int) RT_IPRT_FORMAT_ATTR(7, 8)
+HGCMSvcHlpStamRegister(PVBOXHGCMSVCHELPERS pHlp, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility,
+ STAMUNIT enmUnit, const char *pszDesc, const char *pszName, ...)
+{
+ int rc;
+ va_list va;
+ va_start(va, pszName);
+ rc = pHlp->pfnStamRegisterV(pHlp->pvInstance, pvSample, enmType, enmVisibility, enmUnit, pszDesc, pszName, va);
+ va_end(va);
+ return rc;
+}
+
+/** Wrapper around STAMR3RegisterV. */
+DECLINLINE(int) RT_IPRT_FORMAT_ATTR(7, 0)
+HGCMSvcHlpStamRegisterV(PVBOXHGCMSVCHELPERS pHlp, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility,
+ STAMUNIT enmUnit, const char *pszDesc, const char *pszName, va_list va)
+{
+ return pHlp->pfnStamRegisterV(pHlp->pvInstance, pvSample, enmType, enmVisibility, enmUnit, pszDesc, pszName, va);
+}
+
+/** Wrapper around STAMR3DeregisterF. */
+DECLINLINE(int) RT_IPRT_FORMAT_ATTR(2, 3) HGCMSvcHlpStamDeregister(PVBOXHGCMSVCHELPERS pHlp, const char *pszPatFmt, ...)
+{
+ int rc;
+ va_list va;
+ va_start(va, pszPatFmt);
+ rc = pHlp->pfnStamDeregisterV(pHlp->pvInstance, pszPatFmt, va);
+ va_end(va);
+ return rc;
+}
+
+/** Wrapper around STAMR3DeregisterV. */
+DECLINLINE(int) RT_IPRT_FORMAT_ATTR(2, 0) HGCMSvcHlpStamDeregisterV(PVBOXHGCMSVCHELPERS pHlp, const char *pszPatFmt, va_list va)
+{
+ return pHlp->pfnStamDeregisterV(pHlp->pvInstance, pszPatFmt, va);
+}
+
+/** Wrapper around DBGFR3InfoRegisterExternal. */
+DECLINLINE(int) HGCMSvcHlpInfoRegister(PVBOXHGCMSVCHELPERS pHlp, const char *pszName, const char *pszDesc,
+ PFNDBGFHANDLEREXT pfnHandler, void *pvUser)
+{
+ return pHlp->pfnInfoRegister(pHlp->pvInstance, pszName, pszDesc, pfnHandler, pvUser);
+}
+
+/** Wrapper around DBGFR3InfoDeregisterExternal. */
+DECLINLINE(int) HGCMSvcHlpInfoDeregister(PVBOXHGCMSVCHELPERS pHlp, const char *pszName)
+{
+ return pHlp->pfnInfoDeregister(pHlp->pvInstance, pszName);
+}
+
+#endif /* IN_RING3 */
+
+
+#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)
+#define VBOX_HGCM_SVC_PARM_PAGES (4U)
+
+/** VBOX_HGCM_SVC_PARM_PAGES specific data. */
+typedef struct VBOXHGCMSVCPARMPAGES
+{
+ uint32_t cb;
+ uint16_t cPages;
+ uint16_t u16Padding;
+ void **papvPages;
+} VBOXHGCMSVCPARMPAGES;
+typedef VBOXHGCMSVCPARMPAGES *PVBOXHGCMSVCPARMPAGES;
+
+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;
+ /** VBOX_HGCM_SVC_PARM_PAGES */
+ VBOXHGCMSVCPARMPAGES Pages;
+ } u;
+} VBOXHGCMSVCPARM;
+
+/** Extract an uint32_t value from an HGCM parameter structure. */
+DECLINLINE(int) HGCMSvcGetU32(VBOXHGCMSVCPARM *pParm, uint32_t *pu32)
+{
+ int rc = VINF_SUCCESS;
+ AssertPtrReturn(pParm, VERR_INVALID_POINTER);
+ AssertPtrReturn(pParm, VERR_INVALID_POINTER);
+ AssertPtrReturn(pu32, VERR_INVALID_POINTER);
+ if (pParm->type != VBOX_HGCM_SVC_PARM_32BIT)
+ rc = VERR_INVALID_PARAMETER;
+ if (RT_SUCCESS(rc))
+ *pu32 = pParm->u.uint32;
+ return rc;
+}
+
+/** Extract an uint64_t value from an HGCM parameter structure. */
+DECLINLINE(int) HGCMSvcGetU64(VBOXHGCMSVCPARM *pParm, uint64_t *pu64)
+{
+ int rc = VINF_SUCCESS;
+ AssertPtrReturn(pParm, VERR_INVALID_POINTER);
+ AssertPtrReturn(pParm, VERR_INVALID_POINTER);
+ AssertPtrReturn(pu64, VERR_INVALID_POINTER);
+ if (pParm->type != VBOX_HGCM_SVC_PARM_64BIT)
+ rc = VERR_INVALID_PARAMETER;
+ if (RT_SUCCESS(rc))
+ *pu64 = pParm->u.uint64;
+ return rc;
+}
+
+/** Extract an pointer value from an HGCM parameter structure. */
+DECLINLINE(int) HGCMSvcGetPv(VBOXHGCMSVCPARM *pParm, void **ppv, uint32_t *pcb)
+{
+ AssertPtrReturn(pParm, VERR_INVALID_POINTER);
+ AssertPtrReturn(ppv, VERR_INVALID_POINTER);
+ AssertPtrReturn(pcb, VERR_INVALID_POINTER);
+ if (pParm->type == VBOX_HGCM_SVC_PARM_PTR)
+ {
+ *ppv = pParm->u.pointer.addr;
+ *pcb = pParm->u.pointer.size;
+ return VINF_SUCCESS;
+ }
+
+ return VERR_INVALID_PARAMETER;
+}
+
+/** Extract a constant pointer value from an HGCM parameter structure. */
+DECLINLINE(int) HGCMSvcGetPcv(VBOXHGCMSVCPARM *pParm, const void **ppv, uint32_t *pcb)
+{
+ AssertPtrReturn(pParm, VERR_INVALID_POINTER);
+ AssertPtrReturn(ppv, VERR_INVALID_POINTER);
+ AssertPtrReturn(pcb, VERR_INVALID_POINTER);
+ if (pParm->type == VBOX_HGCM_SVC_PARM_PTR)
+ {
+ *ppv = (const void *)pParm->u.pointer.addr;
+ *pcb = pParm->u.pointer.size;
+ return VINF_SUCCESS;
+ }
+
+ return VERR_INVALID_PARAMETER;
+}
+
+/** Extract a valid pointer to a non-empty buffer from an HGCM parameter
+ * structure. */
+DECLINLINE(int) HGCMSvcGetBuf(VBOXHGCMSVCPARM *pParm, void **ppv, uint32_t *pcb)
+{
+ AssertPtrReturn(pParm, VERR_INVALID_POINTER);
+ AssertPtrReturn(ppv, VERR_INVALID_POINTER);
+ AssertPtrReturn(pcb, VERR_INVALID_POINTER);
+ if ( pParm->type == VBOX_HGCM_SVC_PARM_PTR
+ && RT_VALID_PTR(pParm->u.pointer.addr)
+ && pParm->u.pointer.size > 0)
+ {
+ *ppv = pParm->u.pointer.addr;
+ *pcb = pParm->u.pointer.size;
+ return VINF_SUCCESS;
+ }
+
+ return VERR_INVALID_PARAMETER;
+}
+
+/** Extract a valid pointer to a non-empty constant buffer from an HGCM
+ * parameter structure. */
+DECLINLINE(int) HGCMSvcGetCBuf(VBOXHGCMSVCPARM *pParm, const void **ppv, uint32_t *pcb)
+{
+ AssertPtrReturn(pParm, VERR_INVALID_POINTER);
+ AssertPtrReturn(ppv, VERR_INVALID_POINTER);
+ AssertPtrReturn(pcb, VERR_INVALID_POINTER);
+ if ( pParm->type == VBOX_HGCM_SVC_PARM_PTR
+ && RT_VALID_PTR(pParm->u.pointer.addr)
+ && pParm->u.pointer.size > 0)
+ {
+ *ppv = (const void *)pParm->u.pointer.addr;
+ *pcb = pParm->u.pointer.size;
+ return VINF_SUCCESS;
+ }
+
+ return VERR_INVALID_PARAMETER;
+}
+
+/** Extract a string value from an HGCM parameter structure. */
+DECLINLINE(int) HGCMSvcGetStr(VBOXHGCMSVCPARM *pParm, char **ppch, uint32_t *pcb)
+{
+ AssertPtrReturn(pParm, VERR_INVALID_POINTER);
+ AssertPtrReturn(ppch, VERR_INVALID_POINTER);
+ AssertPtrReturn(pcb, VERR_INVALID_POINTER);
+ if ( pParm->type == VBOX_HGCM_SVC_PARM_PTR
+ && RT_VALID_PTR(pParm->u.pointer.addr)
+ && pParm->u.pointer.size > 0)
+ {
+ int rc = RTStrValidateEncodingEx((char *)pParm->u.pointer.addr,
+ pParm->u.pointer.size,
+ RTSTR_VALIDATE_ENCODING_ZERO_TERMINATED);
+ if (RT_FAILURE(rc))
+ return rc;
+ *ppch = (char *)pParm->u.pointer.addr;
+ *pcb = pParm->u.pointer.size;
+ return VINF_SUCCESS;
+ }
+
+ return VERR_INVALID_PARAMETER;
+}
+
+/** Extract a constant string value from an HGCM parameter structure. */
+DECLINLINE(int) HGCMSvcGetCStr(VBOXHGCMSVCPARM *pParm, const char **ppch, uint32_t *pcb)
+{
+ AssertPtrReturn(pParm, VERR_INVALID_POINTER);
+ AssertPtrReturn(ppch, VERR_INVALID_POINTER);
+ AssertPtrReturn(pcb, VERR_INVALID_POINTER);
+ if ( pParm->type == VBOX_HGCM_SVC_PARM_PTR
+ && RT_VALID_PTR(pParm->u.pointer.addr)
+ && pParm->u.pointer.size > 0)
+ {
+ int rc = RTStrValidateEncodingEx((char *)pParm->u.pointer.addr,
+ pParm->u.pointer.size,
+ RTSTR_VALIDATE_ENCODING_ZERO_TERMINATED);
+ if (RT_FAILURE(rc))
+ return rc;
+ *ppch = (char *)pParm->u.pointer.addr;
+ *pcb = pParm->u.pointer.size;
+ return VINF_SUCCESS;
+ }
+
+ return VERR_INVALID_PARAMETER;
+}
+
+/** Extract a constant string value from an HGCM parameter structure. */
+DECLINLINE(int) HGCMSvcGetPsz(VBOXHGCMSVCPARM *pParm, const char **ppch, uint32_t *pcb)
+{
+ AssertPtrReturn(pParm, VERR_INVALID_POINTER);
+ AssertPtrReturn(ppch, VERR_INVALID_POINTER);
+ AssertPtrReturn(pcb, VERR_INVALID_POINTER);
+ if ( pParm->type == VBOX_HGCM_SVC_PARM_PTR
+ && RT_VALID_PTR(pParm->u.pointer.addr)
+ && pParm->u.pointer.size > 0)
+ {
+ int rc = RTStrValidateEncodingEx((const char *)pParm->u.pointer.addr,
+ pParm->u.pointer.size,
+ RTSTR_VALIDATE_ENCODING_ZERO_TERMINATED);
+ if (RT_FAILURE(rc))
+ return rc;
+ *ppch = (const char *)pParm->u.pointer.addr;
+ *pcb = pParm->u.pointer.size;
+ return VINF_SUCCESS;
+ }
+
+ return VERR_INVALID_PARAMETER;
+}
+
+/** Set a uint32_t value to an HGCM parameter structure */
+DECLINLINE(void) HGCMSvcSetU32(VBOXHGCMSVCPARM *pParm, uint32_t u32)
+{
+ AssertPtr(pParm);
+ pParm->type = VBOX_HGCM_SVC_PARM_32BIT;
+ pParm->u.uint32 = u32;
+}
+
+/** Set a uint64_t value to an HGCM parameter structure */
+DECLINLINE(void) HGCMSvcSetU64(VBOXHGCMSVCPARM *pParm, uint64_t u64)
+{
+ AssertPtr(pParm);
+ pParm->type = VBOX_HGCM_SVC_PARM_64BIT;
+ pParm->u.uint64 = u64;
+}
+
+/** Set a pointer value to an HGCM parameter structure */
+DECLINLINE(void) HGCMSvcSetPv(VBOXHGCMSVCPARM *pParm, void *pv, uint32_t cb)
+{
+ AssertPtr(pParm);
+ pParm->type = VBOX_HGCM_SVC_PARM_PTR;
+ pParm->u.pointer.addr = pv;
+ pParm->u.pointer.size = cb;
+}
+
+/** Set a pointer value to an HGCM parameter structure */
+DECLINLINE(void) HGCMSvcSetStr(VBOXHGCMSVCPARM *pParm, const char *psz)
+{
+ AssertPtr(pParm);
+ pParm->type = VBOX_HGCM_SVC_PARM_PTR;
+ pParm->u.pointer.addr = (void *)psz;
+ pParm->u.pointer.size = (uint32_t)strlen(psz) + 1;
+}
+
+#ifdef __cplusplus
+# ifdef IPRT_INCLUDED_cpp_ministring_h
+/** Set a const string value to an HGCM parameter structure */
+DECLINLINE(void) HGCMSvcSetRTCStr(VBOXHGCMSVCPARM *pParm, const RTCString &rString)
+{
+ AssertPtr(pParm);
+ pParm->type = VBOX_HGCM_SVC_PARM_PTR;
+ pParm->u.pointer.addr = (void *)rString.c_str();
+ pParm->u.pointer.size = (uint32_t)rString.length() + 1;
+}
+# endif
+#endif
+
+#if defined(IN_RING3) && defined(VBOX_INCLUDED_vmm_vmmr3vtable_h)
+
+/**
+ * Puts (serializes) a VBOXHGCMSVCPARM struct into SSM.
+ *
+ * @returns VBox status code.
+ * @param pParm VBOXHGCMSVCPARM to serialize.
+ * @param pSSM SSM handle to serialize to.
+ * @param pVMM The VMM vtable.
+ */
+DECLINLINE(int) HGCMSvcSSMR3Put(VBOXHGCMSVCPARM *pParm, PSSMHANDLE pSSM, PCVMMR3VTABLE pVMM)
+{
+ int rc;
+
+ AssertPtrReturn(pParm, VERR_INVALID_POINTER);
+ AssertPtrReturn(pSSM, VERR_INVALID_POINTER);
+
+ rc = pVMM->pfnSSMR3PutU32(pSSM, sizeof(VBOXHGCMSVCPARM));
+ AssertRCReturn(rc, rc);
+ rc = pVMM->pfnSSMR3PutU32(pSSM, pParm->type);
+ AssertRCReturn(rc, rc);
+
+ switch (pParm->type)
+ {
+ case VBOX_HGCM_SVC_PARM_32BIT:
+ rc = pVMM->pfnSSMR3PutU32(pSSM, pParm->u.uint32);
+ break;
+ case VBOX_HGCM_SVC_PARM_64BIT:
+ rc = pVMM->pfnSSMR3PutU64(pSSM, pParm->u.uint64);
+ break;
+ case VBOX_HGCM_SVC_PARM_PTR:
+ rc = pVMM->pfnSSMR3PutU32(pSSM, pParm->u.pointer.size);
+ if (RT_SUCCESS(rc))
+ rc = pVMM->pfnSSMR3PutMem(pSSM, pParm->u.pointer.addr, pParm->u.pointer.size);
+ break;
+ default:
+ AssertMsgFailed(("Paramter type %RU32 not implemented yet\n", pParm->type));
+ rc = VERR_NOT_IMPLEMENTED;
+ break;
+ }
+
+ return rc;
+}
+
+/**
+ * Gets (loads) a VBOXHGCMSVCPARM struct from SSM.
+ *
+ * @returns VBox status code.
+ * @param pParm VBOXHGCMSVCPARM to load into. Must be zero'ed.
+ * @param pSSM SSM handle to load from.
+ * @param pVMM The VMM vtable.
+ */
+DECLINLINE(int) HGCMSvcSSMR3Get(VBOXHGCMSVCPARM *pParm, PSSMHANDLE pSSM, PCVMMR3VTABLE pVMM)
+{
+ uint32_t cbParm;
+ int rc;
+
+ AssertPtrReturn(pParm, VERR_INVALID_POINTER);
+ AssertPtrReturn(pSSM, VERR_INVALID_POINTER);
+
+ rc = pVMM->pfnSSMR3GetU32(pSSM, &cbParm);
+ AssertRCReturn(rc, rc);
+ AssertReturn(cbParm == sizeof(VBOXHGCMSVCPARM), VERR_SSM_DATA_UNIT_FORMAT_CHANGED);
+
+ rc = pVMM->pfnSSMR3GetU32(pSSM, &pParm->type);
+ AssertRCReturn(rc, rc);
+
+ switch (pParm->type)
+ {
+ case VBOX_HGCM_SVC_PARM_32BIT:
+ {
+ rc = pVMM->pfnSSMR3GetU32(pSSM, &pParm->u.uint32);
+ AssertRCReturn(rc, rc);
+ break;
+ }
+
+ case VBOX_HGCM_SVC_PARM_64BIT:
+ {
+ rc = pVMM->pfnSSMR3GetU64(pSSM, &pParm->u.uint64);
+ AssertRCReturn(rc, rc);
+ break;
+ }
+
+ case VBOX_HGCM_SVC_PARM_PTR:
+ {
+ AssertMsgReturn(pParm->u.pointer.size == 0,
+ ("Pointer size parameter already in use (or not initialized)\n"), VERR_INVALID_PARAMETER);
+
+ rc = pVMM->pfnSSMR3GetU32(pSSM, &pParm->u.pointer.size);
+ AssertRCReturn(rc, rc);
+
+ AssertMsgReturn(pParm->u.pointer.addr == NULL,
+ ("Pointer parameter already in use (or not initialized)\n"), VERR_INVALID_PARAMETER);
+
+ pParm->u.pointer.addr = RTMemAlloc(pParm->u.pointer.size);
+ AssertPtrReturn(pParm->u.pointer.addr, VERR_NO_MEMORY);
+ rc = pVMM->pfnSSMR3GetMem(pSSM, pParm->u.pointer.addr, pParm->u.pointer.size);
+
+ AssertRCReturn(rc, rc);
+ break;
+ }
+
+ default:
+ AssertMsgFailedReturn(("Paramter type %RU32 not implemented yet\n", pParm->type),
+ VERR_NOT_IMPLEMENTED);
+ break;
+ }
+
+ return VINF_SUCCESS;
+}
+
+#endif /* IN_RING3 */
+
+typedef VBOXHGCMSVCPARM *PVBOXHGCMSVCPARM;
+
+
+/** 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 cbParms The size of the function parameters.
+ */
+typedef DECLCALLBACKTYPE(int, FNHGCMSVCEXT,(void *pvExtension, uint32_t u32Function, void *pvParm, uint32_t cbParms));
+typedef FNHGCMSVCEXT *PFNHGCMSVCEXT;
+
+/**
+ * Notification event.
+ */
+typedef enum HGCMNOTIFYEVENT
+{
+ HGCMNOTIFYEVENT_INVALID = 0,
+ HGCMNOTIFYEVENT_POWER_ON,
+ HGCMNOTIFYEVENT_RESUME,
+ HGCMNOTIFYEVENT_SUSPEND,
+ HGCMNOTIFYEVENT_RESET,
+ HGCMNOTIFYEVENT_POWER_OFF,
+ HGCMNOTIFYEVENT_END,
+ HGCMNOTIFYEVENT_32BIT_HACK = 0x7fffffff
+} HGCMNOTIFYEVENT;
+
+/** @name HGCM_CLIENT_CATEGORY_XXX - Client categories
+ * @{ */
+#define HGCM_CLIENT_CATEGORY_KERNEL 0 /**< Guest kernel mode and legacy client. */
+#define HGCM_CLIENT_CATEGORY_ROOT 1 /**< Guest root or admin client. */
+#define HGCM_CLIENT_CATEGORY_USER 2 /**< Regular guest user client. */
+#define HGCM_CLIENT_CATEGORY_MAX 3 /**< Max number of categories. */
+/** @} */
+
+
+/** The Service DLL entry points.
+ *
+ * HGCM will call the DLL "VBoxHGCMSvcLoad"
+ * function and the DLL must fill in the VBOXHGCMSVCFNTABLE
+ * with function pointers.
+ *
+ * @note The structure is used in separately compiled binaries so an explicit
+ * packing is required.
+ */
+typedef struct VBOXHGCMSVCFNTABLE
+{
+ /** @name Filled by HGCM
+ * @{ */
+
+ /** Size of the structure. */
+ uint32_t cbSize;
+
+ /** Version of the structure, including the helpers. (VBOX_HGCM_SVC_VERSION) */
+ uint32_t u32Version;
+
+ PVBOXHGCMSVCHELPERS pHelpers;
+ /** @} */
+
+ /** @name Filled in by the service.
+ * @{ */
+
+ /** Size of client information the service want to have. */
+ uint32_t cbClient;
+
+ /** The maximum number of clients per category. Leave entries as zero for defaults. */
+ uint32_t acMaxClients[HGCM_CLIENT_CATEGORY_MAX];
+ /** The maximum number of concurrent calls per client for each category.
+ * Leave entries as as zero for default. */
+ uint32_t acMaxCallsPerClient[HGCM_CLIENT_CATEGORY_MAX];
+ /** The HGCM_CLIENT_CATEGORY_XXX value for legacy clients.
+ * Defaults to HGCM_CLIENT_CATEGORY_KERNEL. */
+ uint32_t idxLegacyClientCategory;
+
+ /** Uninitialize service */
+ DECLR3CALLBACKMEMBER(int, pfnUnload, (void *pvService));
+
+ /** Inform the service about a client connection. */
+ DECLR3CALLBACKMEMBER(int, pfnConnect, (void *pvService, uint32_t u32ClientID, void *pvClient, uint32_t fRequestor, bool fRestoring));
+
+ /** 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[], uint64_t tsArrival));
+ /** Informs the service that a call was cancelled by the guest (optional).
+ *
+ * This is called for guest calls, connect requests and disconnect requests.
+ * There is unfortunately no way of obtaining the call handle for a guest call
+ * or otherwise identify the request, so that's left to the service to figure
+ * out using VBOXHGCMSVCHELPERS::pfnIsCallCancelled. Because this is an
+ * asynchronous call, the service may have completed the request already.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnCancelled, (void *pvService, uint32_t idClient, void *pvClient));
+
+ /** 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, PCVMMR3VTABLE pVMM));
+
+ /** Inform the service about a VM load operation. */
+ DECLR3CALLBACKMEMBER(int, pfnLoadState, (void *pvService, uint32_t u32ClientID, void *pvClient,
+ PSSMHANDLE pSSM, PCVMMR3VTABLE pVMM, uint32_t uVersion));
+
+ /** Register a service extension callback. */
+ DECLR3CALLBACKMEMBER(int, pfnRegisterExtension, (void *pvService, PFNHGCMSVCEXT pfnExtension, void *pvExtension));
+
+ /** Notification (VM state). */
+ DECLR3CALLBACKMEMBER(void, pfnNotify, (void *pvService, HGCMNOTIFYEVENT enmEvent));
+
+ /** User/instance data pointer for the service. */
+ void *pvService;
+
+ /** @} */
+} VBOXHGCMSVCFNTABLE;
+
+
+/** @name HGCM saved state
+ * @note Need to be here so we can add saved to service which doesn't have it.
+ * @{ */
+/** HGCM saved state version. */
+#define HGCM_SAVED_STATE_VERSION 3
+/** HGCM saved state version w/o client state indicators. */
+#define HGCM_SAVED_STATE_VERSION_V2 2
+/** @} */
+
+
+/** Service initialization entry point. */
+typedef DECLCALLBACKTYPE(int, FNVBOXHGCMSVCLOAD,(VBOXHGCMSVCFNTABLE *ptable));
+typedef FNVBOXHGCMSVCLOAD *PFNVBOXHGCMSVCLOAD;
+#define VBOX_HGCM_SVCLOAD_NAME "VBoxHGCMSvcLoad"
+
+#endif /* !VBOX_INCLUDED_hgcmsvc_h */
diff --git a/include/VBox/intnet.h b/include/VBox/intnet.h
new file mode 100644
index 00000000..41ee508c
--- /dev/null
+++ b/include/VBox/intnet.h
@@ -0,0 +1,1348 @@
+/** @file
+ * INTNET - Internal Networking. (DEV,++)
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_intnet_h
+#define VBOX_INCLUDED_intnet_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/types.h>
+#include <VBox/vmm/stam.h>
+#include <VBox/sup.h>
+#include <iprt/assert.h>
+#include <iprt/asm.h>
+
+RT_C_DECLS_BEGIN
+
+
+/** The userspace internal network service identifier. */
+#if defined(RT_OS_DARWIN) && defined(VBOX_WITH_INTNET_SERVICE_IN_R3)
+/** The XPC service identififer. */
+# define INTNET_R3_SVC_NAME "org.virtualbox.intnet"
+/** The high 32 bits pattern for the "rc" status code field to recognize errors
+ * where xpc_dictionary_get_int64() might return 0 which could be confused with VINF_SUCCESS. */
+# define INTNET_R3_SVC_RC_PATTERN ((uint64_t)RT_MAKE_U32_FROM_U8('V', 'B', 'O', 'X'))
+/** Constructs a signd 64bit value for the given 32-bit status code. */
+# define INTNET_R3_SVC_SET_RC(a_rc) ((INTNET_R3_SVC_RC_PATTERN << 32) | (uint64_t)(a_rc))
+/** Gets the status code from the given 64-bit signed status code value. */
+# define INTNET_R3_SVC_GET_RC(a_RcVal) ((int32_t)(a_RcVal))
+/** Checks whether the given 64-bit signed status code value encodes a valid IPRT/VBOX status code. */
+# define INTNET_R3_SVC_IS_VALID_RC(a_RcVal) (((a_RcVal) >> 32) == INTNET_R3_SVC_RC_PATTERN)
+#endif
+
+
+/**
+ * Generic two-sided ring buffer.
+ *
+ * The deal is that there is exactly one writer and one reader.
+ * When offRead equals offWrite the buffer is empty. In the other
+ * extreme the writer will not use the last free byte in the buffer.
+ */
+typedef struct INTNETRINGBUF
+{
+ /** The offset from this structure to the start of the buffer. */
+ uint32_t offStart;
+ /** The offset from this structure to the end of the buffer. (exclusive). */
+ uint32_t offEnd;
+ /** The current read offset. */
+ uint32_t volatile offReadX;
+ /** Alignment. */
+ uint32_t u32Align0;
+
+ /** The committed write offset. */
+ uint32_t volatile offWriteCom;
+ /** Writer internal current write offset.
+ * This is ahead of offWriteCom when buffer space is handed to a third party for
+ * data gathering. offWriteCom will be assigned this value by the writer then
+ * the frame is ready. */
+ uint32_t volatile offWriteInt;
+ /** The number of bytes written (not counting overflows). */
+ STAMCOUNTER cbStatWritten;
+ /** The number of frames written (not counting overflows). */
+ STAMCOUNTER cStatFrames;
+ /** The number of overflows. */
+ STAMCOUNTER cOverflows;
+} INTNETRINGBUF;
+AssertCompileSize(INTNETRINGBUF, 48);
+/** Pointer to a ring buffer. */
+typedef INTNETRINGBUF *PINTNETRINGBUF;
+
+/** The alignment of a ring buffer. */
+#define INTNETRINGBUF_ALIGNMENT sizeof(INTNETHDR)
+
+/**
+ * Asserts the sanity of the specified INTNETRINGBUF structure.
+ */
+#ifdef VBOX_STRICT
+# define INTNETRINGBUF_ASSERT_SANITY(pRingBuf) \
+ do \
+ { \
+ AssertPtr(pRingBuf); \
+ { \
+ uint32_t const offWriteCom = (pRingBuf)->offWriteCom; \
+ uint32_t const offRead = (pRingBuf)->offReadX; \
+ uint32_t const offWriteInt = (pRingBuf)->offWriteInt; \
+ \
+ AssertMsg(offWriteCom == RT_ALIGN_32(offWriteCom, INTNETHDR_ALIGNMENT), ("%#x\n", offWriteCom)); \
+ AssertMsg(offWriteCom >= (pRingBuf)->offStart, ("%#x %#x\n", offWriteCom, (pRingBuf)->offStart)); \
+ AssertMsg(offWriteCom < (pRingBuf)->offEnd, ("%#x %#x\n", offWriteCom, (pRingBuf)->offEnd)); \
+ \
+ AssertMsg(offRead == RT_ALIGN_32(offRead, INTNETHDR_ALIGNMENT), ("%#x\n", offRead)); \
+ AssertMsg(offRead >= (pRingBuf)->offStart, ("%#x %#x\n", offRead, (pRingBuf)->offStart)); \
+ AssertMsg(offRead < (pRingBuf)->offEnd, ("%#x %#x\n", offRead, (pRingBuf)->offEnd)); \
+ \
+ AssertMsg(offWriteInt == RT_ALIGN_32(offWriteInt, INTNETHDR_ALIGNMENT), ("%#x\n", offWriteInt)); \
+ AssertMsg(offWriteInt >= (pRingBuf)->offStart, ("%#x %#x\n", offWriteInt, (pRingBuf)->offStart)); \
+ AssertMsg(offWriteInt < (pRingBuf)->offEnd, ("%#x %#x\n", offWriteInt, (pRingBuf)->offEnd)); \
+ AssertMsg( offRead <= offWriteCom \
+ ? offWriteCom <= offWriteInt || offWriteInt < offRead \
+ : offWriteCom <= offWriteInt, \
+ ("W=%#x W'=%#x R=%#x\n", offWriteCom, offWriteInt, offRead)); \
+ } \
+ } while (0)
+#else
+# define INTNETRINGBUF_ASSERT_SANITY(pRingBuf) do { } while (0)
+#endif
+
+
+
+/**
+ * A interface buffer.
+ */
+typedef struct INTNETBUF
+{
+ /** Magic number (INTNETBUF_MAGIC). */
+ uint32_t u32Magic;
+ /** The size of the entire buffer. */
+ uint32_t cbBuf;
+ /** The size of the send area. */
+ uint32_t cbSend;
+ /** The size of the receive area. */
+ uint32_t cbRecv;
+ /** The receive buffer. */
+ INTNETRINGBUF Recv;
+ /** The send buffer. */
+ INTNETRINGBUF Send;
+ /** Number of times yields help solve an overflow. */
+ STAMCOUNTER cStatYieldsOk;
+ /** Number of times yields didn't help solve an overflow. */
+ STAMCOUNTER cStatYieldsNok;
+ /** Number of lost packets due to overflows. */
+ STAMCOUNTER cStatLost;
+ /** Number of bad frames (both rings). */
+ STAMCOUNTER cStatBadFrames;
+ /** Reserved for future use. */
+ STAMCOUNTER aStatReserved[2];
+ /** Reserved for future send profiling. */
+ STAMPROFILE StatSend1;
+ /** Reserved for future send profiling. */
+ STAMPROFILE StatSend2;
+ /** Reserved for future receive profiling. */
+ STAMPROFILE StatRecv1;
+ /** Reserved for future receive profiling. */
+ STAMPROFILE StatRecv2;
+ /** Reserved for future profiling. */
+ STAMPROFILE StatReserved;
+} INTNETBUF;
+AssertCompileSize(INTNETBUF, 320);
+AssertCompileMemberOffset(INTNETBUF, Recv, 16);
+AssertCompileMemberOffset(INTNETBUF, Send, 64);
+
+/** Pointer to an interface buffer. */
+typedef INTNETBUF *PINTNETBUF;
+/** Pointer to a const interface buffer. */
+typedef INTNETBUF const *PCINTNETBUF;
+
+/** Magic number for INTNETBUF::u32Magic (Sir William Gerald Golding). */
+#define INTNETBUF_MAGIC UINT32_C(0x19110919)
+
+/**
+ * Asserts the sanity of the specified INTNETBUF structure.
+ */
+#define INTNETBUF_ASSERT_SANITY(pBuf) \
+ do \
+ { \
+ AssertPtr(pBuf); \
+ Assert((pBuf)->u32Magic == INTNETBUF_MAGIC); \
+ { \
+ uint32_t const offRecvStart = (pBuf)->Recv.offStart + RT_UOFFSETOF(INTNETBUF, Recv); \
+ uint32_t const offRecvEnd = (pBuf)->Recv.offStart + RT_UOFFSETOF(INTNETBUF, Recv); \
+ uint32_t const offSendStart = (pBuf)->Send.offStart + RT_UOFFSETOF(INTNETBUF, Send); \
+ uint32_t const offSendEnd = (pBuf)->Send.offStart + RT_UOFFSETOF(INTNETBUF, Send); \
+ \
+ Assert(offRecvEnd > offRecvStart); \
+ Assert(offRecvEnd - offRecvStart == (pBuf)->cbRecv); \
+ Assert(offRecvStart == sizeof(INTNETBUF)); \
+ \
+ Assert(offSendEnd > offSendStart); \
+ Assert(offSendEnd - offSendStart == (pBuf)->cbSend); \
+ Assert(pffSendEnd <= (pBuf)->cbBuf); \
+ \
+ Assert(offSendStart == offRecvEnd); \
+ } \
+ } while (0)
+
+
+/** Internal networking interface handle. */
+typedef uint32_t INTNETIFHANDLE;
+/** Pointer to an internal networking interface handle. */
+typedef INTNETIFHANDLE *PINTNETIFHANDLE;
+
+/** Or mask to obscure the handle index. */
+#define INTNET_HANDLE_MAGIC 0x88880000
+/** Mask to extract the handle index. */
+#define INTNET_HANDLE_INDEX_MASK 0xffff
+/** The maximum number of handles (exclusive) */
+#define INTNET_HANDLE_MAX 0xffff
+/** Invalid handle. */
+#define INTNET_HANDLE_INVALID (0)
+
+
+/**
+ * The frame header.
+ *
+ * The header is intentionally 8 bytes long. It will always
+ * start at an 8 byte aligned address. Assuming that the buffer
+ * size is a multiple of 8 bytes, that means that we can guarantee
+ * that the entire header is contiguous in both virtual and physical
+ * memory.
+ */
+typedef struct INTNETHDR
+{
+ /** The size of the frame. */
+ uint32_t cbFrame : 24;
+ /** Header type. This is currently serving as a magic, it
+ * can be extended later to encode special command frames and stuff. */
+ uint32_t u8Type : 8;
+ /** The offset from the start of this header to where the actual frame starts.
+ * This is used to keep the frame it self contiguous in virtual memory and
+ * thereby both simplify access as well as the descriptor. */
+ int32_t offFrame;
+} INTNETHDR;
+AssertCompileSize(INTNETHDR, 8);
+AssertCompileSizeAlignment(INTNETBUF, sizeof(INTNETHDR));
+/** Pointer to a frame header.*/
+typedef INTNETHDR *PINTNETHDR;
+/** Pointer to a const frame header.*/
+typedef INTNETHDR const *PCINTNETHDR;
+
+/** The alignment of a frame header. */
+#define INTNETHDR_ALIGNMENT sizeof(INTNETHDR)
+AssertCompile(sizeof(INTNETHDR) == INTNETHDR_ALIGNMENT);
+AssertCompile(INTNETHDR_ALIGNMENT <= INTNETRINGBUF_ALIGNMENT);
+
+/** @name Frame types (INTNETHDR::u8Type).
+ * @{ */
+/** Normal frames. */
+#define INTNETHDR_TYPE_FRAME 0x42
+/** Padding frames. */
+#define INTNETHDR_TYPE_PADDING 0x53
+/** Generic segment offload frames.
+ * The frame starts with a PDMNETWORKGSO structure which is followed by the
+ * header template and data. */
+#define INTNETHDR_TYPE_GSO 0x64
+AssertCompileSize(PDMNETWORKGSO, 8);
+/** @} */
+
+/**
+ * Asserts the sanity of the specified INTNETHDR.
+ */
+#ifdef VBOX_STRICT
+#define INTNETHDR_ASSERT_SANITY(pHdr, pRingBuf) \
+ do \
+ { \
+ AssertPtr(pHdr); \
+ Assert(RT_ALIGN_PT(pHdr, INTNETHDR_ALIGNMENT, INTNETHDR *) == pHdr); \
+ Assert( (pHdr)->u8Type == INTNETHDR_TYPE_FRAME \
+ || (pHdr)->u8Type == INTNETHDR_TYPE_GSO \
+ || (pHdr)->u8Type == INTNETHDR_TYPE_PADDING); \
+ { \
+ uintptr_t const offHdr = (uintptr_t)pHdr - (uintptr_t)pRingBuf; \
+ uintptr_t const offFrame = offHdr + (pHdr)->offFrame; \
+ \
+ Assert(offHdr >= (pRingBuf)->offStart); \
+ Assert(offHdr < (pRingBuf)->offEnd); \
+ \
+ /* could do more thorough work here... later, perhaps. */ \
+ Assert(offFrame >= (pRingBuf)->offStart); \
+ Assert(offFrame < (pRingBuf)->offEnd); \
+ } \
+ } while (0)
+#else
+# define INTNETHDR_ASSERT_SANITY(pHdr, pRingBuf) do { } while (0)
+#endif
+
+
+/**
+ * Scatter / Gather segment (internal networking).
+ */
+typedef struct INTNETSEG
+{
+ /** The physical address. NIL_RTHCPHYS is not set. */
+ RTHCPHYS Phys;
+ /** Pointer to the segment data. */
+ void *pv;
+ /** The segment size. */
+ uint32_t cb;
+} INTNETSEG;
+/** Pointer to a internal networking frame segment. */
+typedef INTNETSEG *PINTNETSEG;
+/** Pointer to a internal networking frame segment. */
+typedef INTNETSEG const *PCINTNETSEG;
+
+
+/**
+ * Scatter / Gather list (internal networking).
+ *
+ * This is used when communicating with the trunk port.
+ */
+typedef struct INTNETSG
+{
+ /** Owner data, don't touch! */
+ void *pvOwnerData;
+ /** User data. */
+ void *pvUserData;
+ /** User data 2 in case anyone needs it. */
+ void *pvUserData2;
+ /** GSO context information, set the type to invalid if not relevant. */
+ PDMNETWORKGSO GsoCtx;
+ /** The total length of the scatter gather list. */
+ uint32_t cbTotal;
+ /** The number of users (references).
+ * This is used by the SGRelease code to decide when it can be freed. */
+ uint16_t volatile cUsers;
+ /** Flags, see INTNETSG_FLAGS_* */
+ uint16_t volatile fFlags;
+#if ARCH_BITS == 64
+ /** Alignment padding. */
+ uint16_t uPadding;
+#endif
+ /** The number of segments allocated. */
+ uint16_t cSegsAlloc;
+ /** The number of segments actually used. */
+ uint16_t cSegsUsed;
+ /** Variable sized list of segments. */
+ INTNETSEG aSegs[1];
+} INTNETSG;
+AssertCompileSizeAlignment(INTNETSG, 8);
+/** Pointer to a scatter / gather list. */
+typedef INTNETSG *PINTNETSG;
+/** Pointer to a const scatter / gather list. */
+typedef INTNETSG const *PCINTNETSG;
+
+/** @name INTNETSG::fFlags definitions.
+ * @{ */
+/** Set if the SG is free. */
+#define INTNETSG_FLAGS_FREE RT_BIT_32(1)
+/** Set if the SG is a temporary one that will become invalid upon return.
+ * Try to finish using it before returning, and if that's not possible copy
+ * to other buffers.
+ * When not set, the callee should always free the SG.
+ * Attempts to free it made by the callee will be quietly ignored. */
+#define INTNETSG_FLAGS_TEMP RT_BIT_32(2)
+/** ARP packet, IPv4 + MAC.
+ * @internal */
+#define INTNETSG_FLAGS_ARP_IPV4 RT_BIT_32(3)
+/** Copied to the temporary buffer.
+ * @internal */
+#define INTNETSG_FLAGS_PKT_CP_IN_TMP RT_BIT_32(4)
+/** @} */
+
+
+/** @name Direction (frame source or destination)
+ * @{ */
+/** To/From the wire. */
+#define INTNETTRUNKDIR_WIRE RT_BIT_32(0)
+/** To/From the host. */
+#define INTNETTRUNKDIR_HOST RT_BIT_32(1)
+/** Mask of valid bits. */
+#define INTNETTRUNKDIR_VALID_MASK UINT32_C(3)
+/** @} */
+
+/**
+ * Switch decisions returned by INTNETTRUNKSWPORT::pfnPreRecv.
+ */
+typedef enum INTNETSWDECISION
+{
+ /** The usual invalid zero value. */
+ INTNETSWDECISION_INVALID = 0,
+ /** Everywhere. */
+ INTNETSWDECISION_BROADCAST,
+ /** Only to the internal network. */
+ INTNETSWDECISION_INTNET,
+ /** Only for the trunk (host/wire). */
+ INTNETSWDECISION_TRUNK,
+ /** Used internally to indicate that the packet cannot be handled in the
+ * current context. */
+ INTNETSWDECISION_BAD_CONTEXT,
+ /** Used internally to indicate that the packet should be dropped. */
+ INTNETSWDECISION_DROP,
+ /** The usual 32-bit type expansion. */
+ INTNETSWDECISION_32BIT_HACK = 0x7fffffff
+} INTNETSWDECISION;
+
+
+/**
+ * Network layer address type.
+ */
+typedef enum INTNETADDRTYPE
+{
+ /** The invalid 0 entry. */
+ kIntNetAddrType_Invalid = 0,
+ /** IP version 4. */
+ kIntNetAddrType_IPv4,
+ /** IP version 6. */
+ kIntNetAddrType_IPv6,
+ /** IPX. */
+ kIntNetAddrType_IPX,
+ /** The end of the valid values. */
+ kIntNetAddrType_End,
+ /** The usual 32-bit hack. */
+ kIntNetAddrType_32BitHack = 0x7fffffff
+} INTNETADDRTYPE;
+
+
+/** Pointer to the interface side of a trunk port. */
+typedef struct INTNETTRUNKIFPORT *PINTNETTRUNKIFPORT;
+
+
+/**
+ * Special variation of INTNETTRUNKIFPORT::pfnRelease for use with
+ * INTNETTRUNKSWPORT::pfnDisconnect.
+ *
+ * @param pIfPort Pointer to the INTNETTRUNKIFPORT instance.
+ */
+typedef DECLCALLBACKTYPE(void, FNINTNETTRUNKIFPORTRELEASEBUSY,(PINTNETTRUNKIFPORT pIfPort));
+/** Pointer to a FNINTNETTRUNKIFPORTRELEASEBUSY function. */
+typedef FNINTNETTRUNKIFPORTRELEASEBUSY *PFNINTNETTRUNKIFPORTRELEASEBUSY;
+
+
+/** Pointer to the switch side of a trunk port. */
+typedef struct INTNETTRUNKSWPORT *PINTNETTRUNKSWPORT;
+/**
+ * This is the port on the internal network 'switch', i.e.
+ * what the driver is connected to.
+ *
+ * This is only used for the in-kernel trunk connections.
+ */
+typedef struct INTNETTRUNKSWPORT
+{
+ /** Structure version number. (INTNETTRUNKSWPORT_VERSION) */
+ uint32_t u32Version;
+
+ /**
+ * Examine the packet and figure out where it is going.
+ *
+ * This method is for making packet switching decisions in contexts where
+ * pfnRecv cannot be called or is no longer applicable. This method can be
+ * called from any context.
+ *
+ * @returns INTNETSWDECISION_BROADCAST, INTNETSWDECISION_INTNET or
+ * INTNETSWDECISION_TRUNK. The source is excluded from broadcast &
+ * trunk, of course.
+ *
+ * @param pSwitchPort Pointer to this structure.
+ * @param pvHdrs Pointer to the packet headers.
+ * @param cbHdrs Size of the packet headers. This must be at least 6
+ * bytes (the destination MAC address), but should if
+ * possible also include any VLAN tag and network
+ * layer header (wireless mac address sharing).
+ * @param fSrc Where this frame comes from. Only one bit should be
+ * set!
+ *
+ * @remarks Will only grab the switch table spinlock (interrupt safe). May
+ * signal an event semaphore iff we're racing network cleanup. The
+ * caller must be busy when calling.
+ */
+ DECLR0CALLBACKMEMBER(INTNETSWDECISION, pfnPreRecv,(PINTNETTRUNKSWPORT pSwitchPort,
+ void const *pvHdrs, size_t cbHdrs, uint32_t fSrc));
+
+ /**
+ * Incoming frame.
+ *
+ * The frame may be modified when the trunk port on the switch is set to share
+ * the mac address of the host when hitting the wire. Currently frames
+ * containing ARP packets are subject to this, later other protocols like
+ * NDP/ICMPv6 may need editing as well when operating in this mode. The edited
+ * packet should be forwarded to the host/wire when @c false is returned.
+ *
+ * @returns true if we've handled it and it should be dropped.
+ * false if it should hit the wire/host.
+ *
+ * @param pSwitchPort Pointer to this structure.
+ * @param pvIf Pointer to the interface which received this frame
+ * if available. Can be NULL.
+ * @param pSG The (scatter /) gather structure for the frame. This
+ * will only be use during the call, so a temporary one can
+ * be used. The Phys member will not be used.
+ * @param fSrc Where this frame comes from. Exactly one bit shall be
+ * set!
+ *
+ * @remarks Will only grab the switch table spinlock (interrupt safe). Will
+ * signal event semaphores. The caller must be busy when calling.
+ *
+ * @remarks NAT and TAP will use this interface.
+ *
+ * @todo Do any of the host require notification before frame modifications?
+ * If so, we'll add a callback to INTNETTRUNKIFPORT for this
+ * (pfnSGModifying) and a SG flag.
+ */
+ DECLR0CALLBACKMEMBER(bool, pfnRecv,(PINTNETTRUNKSWPORT pSwitchPort, void *pvIf, PINTNETSG pSG, uint32_t fSrc));
+
+ /**
+ * Retain a SG.
+ *
+ * @param pSwitchPort Pointer to this structure.
+ * @param pSG Pointer to the (scatter /) gather structure.
+ *
+ * @remarks Will not grab any locks. The caller must be busy when calling.
+ */
+ DECLR0CALLBACKMEMBER(void, pfnSGRetain,(PINTNETTRUNKSWPORT pSwitchPort, PINTNETSG pSG));
+
+ /**
+ * Release a SG.
+ *
+ * This is called by the pfnXmit code when done with a SG. This may safe
+ * be done in an asynchronous manner.
+ *
+ * @param pSwitchPort Pointer to this structure.
+ * @param pSG Pointer to the (scatter /) gather structure.
+ *
+ * @remarks May signal an event semaphore later on, currently code won't though.
+ * The caller is busy when making this call.
+ */
+ DECLR0CALLBACKMEMBER(void, pfnSGRelease,(PINTNETTRUNKSWPORT pSwitchPort, PINTNETSG pSG));
+
+ /**
+ * Selects whether outgoing SGs should have their physical address set.
+ *
+ * By enabling physical addresses in the scatter / gather segments it should
+ * be possible to save some unnecessary address translation and memory locking
+ * in the network stack. (Internal networking knows the physical address for
+ * all the INTNETBUF data and that it's locked memory.) There is a negative
+ * side effects though, frames that crosses page boundaries will require
+ * multiple scather / gather segments.
+ *
+ * @returns The old setting.
+ *
+ * @param pSwitchPort Pointer to this structure.
+ * @param fEnable Whether to enable or disable it.
+ *
+ * @remarks Will not grab any locks. The caller must be busy when calling.
+ */
+ DECLR0CALLBACKMEMBER(bool, pfnSetSGPhys,(PINTNETTRUNKSWPORT pSwitchPort, bool fEnable));
+
+ /**
+ * Reports the MAC address of the trunk.
+ *
+ * This is supposed to be called when creating, connection or reconnecting the
+ * trunk and when the MAC address is changed by the system admin.
+ *
+ * @param pSwitchPort Pointer to this structure.
+ * @param pMacAddr The MAC address.
+ *
+ * @remarks May take a spinlock or two. The caller must be busy when calling.
+ */
+ DECLR0CALLBACKMEMBER(void, pfnReportMacAddress,(PINTNETTRUNKSWPORT pSwitchPort, PCRTMAC pMacAddr));
+
+ /**
+ * Reports the promicuousness of the interface.
+ *
+ * This is supposed to be called when creating, connection or reconnecting the
+ * trunk and when the mode is changed by the system admin.
+ *
+ * @param pSwitchPort Pointer to this structure.
+ * @param fPromiscuous True if the host operates the interface in
+ * promiscuous mode, false if not.
+ *
+ * @remarks May take a spinlock or two. The caller must be busy when calling.
+ */
+ DECLR0CALLBACKMEMBER(void, pfnReportPromiscuousMode,(PINTNETTRUNKSWPORT pSwitchPort, bool fPromiscuous));
+
+ /**
+ * Reports the GSO capabilities of the host, wire or both.
+ *
+ * This is supposed to be used only when creating, connecting or reconnecting
+ * the trunk. It is assumed that the GSO capabilities are kind of static the
+ * rest of the time.
+ *
+ * @param pSwitchPort Pointer to this structure.
+ * @param fGsoCapabilities The GSO capability bit mask. The bits
+ * corresponds to the GSO type with the same value.
+ * @param fDst The destination mask (INTNETTRUNKDIR_XXX).
+ *
+ * @remarks Does not take any locks. The caller must be busy when calling.
+ */
+ DECLR0CALLBACKMEMBER(void, pfnReportGsoCapabilities,(PINTNETTRUNKSWPORT pSwitchPort, uint32_t fGsoCapabilities, uint32_t fDst));
+
+ /**
+ * Reports the no-preemption-xmit capabilities of the host and wire.
+ *
+ * This is supposed to be used only when creating, connecting or reconnecting
+ * the trunk. It is assumed that the GSO capabilities are kind of static the
+ * rest of the time.
+ *
+ * @param pSwitchPort Pointer to this structure.
+ * @param fNoPreemptDsts The destinations (INTNETTRUNKDIR_XXX) which it
+ * is safe to transmit to with preemption disabled.
+ * @param fDst The destination mask (INTNETTRUNKDIR_XXX).
+ *
+ * @remarks Does not take any locks. The caller must be busy when calling.
+ */
+ DECLR0CALLBACKMEMBER(void, pfnReportNoPreemptDsts,(PINTNETTRUNKSWPORT pSwitchPort, uint32_t fNoPreemptDsts));
+
+ /**
+ * Notifications about changes to host IP addresses.
+ *
+ * This is used by networks bridged to wifi that share mac with
+ * the host. Host reports changes to its IP addresses so that L3
+ * switching can ingore guests spoofing host's own IP addresses
+ *
+ * This callback may be null to indicate we are not interested.
+ *
+ * @param pSwitchPort Pointer to this structure.
+ * @param fAdded Whether address is added of removed.
+ * @param enmType Address type.
+ * @param pvAddr Pointer to the address.
+ */
+ DECLR0CALLBACKMEMBER(void, pfnNotifyHostAddress,(PINTNETTRUNKSWPORT pSwitchPort, bool fAdded,
+ INTNETADDRTYPE enmType, const void *pvAddr));
+
+ /**
+ * OS triggered trunk disconnect.
+ *
+ * The caller shall must be busy when calling this method to prevent racing the
+ * network destruction code. This method will always consume this busy reference
+ * (released via @a pfnReleaseBusy using @a pIfPort).
+ *
+ * The caller shall guarantee that there are absolutely no chance of concurrent
+ * calls to this method on the same instance.
+ *
+ * @param pSwitchPort Pointer to this structure.
+ * @param pIfPort The interface port structure corresponding to @a
+ * pSwitchPort and which should be used when
+ * calling @a pfnReleaseBusy. This is required as
+ * the method may no longer have access to a valid
+ * @a pIfPort pointer.
+ * @param pfnReleaseBusy Callback for releasing the callers busy
+ * reference to it's side of things.
+ */
+ DECLR0CALLBACKMEMBER(void, pfnDisconnect,(PINTNETTRUNKSWPORT pSwitchPort, PINTNETTRUNKIFPORT pIfPort,
+ PFNINTNETTRUNKIFPORTRELEASEBUSY pfnReleaseBusy));
+
+ /** Structure version number. (INTNETTRUNKSWPORT_VERSION) */
+ uint32_t u32VersionEnd;
+} INTNETTRUNKSWPORT;
+
+/**
+ * Version number for the INTNETTRUNKIFPORT::u32Version and
+ * INTNETTRUNKIFPORT::u32VersionEnd fields.
+ *
+ * NB: Version @c 0xA2CDf005 is consumed by 4.x branches for the
+ * backport of pfnNotifyHostAddress. On the next version bump use
+ * @c 0xA2CDf006 and remove this reminder.
+ */
+# define INTNETTRUNKSWPORT_VERSION UINT32_C(0xA2CDf004)
+
+
+/**
+ * The trunk interface state used set by INTNETTRUNKIFPORT::pfnSetState.
+ */
+typedef enum INTNETTRUNKIFSTATE
+{
+ /** The invalid zero entry. */
+ INTNETTRUNKIFSTATE_INVALID = 0,
+ /** The trunk is inactive. No calls to INTNETTRUNKSWPORT::pfnRecv or
+ * INTNETTRUNKSWPORT::pfnPreRecv. Calling other methods is OK. */
+ INTNETTRUNKIFSTATE_INACTIVE,
+ /** The trunk is active, no restrictions on methods or anything. */
+ INTNETTRUNKIFSTATE_ACTIVE,
+ /** The trunk is about to be disconnected from the internal network. No
+ * calls to any INTNETRUNKSWPORT methods. */
+ INTNETTRUNKIFSTATE_DISCONNECTING,
+ /** The end of the valid states. */
+ INTNETTRUNKIFSTATE_END,
+ /** The usual 32-bit type blow up hack. */
+ INTNETTRUNKIFSTATE_32BIT_HACK = 0x7fffffff
+} INTNETTRUNKIFSTATE;
+
+
+/**
+ * This is the port on the trunk interface, i.e. the driver side which the
+ * internal network is connected to.
+ *
+ * This is only used for the in-kernel trunk connections.
+ */
+typedef struct INTNETTRUNKIFPORT
+{
+ /** Structure version number. (INTNETTRUNKIFPORT_VERSION) */
+ uint32_t u32Version;
+
+ /**
+ * Retain the object.
+ *
+ * It will normally be called while owning the internal network semaphore.
+ *
+ * @param pIfPort Pointer to this structure.
+ *
+ * @remarks May own the big mutex, no spinlocks.
+ */
+ DECLR0CALLBACKMEMBER(void, pfnRetain,(PINTNETTRUNKIFPORT pIfPort));
+
+ /**
+ * Releases the object.
+ *
+ * This must be called for every pfnRetain call.
+ *
+ * @param pIfPort Pointer to this structure.
+ *
+ * @remarks May own the big mutex, no spinlocks.
+ */
+ DECLR0CALLBACKMEMBER(void, pfnRelease,(PINTNETTRUNKIFPORT pIfPort));
+
+ /**
+ * Disconnect from the switch and release the object.
+ *
+ * The is the counter action of the
+ * INTNETTRUNKNETFLTFACTORY::pfnCreateAndConnect method.
+ *
+ * @param pIfPort Pointer to this structure.
+ *
+ * @remarks Owns the big mutex.
+ */
+ DECLR0CALLBACKMEMBER(void, pfnDisconnectAndRelease,(PINTNETTRUNKIFPORT pIfPort));
+
+ /**
+ * Changes the state of the trunk interface.
+ *
+ * The interface is created in the inactive state (INTNETTRUNKIFSTATE_INACTIVE).
+ * When the first connect VM or service is activated, the internal network
+ * activates the trunk (INTNETTRUNKIFSTATE_ACTIVE). The state may then be set
+ * back and forth between INACTIVE and ACTIVE as VMs are paused, added and
+ * removed.
+ *
+ * Eventually though, the network is destroyed as a result of there being no
+ * more VMs left in it and the state is changed to disconnecting
+ * (INTNETTRUNKIFSTATE_DISCONNECTING) and pfnWaitForIdle is called to make sure
+ * there are no active calls in either direction when pfnDisconnectAndRelease is
+ * called.
+ *
+ * A typical operation to performed by this method is to enable/disable promiscuous
+ * mode on the host network interface when entering/leaving the active state.
+ *
+ * @returns The previous state.
+ *
+ * @param pIfPort Pointer to this structure.
+ * @param enmState The new state.
+ *
+ * @remarks Owns the big mutex. No racing pfnSetState, pfnWaitForIdle,
+ * pfnDisconnectAndRelease or INTNETTRUNKFACTORY::pfnCreateAndConnect
+ * calls.
+ */
+ DECLR0CALLBACKMEMBER(INTNETTRUNKIFSTATE, pfnSetState,(PINTNETTRUNKIFPORT pIfPort, INTNETTRUNKIFSTATE enmState));
+
+ /**
+ * Notifies when the MAC address of an interface is set or changes.
+ *
+ * @param pIfPort Pointer to this structure.
+ * @param pvIfData Pointer to the trunk's interface data (see
+ * pfnConnectInterface).
+ * @param pMac Pointer to the MAC address of the connecting VM NIC.
+ *
+ * @remarks Only busy references to the trunk and the interface.
+ */
+ DECLR0CALLBACKMEMBER(void, pfnNotifyMacAddress,(PINTNETTRUNKIFPORT pIfPort, void *pvIfData, PCRTMAC pMac));
+
+ /**
+ * Called when an interface is connected to the network.
+ *
+ * @returns IPRT status code.
+ * @param pIfPort Pointer to this structure.
+ * @param pvIf Opaque pointer to the interface being connected.
+ * For use INTNETTRUNKSWPORT::pfnRecv.
+ * @param ppvIfData Pointer to a pointer variable that the trunk
+ * implementation can use to associate data with the
+ * interface. This pointer will be passed to the
+ * pfnXmit, pfnNotifyMacAddress and
+ * pfnDisconnectInterface methods.
+ *
+ * @remarks Owns the big mutex. No racing pfnDisconnectAndRelease.
+ */
+ DECLR0CALLBACKMEMBER(int, pfnConnectInterface,(PINTNETTRUNKIFPORT pIfPort, void *pvIf, void **ppvIfData));
+
+ /**
+ * Called when an interface is disconnected from the network.
+ *
+ * @param pIfPort Pointer to this structure.
+ * @param pvIfData Pointer to the trunk's interface data (see
+ * pfnConnectInterface).
+ *
+ * @remarks Owns the big mutex. No racing pfnDisconnectAndRelease.
+ */
+ DECLR0CALLBACKMEMBER(void, pfnDisconnectInterface,(PINTNETTRUNKIFPORT pIfPort, void *pvIfData));
+
+ /**
+ * Waits for the interface to become idle.
+ *
+ * This method must be called before disconnecting and releasing the object in
+ * order to prevent racing incoming/outgoing frames and device
+ * enabling/disabling.
+ *
+ * @returns IPRT status code (see RTSemEventWait).
+ * @param pIfPort Pointer to this structure.
+ * @param cMillies The number of milliseconds to wait. 0 means
+ * no waiting at all. Use RT_INDEFINITE_WAIT for
+ * an indefinite wait.
+ *
+ * @remarks Owns the big mutex. No racing pfnDisconnectAndRelease.
+ */
+ DECLR0CALLBACKMEMBER(int, pfnWaitForIdle,(PINTNETTRUNKIFPORT pIfPort, uint32_t cMillies));
+
+ /**
+ * Transmit a frame.
+ *
+ * @return VBox status code. Error generally means we'll drop the frame.
+ * @param pIfPort Pointer to this structure.
+ * @param pvIfData Pointer to the trunk's interface data (see
+ * pfnConnectInterface).
+ * @param pSG Pointer to the (scatter /) gather structure for the frame.
+ * This may or may not be a temporary buffer. If it's temporary
+ * the transmit operation(s) then it's required to make a copy
+ * of the frame unless it can be transmitted synchronously.
+ * @param fDst The destination mask. At least one bit will be set.
+ *
+ * @remarks No locks. May be called concurrently on several threads.
+ */
+ DECLR0CALLBACKMEMBER(int, pfnXmit,(PINTNETTRUNKIFPORT pIfPort, void *pvIfData, PINTNETSG pSG, uint32_t fDst));
+
+ /** Structure version number. (INTNETTRUNKIFPORT_VERSION) */
+ uint32_t u32VersionEnd;
+} INTNETTRUNKIFPORT;
+
+/** Version number for the INTNETTRUNKIFPORT::u32Version and INTNETTRUNKIFPORT::u32VersionEnd fields. */
+#define INTNETTRUNKIFPORT_VERSION UINT32_C(0xA2CDe001)
+
+
+/**
+ * The component factory interface for create a network
+ * interface filter (like VBoxNetFlt).
+ */
+typedef struct INTNETTRUNKFACTORY
+{
+ /**
+ * Release this factory.
+ *
+ * SUPR0ComponentQueryFactory (SUPDRVFACTORY::pfnQueryFactoryInterface to be precise)
+ * will retain a reference to the factory and the caller has to call this method to
+ * release it once the pfnCreateAndConnect call(s) has been done.
+ *
+ * @param pIfFactory Pointer to this structure.
+ */
+ DECLR0CALLBACKMEMBER(void, pfnRelease,(struct INTNETTRUNKFACTORY *pIfFactory));
+
+ /**
+ * Create an instance for the specfied host interface and connects it
+ * to the internal network trunk port.
+ *
+ * The initial interface active state is false (suspended).
+ *
+ *
+ * @returns VBox status code.
+ * @retval VINF_SUCCESS and *ppIfPort set on success.
+ * @retval VERR_INTNET_FLT_IF_NOT_FOUND if the interface was not found.
+ * @retval VERR_INTNET_FLT_IF_BUSY if the interface is already connected.
+ * @retval VERR_INTNET_FLT_IF_FAILED if it failed for some other reason.
+ *
+ * @param pIfFactory Pointer to this structure.
+ * @param pszName The interface name (OS specific).
+ * @param pSwitchPort Pointer to the port interface on the switch that
+ * this interface is being connected to.
+ * @param fFlags Creation flags, see below.
+ * @param ppIfPort Where to store the pointer to the interface port
+ * on success.
+ *
+ * @remarks Called while owning the network and the out-bound trunk semaphores.
+ */
+ DECLR0CALLBACKMEMBER(int, pfnCreateAndConnect,(struct INTNETTRUNKFACTORY *pIfFactory, const char *pszName,
+ PINTNETTRUNKSWPORT pSwitchPort, uint32_t fFlags,
+ PINTNETTRUNKIFPORT *ppIfPort));
+} INTNETTRUNKFACTORY;
+/** Pointer to the trunk factory. */
+typedef INTNETTRUNKFACTORY *PINTNETTRUNKFACTORY;
+
+/** The UUID for the (current) trunk factory. (case sensitive) */
+#define INTNETTRUNKFACTORY_UUID_STR "de504d93-1d1e-4781-8b73-6ea39a0e36a2"
+
+/** @name INTNETTRUNKFACTORY::pfnCreateAndConnect flags.
+ * @{ */
+/** Don't put the filtered interface in promiscuous mode.
+ * This is used for wireless interface since these can misbehave if
+ * we try to put them in promiscuous mode. (Wireless interfaces are
+ * normally bridged on level 3 instead of level 2.) */
+#define INTNETTRUNKFACTORY_FLAG_NO_PROMISC RT_BIT_32(0)
+/** @} */
+
+
+/**
+ * The trunk connection type.
+ *
+ * Used by IntNetR0Open and associated interfaces.
+ */
+typedef enum INTNETTRUNKTYPE
+{
+ /** Invalid trunk type. */
+ kIntNetTrunkType_Invalid = 0,
+ /** No trunk connection. */
+ kIntNetTrunkType_None,
+ /** We don't care which kind of trunk connection if the network exists,
+ * if it doesn't exist create it without a connection. */
+ kIntNetTrunkType_WhateverNone,
+ /** VirtualBox host network interface filter driver.
+ * The trunk name is the name of the host network interface. */
+ kIntNetTrunkType_NetFlt,
+ /** VirtualBox adapter host driver. */
+ kIntNetTrunkType_NetAdp,
+ /** Nat service (ring-0). */
+ kIntNetTrunkType_SrvNat,
+ /** The end of valid types. */
+ kIntNetTrunkType_End,
+ /** The usual 32-bit hack. */
+ kIntNetTrunkType_32bitHack = 0x7fffffff
+} INTNETTRUNKTYPE;
+
+/** @name IntNetR0Open flags.
+ *
+ * The desired policy options must be specified explicitly, if omitted it is
+ * understood that whatever is current or default is fine with the caller.
+ *
+ * @todo Move the policies out of the flags, use three new parameters.
+ *
+ * @{ */
+/** Share the MAC address with the host when sending something to the wire via the trunk.
+ * This is typically used when the trunk is a NetFlt for a wireless interface. */
+#define INTNET_OPEN_FLAGS_SHARED_MAC_ON_WIRE RT_BIT_32(0)
+/** Require that the current security and promiscuous policies of the network
+ * is exactly as the ones specified in this open network request.
+ *
+ * Use this with INTNET_OPEN_FLAGS_REQUIRE_AS_RESTRICTIVE_POLICIES to prevent
+ * restrictions from being lifted. If no further policy changes are desired,
+ * apply the relevant _FIXED flags. */
+#define INTNET_OPEN_FLAGS_REQUIRE_EXACT RT_BIT_32(1)
+/** Require that the security and promiscuous policies of the network is at
+ * least as restrictive as specified this request specifies and prevent them
+ * being lifted later on. */
+#define INTNET_OPEN_FLAGS_REQUIRE_AS_RESTRICTIVE_POLICIES RT_BIT_32(2)
+
+/** Network access policy: Fixed if set, changable if clear. */
+#define INTNET_OPEN_FLAGS_ACCESS_FIXED RT_BIT_32(3)
+/** Network access policy: Public network. */
+#define INTNET_OPEN_FLAGS_ACCESS_PUBLIC RT_BIT_32(4)
+/** Network access policy: Restricted network. */
+#define INTNET_OPEN_FLAGS_ACCESS_RESTRICTED RT_BIT_32(5)
+
+/** Promiscuous mode policy: Is it fixed or changable by new participants? */
+#define INTNET_OPEN_FLAGS_PROMISC_FIXED RT_BIT_32(6)
+/** Promiscuous mode policy: Allow the clients to request it. */
+#define INTNET_OPEN_FLAGS_PROMISC_ALLOW_CLIENTS RT_BIT_32(7)
+/** Promiscuous mode policy: Deny the clients from requesting it. */
+#define INTNET_OPEN_FLAGS_PROMISC_DENY_CLIENTS RT_BIT_32(8)
+/** Promiscuous mode policy: Allow the trunk-host to request it. */
+#define INTNET_OPEN_FLAGS_PROMISC_ALLOW_TRUNK_HOST RT_BIT_32(9)
+/** Promiscuous mode policy: Deny the trunk-host from requesting it. */
+#define INTNET_OPEN_FLAGS_PROMISC_DENY_TRUNK_HOST RT_BIT_32(10)
+/** Promiscuous mode policy: Allow the trunk-wire to request it. */
+#define INTNET_OPEN_FLAGS_PROMISC_ALLOW_TRUNK_WIRE RT_BIT_32(11)
+/** Promiscuous mode policy: Deny the trunk-wire from requesting it. */
+#define INTNET_OPEN_FLAGS_PROMISC_DENY_TRUNK_WIRE RT_BIT_32(12)
+
+/** Interface policies: Is it fixed or changable (by admin).
+ * @note Per interface, not network wide. */
+#define INTNET_OPEN_FLAGS_IF_FIXED RT_BIT_32(13)
+/** Interface promiscuous mode policy: Allow the interface to request it. */
+#define INTNET_OPEN_FLAGS_IF_PROMISC_ALLOW RT_BIT_32(14)
+/** Interface promiscuous mode policy: Deny the interface from requesting it. */
+#define INTNET_OPEN_FLAGS_IF_PROMISC_DENY RT_BIT_32(15)
+/** Interface promiscuous mode policy: See unrelated trunk traffic. */
+#define INTNET_OPEN_FLAGS_IF_PROMISC_SEE_TRUNK RT_BIT_32(16)
+/** Interface promiscuous mode policy: No unrelated trunk traffic visible. */
+#define INTNET_OPEN_FLAGS_IF_PROMISC_NO_TRUNK RT_BIT_32(17)
+
+/** Trunk policy: Fixed if set, changable if clear.
+ * @remarks The DISABLED options are considered more restrictive by
+ * INTNET_OPEN_FLAGS_REQUIRE_AS_RESTRICTIVE_POLICIES. */
+#define INTNET_OPEN_FLAGS_TRUNK_FIXED RT_BIT_32(18)
+/** Trunk policy: The host end should be enabled. */
+#define INTNET_OPEN_FLAGS_TRUNK_HOST_ENABLED RT_BIT_32(19)
+/** Trunk policy: The host end should be disabled. */
+#define INTNET_OPEN_FLAGS_TRUNK_HOST_DISABLED RT_BIT_32(20)
+/** Trunk policy: The host should only see packets destined for it. */
+#define INTNET_OPEN_FLAGS_TRUNK_HOST_CHASTE_MODE RT_BIT_32(21)
+/** Trunk policy: The host should see all packets. */
+#define INTNET_OPEN_FLAGS_TRUNK_HOST_PROMISC_MODE RT_BIT_32(22)
+/** Trunk policy: The wire end should be enabled. */
+#define INTNET_OPEN_FLAGS_TRUNK_WIRE_ENABLED RT_BIT_32(23)
+/** Trunk policy: The wire end should be disabled. */
+#define INTNET_OPEN_FLAGS_TRUNK_WIRE_DISABLED RT_BIT_32(24)
+/** Trunk policy: The wire should only see packets destined for it. */
+#define INTNET_OPEN_FLAGS_TRUNK_WIRE_CHASTE_MODE RT_BIT_32(25)
+/** Trunk policy: The wire should see all packets. */
+#define INTNET_OPEN_FLAGS_TRUNK_WIRE_PROMISC_MODE RT_BIT_32(26)
+
+/** Used to enable host specific workarounds.
+ *
+ * On darwin this will clear ip_tos in DHCP packets when
+ * INTNET_OPEN_FLAGS_SHARED_MAC_ON_WIRE is also set. */
+#define INTNET_OPEN_FLAGS_WORKAROUND_1 RT_BIT_32(31)
+
+
+/** The mask of valid flags. */
+#define INTNET_OPEN_FLAGS_MASK UINT32_C(0x83ffffff)
+/** The mask of all flags use to fix (lock) settings. */
+#define INTNET_OPEN_FLAGS_FIXED_MASK \
+ ( INTNET_OPEN_FLAGS_ACCESS_FIXED \
+ | INTNET_OPEN_FLAGS_PROMISC_FIXED \
+ | INTNET_OPEN_FLAGS_IF_FIXED \
+ | INTNET_OPEN_FLAGS_TRUNK_FIXED )
+
+/** The mask of all policy pairs. */
+#define INTNET_OPEN_FLAGS_PAIR_MASK \
+ ( INTNET_OPEN_FLAGS_ACCESS_PUBLIC | INTNET_OPEN_FLAGS_ACCESS_RESTRICTED \
+ | INTNET_OPEN_FLAGS_PROMISC_ALLOW_CLIENTS | INTNET_OPEN_FLAGS_PROMISC_DENY_CLIENTS \
+ | INTNET_OPEN_FLAGS_PROMISC_ALLOW_TRUNK_HOST | INTNET_OPEN_FLAGS_PROMISC_DENY_TRUNK_HOST \
+ | INTNET_OPEN_FLAGS_PROMISC_ALLOW_TRUNK_WIRE | INTNET_OPEN_FLAGS_PROMISC_DENY_TRUNK_WIRE \
+ | INTNET_OPEN_FLAGS_IF_PROMISC_ALLOW | INTNET_OPEN_FLAGS_IF_PROMISC_DENY \
+ | INTNET_OPEN_FLAGS_IF_PROMISC_SEE_TRUNK | INTNET_OPEN_FLAGS_IF_PROMISC_NO_TRUNK \
+ | INTNET_OPEN_FLAGS_TRUNK_HOST_ENABLED | INTNET_OPEN_FLAGS_TRUNK_HOST_DISABLED \
+ | INTNET_OPEN_FLAGS_TRUNK_HOST_PROMISC_MODE | INTNET_OPEN_FLAGS_TRUNK_HOST_CHASTE_MODE \
+ | INTNET_OPEN_FLAGS_TRUNK_WIRE_ENABLED | INTNET_OPEN_FLAGS_TRUNK_WIRE_DISABLED \
+ | INTNET_OPEN_FLAGS_TRUNK_WIRE_PROMISC_MODE | INTNET_OPEN_FLAGS_TRUNK_WIRE_CHASTE_MODE \
+ )
+/** The mask of all relaxed policy bits. */
+#define INTNET_OPEN_FLAGS_RELAXED_MASK \
+ ( INTNET_OPEN_FLAGS_ACCESS_PUBLIC \
+ | INTNET_OPEN_FLAGS_PROMISC_ALLOW_CLIENTS \
+ | INTNET_OPEN_FLAGS_PROMISC_ALLOW_TRUNK_HOST \
+ | INTNET_OPEN_FLAGS_PROMISC_ALLOW_TRUNK_WIRE \
+ | INTNET_OPEN_FLAGS_IF_PROMISC_ALLOW \
+ | INTNET_OPEN_FLAGS_IF_PROMISC_SEE_TRUNK \
+ | INTNET_OPEN_FLAGS_TRUNK_HOST_ENABLED \
+ | INTNET_OPEN_FLAGS_TRUNK_WIRE_PROMISC_MODE \
+ | INTNET_OPEN_FLAGS_TRUNK_WIRE_ENABLED \
+ | INTNET_OPEN_FLAGS_TRUNK_WIRE_PROMISC_MODE \
+ )
+/** The mask of all strict policy bits. */
+#define INTNET_OPEN_FLAGS_STRICT_MASK \
+ ( INTNET_OPEN_FLAGS_ACCESS_RESTRICTED \
+ | INTNET_OPEN_FLAGS_PROMISC_DENY_CLIENTS \
+ | INTNET_OPEN_FLAGS_PROMISC_DENY_TRUNK_HOST \
+ | INTNET_OPEN_FLAGS_PROMISC_DENY_TRUNK_WIRE \
+ | INTNET_OPEN_FLAGS_IF_PROMISC_DENY \
+ | INTNET_OPEN_FLAGS_IF_PROMISC_NO_TRUNK \
+ | INTNET_OPEN_FLAGS_TRUNK_HOST_DISABLED \
+ | INTNET_OPEN_FLAGS_TRUNK_HOST_CHASTE_MODE \
+ | INTNET_OPEN_FLAGS_TRUNK_WIRE_DISABLED \
+ | INTNET_OPEN_FLAGS_TRUNK_WIRE_CHASTE_MODE \
+ )
+/** @} */
+
+/** The maximum length of a network name. */
+#define INTNET_MAX_NETWORK_NAME 128
+
+/** The maximum length of a trunk name. */
+#define INTNET_MAX_TRUNK_NAME 64
+
+
+/**
+ * Request buffer for IntNetR0OpenReq / VMMR0_DO_INTNET_OPEN.
+ * @see IntNetR0Open.
+ */
+typedef struct INTNETOPENREQ
+{
+ /** The request header. */
+ SUPVMMR0REQHDR Hdr;
+ /** Alternative to passing the taking the session from the VM handle.
+ * Either use this member or use the VM handle, don't do both. */
+ PSUPDRVSESSION pSession;
+ /** The network name. (input) */
+ char szNetwork[INTNET_MAX_NETWORK_NAME];
+ /** What to connect to the trunk port. (input)
+ * This is specific to the trunk type below. */
+ char szTrunk[INTNET_MAX_TRUNK_NAME];
+ /** The type of trunk link (NAT, Filter, TAP, etc). (input) */
+ INTNETTRUNKTYPE enmTrunkType;
+ /** Flags, see INTNET_OPEN_FLAGS_*. (input) */
+ uint32_t fFlags;
+ /** The size of the send buffer. (input) */
+ uint32_t cbSend;
+ /** The size of the receive buffer. (input) */
+ uint32_t cbRecv;
+ /** The handle to the network interface. (output) */
+ INTNETIFHANDLE hIf;
+} INTNETOPENREQ;
+/** Pointer to an IntNetR0OpenReq / VMMR0_DO_INTNET_OPEN request buffer. */
+typedef INTNETOPENREQ *PINTNETOPENREQ;
+
+INTNETR0DECL(int) IntNetR0OpenReq(PSUPDRVSESSION pSession, PINTNETOPENREQ pReq);
+
+
+/**
+ * Request buffer for IntNetR0IfCloseReq / VMMR0_DO_INTNET_IF_CLOSE.
+ * @see IntNetR0IfClose.
+ */
+typedef struct INTNETIFCLOSEREQ
+{
+ /** The request header. */
+ SUPVMMR0REQHDR Hdr;
+ /** Alternative to passing the taking the session from the VM handle.
+ * Either use this member or use the VM handle, don't do both. */
+ PSUPDRVSESSION pSession;
+ /** The handle to the network interface. */
+ INTNETIFHANDLE hIf;
+} INTNETIFCLOSEREQ;
+/** Pointer to an IntNetR0IfCloseReq / VMMR0_DO_INTNET_IF_CLOSE request
+ * buffer. */
+typedef INTNETIFCLOSEREQ *PINTNETIFCLOSEREQ;
+
+INTNETR0DECL(int) IntNetR0IfCloseReq(PSUPDRVSESSION pSession, PINTNETIFCLOSEREQ pReq);
+
+
+/**
+ * Request buffer for IntNetR0IfGetRing3BufferReq /
+ * VMMR0_DO_INTNET_IF_GET_BUFFER_PTRS.
+ * @see IntNetR0IfGetRing3Buffer.
+ */
+typedef struct INTNETIFGETBUFFERPTRSREQ
+{
+ /** The request header. */
+ SUPVMMR0REQHDR Hdr;
+ /** Alternative to passing the taking the session from the VM handle.
+ * Either use this member or use the VM handle, don't do both. */
+ PSUPDRVSESSION pSession;
+ /** Handle to the interface. */
+ INTNETIFHANDLE hIf;
+ /** The pointer to the ring-3 buffer. (output) */
+ R3PTRTYPE(PINTNETBUF) pRing3Buf;
+ /** The pointer to the ring-0 buffer. (output) */
+ R0PTRTYPE(PINTNETBUF) pRing0Buf;
+} INTNETIFGETBUFFERPTRSREQ;
+/** Pointer to an IntNetR0IfGetRing3BufferReq /
+ * VMMR0_DO_INTNET_IF_GET_BUFFER_PTRS request buffer. */
+typedef INTNETIFGETBUFFERPTRSREQ *PINTNETIFGETBUFFERPTRSREQ;
+
+INTNETR0DECL(int) IntNetR0IfGetBufferPtrsReq(PSUPDRVSESSION pSession, PINTNETIFGETBUFFERPTRSREQ pReq);
+
+
+/**
+ * Request buffer for IntNetR0IfSetPromiscuousModeReq /
+ * VMMR0_DO_INTNET_IF_SET_PROMISCUOUS_MODE.
+ * @see IntNetR0IfSetPromiscuousMode.
+ */
+typedef struct INTNETIFSETPROMISCUOUSMODEREQ
+{
+ /** The request header. */
+ SUPVMMR0REQHDR Hdr;
+ /** Alternative to passing the taking the session from the VM handle.
+ * Either use this member or use the VM handle, don't do both. */
+ PSUPDRVSESSION pSession;
+ /** Handle to the interface. */
+ INTNETIFHANDLE hIf;
+ /** The new promiscuous mode. */
+ bool fPromiscuous;
+} INTNETIFSETPROMISCUOUSMODEREQ;
+/** Pointer to an IntNetR0IfSetPromiscuousModeReq /
+ * VMMR0_DO_INTNET_IF_SET_PROMISCUOUS_MODE request buffer. */
+typedef INTNETIFSETPROMISCUOUSMODEREQ *PINTNETIFSETPROMISCUOUSMODEREQ;
+
+INTNETR0DECL(int) IntNetR0IfSetPromiscuousModeReq(PSUPDRVSESSION pSession, PINTNETIFSETPROMISCUOUSMODEREQ pReq);
+
+
+/**
+ * Request buffer for IntNetR0IfSetMacAddressReq /
+ * VMMR0_DO_INTNET_IF_SET_MAC_ADDRESS.
+ * @see IntNetR0IfSetMacAddress.
+ */
+typedef struct INTNETIFSETMACADDRESSREQ
+{
+ /** The request header. */
+ SUPVMMR0REQHDR Hdr;
+ /** Alternative to passing the taking the session from the VM handle.
+ * Either use this member or use the VM handle, don't do both. */
+ PSUPDRVSESSION pSession;
+ /** Handle to the interface. */
+ INTNETIFHANDLE hIf;
+ /** The new MAC address. */
+ RTMAC Mac;
+} INTNETIFSETMACADDRESSREQ;
+/** Pointer to an IntNetR0IfSetMacAddressReq /
+ * VMMR0_DO_INTNET_IF_SET_MAC_ADDRESS request buffer. */
+typedef INTNETIFSETMACADDRESSREQ *PINTNETIFSETMACADDRESSREQ;
+
+INTNETR0DECL(int) IntNetR0IfSetMacAddressReq(PSUPDRVSESSION pSession, PINTNETIFSETMACADDRESSREQ pReq);
+
+
+/**
+ * Request buffer for IntNetR0IfSetActiveReq / VMMR0_DO_INTNET_IF_SET_ACTIVE.
+ * @see IntNetR0IfSetActive.
+ */
+typedef struct INTNETIFSETACTIVEREQ
+{
+ /** The request header. */
+ SUPVMMR0REQHDR Hdr;
+ /** Alternative to passing the taking the session from the VM handle.
+ * Either use this member or use the VM handle, don't do both. */
+ PSUPDRVSESSION pSession;
+ /** Handle to the interface. */
+ INTNETIFHANDLE hIf;
+ /** The new state. */
+ bool fActive;
+} INTNETIFSETACTIVEREQ;
+/** Pointer to an IntNetR0IfSetActiveReq / VMMR0_DO_INTNET_IF_SET_ACTIVE
+ * request buffer. */
+typedef INTNETIFSETACTIVEREQ *PINTNETIFSETACTIVEREQ;
+
+INTNETR0DECL(int) IntNetR0IfSetActiveReq(PSUPDRVSESSION pSession, PINTNETIFSETACTIVEREQ pReq);
+
+
+/**
+ * Request buffer for IntNetR0IfSendReq / VMMR0_DO_INTNET_IF_SEND.
+ * @see IntNetR0IfSend.
+ */
+typedef struct INTNETIFSENDREQ
+{
+ /** The request header. */
+ SUPVMMR0REQHDR Hdr;
+ /** Alternative to passing the taking the session from the VM handle.
+ * Either use this member or use the VM handle, don't do both. */
+ PSUPDRVSESSION pSession;
+ /** Handle to the interface. */
+ INTNETIFHANDLE hIf;
+} INTNETIFSENDREQ;
+/** Pointer to an IntNetR0IfSend() argument package. */
+typedef INTNETIFSENDREQ *PINTNETIFSENDREQ;
+
+INTNETR0DECL(int) IntNetR0IfSendReq(PSUPDRVSESSION pSession, PINTNETIFSENDREQ pReq);
+
+
+/**
+ * Request buffer for IntNetR0IfWaitReq / VMMR0_DO_INTNET_IF_WAIT.
+ * @see IntNetR0IfWait.
+ */
+typedef struct INTNETIFWAITREQ
+{
+ /** The request header. */
+ SUPVMMR0REQHDR Hdr;
+ /** Alternative to passing the taking the session from the VM handle.
+ * Either use this member or use the VM handle, don't do both. */
+ PSUPDRVSESSION pSession;
+ /** Handle to the interface. */
+ INTNETIFHANDLE hIf;
+ /** The number of milliseconds to wait. */
+ uint32_t cMillies;
+} INTNETIFWAITREQ;
+/** Pointer to an IntNetR0IfWaitReq / VMMR0_DO_INTNET_IF_WAIT request buffer. */
+typedef INTNETIFWAITREQ *PINTNETIFWAITREQ;
+
+INTNETR0DECL(int) IntNetR0IfWaitReq(PSUPDRVSESSION pSession, PINTNETIFWAITREQ pReq);
+
+
+/**
+ * Request buffer for IntNetR0IfAbortWaitReq / VMMR0_DO_INTNET_IF_ABORT_WAIT.
+ * @see IntNetR0IfAbortWait.
+ */
+typedef struct INTNETIFABORTWAITREQ
+{
+ /** The request header. */
+ SUPVMMR0REQHDR Hdr;
+ /** Alternative to passing the taking the session from the VM handle.
+ * Either use this member or use the VM handle, don't do both. */
+ PSUPDRVSESSION pSession;
+ /** Handle to the interface. */
+ INTNETIFHANDLE hIf;
+ /** Set this to fend off all future IntNetR0Wait calls. */
+ bool fNoMoreWaits;
+} INTNETIFABORTWAITREQ;
+/** Pointer to an IntNetR0IfAbortWaitReq / VMMR0_DO_INTNET_IF_ABORT_WAIT
+ * request buffer. */
+typedef INTNETIFABORTWAITREQ *PINTNETIFABORTWAITREQ;
+
+INTNETR0DECL(int) IntNetR0IfAbortWaitReq(PSUPDRVSESSION pSession, PINTNETIFABORTWAITREQ pReq);
+
+
+#if defined(IN_RING0) || defined(IN_INTNET_TESTCASE)
+/** @name
+ * @{
+ */
+
+INTNETR0DECL(int) IntNetR0Init(void);
+INTNETR0DECL(void) IntNetR0Term(void);
+INTNETR0DECL(int) IntNetR0Open(PSUPDRVSESSION pSession, const char *pszNetwork,
+ INTNETTRUNKTYPE enmTrunkType, const char *pszTrunk, uint32_t fFlags,
+ uint32_t cbSend, uint32_t cbRecv, PINTNETIFHANDLE phIf);
+INTNETR0DECL(uint32_t) IntNetR0GetNetworkCount(void);
+
+INTNETR0DECL(int) IntNetR0IfClose(INTNETIFHANDLE hIf, PSUPDRVSESSION pSession);
+INTNETR0DECL(int) IntNetR0IfGetBufferPtrs(INTNETIFHANDLE hIf, PSUPDRVSESSION pSession,
+ R3PTRTYPE(PINTNETBUF) *ppRing3Buf, R0PTRTYPE(PINTNETBUF) *ppRing0Buf);
+INTNETR0DECL(int) IntNetR0IfSetPromiscuousMode(INTNETIFHANDLE hIf, PSUPDRVSESSION pSession, bool fPromiscuous);
+INTNETR0DECL(int) IntNetR0IfSetMacAddress(INTNETIFHANDLE hIf, PSUPDRVSESSION pSession, PCRTMAC pMac);
+INTNETR0DECL(int) IntNetR0IfSetActive(INTNETIFHANDLE hIf, PSUPDRVSESSION pSession, bool fActive);
+INTNETR0DECL(int) IntNetR0IfSend(INTNETIFHANDLE hIf, PSUPDRVSESSION pSession);
+INTNETR0DECL(int) IntNetR0IfWait(INTNETIFHANDLE hIf, PSUPDRVSESSION pSession, uint32_t cMillies);
+INTNETR0DECL(int) IntNetR0IfAbortWait(INTNETIFHANDLE hIf, PSUPDRVSESSION pSession);
+
+/** @} */
+#endif /* IN_RING0 */
+
+/**
+ * Callback function for use with IntNetR3Open to signalling incoming data.
+ *
+ * @param hIf Interface handle.
+ * @param pvUser User parameter.
+ */
+typedef DECLCALLBACKTYPE(void, FNINTNETIFRECVAVAIL,(INTNETIFHANDLE hIf, void *pvUser));
+/** Pointer to a FNINTNETIFRECVAVAIL callback. */
+typedef FNINTNETIFRECVAVAIL *PFNINTNETIFRECVAVAIL;
+
+#if defined(VBOX_WITH_INTNET_SERVICE_IN_R3) && defined(IN_RING3)
+INTNETR3DECL(int) IntNetR3Open(PSUPDRVSESSION pSession, const char *pszNetwork,
+ INTNETTRUNKTYPE enmTrunkType, const char *pszTrunk, uint32_t fFlags,
+ uint32_t cbSend, uint32_t cbRecv, PFNINTNETIFRECVAVAIL pfnRecvAvail,
+ void *pvUserRecvAvail, PINTNETIFHANDLE phIf);
+#endif
+
+RT_C_DECLS_END
+
+#endif /* !VBOX_INCLUDED_intnet_h */
diff --git a/include/VBox/intnetinline.h b/include/VBox/intnetinline.h
new file mode 100644
index 00000000..adb338ef
--- /dev/null
+++ b/include/VBox/intnetinline.h
@@ -0,0 +1,837 @@
+/* $Id: intnetinline.h $ */
+/** @file
+ * INTNET - Internal Networking, Inlined Code. (DEV,++)
+ *
+ * This is all inlined because it's too tedious to create 2-3 libraries to
+ * contain it all. Large parts of this header is only accessible from C++
+ * sources because of mixed code and variables.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_intnetinline_h
+#define VBOX_INCLUDED_intnetinline_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/intnet.h>
+#include <iprt/string.h>
+#include <iprt/assert.h>
+#include <iprt/err.h>
+#include <VBox/log.h>
+
+
+
+/**
+ * Valid internal networking frame type.
+ *
+ * @returns true / false.
+ * @param u8Type The frame type to check.
+ */
+DECLINLINE(bool) IntNetIsValidFrameType(uint8_t u8Type)
+{
+ if (RT_LIKELY( u8Type == INTNETHDR_TYPE_FRAME
+ || u8Type == INTNETHDR_TYPE_GSO
+ || u8Type == INTNETHDR_TYPE_PADDING))
+ return true;
+ return false;
+}
+
+
+/**
+ * Partly initializes a scatter / gather buffer, leaving the segments to the
+ * caller.
+ *
+ * @returns Pointer to the start of the frame.
+ * @param pSG Pointer to the scatter / gather structure.
+ * @param cbTotal The total size.
+ * @param cSegs The number of segments.
+ * @param cSegsUsed The number of used segments.
+ */
+DECLINLINE(void) IntNetSgInitTempSegs(PINTNETSG pSG, uint32_t cbTotal, unsigned cSegs, unsigned cSegsUsed)
+{
+ pSG->pvOwnerData = NULL;
+ pSG->pvUserData = NULL;
+ pSG->pvUserData2 = NULL;
+ pSG->cbTotal = cbTotal;
+ pSG->cUsers = 1;
+ pSG->fFlags = INTNETSG_FLAGS_TEMP;
+ pSG->GsoCtx.u8Type = (uint8_t)PDMNETWORKGSOTYPE_INVALID;
+ pSG->GsoCtx.cbHdrsTotal = 0;
+ pSG->GsoCtx.cbHdrsSeg = 0;
+ pSG->GsoCtx.cbMaxSeg= 0;
+ pSG->GsoCtx.offHdr1 = 0;
+ pSG->GsoCtx.offHdr2 = 0;
+ pSG->GsoCtx.u8Unused= 0;
+#if ARCH_BITS == 64
+ pSG->uPadding = 0;
+#endif
+ pSG->cSegsAlloc = (uint16_t)cSegs;
+ Assert(pSG->cSegsAlloc == cSegs);
+ pSG->cSegsUsed = (uint16_t)cSegsUsed;
+ Assert(pSG->cSegsUsed == cSegsUsed);
+ Assert(cSegs >= cSegsUsed);
+}
+
+
+/**
+ * Partly initializes a scatter / gather buffer w/ GSO, leaving the segments to
+ * the caller.
+ *
+ * @returns Pointer to the start of the frame.
+ * @param pSG Pointer to the scatter / gather structure.
+ * @param cbTotal The total size.
+ * @param cSegs The number of segments.
+ * @param cSegsUsed The number of used segments.
+ * @param pGso The GSO context.
+ */
+DECLINLINE(void) IntNetSgInitTempSegsGso(PINTNETSG pSG, uint32_t cbTotal, unsigned cSegs,
+ unsigned cSegsUsed, PCPDMNETWORKGSO pGso)
+{
+ pSG->pvOwnerData = NULL;
+ pSG->pvUserData = NULL;
+ pSG->pvUserData2 = NULL;
+ pSG->cbTotal = cbTotal;
+ pSG->cUsers = 1;
+ pSG->fFlags = INTNETSG_FLAGS_TEMP;
+ pSG->GsoCtx.u8Type = pGso->u8Type;
+ pSG->GsoCtx.cbHdrsTotal = pGso->cbHdrsTotal;
+ pSG->GsoCtx.cbHdrsSeg = pGso->cbHdrsSeg;
+ pSG->GsoCtx.cbMaxSeg= pGso->cbMaxSeg;
+ pSG->GsoCtx.offHdr1 = pGso->offHdr1;
+ pSG->GsoCtx.offHdr2 = pGso->offHdr2;
+ pSG->GsoCtx.u8Unused= 0;
+#if ARCH_BITS == 64
+ pSG->uPadding = 0;
+#endif
+ pSG->cSegsAlloc = (uint16_t)cSegs;
+ Assert(pSG->cSegsAlloc == cSegs);
+ pSG->cSegsUsed = (uint16_t)cSegsUsed;
+ Assert(pSG->cSegsUsed == cSegsUsed);
+ Assert(cSegs >= cSegsUsed);
+}
+
+
+
+/**
+ * Initializes a scatter / gather buffer describing a simple linear buffer.
+ *
+ * @returns Pointer to the start of the frame.
+ * @param pSG Pointer to the scatter / gather structure.
+ * @param pvFrame Pointer to the frame
+ * @param cbFrame The size of the frame.
+ */
+DECLINLINE(void) IntNetSgInitTemp(PINTNETSG pSG, void *pvFrame, uint32_t cbFrame)
+{
+ IntNetSgInitTempSegs(pSG, cbFrame, 1, 1);
+ pSG->aSegs[0].Phys = NIL_RTHCPHYS;
+ pSG->aSegs[0].pv = pvFrame;
+ pSG->aSegs[0].cb = cbFrame;
+}
+
+/**
+ * Initializes a scatter / gather buffer describing a simple linear buffer.
+ *
+ * @returns Pointer to the start of the frame.
+ * @param pSG Pointer to the scatter / gather structure.
+ * @param pvFrame Pointer to the frame
+ * @param cbFrame The size of the frame.
+ * @param pGso The GSO context.
+ */
+DECLINLINE(void) IntNetSgInitTempGso(PINTNETSG pSG, void *pvFrame, uint32_t cbFrame, PCPDMNETWORKGSO pGso)
+{
+ IntNetSgInitTempSegsGso(pSG, cbFrame, 1, 1, pGso);
+ pSG->aSegs[0].Phys = NIL_RTHCPHYS;
+ pSG->aSegs[0].pv = pvFrame;
+ pSG->aSegs[0].cb = cbFrame;
+}
+
+
+/**
+ * Reads an entire SG into a fittingly size buffer.
+ *
+ * @param pSG The SG list to read.
+ * @param pvBuf The buffer to read into (at least pSG->cbTotal in size).
+ */
+DECLINLINE(void) IntNetSgRead(PCINTNETSG pSG, void *pvBuf)
+{
+ memcpy(pvBuf, pSG->aSegs[0].pv, pSG->aSegs[0].cb);
+ if (pSG->cSegsUsed == 1)
+ Assert(pSG->cbTotal == pSG->aSegs[0].cb);
+ else
+ {
+ uint8_t *pbDst = (uint8_t *)pvBuf + pSG->aSegs[0].cb;
+ unsigned iSeg = 0;
+ unsigned const cSegs = pSG->cSegsUsed;
+ while (++iSeg < cSegs)
+ {
+ uint32_t cbSeg = pSG->aSegs[iSeg].cb;
+ Assert((uintptr_t)pbDst - (uintptr_t)pvBuf + cbSeg <= pSG->cbTotal);
+ memcpy(pbDst, pSG->aSegs[iSeg].pv, cbSeg);
+ pbDst += cbSeg;
+ }
+ }
+}
+
+
+/**
+ * Reads a portion of an SG into a buffer.
+ *
+ * @param pSG The SG list to read.
+ * @param offSrc The offset to start start copying from.
+ * @param cbToRead The number of bytes to copy.
+ * @param pvBuf The buffer to read into, cb or more in size.
+ */
+DECLINLINE(void) IntNetSgReadEx(PCINTNETSG pSG, uint32_t offSrc, uint32_t cbToRead, void *pvBuf)
+{
+ uint8_t *pbDst = (uint8_t *)pvBuf;
+ uint32_t iSeg = 0;
+
+ /* validate assumptions */
+ Assert(cbToRead <= pSG->cbTotal);
+ Assert(offSrc <= pSG->cbTotal);
+ Assert(offSrc + cbToRead <= pSG->cbTotal);
+
+ /* Find the right segment and copy any bits from within the segment. */
+ while (offSrc)
+ {
+ uint32_t cbSeg = pSG->aSegs[iSeg].cb;
+ if (offSrc < cbSeg)
+ {
+ uint32_t cbChunk = cbSeg - offSrc;
+ if (cbChunk >= cbToRead)
+ {
+ memcpy(pbDst, (uint8_t const *)pSG->aSegs[iSeg].pv + offSrc, cbToRead);
+ return;
+ }
+
+ memcpy(pbDst, (uint8_t const *)pSG->aSegs[iSeg].pv + offSrc, cbChunk);
+ pbDst += cbChunk;
+ cbToRead -= cbChunk;
+ break;
+ }
+
+ /* advance */
+ offSrc -= cbSeg;
+ iSeg++;
+ }
+
+ /* We're not at the start of a segment, copy until we're done. */
+ for (;;)
+ {
+ uint32_t cbSeg = pSG->aSegs[iSeg].cb;
+ if (cbSeg >= cbToRead)
+ {
+ memcpy(pbDst, pSG->aSegs[iSeg].pv, cbToRead);
+ return;
+ }
+
+ memcpy(pbDst, pSG->aSegs[iSeg].pv, cbSeg);
+ pbDst += cbSeg;
+ cbToRead -= cbSeg;
+ iSeg++;
+ Assert(iSeg < pSG->cSegsUsed);
+ }
+}
+
+#ifdef __cplusplus
+
+/**
+ * Get the amount of space available for writing.
+ *
+ * @returns Number of available bytes.
+ * @param pRingBuf The ring buffer.
+ */
+DECLINLINE(uint32_t) IntNetRingGetWritable(PINTNETRINGBUF pRingBuf)
+{
+ uint32_t const offRead = ASMAtomicUoReadU32(&pRingBuf->offReadX);
+ uint32_t const offWriteInt = ASMAtomicUoReadU32(&pRingBuf->offWriteInt);
+ return offRead <= offWriteInt
+ ? pRingBuf->offEnd - offWriteInt + offRead - pRingBuf->offStart - 1
+ : offRead - offWriteInt - 1;
+}
+
+
+/**
+ * Checks if the ring has more for us to read.
+ *
+ * @returns Number of ready bytes.
+ * @param pRingBuf The ring buffer.
+ */
+DECLINLINE(bool) IntNetRingHasMoreToRead(PINTNETRINGBUF pRingBuf)
+{
+ uint32_t const offRead = ASMAtomicUoReadU32(&pRingBuf->offReadX);
+ uint32_t const offWriteCom = ASMAtomicUoReadU32(&pRingBuf->offWriteCom);
+ return offRead != offWriteCom;
+}
+
+
+/**
+ * Gets the next frame to read.
+ *
+ * @returns Pointer to the next frame. NULL if done.
+ * @param pRingBuf The ring buffer.
+ */
+DECLINLINE(PINTNETHDR) IntNetRingGetNextFrameToRead(PINTNETRINGBUF pRingBuf)
+{
+ uint32_t const offRead = ASMAtomicUoReadU32(&pRingBuf->offReadX);
+ uint32_t const offWriteCom = ASMAtomicUoReadU32(&pRingBuf->offWriteCom);
+ if (offRead == offWriteCom)
+ return NULL;
+ return (PINTNETHDR)((uint8_t *)pRingBuf + offRead);
+}
+
+
+/**
+ * Get the amount of data ready for reading.
+ *
+ * @returns Number of ready bytes.
+ * @param pRingBuf The ring buffer.
+ */
+DECLINLINE(uint32_t) IntNetRingGetReadable(PINTNETRINGBUF pRingBuf)
+{
+ uint32_t const offRead = ASMAtomicUoReadU32(&pRingBuf->offReadX);
+ uint32_t const offWriteCom = ASMAtomicUoReadU32(&pRingBuf->offWriteCom);
+ return offRead <= offWriteCom
+ ? offWriteCom - offRead
+ : pRingBuf->offEnd - offRead + offWriteCom - pRingBuf->offStart;
+}
+
+
+/**
+ * Calculates the pointer to the frame.
+ *
+ * @returns Pointer to the start of the frame.
+ * @param pHdr Pointer to the packet header
+ * @param pBuf The buffer the header is within. Only used in strict builds.
+ */
+DECLINLINE(void *) IntNetHdrGetFramePtr(PCINTNETHDR pHdr, PCINTNETBUF pBuf)
+{
+ uint8_t *pu8 = (uint8_t *)pHdr + pHdr->offFrame;
+#ifdef VBOX_STRICT
+ const uintptr_t off = (uintptr_t)pu8 - (uintptr_t)pBuf;
+ Assert(IntNetIsValidFrameType(pHdr->u8Type));
+ Assert(off < pBuf->cbBuf);
+ Assert(off + pHdr->cbFrame <= pBuf->cbBuf);
+#endif
+ NOREF(pBuf);
+ return pu8;
+}
+
+
+/**
+ * Calculates the pointer to the GSO context.
+ *
+ * ASSUMES the frame is a GSO frame.
+ *
+ * The GSO context is immediately followed by the headers and payload. The size
+ * is INTNETBUF::cbFrame - sizeof(PDMNETWORKGSO).
+ *
+ * @returns Pointer to the GSO context.
+ * @param pHdr Pointer to the packet header
+ * @param pBuf The buffer the header is within. Only used in strict builds.
+ */
+DECLINLINE(PPDMNETWORKGSO) IntNetHdrGetGsoContext(PCINTNETHDR pHdr, PCINTNETBUF pBuf)
+{
+ PPDMNETWORKGSO pGso = (PPDMNETWORKGSO)((uint8_t *)pHdr + pHdr->offFrame);
+#ifdef VBOX_STRICT
+ const uintptr_t off = (uintptr_t)pGso - (uintptr_t)pBuf;
+ Assert(pHdr->u8Type == INTNETHDR_TYPE_GSO);
+ Assert(off < pBuf->cbBuf);
+ Assert(off + pHdr->cbFrame <= pBuf->cbBuf);
+#endif
+ NOREF(pBuf);
+ return pGso;
+}
+
+
+/**
+ * Skips to the next (read) frame in the buffer.
+ *
+ * @param pRingBuf The ring buffer in question.
+ */
+DECLINLINE(void) IntNetRingSkipFrame(PINTNETRINGBUF pRingBuf)
+{
+ uint32_t const offReadOld = ASMAtomicUoReadU32(&pRingBuf->offReadX);
+ PINTNETHDR pHdr = (PINTNETHDR)((uint8_t *)pRingBuf + offReadOld);
+ Assert(offReadOld >= pRingBuf->offStart);
+ Assert(offReadOld < pRingBuf->offEnd);
+ Assert(RT_ALIGN_PT(pHdr, INTNETHDR_ALIGNMENT, INTNETHDR *) == pHdr);
+ Assert(IntNetIsValidFrameType(pHdr->u8Type));
+
+ /* skip the frame */
+ uint32_t offReadNew = offReadOld + pHdr->offFrame + pHdr->cbFrame;
+ offReadNew = RT_ALIGN_32(offReadNew, INTNETHDR_ALIGNMENT);
+ Assert(offReadNew <= pRingBuf->offEnd && offReadNew >= pRingBuf->offStart);
+ if (offReadNew >= pRingBuf->offEnd)
+ offReadNew = pRingBuf->offStart;
+ Log2(("IntNetRingSkipFrame: offReadX: %#x -> %#x (1)\n", offReadOld, offReadNew));
+#ifdef INTNET_POISON_READ_FRAMES
+ memset((uint8_t *)pHdr + pHdr->offFrame, 0xfe, RT_ALIGN_32(pHdr->cbFrame, INTNETHDR_ALIGNMENT));
+ memset(pHdr, 0xef, sizeof(*pHdr));
+#endif
+ ASMAtomicWriteU32(&pRingBuf->offReadX, offReadNew);
+}
+
+
+/**
+ * Allocates a frame in the specified ring.
+ *
+ * @returns VINF_SUCCESS or VERR_BUFFER_OVERFLOW.
+ * @param pRingBuf The ring buffer.
+ * @param cbFrame The frame size.
+ * @param u8Type The header type.
+ * @param ppHdr Where to return the frame header.
+ * Don't touch this!
+ * @param ppvFrame Where to return the frame pointer.
+ */
+DECLINLINE(int) intnetRingAllocateFrameInternal(PINTNETRINGBUF pRingBuf, uint32_t cbFrame, uint8_t u8Type,
+ PINTNETHDR *ppHdr, void **ppvFrame)
+{
+ /*
+ * Validate input and adjust the input.
+ */
+ INTNETRINGBUF_ASSERT_SANITY(pRingBuf);
+ Assert(cbFrame >= sizeof(RTMAC) * 2);
+
+ const uint32_t cb = RT_ALIGN_32(cbFrame, INTNETHDR_ALIGNMENT);
+ uint32_t offWriteInt = ASMAtomicUoReadU32(&pRingBuf->offWriteInt);
+ uint32_t offRead = ASMAtomicUoReadU32(&pRingBuf->offReadX);
+ if (offRead <= offWriteInt)
+ {
+ /*
+ * Try fit it all before the end of the buffer.
+ */
+ if (pRingBuf->offEnd - offWriteInt >= cb + sizeof(INTNETHDR))
+ {
+ uint32_t offNew = offWriteInt + cb + sizeof(INTNETHDR);
+ if (offNew >= pRingBuf->offEnd)
+ offNew = pRingBuf->offStart;
+ if (RT_LIKELY(ASMAtomicCmpXchgU32(&pRingBuf->offWriteInt, offNew, offWriteInt)))
+ { /* likely */ } else return VERR_WRONG_ORDER; /* race */
+ Log2(("intnetRingAllocateFrameInternal: offWriteInt: %#x -> %#x (1) (R=%#x T=%#x S=%#x)\n", offWriteInt, offNew, offRead, u8Type, cbFrame));
+
+ PINTNETHDR pHdr = (PINTNETHDR)((uint8_t *)pRingBuf + offWriteInt);
+ pHdr->u8Type = u8Type;
+ pHdr->cbFrame = cbFrame; Assert(pHdr->cbFrame == cbFrame);
+ pHdr->offFrame = sizeof(INTNETHDR);
+
+ *ppHdr = pHdr;
+ *ppvFrame = pHdr + 1;
+ return VINF_SUCCESS;
+ }
+ /*
+ * Try fit the frame at the start of the buffer.
+ * (The header fits before the end of the buffer because of alignment.)
+ */
+ AssertMsg(pRingBuf->offEnd - offWriteInt >= sizeof(INTNETHDR), ("offEnd=%x offWriteInt=%x\n", pRingBuf->offEnd, offWriteInt));
+ if (offRead - pRingBuf->offStart > cb) /* not >= ! */
+ {
+ uint32_t offNew = pRingBuf->offStart + cb;
+ if (RT_LIKELY(ASMAtomicCmpXchgU32(&pRingBuf->offWriteInt, offNew, offWriteInt)))
+ { /* likely */ } else return VERR_WRONG_ORDER; /* race */
+ Log2(("intnetRingAllocateFrameInternal: offWriteInt: %#x -> %#x (2) (R=%#x T=%#x S=%#x)\n", offWriteInt, offNew, offRead, u8Type, cbFrame));
+
+ PINTNETHDR pHdr = (PINTNETHDR)((uint8_t *)pRingBuf + offWriteInt);
+ pHdr->u8Type = u8Type;
+ pHdr->cbFrame = cbFrame; Assert(pHdr->cbFrame == cbFrame);
+ pHdr->offFrame = pRingBuf->offStart - offWriteInt;
+
+ *ppHdr = pHdr;
+ *ppvFrame = (uint8_t *)pRingBuf + pRingBuf->offStart;
+ return VINF_SUCCESS;
+ }
+ }
+ /*
+ * The reader is ahead of the writer, try fit it into that space.
+ */
+ else if (offRead - offWriteInt > cb + sizeof(INTNETHDR)) /* not >= ! */
+ {
+ uint32_t offNew = offWriteInt + cb + sizeof(INTNETHDR);
+ if (RT_LIKELY(ASMAtomicCmpXchgU32(&pRingBuf->offWriteInt, offNew, offWriteInt)))
+ { /* likely */ } else return VERR_WRONG_ORDER; /* race */
+ Log2(("intnetRingAllocateFrameInternal: offWriteInt: %#x -> %#x (3) (R=%#x T=%#x S=%#x)\n", offWriteInt, offNew, offRead, u8Type, cbFrame));
+
+ PINTNETHDR pHdr = (PINTNETHDR)((uint8_t *)pRingBuf + offWriteInt);
+ pHdr->u8Type = u8Type;
+ pHdr->cbFrame = cbFrame; Assert(pHdr->cbFrame == cbFrame);
+ pHdr->offFrame = sizeof(INTNETHDR);
+
+ *ppHdr = pHdr;
+ *ppvFrame = pHdr + 1;
+ return VINF_SUCCESS;
+ }
+
+ /* (it didn't fit) */
+ *ppHdr = NULL; /* shut up gcc, */
+ *ppvFrame = NULL; /* ditto. */
+ STAM_REL_COUNTER_INC(&pRingBuf->cOverflows);
+ return VERR_BUFFER_OVERFLOW;
+}
+
+
+/**
+ * Allocates a normal frame in the specified ring.
+ *
+ * @returns VINF_SUCCESS or VERR_BUFFER_OVERFLOW.
+ * @param pRingBuf The ring buffer.
+ * @param cbFrame The frame size.
+ * @param ppHdr Where to return the frame header.
+ * Don't touch this!
+ * @param ppvFrame Where to return the frame pointer.
+ */
+DECLINLINE(int) IntNetRingAllocateFrame(PINTNETRINGBUF pRingBuf, uint32_t cbFrame, PINTNETHDR *ppHdr, void **ppvFrame)
+{
+ return intnetRingAllocateFrameInternal(pRingBuf, cbFrame, INTNETHDR_TYPE_FRAME, ppHdr, ppvFrame);
+}
+
+
+/**
+ * Allocates a GSO frame in the specified ring.
+ *
+ * @returns VINF_SUCCESS or VERR_BUFFER_OVERFLOW.
+ * @param pRingBuf The ring buffer.
+ * @param cbFrame The frame size.
+ * @param pGso Pointer to the GSO context.
+ * @param ppHdr Where to return the frame header.
+ * Don't touch this!
+ * @param ppvFrame Where to return the frame pointer.
+ */
+DECLINLINE(int) IntNetRingAllocateGsoFrame(PINTNETRINGBUF pRingBuf, uint32_t cbFrame, PCPDMNETWORKGSO pGso,
+ PINTNETHDR *ppHdr, void **ppvFrame)
+{
+ void *pvFrame = NULL; /* gcc maybe used uninitialized */
+ int rc = intnetRingAllocateFrameInternal(pRingBuf, cbFrame + sizeof(*pGso), INTNETHDR_TYPE_GSO, ppHdr, &pvFrame);
+ if (RT_SUCCESS(rc))
+ {
+ PPDMNETWORKGSO pGsoCopy = (PPDMNETWORKGSO)pvFrame;
+ *pGsoCopy = *pGso;
+ *ppvFrame = pGsoCopy + 1;
+ }
+ return rc;
+}
+
+
+/**
+ * Commits a frame.
+ *
+ * Make sure to commit the frames in the order they've been allocated!
+ *
+ * @returns VINF_SUCCESS or VERR_BUFFER_OVERFLOW.
+ * @param pRingBuf The ring buffer.
+ * @param pHdr The frame header returned by
+ * IntNetRingAllocateFrame.
+ */
+DECLINLINE(void) IntNetRingCommitFrame(PINTNETRINGBUF pRingBuf, PINTNETHDR pHdr)
+{
+ /*
+ * Validate input and commit order.
+ */
+ INTNETRINGBUF_ASSERT_SANITY(pRingBuf);
+ INTNETHDR_ASSERT_SANITY(pHdr, pRingBuf);
+ Assert(pRingBuf->offWriteCom == ((uintptr_t)pHdr - (uintptr_t)pRingBuf));
+
+ /*
+ * Figure out the offWriteCom for this packet and update the ring.
+ */
+ const uint32_t cbFrame = pHdr->cbFrame;
+ const uint32_t cb = RT_ALIGN_32(cbFrame, INTNETHDR_ALIGNMENT);
+ uint32_t offWriteCom = (uint32_t)((uintptr_t)pHdr - (uintptr_t)pRingBuf)
+ + pHdr->offFrame
+ + cb;
+ if (offWriteCom >= pRingBuf->offEnd)
+ {
+ Assert(offWriteCom == pRingBuf->offEnd);
+ offWriteCom = pRingBuf->offStart;
+ }
+ Log2(("IntNetRingCommitFrame: offWriteCom: %#x -> %#x (R=%#x T=%#x S=%#x)\n", pRingBuf->offWriteCom, offWriteCom, pRingBuf->offReadX, pHdr->u8Type, cbFrame));
+ ASMAtomicWriteU32(&pRingBuf->offWriteCom, offWriteCom);
+ STAM_REL_COUNTER_ADD(&pRingBuf->cbStatWritten, cbFrame);
+ STAM_REL_COUNTER_INC(&pRingBuf->cStatFrames);
+}
+
+
+/**
+ * Commits a frame and injects a filler frame if not all of the buffer was used.
+ *
+ * Make sure to commit the frames in the order they've been allocated!
+ *
+ * @returns VINF_SUCCESS or VERR_BUFFER_OVERFLOW.
+ * @param pRingBuf The ring buffer.
+ * @param pHdr The frame header returned by
+ * IntNetRingAllocateFrame.
+ * @param cbUsed The amount of space actually used. This does
+ * not include the GSO part.
+ */
+DECLINLINE(void) IntNetRingCommitFrameEx(PINTNETRINGBUF pRingBuf, PINTNETHDR pHdr, size_t cbUsed)
+{
+ /*
+ * Validate input and commit order.
+ */
+ INTNETRINGBUF_ASSERT_SANITY(pRingBuf);
+ INTNETHDR_ASSERT_SANITY(pHdr, pRingBuf);
+ Assert(pRingBuf->offWriteCom == ((uintptr_t)pHdr - (uintptr_t)pRingBuf));
+
+ if (pHdr->u8Type == INTNETHDR_TYPE_GSO)
+ cbUsed += sizeof(PDMNETWORKGSO);
+
+ /*
+ * Calc the new write commit offset.
+ */
+ const uint32_t cbAlignedFrame = RT_ALIGN_32(pHdr->cbFrame, INTNETHDR_ALIGNMENT);
+ const uint32_t cbAlignedUsed = RT_ALIGN_32(cbUsed, INTNETHDR_ALIGNMENT);
+ uint32_t offWriteCom = (uint32_t)((uintptr_t)pHdr - (uintptr_t)pRingBuf)
+ + pHdr->offFrame
+ + cbAlignedFrame;
+ if (offWriteCom >= pRingBuf->offEnd)
+ {
+ Assert(offWriteCom == pRingBuf->offEnd);
+ offWriteCom = pRingBuf->offStart;
+ }
+
+ /*
+ * Insert a dummy frame to pad any unused space.
+ */
+ if (cbAlignedFrame != cbAlignedUsed)
+ {
+ /** @todo Later: Try unallocate the extra memory. */
+ PINTNETHDR pHdrPadding = (PINTNETHDR)((uint8_t *)pHdr + pHdr->offFrame + cbAlignedUsed);
+ pHdrPadding->u8Type = INTNETHDR_TYPE_PADDING;
+ pHdrPadding->cbFrame = cbAlignedFrame - cbAlignedUsed - sizeof(INTNETHDR);
+ Assert(pHdrPadding->cbFrame == cbAlignedFrame - cbAlignedUsed - sizeof(INTNETHDR));
+ pHdrPadding->offFrame = sizeof(INTNETHDR);
+ pHdr->cbFrame = cbUsed; Assert(pHdr->cbFrame == cbUsed);
+ }
+
+ Log2(("IntNetRingCommitFrameEx: offWriteCom: %#x -> %#x (R=%#x T=%#x S=%#x P=%#x)\n", pRingBuf->offWriteCom, offWriteCom, pRingBuf->offReadX, pHdr->u8Type, pHdr->cbFrame, cbAlignedFrame - cbAlignedUsed));
+ ASMAtomicWriteU32(&pRingBuf->offWriteCom, offWriteCom);
+ STAM_REL_COUNTER_ADD(&pRingBuf->cbStatWritten, cbUsed);
+ STAM_REL_COUNTER_INC(&pRingBuf->cStatFrames);
+}
+
+
+/**
+ * Writes a frame to the specified ring.
+ *
+ * Make sure you don't have any uncommitted frames when calling this function!
+ *
+ * @returns VINF_SUCCESS or VERR_BUFFER_OVERFLOW.
+ * @param pRingBuf The ring buffer.
+ * @param pvFrame The bits to write.
+ * @param cbFrame How much to write.
+ */
+DECLINLINE(int) IntNetRingWriteFrame(PINTNETRINGBUF pRingBuf, const void *pvFrame, size_t cbFrame)
+{
+ /*
+ * Validate input.
+ */
+ INTNETRINGBUF_ASSERT_SANITY(pRingBuf);
+ Assert(cbFrame >= sizeof(RTMAC) * 2);
+
+ /*
+ * Align the size and read the volatile ring buffer variables.
+ */
+ const uint32_t cb = RT_ALIGN_32(cbFrame, INTNETHDR_ALIGNMENT);
+ uint32_t offWriteInt = ASMAtomicUoReadU32(&pRingBuf->offWriteInt);
+ uint32_t offRead = ASMAtomicUoReadU32(&pRingBuf->offReadX);
+ if (offRead <= offWriteInt)
+ {
+ /*
+ * Try fit it all before the end of the buffer.
+ */
+ if (pRingBuf->offEnd - offWriteInt >= cb + sizeof(INTNETHDR))
+ {
+ uint32_t offNew = offWriteInt + cb + sizeof(INTNETHDR);
+ if (offNew >= pRingBuf->offEnd)
+ offNew = pRingBuf->offStart;
+ if (RT_LIKELY(ASMAtomicCmpXchgU32(&pRingBuf->offWriteInt, offNew, offWriteInt)))
+ { /* likely */ } else return VERR_WRONG_ORDER; /* race */
+ Log2(("IntNetRingWriteFrame: offWriteInt: %#x -> %#x (1)\n", offWriteInt, offNew));
+
+ PINTNETHDR pHdr = (PINTNETHDR)((uint8_t *)pRingBuf + offWriteInt);
+ pHdr->u8Type = INTNETHDR_TYPE_FRAME;
+ pHdr->cbFrame = cbFrame; Assert(pHdr->cbFrame == cbFrame);
+ pHdr->offFrame = sizeof(INTNETHDR);
+
+ memcpy(pHdr + 1, pvFrame, cbFrame);
+
+ Log2(("IntNetRingWriteFrame: offWriteCom: %#x -> %#x (1)\n", pRingBuf->offWriteCom, offNew));
+ ASMAtomicWriteU32(&pRingBuf->offWriteCom, offNew);
+ STAM_REL_COUNTER_ADD(&pRingBuf->cbStatWritten, cbFrame);
+ STAM_REL_COUNTER_INC(&pRingBuf->cStatFrames);
+ return VINF_SUCCESS;
+ }
+ /*
+ * Try fit the frame at the start of the buffer.
+ * (The header fits before the end of the buffer because of alignment.)
+ */
+ AssertMsg(pRingBuf->offEnd - offWriteInt >= sizeof(INTNETHDR), ("offEnd=%x offWriteInt=%x\n", pRingBuf->offEnd, offWriteInt));
+ if (offRead - pRingBuf->offStart > cb) /* not >= ! */
+ {
+ uint32_t offNew = pRingBuf->offStart + cb;
+ if (RT_LIKELY(ASMAtomicCmpXchgU32(&pRingBuf->offWriteInt, offNew, offWriteInt)))
+ { /* likely */ } else return VERR_WRONG_ORDER; /* race */
+ Log2(("IntNetRingWriteFrame: offWriteInt: %#x -> %#x (2)\n", offWriteInt, offNew));
+
+ PINTNETHDR pHdr = (PINTNETHDR)((uint8_t *)pRingBuf + offWriteInt);
+ pHdr->u8Type = INTNETHDR_TYPE_FRAME;
+ pHdr->cbFrame = cbFrame; Assert(pHdr->cbFrame == cbFrame);
+ pHdr->offFrame = pRingBuf->offStart - offWriteInt;
+
+ memcpy((uint8_t *)pRingBuf + pRingBuf->offStart, pvFrame, cbFrame);
+
+ Log2(("IntNetRingWriteFrame: offWriteCom: %#x -> %#x (2)\n", pRingBuf->offWriteCom, offNew));
+ ASMAtomicWriteU32(&pRingBuf->offWriteCom, offNew);
+ STAM_REL_COUNTER_ADD(&pRingBuf->cbStatWritten, cbFrame);
+ STAM_REL_COUNTER_INC(&pRingBuf->cStatFrames);
+ return VINF_SUCCESS;
+ }
+ }
+ /*
+ * The reader is ahead of the writer, try fit it into that space.
+ */
+ else if (offRead - offWriteInt > cb + sizeof(INTNETHDR)) /* not >= ! */
+ {
+ uint32_t offNew = offWriteInt + cb + sizeof(INTNETHDR);
+ if (RT_LIKELY(ASMAtomicCmpXchgU32(&pRingBuf->offWriteInt, offNew, offWriteInt)))
+ { /* likely */ } else return VERR_WRONG_ORDER; /* race */
+ Log2(("IntNetRingWriteFrame: offWriteInt: %#x -> %#x (3)\n", offWriteInt, offNew));
+
+ PINTNETHDR pHdr = (PINTNETHDR)((uint8_t *)pRingBuf + offWriteInt);
+ pHdr->u8Type = INTNETHDR_TYPE_FRAME;
+ pHdr->cbFrame = cbFrame; Assert(pHdr->cbFrame == cbFrame);
+ pHdr->offFrame = sizeof(INTNETHDR);
+
+ memcpy(pHdr + 1, pvFrame, cbFrame);
+
+ Log2(("IntNetRingWriteFrame: offWriteCom: %#x -> %#x (3)\n", pRingBuf->offWriteCom, offNew));
+ ASMAtomicWriteU32(&pRingBuf->offWriteCom, offNew);
+ STAM_REL_COUNTER_ADD(&pRingBuf->cbStatWritten, cbFrame);
+ STAM_REL_COUNTER_INC(&pRingBuf->cStatFrames);
+ return VINF_SUCCESS;
+ }
+
+ /* (it didn't fit) */
+ STAM_REL_COUNTER_INC(&pRingBuf->cOverflows);
+ return VERR_BUFFER_OVERFLOW;
+}
+
+
+/**
+ * Reads the next frame in the buffer and moves the read cursor past it.
+ *
+ * @returns Size of the frame in bytes. 0 is returned if nothing in the buffer.
+ * @param pRingBuf The ring buffer to read from.
+ * @param pvFrameDst Where to put the frame. The caller is responsible for
+ * ensuring that there is sufficient space for the frame.
+ *
+ * @deprecated Bad interface, do NOT use it! Only for tstIntNetR0.
+ */
+DECLINLINE(uint32_t) IntNetRingReadAndSkipFrame(PINTNETRINGBUF pRingBuf, void *pvFrameDst)
+{
+ INTNETRINGBUF_ASSERT_SANITY(pRingBuf);
+
+ uint32_t offRead = ASMAtomicUoReadU32(&pRingBuf->offReadX);
+ uint32_t const offWriteCom = ASMAtomicUoReadU32(&pRingBuf->offWriteCom);
+ if (offRead == offWriteCom)
+ return 0;
+
+ PINTNETHDR pHdr = (PINTNETHDR)((uint8_t *)pRingBuf + offRead);
+ INTNETHDR_ASSERT_SANITY(pHdr, pRingBuf);
+
+ uint32_t const cbFrame = pHdr->cbFrame;
+ int32_t const offFrame = pHdr->offFrame;
+ const void *pvFrameSrc = (uint8_t *)pHdr + offFrame;
+ memcpy(pvFrameDst, pvFrameSrc, cbFrame);
+#ifdef INTNET_POISON_READ_FRAMES
+ memset((void *)pvFrameSrc, 0xfe, RT_ALIGN_32(cbFrame, INTNETHDR_ALIGNMENT));
+ memset(pHdr, 0xef, sizeof(*pHdr));
+#endif
+
+ /* skip the frame */
+ offRead += offFrame + cbFrame;
+ offRead = RT_ALIGN_32(offRead, INTNETHDR_ALIGNMENT);
+ Assert(offRead <= pRingBuf->offEnd && offRead >= pRingBuf->offStart);
+ if (offRead >= pRingBuf->offEnd)
+ offRead = pRingBuf->offStart;
+ ASMAtomicWriteU32(&pRingBuf->offReadX, offRead);
+ return cbFrame;
+}
+
+
+/**
+ * Initializes a buffer structure.
+ *
+ * @param pIntBuf The internal networking interface buffer. This
+ * expected to be cleared prior to calling this
+ * function.
+ * @param cbBuf The size of the whole buffer.
+ * @param cbRecv The receive size.
+ * @param cbSend The send size.
+ */
+DECLINLINE(void) IntNetBufInit(PINTNETBUF pIntBuf, uint32_t cbBuf, uint32_t cbRecv, uint32_t cbSend)
+{
+ AssertCompileSizeAlignment(INTNETBUF, INTNETHDR_ALIGNMENT);
+ AssertCompileSizeAlignment(INTNETBUF, INTNETRINGBUF_ALIGNMENT);
+ Assert(cbBuf >= sizeof(INTNETBUF) + cbRecv + cbSend);
+ Assert(RT_ALIGN_32(cbRecv, INTNETRINGBUF_ALIGNMENT) == cbRecv);
+ Assert(RT_ALIGN_32(cbSend, INTNETRINGBUF_ALIGNMENT) == cbSend);
+ Assert(ASMMemIsZero(pIntBuf, cbBuf));
+
+ pIntBuf->u32Magic = INTNETBUF_MAGIC;
+ pIntBuf->cbBuf = cbBuf;
+ pIntBuf->cbRecv = cbRecv;
+ pIntBuf->cbSend = cbSend;
+
+ /* receive ring buffer. */
+ uint32_t offBuf = RT_ALIGN_32(sizeof(INTNETBUF), INTNETRINGBUF_ALIGNMENT) - RT_UOFFSETOF(INTNETBUF, Recv);
+ pIntBuf->Recv.offStart = offBuf;
+ pIntBuf->Recv.offReadX = offBuf;
+ pIntBuf->Recv.offWriteInt = offBuf;
+ pIntBuf->Recv.offWriteCom = offBuf;
+ pIntBuf->Recv.offEnd = offBuf + cbRecv;
+
+ /* send ring buffer. */
+ offBuf += cbRecv + RT_UOFFSETOF(INTNETBUF, Recv) - RT_UOFFSETOF(INTNETBUF, Send);
+ pIntBuf->Send.offStart = offBuf;
+ pIntBuf->Send.offReadX = offBuf;
+ pIntBuf->Send.offWriteCom = offBuf;
+ pIntBuf->Send.offWriteInt = offBuf;
+ pIntBuf->Send.offEnd = offBuf + cbSend;
+ Assert(cbBuf >= offBuf + cbSend);
+}
+
+#endif /* __cplusplus */
+
+#endif /* !VBOX_INCLUDED_intnetinline_h */
+
diff --git a/include/VBox/iommu-amd.h b/include/VBox/iommu-amd.h
new file mode 100644
index 00000000..76558831
--- /dev/null
+++ b/include/VBox/iommu-amd.h
@@ -0,0 +1,2718 @@
+/** @file
+ * IOMMU - Input/Output Memory Management Unit (AMD).
+ */
+
+/*
+ * Copyright (C) 2020-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_iommu_amd_h
+#define VBOX_INCLUDED_iommu_amd_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+#include <iprt/assertcompile.h>
+
+/**
+ * @name PCI configuration register offsets.
+ * In accordance with the AMD spec.
+ * @{
+ */
+#define IOMMU_PCI_OFF_CAP_HDR 0x40
+#define IOMMU_PCI_OFF_BASE_ADDR_REG_LO 0x44
+#define IOMMU_PCI_OFF_BASE_ADDR_REG_HI 0x48
+#define IOMMU_PCI_OFF_RANGE_REG 0x4c
+#define IOMMU_PCI_OFF_MISCINFO_REG_0 0x50
+#define IOMMU_PCI_OFF_MISCINFO_REG_1 0x54
+#define IOMMU_PCI_OFF_MSI_CAP_HDR 0x64
+#define IOMMU_PCI_OFF_MSI_ADDR_LO 0x68
+#define IOMMU_PCI_OFF_MSI_ADDR_HI 0x6c
+#define IOMMU_PCI_OFF_MSI_DATA 0x70
+#define IOMMU_PCI_OFF_MSI_MAP_CAP_HDR 0x74
+/** @} */
+
+/**
+ * @name MMIO register offsets.
+ * In accordance with the AMD spec.
+ * @{
+ */
+#define IOMMU_MMIO_OFF_QWORD_TABLE_0_START IOMMU_MMIO_OFF_DEV_TAB_BAR
+#define IOMMU_MMIO_OFF_DEV_TAB_BAR 0x00
+#define IOMMU_MMIO_OFF_CMD_BUF_BAR 0x08
+#define IOMMU_MMIO_OFF_EVT_LOG_BAR 0x10
+#define IOMMU_MMIO_OFF_CTRL 0x18
+#define IOMMU_MMIO_OFF_EXCL_BAR 0x20
+#define IOMMU_MMIO_OFF_EXCL_RANGE_LIMIT 0x28
+#define IOMMU_MMIO_OFF_EXT_FEAT 0x30
+
+#define IOMMU_MMIO_OFF_PPR_LOG_BAR 0x38
+#define IOMMU_MMIO_OFF_HW_EVT_HI 0x40
+#define IOMMU_MMIO_OFF_HW_EVT_LO 0x48
+#define IOMMU_MMIO_OFF_HW_EVT_STATUS 0x50
+
+#define IOMMU_MMIO_OFF_SMI_FLT_FIRST 0x60
+#define IOMMU_MMIO_OFF_SMI_FLT_LAST 0xd8
+
+#define IOMMU_MMIO_OFF_GALOG_BAR 0xe0
+#define IOMMU_MMIO_OFF_GALOG_TAIL_ADDR 0xe8
+
+#define IOMMU_MMIO_OFF_PPR_LOG_B_BAR 0xf0
+#define IOMMU_MMIO_OFF_PPR_EVT_B_BAR 0xf8
+
+#define IOMMU_MMIO_OFF_DEV_TAB_SEG_FIRST 0x100
+#define IOMMU_MMIO_OFF_DEV_TAB_SEG_1 0x100
+#define IOMMU_MMIO_OFF_DEV_TAB_SEG_2 0x108
+#define IOMMU_MMIO_OFF_DEV_TAB_SEG_3 0x110
+#define IOMMU_MMIO_OFF_DEV_TAB_SEG_4 0x118
+#define IOMMU_MMIO_OFF_DEV_TAB_SEG_5 0x120
+#define IOMMU_MMIO_OFF_DEV_TAB_SEG_6 0x128
+#define IOMMU_MMIO_OFF_DEV_TAB_SEG_7 0x130
+#define IOMMU_MMIO_OFF_DEV_TAB_SEG_LAST 0x130
+
+#define IOMMU_MMIO_OFF_DEV_SPECIFIC_FEAT 0x138
+#define IOMMU_MMIO_OFF_DEV_SPECIFIC_CTRL 0x140
+#define IOMMU_MMIO_OFF_DEV_SPECIFIC_STATUS 0x148
+
+#define IOMMU_MMIO_OFF_MSI_VECTOR_0 0x150
+#define IOMMU_MMIO_OFF_MSI_VECTOR_1 0x154
+#define IOMMU_MMIO_OFF_MSI_CAP_HDR 0x158
+#define IOMMU_MMIO_OFF_MSI_ADDR_LO 0x15c
+#define IOMMU_MMIO_OFF_MSI_ADDR_HI 0x160
+#define IOMMU_MMIO_OFF_MSI_DATA 0x164
+#define IOMMU_MMIO_OFF_MSI_MAPPING_CAP_HDR 0x168
+
+#define IOMMU_MMIO_OFF_PERF_OPT_CTRL 0x16c
+
+#define IOMMU_MMIO_OFF_XT_GEN_INTR_CTRL 0x170
+#define IOMMU_MMIO_OFF_XT_PPR_INTR_CTRL 0x178
+#define IOMMU_MMIO_OFF_XT_GALOG_INT_CTRL 0x180
+#define IOMMU_MMIO_OFF_QWORD_TABLE_0_END (IOMMU_MMIO_OFF_XT_GALOG_INT_CTRL + 8)
+
+#define IOMMU_MMIO_OFF_QWORD_TABLE_1_START IOMMU_MMIO_OFF_MARC_APER_BAR_0
+#define IOMMU_MMIO_OFF_MARC_APER_BAR_0 0x200
+#define IOMMU_MMIO_OFF_MARC_APER_RELOC_0 0x208
+#define IOMMU_MMIO_OFF_MARC_APER_LEN_0 0x210
+#define IOMMU_MMIO_OFF_MARC_APER_BAR_1 0x218
+#define IOMMU_MMIO_OFF_MARC_APER_RELOC_1 0x220
+#define IOMMU_MMIO_OFF_MARC_APER_LEN_1 0x228
+#define IOMMU_MMIO_OFF_MARC_APER_BAR_2 0x230
+#define IOMMU_MMIO_OFF_MARC_APER_RELOC_2 0x238
+#define IOMMU_MMIO_OFF_MARC_APER_LEN_2 0x240
+#define IOMMU_MMIO_OFF_MARC_APER_BAR_3 0x248
+#define IOMMU_MMIO_OFF_MARC_APER_RELOC_3 0x250
+#define IOMMU_MMIO_OFF_MARC_APER_LEN_3 0x258
+#define IOMMU_MMIO_OFF_QWORD_TABLE_1_END (IOMMU_MMIO_OFF_MARC_APER_LEN_3 + 8)
+
+#define IOMMU_MMIO_OFF_QWORD_TABLE_2_START IOMMU_MMIO_OFF_RSVD_REG
+#define IOMMU_MMIO_OFF_RSVD_REG 0x1ff8
+
+#define IOMMU_MMIO_OFF_CMD_BUF_HEAD_PTR 0x2000
+#define IOMMU_MMIO_OFF_CMD_BUF_TAIL_PTR 0x2008
+#define IOMMU_MMIO_OFF_EVT_LOG_HEAD_PTR 0x2010
+#define IOMMU_MMIO_OFF_EVT_LOG_TAIL_PTR 0x2018
+
+#define IOMMU_MMIO_OFF_STATUS 0x2020
+
+#define IOMMU_MMIO_OFF_PPR_LOG_HEAD_PTR 0x2030
+#define IOMMU_MMIO_OFF_PPR_LOG_TAIL_PTR 0x2038
+
+#define IOMMU_MMIO_OFF_GALOG_HEAD_PTR 0x2040
+#define IOMMU_MMIO_OFF_GALOG_TAIL_PTR 0x2048
+
+#define IOMMU_MMIO_OFF_PPR_LOG_B_HEAD_PTR 0x2050
+#define IOMMU_MMIO_OFF_PPR_LOG_B_TAIL_PTR 0x2058
+
+#define IOMMU_MMIO_OFF_EVT_LOG_B_HEAD_PTR 0x2070
+#define IOMMU_MMIO_OFF_EVT_LOG_B_TAIL_PTR 0x2078
+
+#define IOMMU_MMIO_OFF_PPR_LOG_AUTO_RESP 0x2080
+#define IOMMU_MMIO_OFF_PPR_LOG_OVERFLOW_EARLY 0x2088
+#define IOMMU_MMIO_OFF_PPR_LOG_B_OVERFLOW_EARLY 0x2090
+#define IOMMU_MMIO_OFF_QWORD_TABLE_2_END (IOMMU_MMIO_OFF_PPR_LOG_B_OVERFLOW_EARLY + 8)
+/** @} */
+
+/**
+ * @name MMIO register-access table offsets.
+ * Each table [first..last] (both inclusive) represents the range of registers
+ * covered by a distinct register-access table. This is done due to arbitrary large
+ * gaps in the MMIO register offsets themselves.
+ * @{
+ */
+#define IOMMU_MMIO_OFF_TABLE_0_FIRST 0x00
+#define IOMMU_MMIO_OFF_TABLE_0_LAST 0x258
+
+#define IOMMU_MMIO_OFF_TABLE_1_FIRST 0x1ff8
+#define IOMMU_MMIO_OFF_TABLE_1_LAST 0x2090
+/** @} */
+
+/**
+ * @name Commands.
+ * In accordance with the AMD spec.
+ * @{
+ */
+#define IOMMU_CMD_COMPLETION_WAIT 0x01
+#define IOMMU_CMD_INV_DEV_TAB_ENTRY 0x02
+#define IOMMU_CMD_INV_IOMMU_PAGES 0x03
+#define IOMMU_CMD_INV_IOTLB_PAGES 0x04
+#define IOMMU_CMD_INV_INTR_TABLE 0x05
+#define IOMMU_CMD_PREFETCH_IOMMU_PAGES 0x06
+#define IOMMU_CMD_COMPLETE_PPR_REQ 0x07
+#define IOMMU_CMD_INV_IOMMU_ALL 0x08
+/** @} */
+
+/**
+ * @name Event codes.
+ * In accordance with the AMD spec.
+ * @{
+ */
+#define IOMMU_EVT_ILLEGAL_DEV_TAB_ENTRY 0x01
+#define IOMMU_EVT_IO_PAGE_FAULT 0x02
+#define IOMMU_EVT_DEV_TAB_HW_ERROR 0x03
+#define IOMMU_EVT_PAGE_TAB_HW_ERROR 0x04
+#define IOMMU_EVT_ILLEGAL_CMD_ERROR 0x05
+#define IOMMU_EVT_COMMAND_HW_ERROR 0x06
+#define IOMMU_EVT_IOTLB_INV_TIMEOUT 0x07
+#define IOMMU_EVT_INVALID_DEV_REQ 0x08
+#define IOMMU_EVT_INVALID_PPR_REQ 0x09
+#define IOMMU_EVT_EVENT_COUNTER_ZERO 0x10
+#define IOMMU_EVT_GUEST_EVENT_FAULT 0x11
+/** @} */
+
+/**
+ * @name IOMMU Capability Header.
+ * In accordance with the AMD spec.
+ * @{
+ */
+/** CapId: Capability ID. */
+#define IOMMU_BF_CAPHDR_CAP_ID_SHIFT 0
+#define IOMMU_BF_CAPHDR_CAP_ID_MASK UINT32_C(0x000000ff)
+/** CapPtr: Capability Pointer. */
+#define IOMMU_BF_CAPHDR_CAP_PTR_SHIFT 8
+#define IOMMU_BF_CAPHDR_CAP_PTR_MASK UINT32_C(0x0000ff00)
+/** CapType: Capability Type. */
+#define IOMMU_BF_CAPHDR_CAP_TYPE_SHIFT 16
+#define IOMMU_BF_CAPHDR_CAP_TYPE_MASK UINT32_C(0x00070000)
+/** CapRev: Capability Revision. */
+#define IOMMU_BF_CAPHDR_CAP_REV_SHIFT 19
+#define IOMMU_BF_CAPHDR_CAP_REV_MASK UINT32_C(0x00f80000)
+/** IoTlbSup: IO TLB Support. */
+#define IOMMU_BF_CAPHDR_IOTLB_SUP_SHIFT 24
+#define IOMMU_BF_CAPHDR_IOTLB_SUP_MASK UINT32_C(0x01000000)
+/** HtTunnel: HyperTransport Tunnel translation support. */
+#define IOMMU_BF_CAPHDR_HT_TUNNEL_SHIFT 25
+#define IOMMU_BF_CAPHDR_HT_TUNNEL_MASK UINT32_C(0x02000000)
+/** NpCache: Not Present table entries Cached. */
+#define IOMMU_BF_CAPHDR_NP_CACHE_SHIFT 26
+#define IOMMU_BF_CAPHDR_NP_CACHE_MASK UINT32_C(0x04000000)
+/** EFRSup: Extended Feature Register (EFR) Supported. */
+#define IOMMU_BF_CAPHDR_EFR_SUP_SHIFT 27
+#define IOMMU_BF_CAPHDR_EFR_SUP_MASK UINT32_C(0x08000000)
+/** CapExt: Miscellaneous Information Register Supported . */
+#define IOMMU_BF_CAPHDR_CAP_EXT_SHIFT 28
+#define IOMMU_BF_CAPHDR_CAP_EXT_MASK UINT32_C(0x10000000)
+/** Bits 31:29 reserved. */
+#define IOMMU_BF_CAPHDR_RSVD_29_31_SHIFT 29
+#define IOMMU_BF_CAPHDR_RSVD_29_31_MASK UINT32_C(0xe0000000)
+RT_BF_ASSERT_COMPILE_CHECKS(IOMMU_BF_CAPHDR_, UINT32_C(0), UINT32_MAX,
+ (CAP_ID, CAP_PTR, CAP_TYPE, CAP_REV, IOTLB_SUP, HT_TUNNEL, NP_CACHE, EFR_SUP, CAP_EXT, RSVD_29_31));
+/** @} */
+
+/**
+ * @name IOMMU Base Address Low Register.
+ * In accordance with the AMD spec.
+ * @{
+ */
+/** Enable: Enables access to the address specified in the Base Address Register. */
+#define IOMMU_BF_BASEADDR_LO_ENABLE_SHIFT 0
+#define IOMMU_BF_BASEADDR_LO_ENABLE_MASK UINT32_C(0x00000001)
+/** Bits 13:1 reserved. */
+#define IOMMU_BF_BASEADDR_LO_RSVD_1_13_SHIFT 1
+#define IOMMU_BF_BASEADDR_LO_RSVD_1_13_MASK UINT32_C(0x00003ffe)
+/** Base Address[31:14]: Low Base address of IOMMU MMIO control registers. */
+#define IOMMU_BF_BASEADDR_LO_ADDR_SHIFT 14
+#define IOMMU_BF_BASEADDR_LO_ADDR_MASK UINT32_C(0xffffc000)
+RT_BF_ASSERT_COMPILE_CHECKS(IOMMU_BF_BASEADDR_LO_, UINT32_C(0), UINT32_MAX,
+ (ENABLE, RSVD_1_13, ADDR));
+/** @} */
+
+/**
+ * @name IOMMU Range Register.
+ * In accordance with the AMD spec.
+ * @{
+ */
+/** UnitID: HyperTransport Unit ID. */
+#define IOMMU_BF_RANGE_UNIT_ID_SHIFT 0
+#define IOMMU_BF_RANGE_UNIT_ID_MASK UINT32_C(0x0000001f)
+/** Bits 6:5 reserved. */
+#define IOMMU_BF_RANGE_RSVD_5_6_SHIFT 5
+#define IOMMU_BF_RANGE_RSVD_5_6_MASK UINT32_C(0x00000060)
+/** RngValid: Range valid. */
+#define IOMMU_BF_RANGE_VALID_SHIFT 7
+#define IOMMU_BF_RANGE_VALID_MASK UINT32_C(0x00000080)
+/** BusNumber: Device range bus number. */
+#define IOMMU_BF_RANGE_BUS_NUMBER_SHIFT 8
+#define IOMMU_BF_RANGE_BUS_NUMBER_MASK UINT32_C(0x0000ff00)
+/** First Device. */
+#define IOMMU_BF_RANGE_FIRST_DEVICE_SHIFT 16
+#define IOMMU_BF_RANGE_FIRST_DEVICE_MASK UINT32_C(0x00ff0000)
+/** Last Device. */
+#define IOMMU_BF_RANGE_LAST_DEVICE_SHIFT 24
+#define IOMMU_BF_RANGE_LAST_DEVICE_MASK UINT32_C(0xff000000)
+RT_BF_ASSERT_COMPILE_CHECKS(IOMMU_BF_RANGE_, UINT32_C(0), UINT32_MAX,
+ (UNIT_ID, RSVD_5_6, VALID, BUS_NUMBER, FIRST_DEVICE, LAST_DEVICE));
+/** @} */
+
+/**
+ * @name IOMMU Miscellaneous Information Register 0.
+ * In accordance with the AMD spec.
+ * @{
+ */
+/** MsiNum: MSI message number. */
+#define IOMMU_BF_MISCINFO_0_MSI_NUM_SHIFT 0
+#define IOMMU_BF_MISCINFO_0_MSI_NUM_MASK UINT32_C(0x0000001f)
+/** GvaSize: Guest Virtual Address Size. */
+#define IOMMU_BF_MISCINFO_0_GVA_SIZE_SHIFT 5
+#define IOMMU_BF_MISCINFO_0_GVA_SIZE_MASK UINT32_C(0x000000e0)
+/** PaSize: Physical Address Size. */
+#define IOMMU_BF_MISCINFO_0_PA_SIZE_SHIFT 8
+#define IOMMU_BF_MISCINFO_0_PA_SIZE_MASK UINT32_C(0x00007f00)
+/** VaSize: Virtual Address Size. */
+#define IOMMU_BF_MISCINFO_0_VA_SIZE_SHIFT 15
+#define IOMMU_BF_MISCINFO_0_VA_SIZE_MASK UINT32_C(0x003f8000)
+/** HtAtsResv: HyperTransport ATS Response Address range Reserved. */
+#define IOMMU_BF_MISCINFO_0_HT_ATS_RESV_SHIFT 22
+#define IOMMU_BF_MISCINFO_0_HT_ATS_RESV_MASK UINT32_C(0x00400000)
+/** Bits 26:23 reserved. */
+#define IOMMU_BF_MISCINFO_0_RSVD_23_26_SHIFT 23
+#define IOMMU_BF_MISCINFO_0_RSVD_23_26_MASK UINT32_C(0x07800000)
+/** MsiNumPPR: Peripheral Page Request MSI message number. */
+#define IOMMU_BF_MISCINFO_0_MSI_NUM_PPR_SHIFT 27
+#define IOMMU_BF_MISCINFO_0_MSI_NUM_PPR_MASK UINT32_C(0xf8000000)
+RT_BF_ASSERT_COMPILE_CHECKS(IOMMU_BF_MISCINFO_0_, UINT32_C(0), UINT32_MAX,
+ (MSI_NUM, GVA_SIZE, PA_SIZE, VA_SIZE, HT_ATS_RESV, RSVD_23_26, MSI_NUM_PPR));
+/** @} */
+
+/**
+ * @name IOMMU Miscellaneous Information Register 1.
+ * In accordance with the AMD spec.
+ * @{
+ */
+/** MsiNumGA: MSI message number for guest virtual-APIC log. */
+#define IOMMU_BF_MISCINFO_1_MSI_NUM_GA_SHIFT 0
+#define IOMMU_BF_MISCINFO_1_MSI_NUM_GA_MASK UINT32_C(0x0000001f)
+/** Bits 31:5 reserved. */
+#define IOMMU_BF_MISCINFO_1_RSVD_5_31_SHIFT 5
+#define IOMMU_BF_MISCINFO_1_RSVD_5_31_MASK UINT32_C(0xffffffe0)
+RT_BF_ASSERT_COMPILE_CHECKS(IOMMU_BF_MISCINFO_1_, UINT32_C(0), UINT32_MAX,
+ (MSI_NUM_GA, RSVD_5_31));
+/** @} */
+
+/**
+ * @name MSI Capability Header Register.
+ * In accordance with the AMD spec.
+ * @{
+ */
+/** MsiCapId: Capability ID. */
+#define IOMMU_BF_MSI_CAP_HDR_CAP_ID_SHIFT 0
+#define IOMMU_BF_MSI_CAP_HDR_CAP_ID_MASK UINT32_C(0x000000ff)
+/** MsiCapPtr: Pointer (PCI config offset) to the next capability. */
+#define IOMMU_BF_MSI_CAP_HDR_CAP_PTR_SHIFT 8
+#define IOMMU_BF_MSI_CAP_HDR_CAP_PTR_MASK UINT32_C(0x0000ff00)
+/** MsiEn: Message Signal Interrupt enable. */
+#define IOMMU_BF_MSI_CAP_HDR_EN_SHIFT 16
+#define IOMMU_BF_MSI_CAP_HDR_EN_MASK UINT32_C(0x00010000)
+/** MsiMultMessCap: MSI Multi-Message Capability. */
+#define IOMMU_BF_MSI_CAP_HDR_MULTMESS_CAP_SHIFT 17
+#define IOMMU_BF_MSI_CAP_HDR_MULTMESS_CAP_MASK UINT32_C(0x000e0000)
+/** MsiMultMessEn: MSI Mult-Message Enable. */
+#define IOMMU_BF_MSI_CAP_HDR_MULTMESS_EN_SHIFT 20
+#define IOMMU_BF_MSI_CAP_HDR_MULTMESS_EN_MASK UINT32_C(0x00700000)
+/** Msi64BitEn: MSI 64-bit Enabled. */
+#define IOMMU_BF_MSI_CAP_HDR_64BIT_EN_SHIFT 23
+#define IOMMU_BF_MSI_CAP_HDR_64BIT_EN_MASK UINT32_C(0x00800000)
+/** Bits 31:24 reserved. */
+#define IOMMU_BF_MSI_CAP_HDR_RSVD_24_31_SHIFT 24
+#define IOMMU_BF_MSI_CAP_HDR_RSVD_24_31_MASK UINT32_C(0xff000000)
+RT_BF_ASSERT_COMPILE_CHECKS(IOMMU_BF_MSI_CAP_HDR_, UINT32_C(0), UINT32_MAX,
+ (CAP_ID, CAP_PTR, EN, MULTMESS_CAP, MULTMESS_EN, 64BIT_EN, RSVD_24_31));
+/** @} */
+
+/**
+ * @name MSI Mapping Capability Header Register.
+ * In accordance with the AMD spec.
+ * @{
+ */
+/** MsiMapCapId: Capability ID. */
+#define IOMMU_BF_MSI_MAP_CAPHDR_CAP_ID_SHIFT 0
+#define IOMMU_BF_MSI_MAP_CAPHDR_CAP_ID_MASK UINT32_C(0x000000ff)
+/** MsiMapCapPtr: Pointer (PCI config offset) to the next capability. */
+#define IOMMU_BF_MSI_MAP_CAPHDR_CAP_PTR_SHIFT 8
+#define IOMMU_BF_MSI_MAP_CAPHDR_CAP_PTR_MASK UINT32_C(0x0000ff00)
+/** MsiMapEn: MSI mapping capability enable. */
+#define IOMMU_BF_MSI_MAP_CAPHDR_EN_SHIFT 16
+#define IOMMU_BF_MSI_MAP_CAPHDR_EN_MASK UINT32_C(0x00010000)
+/** MsiMapFixd: MSI interrupt mapping range is not programmable. */
+#define IOMMU_BF_MSI_MAP_CAPHDR_FIXED_SHIFT 17
+#define IOMMU_BF_MSI_MAP_CAPHDR_FIXED_MASK UINT32_C(0x00020000)
+/** Bits 18:28 reserved. */
+#define IOMMU_BF_MSI_MAP_CAPHDR_RSVD_18_28_SHIFT 18
+#define IOMMU_BF_MSI_MAP_CAPHDR_RSVD_18_28_MASK UINT32_C(0x07fc0000)
+/** MsiMapCapType: MSI mapping capability. */
+#define IOMMU_BF_MSI_MAP_CAPHDR_CAP_TYPE_SHIFT 27
+#define IOMMU_BF_MSI_MAP_CAPHDR_CAP_TYPE_MASK UINT32_C(0xf8000000)
+RT_BF_ASSERT_COMPILE_CHECKS(IOMMU_BF_MSI_MAP_CAPHDR_, UINT32_C(0), UINT32_MAX,
+ (CAP_ID, CAP_PTR, EN, FIXED, RSVD_18_28, CAP_TYPE));
+/** @} */
+
+/**
+ * @name IOMMU Status Register Bits.
+ * In accordance with the AMD spec.
+ * @{
+ */
+/** EventOverflow: Event log overflow. */
+#define IOMMU_STATUS_EVT_LOG_OVERFLOW RT_BIT_64(0)
+/** EventLogInt: Event log interrupt. */
+#define IOMMU_STATUS_EVT_LOG_INTR RT_BIT_64(1)
+/** ComWaitInt: Completion wait interrupt. */
+#define IOMMU_STATUS_COMPLETION_WAIT_INTR RT_BIT_64(2)
+/** EventLogRun: Event log is running. */
+#define IOMMU_STATUS_EVT_LOG_RUNNING RT_BIT_64(3)
+/** CmdBufRun: Command buffer is running. */
+#define IOMMU_STATUS_CMD_BUF_RUNNING RT_BIT_64(4)
+/** PprOverflow: Peripheral page request log overflow. */
+#define IOMMU_STATUS_PPR_LOG_OVERFLOW RT_BIT_64(5)
+/** PprInt: Peripheral page request log interrupt. */
+#define IOMMU_STATUS_PPR_LOG_INTR RT_BIT_64(6)
+/** PprLogRun: Peripheral page request log is running. */
+#define IOMMU_STATUS_PPR_LOG_RUN RT_BIT_64(7)
+/** GALogRun: Guest virtual-APIC log is running. */
+#define IOMMU_STATUS_GA_LOG_RUN RT_BIT_64(8)
+/** GALOverflow: Guest virtual-APIC log overflow. */
+#define IOMMU_STATUS_GA_LOG_OVERFLOW RT_BIT_64(9)
+/** GAInt: Guest virtual-APIC log interrupt. */
+#define IOMMU_STATUS_GA_LOG_INTR RT_BIT_64(10)
+/** PprOvrflwB: PPR Log B overflow. */
+#define IOMMU_STATUS_PPR_LOG_B_OVERFLOW RT_BIT_64(11)
+/** PprLogActive: PPR Log B is active. */
+#define IOMMU_STATUS_PPR_LOG_B_ACTIVE RT_BIT_64(12)
+/** EvtOvrflwB: Event log B overflow. */
+#define IOMMU_STATUS_EVT_LOG_B_OVERFLOW RT_BIT_64(15)
+/** EventLogActive: Event log B active. */
+#define IOMMU_STATUS_EVT_LOG_B_ACTIVE RT_BIT_64(16)
+/** PprOvrflwEarlyB: PPR log B overflow early warning. */
+#define IOMMU_STATUS_PPR_LOG_B_OVERFLOW_EARLY RT_BIT_64(17)
+/** PprOverflowEarly: PPR log overflow early warning. */
+#define IOMMU_STATUS_PPR_LOG_OVERFLOW_EARLY RT_BIT_64(18)
+/** @} */
+
+/** @name IOMMU_IO_PERM_XXX: IOMMU I/O access permissions bits.
+ * In accordance with the AMD spec.
+ *
+ * These values match the shifted values of the IR and IW field of the DTE and the
+ * PTE, PDE of the I/O page tables.
+ *
+ * @{ */
+#define IOMMU_IO_PERM_NONE (0)
+#define IOMMU_IO_PERM_READ RT_BIT_64(0)
+#define IOMMU_IO_PERM_WRITE RT_BIT_64(1)
+#define IOMMU_IO_PERM_READ_WRITE (IOMMU_IO_PERM_READ | IOMMU_IO_PERM_WRITE)
+#define IOMMU_IO_PERM_SHIFT 61
+#define IOMMU_IO_PERM_MASK 0x3
+/** @} */
+
+/** @name SYSMGT_TYPE_XXX: System Management Message Enable Types.
+ * In accordance with the AMD spec.
+ * @{ */
+#define SYSMGTTYPE_DMA_DENY (0)
+#define SYSMGTTYPE_MSG_ALL_ALLOW (1)
+#define SYSMGTTYPE_MSG_INT_ALLOW (2)
+#define SYSMGTTYPE_DMA_ALLOW (3)
+/** @} */
+
+/** @name IOMMU_INTR_CTRL_XX: DTE::IntCtl field values.
+ * These are control bits for handling fixed and arbitrated interrupts.
+ * In accordance with the AMD spec.
+ * @{ */
+#define IOMMU_INTR_CTRL_TARGET_ABORT (0)
+#define IOMMU_INTR_CTRL_FWD_UNMAPPED (1)
+#define IOMMU_INTR_CTRL_REMAP (2)
+#define IOMMU_INTR_CTRL_RSVD (3)
+/** @} */
+
+/** Gets the device table length (in bytes) given the device table pointer. */
+#define IOMMU_GET_DEV_TAB_LEN(a_pDevTab) (((a_pDevTab)->n.u9Size + 1) << X86_PAGE_4K_SHIFT)
+
+/**
+ * The Device ID.
+ * In accordance with VirtualBox's PCI configuration.
+ */
+typedef union
+{
+ struct
+ {
+ RT_GCC_EXTENSION uint16_t u3Function : 3; /**< Bits 2:0 - Function. */
+ RT_GCC_EXTENSION uint16_t u9Device : 9; /**< Bits 11:3 - Device. */
+ RT_GCC_EXTENSION uint16_t u4Bus : 4; /**< Bits 15:12 - Bus. */
+ } n;
+ /** The unsigned integer view. */
+ uint16_t u;
+} DEVICE_ID_T;
+AssertCompileSize(DEVICE_ID_T, 2);
+
+/**
+ * Device Table Entry (DTE).
+ * In accordance with the AMD spec.
+ */
+typedef union
+{
+ struct
+ {
+ RT_GCC_EXTENSION uint64_t u1Valid : 1; /**< Bit 0 - V: Valid. */
+ RT_GCC_EXTENSION uint64_t u1TranslationValid : 1; /**< Bit 1 - TV: Translation information Valid. */
+ RT_GCC_EXTENSION uint64_t u5Rsvd0 : 5; /**< Bits 6:2 - Reserved. */
+ RT_GCC_EXTENSION uint64_t u2Had : 2; /**< Bits 8:7 - HAD: Host Access Dirty. */
+ RT_GCC_EXTENSION uint64_t u3Mode : 3; /**< Bits 11:9 - Mode: Paging mode. */
+ RT_GCC_EXTENSION uint64_t u40PageTableRootPtrLo : 40; /**< Bits 51:12 - Page Table Root Pointer. */
+ RT_GCC_EXTENSION uint64_t u1Ppr : 1; /**< Bit 52 - PPR: Peripheral Page Request. */
+ RT_GCC_EXTENSION uint64_t u1GstPprRespPasid : 1; /**< Bit 53 - GRPR: Guest PPR Response with PASID. */
+ RT_GCC_EXTENSION uint64_t u1GstIoValid : 1; /**< Bit 54 - GIoV: Guest I/O Protection Valid. */
+ RT_GCC_EXTENSION uint64_t u1GstTranslateValid : 1; /**< Bit 55 - GV: Guest translation Valid. */
+ RT_GCC_EXTENSION uint64_t u2GstMode : 2; /**< Bits 57:56 - GLX: Guest Paging mode levels. */
+ RT_GCC_EXTENSION uint64_t u3GstCr3TableRootPtrLo : 3; /**< Bits 60:58 - GCR3 TRP: Guest CR3 Table Root Ptr (Lo). */
+ RT_GCC_EXTENSION uint64_t u1IoRead : 1; /**< Bit 61 - IR: I/O Read permission. */
+ RT_GCC_EXTENSION uint64_t u1IoWrite : 1; /**< Bit 62 - IW: I/O Write permission. */
+ RT_GCC_EXTENSION uint64_t u1Rsvd0 : 1; /**< Bit 63 - Reserved. */
+ RT_GCC_EXTENSION uint64_t u16DomainId : 16; /**< Bits 79:64 - Domain ID. */
+ RT_GCC_EXTENSION uint64_t u16GstCr3TableRootPtrMid : 16; /**< Bits 95:80 - GCR3 TRP: Guest CR3 Table Root Ptr (Mid). */
+ RT_GCC_EXTENSION uint64_t u1IoTlbEnable : 1; /**< Bit 96 - I: IOTLB Enable (remote). */
+ RT_GCC_EXTENSION uint64_t u1SuppressPfEvents : 1; /**< Bit 97 - SE: Suppress Page-fault events. */
+ RT_GCC_EXTENSION uint64_t u1SuppressAllPfEvents : 1; /**< Bit 98 - SA: Suppress All Page-fault events. */
+ RT_GCC_EXTENSION uint64_t u2IoCtl : 2; /**< Bits 100:99 - IoCtl: Port I/O Control. */
+ RT_GCC_EXTENSION uint64_t u1Cache : 1; /**< Bit 101 - Cache: IOTLB Cache Hint. */
+ RT_GCC_EXTENSION uint64_t u1SnoopDisable : 1; /**< Bit 102 - SD: Snoop Disable. */
+ RT_GCC_EXTENSION uint64_t u1AllowExclusion : 1; /**< Bit 103 - EX: Allow Exclusion. */
+ RT_GCC_EXTENSION uint64_t u2SysMgt : 2; /**< Bits 105:104 - SysMgt: System Management message enable. */
+ RT_GCC_EXTENSION uint64_t u1Rsvd1 : 1; /**< Bit 106 - Reserved. */
+ RT_GCC_EXTENSION uint64_t u21GstCr3TableRootPtrHi : 21; /**< Bits 127:107 - GCR3 TRP: Guest CR3 Table Root Ptr (Hi). */
+ RT_GCC_EXTENSION uint64_t u1IntrMapValid : 1; /**< Bit 128 - IV: Interrupt map Valid. */
+ RT_GCC_EXTENSION uint64_t u4IntrTableLength : 4; /**< Bits 132:129 - IntTabLen: Interrupt Table Length. */
+ RT_GCC_EXTENSION uint64_t u1IgnoreUnmappedIntrs : 1; /**< Bits 133 - IG: Ignore unmapped interrupts. */
+ RT_GCC_EXTENSION uint64_t u46IntrTableRootPtr : 46; /**< Bits 179:134 - Interrupt Root Table Pointer. */
+ RT_GCC_EXTENSION uint64_t u4Rsvd0 : 4; /**< Bits 183:180 - Reserved. */
+ RT_GCC_EXTENSION uint64_t u1InitPassthru : 1; /**< Bits 184 - INIT Pass-through. */
+ RT_GCC_EXTENSION uint64_t u1ExtIntPassthru : 1; /**< Bits 185 - External Interrupt Pass-through. */
+ RT_GCC_EXTENSION uint64_t u1NmiPassthru : 1; /**< Bits 186 - NMI Pass-through. */
+ RT_GCC_EXTENSION uint64_t u1Rsvd2 : 1; /**< Bits 187 - Reserved. */
+ RT_GCC_EXTENSION uint64_t u2IntrCtrl : 2; /**< Bits 189:188 - IntCtl: Interrupt Control. */
+ RT_GCC_EXTENSION uint64_t u1Lint0Passthru : 1; /**< Bit 190 - Lint0Pass: LINT0 Pass-through. */
+ RT_GCC_EXTENSION uint64_t u1Lint1Passthru : 1; /**< Bit 191 - Lint1Pass: LINT1 Pass-through. */
+ RT_GCC_EXTENSION uint64_t u32Rsvd0 : 32; /**< Bits 223:192 - Reserved. */
+ RT_GCC_EXTENSION uint64_t u22Rsvd0 : 22; /**< Bits 245:224 - Reserved. */
+ RT_GCC_EXTENSION uint64_t u1AttrOverride : 1; /**< Bit 246 - AttrV: Attribute Override. */
+ RT_GCC_EXTENSION uint64_t u1Mode0FC : 1; /**< Bit 247 - Mode0FC. */
+ RT_GCC_EXTENSION uint64_t u8SnoopAttr : 8; /**< Bits 255:248 - Snoop Attribute. */
+ } n;
+ /** The 32-bit unsigned integer view. */
+ uint32_t au32[8];
+ /** The 64-bit unsigned integer view. */
+ uint64_t au64[4];
+} DTE_T;
+AssertCompileSize(DTE_T, 32);
+/** Pointer to a device table entry. */
+typedef DTE_T *PDTE_T;
+/** Pointer to a const device table entry. */
+typedef DTE_T const *PCDTE_T;
+
+/** Mask of valid bits for EPHSUP (Enhanced Peripheral Page Request Handling
+ * Support) feature (bits 52:53). */
+#define IOMMU_DTE_QWORD_0_FEAT_EPHSUP_MASK UINT64_C(0x0030000000000000)
+
+/** Mask of valid bits for GTSup (Guest Translation Support) feature (bits 55:60,
+ * bits 80:95). */
+#define IOMMU_DTE_QWORD_0_FEAT_GTSUP_MASK UINT64_C(0x1f80000000000000)
+#define IOMMU_DTE_QWORD_1_FEAT_GTSUP_MASK UINT64_C(0x00000000ffff0000)
+
+/** Mask of valid bits for GIoSup (Guest I/O Protection Support) feature (bit 54). */
+#define IOMMU_DTE_QWORD_0_FEAT_GIOSUP_MASK UINT64_C(0x0040000000000000)
+
+/** Mask of valid DTE feature bits. */
+#define IOMMU_DTE_QWORD_0_FEAT_MASK ( IOMMU_DTE_QWORD_0_FEAT_EPHSUP_MASK \
+ | IOMMU_DTE_QWORD_0_FEAT_GTSUP_MASK \
+ | IOMMU_DTE_QWORD_0_FEAT_GIOSUP_MASK)
+#define IOMMU_DTE_QWORD_1_FEAT_MASK IOMMU_DTE_QWORD_0_FEAT_GIOSUP_MASK
+
+/** Mask of all valid DTE bits (including all feature bits). */
+#define IOMMU_DTE_QWORD_0_VALID_MASK UINT64_C(0x7fffffffffffff83)
+#define IOMMU_DTE_QWORD_1_VALID_MASK UINT64_C(0xfffffbffffffffff)
+#define IOMMU_DTE_QWORD_2_VALID_MASK UINT64_C(0xff0fffffffffffff)
+#define IOMMU_DTE_QWORD_3_VALID_MASK UINT64_C(0xffc0000000000000)
+
+/** Mask of the interrupt table root pointer. */
+#define IOMMU_DTE_IRTE_ROOT_PTR_MASK UINT64_C(0x000fffffffffffc0)
+/** Number of bits to shift to get the interrupt root table pointer at
+ qword 2 (qword 0 being the first one) - 128-byte aligned. */
+#define IOMMU_DTE_IRTE_ROOT_PTR_SHIFT 6
+
+/** Maximum encoded IRTE length (exclusive). */
+#define IOMMU_DTE_INTR_TAB_LEN_MAX 12
+/** Gets the interrupt table entries (in bytes) given the DTE pointer. */
+#define IOMMU_DTE_GET_INTR_TAB_ENTRIES(a_pDte) (UINT64_C(1) << (a_pDte)->n.u4IntrTableLength)
+/** Gets the interrupt table length (in bytes) given the DTE pointer. */
+#define IOMMU_DTE_GET_INTR_TAB_LEN(a_pDte) (IOMMU_DTE_GET_INTR_TAB_ENTRIES(a_pDte) * sizeof(IRTE_T))
+/** Mask of interrupt control bits. */
+#define IOMMU_DTE_INTR_CTRL_MASK 0x3
+/** Gets the interrupt control bits from the DTE. */
+#define IOMMU_DTE_GET_INTR_CTRL(a_pDte) (((a_pDte)->au64[2] >> 60) & IOMMU_DTE_INTR_CTRL_MASK)
+/** Gets the ignore unmapped interrupt bit from DTE. */
+#define IOMMU_DTE_GET_IG(a_pDte) (((a_pDte)->au64[2] >> 5) & 0x1)
+
+/**
+ * I/O Page Translation Entry.
+ * In accordance with the AMD spec.
+ */
+typedef union
+{
+ struct
+ {
+ RT_GCC_EXTENSION uint64_t u1Present : 1; /**< Bit 0 - PR: Present. */
+ RT_GCC_EXTENSION uint64_t u4Ign0 : 4; /**< Bits 4:1 - Ignored. */
+ RT_GCC_EXTENSION uint64_t u1Accessed : 1; /**< Bit 5 - A: Accessed. */
+ RT_GCC_EXTENSION uint64_t u1Dirty : 1; /**< Bit 6 - D: Dirty. */
+ RT_GCC_EXTENSION uint64_t u2Ign0 : 2; /**< Bits 8:7 - Ignored. */
+ RT_GCC_EXTENSION uint64_t u3NextLevel : 3; /**< Bits 11:9 - Next Level: Next page translation level. */
+ RT_GCC_EXTENSION uint64_t u40PageAddr : 40; /**< Bits 51:12 - Page address. */
+ RT_GCC_EXTENSION uint64_t u7Rsvd0 : 7; /**< Bits 58:52 - Reserved. */
+ RT_GCC_EXTENSION uint64_t u1UntranslatedAccess : 1; /**< Bit 59 - U: Untranslated Access Only. */
+ RT_GCC_EXTENSION uint64_t u1ForceCoherent : 1; /**< Bit 60 - FC: Force Coherent. */
+ RT_GCC_EXTENSION uint64_t u1IoRead : 1; /**< Bit 61 - IR: I/O Read permission. */
+ RT_GCC_EXTENSION uint64_t u1IoWrite : 1; /**< Bit 62 - IW: I/O Wead permission. */
+ RT_GCC_EXTENSION uint64_t u1Ign0 : 1; /**< Bit 63 - Ignored. */
+ } n;
+ /** The 64-bit unsigned integer view. */
+ uint64_t u64;
+} IOPTE_T;
+AssertCompileSize(IOPTE_T, 8);
+
+/**
+ * I/O Page Directory Entry.
+ * In accordance with the AMD spec.
+ */
+typedef union
+{
+ struct
+ {
+ RT_GCC_EXTENSION uint64_t u1Present : 1; /**< Bit 0 - PR: Present. */
+ RT_GCC_EXTENSION uint64_t u4Ign0 : 4; /**< Bits 4:1 - Ignored. */
+ RT_GCC_EXTENSION uint64_t u1Accessed : 1; /**< Bit 5 - A: Accessed. */
+ RT_GCC_EXTENSION uint64_t u3Ign0 : 3; /**< Bits 8:6 - Ignored. */
+ RT_GCC_EXTENSION uint64_t u3NextLevel : 3; /**< Bits 11:9 - Next Level: Next page translation level. */
+ RT_GCC_EXTENSION uint64_t u40PageAddr : 40; /**< Bits 51:12 - Page address (Next Table Address). */
+ RT_GCC_EXTENSION uint64_t u9Rsvd0 : 9; /**< Bits 60:52 - Reserved. */
+ RT_GCC_EXTENSION uint64_t u1IoRead : 1; /**< Bit 61 - IR: I/O Read permission. */
+ RT_GCC_EXTENSION uint64_t u1IoWrite : 1; /**< Bit 62 - IW: I/O Wead permission. */
+ RT_GCC_EXTENSION uint64_t u1Ign0 : 1; /**< Bit 63 - Ignored. */
+ } n;
+ /** The 64-bit unsigned integer view. */
+ uint64_t u64;
+} IOPDE_T;
+AssertCompileSize(IOPDE_T, 8);
+
+/**
+ * I/O Page Table Entity.
+ * In accordance with the AMD spec.
+ *
+ * This a common subset of an DTE.au64[0], PTE and PDE.
+ * Named as an "entity" to avoid confusing it with PTE.
+ */
+typedef union
+{
+ struct
+ {
+ RT_GCC_EXTENSION uint64_t u1Present : 1; /**< Bit 0 - PR: Present. */
+ RT_GCC_EXTENSION uint64_t u8Ign0 : 8; /**< Bits 8:1 - Ignored. */
+ RT_GCC_EXTENSION uint64_t u3NextLevel : 3; /**< Bits 11:9 - Mode / Next Level: Next page translation level. */
+ RT_GCC_EXTENSION uint64_t u40Addr : 40; /**< Bits 51:12 - Page address. */
+ RT_GCC_EXTENSION uint64_t u9Ign0 : 9; /**< Bits 60:52 - Ignored. */
+ RT_GCC_EXTENSION uint64_t u1IoRead : 1; /**< Bit 61 - IR: I/O Read permission. */
+ RT_GCC_EXTENSION uint64_t u1IoWrite : 1; /**< Bit 62 - IW: I/O Wead permission. */
+ RT_GCC_EXTENSION uint64_t u1Ign0 : 1; /**< Bit 63 - Ignored. */
+ } n;
+ /** The 64-bit unsigned integer view. */
+ uint64_t u64;
+} IOPTENTITY_T;
+AssertCompileSize(IOPTENTITY_T, 8);
+AssertCompile(sizeof(IOPTENTITY_T) == sizeof(IOPTE_T));
+AssertCompile(sizeof(IOPTENTITY_T) == sizeof(IOPDE_T));
+/** Pointer to an IOPT_ENTITY_T struct. */
+typedef IOPTENTITY_T *PIOPTENTITY_T;
+/** Pointer to a const IOPT_ENTITY_T struct. */
+typedef IOPTENTITY_T const *PCIOPTENTITY_T;
+/** Mask of the address field. */
+#define IOMMU_PTENTITY_ADDR_MASK UINT64_C(0x000ffffffffff000)
+/** Reserved bits in the PDE (bits 60:52). */
+#define IOMMU_PDE_RSVD_MASK UINT64_C(0x1ff0000000000000)
+/** Reserved bits in the PTE (bits 58:52 - U, FC bits not reserved). */
+#define IOMMU_PTE_RSVD_MASK UINT64_C(0x07f0000000000000)
+
+/**
+ * Interrupt Remapping Table Entry (IRTE) - Basic Format.
+ * In accordance with the AMD spec.
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t u1RemapEnable : 1; /**< Bit 0 - RemapEn: Remap Enable. */
+ uint32_t u1SuppressIoPf : 1; /**< Bit 1 - SupIOPF: Suppress I/O Page Fault. */
+ uint32_t u3IntrType : 3; /**< Bits 4:2 - IntType: Interrupt Type. */
+ uint32_t u1ReqEoi : 1; /**< Bit 5 - RqEoi: Request EOI. */
+ uint32_t u1DestMode : 1; /**< Bit 6 - DM: Destination Mode. */
+ uint32_t u1GuestMode : 1; /**< Bit 7 - GuestMode. */
+ uint32_t u8Dest : 8; /**< Bits 15:8 - Destination. */
+ uint32_t u8Vector : 8; /**< Bits 23:16 - Vector. */
+ uint32_t u8Rsvd0 : 8; /**< Bits 31:24 - Reserved. */
+ } n;
+ /** The 32-bit unsigned integer view. */
+ uint32_t u32;
+} IRTE_T;
+AssertCompileSize(IRTE_T, 4);
+/** Pointer to an IRTE_T struct. */
+typedef IRTE_T *PIRTE_T;
+/** Pointer to a const IRTE_T struct. */
+typedef IRTE_T const *PCIRTE_T;
+
+/** The IRTE offset corresponds directly to bits 10:0 of the originating MSI
+ * interrupt message. See AMD IOMMU spec. 2.2.5 "Interrupt Remapping Tables". */
+#define IOMMU_MSI_DATA_IRTE_OFFSET_MASK UINT32_C(0x000007ff)
+/** Gets the IRTE offset from the originating MSI interrupt message. */
+#define IOMMU_GET_IRTE_OFF(a_u32MsiData) (((a_u32MsiData) & IOMMU_MSI_DATA_IRTE_OFFSET_MASK) * sizeof(IRTE_T))
+
+/**
+ * Interrupt Remapping Table Entry (IRTE) - Guest Virtual APIC Enabled.
+ * In accordance with the AMD spec.
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t u1RemapEnable : 1; /**< Bit 0 - RemapEn: Remap Enable. */
+ uint32_t u1SuppressIoPf : 1; /**< Bit 1 - SupIOPF: Suppress I/O Page Fault. */
+ uint32_t u1GALogIntr : 1; /**< Bit 2 - GALogIntr: Guest APIC Log Interrupt. */
+ uint32_t u3Rsvd : 3; /**< Bits 5:3 - Reserved. */
+ uint32_t u1IsRunning : 1; /**< Bit 6 - IsRun: Hint whether the guest is running. */
+ uint32_t u1GuestMode : 1; /**< Bit 7 - GuestMode. */
+ uint32_t u8Dest : 8; /**< Bits 15:8 - Destination. */
+ uint32_t u8Rsvd0 : 8; /**< Bits 31:16 - Reserved. */
+ uint32_t u32GATag : 32; /**< Bits 63:31 - GATag: Tag used when writing to GA log. */
+ uint32_t u8Vector : 8; /**< Bits 71:64 - Vector: Interrupt vector. */
+ uint32_t u4Reserved : 4; /**< Bits 75:72 - Reserved or ignored depending on RemapEn. */
+ uint32_t u20GATableRootPtrLo : 20; /**< Bits 95:76 - Bits [31:12] of Guest vAPIC Table Root Pointer. */
+ uint32_t u20GATableRootPtrHi : 20; /**< Bits 115:76 - Bits [51:32] of Guest vAPIC Table Root Pointer. */
+ uint32_t u12Rsvd : 12; /**< Bits 127:116 - Reserved. */
+ } n;
+ /** The 64-bit unsigned integer view. */
+ uint64_t u64[2];
+} IRTE_GVA_T;
+AssertCompileSize(IRTE_GVA_T, 16);
+/** Pointer to an IRTE_GVA_T struct. */
+typedef IRTE_GVA_T *PIRTE_GVA_T;
+/** Pointer to a const IRTE_GVA_T struct. */
+typedef IRTE_GVA_T const *PCIRTE_GVA_T;
+
+/**
+ * Command: Generic Command Buffer Entry.
+ * In accordance with the AMD spec.
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t u32Operand1Lo; /**< Bits 31:0 - Operand 1 (Lo). */
+ uint32_t u28Operand1Hi : 28; /**< Bits 59:32 - Operand 1 (Hi). */
+ uint32_t u4Opcode : 4; /**< Bits 63:60 - Op Code. */
+ uint64_t u64Operand2; /**< Bits 127:64 - Operand 2. */
+ } n;
+ /** The 64-bit unsigned integer view. */
+ uint64_t au64[2];
+} CMD_GENERIC_T;
+AssertCompileSize(CMD_GENERIC_T, 16);
+/** Pointer to a generic command buffer entry. */
+typedef CMD_GENERIC_T *PCMD_GENERIC_T;
+/** Pointer to a const generic command buffer entry. */
+typedef CMD_GENERIC_T const *PCCMD_GENERIC_T;
+
+/** Number of bits to shift the byte offset of a command in the command buffer to
+ * get its index. */
+#define IOMMU_CMD_GENERIC_SHIFT 4
+
+/**
+ * Command: COMPLETION_WAIT.
+ * In accordance with the AMD spec.
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t u1Store : 1; /**< Bit 0 - S: Completion Store. */
+ uint32_t u1Interrupt : 1; /**< Bit 1 - I: Completion Interrupt. */
+ uint32_t u1Flush : 1; /**< Bit 2 - F: Flush Queue. */
+ uint32_t u29StoreAddrLo : 29; /**< Bits 31:3 - Store Address (Lo). */
+ uint32_t u20StoreAddrHi : 20; /**< Bits 51:32 - Store Address (Hi). */
+ uint32_t u8Rsvd0 : 8; /**< Bits 59:52 - Reserved. */
+ uint32_t u4OpCode : 4; /**< Bits 63:60 - OpCode (Command). */
+ uint64_t u64StoreData; /**< Bits 127:64 - Store Data. */
+ } n;
+ /** The 64-bit unsigned integer view. */
+ uint64_t au64[2];
+} CMD_COMWAIT_T;
+AssertCompileSize(CMD_COMWAIT_T, 16);
+/** Pointer to a completion wait command. */
+typedef CMD_COMWAIT_T *PCMD_COMWAIT_T;
+/** Pointer to a const completion wait command. */
+typedef CMD_COMWAIT_T const *PCCMD_COMWAIT_T;
+#define IOMMU_CMD_COM_WAIT_QWORD_0_VALID_MASK UINT64_C(0xf00fffffffffffff)
+
+/**
+ * Command: INVALIDATE_DEVTAB_ENTRY.
+ * In accordance with the AMD spec.
+ */
+typedef union
+{
+ struct
+ {
+ uint16_t u16DevId; /**< Bits 15:0 - Device ID. */
+ uint16_t u16Rsvd0; /**< Bits 31:16 - Reserved. */
+ uint32_t u28Rsvd0 : 28; /**< Bits 59:32 - Reserved. */
+ uint32_t u4OpCode : 4; /**< Bits 63:60 - Op Code (Command). */
+ uint64_t u64Rsvd0; /**< Bits 127:64 - Reserved. */
+ } n;
+ /** The 64-bit unsigned integer view. */
+ uint64_t au64[2];
+} CMD_INV_DTE_T;
+AssertCompileSize(CMD_INV_DTE_T, 16);
+/** Pointer to a invalidate DTE command. */
+typedef CMD_INV_DTE_T *PCMD_INV_DTE_T;
+/** Pointer to a const invalidate DTE command. */
+typedef CMD_INV_DTE_T const *PCCMD_INV_DTE_T;
+#define IOMMU_CMD_INV_DTE_QWORD_0_VALID_MASK UINT64_C(0xf00000000000ffff)
+#define IOMMU_CMD_INV_DTE_QWORD_1_VALID_MASK UINT64_C(0x0000000000000000)
+
+/**
+ * Command: INVALIDATE_IOMMU_PAGES.
+ * In accordance with the AMD spec.
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t u20Pasid : 20; /**< Bits 19:0 - PASID: Process Address-Space ID. */
+ uint32_t u12Rsvd0 : 12; /**< Bits 31:20 - Reserved. */
+ uint32_t u16DomainId : 16; /**< Bits 47:32 - Domain ID. */
+ uint32_t u12Rsvd1 : 12; /**< Bits 59:48 - Reserved. */
+ uint32_t u4OpCode : 4; /**< Bits 63:60 - Op Code (Command). */
+ uint32_t u1Size : 1; /**< Bit 64 - S: Size. */
+ uint32_t u1PageDirEntries : 1; /**< Bit 65 - PDE: Page Directory Entries. */
+ uint32_t u1GuestOrNested : 1; /**< Bit 66 - GN: Guest (GPA) or Nested (GVA). */
+ uint32_t u9Rsvd0 : 9; /**< Bits 75:67 - Reserved. */
+ uint32_t u20AddrLo : 20; /**< Bits 95:76 - Address (Lo). */
+ uint32_t u32AddrHi; /**< Bits 127:96 - Address (Hi). */
+ } n;
+ /** The 64-bit unsigned integer view. */
+ uint64_t au64[2];
+} CMD_INV_IOMMU_PAGES_T;
+AssertCompileSize(CMD_INV_IOMMU_PAGES_T, 16);
+/** Pointer to a invalidate iommu pages command. */
+typedef CMD_INV_IOMMU_PAGES_T *PCMD_INV_IOMMU_PAGES_T;
+/** Pointer to a const invalidate iommu pages command. */
+typedef CMD_INV_IOMMU_PAGES_T const *PCCMD_INV_IOMMU_PAGES_T;
+#define IOMMU_CMD_INV_IOMMU_PAGES_QWORD_0_VALID_MASK UINT64_C(0xf000ffff000fffff)
+#define IOMMU_CMD_INV_IOMMU_PAGES_QWORD_1_VALID_MASK UINT64_C(0xfffffffffffff007)
+
+/**
+ * Command: INVALIDATE_IOTLB_PAGES.
+ * In accordance with the AMD spec.
+ */
+typedef union
+{
+ struct
+ {
+ uint16_t u16DevId; /**< Bits 15:0 - Device ID. */
+ uint8_t u8PasidLo; /**< Bits 23:16 - PASID: Process Address-Space ID (Lo). */
+ uint8_t u8MaxPend; /**< Bits 31:24 - Maxpend: Maximum simultaneous in-flight transactions. */
+ uint32_t u16QueueId : 16; /**< Bits 47:32 - Queue ID. */
+ uint32_t u12PasidHi : 12; /**< Bits 59:48 - PASID: Process Address-Space ID (Hi). */
+ uint32_t u4OpCode : 4; /**< Bits 63:60 - Op Code (Command). */
+ uint32_t u1Size : 1; /**< Bit 64 - S: Size. */
+ uint32_t u1Rsvd0: 1; /**< Bit 65 - Reserved. */
+ uint32_t u1GuestOrNested : 1; /**< Bit 66 - GN: Guest (GPA) or Nested (GVA). */
+ uint32_t u1Rsvd1 : 1; /**< Bit 67 - Reserved. */
+ uint32_t u2Type : 2; /**< Bit 69:68 - Type. */
+ uint32_t u6Rsvd0 : 6; /**< Bits 75:70 - Reserved. */
+ uint32_t u20AddrLo : 20; /**< Bits 95:76 - Address (Lo). */
+ uint32_t u32AddrHi; /**< Bits 127:96 - Address (Hi). */
+ } n;
+ /** The 64-bit unsigned integer view. */
+ uint64_t au64[2];
+} CMD_INV_IOTLB_PAGES_T;
+AssertCompileSize(CMD_INV_IOTLB_PAGES_T, 16);
+
+/**
+ * Command: INVALIDATE_INTR_TABLE.
+ * In accordance with the AMD spec.
+ */
+typedef union
+{
+ struct
+ {
+ uint16_t u16DevId; /**< Bits 15:0 - Device ID. */
+ uint16_t u16Rsvd0; /**< Bits 31:16 - Reserved. */
+ uint32_t u32Rsvd0 : 28; /**< Bits 59:32 - Reserved. */
+ uint32_t u4OpCode : 4; /**< Bits 63:60 - Op Code (Command). */
+ uint64_t u64Rsvd0; /**< Bits 127:64 - Reserved. */
+ } u;
+ /** The 64-bit unsigned integer view. */
+ uint64_t au64[2];
+} CMD_INV_INTR_TABLE_T;
+AssertCompileSize(CMD_INV_INTR_TABLE_T, 16);
+/** Pointer to a invalidate interrupt table command. */
+typedef CMD_INV_INTR_TABLE_T *PCMD_INV_INTR_TABLE_T;
+/** Pointer to a const invalidate interrupt table command. */
+typedef CMD_INV_INTR_TABLE_T const *PCCMD_INV_INTR_TABLE_T;
+#define IOMMU_CMD_INV_INTR_TABLE_QWORD_0_VALID_MASK UINT64_C(0xf00000000000ffff)
+#define IOMMU_CMD_INV_INTR_TABLE_QWORD_1_VALID_MASK UINT64_C(0x0000000000000000)
+
+/**
+ * Command: PREFETCH_IOMMU_PAGES.
+ * In accordance with the AMD spec.
+ */
+typedef union
+{
+ struct
+ {
+ uint16_t u16DevId; /**< Bits 15:0 - Device ID. */
+ uint8_t u8Rsvd0; /**< Bits 23:16 - Reserved. */
+ uint8_t u8PrefCount; /**< Bits 31:24 - PFCount: Number of translations to prefetch. */
+ uint32_t u20Pasid : 20; /**< Bits 51:32 - PASID: Process Address-Space ID. */
+ uint32_t u8Rsvd1 : 8; /**< Bits 59:52 - Reserved. */
+ uint32_t u4OpCode : 4; /**< Bits 63:60 - Op Code (Command). */
+ uint32_t u1Size : 1; /**< Bit 64 - S: Size of the prefetched pages. */
+ uint32_t u1Rsvd0 : 1; /**< Bit 65 - Reserved. */
+ uint32_t u1GuestOrNested : 1; /**< Bit 66 - GN: Guest (GPA) or Nested (GVA). */
+ uint32_t u1Rsvd1 : 1; /**< Bit 67 - Reserved. */
+ uint32_t u1Invalidate : 1; /**< Bit 68 - Inval: Invalidate prior to prefetch. */
+ uint32_t u7Rsvd0 : 7; /**< Bits 75:69 - Reserved */
+ uint32_t u20AddrLo : 7; /**< Bits 95:76 - Address (Lo). */
+ uint32_t u32AddrHi; /**< Bits 127:96 - Address (Hi). */
+ } u;
+ /** The 64-bit unsigned integer view. */
+ uint64_t au64[2];
+} CMD_PREF_IOMMU_PAGES_T;
+AssertCompileSize(CMD_PREF_IOMMU_PAGES_T, 16);
+/** Pointer to a invalidate iommu pages command. */
+typedef CMD_PREF_IOMMU_PAGES_T *PCMD_PREF_IOMMU_PAGES_T;
+/** Pointer to a const invalidate iommu pages command. */
+typedef CMD_PREF_IOMMU_PAGES_T const *PCCMD_PREF_IOMMU_PAGES_T;
+#define IOMMU_CMD_PREF_IOMMU_PAGES_QWORD_0_VALID_MASK UINT64_C(0x780fffffff00ffff)
+#define IOMMU_CMD_PREF_IOMMU_PAGES_QWORD_1_VALID_MASK UINT64_C(0xfffffffffffff015)
+
+
+/**
+ * Command: COMPLETE_PPR_REQ.
+ * In accordance with the AMD spec.
+ */
+typedef union
+{
+ struct
+ {
+ uint16_t u16DevId; /**< Bits 15:0 - Device ID. */
+ uint16_t u16Rsvd0; /**< Bits 31:16 - Reserved. */
+ uint32_t u20Pasid : 20; /**< Bits 51:32 - PASID: Process Address-Space ID. */
+ uint32_t u8Rsvd0 : 8; /**< Bits 59:52 - Reserved. */
+ uint32_t u4OpCode : 4; /**< Bits 63:60 - Op Code (Command). */
+ uint32_t u2Rsvd0 : 2; /**< Bits 65:64 - Reserved. */
+ uint32_t u1GuestOrNested : 1; /**< Bit 66 - GN: Guest (GPA) or Nested (GVA). */
+ uint32_t u29Rsvd0 : 29; /**< Bits 95:67 - Reserved. */
+ uint32_t u16CompletionTag : 16; /**< Bits 111:96 - Completion Tag. */
+ uint32_t u16Rsvd1 : 16; /**< Bits 127:112 - Reserved. */
+ } n;
+ /** The 64-bit unsigned integer view. */
+ uint64_t au64[2];
+} CMD_COMPLETE_PPR_REQ_T;
+AssertCompileSize(CMD_COMPLETE_PPR_REQ_T, 16);
+
+/**
+ * Command: INV_IOMMU_ALL.
+ * In accordance with the AMD spec.
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t u32Rsvd0; /**< Bits 31:0 - Reserved. */
+ uint32_t u28Rsvd0 : 28; /**< Bits 59:32 - Reserved. */
+ uint32_t u4OpCode : 4; /**< Bits 63:60 - Op Code (Command). */
+ uint64_t u64Rsvd0; /**< Bits 127:64 - Reserved. */
+ } n;
+ /** The 64-bit unsigned integer view. */
+ uint64_t au64[2];
+} CMD_INV_IOMMU_ALL_T;
+AssertCompileSize(CMD_INV_IOMMU_ALL_T, 16);
+/** Pointer to a invalidate IOMMU all command. */
+typedef CMD_INV_IOMMU_ALL_T *PCMD_INV_IOMMU_ALL_T;
+/** Pointer to a const invalidate IOMMU all command. */
+typedef CMD_INV_IOMMU_ALL_T const *PCCMD_INV_IOMMU_ALL_T;
+#define IOMMU_CMD_INV_IOMMU_ALL_QWORD_0_VALID_MASK UINT64_C(0xf000000000000000)
+#define IOMMU_CMD_INV_IOMMU_ALL_QWORD_1_VALID_MASK UINT64_C(0x0000000000000000)
+
+/**
+ * Event Log Entry: Generic.
+ * In accordance with the AMD spec.
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t u32Operand1Lo; /**< Bits 31:0 - Operand 1 (Lo). */
+ uint32_t u28Operand1Hi : 28; /**< Bits 59:32 - Operand 1 (Hi). */
+ uint32_t u4EvtCode : 4; /**< Bits 63:60 - Event code. */
+ uint32_t u32Operand2Lo; /**< Bits 95:64 - Operand 2 (Lo). */
+ uint32_t u32Operand2Hi; /**< Bits 127:96 - Operand 2 (Hi). */
+ } n;
+ /** The 32-bit unsigned integer view. */
+ uint32_t au32[4];
+} EVT_GENERIC_T;
+AssertCompileSize(EVT_GENERIC_T, 16);
+/** Number of bits to shift the byte offset of an event entry in the event log
+ * buffer to get its index. */
+#define IOMMU_EVT_GENERIC_SHIFT 4
+/** Pointer to a generic event log entry. */
+typedef EVT_GENERIC_T *PEVT_GENERIC_T;
+/** Pointer to a const generic event log entry. */
+typedef const EVT_GENERIC_T *PCEVT_GENERIC_T;
+
+/**
+ * Hardware event types.
+ * In accordance with the AMD spec.
+ */
+typedef enum HWEVTTYPE
+{
+ HWEVTTYPE_RSVD = 0,
+ HWEVTTYPE_MASTER_ABORT,
+ HWEVTTYPE_TARGET_ABORT,
+ HWEVTTYPE_DATA_ERROR
+} HWEVTTYPE;
+AssertCompileSize(HWEVTTYPE, 4);
+
+/**
+ * Event Log Entry: ILLEGAL_DEV_TABLE_ENTRY.
+ * In accordance with the AMD spec.
+ */
+typedef union
+{
+ struct
+ {
+ uint16_t u16DevId; /**< Bits 15:0 - Device ID. */
+ RT_GCC_EXTENSION uint16_t u4PasidHi : 4; /**< Bits 19:16 - PASID: Process Address-Space ID (Hi). */
+ RT_GCC_EXTENSION uint16_t u12Rsvd0 : 12; /**< Bits 31:20 - Reserved. */
+ uint16_t u16PasidLo; /**< Bits 47:32 - PASID: Process Address-Space ID (Lo). */
+ RT_GCC_EXTENSION uint16_t u1GuestOrNested : 1; /**< Bit 48 - GN: Guest (GPA) or Nested (GVA). */
+ RT_GCC_EXTENSION uint16_t u2Rsvd0 : 2; /**< Bits 50:49 - Reserved. */
+ RT_GCC_EXTENSION uint16_t u1Interrupt : 1; /**< Bit 51 - I: Interrupt. */
+ RT_GCC_EXTENSION uint16_t u1Rsvd0 : 1; /**< Bit 52 - Reserved. */
+ RT_GCC_EXTENSION uint16_t u1ReadWrite : 1; /**< Bit 53 - RW: Read/Write. */
+ RT_GCC_EXTENSION uint16_t u1Rsvd1 : 1; /**< Bit 54 - Reserved. */
+ RT_GCC_EXTENSION uint16_t u1RsvdNotZero : 1; /**< Bit 55 - RZ: Reserved bit not Zero (0=invalid level encoding). */
+ RT_GCC_EXTENSION uint16_t u1Translation : 1; /**< Bit 56 - TN: Translation. */
+ RT_GCC_EXTENSION uint16_t u3Rsvd0 : 3; /**< Bits 59:57 - Reserved. */
+ RT_GCC_EXTENSION uint16_t u4EvtCode : 4; /**< Bits 63:60 - Event code. */
+ uint64_t u64Addr; /**< Bits 127:64 - Address: I/O Virtual Address (IOVA). */
+ } n;
+ /** The 32-bit unsigned integer view. */
+ uint32_t au32[4];
+ /** The 64-bit unsigned integer view. */
+ uint64_t au64[2];
+} EVT_ILLEGAL_DTE_T;
+AssertCompileSize(EVT_ILLEGAL_DTE_T, 16);
+/** Pointer to an illegal device table entry event. */
+typedef EVT_ILLEGAL_DTE_T *PEVT_ILLEGAL_DTE_T;
+/** Pointer to a const illegal device table entry event. */
+typedef EVT_ILLEGAL_DTE_T const *PCEVT_ILLEGAL_DTE_T;
+
+/**
+ * Event Log Entry: IO_PAGE_FAULT_EVENT.
+ * In accordance with the AMD spec.
+ */
+typedef union
+{
+ struct
+ {
+ uint16_t u16DevId; /**< Bits 15:0 - Device ID. */
+ RT_GCC_EXTENSION uint16_t u4PasidHi : 4; /**< Bits 19:16 - PASID: Process Address-Space ID (Hi). */
+ RT_GCC_EXTENSION uint16_t u16DomainOrPasidLo; /**< Bits 47:32 - D/P: Domain ID or Process Address-Space ID (Lo). */
+ RT_GCC_EXTENSION uint16_t u1GuestOrNested : 1; /**< Bit 48 - GN: Guest (GPA) or Nested (GVA). */
+ RT_GCC_EXTENSION uint16_t u1NoExecute : 1; /**< Bit 49 - NX: No Execute. */
+ RT_GCC_EXTENSION uint16_t u1User : 1; /**< Bit 50 - US: User/Supervisor. */
+ RT_GCC_EXTENSION uint16_t u1Interrupt : 1; /**< Bit 51 - I: Interrupt. */
+ RT_GCC_EXTENSION uint16_t u1Present : 1; /**< Bit 52 - PR: Present. */
+ RT_GCC_EXTENSION uint16_t u1ReadWrite : 1; /**< Bit 53 - RW: Read/Write. */
+ RT_GCC_EXTENSION uint16_t u1PermDenied : 1; /**< Bit 54 - PE: Permission Indicator. */
+ RT_GCC_EXTENSION uint16_t u1RsvdNotZero : 1; /**< Bit 55 - RZ: Reserved bit not Zero (0=invalid level encoding). */
+ RT_GCC_EXTENSION uint16_t u1Translation : 1; /**< Bit 56 - TN: Translation. */
+ RT_GCC_EXTENSION uint16_t u3Rsvd0 : 3; /**< Bit 59:57 - Reserved. */
+ RT_GCC_EXTENSION uint16_t u4EvtCode : 4; /**< Bits 63:60 - Event code. */
+ uint64_t u64Addr; /**< Bits 127:64 - Address: I/O Virtual Address (IOVA). */
+ } n;
+ /** The 32-bit unsigned integer view. */
+ uint32_t au32[4];
+ /** The 64-bit unsigned integer view. */
+ uint64_t au64[2];
+} EVT_IO_PAGE_FAULT_T;
+AssertCompileSize(EVT_IO_PAGE_FAULT_T, 16);
+/** Pointer to an I/O page fault event. */
+typedef EVT_IO_PAGE_FAULT_T *PEVT_IO_PAGE_FAULT_T;
+/** Pointer to a const I/O page fault event. */
+typedef EVT_IO_PAGE_FAULT_T const *PCEVT_IO_PAGE_FAULT_T;
+
+
+/**
+ * Event Log Entry: DEV_TAB_HARDWARE_ERROR.
+ * In accordance with the AMD spec.
+ */
+typedef union
+{
+ struct
+ {
+ uint16_t u16DevId; /**< Bits 15:0 - Device ID. */
+ uint16_t u16Rsvd0; /**< Bits 31:16 - Reserved. */
+ uint32_t u19Rsvd0 : 19; /**< Bits 50:32 - Reserved. */
+ uint32_t u1Intr : 1; /**< Bit 51 - I: Interrupt (1=interrupt request, 0=memory request). */
+ uint32_t u1Rsvd0 : 1; /**< Bit 52 - Reserved. */
+ uint32_t u1ReadWrite : 1; /**< Bit 53 - RW: Read/Write transaction (only meaninful when I=0 and TR=0). */
+ uint32_t u2Rsvd0 : 2; /**< Bits 55:54 - Reserved. */
+ uint32_t u1Translation : 1; /**< Bit 56 - TR: Translation (1=translation, 0=transaction). */
+ uint32_t u2Type : 2; /**< Bits 58:57 - Type: The type of hardware error. */
+ uint32_t u1Rsvd1 : 1; /**< Bit 59 - Reserved. */
+ uint32_t u4EvtCode : 4; /**< Bits 63:60 - Event code. */
+ uint64_t u64Addr; /**< Bits 127:64 - Address. */
+ } n;
+ /** The 32-bit unsigned integer view. */
+ uint32_t au32[4];
+ /** The 64-bit unsigned integer view. */
+ uint64_t au64[2];
+} EVT_DEV_TAB_HW_ERROR_T;
+AssertCompileSize(EVT_DEV_TAB_HW_ERROR_T, 16);
+/** Pointer to a device table hardware error event. */
+typedef EVT_DEV_TAB_HW_ERROR_T *PEVT_DEV_TAB_HW_ERROR_T;
+/** Pointer to a const device table hardware error event. */
+typedef EVT_DEV_TAB_HW_ERROR_T const *PCEVT_DEV_TAB_HW_ERROR_T;
+
+/**
+ * Event Log Entry: EVT_PAGE_TAB_HARDWARE_ERROR.
+ * In accordance with the AMD spec.
+ */
+typedef union
+{
+ struct
+ {
+ uint16_t u16DevId; /**< Bits 15:0 - Device ID. */
+ uint16_t u16Rsvd0; /**< Bits 31:16 - Reserved. */
+ uint32_t u16DomainOrPasidLo : 16; /**< Bits 47:32 - D/P: Domain ID or Process Address-Space ID (Lo). */
+ uint32_t u1GuestOrNested : 1; /**< Bit 48 - GN: Guest (GPA) or Nested (GVA). */
+ uint32_t u2Rsvd0 : 2; /**< Bits 50:49 - Reserved. */
+ uint32_t u1Interrupt : 1; /**< Bit 51 - I: Interrupt. */
+ uint32_t u1Rsvd0 : 1; /**< Bit 52 - Reserved. */
+ uint32_t u1ReadWrite : 1; /**< Bit 53 - RW: Read/Write. */
+ uint32_t u2Rsvd1 : 2; /**< Bit 55:54 - Reserved. */
+ uint32_t u1Translation : 1; /**< Bit 56 - TR: Translation. */
+ uint32_t u2Type : 2; /**< Bits 58:57 - Type: The type of hardware error. */
+ uint32_t u1Rsvd1 : 1; /**< Bit 59 - Reserved. */
+ uint32_t u4EvtCode : 4; /**< Bit 63:60 - Event code. */
+ /** @todo r=ramshankar: Figure 55: PAGE_TAB_HARDWARE_ERROR says Addr[31:3] but
+ * table 58 mentions Addr[31:4], we just use the full 64-bits. Looks like a
+ * typo in the figure.See AMD AMD IOMMU spec (3.05-PUB, Jan 2020). */
+ uint64_t u64Addr; /** Bits 127:64 - Address: SPA of the page table entry. */
+ } n;
+ /** The 32-bit unsigned integer view. */
+ uint32_t au32[4];
+ /** The 64-bit unsigned integer view. */
+ uint64_t au64[2];
+} EVT_PAGE_TAB_HW_ERR_T;
+AssertCompileSize(EVT_PAGE_TAB_HW_ERR_T, 16);
+/** Pointer to a page table hardware error event. */
+typedef EVT_PAGE_TAB_HW_ERR_T *PEVT_PAGE_TAB_HW_ERR_T;
+/** Pointer to a const page table hardware error event. */
+typedef EVT_PAGE_TAB_HW_ERR_T const *PCEVT_PAGE_TAB_HW_ERR_T;
+
+/**
+ * Event Log Entry: ILLEGAL_COMMAND_ERROR.
+ * In accordance with the AMD spec.
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t u32Rsvd0; /**< Bits 31:0 - Reserved. */
+ uint32_t u28Rsvd0 : 28; /**< Bits 47:32 - Reserved. */
+ uint32_t u4EvtCode : 4; /**< Bits 63:60 - Event code. */
+ uint64_t u64Addr; /**< Bits 127:64 - Address: SPA of the invalid command. */
+ } n;
+ /** The 32-bit unsigned integer view. */
+ uint32_t au32[4];
+ /** The 64-bit unsigned integer view. */
+ uint64_t au64[2];
+} EVT_ILLEGAL_CMD_ERR_T;
+AssertCompileSize(EVT_ILLEGAL_CMD_ERR_T, 16);
+/** Pointer to an illegal command error event. */
+typedef EVT_ILLEGAL_CMD_ERR_T *PEVT_ILLEGAL_CMD_ERR_T;
+/** Pointer to a const illegal command error event. */
+typedef EVT_ILLEGAL_CMD_ERR_T const *PCEVT_ILLEGAL_CMD_ERR_T;
+
+/**
+ * Event Log Entry: COMMAND_HARDWARE_ERROR.
+ * In accordance with the AMD spec.
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t u32Rsvd0; /**< Bits 31:0 - Reserved. */
+ uint32_t u25Rsvd1 : 25; /**< Bits 56:32 - Reserved. */
+ uint32_t u2Type : 2; /**< Bits 58:57 - Type: The type of hardware error. */
+ uint32_t u1Rsvd1 : 1; /**< Bit 59 - Reserved. */
+ uint32_t u4EvtCode : 4; /**< Bits 63:60 - Event code. */
+ uint64_t u64Addr; /**< Bits 128:64 - Address: SPA of the attempted access. */
+ } n;
+ /** The 32-bit unsigned integer view. */
+ uint32_t au32[4];
+ /** The 64-bit unsigned integer view. */
+ uint64_t au64[2];
+} EVT_CMD_HW_ERR_T;
+AssertCompileSize(EVT_CMD_HW_ERR_T, 16);
+/** Pointer to a command hardware error event. */
+typedef EVT_CMD_HW_ERR_T *PEVT_CMD_HW_ERR_T;
+/** Pointer to a const command hardware error event. */
+typedef EVT_CMD_HW_ERR_T const *PCEVT_CMD_HW_ERR_T;
+
+/**
+ * Event Log Entry: IOTLB_INV_TIMEOUT.
+ * In accordance with the AMD spec.
+ */
+typedef union
+{
+ struct
+ {
+ uint16_t u16DevId; /**< Bits 15:0 - Device ID. */
+ uint16_t u16Rsvd0; /**< Bits 31:16 - Reserved.*/
+ uint32_t u28Rsvd0 : 28; /**< Bits 59:32 - Reserved. */
+ uint32_t u4EvtCode : 4; /**< Bits 63:60 - Event code. */
+ uint32_t u4Rsvd0 : 4; /**< Bits 67:64 - Reserved. */
+ uint32_t u28AddrLo : 28; /**< Bits 95:68 - Address: SPA of the invalidation command that timedout (Lo). */
+ uint32_t u32AddrHi; /**< Bits 127:96 - Address: SPA of the invalidation command that timedout (Hi). */
+ } n;
+ /** The 32-bit unsigned integer view. */
+ uint32_t au32[4];
+} EVT_IOTLB_INV_TIMEOUT_T;
+AssertCompileSize(EVT_IOTLB_INV_TIMEOUT_T, 16);
+
+/**
+ * Event Log Entry: INVALID_DEVICE_REQUEST.
+ * In accordance with the AMD spec.
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t u16DevId : 16; /***< Bits 15:0 - Device ID. */
+ uint32_t u4PasidHi : 4; /***< Bits 19:16 - PASID: Process Address-Space ID (Hi). */
+ uint32_t u12Rsvd0 : 12; /***< Bits 31:20 - Reserved. */
+ uint32_t u16PasidLo : 16; /***< Bits 47:32 - PASID: Process Address-Space ID (Lo). */
+ uint32_t u1GuestOrNested : 1; /***< Bit 48 - GN: Guest (GPA) or Nested (GVA). */
+ uint32_t u1User : 1; /***< Bit 49 - US: User/Supervisor. */
+ uint32_t u6Rsvd0 : 6; /***< Bits 55:50 - Reserved. */
+ uint32_t u1Translation: 1; /***< Bit 56 - TR: Translation. */
+ uint32_t u3Type: 3; /***< Bits 59:57 - Type: The type of hardware error. */
+ uint32_t u4EvtCode : 4; /***< Bits 63:60 - Event code. */
+ uint64_t u64Addr; /***< Bits 127:64 - Address: Translation or access address. */
+ } n;
+ /** The 32-bit unsigned integer view. */
+ uint32_t au32[4];
+} EVT_INVALID_DEV_REQ_T;
+AssertCompileSize(EVT_INVALID_DEV_REQ_T, 16);
+
+/**
+ * Event Log Entry: EVENT_COUNTER_ZERO.
+ * In accordance with the AMD spec.
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t u32Rsvd0; /**< Bits 31:0 - Reserved. */
+ uint32_t u28Rsvd0 : 28; /**< Bits 59:32 - Reserved. */
+ uint32_t u4EvtCode : 4; /**< Bits 63:60 - Event code. */
+ uint32_t u20CounterNoteHi : 20; /**< Bits 83:64 - CounterNote: Counter value for the event counter register (Hi). */
+ uint32_t u12Rsvd0 : 12; /**< Bits 95:84 - Reserved. */
+ uint32_t u32CounterNoteLo; /**< Bits 127:96 - CounterNote: Counter value for the event cuonter register (Lo). */
+ } n;
+ /** The 32-bit unsigned integer view. */
+ uint32_t au32[4];
+} EVT_EVENT_COUNTER_ZERO_T;
+AssertCompileSize(EVT_EVENT_COUNTER_ZERO_T, 16);
+
+/**
+ * IOMMU Capability Header (PCI).
+ * In accordance with the AMD spec.
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t u8CapId : 8; /**< Bits 7:0 - CapId: Capability ID. */
+ uint32_t u8CapPtr : 8; /**< Bits 15:8 - CapPtr: Pointer (PCI config offset) to the next capability. */
+ uint32_t u3CapType : 3; /**< Bits 18:16 - CapType: Capability Type. */
+ uint32_t u5CapRev : 5; /**< Bits 23:19 - CapRev: Capability revision. */
+ uint32_t u1IoTlbSup : 1; /**< Bit 24 - IotlbSup: IOTLB Support. */
+ uint32_t u1HtTunnel : 1; /**< Bit 25 - HtTunnel: HyperTransport Tunnel translation support. */
+ uint32_t u1NpCache : 1; /**< Bit 26 - NpCache: Not Present table entries are cached. */
+ uint32_t u1EfrSup : 1; /**< Bit 27 - EFRSup: Extended Feature Register Support. */
+ uint32_t u1CapExt : 1; /**< Bit 28 - CapExt: Misc. Information Register 1 Support. */
+ uint32_t u3Rsvd0 : 3; /**< Bits 31:29 - Reserved. */
+ } n;
+ /** The 32-bit unsigned integer view. */
+ uint32_t u32;
+} IOMMU_CAP_HDR_T;
+AssertCompileSize(IOMMU_CAP_HDR_T, 4);
+
+/**
+ * IOMMU Base Address (Lo and Hi) Register (PCI).
+ * In accordance with the AMD spec.
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t u1Enable : 1; /**< Bit 1 - Enable: RW1S - Enable IOMMU MMIO region. */
+ uint32_t u12Rsvd0 : 12; /**< Bits 13:1 - Reserved. */
+ uint32_t u18BaseAddrLo : 18; /**< Bits 31:14 - Base address (Lo) of the MMIO region. */
+ uint32_t u32BaseAddrHi; /**< Bits 63:32 - Base address (Hi) of the MMIO region. */
+ } n;
+ /** The 32-bit unsigned integer view. */
+ uint32_t au32[2];
+ /** The 64-bit unsigned integer view. */
+ uint64_t u64;
+} IOMMU_BAR_T;
+AssertCompileSize(IOMMU_BAR_T, 8);
+#define IOMMU_BAR_VALID_MASK UINT64_C(0xffffffffffffc001)
+
+/**
+ * IOMMU Range Register (PCI).
+ * In accordance with the AMD spec.
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t u5HtUnitId : 5; /**< Bits 4:0 - UnitID: IOMMU HyperTransport Unit ID (not used). */
+ uint32_t u2Rsvd0 : 2; /**< Bits 6:5 - Reserved. */
+ uint32_t u1RangeValid : 1; /**< Bit 7 - RngValid: Range Valid. */
+ uint32_t u8Bus : 8; /**< Bits 15:8 - BusNumber: Bus number of the first and last device. */
+ uint32_t u8FirstDevice : 8; /**< Bits 23:16 - FirstDevice: Device and function number of the first device. */
+ uint32_t u8LastDevice: 8; /**< Bits 31:24 - LastDevice: Device and function number of the last device. */
+ } n;
+ /** The 32-bit unsigned integer view. */
+ uint32_t u32;
+} IOMMU_RANGE_T;
+AssertCompileSize(IOMMU_RANGE_T, 4);
+
+/**
+ * Device Table Base Address Register (MMIO).
+ * In accordance with the AMD spec.
+ */
+typedef union
+{
+ struct
+ {
+ RT_GCC_EXTENSION uint64_t u9Size : 9; /**< Bits 8:0 - Size: Size of the device table. */
+ RT_GCC_EXTENSION uint64_t u3Rsvd0 : 3; /**< Bits 11:9 - Reserved. */
+ RT_GCC_EXTENSION uint64_t u40Base : 40; /**< Bits 51:12 - DevTabBase: Device table base address. */
+ RT_GCC_EXTENSION uint64_t u12Rsvd0 : 12; /**< Bits 63:52 - Reserved. */
+ } n;
+ /** The 64-bit unsigned integer view. */
+ uint64_t u64;
+} DEV_TAB_BAR_T;
+AssertCompileSize(DEV_TAB_BAR_T, 8);
+#define IOMMU_DEV_TAB_BAR_VALID_MASK UINT64_C(0x000ffffffffff1ff)
+#define IOMMU_DEV_TAB_SEG_BAR_VALID_MASK UINT64_C(0x000ffffffffff0ff)
+
+/**
+ * Command Buffer Base Address Register (MMIO).
+ * In accordance with the AMD spec.
+ */
+typedef union
+{
+ struct
+ {
+ RT_GCC_EXTENSION uint64_t u12Rsvd0 : 12; /**< Bits 11:0 - Reserved. */
+ RT_GCC_EXTENSION uint64_t u40Base : 40; /**< Bits 51:12 - ComBase: Command buffer base address. */
+ RT_GCC_EXTENSION uint64_t u4Rsvd0 : 4; /**< Bits 55:52 - Reserved. */
+ RT_GCC_EXTENSION uint64_t u4Len : 4; /**< Bits 59:56 - ComLen: Command buffer length. */
+ RT_GCC_EXTENSION uint64_t u4Rsvd1 : 4; /**< Bits 63:60 - Reserved. */
+ } n;
+ /** The 64-bit unsigned integer view. */
+ uint64_t u64;
+} CMD_BUF_BAR_T;
+AssertCompileSize(CMD_BUF_BAR_T, 8);
+#define IOMMU_CMD_BUF_BAR_VALID_MASK UINT64_C(0x0f0ffffffffff000)
+
+/**
+ * Event Log Base Address Register (MMIO).
+ * In accordance with the AMD spec.
+ */
+typedef union
+{
+ struct
+ {
+ RT_GCC_EXTENSION uint64_t u12Rsvd0 : 12; /**< Bits 11:0 - Reserved. */
+ RT_GCC_EXTENSION uint64_t u40Base : 40; /**< Bits 51:12 - EventBase: Event log base address. */
+ RT_GCC_EXTENSION uint64_t u4Rsvd0 : 4; /**< Bits 55:52 - Reserved. */
+ RT_GCC_EXTENSION uint64_t u4Len : 4; /**< Bits 59:56 - EventLen: Event log length. */
+ RT_GCC_EXTENSION uint64_t u4Rsvd1 : 4; /**< Bits 63:60 - Reserved. */
+ } n;
+ /** The 64-bit unsigned integer view. */
+ uint64_t u64;
+} EVT_LOG_BAR_T;
+AssertCompileSize(EVT_LOG_BAR_T, 8);
+#define IOMMU_EVT_LOG_BAR_VALID_MASK UINT64_C(0x0f0ffffffffff000)
+
+/**
+ * IOMMU Control Register (MMIO).
+ * In accordance with the AMD spec.
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t u1IommuEn : 1; /**< Bit 0 - IommuEn: IOMMU Enable. */
+ uint32_t u1HtTunEn : 1; /**< Bit 1 - HtTunEn: HyperTransport Tunnel Enable. */
+ uint32_t u1EvtLogEn : 1; /**< Bit 2 - EventLogEn: Event Log Enable. */
+ uint32_t u1EvtIntrEn : 1; /**< Bit 3 - EventIntEn: Event Log Interrupt Enable. */
+ uint32_t u1CompWaitIntrEn : 1; /**< Bit 4 - ComWaitIntEn: Completion Wait Interrupt Enable. */
+ uint32_t u3InvTimeOut : 3; /**< Bits 7:5 - InvTimeOut: Invalidation Timeout. */
+ uint32_t u1PassPW : 1; /**< Bit 8 - PassPW: Pass Posted Write. */
+ uint32_t u1ResPassPW : 1; /**< Bit 9 - ResPassPW: Response Pass Posted Write. */
+ uint32_t u1Coherent : 1; /**< Bit 10 - Coherent: HT read request packet Coherent bit. */
+ uint32_t u1Isoc : 1; /**< Bit 11 - Isoc: HT read request packet Isochronous bit. */
+ uint32_t u1CmdBufEn : 1; /**< Bit 12 - CmdBufEn: Command Buffer Enable. */
+ uint32_t u1PprLogEn : 1; /**< Bit 13 - PprLogEn: Peripheral Page Request (PPR) Log Enable. */
+ uint32_t u1PprIntrEn : 1; /**< Bit 14 - PprIntrEn: Peripheral Page Request Interrupt Enable. */
+ uint32_t u1PprEn : 1; /**< Bit 15 - PprEn: Peripheral Page Request processing Enable. */
+ uint32_t u1GstTranslateEn : 1; /**< Bit 16 - GTEn: Guest Translate Enable. */
+ uint32_t u1GstVirtApicEn : 1; /**< Bit 17 - GAEn: Guest Virtual-APIC Enable. */
+ uint32_t u4Crw : 1; /**< Bits 21:18 - CRW: Intended for future use (not documented). */
+ uint32_t u1SmiFilterEn : 1; /**< Bit 22 - SmiFEn: SMI Filter Enable. */
+ uint32_t u1SelfWriteBackDis : 1; /**< Bit 23 - SlfWBDis: Self Write-Back Disable. */
+ uint32_t u1SmiFilterLogEn : 1; /**< Bit 24 - SmiFLogEn: SMI Filter Log Enable. */
+ uint32_t u3GstVirtApicModeEn : 3; /**< Bits 27:25 - GAMEn: Guest Virtual-APIC Mode Enable. */
+ uint32_t u1GstLogEn : 1; /**< Bit 28 - GALogEn: Guest Virtual-APIC GA Log Enable. */
+ uint32_t u1GstIntrEn : 1; /**< Bit 29 - GAIntEn: Guest Virtual-APIC Interrupt Enable. */
+ uint32_t u2DualPprLogEn : 2; /**< Bits 31:30 - DualPprLogEn: Dual Peripheral Page Request Log Enable. */
+ uint32_t u2DualEvtLogEn : 2; /**< Bits 33:32 - DualEventLogEn: Dual Event Log Enable. */
+ uint32_t u3DevTabSegEn : 3; /**< Bits 36:34 - DevTblSegEn: Device Table Segment Enable. */
+ uint32_t u2PrivAbortEn : 2; /**< Bits 38:37 - PrivAbrtEn: Privilege Abort Enable. */
+ uint32_t u1PprAutoRespEn : 1; /**< Bit 39 - PprAutoRspEn: Peripheral Page Request Auto Response Enable. */
+ uint32_t u1MarcEn : 1; /**< Bit 40 - MarcEn: Memory Address Routing and Control Enable. */
+ uint32_t u1BlockStopMarkEn : 1; /**< Bit 41 - BlkStopMarkEn: Block StopMark messages Enable. */
+ uint32_t u1PprAutoRespAlwaysOnEn : 1; /**< Bit 42 - PprAutoRspAon:: PPR Auto Response - Always On Enable. */
+ uint32_t u1DomainIDPNE : 1; /**< Bit 43 - DomainIDPE: Reserved (not documented). */
+ uint32_t u1Rsvd0 : 1; /**< Bit 44 - Reserved. */
+ uint32_t u1EnhancedPpr : 1; /**< Bit 45 - EPHEn: Enhanced Peripheral Page Request Handling Enable. */
+ uint32_t u2HstAccDirtyBitUpdate : 2; /**< Bits 47:46 - HADUpdate: Access and Dirty Bit updated in host page table. */
+ uint32_t u1GstDirtyUpdateDis : 1; /**< Bit 48 - GDUpdateDis: Disable hardare update of Dirty bit in GPT. */
+ uint32_t u1Rsvd1 : 1; /**< Bit 49 - Reserved. */
+ uint32_t u1X2ApicEn : 1; /**< Bit 50 - XTEn: Enable X2APIC. */
+ uint32_t u1X2ApicIntrGenEn : 1; /**< Bit 51 - IntCapXTEn: Enable IOMMU X2APIC Interrupt generation. */
+ uint32_t u2Rsvd0 : 2; /**< Bits 53:52 - Reserved. */
+ uint32_t u1GstAccessUpdateDis : 1; /**< Bit 54 - GAUpdateDis: Disable hardare update of Access bit in GPT. */
+ uint32_t u8Rsvd0 : 8; /**< Bits 63:55 - Reserved. */
+ } n;
+ /** The 64-bit unsigned integer view. */
+ uint64_t u64;
+} IOMMU_CTRL_T;
+AssertCompileSize(IOMMU_CTRL_T, 8);
+#define IOMMU_CTRL_VALID_MASK UINT64_C(0x004defffffffffff)
+#define IOMMU_CTRL_CMD_BUF_EN_MASK UINT64_C(0x0000000000001001)
+
+/**
+ * IOMMU Exclusion Base Register (MMIO).
+ * In accordance with the AMD spec.
+ */
+typedef union
+{
+ struct
+ {
+ RT_GCC_EXTENSION uint64_t u1ExclEnable : 1; /**< Bit 0 - ExEn: Exclusion Range Enable. */
+ RT_GCC_EXTENSION uint64_t u1AllowAll : 1; /**< Bit 1 - Allow: Allow All Devices. */
+ RT_GCC_EXTENSION uint64_t u10Rsvd0 : 10; /**< Bits 11:2 - Reserved. */
+ RT_GCC_EXTENSION uint64_t u40ExclRangeBase : 40; /**< Bits 51:12 - Exclusion Range Base Address. */
+ RT_GCC_EXTENSION uint64_t u12Rsvd0 : 12; /**< Bits 63:52 - Reserved. */
+ } n;
+ /** The 64-bit unsigned integer view. */
+ uint64_t u64;
+} IOMMU_EXCL_RANGE_BAR_T;
+AssertCompileSize(IOMMU_EXCL_RANGE_BAR_T, 8);
+#define IOMMU_EXCL_RANGE_BAR_VALID_MASK UINT64_C(0x000ffffffffff003)
+
+/**
+ * IOMMU Exclusion Range Limit Register (MMIO).
+ * In accordance with the AMD spec.
+ */
+typedef union
+{
+ struct
+ {
+ RT_GCC_EXTENSION uint64_t u12Rsvd0 : 12; /**< Bits 63:52 - Reserved. */
+ RT_GCC_EXTENSION uint64_t u40ExclRangeLimit : 40; /**< Bits 51:12 - Exclusion Range Limit Address. */
+ RT_GCC_EXTENSION uint64_t u12Rsvd1 : 12; /**< Bits 63:52 - Reserved (treated as 1s). */
+ } n;
+ /** The 64-bit unsigned integer view. */
+ uint64_t u64;
+} IOMMU_EXCL_RANGE_LIMIT_T;
+AssertCompileSize(IOMMU_EXCL_RANGE_LIMIT_T, 8);
+#define IOMMU_EXCL_RANGE_LIMIT_VALID_MASK UINT64_C(0x000fffffffffffff)
+
+/**
+ * IOMMU Extended Feature Register (MMIO).
+ * In accordance with the AMD spec.
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t u1PrefetchSup : 1; /**< Bit 0 - PreFSup: Prefetch Support. */
+ uint32_t u1PprSup : 1; /**< Bit 1 - PPRSup: Peripheral Page Request Support. */
+ uint32_t u1X2ApicSup : 1; /**< Bit 2 - XTSup: x2Apic Support. */
+ uint32_t u1NoExecuteSup : 1; /**< Bit 3 - NXSup: No-Execute and Privilege Level Support. */
+ uint32_t u1GstTranslateSup : 1; /**< Bit 4 - GTSup: Guest Translations (for GVAs) Support. */
+ uint32_t u1Rsvd0 : 1; /**< Bit 5 - Reserved. */
+ uint32_t u1InvAllSup : 1; /**< Bit 6 - IASup: Invalidate-All Support. */
+ uint32_t u1GstVirtApicSup : 1; /**< Bit 7 - GASup: Guest Virtual-APIC Support. */
+ uint32_t u1HwErrorSup : 1; /**< Bit 8 - HESup: Hardware Error registers Support. */
+ uint32_t u1PerfCounterSup : 1; /**< Bit 9 - PCSup: Performance Counter Support. */
+ uint32_t u2HostAddrTranslateSize : 2; /**< Bits 11:10 - HATS: Host Address Translation Size. */
+ uint32_t u2GstAddrTranslateSize : 2; /**< Bits 13:12 - GATS: Guest Address Translation Size. */
+ uint32_t u2GstCr3RootTblLevel : 2; /**< Bits 15:14 - GLXSup: Guest CR3 Root Table Level (Max) Size Support. */
+ uint32_t u2SmiFilterSup : 2; /**< Bits 17:16 - SmiFSup: SMI Filter Register Support. */
+ uint32_t u3SmiFilterCount : 3; /**< Bits 20:18 - SmiFRC: SMI Filter Register Count. */
+ uint32_t u3GstVirtApicModeSup : 3; /**< Bits 23:21 - GAMSup: Guest Virtual-APIC Modes Supported. */
+ uint32_t u2DualPprLogSup : 2; /**< Bits 25:24 - DualPprLogSup: Dual Peripheral Page Request Log Support. */
+ uint32_t u2Rsvd0 : 2; /**< Bits 27:26 - Reserved. */
+ uint32_t u2DualEvtLogSup : 2; /**< Bits 29:28 - DualEventLogSup: Dual Event Log Support. */
+ uint32_t u2Rsvd1 : 2; /**< Bits 31:30 - Reserved. */
+ uint32_t u5MaxPasidSup : 5; /**< Bits 36:32 - PASMax: Maximum PASID Supported. */
+ uint32_t u1UserSupervisorSup : 1; /**< Bit 37 - USSup: User/Supervisor Page Protection Support. */
+ uint32_t u2DevTabSegSup : 2; /**< Bits 39:38 - DevTlbSegSup: Segmented Device Table Support. */
+ uint32_t u1PprLogOverflowWarn : 1; /**< Bit 40 - PprOvrflwEarlySup: PPR Log Overflow Early Warning Support. */
+ uint32_t u1PprAutoRespSup : 1; /**< Bit 41 - PprAutoRspSup: PPR Automatic Response Support. */
+ uint32_t u2MarcSup : 2; /**< Bit 43:42 - MarcSup: Memory Access Routing and Control Support. */
+ uint32_t u1BlockStopMarkSup : 1; /**< Bit 44 - BlkStopMarkSup: Block StopMark messages Support. */
+ uint32_t u1PerfOptSup : 1; /**< Bit 45 - PerfOptSup: IOMMU Performance Optimization Support. */
+ uint32_t u1MsiCapMmioSup : 1; /**< Bit 46 - MsiCapMmioSup: MSI Capability Register MMIO Access Support. */
+ uint32_t u1Rsvd1 : 1; /**< Bit 47 - Reserved. */
+ uint32_t u1GstIoSup : 1; /**< Bit 48 - GIoSup: Guest I/O Protection Support. */
+ uint32_t u1HostAccessSup : 1; /**< Bit 49 - HASup: Host Access Support. */
+ uint32_t u1EnhancedPprSup : 1; /**< Bit 50 - EPHSup: Enhanced Peripheral Page Request Handling Support. */
+ uint32_t u1AttrForwardSup : 1; /**< Bit 51 - AttrFWSup: Attribute Forward Support. */
+ uint32_t u1HostDirtySup : 1; /**< Bit 52 - HDSup: Host Dirty Support. */
+ uint32_t u1Rsvd2 : 1; /**< Bit 53 - Reserved. */
+ uint32_t u1InvIoTlbTypeSup : 1; /**< Bit 54 - InvIotlbTypeSup: Invalidate IOTLB Type Support. */
+ uint32_t u6Rsvd0 : 6; /**< Bit 60:55 - Reserved. */
+ uint32_t u1GstUpdateDisSup : 1; /**< Bit 61 - GAUpdateDisSup: Disable hardware update on GPT Support. */
+ uint32_t u1ForcePhysDstSup : 1; /**< Bit 62 - ForcePhyDestSup: Force Phys. Dst. Mode for Remapped Intr. */
+ uint32_t u1Rsvd3 : 1; /**< Bit 63 - Reserved. */
+ } n;
+ /** The 64-bit unsigned integer view. */
+ uint64_t u64;
+} IOMMU_EXT_FEAT_T;
+AssertCompileSize(IOMMU_EXT_FEAT_T, 8);
+
+/**
+ * Peripheral Page Request Log Base Address Register (MMIO).
+ * In accordance with the AMD spec.
+ */
+typedef union
+{
+ struct
+ {
+ RT_GCC_EXTENSION uint64_t u12Rsvd0 : 12; /**< Bit 11:0 - Reserved. */
+ RT_GCC_EXTENSION uint64_t u40Base : 40; /**< Bits 51:12 - PPRLogBase: Peripheral Page Request Log Base Address. */
+ RT_GCC_EXTENSION uint64_t u4Rsvd0 : 4; /**< Bits 55:52 - Reserved. */
+ RT_GCC_EXTENSION uint64_t u4Len : 4; /**< Bits 59:56 - PPRLogLen: Peripheral Page Request Log Length. */
+ RT_GCC_EXTENSION uint64_t u4Rsvd1 : 4; /**< Bits 63:60 - Reserved. */
+ } n;
+ /** The 64-bit unsigned integer view. */
+ uint64_t u64;
+} PPR_LOG_BAR_T;
+AssertCompileSize(PPR_LOG_BAR_T, 8);
+#define IOMMU_PPR_LOG_BAR_VALID_MASK UINT64_C(0x0f0ffffffffff000)
+
+/**
+ * IOMMU Hardware Event Upper Register (MMIO).
+ * In accordance with the AMD spec.
+ */
+typedef union
+{
+ struct
+ {
+ RT_GCC_EXTENSION uint64_t u60FirstOperand : 60; /**< Bits 59:0 - First event code dependent operand. */
+ RT_GCC_EXTENSION uint64_t u4EvtCode : 4; /**< Bits 63:60 - Event Code. */
+ } n;
+ /** The 64-bit unsigned integer view. */
+ uint64_t u64;
+} IOMMU_HW_EVT_HI_T;
+AssertCompileSize(IOMMU_HW_EVT_HI_T, 8);
+
+/**
+ * IOMMU Hardware Event Lower Register (MMIO).
+ * In accordance with the AMD spec.
+ */
+typedef uint64_t IOMMU_HW_EVT_LO_T;
+
+/**
+ * IOMMU Hardware Event Status (MMIO).
+ * In accordance with the AMD spec.
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t u1Valid : 1; /**< Bit 0 - HEV: Hardware Event Valid. */
+ uint32_t u1Overflow : 1; /**< Bit 1 - HEO: Hardware Event Overflow. */
+ uint32_t u30Rsvd0 : 30; /**< Bits 31:2 - Reserved. */
+ uint32_t u32Rsvd0; /**< Bits 63:32 - Reserved. */
+ } n;
+ /** The 64-bit unsigned integer view. */
+ uint64_t u64;
+} IOMMU_HW_EVT_STATUS_T;
+AssertCompileSize(IOMMU_HW_EVT_STATUS_T, 8);
+#define IOMMU_HW_EVT_STATUS_VALID_MASK UINT64_C(0x0000000000000003)
+
+/**
+ * Guest Virtual-APIC Log Base Address Register (MMIO).
+ * In accordance with the AMD spec.
+ */
+typedef union
+{
+ struct
+ {
+ RT_GCC_EXTENSION uint64_t u12Rsvd0 : 12; /**< Bit 11:0 - Reserved. */
+ RT_GCC_EXTENSION uint64_t u40Base : 40; /**< Bits 51:12 - GALogBase: Guest Virtual-APIC Log Base Address. */
+ RT_GCC_EXTENSION uint64_t u4Rsvd0 : 4; /**< Bits 55:52 - Reserved. */
+ RT_GCC_EXTENSION uint64_t u4Len : 4; /**< Bits 59:56 - GALogLen: Guest Virtual-APIC Log Length. */
+ RT_GCC_EXTENSION uint64_t u4Rsvd1 : 4; /**< Bits 63:60 - Reserved. */
+ } n;
+ /** The 64-bit unsigned integer view. */
+ uint64_t u64;
+} GALOG_BAR_T;
+AssertCompileSize(GALOG_BAR_T, 8);
+
+/**
+ * Guest Virtual-APIC Log Tail Address Register (MMIO).
+ * In accordance with the AMD spec.
+ */
+typedef union
+{
+ struct
+ {
+ RT_GCC_EXTENSION uint64_t u3Rsvd0 : 3; /**< Bits 2:0 - Reserved. */
+ RT_GCC_EXTENSION uint64_t u40GALogTailAddr : 48; /**< Bits 51:3 - GATAddr: Guest Virtual-APIC Tail Log Address. */
+ RT_GCC_EXTENSION uint64_t u11Rsvd1 : 11; /**< Bits 63:52 - Reserved. */
+ } n;
+ /** The 64-bit unsigned integer view. */
+ uint64_t u64;
+} GALOG_TAIL_ADDR_T;
+AssertCompileSize(GALOG_TAIL_ADDR_T, 8);
+
+/**
+ * PPR Log B Base Address Register (MMIO).
+ * In accordance with the AMD spec.
+ * Currently identical to PPR_LOG_BAR_T.
+ */
+typedef PPR_LOG_BAR_T PPR_LOG_B_BAR_T;
+
+/**
+ * Event Log B Base Address Register (MMIO).
+ * In accordance with the AMD spec.
+ * Currently identical to EVT_LOG_BAR_T.
+ */
+typedef EVT_LOG_BAR_T EVT_LOG_B_BAR_T;
+
+/**
+ * Device-specific Feature Extension (DSFX) Register (MMIO).
+ * In accordance with the AMD spec.
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t u24DevSpecFeat : 24; /**< Bits 23:0 - DevSpecificFeatSupp: Implementation specific features. */
+ uint32_t u4RevMinor : 4; /**< Bits 27:24 - RevMinor: Minor revision identifier. */
+ uint32_t u4RevMajor : 4; /**< Bits 31:28 - RevMajor: Major revision identifier. */
+ uint32_t u32Rsvd0; /**< Bits 63:32 - Reserved.*/
+ } n;
+ /** The 64-bit unsigned integer view. */
+ uint64_t u64;
+} DEV_SPECIFIC_FEAT_T;
+AssertCompileSize(DEV_SPECIFIC_FEAT_T, 8);
+
+/**
+ * Device-specific Control Extension (DSCX) Register (MMIO).
+ * In accordance with the AMD spec.
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t u24DevSpecCtrl : 24; /**< Bits 23:0 - DevSpecificFeatCntrl: Implementation specific control. */
+ uint32_t u4RevMinor : 4; /**< Bits 27:24 - RevMinor: Minor revision identifier. */
+ uint32_t u4RevMajor : 4; /**< Bits 31:28 - RevMajor: Major revision identifier. */
+ uint32_t u32Rsvd0; /**< Bits 63:32 - Reserved.*/
+ } n;
+ /** The 64-bit unsigned integer view. */
+ uint64_t u64;
+} DEV_SPECIFIC_CTRL_T;
+AssertCompileSize(DEV_SPECIFIC_CTRL_T, 8);
+
+/**
+ * Device-specific Status Extension (DSSX) Register (MMIO).
+ * In accordance with the AMD spec.
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t u24DevSpecStatus : 24; /**< Bits 23:0 - DevSpecificFeatStatus: Implementation specific status. */
+ uint32_t u4RevMinor : 4; /**< Bits 27:24 - RevMinor: Minor revision identifier. */
+ uint32_t u4RevMajor : 4; /**< Bits 31:28 - RevMajor: Major revision identifier. */
+ uint32_t u32Rsvd0; /**< Bits 63:32 - Reserved.*/
+ } n;
+ /** The 64-bit unsigned integer view. */
+ uint64_t u64;
+} DEV_SPECIFIC_STATUS_T;
+AssertCompileSize(DEV_SPECIFIC_STATUS_T, 8);
+
+/**
+ * MSI Information Register 0 and 1 (PCI) / MSI Vector Register 0 and 1 (MMIO).
+ * In accordance with the AMD spec.
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t u5MsiNumEvtLog : 5; /**< Bits 4:0 - MsiNum: Event Log MSI message number. */
+ uint32_t u3GstVirtAddrSize: 3; /**< Bits 7:5 - GVAsize: Guest Virtual Address Size. */
+ uint32_t u7PhysAddrSize : 7; /**< Bits 14:8 - PAsize: Physical Address Size. */
+ uint32_t u7VirtAddrSize : 7; /**< Bits 21:15 - VAsize: Virtual Address Size. */
+ uint32_t u1HtAtsResv: 1; /**< Bit 22 - HtAtsResv: HyperTransport ATS Response Address range Reserved. */
+ uint32_t u4Rsvd0 : 4; /**< Bits 26:23 - Reserved. */
+ uint32_t u5MsiNumPpr : 5; /**< Bits 31:27 - MsiNumPPR: Peripheral Page Request MSI message number. */
+ uint32_t u5MsiNumGa : 5; /**< Bits 36:32 - MsiNumGa: MSI message number for guest virtual-APIC log. */
+ uint32_t u27Rsvd0: 27; /**< Bits 63:37 - Reserved. */
+ } n;
+ /** The 32-bit unsigned integer view. */
+ uint32_t au32[2];
+ /** The 64-bit unsigned integer view. */
+ uint64_t u64;
+} MSI_MISC_INFO_T;
+AssertCompileSize(MSI_MISC_INFO_T, 8);
+/** MSI Vector Register 0 and 1 (MMIO). */
+typedef MSI_MISC_INFO_T MSI_VECTOR_T;
+/** Mask of valid bits in MSI Vector Register 1 (or high dword of MSI Misc.
+ * info). */
+#define IOMMU_MSI_VECTOR_1_VALID_MASK UINT32_C(0x1f)
+
+/**
+ * MSI Capability Header Register (PCI + MMIO).
+ * In accordance with the AMD spec.
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t u8MsiCapId : 8; /**< Bits 7:0 - MsiCapId: Capability ID. */
+ uint32_t u8MsiCapPtr : 8; /**< Bits 15:8 - MsiCapPtr: Pointer (PCI config offset) to the next capability. */
+ uint32_t u1MsiEnable : 1; /**< Bit 16 - MsiEn: Message Signal Interrupt Enable. */
+ uint32_t u3MsiMultiMessCap : 3; /**< Bits 19:17 - MsiMultMessCap: MSI Multi-Message Capability. */
+ uint32_t u3MsiMultiMessEn : 3; /**< Bits 22:20 - MsiMultMessEn: MSI Multi-Message Enable. */
+ uint32_t u1Msi64BitEn : 1; /**< Bit 23 - Msi64BitEn: MSI 64-bit Enable. */
+ uint32_t u8Rsvd0 : 8; /**< Bits 31:24 - Reserved. */
+ } n;
+ /** The 32-bit unsigned integer view. */
+ uint32_t u32;
+} MSI_CAP_HDR_T;
+AssertCompileSize(MSI_CAP_HDR_T, 4);
+#define IOMMU_MSI_CAP_HDR_MSI_EN_MASK RT_BIT(16)
+
+/**
+ * MSI Mapping Capability Header Register (PCI + MMIO).
+ * In accordance with the AMD spec.
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t u8MsiMapCapId : 8; /**< Bits 7:0 - MsiMapCapId: MSI Map capability ID. */
+ uint32_t u8Rsvd0 : 8; /**< Bits 15:8 - Reserved. */
+ uint32_t u1MsiMapEn : 1; /**< Bit 16 - MsiMapEn: MSI Map enable. */
+ uint32_t u1MsiMapFixed : 1; /**< Bit 17 - MsiMapFixd: MSI Map fixed. */
+ uint32_t u9Rsvd0 : 9; /**< Bits 26:18 - Reserved. */
+ uint32_t u5MapCapType : 5; /**< Bits 31:27 - MsiMapCapType: MSI Mapping capability type. */
+ } n;
+ /** The 32-bit unsigned integer view. */
+ uint32_t u32;
+} MSI_MAP_CAP_HDR_T;
+AssertCompileSize(MSI_MAP_CAP_HDR_T, 4);
+
+/**
+ * Performance Optimization Control Register (MMIO).
+ * In accordance with the AMD spec.
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t u13Rsvd0 : 13; /**< Bits 12:0 - Reserved. */
+ uint32_t u1PerfOptEn : 1; /**< Bit 13 - PerfOptEn: Performance Optimization Enable. */
+ uint32_t u17Rsvd0 : 18; /**< Bits 31:14 - Reserved. */
+ } n;
+ /** The 32-bit unsigned integer view. */
+ uint32_t u32;
+} IOMMU_PERF_OPT_CTRL_T;
+AssertCompileSize(IOMMU_PERF_OPT_CTRL_T, 4);
+
+/**
+ * XT (x2APIC) IOMMU General Interrupt Control Register (MMIO).
+ * In accordance with the AMD spec.
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t u2Rsvd0 : 2; /**< Bits 1:0 - Reserved.*/
+ uint32_t u1X2ApicIntrDstMode : 1; /**< Bit 2 - Destination Mode for general interrupt.*/
+ uint32_t u4Rsvd0 : 4; /**< Bits 7:3 - Reserved.*/
+ uint32_t u24X2ApicIntrDstLo : 24; /**< Bits 31:8 - Destination for general interrupt (Lo).*/
+ uint32_t u8X2ApicIntrVector : 8; /**< Bits 39:32 - Vector for general interrupt.*/
+ uint32_t u1X2ApicIntrDeliveryMode : 1; /**< Bit 40 - Delivery Mode for general interrupt.*/
+ uint32_t u15Rsvd0 : 15; /**< Bits 55:41 - Reserved.*/
+ uint32_t u7X2ApicIntrDstHi : 7; /**< Bits 63:56 - Destination for general interrupt (Hi) .*/
+ } n;
+ /** The 64-bit unsigned integer view. */
+ uint64_t u64;
+} IOMMU_XT_GEN_INTR_CTRL_T;
+AssertCompileSize(IOMMU_XT_GEN_INTR_CTRL_T, 8);
+
+/**
+ * XT (x2APIC) IOMMU General Interrupt Control Register (MMIO).
+ * In accordance with the AMD spec.
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t u2Rsvd0 : 2; /**< Bits 1:0 - Reserved.*/
+ uint32_t u1X2ApicIntrDstMode : 1; /**< Bit 2 - Destination Mode for the interrupt.*/
+ uint32_t u4Rsvd0 : 4; /**< Bits 7:3 - Reserved.*/
+ uint32_t u24X2ApicIntrDstLo : 24; /**< Bits 31:8 - Destination for the interrupt (Lo).*/
+ uint32_t u8X2ApicIntrVector : 8; /**< Bits 39:32 - Vector for the interrupt.*/
+ uint32_t u1X2ApicIntrDeliveryMode : 1; /**< Bit 40 - Delivery Mode for the interrupt.*/
+ uint32_t u15Rsvd0 : 15; /**< Bits 55:41 - Reserved.*/
+ uint32_t u7X2ApicIntrDstHi : 7; /**< Bits 63:56 - Destination for the interrupt (Hi) .*/
+ } n;
+ /** The 64-bit unsigned integer view. */
+ uint64_t u64;
+} IOMMU_XT_INTR_CTRL_T;
+AssertCompileSize(IOMMU_XT_INTR_CTRL_T, 8);
+
+/**
+ * XT (x2APIC) IOMMU PPR Interrupt Control Register (MMIO).
+ * In accordance with the AMD spec.
+ * Currently identical to IOMMU_XT_INTR_CTRL_T.
+ */
+typedef IOMMU_XT_INTR_CTRL_T IOMMU_XT_PPR_INTR_CTRL_T;
+
+/**
+ * XT (x2APIC) IOMMU GA (Guest Address) Log Control Register (MMIO).
+ * In accordance with the AMD spec.
+ * Currently identical to IOMMU_XT_INTR_CTRL_T.
+ */
+typedef IOMMU_XT_INTR_CTRL_T IOMMU_XT_GALOG_INTR_CTRL_T;
+
+/**
+ * Memory Access and Routing Control (MARC) Aperture Base Register (MMIO).
+ * In accordance with the AMD spec.
+ */
+typedef union
+{
+ struct
+ {
+ RT_GCC_EXTENSION uint64_t u12Rsvd0 : 12; /**< Bits 11:0 - Reserved. */
+ RT_GCC_EXTENSION uint64_t u40MarcBaseAddr : 40; /**< Bits 51:12 - MarcBaseAddr: MARC Aperture Base Address. */
+ RT_GCC_EXTENSION uint64_t u12Rsvd1 : 12; /**< Bits 63:52 - Reserved. */
+ } n;
+ /** The 64-bit unsigned integer view. */
+ uint64_t u64;
+} MARC_APER_BAR_T;
+AssertCompileSize(MARC_APER_BAR_T, 8);
+
+/**
+ * Memory Access and Routing Control (MARC) Relocation Register (MMIO).
+ * In accordance with the AMD spec.
+ */
+typedef union
+{
+ struct
+ {
+ RT_GCC_EXTENSION uint64_t u1RelocEn : 1; /**< Bit 0 - RelocEn: Relocation Enabled. */
+ RT_GCC_EXTENSION uint64_t u1ReadOnly : 1; /**< Bit 1 - ReadOnly: Whether only read-only acceses allowed. */
+ RT_GCC_EXTENSION uint64_t u10Rsvd0 : 10; /**< Bits 11:2 - Reserved. */
+ RT_GCC_EXTENSION uint64_t u40MarcRelocAddr : 40; /**< Bits 51:12 - MarcRelocAddr: MARC Aperture Relocation Address. */
+ RT_GCC_EXTENSION uint64_t u12Rsvd1 : 12; /**< Bits 63:52 - Reserved. */
+ } n;
+ /** The 64-bit unsigned integer view. */
+ uint64_t u64;
+} MARC_APER_RELOC_T;
+AssertCompileSize(MARC_APER_RELOC_T, 8);
+
+/**
+ * Memory Access and Routing Control (MARC) Length Register (MMIO).
+ * In accordance with the AMD spec.
+ */
+typedef union
+{
+ struct
+ {
+ RT_GCC_EXTENSION uint64_t u12Rsvd0 : 12; /**< Bits 11:0 - Reserved. */
+ RT_GCC_EXTENSION uint64_t u40MarcLength : 40; /**< Bits 51:12 - MarcLength: MARC Aperture Length. */
+ RT_GCC_EXTENSION uint64_t u12Rsvd1 : 12; /**< Bits 63:52 - Reserved. */
+ } n;
+ /** The 64-bit unsigned integer view. */
+ uint64_t u64;
+} MARC_APER_LEN_T;
+
+/**
+ * Memory Access and Routing Control (MARC) Aperture Register.
+ * This combines other registers to match the MMIO layout for convenient access.
+ */
+typedef struct
+{
+ MARC_APER_BAR_T Base;
+ MARC_APER_RELOC_T Reloc;
+ MARC_APER_LEN_T Length;
+} MARC_APER_T;
+AssertCompileSize(MARC_APER_T, 24);
+
+/**
+ * IOMMU Reserved Register (MMIO).
+ * In accordance with the AMD spec.
+ * This register is reserved for hardware use (although RW?).
+ */
+typedef uint64_t IOMMU_RSVD_REG_T;
+
+/**
+ * Command Buffer Head Pointer Register (MMIO).
+ * In accordance with the AMD spec.
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t off; /**< Bits 31:0 - Buffer pointer (offset; 16 byte aligned, 512 KB max). */
+ uint32_t u32Rsvd0; /**< Bits 63:32 - Reserved. */
+ } n;
+ /** The 32-bit unsigned integer view. */
+ uint32_t au32[2];
+ /** The 64-bit unsigned integer view. */
+ uint64_t u64;
+} CMD_BUF_HEAD_PTR_T;
+AssertCompileSize(CMD_BUF_HEAD_PTR_T, 8);
+#define IOMMU_CMD_BUF_HEAD_PTR_VALID_MASK UINT64_C(0x000000000007fff0)
+
+/**
+ * Command Buffer Tail Pointer Register (MMIO).
+ * In accordance with the AMD spec.
+ * Currently identical to CMD_BUF_HEAD_PTR_T.
+ */
+typedef CMD_BUF_HEAD_PTR_T CMD_BUF_TAIL_PTR_T;
+#define IOMMU_CMD_BUF_TAIL_PTR_VALID_MASK IOMMU_CMD_BUF_HEAD_PTR_VALID_MASK
+
+/**
+ * Event Log Head Pointer Register (MMIO).
+ * In accordance with the AMD spec.
+ * Currently identical to CMD_BUF_HEAD_PTR_T.
+ */
+typedef CMD_BUF_HEAD_PTR_T EVT_LOG_HEAD_PTR_T;
+#define IOMMU_EVT_LOG_HEAD_PTR_VALID_MASK IOMMU_CMD_BUF_HEAD_PTR_VALID_MASK
+
+/**
+ * Event Log Tail Pointer Register (MMIO).
+ * In accordance with the AMD spec.
+ * Currently identical to CMD_BUF_HEAD_PTR_T.
+ */
+typedef CMD_BUF_HEAD_PTR_T EVT_LOG_TAIL_PTR_T;
+#define IOMMU_EVT_LOG_TAIL_PTR_VALID_MASK IOMMU_CMD_BUF_HEAD_PTR_VALID_MASK
+
+
+/**
+ * IOMMU Status Register (MMIO).
+ * In accordance with the AMD spec.
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t u1EvtOverflow : 1; /**< Bit 0 - EventOverflow: Event log overflow. */
+ uint32_t u1EvtLogIntr : 1; /**< Bit 1 - EventLogInt: Event log interrupt. */
+ uint32_t u1CompWaitIntr : 1; /**< Bit 2 - ComWaitInt: Completion wait interrupt . */
+ uint32_t u1EvtLogRunning : 1; /**< Bit 3 - EventLogRun: Event logging is running. */
+ uint32_t u1CmdBufRunning : 1; /**< Bit 4 - CmdBufRun: Command buffer is running. */
+ uint32_t u1PprOverflow : 1; /**< Bit 5 - PprOverflow: Peripheral Page Request Log (PPR) overflow. */
+ uint32_t u1PprIntr : 1; /**< Bit 6 - PprInt: PPR interrupt. */
+ uint32_t u1PprLogRunning : 1; /**< Bit 7 - PprLogRun: PPR logging is running. */
+ uint32_t u1GstLogRunning : 1; /**< Bit 8 - GALogRun: Guest virtual-APIC logging is running. */
+ uint32_t u1GstLogOverflow : 1; /**< Bit 9 - GALOverflow: Guest virtual-APIC log overflow. */
+ uint32_t u1GstLogIntr : 1; /**< Bit 10 - GAInt: Guest virtual-APIC log interrupt. */
+ uint32_t u1PprOverflowB : 1; /**< Bit 11 - PprOverflowB: PPR log B overflow. */
+ uint32_t u1PprLogActive : 1; /**< Bit 12 - PprLogActive: PPR log A is active. */
+ uint32_t u2Rsvd0 : 2; /**< Bits 14:13 - Reserved. */
+ uint32_t u1EvtOverflowB : 1; /**< Bit 15 - EvtOverflowB: Event log B overflow. */
+ uint32_t u1EvtLogActive : 1; /**< Bit 16 - EvtLogActive: Event log A active. */
+ uint32_t u1PprOverflowEarlyB : 1; /**< Bit 17 - PprOverflowEarlyB: PPR log B overflow early warning. */
+ uint32_t u1PprOverflowEarly : 1; /**< Bit 18 - PprOverflowEarly: PPR log overflow early warning. */
+ uint32_t u13Rsvd0 : 13; /**< Bits 31:19 - Reserved. */
+ uint32_t u32Rsvd0; /**< Bits 63:32 - Reserved . */
+ } n;
+ /** The 32-bit unsigned integer view. */
+ uint32_t au32[2];
+ /** The 64-bit unsigned integer view. */
+ uint64_t u64;
+} IOMMU_STATUS_T;
+AssertCompileSize(IOMMU_STATUS_T, 8);
+#define IOMMU_STATUS_VALID_MASK UINT64_C(0x0000000000079fff)
+#define IOMMU_STATUS_RW1C_MASK UINT64_C(0x0000000000068e67)
+
+/**
+ * PPR Log Head Pointer Register (MMIO).
+ * In accordance with the AMD spec.
+ * Currently identical to CMD_BUF_HEAD_PTR_T.
+ */
+typedef CMD_BUF_HEAD_PTR_T PPR_LOG_HEAD_PTR_T;
+
+/**
+ * PPR Log Tail Pointer Register (MMIO).
+ * In accordance with the AMD spec.
+ * Currently identical to CMD_BUF_HEAD_PTR_T.
+ */
+typedef CMD_BUF_HEAD_PTR_T PPR_LOG_TAIL_PTR_T;
+
+/**
+ * Guest Virtual-APIC Log Head Pointer Register (MMIO).
+ * In accordance with the AMD spec.
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t u2Rsvd0 : 2; /**< Bits 2:0 - Reserved. */
+ uint32_t u12GALogPtr : 12; /**< Bits 15:3 - Guest Virtual-APIC Log Head or Tail Pointer. */
+ uint32_t u16Rsvd0 : 16; /**< Bits 31:16 - Reserved. */
+ uint32_t u32Rsvd0; /**< Bits 63:32 - Reserved. */
+ } n;
+ /** The 32-bit unsigned integer view. */
+ uint32_t au32[2];
+ /** The 64-bit unsigned integer view. */
+ uint64_t u64;
+} GALOG_HEAD_PTR_T;
+AssertCompileSize(GALOG_HEAD_PTR_T, 8);
+
+/**
+ * Guest Virtual-APIC Log Tail Pointer Register (MMIO).
+ * In accordance with the AMD spec.
+ * Currently identical to GALOG_HEAD_PTR_T.
+ */
+typedef GALOG_HEAD_PTR_T GALOG_TAIL_PTR_T;
+
+/**
+ * PPR Log B Head Pointer Register (MMIO).
+ * In accordance with the AMD spec.
+ * Currently identical to CMD_BUF_HEAD_PTR_T.
+ */
+typedef CMD_BUF_HEAD_PTR_T PPR_LOG_B_HEAD_PTR_T;
+
+/**
+ * PPR Log B Tail Pointer Register (MMIO).
+ * In accordance with the AMD spec.
+ * Currently identical to CMD_BUF_HEAD_PTR_T.
+ */
+typedef CMD_BUF_HEAD_PTR_T PPR_LOG_B_TAIL_PTR_T;
+
+/**
+ * Event Log B Head Pointer Register (MMIO).
+ * In accordance with the AMD spec.
+ * Currently identical to CMD_BUF_HEAD_PTR_T.
+ */
+typedef CMD_BUF_HEAD_PTR_T EVT_LOG_B_HEAD_PTR_T;
+
+/**
+ * Event Log B Tail Pointer Register (MMIO).
+ * In accordance with the AMD spec.
+ * Currently identical to CMD_BUF_HEAD_PTR_T.
+ */
+typedef CMD_BUF_HEAD_PTR_T EVT_LOG_B_TAIL_PTR_T;
+
+/**
+ * PPR Log Auto Response Register (MMIO).
+ * In accordance with the AMD spec.
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t u4AutoRespCode : 4; /**< Bits 3:0 - PprAutoRespCode: PPR log Auto Response Code. */
+ uint32_t u1AutoRespMaskGen : 1; /**< Bit 4 - PprAutoRespMaskGn: PPR log Auto Response Mask Gen. */
+ uint32_t u27Rsvd0 : 27; /**< Bits 31:5 - Reserved. */
+ uint32_t u32Rsvd0; /**< Bits 63:32 - Reserved.*/
+ } n;
+ /** The 32-bit unsigned integer view. */
+ uint32_t au32[2];
+ /** The 64-bit unsigned integer view. */
+ uint64_t u64;
+} PPR_LOG_AUTO_RESP_T;
+AssertCompileSize(PPR_LOG_AUTO_RESP_T, 8);
+
+/**
+ * PPR Log Overflow Early Indicator Register (MMIO).
+ * In accordance with the AMD spec.
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t u15Threshold : 15; /**< Bits 14:0 - PprOvrflwEarlyThreshold: Overflow early indicator threshold. */
+ uint32_t u15Rsvd0 : 15; /**< Bits 29:15 - Reserved. */
+ uint32_t u1IntrEn : 1; /**< Bit 30 - PprOvrflwEarlyIntEn: Overflow early indicator interrupt enable. */
+ uint32_t u1Enable : 1; /**< Bit 31 - PprOvrflwEarlyEn: Overflow early indicator enable. */
+ uint32_t u32Rsvd0; /**< Bits 63:32 - Reserved. */
+ } n;
+ /** The 32-bit unsigned integer view. */
+ uint32_t au32[2];
+ /** The 64-bit unsigned integer view. */
+ uint64_t u64;
+} PPR_LOG_OVERFLOW_EARLY_T;
+AssertCompileSize(PPR_LOG_OVERFLOW_EARLY_T, 8);
+
+/**
+ * PPR Log B Overflow Early Indicator Register (MMIO).
+ * In accordance with the AMD spec.
+ * Currently identical to PPR_LOG_OVERFLOW_EARLY_T.
+ */
+typedef PPR_LOG_OVERFLOW_EARLY_T PPR_LOG_B_OVERFLOW_EARLY_T;
+
+/**
+ * ILLEGAL_DEV_TABLE_ENTRY Event Types.
+ * In accordance with the AMD spec.
+ */
+typedef enum EVT_ILLEGAL_DTE_TYPE_T
+{
+ kIllegalDteType_RsvdNotZero = 0,
+ kIllegalDteType_RsvdIntTabLen,
+ kIllegalDteType_RsvdIoCtl,
+ kIllegalDteType_RsvdIntCtl
+} EVT_ILLEGAL_DTE_TYPE_T;
+
+/**
+ * ILLEGAL_DEV_TABLE_ENTRY Event Types.
+ * In accordance with the AMD spec.
+ */
+typedef enum EVT_IO_PAGE_FAULT_TYPE_T
+{
+ /* Memory transaction. */
+ kIoPageFaultType_DteRsvdPagingMode = 0,
+ kIoPageFaultType_PteInvalidPageSize,
+ kIoPageFaultType_PteInvalidLvlEncoding,
+ kIoPageFaultType_SkippedLevelIovaNotZero,
+ kIoPageFaultType_PteRsvdNotZero,
+ kIoPageFaultType_PteValidNotSet,
+ kIoPageFaultType_DteTranslationDisabled,
+ kIoPageFaultType_PasidInvalidRange,
+ kIoPageFaultType_PermDenied,
+ kIoPageFaultType_UserSupervisor,
+ /* Interrupt remapping */
+ kIoPageFaultType_IrteAddrInvalid,
+ kIoPageFaultType_IrteRsvdNotZero,
+ kIoPageFaultType_IrteRemapEn,
+ kIoPageFaultType_IrteRsvdIntType,
+ kIoPageFaultType_IntrReqAborted,
+ kIoPageFaultType_IntrWithPasid,
+ kIoPageFaultType_SmiFilterMismatch,
+ /* Memory transaction or interrupt remapping. */
+ kIoPageFaultType_DevId_Invalid
+} EVT_IO_PAGE_FAULT_TYPE_T;
+
+/**
+ * IOTLB_INV_TIMEOUT Event Types.
+ * In accordance with the AMD spec.
+ */
+typedef enum EVT_IOTLB_INV_TIMEOUT_TYPE_T
+{
+ InvTimeoutType_NoResponse = 0
+} EVT_IOTLB_INV_TIMEOUT_TYPE_T;
+
+/**
+ * INVALID_DEVICE_REQUEST Event Types.
+ * In accordance with the AMD spec.
+ */
+typedef enum EVT_INVALID_DEV_REQ_TYPE_T
+{
+ /* Access. */
+ kInvalidDevReqType_ReadOrNonPostedWrite = 0,
+ kInvalidDevReqType_PretranslatedTransaction,
+ kInvalidDevReqType_PortIo,
+ kInvalidDevReqType_SysMgt,
+ kInvalidDevReqType_IntrRange,
+ kInvalidDevReqType_RsvdIntrRange,
+ kInvalidDevReqType_SysMgtAddr,
+ /* Translation Request. */
+ kInvalidDevReqType_TrAccessInvalid,
+ kInvalidDevReqType_TrDisabled,
+ kInvalidDevReqType_DevIdInvalid
+} EVT_INVALID_DEV_REQ_TYPE_T;
+
+/**
+ * INVALID_PPR_REQUEST Event Types.
+ * In accordance with the AMD spec.
+ */
+typedef enum EVT_INVALID_PPR_REQ_TYPE_T
+{
+ kInvalidPprReqType_PriNotSupported,
+ kInvalidPprReqType_GstTranslateDisabled
+} EVT_INVALID_PPR_REQ_TYPE_T;
+
+
+/** @name IVRS format revision field.
+ * In accordance with the AMD spec.
+ * @{ */
+/** Fixed: Supports only pre-assigned device IDs and type 10h and 11h IVHD
+ * blocks. */
+#define ACPI_IVRS_FMT_REV_FIXED 0x1
+/** Mixed: Supports pre-assigned and ACPI HID device naming and all IVHD blocks. */
+#define ACPI_IVRS_FMT_REV_MIXED 0x2
+/** @} */
+
+/** @name IVHD special device entry variety field.
+ * In accordance with the AMD spec.
+ * @{ */
+/** I/O APIC. */
+#define ACPI_IVHD_VARIETY_IOAPIC 0x1
+/** HPET. */
+#define ACPI_IVHD_VARIETY_HPET 0x2
+/** @} */
+
+/** @name IVHD device entry type codes.
+ * In accordance with the AMD spec.
+ * @{ */
+/** Reserved. */
+#define ACPI_IVHD_DEVENTRY_TYPE_RSVD 0x0
+/** All: DTE setting applies to all Device IDs. */
+#define ACPI_IVHD_DEVENTRY_TYPE_ALL 0x1
+/** Select: DTE setting applies to the device specified in DevId field. */
+#define ACPI_IVHD_DEVENTRY_TYPE_SELECT 0x2
+/** Start of range: DTE setting applies to all devices from start of range specified
+ * by the DevId field. */
+#define ACPI_IVHD_DEVENTRY_TYPE_START_RANGE 0x3
+/** End of range: DTE setting from previous type 3 entry applies to all devices
+ * incl. DevId specified by this entry. */
+#define ACPI_IVHD_DEVENTRY_TYPE_END_RANGE 0x4
+/** @} */
+
+/** @name IVHD DTE (Device Table Entry) Settings.
+ * In accordance with the AMD spec.
+ * @{ */
+/** INITPass: Identifies a device able to assert INIT interrupts. */
+#define ACPI_IVHD_DTE_INIT_PASS_SHIFT 0
+#define ACPI_IVHD_DTE_INIT_PASS_MASK UINT8_C(0x01)
+/** EIntPass: Identifies a device able to assert ExtInt interrupts. */
+#define ACPI_IVHD_DTE_EXTINT_PASS_SHIFT 1
+#define ACPI_IVHD_DTE_EXTINT_PASS_MASK UINT8_C(0x02)
+/** NMIPass: Identifies a device able to assert NMI interrupts. */
+#define ACPI_IVHD_DTE_NMI_PASS_SHIFT 2
+#define ACPI_IVHD_DTE_NMI_PASS_MASK UINT8_C(0x04)
+/** Bit 3 reserved. */
+#define ACPI_IVHD_DTE_RSVD_3_SHIFT 3
+#define ACPI_IVHD_DTE_RSVD_3_MASK UINT8_C(0x08)
+/** SysMgt: Identifies a device able to assert system management messages. */
+#define ACPI_IVHD_DTE_SYS_MGT_SHIFT 4
+#define ACPI_IVHD_DTE_SYS_MGT_MASK UINT8_C(0x30)
+/** Lint0Pass: Identifies a device able to assert LINT0 interrupts. */
+#define ACPI_IVHD_DTE_LINT0_PASS_SHIFT 6
+#define ACPI_IVHD_DTE_LINT0_PASS_MASK UINT8_C(0x40)
+/** Lint0Pass: Identifies a device able to assert LINT1 interrupts. */
+#define ACPI_IVHD_DTE_LINT1_PASS_SHIFT 7
+#define ACPI_IVHD_DTE_LINT1_PASS_MASK UINT8_C(0x80)
+RT_BF_ASSERT_COMPILE_CHECKS(ACPI_IVHD_DTE_, UINT8_C(0), UINT8_MAX,
+ (INIT_PASS, EXTINT_PASS, NMI_PASS, RSVD_3, SYS_MGT, LINT0_PASS, LINT1_PASS));
+/** @} */
+
+/**
+ * AMD IOMMU: IVHD (I/O Virtualization Hardware Definition) Device Entry (4-byte).
+ * In accordance with the AMD spec.
+ */
+#pragma pack(1)
+typedef struct ACPIIVHDDEVENTRY4
+{
+ uint8_t u8DevEntryType; /**< Device entry type. */
+ uint16_t u16DevId; /**< Device ID. */
+ uint8_t u8DteSetting; /**< DTE (Device Table Entry) setting. */
+} ACPIIVHDDEVENTRY4;
+#pragma pack()
+AssertCompileSize(ACPIIVHDDEVENTRY4, 4);
+
+/**
+ * AMD IOMMU: IVHD (I/O Virtualization Hardware Definition) Device Entry (8-byte).
+ * In accordance with the AMD spec.
+ */
+#pragma pack(1)
+typedef struct ACPIIVHDDEVENTRY8
+{
+ uint8_t u8DevEntryType; /**< Device entry type. */
+ union
+ {
+ /** Reserved: When u8DevEntryType is 0x40, 0x41, 0x44 or 0x45 (or 0x49-0x7F). */
+ struct
+ {
+ uint8_t au8Rsvd0[7]; /**< Reserved (MBZ). */
+ } rsvd;
+ /** Alias Select: When u8DevEntryType is 0x42 or 0x43. */
+ struct
+ {
+ uint16_t u16DevIdA; /**< Device ID A. */
+ uint8_t u8DteSetting; /**< DTE (Device Table Entry) setting. */
+ uint8_t u8Rsvd0; /**< Reserved (MBZ). */
+ uint16_t u16DevIdB; /**< Device ID B. */
+ uint8_t u8Rsvd1; /**< Reserved (MBZ). */
+ } alias;
+ /** Extended Select: When u8DevEntryType is 0x46 or 0x47. */
+ struct
+ {
+ uint16_t u16DevId; /**< Device ID. */
+ uint8_t u8DteSetting; /**< DTE (Device Table Entry) setting. */
+ uint32_t u32ExtDteSetting; /**< Extended DTE setting. */
+ } ext;
+ /** Special Device: When u8DevEntryType is 0x48. */
+ struct
+ {
+ uint16_t u16Rsvd0; /**< Reserved (MBZ). */
+ uint8_t u8DteSetting; /**< DTE (Device Table Entry) setting. */
+ uint8_t u8Handle; /**< Handle contains I/O APIC ID or HPET number. */
+ uint16_t u16DevIdB; /**< Device ID B (I/O APIC or HPET). */
+ uint8_t u8Variety; /**< Whether this is the HPET or I/O APIC. */
+ } special;
+ } u;
+} ACPIIVHDDEVENTRY8;
+#pragma pack()
+AssertCompileSize(ACPIIVHDDEVENTRY8, 8);
+
+/** @name IVHD Type 10h Flags.
+ * In accordance with the AMD spec.
+ * @{ */
+/** Peripheral page request support. */
+#define ACPI_IVHD_10H_F_PPR_SUP RT_BIT(7)
+/** Prefetch IOMMU pages command support. */
+#define ACPI_IVHD_10H_F_PREF_SUP RT_BIT(6)
+/** Coherent control. */
+#define ACPI_IVHD_10H_F_COHERENT RT_BIT(5)
+/** Remote IOTLB support. */
+#define ACPI_IVHD_10H_F_IOTLB_SUP RT_BIT(4)
+/** Isochronous control. */
+#define ACPI_IVHD_10H_F_ISOC RT_BIT(3)
+/** Response Pass Posted Write. */
+#define ACPI_IVHD_10H_F_RES_PASS_PW RT_BIT(2)
+/** Pass Posted Write. */
+#define ACPI_IVHD_10H_F_PASS_PW RT_BIT(1)
+/** HyperTransport Tunnel. */
+#define ACPI_IVHD_10H_F_HT_TUNNEL RT_BIT(0)
+/** @} */
+
+/** @name IVRS IVinfo field.
+ * In accordance with the AMD spec.
+ * @{ */
+/** EFRSup: Extended Feature Support. */
+#define ACPI_IVINFO_BF_EFR_SUP_SHIFT 0
+#define ACPI_IVINFO_BF_EFR_SUP_MASK UINT32_C(0x00000001)
+/** DMA Remap Sup: DMA remapping support (pre-boot DMA protection with
+ * mandatory remapping of device accessed memory). */
+#define ACPI_IVINFO_BF_DMA_REMAP_SUP_SHIFT 1
+#define ACPI_IVINFO_BF_DMA_REMAP_SUP_MASK UINT32_C(0x00000002)
+/** Bits 4:2 reserved. */
+#define ACPI_IVINFO_BF_RSVD_2_4_SHIFT 2
+#define ACPI_IVINFO_BF_RSVD_2_4_MASK UINT32_C(0x0000001c)
+/** GVASize: Guest virtual-address size. */
+#define ACPI_IVINFO_BF_GVA_SIZE_SHIFT 5
+#define ACPI_IVINFO_BF_GVA_SIZE_MASK UINT32_C(0x000000e0)
+/** PASize: System physical address size. */
+#define ACPI_IVINFO_BF_PA_SIZE_SHIFT 8
+#define ACPI_IVINFO_BF_PA_SIZE_MASK UINT32_C(0x00007f00)
+/** VASize: Virtual address size. */
+#define ACPI_IVINFO_BF_VA_SIZE_SHIFT 15
+#define ACPI_IVINFO_BF_VA_SIZE_MASK UINT32_C(0x003f8000)
+/** HTAtsResv: HyperTransport ATS-response address translation range reserved. */
+#define ACPI_IVINFO_BF_HT_ATS_RESV_SHIFT 22
+#define ACPI_IVINFO_BF_HT_ATS_RESV_MASK UINT32_C(0x00400000)
+/** Bits 31:23 reserved. */
+#define ACPI_IVINFO_BF_RSVD_23_31_SHIFT 23
+#define ACPI_IVINFO_BF_RSVD_23_31_MASK UINT32_C(0xff800000)
+RT_BF_ASSERT_COMPILE_CHECKS(ACPI_IVINFO_BF_, UINT32_C(0), UINT32_MAX,
+ (EFR_SUP, DMA_REMAP_SUP, RSVD_2_4, GVA_SIZE, PA_SIZE, VA_SIZE, HT_ATS_RESV, RSVD_23_31));
+/** @} */
+
+/** @name IVHD IOMMU info flags.
+ * In accordance with the AMD spec.
+ * @{ */
+/** MSI message number for the event log. */
+#define ACPI_IOMMU_INFO_BF_MSI_NUM_SHIFT 0
+#define ACPI_IOMMU_INFO_BF_MSI_NUM_MASK UINT16_C(0x001f)
+/** Bits 7:5 reserved. */
+#define ACPI_IOMMU_INFO_BF_RSVD_5_7_SHIFT 5
+#define ACPI_IOMMU_INFO_BF_RSVD_5_7_MASK UINT16_C(0x00e0)
+/** IOMMU HyperTransport Unit ID number. */
+#define ACPI_IOMMU_INFO_BF_UNIT_ID_SHIFT 8
+#define ACPI_IOMMU_INFO_BF_UNIT_ID_MASK UINT16_C(0x1f00)
+/** Bits 15:13 reserved. */
+#define ACPI_IOMMU_INFO_BF_RSVD_13_15_SHIFT 13
+#define ACPI_IOMMU_INFO_BF_RSVD_13_15_MASK UINT16_C(0xe000)
+RT_BF_ASSERT_COMPILE_CHECKS(ACPI_IOMMU_INFO_BF_, UINT16_C(0), UINT16_MAX,
+ (MSI_NUM, RSVD_5_7, UNIT_ID, RSVD_13_15));
+/** @} */
+
+/** @name IVHD IOMMU feature reporting field.
+ * In accordance with the AMD spec.
+ * @{ */
+/** x2APIC supported for peripherals. */
+#define ACPI_IOMMU_FEAT_BF_XT_SUP_SHIFT 0
+#define ACPI_IOMMU_FEAT_BF_XT_SUP_MASK UINT32_C(0x00000001)
+/** NX supported for I/O. */
+#define ACPI_IOMMU_FEAT_BF_NX_SUP_SHIFT 1
+#define ACPI_IOMMU_FEAT_BF_NX_SUP_MASK UINT32_C(0x00000002)
+/** GT (Guest Translation) supported. */
+#define ACPI_IOMMU_FEAT_BF_GT_SUP_SHIFT 2
+#define ACPI_IOMMU_FEAT_BF_GT_SUP_MASK UINT32_C(0x00000004)
+/** GLX (Number of guest CR3 tables) supported. */
+#define ACPI_IOMMU_FEAT_BF_GLX_SUP_SHIFT 3
+#define ACPI_IOMMU_FEAT_BF_GLX_SUP_MASK UINT32_C(0x00000018)
+/** IA (INVALIDATE_IOMMU_ALL) command supported. */
+#define ACPI_IOMMU_FEAT_BF_IA_SUP_SHIFT 5
+#define ACPI_IOMMU_FEAT_BF_IA_SUP_MASK UINT32_C(0x00000020)
+/** GA (Guest virtual APIC) supported. */
+#define ACPI_IOMMU_FEAT_BF_GA_SUP_SHIFT 6
+#define ACPI_IOMMU_FEAT_BF_GA_SUP_MASK UINT32_C(0x00000040)
+/** HE (Hardware error) registers supported. */
+#define ACPI_IOMMU_FEAT_BF_HE_SUP_SHIFT 7
+#define ACPI_IOMMU_FEAT_BF_HE_SUP_MASK UINT32_C(0x00000080)
+/** PASMax (maximum PASID) supported. Ignored if PPRSup=0. */
+#define ACPI_IOMMU_FEAT_BF_PAS_MAX_SHIFT 8
+#define ACPI_IOMMU_FEAT_BF_PAS_MAX_MASK UINT32_C(0x00001f00)
+/** PNCounters (Number of performance counters per counter bank) supported. */
+#define ACPI_IOMMU_FEAT_BF_PN_COUNTERS_SHIFT 13
+#define ACPI_IOMMU_FEAT_BF_PN_COUNTERS_MASK UINT32_C(0x0001e000)
+/** PNBanks (Number of performance counter banks) supported. */
+#define ACPI_IOMMU_FEAT_BF_PN_BANKS_SHIFT 17
+#define ACPI_IOMMU_FEAT_BF_PN_BANKS_MASK UINT32_C(0x007e0000)
+/** MSINumPPR (MSI number for peripheral page requests). */
+#define ACPI_IOMMU_FEAT_BF_MSI_NUM_PPR_SHIFT 23
+#define ACPI_IOMMU_FEAT_BF_MSI_NUM_PPR_MASK UINT32_C(0x0f800000)
+/** GATS (Guest address translation size). MBZ when GTSup=0. */
+#define ACPI_IOMMU_FEAT_BF_GATS_SHIFT 28
+#define ACPI_IOMMU_FEAT_BF_GATS_MASK UINT32_C(0x30000000)
+/** HATS (Host address translation size). */
+#define ACPI_IOMMU_FEAT_BF_HATS_SHIFT 30
+#define ACPI_IOMMU_FEAT_BF_HATS_MASK UINT32_C(0xc0000000)
+RT_BF_ASSERT_COMPILE_CHECKS(ACPI_IOMMU_FEAT_BF_, UINT32_C(0), UINT32_MAX,
+ (XT_SUP, NX_SUP, GT_SUP, GLX_SUP, IA_SUP, GA_SUP, HE_SUP, PAS_MAX, PN_COUNTERS, PN_BANKS,
+ MSI_NUM_PPR, GATS, HATS));
+/** @} */
+
+/** @name IOMMU Extended Feature Register (PCI/MMIO/ACPI).
+ * In accordance with the AMD spec.
+ * @{ */
+/** PreFSup: Prefetch support (RO). */
+#define IOMMU_EXT_FEAT_BF_PREF_SUP_SHIFT 0
+#define IOMMU_EXT_FEAT_BF_PREF_SUP_MASK UINT64_C(0x0000000000000001)
+/** PPRSup: Peripheral Page Request (PPR) support (RO). */
+#define IOMMU_EXT_FEAT_BF_PPR_SUP_SHIFT 1
+#define IOMMU_EXT_FEAT_BF_PPR_SUP_MASK UINT64_C(0x0000000000000002)
+/** XTSup: x2APIC support (RO). */
+#define IOMMU_EXT_FEAT_BF_X2APIC_SUP_SHIFT 2
+#define IOMMU_EXT_FEAT_BF_X2APIC_SUP_MASK UINT64_C(0x0000000000000004)
+/** NXSup: No Execute (PMR and PRIV) support (RO). */
+#define IOMMU_EXT_FEAT_BF_NO_EXEC_SUP_SHIFT 3
+#define IOMMU_EXT_FEAT_BF_NO_EXEC_SUP_MASK UINT64_C(0x0000000000000008)
+/** GTSup: Guest Translation support (RO). */
+#define IOMMU_EXT_FEAT_BF_GT_SUP_SHIFT 4
+#define IOMMU_EXT_FEAT_BF_GT_SUP_MASK UINT64_C(0x0000000000000010)
+/** Bit 5 reserved. */
+#define IOMMU_EXT_FEAT_BF_RSVD_5_SHIFT 5
+#define IOMMU_EXT_FEAT_BF_RSVD_5_MASK UINT64_C(0x0000000000000020)
+/** IASup: INVALIDATE_IOMMU_ALL command support (RO). */
+#define IOMMU_EXT_FEAT_BF_IA_SUP_SHIFT 6
+#define IOMMU_EXT_FEAT_BF_IA_SUP_MASK UINT64_C(0x0000000000000040)
+/** GASup: Guest virtual-APIC support (RO). */
+#define IOMMU_EXT_FEAT_BF_GA_SUP_SHIFT 7
+#define IOMMU_EXT_FEAT_BF_GA_SUP_MASK UINT64_C(0x0000000000000080)
+/** HESup: Hardware error registers support (RO). */
+#define IOMMU_EXT_FEAT_BF_HE_SUP_SHIFT 8
+#define IOMMU_EXT_FEAT_BF_HE_SUP_MASK UINT64_C(0x0000000000000100)
+/** PCSup: Performance counters support (RO). */
+#define IOMMU_EXT_FEAT_BF_PC_SUP_SHIFT 9
+#define IOMMU_EXT_FEAT_BF_PC_SUP_MASK UINT64_C(0x0000000000000200)
+/** HATS: Host Address Translation Size (RO). */
+#define IOMMU_EXT_FEAT_BF_HATS_SHIFT 10
+#define IOMMU_EXT_FEAT_BF_HATS_MASK UINT64_C(0x0000000000000c00)
+/** GATS: Guest Address Translation Size (RO). */
+#define IOMMU_EXT_FEAT_BF_GATS_SHIFT 12
+#define IOMMU_EXT_FEAT_BF_GATS_MASK UINT64_C(0x0000000000003000)
+/** GLXSup: Guest CR3 root table level support (RO). */
+#define IOMMU_EXT_FEAT_BF_GLX_SUP_SHIFT 14
+#define IOMMU_EXT_FEAT_BF_GLX_SUP_MASK UINT64_C(0x000000000000c000)
+/** SmiFSup: SMI filter register support (RO). */
+#define IOMMU_EXT_FEAT_BF_SMI_FLT_SUP_SHIFT 16
+#define IOMMU_EXT_FEAT_BF_SMI_FLT_SUP_MASK UINT64_C(0x0000000000030000)
+/** SmiFRC: SMI filter register count (RO). */
+#define IOMMU_EXT_FEAT_BF_SMI_FLT_REG_CNT_SHIFT 18
+#define IOMMU_EXT_FEAT_BF_SMI_FLT_REG_CNT_MASK UINT64_C(0x00000000001c0000)
+/** GAMSup: Guest virtual-APIC modes support (RO). */
+#define IOMMU_EXT_FEAT_BF_GAM_SUP_SHIFT 21
+#define IOMMU_EXT_FEAT_BF_GAM_SUP_MASK UINT64_C(0x0000000000e00000)
+/** DualPprLogSup: Dual PPR Log support (RO). */
+#define IOMMU_EXT_FEAT_BF_DUAL_PPR_LOG_SUP_SHIFT 24
+#define IOMMU_EXT_FEAT_BF_DUAL_PPR_LOG_SUP_MASK UINT64_C(0x0000000003000000)
+/** Bits 27:26 reserved. */
+#define IOMMU_EXT_FEAT_BF_RSVD_26_27_SHIFT 26
+#define IOMMU_EXT_FEAT_BF_RSVD_26_27_MASK UINT64_C(0x000000000c000000)
+/** DualEventLogSup: Dual Event Log support (RO). */
+#define IOMMU_EXT_FEAT_BF_DUAL_EVT_LOG_SUP_SHIFT 28
+#define IOMMU_EXT_FEAT_BF_DUAL_EVT_LOG_SUP_MASK UINT64_C(0x0000000030000000)
+/** Bits 31:30 reserved. */
+#define IOMMU_EXT_FEAT_BF_RSVD_30_31_SHIFT 30
+#define IOMMU_EXT_FEAT_BF_RSVD_30_31_MASK UINT64_C(0x00000000c0000000)
+/** PASMax: Maximum PASID support (RO). */
+#define IOMMU_EXT_FEAT_BF_PASID_MAX_SHIFT 32
+#define IOMMU_EXT_FEAT_BF_PASID_MAX_MASK UINT64_C(0x0000001f00000000)
+/** USSup: User/Supervisor support (RO). */
+#define IOMMU_EXT_FEAT_BF_US_SUP_SHIFT 37
+#define IOMMU_EXT_FEAT_BF_US_SUP_MASK UINT64_C(0x0000002000000000)
+/** DevTblSegSup: Segmented Device Table support (RO). */
+#define IOMMU_EXT_FEAT_BF_DEV_TBL_SEG_SUP_SHIFT 38
+#define IOMMU_EXT_FEAT_BF_DEV_TBL_SEG_SUP_MASK UINT64_C(0x000000c000000000)
+/** PprOverflwEarlySup: PPR Log Overflow Early warning support (RO). */
+#define IOMMU_EXT_FEAT_BF_PPR_OVERFLOW_EARLY_SHIFT 40
+#define IOMMU_EXT_FEAT_BF_PPR_OVERFLOW_EARLY_MASK UINT64_C(0x0000010000000000)
+/** PprAutoRspSup: PPR Automatic Response support (RO). */
+#define IOMMU_EXT_FEAT_BF_PPR_AUTO_RES_SUP_SHIFT 41
+#define IOMMU_EXT_FEAT_BF_PPR_AUTO_RES_SUP_MASK UINT64_C(0x0000020000000000)
+/** MarcSup: Memory Access and Routing (MARC) support (RO). */
+#define IOMMU_EXT_FEAT_BF_MARC_SUP_SHIFT 42
+#define IOMMU_EXT_FEAT_BF_MARC_SUP_MASK UINT64_C(0x00000c0000000000)
+/** BlkStopMrkSup: Block StopMark message support (RO). */
+#define IOMMU_EXT_FEAT_BF_BLKSTOP_MARK_SUP_SHIFT 44
+#define IOMMU_EXT_FEAT_BF_BLKSTOP_MARK_SUP_MASK UINT64_C(0x0000100000000000)
+/** PerfOptSup: IOMMU Performance Optimization support (RO). */
+#define IOMMU_EXT_FEAT_BF_PERF_OPT_SUP_SHIFT 45
+#define IOMMU_EXT_FEAT_BF_PERF_OPT_SUP_MASK UINT64_C(0x0000200000000000)
+/** MsiCapMmioSup: MSI-Capability Register MMIO access support (RO). */
+#define IOMMU_EXT_FEAT_BF_MSI_CAP_MMIO_SUP_SHIFT 46
+#define IOMMU_EXT_FEAT_BF_MSI_CAP_MMIO_SUP_MASK UINT64_C(0x0000400000000000)
+/** Bit 47 reserved. */
+#define IOMMU_EXT_FEAT_BF_RSVD_47_SHIFT 47
+#define IOMMU_EXT_FEAT_BF_RSVD_47_MASK UINT64_C(0x0000800000000000)
+/** GIoSup: Guest I/O Protection support (RO). */
+#define IOMMU_EXT_FEAT_BF_GST_IO_PROT_SUP_SHIFT 48
+#define IOMMU_EXT_FEAT_BF_GST_IO_PROT_SUP_MASK UINT64_C(0x0001000000000000)
+/** HASup: Host Access support (RO). */
+#define IOMMU_EXT_FEAT_BF_HST_ACCESS_SUP_SHIFT 49
+#define IOMMU_EXT_FEAT_BF_HST_ACCESS_SUP_MASK UINT64_C(0x0002000000000000)
+/** EPHSup: Enhandled PPR Handling support (RO). */
+#define IOMMU_EXT_FEAT_BF_ENHANCED_PPR_SUP_SHIFT 50
+#define IOMMU_EXT_FEAT_BF_ENHANCED_PPR_SUP_MASK UINT64_C(0x0004000000000000)
+/** AttrFWSup: Attribute Forward support (RO). */
+#define IOMMU_EXT_FEAT_BF_ATTR_FW_SUP_SHIFT 51
+#define IOMMU_EXT_FEAT_BF_ATTR_FW_SUP_MASK UINT64_C(0x0008000000000000)
+/** HDSup: Host Dirty Support (RO). */
+#define IOMMU_EXT_FEAT_BF_HST_DIRTY_SUP_SHIFT 52
+#define IOMMU_EXT_FEAT_BF_HST_DIRTY_SUP_MASK UINT64_C(0x0010000000000000)
+/** Bit 53 reserved. */
+#define IOMMU_EXT_FEAT_BF_RSVD_53_SHIFT 53
+#define IOMMU_EXT_FEAT_BF_RSVD_53_MASK UINT64_C(0x0020000000000000)
+/** InvIotlbTypeSup: Invalidate IOTLB type support (RO). */
+#define IOMMU_EXT_FEAT_BF_INV_IOTLB_TYPE_SUP_SHIFT 54
+#define IOMMU_EXT_FEAT_BF_INV_IOTLB_TYPE_SUP_MASK UINT64_C(0x0040000000000000)
+/** Bits 60:55 reserved. */
+#define IOMMU_EXT_FEAT_BF_RSVD_55_60_SHIFT 55
+#define IOMMU_EXT_FEAT_BF_RSVD_55_60_MASK UINT64_C(0x1f80000000000000)
+/** GAUpdateDisSup: Support disabling hardware update on guest page table access
+ * (RO). */
+#define IOMMU_EXT_FEAT_BF_GA_UPDATE_DIS_SUP_SHIFT 61
+#define IOMMU_EXT_FEAT_BF_GA_UPDATE_DIS_SUP_MASK UINT64_C(0x2000000000000000)
+/** ForcePhysDestSup: Force Physical Destination Mode for Remapped Interrupt
+ * support (RO). */
+#define IOMMU_EXT_FEAT_BF_FORCE_PHYS_DST_SUP_SHIFT 62
+#define IOMMU_EXT_FEAT_BF_FORCE_PHYS_DST_SUP_MASK UINT64_C(0x4000000000000000)
+/** Bit 63 reserved. */
+#define IOMMU_EXT_FEAT_BF_RSVD_63_SHIFT 63
+#define IOMMU_EXT_FEAT_BF_RSVD_63_MASK UINT64_C(0x8000000000000000)
+RT_BF_ASSERT_COMPILE_CHECKS(IOMMU_EXT_FEAT_BF_, UINT64_C(0), UINT64_MAX,
+ (PREF_SUP, PPR_SUP, X2APIC_SUP, NO_EXEC_SUP, GT_SUP, RSVD_5, IA_SUP, GA_SUP, HE_SUP, PC_SUP,
+ HATS, GATS, GLX_SUP, SMI_FLT_SUP, SMI_FLT_REG_CNT, GAM_SUP, DUAL_PPR_LOG_SUP, RSVD_26_27,
+ DUAL_EVT_LOG_SUP, RSVD_30_31, PASID_MAX, US_SUP, DEV_TBL_SEG_SUP, PPR_OVERFLOW_EARLY,
+ PPR_AUTO_RES_SUP, MARC_SUP, BLKSTOP_MARK_SUP, PERF_OPT_SUP, MSI_CAP_MMIO_SUP, RSVD_47,
+ GST_IO_PROT_SUP, HST_ACCESS_SUP, ENHANCED_PPR_SUP, ATTR_FW_SUP, HST_DIRTY_SUP, RSVD_53,
+ INV_IOTLB_TYPE_SUP, RSVD_55_60, GA_UPDATE_DIS_SUP, FORCE_PHYS_DST_SUP, RSVD_63));
+/** @} */
+
+/**
+ * IVHD (I/O Virtualization Hardware Definition) Type 10h.
+ * In accordance with the AMD spec.
+ */
+#pragma pack(1)
+typedef struct ACPIIVHDTYPE10
+{
+ uint8_t u8Type; /**< Type: Must be 0x10. */
+ uint8_t u8Flags; /**< Flags (see ACPI_IVHD_10H_F_XXX). */
+ uint16_t u16Length; /**< Length of IVHD including IVHD device entries. */
+ uint16_t u16DeviceId; /**< Device ID of the IOMMU. */
+ uint16_t u16CapOffset; /**< Offset in Capability space for control fields of IOMMU. */
+ uint64_t u64BaseAddress; /**< Base address of IOMMU control registers in MMIO space. */
+ uint16_t u16PciSegmentGroup; /**< PCI segment group number. */
+ uint16_t u16IommuInfo; /**< Interrupt number and Unit ID. */
+ uint32_t u32Features; /**< IOMMU feature reporting. */
+ /* IVHD device entry block follows. */
+} ACPIIVHDTYPE10;
+#pragma pack()
+AssertCompileSize(ACPIIVHDTYPE10, 24);
+AssertCompileMemberOffset(ACPIIVHDTYPE10, u8Type, 0);
+AssertCompileMemberOffset(ACPIIVHDTYPE10, u8Flags, 1);
+AssertCompileMemberOffset(ACPIIVHDTYPE10, u16Length, 2);
+AssertCompileMemberOffset(ACPIIVHDTYPE10, u16DeviceId, 4);
+AssertCompileMemberOffset(ACPIIVHDTYPE10, u16CapOffset, 6);
+AssertCompileMemberOffset(ACPIIVHDTYPE10, u64BaseAddress, 8);
+AssertCompileMemberOffset(ACPIIVHDTYPE10, u16PciSegmentGroup, 16);
+AssertCompileMemberOffset(ACPIIVHDTYPE10, u16IommuInfo, 18);
+AssertCompileMemberOffset(ACPIIVHDTYPE10, u32Features, 20);
+
+/** @name IVHD Type 11h Flags.
+ * In accordance with the AMD spec.
+ * @{ */
+/** Coherent control. */
+#define ACPI_IVHD_11H_F_COHERENT RT_BIT(5)
+/** Remote IOTLB support. */
+#define ACPI_IVHD_11H_F_IOTLB_SUP RT_BIT(4)
+/** Isochronous control. */
+#define ACPI_IVHD_11H_F_ISOC RT_BIT(3)
+/** Response Pass Posted Write. */
+#define ACPI_IVHD_11H_F_RES_PASS_PW RT_BIT(2)
+/** Pass Posted Write. */
+#define ACPI_IVHD_11H_F_PASS_PW RT_BIT(1)
+/** HyperTransport Tunnel. */
+#define ACPI_IVHD_11H_F_HT_TUNNEL RT_BIT(0)
+/** @} */
+
+/** @name IVHD IOMMU Type 11 Attributes field.
+ * In accordance with the AMD spec.
+ * @{ */
+/** Bits 12:0 reserved. */
+#define ACPI_IOMMU_ATTR_BF_RSVD_0_12_SHIFT 0
+#define ACPI_IOMMU_ATTR_BF_RSVD_0_12_MASK UINT32_C(0x00001fff)
+/** PNCounters: Number of performance counters per counter bank. */
+#define ACPI_IOMMU_ATTR_BF_PN_COUNTERS_SHIFT 13
+#define ACPI_IOMMU_ATTR_BF_PN_COUNTERS_MASK UINT32_C(0x0001e000)
+/** PNBanks: Number of performance counter banks. */
+#define ACPI_IOMMU_ATTR_BF_PN_BANKS_SHIFT 17
+#define ACPI_IOMMU_ATTR_BF_PN_BANKS_MASK UINT32_C(0x007e0000)
+/** MSINumPPR: MSI number for peripheral page requests (PPR). */
+#define ACPI_IOMMU_ATTR_BF_MSI_NUM_PPR_SHIFT 23
+#define ACPI_IOMMU_ATTR_BF_MSI_NUM_PPR_MASK UINT32_C(0x0f800000)
+/** Bits 31:28 reserved. */
+#define ACPI_IOMMU_ATTR_BF_RSVD_28_31_SHIFT 28
+#define ACPI_IOMMU_ATTR_BF_RSVD_28_31_MASK UINT32_C(0xf0000000)
+RT_BF_ASSERT_COMPILE_CHECKS(ACPI_IOMMU_ATTR_BF_, UINT32_C(0), UINT32_MAX,
+ (RSVD_0_12, PN_COUNTERS, PN_BANKS, MSI_NUM_PPR, RSVD_28_31));
+/** @} */
+
+/**
+ * AMD IOMMU: IVHD (I/O Virtualization Hardware Definition) Type 11h.
+ * In accordance with the AMD spec.
+ */
+#pragma pack(1)
+typedef struct ACPIIVHDTYPE11
+{
+ uint8_t u8Type; /**< Type: Must be 0x11. */
+ uint8_t u8Flags; /**< Flags. */
+ uint16_t u16Length; /**< Length: Size starting from Type fields incl. IVHD device entries. */
+ uint16_t u16DeviceId; /**< Device ID of the IOMMU. */
+ uint16_t u16CapOffset; /**< Offset in Capability space for control fields of IOMMU. */
+ uint64_t u64BaseAddress; /**< Base address of IOMMU control registers in MMIO space. */
+ uint16_t u16PciSegmentGroup; /**< PCI segment group number. */
+ uint16_t u16IommuInfo; /**< Interrupt number and unit ID. */
+ uint32_t u32IommuAttr; /**< IOMMU info. not reported in EFR. */
+ uint64_t u64EfrRegister; /**< Extended Feature Register (must be identical to its MMIO shadow). */
+ uint64_t u64Rsvd0; /**< Reserved for future. */
+ /* IVHD device entry block follows. */
+} ACPIIVHDTYPE11;
+#pragma pack()
+AssertCompileSize(ACPIIVHDTYPE11, 40);
+AssertCompileMemberOffset(ACPIIVHDTYPE11, u8Type, 0);
+AssertCompileMemberOffset(ACPIIVHDTYPE11, u8Flags, 1);
+AssertCompileMemberOffset(ACPIIVHDTYPE11, u16Length, 2);
+AssertCompileMemberOffset(ACPIIVHDTYPE11, u16DeviceId, 4);
+AssertCompileMemberOffset(ACPIIVHDTYPE11, u16CapOffset, 6);
+AssertCompileMemberOffset(ACPIIVHDTYPE11, u64BaseAddress, 8);
+AssertCompileMemberOffset(ACPIIVHDTYPE11, u16PciSegmentGroup, 16);
+AssertCompileMemberOffset(ACPIIVHDTYPE11, u16IommuInfo, 18);
+AssertCompileMemberOffset(ACPIIVHDTYPE11, u32IommuAttr, 20);
+AssertCompileMemberOffset(ACPIIVHDTYPE11, u64EfrRegister, 24);
+AssertCompileMemberOffset(ACPIIVHDTYPE11, u64Rsvd0, 32);
+
+/**
+ * AMD IOMMU: IVHD (I/O Virtualization Hardware Definition) Type 40h.
+ * In accordance with the AMD spec.
+ */
+typedef struct ACPIIVHDTYPE11 ACPIIVHDTYPE40;
+
+#endif /* !VBOX_INCLUDED_iommu_amd_h */
diff --git a/include/VBox/iommu-intel.h b/include/VBox/iommu-intel.h
new file mode 100644
index 00000000..cbf2121c
--- /dev/null
+++ b/include/VBox/iommu-intel.h
@@ -0,0 +1,2915 @@
+/** @file
+ * IOMMU - Input/Output Memory Management Unit (Intel).
+ */
+
+/*
+ * Copyright (C) 2021-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_iommu_intel_h
+#define VBOX_INCLUDED_iommu_intel_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/assertcompile.h>
+#include <iprt/types.h>
+
+
+/**
+ * @name MMIO register offsets.
+ * In accordance with the Intel spec.
+ * @{
+ */
+#define VTD_MMIO_OFF_VER_REG 0x000 /**< Version. */
+#define VTD_MMIO_OFF_CAP_REG 0x008 /**< Capability. */
+#define VTD_MMIO_OFF_ECAP_REG 0x010 /**< Extended Capability. */
+#define VTD_MMIO_OFF_GCMD_REG 0x018 /**< Global Command. */
+#define VTD_MMIO_OFF_GSTS_REG 0x01c /**< Global Status. */
+#define VTD_MMIO_OFF_RTADDR_REG 0x020 /**< Root Table Address. */
+#define VTD_MMIO_OFF_CCMD_REG 0x028 /**< Context Command. */
+
+#define VTD_MMIO_OFF_FSTS_REG 0x034 /**< Fault Status.*/
+#define VTD_MMIO_OFF_FECTL_REG 0x038 /**< Fault Event Control.*/
+#define VTD_MMIO_OFF_FEDATA_REG 0x03c /**< Fault Event Data. */
+#define VTD_MMIO_OFF_FEADDR_REG 0x040 /**< Fault Event Address. */
+#define VTD_MMIO_OFF_FEUADDR_REG 0x044 /**< Fault Event Upper Address. */
+
+#define VTD_MMIO_OFF_AFLOG_REG 0x058 /**< Advance Fault Log. */
+
+#define VTD_MMIO_OFF_PMEN_REG 0x064 /**< Protected Memory Enable (PMEN). */
+#define VTD_MMIO_OFF_PLMBASE_REG 0x068 /**< Protected Low Memory Base. */
+#define VTD_MMIO_OFF_PLMLIMIT_REG 0x06c /**< Protected Low Memory Limit. */
+#define VTD_MMIO_OFF_PHMBASE_REG 0x070 /**< Protected High Memory Base. */
+#define VTD_MMIO_OFF_PHMLIMIT_REG 0x078 /**< Protected High Memory Limit. */
+
+#define VTD_MMIO_OFF_IQH_REG 0x080 /**< Invalidation Queue Head. */
+#define VTD_MMIO_OFF_IQT_REG 0x088 /**< Invalidation Queue Tail. */
+#define VTD_MMIO_OFF_IQA_REG 0x090 /**< Invalidation Queue Address. */
+#define VTD_MMIO_OFF_ICS_REG 0x09c /**< Invalidation Completion Status. */
+#define VTD_MMIO_OFF_IECTL_REG 0x0a0 /**< Invalidation Completion Event Control. */
+#define VTD_MMIO_OFF_IEDATA_REG 0x0a4 /**< Invalidation Completion Event Data. */
+#define VTD_MMIO_OFF_IEADDR_REG 0x0a8 /**< Invalidation Completion Event Address. */
+#define VTD_MMIO_OFF_IEUADDR_REG 0x0ac /**< Invalidation Completion Event Upper Address. */
+#define VTD_MMIO_OFF_IQERCD_REG 0x0b0 /**< Invalidation Queue Error Record. */
+
+#define VTD_MMIO_OFF_IRTA_REG 0x0b8 /**< Interrupt Remapping Table Address. */
+
+#define VTD_MMIO_OFF_PQH_REG 0x0c0 /**< Page Request Queue Head. */
+#define VTD_MMIO_OFF_PQT_REG 0x0c8 /**< Page Request Queue Tail. */
+#define VTD_MMIO_OFF_PQA_REG 0x0d0 /**< Page Request Queue Address. */
+#define VTD_MMIO_OFF_PRS_REG 0x0dc /**< Page Request Status. */
+#define VTD_MMIO_OFF_PECTL_REG 0x0e0 /**< Page Request Event Control. */
+#define VTD_MMIO_OFF_PEDATA_REG 0x0e4 /**< Page Request Event Data. */
+#define VTD_MMIO_OFF_PEADDR_REG 0x0e8 /**< Page Request Event Address. */
+#define VTD_MMIO_OFF_PEUADDR_REG 0x0ec /**< Page Request Event Upper Address. */
+
+#define VTD_MMIO_OFF_MTRRCAP_REG 0x100 /**< MTRR Capabliity. */
+#define VTD_MMIO_OFF_MTRRDEF_REG 0x108 /**< MTRR Default Type. */
+
+#define VTD_MMIO_OFF_MTRR_FIX64_00000_REG 0x120 /**< Fixed-range MTRR Register for 64K at 00000. */
+#define VTD_MMIO_OFF_MTRR_FIX16K_80000_REG 0x128 /**< Fixed-range MTRR Register for 16K at 80000. */
+#define VTD_MMIO_OFF_MTRR_FIX16K_A0000_REG 0x130 /**< Fixed-range MTRR Register for 16K at a0000. */
+#define VTD_MMIO_OFF_MTRR_FIX4K_C0000_REG 0x138 /**< Fixed-range MTRR Register for 4K at c0000. */
+#define VTD_MMIO_OFF_MTRR_FIX4K_C8000_REG 0x140 /**< Fixed-range MTRR Register for 4K at c8000. */
+#define VTD_MMIO_OFF_MTRR_FIX4K_D0000_REG 0x148 /**< Fixed-range MTRR Register for 4K at d0000. */
+#define VTD_MMIO_OFF_MTRR_FIX4K_D8000_REG 0x150 /**< Fixed-range MTRR Register for 4K at d8000. */
+#define VTD_MMIO_OFF_MTRR_FIX4K_E0000_REG 0x158 /**< Fixed-range MTRR Register for 4K at e0000. */
+#define VTD_MMIO_OFF_MTRR_FIX4K_E8000_REG 0x160 /**< Fixed-range MTRR Register for 4K at e8000. */
+#define VTD_MMIO_OFF_MTRR_FIX4K_F0000_REG 0x168 /**< Fixed-range MTRR Register for 4K at f0000. */
+#define VTD_MMIO_OFF_MTRR_FIX4K_F8000_REG 0x170 /**< Fixed-range MTRR Register for 4K at f8000. */
+
+#define VTD_MMIO_OFF_MTRR_PHYSBASE0_REG 0x180 /**< Variable-range MTRR Base 0. */
+#define VTD_MMIO_OFF_MTRR_PHYSMASK0_REG 0x188 /**< Variable-range MTRR Mask 0. */
+#define VTD_MMIO_OFF_MTRR_PHYSBASE1_REG 0x190 /**< Variable-range MTRR Base 1. */
+#define VTD_MMIO_OFF_MTRR_PHYSMASK1_REG 0x198 /**< Variable-range MTRR Mask 1. */
+#define VTD_MMIO_OFF_MTRR_PHYSBASE2_REG 0x1a0 /**< Variable-range MTRR Base 2. */
+#define VTD_MMIO_OFF_MTRR_PHYSMASK2_REG 0x1a8 /**< Variable-range MTRR Mask 2. */
+#define VTD_MMIO_OFF_MTRR_PHYSBASE3_REG 0x1b0 /**< Variable-range MTRR Base 3. */
+#define VTD_MMIO_OFF_MTRR_PHYSMASK3_REG 0x1b8 /**< Variable-range MTRR Mask 3. */
+#define VTD_MMIO_OFF_MTRR_PHYSBASE4_REG 0x1c0 /**< Variable-range MTRR Base 4. */
+#define VTD_MMIO_OFF_MTRR_PHYSMASK4_REG 0x1c8 /**< Variable-range MTRR Mask 4. */
+#define VTD_MMIO_OFF_MTRR_PHYSBASE5_REG 0x1d0 /**< Variable-range MTRR Base 5. */
+#define VTD_MMIO_OFF_MTRR_PHYSMASK5_REG 0x1d8 /**< Variable-range MTRR Mask 5. */
+#define VTD_MMIO_OFF_MTRR_PHYSBASE6_REG 0x1e0 /**< Variable-range MTRR Base 6. */
+#define VTD_MMIO_OFF_MTRR_PHYSMASK6_REG 0x1e8 /**< Variable-range MTRR Mask 6. */
+#define VTD_MMIO_OFF_MTRR_PHYSBASE7_REG 0x1f0 /**< Variable-range MTRR Base 7. */
+#define VTD_MMIO_OFF_MTRR_PHYSMASK7_REG 0x1f8 /**< Variable-range MTRR Mask 7. */
+#define VTD_MMIO_OFF_MTRR_PHYSBASE8_REG 0x200 /**< Variable-range MTRR Base 8. */
+#define VTD_MMIO_OFF_MTRR_PHYSMASK8_REG 0x208 /**< Variable-range MTRR Mask 8. */
+#define VTD_MMIO_OFF_MTRR_PHYSBASE9_REG 0x210 /**< Variable-range MTRR Base 9. */
+#define VTD_MMIO_OFF_MTRR_PHYSMASK9_REG 0x218 /**< Variable-range MTRR Mask 9. */
+
+#define VTD_MMIO_OFF_VCCAP_REG 0xe00 /**< Virtual Command Capability. */
+#define VTD_MMIO_OFF_VCMD_REG 0xe10 /**< Virtual Command. */
+#define VTD_MMIO_OFF_VCMDRSVD_REG 0xe18 /**< Reserved for future for Virtual Command. */
+#define VTD_MMIO_OFF_VCRSP_REG 0xe20 /**< Virtual Command Response. */
+#define VTD_MMIO_OFF_VCRSPRSVD_REG 0xe28 /**< Reserved for future for Virtual Command Response. */
+/** @} */
+
+
+/** @name Root Entry.
+ * In accordance with the Intel spec.
+ * @{ */
+/** P: Present. */
+#define VTD_BF_0_ROOT_ENTRY_P_SHIFT 0
+#define VTD_BF_0_ROOT_ENTRY_P_MASK UINT64_C(0x0000000000000001)
+/** R: Reserved (bits 11:1). */
+#define VTD_BF_0_ROOT_ENTRY_RSVD_11_1_SHIFT 1
+#define VTD_BF_0_ROOT_ENTRY_RSVD_11_1_MASK UINT64_C(0x0000000000000ffe)
+/** CTP: Context-Table Pointer. */
+#define VTD_BF_0_ROOT_ENTRY_CTP_SHIFT 12
+#define VTD_BF_0_ROOT_ENTRY_CTP_MASK UINT64_C(0xfffffffffffff000)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_0_ROOT_ENTRY_, UINT64_C(0), UINT64_MAX,
+ (P, RSVD_11_1, CTP));
+
+/** Root Entry. */
+typedef struct VTD_ROOT_ENTRY_T
+{
+ /** The qwords in the root entry. */
+ uint64_t au64[2];
+} VTD_ROOT_ENTRY_T;
+/** Pointer to a root entry. */
+typedef VTD_ROOT_ENTRY_T *PVTD_ROOT_ENTRY_T;
+/** Pointer to a const root entry. */
+typedef VTD_ROOT_ENTRY_T const *PCVTD_ROOT_ENTRY_T;
+
+/* Root Entry: Qword 0 valid mask. */
+#define VTD_ROOT_ENTRY_0_VALID_MASK (VTD_BF_0_ROOT_ENTRY_P_MASK | VTD_BF_0_ROOT_ENTRY_CTP_MASK)
+/* Root Entry: Qword 1 valid mask. */
+#define VTD_ROOT_ENTRY_1_VALID_MASK UINT64_C(0)
+/** @} */
+
+
+/** @name Scalable-mode Root Entry.
+ * In accordance with the Intel spec.
+ * @{ */
+/** LP: Lower Present. */
+#define VTD_BF_0_SM_ROOT_ENTRY_LP_SHIFT 0
+#define VTD_BF_0_SM_ROOT_ENTRY_LP_MASK UINT64_C(0x0000000000000001)
+/** R: Reserved (bits 11:1). */
+#define VTD_BF_0_SM_ROOT_ENTRY_RSVD_11_1_SHIFT 1
+#define VTD_BF_0_SM_ROOT_ENTRY_RSVD_11_1_MASK UINT64_C(0x0000000000000ffe)
+/** LCTP: Lower Context-Table Pointer */
+#define VTD_BF_0_SM_ROOT_ENTRY_LCTP_SHIFT 12
+#define VTD_BF_0_SM_ROOT_ENTRY_LCTP_MASK UINT64_C(0xfffffffffffff000)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_0_SM_ROOT_ENTRY_, UINT64_C(0), UINT64_MAX,
+ (LP, RSVD_11_1, LCTP));
+
+/** UP: Upper Present. */
+#define VTD_BF_1_SM_ROOT_ENTRY_UP_SHIFT 0
+#define VTD_BF_1_SM_ROOT_ENTRY_UP_MASK UINT64_C(0x0000000000000001)
+/** R: Reserved (bits 11:1). */
+#define VTD_BF_1_SM_ROOT_ENTRY_RSVD_11_1_SHIFT 1
+#define VTD_BF_1_SM_ROOT_ENTRY_RSVD_11_1_MASK UINT64_C(0x0000000000000ffe)
+/** UCTP: Upper Context-Table Pointer. */
+#define VTD_BF_1_SM_ROOT_ENTRY_UCTP_SHIFT 12
+#define VTD_BF_1_SM_ROOT_ENTRY_UCTP_MASK UINT64_C(0xfffffffffffff000)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_1_SM_ROOT_ENTRY_, UINT64_C(0), UINT64_MAX,
+ (UP, RSVD_11_1, UCTP));
+
+/** Scalable-mode root entry. */
+typedef struct VTD_SM_ROOT_ENTRY_T
+{
+ /** The lower scalable-mode root entry. */
+ uint64_t uLower;
+ /** The upper scalable-mode root entry. */
+ uint64_t uUpper;
+} VTD_SM_ROOT_ENTRY_T;
+/** Pointer to a scalable-mode root entry. */
+typedef VTD_SM_ROOT_ENTRY_T *PVTD_SM_ROOT_ENTRY_T;
+/** Pointer to a const scalable-mode root entry. */
+typedef VTD_SM_ROOT_ENTRY_T const *PCVTD_SM_ROOT_ENTRY_T;
+/** @} */
+
+
+/** @name Context Entry.
+ * In accordance with the Intel spec.
+ * @{ */
+/** P: Present. */
+#define VTD_BF_0_CONTEXT_ENTRY_P_SHIFT 0
+#define VTD_BF_0_CONTEXT_ENTRY_P_MASK UINT64_C(0x0000000000000001)
+/** FPD: Fault Processing Disable. */
+#define VTD_BF_0_CONTEXT_ENTRY_FPD_SHIFT 1
+#define VTD_BF_0_CONTEXT_ENTRY_FPD_MASK UINT64_C(0x0000000000000002)
+/** TT: Translation Type. */
+#define VTD_BF_0_CONTEXT_ENTRY_TT_SHIFT 2
+#define VTD_BF_0_CONTEXT_ENTRY_TT_MASK UINT64_C(0x000000000000000c)
+/** R: Reserved (bits 11:4). */
+#define VTD_BF_0_CONTEXT_ENTRY_RSVD_11_4_SHIFT 4
+#define VTD_BF_0_CONTEXT_ENTRY_RSVD_11_4_MASK UINT64_C(0x0000000000000ff0)
+/** SLPTPTR: Second Level Page Translation Pointer. */
+#define VTD_BF_0_CONTEXT_ENTRY_SLPTPTR_SHIFT 12
+#define VTD_BF_0_CONTEXT_ENTRY_SLPTPTR_MASK UINT64_C(0xfffffffffffff000)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_0_CONTEXT_ENTRY_, UINT64_C(0), UINT64_MAX,
+ (P, FPD, TT, RSVD_11_4, SLPTPTR));
+
+/** AW: Address Width. */
+#define VTD_BF_1_CONTEXT_ENTRY_AW_SHIFT 0
+#define VTD_BF_1_CONTEXT_ENTRY_AW_MASK UINT64_C(0x0000000000000007)
+/** IGN: Ignored (bits 6:3). */
+#define VTD_BF_1_CONTEXT_ENTRY_IGN_6_3_SHIFT 3
+#define VTD_BF_1_CONTEXT_ENTRY_IGN_6_3_MASK UINT64_C(0x0000000000000078)
+/** R: Reserved (bit 7). */
+#define VTD_BF_1_CONTEXT_ENTRY_RSVD_7_SHIFT 7
+#define VTD_BF_1_CONTEXT_ENTRY_RSVD_7_MASK UINT64_C(0x0000000000000080)
+/** DID: Domain Identifier. */
+#define VTD_BF_1_CONTEXT_ENTRY_DID_SHIFT 8
+#define VTD_BF_1_CONTEXT_ENTRY_DID_MASK UINT64_C(0x0000000000ffff00)
+/** R: Reserved (bits 63:24). */
+#define VTD_BF_1_CONTEXT_ENTRY_RSVD_63_24_SHIFT 24
+#define VTD_BF_1_CONTEXT_ENTRY_RSVD_63_24_MASK UINT64_C(0xffffffffff000000)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_1_CONTEXT_ENTRY_, UINT64_C(0), UINT64_MAX,
+ (AW, IGN_6_3, RSVD_7, DID, RSVD_63_24));
+
+/** Context Entry. */
+typedef struct VTD_CONTEXT_ENTRY_T
+{
+ /** The qwords in the context entry. */
+ uint64_t au64[2];
+} VTD_CONTEXT_ENTRY_T;
+/** Pointer to a context entry. */
+typedef VTD_CONTEXT_ENTRY_T *PVTD_CONTEXT_ENTRY_T;
+/** Pointer to a const context entry. */
+typedef VTD_CONTEXT_ENTRY_T const *PCVTD_CONTEXT_ENTRY_T;
+AssertCompileSize(VTD_CONTEXT_ENTRY_T, 16);
+
+/** Context Entry: Qword 0 valid mask. */
+#define VTD_CONTEXT_ENTRY_0_VALID_MASK ( VTD_BF_0_CONTEXT_ENTRY_P_MASK \
+ | VTD_BF_0_CONTEXT_ENTRY_FPD_MASK \
+ | VTD_BF_0_CONTEXT_ENTRY_TT_MASK \
+ | VTD_BF_0_CONTEXT_ENTRY_SLPTPTR_MASK)
+/** Context Entry: Qword 1 valid mask. */
+#define VTD_CONTEXT_ENTRY_1_VALID_MASK ( VTD_BF_1_CONTEXT_ENTRY_AW_MASK \
+ | VTD_BF_1_CONTEXT_ENTRY_IGN_6_3_MASK \
+ | VTD_BF_1_CONTEXT_ENTRY_DID_MASK)
+
+/** Translation Type: Untranslated requests uses second-level paging. */
+#define VTD_TT_UNTRANSLATED_SLP 0
+/** Translation Type: Untranslated requests requires device-TLB support. */
+#define VTD_TT_UNTRANSLATED_DEV_TLB 1
+/** Translation Type: Untranslated requests are pass-through. */
+#define VTD_TT_UNTRANSLATED_PT 2
+/** Translation Type: Reserved. */
+#define VTD_TT_RSVD 3
+/** @} */
+
+
+/** @name Scalable-mode Context Entry.
+ * In accordance with the Intel spec.
+ * @{ */
+/** P: Present. */
+#define VTD_BF_0_SM_CONTEXT_ENTRY_P_SHIFT 0
+#define VTD_BF_0_SM_CONTEXT_ENTRY_P_MASK UINT64_C(0x0000000000000001)
+/** FPD: Fault Processing Disable. */
+#define VTD_BF_0_SM_CONTEXT_ENTRY_FPD_SHIFT 1
+#define VTD_BF_0_SM_CONTEXT_ENTRY_FPD_MASK UINT64_C(0x0000000000000002)
+/** DTE: Device-TLB Enable. */
+#define VTD_BF_0_SM_CONTEXT_ENTRY_DTE_SHIFT 2
+#define VTD_BF_0_SM_CONTEXT_ENTRY_DTE_MASK UINT64_C(0x0000000000000004)
+/** PASIDE: PASID Enable. */
+#define VTD_BF_0_SM_CONTEXT_ENTRY_PASIDE_SHIFT 3
+#define VTD_BF_0_SM_CONTEXT_ENTRY_PASIDE_MASK UINT64_C(0x0000000000000008)
+/** PRE: Page Request Enable. */
+#define VTD_BF_0_SM_CONTEXT_ENTRY_PRE_SHIFT 4
+#define VTD_BF_0_SM_CONTEXT_ENTRY_PRE_MASK UINT64_C(0x0000000000000010)
+/** R: Reserved (bits 8:5). */
+#define VTD_BF_0_SM_CONTEXT_ENTRY_RSVD_8_5_SHIFT 5
+#define VTD_BF_0_SM_CONTEXT_ENTRY_RSVD_8_5_MASK UINT64_C(0x00000000000001e0)
+/** PDTS: PASID Directory Size. */
+#define VTD_BF_0_SM_CONTEXT_ENTRY_PDTS_SHIFT 9
+#define VTD_BF_0_SM_CONTEXT_ENTRY_PDTS_MASK UINT64_C(0x0000000000000e00)
+/** PASIDDIRPTR: PASID Directory Pointer. */
+#define VTD_BF_0_SM_CONTEXT_ENTRY_PASIDDIRPTR_SHIFT 12
+#define VTD_BF_0_SM_CONTEXT_ENTRY_PASIDDIRPTR_MASK UINT64_C(0xfffffffffffff000)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_0_SM_CONTEXT_ENTRY_, UINT64_C(0), UINT64_MAX,
+ (P, FPD, DTE, PASIDE, PRE, RSVD_8_5, PDTS, PASIDDIRPTR));
+
+/** RID_PASID: Requested Id to PASID assignment. */
+#define VTD_BF_1_SM_CONTEXT_ENTRY_RID_PASID_SHIFT 0
+#define VTD_BF_1_SM_CONTEXT_ENTRY_RID_PASID_MASK UINT64_C(0x00000000000fffff)
+/** RID_PRIV: Requested Id to PrivilegeModeRequested assignment. */
+#define VTD_BF_1_SM_CONTEXT_ENTRY_RID_PRIV_SHIFT 20
+#define VTD_BF_1_SM_CONTEXT_ENTRY_RID_PRIV_MASK UINT64_C(0x0000000000100000)
+/** R: Reserved (bits 63:21). */
+#define VTD_BF_1_SM_CONTEXT_ENTRY_RSVD_63_21_SHIFT 21
+#define VTD_BF_1_SM_CONTEXT_ENTRY_RSVD_63_21_MASK UINT64_C(0xffffffffffe00000)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_1_SM_CONTEXT_ENTRY_, UINT64_C(0), UINT64_MAX,
+ (RID_PASID, RID_PRIV, RSVD_63_21));
+
+/** Scalable-mode Context Entry. */
+typedef struct VTD_SM_CONTEXT_ENTRY_T
+{
+ /** The qwords in the scalable-mode context entry. */
+ uint64_t au64[4];
+} VTD_SM_CONTEXT_ENTRY_T;
+/** Pointer to a scalable-mode context entry. */
+typedef VTD_SM_CONTEXT_ENTRY_T *PVTD_SM_CONTEXT_ENTRY_T;
+/** Pointer to a const scalable-mode context entry. */
+typedef VTD_SM_CONTEXT_ENTRY_T const *PCVTD_SM_CONTEXT_ENTRY_T;
+/** @} */
+
+
+/** @name Scalable-mode PASID Directory Entry.
+ * In accordance with the Intel spec.
+ * @{ */
+/** P: Present. */
+#define VTD_BF_SM_PASID_DIR_ENTRY_P_SHIFT 0
+#define VTD_BF_SM_PASID_DIR_ENTRY_P_MASK UINT64_C(0x0000000000000001)
+/** FPD: Fault Processing Disable. */
+#define VTD_BF_SM_PASID_DIR_ENTRY_FPD_SHIFT 1
+#define VTD_BF_SM_PASID_DIR_ENTRY_FPD_MASK UINT64_C(0x0000000000000002)
+/** R: Reserved (bits 11:2). */
+#define VTD_BF_SM_PASID_DIR_ENTRY_RSVD_11_2_SHIFT 2
+#define VTD_BF_SM_PASID_DIR_ENTRY_RSVD_11_2_MASK UINT64_C(0x0000000000000ffc)
+/** SMPTBLPTR: Scalable Mode PASID Table Pointer. */
+#define VTD_BF_SM_PASID_DIR_ENTRY_SMPTBLPTR_SHIFT 12
+#define VTD_BF_SM_PASID_DIR_ENTRY_SMPTBLPTR_MASK UINT64_C(0xfffffffffffff000)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_SM_PASID_DIR_ENTRY_, UINT64_C(0), UINT64_MAX,
+ (P, FPD, RSVD_11_2, SMPTBLPTR));
+
+/** Scalable-mode PASID Directory Entry. */
+typedef struct VTD_SM_PASID_DIR_ENTRY_T
+{
+ /** The scalable-mode PASID directory entry. */
+ uint64_t u;
+} VTD_SM_PASID_DIR_ENTRY_T;
+/** Pointer to a scalable-mode PASID directory entry. */
+typedef VTD_SM_PASID_DIR_ENTRY_T *PVTD_SM_PASID_DIR_ENTRY_T;
+/** Pointer to a const scalable-mode PASID directory entry. */
+typedef VTD_SM_PASID_DIR_ENTRY_T const *PCVTD_SM_PASID_DIR_ENTRY_T;
+/** @} */
+
+
+/** @name Scalable-mode PASID Table Entry.
+ * In accordance with the Intel spec.
+ * @{ */
+/** P: Present. */
+#define VTD_BF_0_SM_PASID_TBL_ENTRY_P_SHIFT 0
+#define VTD_BF_0_SM_PASID_TBL_ENTRY_P_MASK UINT64_C(0x0000000000000001)
+/** FPD: Fault Processing Disable. */
+#define VTD_BF_0_SM_PASID_TBL_ENTRY_FPD_SHIFT 1
+#define VTD_BF_0_SM_PASID_TBL_ENTRY_FPD_MASK UINT64_C(0x0000000000000002)
+/** AW: Address Width. */
+#define VTD_BF_0_SM_PASID_TBL_ENTRY_AW_SHIFT 2
+#define VTD_BF_0_SM_PASID_TBL_ENTRY_AW_MASK UINT64_C(0x000000000000001c)
+/** SLEE: Second-Level Execute Enable. */
+#define VTD_BF_0_SM_PASID_TBL_ENTRY_SLEE_SHIFT 5
+#define VTD_BF_0_SM_PASID_TBL_ENTRY_SLEE_MASK UINT64_C(0x0000000000000020)
+/** PGTT: PASID Granular Translation Type. */
+#define VTD_BF_0_SM_PASID_TBL_ENTRY_PGTT_SHIFT 6
+#define VTD_BF_0_SM_PASID_TBL_ENTRY_PGTT_MASK UINT64_C(0x00000000000001c0)
+/** SLADE: Second-Level Address/Dirty Enable. */
+#define VTD_BF_0_SM_PASID_TBL_ENTRY_SLADE_SHIFT 9
+#define VTD_BF_0_SM_PASID_TBL_ENTRY_SLADE_MASK UINT64_C(0x0000000000000200)
+/** R: Reserved (bits 11:10). */
+#define VTD_BF_0_SM_PASID_TBL_ENTRY_RSVD_11_10_SHIFT 10
+#define VTD_BF_0_SM_PASID_TBL_ENTRY_RSVD_11_10_MASK UINT64_C(0x0000000000000c00)
+/** SLPTPTR: Second-Level Page Table Pointer. */
+#define VTD_BF_0_SM_PASID_TBL_ENTRY_SLPTPTR_SHIFT 12
+#define VTD_BF_0_SM_PASID_TBL_ENTRY_SLPTPTR_MASK UINT64_C(0xfffffffffffff000)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_0_SM_PASID_TBL_ENTRY_, UINT64_C(0), UINT64_MAX,
+ (P, FPD, AW, SLEE, PGTT, SLADE, RSVD_11_10, SLPTPTR));
+
+/** DID: Domain Identifer. */
+#define VTD_BF_1_SM_PASID_TBL_ENTRY_DID_SHIFT 0
+#define VTD_BF_1_SM_PASID_TBL_ENTRY_DID_MASK UINT64_C(0x000000000000ffff)
+/** R: Reserved (bits 22:16). */
+#define VTD_BF_1_SM_PASID_TBL_ENTRY_RSVD_22_16_SHIFT 16
+#define VTD_BF_1_SM_PASID_TBL_ENTRY_RSVD_22_16_MASK UINT64_C(0x00000000007f0000)
+/** PWSNP: Page-Walk Snoop. */
+#define VTD_BF_1_SM_PASID_TBL_ENTRY_PWSNP_SHIFT 23
+#define VTD_BF_1_SM_PASID_TBL_ENTRY_PWSNP_MASK UINT64_C(0x0000000000800000)
+/** PGSNP: Page Snoop. */
+#define VTD_BF_1_SM_PASID_TBL_ENTRY_PGSNP_SHIFT 24
+#define VTD_BF_1_SM_PASID_TBL_ENTRY_PGSNP_MASK UINT64_C(0x0000000001000000)
+/** CD: Cache Disable. */
+#define VTD_BF_1_SM_PASID_TBL_ENTRY_CD_SHIFT 25
+#define VTD_BF_1_SM_PASID_TBL_ENTRY_CD_MASK UINT64_C(0x0000000002000000)
+/** EMTE: Extended Memory Type Enable. */
+#define VTD_BF_1_SM_PASID_TBL_ENTRY_EMTE_SHIFT 26
+#define VTD_BF_1_SM_PASID_TBL_ENTRY_EMTE_MASK UINT64_C(0x0000000004000000)
+/** EMT: Extended Memory Type. */
+#define VTD_BF_1_SM_PASID_TBL_ENTRY_EMT_SHIFT 27
+#define VTD_BF_1_SM_PASID_TBL_ENTRY_EMT_MASK UINT64_C(0x0000000038000000)
+/** PWT: Page-Level Write Through. */
+#define VTD_BF_1_SM_PASID_TBL_ENTRY_PWT_SHIFT 30
+#define VTD_BF_1_SM_PASID_TBL_ENTRY_PWT_MASK UINT64_C(0x0000000040000000)
+/** PCD: Page-Level Cache Disable. */
+#define VTD_BF_1_SM_PASID_TBL_ENTRY_PCD_SHIFT 31
+#define VTD_BF_1_SM_PASID_TBL_ENTRY_PCD_MASK UINT64_C(0x0000000080000000)
+/** PAT: Page Attribute Table. */
+#define VTD_BF_1_SM_PASID_TBL_ENTRY_PAT_SHIFT 32
+#define VTD_BF_1_SM_PASID_TBL_ENTRY_PAT_MASK UINT64_C(0xffffffff00000000)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_1_SM_PASID_TBL_ENTRY_, UINT64_C(0), UINT64_MAX,
+ (DID, RSVD_22_16, PWSNP, PGSNP, CD, EMTE, EMT, PWT, PCD, PAT));
+
+/** SRE: Supervisor Request Enable. */
+#define VTD_BF_2_SM_PASID_TBL_ENTRY_SRE_SHIFT 0
+#define VTD_BF_2_SM_PASID_TBL_ENTRY_SRE_MASK UINT64_C(0x0000000000000001)
+/** ERE: Execute Request Enable. */
+#define VTD_BF_2_SM_PASID_TBL_ENTRY_ERE_SHIFT 1
+#define VTD_BF_2_SM_PASID_TBL_ENTRY_ERE_MASK UINT64_C(0x0000000000000002)
+/** FLPM: First Level Paging Mode. */
+#define VTD_BF_2_SM_PASID_TBL_ENTRY_FLPM_SHIFT 2
+#define VTD_BF_2_SM_PASID_TBL_ENTRY_FLPM_MASK UINT64_C(0x000000000000000c)
+/** WPE: Write Protect Enable. */
+#define VTD_BF_2_SM_PASID_TBL_ENTRY_WPE_SHIFT 4
+#define VTD_BF_2_SM_PASID_TBL_ENTRY_WPE_MASK UINT64_C(0x0000000000000010)
+/** NXE: No-Execute Enable. */
+#define VTD_BF_2_SM_PASID_TBL_ENTRY_NXE_SHIFT 5
+#define VTD_BF_2_SM_PASID_TBL_ENTRY_NXE_MASK UINT64_C(0x0000000000000020)
+/** SMEP: Supervisor Mode Execute Prevent. */
+#define VTD_BF_2_SM_PASID_TBL_ENTRY_SMPE_SHIFT 6
+#define VTD_BF_2_SM_PASID_TBL_ENTRY_SMPE_MASK UINT64_C(0x0000000000000040)
+/** EAFE: Extended Accessed Flag Enable. */
+#define VTD_BF_2_SM_PASID_TBL_ENTRY_EAFE_SHIFT 7
+#define VTD_BF_2_SM_PASID_TBL_ENTRY_EAFE_MASK UINT64_C(0x0000000000000080)
+/** R: Reserved (bits 11:8). */
+#define VTD_BF_2_SM_PASID_TBL_ENTRY_RSVD_11_8_SHIFT 8
+#define VTD_BF_2_SM_PASID_TBL_ENTRY_RSVD_11_8_MASK UINT64_C(0x0000000000000f00)
+/** FLPTPTR: First Level Page Table Pointer. */
+#define VTD_BF_2_SM_PASID_TBL_ENTRY_FLPTPTR_SHIFT 12
+#define VTD_BF_2_SM_PASID_TBL_ENTRY_FLPTPTR_MASK UINT64_C(0xfffffffffffff000)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_2_SM_PASID_TBL_ENTRY_, UINT64_C(0), UINT64_MAX,
+ (SRE, ERE, FLPM, WPE, NXE, SMPE, EAFE, RSVD_11_8, FLPTPTR));
+
+/** Scalable-mode PASID Table Entry. */
+typedef struct VTD_SM_PASID_TBL_ENTRY_T
+{
+ /** The qwords in the scalable-mode PASID table entry. */
+ uint64_t au64[8];
+} VTD_SM_PASID_TBL_ENTRY_T;
+/** Pointer to a scalable-mode PASID table entry. */
+typedef VTD_SM_PASID_TBL_ENTRY_T *PVTD_SM_PASID_TBL_ENTRY_T;
+/** Pointer to a const scalable-mode PASID table entry. */
+typedef VTD_SM_PASID_TBL_ENTRY_T const *PCVTD_SM_PASID_TBL_ENTRY_T;
+/** @} */
+
+
+/** @name First-Level Paging Entry.
+ * In accordance with the Intel spec.
+ * @{ */
+/** P: Present. */
+#define VTD_BF_FLP_ENTRY_P_SHIFT 0
+#define VTD_BF_FLP_ENTRY_P_MASK UINT64_C(0x0000000000000001)
+/** R/W: Read/Write. */
+#define VTD_BF_FLP_ENTRY_RW_SHIFT 1
+#define VTD_BF_FLP_ENTRY_RW_MASK UINT64_C(0x0000000000000002)
+/** U/S: User/Supervisor. */
+#define VTD_BF_FLP_ENTRY_US_SHIFT 2
+#define VTD_BF_FLP_ENTRY_US_MASK UINT64_C(0x0000000000000004)
+/** PWT: Page-Level Write Through. */
+#define VTD_BF_FLP_ENTRY_PWT_SHIFT 3
+#define VTD_BF_FLP_ENTRY_PWT_MASK UINT64_C(0x0000000000000008)
+/** PC: Page-Level Cache Disable. */
+#define VTD_BF_FLP_ENTRY_PCD_SHIFT 4
+#define VTD_BF_FLP_ENTRY_PCD_MASK UINT64_C(0x0000000000000010)
+/** A: Accessed. */
+#define VTD_BF_FLP_ENTRY_A_SHIFT 5
+#define VTD_BF_FLP_ENTRY_A_MASK UINT64_C(0x0000000000000020)
+/** IGN: Ignored (bit 6). */
+#define VTD_BF_FLP_ENTRY_IGN_6_SHIFT 6
+#define VTD_BF_FLP_ENTRY_IGN_6_MASK UINT64_C(0x0000000000000040)
+/** R: Reserved (bit 7). */
+#define VTD_BF_FLP_ENTRY_RSVD_7_SHIFT 7
+#define VTD_BF_FLP_ENTRY_RSVD_7_MASK UINT64_C(0x0000000000000080)
+/** IGN: Ignored (bits 9:8). */
+#define VTD_BF_FLP_ENTRY_IGN_9_8_SHIFT 8
+#define VTD_BF_FLP_ENTRY_IGN_9_8_MASK UINT64_C(0x0000000000000300)
+/** EA: Extended Accessed. */
+#define VTD_BF_FLP_ENTRY_EA_SHIFT 10
+#define VTD_BF_FLP_ENTRY_EA_MASK UINT64_C(0x0000000000000400)
+/** IGN: Ignored (bit 11). */
+#define VTD_BF_FLP_ENTRY_IGN_11_SHIFT 11
+#define VTD_BF_FLP_ENTRY_IGN_11_MASK UINT64_C(0x0000000000000800)
+/** ADDR: Address. */
+#define VTD_BF_FLP_ENTRY_ADDR_SHIFT 12
+#define VTD_BF_FLP_ENTRY_ADDR_MASK UINT64_C(0x000ffffffffff000)
+/** IGN: Ignored (bits 62:52). */
+#define VTD_BF_FLP_ENTRY_IGN_62_52_SHIFT 52
+#define VTD_BF_FLP_ENTRY_IGN_62_52_MASK UINT64_C(0x7ff0000000000000)
+/** XD: Execute Disabled. */
+#define VTD_BF_FLP_ENTRY_XD_SHIFT 63
+#define VTD_BF_FLP_ENTRY_XD_MASK UINT64_C(0x8000000000000000)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_FLP_ENTRY_, UINT64_C(0), UINT64_MAX,
+ (P, RW, US, PWT, PCD, A, IGN_6, RSVD_7, IGN_9_8, EA, IGN_11, ADDR, IGN_62_52, XD));
+/** @} */
+
+
+/** @name Second-Level PML5E.
+ * In accordance with the Intel spec.
+ * @{ */
+/** R: Read. */
+#define VTD_BF_SL_PML5E_R_SHIFT 0
+#define VTD_BF_SL_PML5E_R_MASK UINT64_C(0x0000000000000001)
+/** W: Write. */
+#define VTD_BF_SL_PML5E_W_SHIFT 1
+#define VTD_BF_SL_PML5E_W_MASK UINT64_C(0x0000000000000002)
+/** X: Execute. */
+#define VTD_BF_SL_PML5E_X_SHIFT 2
+#define VTD_BF_SL_PML5E_X_MASK UINT64_C(0x0000000000000004)
+/** IGN: Ignored (bits 6:3). */
+#define VTD_BF_SL_PML5E_IGN_6_3_SHIFT 3
+#define VTD_BF_SL_PML5E_IGN_6_3_MASK UINT64_C(0x0000000000000078)
+/** R: Reserved (bit 7). */
+#define VTD_BF_SL_PML5E_RSVD_7_SHIFT 7
+#define VTD_BF_SL_PML5E_RSVD_7_MASK UINT64_C(0x0000000000000080)
+/** A: Accessed. */
+#define VTD_BF_SL_PML5E_A_SHIFT 8
+#define VTD_BF_SL_PML5E_A_MASK UINT64_C(0x0000000000000100)
+/** IGN: Ignored (bits 10:9). */
+#define VTD_BF_SL_PML5E_IGN_10_9_SHIFT 9
+#define VTD_BF_SL_PML5E_IGN_10_9_MASK UINT64_C(0x0000000000000600)
+/** R: Reserved (bit 11). */
+#define VTD_BF_SL_PML5E_RSVD_11_SHIFT 11
+#define VTD_BF_SL_PML5E_RSVD_11_MASK UINT64_C(0x0000000000000800)
+/** ADDR: Address. */
+#define VTD_BF_SL_PML5E_ADDR_SHIFT 12
+#define VTD_BF_SL_PML5E_ADDR_MASK UINT64_C(0x000ffffffffff000)
+/** IGN: Ignored (bits 61:52). */
+#define VTD_BF_SL_PML5E_IGN_61_52_SHIFT 52
+#define VTD_BF_SL_PML5E_IGN_61_52_MASK UINT64_C(0x3ff0000000000000)
+/** R: Reserved (bit 62). */
+#define VTD_BF_SL_PML5E_RSVD_62_SHIFT 62
+#define VTD_BF_SL_PML5E_RSVD_62_MASK UINT64_C(0x4000000000000000)
+/** IGN: Ignored (bit 63). */
+#define VTD_BF_SL_PML5E_IGN_63_SHIFT 63
+#define VTD_BF_SL_PML5E_IGN_63_MASK UINT64_C(0x8000000000000000)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_SL_PML5E_, UINT64_C(0), UINT64_MAX,
+ (R, W, X, IGN_6_3, RSVD_7, A, IGN_10_9, RSVD_11, ADDR, IGN_61_52, RSVD_62, IGN_63));
+
+/** Second-level PML5E valid mask. */
+#define VTD_SL_PML5E_VALID_MASK ( VTD_BF_SL_PML5E_R_MASK | VTD_BF_SL_PML5E_W_MASK \
+ | VTD_BF_SL_PML5E_X_MASK | VTD_BF_SL_PML5E_IGN_6_3_MASK \
+ | VTD_BF_SL_PML5E_A_MASK | VTD_BF_SL_PML5E_IGN_10_9_MASK \
+ | VTD_BF_SL_PML5E_ADDR_MASK | VTD_BF_SL_PML5E_IGN_61_52_MASK \
+ | VTD_BF_SL_PML5E_IGN_63_MASK)
+/** @} */
+
+
+/** @name Second-Level PML4E.
+ * In accordance with the Intel spec.
+ * @{ */
+/** R: Read. */
+#define VTD_BF_SL_PML4E_R_SHIFT 0
+#define VTD_BF_SL_PML4E_R_MASK UINT64_C(0x0000000000000001)
+/** W: Write. */
+#define VTD_BF_SL_PML4E_W_SHIFT 1
+#define VTD_BF_SL_PML4E_W_MASK UINT64_C(0x0000000000000002)
+/** X: Execute. */
+#define VTD_BF_SL_PML4E_X_SHIFT 2
+#define VTD_BF_SL_PML4E_X_MASK UINT64_C(0x0000000000000004)
+/** IGN: Ignored (bits 6:3). */
+#define VTD_BF_SL_PML4E_IGN_6_3_SHIFT 3
+#define VTD_BF_SL_PML4E_IGN_6_3_MASK UINT64_C(0x0000000000000078)
+/** R: Reserved (bit 7). */
+#define VTD_BF_SL_PML4E_RSVD_7_SHIFT 7
+#define VTD_BF_SL_PML4E_RSVD_7_MASK UINT64_C(0x0000000000000080)
+/** A: Accessed. */
+#define VTD_BF_SL_PML4E_A_SHIFT 8
+#define VTD_BF_SL_PML4E_A_MASK UINT64_C(0x0000000000000100)
+/** IGN: Ignored (bits 10:9). */
+#define VTD_BF_SL_PML4E_IGN_10_9_SHIFT 9
+#define VTD_BF_SL_PML4E_IGN_10_9_MASK UINT64_C(0x0000000000000600)
+/** R: Reserved (bit 11). */
+#define VTD_BF_SL_PML4E_RSVD_11_SHIFT 11
+#define VTD_BF_SL_PML4E_RSVD_11_MASK UINT64_C(0x0000000000000800)
+/** ADDR: Address. */
+#define VTD_BF_SL_PML4E_ADDR_SHIFT 12
+#define VTD_BF_SL_PML4E_ADDR_MASK UINT64_C(0x000ffffffffff000)
+/** IGN: Ignored (bits 61:52). */
+#define VTD_BF_SL_PML4E_IGN_61_52_SHIFT 52
+#define VTD_BF_SL_PML4E_IGN_61_52_MASK UINT64_C(0x3ff0000000000000)
+/** R: Reserved (bit 62). */
+#define VTD_BF_SL_PML4E_RSVD_62_SHIFT 62
+#define VTD_BF_SL_PML4E_RSVD_62_MASK UINT64_C(0x4000000000000000)
+/** IGN: Ignored (bit 63). */
+#define VTD_BF_SL_PML4E_IGN_63_SHIFT 63
+#define VTD_BF_SL_PML4E_IGN_63_MASK UINT64_C(0x8000000000000000)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_SL_PML4E_, UINT64_C(0), UINT64_MAX,
+ (R, W, X, IGN_6_3, RSVD_7, A, IGN_10_9, RSVD_11, ADDR, IGN_61_52, RSVD_62, IGN_63));
+
+/** Second-level PML4E valid mask. */
+#define VTD_SL_PML4E_VALID_MASK VTD_SL_PML5E_VALID_MASK
+/** @} */
+
+
+/** @name Second-Level PDPE (1GB Page).
+ * In accordance with the Intel spec.
+ * @{ */
+/** R: Read. */
+#define VTD_BF_SL_PDPE1G_R_SHIFT 0
+#define VTD_BF_SL_PDPE1G_R_MASK UINT64_C(0x0000000000000001)
+/** W: Write. */
+#define VTD_BF_SL_PDPE1G_W_SHIFT 1
+#define VTD_BF_SL_PDPE1G_W_MASK UINT64_C(0x0000000000000002)
+/** X: Execute. */
+#define VTD_BF_SL_PDPE1G_X_SHIFT 2
+#define VTD_BF_SL_PDPE1G_X_MASK UINT64_C(0x0000000000000004)
+/** EMT: Extended Memory Type. */
+#define VTD_BF_SL_PDPE1G_EMT_SHIFT 3
+#define VTD_BF_SL_PDPE1G_EMT_MASK UINT64_C(0x0000000000000038)
+/** IPAT: Ignore PAT (Page Attribute Table). */
+#define VTD_BF_SL_PDPE1G_IPAT_SHIFT 6
+#define VTD_BF_SL_PDPE1G_IPAT_MASK UINT64_C(0x0000000000000040)
+/** PS: Page Size (MB1). */
+#define VTD_BF_SL_PDPE1G_PS_SHIFT 7
+#define VTD_BF_SL_PDPE1G_PS_MASK UINT64_C(0x0000000000000080)
+/** A: Accessed. */
+#define VTD_BF_SL_PDPE1G_A_SHIFT 8
+#define VTD_BF_SL_PDPE1G_A_MASK UINT64_C(0x0000000000000100)
+/** D: Dirty. */
+#define VTD_BF_SL_PDPE1G_D_SHIFT 9
+#define VTD_BF_SL_PDPE1G_D_MASK UINT64_C(0x0000000000000200)
+/** IGN: Ignored (bit 10). */
+#define VTD_BF_SL_PDPE1G_IGN_10_SHIFT 10
+#define VTD_BF_SL_PDPE1G_IGN_10_MASK UINT64_C(0x0000000000000400)
+/** R: Reserved (bit 11). */
+#define VTD_BF_SL_PDPE1G_RSVD_11_SHIFT 11
+#define VTD_BF_SL_PDPE1G_RSVD_11_MASK UINT64_C(0x0000000000000800)
+/** R: Reserved (bits 29:12). */
+#define VTD_BF_SL_PDPE1G_RSVD_29_12_SHIFT 12
+#define VTD_BF_SL_PDPE1G_RSVD_29_12_MASK UINT64_C(0x000000003ffff000)
+/** ADDR: Address of 1GB page. */
+#define VTD_BF_SL_PDPE1G_ADDR_SHIFT 30
+#define VTD_BF_SL_PDPE1G_ADDR_MASK UINT64_C(0x000fffffc0000000)
+/** IGN: Ignored (bits 61:52). */
+#define VTD_BF_SL_PDPE1G_IGN_61_52_SHIFT 52
+#define VTD_BF_SL_PDPE1G_IGN_61_52_MASK UINT64_C(0x3ff0000000000000)
+/** R: Reserved (bit 62). */
+#define VTD_BF_SL_PDPE1G_RSVD_62_SHIFT 62
+#define VTD_BF_SL_PDPE1G_RSVD_62_MASK UINT64_C(0x4000000000000000)
+/** IGN: Ignored (bit 63). */
+#define VTD_BF_SL_PDPE1G_IGN_63_SHIFT 63
+#define VTD_BF_SL_PDPE1G_IGN_63_MASK UINT64_C(0x8000000000000000)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_SL_PDPE1G_, UINT64_C(0), UINT64_MAX,
+ (R, W, X, EMT, IPAT, PS, A, D, IGN_10, RSVD_11, RSVD_29_12, ADDR, IGN_61_52, RSVD_62, IGN_63));
+
+/** Second-level PDPE (1GB Page) valid mask. */
+#define VTD_SL_PDPE1G_VALID_MASK ( VTD_BF_SL_PDPE1G_R_MASK | VTD_BF_SL_PDPE1G_W_MASK \
+ | VTD_BF_SL_PDPE1G_X_MASK | VTD_BF_SL_PDPE1G_EMT_MASK \
+ | VTD_BF_SL_PDPE1G_IPAT_MASK | VTD_BF_SL_PDPE1G_PS_MASK \
+ | VTD_BF_SL_PDPE1G_A_MASK | VTD_BF_SL_PDPE1G_D_MASK \
+ | VTD_BF_SL_PDPE1G_IGN_10_MASK | VTD_BF_SL_PDPE1G_ADDR_MASK \
+ | VTD_BF_SL_PDPE1G_IGN_61_52_MASK | VTD_BF_SL_PDPE1G_IGN_63_MASK)
+/** @} */
+
+
+/** @name Second-Level PDPE.
+ * In accordance with the Intel spec.
+ * @{ */
+/** R: Read. */
+#define VTD_BF_SL_PDPE_R_SHIFT 0
+#define VTD_BF_SL_PDPE_R_MASK UINT64_C(0x0000000000000001)
+/** W: Write. */
+#define VTD_BF_SL_PDPE_W_SHIFT 1
+#define VTD_BF_SL_PDPE_W_MASK UINT64_C(0x0000000000000002)
+/** X: Execute. */
+#define VTD_BF_SL_PDPE_X_SHIFT 2
+#define VTD_BF_SL_PDPE_X_MASK UINT64_C(0x0000000000000004)
+/** IGN: Ignored (bits 6:3). */
+#define VTD_BF_SL_PDPE_IGN_6_3_SHIFT 3
+#define VTD_BF_SL_PDPE_IGN_6_3_MASK UINT64_C(0x0000000000000078)
+/** PS: Page Size (MBZ). */
+#define VTD_BF_SL_PDPE_PS_SHIFT 7
+#define VTD_BF_SL_PDPE_PS_MASK UINT64_C(0x0000000000000080)
+/** A: Accessed. */
+#define VTD_BF_SL_PDPE_A_SHIFT 8
+#define VTD_BF_SL_PDPE_A_MASK UINT64_C(0x0000000000000100)
+/** IGN: Ignored (bits 10:9). */
+#define VTD_BF_SL_PDPE_IGN_10_9_SHIFT 9
+#define VTD_BF_SL_PDPE_IGN_10_9_MASK UINT64_C(0x0000000000000600)
+/** R: Reserved (bit 11). */
+#define VTD_BF_SL_PDPE_RSVD_11_SHIFT 11
+#define VTD_BF_SL_PDPE_RSVD_11_MASK UINT64_C(0x0000000000000800)
+/** ADDR: Address of second-level PDT. */
+#define VTD_BF_SL_PDPE_ADDR_SHIFT 12
+#define VTD_BF_SL_PDPE_ADDR_MASK UINT64_C(0x000ffffffffff000)
+/** IGN: Ignored (bits 61:52). */
+#define VTD_BF_SL_PDPE_IGN_61_52_SHIFT 52
+#define VTD_BF_SL_PDPE_IGN_61_52_MASK UINT64_C(0x3ff0000000000000)
+/** R: Reserved (bit 62). */
+#define VTD_BF_SL_PDPE_RSVD_62_SHIFT 62
+#define VTD_BF_SL_PDPE_RSVD_62_MASK UINT64_C(0x4000000000000000)
+/** IGN: Ignored (bit 63). */
+#define VTD_BF_SL_PDPE_IGN_63_SHIFT 63
+#define VTD_BF_SL_PDPE_IGN_63_MASK UINT64_C(0x8000000000000000)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_SL_PDPE_, UINT64_C(0), UINT64_MAX,
+ (R, W, X, IGN_6_3, PS, A, IGN_10_9, RSVD_11, ADDR, IGN_61_52, RSVD_62, IGN_63));
+
+/** Second-level PDPE valid mask. */
+#define VTD_SL_PDPE_VALID_MASK ( VTD_BF_SL_PDPE_R_MASK | VTD_BF_SL_PDPE_W_MASK \
+ | VTD_BF_SL_PDPE_X_MASK | VTD_BF_SL_PDPE_IGN_6_3_MASK \
+ | VTD_BF_SL_PDPE_PS_MASK | VTD_BF_SL_PDPE_A_MASK \
+ | VTD_BF_SL_PDPE_IGN_10_9_MASK | VTD_BF_SL_PDPE_ADDR_MASK \
+ | VTD_BF_SL_PDPE_IGN_61_52_MASK | VTD_BF_SL_PDPE_IGN_63_MASK)
+/** @} */
+
+
+/** @name Second-Level PDE (2MB Page).
+ * In accordance with the Intel spec.
+ * @{ */
+/** R: Read. */
+#define VTD_BF_SL_PDE2M_R_SHIFT 0
+#define VTD_BF_SL_PDE2M_R_MASK UINT64_C(0x0000000000000001)
+/** W: Write. */
+#define VTD_BF_SL_PDE2M_W_SHIFT 1
+#define VTD_BF_SL_PDE2M_W_MASK UINT64_C(0x0000000000000002)
+/** X: Execute. */
+#define VTD_BF_SL_PDE2M_X_SHIFT 2
+#define VTD_BF_SL_PDE2M_X_MASK UINT64_C(0x0000000000000004)
+/** EMT: Extended Memory Type. */
+#define VTD_BF_SL_PDE2M_EMT_SHIFT 3
+#define VTD_BF_SL_PDE2M_EMT_MASK UINT64_C(0x0000000000000038)
+/** IPAT: Ignore PAT (Page Attribute Table). */
+#define VTD_BF_SL_PDE2M_IPAT_SHIFT 6
+#define VTD_BF_SL_PDE2M_IPAT_MASK UINT64_C(0x0000000000000040)
+/** PS: Page Size (MB1). */
+#define VTD_BF_SL_PDE2M_PS_SHIFT 7
+#define VTD_BF_SL_PDE2M_PS_MASK UINT64_C(0x0000000000000080)
+/** A: Accessed. */
+#define VTD_BF_SL_PDE2M_A_SHIFT 8
+#define VTD_BF_SL_PDE2M_A_MASK UINT64_C(0x0000000000000100)
+/** D: Dirty. */
+#define VTD_BF_SL_PDE2M_D_SHIFT 9
+#define VTD_BF_SL_PDE2M_D_MASK UINT64_C(0x0000000000000200)
+/** IGN: Ignored (bit 10). */
+#define VTD_BF_SL_PDE2M_IGN_10_SHIFT 10
+#define VTD_BF_SL_PDE2M_IGN_10_MASK UINT64_C(0x0000000000000400)
+/** R: Reserved (bit 11). */
+#define VTD_BF_SL_PDE2M_RSVD_11_SHIFT 11
+#define VTD_BF_SL_PDE2M_RSVD_11_MASK UINT64_C(0x0000000000000800)
+/** R: Reserved (bits 20:12). */
+#define VTD_BF_SL_PDE2M_RSVD_20_12_SHIFT 12
+#define VTD_BF_SL_PDE2M_RSVD_20_12_MASK UINT64_C(0x00000000001ff000)
+/** ADDR: Address of 2MB page. */
+#define VTD_BF_SL_PDE2M_ADDR_SHIFT 21
+#define VTD_BF_SL_PDE2M_ADDR_MASK UINT64_C(0x000fffffffe00000)
+/** IGN: Ignored (bits 61:52). */
+#define VTD_BF_SL_PDE2M_IGN_61_52_SHIFT 52
+#define VTD_BF_SL_PDE2M_IGN_61_52_MASK UINT64_C(0x3ff0000000000000)
+/** R: Reserved (bit 62). */
+#define VTD_BF_SL_PDE2M_RSVD_62_SHIFT 62
+#define VTD_BF_SL_PDE2M_RSVD_62_MASK UINT64_C(0x4000000000000000)
+/** IGN: Ignored (bit 63). */
+#define VTD_BF_SL_PDE2M_IGN_63_SHIFT 63
+#define VTD_BF_SL_PDE2M_IGN_63_MASK UINT64_C(0x8000000000000000)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_SL_PDE2M_, UINT64_C(0), UINT64_MAX,
+ (R, W, X, EMT, IPAT, PS, A, D, IGN_10, RSVD_11, RSVD_20_12, ADDR, IGN_61_52, RSVD_62, IGN_63));
+
+/** Second-level PDE (2MB page) valid mask. */
+#define VTD_SL_PDE2M_VALID_MASK ( VTD_BF_SL_PDE2M_R_MASK | VTD_BF_SL_PDE2M_W_MASK \
+ | VTD_BF_SL_PDE2M_X_MASK | VTD_BF_SL_PDE2M_EMT_MASK \
+ | VTD_BF_SL_PDE2M_IPAT_MASK | VTD_BF_SL_PDE2M_PS_MASK \
+ | VTD_BF_SL_PDE2M_A_MASK | VTD_BF_SL_PDE2M_D_MASK \
+ | VTD_BF_SL_PDE2M_IGN_10_MASK | VTD_BF_SL_PDE2M_ADDR_MASK \
+ | VTD_BF_SL_PDE2M_IGN_61_52_MASK | VTD_BF_SL_PDE2M_IGN_63_MASK)
+/** @} */
+
+
+/** @name Second-Level PDE.
+ * In accordance with the Intel spec.
+ * @{ */
+/** R: Read. */
+#define VTD_BF_SL_PDE_R_SHIFT 0
+#define VTD_BF_SL_PDE_R_MASK UINT64_C(0x0000000000000001)
+/** W: Write. */
+#define VTD_BF_SL_PDE_W_SHIFT 1
+#define VTD_BF_SL_PDE_W_MASK UINT64_C(0x0000000000000002)
+/** X: Execute. */
+#define VTD_BF_SL_PDE_X_SHIFT 2
+#define VTD_BF_SL_PDE_X_MASK UINT64_C(0x0000000000000004)
+/** IGN: Ignored (bits 6:3). */
+#define VTD_BF_SL_PDE_IGN_6_3_SHIFT 3
+#define VTD_BF_SL_PDE_IGN_6_3_MASK UINT64_C(0x0000000000000078)
+/** PS: Page Size (MBZ). */
+#define VTD_BF_SL_PDE_PS_SHIFT 7
+#define VTD_BF_SL_PDE_PS_MASK UINT64_C(0x0000000000000080)
+/** A: Accessed. */
+#define VTD_BF_SL_PDE_A_SHIFT 8
+#define VTD_BF_SL_PDE_A_MASK UINT64_C(0x0000000000000100)
+/** IGN: Ignored (bits 10:9). */
+#define VTD_BF_SL_PDE_IGN_10_9_SHIFT 9
+#define VTD_BF_SL_PDE_IGN_10_9_MASK UINT64_C(0x0000000000000600)
+/** R: Reserved (bit 11). */
+#define VTD_BF_SL_PDE_RSVD_11_SHIFT 11
+#define VTD_BF_SL_PDE_RSVD_11_MASK UINT64_C(0x0000000000000800)
+/** ADDR: Address of second-level PT. */
+#define VTD_BF_SL_PDE_ADDR_SHIFT 12
+#define VTD_BF_SL_PDE_ADDR_MASK UINT64_C(0x000ffffffffff000)
+/** IGN: Ignored (bits 61:52). */
+#define VTD_BF_SL_PDE_IGN_61_52_SHIFT 52
+#define VTD_BF_SL_PDE_IGN_61_52_MASK UINT64_C(0x3ff0000000000000)
+/** R: Reserved (bit 62). */
+#define VTD_BF_SL_PDE_RSVD_62_SHIFT 62
+#define VTD_BF_SL_PDE_RSVD_62_MASK UINT64_C(0x4000000000000000)
+/** IGN: Ignored (bit 63). */
+#define VTD_BF_SL_PDE_IGN_63_SHIFT 63
+#define VTD_BF_SL_PDE_IGN_63_MASK UINT64_C(0x8000000000000000)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_SL_PDE_, UINT64_C(0), UINT64_MAX,
+ (R, W, X, IGN_6_3, PS, A, IGN_10_9, RSVD_11, ADDR, IGN_61_52, RSVD_62, IGN_63));
+
+/** Second-level PDE valid mask. */
+#define VTD_SL_PDE_VALID_MASK ( VTD_BF_SL_PDE_R_MASK | VTD_BF_SL_PDE_W_MASK \
+ | VTD_BF_SL_PDE_X_MASK | VTD_BF_SL_PDE_IGN_6_3_MASK \
+ | VTD_BF_SL_PDE_PS_MASK | VTD_BF_SL_PDE_A_MASK \
+ | VTD_BF_SL_PDE_IGN_10_9_MASK | VTD_BF_SL_PDE_ADDR_MASK \
+ | VTD_BF_SL_PDE_IGN_61_52_MASK | VTD_BF_SL_PDE_IGN_63_MASK)
+/** @} */
+
+
+/** @name Second-Level PTE.
+ * In accordance with the Intel spec.
+ * @{ */
+/** R: Read. */
+#define VTD_BF_SL_PTE_R_SHIFT 0
+#define VTD_BF_SL_PTE_R_MASK UINT64_C(0x0000000000000001)
+/** W: Write. */
+#define VTD_BF_SL_PTE_W_SHIFT 1
+#define VTD_BF_SL_PTE_W_MASK UINT64_C(0x0000000000000002)
+/** X: Execute. */
+#define VTD_BF_SL_PTE_X_SHIFT 2
+#define VTD_BF_SL_PTE_X_MASK UINT64_C(0x0000000000000004)
+/** EMT: Extended Memory Type. */
+#define VTD_BF_SL_PTE_EMT_SHIFT 3
+#define VTD_BF_SL_PTE_EMT_MASK UINT64_C(0x0000000000000038)
+/** IPAT: Ignore PAT (Page Attribute Table). */
+#define VTD_BF_SL_PTE_IPAT_SHIFT 6
+#define VTD_BF_SL_PTE_IPAT_MASK UINT64_C(0x0000000000000040)
+/** IGN: Ignored (bit 7). */
+#define VTD_BF_SL_PTE_IGN_7_SHIFT 7
+#define VTD_BF_SL_PTE_IGN_7_MASK UINT64_C(0x0000000000000080)
+/** A: Accessed. */
+#define VTD_BF_SL_PTE_A_SHIFT 8
+#define VTD_BF_SL_PTE_A_MASK UINT64_C(0x0000000000000100)
+/** D: Dirty. */
+#define VTD_BF_SL_PTE_D_SHIFT 9
+#define VTD_BF_SL_PTE_D_MASK UINT64_C(0x0000000000000200)
+/** IGN: Ignored (bit 10). */
+#define VTD_BF_SL_PTE_IGN_10_SHIFT 10
+#define VTD_BF_SL_PTE_IGN_10_MASK UINT64_C(0x0000000000000400)
+/** R: Reserved (bit 11). */
+#define VTD_BF_SL_PTE_RSVD_11_SHIFT 11
+#define VTD_BF_SL_PTE_RSVD_11_MASK UINT64_C(0x0000000000000800)
+/** ADDR: Address of 4K page. */
+#define VTD_BF_SL_PTE_ADDR_SHIFT 12
+#define VTD_BF_SL_PTE_ADDR_MASK UINT64_C(0x000ffffffffff000)
+/** IGN: Ignored (bits 61:52). */
+#define VTD_BF_SL_PTE_IGN_61_52_SHIFT 52
+#define VTD_BF_SL_PTE_IGN_61_52_MASK UINT64_C(0x3ff0000000000000)
+/** R: Reserved (bit 62). */
+#define VTD_BF_SL_PTE_RSVD_62_SHIFT 62
+#define VTD_BF_SL_PTE_RSVD_62_MASK UINT64_C(0x4000000000000000)
+/** IGN: Ignored (bit 63). */
+#define VTD_BF_SL_PTE_IGN_63_SHIFT 63
+#define VTD_BF_SL_PTE_IGN_63_MASK UINT64_C(0x8000000000000000)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_SL_PTE_, UINT64_C(0), UINT64_MAX,
+ (R, W, X, EMT, IPAT, IGN_7, A, D, IGN_10, RSVD_11, ADDR, IGN_61_52, RSVD_62, IGN_63));
+
+/** Second-level PTE valid mask. */
+#define VTD_SL_PTE_VALID_MASK ( VTD_BF_SL_PTE_R_MASK | VTD_BF_SL_PTE_W_MASK \
+ | VTD_BF_SL_PTE_X_MASK | VTD_BF_SL_PTE_EMT_MASK \
+ | VTD_BF_SL_PTE_IPAT_MASK | VTD_BF_SL_PTE_IGN_7_MASK \
+ | VTD_BF_SL_PTE_A_MASK | VTD_BF_SL_PTE_D_MASK \
+ | VTD_BF_SL_PTE_IGN_10_MASK | VTD_BF_SL_PTE_ADDR_MASK \
+ | VTD_BF_SL_PTE_IGN_61_52_MASK | VTD_BF_SL_PTE_IGN_63_MASK)
+/** @} */
+
+
+/** @name Fault Record.
+ * In accordance with the Intel spec.
+ * @{ */
+/** R: Reserved (bits 11:0). */
+#define VTD_BF_0_FAULT_RECORD_RSVD_11_0_SHIFT 0
+#define VTD_BF_0_FAULT_RECORD_RSVD_11_0_MASK UINT64_C(0x0000000000000fff)
+/** FI: Fault Information. */
+#define VTD_BF_0_FAULT_RECORD_FI_SHIFT 12
+#define VTD_BF_0_FAULT_RECORD_FI_MASK UINT64_C(0xfffffffffffff000)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_0_FAULT_RECORD_, UINT64_C(0), UINT64_MAX,
+ (RSVD_11_0, FI));
+
+/** SID: Source identifier. */
+#define VTD_BF_1_FAULT_RECORD_SID_SHIFT 0
+#define VTD_BF_1_FAULT_RECORD_SID_MASK UINT64_C(0x000000000000ffff)
+/** R: Reserved (bits 28:16). */
+#define VTD_BF_1_FAULT_RECORD_RSVD_28_16_SHIFT 16
+#define VTD_BF_1_FAULT_RECORD_RSVD_28_16_MASK UINT64_C(0x000000001fff0000)
+/** PRIV: Privilege Mode Requested. */
+#define VTD_BF_1_FAULT_RECORD_PRIV_SHIFT 29
+#define VTD_BF_1_FAULT_RECORD_PRIV_MASK UINT64_C(0x0000000020000000)
+/** EXE: Execute Permission Requested. */
+#define VTD_BF_1_FAULT_RECORD_EXE_SHIFT 30
+#define VTD_BF_1_FAULT_RECORD_EXE_MASK UINT64_C(0x0000000040000000)
+/** PP: PASID Present. */
+#define VTD_BF_1_FAULT_RECORD_PP_SHIFT 31
+#define VTD_BF_1_FAULT_RECORD_PP_MASK UINT64_C(0x0000000080000000)
+/** FR: Fault Reason. */
+#define VTD_BF_1_FAULT_RECORD_FR_SHIFT 32
+#define VTD_BF_1_FAULT_RECORD_FR_MASK UINT64_C(0x000000ff00000000)
+/** PV: PASID Value. */
+#define VTD_BF_1_FAULT_RECORD_PV_SHIFT 40
+#define VTD_BF_1_FAULT_RECORD_PV_MASK UINT64_C(0x0fffff0000000000)
+/** AT: Address Type. */
+#define VTD_BF_1_FAULT_RECORD_AT_SHIFT 60
+#define VTD_BF_1_FAULT_RECORD_AT_MASK UINT64_C(0x3000000000000000)
+/** T: Type. */
+#define VTD_BF_1_FAULT_RECORD_T_SHIFT 62
+#define VTD_BF_1_FAULT_RECORD_T_MASK UINT64_C(0x4000000000000000)
+/** R: Reserved (bit 127). */
+#define VTD_BF_1_FAULT_RECORD_RSVD_63_SHIFT 63
+#define VTD_BF_1_FAULT_RECORD_RSVD_63_MASK UINT64_C(0x8000000000000000)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_1_FAULT_RECORD_, UINT64_C(0), UINT64_MAX,
+ (SID, RSVD_28_16, PRIV, EXE, PP, FR, PV, AT, T, RSVD_63));
+
+/** Fault record. */
+typedef struct VTD_FAULT_RECORD_T
+{
+ /** The qwords in the fault record. */
+ uint64_t au64[2];
+} VTD_FAULT_RECORD_T;
+/** Pointer to a fault record. */
+typedef VTD_FAULT_RECORD_T *PVTD_FAULT_RECORD_T;
+/** Pointer to a const fault record. */
+typedef VTD_FAULT_RECORD_T const *PCVTD_FAULT_RECORD_T;
+/** @} */
+
+
+/** @name Interrupt Remapping Table Entry (IRTE) for Remapped Interrupts.
+ * In accordance with the Intel spec.
+ * @{ */
+/** P: Present. */
+#define VTD_BF_0_IRTE_P_SHIFT 0
+#define VTD_BF_0_IRTE_P_MASK UINT64_C(0x0000000000000001)
+/** FPD: Fault Processing Disable. */
+#define VTD_BF_0_IRTE_FPD_SHIFT 1
+#define VTD_BF_0_IRTE_FPD_MASK UINT64_C(0x0000000000000002)
+/** DM: Destination Mode (0=physical, 1=logical). */
+#define VTD_BF_0_IRTE_DM_SHIFT 2
+#define VTD_BF_0_IRTE_DM_MASK UINT64_C(0x0000000000000004)
+/** RH: Redirection Hint. */
+#define VTD_BF_0_IRTE_RH_SHIFT 3
+#define VTD_BF_0_IRTE_RH_MASK UINT64_C(0x0000000000000008)
+/** TM: Trigger Mode. */
+#define VTD_BF_0_IRTE_TM_SHIFT 4
+#define VTD_BF_0_IRTE_TM_MASK UINT64_C(0x0000000000000010)
+/** DLM: Delivery Mode. */
+#define VTD_BF_0_IRTE_DLM_SHIFT 5
+#define VTD_BF_0_IRTE_DLM_MASK UINT64_C(0x00000000000000e0)
+/** AVL: Available. */
+#define VTD_BF_0_IRTE_AVAIL_SHIFT 8
+#define VTD_BF_0_IRTE_AVAIL_MASK UINT64_C(0x0000000000000f00)
+/** R: Reserved (bits 14:12). */
+#define VTD_BF_0_IRTE_RSVD_14_12_SHIFT 12
+#define VTD_BF_0_IRTE_RSVD_14_12_MASK UINT64_C(0x0000000000007000)
+/** IM: IRTE Mode. */
+#define VTD_BF_0_IRTE_IM_SHIFT 15
+#define VTD_BF_0_IRTE_IM_MASK UINT64_C(0x0000000000008000)
+/** V: Vector. */
+#define VTD_BF_0_IRTE_V_SHIFT 16
+#define VTD_BF_0_IRTE_V_MASK UINT64_C(0x0000000000ff0000)
+/** R: Reserved (bits 31:24). */
+#define VTD_BF_0_IRTE_RSVD_31_24_SHIFT 24
+#define VTD_BF_0_IRTE_RSVD_31_24_MASK UINT64_C(0x00000000ff000000)
+/** DST: Desination Id. */
+#define VTD_BF_0_IRTE_DST_SHIFT 32
+#define VTD_BF_0_IRTE_DST_MASK UINT64_C(0xffffffff00000000)
+/** R: Reserved (bits 39:32) when EIME=0. */
+#define VTD_BF_0_IRTE_RSVD_39_32_SHIFT 32
+#define VTD_BF_0_IRTE_RSVD_39_32_MASK UINT64_C(0x000000ff00000000)
+/** DST_XAPIC: Destination Id when EIME=0. */
+#define VTD_BF_0_IRTE_DST_XAPIC_SHIFT 40
+#define VTD_BF_0_IRTE_DST_XAPIC_MASK UINT64_C(0x0000ff0000000000)
+/** R: Reserved (bits 63:48) when EIME=0. */
+#define VTD_BF_0_IRTE_RSVD_63_48_SHIFT 48
+#define VTD_BF_0_IRTE_RSVD_63_48_MASK UINT64_C(0xffff000000000000)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_0_IRTE_, UINT64_C(0), UINT64_MAX,
+ (P, FPD, DM, RH, TM, DLM, AVAIL, RSVD_14_12, IM, V, RSVD_31_24, DST));
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_0_IRTE_, UINT64_C(0), UINT64_MAX,
+ (P, FPD, DM, RH, TM, DLM, AVAIL, RSVD_14_12, IM, V, RSVD_31_24, RSVD_39_32, DST_XAPIC, RSVD_63_48));
+
+/** SID: Source Identifier. */
+#define VTD_BF_1_IRTE_SID_SHIFT 0
+#define VTD_BF_1_IRTE_SID_MASK UINT64_C(0x000000000000ffff)
+/** SQ: Source-Id Qualifier. */
+#define VTD_BF_1_IRTE_SQ_SHIFT 16
+#define VTD_BF_1_IRTE_SQ_MASK UINT64_C(0x0000000000030000)
+/** SVT: Source Validation Type. */
+#define VTD_BF_1_IRTE_SVT_SHIFT 18
+#define VTD_BF_1_IRTE_SVT_MASK UINT64_C(0x00000000000c0000)
+/** R: Reserved (bits 127:84). */
+#define VTD_BF_1_IRTE_RSVD_63_20_SHIFT 20
+#define VTD_BF_1_IRTE_RSVD_63_20_MASK UINT64_C(0xfffffffffff00000)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_1_IRTE_, UINT64_C(0), UINT64_MAX,
+ (SID, SQ, SVT, RSVD_63_20));
+
+/** IRTE: Qword 0 valid mask when EIME=1. */
+#define VTD_IRTE_0_X2APIC_VALID_MASK ( VTD_BF_0_IRTE_P_MASK | VTD_BF_0_IRTE_FPD_MASK \
+ | VTD_BF_0_IRTE_DM_MASK | VTD_BF_0_IRTE_RH_MASK \
+ | VTD_BF_0_IRTE_TM_MASK | VTD_BF_0_IRTE_DLM_MASK \
+ | VTD_BF_0_IRTE_AVAIL_MASK | VTD_BF_0_IRTE_IM_MASK \
+ | VTD_BF_0_IRTE_V_MASK | VTD_BF_0_IRTE_DST_MASK)
+/** IRTE: Qword 0 valid mask when EIME=0. */
+#define VTD_IRTE_0_XAPIC_VALID_MASK ( VTD_BF_0_IRTE_P_MASK | VTD_BF_0_IRTE_FPD_MASK \
+ | VTD_BF_0_IRTE_DM_MASK | VTD_BF_0_IRTE_RH_MASK \
+ | VTD_BF_0_IRTE_TM_MASK | VTD_BF_0_IRTE_DLM_MASK \
+ | VTD_BF_0_IRTE_AVAIL_MASK | VTD_BF_0_IRTE_IM_MASK \
+ | VTD_BF_0_IRTE_V_MASK | VTD_BF_0_IRTE_DST_XAPIC_MASK)
+/** IRTE: Qword 1 valid mask. */
+#define VTD_IRTE_1_VALID_MASK ( VTD_BF_1_IRTE_SID_MASK | VTD_BF_1_IRTE_SQ_MASK \
+ | VTD_BF_1_IRTE_SVT_MASK)
+
+/** Interrupt Remapping Table Entry (IRTE) for remapped interrupts. */
+typedef struct VTD_IRTE_T
+{
+ /** The qwords in the IRTE. */
+ uint64_t au64[2];
+} VTD_IRTE_T;
+/** Pointer to an IRTE. */
+typedef VTD_IRTE_T *PVTD_IRTE_T;
+/** Pointer to a const IRTE. */
+typedef VTD_IRTE_T const *PCVTD_IRTE_T;
+
+/** IRTE SVT: No validation required. */
+#define VTD_IRTE_SVT_NONE 0
+/** IRTE SVT: Validate using a mask derived from SID and SQT. */
+#define VTD_IRTE_SVT_VALIDATE_MASK 1
+/** IRTE SVT: Validate using Bus range in the SID. */
+#define VTD_IRTE_SVT_VALIDATE_BUS_RANGE 2
+/** IRTE SVT: Reserved. */
+#define VTD_IRTE_SVT_VALIDATE_RSVD 3
+/** @} */
+
+
+/** @name Version Register (VER_REG).
+ * In accordance with the Intel spec.
+ * @{ */
+/** Min: Minor Version Number. */
+#define VTD_BF_VER_REG_MIN_SHIFT 0
+#define VTD_BF_VER_REG_MIN_MASK UINT32_C(0x0000000f)
+/** Max: Major Version Number. */
+#define VTD_BF_VER_REG_MAX_SHIFT 4
+#define VTD_BF_VER_REG_MAX_MASK UINT32_C(0x000000f0)
+/** R: Reserved (bits 31:8). */
+#define VTD_BF_VER_REG_RSVD_31_8_SHIFT 8
+#define VTD_BF_VER_REG_RSVD_31_8_MASK UINT32_C(0xffffff00)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_VER_REG_, UINT32_C(0), UINT32_MAX,
+ (MIN, MAX, RSVD_31_8));
+/** RW: Read/write mask. */
+#define VTD_VER_REG_RW_MASK UINT32_C(0)
+/** @} */
+
+
+/** @name Capability Register (CAP_REG).
+ * In accordance with the Intel spec.
+ * @{ */
+/** ND: Number of domains supported. */
+#define VTD_BF_CAP_REG_ND_SHIFT 0
+#define VTD_BF_CAP_REG_ND_MASK UINT64_C(0x0000000000000007)
+/** AFL: Advanced Fault Logging. */
+#define VTD_BF_CAP_REG_AFL_SHIFT 3
+#define VTD_BF_CAP_REG_AFL_MASK UINT64_C(0x0000000000000008)
+/** RWBF: Required Write-Buffer Flushing. */
+#define VTD_BF_CAP_REG_RWBF_SHIFT 4
+#define VTD_BF_CAP_REG_RWBF_MASK UINT64_C(0x0000000000000010)
+/** PLMR: Protected Low-Memory Region. */
+#define VTD_BF_CAP_REG_PLMR_SHIFT 5
+#define VTD_BF_CAP_REG_PLMR_MASK UINT64_C(0x0000000000000020)
+/** PHMR: Protected High-Memory Region. */
+#define VTD_BF_CAP_REG_PHMR_SHIFT 6
+#define VTD_BF_CAP_REG_PHMR_MASK UINT64_C(0x0000000000000040)
+/** CM: Caching Mode. */
+#define VTD_BF_CAP_REG_CM_SHIFT 7
+#define VTD_BF_CAP_REG_CM_MASK UINT64_C(0x0000000000000080)
+/** SAGAW: Supported Adjusted Guest Address Widths. */
+#define VTD_BF_CAP_REG_SAGAW_SHIFT 8
+#define VTD_BF_CAP_REG_SAGAW_MASK UINT64_C(0x0000000000001f00)
+/** R: Reserved (bits 15:13). */
+#define VTD_BF_CAP_REG_RSVD_15_13_SHIFT 13
+#define VTD_BF_CAP_REG_RSVD_15_13_MASK UINT64_C(0x000000000000e000)
+/** MGAW: Maximum Guest Address Width. */
+#define VTD_BF_CAP_REG_MGAW_SHIFT 16
+#define VTD_BF_CAP_REG_MGAW_MASK UINT64_C(0x00000000003f0000)
+/** ZLR: Zero Length Read. */
+#define VTD_BF_CAP_REG_ZLR_SHIFT 22
+#define VTD_BF_CAP_REG_ZLR_MASK UINT64_C(0x0000000000400000)
+/** DEP: Deprecated MBZ. Reserved (bit 23). */
+#define VTD_BF_CAP_REG_RSVD_23_SHIFT 23
+#define VTD_BF_CAP_REG_RSVD_23_MASK UINT64_C(0x0000000000800000)
+/** FRO: Fault-recording Register Offset. */
+#define VTD_BF_CAP_REG_FRO_SHIFT 24
+#define VTD_BF_CAP_REG_FRO_MASK UINT64_C(0x00000003ff000000)
+/** SLLPS: Second Level Large Page Support. */
+#define VTD_BF_CAP_REG_SLLPS_SHIFT 34
+#define VTD_BF_CAP_REG_SLLPS_MASK UINT64_C(0x0000003c00000000)
+/** R: Reserved (bit 38). */
+#define VTD_BF_CAP_REG_RSVD_38_SHIFT 38
+#define VTD_BF_CAP_REG_RSVD_38_MASK UINT64_C(0x0000004000000000)
+/** PSI: Page Selective Invalidation. */
+#define VTD_BF_CAP_REG_PSI_SHIFT 39
+#define VTD_BF_CAP_REG_PSI_MASK UINT64_C(0x0000008000000000)
+/** NFR: Number of Fault-recording Registers. */
+#define VTD_BF_CAP_REG_NFR_SHIFT 40
+#define VTD_BF_CAP_REG_NFR_MASK UINT64_C(0x0000ff0000000000)
+/** MAMV: Maximum Address Mask Value. */
+#define VTD_BF_CAP_REG_MAMV_SHIFT 48
+#define VTD_BF_CAP_REG_MAMV_MASK UINT64_C(0x003f000000000000)
+/** DWD: Write Draining. */
+#define VTD_BF_CAP_REG_DWD_SHIFT 54
+#define VTD_BF_CAP_REG_DWD_MASK UINT64_C(0x0040000000000000)
+/** DRD: Read Draining. */
+#define VTD_BF_CAP_REG_DRD_SHIFT 55
+#define VTD_BF_CAP_REG_DRD_MASK UINT64_C(0x0080000000000000)
+/** FL1GP: First Level 1 GB Page Support. */
+#define VTD_BF_CAP_REG_FL1GP_SHIFT 56
+#define VTD_BF_CAP_REG_FL1GP_MASK UINT64_C(0x0100000000000000)
+/** R: Reserved (bits 58:57). */
+#define VTD_BF_CAP_REG_RSVD_58_57_SHIFT 57
+#define VTD_BF_CAP_REG_RSVD_58_57_MASK UINT64_C(0x0600000000000000)
+/** PI: Posted Interrupt Support. */
+#define VTD_BF_CAP_REG_PI_SHIFT 59
+#define VTD_BF_CAP_REG_PI_MASK UINT64_C(0x0800000000000000)
+/** FL5LP: First Level 5-level Paging Support. */
+#define VTD_BF_CAP_REG_FL5LP_SHIFT 60
+#define VTD_BF_CAP_REG_FL5LP_MASK UINT64_C(0x1000000000000000)
+/** R: Reserved (bit 61). */
+#define VTD_BF_CAP_REG_RSVD_61_SHIFT 61
+#define VTD_BF_CAP_REG_RSVD_61_MASK UINT64_C(0x2000000000000000)
+/** ESIRTPS: Enhanced Set Interrupt Root Table Pointer Support. */
+#define VTD_BF_CAP_REG_ESIRTPS_SHIFT 62
+#define VTD_BF_CAP_REG_ESIRTPS_MASK UINT64_C(0x4000000000000000)
+/** : Enhanced Set Root Table Pointer Support. */
+#define VTD_BF_CAP_REG_ESRTPS_SHIFT 63
+#define VTD_BF_CAP_REG_ESRTPS_MASK UINT64_C(0x8000000000000000)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_CAP_REG_, UINT64_C(0), UINT64_MAX,
+ (ND, AFL, RWBF, PLMR, PHMR, CM, SAGAW, RSVD_15_13, MGAW, ZLR, RSVD_23, FRO, SLLPS, RSVD_38, PSI, NFR,
+ MAMV, DWD, DRD, FL1GP, RSVD_58_57, PI, FL5LP, RSVD_61, ESIRTPS, ESRTPS));
+
+/** RW: Read/write mask. */
+#define VTD_CAP_REG_RW_MASK UINT64_C(0)
+/** @} */
+
+
+/** @name Extended Capability Register (ECAP_REG).
+ * In accordance with the Intel spec.
+ * @{ */
+/** C: Page-walk Coherence. */
+#define VTD_BF_ECAP_REG_C_SHIFT 0
+#define VTD_BF_ECAP_REG_C_MASK UINT64_C(0x0000000000000001)
+/** QI: Queued Invalidation Support. */
+#define VTD_BF_ECAP_REG_QI_SHIFT 1
+#define VTD_BF_ECAP_REG_QI_MASK UINT64_C(0x0000000000000002)
+/** DT: Device-TLB Support. */
+#define VTD_BF_ECAP_REG_DT_SHIFT 2
+#define VTD_BF_ECAP_REG_DT_MASK UINT64_C(0x0000000000000004)
+/** IR: Interrupt Remapping Support. */
+#define VTD_BF_ECAP_REG_IR_SHIFT 3
+#define VTD_BF_ECAP_REG_IR_MASK UINT64_C(0x0000000000000008)
+/** EIM: Extended Interrupt Mode. */
+#define VTD_BF_ECAP_REG_EIM_SHIFT 4
+#define VTD_BF_ECAP_REG_EIM_MASK UINT64_C(0x0000000000000010)
+/** DEP: Deprecated MBZ. Reserved (bit 5). */
+#define VTD_BF_ECAP_REG_RSVD_5_SHIFT 5
+#define VTD_BF_ECAP_REG_RSVD_5_MASK UINT64_C(0x0000000000000020)
+/** PT: Pass Through. */
+#define VTD_BF_ECAP_REG_PT_SHIFT 6
+#define VTD_BF_ECAP_REG_PT_MASK UINT64_C(0x0000000000000040)
+/** SC: Snoop Control. */
+#define VTD_BF_ECAP_REG_SC_SHIFT 7
+#define VTD_BF_ECAP_REG_SC_MASK UINT64_C(0x0000000000000080)
+/** IRO: IOTLB Register Offset. */
+#define VTD_BF_ECAP_REG_IRO_SHIFT 8
+#define VTD_BF_ECAP_REG_IRO_MASK UINT64_C(0x000000000003ff00)
+/** R: Reserved (bits 19:18). */
+#define VTD_BF_ECAP_REG_RSVD_19_18_SHIFT 18
+#define VTD_BF_ECAP_REG_RSVD_19_18_MASK UINT64_C(0x00000000000c0000)
+/** MHMV: Maximum Handle Mask Value. */
+#define VTD_BF_ECAP_REG_MHMV_SHIFT 20
+#define VTD_BF_ECAP_REG_MHMV_MASK UINT64_C(0x0000000000f00000)
+/** DEP: Deprecated MBZ. Reserved (bit 24). */
+#define VTD_BF_ECAP_REG_RSVD_24_SHIFT 24
+#define VTD_BF_ECAP_REG_RSVD_24_MASK UINT64_C(0x0000000001000000)
+/** MTS: Memory Type Support. */
+#define VTD_BF_ECAP_REG_MTS_SHIFT 25
+#define VTD_BF_ECAP_REG_MTS_MASK UINT64_C(0x0000000002000000)
+/** NEST: Nested Translation Support. */
+#define VTD_BF_ECAP_REG_NEST_SHIFT 26
+#define VTD_BF_ECAP_REG_NEST_MASK UINT64_C(0x0000000004000000)
+/** R: Reserved (bit 27). */
+#define VTD_BF_ECAP_REG_RSVD_27_SHIFT 27
+#define VTD_BF_ECAP_REG_RSVD_27_MASK UINT64_C(0x0000000008000000)
+/** DEP: Deprecated MBZ. Reserved (bit 28). */
+#define VTD_BF_ECAP_REG_RSVD_28_SHIFT 28
+#define VTD_BF_ECAP_REG_RSVD_28_MASK UINT64_C(0x0000000010000000)
+/** PRS: Page Request Support. */
+#define VTD_BF_ECAP_REG_PRS_SHIFT 29
+#define VTD_BF_ECAP_REG_PRS_MASK UINT64_C(0x0000000020000000)
+/** ERS: Execute Request Support. */
+#define VTD_BF_ECAP_REG_ERS_SHIFT 30
+#define VTD_BF_ECAP_REG_ERS_MASK UINT64_C(0x0000000040000000)
+/** SRS: Supervisor Request Support. */
+#define VTD_BF_ECAP_REG_SRS_SHIFT 31
+#define VTD_BF_ECAP_REG_SRS_MASK UINT64_C(0x0000000080000000)
+/** R: Reserved (bit 32). */
+#define VTD_BF_ECAP_REG_RSVD_32_SHIFT 32
+#define VTD_BF_ECAP_REG_RSVD_32_MASK UINT64_C(0x0000000100000000)
+/** NWFS: No Write Flag Support. */
+#define VTD_BF_ECAP_REG_NWFS_SHIFT 33
+#define VTD_BF_ECAP_REG_NWFS_MASK UINT64_C(0x0000000200000000)
+/** EAFS: Extended Accessed Flags Support. */
+#define VTD_BF_ECAP_REG_EAFS_SHIFT 34
+#define VTD_BF_ECAP_REG_EAFS_MASK UINT64_C(0x0000000400000000)
+/** PSS: PASID Size Supported. */
+#define VTD_BF_ECAP_REG_PSS_SHIFT 35
+#define VTD_BF_ECAP_REG_PSS_MASK UINT64_C(0x000000f800000000)
+/** PASID: Process Address Space ID Support. */
+#define VTD_BF_ECAP_REG_PASID_SHIFT 40
+#define VTD_BF_ECAP_REG_PASID_MASK UINT64_C(0x0000010000000000)
+/** DIT: Device-TLB Invalidation Throttle. */
+#define VTD_BF_ECAP_REG_DIT_SHIFT 41
+#define VTD_BF_ECAP_REG_DIT_MASK UINT64_C(0x0000020000000000)
+/** PDS: Page-request Drain Support. */
+#define VTD_BF_ECAP_REG_PDS_SHIFT 42
+#define VTD_BF_ECAP_REG_PDS_MASK UINT64_C(0x0000040000000000)
+/** SMTS: Scalable-Mode Translation Support. */
+#define VTD_BF_ECAP_REG_SMTS_SHIFT 43
+#define VTD_BF_ECAP_REG_SMTS_MASK UINT64_C(0x0000080000000000)
+/** VCS: Virtual Command Support. */
+#define VTD_BF_ECAP_REG_VCS_SHIFT 44
+#define VTD_BF_ECAP_REG_VCS_MASK UINT64_C(0x0000100000000000)
+/** SLADS: Second-Level Accessed/Dirty Support. */
+#define VTD_BF_ECAP_REG_SLADS_SHIFT 45
+#define VTD_BF_ECAP_REG_SLADS_MASK UINT64_C(0x0000200000000000)
+/** SLTS: Second-Level Translation Support. */
+#define VTD_BF_ECAP_REG_SLTS_SHIFT 46
+#define VTD_BF_ECAP_REG_SLTS_MASK UINT64_C(0x0000400000000000)
+/** FLTS: First-Level Translation Support. */
+#define VTD_BF_ECAP_REG_FLTS_SHIFT 47
+#define VTD_BF_ECAP_REG_FLTS_MASK UINT64_C(0x0000800000000000)
+/** SMPWCS: Scalable-Mode Page-Walk Coherency Support. */
+#define VTD_BF_ECAP_REG_SMPWCS_SHIFT 48
+#define VTD_BF_ECAP_REG_SMPWCS_MASK UINT64_C(0x0001000000000000)
+/** RPS: RID-PASID Support. */
+#define VTD_BF_ECAP_REG_RPS_SHIFT 49
+#define VTD_BF_ECAP_REG_RPS_MASK UINT64_C(0x0002000000000000)
+/** R: Reserved (bits 51:50). */
+#define VTD_BF_ECAP_REG_RSVD_51_50_SHIFT 50
+#define VTD_BF_ECAP_REG_RSVD_51_50_MASK UINT64_C(0x000c000000000000)
+/** ADMS: Abort DMA Mode Support. */
+#define VTD_BF_ECAP_REG_ADMS_SHIFT 52
+#define VTD_BF_ECAP_REG_ADMS_MASK UINT64_C(0x0010000000000000)
+/** RPRIVS: RID_PRIV Support. */
+#define VTD_BF_ECAP_REG_RPRIVS_SHIFT 53
+#define VTD_BF_ECAP_REG_RPRIVS_MASK UINT64_C(0x0020000000000000)
+/** R: Reserved (bits 63:54). */
+#define VTD_BF_ECAP_REG_RSVD_63_54_SHIFT 54
+#define VTD_BF_ECAP_REG_RSVD_63_54_MASK UINT64_C(0xffc0000000000000)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_ECAP_REG_, UINT64_C(0), UINT64_MAX,
+ (C, QI, DT, IR, EIM, RSVD_5, PT, SC, IRO, RSVD_19_18, MHMV, RSVD_24, MTS, NEST, RSVD_27, RSVD_28,
+ PRS, ERS, SRS, RSVD_32, NWFS, EAFS, PSS, PASID, DIT, PDS, SMTS, VCS, SLADS, SLTS, FLTS, SMPWCS, RPS,
+ RSVD_51_50, ADMS, RPRIVS, RSVD_63_54));
+
+/** RW: Read/write mask. */
+#define VTD_ECAP_REG_RW_MASK UINT64_C(0)
+/** @} */
+
+
+/** @name Global Command Register (GCMD_REG).
+ * In accordance with the Intel spec.
+ * @{ */
+/** R: Reserved (bits 22:0). */
+#define VTD_BF_GCMD_REG_RSVD_22_0_SHIFT 0
+#define VTD_BF_GCMD_REG_RSVD_22_0_MASK UINT32_C(0x007fffff)
+/** CFI: Compatibility Format Interrupt. */
+#define VTD_BF_GCMD_REG_CFI_SHIFT 23
+#define VTD_BF_GCMD_REG_CFI_MASK UINT32_C(0x00800000)
+/** SIRTP: Set Interrupt Table Remap Pointer. */
+#define VTD_BF_GCMD_REG_SIRTP_SHIFT 24
+#define VTD_BF_GCMD_REG_SIRTP_MASK UINT32_C(0x01000000)
+/** IRE: Interrupt Remap Enable. */
+#define VTD_BF_GCMD_REG_IRE_SHIFT 25
+#define VTD_BF_GCMD_REG_IRE_MASK UINT32_C(0x02000000)
+/** QIE: Queued Invalidation Enable. */
+#define VTD_BF_GCMD_REG_QIE_SHIFT 26
+#define VTD_BF_GCMD_REG_QIE_MASK UINT32_C(0x04000000)
+/** WBF: Write Buffer Flush. */
+#define VTD_BF_GCMD_REG_WBF_SHIFT 27
+#define VTD_BF_GCMD_REG_WBF_MASK UINT32_C(0x08000000)
+/** EAFL: Enable Advance Fault Logging. */
+#define VTD_BF_GCMD_REG_EAFL_SHIFT 28
+#define VTD_BF_GCMD_REG_EAFL_MASK UINT32_C(0x10000000)
+/** SFL: Set Fault Log. */
+#define VTD_BF_GCMD_REG_SFL_SHIFT 29
+#define VTD_BF_GCMD_REG_SFL_MASK UINT32_C(0x20000000)
+/** SRTP: Set Root Table Pointer. */
+#define VTD_BF_GCMD_REG_SRTP_SHIFT 30
+#define VTD_BF_GCMD_REG_SRTP_MASK UINT32_C(0x40000000)
+/** TE: Translation Enable. */
+#define VTD_BF_GCMD_REG_TE_SHIFT 31
+#define VTD_BF_GCMD_REG_TE_MASK UINT32_C(0x80000000)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_GCMD_REG_, UINT32_C(0), UINT32_MAX,
+ (RSVD_22_0, CFI, SIRTP, IRE, QIE, WBF, EAFL, SFL, SRTP, TE));
+
+/** RW: Read/write mask. */
+#define VTD_GCMD_REG_RW_MASK ( VTD_BF_GCMD_REG_TE_MASK | VTD_BF_GCMD_REG_SRTP_MASK \
+ | VTD_BF_GCMD_REG_SFL_MASK | VTD_BF_GCMD_REG_EAFL_MASK \
+ | VTD_BF_GCMD_REG_WBF_MASK | VTD_BF_GCMD_REG_QIE_MASK \
+ | VTD_BF_GCMD_REG_IRE_MASK | VTD_BF_GCMD_REG_SIRTP_MASK \
+ | VTD_BF_GCMD_REG_CFI_MASK)
+/** @} */
+
+
+/** @name Global Status Register (GSTS_REG).
+ * In accordance with the Intel spec.
+ * @{ */
+/** R: Reserved (bits 22:0). */
+#define VTD_BF_GSTS_REG_RSVD_22_0_SHIFT 0
+#define VTD_BF_GSTS_REG_RSVD_22_0_MASK UINT32_C(0x007fffff)
+/** CFIS: Compatibility Format Interrupt Status. */
+#define VTD_BF_GSTS_REG_CFIS_SHIFT 23
+#define VTD_BF_GSTS_REG_CFIS_MASK UINT32_C(0x00800000)
+/** IRTPS: Interrupt Remapping Table Pointer Status. */
+#define VTD_BF_GSTS_REG_IRTPS_SHIFT 24
+#define VTD_BF_GSTS_REG_IRTPS_MASK UINT32_C(0x01000000)
+/** IRES: Interrupt Remapping Enable Status. */
+#define VTD_BF_GSTS_REG_IRES_SHIFT 25
+#define VTD_BF_GSTS_REG_IRES_MASK UINT32_C(0x02000000)
+/** QIES: Queued Invalidation Enable Status. */
+#define VTD_BF_GSTS_REG_QIES_SHIFT 26
+#define VTD_BF_GSTS_REG_QIES_MASK UINT32_C(0x04000000)
+/** WBFS: Write Buffer Flush Status. */
+#define VTD_BF_GSTS_REG_WBFS_SHIFT 27
+#define VTD_BF_GSTS_REG_WBFS_MASK UINT32_C(0x08000000)
+/** AFLS: Advanced Fault Logging Status. */
+#define VTD_BF_GSTS_REG_AFLS_SHIFT 28
+#define VTD_BF_GSTS_REG_AFLS_MASK UINT32_C(0x10000000)
+/** FLS: Fault Log Status. */
+#define VTD_BF_GSTS_REG_FLS_SHIFT 29
+#define VTD_BF_GSTS_REG_FLS_MASK UINT32_C(0x20000000)
+/** RTPS: Root Table Pointer Status. */
+#define VTD_BF_GSTS_REG_RTPS_SHIFT 30
+#define VTD_BF_GSTS_REG_RTPS_MASK UINT32_C(0x40000000)
+/** TES: Translation Enable Status. */
+#define VTD_BF_GSTS_REG_TES_SHIFT 31
+#define VTD_BF_GSTS_REG_TES_MASK UINT32_C(0x80000000)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_GSTS_REG_, UINT32_C(0), UINT32_MAX,
+ (RSVD_22_0, CFIS, IRTPS, IRES, QIES, WBFS, AFLS, FLS, RTPS, TES));
+
+/** RW: Read/write mask. */
+#define VTD_GSTS_REG_RW_MASK UINT32_C(0)
+/** @} */
+
+
+/** @name Root Table Address Register (RTADDR_REG).
+ * In accordance with the Intel spec.
+ * @{ */
+/** R: Reserved (bits 9:0). */
+#define VTD_BF_RTADDR_REG_RSVD_9_0_SHIFT 0
+#define VTD_BF_RTADDR_REG_RSVD_9_0_MASK UINT64_C(0x00000000000003ff)
+/** TTM: Translation Table Mode. */
+#define VTD_BF_RTADDR_REG_TTM_SHIFT 10
+#define VTD_BF_RTADDR_REG_TTM_MASK UINT64_C(0x0000000000000c00)
+/** RTA: Root Table Address. */
+#define VTD_BF_RTADDR_REG_RTA_SHIFT 12
+#define VTD_BF_RTADDR_REG_RTA_MASK UINT64_C(0xfffffffffffff000)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_RTADDR_REG_, UINT64_C(0), UINT64_MAX,
+ (RSVD_9_0, TTM, RTA));
+
+/** RW: Read/write mask. */
+#define VTD_RTADDR_REG_RW_MASK UINT64_C(0xfffffffffffffc00)
+
+/** RTADDR_REG.TTM: Legacy mode. */
+#define VTD_TTM_LEGACY_MODE 0
+/** RTADDR_REG.TTM: Scalable mode. */
+#define VTD_TTM_SCALABLE_MODE 1
+/** RTADDR_REG.TTM: Reserved. */
+#define VTD_TTM_RSVD 2
+/** RTADDR_REG.TTM: Abort DMA mode. */
+#define VTD_TTM_ABORT_DMA_MODE 3
+/** @} */
+
+
+/** @name Context Command Register (CCMD_REG).
+ * In accordance with the Intel spec.
+ * @{ */
+/** DID: Domain-ID. */
+#define VTD_BF_CCMD_REG_DID_SHIFT 0
+#define VTD_BF_CCMD_REG_DID_MASK UINT64_C(0x000000000000ffff)
+/** SID: Source-ID. */
+#define VTD_BF_CCMD_REG_SID_SHIFT 16
+#define VTD_BF_CCMD_REG_SID_MASK UINT64_C(0x00000000ffff0000)
+/** FM: Function Mask. */
+#define VTD_BF_CCMD_REG_FM_SHIFT 32
+#define VTD_BF_CCMD_REG_FM_MASK UINT64_C(0x0000000300000000)
+/** R: Reserved (bits 58:34). */
+#define VTD_BF_CCMD_REG_RSVD_58_34_SHIFT 34
+#define VTD_BF_CCMD_REG_RSVD_58_34_MASK UINT64_C(0x07fffffc00000000)
+/** CAIG: Context Actual Invalidation Granularity. */
+#define VTD_BF_CCMD_REG_CAIG_SHIFT 59
+#define VTD_BF_CCMD_REG_CAIG_MASK UINT64_C(0x1800000000000000)
+/** CIRG: Context Invalidation Request Granularity. */
+#define VTD_BF_CCMD_REG_CIRG_SHIFT 61
+#define VTD_BF_CCMD_REG_CIRG_MASK UINT64_C(0x6000000000000000)
+/** ICC: Invalidation Context Cache. */
+#define VTD_BF_CCMD_REG_ICC_SHIFT 63
+#define VTD_BF_CCMD_REG_ICC_MASK UINT64_C(0x8000000000000000)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_CCMD_REG_, UINT64_C(0), UINT64_MAX,
+ (DID, SID, FM, RSVD_58_34, CAIG, CIRG, ICC));
+
+/** RW: Read/write mask. */
+#define VTD_CCMD_REG_RW_MASK ( VTD_BF_CCMD_REG_DID_MASK | VTD_BF_CCMD_REG_SID_MASK \
+ | VTD_BF_CCMD_REG_FM_MASK | VTD_BF_CCMD_REG_CIRG_MASK \
+ | VTD_BF_CCMD_REG_ICC_MASK)
+/** @} */
+
+
+/** @name IOTLB Invalidation Register (IOTLB_REG).
+ * In accordance with the Intel spec.
+ * @{ */
+/** R: Reserved (bits 31:0). */
+#define VTD_BF_IOTLB_REG_RSVD_31_0_SHIFT 0
+#define VTD_BF_IOTLB_REG_RSVD_31_0_MASK UINT64_C(0x00000000ffffffff)
+/** DID: Domain-ID. */
+#define VTD_BF_IOTLB_REG_DID_SHIFT 32
+#define VTD_BF_IOTLB_REG_DID_MASK UINT64_C(0x0000ffff00000000)
+/** DW: Draining Writes. */
+#define VTD_BF_IOTLB_REG_DW_SHIFT 48
+#define VTD_BF_IOTLB_REG_DW_MASK UINT64_C(0x0001000000000000)
+/** DR: Draining Reads. */
+#define VTD_BF_IOTLB_REG_DR_SHIFT 49
+#define VTD_BF_IOTLB_REG_DR_MASK UINT64_C(0x0002000000000000)
+/** R: Reserved (bits 56:50). */
+#define VTD_BF_IOTLB_REG_RSVD_56_50_SHIFT 50
+#define VTD_BF_IOTLB_REG_RSVD_56_50_MASK UINT64_C(0x01fc000000000000)
+/** IAIG: IOTLB Actual Invalidation Granularity. */
+#define VTD_BF_IOTLB_REG_IAIG_SHIFT 57
+#define VTD_BF_IOTLB_REG_IAIG_MASK UINT64_C(0x0600000000000000)
+/** R: Reserved (bit 59). */
+#define VTD_BF_IOTLB_REG_RSVD_59_SHIFT 59
+#define VTD_BF_IOTLB_REG_RSVD_59_MASK UINT64_C(0x0800000000000000)
+/** IIRG: IOTLB Invalidation Request Granularity. */
+#define VTD_BF_IOTLB_REG_IIRG_SHIFT 60
+#define VTD_BF_IOTLB_REG_IIRG_MASK UINT64_C(0x3000000000000000)
+/** R: Reserved (bit 62). */
+#define VTD_BF_IOTLB_REG_RSVD_62_SHIFT 62
+#define VTD_BF_IOTLB_REG_RSVD_62_MASK UINT64_C(0x4000000000000000)
+/** IVT: Invalidate IOTLB. */
+#define VTD_BF_IOTLB_REG_IVT_SHIFT 63
+#define VTD_BF_IOTLB_REG_IVT_MASK UINT64_C(0x8000000000000000)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_IOTLB_REG_, UINT64_C(0), UINT64_MAX,
+ (RSVD_31_0, DID, DW, DR, RSVD_56_50, IAIG, RSVD_59, IIRG, RSVD_62, IVT));
+
+/** RW: Read/write mask. */
+#define VTD_IOTLB_REG_RW_MASK ( VTD_BF_IOTLB_REG_DID_MASK | VTD_BF_IOTLB_REG_DW_MASK \
+ | VTD_BF_IOTLB_REG_DR_MASK | VTD_BF_IOTLB_REG_IIRG_MASK \
+ | VTD_BF_IOTLB_REG_IVT_MASK)
+/** @} */
+
+
+/** @name Invalidate Address Register (IVA_REG).
+ * In accordance with the Intel spec.
+ * @{ */
+/** AM: Address Mask. */
+#define VTD_BF_IVA_REG_AM_SHIFT 0
+#define VTD_BF_IVA_REG_AM_MASK UINT64_C(0x000000000000003f)
+/** IH: Invalidation Hint. */
+#define VTD_BF_IVA_REG_IH_SHIFT 6
+#define VTD_BF_IVA_REG_IH_MASK UINT64_C(0x0000000000000040)
+/** R: Reserved (bits 11:7). */
+#define VTD_BF_IVA_REG_RSVD_11_7_SHIFT 7
+#define VTD_BF_IVA_REG_RSVD_11_7_MASK UINT64_C(0x0000000000000f80)
+/** ADDR: Address. */
+#define VTD_BF_IVA_REG_ADDR_SHIFT 12
+#define VTD_BF_IVA_REG_ADDR_MASK UINT64_C(0xfffffffffffff000)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_IVA_REG_, UINT64_C(0), UINT64_MAX,
+ (AM, IH, RSVD_11_7, ADDR));
+
+/** RW: Read/write mask. */
+#define VTD_IVA_REG_RW_MASK ( VTD_BF_IVA_REG_AM_MASK | VTD_BF_IVA_REG_IH_MASK \
+ | VTD_BF_IVA_REG_ADDR_MASK)
+/** @} */
+
+
+/** @name Fault Status Register (FSTS_REG).
+ * In accordance with the Intel spec.
+ * @{ */
+/** PFO: Primary Fault Overflow. */
+#define VTD_BF_FSTS_REG_PFO_SHIFT 0
+#define VTD_BF_FSTS_REG_PFO_MASK UINT32_C(0x00000001)
+/** PPF: Primary Pending Fault. */
+#define VTD_BF_FSTS_REG_PPF_SHIFT 1
+#define VTD_BF_FSTS_REG_PPF_MASK UINT32_C(0x00000002)
+/** AFO: Advanced Fault Overflow. */
+#define VTD_BF_FSTS_REG_AFO_SHIFT 2
+#define VTD_BF_FSTS_REG_AFO_MASK UINT32_C(0x00000004)
+/** APF: Advanced Pending Fault. */
+#define VTD_BF_FSTS_REG_APF_SHIFT 3
+#define VTD_BF_FSTS_REG_APF_MASK UINT32_C(0x00000008)
+/** IQE: Invalidation Queue Error. */
+#define VTD_BF_FSTS_REG_IQE_SHIFT 4
+#define VTD_BF_FSTS_REG_IQE_MASK UINT32_C(0x00000010)
+/** ICE: Invalidation Completion Error. */
+#define VTD_BF_FSTS_REG_ICE_SHIFT 5
+#define VTD_BF_FSTS_REG_ICE_MASK UINT32_C(0x00000020)
+/** ITE: Invalidation Timeout Error. */
+#define VTD_BF_FSTS_REG_ITE_SHIFT 6
+#define VTD_BF_FSTS_REG_ITE_MASK UINT32_C(0x00000040)
+/** DEP: Deprecated MBZ. Reserved (bit 7). */
+#define VTD_BF_FSTS_REG_RSVD_7_SHIFT 7
+#define VTD_BF_FSTS_REG_RSVD_7_MASK UINT32_C(0x00000080)
+/** FRI: Fault Record Index. */
+#define VTD_BF_FSTS_REG_FRI_SHIFT 8
+#define VTD_BF_FSTS_REG_FRI_MASK UINT32_C(0x0000ff00)
+/** R: Reserved (bits 31:16). */
+#define VTD_BF_FSTS_REG_RSVD_31_16_SHIFT 16
+#define VTD_BF_FSTS_REG_RSVD_31_16_MASK UINT32_C(0xffff0000)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_FSTS_REG_, UINT32_C(0), UINT32_MAX,
+ (PFO, PPF, AFO, APF, IQE, ICE, ITE, RSVD_7, FRI, RSVD_31_16));
+
+/** RW: Read/write mask. */
+#define VTD_FSTS_REG_RW_MASK ( VTD_BF_FSTS_REG_PFO_MASK | VTD_BF_FSTS_REG_AFO_MASK \
+ | VTD_BF_FSTS_REG_APF_MASK | VTD_BF_FSTS_REG_IQE_MASK \
+ | VTD_BF_FSTS_REG_ICE_MASK | VTD_BF_FSTS_REG_ITE_MASK)
+/** RW1C: Read-only-status, Write-1-to-clear status mask. */
+#define VTD_FSTS_REG_RW1C_MASK ( VTD_BF_FSTS_REG_PFO_MASK | VTD_BF_FSTS_REG_AFO_MASK \
+ | VTD_BF_FSTS_REG_APF_MASK | VTD_BF_FSTS_REG_IQE_MASK \
+ | VTD_BF_FSTS_REG_ICE_MASK | VTD_BF_FSTS_REG_ITE_MASK)
+/** @} */
+
+
+/** @name Fault Event Control Register (FECTL_REG).
+ * In accordance with the Intel spec.
+ * @{ */
+/** R: Reserved (bits 29:0). */
+#define VTD_BF_FECTL_REG_RSVD_29_0_SHIFT 0
+#define VTD_BF_FECTL_REG_RSVD_29_0_MASK UINT32_C(0x3fffffff)
+/** IP: Interrupt Pending. */
+#define VTD_BF_FECTL_REG_IP_SHIFT 30
+#define VTD_BF_FECTL_REG_IP_MASK UINT32_C(0x40000000)
+/** IM: Interrupt Mask. */
+#define VTD_BF_FECTL_REG_IM_SHIFT 31
+#define VTD_BF_FECTL_REG_IM_MASK UINT32_C(0x80000000)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_FECTL_REG_, UINT32_C(0), UINT32_MAX,
+ (RSVD_29_0, IP, IM));
+
+/** RW: Read/write mask. */
+#define VTD_FECTL_REG_RW_MASK VTD_BF_FECTL_REG_IM_MASK
+/** @} */
+
+
+/** @name Fault Event Data Register (FEDATA_REG).
+ * In accordance with the Intel spec.
+ * @{ */
+/** IMD: Interrupt Message Data. */
+#define VTD_BF_FEDATA_REG_IMD_SHIFT 0
+#define VTD_BF_FEDATA_REG_IMD_MASK UINT32_C(0x0000ffff)
+/** R: Reserved (bits 31:16). VT-d specs. prior to 2021 had EIMD here. */
+#define VTD_BF_FEDATA_REG_RSVD_31_16_SHIFT 16
+#define VTD_BF_FEDATA_REG_RSVD_31_16_MASK UINT32_C(0xffff0000)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_FEDATA_REG_, UINT32_C(0), UINT32_MAX,
+ (IMD, RSVD_31_16));
+
+/** RW: Read/write mask, see 5.1.6 "Remapping Hardware Event Interrupt
+ * Programming". */
+#define VTD_FEDATA_REG_RW_MASK UINT32_C(0x000001ff)
+/** @} */
+
+
+/** @name Fault Event Address Register (FEADDR_REG).
+ * In accordance with the Intel spec.
+ * @{ */
+/** R: Reserved (bits 1:0). */
+#define VTD_BF_FEADDR_REG_RSVD_1_0_SHIFT 0
+#define VTD_BF_FEADDR_REG_RSVD_1_0_MASK UINT32_C(0x00000003)
+/** MA: Message Address. */
+#define VTD_BF_FEADDR_REG_MA_SHIFT 2
+#define VTD_BF_FEADDR_REG_MA_MASK UINT32_C(0xfffffffc)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_FEADDR_REG_, UINT32_C(0), UINT32_MAX,
+ (RSVD_1_0, MA));
+
+/** RW: Read/write mask. */
+#define VTD_FEADDR_REG_RW_MASK VTD_BF_FEADDR_REG_MA_MASK
+/** @} */
+
+
+/** @name Fault Event Upper Address Register (FEUADDR_REG).
+ * In accordance with the Intel spec.
+ * @{ */
+/** MUA: Message Upper Address. */
+#define VTD_BF_FEUADDR_REG_MA_SHIFT 0
+#define VTD_BF_FEUADDR_REG_MA_MASK UINT32_C(0xffffffff)
+
+/** RW: Read/write mask. */
+#define VTD_FEUADDR_REG_RW_MASK VTD_BF_FEUADDR_REG_MA_MASK
+/** @} */
+
+
+/** @name Fault Recording Register (FRCD_REG).
+ * In accordance with the Intel spec.
+ * @{ */
+/** R: Reserved (bits 11:0). */
+#define VTD_BF_0_FRCD_REG_RSVD_11_0_SHIFT 0
+#define VTD_BF_0_FRCD_REG_RSVD_11_0_MASK UINT64_C(0x0000000000000fff)
+/** FI: Fault Info. */
+#define VTD_BF_0_FRCD_REG_FI_SHIFT 12
+#define VTD_BF_0_FRCD_REG_FI_MASK UINT64_C(0xfffffffffffff000)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_0_FRCD_REG_, UINT64_C(0), UINT64_MAX,
+ (RSVD_11_0, FI));
+
+/** SID: Source Identifier. */
+#define VTD_BF_1_FRCD_REG_SID_SHIFT 0
+#define VTD_BF_1_FRCD_REG_SID_MASK UINT64_C(0x000000000000ffff)
+/** R: Reserved (bits 27:16). */
+#define VTD_BF_1_FRCD_REG_RSVD_27_16_SHIFT 16
+#define VTD_BF_1_FRCD_REG_RSVD_27_16_MASK UINT64_C(0x000000000fff0000)
+/** T2: Type bit 2. */
+#define VTD_BF_1_FRCD_REG_T2_SHIFT 28
+#define VTD_BF_1_FRCD_REG_T2_MASK UINT64_C(0x0000000010000000)
+/** PRIV: Privilege Mode. */
+#define VTD_BF_1_FRCD_REG_PRIV_SHIFT 29
+#define VTD_BF_1_FRCD_REG_PRIV_MASK UINT64_C(0x0000000020000000)
+/** EXE: Execute Permission Requested. */
+#define VTD_BF_1_FRCD_REG_EXE_SHIFT 30
+#define VTD_BF_1_FRCD_REG_EXE_MASK UINT64_C(0x0000000040000000)
+/** PP: PASID Present. */
+#define VTD_BF_1_FRCD_REG_PP_SHIFT 31
+#define VTD_BF_1_FRCD_REG_PP_MASK UINT64_C(0x0000000080000000)
+/** FR: Fault Reason. */
+#define VTD_BF_1_FRCD_REG_FR_SHIFT 32
+#define VTD_BF_1_FRCD_REG_FR_MASK UINT64_C(0x000000ff00000000)
+/** PV: PASID Value. */
+#define VTD_BF_1_FRCD_REG_PV_SHIFT 40
+#define VTD_BF_1_FRCD_REG_PV_MASK UINT64_C(0x0fffff0000000000)
+/** AT: Address Type. */
+#define VTD_BF_1_FRCD_REG_AT_SHIFT 60
+#define VTD_BF_1_FRCD_REG_AT_MASK UINT64_C(0x3000000000000000)
+/** T1: Type bit 1. */
+#define VTD_BF_1_FRCD_REG_T1_SHIFT 62
+#define VTD_BF_1_FRCD_REG_T1_MASK UINT64_C(0x4000000000000000)
+/** F: Fault. */
+#define VTD_BF_1_FRCD_REG_F_SHIFT 63
+#define VTD_BF_1_FRCD_REG_F_MASK UINT64_C(0x8000000000000000)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_1_FRCD_REG_, UINT64_C(0), UINT64_MAX,
+ (SID, RSVD_27_16, T2, PRIV, EXE, PP, FR, PV, AT, T1, F));
+
+/** RW: Read/write mask. */
+#define VTD_FRCD_REG_LO_RW_MASK UINT64_C(0)
+#define VTD_FRCD_REG_HI_RW_MASK VTD_BF_1_FRCD_REG_F_MASK
+/** RW1C: Read-only-status, Write-1-to-clear status mask. */
+#define VTD_FRCD_REG_LO_RW1C_MASK UINT64_C(0)
+#define VTD_FRCD_REG_HI_RW1C_MASK VTD_BF_1_FRCD_REG_F_MASK
+/** @} */
+
+
+/**
+ * VT-d faulted address translation request types (FRCD_REG::T2).
+ * In accordance with the Intel spec.
+ */
+typedef enum VTDREQTYPE
+{
+ VTDREQTYPE_WRITE = 0, /**< Memory access write request. */
+ VTDREQTYPE_PAGE, /**< Page translation request. */
+ VTDREQTYPE_READ, /**< Memory access read request. */
+ VTDREQTYPE_ATOMIC_OP /**< Memory access atomic operation. */
+} VTDREQTYPE;
+/** Pointer to a VTDREQTYPE. */
+typedef VTDREQTYPE *PVTDREQTYPE;
+
+
+/** @name Advanced Fault Log Register (AFLOG_REG).
+ * In accordance with the Intel spec.
+ * @{ */
+/** R: Reserved (bits 8:0). */
+#define VTD_BF_0_AFLOG_REG_RSVD_8_0_SHIFT 0
+#define VTD_BF_0_AFLOG_REG_RSVD_8_0_MASK UINT64_C(0x00000000000001ff)
+/** FLS: Fault Log Size. */
+#define VTD_BF_0_AFLOG_REG_FLS_SHIFT 9
+#define VTD_BF_0_AFLOG_REG_FLS_MASK UINT64_C(0x0000000000000e00)
+/** FLA: Fault Log Address. */
+#define VTD_BF_0_AFLOG_REG_FLA_SHIFT 12
+#define VTD_BF_0_AFLOG_REG_FLA_MASK UINT64_C(0xfffffffffffff000)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_0_AFLOG_REG_, UINT64_C(0), UINT64_MAX,
+ (RSVD_8_0, FLS, FLA));
+
+/** RW: Read/write mask. */
+#define VTD_AFLOG_REG_RW_MASK (VTD_BF_0_AFLOG_REG_FLS_MASK | VTD_BF_0_AFLOG_REG_FLA_MASK)
+/** @} */
+
+
+/** @name Protected Memory Enable Register (PMEN_REG).
+ * In accordance with the Intel spec.
+ * @{ */
+/** PRS: Protected Region Status. */
+#define VTD_BF_PMEN_REG_PRS_SHIFT 0
+#define VTD_BF_PMEN_REG_PRS_MASK UINT32_C(0x00000001)
+/** R: Reserved (bits 30:1). */
+#define VTD_BF_PMEN_REG_RSVD_30_1_SHIFT 1
+#define VTD_BF_PMEN_REG_RSVD_30_1_MASK UINT32_C(0x7ffffffe)
+/** EPM: Enable Protected Memory. */
+#define VTD_BF_PMEN_REG_EPM_SHIFT 31
+#define VTD_BF_PMEN_REG_EPM_MASK UINT32_C(0x80000000)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_PMEN_REG_, UINT32_C(0), UINT32_MAX,
+ (PRS, RSVD_30_1, EPM));
+
+/** RW: Read/write mask. */
+#define VTD_PMEN_REG_RW_MASK VTD_BF_PMEN_REG_EPM_MASK
+/** @} */
+
+
+/** @name Invalidation Queue Head Register (IQH_REG).
+ * In accordance with the Intel spec.
+ * @{ */
+/** R: Reserved (bits 3:0). */
+#define VTD_BF_IQH_REG_RSVD_3_0_SHIFT 0
+#define VTD_BF_IQH_REG_RSVD_3_0_MASK UINT64_C(0x000000000000000f)
+/** QH: Queue Head. */
+#define VTD_BF_IQH_REG_QH_SHIFT 4
+#define VTD_BF_IQH_REG_QH_MASK UINT64_C(0x000000000007fff0)
+/** R: Reserved (bits 63:19). */
+#define VTD_BF_IQH_REG_RSVD_63_19_SHIFT 19
+#define VTD_BF_IQH_REG_RSVD_63_19_MASK UINT64_C(0xfffffffffff80000)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_IQH_REG_, UINT64_C(0), UINT64_MAX,
+ (RSVD_3_0, QH, RSVD_63_19));
+
+/** RW: Read/write mask. */
+#define VTD_IQH_REG_RW_MASK UINT64_C(0x0)
+/** @} */
+
+
+/** @name Invalidation Queue Tail Register (IQT_REG).
+ * In accordance with the Intel spec.
+ * @{ */
+/** R: Reserved (bits 3:0). */
+#define VTD_BF_IQT_REG_RSVD_3_0_SHIFT 0
+#define VTD_BF_IQT_REG_RSVD_3_0_MASK UINT64_C(0x000000000000000f)
+/** QH: Queue Tail. */
+#define VTD_BF_IQT_REG_QT_SHIFT 4
+#define VTD_BF_IQT_REG_QT_MASK UINT64_C(0x000000000007fff0)
+/** R: Reserved (bits 63:19). */
+#define VTD_BF_IQT_REG_RSVD_63_19_SHIFT 19
+#define VTD_BF_IQT_REG_RSVD_63_19_MASK UINT64_C(0xfffffffffff80000)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_IQT_REG_, UINT64_C(0), UINT64_MAX,
+ (RSVD_3_0, QT, RSVD_63_19));
+
+/** RW: Read/write mask. */
+#define VTD_IQT_REG_RW_MASK VTD_BF_IQT_REG_QT_MASK
+/** @} */
+
+
+/** @name Invalidation Queue Address Register (IQA_REG).
+ * In accordance with the Intel spec.
+ * @{ */
+/** QS: Queue Size. */
+#define VTD_BF_IQA_REG_QS_SHIFT 0
+#define VTD_BF_IQA_REG_QS_MASK UINT64_C(0x0000000000000007)
+/** R: Reserved (bits 10:3). */
+#define VTD_BF_IQA_REG_RSVD_10_3_SHIFT 3
+#define VTD_BF_IQA_REG_RSVD_10_3_MASK UINT64_C(0x00000000000007f8)
+/** DW: Descriptor Width. */
+#define VTD_BF_IQA_REG_DW_SHIFT 11
+#define VTD_BF_IQA_REG_DW_MASK UINT64_C(0x0000000000000800)
+/** IQA: Invalidation Queue Base Address. */
+#define VTD_BF_IQA_REG_IQA_SHIFT 12
+#define VTD_BF_IQA_REG_IQA_MASK UINT64_C(0xfffffffffffff000)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_IQA_REG_, UINT64_C(0), UINT64_MAX,
+ (QS, RSVD_10_3, DW, IQA));
+
+/** RW: Read/write mask. */
+#define VTD_IQA_REG_RW_MASK ( VTD_BF_IQA_REG_QS_MASK | VTD_BF_IQA_REG_DW_MASK \
+ | VTD_BF_IQA_REG_IQA_MASK)
+/** DW: 128-bit descriptor. */
+#define VTD_IQA_REG_DW_128_BIT 0
+/** DW: 256-bit descriptor. */
+#define VTD_IQA_REG_DW_256_BIT 1
+/** @} */
+
+
+/** @name Invalidation Completion Status Register (ICS_REG).
+ * In accordance with the Intel spec.
+ * @{ */
+/** IWC: Invalidation Wait Descriptor Complete. */
+#define VTD_BF_ICS_REG_IWC_SHIFT 0
+#define VTD_BF_ICS_REG_IWC_MASK UINT32_C(0x00000001)
+/** R: Reserved (bits 31:1). */
+#define VTD_BF_ICS_REG_RSVD_31_1_SHIFT 1
+#define VTD_BF_ICS_REG_RSVD_31_1_MASK UINT32_C(0xfffffffe)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_ICS_REG_, UINT32_C(0), UINT32_MAX,
+ (IWC, RSVD_31_1));
+
+/** RW: Read/write mask. */
+#define VTD_ICS_REG_RW_MASK VTD_BF_ICS_REG_IWC_MASK
+/** RW1C: Read-only-status, Write-1-to-clear status mask. */
+#define VTD_ICS_REG_RW1C_MASK VTD_BF_ICS_REG_IWC_MASK
+/** @} */
+
+
+/** @name Invalidation Event Control Register (IECTL_REG).
+ * In accordance with the Intel spec.
+ * @{ */
+/** R: Reserved (bits 29:0). */
+#define VTD_BF_IECTL_REG_RSVD_29_0_SHIFT 0
+#define VTD_BF_IECTL_REG_RSVD_29_0_MASK UINT32_C(0x3fffffff)
+/** IP: Interrupt Pending. */
+#define VTD_BF_IECTL_REG_IP_SHIFT 30
+#define VTD_BF_IECTL_REG_IP_MASK UINT32_C(0x40000000)
+/** IM: Interrupt Mask. */
+#define VTD_BF_IECTL_REG_IM_SHIFT 31
+#define VTD_BF_IECTL_REG_IM_MASK UINT32_C(0x80000000)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_IECTL_REG_, UINT32_C(0), UINT32_MAX,
+ (RSVD_29_0, IP, IM));
+
+/** RW: Read/write mask. */
+#define VTD_IECTL_REG_RW_MASK VTD_BF_IECTL_REG_IM_MASK
+/** @} */
+
+
+/** @name Invalidation Event Data Register (IEDATA_REG).
+ * In accordance with the Intel spec.
+ * @{ */
+/** IMD: Interrupt Message Data. */
+#define VTD_BF_IEDATA_REG_IMD_SHIFT 0
+#define VTD_BF_IEDATA_REG_IMD_MASK UINT32_C(0x0000ffff)
+/** R: Reserved (bits 31:16). VT-d specs. prior to 2021 had EIMD here. */
+#define VTD_BF_IEDATA_REG_RSVD_31_16_SHIFT 16
+#define VTD_BF_IEDATA_REG_RSVD_31_16_MASK UINT32_C(0xffff0000)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_IEDATA_REG_, UINT32_C(0), UINT32_MAX,
+ (IMD, RSVD_31_16));
+
+/** RW: Read/write mask, see 5.1.6 "Remapping Hardware Event Interrupt
+ * Programming". */
+#define VTD_IEDATA_REG_RW_MASK UINT32_C(0x000001ff)
+/** @} */
+
+
+/** @name Invalidation Event Address Register (IEADDR_REG).
+ * In accordance with the Intel spec.
+ * @{ */
+/** R: Reserved (bits 1:0). */
+#define VTD_BF_IEADDR_REG_RSVD_1_0_SHIFT 0
+#define VTD_BF_IEADDR_REG_RSVD_1_0_MASK UINT32_C(0x00000003)
+/** MA: Message Address. */
+#define VTD_BF_IEADDR_REG_MA_SHIFT 2
+#define VTD_BF_IEADDR_REG_MA_MASK UINT32_C(0xfffffffc)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_IEADDR_REG_, UINT32_C(0), UINT32_MAX,
+ (RSVD_1_0, MA));
+
+/** RW: Read/write mask. */
+#define VTD_IEADDR_REG_RW_MASK VTD_BF_IEADDR_REG_MA_MASK
+/** @} */
+
+
+/** @name Invalidation Event Upper Address Register (IEUADDR_REG).
+ * @{ */
+/** MUA: Message Upper Address. */
+#define VTD_BF_IEUADDR_REG_MUA_SHIFT 0
+#define VTD_BF_IEUADDR_REG_MUA_MASK UINT32_C(0xffffffff)
+
+/** RW: Read/write mask. */
+#define VTD_IEUADDR_REG_RW_MASK VTD_BF_IEUADDR_REG_MUA_MASK
+/** @} */
+
+
+/** @name Invalidation Queue Error Record Register (IQERCD_REG).
+ * In accordance with the Intel spec.
+ * @{ */
+/** IQEI: Invalidation Queue Error Info. */
+#define VTD_BF_IQERCD_REG_IQEI_SHIFT 0
+#define VTD_BF_IQERCD_REG_IQEI_MASK UINT64_C(0x000000000000000f)
+/** R: Reserved (bits 31:4). */
+#define VTD_BF_IQERCD_REG_RSVD_31_4_SHIFT 4
+#define VTD_BF_IQERCD_REG_RSVD_31_4_MASK UINT64_C(0x00000000fffffff0)
+/** ITESID: Invalidation Timeout Error Source Identifier. */
+#define VTD_BF_IQERCD_REG_ITESID_SHIFT 32
+#define VTD_BF_IQERCD_REG_ITESID_MASK UINT64_C(0x0000ffff00000000)
+/** ICESID: Invalidation Completion Error Source Identifier. */
+#define VTD_BF_IQERCD_REG_ICESID_SHIFT 48
+#define VTD_BF_IQERCD_REG_ICESID_MASK UINT64_C(0xffff000000000000)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_IQERCD_REG_, UINT64_C(0), UINT64_MAX,
+ (IQEI, RSVD_31_4, ITESID, ICESID));
+
+/** RW: Read/write mask. */
+#define VTD_IQERCD_REG_RW_MASK UINT64_C(0)
+
+/** Invalidation Queue Error Information. */
+typedef enum VTDIQEI
+{
+ VTDIQEI_INFO_NOT_AVAILABLE,
+ VTDIQEI_INVALID_TAIL_PTR,
+ VTDIQEI_FETCH_DESCRIPTOR_ERR,
+ VTDIQEI_INVALID_DESCRIPTOR_TYPE,
+ VTDIQEI_RSVD_FIELD_VIOLATION,
+ VTDIQEI_INVALID_DESCRIPTOR_WIDTH,
+ VTDIQEI_QUEUE_TAIL_MISALIGNED,
+ VTDIQEI_INVALID_TTM
+} VTDIQEI;
+/** @} */
+
+
+/** @name Interrupt Remapping Table Address Register (IRTA_REG).
+ * In accordance with the Intel spec.
+ * @{ */
+/** S: Size. */
+#define VTD_BF_IRTA_REG_S_SHIFT 0
+#define VTD_BF_IRTA_REG_S_MASK UINT64_C(0x000000000000000f)
+/** R: Reserved (bits 10:4). */
+#define VTD_BF_IRTA_REG_RSVD_10_4_SHIFT 4
+#define VTD_BF_IRTA_REG_RSVD_10_4_MASK UINT64_C(0x00000000000007f0)
+/** EIME: Extended Interrupt Mode Enable. */
+#define VTD_BF_IRTA_REG_EIME_SHIFT 11
+#define VTD_BF_IRTA_REG_EIME_MASK UINT64_C(0x0000000000000800)
+/** IRTA: Interrupt Remapping Table Address. */
+#define VTD_BF_IRTA_REG_IRTA_SHIFT 12
+#define VTD_BF_IRTA_REG_IRTA_MASK UINT64_C(0xfffffffffffff000)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_IRTA_REG_, UINT64_C(0), UINT64_MAX,
+ (S, RSVD_10_4, EIME, IRTA));
+
+/** RW: Read/write mask. */
+#define VTD_IRTA_REG_RW_MASK ( VTD_BF_IRTA_REG_S_MASK | VTD_BF_IRTA_REG_EIME_MASK \
+ | VTD_BF_IRTA_REG_IRTA_MASK)
+/** IRTA_REG: Get number of interrupt entries. */
+#define VTD_IRTA_REG_GET_ENTRY_COUNT(a) (UINT32_C(1) << (1 + ((a) & VTD_BF_IRTA_REG_S_MASK)))
+/** @} */
+
+
+/** @name Page Request Queue Head Register (PQH_REG).
+ * In accordance with the Intel spec.
+ * @{ */
+/** R: Reserved (bits 4:0). */
+#define VTD_BF_PQH_REG_RSVD_4_0_SHIFT 0
+#define VTD_BF_PQH_REG_RSVD_4_0_MASK UINT64_C(0x000000000000001f)
+/** PQH: Page Queue Head. */
+#define VTD_BF_PQH_REG_PQH_SHIFT 5
+#define VTD_BF_PQH_REG_PQH_MASK UINT64_C(0x000000000007ffe0)
+/** R: Reserved (bits 63:19). */
+#define VTD_BF_PQH_REG_RSVD_63_19_SHIFT 19
+#define VTD_BF_PQH_REG_RSVD_63_19_MASK UINT64_C(0xfffffffffff80000)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_PQH_REG_, UINT64_C(0), UINT64_MAX,
+ (RSVD_4_0, PQH, RSVD_63_19));
+
+/** RW: Read/write mask. */
+#define VTD_PQH_REG_RW_MASK VTD_BF_PQH_REG_PQH_MASK
+/** @} */
+
+
+/** @name Page Request Queue Tail Register (PQT_REG).
+ * In accordance with the Intel spec.
+ * @{ */
+/** R: Reserved (bits 4:0). */
+#define VTD_BF_PQT_REG_RSVD_4_0_SHIFT 0
+#define VTD_BF_PQT_REG_RSVD_4_0_MASK UINT64_C(0x000000000000001f)
+/** PQT: Page Queue Tail. */
+#define VTD_BF_PQT_REG_PQT_SHIFT 5
+#define VTD_BF_PQT_REG_PQT_MASK UINT64_C(0x000000000007ffe0)
+/** R: Reserved (bits 63:19). */
+#define VTD_BF_PQT_REG_RSVD_63_19_SHIFT 19
+#define VTD_BF_PQT_REG_RSVD_63_19_MASK UINT64_C(0xfffffffffff80000)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_PQT_REG_, UINT64_C(0), UINT64_MAX,
+ (RSVD_4_0, PQT, RSVD_63_19));
+
+/** RW: Read/write mask. */
+#define VTD_PQT_REG_RW_MASK VTD_BF_PQT_REG_PQT_MASK
+/** @} */
+
+
+/** @name Page Request Queue Address Register (PQA_REG).
+ * In accordance with the Intel spec.
+ * @{ */
+/** PQS: Page Queue Size. */
+#define VTD_BF_PQA_REG_PQS_SHIFT 0
+#define VTD_BF_PQA_REG_PQS_MASK UINT64_C(0x0000000000000007)
+/** R: Reserved bits (11:3). */
+#define VTD_BF_PQA_REG_RSVD_11_3_SHIFT 3
+#define VTD_BF_PQA_REG_RSVD_11_3_MASK UINT64_C(0x0000000000000ff8)
+/** PQA: Page Request Queue Base Address. */
+#define VTD_BF_PQA_REG_PQA_SHIFT 12
+#define VTD_BF_PQA_REG_PQA_MASK UINT64_C(0xfffffffffffff000)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_PQA_REG_, UINT64_C(0), UINT64_MAX,
+ (PQS, RSVD_11_3, PQA));
+
+/** RW: Read/write mask. */
+#define VTD_PQA_REG_RW_MASK (VTD_BF_PQA_REG_PQS_MASK | VTD_BF_PQA_REG_PQA_MASK)
+/** @} */
+
+
+/** @name Page Request Status Register (PRS_REG).
+ * In accordance with the Intel spec.
+ * @{ */
+/** PPR: Pending Page Request. */
+#define VTD_BF_PRS_REG_PPR_SHIFT 0
+#define VTD_BF_PRS_REG_PPR_MASK UINT64_C(0x00000001)
+/** PRO: Page Request Overflow. */
+#define VTD_BF_PRS_REG_PRO_SHIFT 1
+#define VTD_BF_PRS_REG_PRO_MASK UINT64_C(0x00000002)
+/** R: Reserved (bits 31:2). */
+#define VTD_BF_PRS_REG_RSVD_31_2_SHIFT 2
+#define VTD_BF_PRS_REG_RSVD_31_2_MASK UINT64_C(0xfffffffc)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_PRS_REG_, UINT32_C(0), UINT32_MAX,
+ (PPR, PRO, RSVD_31_2));
+
+/** RW: Read/write mask. */
+#define VTD_PRS_REG_RW_MASK (VTD_BF_PRS_REG_PPR_MASK | VTD_BF_PRS_REG_PRO_MASK)
+/** RW1C: Read-only-status, Write-1-to-clear status mask. */
+#define VTD_PRS_REG_RW1C_MASK (VTD_BF_PRS_REG_PPR_MASK | VTD_BF_PRS_REG_PRO_MASK)
+/** @} */
+
+
+/** @name Page Request Event Control Register (PECTL_REG).
+ * In accordance with the Intel spec.
+ * @{ */
+/** R: Reserved (bits 29:0). */
+#define VTD_BF_PECTL_REG_RSVD_29_0_SHIFT 0
+#define VTD_BF_PECTL_REG_RSVD_29_0_MASK UINT32_C(0x3fffffff)
+/** IP: Interrupt Pending. */
+#define VTD_BF_PECTL_REG_IP_SHIFT 30
+#define VTD_BF_PECTL_REG_IP_MASK UINT32_C(0x40000000)
+/** IM: Interrupt Mask. */
+#define VTD_BF_PECTL_REG_IM_SHIFT 31
+#define VTD_BF_PECTL_REG_IM_MASK UINT32_C(0x80000000)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_PECTL_REG_, UINT32_C(0), UINT32_MAX,
+ (RSVD_29_0, IP, IM));
+
+/** RW: Read/write mask. */
+#define VTD_PECTL_REG_RW_MASK VTD_BF_PECTL_REG_IM_MASK
+/** @} */
+
+
+/** @name Page Request Event Data Register (PEDATA_REG).
+ * In accordance with the Intel spec.
+ * @{ */
+/** IMD: Interrupt Message Data. */
+#define VTD_BF_PEDATA_REG_IMD_SHIFT 0
+#define VTD_BF_PEDATA_REG_IMD_MASK UINT32_C(0x0000ffff)
+/** R: Reserved (bits 31:16). VT-d specs. prior to 2021 had EIMD here. */
+#define VTD_BF_PEDATA_REG_RSVD_31_16_SHIFT 16
+#define VTD_BF_PEDATA_REG_RSVD_31_16_MASK UINT32_C(0xffff0000)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_PEDATA_REG_, UINT32_C(0), UINT32_MAX,
+ (IMD, RSVD_31_16));
+
+/** RW: Read/write mask, see 5.1.6 "Remapping Hardware Event Interrupt
+ * Programming". */
+#define VTD_PEDATA_REG_RW_MASK UINT32_C(0x000001ff)
+/** @} */
+
+
+/** @name Page Request Event Address Register (PEADDR_REG).
+ * In accordance with the Intel spec.
+ * @{ */
+/** R: Reserved (bits 1:0). */
+#define VTD_BF_PEADDR_REG_RSVD_1_0_SHIFT 0
+#define VTD_BF_PEADDR_REG_RSVD_1_0_MASK UINT32_C(0x00000003)
+/** MA: Message Address. */
+#define VTD_BF_PEADDR_REG_MA_SHIFT 2
+#define VTD_BF_PEADDR_REG_MA_MASK UINT32_C(0xfffffffc)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_PEADDR_REG_, UINT32_C(0), UINT32_MAX,
+ (RSVD_1_0, MA));
+
+/** RW: Read/write mask. */
+#define VTD_PEADDR_REG_RW_MASK VTD_BF_PEADDR_REG_MA_MASK
+/** @} */
+
+
+
+/** @name Page Request Event Upper Address Register (PEUADDR_REG).
+ * In accordance with the Intel spec.
+ * @{ */
+/** MA: Message Address. */
+#define VTD_BF_PEUADDR_REG_MUA_SHIFT 0
+#define VTD_BF_PEUADDR_REG_MUA_MASK UINT32_C(0xffffffff)
+
+/** RW: Read/write mask. */
+#define VTD_PEUADDR_REG_RW_MASK VTD_BF_PEUADDR_REG_MUA_MASK
+/** @} */
+
+
+/** @name MTRR Capability Register (MTRRCAP_REG).
+ * In accordance with the Intel spec.
+ * @{ */
+/** VCNT: Variable MTRR Count. */
+#define VTD_BF_MTRRCAP_REG_VCNT_SHIFT 0
+#define VTD_BF_MTRRCAP_REG_VCNT_MASK UINT64_C(0x00000000000000ff)
+/** FIX: Fixed range MTRRs Supported. */
+#define VTD_BF_MTRRCAP_REG_FIX_SHIFT 8
+#define VTD_BF_MTRRCAP_REG_FIX_MASK UINT64_C(0x0000000000000100)
+/** R: Reserved (bit 9). */
+#define VTD_BF_MTRRCAP_REG_RSVD_9_SHIFT 9
+#define VTD_BF_MTRRCAP_REG_RSVD_9_MASK UINT64_C(0x0000000000000200)
+/** WC: Write Combining. */
+#define VTD_BF_MTRRCAP_REG_WC_SHIFT 10
+#define VTD_BF_MTRRCAP_REG_WC_MASK UINT64_C(0x0000000000000400)
+/** R: Reserved (bits 63:11). */
+#define VTD_BF_MTRRCAP_REG_RSVD_63_11_SHIFT 11
+#define VTD_BF_MTRRCAP_REG_RSVD_63_11_MASK UINT64_C(0xfffffffffffff800)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_MTRRCAP_REG_, UINT64_C(0), UINT64_MAX,
+ (VCNT, FIX, RSVD_9, WC, RSVD_63_11));
+
+/** RW: Read/write mask. */
+#define VTD_MTRRCAP_REG_RW_MASK UINT64_C(0)
+/** @} */
+
+
+/** @name MTRR Default Type Register (MTRRDEF_REG).
+ * In accordance with the Intel spec.
+ * @{ */
+/** TYPE: Default Memory Type. */
+#define VTD_BF_MTRRDEF_REG_TYPE_SHIFT 0
+#define VTD_BF_MTRRDEF_REG_TYPE_MASK UINT64_C(0x00000000000000ff)
+/** R: Reserved (bits 9:8). */
+#define VTD_BF_MTRRDEF_REG_RSVD_9_8_SHIFT 8
+#define VTD_BF_MTRRDEF_REG_RSVD_9_8_MASK UINT64_C(0x0000000000000300)
+/** FE: Fixed Range MTRR Enable. */
+#define VTD_BF_MTRRDEF_REG_FE_SHIFT 10
+#define VTD_BF_MTRRDEF_REG_FE_MASK UINT64_C(0x0000000000000400)
+/** E: MTRR Enable. */
+#define VTD_BF_MTRRDEF_REG_E_SHIFT 11
+#define VTD_BF_MTRRDEF_REG_E_MASK UINT64_C(0x0000000000000800)
+/** R: Reserved (bits 63:12). */
+#define VTD_BF_MTRRDEF_REG_RSVD_63_12_SHIFT 12
+#define VTD_BF_MTRRDEF_REG_RSVD_63_12_MASK UINT64_C(0xfffffffffffff000)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_MTRRDEF_REG_, UINT64_C(0), UINT64_MAX,
+ (TYPE, RSVD_9_8, FE, E, RSVD_63_12));
+
+/** RW: Read/write mask. */
+#define VTD_MTRRDEF_REG_RW_MASK ( VTD_BF_MTRRDEF_REG_TYPE_MASK | VTD_BF_MTRRDEF_REG_FE_MASK \
+ | VTD_BF_MTRRDEF_REG_E_MASK)
+/** @} */
+
+
+/** @name Virtual Command Capability Register (VCCAP_REG).
+ * In accordance with the Intel spec.
+ * @{ */
+/** PAS: PASID Support. */
+#define VTD_BF_VCCAP_REG_PAS_SHIFT 0
+#define VTD_BF_VCCAP_REG_PAS_MASK UINT64_C(0x0000000000000001)
+/** R: Reserved (bits 63:1). */
+#define VTD_BF_VCCAP_REG_RSVD_63_1_SHIFT 1
+#define VTD_BF_VCCAP_REG_RSVD_63_1_MASK UINT64_C(0xfffffffffffffffe)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_VCCAP_REG_, UINT64_C(0), UINT64_MAX,
+ (PAS, RSVD_63_1));
+
+/** RW: Read/write mask. */
+#define VTD_VCCAP_REG_RW_MASK UINT64_C(0)
+/** @} */
+
+
+/** @name Virtual Command Extended Operand Register (VCMD_EO_REG).
+ * In accordance with the Intel spec.
+ * @{ */
+/** OB: Operand B. */
+#define VTD_BF_VCMD_EO_REG_OB_SHIFT 0
+#define VTD_BF_VCMD_EO_REG_OB_MASK UINT32_C(0xffffffffffffffff)
+
+/** RW: Read/write mask. */
+#define VTD_VCMD_EO_REG_RW_MASK VTD_BF_VCMD_EO_REG_OB_MASK
+/** @} */
+
+
+/** @name Virtual Command Register (VCMD_REG).
+ * In accordance with the Intel spec.
+ * @{ */
+/** CMD: Command. */
+#define VTD_BF_VCMD_REG_CMD_SHIFT 0
+#define VTD_BF_VCMD_REG_CMD_MASK UINT64_C(0x00000000000000ff)
+/** OP: Operand. */
+#define VTD_BF_VCMD_REG_OP_SHIFT 8
+#define VTD_BF_VCMD_REG_OP_MASK UINT64_C(0xffffffffffffff00)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_VCMD_REG_, UINT64_C(0), UINT64_MAX,
+ (CMD, OP));
+
+/** RW: Read/write mask. */
+#define VTD_VCMD_REG_RW_MASK (VTD_BF_VCMD_REG_CMD_MASK | VTD_BF_VCMD_REG_OP_MASK)
+/** @} */
+
+
+/** @name Virtual Command Response Register (VCRSP_REG).
+ * In accordance with the Intel spec.
+ * @{ */
+/** IP: In Progress. */
+#define VTD_BF_VCRSP_REG_IP_SHIFT 0
+#define VTD_BF_VCRSP_REG_IP_MASK UINT64_C(0x0000000000000001)
+/** SC: Status Code. */
+#define VTD_BF_VCRSP_REG_SC_SHIFT 1
+#define VTD_BF_VCRSP_REG_SC_MASK UINT64_C(0x0000000000000006)
+/** R: Reserved (bits 7:3). */
+#define VTD_BF_VCRSP_REG_RSVD_7_3_SHIFT 3
+#define VTD_BF_VCRSP_REG_RSVD_7_3_MASK UINT64_C(0x00000000000000f8)
+/** RSLT: Result. */
+#define VTD_BF_VCRSP_REG_RSLT_SHIFT 8
+#define VTD_BF_VCRSP_REG_RSLT_MASK UINT64_C(0xffffffffffffff00)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_VCRSP_REG_, UINT64_C(0), UINT64_MAX,
+ (IP, SC, RSVD_7_3, RSLT));
+
+/** RW: Read/write mask. */
+#define VTD_VCRSP_REG_RW_MASK UINT64_C(0)
+/** @} */
+
+
+/** @name Generic Invalidation Descriptor.
+ * In accordance with the Intel spec.
+ * Non-reserved fields here are common to all invalidation descriptors.
+ * @{ */
+/** Type (Lo). */
+#define VTD_BF_0_GENERIC_INV_DSC_TYPE_LO_SHIFT 0
+#define VTD_BF_0_GENERIC_INV_DSC_TYPE_LO_MASK UINT64_C(0x000000000000000f)
+/** R: Reserved (bits 8:4). */
+#define VTD_BF_0_GENERIC_INV_DSC_RSVD_8_4_SHIFT 4
+#define VTD_BF_0_GENERIC_INV_DSC_RSVD_8_4_MASK UINT64_C(0x00000000000001f0)
+/** Type (Hi). */
+#define VTD_BF_0_GENERIC_INV_DSC_TYPE_HI_SHIFT 9
+#define VTD_BF_0_GENERIC_INV_DSC_TYPE_HI_MASK UINT64_C(0x0000000000000e00)
+/** R: Reserved (bits 63:12). */
+#define VTD_BF_0_GENERIC_INV_DSC_RSVD_63_12_SHIFT 12
+#define VTD_BF_0_GENERIC_INV_DSC_RSVD_63_12_MASK UINT64_C(0xfffffffffffff000)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_0_GENERIC_INV_DSC_, UINT64_C(0), UINT64_MAX,
+ (TYPE_LO, RSVD_8_4, TYPE_HI, RSVD_63_12));
+
+/** GENERIC_INV_DSC: Type. */
+#define VTD_GENERIC_INV_DSC_GET_TYPE(a) ((((a) & VTD_BF_0_GENERIC_INV_DSC_TYPE_HI_MASK) >> 5) \
+ | ((a) & VTD_BF_0_GENERIC_INV_DSC_TYPE_LO_MASK))
+/** @} */
+
+
+/** @name Context-Cache Invalidation Descriptor (cc_inv_dsc).
+ * In accordance with the Intel spec.
+ * @{ */
+/** Type (Lo). */
+#define VTD_BF_0_CC_INV_DSC_TYPE_LO_SHIFT 0
+#define VTD_BF_0_CC_INV_DSC_TYPE_LO_MASK UINT64_C(0x000000000000000f)
+/** G: Granularity. */
+#define VTD_BF_0_CC_INV_DSC_G_SHIFT 4
+#define VTD_BF_0_CC_INV_DSC_G_MASK UINT64_C(0x0000000000000030)
+/** R: Reserved (bits 8:6). */
+#define VTD_BF_0_CC_INV_DSC_RSVD_8_6_SHIFT 6
+#define VTD_BF_0_CC_INV_DSC_RSVD_8_6_MASK UINT64_C(0x00000000000001c0)
+/** Type (Hi). */
+#define VTD_BF_0_CC_INV_DSC_TYPE_HI_SHIFT 9
+#define VTD_BF_0_CC_INV_DSC_TYPE_HI_MASK UINT64_C(0x0000000000000e00)
+/** R: Reserved (bits 15:12). */
+#define VTD_BF_0_CC_INV_DSC_RSVD_15_12_SHIFT 12
+#define VTD_BF_0_CC_INV_DSC_RSVD_15_12_MASK UINT64_C(0x000000000000f000)
+/** DID: Domain Id. */
+#define VTD_BF_0_CC_INV_DSC_DID_SHIFT 16
+#define VTD_BF_0_CC_INV_DSC_DID_MASK UINT64_C(0x00000000ffff0000)
+/** SID: Source Id. */
+#define VTD_BF_0_CC_INV_DSC_SID_SHIFT 32
+#define VTD_BF_0_CC_INV_DSC_SID_MASK UINT64_C(0x0000ffff00000000)
+/** FM: Function Mask. */
+#define VTD_BF_0_CC_INV_DSC_FM_SHIFT 48
+#define VTD_BF_0_CC_INV_DSC_FM_MASK UINT64_C(0x0003000000000000)
+/** R: Reserved (bits 63:50). */
+#define VTD_BF_0_CC_INV_DSC_RSVD_63_50_SHIFT 50
+#define VTD_BF_0_CC_INV_DSC_RSVD_63_50_MASK UINT64_C(0xfffc000000000000)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_0_CC_INV_DSC_, UINT64_C(0), UINT64_MAX,
+ (TYPE_LO, G, RSVD_8_6, TYPE_HI, RSVD_15_12, DID, SID, FM, RSVD_63_50));
+/** @} */
+
+
+/** @name PASID-Cache Invalidation Descriptor (pc_inv_dsc).
+ * In accordance with the Intel spec.
+ * @{ */
+/** Type (Lo). */
+#define VTD_BF_0_PC_INV_DSC_TYPE_LO_SHIFT 0
+#define VTD_BF_0_PC_INV_DSC_TYPE_LO_MASK UINT64_C(0x000000000000000f)
+/** G: Granularity. */
+#define VTD_BF_0_PC_INV_DSC_G_SHIFT 4
+#define VTD_BF_0_PC_INV_DSC_G_MASK UINT64_C(0x0000000000000030)
+/** R: Reserved (bits 8:6). */
+#define VTD_BF_0_PC_INV_DSC_RSVD_8_6_SHIFT 6
+#define VTD_BF_0_PC_INV_DSC_RSVD_8_6_MASK UINT64_C(0x00000000000001c0)
+/** Type (Hi). */
+#define VTD_BF_0_PC_INV_DSC_TYPE_HI_SHIFT 9
+#define VTD_BF_0_PC_INV_DSC_TYPE_HI_MASK UINT64_C(0x0000000000000e00)
+/** R: Reserved (bits 15:12). */
+#define VTD_BF_0_PC_INV_DSC_RSVD_15_12_SHIFT 12
+#define VTD_BF_0_PC_INV_DSC_RSVD_15_12_MASK UINT64_C(0x000000000000f000)
+/** DID: Domain Id. */
+#define VTD_BF_0_PC_INV_DSC_DID_SHIFT 16
+#define VTD_BF_0_PC_INV_DSC_DID_MASK UINT64_C(0x00000000ffff0000)
+/** PASID: Process Address-Space Id. */
+#define VTD_BF_0_PC_INV_DSC_PASID_SHIFT 32
+#define VTD_BF_0_PC_INV_DSC_PASID_MASK UINT64_C(0x000fffff00000000)
+/** R: Reserved (bits 63:52). */
+#define VTD_BF_0_PC_INV_DSC_RSVD_63_52_SHIFT 52
+#define VTD_BF_0_PC_INV_DSC_RSVD_63_52_MASK UINT64_C(0xfff0000000000000)
+
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_0_PC_INV_DSC_, UINT64_C(0), UINT64_MAX,
+ (TYPE_LO, G, RSVD_8_6, TYPE_HI, RSVD_15_12, DID, PASID, RSVD_63_52));
+/** @} */
+
+
+/** @name IOTLB Invalidate Descriptor (iotlb_inv_dsc).
+ * In accordance with the Intel spec.
+ * @{ */
+/** Type (Lo). */
+#define VTD_BF_0_IOTLB_INV_DSC_TYPE_LO_SHIFT 0
+#define VTD_BF_0_IOTLB_INV_DSC_TYPE_LO_MASK UINT64_C(0x000000000000000f)
+/** G: Granularity. */
+#define VTD_BF_0_IOTLB_INV_DSC_G_SHIFT 4
+#define VTD_BF_0_IOTLB_INV_DSC_G_MASK UINT64_C(0x0000000000000030)
+/** DW: Drain Writes. */
+#define VTD_BF_0_IOTLB_INV_DSC_DW_SHIFT 6
+#define VTD_BF_0_IOTLB_INV_DSC_DW_MASK UINT64_C(0x0000000000000040)
+/** DR: Drain Reads. */
+#define VTD_BF_0_IOTLB_INV_DSC_DR_SHIFT 7
+#define VTD_BF_0_IOTLB_INV_DSC_DR_MASK UINT64_C(0x0000000000000080)
+/** R: Reserved (bit 8). */
+#define VTD_BF_0_IOTLB_INV_DSC_RSVD_8_SHIFT 8
+#define VTD_BF_0_IOTLB_INV_DSC_RSVD_8_MASK UINT64_C(0x0000000000000100)
+/** Type (Hi). */
+#define VTD_BF_0_IOTLB_INV_DSC_TYPE_HI_SHIFT 9
+#define VTD_BF_0_IOTLB_INV_DSC_TYPE_HI_MASK UINT64_C(0x0000000000000e00)
+/** R: Reserved (bits 15:12). */
+#define VTD_BF_0_IOTLB_INV_DSC_RSVD_15_12_SHIFT 12
+#define VTD_BF_0_IOTLB_INV_DSC_RSVD_15_12_MASK UINT64_C(0x000000000000f000)
+/** DID: Domain Id. */
+#define VTD_BF_0_IOTLB_INV_DSC_DID_SHIFT 16
+#define VTD_BF_0_IOTLB_INV_DSC_DID_MASK UINT64_C(0x00000000ffff0000)
+/** R: Reserved (bits 63:32). */
+#define VTD_BF_0_IOTLB_INV_DSC_RSVD_63_32_SHIFT 32
+#define VTD_BF_0_IOTLB_INV_DSC_RSVD_63_32_MASK UINT64_C(0xffffffff00000000)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_0_IOTLB_INV_DSC_, UINT64_C(0), UINT64_MAX,
+ (TYPE_LO, G, DW, DR, RSVD_8, TYPE_HI, RSVD_15_12, DID, RSVD_63_32));
+
+/** AM: Address Mask. */
+#define VTD_BF_1_IOTLB_INV_DSC_AM_SHIFT 0
+#define VTD_BF_1_IOTLB_INV_DSC_AM_MASK UINT64_C(0x000000000000003f)
+/** IH: Invalidation Hint. */
+#define VTD_BF_1_IOTLB_INV_DSC_IH_SHIFT 6
+#define VTD_BF_1_IOTLB_INV_DSC_IH_MASK UINT64_C(0x0000000000000040)
+/** R: Reserved (bits 11:7). */
+#define VTD_BF_1_IOTLB_INV_DSC_RSVD_11_7_SHIFT 7
+#define VTD_BF_1_IOTLB_INV_DSC_RSVD_11_7_MASK UINT64_C(0x0000000000000f80)
+/** ADDR: Address. */
+#define VTD_BF_1_IOTLB_INV_DSC_ADDR_SHIFT 12
+#define VTD_BF_1_IOTLB_INV_DSC_ADDR_MASK UINT64_C(0xfffffffffffff000)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_1_IOTLB_INV_DSC_, UINT64_C(0), UINT64_MAX,
+ (AM, IH, RSVD_11_7, ADDR));
+/** @} */
+
+
+/** @name PASID-based IOTLB Invalidate Descriptor (p_iotlb_inv_dsc).
+ * In accordance with the Intel spec.
+ * @{ */
+/** Type (Lo). */
+#define VTD_BF_0_P_IOTLB_INV_DSC_TYPE_LO_SHIFT 0
+#define VTD_BF_0_P_IOTLB_INV_DSC_TYPE_LO_MASK UINT64_C(0x000000000000000f)
+/** G: Granularity. */
+#define VTD_BF_0_P_IOTLB_INV_DSC_G_SHIFT 4
+#define VTD_BF_0_P_IOTLB_INV_DSC_G_MASK UINT64_C(0x0000000000000030)
+/** R: Reserved (bits 8:6). */
+#define VTD_BF_0_P_IOTLB_INV_DSC_RSVD_8_6_SHIFT 6
+#define VTD_BF_0_P_IOTLB_INV_DSC_RSVD_8_6_MASK UINT64_C(0x00000000000001c0)
+/** Type (Hi). */
+#define VTD_BF_0_P_IOTLB_INV_DSC_TYPE_HI_SHIFT 9
+#define VTD_BF_0_P_IOTLB_INV_DSC_TYPE_HI_MASK UINT64_C(0x0000000000000e00)
+/** R: Reserved (bits 15:12). */
+#define VTD_BF_0_P_IOTLB_INV_DSC_RSVD_15_12_SHIFT 12
+#define VTD_BF_0_P_IOTLB_INV_DSC_RSVD_15_12_MASK UINT64_C(0x000000000000f000)
+/** DID: Domain Id. */
+#define VTD_BF_0_P_IOTLB_INV_DSC_DID_SHIFT 16
+#define VTD_BF_0_P_IOTLB_INV_DSC_DID_MASK UINT64_C(0x00000000ffff0000)
+/** PASID: Process Address-Space Id. */
+#define VTD_BF_0_P_IOTLB_INV_DSC_PASID_SHIFT 32
+#define VTD_BF_0_P_IOTLB_INV_DSC_PASID_MASK UINT64_C(0x000fffff00000000)
+/** R: Reserved (bits 63:52). */
+#define VTD_BF_0_P_IOTLB_INV_DSC_RSVD_63_52_SHIFT 52
+#define VTD_BF_0_P_IOTLB_INV_DSC_RSVD_63_52_MASK UINT64_C(0xfff0000000000000)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_0_P_IOTLB_INV_DSC_, UINT64_C(0), UINT64_MAX,
+ (TYPE_LO, G, RSVD_8_6, TYPE_HI, RSVD_15_12, DID, PASID, RSVD_63_52));
+
+
+/** AM: Address Mask. */
+#define VTD_BF_1_P_IOTLB_INV_DSC_AM_SHIFT 0
+#define VTD_BF_1_P_IOTLB_INV_DSC_AM_MASK UINT64_C(0x000000000000003f)
+/** IH: Invalidation Hint. */
+#define VTD_BF_1_P_IOTLB_INV_DSC_IH_SHIFT 6
+#define VTD_BF_1_P_IOTLB_INV_DSC_IH_MASK UINT64_C(0x0000000000000040)
+/** R: Reserved (bits 11:7). */
+#define VTD_BF_1_P_IOTLB_INV_DSC_RSVD_11_7_SHIFT 7
+#define VTD_BF_1_P_IOTLB_INV_DSC_RSVD_11_7_MASK UINT64_C(0x0000000000000f80)
+/** ADDR: Address. */
+#define VTD_BF_1_P_IOTLB_INV_DSC_ADDR_SHIFT 12
+#define VTD_BF_1_P_IOTLB_INV_DSC_ADDR_MASK UINT64_C(0xfffffffffffff000)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_1_P_IOTLB_INV_DSC_, UINT64_C(0), UINT64_MAX,
+ (AM, IH, RSVD_11_7, ADDR));
+/** @} */
+
+
+/** @name Device-TLB Invalidate Descriptor (dev_tlb_inv_dsc).
+ * In accordance with the Intel spec.
+ * @{ */
+/** Type (Lo). */
+#define VTD_BF_0_DEV_TLB_INV_DSC_TYPE_LO_SHIFT 0
+#define VTD_BF_0_DEV_TLB_INV_DSC_TYPE_LO_MASK UINT64_C(0x000000000000000f)
+/** R: Reserved (bits 8:4). */
+#define VTD_BF_0_DEV_TLB_INV_DSC_RSVD_8_4_SHIFT 4
+#define VTD_BF_0_DEV_TLB_INV_DSC_RSVD_8_4_MASK UINT64_C(0x00000000000001f0)
+/** Type (Hi). */
+#define VTD_BF_0_DEV_TLB_INV_DSC_TYPE_HI_SHIFT 9
+#define VTD_BF_0_DEV_TLB_INV_DSC_TYPE_HI_MASK UINT64_C(0x0000000000000e00)
+/** PFSID: Physical-Function Source Id (Lo). */
+#define VTD_BF_0_DEV_TLB_INV_DSC_PFSID_LO_SHIFT 12
+#define VTD_BF_0_DEV_TLB_INV_DSC_PFSID_LO_MASK UINT64_C(0x000000000000f000)
+/** MIP: Max Invalidations Pending. */
+#define VTD_BF_0_DEV_TLB_INV_DSC_MIP_SHIFT 16
+#define VTD_BF_0_DEV_TLB_INV_DSC_MIP_MASK UINT64_C(0x00000000001f0000)
+/** R: Reserved (bits 31:21). */
+#define VTD_BF_0_DEV_TLB_INV_DSC_RSVD_31_21_SHIFT 21
+#define VTD_BF_0_DEV_TLB_INV_DSC_RSVD_31_21_MASK UINT64_C(0x00000000ffe00000)
+/** SID: Source Id. */
+#define VTD_BF_0_DEV_TLB_INV_DSC_SID_SHIFT 32
+#define VTD_BF_0_DEV_TLB_INV_DSC_SID_MASK UINT64_C(0x0000ffff00000000)
+/** R: Reserved (bits 51:48). */
+#define VTD_BF_0_DEV_TLB_INV_DSC_RSVD_51_48_SHIFT 48
+#define VTD_BF_0_DEV_TLB_INV_DSC_RSVD_51_48_MASK UINT64_C(0x000f000000000000)
+/** PFSID: Physical-Function Source Id (Hi). */
+#define VTD_BF_0_DEV_TLB_INV_DSC_PFSID_HI_SHIFT 52
+#define VTD_BF_0_DEV_TLB_INV_DSC_PFSID_HI_MASK UINT64_C(0xfff0000000000000)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_0_DEV_TLB_INV_DSC_, UINT64_C(0), UINT64_MAX,
+ (TYPE_LO, RSVD_8_4, TYPE_HI, PFSID_LO, MIP, RSVD_31_21, SID, RSVD_51_48, PFSID_HI));
+
+/** S: Size. */
+#define VTD_BF_1_DEV_TLB_INV_DSC_S_SHIFT 0
+#define VTD_BF_1_DEV_TLB_INV_DSC_S_MASK UINT64_C(0x0000000000000001)
+/** R: Reserved (bits 11:1). */
+#define VTD_BF_1_DEV_TLB_INV_DSC_RSVD_11_1_SHIFT 1
+#define VTD_BF_1_DEV_TLB_INV_DSC_RSVD_11_1_MASK UINT64_C(0x0000000000000ffe)
+/** ADDR: Address. */
+#define VTD_BF_1_DEV_TLB_INV_DSC_ADDR_SHIFT 12
+#define VTD_BF_1_DEV_TLB_INV_DSC_ADDR_MASK UINT64_C(0xfffffffffffff000)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_1_DEV_TLB_INV_DSC_, UINT64_C(0), UINT64_MAX,
+ (S, RSVD_11_1, ADDR));
+/** @} */
+
+
+/** @name PASID-based-device-TLB Invalidate Descriptor (p_dev_tlb_inv_dsc).
+ * In accordance with the Intel spec.
+ * @{ */
+/** Type (Lo). */
+#define VTD_BF_0_P_DEV_TLB_INV_DSC_TYPE_LO_SHIFT 0
+#define VTD_BF_0_P_DEV_TLB_INV_DSC_TYPE_LO_MASK UINT64_C(0x000000000000000f)
+/** MIP: Max Invalidations Pending. */
+#define VTD_BF_0_P_DEV_TLB_INV_DSC_MIP_SHIFT 4
+#define VTD_BF_0_P_DEV_TLB_INV_DSC_MIP_MASK UINT64_C(0x00000000000001f0)
+/** Type (Hi). */
+#define VTD_BF_0_P_DEV_TLB_INV_DSC_TYPE_HI_SHIFT 9
+#define VTD_BF_0_P_DEV_TLB_INV_DSC_TYPE_HI_MASK UINT64_C(0x0000000000000e00)
+/** PFSID: Physical-Function Source Id (Lo). */
+#define VTD_BF_0_P_DEV_TLB_INV_DSC_PFSID_LO_SHIFT 12
+#define VTD_BF_0_P_DEV_TLB_INV_DSC_PFSID_LO_MASK UINT64_C(0x000000000000f000)
+/** SID: Source Id. */
+#define VTD_BF_0_P_DEV_TLB_INV_DSC_SID_SHIFT 16
+#define VTD_BF_0_P_DEV_TLB_INV_DSC_SID_MASK UINT64_C(0x00000000ffff0000)
+/** PASID: Process Address-Space Id. */
+#define VTD_BF_0_P_DEV_TLB_INV_DSC_PASID_SHIFT 32
+#define VTD_BF_0_P_DEV_TLB_INV_DSC_PASID_MASK UINT64_C(0x000fffff00000000)
+/** PFSID: Physical-Function Source Id (Hi). */
+#define VTD_BF_0_P_DEV_TLB_INV_DSC_PFSID_HI_SHIFT 52
+#define VTD_BF_0_P_DEV_TLB_INV_DSC_PFSID_HI_MASK UINT64_C(0xfff0000000000000)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_0_P_DEV_TLB_INV_DSC_, UINT64_C(0), UINT64_MAX,
+ (TYPE_LO, MIP, TYPE_HI, PFSID_LO, SID, PASID, PFSID_HI));
+
+/** G: Granularity. */
+#define VTD_BF_1_P_DEV_TLB_INV_DSC_G_SHIFT 0
+#define VTD_BF_1_P_DEV_TLB_INV_DSC_G_MASK UINT64_C(0x0000000000000001)
+/** R: Reserved (bits 10:1). */
+#define VTD_BF_1_P_DEV_TLB_INV_DSC_RSVD_10_1_SHIFT 1
+#define VTD_BF_1_P_DEV_TLB_INV_DSC_RSVD_10_1_MASK UINT64_C(0x00000000000007fe)
+/** S: Size. */
+#define VTD_BF_1_P_DEV_TLB_INV_DSC_S_SHIFT 11
+#define VTD_BF_1_P_DEV_TLB_INV_DSC_S_MASK UINT64_C(0x0000000000000800)
+/** ADDR: Address. */
+#define VTD_BF_1_P_DEV_TLB_INV_DSC_ADDR_SHIFT 12
+#define VTD_BF_1_P_DEV_TLB_INV_DSC_ADDR_MASK UINT64_C(0xfffffffffffff000)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_1_P_DEV_TLB_INV_DSC_, UINT64_C(0), UINT64_MAX,
+ (G, RSVD_10_1, S, ADDR));
+/** @} */
+
+
+/** @name Interrupt Entry Cache Invalidate Descriptor (iec_inv_dsc).
+ * In accordance with the Intel spec.
+ * @{ */
+/** Type (Lo). */
+#define VTD_BF_0_IEC_INV_DSC_TYPE_LO_SHIFT 0
+#define VTD_BF_0_IEC_INV_DSC_TYPE_LO_MASK UINT64_C(0x000000000000000f)
+/** G: Granularity. */
+#define VTD_BF_0_IEC_INV_DSC_G_SHIFT 4
+#define VTD_BF_0_IEC_INV_DSC_G_MASK UINT64_C(0x0000000000000010)
+/** R: Reserved (bits 8:5). */
+#define VTD_BF_0_IEC_INV_DSC_RSVD_8_5_SHIFT 5
+#define VTD_BF_0_IEC_INV_DSC_RSVD_8_5_MASK UINT64_C(0x00000000000001e0)
+/** Type (Hi). */
+#define VTD_BF_0_IEC_INV_DSC_TYPE_HI_SHIFT 9
+#define VTD_BF_0_IEC_INV_DSC_TYPE_HI_MASK UINT64_C(0x0000000000000e00)
+/** R: Reserved (bits 26:12). */
+#define VTD_BF_0_IEC_INV_DSC_RSVD_26_12_SHIFT 12
+#define VTD_BF_0_IEC_INV_DSC_RSVD_26_12_MASK UINT64_C(0x0000000007fff000)
+/** IM: Index Mask. */
+#define VTD_BF_0_IEC_INV_DSC_IM_SHIFT 27
+#define VTD_BF_0_IEC_INV_DSC_IM_MASK UINT64_C(0x00000000f8000000)
+/** IIDX: Interrupt Index. */
+#define VTD_BF_0_IEC_INV_DSC_IIDX_SHIFT 32
+#define VTD_BF_0_IEC_INV_DSC_IIDX_MASK UINT64_C(0x0000ffff00000000)
+/** R: Reserved (bits 63:48). */
+#define VTD_BF_0_IEC_INV_DSC_RSVD_63_48_SHIFT 48
+#define VTD_BF_0_IEC_INV_DSC_RSVD_63_48_MASK UINT64_C(0xffff000000000000)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_0_IEC_INV_DSC_, UINT64_C(0), UINT64_MAX,
+ (TYPE_LO, G, RSVD_8_5, TYPE_HI, RSVD_26_12, IM, IIDX, RSVD_63_48));
+/** @} */
+
+
+/** @name Invalidation Wait Descriptor (inv_wait_dsc).
+ * In accordance with the Intel spec.
+ * @{ */
+/** Type (Lo). */
+#define VTD_BF_0_INV_WAIT_DSC_TYPE_LO_SHIFT 0
+#define VTD_BF_0_INV_WAIT_DSC_TYPE_LO_MASK UINT64_C(0x000000000000000f)
+/** IF: Interrupt Flag. */
+#define VTD_BF_0_INV_WAIT_DSC_IF_SHIFT 4
+#define VTD_BF_0_INV_WAIT_DSC_IF_MASK UINT64_C(0x0000000000000010)
+/** SW: Status Write. */
+#define VTD_BF_0_INV_WAIT_DSC_SW_SHIFT 5
+#define VTD_BF_0_INV_WAIT_DSC_SW_MASK UINT64_C(0x0000000000000020)
+/** FN: Fence Flag. */
+#define VTD_BF_0_INV_WAIT_DSC_FN_SHIFT 6
+#define VTD_BF_0_INV_WAIT_DSC_FN_MASK UINT64_C(0x0000000000000040)
+/** PD: Page-Request Drain. */
+#define VTD_BF_0_INV_WAIT_DSC_PD_SHIFT 7
+#define VTD_BF_0_INV_WAIT_DSC_PD_MASK UINT64_C(0x0000000000000080)
+/** R: Reserved (bit 8). */
+#define VTD_BF_0_INV_WAIT_DSC_RSVD_8_SHIFT 8
+#define VTD_BF_0_INV_WAIT_DSC_RSVD_8_MASK UINT64_C(0x0000000000000100)
+/** Type (Hi). */
+#define VTD_BF_0_INV_WAIT_DSC_TYPE_HI_SHIFT 9
+#define VTD_BF_0_INV_WAIT_DSC_TYPE_HI_MASK UINT64_C(0x0000000000000e00)
+/** R: Reserved (bits 31:12). */
+#define VTD_BF_0_INV_WAIT_DSC_RSVD_31_12_SHIFT 12
+#define VTD_BF_0_INV_WAIT_DSC_RSVD_31_12_MASK UINT64_C(0x00000000fffff000)
+/** STDATA: Status Data. */
+#define VTD_BF_0_INV_WAIT_DSC_STDATA_SHIFT 32
+#define VTD_BF_0_INV_WAIT_DSC_STDATA_MASK UINT64_C(0xffffffff00000000)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_0_INV_WAIT_DSC_, UINT64_C(0), UINT64_MAX,
+ (TYPE_LO, IF, SW, FN, PD, RSVD_8, TYPE_HI, RSVD_31_12, STDATA));
+
+/** R: Reserved (bits 1:0). */
+#define VTD_BF_1_INV_WAIT_DSC_RSVD_1_0_SHIFT 0
+#define VTD_BF_1_INV_WAIT_DSC_RSVD_1_0_MASK UINT64_C(0x0000000000000003)
+/** STADDR: Status Address. */
+#define VTD_BF_1_INV_WAIT_DSC_STADDR_SHIFT 2
+#define VTD_BF_1_INV_WAIT_DSC_STADDR_MASK UINT64_C(0xfffffffffffffffc)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_1_INV_WAIT_DSC_, UINT64_C(0), UINT64_MAX,
+ (RSVD_1_0, STADDR));
+
+/* INV_WAIT_DSC: Qword 0 valid mask. */
+#define VTD_INV_WAIT_DSC_0_VALID_MASK ( VTD_BF_0_INV_WAIT_DSC_TYPE_LO_MASK \
+ | VTD_BF_0_INV_WAIT_DSC_IF_MASK \
+ | VTD_BF_0_INV_WAIT_DSC_SW_MASK \
+ | VTD_BF_0_INV_WAIT_DSC_FN_MASK \
+ | VTD_BF_0_INV_WAIT_DSC_PD_MASK \
+ | VTD_BF_0_INV_WAIT_DSC_TYPE_HI_MASK \
+ | VTD_BF_0_INV_WAIT_DSC_STDATA_MASK)
+/* INV_WAIT_DSC: Qword 1 valid mask. */
+#define VTD_INV_WAIT_DSC_1_VALID_MASK VTD_BF_1_INV_WAIT_DSC_STADDR_MASK
+/** @} */
+
+
+/** @name Invalidation descriptor types.
+ * In accordance with the Intel spec.
+ * @{ */
+#define VTD_CC_INV_DSC_TYPE 1
+#define VTD_IOTLB_INV_DSC_TYPE 2
+#define VTD_DEV_TLB_INV_DSC_TYPE 3
+#define VTD_IEC_INV_DSC_TYPE 4
+#define VTD_INV_WAIT_DSC_TYPE 5
+#define VTD_P_IOTLB_INV_DSC_TYPE 6
+#define VTD_PC_INV_DSC_TYPE 7
+#define VTD_P_DEV_TLB_INV_DSC_TYPE 8
+/** @} */
+
+
+/** @name Remappable Format Interrupt Request.
+ * In accordance with the Intel spec.
+ * @{ */
+/** IGN: Ignored (bits 1:0). */
+#define VTD_BF_REMAPPABLE_MSI_ADDR_IGN_1_0_SHIFT 0
+#define VTD_BF_REMAPPABLE_MSI_ADDR_IGN_1_0_MASK UINT32_C(0x00000003)
+/** Handle (Hi). */
+#define VTD_BF_REMAPPABLE_MSI_ADDR_HANDLE_HI_SHIFT 2
+#define VTD_BF_REMAPPABLE_MSI_ADDR_HANDLE_HI_MASK UINT32_C(0x00000004)
+/** SHV: Subhandle Valid. */
+#define VTD_BF_REMAPPABLE_MSI_ADDR_SHV_SHIFT 3
+#define VTD_BF_REMAPPABLE_MSI_ADDR_SHV_MASK UINT32_C(0x00000008)
+/** Interrupt format. */
+#define VTD_BF_REMAPPABLE_MSI_ADDR_INTR_FMT_SHIFT 4
+#define VTD_BF_REMAPPABLE_MSI_ADDR_INTR_FMT_MASK UINT32_C(0x00000010)
+/** Handle (Lo). */
+#define VTD_BF_REMAPPABLE_MSI_ADDR_HANDLE_LO_SHIFT 5
+#define VTD_BF_REMAPPABLE_MSI_ADDR_HANDLE_LO_MASK UINT32_C(0x000fffe0)
+/** Address. */
+#define VTD_BF_REMAPPABLE_MSI_ADDR_ADDR_SHIFT 20
+#define VTD_BF_REMAPPABLE_MSI_ADDR_ADDR_MASK UINT32_C(0xfff00000)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_REMAPPABLE_MSI_ADDR_, UINT32_C(0), UINT32_MAX,
+ (IGN_1_0, HANDLE_HI, SHV, INTR_FMT, HANDLE_LO, ADDR));
+
+/** Subhandle. */
+#define VTD_BF_REMAPPABLE_MSI_DATA_SUBHANDLE_SHIFT 0
+#define VTD_BF_REMAPPABLE_MSI_DATA_SUBHANDLE_MASK UINT32_C(0x0000ffff)
+/** R: Reserved (bits 31:16). */
+#define VTD_BF_REMAPPABLE_MSI_DATA_RSVD_31_16_SHIFT 16
+#define VTD_BF_REMAPPABLE_MSI_DATA_RSVD_31_16_MASK UINT32_C(0xffff0000)
+RT_BF_ASSERT_COMPILE_CHECKS(VTD_BF_REMAPPABLE_MSI_DATA_, UINT32_C(0), UINT32_MAX,
+ (SUBHANDLE, RSVD_31_16));
+
+/** Remappable MSI Address: Valid mask. */
+#define VTD_REMAPPABLE_MSI_ADDR_VALID_MASK UINT32_MAX
+/** Remappable MSI Data: Valid mask. */
+#define VTD_REMAPPABLE_MSI_DATA_VALID_MASK VTD_BF_REMAPPABLE_MSI_DATA_SUBHANDLE_MASK
+
+/** Interrupt format: Compatibility. */
+#define VTD_INTR_FORMAT_COMPAT 0
+/** Interrupt format: Remappable. */
+#define VTD_INTR_FORMAT_REMAPPABLE 1
+/** @} */
+
+
+/** @name Interrupt Remapping Fault Conditions.
+ * In accordance with the Intel spec.
+ * @{ */
+typedef enum VTDIRFAULT
+{
+ /** Reserved bits invalid in remappable interrupt. */
+ VTDIRFAULT_REMAPPABLE_INTR_RSVD = 0x20,
+
+ /** Interrupt index for remappable interrupt exceeds table size or referenced
+ * address above host address width (HAW) */
+ VTDIRFAULT_INTR_INDEX_INVALID = 0x21,
+
+ /** The IRTE is not present. */
+ VTDIRFAULT_IRTE_NOT_PRESENT = 0x22,
+ /** Reading IRTE from memory failed. */
+ VTDIRFAULT_IRTE_READ_FAILED = 0x23,
+ /** IRTE reserved bits invalid for an IRTE with Present bit set. */
+ VTDIRFAULT_IRTE_PRESENT_RSVD = 0x24,
+
+ /** Compatibility format interrupt (CFI) blocked due to EIME being enabled or CFIs
+ * were disabled. */
+ VTDIRFAULT_CFI_BLOCKED = 0x25,
+
+ /** IRTE SID, SVT, SQ bits invalid for an IRTE with Present bit set. */
+ VTDIRFAULT_IRTE_PRESENT_INVALID = 0x26,
+
+ /** Reading posted interrupt descriptor (PID) failed. */
+ VTDIRFAULT_PID_READ_FAILED = 0x27,
+ /** PID reserved bits invalid. */
+ VTDIRFAULT_PID_RSVD = 0x28,
+
+ /** Untranslated interrupt requested (without PASID) is invalid. */
+ VTDIRFAULT_IR_WITHOUT_PASID_INVALID = 0x29
+} VTDIRFAULT;
+AssertCompileSize(VTDIRFAULT, 4);
+/** @} */
+
+
+/** @name Address Translation Fault Conditions.
+ * In accordance with the Intel spec.
+ * @{ */
+typedef enum VTDATFAULT
+{
+ /* Legacy root table faults (LRT). */
+ VTDATFAULT_LRT_1 = 0x8,
+ VTDATFAULT_LRT_2 = 0x1,
+ VTDATFAULT_LRT_3 = 0xa,
+
+ /* Legacy Context-Table Faults (LCT). */
+ VTDATFAULT_LCT_1 = 0x9,
+ VTDATFAULT_LCT_2 = 0x2,
+ VTDATFAULT_LCT_3 = 0xb,
+ VTDATFAULT_LCT_4_1 = 0x3,
+ VTDATFAULT_LCT_4_2 = 0x3,
+ VTDATFAULT_LCT_4_3 = 0x3,
+ VTDATFAULT_LCT_5 = 0xd,
+
+ /* Legacy Second-Level Table Faults (LSL). */
+ VTDATFAULT_LSL_1 = 0x7,
+ VTDATFAULT_LSL_2 = 0xc,
+
+ /* Legacy General Faults (LGN). */
+ VTDATFAULT_LGN_1_1 = 0x4,
+ VTDATFAULT_LGN_1_2 = 0x4,
+ VTDATFAULT_LGN_1_3 = 0x4,
+ VTDATFAULT_LGN_2 = 0x5,
+ VTDATFAULT_LGN_3 = 0x6,
+ VTDATFAULT_LGN_4 = 0xe,
+
+ /* Root-Table Address Register Faults (RTA). */
+ VTDATFAULT_RTA_1_1 = 0x30,
+ VTDATFAULT_RTA_1_2 = 0x30,
+ VTDATFAULT_RTA_1_3 = 0x30,
+ VTDATFAULT_RTA_2 = 0x31,
+ VTDATFAULT_RTA_3 = 0x32,
+ VTDATFAULT_RTA_4 = 0x33,
+
+ /* Scalable-Mode Root-Table Faults (SRT). */
+ VTDATFAULT_SRT_1 = 0x38,
+ VTDATFAULT_SRT_2 = 0x39,
+ VTDATFAULT_SRT_3 = 0x3a,
+
+ /* Scalable-Mode Context-Table Faults (SCT). */
+ VTDATFAULT_SCT_1 = 0x40,
+ VTDATFAULT_SCT_2 = 0x41,
+ VTDATFAULT_SCT_3 = 0x42,
+ VTDATFAULT_SCT_4_1 = 0x43,
+ VTDATFAULT_SCT_4_2 = 0x43,
+ VTDATFAULT_SCT_5 = 0x44,
+ VTDATFAULT_SCT_6 = 0x45,
+ VTDATFAULT_SCT_7 = 0x46,
+ VTDATFAULT_SCT_8 = 0x47,
+ VTDATFAULT_SCT_9 = 0x48,
+
+ /* Scalable-Mode PASID-Directory Faults (SPD). */
+ VTDATFAULT_SPD_1 = 0x50,
+ VTDATFAULT_SPD_2 = 0x51,
+ VTDATFAULT_SPD_3 = 0x52,
+
+ /* Scalable-Mode PASID-Table Faults (SPT). */
+ VTDATFAULT_SPT_1 = 0x58,
+ VTDATFAULT_SPT_2 = 0x59,
+ VTDATFAULT_SPT_3 = 0x5a,
+ VTDATFAULT_SPT_4_1 = 0x5b,
+ VTDATFAULT_SPT_4_2 = 0x5b,
+ VTDATFAULT_SPT_4_3 = 0x5b,
+ VTDATFAULT_SPT_4_4 = 0x5b,
+ VTDATFAULT_SPT_5 = 0x5c,
+ VTDATFAULT_SPT_6 = 0x5d,
+
+ /* Scalable-Mode First-Level Table Faults (SFL). */
+ VTDATFAULT_SFL_1 = 0x70,
+ VTDATFAULT_SFL_2 = 0x71,
+ VTDATFAULT_SFL_3 = 0x72,
+ VTDATFAULT_SFL_4 = 0x73,
+ VTDATFAULT_SFL_5 = 0x74,
+ VTDATFAULT_SFL_6 = 0x75,
+ VTDATFAULT_SFL_7 = 0x76,
+ VTDATFAULT_SFL_8 = 0x77,
+ VTDATFAULT_SFL_9 = 0x90,
+ VTDATFAULT_SFL_10 = 0x91,
+
+ /* Scalable-Mode Second-Level Table Faults (SSL). */
+ VTDATFAULT_SSL_1 = 0x78,
+ VTDATFAULT_SSL_2 = 0x79,
+ VTDATFAULT_SSL_3 = 0x7a,
+ VTDATFAULT_SSL_4 = 0x7b,
+ VTDATFAULT_SSL_5 = 0x7c,
+ VTDATFAULT_SSL_6 = 0x7d,
+
+ /* Scalable-Mode General Faults (SGN). */
+ VTDATFAULT_SGN_1 = 0x80,
+ VTDATFAULT_SGN_2 = 0x81,
+ VTDATFAULT_SGN_3 = 0x82,
+ VTDATFAULT_SGN_4_1 = 0x83,
+ VTDATFAULT_SGN_4_2 = 0x83,
+ VTDATFAULT_SGN_5 = 0x84,
+ VTDATFAULT_SGN_6 = 0x85,
+ VTDATFAULT_SGN_7 = 0x86,
+ VTDATFAULT_SGN_8 = 0x87,
+ VTDATFAULT_SGN_9 = 0x88,
+ VTDATFAULT_SGN_10 = 0x89
+} VTDATFAULT;
+AssertCompileSize(VTDATFAULT, 4);
+/** @} */
+
+
+/** @name ACPI_DMAR_F_XXX: DMA Remapping Reporting Structure Flags.
+ * In accordance with the Intel spec.
+ * @{ */
+/** INTR_REMAP: Interrupt remapping supported. */
+#define ACPI_DMAR_F_INTR_REMAP RT_BIT(0)
+/** X2APIC_OPT_OUT: Request system software to opt-out of enabling x2APIC. */
+#define ACPI_DMAR_F_X2APIC_OPT_OUT RT_BIT(1)
+/** DMA_CTRL_PLATFORM_OPT_IN_FLAG: Firmware initiated DMA restricted to reserved
+ * memory regions (RMRR). */
+#define ACPI_DMAR_F_DMA_CTRL_PLATFORM_OPT_IN RT_BIT(2)
+/** @} */
+
+
+/** @name ACPI_DRHD_F_XXX: DMA-Remapping Hardware Unit Definition Flags.
+ * In accordance with the Intel spec.
+ * @{ */
+/** INCLUDE_PCI_ALL: All PCI devices under scope. */
+#define ACPI_DRHD_F_INCLUDE_PCI_ALL RT_BIT(0)
+/** @} */
+
+
+/**
+ * DRHD: DMA-Remapping Hardware Unit Definition.
+ * In accordance with the Intel spec.
+ */
+#pragma pack(1)
+typedef struct ACPIDRHD
+{
+ /** Type (must be 0=DRHD). */
+ uint16_t uType;
+ /** Length (must be 16 + size of device scope structure). */
+ uint16_t cbLength;
+ /** Flags, see ACPI_DRHD_F_XXX. */
+ uint8_t fFlags;
+ /** Reserved (MBZ). */
+ uint8_t bRsvd;
+ /** PCI segment number. */
+ uint16_t uPciSegment;
+ /** Register Base Address (MMIO). */
+ uint64_t uRegBaseAddr;
+ /* Device Scope[] Structures follow. */
+} ACPIDRHD;
+#pragma pack()
+AssertCompileSize(ACPIDRHD, 16);
+AssertCompileMemberOffset(ACPIDRHD, cbLength, 2);
+AssertCompileMemberOffset(ACPIDRHD, fFlags, 4);
+AssertCompileMemberOffset(ACPIDRHD, uPciSegment, 6);
+AssertCompileMemberOffset(ACPIDRHD, uRegBaseAddr, 8);
+
+
+/** @name ACPIDMARDEVSCOPE_TYPE_XXX: Device Type.
+ * In accordance with the Intel spec.
+ * @{ */
+#define ACPIDMARDEVSCOPE_TYPE_PCI_ENDPOINT 1
+#define ACPIDMARDEVSCOPE_TYPE_PCI_SUB_HIERARCHY 2
+#define ACPIDMARDEVSCOPE_TYPE_IOAPIC 3
+#define ACPIDMARDEVSCOPE_TYPE_MSI_CAP_HPET 4
+#define ACPIDMARDEVSCOPE_TYPE_ACPI_NAMESPACE_DEV 5
+/** @} */
+
+
+/**
+ * ACPI Device Scope Structure - PCI device path.
+ * In accordance with the Intel spec.
+ */
+typedef struct ACPIDEVSCOPEPATH
+{
+ /** PCI device number. */
+ uint8_t uDevice;
+ /** PCI function number. */
+ uint8_t uFunction;
+} ACPIDEVSCOPEPATH;
+AssertCompileSize(ACPIDEVSCOPEPATH, 2);
+
+
+/**
+ * Device Scope Structure.
+ * In accordance with the Intel spec.
+ */
+#pragma pack(1)
+typedef struct ACPIDMARDEVSCOPE
+{
+ /** Type, see ACPIDMARDEVSCOPE_TYPE_XXX. */
+ uint8_t uType;
+ /** Length (must be 6 + size of auPath field). */
+ uint8_t cbLength;
+ /** Reserved (MBZ). */
+ uint8_t abRsvd[2];
+ /** Enumeration ID (for I/O APIC, HPET and ACPI namespace devices). */
+ uint8_t idEnum;
+ /** First bus number for this device. */
+ uint8_t uStartBusNum;
+ /** Hierarchical path from the Host Bridge to the device. */
+ ACPIDEVSCOPEPATH Path;
+} ACPIDMARDEVSCOPE;
+#pragma pack()
+AssertCompileMemberOffset(ACPIDMARDEVSCOPE, cbLength, 1);
+AssertCompileMemberOffset(ACPIDMARDEVSCOPE, idEnum, 4);
+AssertCompileMemberOffset(ACPIDMARDEVSCOPE, uStartBusNum, 5);
+AssertCompileMemberOffset(ACPIDMARDEVSCOPE, Path, 6);
+
+/** ACPI DMAR revision (not the OEM revision field).
+ * In accordance with the Intel spec. */
+#define ACPI_DMAR_REVISION 1
+
+
+#endif /* !VBOX_INCLUDED_iommu_intel_h */
+
diff --git a/include/VBox/log.h b/include/VBox/log.h
new file mode 100644
index 00000000..9a2fe937
--- /dev/null
+++ b/include/VBox/log.h
@@ -0,0 +1,1239 @@
+/** @file
+ * VirtualBox - Logging.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_log_h
+#define VBOX_INCLUDED_log_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+/*
+ * 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 VBOXLOGGROUP
+{
+ /** 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,
+ /** Audio test group. */
+ LOG_GROUP_AUDIO_TEST,
+ /** 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,
+ /** NS DP8390 Ethernet Device group. */
+ LOG_GROUP_DEV_DP8390,
+ /** 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,
+ /** 3C501 Ethernet Device group. */
+ LOG_GROUP_DEV_ELNK,
+ /** Floppy Controller Device group. */
+ LOG_GROUP_DEV_FDC,
+ /** Flash Device group. */
+ LOG_GROUP_DEV_FLASH,
+ /** 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,
+ /** The internal networking IP stack Device group. */
+ LOG_GROUP_DEV_INIP,
+ /** I/O APIC Device group. */
+ LOG_GROUP_DEV_IOAPIC,
+ /** IOMMU Device group. */
+ LOG_GROUP_DEV_IOMMU,
+ /** 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,
+ /** QEMU firmware config Device group. */
+ LOG_GROUP_DEV_QEMUFWCFG,
+ /** 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,
+ /** Trusted Platform Module Device group. */
+ LOG_GROUP_DEV_TPM,
+ /** 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,
+ /** Cloud tunnel driver group. */
+ LOG_GROUP_DRV_CTUN,
+ /** 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,
+ /** Trusted Platform Module Emulation driver group. */
+ LOG_GROUP_DRV_TPM_EMU,
+ /** Trusted Platform Module Host driver group. */
+ LOG_GROUP_DRV_TPM_HOST,
+ /** 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,
+ /** The VMNET networking driver group. */
+ LOG_GROUP_DRV_VMNET,
+ /** 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,
+ /** IEM AMD-V group. */
+ LOG_GROUP_IEM_SVM,
+ /** IEM VT-x group. */
+ LOG_GROUP_IEM_VMX,
+ /** I/O buffer management group. */
+ LOG_GROUP_IOBUFMGMT,
+ /** IOM group. */
+ LOG_GROUP_IOM,
+ /** IOM group, I/O port part. */
+ LOG_GROUP_IOM_IOPORT,
+ /** IOM group, MMIO part. */
+ LOG_GROUP_IOM_MMIO,
+ /** 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, 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, tcpip.c TCPIP_DEBUG */
+ LOG_GROUP_LWIP_TCPIP,
+ /** 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, IAppliance. */
+ LOG_GROUP_MAIN_APPLIANCE,
+ /** Main group, IAudioAdapter. */
+ LOG_GROUP_MAIN_AUDIOADAPTER,
+ /** Main group, IAudioDevice. */
+ LOG_GROUP_MAIN_AUDIODEVICE,
+ /** Main group, IAudioSettings. */
+ LOG_GROUP_MAIN_AUDIOSETTINGS,
+ /** Main group, IBandwidthControl. */
+ LOG_GROUP_MAIN_BANDWIDTHCONTROL,
+ /** Main group, IBandwidthGroup. */
+ LOG_GROUP_MAIN_BANDWIDTHGROUP,
+ /** Main group, IBIOSSettings. */
+ LOG_GROUP_MAIN_BIOSSETTINGS,
+ /** Main group, IBooleanFormValue. */
+ LOG_GROUP_MAIN_BOOLEANFORMVALUE,
+ /** Main group, ICertificate. */
+ LOG_GROUP_MAIN_CERTIFICATE,
+ /** Main group, IChoiceFormValue. */
+ LOG_GROUP_MAIN_CHOICEFORMVALUE,
+ /** Main group, ICloudClient. */
+ LOG_GROUP_MAIN_CLOUDCLIENT,
+ /** Main group, ICloudMachine. */
+ LOG_GROUP_MAIN_CLOUDMACHINE,
+ /** Main group, ICloudNetwork. */
+ LOG_GROUP_MAIN_CLOUDNETWORK,
+ /** Main group, ICloudNetworkEnvironmentInfo */
+ LOG_GROUP_MAIN_CLOUDNETWORKENVIRONMENTINFO,
+ /** Main group, ICloudNetworkGatewayInfo */
+ LOG_GROUP_MAIN_CLOUDNETWORKGATEWAYINFO,
+ /** Main group, ICloudProfile. */
+ LOG_GROUP_MAIN_CLOUDPROFILE,
+ /** Main group, ICloudProfileChangedEvent. */
+ LOG_GROUP_MAIN_CLOUDPROFILECHANGEDEVENT,
+ /** Main group, ICloudProfileRegisteredEvent. */
+ LOG_GROUP_MAIN_CLOUDPROFILEREGISTEREDEVENT,
+ /** Main group, ICloudProvider. */
+ LOG_GROUP_MAIN_CLOUDPROVIDER,
+ /** Main group, ICloudProviderManager. */
+ LOG_GROUP_MAIN_CLOUDPROVIDERMANAGER,
+ /** Main group, IConsole. */
+ LOG_GROUP_MAIN_CONSOLE,
+ /** Main group, ICPUProfile. */
+ LOG_GROUP_MAIN_CPUPROFILE,
+ /** Main group, IDataModel. */
+ LOG_GROUP_MAIN_DATAMODEL,
+ /** Main group, IDataStream. */
+ LOG_GROUP_MAIN_DATASTREAM,
+ /** Main group, IDHCPConfig. */
+ LOG_GROUP_MAIN_DHCPCONFIG,
+ /** Main group, IDHCPGlobalConfig. */
+ LOG_GROUP_MAIN_DHCPGLOBALCONFIG,
+ /** Main group, IDHCPGroupCondition. */
+ LOG_GROUP_MAIN_DHCPGROUPCONDITION,
+ /** Main group, IDHCPGroupConfig. */
+ LOG_GROUP_MAIN_DHCPGROUPCONFIG,
+ /** Main group, IDHCPIndividualConfig. */
+ LOG_GROUP_MAIN_DHCPINDIVIDUALCONFIG,
+ /** 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, 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, 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, IFile. */
+ LOG_GROUP_MAIN_FILE,
+ /** Main group, IForm. */
+ LOG_GROUP_MAIN_FORM,
+ /** Main group, IFormValue. */
+ LOG_GROUP_MAIN_FORMVALUE,
+ /** Main group, IFramebuffer. */
+ LOG_GROUP_MAIN_FRAMEBUFFER,
+ /** Main group, IFramebufferOverlay. */
+ LOG_GROUP_MAIN_FRAMEBUFFEROVERLAY,
+ /** Main group, IFsInfo. */
+ LOG_GROUP_MAIN_FSINFO,
+ /** Main group, IFsObjInfo. */
+ LOG_GROUP_MAIN_FSOBJINFO,
+ /** Main group, IGraphicsAdapter. */
+ LOG_GROUP_MAIN_GRAPHICSADAPTER,
+ /** Main group, IGuest. */
+ LOG_GROUP_MAIN_GUEST,
+ /** Main group, IGuestDebugControl. */
+ LOG_GROUP_MAIN_GUESTDEBUGCONTROL,
+ /** 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, IGuestFsInfo. */
+ LOG_GROUP_MAIN_GUESTFSINFO,
+ /** Main group, IGuestFsObjInfo. */
+ LOG_GROUP_MAIN_GUESTFSOBJINFO,
+ /** Main group, IGuestOSType. */
+ LOG_GROUP_MAIN_GUESTOSTYPE,
+ /** Main group, IGuestProcess. */
+ LOG_GROUP_MAIN_GUESTPROCESS,
+ /** Main group, IGuestProcessEvent. */
+ LOG_GROUP_MAIN_GUESTPROCESSEVENT,
+ /** Main group, IGuestProcessIOEvent. */
+ LOG_GROUP_MAIN_GUESTPROCESSIOEVENT,
+ /** Main group, IGuestScreenInfo. */
+ LOG_GROUP_MAIN_GUESTSCREENINFO,
+ /** Main group, IGuestSession. */
+ LOG_GROUP_MAIN_GUESTSESSION,
+ /** Main group, IGuestSessionEvent. */
+ LOG_GROUP_MAIN_GUESTSESSIONEVENT,
+ /** Main group, IHost. */
+ LOG_GROUP_MAIN_HOST,
+ /** Main group, IHostAudioDevice. */
+ LOG_GROUP_MAIN_HOSTAUDIODEVICE,
+ /** Main group, IHostDrive. */
+ LOG_GROUP_MAIN_HOSTDRIVE,
+ /** Main group, IHostDriveList. */
+ LOG_GROUP_MAIN_HOSTDRIVELIST,
+ /** Main group, IHostDrivePartition. */
+ LOG_GROUP_MAIN_HOSTDRIVEPARTITION,
+ /** Main group, IHostNetworkInterface. */
+ LOG_GROUP_MAIN_HOSTNETWORKINTERFACE,
+ /** Main group, IHostOnlyNetwork. */
+ LOG_GROUP_MAIN_HOSTONLYNETWORK,
+ /** Main group, IHostUpdateAgent. */
+ LOG_GROUP_MAIN_HOSTUPDATEAGENT,
+ /** 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, IMachine. */
+ LOG_GROUP_MAIN_MACHINE,
+ /** Main group, IMachineDebugger. */
+ LOG_GROUP_MAIN_MACHINEDEBUGGER,
+ /** Main group, IMachineEvent. */
+ LOG_GROUP_MAIN_MACHINEEVENT,
+ /** Main group, IMedium. */
+ LOG_GROUP_MAIN_MEDIUM,
+ /** Main group, IMediumAttachment. */
+ LOG_GROUP_MAIN_MEDIUMATTACHMENT,
+ /** Main group, IMediumFormat. */
+ LOG_GROUP_MAIN_MEDIUMFORMAT,
+ /** Main group, IMediumIO. */
+ LOG_GROUP_MAIN_MEDIUMIO,
+ /** Main group, IMouse. */
+ LOG_GROUP_MAIN_MOUSE,
+ /** Main group, IMousePointerShape. */
+ LOG_GROUP_MAIN_MOUSEPOINTERSHAPE,
+ /** Main group, INATEngine. */
+ LOG_GROUP_MAIN_NATENGINE,
+ /** Main group, INATNetwork. */
+ LOG_GROUP_MAIN_NATNETWORK,
+ /** Main group, INetworkAdapter. */
+ LOG_GROUP_MAIN_NETWORKADAPTER,
+ /** Main group, INvramStore. */
+ LOG_GROUP_MAIN_NVRAMSTORE,
+ /** Main group, IParallelPort. */
+ LOG_GROUP_MAIN_PARALLELPORT,
+ /** 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, IProgressCreatedEvent. */
+ LOG_GROUP_MAIN_PROGRESSCREATEDEVENT,
+ /** Main group, IProgressEvent. */
+ LOG_GROUP_MAIN_PROGRESSEVENT,
+ /** Main group, IRangedIntegerFormValue. */
+ LOG_GROUP_MAIN_RANGEDINTEGERFORMVALUE,
+ /** Main group, IRecordingScreenSettings. */
+ LOG_GROUP_MAIN_RECORDINGSCREENSETTINGS,
+ /** Main group, IRecordingSettings. */
+ LOG_GROUP_MAIN_RECORDINGSETTINGS,
+ /** Main group, IReusableEvent. */
+ LOG_GROUP_MAIN_REUSABLEEVENT,
+ /** Main group, ISerialPort. */
+ LOG_GROUP_MAIN_SERIALPORT,
+ /** Main group, ISession. */
+ LOG_GROUP_MAIN_SESSION,
+ /** Main group, ISharedFolder. */
+ LOG_GROUP_MAIN_SHAREDFOLDER,
+ /** Main group, ISnapshot. */
+ LOG_GROUP_MAIN_SNAPSHOT,
+ /** Main group, ISnapshotEvent. */
+ LOG_GROUP_MAIN_SNAPSHOTEVENT,
+ /** Main group, IStorageController. */
+ LOG_GROUP_MAIN_STORAGECONTROLLER,
+ /** Main group, IStringArray. */
+ LOG_GROUP_MAIN_STRINGARRAY,
+ /** Main group, IStringFormValue. */
+ LOG_GROUP_MAIN_STRINGFORMVALUE,
+ /** Main group, ISystemProperties. */
+ LOG_GROUP_MAIN_SYSTEMPROPERTIES,
+ /** Main group, threaded tasks. */
+ LOG_GROUP_MAIN_THREAD_TASK,
+ /** Main group, IToken. */
+ LOG_GROUP_MAIN_TOKEN,
+ /** Main group, ITrustedPlatformModule. */
+ LOG_GROUP_MAIN_TRUSTEDPLATFORMMODULE,
+ /** Main group, IUefiVariableStore. */
+ LOG_GROUP_MAIN_UEFIVARIABLESTORE,
+ /** Main group, IUnattended. */
+ LOG_GROUP_MAIN_UNATTENDED,
+ /** Main group, IUpdateAgent. */
+ LOG_GROUP_MAIN_UPDATEAGENT,
+ /** Main group, IUpdateAgentAvailableEvent. */
+ LOG_GROUP_MAIN_UPDATEAGENTAVAILABLEEVENT,
+ /** Main group, IUpdateAgentErrorEvent. */
+ LOG_GROUP_MAIN_UPDATEAGENTERROREVENT,
+ /** Main group, IUpdateAgentEvent. */
+ LOG_GROUP_MAIN_UPDATEAGENTEVENT,
+ /** Main group, IUpdateAgentSettingsChangedEvent. */
+ LOG_GROUP_MAIN_UPDATEAGENTSETTINGSCHANGEDEVENT,
+ /** Main group, IUpdateAgentStateChangedEvent. */
+ LOG_GROUP_MAIN_UPDATEAGENTSTATECHANGEDEVENT,
+ /** Main group, IUSBController. */
+ LOG_GROUP_MAIN_USBCONTROLLER,
+ /** Main group, IUSBDevice. */
+ LOG_GROUP_MAIN_USBDEVICE,
+ /** Main group, IUSBDeviceFilter. */
+ LOG_GROUP_MAIN_USBDEVICEFILTER,
+ /** Main group, IUSBDeviceFilters. */
+ LOG_GROUP_MAIN_USBDEVICEFILTERS,
+ /** Main group, IUSBProxyBackend. */
+ LOG_GROUP_MAIN_USBPROXYBACKEND,
+ /** Main group, IVBoxSVC. */
+ LOG_GROUP_MAIN_VBOXSVC,
+ /** Main group, IVetoEvent. */
+ LOG_GROUP_MAIN_VETOEVENT,
+ /** Main group, IVFSExplorer. */
+ LOG_GROUP_MAIN_VFSEXPLORER,
+ /** Main group, IVirtualBox. */
+ LOG_GROUP_MAIN_VIRTUALBOX,
+ /** Main group, IVirtualBoxClient. */
+ LOG_GROUP_MAIN_VIRTUALBOXCLIENT,
+ /** Main group, IVirtualBoxSDS. */
+ LOG_GROUP_MAIN_VIRTUALBOXSDS,
+ /** Main group, IVirtualSystemDescription. */
+ LOG_GROUP_MAIN_VIRTUALSYSTEMDESCRIPTION,
+ /** Main group, IVirtualSystemDescriptionForm. */
+ LOG_GROUP_MAIN_VIRTUALSYSTEMDESCRIPTIONFORM,
+ /** Main group, VMM device interfaces. */
+ LOG_GROUP_MAIN_VMMDEVINTERFACES,
+ /** Main group, IVRDEServer. */
+ LOG_GROUP_MAIN_VRDESERVER,
+ /** Main group, IVRDEServerInfo. */
+ LOG_GROUP_MAIN_VRDESERVERINFO,
+ /** 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,
+ /** NEM group. */
+ LOG_GROUP_NEM,
+ /** The network adaptor driver group. */
+ LOG_GROUP_NET_ADP_DRV,
+ /** The DHCP network service deamon. */
+ LOG_GROUP_NET_DHCPD,
+ /** 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 critical section group. */
+ LOG_GROUP_PDM_CRITSECT,
+ /** PDM read/write critical section group. */
+ LOG_GROUP_PDM_CRITSECTRW,
+ /** PDM Device group. */
+ LOG_GROUP_PDM_DEVICE,
+ /** PDM Driver group. */
+ LOG_GROUP_PDM_DRIVER,
+ /** PDM Loader group. */
+ LOG_GROUP_PDM_LDR,
+ /** PDM Queue group. */
+ LOG_GROUP_PDM_QUEUE,
+ /** PDM Task group. */
+ LOG_GROUP_PDM_TASK,
+ /** PDM Thread group. */
+ LOG_GROUP_PDM_THREAD,
+ /** 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,
+ /** Audio + video recording. */
+ LOG_GROUP_RECORDING,
+ /** 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 Library. */
+ LOG_GROUP_VBGL,
+ /** Generic virtual disk layer. */
+ LOG_GROUP_VD,
+ /** CUE/BIN virtual disk backend. */
+ LOG_GROUP_VD_CUE,
+ /** 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,
+ /** VBox Guest Additions Driver (VBoxGuest). */
+ LOG_GROUP_VGDRV,
+ /** 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!!! */
+} VBOXLOGGROUP;
+
+
+/** @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", \
+ "AUDIO_TEST", \
+ "AUTOLOGON", \
+ "CFGM", \
+ "CPUM", \
+ "CSAM", \
+ "DBGC", \
+ "DBGF", \
+ "DBGF_INFO", \
+ "DBGG", \
+ "DEV", \
+ "DEV_AC97", \
+ "DEV_ACPI", \
+ "DEV_AHCI", \
+ "DEV_APIC", \
+ "DEV_BUSLOGIC", \
+ "DEV_DMA", \
+ "DEV_DP8390", \
+ "DEV_E1000", \
+ "DEV_EFI", \
+ "DEV_EHCI", \
+ "DEV_ELNK", \
+ "DEV_FDC", \
+ "DEV_FLASH", \
+ "DEV_GIM", \
+ "DEV_HDA", \
+ "DEV_HDA_CODEC", \
+ "DEV_HPET", \
+ "DEV_IDE", \
+ "DEV_INIP", \
+ "DEV_IOAPIC", \
+ "DEV_IOMMU", \
+ "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_QEMUFWCFG", \
+ "DEV_RTC", \
+ "DEV_SB16", \
+ "DEV_SERIAL", \
+ "DEV_SMC", \
+ "DEV_TPM", \
+ "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_CTUN", \
+ "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_TPM_EMU", \
+ "DRV_TPM_HOST", \
+ "DRV_TRANSPORT_ASYNC", \
+ "DRV_TUN", \
+ "DRV_UDP", \
+ "DRV_UDPTUNNEL", \
+ "DRV_USBPROXY", \
+ "DRV_VBOXHDD", \
+ "DRV_VD", \
+ "DRV_VMNET", \
+ "DRV_VRDE_AUDIO", \
+ "DRV_VSWITCH", \
+ "DRV_VUSB", \
+ "EM", \
+ "FTM", \
+ "GIM", \
+ "GMM", \
+ "GUEST_CONTROL", \
+ "GUEST_DND", \
+ "GUI", \
+ "GVMM", \
+ "HGCM", \
+ "HGSMI", \
+ "HM", \
+ "IEM", \
+ "IEM_SVM", \
+ "IEM_VMX", \
+ "IOBUFMGMT", \
+ "IOM", \
+ "IOM_IOPORT", \
+ "IOM_MMIO", \
+ "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_TCP_CWND", \
+ "LWIP_TCP_FR", \
+ "LWIP_TCP_INPUT", \
+ "LWIP_TCP_OUTPUT", \
+ "LWIP_TCP_QLEN", \
+ "LWIP_TCP_RST", \
+ "LWIP_TCP_RTO", \
+ "LWIP_TCP_WND", \
+ "LWIP_TCPIP", \
+ "LWIP_TIMERS", \
+ "LWIP_UDP", \
+ "MAIN", \
+ "MAIN_ADDITIONSFACILITY", \
+ "MAIN_APPLIANCE", \
+ "MAIN_AUDIOADAPTER", \
+ "MAIN_AUDIODEVICE", \
+ "MAIN_AUDIOSETTINGS", \
+ "MAIN_BANDWIDTHCONTROL", \
+ "MAIN_BANDWIDTHGROUP", \
+ "MAIN_BIOSSETTINGS", \
+ "MAIN_BOOLEANFORMVALUE", \
+ "MAIN_CERTIFICATE", \
+ "MAIN_CHOICEFORMVALUE", \
+ "MAIN_CLOUDCLIENT", \
+ "MAIN_CLOUDMACHINE", \
+ "MAIN_CLOUDNETWORK", \
+ "MAIN_CLOUDNETWORKENVIRONMENTINFO", \
+ "MAIN_CLOUDNETWORKGATEWAYINFO", \
+ "MAIN_CLOUDPROFILE", \
+ "MAIN_CLOUDPROFILECHANGEDEVENT", \
+ "MAIN_CLOUDPROFILEREGISTEREDEVENT", \
+ "MAIN_CLOUDPROVIDER", \
+ "MAIN_CLOUDPROVIDERMANAGER", \
+ "MAIN_CONSOLE", \
+ "MAIN_CPUPROFILE", \
+ "MAIN_DATAMODEL", \
+ "MAIN_DATASTREAM", \
+ "MAIN_DHCPCONFIG", \
+ "MAIN_DHCPGLOBALCONFIG", \
+ "MAIN_DHCPGROUPCONDITION", \
+ "MAIN_DHCPGROUPCONFIG", \
+ "MAIN_DHCPINDIVIDUALCONFIG", \
+ "MAIN_DHCPSERVER", \
+ "MAIN_DIRECTORY", \
+ "MAIN_DISPLAY", \
+ "MAIN_DISPLAYSOURCEBITMAP", \
+ "MAIN_DNDBASE", \
+ "MAIN_DNDSOURCE", \
+ "MAIN_DNDTARGET", \
+ "MAIN_EMULATEDUSB", \
+ "MAIN_EVENT", \
+ "MAIN_EVENTLISTENER", \
+ "MAIN_EVENTSOURCE", \
+ "MAIN_EXTPACK", \
+ "MAIN_EXTPACKBASE", \
+ "MAIN_EXTPACKFILE", \
+ "MAIN_EXTPACKMANAGER", \
+ "MAIN_EXTPACKPLUGIN", \
+ "MAIN_FILE", \
+ "MAIN_FORM", \
+ "MAIN_FORMVALUE", \
+ "MAIN_FRAMEBUFFER", \
+ "MAIN_FRAMEBUFFEROVERLAY", \
+ "MAIN_FSINFO", \
+ "MAIN_FSOBJINFO", \
+ "MAIN_GRAPHICSADAPTER", \
+ "MAIN_GUEST", \
+ "MAIN_GUESTDEBUGCONTROL", \
+ "MAIN_GUESTDIRECTORY", \
+ "MAIN_GUESTDNDSOURCE", \
+ "MAIN_GUESTDNDTARGET", \
+ "MAIN_GUESTERRORINFO", \
+ "MAIN_GUESTFILE", \
+ "MAIN_GUESTFILEEVENT", \
+ "MAIN_GUESTFILEIOEVENT", \
+ "MAIN_GUESTFSINFO", \
+ "MAIN_GUESTFSOBJINFO", \
+ "MAIN_GUESTOSTYPE", \
+ "MAIN_GUESTPROCESS", \
+ "MAIN_GUESTPROCESSEVENT", \
+ "MAIN_GUESTPROCESSIOEVENT", \
+ "MAIN_GUESTSCREENINFO", \
+ "MAIN_GUESTSESSION", \
+ "MAIN_GUESTSESSIONEVENT", \
+ "MAIN_HOST", \
+ "MAIN_HOSTAUDIODEVICE", \
+ "MAIN_HOSTDRIVE", \
+ "MAIN_HOSTDRIVELIST", \
+ "MAIN_HOSTDRIVEPARTITION", \
+ "MAIN_HOSTNETWORKINTERFACE", \
+ "MAIN_HOSTONLYNETWORK", \
+ "MAIN_HOSTUPDATEAGENT", \
+ "MAIN_HOSTUSBDEVICE", \
+ "MAIN_HOSTUSBDEVICEFILTER", \
+ "MAIN_HOSTVIDEOINPUTDEVICE", \
+ "MAIN_INTERNALMACHINECONTROL", \
+ "MAIN_INTERNALSESSIONCONTROL", \
+ "MAIN_KEYBOARD", \
+ "MAIN_MACHINE", \
+ "MAIN_MACHINEDEBUGGER", \
+ "MAIN_MACHINEEVENT", \
+ "MAIN_MEDIUM", \
+ "MAIN_MEDIUMATTACHMENT", \
+ "MAIN_MEDIUMFORMAT", \
+ "MAIN_MEDIUMIO", \
+ "MAIN_MOUSE", \
+ "MAIN_MOUSEPOINTERSHAPE", \
+ "MAIN_NATENGINE", \
+ "MAIN_NATNETWORK", \
+ "MAIN_NETWORKADAPTER", \
+ "MAIN_NVRAMSTORE", \
+ "MAIN_PARALLELPORT", \
+ "MAIN_PCIADDRESS", \
+ "MAIN_PCIDEVICEATTACHMENT", \
+ "MAIN_PERFORMANCECOLLECTOR", \
+ "MAIN_PERFORMANCEMETRIC", \
+ "MAIN_PROCESS", \
+ "MAIN_PROGRESS", \
+ "MAIN_PROGRESSCREATEDEVENT", \
+ "MAIN_PROGRESSEVENT", \
+ "MAIN_RANGEDINTEGERFORMVALUE", \
+ "MAIN_RECORDINGSCREENSETTINGS", \
+ "MAIN_RECORDINGSETTINGS", \
+ "MAIN_REUSABLEEVENT", \
+ "MAIN_SERIALPORT", \
+ "MAIN_SESSION", \
+ "MAIN_SHAREDFOLDER", \
+ "MAIN_SNAPSHOT", \
+ "MAIN_SNAPSHOTEVENT", \
+ "MAIN_STORAGECONTROLLER", \
+ "MAIN_STRINGARRAY", \
+ "MAIN_STRINGFORMVALUE", \
+ "MAIN_SYSTEMPROPERTIES", \
+ "MAIN_THREAD_TASK", \
+ "MAIN_TOKEN", \
+ "MAIN_TRUSTEDPLATFORMMODULE", \
+ "MAIN_UEFIVARIABLESTORE", \
+ "MAIN_UNATTENDED", \
+ "MAIN_UPDATEAGENT", \
+ "MAIN_UPDATEAGENTAVAILABLEEVENT", \
+ "MAIN_UPDATEAGENTERROREVENT", \
+ "MAIN_UPDATEAGENTEVENT", \
+ "MAIN_UPDATEAGENTSETTINGSCHANGEDEVENT", \
+ "MAIN_UPDATEAGENTSTATECHANGEDEVENT", \
+ "MAIN_USBCONTROLLER", \
+ "MAIN_USBDEVICE", \
+ "MAIN_USBDEVICEFILTER", \
+ "MAIN_USBDEVICEFILTERS", \
+ "MAIN_USBPROXYBACKEND", \
+ "MAIN_VBOXSVC", \
+ "MAIN_VETOEVENT", \
+ "MAIN_VFSEXPLORER", \
+ "MAIN_VIRTUALBOX", \
+ "MAIN_VIRTUALBOXCLIENT", \
+ "MAIN_VIRTUALBOXSDS", \
+ "MAIN_VIRTUALSYSTEMDESCRIPTION", \
+ "MAIN_VIRTUALSYSTEMDESCRIPTIONFORM", \
+ "MAIN_VMMDEVINTERFACES", \
+ "MAIN_VRDESERVER", \
+ "MAIN_VRDESERVERINFO", \
+ "MISC", \
+ "MM", \
+ "MM_HEAP", \
+ "MM_HYPER", \
+ "MM_HYPER_HEAP", \
+ "MM_PHYS", \
+ "MM_POOL", \
+ "NAT_SERVICE", \
+ "NEM", \
+ "NET_ADP_DRV", \
+ "NET_DHCPD", \
+ "NET_FLT_DRV", \
+ "NET_SERVICE", \
+ "NET_SHAPER", \
+ "PATM", \
+ "PDM", \
+ "PDM_ASYNC_COMPLETION", \
+ "PDM_BLK_CACHE", \
+ "PDM_CRITSECT", \
+ "PDM_CRITSECTRW", \
+ "PDM_DEVICE", \
+ "PDM_DRIVER", \
+ "PDM_LDR", \
+ "PDM_QUEUE", \
+ "PDM_TASK", \
+ "PDM_THREAD", \
+ "PGM", \
+ "PGM_DYNMAP", \
+ "PGM_PHYS", \
+ "PGM_PHYS_ACCESS", \
+ "PGM_POOL", \
+ "PGM_SHARED", \
+ "RECORDING", \
+ "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", \
+ "VBGL", \
+ "VD", \
+ "VD_CUE", \
+ "VD_DMG", \
+ "VD_ISCSI", \
+ "VD_PARALLELS", \
+ "VD_QCOW", \
+ "VD_QED", \
+ "VD_RAW", \
+ "VD_VDI", \
+ "VD_VHD", \
+ "VD_VHDX", \
+ "VD_VMDK", \
+ "VGDRV", \
+ "VM", \
+ "VMM", \
+ "VRDE", \
+ "VRDP", \
+ "VSCSI", \
+ "WEBSERVICE", \
+}
+
+/** @} */
+#endif /* !VBOX_INCLUDED_log_h */
diff --git a/include/VBox/msi.h b/include/VBox/msi.h
new file mode 100644
index 00000000..34aae831
--- /dev/null
+++ b/include/VBox/msi.h
@@ -0,0 +1,287 @@
+/** @file
+ * MSI - Message signalled interrupts support.
+ */
+
+/*
+ * Copyright (C) 2010-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_msi_h
+#define VBOX_INCLUDED_msi_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/cdefs.h>
+#include <VBox/types.h>
+#include <iprt/assert.h>
+
+#include <VBox/pci.h>
+
+/* Constants for Intel APIC MSI messages */
+#define VBOX_MSI_DATA_VECTOR_SHIFT 0
+#define VBOX_MSI_DATA_VECTOR_MASK 0x000000ff
+#define VBOX_MSI_DATA_VECTOR(v) (((v) << VBOX_MSI_DATA_VECTOR_SHIFT) & \
+ VBOX_MSI_DATA_VECTOR_MASK)
+#define VBOX_MSI_DATA_DELIVERY_MODE_SHIFT 8
+#define VBOX_MSI_DATA_DELIVERY_FIXED (0 << VBOX_MSI_DATA_DELIVERY_MODE_SHIFT)
+#define VBOX_MSI_DATA_DELIVERY_LOWPRI (1 << VBOX_MSI_DATA_DELIVERY_MODE_SHIFT)
+
+#define VBOX_MSI_DATA_LEVEL_SHIFT 14
+#define VBOX_MSI_DATA_LEVEL_DEASSERT (0 << VBOX_MSI_DATA_LEVEL_SHIFT)
+#define VBOX_MSI_DATA_LEVEL_ASSERT (1 << VBOX_MSI_DATA_LEVEL_SHIFT)
+
+#define VBOX_MSI_DATA_TRIGGER_SHIFT 15
+#define VBOX_MSI_DATA_TRIGGER_EDGE (0 << VBOX_MSI_DATA_TRIGGER_SHIFT)
+#define VBOX_MSI_DATA_TRIGGER_LEVEL (1 << VBOX_MSI_DATA_TRIGGER_SHIFT)
+
+/**
+ * MSI Interrupt Delivery modes.
+ * In accordance with the Intel spec.
+ * See Intel spec. "10.11.2 Message Data Register Format".
+ */
+#define VBOX_MSI_DELIVERY_MODE_FIXED (0)
+#define VBOX_MSI_DELIVERY_MODE_LOWEST_PRIO (1)
+#define VBOX_MSI_DELIVERY_MODE_SMI (2)
+#define VBOX_MSI_DELIVERY_MODE_NMI (4)
+#define VBOX_MSI_DELIVERY_MODE_INIT (5)
+#define VBOX_MSI_DELIVERY_MODE_EXT_INT (7)
+
+/**
+ * MSI region, actually same as LAPIC MMIO region, but listens on bus,
+ * not CPU, accesses.
+ */
+#define VBOX_MSI_ADDR_BASE 0xfee00000
+#define VBOX_MSI_ADDR_SIZE 0x100000
+
+#define VBOX_MSI_ADDR_SHIFT 20
+
+#define VBOX_MSI_ADDR_DEST_MODE_SHIFT 2
+#define VBOX_MSI_ADDR_DEST_MODE_PHYSICAL (0 << VBOX_MSI_ADDR_DEST_MODE_SHIFT)
+#define VBOX_MSI_ADDR_DEST_MODE_LOGICAL (1 << VBOX_MSI_ADDR_DEST_MODE_SHIFT)
+
+#define VBOX_MSI_ADDR_REDIRECTION_SHIFT 3
+#define VBOX_MSI_ADDR_REDIRECTION_CPU (0 << VBOX_MSI_ADDR_REDIRECTION_SHIFT)
+ /* dedicated cpu */
+#define VBOX_MSI_ADDR_REDIRECTION_LOWPRI (1 << VBOX_MSI_ADDR_REDIRECTION_SHIFT)
+ /* lowest priority */
+
+#define VBOX_MSI_ADDR_DEST_ID_SHIFT 12
+#define VBOX_MSI_ADDR_DEST_ID_MASK 0x00ffff0
+#define VBOX_MSI_ADDR_DEST_ID(dest) (((dest) << VBOX_MSI_ADDR_DEST_ID_SHIFT) & \
+ VBOX_MSI_ADDR_DEST_ID_MASK)
+#define VBOX_MSI_ADDR_EXT_DEST_ID(dest) ((dest) & 0xffffff00)
+
+#define VBOX_MSI_ADDR_IR_EXT_INT (1 << 4)
+#define VBOX_MSI_ADDR_IR_SHV (1 << 3)
+#define VBOX_MSI_ADDR_IR_INDEX1(index) ((index & 0x8000) >> 13)
+#define VBOX_MSI_ADDR_IR_INDEX2(index) ((index & 0x7fff) << 5)
+
+/* Maximum number of vectors, per device/function */
+#define VBOX_MSI_MAX_ENTRIES 32
+
+/* Offsets in MSI PCI capability structure (VBOX_PCI_CAP_ID_MSI) */
+#define VBOX_MSI_CAP_MESSAGE_CONTROL 0x02
+#define VBOX_MSI_CAP_MESSAGE_ADDRESS_32 0x04
+#define VBOX_MSI_CAP_MESSAGE_ADDRESS_LO 0x04
+#define VBOX_MSI_CAP_MESSAGE_ADDRESS_HI 0x08
+#define VBOX_MSI_CAP_MESSAGE_DATA_32 0x08
+#define VBOX_MSI_CAP_MESSAGE_DATA_64 0x0c
+#define VBOX_MSI_CAP_MASK_BITS_32 0x0c
+#define VBOX_MSI_CAP_PENDING_BITS_32 0x10
+#define VBOX_MSI_CAP_MASK_BITS_64 0x10
+#define VBOX_MSI_CAP_PENDING_BITS_64 0x14
+
+/* We implement MSI with per-vector masking */
+#define VBOX_MSI_CAP_SIZE_32 0x14
+#define VBOX_MSI_CAP_SIZE_64 0x18
+
+/**
+ * MSI-X differs from MSI by the fact that a dedicated physical page (in device
+ * memory) is assigned for MSI-X table, and Pending Bit Array (PBA), which is
+ * recommended to be separated from the main table by at least 2K.
+ *
+ * @{
+ */
+/** Size of a MSI-X page */
+#define VBOX_MSIX_PAGE_SIZE 0x1000
+/** Pending interrupts (PBA) */
+#define VBOX_MSIX_PAGE_PENDING (VBOX_MSIX_PAGE_SIZE / 2)
+/** Maximum number of vectors, per device/function */
+#define VBOX_MSIX_MAX_ENTRIES 2048
+/** Size of MSI-X PCI capability */
+#define VBOX_MSIX_CAP_SIZE 12
+/** Offsets in MSI-X PCI capability structure (VBOX_PCI_CAP_ID_MSIX) */
+#define VBOX_MSIX_CAP_MESSAGE_CONTROL 0x02
+#define VBOX_MSIX_TABLE_BIROFFSET 0x04
+#define VBOX_MSIX_PBA_BIROFFSET 0x08
+/** Size of single MSI-X table entry */
+#define VBOX_MSIX_ENTRY_SIZE 16
+/** @} */
+
+/**
+ * MSI Address Register.
+ */
+typedef union MSIADDR
+{
+ /*
+ * Intel and AMD xAPIC format.
+ * See Intel spec. 10.11.1 "Message Address Register Format".
+ * This also conforms to the AMD IOMMU spec. which omits specifying
+ * individual fields but specifies reserved bits.
+ */
+ struct
+ {
+ uint32_t u2Ign0 : 2; /**< Bits 1:0 - Ignored (read as 0, writes ignored). */
+ uint32_t u1DestMode : 1; /**< Bit 2 - DM: Destination Mode. */
+ uint32_t u1RedirHint : 1; /**< Bit 3 - RH: Redirection Hint. */
+ uint32_t u8Rsvd0 : 8; /**< Bits 11:4 - Reserved. */
+ uint32_t u8DestId : 8; /**< Bits 19:12 - Destination Id. */
+ uint32_t u12Addr : 12; /**< Bits 31:20 - Address. */
+ uint32_t u32Rsvd0; /**< Bits 63:32 - Reserved. */
+ } n;
+
+ /*
+ * Intel x2APIC Format.
+ * See Intel VT-d spec. 5.1.6.2 "Programming in Intel 64 x2APIC Mode".
+ */
+ struct
+ {
+ uint32_t u2Ign0 : 2; /**< Bits 1:0 - Ignored (read as 0, writes ignored). */
+ uint32_t u1DestMode : 1; /**< Bit 2 - DM: Destination Mode. */
+ uint32_t u1RedirHint : 1; /**< Bit 3 - RH: Redirection Hint. */
+ uint32_t u8Rsvd0 : 8; /**< Bits 11:4 - Reserved. */
+ uint32_t u8DestIdLo : 8; /**< Bits 19:12 - Destination Id (bits 7:0). */
+ uint32_t u12Addr : 12; /**< Bits 31:20 - Address. */
+ uint32_t u8Rsvd : 8; /**< Bits 39:32 - Reserved. */
+ uint32_t u24DestIdHi : 24; /**< Bits 63:40 - Destination Id (bits 31:8). */
+ } x2apic;
+
+ /*
+ * Intel IOMMU Remappable Interrupt Format.
+ * See Intel VT-d spec. 5.1.2.2 "Interrupt Requests in Remappable Format".
+ */
+ struct
+ {
+ uint32_t u2Ign0 : 2; /**< Bits 1:0 - Ignored (read as 0, writes ignored). */
+ uint32_t u1IntrIndexHi : 1; /**< Bit 2 - Interrupt Index[15]. */
+ uint32_t fShv : 1; /**< Bit 3 - Sub-Handle Valid. */
+ uint32_t fIntrFormat : 1; /**< Bit 4 - Interrupt Format (1=remappable, 0=compatibility). */
+ uint32_t u14IntrIndexLo : 15; /**< Bits 19:5 - Interrupt Index[14:0]. */
+ uint32_t u12Addr : 12; /**< Bits 31:20 - Address. */
+ uint32_t u32Rsvd0; /**< Bits 63:32 - Reserved. */
+ } dmar_remap;
+
+ /** The 32-bit unsigned integer view. */
+ uint32_t au32[2];
+
+ /** The 64-bit unsigned integer view. */
+ uint64_t u64;
+} MSIADDR;
+AssertCompileSize(MSIADDR, 8);
+/** Pointer to an MSI address register. */
+typedef MSIADDR *PMSIADDR;
+/** Pointer to a const MSI address register. */
+typedef MSIADDR const *PCMSIADDR;
+
+/** Mask of valid bits in the MSI address register. According to the AMD IOMMU spec.
+ * and presumably the PCI spec., the top 32-bits are not reserved. From a PCI/IOMMU
+ * standpoint this makes sense. However, when dealing with the CPU side of things
+ * we might want to ensure the upper bits are reserved. Does x86/x64 really
+ * support a 64-bit MSI address? */
+#define VBOX_MSI_ADDR_VALID_MASK UINT64_C(0xfffffffffffffffc)
+#define VBOX_MSI_ADDR_ADDR_MASK UINT64_C(0x00000000fff00000)
+
+/**
+ * MSI Data Register.
+ */
+typedef union MSIDATA
+{
+ /*
+ * Intel and AMD xAPIC format.
+ * See Intel spec. 10.11.2 "Message Data Register Format".
+ * This also conforms to the AMD IOMMU spec. which omits specifying
+ * individual fields but specifies reserved bits.
+ */
+ struct
+ {
+ uint32_t u8Vector : 8; /**< Bits 7:0 - Vector. */
+ uint32_t u3DeliveryMode : 3; /**< Bits 10:8 - Delivery Mode. */
+ uint32_t u3Rsvd0 : 3; /**< Bits 13:11 - Reserved. */
+ uint32_t u1Level : 1; /**< Bit 14 - Level. */
+ uint32_t u1TriggerMode : 1; /**< Bit 15 - Trigger Mode (0=edge, 1=level). */
+ uint32_t u16Rsvd0 : 16; /**< Bits 31:16 - Reserved. */
+ } n;
+
+ /*
+ * Intel x2APIC Format.
+ * See Intel VT-d spec. 5.1.6.2 "Programming in Intel 64 x2APIC Mode".
+ */
+ struct
+ {
+ uint32_t u8Vector : 8; /**< Bits 7:0 - Vector. */
+ uint32_t u1DeliveryMode : 1; /**< Bit 8 - Delivery Mode (0=fixed, 1=lowest priority). */
+ uint32_t u23Rsvd0 : 23; /**< Bits 31:9 - Reserved. */
+ } x2apic;
+
+ /*
+ * Intel IOMMU Remappable Interrupt Format.
+ * See Intel VT-d spec. 5.1.2.2 "Interrupt Requests in Remappable Format".
+ */
+ struct
+ {
+ uint16_t u16SubHandle;
+ uint16_t u16Rsvd0;
+ } dmar_remap;
+
+ /** The 32-bit unsigned integer view. */
+ uint32_t u32;
+} MSIDATA;
+AssertCompileSize(MSIDATA, 4);
+/** Pointer to an MSI data register. */
+typedef MSIDATA *PMSIDATA;
+/** Pointer to a const MSI data register. */
+typedef MSIDATA const *PCMSIDATA;
+
+/** Mask of valid bits in the MSI data register. */
+#define VBOX_MSI_DATA_VALID_MASK UINT64_C(0x000000000000ffff)
+
+/**
+ * MSI Message (Address and Data Register Pair).
+ */
+typedef struct MSIMSG
+{
+ /** The MSI Address Register. */
+ MSIADDR Addr;
+ /** The MSI Data Register. */
+ MSIDATA Data;
+} MSIMSG;
+
+#endif /* !VBOX_INCLUDED_msi_h */
diff --git a/include/VBox/nasm.mac b/include/VBox/nasm.mac
new file mode 100644
index 00000000..13abd88b
--- /dev/null
+++ b/include/VBox/nasm.mac
@@ -0,0 +1,44 @@
+;; @file
+; Global NASM macros
+;
+; @deprecated Use VBox/asmdefs.mac
+;
+
+;
+; Copyright (C) 2006-2022 Oracle and/or its affiliates.
+;
+; This file is part of VirtualBox base platform packages, as
+; available from https://www.virtualbox.org.
+;
+; This program is free software; you can redistribute it and/or
+; modify it under the terms of the GNU General Public License
+; as published by the Free Software Foundation, in version 3 of the
+; License.
+;
+; This program is distributed in the hope that it will be useful, but
+; WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with this program; if not, see <https://www.gnu.org/licenses>.
+;
+; The contents of this file may alternatively be used under the terms
+; of the Common Development and Distribution License Version 1.0
+; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+; in the VirtualBox 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.
+;
+; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+;
+
+%ifndef __VBox_nasm_mac__
+%define __VBox_nasm_mac__
+
+%include "VBox/asmdefs.mac"
+
+%endif
+
diff --git a/include/VBox/ostypes.h b/include/VBox/ostypes.h
new file mode 100644
index 00000000..8b82da43
--- /dev/null
+++ b/include/VBox/ostypes.h
@@ -0,0 +1,305 @@
+/** @file
+ * VirtualBox - Global Guest Operating System definition.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_ostypes_h
+#define VBOX_INCLUDED_ostypes_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#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.
+ */
+typedef enum VBOXOSTYPE
+{
+ VBOXOSTYPE_Unknown = 0,
+ VBOXOSTYPE_Unknown_x64 = 0x00100,
+
+ /** @name DOS and it's descendants
+ * @{ */
+ 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_WinNT3x = 0x30800,
+ 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_Win2k19_x64 = 0x3D100,
+ VBOXOSTYPE_Win11_x64 = 0x3E100,
+ VBOXOSTYPE_Win2k22_x64 = 0x3F100,
+ VBOXOSTYPE_OS2 = 0x40000,
+ VBOXOSTYPE_OS2Warp3 = 0x41000,
+ VBOXOSTYPE_OS2Warp4 = 0x42000,
+ VBOXOSTYPE_OS2Warp45 = 0x43000,
+ VBOXOSTYPE_ECS = 0x44000,
+ VBOXOSTYPE_ArcaOS = 0x45000,
+ VBOXOSTYPE_OS21x = 0x48000,
+ /** @} */
+ /** @name Unixy related OSes
+ * @{ */
+ 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_Debian31 = 0x55001, // 32-bit only
+ VBOXOSTYPE_Debian4 = 0x55002,
+ VBOXOSTYPE_Debian4_x64 = 0x55102,
+ VBOXOSTYPE_Debian5 = 0x55003,
+ VBOXOSTYPE_Debian5_x64 = 0x55103,
+ VBOXOSTYPE_Debian6 = 0x55004,
+ VBOXOSTYPE_Debian6_x64 = 0x55104,
+ VBOXOSTYPE_Debian7 = 0x55005,
+ VBOXOSTYPE_Debian7_x64 = 0x55105,
+ VBOXOSTYPE_Debian8 = 0x55006,
+ VBOXOSTYPE_Debian8_x64 = 0x55106,
+ VBOXOSTYPE_Debian9 = 0x55007,
+ VBOXOSTYPE_Debian9_x64 = 0x55107,
+ VBOXOSTYPE_Debian10 = 0x55008,
+ VBOXOSTYPE_Debian10_x64 = 0x55108,
+ VBOXOSTYPE_Debian11 = 0x55009,
+ VBOXOSTYPE_Debian11_x64 = 0x55109,
+ VBOXOSTYPE_Debian_latest_x64 = VBOXOSTYPE_Debian11_x64,
+ VBOXOSTYPE_OpenSUSE = 0x56000,
+ VBOXOSTYPE_OpenSUSE_x64 = 0x56100,
+ VBOXOSTYPE_OpenSUSE_Leap_x64 = 0x56101, // 64-bit only
+ VBOXOSTYPE_OpenSUSE_Tumbleweed = 0x56002,
+ VBOXOSTYPE_OpenSUSE_Tumbleweed_x64 = 0x56102,
+ VBOXOSTYPE_SUSE_LE = 0x56003,
+ VBOXOSTYPE_SUSE_LE_x64 = 0x56103,
+ VBOXOSTYPE_FedoraCore = 0x57000,
+ VBOXOSTYPE_FedoraCore_x64 = 0x57100,
+ VBOXOSTYPE_Gentoo = 0x58000,
+ VBOXOSTYPE_Gentoo_x64 = 0x58100,
+ VBOXOSTYPE_Mandriva = 0x59000,
+ VBOXOSTYPE_Mandriva_x64 = 0x59100,
+ VBOXOSTYPE_OpenMandriva_Lx = 0x59001,
+ VBOXOSTYPE_OpenMandriva_Lx_x64 = 0x59101,
+ VBOXOSTYPE_PCLinuxOS = 0x59002,
+ VBOXOSTYPE_PCLinuxOS_x64 = 0x59102,
+ VBOXOSTYPE_Mageia = 0x59003,
+ VBOXOSTYPE_Mageia_x64 = 0x59103,
+ VBOXOSTYPE_RedHat = 0x5A000,
+ VBOXOSTYPE_RedHat_x64 = 0x5A100,
+ VBOXOSTYPE_RedHat3 = 0x5A001,
+ VBOXOSTYPE_RedHat3_x64 = 0x5A101,
+ VBOXOSTYPE_RedHat4 = 0x5A002,
+ VBOXOSTYPE_RedHat4_x64 = 0x5A102,
+ VBOXOSTYPE_RedHat5 = 0x5A003,
+ VBOXOSTYPE_RedHat5_x64 = 0x5A103,
+ VBOXOSTYPE_RedHat6 = 0x5A004,
+ VBOXOSTYPE_RedHat6_x64 = 0x5A104,
+ VBOXOSTYPE_RedHat7_x64 = 0x5A105, // 64-bit only
+ VBOXOSTYPE_RedHat8_x64 = 0x5A106, // 64-bit only
+ VBOXOSTYPE_RedHat9_x64 = 0x5A107, // 64-bit only
+ VBOXOSTYPE_RedHat_latest_x64 = VBOXOSTYPE_RedHat9_x64,
+ VBOXOSTYPE_Turbolinux = 0x5B000,
+ VBOXOSTYPE_Turbolinux_x64 = 0x5B100,
+ VBOXOSTYPE_Ubuntu = 0x5C000,
+ VBOXOSTYPE_Ubuntu_x64 = 0x5C100,
+ VBOXOSTYPE_Xubuntu = 0x5C001,
+ VBOXOSTYPE_Xubuntu_x64 = 0x5C101,
+ VBOXOSTYPE_Lubuntu = 0x5C002,
+ VBOXOSTYPE_Lubuntu_x64 = 0x5C102,
+ VBOXOSTYPE_Ubuntu10_LTS = 0x5C003,
+ VBOXOSTYPE_Ubuntu10_LTS_x64 = 0x5C103,
+ VBOXOSTYPE_Ubuntu10 = 0x5C004,
+ VBOXOSTYPE_Ubuntu10_x64 = 0x5C104,
+ VBOXOSTYPE_Ubuntu11 = 0x5C005,
+ VBOXOSTYPE_Ubuntu11_x64 = 0x5C105,
+ VBOXOSTYPE_Ubuntu12_LTS = 0x5C006,
+ VBOXOSTYPE_Ubuntu12_LTS_x64 = 0x5C106,
+ VBOXOSTYPE_Ubuntu12 = 0x5C007,
+ VBOXOSTYPE_Ubuntu12_x64 = 0x5C107,
+ VBOXOSTYPE_Ubuntu13 = 0x5C008,
+ VBOXOSTYPE_Ubuntu13_x64 = 0x5C108,
+ VBOXOSTYPE_Ubuntu14_LTS = 0x5C009,
+ VBOXOSTYPE_Ubuntu14_LTS_x64 = 0x5C109,
+ VBOXOSTYPE_Ubuntu14 = 0x5C00a,
+ VBOXOSTYPE_Ubuntu14_x64 = 0x5C10a,
+ VBOXOSTYPE_Ubuntu15 = 0x5C00b,
+ VBOXOSTYPE_Ubuntu15_x64 = 0x5C10b,
+ VBOXOSTYPE_Ubuntu16_LTS = 0x5C00c,
+ VBOXOSTYPE_Ubuntu16_LTS_x64 = 0x5C10c,
+ VBOXOSTYPE_Ubuntu16 = 0x5C00d,
+ VBOXOSTYPE_Ubuntu16_x64 = 0x5C10d,
+ VBOXOSTYPE_Ubuntu17 = 0x5C00e,
+ VBOXOSTYPE_Ubuntu17_x64 = 0x5C10e,
+ VBOXOSTYPE_Ubuntu18_LTS = 0x5C00f,
+ VBOXOSTYPE_Ubuntu18_LTS_x64 = 0x5C10f,
+ VBOXOSTYPE_Ubuntu18 = 0x5C010,
+ VBOXOSTYPE_Ubuntu18_x64 = 0x5C110,
+ VBOXOSTYPE_Ubuntu19 = 0x5C011,
+ VBOXOSTYPE_Ubuntu19_x64 = 0x5C111,
+ VBOXOSTYPE_Ubuntu20_LTS_x64 = 0x5C112, // 64-bit only
+ VBOXOSTYPE_Ubuntu20_x64 = 0x5C113, // 64-bit only
+ VBOXOSTYPE_Ubuntu21_x64 = 0x5C114, // 64-bit only
+ VBOXOSTYPE_Ubuntu22_LTS_x64 = 0x5C115, // 64-bit only
+ VBOXOSTYPE_Ubuntu22_x64 = 0x5C116, // 64-bit only
+ VBOXOSTYPE_Ubuntu_latest_x64 = VBOXOSTYPE_Ubuntu22_x64,
+ VBOXOSTYPE_Xandros = 0x5D000,
+ VBOXOSTYPE_Xandros_x64 = 0x5D100,
+ VBOXOSTYPE_Oracle = 0x5E000,
+ VBOXOSTYPE_Oracle_x64 = 0x5E100,
+ VBOXOSTYPE_Oracle4 = 0x5E001,
+ VBOXOSTYPE_Oracle4_x64 = 0x5E101,
+ VBOXOSTYPE_Oracle5 = 0x5E002,
+ VBOXOSTYPE_Oracle5_x64 = 0x5E102,
+ VBOXOSTYPE_Oracle6 = 0x5E003,
+ VBOXOSTYPE_Oracle6_x64 = 0x5E103,
+ VBOXOSTYPE_Oracle7_x64 = 0x5E104, // 64-bit only
+ VBOXOSTYPE_Oracle8_x64 = 0x5E105, // 64-bit only
+ VBOXOSTYPE_Oracle9_x64 = 0x5E106, // 64-bit only
+ VBOXOSTYPE_Oracle_latest_x64 = VBOXOSTYPE_Oracle9_x64,
+ 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, // Solaris 10U7 (5/09) and earlier
+ VBOXOSTYPE_Solaris_x64 = 0x80100, // Solaris 10U7 (5/09) and earlier
+ VBOXOSTYPE_Solaris10U8_or_later = 0x80001,
+ VBOXOSTYPE_Solaris10U8_or_later_x64 = 0x80101,
+ 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,
+ /** @} */
+ /** @name Other OSes and stuff
+ * @{ */
+ VBOXOSTYPE_JRockitVE = 0xC0000,
+ VBOXOSTYPE_Haiku = 0xD0000,
+ VBOXOSTYPE_Haiku_x64 = 0xD0100,
+ VBOXOSTYPE_VBoxBS_x64 = 0xE0100,
+ /** @} */
+
+ /** OS type mask. */
+ VBOXOSTYPE_OsTypeMask = 0x00fff000,
+
+ /** @name Architecture Type
+ * @{ */
+ /** Mask containing the architecture value. */
+ VBOXOSTYPE_ArchitectureMask = 0x00f00,
+ /** Architecture value for 16-bit and 32-bit x86. */
+ VBOXOSTYPE_x86 = 0x00000,
+ /** Architecture value for 64-bit x86 (AMD64). */
+ VBOXOSTYPE_x64 = 0x00100,
+ /** Architecture value for 32-bit ARM. */
+ VBOXOSTYPE_arm32 = 0x00200,
+ /** Architecture value for 64-bit ARM. */
+ VBOXOSTYPE_arm64 = 0x00300,
+ /** Architecture value for unknown or unsupported architectures. */
+ VBOXOSTYPE_UnknownArch = 0x00f00,
+ /** @} */
+
+ /** 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 /* !VBOX_INCLUDED_ostypes_h */
diff --git a/include/VBox/param.h b/include/VBox/param.h
new file mode 100644
index 00000000..fb6e5ddc
--- /dev/null
+++ b/include/VBox/param.h
@@ -0,0 +1,229 @@
+/** @file
+ * VirtualBox Parameter Definitions. (VMM,+)
+ *
+ * param.mac is generated from this file by running 'kmk incs' in the root.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_param_h
+#define VBOX_INCLUDED_param_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/param.h>
+#include <iprt/cdefs.h>
+
+
+/** @defgroup grp_vbox_param VBox Parameter Definition
+ * @{
+ */
+
+/** The guest page size (x86). */
+#define GUEST_PAGE_SIZE 0x1000
+/** The guest page offset mask (x86).
+ * @note If one-complementing this, always put a typecast after the operator! */
+#define GUEST_PAGE_OFFSET_MASK 0xfff
+/** The guest page shift (x86). */
+#define GUEST_PAGE_SHIFT 12
+
+/** Host page size. */
+#define HOST_PAGE_SIZE PAGE_SIZE
+/** Host page offset mask.
+ * @note If one-complementing this, always put a typecast after the operator! */
+#define HOST_PAGE_OFFSET_MASK PAGE_OFFSET_MASK
+/** Host page shift. */
+#define HOST_PAGE_SHIFT PAGE_SHIFT
+
+
+/** 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_pdm Pluggable Device Manager Parameters
+ * @{
+ */
+/** Max number of network shaper groups. */
+#define PDM_NET_SHAPER_MAX_GROUPS 32
+/** Max length of a network shaper group name (excluding terminator). */
+#define PDM_NET_SHAPER_MAX_NAME_LEN 63
+/** @} */
+
+
+/** @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 /* !VBOX_INCLUDED_param_h */
+
diff --git a/include/VBox/param.mac b/include/VBox/param.mac
new file mode 100644
index 00000000..b35a5f45
--- /dev/null
+++ b/include/VBox/param.mac
@@ -0,0 +1,98 @@
+;; @file
+; VirtualBox Parameter Definitions. (VMM,+)
+;
+; Automatically generated by various.sed. DO NOT EDIT!
+;
+
+;
+; Copyright (C) 2006-2022 Oracle and/or its affiliates.
+;
+; This file is part of VirtualBox base platform packages, as
+; available from https://www.virtualbox.org.
+;
+; This program is free software; you can redistribute it and/or
+; modify it under the terms of the GNU General Public License
+; as published by the Free Software Foundation, in version 3 of the
+; License.
+;
+; This program is distributed in the hope that it will be useful, but
+; WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with this program; if not, see <https://www.gnu.org/licenses>.
+;
+; The contents of this file may alternatively be used under the terms
+; of the Common Development and Distribution License Version 1.0
+; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+; in the VirtualBox 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.
+;
+; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+;
+
+%ifndef VBOX_INCLUDED_param_h
+%define VBOX_INCLUDED_param_h
+%ifndef RT_WITHOUT_PRAGMA_ONCE
+%endif
+%define GUEST_PAGE_SIZE 0x1000
+%define GUEST_PAGE_OFFSET_MASK 0xfff
+%define GUEST_PAGE_SHIFT 12
+%define HOST_PAGE_SIZE PAGE_SIZE
+%define HOST_PAGE_OFFSET_MASK PAGE_OFFSET_MASK
+%define HOST_PAGE_SHIFT PAGE_SHIFT
+%if ARCH_BITS == 64
+ %define VBOX_MAX_ALLOC_PAGE_COUNT (_512M / PAGE_SIZE)
+%else
+ %define VBOX_MAX_ALLOC_PAGE_COUNT (_256M / PAGE_SIZE)
+%endif
+%define MM_HYPER_AREA_ADDRESS 0xa0000000
+%define MM_HYPER_AREA_MAX_SIZE (40U * _1M)
+%define MM_HYPER_DYNAMIC_SIZE (16U * PAGE_SIZE)
+%define MM_RAM_MIN 0x00400000
+%if HC_ARCH_BITS == 64
+ %define MM_RAM_MAX 0x20000000000
+%else
+ %define MM_RAM_MAX 0x000E0000000
+%endif
+%define MM_RAM_MIN_IN_MB 4
+%if HC_ARCH_BITS == 64
+ %define MM_RAM_MAX_IN_MB 2097152
+%else
+ %define MM_RAM_MAX_IN_MB 3584
+%endif
+%define MM_RAM_HOLE_SIZE_DEFAULT (512U * _1M)
+%if HC_ARCH_BITS == 64
+ %define MM_MMIO_64_MAX _1T
+%else
+ %define MM_MMIO_64_MAX (_1G64 * 16)
+%endif
+%define MM_MMIO_32_MAX _2G
+%define PDM_NET_SHAPER_MAX_GROUPS 32
+%define PDM_NET_SHAPER_MAX_NAME_LEN 63
+%define PGM_HANDY_PAGES 128
+%define PGM_HANDY_PAGES_SET_FF 32
+%define PGM_HANDY_PAGES_R3_ALLOC 8
+%define PGM_HANDY_PAGES_RZ_ALLOC 8
+%define PGM_HANDY_PAGES_RZ_TO_R3 24
+%define PGM_HANDY_PAGES_MIN 32
+%ifdef RT_OS_DARWIN
+ %define VMM_STACK_SIZE 16384
+%else
+ %define VMM_STACK_SIZE 8192
+%endif
+%define VMM_MIN_CPU_COUNT 1
+%define VMM_MAX_CPU_COUNT 64
+%define VBOX_PCI_VENDORID (0x80ee)
+%define VBOX_VENDORID VBOX_PCI_VENDORID
+%define VBOX_DEVICEID (0xbeef)
+%define VBOX_VESA_VENDORID VBOX_PCI_VENDORID
+%define VBOX_VESA_DEVICEID (0xbeef)
+%define VMMDEV_VENDORID VBOX_PCI_VENDORID
+%define VMMDEV_DEVICEID (0xcafe)
+%define VBOX_MAX_GSO_SIZE 0xfff0
+%endif
diff --git a/include/VBox/pci.h b/include/VBox/pci.h
new file mode 100644
index 00000000..8d5054fe
--- /dev/null
+++ b/include/VBox/pci.h
@@ -0,0 +1,827 @@
+/** @file
+ * PCI - The PCI Controller And Devices Constants. (DEV)
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_pci_h
+#define VBOX_INCLUDED_pci_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/cdefs.h>
+#include <VBox/types.h>
+#include <iprt/assert.h>
+
+/** @defgroup grp_pci PCI - The PCI Controller.
+ * @ingroup grp_devdrv
+ * @{
+ */
+
+/** @name PCI device classes.
+ * @{ */
+#define VBOX_PCI_CLASS_UNCLASSIFIED 0x00
+#define VBOX_PCI_CLASS_MASS_STORAGE 0x01
+#define VBOX_PCI_CLASS_NETWORK 0x02
+#define VBOX_PCI_CLASS_DISPLAY 0x03
+#define VBOX_PCI_CLASS_MULTI_MEDIA 0x04
+#define VBOX_PCI_CLASS_MEMORY 0x05
+#define VBOX_PCI_CLASS_BRIDGE 0x06
+#define VBOX_PCI_CLASS_COMM 0x07
+#define VBOX_PCI_CLASS_SYSTEM 0x08
+#define VBOX_PCI_CLASS_INPUT 0x09
+#define VBOX_PCI_CLASS_DOCKING_STATION 0x0a
+#define VBOX_PCI_CLASS_PROCESSOR 0x0b
+#define VBOX_PCI_CLASS_SERIAL_BUS 0x0c
+#define VBOX_PCI_CLASS_WIRELESS 0x0d
+#define VBOX_PCI_CLASS_INTELLIGENT 0x0e
+#define VBOX_PCI_CLASS_SAT_COMM 0x0f
+#define VBOX_PCI_CLASS_ENCRYPTION 0x10
+#define VBOX_PCI_CLASS_SIG_PROC 0x11
+#define VBOX_PCI_CLASS_PROC_ACCEL 0x12
+#define VBOX_PCI_CLASS_NON_ESS_INSTR 0x13
+#define VBOX_PCI_CLASS_CO_PROCESSOR 0x40
+#define VBOX_PCI_CLASS_UNASSIGNED 0xff
+/** @} */
+
+/** @name PCI device sub-classes.
+ * @{ */
+#define VBOX_PCI_SUB_UNCLASSIFIED_NON_VGA 0x00
+#define VBOX_PCI_SUB_UNCLASSIFIED_VGA 0x01
+
+#define VBOX_PCI_SUB_MASS_STORAGE_SCSI_BUS 0x00
+#define VBOX_PCI_SUB_MASS_STORAGE_IDE 0x01
+#define VBOX_PCI_SUB_MASS_STORAGE_FLOPPY 0x02
+#define VBOX_PCI_SUB_MASS_STORAGE_IPI_BUS 0x03
+#define VBOX_PCI_SUB_MASS_STORAGE_RAID 0x04
+#define VBOX_PCI_SUB_MASS_STORAGE_ATA 0x05
+#define VBOX_PCI_SUB_MASS_STORAGE_SATA 0x06
+#define VBOX_PCI_SUB_MASS_STORAGE_SCSI 0x07
+#define VBOX_PCI_SUB_MASS_STORAGE_NVME 0x08
+#define VBOX_PCI_SUB_MASS_STORAGE_OTHER 0x80
+
+#define VBOX_PCI_SUB_NETWORK_ETHERNET 0x00
+#define VBOX_PCI_SUB_NETWORK_TOKEN_RING 0x01
+#define VBOX_PCI_SUB_NETWORK_FDDI 0x02
+#define VBOX_PCI_SUB_NETWORK_ATM 0x03
+#define VBOX_PCI_SUB_NETWORK_ISDN 0x04
+#define VBOX_PCI_SUB_NETWORK_WORLD_FIP 0x05
+#define VBOX_PCI_SUB_NETWORK_PICMG 0x06
+#define VBOX_PCI_SUB_NETWORK_INFINIBAND 0x07
+#define VBOX_PCI_SUB_NETWORK_FABRIC 0x08
+#define VBOX_PCI_SUB_NETWORK_OTHER 0x80
+
+#define VBOX_PCI_SUB_DISPLAY_VGA 0x00
+#define VBOX_PCI_SUB_DISPLAY_XGA 0x01
+#define VBOX_PCI_SUB_DISPLAY_3D 0x02
+#define VBOX_PCI_SUB_DISPLAY_OTHER 0x80
+
+#define VBOX_PCI_SUB_MULTI_MEDIA_MM_VIDEO 0x00
+#define VBOX_PCI_SUB_MULTI_MEDIA_MM_AUDIO 0x01
+#define VBOX_PCI_SUB_MULTI_MEDIA_TELE 0x02
+#define VBOX_PCI_SUB_MULTI_MEDIA_AUDIO 0x03
+#define VBOX_PCI_SUB_MULTI_MEDIA_OTHER 0x80
+
+#define VBOX_PCI_SUB_MEMORY_RAM 0x00
+#define VBOX_PCI_SUB_MEMORY_FLASH 0x01
+#define VBOX_PCI_SUB_MEMORY_OTHER 0x80
+
+#define VBOX_PCI_SUB_BRIDGE_HOST 0x00
+#define VBOX_PCI_SUB_BRIDGE_ISA 0x01
+#define VBOX_PCI_SUB_BRIDGE_EISA 0x02
+#define VBOX_PCI_SUB_BRIDGE_MCA 0x03
+#define VBOX_PCI_SUB_BRIDGE_PCI 0x04
+#define VBOX_PCI_SUB_BRIDGE_PCMCIA 0x05
+#define VBOX_PCI_SUB_BRIDGE_NUBUS 0x06
+#define VBOX_PCI_SUB_BRIDGE_CARDBUS 0x07
+#define VBOX_PCI_SUB_BRIDGE_RACEWAY 0x08
+#define VBOX_PCI_SUB_BRIDGE_SEMI_PCI 0x09
+#define VBOX_PCI_SUB_BRIDGE_INFINIBAND_PCI 0x0a
+#define VBOX_PCI_SUB_BRIDGE_OTHER 0x80
+
+#define VBOX_PCI_SUB_COMM_SERIAL 0x00
+#define VBOX_PCI_SUB_COMM_PARALLEL 0x01
+#define VBOX_PCI_SUB_COMM_MULTIPORT_SERIAL 0x02
+#define VBOX_PCI_SUB_COMM_MODEM 0x03
+#define VBOX_PCI_SUB_COMM_GBIP 0x04
+#define VBOX_PCI_SUB_COMM_SMART_CARD 0x05
+#define VBOX_PCI_SUB_COMM_OTHER 0x80
+
+#define VBOX_PCI_SUB_SYSTEM_PIC 0x00
+#define VBOX_PCI_SUB_SYSTEM_DMA 0x01
+#define VBOX_PCI_SUB_SYSTEM_TIMER 0x02
+#define VBOX_PCI_SUB_SYSTEM_RTC 0x03
+#define VBOX_PCI_SUB_SYSTEM_PCI_HOTPLUG 0x04
+#define VBOX_PCI_SUB_SYSTEM_SD_HOST 0x05
+#define VBOX_PCI_SUB_SYSTEM_IOMMU 0x06
+#define VBOX_PCI_SUB_SYSTEM_OTHER 0x80
+
+#define VBOX_PCI_SUB_INPUT_KEYBOARD 0x00
+#define VBOX_PCI_SUB_INPUT_PEN 0x01
+#define VBOX_PCI_SUB_INPUT_MOUSE 0x02
+#define VBOX_PCI_SUB_INPUT_SCANNER 0x03
+#define VBOX_PCI_SUB_INPUT_GAMEPORT 0x04
+#define VBOX_PCI_SUB_INPUT_OTHER 0x80
+
+#define VBOX_PCI_SUB_DOCKING_ST_GENERIC 0x00
+#define VBOX_PCI_SUB_DOCKING_ST_OTHER 0x80
+
+#define VBOX_PCI_SUB_PROCESSOR_386 0x00
+#define VBOX_PCI_SUB_PROCESSOR_486 0x01
+#define VBOX_PCI_SUB_PROCESSOR_PENTIUM 0x02
+#define VBOX_PCI_SUB_PROCESSOR_PENTIUM_PRO 0x03
+#define VBOX_PCI_SUB_PROCESSOR_ALPHA 0x10
+#define VBOX_PCI_SUB_PROCESSOR_POWERPC 0x20
+#define VBOX_PCI_SUB_PROCESSOR_MIPS 0x30
+#define VBOX_PCI_SUB_PROCESSOR_CO_PROC 0x40
+#define VBOX_PCI_SUB_PROCESSOR_OTHER 0x80
+
+#define VBOX_PCI_SUB_SERIAL_BUS_FIREWIRE 0x00
+#define VBOX_PCI_SUB_SERIAL_BUS_ACCESS 0x01
+#define VBOX_PCI_SUB_SERIAL_BUS_SSA 0x02
+#define VBOX_PCI_SUB_SERIAL_BUS_USB 0x03
+#define VBOX_PCI_SUB_SERIAL_BUS_FIBRE 0x04
+#define VBOX_PCI_SUB_SERIAL_BUS_SMBUS 0x05
+#define VBOX_PCI_SUB_SERIAL_BUS_INFINIBAND 0x06
+#define VBOX_PCI_SUB_SERIAL_BUS_IPMI 0x07
+#define VBOX_PCI_SUB_SERIAL_BUS_SERCOS 0x08
+#define VBOX_PCI_SUB_SERIAL_BUS_CANBUS 0x09
+#define VBOX_PCI_SUB_SERIAL_BUS_OTHER 0x80
+
+#define VBOX_PCI_SUB_WIRELESS_IRDA 0x00
+#define VBOX_PCI_SUB_WIRELESS_IR 0x01
+#define VBOX_PCI_SUB_WIRELESS_RF 0x10
+#define VBOX_PCI_SUB_WIRELESS_BLUETOOTH 0x11
+#define VBOX_PCI_SUB_WIRELESS_BROADBAND 0x12
+#define VBOX_PCI_SUB_WIRELESS_ETH_8021A 0x20
+#define VBOX_PCI_SUB_WIRELESS_ETH_8021B 0x21
+#define VBOX_PCI_SUB_WIRELESS_OTHER 0x80
+
+#define VBOX_PCI_SUB_INTELLIGENT_I20 0x00
+
+#define VBOX_PCI_SUB_SAT_COMM_TV 0x01
+#define VBOX_PCI_SUB_SAT_COMM_AUDIO 0x02
+#define VBOX_PCI_SUB_SAT_COMM_VOICE 0x03
+#define VBOX_PCI_SUB_SAT_COMM_DATA 0x04
+
+#define VBOX_PCI_SUB_ENCRYPT_NETWORK 0x00
+#define VBOX_PCI_SUB_ENCRYPT_ENTERTAINMENT 0x01
+#define VBOX_PCI_SUB_ENCRYPT_OTHER 0x80
+
+#define VBOX_PCI_SUB_SIG_PROC_DPIO 0x00
+#define VBOX_PCI_SUB_SIG_PROC_PERF_COUNTERS 0x01
+#define VBOX_PCI_SUB_SIG_PROC_COMM_SYNC 0x10
+#define VBOX_PCI_SUB_SIG_PROC_MANAGEMENT 0x20
+#define VBOX_PCI_SUB_SIG_PROC_OTHER 0x80
+/** @} */
+
+/**
+ * PCI configuration word 4 (command) and word 6 (status).
+ */
+typedef enum PCICONFIGCOMMAND
+{
+ /** Supports/uses memory accesses. */
+ PCI_COMMAND_IOACCESS = 0x0001,
+ PCI_COMMAND_MEMACCESS = 0x0002,
+ PCI_COMMAND_BUSMASTER = 0x0004
+} PCICONFIGCOMMAND;
+
+
+/**
+ * PCI Address space specification.
+ * This is used when registering a I/O region.
+ */
+/**
+ * Defined by the PCI specification.
+ */
+typedef enum PCIADDRESSSPACE
+{
+ /** Memory. */
+ PCI_ADDRESS_SPACE_MEM = 0x00,
+ /** I/O space. */
+ PCI_ADDRESS_SPACE_IO = 0x01,
+ /** 32-bit BAR. */
+ PCI_ADDRESS_SPACE_BAR32 = 0x00,
+ /** 64-bit BAR. */
+ PCI_ADDRESS_SPACE_BAR64 = 0x04,
+ /** Prefetch memory. */
+ PCI_ADDRESS_SPACE_MEM_PREFETCH = 0x08
+} PCIADDRESSSPACE;
+
+
+/**
+ * PCI Memory Request with Address Type.
+ * In accordance with the PCI ATS spec.
+ * See PCI ATS spec. 2.1."Memory Requests with Address Type".
+ */
+typedef enum PCIADDRTYPE
+{
+ /** Untranslated request. */
+ PCIADDRTYPE_UNTRANSLATED = 0x0,
+ /** Translation request. */
+ PCIADDRTYPE_TRANSLATION,
+ /** Translated requested. */
+ PCIADDRTYPE_TRANSLATED,
+ /** Reserved. */
+ PCIADDRTYPE_RSVD
+} PCIADDRTYPE;
+
+
+/** @name PCI Configuration Space Registers
+ * @{ */
+/* Commented out values common for different header types */
+/* Common part of the header */
+#define VBOX_PCI_VENDOR_ID 0x00 /**< 16-bit RO */
+#define VBOX_PCI_DEVICE_ID 0x02 /**< 16-bit RO */
+#define VBOX_PCI_COMMAND 0x04 /**< 16-bit RW, some bits RO */
+#define VBOX_PCI_STATUS 0x06 /**< 16-bit RW, some bits RO */
+#define VBOX_PCI_REVISION_ID 0x08 /**< 8-bit RO - - device revision */
+#define VBOX_PCI_CLASS_PROG 0x09 /**< 8-bit RO - - register-level programming class code (device specific). */
+#define VBOX_PCI_CLASS_SUB 0x0a /**< 8-bit RO - - sub-class code. */
+#define VBOX_PCI_CLASS_DEVICE VBOX_PCI_CLASS_SUB
+#define VBOX_PCI_CLASS_BASE 0x0b /**< 8-bit RO - - base class code. */
+#define VBOX_PCI_CACHE_LINE_SIZE 0x0c /**< 8-bit RW - - system cache line size */
+#define VBOX_PCI_LATENCY_TIMER 0x0d /**< 8-bit RW - - master latency timer, hardwired to 0 for PCIe */
+#define VBOX_PCI_HEADER_TYPE 0x0e /**< 8-bit RO - - header type (0 - device, 1 - bridge, 2 - CardBus bridge) */
+#define VBOX_PCI_BIST 0x0f /**< 8-bit RW - - built-in self test control */
+#define VBOX_PCI_CAPABILITY_LIST 0x34 /**< 8-bit RO? - - linked list of new capabilities implemented by the device, 2 bottom bits reserved */
+#define VBOX_PCI_INTERRUPT_LINE 0x3c /**< 8-bit RW - - interrupt line. */
+#define VBOX_PCI_INTERRUPT_PIN 0x3d /**< 8-bit RO - - interrupt pin. */
+
+/* Type 0 header, device */
+#define VBOX_PCI_BASE_ADDRESS_0 0x10 /**< 32-bit RW */
+#define VBOX_PCI_BASE_ADDRESS_1 0x14 /**< 32-bit RW */
+#define VBOX_PCI_BASE_ADDRESS_2 0x18 /**< 32-bit RW */
+#define VBOX_PCI_BASE_ADDRESS_3 0x1c /**< 32-bit RW */
+#define VBOX_PCI_BASE_ADDRESS_4 0x20 /**< 32-bit RW */
+#define VBOX_PCI_BASE_ADDRESS_5 0x24 /**< 32-bit RW */
+#define VBOX_PCI_CARDBUS_CIS 0x28 /**< 32-bit ?? */
+#define VBOX_PCI_SUBSYSTEM_VENDOR_ID 0x2c /**< 16-bit RO */
+#define VBOX_PCI_SUBSYSTEM_ID 0x2e /**< 16-bit RO */
+#define VBOX_PCI_ROM_ADDRESS 0x30 /**< 32-bit ?? */
+/* #define VBOX_PCI_CAPABILITY_LIST 0x34 */ /**< 8-bit? ?? */
+#define VBOX_PCI_RESERVED_35 0x35 /**< 8-bit ?? - - reserved */
+#define VBOX_PCI_RESERVED_36 0x36 /**< 8-bit ?? - - reserved */
+#define VBOX_PCI_RESERVED_37 0x37 /**< 8-bit ?? - - reserved */
+#define VBOX_PCI_RESERVED_38 0x38 /**< 32-bit ?? - - reserved */
+/* #define VBOX_PCI_INTERRUPT_LINE 0x3c */ /**< 8-bit RW - - interrupt line. */
+/* #define VBOX_PCI_INTERRUPT_PIN 0x3d */ /**< 8-bit RO - - interrupt pin. */
+#define VBOX_PCI_MIN_GNT 0x3e /**< 8-bit RO - - burst period length (in 1/4 microsecond units) */
+#define VBOX_PCI_MAX_LAT 0x3f /**< 8-bit RO - - how often the device needs access to the PCI bus (in 1/4 microsecond units) */
+
+/* Type 1 header, PCI-to-PCI bridge */
+/* #define VBOX_PCI_BASE_ADDRESS_0 0x10 */ /**< 32-bit RW */
+/* #define VBOX_PCI_BASE_ADDRESS_1 0x14 */ /**< 32-bit RW */
+#define VBOX_PCI_PRIMARY_BUS 0x18 /**< 8-bit ?? - - primary bus number. */
+#define VBOX_PCI_SECONDARY_BUS 0x19 /**< 8-bit ?? - - secondary bus number. */
+#define VBOX_PCI_SUBORDINATE_BUS 0x1a /**< 8-bit ?? - - highest subordinate bus number. (behind the bridge) */
+#define VBOX_PCI_SEC_LATENCY_TIMER 0x1b /**< 8-bit ?? - - secondary latency timer. */
+#define VBOX_PCI_IO_BASE 0x1c /**< 8-bit ?? - - I/O range base. */
+#define VBOX_PCI_IO_LIMIT 0x1d /**< 8-bit ?? - - I/O range limit. */
+#define VBOX_PCI_SEC_STATUS 0x1e /**< 16-bit ?? - - secondary status register. */
+#define VBOX_PCI_MEMORY_BASE 0x20 /**< 16-bit ?? - - memory range base. */
+#define VBOX_PCI_MEMORY_LIMIT 0x22 /**< 16-bit ?? - - memory range limit. */
+#define VBOX_PCI_PREF_MEMORY_BASE 0x24 /**< 16-bit ?? - - prefetchable memory range base. */
+#define VBOX_PCI_PREF_MEMORY_LIMIT 0x26 /**< 16-bit ?? - - prefetchable memory range limit. */
+#define VBOX_PCI_PREF_BASE_UPPER32 0x28 /**< 32-bit ?? - - prefetchable memory range high base.*/
+#define VBOX_PCI_PREF_LIMIT_UPPER32 0x2c /**< 32-bit ?? - - prefetchable memory range high limit. */
+#define VBOX_PCI_IO_BASE_UPPER16 0x30 /**< 16-bit ?? - - memory range high base. */
+#define VBOX_PCI_IO_LIMIT_UPPER16 0x32 /**< 16-bit ?? - - memory range high limit. */
+/* #define VBOX_PCI_CAPABILITY_LIST 0x34 */ /**< 8-bit? ?? */
+/* #define VBOX_PCI_RESERVED_35 0x35 */ /**< 8-bit ?? - - reserved */
+/* #define VBOX_PCI_RESERVED_36 0x36 */ /**< 8-bit ?? - - reserved */
+/* #define VBOX_PCI_RESERVED_37 0x37 */ /**< 8-bit ?? - - reserved */
+#define VBOX_PCI_ROM_ADDRESS_BR 0x38 /**< 32-bit ?? - - expansion ROM base address */
+#define VBOX_PCI_BRIDGE_CONTROL 0x3e /**< 16-bit? ?? - - bridge control */
+
+/* Type 2 header, PCI-to-CardBus bridge */
+#define VBOX_PCI_CARDBUS_BASE_ADDRESS 0x10 /**< 32-bit RW - - CardBus Socket/ExCa base address */
+#define VBOX_PCI_CARDBUS_CAPLIST 0x14 /**< 8-bit RO? - - offset of capabilities list */
+#define VBOX_PCI_CARDBUS_RESERVED_15 0x15 /**< 8-bit ?? - - reserved */
+#define VBOX_PCI_CARDBUS_SEC_STATUS 0x16 /**< 16-bit ?? - - secondary status */
+#define VBOX_PCI_CARDBUS_PCIBUS_NUMBER 0x18 /**< 8-bit ?? - - PCI bus number */
+#define VBOX_PCI_CARDBUS_CARDBUS_NUMBER 0x19 /**< 8-bit ?? - - CardBus bus number */
+/* #define VBOX_PCI_SUBORDINATE_BUS 0x1a */ /**< 8-bit ?? - - highest subordinate bus number. (behind the bridge) */
+/* #define VBOX_PCI_SEC_LATENCY_TIMER 0x1b */ /**< 8-bit ?? - - secondary latency timer. */
+#define VBOX_PCI_CARDBUS_MEMORY_BASE0 0x1c /**< 32-bit RW - - memory base address 0 */
+#define VBOX_PCI_CARDBUS_MEMORY_LIMIT0 0x20 /**< 32-bit RW - - memory limit 0 */
+#define VBOX_PCI_CARDBUS_MEMORY_BASE1 0x24 /**< 32-bit RW - - memory base address 1 */
+#define VBOX_PCI_CARDBUS_MEMORY_LIMIT1 0x28 /**< 32-bit RW - - memory limit 1 */
+#define VBOX_PCI_CARDBUS_IO_BASE0 0x2c /**< 32-bit RW - - IO base address 0 */
+#define VBOX_PCI_CARDBUS_IO_LIMIT0 0x30 /**< 32-bit RW - - IO limit 0 */
+#define VBOX_PCI_CARDBUS_IO_BASE1 0x34 /**< 32-bit RW - - IO base address 1 */
+#define VBOX_PCI_CARDBUS_IO_LIMIT1 0x38 /**< 32-bit RW - - IO limit 1 */
+/* #define VBOX_PCI_INTERRUPT_LINE 0x3c */ /**< 8-bit RW - - interrupt line. */
+/* #define VBOX_PCI_INTERRUPT_PIN 0x3d */ /**< 8-bit RO - - interrupt pin. */
+/* #define VBOX_PCI_BRIDGE_CONTROL 0x3e */ /**< 16-bit? ?? - - bridge control */
+/** @} */
+
+
+/* Possible values in status bitmask */
+#define VBOX_PCI_STATUS_CAP_LIST 0x10 /* Support Capability List */
+#define VBOX_PCI_STATUS_66MHZ 0x20 /* Support 66 Mhz PCI 2.1 bus */
+#define VBOX_PCI_STATUS_UDF 0x40 /* Support User Definable Features [obsolete] */
+#define VBOX_PCI_STATUS_FAST_BACK 0x80 /* Accept fast-back to back */
+#define VBOX_PCI_STATUS_PARITY 0x100 /* Detected parity error */
+#define VBOX_PCI_STATUS_DEVSEL_MASK 0x600 /* DEVSEL timing */
+#define VBOX_PCI_STATUS_DEVSEL_FAST 0x000
+#define VBOX_PCI_STATUS_DEVSEL_MEDIUM 0x200
+#define VBOX_PCI_STATUS_DEVSEL_SLOW 0x400
+#define VBOX_PCI_STATUS_SIG_TARGET_ABORT 0x800 /* Set on target abort */
+#define VBOX_PCI_STATUS_REC_TARGET_ABORT 0x1000 /* Master ack of " */
+#define VBOX_PCI_STATUS_REC_MASTER_ABORT 0x2000 /* Set on master abort */
+#define VBOX_PCI_STATUS_SIG_SYSTEM_ERROR 0x4000 /* Set when we drive SERR */
+#define VBOX_PCI_STATUS_DETECTED_PARITY 0x8000 /* Set on parity error */
+
+
+/* Command bitmask */
+#define VBOX_PCI_COMMAND_IO 0x1 /* Enable response in I/O space */
+#define VBOX_PCI_COMMAND_MEMORY 0x2 /* Enable response in Memory space */
+#define VBOX_PCI_COMMAND_MASTER 0x4 /* Enable bus mastering */
+#define VBOX_PCI_COMMAND_SPECIAL 0x8 /* Enable response to special cycles */
+#define VBOX_PCI_COMMAND_INVALIDATE 0x10 /* Use memory write and invalidate */
+#define VBOX_PCI_COMMAND_VGA_PALETTE 0x20 /* Enable palette snooping */
+#define VBOX_PCI_COMMAND_PARITY 0x40 /* Enable parity checking */
+#define VBOX_PCI_COMMAND_WAIT 0x80 /* Enable address/data stepping */
+#define VBOX_PCI_COMMAND_SERR 0x100 /* Enable SERR */
+#define VBOX_PCI_COMMAND_FAST_BACK 0x200 /* Enable back-to-back writes */
+#define VBOX_PCI_COMMAND_INTX_DISABLE 0x400 /* INTx Emulation Disable */
+
+
+/* Capability list values (capability offset 0) */
+/* Next value pointer in offset 1, or 0 if none */
+#define VBOX_PCI_CAP_ID_PM 0x01 /* Power Management */
+#define VBOX_PCI_CAP_ID_AGP 0x02 /* Accelerated Graphics Port */
+#define VBOX_PCI_CAP_ID_VPD 0x03 /* Vital Product Data */
+#define VBOX_PCI_CAP_ID_SLOTID 0x04 /* Slot Identification */
+#define VBOX_PCI_CAP_ID_MSI 0x05 /* Message Signalled Interrupts */
+#define VBOX_PCI_CAP_ID_CHSWP 0x06 /* CompactPCI HotSwap */
+#define VBOX_PCI_CAP_ID_PCIX 0x07 /* PCI-X */
+#define VBOX_PCI_CAP_ID_HT 0x08 /* HyperTransport */
+#define VBOX_PCI_CAP_ID_VNDR 0x09 /* Vendor specific */
+#define VBOX_PCI_CAP_ID_DBG 0x0A /* Debug port */
+#define VBOX_PCI_CAP_ID_CCRC 0x0B /* CompactPCI Central Resource Control */
+#define VBOX_PCI_CAP_ID_SHPC 0x0C /* PCI Standard Hot-Plug Controller */
+#define VBOX_PCI_CAP_ID_SSVID 0x0D /* Bridge subsystem vendor/device ID */
+#define VBOX_PCI_CAP_ID_AGP3 0x0E /* AGP Target PCI-PCI bridge */
+#define VBOX_PCI_CAP_ID_SECURE 0x0F /* Secure device (?) */
+#define VBOX_PCI_CAP_ID_EXP 0x10 /* PCI Express */
+#define VBOX_PCI_CAP_ID_MSIX 0x11 /* MSI-X */
+#define VBOX_PCI_CAP_ID_SATA 0x12 /* Serial-ATA HBA */
+#define VBOX_PCI_CAP_ID_AF 0x13 /* PCI Advanced Features */
+
+/* Extended Capabilities (PCI-X 2.0 and Express), start at 0x100, next - bits [20..32] */
+#define VBOX_PCI_EXT_CAP_ID_ERR 0x01 /* Advanced Error Reporting */
+#define VBOX_PCI_EXT_CAP_ID_VC 0x02 /* Virtual Channel */
+#define VBOX_PCI_EXT_CAP_ID_DSN 0x03 /* Device Serial Number */
+#define VBOX_PCI_EXT_CAP_ID_PWR 0x04 /* Power Budgeting */
+#define VBOX_PCI_EXT_CAP_ID_RCLINK 0x05 /* Root Complex Link Declaration */
+#define VBOX_PCI_EXT_CAP_ID_RCILINK 0x06 /* Root Complex Internal Link Declaration */
+#define VBOX_PCI_EXT_CAP_ID_RCECOLL 0x07 /* Root Complex Event Collector */
+#define VBOX_PCI_EXT_CAP_ID_MFVC 0x08 /* Multi-Function Virtual Channel */
+#define VBOX_PCI_EXT_CAP_ID_RBCB 0x0a /* Root Bridge Control Block */
+#define VBOX_PCI_EXT_CAP_ID_VNDR 0x0b /* Vendor specific */
+#define VBOX_PCI_EXT_CAP_ID_ACS 0x0d /* Access Controls */
+#define VBOX_PCI_EXT_CAP_ID_ARI 0x0e
+#define VBOX_PCI_EXT_CAP_ID_ATS 0x0f
+#define VBOX_PCI_EXT_CAP_ID_SRIOV 0x10
+
+
+/* MSI flags, aka Message Control (2 bytes, capability offset 2) */
+#define VBOX_PCI_MSI_FLAGS_ENABLE 0x0001 /* MSI feature enabled */
+#define VBOX_PCI_MSI_FLAGS_64BIT 0x0080 /* 64-bit addresses allowed */
+#define VBOX_PCI_MSI_FLAGS_MASKBIT 0x0100 /* Per-vector masking support */
+/* Encoding for 3-bit patterns for message queue (per chapter 6.8.1 of PCI spec),
+ someone very similar to log_2().
+ 000 1
+ 001 2
+ 010 4
+ 011 8
+ 100 16
+ 101 32
+ 110 Reserved
+ 111 Reserved */
+#define VBOX_PCI_MSI_FLAGS_QSIZE 0x0070 /* Message queue size configured (i.e. vectors per device allocated) */
+#define VBOX_PCI_MSI_FLAGS_QMASK 0x000e /* Maximum queue size available (i.e. vectors per device possible) */
+
+/* MSI-X flags (2 bytes, capability offset 2) */
+#define VBOX_PCI_MSIX_FLAGS_ENABLE 0x8000 /* MSI-X enable */
+#define VBOX_PCI_MSIX_FLAGS_FUNCMASK 0x4000 /* Function mask */
+
+/* Power management flags (2 bytes, capability offset 2) */
+#define VBOX_PCI_PM_CAP_VER_MASK 0x0007 /* Version mask */
+#define VBOX_PCI_PM_CAP_PME_CLOCK 0x0008 /* PME clock required */
+#define VBOX_PCI_PM_CAP_RESERVED 0x0010 /* Reserved field */
+#define VBOX_PCI_PM_CAP_DSI 0x0020 /* Device specific initialization */
+#define VBOX_PCI_PM_CAP_AUX_POWER 0x01C0 /* Auxilliary power support mask */
+#define VBOX_PCI_PM_CAP_D1 0x0200 /* D1 power state support */
+#define VBOX_PCI_PM_CAP_D2 0x0400 /* D2 power state support */
+#define VBOX_PCI_PM_CAP_PME 0x0800 /* PME pin supported */
+#define VBOX_PCI_PM_CAP_PME_MASK 0xF800 /* PME Mask of all supported states */
+#define VBOX_PCI_PM_CAP_PME_D0 0x0800 /* PME# from D0 */
+#define VBOX_PCI_PM_CAP_PME_D1 0x1000 /* PME# from D1 */
+#define VBOX_PCI_PM_CAP_PME_D2 0x2000 /* PME# from D2 */
+#define VBOX_PCI_PM_CAP_PME_D3 0x4000 /* PME# from D3 (hot) */
+#define VBOX_PCI_PM_CAP_PME_D3cold 0x8000 /* PME# from D3 (cold) */
+
+/* Power management control flags (2 bytes, capability offset 4) */
+#define VBOX_PCI_PM_CTRL_STATE_MASK 0x0003 /* Current power state (D0 to D3) */
+#define VBOX_PCI_PM_CTRL_NO_SOFT_RESET 0x0008 /* No reset for D3hot->D0 */
+#define VBOX_PCI_PM_CTRL_PME_ENABLE 0x0100 /* PME pin enable */
+#define VBOX_PCI_PM_CTRL_DATA_SEL_MASK 0x1e00 /* Data select (??) */
+#define VBOX_PCI_PM_CTRL_DATA_SCALE_MASK 0x6000 /* Data scale (??) */
+#define VBOX_PCI_PM_CTRL_PME_STATUS 0x8000 /* PME pin status */
+
+/* PCI-X config flags (2 bytes, capability offset 2) */
+#define VBOX_PCI_X_CMD_DPERR_E 0x0001 /* Data Parity Error Recovery Enable */
+#define VBOX_PCI_X_CMD_ERO 0x0002 /* Enable Relaxed Ordering */
+#define VBOX_PCI_X_CMD_MAX_OUTSTANDING_SPLIT_TRANS 0x0070
+#define VBOX_PCI_X_CMD_READ_512 0x0000 /* 512 byte maximum read byte count */
+#define VBOX_PCI_X_CMD_READ_1K 0x0004 /* 1Kbyte maximum read byte count */
+#define VBOX_PCI_X_CMD_READ_2K 0x0008 /* 2Kbyte maximum read byte count */
+#define VBOX_PCI_X_CMD_READ_4K 0x000c /* 4Kbyte maximum read byte count */
+#define VBOX_PCI_X_CMD_MAX_READ 0x000c /* Max Memory Read Byte Count */
+
+/* PCI-X config flags (4 bytes, capability offset 4) */
+#define VBOX_PCI_X_STATUS_DEVFN 0x000000ff /* A copy of devfn */
+#define VBOX_PCI_X_STATUS_BUS 0x0000ff00 /* A copy of bus nr */
+#define VBOX_PCI_X_STATUS_64BIT 0x00010000 /* 64-bit device */
+#define VBOX_PCI_X_STATUS_133MHZ 0x00020000 /* 133 MHz capable */
+#define VBOX_PCI_X_STATUS_SPL_DISC 0x00040000 /* Split Completion Discarded */
+#define VBOX_PCI_X_STATUS_UNX_SPL 0x00080000 /* Unexpected Split Completion */
+#define VBOX_PCI_X_STATUS_COMPLEX 0x00100000 /* Device Complexity, 0 = simple device, 1 = bridge device */
+#define VBOX_PCI_X_STATUS_MAX_READ 0x00600000 /* Designed Max Memory Read Count, 0 = 512 bytes, 1 = 1024, 2 = 2048, 3 = 4096 */
+#define VBOX_PCI_X_STATUS_MAX_SPLIT 0x03800000 /* Designed Max Outstanding Split Transactions */
+#define VBOX_PCI_X_STATUS_MAX_CUM 0x1c000000 /* Designed Max Cumulative Read Size */
+#define VBOX_PCI_X_STATUS_SPL_ERR 0x20000000 /* Rcvd Split Completion Error Msg */
+#define VBOX_PCI_X_STATUS_266MHZ 0x40000000 /* 266 MHz capable */
+#define VBOX_PCI_X_STATUS_533MHZ 0x80000000 /* 533 MHz capable */
+
+/* PCI Express config flags (2 bytes, capability offset 2) */
+#define VBOX_PCI_EXP_FLAGS_VERS 0x000f /* Capability version */
+#define VBOX_PCI_EXP_FLAGS_TYPE 0x00f0 /* Device/Port type */
+#define VBOX_PCI_EXP_TYPE_ENDPOINT 0x0 /* Express Endpoint */
+#define VBOX_PCI_EXP_TYPE_LEG_END 0x1 /* Legacy Endpoint */
+#define VBOX_PCI_EXP_TYPE_ROOT_PORT 0x4 /* Root Port */
+#define VBOX_PCI_EXP_TYPE_UPSTREAM 0x5 /* Upstream Port */
+#define VBOX_PCI_EXP_TYPE_DOWNSTREAM 0x6 /* Downstream Port */
+#define VBOX_PCI_EXP_TYPE_PCI_BRIDGE 0x7 /* PCI/PCI-X Bridge */
+#define VBOX_PCI_EXP_TYPE_PCIE_BRIDGE 0x8 /* PCI/PCI-X to PCIE Bridge */
+#define VBOX_PCI_EXP_TYPE_ROOT_INT_EP 0x9 /* Root Complex Integrated Endpoint */
+#define VBOX_PCI_EXP_TYPE_ROOT_EC 0xa /* Root Complex Event Collector */
+#define VBOX_PCI_EXP_FLAGS_SLOT 0x0100 /* Slot implemented */
+#define VBOX_PCI_EXP_FLAGS_IRQ 0x3e00 /* Interrupt message number */
+
+/* PCI Express device capabilities (4 bytes, capability offset 4) */
+#define VBOX_PCI_EXP_DEVCAP_PAYLOAD 0x07 /* Max_Payload_Size */
+#define VBOX_PCI_EXP_DEVCAP_PHANTOM 0x18 /* Phantom functions */
+#define VBOX_PCI_EXP_DEVCAP_EXT_TAG 0x20 /* Extended tags */
+#define VBOX_PCI_EXP_DEVCAP_L0S 0x1c0 /* L0s Acceptable Latency */
+#define VBOX_PCI_EXP_DEVCAP_L1 0xe00 /* L1 Acceptable Latency */
+#define VBOX_PCI_EXP_DEVCAP_ATN_BUT 0x1000 /* Attention Button Present */
+#define VBOX_PCI_EXP_DEVCAP_ATN_IND 0x2000 /* Attention Indicator Present */
+#define VBOX_PCI_EXP_DEVCAP_PWR_IND 0x4000 /* Power Indicator Present */
+#define VBOX_PCI_EXP_DEVCAP_RBE 0x8000 /* Role-Based Error Reporting */
+#define VBOX_PCI_EXP_DEVCAP_PWR_VAL 0x3fc0000 /* Slot Power Limit Value */
+#define VBOX_PCI_EXP_DEVCAP_PWR_SCL 0xc000000 /* Slot Power Limit Scale */
+#define VBOX_PCI_EXP_DEVCAP_FLRESET 0x10000000 /* Function-Level Reset */
+
+/* PCI Express device control (2 bytes, capability offset 8) */
+#define VBOX_PCI_EXP_DEVCTL_CERE 0x0001 /* Correctable Error Reporting En. */
+#define VBOX_PCI_EXP_DEVCTL_NFERE 0x0002 /* Non-Fatal Error Reporting Enable */
+#define VBOX_PCI_EXP_DEVCTL_FERE 0x0004 /* Fatal Error Reporting Enable */
+#define VBOX_PCI_EXP_DEVCTL_URRE 0x0008 /* Unsupported Request Reporting En. */
+#define VBOX_PCI_EXP_DEVCTL_RELAXED 0x0010 /* Enable Relaxed Ordering */
+#define VBOX_PCI_EXP_DEVCTL_PAYLOAD 0x00e0 /* Max_Payload_Size */
+#define VBOX_PCI_EXP_DEVCTL_EXT_TAG 0x0100 /* Extended Tag Field Enable */
+#define VBOX_PCI_EXP_DEVCTL_PHANTOM 0x0200 /* Phantom Functions Enable */
+#define VBOX_PCI_EXP_DEVCTL_AUX_PME 0x0400 /* Auxiliary Power PM Enable */
+#define VBOX_PCI_EXP_DEVCTL_NOSNOOP 0x0800 /* Enable No Snoop */
+#define VBOX_PCI_EXP_DEVCTL_READRQ 0x7000 /* Max_Read_Request_Size */
+#define VBOX_PCI_EXP_DEVCTL_BCRE 0x8000 /* Bridge Configuration Retry Enable */
+#define VBOX_PCI_EXP_DEVCTL_FLRESET 0x8000 /* Function-Level Reset [bit shared with BCRE] */
+
+/* PCI Express device status (2 bytes, capability offset 10) */
+#define VBOX_PCI_EXP_DEVSTA_CED 0x01 /* Correctable Error Detected */
+#define VBOX_PCI_EXP_DEVSTA_NFED 0x02 /* Non-Fatal Error Detected */
+#define VBOX_PCI_EXP_DEVSTA_FED 0x04 /* Fatal Error Detected */
+#define VBOX_PCI_EXP_DEVSTA_URD 0x08 /* Unsupported Request Detected */
+#define VBOX_PCI_EXP_DEVSTA_AUXPD 0x10 /* AUX Power Detected */
+#define VBOX_PCI_EXP_DEVSTA_TRPND 0x20 /* Transactions Pending */
+
+/* PCI Express link capabilities (4 bytes, capability offset 12) */
+#define VBOX_PCI_EXP_LNKCAP_SPEED 0x0000f /* Maximum Link Speed */
+#define VBOX_PCI_EXP_LNKCAP_WIDTH 0x003f0 /* Maximum Link Width */
+#define VBOX_PCI_EXP_LNKCAP_ASPM 0x00c00 /* Active State Power Management */
+#define VBOX_PCI_EXP_LNKCAP_L0S 0x07000 /* L0s Acceptable Latency */
+#define VBOX_PCI_EXP_LNKCAP_L1 0x38000 /* L1 Acceptable Latency */
+#define VBOX_PCI_EXP_LNKCAP_CLOCKPM 0x40000 /* Clock Power Management */
+#define VBOX_PCI_EXP_LNKCAP_SURPRISE 0x80000 /* Surprise Down Error Reporting */
+#define VBOX_PCI_EXP_LNKCAP_DLLA 0x100000 /* Data Link Layer Active Reporting */
+#define VBOX_PCI_EXP_LNKCAP_LBNC 0x200000 /* Link Bandwidth Notification Capability */
+#define VBOX_PCI_EXP_LNKCAP_PORT 0xff000000 /* Port Number */
+
+/* PCI Express link control (2 bytes, capability offset 16) */
+#define VBOX_PCI_EXP_LNKCTL_ASPM 0x0003 /* ASPM Control */
+#define VBOX_PCI_EXP_LNKCTL_RCB 0x0008 /* Read Completion Boundary */
+#define VBOX_PCI_EXP_LNKCTL_DISABLE 0x0010 /* Link Disable */
+#define VBOX_PCI_EXP_LNKCTL_RETRAIN 0x0020 /* Retrain Link */
+#define VBOX_PCI_EXP_LNKCTL_CLOCK 0x0040 /* Common Clock Configuration */
+#define VBOX_PCI_EXP_LNKCTL_XSYNCH 0x0080 /* Extended Synch */
+#define VBOX_PCI_EXP_LNKCTL_CLOCKPM 0x0100 /* Clock Power Management */
+#define VBOX_PCI_EXP_LNKCTL_HWAUTWD 0x0200 /* Hardware Autonomous Width Disable */
+#define VBOX_PCI_EXP_LNKCTL_BWMIE 0x0400 /* Bandwidth Mgmt Interrupt Enable */
+#define VBOX_PCI_EXP_LNKCTL_AUTBWIE 0x0800 /* Autonomous Bandwidth Mgmt Interrupt Enable */
+
+/* PCI Express link status (2 bytes, capability offset 18) */
+#define VBOX_PCI_EXP_LNKSTA_SPEED 0x000f /* Negotiated Link Speed */
+#define VBOX_PCI_EXP_LNKSTA_WIDTH 0x03f0 /* Negotiated Link Width */
+#define VBOX_PCI_EXP_LNKSTA_TR_ERR 0x0400 /* Training Error (obsolete) */
+#define VBOX_PCI_EXP_LNKSTA_TRAIN 0x0800 /* Link Training */
+#define VBOX_PCI_EXP_LNKSTA_SL_CLK 0x1000 /* Slot Clock Configuration */
+#define VBOX_PCI_EXP_LNKSTA_DL_ACT 0x2000 /* Data Link Layer in DL_Active State */
+#define VBOX_PCI_EXP_LNKSTA_BWMGMT 0x4000 /* Bandwidth Mgmt Status */
+#define VBOX_PCI_EXP_LNKSTA_AUTBW 0x8000 /* Autonomous Bandwidth Mgmt Status */
+
+/* PCI Express slot capabilities (4 bytes, capability offset 20) */
+#define VBOX_PCI_EXP_SLTCAP_ATNB 0x0001 /* Attention Button Present */
+#define VBOX_PCI_EXP_SLTCAP_PWRC 0x0002 /* Power Controller Present */
+#define VBOX_PCI_EXP_SLTCAP_MRL 0x0004 /* MRL Sensor Present */
+#define VBOX_PCI_EXP_SLTCAP_ATNI 0x0008 /* Attention Indicator Present */
+#define VBOX_PCI_EXP_SLTCAP_PWRI 0x0010 /* Power Indicator Present */
+#define VBOX_PCI_EXP_SLTCAP_HPS 0x0020 /* Hot-Plug Surprise */
+#define VBOX_PCI_EXP_SLTCAP_HPC 0x0040 /* Hot-Plug Capable */
+#define VBOX_PCI_EXP_SLTCAP_PWR_VAL 0x00007f80 /* Slot Power Limit Value */
+#define VBOX_PCI_EXP_SLTCAP_PWR_SCL 0x00018000 /* Slot Power Limit Scale */
+#define VBOX_PCI_EXP_SLTCAP_INTERLOCK 0x020000 /* Electromechanical Interlock Present */
+#define VBOX_PCI_EXP_SLTCAP_NOCMDCOMP 0x040000 /* No Command Completed Support */
+#define VBOX_PCI_EXP_SLTCAP_PSN 0xfff80000 /* Physical Slot Number */
+
+/* PCI Express slot control (2 bytes, capability offset 24) */
+#define VBOX_PCI_EXP_SLTCTL_ATNB 0x0001 /* Attention Button Pressed Enable */
+#define VBOX_PCI_EXP_SLTCTL_PWRF 0x0002 /* Power Fault Detected Enable */
+#define VBOX_PCI_EXP_SLTCTL_MRLS 0x0004 /* MRL Sensor Changed Enable */
+#define VBOX_PCI_EXP_SLTCTL_PRSD 0x0008 /* Presence Detect Changed Enable */
+#define VBOX_PCI_EXP_SLTCTL_CMDC 0x0010 /* Command Completed Interrupt Enable */
+#define VBOX_PCI_EXP_SLTCTL_HPIE 0x0020 /* Hot-Plug Interrupt Enable */
+#define VBOX_PCI_EXP_SLTCTL_ATNI 0x00c0 /* Attention Indicator Control */
+#define VBOX_PCI_EXP_SLTCTL_PWRI 0x0300 /* Power Indicator Control */
+#define VBOX_PCI_EXP_SLTCTL_PWRC 0x0400 /* Power Controller Control */
+#define VBOX_PCI_EXP_SLTCTL_INTERLOCK 0x0800 /* Electromechanical Interlock Control */
+#define VBOX_PCI_EXP_SLTCTL_LLCHG 0x1000 /* Data Link Layer State Changed Enable */
+
+/* PCI Express slot status (2 bytes, capability offset 26) */
+#define VBOX_PCI_EXP_SLTSTA_ATNB 0x0001 /* Attention Button Pressed */
+#define VBOX_PCI_EXP_SLTSTA_PWRF 0x0002 /* Power Fault Detected */
+#define VBOX_PCI_EXP_SLTSTA_MRLS 0x0004 /* MRL Sensor Changed */
+#define VBOX_PCI_EXP_SLTSTA_PRSD 0x0008 /* Presence Detect Changed */
+#define VBOX_PCI_EXP_SLTSTA_CMDC 0x0010 /* Command Completed */
+#define VBOX_PCI_EXP_SLTSTA_MRL_ST 0x0020 /* MRL Sensor State */
+#define VBOX_PCI_EXP_SLTSTA_PRES 0x0040 /* Presence Detect State */
+#define VBOX_PCI_EXP_SLTSTA_INTERLOCK 0x0080 /* Electromechanical Interlock Status */
+#define VBOX_PCI_EXP_SLTSTA_LLCHG 0x0100 /* Data Link Layer State Changed */
+
+/* PCI Express root control (2 bytes, capability offset 28) */
+#define VBOX_PCI_EXP_RTCTL_SECEE 0x0001 /* System Error on Correctable Error */
+#define VBOX_PCI_EXP_RTCTL_SENFEE 0x0002 /* System Error on Non-Fatal Error */
+#define VBOX_PCI_EXP_RTCTL_SEFEE 0x0004 /* System Error on Fatal Error */
+#define VBOX_PCI_EXP_RTCTL_PMEIE 0x0008 /* PME Interrupt Enable */
+#define VBOX_PCI_EXP_RTCTL_CRSVIS 0x0010 /* Configuration Request Retry Status Visible to SW */
+
+/* PCI Express root capabilities (2 bytes, capability offset 30) */
+#define VBOX_PCI_EXP_RTCAP_CRSVIS 0x0010 /* Configuration Request Retry Status Visible to SW */
+
+/* PCI Express root status (4 bytes, capability offset 32) */
+#define VBOX_PCI_EXP_RTSTA_PME_REQID 0x0000ffff /* PME Requester ID */
+#define VBOX_PCI_EXP_RTSTA_PME_STATUS 0x00010000 /* PME Status */
+#define VBOX_PCI_EXP_RTSTA_PME_PENDING 0x00020000 /* PME is Pending */
+
+
+/** Fixed I/O region number for ROM. */
+#define VBOX_PCI_ROM_SLOT 6
+/** Max number of I/O regions. */
+#define VBOX_PCI_NUM_REGIONS 7
+
+#define PCI_ROM_SLOT VBOX_PCI_ROM_SLOT /**< deprecated */
+#define PCI_NUM_REGIONS VBOX_PCI_NUM_REGIONS /**< deprecated */
+
+/** Number of functions per device. */
+#define VBOX_PCI_MAX_FUNCTIONS 8
+/** Number of devices per bus. */
+#define VBOX_PCI_MAX_DEVICES 32
+/** The function number mask for a device+function number. */
+#define VBOX_PCI_DEVFN_FUN_MASK 0x7
+/** The device number shift count for a device+function number. */
+#define VBOX_PCI_DEVFN_DEV_SHIFT 3
+/** The device number mask for a device+function number. */
+#define VBOX_PCI_DEVFN_DEV_MASK 0x1f
+/** The bus number shift count for a bus+device+function number. */
+#define VBOX_PCI_BUS_SHIFT 0x8
+/** The bus number mask a bus+device+function number. */
+#define VBOX_PCI_BUS_MASK 0xff
+/** Make a device+function number. */
+#define VBOX_PCI_DEVFN_MAKE(a_uPciDevNo, a_uPciFunNo) ( ((a_uPciDevNo) << VBOX_PCI_DEVFN_DEV_SHIFT) \
+ | ((a_uPciFunNo) & VBOX_PCI_DEVFN_FUN_MASK))
+
+/** Checks whether the PCIBDF is valid. */
+#define PCIBDF_IS_VALID(a_uBusDevFn) (!((a_uBusDevFn) & PCI_BDF_F_INVALID))
+/** Make a PCIBDF given the bus and device:function. */
+#define PCIBDF_MAKE(a_uBus, a_uDevFn) (((a_uBus) << VBOX_PCI_BUS_SHIFT) | (a_uDevFn))
+
+/** Southbridge I/O APIC (when IOMMU is enabled): Bus. */
+#define VBOX_PCI_BUS_SB_IOAPIC 0
+/** Southbridge I/O APIC (when IOMMU is enabled): Device. */
+#define VBOX_PCI_DEV_SB_IOAPIC 0x14
+/** Southbridge I/O APIC (when IOMMU is enabled): Function. */
+#define VBOX_PCI_FN_SB_IOAPIC 0
+/** PCI BDF (hardcoded by linux guests) reserved for the SB I/O APIC when using VMs
+ * with an AMD IOMMU. */
+#define VBOX_PCI_BDF_SB_IOAPIC PCIBDF_MAKE(VBOX_PCI_BUS_SB_IOAPIC, \
+ VBOX_PCI_DEVFN_MAKE(VBOX_PCI_DEV_SB_IOAPIC, VBOX_PCI_FN_SB_IOAPIC))
+
+/**
+ * A PCI PASID (Process Address Space ID).
+ *
+ * A PASID is 20 bits wide. We use bit 31 to indicate the PASID is invalid or not
+ * present.
+ */
+typedef uint32_t PCIPASID;
+/** PCIPASID: Valid. */
+#define PCIPASID_F_VALID RT_BIT(31)
+/** Nil PCIPASID value. */
+#define NIL_PCIPASID UINT32_C(0)
+/** Returns whether the PCI PASID is valid. */
+#define PCIPASID_IS_VALID(a) (((a) & PCIPASID_F_VALID) != 0)
+/** Returns the PASID value of a PCI PASID. */
+#define PCIPASID_VAL(a) ((a) & UINT32_C(0xfffff))
+
+
+#if defined(__cplusplus) && defined(IN_RING3)
+/* For RTStrPrintf(). */
+# include <iprt/string.h>
+
+/**
+ * Class representing PCI address. PCI device consist of
+ * bus, device and function numbers. Generally device PCI
+ * address could be changed during runtime, but only by
+ * an OS PCI driver.
+ *
+ * @remarks C++ classes (structs included) are not generally accepted in
+ * VMM devices or drivers. An exception may be granted for this class
+ * if it's contained to ring-3 and that this is a one time exception
+ * which sets no precedent.
+ */
+struct PCIBusAddress
+{
+ /** @todo: think if we'll need domain, which is higher
+ * word of the address. */
+ int miBus;
+ int miDevice;
+ int miFn;
+
+ PCIBusAddress()
+ {
+ clear();
+ }
+
+ PCIBusAddress(int iBus, int iDevice, int iFn)
+ {
+ init(iBus, iDevice, iFn);
+ }
+
+ PCIBusAddress(int32_t iAddr)
+ {
+ clear();
+ fromLong(iAddr);
+ }
+
+ PCIBusAddress& clear()
+ {
+ miBus = miDevice = miFn = -1;
+ return *this;
+ }
+
+ void init(int iBus, int iDevice, int iFn)
+ {
+ miBus = iBus;
+ miDevice = iDevice;
+ miFn = iFn;
+ }
+
+ void init(const PCIBusAddress &a)
+ {
+ miBus = a.miBus;
+ miDevice = a.miDevice;
+ miFn = a.miFn;
+ }
+
+ bool operator<(const PCIBusAddress &a) const
+ {
+ if (miBus < a.miBus)
+ return true;
+
+ if (miBus > a.miBus)
+ return false;
+
+ if (miDevice < a.miDevice)
+ return true;
+
+ if (miDevice > a.miDevice)
+ return false;
+
+ if (miFn < a.miFn)
+ return true;
+
+ if (miFn > a.miFn)
+ return false;
+
+ return false;
+ }
+
+ bool operator==(const PCIBusAddress &a) const
+ {
+ return (miBus == a.miBus)
+ && (miDevice == a.miDevice)
+ && (miFn == a.miFn);
+ }
+
+ bool operator!=(const PCIBusAddress &a) const
+ {
+ return (miBus != a.miBus)
+ || (miDevice != a.miDevice)
+ || (miFn != a.miFn);
+ }
+
+ bool valid() const
+ {
+ return (miBus != -1)
+ && (miDevice != -1)
+ && (miFn != -1);
+ }
+
+ int32_t asLong() const
+ {
+ Assert(valid());
+ return (miBus << 8) | (miDevice << 3) | miFn;
+ }
+
+ PCIBusAddress& fromLong(int32_t value)
+ {
+ miBus = (value >> 8) & 0xff;
+ miDevice = (value & 0xff) >> 3;
+ miFn = (value & 7);
+ return *this;
+ }
+
+ /** Create string representation of this PCI address. */
+ bool format(char* szBuf, int32_t cBufSize)
+ {
+ if (cBufSize < (/* bus */ 2 + /* : */ 1 + /* device */ 2 + /* . */ 1 + /* function*/ 1 + /* \0 */1))
+ return false;
+
+ if (valid())
+ RTStrPrintf(szBuf, cBufSize, "%02x:%02x.%01x", miBus, miDevice, miFn);
+ else
+ RTStrPrintf(szBuf, cBufSize, "%s", "<bad>");
+
+ return true;
+ }
+
+ static const size_t cMaxAddrSize = 10;
+};
+
+#endif /* __cplusplus && IN_RING3 */
+
+/** @} */
+
+#endif /* !VBOX_INCLUDED_pci_h */
diff --git a/include/VBox/rawpci.h b/include/VBox/rawpci.h
new file mode 100644
index 00000000..290983c0
--- /dev/null
+++ b/include/VBox/rawpci.h
@@ -0,0 +1,618 @@
+/** @file
+ * Raw PCI Devices (aka PCI pass-through). (VMM)
+ */
+
+/*
+ * Copyright (C) 2010-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_rawpci_h
+#define VBOX_INCLUDED_rawpci_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/types.h>
+#include <VBox/sup.h>
+
+RT_C_DECLS_BEGIN
+
+/**
+ * Handle for the raw PCI device.
+ */
+typedef uint32_t PCIRAWDEVHANDLE;
+
+/**
+ * Handle for the ISR.
+ */
+typedef uint32_t PCIRAWISRHANDLE;
+
+/**
+ * Physical memory action enumeration.
+ */
+typedef enum PCIRAWMEMINFOACTION
+{
+ /** Pages mapped. */
+ PCIRAW_MEMINFO_MAP,
+ /** Pages unmapped. */
+ PCIRAW_MEMINFO_UNMAP,
+ /** The usual 32-bit type blow up. */
+ PCIRAW_MEMINFO_32BIT_HACK = 0x7fffffff
+} PCIRAWMEMINFOACTION;
+
+/**
+ * Per-VM capability flag bits.
+ */
+typedef enum PCIRAWVMFLAGS
+{
+ /** If we can use IOMMU in this VM. */
+ PCIRAW_VMFLAGS_HAS_IOMMU = (1 << 0),
+ PCIRAW_VMFLAGS_32BIT_HACK = 0x7fffffff
+} PCIRAWVMFLAGS;
+
+/* Forward declaration. */
+struct RAWPCIPERVM;
+
+/**
+ * Callback to notify raw PCI subsystem about mapping/unmapping of
+ * host pages to the guest. Typical usecase is to register physical
+ * RAM pages with IOMMU, so that it could allow DMA for PCI devices
+ * directly from the guest RAM.
+ * Region shall be one or more contigous (both host and guest) pages
+ * of physical memory.
+ *
+ * @returns VBox status code.
+ *
+ * @param pVmData The per VM data.
+ * @param HCPhysStart Physical address of region start on the host.
+ * @param GCPhysStart Physical address of region start on the guest.
+ * @param cbMem Region size in bytes.
+ * @param enmAction Action performed (i.e. if page was mapped
+ * or unmapped).
+ */
+typedef DECLCALLBACKTYPE(int, FNRAWPCICONTIGPHYSMEMINFO,(struct RAWPCIPERVM *pVmData, RTHCPHYS HCPhysStart,
+ RTGCPHYS GCPhysStart, uint64_t cbMem, PCIRAWMEMINFOACTION enmAction));
+typedef FNRAWPCICONTIGPHYSMEMINFO *PFNRAWPCICONTIGPHYSMEMINFO;
+
+/** Data being part of the VM structure. */
+typedef struct RAWPCIPERVM
+{
+ /** Shall only be interpreted by the host PCI driver. */
+ RTR0PTR pDriverData;
+ /** Callback called when mapping of host pages to the guest changes. */
+ PFNRAWPCICONTIGPHYSMEMINFO pfnContigMemInfo;
+ /** Flags describing VM capabilities (such as IOMMU presence). */
+ uint32_t fVmCaps;
+} RAWPCIPERVM;
+typedef RAWPCIPERVM *PRAWPCIPERVM;
+
+/** Parameters buffer for PCIRAWR0_DO_OPEN_DEVICE call */
+typedef struct
+{
+ /* in */
+ uint32_t PciAddress;
+ uint32_t fFlags;
+ /* out */
+ PCIRAWDEVHANDLE Device;
+ uint32_t fDevFlags;
+} PCIRAWREQOPENDEVICE;
+
+/** Parameters buffer for PCIRAWR0_DO_CLOSE_DEVICE call */
+typedef struct
+{
+ /* in */
+ uint32_t fFlags;
+} PCIRAWREQCLOSEDEVICE;
+
+/** Parameters buffer for PCIRAWR0_DO_GET_REGION_INFO call */
+typedef struct
+{
+ /* in */
+ int32_t iRegion;
+ /* out */
+ RTGCPHYS RegionStart;
+ uint64_t u64RegionSize;
+ bool fPresent;
+ uint32_t fFlags;
+} PCIRAWREQGETREGIONINFO;
+
+/** Parameters buffer for PCIRAWR0_DO_MAP_REGION call. */
+typedef struct
+{
+ /* in */
+ RTGCPHYS StartAddress;
+ uint64_t iRegionSize;
+ int32_t iRegion;
+ uint32_t fFlags;
+ /* out */
+ RTR3PTR pvAddressR3;
+ RTR0PTR pvAddressR0;
+} PCIRAWREQMAPREGION;
+
+/** Parameters buffer for PCIRAWR0_DO_UNMAP_REGION call. */
+typedef struct
+{
+ /* in */
+ RTGCPHYS StartAddress;
+ uint64_t iRegionSize;
+ RTR3PTR pvAddressR3;
+ RTR0PTR pvAddressR0;
+ int32_t iRegion;
+} PCIRAWREQUNMAPREGION;
+
+/** Parameters buffer for PCIRAWR0_DO_PIO_WRITE call. */
+typedef struct
+{
+ /* in */
+ uint16_t iPort;
+ uint16_t cb;
+ uint32_t iValue;
+} PCIRAWREQPIOWRITE;
+
+/** Parameters buffer for PCIRAWR0_DO_PIO_READ call. */
+typedef struct
+{
+ /* in */
+ uint16_t iPort;
+ uint16_t cb;
+ /* out */
+ uint32_t iValue;
+} PCIRAWREQPIOREAD;
+
+/** Memory operand. */
+typedef struct
+{
+ union
+ {
+ uint8_t u8;
+ uint16_t u16;
+ uint32_t u32;
+ uint64_t u64;
+ } u;
+ uint8_t cb;
+} PCIRAWMEMLOC;
+
+/** Parameters buffer for PCIRAWR0_DO_MMIO_WRITE call. */
+typedef struct
+{
+ /* in */
+ RTR0PTR Address;
+ PCIRAWMEMLOC Value;
+} PCIRAWREQMMIOWRITE;
+
+/** Parameters buffer for PCIRAWR0_DO_MMIO_READ call. */
+typedef struct
+{
+ /* in */
+ RTR0PTR Address;
+ /* inout (Value.cb is in) */
+ PCIRAWMEMLOC Value;
+} PCIRAWREQMMIOREAD;
+
+/* Parameters buffer for PCIRAWR0_DO_PCICFG_WRITE call. */
+typedef struct
+{
+ /* in */
+ uint32_t iOffset;
+ PCIRAWMEMLOC Value;
+} PCIRAWREQPCICFGWRITE;
+
+/** Parameters buffer for PCIRAWR0_DO_PCICFG_READ call. */
+typedef struct
+{
+ /* in */
+ uint32_t iOffset;
+ /* inout (Value.cb is in) */
+ PCIRAWMEMLOC Value;
+} PCIRAWREQPCICFGREAD;
+
+/** Parameters buffer for PCIRAWR0_DO_GET_IRQ call. */
+typedef struct PCIRAWREQGETIRQ
+{
+ /* in */
+ int64_t iTimeout;
+ /* out */
+ int32_t iIrq;
+} PCIRAWREQGETIRQ;
+
+/** Parameters buffer for PCIRAWR0_DO_POWER_STATE_CHANGE call. */
+typedef struct PCIRAWREQPOWERSTATECHANGE
+{
+ /* in */
+ uint32_t iState;
+ /* in/out */
+ uint64_t u64Param;
+} PCIRAWREQPOWERSTATECHANGE;
+
+/**
+ * Request buffer use for communication with the driver.
+ */
+typedef struct PCIRAWSENDREQ
+{
+ /** The request header. */
+ SUPVMMR0REQHDR Hdr;
+ /** Alternative to passing the taking the session from the VM handle.
+ * Either use this member or use the VM handle, don't do both.
+ */
+ PSUPDRVSESSION pSession;
+ /** Request type. */
+ int32_t iRequest;
+ /** Host device request targetted to. */
+ PCIRAWDEVHANDLE TargetDevice;
+ /** Call parameters. */
+ union
+ {
+ PCIRAWREQOPENDEVICE aOpenDevice;
+ PCIRAWREQCLOSEDEVICE aCloseDevice;
+ PCIRAWREQGETREGIONINFO aGetRegionInfo;
+ PCIRAWREQMAPREGION aMapRegion;
+ PCIRAWREQUNMAPREGION aUnmapRegion;
+ PCIRAWREQPIOWRITE aPioWrite;
+ PCIRAWREQPIOREAD aPioRead;
+ PCIRAWREQMMIOWRITE aMmioWrite;
+ PCIRAWREQMMIOREAD aMmioRead;
+ PCIRAWREQPCICFGWRITE aPciCfgWrite;
+ PCIRAWREQPCICFGREAD aPciCfgRead;
+ PCIRAWREQGETIRQ aGetIrq;
+ PCIRAWREQPOWERSTATECHANGE aPowerStateChange;
+ } u;
+} PCIRAWSENDREQ;
+typedef PCIRAWSENDREQ *PPCIRAWSENDREQ;
+
+/**
+ * Operations performed by the driver.
+ */
+typedef enum PCIRAWR0OPERATION
+{
+ /* Open device. */
+ PCIRAWR0_DO_OPEN_DEVICE,
+ /* Close device. */
+ PCIRAWR0_DO_CLOSE_DEVICE,
+ /* Get PCI region info. */
+ PCIRAWR0_DO_GET_REGION_INFO,
+ /* Map PCI region into VM address space. */
+ PCIRAWR0_DO_MAP_REGION,
+ /* Unmap PCI region from VM address space. */
+ PCIRAWR0_DO_UNMAP_REGION,
+ /* Perform PIO write. */
+ PCIRAWR0_DO_PIO_WRITE,
+ /* Perform PIO read. */
+ PCIRAWR0_DO_PIO_READ,
+ /* Perform MMIO write. */
+ PCIRAWR0_DO_MMIO_WRITE,
+ /* Perform MMIO read. */
+ PCIRAWR0_DO_MMIO_READ,
+ /* Perform PCI config write. */
+ PCIRAWR0_DO_PCICFG_WRITE,
+ /* Perform PCI config read. */
+ PCIRAWR0_DO_PCICFG_READ,
+ /* Get next IRQ for the device. */
+ PCIRAWR0_DO_GET_IRQ,
+ /* Enable getting IRQs for the device. */
+ PCIRAWR0_DO_ENABLE_IRQ,
+ /* Disable getting IRQs for the device. */
+ PCIRAWR0_DO_DISABLE_IRQ,
+ /* Notify driver about guest power state change. */
+ PCIRAWR0_DO_POWER_STATE_CHANGE,
+ /** The usual 32-bit type blow up. */
+ PCIRAWR0_DO_32BIT_HACK = 0x7fffffff
+} PCIRAWR0OPERATION;
+
+/**
+ * Power state enumeration.
+ */
+typedef enum PCIRAWPOWERSTATE
+{
+ /* Power on. */
+ PCIRAW_POWER_ON,
+ /* Power off. */
+ PCIRAW_POWER_OFF,
+ /* Suspend. */
+ PCIRAW_POWER_SUSPEND,
+ /* Resume. */
+ PCIRAW_POWER_RESUME,
+ /* Reset. */
+ PCIRAW_POWER_RESET,
+ /** The usual 32-bit type blow up. */
+ PCIRAW_POWER_32BIT_HACK = 0x7fffffff
+} PCIRAWPOWERSTATE;
+
+
+/** Forward declarations. */
+typedef struct RAWPCIFACTORY *PRAWPCIFACTORY;
+typedef struct RAWPCIDEVPORT *PRAWPCIDEVPORT;
+
+/**
+ * Interrupt service routine callback.
+ *
+ * @returns if interrupt was processed.
+ *
+ * @param pvContext Opaque user data passed to the handler.
+ * @param iIrq Interrupt number.
+ */
+typedef DECLCALLBACKTYPE(bool, FNRAWPCIISR,(void *pvContext, int32_t iIrq));
+typedef FNRAWPCIISR *PFNRAWPCIISR;
+
+/**
+ * This is the port on the device interface, i.e. the driver side which the
+ * host device is connected to.
+ *
+ * This is only used for the in-kernel PCI device connections.
+ */
+typedef struct RAWPCIDEVPORT
+{
+ /** Structure version number. (RAWPCIDEVPORT_VERSION) */
+ uint32_t u32Version;
+
+ /**
+ * Init device.
+ *
+ * @param pPort Pointer to this structure.
+ * @param fFlags Initialization flags.
+ */
+ DECLR0CALLBACKMEMBER(int, pfnInit,(PRAWPCIDEVPORT pPort,
+ uint32_t fFlags));
+
+
+ /**
+ * Deinit device.
+ *
+ * @param pPort Pointer to this structure.
+ * @param fFlags Initialization flags.
+ */
+ DECLR0CALLBACKMEMBER(int, pfnDeinit,(PRAWPCIDEVPORT pPort,
+ uint32_t fFlags));
+
+
+ /**
+ * Destroy device.
+ *
+ * @param pPort Pointer to this structure.
+ */
+ DECLR0CALLBACKMEMBER(int, pfnDestroy,(PRAWPCIDEVPORT pPort));
+
+ /**
+ * Get PCI region info.
+ *
+ * @param pPort Pointer to this structure.
+ * @param iRegion Region number.
+ * @param pRegionStart Where to start the region address.
+ * @param pu64RegionSize Where to store the region size.
+ * @param pfPresent Where to store if the region is present.
+ * @param pfFlags Where to store the flags.
+ */
+ DECLR0CALLBACKMEMBER(int, pfnGetRegionInfo,(PRAWPCIDEVPORT pPort,
+ int32_t iRegion,
+ RTHCPHYS *pRegionStart,
+ uint64_t *pu64RegionSize,
+ bool *pfPresent,
+ uint32_t *pfFlags));
+
+
+ /**
+ * Map PCI region.
+ *
+ * @param pPort Pointer to this structure.
+ * @param iRegion Region number.
+ * @param RegionStart Region start.
+ * @param u64RegionSize Region size.
+ * @param fFlags Flags.
+ * @param pRegionBaseR0 Where to store the R0 address.
+ */
+ DECLR0CALLBACKMEMBER(int, pfnMapRegion,(PRAWPCIDEVPORT pPort,
+ int32_t iRegion,
+ RTHCPHYS RegionStart,
+ uint64_t u64RegionSize,
+ int32_t fFlags,
+ RTR0PTR *pRegionBaseR0));
+
+ /**
+ * Unmap PCI region.
+ *
+ * @param pPort Pointer to this structure.
+ * @param iRegion Region number.
+ * @param RegionStart Region start.
+ * @param u64RegionSize Region size.
+ * @param RegionBase Base address.
+ */
+ DECLR0CALLBACKMEMBER(int, pfnUnmapRegion,(PRAWPCIDEVPORT pPort,
+ int32_t iRegion,
+ RTHCPHYS RegionStart,
+ uint64_t u64RegionSize,
+ RTR0PTR RegionBase));
+
+ /**
+ * Read device PCI register.
+ *
+ * @param pPort Pointer to this structure.
+ * @param Register PCI register.
+ * @param pValue Read value (with desired read width).
+ */
+ DECLR0CALLBACKMEMBER(int, pfnPciCfgRead,(PRAWPCIDEVPORT pPort,
+ uint32_t Register,
+ PCIRAWMEMLOC *pValue));
+
+
+ /**
+ * Write device PCI register.
+ *
+ * @param pPort Pointer to this structure.
+ * @param Register PCI register.
+ * @param pValue Write value (with desired write width).
+ */
+ DECLR0CALLBACKMEMBER(int, pfnPciCfgWrite,(PRAWPCIDEVPORT pPort,
+ uint32_t Register,
+ PCIRAWMEMLOC *pValue));
+
+ /**
+ * Request to register interrupt handler.
+ *
+ * @param pPort Pointer to this structure.
+ * @param pfnHandler Pointer to the handler.
+ * @param pIrqContext Context passed to the handler.
+ * @param phIsr Handle for the ISR, .
+ */
+ DECLR0CALLBACKMEMBER(int, pfnRegisterIrqHandler,(PRAWPCIDEVPORT pPort,
+ PFNRAWPCIISR pfnHandler,
+ void* pIrqContext,
+ PCIRAWISRHANDLE *phIsr));
+
+ /**
+ * Request to unregister interrupt handler.
+ *
+ * @param pPort Pointer to this structure.
+ * @param hIsr Handle of ISR to unregister (retured by earlier pfnRegisterIrqHandler).
+ */
+ DECLR0CALLBACKMEMBER(int, pfnUnregisterIrqHandler,(PRAWPCIDEVPORT pPort,
+ PCIRAWISRHANDLE hIsr));
+
+ /**
+ * Power state change notification.
+ *
+ * @param pPort Pointer to this structure.
+ * @param aState New power state.
+ * @param pu64Param State-specific in/out parameter.
+ */
+ DECLR0CALLBACKMEMBER(int, pfnPowerStateChange,(PRAWPCIDEVPORT pPort,
+ PCIRAWPOWERSTATE aState,
+ uint64_t *pu64Param));
+
+ /** Structure version number. (RAWPCIDEVPORT_VERSION) */
+ uint32_t u32VersionEnd;
+} RAWPCIDEVPORT;
+/** Version number for the RAWPCIDEVPORT::u32Version and RAWPCIIFPORT::u32VersionEnd fields. */
+#define RAWPCIDEVPORT_VERSION UINT32_C(0xAFBDCC02)
+
+/**
+ * The component factory interface for create a raw PCI interfaces.
+ */
+typedef struct RAWPCIFACTORY
+{
+ /**
+ * Release this factory.
+ *
+ * SUPR0ComponentQueryFactory (SUPDRVFACTORY::pfnQueryFactoryInterface to be precise)
+ * will retain a reference to the factory and the caller has to call this method to
+ * release it once the pfnCreateAndConnect call(s) has been done.
+ *
+ * @param pFactory Pointer to this structure.
+ */
+ DECLR0CALLBACKMEMBER(void, pfnRelease,(PRAWPCIFACTORY pFactory));
+
+ /**
+ * Create an instance for the specfied host PCI card and connects it
+ * to the driver.
+ *
+ *
+ * @returns VBox status code.
+ *
+ * @param pFactory Pointer to this structure.
+ * @param u32HostAddress Address of PCI device on the host.
+ * @param fFlags Creation flags.
+ * @param pVmCtx Context of VM where device is created.
+ * @param ppDevPort Where to store the pointer to the device port
+ * on success.
+ * @param pfDevFlags Where to store the device flags.
+ *
+ */
+ DECLR0CALLBACKMEMBER(int, pfnCreateAndConnect,(PRAWPCIFACTORY pFactory,
+ uint32_t u32HostAddress,
+ uint32_t fFlags,
+ PRAWPCIPERVM pVmCtx,
+ PRAWPCIDEVPORT *ppDevPort,
+ uint32_t *pfDevFlags));
+
+
+ /**
+ * Initialize per-VM data related to PCI passthrough.
+ *
+ * @returns VBox status code.
+ *
+ * @param pFactory Pointer to this structure.
+ * @param pVM The cross context VM structure.
+ * @param pVmData Pointer to PCI data.
+ */
+ DECLR0CALLBACKMEMBER(int, pfnInitVm,(PRAWPCIFACTORY pFactory,
+ PVM pVM,
+ PRAWPCIPERVM pVmData));
+
+ /**
+ * Deinitialize per-VM data related to PCI passthrough.
+ *
+ * @returns VBox status code.
+ *
+ * @param pFactory Pointer to this structure.
+ * @param pVM The cross context VM structure.
+ * @param pVmData Pointer to PCI data.
+ */
+ DECLR0CALLBACKMEMBER(void, pfnDeinitVm,(PRAWPCIFACTORY pFactory,
+ PVM pVM,
+ PRAWPCIPERVM pVmData));
+} RAWPCIFACTORY;
+
+#define RAWPCIFACTORY_UUID_STR "ea089839-4171-476f-adfb-9e7ab1cbd0fb"
+
+/**
+ * Flags passed to pfnPciDeviceConstructStart(), to notify driver
+ * about options to be used to open device.
+ */
+typedef enum PCIRAWDRIVERFLAGS
+{
+ /** If runtime shall try to detach host driver. */
+ PCIRAWDRIVERRFLAG_DETACH_HOST_DRIVER = (1 << 0),
+ /** The usual 32-bit type blow up. */
+ PCIRAWDRIVERRFLAG_32BIT_HACK = 0x7fffffff
+} PCIRAWDRIVERFLAGS;
+
+/**
+ * Flags used to describe PCI region, matches to PCIADDRESSSPACE
+ * in pci.h.
+ */
+typedef enum PCIRAWADDRESSSPACE
+{
+ /** Memory. */
+ PCIRAW_ADDRESS_SPACE_MEM = 0x00,
+ /** I/O space. */
+ PCIRAW_ADDRESS_SPACE_IO = 0x01,
+ /** 32-bit BAR. */
+ PCIRAW_ADDRESS_SPACE_BAR32 = 0x00,
+ /** 64-bit BAR. */
+ PCIRAW_ADDRESS_SPACE_BAR64 = 0x04,
+ /** Prefetch memory. */
+ PCIRAW_ADDRESS_SPACE_MEM_PREFETCH = 0x08,
+ /** The usual 32-bit type blow up. */
+ PCIRAW_ADDRESS_SPACE_32BIT_HACK = 0x7fffffff
+} PCIRAWADDRESSSPACE;
+
+RT_C_DECLS_END
+
+/* #define VBOX_WITH_SHARED_PCI_INTERRUPTS */
+
+#endif /* !VBOX_INCLUDED_rawpci_h */
diff --git a/include/VBox/scsi.h b/include/VBox/scsi.h
new file mode 100644
index 00000000..1acf1f3c
--- /dev/null
+++ b/include/VBox/scsi.h
@@ -0,0 +1,339 @@
+/** @file
+ * VirtualBox - SCSI declarations. (DEV,+)
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_scsi_h
+#define VBOX_INCLUDED_scsi_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/assert.h>
+
+/**
+ * @todo: Remove when the splitting code was removed from DevATA.
+ * The limit doesn't belong here but is specific for each host platform.
+ */
+#ifdef RT_OS_FREEBSD
+/* The cam subsystem doesn't allow more */
+# define SCSI_MAX_BUFFER_SIZE (64 * _1K)
+#else
+# define SCSI_MAX_BUFFER_SIZE (100 * _1K)
+#endif
+
+/**
+ * SCSI command opcode identifiers.
+ *
+ * SCSI-3, so far for CD/DVD Logical Units, from Table 49 of the MMC-3 draft standard.
+ */
+typedef enum SCSICMD
+{
+ SCSI_BLANK = 0xa1,
+ SCSI_CLOSE_TRACK_SESSION = 0x5b,
+ SCSI_ERASE_10 = 0x2c,
+ SCSI_FORMAT_UNIT = 0x04,
+ SCSI_GET_CONFIGURATION = 0x46,
+ SCSI_GET_EVENT_STATUS_NOTIFICATION = 0x4a,
+ SCSI_GET_PERFORMANCE = 0xac,
+ /** Inquiry command. */
+ SCSI_INQUIRY = 0x12,
+ SCSI_LOAD_UNLOAD_MEDIUM = 0xa6,
+ SCSI_MECHANISM_STATUS = 0xbd,
+ SCSI_MODE_SELECT_10 = 0x55,
+ SCSI_MODE_SENSE_10 = 0x5a,
+ SCSI_PAUSE_RESUME = 0x4b,
+ SCSI_PLAY_AUDIO_10 = 0x45,
+ SCSI_PLAY_AUDIO_12 = 0xa5,
+ SCSI_PLAY_AUDIO_MSF = 0x47,
+ SCSI_PREVENT_ALLOW_MEDIUM_REMOVAL = 0x1e,
+ /** Read(10) command. */
+ SCSI_READ_10 = 0x28,
+ SCSI_READ_12 = 0xa8,
+ SCSI_READ_BUFFER = 0x3c,
+ SCSI_READ_BUFFER_CAPACITY = 0x5c,
+ /** Read Capacity(6) command. */
+ SCSI_READ_CAPACITY = 0x25,
+ SCSI_READ_CD = 0xbe,
+ SCSI_READ_CD_MSF = 0xb9,
+ SCSI_READ_DISC_INFORMATION = 0x51,
+ SCSI_READ_DVD_STRUCTURE = 0xad,
+ SCSI_READ_FORMAT_CAPACITIES = 0x23,
+ SCSI_READ_SUBCHANNEL = 0x42,
+ SCSI_READ_TOC_PMA_ATIP = 0x43,
+ SCSI_READ_TRACK_INFORMATION = 0x52,
+ SCSI_REPAIR_TRACK = 0x58,
+ SCSI_REPORT_KEY = 0xa4,
+ SCSI_REQUEST_SENSE = 0x03,
+ SCSI_RESERVE_TRACK = 0x53,
+ SCSI_SCAN = 0xba,
+ SCSI_SEEK_10 = 0x2b,
+ SCSI_SEND_CUE_SHEET = 0x5d,
+ SCSI_SEND_DVD_STRUCTURE = 0xbf,
+ SCSI_SEND_EVENT = 0xa2,
+ SCSI_SEND_KEY = 0xa3,
+ SCSI_SEND_OPC_INFORMATION = 0x54,
+ SCSI_SET_CD_SPEED = 0xbb,
+ SCSI_SET_READ_AHEAD = 0xa7,
+ SCSI_SET_STREAMING = 0xb6,
+ SCSI_START_STOP_UNIT = 0x1b,
+ SCSI_LOAD_UNLOAD = 0x1b,
+ SCSI_STOP_PLAY_SCAN = 0x4e,
+ /** Synchronize Cache command. */
+ SCSI_SYNCHRONIZE_CACHE = 0x35,
+ SCSI_TEST_UNIT_READY = 0x00,
+ SCSI_VERIFY_10 = 0x2f,
+ /** Write(10) command. */
+ SCSI_WRITE_10 = 0x2a,
+ SCSI_WRITE_12 = 0xaa,
+ SCSI_WRITE_AND_VERIFY_10 = 0x2e,
+ SCSI_WRITE_BUFFER = 0x3b,
+
+ /** Mode Select(6) command */
+ SCSI_MODE_SELECT_6 = 0x15,
+ /** Mode Sense(6) command */
+ SCSI_MODE_SENSE_6 = 0x1a,
+ /** Report LUNs command. */
+ SCSI_REPORT_LUNS = 0xa0,
+ SCSI_REPORT_DENSITY = 0x44,
+ /** Rezero Unit command. Obsolete for ages now, but used by cdrecord. */
+ SCSI_REZERO_UNIT = 0x01,
+ SCSI_REWIND = 0x01,
+ SCSI_SERVICE_ACTION_IN_16 = 0x9e,
+ SCSI_READ_16 = 0x88,
+ SCSI_WRITE_16 = 0x8a,
+ SCSI_READ_6 = 0x08,
+ SCSI_WRITE_6 = 0x0a,
+ SCSI_LOG_SENSE = 0x4d,
+ SCSI_UNMAP = 0x42,
+ SCSI_RESERVE_6 = 0x16,
+ SCSI_RELEASE_6 = 0x17,
+ SCSI_RESERVE_10 = 0x56,
+ SCSI_RELEASE_10 = 0x57,
+ SCSI_READ_BLOCK_LIMITS = 0x05,
+ SCSI_MAINTENANCE_IN = 0xa3
+} SCSICMD;
+
+/**
+ * Service action in opcode identifiers
+ */
+typedef enum SCSISVCACTIONIN
+{
+ SCSI_SVC_ACTION_IN_READ_CAPACITY_16 = 0x10
+} SCSISVCACTIONIN;
+
+/**
+ * Maintenance in opcode identifiers
+ */
+typedef enum SCSIMAINTENANCEIN
+{
+ SCSI_MAINTENANCE_IN_REPORT_SUPP_OPC = 0x0c
+} SCSIMAINTENANCEIN;
+
+/* Mode page codes for mode sense/select commands. */
+#define SCSI_MODEPAGE_ERROR_RECOVERY 0x01
+#define SCSI_MODEPAGE_WRITE_PARAMETER 0x05
+#define SCSI_MODEPAGE_CD_STATUS 0x2a
+
+
+/* Page control codes. */
+#define SCSI_PAGECONTROL_CURRENT 0x00
+#define SCSI_PAGECONTROL_CHANGEABLE 0x01
+#define SCSI_PAGECONTROL_DEFAULT 0x02
+#define SCSI_PAGECONTROL_SAVED 0x03
+
+
+/* Status codes */
+#define SCSI_STATUS_OK 0x00
+#define SCSI_STATUS_CHECK_CONDITION 0x02
+#define SCSI_STATUS_CONDITION_MET 0x04
+#define SCSI_STATUS_BUSY 0x08
+#define SCSI_STATUS_INTERMEDIATE 0x10
+#define SCSI_STATUS_DATA_UNDEROVER_RUN 0x12
+#define SCSI_STATUS_INTERMEDIATE_CONDITION_MET 0x14
+#define SCSI_STATUS_RESERVATION_CONFLICT 0x18
+#define SCSI_STATUS_COMMAND_TERMINATED 0x22
+#define SCSI_STATUS_QUEUE_FULL 0x28
+#define SCSI_STATUS_ACA_ACTIVE 0x30
+#define SCSI_STATUS_TASK_ABORTED 0x40
+
+/* Sense data response codes - This is the first byte in the sense data */
+#define SCSI_SENSE_RESPONSE_CODE_CURR_FIXED 0x70
+#define SCSI_SENSE_RESPONSE_CODE_DEFERRED_FIXED 0x71
+#define SCSI_SENSE_RESPONSE_CODE_CURR_DESC 0x72
+#define SCSI_SENSE_RESPONSE_CODE_DEFERRED_DESC 0x73
+
+/* Sense keys */
+#define SCSI_SENSE_NONE 0
+#define SCSI_SENSE_RECOVERED_ERROR 1
+#define SCSI_SENSE_NOT_READY 2
+#define SCSI_SENSE_MEDIUM_ERROR 3
+#define SCSI_SENSE_HARDWARE_ERROR 4
+#define SCSI_SENSE_ILLEGAL_REQUEST 5
+#define SCSI_SENSE_UNIT_ATTENTION 6
+#define SCSI_SENSE_DATA_PROTECT 7
+#define SCSI_SENSE_BLANK_CHECK 8
+#define SCSI_SENSE_VENDOR_SPECIFIC 9
+#define SCSI_SENSE_COPY_ABORTED 10
+#define SCSI_SENSE_ABORTED_COMMAND 11
+#define SCSI_SENSE_VOLUME_OVERFLOW 13
+#define SCSI_SENSE_MISCOMPARE 14
+
+/* Additional sense bit flags (to be ORed with sense key). */
+#define SCSI_SENSE_FLAG_FILEMARK 0x80
+#define SCSI_SENSE_FLAG_EOM 0x40
+#define SCSI_SENSE_FLAG_ILI 0x20
+
+/* Additional sense keys */
+#define SCSI_ASC_NONE 0x00
+#define SCSI_ASC_WRITE_ERROR 0x0c
+#define SCSI_ASC_READ_ERROR 0x11
+#define SCSI_ASC_ILLEGAL_OPCODE 0x20
+#define SCSI_ASC_LOGICAL_BLOCK_OOR 0x21
+#define SCSI_ASC_INV_FIELD_IN_CMD_PACKET 0x24
+#define SCSI_ASC_LOGICAL_UNIT_NOT_SUPPORTED 0x25
+#define SCSI_ASC_WRITE_PROTECTED 0x27
+#define SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED 0x28
+#define SCSI_ASC_POWER_ON_RESET_BUS_DEVICE_RESET_OCCURRED 0x29
+#define SCSI_ASC_CANNOT_READ_MEDIUM 0x30
+#define SCSI_ASC_MEDIUM_NOT_PRESENT 0x3a
+#define SCSI_ASC_SAVING_PARAMETERS_NOT_SUPPORTED 0x39
+#define SCSI_ASC_INTERNAL_TARGET_FAILURE 0x44
+#define SCSI_ASC_INVALID_MESSAGE 0x49
+#define SCSI_ASC_MEDIA_LOAD_OR_EJECT_FAILED 0x53
+#define SCSI_ASC_LOGICAL_UNIT_DOES_NOT_RESPOND_TO_SELECTION 0x00
+#define SCSI_ASC_SYSTEM_RESOURCE_FAILURE 0x55
+#define SCSI_ASC_ILLEGAL_MODE_FOR_THIS_TRACK 0x64
+#define SCSI_ASC_COMMAND_TO_LOGICAL_UNIT_FAILED 0x6E
+
+/** Additional sense code qualifiers (ASCQ). */
+/* NB: The ASC/ASCQ combination determines the full meaning. */
+#define SCSI_ASCQ_SYSTEM_BUFFER_FULL 0x01
+#define SCSI_ASCQ_POWER_ON_RESET_BUS_DEVICE_RESET_OCCURRED 0x00
+#define SCSI_ASCQ_END_OF_DATA_DETECTED 0x05
+#define SCSI_ASCQ_FILEMARK_DETECTED 0x01
+#define SCSI_ASCQ_EOP_EOM_DETECTED 0x02
+#define SCSI_ASCQ_SETMARK_DETECTED 0x03
+#define SCSI_ASCQ_BOP_BOM_DETECTED 0x04
+#define SCSI_ASCQ_UNKNOWN_FORMAT 0x01
+#define SCSI_ASCQ_INCOMPATIBLE_FORMAT 0x02
+#define SCSI_ASCQ_COPY_TARGET_DEVICE_DATA_OVERRUN 0x0d
+
+/** @name SCSI_INQUIRY
+ * @{
+ */
+
+/** Length of the SCSI INQUIRY vendor identifier (without termination). */
+#define SCSI_INQUIRY_VENDOR_ID_LENGTH 8
+/** Length of the SCSI INQUIRY product identifier (without termination). */
+#define SCSI_INQUIRY_PRODUCT_ID_LENGTH 16
+/** Length of the SCSI INQUIRY revision identifier (without termination). */
+#define SCSI_INQUIRY_REVISION_LENGTH 4
+
+#pragma pack(1)
+typedef struct SCSIINQUIRYCDB
+{
+ unsigned u8Cmd : 8;
+ unsigned fEVPD : 1;
+ unsigned u4Reserved : 4;
+ unsigned u3LUN : 3;
+ unsigned u8PageCode : 8;
+ unsigned u8Reserved : 8;
+ uint8_t cbAlloc;
+ uint8_t u8Control;
+} SCSIINQUIRYCDB;
+#pragma pack()
+AssertCompileSize(SCSIINQUIRYCDB, 6);
+typedef SCSIINQUIRYCDB *PSCSIINQUIRYCDB;
+typedef const SCSIINQUIRYCDB *PCSCSIINQUIRYCDB;
+
+#pragma pack(1)
+typedef struct SCSIINQUIRYDATA
+{
+ unsigned u5PeripheralDeviceType : 5; /**< 0x00 / 00 */
+ unsigned u3PeripheralQualifier : 3;
+ unsigned u6DeviceTypeModifier : 7; /**< 0x01 */
+ unsigned fRMB : 1;
+ unsigned u3AnsiVersion : 3; /**< 0x02 */
+ unsigned u3EcmaVersion : 3;
+ unsigned u2IsoVersion : 2;
+ unsigned u4ResponseDataFormat : 4; /**< 0x03 */
+ unsigned u2Reserved0 : 2;
+ unsigned fTrmlOP : 1;
+ unsigned fAEC : 1;
+ unsigned cbAdditional : 8; /**< 0x04 */
+ unsigned u8Reserved1 : 8; /**< 0x05 */
+ unsigned u8Reserved2 : 8; /**< 0x06 */
+ unsigned fSftRe : 1; /**< 0x07 */
+ unsigned fCmdQue : 1;
+ unsigned fReserved3 : 1;
+ unsigned fLinked : 1;
+ unsigned fSync : 1;
+ unsigned fWBus16 : 1;
+ unsigned fWBus32 : 1;
+ unsigned fRelAdr : 1;
+ int8_t achVendorId[SCSI_INQUIRY_VENDOR_ID_LENGTH]; /**< 0x08 */
+ int8_t achProductId[SCSI_INQUIRY_PRODUCT_ID_LENGTH]; /**< 0x10 */
+ int8_t achProductLevel[SCSI_INQUIRY_REVISION_LENGTH]; /**< 0x20 */
+ uint8_t abVendorSpecific[20]; /**< 0x24/36 - Optional it seems. */
+ uint8_t abReserved4[40];
+ uint8_t abVendorSpecificParameters[1]; /**< 0x60/96 - Variable size. */
+} SCSIINQUIRYDATA;
+#pragma pack()
+AssertCompileSize(SCSIINQUIRYDATA, 97);
+typedef SCSIINQUIRYDATA *PSCSIINQUIRYDATA;
+typedef const SCSIINQUIRYDATA *PCSCSIINQUIRYDATA;
+
+#define SCSI_INQUIRY_DATA_PERIPHERAL_QUALIFIER_CONNECTED 0x00
+#define SCSI_INQUIRY_DATA_PERIPHERAL_QUALIFIER_NOT_CONNECTED_BUT_SUPPORTED 0x01
+#define SCSI_INQUIRY_DATA_PERIPHERAL_QUALIFIER_NOT_CONNECTED_NOT_SUPPORTED 0x03
+
+#define SCSI_INQUIRY_DATA_PERIPHERAL_DEVICE_TYPE_DIRECT_ACCESS 0x00
+#define SCSI_INQUIRY_DATA_PERIPHERAL_DEVICE_TYPE_SEQUENTIAL_ACCESS 0x01
+#define SCSI_INQUIRY_DATA_PERIPHERAL_DEVICE_TYPE_CD_DVD 0x05
+#define SCSI_INQUIRY_DATA_PERIPHERAL_DEVICE_TYPE_UNKNOWN 0x1f
+
+/** @} */
+
+#if defined(IN_RING3) && (defined(LOG_ENABLED) || defined(RT_STRICT))
+const char * SCSICmdText(uint8_t uCmd);
+const char * SCSIStatusText(uint8_t uStatus);
+const char * SCSISenseText(uint8_t uSense);
+const char * SCSISenseExtText(uint8_t uASC, uint8_t uASCQ);
+int SCSILogModePage(char *pszBuf, size_t cchBuffer, uint8_t *pbModePage,
+ size_t cbModePage);
+int SCSILogCueSheet(char *pszBuf, size_t cchBuffer, uint8_t *pbCueSheet,
+ size_t cbCueSheet);
+#endif
+
+#endif /* !VBOX_INCLUDED_scsi_h */
diff --git a/include/VBox/scsiinline.h b/include/VBox/scsiinline.h
new file mode 100644
index 00000000..c27a1f67
--- /dev/null
+++ b/include/VBox/scsiinline.h
@@ -0,0 +1,246 @@
+/* $Id: scsiinline.h $ */
+/** @file
+ * VirtualBox: SCSI inline helpers used by devices, drivers, etc.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_scsiinline_h
+#define VBOX_INCLUDED_scsiinline_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/stdint.h>
+
+/** @defgroup grp_scsi_inline The SCSI inline helpers
+ * @{
+ */
+
+
+/**
+ * Converts a given 16bit value to big endian and stores it in the given buffer.
+ *
+ * @returns nothing.
+ * @param pbBuf The buffer to store the value into.
+ * @param u16Val The value to store.
+ */
+DECLINLINE(void) scsiH2BE_U16(uint8_t *pbBuf, uint16_t u16Val)
+{
+ pbBuf[0] = u16Val >> 8;
+ pbBuf[1] = u16Val;
+}
+
+
+/**
+ * Converts a given 24bit value to big endian and stores it in the given buffer.
+ *
+ * @returns nothing.
+ * @param pbBuf The buffer to store the value into.
+ * @param u32Val The value to store.
+ */
+DECLINLINE(void) scsiH2BE_U24(uint8_t *pbBuf, uint32_t u32Val)
+{
+ pbBuf[0] = u32Val >> 16;
+ pbBuf[1] = u32Val >> 8;
+ pbBuf[2] = u32Val;
+}
+
+
+/**
+ * Converts a given 32bit value to big endian and stores it in the given buffer.
+ *
+ * @returns nothing.
+ * @param pbBuf The buffer to store the value into.
+ * @param u32Val The value to store.
+ */
+DECLINLINE(void) scsiH2BE_U32(uint8_t *pbBuf, uint32_t u32Val)
+{
+ pbBuf[0] = u32Val >> 24;
+ pbBuf[1] = u32Val >> 16;
+ pbBuf[2] = u32Val >> 8;
+ pbBuf[3] = u32Val;
+}
+
+
+/**
+ * Converts a given 64bit value to big endian and stores it in the given buffer.
+ *
+ * @returns nothing.
+ * @param pbBuf The buffer to store the value into.
+ * @param u64Val The value to store.
+ */
+DECLINLINE(void) scsiH2BE_U64(uint8_t *pbBuf, uint64_t u64Val)
+{
+ pbBuf[0] = u64Val >> 56;
+ pbBuf[1] = u64Val >> 48;
+ pbBuf[2] = u64Val >> 40;
+ pbBuf[3] = u64Val >> 32;
+ pbBuf[4] = u64Val >> 24;
+ pbBuf[5] = u64Val >> 16;
+ pbBuf[6] = u64Val >> 8;
+ pbBuf[7] = u64Val;
+}
+
+/**
+ * Returns a 16bit value read from the given buffer converted to host endianess.
+ *
+ * @returns The converted 16bit value.
+ * @param pbBuf The buffer to read the value from.
+ */
+DECLINLINE(uint16_t) scsiBE2H_U16(const uint8_t *pbBuf)
+{
+ return (pbBuf[0] << 8) | pbBuf[1];
+}
+
+
+/**
+ * Returns a 24bit value read from the given buffer converted to host endianess.
+ *
+ * @returns The converted 24bit value as a 32bit unsigned integer.
+ * @param pbBuf The buffer to read the value from.
+ */
+DECLINLINE(uint32_t) scsiBE2H_U24(const uint8_t *pbBuf)
+{
+ return (pbBuf[0] << 16) | (pbBuf[1] << 8) | pbBuf[2];
+}
+
+
+/**
+ * Returns a 32bit value read from the given buffer converted to host endianess.
+ *
+ * @returns The converted 32bit value.
+ * @param pbBuf The buffer to read the value from.
+ */
+DECLINLINE(uint32_t) scsiBE2H_U32(const uint8_t *pbBuf)
+{
+ return (pbBuf[0] << 24) | (pbBuf[1] << 16) | (pbBuf[2] << 8) | pbBuf[3];
+}
+
+
+/**
+ * Returns a 64bit value read from the given buffer converted to host endianess.
+ *
+ * @returns The converted 64bit value.
+ * @param pbBuf The buffer to read the value from.
+ */
+DECLINLINE(uint64_t) scsiBE2H_U64(const uint8_t *pbBuf)
+{
+ return ((uint64_t)pbBuf[0] << 56)
+ | ((uint64_t)pbBuf[1] << 48)
+ | ((uint64_t)pbBuf[2] << 40)
+ | ((uint64_t)pbBuf[3] << 32)
+ | ((uint64_t)pbBuf[4] << 24)
+ | ((uint64_t)pbBuf[5] << 16)
+ | ((uint64_t)pbBuf[6] << 8)
+ | (uint64_t)pbBuf[7];
+}
+
+
+/**
+ * Converts the given LBA number to the MSF (Minutes:Seconds:Frames) format
+ * and stores it in the given buffer.
+ *
+ * @returns nothing.
+ * @param pbBuf The buffer to store the value into.
+ * @param iLBA The LBA to convert.
+ */
+DECLINLINE(void) scsiLBA2MSF(uint8_t *pbBuf, uint32_t iLBA)
+{
+ iLBA += 150;
+ pbBuf[0] = (iLBA / 75) / 60;
+ pbBuf[1] = (iLBA / 75) % 60;
+ pbBuf[2] = iLBA % 75;
+}
+
+
+/**
+ * Converts a MSF formatted address value read from the given buffer
+ * to an LBA number.
+ *
+ * @returns The LBA number.
+ * @param pbBuf The buffer to read the MSF formatted address
+ * from.
+ */
+DECLINLINE(uint32_t) scsiMSF2LBA(const uint8_t *pbBuf)
+{
+ return (pbBuf[0] * 60 + pbBuf[1]) * 75 + pbBuf[2] - 150;
+}
+
+
+/**
+ * Copies a given string to the given destination padding all unused space
+ * in the destination with spaces.
+ *
+ * @returns nothing.
+ * @param pbDst Where to store the string padded with spaces.
+ * @param pbSrc The string to copy.
+ * @param cbSize Size of the destination buffer.
+ */
+DECLINLINE(void) scsiPadStr(uint8_t *pbDst, const char *pbSrc, uint32_t cbSize)
+{
+ uint32_t i;
+ for (i = 0; i < cbSize; i++)
+ {
+ if (*pbSrc)
+ pbDst[i] = *pbSrc++;
+ else
+ pbDst[i] = ' ';
+ }
+}
+
+
+/**
+ * Copies a given string to the given destination padding all unused space
+ * in the destination with spaces.
+ *
+ * @returns nothing.
+ * @param pbDst Where to store the string padded with spaces.
+ * @param pbSrc The string to copy.
+ * @param cbSize Size of the destination buffer.
+ */
+DECLINLINE(void) scsiPadStrS(int8_t *pbDst, const char *pbSrc, uint32_t cbSize)
+{
+ uint32_t i;
+ for (i = 0; i < cbSize; i++)
+ {
+ if (*pbSrc)
+ pbDst[i] = *pbSrc++;
+ else
+ pbDst[i] = ' ';
+ }
+}
+
+/** @} */
+
+#endif /* !VBOX_INCLUDED_scsiinline_h */
+
diff --git a/include/VBox/settings.h b/include/VBox/settings.h
new file mode 100644
index 00000000..866a9818
--- /dev/null
+++ b/include/VBox/settings.h
@@ -0,0 +1,1539 @@
+/** @file
+ * Settings file data structures.
+ *
+ * These structures are created by the settings file loader and filled with values
+ * copied from the raw XML data. This was all new with VirtualBox 3.1 and allows us
+ * to finally make the XML reader version-independent and read VirtualBox XML files
+ * from earlier and even newer (future) versions without requiring complicated,
+ * tedious and error-prone XSLT conversions.
+ *
+ * It is this file that defines all structures that map VirtualBox global and
+ * machine settings to XML files. These structures are used by the rest of Main,
+ * even though this header file does not require anything else in Main.
+ *
+ * Note: Headers in Main code have been tweaked to only declare the structures
+ * defined here so that this header need only be included from code files that
+ * actually use these structures.
+ */
+
+/*
+ * Copyright (C) 2007-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_settings_h
+#define VBOX_INCLUDED_settings_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/time.h>
+
+#include "VBox/com/VirtualBox.h"
+
+#include <VBox/com/Guid.h>
+#include <VBox/com/string.h>
+#include <VBox/VBoxCryptoIf.h>
+
+#include <list>
+#include <map>
+#include <vector>
+
+/**
+ * Maximum depth of a medium tree, to prevent stack overflows.
+ * XPCOM has a relatively low stack size for its workers, and we have
+ * to avoid crashes due to exceeding the limit both on reading and
+ * writing config files. The bottleneck is in libxml2.
+ * Data point: a release and asan build could both handle 3800 on Debian 10.
+ */
+#define SETTINGS_MEDIUM_DEPTH_MAX 300
+
+/**
+ * Maximum depth of the snapshot tree, to prevent stack overflows.
+ * XPCOM has a relatively low stack size for its workers, and we have
+ * to avoid crashes due to exceeding the limit both on reading and
+ * writing config files. The bottleneck is reading config files with
+ * deep snapshot nesting, as libxml2 needs quite some stack space.
+ * Data point: a release and asan build could both handle 1300 on Debian 10.
+ */
+#define SETTINGS_SNAPSHOT_DEPTH_MAX 250
+
+namespace xml
+{
+ class ElementNode;
+}
+
+namespace settings
+{
+
+class ConfigFileError;
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Structures shared between Machine XML and VirtualBox.xml
+//
+////////////////////////////////////////////////////////////////////////////////
+
+typedef std::map<com::Utf8Str, com::Utf8Str> StringsMap;
+typedef std::list<com::Utf8Str> StringsList;
+
+/**
+ * USB device filter definition. This struct is used both in MainConfigFile
+ * (for global USB filters) and MachineConfigFile (for machine filters).
+ *
+ * NOTE: If you add any fields in here, you must update a) the constructor and b)
+ * the operator== which is used by MachineConfigFile::operator==(), or otherwise
+ * your settings might never get saved.
+ */
+struct USBDeviceFilter
+{
+ USBDeviceFilter();
+
+ bool operator==(const USBDeviceFilter&u) const;
+
+ com::Utf8Str strName;
+ bool fActive;
+ com::Utf8Str strVendorId,
+ strProductId,
+ strRevision,
+ strManufacturer,
+ strProduct,
+ strSerialNumber,
+ strPort;
+ USBDeviceFilterAction_T action; // only used with host USB filters
+ com::Utf8Str strRemote; // irrelevant for host USB objects
+ uint32_t ulMaskedInterfaces; // irrelevant for host USB objects
+};
+
+typedef std::list<USBDeviceFilter> USBDeviceFiltersList;
+
+struct Medium;
+typedef std::list<Medium> MediaList;
+
+/**
+ * NOTE: If you add any fields in here, you must update a) the constructor and b)
+ * the operator== which is used by MachineConfigFile::operator==(), or otherwise
+ * your settings might never get saved.
+ */
+struct Medium
+{
+ Medium();
+
+ bool operator==(const Medium &m) const;
+
+ com::Guid uuid;
+ com::Utf8Str strLocation;
+ com::Utf8Str strDescription;
+
+ // the following are for hard disks only:
+ com::Utf8Str strFormat;
+ bool fAutoReset; // optional, only for diffs, default is false
+ StringsMap properties;
+ MediumType_T hdType;
+
+ MediaList llChildren; // only used with hard disks
+
+ static const struct Medium Empty;
+};
+
+/**
+ * A media registry. Starting with VirtualBox 3.3, this can appear in both the
+ * VirtualBox.xml file as well as machine XML files with settings version 1.11
+ * or higher, so these lists are now in ConfigFileBase.
+ *
+ * NOTE: If you add any fields in here, you must update a) the constructor and b)
+ * the operator== which is used by MachineConfigFile::operator==(), or otherwise
+ * your settings might never get saved.
+ */
+struct MediaRegistry
+{
+ bool operator==(const MediaRegistry &m) const;
+
+ MediaList llHardDisks,
+ llDvdImages,
+ llFloppyImages;
+};
+
+/**
+ * NOTE: If you add any fields in here, you must update a) the constructor and b)
+ * the operator== which is used by MachineConfigFile::operator==(), or otherwise
+ * your settings might never get saved.
+ */
+struct NATRule
+{
+ NATRule();
+
+ bool operator==(const NATRule &r) const;
+
+ com::Utf8Str strName;
+ NATProtocol_T proto;
+ uint16_t u16HostPort;
+ com::Utf8Str strHostIP;
+ uint16_t u16GuestPort;
+ com::Utf8Str strGuestIP;
+};
+typedef std::map<com::Utf8Str, NATRule> NATRulesMap;
+
+struct NATHostLoopbackOffset
+{
+ NATHostLoopbackOffset();
+
+ bool operator==(const NATHostLoopbackOffset &o) const;
+
+ bool operator==(const com::Utf8Str& strAddr)
+ {
+ return strLoopbackHostAddress == strAddr;
+ }
+
+ bool operator==(uint32_t off)
+ {
+ return u32Offset == off;
+ }
+
+ /** Note: 128/8 is only acceptable */
+ com::Utf8Str strLoopbackHostAddress;
+ uint32_t u32Offset;
+};
+
+typedef std::list<NATHostLoopbackOffset> NATLoopbackOffsetList;
+
+typedef std::vector<uint8_t> IconBlob;
+
+/**
+ * Common base class for both MainConfigFile and MachineConfigFile
+ * which contains some common logic for both.
+ */
+class ConfigFileBase
+{
+public:
+ bool fileExists();
+ SettingsVersion_T getSettingsVersion();
+
+ void copyBaseFrom(const ConfigFileBase &b);
+
+protected:
+ ConfigFileBase(const com::Utf8Str *pstrFilename);
+ /* Note: this copy constructor doesn't create a full copy of other, cause
+ * the file based stuff (xml doc) could not be copied. */
+ ConfigFileBase(const ConfigFileBase &other);
+
+ ~ConfigFileBase();
+
+ typedef enum {Error, HardDisk, DVDImage, FloppyImage} MediaType;
+
+ static const char *stringifyMediaType(MediaType t);
+ SettingsVersion_T parseVersion(const com::Utf8Str &strVersion,
+ const xml::ElementNode *pElm);
+ void parseUUID(com::Guid &guid,
+ const com::Utf8Str &strUUID,
+ const xml::ElementNode *pElm) const;
+ void parseTimestamp(RTTIMESPEC &timestamp,
+ const com::Utf8Str &str,
+ const xml::ElementNode *pElm) const;
+ void parseBase64(IconBlob &binary,
+ const com::Utf8Str &str,
+ const xml::ElementNode *pElm) const;
+ com::Utf8Str stringifyTimestamp(const RTTIMESPEC &tm) const;
+ void toBase64(com::Utf8Str &str,
+ const IconBlob &binary) const;
+
+ void readExtraData(const xml::ElementNode &elmExtraData,
+ StringsMap &map);
+ void readUSBDeviceFilters(const xml::ElementNode &elmDeviceFilters,
+ USBDeviceFiltersList &ll);
+ void readMediumOne(MediaType t, const xml::ElementNode &elmMedium, Medium &med);
+ void readMedium(MediaType t, const xml::ElementNode &elmMedium, Medium &med);
+ void readMediaRegistry(const xml::ElementNode &elmMediaRegistry, MediaRegistry &mr);
+ void readNATForwardRulesMap(const xml::ElementNode &elmParent, NATRulesMap &mapRules);
+ void readNATLoopbacks(const xml::ElementNode &elmParent, NATLoopbackOffsetList &llLoopBacks);
+
+ void setVersionAttribute(xml::ElementNode &elm);
+ void specialBackupIfFirstBump();
+ void createStubDocument();
+
+ void buildExtraData(xml::ElementNode &elmParent, const StringsMap &me);
+ void buildUSBDeviceFilters(xml::ElementNode &elmParent,
+ const USBDeviceFiltersList &ll,
+ bool fHostMode);
+ void buildMedium(MediaType t,
+ xml::ElementNode &elmMedium,
+ const Medium &med);
+ void buildMediaRegistry(xml::ElementNode &elmParent,
+ const MediaRegistry &mr);
+ void buildNATForwardRulesMap(xml::ElementNode &elmParent, const NATRulesMap &mapRules);
+ void buildNATLoopbacks(xml::ElementNode &elmParent, const NATLoopbackOffsetList &natLoopbackList);
+ void clearDocument();
+
+ struct Data;
+ Data *m;
+
+ friend class ConfigFileError;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// VirtualBox.xml structures
+//
+////////////////////////////////////////////////////////////////////////////////
+
+struct USBDeviceSource
+{
+ com::Utf8Str strName;
+ com::Utf8Str strBackend;
+ com::Utf8Str strAddress;
+ StringsMap properties;
+};
+
+typedef std::list<USBDeviceSource> USBDeviceSourcesList;
+
+#ifdef VBOX_WITH_UPDATE_AGENT
+struct UpdateAgent
+{
+ UpdateAgent();
+
+ bool fEnabled;
+ UpdateChannel_T enmChannel;
+ uint32_t uCheckFreqSeconds;
+ com::Utf8Str strRepoUrl;
+ com::Utf8Str strLastCheckDate;
+ uint32_t uCheckCount;
+};
+#endif /* VBOX_WITH_UPDATE_AGENT */
+
+struct Host
+{
+ USBDeviceFiltersList llUSBDeviceFilters;
+ USBDeviceSourcesList llUSBDeviceSources;
+#ifdef VBOX_WITH_UPDATE_AGENT
+ UpdateAgent updateHost;
+ /** @todo Add handling for ExtPack and Guest Additions updates here later. See @bugref{7983}. */
+#endif /* VBOX_WITH_UPDATE_AGENT */
+};
+
+struct SystemProperties
+{
+ SystemProperties();
+
+ com::Utf8Str strDefaultMachineFolder;
+ com::Utf8Str strDefaultHardDiskFolder;
+ com::Utf8Str strDefaultHardDiskFormat;
+ com::Utf8Str strVRDEAuthLibrary;
+ com::Utf8Str strWebServiceAuthLibrary;
+ com::Utf8Str strDefaultVRDEExtPack;
+ com::Utf8Str strDefaultCryptoExtPack;
+ com::Utf8Str strAutostartDatabasePath;
+ com::Utf8Str strDefaultAdditionsISO;
+ com::Utf8Str strDefaultFrontend;
+ com::Utf8Str strLoggingLevel;
+ com::Utf8Str strProxyUrl;
+ uint32_t uProxyMode; /**< ProxyMode_T */
+ uint32_t uLogHistoryCount;
+ bool fExclusiveHwVirt;
+ com::Utf8Str strLanguageId;
+};
+
+struct MachineRegistryEntry
+{
+ com::Guid uuid;
+ com::Utf8Str strSettingsFile;
+};
+
+typedef std::list<MachineRegistryEntry> MachinesRegistry;
+
+struct DhcpOptValue
+{
+ DhcpOptValue();
+ DhcpOptValue(const com::Utf8Str &aText, DHCPOptionEncoding_T aEncoding = DHCPOptionEncoding_Normal);
+
+ com::Utf8Str strValue;
+ DHCPOptionEncoding_T enmEncoding;
+};
+
+typedef std::map<DHCPOption_T, DhcpOptValue> DhcpOptionMap;
+typedef DhcpOptionMap::value_type DhcpOptValuePair;
+typedef DhcpOptionMap::iterator DhcpOptIterator;
+typedef DhcpOptionMap::const_iterator DhcpOptConstIterator;
+
+struct DHCPGroupCondition
+{
+ DHCPGroupCondition();
+
+ bool fInclusive;
+ DHCPGroupConditionType_T enmType;
+ com::Utf8Str strValue;
+};
+typedef std::vector<DHCPGroupCondition> DHCPGroupConditionVec;
+
+
+struct DHCPConfig
+{
+ DHCPConfig();
+
+ DhcpOptionMap mapOptions;
+ uint32_t secMinLeaseTime;
+ uint32_t secDefaultLeaseTime;
+ uint32_t secMaxLeaseTime;
+ com::Utf8Str strForcedOptions;
+ com::Utf8Str strSuppressedOptions;
+};
+
+struct DHCPGroupConfig : DHCPConfig
+{
+ DHCPGroupConfig();
+
+ com::Utf8Str strName;
+ DHCPGroupConditionVec vecConditions;
+};
+typedef std::vector<DHCPGroupConfig> DHCPGroupConfigVec;
+
+struct DHCPIndividualConfig : DHCPConfig
+{
+ DHCPIndividualConfig();
+
+ com::Utf8Str strMACAddress;
+ com::Utf8Str strVMName;
+ uint32_t uSlot;
+ com::Utf8Str strFixedAddress;
+};
+typedef std::map<com::Utf8Str, DHCPIndividualConfig> DHCPIndividualConfigMap;
+
+struct DHCPServer
+{
+ DHCPServer();
+
+ com::Utf8Str strNetworkName;
+ com::Utf8Str strIPAddress;
+ com::Utf8Str strIPLower;
+ com::Utf8Str strIPUpper;
+ bool fEnabled;
+ DHCPConfig globalConfig;
+ DHCPGroupConfigVec vecGroupConfigs;
+ DHCPIndividualConfigMap mapIndividualConfigs;
+};
+typedef std::list<DHCPServer> DHCPServersList;
+
+
+/**
+ * NAT Networking settings (NAT service).
+ */
+struct NATNetwork
+{
+ NATNetwork();
+
+ com::Utf8Str strNetworkName;
+ com::Utf8Str strIPv4NetworkCidr;
+ com::Utf8Str strIPv6Prefix;
+ bool fEnabled;
+ bool fIPv6Enabled;
+ bool fAdvertiseDefaultIPv6Route;
+ bool fNeedDhcpServer;
+ uint32_t u32HostLoopback6Offset;
+ NATLoopbackOffsetList llHostLoopbackOffsetList;
+ NATRulesMap mapPortForwardRules4;
+ NATRulesMap mapPortForwardRules6;
+};
+
+typedef std::list<NATNetwork> NATNetworksList;
+
+#ifdef VBOX_WITH_VMNET
+/**
+ * HostOnly Networking settings.
+ */
+struct HostOnlyNetwork
+{
+ HostOnlyNetwork();
+
+ com::Guid uuid;
+ com::Utf8Str strNetworkName;
+ com::Utf8Str strNetworkMask;
+ com::Utf8Str strIPLower;
+ com::Utf8Str strIPUpper;
+ bool fEnabled;
+};
+
+typedef std::list<HostOnlyNetwork> HostOnlyNetworksList;
+#endif /* VBOX_WITH_VMNET */
+
+#ifdef VBOX_WITH_CLOUD_NET
+/**
+ * Cloud Networking settings.
+ */
+struct CloudNetwork
+{
+ CloudNetwork();
+
+ com::Utf8Str strNetworkName;
+ com::Utf8Str strProviderShortName;
+ com::Utf8Str strProfileName;
+ com::Utf8Str strNetworkId;
+ bool fEnabled;
+};
+
+typedef std::list<CloudNetwork> CloudNetworksList;
+#endif /* VBOX_WITH_CLOUD_NET */
+
+
+class MainConfigFile : public ConfigFileBase
+{
+public:
+ MainConfigFile(const com::Utf8Str *pstrFilename);
+
+ void readMachineRegistry(const xml::ElementNode &elmMachineRegistry);
+ void readNATNetworks(const xml::ElementNode &elmNATNetworks);
+#ifdef VBOX_WITH_VMNET
+ void readHostOnlyNetworks(const xml::ElementNode &elmHostOnlyNetworks);
+#endif /* VBOX_WITH_VMNET */
+#ifdef VBOX_WITH_CLOUD_NET
+ void readCloudNetworks(const xml::ElementNode &elmCloudNetworks);
+#endif /* VBOX_WITH_CLOUD_NET */
+
+ void write(const com::Utf8Str strFilename);
+
+ Host host;
+ SystemProperties systemProperties;
+ MediaRegistry mediaRegistry;
+ MachinesRegistry llMachines;
+ DHCPServersList llDhcpServers;
+ NATNetworksList llNATNetworks;
+#ifdef VBOX_WITH_VMNET
+ HostOnlyNetworksList llHostOnlyNetworks;
+#endif /* VBOX_WITH_VMNET */
+#ifdef VBOX_WITH_CLOUD_NET
+ CloudNetworksList llCloudNetworks;
+#endif /* VBOX_WITH_CLOUD_NET */
+ StringsMap mapExtraDataItems;
+
+private:
+ void bumpSettingsVersionIfNeeded();
+ void buildUSBDeviceSources(xml::ElementNode &elmParent, const USBDeviceSourcesList &ll);
+ void readUSBDeviceSources(const xml::ElementNode &elmDeviceSources, USBDeviceSourcesList &ll);
+ void buildDHCPServers(xml::ElementNode &elmDHCPServers, DHCPServersList const &ll);
+ void buildDHCPOptions(xml::ElementNode &elmOptions, DHCPConfig const &rConfig, bool fIgnoreSubnetMask);
+ void readDHCPServers(const xml::ElementNode &elmDHCPServers);
+ void readDHCPOptions(DHCPConfig &rConfig, const xml::ElementNode &elmOptions, bool fIgnoreSubnetMask);
+ bool convertGuiProxySettings(const com::Utf8Str &strUIProxySettings);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Machine XML structures
+//
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * NOTE: If you add any fields in here, you must update a) the constructor and b)
+ * the operator== which is used by MachineConfigFile::operator==(), or otherwise
+ * your settings might never get saved.
+ */
+struct VRDESettings
+{
+ VRDESettings();
+
+ bool areDefaultSettings(SettingsVersion_T sv) const;
+
+ bool operator==(const VRDESettings& v) const;
+
+ bool fEnabled;
+ AuthType_T authType;
+ uint32_t ulAuthTimeout;
+ com::Utf8Str strAuthLibrary;
+ bool fAllowMultiConnection,
+ fReuseSingleConnection;
+ com::Utf8Str strVrdeExtPack;
+ StringsMap mapProperties;
+};
+
+/**
+ * NOTE: If you add any fields in here, you must update a) the constructor and b)
+ * the operator== which is used by MachineConfigFile::operator==(), or otherwise
+ * your settings might never get saved.
+ */
+struct BIOSSettings
+{
+ BIOSSettings();
+
+ bool areDefaultSettings() const;
+
+ bool operator==(const BIOSSettings &d) const;
+
+ bool fACPIEnabled,
+ fIOAPICEnabled,
+ fLogoFadeIn,
+ fLogoFadeOut,
+ fPXEDebugEnabled,
+ fSmbiosUuidLittleEndian;
+ uint32_t ulLogoDisplayTime;
+ BIOSBootMenuMode_T biosBootMenuMode;
+ APICMode_T apicMode; // requires settings version 1.16 (VirtualBox 5.1)
+ int64_t llTimeOffset;
+ com::Utf8Str strLogoImagePath;
+};
+
+/**
+ * NOTE: If you add any fields in here, you must update a) the constructor and b)
+ * the operator== which is used by MachineConfigFile::operator==(), or otherwise
+ * your settings might never get saved.
+ */
+struct TpmSettings
+{
+ TpmSettings();
+
+ bool areDefaultSettings() const;
+
+ bool operator==(const TpmSettings &d) const;
+
+ TpmType_T tpmType;
+ com::Utf8Str strLocation;
+};
+
+/**
+ * NOTE: If you add any fields in here, you must update a) the constructor and b)
+ * the operator== which is used by MachineConfigFile::operator==(), or otherwise
+ * your settings might never get saved.
+ */
+struct NvramSettings
+{
+ NvramSettings();
+
+ bool areDefaultSettings() const;
+
+ bool operator==(const NvramSettings &d) const;
+
+ com::Utf8Str strNvramPath;
+ com::Utf8Str strKeyId;
+ com::Utf8Str strKeyStore;
+};
+
+/** List for keeping a recording feature list. */
+typedef std::map<RecordingFeature_T, bool> RecordingFeatureMap;
+
+/**
+ * Recording settings for a single screen (e.g. virtual monitor).
+ *
+ * NOTE: If you add any fields in here, you must update a) the constructor and b)
+ * the operator== which is used by MachineConfigFile::operator==(), or otherwise
+ * your settings might never get saved.
+ */
+struct RecordingScreenSettings
+{
+ RecordingScreenSettings(uint32_t idScreen = UINT32_MAX);
+
+ virtual ~RecordingScreenSettings();
+
+ void applyDefaults(void);
+
+ bool areDefaultSettings(void) const;
+
+ bool isFeatureEnabled(RecordingFeature_T enmFeature) const;
+
+ static const char *getDefaultOptions(void);
+
+ static int featuresFromString(const com::Utf8Str &strFeatures, RecordingFeatureMap &featureMap);
+
+ static void featuresToString(const RecordingFeatureMap &featureMap, com::Utf8Str &strFeatures);
+
+ static int audioCodecFromString(const com::Utf8Str &strCodec, RecordingAudioCodec_T &enmCodec);
+
+ static void audioCodecToString(const RecordingAudioCodec_T &enmCodec, com::Utf8Str &strCodec);
+
+ static int videoCodecFromString(const com::Utf8Str &strCodec, RecordingVideoCodec_T &enmCodec);
+
+ static void videoCodecToString(const RecordingVideoCodec_T &enmCodec, com::Utf8Str &strCodec);
+
+ bool operator==(const RecordingScreenSettings &d) const;
+
+ /** Screen ID.
+ * UINT32_MAX if not set. */
+ uint32_t idScreen;
+ /** Whether to record this screen or not. */
+ bool fEnabled; // requires settings version 1.14 (VirtualBox 4.3)
+ /** Destination to record to. */
+ RecordingDestination_T enmDest;
+ /** Which features are enable or not. */
+ RecordingFeatureMap featureMap; // requires settings version 1.19 (VirtualBox 7.0)
+ /** Maximum time (in s) to record. If set to 0, no time limit is set. */
+ uint32_t ulMaxTimeS; // requires settings version 1.14 (VirtualBox 4.3)
+ /** Options string for hidden / advanced / experimental features.
+ * Use RecordingScreenSettings::getDefaultOptions(). */
+ com::Utf8Str strOptions; // new since VirtualBox 5.2.
+
+ /**
+ * Structure holding settings for audio recording.
+ */
+ struct Audio
+ {
+ /** The audio codec type to use. */
+ RecordingAudioCodec_T enmCodec; // requires settings version 1.19 (VirtualBox 7.0)
+ /** Codec deadline to use. */
+ RecordingCodecDeadline_T enmDeadline; // requires settings version 1.19 (VirtualBox 7.0)
+ /** Rate control mode to use. */
+ RecordingRateControlMode_T
+ enmRateCtlMode;// requires settings version 1.19 (VirtualBox 7.0)
+ /** Hz rate. */
+ uint16_t uHz; // requires settings version 1.19 (VirtualBox 7.0)
+ /** Bits per sample. */
+ uint8_t cBits; // requires settings version 1.19 (VirtualBox 7.0)
+ /** Number of audio channels. */
+ uint8_t cChannels; // requires settings version 1.19 (VirtualBox 7.0)
+ } Audio;
+
+ /**
+ * Structure holding settings for video recording.
+ */
+ struct Video
+ {
+ /** The codec to use. */
+ RecordingVideoCodec_T enmCodec; // requires settings version 1.19 (VirtualBox 7.0)
+ /** Codec deadline to use. */
+ RecordingCodecDeadline_T enmDeadline; // requires settings version 1.19 (VirtualBox 7.0)
+ /** Rate control mode to use. */
+ RecordingRateControlMode_T
+ enmRateCtlMode; // requires settings version 1.19 (VirtualBox 7.0)
+ /** Rate control mode to use. */
+ RecordingVideoScalingMode_T
+ enmScalingMode; // requires settings version 1.19 (VirtualBox 7.0)
+ /** Target frame width in pixels (X). */
+ uint32_t ulWidth; // requires settings version 1.14 (VirtualBox 4.3)
+ /** Target frame height in pixels (Y). */
+ uint32_t ulHeight; // requires settings version 1.14 (VirtualBox 4.3)
+ /** Encoding rate. */
+ uint32_t ulRate; // requires settings version 1.14 (VirtualBox 4.3)
+ /** Frames per second (FPS). */
+ uint32_t ulFPS; // requires settings version 1.14 (VirtualBox 4.3)
+ } Video;
+
+ /**
+ * Structure holding settings if the destination is a file.
+ */
+ struct File
+ {
+ /** Maximum size (in MB) the file is allowed to have.
+ * When reaching the limit, recording will stop. 0 means no limit. */
+ uint32_t ulMaxSizeMB; // requires settings version 1.14 (VirtualBox 4.3)
+ /** Absolute file name path to use for recording.
+ * When empty, this is considered as being the default setting. */
+ com::Utf8Str strName; // requires settings version 1.14 (VirtualBox 4.3)
+ } File;
+};
+
+/** Map for keeping settings per virtual screen.
+ * The key specifies the screen ID. */
+typedef std::map<uint32_t, RecordingScreenSettings> RecordingScreenSettingsMap;
+
+/**
+ * Common recording settings, shared among all per-screen recording settings.
+ *
+ * NOTE: If you add any fields in here, you must update a) the constructor and b)
+ * the operator== which is used by MachineConfigFile::operator==(), or otherwise
+ * your settings might never get saved.
+ */
+struct RecordingCommonSettings
+{
+ RecordingCommonSettings();
+
+ void applyDefaults(void);
+
+ bool areDefaultSettings(void) const;
+
+ bool operator==(const RecordingCommonSettings &d) const;
+
+ /** Whether recording as a whole is enabled or disabled. */
+ bool fEnabled; // requires settings version 1.14 (VirtualBox 4.3)
+};
+
+/**
+ * NOTE: If you add any fields in here, you must update a) the constructor and b)
+ * the operator== which is used by MachineConfigFile::operator==(), or otherwise
+ * your settings might never get saved.
+ */
+struct RecordingSettings
+{
+ RecordingSettings();
+
+ void applyDefaults(void);
+
+ bool areDefaultSettings(void) const;
+
+ bool operator==(const RecordingSettings &that) const;
+
+ /** Common settings for all per-screen recording settings. */
+ RecordingCommonSettings common;
+ /** Map of handled recording screen settings.
+ * The key specifies the screen ID. */
+ RecordingScreenSettingsMap mapScreens;
+};
+
+/**
+ * NOTE: If you add any fields in here, you must update a) the constructor and b)
+ * the operator== which is used by MachineConfigFile::operator==(), or otherwise
+ * your settings might never get saved.
+ */
+struct GraphicsAdapter
+{
+ GraphicsAdapter();
+
+ bool areDefaultSettings() const;
+
+ bool operator==(const GraphicsAdapter &g) const;
+
+ GraphicsControllerType_T graphicsControllerType;
+ uint32_t ulVRAMSizeMB;
+ uint32_t cMonitors;
+ bool fAccelerate3D,
+ fAccelerate2DVideo; // requires settings version 1.8 (VirtualBox 3.1)
+};
+
+/**
+ * NOTE: If you add any fields in here, you must update a) the constructor and b)
+ * the operator== which is used by MachineConfigFile::operator==(), or otherwise
+ * your settings might never get saved.
+ */
+struct USBController
+{
+ USBController();
+
+ bool operator==(const USBController &u) const;
+
+ com::Utf8Str strName;
+ USBControllerType_T enmType;
+};
+
+typedef std::list<USBController> USBControllerList;
+
+struct USB
+{
+ USB();
+
+ bool operator==(const USB &u) const;
+
+ /** List of USB controllers present. */
+ USBControllerList llUSBControllers;
+ /** List of USB device filters. */
+ USBDeviceFiltersList llDeviceFilters;
+};
+
+struct NAT
+{
+ NAT();
+
+ bool areDNSDefaultSettings() const;
+ bool areAliasDefaultSettings() const;
+ bool areTFTPDefaultSettings() const;
+ bool areLocalhostReachableDefaultSettings(SettingsVersion_T sv) const;
+ bool areDefaultSettings(SettingsVersion_T sv) const;
+
+ bool operator==(const NAT &n) const;
+
+ com::Utf8Str strNetwork;
+ com::Utf8Str strBindIP;
+ uint32_t u32Mtu;
+ uint32_t u32SockRcv;
+ uint32_t u32SockSnd;
+ uint32_t u32TcpRcv;
+ uint32_t u32TcpSnd;
+ com::Utf8Str strTFTPPrefix;
+ com::Utf8Str strTFTPBootFile;
+ com::Utf8Str strTFTPNextServer;
+ bool fDNSPassDomain;
+ bool fDNSProxy;
+ bool fDNSUseHostResolver;
+ bool fAliasLog;
+ bool fAliasProxyOnly;
+ bool fAliasUseSamePorts;
+ bool fLocalhostReachable;
+ NATRulesMap mapRules;
+};
+
+/**
+ * NOTE: If you add any fields in here, you must update a) the constructor and b)
+ * the operator== which is used by MachineConfigFile::operator==(), or otherwise
+ * your settings might never get saved.
+ */
+struct NetworkAdapter
+{
+ NetworkAdapter();
+
+ bool areGenericDriverDefaultSettings() const;
+ bool areDefaultSettings(SettingsVersion_T sv) const;
+ bool areDisabledDefaultSettings(SettingsVersion_T sv) const;
+
+ bool operator==(const NetworkAdapter &n) const;
+
+ uint32_t ulSlot;
+
+ NetworkAdapterType_T type;
+ bool fEnabled;
+ com::Utf8Str strMACAddress;
+ bool fCableConnected;
+ uint32_t ulLineSpeed;
+ NetworkAdapterPromiscModePolicy_T enmPromiscModePolicy;
+ bool fTraceEnabled;
+ com::Utf8Str strTraceFile;
+
+ NetworkAttachmentType_T mode;
+ NAT nat;
+ com::Utf8Str strBridgedName;
+ com::Utf8Str strHostOnlyName;
+#ifdef VBOX_WITH_VMNET
+ com::Utf8Str strHostOnlyNetworkName;
+#endif /* VBOX_WITH_VMNET */
+ com::Utf8Str strInternalNetworkName;
+ com::Utf8Str strGenericDriver;
+ StringsMap genericProperties;
+ com::Utf8Str strNATNetworkName;
+#ifdef VBOX_WITH_CLOUD_NET
+ com::Utf8Str strCloudNetworkName;
+#endif /* VBOX_WITH_CLOUD_NET */
+ uint32_t ulBootPriority;
+ com::Utf8Str strBandwidthGroup; // requires settings version 1.13 (VirtualBox 4.2)
+};
+
+typedef std::list<NetworkAdapter> NetworkAdaptersList;
+
+/**
+ * NOTE: If you add any fields in here, you must update a) the constructor and b)
+ * the operator== which is used by MachineConfigFile::operator==(), or otherwise
+ * your settings might never get saved.
+ */
+struct SerialPort
+{
+ SerialPort();
+
+ bool operator==(const SerialPort &n) const;
+
+ uint32_t ulSlot;
+
+ bool fEnabled;
+ uint32_t ulIOBase;
+ uint32_t ulIRQ;
+ PortMode_T portMode;
+ com::Utf8Str strPath;
+ bool fServer;
+ UartType_T uartType;
+};
+
+typedef std::list<SerialPort> SerialPortsList;
+
+/**
+ * NOTE: If you add any fields in here, you must update a) the constructor and b)
+ * the operator== which is used by MachineConfigFile::operator==(), or otherwise
+ * your settings might never get saved.
+ */
+struct ParallelPort
+{
+ ParallelPort();
+
+ bool operator==(const ParallelPort &d) const;
+
+ uint32_t ulSlot;
+
+ bool fEnabled;
+ uint32_t ulIOBase;
+ uint32_t ulIRQ;
+ com::Utf8Str strPath;
+};
+
+typedef std::list<ParallelPort> ParallelPortsList;
+
+/**
+ * NOTE: If you add any fields in here, you must update a) the constructor and b)
+ * the operator== which is used by MachineConfigFile::operator==(), or otherwise
+ * your settings might never get saved.
+ */
+struct AudioAdapter
+{
+ AudioAdapter();
+
+ bool areDefaultSettings(SettingsVersion_T sv) const;
+
+ bool operator==(const AudioAdapter &a) const;
+
+ bool fEnabled;
+ bool fEnabledIn;
+ bool fEnabledOut;
+ AudioControllerType_T controllerType;
+ AudioCodecType_T codecType;
+ AudioDriverType_T driverType;
+ settings::StringsMap properties;
+};
+
+/**
+ * NOTE: If you add any fields in here, you must update a) the constructor and b)
+ * the operator== which is used by MachineConfigFile::operator==(), or otherwise
+ * your settings might never get saved.
+ */
+struct SharedFolder
+{
+ SharedFolder();
+
+ bool operator==(const SharedFolder &a) const;
+
+ com::Utf8Str strName,
+ strHostPath;
+ bool fWritable;
+ bool fAutoMount;
+ com::Utf8Str strAutoMountPoint;
+};
+
+typedef std::list<SharedFolder> SharedFoldersList;
+
+/**
+ * NOTE: If you add any fields in here, you must update a) the constructor and b)
+ * the operator== which is used by MachineConfigFile::operator==(), or otherwise
+ * your settings might never get saved.
+ */
+struct GuestProperty
+{
+ GuestProperty();
+
+ bool operator==(const GuestProperty &g) const;
+
+ com::Utf8Str strName,
+ strValue;
+ uint64_t timestamp;
+ com::Utf8Str strFlags;
+};
+
+typedef std::list<GuestProperty> GuestPropertiesList;
+
+typedef std::map<uint32_t, DeviceType_T> BootOrderMap;
+
+/**
+ * NOTE: If you add any fields in here, you must update a) the constructor and b)
+ * the operator== which is used by MachineConfigFile::operator==(), or otherwise
+ * your settings might never get saved.
+ */
+struct CpuIdLeaf
+{
+ CpuIdLeaf();
+
+ bool operator==(const CpuIdLeaf &c) const;
+
+ uint32_t idx;
+ uint32_t idxSub;
+ uint32_t uEax;
+ uint32_t uEbx;
+ uint32_t uEcx;
+ uint32_t uEdx;
+};
+
+typedef std::list<CpuIdLeaf> CpuIdLeafsList;
+
+/**
+ * NOTE: If you add any fields in here, you must update a) the constructor and b)
+ * the operator== which is used by MachineConfigFile::operator==(), or otherwise
+ * your settings might never get saved.
+ */
+struct Cpu
+{
+ Cpu();
+
+ bool operator==(const Cpu &c) const;
+
+ uint32_t ulId;
+};
+
+typedef std::list<Cpu> CpuList;
+
+/**
+ * NOTE: If you add any fields in here, you must update a) the constructor and b)
+ * the operator== which is used by MachineConfigFile::operator==(), or otherwise
+ * your settings might never get saved.
+ */
+struct BandwidthGroup
+{
+ BandwidthGroup();
+
+ bool operator==(const BandwidthGroup &i) const;
+
+ com::Utf8Str strName;
+ uint64_t cMaxBytesPerSec;
+ BandwidthGroupType_T enmType;
+};
+
+typedef std::list<BandwidthGroup> BandwidthGroupList;
+
+/**
+ * NOTE: If you add any fields in here, you must update a) the constructor and b)
+ * the operator== which is used by MachineConfigFile::operator==(), or otherwise
+ * your settings might never get saved.
+ */
+struct IOSettings
+{
+ IOSettings();
+
+ bool areIOCacheDefaultSettings() const;
+ bool areDefaultSettings() const;
+
+ bool operator==(const IOSettings &i) const;
+
+ bool fIOCacheEnabled;
+ uint32_t ulIOCacheSize;
+ BandwidthGroupList llBandwidthGroups;
+};
+
+/**
+ * NOTE: If you add any fields in here, you must update a) the constructor and b)
+ * the operator== which is used by MachineConfigFile::operator==(), or otherwise
+ * your settings might never get saved.
+ */
+struct HostPCIDeviceAttachment
+{
+ HostPCIDeviceAttachment();
+
+ bool operator==(const HostPCIDeviceAttachment &a) const;
+
+ com::Utf8Str strDeviceName;
+ uint32_t uHostAddress;
+ uint32_t uGuestAddress;
+};
+
+typedef std::list<HostPCIDeviceAttachment> HostPCIDeviceAttachmentList;
+
+/**
+ * A device attached to a storage controller. This can either be a
+ * hard disk or a DVD drive or a floppy drive and also specifies
+ * which medium is "in" the drive; as a result, this is a combination
+ * of the Main IMedium and IMediumAttachment interfaces.
+ *
+ * NOTE: If you add any fields in here, you must update a) the constructor and b)
+ * the operator== which is used by MachineConfigFile::operator==(), or otherwise
+ * your settings might never get saved.
+ */
+struct AttachedDevice
+{
+ AttachedDevice();
+
+ bool operator==(const AttachedDevice &a) const;
+
+ DeviceType_T deviceType; // only HardDisk, DVD or Floppy are allowed
+
+ // DVDs can be in pass-through mode:
+ bool fPassThrough;
+
+ // Whether guest-triggered eject of DVDs will keep the medium in the
+ // VM config or not:
+ bool fTempEject;
+
+ // Whether the medium is non-rotational:
+ bool fNonRotational;
+
+ // Whether the medium supports discarding unused blocks:
+ bool fDiscard;
+
+ // Whether the medium is hot-pluggable:
+ bool fHotPluggable;
+
+ int32_t lPort;
+ int32_t lDevice;
+
+ // if an image file is attached to the device (ISO, RAW, or hard disk image such as VDI),
+ // this is its UUID; it depends on deviceType which media registry this then needs to
+ // be looked up in. If no image file (only permitted for DVDs and floppies), then the UUID is NULL
+ com::Guid uuid;
+
+ // for DVDs and floppies, the attachment can also be a host device:
+ com::Utf8Str strHostDriveSrc; // if != NULL, value of <HostDrive>/@src
+
+ // Bandwidth group the device is attached to.
+ com::Utf8Str strBwGroup;
+};
+
+typedef std::list<AttachedDevice> AttachedDevicesList;
+
+/**
+ * NOTE: If you add any fields in here, you must update a) the constructor and b)
+ * the operator== which is used by MachineConfigFile::operator==(), or otherwise
+ * your settings might never get saved.
+ */
+struct StorageController
+{
+ StorageController();
+
+ bool operator==(const StorageController &s) const;
+
+ com::Utf8Str strName;
+ StorageBus_T storageBus; // _SATA, _SCSI, _IDE, _SAS
+ StorageControllerType_T controllerType;
+ uint32_t ulPortCount;
+ uint32_t ulInstance;
+ bool fUseHostIOCache;
+ bool fBootable;
+
+ // only for when controllerType == StorageControllerType_IntelAhci:
+ int32_t lIDE0MasterEmulationPort,
+ lIDE0SlaveEmulationPort,
+ lIDE1MasterEmulationPort,
+ lIDE1SlaveEmulationPort;
+
+ AttachedDevicesList llAttachedDevices;
+};
+
+typedef std::list<StorageController> StorageControllersList;
+
+/**
+ * We wrap the storage controllers list into an extra struct so we can
+ * use an undefined struct without needing std::list<> in all the headers.
+ *
+ * NOTE: If you add any fields in here, you must update a) the constructor and b)
+ * the operator== which is used by MachineConfigFile::operator==(), or otherwise
+ * your settings might never get saved.
+ */
+struct Storage
+{
+ bool operator==(const Storage &s) const;
+
+ StorageControllersList llStorageControllers;
+};
+
+/**
+ * Representation of Machine hardware; this is used in the MachineConfigFile.hardwareMachine
+ * field.
+ *
+ * NOTE: If you add any fields in here, you must update a) the constructor and b)
+ * the operator== which is used by MachineConfigFile::operator==(), or otherwise
+ * your settings might never get saved.
+ */
+struct Hardware
+{
+ Hardware();
+
+ bool areParavirtDefaultSettings(SettingsVersion_T sv) const;
+ bool areBootOrderDefaultSettings() const;
+ bool areDisplayDefaultSettings() const;
+ bool areAllNetworkAdaptersDefaultSettings(SettingsVersion_T sv) const;
+
+ bool operator==(const Hardware&) const;
+
+ com::Utf8Str strVersion; // hardware version, optional
+ com::Guid uuid; // hardware uuid, optional (null).
+
+ bool fHardwareVirt,
+ fNestedPaging,
+ fLargePages,
+ fVPID,
+ fUnrestrictedExecution,
+ fHardwareVirtForce,
+ fUseNativeApi,
+ fSyntheticCpu,
+ fTripleFaultReset,
+ fPAE,
+ fAPIC, // requires settings version 1.16 (VirtualBox 5.1)
+ fX2APIC; // requires settings version 1.16 (VirtualBox 5.1)
+ bool fIBPBOnVMExit; //< added out of cycle, after 1.16 was out.
+ bool fIBPBOnVMEntry; //< added out of cycle, after 1.16 was out.
+ bool fSpecCtrl; //< added out of cycle, after 1.16 was out.
+ bool fSpecCtrlByHost; //< added out of cycle, after 1.16 was out.
+ bool fL1DFlushOnSched ; //< added out of cycle, after 1.16 was out.
+ bool fL1DFlushOnVMEntry ; //< added out of cycle, after 1.16 was out.
+ bool fMDSClearOnSched; //< added out of cycle, after 1.16 was out.
+ bool fMDSClearOnVMEntry; //< added out of cycle, after 1.16 was out.
+ bool fNestedHWVirt; //< requires settings version 1.17 (VirtualBox 6.0)
+ bool fVirtVmsaveVmload; //< requires settings version 1.18 (VirtualBox 6.1)
+ typedef enum LongModeType { LongMode_Enabled, LongMode_Disabled, LongMode_Legacy } LongModeType;
+ LongModeType enmLongMode;
+ uint32_t cCPUs;
+ bool fCpuHotPlug; // requires settings version 1.10 (VirtualBox 3.2)
+ CpuList llCpus; // requires settings version 1.10 (VirtualBox 3.2)
+ bool fHPETEnabled; // requires settings version 1.10 (VirtualBox 3.2)
+ uint32_t ulCpuExecutionCap; // requires settings version 1.11 (VirtualBox 3.3)
+ uint32_t uCpuIdPortabilityLevel; // requires settings version 1.15 (VirtualBox 5.0)
+ com::Utf8Str strCpuProfile; // requires settings version 1.16 (VirtualBox 5.1)
+
+ CpuIdLeafsList llCpuIdLeafs;
+
+ uint32_t ulMemorySizeMB;
+
+ BootOrderMap mapBootOrder; // item 0 has highest priority
+
+ FirmwareType_T firmwareType; // requires settings version 1.9 (VirtualBox 3.1)
+
+ PointingHIDType_T pointingHIDType; // requires settings version 1.10 (VirtualBox 3.2)
+ KeyboardHIDType_T keyboardHIDType; // requires settings version 1.10 (VirtualBox 3.2)
+
+ ChipsetType_T chipsetType; // requires settings version 1.11 (VirtualBox 4.0)
+ IommuType_T iommuType; // requires settings version 1.19 (VirtualBox 6.2)
+ ParavirtProvider_T paravirtProvider; // requires settings version 1.15 (VirtualBox 4.4)
+ com::Utf8Str strParavirtDebug; // requires settings version 1.16 (VirtualBox 5.1)
+
+ bool fEmulatedUSBCardReader; // 1.12 (VirtualBox 4.1)
+
+ VRDESettings vrdeSettings;
+
+ BIOSSettings biosSettings;
+ NvramSettings nvramSettings;
+ GraphicsAdapter graphicsAdapter;
+ USB usbSettings;
+ TpmSettings tpmSettings; // requires settings version 1.19 (VirtualBox 6.2)
+ NetworkAdaptersList llNetworkAdapters;
+ SerialPortsList llSerialPorts;
+ ParallelPortsList llParallelPorts;
+ AudioAdapter audioAdapter;
+ Storage storage;
+
+ // technically these two have no business in the hardware section, but for some
+ // clever reason <Hardware> is where they are in the XML....
+ SharedFoldersList llSharedFolders;
+
+ ClipboardMode_T clipboardMode;
+ bool fClipboardFileTransfersEnabled;
+
+ DnDMode_T dndMode;
+
+ uint32_t ulMemoryBalloonSize;
+ bool fPageFusionEnabled;
+
+ GuestPropertiesList llGuestProperties;
+
+ IOSettings ioSettings; // requires settings version 1.10 (VirtualBox 3.2)
+ HostPCIDeviceAttachmentList pciAttachments; // requires settings version 1.12 (VirtualBox 4.1)
+
+ com::Utf8Str strDefaultFrontend; // requires settings version 1.14 (VirtualBox 4.3)
+};
+
+/**
+ * Settings that has to do with debugging.
+ */
+struct Debugging
+{
+ Debugging();
+
+ bool areDefaultSettings() const;
+
+ bool operator==(const Debugging &rOther) const;
+
+ bool fTracingEnabled;
+ bool fAllowTracingToAccessVM;
+ com::Utf8Str strTracingConfig;
+ GuestDebugProvider_T enmDbgProvider;
+ GuestDebugIoProvider_T enmIoProvider;
+ com::Utf8Str strAddress;
+ uint32_t ulPort;
+};
+
+/**
+ * Settings that has to do with autostart.
+ */
+struct Autostart
+{
+ Autostart();
+
+ bool areDefaultSettings() const;
+
+ bool operator==(const Autostart &rOther) const;
+
+ bool fAutostartEnabled;
+ uint32_t uAutostartDelay;
+ AutostopType_T enmAutostopType;
+};
+
+struct Snapshot;
+typedef std::list<Snapshot> SnapshotsList;
+
+/**
+ * NOTE: If you add any fields in here, you must update a) the constructor and b)
+ * the operator== which is used by MachineConfigFile::operator==(), or otherwise
+ * your settings might never get saved.
+ */
+struct Snapshot
+{
+ Snapshot();
+
+ bool operator==(const Snapshot &s) const;
+
+ com::Guid uuid;
+ com::Utf8Str strName,
+ strDescription; // optional
+ RTTIMESPEC timestamp;
+
+ com::Utf8Str strStateFile; // for online snapshots only
+
+ Hardware hardware;
+
+ Debugging debugging;
+ Autostart autostart;
+ RecordingSettings recordingSettings;
+
+ SnapshotsList llChildSnapshots;
+
+ static const struct Snapshot Empty;
+};
+
+/**
+ * NOTE: If you add any fields in here, you must update a) the constructor and b)
+ * the operator== which is used by MachineConfigFile::operator==(), or otherwise
+ * your settings might never get saved.
+ */
+struct MachineUserData
+{
+ MachineUserData();
+
+ bool operator==(const MachineUserData &c) const;
+
+ com::Utf8Str strName;
+ bool fDirectoryIncludesUUID;
+ bool fNameSync;
+ com::Utf8Str strDescription;
+ StringsList llGroups;
+ com::Utf8Str strOsType;
+ com::Utf8Str strSnapshotFolder;
+ bool fTeleporterEnabled;
+ uint32_t uTeleporterPort;
+ com::Utf8Str strTeleporterAddress;
+ com::Utf8Str strTeleporterPassword;
+ bool fRTCUseUTC;
+ IconBlob ovIcon;
+ VMProcPriority_T enmVMPriority;
+};
+
+
+/**
+ * MachineConfigFile represents an XML machine configuration. All the machine settings
+ * that go out to the XML (or are read from it) are in here.
+ *
+ * NOTE: If you add any fields in here, you must update a) the constructor and b)
+ * the operator== which is used by Machine::saveSettings(), or otherwise your settings
+ * might never get saved.
+ */
+class MachineConfigFile : public ConfigFileBase
+{
+public:
+ com::Guid uuid;
+
+ enum
+ {
+ ParseState_NotParsed,
+ ParseState_PasswordError,
+ ParseState_Parsed
+ } enmParseState;
+
+ MachineUserData machineUserData;
+
+ com::Utf8Str strStateKeyId;
+ com::Utf8Str strStateKeyStore;
+ com::Utf8Str strStateFile;
+ bool fCurrentStateModified; // optional, default is true
+ RTTIMESPEC timeLastStateChange; // optional, defaults to now
+ bool fAborted; // optional, default is false
+
+ com::Guid uuidCurrentSnapshot;
+
+ Hardware hardwareMachine;
+ MediaRegistry mediaRegistry;
+ Debugging debugging;
+ Autostart autostart;
+ RecordingSettings recordingSettings;
+
+ StringsMap mapExtraDataItems;
+
+ SnapshotsList llFirstSnapshot; // first snapshot or empty list if there's none
+
+ com::Utf8Str strKeyId;
+ com::Utf8Str strKeyStore; // if not empty, the encryption is used
+ com::Utf8Str strLogKeyId;
+ com::Utf8Str strLogKeyStore;
+
+ MachineConfigFile(const com::Utf8Str *pstrFilename,
+ PCVBOXCRYPTOIF pCryptoIf = NULL,
+ const char *pszPassword = NULL);
+
+ bool operator==(const MachineConfigFile &m) const;
+
+ bool canHaveOwnMediaRegistry() const;
+
+ void importMachineXML(const xml::ElementNode &elmMachine);
+
+ void write(const com::Utf8Str &strFilename, PCVBOXCRYPTOIF pCryptoIf = NULL, const char *pszPassword = NULL);
+
+ enum
+ {
+ BuildMachineXML_IncludeSnapshots = 0x01,
+ BuildMachineXML_WriteVBoxVersionAttribute = 0x02,
+ BuildMachineXML_SkipRemovableMedia = 0x04,
+ BuildMachineXML_MediaRegistry = 0x08,
+ BuildMachineXML_SuppressSavedState = 0x10
+ };
+
+ void copyEncryptionSettingsFrom(const MachineConfigFile &other);
+ void buildMachineXML(xml::ElementNode &elmMachine,
+ uint32_t fl,
+ std::list<xml::ElementNode*> *pllElementsWithUuidAttributes);
+
+ static bool isAudioDriverAllowedOnThisHost(AudioDriverType_T enmDrvType);
+ static AudioDriverType_T getHostDefaultAudioDriver();
+
+private:
+ void readNetworkAdapters(const xml::ElementNode &elmHardware, NetworkAdaptersList &ll);
+ void readAttachedNetworkMode(const xml::ElementNode &pelmMode, bool fEnabled, NetworkAdapter &nic);
+ void readCpuIdTree(const xml::ElementNode &elmCpuid, CpuIdLeafsList &ll);
+ void readCpuTree(const xml::ElementNode &elmCpu, CpuList &ll);
+ void readSerialPorts(const xml::ElementNode &elmUART, SerialPortsList &ll);
+ void readParallelPorts(const xml::ElementNode &elmLPT, ParallelPortsList &ll);
+ void readAudioAdapter(const xml::ElementNode &elmAudioAdapter, AudioAdapter &aa);
+ void readGuestProperties(const xml::ElementNode &elmGuestProperties, Hardware &hw);
+ void readStorageControllerAttributes(const xml::ElementNode &elmStorageController, StorageController &sctl);
+ void readHardware(const xml::ElementNode &elmHardware, Hardware &hw);
+ void readHardDiskAttachments_pre1_7(const xml::ElementNode &elmHardDiskAttachments, Storage &strg);
+ void readStorageControllers(const xml::ElementNode &elmStorageControllers, Storage &strg);
+ void readDVDAndFloppies_pre1_9(const xml::ElementNode &elmHardware, Storage &strg);
+ void readTeleporter(const xml::ElementNode &elmTeleporter, MachineUserData &userData);
+ void readDebugging(const xml::ElementNode &elmDbg, Debugging &dbg);
+ void readAutostart(const xml::ElementNode &elmAutostart, Autostart &autostrt);
+ void readRecordingSettings(const xml::ElementNode &elmRecording, uint32_t cMonitors, RecordingSettings &recording);
+ void readGroups(const xml::ElementNode &elmGroups, StringsList &llGroups);
+ bool readSnapshot(const com::Guid &curSnapshotUuid, const xml::ElementNode &elmSnapshot, Snapshot &snap);
+ void convertOldOSType_pre1_5(com::Utf8Str &str);
+ void readMachine(const xml::ElementNode &elmMachine);
+ void readMachineEncrypted(const xml::ElementNode &elmMachine, PCVBOXCRYPTOIF pCryptoIf, const char *pszPassword);
+
+ void buildHardwareXML(xml::ElementNode &elmParent, const Hardware &hw, uint32_t fl, std::list<xml::ElementNode*> *pllElementsWithUuidAttributes);
+ void buildNetworkXML(NetworkAttachmentType_T mode, bool fEnabled, xml::ElementNode &elmParent, const NetworkAdapter &nic);
+ void buildStorageControllersXML(xml::ElementNode &elmParent,
+ const Storage &st,
+ bool fSkipRemovableMedia,
+ std::list<xml::ElementNode*> *pllElementsWithUuidAttributes);
+ void buildDebuggingXML(xml::ElementNode &elmParent, const Debugging &dbg);
+ void buildAutostartXML(xml::ElementNode &elmParent, const Autostart &autostrt);
+ void buildRecordingXML(xml::ElementNode &elmParent, const RecordingSettings &recording);
+ void buildGroupsXML(xml::ElementNode &elmParent, const StringsList &llGroups);
+ void buildSnapshotXML(xml::ElementNode &elmParent, const Snapshot &snap);
+
+ void buildMachineEncryptedXML(xml::ElementNode &elmMachine,
+ uint32_t fl,
+ std::list<xml::ElementNode*> *pllElementsWithUuidAttributes,
+ PCVBOXCRYPTOIF pCryptoIf,
+ const char *pszPassword);
+
+ void bumpSettingsVersionIfNeeded();
+};
+
+} // namespace settings
+
+
+#endif /* !VBOX_INCLUDED_settings_h */
diff --git a/include/VBox/shflsvc.h b/include/VBox/shflsvc.h
new file mode 100644
index 00000000..725eae76
--- /dev/null
+++ b/include/VBox/shflsvc.h
@@ -0,0 +1,2151 @@
+/** @file
+ * Shared Folders - Common header for host service and guest clients.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef VBOX_INCLUDED_shflsvc_h
+#define VBOX_INCLUDED_shflsvc_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#ifndef IN_MODULE
+# include <VBox/VMMDevCoreTypes.h>
+# include <VBox/VBoxGuestCoreTypes.h>
+#endif
+#include <iprt/string.h>
+#include <VBox/cdefs.h>
+#include <VBox/types.h>
+#include <iprt/fs.h>
+#include <iprt/assert.h>
+#include <iprt/errcore.h>
+#if defined(IN_RING3) || (defined(IN_RING0) && defined(RT_OS_DARWIN))
+# include <iprt/mem.h>
+#endif
+#include <iprt/utf16.h>
+
+
+
+/** @defgroup grp_vbox_shfl Shared Folder Interface Definition.
+ *
+ * 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.
+ *
+ * @{
+ */
+
+/** @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
+/** @} */
+
+
+/** @name Shared Folders service functions. (guest)
+ * @{
+ */
+/** Query mappings changes.
+ * @note Description is currently misleading, it will always return all
+ * current mappings with SHFL_MS_NEW status. Only modification is the
+ * SHFL_MF_AUTOMOUNT flag that causes filtering out non-auto mounts. */
+#define SHFL_FN_QUERY_MAPPINGS (1)
+/** Query the name of a map. */
+#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.
+ * @since VBox 4.0 */
+#define SHFL_FN_READLINK (18) /**< @todo rename to SHFL_FN_READ_LINK (see struct capitalization) */
+/** Create symlink.
+ * @since VBox 4.0 */
+#define SHFL_FN_SYMLINK (19)
+/** Ask host to show symlinks
+ * @since VBox 4.0 */
+#define SHFL_FN_SET_SYMLINKS (20)
+/** Query information about a map.
+ * @since VBox 6.0 */
+#define SHFL_FN_QUERY_MAP_INFO (21)
+/** Wait for changes to the mappings.
+ * @since VBox 6.0 */
+#define SHFL_FN_WAIT_FOR_MAPPINGS_CHANGES (22)
+/** Cancel all waits for changes to the mappings for the calling client.
+ * The wait calls will return VERR_CANCELLED.
+ * @since VBox 6.0 */
+#define SHFL_FN_CANCEL_MAPPINGS_CHANGES_WAITS (23)
+/** Sets the file size.
+ * @since VBox 6.0 */
+#define SHFL_FN_SET_FILE_SIZE (24)
+/** Queries supported features.
+ * @since VBox 6.0.6 */
+#define SHFL_FN_QUERY_FEATURES (25)
+/** Copies a file to another.
+ * @since VBox 6.0.6 */
+#define SHFL_FN_COPY_FILE (26)
+/** Copies part of a file to another.
+ * @since VBox 6.0.6 */
+#define SHFL_FN_COPY_FILE_PART (27)
+/** Close handle to (optional) and remove object by path.
+ * This function is tailored for Windows guests.
+ * @since VBox 6.0.8 */
+#define SHFL_FN_CLOSE_AND_REMOVE (28)
+/** Set the host error code style.
+ * This is for more efficiently getting the correct error status when the host
+ * and guest OS types differs and it won't happen naturally.
+ * @since VBox 6.0.10 */
+#define SHFL_FN_SET_ERROR_STYLE (29)
+/** The last function number. */
+#define SHFL_FN_LAST SHFL_FN_SET_ERROR_STYLE
+/** @} */
+
+
+/** @name 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
+ * @since 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;
+
+/** NIL shared folder root handle. */
+#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.
+ */
+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
+ {
+#if 1
+ char ach[1]; /**< UTF-8 but with a type that makes some more sense. */
+ uint8_t utf8[1];
+ RTUTF16 utf16[1];
+ uint16_t ucs2[1]; /**< misnomer, use utf16. */
+#else
+ uint8_t utf8[RT_FLEXIBLE_ARRAY_IN_NESTED_UNION];
+ RTUTF16 utf16[RT_FLEXIBLE_ARRAY_IN_NESTED_UNION];
+ RTUTF16 ucs2[RT_FLEXIBLE_ARRAY_IN_NESTED_UNION]; /**< misnomer, use utf16. */
+#endif
+ } String;
+} SHFLSTRING;
+AssertCompileSize(RTUTF16, 2);
+AssertCompileSize(SHFLSTRING, 6);
+AssertCompileMemberOffset(SHFLSTRING, String, 4);
+/** The size of SHFLSTRING w/o the string part. */
+#define SHFLSTRING_HEADER_SIZE 4
+AssertCompileMemberOffset(SHFLSTRING, String, SHFLSTRING_HEADER_SIZE);
+
+/** 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)(SHFLSTRING_HEADER_SIZE + 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;
+}
+
+/**
+ * Helper for copying one string into another.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_BUFFER_OVERFLOW and pDst->u16Length set to source length.
+ * @param pDst The destination string.
+ * @param pSrc The source string.
+ * @param cbTerm The size of the string terminator.
+ */
+DECLINLINE(int) ShflStringCopy(PSHFLSTRING pDst, PCSHFLSTRING pSrc, size_t cbTerm)
+{
+ int rc = VINF_SUCCESS;
+ if (pDst->u16Size >= pSrc->u16Length + cbTerm)
+ {
+ memcpy(&pDst->String, &pSrc->String, pSrc->u16Length);
+ switch (cbTerm)
+ {
+ default:
+ case 2: pDst->String.ach[pSrc->u16Length + 1] = '\0'; RT_FALL_THROUGH();
+ case 1: pDst->String.ach[pSrc->u16Length + 0] = '\0'; break;
+ case 0: break;
+ }
+ }
+ else
+ rc = VERR_BUFFER_OVERFLOW;
+ pDst->u16Length = pSrc->u16Length;
+ return rc;
+}
+
+#if defined(IN_RING3) \
+ || (defined(IN_RING0) && defined(RT_OS_DARWIN))
+
+/**
+ * Duplicates a string using RTMemAlloc as allocator.
+ *
+ * @returns Copy, NULL if out of memory.
+ * @param pSrc The source string.
+ */
+DECLINLINE(PSHFLSTRING) ShflStringDup(PCSHFLSTRING pSrc)
+{
+ PSHFLSTRING pDst = (PSHFLSTRING)RTMemAlloc(SHFLSTRING_HEADER_SIZE + pSrc->u16Size);
+ if (pDst)
+ {
+ pDst->u16Length = pSrc->u16Length;
+ pDst->u16Size = pSrc->u16Size;
+ memcpy(&pDst->String, &pSrc->String, pSrc->u16Size);
+ }
+ return pDst;
+}
+
+/**
+ * Duplicates a UTF-16 string using RTMemAlloc as allocator.
+ *
+ * The returned string will be using UTF-16 encoding too.
+ *
+ * @returns Pointer to copy on success - pass to RTMemFree to free.
+ * NULL if out of memory.
+ * @param pwszSrc The source string. Encoding is not checked.
+ */
+DECLINLINE(PSHFLSTRING) ShflStringDupUtf16(PCRTUTF16 pwszSrc)
+{
+ size_t cwcSrc = RTUtf16Len(pwszSrc);
+ if (cwcSrc < UINT16_MAX / sizeof(RTUTF16))
+ {
+ PSHFLSTRING pDst = (PSHFLSTRING)RTMemAlloc(SHFLSTRING_HEADER_SIZE + (cwcSrc + 1) * sizeof(RTUTF16));
+ if (pDst)
+ {
+ pDst->u16Length = (uint16_t)(cwcSrc * sizeof(RTUTF16));
+ pDst->u16Size = (uint16_t)((cwcSrc + 1) * sizeof(RTUTF16));
+ memcpy(&pDst->String, pwszSrc, (cwcSrc + 1) * sizeof(RTUTF16));
+ return pDst;
+ }
+ }
+ AssertFailed();
+ return NULL;
+}
+
+/**
+ * Duplicates a UTF-8 string using RTMemAlloc as allocator.
+ *
+ * The returned string will be using UTF-8 encoding too.
+ *
+ * @returns Pointer to copy on success - pass to RTMemFree to free.
+ * NULL if out of memory.
+ * @param pszSrc The source string. Encoding is not checked.
+ */
+DECLINLINE(PSHFLSTRING) ShflStringDupUtf8(const char *pszSrc)
+{
+ size_t cchSrc = strlen(pszSrc);
+ if (cchSrc < UINT16_MAX)
+ {
+ PSHFLSTRING pDst = (PSHFLSTRING)RTMemAlloc(SHFLSTRING_HEADER_SIZE + cchSrc + 1);
+ if (pDst)
+ {
+ pDst->u16Length = (uint16_t)cchSrc;
+ pDst->u16Size = (uint16_t)(cchSrc + 1);
+ memcpy(&pDst->String, pszSrc, cchSrc + 1);
+ return pDst;
+ }
+ }
+ AssertFailed();
+ return NULL;
+}
+
+/**
+ * Creates a UTF-16 duplicate of the UTF-8 string @a pszSrc using RTMemAlloc as
+ * allocator.
+ *
+ * @returns Pointer to copy on success - pass to RTMemFree to free.
+ * NULL if out of memory or invalid UTF-8 encoding.
+ * @param pszSrc The source string.
+ */
+DECLINLINE(PSHFLSTRING) ShflStringDupUtf8AsUtf16(const char *pszSrc)
+{
+ size_t cwcConversion = 0;
+ int rc = RTStrCalcUtf16LenEx(pszSrc, RTSTR_MAX, &cwcConversion);
+ if ( RT_SUCCESS(rc)
+ && cwcConversion < UINT16_MAX / sizeof(RTUTF16))
+ {
+ PSHFLSTRING pDst = (PSHFLSTRING)RTMemAlloc(SHFLSTRING_HEADER_SIZE + (cwcConversion + 1) * sizeof(RTUTF16));
+ if (pDst)
+ {
+ PRTUTF16 pwszDst = pDst->String.ucs2;
+ pDst->u16Size = (uint16_t)((cwcConversion + 1) * sizeof(RTUTF16));
+ rc = RTStrToUtf16Ex(pszSrc, RTSTR_MAX, &pwszDst, cwcConversion + 1, &cwcConversion);
+ AssertRC(rc);
+ if (RT_SUCCESS(rc))
+ {
+ pDst->u16Length = (uint16_t)(cwcConversion * sizeof(RTUTF16));
+ return pDst;
+ }
+ RTMemFree(pDst);
+ }
+ }
+ AssertMsgFailed(("rc=%Rrc cwcConversion=%#x\n", rc, cwcConversion));
+ return NULL;
+}
+
+/**
+ * Copies a UTF-8 string to a buffer as UTF-16.
+ *
+ * @returns IPRT status code.
+ * @param pDst The destination buffer.
+ * @param pszSrc The source string.
+ * @param cchSrc The source string length, or RTSTR_MAX.
+ */
+DECLINLINE(int) ShflStringCopyUtf8AsUtf16(PSHFLSTRING pDst, const char *pszSrc, size_t cchSrc)
+{
+ int rc;
+ size_t cwcDst = 0;
+ if (pDst->u16Size >= sizeof(RTUTF16))
+ {
+ PRTUTF16 pwszDst = pDst->String.utf16;
+ rc = RTStrToUtf16Ex(pszSrc, cchSrc, &pwszDst, pDst->u16Size / sizeof(RTUTF16), &cwcDst);
+ }
+ else
+ {
+ RTStrCalcUtf16LenEx(pszSrc, cchSrc, &cwcDst);
+ rc = VERR_BUFFER_OVERFLOW;
+ }
+ pDst->u16Length = (uint16_t)(cwcDst * sizeof(RTUTF16));
+ return rc != VERR_BUFFER_OVERFLOW || cwcDst < UINT16_MAX / sizeof(RTUTF16) ? rc : VERR_TOO_MUCH_DATA;
+}
+
+/**
+ * Copies a UTF-8 string buffer to another buffer as UTF-16
+ *
+ * @returns IPRT status code.
+ * @param pDst The destination buffer (UTF-16).
+ * @param pSrc The source buffer (UTF-8).
+ */
+DECLINLINE(int) ShflStringCopyUtf8BufAsUtf16(PSHFLSTRING pDst, PCSHFLSTRING pSrc)
+{
+ return ShflStringCopyUtf8AsUtf16(pDst, pSrc->String.ach, pSrc->u16Length);
+}
+
+/**
+ * Copies a UTF-16 string to a buffer as UTF-8
+ *
+ * @returns IPRT status code.
+ * @param pDst The destination buffer.
+ * @param pwszSrc The source string.
+ * @param cwcSrc The source string length, or RTSTR_MAX.
+ */
+DECLINLINE(int) ShflStringCopyUtf16AsUtf8(PSHFLSTRING pDst, PCRTUTF16 pwszSrc, size_t cwcSrc)
+{
+ int rc;
+ size_t cchDst = 0;
+ if (pDst->u16Size > 0)
+ {
+ char *pszDst = pDst->String.ach;
+ rc = RTUtf16ToUtf8Ex(pwszSrc, cwcSrc, &pszDst, pDst->u16Size, &cchDst);
+ }
+ else
+ {
+ RTUtf16CalcUtf8LenEx(pwszSrc, cwcSrc, &cchDst);
+ rc = VERR_BUFFER_OVERFLOW;
+ }
+ pDst->u16Length = (uint16_t)cchDst;
+ return rc != VERR_BUFFER_OVERFLOW || cchDst < UINT16_MAX ? rc : VERR_TOO_MUCH_DATA;
+}
+
+/**
+ * Copies a UTF-16 string buffer to another buffer as UTF-8
+ *
+ * @returns IPRT status code.
+ * @param pDst The destination buffer (UTF-8).
+ * @param pSrc The source buffer (UTF-16).
+ */
+DECLINLINE(int) ShflStringCopyUtf16BufAsUtf8(PSHFLSTRING pDst, PCSHFLSTRING pSrc)
+{
+ return ShflStringCopyUtf16AsUtf8(pDst, pSrc->String.utf16, pSrc->u16Length / sizeof(RTUTF16));
+}
+
+#endif /* IN_RING3 */
+
+/**
+ * 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;
+}
+
+/** Macro for passing as string as a HGCM parmeter (pointer) */
+#define SHFLSTRING_TO_HGMC_PARAM(a_pParam, a_pString) \
+ do { \
+ (a_pParam)->type = VBOX_HGCM_SVC_PARM_PTR; \
+ (a_pParam)->u.pointer.addr = (a_pString); \
+ (a_pParam)->u.pointer.size = ShflStringSizeOfBuffer(a_pString); \
+ } while (0)
+
+/** @} */
+
+
+/**
+ * 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;
+ /* Clear bits which we don't pass through for security reasons. */
+ pDst->Attr.fMode &= ~(RTFS_UNIX_ISUID | RTFS_UNIX_ISGID | RTFS_UNIX_ISTXT);
+ 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,
+ /** Blow the type up to 32-bit. */
+ SHFL_32BIT_HACK = 0x7fffffff
+} SHFLCREATERESULT;
+AssertCompile(SHFL_NO_RESULT == 0);
+AssertCompileSize(SHFLCREATERESULT, 4);
+
+
+/** @name 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;
+
+
+/** @name 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.
+ * @note Currently always set to SHFL_MS_NEW. */
+ uint32_t u32Status;
+ /** Root handle. */
+ SHFLROOT root;
+} SHFLMAPPING;
+/** Pointer to a SHFLMAPPING structure. */
+typedef SHFLMAPPING *PSHFLMAPPING;
+
+/** @} */
+
+
+/** @name 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;
+
+/** @} */
+
+
+/** @defgroup grp_vbox_shfl_params Function parameter structures.
+ * @{
+ */
+
+/** @name SHFL_FN_QUERY_MAPPINGS
+ * @{
+ */
+/** Validation mask. Needs to be adjusted
+ * whenever a new SHFL_MF_ flag is added. */
+#define SHFL_MF_MASK (0x00000011)
+/** UTF-16 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)
+
+/** Parameters structure. */
+typedef struct _VBoxSFQueryMappings
+{
+ VBGLIOCHGCMCALL 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)
+/** @} */
+
+
+/** @name SHFL_FN_QUERY_MAP_NAME
+ * @{
+ */
+
+/** Parameters structure. */
+typedef struct _VBoxSFQueryMapName
+{
+ VBGLIOCHGCMCALL 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)
+/** @} */
+
+
+/** @name SHFL_FN_MAP_FOLDER_OLD
+ * @{
+ */
+
+/** Parameters structure. */
+typedef struct _VBoxSFMapFolder_Old
+{
+ VBGLIOCHGCMCALL 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)
+/** @} */
+
+
+/** @name SHFL_FN_MAP_FOLDER
+ * @{
+ */
+
+/** SHFL_FN_MAP_FOLDER parameters. */
+typedef struct VBoxSFParmMapFolder
+{
+ /** pointer, in: SHFLSTRING with the name of the folder to map. */
+ HGCMFunctionParameter pStrName;
+ /** value32, out: The root ID (SHFLROOT) of the mapping. */
+ HGCMFunctionParameter id32Root;
+ /** value32, in: Path delimiter code point. */
+ HGCMFunctionParameter uc32Delimiter;
+ /** value32, in: case senstive flag */
+ HGCMFunctionParameter fCaseSensitive;
+} VBoxSFParmMapFolder;
+
+/** Parameters structure. */
+typedef struct _VBoxSFMapFolder
+{
+ VBGLIOCHGCMCALL 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)
+/** @} */
+
+
+/** @name SHFL_FN_UNMAP_FOLDER
+ * @{
+ */
+
+/** SHFL_FN_UNMAP_FOLDER parameters. */
+typedef struct VBoxSFParmUnmapFolder
+{
+ /** value32, in: SHFLROOT of the mapping to unmap */
+ HGCMFunctionParameter id32Root;
+} VBoxSFParmUnmapFolder;
+
+/** Parameters structure. */
+typedef struct _VBoxSFUnmapFolder
+{
+ VBGLIOCHGCMCALL 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)
+/** @} */
+
+
+/** @name SHFL_FN_CREATE
+ * @{
+ */
+
+/** SHFL_FN_CREATE parameters. */
+typedef struct VBoxSFParmCreate
+{
+ /** value32, in: SHFLROOT
+ * Root handle of the mapping which name is queried. */
+ HGCMFunctionParameter id32Root;
+ /** pointer, in: Points to SHFLSTRING buffer. */
+ HGCMFunctionParameter pStrPath;
+ /** pointer, in/out: Points to SHFLCREATEPARMS buffer. */
+ HGCMFunctionParameter pCreateParms;
+} VBoxSFParmCreate;
+
+/** Parameters structure. */
+typedef struct _VBoxSFCreate
+{
+ VBGLIOCHGCMCALL 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)
+/** @} */
+
+
+/** @name SHFL_FN_CLOSE
+ * @{
+ */
+
+/** SHFL_FN_CLOSE parameters. */
+typedef struct VBoxSFParmClose
+{
+ /** value32, in: SHFLROOT of the mapping with the handle. */
+ HGCMFunctionParameter id32Root;
+ /** value64, in: SHFLHANDLE of object to close. */
+ HGCMFunctionParameter u64Handle;
+} VBoxSFParmClose;
+
+/** Parameters structure. */
+typedef struct _VBoxSFClose
+{
+ VBGLIOCHGCMCALL 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)
+/** @} */
+
+
+/** @name SHFL_FN_READ
+ * @{
+ */
+
+/** SHFL_FN_READ parameters. */
+typedef struct VBoxSFParmRead
+{
+ /** value32, in: SHFLROOT of the mapping with the handle. */
+ HGCMFunctionParameter id32Root;
+ /** value64, in: SHFLHANDLE of object to read from . */
+ HGCMFunctionParameter u64Handle;
+ /** value64, in: Offset to start reading from. */
+ HGCMFunctionParameter off64Read;
+ /** value32, in/out: How much to try read / Actually read. */
+ HGCMFunctionParameter cb32Read;
+ /** pointer, out: Buffer to return the data in. */
+ HGCMFunctionParameter pBuf;
+} VBoxSFParmRead;
+
+/** Parameters structure. */
+typedef struct _VBoxSFRead
+{
+ VBGLIOCHGCMCALL 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)
+/** @} */
+
+
+/** @name SHFL_FN_WRITE
+ * @{
+ */
+
+/** SHFL_FN_WRITE parameters. */
+typedef struct VBoxSFParmWrite
+{
+ /** value32, in: SHFLROOT of the mapping with the handle. */
+ HGCMFunctionParameter id32Root;
+ /** value64, in: SHFLHANDLE of object to write to. */
+ HGCMFunctionParameter u64Handle;
+ /** value64, in/out: Offset to start writing at / New offset.
+ * @note The new offset isn't necessarily off + cb for files opened with
+ * SHFL_CF_ACCESS_APPEND since other parties (host programs, other VMs,
+ * other computers) could have extended the file since the last time the
+ * guest got a fresh size statistic. So, this helps the guest avoiding
+ * a stat call to check the actual size. */
+ HGCMFunctionParameter off64Write;
+ /** value32, in/out: How much to try write / Actually written. */
+ HGCMFunctionParameter cb32Write;
+ /** pointer, out: Buffer to return the data in. */
+ HGCMFunctionParameter pBuf;
+} VBoxSFParmWrite;
+
+/** Parameters structure. */
+typedef struct _VBoxSFWrite
+{
+ VBGLIOCHGCMCALL 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/out:
+ * Offset to write to/New offset.
+ * @note The new offset isn't necessarily off + cb for files opened with
+ * SHFL_CF_ACCESS_APPEND since other parties (host programs, other VMs,
+ * other computers) could have extended the file since the last time the
+ * guest got a fresh size statistic. So, this helps the guest avoiding
+ * a stat call to check the actual size.
+ */
+ 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)
+/** @} */
+
+
+/** @name SHFL_FN_LOCK
+ * @remarks 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
+{
+ VBGLIOCHGCMCALL 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)
+/** @} */
+
+
+/** @name SHFL_FN_FLUSH
+ * @{
+ */
+
+/** SHFL_FN_FLUSH parameters. */
+typedef struct VBoxSFParmFlush
+{
+ /** value32, in: SHFLROOT of the mapping with the handle. */
+ HGCMFunctionParameter id32Root;
+ /** value64, in: SHFLHANDLE of object to flush. */
+ HGCMFunctionParameter u64Handle;
+} VBoxSFParmFlush;
+
+/** Parameters structure. */
+typedef struct _VBoxSFFlush
+{
+ VBGLIOCHGCMCALL 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)
+/** @} */
+
+
+/** @name SHFL_FN_SET_UTF8
+ * @{ */
+/** NUmber of parameters for SHFL_FN_SET_UTF8. */
+#define SHFL_CPARMS_SET_UTF8 (0)
+/** @} */
+
+
+/** @name SHFL_FN_LIST
+ * @remarks 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
+#define SHFL_LIST_RESTART 2
+
+/** SHFL_FN_LIST parameters. */
+typedef struct VBoxSFParmList
+{
+ /** value32, in: SHFLROOT of the mapping the handle belongs to. */
+ HGCMFunctionParameter id32Root;
+ /** value64, in: SHFLHANDLE of the directory. */
+ HGCMFunctionParameter u64Handle;
+ /** value32, in: List flags SHFL_LIST_XXX. */
+ HGCMFunctionParameter f32Flags;
+ /** value32, in/out: Input buffer size / Returned bytes count. */
+ HGCMFunctionParameter cb32Buffer;
+ /** pointer, in[optional]: SHFLSTRING filter string (full path). */
+ HGCMFunctionParameter pStrFilter;
+ /** pointer, out: Buffer to return listing information in (SHFLDIRINFO).
+ * When SHFL_LIST_RETURN_ONE is not specfied, multiple record may be
+ * returned, deriving the entry size using SHFLDIRINFO::name.u16Size. */
+ HGCMFunctionParameter pBuffer;
+ /** value32, out: Set to 0 if the listing is done, 1 if there are more entries.
+ * @note Must be set to zero on call as it was declared in/out parameter and
+ * may be used as such again. */
+ HGCMFunctionParameter f32More;
+ /** value32, out: Number of entries returned. */
+ HGCMFunctionParameter c32Entries;
+} VBoxSFParmList;
+
+
+/** Parameters structure. */
+typedef struct _VBoxSFList
+{
+ VBGLIOCHGCMCALL 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)
+/** @} */
+
+
+/** @name SHFL_FN_READLINK
+ * @{
+ */
+
+/** SHFL_FN_READLINK parameters. */
+typedef struct VBoxSFParmReadLink
+{
+ /** value32, in: SHFLROOT of the mapping which the symlink is read. */
+ HGCMFunctionParameter id32Root;
+ /** pointer, in: SHFLSTRING full path to the symlink. */
+ HGCMFunctionParameter pStrPath;
+ /** pointer, out: Buffer to place the symlink target into.
+ * @note Buffer contains UTF-8 characters on success, regardless of the
+ * UTF-8/UTF-16 setting of the connection. Will be zero terminated.
+ *
+ * @todo r=bird: This should've been a string!
+ * @todo r=bird: There should've been a byte count returned! */
+ HGCMFunctionParameter pBuffer;
+} VBoxSFParmReadLink;
+
+/** Parameters structure. */
+typedef struct _VBoxSFReadLink
+{
+ VBGLIOCHGCMCALL 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.
+ * @note Buffer contains UTF-8 characters on success, regardless of the
+ * UTF-8/UTF-16 setting of the connection. Will be zero terminated.
+ */
+ HGCMFunctionParameter buffer;
+
+} VBoxSFReadLink;
+
+/** Number of parameters */
+#define SHFL_CPARMS_READLINK (3)
+/** @} */
+
+
+/** @name 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 */
+
+/** SHFL_FN_INFORMATION parameters. */
+typedef struct VBoxSFParmInformation
+{
+ /** value32, in: SHFLROOT of the mapping the handle belongs to. */
+ HGCMFunctionParameter id32Root;
+ /** value64, in: SHFLHANDLE of object to be queried/set. */
+ HGCMFunctionParameter u64Handle;
+ /** value32, in: SHFL_INFO_XXX */
+ HGCMFunctionParameter f32Flags;
+ /** value32, in/out: Bytes to be used for information/How many bytes were used. */
+ HGCMFunctionParameter cb32;
+ /** pointer, in/out: Information to be set/get (SHFLFSOBJINFO, SHFLVOLINFO, or SHFLSTRING).
+ * Do not forget to set the SHFLFSOBJINFO::Attr::enmAdditional for Get operation as well. */
+ HGCMFunctionParameter pInfo;
+} VBoxSFParmInformation;
+
+
+/** Parameters structure. */
+typedef struct _VBoxSFInformation
+{
+ VBGLIOCHGCMCALL 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)
+/** @} */
+
+
+/** @name SHFL_FN_REMOVE
+ * @{
+ */
+
+#define SHFL_REMOVE_FILE (0x1)
+#define SHFL_REMOVE_DIR (0x2)
+#define SHFL_REMOVE_SYMLINK (0x4)
+
+/** SHFL_FN_REMOVE parameters. */
+typedef struct VBoxSFParmRemove
+{
+ /** value32, in: SHFLROOT of the mapping the path is relative to. */
+ HGCMFunctionParameter id32Root;
+ /** pointer, in: Points to SHFLSTRING buffer. */
+ HGCMFunctionParameter pStrPath;
+ /** value32, in: SHFL_REMOVE_XXX */
+ HGCMFunctionParameter f32Flags;
+} VBoxSFParmRemove;
+
+/** Parameters structure. */
+typedef struct _VBoxSFRemove
+{
+ VBGLIOCHGCMCALL 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)
+/** @} */
+
+
+/** @name SHFL_FN_CLOSE_AND_REMOVE
+ * Extends SHFL_FN_REMOVE with a 4th handle parameter that can be nil.
+ * @{
+ */
+/** SHFL_FN_CLOSE_AND_REMOVE parameters. */
+typedef struct VBoxSFParmCloseAndRemove
+{
+ /** value32, in: SHFLROOT of the mapping the path is relative to. */
+ HGCMFunctionParameter id32Root;
+ /** pointer, in: Points to SHFLSTRING buffer. */
+ HGCMFunctionParameter pStrPath;
+ /** value32, in: SHFL_REMOVE_XXX */
+ HGCMFunctionParameter f32Flags;
+ /** value64, in: SHFLHANDLE to the object to be removed & close, optional. */
+ HGCMFunctionParameter u64Handle;
+} VBoxSFParmCloseAndRemove;
+/** Number of parameters */
+#define SHFL_CPARMS_CLOSE_AND_REMOVE (4)
+AssertCompileSize(VBoxSFParmCloseAndRemove, SHFL_CPARMS_CLOSE_AND_REMOVE * sizeof(HGCMFunctionParameter));
+/** @} */
+
+
+/** @name SHFL_FN_RENAME
+ * @{
+ */
+
+#define SHFL_RENAME_FILE (0x1)
+#define SHFL_RENAME_DIR (0x2)
+#define SHFL_RENAME_REPLACE_IF_EXISTS (0x4)
+
+/** SHFL_FN_RENAME parameters. */
+typedef struct VBoxSFParmRename
+{
+ /** value32, in: SHFLROOT of the mapping the paths are relative to. */
+ HGCMFunctionParameter id32Root;
+ /** pointer, in: SHFLSTRING giving the source (old) path. */
+ HGCMFunctionParameter pStrSrcPath;
+ /** pointer, in: SHFLSTRING giving the destination (new) path. */
+ HGCMFunctionParameter pStrDstPath;
+ /** value32, in: SHFL_RENAME_XXX */
+ HGCMFunctionParameter f32Flags;
+} VBoxSFParmRename;
+
+/** Parameters structure. */
+typedef struct _VBoxSFRename
+{
+ VBGLIOCHGCMCALL 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)
+/** @} */
+
+
+/** @name SHFL_FN_SYMLINK
+ * @{
+ */
+
+/** Parameters structure. */
+typedef struct VBoxSFParmCreateSymlink
+{
+ /** value32, in: SHFLROOT of the mapping the symlink should be created on. */
+ HGCMFunctionParameter id32Root;
+ /** pointer, in: SHFLSTRING giving the path to the symlink. */
+ HGCMFunctionParameter pStrSymlink;
+ /** pointer, in: SHFLSTRING giving the target. */
+ HGCMFunctionParameter pStrTarget;
+ /** pointer, out: SHFLFSOBJINFO buffer to be filled with info about the created symlink. */
+ HGCMFunctionParameter pInfo;
+} VBoxSFParmCreateSymlink;
+
+/** Parameters structure. */
+typedef struct _VBoxSFSymlink
+{
+ VBGLIOCHGCMCALL 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)
+/** @} */
+
+
+/** @name SHFL_FN_SET_SYMLINKS
+ * @{ */
+/** NUmber of parameters for SHFL_FN_SET_SYMLINKS. */
+#define SHFL_CPARMS_SET_SYMLINKS (0)
+/** @} */
+
+
+/** @name SHFL_FN_QUERY_MAP_INFO
+ * @{
+ */
+/** Query flag: Guest prefers drive letters as mount points. */
+#define SHFL_MIQF_DRIVE_LETTER RT_BIT_64(0)
+/** Query flag: Guest prefers paths as mount points. */
+#define SHFL_MIQF_PATH RT_BIT_64(1)
+
+/** Set if writable. */
+#define SHFL_MIF_WRITABLE RT_BIT_64(0)
+/** Indicates that the mapping should be auto-mounted. */
+#define SHFL_MIF_AUTO_MOUNT RT_BIT_64(1)
+/** Set if host is case insensitive. */
+#define SHFL_MIF_HOST_ICASE RT_BIT_64(2)
+/** Set if guest is case insensitive. */
+#define SHFL_MIF_GUEST_ICASE RT_BIT_64(3)
+/** Symbolic link creation is allowed. */
+#define SHFL_MIF_SYMLINK_CREATION RT_BIT_64(4)
+
+/** Parameters structure. */
+typedef struct VBoxSFQueryMapInfo
+{
+ /** Common header. */
+ VBGLIOCHGCMCALL callInfo;
+ /** 32-bit, in: SHFLROOT - root handle of the mapping to query. */
+ HGCMFunctionParameter root;
+ /** pointer, in/out: SHFLSTRING buffer for the name. */
+ HGCMFunctionParameter name;
+ /** pointer, in/out: SHFLSTRING buffer for the auto mount point. */
+ HGCMFunctionParameter mountPoint;
+ /** 64-bit, in: SHFL_MIQF_XXX; out: SHFL_MIF_XXX. */
+ HGCMFunctionParameter flags;
+ /** 32-bit, out: Root ID version number - root handle reuse guard. */
+ HGCMFunctionParameter rootIdVersion;
+} VBoxSFQueryMapInfo;
+/** Number of parameters */
+#define SHFL_CPARMS_QUERY_MAP_INFO (5)
+/** @} */
+
+
+/** @name SHFL_FN_WAIT_FOR_MAPPINGS_CHANGES
+ *
+ * Returns VINF_SUCCESS on change and VINF_TRY_AGAIN when restored from saved
+ * state. If the guest makes too many calls (max 64) VERR_OUT_OF_RESOURCES will
+ * be returned.
+ *
+ * @{
+ */
+/** Parameters structure. */
+typedef struct VBoxSFWaitForMappingsChanges
+{
+ /** Common header. */
+ VBGLIOCHGCMCALL callInfo;
+ /** 32-bit, in/out: The mappings configuration version.
+ * On input the client sets it to the last config it knows about, on return
+ * it holds the current version. */
+ HGCMFunctionParameter version;
+} VBoxSFWaitForMappingsChanges;
+/** Number of parameters */
+#define SHFL_CPARMS_WAIT_FOR_MAPPINGS_CHANGES (1)
+/** @} */
+
+
+/** @name SHFL_FN_CANCEL_MAPPINGS_CHANGES_WAITS
+ * @{
+ */
+/** Number of parameters */
+#define SHFL_CPARMS_CANCEL_MAPPINGS_CHANGES_WAITS (0)
+/** @} */
+
+
+/** @name SHFL_FN_SET_FILE_SIZE
+ * @{
+ */
+/** SHFL_FN_SET_FILE_SIZE parameters. */
+typedef struct VBoxSFParmSetFileSize
+{
+ /** value32, in: SHFLROOT of the mapping the handle belongs to. */
+ HGCMFunctionParameter id32Root;
+ /** value64, in: SHFLHANDLE of the file to change the size of. */
+ HGCMFunctionParameter u64Handle;
+ /** value64, in: The new file size. */
+ HGCMFunctionParameter cb64NewSize;
+} VBoxSFParmSetFileSize;
+/** Number of parameters */
+#define SHFL_CPARMS_SET_FILE_SIZE (3)
+/** @} */
+
+
+/** @name SHFL_FN_QUERY_FEATURES
+ * @{ */
+/** SHFL_FN_QUERY_FEATURES parameters. */
+typedef struct VBoxSFParmQueryFeatures
+{
+ /** value64, out: Feature flags, SHFL_FEATURE_XXX. */
+ HGCMFunctionParameter f64Features;
+ /** value32, out: The ordinal of the last valid function */
+ HGCMFunctionParameter u32LastFunction;
+} VBoxSFParmQueryFeatures;
+/** Number of parameters for SHFL_FN_QUERY_FEATURES. */
+#define SHFL_CPARMS_QUERY_FEATURES (2)
+
+/** The write functions updates the file offset upon return.
+ * This can be helpful for files open in append mode. */
+#define SHFL_FEATURE_WRITE_UPDATES_OFFSET RT_BIT_64(0)
+/** @} */
+
+
+/** @name SHFL_FN_COPY_FILE
+ * @{ */
+/** SHFL_FN_COPY_FILE parameters. */
+typedef struct VBoxSFParmCopyFile
+{
+ /** value32, in: SHFLROOT of the mapping the source handle belongs to. */
+ HGCMFunctionParameter id32RootSrc;
+ /** pointer, in: SHFLSTRING giving the source file path. */
+ HGCMFunctionParameter pStrPathSrc;
+
+ /** value32, in: SHFLROOT of the mapping the destination handle belongs to. */
+ HGCMFunctionParameter id32RootDst;
+ /** pointer, in: SHFLSTRING giving the destination file path. */
+ HGCMFunctionParameter pStrPathDst;
+
+ /** value32, in: Reserved for the future, must be zero. */
+ HGCMFunctionParameter f32Flags;
+} VBoxSFParmCopyFile;
+/** Number of parameters for SHFL_FN_COPY_FILE. */
+#define SHFL_CPARMS_COPY_FILE (5)
+/** @} */
+
+
+/** @name SHFL_FN_COPY_FILE_PART
+ * @{ */
+/** SHFL_FN_COPY_FILE_PART parameters. */
+typedef struct VBoxSFParmCopyFilePart
+{
+ /** value32, in: SHFLROOT of the mapping the source handle belongs to. */
+ HGCMFunctionParameter id32RootSrc;
+ /** value64, in: SHFLHANDLE of the source file. */
+ HGCMFunctionParameter u64HandleSrc;
+ /** value64, in: The source file offset. */
+ HGCMFunctionParameter off64Src;
+
+ /** value32, in: SHFLROOT of the mapping the destination handle belongs to. */
+ HGCMFunctionParameter id32RootDst;
+ /** value64, in: SHFLHANDLE of the destination file. */
+ HGCMFunctionParameter u64HandleDst;
+ /** value64, in: The destination file offset. */
+ HGCMFunctionParameter off64Dst;
+
+ /** value64, in/out: The number of bytes to copy on input / bytes actually copied. */
+ HGCMFunctionParameter cb64ToCopy;
+ /** value32, in: Reserved for the future, must be zero. */
+ HGCMFunctionParameter f32Flags;
+} VBoxSFParmCopyFilePart;
+/** Number of parameters for SHFL_FN_COPY_FILE_PART. */
+#define SHFL_CPARMS_COPY_FILE_PART (8)
+/** @} */
+
+
+/** @name SHFL_FN_SET_ERROR_STYLE
+ * @{ */
+/** The defined error styles. */
+typedef enum SHFLERRORSTYLE
+{
+ kShflErrorStyle_Invalid = 0,
+ kShflErrorStyle_Windows,
+ kShflErrorStyle_Linux,
+ kShflErrorStyle_End,
+ kShflErrorStyle_32BitHack = 0x7fffffff
+} SHFLERRORSTYLE;
+/** The native error style. */
+#if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2)
+# define SHFLERRORSTYLE_NATIVE kShflErrorStyle_Windows
+#else
+# define SHFLERRORSTYLE_NATIVE kShflErrorStyle_Linux
+#endif
+
+/** SHFL_FN_SET_ERROR_STYLE parameters. */
+typedef struct VBoxSFParmSetErrorStyle
+{
+ /** value32, in: The style, SHFLERRORSTYLE. */
+ HGCMFunctionParameter u32Style;
+ /** value32, in: Reserved for the future, must be zero. */
+ HGCMFunctionParameter u32Reserved;
+} VBoxSFParmSetErrorStyle;
+/** Number of parameters for SHFL_FN_SET_ERROR_STYLE. */
+#define SHFL_CPARMS_SET_ERROR_STYLE (2)
+/** @} */
+
+
+/** @name SHFL_FN_ADD_MAPPING
+ * @note 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 (4)
+/** @} */
+
+
+/** @name SHFL_FN_REMOVE_MAPPING
+ * @note Host call, no guest structure is used.
+ * @{
+ */
+
+#define SHFL_CPARMS_REMOVE_MAPPING (1)
+/** @} */
+
+
+/** @name SHFL_FN_SET_STATUS_LED
+ * @note Host call, no guest structure is used.
+ * @{
+ */
+
+#define SHFL_CPARMS_SET_STATUS_LED (1)
+/** @} */
+
+
+/** @} */
+/** @} */
+
+#endif /* !VBOX_INCLUDED_shflsvc_h */
+
diff --git a/include/VBox/sup.h b/include/VBox/sup.h
new file mode 100644
index 00000000..258134fa
--- /dev/null
+++ b/include/VBox/sup.h
@@ -0,0 +1,2832 @@
+/** @file
+ * SUP - Support Library. (HDrv)
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_sup_h
+#define VBOX_INCLUDED_sup_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/cdefs.h>
+#include <VBox/types.h>
+#include <iprt/assert.h>
+#include <iprt/stdarg.h>
+#include <iprt/cpuset.h>
+#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
+# include <iprt/asm-amd64-x86.h>
+#elif defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM64)
+# include <iprt/asm-arm.h>
+#endif
+
+RT_C_DECLS_BEGIN
+
+struct VTGOBJHDR;
+struct VTGPROBELOC;
+
+
+/** @defgroup grp_sup The Support Library API
+ * @{
+ */
+
+/**
+ * Physical page descriptor.
+ */
+#pragma pack(4) /* space is more important. */
+typedef struct SUPPAGE
+{
+ /** Physical memory address. */
+ RTHCPHYS Phys;
+ /** Reserved entry for internal use by the caller. */
+ RTHCUINTPTR uReserved;
+} SUPPAGE;
+#pragma pack()
+/** Pointer to a page descriptor. */
+typedef SUPPAGE *PSUPPAGE;
+/** Pointer to a const page descriptor. */
+typedef const SUPPAGE *PCSUPPAGE;
+
+/**
+ * The paging mode.
+ *
+ * @remarks Users are making assumptions about the order here!
+ */
+typedef enum SUPPAGINGMODE
+{
+ /** The usual invalid entry.
+ * This is returned by SUPR3GetPagingMode() */
+ SUPPAGINGMODE_INVALID = 0,
+ /** Normal 32-bit paging, no global pages */
+ SUPPAGINGMODE_32_BIT,
+ /** Normal 32-bit paging with global pages. */
+ SUPPAGINGMODE_32_BIT_GLOBAL,
+ /** PAE mode, no global pages, no NX. */
+ SUPPAGINGMODE_PAE,
+ /** PAE mode with global pages. */
+ SUPPAGINGMODE_PAE_GLOBAL,
+ /** PAE mode with NX, no global pages. */
+ SUPPAGINGMODE_PAE_NX,
+ /** PAE mode with global pages and NX. */
+ SUPPAGINGMODE_PAE_GLOBAL_NX,
+ /** AMD64 mode, no global pages. */
+ SUPPAGINGMODE_AMD64,
+ /** AMD64 mode with global pages, no NX. */
+ SUPPAGINGMODE_AMD64_GLOBAL,
+ /** AMD64 mode with NX, no global pages. */
+ SUPPAGINGMODE_AMD64_NX,
+ /** AMD64 mode with global pages and NX. */
+ SUPPAGINGMODE_AMD64_GLOBAL_NX
+} SUPPAGINGMODE;
+
+
+/** @name Flags returned by SUPR0GetKernelFeatures().
+ * @{
+ */
+/** GDT is read-only. */
+#define SUPKERNELFEATURES_GDT_READ_ONLY RT_BIT(0)
+/** SMAP is possibly enabled. */
+#define SUPKERNELFEATURES_SMAP RT_BIT(1)
+/** GDT is read-only but the writable GDT can be fetched by SUPR0GetCurrentGdtRw(). */
+#define SUPKERNELFEATURES_GDT_NEED_WRITABLE RT_BIT(2)
+/** @} */
+
+/**
+ * An VT-x control MSR.
+ * @sa VMXCTLSMSR.
+ */
+typedef union SUPVMXCTLSMSR
+{
+ uint64_t u;
+ struct
+ {
+ /** Bits set here _must_ be set in the corresponding VM-execution controls. */
+ uint32_t allowed0;
+ /** Bits cleared here _must_ be cleared in the corresponding VM-execution controls. */
+ uint32_t allowed1;
+ } n;
+} SUPVMXCTLSMSR;
+AssertCompileSize(SUPVMXCTLSMSR, sizeof(uint64_t));
+
+/**
+ * Hardware-virtualization MSRs.
+ */
+typedef struct SUPHWVIRTMSRS
+{
+ union
+ {
+ /** @sa VMXMSRS */
+ struct
+ {
+ uint64_t u64FeatCtrl;
+ uint64_t u64Basic;
+ /** Pin-based VM-execution controls. */
+ SUPVMXCTLSMSR PinCtls;
+ /** Processor-based VM-execution controls. */
+ SUPVMXCTLSMSR ProcCtls;
+ /** Secondary processor-based VM-execution controls. */
+ SUPVMXCTLSMSR ProcCtls2;
+ /** VM-exit controls. */
+ SUPVMXCTLSMSR ExitCtls;
+ /** VM-entry controls. */
+ SUPVMXCTLSMSR EntryCtls;
+ /** True pin-based VM-execution controls. */
+ SUPVMXCTLSMSR TruePinCtls;
+ /** True processor-based VM-execution controls. */
+ SUPVMXCTLSMSR TrueProcCtls;
+ /** True VM-entry controls. */
+ SUPVMXCTLSMSR TrueEntryCtls;
+ /** True VM-exit controls. */
+ SUPVMXCTLSMSR TrueExitCtls;
+ uint64_t u64Misc;
+ uint64_t u64Cr0Fixed0;
+ uint64_t u64Cr0Fixed1;
+ uint64_t u64Cr4Fixed0;
+ uint64_t u64Cr4Fixed1;
+ uint64_t u64VmcsEnum;
+ uint64_t u64VmFunc;
+ uint64_t u64EptVpidCaps;
+ uint64_t u64ProcCtls3;
+ uint64_t u64ExitCtls2;
+ uint64_t au64Reserved[7];
+ } vmx;
+ struct
+ {
+ uint64_t u64MsrHwcr;
+ uint64_t u64MsrSmmAddr;
+ uint64_t u64MsrSmmMask;
+ uint64_t u64Padding[25];
+ } svm;
+ } u;
+} SUPHWVIRTMSRS;
+AssertCompileSize(SUPHWVIRTMSRS, 224);
+/** Pointer to a hardware-virtualization MSRs struct. */
+typedef SUPHWVIRTMSRS *PSUPHWVIRTMSRS;
+/** Pointer to a hardware-virtualization MSRs struct. */
+typedef const SUPHWVIRTMSRS *PCSUPHWVIRTMSRS;
+
+
+/**
+ * Usermode probe context information.
+ */
+typedef struct SUPDRVTRACERUSRCTX
+{
+ /** The probe ID from the VTG location record. */
+ uint32_t idProbe;
+ /** 32 if X86, 64 if AMD64. */
+ uint8_t cBits;
+ /** Reserved padding. */
+ uint8_t abReserved[3];
+ /** Data which format is dictated by the cBits member. */
+ union
+ {
+ /** X86 context info. */
+ struct
+ {
+ uint32_t uVtgProbeLoc; /**< Location record address. */
+ uint32_t aArgs[20]; /**< Raw arguments. */
+ uint32_t eip;
+ uint32_t eflags;
+ uint32_t eax;
+ uint32_t ecx;
+ uint32_t edx;
+ uint32_t ebx;
+ uint32_t esp;
+ uint32_t ebp;
+ uint32_t esi;
+ uint32_t edi;
+ uint16_t cs;
+ uint16_t ss;
+ uint16_t ds;
+ uint16_t es;
+ uint16_t fs;
+ uint16_t gs;
+ } X86;
+
+ /** AMD64 context info. */
+ struct
+ {
+ uint64_t uVtgProbeLoc; /**< Location record address. */
+ uint64_t aArgs[10]; /**< Raw arguments. */
+ uint64_t rip;
+ uint64_t rflags;
+ uint64_t rax;
+ uint64_t rcx;
+ uint64_t rdx;
+ uint64_t rbx;
+ uint64_t rsp;
+ uint64_t rbp;
+ uint64_t rsi;
+ uint64_t rdi;
+ uint64_t r8;
+ uint64_t r9;
+ uint64_t r10;
+ uint64_t r11;
+ uint64_t r12;
+ uint64_t r13;
+ uint64_t r14;
+ uint64_t r15;
+ } Amd64;
+ } u;
+} SUPDRVTRACERUSRCTX;
+/** Pointer to the usermode probe context information. */
+typedef SUPDRVTRACERUSRCTX *PSUPDRVTRACERUSRCTX;
+/** Pointer to the const usermode probe context information. */
+typedef SUPDRVTRACERUSRCTX const *PCSUPDRVTRACERUSRCTX;
+
+/**
+ * The result of a modification operation (SUPMSRPROBEROP_MODIFY or
+ * SUPMSRPROBEROP_MODIFY_FASTER).
+ */
+typedef struct SUPMSRPROBERMODIFYRESULT
+{
+ /** The MSR value prior to the modifications. Valid if fBeforeGp is false */
+ uint64_t uBefore;
+ /** The value that was written. Valid if fBeforeGp is false */
+ uint64_t uWritten;
+ /** The MSR value after the modifications. Valid if AfterGp is false. */
+ uint64_t uAfter;
+ /** Set if we GPed reading the MSR before the modification. */
+ bool fBeforeGp;
+ /** Set if we GPed while trying to write the modified value.
+ * This is set when fBeforeGp is true. */
+ bool fModifyGp;
+ /** Set if we GPed while trying to read the MSR after the modification.
+ * This is set when fBeforeGp is true. */
+ bool fAfterGp;
+ /** Set if we GPed while trying to restore the MSR after the modification.
+ * This is set when fBeforeGp is true. */
+ bool fRestoreGp;
+ /** Structure size alignment padding. */
+ bool afReserved[4];
+} SUPMSRPROBERMODIFYRESULT, *PSUPMSRPROBERMODIFYRESULT;
+
+
+/**
+ * The CPU state.
+ */
+typedef enum SUPGIPCPUSTATE
+{
+ /** Invalid CPU state / unused CPU entry. */
+ SUPGIPCPUSTATE_INVALID = 0,
+ /** The CPU is not present. */
+ SUPGIPCPUSTATE_ABSENT,
+ /** The CPU is offline. */
+ SUPGIPCPUSTATE_OFFLINE,
+ /** The CPU is online. */
+ SUPGIPCPUSTATE_ONLINE,
+ /** Force 32-bit enum type. */
+ SUPGIPCPUSTATE_32_BIT_HACK = 0x7fffffff
+} SUPGIPCPUSTATE;
+
+/**
+ * Per CPU data.
+ */
+typedef struct SUPGIPCPU
+{
+ /** Update transaction number.
+ * This number is incremented at the start and end of each update. It follows
+ * thusly that odd numbers indicates update in progress, while even numbers
+ * indicate stable data. Use this to make sure that the data items you fetch
+ * are consistent. */
+ volatile uint32_t u32TransactionId;
+ /** The interval in TSC ticks between two NanoTS updates.
+ * This is the average interval over the last 2, 4 or 8 updates + a little slack.
+ * The slack makes the time go a tiny tiny bit slower and extends the interval enough
+ * to avoid ending up with too many 1ns increments. */
+ volatile uint32_t u32UpdateIntervalTSC;
+ /** Current nanosecond timestamp. */
+ volatile uint64_t u64NanoTS;
+ /** The TSC at the time of u64NanoTS. */
+ volatile uint64_t u64TSC;
+ /** Current CPU Frequency. */
+ volatile uint64_t u64CpuHz;
+ /** The TSC delta with reference to the master TSC, subtract from RDTSC. */
+ volatile int64_t i64TSCDelta;
+ /** Number of errors during updating.
+ * Typical errors are under/overflows. */
+ volatile uint32_t cErrors;
+ /** Index of the head item in au32TSCHistory. */
+ volatile uint32_t iTSCHistoryHead;
+ /** Array of recent TSC interval deltas.
+ * The most recent item is at index iTSCHistoryHead.
+ * This history is used to calculate u32UpdateIntervalTSC.
+ */
+ volatile uint32_t au32TSCHistory[8];
+ /** The interval between the last two NanoTS updates. (experiment for now) */
+ volatile uint32_t u32PrevUpdateIntervalNS;
+
+ /** Reserved for future per processor data. */
+ volatile uint32_t u32Reserved;
+ /** The TSC value read while doing TSC delta measurements across CPUs. */
+ volatile uint64_t u64TSCSample;
+ /** Reserved for future per processor data. */
+ volatile uint32_t au32Reserved1[3];
+
+ /** The CPU state. */
+ SUPGIPCPUSTATE volatile enmState;
+ /** The host CPU ID of this CPU (the SUPGIPCPU is indexed by APIC ID). */
+ RTCPUID idCpu;
+ /** The CPU set index of this CPU. */
+ int16_t iCpuSet;
+ /** CPU group number (always zero, except on windows). */
+ uint16_t iCpuGroup;
+ /** CPU group member number (same as iCpuSet, except on windows). */
+ uint16_t iCpuGroupMember;
+ /** The APIC ID of this CPU. */
+ uint16_t idApic;
+ /** @todo Add topology/NUMA info. */
+ uint32_t iReservedForNumaNode;
+} SUPGIPCPU;
+AssertCompileSize(RTCPUID, 4);
+AssertCompileSize(SUPGIPCPU, 128);
+AssertCompileMemberAlignment(SUPGIPCPU, u64NanoTS, 8);
+AssertCompileMemberAlignment(SUPGIPCPU, u64TSC, 8);
+AssertCompileMemberAlignment(SUPGIPCPU, u64TSCSample, 8);
+
+/** Pointer to per cpu data.
+ * @remark there is no const version of this typedef, see g_pSUPGlobalInfoPage for details. */
+typedef SUPGIPCPU *PSUPGIPCPU;
+
+/**
+ * CPU group information.
+ * @remarks Windows only.
+ */
+typedef struct SUPGIPCPUGROUP
+{
+ /** Current number of CPUs in this group. */
+ uint16_t volatile cMembers;
+ /** Maximum number of CPUs in the group. */
+ uint16_t cMaxMembers;
+ /** The CPU set index of the members. This table has cMaxMembers entries.
+ * @note For various reasons, entries from cMembers and up to cMaxMembers are
+ * may change as the host OS does set dynamic assignments during CPU
+ * hotplugging. */
+ int16_t aiCpuSetIdxs[1];
+} SUPGIPCPUGROUP;
+/** Pointer to a GIP CPU group structure. */
+typedef SUPGIPCPUGROUP *PSUPGIPCPUGROUP;
+/** Pointer to a const GIP CPU group structure. */
+typedef SUPGIPCPUGROUP const *PCSUPGIPCPUGROUP;
+
+/**
+ * The rules concerning the applicability of SUPGIPCPU::i64TscDelta.
+ */
+typedef enum SUPGIPUSETSCDELTA
+{
+ /** Value for SUPGIPMODE_ASYNC_TSC. */
+ SUPGIPUSETSCDELTA_NOT_APPLICABLE = 0,
+ /** The OS specific part of SUPDrv (or the user) claims the TSC is as
+ * good as zero. */
+ SUPGIPUSETSCDELTA_ZERO_CLAIMED,
+ /** The differences in RDTSC output between the CPUs/cores/threads should
+ * be considered zero for all practical purposes. */
+ SUPGIPUSETSCDELTA_PRACTICALLY_ZERO,
+ /** The differences in RDTSC output between the CPUs/cores/threads are a few
+ * hundred ticks or less. (Probably not worth calling ASMGetApicId two times
+ * just to apply deltas.) */
+ SUPGIPUSETSCDELTA_ROUGHLY_ZERO,
+ /** Significant differences in RDTSC output between the CPUs/cores/threads,
+ * deltas must be applied. */
+ SUPGIPUSETSCDELTA_NOT_ZERO,
+ /** End of valid values (exclusive). */
+ SUPGIPUSETSCDELTA_END,
+ /** Make sure the type is 32-bit sized. */
+ SUPGIPUSETSCDELTA_32BIT_HACK = 0x7fffffff
+} SUPGIPUSETSCDELTA;
+
+
+/** @name SUPGIPGETCPU_XXX - methods that aCPUs can be indexed.
+ *
+ * @note Linux offers information via selector 0x78, and Windows via selector
+ * 0x53. But since they both support RDTSCP as well, and because most
+ * CPUs now have RDTSCP, we prefer it over LSL. We can implement more
+ * alternatives if it becomes necessary.
+ *
+ * @{
+ */
+/** Use ASMGetApicId (or equivalent) and translate the result via
+ * aiCpuFromApicId. */
+#define SUPGIPGETCPU_APIC_ID RT_BIT_32(0)
+/** Use RDTSCP and translate the first RTCPUSET_MAX_CPUS of ECX via
+ * aiCpuFromCpuSetIdx.
+ *
+ * Linux stores the RTMpCpuId() value in ECX[11:0] and NUMA node number in
+ * ECX[12:31]. Solaris only stores RTMpCpuId() in ECX. On both systems
+ * RTMpCpuId() == RTMpCpuIdToSetIndex(RTMpCpuId()). RTCPUSET_MAX_CPUS is
+ * currently 64, 256 or 1024 in size, which lower than
+ * 4096, so there shouldn't be any range issues. */
+#define SUPGIPGETCPU_RDTSCP_MASK_MAX_SET_CPUS RT_BIT_32(1)
+/** Subtract the max IDT size from IDTR.LIMIT, extract the
+ * first RTCPUSET_MAX_CPUS and translate it via aiCpuFromCpuSetIdx.
+ *
+ * Darwin stores the RTMpCpuId() (== RTMpCpuIdToSetIndex(RTMpCpuId()))
+ * value in the IDT limit. The masking is a precaution against what linux
+ * does with RDTSCP. */
+#define SUPGIPGETCPU_IDTR_LIMIT_MASK_MAX_SET_CPUS RT_BIT_32(2)
+/** Windows specific RDTSCP variant, where CH gives you the group and CL gives
+ * you the CPU number within that group.
+ *
+ * Use SUPGLOBALINFOPAGE::aidFirstCpuFromCpuGroup to get the group base CPU set
+ * index, then translate the sum of thru aiCpuFromCpuSetIdx to find the aCPUs
+ * entry.
+ *
+ * @note The group number is actually 16-bit wide (ECX[23:8]), but we simplify
+ * it since we only support 256 CPUs/groups at the moment.
+ */
+#define SUPGIPGETCPU_RDTSCP_GROUP_IN_CH_NUMBER_IN_CL RT_BIT_32(3)
+/** Can use CPUID[0xb].EDX and translate the result via aiCpuFromApicId. */
+#define SUPGIPGETCPU_APIC_ID_EXT_0B RT_BIT_32(4)
+/** Can use CPUID[0x8000001e].EAX and translate the result via aiCpuFromApicId. */
+#define SUPGIPGETCPU_APIC_ID_EXT_8000001E RT_BIT_32(5)
+/** @} */
+
+/** @def SUPGIP_MAX_CPU_GROUPS
+ * Maximum number of CPU groups. */
+#if RTCPUSET_MAX_CPUS >= 256
+# define SUPGIP_MAX_CPU_GROUPS 256
+#else
+# define SUPGIP_MAX_CPU_GROUPS RTCPUSET_MAX_CPUS
+#endif
+
+/**
+ * Global Information Page.
+ *
+ * This page contains useful information and can be mapped into any
+ * process or VM. It can be accessed thru the g_pSUPGlobalInfoPage
+ * pointer when a session is open.
+ */
+typedef struct SUPGLOBALINFOPAGE
+{
+ /** Magic (SUPGLOBALINFOPAGE_MAGIC). */
+ uint32_t u32Magic;
+ /** The GIP version. */
+ uint32_t u32Version;
+
+ /** The GIP update mode, see SUPGIPMODE. */
+ uint32_t u32Mode;
+ /** The number of entries in the CPU table.
+ * (This can work as RTMpGetArraySize().) */
+ uint16_t cCpus;
+ /** The size of the GIP in pages. */
+ uint16_t cPages;
+ /** The update frequency of the of the NanoTS. */
+ volatile uint32_t u32UpdateHz;
+ /** The update interval in nanoseconds. (10^9 / u32UpdateHz) */
+ volatile uint32_t u32UpdateIntervalNS;
+ /** The timestamp of the last time we update the update frequency. */
+ volatile uint64_t u64NanoTSLastUpdateHz;
+ /** The TSC frequency of the system. */
+ uint64_t u64CpuHz;
+ /** The number of CPUs that are online. */
+ volatile uint16_t cOnlineCpus;
+ /** The number of CPUs present in the system. */
+ volatile uint16_t cPresentCpus;
+ /** The highest number of CPUs possible. */
+ uint16_t cPossibleCpus;
+ /** The highest number of CPU groups possible. */
+ uint16_t cPossibleCpuGroups;
+ /** The max CPU ID (RTMpGetMaxCpuId). */
+ RTCPUID idCpuMax;
+ /** The applicability of SUPGIPCPU::i64TscDelta. */
+ SUPGIPUSETSCDELTA enmUseTscDelta;
+ /** Mask of SUPGIPGETCPU_XXX values that indicates different ways that aCPU
+ * can be accessed from ring-3 and raw-mode context. */
+ uint32_t fGetGipCpu;
+ /** GIP flags, see SUPGIP_FLAGS_XXX. */
+ volatile uint32_t fFlags;
+ /** The set of online CPUs. */
+ RTCPUSET OnlineCpuSet;
+#if RTCPUSET_MAX_CPUS < 1024
+ uint64_t abOnlineCpuSetPadding[(1024 - RTCPUSET_MAX_CPUS) / 64];
+#endif
+ /** The set of present CPUs. */
+ RTCPUSET PresentCpuSet;
+#if RTCPUSET_MAX_CPUS < 1024
+ uint64_t abPresentCpuSetPadding[(1024 - RTCPUSET_MAX_CPUS) / 64];
+#endif
+ /** The set of possible CPUs. */
+ RTCPUSET PossibleCpuSet;
+#if RTCPUSET_MAX_CPUS < 1024
+ uint64_t abPossibleCpuSetPadding[(1024 - RTCPUSET_MAX_CPUS) / 64];
+#endif
+
+ /** Padding / reserved space for future data. */
+ uint32_t au32Padding1[48];
+
+ /** Table indexed by the CPU APIC ID to get the CPU table index. */
+ uint16_t aiCpuFromApicId[4096];
+ /** CPU set index to CPU table index. */
+ uint16_t aiCpuFromCpuSetIdx[1024];
+ /** Table indexed by CPU group to containing offsets to SUPGIPCPUGROUP
+ * structures, invalid entries are set to UINT32_MAX. The offsets are relative
+ * to the start of this structure.
+ * @note Windows only. The other hosts sets all entries to UINT32_MAX! */
+ uint32_t aoffCpuGroup[SUPGIP_MAX_CPU_GROUPS];
+
+ /** Array of per-cpu data.
+ * This is index by ApicId via the aiCpuFromApicId table.
+ *
+ * The clock and frequency information is updated for all CPUs if @c u32Mode
+ * is SUPGIPMODE_ASYNC_TSC. If @c u32Mode is SUPGIPMODE_SYNC_TSC only the first
+ * entry is updated. If @c u32Mode is SUPGIPMODE_SYNC_TSC the TSC frequency in
+ * @c u64CpuHz is copied to all CPUs. */
+ SUPGIPCPU aCPUs[1];
+} SUPGLOBALINFOPAGE;
+AssertCompileMemberAlignment(SUPGLOBALINFOPAGE, u64NanoTSLastUpdateHz, 8);
+AssertCompileMemberAlignment(SUPGLOBALINFOPAGE, OnlineCpuSet, 64);
+AssertCompileMemberAlignment(SUPGLOBALINFOPAGE, PresentCpuSet, 64);
+AssertCompileMemberAlignment(SUPGLOBALINFOPAGE, PossibleCpuSet, 64);
+#if defined(RT_ARCH_SPARC) || defined(RT_ARCH_SPARC64) /* ?? needed ?? */
+AssertCompileMemberAlignment(SUPGLOBALINFOPAGE, aCPUs, 32);
+#else
+AssertCompileMemberAlignment(SUPGLOBALINFOPAGE, aCPUs, 128);
+#endif
+
+/** Pointer to the global info page.
+ * @remark there is no const version of this typedef, see g_pSUPGlobalInfoPage for details. */
+typedef SUPGLOBALINFOPAGE *PSUPGLOBALINFOPAGE;
+
+
+/** The value of the SUPGLOBALINFOPAGE::u32Magic field. (Soryo Fuyumi) */
+#define SUPGLOBALINFOPAGE_MAGIC 0x19590106
+/** The GIP version.
+ * Upper 16 bits is the major version. Major version is only changed with
+ * incompatible changes in the GIP. */
+#define SUPGLOBALINFOPAGE_VERSION 0x000a0000
+
+/**
+ * SUPGLOBALINFOPAGE::u32Mode values.
+ */
+typedef enum SUPGIPMODE
+{
+ /** The usual invalid null entry. */
+ SUPGIPMODE_INVALID = 0,
+ /** The TSC of the cores and cpus in the system is in sync. */
+ SUPGIPMODE_SYNC_TSC,
+ /** Each core has it's own TSC. */
+ SUPGIPMODE_ASYNC_TSC,
+ /** The TSC of the cores are non-stop and have a constant frequency. */
+ SUPGIPMODE_INVARIANT_TSC,
+ /** End of valid GIP mode values (exclusive). */
+ SUPGIPMODE_END,
+ /** The usual 32-bit hack. */
+ SUPGIPMODE_32BIT_HACK = 0x7fffffff
+} SUPGIPMODE;
+
+/** Pointer to the Global Information Page.
+ *
+ * This pointer is valid as long as SUPLib has a open session. Anyone using
+ * the page must treat this pointer as highly volatile and not trust it beyond
+ * one transaction.
+ *
+ * @remark The GIP page is read-only to everyone but the support driver and
+ * is actually mapped read only everywhere but in ring-0. However
+ * it is not marked 'const' as this might confuse compilers into
+ * thinking that values doesn't change even if members are marked
+ * as volatile. Thus, there is no PCSUPGLOBALINFOPAGE type.
+ */
+#if defined(IN_SUP_R3) || defined(IN_SUP_R0)
+extern DECLEXPORT(PSUPGLOBALINFOPAGE) g_pSUPGlobalInfoPage;
+
+#elif !defined(IN_RING0) || defined(RT_OS_WINDOWS) || defined(RT_OS_SOLARIS) || defined(VBOX_WITH_KMOD_WRAPPED_R0_MODS)
+extern DECLIMPORT(PSUPGLOBALINFOPAGE) g_pSUPGlobalInfoPage;
+
+#else /* IN_RING0 && !RT_OS_WINDOWS */
+# if !defined(__GNUC__) || defined(RT_OS_DARWIN) || !defined(RT_ARCH_AMD64)
+# define g_pSUPGlobalInfoPage (&g_SUPGlobalInfoPage)
+# else
+# define g_pSUPGlobalInfoPage (SUPGetGIPHlp())
+/** Workaround for ELF+GCC problem on 64-bit hosts.
+ * (GCC emits a mov with a R_X86_64_32 reloc, we need R_X86_64_64.) */
+DECLINLINE(PSUPGLOBALINFOPAGE) SUPGetGIPHlp(void)
+{
+ PSUPGLOBALINFOPAGE pGIP;
+ __asm__ __volatile__ ("movabs $g_SUPGlobalInfoPage,%0\n\t"
+ : "=a" (pGIP));
+ return pGIP;
+}
+# endif
+/** The GIP.
+ * We save a level of indirection by exporting the GIP instead of a variable
+ * pointing to it. */
+extern DECLIMPORT(SUPGLOBALINFOPAGE) g_SUPGlobalInfoPage;
+#endif
+
+/**
+ * Gets the GIP pointer.
+ *
+ * @returns Pointer to the GIP or NULL.
+ */
+SUPDECL(PSUPGLOBALINFOPAGE) SUPGetGIP(void);
+
+/** @name SUPGIP_FLAGS_XXX - SUPR3GipSetFlags flags.
+ * @{ */
+/** Enable GIP test mode. */
+#define SUPGIP_FLAGS_TESTING_ENABLE RT_BIT_32(0)
+/** Valid mask of flags that can be set through the ioctl. */
+#define SUPGIP_FLAGS_VALID_MASK RT_BIT_32(0)
+/** GIP test mode needs to be checked (e.g. when enabled or being disabled). */
+#define SUPGIP_FLAGS_TESTING RT_BIT_32(24)
+/** Prepare to start GIP test mode. */
+#define SUPGIP_FLAGS_TESTING_START RT_BIT_32(25)
+/** Prepare to stop GIP test mode. */
+#define SUPGIP_FLAGS_TESTING_STOP RT_BIT_32(26)
+/** @} */
+
+/** @internal */
+SUPDECL(PSUPGIPCPU) SUPGetGipCpuPtrForAsyncMode(PSUPGLOBALINFOPAGE pGip);
+SUPDECL(uint64_t) SUPGetCpuHzFromGipForAsyncMode(PSUPGLOBALINFOPAGE pGip);
+SUPDECL(bool) SUPIsTscFreqCompatible(uint64_t uCpuHz, uint64_t *puGipCpuHz, bool fRelax);
+SUPDECL(bool) SUPIsTscFreqCompatibleEx(uint64_t uBaseCpuHz, uint64_t uCpuHz, bool fRelax);
+
+
+/**
+ * Gets CPU entry of the calling CPU.
+ *
+ * @returns Pointer to the CPU entry on success, NULL on failure.
+ * @param pGip The GIP pointer.
+ */
+DECLINLINE(PSUPGIPCPU) SUPGetGipCpuPtr(PSUPGLOBALINFOPAGE pGip)
+{
+ if (RT_LIKELY( pGip
+ && pGip->u32Magic == SUPGLOBALINFOPAGE_MAGIC))
+ {
+ switch (pGip->u32Mode)
+ {
+ case SUPGIPMODE_INVARIANT_TSC:
+ case SUPGIPMODE_SYNC_TSC:
+ return &pGip->aCPUs[0];
+ case SUPGIPMODE_ASYNC_TSC:
+ return SUPGetGipCpuPtrForAsyncMode(pGip);
+ default: break; /* shut up gcc */
+ }
+ }
+ AssertFailed();
+ return NULL;
+}
+
+/**
+ * Gets the TSC frequency of the calling CPU.
+ *
+ * @returns TSC frequency, UINT64_MAX on failure (asserted).
+ * @param pGip The GIP pointer.
+ */
+DECLINLINE(uint64_t) SUPGetCpuHzFromGip(PSUPGLOBALINFOPAGE pGip)
+{
+ if (RT_LIKELY( pGip
+ && pGip->u32Magic == SUPGLOBALINFOPAGE_MAGIC))
+ {
+ switch (pGip->u32Mode)
+ {
+ case SUPGIPMODE_INVARIANT_TSC:
+ case SUPGIPMODE_SYNC_TSC:
+ return pGip->aCPUs[0].u64CpuHz;
+ case SUPGIPMODE_ASYNC_TSC:
+ return SUPGetCpuHzFromGipForAsyncMode(pGip);
+ default: break; /* shut up gcc */
+ }
+ }
+ AssertFailed();
+ return UINT64_MAX;
+}
+
+
+/**
+ * Gets the TSC frequency of the specified CPU.
+ *
+ * @returns TSC frequency, UINT64_MAX on failure (asserted).
+ * @param pGip The GIP pointer.
+ * @param iCpuSet The CPU set index of the CPU in question.
+ */
+DECLINLINE(uint64_t) SUPGetCpuHzFromGipBySetIndex(PSUPGLOBALINFOPAGE pGip, uint32_t iCpuSet)
+{
+ if (RT_LIKELY( pGip
+ && pGip->u32Magic == SUPGLOBALINFOPAGE_MAGIC))
+ {
+ switch (pGip->u32Mode)
+ {
+ case SUPGIPMODE_INVARIANT_TSC:
+ case SUPGIPMODE_SYNC_TSC:
+ return pGip->aCPUs[0].u64CpuHz;
+ case SUPGIPMODE_ASYNC_TSC:
+ if (RT_LIKELY(iCpuSet < RT_ELEMENTS(pGip->aiCpuFromCpuSetIdx)))
+ {
+ uint16_t iCpu = pGip->aiCpuFromCpuSetIdx[iCpuSet];
+ if (RT_LIKELY(iCpu < pGip->cCpus))
+ return pGip->aCPUs[iCpu].u64CpuHz;
+ }
+ break;
+ default: break; /* shut up gcc */
+ }
+ }
+ AssertFailed();
+ return UINT64_MAX;
+}
+
+
+/**
+ * Gets the pointer to the per CPU data for a CPU given by its set index.
+ *
+ * @returns Pointer to the corresponding per CPU structure, or NULL if invalid.
+ * @param pGip The GIP pointer.
+ * @param iCpuSet The CPU set index of the CPU which we want.
+ */
+DECLINLINE(PSUPGIPCPU) SUPGetGipCpuBySetIndex(PSUPGLOBALINFOPAGE pGip, uint32_t iCpuSet)
+{
+ if (RT_LIKELY( pGip
+ && pGip->u32Magic == SUPGLOBALINFOPAGE_MAGIC))
+ {
+ if (RT_LIKELY(iCpuSet < RT_ELEMENTS(pGip->aiCpuFromCpuSetIdx)))
+ {
+ uint16_t iCpu = pGip->aiCpuFromCpuSetIdx[iCpuSet];
+ if (RT_LIKELY(iCpu < pGip->cCpus))
+ return &pGip->aCPUs[iCpu];
+ }
+ }
+ return NULL;
+}
+
+
+#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86) || defined(RT_ARCH_ARM64) ||defined(RT_ARCH_ARM32)
+
+/** @internal */
+SUPDECL(uint64_t) SUPReadTscWithDelta(PSUPGLOBALINFOPAGE pGip);
+
+/**
+ * Read the host TSC value and applies the TSC delta if appropriate.
+ *
+ * @returns the TSC value.
+ * @remarks Requires GIP to be initialized and valid.
+ */
+DECLINLINE(uint64_t) SUPReadTsc(void)
+{
+# if defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32) /** @todo portme: ring-0 arm. */
+ return ASMReadTSC();
+# else
+ PSUPGLOBALINFOPAGE pGip = g_pSUPGlobalInfoPage;
+ if (!pGip || pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_ROUGHLY_ZERO)
+ return ASMReadTSC();
+ return SUPReadTscWithDelta(pGip);
+# endif
+}
+
+#endif /* X86 || AMD64 || ARM */
+
+/** @internal */
+SUPDECL(int64_t) SUPGetTscDeltaSlow(PSUPGLOBALINFOPAGE pGip);
+
+/**
+ * Gets the TSC delta for the current CPU.
+ *
+ * @returns The TSC delta value (will not return the special INT64_MAX value).
+ * @param pGip The GIP, NULL is okay in ring-3.
+ * @remarks Requires GIP to be initialized and valid if pGip isn't NULL.
+ */
+DECLINLINE(int64_t) SUPGetTscDelta(PSUPGLOBALINFOPAGE pGip)
+{
+#ifdef IN_RING3
+ if (!pGip || pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_ROUGHLY_ZERO)
+#else
+ if (pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_ROUGHLY_ZERO)
+#endif
+ return 0;
+ return SUPGetTscDeltaSlow(pGip);
+}
+
+
+/**
+ * Gets the TSC delta for a given CPU.
+ *
+ * @returns The TSC delta value (will not return the special INT64_MAX value).
+ * @param iCpuSet The CPU set index of the CPU which TSC delta we want.
+ * @remarks Requires GIP to be initialized and valid.
+ */
+DECLINLINE(int64_t) SUPGetTscDeltaByCpuSetIndex(uint32_t iCpuSet)
+{
+ PSUPGLOBALINFOPAGE pGip = g_pSUPGlobalInfoPage;
+ if (pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_ROUGHLY_ZERO)
+ return 0;
+ if (RT_LIKELY(iCpuSet < RT_ELEMENTS(pGip->aiCpuFromCpuSetIdx)))
+ {
+ uint16_t iCpu = pGip->aiCpuFromCpuSetIdx[iCpuSet];
+ if (RT_LIKELY(iCpu < pGip->cCpus))
+ {
+ int64_t iTscDelta = pGip->aCPUs[iCpu].i64TSCDelta;
+ if (iTscDelta != INT64_MAX)
+ return iTscDelta;
+ }
+ }
+ AssertFailed();
+ return 0;
+}
+
+
+/**
+ * Checks if the TSC delta is available for a given CPU (if TSC-deltas are
+ * relevant).
+ *
+ * @returns true if it's okay to read the TSC, false otherwise.
+ *
+ * @param iCpuSet The CPU set index of the CPU which TSC delta we check.
+ * @remarks Requires GIP to be initialized and valid.
+ */
+DECLINLINE(bool) SUPIsTscDeltaAvailableForCpuSetIndex(uint32_t iCpuSet)
+{
+ PSUPGLOBALINFOPAGE pGip = g_pSUPGlobalInfoPage;
+ if (pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_ROUGHLY_ZERO)
+ return true;
+ if (RT_LIKELY(iCpuSet < RT_ELEMENTS(pGip->aiCpuFromCpuSetIdx)))
+ {
+ uint16_t iCpu = pGip->aiCpuFromCpuSetIdx[iCpuSet];
+ if (RT_LIKELY(iCpu < pGip->cCpus))
+ {
+ int64_t iTscDelta = pGip->aCPUs[iCpu].i64TSCDelta;
+ if (iTscDelta != INT64_MAX)
+ return true;
+ }
+ }
+ return false;
+}
+
+
+/**
+ * Gets the descriptive GIP mode name.
+ *
+ * @returns The name.
+ * @param pGip Pointer to the GIP.
+ */
+DECLINLINE(const char *) SUPGetGIPModeName(PSUPGLOBALINFOPAGE pGip)
+{
+ AssertReturn(pGip, NULL);
+ switch (pGip->u32Mode)
+ {
+ case SUPGIPMODE_INVARIANT_TSC: return "Invariant";
+ case SUPGIPMODE_SYNC_TSC: return "Synchronous";
+ case SUPGIPMODE_ASYNC_TSC: return "Asynchronous";
+ case SUPGIPMODE_INVALID: return "Invalid";
+ default: return "???";
+ }
+}
+
+
+/**
+ * Gets the descriptive TSC-delta enum name.
+ *
+ * @returns The name.
+ * @param pGip Pointer to the GIP.
+ */
+DECLINLINE(const char *) SUPGetGIPTscDeltaModeName(PSUPGLOBALINFOPAGE pGip)
+{
+ AssertReturn(pGip, NULL);
+ switch (pGip->enmUseTscDelta)
+ {
+ case SUPGIPUSETSCDELTA_NOT_APPLICABLE: return "Not Applicable";
+ case SUPGIPUSETSCDELTA_ZERO_CLAIMED: return "Zero Claimed";
+ case SUPGIPUSETSCDELTA_PRACTICALLY_ZERO: return "Practically Zero";
+ case SUPGIPUSETSCDELTA_ROUGHLY_ZERO: return "Roughly Zero";
+ case SUPGIPUSETSCDELTA_NOT_ZERO: return "Not Zero";
+ default: return "???";
+ }
+}
+
+
+/**
+ * Request for generic VMMR0Entry calls.
+ */
+typedef struct SUPVMMR0REQHDR
+{
+ /** The magic. (SUPVMMR0REQHDR_MAGIC) */
+ uint32_t u32Magic;
+ /** The size of the request. */
+ uint32_t cbReq;
+} SUPVMMR0REQHDR;
+/** Pointer to a ring-0 request header. */
+typedef SUPVMMR0REQHDR *PSUPVMMR0REQHDR;
+/** the SUPVMMR0REQHDR::u32Magic value (Ethan Iverson - The Bad Plus). */
+#define SUPVMMR0REQHDR_MAGIC UINT32_C(0x19730211)
+
+
+/** For the fast ioctl path.
+ * @{
+ */
+/** @see VMMR0_DO_HM_RUN. */
+#define SUP_VMMR0_DO_HM_RUN 0
+/** @see VMMR0_DO_NEM_RUN */
+#define SUP_VMMR0_DO_NEM_RUN 1
+/** @see VMMR0_DO_NOP */
+#define SUP_VMMR0_DO_NOP 2
+/** @} */
+
+/** SUPR3QueryVTCaps capability flags.
+ * @{
+ */
+/** AMD-V support. */
+#define SUPVTCAPS_AMD_V RT_BIT(0)
+/** VT-x support. */
+#define SUPVTCAPS_VT_X RT_BIT(1)
+/** Nested paging is supported. */
+#define SUPVTCAPS_NESTED_PAGING RT_BIT(2)
+/** VT-x: Unrestricted guest execution is supported. */
+#define SUPVTCAPS_VTX_UNRESTRICTED_GUEST RT_BIT(3)
+/** VT-x: VMCS shadowing is supported. */
+#define SUPVTCAPS_VTX_VMCS_SHADOWING RT_BIT(4)
+/** AMD-V: Virtualized VMSAVE/VMLOAD is supported. */
+#define SUPVTCAPS_AMDV_VIRT_VMSAVE_VMLOAD RT_BIT(5)
+/** @} */
+
+/**
+ * Request for generic FNSUPR0SERVICEREQHANDLER calls.
+ */
+typedef struct SUPR0SERVICEREQHDR
+{
+ /** The magic. (SUPR0SERVICEREQHDR_MAGIC) */
+ uint32_t u32Magic;
+ /** The size of the request. */
+ uint32_t cbReq;
+} SUPR0SERVICEREQHDR;
+/** Pointer to a ring-0 service request header. */
+typedef SUPR0SERVICEREQHDR *PSUPR0SERVICEREQHDR;
+/** the SUPVMMR0REQHDR::u32Magic value (Esbjoern Svensson - E.S.P.). */
+#define SUPR0SERVICEREQHDR_MAGIC UINT32_C(0x19640416)
+
+
+/**
+ * Creates a single release event semaphore.
+ *
+ * @returns VBox status code.
+ * @param pSession The session handle of the caller.
+ * @param phEvent Where to return the handle to the event semaphore.
+ */
+SUPDECL(int) SUPSemEventCreate(PSUPDRVSESSION pSession, PSUPSEMEVENT phEvent);
+
+/**
+ * Closes a single release event semaphore handle.
+ *
+ * @returns VBox status code.
+ * @retval VINF_OBJECT_DESTROYED if the semaphore was destroyed.
+ * @retval VINF_SUCCESS if the handle was successfully closed but the semaphore
+ * object remained alive because of other references.
+ *
+ * @param pSession The session handle of the caller.
+ * @param hEvent The handle. Nil is quietly ignored.
+ */
+SUPDECL(int) SUPSemEventClose(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent);
+
+/**
+ * Signals a single release event semaphore.
+ *
+ * @returns VBox status code.
+ * @param pSession The session handle of the caller.
+ * @param hEvent The semaphore handle.
+ */
+SUPDECL(int) SUPSemEventSignal(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent);
+
+#ifdef IN_RING0
+/**
+ * Waits on a single release event semaphore, not interruptible.
+ *
+ * @returns VBox status code.
+ * @param pSession The session handle of the caller.
+ * @param hEvent The semaphore handle.
+ * @param cMillies The number of milliseconds to wait.
+ * @remarks Not available in ring-3.
+ */
+SUPDECL(int) SUPSemEventWait(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent, uint32_t cMillies);
+#endif
+
+/**
+ * Waits on a single release event semaphore, interruptible.
+ *
+ * @returns VBox status code.
+ * @param pSession The session handle of the caller.
+ * @param hEvent The semaphore handle.
+ * @param cMillies The number of milliseconds to wait.
+ */
+SUPDECL(int) SUPSemEventWaitNoResume(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent, uint32_t cMillies);
+
+/**
+ * Waits on a single release event semaphore, interruptible.
+ *
+ * @returns VBox status code.
+ * @param pSession The session handle of the caller.
+ * @param hEvent The semaphore handle.
+ * @param uNsTimeout The deadline given on the RTTimeNanoTS() clock.
+ */
+SUPDECL(int) SUPSemEventWaitNsAbsIntr(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent, uint64_t uNsTimeout);
+
+/**
+ * Waits on a single release event semaphore, interruptible.
+ *
+ * @returns VBox status code.
+ * @param pSession The session handle of the caller.
+ * @param hEvent The semaphore handle.
+ * @param cNsTimeout The number of nanoseconds to wait.
+ */
+SUPDECL(int) SUPSemEventWaitNsRelIntr(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent, uint64_t cNsTimeout);
+
+/**
+ * Gets the best timeout resolution that SUPSemEventWaitNsAbsIntr and
+ * SUPSemEventWaitNsAbsIntr can do.
+ *
+ * @returns The resolution in nanoseconds.
+ * @param pSession The session handle of the caller.
+ */
+SUPDECL(uint32_t) SUPSemEventGetResolution(PSUPDRVSESSION pSession);
+
+
+/**
+ * Creates a multiple release event semaphore.
+ *
+ * @returns VBox status code.
+ * @param pSession The session handle of the caller.
+ * @param phEventMulti Where to return the handle to the event semaphore.
+ */
+SUPDECL(int) SUPSemEventMultiCreate(PSUPDRVSESSION pSession, PSUPSEMEVENTMULTI phEventMulti);
+
+/**
+ * Closes a multiple release event semaphore handle.
+ *
+ * @returns VBox status code.
+ * @retval VINF_OBJECT_DESTROYED if the semaphore was destroyed.
+ * @retval VINF_SUCCESS if the handle was successfully closed but the semaphore
+ * object remained alive because of other references.
+ *
+ * @param pSession The session handle of the caller.
+ * @param hEventMulti The handle. Nil is quietly ignored.
+ */
+SUPDECL(int) SUPSemEventMultiClose(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti);
+
+/**
+ * Signals a multiple release event semaphore.
+ *
+ * @returns VBox status code.
+ * @param pSession The session handle of the caller.
+ * @param hEventMulti The semaphore handle.
+ */
+SUPDECL(int) SUPSemEventMultiSignal(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti);
+
+/**
+ * Resets a multiple release event semaphore.
+ *
+ * @returns VBox status code.
+ * @param pSession The session handle of the caller.
+ * @param hEventMulti The semaphore handle.
+ */
+SUPDECL(int) SUPSemEventMultiReset(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti);
+
+#ifdef IN_RING0
+/**
+ * Waits on a multiple release event semaphore, not interruptible.
+ *
+ * @returns VBox status code.
+ * @param pSession The session handle of the caller.
+ * @param hEventMulti The semaphore handle.
+ * @param cMillies The number of milliseconds to wait.
+ * @remarks Not available in ring-3.
+ */
+SUPDECL(int) SUPSemEventMultiWait(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti, uint32_t cMillies);
+#endif
+
+/**
+ * Waits on a multiple release event semaphore, interruptible.
+ *
+ * @returns VBox status code.
+ * @param pSession The session handle of the caller.
+ * @param hEventMulti The semaphore handle.
+ * @param cMillies The number of milliseconds to wait.
+ */
+SUPDECL(int) SUPSemEventMultiWaitNoResume(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti, uint32_t cMillies);
+
+/**
+ * Waits on a multiple release event semaphore, interruptible.
+ *
+ * @returns VBox status code.
+ * @param pSession The session handle of the caller.
+ * @param hEventMulti The semaphore handle.
+ * @param uNsTimeout The deadline given on the RTTimeNanoTS() clock.
+ */
+SUPDECL(int) SUPSemEventMultiWaitNsAbsIntr(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti, uint64_t uNsTimeout);
+
+/**
+ * Waits on a multiple release event semaphore, interruptible.
+ *
+ * @returns VBox status code.
+ * @param pSession The session handle of the caller.
+ * @param hEventMulti The semaphore handle.
+ * @param cNsTimeout The number of nanoseconds to wait.
+ */
+SUPDECL(int) SUPSemEventMultiWaitNsRelIntr(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti, uint64_t cNsTimeout);
+
+/**
+ * Gets the best timeout resolution that SUPSemEventMultiWaitNsAbsIntr and
+ * SUPSemEventMultiWaitNsRelIntr can do.
+ *
+ * @returns The resolution in nanoseconds.
+ * @param pSession The session handle of the caller.
+ */
+SUPDECL(uint32_t) SUPSemEventMultiGetResolution(PSUPDRVSESSION pSession);
+
+
+#ifdef IN_RING3
+
+/** @defgroup grp_sup_r3 SUP Host Context Ring-3 API
+ * @{
+ */
+
+/**
+ * Installs the support library.
+ *
+ * @returns VBox status code.
+ */
+SUPR3DECL(int) SUPR3Install(void);
+
+/**
+ * Uninstalls the support library.
+ *
+ * @returns VBox status code.
+ */
+SUPR3DECL(int) SUPR3Uninstall(void);
+
+/**
+ * Trusted main entry point.
+ *
+ * This is exported as "TrustedMain" by the dynamic libraries which contains the
+ * "real" application binary for which the hardened stub is built. The entry
+ * point is invoked upon successful initialization of the support library and
+ * runtime.
+ *
+ * @returns main kind of exit code.
+ * @param argc The argument count.
+ * @param argv The argument vector.
+ * @param envp The environment vector.
+ */
+typedef DECLCALLBACKTYPE(int, FNSUPTRUSTEDMAIN,(int argc, char **argv, char **envp));
+/** Pointer to FNSUPTRUSTEDMAIN(). */
+typedef FNSUPTRUSTEDMAIN *PFNSUPTRUSTEDMAIN;
+
+/** Which operation failed. */
+typedef enum SUPINITOP
+{
+ /** Invalid. */
+ kSupInitOp_Invalid = 0,
+ /** Installation integrity error. */
+ kSupInitOp_Integrity,
+ /** Setuid related. */
+ kSupInitOp_RootCheck,
+ /** Driver related. */
+ kSupInitOp_Driver,
+ /** IPRT init related. */
+ kSupInitOp_IPRT,
+ /** Miscellaneous. */
+ kSupInitOp_Misc,
+ /** Place holder. */
+ kSupInitOp_End
+} SUPINITOP;
+
+/**
+ * Trusted error entry point, optional.
+ *
+ * This is exported as "TrustedError" by the dynamic libraries which contains
+ * the "real" application binary for which the hardened stub is built. The
+ * hardened main() must specify SUPSECMAIN_FLAGS_TRUSTED_ERROR when calling
+ * SUPR3HardenedMain.
+ *
+ * @param pszWhere Where the error occurred (function name).
+ * @param enmWhat Which operation went wrong.
+ * @param rc The status code.
+ * @param pszMsgFmt Error message format string.
+ * @param va The message format arguments.
+ */
+typedef DECLCALLBACKTYPE(void, FNSUPTRUSTEDERROR,(const char *pszWhere, SUPINITOP enmWhat, int rc,
+ const char *pszMsgFmt, va_list va)) RT_IPRT_FORMAT_ATTR(4, 0);
+/** Pointer to FNSUPTRUSTEDERROR. */
+typedef FNSUPTRUSTEDERROR *PFNSUPTRUSTEDERROR;
+
+/**
+ * Secure main.
+ *
+ * This is used for the set-user-ID-on-execute binaries on unixy systems
+ * and when using the open-vboxdrv-via-root-service setup on Windows.
+ *
+ * This function will perform the integrity checks of the VirtualBox
+ * installation, open the support driver, open the root service (later),
+ * and load the DLL corresponding to \a pszProgName and execute its main
+ * function.
+ *
+ * @returns Return code appropriate for main().
+ *
+ * @param pszProgName The program name. This will be used to figure out which
+ * DLL/SO/DYLIB to load and execute.
+ * @param fFlags SUPSECMAIN_FLAGS_XXX.
+ * @param argc The argument count.
+ * @param argv The argument vector.
+ * @param envp The environment vector.
+ */
+DECLHIDDEN(int) SUPR3HardenedMain(const char *pszProgName, uint32_t fFlags, int argc, char **argv, char **envp);
+
+/** @name SUPSECMAIN_FLAGS_XXX - SUPR3HardenedMain flags.
+ * @{ */
+/** Don't open the device. (Intended for VirtualBox without -startvm.) */
+#define SUPSECMAIN_FLAGS_DONT_OPEN_DEV RT_BIT_32(0)
+/** The hardened DLL has a "TrustedError" function (see FNSUPTRUSTEDERROR). */
+#define SUPSECMAIN_FLAGS_TRUSTED_ERROR RT_BIT_32(1)
+/** Hack for making VirtualBoxVM use VirtualBox.dylib on Mac OS X.
+ * @note Not used since 6.0 */
+#define SUPSECMAIN_FLAGS_OSX_VM_APP RT_BIT_32(2)
+/** The first process.
+ * @internal */
+#define SUPSECMAIN_FLAGS_FIRST_PROCESS RT_BIT_32(3)
+/** Program binary location mask. */
+#define SUPSECMAIN_FLAGS_LOC_MASK UINT32_C(0x00000030)
+/** Default binary location is the application binary directory. Does
+ * not need to be given explicitly (it's 0). */
+#define SUPSECMAIN_FLAGS_LOC_APP_BIN UINT32_C(0x00000000)
+/** The binary is located in the testcase directory instead of the
+ * default application binary directory. */
+#define SUPSECMAIN_FLAGS_LOC_TESTCASE UINT32_C(0x00000010)
+/** The binary is located in a nested application bundle under Resources/ in the
+ * main Mac OS X application (think Resources/VirtualBoxVM.app). */
+#define SUPSECMAIN_FLAGS_LOC_OSX_HLP_APP UINT32_C(0x00000020)
+/** Force driverless mode. */
+#define SUPSECMAIN_FLAGS_DRIVERLESS RT_BIT_32(8)
+/** Driverless IEM-only mode is allowed, so don't fail fatally just because
+ * the VBox support driver is unavailable. */
+#define SUPSECMAIN_FLAGS_DRIVERLESS_IEM_ALLOWED RT_BIT_32(9)
+#ifdef VBOX_WITH_DRIVERLESS_NEM_FALLBACK
+/** Driverless NEM is a fallback posibility, so don't fail fatally just
+ * because the VBox support driver is unavailable.
+ * This may imply checking NEM requirements, depending on the host.
+ * @note Not supported on Windows. */
+# define SUPSECMAIN_FLAGS_DRIVERLESS_NEM_FALLBACK RT_BIT_32(10)
+#endif
+
+/** @} */
+
+/**
+ * Initializes the support library.
+ *
+ * Each successful call to SUPR3Init() or SUPR3InitEx must be countered by a
+ * call to SUPR3Term(false).
+ *
+ * @returns VBox status code.
+ * @param ppSession Where to store the session handle. Defaults to NULL.
+ */
+SUPR3DECL(int) SUPR3Init(PSUPDRVSESSION *ppSession);
+
+/**
+ * Initializes the support library, extended version.
+ *
+ * Each successful call to SUPR3Init() or SUPR3InitEx must be countered by a
+ * call to SUPR3Term(false).
+ *
+ * @returns VBox status code.
+ * @param fFlags SUPR3INIT_F_XXX
+ * @param ppSession Where to store the session handle. Defaults to NULL.
+ */
+SUPR3DECL(int) SUPR3InitEx(uint32_t fFlags, PSUPDRVSESSION *ppSession);
+/** @name SUPR3INIT_F_XXX - Flags for SUPR3InitEx
+ * @{ */
+/** Unrestricted access. */
+#define SUPR3INIT_F_UNRESTRICTED RT_BIT_32(0)
+/** Limited access (for Main). */
+#define SUPR3INIT_F_LIMITED RT_BIT_32(1)
+/** Force driverless mode. */
+#define SUPR3INIT_F_DRIVERLESS RT_BIT_32(2)
+/** Allow driverless IEM mode if the VBox support driver is unavailable.
+ * @see SUPSECMAIN_FLAGS_DRIVERLESS_IEM_ALLOWED */
+#define SUPR3INIT_F_DRIVERLESS_IEM_ALLOWED RT_BIT_32(3)
+#ifdef VBOX_WITH_DRIVERLESS_NEM_FALLBACK
+/** Allow driverless NEM mode as fallback if the VBox support driver is unavailable.
+ * @see SUPSECMAIN_FLAGS_DRIVERLESS_NEM_FALLBACK */
+# define SUPR3INIT_F_DRIVERLESS_NEM_FALLBACK RT_BIT_32(4)
+#endif
+/** Mask with all the flags that may trigger driverless mode. */
+#ifdef VBOX_WITH_DRIVERLESS_NEM_FALLBACK
+# define SUPR3INIT_F_DRIVERLESS_MASK UINT32_C(0x0000001c)
+#else
+# define SUPR3INIT_F_DRIVERLESS_MASK UINT32_C(0x0000000c)
+#endif
+/** @} */
+
+/**
+ * Terminates the support library.
+ *
+ * @returns VBox status code.
+ * @param fForced Forced termination. This means to ignore the
+ * init call count and just terminated.
+ */
+#ifdef __cplusplus
+SUPR3DECL(int) SUPR3Term(bool fForced = false);
+#else
+SUPR3DECL(int) SUPR3Term(int fForced);
+#endif
+
+/**
+ * Check if the support library is operating in driverless mode.
+ *
+ * @returns true/false accordingly.
+ * @see SUPR3INIT_F_DRIVERLESS_IEM_ALLOWED,
+ * SUPR3INIT_F_DRIVERLESS_NEM_FALLBACK
+ */
+SUPR3DECL(bool) SUPR3IsDriverless(void);
+
+/**
+ * Sets the ring-0 VM handle for use with fast IOCtls.
+ *
+ * @returns VBox status code.
+ * @param pVMR0 The ring-0 VM handle.
+ * NIL_RTR0PTR can be used to unset the handle when the
+ * VM is about to be destroyed.
+ */
+SUPR3DECL(int) SUPR3SetVMForFastIOCtl(PVMR0 pVMR0);
+
+/**
+ * Calls the HC R0 VMM entry point.
+ * See VMMR0Entry() for more details.
+ *
+ * @returns error code specific to uFunction.
+ * @param pVMR0 Pointer to the Ring-0 (Host Context) mapping of the VM structure.
+ * @param idCpu The virtual CPU ID.
+ * @param uOperation Operation to execute.
+ * @param pvArg Argument.
+ */
+SUPR3DECL(int) SUPR3CallVMMR0(PVMR0 pVMR0, VMCPUID idCpu, unsigned uOperation, void *pvArg);
+
+/**
+ * Variant of SUPR3CallVMMR0, except that this takes the fast ioclt path
+ * regardsless of compile-time defaults.
+ *
+ * @returns VBox status code.
+ * @param pVMR0 The ring-0 VM handle.
+ * @param uOperation The operation; only the SUP_VMMR0_DO_* ones are valid.
+ * @param idCpu The virtual CPU ID.
+ */
+SUPR3DECL(int) SUPR3CallVMMR0Fast(PVMR0 pVMR0, unsigned uOperation, VMCPUID idCpu);
+
+/**
+ * Calls the HC R0 VMM entry point, in a safer but slower manner than
+ * SUPR3CallVMMR0. When entering using this call the R0 components can call
+ * into the host kernel (i.e. use the SUPR0 and RT APIs).
+ *
+ * See VMMR0Entry() for more details.
+ *
+ * @returns error code specific to uFunction.
+ * @param pVMR0 Pointer to the Ring-0 (Host Context) mapping of the VM structure.
+ * @param idCpu The virtual CPU ID.
+ * @param uOperation Operation to execute.
+ * @param u64Arg Constant argument.
+ * @param pReqHdr Pointer to a request header. Optional.
+ * This will be copied in and out of kernel space. There currently is a size
+ * limit on this, just below 4KB.
+ */
+SUPR3DECL(int) SUPR3CallVMMR0Ex(PVMR0 pVMR0, VMCPUID idCpu, unsigned uOperation, uint64_t u64Arg, PSUPVMMR0REQHDR pReqHdr);
+
+/**
+ * Calls a ring-0 service.
+ *
+ * The operation and the request packet is specific to the service.
+ *
+ * @returns error code specific to uFunction.
+ * @param pszService The service name.
+ * @param cchService The length of the service name.
+ * @param uOperation The request number.
+ * @param u64Arg Constant argument.
+ * @param pReqHdr Pointer to a request header. Optional.
+ * This will be copied in and out of kernel space. There currently is a size
+ * limit on this, just below 4KB.
+ */
+SUPR3DECL(int) SUPR3CallR0Service(const char *pszService, size_t cchService, uint32_t uOperation, uint64_t u64Arg, PSUPR0SERVICEREQHDR pReqHdr);
+
+/** Which logger. */
+typedef enum SUPLOGGER
+{
+ SUPLOGGER_DEBUG = 1,
+ SUPLOGGER_RELEASE
+} SUPLOGGER;
+
+/**
+ * Changes the settings of the specified ring-0 logger.
+ *
+ * @returns VBox status code.
+ * @param enmWhich Which logger.
+ * @param pszFlags The flags settings.
+ * @param pszGroups The groups settings.
+ * @param pszDest The destination specificier.
+ */
+SUPR3DECL(int) SUPR3LoggerSettings(SUPLOGGER enmWhich, const char *pszFlags, const char *pszGroups, const char *pszDest);
+
+/**
+ * Creates a ring-0 logger instance.
+ *
+ * @returns VBox status code.
+ * @param enmWhich Which logger to create.
+ * @param pszFlags The flags settings.
+ * @param pszGroups The groups settings.
+ * @param pszDest The destination specificier.
+ */
+SUPR3DECL(int) SUPR3LoggerCreate(SUPLOGGER enmWhich, const char *pszFlags, const char *pszGroups, const char *pszDest);
+
+/**
+ * Destroys a ring-0 logger instance.
+ *
+ * @returns VBox status code.
+ * @param enmWhich Which logger.
+ */
+SUPR3DECL(int) SUPR3LoggerDestroy(SUPLOGGER enmWhich);
+
+/**
+ * Queries the paging mode of the host OS.
+ *
+ * @returns The paging mode.
+ */
+SUPR3DECL(SUPPAGINGMODE) SUPR3GetPagingMode(void);
+
+/**
+ * Allocate zero-filled pages.
+ *
+ * Use this to allocate a number of pages suitable for seeding / locking.
+ * Call SUPR3PageFree() to free the pages once done with them.
+ *
+ * @returns VBox status.
+ * @param cPages Number of pages to allocate.
+ * @param fFlags SUP_PAGE_ALLOC_F_XXX
+ * @param ppvPages Where to store the base pointer to the allocated pages.
+ */
+SUPR3DECL(int) SUPR3PageAlloc(size_t cPages, uint32_t fFlags, void **ppvPages);
+
+/** @name SUP_PAGE_ALLOC_F_XXX - SUPR3PageAlloc flags.
+ * @{ */
+/** Use large pages if available. */
+#define SUP_PAGE_ALLOC_F_LARGE_PAGES RT_BIT_32(0)
+/** Advice that the allocated pages will probably be locked by
+ * RTR0MemObjLockUser later, so play nice if needed. */
+#define SUP_PAGE_ALLOC_F_FOR_LOCKING RT_BIT_32(1)
+/** Mask of valid flags. */
+#define SUP_PAGE_ALLOC_F_VALID_MASK UINT32_C(0x00000003)
+/** @} */
+
+/**
+ * Frees pages allocated with SUPR3PageAlloc().
+ *
+ * @returns VBox status.
+ * @param pvPages Pointer returned by SUPR3PageAlloc().
+ * @param cPages Number of pages that was allocated.
+ */
+SUPR3DECL(int) SUPR3PageFree(void *pvPages, size_t cPages);
+
+/**
+ * Allocate non-zeroed, locked, pages with user and, optionally, kernel
+ * mappings.
+ *
+ * Use SUPR3PageFreeEx() to free memory allocated with this function.
+ *
+ * @returns VBox status code.
+ * @param cPages The number of pages to allocate.
+ * @param fFlags Flags, reserved. Must be zero.
+ * @param ppvPages Where to store the address of the user mapping.
+ * @param pR0Ptr Where to store the address of the kernel mapping.
+ * NULL if no kernel mapping is desired.
+ * @param paPages Where to store the physical addresses of each page.
+ * Optional.
+ */
+SUPR3DECL(int) SUPR3PageAllocEx(size_t cPages, uint32_t fFlags, void **ppvPages, PRTR0PTR pR0Ptr, PSUPPAGE paPages);
+
+/**
+ * Maps a portion of a ring-3 only allocation into kernel space.
+ *
+ * @returns VBox status code.
+ *
+ * @param pvR3 The address SUPR3PageAllocEx return.
+ * @param off Offset to start mapping at. Must be page aligned.
+ * @param cb Number of bytes to map. Must be page aligned.
+ * @param fFlags Flags, must be zero.
+ * @param pR0Ptr Where to store the address on success.
+ *
+ */
+SUPR3DECL(int) SUPR3PageMapKernel(void *pvR3, uint32_t off, uint32_t cb, uint32_t fFlags, PRTR0PTR pR0Ptr);
+
+/**
+ * Changes the protection of
+ *
+ * @returns VBox status code.
+ * @retval VERR_NOT_SUPPORTED if the OS doesn't allow us to change page level
+ * protection. See also RTR0MemObjProtect.
+ *
+ * @param pvR3 The ring-3 address SUPR3PageAllocEx returned.
+ * @param R0Ptr The ring-0 address SUPR3PageAllocEx returned if it
+ * is desired that the corresponding ring-0 page
+ * mappings should change protection as well. Pass
+ * NIL_RTR0PTR if the ring-0 pages should remain
+ * unaffected.
+ * @param off Offset to start at which to start chagning the page
+ * level protection. Must be page aligned.
+ * @param cb Number of bytes to change. Must be page aligned.
+ * @param fProt The new page level protection, either a combination
+ * of RTMEM_PROT_READ, RTMEM_PROT_WRITE and
+ * RTMEM_PROT_EXEC, or just RTMEM_PROT_NONE.
+ */
+SUPR3DECL(int) SUPR3PageProtect(void *pvR3, RTR0PTR R0Ptr, uint32_t off, uint32_t cb, uint32_t fProt);
+
+/**
+ * Free pages allocated by SUPR3PageAllocEx.
+ *
+ * @returns VBox status code.
+ * @param pvPages The address of the user mapping.
+ * @param cPages The number of pages.
+ */
+SUPR3DECL(int) SUPR3PageFreeEx(void *pvPages, size_t cPages);
+
+/**
+ * Allocated memory with page aligned memory with a contiguous and locked physical
+ * memory backing below 4GB.
+ *
+ * @returns Pointer to the allocated memory (virtual address).
+ * *pHCPhys is set to the physical address of the memory.
+ * If ppvR0 isn't NULL, *ppvR0 is set to the ring-0 mapping.
+ * The returned memory must be freed using SUPR3ContFree().
+ * @returns NULL on failure.
+ * @param cPages Number of pages to allocate.
+ * @param pR0Ptr Where to store the ring-0 mapping of the allocation. (optional)
+ * @param pHCPhys Where to store the physical address of the memory block.
+ *
+ * @remark This 2nd version of this API exists because we're not able to map the
+ * ring-3 mapping executable on WIN64. This is a serious problem in regard to
+ * the world switchers.
+ */
+SUPR3DECL(void *) SUPR3ContAlloc(size_t cPages, PRTR0PTR pR0Ptr, PRTHCPHYS pHCPhys);
+
+/**
+ * Frees memory allocated with SUPR3ContAlloc().
+ *
+ * @returns VBox status code.
+ * @param pv Pointer to the memory block which should be freed.
+ * @param cPages Number of pages to be freed.
+ */
+SUPR3DECL(int) SUPR3ContFree(void *pv, size_t cPages);
+
+/**
+ * Allocated non contiguous physical memory below 4GB.
+ *
+ * The memory isn't zeroed.
+ *
+ * @returns VBox status code.
+ * @returns NULL on failure.
+ * @param cPages Number of pages to allocate.
+ * @param ppvPages Where to store the pointer to the allocated memory.
+ * The pointer stored here on success must be passed to
+ * SUPR3LowFree when the memory should be released.
+ * @param ppvPagesR0 Where to store the ring-0 pointer to the allocated memory. optional.
+ * @param paPages Where to store the physical addresses of the individual pages.
+ */
+SUPR3DECL(int) SUPR3LowAlloc(size_t cPages, void **ppvPages, PRTR0PTR ppvPagesR0, PSUPPAGE paPages);
+
+/**
+ * Frees memory allocated with SUPR3LowAlloc().
+ *
+ * @returns VBox status code.
+ * @param pv Pointer to the memory block which should be freed.
+ * @param cPages Number of pages that was allocated.
+ */
+SUPR3DECL(int) SUPR3LowFree(void *pv, size_t cPages);
+
+/**
+ * Load a module into R0 HC.
+ *
+ * This will verify the file integrity in a similar manner as
+ * SUPR3HardenedVerifyFile before loading it.
+ *
+ * @returns VBox status code.
+ * @param pszFilename The path to the image file.
+ * @param pszModule The module name. Max 32 bytes.
+ * @param ppvImageBase Where to store the image address.
+ * @param pErrInfo Where to return extended error information.
+ * Optional.
+ */
+SUPR3DECL(int) SUPR3LoadModule(const char *pszFilename, const char *pszModule, void **ppvImageBase, PRTERRINFO pErrInfo);
+
+/**
+ * Load a module into R0 HC.
+ *
+ * This will verify the file integrity in a similar manner as
+ * SUPR3HardenedVerifyFile before loading it.
+ *
+ * @returns VBox status code.
+ * @param pszFilename The path to the image file.
+ * @param pszModule The module name. Max 32 bytes.
+ * @param pszSrvReqHandler The name of the service request handler entry
+ * point. See FNSUPR0SERVICEREQHANDLER.
+ * @param ppvImageBase Where to store the image address.
+ */
+SUPR3DECL(int) SUPR3LoadServiceModule(const char *pszFilename, const char *pszModule,
+ const char *pszSrvReqHandler, void **ppvImageBase);
+
+/**
+ * Frees a R0 HC module.
+ *
+ * @returns VBox status code.
+ * @param pvImageBase The base address of the image to free.
+ * @remark This will not actually 'free' the module, there are of course usage counting.
+ */
+SUPR3DECL(int) SUPR3FreeModule(void *pvImageBase);
+
+/**
+ * Lock down the module loader interface.
+ *
+ * This will lock down the module loader interface. No new modules can be
+ * loaded and all loaded modules can no longer be freed.
+ *
+ * @returns VBox status code.
+ * @param pErrInfo Where to return extended error information.
+ * Optional.
+ */
+SUPR3DECL(int) SUPR3LockDownLoader(PRTERRINFO pErrInfo);
+
+/**
+ * Get the address of a symbol in a ring-0 module.
+ *
+ * @returns VBox status code.
+ * @param pvImageBase The base address of the image to search.
+ * @param pszSymbol Symbol name. If it's value is less than 64k it's treated like a
+ * ordinal value rather than a string pointer.
+ * @param ppvValue Where to store the symbol value.
+ */
+SUPR3DECL(int) SUPR3GetSymbolR0(void *pvImageBase, const char *pszSymbol, void **ppvValue);
+
+/**
+ * Load R0 HC VMM code.
+ *
+ * @returns VBox status code.
+ * @deprecated Use SUPR3LoadModule(pszFilename, "VMMR0.r0", &pvImageBase)
+ * @param pszFilename Full path to the VMMR0.r0 file (silly).
+ * @param pErrInfo Where to return extended error information.
+ * Optional.
+ */
+SUPR3DECL(int) SUPR3LoadVMM(const char *pszFilename, PRTERRINFO pErrInfo);
+
+/**
+ * Unloads R0 HC VMM code.
+ *
+ * @returns VBox status code.
+ * @deprecated Use SUPR3FreeModule().
+ */
+SUPR3DECL(int) SUPR3UnloadVMM(void);
+
+/**
+ * Get the physical address of the GIP.
+ *
+ * @returns VBox status code.
+ * @param pHCPhys Where to store the physical address of the GIP.
+ */
+SUPR3DECL(int) SUPR3GipGetPhys(PRTHCPHYS pHCPhys);
+
+/**
+ * Initializes only the bits relevant for the SUPR3HardenedVerify* APIs.
+ *
+ * This is for users that don't necessarily need to initialize the whole of
+ * SUPLib. There is no harm in calling this one more time.
+ *
+ * @returns VBox status code.
+ * @remarks Currently not counted, so only call once.
+ */
+SUPR3DECL(int) SUPR3HardenedVerifyInit(void);
+
+/**
+ * Reverses the effect of SUPR3HardenedVerifyInit if SUPR3InitEx hasn't been
+ * called.
+ *
+ * Ignored if the support library was initialized using SUPR3Init or
+ * SUPR3InitEx.
+ *
+ * @returns VBox status code.
+ */
+SUPR3DECL(int) SUPR3HardenedVerifyTerm(void);
+
+/**
+ * Verifies the integrity of a file, and optionally opens it.
+ *
+ * The integrity check is for whether the file is suitable for loading into
+ * the hypervisor or VM process. The integrity check may include verifying
+ * the authenticode/elfsign/whatever signature of the file, which can take
+ * a little while.
+ *
+ * @returns VBox status code. On failure it will have printed a LogRel message.
+ *
+ * @param pszFilename The file.
+ * @param pszWhat For the LogRel on failure.
+ * @param phFile Where to store the handle to the opened file. This is optional, pass NULL
+ * if the file should not be opened.
+ * @deprecated Write a new one.
+ */
+SUPR3DECL(int) SUPR3HardenedVerifyFile(const char *pszFilename, const char *pszWhat, PRTFILE phFile);
+
+/**
+ * Verifies the integrity of a the current process, including the image
+ * location and that the invocation was absolute.
+ *
+ * This must currently be called after initializing the runtime. The intended
+ * audience is set-uid-to-root applications, root services and similar.
+ *
+ * @returns VBox status code. On failure
+ * message.
+ * @param pszArgv0 The first argument to main().
+ * @param fInternal Set this to @c true if this is an internal
+ * VirtualBox application. Otherwise pass @c false.
+ * @param pErrInfo Where to return extended error information.
+ */
+SUPR3DECL(int) SUPR3HardenedVerifySelf(const char *pszArgv0, bool fInternal, PRTERRINFO pErrInfo);
+
+/**
+ * Verifies the integrity of an installation directory.
+ *
+ * The integrity check verifies that the directory cannot be tampered with by
+ * normal users on the system. On Unix this translates to root ownership and
+ * no symbolic linking.
+ *
+ * @returns VBox status code. On failure a message will be stored in @a pszErr.
+ *
+ * @param pszDirPath The directory path.
+ * @param fRecursive Whether the check should be recursive or
+ * not. When set, all sub-directores will be checked,
+ * including files (@a fCheckFiles is ignored).
+ * @param fCheckFiles Whether to apply the same basic integrity check to
+ * the files in the directory as the directory itself.
+ * @param pErrInfo Where to return extended error information.
+ * Optional.
+ */
+SUPR3DECL(int) SUPR3HardenedVerifyDir(const char *pszDirPath, bool fRecursive, bool fCheckFiles, PRTERRINFO pErrInfo);
+
+/**
+ * Verifies the integrity of a plug-in module.
+ *
+ * This is similar to SUPR3HardenedLdrLoad, except it does not load the module
+ * and that the module does not have to be shipped with VirtualBox.
+ *
+ * @returns VBox status code. On failure a message will be stored in @a pszErr.
+ *
+ * @param pszFilename The filename of the plug-in module (nothing can be
+ * omitted here).
+ * @param pErrInfo Where to return extended error information.
+ * Optional.
+ */
+SUPR3DECL(int) SUPR3HardenedVerifyPlugIn(const char *pszFilename, PRTERRINFO pErrInfo);
+
+/**
+ * Same as RTLdrLoad() but will verify the files it loads (hardened builds).
+ *
+ * Will add dll suffix if missing and try load the file.
+ *
+ * @returns iprt status code.
+ * @param pszFilename Image filename. This must have a path.
+ * @param phLdrMod Where to store the handle to the loaded module.
+ * @param fFlags See RTLDRLOAD_FLAGS_XXX.
+ * @param pErrInfo Where to return extended error information.
+ * Optional.
+ */
+SUPR3DECL(int) SUPR3HardenedLdrLoad(const char *pszFilename, PRTLDRMOD phLdrMod, uint32_t fFlags, PRTERRINFO pErrInfo);
+
+/**
+ * Same as RTLdrLoadAppPriv() but it will verify the files it loads (hardened
+ * builds).
+ *
+ * Will add dll suffix to the file if missing, then look for it in the
+ * architecture dependent application directory.
+ *
+ * @returns iprt status code.
+ * @param pszFilename Image filename.
+ * @param phLdrMod Where to store the handle to the loaded module.
+ * @param fFlags See RTLDRLOAD_FLAGS_XXX.
+ * @param pErrInfo Where to return extended error information.
+ * Optional.
+ */
+SUPR3DECL(int) SUPR3HardenedLdrLoadAppPriv(const char *pszFilename, PRTLDRMOD phLdrMod, uint32_t fFlags, PRTERRINFO pErrInfo);
+
+/**
+ * Same as RTLdrLoad() but will verify the files it loads (hardened builds).
+ *
+ * This differs from SUPR3HardenedLdrLoad() in that it can load modules from
+ * extension packs and anything else safely installed on the system, provided
+ * they pass the hardening tests.
+ *
+ * @returns iprt status code.
+ * @param pszFilename The full path to the module, with extension.
+ * @param phLdrMod Where to store the handle to the loaded module.
+ * @param pErrInfo Where to return extended error information.
+ * Optional.
+ */
+SUPR3DECL(int) SUPR3HardenedLdrLoadPlugIn(const char *pszFilename, PRTLDRMOD phLdrMod, PRTERRINFO pErrInfo);
+
+/**
+ * Check if the host kernel can run in VMX root mode.
+ *
+ * @returns VINF_SUCCESS if supported, error code indicating why if not.
+ * @param ppszWhy Where to return an explanatory message on failure.
+ */
+SUPR3DECL(int) SUPR3QueryVTxSupported(const char **ppszWhy);
+
+/**
+ * Return VT-x/AMD-V capabilities.
+ *
+ * @returns VINF_SUCCESS if supported, error code indicating why if not.
+ * @param pfCaps Pointer to capability dword (out).
+ * @todo Intended for main, which means we need to relax the privilege requires
+ * when accessing certain vboxdrv functions.
+ */
+SUPR3DECL(int) SUPR3QueryVTCaps(uint32_t *pfCaps);
+
+/**
+ * Check if NEM is supported when no VT-x/AMD-V is indicated by the CPU.
+ *
+ * This is really only for the windows case where we're running in a root
+ * partition and isn't allowed to use the hardware directly.
+ *
+ * @returns True if NEM API support, false if not.
+ */
+SUPR3DECL(bool) SUPR3IsNemSupportedWhenNoVtxOrAmdV(void);
+
+/**
+ * Open the tracer.
+ *
+ * @returns VBox status code.
+ * @param uCookie Cookie identifying the tracer we expect to talk to.
+ * @param uArg Tracer specific open argument.
+ */
+SUPR3DECL(int) SUPR3TracerOpen(uint32_t uCookie, uintptr_t uArg);
+
+/**
+ * Closes the tracer.
+ *
+ * @returns VBox status code.
+ */
+SUPR3DECL(int) SUPR3TracerClose(void);
+
+/**
+ * Perform an I/O request on the tracer.
+ *
+ * @returns VBox status.
+ * @param uCmd The tracer command.
+ * @param uArg The argument.
+ * @param piRetVal Where to store the tracer return value.
+ */
+SUPR3DECL(int) SUPR3TracerIoCtl(uintptr_t uCmd, uintptr_t uArg, int32_t *piRetVal);
+
+/**
+ * Registers the user module with the tracer.
+ *
+ * @returns VBox status code.
+ * @param hModNative Native module handle. Pass ~(uintptr_t)0 if not
+ * at hand.
+ * @param pszModule The module name.
+ * @param pVtgHdr The VTG header.
+ * @param uVtgHdrAddr The address to which the VTG header is loaded
+ * in the relevant execution context.
+ * @param fFlags See SUP_TRACER_UMOD_FLAGS_XXX
+ */
+SUPR3DECL(int) SUPR3TracerRegisterModule(uintptr_t hModNative, const char *pszModule, struct VTGOBJHDR *pVtgHdr,
+ RTUINTPTR uVtgHdrAddr, uint32_t fFlags);
+
+/**
+ * Deregisters the user module.
+ *
+ * @returns VBox status code.
+ * @param pVtgHdr The VTG header.
+ */
+SUPR3DECL(int) SUPR3TracerDeregisterModule(struct VTGOBJHDR *pVtgHdr);
+
+/**
+ * Fire the probe.
+ *
+ * @param pVtgProbeLoc The probe location record.
+ * @param uArg0 Raw probe argument 0.
+ * @param uArg1 Raw probe argument 1.
+ * @param uArg2 Raw probe argument 2.
+ * @param uArg3 Raw probe argument 3.
+ * @param uArg4 Raw probe argument 4.
+ */
+SUPDECL(void) SUPTracerFireProbe(struct VTGPROBELOC *pVtgProbeLoc, uintptr_t uArg0, uintptr_t uArg1, uintptr_t uArg2,
+ uintptr_t uArg3, uintptr_t uArg4);
+
+/**
+ * Attempts to read the value of an MSR.
+ *
+ * @returns VBox status code.
+ * @param uMsr The MSR to read.
+ * @param idCpu The CPU to read it on, NIL_RTCPUID if it doesn't
+ * matter which CPU.
+ * @param puValue Where to return the value.
+ * @param pfGp Where to store the \#GP indicator for the read
+ * operation.
+ */
+SUPR3DECL(int) SUPR3MsrProberRead(uint32_t uMsr, RTCPUID idCpu, uint64_t *puValue, bool *pfGp);
+
+/**
+ * Attempts to write to an MSR.
+ *
+ * @returns VBox status code.
+ * @param uMsr The MSR to write to.
+ * @param idCpu The CPU to wrtie it on, NIL_RTCPUID if it
+ * doesn't matter which CPU.
+ * @param uValue The value to write.
+ * @param pfGp Where to store the \#GP indicator for the write
+ * operation.
+ */
+SUPR3DECL(int) SUPR3MsrProberWrite(uint32_t uMsr, RTCPUID idCpu, uint64_t uValue, bool *pfGp);
+
+/**
+ * Attempts to modify the value of an MSR.
+ *
+ * @returns VBox status code.
+ * @param uMsr The MSR to modify.
+ * @param idCpu The CPU to modify it on, NIL_RTCPUID if it
+ * doesn't matter which CPU.
+ * @param fAndMask The bits to keep in the current MSR value.
+ * @param fOrMask The bits to set before writing.
+ * @param pResult The result buffer.
+ */
+SUPR3DECL(int) SUPR3MsrProberModify(uint32_t uMsr, RTCPUID idCpu, uint64_t fAndMask, uint64_t fOrMask,
+ PSUPMSRPROBERMODIFYRESULT pResult);
+
+/**
+ * Attempts to modify the value of an MSR, extended version.
+ *
+ * @returns VBox status code.
+ * @param uMsr The MSR to modify.
+ * @param idCpu The CPU to modify it on, NIL_RTCPUID if it
+ * doesn't matter which CPU.
+ * @param fAndMask The bits to keep in the current MSR value.
+ * @param fOrMask The bits to set before writing.
+ * @param fFaster If set to @c true some cache/tlb invalidation is
+ * skipped, otherwise behave like
+ * SUPR3MsrProberModify.
+ * @param pResult The result buffer.
+ */
+SUPR3DECL(int) SUPR3MsrProberModifyEx(uint32_t uMsr, RTCPUID idCpu, uint64_t fAndMask, uint64_t fOrMask, bool fFaster,
+ PSUPMSRPROBERMODIFYRESULT pResult);
+
+/**
+ * Resume built-in keyboard on MacBook Air and Pro hosts.
+ *
+ * @returns VBox status code.
+ */
+SUPR3DECL(int) SUPR3ResumeSuspendedKeyboards(void);
+
+/**
+ * Measure the TSC-delta for the specified CPU.
+ *
+ * @returns VBox status code.
+ * @param idCpu The CPU to measure the TSC-delta for.
+ * @param fAsync Whether the measurement is asynchronous, returns
+ * immediately after signalling a measurement
+ * request.
+ * @param fForce Whether to perform a measurement even if the
+ * specified CPU has a (possibly) valid TSC delta.
+ * @param cRetries Number of times to retry failed delta
+ * measurements.
+ * @param cMsWaitRetry Number of milliseconds to wait between retries.
+ */
+SUPR3DECL(int) SUPR3TscDeltaMeasure(RTCPUID idCpu, bool fAsync, bool fForce, uint8_t cRetries, uint8_t cMsWaitRetry);
+
+/**
+ * Reads the delta-adjust TSC value.
+ *
+ * @returns VBox status code.
+ * @param puTsc Where to store the read TSC value.
+ * @param pidApic Where to store the APIC ID of the CPU where the TSC
+ * was read (optional, can be NULL).
+ */
+SUPR3DECL(int) SUPR3ReadTsc(uint64_t *puTsc, uint16_t *pidApic);
+
+/**
+ * Modifies the GIP flags.
+ *
+ * @returns VBox status code.
+ * @param fOrMask The OR mask of the GIP flags, see SUPGIP_FLAGS_XXX.
+ * @param fAndMask The AND mask of the GIP flags, see SUPGIP_FLAGS_XXX.
+ */
+SUPR3DECL(int) SUPR3GipSetFlags(uint32_t fOrMask, uint32_t fAndMask);
+
+/**
+ * Return processor microcode revision, if applicable.
+ *
+ * @returns VINF_SUCCESS if supported, error code indicating why if not.
+ * @param puMicrocodeRev Pointer to microcode revision dword (out).
+ */
+SUPR3DECL(int) SUPR3QueryMicrocodeRev(uint32_t *puMicrocodeRev);
+
+/**
+ * Gets hardware-virtualization MSRs of the CPU, if available.
+ *
+ * @returns VINF_SUCCESS if available, error code indicating why if not.
+ * @param pHwvirtMsrs Where to store the hardware-virtualization MSRs.
+ * @param fForceRequery Whether to force complete re-querying of MSRs (rather
+ * than fetching cached values when available).
+ */
+SUPR3DECL(int) SUPR3GetHwvirtMsrs(PSUPHWVIRTMSRS pHwvirtMsrs, bool fForceRequery);
+
+/** @} */
+#endif /* IN_RING3 */
+
+
+/** @name User mode module flags (SUPR3TracerRegisterModule & SUP_IOCTL_TRACER_UMOD_REG).
+ * @{ */
+/** Executable image. */
+#define SUP_TRACER_UMOD_FLAGS_EXE UINT32_C(1)
+/** Shared library (DLL, DYLIB, SO, etc). */
+#define SUP_TRACER_UMOD_FLAGS_SHARED UINT32_C(2)
+/** Image type mask. */
+#define SUP_TRACER_UMOD_FLAGS_TYPE_MASK UINT32_C(3)
+/** @} */
+
+
+#ifdef IN_RING0
+/** @defgroup grp_sup_r0 SUP Host Context Ring-0 API
+ * @{
+ */
+
+/**
+ * Security objectype.
+ */
+typedef enum SUPDRVOBJTYPE
+{
+ /** The usual invalid object. */
+ SUPDRVOBJTYPE_INVALID = 0,
+ /** A Virtual Machine instance. */
+ SUPDRVOBJTYPE_VM,
+ /** Internal network. */
+ SUPDRVOBJTYPE_INTERNAL_NETWORK,
+ /** Internal network interface. */
+ SUPDRVOBJTYPE_INTERNAL_NETWORK_INTERFACE,
+ /** Single release event semaphore. */
+ SUPDRVOBJTYPE_SEM_EVENT,
+ /** Multiple release event semaphore. */
+ SUPDRVOBJTYPE_SEM_EVENT_MULTI,
+ /** Raw PCI device. */
+ SUPDRVOBJTYPE_RAW_PCI_DEVICE,
+ /** The first invalid object type in this end. */
+ SUPDRVOBJTYPE_END,
+ /** The usual 32-bit type size hack. */
+ SUPDRVOBJTYPE_32_BIT_HACK = 0x7ffffff
+} SUPDRVOBJTYPE;
+
+/**
+ * Object destructor callback.
+ * This is called for reference counted objectes when the count reaches 0.
+ *
+ * @param pvObj The object pointer.
+ * @param pvUser1 The first user argument.
+ * @param pvUser2 The second user argument.
+ */
+typedef DECLCALLBACKTYPE(void, FNSUPDRVDESTRUCTOR,(void *pvObj, void *pvUser1, void *pvUser2));
+/** Pointer to a FNSUPDRVDESTRUCTOR(). */
+typedef FNSUPDRVDESTRUCTOR *PFNSUPDRVDESTRUCTOR;
+
+/**
+ * Service request callback function.
+ *
+ * @returns VBox status code.
+ * @param pSession The caller's session.
+ * @param uOperation The operation identifier.
+ * @param u64Arg 64-bit integer argument.
+ * @param pReqHdr The request header. Input / Output. Optional.
+ */
+typedef DECLCALLBACKTYPE(int, FNSUPR0SERVICEREQHANDLER,(PSUPDRVSESSION pSession, uint32_t uOperation,
+ uint64_t u64Arg, PSUPR0SERVICEREQHDR pReqHdr));
+/** Pointer to a FNR0SERVICEREQHANDLER(). */
+typedef R0PTRTYPE(FNSUPR0SERVICEREQHANDLER *) PFNSUPR0SERVICEREQHANDLER;
+
+/**
+ * Symbol entry for a wrapped module (SUPLDRWRAPPEDMODULE).
+ */
+typedef struct SUPLDRWRAPMODSYMBOL
+{
+ /** The symbol namel. */
+ const char *pszSymbol;
+ /** The symbol address/value. */
+ PFNRT pfnValue;
+} SUPLDRWRAPMODSYMBOL;
+/** Pointer to a symbol entry for a wrapped module. */
+typedef SUPLDRWRAPMODSYMBOL const *PCSUPLDRWRAPMODSYMBOL;
+
+/**
+ * Registration structure for SUPR0LdrRegisterWrapperModule.
+ *
+ * This is used to register a .r0 module when loaded manually as a native kernel
+ * module/extension/driver/whatever.
+ */
+typedef struct SUPLDRWRAPPEDMODULE
+{
+ /** Magic value (SUPLDRWRAPPEDMODULE_MAGIC). */
+ uint32_t uMagic;
+ /** The structure version. */
+ uint16_t uVersion;
+ /** SUPLDRWRAPPEDMODULE_F_XXX. */
+ uint16_t fFlags;
+
+ /** As close as possible to the start of the image. */
+ void *pvImageStart;
+ /** As close as possible to the end of the image. */
+ void *pvImageEnd;
+
+ /** @name Standar entry points
+ * @{ */
+ /** Pointer to the module initialization function (optional). */
+ DECLCALLBACKMEMBER(int, pfnModuleInit,(void *hMod));
+ /** Pointer to the module termination function (optional). */
+ DECLCALLBACKMEMBER(void, pfnModuleTerm,(void *hMod));
+ /** The VMMR0EntryFast entry point for VMMR0. */
+ PFNRT pfnVMMR0EntryFast;
+ /** The VMMR0EntryEx entry point for VMMR0. */
+ PFNRT pfnVMMR0EntryEx;
+ /** The service request handler entry point. */
+ PFNSUPR0SERVICEREQHANDLER pfnServiceReqHandler;
+ /** @} */
+
+ /** The symbol table. */
+ PCSUPLDRWRAPMODSYMBOL paSymbols;
+ /** Number of symbols. */
+ uint32_t cSymbols;
+
+ /** The normal VBox module name. */
+ char szName[32];
+ /** Repeating the magic value here (SUPLDRWRAPPEDMODULE_MAGIC). */
+ uint32_t uEndMagic;
+} SUPLDRWRAPPEDMODULE;
+/** Pointer to the wrapped module registration structure. */
+typedef SUPLDRWRAPPEDMODULE const *PCSUPLDRWRAPPEDMODULE;
+
+/** Magic value for the wrapped module structure (Doris lessing). */
+#define SUPLDRWRAPPEDMODULE_MAGIC UINT32_C(0x19191117)
+/** Current SUPLDRWRAPPEDMODULE structure version. */
+#define SUPLDRWRAPPEDMODULE_VERSION UINT16_C(0x0001)
+
+/** Set if this is the VMMR0 module. */
+#define SUPLDRWRAPPEDMODULE_F_VMMR0 UINT16_C(0x0001)
+
+
+SUPR0DECL(void *) SUPR0ObjRegister(PSUPDRVSESSION pSession, SUPDRVOBJTYPE enmType, PFNSUPDRVDESTRUCTOR pfnDestructor, void *pvUser1, void *pvUser2);
+SUPR0DECL(int) SUPR0ObjAddRef(void *pvObj, PSUPDRVSESSION pSession);
+SUPR0DECL(int) SUPR0ObjAddRefEx(void *pvObj, PSUPDRVSESSION pSession, bool fNoBlocking);
+SUPR0DECL(int) SUPR0ObjRelease(void *pvObj, PSUPDRVSESSION pSession);
+SUPR0DECL(int) SUPR0ObjVerifyAccess(void *pvObj, PSUPDRVSESSION pSession, const char *pszObjName);
+
+SUPR0DECL(PVM) SUPR0GetSessionVM(PSUPDRVSESSION pSession);
+SUPR0DECL(PGVM) SUPR0GetSessionGVM(PSUPDRVSESSION pSession);
+SUPR0DECL(int) SUPR0SetSessionVM(PSUPDRVSESSION pSession, PGVM pGVM, PVM pVM);
+SUPR0DECL(RTUID) SUPR0GetSessionUid(PSUPDRVSESSION pSession);
+
+SUPR0DECL(int) SUPR0LockMem(PSUPDRVSESSION pSession, RTR3PTR pvR3, uint32_t cPages, PRTHCPHYS paPages);
+SUPR0DECL(int) SUPR0UnlockMem(PSUPDRVSESSION pSession, RTR3PTR pvR3);
+SUPR0DECL(int) SUPR0ContAlloc(PSUPDRVSESSION pSession, uint32_t cPages, PRTR0PTR ppvR0, PRTR3PTR ppvR3, PRTHCPHYS pHCPhys);
+SUPR0DECL(int) SUPR0ContFree(PSUPDRVSESSION pSession, RTHCUINTPTR uPtr);
+SUPR0DECL(int) SUPR0LowAlloc(PSUPDRVSESSION pSession, uint32_t cPages, PRTR0PTR ppvR0, PRTR3PTR ppvR3, PRTHCPHYS paPages);
+SUPR0DECL(int) SUPR0LowFree(PSUPDRVSESSION pSession, RTHCUINTPTR uPtr);
+SUPR0DECL(int) SUPR0MemAlloc(PSUPDRVSESSION pSession, uint32_t cb, PRTR0PTR ppvR0, PRTR3PTR ppvR3);
+SUPR0DECL(int) SUPR0MemGetPhys(PSUPDRVSESSION pSession, RTHCUINTPTR uPtr, PSUPPAGE paPages);
+SUPR0DECL(int) SUPR0MemFree(PSUPDRVSESSION pSession, RTHCUINTPTR uPtr);
+SUPR0DECL(int) SUPR0PageAllocEx(PSUPDRVSESSION pSession, uint32_t cPages, uint32_t fFlags, PRTR3PTR ppvR3, PRTR0PTR ppvR0, PRTHCPHYS paPages);
+SUPR0DECL(int) SUPR0PageMapKernel(PSUPDRVSESSION pSession, RTR3PTR pvR3, uint32_t offSub, uint32_t cbSub, uint32_t fFlags, PRTR0PTR ppvR0);
+SUPR0DECL(int) SUPR0PageProtect(PSUPDRVSESSION pSession, RTR3PTR pvR3, RTR0PTR pvR0, uint32_t offSub, uint32_t cbSub, uint32_t fProt);
+SUPR0DECL(int) SUPR0PageFree(PSUPDRVSESSION pSession, RTR3PTR pvR3);
+SUPR0DECL(int) SUPR0GipMap(PSUPDRVSESSION pSession, PRTR3PTR ppGipR3, PRTHCPHYS pHCPhysGip);
+SUPR0DECL(int) SUPR0LdrLock(PSUPDRVSESSION pSession);
+SUPR0DECL(int) SUPR0LdrUnlock(PSUPDRVSESSION pSession);
+SUPR0DECL(bool) SUPR0LdrIsLockOwnerByMod(void *hMod, bool fWantToHear);
+SUPR0DECL(int) SUPR0LdrModByName(PSUPDRVSESSION pSession, const char *pszName, void **phMod);
+SUPR0DECL(int) SUPR0LdrModRetain(PSUPDRVSESSION pSession, void *hMod);
+SUPR0DECL(int) SUPR0LdrModRelease(PSUPDRVSESSION pSession, void *hMod);
+#ifdef RT_OS_LINUX
+SUPR0DECL(int) SUPDrvLinuxLdrRegisterWrappedModule(PCSUPLDRWRAPPEDMODULE pWrappedModInfo, const char *pszLnxModName, void **phMod);
+SUPR0DECL(int) SUPDrvLinuxLdrDeregisterWrappedModule(PCSUPLDRWRAPPEDMODULE pWrappedModInfo, void **phMod);
+#endif
+SUPR0DECL(int) SUPR0GetVTSupport(uint32_t *pfCaps);
+SUPR0DECL(int) SUPR0GetHwvirtMsrs(PSUPHWVIRTMSRS pMsrs, uint32_t fCaps, bool fForce);
+SUPR0DECL(int) SUPR0GetSvmUsability(bool fInitSvm);
+SUPR0DECL(int) SUPR0GetVmxUsability(bool *pfIsSmxModeAmbiguous);
+SUPR0DECL(int) SUPR0GetCurrentGdtRw(RTHCUINTPTR *pGdtRw);
+SUPR0DECL(int) SUPR0QueryVTCaps(PSUPDRVSESSION pSession, uint32_t *pfCaps);
+SUPR0DECL(int) SUPR0GipUnmap(PSUPDRVSESSION pSession);
+SUPR0DECL(int) SUPR0QueryUcodeRev(PSUPDRVSESSION pSession, uint32_t *puMicrocodeRev);
+SUPR0DECL(SUPPAGINGMODE) SUPR0GetPagingMode(void);
+SUPR0DECL(RTCCUINTREG) SUPR0ChangeCR4(RTCCUINTREG fOrMask, RTCCUINTREG fAndMask);
+SUPR0DECL(int) SUPR0EnableVTx(bool fEnable);
+SUPR0DECL(bool) SUPR0SuspendVTxOnCpu(void);
+SUPR0DECL(void) SUPR0ResumeVTxOnCpu(bool fSuspended);
+#define SUP_TSCDELTA_MEASURE_F_FORCE RT_BIT_32(0)
+#define SUP_TSCDELTA_MEASURE_F_ASYNC RT_BIT_32(1)
+#define SUP_TSCDELTA_MEASURE_F_VALID_MASK UINT32_C(0x00000003)
+SUPR0DECL(int) SUPR0TscDeltaMeasureBySetIndex(PSUPDRVSESSION pSession, uint32_t iCpuSet, uint32_t fFlags,
+ RTMSINTERVAL cMsWaitRetry, RTMSINTERVAL cMsWaitThread, uint32_t cTries);
+
+SUPR0DECL(void) SUPR0BadContext(PSUPDRVSESSION pSession, const char *pszFile, uint32_t uLine, const char *pszExpr);
+
+#if defined(RT_OS_LINUX) || defined(RT_OS_SOLARIS) || defined(RT_OS_FREEBSD)
+/**
+ * Translates a physical address to a virtual mapping (valid up to end of page).
+ * @returns VBox status code.
+ * @param HCPhys The physical address, must be page aligned.
+ * @param ppv Where to store the mapping address on success.
+ */
+SUPR0DECL(int) SUPR0HCPhysToVirt(RTHCPHYS HCPhys, void **ppv);
+#endif
+
+/** Context structure returned by SUPR0IoCtlSetup for use with
+ * SUPR0IoCtlPerform and cleaned up by SUPR0IoCtlCleanup. */
+typedef struct SUPR0IOCTLCTX *PSUPR0IOCTLCTX;
+
+/**
+ * Sets up a I/O control context for the given handle.
+ *
+ * @returns VBox status code.
+ * @param pSession The support driver session.
+ * @param hHandle The handle.
+ * @param fFlags Flag, MBZ.
+ * @param ppCtx Where the context is returned.
+ */
+SUPR0DECL(int) SUPR0IoCtlSetupForHandle(PSUPDRVSESSION pSession, intptr_t hHandle, uint32_t fFlags, PSUPR0IOCTLCTX *ppCtx);
+
+/**
+ * Cleans up the I/O control context when done.
+ *
+ * This won't close the handle passed to SUPR0IoCtlSetupForHandle.
+ *
+ * @returns VBox status code.
+ * @param pCtx The I/O control context to cleanup.
+ */
+SUPR0DECL(int) SUPR0IoCtlCleanup(PSUPR0IOCTLCTX pCtx);
+
+/**
+ * Performs an I/O control operation.
+ *
+ * @returns VBox status code.
+ * @param pCtx The I/O control context returned by
+ * SUPR0IoCtlSetupForHandle.
+ * @param uFunction The I/O control function to perform.
+ * @param pvInput Pointer to input buffer (ring-0).
+ * @param pvInputUser Ring-3 pointer corresponding to @a pvInput.
+ * @param cbInput The amount of input. If zero, both input pointers
+ * are expected to be NULL.
+ * @param pvOutput Pointer to output buffer (ring-0).
+ * @param pvOutputUser Ring-3 pointer corresponding to @a pvInput.
+ * @param cbOutput The amount of input. If zero, both input pointers
+ * are expected to be NULL.
+ * @param piNativeRc Where to return the native return code. When
+ * specified the VBox status code will typically be
+ * VINF_SUCCESS and the caller have to consult this for
+ * the actual result of the operation. (This saves
+ * pointless status code conversion.) Optional.
+ *
+ * @note On unix systems where there is only one set of buffers possible,
+ * pass the same pointers as input and output.
+ */
+SUPR0DECL(int) SUPR0IoCtlPerform(PSUPR0IOCTLCTX pCtx, uintptr_t uFunction,
+ void *pvInput, RTR3PTR pvInputUser, size_t cbInput,
+ void *pvOutput, RTR3PTR pvOutputUser, size_t cbOutput,
+ int32_t *piNativeRc);
+
+/**
+ * Writes to the debugger and/or kernel log, va_list version.
+ *
+ * The length of the formatted message is somewhat limited, so keep things short
+ * and to the point.
+ *
+ * @returns Number of bytes written, mabye.
+ * @param pszFormat IPRT format string.
+ * @param va Arguments referenced by the format string.
+ */
+SUPR0DECL(int) SUPR0PrintfV(const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(1, 0);
+
+/**
+ * Writes to the debugger and/or kernel log.
+ *
+ * The length of the formatted message is somewhat limited, so keep things short
+ * and to the point.
+ *
+ * @returns Number of bytes written, mabye.
+ * @param pszFormat IPRT format string.
+ * @param ... Arguments referenced by the format string.
+ */
+#if defined(__GNUC__) && defined(__inline__)
+/* Define it as static for GCC as it cannot inline functions using va_start() anyway,
+ and linux redefines __inline__ to always inlining forcing gcc to issue an error. */
+static int __attribute__((__unused__))
+#else
+DECLINLINE(int)
+#endif
+RT_IPRT_FORMAT_ATTR(1, 2) SUPR0Printf(const char *pszFormat, ...)
+{
+ va_list va;
+ va_start(va, pszFormat);
+ SUPR0PrintfV(pszFormat, va);
+ va_end(va);
+ return 0;
+}
+
+/* HACK ALERT! See above. */
+#ifdef SUPR0PRINTF_UNDO_INLINE_HACK
+# define __inline__ inline
+#endif
+
+#ifdef IN_RING0
+/** Debug printf macro. This also exist in SUPLib, see SUPLibInternal.h. */
+# ifdef DEBUG
+# define SUP_DPRINTF(a) SUPR0Printf a
+# else
+# define SUP_DPRINTF(a) do { } while (0)
+# endif
+#endif
+
+/**
+ * Returns configuration flags of the host kernel.
+ *
+ * @returns Combination of SUPKERNELFEATURES_XXX flags.
+ */
+SUPR0DECL(uint32_t) SUPR0GetKernelFeatures(void);
+
+/**
+ * Notification from R0 VMM prior to loading the guest-FPU register state.
+ *
+ * @returns Whether the host-FPU register state has been saved by the host kernel.
+ * @param fCtxHook Whether thread-context hooks are enabled.
+ *
+ * @remarks Called with preemption disabled.
+ */
+SUPR0DECL(bool) SUPR0FpuBegin(bool fCtxHook);
+
+/**
+ * Notification from R0 VMM after saving the guest-FPU register state (and
+ * potentially restoring the host-FPU register state) in ring-0.
+ *
+ * @param fCtxHook Whether thread-context hooks are enabled.
+ *
+ * @remarks Called with preemption disabled.
+ */
+SUPR0DECL(void) SUPR0FpuEnd(bool fCtxHook);
+
+/** @copydoc RTLogDefaultInstanceEx
+ * @remarks To allow overriding RTLogDefaultInstanceEx locally. */
+SUPR0DECL(struct RTLOGGER *) SUPR0DefaultLogInstanceEx(uint32_t fFlagsAndGroup);
+/** @copydoc RTLogGetDefaultInstanceEx
+ * @remarks To allow overriding RTLogGetDefaultInstanceEx locally. */
+SUPR0DECL(struct RTLOGGER *) SUPR0GetDefaultLogInstanceEx(uint32_t fFlagsAndGroup);
+/** @copydoc RTLogRelGetDefaultInstanceEx
+ * @remarks To allow overriding RTLogRelGetDefaultInstanceEx locally. */
+SUPR0DECL(struct RTLOGGER *) SUPR0GetDefaultLogRelInstanceEx(uint32_t fFlagsAndGroup);
+
+
+/** @name Absolute symbols
+ * Take the address of these, don't try call them.
+ * @{ */
+SUPR0DECL(void) SUPR0AbsIs64bit(void);
+SUPR0DECL(void) SUPR0Abs64bitKernelCS(void);
+SUPR0DECL(void) SUPR0Abs64bitKernelSS(void);
+SUPR0DECL(void) SUPR0Abs64bitKernelDS(void);
+SUPR0DECL(void) SUPR0AbsKernelCS(void);
+SUPR0DECL(void) SUPR0AbsKernelSS(void);
+SUPR0DECL(void) SUPR0AbsKernelDS(void);
+SUPR0DECL(void) SUPR0AbsKernelES(void);
+SUPR0DECL(void) SUPR0AbsKernelFS(void);
+SUPR0DECL(void) SUPR0AbsKernelGS(void);
+/** @} */
+
+/**
+ * Support driver component factory.
+ *
+ * Component factories are registered by drivers that provides services
+ * such as the host network interface filtering and access to the host
+ * TCP/IP stack.
+ *
+ * @remark Module dependencies and making sure that a component doesn't
+ * get unloaded while in use, is the sole responsibility of the
+ * driver/kext/whatever implementing the component.
+ */
+typedef struct SUPDRVFACTORY
+{
+ /** The (unique) name of the component factory. */
+ char szName[56];
+ /**
+ * Queries a factory interface.
+ *
+ * The factory interface is specific to each component and will be be
+ * found in the header(s) for the component alongside its UUID.
+ *
+ * @returns Pointer to the factory interfaces on success, NULL on failure.
+ *
+ * @param pSupDrvFactory Pointer to this structure.
+ * @param pSession The SUPDRV session making the query.
+ * @param pszInterfaceUuid The UUID of the factory interface.
+ */
+ DECLR0CALLBACKMEMBER(void *, pfnQueryFactoryInterface,(struct SUPDRVFACTORY const *pSupDrvFactory, PSUPDRVSESSION pSession, const char *pszInterfaceUuid));
+} SUPDRVFACTORY;
+/** Pointer to a support driver factory. */
+typedef SUPDRVFACTORY *PSUPDRVFACTORY;
+/** Pointer to a const support driver factory. */
+typedef SUPDRVFACTORY const *PCSUPDRVFACTORY;
+
+SUPR0DECL(int) SUPR0ComponentRegisterFactory(PSUPDRVSESSION pSession, PCSUPDRVFACTORY pFactory);
+SUPR0DECL(int) SUPR0ComponentDeregisterFactory(PSUPDRVSESSION pSession, PCSUPDRVFACTORY pFactory);
+SUPR0DECL(int) SUPR0ComponentQueryFactory(PSUPDRVSESSION pSession, const char *pszName, const char *pszInterfaceUuid, void **ppvFactoryIf);
+
+
+/** @name Tracing
+ * @{ */
+
+/**
+ * Tracer data associated with a provider.
+ */
+typedef union SUPDRVTRACERDATA
+{
+ /** Generic */
+ uint64_t au64[2];
+
+ /** DTrace data. */
+ struct
+ {
+ /** Provider ID. */
+ uintptr_t idProvider;
+ /** The number of trace points provided. */
+ uint32_t volatile cProvidedProbes;
+ /** Whether we've invalidated this bugger. */
+ bool fZombie;
+ } DTrace;
+} SUPDRVTRACERDATA;
+/** Pointer to the tracer data associated with a provider. */
+typedef SUPDRVTRACERDATA *PSUPDRVTRACERDATA;
+
+/**
+ * Probe location info for ring-0.
+ *
+ * Since we cannot trust user tracepoint modules, we need to duplicate the probe
+ * ID and enabled flag in ring-0.
+ */
+typedef struct SUPDRVPROBELOC
+{
+ /** The probe ID. */
+ uint32_t idProbe;
+ /** Whether it's enabled or not. */
+ bool fEnabled;
+} SUPDRVPROBELOC;
+/** Pointer to a ring-0 probe location record. */
+typedef SUPDRVPROBELOC *PSUPDRVPROBELOC;
+
+/**
+ * Probe info for ring-0.
+ *
+ * Since we cannot trust user tracepoint modules, we need to duplicate the
+ * probe enable count.
+ */
+typedef struct SUPDRVPROBEINFO
+{
+ /** The number of times this probe has been enabled. */
+ uint32_t volatile cEnabled;
+} SUPDRVPROBEINFO;
+/** Pointer to a ring-0 probe info record. */
+typedef SUPDRVPROBEINFO *PSUPDRVPROBEINFO;
+
+/**
+ * Support driver tracepoint provider core.
+ */
+typedef struct SUPDRVVDTPROVIDERCORE
+{
+ /** The tracer data member. */
+ SUPDRVTRACERDATA TracerData;
+ /** Pointer to the provider name (a copy that's always available). */
+ const char *pszName;
+ /** Pointer to the module name (a copy that's always available). */
+ const char *pszModName;
+
+ /** The provider descriptor. */
+ struct VTGDESCPROVIDER *pDesc;
+ /** The VTG header. */
+ struct VTGOBJHDR *pHdr;
+
+ /** The size of the entries in the pvProbeLocsEn table. */
+ uint8_t cbProbeLocsEn;
+ /** The actual module bit count (corresponds to cbProbeLocsEn). */
+ uint8_t cBits;
+ /** Set if this is a Umod, otherwise clear. */
+ bool fUmod;
+ /** Explicit alignment padding (paranoia). */
+ uint8_t abAlignment[ARCH_BITS == 32 ? 1 : 5];
+
+ /** The probe locations used for descriptive purposes. */
+ struct VTGPROBELOC const *paProbeLocsRO;
+ /** Pointer to the probe location array where the enable flag needs
+ * flipping. For kernel providers, this will always be SUPDRVPROBELOC,
+ * while user providers can either be 32-bit or 64-bit. Use
+ * cbProbeLocsEn to calculate the address of an entry. */
+ void *pvProbeLocsEn;
+ /** Pointer to the probe array containing the enabled counts. */
+ uint32_t *pacProbeEnabled;
+
+ /** The ring-0 probe location info for user tracepoint modules.
+ * This is NULL if fUmod is false. */
+ PSUPDRVPROBELOC paR0ProbeLocs;
+ /** The ring-0 probe info for user tracepoint modules.
+ * This is NULL if fUmod is false. */
+ PSUPDRVPROBEINFO paR0Probes;
+
+} SUPDRVVDTPROVIDERCORE;
+/** Pointer to a tracepoint provider core structure. */
+typedef SUPDRVVDTPROVIDERCORE *PSUPDRVVDTPROVIDERCORE;
+
+/** Pointer to a tracer registration record. */
+typedef struct SUPDRVTRACERREG const *PCSUPDRVTRACERREG;
+/**
+ * Support driver tracer registration record.
+ */
+typedef struct SUPDRVTRACERREG
+{
+ /** Magic value (SUPDRVTRACERREG_MAGIC). */
+ uint32_t u32Magic;
+ /** Version (SUPDRVTRACERREG_VERSION). */
+ uint32_t u32Version;
+
+ /**
+ * Fire off a kernel probe.
+ *
+ * @param pVtgProbeLoc The probe location record.
+ * @param uArg0 The first raw probe argument.
+ * @param uArg1 The second raw probe argument.
+ * @param uArg2 The third raw probe argument.
+ * @param uArg3 The fourth raw probe argument.
+ * @param uArg4 The fifth raw probe argument.
+ *
+ * @remarks SUPR0TracerFireProbe will do a tail jump thru this member, so
+ * no extra stack frames will be added.
+ * @remarks This does not take a 'this' pointer argument because it doesn't map
+ * well onto VTG or DTrace.
+ *
+ */
+ DECLR0CALLBACKMEMBER(void, pfnProbeFireKernel, (struct VTGPROBELOC *pVtgProbeLoc, uintptr_t uArg0, uintptr_t uArg1, uintptr_t uArg2,
+ uintptr_t uArg3, uintptr_t uArg4));
+
+ /**
+ * Fire off a user-mode probe.
+ *
+ * @param pThis Pointer to the registration record.
+ *
+ * @param pVtgProbeLoc The probe location record.
+ * @param pSession The user session.
+ * @param pCtx The usermode context info.
+ * @param pVtgHdr The VTG header (read-only).
+ * @param pProbeLocRO The read-only probe location record .
+ */
+ DECLR0CALLBACKMEMBER(void, pfnProbeFireUser, (PCSUPDRVTRACERREG pThis, PSUPDRVSESSION pSession, PCSUPDRVTRACERUSRCTX pCtx,
+ struct VTGOBJHDR const *pVtgHdr, struct VTGPROBELOC const *pProbeLocRO));
+
+ /**
+ * Opens up the tracer.
+ *
+ * @returns VBox status code.
+ * @param pThis Pointer to the registration record.
+ * @param pSession The session doing the opening.
+ * @param uCookie A cookie (magic) unique to the tracer, so it can
+ * fend off incompatible clients.
+ * @param uArg Tracer specific argument.
+ * @param puSessionData Pointer to the session data variable. This must be
+ * set to a non-zero value on success.
+ */
+ DECLR0CALLBACKMEMBER(int, pfnTracerOpen, (PCSUPDRVTRACERREG pThis, PSUPDRVSESSION pSession, uint32_t uCookie, uintptr_t uArg,
+ uintptr_t *puSessionData));
+
+ /**
+ * I/O control style tracer communication method.
+ *
+ *
+ * @returns VBox status code.
+ * @param pThis Pointer to the registration record.
+ * @param pSession The session.
+ * @param uSessionData The session data value.
+ * @param uCmd The tracer specific command.
+ * @param uArg The tracer command specific argument.
+ * @param piRetVal The tracer specific return value.
+ */
+ DECLR0CALLBACKMEMBER(int, pfnTracerIoCtl, (PCSUPDRVTRACERREG pThis, PSUPDRVSESSION pSession, uintptr_t uSessionData,
+ uintptr_t uCmd, uintptr_t uArg, int32_t *piRetVal));
+
+ /**
+ * Cleans up data the tracer has associated with a session.
+ *
+ * @param pThis Pointer to the registration record.
+ * @param pSession The session handle.
+ * @param uSessionData The data assoicated with the session.
+ */
+ DECLR0CALLBACKMEMBER(void, pfnTracerClose, (PCSUPDRVTRACERREG pThis, PSUPDRVSESSION pSession, uintptr_t uSessionData));
+
+ /**
+ * Registers a provider.
+ *
+ * @returns VBox status code.
+ * @param pThis Pointer to the registration record.
+ * @param pCore The provider core data.
+ *
+ * @todo Kernel vs. Userland providers.
+ */
+ DECLR0CALLBACKMEMBER(int, pfnProviderRegister, (PCSUPDRVTRACERREG pThis, PSUPDRVVDTPROVIDERCORE pCore));
+
+ /**
+ * Attempts to deregisters a provider.
+ *
+ * @returns VINF_SUCCESS or VERR_TRY_AGAIN. If the latter, the provider
+ * should be made as harmless as possible before returning as the
+ * VTG object and associated code will be unloaded upon return.
+ *
+ * @param pThis Pointer to the registration record.
+ * @param pCore The provider core data.
+ */
+ DECLR0CALLBACKMEMBER(int, pfnProviderDeregister, (PCSUPDRVTRACERREG pThis, PSUPDRVVDTPROVIDERCORE pCore));
+
+ /**
+ * Make another attempt at unregister a busy provider.
+ *
+ * @returns VINF_SUCCESS or VERR_TRY_AGAIN.
+ * @param pThis Pointer to the registration record.
+ * @param pCore The provider core data.
+ */
+ DECLR0CALLBACKMEMBER(int, pfnProviderDeregisterZombie, (PCSUPDRVTRACERREG pThis, PSUPDRVVDTPROVIDERCORE pCore));
+
+ /** End marker (SUPDRVTRACERREG_MAGIC). */
+ uintptr_t uEndMagic;
+} SUPDRVTRACERREG;
+
+/** Tracer magic (Kenny Garrett). */
+#define SUPDRVTRACERREG_MAGIC UINT32_C(0x19601009)
+/** Tracer registration structure version. */
+#define SUPDRVTRACERREG_VERSION RT_MAKE_U32(0, 1)
+
+/** Pointer to a trace helper structure. */
+typedef struct SUPDRVTRACERHLP const *PCSUPDRVTRACERHLP;
+/**
+ * Helper structure.
+ */
+typedef struct SUPDRVTRACERHLP
+{
+ /** The structure version (SUPDRVTRACERHLP_VERSION). */
+ uintptr_t uVersion;
+
+ /** @todo ... */
+
+ /** End marker (SUPDRVTRACERHLP_VERSION) */
+ uintptr_t uEndVersion;
+} SUPDRVTRACERHLP;
+/** Tracer helper structure version. */
+#define SUPDRVTRACERHLP_VERSION RT_MAKE_U32(0, 1)
+
+SUPR0DECL(int) SUPR0TracerRegisterImpl(void *hMod, PSUPDRVSESSION pSession, PCSUPDRVTRACERREG pReg, PCSUPDRVTRACERHLP *ppHlp);
+SUPR0DECL(int) SUPR0TracerDeregisterImpl(void *hMod, PSUPDRVSESSION pSession);
+SUPR0DECL(int) SUPR0TracerRegisterDrv(PSUPDRVSESSION pSession, struct VTGOBJHDR *pVtgHdr, const char *pszName);
+SUPR0DECL(void) SUPR0TracerDeregisterDrv(PSUPDRVSESSION pSession);
+SUPR0DECL(int) SUPR0TracerRegisterModule(void *hMod, struct VTGOBJHDR *pVtgHdr);
+SUPR0DECL(void) SUPR0TracerFireProbe(struct VTGPROBELOC *pVtgProbeLoc, uintptr_t uArg0, uintptr_t uArg1, uintptr_t uArg2,
+ uintptr_t uArg3, uintptr_t uArg4);
+SUPR0DECL(void) SUPR0TracerUmodProbeFire(PSUPDRVSESSION pSession, PSUPDRVTRACERUSRCTX pCtx);
+/** @} */
+
+
+/** @defgroup grp_sup_r0_idc The IDC Interface
+ * @{
+ */
+
+/** The current SUPDRV IDC version.
+ * This follows the usual high word / low word rules, i.e. high word is the
+ * major number and it signifies incompatible interface changes. */
+#define SUPDRV_IDC_VERSION UINT32_C(0x00010000)
+
+/**
+ * Inter-Driver Communication Handle.
+ */
+typedef union SUPDRVIDCHANDLE
+{
+ /** Padding for opaque usage.
+ * Must be greater or equal in size than the private struct. */
+ void *apvPadding[4];
+#ifdef SUPDRVIDCHANDLEPRIVATE_DECLARED
+ /** The private view. */
+ struct SUPDRVIDCHANDLEPRIVATE s;
+#endif
+} SUPDRVIDCHANDLE;
+/** Pointer to a handle. */
+typedef SUPDRVIDCHANDLE *PSUPDRVIDCHANDLE;
+
+SUPR0DECL(int) SUPR0IdcOpen(PSUPDRVIDCHANDLE pHandle, uint32_t uReqVersion, uint32_t uMinVersion,
+ uint32_t *puSessionVersion, uint32_t *puDriverVersion, uint32_t *puDriverRevision);
+SUPR0DECL(int) SUPR0IdcCall(PSUPDRVIDCHANDLE pHandle, uint32_t iReq, void *pvReq, uint32_t cbReq);
+SUPR0DECL(int) SUPR0IdcClose(PSUPDRVIDCHANDLE pHandle);
+SUPR0DECL(PSUPDRVSESSION) SUPR0IdcGetSession(PSUPDRVIDCHANDLE pHandle);
+SUPR0DECL(int) SUPR0IdcComponentRegisterFactory(PSUPDRVIDCHANDLE pHandle, PCSUPDRVFACTORY pFactory);
+SUPR0DECL(int) SUPR0IdcComponentDeregisterFactory(PSUPDRVIDCHANDLE pHandle, PCSUPDRVFACTORY pFactory);
+
+/** @} */
+
+/** @name Ring-0 module entry points.
+ *
+ * These can be exported by ring-0 modules SUP are told to load.
+ *
+ * @{ */
+DECLEXPORT(int) ModuleInit(void *hMod);
+DECLEXPORT(void) ModuleTerm(void *hMod);
+/** @} */
+
+
+/** @} */
+#endif
+
+
+/** @name Trust Anchors and Certificates
+ * @{ */
+
+/**
+ * Trust anchor table entry (in generated Certificates.cpp).
+ */
+typedef struct SUPTAENTRY
+{
+ /** Pointer to the raw bytes. */
+ const unsigned char *pch;
+ /** Number of bytes. */
+ unsigned cb;
+} SUPTAENTRY;
+/** Pointer to a trust anchor table entry. */
+typedef SUPTAENTRY const *PCSUPTAENTRY;
+
+/** Macro for simplifying generating the trust anchor tables. */
+#define SUPTAENTRY_GEN(a_abTA) { &a_abTA[0], sizeof(a_abTA) }
+
+/** All certificates we know. */
+extern SUPTAENTRY const g_aSUPAllTAs[];
+/** Number of entries in g_aSUPAllTAs. */
+extern unsigned const g_cSUPAllTAs;
+
+/** Software publisher certificate roots (Authenticode). */
+extern SUPTAENTRY const g_aSUPSpcRootTAs[];
+/** Number of entries in g_aSUPSpcRootTAs. */
+extern unsigned const g_cSUPSpcRootTAs;
+
+/** Kernel root certificates used by Windows. */
+extern SUPTAENTRY const g_aSUPNtKernelRootTAs[];
+/** Number of entries in g_aSUPNtKernelRootTAs. */
+extern unsigned const g_cSUPNtKernelRootTAs;
+
+/** Timestamp root certificates trusted by Windows. */
+extern SUPTAENTRY const g_aSUPTimestampTAs[];
+/** Number of entries in g_aSUPTimestampTAs. */
+extern unsigned const g_cSUPTimestampTAs;
+
+/** Root certificates trusted by Apple code signing. */
+extern SUPTAENTRY const g_aSUPAppleRootTAs[];
+/** Number of entries in g_cSUPAppleRootTAs. */
+extern unsigned const g_cSUPAppleRootTAs;
+
+/** TAs we trust (the build certificate, Oracle VirtualBox). */
+extern SUPTAENTRY const g_aSUPTrustedTAs[];
+/** Number of entries in g_aSUPTrustedTAs. */
+extern unsigned const g_cSUPTrustedTAs;
+
+/** Supplemental certificates, like cross signing certificates. */
+extern SUPTAENTRY const g_aSUPSupplementalTAs[];
+/** Number of entries in g_aSUPTrustedTAs. */
+extern unsigned const g_cSUPSupplementalTAs;
+
+/** The build certificate. */
+extern const unsigned char g_abSUPBuildCert[];
+/** The size of the build certificate. */
+extern const unsigned g_cbSUPBuildCert;
+
+/** @} */
+
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !VBOX_INCLUDED_sup_h */
+
diff --git a/include/VBox/sup.mac b/include/VBox/sup.mac
new file mode 100644
index 00000000..5b1b5f00
--- /dev/null
+++ b/include/VBox/sup.mac
@@ -0,0 +1,157 @@
+; $Id: sup.mac $
+;; @file
+; SUP - Support Library, assembly definitions.
+;
+
+;
+; Copyright (C) 2006-2022 Oracle and/or its affiliates.
+;
+; This file is part of VirtualBox base platform packages, as
+; available from https://www.virtualbox.org.
+;
+; This program is free software; you can redistribute it and/or
+; modify it under the terms of the GNU General Public License
+; as published by the Free Software Foundation, in version 3 of the
+; License.
+;
+; This program is distributed in the hope that it will be useful, but
+; WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with this program; if not, see <https://www.gnu.org/licenses>.
+;
+; The contents of this file may alternatively be used under the terms
+; of the Common Development and Distribution License Version 1.0
+; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+; in the VirtualBox 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.
+;
+; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+;
+
+%ifndef ___VBox_sup_mac
+%define ___VBox_sup_mac
+
+struc SUPGIPCPU
+ .u32TransactionId resd 1
+ .u32UpdateIntervalTSC resd 1
+ .u64NanoTS resq 1
+ .u64TSC resq 1
+ .u64CpuHz resq 1
+ .i64TSCDelta resq 1
+ .cErrors resd 1
+ .iTSCHistoryHead resd 1
+ .au32TSCHistory resd 8
+ .u32PrevUpdateIntervalNS resd 1
+ .u32Reserved resd 1
+ .u64TSCSample resq 1
+ .au32Reserved1 resd 3
+ .enmState resd 1
+ .idCpu resd 1
+ .iCpuSet resw 1
+ .iCpuGroup resw 1
+ .iCpuGroupMember resw 1
+ .idApic resw 1
+ .iReservedForNumaNode resd 1
+endstruc
+
+%define SUPGIPUSETSCDELTA_NOT_APPLICABLE 0
+%define SUPGIPUSETSCDELTA_ZERO_CLAIMED 1
+%define SUPGIPUSETSCDELTA_PRACTICALLY_ZERO 2
+%define SUPGIPUSETSCDELTA_ROUGHLY_ZERO 3
+%define SUPGIPUSETSCDELTA_NOT_ZERO 4
+
+%define SUPGIPGETCPU_APIC_ID 1
+%define SUPGIPGETCPU_RDTSCP_MASK_MAX_SET_CPUS 2
+%define SUPGIPGETCPU_IDTR_LIMIT_MASK_MAX_SET_CPUS 4
+%define SUPGIPGETCPU_RDTSCP_GROUP_IN_CH_NUMBER_IN_CL 8
+%define SUPGIPGETCPU_APIC_ID_EXT_0B 16
+%define SUPGIPGETCPU_APIC_ID_EXT_8000001E 32
+
+
+%define SUPGLOBALINFOPAGE_MAGIC 0x19590106
+struc SUPGLOBALINFOPAGE
+ .u32Magic resd 1
+ .u32Version resd 1
+ .u32Mode resd 1
+ .cCpus resw 1
+ .cPages resw 1
+ .u32UpdateHz resd 1
+ .u32UpdateIntervalNS resd 1
+ .u64NanoTSLastUpdateHz resq 1
+ .u64CpuHz resq 1
+ .cOnlineCpus resw 1
+ .cPresentCpus resw 1
+ .cPossibleCpus resw 1
+ .cPossibleCpuGroups resw 1
+ .idCpuMax resd 1
+ .enmUseTscDelta resd 1
+ .fGetGipCpu resd 1
+ .fFlags resd 1
+ .OnlineCpuSet resq 16
+ .PresentCpuSet resq 16
+ .PossibleCpuSet resq 16
+ .au32Padding1 resd 48
+ .aiCpuFromApicId resw 4096
+ .aiCpuFromCpuSetIdx resw 1024
+ .aoffCpuGroup resd 256
+ .aCPUs resb SUPGIPCPU_size
+endstruc
+
+struc SUPDRVTRACERUSRCTX32
+ .idProbe resd 1
+ .cBits resb 1
+ .abReserved resb 3
+ .u.X86.uVtgProbeLoc resd 1
+ .u.X86.aArgs resd 20
+ .u.X86.eip resd 1
+ .u.X86.eflags resd 1
+ .u.X86.eax resd 1
+ .u.X86.ecx resd 1
+ .u.X86.edx resd 1
+ .u.X86.ebx resd 1
+ .u.X86.esp resd 1
+ .u.X86.ebp resd 1
+ .u.X86.esi resd 1
+ .u.X86.edi resd 1
+ .u.X86.cs resw 1
+ .u.X86.ss resw 1
+ .u.X86.ds resw 1
+ .u.X86.es resw 1
+ .u.X86.fs resw 1
+ .u.X86.gs resw 1
+endstruc
+
+struc SUPDRVTRACERUSRCTX64
+ .idProbe resd 1
+ .cBits resb 1
+ .abReserved resb 3
+ .u.Amd64.uVtgProbeLoc resq 1
+ .u.Amd64.aArgs resq 10
+ .u.Amd64.rip resq 1
+ .u.Amd64.rflags resq 1
+ .u.Amd64.rax resq 1
+ .u.Amd64.rcx resq 1
+ .u.Amd64.rdx resq 1
+ .u.Amd64.rbx resq 1
+ .u.Amd64.rsp resq 1
+ .u.Amd64.rbp resq 1
+ .u.Amd64.rsi resq 1
+ .u.Amd64.rdi resq 1
+ .u.Amd64.r8 resq 1
+ .u.Amd64.r9 resq 1
+ .u.Amd64.r10 resq 1
+ .u.Amd64.r11 resq 1
+ .u.Amd64.r12 resq 1
+ .u.Amd64.r13 resq 1
+ .u.Amd64.r14 resq 1
+ .u.Amd64.r15 resq 1
+endstruc
+
+%endif
+
diff --git a/include/VBox/types.h b/include/VBox/types.h
new file mode 100644
index 00000000..9b7e1cf5
--- /dev/null
+++ b/include/VBox/types.h
@@ -0,0 +1,1258 @@
+/** @file
+ * VirtualBox - Types.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_types_h
+#define VBOX_INCLUDED_types_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#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 ring-3 VMM API vtable. */
+typedef R3PTRTYPE(const struct VMMR3VTABLE *) PCVMMR3VTABLE;
+
+/** Pointer to a VM. */
+typedef struct VM *PVM;
+/** Pointer to a const VM. */
+typedef const struct VM *PCVM;
+/** 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 const ring-0 (global) VM structure. */
+typedef R0PTRTYPE(const struct GVM *) PCGVM;
+/** Pointer to a GVMCPU structure. */
+typedef R0PTRTYPE(struct GVMCPU *) PGVMCPU;
+/** Pointer to a const GVMCPU structure. */
+typedef R0PTRTYPE(struct GVMCPU const *) PCGVMCPU;
+
+/** 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;
+
+/** Pointer to a context specific VM derived structure.
+ * This is PGVM in ring-0 and plain PVM in ring-3. */
+#ifdef IN_RING0
+typedef PGVM PVMCC;
+#else
+typedef PVM PVMCC;
+#endif
+/** Pointer to a const context specific VM derived structure.
+ * This is PCGVM in ring-0 and plain PCVM in ring-3. */
+#ifdef IN_RING0
+typedef PCGVM PCVMCC;
+#else
+typedef PCVM PCVMCC;
+#endif
+/** Pointer to a context specific VMCPUM derived structure.
+ * This is PGVMCPU in ring-0 and plain PVMCPU in ring-3. */
+#ifdef IN_RING0
+typedef PGVMCPU PVMCPUCC;
+#else
+typedef PVMCPU PVMCPUCC;
+#endif
+/** Pointer to a const context specific VMCPU derived structure.
+ * This is PCGVMCPU in ring-0 and plain PCVMCPU in ring-3. */
+#ifdef IN_RING0
+typedef PCGVMCPU PCVMCPUCC;
+#else
+typedef PCVMCPU PCVMCPUCC;
+#endif
+
+/** 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)
+
+
+/** A cross context I/O port range handle. */
+typedef uint64_t IOMIOPORTHANDLE;
+/** Pointer to a cross context I/O port handle. */
+typedef IOMIOPORTHANDLE *PIOMIOPORTHANDLE;
+/** A NIL I/O port handle. */
+#define NIL_IOMIOPORTHANDLE ((uint64_t)UINT64_MAX)
+
+/** A cross context MMIO range handle. */
+typedef uint64_t IOMMMIOHANDLE;
+/** Pointer to a cross context MMIO handle. */
+typedef IOMMMIOHANDLE *PIOMMMIOHANDLE;
+/** A NIL MMIO handle. */
+#define NIL_IOMMMIOHANDLE ((uint64_t)UINT64_MAX)
+
+/** A cross context MMIO2 range handle. */
+typedef uint64_t PGMMMIO2HANDLE;
+/** Pointer to a cross context MMIO2 handle. */
+typedef PGMMMIO2HANDLE *PPGMMMIO2HANDLE;
+/** A NIL MMIO2 handle. */
+#define NIL_PGMMMIO2HANDLE ((uint64_t)UINT64_MAX)
+
+/** 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 for the current context. */
+#ifdef IN_RING3
+typedef struct PDMDEVINSR3 *PPDMDEVINS;
+#elif defined(IN_RING0) || defined(DOXYGEN_RUNNING)
+typedef struct PDMDEVINSR0 *PPDMDEVINS;
+#else
+typedef struct PDMDEVINSRC *PPDMDEVINS;
+#endif
+/** Pointer to a pointer a PDM device instance for the current context. */
+typedef PPDMDEVINS *PPPDMDEVINS;
+/** R3 pointer to a PDM device instance. */
+typedef R3PTRTYPE(struct PDMDEVINSR3 *) PPDMDEVINSR3;
+/** R0 pointer to a PDM device instance. */
+typedef R0PTRTYPE(struct PDMDEVINSR0 *) PPDMDEVINSR0;
+/** RC pointer to a PDM device instance. */
+typedef RCPTRTYPE(struct PDMDEVINSRC *) PPDMDEVINSRC;
+
+/** Pointer to a PDM PCI device structure. */
+typedef struct PDMPCIDEV *PPDMPCIDEV;
+/** Pointer to a const PDM PCI device structure. */
+typedef const struct PDMPCIDEV *PCPDMPCIDEV;
+
+/** 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;
+
+/** PDM queue handle. */
+typedef uint64_t PDMQUEUEHANDLE;
+/** Pointer to a PDM queue handle. */
+typedef PDMQUEUEHANDLE *PPDMQUEUEHANDLE;
+/** NIL PDM queue handle. */
+#define NIL_PDMQUEUEHANDLE ((PDMQUEUEHANDLE)UINT64_MAX)
+
+/** 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;
+
+/** A cross context timer handle. */
+typedef uint64_t TMTIMERHANDLE;
+/** Pointer to a cross context timer handle. */
+typedef TMTIMERHANDLE *PTMTIMERHANDLE;
+/** A NIL timer handle. */
+#define NIL_TMTIMERHANDLE ((uint64_t)UINT64_MAX)
+
+/** 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 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;
+
+/** A cross context DBGF tracer event source handle. */
+typedef uint64_t DBGFTRACEREVTSRC;
+/** Pointer to a cross context DBGF tracer event source handle. */
+typedef DBGFTRACEREVTSRC *PDBGFTRACEREVTSRC;
+/** A NIL DBGF tracer event source handle. */
+#define NIL_DBGFTRACEREVTSRC ((uint64_t)UINT64_MAX)
+
+/** Pointer to a DBGF tracer instance for the current context. */
+#ifdef IN_RING3
+typedef struct DBGFTRACERINSR3 *PDBGFTRACERINSCC;
+#elif defined(IN_RING0) || defined(DOXYGEN_RUNNING)
+typedef struct DBGFTRACERINSR0 *PDBGFTRACERINSCC;
+#else
+typedef struct DBGFTRACERINSRC *PDBGFTRACERINSCC;
+#endif
+/** Pointer to a pointer a DBGF tracer instance for the current context. */
+typedef PDBGFTRACERINSCC *PPDBGFTRACERINSCC;
+/** R3 pointer to a DBGF tracer instance. */
+typedef R3PTRTYPE(struct DBGFTRACERINSR3 *) PDBGFTRACERINSR3;
+/** R0 pointer to a DBGF tracer instance. */
+typedef R0PTRTYPE(struct DBGFTRACERINSR0 *) PDBGFTRACERINSR0;
+/** RC pointer to a DBGF tracer instance. */
+typedef RCPTRTYPE(struct DBGFTRACERINSRC *) PDBGFTRACERINSRC;
+
+/** A cross context DBGF breakpoint owner handle. */
+typedef uint32_t DBGFBPOWNER;
+/** Pointer to a cross context DBGF breakpoint owner handle. */
+typedef DBGFBPOWNER *PDBGFBPOWNER;
+/** A NIL DBGF breakpoint owner handle. */
+#define NIL_DBGFBPOWNER ((uint32_t)UINT32_MAX)
+
+/** A cross context DBGF breakpoint handle. */
+typedef uint32_t DBGFBP;
+/** Pointer to a cross context DBGF breakpoint handle. */
+typedef DBGFBP *PDBGFBP;
+/** A NIL DBGF breakpoint handle. */
+#define NIL_DBGFBP ((uint32_t)UINT32_MAX)
+
+/** A sample report handle. */
+typedef struct DBGFSAMPLEREPORTINT *DBGFSAMPLEREPORT;
+/** Pointer to a sample report handle. */
+typedef DBGFSAMPLEREPORT *PDBGFSAMPLEREPORT;
+/** @} */
+
+
+/** @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.
+ *
+ * @ingroup grp_pdm
+ */
+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.
+ * @ingroup grp_pdm */
+typedef PDMNETWORKGSO *PPDMNETWORKGSO;
+/** Pointer to a const GSO context.
+ * @ingroup grp_pdm */
+typedef PDMNETWORKGSO const *PCPDMNETWORKGSO;
+
+/** Pointer to a PDM filter handle.
+ * @ingroup grp_pdm_net_shaper */
+typedef struct PDMNSFILTER *PPDMNSFILTER;
+/** Pointer to a network shaper.
+ * @ingroup grp_pdm_net_shaper */
+typedef struct PDMNETSHAPER *PPDMNETSHAPER;
+
+
+/**
+ * The current ROM page protection.
+ *
+ * @remarks This is part of the saved state.
+ * @ingroup grp_pgm
+ */
+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.
+ * @ingroup grp_pgm
+ */
+typedef struct PGMPAGEMAPLOCK
+{
+#if defined(IN_RC)
+ /** 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.
+ * @ingroup grp_pgm */
+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;
+
+
+/**
+ * Shared region description (needed by GMM and others, thus global).
+ * @ingroup grp_vmmdev
+ */
+typedef struct VMMDEVSHAREDREGIONDESC
+{
+ RTGCPTR64 GCRegionAddr;
+ uint32_t cbRegion;
+ uint32_t u32Alignment;
+} VMMDEVSHAREDREGIONDESC;
+
+
+/**
+ * A PCI bus:device:function (BDF) identifier.
+ *
+ * All 16 bits of a BDF are valid according to the PCI spec. We need one extra bit
+ * to determine whether the BDF is valid in interfaces where the BDF may be
+ * optional.
+ */
+typedef uint32_t PCIBDF;
+/** PCIBDF flag: Invalid. */
+#define PCI_BDF_F_INVALID RT_BIT(31)
+/** Nil PCIBDF value. */
+#define NIL_PCIBDF PCI_BDF_F_INVALID
+
+/** Pointer to an MSI message struct. */
+typedef struct MSIMSG *PMSIMSG;
+/** Pointer to a const MSI message struct. */
+typedef const struct MSIMSG *PCMSIMSG;
+
+
+/** @} */
+
+#endif /* !VBOX_INCLUDED_types_h */
diff --git a/include/VBox/usb.h b/include/VBox/usb.h
new file mode 100644
index 00000000..e83b7661
--- /dev/null
+++ b/include/VBox/usb.h
@@ -0,0 +1,280 @@
+/** @file
+ * USB - Universal Serial Bus. (DEV,Main?)
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_usb_h
+#define VBOX_INCLUDED_usb_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/types.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_usblib_usb USB Device Structures & Types
+ * @ingroup grp_usblib
+ * @{
+ */
+
+/**
+ * The USB host device state.
+ */
+typedef enum USBDEVICESTATE
+{
+ /** The device is unsupported. */
+ USBDEVICESTATE_UNSUPPORTED = 1,
+ /** The device is in use by the host. */
+ USBDEVICESTATE_USED_BY_HOST,
+ /** The device is in use by the host but could perhaps be captured even so. */
+ USBDEVICESTATE_USED_BY_HOST_CAPTURABLE,
+ /** The device is not used by the host or any guest. */
+ USBDEVICESTATE_UNUSED,
+ /** The device is held by the proxy for later guest usage. */
+ USBDEVICESTATE_HELD_BY_PROXY,
+ /** The device in use by a guest. */
+ USBDEVICESTATE_USED_BY_GUEST,
+ /** The usual 32-bit hack. */
+ USBDEVICESTATE_32BIT_HACK = 0x7fffffff
+} USBDEVICESTATE;
+
+
+/**
+ * The USB device speed.
+ */
+typedef enum USBDEVICESPEED
+{
+ /** Unknown. */
+ USBDEVICESPEED_UNKNOWN = 0,
+ /** Low speed (1.5 Mbit/s). */
+ USBDEVICESPEED_LOW,
+ /** Full speed (12 Mbit/s). */
+ USBDEVICESPEED_FULL,
+ /** High speed (480 Mbit/s). */
+ USBDEVICESPEED_HIGH,
+ /** Variable speed - USB 2.5 / wireless. */
+ USBDEVICESPEED_VARIABLE,
+ /** Super speed - USB 3.0 (5Gbit/s). */
+ USBDEVICESPEED_SUPER,
+ /** The usual 32-bit hack. */
+ USBDEVICESPEED_32BIT_HACK = 0x7fffffff
+} USBDEVICESPEED;
+
+
+/**
+ * USB host device description.
+ * Used for enumeration of USB devices.
+ */
+typedef struct USBDEVICE
+{
+ /** If linked, this is the pointer to the next device in the list. */
+ struct USBDEVICE *pNext;
+ /** If linked doubly, this is the pointer to the prev device in the list. */
+ struct USBDEVICE *pPrev;
+ /** Manufacturer string. */
+ const char *pszManufacturer;
+ /** Product string. */
+ const char *pszProduct;
+ /** Serial number string. */
+ const char *pszSerialNumber;
+ /** The address of the device. */
+ const char *pszAddress;
+ /** The backend to use for this device. */
+ const char *pszBackend;
+
+ /** Vendor ID. */
+ uint16_t idVendor;
+ /** Product ID. */
+ uint16_t idProduct;
+ /** Revision, integer part. */
+ uint16_t bcdDevice;
+ /** USB version number. */
+ uint16_t bcdUSB;
+ /** Device class. */
+ uint8_t bDeviceClass;
+ /** Device subclass. */
+ uint8_t bDeviceSubClass;
+ /** Device protocol */
+ uint8_t bDeviceProtocol;
+ /** Number of configurations. */
+ uint8_t bNumConfigurations;
+ /** The device state. */
+ USBDEVICESTATE enmState;
+ /** The device speed. */
+ USBDEVICESPEED enmSpeed;
+ /** Serial hash. */
+ uint64_t u64SerialHash;
+ /** The USB Bus number. */
+ uint8_t bBus;
+ /** The port number. */
+ uint8_t bPort;
+ /** The hub+port path. */
+ char *pszPortPath;
+#if defined(RT_OS_LINUX) || defined(RT_OS_FREEBSD)
+ /** Device number. */
+ uint8_t bDevNum;
+#endif
+#ifdef RT_OS_WINDOWS
+ /** Alternate address. Can be NULL. */
+ char *pszAltAddress;
+ /** The hub name. */
+ char *pszHubName;
+#endif
+#ifdef RT_OS_SOLARIS
+ /** The /devices path of the device. */
+ char *pszDevicePath;
+ /** Do we have a partial or full device descriptor here. */
+ bool fPartialDescriptor;
+#endif
+} USBDEVICE;
+/** Pointer to a USB device. */
+typedef USBDEVICE *PUSBDEVICE;
+/** Pointer to a const USB device. */
+typedef USBDEVICE *PCUSBDEVICE;
+
+
+#ifdef VBOX_USB_H_INCL_DESCRIPTORS /* for the time being, since this may easily conflict with system headers */
+
+/**
+ * USB device descriptor.
+ */
+#pragma pack(1)
+typedef struct USBDESCHDR
+{
+ /** The descriptor length. */
+ uint8_t bLength;
+ /** The descriptor type. */
+ uint8_t bDescriptorType;
+} USBDESCHDR;
+#pragma pack()
+/** Pointer to an USB descriptor header. */
+typedef USBDESCHDR *PUSBDESCHDR;
+
+/** @name Descriptor Type values (bDescriptorType)
+ * {@ */
+#if !defined(USB_DT_DEVICE) && !defined(USB_DT_ENDPOINT)
+# define USB_DT_DEVICE 0x01
+# define USB_DT_CONFIG 0x02
+# define USB_DT_STRING 0x03
+# define USB_DT_INTERFACE 0x04
+# define USB_DT_ENDPOINT 0x05
+
+# define USB_DT_HID 0x21
+# define USB_DT_REPORT 0x22
+# define USB_DT_PHYSICAL 0x23
+# define USB_DT_HUB 0x29
+#endif
+/** @} */
+
+
+/**
+ * USB device descriptor.
+ */
+#pragma pack(1)
+typedef struct USBDEVICEDESC
+{
+ /** The descriptor length. (Usually sizeof(USBDEVICEDESC).) */
+ uint8_t bLength;
+ /** The descriptor type. (USB_DT_DEVICE) */
+ uint8_t bDescriptorType;
+ /** USB version number. */
+ uint16_t bcdUSB;
+ /** Device class. */
+ uint8_t bDeviceClass;
+ /** Device subclass. */
+ uint8_t bDeviceSubClass;
+ /** Device protocol */
+ uint8_t bDeviceProtocol;
+ /** The max packet size of the default control pipe. */
+ uint8_t bMaxPacketSize0;
+ /** Vendor ID. */
+ uint16_t idVendor;
+ /** Product ID. */
+ uint16_t idProduct;
+ /** Revision, integer part. */
+ uint16_t bcdDevice;
+ /** Manufacturer string index. */
+ uint8_t iManufacturer;
+ /** Product string index. */
+ uint8_t iProduct;
+ /** Serial number string index. */
+ uint8_t iSerialNumber;
+ /** Number of configurations. */
+ uint8_t bNumConfigurations;
+} USBDEVICEDESC;
+#pragma pack()
+/** Pointer to an USB device descriptor. */
+typedef USBDEVICEDESC *PUSBDEVICEDESC;
+
+/** @name Class codes (bDeviceClass)
+ * @{ */
+#ifndef USB_HUB_CLASSCODE
+# define USB_HUB_CLASSCODE 0x09
+#endif
+/** @} */
+
+/**
+ * USB configuration descriptor.
+ */
+#pragma pack(1)
+typedef struct USBCONFIGDESC
+{
+ /** The descriptor length. (Usually sizeof(USBCONFIGDESC).) */
+ uint8_t bLength;
+ /** The descriptor type. (USB_DT_CONFIG) */
+ uint8_t bDescriptorType;
+ /** The length of the configuration descriptor plus all associated descriptors. */
+ uint16_t wTotalLength;
+ /** Number of interfaces. */
+ uint8_t bNumInterfaces;
+ /** Configuration number. (For SetConfiguration().) */
+ uint8_t bConfigurationValue;
+ /** Configuration description string. */
+ uint8_t iConfiguration;
+ /** Configuration characteristics. */
+ uint8_t bmAttributes;
+ /** Maximum power consumption of the USB device in this config. */
+ uint8_t MaxPower;
+} USBCONFIGDESC;
+#pragma pack()
+/** Pointer to an USB configuration descriptor. */
+typedef USBCONFIGDESC *PUSBCONFIGDESC;
+
+#endif /* VBOX_USB_H_INCL_DESCRIPTORS */
+
+/** @} */
+RT_C_DECLS_END
+
+#endif /* !VBOX_INCLUDED_usb_h */
+
diff --git a/include/VBox/usbfilter.h b/include/VBox/usbfilter.h
new file mode 100644
index 00000000..3f7f15ca
--- /dev/null
+++ b/include/VBox/usbfilter.h
@@ -0,0 +1,271 @@
+/** @file
+ * USBFilter - USB Filter constructs shared by kernel and user mode.
+ * (DEV,HDrv,Main)
+ */
+
+/*
+ * Copyright (C) 2007-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_usbfilter_h
+#define VBOX_INCLUDED_usbfilter_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+#include <iprt/assert.h>
+#include <VBox/cdefs.h>
+#include <VBox/usb.h>
+
+
+/** @defgroup grp_usbfilter USBFilter - USB Filter constructs shared by kernel and user mode
+ * @ingroup grp_usblib
+ * @{
+ */
+
+/**
+ * How to match a field.
+ *
+ * @remarks This is a binary interface (drivers).
+ */
+typedef enum USBFILTERMATCH
+{
+ /** The usual invalid first zero value. */
+ USBFILTERMATCH_INVALID = 0,
+ /** Ignore this field (always matching).
+ * Device Data: No value present. */
+ USBFILTERMATCH_IGNORE,
+ /** Only require this field to be present on the device. */
+ USBFILTERMATCH_PRESENT,
+
+ /** Numeric Field: The first numeric field matching method. */
+ USBFILTERMATCH_NUM_FIRST,
+ /** Numeric Field: Exact match, required to be present. */
+ USBFILTERMATCH_NUM_EXACT = USBFILTERMATCH_NUM_FIRST,
+ /** Numeric Field: Exact match or not present. */
+ USBFILTERMATCH_NUM_EXACT_NP,
+ /** Numeric Field: Expression match, required to be present.
+ * The expression is represented as a string. */
+ USBFILTERMATCH_NUM_EXPRESSION,
+ /** Numeric Field: Expression match or not present.
+ * The expression is represented as a string. */
+ USBFILTERMATCH_NUM_EXPRESSION_NP,
+ /** Numeric Field: The last numeric field matching method (inclusive). */
+ USBFILTERMATCH_NUM_LAST = USBFILTERMATCH_NUM_EXPRESSION_NP,
+
+ /** String Field: The first string field matching method. */
+ USBFILTERMATCH_STR_FIRST,
+ /** String Field: Exact match, required to be present. */
+ USBFILTERMATCH_STR_EXACT = USBFILTERMATCH_STR_FIRST,
+ /** String Field: Exact match or not present. */
+ USBFILTERMATCH_STR_EXACT_NP,
+ /** String Field: Pattern match, required to be present.*/
+ USBFILTERMATCH_STR_PATTERN,
+ /** String Field: Pattern match or not present.*/
+ USBFILTERMATCH_STR_PATTERN_NP,
+ /** String Field: The last string field matching method (inclusive). */
+ USBFILTERMATCH_STR_LAST = USBFILTERMATCH_STR_PATTERN_NP,
+
+ /** The end of valid matching methods (exclusive). */
+ USBFILTERMATCH_END
+} USBFILTERMATCH;
+AssertCompile(USBFILTERMATCH_END == 11);
+
+
+/**
+ * A USB filter field.
+ *
+ * @remarks This is a binary interface (drivers).
+ */
+typedef struct USBFILTERFIELD
+{
+ /** The matching method. (USBFILTERMATCH) */
+ uint16_t enmMatch;
+ /** The field value or offset into the string table.
+ * The enmMatch field decides which it is. */
+ uint16_t u16Value;
+} USBFILTERFIELD;
+AssertCompileSize(USBFILTERFIELD, 4);
+/** Pointer to a USB filter field. */
+typedef USBFILTERFIELD *PUSBFILTERFIELD;
+/** Pointer to a const USBFILTERFIELD. */
+typedef const USBFILTERFIELD *PCUSBFILTERFIELD;
+
+
+/**
+ * USB filter field index.
+ *
+ * This is used as an index into the USBFILTER::aFields array.
+ *
+ * @remarks This is a binary interface (drivers).
+ */
+typedef enum USBFILTERIDX
+{
+ /** idVendor (= 0) */
+ USBFILTERIDX_VENDOR_ID = 0,
+ /** idProduct (= 1) */
+ USBFILTERIDX_PRODUCT_ID,
+ /** bcdDevice (= 2)*/
+ USBFILTERIDX_DEVICE_REV,
+ USBFILTERIDX_DEVICE = USBFILTERIDX_DEVICE_REV,
+ /** bDeviceClass (= 3) */
+ USBFILTERIDX_DEVICE_CLASS,
+ /** bDeviceSubClass (= 4) */
+ USBFILTERIDX_DEVICE_SUB_CLASS,
+ /** bDeviceProtocol (= 5) */
+ USBFILTERIDX_DEVICE_PROTOCOL,
+ /** bBus (= 6 )*/
+ USBFILTERIDX_BUS,
+ /** bPort (=7) */
+ USBFILTERIDX_PORT,
+ /** Manufacturer string. (=8) */
+ USBFILTERIDX_MANUFACTURER_STR,
+ /** Product string. (=9) */
+ USBFILTERIDX_PRODUCT_STR,
+ /** SerialNumber string. (=10) */
+ USBFILTERIDX_SERIAL_NUMBER_STR,
+ /** The end of the USB filter fields (exclusive). */
+ USBFILTERIDX_END
+} USBFILTERIDX;
+AssertCompile(USBFILTERIDX_END == 11);
+
+
+/**
+ * USB Filter types.
+ *
+ * The filters types are list in priority order, i.e. highest priority first.
+ *
+ * @remarks This is a binary interface (drivers).
+ */
+typedef enum USBFILTERTYPE
+{
+ /** The usual invalid first zero value. */
+ USBFILTERTYPE_INVALID = 0,
+ /** The first valid entry. */
+ USBFILTERTYPE_FIRST,
+ /** A one-shot ignore filter that's installed when releasing a device.
+ * This filter will be automatically removedwhen the device re-appears,
+ * or when ring-3 decides that time is up, or if ring-3 dies upon us. */
+ USBFILTERTYPE_ONESHOT_IGNORE = USBFILTERTYPE_FIRST,
+ /** A one-shot capture filter that's installed when hijacking a device that's already plugged.
+ * This filter will be automatically removed when the device re-appears,
+ * or when ring-3 decides that time is up, or if ring-3 dies upon us. */
+ USBFILTERTYPE_ONESHOT_CAPTURE,
+ /** Ignore filter.
+ * This picks out devices that shouldn't be captured. */
+ USBFILTERTYPE_IGNORE,
+ /** A normal capture filter.
+ * When a device matching the filter is attach, we'll take it. */
+ USBFILTERTYPE_CAPTURE,
+ /** The end of the valid filter types (exclusive). */
+ USBFILTERTYPE_END,
+ /** The usual 32-bit hack. */
+ USBFILTERTYPE_32BIT_HACK = 0x7fffffff
+} USBFILTERTYPE;
+AssertCompileSize(USBFILTERTYPE, 4);
+AssertCompile(USBFILTERTYPE_END == 5);
+
+
+/**
+ * USB Filter.
+ *
+ * Consider the an abstract data type, use the methods below to access it.
+ *
+ * @remarks This is a binary interface (drivers).
+ */
+typedef struct USBFILTER
+{
+ /** Magic number (USBFILTER_MAGIC). */
+ uint32_t u32Magic;
+ /** The filter type. */
+ USBFILTERTYPE enmType;
+ /** The filter fields.
+ * This array is indexed by USBFILTERIDX */
+ USBFILTERFIELD aFields[USBFILTERIDX_END];
+ /** Offset to the end of the string table (last terminator). (used to speed up things) */
+ uint32_t offCurEnd;
+ /** String table.
+ * This is used for string and numeric patterns. */
+ char achStrTab[256];
+} USBFILTER;
+AssertCompileSize(USBFILTER, 312);
+
+/** Pointer to a USBLib filter. */
+typedef USBFILTER *PUSBFILTER;
+/** Pointer to a const USBLib filter. */
+typedef const USBFILTER *PCUSBFILTER;
+
+/** USBFILTER::u32Magic (Yasuhiro Nightow). */
+#define USBFILTER_MAGIC UINT32_C(0x19670408)
+
+
+RT_C_DECLS_BEGIN
+
+USBLIB_DECL(void) USBFilterInit(PUSBFILTER pFilter, USBFILTERTYPE enmType);
+USBLIB_DECL(void) USBFilterClone(PUSBFILTER pFilter, PCUSBFILTER pToClone);
+USBLIB_DECL(void) USBFilterDelete(PUSBFILTER pFilter);
+USBLIB_DECL(int) USBFilterValidate(PCUSBFILTER pFilter);
+USBLIB_DECL(bool) USBFilterMatch(PCUSBFILTER pFilter, PCUSBFILTER pDevice);
+USBLIB_DECL(int) USBFilterMatchRated(PCUSBFILTER pFilter, PCUSBFILTER pDevice);
+USBLIB_DECL(bool) USBFilterMatchDevice(PCUSBFILTER pFilter, PCUSBDEVICE pDevice);
+USBLIB_DECL(bool) USBFilterIsIdentical(PCUSBFILTER pFilter, PCUSBFILTER pFilter2);
+
+USBLIB_DECL(int) USBFilterSetFilterType(PUSBFILTER pFilter, USBFILTERTYPE enmType);
+USBLIB_DECL(int) USBFilterSetIgnore(PUSBFILTER pFilter, USBFILTERIDX enmFieldIdx);
+USBLIB_DECL(int) USBFilterSetPresentOnly(PUSBFILTER pFilter, USBFILTERIDX enmFieldIdx);
+USBLIB_DECL(int) USBFilterSetNumExact(PUSBFILTER pFilter, USBFILTERIDX enmFieldIdx, uint16_t u16Value, bool fMustBePresent);
+USBLIB_DECL(int) USBFilterSetNumExpression(PUSBFILTER pFilter, USBFILTERIDX enmFieldIdx, const char *pszExpression, bool fMustBePresent);
+USBLIB_DECL(int) USBFilterSetStringExact(PUSBFILTER pFilter, USBFILTERIDX enmFieldIdx, const char *pszValue,
+ bool fMustBePresent, bool fPurge);
+USBLIB_DECL(int) USBFilterSetStringPattern(PUSBFILTER pFilter, USBFILTERIDX enmFieldIdx, const char *pszPattern, bool fMustBePresent);
+USBLIB_DECL(int) USBFilterSetMustBePresent(PUSBFILTER pFilter, USBFILTERIDX enmFieldIdx, bool fMustBePresent);
+
+USBLIB_DECL(USBFILTERTYPE) USBFilterGetFilterType(PCUSBFILTER pFilter);
+USBLIB_DECL(USBFILTERMATCH) USBFilterGetMatchingMethod(PCUSBFILTER pFilter, USBFILTERIDX enmFieldIdx);
+USBLIB_DECL(int) USBFilterQueryNum(PCUSBFILTER pFilter, USBFILTERIDX enmFieldIdx, uint16_t *pu16Value);
+USBLIB_DECL(int) USBFilterGetNum(PCUSBFILTER pFilter, USBFILTERIDX enmFieldIdx);
+USBLIB_DECL(int) USBFilterQueryString(PUSBFILTER pFilter, USBFILTERIDX enmFieldIdx, char *pszBuf, size_t cchBuf);
+USBLIB_DECL(const char *) USBFilterGetString(PCUSBFILTER pFilter, USBFILTERIDX enmFieldIdx);
+USBLIB_DECL(ssize_t) USBFilterGetStringLen(PCUSBFILTER pFilter, USBFILTERIDX enmFieldIdx);
+
+USBLIB_DECL(bool) USBFilterHasAnySubstatialCriteria(PCUSBFILTER pFilter);
+USBLIB_DECL(bool) USBFilterIsNumericField(USBFILTERIDX enmFieldIdx);
+USBLIB_DECL(bool) USBFilterIsStringField(USBFILTERIDX enmFieldIdx);
+USBLIB_DECL(bool) USBFilterIsMethodUsingNumericValue(USBFILTERMATCH enmMatchingMethod);
+USBLIB_DECL(bool) USBFilterIsMethodUsingStringValue(USBFILTERMATCH enmMatchingMethod);
+USBLIB_DECL(bool) USBFilterIsMethodNumeric(USBFILTERMATCH enmMatchingMethod);
+USBLIB_DECL(bool) USBFilterIsMethodString(USBFILTERMATCH enmMatchingMethod);
+
+RT_C_DECLS_END
+
+/** @} */
+
+#endif /* !VBOX_INCLUDED_usbfilter_h */
diff --git a/include/VBox/usblib-darwin.h b/include/VBox/usblib-darwin.h
new file mode 100644
index 00000000..f74d5f92
--- /dev/null
+++ b/include/VBox/usblib-darwin.h
@@ -0,0 +1,72 @@
+/** @file
+ * USBLib - Library for wrapping up the VBoxUSB functionality, Darwin flavor.
+ * (DEV,HDrv,Main)
+ */
+
+/*
+ * Copyright (C) 2007-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_usblib_darwin_h
+#define VBOX_INCLUDED_usblib_darwin_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/cdefs.h>
+#include <VBox/usbfilter.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_usblib_darwin Darwin USB Specifics
+ * @ingroup grp_usblib
+ * @{
+ */
+
+/** @name VBoxUSB specific device properties.
+ * VBoxUSB makes use of the OWNER property for communicating between the probe and
+ * start stage.
+ * USBProxyServiceDarwin makes use of all of them to correctly determine the state
+ * of the device.
+ * @{ */
+/** Contains the pid of the current client. If 0, the kernel is the current client. */
+#define VBOXUSB_CLIENT_KEY "VBoxUSB-Client"
+/** Contains the pid of the filter owner (i.e. the VBoxSVC pid). */
+#define VBOXUSB_OWNER_KEY "VBoxUSB-Owner"
+/** Contains the ID of the matching filter. */
+#define VBOXUSB_FILTER_KEY "VBoxUSB-Filter"
+/** @} */
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !VBOX_INCLUDED_usblib_darwin_h */
+
diff --git a/include/VBox/usblib-solaris.h b/include/VBox/usblib-solaris.h
new file mode 100644
index 00000000..3cc900bb
--- /dev/null
+++ b/include/VBox/usblib-solaris.h
@@ -0,0 +1,288 @@
+/** @file
+ * USBLib - Library for wrapping up the VBoxUSB functionality, Solaris flavor.
+ * (DEV,HDrv,Main)
+ */
+
+/*
+ * Copyright (C) 2008-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_usblib_solaris_h
+#define VBOX_INCLUDED_usblib_solaris_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/cdefs.h>
+#include <VBox/usbfilter.h>
+#include <VBox/vusb.h>
+#include <sys/types.h>
+#include <sys/ioccom.h>
+#include <sys/param.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_usblib_solaris Solaris USB Specifics
+ * @ingroup grp_usblib
+ * @{
+ */
+
+/** @name VBoxUSB specific IOCtls.
+ * VBoxUSB uses them for resetting USB devices requests from userland.
+ * USBProxyService/Device makes use of them to communicate with VBoxUSB.
+ * @{ */
+
+/** 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 VBOXUSBREQ
+{
+ /** Magic value (VBOXUSB(MON)_MAGIC). */
+ uint32_t u32Magic;
+ /** The size of the data buffer (In & Out). */
+ uint32_t cbData;
+ /** Result code of the request filled by driver. */
+ int32_t rc;
+ /** The user address of the data buffer. */
+ RTR3PTR pvDataR3;
+} VBOXUSBREQ;
+/** Pointer to a request wrapper for solaris. */
+typedef VBOXUSBREQ *PVBOXUSBREQ;
+/** Pointer to a const request wrapper for solaris. */
+typedef const VBOXUSBREQ *PCVBOXUSBREQ;
+
+#pragma pack(1)
+typedef struct
+{
+ /* Pointer to the Filter. */
+ USBFILTER Filter;
+ /* Where to store the added Filter (Id). */
+ uintptr_t uId;
+} VBOXUSBREQ_ADD_FILTER;
+
+typedef struct
+{
+ /* Pointer to Filter (Id) to be removed. */
+ uintptr_t uId;
+} VBOXUSBREQ_REMOVE_FILTER;
+
+typedef struct
+{
+ /** Whether to re-attach the driver. */
+ bool fReattach;
+ /* Physical path of the USB device. */
+ char szDevicePath[1];
+} VBOXUSBREQ_RESET_DEVICE;
+
+typedef struct
+{
+ /* Where to store the instance. */
+ int *pInstance;
+ /* Physical path of the USB device. */
+ char szDevicePath[1];
+} VBOXUSBREQ_DEVICE_INSTANCE;
+
+typedef struct
+{
+ /** Where to store the instance. */
+ int Instance;
+ /* Where to store the client path. */
+ char szClientPath[MAXPATHLEN];
+ /** Device identifier (VendorId:ProductId:Release:StaticPath) */
+ char szDeviceIdent[MAXPATHLEN+48];
+ /** Callback from monitor specifying client consumer (VM) credentials */
+ DECLR0CALLBACKMEMBER(int, pfnSetConsumerCredentials,(RTPROCESS Process, int Instance, void *pvReserved));
+} VBOXUSBREQ_CLIENT_INFO, *PVBOXUSBREQ_CLIENT_INFO;
+typedef VBOXUSBREQ_CLIENT_INFO VBOXUSB_CLIENT_INFO;
+typedef PVBOXUSBREQ_CLIENT_INFO PVBOXUSB_CLIENT_INFO;
+
+/** Isoc packet descriptor (Must mirror exactly Solaris USBA's usb_isoc_pkt_descr_t) */
+typedef struct
+{
+ ushort_t cbPkt; /* Size of the packet */
+ ushort_t cbActPkt; /* Size of the packet actually transferred */
+ VUSBSTATUS enmStatus; /* Per frame transfer status */
+} VUSBISOC_PKT_DESC;
+
+/** VBoxUSB IOCtls */
+typedef struct
+{
+ void *pvUrbR3; /* Pointer to userland URB (untouched by kernel driver) */
+ uint8_t bEndpoint; /* Endpoint address */
+ VUSBXFERTYPE enmType; /* Xfer type */
+ VUSBDIRECTION enmDir; /* Xfer direction */
+ VUSBSTATUS enmStatus; /* URB status */
+ bool fShortOk; /* Whether receiving less data than requested is acceptable. */
+ size_t cbData; /* Size of the data */
+ void *pvData; /* Pointer to the data */
+ uint32_t cIsocPkts; /* Number of Isoc packets */
+ VUSBISOC_PKT_DESC aIsocPkts[8]; /* Array of Isoc packet descriptors */
+} VBOXUSBREQ_URB, *PVBOXUSBREQ_URB;
+
+typedef struct
+{
+ uint8_t bEndpoint; /* Endpoint address */
+} VBOXUSBREQ_CLEAR_EP, *PVBOXUSBREQ_CLEAR_EP;
+
+
+typedef struct
+{
+ uint8_t bConfigValue; /* Configuration value */
+} VBOXUSBREQ_SET_CONFIG, *PVBOXUSBREQ_SET_CONFIG;
+typedef VBOXUSBREQ_SET_CONFIG VBOXUSBREQ_GET_CONFIG;
+typedef PVBOXUSBREQ_SET_CONFIG PVBOXUSBREQ_GET_CONFIG;
+
+typedef struct
+{
+ uint8_t bInterface; /* Interface number */
+ uint8_t bAlternate; /* Alternate setting */
+} VBOXUSBREQ_SET_INTERFACE, *PVBOXUSBREQ_SET_INTERFACE;
+
+typedef enum
+{
+ /** Close device not a reset. */
+ VBOXUSB_RESET_LEVEL_CLOSE = 0,
+ /** Hard reset resulting in device replug behaviour. */
+ VBOXUSB_RESET_LEVEL_REATTACH = 2,
+ /** Device-level reset. */
+ VBOXUSB_RESET_LEVEL_SOFT = 4
+} VBOXUSB_RESET_LEVEL;
+
+typedef struct
+{
+ VBOXUSB_RESET_LEVEL ResetLevel; /* Reset level after closing */
+} VBOXUSBREQ_CLOSE_DEVICE, *PVBOXUSBREQ_CLOSE_DEVICE;
+
+typedef struct
+{
+ uint8_t bEndpoint; /* Endpoint address */
+} VBOXUSBREQ_ABORT_PIPE, *PVBOXUSBREQ_ABORT_PIPE;
+
+typedef struct
+{
+ uint32_t u32Major; /* Driver major number */
+ uint32_t u32Minor; /* Driver minor number */
+} VBOXUSBREQ_GET_VERSION, *PVBOXUSBREQ_GET_VERSION;
+
+#pragma pack()
+
+/** The VBOXUSBREQ::u32Magic value for VBoxUSBMon. */
+#define VBOXUSBMON_MAGIC 0xba5eba11
+/** The VBOXUSBREQ::u32Magic value for VBoxUSB.*/
+#define VBOXUSB_MAGIC 0x601fba11
+/** The USBLib entry point for userland. */
+#define VBOXUSB_DEVICE_NAME "/dev/vboxusbmon"
+
+/** The USBMonitor Major version. */
+#define VBOXUSBMON_VERSION_MAJOR 2
+/** The USBMonitor Minor version. */
+#define VBOXUSBMON_VERSION_MINOR 1
+
+/** The USB Major version. */
+#define VBOXUSB_VERSION_MAJOR 1
+/** The USB Minor version. */
+#define VBOXUSB_VERSION_MINOR 1
+
+#ifdef RT_ARCH_AMD64
+# define VBOXUSB_IOCTL_FLAG 128
+#elif defined(RT_ARCH_X86)
+# define VBOXUSB_IOCTL_FLAG 0
+#else
+# error "dunno which arch this is!"
+#endif
+
+/** USB driver name*/
+#define VBOXUSB_DRIVER_NAME "vboxusb"
+
+/* No automatic buffering, size limited to 255 bytes => use VBOXUSBREQ for everything. */
+#define VBOXUSB_IOCTL_CODE(Function, Size) _IOWRN('V', (Function) | VBOXUSB_IOCTL_FLAG, sizeof(VBOXUSBREQ))
+#define VBOXUSB_IOCTL_CODE_FAST(Function) _IO( 'V', (Function) | VBOXUSB_IOCTL_FLAG)
+#define VBOXUSB_IOCTL_STRIP_SIZE(Code) (Code)
+
+#define VBOXUSBMON_IOCTL_ADD_FILTER VBOXUSB_IOCTL_CODE(1, (sizeof(VBoxUSBAddFilterReq)))
+#define VBOXUSBMON_IOCTL_REMOVE_FILTER VBOXUSB_IOCTL_CODE(2, (sizeof(VBoxUSBRemoveFilterReq)))
+#define VBOXUSBMON_IOCTL_RESET_DEVICE VBOXUSB_IOCTL_CODE(3, (sizeof(VBOXUSBREQ_RESET_DEVICE)))
+#define VBOXUSBMON_IOCTL_DEVICE_INSTANCE VBOXUSB_IOCTL_CODE(4, (sizeof(VBOXUSBREQ_DEVICE_INSTANCE)))
+#define VBOXUSBMON_IOCTL_CLIENT_INFO VBOXUSB_IOCTL_CODE(5, (sizeof(VBOXUSBREQ_CLIENT_PATH)))
+#define VBOXUSBMON_IOCTL_GET_VERSION VBOXUSB_IOCTL_CODE(6, (sizeof(VBOXUSBREQ_GET_VERSION)))
+
+/* VBoxUSB ioctls */
+#define VBOXUSB_IOCTL_SEND_URB VBOXUSB_IOCTL_CODE(20, (sizeof(VBOXUSBREQ_URB))) /* 1072146796 */
+#define VBOXUSB_IOCTL_REAP_URB VBOXUSB_IOCTL_CODE(21, (sizeof(VBOXUSBREQ_URB))) /* 1072146795 */
+#define VBOXUSB_IOCTL_CLEAR_EP VBOXUSB_IOCTL_CODE(22, (sizeof(VBOXUSBREQ_CLEAR_EP))) /* 1072146794 */
+#define VBOXUSB_IOCTL_SET_CONFIG VBOXUSB_IOCTL_CODE(23, (sizeof(VBOXUSBREQ_SET_CONFIG))) /* 1072146793 */
+#define VBOXUSB_IOCTL_SET_INTERFACE VBOXUSB_IOCTL_CODE(24, (sizeof(VBOXUSBREQ_SET_INTERFACE))) /* 1072146792 */
+#define VBOXUSB_IOCTL_CLOSE_DEVICE VBOXUSB_IOCTL_CODE(25, (sizeof(VBOXUSBREQ_CLOSE_DEVICE))) /* 1072146791 0xc0185699 */
+#define VBOXUSB_IOCTL_ABORT_PIPE VBOXUSB_IOCTL_CODE(26, (sizeof(VBOXUSBREQ_ABORT_PIPE))) /* 1072146790 */
+#define VBOXUSB_IOCTL_GET_CONFIG VBOXUSB_IOCTL_CODE(27, (sizeof(VBOXUSBREQ_GET_CONFIG))) /* 1072146789 */
+#define VBOXUSB_IOCTL_GET_VERSION VBOXUSB_IOCTL_CODE(28, (sizeof(VBOXUSBREQ_GET_VERSION))) /* 1072146788 */
+
+/** @} */
+
+/* USBLibHelper data for resetting the device. */
+typedef struct VBOXUSBHELPERDATA_RESET
+{
+ /** Path of the USB device. */
+ const char *pszDevicePath;
+ /** Re-enumerate or not. */
+ bool fHardReset;
+} VBOXUSBHELPERDATA_RESET;
+typedef VBOXUSBHELPERDATA_RESET *PVBOXUSBHELPERDATA_RESET;
+typedef const VBOXUSBHELPERDATA_RESET *PCVBOXUSBHELPERDATA_RESET;
+
+/* USBLibHelper data for device hijacking. */
+typedef struct VBOXUSBHELPERDATA_ALIAS
+{
+ /** Vendor ID. */
+ uint16_t idVendor;
+ /** Product ID. */
+ uint16_t idProduct;
+ /** Revision, integer part. */
+ uint16_t bcdDevice;
+ /** Path of the USB device. */
+ const char *pszDevicePath;
+} VBOXUSBHELPERDATA_ALIAS;
+typedef VBOXUSBHELPERDATA_ALIAS *PVBOXUSBHELPERDATA_ALIAS;
+typedef const VBOXUSBHELPERDATA_ALIAS *PCVBOXUSBHELPERDATA_ALIAS;
+
+USBLIB_DECL(int) USBLibResetDevice(char *pszDevicePath, bool fReattach);
+USBLIB_DECL(int) USBLibDeviceInstance(char *pszDevicePath, int *pInstance);
+USBLIB_DECL(int) USBLibGetClientInfo(char *pszDeviceIdent, char **ppszClientPath, int *pInstance);
+USBLIB_DECL(int) USBLibAddDeviceAlias(PUSBDEVICE pDevice);
+USBLIB_DECL(int) USBLibRemoveDeviceAlias(PUSBDEVICE pDevice);
+/*USBLIB_DECL(int) USBLibConfigureDevice(PUSBDEVICE pDevice);*/
+
+/** @} */
+RT_C_DECLS_END
+
+#endif /* !VBOX_INCLUDED_usblib_solaris_h */
+
diff --git a/include/VBox/usblib-win.h b/include/VBox/usblib-win.h
new file mode 100644
index 00000000..24b26c6d
--- /dev/null
+++ b/include/VBox/usblib-win.h
@@ -0,0 +1,309 @@
+/** @file
+ * USBLib - Library for wrapping up the VBoxUSB functionality, Windows flavor.
+ * (DEV,HDrv,Main)
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_usblib_win_h
+#define VBOX_INCLUDED_usblib_win_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/cdefs.h>
+#include <VBox/types.h>
+#include <VBox/usb.h>
+
+#include <initguid.h>
+
+
+/** @defgroup grp_usblib_win Windows USB Specifics
+ * @ingroup grp_usblib
+ * @{
+ */
+
+// {6068EB61-98E7-4c98-9E20-1F068295909A}
+DEFINE_GUID(GUID_CLASS_VBOXUSB, 0x873fdf, 0xCAFE, 0x80EE, 0xaa, 0x5e, 0x0, 0xc0, 0x4f, 0xb1, 0x72, 0xb);
+
+#define USBFLT_SERVICE_NAME "\\\\.\\VBoxUSBFlt"
+#define USBFLT_NTDEVICE_NAME_STRING L"\\Device\\VBoxUSBFlt"
+#define USBFLT_SYMBOLIC_NAME_STRING L"\\DosDevices\\VBoxUSBFlt"
+
+#define USBMON_SERVICE_NAME_W L"VBoxUSBMon"
+#define USBMON_DEVICE_NAME "\\\\.\\VBoxUSBMon"
+#define USBMON_DEVICE_NAME_NT L"\\Device\\VBoxUSBMon"
+#define USBMON_DEVICE_NAME_DOS L"\\DosDevices\\VBoxUSBMon"
+
+/*
+ * IOCtl numbers.
+ * We're using the Win32 type of numbers here, thus the macros below.
+ */
+
+#ifndef CTL_CODE
+# if defined(RT_OS_WINDOWS)
+# define CTL_CODE(DeviceType, Function, Method, Access) \
+ ( ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method))
+#else /* unix: */
+# define CTL_CODE(DeviceType, Function, Method_ignored, Access_ignored) \
+ ( (3 << 30) | ((DeviceType) << 8) | (Function) | (sizeof(SUPDRVIOCTLDATA) << 16) )
+# endif
+#endif
+#ifndef METHOD_BUFFERED
+# define METHOD_BUFFERED 0
+#endif
+#ifndef FILE_WRITE_ACCESS
+# define FILE_WRITE_ACCESS 0x0002
+#endif
+#ifndef FILE_DEVICE_UNKNOWN
+# define FILE_DEVICE_UNKNOWN 0x00000022
+#endif
+
+#define USBMON_MAJOR_VERSION 5
+#define USBMON_MINOR_VERSION 0
+
+#define USBDRV_MAJOR_VERSION 5
+#define USBDRV_MINOR_VERSION 0
+
+#define SUPUSB_IOCTL_TEST CTL_CODE(FILE_DEVICE_UNKNOWN, 0x601, METHOD_BUFFERED, FILE_WRITE_ACCESS)
+#define SUPUSB_IOCTL_GET_DEVICE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x603, METHOD_BUFFERED, FILE_WRITE_ACCESS)
+#define SUPUSB_IOCTL_SEND_URB CTL_CODE(FILE_DEVICE_UNKNOWN, 0x607, METHOD_BUFFERED, FILE_WRITE_ACCESS)
+#define SUPUSB_IOCTL_USB_RESET CTL_CODE(FILE_DEVICE_UNKNOWN, 0x608, METHOD_BUFFERED, FILE_WRITE_ACCESS)
+#define SUPUSB_IOCTL_USB_SELECT_INTERFACE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x609, METHOD_BUFFERED, FILE_WRITE_ACCESS)
+#define SUPUSB_IOCTL_USB_SET_CONFIG CTL_CODE(FILE_DEVICE_UNKNOWN, 0x60A, METHOD_BUFFERED, FILE_WRITE_ACCESS)
+#define SUPUSB_IOCTL_USB_CLAIM_DEVICE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x60B, METHOD_BUFFERED, FILE_WRITE_ACCESS)
+#define SUPUSB_IOCTL_USB_RELEASE_DEVICE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x60C, METHOD_BUFFERED, FILE_WRITE_ACCESS)
+#define SUPUSB_IOCTL_IS_OPERATIONAL CTL_CODE(FILE_DEVICE_UNKNOWN, 0x60D, METHOD_BUFFERED, FILE_WRITE_ACCESS)
+#define SUPUSB_IOCTL_USB_CLEAR_ENDPOINT CTL_CODE(FILE_DEVICE_UNKNOWN, 0x60E, METHOD_BUFFERED, FILE_WRITE_ACCESS)
+#define SUPUSB_IOCTL_GET_VERSION CTL_CODE(FILE_DEVICE_UNKNOWN, 0x60F, METHOD_BUFFERED, FILE_WRITE_ACCESS)
+#define SUPUSB_IOCTL_USB_ABORT_ENDPOINT CTL_CODE(FILE_DEVICE_UNKNOWN, 0x610, METHOD_BUFFERED, FILE_WRITE_ACCESS)
+
+#define SUPUSBFLT_IOCTL_GET_NUM_DEVICES CTL_CODE(FILE_DEVICE_UNKNOWN, 0x602, METHOD_BUFFERED, FILE_WRITE_ACCESS)
+#define SUPUSBFLT_IOCTL_USB_CHANGE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x604, METHOD_BUFFERED, FILE_WRITE_ACCESS)
+#define SUPUSBFLT_IOCTL_DISABLE_CAPTURE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x605, METHOD_BUFFERED, FILE_WRITE_ACCESS)
+#define SUPUSBFLT_IOCTL_ENABLE_CAPTURE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x606, METHOD_BUFFERED, FILE_WRITE_ACCESS)
+#define SUPUSBFLT_IOCTL_IGNORE_DEVICE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x60F, METHOD_BUFFERED, FILE_WRITE_ACCESS)
+#define SUPUSBFLT_IOCTL_GET_VERSION CTL_CODE(FILE_DEVICE_UNKNOWN, 0x610, METHOD_BUFFERED, FILE_WRITE_ACCESS)
+#define SUPUSBFLT_IOCTL_ADD_FILTER CTL_CODE(FILE_DEVICE_UNKNOWN, 0x611, METHOD_BUFFERED, FILE_WRITE_ACCESS)
+#define SUPUSBFLT_IOCTL_REMOVE_FILTER CTL_CODE(FILE_DEVICE_UNKNOWN, 0x612, METHOD_BUFFERED, FILE_WRITE_ACCESS)
+#define SUPUSBFLT_IOCTL_CAPTURE_DEVICE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x613, METHOD_BUFFERED, FILE_WRITE_ACCESS)
+#define SUPUSBFLT_IOCTL_RELEASE_DEVICE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x614, METHOD_BUFFERED, FILE_WRITE_ACCESS)
+#define SUPUSBFLT_IOCTL_RUN_FILTERS CTL_CODE(FILE_DEVICE_UNKNOWN, 0x615, METHOD_BUFFERED, FILE_WRITE_ACCESS)
+/* Used to be SUPUSBFLT_IOCTL_SET_NOTIFY_EVENT, 0x616 */
+#define SUPUSBFLT_IOCTL_GET_DEVICE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x617, METHOD_BUFFERED, FILE_WRITE_ACCESS)
+
+#pragma pack(4)
+
+#define MAX_FILTER_NAME 128
+#define MAX_USB_SERIAL_STRING 64
+
+/* a user-mode handle that could be used for retriving device information
+ * from the monitor driver */
+typedef void* HVBOXUSBDEVUSR;
+
+typedef struct
+{
+ HVBOXUSBDEVUSR hDevice;
+} USBSUP_GETDEV, *PUSBSUP_GETDEV;
+
+typedef struct
+{
+ USBDEVICESTATE enmState;
+} USBSUP_GETDEV_MON, *PUSBSUP_GETDEV_MON;
+
+typedef struct
+{
+ uint32_t u32Major;
+ uint32_t u32Minor;
+} USBSUP_VERSION, *PUSBSUP_VERSION;
+
+
+typedef struct USBSUP_FLTADDOUT
+{
+ uintptr_t uId; /* The ID. */
+ int rc; /* The return code. */
+} USBSUP_FLTADDOUT, *PUSBSUP_FLTADDOUT;
+
+typedef struct
+{
+ uint16_t usVendorId;
+ uint16_t usProductId;
+ uint16_t usRevision;
+} USBSUP_CAPTURE, *PUSBSUP_CAPTURE;
+
+typedef USBSUP_CAPTURE USBSUP_RELEASE;
+typedef PUSBSUP_CAPTURE PUSBSUP_RELEASE;
+
+typedef struct
+{
+ uint8_t bInterfaceNumber;
+ uint8_t fClaimed;
+} USBSUP_CLAIMDEV, *PUSBSUP_CLAIMDEV;
+
+typedef USBSUP_CLAIMDEV USBSUP_RELEASEDEV;
+typedef PUSBSUP_CLAIMDEV PUSBSUP_RELEASEDEV;
+
+typedef struct
+{
+ uint32_t cUSBDevices;
+} USBSUP_GETNUMDEV, *PUSBSUP_GETNUMDEV;
+
+typedef struct
+{
+ uint8_t fUSBChange;
+ uint32_t cUSBStateChange;
+} USBSUP_USB_CHANGE, *PUSBSUP_USB_CHANGE;
+
+typedef struct
+{
+ uint8_t bConfigurationValue;
+} USBSUP_SET_CONFIG, *PUSBSUP_SET_CONFIG;
+
+typedef struct
+{
+ uint8_t bInterfaceNumber;
+ uint8_t bAlternateSetting;
+} USBSUP_SELECT_INTERFACE, *PUSBSUP_SELECT_INTERFACE;
+
+typedef struct
+{
+ uint8_t bEndpoint;
+} USBSUP_CLEAR_ENDPOINT, *PUSBSUP_CLEAR_ENDPOINT;
+
+typedef enum
+{
+ USBSUP_TRANSFER_TYPE_CTRL = 0,
+ USBSUP_TRANSFER_TYPE_ISOC = 1,
+ USBSUP_TRANSFER_TYPE_BULK = 2,
+ USBSUP_TRANSFER_TYPE_INTR = 3,
+ USBSUP_TRANSFER_TYPE_MSG = 4
+} USBSUP_TRANSFER_TYPE;
+
+typedef enum
+{
+ USBSUP_DIRECTION_SETUP = 0,
+ USBSUP_DIRECTION_IN = 1,
+ USBSUP_DIRECTION_OUT = 2
+} USBSUP_DIRECTION;
+
+typedef enum
+{
+ USBSUP_FLAG_NONE = 0,
+ USBSUP_FLAG_SHORT_OK = 1
+} USBSUP_XFER_FLAG;
+
+typedef enum
+{
+ USBSUP_XFER_OK = 0,
+ USBSUP_XFER_STALL = 1,
+ USBSUP_XFER_DNR = 2,
+ USBSUP_XFER_CRC = 3,
+ USBSUP_XFER_NAC = 4,
+ USBSUP_XFER_UNDERRUN = 5,
+ USBSUP_XFER_OVERRUN = 6
+} USBSUP_ERROR;
+
+typedef struct USBSUP_ISOCPKT
+{
+ uint16_t cb; /* [in/out] packet size/size transferred */
+ uint16_t off; /* [in] offset of packet in buffer */
+ USBSUP_ERROR stat; /* [out] packet status */
+} USBSUP_ISOCPKT;
+
+typedef struct
+{
+ USBSUP_TRANSFER_TYPE type; /* [in] USBSUP_TRANSFER_TYPE_XXX */
+ uint32_t ep; /* [in] index to dev->pipe */
+ USBSUP_DIRECTION dir; /* [in] USBSUP_DIRECTION_XXX */
+ USBSUP_XFER_FLAG flags; /* [in] USBSUP_FLAG_XXX */
+ USBSUP_ERROR error; /* [out] USBSUP_XFER_XXX */
+ size_t len; /* [in/out] may change */
+ void *buf; /* [in/out] depends on dir */
+ uint32_t numIsoPkts; /* [in] number of isochronous packets (8 max) */
+ USBSUP_ISOCPKT aIsoPkts[8]; /* [in/out] isochronous packet descriptors */
+} USBSUP_URB, *PUSBSUP_URB;
+
+typedef struct
+{
+ union
+ {
+ /* in: event handle */
+ void* hEvent;
+ /* out: result */
+ int rc;
+ } u;
+} USBSUP_SET_NOTIFY_EVENT, *PUSBSUP_SET_NOTIFY_EVENT;
+
+typedef struct
+{
+ uint16_t usVendorId;
+ uint16_t usProductId;
+ uint16_t usRevision;
+ uint16_t usAlignment;
+ char DrvKeyName[512];
+} USBSUP_DEVID, *PUSBSUP_DEVID;
+
+#pragma pack() /* paranoia */
+
+
+RT_C_DECLS_BEGIN
+
+#ifdef IN_RING3
+
+/** @defgroup grp_usblib_r3 USBLIB Host Context Ring 3 API
+ * @{
+ */
+
+/**
+ * Return all attached USB devices.
+ *
+ * @returns VBox status code
+ * @param ppDevices Receives pointer to list of devices
+ * @param pcbNumDevices Number of USB devices in the list
+ */
+USBLIB_DECL(int) USBLibGetDevices(PUSBDEVICE *ppDevices, uint32_t *pcbNumDevices);
+
+USBLIB_DECL(int) USBLibWaitChange(RTMSINTERVAL cMillies);
+
+USBLIB_DECL(int) USBLibInterruptWaitChange(void);
+
+USBLIB_DECL(int) USBLibRunFilters(void);
+
+/** @} */
+#endif
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !VBOX_INCLUDED_usblib_win_h */
+
diff --git a/include/VBox/usblib.h b/include/VBox/usblib.h
new file mode 100644
index 00000000..13fc690e
--- /dev/null
+++ b/include/VBox/usblib.h
@@ -0,0 +1,196 @@
+/** @file
+ * USBLib - Library for wrapping up the VBoxUSB functionality. (DEV,HDrv,Main)
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_usblib_h
+#define VBOX_INCLUDED_usblib_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/cdefs.h>
+#include <VBox/types.h>
+#include <VBox/usb.h>
+#include <VBox/usbfilter.h>
+#include <iprt/ctype.h>
+#include <iprt/string.h>
+
+#ifdef RT_OS_WINDOWS
+# include <VBox/usblib-win.h>
+#endif
+#ifdef RT_OS_SOLARIS
+# include <VBox/usblib-solaris.h>
+#endif
+#ifdef RT_OS_DARWIN
+# include <VBox/usblib-darwin.h>
+#endif
+/** @todo merge the usblib-win.h interface into the darwin and linux ports where suitable. */
+
+RT_C_DECLS_BEGIN
+/** @defgroup grp_usblib USBLib - USB Support Library
+ * This module implements the basic low-level OS interfaces and common USB code.
+ * @{
+ */
+
+#ifdef IN_RING3
+/**
+ * Initializes the USBLib component.
+ *
+ * The USBLib keeps a per process connection to the kernel driver
+ * and all USBLib users within a process will share the same
+ * connection. USBLib does reference counting to make sure that
+ * the connection remains open until all users has called USBLibTerm().
+ *
+ * @returns VBox status code.
+ *
+ * @remark The users within the process are responsible for not calling
+ * this function at the same time (because I'm lazy).
+ */
+USBLIB_DECL(int) USBLibInit(void);
+
+/**
+ * Terminates the USBLib component.
+ *
+ * Must match successful USBLibInit calls.
+ *
+ * @returns VBox status code.
+ */
+USBLIB_DECL(int) USBLibTerm(void);
+
+/**
+ * Adds a filter.
+ *
+ * This function will validate and transfer the specified filter
+ * to the kernel driver and make it start using it. The kernel
+ * driver will return a filter id that this function passes on
+ * to its caller.
+ *
+ * The kernel driver will associate the added filter with the
+ * calling process and automatically remove all filters when
+ * the process terminates the connection to it or dies.
+ *
+ * @returns Filter id for passing to USBLibRemoveFilter on success.
+ * @returns NULL on failure.
+ *
+ * @param pFilter The filter to add.
+ */
+USBLIB_DECL(void *) USBLibAddFilter(PCUSBFILTER pFilter);
+
+/**
+ * Removes a filter.
+ *
+ * @param pvId The ID returned by USBLibAddFilter.
+ */
+USBLIB_DECL(void) USBLibRemoveFilter(void *pvId);
+
+/**
+ * Calculate the hash of the serial string.
+ *
+ * 64bit FNV1a, chosen because it is designed to hash in to a power of two
+ * space, and is much quicker and simpler than, say, a half MD4.
+ *
+ * @returns the hash.
+ * @param pszSerial The serial string.
+ */
+USBLIB_DECL(uint64_t) USBLibHashSerial(const char *pszSerial);
+
+#endif /* IN_RING3 */
+
+/**
+ * Purge string of non-UTF-8 encodings and control characters.
+ *
+ * Control characters creates problems when presented to the user and currently
+ * also when used in XML settings. So, we must purge them in the USB vendor,
+ * product, and serial number strings.
+ *
+ * @returns String length (excluding terminator).
+ * @param psz The string to purge.
+ *
+ * @remarks The return string may be shorter than the input, left over space
+ * after the end of the string will be filled with zeros.
+ */
+DECLINLINE(size_t) USBLibPurgeEncoding(char *psz)
+{
+ if (psz)
+ {
+ size_t offSrc;
+
+ /* Beat it into valid UTF-8 encoding. */
+ RTStrPurgeEncoding(psz);
+
+ /* Look for control characters. */
+ for (offSrc = 0; ; offSrc++)
+ {
+ char ch = psz[offSrc];
+ if (RT_UNLIKELY(RT_C_IS_CNTRL(ch) && ch != '\0'))
+ {
+ /* Found a control character! Replace tab by space and remove all others. */
+ size_t offDst = offSrc;
+ for (;; offSrc++)
+ {
+ ch = psz[offSrc];
+ if (RT_C_IS_CNTRL(ch) && ch != '\0')
+ {
+ if (ch == '\t')
+ ch = ' ';
+ else
+ continue;
+ }
+ psz[offDst++] = ch;
+ if (ch == '\0')
+ break;
+ }
+
+ /* Wind back to the zero terminator and zero fill any gap to make
+ USBFilterValidate happy. (offSrc is at zero terminator too.) */
+ offDst--;
+ while (offSrc > offDst)
+ psz[offSrc--] = '\0';
+
+ return offDst;
+ }
+ if (ch == '\0')
+ break;
+ }
+ return offSrc;
+ }
+ return 0;
+}
+
+
+/** @} */
+RT_C_DECLS_END
+
+#endif /* !VBOX_INCLUDED_usblib_h */
+
diff --git a/include/VBox/various.sed b/include/VBox/various.sed
new file mode 100644
index 00000000..8797b029
--- /dev/null
+++ b/include/VBox/various.sed
@@ -0,0 +1,148 @@
+# $Id: various.sed $
+## @file
+# Converts some C header elements into nasm/yasm syntax.
+#
+# This is used by 'incs' in /Maintenance.kmk (/Makefile.kmk).
+#
+
+#
+# Copyright (C) 2006-2022 Oracle and/or its affiliates.
+#
+# This file is part of VirtualBox base platform packages, as
+# available from https://www.virtualbox.org.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation, in version 3 of the
+# License.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <https://www.gnu.org/licenses>.
+#
+# The contents of this file may alternatively be used under the terms
+# of the Common Development and Distribution License Version 1.0
+# (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+# in the VirtualBox 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.
+#
+# SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+#
+
+# Pass thru the file header and copyright.
+1,/^\#ifndef/{
+/^\#ifndef/b next
+s/^[/ ]//
+s/^\*\//;/
+s/\*/;/g
+4s/^.*$/; Automatically generated by various.sed. DO NOT EDIT!/
+b end
+}
+:next
+
+# Check for markers (typically in comments).
+/ASM-INC/basm-inc
+/ASM-NOINC/basm-noinc
+
+# Newline escapes.
+:check-newline-escape
+/\\$/!bno-more-newline-escapes
+N
+b check-newline-escape
+:no-more-newline-escapes
+
+# Strip comments and trailing space.
+s/[[:space:]][[:space:]]*\/\*.*$//g
+s/[[:space:]][[:space:]]*\/\/.*$//g
+s/[[:space:]][[:space:]]*$//g
+
+# Try identify the statement.
+/#[[:space:]]*define[[:space:]]/bdefine
+/#[[:space:]]*ifdef[[:space:]]/bifdef
+/#[[:space:]]*ifndef[[:space:]]/bifndef
+/#[[:space:]]*if[[:space:]]/bif
+/#[[:space:]]*elif[[:space:]]/belif
+/#[[:space:]]*else$/belse
+/#[[:space:]]*endif$/bendif
+
+# Not recognized, drop it.
+:asm-noinc
+d
+b end
+
+#
+# Defines needs some extra massaging to work in yasm.
+# Things like trailing type indicators ('U', 'ULL' ++) does not go down well.
+#
+:define
+/\$/d
+s/#\([[:space:]]*\)define/\1%define/
+
+s/\([[:space:]]0[xX][0-9a-fA-F][0-9a-fA-F]*\)U$/\1/
+s/\([[:space:]]0[xX][0-9a-fA-F][0-9a-fA-F]*\)U\([[:space:]]*\))$/\1\2)/
+s/\([[:space:]][0-9][0-9]*\)U[[:space:]]*$/\1/
+s/\([[:space:]][0-9][0-9]*\)U\([[:space:]]*\))$/\1\2)/
+
+s/\([[:space:]]0[xX][0-9a-fA-F][0-9a-fA-F]*\)UL$/\1/
+s/\([[:space:]]0[xX][0-9a-fA-F][0-9a-fA-F]*\)UL\([[:space:]]*\))$/\1\2)/
+s/\([[:space:]][0-9][0-9]*\)UL[[:space:]]*$/\1/
+s/\([[:space:]][0-9][0-9]*\)UL\([[:space:]]*\))$/\1\2)/
+
+s/\([[:space:]]0[xX][0-9a-fA-F][0-9a-fA-F]*\)ULL$/\1/
+s/\([[:space:]]0[xX][0-9a-fA-F][0-9a-fA-F]*\)ULL\([[:space:]]*\))$/\1\2)/
+s/\([[:space:]][0-9][0-9]*\)ULL[[:space:]]*$/\1/
+s/\([[:space:]][0-9][0-9]*\)ULL\([[:space:]]*\))$/\1\2)/
+
+s/UINT64_C([[:space:]]*\(0[xX][0-9a-fA-F][0-9a-fA-F]*\)[[:space:]]*)/\1/
+s/UINT64_C([[:space:]]*\([0-9][0-9]*\)[[:space:]]*)/\1/
+s/UINT32_C([[:space:]]*\(0[xX][0-9a-fA-F][0-9a-fA-F]*\)[[:space:]]*)/\1/
+s/UINT32_C([[:space:]]*\([0-9][0-9]*\)[[:space:]]*)/\1/
+s/UINT16_C([[:space:]]*\(0[xX][0-9a-fA-F][0-9a-fA-F]*\)[[:space:]]*)/\1/
+s/UINT16_C([[:space:]]*\([0-9][0-9]*\)[[:space:]]*)/\1/
+s/UINT8_C([[:space:]]*\(0[xX][0-9a-fA-F][0-9a-fA-F]*\)[[:space:]]*)/\1/
+s/UINT8_C([[:space:]]*\([0-9][0-9]*\)[[:space:]]*)/\1/
+
+b end
+
+#
+# Conditional statements, 1:1.
+#
+:ifdef
+s/#\([[:space:]]*\)ifdef/\1%ifdef/
+b end
+
+:ifndef
+s/#\([[:space:]]*\)ifndef/\1%ifndef/
+b end
+
+:if
+s/#\([[:space:]]*\)if/\1%if/
+b end
+
+:elif
+s/#\([[:space:]]*\)elif/\1%elif/
+b end
+
+:else
+s/#\([[:space:]]*\)else.*$/\1%else/
+b end
+
+:endif
+s/#\([[:space:]]*\)endif.*$/\1%endif/
+b end
+
+#
+# Assembly statement... may need adjusting when used.
+#
+:asm-inc
+b end
+
+:end
+
diff --git a/include/VBox/vd-cache-backend.h b/include/VBox/vd-cache-backend.h
new file mode 100644
index 00000000..c2d7163f
--- /dev/null
+++ b/include/VBox/vd-cache-backend.h
@@ -0,0 +1,332 @@
+/** @file
+ * Internal hard disk format support API for VBoxHDD cache images.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vd_cache_backend_h
+#define VBOX_INCLUDED_vd_cache_backend_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/vd.h>
+#include <VBox/vd-common.h>
+#include <VBox/vd-ifs-internal.h>
+
+/**
+ * Cache format backend interface used by VBox HDD Container implementation.
+ */
+typedef struct VDCACHEBACKEND
+{
+ /** Structure version. VD_CACHEBACKEND_VERSION defines the current version. */
+ uint32_t u32Version;
+ /** The name of the backend (constant string). */
+ const char *pszBackendName;
+ /** The capabilities of the backend. */
+ uint64_t uBackendCaps;
+
+ /**
+ * Pointer to a NULL-terminated array of strings, containing the supported
+ * file extensions. Note that some backends do not work on files, so this
+ * pointer may just contain NULL.
+ */
+ const char * const *papszFileExtensions;
+
+ /**
+ * Pointer to an array of structs describing each supported config key.
+ * Terminated by a NULL config key. Note that some backends do not support
+ * the configuration interface, so this pointer may just contain NULL.
+ * Mandatory if the backend sets VD_CAP_CONFIG.
+ */
+ PCVDCONFIGINFO paConfigInfo;
+
+ /**
+ * Probes the given image.
+ *
+ * @returns VBox status code.
+ * @param pszFilename Name of the image file.
+ * @param pVDIfsDisk Pointer to the per-disk VD interface list.
+ * @param pVDIfsImage Pointer to the per-image VD interface list.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnProbe, (const char *pszFilename, PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage));
+
+ /**
+ * Open a cache image.
+ *
+ * @returns VBox status code.
+ * @param pszFilename Name of the image file to open. Guaranteed to be available and
+ * unchanged during the lifetime of this image.
+ * @param uOpenFlags Image file open mode, see VD_OPEN_FLAGS_* constants.
+ * @param pVDIfsDisk Pointer to the per-disk VD interface list.
+ * @param pVDIfsImage Pointer to the per-image VD interface list.
+ * @param ppBackendData Opaque state data for this image.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnOpen, (const char *pszFilename, unsigned uOpenFlags,
+ PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage,
+ void **ppBackendData));
+
+ /**
+ * Create a cache image.
+ *
+ * @returns VBox status code.
+ * @param pszFilename Name of the image file to create. Guaranteed to be available and
+ * unchanged during the lifetime of this image.
+ * @param cbSize Image size in bytes.
+ * @param uImageFlags Flags specifying special image features.
+ * @param pszComment Pointer to image comment. NULL is ok.
+ * @param pUuid New UUID of the image. Not NULL.
+ * @param uOpenFlags Image file open mode, see VD_OPEN_FLAGS_* constants.
+ * @param uPercentStart Starting value for progress percentage.
+ * @param uPercentSpan Span for varying progress percentage.
+ * @param pVDIfsDisk Pointer to the per-disk VD interface list.
+ * @param pVDIfsImage Pointer to the per-image VD interface list.
+ * @param pVDIfsOperation Pointer to the per-operation VD interface list.
+ * @param ppBackendData Opaque state data for this image.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnCreate, (const char *pszFilename, uint64_t cbSize,
+ unsigned uImageFlags, const char *pszComment,
+ PCRTUUID pUuid, unsigned uOpenFlags,
+ unsigned uPercentStart, unsigned uPercentSpan,
+ PVDINTERFACE pVDIfsDisk,
+ PVDINTERFACE pVDIfsImage,
+ PVDINTERFACE pVDIfsOperation,
+ void **ppBackendData));
+
+ /**
+ * Close a cache image.
+ *
+ * @returns VBox status code.
+ * @param pBackendData Opaque state data for this image.
+ * @param fDelete If true, delete the image from the host disk.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnClose, (void *pBackendData, bool fDelete));
+
+ /**
+ * Start a read request.
+ *
+ * @returns VBox status code.
+ * @param pBackendData Opaque state data for this image.
+ * @param uOffset The offset of the virtual disk to read from.
+ * @param cbToRead How many bytes to read.
+ * @param pIoCtx I/O context associated with this request.
+ * @param pcbActuallyRead Pointer to returned number of bytes read.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnRead, (void *pBackendData, uint64_t uOffset, size_t cbToRead,
+ PVDIOCTX pIoCtx, size_t *pcbActuallyRead));
+
+ /**
+ * Start a write request.
+ *
+ * @returns VBox status code.
+ * @param pBackendData Opaque state data for this image.
+ * @param uOffset The offset of the virtual disk to write to.
+ * @param cbToWrite How many bytes to write.
+ * @param pIoCtx I/O context associated with this request.
+ * @param pcbWriteProcess Pointer to returned number of bytes that could
+ * be processed. In case the function returned
+ * VERR_VD_BLOCK_FREE this is the number of bytes
+ * that could be written in a full block write,
+ * when prefixed/postfixed by the appropriate
+ * amount of (previously read) padding data.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnWrite, (void *pBackendData, uint64_t uOffset, size_t cbToWrite,
+ PVDIOCTX pIoCtx, size_t *pcbWriteProcess));
+
+ /**
+ * Flush data to disk.
+ *
+ * @returns VBox status code.
+ * @param pBackendData Opaque state data for this image.
+ * @param pIoCtx I/O context associated with this request.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnFlush, (void *pBackendData, PVDIOCTX pIoCtx));
+
+ /**
+ * Discards the given amount of bytes from the cache.
+ *
+ * @returns VBox status code.
+ * @retval VERR_VD_DISCARD_ALIGNMENT_NOT_MET if the range doesn't meet the required alignment
+ * for the discard.
+ * @param pBackendData Opaque state data for this image.
+ * @param pIoCtx I/O context associated with this request.
+ * @param uOffset The offset of the first byte to discard.
+ * @param cbDiscard How many bytes to discard.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnDiscard, (void *pBackendData, PVDIOCTX pIoCtx,
+ uint64_t uOffset, size_t cbDiscard,
+ size_t *pcbPreAllocated,
+ size_t *pcbPostAllocated,
+ size_t *pcbActuallyDiscarded,
+ void **ppbmAllocationBitmap,
+ unsigned fDiscard));
+
+ /**
+ * Get the version of a cache image.
+ *
+ * @returns version of cache image.
+ * @param pBackendData Opaque state data for this image.
+ */
+ DECLR3CALLBACKMEMBER(unsigned, pfnGetVersion, (void *pBackendData));
+
+ /**
+ * Get the capacity of a cache image.
+ *
+ * @returns size of cache image in bytes.
+ * @param pBackendData Opaque state data for this image.
+ */
+ DECLR3CALLBACKMEMBER(uint64_t, pfnGetSize, (void *pBackendData));
+
+ /**
+ * Get the file size of a cache image.
+ *
+ * @returns size of cache image in bytes.
+ * @param pBackendData Opaque state data for this image.
+ */
+ DECLR3CALLBACKMEMBER(uint64_t, pfnGetFileSize, (void *pBackendData));
+
+ /**
+ * Get the image flags of a cache image.
+ *
+ * @returns image flags of cache image.
+ * @param pBackendData Opaque state data for this image.
+ */
+ DECLR3CALLBACKMEMBER(unsigned, pfnGetImageFlags, (void *pBackendData));
+
+ /**
+ * Get the open flags of a cache image.
+ *
+ * @returns open flags of cache image.
+ * @param pBackendData Opaque state data for this image.
+ */
+ DECLR3CALLBACKMEMBER(unsigned, pfnGetOpenFlags, (void *pBackendData));
+
+ /**
+ * Set the open flags of a cache image. May cause the image to be locked
+ * in a different mode or be reopened (which can fail).
+ *
+ * @returns VBox status code.
+ * @param pBackendData Opaque state data for this image.
+ * @param uOpenFlags New open flags for this image.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSetOpenFlags, (void *pBackendData, unsigned uOpenFlags));
+
+ /**
+ * Get comment of a cache image.
+ *
+ * @returns VBox status code.
+ * @param pBackendData Opaque state data for this image.
+ * @param pszComment Where to store the comment.
+ * @param cbComment Size of the comment buffer.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnGetComment, (void *pBackendData, char *pszComment, size_t cbComment));
+
+ /**
+ * Set comment of a cache image.
+ *
+ * @returns VBox status code.
+ * @param pBackendData Opaque state data for this image.
+ * @param pszComment Where to get the comment from. NULL resets comment.
+ * The comment is silently truncated if the image format
+ * limit is exceeded.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSetComment, (void *pBackendData, const char *pszComment));
+
+ /**
+ * Get UUID of a cache image.
+ *
+ * @returns VBox status code.
+ * @param pBackendData Opaque state data for this image.
+ * @param pUuid Where to store the image UUID.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnGetUuid, (void *pBackendData, PRTUUID pUuid));
+
+ /**
+ * Set UUID of a cache image.
+ *
+ * @returns VBox status code.
+ * @param pBackendData Opaque state data for this image.
+ * @param pUuid Where to get the image UUID from.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSetUuid, (void *pBackendData, PCRTUUID pUuid));
+
+ /**
+ * Get last modification UUID of a cache image.
+ *
+ * @returns VBox status code.
+ * @param pBackendData Opaque state data for this image.
+ * @param pUuid Where to store the image modification UUID.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnGetModificationUuid, (void *pBackendData, PRTUUID pUuid));
+
+ /**
+ * Set last modification UUID of a cache image.
+ *
+ * @returns VBox status code.
+ * @param pBackendData Opaque state data for this image.
+ * @param pUuid Where to get the image modification UUID from.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSetModificationUuid, (void *pBackendData, PCRTUUID pUuid));
+
+ /**
+ * Dump information about a cache image.
+ *
+ * @param pBackendData Opaque state data for this image.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnDump, (void *pBackendData));
+
+ /** Returns a human readable hard disk location string given a
+ * set of hard disk configuration keys. The returned string is an
+ * equivalent of the full file path for image-based hard disks.
+ * Mandatory for backends with no VD_CAP_FILE and NULL otherwise. */
+ DECLR3CALLBACKMEMBER(int, pfnComposeLocation, (PVDINTERFACE pConfig, char **pszLocation));
+
+ /** Returns a human readable hard disk name string given a
+ * set of hard disk configuration keys. The returned string is an
+ * equivalent of the file name part in the full file path for
+ * image-based hard disks. Mandatory for backends with no
+ * VD_CAP_FILE and NULL otherwise. */
+ DECLR3CALLBACKMEMBER(int, pfnComposeName, (PVDINTERFACE pConfig, char **pszName));
+
+ /** Initialization safty marker. */
+ uint32_t u32VersionEnd;
+
+} VDCACHEBACKEND;
+/** Pointer to VD cache backend. */
+typedef VDCACHEBACKEND *PVDCACHEBACKEND;
+/** Constant pointer to VD backend. */
+typedef const VDCACHEBACKEND *PCVDCACHEBACKEND;
+
+/** The current version of the VDCACHEBACKEND structure. */
+#define VD_CACHEBACKEND_VERSION VD_VERSION_MAKE(0xff03, 1, 0)
+
+#endif /* !VBOX_INCLUDED_vd_cache_backend_h */
diff --git a/include/VBox/vd-common.h b/include/VBox/vd-common.h
new file mode 100644
index 00000000..6c65e13a
--- /dev/null
+++ b/include/VBox/vd-common.h
@@ -0,0 +1,76 @@
+/** @file
+ * VD: common definitions for the registration, backend and interface structures.
+ */
+
+/*
+ * Copyright (C) 2016-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vd_common_h
+#define VBOX_INCLUDED_vd_common_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/types.h>
+
+/** Makes a VD structure version out of an unique magic value and major &
+ * minor version numbers.
+ *
+ * @returns 32-bit structure version number.
+ *
+ * @param uMagic 16-bit magic value. This must be unique.
+ * @param uMajor 12-bit major version number. Structures with different
+ * major numbers are not compatible.
+ * @param uMinor 4-bit minor version number. When only the minor version
+ * differs, the structures will be 100% backwards
+ * compatible.
+ */
+#define VD_VERSION_MAKE(uMagic, uMajor, uMinor) \
+ ( ((uint32_t)(uMagic) << 16) | ((uint32_t)((uMajor) & 0xff) << 4) | ((uint32_t)((uMinor) & 0xf) << 0) )
+
+/** Checks if @a uVerMagic1 is compatible with @a uVerMagic2.
+ *
+ * @returns true / false.
+ * @param uVerMagic1 Typically the runtime version of the struct. This must
+ * have the same magic and major version as @a uVerMagic2
+ * and the minor version must be greater or equal to that
+ * of @a uVerMagic2.
+ * @param uVerMagic2 Typically the version the code was compiled against.
+ *
+ * @remarks The parameters will be referenced more than once.
+ */
+#define VD_VERSION_ARE_COMPATIBLE(uVerMagic1, uVerMagic2) \
+ ( (uVerMagic1) == (uVerMagic2) \
+ || ( (uVerMagic1) >= (uVerMagic2) \
+ && ((uVerMagic1) & UINT32_C(0xfffffff0)) == ((uVerMagic2) & UINT32_C(0xfffffff0)) ) \
+ )
+
+#endif /* !VBOX_INCLUDED_vd_common_h */
diff --git a/include/VBox/vd-filter-backend.h b/include/VBox/vd-filter-backend.h
new file mode 100644
index 00000000..ab45253f
--- /dev/null
+++ b/include/VBox/vd-filter-backend.h
@@ -0,0 +1,122 @@
+/** @file
+ * Internal VD filter backend interface.
+ */
+
+/*
+ * Copyright (C) 2014-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vd_filter_backend_h
+#define VBOX_INCLUDED_vd_filter_backend_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/vd.h>
+#include <VBox/vd-common.h>
+#include <VBox/vd-ifs-internal.h>
+
+/**
+ * VD filter backend interface.
+ */
+typedef struct VDFILTERBACKEND
+{
+ /** Structure version. VD_FLTBACKEND_VERSION defines the current version. */
+ uint32_t u32Version;
+ /** The name of the backend (constant string). */
+ const char *pszBackendName;
+
+ /**
+ * Pointer to an array of structs describing each supported config key.
+ * Terminated by a NULL config key. Note that some backends do not support
+ * the configuration interface, so this pointer may just contain NULL.
+ * Mandatory if the backend sets VD_CAP_CONFIG.
+ */
+ PCVDCONFIGINFO paConfigInfo;
+
+ /**
+ * Creates a new filter instance.
+ *
+ * @returns VBox status code.
+ * @param pVDIfsDisk Pointer to the per-disk VD interface list.
+ * @param fFlags Subset of VD_FILTER_FLAGS_*.
+ * @param pVDIfsFilter Pointer to the per-filter VD interface list.
+ * @param ppvBackendData Opaque state data for this filter instance.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnCreate, (PVDINTERFACE pVDIfsDisk, uint32_t fFlags,
+ PVDINTERFACE pVDIfsFilter,
+ void **ppvBackendData));
+
+ /**
+ * Destroys a filter instance.
+ *
+ * @returns VBox status code.
+ * @param pvBackendData Opaque state data for the filter instance to destroy.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnDestroy, (void *pvBackendData));
+
+ /**
+ * Filters the data of a read from the image chain. The filter is applied
+ * after everything was read.
+ *
+ * @returns VBox status code.
+ * @param pvBackendData Opaque state data for the filter instance.
+ * @param uOffset Start offset of the read.
+ * @param cbRead Number of bytes read.
+ * @param pIoCtx The I/O context holding the read data.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnFilterRead, (void *pvBackendData, uint64_t uOffset, size_t cbRead,
+ PVDIOCTX pIoCtx));
+
+ /**
+ * Filters the data of a write to the image chain. The filter is applied
+ * before everything is written.
+ *
+ * @returns VBox status code.
+ * @param pvBackendData Opaque state data for the filter instance.
+ * @param uOffset Start offset of the write.
+ * @param cbWrite Number of bytes to be written.
+ * @param pIoCtx The I/O context holding the data to write.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnFilterWrite, (void *pvBackendData, uint64_t uOffset, size_t cbWrite,
+ PVDIOCTX pIoCtx));
+
+ /** Initialization safty marker. */
+ uint32_t u32VersionEnd;
+} VDFILTERBACKEND;
+/** Pointer to VD filter backend. */
+typedef VDFILTERBACKEND *PVDFILTERBACKEND;
+/** Constant pointer to a VD filter backend. */
+typedef const VDFILTERBACKEND *PCVDFILTERBACKEND;
+
+/** The current version of the VDFILTERBACKEND structure. */
+#define VD_FLTBACKEND_VERSION VD_VERSION_MAKE(0xff02, 1, 0)
+
+#endif /* !VBOX_INCLUDED_vd_filter_backend_h */
diff --git a/include/VBox/vd-ifs-internal.h b/include/VBox/vd-ifs-internal.h
new file mode 100644
index 00000000..7bff7642
--- /dev/null
+++ b/include/VBox/vd-ifs-internal.h
@@ -0,0 +1,710 @@
+/** @file
+ * VD Container API - internal interfaces.
+ */
+
+/*
+ * Copyright (C) 2011-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vd_ifs_internal_h
+#define VBOX_INCLUDED_vd_ifs_internal_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/sg.h>
+#include <VBox/vd-ifs.h>
+
+RT_C_DECLS_BEGIN
+
+/** @addtogroup grp_vd
+ * @internal
+ * @{ */
+
+/**
+ * Read data callback.
+ *
+ * @return VBox status code.
+ * @return VERR_VD_NOT_OPENED if no image is opened in HDD container.
+ * @param pvUser The opaque data passed for the operation.
+ * @param uOffset Offset of first reading byte from start of disk.
+ * Must be aligned to a sector boundary.
+ * @param pvBuffer Pointer to buffer for reading data.
+ * @param cbBuffer Number of bytes to read.
+ * Must be aligned to a sector boundary.
+ */
+typedef DECLCALLBACKTYPE(int, FNVDPARENTREAD,(void *pvUser, uint64_t uOffset, void *pvBuffer, size_t cbBuffer));
+/** Pointer to a FNVDPARENTREAD. */
+typedef FNVDPARENTREAD *PFNVDPARENTREAD;
+
+/**
+ * Interface to get the parent state.
+ *
+ * Per-operation interface. Optional, present only if there is a parent, and
+ * used only internally for compacting.
+ */
+typedef struct VDINTERFACEPARENTSTATE
+{
+ /**
+ * Common interface header.
+ */
+ VDINTERFACE Core;
+
+ /**
+ * Read data callback, see FNVDPARENTREAD for details.
+ */
+ PFNVDPARENTREAD pfnParentRead;
+
+} VDINTERFACEPARENTSTATE, *PVDINTERFACEPARENTSTATE;
+
+
+/**
+ * Get parent state interface from interface list.
+ *
+ * @return Pointer to the first parent state interface in the list.
+ * @param pVDIfs Pointer to the interface list.
+ */
+DECLINLINE(PVDINTERFACEPARENTSTATE) VDIfParentStateGet(PVDINTERFACE pVDIfs)
+{
+ PVDINTERFACE pIf = VDInterfaceGet(pVDIfs, VDINTERFACETYPE_PARENTSTATE);
+
+ /* Check that the interface descriptor is a progress interface. */
+ AssertMsgReturn( !pIf
+ || ( (pIf->enmInterface == VDINTERFACETYPE_PARENTSTATE)
+ && (pIf->cbSize == sizeof(VDINTERFACEPARENTSTATE))),
+ ("Not a parent state interface"), NULL);
+
+ return (PVDINTERFACEPARENTSTATE)pIf;
+}
+
+/** Forward declaration. Only visible in the VBoxHDD module. */
+/** I/O context */
+typedef struct VDIOCTX *PVDIOCTX;
+/** Storage backend handle. */
+typedef struct VDIOSTORAGE *PVDIOSTORAGE;
+/** Pointer to a storage backend handle. */
+typedef PVDIOSTORAGE *PPVDIOSTORAGE;
+
+/**
+ * Completion callback for meta/userdata reads or writes.
+ *
+ * @return VBox status code.
+ * VINF_SUCCESS if everything was successful and the transfer can continue.
+ * VERR_VD_ASYNC_IO_IN_PROGRESS if there is another data transfer pending.
+ * @param pBackendData The opaque backend data.
+ * @param pIoCtx I/O context associated with this request.
+ * @param pvUser Opaque user data passed during a read/write request.
+ * @param rcReq Status code for the completed request.
+ */
+typedef DECLCALLBACKTYPE(int, FNVDXFERCOMPLETED,(void *pBackendData, PVDIOCTX pIoCtx, void *pvUser, int rcReq));
+/** Pointer to FNVDXFERCOMPLETED() */
+typedef FNVDXFERCOMPLETED *PFNVDXFERCOMPLETED;
+
+/** Metadata transfer handle. */
+typedef struct VDMETAXFER *PVDMETAXFER;
+/** Pointer to a metadata transfer handle. */
+typedef PVDMETAXFER *PPVDMETAXFER;
+
+
+/**
+ * Internal I/O interface between the generic VD layer and the backends.
+ *
+ * Per-image. Always passed to backends.
+ */
+typedef struct VDINTERFACEIOINT
+{
+ /**
+ * Common interface header.
+ */
+ VDINTERFACE Core;
+
+ /**
+ * Open callback
+ *
+ * @return VBox status code.
+ * @param pvUser The opaque data passed on container creation.
+ * @param pszLocation Name of the location to open.
+ * @param fOpen Flags for opening the backend.
+ * See RTFILE_O_* \#defines, inventing another set
+ * of open flags is not worth the mapping effort.
+ * @param ppStorage Where to store the storage handle.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnOpen, (void *pvUser, const char *pszLocation,
+ uint32_t fOpen, PPVDIOSTORAGE ppStorage));
+
+ /**
+ * Close callback.
+ *
+ * @return VBox status code.
+ * @param pvUser The opaque data passed on container creation.
+ * @param pStorage The storage handle to close.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnClose, (void *pvUser, PVDIOSTORAGE pStorage));
+
+ /**
+ * Delete callback.
+ *
+ * @return VBox status code.
+ * @param pvUser The opaque data passed on container creation.
+ * @param pcszFilename Name of the file to delete.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnDelete, (void *pvUser, const char *pcszFilename));
+
+ /**
+ * Move callback.
+ *
+ * @return VBox status code.
+ * @param pvUser The opaque data passed on container creation.
+ * @param pcszSrc The path to the source file.
+ * @param pcszDst The path to the destination file.
+ * This file will be created.
+ * @param fMove A combination of the RTFILEMOVE_* flags.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnMove, (void *pvUser, const char *pcszSrc, const char *pcszDst, unsigned fMove));
+
+ /**
+ * Returns the free space on a disk.
+ *
+ * @return VBox status code.
+ * @param pvUser The opaque data passed on container creation.
+ * @param pcszFilename Name of a file to identify the disk.
+ * @param pcbFreeSpace Where to store the free space of the disk.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnGetFreeSpace, (void *pvUser, const char *pcszFilename, int64_t *pcbFreeSpace));
+
+ /**
+ * Returns the last modification timestamp of a file.
+ *
+ * @return VBox status code.
+ * @param pvUser The opaque data passed on container creation.
+ * @param pcszFilename Name of a file to identify the disk.
+ * @param pModificationTime Where to store the timestamp of the file.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnGetModificationTime, (void *pvUser, const char *pcszFilename, PRTTIMESPEC pModificationTime));
+
+ /**
+ * Returns the size of the opened storage backend.
+ *
+ * @return VBox status code.
+ * @param pvUser The opaque data passed on container creation.
+ * @param pStorage The storage handle to get the size from.
+ * @param pcbSize Where to store the size of the storage backend.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnGetSize, (void *pvUser, PVDIOSTORAGE pStorage,
+ uint64_t *pcbSize));
+
+ /**
+ * Sets the size of the opened storage backend if possible.
+ *
+ * @return VBox status code.
+ * @retval VERR_NOT_SUPPORTED if the backend does not support this operation.
+ * @param pvUser The opaque data passed on container creation.
+ * @param pStorage The storage handle.
+ * @param cbSize The new size of the image.
+ *
+ * @note Depending on the host the underlying storage (backing file, etc.)
+ * might not have all required storage allocated (sparse file) which
+ * can delay writes or fail with a not enough free space error if there
+ * is not enough space on the storage medium when writing to the range for
+ * the first time.
+ * Use VDINTERFACEIOINT::pfnSetAllocationSize to make sure the storage is
+ * really alloacted.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSetSize, (void *pvUser, PVDIOSTORAGE pStorage,
+ uint64_t cbSize));
+
+ /**
+ * Sets the size of the opened storage backend making sure the given size
+ * is really allocated.
+ *
+ * @return VBox status code.
+ * @param pvUser The opaque data passed on container creation.
+ * @param pStorage The storage handle.
+ * @param cbSize The new size of the image.
+ * @param fFlags Flags for controlling the allocation strategy.
+ * Reserved for future use, MBZ.
+ * @param pIfProgress Progress interface (optional).
+ * @param uPercentStart Progress starting point.
+ * @param uPercentSpan Length of operation in percent.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSetAllocationSize, (void *pvUser, PVDIOSTORAGE pStorage,
+ uint64_t cbSize, uint32_t fFlags,
+ PVDINTERFACEPROGRESS pIfProgress,
+ unsigned uPercentStart, unsigned uPercentSpan));
+
+ /**
+ * Initiate a read request for user data.
+ *
+ * @return VBox status code.
+ * @param pvUser The opaque user data passed on container creation.
+ * @param pStorage The storage handle.
+ * @param uOffset The offset to start reading from.
+ * @param pIoCtx I/O context passed in the read/write callback.
+ * @param cbRead How many bytes to read.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnReadUser, (void *pvUser, PVDIOSTORAGE pStorage,
+ uint64_t uOffset, PVDIOCTX pIoCtx,
+ size_t cbRead));
+
+ /**
+ * Initiate a write request for user data.
+ *
+ * @return VBox status code.
+ * @param pvUser The opaque user data passed on container creation.
+ * @param pStorage The storage handle.
+ * @param uOffset The offset to start writing to.
+ * @param pIoCtx I/O context passed in the read/write callback.
+ * @param cbWrite How many bytes to write.
+ * @param pfnCompleted Completion callback.
+ * @param pvCompleteUser Opaque user data passed in the completion callback.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnWriteUser, (void *pvUser, PVDIOSTORAGE pStorage,
+ uint64_t uOffset, PVDIOCTX pIoCtx,
+ size_t cbWrite,
+ PFNVDXFERCOMPLETED pfnComplete,
+ void *pvCompleteUser));
+
+ /**
+ * Reads metadata from storage.
+ * The current I/O context will be halted.
+ *
+ * @returns VBox status code.
+ * @param pvUser The opaque user data passed on container creation.
+ * @param pStorage The storage handle.
+ * @param uOffset Offset to start reading from.
+ * @param pvBuffer Where to store the data.
+ * @param cbBuffer How many bytes to read.
+ * @param pIoCtx The I/O context which triggered the read.
+ * @param ppMetaXfer Where to store the metadata transfer handle on success.
+ * @param pfnCompleted Completion callback.
+ * @param pvCompleteUser Opaque user data passed in the completion callback.
+ *
+ * @note If pIoCtx is NULL the metadata read is handled synchronously
+ * i.e. the call returns only if the data is available in the given
+ * buffer. ppMetaXfer, pfnCompleted and pvCompleteUser are ignored in that case.
+ * Use the synchronous version only when opening/closing the image
+ * or when doing certain operations like resizing, compacting or repairing
+ * the disk.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnReadMeta, (void *pvUser, PVDIOSTORAGE pStorage,
+ uint64_t uOffset, void *pvBuffer,
+ size_t cbBuffer, PVDIOCTX pIoCtx,
+ PPVDMETAXFER ppMetaXfer,
+ PFNVDXFERCOMPLETED pfnComplete,
+ void *pvCompleteUser));
+
+ /**
+ * Writes metadata to storage.
+ *
+ * @returns VBox status code.
+ * @param pvUser The opaque user data passed on container creation.
+ * @param pStorage The storage handle.
+ * @param uOffset Offset to start writing to.
+ * @param pvBuffer Written data.
+ * @param cbBuffer How many bytes to write.
+ * @param pIoCtx The I/O context which triggered the write.
+ * @param pfnCompleted Completion callback.
+ * @param pvCompleteUser Opaque user data passed in the completion callback.
+ *
+ * @sa VDINTERFACEIOINT::pfnReadMeta
+ */
+ DECLR3CALLBACKMEMBER(int, pfnWriteMeta, (void *pvUser, PVDIOSTORAGE pStorage,
+ uint64_t uOffset, const void *pvBuffer,
+ size_t cbBuffer, PVDIOCTX pIoCtx,
+ PFNVDXFERCOMPLETED pfnComplete,
+ void *pvCompleteUser));
+
+ /**
+ * Releases a metadata transfer handle.
+ * The free space can be used for another transfer.
+ *
+ * @returns nothing.
+ * @param pvUser The opaque user data passed on container creation.
+ * @param pMetaXfer The metadata transfer handle to release.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnMetaXferRelease, (void *pvUser, PVDMETAXFER pMetaXfer));
+
+ /**
+ * Initiates a flush request.
+ *
+ * @return VBox status code.
+ * @param pvUser The opaque data passed on container creation.
+ * @param pStorage The storage handle to flush.
+ * @param pIoCtx I/O context which triggered the flush.
+ * @param pfnCompleted Completion callback.
+ * @param pvCompleteUser Opaque user data passed in the completion callback.
+ *
+ * @sa VDINTERFACEIOINT::pfnReadMeta
+ */
+ DECLR3CALLBACKMEMBER(int, pfnFlush, (void *pvUser, PVDIOSTORAGE pStorage,
+ PVDIOCTX pIoCtx,
+ PFNVDXFERCOMPLETED pfnComplete,
+ void *pvCompleteUser));
+
+ /**
+ * Copies a buffer into the I/O context.
+ *
+ * @return Number of bytes copied.
+ * @param pvUser The opaque user data passed on container creation.
+ * @param pIoCtx I/O context to copy the data to.
+ * @param pvBuffer Buffer to copy.
+ * @param cbBuffer Number of bytes to copy.
+ */
+ DECLR3CALLBACKMEMBER(size_t, pfnIoCtxCopyTo, (void *pvUser, PVDIOCTX pIoCtx,
+ const void *pvBuffer, size_t cbBuffer));
+
+ /**
+ * Copies data from the I/O context into a buffer.
+ *
+ * @return Number of bytes copied.
+ * @param pvUser The opaque user data passed on container creation.
+ * @param pIoCtx I/O context to copy the data from.
+ * @param pvBuffer Destination buffer.
+ * @param cbBuffer Number of bytes to copy.
+ */
+ DECLR3CALLBACKMEMBER(size_t, pfnIoCtxCopyFrom, (void *pvUser, PVDIOCTX pIoCtx,
+ void *pvBuffer, size_t cbBuffer));
+
+ /**
+ * Sets the buffer of the given context to a specific byte.
+ *
+ * @return Number of bytes set.
+ * @param pvUser The opaque user data passed on container creation.
+ * @param pIoCtx I/O context to copy the data from.
+ * @param ch The byte to set.
+ * @param cbSet Number of bytes to set.
+ */
+ DECLR3CALLBACKMEMBER(size_t, pfnIoCtxSet, (void *pvUser, PVDIOCTX pIoCtx,
+ int ch, size_t cbSet));
+
+ /**
+ * Creates a segment array from the I/O context data buffer.
+ *
+ * @returns Number of bytes the array describes.
+ * @param pvUser The opaque user data passed on container creation.
+ * @param pIoCtx I/O context to copy the data from.
+ * @param paSeg The uninitialized segment array.
+ * If NULL pcSeg will contain the number of segments needed
+ * to describe the requested amount of data.
+ * @param pcSeg The number of segments the given array has.
+ * This will hold the actual number of entries needed upon return.
+ * @param cbData Number of bytes the new array should describe.
+ */
+ DECLR3CALLBACKMEMBER(size_t, pfnIoCtxSegArrayCreate, (void *pvUser, PVDIOCTX pIoCtx,
+ PRTSGSEG paSeg, unsigned *pcSeg,
+ size_t cbData));
+ /**
+ * Marks the given number of bytes as completed and continues the I/O context.
+ *
+ * @returns nothing.
+ * @param pvUser The opaque user data passed on container creation.
+ * @param pIoCtx The I/O context.
+ * @param rcReq Status code the request completed with.
+ * @param cbCompleted Number of bytes completed.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnIoCtxCompleted, (void *pvUser, PVDIOCTX pIoCtx,
+ int rcReq, size_t cbCompleted));
+
+ /**
+ * Returns whether the given I/O context must be treated synchronously.
+ *
+ * @returns true if the I/O context must be processed synchronously
+ * false otherwise.
+ * @param pvUser The opaque user data passed on container creation.
+ * @param pIoCtx The I/O context.
+ */
+ DECLR3CALLBACKMEMBER(bool, pfnIoCtxIsSynchronous, (void *pvUser, PVDIOCTX pIoCtx));
+
+ /**
+ * Returns whether the user buffer of the I/O context is complete zero
+ * from to current position upto the given number of bytes.
+ *
+ * @returns true if the I/O context user buffer consists solely of zeros
+ * false otherwise.
+ * @param pvUser The opaque user data passed on container creation.
+ * @param pIoCtx The I/O context.
+ * @param cbCheck Number of bytes to check for zeros.
+ * @param fAdvance Flag whether to advance the buffer pointer if true
+ * is returned.
+ */
+ DECLR3CALLBACKMEMBER(bool, pfnIoCtxIsZero, (void *pvUser, PVDIOCTX pIoCtx,
+ size_t cbCheck, bool fAdvance));
+
+ /**
+ * Returns the data unit size, i.e. the smallest size for a transfer.
+ * (similar to the sector size of disks).
+ *
+ * @returns The data unit size.
+ * @param pvUser The opaque user data passed on container creation.
+ * @param pIoCtx The I/O context.
+ */
+ DECLR3CALLBACKMEMBER(size_t, pfnIoCtxGetDataUnitSize, (void *pvUser, PVDIOCTX pIoCtx));
+
+} VDINTERFACEIOINT, *PVDINTERFACEIOINT;
+
+/**
+ * Get internal I/O interface from interface list.
+ *
+ * @return Pointer to the first internal I/O interface in the list.
+ * @param pVDIfs Pointer to the interface list.
+ */
+DECLINLINE(PVDINTERFACEIOINT) VDIfIoIntGet(PVDINTERFACE pVDIfs)
+{
+ PVDINTERFACE pIf = VDInterfaceGet(pVDIfs, VDINTERFACETYPE_IOINT);
+
+ /* Check that the interface descriptor is a progress interface. */
+ AssertMsgReturn( !pIf
+ || ( (pIf->enmInterface == VDINTERFACETYPE_IOINT)
+ && (pIf->cbSize == sizeof(VDINTERFACEIOINT))),
+ ("Not an internal I/O interface"), NULL);
+
+ return (PVDINTERFACEIOINT)pIf;
+}
+
+DECLINLINE(int) vdIfIoIntFileOpen(PVDINTERFACEIOINT pIfIoInt, const char *pszFilename,
+ uint32_t fOpen, PPVDIOSTORAGE ppStorage)
+{
+ return pIfIoInt->pfnOpen(pIfIoInt->Core.pvUser, pszFilename, fOpen, ppStorage);
+}
+
+DECLINLINE(int) vdIfIoIntFileClose(PVDINTERFACEIOINT pIfIoInt, PVDIOSTORAGE pStorage)
+{
+ return pIfIoInt->pfnClose(pIfIoInt->Core.pvUser, pStorage);
+}
+
+DECLINLINE(int) vdIfIoIntFileDelete(PVDINTERFACEIOINT pIfIoInt, const char *pszFilename)
+{
+ return pIfIoInt->pfnDelete(pIfIoInt->Core.pvUser, pszFilename);
+}
+
+DECLINLINE(int) vdIfIoIntFileMove(PVDINTERFACEIOINT pIfIoInt, const char *pszSrc,
+ const char *pszDst, unsigned fMove)
+{
+ return pIfIoInt->pfnMove(pIfIoInt->Core.pvUser, pszSrc, pszDst, fMove);
+}
+
+DECLINLINE(int) vdIfIoIntFileGetFreeSpace(PVDINTERFACEIOINT pIfIoInt, const char *pszFilename,
+ int64_t *pcbFree)
+{
+ return pIfIoInt->pfnGetFreeSpace(pIfIoInt->Core.pvUser, pszFilename, pcbFree);
+}
+
+DECLINLINE(int) vdIfIoIntFileGetModificationTime(PVDINTERFACEIOINT pIfIoInt, const char *pcszFilename,
+ PRTTIMESPEC pModificationTime)
+{
+ return pIfIoInt->pfnGetModificationTime(pIfIoInt->Core.pvUser, pcszFilename,
+ pModificationTime);
+}
+
+DECLINLINE(int) vdIfIoIntFileGetSize(PVDINTERFACEIOINT pIfIoInt, PVDIOSTORAGE pStorage,
+ uint64_t *pcbSize)
+{
+ return pIfIoInt->pfnGetSize(pIfIoInt->Core.pvUser, pStorage, pcbSize);
+}
+
+DECLINLINE(int) vdIfIoIntFileSetSize(PVDINTERFACEIOINT pIfIoInt, PVDIOSTORAGE pStorage,
+ uint64_t cbSize)
+{
+ return pIfIoInt->pfnSetSize(pIfIoInt->Core.pvUser, pStorage, cbSize);
+}
+
+DECLINLINE(int) vdIfIoIntFileSetAllocationSize(PVDINTERFACEIOINT pIfIoInt, PVDIOSTORAGE pStorage,
+ uint64_t cbSize, uint32_t fFlags,
+ PVDINTERFACEPROGRESS pIfProgress,
+ unsigned uPercentStart, unsigned uPercentSpan)
+{
+ return pIfIoInt->pfnSetAllocationSize(pIfIoInt->Core.pvUser, pStorage, cbSize, fFlags,
+ pIfProgress, uPercentStart, uPercentSpan);
+}
+
+DECLINLINE(int) vdIfIoIntFileWriteSync(PVDINTERFACEIOINT pIfIoInt, PVDIOSTORAGE pStorage,
+ uint64_t uOffset, const void *pvBuffer, size_t cbBuffer)
+{
+ return pIfIoInt->pfnWriteMeta(pIfIoInt->Core.pvUser, pStorage,
+ uOffset, pvBuffer, cbBuffer, NULL,
+ NULL, NULL);
+}
+
+DECLINLINE(int) vdIfIoIntFileReadSync(PVDINTERFACEIOINT pIfIoInt, PVDIOSTORAGE pStorage,
+ uint64_t uOffset, void *pvBuffer, size_t cbBuffer)
+{
+ return pIfIoInt->pfnReadMeta(pIfIoInt->Core.pvUser, pStorage,
+ uOffset, pvBuffer, cbBuffer, NULL,
+ NULL, NULL, NULL);
+}
+
+DECLINLINE(int) vdIfIoIntFileFlushSync(PVDINTERFACEIOINT pIfIoInt, PVDIOSTORAGE pStorage)
+{
+ return pIfIoInt->pfnFlush(pIfIoInt->Core.pvUser, pStorage, NULL, NULL, NULL);
+}
+
+DECLINLINE(int) vdIfIoIntFileReadUser(PVDINTERFACEIOINT pIfIoInt, PVDIOSTORAGE pStorage,
+ uint64_t uOffset, PVDIOCTX pIoCtx, size_t cbRead)
+{
+ return pIfIoInt->pfnReadUser(pIfIoInt->Core.pvUser, pStorage,
+ uOffset, pIoCtx, cbRead);
+}
+
+DECLINLINE(int) vdIfIoIntFileWriteUser(PVDINTERFACEIOINT pIfIoInt, PVDIOSTORAGE pStorage,
+ uint64_t uOffset, PVDIOCTX pIoCtx, size_t cbWrite,
+ PFNVDXFERCOMPLETED pfnComplete,
+ void *pvCompleteUser)
+{
+ return pIfIoInt->pfnWriteUser(pIfIoInt->Core.pvUser, pStorage,
+ uOffset, pIoCtx, cbWrite, pfnComplete,
+ pvCompleteUser);
+}
+
+DECLINLINE(int) vdIfIoIntFileReadMeta(PVDINTERFACEIOINT pIfIoInt, PVDIOSTORAGE pStorage,
+ uint64_t uOffset, void *pvBuffer,
+ size_t cbBuffer, PVDIOCTX pIoCtx,
+ PPVDMETAXFER ppMetaXfer,
+ PFNVDXFERCOMPLETED pfnComplete,
+ void *pvCompleteUser)
+{
+ return pIfIoInt->pfnReadMeta(pIfIoInt->Core.pvUser, pStorage,
+ uOffset, pvBuffer, cbBuffer, pIoCtx,
+ ppMetaXfer, pfnComplete, pvCompleteUser);
+}
+
+DECLINLINE(int) vdIfIoIntFileWriteMeta(PVDINTERFACEIOINT pIfIoInt, PVDIOSTORAGE pStorage,
+ uint64_t uOffset, void *pvBuffer,
+ size_t cbBuffer, PVDIOCTX pIoCtx,
+ PFNVDXFERCOMPLETED pfnComplete,
+ void *pvCompleteUser)
+{
+ return pIfIoInt->pfnWriteMeta(pIfIoInt->Core.pvUser, pStorage,
+ uOffset, pvBuffer, cbBuffer, pIoCtx,
+ pfnComplete, pvCompleteUser);
+}
+
+DECLINLINE(void) vdIfIoIntMetaXferRelease(PVDINTERFACEIOINT pIfIoInt, PVDMETAXFER pMetaXfer)
+{
+ pIfIoInt->pfnMetaXferRelease(pIfIoInt->Core.pvUser, pMetaXfer);
+}
+
+DECLINLINE(int) vdIfIoIntFileFlush(PVDINTERFACEIOINT pIfIoInt, PVDIOSTORAGE pStorage,
+ PVDIOCTX pIoCtx, PFNVDXFERCOMPLETED pfnComplete,
+ void *pvCompleteUser)
+{
+ return pIfIoInt->pfnFlush(pIfIoInt->Core.pvUser, pStorage, pIoCtx, pfnComplete,
+ pvCompleteUser);
+}
+
+DECLINLINE(size_t) vdIfIoIntIoCtxCopyTo(PVDINTERFACEIOINT pIfIoInt, PVDIOCTX pIoCtx,
+ const void *pvBuffer, size_t cbBuffer)
+{
+ return pIfIoInt->pfnIoCtxCopyTo(pIfIoInt->Core.pvUser, pIoCtx, pvBuffer, cbBuffer);
+}
+
+DECLINLINE(size_t) vdIfIoIntIoCtxCopyFrom(PVDINTERFACEIOINT pIfIoInt, PVDIOCTX pIoCtx,
+ void *pvBuffer, size_t cbBuffer)
+{
+ return pIfIoInt->pfnIoCtxCopyFrom(pIfIoInt->Core.pvUser, pIoCtx, pvBuffer, cbBuffer);
+}
+
+DECLINLINE(size_t) vdIfIoIntIoCtxSet(PVDINTERFACEIOINT pIfIoInt, PVDIOCTX pIoCtx,
+ int ch, size_t cbSet)
+{
+ return pIfIoInt->pfnIoCtxSet(pIfIoInt->Core.pvUser, pIoCtx, ch, cbSet);
+}
+
+DECLINLINE(size_t) vdIfIoIntIoCtxSegArrayCreate(PVDINTERFACEIOINT pIfIoInt, PVDIOCTX pIoCtx,
+ PRTSGSEG paSeg, unsigned *pcSeg,
+ size_t cbData)
+{
+ return pIfIoInt->pfnIoCtxSegArrayCreate(pIfIoInt->Core.pvUser, pIoCtx, paSeg, pcSeg, cbData);
+}
+
+DECLINLINE(bool) vdIfIoIntIoCtxIsSynchronous(PVDINTERFACEIOINT pIfIoInt, PVDIOCTX pIoCtx)
+{
+ return pIfIoInt->pfnIoCtxIsSynchronous(pIfIoInt->Core.pvUser, pIoCtx);
+}
+
+DECLINLINE(bool) vdIfIoIntIoCtxIsZero(PVDINTERFACEIOINT pIfIoInt, PVDIOCTX pIoCtx,
+ size_t cbCheck, bool fAdvance)
+{
+ return pIfIoInt->pfnIoCtxIsZero(pIfIoInt->Core.pvUser, pIoCtx, cbCheck, fAdvance);
+}
+
+DECLINLINE(size_t) vdIfIoIntIoCtxGetDataUnitSize(PVDINTERFACEIOINT pIfIoInt, PVDIOCTX pIoCtx)
+{
+ return pIfIoInt->pfnIoCtxGetDataUnitSize(pIfIoInt->Core.pvUser, pIoCtx);
+}
+
+/**
+ * Interface for the metadata traverse callback.
+ *
+ * Per-operation interface. Present only for the metadata traverse callback.
+ */
+typedef struct VDINTERFACETRAVERSEMETADATA
+{
+ /**
+ * Common interface header.
+ */
+ VDINTERFACE Core;
+
+ /**
+ * Traverse callback.
+ *
+ * @returns VBox status code.
+ * @param pvUser The opaque data passed for the operation.
+ * @param pvMetadataChunk Pointer to a chunk of the image metadata.
+ * @param cbMetadataChunk Size of the metadata chunk
+ */
+ DECLR3CALLBACKMEMBER(int, pfnMetadataCallback, (void *pvUser, const void *pvMetadataChunk,
+ size_t cbMetadataChunk));
+
+} VDINTERFACETRAVERSEMETADATA, *PVDINTERFACETRAVERSEMETADATA;
+
+
+/**
+ * Get parent state interface from interface list.
+ *
+ * @return Pointer to the first parent state interface in the list.
+ * @param pVDIfs Pointer to the interface list.
+ */
+DECLINLINE(PVDINTERFACETRAVERSEMETADATA) VDIfTraverseMetadataGet(PVDINTERFACE pVDIfs)
+{
+ PVDINTERFACE pIf = VDInterfaceGet(pVDIfs, VDINTERFACETYPE_TRAVERSEMETADATA);
+
+ /* Check that the interface descriptor the correct interface. */
+ AssertMsgReturn( !pIf
+ || ( (pIf->enmInterface == VDINTERFACETYPE_TRAVERSEMETADATA)
+ && (pIf->cbSize == sizeof(VDINTERFACETRAVERSEMETADATA))),
+ ("Not a traverse metadata interface"), NULL);
+
+ return (PVDINTERFACETRAVERSEMETADATA)pIf;
+}
+
+/** @} */
+RT_C_DECLS_END
+
+#endif /* !VBOX_INCLUDED_vd_ifs_internal_h */
diff --git a/include/VBox/vd-ifs.h b/include/VBox/vd-ifs.h
new file mode 100644
index 00000000..87dec3f3
--- /dev/null
+++ b/include/VBox/vd-ifs.h
@@ -0,0 +1,1765 @@
+/** @file
+ * VD Container API - interfaces.
+ */
+
+/*
+ * Copyright (C) 2011-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vd_ifs_h
+#define VBOX_INCLUDED_vd_ifs_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/assert.h>
+#include <iprt/string.h>
+#include <iprt/mem.h>
+#include <iprt/file.h>
+#include <iprt/net.h>
+#include <iprt/sg.h>
+#include <VBox/cdefs.h>
+#include <VBox/types.h>
+#include <VBox/err.h>
+
+RT_C_DECLS_BEGIN
+
+/** @addtogroup grp_vd
+ * @{ */
+
+/** Interface header magic. */
+#define VDINTERFACE_MAGIC UINT32_C(0x19701015)
+
+/**
+ * Supported interface types.
+ */
+typedef enum VDINTERFACETYPE
+{
+ /** First valid interface. */
+ VDINTERFACETYPE_FIRST = 0,
+ /** Interface to pass error message to upper layers. Per-disk. */
+ VDINTERFACETYPE_ERROR = VDINTERFACETYPE_FIRST,
+ /** Interface for I/O operations. Per-image. */
+ VDINTERFACETYPE_IO,
+ /** Interface for progress notification. Per-operation. */
+ VDINTERFACETYPE_PROGRESS,
+ /** Interface for configuration information. Per-image. */
+ VDINTERFACETYPE_CONFIG,
+ /** Interface for TCP network stack. Per-image. */
+ VDINTERFACETYPE_TCPNET,
+ /** Interface for getting parent image state. Per-operation. */
+ VDINTERFACETYPE_PARENTSTATE,
+ /** Interface for synchronizing accesses from several threads. Per-disk. */
+ VDINTERFACETYPE_THREADSYNC,
+ /** Interface for I/O between the generic VBoxHDD code and the backend. Per-image (internal).
+ * This interface is completely internal and must not be used elsewhere. */
+ VDINTERFACETYPE_IOINT,
+ /** Interface to query the use of block ranges on the disk. Per-operation. */
+ VDINTERFACETYPE_QUERYRANGEUSE,
+ /** Interface for the metadata traverse callback. Per-operation. */
+ VDINTERFACETYPE_TRAVERSEMETADATA,
+ /** Interface for crypto operations. Per-filter. */
+ VDINTERFACETYPE_CRYPTO,
+ /** invalid interface. */
+ VDINTERFACETYPE_INVALID
+} VDINTERFACETYPE;
+
+/**
+ * Common structure for all interfaces and at the beginning of all types.
+ */
+typedef struct VDINTERFACE
+{
+ uint32_t u32Magic;
+ /** Human readable interface name. */
+ const char *pszInterfaceName;
+ /** Pointer to the next common interface structure. */
+ struct VDINTERFACE *pNext;
+ /** Interface type. */
+ VDINTERFACETYPE enmInterface;
+ /** Size of the interface. */
+ size_t cbSize;
+ /** Opaque user data which is passed on every call. */
+ void *pvUser;
+} VDINTERFACE;
+/** Pointer to a VDINTERFACE. */
+typedef VDINTERFACE *PVDINTERFACE;
+/** Pointer to a const VDINTERFACE. */
+typedef const VDINTERFACE *PCVDINTERFACE;
+
+/**
+ * Helper functions to handle interface lists.
+ *
+ * @note These interface lists are used consistently to pass per-disk,
+ * per-image and/or per-operation callbacks. Those three purposes are strictly
+ * separate. See the individual interface declarations for what context they
+ * apply to. The caller is responsible for ensuring that the lifetime of the
+ * interface descriptors is appropriate for the category of interface.
+ */
+
+/**
+ * Get a specific interface from a list of interfaces specified by the type.
+ *
+ * @return Pointer to the matching interface or NULL if none was found.
+ * @param pVDIfs Pointer to the VD interface list.
+ * @param enmInterface Interface to search for.
+ */
+DECLINLINE(PVDINTERFACE) VDInterfaceGet(PVDINTERFACE pVDIfs, VDINTERFACETYPE enmInterface)
+{
+ AssertMsgReturn( enmInterface >= VDINTERFACETYPE_FIRST
+ && enmInterface < VDINTERFACETYPE_INVALID,
+ ("enmInterface=%u", enmInterface), NULL);
+
+ while (pVDIfs)
+ {
+ AssertMsgBreak(pVDIfs->u32Magic == VDINTERFACE_MAGIC,
+ ("u32Magic=%#x\n", pVDIfs->u32Magic));
+
+ if (pVDIfs->enmInterface == enmInterface)
+ return pVDIfs;
+ pVDIfs = pVDIfs->pNext;
+ }
+
+ /* No matching interface was found. */
+ return NULL;
+}
+
+/**
+ * Add an interface to a list of interfaces.
+ *
+ * @return VBox status code.
+ * @param pInterface Pointer to an unitialized common interface structure.
+ * @param pszName Name of the interface.
+ * @param enmInterface Type of the interface.
+ * @param pvUser Opaque user data passed on every function call.
+ * @param cbInterface The interface size.
+ * @param ppVDIfs Pointer to the VD interface list.
+ */
+DECLINLINE(int) VDInterfaceAdd(PVDINTERFACE pInterface, const char *pszName, VDINTERFACETYPE enmInterface, void *pvUser,
+ size_t cbInterface, PVDINTERFACE *ppVDIfs)
+{
+ /* Argument checks. */
+ AssertMsgReturn( enmInterface >= VDINTERFACETYPE_FIRST
+ && enmInterface < VDINTERFACETYPE_INVALID,
+ ("enmInterface=%u", enmInterface), VERR_INVALID_PARAMETER);
+
+ AssertPtrReturn(ppVDIfs, VERR_INVALID_PARAMETER);
+
+ /* Fill out interface descriptor. */
+ pInterface->u32Magic = VDINTERFACE_MAGIC;
+ pInterface->cbSize = cbInterface;
+ pInterface->pszInterfaceName = pszName;
+ pInterface->enmInterface = enmInterface;
+ pInterface->pvUser = pvUser;
+ pInterface->pNext = *ppVDIfs;
+
+ /* Remember the new start of the list. */
+ *ppVDIfs = pInterface;
+
+ return VINF_SUCCESS;
+}
+
+/**
+ * Removes an interface from a list of interfaces.
+ *
+ * @return VBox status code
+ * @param pInterface Pointer to an initialized common interface structure to remove.
+ * @param ppVDIfs Pointer to the VD interface list to remove from.
+ */
+DECLINLINE(int) VDInterfaceRemove(PVDINTERFACE pInterface, PVDINTERFACE *ppVDIfs)
+{
+ int rc = VERR_NOT_FOUND;
+
+ /* Argument checks. */
+ AssertPtrReturn(pInterface, VERR_INVALID_PARAMETER);
+ AssertPtrReturn(ppVDIfs, VERR_INVALID_PARAMETER);
+
+ if (*ppVDIfs)
+ {
+ PVDINTERFACE pPrev = NULL;
+ PVDINTERFACE pCurr = *ppVDIfs;
+
+ while ( pCurr
+ && (pCurr != pInterface))
+ {
+ pPrev = pCurr;
+ pCurr = pCurr->pNext;
+ }
+
+ /* First interface */
+ if (!pPrev)
+ {
+ *ppVDIfs = pCurr->pNext;
+ rc = VINF_SUCCESS;
+ }
+ else if (pCurr)
+ {
+ Assert(pPrev->pNext == pCurr);
+ pPrev->pNext = pCurr->pNext;
+ rc = VINF_SUCCESS;
+ }
+ }
+
+ return rc;
+}
+
+/**
+ * Interface to deliver error messages (and also informational messages)
+ * to upper layers.
+ *
+ * Per-disk interface. Optional, but think twice if you want to miss the
+ * opportunity of reporting better human-readable error messages.
+ */
+typedef struct VDINTERFACEERROR
+{
+ /**
+ * Common interface header.
+ */
+ VDINTERFACE Core;
+
+ /**
+ * Error message callback. Must be able to accept special IPRT format
+ * strings.
+ *
+ * @param pvUser The opaque data passed on container creation.
+ * @param rc The VBox error code.
+ * @param SRC_POS Use RT_SRC_POS.
+ * @param pszFormat Error message format string.
+ * @param va Error message arguments.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnError, (void *pvUser, int rc, RT_SRC_POS_DECL,
+ const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(6, 0));
+
+ /**
+ * Informational message callback. May be NULL. Used e.g. in
+ * VDDumpImages(). Must be able to accept special IPRT format strings.
+ *
+ * @return VBox status code.
+ * @param pvUser The opaque data passed on container creation.
+ * @param pszFormat Message format string.
+ * @param va Message arguments.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnMessage, (void *pvUser, const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(2, 0));
+
+} VDINTERFACEERROR, *PVDINTERFACEERROR;
+
+/**
+ * Get error interface from interface list.
+ *
+ * @return Pointer to the first error interface in the list.
+ * @param pVDIfs Pointer to the interface list.
+ */
+DECLINLINE(PVDINTERFACEERROR) VDIfErrorGet(PVDINTERFACE pVDIfs)
+{
+ PVDINTERFACE pIf = VDInterfaceGet(pVDIfs, VDINTERFACETYPE_ERROR);
+
+ /* Check that the interface descriptor is a progress interface. */
+ AssertMsgReturn( !pIf
+ || ( (pIf->enmInterface == VDINTERFACETYPE_ERROR)
+ && (pIf->cbSize == sizeof(VDINTERFACEERROR))),
+ ("Not an error interface\n"), NULL);
+
+ return (PVDINTERFACEERROR)pIf;
+}
+
+/**
+ * Signal an error to the frontend.
+ *
+ * @returns VBox status code.
+ * @param pIfError The error interface.
+ * @param rc The status code.
+ * @param SRC_POS The position in the source code.
+ * @param pszFormat The format string to pass.
+ * @param ... Arguments to the format string.
+ */
+DECLINLINE(int) RT_IPRT_FORMAT_ATTR(6, 7) vdIfError(PVDINTERFACEERROR pIfError, int rc, RT_SRC_POS_DECL,
+ const char *pszFormat, ...)
+{
+ va_list va;
+ va_start(va, pszFormat);
+ if (pIfError)
+ pIfError->pfnError(pIfError->Core.pvUser, rc, RT_SRC_POS_ARGS, pszFormat, va);
+ va_end(va);
+
+#if defined(LOG_ENABLED) && defined(Log)
+ va_start(va, pszFormat);
+ Log(("vdIfError: %N\n", pszFormat, &va));
+ va_end(va);
+#endif
+ return rc;
+}
+
+/**
+ * Signal an informational message to the frontend.
+ *
+ * @returns VBox status code.
+ * @param pIfError The error interface.
+ * @param pszFormat The format string to pass.
+ * @param ... Arguments to the format string.
+ */
+DECLINLINE(int) RT_IPRT_FORMAT_ATTR(2, 3) vdIfErrorMessage(PVDINTERFACEERROR pIfError, const char *pszFormat, ...)
+{
+ int rc = VINF_SUCCESS;
+ va_list va;
+ va_start(va, pszFormat);
+ if (pIfError && pIfError->pfnMessage)
+ rc = pIfError->pfnMessage(pIfError->Core.pvUser, pszFormat, va);
+ va_end(va);
+
+#if defined(LOG_ENABLED) && defined(Log)
+ va_start(va, pszFormat);
+ Log(("vdIfErrorMessage: %N\n", pszFormat, &va));
+ va_end(va);
+#endif
+ return rc;
+}
+
+/**
+ * Completion callback which is called by the interface owner
+ * to inform the backend that a task finished.
+ *
+ * @return VBox status code.
+ * @param pvUser Opaque user data which is passed on request submission.
+ * @param rcReq Status code of the completed request.
+ */
+typedef DECLCALLBACKTYPE(int, FNVDCOMPLETED,(void *pvUser, int rcReq));
+/** Pointer to FNVDCOMPLETED() */
+typedef FNVDCOMPLETED *PFNVDCOMPLETED;
+
+/**
+ * Support interface for I/O
+ *
+ * Per-image. Optional as input.
+ */
+typedef struct VDINTERFACEIO
+{
+ /**
+ * Common interface header.
+ */
+ VDINTERFACE Core;
+
+ /**
+ * Open callback
+ *
+ * @return VBox status code.
+ * @param pvUser The opaque data passed on container creation.
+ * @param pszLocation Name of the location to open.
+ * @param fOpen Flags for opening the backend.
+ * See RTFILE_O_* \#defines, inventing another set
+ * of open flags is not worth the mapping effort.
+ * @param pfnCompleted The callback which is called whenever a task
+ * completed. The backend has to pass the user data
+ * of the request initiator (ie the one who calls
+ * VDAsyncRead or VDAsyncWrite) in pvCompletion
+ * if this is NULL.
+ * @param ppvStorage Where to store the opaque storage handle.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnOpen, (void *pvUser, const char *pszLocation,
+ uint32_t fOpen,
+ PFNVDCOMPLETED pfnCompleted,
+ void **ppvStorage));
+
+ /**
+ * Close callback.
+ *
+ * @return VBox status code.
+ * @param pvUser The opaque data passed on container creation.
+ * @param pvStorage The opaque storage handle to close.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnClose, (void *pvUser, void *pvStorage));
+
+ /**
+ * Delete callback.
+ *
+ * @return VBox status code.
+ * @param pvUser The opaque data passed on container creation.
+ * @param pcszFilename Name of the file to delete.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnDelete, (void *pvUser, const char *pcszFilename));
+
+ /**
+ * Move callback.
+ *
+ * @return VBox status code.
+ * @param pvUser The opaque data passed on container creation.
+ * @param pcszSrc The path to the source file.
+ * @param pcszDst The path to the destination file.
+ * This file will be created.
+ * @param fMove A combination of the RTFILEMOVE_* flags.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnMove, (void *pvUser, const char *pcszSrc, const char *pcszDst, unsigned fMove));
+
+ /**
+ * Returns the free space on a disk.
+ *
+ * @return VBox status code.
+ * @param pvUser The opaque data passed on container creation.
+ * @param pcszFilename Name of a file to identify the disk.
+ * @param pcbFreeSpace Where to store the free space of the disk.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnGetFreeSpace, (void *pvUser, const char *pcszFilename, int64_t *pcbFreeSpace));
+
+ /**
+ * Returns the last modification timestamp of a file.
+ *
+ * @return VBox status code.
+ * @param pvUser The opaque data passed on container creation.
+ * @param pcszFilename Name of a file to identify the disk.
+ * @param pModificationTime Where to store the timestamp of the file.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnGetModificationTime, (void *pvUser, const char *pcszFilename, PRTTIMESPEC pModificationTime));
+
+ /**
+ * Returns the size of the opened storage backend.
+ *
+ * @return VBox status code.
+ * @param pvUser The opaque data passed on container creation.
+ * @param pvStorage The opaque storage handle to get the size from.
+ * @param pcb Where to store the size of the storage backend.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnGetSize, (void *pvUser, void *pvStorage, uint64_t *pcb));
+
+ /**
+ * Sets the size of the opened storage backend if possible.
+ *
+ * @return VBox status code.
+ * @retval VERR_NOT_SUPPORTED if the backend does not support this operation.
+ * @param pvUser The opaque data passed on container creation.
+ * @param pvStorage The opaque storage handle to set the size for.
+ * @param cb The new size of the image.
+ *
+ * @note Depending on the host the underlying storage (backing file, etc.)
+ * might not have all required storage allocated (sparse file) which
+ * can delay writes or fail with a not enough free space error if there
+ * is not enough space on the storage medium when writing to the range for
+ * the first time.
+ * Use VDINTERFACEIO::pfnSetAllocationSize to make sure the storage is
+ * really alloacted.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSetSize, (void *pvUser, void *pvStorage, uint64_t cb));
+
+ /**
+ * Sets the size of the opened storage backend making sure the given size
+ * is really allocated.
+ *
+ * @return VBox status code.
+ * @retval VERR_NOT_SUPPORTED if the implementer of the interface doesn't support
+ * this method.
+ * @param pvUser The opaque data passed on container creation.
+ * @param pvStorage The storage handle.
+ * @param cbSize The new size of the image.
+ * @param fFlags Flags for controlling the allocation strategy.
+ * Reserved for future use, MBZ.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSetAllocationSize, (void *pvUser, void *pvStorage,
+ uint64_t cbSize, uint32_t fFlags));
+
+ /**
+ * Synchronous write callback.
+ *
+ * @return VBox status code.
+ * @param pvUser The opaque data passed on container creation.
+ * @param pvStorage The storage handle to use.
+ * @param off The offset to start from.
+ * @param pvBuf Pointer to the bits need to be written.
+ * @param cbToWrite How many bytes to write.
+ * @param pcbWritten Where to store how many bytes were actually written.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnWriteSync, (void *pvUser, void *pvStorage, uint64_t off,
+ const void *pvBuf, size_t cbToWrite, size_t *pcbWritten));
+
+ /**
+ * Synchronous read callback.
+ *
+ * @return VBox status code.
+ * @param pvUser The opaque data passed on container creation.
+ * @param pvStorage The storage handle to use.
+ * @param off The offset to start from.
+ * @param pvBuf Where to store the read bits.
+ * @param cbToRead How many bytes to read.
+ * @param pcbRead Where to store how many bytes were actually read.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnReadSync, (void *pvUser, void *pvStorage, uint64_t off,
+ void *pvBuf, size_t cbToRead, size_t *pcbRead));
+
+ /**
+ * Flush data to the storage backend.
+ *
+ * @return VBox status code.
+ * @param pvUser The opaque data passed on container creation.
+ * @param pvStorage The storage handle to flush.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnFlushSync, (void *pvUser, void *pvStorage));
+
+ /**
+ * Initiate an asynchronous read request.
+ *
+ * @return VBox status code.
+ * @param pvUser The opaque user data passed on container creation.
+ * @param pvStorage The storage handle.
+ * @param uOffset The offset to start reading from.
+ * @param paSegments Scatter gather list to store the data in.
+ * @param cSegments Number of segments in the list.
+ * @param cbRead How many bytes to read.
+ * @param pvCompletion The opaque user data which is returned upon completion.
+ * @param ppTask Where to store the opaque task handle.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnReadAsync, (void *pvUser, void *pvStorage, uint64_t uOffset,
+ PCRTSGSEG paSegments, size_t cSegments,
+ size_t cbRead, void *pvCompletion,
+ void **ppTask));
+
+ /**
+ * Initiate an asynchronous write request.
+ *
+ * @return VBox status code.
+ * @param pvUser The opaque user data passed on conatiner creation.
+ * @param pvStorage The storage handle.
+ * @param uOffset The offset to start writing to.
+ * @param paSegments Scatter gather list of the data to write
+ * @param cSegments Number of segments in the list.
+ * @param cbWrite How many bytes to write.
+ * @param pvCompletion The opaque user data which is returned upon completion.
+ * @param ppTask Where to store the opaque task handle.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnWriteAsync, (void *pvUser, void *pvStorage, uint64_t uOffset,
+ PCRTSGSEG paSegments, size_t cSegments,
+ size_t cbWrite, void *pvCompletion,
+ void **ppTask));
+
+ /**
+ * Initiates an async flush request.
+ *
+ * @return VBox status code.
+ * @param pvUser The opaque data passed on container creation.
+ * @param pvStorage The storage handle to flush.
+ * @param pvCompletion The opaque user data which is returned upon completion.
+ * @param ppTask Where to store the opaque task handle.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnFlushAsync, (void *pvUser, void *pvStorage,
+ void *pvCompletion, void **ppTask));
+
+} VDINTERFACEIO, *PVDINTERFACEIO;
+
+/**
+ * Get I/O interface from interface list.
+ *
+ * @return Pointer to the first I/O interface in the list.
+ * @param pVDIfs Pointer to the interface list.
+ */
+DECLINLINE(PVDINTERFACEIO) VDIfIoGet(PVDINTERFACE pVDIfs)
+{
+ PVDINTERFACE pIf = VDInterfaceGet(pVDIfs, VDINTERFACETYPE_IO);
+
+ /* Check that the interface descriptor is a progress interface. */
+ AssertMsgReturn( !pIf
+ || ( (pIf->enmInterface == VDINTERFACETYPE_IO)
+ && (pIf->cbSize == sizeof(VDINTERFACEIO))),
+ ("Not a I/O interface"), NULL);
+
+ return (PVDINTERFACEIO)pIf;
+}
+
+DECLINLINE(int) vdIfIoFileOpen(PVDINTERFACEIO pIfIo, const char *pszFilename,
+ uint32_t fOpen, PFNVDCOMPLETED pfnCompleted,
+ void **ppStorage)
+{
+ return pIfIo->pfnOpen(pIfIo->Core.pvUser, pszFilename, fOpen, pfnCompleted, ppStorage);
+}
+
+DECLINLINE(int) vdIfIoFileClose(PVDINTERFACEIO pIfIo, void *pStorage)
+{
+ return pIfIo->pfnClose(pIfIo->Core.pvUser, pStorage);
+}
+
+DECLINLINE(int) vdIfIoFileDelete(PVDINTERFACEIO pIfIo, const char *pszFilename)
+{
+ return pIfIo->pfnDelete(pIfIo->Core.pvUser, pszFilename);
+}
+
+DECLINLINE(int) vdIfIoFileMove(PVDINTERFACEIO pIfIo, const char *pszSrc,
+ const char *pszDst, unsigned fMove)
+{
+ return pIfIo->pfnMove(pIfIo->Core.pvUser, pszSrc, pszDst, fMove);
+}
+
+DECLINLINE(int) vdIfIoFileGetFreeSpace(PVDINTERFACEIO pIfIo, const char *pszFilename,
+ int64_t *pcbFree)
+{
+ return pIfIo->pfnGetFreeSpace(pIfIo->Core.pvUser, pszFilename, pcbFree);
+}
+
+DECLINLINE(int) vdIfIoFileGetModificationTime(PVDINTERFACEIO pIfIo, const char *pcszFilename,
+ PRTTIMESPEC pModificationTime)
+{
+ return pIfIo->pfnGetModificationTime(pIfIo->Core.pvUser, pcszFilename,
+ pModificationTime);
+}
+
+DECLINLINE(int) vdIfIoFileGetSize(PVDINTERFACEIO pIfIo, void *pStorage,
+ uint64_t *pcbSize)
+{
+ return pIfIo->pfnGetSize(pIfIo->Core.pvUser, pStorage, pcbSize);
+}
+
+DECLINLINE(int) vdIfIoFileSetSize(PVDINTERFACEIO pIfIo, void *pStorage,
+ uint64_t cbSize)
+{
+ return pIfIo->pfnSetSize(pIfIo->Core.pvUser, pStorage, cbSize);
+}
+
+DECLINLINE(int) vdIfIoFileWriteSync(PVDINTERFACEIO pIfIo, void *pStorage,
+ uint64_t uOffset, const void *pvBuffer, size_t cbBuffer,
+ size_t *pcbWritten)
+{
+ return pIfIo->pfnWriteSync(pIfIo->Core.pvUser, pStorage, uOffset,
+ pvBuffer, cbBuffer, pcbWritten);
+}
+
+DECLINLINE(int) vdIfIoFileReadSync(PVDINTERFACEIO pIfIo, void *pStorage,
+ uint64_t uOffset, void *pvBuffer, size_t cbBuffer,
+ size_t *pcbRead)
+{
+ return pIfIo->pfnReadSync(pIfIo->Core.pvUser, pStorage, uOffset,
+ pvBuffer, cbBuffer, pcbRead);
+}
+
+DECLINLINE(int) vdIfIoFileFlushSync(PVDINTERFACEIO pIfIo, void *pStorage)
+{
+ return pIfIo->pfnFlushSync(pIfIo->Core.pvUser, pStorage);
+}
+
+/**
+ * Create a VFS stream handle around a VD I/O interface.
+ *
+ * The I/O interface will not be closed or free by the stream, the caller will
+ * do so after it is done with the stream and has released the instances of the
+ * I/O stream object returned by this API.
+ *
+ * @return VBox status code.
+ * @param pVDIfsIo Pointer to the VD I/O interface.
+ * @param pvStorage The storage argument to pass to the interface
+ * methods.
+ * @param fFlags RTFILE_O_XXX, access mask requied.
+ * @param phVfsIos Where to return the VFS I/O stream handle on
+ * success.
+ */
+VBOXDDU_DECL(int) VDIfCreateVfsStream(PVDINTERFACEIO pVDIfsIo, void *pvStorage, uint32_t fFlags, PRTVFSIOSTREAM phVfsIos);
+
+struct VDINTERFACEIOINT;
+
+/**
+ * Create a VFS file handle around a VD I/O interface.
+ *
+ * The I/O interface will not be closed or free by the VFS file, the caller will
+ * do so after it is done with the VFS file and has released the instances of
+ * the VFS object returned by this API.
+ *
+ * @return VBox status code.
+ * @param pVDIfs Pointer to the VD I/O interface. If NULL, then @a
+ * pVDIfsInt must be specified.
+ * @param pVDIfsInt Pointer to the internal VD I/O interface. If NULL,
+ * then @ pVDIfs must be specified.
+ * @param pvStorage The storage argument to pass to the interface
+ * methods.
+ * @param fFlags RTFILE_O_XXX, access mask requied.
+ * @param phVfsFile Where to return the VFS file handle on success.
+ */
+VBOXDDU_DECL(int) VDIfCreateVfsFile(PVDINTERFACEIO pVDIfs, struct VDINTERFACEIOINT *pVDIfsInt, void *pvStorage,
+ uint32_t fFlags, PRTVFSFILE phVfsFile);
+
+/**
+ * Creates an VD I/O interface wrapper around an IPRT VFS I/O stream.
+ *
+ * @return VBox status code.
+ * @param hVfsIos The IPRT VFS I/O stream handle. The handle will be
+ * retained by the returned I/O interface (released on
+ * close or destruction).
+ * @param fAccessMode The access mode (RTFILE_O_ACCESS_MASK) to accept.
+ * @param ppIoIf Where to return the pointer to the VD I/O interface.
+ * This must be passed to VDIfDestroyFromVfsStream().
+ */
+VBOXDDU_DECL(int) VDIfCreateFromVfsStream(RTVFSIOSTREAM hVfsIos, uint32_t fAccessMode, PVDINTERFACEIO *ppIoIf);
+
+/**
+ * Destroys the VD I/O interface returned by VDIfCreateFromVfsStream.
+ *
+ * @returns VBox status code.
+ * @param pIoIf The I/O interface pointer returned by
+ * VDIfCreateFromVfsStream. NULL will be quietly
+ * ignored.
+ */
+VBOXDDU_DECL(int) VDIfDestroyFromVfsStream(PVDINTERFACEIO pIoIf);
+
+
+/**
+ * Callback which provides progress information about a currently running
+ * lengthy operation.
+ *
+ * @return VBox status code.
+ * @param pvUser The opaque user data associated with this interface.
+ * @param uPercentage Completion percentage.
+ */
+typedef DECLCALLBACKTYPE(int, FNVDPROGRESS,(void *pvUser, unsigned uPercentage));
+/** Pointer to FNVDPROGRESS() */
+typedef FNVDPROGRESS *PFNVDPROGRESS;
+
+/**
+ * Progress notification interface
+ *
+ * Per-operation. Optional.
+ */
+typedef struct VDINTERFACEPROGRESS
+{
+ /**
+ * Common interface header.
+ */
+ VDINTERFACE Core;
+
+ /**
+ * Progress notification callbacks.
+ */
+ PFNVDPROGRESS pfnProgress;
+
+} VDINTERFACEPROGRESS, *PVDINTERFACEPROGRESS;
+
+/** Initializer for VDINTERFACEPROGRESS. */
+#define VDINTERFACEPROGRESS_INITALIZER(a_pfnProgress) { { 0, NULL, NULL, VDINTERFACETYPE_INVALID, 0, NULL }, a_pfnProgress }
+
+/**
+ * Get progress interface from interface list.
+ *
+ * @return Pointer to the first progress interface in the list.
+ * @param pVDIfs Pointer to the interface list.
+ */
+DECLINLINE(PVDINTERFACEPROGRESS) VDIfProgressGet(PVDINTERFACE pVDIfs)
+{
+ PVDINTERFACE pIf = VDInterfaceGet(pVDIfs, VDINTERFACETYPE_PROGRESS);
+
+ /* Check that the interface descriptor is a progress interface. */
+ AssertMsgReturn( !pIf
+ || ( (pIf->enmInterface == VDINTERFACETYPE_PROGRESS)
+ && (pIf->cbSize == sizeof(VDINTERFACEPROGRESS))),
+ ("Not a progress interface"), NULL);
+
+ return (PVDINTERFACEPROGRESS)pIf;
+}
+
+/**
+ * Signal new progress information to the frontend.
+ *
+ * @returns VBox status code.
+ * @param pIfProgress The progress interface.
+ * @param uPercentage Completion percentage.
+ */
+DECLINLINE(int) vdIfProgress(PVDINTERFACEPROGRESS pIfProgress, unsigned uPercentage)
+{
+ if (pIfProgress)
+ return pIfProgress->pfnProgress(pIfProgress->Core.pvUser, uPercentage);
+ return VINF_SUCCESS;
+}
+
+/**
+ * Configuration information interface
+ *
+ * Per-image. Optional for most backends, but mandatory for images which do
+ * not operate on files (including standard block or character devices).
+ */
+typedef struct VDINTERFACECONFIG
+{
+ /**
+ * Common interface header.
+ */
+ VDINTERFACE Core;
+
+ /**
+ * Validates that the keys are within a set of valid names.
+ *
+ * @return true if all key names are found in pszzAllowed.
+ * @return false if not.
+ * @param pvUser The opaque user data associated with this interface.
+ * @param pszzValid List of valid key names separated by '\\0' and ending with
+ * a double '\\0'.
+ */
+ DECLR3CALLBACKMEMBER(bool, pfnAreKeysValid, (void *pvUser, const char *pszzValid));
+
+ /**
+ * Retrieves the length of the string value associated with a key (including
+ * the terminator, for compatibility with CFGMR3QuerySize).
+ *
+ * @return VBox status code.
+ * VERR_CFGM_VALUE_NOT_FOUND means that the key is not known.
+ * @param pvUser The opaque user data associated with this interface.
+ * @param pszName Name of the key to query.
+ * @param pcbValue Where to store the value length. Non-NULL.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnQuerySize, (void *pvUser, const char *pszName, size_t *pcbValue));
+
+ /**
+ * Query the string value associated with a key.
+ *
+ * @return VBox status code.
+ * VERR_CFGM_VALUE_NOT_FOUND means that the key is not known.
+ * VERR_CFGM_NOT_ENOUGH_SPACE means that the buffer is not big enough.
+ * @param pvUser The opaque user data associated with this interface.
+ * @param pszName Name of the key to query.
+ * @param pszValue Pointer to buffer where to store value.
+ * @param cchValue Length of value buffer.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnQuery, (void *pvUser, const char *pszName, char *pszValue, size_t cchValue));
+
+ /**
+ * Query the bytes value associated with a key.
+ *
+ * @return VBox status code.
+ * VERR_CFGM_VALUE_NOT_FOUND means that the key is not known.
+ * VERR_CFGM_NOT_ENOUGH_SPACE means that the buffer is not big enough.
+ * @param pvUser The opaque user data associated with this interface.
+ * @param pszName Name of the key to query.
+ * @param ppvData Pointer to buffer where to store the data.
+ * @param cbData Length of data buffer.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnQueryBytes, (void *pvUser, const char *pszName, void *ppvData, size_t cbData));
+
+ /**
+ * Set a named property to a specified string value, optionally creating if it doesn't exist.
+ *
+ * @return VBox status code.
+ * VERR_CFGM_VALUE_NOT_FOUND means that the key is not known and fCreate flag was not set.
+ * @param pvUser The opaque user data associated with this interface.
+ * @param fCreate Create property if it doesn't exist (if property exists, it is not an error)
+ * @param pszName Name of the key to query.
+ * @param pszValue String value to set the name property to.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnUpdate, (void *pvUser, bool fCreate,
+ const char *pszName, const char *pszValue));
+
+} VDINTERFACECONFIG, *PVDINTERFACECONFIG;
+
+/**
+ * Get configuration information interface from interface list.
+ *
+ * @return Pointer to the first configuration information interface in the list.
+ * @param pVDIfs Pointer to the interface list.
+ */
+DECLINLINE(PVDINTERFACECONFIG) VDIfConfigGet(PVDINTERFACE pVDIfs)
+{
+ PVDINTERFACE pIf = VDInterfaceGet(pVDIfs, VDINTERFACETYPE_CONFIG);
+
+ /* Check that the interface descriptor is a progress interface. */
+ AssertMsgReturn( !pIf
+ || ( (pIf->enmInterface == VDINTERFACETYPE_CONFIG)
+ && (pIf->cbSize == sizeof(VDINTERFACECONFIG))),
+ ("Not a config interface"), NULL);
+
+ return (PVDINTERFACECONFIG)pIf;
+}
+
+/**
+ * Query configuration, validates that the keys are within a set of valid names.
+ *
+ * @return true if all key names are found in pszzAllowed.
+ * @return false if not.
+ * @param pCfgIf Pointer to configuration callback table.
+ * @param pszzValid List of valid names separated by '\\0' and ending with
+ * a double '\\0'.
+ */
+DECLINLINE(bool) VDCFGAreKeysValid(PVDINTERFACECONFIG pCfgIf, const char *pszzValid)
+{
+ return pCfgIf->pfnAreKeysValid(pCfgIf->Core.pvUser, pszzValid);
+}
+
+/**
+ * Checks whether a given key is existing.
+ *
+ * @return true if the key exists.
+ * @return false if the key does not exist.
+ * @param pCfgIf Pointer to configuration callback table.
+ * @param pszName Name of the key.
+ */
+DECLINLINE(bool) VDCFGIsKeyExisting(PVDINTERFACECONFIG pCfgIf, const char *pszName)
+{
+ size_t cb = 0;
+ int rc = pCfgIf->pfnQuerySize(pCfgIf->Core.pvUser, pszName, &cb);
+ return rc == VERR_CFGM_VALUE_NOT_FOUND ? false : true;
+}
+
+/**
+ * Query configuration, unsigned 64-bit integer value with default.
+ *
+ * @return VBox status code.
+ * @param pCfgIf Pointer to configuration callback table.
+ * @param pszName Name of an integer value
+ * @param pu64 Where to store the value. Set to default on failure.
+ * @param u64Def The default value.
+ */
+DECLINLINE(int) VDCFGQueryU64Def(PVDINTERFACECONFIG pCfgIf,
+ const char *pszName, uint64_t *pu64,
+ uint64_t u64Def)
+{
+ char aszBuf[32];
+ int rc = pCfgIf->pfnQuery(pCfgIf->Core.pvUser, pszName, aszBuf, sizeof(aszBuf));
+ if (RT_SUCCESS(rc))
+ {
+ rc = RTStrToUInt64Full(aszBuf, 0, pu64);
+ }
+ else if (rc == VERR_CFGM_VALUE_NOT_FOUND)
+ {
+ rc = VINF_SUCCESS;
+ *pu64 = u64Def;
+ }
+ return rc;
+}
+
+/**
+ * Query configuration, unsigned 64-bit integer value.
+ *
+ * @return VBox status code.
+ * @param pCfgIf Pointer to configuration callback table.
+ * @param pszName Name of an integer value
+ * @param pu64 Where to store the value.
+ */
+DECLINLINE(int) VDCFGQueryU64(PVDINTERFACECONFIG pCfgIf, const char *pszName,
+ uint64_t *pu64)
+{
+ char aszBuf[32];
+ int rc = pCfgIf->pfnQuery(pCfgIf->Core.pvUser, pszName, aszBuf, sizeof(aszBuf));
+ if (RT_SUCCESS(rc))
+ {
+ rc = RTStrToUInt64Full(aszBuf, 0, pu64);
+ }
+
+ return rc;
+}
+
+/**
+ * Query configuration, unsigned 32-bit integer value with default.
+ *
+ * @return VBox status code.
+ * @param pCfgIf Pointer to configuration callback table.
+ * @param pszName Name of an integer value
+ * @param pu32 Where to store the value. Set to default on failure.
+ * @param u32Def The default value.
+ */
+DECLINLINE(int) VDCFGQueryU32Def(PVDINTERFACECONFIG pCfgIf,
+ const char *pszName, uint32_t *pu32,
+ uint32_t u32Def)
+{
+ uint64_t u64;
+ int rc = VDCFGQueryU64Def(pCfgIf, pszName, &u64, u32Def);
+ if (RT_SUCCESS(rc))
+ {
+ if (!(u64 & UINT64_C(0xffffffff00000000)))
+ *pu32 = (uint32_t)u64;
+ else
+ rc = VERR_CFGM_INTEGER_TOO_BIG;
+ }
+ return rc;
+}
+
+/**
+ * Query configuration, bool value with default.
+ *
+ * @return VBox status code.
+ * @param pCfgIf Pointer to configuration callback table.
+ * @param pszName Name of an integer value
+ * @param pf Where to store the value. Set to default on failure.
+ * @param fDef The default value.
+ */
+DECLINLINE(int) VDCFGQueryBoolDef(PVDINTERFACECONFIG pCfgIf,
+ const char *pszName, bool *pf,
+ bool fDef)
+{
+ uint64_t u64;
+ int rc = VDCFGQueryU64Def(pCfgIf, pszName, &u64, fDef);
+ if (RT_SUCCESS(rc))
+ *pf = u64 ? true : false;
+ return rc;
+}
+
+/**
+ * Query configuration, bool value.
+ *
+ * @return VBox status code.
+ * @param pCfgIf Pointer to configuration callback table.
+ * @param pszName Name of an integer value
+ * @param pf Where to store the value.
+ */
+DECLINLINE(int) VDCFGQueryBool(PVDINTERFACECONFIG pCfgIf, const char *pszName,
+ bool *pf)
+{
+ uint64_t u64;
+ int rc = VDCFGQueryU64(pCfgIf, pszName, &u64);
+ if (RT_SUCCESS(rc))
+ *pf = u64 ? true : false;
+ return rc;
+}
+
+/**
+ * Query configuration, dynamically allocated (RTMemAlloc) zero terminated
+ * character value.
+ *
+ * @return VBox status code.
+ * @param pCfgIf Pointer to configuration callback table.
+ * @param pszName Name of an zero terminated character value
+ * @param ppszString Where to store the string pointer. Not set on failure.
+ * Free this using RTMemFree().
+ */
+DECLINLINE(int) VDCFGQueryStringAlloc(PVDINTERFACECONFIG pCfgIf,
+ const char *pszName, char **ppszString)
+{
+ size_t cb;
+ int rc = pCfgIf->pfnQuerySize(pCfgIf->Core.pvUser, pszName, &cb);
+ if (RT_SUCCESS(rc))
+ {
+ char *pszString = (char *)RTMemAlloc(cb);
+ if (pszString)
+ {
+ rc = pCfgIf->pfnQuery(pCfgIf->Core.pvUser, pszName, pszString, cb);
+ if (RT_SUCCESS(rc))
+ *ppszString = pszString;
+ else
+ RTMemFree(pszString);
+ }
+ else
+ rc = VERR_NO_MEMORY;
+ }
+ return rc;
+}
+
+/**
+ * Query configuration, dynamically allocated (RTMemAlloc) zero terminated
+ * character value with default.
+ *
+ * @return VBox status code.
+ * @param pCfgIf Pointer to configuration callback table.
+ * @param pszName Name of an zero terminated character value
+ * @param ppszString Where to store the string pointer. Not set on failure.
+ * Free this using RTMemFree().
+ * @param pszDef The default value.
+ */
+DECLINLINE(int) VDCFGQueryStringAllocDef(PVDINTERFACECONFIG pCfgIf,
+ const char *pszName,
+ char **ppszString,
+ const char *pszDef)
+{
+ size_t cb;
+ int rc = pCfgIf->pfnQuerySize(pCfgIf->Core.pvUser, pszName, &cb);
+ if (rc == VERR_CFGM_VALUE_NOT_FOUND || rc == VERR_CFGM_NO_PARENT)
+ {
+ cb = strlen(pszDef) + 1;
+ rc = VINF_SUCCESS;
+ }
+ if (RT_SUCCESS(rc))
+ {
+ char *pszString = (char *)RTMemAlloc(cb);
+ if (pszString)
+ {
+ rc = pCfgIf->pfnQuery(pCfgIf->Core.pvUser, pszName, pszString, cb);
+ if (rc == VERR_CFGM_VALUE_NOT_FOUND || rc == VERR_CFGM_NO_PARENT)
+ {
+ memcpy(pszString, pszDef, cb);
+ rc = VINF_SUCCESS;
+ }
+ if (RT_SUCCESS(rc))
+ *ppszString = pszString;
+ else
+ RTMemFree(pszString);
+ }
+ else
+ rc = VERR_NO_MEMORY;
+ }
+ return rc;
+}
+
+/**
+ * Query configuration, dynamically allocated (RTMemAlloc) byte string value.
+ *
+ * @return VBox status code.
+ * @param pCfgIf Pointer to configuration callback table.
+ * @param pszName Name of an zero terminated character value
+ * @param ppvData Where to store the byte string pointer. Not set on failure.
+ * Free this using RTMemFree().
+ * @param pcbData Where to store the byte string length.
+ */
+DECLINLINE(int) VDCFGQueryBytesAlloc(PVDINTERFACECONFIG pCfgIf,
+ const char *pszName, void **ppvData, size_t *pcbData)
+{
+ size_t cb;
+ int rc = pCfgIf->pfnQuerySize(pCfgIf->Core.pvUser, pszName, &cb);
+ if (RT_SUCCESS(rc))
+ {
+ char *pbData;
+ Assert(cb);
+
+ pbData = (char *)RTMemAlloc(cb);
+ if (pbData)
+ {
+ if(pCfgIf->pfnQueryBytes)
+ rc = pCfgIf->pfnQueryBytes(pCfgIf->Core.pvUser, pszName, pbData, cb);
+ else
+ rc = pCfgIf->pfnQuery(pCfgIf->Core.pvUser, pszName, pbData, cb);
+
+ if (RT_SUCCESS(rc))
+ {
+ *ppvData = pbData;
+ /* Exclude terminator if the byte data was obtained using the string query callback. */
+ *pcbData = cb;
+ if (!pCfgIf->pfnQueryBytes)
+ (*pcbData)--;
+ }
+ else
+ RTMemFree(pbData);
+ }
+ else
+ rc = VERR_NO_MEMORY;
+ }
+ return rc;
+}
+
+/**
+ * Set property value to string (optionally create if non-existent).
+ *
+ * @return VBox status code.
+ * @param pCfgIf Pointer to configuration callback table.
+ * @param fCreate Create the property if it doesn't exist
+ * @param pszName Name of property
+ * @param pszValue String value to assign to property
+ */
+DECLINLINE(int) VDCFGUpdate(PVDINTERFACECONFIG pCfgIf, bool fCreate, const char *pszName, const char *pszValue)
+{
+ int rc = pCfgIf->pfnUpdate(pCfgIf->Core.pvUser, fCreate, pszName, pszValue);
+ return rc;
+}
+
+/**
+ * Set property value to Unsigned Int 64-bit (optionally create if non-existent).
+ *
+ * @return VBox status code.
+ * @param pCfgIf Pointer to configuration callback table.
+ * @param fCreate Create the property if it doesn't exist
+ * @param pszName Name of property
+ * @param u64Value 64-bit unsigned value to save with property.
+ */
+
+DECLINLINE(int) VDCFGUpdateU64(PVDINTERFACECONFIG pCfgIf, bool fCreate, const char *pszName, uint64_t u64Value)
+{
+ int rc = 0;
+ char pszValue[21];
+ (void) RTStrPrintf(pszValue, sizeof(pszValue), "%RU64", u64Value);
+ rc = VDCFGUpdate(pCfgIf, fCreate, pszName, pszValue);
+ return rc;
+}
+
+
+
+/** Forward declaration of a VD socket. */
+typedef struct VDSOCKETINT *VDSOCKET;
+/** Pointer to a VD socket. */
+typedef VDSOCKET *PVDSOCKET;
+/** Nil socket handle. */
+#define NIL_VDSOCKET ((VDSOCKET)0)
+
+/** Connect flag to indicate that the backend wants to use the extended
+ * socket I/O multiplexing call. This might not be supported on all configurations
+ * (internal networking and iSCSI)
+ * and the backend needs to take appropriate action.
+ */
+#define VD_INTERFACETCPNET_CONNECT_EXTENDED_SELECT RT_BIT_32(0)
+
+/** @name Select events
+ * @{ */
+/** Readable without blocking. */
+#define VD_INTERFACETCPNET_EVT_READ RT_BIT_32(0)
+/** Writable without blocking. */
+#define VD_INTERFACETCPNET_EVT_WRITE RT_BIT_32(1)
+/** Error condition, hangup, exception or similar. */
+#define VD_INTERFACETCPNET_EVT_ERROR RT_BIT_32(2)
+/** Hint for the select that getting interrupted while waiting is more likely.
+ * The interface implementation can optimize the waiting strategy based on this.
+ * It is assumed that it is more likely to get one of the above socket events
+ * instead of being interrupted if the flag is not set. */
+#define VD_INTERFACETCPNET_HINT_INTERRUPT RT_BIT_32(3)
+/** Mask of the valid bits. */
+#define VD_INTERFACETCPNET_EVT_VALID_MASK UINT32_C(0x0000000f)
+/** @} */
+
+/**
+ * TCP network stack interface
+ *
+ * Per-image. Mandatory for backends which have the VD_CAP_TCPNET bit set.
+ */
+typedef struct VDINTERFACETCPNET
+{
+ /**
+ * Common interface header.
+ */
+ VDINTERFACE Core;
+
+ /**
+ * Creates a socket. The socket is not connected if this succeeds.
+ *
+ * @return iprt status code.
+ * @retval VERR_NOT_SUPPORTED if the combination of flags is not supported.
+ * @param fFlags Combination of the VD_INTERFACETCPNET_CONNECT_* \#defines.
+ * @param phVdSock Where to store the handle.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSocketCreate, (uint32_t fFlags, PVDSOCKET phVdSock));
+
+ /**
+ * Destroys the socket.
+ *
+ * @return iprt status code.
+ * @param hVdSock Socket handle (/ pointer).
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSocketDestroy, (VDSOCKET hVdSock));
+
+ /**
+ * Connect as a client to a TCP port.
+ *
+ * @return iprt status code.
+ * @param hVdSock Socket handle (/ pointer)..
+ * @param pszAddress The address to connect to.
+ * @param uPort The port to connect to.
+ * @param cMillies Number of milliseconds to wait for the connect attempt to complete.
+ * Use RT_INDEFINITE_WAIT to wait for ever.
+ * Use RT_SOCKETCONNECT_DEFAULT_WAIT to wait for the default time
+ * configured on the running system.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnClientConnect, (VDSOCKET hVdSock, const char *pszAddress, uint32_t uPort,
+ RTMSINTERVAL cMillies));
+
+ /**
+ * Close a TCP connection.
+ *
+ * @return iprt status code.
+ * @param hVdSock Socket handle (/ pointer).
+ */
+ DECLR3CALLBACKMEMBER(int, pfnClientClose, (VDSOCKET hVdSock));
+
+ /**
+ * Returns whether the socket is currently connected to the client.
+ *
+ * @returns true if the socket is connected.
+ * false otherwise.
+ * @param hVdSock Socket handle (/ pointer).
+ */
+ DECLR3CALLBACKMEMBER(bool, pfnIsClientConnected, (VDSOCKET hVdSock));
+
+ /**
+ * Socket I/O multiplexing.
+ * Checks if the socket is ready for reading.
+ *
+ * @return iprt status code.
+ * @param hVdSock Socket handle (/ pointer).
+ * @param cMillies Number of milliseconds to wait for the socket.
+ * Use RT_INDEFINITE_WAIT to wait for ever.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSelectOne, (VDSOCKET hVdSock, RTMSINTERVAL cMillies));
+
+ /**
+ * Receive data from a socket.
+ *
+ * @return iprt status code.
+ * @param hVdSock Socket handle (/ pointer).
+ * @param pvBuffer Where to put the data we read.
+ * @param cbBuffer Read buffer size.
+ * @param pcbRead Number of bytes read.
+ * If NULL the entire buffer will be filled upon successful return.
+ * If not NULL a partial read can be done successfully.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnRead, (VDSOCKET hVdSock, void *pvBuffer, size_t cbBuffer, size_t *pcbRead));
+
+ /**
+ * Send data to a socket.
+ *
+ * @return iprt status code.
+ * @param hVdSock Socket handle (/ pointer).
+ * @param pvBuffer Buffer to write data to socket.
+ * @param cbBuffer How much to write.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnWrite, (VDSOCKET hVdSock, const void *pvBuffer, size_t cbBuffer));
+
+ /**
+ * Send data from scatter/gather buffer to a socket.
+ *
+ * @return iprt status code.
+ * @param hVdSock Socket handle (/ pointer).
+ * @param pSgBuf Scatter/gather buffer to write data to socket.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSgWrite, (VDSOCKET hVdSock, PCRTSGBUF pSgBuf));
+
+ /**
+ * Receive data from a socket - not blocking.
+ *
+ * @return iprt status code.
+ * @param hVdSock Socket handle (/ pointer).
+ * @param pvBuffer Where to put the data we read.
+ * @param cbBuffer Read buffer size.
+ * @param pcbRead Number of bytes read.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnReadNB, (VDSOCKET hVdSock, void *pvBuffer, size_t cbBuffer, size_t *pcbRead));
+
+ /**
+ * Send data to a socket - not blocking.
+ *
+ * @return iprt status code.
+ * @param hVdSock Socket handle (/ pointer).
+ * @param pvBuffer Buffer to write data to socket.
+ * @param cbBuffer How much to write.
+ * @param pcbWritten Number of bytes written.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnWriteNB, (VDSOCKET hVdSock, const void *pvBuffer, size_t cbBuffer, size_t *pcbWritten));
+
+ /**
+ * Send data from scatter/gather buffer to a socket - not blocking.
+ *
+ * @return iprt status code.
+ * @param hVdSock Socket handle (/ pointer).
+ * @param pSgBuf Scatter/gather buffer to write data to socket.
+ * @param pcbWritten Number of bytes written.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSgWriteNB, (VDSOCKET hVdSock, PRTSGBUF pSgBuf, size_t *pcbWritten));
+
+ /**
+ * Flush socket write buffers.
+ *
+ * @return iprt status code.
+ * @param hVdSock Socket handle (/ pointer).
+ */
+ DECLR3CALLBACKMEMBER(int, pfnFlush, (VDSOCKET hVdSock));
+
+ /**
+ * Enables or disables delaying sends to coalesce packets.
+ *
+ * @return iprt status code.
+ * @param hVdSock Socket handle (/ pointer).
+ * @param fEnable When set to true enables coalescing.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSetSendCoalescing, (VDSOCKET hVdSock, bool fEnable));
+
+ /**
+ * Gets the address of the local side.
+ *
+ * @return iprt status code.
+ * @param hVdSock Socket handle (/ pointer).
+ * @param pAddr Where to store the local address on success.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnGetLocalAddress, (VDSOCKET hVdSock, PRTNETADDR pAddr));
+
+ /**
+ * Gets the address of the other party.
+ *
+ * @return iprt status code.
+ * @param hVdSock Socket handle (/ pointer).
+ * @param pAddr Where to store the peer address on success.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnGetPeerAddress, (VDSOCKET hVdSock, PRTNETADDR pAddr));
+
+ /**
+ * Socket I/O multiplexing - extended version which can be woken up.
+ * Checks if the socket is ready for reading or writing.
+ *
+ * @return iprt status code.
+ * @retval VERR_INTERRUPTED if the thread was woken up by a pfnPoke call.
+ * @param hVdSock VD Socket handle(/pointer).
+ * @param fEvents Mask of events to wait for.
+ * @param pfEvents Where to store the received events.
+ * @param cMillies Number of milliseconds to wait for the socket.
+ * Use RT_INDEFINITE_WAIT to wait for ever.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSelectOneEx, (VDSOCKET hVdSock, uint32_t fEvents,
+ uint32_t *pfEvents, RTMSINTERVAL cMillies));
+
+ /**
+ * Wakes up the thread waiting in pfnSelectOneEx.
+ *
+ * @return iprt status code.
+ * @param hVdSock VD Socket handle(/pointer).
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPoke, (VDSOCKET hVdSock));
+
+} VDINTERFACETCPNET, *PVDINTERFACETCPNET;
+
+/**
+ * Get TCP network stack interface from interface list.
+ *
+ * @return Pointer to the first TCP network stack interface in the list.
+ * @param pVDIfs Pointer to the interface list.
+ */
+DECLINLINE(PVDINTERFACETCPNET) VDIfTcpNetGet(PVDINTERFACE pVDIfs)
+{
+ PVDINTERFACE pIf = VDInterfaceGet(pVDIfs, VDINTERFACETYPE_TCPNET);
+
+ /* Check that the interface descriptor is a progress interface. */
+ AssertMsgReturn( !pIf
+ || ( (pIf->enmInterface == VDINTERFACETYPE_TCPNET)
+ && (pIf->cbSize == sizeof(VDINTERFACETCPNET))),
+ ("Not a TCP net interface"), NULL);
+
+ return (PVDINTERFACETCPNET)pIf;
+}
+
+
+/**
+ * Interface to synchronize concurrent accesses by several threads.
+ *
+ * @note The scope of this interface is to manage concurrent accesses after
+ * the HDD container has been created, and they must stop before destroying the
+ * container. Opening or closing images is covered by the synchronization, but
+ * that does not mean it is safe to close images while a thread executes
+ * #VDMerge or #VDCopy operating on these images. Making them safe would require
+ * the lock to be held during the entire operation, which prevents other
+ * concurrent acitivities.
+ *
+ * @note Right now this is kept as simple as possible, and does not even
+ * attempt to provide enough information to allow e.g. concurrent write
+ * accesses to different areas of the disk. The reason is that it is very
+ * difficult to predict which area of a disk is affected by a write,
+ * especially when different image formats are mixed. Maybe later a more
+ * sophisticated interface will be provided which has the necessary information
+ * about worst case affected areas.
+ *
+ * Per-disk interface. Optional, needed if the disk is accessed concurrently
+ * by several threads, e.g. when merging diff images while a VM is running.
+ */
+typedef struct VDINTERFACETHREADSYNC
+{
+ /**
+ * Common interface header.
+ */
+ VDINTERFACE Core;
+
+ /**
+ * Start a read operation.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnStartRead, (void *pvUser));
+
+ /**
+ * Finish a read operation.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnFinishRead, (void *pvUser));
+
+ /**
+ * Start a write operation.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnStartWrite, (void *pvUser));
+
+ /**
+ * Finish a write operation.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnFinishWrite, (void *pvUser));
+
+} VDINTERFACETHREADSYNC, *PVDINTERFACETHREADSYNC;
+
+/**
+ * Get thread synchronization interface from interface list.
+ *
+ * @return Pointer to the first thread synchronization interface in the list.
+ * @param pVDIfs Pointer to the interface list.
+ */
+DECLINLINE(PVDINTERFACETHREADSYNC) VDIfThreadSyncGet(PVDINTERFACE pVDIfs)
+{
+ PVDINTERFACE pIf = VDInterfaceGet(pVDIfs, VDINTERFACETYPE_THREADSYNC);
+
+ /* Check that the interface descriptor is a progress interface. */
+ AssertMsgReturn( !pIf
+ || ( (pIf->enmInterface == VDINTERFACETYPE_THREADSYNC)
+ && (pIf->cbSize == sizeof(VDINTERFACETHREADSYNC))),
+ ("Not a thread synchronization interface"), NULL);
+
+ return (PVDINTERFACETHREADSYNC)pIf;
+}
+
+/**
+ * Interface to query usage of disk ranges.
+ *
+ * Per-operation interface. Optional.
+ */
+typedef struct VDINTERFACEQUERYRANGEUSE
+{
+ /**
+ * Common interface header.
+ */
+ VDINTERFACE Core;
+
+ /**
+ * Query use of a disk range.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnQueryRangeUse, (void *pvUser, uint64_t off, uint64_t cb,
+ bool *pfUsed));
+
+} VDINTERFACEQUERYRANGEUSE, *PVDINTERFACEQUERYRANGEUSE;
+
+/**
+ * Get query range use interface from interface list.
+ *
+ * @return Pointer to the first thread synchronization interface in the list.
+ * @param pVDIfs Pointer to the interface list.
+ */
+DECLINLINE(PVDINTERFACEQUERYRANGEUSE) VDIfQueryRangeUseGet(PVDINTERFACE pVDIfs)
+{
+ PVDINTERFACE pIf = VDInterfaceGet(pVDIfs, VDINTERFACETYPE_QUERYRANGEUSE);
+
+ /* Check that the interface descriptor is a progress interface. */
+ AssertMsgReturn( !pIf
+ || ( (pIf->enmInterface == VDINTERFACETYPE_QUERYRANGEUSE)
+ && (pIf->cbSize == sizeof(VDINTERFACEQUERYRANGEUSE))),
+ ("Not a query range use interface"), NULL);
+
+ return (PVDINTERFACEQUERYRANGEUSE)pIf;
+}
+
+DECLINLINE(int) vdIfQueryRangeUse(PVDINTERFACEQUERYRANGEUSE pIfQueryRangeUse, uint64_t off, uint64_t cb,
+ bool *pfUsed)
+{
+ return pIfQueryRangeUse->pfnQueryRangeUse(pIfQueryRangeUse->Core.pvUser, off, cb, pfUsed);
+}
+
+
+/**
+ * Interface used to retrieve keys for cryptographic operations.
+ *
+ * Per-module interface. Optional but cryptographic modules might fail and
+ * return an error if this is not present.
+ */
+typedef struct VDINTERFACECRYPTO
+{
+ /**
+ * Common interface header.
+ */
+ VDINTERFACE Core;
+
+ /**
+ * Retains a key identified by the ID. The caller will only hold a reference
+ * to the key and must not modify the key buffer in any way.
+ *
+ * @returns VBox status code.
+ * @param pvUser The opaque user data associated with this interface.
+ * @param pszId The alias/id for the key to retrieve.
+ * @param ppbKey Where to store the pointer to the key buffer on success.
+ * @param pcbKey Where to store the size of the key in bytes on success.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnKeyRetain, (void *pvUser, const char *pszId, const uint8_t **ppbKey, size_t *pcbKey));
+
+ /**
+ * Releases one reference of the key identified by the given identifier.
+ * The caller must not access the key buffer after calling this operation.
+ *
+ * @returns VBox status code.
+ * @param pvUser The opaque user data associated with this interface.
+ * @param pszId The alias/id for the key to release.
+ *
+ * @note It is advised to release the key whenever it is not used anymore so
+ * the entity storing the key can do anything to make retrieving the key
+ * from memory more difficult like scrambling the memory buffer for
+ * instance.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnKeyRelease, (void *pvUser, const char *pszId));
+
+ /**
+ * Gets a reference to the password identified by the given ID to open a key store supplied through the config interface.
+ *
+ * @returns VBox status code.
+ * @param pvUser The opaque user data associated with this interface.
+ * @param pszId The alias/id for the password to retain.
+ * @param ppszPassword Where to store the password to unlock the key store on success.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnKeyStorePasswordRetain, (void *pvUser, const char *pszId, const char **ppszPassword));
+
+ /**
+ * Releases a reference of the password previously acquired with VDINTERFACECRYPTO::pfnKeyStorePasswordRetain()
+ * identified by the given ID.
+ *
+ * @returns VBox status code.
+ * @param pvUser The opaque user data associated with this interface.
+ * @param pszId The alias/id for the password to release.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnKeyStorePasswordRelease, (void *pvUser, const char *pszId));
+
+ /**
+ * Saves a key store.
+ *
+ * @returns VBox status code.
+ * @param pvUser The opaque user data associated with this interface.
+ * @param pvKeyStore The key store to save.
+ * @param cbKeyStore Size of the key store in bytes.
+ *
+ * @note The format is filter specific and should be treated as binary data.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnKeyStoreSave, (void *pvUser, const void *pvKeyStore, size_t cbKeyStore));
+
+ /**
+ * Returns the parameters after the key store was loaded successfully.
+ *
+ * @returns VBox status code.
+ * @param pvUser The opaque user data associated with this interface.
+ * @param pszCipher The cipher identifier the DEK is used for.
+ * @param pbDek The raw DEK which was contained in the key store loaded by
+ * VDINTERFACECRYPTO::pfnKeyStoreLoad().
+ * @param cbDek The size of the DEK.
+ *
+ * @note The provided pointer to the DEK is only valid until this call returns.
+ * The content might change afterwards with out notice (when scrambling the key
+ * for further protection for example) or might be even freed.
+ *
+ * @note This method is optional and can be NULL if the caller does not require the
+ * parameters.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnKeyStoreReturnParameters, (void *pvUser, const char *pszCipher,
+ const uint8_t *pbDek, size_t cbDek));
+
+} VDINTERFACECRYPTO, *PVDINTERFACECRYPTO;
+
+
+/**
+ * Get error interface from interface list.
+ *
+ * @return Pointer to the first error interface in the list.
+ * @param pVDIfs Pointer to the interface list.
+ */
+DECLINLINE(PVDINTERFACECRYPTO) VDIfCryptoGet(PVDINTERFACE pVDIfs)
+{
+ PVDINTERFACE pIf = VDInterfaceGet(pVDIfs, VDINTERFACETYPE_CRYPTO);
+
+ /* Check that the interface descriptor is a crypto interface. */
+ AssertMsgReturn( !pIf
+ || ( (pIf->enmInterface == VDINTERFACETYPE_CRYPTO)
+ && (pIf->cbSize == sizeof(VDINTERFACECRYPTO))),
+ ("Not an crypto interface\n"), NULL);
+
+ return (PVDINTERFACECRYPTO)pIf;
+}
+
+/**
+ * Retains a key identified by the ID. The caller will only hold a reference
+ * to the key and must not modify the key buffer in any way.
+ *
+ * @returns VBox status code.
+ * @param pIfCrypto Pointer to the crypto interface.
+ * @param pszId The alias/id for the key to retrieve.
+ * @param ppbKey Where to store the pointer to the key buffer on success.
+ * @param pcbKey Where to store the size of the key in bytes on success.
+ */
+DECLINLINE(int) vdIfCryptoKeyRetain(PVDINTERFACECRYPTO pIfCrypto, const char *pszId, const uint8_t **ppbKey, size_t *pcbKey)
+{
+ return pIfCrypto->pfnKeyRetain(pIfCrypto->Core.pvUser, pszId, ppbKey, pcbKey);
+}
+
+/**
+ * Releases one reference of the key identified by the given identifier.
+ * The caller must not access the key buffer after calling this operation.
+ *
+ * @returns VBox status code.
+ * @param pIfCrypto Pointer to the crypto interface.
+ * @param pszId The alias/id for the key to release.
+ *
+ * @note It is advised to release the key whenever it is not used anymore so
+ * the entity storing the key can do anything to make retrieving the key
+ * from memory more difficult like scrambling the memory buffer for
+ * instance.
+ */
+DECLINLINE(int) vdIfCryptoKeyRelease(PVDINTERFACECRYPTO pIfCrypto, const char *pszId)
+{
+ return pIfCrypto->pfnKeyRelease(pIfCrypto->Core.pvUser, pszId);
+}
+
+/**
+ * Gets a reference to the password identified by the given ID to open a key store supplied through the config interface.
+ *
+ * @returns VBox status code.
+ * @param pIfCrypto Pointer to the crypto interface.
+ * @param pszId The alias/id for the password to retain.
+ * @param ppszPassword Where to store the password to unlock the key store on success.
+ */
+DECLINLINE(int) vdIfCryptoKeyStorePasswordRetain(PVDINTERFACECRYPTO pIfCrypto, const char *pszId, const char **ppszPassword)
+{
+ return pIfCrypto->pfnKeyStorePasswordRetain(pIfCrypto->Core.pvUser, pszId, ppszPassword);
+}
+
+/**
+ * Releases a reference of the password previously acquired with VDINTERFACECRYPTO::pfnKeyStorePasswordRetain()
+ * identified by the given ID.
+ *
+ * @returns VBox status code.
+ * @param pIfCrypto Pointer to the crypto interface.
+ * @param pszId The alias/id for the password to release.
+ */
+DECLINLINE(int) vdIfCryptoKeyStorePasswordRelease(PVDINTERFACECRYPTO pIfCrypto, const char *pszId)
+{
+ return pIfCrypto->pfnKeyStorePasswordRelease(pIfCrypto->Core.pvUser, pszId);
+}
+
+/**
+ * Saves a key store.
+ *
+ * @returns VBox status code.
+ * @param pIfCrypto Pointer to the crypto interface.
+ * @param pvKeyStore The key store to save.
+ * @param cbKeyStore Size of the key store in bytes.
+ *
+ * @note The format is filter specific and should be treated as binary data.
+ */
+DECLINLINE(int) vdIfCryptoKeyStoreSave(PVDINTERFACECRYPTO pIfCrypto, const void *pvKeyStore, size_t cbKeyStore)
+{
+ return pIfCrypto->pfnKeyStoreSave(pIfCrypto->Core.pvUser, pvKeyStore, cbKeyStore);
+}
+
+/**
+ * Returns the parameters after the key store was loaded successfully.
+ *
+ * @returns VBox status code.
+ * @param pIfCrypto Pointer to the crypto interface.
+ * @param pszCipher The cipher identifier the DEK is used for.
+ * @param pbDek The raw DEK which was contained in the key store loaded by
+ * VDINTERFACECRYPTO::pfnKeyStoreLoad().
+ * @param cbDek The size of the DEK.
+ *
+ * @note The provided pointer to the DEK is only valid until this call returns.
+ * The content might change afterwards with out notice (when scrambling the key
+ * for further protection for example) or might be even freed.
+ *
+ * @note This method is optional and can be NULL if the caller does not require the
+ * parameters.
+ */
+DECLINLINE(int) vdIfCryptoKeyStoreReturnParameters(PVDINTERFACECRYPTO pIfCrypto, const char *pszCipher,
+ const uint8_t *pbDek, size_t cbDek)
+{
+ if (pIfCrypto->pfnKeyStoreReturnParameters)
+ return pIfCrypto->pfnKeyStoreReturnParameters(pIfCrypto->Core.pvUser, pszCipher, pbDek, cbDek);
+
+ return VINF_SUCCESS;
+}
+
+
+RT_C_DECLS_END
+
+/** @} */
+
+#endif /* !VBOX_INCLUDED_vd_ifs_h */
diff --git a/include/VBox/vd-image-backend.h b/include/VBox/vd-image-backend.h
new file mode 100644
index 00000000..163720c9
--- /dev/null
+++ b/include/VBox/vd-image-backend.h
@@ -0,0 +1,617 @@
+/** @file
+ * VD: Image backend interface.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vd_image_backend_h
+#define VBOX_INCLUDED_vd_image_backend_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/vd.h>
+#include <VBox/vd-common.h>
+#include <VBox/vd-ifs-internal.h>
+
+
+/** @name VBox HDD backend write flags
+ * @{
+ */
+/** Do not allocate a new block on this write. This is just an advisory
+ * flag. The backend may still decide in some circumstances that it wants
+ * to ignore this flag (which may cause extra dynamic image expansion). */
+#define VD_WRITE_NO_ALLOC RT_BIT(1)
+/** @}*/
+
+/** @name VBox HDD backend discard flags
+ * @{
+ */
+/** Don't discard block but mark the given range as unused
+ * (usually by writing 0's to it).
+ * This doesn't require the range to be aligned on a block boundary but
+ * the image size might not be decreased. */
+#define VD_DISCARD_MARK_UNUSED RT_BIT(0)
+/** @}*/
+
+/** @name VBox HDD backend metadata traverse flags
+ * @{
+ */
+/** Include per block metadata while traversing the metadata.
+ * This might take much longer instead of traversing just global metadata. */
+#define VD_TRAVERSE_METADATA_INCLUDE_PER_BLOCK_METADATA RT_BIT(0)
+/** @}*/
+
+/**
+ * Image format backend interface used by VBox HDD Container implementation.
+ */
+typedef struct VDIMAGEBACKEND
+{
+ /** Structure version. VD_IMGBACKEND_VERSION defines the current version. */
+ uint32_t u32Version;
+ /** The name of the backend (constant string). */
+ const char *pszBackendName;
+ /** The capabilities of the backend. */
+ uint64_t uBackendCaps;
+
+ /**
+ * Pointer to a NULL-terminated array, containing the supported
+ * file extensions. Note that some backends do not work on files, so this
+ * pointer may just contain NULL.
+ */
+ PCVDFILEEXTENSION paFileExtensions;
+
+ /**
+ * Pointer to an array of structs describing each supported config key.
+ * Terminated by a NULL config key. Note that some backends do not support
+ * the configuration interface, so this pointer may just contain NULL.
+ * Mandatory if the backend sets VD_CAP_CONFIG.
+ */
+ PCVDCONFIGINFO paConfigInfo;
+
+ /**
+ * Check whether the file is supported by the backend.
+ *
+ * @returns VBox status code.
+ * @param pszFilename Name of the image file.
+ * @param pVDIfsDisk Pointer to the per-disk VD interface list.
+ * @param pVDIfsImage Pointer to the per-image VD interface list.
+ * @param enmDesiredType The desired image type, VDTYPE_INVALID if anything goes.
+ * @param penmType Returns the supported device type on success.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnProbe, (const char *pszFilename, PVDINTERFACE pVDIfsDisk,
+ PVDINTERFACE pVDIfsImage, VDTYPE enmDesiredType, VDTYPE *penmType));
+
+ /**
+ * Open a disk image.
+ *
+ * @returns VBox status code.
+ * @param pszFilename Name of the image file to open. Guaranteed to be available and
+ * unchanged during the lifetime of this image.
+ * @param uOpenFlags Image file open mode, see VD_OPEN_FLAGS_* constants.
+ * @param pVDIfsDisk Pointer to the per-disk VD interface list.
+ * @param pVDIfsImage Pointer to the per-image VD interface list.
+ * @param enmType Requested type of the image.
+ * @param ppBackendData Opaque state data for this image.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnOpen, (const char *pszFilename, unsigned uOpenFlags,
+ PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage,
+ VDTYPE enmType, void **ppBackendData));
+
+ /**
+ * Create a disk image.
+ *
+ * @returns VBox status code.
+ * @param pszFilename Name of the image file to create. Guaranteed to be available and
+ * unchanged during the lifetime of this image.
+ * @param cbSize Image size in bytes.
+ * @param uImageFlags Flags specifying special image features.
+ * @param pszComment Pointer to image comment. NULL is ok.
+ * @param pPCHSGeometry Physical drive geometry CHS <= (16383,16,255).
+ * @param pLCHSGeometry Logical drive geometry CHS <= (1024,255,63).
+ * @param pUuid New UUID of the image. Not NULL.
+ * @param uOpenFlags Image file open mode, see VD_OPEN_FLAGS_* constants.
+ * @param uPercentStart Starting value for progress percentage.
+ * @param uPercentSpan Span for varying progress percentage.
+ * @param pVDIfsDisk Pointer to the per-disk VD interface list.
+ * @param pVDIfsImage Pointer to the per-image VD interface list.
+ * @param pVDIfsOperation Pointer to the per-operation VD interface list.
+ * @param enmType Requested type of the image.
+ * @param ppBackendData Opaque state data for this image.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnCreate, (const char *pszFilename, uint64_t cbSize,
+ unsigned uImageFlags, const char *pszComment,
+ PCVDGEOMETRY pPCHSGeometry,
+ PCVDGEOMETRY pLCHSGeometry,
+ PCRTUUID pUuid, unsigned uOpenFlags,
+ unsigned uPercentStart, unsigned uPercentSpan,
+ PVDINTERFACE pVDIfsDisk,
+ PVDINTERFACE pVDIfsImage,
+ PVDINTERFACE pVDIfsOperation,
+ VDTYPE enmType,
+ void **ppBackendData));
+
+ /**
+ * Rename a disk image. Only needs to work as long as the operating
+ * system's rename file functionality is usable. If an attempt is made to
+ * rename an image to a location on another disk/filesystem, this function
+ * may just fail with an appropriate error code (not changing the opened
+ * image data at all). Also works only on images which actually refer to
+ * regular files. May be NULL.
+ *
+ * @returns VBox status code.
+ * @param pBackendData Opaque state data for this image.
+ * @param pszFilename New name of the image file. Guaranteed to be available and
+ * unchanged during the lifetime of this image.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnRename, (void *pBackendData, const char *pszFilename));
+
+ /**
+ * Close a disk image.
+ *
+ * @returns VBox status code.
+ * @param pBackendData Opaque state data for this image.
+ * @param fDelete If true, delete the image from the host disk.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnClose, (void *pBackendData, bool fDelete));
+
+ /**
+ * Start a read request.
+ *
+ * @returns VBox status code.
+ * @param pBackendData Opaque state data for this image.
+ * @param uOffset The offset of the virtual disk to read from.
+ * @param cbToRead How many bytes to read.
+ * @param pIoCtx I/O context associated with this request.
+ * @param pcbActuallyRead Pointer to returned number of bytes read.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnRead, (void *pBackendData, uint64_t uOffset, size_t cbToRead,
+ PVDIOCTX pIoCtx, size_t *pcbActuallyRead));
+
+ /**
+ * Start a write request.
+ *
+ * @returns VBox status code.
+ * @param pBackendData Opaque state data for this image.
+ * @param uOffset The offset of the virtual disk to write to.
+ * @param cbToWrite How many bytes to write.
+ * @param pIoCtx I/O context associated with this request.
+ * @param pcbWriteProcess Pointer to returned number of bytes that could
+ * be processed. In case the function returned
+ * VERR_VD_BLOCK_FREE this is the number of bytes
+ * that could be written in a full block write,
+ * when prefixed/postfixed by the appropriate
+ * amount of (previously read) padding data.
+ * @param pcbPreRead Pointer to the returned amount of data that must
+ * be prefixed to perform a full block write.
+ * @param pcbPostRead Pointer to the returned amount of data that must
+ * be postfixed to perform a full block write.
+ * @param fWrite Flags which affect write behavior. Combination
+ * of the VD_WRITE_* flags.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnWrite, (void *pBackendData, uint64_t uOffset, size_t cbToWrite,
+ PVDIOCTX pIoCtx,
+ size_t *pcbWriteProcess, size_t *pcbPreRead,
+ size_t *pcbPostRead, unsigned fWrite));
+
+ /**
+ * Flush data to disk.
+ *
+ * @returns VBox status code.
+ * @param pBackendData Opaque state data for this image.
+ * @param pIoCtx I/O context associated with this request.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnFlush, (void *pBackendData, PVDIOCTX pIoCtx));
+
+ /**
+ * Discards the given amount of bytes decreasing the size of the image if possible
+ *
+ * @returns VBox status code.
+ * @retval VERR_VD_DISCARD_ALIGNMENT_NOT_MET if the range doesn't meet the required alignment
+ * for the discard.
+ * @param pBackendData Opaque state data for this image.
+ * @param pIoCtx I/O context associated with this request.
+ * @param uOffset The offset of the first byte to discard.
+ * @param cbDiscard How many bytes to discard.
+ * @param pcbPreAllocated Pointer to the returned amount of bytes that must
+ * be discarded before the range to perform a full
+ * block discard.
+ * @param pcbPostAllocated Pointer to the returned amount of bytes that must
+ * be discarded after the range to perform a full
+ * block discard.
+ * @param pcbActuallyDiscarded Pointer to the returned amount of bytes which
+ * could be actually discarded.
+ * @param ppbmAllocationBitmap Where to store the pointer to the allocation bitmap
+ * if VERR_VD_DISCARD_ALIGNMENT_NOT_MET is returned or NULL
+ * if the allocation bitmap should be returned.
+ * @param fDiscard Flags which affect discard behavior. Combination
+ * of the VD_DISCARD_* flags.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnDiscard, (void *pBackendData, PVDIOCTX pIoCtx,
+ uint64_t uOffset, size_t cbDiscard,
+ size_t *pcbPreAllocated,
+ size_t *pcbPostAllocated,
+ size_t *pcbActuallyDiscarded,
+ void **ppbmAllocationBitmap,
+ unsigned fDiscard));
+
+ /**
+ * Get the version of a disk image.
+ *
+ * @returns version of disk image.
+ * @param pBackendData Opaque state data for this image.
+ */
+ DECLR3CALLBACKMEMBER(unsigned, pfnGetVersion, (void *pBackendData));
+
+ /**
+ * Get the file size of a disk image.
+ *
+ * @returns size of disk image in bytes.
+ * @param pBackendData Opaque state data for this image.
+ */
+ DECLR3CALLBACKMEMBER(uint64_t, pfnGetFileSize, (void *pBackendData));
+
+ /**
+ * Get virtual disk PCHS geometry stored in a disk image.
+ *
+ * @returns VBox status code.
+ * @returns VERR_VD_GEOMETRY_NOT_SET if no geometry present in the image.
+ * @param pBackendData Opaque state data for this image.
+ * @param pPCHSGeometry Where to store the geometry. Not NULL.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnGetPCHSGeometry, (void *pBackendData, PVDGEOMETRY pPCHSGeometry));
+
+ /**
+ * Set virtual disk PCHS geometry stored in a disk image.
+ * Only called if geometry is different than before.
+ *
+ * @returns VBox status code.
+ * @param pBackendData Opaque state data for this image.
+ * @param pPCHSGeometry Where to load the geometry from. Not NULL.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSetPCHSGeometry, (void *pBackendData, PCVDGEOMETRY pPCHSGeometry));
+
+ /**
+ * Get virtual disk LCHS geometry stored in a disk image.
+ *
+ * @returns VBox status code.
+ * @returns VERR_VD_GEOMETRY_NOT_SET if no geometry present in the image.
+ * @param pBackendData Opaque state data for this image.
+ * @param pLCHSGeometry Where to store the geometry. Not NULL.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnGetLCHSGeometry, (void *pBackendData, PVDGEOMETRY pLCHSGeometry));
+
+ /**
+ * Set virtual disk LCHS geometry stored in a disk image.
+ * Only called if geometry is different than before.
+ *
+ * @returns VBox status code.
+ * @param pBackendData Opaque state data for this image.
+ * @param pLCHSGeometry Where to load the geometry from. Not NULL.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSetLCHSGeometry, (void *pBackendData, PCVDGEOMETRY pLCHSGeometry));
+
+ /**
+ * Returns a region list for the disk image if supported, optional.
+ *
+ * @returns VBox status code.
+ * @retval VERR_NOT_SUPPORTED if region lists are not supported for this kind of image.
+ * @param pBackendData Opaque state data for this image.
+ * @param ppRegionList Where to store the pointer to the region list on success.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnQueryRegions, (void *pBackendData, PCVDREGIONLIST *ppRegionList));
+
+ /**
+ * Releases the region list acquired with VDIMAGEBACKEND::pfnQueryRegions() before.
+ *
+ * @returns nothing.
+ * @param pBackendData Opaque state data for this image.
+ * @param pRegionList The region list to release.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnRegionListRelease, (void *pBackendData, PCVDREGIONLIST pRegionList));
+
+ /**
+ * Get the image flags of a disk image.
+ *
+ * @returns image flags of disk image (VD_IMAGE_FLAGS_XXX).
+ * @param pBackendData Opaque state data for this image.
+ */
+ DECLR3CALLBACKMEMBER(unsigned, pfnGetImageFlags, (void *pBackendData));
+
+ /**
+ * Get the open flags of a disk image.
+ *
+ * @returns open flags of disk image (VD_OPEN_FLAGS_XXX).
+ * @param pBackendData Opaque state data for this image.
+ */
+ DECLR3CALLBACKMEMBER(unsigned, pfnGetOpenFlags, (void *pBackendData));
+
+ /**
+ * Set the open flags of a disk image.
+ *
+ * May cause the image to be locked in a different mode or be reopened (which
+ * can fail).
+ *
+ * @returns VBox status code.
+ * @param pBackendData Opaque state data for this image.
+ * @param uOpenFlags New open flags for this image (VD_OPEN_FLAGS_XXX).
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSetOpenFlags, (void *pBackendData, unsigned uOpenFlags));
+
+ /**
+ * Get comment of a disk image.
+ *
+ * @returns VBox status code.
+ * @param pBackendData Opaque state data for this image.
+ * @param pszComment Where to store the comment.
+ * @param cbComment Size of the comment buffer.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnGetComment, (void *pBackendData, char *pszComment, size_t cbComment));
+
+ /**
+ * Set comment of a disk image.
+ *
+ * @returns VBox status code.
+ * @param pBackendData Opaque state data for this image.
+ * @param pszComment Where to get the comment from. NULL resets comment.
+ * The comment is silently truncated if the image format
+ * limit is exceeded.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSetComment, (void *pBackendData, const char *pszComment));
+
+ /**
+ * Get UUID of a disk image.
+ *
+ * @returns VBox status code.
+ * @param pBackendData Opaque state data for this image.
+ * @param pUuid Where to store the image UUID.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnGetUuid, (void *pBackendData, PRTUUID pUuid));
+
+ /**
+ * Set UUID of a disk image.
+ *
+ * @returns VBox status code.
+ * @param pBackendData Opaque state data for this image.
+ * @param pUuid Where to get the image UUID from.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSetUuid, (void *pBackendData, PCRTUUID pUuid));
+
+ /**
+ * Get last modification UUID of a disk image.
+ *
+ * @returns VBox status code.
+ * @param pBackendData Opaque state data for this image.
+ * @param pUuid Where to store the image modification UUID.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnGetModificationUuid, (void *pBackendData, PRTUUID pUuid));
+
+ /**
+ * Set last modification UUID of a disk image.
+ *
+ * @returns VBox status code.
+ * @param pBackendData Opaque state data for this image.
+ * @param pUuid Where to get the image modification UUID from.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSetModificationUuid, (void *pBackendData, PCRTUUID pUuid));
+
+ /**
+ * Get parent UUID of a disk image.
+ *
+ * @returns VBox status code.
+ * @param pBackendData Opaque state data for this image.
+ * @param pUuid Where to store the parent image UUID.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnGetParentUuid, (void *pBackendData, PRTUUID pUuid));
+
+ /**
+ * Set parent UUID of a disk image.
+ *
+ * @returns VBox status code.
+ * @param pBackendData Opaque state data for this image.
+ * @param pUuid Where to get the parent image UUID from.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSetParentUuid, (void *pBackendData, PCRTUUID pUuid));
+
+ /**
+ * Get parent modification UUID of a disk image.
+ *
+ * @returns VBox status code.
+ * @param pBackendData Opaque state data for this image.
+ * @param pUuid Where to store the parent image modification UUID.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnGetParentModificationUuid, (void *pBackendData, PRTUUID pUuid));
+
+ /**
+ * Set parent modification UUID of a disk image.
+ *
+ * @returns VBox status code.
+ * @param pBackendData Opaque state data for this image.
+ * @param pUuid Where to get the parent image modification UUID from.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSetParentModificationUuid, (void *pBackendData, PCRTUUID pUuid));
+
+ /**
+ * Dump information about a disk image.
+ *
+ * @param pBackendData Opaque state data for this image.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnDump, (void *pBackendData));
+
+ /**
+ * Get a time stamp of a disk image. May be NULL.
+ *
+ * @returns VBox status code.
+ * @param pBackendData Opaque state data for this image.
+ * @param pTimestamp Where to store the time stamp.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnGetTimestamp, (void *pBackendData, PRTTIMESPEC pTimestamp));
+
+ /**
+ * Get the parent time stamp of a disk image. May be NULL.
+ *
+ * @returns VBox status code.
+ * @param pBackendData Opaque state data for this image.
+ * @param pTimestamp Where to store the time stamp.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnGetParentTimestamp, (void *pBackendData, PRTTIMESPEC pTimestamp));
+
+ /**
+ * Set the parent time stamp of a disk image. May be NULL.
+ *
+ * @returns VBox status code.
+ * @param pBackendData Opaque state data for this image.
+ * @param pTimestamp Where to get the time stamp from.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSetParentTimestamp, (void *pBackendData, PCRTTIMESPEC pTimestamp));
+
+ /**
+ * Get the relative path to parent image. May be NULL.
+ *
+ * @returns VBox status code.
+ * @param pBackendData Opaque state data for this image.
+ * @param ppszParentFilename Where to store the path.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnGetParentFilename, (void *pBackendData, char **ppszParentFilename));
+
+ /**
+ * Set the relative path to parent image. May be NULL.
+ *
+ * @returns VBox status code.
+ * @param pBackendData Opaque state data for this image.
+ * @param pszParentFilename Where to get the path from.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSetParentFilename, (void *pBackendData, const char *pszParentFilename));
+
+ /** Returns a human readable hard disk location string given a
+ * set of hard disk configuration keys. The returned string is an
+ * equivalent of the full file path for image-based hard disks.
+ * Mandatory for backends with no VD_CAP_FILE and NULL otherwise. */
+ DECLR3CALLBACKMEMBER(int, pfnComposeLocation, (PVDINTERFACE pConfig, char **pszLocation));
+
+ /** Returns a human readable hard disk name string given a
+ * set of hard disk configuration keys. The returned string is an
+ * equivalent of the file name part in the full file path for
+ * image-based hard disks. Mandatory for backends with no
+ * VD_CAP_FILE and NULL otherwise. */
+ DECLR3CALLBACKMEMBER(int, pfnComposeName, (PVDINTERFACE pConfig, char **pszName));
+
+ /**
+ * Compact the image. The pointer may be NULL, indicating that this
+ * isn't supported yet (for file-based images) or not necessary.
+ *
+ * @returns VBox status code.
+ * @returns VERR_NOT_SUPPORTED if this image cannot be compacted yet.
+ * @param pBackendData Opaque state data for this image.
+ * @param uPercentStart Starting value for progress percentage.
+ * @param uPercentSpan Span for varying progress percentage.
+ * @param pVDIfsDisk Pointer to the per-disk VD interface list.
+ * @param pVDIfsImage Pointer to the per-image VD interface list.
+ * @param pVDIfsOperation Pointer to the per-operation VD interface list.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnCompact, (void *pBackendData,
+ unsigned uPercentStart, unsigned uPercentSpan,
+ PVDINTERFACE pVDIfsDisk,
+ PVDINTERFACE pVDIfsImage,
+ PVDINTERFACE pVDIfsOperation));
+
+ /**
+ * Resize the image. The pointer may be NULL, indicating that this
+ * isn't supported yet (for file-based images) or not necessary.
+ *
+ * @returns VBox status code.
+ * @returns VERR_NOT_SUPPORTED if this image cannot be resized yet.
+ * @param pBackendData Opaque state data for this image.
+ * @param cbSize New size of the image.
+ * @param pPCHSGeometry Pointer to the new physical disk geometry <= (16383,16,63). Not NULL.
+ * @param pLCHSGeometry Pointer to the new logical disk geometry <= (x,255,63). Not NULL.
+ * @param uPercentStart Starting value for progress percentage.
+ * @param uPercentSpan Span for varying progress percentage.
+ * @param pVDIfsDisk Pointer to the per-disk VD interface list.
+ * @param pVDIfsImage Pointer to the per-image VD interface list.
+ * @param pVDIfsOperation Pointer to the per-operation VD interface list.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnResize, (void *pBackendData,
+ uint64_t cbSize,
+ PCVDGEOMETRY pPCHSGeometry,
+ PCVDGEOMETRY pLCHSGeometry,
+ unsigned uPercentStart, unsigned uPercentSpan,
+ PVDINTERFACE pVDIfsDisk,
+ PVDINTERFACE pVDIfsImage,
+ PVDINTERFACE pVDIfsOperation));
+
+ /**
+ * Try to repair the given image.
+ *
+ * @returns VBox status code.
+ * @param pszFilename Name of the image file.
+ * @param pVDIfsDisk Pointer to the per-disk VD interface list.
+ * @param pVDIfsImage Pointer to the per-image VD interface list.
+ * @param fFlags Combination of the VD_REPAIR_* flags.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnRepair, (const char *pszFilename, PVDINTERFACE pVDIfsDisk,
+ PVDINTERFACE pVDIfsImage, uint32_t fFlags));
+
+ /**
+ * Traverse all metadata of the opened image.
+ *
+ * @returns VBox status code.
+ * @param pBackendData Opaque state data for this image.
+ * @param fFlags Traverse flags, combination of VD_TRAVERSE_METDATA_* defines.
+ * @param pVDIfsDisk Pointer to the per-disk VD interface list.
+ * @param pVDIfsImage Pointer to the per-image VD interface list.
+ * @param pVDIfsOperation Pointer to the per-operation VD interface list.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnTraverseMetadata, (void *pBackendData, uint32_t fFlags,
+ PVDINTERFACE pVDIfsDisk,
+ PVDINTERFACE pVDIfsImage,
+ PVDINTERFACE pVDIfsOperation));
+
+ /** Initialization safty marker. */
+ uint32_t u32VersionEnd;
+
+} VDIMAGEBACKEND;
+
+/** Pointer to VD backend. */
+typedef VDIMAGEBACKEND *PVDIMAGEBACKEND;
+/** Constant pointer to VD backend. */
+typedef const VDIMAGEBACKEND *PCVDIMAGEBACKEND;
+
+/** The current version of the VDIMAGEBACKEND structure. */
+#define VD_IMGBACKEND_VERSION VD_VERSION_MAKE(0xff01, 3, 0)
+
+/** @copydoc VDIMAGEBACKEND::pfnComposeLocation */
+DECLCALLBACK(int) genericFileComposeLocation(PVDINTERFACE pConfig, char **pszLocation);
+/** @copydoc VDIMAGEBACKEND::pfnComposeName */
+DECLCALLBACK(int) genericFileComposeName(PVDINTERFACE pConfig, char **pszName);
+
+#endif /* !VBOX_INCLUDED_vd_image_backend_h */
diff --git a/include/VBox/vd-plugin.h b/include/VBox/vd-plugin.h
new file mode 100644
index 00000000..f165f1cf
--- /dev/null
+++ b/include/VBox/vd-plugin.h
@@ -0,0 +1,106 @@
+/** @file
+ * VD: Plugin support API.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vd_plugin_h
+#define VBOX_INCLUDED_vd_plugin_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/vd.h>
+#include <VBox/vd-common.h>
+#include <VBox/vd-image-backend.h>
+#include <VBox/vd-cache-backend.h>
+#include <VBox/vd-filter-backend.h>
+
+/**
+ * Backend register callbacks structure.
+ */
+typedef struct VDBACKENDREGISTER
+{
+ /** Interface version.
+ * This is set to VD_BACKENDREG_CB_VERSION. */
+ uint32_t u32Version;
+
+ /**
+ * Registers a new image backend.
+ *
+ * @returns VBox status code.
+ * @param pvUser Opaque user data given in the plugin load callback.
+ * @param pBackend The image backend to register.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnRegisterImage, (void *pvUser, PCVDIMAGEBACKEND pBackend));
+
+ /**
+ * Registers a new cache backend.
+ *
+ * @returns VBox status code.
+ * @param pvUser Opaque user data given in the plugin load callback.
+ * @param pBackend The cache backend to register.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnRegisterCache, (void *pvUser, PCVDCACHEBACKEND pBackend));
+
+ /**
+ * Registers a new filter plugin.
+ * @param pvUser Opaque user data given in the plugin load callback.
+ * @param pBackend The filter backend to register.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnRegisterFilter, (void *pvUser, PCVDFILTERBACKEND pBackend));
+
+} VDBACKENDREGISTER;
+/** Pointer to a backend register callbacks structure. */
+typedef VDBACKENDREGISTER *PVDBACKENDREGISTER;
+
+/** Current version of the VDBACKENDREGISTER structure. */
+#define VD_BACKENDREG_CB_VERSION VD_VERSION_MAKE(0xff00, 1, 0)
+
+/**
+ * Initialization entry point called by the generic VD layer when
+ * a plugin is loaded.
+ *
+ * @returns VBox status code.
+ * @param pvUser Opaque user data passed in the register callbacks.
+ * @param pRegisterCallbacks Pointer to the register callbacks structure.
+ */
+typedef DECLCALLBACKTYPE(int, FNVDPLUGINLOAD,(void *pvUser, PVDBACKENDREGISTER pRegisterCallbacks));
+typedef FNVDPLUGINLOAD *PFNVDPLUGINLOAD;
+#define VD_PLUGIN_LOAD_NAME "VDPluginLoad"
+
+/** The prefix to identify Storage Plugins. */
+#define VD_PLUGIN_PREFIX "VDPlugin"
+/** The size of the prefix excluding the '\\0' terminator. */
+#define VD_PLUGIN_PREFIX_LENGTH (sizeof(VD_PLUGIN_PREFIX)-1)
+
+#endif /* !VBOX_INCLUDED_vd_plugin_h */
diff --git a/include/VBox/vd.h b/include/VBox/vd.h
new file mode 100644
index 00000000..7013846e
--- /dev/null
+++ b/include/VBox/vd.h
@@ -0,0 +1,1847 @@
+/** @file
+ * VBox HDD Container API.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vd_h
+#define VBOX_INCLUDED_vd_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/assert.h>
+#include <iprt/string.h>
+#include <iprt/mem.h>
+#include <iprt/file.h>
+#include <iprt/net.h>
+#include <iprt/sg.h>
+#include <iprt/vfs.h>
+#include <VBox/cdefs.h>
+#include <VBox/types.h>
+#include <VBox/vdmedia.h>
+#include <VBox/vd-ifs.h>
+
+RT_C_DECLS_BEGIN
+
+#ifdef IN_RING0
+# error "There are no VBox HDD Container APIs available in Ring-0 Host Context!"
+#endif
+
+/** @defgroup grp_vd Virtual Disk Container
+ * @{
+ */
+
+/** Current VMDK image version. */
+#define VMDK_IMAGE_VERSION (0x0001)
+
+/** Current VDI image major version. */
+#define VDI_IMAGE_VERSION_MAJOR (0x0001)
+/** Current VDI image minor version. */
+#define VDI_IMAGE_VERSION_MINOR (0x0001)
+/** Current VDI image version. */
+#define VDI_IMAGE_VERSION ((VDI_IMAGE_VERSION_MAJOR << 16) | VDI_IMAGE_VERSION_MINOR)
+
+/** Get VDI major version from combined version. */
+#define VDI_GET_VERSION_MAJOR(uVer) ((uVer) >> 16)
+/** Get VDI minor version from combined version. */
+#define VDI_GET_VERSION_MINOR(uVer) ((uVer) & 0xffff)
+
+/** Placeholder for specifying the last opened image. */
+#define VD_LAST_IMAGE 0xffffffffU
+
+/** Placeholder for VDCopyEx to indicate that the image content is unknown. */
+#define VD_IMAGE_CONTENT_UNKNOWN 0xffffffffU
+
+/** @name VBox HDD container image flags
+ * Same values as MediumVariant API enum.
+ * @{
+ */
+/** No flags. */
+#define VD_IMAGE_FLAGS_NONE (0)
+/** Fixed image. */
+#define VD_IMAGE_FLAGS_FIXED (0x10000)
+/** Diff image. Mutually exclusive with fixed image. */
+#define VD_IMAGE_FLAGS_DIFF (0x20000)
+/** VMDK: Split image into 2GB extents. */
+#define VD_VMDK_IMAGE_FLAGS_SPLIT_2G (0x0001)
+/** VMDK: Raw disk image (giving access to a number of host partitions). */
+#define VD_VMDK_IMAGE_FLAGS_RAWDISK (0x0002)
+/** VMDK: stream optimized image, read only. */
+#define VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED (0x0004)
+/** VMDK: ESX variant, use in addition to other flags. */
+#define VD_VMDK_IMAGE_FLAGS_ESX (0x0008)
+/** VDI: Fill new blocks with zeroes while expanding image file. Only valid
+ * for newly created images, never set for opened existing images. */
+#define VD_VDI_IMAGE_FLAGS_ZERO_EXPAND (0x0100)
+
+/** Mask of valid image flags for VMDK. */
+#define VD_VMDK_IMAGE_FLAGS_MASK ( VD_IMAGE_FLAGS_FIXED | VD_IMAGE_FLAGS_DIFF | VD_IMAGE_FLAGS_NONE \
+ | VD_VMDK_IMAGE_FLAGS_SPLIT_2G | VD_VMDK_IMAGE_FLAGS_RAWDISK \
+ | VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED | VD_VMDK_IMAGE_FLAGS_ESX)
+
+/** Mask of valid image flags for VDI. */
+#define VD_VDI_IMAGE_FLAGS_MASK (VD_IMAGE_FLAGS_FIXED | VD_IMAGE_FLAGS_DIFF | VD_IMAGE_FLAGS_NONE | VD_VDI_IMAGE_FLAGS_ZERO_EXPAND)
+
+/** Mask of all valid image flags for all formats. */
+#define VD_IMAGE_FLAGS_MASK (VD_VMDK_IMAGE_FLAGS_MASK | VD_VDI_IMAGE_FLAGS_MASK)
+
+/** Default image flags. */
+#define VD_IMAGE_FLAGS_DEFAULT (VD_IMAGE_FLAGS_NONE)
+/** @} */
+
+/** @name VD image repair flags
+ * @{
+ */
+/** Don't repair the image but check what needs to be done. */
+#define VD_REPAIR_DRY_RUN RT_BIT_32(0)
+
+/** Mask of all valid repair flags. */
+#define VD_REPAIR_FLAGS_MASK (VD_REPAIR_DRY_RUN)
+/** @} */
+
+/** @name VD image VFS file flags
+ * @{
+ */
+/** Destroy the VD disk container when the VFS file is released. */
+#define VD_VFSFILE_DESTROY_ON_RELEASE RT_BIT_32(0)
+
+/** Mask of all valid repair flags. */
+#define VD_VFSFILE_FLAGS_MASK (VD_VFSFILE_DESTROY_ON_RELEASE)
+/** @} */
+
+/** @name VDISKRAW_XXX - VBox raw disk or partition flags
+ * @{
+ */
+/** No special treatment. */
+#define VDISKRAW_NORMAL 0
+/** Whether this is a raw disk (where the partition information is ignored) or
+ * not. Valid only in the raw disk descriptor. */
+#define VDISKRAW_DISK RT_BIT(0)
+/** Open the corresponding raw disk or partition for reading only, no matter
+ * how the image is created or opened. */
+#define VDISKRAW_READONLY RT_BIT(1)
+/** @} */
+
+/**
+ * Auxiliary type for describing partitions on raw disks.
+ *
+ * The entries must be in ascending order (as far as uStart is concerned), and
+ * must not overlap. Note that this does not correspond 1:1 to partitions, it is
+ * describing the general meaning of contiguous areas on the disk.
+ */
+typedef struct VDISKRAWPARTDESC
+{
+ /** Device to use for this partition/data area. Can be the disk device if
+ * the offset field is set appropriately. If this is NULL, then this
+ * partition will not be accessible to the guest. The size of the data area
+ * must still be set correctly. */
+ char *pszRawDevice;
+ /** Pointer to the partitioning info. NULL means this is a regular data
+ * area on disk, non-NULL denotes data which should be copied to the
+ * partition data overlay. */
+ void *pvPartitionData;
+ /** Offset where the data starts in this device. */
+ uint64_t offStartInDevice;
+ /** Offset where the data starts in the disk. */
+ uint64_t offStartInVDisk;
+ /** Size of the data area. */
+ uint64_t cbData;
+ /** Flags for special treatment, see VDISKRAW_XXX. */
+ uint32_t uFlags;
+} VDISKRAWPARTDESC, *PVDISKRAWPARTDESC;
+
+/**
+ * Auxiliary data structure for difference between GPT and MBR disks.
+ */
+typedef enum VDISKPARTTYPE
+{
+ VDISKPARTTYPE_MBR = 0,
+ VDISKPARTTYPE_GPT
+} VDISKPARTTYPE;
+
+/**
+ * Auxiliary data structure for creating raw disks.
+ */
+typedef struct VDISKRAW
+{
+ /** Signature for structure. Must be 'R', 'A', 'W', '\\0'. Actually a trick
+ * to make logging of the comment string produce sensible results. */
+ char szSignature[4];
+ /** Flags for special treatment, see VDISKRAW_XXX. */
+ uint32_t uFlags;
+ /** Filename for the raw disk. Ignored for partitioned raw disks.
+ * For Linux e.g. /dev/sda, and for Windows e.g. //./PhysicalDisk0. */
+ char *pszRawDisk;
+ /** Partitioning type of the disk */
+ VDISKPARTTYPE enmPartitioningType;
+ /** Number of entries in the partition descriptor array. */
+ uint32_t cPartDescs;
+ /** Pointer to the partition descriptor array. */
+ PVDISKRAWPARTDESC pPartDescs;
+} VDISKRAW, *PVDISKRAW;
+
+
+/** @name VBox HDD container image open mode flags
+ * @{
+ */
+/** Try to open image in read/write exclusive access mode if possible, or in read-only elsewhere. */
+#define VD_OPEN_FLAGS_NORMAL 0
+/** Open image in read-only mode with sharing access with others. */
+#define VD_OPEN_FLAGS_READONLY RT_BIT(0)
+/** Honor zero block writes instead of ignoring them whenever possible.
+ * This is not supported by all formats. It is silently ignored in this case. */
+#define VD_OPEN_FLAGS_HONOR_ZEROES RT_BIT(1)
+/** Honor writes of the same data instead of ignoring whenever possible.
+ * This is handled generically, and is only meaningful for differential image
+ * formats. It is silently ignored otherwise. */
+#define VD_OPEN_FLAGS_HONOR_SAME RT_BIT(2)
+/** Do not perform the base/diff image check on open. This does NOT imply
+ * opening the image as readonly (would break e.g. adding UUIDs to VMDK files
+ * created by other products). Images opened with this flag should only be
+ * used for querying information, and nothing else. */
+#define VD_OPEN_FLAGS_INFO RT_BIT(3)
+/** Open image for asynchronous access. Only available if VD_CAP_ASYNC_IO is
+ * set. VDOpen fails with VERR_NOT_SUPPORTED if this operation is not supported for
+ * this kind of image. */
+#define VD_OPEN_FLAGS_ASYNC_IO RT_BIT(4)
+/** Allow sharing of the image for writable images. May be ignored if the
+ * format backend doesn't support this type of concurrent access. */
+#define VD_OPEN_FLAGS_SHAREABLE RT_BIT(5)
+/** Ask the backend to switch to sequential accesses if possible. Opening
+ * will not fail if it cannot do this, the flag will be simply ignored. */
+#define VD_OPEN_FLAGS_SEQUENTIAL RT_BIT(6)
+/** Allow the discard operation if supported. Only available if VD_CAP_DISCARD
+ * is set. VDOpen fails with VERR_VD_DISCARD_NOT_SUPPORTED if discarding is not
+ * supported. */
+#define VD_OPEN_FLAGS_DISCARD RT_BIT(7)
+/** Ignore all flush requests to workaround certain filesystems which are slow
+ * when writing a lot of cached data to the medium.
+ * Use with extreme care as a host crash can result in completely corrupted and
+ * unusable images.
+ */
+#define VD_OPEN_FLAGS_IGNORE_FLUSH RT_BIT(8)
+/**
+ * Return VINF_VD_NEW_ZEROED_BLOCK for reads from unallocated blocks.
+ * The caller who uses the flag has to make sure that the read doesn't cross
+ * a block boundary. Because the block size can differ between images reading one
+ * sector at a time is the safest solution.
+ */
+#define VD_OPEN_FLAGS_INFORM_ABOUT_ZERO_BLOCKS RT_BIT(9)
+/**
+ * Don't do unnecessary consistency checks when opening the image.
+ * Only valid when the image is opened in readonly because inconsistencies
+ * can lead to corrupted images in read-write mode.
+ */
+#define VD_OPEN_FLAGS_SKIP_CONSISTENCY_CHECKS RT_BIT(10)
+/** Mask of valid flags. */
+#define VD_OPEN_FLAGS_MASK (VD_OPEN_FLAGS_NORMAL | VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_HONOR_ZEROES | VD_OPEN_FLAGS_HONOR_SAME | VD_OPEN_FLAGS_INFO | VD_OPEN_FLAGS_ASYNC_IO | VD_OPEN_FLAGS_SHAREABLE | VD_OPEN_FLAGS_SEQUENTIAL | VD_OPEN_FLAGS_DISCARD | VD_OPEN_FLAGS_IGNORE_FLUSH | VD_OPEN_FLAGS_INFORM_ABOUT_ZERO_BLOCKS | VD_OPEN_FLAGS_SKIP_CONSISTENCY_CHECKS)
+/** @}*/
+
+/** @name VBox HDD container filter flags
+ * @{
+ */
+/** The filter is applied during writes. */
+#define VD_FILTER_FLAGS_WRITE RT_BIT(0)
+/** The filter is applied during reads. */
+#define VD_FILTER_FLAGS_READ RT_BIT(1)
+/** Open the filter in info mode. */
+#define VD_FILTER_FLAGS_INFO RT_BIT(2)
+/** Default set of filter flags. */
+#define VD_FILTER_FLAGS_DEFAULT (VD_FILTER_FLAGS_WRITE | VD_FILTER_FLAGS_READ)
+/** Mask of valid flags. */
+#define VD_FILTER_FLAGS_MASK (VD_FILTER_FLAGS_WRITE | VD_FILTER_FLAGS_READ | VD_FILTER_FLAGS_INFO)
+/** @} */
+
+/**
+ * Helper functions to handle open flags.
+ */
+
+/**
+ * Translate VD_OPEN_FLAGS_* to RTFile open flags.
+ *
+ * @return RTFile open flags.
+ * @param fOpenFlags VD_OPEN_FLAGS_* open flags.
+ * @param fCreate Flag that the file should be created.
+ */
+DECLINLINE(uint32_t) VDOpenFlagsToFileOpenFlags(unsigned fOpenFlags, bool fCreate)
+{
+ uint32_t fOpen;
+ AssertMsg(!(fOpenFlags & VD_OPEN_FLAGS_READONLY) || !fCreate, ("Image can't be opened readonly while being created\n"));
+
+ if (fOpenFlags & VD_OPEN_FLAGS_READONLY)
+ fOpen = RTFILE_O_READ | RTFILE_O_DENY_NONE;
+ else
+ {
+ fOpen = RTFILE_O_READWRITE;
+
+ if (fOpenFlags & VD_OPEN_FLAGS_SHAREABLE)
+ fOpen |= RTFILE_O_DENY_NONE;
+ else
+ fOpen |= RTFILE_O_DENY_WRITE;
+ }
+
+ if (!fCreate)
+ fOpen |= RTFILE_O_OPEN;
+ else
+ fOpen |= RTFILE_O_CREATE | RTFILE_O_NOT_CONTENT_INDEXED;
+
+ return fOpen;
+}
+
+
+/** @name VBox HDD container backend capability flags
+ * @{
+ */
+/** Supports UUIDs as expected by VirtualBox code. */
+#define VD_CAP_UUID RT_BIT(0)
+/** Supports creating fixed size images, allocating all space instantly. */
+#define VD_CAP_CREATE_FIXED RT_BIT(1)
+/** Supports creating dynamically growing images, allocating space on demand. */
+#define VD_CAP_CREATE_DYNAMIC RT_BIT(2)
+/** Supports creating images split in chunks of a bit less than 2GBytes. */
+#define VD_CAP_CREATE_SPLIT_2G RT_BIT(3)
+/** Supports being used as differencing image format backend. */
+#define VD_CAP_DIFF RT_BIT(4)
+/** Supports asynchronous I/O operations for at least some configurations. */
+#define VD_CAP_ASYNC RT_BIT(5)
+/** The backend operates on files. The caller needs to know to handle the
+ * location appropriately. */
+#define VD_CAP_FILE RT_BIT(6)
+/** The backend uses the config interface. The caller needs to know how to
+ * provide the mandatory configuration parts this way. */
+#define VD_CAP_CONFIG RT_BIT(7)
+/** The backend uses the network stack interface. The caller has to provide
+ * the appropriate interface. */
+#define VD_CAP_TCPNET RT_BIT(8)
+/** The backend supports VFS (virtual filesystem) functionality since it uses
+ * VDINTERFACEIO exclusively for all file operations. */
+#define VD_CAP_VFS RT_BIT(9)
+/** The backend supports the discard operation. */
+#define VD_CAP_DISCARD RT_BIT(10)
+/** This is a frequently used backend. */
+#define VD_CAP_PREFERRED RT_BIT(11)
+/** @}*/
+
+/** @name Configuration interface key handling flags.
+ * @{
+ */
+/** Mandatory config key. Not providing a value for this key will cause
+ * the backend to fail. */
+#define VD_CFGKEY_MANDATORY RT_BIT(0)
+/** Expert config key. Not showing it by default in the GUI is is probably
+ * a good idea, as the average user won't understand it easily. */
+#define VD_CFGKEY_EXPERT RT_BIT(1)
+/** Key only need at media creation, not to be retained in registry.
+ * Should not be exposed in the GUI */
+#define VD_CFGKEY_CREATEONLY RT_BIT(2)
+/** @}*/
+
+
+/**
+ * Configuration value type for configuration information interface.
+ */
+typedef enum VDCFGVALUETYPE
+{
+ /** Integer value. */
+ VDCFGVALUETYPE_INTEGER = 1,
+ /** String value. */
+ VDCFGVALUETYPE_STRING,
+ /** Bytestring value. */
+ VDCFGVALUETYPE_BYTES
+} VDCFGVALUETYPE;
+
+
+/**
+ * Structure describing configuration keys required/supported by a backend
+ * through the config interface.
+ */
+typedef struct VDCONFIGINFO
+{
+ /** Key name of the configuration. */
+ const char *pszKey;
+ /** Pointer to default value (descriptor). NULL if no useful default value
+ * can be specified. */
+ const char *pszDefaultValue;
+ /** Value type for this key. */
+ VDCFGVALUETYPE enmValueType;
+ /** Key handling flags (a combination of VD_CFGKEY_* flags). */
+ uint64_t uKeyFlags;
+} VDCONFIGINFO;
+
+/** Pointer to structure describing configuration keys. */
+typedef VDCONFIGINFO *PVDCONFIGINFO;
+
+/** Pointer to const structure describing configuration keys. */
+typedef const VDCONFIGINFO *PCVDCONFIGINFO;
+
+/**
+ * Structure describing a file extension.
+ */
+typedef struct VDFILEEXTENSION
+{
+ /** Pointer to the NULL-terminated string containing the extension. */
+ const char *pszExtension;
+ /** The device type the extension supports. */
+ VDTYPE enmType;
+} VDFILEEXTENSION;
+
+/** Pointer to a structure describing a file extension. */
+typedef VDFILEEXTENSION *PVDFILEEXTENSION;
+
+/** Pointer to a const structure describing a file extension. */
+typedef const VDFILEEXTENSION *PCVDFILEEXTENSION;
+
+/**
+ * Data structure for returning a list of backend capabilities.
+ */
+typedef struct VDBACKENDINFO
+{
+ /** Name of the backend. Must be unique even with case insensitive comparison. */
+ const char *pszBackend;
+ /** Capabilities of the backend (a combination of the VD_CAP_* flags). */
+ uint64_t uBackendCaps;
+ /** Pointer to a NULL-terminated array of strings, containing the supported
+ * file extensions. Note that some backends do not work on files, so this
+ * pointer may just contain NULL. */
+ PCVDFILEEXTENSION paFileExtensions;
+ /** Pointer to an array of structs describing each supported config key.
+ * Terminated by a NULL config key. Note that some backends do not support
+ * the configuration interface, so this pointer may just contain NULL.
+ * Mandatory if the backend sets VD_CAP_CONFIG. */
+ PCVDCONFIGINFO paConfigInfo;
+ /** Returns a human readable hard disk location string given a
+ * set of hard disk configuration keys. The returned string is an
+ * equivalent of the full file path for image-based hard disks.
+ * Mandatory for backends with no VD_CAP_FILE and NULL otherwise. */
+ DECLR3CALLBACKMEMBER(int, pfnComposeLocation, (PVDINTERFACE pConfig, char **pszLocation));
+ /** Returns a human readable hard disk name string given a
+ * set of hard disk configuration keys. The returned string is an
+ * equivalent of the file name part in the full file path for
+ * image-based hard disks. Mandatory for backends with no
+ * VD_CAP_FILE and NULL otherwise. */
+ DECLR3CALLBACKMEMBER(int, pfnComposeName, (PVDINTERFACE pConfig, char **pszName));
+} VDBACKENDINFO, *PVDBACKENDINFO;
+
+/**
+ * Data structure for returning a list of filter capabilities.
+ */
+typedef struct VDFILTERINFO
+{
+ /** Name of the filter. Must be unique even with case insensitive comparison. */
+ const char *pszFilter;
+ /** Pointer to an array of structs describing each supported config key.
+ * Terminated by a NULL config key. Note that some filters do not support
+ * the configuration interface, so this pointer may just contain NULL. */
+ PCVDCONFIGINFO paConfigInfo;
+} VDFILTERINFO, *PVDFILTERINFO;
+
+
+/**
+ * Request completion callback for the async read/write API.
+ */
+typedef DECLCALLBACKTYPE(void, FNVDASYNCTRANSFERCOMPLETE,(void *pvUser1, void *pvUser2, int rcReq));
+/** Pointer to a transfer compelte callback. */
+typedef FNVDASYNCTRANSFERCOMPLETE *PFNVDASYNCTRANSFERCOMPLETE;
+
+/**
+ * VD Container main structure.
+ */
+/* Forward declaration, VDISK structure is visible only inside VD module. */
+struct VDISK;
+typedef struct VDISK VDISK;
+typedef VDISK *PVDISK;
+
+/**
+ * Initializes HDD backends.
+ *
+ * @returns VBox status code.
+ */
+VBOXDDU_DECL(int) VDInit(void);
+
+/**
+ * Destroys loaded HDD backends.
+ *
+ * @returns VBox status code.
+ */
+VBOXDDU_DECL(int) VDShutdown(void);
+
+/**
+ * Loads a single plugin given by filename.
+ *
+ * @returns VBox status code.
+ * @param pszFilename The plugin filename to load.
+ */
+VBOXDDU_DECL(int) VDPluginLoadFromFilename(const char *pszFilename);
+
+/**
+ * Load all plugins from a given path.
+ *
+ * @returns VBox statuse code.
+ * @param pszPath The path to load plugins from.
+ */
+VBOXDDU_DECL(int) VDPluginLoadFromPath(const char *pszPath);
+
+/**
+ * Unloads a single plugin given by filename.
+ *
+ * @returns VBox status code.
+ * @param pszFilename The plugin filename to unload.
+ */
+VBOXDDU_DECL(int) VDPluginUnloadFromFilename(const char *pszFilename);
+
+/**
+ * Unload all plugins from a given path.
+ *
+ * @returns VBox statuse code.
+ * @param pszPath The path to unload plugins from.
+ */
+VBOXDDU_DECL(int) VDPluginUnloadFromPath(const char *pszPath);
+
+/**
+ * Lists all HDD backends and their capabilities in a caller-provided buffer.
+ *
+ * @return VBox status code.
+ * VERR_BUFFER_OVERFLOW if not enough space is passed.
+ * @param cEntriesAlloc Number of list entries available.
+ * @param pEntries Pointer to array for the entries.
+ * @param pcEntriesUsed Number of entries returned.
+ */
+VBOXDDU_DECL(int) VDBackendInfo(unsigned cEntriesAlloc, PVDBACKENDINFO pEntries,
+ unsigned *pcEntriesUsed);
+
+/**
+ * Lists the capabilities of a backend identified by its name.
+ *
+ * @return VBox status code.
+ * @param pszBackend The backend name (case insensitive).
+ * @param pEntry Pointer to an entry.
+ */
+VBOXDDU_DECL(int) VDBackendInfoOne(const char *pszBackend, PVDBACKENDINFO pEntry);
+
+/**
+ * Lists all filters and their capabilities in a caller-provided buffer.
+ *
+ * @return VBox status code.
+ * VERR_BUFFER_OVERFLOW if not enough space is passed.
+ * @param cEntriesAlloc Number of list entries available.
+ * @param pEntries Pointer to array for the entries.
+ * @param pcEntriesUsed Number of entries returned.
+ */
+VBOXDDU_DECL(int) VDFilterInfo(unsigned cEntriesAlloc, PVDFILTERINFO pEntries,
+ unsigned *pcEntriesUsed);
+
+/**
+ * Lists the capabilities of a filter identified by its name.
+ *
+ * @return VBox status code.
+ * @param pszFilter The filter name (case insensitive).
+ * @param pEntry Pointer to an entry.
+ */
+VBOXDDU_DECL(int) VDFilterInfoOne(const char *pszFilter, PVDFILTERINFO pEntry);
+
+/**
+ * Allocates and initializes an empty HDD container.
+ * No image files are opened.
+ *
+ * @return VBox status code.
+ * @param pVDIfsDisk Pointer to the per-disk VD interface list.
+ * @param enmType Type of the image container.
+ * @param ppDisk Where to store the reference to HDD container.
+ */
+VBOXDDU_DECL(int) VDCreate(PVDINTERFACE pVDIfsDisk, VDTYPE enmType, PVDISK *ppDisk);
+
+/**
+ * Destroys HDD container.
+ * If container has opened image files they will be closed.
+ *
+ * @return VBox status code.
+ * @param pDisk Pointer to HDD container.
+ */
+VBOXDDU_DECL(int) VDDestroy(PVDISK pDisk);
+
+/**
+ * Try to get the backend name which can use this image.
+ *
+ * @return VBox status code.
+ * VINF_SUCCESS if a plugin was found.
+ * ppszFormat contains the string which can be used as backend name.
+ * VERR_NOT_SUPPORTED if no backend was found.
+ * @param pVDIfsDisk Pointer to the per-disk VD interface list.
+ * @param pVDIfsImage Pointer to the per-image VD interface list.
+ * @param pszFilename Name of the image file for which the backend is queried.
+ * @param enmDesiredType The desired image type, VDTYPE_INVALID if anything goes.
+ * @param ppszFormat Receives pointer of the UTF-8 string which contains the format name.
+ * The returned pointer must be freed using RTStrFree().
+ * @param penmType Where to store the type of the image.
+ */
+VBOXDDU_DECL(int) VDGetFormat(PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage,
+ const char *pszFilename, VDTYPE enmDesiredType,
+ char **ppszFormat, VDTYPE *penmType);
+
+/**
+ * Opens an image file.
+ *
+ * The first opened image file in HDD container must have a base image type,
+ * others (next opened images) must be differencing or undo images.
+ * Linkage is checked for differencing image to be consistent with the previously opened image.
+ * When another differencing image is opened and the last image was opened in read/write access
+ * mode, then the last image is reopened in read-only with deny write sharing mode. This allows
+ * other processes to use images in read-only mode too.
+ *
+ * Note that the image is opened in read-only mode if a read/write open is not possible.
+ * Use VDIsReadOnly to check open mode.
+ *
+ * @return VBox status code.
+ * @param pDisk Pointer to HDD container.
+ * @param pszBackend Name of the image file backend to use (case insensitive).
+ * @param pszFilename Name of the image file to open.
+ * @param uOpenFlags Image file open mode, see VD_OPEN_FLAGS_* constants.
+ * @param pVDIfsImage Pointer to the per-image VD interface list.
+ */
+VBOXDDU_DECL(int) VDOpen(PVDISK pDisk, const char *pszBackend,
+ const char *pszFilename, unsigned uOpenFlags,
+ PVDINTERFACE pVDIfsImage);
+
+/**
+ * Opens a cache image.
+ *
+ * @return VBox status code.
+ * @param pDisk Pointer to the HDD container which should use the cache image.
+ * @param pszBackend Name of the cache file backend to use (case insensitive).
+ * @param pszFilename Name of the cache image to open.
+ * @param uOpenFlags Image file open mode, see VD_OPEN_FLAGS_* constants.
+ * @param pVDIfsCache Pointer to the per-cache VD interface list.
+ */
+VBOXDDU_DECL(int) VDCacheOpen(PVDISK pDisk, const char *pszBackend,
+ const char *pszFilename, unsigned uOpenFlags,
+ PVDINTERFACE pVDIfsCache);
+
+/**
+ * Adds a filter to the disk.
+ *
+ * @returns VBox status code.
+ * @param pDisk Pointer to the HDD container which should use the filter.
+ * @param pszFilter Name of the filter backend to use (case insensitive).
+ * @param fFlags Flags which apply to the filter, combination of VD_FILTER_FLAGS_*
+ * defines.
+ * @param pVDIfsFilter Pointer to the per-filter VD interface list.
+ */
+VBOXDDU_DECL(int) VDFilterAdd(PVDISK pDisk, const char *pszFilter, uint32_t fFlags,
+ PVDINTERFACE pVDIfsFilter);
+
+/**
+ * Creates and opens a new base image file.
+ *
+ * @return VBox status code.
+ * @param pDisk Pointer to HDD container.
+ * @param pszBackend Name of the image file backend to use (case insensitive).
+ * @param pszFilename Name of the image file to create.
+ * @param cbSize Image size in bytes.
+ * @param uImageFlags Flags specifying special image features.
+ * @param pszComment Pointer to image comment. NULL is ok.
+ * @param pPCHSGeometry Pointer to physical disk geometry <= (16383,16,63). Not NULL.
+ * @param pLCHSGeometry Pointer to logical disk geometry <= (x,255,63). Not NULL.
+ * @param pUuid New UUID of the image. If NULL, a new UUID is created.
+ * @param uOpenFlags Image file open mode, see VD_OPEN_FLAGS_* constants.
+ * @param pVDIfsImage Pointer to the per-image VD interface list.
+ * @param pVDIfsOperation Pointer to the per-operation VD interface list.
+ */
+VBOXDDU_DECL(int) VDCreateBase(PVDISK pDisk, const char *pszBackend,
+ const char *pszFilename, uint64_t cbSize,
+ unsigned uImageFlags, const char *pszComment,
+ PCVDGEOMETRY pPCHSGeometry,
+ PCVDGEOMETRY pLCHSGeometry,
+ PCRTUUID pUuid, unsigned uOpenFlags,
+ PVDINTERFACE pVDIfsImage,
+ PVDINTERFACE pVDIfsOperation);
+
+/**
+ * Creates and opens a new differencing image file in HDD container.
+ * See comments for VDOpen function about differencing images.
+ *
+ * @return VBox status code.
+ * @param pDisk Pointer to HDD container.
+ * @param pszBackend Name of the image file backend to use (case insensitive).
+ * @param pszFilename Name of the differencing image file to create.
+ * @param uImageFlags Flags specifying special image features.
+ * @param pszComment Pointer to image comment. NULL is ok.
+ * @param pUuid New UUID of the image. If NULL, a new UUID is created.
+ * @param pParentUuid New parent UUID of the image. If NULL, the UUID is queried automatically.
+ * @param uOpenFlags Image file open mode, see VD_OPEN_FLAGS_* constants.
+ * @param pVDIfsImage Pointer to the per-image VD interface list.
+ * @param pVDIfsOperation Pointer to the per-operation VD interface list.
+ */
+VBOXDDU_DECL(int) VDCreateDiff(PVDISK pDisk, const char *pszBackend,
+ const char *pszFilename, unsigned uImageFlags,
+ const char *pszComment, PCRTUUID pUuid,
+ PCRTUUID pParentUuid, unsigned uOpenFlags,
+ PVDINTERFACE pVDIfsImage,
+ PVDINTERFACE pVDIfsOperation);
+
+/**
+ * Creates and opens new cache image file in HDD container.
+ *
+ * @return VBox status code.
+ * @param pDisk Name of the cache file backend to use (case insensitive).
+ * @param pszBackend Name of the image file backend to use (case insensitive).
+ * @param pszFilename Name of the differencing cache file to create.
+ * @param cbSize Maximum size of the cache.
+ * @param uImageFlags Flags specifying special cache features.
+ * @param pszComment Pointer to image comment. NULL is ok.
+ * @param pUuid New UUID of the image. If NULL, a new UUID is created.
+ * @param uOpenFlags Image file open mode, see VD_OPEN_FLAGS_* constants.
+ * @param pVDIfsCache Pointer to the per-cache VD interface list.
+ * @param pVDIfsOperation Pointer to the per-operation VD interface list.
+ */
+VBOXDDU_DECL(int) VDCreateCache(PVDISK pDisk, const char *pszBackend,
+ const char *pszFilename, uint64_t cbSize,
+ unsigned uImageFlags, const char *pszComment,
+ PCRTUUID pUuid, unsigned uOpenFlags,
+ PVDINTERFACE pVDIfsCache, PVDINTERFACE pVDIfsOperation);
+
+/**
+ * Merges two images (not necessarily with direct parent/child relationship).
+ * As a side effect the source image and potentially the other images which
+ * are also merged to the destination are deleted from both the disk and the
+ * images in the HDD container.
+ *
+ * @return VBox status code.
+ * @return VERR_VD_IMAGE_NOT_FOUND if image with specified number was not opened.
+ * @param pDisk Pointer to HDD container.
+ * @param nImageFrom Image number to merge from, counts from 0. 0 is always base image of container.
+ * @param nImageTo Image number to merge to, counts from 0. 0 is always base image of container.
+ * @param pVDIfsOperation Pointer to the per-operation VD interface list.
+ */
+VBOXDDU_DECL(int) VDMerge(PVDISK pDisk, unsigned nImageFrom,
+ unsigned nImageTo, PVDINTERFACE pVDIfsOperation);
+
+/**
+ * Copies an image from one HDD container to another - extended version.
+ *
+ * The copy is opened in the target HDD container. It is possible to convert
+ * between different image formats, because the backend for the destination may
+ * be different from the source. If both the source and destination reference
+ * the same HDD container, then the image is moved (by copying/deleting or
+ * renaming) to the new location. The source container is unchanged if the move
+ * operation fails, otherwise the image at the new location is opened in the
+ * same way as the old one was.
+ *
+ * @note The read/write accesses across disks are not synchronized, just the
+ * accesses to each disk. Once there is a use case which requires a defined
+ * read/write behavior in this situation this needs to be extended.
+ *
+ * @return VBox status code.
+ * @return VERR_VD_IMAGE_NOT_FOUND if image with specified number was not opened.
+ *
+ * @param pDiskFrom Pointer to source HDD container.
+ * @param nImage Image number, counts from 0. 0 is always base image
+ * of container.
+ * @param pDiskTo Pointer to destination HDD container.
+ * @param pszBackend Name of the image file backend to use (may be NULL
+ * to use the same as the source, case insensitive).
+ * @param pszFilename New name of the image (may be NULL to specify that
+ * the copy destination is the destination container,
+ * or if pDiskFrom == pDiskTo, i.e. when moving).
+ * @param fMoveByRename If true, attempt to perform a move by renaming (if
+ * successful the new size is ignored).
+ * @param cbSize New image size (0 means leave unchanged).
+ * @param nImageFromSame The number of the last image in the source chain
+ * having the same content as the image in the
+ * destination chain given by nImageToSame or
+ * VD_IMAGE_CONTENT_UNKNOWN to indicate that the
+ * content of both containers is unknown. See the
+ * notes for further information.
+ * @param nImageToSame The number of the last image in the destination
+ * chain having the same content as the image in the
+ * source chain given by nImageFromSame or
+ * VD_IMAGE_CONTENT_UNKNOWN to indicate that the
+ * content of both containers is unknown. See the notes
+ * for further information.
+ * @param uImageFlags Flags specifying special destination image features.
+ * @param pDstUuid New UUID of the destination image. If NULL, a new
+ * UUID is created. This parameter is used if and only
+ * if a true copy is created. In all rename/move cases
+ * or copy to existing image cases the modification
+ * UUIDs are copied over.
+ * @param uOpenFlags Image file open mode, see VD_OPEN_FLAGS_* constants.
+ * Only used if the destination image is created.
+ * @param pVDIfsOperation Pointer to the per-operation VD interface list.
+ * @param pDstVDIfsImage Pointer to the per-image VD interface list, for the
+ * destination image.
+ * @param pDstVDIfsOperation Pointer to the per-operation VD interface list,
+ * for the destination operation.
+ *
+ * @note Using nImageFromSame and nImageToSame can lead to a significant speedup
+ * when copying an image but can also lead to a corrupted copy if used
+ * incorrectly. It is mainly useful when cloning a chain of images and it
+ * is known that the virtual disk content of the two chains is exactly the
+ * same upto a certain image. Example:
+ * Imagine the chain of images which consist of a base and one diff
+ * image. Copying the chain starts with the base image. When copying
+ * the first diff image VDCopy() will read the data from the diff of
+ * the source chain and probably from the base image again in case the
+ * diff doesn't has data for the block. However the block will be
+ * optimized away because VDCopy() reads data from the base image of
+ * the destination chain compares the to and suppresses the write
+ * because the data is unchanged. For a lot of diff images this will be
+ * a huge waste of I/O bandwidth if the diff images contain only few
+ * changes. Because it is known that the base image of the source and
+ * the destination chain have the same content it is enough to check
+ * the diff image for changed data and copy it to the destination diff
+ * image which is achieved with nImageFromSame and nImageToSame.
+ * Setting both to 0 can suppress a lot of I/O.
+ */
+VBOXDDU_DECL(int) VDCopyEx(PVDISK pDiskFrom, unsigned nImage, PVDISK pDiskTo,
+ const char *pszBackend, const char *pszFilename,
+ bool fMoveByRename, uint64_t cbSize,
+ unsigned nImageFromSame, unsigned nImageToSame,
+ unsigned uImageFlags, PCRTUUID pDstUuid,
+ unsigned uOpenFlags, PVDINTERFACE pVDIfsOperation,
+ PVDINTERFACE pDstVDIfsImage,
+ PVDINTERFACE pDstVDIfsOperation);
+
+/**
+ * Copies an image from one HDD container to another.
+ * The copy is opened in the target HDD container.
+ * It is possible to convert between different image formats, because the
+ * backend for the destination may be different from the source.
+ * If both the source and destination reference the same HDD container,
+ * then the image is moved (by copying/deleting or renaming) to the new location.
+ * The source container is unchanged if the move operation fails, otherwise
+ * the image at the new location is opened in the same way as the old one was.
+ *
+ * @note The read/write accesses across disks are not synchronized, just the
+ * accesses to each disk. Once there is a use case which requires a defined
+ * read/write behavior in this situation this needs to be extended.
+ *
+ * @return VBox status code.
+ * @return VERR_VD_IMAGE_NOT_FOUND if image with specified number was not opened.
+ * @param pDiskFrom Pointer to source HDD container.
+ * @param nImage Image number, counts from 0. 0 is always base image of container.
+ * @param pDiskTo Pointer to destination HDD container.
+ * @param pszBackend Name of the image file backend to use (may be NULL to use the same as the source, case insensitive).
+ * @param pszFilename New name of the image (may be NULL to specify that the
+ * copy destination is the destination container, or
+ * if pDiskFrom == pDiskTo, i.e. when moving).
+ * @param fMoveByRename If true, attempt to perform a move by renaming (if successful the new size is ignored).
+ * @param cbSize New image size (0 means leave unchanged).
+ * @param uImageFlags Flags specifying special destination image features.
+ * @param pDstUuid New UUID of the destination image. If NULL, a new UUID is created.
+ * This parameter is used if and only if a true copy is created.
+ * In all rename/move cases or copy to existing image cases the modification UUIDs are copied over.
+ * @param uOpenFlags Image file open mode, see VD_OPEN_FLAGS_* constants.
+ * Only used if the destination image is created.
+ * @param pVDIfsOperation Pointer to the per-operation VD interface list.
+ * @param pDstVDIfsImage Pointer to the per-image VD interface list, for the
+ * destination image.
+ * @param pDstVDIfsOperation Pointer to the per-operation VD interface list,
+ * for the destination operation.
+ */
+VBOXDDU_DECL(int) VDCopy(PVDISK pDiskFrom, unsigned nImage, PVDISK pDiskTo,
+ const char *pszBackend, const char *pszFilename,
+ bool fMoveByRename, uint64_t cbSize,
+ unsigned uImageFlags, PCRTUUID pDstUuid,
+ unsigned uOpenFlags, PVDINTERFACE pVDIfsOperation,
+ PVDINTERFACE pDstVDIfsImage,
+ PVDINTERFACE pDstVDIfsOperation);
+
+/**
+ * Optimizes the storage consumption of an image. Typically the unused blocks
+ * have to be wiped with zeroes to achieve a substantial reduced storage use.
+ * Another optimization done is reordering the image blocks, which can provide
+ * a significant performance boost, as reads and writes tend to use less random
+ * file offsets.
+ *
+ * @note Compaction is treated as a single operation with regard to thread
+ * synchronization, which means that it potentially blocks other activities for
+ * a long time. The complexity of compaction would grow even more if concurrent
+ * accesses have to be handled.
+ *
+ * @return VBox status code.
+ * @return VERR_VD_IMAGE_NOT_FOUND if image with specified number was not opened.
+ * @return VERR_VD_IMAGE_READ_ONLY if image is not writable.
+ * @return VERR_NOT_SUPPORTED if this kind of image can be compacted, but
+ * this isn't supported yet.
+ * @param pDisk Pointer to HDD container.
+ * @param nImage Image number, counts from 0. 0 is always base image of container.
+ * @param pVDIfsOperation Pointer to the per-operation VD interface list.
+ */
+VBOXDDU_DECL(int) VDCompact(PVDISK pDisk, unsigned nImage, PVDINTERFACE pVDIfsOperation);
+
+/**
+ * Resizes the given disk image to the given size. It is OK if there are
+ * multiple images open in the container. In this case the last disk image
+ * will be resized.
+ *
+ * @return VBox status
+ * @return VERR_VD_IMAGE_READ_ONLY if image is not writable.
+ * @return VERR_NOT_SUPPORTED if this kind of image can't be compacted.
+ *
+ * @param pDisk Pointer to the HDD container.
+ * @param cbSize New size of the image.
+ * @param pPCHSGeometry Pointer to the new physical disk geometry <= (16383,16,63). Not NULL.
+ * @param pLCHSGeometry Pointer to the new logical disk geometry <= (x,255,63). Not NULL.
+ * @param pVDIfsOperation Pointer to the per-operation VD interface list.
+ */
+VBOXDDU_DECL(int) VDResize(PVDISK pDisk, uint64_t cbSize,
+ PCVDGEOMETRY pPCHSGeometry,
+ PCVDGEOMETRY pLCHSGeometry,
+ PVDINTERFACE pVDIfsOperation);
+
+/**
+ * Prepares the given disk for use by the added filters. This applies to all
+ * opened images in the chain which might be opened read/write temporary.
+ *
+ * @return VBox status code.
+ *
+ * @param pDisk Pointer to the HDD container.
+ * @param pVDIfsOperation Pointer to the per-operation VD interface list.
+ */
+VBOXDDU_DECL(int) VDPrepareWithFilters(PVDISK pDisk, PVDINTERFACE pVDIfsOperation);
+
+/**
+ * Closes the last opened image file in HDD container.
+ * If previous image file was opened in read-only mode (the normal case) and
+ * the last opened image is in read-write mode then the previous image will be
+ * reopened in read/write mode.
+ *
+ * @return VBox status code.
+ * @return VERR_VD_NOT_OPENED if no image is opened in HDD container.
+ * @param pDisk Pointer to HDD container.
+ * @param fDelete If true, delete the image from the host disk.
+ */
+VBOXDDU_DECL(int) VDClose(PVDISK pDisk, bool fDelete);
+
+/**
+ * Removes the last added filter in the HDD container from the specified chain.
+ *
+ * @return VBox status code.
+ * @retval VERR_VD_NOT_OPENED if no filter is present for the disk.
+ * @param pDisk Pointer to HDD container.
+ * @param fFlags Combination of VD_FILTER_FLAGS_* defines.
+ */
+VBOXDDU_DECL(int) VDFilterRemove(PVDISK pDisk, uint32_t fFlags);
+
+/**
+ * Closes the currently opened cache image file in HDD container.
+ *
+ * @return VBox status code.
+ * @return VERR_VD_NOT_OPENED if no cache is opened in HDD container.
+ * @param pDisk Pointer to HDD container.
+ * @param fDelete If true, delete the image from the host disk.
+ */
+VBOXDDU_DECL(int) VDCacheClose(PVDISK pDisk, bool fDelete);
+
+/**
+ * Closes all opened image files in HDD container.
+ *
+ * @return VBox status code.
+ * @param pDisk Pointer to HDD container.
+ */
+VBOXDDU_DECL(int) VDCloseAll(PVDISK pDisk);
+
+/**
+ * Removes all filters of the given HDD container.
+ *
+ * @return VBox status code.
+ * @param pDisk Pointer to HDD container.
+ */
+VBOXDDU_DECL(int) VDFilterRemoveAll(PVDISK pDisk);
+
+/**
+ * Read data from virtual HDD.
+ *
+ * @return VBox status code.
+ * @retval VERR_VD_NOT_OPENED if no image is opened in HDD container.
+ * @param pDisk Pointer to HDD container.
+ * @param uOffset Offset of first reading byte from start of disk.
+ * Must be aligned to a sector boundary.
+ * @param pvBuf Pointer to buffer for reading data.
+ * @param cbRead Number of bytes to read.
+ * Must be aligned to a sector boundary.
+ */
+VBOXDDU_DECL(int) VDRead(PVDISK pDisk, uint64_t uOffset, void *pvBuf, size_t cbRead);
+
+/**
+ * Write data to virtual HDD.
+ *
+ * @return VBox status code.
+ * @retval VERR_VD_NOT_OPENED if no image is opened in HDD container.
+ * @param pDisk Pointer to HDD container.
+ * @param uOffset Offset of first writing byte from start of disk.
+ * Must be aligned to a sector boundary.
+ * @param pvBuf Pointer to buffer for writing data.
+ * @param cbWrite Number of bytes to write.
+ * Must be aligned to a sector boundary.
+ */
+VBOXDDU_DECL(int) VDWrite(PVDISK pDisk, uint64_t uOffset, const void *pvBuf, size_t cbWrite);
+
+/**
+ * Make sure the on disk representation of a virtual HDD is up to date.
+ *
+ * @return VBox status code.
+ * @retval VERR_VD_NOT_OPENED if no image is opened in HDD container.
+ * @param pDisk Pointer to HDD container.
+ */
+VBOXDDU_DECL(int) VDFlush(PVDISK pDisk);
+
+/**
+ * Get number of opened images in HDD container.
+ *
+ * @return Number of opened images for HDD container. 0 if no images have been opened.
+ * @param pDisk Pointer to HDD container.
+ */
+VBOXDDU_DECL(unsigned) VDGetCount(PVDISK pDisk);
+
+/**
+ * Get read/write mode of HDD container.
+ *
+ * @return Virtual disk ReadOnly status.
+ * @return true if no image is opened in HDD container.
+ * @param pDisk Pointer to HDD container.
+ */
+VBOXDDU_DECL(bool) VDIsReadOnly(PVDISK pDisk);
+
+/**
+ * Get sector size of an image in HDD container.
+ *
+ * @return Virtual disk sector size in bytes.
+ * @return 0 if image with specified number was not opened.
+ * @param pDisk Pointer to HDD container.
+ * @param nImage Image number, counts from 0. 0 is always base image of container.
+ */
+VBOXDDU_DECL(uint32_t) VDGetSectorSize(PVDISK pDisk, unsigned nImage);
+
+/**
+ * Get total capacity of an image in HDD container.
+ *
+ * @return Virtual disk size in bytes.
+ * @return 0 if image with specified number was not opened.
+ * @param pDisk Pointer to HDD container.
+ * @param nImage Image number, counts from 0. 0 is always base image of container.
+ */
+VBOXDDU_DECL(uint64_t) VDGetSize(PVDISK pDisk, unsigned nImage);
+
+/**
+ * Get total file size of an image in HDD container.
+ *
+ * @return Virtual disk size in bytes.
+ * @return 0 if image with specified number was not opened.
+ * @param pDisk Pointer to HDD container.
+ * @param nImage Image number, counts from 0. 0 is always base image of container.
+ */
+VBOXDDU_DECL(uint64_t) VDGetFileSize(PVDISK pDisk, unsigned nImage);
+
+/**
+ * Get virtual disk PCHS geometry of an image in HDD container.
+ *
+ * @return VBox status code.
+ * @return VERR_VD_IMAGE_NOT_FOUND if image with specified number was not opened.
+ * @return VERR_VD_GEOMETRY_NOT_SET if no geometry present in the HDD container.
+ * @param pDisk Pointer to HDD container.
+ * @param nImage Image number, counts from 0. 0 is always base image of container.
+ * @param pPCHSGeometry Where to store PCHS geometry. Not NULL.
+ */
+VBOXDDU_DECL(int) VDGetPCHSGeometry(PVDISK pDisk, unsigned nImage, PVDGEOMETRY pPCHSGeometry);
+
+/**
+ * Store virtual disk PCHS geometry of an image in HDD container.
+ *
+ * @return VBox status code.
+ * @return VERR_VD_IMAGE_NOT_FOUND if image with specified number was not opened.
+ * @param pDisk Pointer to HDD container.
+ * @param nImage Image number, counts from 0. 0 is always base image of container.
+ * @param pPCHSGeometry Where to load PCHS geometry from. Not NULL.
+ */
+VBOXDDU_DECL(int) VDSetPCHSGeometry(PVDISK pDisk, unsigned nImage, PCVDGEOMETRY pPCHSGeometry);
+
+/**
+ * Get virtual disk LCHS geometry of an image in HDD container.
+ *
+ * @return VBox status code.
+ * @return VERR_VD_IMAGE_NOT_FOUND if image with specified number was not opened.
+ * @return VERR_VD_GEOMETRY_NOT_SET if no geometry present in the HDD container.
+ * @param pDisk Pointer to HDD container.
+ * @param nImage Image number, counts from 0. 0 is always base image of container.
+ * @param pLCHSGeometry Where to store LCHS geometry. Not NULL.
+ */
+VBOXDDU_DECL(int) VDGetLCHSGeometry(PVDISK pDisk, unsigned nImage, PVDGEOMETRY pLCHSGeometry);
+
+/**
+ * Store virtual disk LCHS geometry of an image in HDD container.
+ *
+ * @return VBox status code.
+ * @return VERR_VD_IMAGE_NOT_FOUND if image with specified number was not opened.
+ * @param pDisk Pointer to HDD container.
+ * @param nImage Image number, counts from 0. 0 is always base image of container.
+ * @param pLCHSGeometry Where to load LCHS geometry from. Not NULL.
+ */
+VBOXDDU_DECL(int) VDSetLCHSGeometry(PVDISK pDisk, unsigned nImage, PCVDGEOMETRY pLCHSGeometry);
+
+/**
+ * Queries the available regions of an image in the given VD container.
+ *
+ * @return VBox status code.
+ * @retval VERR_VD_IMAGE_NOT_FOUND if image with specified number was not opened.
+ * @retval VERR_NOT_SUPPORTED if the image backend doesn't support region lists.
+ * @param pDisk Pointer to HDD container.
+ * @param nImage Image number, counts from 0. 0 is always base image of container.
+ * @param fFlags Combination of VD_REGION_LIST_F_* flags.
+ * @param ppRegionList Where to store the pointer to the region list on success, must be freed
+ * with VDRegionListFree().
+ */
+VBOXDDU_DECL(int) VDQueryRegions(PVDISK pDisk, unsigned nImage, uint32_t fFlags,
+ PPVDREGIONLIST ppRegionList);
+
+/**
+ * Frees a region list previously queried with VDQueryRegions().
+ *
+ * @return nothing.
+ * @param pRegionList The region list to free.
+ */
+VBOXDDU_DECL(void) VDRegionListFree(PVDREGIONLIST pRegionList);
+
+/**
+ * Get version of image in HDD container.
+ *
+ * @return VBox status code.
+ * @return VERR_VD_IMAGE_NOT_FOUND if image with specified number was not opened.
+ * @param pDisk Pointer to HDD container.
+ * @param nImage Image number, counts from 0. 0 is always base image of container.
+ * @param puVersion Where to store the image version.
+ */
+VBOXDDU_DECL(int) VDGetVersion(PVDISK pDisk, unsigned nImage, unsigned *puVersion);
+
+/**
+ * List the capabilities of image backend in HDD container.
+ *
+ * @return VBox status code.
+ * @return VERR_VD_IMAGE_NOT_FOUND if image with specified number was not opened.
+ * @param pDisk Pointer to the HDD container.
+ * @param nImage Image number, counts from 0. 0 is always base image of container.
+ * @param pBackendInfo Where to store the backend information.
+ */
+VBOXDDU_DECL(int) VDBackendInfoSingle(PVDISK pDisk, unsigned nImage, PVDBACKENDINFO pBackendInfo);
+
+/**
+ * Get flags of image in HDD container.
+ *
+ * @return VBox status code.
+ * @return VERR_VD_IMAGE_NOT_FOUND if image with specified number was not opened.
+ * @param pDisk Pointer to HDD container.
+ * @param nImage Image number, counts from 0. 0 is always base image of container.
+ * @param puImageFlags Where to store the image flags.
+ */
+VBOXDDU_DECL(int) VDGetImageFlags(PVDISK pDisk, unsigned nImage, unsigned *puImageFlags);
+
+/**
+ * Get open flags of image in HDD container.
+ *
+ * @return VBox status code.
+ * @return VERR_VD_IMAGE_NOT_FOUND if image with specified number was not opened.
+ * @param pDisk Pointer to HDD container.
+ * @param nImage Image number, counts from 0. 0 is always base image of container.
+ * @param puOpenFlags Where to store the image open flags.
+ */
+VBOXDDU_DECL(int) VDGetOpenFlags(PVDISK pDisk, unsigned nImage, unsigned *puOpenFlags);
+
+/**
+ * Set open flags of image in HDD container.
+ * This operation may cause file locking changes and/or files being reopened.
+ * Note that in case of unrecoverable error all images in HDD container will be closed.
+ *
+ * @return VBox status code.
+ * @return VERR_VD_IMAGE_NOT_FOUND if image with specified number was not opened.
+ * @param pDisk Pointer to HDD container.
+ * @param nImage Image number, counts from 0. 0 is always base image of container.
+ * @param uOpenFlags Image file open mode, see VD_OPEN_FLAGS_* constants.
+ */
+VBOXDDU_DECL(int) VDSetOpenFlags(PVDISK pDisk, unsigned nImage, unsigned uOpenFlags);
+
+/**
+ * Get base filename of image in HDD container. Some image formats use
+ * other filenames as well, so don't use this for anything but informational
+ * purposes.
+ *
+ * @return VBox status code.
+ * @return VERR_VD_IMAGE_NOT_FOUND if image with specified number was not opened.
+ * @return VERR_BUFFER_OVERFLOW if pszFilename buffer too small to hold filename.
+ * @param pDisk Pointer to HDD container.
+ * @param nImage Image number, counts from 0. 0 is always base image of container.
+ * @param pszFilename Where to store the image file name.
+ * @param cbFilename Size of buffer pszFilename points to.
+ */
+VBOXDDU_DECL(int) VDGetFilename(PVDISK pDisk, unsigned nImage, char *pszFilename, unsigned cbFilename);
+
+/**
+ * Get the comment line of image in HDD container.
+ *
+ * @return VBox status code.
+ * @return VERR_VD_IMAGE_NOT_FOUND if image with specified number was not opened.
+ * @return VERR_BUFFER_OVERFLOW if pszComment buffer too small to hold comment text.
+ * @param pDisk Pointer to HDD container.
+ * @param nImage Image number, counts from 0. 0 is always base image of container.
+ * @param pszComment Where to store the comment string of image. NULL is ok.
+ * @param cbComment The size of pszComment buffer. 0 is ok.
+ */
+VBOXDDU_DECL(int) VDGetComment(PVDISK pDisk, unsigned nImage, char *pszComment, unsigned cbComment);
+
+/**
+ * Changes the comment line of image in HDD container.
+ *
+ * @return VBox status code.
+ * @return VERR_VD_IMAGE_NOT_FOUND if image with specified number was not opened.
+ * @param pDisk Pointer to HDD container.
+ * @param nImage Image number, counts from 0. 0 is always base image of container.
+ * @param pszComment New comment string (UTF-8). NULL is allowed to reset the comment.
+ */
+VBOXDDU_DECL(int) VDSetComment(PVDISK pDisk, unsigned nImage, const char *pszComment);
+
+/**
+ * Get UUID of image in HDD container.
+ *
+ * @return VBox status code.
+ * @return VERR_VD_IMAGE_NOT_FOUND if image with specified number was not opened.
+ * @param pDisk Pointer to HDD container.
+ * @param nImage Image number, counts from 0. 0 is always base image of container.
+ * @param pUuid Where to store the image UUID.
+ */
+VBOXDDU_DECL(int) VDGetUuid(PVDISK pDisk, unsigned nImage, PRTUUID pUuid);
+
+/**
+ * Set the image's UUID. Should not be used by normal applications.
+ *
+ * @return VBox status code.
+ * @return VERR_VD_IMAGE_NOT_FOUND if image with specified number was not opened.
+ * @param pDisk Pointer to HDD container.
+ * @param nImage Image number, counts from 0. 0 is always base image of container.
+ * @param pUuid New UUID of the image. If NULL, a new UUID is created.
+ */
+VBOXDDU_DECL(int) VDSetUuid(PVDISK pDisk, unsigned nImage, PCRTUUID pUuid);
+
+/**
+ * Get last modification UUID of image in HDD container.
+ *
+ * @return VBox status code.
+ * @return VERR_VD_IMAGE_NOT_FOUND if image with specified number was not opened.
+ * @param pDisk Pointer to HDD container.
+ * @param nImage Image number, counts from 0. 0 is always base image of container.
+ * @param pUuid Where to store the image modification UUID.
+ */
+VBOXDDU_DECL(int) VDGetModificationUuid(PVDISK pDisk, unsigned nImage, PRTUUID pUuid);
+
+/**
+ * Set the image's last modification UUID. Should not be used by normal applications.
+ *
+ * @return VBox status code.
+ * @return VERR_VD_IMAGE_NOT_FOUND if image with specified number was not opened.
+ * @param pDisk Pointer to HDD container.
+ * @param nImage Image number, counts from 0. 0 is always base image of container.
+ * @param pUuid New modification UUID of the image. If NULL, a new UUID is created.
+ */
+VBOXDDU_DECL(int) VDSetModificationUuid(PVDISK pDisk, unsigned nImage, PCRTUUID pUuid);
+
+/**
+ * Get parent UUID of image in HDD container.
+ *
+ * @return VBox status code.
+ * @return VERR_VD_IMAGE_NOT_FOUND if image with specified number was not opened.
+ * @param pDisk Pointer to HDD container.
+ * @param nImage Image number, counts from 0. 0 is always base image of the container.
+ * @param pUuid Where to store the parent image UUID.
+ */
+VBOXDDU_DECL(int) VDGetParentUuid(PVDISK pDisk, unsigned nImage, PRTUUID pUuid);
+
+/**
+ * Set the image's parent UUID. Should not be used by normal applications.
+ *
+ * @return VBox status code.
+ * @param pDisk Pointer to HDD container.
+ * @param nImage Image number, counts from 0. 0 is always base image of container.
+ * @param pUuid New parent UUID of the image. If NULL, a new UUID is created.
+ */
+VBOXDDU_DECL(int) VDSetParentUuid(PVDISK pDisk, unsigned nImage, PCRTUUID pUuid);
+
+
+/**
+ * Debug helper - dumps all opened images in HDD container into the log file.
+ *
+ * @param pDisk Pointer to HDD container.
+ */
+VBOXDDU_DECL(void) VDDumpImages(PVDISK pDisk);
+
+
+/**
+ * Discards unused ranges given as a list.
+ *
+ * @return VBox status code.
+ * @param pDisk Pointer to HDD container.
+ * @param paRanges The array of ranges to discard.
+ * @param cRanges Number of entries in the array.
+ *
+ * @note In contrast to VDCompact() the ranges are always discarded even if they
+ * appear to contain data. This method is mainly used to implement TRIM support.
+ */
+VBOXDDU_DECL(int) VDDiscardRanges(PVDISK pDisk, PCRTRANGE paRanges, unsigned cRanges);
+
+
+/**
+ * Start an asynchronous read request.
+ *
+ * @return VBox status code.
+ * @param pDisk Pointer to the HDD container.
+ * @param off The offset of the virtual disk to read from.
+ * @param cbRead How many bytes to read.
+ * @param pSgBuf Pointer to the S/G buffer to read into.
+ * @param pfnComplete Completion callback.
+ * @param pvUser1 User data which is passed on completion.
+ * @param pvUser2 User data which is passed on completion.
+ */
+VBOXDDU_DECL(int) VDAsyncRead(PVDISK pDisk, uint64_t off, size_t cbRead,
+ PCRTSGBUF pSgBuf,
+ PFNVDASYNCTRANSFERCOMPLETE pfnComplete,
+ void *pvUser1, void *pvUser2);
+
+
+/**
+ * Start an asynchronous write request.
+ *
+ * @return VBox status code.
+ * @param pDisk Pointer to the HDD container.
+ * @param off The offset of the virtual disk to write to.
+ * @param cbWrite How many bytes to write.
+ * @param pSgBuf Pointer to the S/G buffer to write from.
+ * @param pfnComplete Completion callback.
+ * @param pvUser1 User data which is passed on completion.
+ * @param pvUser2 User data which is passed on completion.
+ */
+VBOXDDU_DECL(int) VDAsyncWrite(PVDISK pDisk, uint64_t off, size_t cbWrite,
+ PCRTSGBUF pSgBuf,
+ PFNVDASYNCTRANSFERCOMPLETE pfnComplete,
+ void *pvUser1, void *pvUser2);
+
+
+/**
+ * Start an asynchronous flush request.
+ *
+ * @return VBox status code.
+ * @param pDisk Pointer to the HDD container.
+ * @param pfnComplete Completion callback.
+ * @param pvUser1 User data which is passed on completion.
+ * @param pvUser2 User data which is passed on completion.
+ */
+VBOXDDU_DECL(int) VDAsyncFlush(PVDISK pDisk,
+ PFNVDASYNCTRANSFERCOMPLETE pfnComplete,
+ void *pvUser1, void *pvUser2);
+
+/**
+ * Start an asynchronous discard request.
+ *
+ * @return VBox status code.
+ * @param pDisk Pointer to HDD container.
+ * @param paRanges The array of ranges to discard.
+ * @param cRanges Number of entries in the array.
+ * @param pfnComplete Completion callback.
+ * @param pvUser1 User data which is passed on completion.
+ * @param pvUser2 User data which is passed on completion.
+ */
+VBOXDDU_DECL(int) VDAsyncDiscardRanges(PVDISK pDisk, PCRTRANGE paRanges, unsigned cRanges,
+ PFNVDASYNCTRANSFERCOMPLETE pfnComplete,
+ void *pvUser1, void *pvUser2);
+
+/**
+ * Tries to repair a corrupted image.
+ *
+ * @return VBox status code.
+ * @retval VERR_VD_IMAGE_REPAIR_NOT_SUPPORTED if the backend does not support repairing the image.
+ * @retval VERR_VD_IMAGE_REPAIR_IMPOSSIBLE if the corruption is to severe to repair the image.
+ * @param pVDIfsDisk Pointer to the per-disk VD interface list.
+ * @param pVDIfsImage Pointer to the per-image VD interface list.
+ * @param pszFilename Name of the image file to repair.
+ * @param pszBackend The backend to use.
+ * @param fFlags Combination of the VD_REPAIR_* flags.
+ */
+VBOXDDU_DECL(int) VDRepair(PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage,
+ const char *pszFilename, const char *pszBackend, uint32_t fFlags);
+
+/**
+ * Create a VFS file handle from the given HDD container.
+ *
+ * @return VBox status code.
+ * @param pDisk Pointer to HDD container.
+ * @param fFlags Combination of the VD_VFSFILE_* flags.
+ * @param phVfsFile Where to store the handle to the VFS file on
+ * success.
+ */
+VBOXDDU_DECL(int) VDCreateVfsFileFromDisk(PVDISK pDisk, uint32_t fFlags,
+ PRTVFSFILE phVfsFile);
+
+
+
+/** @defgroup grp_vd_ifs_def Default implementations for certain VD interfaces.
+ * @{
+ */
+/** Internal per interface instance data. */
+typedef struct VDIFINSTINT *VDIFINST;
+/** Pointer to the per instance interface data. */
+typedef VDIFINST *PVDIFINST;
+
+/**
+ * Creates a new VD TCP/IP interface instance and adds it to the given interface list.
+ *
+ * @returns VBox status code.
+ * @param phTcpNetInst Where to store the TCP/IP interface handle on success.
+ * @param ppVdIfs Pointer to the VD interface list.
+ */
+VBOXDDU_DECL(int) VDIfTcpNetInstDefaultCreate(PVDIFINST phTcpNetInst, PVDINTERFACE *ppVdIfs);
+
+/**
+ * Destroys the given VD TCP/IP interface instance.
+ *
+ * @returns nothing.
+ * @param hTcpNetInst The TCP/IP interface instance handle.
+ */
+VBOXDDU_DECL(void) VDIfTcpNetInstDefaultDestroy(VDIFINST hTcpNetInst);
+/** @} */
+
+
+
+/** @defgroup grp_vd_ioiter I/O iterator
+ * @{
+ */
+
+/** Read metadata coming before each main data block addressed in the segment. */
+#define VD_IOITER_SEG_F_PRE_METADATA RT_BIT_32(0)
+/** Read the main user data of each addressed block in the segment. */
+#define VD_IOITER_SEG_F_MAIN_DATA RT_BIT_32(1)
+/** Read metadata coming after each main data block addressed in the segment. */
+#define VD_IOITER_SEG_F_POST_METADATA RT_BIT_32(2)
+/** Read checksum data of each data block addressed in the segment. */
+#define VD_IOITER_SEG_F_CHKSUM RT_BIT_32(3)
+/** Read all available data for each addressed block in the segment. */
+#define VD_IOITER_SEG_F_AVAILABLE RT_BIT_32(4)
+
+/** The offset and size members in the segments use byte granularity instead of a
+ * block address and number of blocks respectively. */
+#define VDIOITER_F_BYTE_OFFSET_AND_SIZE RT_BIT_32(0)
+
+/**
+ * VD I/O iterator segment.
+ */
+typedef struct VDIOITERSEG
+{
+ /** Start offset for this segment. */
+ uint64_t offStartSeg;
+ /** Size of the segment (bytes or blocks). */
+ uint64_t cSizeSeg;
+ /** Flags for this segment, see VD_IOITER_SEG_F_*. */
+ uint32_t fFlags;
+} VDIOITERSEG;
+/** Pointer to a I/O iterator segment. */
+typedef VDIOITERSEG *PVDIOITERSEG;
+/** Pointer to a constant I/O iterator segment. */
+typedef VDIOITERSEG *PCVDIOITERSEG;
+
+/** I/O iterator handle. */
+typedef struct VDIOITERINT *VDIOITER;
+/** Pointer to a I/O iterator handle. */
+typedef VDIOITER *PVDIOITER;
+
+/**
+ * Create a new I/O iterator.
+ *
+ * @returns VBox status code.
+ * @param pDisk The disk to create the iterator for.
+ * @param phVdIoIter Where to store the handle to the I/O iterator on success.
+ * @param paIoIterSegs The segments for the iterator, can be destroyed after the call.
+ * @param cIoIterSegs Number of segments.
+ * @param fFlags Flags for the iterator, see VDIOITER_F_*
+ */
+VBOXDDU_DECL(int) VDIoIterCreate(PVDISK pDisk, PVDIOITER phVdIoIter, PCVDIOITERSEG paIoIterSegs,
+ uint32_t cIoIterSegs, uint32_t fFlags);
+
+/**
+ * Retains the reference count of the given I/O iterator.
+ *
+ * @returns New reference count.
+ * @param hVdIoIter The I/O iterator handle.
+ */
+VBOXDDU_DECL(uint32_t) VDIoIterRetain(VDIOITER hVdIoIter);
+
+/**
+ * Releases the reference count of the given I/O iterator.
+ *
+ * @returns New reference count, on 0 the iterator is destroyed.
+ * @param hVdIoIter The I/O iterator handle.
+ */
+VBOXDDU_DECL(uint32_t) VDIoIterRelease(VDIOITER hVdIoIter);
+
+/**
+ * Returns the number of segments in the given I/O iterator.
+ *
+ * @returns Number of segments.
+ * @param hVdIoIter The I/O iterator handle.
+ */
+VBOXDDU_DECL(uint32_t) VDIoIterGetSegmentCount(VDIOITER hVdIoIter);
+
+/**
+ * Returns the flags of the given I/O iterator.
+ *
+ * @returns Flags.
+ * @param hVdIoIter The I/O iterator handle.
+ */
+VBOXDDU_DECL(uint32_t) VDIoIterGetFlags(VDIOITER hVdIoIter);
+
+/**
+ * Queries the properties of the given segment for the given I/O iterator.
+ *
+ * @returns VBox status code.
+ * @param hVdIoIter The I/O iterator handle.
+ * @param idx The segment index to query.
+ * @param pSegment Where to store the segment properties on success.
+ */
+VBOXDDU_DECL(int) VDIoIterQuerySegment(VDIOITER hVdIoIter, uint32_t idx, PVDIOITERSEG pSegment);
+
+/** @} */
+
+
+/** @defgroup grp_vd_io_buf I/O buffer management API.
+ * @{
+ */
+
+/** VD I/O buffer manager handle. */
+typedef struct VDIOBUFMGRINT *VDIOBUFMGR;
+/** Pointer to VD I/O buffer manager handle. */
+typedef VDIOBUFMGR *PVDIOBUFMGR;
+
+/** VD I/O buffer handle. */
+typedef struct VDIOBUFINT *VDIOBUF;
+/** Pointer to a VD I/O buffer handle. */
+typedef VDIOBUF *PVDIOBUF;
+
+/** Default I/O buffer manager flags. */
+#define VD_IOBUFMGR_F_DEFAULT (0)
+/** I/O buffer memory needs to be non pageable (for example because it contains sensitive data
+ * which shouldn't end up in swap unencrypted). */
+#define VD_IOBUFMGR_F_REQUIRE_NOT_PAGABLE RT_BIT(0)
+
+/** Pointer to VD I/O buffer callbacks. */
+typedef struct VDIOBUFCALLBACKS *PVDIOBUFCALLBACKS;
+/** Pointer to const VD I/O buffer callbacks. */
+typedef const struct VDIOBUFCALLBACKS *PCVDIOBUFCALLBACKS;
+
+/**
+ * VD I/O buffer callbacks.
+ */
+typedef struct VDIOBUFCALLBACKS
+{
+ /**
+ * Copy data from the memory buffer of the caller to the callees memory buffer for the given request.
+ *
+ * @returns VBox status code.
+ * @retval VERR_PDM_MEDIAEX_IOBUF_OVERFLOW if there is not enough room to store the data.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param hIoBuf The I/O request handle.
+ * @param pvIoBufAlloc The allocator specific memory for this request.
+ * @param offDst The destination offset from the start to write the data to.
+ * @param pSgBuf The S/G buffer to read the data from.
+ * @param cbCopy How many bytes to copy.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnIoBufCopyFromBuf, (PVDIOBUFCALLBACKS pInterface, VDIOBUF hIoBuf,
+ void *pvIoBufAlloc, uint32_t offDst, PRTSGBUF pSgBuf,
+ size_t cbCopy));
+
+ /**
+ * Copy data to the memory buffer of the caller from the callees memory buffer for the given request.
+ *
+ * @returns VBox status code.
+ * @retval VERR_PDM_MEDIAEX_IOBUF_UNDERRUN if there is not enough data to copy from the buffer.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param hIoBuf The I/O request handle.
+ * @param pvIoBufAlloc The allocator specific memory for this request.
+ * @param offSrc The offset from the start of the buffer to read the data from.
+ * @param pSgBuf The S/G buffer to write the data to.
+ * @param cbCopy How many bytes to copy.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnIoBufCopyToBuf, (PVDIOBUFCALLBACKS pInterface, VDIOBUF hIoBuf,
+ void *pvIoBufAlloc, uint32_t offSrc, PRTSGBUF pSgBuf,
+ size_t cbCopy));
+
+ /**
+ * Queries a pointer to the memory buffer for the request from the drive/device above.
+ *
+ * @returns VBox status code.
+ * @retval VERR_NOT_SUPPORTED if this is not supported for this request.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param hIoBuf The I/O request handle.
+ * @param pvIoBufAlloc The allocator specific memory for this request.
+ * @param offBuf The offset from the start of the buffer to get the buffer address.
+ * @param cbBuf The number of bytes requested.
+ * @param ppvBuf Where to store the pointer to the guest buffer on success.
+ * @param pcbBuf Where to store the size of the buffer on success.
+ *
+ * @note This is an optional feature of the entity implementing this interface to avoid overhead
+ * by copying the data between buffers. If NULL it is not supported at all and the caller
+ * has to resort to VDIOBUFCALLBACKS::pfnIoBufCopyToBuf and VDIOBUFCALLBACKS::pfnIoBufCopyFromBuf.
+ * The same holds when VERR_NOT_SUPPORTED is returned.
+ *
+ * On the upside the caller of this interface might not call this method at all and just
+ * use the before mentioned methods to copy the data between the buffers.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnIoBufQueryBuf, (PVDIOBUFCALLBACKS pInterface, VDIOBUF hIoBuf,
+ void *pvIoBufAlloc, uint32_t offBuf, size_t cbBuf,
+ void **ppvBuf, size_t *pcbBuf));
+
+} VDIOBUFCALLBACKS;
+
+/**
+ * Creates a new I/O buffer manager.
+ *
+ * @returns VBox status code.
+ * @param phIoBufMgr Where to store the handle to the I/O buffer manager on success.
+ * @param cbMax The maximum amount of I/O memory to allow. Trying to allocate more than
+ * this will lead to out of memory errors. 0 for "unlimited" size (only restriction
+ * is the available memory on the host).
+ * @param fFlags Combination of VD_IOBUFMGR_F_*.
+ * @param pIoBufClbks Memory copy callbacks between source and target memory regions, optional.
+ * When NULL all I/O buffers must be allocated with a valid S/G buffer laying out the
+ * memory.
+ * @param cbIoBufAlloc How much to allocate extra in the I/O buffer for private use.
+ */
+VBOXDDU_DECL(int) VDIoBufMgrCreate(PVDIOBUFMGR phIoBufMgr, size_t cbMax, uint32_t fFlags,
+ PVDIOBUFCALLBACKS pIoBufClbks, size_t cbIoBufAlloc);
+
+/**
+ * Destroys the given I/O buffer manager.
+ *
+ * @returns VBox status code.
+ * @retval VERR_INVALID_STATE if there are still buffers allocated by the given manager.
+ * @param hIoBufMgr The I/O buffer manager.
+ */
+VBOXDDU_DECL(int) VDIoBufMgrDestroy(VDIOBUFMGR hIoBufMgr);
+
+/**
+ * Allocate a new I/O buffer handle.
+ *
+ * @returns VBox status code.
+ * @param hIoBufMgr The I/O buffer manager to use.
+ * @param phIoBuf Where to store the I/O buffer handle on success.
+ * @param ppvIoBufAlloc Where to store the pointe to the private party on success.
+ * @param pSgBuf The S/G buffer to use, optional. If NULL the I/O buffer callbacks
+ * supplied when creating the owning manager are used to transfer the
+ * data.
+ * @param cbBuf Size of the buffer in bytes.
+ */
+VBOXDDU_DECL(int) VDIoBufMgrAllocBuf(VDIOBUFMGR hIoBufMgr, PVDIOBUF phIoBuf, void **ppvIoBufAlloc,
+ PCRTSGBUF pSgBuf, size_t cbBuf);
+
+/**
+ * Retains the I/O buffer reference count.
+ *
+ * @returns New reference count.
+ * @param hIoBuf The I/O buffer handle.
+ */
+VBOXDDU_DECL(uint32_t) VDIoBufRetain(VDIOBUF hIoBuf);
+
+/**
+ * Releases the given I/O buffer reference.
+ *
+ * @returns New reference count, on 0 the I/O buffer is destroyed.
+ * @param hIoBuf The I/O buffer handle.
+ */
+VBOXDDU_DECL(uint32_t) VDIoBufRelease(VDIOBUF hIoBuf);
+
+/** @} */
+
+
+/** @defgroup grp_vd_ioqueue I/O queues
+ * @{
+ */
+
+/** VD I/O queue handle. */
+typedef struct VDIOQUEUEINT *VDIOQUEUE;
+/** Pointer to an VD I/O queue handle. */
+typedef VDIOQUEUE *PVDIOQUEUE;
+
+/** VD I/O queue request handle. */
+typedef struct VDIOREQINT *VDIOREQ;
+/** Pointer to an VD I/O queue request handle. */
+typedef VDIOREQ *PVDIOREQ;
+
+/** A I/O request ID. */
+typedef uint64_t VDIOREQID;
+
+/**
+ * I/O request type.
+ */
+typedef enum VDIOREQTYPE
+{
+ /** Invalid request type. */
+ VDIOREQTYPE_INVALID = 0,
+ /** Read request. */
+ VDIOREQTYPE_READ,
+ /** Write request. */
+ VDIOREQTYPE_WRITE,
+ /** Flush request. */
+ VDIOREQTYPE_FLUSH,
+ /** Discard request. */
+ VDIOREQTYPE_DISCARD,
+ /** 32bit hack. */
+ VDIOREQTYPE_32BIT_HACK = 0x7fffffff
+} VDIOREQTYPE;
+/** Pointer to a request type. */
+typedef VDIOREQTYPE *PVDIOREQTYPE;
+
+/**
+ * I/O queue request completion callback.
+ *
+ * @returns nothing.
+ * @param hVdIoQueue The VD I/O queue handle.
+ * @param pDisk The disk the queue is attached to.
+ * @param hVdIoReq The VD I/O request which completed.
+ * @param pvVdIoReq Pointer to the allocator specific memory for this request.
+ * @param rcReq The completion status code.
+ */
+typedef DECLCALLBACKTYPE(void, FNVDIOQUEUEREQCOMPLETE,(VDIOQUEUE hVdIoQueue, PVDISK pDisk,
+ VDIOREQ hVdIoReq, void *pvVdIoReq, int rcReq));
+/** Pointer to a VD I/O queue request completion callback. */
+typedef FNVDIOQUEUEREQCOMPLETE *PFNVDIOQUEUEREQCOMPLETE;
+
+
+/**
+ * Creates a new I/O queue.
+ *
+ * @returns VBox status code.
+ * @param phVdIoQueue Where to store the handle to the I/O queue on success.
+ * @param pfnIoReqComplete The completion handle to call when a request on the specified queue completes.
+ * @param cbIoReqAlloc The extra amount of memory to allocate and associate with allocated requests
+ * for use by the caller.
+ * @param iPriority The priority of the queue from 0..UINT32_MAX. The lower the number the higher
+ * the priority of the queue.
+ */
+VBOXDDU_DECL(int) VDIoQueueCreate(PVDIOQUEUE phVdIoQueue, PFNVDIOQUEUEREQCOMPLETE pfnIoReqComplete,
+ size_t cbIoReqAlloc, uint32_t iPriority);
+
+/**
+ * Destroys the given I/O queue.
+ *
+ * @returns VBox status code.
+ * @param hVdIoQueue The I/O queue handle.
+ */
+VBOXDDU_DECL(int) VDIoQueueDestroy(VDIOQUEUE hVdIoQueue);
+
+/**
+ * Attaches the given I/O queue to the given virtual disk container.
+ *
+ * @returns VBox status code.
+ * @param pDisk The disk container handle.
+ * @param hVdIoQueue The I/O queue to attach.
+ */
+VBOXDDU_DECL(int) VDIoQueueAttach(PVDISK pDisk, VDIOQUEUE hVdIoQueue);
+
+/**
+ * Detaches the given I/O queue from the currently attached disk container.
+ *
+ * @returns VBox status code.
+ * @param hVdIoQueue The I/O queue.
+ * @param fPurge Flag whether to cancel all active requests on this queue
+ * before detaching.
+ */
+VBOXDDU_DECL(int) VDIoQueueDetach(VDIOQUEUE hVdIoQueue, bool fPurge);
+
+/**
+ * Purges all requests on the given queue.
+ *
+ * @returns VBox status code.
+ * @param hVdIoQueue The I/O queue.
+ */
+VBOXDDU_DECL(int) VDIoQueuePurge(VDIOQUEUE hVdIoQueue);
+
+/**
+ * Allocates a new request from the given queue.
+ *
+ * @returns VBox status code.
+ * @param hVdIoQueue The I/O queue.
+ * @param phVdIoReq Where to store the handle of the request on success.
+ * @param ppvVdIoReq Where to store the pointer to the allocator usable memory on success.
+ * @param uIoReqId The request ID to assign to the request for canceling.
+ */
+VBOXDDU_DECL(int) VDIoQueueReqAlloc(VDIOQUEUE hVdIoQueue, PVDIOREQ phVdIoReq,
+ void **ppvVdIoReq, VDIOREQID uIoReqId);
+
+/**
+ * Frees a given non active request.
+ *
+ * @returns VBox status code.
+ * @param hVdIoReq The I/O request to free.
+ */
+VBOXDDU_DECL(int) VDIoQueueReqFree(VDIOREQ hVdIoReq);
+
+/**
+ * Cancels an active request by the given request ID.
+ *
+ * @returns VBox status code.
+ * @param hVdIoQueue The I/O queue to cancel the request on.
+ * @param uIoReqId The request ID.
+ */
+VBOXDDU_DECL(int) VDIoQueueReqCancelById(VDIOQUEUE hVdIoQueue, VDIOREQID uIoReqId);
+
+/**
+ * Cancels an active request by the given handle.
+ *
+ * @returns VBox status code.
+ * @param hVdIoReq The I/O request handle to cancel.
+ */
+VBOXDDU_DECL(int) VDIoQueueReqCancelByHandle(VDIOREQ hVdIoReq);
+
+/**
+ * Submit a new request to the queue the request was allocated from.
+ *
+ * @returns VBox status code.
+ * @param hVdIoReq The I/O request handle to submit.
+ * @param enmType The type of the request.
+ * @param hVdIoIter The iterator to use, NULL for flush requests.
+ * @param hVdIoBuf The I/O buffer handle to use, NULL for flush and discard requests.
+ */
+VBOXDDU_DECL(int) VDIoQueueReqSubmit(VDIOREQ hVdIoReq, VDIOREQTYPE enmType,
+ VDIOITER hVdIoIter, VDIOBUF hVdIoBuf);
+
+/** @} */
+
+
+RT_C_DECLS_END
+
+/** @} */
+
+#endif /* !VBOX_INCLUDED_vd_h */
+
diff --git a/include/VBox/vdmedia.h b/include/VBox/vdmedia.h
new file mode 100644
index 00000000..89886efb
--- /dev/null
+++ b/include/VBox/vdmedia.h
@@ -0,0 +1,226 @@
+/** @file
+ * Virtual Disk Container API - Media type definitions shared with PDM.
+ */
+
+/*
+ * Copyright (C) 2017-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vdmedia_h
+#define VBOX_INCLUDED_vdmedia_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+
+/** @name VD container type.
+ * @{
+ */
+typedef enum VDTYPE
+{
+ /** Invalid. */
+ VDTYPE_INVALID = 0,
+ /** HardDisk */
+ VDTYPE_HDD,
+ /** Any kind of optical disc (CD/DVD etc.). */
+ VDTYPE_OPTICAL_DISC,
+ /** Floppy. */
+ VDTYPE_FLOPPY
+} VDTYPE;
+/** @}*/
+
+/** @name VD medium type.
+ * @{
+ */
+typedef enum VDMEDIUMTYPE
+{
+ /** Invalid. */
+ VDMEDIUMTYPE_INVALID = 0,
+ /** HardDisk (spinning platter or SSD). */
+ VDMEDIUMTYPE_HDD,
+ /** CD-ROM */
+ VDMEDIUMTYPE_CDROM,
+ /** DVD-ROM */
+ VDMEDIUMTYPE_DVDROM,
+ /** BluRay. */
+ VDMEDIUMTYPE_BD,
+ /** 360KB 5 1/4" floppy. */
+ VDMEDIUMTYPE_FLOPPY_360,
+ /** 720KB 3 1/2" floppy. */
+ VDMEDIUMTYPE_FLOPPY_720,
+ /** 1.2MB 5 1/4" floppy. */
+ VDMEDIUMTYPE_FLOPPY_1_20,
+ /** 1.44MB 3 1/2" floppy. */
+ VDMEDIUMTYPE_FLOPPY_1_44,
+ /** 2.88MB 3 1/2" floppy. */
+ VDMEDIUMTYPE_FLOPPY_2_88,
+ /** Fake disk that can take up to 15.6 MB images.
+ * C=255, H=2, S=63. */
+ VDMEDIUMTYPE_FLOPPY_FAKE_15_6,
+ /** Fake disk that can take up to 63.5 MB images.
+ * C=255, H=2, S=255. */
+ VDMEDIUMTYPE_FLOPPY_FAKE_63_5
+} VDMEDIUMTYPE;
+/** @} */
+
+/** Check if the given medium type is a floppy. */
+#define VDMEDIUMTYPE_IS_FLOPPY(a_enmType) ( (a_enmType) >= VDMEDIUMTYPE_FLOPPY_360 && (a_enmType) <= VDMEDIUMTYPE_FLOPPY_2_88 )
+
+/**
+ * Disk geometry.
+ */
+typedef struct VDGEOMETRY
+{
+ /** Number of cylinders. */
+ uint32_t cCylinders;
+ /** Number of heads. */
+ uint32_t cHeads;
+ /** Number of sectors. */
+ uint32_t cSectors;
+} VDGEOMETRY;
+
+/** Pointer to disk geometry. */
+typedef VDGEOMETRY *PVDGEOMETRY;
+/** Pointer to constant disk geometry. */
+typedef const VDGEOMETRY *PCVDGEOMETRY;
+
+/**
+ * Disk region data form known to us from various standards.
+ */
+typedef enum VDREGIONDATAFORM
+{
+ /** Invalid data form. */
+ VDREGIONDATAFORM_INVALID = 0,
+ /** Raw data, no standardized format. */
+ VDREGIONDATAFORM_RAW,
+ /** CD-DA (audio CD), 2352 bytes of data. */
+ VDREGIONDATAFORM_CDDA,
+ /** CDDA data is pause. */
+ VDREGIONDATAFORM_CDDA_PAUSE,
+ /** Mode 1 with 2048 bytes sector size. */
+ VDREGIONDATAFORM_MODE1_2048,
+ /** Mode 1 with 2352 bytes sector size. */
+ VDREGIONDATAFORM_MODE1_2352,
+ /** Mode 1 with 0 bytes sector size (generated by the drive). */
+ VDREGIONDATAFORM_MODE1_0,
+ /** XA Mode with 2336 bytes sector size. */
+ VDREGIONDATAFORM_XA_2336,
+ /** XA Mode with 2352 bytes sector size. */
+ VDREGIONDATAFORM_XA_2352,
+ /** XA Mode with 0 bytes sector size (generated by the drive). */
+ VDREGIONDATAFORM_XA_0,
+ /** Mode 2 with 2336 bytes sector size. */
+ VDREGIONDATAFORM_MODE2_2336,
+ /** Mode 2 with 2352 bytes sector size. */
+ VDREGIONDATAFORM_MODE2_2352,
+ /** Mode 2 with 0 bytes sector size (generated by the drive). */
+ VDREGIONDATAFORM_MODE2_0
+} VDREGIONDATAFORM;
+/** Pointer to a region data form. */
+typedef VDREGIONDATAFORM *PVDREGIONDATAFORM;
+/** Pointer to a const region data form. */
+typedef const VDREGIONDATAFORM PCVDREGIONDATAFORM;
+
+/**
+ * Disk region metadata forms known to us.
+ */
+typedef enum VDREGIONMETADATAFORM
+{
+ /** Invalid metadata form. */
+ VDREGIONMETADATAFORM_INVALID = 0,
+ /** No metadata assined to the region. */
+ VDREGIONMETADATAFORM_NONE,
+ /** Raw metadata, no standardized format. */
+ VDREGIONMETADATAFORM_RAW
+} VDREGIONMETADATAFORM;
+/** Pointer to a region metadata form. */
+typedef VDREGIONMETADATAFORM *PVDREGIONMETADATAFORM;
+/** Pointer to a const region metadata form. */
+typedef const VDREGIONMETADATAFORM PCVDREGIONMETADATAFORM;
+
+/**
+ * Disk region descriptor.
+ */
+typedef struct VDREGIONDESC
+{
+ /** Start of the region in bytes or LBA number (depending on the flag in the
+ * list header). */
+ uint64_t offRegion;
+ /** Overall size of the region in bytes or number of blocks (depending on the
+ * flag in the list header). */
+ uint64_t cRegionBlocksOrBytes;
+ /** Size of one block in bytes, containing user and metadata. */
+ uint64_t cbBlock;
+ /** User data form of the block. */
+ VDREGIONDATAFORM enmDataForm;
+ /** Metadata form of the block. */
+ VDREGIONMETADATAFORM enmMetadataForm;
+ /** Size of the data block in bytes. */
+ uint64_t cbData;
+ /** Size of the metadata in a block in bytes. */
+ uint64_t cbMetadata;
+} VDREGIONDESC;
+/** Pointer to a region descriptor. */
+typedef VDREGIONDESC *PVDREGIONDESC;
+/** Pointer to a constant region descriptor. */
+typedef const VDREGIONDESC *PCVDREGIONDESC;
+
+/**
+ * Disk region list.
+ */
+typedef struct VDREGIONLIST
+{
+ /** Flags valid for the region list. */
+ uint32_t fFlags;
+ /** Number of regions in the descriptor array. */
+ uint32_t cRegions;
+ /** Region descriptors - variable in size. */
+ VDREGIONDESC aRegions[RT_FLEXIBLE_ARRAY_NESTED];
+} VDREGIONLIST;
+/** Pointer to a region list. */
+typedef VDREGIONLIST *PVDREGIONLIST;
+/** Pointer to a constant region list. */
+typedef const VDREGIONLIST *PCVDREGIONLIST;
+/** Pointer to a region list pointer. */
+typedef PVDREGIONLIST *PPVDREGIONLIST;
+
+/** @name Valid region list flags.
+ * @{
+ */
+/** When set the region start offset and size are given in numbers of blocks
+ * instead of byte offsets and sizes. */
+#define VD_REGION_LIST_F_LOC_SIZE_BLOCKS RT_BIT_32(0)
+/** Mask of all valid flags. */
+#define VD_REGION_LIST_F_VALID (VD_REGION_LIST_F_LOC_SIZE_BLOCKS)
+/** @} */
+
+#endif /* !VBOX_INCLUDED_vdmedia_h */
+
diff --git a/include/VBox/version.h b/include/VBox/version.h
new file mode 100644
index 00000000..256e3a0c
--- /dev/null
+++ b/include/VBox/version.h
@@ -0,0 +1,166 @@
+/** @file
+ * VBox Version Management.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_version_h
+#define VBOX_INCLUDED_version_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+/* 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 /* !VBOX_INCLUDED_version_h */
+
diff --git a/include/VBox/vmm/Makefile.kup b/include/VBox/vmm/Makefile.kup
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/include/VBox/vmm/Makefile.kup
diff --git a/include/VBox/vmm/apic.h b/include/VBox/vmm/apic.h
new file mode 100644
index 00000000..6e9c3673
--- /dev/null
+++ b/include/VBox/vmm/apic.h
@@ -0,0 +1,107 @@
+/** @file
+ * APIC - Advanced Programmable Interrupt Controller.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vmm_apic_h
+#define VBOX_INCLUDED_vmm_apic_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/types.h>
+#include <VBox/apic.h>
+struct PDMDEVREGCB;
+
+/** @defgroup grp_apic The local APIC VMM API
+ * @ingroup grp_vmm
+ * @{
+ */
+
+RT_C_DECLS_BEGIN
+
+#ifdef VBOX_INCLUDED_vmm_pdmdev_h
+extern const PDMDEVREG g_DeviceAPIC;
+#endif
+
+/* These functions are exported as they are called from external modules (recompiler). */
+VMMDECL(void) APICUpdatePendingInterrupts(PVMCPUCC pVCpu);
+VMMDECL(int) APICGetTpr(PCVMCPUCC pVCpu, uint8_t *pu8Tpr, bool *pfPending, uint8_t *pu8PendingIntr);
+VMMDECL(int) APICSetTpr(PVMCPUCC pVCpu, uint8_t u8Tpr);
+
+/* These functions are VMM internal. */
+VMM_INT_DECL(bool) APICIsEnabled(PCVMCPUCC pVCpu);
+VMM_INT_DECL(bool) APICGetHighestPendingInterrupt(PVMCPUCC pVCpu, uint8_t *pu8PendingIntr);
+VMM_INT_DECL(bool) APICQueueInterruptToService(PVMCPUCC pVCpu, uint8_t u8PendingIntr);
+VMM_INT_DECL(void) APICDequeueInterruptFromService(PVMCPUCC pVCpu, uint8_t u8PendingIntr);
+VMM_INT_DECL(VBOXSTRICTRC) APICReadMsr(PVMCPUCC pVCpu, uint32_t u32Reg, uint64_t *pu64Value);
+VMM_INT_DECL(VBOXSTRICTRC) APICWriteMsr(PVMCPUCC pVCpu, uint32_t u32Reg, uint64_t u64Value);
+VMM_INT_DECL(int) APICGetTimerFreq(PVMCC pVM, uint64_t *pu64Value);
+VMM_INT_DECL(VBOXSTRICTRC) APICLocalInterrupt(PVMCPUCC pVCpu, uint8_t u8Pin, uint8_t u8Level, int rcRZ);
+VMM_INT_DECL(uint64_t) APICGetBaseMsrNoCheck(PCVMCPUCC pVCpu);
+VMM_INT_DECL(VBOXSTRICTRC) APICGetBaseMsr(PVMCPUCC pVCpu, uint64_t *pu64Value);
+VMM_INT_DECL(int) APICSetBaseMsr(PVMCPUCC pVCpu, uint64_t u64BaseMsr);
+VMM_INT_DECL(int) APICGetInterrupt(PVMCPUCC pVCpu, uint8_t *pu8Vector, uint32_t *pu32TagSrc);
+VMM_INT_DECL(int) APICBusDeliver(PVMCC pVM, uint8_t uDest, uint8_t uDestMode, uint8_t uDeliveryMode, uint8_t uVector,
+ uint8_t uPolarity, uint8_t uTriggerMode, uint32_t uTagSrc);
+VMM_INT_DECL(int) APICGetApicPageForCpu(PCVMCPUCC pVCpu, PRTHCPHYS pHCPhys, PRTR0PTR pR0Ptr, PRTR3PTR pR3Ptr);
+
+/** @name Hyper-V interface (Ring-3 and all-context API).
+ * @{ */
+#ifdef IN_RING3
+VMMR3_INT_DECL(void) APICR3HvSetCompatMode(PVM pVM, bool fHyperVCompatMode);
+#endif
+VMM_INT_DECL(void) APICHvSendInterrupt(PVMCPUCC pVCpu, uint8_t uVector, bool fAutoEoi, XAPICTRIGGERMODE enmTriggerMode);
+VMM_INT_DECL(VBOXSTRICTRC) APICHvSetTpr(PVMCPUCC pVCpu, uint8_t uTpr);
+VMM_INT_DECL(uint8_t) APICHvGetTpr(PVMCPUCC pVCpu);
+VMM_INT_DECL(VBOXSTRICTRC) APICHvSetIcr(PVMCPUCC pVCpu, uint64_t uIcr);
+VMM_INT_DECL(uint64_t) APICHvGetIcr(PVMCPUCC pVCpu);
+VMM_INT_DECL(VBOXSTRICTRC) APICHvSetEoi(PVMCPUCC pVCpu, uint32_t uEoi);
+/** @} */
+
+#ifdef IN_RING3
+/** @defgroup grp_apic_r3 The APIC Host Context Ring-3 API
+ * @{
+ */
+VMMR3_INT_DECL(int) APICR3RegisterDevice(struct PDMDEVREGCB *pCallbacks);
+VMMR3_INT_DECL(void) APICR3InitIpi(PVMCPU pVCpu);
+VMMR3_INT_DECL(void) APICR3HvEnable(PVM pVM);
+/** @} */
+#endif /* IN_RING3 */
+
+RT_C_DECLS_END
+
+/** @} */
+
+#endif /* !VBOX_INCLUDED_vmm_apic_h */
+
diff --git a/include/VBox/vmm/cfgm.h b/include/VBox/vmm/cfgm.h
new file mode 100644
index 00000000..7a84dd94
--- /dev/null
+++ b/include/VBox/vmm/cfgm.h
@@ -0,0 +1,245 @@
+/** @file
+ * CFGM - Configuration Manager.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vmm_cfgm_h
+#define VBOX_INCLUDED_vmm_cfgm_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/types.h>
+#include <iprt/stdarg.h>
+
+/** @defgroup grp_cfgm The Configuration Manager API
+ * @ingroup grp_vmm
+ * @{
+ */
+
+/**
+ * Configuration manager value type.
+ */
+typedef enum CFGMVALUETYPE
+{
+ /** Integer value. */
+ CFGMVALUETYPE_INTEGER = 1,
+ /** String value. */
+ CFGMVALUETYPE_STRING,
+ /** Bytestring value. */
+ CFGMVALUETYPE_BYTES,
+ /** Password value, same as String but hides the content in dump. */
+ CFGMVALUETYPE_PASSWORD
+} CFGMVALUETYPE;
+/** Pointer to configuration manager property type. */
+typedef CFGMVALUETYPE *PCFGMVALUETYPE;
+
+
+
+RT_C_DECLS_BEGIN
+
+#ifdef IN_RING3
+/** @defgroup grp_cfgm_r3 The CFGM Host Context Ring-3 API
+ * @{
+ */
+
+typedef enum CFGMCONFIGTYPE
+{
+ /** pvConfig points to nothing, use defaults. */
+ CFGMCONFIGTYPE_NONE = 0,
+ /** pvConfig points to a IMachine interface. */
+ CFGMCONFIGTYPE_IMACHINE
+} CFGMCONFIGTYPE;
+
+
+/**
+ * CFGM init callback for constructing the configuration tree.
+ *
+ * This is called from the emulation thread, and the one interfacing the VM
+ * can make any necessary per-thread initializations at this point.
+ *
+ * @returns VBox status code.
+ * @param pUVM The user mode VM handle.
+ * @param pVM The cross context VM structure.
+ * @param pVMM The VMM R3 vtable.
+ * @param pvUser The argument supplied to VMR3Create().
+ */
+typedef DECLCALLBACKTYPE(int, FNCFGMCONSTRUCTOR,(PUVM pUVM, PVM pVM, PCVMMR3VTABLE pVMM, void *pvUser));
+/** Pointer to a FNCFGMCONSTRUCTOR(). */
+typedef FNCFGMCONSTRUCTOR *PFNCFGMCONSTRUCTOR;
+
+VMMR3DECL(int) CFGMR3Init(PVM pVM, PFNCFGMCONSTRUCTOR pfnCFGMConstructor, void *pvUser);
+VMMR3DECL(int) CFGMR3Term(PVM pVM);
+VMMR3DECL(int) CFGMR3ConstructDefaultTree(PVM pVM);
+
+VMMR3DECL(PCFGMNODE) CFGMR3CreateTree(PUVM pUVM);
+VMMR3DECL(int) CFGMR3DestroyTree(PCFGMNODE pRoot);
+VMMR3DECL(void) CFGMR3Dump(PCFGMNODE pRoot);
+VMMR3DECL(int) CFGMR3DuplicateSubTree(PCFGMNODE pRoot, PCFGMNODE *ppCopy);
+VMMR3DECL(int) CFGMR3ReplaceSubTree(PCFGMNODE pRoot, PCFGMNODE pNewRoot);
+VMMR3DECL(int) CFGMR3InsertSubTree(PCFGMNODE pNode, const char *pszName, PCFGMNODE pSubTree, PCFGMNODE *ppChild);
+VMMR3DECL(int) CFGMR3InsertNode(PCFGMNODE pNode, const char *pszName, PCFGMNODE *ppChild);
+VMMR3DECL(int) CFGMR3InsertNodeF(PCFGMNODE pNode, PCFGMNODE *ppChild,
+ const char *pszNameFormat, ...) RT_IPRT_FORMAT_ATTR(3, 4);
+VMMR3DECL(int) CFGMR3InsertNodeFV(PCFGMNODE pNode, PCFGMNODE *ppChild,
+ const char *pszNameFormat, va_list Args) RT_IPRT_FORMAT_ATTR(3, 0);
+VMMR3DECL(void) CFGMR3SetRestrictedRoot(PCFGMNODE pNode);
+VMMR3DECL(void) CFGMR3RemoveNode(PCFGMNODE pNode);
+VMMR3DECL(int) CFGMR3InsertInteger(PCFGMNODE pNode, const char *pszName, uint64_t u64Integer);
+VMMR3DECL(int) CFGMR3InsertString(PCFGMNODE pNode, const char *pszName, const char *pszString);
+VMMR3DECL(int) CFGMR3InsertStringN(PCFGMNODE pNode, const char *pszName, const char *pszString, size_t cchString);
+VMMR3DECL(int) CFGMR3InsertStringF(PCFGMNODE pNode, const char *pszName,
+ const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(3, 4);
+VMMR3DECL(int) CFGMR3InsertStringFV(PCFGMNODE pNode, const char *pszName,
+ const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(3, 0);
+VMMR3DECL(int) CFGMR3InsertStringW(PCFGMNODE pNode, const char *pszName, PCRTUTF16 pwszValue);
+VMMR3DECL(int) CFGMR3InsertBytes(PCFGMNODE pNode, const char *pszName, const void *pvBytes, size_t cbBytes);
+VMMR3DECL(int) CFGMR3InsertPassword(PCFGMNODE pNode, const char *pszName, const char *pszString);
+VMMR3DECL(int) CFGMR3InsertPasswordN(PCFGMNODE pNode, const char *pszName, const char *pszString, size_t cchString);
+VMMR3DECL(int) CFGMR3InsertValue(PCFGMNODE pNode, PCFGMLEAF pValue);
+VMMR3DECL(int) CFGMR3RemoveValue(PCFGMNODE pNode, const char *pszName);
+
+/** @name CFGMR3CopyTree flags.
+ * @{ */
+/** Reserved value disposition \#0. */
+#define CFGM_COPY_FLAGS_RESERVED_VALUE_DISP_0 UINT32_C(0x00000000)
+/** Reserved value disposition \#1. */
+#define CFGM_COPY_FLAGS_RESERVED_VALUE_DISP_1 UINT32_C(0x00000001)
+/** Replace exiting values. */
+#define CFGM_COPY_FLAGS_REPLACE_VALUES UINT32_C(0x00000002)
+/** Ignore exiting values. */
+#define CFGM_COPY_FLAGS_IGNORE_EXISTING_VALUES UINT32_C(0x00000003)
+/** Value disposition mask. */
+#define CFGM_COPY_FLAGS_VALUE_DISP_MASK UINT32_C(0x00000003)
+
+/** Replace exiting keys. */
+#define CFGM_COPY_FLAGS_RESERVED_KEY_DISP UINT32_C(0x00000000)
+/** Replace exiting keys. */
+#define CFGM_COPY_FLAGS_MERGE_KEYS UINT32_C(0x00000010)
+/** Replace exiting keys. */
+#define CFGM_COPY_FLAGS_REPLACE_KEYS UINT32_C(0x00000020)
+/** Ignore existing keys. */
+#define CFGM_COPY_FLAGS_IGNORE_EXISTING_KEYS UINT32_C(0x00000030)
+/** Key disposition. */
+#define CFGM_COPY_FLAGS_KEY_DISP_MASK UINT32_C(0x00000030)
+/** @} */
+VMMR3DECL(int) CFGMR3CopyTree(PCFGMNODE pDstTree, PCFGMNODE pSrcTree, uint32_t fFlags);
+
+VMMR3DECL(bool) CFGMR3Exists( PCFGMNODE pNode, const char *pszName);
+VMMR3DECL(int) CFGMR3QueryType( PCFGMNODE pNode, const char *pszName, PCFGMVALUETYPE penmType);
+VMMR3DECL(int) CFGMR3QuerySize( PCFGMNODE pNode, const char *pszName, size_t *pcb);
+VMMR3DECL(int) CFGMR3QueryInteger( PCFGMNODE pNode, const char *pszName, uint64_t *pu64);
+VMMR3DECL(int) CFGMR3QueryIntegerDef( PCFGMNODE pNode, const char *pszName, uint64_t *pu64, uint64_t u64Def);
+VMMR3DECL(int) CFGMR3QueryString( PCFGMNODE pNode, const char *pszName, char *pszString, size_t cchString);
+VMMR3DECL(int) CFGMR3QueryStringDef( PCFGMNODE pNode, const char *pszName, char *pszString, size_t cchString, const char *pszDef);
+VMMR3DECL(int) CFGMR3QueryPassword( PCFGMNODE pNode, const char *pszName, char *pszString, size_t cchString);
+VMMR3DECL(int) CFGMR3QueryPasswordDef( PCFGMNODE pNode, const char *pszName, char *pszString, size_t cchString, const char *pszDef);
+VMMR3DECL(int) CFGMR3QueryBytes( PCFGMNODE pNode, const char *pszName, void *pvData, size_t cbData);
+
+
+/** @name Helpers
+ * @{
+ */
+VMMR3DECL(int) CFGMR3QueryU64( PCFGMNODE pNode, const char *pszName, uint64_t *pu64);
+VMMR3DECL(int) CFGMR3QueryU64Def( PCFGMNODE pNode, const char *pszName, uint64_t *pu64, uint64_t u64Def);
+VMMR3DECL(int) CFGMR3QueryS64( PCFGMNODE pNode, const char *pszName, int64_t *pi64);
+VMMR3DECL(int) CFGMR3QueryS64Def( PCFGMNODE pNode, const char *pszName, int64_t *pi64, int64_t i64Def);
+VMMR3DECL(int) CFGMR3QueryU32( PCFGMNODE pNode, const char *pszName, uint32_t *pu32);
+VMMR3DECL(int) CFGMR3QueryU32Def( PCFGMNODE pNode, const char *pszName, uint32_t *pu32, uint32_t u32Def);
+VMMR3DECL(int) CFGMR3QueryS32( PCFGMNODE pNode, const char *pszName, int32_t *pi32);
+VMMR3DECL(int) CFGMR3QueryS32Def( PCFGMNODE pNode, const char *pszName, int32_t *pi32, int32_t i32Def);
+VMMR3DECL(int) CFGMR3QueryU16( PCFGMNODE pNode, const char *pszName, uint16_t *pu16);
+VMMR3DECL(int) CFGMR3QueryU16Def( PCFGMNODE pNode, const char *pszName, uint16_t *pu16, uint16_t u16Def);
+VMMR3DECL(int) CFGMR3QueryS16( PCFGMNODE pNode, const char *pszName, int16_t *pi16);
+VMMR3DECL(int) CFGMR3QueryS16Def( PCFGMNODE pNode, const char *pszName, int16_t *pi16, int16_t i16Def);
+VMMR3DECL(int) CFGMR3QueryU8( PCFGMNODE pNode, const char *pszName, uint8_t *pu8);
+VMMR3DECL(int) CFGMR3QueryU8Def( PCFGMNODE pNode, const char *pszName, uint8_t *pu8, uint8_t u8Def);
+VMMR3DECL(int) CFGMR3QueryS8( PCFGMNODE pNode, const char *pszName, int8_t *pi8);
+VMMR3DECL(int) CFGMR3QueryS8Def( PCFGMNODE pNode, const char *pszName, int8_t *pi8, int8_t i8Def);
+VMMR3DECL(int) CFGMR3QueryBool( PCFGMNODE pNode, const char *pszName, bool *pf);
+VMMR3DECL(int) CFGMR3QueryBoolDef( PCFGMNODE pNode, const char *pszName, bool *pf, bool fDef);
+VMMR3DECL(int) CFGMR3QueryPort( PCFGMNODE pNode, const char *pszName, PRTIOPORT pPort);
+VMMR3DECL(int) CFGMR3QueryPortDef( PCFGMNODE pNode, const char *pszName, PRTIOPORT pPort, RTIOPORT PortDef);
+VMMR3DECL(int) CFGMR3QueryUInt( PCFGMNODE pNode, const char *pszName, unsigned int *pu);
+VMMR3DECL(int) CFGMR3QueryUIntDef( PCFGMNODE pNode, const char *pszName, unsigned int *pu, unsigned int uDef);
+VMMR3DECL(int) CFGMR3QuerySInt( PCFGMNODE pNode, const char *pszName, signed int *pi);
+VMMR3DECL(int) CFGMR3QuerySIntDef( PCFGMNODE pNode, const char *pszName, signed int *pi, signed int iDef);
+VMMR3DECL(int) CFGMR3QueryGCPtr( PCFGMNODE pNode, const char *pszName, PRTGCPTR pGCPtr);
+VMMR3DECL(int) CFGMR3QueryGCPtrDef( PCFGMNODE pNode, const char *pszName, PRTGCPTR pGCPtr, RTGCPTR GCPtrDef);
+VMMR3DECL(int) CFGMR3QueryGCPtrU( PCFGMNODE pNode, const char *pszName, PRTGCUINTPTR pGCPtr);
+VMMR3DECL(int) CFGMR3QueryGCPtrUDef( PCFGMNODE pNode, const char *pszName, PRTGCUINTPTR pGCPtr, RTGCUINTPTR GCPtrDef);
+VMMR3DECL(int) CFGMR3QueryGCPtrS( PCFGMNODE pNode, const char *pszName, PRTGCINTPTR pGCPtr);
+VMMR3DECL(int) CFGMR3QueryGCPtrSDef( PCFGMNODE pNode, const char *pszName, PRTGCINTPTR pGCPtr, RTGCINTPTR GCPtrDef);
+VMMR3DECL(int) CFGMR3QueryStringAlloc( PCFGMNODE pNode, const char *pszName, char **ppszString);
+VMMR3DECL(int) CFGMR3QueryStringAllocDef(PCFGMNODE pNode, const char *pszName, char **ppszString, const char *pszDef);
+
+/** @} */
+
+/** @name Tree Navigation and Enumeration.
+ * @{
+ */
+VMMR3DECL(PCFGMNODE) CFGMR3GetRoot(PVM pVM);
+VMMR3DECL(PCFGMNODE) CFGMR3GetRootU(PUVM pUVM);
+VMMR3DECL(PCFGMNODE) CFGMR3GetParent(PCFGMNODE pNode);
+VMMR3DECL(PCFGMNODE) CFGMR3GetParentEx(PVM pVM, PCFGMNODE pNode);
+VMMR3DECL(PCFGMNODE) CFGMR3GetChild(PCFGMNODE pNode, const char *pszPath);
+VMMR3DECL(PCFGMNODE) CFGMR3GetChildF(PCFGMNODE pNode, const char *pszPathFormat, ...) RT_IPRT_FORMAT_ATTR(2, 3);
+VMMR3DECL(PCFGMNODE) CFGMR3GetChildFV(PCFGMNODE pNode, const char *pszPathFormat, va_list Args) RT_IPRT_FORMAT_ATTR(3, 0);
+VMMR3DECL(PCFGMNODE) CFGMR3GetFirstChild(PCFGMNODE pNode);
+VMMR3DECL(PCFGMNODE) CFGMR3GetNextChild(PCFGMNODE pCur);
+VMMR3DECL(int) CFGMR3GetName(PCFGMNODE pCur, char *pszName, size_t cchName);
+VMMR3DECL(size_t) CFGMR3GetNameLen(PCFGMNODE pCur);
+VMMR3DECL(bool) CFGMR3AreChildrenValid(PCFGMNODE pNode, const char *pszzValid);
+VMMR3DECL(PCFGMLEAF) CFGMR3GetFirstValue(PCFGMNODE pCur);
+VMMR3DECL(PCFGMLEAF) CFGMR3GetNextValue(PCFGMLEAF pCur);
+VMMR3DECL(int) CFGMR3GetValueName(PCFGMLEAF pCur, char *pszName, size_t cchName);
+VMMR3DECL(size_t) CFGMR3GetValueNameLen(PCFGMLEAF pCur);
+VMMR3DECL(CFGMVALUETYPE) CFGMR3GetValueType(PCFGMLEAF pCur);
+VMMR3DECL(bool) CFGMR3AreValuesValid(PCFGMNODE pNode, const char *pszzValid);
+VMMR3DECL(int) CFGMR3ValidateConfig(PCFGMNODE pNode, const char *pszNode,
+ const char *pszValidValues, const char *pszValidNodes,
+ const char *pszWho, uint32_t uInstance);
+
+/** @} */
+
+
+/** @} */
+#endif /* IN_RING3 */
+
+
+RT_C_DECLS_END
+
+/** @} */
+
+#endif /* !VBOX_INCLUDED_vmm_cfgm_h */
+
diff --git a/include/VBox/vmm/cpuidcall.h b/include/VBox/vmm/cpuidcall.h
new file mode 100644
index 00000000..8bcdb8da
--- /dev/null
+++ b/include/VBox/vmm/cpuidcall.h
@@ -0,0 +1,107 @@
+/** @file
+ * VM - The Virtual Machine, CPU Host Call Interface (AMD64 & x86 only).
+ *
+ * @note cpuidcall.mac is generated from this file by running 'kmk incs' in the root.
+ */
+
+/*
+ * Copyright (C) 2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vmm_cpuidcall_h
+#define VBOX_INCLUDED_vmm_cpuidcall_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/types.h>
+
+
+/** @defgroup grp_cpuidcall VBox CPUID Host Call Interface (AMD64 & x86)
+ *
+ * This describes an interface using CPUID for calling the host from within the
+ * VM. This is chiefly intended for nested VM debugging at present and is
+ * therefore disabled by default.
+ *
+ * @{ */
+
+/** Fixed EAX value for all requests (big-endian 'VBox'). */
+#define VBOX_CPUID_REQ_EAX_FIXED UINT32_C(0x56426f78)
+/** Fixed portion of ECX for all requests. */
+#define VBOX_CPUID_REQ_ECX_FIXED UINT32_C(0xc0de0000)
+/** Fixed portion of ECX for all requests. */
+#define VBOX_CPUID_REQ_ECX_FIXED_MASK UINT32_C(0xffff0000)
+/** Function part of ECX for requests. */
+#define VBOX_CPUID_REQ_ECX_FN_MASK UINT32_C(0x0000ffff)
+
+/** Generic ECX return value. */
+#define VBOX_CPUID_RESP_GEN_ECX UINT32_C(0x19410612)
+/** Generic EDX return value. */
+#define VBOX_CPUID_RESP_GEN_EDX UINT32_C(0x19400412)
+/** Generic EBX return value. */
+#define VBOX_CPUID_RESP_GEN_EBX UINT32_C(0x19450508)
+
+/** @name Function \#1: Interface ID check and max function.
+ *
+ * Input: EDX & EBX content is unused and ignored. Best set to zero.
+ *
+ * Result: EAX:EDX:EBX forms the little endian string "VBox RuleZ!\0".
+ * ECX contains the max function number acccepted.
+ * @{ */
+#define VBOX_CPUID_FN_ID UINT32_C(0x0001)
+#define VBOX_CPUID_RESP_ID_EAX UINT32_C(0x786f4256)
+#define VBOX_CPUID_RESP_ID_EDX UINT32_C(0x6c755220)
+#define VBOX_CPUID_RESP_ID_EBX UINT32_C(0x00215A65)
+#define VBOX_CPUID_RESP_ID_ECX UINT32_C(0x00000002)
+/** @} */
+
+/** Function \#2: Write string to host Log.
+ *
+ * Input: EDX gives the number of bytes to log (max 2MB).
+ * EBX indicates the log to write to: 0 for debug, 1 for release.
+ * RSI is the FLAT pointer to the UTF-8 string to log.
+ *
+ * Output: EAX contains IPRT status code. ECX, EDX and EBX are set to the
+ * generic their response values (VBOX_CPUID_RESP_GEN_XXX). RSI is
+ * advanced EDX bytes on success.
+ *
+ * Except: May raise \#PF when reading the string. RSI and EDX is then be
+ * updated to the point where the page fault triggered, allowing paging
+ * in of logging buffer and such like.
+ *
+ * @note Buffer is not accessed if the target logger isn't enabled.
+ */
+#define VBOX_CPUID_FN_LOG UINT32_C(0x0002)
+
+
+/** @} */
+
+#endif /* !VBOX_INCLUDED_vmm_cpuidcall_h */
+
diff --git a/include/VBox/vmm/cpuidcall.mac b/include/VBox/vmm/cpuidcall.mac
new file mode 100644
index 00000000..5965550c
--- /dev/null
+++ b/include/VBox/vmm/cpuidcall.mac
@@ -0,0 +1,55 @@
+;; @file
+; VM - The Virtual Machine, CPU Host Call Interface (AMD64 & x86 only).
+;
+; Automatically generated by various.sed. DO NOT EDIT!
+;
+
+;
+; Copyright (C) 2022 Oracle and/or its affiliates.
+;
+; This file is part of VirtualBox base platform packages, as
+; available from https://www.virtualbox.org.
+;
+; This program is free software; you can redistribute it and/or
+; modify it under the terms of the GNU General Public License
+; as published by the Free Software Foundation, in version 3 of the
+; License.
+;
+; This program is distributed in the hope that it will be useful, but
+; WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with this program; if not, see <https://www.gnu.org/licenses>.
+;
+; The contents of this file may alternatively be used under the terms
+; of the Common Development and Distribution License Version 1.0
+; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+; in the VirtualBox 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.
+;
+; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+;
+
+%ifndef VBOX_INCLUDED_vmm_cpuidcall_h
+%define VBOX_INCLUDED_vmm_cpuidcall_h
+%ifndef RT_WITHOUT_PRAGMA_ONCE
+%endif
+%define VBOX_CPUID_REQ_EAX_FIXED 0x56426f78
+%define VBOX_CPUID_REQ_ECX_FIXED 0xc0de0000
+%define VBOX_CPUID_REQ_ECX_FIXED_MASK 0xffff0000
+%define VBOX_CPUID_REQ_ECX_FN_MASK 0x0000ffff
+%define VBOX_CPUID_RESP_GEN_ECX 0x19410612
+%define VBOX_CPUID_RESP_GEN_EDX 0x19400412
+%define VBOX_CPUID_RESP_GEN_EBX 0x19450508
+%define VBOX_CPUID_FN_ID 0x0001
+%define VBOX_CPUID_RESP_ID_EAX 0x786f4256
+%define VBOX_CPUID_RESP_ID_EDX 0x6c755220
+%define VBOX_CPUID_RESP_ID_EBX 0x00215A65
+%define VBOX_CPUID_RESP_ID_ECX 0x00000002
+%define VBOX_CPUID_FN_LOG 0x0002
+%endif
diff --git a/include/VBox/vmm/cpum.h b/include/VBox/vmm/cpum.h
new file mode 100644
index 00000000..1f5f28e3
--- /dev/null
+++ b/include/VBox/vmm/cpum.h
@@ -0,0 +1,3248 @@
+/** @file
+ * CPUM - CPU Monitor(/ Manager).
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vmm_cpum_h
+#define VBOX_INCLUDED_vmm_cpum_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/x86.h>
+#include <VBox/types.h>
+#include <VBox/vmm/cpumctx.h>
+#include <VBox/vmm/stam.h>
+#include <VBox/vmm/vmapi.h>
+#include <VBox/vmm/hm_svm.h>
+#include <VBox/vmm/hm_vmx.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_cpum The CPU Monitor / Manager API
+ * @ingroup grp_vmm
+ * @{
+ */
+
+/**
+ * CPUID feature to set or clear.
+ */
+typedef enum CPUMCPUIDFEATURE
+{
+ CPUMCPUIDFEATURE_INVALID = 0,
+ /** The APIC feature bit. (Std+Ext)
+ * Note! There is a per-cpu flag for masking this CPUID feature bit when the
+ * APICBASE.ENABLED bit is zero. So, this feature is only set/cleared
+ * at VM construction time like all the others. This didn't used to be
+ * that way, this is new with 5.1. */
+ CPUMCPUIDFEATURE_APIC,
+ /** The sysenter/sysexit feature bit. (Std) */
+ CPUMCPUIDFEATURE_SEP,
+ /** The SYSCALL/SYSEXIT feature bit (64 bits mode only for Intel CPUs). (Ext) */
+ CPUMCPUIDFEATURE_SYSCALL,
+ /** The PAE feature bit. (Std+Ext) */
+ CPUMCPUIDFEATURE_PAE,
+ /** The NX feature bit. (Ext) */
+ CPUMCPUIDFEATURE_NX,
+ /** The LAHF/SAHF feature bit (64 bits mode only). (Ext) */
+ CPUMCPUIDFEATURE_LAHF,
+ /** The LONG MODE feature bit. (Ext) */
+ CPUMCPUIDFEATURE_LONG_MODE,
+ /** The x2APIC feature bit. (Std) */
+ CPUMCPUIDFEATURE_X2APIC,
+ /** The RDTSCP feature bit. (Ext) */
+ CPUMCPUIDFEATURE_RDTSCP,
+ /** The Hypervisor Present bit. (Std) */
+ CPUMCPUIDFEATURE_HVP,
+ /** The speculation control feature bits. (StExt) */
+ CPUMCPUIDFEATURE_SPEC_CTRL,
+ /** 32bit hackishness. */
+ CPUMCPUIDFEATURE_32BIT_HACK = 0x7fffffff
+} CPUMCPUIDFEATURE;
+
+/**
+ * CPU Vendor.
+ */
+typedef enum CPUMCPUVENDOR
+{
+ CPUMCPUVENDOR_INVALID = 0,
+ CPUMCPUVENDOR_INTEL,
+ CPUMCPUVENDOR_AMD,
+ CPUMCPUVENDOR_VIA,
+ CPUMCPUVENDOR_CYRIX,
+ CPUMCPUVENDOR_SHANGHAI,
+ CPUMCPUVENDOR_HYGON,
+ CPUMCPUVENDOR_UNKNOWN,
+ /** 32bit hackishness. */
+ CPUMCPUVENDOR_32BIT_HACK = 0x7fffffff
+} CPUMCPUVENDOR;
+
+
+/**
+ * X86 and AMD64 CPU microarchitectures and in processor generations.
+ *
+ * @remarks The separation here is sometimes a little bit too finely grained,
+ * and the differences is more like processor generation than micro
+ * arch. This can be useful, so we'll provide functions for getting at
+ * more coarse grained info.
+ */
+typedef enum CPUMMICROARCH
+{
+ kCpumMicroarch_Invalid = 0,
+
+ kCpumMicroarch_Intel_First,
+
+ kCpumMicroarch_Intel_8086 = kCpumMicroarch_Intel_First,
+ kCpumMicroarch_Intel_80186,
+ kCpumMicroarch_Intel_80286,
+ kCpumMicroarch_Intel_80386,
+ kCpumMicroarch_Intel_80486,
+ kCpumMicroarch_Intel_P5,
+
+ kCpumMicroarch_Intel_P6_Core_Atom_First,
+ kCpumMicroarch_Intel_P6 = kCpumMicroarch_Intel_P6_Core_Atom_First,
+ kCpumMicroarch_Intel_P6_II,
+ kCpumMicroarch_Intel_P6_III,
+
+ kCpumMicroarch_Intel_P6_M_Banias,
+ kCpumMicroarch_Intel_P6_M_Dothan,
+ kCpumMicroarch_Intel_Core_Yonah, /**< Core, also known as Enhanced Pentium M. */
+
+ kCpumMicroarch_Intel_Core2_First,
+ kCpumMicroarch_Intel_Core2_Merom = kCpumMicroarch_Intel_Core2_First, /**< 65nm, Merom/Conroe/Kentsfield/Tigerton */
+ kCpumMicroarch_Intel_Core2_Penryn, /**< 45nm, Penryn/Wolfdale/Yorkfield/Harpertown */
+ kCpumMicroarch_Intel_Core2_End,
+
+ kCpumMicroarch_Intel_Core7_First,
+ kCpumMicroarch_Intel_Core7_Nehalem = kCpumMicroarch_Intel_Core7_First,
+ kCpumMicroarch_Intel_Core7_Westmere,
+ kCpumMicroarch_Intel_Core7_SandyBridge,
+ kCpumMicroarch_Intel_Core7_IvyBridge,
+ kCpumMicroarch_Intel_Core7_Haswell,
+ kCpumMicroarch_Intel_Core7_Broadwell,
+ kCpumMicroarch_Intel_Core7_Skylake,
+ kCpumMicroarch_Intel_Core7_KabyLake,
+ kCpumMicroarch_Intel_Core7_CoffeeLake,
+ kCpumMicroarch_Intel_Core7_WhiskeyLake,
+ kCpumMicroarch_Intel_Core7_CascadeLake,
+ kCpumMicroarch_Intel_Core7_CannonLake, /**< Limited 10nm. */
+ kCpumMicroarch_Intel_Core7_CometLake, /**< 10th gen, 14nm desktop + high power mobile. */
+ kCpumMicroarch_Intel_Core7_IceLake, /**< 10th gen, 10nm mobile and some Xeons. Actually 'Sunny Cove' march. */
+ kCpumMicroarch_Intel_Core7_SunnyCove = kCpumMicroarch_Intel_Core7_IceLake,
+ kCpumMicroarch_Intel_Core7_RocketLake, /**< 11th gen, 14nm desktop + high power mobile. Aka 'Cypress Cove', backport of 'Willow Cove' to 14nm. */
+ kCpumMicroarch_Intel_Core7_CypressCove = kCpumMicroarch_Intel_Core7_RocketLake,
+ kCpumMicroarch_Intel_Core7_TigerLake, /**< 11th gen, 10nm mobile. Actually 'Willow Cove' march. */
+ kCpumMicroarch_Intel_Core7_WillowCove = kCpumMicroarch_Intel_Core7_TigerLake,
+ kCpumMicroarch_Intel_Core7_AlderLake, /**< 12th gen, 10nm all platforms(?). */
+ kCpumMicroarch_Intel_Core7_SapphireRapids, /**< 12th? gen, 10nm server? */
+ kCpumMicroarch_Intel_Core7_End,
+
+ kCpumMicroarch_Intel_Atom_First,
+ kCpumMicroarch_Intel_Atom_Bonnell = kCpumMicroarch_Intel_Atom_First,
+ kCpumMicroarch_Intel_Atom_Lincroft, /**< Second generation bonnell (44nm). */
+ kCpumMicroarch_Intel_Atom_Saltwell, /**< 32nm shrink of Bonnell. */
+ kCpumMicroarch_Intel_Atom_Silvermont, /**< 22nm */
+ kCpumMicroarch_Intel_Atom_Airmount, /**< 14nm */
+ kCpumMicroarch_Intel_Atom_Goldmont, /**< 14nm */
+ kCpumMicroarch_Intel_Atom_GoldmontPlus, /**< 14nm */
+ kCpumMicroarch_Intel_Atom_Unknown,
+ kCpumMicroarch_Intel_Atom_End,
+
+
+ kCpumMicroarch_Intel_Phi_First,
+ kCpumMicroarch_Intel_Phi_KnightsFerry = kCpumMicroarch_Intel_Phi_First,
+ kCpumMicroarch_Intel_Phi_KnightsCorner,
+ kCpumMicroarch_Intel_Phi_KnightsLanding,
+ kCpumMicroarch_Intel_Phi_KnightsHill,
+ kCpumMicroarch_Intel_Phi_KnightsMill,
+ kCpumMicroarch_Intel_Phi_End,
+
+ kCpumMicroarch_Intel_P6_Core_Atom_End,
+
+ kCpumMicroarch_Intel_NB_First,
+ kCpumMicroarch_Intel_NB_Willamette = kCpumMicroarch_Intel_NB_First, /**< 180nm */
+ kCpumMicroarch_Intel_NB_Northwood, /**< 130nm */
+ kCpumMicroarch_Intel_NB_Prescott, /**< 90nm */
+ kCpumMicroarch_Intel_NB_Prescott2M, /**< 90nm */
+ kCpumMicroarch_Intel_NB_CedarMill, /**< 65nm */
+ kCpumMicroarch_Intel_NB_Gallatin, /**< 90nm Xeon, Pentium 4 Extreme Edition ("Emergency Edition"). */
+ kCpumMicroarch_Intel_NB_Unknown,
+ kCpumMicroarch_Intel_NB_End,
+
+ kCpumMicroarch_Intel_Unknown,
+ kCpumMicroarch_Intel_End,
+
+ kCpumMicroarch_AMD_First,
+ kCpumMicroarch_AMD_Am286 = kCpumMicroarch_AMD_First,
+ kCpumMicroarch_AMD_Am386,
+ kCpumMicroarch_AMD_Am486,
+ kCpumMicroarch_AMD_Am486Enh, /**< Covers Am5x86 as well. */
+ kCpumMicroarch_AMD_K5,
+ kCpumMicroarch_AMD_K6,
+
+ kCpumMicroarch_AMD_K7_First,
+ kCpumMicroarch_AMD_K7_Palomino = kCpumMicroarch_AMD_K7_First,
+ kCpumMicroarch_AMD_K7_Spitfire,
+ kCpumMicroarch_AMD_K7_Thunderbird,
+ kCpumMicroarch_AMD_K7_Morgan,
+ kCpumMicroarch_AMD_K7_Thoroughbred,
+ kCpumMicroarch_AMD_K7_Barton,
+ kCpumMicroarch_AMD_K7_Unknown,
+ kCpumMicroarch_AMD_K7_End,
+
+ kCpumMicroarch_AMD_K8_First,
+ kCpumMicroarch_AMD_K8_130nm = kCpumMicroarch_AMD_K8_First, /**< 130nm Clawhammer, Sledgehammer, Newcastle, Paris, Odessa, Dublin */
+ kCpumMicroarch_AMD_K8_90nm, /**< 90nm shrink */
+ kCpumMicroarch_AMD_K8_90nm_DualCore, /**< 90nm with two cores. */
+ kCpumMicroarch_AMD_K8_90nm_AMDV, /**< 90nm with AMD-V (usually) and two cores (usually). */
+ kCpumMicroarch_AMD_K8_65nm, /**< 65nm shrink. */
+ kCpumMicroarch_AMD_K8_End,
+
+ kCpumMicroarch_AMD_K10,
+ kCpumMicroarch_AMD_K10_Lion,
+ kCpumMicroarch_AMD_K10_Llano,
+ kCpumMicroarch_AMD_Bobcat,
+ kCpumMicroarch_AMD_Jaguar,
+
+ kCpumMicroarch_AMD_15h_First,
+ kCpumMicroarch_AMD_15h_Bulldozer = kCpumMicroarch_AMD_15h_First,
+ kCpumMicroarch_AMD_15h_Piledriver,
+ kCpumMicroarch_AMD_15h_Steamroller, /**< Yet to be released, might have different family. */
+ kCpumMicroarch_AMD_15h_Excavator, /**< Yet to be released, might have different family. */
+ kCpumMicroarch_AMD_15h_Unknown,
+ kCpumMicroarch_AMD_15h_End,
+
+ kCpumMicroarch_AMD_16h_First,
+ kCpumMicroarch_AMD_16h_End,
+
+ kCpumMicroarch_AMD_Zen_First,
+ kCpumMicroarch_AMD_Zen_Ryzen = kCpumMicroarch_AMD_Zen_First,
+ kCpumMicroarch_AMD_Zen_End,
+
+ kCpumMicroarch_AMD_Unknown,
+ kCpumMicroarch_AMD_End,
+
+ kCpumMicroarch_Hygon_First,
+ kCpumMicroarch_Hygon_Dhyana = kCpumMicroarch_Hygon_First,
+ kCpumMicroarch_Hygon_Unknown,
+ kCpumMicroarch_Hygon_End,
+
+ kCpumMicroarch_VIA_First,
+ kCpumMicroarch_Centaur_C6 = kCpumMicroarch_VIA_First,
+ kCpumMicroarch_Centaur_C2,
+ kCpumMicroarch_Centaur_C3,
+ kCpumMicroarch_VIA_C3_M2,
+ kCpumMicroarch_VIA_C3_C5A, /**< 180nm Samuel - Cyrix III, C3, 1GigaPro. */
+ kCpumMicroarch_VIA_C3_C5B, /**< 150nm Samuel 2 - Cyrix III, C3, 1GigaPro, Eden ESP, XP 2000+. */
+ kCpumMicroarch_VIA_C3_C5C, /**< 130nm Ezra - C3, Eden ESP. */
+ kCpumMicroarch_VIA_C3_C5N, /**< 130nm Ezra-T - C3. */
+ kCpumMicroarch_VIA_C3_C5XL, /**< 130nm Nehemiah - C3, Eden ESP, Eden-N. */
+ kCpumMicroarch_VIA_C3_C5P, /**< 130nm Nehemiah+ - C3. */
+ kCpumMicroarch_VIA_C7_C5J, /**< 90nm Esther - C7, C7-D, C7-M, Eden, Eden ULV. */
+ kCpumMicroarch_VIA_Isaiah,
+ kCpumMicroarch_VIA_Unknown,
+ kCpumMicroarch_VIA_End,
+
+ kCpumMicroarch_Shanghai_First,
+ kCpumMicroarch_Shanghai_Wudaokou = kCpumMicroarch_Shanghai_First,
+ kCpumMicroarch_Shanghai_Unknown,
+ kCpumMicroarch_Shanghai_End,
+
+ kCpumMicroarch_Cyrix_First,
+ kCpumMicroarch_Cyrix_5x86 = kCpumMicroarch_Cyrix_First,
+ kCpumMicroarch_Cyrix_M1,
+ kCpumMicroarch_Cyrix_MediaGX,
+ kCpumMicroarch_Cyrix_MediaGXm,
+ kCpumMicroarch_Cyrix_M2,
+ kCpumMicroarch_Cyrix_Unknown,
+ kCpumMicroarch_Cyrix_End,
+
+ kCpumMicroarch_NEC_First,
+ kCpumMicroarch_NEC_V20 = kCpumMicroarch_NEC_First,
+ kCpumMicroarch_NEC_V30,
+ kCpumMicroarch_NEC_End,
+
+ kCpumMicroarch_Unknown,
+
+ kCpumMicroarch_32BitHack = 0x7fffffff
+} CPUMMICROARCH;
+
+
+/** Predicate macro for catching netburst CPUs. */
+#define CPUMMICROARCH_IS_INTEL_NETBURST(a_enmMicroarch) \
+ ((a_enmMicroarch) >= kCpumMicroarch_Intel_NB_First && (a_enmMicroarch) <= kCpumMicroarch_Intel_NB_End)
+
+/** Predicate macro for catching Core7 CPUs. */
+#define CPUMMICROARCH_IS_INTEL_CORE7(a_enmMicroarch) \
+ ((a_enmMicroarch) >= kCpumMicroarch_Intel_Core7_First && (a_enmMicroarch) <= kCpumMicroarch_Intel_Core7_End)
+
+/** Predicate macro for catching Core 2 CPUs. */
+#define CPUMMICROARCH_IS_INTEL_CORE2(a_enmMicroarch) \
+ ((a_enmMicroarch) >= kCpumMicroarch_Intel_Core2_First && (a_enmMicroarch) <= kCpumMicroarch_Intel_Core2_End)
+
+/** Predicate macro for catching Atom CPUs, Silvermont and upwards. */
+#define CPUMMICROARCH_IS_INTEL_SILVERMONT_PLUS(a_enmMicroarch) \
+ ((a_enmMicroarch) >= kCpumMicroarch_Intel_Atom_Silvermont && (a_enmMicroarch) <= kCpumMicroarch_Intel_Atom_End)
+
+/** Predicate macro for catching AMD Family OFh CPUs (aka K8). */
+#define CPUMMICROARCH_IS_AMD_FAM_0FH(a_enmMicroarch) \
+ ((a_enmMicroarch) >= kCpumMicroarch_AMD_K8_First && (a_enmMicroarch) <= kCpumMicroarch_AMD_K8_End)
+
+/** Predicate macro for catching AMD Family 10H CPUs (aka K10). */
+#define CPUMMICROARCH_IS_AMD_FAM_10H(a_enmMicroarch) ((a_enmMicroarch) == kCpumMicroarch_AMD_K10)
+
+/** Predicate macro for catching AMD Family 11H CPUs (aka Lion). */
+#define CPUMMICROARCH_IS_AMD_FAM_11H(a_enmMicroarch) ((a_enmMicroarch) == kCpumMicroarch_AMD_K10_Lion)
+
+/** Predicate macro for catching AMD Family 12H CPUs (aka Llano). */
+#define CPUMMICROARCH_IS_AMD_FAM_12H(a_enmMicroarch) ((a_enmMicroarch) == kCpumMicroarch_AMD_K10_Llano)
+
+/** Predicate macro for catching AMD Family 14H CPUs (aka Bobcat). */
+#define CPUMMICROARCH_IS_AMD_FAM_14H(a_enmMicroarch) ((a_enmMicroarch) == kCpumMicroarch_AMD_Bobcat)
+
+/** Predicate macro for catching AMD Family 15H CPUs (bulldozer and it's
+ * decendants). */
+#define CPUMMICROARCH_IS_AMD_FAM_15H(a_enmMicroarch) \
+ ((a_enmMicroarch) >= kCpumMicroarch_AMD_15h_First && (a_enmMicroarch) <= kCpumMicroarch_AMD_15h_End)
+
+/** Predicate macro for catching AMD Family 16H CPUs. */
+#define CPUMMICROARCH_IS_AMD_FAM_16H(a_enmMicroarch) \
+ ((a_enmMicroarch) >= kCpumMicroarch_AMD_16h_First && (a_enmMicroarch) <= kCpumMicroarch_AMD_16h_End)
+
+/** Predicate macro for catching AMD Zen Family CPUs. */
+#define CPUMMICROARCH_IS_AMD_FAM_ZEN(a_enmMicroarch) \
+ ((a_enmMicroarch) >= kCpumMicroarch_AMD_Zen_First && (a_enmMicroarch) <= kCpumMicroarch_AMD_Zen_End)
+
+
+/**
+ * CPUID leaf.
+ *
+ * @remarks This structure is used by the patch manager and is therefore
+ * more or less set in stone.
+ */
+typedef struct CPUMCPUIDLEAF
+{
+ /** The leaf number. */
+ uint32_t uLeaf;
+ /** The sub-leaf number. */
+ uint32_t uSubLeaf;
+ /** Sub-leaf mask. This is 0 when sub-leaves aren't used. */
+ uint32_t fSubLeafMask;
+
+ /** The EAX value. */
+ uint32_t uEax;
+ /** The EBX value. */
+ uint32_t uEbx;
+ /** The ECX value. */
+ uint32_t uEcx;
+ /** The EDX value. */
+ uint32_t uEdx;
+
+ /** Flags. */
+ uint32_t fFlags;
+} CPUMCPUIDLEAF;
+#ifndef VBOX_FOR_DTRACE_LIB
+AssertCompileSize(CPUMCPUIDLEAF, 32);
+#endif
+/** Pointer to a CPUID leaf. */
+typedef CPUMCPUIDLEAF *PCPUMCPUIDLEAF;
+/** Pointer to a const CPUID leaf. */
+typedef CPUMCPUIDLEAF const *PCCPUMCPUIDLEAF;
+
+/** @name CPUMCPUIDLEAF::fFlags
+ * @{ */
+/** Indicates working intel leaf 0xb where the lower 8 ECX bits are not modified
+ * and EDX containing the extended APIC ID. */
+#define CPUMCPUIDLEAF_F_INTEL_TOPOLOGY_SUBLEAVES RT_BIT_32(0)
+/** The leaf contains an APIC ID that needs changing to that of the current CPU. */
+#define CPUMCPUIDLEAF_F_CONTAINS_APIC_ID RT_BIT_32(1)
+/** The leaf contains an OSXSAVE which needs individual handling on each CPU. */
+#define CPUMCPUIDLEAF_F_CONTAINS_OSXSAVE RT_BIT_32(2)
+/** The leaf contains an APIC feature bit which is tied to APICBASE.EN. */
+#define CPUMCPUIDLEAF_F_CONTAINS_APIC RT_BIT_32(3)
+/** Mask of the valid flags. */
+#define CPUMCPUIDLEAF_F_VALID_MASK UINT32_C(0xf)
+/** @} */
+
+/**
+ * Method used to deal with unknown CPUID leaves.
+ * @remarks Used in patch code.
+ */
+typedef enum CPUMUNKNOWNCPUID
+{
+ /** Invalid zero value. */
+ CPUMUNKNOWNCPUID_INVALID = 0,
+ /** Use given default values (DefCpuId). */
+ CPUMUNKNOWNCPUID_DEFAULTS,
+ /** Return the last standard leaf.
+ * Intel Sandy Bridge has been observed doing this. */
+ CPUMUNKNOWNCPUID_LAST_STD_LEAF,
+ /** Return the last standard leaf, with ecx observed.
+ * Intel Sandy Bridge has been observed doing this. */
+ CPUMUNKNOWNCPUID_LAST_STD_LEAF_WITH_ECX,
+ /** The register values are passed thru unmodified. */
+ CPUMUNKNOWNCPUID_PASSTHRU,
+ /** End of valid value. */
+ CPUMUNKNOWNCPUID_END,
+ /** Ensure 32-bit type. */
+ CPUMUNKNOWNCPUID_32BIT_HACK = 0x7fffffff
+} CPUMUNKNOWNCPUID;
+/** Pointer to unknown CPUID leaf method. */
+typedef CPUMUNKNOWNCPUID *PCPUMUNKNOWNCPUID;
+
+
+/**
+ * The register set returned by a CPUID operation.
+ */
+typedef struct CPUMCPUID
+{
+ uint32_t uEax;
+ uint32_t uEbx;
+ uint32_t uEcx;
+ uint32_t uEdx;
+} CPUMCPUID;
+/** Pointer to a CPUID leaf. */
+typedef CPUMCPUID *PCPUMCPUID;
+/** Pointer to a const CPUID leaf. */
+typedef const CPUMCPUID *PCCPUMCPUID;
+
+
+/**
+ * MSR read functions.
+ */
+typedef enum CPUMMSRRDFN
+{
+ /** Invalid zero value. */
+ kCpumMsrRdFn_Invalid = 0,
+ /** Return the CPUMMSRRANGE::uValue. */
+ kCpumMsrRdFn_FixedValue,
+ /** Alias to the MSR range starting at the MSR given by
+ * CPUMMSRRANGE::uValue. Must be used in pair with
+ * kCpumMsrWrFn_MsrAlias. */
+ kCpumMsrRdFn_MsrAlias,
+ /** Write only register, GP all read attempts. */
+ kCpumMsrRdFn_WriteOnly,
+
+ kCpumMsrRdFn_Ia32P5McAddr,
+ kCpumMsrRdFn_Ia32P5McType,
+ kCpumMsrRdFn_Ia32TimestampCounter,
+ kCpumMsrRdFn_Ia32PlatformId, /**< Takes real CPU value for reference. */
+ kCpumMsrRdFn_Ia32ApicBase,
+ kCpumMsrRdFn_Ia32FeatureControl,
+ kCpumMsrRdFn_Ia32BiosSignId, /**< Range value returned. */
+ kCpumMsrRdFn_Ia32SmmMonitorCtl,
+ kCpumMsrRdFn_Ia32PmcN,
+ kCpumMsrRdFn_Ia32MonitorFilterLineSize,
+ kCpumMsrRdFn_Ia32MPerf,
+ kCpumMsrRdFn_Ia32APerf,
+ kCpumMsrRdFn_Ia32MtrrCap, /**< Takes real CPU value for reference. */
+ kCpumMsrRdFn_Ia32MtrrPhysBaseN, /**< Takes register number. */
+ kCpumMsrRdFn_Ia32MtrrPhysMaskN, /**< Takes register number. */
+ kCpumMsrRdFn_Ia32MtrrFixed, /**< Takes CPUMCPU offset. */
+ kCpumMsrRdFn_Ia32MtrrDefType,
+ kCpumMsrRdFn_Ia32Pat,
+ kCpumMsrRdFn_Ia32SysEnterCs,
+ kCpumMsrRdFn_Ia32SysEnterEsp,
+ kCpumMsrRdFn_Ia32SysEnterEip,
+ kCpumMsrRdFn_Ia32McgCap,
+ kCpumMsrRdFn_Ia32McgStatus,
+ kCpumMsrRdFn_Ia32McgCtl,
+ kCpumMsrRdFn_Ia32DebugCtl,
+ kCpumMsrRdFn_Ia32SmrrPhysBase,
+ kCpumMsrRdFn_Ia32SmrrPhysMask,
+ kCpumMsrRdFn_Ia32PlatformDcaCap,
+ kCpumMsrRdFn_Ia32CpuDcaCap,
+ kCpumMsrRdFn_Ia32Dca0Cap,
+ kCpumMsrRdFn_Ia32PerfEvtSelN, /**< Range value indicates the register number. */
+ kCpumMsrRdFn_Ia32PerfStatus, /**< Range value returned. */
+ kCpumMsrRdFn_Ia32PerfCtl, /**< Range value returned. */
+ kCpumMsrRdFn_Ia32FixedCtrN, /**< Takes register number of start of range. */
+ kCpumMsrRdFn_Ia32PerfCapabilities, /**< Takes reference value. */
+ kCpumMsrRdFn_Ia32FixedCtrCtrl,
+ kCpumMsrRdFn_Ia32PerfGlobalStatus, /**< Takes reference value. */
+ kCpumMsrRdFn_Ia32PerfGlobalCtrl,
+ kCpumMsrRdFn_Ia32PerfGlobalOvfCtrl,
+ kCpumMsrRdFn_Ia32PebsEnable,
+ kCpumMsrRdFn_Ia32ClockModulation, /**< Range value returned. */
+ kCpumMsrRdFn_Ia32ThermInterrupt, /**< Range value returned. */
+ kCpumMsrRdFn_Ia32ThermStatus, /**< Range value returned. */
+ kCpumMsrRdFn_Ia32Therm2Ctl, /**< Range value returned. */
+ kCpumMsrRdFn_Ia32MiscEnable, /**< Range value returned. */
+ kCpumMsrRdFn_Ia32McCtlStatusAddrMiscN, /**< Takes bank number. */
+ kCpumMsrRdFn_Ia32McNCtl2, /**< Takes register number of start of range. */
+ kCpumMsrRdFn_Ia32DsArea,
+ kCpumMsrRdFn_Ia32TscDeadline,
+ kCpumMsrRdFn_Ia32X2ApicN,
+ kCpumMsrRdFn_Ia32DebugInterface,
+ kCpumMsrRdFn_Ia32VmxBasic, /**< Takes real value as reference. */
+ kCpumMsrRdFn_Ia32VmxPinbasedCtls, /**< Takes real value as reference. */
+ kCpumMsrRdFn_Ia32VmxProcbasedCtls, /**< Takes real value as reference. */
+ kCpumMsrRdFn_Ia32VmxExitCtls, /**< Takes real value as reference. */
+ kCpumMsrRdFn_Ia32VmxEntryCtls, /**< Takes real value as reference. */
+ kCpumMsrRdFn_Ia32VmxMisc, /**< Takes real value as reference. */
+ kCpumMsrRdFn_Ia32VmxCr0Fixed0, /**< Takes real value as reference. */
+ kCpumMsrRdFn_Ia32VmxCr0Fixed1, /**< Takes real value as reference. */
+ kCpumMsrRdFn_Ia32VmxCr4Fixed0, /**< Takes real value as reference. */
+ kCpumMsrRdFn_Ia32VmxCr4Fixed1, /**< Takes real value as reference. */
+ kCpumMsrRdFn_Ia32VmxVmcsEnum, /**< Takes real value as reference. */
+ kCpumMsrRdFn_Ia32VmxProcBasedCtls2, /**< Takes real value as reference. */
+ kCpumMsrRdFn_Ia32VmxEptVpidCap, /**< Takes real value as reference. */
+ kCpumMsrRdFn_Ia32VmxTruePinbasedCtls, /**< Takes real value as reference. */
+ kCpumMsrRdFn_Ia32VmxTrueProcbasedCtls, /**< Takes real value as reference. */
+ kCpumMsrRdFn_Ia32VmxTrueExitCtls, /**< Takes real value as reference. */
+ kCpumMsrRdFn_Ia32VmxTrueEntryCtls, /**< Takes real value as reference. */
+ kCpumMsrRdFn_Ia32VmxVmFunc, /**< Takes real value as reference. */
+ kCpumMsrRdFn_Ia32SpecCtrl,
+ kCpumMsrRdFn_Ia32ArchCapabilities,
+
+ kCpumMsrRdFn_Amd64Efer,
+ kCpumMsrRdFn_Amd64SyscallTarget,
+ kCpumMsrRdFn_Amd64LongSyscallTarget,
+ kCpumMsrRdFn_Amd64CompSyscallTarget,
+ kCpumMsrRdFn_Amd64SyscallFlagMask,
+ kCpumMsrRdFn_Amd64FsBase,
+ kCpumMsrRdFn_Amd64GsBase,
+ kCpumMsrRdFn_Amd64KernelGsBase,
+ kCpumMsrRdFn_Amd64TscAux,
+
+ kCpumMsrRdFn_IntelEblCrPowerOn,
+ kCpumMsrRdFn_IntelI7CoreThreadCount,
+ kCpumMsrRdFn_IntelP4EbcHardPowerOn,
+ kCpumMsrRdFn_IntelP4EbcSoftPowerOn,
+ kCpumMsrRdFn_IntelP4EbcFrequencyId,
+ kCpumMsrRdFn_IntelP6FsbFrequency, /**< Takes real value as reference. */
+ kCpumMsrRdFn_IntelPlatformInfo,
+ kCpumMsrRdFn_IntelFlexRatio, /**< Takes real value as reference. */
+ kCpumMsrRdFn_IntelPkgCStConfigControl,
+ kCpumMsrRdFn_IntelPmgIoCaptureBase,
+ kCpumMsrRdFn_IntelLastBranchFromToN,
+ kCpumMsrRdFn_IntelLastBranchFromN,
+ kCpumMsrRdFn_IntelLastBranchToN,
+ kCpumMsrRdFn_IntelLastBranchTos,
+ kCpumMsrRdFn_IntelBblCrCtl,
+ kCpumMsrRdFn_IntelBblCrCtl3,
+ kCpumMsrRdFn_IntelI7TemperatureTarget, /**< Range value returned. */
+ kCpumMsrRdFn_IntelI7MsrOffCoreResponseN,/**< Takes register number. */
+ kCpumMsrRdFn_IntelI7MiscPwrMgmt,
+ kCpumMsrRdFn_IntelP6CrN,
+ kCpumMsrRdFn_IntelCpuId1FeatureMaskEcdx,
+ kCpumMsrRdFn_IntelCpuId1FeatureMaskEax,
+ kCpumMsrRdFn_IntelCpuId80000001FeatureMaskEcdx,
+ kCpumMsrRdFn_IntelI7SandyAesNiCtl,
+ kCpumMsrRdFn_IntelI7TurboRatioLimit, /**< Returns range value. */
+ kCpumMsrRdFn_IntelI7LbrSelect,
+ kCpumMsrRdFn_IntelI7SandyErrorControl,
+ kCpumMsrRdFn_IntelI7VirtualLegacyWireCap,/**< Returns range value. */
+ kCpumMsrRdFn_IntelI7PowerCtl,
+ kCpumMsrRdFn_IntelI7SandyPebsNumAlt,
+ kCpumMsrRdFn_IntelI7PebsLdLat,
+ kCpumMsrRdFn_IntelI7PkgCnResidencyN, /**< Takes C-state number. */
+ kCpumMsrRdFn_IntelI7CoreCnResidencyN, /**< Takes C-state number. */
+ kCpumMsrRdFn_IntelI7SandyVrCurrentConfig,/**< Takes real value as reference. */
+ kCpumMsrRdFn_IntelI7SandyVrMiscConfig, /**< Takes real value as reference. */
+ kCpumMsrRdFn_IntelI7SandyRaplPowerUnit, /**< Takes real value as reference. */
+ kCpumMsrRdFn_IntelI7SandyPkgCnIrtlN, /**< Takes real value as reference. */
+ kCpumMsrRdFn_IntelI7SandyPkgC2Residency, /**< Takes real value as reference. */
+ kCpumMsrRdFn_IntelI7RaplPkgPowerLimit, /**< Takes real value as reference. */
+ kCpumMsrRdFn_IntelI7RaplPkgEnergyStatus, /**< Takes real value as reference. */
+ kCpumMsrRdFn_IntelI7RaplPkgPerfStatus, /**< Takes real value as reference. */
+ kCpumMsrRdFn_IntelI7RaplPkgPowerInfo, /**< Takes real value as reference. */
+ kCpumMsrRdFn_IntelI7RaplDramPowerLimit, /**< Takes real value as reference. */
+ kCpumMsrRdFn_IntelI7RaplDramEnergyStatus,/**< Takes real value as reference. */
+ kCpumMsrRdFn_IntelI7RaplDramPerfStatus, /**< Takes real value as reference. */
+ kCpumMsrRdFn_IntelI7RaplDramPowerInfo, /**< Takes real value as reference. */
+ kCpumMsrRdFn_IntelI7RaplPp0PowerLimit, /**< Takes real value as reference. */
+ kCpumMsrRdFn_IntelI7RaplPp0EnergyStatus, /**< Takes real value as reference. */
+ kCpumMsrRdFn_IntelI7RaplPp0Policy, /**< Takes real value as reference. */
+ kCpumMsrRdFn_IntelI7RaplPp0PerfStatus, /**< Takes real value as reference. */
+ kCpumMsrRdFn_IntelI7RaplPp1PowerLimit, /**< Takes real value as reference. */
+ kCpumMsrRdFn_IntelI7RaplPp1EnergyStatus, /**< Takes real value as reference. */
+ kCpumMsrRdFn_IntelI7RaplPp1Policy, /**< Takes real value as reference. */
+ kCpumMsrRdFn_IntelI7IvyConfigTdpNominal, /**< Takes real value as reference. */
+ kCpumMsrRdFn_IntelI7IvyConfigTdpLevel1, /**< Takes real value as reference. */
+ kCpumMsrRdFn_IntelI7IvyConfigTdpLevel2, /**< Takes real value as reference. */
+ kCpumMsrRdFn_IntelI7IvyConfigTdpControl,
+ kCpumMsrRdFn_IntelI7IvyTurboActivationRatio,
+ kCpumMsrRdFn_IntelI7UncPerfGlobalCtrl,
+ kCpumMsrRdFn_IntelI7UncPerfGlobalStatus,
+ kCpumMsrRdFn_IntelI7UncPerfGlobalOvfCtrl,
+ kCpumMsrRdFn_IntelI7UncPerfFixedCtrCtrl,
+ kCpumMsrRdFn_IntelI7UncPerfFixedCtr,
+ kCpumMsrRdFn_IntelI7UncCBoxConfig,
+ kCpumMsrRdFn_IntelI7UncArbPerfCtrN,
+ kCpumMsrRdFn_IntelI7UncArbPerfEvtSelN,
+ kCpumMsrRdFn_IntelI7SmiCount,
+ kCpumMsrRdFn_IntelCore2EmttmCrTablesN, /**< Range value returned. */
+ kCpumMsrRdFn_IntelCore2SmmCStMiscInfo,
+ kCpumMsrRdFn_IntelCore1ExtConfig,
+ kCpumMsrRdFn_IntelCore1DtsCalControl,
+ kCpumMsrRdFn_IntelCore2PeciControl,
+ kCpumMsrRdFn_IntelAtSilvCoreC1Recidency,
+
+ kCpumMsrRdFn_P6LastBranchFromIp,
+ kCpumMsrRdFn_P6LastBranchToIp,
+ kCpumMsrRdFn_P6LastIntFromIp,
+ kCpumMsrRdFn_P6LastIntToIp,
+
+ kCpumMsrRdFn_AmdFam15hTscRate,
+ kCpumMsrRdFn_AmdFam15hLwpCfg,
+ kCpumMsrRdFn_AmdFam15hLwpCbAddr,
+ kCpumMsrRdFn_AmdFam10hMc4MiscN,
+ kCpumMsrRdFn_AmdK8PerfCtlN,
+ kCpumMsrRdFn_AmdK8PerfCtrN,
+ kCpumMsrRdFn_AmdK8SysCfg, /**< Range value returned. */
+ kCpumMsrRdFn_AmdK8HwCr,
+ kCpumMsrRdFn_AmdK8IorrBaseN,
+ kCpumMsrRdFn_AmdK8IorrMaskN,
+ kCpumMsrRdFn_AmdK8TopOfMemN,
+ kCpumMsrRdFn_AmdK8NbCfg1,
+ kCpumMsrRdFn_AmdK8McXcptRedir,
+ kCpumMsrRdFn_AmdK8CpuNameN,
+ kCpumMsrRdFn_AmdK8HwThermalCtrl, /**< Range value returned. */
+ kCpumMsrRdFn_AmdK8SwThermalCtrl,
+ kCpumMsrRdFn_AmdK8FidVidControl, /**< Range value returned. */
+ kCpumMsrRdFn_AmdK8FidVidStatus, /**< Range value returned. */
+ kCpumMsrRdFn_AmdK8McCtlMaskN,
+ kCpumMsrRdFn_AmdK8SmiOnIoTrapN,
+ kCpumMsrRdFn_AmdK8SmiOnIoTrapCtlSts,
+ kCpumMsrRdFn_AmdK8IntPendingMessage,
+ kCpumMsrRdFn_AmdK8SmiTriggerIoCycle,
+ kCpumMsrRdFn_AmdFam10hMmioCfgBaseAddr,
+ kCpumMsrRdFn_AmdFam10hTrapCtlMaybe,
+ kCpumMsrRdFn_AmdFam10hPStateCurLimit, /**< Returns range value. */
+ kCpumMsrRdFn_AmdFam10hPStateControl, /**< Returns range value. */
+ kCpumMsrRdFn_AmdFam10hPStateStatus, /**< Returns range value. */
+ kCpumMsrRdFn_AmdFam10hPStateN, /**< Returns range value. This isn't an register index! */
+ kCpumMsrRdFn_AmdFam10hCofVidControl, /**< Returns range value. */
+ kCpumMsrRdFn_AmdFam10hCofVidStatus, /**< Returns range value. */
+ kCpumMsrRdFn_AmdFam10hCStateIoBaseAddr,
+ kCpumMsrRdFn_AmdFam10hCpuWatchdogTimer,
+ kCpumMsrRdFn_AmdK8SmmBase,
+ kCpumMsrRdFn_AmdK8SmmAddr,
+ kCpumMsrRdFn_AmdK8SmmMask,
+ kCpumMsrRdFn_AmdK8VmCr,
+ kCpumMsrRdFn_AmdK8IgnNe,
+ kCpumMsrRdFn_AmdK8SmmCtl,
+ kCpumMsrRdFn_AmdK8VmHSavePa,
+ kCpumMsrRdFn_AmdFam10hVmLockKey,
+ kCpumMsrRdFn_AmdFam10hSmmLockKey,
+ kCpumMsrRdFn_AmdFam10hLocalSmiStatus,
+ kCpumMsrRdFn_AmdFam10hOsVisWrkIdLength,
+ kCpumMsrRdFn_AmdFam10hOsVisWrkStatus,
+ kCpumMsrRdFn_AmdFam16hL2IPerfCtlN,
+ kCpumMsrRdFn_AmdFam16hL2IPerfCtrN,
+ kCpumMsrRdFn_AmdFam15hNorthbridgePerfCtlN,
+ kCpumMsrRdFn_AmdFam15hNorthbridgePerfCtrN,
+ kCpumMsrRdFn_AmdK7MicrocodeCtl, /**< Returns range value. */
+ kCpumMsrRdFn_AmdK7ClusterIdMaybe, /**< Returns range value. */
+ kCpumMsrRdFn_AmdK8CpuIdCtlStd07hEbax,
+ kCpumMsrRdFn_AmdK8CpuIdCtlStd06hEcx,
+ kCpumMsrRdFn_AmdK8CpuIdCtlStd01hEdcx,
+ kCpumMsrRdFn_AmdK8CpuIdCtlExt01hEdcx,
+ kCpumMsrRdFn_AmdK8PatchLevel, /**< Returns range value. */
+ kCpumMsrRdFn_AmdK7DebugStatusMaybe,
+ kCpumMsrRdFn_AmdK7BHTraceBaseMaybe,
+ kCpumMsrRdFn_AmdK7BHTracePtrMaybe,
+ kCpumMsrRdFn_AmdK7BHTraceLimitMaybe,
+ kCpumMsrRdFn_AmdK7HardwareDebugToolCfgMaybe,
+ kCpumMsrRdFn_AmdK7FastFlushCountMaybe,
+ kCpumMsrRdFn_AmdK7NodeId,
+ kCpumMsrRdFn_AmdK7DrXAddrMaskN, /**< Takes register index. */
+ kCpumMsrRdFn_AmdK7Dr0DataMatchMaybe,
+ kCpumMsrRdFn_AmdK7Dr0DataMaskMaybe,
+ kCpumMsrRdFn_AmdK7LoadStoreCfg,
+ kCpumMsrRdFn_AmdK7InstrCacheCfg,
+ kCpumMsrRdFn_AmdK7DataCacheCfg,
+ kCpumMsrRdFn_AmdK7BusUnitCfg,
+ kCpumMsrRdFn_AmdK7DebugCtl2Maybe,
+ kCpumMsrRdFn_AmdFam15hFpuCfg,
+ kCpumMsrRdFn_AmdFam15hDecoderCfg,
+ kCpumMsrRdFn_AmdFam10hBusUnitCfg2,
+ kCpumMsrRdFn_AmdFam15hCombUnitCfg,
+ kCpumMsrRdFn_AmdFam15hCombUnitCfg2,
+ kCpumMsrRdFn_AmdFam15hCombUnitCfg3,
+ kCpumMsrRdFn_AmdFam15hExecUnitCfg,
+ kCpumMsrRdFn_AmdFam15hLoadStoreCfg2,
+ kCpumMsrRdFn_AmdFam10hIbsFetchCtl,
+ kCpumMsrRdFn_AmdFam10hIbsFetchLinAddr,
+ kCpumMsrRdFn_AmdFam10hIbsFetchPhysAddr,
+ kCpumMsrRdFn_AmdFam10hIbsOpExecCtl,
+ kCpumMsrRdFn_AmdFam10hIbsOpRip,
+ kCpumMsrRdFn_AmdFam10hIbsOpData,
+ kCpumMsrRdFn_AmdFam10hIbsOpData2,
+ kCpumMsrRdFn_AmdFam10hIbsOpData3,
+ kCpumMsrRdFn_AmdFam10hIbsDcLinAddr,
+ kCpumMsrRdFn_AmdFam10hIbsDcPhysAddr,
+ kCpumMsrRdFn_AmdFam10hIbsCtl,
+ kCpumMsrRdFn_AmdFam14hIbsBrTarget,
+
+ kCpumMsrRdFn_Gim,
+
+ /** End of valid MSR read function indexes. */
+ kCpumMsrRdFn_End
+} CPUMMSRRDFN;
+
+/**
+ * MSR write functions.
+ */
+typedef enum CPUMMSRWRFN
+{
+ /** Invalid zero value. */
+ kCpumMsrWrFn_Invalid = 0,
+ /** Writes are ignored, the fWrGpMask is observed though. */
+ kCpumMsrWrFn_IgnoreWrite,
+ /** Writes cause GP(0) to be raised, the fWrGpMask should be UINT64_MAX. */
+ kCpumMsrWrFn_ReadOnly,
+ /** Alias to the MSR range starting at the MSR given by
+ * CPUMMSRRANGE::uValue. Must be used in pair with
+ * kCpumMsrRdFn_MsrAlias. */
+ kCpumMsrWrFn_MsrAlias,
+
+ kCpumMsrWrFn_Ia32P5McAddr,
+ kCpumMsrWrFn_Ia32P5McType,
+ kCpumMsrWrFn_Ia32TimestampCounter,
+ kCpumMsrWrFn_Ia32ApicBase,
+ kCpumMsrWrFn_Ia32FeatureControl,
+ kCpumMsrWrFn_Ia32BiosSignId,
+ kCpumMsrWrFn_Ia32BiosUpdateTrigger,
+ kCpumMsrWrFn_Ia32SmmMonitorCtl,
+ kCpumMsrWrFn_Ia32PmcN,
+ kCpumMsrWrFn_Ia32MonitorFilterLineSize,
+ kCpumMsrWrFn_Ia32MPerf,
+ kCpumMsrWrFn_Ia32APerf,
+ kCpumMsrWrFn_Ia32MtrrPhysBaseN, /**< Takes register number. */
+ kCpumMsrWrFn_Ia32MtrrPhysMaskN, /**< Takes register number. */
+ kCpumMsrWrFn_Ia32MtrrFixed, /**< Takes CPUMCPU offset. */
+ kCpumMsrWrFn_Ia32MtrrDefType,
+ kCpumMsrWrFn_Ia32Pat,
+ kCpumMsrWrFn_Ia32SysEnterCs,
+ kCpumMsrWrFn_Ia32SysEnterEsp,
+ kCpumMsrWrFn_Ia32SysEnterEip,
+ kCpumMsrWrFn_Ia32McgStatus,
+ kCpumMsrWrFn_Ia32McgCtl,
+ kCpumMsrWrFn_Ia32DebugCtl,
+ kCpumMsrWrFn_Ia32SmrrPhysBase,
+ kCpumMsrWrFn_Ia32SmrrPhysMask,
+ kCpumMsrWrFn_Ia32PlatformDcaCap,
+ kCpumMsrWrFn_Ia32Dca0Cap,
+ kCpumMsrWrFn_Ia32PerfEvtSelN, /**< Range value indicates the register number. */
+ kCpumMsrWrFn_Ia32PerfStatus,
+ kCpumMsrWrFn_Ia32PerfCtl,
+ kCpumMsrWrFn_Ia32FixedCtrN, /**< Takes register number of start of range. */
+ kCpumMsrWrFn_Ia32PerfCapabilities,
+ kCpumMsrWrFn_Ia32FixedCtrCtrl,
+ kCpumMsrWrFn_Ia32PerfGlobalStatus,
+ kCpumMsrWrFn_Ia32PerfGlobalCtrl,
+ kCpumMsrWrFn_Ia32PerfGlobalOvfCtrl,
+ kCpumMsrWrFn_Ia32PebsEnable,
+ kCpumMsrWrFn_Ia32ClockModulation,
+ kCpumMsrWrFn_Ia32ThermInterrupt,
+ kCpumMsrWrFn_Ia32ThermStatus,
+ kCpumMsrWrFn_Ia32Therm2Ctl,
+ kCpumMsrWrFn_Ia32MiscEnable,
+ kCpumMsrWrFn_Ia32McCtlStatusAddrMiscN, /**< Takes bank number. */
+ kCpumMsrWrFn_Ia32McNCtl2, /**< Takes register number of start of range. */
+ kCpumMsrWrFn_Ia32DsArea,
+ kCpumMsrWrFn_Ia32TscDeadline,
+ kCpumMsrWrFn_Ia32X2ApicN,
+ kCpumMsrWrFn_Ia32DebugInterface,
+ kCpumMsrWrFn_Ia32SpecCtrl,
+ kCpumMsrWrFn_Ia32PredCmd,
+ kCpumMsrWrFn_Ia32FlushCmd,
+
+ kCpumMsrWrFn_Amd64Efer,
+ kCpumMsrWrFn_Amd64SyscallTarget,
+ kCpumMsrWrFn_Amd64LongSyscallTarget,
+ kCpumMsrWrFn_Amd64CompSyscallTarget,
+ kCpumMsrWrFn_Amd64SyscallFlagMask,
+ kCpumMsrWrFn_Amd64FsBase,
+ kCpumMsrWrFn_Amd64GsBase,
+ kCpumMsrWrFn_Amd64KernelGsBase,
+ kCpumMsrWrFn_Amd64TscAux,
+ kCpumMsrWrFn_IntelEblCrPowerOn,
+ kCpumMsrWrFn_IntelP4EbcHardPowerOn,
+ kCpumMsrWrFn_IntelP4EbcSoftPowerOn,
+ kCpumMsrWrFn_IntelP4EbcFrequencyId,
+ kCpumMsrWrFn_IntelFlexRatio,
+ kCpumMsrWrFn_IntelPkgCStConfigControl,
+ kCpumMsrWrFn_IntelPmgIoCaptureBase,
+ kCpumMsrWrFn_IntelLastBranchFromToN,
+ kCpumMsrWrFn_IntelLastBranchFromN,
+ kCpumMsrWrFn_IntelLastBranchToN,
+ kCpumMsrWrFn_IntelLastBranchTos,
+ kCpumMsrWrFn_IntelBblCrCtl,
+ kCpumMsrWrFn_IntelBblCrCtl3,
+ kCpumMsrWrFn_IntelI7TemperatureTarget,
+ kCpumMsrWrFn_IntelI7MsrOffCoreResponseN, /**< Takes register number. */
+ kCpumMsrWrFn_IntelI7MiscPwrMgmt,
+ kCpumMsrWrFn_IntelP6CrN,
+ kCpumMsrWrFn_IntelCpuId1FeatureMaskEcdx,
+ kCpumMsrWrFn_IntelCpuId1FeatureMaskEax,
+ kCpumMsrWrFn_IntelCpuId80000001FeatureMaskEcdx,
+ kCpumMsrWrFn_IntelI7SandyAesNiCtl,
+ kCpumMsrWrFn_IntelI7TurboRatioLimit,
+ kCpumMsrWrFn_IntelI7LbrSelect,
+ kCpumMsrWrFn_IntelI7SandyErrorControl,
+ kCpumMsrWrFn_IntelI7PowerCtl,
+ kCpumMsrWrFn_IntelI7SandyPebsNumAlt,
+ kCpumMsrWrFn_IntelI7PebsLdLat,
+ kCpumMsrWrFn_IntelI7SandyVrCurrentConfig,
+ kCpumMsrWrFn_IntelI7SandyVrMiscConfig,
+ kCpumMsrWrFn_IntelI7SandyRaplPowerUnit, /**< R/O but found writable bits on a Silvermont CPU here. */
+ kCpumMsrWrFn_IntelI7SandyPkgCnIrtlN,
+ kCpumMsrWrFn_IntelI7SandyPkgC2Residency, /**< R/O but found writable bits on a Silvermont CPU here. */
+ kCpumMsrWrFn_IntelI7RaplPkgPowerLimit,
+ kCpumMsrWrFn_IntelI7RaplDramPowerLimit,
+ kCpumMsrWrFn_IntelI7RaplPp0PowerLimit,
+ kCpumMsrWrFn_IntelI7RaplPp0Policy,
+ kCpumMsrWrFn_IntelI7RaplPp1PowerLimit,
+ kCpumMsrWrFn_IntelI7RaplPp1Policy,
+ kCpumMsrWrFn_IntelI7IvyConfigTdpControl,
+ kCpumMsrWrFn_IntelI7IvyTurboActivationRatio,
+ kCpumMsrWrFn_IntelI7UncPerfGlobalCtrl,
+ kCpumMsrWrFn_IntelI7UncPerfGlobalStatus,
+ kCpumMsrWrFn_IntelI7UncPerfGlobalOvfCtrl,
+ kCpumMsrWrFn_IntelI7UncPerfFixedCtrCtrl,
+ kCpumMsrWrFn_IntelI7UncPerfFixedCtr,
+ kCpumMsrWrFn_IntelI7UncArbPerfCtrN,
+ kCpumMsrWrFn_IntelI7UncArbPerfEvtSelN,
+ kCpumMsrWrFn_IntelCore2EmttmCrTablesN,
+ kCpumMsrWrFn_IntelCore2SmmCStMiscInfo,
+ kCpumMsrWrFn_IntelCore1ExtConfig,
+ kCpumMsrWrFn_IntelCore1DtsCalControl,
+ kCpumMsrWrFn_IntelCore2PeciControl,
+
+ kCpumMsrWrFn_P6LastIntFromIp,
+ kCpumMsrWrFn_P6LastIntToIp,
+
+ kCpumMsrWrFn_AmdFam15hTscRate,
+ kCpumMsrWrFn_AmdFam15hLwpCfg,
+ kCpumMsrWrFn_AmdFam15hLwpCbAddr,
+ kCpumMsrWrFn_AmdFam10hMc4MiscN,
+ kCpumMsrWrFn_AmdK8PerfCtlN,
+ kCpumMsrWrFn_AmdK8PerfCtrN,
+ kCpumMsrWrFn_AmdK8SysCfg,
+ kCpumMsrWrFn_AmdK8HwCr,
+ kCpumMsrWrFn_AmdK8IorrBaseN,
+ kCpumMsrWrFn_AmdK8IorrMaskN,
+ kCpumMsrWrFn_AmdK8TopOfMemN,
+ kCpumMsrWrFn_AmdK8NbCfg1,
+ kCpumMsrWrFn_AmdK8McXcptRedir,
+ kCpumMsrWrFn_AmdK8CpuNameN,
+ kCpumMsrWrFn_AmdK8HwThermalCtrl,
+ kCpumMsrWrFn_AmdK8SwThermalCtrl,
+ kCpumMsrWrFn_AmdK8FidVidControl,
+ kCpumMsrWrFn_AmdK8McCtlMaskN,
+ kCpumMsrWrFn_AmdK8SmiOnIoTrapN,
+ kCpumMsrWrFn_AmdK8SmiOnIoTrapCtlSts,
+ kCpumMsrWrFn_AmdK8IntPendingMessage,
+ kCpumMsrWrFn_AmdK8SmiTriggerIoCycle,
+ kCpumMsrWrFn_AmdFam10hMmioCfgBaseAddr,
+ kCpumMsrWrFn_AmdFam10hTrapCtlMaybe,
+ kCpumMsrWrFn_AmdFam10hPStateControl,
+ kCpumMsrWrFn_AmdFam10hPStateStatus,
+ kCpumMsrWrFn_AmdFam10hPStateN,
+ kCpumMsrWrFn_AmdFam10hCofVidControl,
+ kCpumMsrWrFn_AmdFam10hCofVidStatus,
+ kCpumMsrWrFn_AmdFam10hCStateIoBaseAddr,
+ kCpumMsrWrFn_AmdFam10hCpuWatchdogTimer,
+ kCpumMsrWrFn_AmdK8SmmBase,
+ kCpumMsrWrFn_AmdK8SmmAddr,
+ kCpumMsrWrFn_AmdK8SmmMask,
+ kCpumMsrWrFn_AmdK8VmCr,
+ kCpumMsrWrFn_AmdK8IgnNe,
+ kCpumMsrWrFn_AmdK8SmmCtl,
+ kCpumMsrWrFn_AmdK8VmHSavePa,
+ kCpumMsrWrFn_AmdFam10hVmLockKey,
+ kCpumMsrWrFn_AmdFam10hSmmLockKey,
+ kCpumMsrWrFn_AmdFam10hLocalSmiStatus,
+ kCpumMsrWrFn_AmdFam10hOsVisWrkIdLength,
+ kCpumMsrWrFn_AmdFam10hOsVisWrkStatus,
+ kCpumMsrWrFn_AmdFam16hL2IPerfCtlN,
+ kCpumMsrWrFn_AmdFam16hL2IPerfCtrN,
+ kCpumMsrWrFn_AmdFam15hNorthbridgePerfCtlN,
+ kCpumMsrWrFn_AmdFam15hNorthbridgePerfCtrN,
+ kCpumMsrWrFn_AmdK7MicrocodeCtl,
+ kCpumMsrWrFn_AmdK7ClusterIdMaybe,
+ kCpumMsrWrFn_AmdK8CpuIdCtlStd07hEbax,
+ kCpumMsrWrFn_AmdK8CpuIdCtlStd06hEcx,
+ kCpumMsrWrFn_AmdK8CpuIdCtlStd01hEdcx,
+ kCpumMsrWrFn_AmdK8CpuIdCtlExt01hEdcx,
+ kCpumMsrWrFn_AmdK8PatchLoader,
+ kCpumMsrWrFn_AmdK7DebugStatusMaybe,
+ kCpumMsrWrFn_AmdK7BHTraceBaseMaybe,
+ kCpumMsrWrFn_AmdK7BHTracePtrMaybe,
+ kCpumMsrWrFn_AmdK7BHTraceLimitMaybe,
+ kCpumMsrWrFn_AmdK7HardwareDebugToolCfgMaybe,
+ kCpumMsrWrFn_AmdK7FastFlushCountMaybe,
+ kCpumMsrWrFn_AmdK7NodeId,
+ kCpumMsrWrFn_AmdK7DrXAddrMaskN, /**< Takes register index. */
+ kCpumMsrWrFn_AmdK7Dr0DataMatchMaybe,
+ kCpumMsrWrFn_AmdK7Dr0DataMaskMaybe,
+ kCpumMsrWrFn_AmdK7LoadStoreCfg,
+ kCpumMsrWrFn_AmdK7InstrCacheCfg,
+ kCpumMsrWrFn_AmdK7DataCacheCfg,
+ kCpumMsrWrFn_AmdK7BusUnitCfg,
+ kCpumMsrWrFn_AmdK7DebugCtl2Maybe,
+ kCpumMsrWrFn_AmdFam15hFpuCfg,
+ kCpumMsrWrFn_AmdFam15hDecoderCfg,
+ kCpumMsrWrFn_AmdFam10hBusUnitCfg2,
+ kCpumMsrWrFn_AmdFam15hCombUnitCfg,
+ kCpumMsrWrFn_AmdFam15hCombUnitCfg2,
+ kCpumMsrWrFn_AmdFam15hCombUnitCfg3,
+ kCpumMsrWrFn_AmdFam15hExecUnitCfg,
+ kCpumMsrWrFn_AmdFam15hLoadStoreCfg2,
+ kCpumMsrWrFn_AmdFam10hIbsFetchCtl,
+ kCpumMsrWrFn_AmdFam10hIbsFetchLinAddr,
+ kCpumMsrWrFn_AmdFam10hIbsFetchPhysAddr,
+ kCpumMsrWrFn_AmdFam10hIbsOpExecCtl,
+ kCpumMsrWrFn_AmdFam10hIbsOpRip,
+ kCpumMsrWrFn_AmdFam10hIbsOpData,
+ kCpumMsrWrFn_AmdFam10hIbsOpData2,
+ kCpumMsrWrFn_AmdFam10hIbsOpData3,
+ kCpumMsrWrFn_AmdFam10hIbsDcLinAddr,
+ kCpumMsrWrFn_AmdFam10hIbsDcPhysAddr,
+ kCpumMsrWrFn_AmdFam10hIbsCtl,
+ kCpumMsrWrFn_AmdFam14hIbsBrTarget,
+
+ kCpumMsrWrFn_Gim,
+
+ /** End of valid MSR write function indexes. */
+ kCpumMsrWrFn_End
+} CPUMMSRWRFN;
+
+/**
+ * MSR range.
+ */
+typedef struct CPUMMSRRANGE
+{
+ /** The first MSR. [0] */
+ uint32_t uFirst;
+ /** The last MSR. [4] */
+ uint32_t uLast;
+ /** The read function (CPUMMSRRDFN). [8] */
+ uint16_t enmRdFn;
+ /** The write function (CPUMMSRWRFN). [10] */
+ uint16_t enmWrFn;
+ /** The offset of the 64-bit MSR value relative to the start of CPUMCPU.
+ * UINT16_MAX if not used by the read and write functions. [12] */
+ uint32_t offCpumCpu : 24;
+ /** Reserved for future hacks. [15] */
+ uint32_t fReserved : 8;
+ /** The init/read value. [16]
+ * When enmRdFn is kCpumMsrRdFn_INIT_VALUE, this is the value returned on RDMSR.
+ * offCpumCpu must be UINT16_MAX in that case, otherwise it must be a valid
+ * offset into CPUM. */
+ uint64_t uValue;
+ /** The bits to ignore when writing. [24] */
+ uint64_t fWrIgnMask;
+ /** The bits that will cause a GP(0) when writing. [32]
+ * This is always checked prior to calling the write function. Using
+ * UINT64_MAX effectively marks the MSR as read-only. */
+ uint64_t fWrGpMask;
+ /** The register name, if applicable. [40] */
+ char szName[56];
+
+ /** The number of reads. */
+ STAMCOUNTER cReads;
+ /** The number of writes. */
+ STAMCOUNTER cWrites;
+ /** The number of times ignored bits were written. */
+ STAMCOUNTER cIgnoredBits;
+ /** The number of GPs generated. */
+ STAMCOUNTER cGps;
+} CPUMMSRRANGE;
+#ifndef VBOX_FOR_DTRACE_LIB
+AssertCompileSize(CPUMMSRRANGE, 128);
+#endif
+/** Pointer to an MSR range. */
+typedef CPUMMSRRANGE *PCPUMMSRRANGE;
+/** Pointer to a const MSR range. */
+typedef CPUMMSRRANGE const *PCCPUMMSRRANGE;
+
+
+/**
+ * MSRs which are required while exploding features.
+ */
+typedef struct CPUMMSRS
+{
+ union
+ {
+ VMXMSRS vmx;
+ SVMMSRS svm;
+ } hwvirt;
+} CPUMMSRS;
+/** Pointer to an CPUMMSRS struct. */
+typedef CPUMMSRS *PCPUMMSRS;
+/** Pointer to a const CPUMMSRS struct. */
+typedef CPUMMSRS const *PCCPUMMSRS;
+
+
+/**
+ * CPU features and quirks.
+ * This is mostly exploded CPUID info.
+ */
+typedef struct CPUMFEATURES
+{
+ /** The CPU vendor (CPUMCPUVENDOR). */
+ uint8_t enmCpuVendor;
+ /** The CPU family. */
+ uint8_t uFamily;
+ /** The CPU model. */
+ uint8_t uModel;
+ /** The CPU stepping. */
+ uint8_t uStepping;
+ /** The microarchitecture. */
+#ifndef VBOX_FOR_DTRACE_LIB
+ CPUMMICROARCH enmMicroarch;
+#else
+ uint32_t enmMicroarch;
+#endif
+ /** The maximum physical address width of the CPU. */
+ uint8_t cMaxPhysAddrWidth;
+ /** The maximum linear address width of the CPU. */
+ uint8_t cMaxLinearAddrWidth;
+ /** Max size of the extended state (or FPU state if no XSAVE). */
+ uint16_t cbMaxExtendedState;
+
+ /** Supports MSRs. */
+ uint32_t fMsr : 1;
+ /** Supports the page size extension (4/2 MB pages). */
+ uint32_t fPse : 1;
+ /** Supports 36-bit page size extension (4 MB pages can map memory above
+ * 4GB). */
+ uint32_t fPse36 : 1;
+ /** Supports physical address extension (PAE). */
+ uint32_t fPae : 1;
+ /** Supports page-global extension (PGE). */
+ uint32_t fPge : 1;
+ /** Page attribute table (PAT) support (page level cache control). */
+ uint32_t fPat : 1;
+ /** Supports the FXSAVE and FXRSTOR instructions. */
+ uint32_t fFxSaveRstor : 1;
+ /** Supports the XSAVE and XRSTOR instructions. */
+ uint32_t fXSaveRstor : 1;
+ /** Supports the XSAVEOPT instruction. */
+ uint32_t fXSaveOpt : 1;
+ /** The XSAVE/XRSTOR bit in CR4 has been set (only applicable for host!). */
+ uint32_t fOpSysXSaveRstor : 1;
+ /** Supports MMX. */
+ uint32_t fMmx : 1;
+ /** Supports AMD extensions to MMX instructions. */
+ uint32_t fAmdMmxExts : 1;
+ /** Supports SSE. */
+ uint32_t fSse : 1;
+ /** Supports SSE2. */
+ uint32_t fSse2 : 1;
+ /** Supports SSE3. */
+ uint32_t fSse3 : 1;
+ /** Supports SSSE3. */
+ uint32_t fSsse3 : 1;
+ /** Supports SSE4.1. */
+ uint32_t fSse41 : 1;
+ /** Supports SSE4.2. */
+ uint32_t fSse42 : 1;
+ /** Supports AVX. */
+ uint32_t fAvx : 1;
+ /** Supports AVX2. */
+ uint32_t fAvx2 : 1;
+ /** Supports AVX512 foundation. */
+ uint32_t fAvx512Foundation : 1;
+ /** Supports RDTSC. */
+ uint32_t fTsc : 1;
+ /** Intel SYSENTER/SYSEXIT support */
+ uint32_t fSysEnter : 1;
+ /** First generation APIC. */
+ uint32_t fApic : 1;
+ /** Second generation APIC. */
+ uint32_t fX2Apic : 1;
+ /** Hypervisor present. */
+ uint32_t fHypervisorPresent : 1;
+ /** MWAIT & MONITOR instructions supported. */
+ uint32_t fMonitorMWait : 1;
+ /** MWAIT Extensions present. */
+ uint32_t fMWaitExtensions : 1;
+ /** Supports CMPXCHG16B in 64-bit mode. */
+ uint32_t fMovCmpXchg16b : 1;
+ /** Supports CLFLUSH. */
+ uint32_t fClFlush : 1;
+ /** Supports CLFLUSHOPT. */
+ uint32_t fClFlushOpt : 1;
+ /** Supports IA32_PRED_CMD.IBPB. */
+ uint32_t fIbpb : 1;
+ /** Supports IA32_SPEC_CTRL.IBRS. */
+ uint32_t fIbrs : 1;
+ /** Supports IA32_SPEC_CTRL.STIBP. */
+ uint32_t fStibp : 1;
+ /** Supports IA32_FLUSH_CMD. */
+ uint32_t fFlushCmd : 1;
+ /** Supports IA32_ARCH_CAP. */
+ uint32_t fArchCap : 1;
+ /** Supports MD_CLEAR functionality (VERW, IA32_FLUSH_CMD). */
+ uint32_t fMdsClear : 1;
+ /** Supports PCID. */
+ uint32_t fPcid : 1;
+ /** Supports INVPCID. */
+ uint32_t fInvpcid : 1;
+ /** Supports read/write FSGSBASE instructions. */
+ uint32_t fFsGsBase : 1;
+ /** Supports BMI1 instructions (ANDN, BEXTR, BLSI, BLSMSK, BLSR, and TZCNT). */
+ uint32_t fBmi1 : 1;
+ /** Supports BMI2 instructions (BZHI, MULX, PDEP, PEXT, RORX, SARX, SHRX,
+ * and SHLX). */
+ uint32_t fBmi2 : 1;
+ /** Supports POPCNT instruction. */
+ uint32_t fPopCnt : 1;
+ /** Supports RDRAND instruction. */
+ uint32_t fRdRand : 1;
+ /** Supports RDSEED instruction. */
+ uint32_t fRdSeed : 1;
+ /** Supports Hardware Lock Elision (HLE). */
+ uint32_t fHle : 1;
+ /** Supports Restricted Transactional Memory (RTM - XBEGIN, XEND, XABORT). */
+ uint32_t fRtm : 1;
+ /** Supports PCLMULQDQ instruction. */
+ uint32_t fPclMul : 1;
+ /** Supports AES-NI (six AESxxx instructions). */
+ uint32_t fAesNi : 1;
+ /** Support MOVBE instruction. */
+ uint32_t fMovBe : 1;
+
+ /** Supports AMD 3DNow instructions. */
+ uint32_t f3DNow : 1;
+ /** Supports the 3DNow/AMD64 prefetch instructions (could be nops). */
+ uint32_t f3DNowPrefetch : 1;
+
+ /** AMD64: Supports long mode. */
+ uint32_t fLongMode : 1;
+ /** AMD64: SYSCALL/SYSRET support. */
+ uint32_t fSysCall : 1;
+ /** AMD64: No-execute page table bit. */
+ uint32_t fNoExecute : 1;
+ /** AMD64: Supports LAHF & SAHF instructions in 64-bit mode. */
+ uint32_t fLahfSahf : 1;
+ /** AMD64: Supports RDTSCP. */
+ uint32_t fRdTscP : 1;
+ /** AMD64: Supports MOV CR8 in 32-bit code (lock prefix hack). */
+ uint32_t fMovCr8In32Bit : 1;
+ /** AMD64: Supports XOP (similar to VEX3/AVX). */
+ uint32_t fXop : 1;
+ /** AMD64: Supports ABM, i.e. the LZCNT instruction. */
+ uint32_t fAbm : 1;
+ /** AMD64: Supports TBM (BEXTR, BLCFILL, BLCI, BLCIC, BLCMSK, BLCS,
+ * BLSFILL, BLSIC, T1MSKC, and TZMSK). */
+ uint32_t fTbm : 1;
+
+ /** Indicates that FPU instruction and data pointers may leak.
+ * This generally applies to recent AMD CPUs, where the FPU IP and DP pointer
+ * is only saved and restored if an exception is pending. */
+ uint32_t fLeakyFxSR : 1;
+
+ /** AMD64: Supports AMD SVM. */
+ uint32_t fSvm : 1;
+
+ /** Support for Intel VMX. */
+ uint32_t fVmx : 1;
+
+ /** Indicates that speculative execution control CPUID bits and MSRs are exposed.
+ * The details are different for Intel and AMD but both have similar
+ * functionality. */
+ uint32_t fSpeculationControl : 1;
+
+ /** MSR_IA32_ARCH_CAPABILITIES: RDCL_NO (bit 0).
+ * @remarks Only safe use after CPUM ring-0 init! */
+ uint32_t fArchRdclNo : 1;
+ /** MSR_IA32_ARCH_CAPABILITIES: IBRS_ALL (bit 1).
+ * @remarks Only safe use after CPUM ring-0 init! */
+ uint32_t fArchIbrsAll : 1;
+ /** MSR_IA32_ARCH_CAPABILITIES: RSB Override (bit 2).
+ * @remarks Only safe use after CPUM ring-0 init! */
+ uint32_t fArchRsbOverride : 1;
+ /** MSR_IA32_ARCH_CAPABILITIES: RSB Override (bit 3).
+ * @remarks Only safe use after CPUM ring-0 init! */
+ uint32_t fArchVmmNeedNotFlushL1d : 1;
+ /** MSR_IA32_ARCH_CAPABILITIES: MDS_NO (bit 4).
+ * @remarks Only safe use after CPUM ring-0 init! */
+ uint32_t fArchMdsNo : 1;
+
+ /** Alignment padding / reserved for future use (96 bits total, plus 12 bytes
+ * prior to the bit fields -> total of 24 bytes) */
+ uint32_t fPadding0 : 26;
+
+
+ /** @name SVM
+ * @{ */
+ /** SVM: Supports Nested-paging. */
+ uint32_t fSvmNestedPaging : 1;
+ /** SVM: Support LBR (Last Branch Record) virtualization. */
+ uint32_t fSvmLbrVirt : 1;
+ /** SVM: Supports SVM lock. */
+ uint32_t fSvmSvmLock : 1;
+ /** SVM: Supports Next RIP save. */
+ uint32_t fSvmNextRipSave : 1;
+ /** SVM: Supports TSC rate MSR. */
+ uint32_t fSvmTscRateMsr : 1;
+ /** SVM: Supports VMCB clean bits. */
+ uint32_t fSvmVmcbClean : 1;
+ /** SVM: Supports Flush-by-ASID. */
+ uint32_t fSvmFlusbByAsid : 1;
+ /** SVM: Supports decode assist. */
+ uint32_t fSvmDecodeAssists : 1;
+ /** SVM: Supports Pause filter. */
+ uint32_t fSvmPauseFilter : 1;
+ /** SVM: Supports Pause filter threshold. */
+ uint32_t fSvmPauseFilterThreshold : 1;
+ /** SVM: Supports AVIC (Advanced Virtual Interrupt Controller). */
+ uint32_t fSvmAvic : 1;
+ /** SVM: Supports Virtualized VMSAVE/VMLOAD. */
+ uint32_t fSvmVirtVmsaveVmload : 1;
+ /** SVM: Supports VGIF (Virtual Global Interrupt Flag). */
+ uint32_t fSvmVGif : 1;
+ /** SVM: Supports GMET (Guest Mode Execute Trap Extension). */
+ uint32_t fSvmGmet : 1;
+ /** SVM: Supports SSSCheck (SVM Supervisor Shadow Stack). */
+ uint32_t fSvmSSSCheck : 1;
+ /** SVM: Supports SPEC_CTRL virtualization. */
+ uint32_t fSvmSpecCtrl : 1;
+ /** SVM: Supports HOST_MCE_OVERRIDE. */
+ uint32_t fSvmHostMceOverride : 1;
+ /** SVM: Supports TlbiCtl (INVLPGB/TLBSYNC in VMCB and TLBSYNC intercept). */
+ uint32_t fSvmTlbiCtl : 1;
+ /** SVM: Padding / reserved for future features (64 bits total w/ max ASID). */
+ uint32_t fSvmPadding0 : 14;
+ /** SVM: Maximum supported ASID. */
+ uint32_t uSvmMaxAsid;
+ /** @} */
+
+
+ /** VMX: Maximum physical address width. */
+ uint32_t cVmxMaxPhysAddrWidth : 8;
+
+ /** @name VMX basic controls.
+ * @{ */
+ /** VMX: Supports INS/OUTS VM-exit instruction info. */
+ uint32_t fVmxInsOutInfo : 1;
+ /** @} */
+
+ /** @name VMX Pin-based controls.
+ * @{ */
+ /** VMX: Supports external interrupt VM-exit. */
+ uint32_t fVmxExtIntExit : 1;
+ /** VMX: Supports NMI VM-exit. */
+ uint32_t fVmxNmiExit : 1;
+ /** VMX: Supports Virtual NMIs. */
+ uint32_t fVmxVirtNmi : 1;
+ /** VMX: Supports preemption timer. */
+ uint32_t fVmxPreemptTimer : 1;
+ /** VMX: Supports posted interrupts. */
+ uint32_t fVmxPostedInt : 1;
+ /** @} */
+
+ /** @name VMX Processor-based controls.
+ * @{ */
+ /** VMX: Supports Interrupt-window exiting. */
+ uint32_t fVmxIntWindowExit : 1;
+ /** VMX: Supports TSC offsetting. */
+ uint32_t fVmxTscOffsetting : 1;
+ /** VMX: Supports HLT exiting. */
+ uint32_t fVmxHltExit : 1;
+ /** VMX: Supports INVLPG exiting. */
+ uint32_t fVmxInvlpgExit : 1;
+ /** VMX: Supports MWAIT exiting. */
+ uint32_t fVmxMwaitExit : 1;
+ /** VMX: Supports RDPMC exiting. */
+ uint32_t fVmxRdpmcExit : 1;
+ /** VMX: Supports RDTSC exiting. */
+ uint32_t fVmxRdtscExit : 1;
+ /** VMX: Supports CR3-load exiting. */
+ uint32_t fVmxCr3LoadExit : 1;
+ /** VMX: Supports CR3-store exiting. */
+ uint32_t fVmxCr3StoreExit : 1;
+ /** VMX: Supports tertiary processor-based VM-execution controls. */
+ uint32_t fVmxTertiaryExecCtls : 1;
+ /** VMX: Supports CR8-load exiting. */
+ uint32_t fVmxCr8LoadExit : 1;
+ /** VMX: Supports CR8-store exiting. */
+ uint32_t fVmxCr8StoreExit : 1;
+ /** VMX: Supports TPR shadow. */
+ uint32_t fVmxUseTprShadow : 1;
+ /** VMX: Supports NMI-window exiting. */
+ uint32_t fVmxNmiWindowExit : 1;
+ /** VMX: Supports Mov-DRx exiting. */
+ uint32_t fVmxMovDRxExit : 1;
+ /** VMX: Supports Unconditional I/O exiting. */
+ uint32_t fVmxUncondIoExit : 1;
+ /** VMX: Supportgs I/O bitmaps. */
+ uint32_t fVmxUseIoBitmaps : 1;
+ /** VMX: Supports Monitor Trap Flag. */
+ uint32_t fVmxMonitorTrapFlag : 1;
+ /** VMX: Supports MSR bitmap. */
+ uint32_t fVmxUseMsrBitmaps : 1;
+ /** VMX: Supports MONITOR exiting. */
+ uint32_t fVmxMonitorExit : 1;
+ /** VMX: Supports PAUSE exiting. */
+ uint32_t fVmxPauseExit : 1;
+ /** VMX: Supports secondary processor-based VM-execution controls. */
+ uint32_t fVmxSecondaryExecCtls : 1;
+ /** @} */
+
+ /** @name VMX Secondary processor-based controls.
+ * @{ */
+ /** VMX: Supports virtualize-APIC access. */
+ uint32_t fVmxVirtApicAccess : 1;
+ /** VMX: Supports EPT (Extended Page Tables). */
+ uint32_t fVmxEpt : 1;
+ /** VMX: Supports descriptor-table exiting. */
+ uint32_t fVmxDescTableExit : 1;
+ /** VMX: Supports RDTSCP. */
+ uint32_t fVmxRdtscp : 1;
+ /** VMX: Supports virtualize-x2APIC mode. */
+ uint32_t fVmxVirtX2ApicMode : 1;
+ /** VMX: Supports VPID. */
+ uint32_t fVmxVpid : 1;
+ /** VMX: Supports WBIND exiting. */
+ uint32_t fVmxWbinvdExit : 1;
+ /** VMX: Supports Unrestricted guest. */
+ uint32_t fVmxUnrestrictedGuest : 1;
+ /** VMX: Supports APIC-register virtualization. */
+ uint32_t fVmxApicRegVirt : 1;
+ /** VMX: Supports virtual-interrupt delivery. */
+ uint32_t fVmxVirtIntDelivery : 1;
+ /** VMX: Supports Pause-loop exiting. */
+ uint32_t fVmxPauseLoopExit : 1;
+ /** VMX: Supports RDRAND exiting. */
+ uint32_t fVmxRdrandExit : 1;
+ /** VMX: Supports INVPCID. */
+ uint32_t fVmxInvpcid : 1;
+ /** VMX: Supports VM functions. */
+ uint32_t fVmxVmFunc : 1;
+ /** VMX: Supports VMCS shadowing. */
+ uint32_t fVmxVmcsShadowing : 1;
+ /** VMX: Supports RDSEED exiting. */
+ uint32_t fVmxRdseedExit : 1;
+ /** VMX: Supports PML. */
+ uint32_t fVmxPml : 1;
+ /** VMX: Supports EPT-violations \#VE. */
+ uint32_t fVmxEptXcptVe : 1;
+ /** VMX: Supports conceal VMX from PT. */
+ uint32_t fVmxConcealVmxFromPt : 1;
+ /** VMX: Supports XSAVES/XRSTORS. */
+ uint32_t fVmxXsavesXrstors : 1;
+ /** VMX: Supports mode-based execute control for EPT. */
+ uint32_t fVmxModeBasedExecuteEpt : 1;
+ /** VMX: Supports sub-page write permissions for EPT. */
+ uint32_t fVmxSppEpt : 1;
+ /** VMX: Supports Intel PT to output guest-physical addresses for EPT. */
+ uint32_t fVmxPtEpt : 1;
+ /** VMX: Supports TSC scaling. */
+ uint32_t fVmxUseTscScaling : 1;
+ /** VMX: Supports TPAUSE, UMONITOR, or UMWAIT. */
+ uint32_t fVmxUserWaitPause : 1;
+ /** VMX: Supports enclave (ENCLV) exiting. */
+ uint32_t fVmxEnclvExit : 1;
+ /** @} */
+
+ /** @name VMX Tertiary processor-based controls.
+ * @{ */
+ /** VMX: Supports LOADIWKEY exiting. */
+ uint32_t fVmxLoadIwKeyExit : 1;
+ /** @} */
+
+ /** @name VMX VM-entry controls.
+ * @{ */
+ /** VMX: Supports load-debug controls on VM-entry. */
+ uint32_t fVmxEntryLoadDebugCtls : 1;
+ /** VMX: Supports IA32e mode guest. */
+ uint32_t fVmxIa32eModeGuest : 1;
+ /** VMX: Supports load guest EFER MSR on VM-entry. */
+ uint32_t fVmxEntryLoadEferMsr : 1;
+ /** VMX: Supports load guest PAT MSR on VM-entry. */
+ uint32_t fVmxEntryLoadPatMsr : 1;
+ /** @} */
+
+ /** @name VMX VM-exit controls.
+ * @{ */
+ /** VMX: Supports save debug controls on VM-exit. */
+ uint32_t fVmxExitSaveDebugCtls : 1;
+ /** VMX: Supports host-address space size. */
+ uint32_t fVmxHostAddrSpaceSize : 1;
+ /** VMX: Supports acknowledge external interrupt on VM-exit. */
+ uint32_t fVmxExitAckExtInt : 1;
+ /** VMX: Supports save guest PAT MSR on VM-exit. */
+ uint32_t fVmxExitSavePatMsr : 1;
+ /** VMX: Supports load hsot PAT MSR on VM-exit. */
+ uint32_t fVmxExitLoadPatMsr : 1;
+ /** VMX: Supports save guest EFER MSR on VM-exit. */
+ uint32_t fVmxExitSaveEferMsr : 1;
+ /** VMX: Supports load host EFER MSR on VM-exit. */
+ uint32_t fVmxExitLoadEferMsr : 1;
+ /** VMX: Supports save VMX preemption timer on VM-exit. */
+ uint32_t fVmxSavePreemptTimer : 1;
+ /** VMX: Supports secondary VM-exit controls. */
+ uint32_t fVmxSecondaryExitCtls : 1;
+ /** @} */
+
+ /** @name VMX Miscellaneous data.
+ * @{ */
+ /** VMX: Supports storing EFER.LMA into IA32e-mode guest field on VM-exit. */
+ uint32_t fVmxExitSaveEferLma : 1;
+ /** VMX: Whether Intel PT (Processor Trace) is supported in VMX mode or not. */
+ uint32_t fVmxPt : 1;
+ /** VMX: Supports VMWRITE to any valid VMCS field incl. read-only fields, otherwise
+ * VMWRITE cannot modify read-only VM-exit information fields. */
+ uint32_t fVmxVmwriteAll : 1;
+ /** VMX: Supports injection of software interrupts, ICEBP on VM-entry for zero
+ * length instructions. */
+ uint32_t fVmxEntryInjectSoftInt : 1;
+ /** @} */
+
+ /** VMX: Padding / reserved for future features. */
+ uint32_t fVmxPadding0 : 16;
+ /** VMX: Padding / reserved for future, making it a total of 128 bits. */
+ uint32_t fVmxPadding1;
+} CPUMFEATURES;
+#ifndef VBOX_FOR_DTRACE_LIB
+AssertCompileSize(CPUMFEATURES, 48);
+#endif
+/** Pointer to a CPU feature structure. */
+typedef CPUMFEATURES *PCPUMFEATURES;
+/** Pointer to a const CPU feature structure. */
+typedef CPUMFEATURES const *PCCPUMFEATURES;
+
+/**
+ * Chameleon wrapper structure for the host CPU features.
+ *
+ * This is used for the globally readable g_CpumHostFeatures variable, which is
+ * initialized once during VMMR0 load for ring-0 and during CPUMR3Init in
+ * ring-3. To reflect this immutability after load/init, we use this wrapper
+ * structure to switch it between const and non-const depending on the context.
+ * Only two files sees it as non-const (CPUMR0.cpp and CPUM.cpp).
+ */
+typedef struct CPUHOSTFEATURES
+{
+ CPUMFEATURES
+#ifndef CPUM_WITH_NONCONST_HOST_FEATURES
+ const
+#endif
+ s;
+} CPUHOSTFEATURES;
+/** Pointer to a const host CPU feature structure. */
+typedef CPUHOSTFEATURES const *PCCPUHOSTFEATURES;
+
+/** Host CPU features.
+ * @note In ring-3, only valid after CPUMR3Init. In ring-0, valid after
+ * module init. */
+extern CPUHOSTFEATURES g_CpumHostFeatures;
+
+
+/**
+ * CPU database entry.
+ */
+typedef struct CPUMDBENTRY
+{
+ /** The CPU name. */
+ const char *pszName;
+ /** The full CPU name. */
+ const char *pszFullName;
+ /** The CPU vendor (CPUMCPUVENDOR). */
+ uint8_t enmVendor;
+ /** The CPU family. */
+ uint8_t uFamily;
+ /** The CPU model. */
+ uint8_t uModel;
+ /** The CPU stepping. */
+ uint8_t uStepping;
+ /** The microarchitecture. */
+ CPUMMICROARCH enmMicroarch;
+ /** Scalable bus frequency used for reporting other frequencies. */
+ uint64_t uScalableBusFreq;
+ /** Flags - CPUMDB_F_XXX. */
+ uint32_t fFlags;
+ /** The maximum physical address with of the CPU. This should correspond to
+ * the value in CPUID leaf 0x80000008 when present. */
+ uint8_t cMaxPhysAddrWidth;
+ /** The MXCSR mask. */
+ uint32_t fMxCsrMask;
+ /** Pointer to an array of CPUID leaves. */
+ PCCPUMCPUIDLEAF paCpuIdLeaves;
+ /** The number of CPUID leaves in the array paCpuIdLeaves points to. */
+ uint32_t cCpuIdLeaves;
+ /** The method used to deal with unknown CPUID leaves. */
+ CPUMUNKNOWNCPUID enmUnknownCpuId;
+ /** The default unknown CPUID value. */
+ CPUMCPUID DefUnknownCpuId;
+
+ /** MSR mask. Several microarchitectures ignore the higher bits of ECX in
+ * the RDMSR and WRMSR instructions. */
+ uint32_t fMsrMask;
+
+ /** The number of ranges in the table pointed to b paMsrRanges. */
+ uint32_t cMsrRanges;
+ /** MSR ranges for this CPU. */
+ PCCPUMMSRRANGE paMsrRanges;
+} CPUMDBENTRY;
+/** Pointer to a const CPU database entry. */
+typedef CPUMDBENTRY const *PCCPUMDBENTRY;
+
+/** @name CPUMDB_F_XXX - CPUDBENTRY::fFlags
+ * @{ */
+/** Should execute all in IEM.
+ * @todo Implement this - currently done in Main... */
+#define CPUMDB_F_EXECUTE_ALL_IN_IEM RT_BIT_32(0)
+/** @} */
+
+
+
+#ifndef VBOX_FOR_DTRACE_LIB
+
+#if defined(RT_ARCH_X86) || defined(RT_ARCH_AMD64)
+VMMDECL(int) CPUMCpuIdCollectLeavesX86(PCPUMCPUIDLEAF *ppaLeaves, uint32_t *pcLeaves);
+VMMDECL(CPUMCPUVENDOR) CPUMCpuIdDetectX86VendorEx(uint32_t uEAX, uint32_t uEBX, uint32_t uECX, uint32_t uEDX);
+#endif
+
+VMM_INT_DECL(bool) CPUMAssertGuestRFlagsCookie(PVM pVM, PVMCPU pVCpu);
+
+
+/** @name Guest Register Getters.
+ * @{ */
+VMMDECL(void) CPUMGetGuestGDTR(PCVMCPU pVCpu, PVBOXGDTR pGDTR);
+VMMDECL(RTGCPTR) CPUMGetGuestIDTR(PCVMCPU pVCpu, uint16_t *pcbLimit);
+VMMDECL(RTSEL) CPUMGetGuestTR(PCVMCPU pVCpu, PCPUMSELREGHID pHidden);
+VMMDECL(RTSEL) CPUMGetGuestLDTR(PCVMCPU pVCpu);
+VMMDECL(RTSEL) CPUMGetGuestLdtrEx(PCVMCPU pVCpu, uint64_t *pGCPtrBase, uint32_t *pcbLimit);
+VMMDECL(uint64_t) CPUMGetGuestCR0(PCVMCPU pVCpu);
+VMMDECL(uint64_t) CPUMGetGuestCR2(PCVMCPU pVCpu);
+VMMDECL(uint64_t) CPUMGetGuestCR3(PCVMCPU pVCpu);
+VMMDECL(uint64_t) CPUMGetGuestCR4(PCVMCPU pVCpu);
+VMMDECL(uint64_t) CPUMGetGuestCR8(PCVMCPUCC pVCpu);
+VMMDECL(int) CPUMGetGuestCRx(PCVMCPUCC pVCpu, unsigned iReg, uint64_t *pValue);
+VMMDECL(uint32_t) CPUMGetGuestEFlags(PCVMCPU pVCpu);
+VMMDECL(uint32_t) CPUMGetGuestEIP(PCVMCPU pVCpu);
+VMMDECL(uint64_t) CPUMGetGuestRIP(PCVMCPU pVCpu);
+VMMDECL(uint32_t) CPUMGetGuestEAX(PCVMCPU pVCpu);
+VMMDECL(uint32_t) CPUMGetGuestEBX(PCVMCPU pVCpu);
+VMMDECL(uint32_t) CPUMGetGuestECX(PCVMCPU pVCpu);
+VMMDECL(uint32_t) CPUMGetGuestEDX(PCVMCPU pVCpu);
+VMMDECL(uint32_t) CPUMGetGuestESI(PCVMCPU pVCpu);
+VMMDECL(uint32_t) CPUMGetGuestEDI(PCVMCPU pVCpu);
+VMMDECL(uint32_t) CPUMGetGuestESP(PCVMCPU pVCpu);
+VMMDECL(uint32_t) CPUMGetGuestEBP(PCVMCPU pVCpu);
+VMMDECL(RTSEL) CPUMGetGuestCS(PCVMCPU pVCpu);
+VMMDECL(RTSEL) CPUMGetGuestDS(PCVMCPU pVCpu);
+VMMDECL(RTSEL) CPUMGetGuestES(PCVMCPU pVCpu);
+VMMDECL(RTSEL) CPUMGetGuestFS(PCVMCPU pVCpu);
+VMMDECL(RTSEL) CPUMGetGuestGS(PCVMCPU pVCpu);
+VMMDECL(RTSEL) CPUMGetGuestSS(PCVMCPU pVCpu);
+VMMDECL(uint64_t) CPUMGetGuestFlatPC(PVMCPU pVCpu);
+VMMDECL(uint64_t) CPUMGetGuestFlatSP(PVMCPU pVCpu);
+VMMDECL(uint64_t) CPUMGetGuestDR0(PCVMCPU pVCpu);
+VMMDECL(uint64_t) CPUMGetGuestDR1(PCVMCPU pVCpu);
+VMMDECL(uint64_t) CPUMGetGuestDR2(PCVMCPU pVCpu);
+VMMDECL(uint64_t) CPUMGetGuestDR3(PCVMCPU pVCpu);
+VMMDECL(uint64_t) CPUMGetGuestDR6(PCVMCPU pVCpu);
+VMMDECL(uint64_t) CPUMGetGuestDR7(PCVMCPU pVCpu);
+VMMDECL(int) CPUMGetGuestDRx(PCVMCPU pVCpu, uint32_t iReg, uint64_t *pValue);
+VMMDECL(void) CPUMGetGuestCpuId(PVMCPUCC pVCpu, uint32_t iLeaf, uint32_t iSubLeaf, int f64BitMode,
+ uint32_t *pEax, uint32_t *pEbx, uint32_t *pEcx, uint32_t *pEdx);
+VMMDECL(uint64_t) CPUMGetGuestEFER(PCVMCPU pVCpu);
+VMM_INT_DECL(uint64_t) CPUMGetGuestIa32FeatCtrl(PCVMCPUCC pVCpu);
+VMM_INT_DECL(uint64_t) CPUMGetGuestIa32MtrrCap(PCVMCPU pVCpu);
+VMM_INT_DECL(uint64_t) CPUMGetGuestIa32SmmMonitorCtl(PCVMCPUCC pVCpu);
+VMM_INT_DECL(uint64_t) CPUMGetGuestIa32VmxEptVpidCap(PCVMCPUCC pVCpu);
+VMMDECL(VBOXSTRICTRC) CPUMQueryGuestMsr(PVMCPUCC pVCpu, uint32_t idMsr, uint64_t *puValue);
+VMMDECL(VBOXSTRICTRC) CPUMSetGuestMsr(PVMCPUCC pVCpu, uint32_t idMsr, uint64_t uValue);
+VMMDECL(CPUMCPUVENDOR) CPUMGetGuestCpuVendor(PVM pVM);
+VMMDECL(CPUMMICROARCH) CPUMGetGuestMicroarch(PCVM pVM);
+VMMDECL(void) CPUMGetGuestAddrWidths(PCVM pVM, uint8_t *pcPhysAddrWidth, uint8_t *pcLinearAddrWidth);
+VMMDECL(CPUMCPUVENDOR) CPUMGetHostCpuVendor(PVM pVM);
+VMMDECL(CPUMMICROARCH) CPUMGetHostMicroarch(PCVM pVM);
+/** @} */
+
+/** @name Guest Register Setters.
+ * @{ */
+VMMDECL(int) CPUMSetGuestGDTR(PVMCPU pVCpu, uint64_t GCPtrBase, uint16_t cbLimit);
+VMMDECL(int) CPUMSetGuestIDTR(PVMCPU pVCpu, uint64_t GCPtrBase, uint16_t cbLimit);
+VMMDECL(int) CPUMSetGuestTR(PVMCPU pVCpu, uint16_t tr);
+VMMDECL(int) CPUMSetGuestLDTR(PVMCPU pVCpu, uint16_t ldtr);
+VMMDECL(int) CPUMSetGuestCR0(PVMCPUCC pVCpu, uint64_t cr0);
+VMMDECL(int) CPUMSetGuestCR2(PVMCPU pVCpu, uint64_t cr2);
+VMMDECL(int) CPUMSetGuestCR3(PVMCPU pVCpu, uint64_t cr3);
+VMMDECL(int) CPUMSetGuestCR4(PVMCPU pVCpu, uint64_t cr4);
+VMMDECL(int) CPUMSetGuestDR0(PVMCPUCC pVCpu, uint64_t uDr0);
+VMMDECL(int) CPUMSetGuestDR1(PVMCPUCC pVCpu, uint64_t uDr1);
+VMMDECL(int) CPUMSetGuestDR2(PVMCPUCC pVCpu, uint64_t uDr2);
+VMMDECL(int) CPUMSetGuestDR3(PVMCPUCC pVCpu, uint64_t uDr3);
+VMMDECL(int) CPUMSetGuestDR6(PVMCPU pVCpu, uint64_t uDr6);
+VMMDECL(int) CPUMSetGuestDR7(PVMCPUCC pVCpu, uint64_t uDr7);
+VMMDECL(int) CPUMSetGuestDRx(PVMCPUCC pVCpu, uint32_t iReg, uint64_t Value);
+VMM_INT_DECL(int) CPUMSetGuestXcr0(PVMCPUCC pVCpu, uint64_t uNewValue);
+VMMDECL(int) CPUMSetGuestEFlags(PVMCPU pVCpu, uint32_t eflags);
+VMMDECL(int) CPUMSetGuestEIP(PVMCPU pVCpu, uint32_t eip);
+VMMDECL(int) CPUMSetGuestEAX(PVMCPU pVCpu, uint32_t eax);
+VMMDECL(int) CPUMSetGuestEBX(PVMCPU pVCpu, uint32_t ebx);
+VMMDECL(int) CPUMSetGuestECX(PVMCPU pVCpu, uint32_t ecx);
+VMMDECL(int) CPUMSetGuestEDX(PVMCPU pVCpu, uint32_t edx);
+VMMDECL(int) CPUMSetGuestESI(PVMCPU pVCpu, uint32_t esi);
+VMMDECL(int) CPUMSetGuestEDI(PVMCPU pVCpu, uint32_t edi);
+VMMDECL(int) CPUMSetGuestESP(PVMCPU pVCpu, uint32_t esp);
+VMMDECL(int) CPUMSetGuestEBP(PVMCPU pVCpu, uint32_t ebp);
+VMMDECL(int) CPUMSetGuestCS(PVMCPU pVCpu, uint16_t cs);
+VMMDECL(int) CPUMSetGuestDS(PVMCPU pVCpu, uint16_t ds);
+VMMDECL(int) CPUMSetGuestES(PVMCPU pVCpu, uint16_t es);
+VMMDECL(int) CPUMSetGuestFS(PVMCPU pVCpu, uint16_t fs);
+VMMDECL(int) CPUMSetGuestGS(PVMCPU pVCpu, uint16_t gs);
+VMMDECL(int) CPUMSetGuestSS(PVMCPU pVCpu, uint16_t ss);
+VMMDECL(void) CPUMSetGuestEFER(PVMCPU pVCpu, uint64_t val);
+VMMR3_INT_DECL(void) CPUMR3SetGuestCpuIdFeature(PVM pVM, CPUMCPUIDFEATURE enmFeature);
+VMMR3_INT_DECL(void) CPUMR3ClearGuestCpuIdFeature(PVM pVM, CPUMCPUIDFEATURE enmFeature);
+VMMR3_INT_DECL(bool) CPUMR3GetGuestCpuIdFeature(PVM pVM, CPUMCPUIDFEATURE enmFeature);
+VMMDECL(bool) CPUMSetGuestCpuIdPerCpuApicFeature(PVMCPU pVCpu, bool fVisible);
+VMMDECL(void) CPUMSetGuestCtx(PVMCPU pVCpu, const PCPUMCTX pCtx);
+VMM_INT_DECL(void) CPUMSetGuestTscAux(PVMCPUCC pVCpu, uint64_t uValue);
+VMM_INT_DECL(uint64_t) CPUMGetGuestTscAux(PVMCPUCC pVCpu);
+VMM_INT_DECL(void) CPUMSetGuestSpecCtrl(PVMCPUCC pVCpu, uint64_t uValue);
+VMM_INT_DECL(uint64_t) CPUMGetGuestSpecCtrl(PVMCPUCC pVCpu);
+VMM_INT_DECL(uint64_t) CPUMGetGuestCR4ValidMask(PVM pVM);
+VMM_INT_DECL(void) CPUMSetGuestPaePdpes(PVMCPU pVCpu, PCX86PDPE paPaePdpes);
+VMM_INT_DECL(void) CPUMGetGuestPaePdpes(PVMCPU pVCpu, PX86PDPE paPaePdpes);
+/** @} */
+
+
+/** @name Misc Guest Predicate Functions.
+ * @{ */
+VMMDECL(bool) CPUMIsGuestIn64BitCode(PVMCPU pVCpu);
+VMMDECL(bool) CPUMIsGuestNXEnabled(PCVMCPU pVCpu);
+VMMDECL(bool) CPUMIsGuestPageSizeExtEnabled(PCVMCPU pVCpu);
+VMMDECL(bool) CPUMIsGuestPagingEnabled(PCVMCPU pVCpu);
+VMMDECL(bool) CPUMIsGuestR0WriteProtEnabled(PCVMCPU pVCpu);
+VMMDECL(bool) CPUMIsGuestInRealMode(PCVMCPU pVCpu);
+VMMDECL(bool) CPUMIsGuestInRealOrV86Mode(PCVMCPU pVCpu);
+VMMDECL(bool) CPUMIsGuestInProtectedMode(PCVMCPU pVCpu);
+VMMDECL(bool) CPUMIsGuestInPagedProtectedMode(PCVMCPU pVCpu);
+VMMDECL(bool) CPUMIsGuestInLongMode(PCVMCPU pVCpu);
+VMMDECL(bool) CPUMIsGuestInPAEMode(PCVMCPU pVCpu);
+/** @} */
+
+/** @name Nested Hardware-Virtualization Helpers.
+ * @{ */
+VMM_INT_DECL(bool) CPUMIsGuestPhysIntrEnabled(PVMCPU pVCpu);
+VMM_INT_DECL(bool) CPUMIsGuestVirtIntrEnabled(PVMCPU pVCpu);
+VMM_INT_DECL(uint64_t) CPUMApplyNestedGuestTscOffset(PCVMCPU pVCpu, uint64_t uTscValue);
+VMM_INT_DECL(uint64_t) CPUMRemoveNestedGuestTscOffset(PCVMCPU pVCpu, uint64_t uTscValue);
+
+/* SVM helpers. */
+VMM_INT_DECL(bool) CPUMIsGuestSvmPhysIntrEnabled(PCVMCPU pVCpu, PCCPUMCTX pCtx);
+VMM_INT_DECL(bool) CPUMIsGuestSvmVirtIntrEnabled(PCVMCPU pVCpu, PCCPUMCTX pCtx);
+VMM_INT_DECL(uint8_t) CPUMGetGuestSvmVirtIntrVector(PCCPUMCTX pCtx);
+VMM_INT_DECL(void) CPUMSvmVmExitRestoreHostState(PVMCPUCC pVCpu, PCPUMCTX pCtx);
+VMM_INT_DECL(void) CPUMSvmVmRunSaveHostState(PCPUMCTX pCtx, uint8_t cbInstr);
+VMM_INT_DECL(bool) CPUMIsSvmIoInterceptSet(void *pvIoBitmap, uint16_t u16Port, SVMIOIOTYPE enmIoType, uint8_t cbReg,
+ uint8_t cAddrSizeBits, uint8_t iEffSeg, bool fRep, bool fStrIo,
+ PSVMIOIOEXITINFO pIoExitInfo);
+VMM_INT_DECL(int) CPUMGetSvmMsrpmOffsetAndBit(uint32_t idMsr, uint16_t *pbOffMsrpm, uint8_t *puMsrpmBit);
+
+/* VMX helpers. */
+VMM_INT_DECL(bool) CPUMIsGuestVmxVmcsFieldValid(PVMCC pVM, uint64_t u64VmcsField);
+VMM_INT_DECL(bool) CPUMIsGuestVmxIoInterceptSet(PCVMCPU pVCpu, uint16_t u16Port, uint8_t cbAccess);
+VMM_INT_DECL(bool) CPUMIsGuestVmxMovToCr3InterceptSet(PVMCPU pVCpu, uint64_t uNewCr3);
+VMM_INT_DECL(bool) CPUMIsGuestVmxVmreadVmwriteInterceptSet(PCVMCPU pVCpu, uint32_t uExitReason, uint64_t u64FieldEnc);
+VMM_INT_DECL(int) CPUMStartGuestVmxPremptTimer(PVMCPUCC pVCpu, uint32_t uTimer, uint8_t cShift, uint64_t *pu64EntryTick);
+VMM_INT_DECL(int) CPUMStopGuestVmxPremptTimer(PVMCPUCC pVCpu);
+VMM_INT_DECL(uint32_t) CPUMGetVmxMsrPermission(void const *pvMsrBitmap, uint32_t idMsr);
+VMM_INT_DECL(bool) CPUMIsGuestVmxEptPagingEnabled(PCVMCPUCC pVCpu);
+VMM_INT_DECL(bool) CPUMIsGuestVmxEptPaePagingEnabled(PCVMCPUCC pVCpu);
+VMM_INT_DECL(uint64_t) CPUMGetGuestVmxApicAccessPageAddr(PCVMCPUCC pVCpu);
+/** @} */
+
+/** @name Externalized State Helpers.
+ * @{ */
+/** @def CPUM_ASSERT_NOT_EXTRN
+ * Macro for asserting that @a a_fNotExtrn are present.
+ *
+ * @param a_pVCpu The cross context virtual CPU structure of the calling EMT.
+ * @param a_fNotExtrn Mask of CPUMCTX_EXTRN_XXX bits to check.
+ *
+ * @remarks Requires VMCPU_INCL_CPUM_GST_CTX to be defined.
+ */
+#define CPUM_ASSERT_NOT_EXTRN(a_pVCpu, a_fNotExtrn) \
+ AssertMsg(!((a_pVCpu)->cpum.GstCtx.fExtrn & (a_fNotExtrn)), \
+ ("%#RX64; a_fNotExtrn=%#RX64\n", (a_pVCpu)->cpum.GstCtx.fExtrn, (a_fNotExtrn)))
+
+/** @def CPUMCTX_ASSERT_NOT_EXTRN
+ * Macro for asserting that @a a_fNotExtrn are present in @a a_pCtx.
+ *
+ * @param a_pCtx The CPU context of the calling EMT.
+ * @param a_fNotExtrn Mask of CPUMCTX_EXTRN_XXX bits to check.
+ */
+#define CPUMCTX_ASSERT_NOT_EXTRN(a_pCtx, a_fNotExtrn) \
+ AssertMsg(!((a_pCtx)->fExtrn & (a_fNotExtrn)), \
+ ("%#RX64; a_fNotExtrn=%#RX64\n", (a_pCtx)->fExtrn, (a_fNotExtrn)))
+
+/** @def CPUM_IMPORT_EXTRN_RET
+ * Macro for making sure the state specified by @a fExtrnImport is present,
+ * calling CPUMImportGuestStateOnDemand() to get it if necessary.
+ *
+ * Will return if CPUMImportGuestStateOnDemand() fails.
+ *
+ * @param a_pVCpu The cross context virtual CPU structure of the calling EMT.
+ * @param a_fExtrnImport Mask of CPUMCTX_EXTRN_XXX bits to get.
+ * @thread EMT(a_pVCpu)
+ *
+ * @remarks Requires VMCPU_INCL_CPUM_GST_CTX to be defined.
+ */
+#define CPUM_IMPORT_EXTRN_RET(a_pVCpu, a_fExtrnImport) \
+ do { \
+ if (!((a_pVCpu)->cpum.GstCtx.fExtrn & (a_fExtrnImport))) \
+ { /* already present, consider this likely */ } \
+ else \
+ { \
+ int rcCpumImport = CPUMImportGuestStateOnDemand(a_pVCpu, a_fExtrnImport); \
+ AssertRCReturn(rcCpumImport, rcCpumImport); \
+ } \
+ } while (0)
+
+/** @def CPUM_IMPORT_EXTRN_RCSTRICT
+ * Macro for making sure the state specified by @a fExtrnImport is present,
+ * calling CPUMImportGuestStateOnDemand() to get it if necessary.
+ *
+ * Will update a_rcStrict if CPUMImportGuestStateOnDemand() fails.
+ *
+ * @param a_pVCpu The cross context virtual CPU structure of the calling EMT.
+ * @param a_fExtrnImport Mask of CPUMCTX_EXTRN_XXX bits to get.
+ * @param a_rcStrict Strict status code variable to update on failure.
+ * @thread EMT(a_pVCpu)
+ *
+ * @remarks Requires VMCPU_INCL_CPUM_GST_CTX to be defined.
+ */
+#define CPUM_IMPORT_EXTRN_RCSTRICT(a_pVCpu, a_fExtrnImport, a_rcStrict) \
+ do { \
+ if (!((a_pVCpu)->cpum.GstCtx.fExtrn & (a_fExtrnImport))) \
+ { /* already present, consider this likely */ } \
+ else \
+ { \
+ int rcCpumImport = CPUMImportGuestStateOnDemand(a_pVCpu, a_fExtrnImport); \
+ AssertStmt(RT_SUCCESS(rcCpumImport) || RT_FAILURE_NP(a_rcStrict), a_rcStrict = rcCpumImport); \
+ } \
+ } while (0)
+
+VMM_INT_DECL(int) CPUMImportGuestStateOnDemand(PVMCPUCC pVCpu, uint64_t fExtrnImport);
+/** @} */
+
+#if !defined(IPRT_WITHOUT_NAMED_UNIONS_AND_STRUCTS) || defined(DOXYGEN_RUNNING)
+/** @name Inlined Guest Getters and predicates Functions.
+ * @{ */
+
+/**
+ * Gets valid CR0 bits for the guest.
+ *
+ * @returns Valid CR0 bits.
+ */
+DECLINLINE(uint64_t) CPUMGetGuestCR0ValidMask(void)
+{
+ return ( X86_CR0_PE | X86_CR0_MP | X86_CR0_EM | X86_CR0_TS
+ | X86_CR0_ET | X86_CR0_NE | X86_CR0_WP | X86_CR0_AM
+ | X86_CR0_NW | X86_CR0_CD | X86_CR0_PG);
+}
+
+/**
+ * Tests if the guest is running in real mode or not.
+ *
+ * @returns true if in real mode, otherwise false.
+ * @param pCtx Current CPU context.
+ */
+DECLINLINE(bool) CPUMIsGuestInRealModeEx(PCCPUMCTX pCtx)
+{
+ return !(pCtx->cr0 & X86_CR0_PE);
+}
+
+/**
+ * Tests if the guest is running in real or virtual 8086 mode.
+ *
+ * @returns @c true if it is, @c false if not.
+ * @param pCtx Current CPU context.
+ */
+DECLINLINE(bool) CPUMIsGuestInRealOrV86ModeEx(PCCPUMCTX pCtx)
+{
+ return !(pCtx->cr0 & X86_CR0_PE)
+ || pCtx->eflags.Bits.u1VM; /* Cannot be set in long mode. Intel spec 2.3.1 "System Flags and Fields in IA-32e Mode". */
+}
+
+/**
+ * Tests if the guest is running in virtual 8086 mode.
+ *
+ * @returns @c true if it is, @c false if not.
+ * @param pCtx Current CPU context.
+ */
+DECLINLINE(bool) CPUMIsGuestInV86ModeEx(PCCPUMCTX pCtx)
+{
+ return (pCtx->eflags.Bits.u1VM == 1);
+}
+
+/**
+ * Tests if the guest is running in paged protected or not.
+ *
+ * @returns true if in paged protected mode, otherwise false.
+ * @param pCtx Current CPU context.
+ */
+DECLINLINE(bool) CPUMIsGuestInPagedProtectedModeEx(PCPUMCTX pCtx)
+{
+ return (pCtx->cr0 & (X86_CR0_PE | X86_CR0_PG)) == (X86_CR0_PE | X86_CR0_PG);
+}
+
+/**
+ * Tests if the guest is running in long mode or not.
+ *
+ * @returns true if in long mode, otherwise false.
+ * @param pCtx Current CPU context.
+ */
+DECLINLINE(bool) CPUMIsGuestInLongModeEx(PCCPUMCTX pCtx)
+{
+ return (pCtx->msrEFER & MSR_K6_EFER_LMA) == MSR_K6_EFER_LMA;
+}
+
+VMM_INT_DECL(bool) CPUMIsGuestIn64BitCodeSlow(PCPUMCTX pCtx);
+
+/**
+ * Tests if the guest is running in 64 bits mode or not.
+ *
+ * @returns true if in 64 bits protected mode, otherwise false.
+ * @param pCtx Current CPU context.
+ */
+DECLINLINE(bool) CPUMIsGuestIn64BitCodeEx(PCPUMCTX pCtx)
+{
+ if (!(pCtx->msrEFER & MSR_K6_EFER_LMA))
+ return false;
+ if (!CPUMSELREG_ARE_HIDDEN_PARTS_VALID(NULL, &pCtx->cs))
+ return CPUMIsGuestIn64BitCodeSlow(pCtx);
+ return pCtx->cs.Attr.n.u1Long;
+}
+
+/**
+ * Tests if the guest has paging enabled or not.
+ *
+ * @returns true if paging is enabled, otherwise false.
+ * @param pCtx Current CPU context.
+ */
+DECLINLINE(bool) CPUMIsGuestPagingEnabledEx(PCCPUMCTX pCtx)
+{
+ return !!(pCtx->cr0 & X86_CR0_PG);
+}
+
+/**
+ * Tests if PAE paging is enabled given the relevant control registers.
+ *
+ * @returns @c true if in PAE mode, @c false otherwise.
+ * @param uCr0 The CR0 value.
+ * @param uCr4 The CR4 value.
+ * @param uEferMsr The EFER value.
+ */
+DECLINLINE(bool) CPUMIsPaePagingEnabled(uint64_t uCr0, uint64_t uCr4, uint64_t uEferMsr)
+{
+ /* Intel mentions EFER.LMA and EFER.LME in different parts of their spec. We shall use EFER.LMA rather
+ than EFER.LME as it reflects if the CPU has entered paging with EFER.LME set. */
+ return ( (uCr4 & X86_CR4_PAE)
+ && (uCr0 & X86_CR0_PG)
+ && !(uEferMsr & MSR_K6_EFER_LMA));
+}
+
+/**
+ * Tests if the guest is running in PAE mode or not.
+ *
+ * @returns @c true if in PAE mode, @c false otherwise.
+ * @param pCtx Current CPU context.
+ */
+DECLINLINE(bool) CPUMIsGuestInPAEModeEx(PCCPUMCTX pCtx)
+{
+ return CPUMIsPaePagingEnabled(pCtx->cr0, pCtx->cr4, pCtx->msrEFER);
+}
+
+/**
+ * Tests if the guest has AMD SVM enabled or not.
+ *
+ * @returns true if SMV is enabled, otherwise false.
+ * @param pCtx Current CPU context.
+ */
+DECLINLINE(bool) CPUMIsGuestSvmEnabled(PCCPUMCTX pCtx)
+{
+ return RT_BOOL(pCtx->msrEFER & MSR_K6_EFER_SVME);
+}
+
+/**
+ * Tests if the guest has Intel VT-x enabled or not.
+ *
+ * @returns true if VMX is enabled, otherwise false.
+ * @param pCtx Current CPU context.
+ */
+DECLINLINE(bool) CPUMIsGuestVmxEnabled(PCCPUMCTX pCtx)
+{
+ return RT_BOOL(pCtx->cr4 & X86_CR4_VMXE);
+}
+
+/**
+ * Returns the guest's global-interrupt (GIF) flag.
+ *
+ * @returns true when global-interrupts are enabled, otherwise false.
+ * @param pCtx Current CPU context.
+ */
+DECLINLINE(bool) CPUMGetGuestGif(PCCPUMCTX pCtx)
+{
+ return pCtx->hwvirt.fGif;
+}
+
+/**
+ * Sets the guest's global-interrupt flag (GIF).
+ *
+ * @param pCtx Current CPU context.
+ * @param fGif The value to set.
+ */
+DECLINLINE(void) CPUMSetGuestGif(PCPUMCTX pCtx, bool fGif)
+{
+ pCtx->hwvirt.fGif = fGif;
+}
+
+/**
+ * Checks if we're in an "interrupt shadow", i.e. after a STI, POP SS or MOV SS.
+ *
+ * This also inhibit NMIs, except perhaps for nested guests.
+ *
+ * @returns true if interrupts are inhibited by interrupt shadow, false if not.
+ * @param pCtx Current guest CPU context.
+ * @note Requires pCtx->rip to be up to date.
+ * @note Does NOT clear CPUMCTX_INHIBIT_SHADOW when CPUMCTX::uRipInhibitInt
+ * differs from CPUMCTX::rip.
+ */
+DECLINLINE(bool) CPUMIsInInterruptShadow(PCCPUMCTX pCtx)
+{
+ if (!(pCtx->eflags.uBoth & CPUMCTX_INHIBIT_SHADOW))
+ return false;
+
+ CPUMCTX_ASSERT_NOT_EXTRN(pCtx, CPUMCTX_EXTRN_RIP);
+ return pCtx->uRipInhibitInt == pCtx->rip;
+}
+
+/**
+ * Checks if we're in an "interrupt shadow", i.e. after a STI, POP SS or MOV SS,
+ * updating the state if stale.
+ *
+ * This also inhibit NMIs, except perhaps for nested guests.
+ *
+ * @retval true if interrupts are inhibited by interrupt shadow.
+ * @retval false if not.
+ * @param pCtx Current guest CPU context.
+ * @note Requires pCtx->rip to be up to date.
+ */
+DECLINLINE(bool) CPUMIsInInterruptShadowWithUpdate(PCPUMCTX pCtx)
+{
+ if (!(pCtx->eflags.uBoth & CPUMCTX_INHIBIT_SHADOW))
+ return false;
+
+ CPUMCTX_ASSERT_NOT_EXTRN(pCtx, CPUMCTX_EXTRN_RIP);
+ if (pCtx->uRipInhibitInt == pCtx->rip)
+ return true;
+
+ pCtx->eflags.uBoth &= ~CPUMCTX_INHIBIT_SHADOW;
+ return false;
+}
+
+/**
+ * Checks if we're in an "interrupt shadow" due to a POP SS or MOV SS
+ * instruction.
+ *
+ * This also inhibit NMIs, except perhaps for nested guests.
+ *
+ * @retval true if interrupts are inhibited due to POP/MOV SS.
+ * @retval false if not.
+ * @param pCtx Current guest CPU context.
+ * @note Requires pCtx->rip to be up to date.
+ * @note Does NOT clear CPUMCTX_INHIBIT_SHADOW when CPUMCTX::uRipInhibitInt
+ * differs from CPUMCTX::rip.
+ * @note Both CPUMIsInInterruptShadowAfterSti() and this function may return
+ * true depending on the execution engine being used.
+ */
+DECLINLINE(bool) CPUMIsInInterruptShadowAfterSs(PCCPUMCTX pCtx)
+{
+ if (!(pCtx->eflags.uBoth & CPUMCTX_INHIBIT_SHADOW_SS))
+ return false;
+
+ CPUMCTX_ASSERT_NOT_EXTRN(pCtx, CPUMCTX_EXTRN_RIP);
+ return pCtx->uRipInhibitInt == pCtx->rip;
+}
+
+/**
+ * Checks if we're in an "interrupt shadow" due to an STI instruction.
+ *
+ * This also inhibit NMIs, except perhaps for nested guests.
+ *
+ * @retval true if interrupts are inhibited due to STI.
+ * @retval false if not.
+ * @param pCtx Current guest CPU context.
+ * @note Requires pCtx->rip to be up to date.
+ * @note Does NOT clear CPUMCTX_INHIBIT_SHADOW when CPUMCTX::uRipInhibitInt
+ * differs from CPUMCTX::rip.
+ * @note Both CPUMIsInInterruptShadowAfterSs() and this function may return
+ * true depending on the execution engine being used.
+ */
+DECLINLINE(bool) CPUMIsInInterruptShadowAfterSti(PCCPUMCTX pCtx)
+{
+ if (!(pCtx->eflags.uBoth & CPUMCTX_INHIBIT_SHADOW_STI))
+ return false;
+
+ CPUMCTX_ASSERT_NOT_EXTRN(pCtx, CPUMCTX_EXTRN_RIP);
+ return pCtx->uRipInhibitInt == pCtx->rip;
+}
+
+/**
+ * Sets the "interrupt shadow" flag, after a STI, POP SS or MOV SS instruction.
+ *
+ * @param pCtx Current guest CPU context.
+ * @note Requires pCtx->rip to be up to date.
+ */
+DECLINLINE(void) CPUMSetInInterruptShadow(PCPUMCTX pCtx)
+{
+ CPUMCTX_ASSERT_NOT_EXTRN(pCtx, CPUMCTX_EXTRN_RIP);
+ pCtx->eflags.uBoth |= CPUMCTX_INHIBIT_SHADOW;
+ pCtx->uRipInhibitInt = pCtx->rip;
+}
+
+/**
+ * Sets the "interrupt shadow" flag, after a STI, POP SS or MOV SS instruction,
+ * extended version.
+ *
+ * @param pCtx Current guest CPU context.
+ * @param rip The RIP for which it is inhibited.
+ */
+DECLINLINE(void) CPUMSetInInterruptShadowEx(PCPUMCTX pCtx, uint64_t rip)
+{
+ pCtx->eflags.uBoth |= CPUMCTX_INHIBIT_SHADOW;
+ pCtx->uRipInhibitInt = rip;
+}
+
+/**
+ * Sets the "interrupt shadow" flag after a POP SS or MOV SS instruction.
+ *
+ * @param pCtx Current guest CPU context.
+ * @note Requires pCtx->rip to be up to date.
+ */
+DECLINLINE(void) CPUMSetInInterruptShadowSs(PCPUMCTX pCtx)
+{
+ CPUMCTX_ASSERT_NOT_EXTRN(pCtx, CPUMCTX_EXTRN_RIP);
+ pCtx->eflags.uBoth |= CPUMCTX_INHIBIT_SHADOW_SS;
+ pCtx->uRipInhibitInt = pCtx->rip;
+}
+
+/**
+ * Sets the "interrupt shadow" flag after an STI instruction.
+ *
+ * @param pCtx Current guest CPU context.
+ * @note Requires pCtx->rip to be up to date.
+ */
+DECLINLINE(void) CPUMSetInInterruptShadowSti(PCPUMCTX pCtx)
+{
+ CPUMCTX_ASSERT_NOT_EXTRN(pCtx, CPUMCTX_EXTRN_RIP);
+ pCtx->eflags.uBoth |= CPUMCTX_INHIBIT_SHADOW_STI;
+ pCtx->uRipInhibitInt = pCtx->rip;
+}
+
+/**
+ * Clears the "interrupt shadow" flag.
+ *
+ * @param pCtx Current guest CPU context.
+ */
+DECLINLINE(void) CPUMClearInterruptShadow(PCPUMCTX pCtx)
+{
+ pCtx->eflags.uBoth &= ~CPUMCTX_INHIBIT_SHADOW;
+}
+
+/**
+ * Update the "interrupt shadow" flag.
+ *
+ * @param pCtx Current guest CPU context.
+ * @param fInhibited The new state.
+ * @note Requires pCtx->rip to be up to date.
+ */
+DECLINLINE(void) CPUMUpdateInterruptShadow(PCPUMCTX pCtx, bool fInhibited)
+{
+ CPUMCTX_ASSERT_NOT_EXTRN(pCtx, CPUMCTX_EXTRN_RIP);
+ if (!fInhibited)
+ pCtx->eflags.uBoth &= ~CPUMCTX_INHIBIT_SHADOW;
+ else
+ {
+ pCtx->eflags.uBoth |= CPUMCTX_INHIBIT_SHADOW;
+ pCtx->uRipInhibitInt = pCtx->rip;
+ }
+}
+
+/**
+ * Update the "interrupt shadow" flag, extended version.
+ *
+ * @returns fInhibited.
+ * @param pCtx Current guest CPU context.
+ * @param fInhibited The new state.
+ * @param rip The RIP for which it is inhibited.
+ */
+DECLINLINE(bool) CPUMUpdateInterruptShadowEx(PCPUMCTX pCtx, bool fInhibited, uint64_t rip)
+{
+ if (!fInhibited)
+ pCtx->eflags.uBoth &= ~CPUMCTX_INHIBIT_SHADOW;
+ else
+ {
+ pCtx->eflags.uBoth |= CPUMCTX_INHIBIT_SHADOW;
+ pCtx->uRipInhibitInt = rip;
+ }
+ return fInhibited;
+}
+
+/**
+ * Update the two "interrupt shadow" flags separately, extended version.
+ *
+ * @param pCtx Current guest CPU context.
+ * @param fInhibitedBySs The new state for the MOV SS & POP SS aspect.
+ * @param fInhibitedBySti The new state for the STI aspect.
+ * @param rip The RIP for which it is inhibited.
+ */
+DECLINLINE(void) CPUMUpdateInterruptShadowSsStiEx(PCPUMCTX pCtx, bool fInhibitedBySs, bool fInhibitedBySti, uint64_t rip)
+{
+ if (!(fInhibitedBySs | fInhibitedBySti))
+ pCtx->eflags.uBoth &= ~CPUMCTX_INHIBIT_SHADOW;
+ else
+ {
+ pCtx->eflags.uBoth |= (fInhibitedBySs ? CPUMCTX_INHIBIT_SHADOW_SS : UINT32_C(0))
+ | (fInhibitedBySti ? CPUMCTX_INHIBIT_SHADOW_STI : UINT32_C(0));
+ pCtx->uRipInhibitInt = rip;
+ }
+}
+
+/* VMX forward declarations used by extended function versions: */
+DECLINLINE(bool) CPUMIsGuestInVmxNonRootMode(PCCPUMCTX pCtx);
+DECLINLINE(bool) CPUMIsGuestVmxPinCtlsSet(PCCPUMCTX pCtx, uint32_t uPinCtls);
+DECLINLINE(bool) CPUMIsGuestVmxVirtNmiBlocking(PCCPUMCTX pCtx);
+DECLINLINE(void) CPUMSetGuestVmxVirtNmiBlocking(PCPUMCTX pCtx, bool fBlocking);
+
+/**
+ * Checks whether interrupts, include NMIs, are inhibited by pending NMI
+ * delivery.
+ *
+ * This only checks the inhibit mask.
+ *
+ * @retval true if interrupts are inhibited by NMI handling.
+ * @retval false if interrupts are not inhibited by NMI handling.
+ * @param pCtx Current guest CPU context.
+ */
+DECLINLINE(bool) CPUMAreInterruptsInhibitedByNmi(PCCPUMCTX pCtx)
+{
+ return (pCtx->eflags.uBoth & CPUMCTX_INHIBIT_NMI) != 0;
+}
+
+/**
+ * Extended version of CPUMAreInterruptsInhibitedByNmi() that takes VMX non-root
+ * mode into account when check whether interrupts are inhibited by NMI.
+ *
+ * @retval true if interrupts are inhibited by NMI handling.
+ * @retval false if interrupts are not inhibited by NMI handling.
+ * @param pCtx Current guest CPU context.
+ */
+DECLINLINE(bool) CPUMAreInterruptsInhibitedByNmiEx(PCCPUMCTX pCtx)
+{
+ /* See CPUMUpdateInterruptInhibitingByNmiEx for comments. */
+ if ( !CPUMIsGuestInVmxNonRootMode(pCtx)
+ || !CPUMIsGuestVmxPinCtlsSet(pCtx, VMX_PIN_CTLS_VIRT_NMI))
+ return CPUMAreInterruptsInhibitedByNmi(pCtx);
+ return CPUMIsGuestVmxVirtNmiBlocking(pCtx);
+}
+
+/**
+ * Marks interrupts, include NMIs, as inhibited by pending NMI delivery.
+ *
+ * @param pCtx Current guest CPU context.
+ */
+DECLINLINE(void) CPUMSetInterruptInhibitingByNmi(PCPUMCTX pCtx)
+{
+ pCtx->eflags.uBoth |= CPUMCTX_INHIBIT_NMI;
+}
+
+/**
+ * Extended version of CPUMSetInterruptInhibitingByNmi() that takes VMX non-root
+ * mode into account when marking interrupts as inhibited by NMI.
+ *
+ * @param pCtx Current guest CPU context.
+ */
+DECLINLINE(void) CPUMSetInterruptInhibitingByNmiEx(PCPUMCTX pCtx)
+{
+ /* See CPUMUpdateInterruptInhibitingByNmiEx for comments. */
+ if ( !CPUMIsGuestInVmxNonRootMode(pCtx)
+ || !CPUMIsGuestVmxPinCtlsSet(pCtx, VMX_PIN_CTLS_VIRT_NMI))
+ CPUMSetInterruptInhibitingByNmi(pCtx);
+ else
+ CPUMSetGuestVmxVirtNmiBlocking(pCtx, true);
+}
+
+/**
+ * Marks interrupts, include NMIs, as no longer inhibited by pending NMI
+ * delivery.
+ *
+ * @param pCtx Current guest CPU context.
+ */
+DECLINLINE(void) CPUMClearInterruptInhibitingByNmi(PCPUMCTX pCtx)
+{
+ pCtx->eflags.uBoth &= ~CPUMCTX_INHIBIT_NMI;
+}
+
+/**
+ * Extended version of CPUMClearInterruptInhibitingByNmi() that takes VMX
+ * non-root mode into account when doing the updating.
+ *
+ * @param pCtx Current guest CPU context.
+ */
+DECLINLINE(void) CPUMClearInterruptInhibitingByNmiEx(PCPUMCTX pCtx)
+{
+ /* See CPUMUpdateInterruptInhibitingByNmiEx for comments. */
+ if ( !CPUMIsGuestInVmxNonRootMode(pCtx)
+ || !CPUMIsGuestVmxPinCtlsSet(pCtx, VMX_PIN_CTLS_VIRT_NMI))
+ CPUMClearInterruptInhibitingByNmi(pCtx);
+ else
+ CPUMSetGuestVmxVirtNmiBlocking(pCtx, false);
+}
+
+/**
+ * Update whether interrupts, include NMIs, are inhibited by pending NMI
+ * delivery.
+ *
+ * @param pCtx Current guest CPU context.
+ * @param fInhibited The new state.
+ */
+DECLINLINE(void) CPUMUpdateInterruptInhibitingByNmi(PCPUMCTX pCtx, bool fInhibited)
+{
+ if (!fInhibited)
+ pCtx->eflags.uBoth &= ~CPUMCTX_INHIBIT_NMI;
+ else
+ pCtx->eflags.uBoth |= CPUMCTX_INHIBIT_NMI;
+}
+
+/**
+ * Extended version of CPUMUpdateInterruptInhibitingByNmi() that takes VMX
+ * non-root mode into account when doing the updating.
+ *
+ * @param pCtx Current guest CPU context.
+ * @param fInhibited The new state.
+ */
+DECLINLINE(void) CPUMUpdateInterruptInhibitingByNmiEx(PCPUMCTX pCtx, bool fInhibited)
+{
+ /*
+ * Set the state of guest-NMI blocking in any of the following cases:
+ * - We're not executing a nested-guest.
+ * - We're executing an SVM nested-guest[1].
+ * - We're executing a VMX nested-guest without virtual-NMIs enabled.
+ *
+ * [1] -- SVM does not support virtual-NMIs or virtual-NMI blocking.
+ * SVM hypervisors must track NMI blocking themselves by intercepting
+ * the IRET instruction after injection of an NMI.
+ */
+ if ( !CPUMIsGuestInVmxNonRootMode(pCtx)
+ || !CPUMIsGuestVmxPinCtlsSet(pCtx, VMX_PIN_CTLS_VIRT_NMI))
+ CPUMUpdateInterruptInhibitingByNmi(pCtx, fInhibited);
+ /*
+ * Set the state of virtual-NMI blocking, if we are executing a
+ * VMX nested-guest with virtual-NMIs enabled.
+ */
+ else
+ CPUMSetGuestVmxVirtNmiBlocking(pCtx, fInhibited);
+}
+
+
+/**
+ * Checks if we are executing inside an SVM nested hardware-virtualized guest.
+ *
+ * @returns @c true if in SVM nested-guest mode, @c false otherwise.
+ * @param pCtx Current CPU context.
+ */
+DECLINLINE(bool) CPUMIsGuestInSvmNestedHwVirtMode(PCCPUMCTX pCtx)
+{
+ /*
+ * With AMD-V, the VMRUN intercept is a pre-requisite to entering SVM guest-mode.
+ * See AMD spec. 15.5 "VMRUN instruction" subsection "Canonicalization and Consistency Checks".
+ */
+#ifndef IN_RC
+ if ( pCtx->hwvirt.enmHwvirt != CPUMHWVIRT_SVM
+ || !(pCtx->hwvirt.svm.Vmcb.ctrl.u64InterceptCtrl & SVM_CTRL_INTERCEPT_VMRUN))
+ return false;
+ return true;
+#else
+ NOREF(pCtx);
+ return false;
+#endif
+}
+
+/**
+ * Checks if the guest is in VMX non-root operation.
+ *
+ * @returns @c true if in VMX non-root operation, @c false otherwise.
+ * @param pCtx Current CPU context.
+ */
+DECLINLINE(bool) CPUMIsGuestInVmxNonRootMode(PCCPUMCTX pCtx)
+{
+#ifndef IN_RC
+ if (pCtx->hwvirt.enmHwvirt != CPUMHWVIRT_VMX)
+ return false;
+ Assert(!pCtx->hwvirt.vmx.fInVmxNonRootMode || pCtx->hwvirt.vmx.fInVmxRootMode);
+ return pCtx->hwvirt.vmx.fInVmxNonRootMode;
+#else
+ NOREF(pCtx);
+ return false;
+#endif
+}
+
+/**
+ * Checks if we are executing inside an SVM or VMX nested hardware-virtualized
+ * guest.
+ *
+ * @returns @c true if in nested-guest mode, @c false otherwise.
+ * @param pCtx Current CPU context.
+ */
+DECLINLINE(bool) CPUMIsGuestInNestedHwvirtMode(PCCPUMCTX pCtx)
+{
+#if 0
+ return CPUMIsGuestInVmxNonRootMode(pCtx) || CPUMIsGuestInSvmNestedHwVirtMode(pCtx);
+#else
+ if (pCtx->hwvirt.enmHwvirt == CPUMHWVIRT_NONE)
+ return false;
+ if (pCtx->hwvirt.enmHwvirt == CPUMHWVIRT_VMX)
+ {
+ Assert(!pCtx->hwvirt.vmx.fInVmxNonRootMode || pCtx->hwvirt.vmx.fInVmxRootMode);
+ return pCtx->hwvirt.vmx.fInVmxNonRootMode;
+ }
+ Assert(pCtx->hwvirt.enmHwvirt == CPUMHWVIRT_SVM);
+ return RT_BOOL(pCtx->hwvirt.svm.Vmcb.ctrl.u64InterceptCtrl & SVM_CTRL_INTERCEPT_VMRUN);
+#endif
+}
+
+/**
+ * Checks if we are executing inside an SVM or VMX nested hardware-virtualized
+ * guest.
+ *
+ * @retval CPUMHWVIRT_NONE if not in SVM or VMX non-root mode.
+ * @retval CPUMHWVIRT_VMX if in VMX non-root mode.
+ * @retval CPUMHWVIRT_SVM if in SVM non-root mode.
+ * @param pCtx Current CPU context.
+ */
+DECLINLINE(CPUMHWVIRT) CPUMGetGuestInNestedHwvirtMode(PCCPUMCTX pCtx)
+{
+ if (pCtx->hwvirt.enmHwvirt == CPUMHWVIRT_NONE)
+ return CPUMHWVIRT_NONE;
+ if (pCtx->hwvirt.enmHwvirt == CPUMHWVIRT_VMX)
+ {
+ Assert(!pCtx->hwvirt.vmx.fInVmxNonRootMode || pCtx->hwvirt.vmx.fInVmxRootMode);
+ return pCtx->hwvirt.vmx.fInVmxNonRootMode ? CPUMHWVIRT_VMX : CPUMHWVIRT_NONE;
+ }
+ Assert(pCtx->hwvirt.enmHwvirt == CPUMHWVIRT_SVM);
+ return pCtx->hwvirt.svm.Vmcb.ctrl.u64InterceptCtrl & SVM_CTRL_INTERCEPT_VMRUN ? CPUMHWVIRT_SVM : CPUMHWVIRT_NONE;
+}
+
+/**
+ * Checks if the guest is in VMX root operation.
+ *
+ * @returns @c true if in VMX root operation, @c false otherwise.
+ * @param pCtx Current CPU context.
+ */
+DECLINLINE(bool) CPUMIsGuestInVmxRootMode(PCCPUMCTX pCtx)
+{
+#ifndef IN_RC
+ if (pCtx->hwvirt.enmHwvirt != CPUMHWVIRT_VMX)
+ return false;
+ return pCtx->hwvirt.vmx.fInVmxRootMode;
+#else
+ NOREF(pCtx);
+ return false;
+#endif
+}
+
+# ifndef IN_RC
+
+/**
+ * Checks if the nested-guest VMCB has the specified ctrl/instruction intercept
+ * active.
+ *
+ * @returns @c true if in intercept is set, @c false otherwise.
+ * @param pVCpu The cross context virtual CPU structure of the calling EMT.
+ * @param pCtx Current CPU context.
+ * @param fIntercept The SVM control/instruction intercept, see
+ * SVM_CTRL_INTERCEPT_*.
+ */
+DECLINLINE(bool) CPUMIsGuestSvmCtrlInterceptSet(PCVMCPU pVCpu, PCCPUMCTX pCtx, uint64_t fIntercept)
+{
+ if (pCtx->hwvirt.enmHwvirt != CPUMHWVIRT_SVM)
+ return false;
+ uint64_t u64Intercepts;
+ if (!HMGetGuestSvmCtrlIntercepts(pVCpu, &u64Intercepts))
+ u64Intercepts = pCtx->hwvirt.svm.Vmcb.ctrl.u64InterceptCtrl;
+ return RT_BOOL(u64Intercepts & fIntercept);
+}
+
+/**
+ * Checks if the nested-guest VMCB has the specified CR read intercept active.
+ *
+ * @returns @c true if in intercept is set, @c false otherwise.
+ * @param pVCpu The cross context virtual CPU structure of the calling EMT.
+ * @param pCtx Current CPU context.
+ * @param uCr The CR register number (0 to 15).
+ */
+DECLINLINE(bool) CPUMIsGuestSvmReadCRxInterceptSet(PCVMCPU pVCpu, PCCPUMCTX pCtx, uint8_t uCr)
+{
+ Assert(uCr < 16);
+ if (pCtx->hwvirt.enmHwvirt != CPUMHWVIRT_SVM)
+ return false;
+ uint16_t u16Intercepts;
+ if (!HMGetGuestSvmReadCRxIntercepts(pVCpu, &u16Intercepts))
+ u16Intercepts = pCtx->hwvirt.svm.Vmcb.ctrl.u16InterceptRdCRx;
+ return RT_BOOL(u16Intercepts & (UINT16_C(1) << uCr));
+}
+
+/**
+ * Checks if the nested-guest VMCB has the specified CR write intercept active.
+ *
+ * @returns @c true if in intercept is set, @c false otherwise.
+ * @param pVCpu The cross context virtual CPU structure of the calling EMT.
+ * @param pCtx Current CPU context.
+ * @param uCr The CR register number (0 to 15).
+ */
+DECLINLINE(bool) CPUMIsGuestSvmWriteCRxInterceptSet(PCVMCPU pVCpu, PCCPUMCTX pCtx, uint8_t uCr)
+{
+ Assert(uCr < 16);
+ if (pCtx->hwvirt.enmHwvirt != CPUMHWVIRT_SVM)
+ return false;
+ uint16_t u16Intercepts;
+ if (!HMGetGuestSvmWriteCRxIntercepts(pVCpu, &u16Intercepts))
+ u16Intercepts = pCtx->hwvirt.svm.Vmcb.ctrl.u16InterceptWrCRx;
+ return RT_BOOL(u16Intercepts & (UINT16_C(1) << uCr));
+}
+
+/**
+ * Checks if the nested-guest VMCB has the specified DR read intercept active.
+ *
+ * @returns @c true if in intercept is set, @c false otherwise.
+ * @param pVCpu The cross context virtual CPU structure of the calling EMT.
+ * @param pCtx Current CPU context.
+ * @param uDr The DR register number (0 to 15).
+ */
+DECLINLINE(bool) CPUMIsGuestSvmReadDRxInterceptSet(PCVMCPU pVCpu, PCCPUMCTX pCtx, uint8_t uDr)
+{
+ Assert(uDr < 16);
+ if (pCtx->hwvirt.enmHwvirt != CPUMHWVIRT_SVM)
+ return false;
+ uint16_t u16Intercepts;
+ if (!HMGetGuestSvmReadDRxIntercepts(pVCpu, &u16Intercepts))
+ u16Intercepts = pCtx->hwvirt.svm.Vmcb.ctrl.u16InterceptRdDRx;
+ return RT_BOOL(u16Intercepts & (UINT16_C(1) << uDr));
+}
+
+/**
+ * Checks if the nested-guest VMCB has the specified DR write intercept active.
+ *
+ * @returns @c true if in intercept is set, @c false otherwise.
+ * @param pVCpu The cross context virtual CPU structure of the calling EMT.
+ * @param pCtx Current CPU context.
+ * @param uDr The DR register number (0 to 15).
+ */
+DECLINLINE(bool) CPUMIsGuestSvmWriteDRxInterceptSet(PCVMCPU pVCpu, PCCPUMCTX pCtx, uint8_t uDr)
+{
+ Assert(uDr < 16);
+ if (pCtx->hwvirt.enmHwvirt != CPUMHWVIRT_SVM)
+ return false;
+ uint16_t u16Intercepts;
+ if (!HMGetGuestSvmWriteDRxIntercepts(pVCpu, &u16Intercepts))
+ u16Intercepts = pCtx->hwvirt.svm.Vmcb.ctrl.u16InterceptWrDRx;
+ return RT_BOOL(u16Intercepts & (UINT16_C(1) << uDr));
+}
+
+/**
+ * Checks if the nested-guest VMCB has the specified exception intercept active.
+ *
+ * @returns @c true if in intercept is active, @c false otherwise.
+ * @param pVCpu The cross context virtual CPU structure of the calling EMT.
+ * @param pCtx Current CPU context.
+ * @param uVector The exception / interrupt vector.
+ */
+DECLINLINE(bool) CPUMIsGuestSvmXcptInterceptSet(PCVMCPU pVCpu, PCCPUMCTX pCtx, uint8_t uVector)
+{
+ Assert(uVector <= X86_XCPT_LAST);
+ if (pCtx->hwvirt.enmHwvirt != CPUMHWVIRT_SVM)
+ return false;
+ uint32_t u32Intercepts;
+ if (!HMGetGuestSvmXcptIntercepts(pVCpu, &u32Intercepts))
+ u32Intercepts = pCtx->hwvirt.svm.Vmcb.ctrl.u32InterceptXcpt;
+ return RT_BOOL(u32Intercepts & RT_BIT(uVector));
+}
+
+/**
+ * Checks if the nested-guest VMCB has virtual-interrupt masking enabled.
+ *
+ * @returns @c true if virtual-interrupts are masked, @c false otherwise.
+ * @param pVCpu The cross context virtual CPU structure of the calling EMT.
+ * @param pCtx Current CPU context.
+ *
+ * @remarks Should only be called when SVM feature is exposed to the guest.
+ */
+DECLINLINE(bool) CPUMIsGuestSvmVirtIntrMasking(PCVMCPU pVCpu, PCCPUMCTX pCtx)
+{
+ if (pCtx->hwvirt.enmHwvirt != CPUMHWVIRT_SVM)
+ return false;
+ bool fVIntrMasking;
+ if (!HMGetGuestSvmVirtIntrMasking(pVCpu, &fVIntrMasking))
+ fVIntrMasking = pCtx->hwvirt.svm.Vmcb.ctrl.IntCtrl.n.u1VIntrMasking;
+ return fVIntrMasking;
+}
+
+/**
+ * Checks if the nested-guest VMCB has nested-paging enabled.
+ *
+ * @returns @c true if nested-paging is enabled, @c false otherwise.
+ * @param pVCpu The cross context virtual CPU structure of the calling EMT.
+ * @param pCtx Current CPU context.
+ *
+ * @remarks Should only be called when SVM feature is exposed to the guest.
+ */
+DECLINLINE(bool) CPUMIsGuestSvmNestedPagingEnabled(PCVMCPU pVCpu, PCCPUMCTX pCtx)
+{
+ if (pCtx->hwvirt.enmHwvirt != CPUMHWVIRT_SVM)
+ return false;
+ bool fNestedPaging;
+ if (!HMGetGuestSvmNestedPaging(pVCpu, &fNestedPaging))
+ fNestedPaging = pCtx->hwvirt.svm.Vmcb.ctrl.NestedPagingCtrl.n.u1NestedPaging;
+ return fNestedPaging;
+}
+
+/**
+ * Gets the nested-guest VMCB pause-filter count.
+ *
+ * @returns The pause-filter count.
+ * @param pVCpu The cross context virtual CPU structure of the calling EMT.
+ * @param pCtx Current CPU context.
+ *
+ * @remarks Should only be called when SVM feature is exposed to the guest.
+ */
+DECLINLINE(uint16_t) CPUMGetGuestSvmPauseFilterCount(PCVMCPU pVCpu, PCCPUMCTX pCtx)
+{
+ if (pCtx->hwvirt.enmHwvirt != CPUMHWVIRT_SVM)
+ return false;
+ uint16_t u16PauseFilterCount;
+ if (!HMGetGuestSvmPauseFilterCount(pVCpu, &u16PauseFilterCount))
+ u16PauseFilterCount = pCtx->hwvirt.svm.Vmcb.ctrl.u16PauseFilterCount;
+ return u16PauseFilterCount;
+}
+
+/**
+ * Updates the NextRIP (NRIP) field in the nested-guest VMCB.
+ *
+ * @param pVCpu The cross context virtual CPU structure of the calling EMT.
+ * @param pCtx Current CPU context.
+ * @param cbInstr The length of the current instruction in bytes.
+ *
+ * @remarks Should only be called when SVM feature is exposed to the guest.
+ */
+DECLINLINE(void) CPUMGuestSvmUpdateNRip(PVMCPU pVCpu, PCPUMCTX pCtx, uint8_t cbInstr)
+{
+ RT_NOREF(pVCpu);
+ Assert(pCtx->hwvirt.enmHwvirt == CPUMHWVIRT_SVM);
+ pCtx->hwvirt.svm.Vmcb.ctrl.u64NextRIP = pCtx->rip + cbInstr;
+}
+
+/**
+ * Checks whether one of the given Pin-based VM-execution controls are set when
+ * executing a nested-guest.
+ *
+ * @returns @c true if set, @c false otherwise.
+ * @param pCtx Current CPU context.
+ * @param uPinCtls The Pin-based VM-execution controls to check.
+ *
+ * @remarks This does not check if all given controls are set if more than one
+ * control is passed in @a uPinCtl.
+ */
+DECLINLINE(bool) CPUMIsGuestVmxPinCtlsSet(PCCPUMCTX pCtx, uint32_t uPinCtls)
+{
+ Assert(CPUMIsGuestInVmxNonRootMode(pCtx));
+ return RT_BOOL(pCtx->hwvirt.vmx.Vmcs.u32PinCtls & uPinCtls);
+}
+
+/**
+ * Checks whether one of the given Processor-based VM-execution controls are set
+ * when executing a nested-guest.
+ *
+ * @returns @c true if set, @c false otherwise.
+ * @param pCtx Current CPU context.
+ * @param uProcCtls The Processor-based VM-execution controls to check.
+ *
+ * @remarks This does not check if all given controls are set if more than one
+ * control is passed in @a uProcCtls.
+ */
+DECLINLINE(bool) CPUMIsGuestVmxProcCtlsSet(PCCPUMCTX pCtx, uint32_t uProcCtls)
+{
+ Assert(CPUMIsGuestInVmxNonRootMode(pCtx));
+ return RT_BOOL(pCtx->hwvirt.vmx.Vmcs.u32ProcCtls & uProcCtls);
+}
+
+/**
+ * Checks whether one of the given Secondary Processor-based VM-execution controls
+ * are set when executing a nested-guest.
+ *
+ * @returns @c true if set, @c false otherwise.
+ * @param pCtx Current CPU context.
+ * @param uProcCtls2 The Secondary Processor-based VM-execution controls to
+ * check.
+ *
+ * @remarks This does not check if all given controls are set if more than one
+ * control is passed in @a uProcCtls2.
+ */
+DECLINLINE(bool) CPUMIsGuestVmxProcCtls2Set(PCCPUMCTX pCtx, uint32_t uProcCtls2)
+{
+ Assert(CPUMIsGuestInVmxNonRootMode(pCtx));
+ return RT_BOOL(pCtx->hwvirt.vmx.Vmcs.u32ProcCtls2 & uProcCtls2);
+}
+
+/**
+ * Checks whether one of the given Tertiary Processor-based VM-execution controls
+ * are set when executing a nested-guest.
+ *
+ * @returns @c true if set, @c false otherwise.
+ * @param pCtx Current CPU context.
+ * @param uProcCtls3 The Tertiary Processor-based VM-execution controls to
+ * check.
+ *
+ * @remarks This does not check if all given controls are set if more than one
+ * control is passed in @a uProcCtls3.
+ */
+DECLINLINE(bool) CPUMIsGuestVmxProcCtls3Set(PCCPUMCTX pCtx, uint64_t uProcCtls3)
+{
+ Assert(CPUMIsGuestInVmxNonRootMode(pCtx));
+ return RT_BOOL(pCtx->hwvirt.vmx.Vmcs.u64ProcCtls3.u & uProcCtls3);
+}
+
+/**
+ * Checks whether one of the given VM-exit controls are set when executing a
+ * nested-guest.
+ *
+ * @returns @c true if set, @c false otherwise.
+ * @param pCtx Current CPU context.
+ * @param uExitCtls The VM-exit controls to check.
+ *
+ * @remarks This does not check if all given controls are set if more than one
+ * control is passed in @a uExitCtls.
+ */
+DECLINLINE(bool) CPUMIsGuestVmxExitCtlsSet(PCCPUMCTX pCtx, uint32_t uExitCtls)
+{
+ Assert(CPUMIsGuestInVmxNonRootMode(pCtx));
+ return RT_BOOL(pCtx->hwvirt.vmx.Vmcs.u32ExitCtls & uExitCtls);
+}
+
+/**
+ * Checks whether one of the given VM-entry controls are set when executing a
+ * nested-guest.
+ *
+ * @returns @c true if set, @c false otherwise.
+ * @param pCtx Current CPU context.
+ * @param uEntryCtls The VM-entry controls to check.
+ *
+ * @remarks This does not check if all given controls are set if more than one
+ * control is passed in @a uEntryCtls.
+ */
+DECLINLINE(bool) CPUMIsGuestVmxEntryCtlsSet(PCCPUMCTX pCtx, uint32_t uEntryCtls)
+{
+ Assert(CPUMIsGuestInVmxNonRootMode(pCtx));
+ return RT_BOOL(pCtx->hwvirt.vmx.Vmcs.u32EntryCtls & uEntryCtls);
+}
+
+/**
+ * Checks whether events injected in the nested-guest are subject to VM-exit checks.
+ *
+ * @returns @c true if set, @c false otherwise.
+ * @param pCtx Current CPU context.
+ */
+DECLINLINE(bool) CPUMIsGuestVmxInterceptEvents(PCCPUMCTX pCtx)
+{
+ Assert(CPUMIsGuestInVmxNonRootMode(pCtx));
+ return pCtx->hwvirt.vmx.fInterceptEvents;
+}
+
+/**
+ * Sets whether events injected in the nested-guest are subject to VM-exit checks.
+ *
+ * @param pCtx Current CPU context.
+ * @param fIntercept Whether to subject injected events to VM-exits or not.
+ */
+DECLINLINE(void) CPUMSetGuestVmxInterceptEvents(PCPUMCTX pCtx, bool fInterceptEvents)
+{
+ Assert(CPUMIsGuestInVmxNonRootMode(pCtx));
+ pCtx->hwvirt.vmx.fInterceptEvents = fInterceptEvents;
+}
+
+/**
+ * Checks whether the given exception causes a VM-exit.
+ *
+ * The exception type include hardware exceptions, software exceptions (#BP, #OF)
+ * and privileged software exceptions (#DB generated by INT1/ICEBP).
+ *
+ * Software interrupts do -not- cause VM-exits and hence must not be used with this
+ * function.
+ *
+ * @returns @c true if the exception causes a VM-exit, @c false otherwise.
+ * @param pCtx Current CPU context.
+ * @param uVector The exception vector.
+ * @param uErrCode The error code associated with the exception. Pass 0 if not
+ * applicable.
+ */
+DECLINLINE(bool) CPUMIsGuestVmxXcptInterceptSet(PCCPUMCTX pCtx, uint8_t uVector, uint32_t uErrCode)
+{
+ Assert(uVector <= X86_XCPT_LAST);
+
+ Assert(CPUMIsGuestInVmxNonRootMode(pCtx));
+
+ /* NMIs have a dedicated VM-execution control for causing VM-exits. */
+ if (uVector == X86_XCPT_NMI)
+ return RT_BOOL(pCtx->hwvirt.vmx.Vmcs.u32PinCtls & VMX_PIN_CTLS_NMI_EXIT);
+
+ /* Page-faults are subject to masking using its error code. */
+ uint32_t fXcptBitmap = pCtx->hwvirt.vmx.Vmcs.u32XcptBitmap;
+ if (uVector == X86_XCPT_PF)
+ {
+ uint32_t const fXcptPFMask = pCtx->hwvirt.vmx.Vmcs.u32XcptPFMask;
+ uint32_t const fXcptPFMatch = pCtx->hwvirt.vmx.Vmcs.u32XcptPFMatch;
+ if ((uErrCode & fXcptPFMask) != fXcptPFMatch)
+ fXcptBitmap ^= RT_BIT(X86_XCPT_PF);
+ }
+
+ /* Consult the exception bitmap for all other exceptions. */
+ if (fXcptBitmap & RT_BIT(uVector))
+ return true;
+ return false;
+}
+
+
+/**
+ * Checks whether the guest is in VMX non-root mode and using EPT paging.
+ *
+ * @returns @c true if in VMX non-root operation with EPT, @c false otherwise.
+ * @param pCtx Current CPU context.
+ */
+DECLINLINE(bool) CPUMIsGuestVmxEptPagingEnabledEx(PCCPUMCTX pCtx)
+{
+ return CPUMIsGuestInVmxNonRootMode(pCtx)
+ && CPUMIsGuestVmxProcCtls2Set(pCtx, VMX_PROC_CTLS2_EPT);
+}
+
+
+/**
+ * Implements VMSucceed for VMX instruction success.
+ *
+ * @param pCtx Current CPU context.
+ */
+DECLINLINE(void) CPUMSetGuestVmxVmSucceed(PCPUMCTX pCtx)
+{
+ pCtx->eflags.uBoth &= ~(X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF);
+}
+
+/**
+ * Implements VMFailInvalid for VMX instruction failure.
+ *
+ * @param pCtx Current CPU context.
+ */
+DECLINLINE(void) CPUMSetGuestVmxVmFailInvalid(PCPUMCTX pCtx)
+{
+ pCtx->eflags.uBoth &= ~(X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF);
+ pCtx->eflags.uBoth |= X86_EFL_CF;
+}
+
+/**
+ * Implements VMFailValid for VMX instruction failure.
+ *
+ * @param pCtx Current CPU context.
+ * @param enmInsErr The VM instruction error.
+ */
+DECLINLINE(void) CPUMSetGuestVmxVmFailValid(PCPUMCTX pCtx, VMXINSTRERR enmInsErr)
+{
+ pCtx->eflags.uBoth &= ~(X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF);
+ pCtx->eflags.uBoth |= X86_EFL_ZF;
+ pCtx->hwvirt.vmx.Vmcs.u32RoVmInstrError = enmInsErr;
+}
+
+/**
+ * Implements VMFail for VMX instruction failure.
+ *
+ * @param pCtx Current CPU context.
+ * @param enmInsErr The VM instruction error.
+ */
+DECLINLINE(void) CPUMSetGuestVmxVmFail(PCPUMCTX pCtx, VMXINSTRERR enmInsErr)
+{
+ if (pCtx->hwvirt.vmx.GCPhysVmcs != NIL_RTGCPHYS)
+ CPUMSetGuestVmxVmFailValid(pCtx, enmInsErr);
+ else
+ CPUMSetGuestVmxVmFailInvalid(pCtx);
+}
+
+/**
+ * Returns the guest-physical address of the APIC-access page when executing a
+ * nested-guest.
+ *
+ * @returns The APIC-access page guest-physical address.
+ * @param pCtx Current CPU context.
+ */
+DECLINLINE(uint64_t) CPUMGetGuestVmxApicAccessPageAddrEx(PCCPUMCTX pCtx)
+{
+ Assert(CPUMIsGuestInVmxNonRootMode(pCtx));
+ return pCtx->hwvirt.vmx.Vmcs.u64AddrApicAccess.u;
+}
+
+/**
+ * Gets the nested-guest CR0 subject to the guest/host mask and the read-shadow.
+ *
+ * @returns The nested-guest CR0.
+ * @param pCtx Current CPU context.
+ * @param fGstHostMask The CR0 guest/host mask to use.
+ */
+DECLINLINE(uint64_t) CPUMGetGuestVmxMaskedCr0(PCCPUMCTX pCtx, uint64_t fGstHostMask)
+{
+ /*
+ * For each CR0 bit owned by the host, the corresponding bit from the
+ * CR0 read shadow is loaded. For each CR0 bit that is not owned by the host,
+ * the corresponding bit from the guest CR0 is loaded.
+ *
+ * See Intel Spec. 25.3 "Changes To Instruction Behavior In VMX Non-root Operation".
+ */
+ Assert(CPUMIsGuestInVmxNonRootMode(pCtx));
+ uint64_t const uGstCr0 = pCtx->cr0;
+ uint64_t const fReadShadow = pCtx->hwvirt.vmx.Vmcs.u64Cr0ReadShadow.u;
+ return (fReadShadow & fGstHostMask) | (uGstCr0 & ~fGstHostMask);
+}
+
+/**
+ * Gets the nested-guest CR4 subject to the guest/host mask and the read-shadow.
+ *
+ * @returns The nested-guest CR4.
+ * @param pCtx Current CPU context.
+ * @param fGstHostMask The CR4 guest/host mask to use.
+ */
+DECLINLINE(uint64_t) CPUMGetGuestVmxMaskedCr4(PCCPUMCTX pCtx, uint64_t fGstHostMask)
+{
+ /*
+ * For each CR4 bit owned by the host, the corresponding bit from the
+ * CR4 read shadow is loaded. For each CR4 bit that is not owned by the host,
+ * the corresponding bit from the guest CR4 is loaded.
+ *
+ * See Intel Spec. 25.3 "Changes To Instruction Behavior In VMX Non-root Operation".
+ */
+ Assert(CPUMIsGuestInVmxNonRootMode(pCtx));
+ uint64_t const uGstCr4 = pCtx->cr4;
+ uint64_t const fReadShadow = pCtx->hwvirt.vmx.Vmcs.u64Cr4ReadShadow.u;
+ return (fReadShadow & fGstHostMask) | (uGstCr4 & ~fGstHostMask);
+}
+
+/**
+ * Checks whether the LMSW access causes a VM-exit or not.
+ *
+ * @returns @c true if the LMSW access causes a VM-exit, @c false otherwise.
+ * @param pCtx Current CPU context.
+ * @param uNewMsw The LMSW source operand (the Machine Status Word).
+ */
+DECLINLINE(bool) CPUMIsGuestVmxLmswInterceptSet(PCCPUMCTX pCtx, uint16_t uNewMsw)
+{
+ /*
+ * LMSW VM-exits are subject to the CR0 guest/host mask and the CR0 read shadow.
+ *
+ * See Intel spec. 24.6.6 "Guest/Host Masks and Read Shadows for CR0 and CR4".
+ * See Intel spec. 25.1.3 "Instructions That Cause VM Exits Conditionally".
+ */
+ Assert(CPUMIsGuestInVmxNonRootMode(pCtx));
+
+ uint32_t const fGstHostMask = (uint32_t)pCtx->hwvirt.vmx.Vmcs.u64Cr0Mask.u;
+ uint32_t const fReadShadow = (uint32_t)pCtx->hwvirt.vmx.Vmcs.u64Cr0ReadShadow.u;
+
+ /*
+ * LMSW can never clear CR0.PE but it may set it. Hence, we handle the
+ * CR0.PE case first, before the rest of the bits in the MSW.
+ *
+ * If CR0.PE is owned by the host and CR0.PE differs between the
+ * MSW (source operand) and the read-shadow, we must cause a VM-exit.
+ */
+ if ( (fGstHostMask & X86_CR0_PE)
+ && (uNewMsw & X86_CR0_PE)
+ && !(fReadShadow & X86_CR0_PE))
+ return true;
+
+ /*
+ * If CR0.MP, CR0.EM or CR0.TS is owned by the host, and the corresponding
+ * bits differ between the MSW (source operand) and the read-shadow, we must
+ * cause a VM-exit.
+ */
+ uint32_t const fGstHostLmswMask = fGstHostMask & (X86_CR0_MP | X86_CR0_EM | X86_CR0_TS);
+ if ((fReadShadow & fGstHostLmswMask) != (uNewMsw & fGstHostLmswMask))
+ return true;
+
+ return false;
+}
+
+/**
+ * Checks whether the Mov-to-CR0/CR4 access causes a VM-exit or not.
+ *
+ * @returns @c true if the Mov CRX access causes a VM-exit, @c false otherwise.
+ * @param pCtx Current CPU context.
+ * @param iCrReg The control register number (must be 0 or 4).
+ * @param uNewCrX The CR0/CR4 value being written.
+ */
+DECLINLINE(bool) CPUMIsGuestVmxMovToCr0Cr4InterceptSet(PCCPUMCTX pCtx, uint8_t iCrReg, uint64_t uNewCrX)
+{
+ /*
+ * For any CR0/CR4 bit owned by the host (in the CR0/CR4 guest/host mask), if the
+ * corresponding bits differ between the source operand and the read-shadow,
+ * we must cause a VM-exit.
+ *
+ * See Intel spec. 25.1.3 "Instructions That Cause VM Exits Conditionally".
+ */
+ Assert(CPUMIsGuestInVmxNonRootMode(pCtx));
+ Assert(iCrReg == 0 || iCrReg == 4);
+
+ uint64_t fGstHostMask;
+ uint64_t fReadShadow;
+ if (iCrReg == 0)
+ {
+ fGstHostMask = pCtx->hwvirt.vmx.Vmcs.u64Cr0Mask.u;
+ fReadShadow = pCtx->hwvirt.vmx.Vmcs.u64Cr0ReadShadow.u;
+ }
+ else
+ {
+ fGstHostMask = pCtx->hwvirt.vmx.Vmcs.u64Cr4Mask.u;
+ fReadShadow = pCtx->hwvirt.vmx.Vmcs.u64Cr4ReadShadow.u;
+ }
+
+ if ((fReadShadow & fGstHostMask) != (uNewCrX & fGstHostMask))
+ {
+ Assert(fGstHostMask != 0);
+ return true;
+ }
+
+ return false;
+}
+
+/**
+ * Returns whether the guest has an active, current VMCS.
+ *
+ * @returns @c true if the guest has an active, current VMCS, @c false otherwise.
+ * @param pCtx Current CPU context.
+ */
+DECLINLINE(bool) CPUMIsGuestVmxCurrentVmcsValid(PCCPUMCTX pCtx)
+{
+ return pCtx->hwvirt.vmx.GCPhysVmcs != NIL_RTGCPHYS;
+}
+
+# endif /* !IN_RC */
+
+/**
+ * Checks whether the VMX nested-guest is in a state to receive physical (APIC)
+ * interrupts.
+ *
+ * @returns @c true if it's ready, @c false otherwise.
+ * @param pCtx The guest-CPU context.
+ */
+DECLINLINE(bool) CPUMIsGuestVmxPhysIntrEnabled(PCCPUMCTX pCtx)
+{
+#ifdef IN_RC
+ AssertReleaseFailedReturn(false);
+#else
+ Assert(CPUMIsGuestInVmxNonRootMode(pCtx));
+ if (CPUMIsGuestVmxPinCtlsSet(pCtx, VMX_PIN_CTLS_EXT_INT_EXIT))
+ return true;
+ return RT_BOOL(pCtx->eflags.u & X86_EFL_IF);
+#endif
+}
+
+/**
+ * Checks whether the VMX nested-guest is blocking virtual-NMIs.
+ *
+ * @returns @c true if it's blocked, @c false otherwise.
+ * @param pCtx The guest-CPU context.
+ */
+DECLINLINE(bool) CPUMIsGuestVmxVirtNmiBlocking(PCCPUMCTX pCtx)
+{
+#ifdef IN_RC
+ RT_NOREF(pCtx);
+ AssertReleaseFailedReturn(false);
+#else
+ /*
+ * Return the state of virtual-NMI blocking, if we are executing a
+ * VMX nested-guest with virtual-NMIs enabled.
+ */
+ Assert(CPUMIsGuestInVmxNonRootMode(pCtx));
+ Assert(CPUMIsGuestVmxPinCtlsSet(pCtx, VMX_PIN_CTLS_VIRT_NMI));
+ return pCtx->hwvirt.vmx.fVirtNmiBlocking;
+#endif
+}
+
+/**
+ * Sets or clears VMX nested-guest virtual-NMI blocking.
+ *
+ * @param pCtx The guest-CPU context.
+ * @param fBlocking Whether virtual-NMI blocking is in effect or not.
+ */
+DECLINLINE(void) CPUMSetGuestVmxVirtNmiBlocking(PCPUMCTX pCtx, bool fBlocking)
+{
+#ifdef IN_RC
+ RT_NOREF2(pCtx, fBlocking);
+ AssertReleaseFailedReturnVoid();
+#else
+ Assert(CPUMIsGuestInVmxNonRootMode(pCtx));
+ Assert(CPUMIsGuestVmxPinCtlsSet(pCtx, VMX_PIN_CTLS_VIRT_NMI));
+ pCtx->hwvirt.vmx.fVirtNmiBlocking = fBlocking;
+#endif
+}
+
+/**
+ * Checks whether the VMX nested-guest is in a state to receive virtual interrupts
+ * (those injected with the "virtual-interrupt delivery" feature).
+ *
+ * @returns @c true if it's ready, @c false otherwise.
+ * @param pCtx The guest-CPU context.
+ */
+DECLINLINE(bool) CPUMIsGuestVmxVirtIntrEnabled(PCCPUMCTX pCtx)
+{
+#ifdef IN_RC
+ RT_NOREF2(pCtx);
+ AssertReleaseFailedReturn(false);
+#else
+ Assert(CPUMIsGuestInVmxNonRootMode(pCtx));
+ return RT_BOOL(pCtx->eflags.u & X86_EFL_IF);
+#endif
+}
+
+/** @} */
+#endif /* !IPRT_WITHOUT_NAMED_UNIONS_AND_STRUCTS || DOXYGEN_RUNNING */
+
+
+
+/** @name Hypervisor Register Getters.
+ * @{ */
+VMMDECL(RTGCUINTREG) CPUMGetHyperDR0(PVMCPU pVCpu);
+VMMDECL(RTGCUINTREG) CPUMGetHyperDR1(PVMCPU pVCpu);
+VMMDECL(RTGCUINTREG) CPUMGetHyperDR2(PVMCPU pVCpu);
+VMMDECL(RTGCUINTREG) CPUMGetHyperDR3(PVMCPU pVCpu);
+VMMDECL(RTGCUINTREG) CPUMGetHyperDR6(PVMCPU pVCpu);
+VMMDECL(RTGCUINTREG) CPUMGetHyperDR7(PVMCPU pVCpu);
+VMMDECL(uint32_t) CPUMGetHyperCR3(PVMCPU pVCpu);
+/** @} */
+
+/** @name Hypervisor Register Setters.
+ * @{ */
+VMMDECL(void) CPUMSetHyperCR3(PVMCPU pVCpu, uint32_t cr3);
+VMMDECL(void) CPUMSetHyperDR0(PVMCPU pVCpu, RTGCUINTREG uDr0);
+VMMDECL(void) CPUMSetHyperDR1(PVMCPU pVCpu, RTGCUINTREG uDr1);
+VMMDECL(void) CPUMSetHyperDR2(PVMCPU pVCpu, RTGCUINTREG uDr2);
+VMMDECL(void) CPUMSetHyperDR3(PVMCPU pVCpu, RTGCUINTREG uDr3);
+VMMDECL(void) CPUMSetHyperDR6(PVMCPU pVCpu, RTGCUINTREG uDr6);
+VMMDECL(void) CPUMSetHyperDR7(PVMCPU pVCpu, RTGCUINTREG uDr7);
+VMMDECL(int) CPUMRecalcHyperDRx(PVMCPUCC pVCpu, uint8_t iGstReg);
+/** @} */
+
+VMMDECL(PCPUMCTX) CPUMQueryGuestCtxPtr(PVMCPU pVCpu);
+#ifdef VBOX_INCLUDED_vmm_cpumctx_h
+VMM_INT_DECL(PCPUMCTXMSRS) CPUMQueryGuestCtxMsrsPtr(PVMCPU pVCpu);
+#endif
+
+/** @name Changed flags.
+ * These flags are used to keep track of which important register that
+ * have been changed since last they were reset. The only one allowed
+ * to clear them is REM!
+ *
+ * @todo This is obsolete, but remains as it will be refactored for coordinating
+ * IEM and NEM/HM later. Probably.
+ * @{
+ */
+#define CPUM_CHANGED_FPU_REM RT_BIT(0)
+#define CPUM_CHANGED_CR0 RT_BIT(1)
+#define CPUM_CHANGED_CR4 RT_BIT(2)
+#define CPUM_CHANGED_GLOBAL_TLB_FLUSH RT_BIT(3)
+#define CPUM_CHANGED_CR3 RT_BIT(4)
+#define CPUM_CHANGED_GDTR RT_BIT(5)
+#define CPUM_CHANGED_IDTR RT_BIT(6)
+#define CPUM_CHANGED_LDTR RT_BIT(7)
+#define CPUM_CHANGED_TR RT_BIT(8) /**@< Currently unused. */
+#define CPUM_CHANGED_SYSENTER_MSR RT_BIT(9)
+#define CPUM_CHANGED_HIDDEN_SEL_REGS RT_BIT(10) /**@< Currently unused. */
+#define CPUM_CHANGED_CPUID RT_BIT(11)
+#define CPUM_CHANGED_ALL ( CPUM_CHANGED_FPU_REM \
+ | CPUM_CHANGED_CR0 \
+ | CPUM_CHANGED_CR4 \
+ | CPUM_CHANGED_GLOBAL_TLB_FLUSH \
+ | CPUM_CHANGED_CR3 \
+ | CPUM_CHANGED_GDTR \
+ | CPUM_CHANGED_IDTR \
+ | CPUM_CHANGED_LDTR \
+ | CPUM_CHANGED_TR \
+ | CPUM_CHANGED_SYSENTER_MSR \
+ | CPUM_CHANGED_HIDDEN_SEL_REGS \
+ | CPUM_CHANGED_CPUID )
+/** @} */
+
+VMMDECL(void) CPUMSetChangedFlags(PVMCPU pVCpu, uint32_t fChangedAdd);
+VMMDECL(bool) CPUMSupportsXSave(PVM pVM);
+VMMDECL(bool) CPUMIsHostUsingSysEnter(PVM pVM);
+VMMDECL(bool) CPUMIsHostUsingSysCall(PVM pVM);
+VMMDECL(bool) CPUMIsGuestFPUStateActive(PVMCPU pVCpu);
+VMMDECL(bool) CPUMIsGuestFPUStateLoaded(PVMCPU pVCpu);
+VMMDECL(bool) CPUMIsHostFPUStateSaved(PVMCPU pVCpu);
+VMMDECL(bool) CPUMIsGuestDebugStateActive(PVMCPU pVCpu);
+VMMDECL(void) CPUMDeactivateGuestDebugState(PVMCPU pVCpu);
+VMMDECL(bool) CPUMIsHyperDebugStateActive(PVMCPU pVCpu);
+VMMDECL(uint32_t) CPUMGetGuestCPL(PVMCPU pVCpu);
+VMMDECL(CPUMMODE) CPUMGetGuestMode(PVMCPU pVCpu);
+VMMDECL(uint32_t) CPUMGetGuestCodeBits(PVMCPU pVCpu);
+VMMDECL(DISCPUMODE) CPUMGetGuestDisMode(PVMCPU pVCpu);
+VMMDECL(uint32_t) CPUMGetGuestMxCsrMask(PVM pVM);
+VMMDECL(uint64_t) CPUMGetGuestScalableBusFrequency(PVM pVM);
+VMMDECL(uint64_t) CPUMGetGuestEferMsrValidMask(PVM pVM);
+VMMDECL(int) CPUMIsGuestEferMsrWriteValid(PVM pVM, uint64_t uCr0, uint64_t uOldEfer, uint64_t uNewEfer,
+ uint64_t *puValidEfer);
+VMMDECL(void) CPUMSetGuestEferMsrNoChecks(PVMCPUCC pVCpu, uint64_t uOldEfer, uint64_t uValidEfer);
+VMMDECL(bool) CPUMIsPatMsrValid(uint64_t uValue);
+
+
+/** Guest CPU interruptibility level, see CPUMGetGuestInterruptibility(). */
+typedef enum CPUMINTERRUPTIBILITY
+{
+ CPUMINTERRUPTIBILITY_INVALID = 0,
+ CPUMINTERRUPTIBILITY_UNRESTRAINED,
+ CPUMINTERRUPTIBILITY_VIRT_INT_DISABLED,
+ CPUMINTERRUPTIBILITY_INT_DISABLED,
+ CPUMINTERRUPTIBILITY_INT_INHIBITED, /**< @todo rename as it inhibits NMIs too. */
+ CPUMINTERRUPTIBILITY_NMI_INHIBIT,
+ CPUMINTERRUPTIBILITY_GLOBAL_INHIBIT,
+ CPUMINTERRUPTIBILITY_END,
+ CPUMINTERRUPTIBILITY_32BIT_HACK = 0x7fffffff
+} CPUMINTERRUPTIBILITY;
+
+VMM_INT_DECL(CPUMINTERRUPTIBILITY) CPUMGetGuestInterruptibility(PVMCPU pVCpu);
+
+/** @name Typical scalable bus frequency values.
+ * @{ */
+/** Special internal value indicating that we don't know the frequency.
+ * @internal */
+#define CPUM_SBUSFREQ_UNKNOWN UINT64_C(1)
+#define CPUM_SBUSFREQ_100MHZ UINT64_C(100000000)
+#define CPUM_SBUSFREQ_133MHZ UINT64_C(133333333)
+#define CPUM_SBUSFREQ_167MHZ UINT64_C(166666666)
+#define CPUM_SBUSFREQ_200MHZ UINT64_C(200000000)
+#define CPUM_SBUSFREQ_267MHZ UINT64_C(266666666)
+#define CPUM_SBUSFREQ_333MHZ UINT64_C(333333333)
+#define CPUM_SBUSFREQ_400MHZ UINT64_C(400000000)
+/** @} */
+
+
+#ifdef IN_RING3
+/** @defgroup grp_cpum_r3 The CPUM ring-3 API
+ * @{
+ */
+
+VMMR3DECL(int) CPUMR3Init(PVM pVM);
+VMMR3DECL(int) CPUMR3InitCompleted(PVM pVM, VMINITCOMPLETED enmWhat);
+VMMR3DECL(void) CPUMR3LogCpuIdAndMsrFeatures(PVM pVM);
+VMMR3DECL(void) CPUMR3Relocate(PVM pVM);
+VMMR3DECL(int) CPUMR3Term(PVM pVM);
+VMMR3DECL(void) CPUMR3Reset(PVM pVM);
+VMMR3DECL(void) CPUMR3ResetCpu(PVM pVM, PVMCPU pVCpu);
+VMMDECL(bool) CPUMR3IsStateRestorePending(PVM pVM);
+VMMR3DECL(int) CPUMR3SetCR4Feature(PVM pVM, RTHCUINTREG fOr, RTHCUINTREG fAnd);
+
+VMMR3DECL(int) CPUMR3CpuIdInsert(PVM pVM, PCPUMCPUIDLEAF pNewLeaf);
+VMMR3DECL(int) CPUMR3CpuIdGetLeaf(PVM pVM, PCPUMCPUIDLEAF pLeaf, uint32_t uLeaf, uint32_t uSubLeaf);
+VMMR3_INT_DECL(PCCPUMCPUIDLEAF) CPUMR3CpuIdGetPtr(PVM pVM, uint32_t *pcLeaves);
+VMMDECL(CPUMMICROARCH) CPUMCpuIdDetermineX86MicroarchEx(CPUMCPUVENDOR enmVendor, uint8_t bFamily,
+ uint8_t bModel, uint8_t bStepping);
+VMMDECL(const char *) CPUMMicroarchName(CPUMMICROARCH enmMicroarch);
+VMMR3DECL(int) CPUMR3CpuIdDetectUnknownLeafMethod(PCPUMUNKNOWNCPUID penmUnknownMethod, PCPUMCPUID pDefUnknown);
+VMMR3DECL(const char *) CPUMR3CpuIdUnknownLeafMethodName(CPUMUNKNOWNCPUID enmUnknownMethod);
+VMMR3DECL(const char *) CPUMCpuVendorName(CPUMCPUVENDOR enmVendor);
+#if defined(RT_ARCH_X86) || defined(RT_ARCH_AMD64)
+VMMR3DECL(uint32_t) CPUMR3DeterminHostMxCsrMask(void);
+#endif
+
+VMMR3DECL(int) CPUMR3MsrRangesInsert(PVM pVM, PCCPUMMSRRANGE pNewRange);
+
+VMMR3DECL(uint32_t) CPUMR3DbGetEntries(void);
+/** Pointer to CPUMR3DbGetEntries. */
+typedef DECLCALLBACKPTR(uint32_t, PFNCPUMDBGETENTRIES, (void));
+VMMR3DECL(PCCPUMDBENTRY) CPUMR3DbGetEntryByIndex(uint32_t idxCpuDb);
+/** Pointer to CPUMR3DbGetEntryByIndex. */
+typedef DECLCALLBACKPTR(PCCPUMDBENTRY, PFNCPUMDBGETENTRYBYINDEX, (uint32_t idxCpuDb));
+VMMR3DECL(PCCPUMDBENTRY) CPUMR3DbGetEntryByName(const char *pszName);
+/** Pointer to CPUMR3DbGetEntryByName. */
+typedef DECLCALLBACKPTR(PCCPUMDBENTRY, PFNCPUMDBGETENTRYBYNAME, (const char *pszName));
+
+VMMR3_INT_DECL(void) CPUMR3NemActivateGuestDebugState(PVMCPUCC pVCpu);
+VMMR3_INT_DECL(void) CPUMR3NemActivateHyperDebugState(PVMCPUCC pVCpu);
+/** @} */
+#endif /* IN_RING3 */
+
+#ifdef IN_RING0
+/** @defgroup grp_cpum_r0 The CPUM ring-0 API
+ * @{
+ */
+VMMR0_INT_DECL(int) CPUMR0ModuleInit(void);
+VMMR0_INT_DECL(int) CPUMR0ModuleTerm(void);
+VMMR0_INT_DECL(void) CPUMR0InitPerVMData(PGVM pGVM);
+VMMR0_INT_DECL(int) CPUMR0InitVM(PVMCC pVM);
+DECLASM(void) CPUMR0RegisterVCpuThread(PVMCPUCC pVCpu);
+DECLASM(void) CPUMR0TouchHostFpu(void);
+VMMR0_INT_DECL(int) CPUMR0Trap07Handler(PVMCC pVM, PVMCPUCC pVCpu);
+VMMR0_INT_DECL(int) CPUMR0LoadGuestFPU(PVMCC pVM, PVMCPUCC pVCpu);
+VMMR0_INT_DECL(bool) CPUMR0FpuStateMaybeSaveGuestAndRestoreHost(PVMCPUCC pVCpu);
+VMMR0_INT_DECL(int) CPUMR0SaveHostDebugState(PVMCC pVM, PVMCPUCC pVCpu);
+VMMR0_INT_DECL(bool) CPUMR0DebugStateMaybeSaveGuestAndRestoreHost(PVMCPUCC pVCpu, bool fDr6);
+VMMR0_INT_DECL(bool) CPUMR0DebugStateMaybeSaveGuest(PVMCPUCC pVCpu, bool fDr6);
+
+VMMR0_INT_DECL(void) CPUMR0LoadGuestDebugState(PVMCPUCC pVCpu, bool fDr6);
+VMMR0_INT_DECL(void) CPUMR0LoadHyperDebugState(PVMCPUCC pVCpu, bool fDr6);
+/** @} */
+#endif /* IN_RING0 */
+
+/** @defgroup grp_cpum_rz The CPUM raw-mode and ring-0 context API
+ * @{
+ */
+VMMRZ_INT_DECL(void) CPUMRZFpuStatePrepareHostCpuForUse(PVMCPUCC pVCpu);
+VMMRZ_INT_DECL(void) CPUMRZFpuStateActualizeForRead(PVMCPUCC pVCpu);
+VMMRZ_INT_DECL(void) CPUMRZFpuStateActualizeForChange(PVMCPUCC pVCpu);
+VMMRZ_INT_DECL(void) CPUMRZFpuStateActualizeSseForRead(PVMCPUCC pVCpu);
+VMMRZ_INT_DECL(void) CPUMRZFpuStateActualizeAvxForRead(PVMCPUCC pVCpu);
+/** @} */
+
+
+#endif /* !VBOX_FOR_DTRACE_LIB */
+/** @} */
+RT_C_DECLS_END
+
+
+#endif /* !VBOX_INCLUDED_vmm_cpum_h */
+
diff --git a/include/VBox/vmm/cpum.mac b/include/VBox/vmm/cpum.mac
new file mode 100644
index 00000000..dac92f61
--- /dev/null
+++ b/include/VBox/vmm/cpum.mac
@@ -0,0 +1,275 @@
+;; @file
+; CPUM - CPU Monitor, Assembly header file.
+;
+
+;
+; Copyright (C) 2006-2022 Oracle and/or its affiliates.
+;
+; This file is part of VirtualBox base platform packages, as
+; available from https://www.virtualbox.org.
+;
+; This program is free software; you can redistribute it and/or
+; modify it under the terms of the GNU General Public License
+; as published by the Free Software Foundation, in version 3 of the
+; License.
+;
+; This program is distributed in the hope that it will be useful, but
+; WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with this program; if not, see <https://www.gnu.org/licenses>.
+;
+; The contents of this file may alternatively be used under the terms
+; of the Common Development and Distribution License Version 1.0
+; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+; in the VirtualBox 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.
+;
+; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+;
+
+%ifndef ___VBox_vmm_cpum_mac__
+%define ___VBox_vmm_cpum_mac__
+
+%include "iprt/asmdefs.mac"
+
+
+;;
+; The volatile XSAVE components when VBOX_WITH_KERNEL_USING_XMM is active.
+; @note ASSUMED to be at the most 32-bit in width at the moment.
+%ifdef VBOX_WITH_KERNEL_USING_XMM
+ %define CPUM_VOLATILE_XSAVE_GUEST_COMPONENTS (XSAVE_C_SSE | XSAVE_C_YMM | XSAVE_C_ZMM_HI256 | XSAVE_C_ZMM_16HI)
+%endif
+
+;;
+; CPUID leaf.
+; @remarks This structure is used by the patch manager and can only be extended
+; by adding to the end of it.
+struc CPUMCPUIDLEAF
+ .uLeaf resd 1
+ .uSubLeaf resd 1
+ .fSubLeafMask resd 1
+ .uEax resd 1
+ .uEbx resd 1
+ .uEcx resd 1
+ .uEdx resd 1
+ .fFlags resd 1
+endstruc
+%define CPUMCPUIDLEAF_F_INTEL_TOPOLOGY_SUBLEAVES RT_BIT_32(0)
+%define CPUMCPUIDLEAF_F_CONTAINS_APIC_ID RT_BIT_32(1)
+%define CPUMCPUIDLEAF_F_CONTAINS_OSXSAVE RT_BIT_32(2)
+%define CPUMCPUIDLEAF_F_CONTAINS_APIC RT_BIT_32(3)
+
+
+;;
+; For the default CPUID leaf value.
+; @remarks This is used by the patch manager and cannot be modified in any way.
+struc CPUMCPUID
+ .uEax resd 1
+ .uEbx resd 1
+ .uEcx resd 1
+ .uEdx resd 1
+endstruc
+
+
+;; @name Method used to deal with unknown CPUID leaves.
+;; @{
+%define CPUMUNKNOWNCPUID_DEFAULTS 1
+%define CPUMUNKNOWNCPUID_LAST_STD_LEAF 2
+%define CPUMUNKNOWNCPUID_LAST_STD_LEAF_WITH_ECX 3
+%define CPUMUNKNOWNCPUID_PASSTHRU 4
+;; @}
+
+
+%define XSTATE_SIZE 8192
+
+;; Note! Updates here must be reflected in CPUMInternal.mac too!
+struc CPUMCTX
+ .eax resq 1
+ .ecx resq 1
+ .edx resq 1
+ .ebx resq 1
+ .esp resq 1
+ .ebp resq 1
+ .esi resq 1
+ .edi resq 1
+ .r8 resq 1
+ .r9 resq 1
+ .r10 resq 1
+ .r11 resq 1
+ .r12 resq 1
+ .r13 resq 1
+ .r14 resq 1
+ .r15 resq 1
+ .es.Sel resw 1
+ .es.PaddingSel resw 1
+ .es.ValidSel resw 1
+ .es.fFlags resw 1
+ .es.u64Base resq 1
+ .es.u32Limit resd 1
+ .es.Attr resd 1
+ .cs.Sel resw 1
+ .cs.PaddingSel resw 1
+ .cs.ValidSel resw 1
+ .cs.fFlags resw 1
+ .cs.u64Base resq 1
+ .cs.u32Limit resd 1
+ .cs.Attr resd 1
+ .ss.Sel resw 1
+ .ss.PaddingSel resw 1
+ .ss.ValidSel resw 1
+ .ss.fFlags resw 1
+ .ss.u64Base resq 1
+ .ss.u32Limit resd 1
+ .ss.Attr resd 1
+ .ds.Sel resw 1
+ .ds.PaddingSel resw 1
+ .ds.ValidSel resw 1
+ .ds.fFlags resw 1
+ .ds.u64Base resq 1
+ .ds.u32Limit resd 1
+ .ds.Attr resd 1
+ .fs.Sel resw 1
+ .fs.PaddingSel resw 1
+ .fs.ValidSel resw 1
+ .fs.fFlags resw 1
+ .fs.u64Base resq 1
+ .fs.u32Limit resd 1
+ .fs.Attr resd 1
+ .gs.Sel resw 1
+ .gs.PaddingSel resw 1
+ .gs.ValidSel resw 1
+ .gs.fFlags resw 1
+ .gs.u64Base resq 1
+ .gs.u32Limit resd 1
+ .gs.Attr resd 1
+ .ldtr.Sel resw 1
+ .ldtr.PaddingSel resw 1
+ .ldtr.ValidSel resw 1
+ .ldtr.fFlags resw 1
+ .ldtr.u64Base resq 1
+ .ldtr.u32Limit resd 1
+ .ldtr.Attr resd 1
+ .tr.Sel resw 1
+ .tr.PaddingSel resw 1
+ .tr.ValidSel resw 1
+ .tr.fFlags resw 1
+ .tr.u64Base resq 1
+ .tr.u32Limit resd 1
+ .tr.Attr resd 1
+ alignb 8
+ .eip resq 1
+ .eflags resq 1
+ .fExtrn resq 1
+ .uRipInhibitInt resq 1
+ .cr0 resq 1
+ .cr2 resq 1
+ .cr3 resq 1
+ .cr4 resq 1
+ .dr resq 8
+ .gdtrPadding resw 3
+ .gdtr resw 0
+ .gdtr.cbGdt resw 1
+ .gdtr.pGdt resq 1
+ .idtrPadding resw 3
+ .idtr resw 0
+ .idtr.cbIdt resw 1
+ .idtr.pIdt resq 1
+ .SysEnter.cs resb 8
+ .SysEnter.eip resb 8
+ .SysEnter.esp resb 8
+ .msrEFER resb 8
+ .msrSTAR resb 8
+ .msrPAT resb 8
+ .msrLSTAR resb 8
+ .msrCSTAR resb 8
+ .msrSFMASK resb 8
+ .msrKERNELGSBASE resb 8
+
+ alignb 32
+ .aPaePdpes resq 4
+
+ alignb 8
+ .aXcr resq 2
+ .fXStateMask resq 1
+ .fUsedFpuGuest resb 1
+ alignb 8
+ .aoffXState resw 64
+ alignb 256
+ .abXState resb 0x4000-0x300
+ .XState EQU .abXState
+
+ alignb 4096
+ .hwvirt resb 0
+ .hwvirt.svm resb 0
+ .hwvirt.vmx resb 0
+
+ .hwvirt.svm.Vmcb EQU .hwvirt.svm
+ .hwvirt.svm.abMsrBitmap EQU (.hwvirt.svm.Vmcb + 0x1000)
+ .hwvirt.svm.abIoBitmap EQU (.hwvirt.svm.abMsrBitmap + 0x2000)
+ .hwvirt.svm.uMsrHSavePa EQU (.hwvirt.svm.abIoBitmap + 0x3000) ; resq 1
+ .hwvirt.svm.GCPhysVmcb EQU (.hwvirt.svm.uMsrHSavePa + 8) ; resq 1
+ alignb 8
+ .hwvirt.svm.HostState EQU (.hwvirt.svm.GCPhysVmcb + 8) ; resb 184
+ .hwvirt.svm.uPrevPauseTick EQU (.hwvirt.svm.HostState + 184) ; resq 1
+ .hwvirt.svm.cPauseFilter EQU (.hwvirt.svm.uPrevPauseTick + 8) ; resw 1
+ .hwvirt.svm.cPauseFilterThreshold EQU (.hwvirt.svm.cPauseFilter + 2) ; resw 1
+ .hwvirt.svm.fInterceptEvents EQU (.hwvirt.svm.cPauseFilterThreshold + 2) ; resb 1
+
+ .hwvirt.vmx.Vmcs resb 0x1000
+ .hwvirt.vmx.ShadowVmcs resb 0x1000
+ .hwvirt.vmx.abVmreadBitmap resb 0x1000
+ .hwvirt.vmx.abVmwriteBitmap resb 0x1000
+ .hwvirt.vmx.aEntryMsrLoadArea resb 0x2000
+ .hwvirt.vmx.aExitMsrStoreArea resb 0x2000
+ .hwvirt.vmx.aExitMsrLoadArea resb 0x2000
+ .hwvirt.vmx.abMsrBitmap resb 0x1000
+ .hwvirt.vmx.abIoBitmap resb 0x1000+0x1000
+ alignb 8
+ .hwvirt.vmx.GCPhysVmxon resq 1
+ .hwvirt.vmx.GCPhysVmcs resq 1
+ .hwvirt.vmx.GCPhysShadowVmcs resq 1
+ .hwvirt.vmx.enmDiag resd 1
+ .hwvirt.vmx.enmAbort resd 1
+ .hwvirt.vmx.uDiagAux resq 1
+ .hwvirt.vmx.uAbortAux resd 1
+ .hwvirt.vmx.fInVmxRootMode resb 1
+ .hwvirt.vmx.fInVmxNonRootMode resb 1
+ .hwvirt.vmx.fInterceptEvents resb 1
+ .hwvirt.vmx.fNmiUnblockingIret resb 1
+ .hwvirt.vmx.uFirstPauseLoopTick resq 1
+ .hwvirt.vmx.uPrevPauseTick resq 1
+ .hwvirt.vmx.uEntryTick resq 1
+ .hwvirt.vmx.offVirtApicWrite resw 1
+ .hwvirt.vmx.fVirtNmiBlocking resb 1
+ alignb 8
+ .hwvirt.vmx.Msrs resb 224
+
+ alignb 8
+ .hwvirt.enmHwvirt resd 1
+ .hwvirt.fGif resb 1
+ alignb 4
+ .hwvirt.fSavedInhibit resd 1
+ alignb 64
+endstruc
+
+
+%define CPUMSELREG_FLAGS_VALID 0x0001
+%define CPUMSELREG_FLAGS_STALE 0x0002
+%define CPUMSELREG_FLAGS_VALID_MASK 0x0003
+
+
+;;
+; Guest MSR state.
+struc CPUMCTXMSRS
+ .au64 resq 64
+endstruc
+
+
+%endif
+
diff --git a/include/VBox/vmm/cpumctx-v1_6.h b/include/VBox/vmm/cpumctx-v1_6.h
new file mode 100644
index 00000000..fe6d30db
--- /dev/null
+++ b/include/VBox/vmm/cpumctx-v1_6.h
@@ -0,0 +1,263 @@
+/** @file
+ * CPUM - CPU Monitor(/ Manager), Context Structures from v1.6 (saved state).
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vmm_cpumctx_v1_6_h
+#define VBOX_INCLUDED_vmm_cpumctx_v1_6_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/x86.h>
+#include <VBox/vmm/cpumctx.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_cpum_ctx_v1_6 The CPUM Context Structures from v1.6
+ * @ingroup grp_cpum
+ * @{
+ */
+
+#pragma pack(1)
+/** IDTR from version 1.6 */
+typedef struct VBOXIDTR_VER1_6
+{
+ /** Size of the IDT. */
+ uint16_t cbIdt;
+ /** Address of the IDT. */
+ uint32_t pIdt;
+} VBOXIDTR_VER1_6;
+#pragma pack()
+
+#pragma pack(1)
+/** GDTR from version 1.6 */
+typedef struct VBOXGDTR_VER1_6
+{
+ /** Size of the GDT. */
+ uint16_t cbGdt;
+ /** Address of the GDT. */
+ uint32_t pGdt;
+} VBOXGDTR_VER1_6;
+#pragma pack()
+
+
+/**
+ * Selector hidden registers, for version 1.6 saved state.
+ */
+typedef struct CPUMSELREGHID_VER1_6
+{
+ /** Base register. */
+ uint32_t u32Base;
+ /** Limit (expanded). */
+ uint32_t u32Limit;
+ /** Flags.
+ * This is the high 32-bit word of the descriptor entry.
+ * Only the flags, dpl and type are used. */
+ X86DESCATTR Attr;
+} CPUMSELREGHID_VER1_6;
+
+/**
+ * CPU context, for version 1.6 saved state.
+ * @remarks PATM uses this, which is why it has to be here.
+ */
+# pragma pack(1)
+typedef struct CPUMCTX_VER1_6
+{
+ /** FPU state. (16-byte alignment)
+ * @todo This doesn't have to be in X86FXSTATE on CPUs without fxsr - we need a type for the
+ * actual format or convert it (waste of time). */
+ X86FXSTATE fpu;
+
+ /** CPUMCTXCORE Part.
+ * @{ */
+ union
+ {
+ uint32_t edi;
+ uint64_t rdi;
+ } CPUM_UNION_NM(rdi);
+ union
+ {
+ uint32_t esi;
+ uint64_t rsi;
+ } CPUM_UNION_NM(rsi);
+ union
+ {
+ uint32_t ebp;
+ uint64_t rbp;
+ } CPUM_UNION_NM(rbp);
+ union
+ {
+ uint32_t eax;
+ uint64_t rax;
+ } CPUM_UNION_NM(rax);
+ union
+ {
+ uint32_t ebx;
+ uint64_t rbx;
+ } CPUM_UNION_NM(rbx);
+ union
+ {
+ uint32_t edx;
+ uint64_t rdx;
+ } CPUM_UNION_NM(rdx);
+ union
+ {
+ uint32_t ecx;
+ uint64_t rcx;
+ } CPUM_UNION_NM(rcx);
+ /** @note We rely on the exact layout, because we use lss esp, [] in the
+ * switcher. */
+ uint32_t esp;
+ RTSEL ss;
+ RTSEL ssPadding;
+ /* Note: no overlap with esp here. */
+ uint64_t rsp_notused;
+
+ RTSEL gs;
+ RTSEL gsPadding;
+ RTSEL fs;
+ RTSEL fsPadding;
+ RTSEL es;
+ RTSEL esPadding;
+ RTSEL ds;
+ RTSEL dsPadding;
+ RTSEL cs;
+ RTSEL csPadding[3]; /**< 3 words to force 8 byte alignment for the remainder. */
+
+ union
+ {
+ X86EFLAGS eflags;
+ X86RFLAGS rflags;
+ } CPUM_UNION_NM(rflags);
+ union
+ {
+ uint32_t eip;
+ uint64_t rip;
+ } CPUM_UNION_NM(rip);
+
+ uint64_t r8;
+ uint64_t r9;
+ uint64_t r10;
+ uint64_t r11;
+ uint64_t r12;
+ uint64_t r13;
+ uint64_t r14;
+ uint64_t r15;
+
+ /** Hidden selector registers.
+ * @{ */
+ CPUMSELREGHID_VER1_6 esHid;
+ CPUMSELREGHID_VER1_6 csHid;
+ CPUMSELREGHID_VER1_6 ssHid;
+ CPUMSELREGHID_VER1_6 dsHid;
+ CPUMSELREGHID_VER1_6 fsHid;
+ CPUMSELREGHID_VER1_6 gsHid;
+ /** @} */
+
+ /** @} */
+
+ /** Control registers.
+ * @{ */
+ uint64_t cr0;
+ uint64_t cr2;
+ uint64_t cr3;
+ uint64_t cr4;
+ uint64_t cr8;
+ /** @} */
+
+ /** Debug registers.
+ * @{ */
+ uint64_t dr0;
+ uint64_t dr1;
+ uint64_t dr2;
+ uint64_t dr3;
+ uint64_t dr4; /**< @todo remove dr4 and dr5. */
+ uint64_t dr5;
+ uint64_t dr6;
+ uint64_t dr7;
+ /* DR8-15 are currently not supported */
+ /** @} */
+
+ /** Global Descriptor Table register. */
+ VBOXGDTR_VER1_6 gdtr;
+ uint16_t gdtrPadding;
+ uint32_t gdtrPadding64;/** @todo fix this hack */
+ /** Interrupt Descriptor Table register. */
+ VBOXIDTR_VER1_6 idtr;
+ uint16_t idtrPadding;
+ uint32_t idtrPadding64;/** @todo fix this hack */
+ /** The task register.
+ * Only the guest context uses all the members. */
+ RTSEL ldtr;
+ RTSEL ldtrPadding;
+ /** The task register.
+ * Only the guest context uses all the members. */
+ RTSEL tr;
+ RTSEL trPadding;
+
+ /** The sysenter msr registers.
+ * This member is not used by the hypervisor context. */
+ CPUMSYSENTER SysEnter;
+
+ /** System MSRs.
+ * @{ */
+ uint64_t msrEFER;
+ uint64_t msrSTAR;
+ uint64_t msrPAT;
+ uint64_t msrLSTAR;
+ uint64_t msrCSTAR;
+ uint64_t msrSFMASK;
+ uint64_t msrFSBASE;
+ uint64_t msrGSBASE;
+ uint64_t msrKERNELGSBASE;
+ /** @} */
+
+ /** Hidden selector registers.
+ * @{ */
+ CPUMSELREGHID_VER1_6 ldtrHid;
+ CPUMSELREGHID_VER1_6 trHid;
+ /** @} */
+
+ /** padding to get 32byte aligned size. */
+ uint32_t padding[2];
+} CPUMCTX_VER1_6;
+# pragma pack()
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !VBOX_INCLUDED_vmm_cpumctx_v1_6_h */
+
diff --git a/include/VBox/vmm/cpumctx.h b/include/VBox/vmm/cpumctx.h
new file mode 100644
index 00000000..fd8a4fec
--- /dev/null
+++ b/include/VBox/vmm/cpumctx.h
@@ -0,0 +1,1116 @@
+/** @file
+ * CPUM - CPU Monitor(/ Manager), Context Structures.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vmm_cpumctx_h
+#define VBOX_INCLUDED_vmm_cpumctx_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#ifndef VBOX_FOR_DTRACE_LIB
+# include <iprt/x86.h>
+# include <VBox/types.h>
+# include <VBox/vmm/hm_svm.h>
+# include <VBox/vmm/hm_vmx.h>
+#else
+# pragma D depends_on library x86.d
+#endif
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_cpum_ctx The CPUM Context Structures
+ * @ingroup grp_cpum
+ * @{
+ */
+
+/**
+ * Selector hidden registers.
+ */
+typedef struct CPUMSELREG
+{
+ /** The selector register. */
+ RTSEL Sel;
+ /** Padding, don't use. */
+ RTSEL PaddingSel;
+ /** The selector which info resides in u64Base, u32Limit and Attr, provided
+ * that CPUMSELREG_FLAGS_VALID is set. */
+ RTSEL ValidSel;
+ /** Flags, see CPUMSELREG_FLAGS_XXX. */
+ uint16_t fFlags;
+
+ /** Base register.
+ *
+ * Long mode remarks:
+ * - Unused in long mode for CS, DS, ES, SS
+ * - 32 bits for FS & GS; FS(GS)_BASE msr used for the base address
+ * - 64 bits for TR & LDTR
+ */
+ uint64_t u64Base;
+ /** Limit (expanded). */
+ uint32_t u32Limit;
+ /** Flags.
+ * This is the high 32-bit word of the descriptor entry.
+ * Only the flags, dpl and type are used. */
+ X86DESCATTR Attr;
+} CPUMSELREG;
+#ifndef VBOX_FOR_DTRACE_LIB
+AssertCompileSize(CPUMSELREG, 24);
+#endif
+
+/** @name CPUMSELREG_FLAGS_XXX - CPUMSELREG::fFlags values.
+ * @{ */
+#define CPUMSELREG_FLAGS_VALID UINT16_C(0x0001)
+#define CPUMSELREG_FLAGS_STALE UINT16_C(0x0002)
+#define CPUMSELREG_FLAGS_VALID_MASK UINT16_C(0x0003)
+/** @} */
+
+/** Checks if the hidden parts of the selector register are valid. */
+#define CPUMSELREG_ARE_HIDDEN_PARTS_VALID(a_pVCpu, a_pSelReg) \
+ ( ((a_pSelReg)->fFlags & CPUMSELREG_FLAGS_VALID) \
+ && (a_pSelReg)->ValidSel == (a_pSelReg)->Sel )
+
+/** Old type used for the hidden register part.
+ * @deprecated */
+typedef CPUMSELREG CPUMSELREGHID;
+
+/**
+ * The sysenter register set.
+ */
+typedef struct CPUMSYSENTER
+{
+ /** Ring 0 cs.
+ * This value + 8 is the Ring 0 ss.
+ * This value + 16 is the Ring 3 cs.
+ * This value + 24 is the Ring 3 ss.
+ */
+ uint64_t cs;
+ /** Ring 0 eip. */
+ uint64_t eip;
+ /** Ring 0 esp. */
+ uint64_t esp;
+} CPUMSYSENTER;
+
+/** @def CPUM_UNION_NM
+ * For compilers (like DTrace) that does not grok nameless unions, we have a
+ * little hack to make them palatable.
+ */
+/** @def CPUM_STRUCT_NM
+ * For compilers (like DTrace) that does not grok nameless structs (it is
+ * non-standard C++), we have a little hack to make them palatable.
+ */
+#ifdef VBOX_FOR_DTRACE_LIB
+# define CPUM_UNION_NM(a_Nm) a_Nm
+# define CPUM_STRUCT_NM(a_Nm) a_Nm
+#elif defined(IPRT_WITHOUT_NAMED_UNIONS_AND_STRUCTS)
+# define CPUM_UNION_NM(a_Nm) a_Nm
+# define CPUM_STRUCT_NM(a_Nm) a_Nm
+#else
+# define CPUM_UNION_NM(a_Nm)
+# define CPUM_STRUCT_NM(a_Nm)
+#endif
+/** @def CPUM_UNION_STRUCT_NM
+ * Combines CPUM_UNION_NM and CPUM_STRUCT_NM to avoid hitting the right side of
+ * the screen in the compile time assertions.
+ */
+#define CPUM_UNION_STRUCT_NM(a_UnionNm, a_StructNm) CPUM_UNION_NM(a_UnionNm .) CPUM_STRUCT_NM(a_StructNm)
+
+/** A general register (union). */
+typedef union CPUMCTXGREG
+{
+ /** Natural unsigned integer view. */
+ uint64_t u;
+ /** 64-bit view. */
+ uint64_t u64;
+ /** 32-bit view. */
+ uint32_t u32;
+ /** 16-bit view. */
+ uint16_t u16;
+ /** 8-bit view. */
+ uint8_t u8;
+ /** 8-bit low/high view. */
+ RT_GCC_EXTENSION struct
+ {
+ /** Low byte (al, cl, dl, bl, ++). */
+ uint8_t bLo;
+ /** High byte in the first word - ah, ch, dh, bh. */
+ uint8_t bHi;
+ } CPUM_STRUCT_NM(s);
+} CPUMCTXGREG;
+#ifndef VBOX_FOR_DTRACE_LIB
+AssertCompileSize(CPUMCTXGREG, 8);
+AssertCompileMemberOffset(CPUMCTXGREG, CPUM_STRUCT_NM(s.) bLo, 0);
+AssertCompileMemberOffset(CPUMCTXGREG, CPUM_STRUCT_NM(s.) bHi, 1);
+#endif
+
+
+
+/**
+ * SVM Host-state area (Nested Hw.virt - VirtualBox's layout).
+ *
+ * @warning Exercise caution while modifying the layout of this struct. It's
+ * part of VM saved states.
+ */
+#pragma pack(1)
+typedef struct SVMHOSTSTATE
+{
+ uint64_t uEferMsr;
+ uint64_t uCr0;
+ uint64_t uCr4;
+ uint64_t uCr3;
+ uint64_t uRip;
+ uint64_t uRsp;
+ uint64_t uRax;
+ X86RFLAGS rflags;
+ CPUMSELREG es;
+ CPUMSELREG cs;
+ CPUMSELREG ss;
+ CPUMSELREG ds;
+ VBOXGDTR gdtr;
+ VBOXIDTR idtr;
+ uint8_t abPadding[4];
+} SVMHOSTSTATE;
+#pragma pack()
+/** Pointer to the SVMHOSTSTATE structure. */
+typedef SVMHOSTSTATE *PSVMHOSTSTATE;
+/** Pointer to a const SVMHOSTSTATE structure. */
+typedef const SVMHOSTSTATE *PCSVMHOSTSTATE;
+#ifndef VBOX_FOR_DTRACE_LIB
+AssertCompileSizeAlignment(SVMHOSTSTATE, 8);
+AssertCompileSize(SVMHOSTSTATE, 184);
+#endif
+
+
+/**
+ * CPU hardware virtualization types.
+ */
+typedef enum
+{
+ CPUMHWVIRT_NONE = 0,
+ CPUMHWVIRT_VMX,
+ CPUMHWVIRT_SVM,
+ CPUMHWVIRT_32BIT_HACK = 0x7fffffff
+} CPUMHWVIRT;
+#ifndef VBOX_FOR_DTRACE_LIB
+AssertCompileSize(CPUMHWVIRT, 4);
+#endif
+
+/** Number of EFLAGS bits we put aside for the hardware EFLAGS, with the bits
+ * above this we use for storing internal state not visible to the guest.
+ *
+ * Using a value less than 32 here means some code bloat when loading and
+ * fetching the hardware EFLAGS value. Comparing VMMR0.r0 text size when
+ * compiling release build using gcc 11.3.1 on linux:
+ * - 32 bits: 2475709 bytes
+ * - 24 bits: 2482069 bytes; +6360 bytes.
+ * - 22 bits: 2482261 bytes; +6552 bytes.
+ * Same for windows (virtual size of .text):
+ * - 32 bits: 1498502 bytes
+ * - 24 bits: 1502278 bytes; +3776 bytes.
+ * - 22 bits: 1502198 bytes; +3696 bytes.
+ *
+ * In addition we pass pointer the 32-bit EFLAGS to a number of IEM assembly
+ * functions, so it would be safer to not store anything in the lower 32 bits.
+ * OTOH, we'd sooner discover buggy assembly code by doing so, as we've had one
+ * example of accidental EFLAGS trashing by these functions already.
+ *
+ * It would be more efficient for IEM to store the interrupt shadow bit (and
+ * anything else that needs to be cleared at the same time) in the 30:22 bit
+ * range, because that would allow using a simple AND imm32 instruction on x86
+ * and a MOVN imm16,16 instruction to load the constant on ARM64 (assuming the
+ * other flag needing clearing is RF (bit 16)). Putting it in the 63:32 range
+ * means we that on x86 we'll either use a memory variant of AND or require a
+ * separate load instruction for the immediate, whereas on ARM we'll need more
+ * instructions to construct the immediate value.
+ *
+ * Comparing the instruction exit thruput via the bs2-test-1 testcase, there
+ * seems to be little difference between 32 and 24 here (best results out of 9
+ * runs on Linux/VT-x). So, unless the results are really wrong and there is
+ * clear drop in thruput, it would on the whole make the most sense to use 24
+ * here.
+ *
+ * Update: We need more than 8 bits because of DBGF, so using 22 now.
+ */
+#define CPUMX86EFLAGS_HW_BITS 22
+/** Mask for the hardware EFLAGS bits, 64-bit version. */
+#define CPUMX86EFLAGS_HW_MASK_64 (RT_BIT_64(CPUMX86EFLAGS_HW_BITS) - UINT64_C(1))
+/** Mask for the hardware EFLAGS bits, 32-bit version. */
+#if CPUMX86EFLAGS_HW_BITS == 32
+# define CPUMX86EFLAGS_HW_MASK_32 UINT32_MAX
+#elif CPUMX86EFLAGS_HW_BITS < 32 && CPUMX86EFLAGS_HW_BITS >= 22
+# define CPUMX86EFLAGS_HW_MASK_32 (RT_BIT_32(CPUMX86EFLAGS_HW_BITS) - UINT32_C(1))
+#else
+# error "Misconfigured CPUMX86EFLAGS_HW_BITS value!"
+#endif
+
+/** Mask of internal flags kept with EFLAGS, 64-bit version.
+ * Bits 22-24 are taken by CPUMCTX_INHIBIT_SHADOW_SS, CPUMCTX_INHIBIT_SHADOW_STI
+ * and CPUMCTX_INHIBIT_NMI, bits 25-28 are for CPUMCTX_DBG_HIT_DRX_MASK, and
+ * bits 29-30 are for DBGF events and breakpoints.
+ *
+ * @todo The two DBGF bits could be merged. The NMI inhibiting could move to
+ * bit 32 or higher as it isn't automatically cleared on instruction
+ * completion (except for iret).
+ */
+#define CPUMX86EFLAGS_INT_MASK_64 UINT64_C(0x00000000ffc00000)
+/** Mask of internal flags kept with EFLAGS, 32-bit version. */
+#define CPUMX86EFLAGS_INT_MASK_32 UINT32_C(0xffc00000)
+
+
+/**
+ * CPUM EFLAGS.
+ *
+ * This differs from X86EFLAGS in that we could use bits 31:22 for internal
+ * purposes, see CPUMX86EFLAGS_HW_BITS.
+ */
+typedef union CPUMX86EFLAGS
+{
+ /** The full unsigned view, both hardware and VBox bits. */
+ uint32_t uBoth;
+ /** The plain unsigned view of the hardware bits. */
+#if CPUMX86EFLAGS_HW_BITS == 32
+ uint32_t u;
+#else
+ uint32_t u : CPUMX86EFLAGS_HW_BITS;
+#endif
+#ifndef VBOX_FOR_DTRACE_LIB
+ /** The bitfield view. */
+ X86EFLAGSBITS Bits;
+#endif
+} CPUMX86EFLAGS;
+/** Pointer to CPUM EFLAGS. */
+typedef CPUMX86EFLAGS *PCPUMX86EFLAGS;
+/** Pointer to const CPUM EFLAGS. */
+typedef const CPUMX86EFLAGS *PCCPUMX86EFLAGS;
+
+/**
+ * CPUM RFLAGS.
+ *
+ * This differs from X86EFLAGS in that we use could be using bits 63:22 for
+ * internal purposes, see CPUMX86EFLAGS_HW_BITS.
+ */
+typedef union CPUMX86RFLAGS
+{
+ /** The full unsigned view, both hardware and VBox bits. */
+ uint64_t uBoth;
+ /** The plain unsigned view of the hardware bits. */
+#if CPUMX86EFLAGS_HW_BITS == 32
+ uint32_t u;
+#else
+ uint32_t u : CPUMX86EFLAGS_HW_BITS;
+#endif
+#ifndef VBOX_FOR_DTRACE_LIB
+ /** The bitfield view. */
+ X86EFLAGSBITS Bits;
+#endif
+} CPUMX86RFLAGS;
+/** Pointer to CPUM RFLAGS. */
+typedef CPUMX86RFLAGS *PCPUMX86RFLAGS;
+/** Pointer to const CPUM RFLAGS. */
+typedef const CPUMX86RFLAGS *PCCPUMX86RFLAGS;
+
+
+/**
+ * CPU context.
+ */
+#pragma pack(1) /* for VBOXIDTR / VBOXGDTR. */
+typedef struct CPUMCTX
+{
+ /** General purpose registers. */
+ union /* no tag! */
+ {
+ /** The general purpose register array view, indexed by X86_GREG_XXX. */
+ CPUMCTXGREG aGRegs[16];
+
+ /** 64-bit general purpose register view. */
+ RT_GCC_EXTENSION struct /* no tag! */
+ {
+ uint64_t rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi, r8, r9, r10, r11, r12, r13, r14, r15;
+ } CPUM_STRUCT_NM(qw);
+ /** 64-bit general purpose register view. */
+ RT_GCC_EXTENSION struct /* no tag! */
+ {
+ uint64_t r0, r1, r2, r3, r4, r5, r6, r7;
+ } CPUM_STRUCT_NM(qw2);
+ /** 32-bit general purpose register view. */
+ RT_GCC_EXTENSION struct /* no tag! */
+ {
+ uint32_t eax, u32Pad00, ecx, u32Pad01, edx, u32Pad02, ebx, u32Pad03,
+ esp, u32Pad04, ebp, u32Pad05, esi, u32Pad06, edi, u32Pad07,
+ r8d, u32Pad08, r9d, u32Pad09, r10d, u32Pad10, r11d, u32Pad11,
+ r12d, u32Pad12, r13d, u32Pad13, r14d, u32Pad14, r15d, u32Pad15;
+ } CPUM_STRUCT_NM(dw);
+ /** 16-bit general purpose register view. */
+ RT_GCC_EXTENSION struct /* no tag! */
+ {
+ uint16_t ax, au16Pad00[3], cx, au16Pad01[3], dx, au16Pad02[3], bx, au16Pad03[3],
+ sp, au16Pad04[3], bp, au16Pad05[3], si, au16Pad06[3], di, au16Pad07[3],
+ r8w, au16Pad08[3], r9w, au16Pad09[3], r10w, au16Pad10[3], r11w, au16Pad11[3],
+ r12w, au16Pad12[3], r13w, au16Pad13[3], r14w, au16Pad14[3], r15w, au16Pad15[3];
+ } CPUM_STRUCT_NM(w);
+ RT_GCC_EXTENSION struct /* no tag! */
+ {
+ uint8_t al, ah, abPad00[6], cl, ch, abPad01[6], dl, dh, abPad02[6], bl, bh, abPad03[6],
+ spl, abPad04[7], bpl, abPad05[7], sil, abPad06[7], dil, abPad07[7],
+ r8l, abPad08[7], r9l, abPad09[7], r10l, abPad10[7], r11l, abPad11[7],
+ r12l, abPad12[7], r13l, abPad13[7], r14l, abPad14[7], r15l, abPad15[7];
+ } CPUM_STRUCT_NM(b);
+ } CPUM_UNION_NM(g);
+
+ /** Segment registers. */
+ union /* no tag! */
+ {
+ /** The segment register array view, indexed by X86_SREG_XXX. */
+ CPUMSELREG aSRegs[6];
+ /** The named segment register view. */
+ RT_GCC_EXTENSION struct /* no tag! */
+ {
+ CPUMSELREG es, cs, ss, ds, fs, gs;
+ } CPUM_STRUCT_NM(n);
+ } CPUM_UNION_NM(s);
+
+ /** The task register.
+ * Only the guest context uses all the members. */
+ CPUMSELREG ldtr;
+ /** The task register.
+ * Only the guest context uses all the members. */
+ CPUMSELREG tr;
+
+ /** The program counter. */
+ union
+ {
+ uint16_t ip;
+ uint32_t eip;
+ uint64_t rip;
+ } CPUM_UNION_NM(rip);
+
+ /** The flags register. */
+ union
+ {
+ CPUMX86EFLAGS eflags;
+ CPUMX86RFLAGS rflags;
+ } CPUM_UNION_NM(rflags);
+
+ /** 0x150 - Externalized state tracker, CPUMCTX_EXTRN_XXX. */
+ uint64_t fExtrn;
+
+ /** The RIP value an interrupt shadow is/was valid for. */
+ uint64_t uRipInhibitInt;
+
+ /** @name Control registers.
+ * @{ */
+ uint64_t cr0;
+ uint64_t cr2;
+ uint64_t cr3;
+ uint64_t cr4;
+ /** @} */
+
+ /** Debug registers.
+ * @remarks DR4 and DR5 should not be used since they are aliases for
+ * DR6 and DR7 respectively on both AMD and Intel CPUs.
+ * @remarks DR8-15 are currently not supported by AMD or Intel, so
+ * neither do we.
+ */
+ uint64_t dr[8];
+
+ /** Padding before the structure so the 64-bit member is correctly aligned.
+ * @todo fix this structure! */
+ uint16_t gdtrPadding[3];
+ /** Global Descriptor Table register. */
+ VBOXGDTR gdtr;
+
+ /** Padding before the structure so the 64-bit member is correctly aligned.
+ * @todo fix this structure! */
+ uint16_t idtrPadding[3];
+ /** Interrupt Descriptor Table register. */
+ VBOXIDTR idtr;
+
+ /** The sysenter msr registers.
+ * This member is not used by the hypervisor context. */
+ CPUMSYSENTER SysEnter;
+
+ /** @name System MSRs.
+ * @{ */
+ uint64_t msrEFER; /**< @todo move EFER up to the crX registers for better cacheline mojo */
+ uint64_t msrSTAR; /**< Legacy syscall eip, cs & ss. */
+ uint64_t msrPAT; /**< Page attribute table. */
+ uint64_t msrLSTAR; /**< 64 bits mode syscall rip. */
+ uint64_t msrCSTAR; /**< Compatibility mode syscall rip. */
+ uint64_t msrSFMASK; /**< syscall flag mask. */
+ uint64_t msrKERNELGSBASE; /**< swapgs exchange value. */
+ /** @} */
+
+ uint64_t au64Unused[2];
+
+ /** 0x240 - PAE PDPTEs. */
+ X86PDPE aPaePdpes[4];
+
+ /** 0x260 - The XCR0..XCR1 registers. */
+ uint64_t aXcr[2];
+ /** 0x270 - The mask to pass to XSAVE/XRSTOR in EDX:EAX. If zero we use
+ * FXSAVE/FXRSTOR (since bit 0 will always be set, we only need to test it). */
+ uint64_t fXStateMask;
+ /** 0x278 - Mirror of CPUMCPU::fUseFlags[CPUM_USED_FPU_GUEST]. */
+ bool fUsedFpuGuest;
+ uint8_t afUnused[7];
+
+ /* ---- Start of members not zeroed at reset. ---- */
+
+ /** 0x280 - State component offsets into pXState, UINT16_MAX if not present.
+ * @note Everything before this member will be memset to zero during reset. */
+ uint16_t aoffXState[64];
+ /** 0x300 - The extended state (FPU/SSE/AVX/AVX-2/XXXX).
+ * Aligned on 256 byte boundrary (min req is currently 64 bytes). */
+ union /* no tag */
+ {
+ X86XSAVEAREA XState;
+ /** Byte view for simple indexing and space allocation. */
+ uint8_t abXState[0x4000 - 0x300];
+ } CPUM_UNION_NM(u);
+
+ /** 0x4000 - Hardware virtualization state.
+ * @note This is page aligned, so an full page member comes first in the
+ * substructures. */
+ struct
+ {
+ union /* no tag! */
+ {
+ struct
+ {
+ /** 0x4000 - Cache of the nested-guest VMCB. */
+ SVMVMCB Vmcb;
+ /** 0x5000 - The MSRPM (MSR Permission bitmap).
+ *
+ * This need not be physically contiguous pages because we use the one from
+ * HMPHYSCPU while executing the nested-guest using hardware-assisted SVM.
+ * This one is just used for caching the bitmap from guest physical memory.
+ *
+ * @todo r=bird: This is not used directly by AMD-V hardware, so it doesn't
+ * really need to even be page aligned.
+ *
+ * Also, couldn't we just access the guest page directly when we need to,
+ * or do we have to use a cached copy of it? */
+ uint8_t abMsrBitmap[SVM_MSRPM_PAGES * X86_PAGE_SIZE];
+ /** 0x7000 - The IOPM (IO Permission bitmap).
+ *
+ * This need not be physically contiguous pages because we re-use the ring-0
+ * allocated IOPM while executing the nested-guest using hardware-assisted SVM
+ * because it's identical (we trap all IO accesses).
+ *
+ * This one is just used for caching the IOPM from guest physical memory in
+ * case the guest hypervisor allows direct access to some IO ports.
+ *
+ * @todo r=bird: This is not used directly by AMD-V hardware, so it doesn't
+ * really need to even be page aligned.
+ *
+ * Also, couldn't we just access the guest page directly when we need to,
+ * or do we have to use a cached copy of it? */
+ uint8_t abIoBitmap[SVM_IOPM_PAGES * X86_PAGE_SIZE];
+
+ /** 0xa000 - MSR holding physical address of the Guest's Host-state. */
+ uint64_t uMsrHSavePa;
+ /** 0xa008 - Guest physical address of the nested-guest VMCB. */
+ RTGCPHYS GCPhysVmcb;
+ /** 0xa010 - Guest's host-state save area. */
+ SVMHOSTSTATE HostState;
+ /** 0xa0c8 - Guest TSC time-stamp of when the previous PAUSE instr. was
+ * executed. */
+ uint64_t uPrevPauseTick;
+ /** 0xa0d0 - Pause filter count. */
+ uint16_t cPauseFilter;
+ /** 0xa0d2 - Pause filter threshold. */
+ uint16_t cPauseFilterThreshold;
+ /** 0xa0d4 - Whether the injected event is subject to event intercepts. */
+ bool fInterceptEvents;
+ /** 0xa0d5 - Padding. */
+ bool afPadding[3];
+ } svm;
+
+ struct
+ {
+ /** 0x4000 - The current VMCS. */
+ VMXVVMCS Vmcs;
+ /** 0X5000 - The shadow VMCS. */
+ VMXVVMCS ShadowVmcs;
+ /** 0x6000 - The VMREAD bitmap.
+ * @todo r=bird: Do we really need to keep copies for these? Couldn't we just
+ * access the guest memory directly as needed? */
+ uint8_t abVmreadBitmap[VMX_V_VMREAD_VMWRITE_BITMAP_SIZE];
+ /** 0x7000 - The VMWRITE bitmap.
+ * @todo r=bird: Do we really need to keep copies for these? Couldn't we just
+ * access the guest memory directly as needed? */
+ uint8_t abVmwriteBitmap[VMX_V_VMREAD_VMWRITE_BITMAP_SIZE];
+ /** 0x8000 - The VM-entry MSR-load area. */
+ VMXAUTOMSR aEntryMsrLoadArea[VMX_V_AUTOMSR_AREA_SIZE / sizeof(VMXAUTOMSR)];
+ /** 0xa000 - The VM-exit MSR-store area. */
+ VMXAUTOMSR aExitMsrStoreArea[VMX_V_AUTOMSR_AREA_SIZE / sizeof(VMXAUTOMSR)];
+ /** 0xc000 - The VM-exit MSR-load area. */
+ VMXAUTOMSR aExitMsrLoadArea[VMX_V_AUTOMSR_AREA_SIZE / sizeof(VMXAUTOMSR)];
+ /** 0xe000 - The MSR permission bitmap.
+ * @todo r=bird: Do we really need to keep copies for these? Couldn't we just
+ * access the guest memory directly as needed? */
+ uint8_t abMsrBitmap[VMX_V_MSR_BITMAP_SIZE];
+ /** 0xf000 - The I/O permission bitmap.
+ * @todo r=bird: Do we really need to keep copies for these? Couldn't we just
+ * access the guest memory directly as needed? */
+ uint8_t abIoBitmap[VMX_V_IO_BITMAP_A_SIZE + VMX_V_IO_BITMAP_B_SIZE];
+
+ /** 0x11000 - Guest physical address of the VMXON region. */
+ RTGCPHYS GCPhysVmxon;
+ /** 0x11008 - Guest physical address of the current VMCS pointer. */
+ RTGCPHYS GCPhysVmcs;
+ /** 0x11010 - Guest physical address of the shadow VMCS pointer. */
+ RTGCPHYS GCPhysShadowVmcs;
+ /** 0x11018 - Last emulated VMX instruction/VM-exit diagnostic. */
+ VMXVDIAG enmDiag;
+ /** 0x1101c - VMX abort reason. */
+ VMXABORT enmAbort;
+ /** 0x11020 - Last emulated VMX instruction/VM-exit diagnostic auxiliary info.
+ * (mainly used for info. that's not part of the VMCS). */
+ uint64_t uDiagAux;
+ /** 0x11028 - VMX abort auxiliary info. */
+ uint32_t uAbortAux;
+ /** 0x1102c - Whether the guest is in VMX root mode. */
+ bool fInVmxRootMode;
+ /** 0x1102d - Whether the guest is in VMX non-root mode. */
+ bool fInVmxNonRootMode;
+ /** 0x1102e - Whether the injected events are subjected to event intercepts. */
+ bool fInterceptEvents;
+ /** 0x1102f - Whether blocking of NMI (or virtual-NMIs) was in effect in VMX
+ * non-root mode before execution of IRET. */
+ bool fNmiUnblockingIret;
+ /** 0x11030 - Guest TSC timestamp of the first PAUSE instruction that is
+ * considered to be the first in a loop. */
+ uint64_t uFirstPauseLoopTick;
+ /** 0x11038 - Guest TSC timestamp of the previous PAUSE instruction. */
+ uint64_t uPrevPauseTick;
+ /** 0x11040 - Guest TSC timestamp of VM-entry (used for VMX-preemption
+ * timer). */
+ uint64_t uEntryTick;
+ /** 0x11048 - Virtual-APIC write offset (until trap-like VM-exit). */
+ uint16_t offVirtApicWrite;
+ /** 0x1104a - Whether virtual-NMI blocking is in effect. */
+ bool fVirtNmiBlocking;
+ /** 0x1104b - Padding. */
+ uint8_t abPadding0[5];
+ /** 0x11050 - Guest VMX MSRs. */
+ VMXMSRS Msrs;
+ } vmx;
+ } CPUM_UNION_NM(s);
+
+ /** 0x11130 - Hardware virtualization type currently in use. */
+ CPUMHWVIRT enmHwvirt;
+ /** 0x11134 - Global interrupt flag - AMD only (always true on Intel). */
+ bool fGif;
+ /** 0x11135 - Padding. */
+ bool afPadding0[3];
+ /** 0x11138 - A subset of guest inhibit flags (CPUMCTX_INHIBIT_XXX) that are
+ * saved while running the nested-guest. */
+ uint32_t fSavedInhibit;
+ /** 0x1113c - Pad to 64 byte boundary. */
+ uint8_t abPadding1[4];
+ } hwvirt;
+} CPUMCTX;
+#pragma pack()
+
+#ifndef VBOX_FOR_DTRACE_LIB
+AssertCompileSizeAlignment(CPUMCTX, 64);
+AssertCompileSizeAlignment(CPUMCTX, 32);
+AssertCompileSizeAlignment(CPUMCTX, 16);
+AssertCompileSizeAlignment(CPUMCTX, 8);
+AssertCompileMemberOffset(CPUMCTX, CPUM_UNION_NM(g.) CPUM_STRUCT_NM(qw.) rax, 0x0000);
+AssertCompileMemberOffset(CPUMCTX, CPUM_UNION_NM(g.) CPUM_STRUCT_NM(qw.) rcx, 0x0008);
+AssertCompileMemberOffset(CPUMCTX, CPUM_UNION_NM(g.) CPUM_STRUCT_NM(qw.) rdx, 0x0010);
+AssertCompileMemberOffset(CPUMCTX, CPUM_UNION_NM(g.) CPUM_STRUCT_NM(qw.) rbx, 0x0018);
+AssertCompileMemberOffset(CPUMCTX, CPUM_UNION_NM(g.) CPUM_STRUCT_NM(qw.) rsp, 0x0020);
+AssertCompileMemberOffset(CPUMCTX, CPUM_UNION_NM(g.) CPUM_STRUCT_NM(qw.) rbp, 0x0028);
+AssertCompileMemberOffset(CPUMCTX, CPUM_UNION_NM(g.) CPUM_STRUCT_NM(qw.) rsi, 0x0030);
+AssertCompileMemberOffset(CPUMCTX, CPUM_UNION_NM(g.) CPUM_STRUCT_NM(qw.) rdi, 0x0038);
+AssertCompileMemberOffset(CPUMCTX, CPUM_UNION_NM(g.) CPUM_STRUCT_NM(qw.) r8, 0x0040);
+AssertCompileMemberOffset(CPUMCTX, CPUM_UNION_NM(g.) CPUM_STRUCT_NM(qw.) r9, 0x0048);
+AssertCompileMemberOffset(CPUMCTX, CPUM_UNION_NM(g.) CPUM_STRUCT_NM(qw.) r10, 0x0050);
+AssertCompileMemberOffset(CPUMCTX, CPUM_UNION_NM(g.) CPUM_STRUCT_NM(qw.) r11, 0x0058);
+AssertCompileMemberOffset(CPUMCTX, CPUM_UNION_NM(g.) CPUM_STRUCT_NM(qw.) r12, 0x0060);
+AssertCompileMemberOffset(CPUMCTX, CPUM_UNION_NM(g.) CPUM_STRUCT_NM(qw.) r13, 0x0068);
+AssertCompileMemberOffset(CPUMCTX, CPUM_UNION_NM(g.) CPUM_STRUCT_NM(qw.) r14, 0x0070);
+AssertCompileMemberOffset(CPUMCTX, CPUM_UNION_NM(g.) CPUM_STRUCT_NM(qw.) r15, 0x0078);
+AssertCompileMemberOffset(CPUMCTX, CPUM_UNION_NM(s.) CPUM_STRUCT_NM(n.) es, 0x0080);
+AssertCompileMemberOffset(CPUMCTX, CPUM_UNION_NM(s.) CPUM_STRUCT_NM(n.) cs, 0x0098);
+AssertCompileMemberOffset(CPUMCTX, CPUM_UNION_NM(s.) CPUM_STRUCT_NM(n.) ss, 0x00b0);
+AssertCompileMemberOffset(CPUMCTX, CPUM_UNION_NM(s.) CPUM_STRUCT_NM(n.) ds, 0x00c8);
+AssertCompileMemberOffset(CPUMCTX, CPUM_UNION_NM(s.) CPUM_STRUCT_NM(n.) fs, 0x00e0);
+AssertCompileMemberOffset(CPUMCTX, CPUM_UNION_NM(s.) CPUM_STRUCT_NM(n.) gs, 0x00f8);
+AssertCompileMemberOffset(CPUMCTX, ldtr, 0x0110);
+AssertCompileMemberOffset(CPUMCTX, tr, 0x0128);
+AssertCompileMemberOffset(CPUMCTX, rip, 0x0140);
+AssertCompileMemberOffset(CPUMCTX, rflags, 0x0148);
+AssertCompileMemberOffset(CPUMCTX, fExtrn, 0x0150);
+AssertCompileMemberOffset(CPUMCTX, uRipInhibitInt, 0x0158);
+AssertCompileMemberOffset(CPUMCTX, cr0, 0x0160);
+AssertCompileMemberOffset(CPUMCTX, cr2, 0x0168);
+AssertCompileMemberOffset(CPUMCTX, cr3, 0x0170);
+AssertCompileMemberOffset(CPUMCTX, cr4, 0x0178);
+AssertCompileMemberOffset(CPUMCTX, dr, 0x0180);
+AssertCompileMemberOffset(CPUMCTX, gdtr, 0x01c0+6);
+AssertCompileMemberOffset(CPUMCTX, idtr, 0x01d0+6);
+AssertCompileMemberOffset(CPUMCTX, SysEnter, 0x01e0);
+AssertCompileMemberOffset(CPUMCTX, msrEFER, 0x01f8);
+AssertCompileMemberOffset(CPUMCTX, msrSTAR, 0x0200);
+AssertCompileMemberOffset(CPUMCTX, msrPAT, 0x0208);
+AssertCompileMemberOffset(CPUMCTX, msrLSTAR, 0x0210);
+AssertCompileMemberOffset(CPUMCTX, msrCSTAR, 0x0218);
+AssertCompileMemberOffset(CPUMCTX, msrSFMASK, 0x0220);
+AssertCompileMemberOffset(CPUMCTX, msrKERNELGSBASE, 0x0228);
+AssertCompileMemberOffset(CPUMCTX, aPaePdpes, 0x0240);
+AssertCompileMemberOffset(CPUMCTX, aXcr, 0x0260);
+AssertCompileMemberOffset(CPUMCTX, fXStateMask, 0x0270);
+AssertCompileMemberOffset(CPUMCTX, fUsedFpuGuest, 0x0278);
+AssertCompileMemberOffset(CPUMCTX, CPUM_UNION_NM(u.) XState, 0x0300);
+AssertCompileMemberOffset(CPUMCTX, CPUM_UNION_NM(u.) abXState, 0x0300);
+AssertCompileMemberAlignment(CPUMCTX, CPUM_UNION_NM(u.) XState, 0x0100);
+/* Only do spot checks for hwvirt */
+AssertCompileMemberAlignment(CPUMCTX, hwvirt, 0x1000);
+AssertCompileMemberAlignment(CPUMCTX, hwvirt.CPUM_UNION_NM(s.) svm.Vmcb, X86_PAGE_SIZE);
+AssertCompileMemberAlignment(CPUMCTX, hwvirt.CPUM_UNION_NM(s.) svm.abMsrBitmap, X86_PAGE_SIZE);
+AssertCompileMemberAlignment(CPUMCTX, hwvirt.CPUM_UNION_NM(s.) svm.abIoBitmap, X86_PAGE_SIZE);
+AssertCompileMemberAlignment(CPUMCTX, hwvirt.CPUM_UNION_NM(s.) vmx.Vmcs, X86_PAGE_SIZE);
+AssertCompileMemberAlignment(CPUMCTX, hwvirt.CPUM_UNION_NM(s.) vmx.ShadowVmcs, X86_PAGE_SIZE);
+AssertCompileMemberAlignment(CPUMCTX, hwvirt.CPUM_UNION_NM(s.) vmx.abVmreadBitmap, X86_PAGE_SIZE);
+AssertCompileMemberAlignment(CPUMCTX, hwvirt.CPUM_UNION_NM(s.) vmx.abVmwriteBitmap, X86_PAGE_SIZE);
+AssertCompileMemberAlignment(CPUMCTX, hwvirt.CPUM_UNION_NM(s.) vmx.aEntryMsrLoadArea, X86_PAGE_SIZE);
+AssertCompileMemberAlignment(CPUMCTX, hwvirt.CPUM_UNION_NM(s.) vmx.aExitMsrStoreArea, X86_PAGE_SIZE);
+AssertCompileMemberAlignment(CPUMCTX, hwvirt.CPUM_UNION_NM(s.) vmx.aExitMsrLoadArea, X86_PAGE_SIZE);
+AssertCompileMemberAlignment(CPUMCTX, hwvirt.CPUM_UNION_NM(s.) vmx.abMsrBitmap, X86_PAGE_SIZE);
+AssertCompileMemberAlignment(CPUMCTX, hwvirt.CPUM_UNION_NM(s.) vmx.abIoBitmap, X86_PAGE_SIZE);
+AssertCompileMemberAlignment(CPUMCTX, hwvirt.CPUM_UNION_NM(s.) vmx.Msrs, 8);
+AssertCompileMemberOffset(CPUMCTX, hwvirt.CPUM_UNION_NM(s.) svm.abIoBitmap, 0x7000);
+AssertCompileMemberOffset(CPUMCTX, hwvirt.CPUM_UNION_NM(s.) svm.fInterceptEvents, 0xa0d4);
+AssertCompileMemberOffset(CPUMCTX, hwvirt.CPUM_UNION_NM(s.) vmx.abIoBitmap, 0xf000);
+AssertCompileMemberOffset(CPUMCTX, hwvirt.CPUM_UNION_NM(s.) vmx.fVirtNmiBlocking, 0x1104a);
+AssertCompileMemberOffset(CPUMCTX, hwvirt.enmHwvirt, 0x11130);
+AssertCompileMemberOffset(CPUMCTX, hwvirt.fGif, 0x11134);
+AssertCompileMemberOffset(CPUMCTX, hwvirt.fSavedInhibit, 0x11138);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw.) rax, CPUMCTX, CPUM_UNION_NM(g.) aGRegs);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw.) rax, CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw2.) r0);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw.) rcx, CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw2.) r1);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw.) rdx, CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw2.) r2);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw.) rbx, CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw2.) r3);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw.) rsp, CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw2.) r4);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw.) rbp, CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw2.) r5);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw.) rsi, CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw2.) r6);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw.) rdi, CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw2.) r7);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw.) rax, CPUMCTX, CPUM_UNION_STRUCT_NM(g,dw.) eax);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw.) rcx, CPUMCTX, CPUM_UNION_STRUCT_NM(g,dw.) ecx);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw.) rdx, CPUMCTX, CPUM_UNION_STRUCT_NM(g,dw.) edx);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw.) rbx, CPUMCTX, CPUM_UNION_STRUCT_NM(g,dw.) ebx);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw.) rsp, CPUMCTX, CPUM_UNION_STRUCT_NM(g,dw.) esp);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw.) rbp, CPUMCTX, CPUM_UNION_STRUCT_NM(g,dw.) ebp);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw.) rsi, CPUMCTX, CPUM_UNION_STRUCT_NM(g,dw.) esi);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw.) rdi, CPUMCTX, CPUM_UNION_STRUCT_NM(g,dw.) edi);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw.) r8, CPUMCTX, CPUM_UNION_STRUCT_NM(g,dw.) r8d);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw.) r9, CPUMCTX, CPUM_UNION_STRUCT_NM(g,dw.) r9d);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw.) r10, CPUMCTX, CPUM_UNION_STRUCT_NM(g,dw.) r10d);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw.) r11, CPUMCTX, CPUM_UNION_STRUCT_NM(g,dw.) r11d);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw.) r12, CPUMCTX, CPUM_UNION_STRUCT_NM(g,dw.) r12d);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw.) r13, CPUMCTX, CPUM_UNION_STRUCT_NM(g,dw.) r13d);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw.) r14, CPUMCTX, CPUM_UNION_STRUCT_NM(g,dw.) r14d);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw.) r15, CPUMCTX, CPUM_UNION_STRUCT_NM(g,dw.) r15d);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw.) rax, CPUMCTX, CPUM_UNION_STRUCT_NM(g,w.) ax);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw.) rcx, CPUMCTX, CPUM_UNION_STRUCT_NM(g,w.) cx);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw.) rdx, CPUMCTX, CPUM_UNION_STRUCT_NM(g,w.) dx);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw.) rbx, CPUMCTX, CPUM_UNION_STRUCT_NM(g,w.) bx);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw.) rsp, CPUMCTX, CPUM_UNION_STRUCT_NM(g,w.) sp);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw.) rbp, CPUMCTX, CPUM_UNION_STRUCT_NM(g,w.) bp);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw.) rsi, CPUMCTX, CPUM_UNION_STRUCT_NM(g,w.) si);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw.) rdi, CPUMCTX, CPUM_UNION_STRUCT_NM(g,w.) di);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw.) r8, CPUMCTX, CPUM_UNION_STRUCT_NM(g,w.) r8w);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw.) r9, CPUMCTX, CPUM_UNION_STRUCT_NM(g,w.) r9w);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw.) r10, CPUMCTX, CPUM_UNION_STRUCT_NM(g,w.) r10w);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw.) r11, CPUMCTX, CPUM_UNION_STRUCT_NM(g,w.) r11w);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw.) r12, CPUMCTX, CPUM_UNION_STRUCT_NM(g,w.) r12w);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw.) r13, CPUMCTX, CPUM_UNION_STRUCT_NM(g,w.) r13w);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw.) r14, CPUMCTX, CPUM_UNION_STRUCT_NM(g,w.) r14w);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw.) r15, CPUMCTX, CPUM_UNION_STRUCT_NM(g,w.) r15w);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw.) rax, CPUMCTX, CPUM_UNION_STRUCT_NM(g,b.) al);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw.) rcx, CPUMCTX, CPUM_UNION_STRUCT_NM(g,b.) cl);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw.) rdx, CPUMCTX, CPUM_UNION_STRUCT_NM(g,b.) dl);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw.) rbx, CPUMCTX, CPUM_UNION_STRUCT_NM(g,b.) bl);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw.) rsp, CPUMCTX, CPUM_UNION_STRUCT_NM(g,b.) spl);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw.) rbp, CPUMCTX, CPUM_UNION_STRUCT_NM(g,b.) bpl);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw.) rsi, CPUMCTX, CPUM_UNION_STRUCT_NM(g,b.) sil);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw.) rdi, CPUMCTX, CPUM_UNION_STRUCT_NM(g,b.) dil);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw.) r8, CPUMCTX, CPUM_UNION_STRUCT_NM(g,b.) r8l);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw.) r9, CPUMCTX, CPUM_UNION_STRUCT_NM(g,b.) r9l);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw.) r10, CPUMCTX, CPUM_UNION_STRUCT_NM(g,b.) r10l);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw.) r11, CPUMCTX, CPUM_UNION_STRUCT_NM(g,b.) r11l);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw.) r12, CPUMCTX, CPUM_UNION_STRUCT_NM(g,b.) r12l);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw.) r13, CPUMCTX, CPUM_UNION_STRUCT_NM(g,b.) r13l);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw.) r14, CPUMCTX, CPUM_UNION_STRUCT_NM(g,b.) r14l);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw.) r15, CPUMCTX, CPUM_UNION_STRUCT_NM(g,b.) r15l);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_NM(s.) CPUM_STRUCT_NM(n.) es, CPUMCTX, CPUM_UNION_NM(s.) aSRegs);
+# ifndef _MSC_VER
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw.) rax, CPUMCTX, CPUM_UNION_NM(g.) aGRegs[X86_GREG_xAX]);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw.) rcx, CPUMCTX, CPUM_UNION_NM(g.) aGRegs[X86_GREG_xCX]);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw.) rdx, CPUMCTX, CPUM_UNION_NM(g.) aGRegs[X86_GREG_xDX]);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw.) rbx, CPUMCTX, CPUM_UNION_NM(g.) aGRegs[X86_GREG_xBX]);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw.) rsp, CPUMCTX, CPUM_UNION_NM(g.) aGRegs[X86_GREG_xSP]);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw.) rbp, CPUMCTX, CPUM_UNION_NM(g.) aGRegs[X86_GREG_xBP]);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw.) rsi, CPUMCTX, CPUM_UNION_NM(g.) aGRegs[X86_GREG_xSI]);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw.) rdi, CPUMCTX, CPUM_UNION_NM(g.) aGRegs[X86_GREG_xDI]);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw.) r8, CPUMCTX, CPUM_UNION_NM(g.) aGRegs[X86_GREG_x8]);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw.) r9, CPUMCTX, CPUM_UNION_NM(g.) aGRegs[X86_GREG_x9]);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw.) r10, CPUMCTX, CPUM_UNION_NM(g.) aGRegs[X86_GREG_x10]);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw.) r11, CPUMCTX, CPUM_UNION_NM(g.) aGRegs[X86_GREG_x11]);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw.) r12, CPUMCTX, CPUM_UNION_NM(g.) aGRegs[X86_GREG_x12]);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw.) r13, CPUMCTX, CPUM_UNION_NM(g.) aGRegs[X86_GREG_x13]);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw.) r14, CPUMCTX, CPUM_UNION_NM(g.) aGRegs[X86_GREG_x14]);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(g,qw.) r15, CPUMCTX, CPUM_UNION_NM(g.) aGRegs[X86_GREG_x15]);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(s,n.) es, CPUMCTX, CPUM_UNION_NM(s.) aSRegs[X86_SREG_ES]);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(s,n.) cs, CPUMCTX, CPUM_UNION_NM(s.) aSRegs[X86_SREG_CS]);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(s,n.) ss, CPUMCTX, CPUM_UNION_NM(s.) aSRegs[X86_SREG_SS]);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(s,n.) ds, CPUMCTX, CPUM_UNION_NM(s.) aSRegs[X86_SREG_DS]);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(s,n.) fs, CPUMCTX, CPUM_UNION_NM(s.) aSRegs[X86_SREG_FS]);
+AssertCompileMembersAtSameOffset(CPUMCTX, CPUM_UNION_STRUCT_NM(s,n.) gs, CPUMCTX, CPUM_UNION_NM(s.) aSRegs[X86_SREG_GS]);
+# endif
+
+
+/**
+ * Calculates the pointer to the given extended state component.
+ *
+ * @returns Pointer of type @a a_PtrType
+ * @param a_pCtx Pointer to the context.
+ * @param a_iCompBit The extended state component bit number. This bit
+ * must be set in CPUMCTX::fXStateMask.
+ * @param a_PtrType The pointer type of the extended state component.
+ *
+ */
+#if defined(VBOX_STRICT) && defined(RT_COMPILER_SUPPORTS_LAMBDA)
+# define CPUMCTX_XSAVE_C_PTR(a_pCtx, a_iCompBit, a_PtrType) \
+ ([](PCCPUMCTX a_pLambdaCtx) -> a_PtrType \
+ { \
+ AssertCompile((a_iCompBit) < 64U); \
+ AssertMsg(a_pLambdaCtx->fXStateMask & RT_BIT_64(a_iCompBit), (#a_iCompBit "\n")); \
+ AssertMsg(a_pLambdaCtx->aoffXState[(a_iCompBit)] != UINT16_MAX, (#a_iCompBit "\n")); \
+ return (a_PtrType)(&a_pLambdaCtx->abXState[a_pLambdaCtx->aoffXState[(a_iCompBit)]]); \
+ }(a_pCtx))
+#elif defined(VBOX_STRICT) && defined(__GNUC__)
+# define CPUMCTX_XSAVE_C_PTR(a_pCtx, a_iCompBit, a_PtrType) \
+ __extension__ (\
+ { \
+ AssertCompile((a_iCompBit) < 64U); \
+ AssertMsg((a_pCtx)->fXStateMask & RT_BIT_64(a_iCompBit), (#a_iCompBit "\n")); \
+ AssertMsg((a_pCtx)->aoffXState[(a_iCompBit)] != UINT16_MAX, (#a_iCompBit "\n")); \
+ (a_PtrType)(&(a_pCtx)->abXState[(a_pCtx)->aoffXState[(a_iCompBit)]]); \
+ })
+#else
+# define CPUMCTX_XSAVE_C_PTR(a_pCtx, a_iCompBit, a_PtrType) \
+ ((a_PtrType)(&(a_pCtx)->abXState[(a_pCtx)->aoffXState[(a_iCompBit)]]))
+#endif
+
+/**
+ * Gets the first selector register of a CPUMCTX.
+ *
+ * Use this with X86_SREG_COUNT to loop thru the selector registers.
+ */
+# define CPUMCTX_FIRST_SREG(a_pCtx) (&(a_pCtx)->es)
+
+#endif /* !VBOX_FOR_DTRACE_LIB */
+
+
+/** @name CPUMCTX_EXTRN_XXX
+ * Used for parts of the CPUM state that is externalized and needs fetching
+ * before use.
+ *
+ * @{ */
+/** External state keeper: Invalid. */
+#define CPUMCTX_EXTRN_KEEPER_INVALID UINT64_C(0x0000000000000000)
+/** External state keeper: HM. */
+#define CPUMCTX_EXTRN_KEEPER_HM UINT64_C(0x0000000000000001)
+/** External state keeper: NEM. */
+#define CPUMCTX_EXTRN_KEEPER_NEM UINT64_C(0x0000000000000002)
+/** External state keeper: REM. */
+#define CPUMCTX_EXTRN_KEEPER_REM UINT64_C(0x0000000000000003)
+/** External state keeper mask. */
+#define CPUMCTX_EXTRN_KEEPER_MASK UINT64_C(0x0000000000000003)
+
+/** The RIP register value is kept externally. */
+#define CPUMCTX_EXTRN_RIP UINT64_C(0x0000000000000004)
+/** The RFLAGS register values are kept externally. */
+#define CPUMCTX_EXTRN_RFLAGS UINT64_C(0x0000000000000008)
+
+/** The RAX register value is kept externally. */
+#define CPUMCTX_EXTRN_RAX UINT64_C(0x0000000000000010)
+/** The RCX register value is kept externally. */
+#define CPUMCTX_EXTRN_RCX UINT64_C(0x0000000000000020)
+/** The RDX register value is kept externally. */
+#define CPUMCTX_EXTRN_RDX UINT64_C(0x0000000000000040)
+/** The RBX register value is kept externally. */
+#define CPUMCTX_EXTRN_RBX UINT64_C(0x0000000000000080)
+/** The RSP register value is kept externally. */
+#define CPUMCTX_EXTRN_RSP UINT64_C(0x0000000000000100)
+/** The RBP register value is kept externally. */
+#define CPUMCTX_EXTRN_RBP UINT64_C(0x0000000000000200)
+/** The RSI register value is kept externally. */
+#define CPUMCTX_EXTRN_RSI UINT64_C(0x0000000000000400)
+/** The RDI register value is kept externally. */
+#define CPUMCTX_EXTRN_RDI UINT64_C(0x0000000000000800)
+/** The R8 thru R15 register values are kept externally. */
+#define CPUMCTX_EXTRN_R8_R15 UINT64_C(0x0000000000001000)
+/** General purpose registers mask. */
+#define CPUMCTX_EXTRN_GPRS_MASK UINT64_C(0x0000000000001ff0)
+
+/** The ES register values are kept externally. */
+#define CPUMCTX_EXTRN_ES UINT64_C(0x0000000000002000)
+/** The CS register values are kept externally. */
+#define CPUMCTX_EXTRN_CS UINT64_C(0x0000000000004000)
+/** The SS register values are kept externally. */
+#define CPUMCTX_EXTRN_SS UINT64_C(0x0000000000008000)
+/** The DS register values are kept externally. */
+#define CPUMCTX_EXTRN_DS UINT64_C(0x0000000000010000)
+/** The FS register values are kept externally. */
+#define CPUMCTX_EXTRN_FS UINT64_C(0x0000000000020000)
+/** The GS register values are kept externally. */
+#define CPUMCTX_EXTRN_GS UINT64_C(0x0000000000040000)
+/** Segment registers (includes CS). */
+#define CPUMCTX_EXTRN_SREG_MASK UINT64_C(0x000000000007e000)
+/** Converts a X86_XREG_XXX index to a CPUMCTX_EXTRN_xS mask. */
+#define CPUMCTX_EXTRN_SREG_FROM_IDX(a_SRegIdx) RT_BIT_64((a_SRegIdx) + 13)
+#ifndef VBOX_FOR_DTRACE_LIB
+AssertCompile(CPUMCTX_EXTRN_SREG_FROM_IDX(X86_SREG_ES) == CPUMCTX_EXTRN_ES);
+AssertCompile(CPUMCTX_EXTRN_SREG_FROM_IDX(X86_SREG_CS) == CPUMCTX_EXTRN_CS);
+AssertCompile(CPUMCTX_EXTRN_SREG_FROM_IDX(X86_SREG_DS) == CPUMCTX_EXTRN_DS);
+AssertCompile(CPUMCTX_EXTRN_SREG_FROM_IDX(X86_SREG_FS) == CPUMCTX_EXTRN_FS);
+AssertCompile(CPUMCTX_EXTRN_SREG_FROM_IDX(X86_SREG_GS) == CPUMCTX_EXTRN_GS);
+#endif
+
+/** The GDTR register values are kept externally. */
+#define CPUMCTX_EXTRN_GDTR UINT64_C(0x0000000000080000)
+/** The IDTR register values are kept externally. */
+#define CPUMCTX_EXTRN_IDTR UINT64_C(0x0000000000100000)
+/** The LDTR register values are kept externally. */
+#define CPUMCTX_EXTRN_LDTR UINT64_C(0x0000000000200000)
+/** The TR register values are kept externally. */
+#define CPUMCTX_EXTRN_TR UINT64_C(0x0000000000400000)
+/** Table register mask. */
+#define CPUMCTX_EXTRN_TABLE_MASK UINT64_C(0x0000000000780000)
+
+/** The CR0 register value is kept externally. */
+#define CPUMCTX_EXTRN_CR0 UINT64_C(0x0000000000800000)
+/** The CR2 register value is kept externally. */
+#define CPUMCTX_EXTRN_CR2 UINT64_C(0x0000000001000000)
+/** The CR3 register value is kept externally. */
+#define CPUMCTX_EXTRN_CR3 UINT64_C(0x0000000002000000)
+/** The CR4 register value is kept externally. */
+#define CPUMCTX_EXTRN_CR4 UINT64_C(0x0000000004000000)
+/** Control register mask. */
+#define CPUMCTX_EXTRN_CR_MASK UINT64_C(0x0000000007800000)
+/** The TPR/CR8 register value is kept externally. */
+#define CPUMCTX_EXTRN_APIC_TPR UINT64_C(0x0000000008000000)
+/** The EFER register value is kept externally. */
+#define CPUMCTX_EXTRN_EFER UINT64_C(0x0000000010000000)
+
+/** The DR0, DR1, DR2 and DR3 register values are kept externally. */
+#define CPUMCTX_EXTRN_DR0_DR3 UINT64_C(0x0000000020000000)
+/** The DR6 register value is kept externally. */
+#define CPUMCTX_EXTRN_DR6 UINT64_C(0x0000000040000000)
+/** The DR7 register value is kept externally. */
+#define CPUMCTX_EXTRN_DR7 UINT64_C(0x0000000080000000)
+/** Debug register mask. */
+#define CPUMCTX_EXTRN_DR_MASK UINT64_C(0x00000000e0000000)
+
+/** The XSAVE_C_X87 state is kept externally. */
+#define CPUMCTX_EXTRN_X87 UINT64_C(0x0000000100000000)
+/** The XSAVE_C_SSE, XSAVE_C_YMM, XSAVE_C_ZMM_HI256, XSAVE_C_ZMM_16HI and
+ * XSAVE_C_OPMASK state is kept externally. */
+#define CPUMCTX_EXTRN_SSE_AVX UINT64_C(0x0000000200000000)
+/** The state of XSAVE components not covered by CPUMCTX_EXTRN_X87 and
+ * CPUMCTX_EXTRN_SEE_AVX is kept externally. */
+#define CPUMCTX_EXTRN_OTHER_XSAVE UINT64_C(0x0000000400000000)
+/** The state of XCR0 and XCR1 register values are kept externally. */
+#define CPUMCTX_EXTRN_XCRx UINT64_C(0x0000000800000000)
+
+
+/** The KERNEL GS BASE MSR value is kept externally. */
+#define CPUMCTX_EXTRN_KERNEL_GS_BASE UINT64_C(0x0000001000000000)
+/** The STAR, LSTAR, CSTAR and SFMASK MSR values are kept externally. */
+#define CPUMCTX_EXTRN_SYSCALL_MSRS UINT64_C(0x0000002000000000)
+/** The SYSENTER_CS, SYSENTER_EIP and SYSENTER_ESP MSR values are kept externally. */
+#define CPUMCTX_EXTRN_SYSENTER_MSRS UINT64_C(0x0000004000000000)
+/** The TSC_AUX MSR is kept externally. */
+#define CPUMCTX_EXTRN_TSC_AUX UINT64_C(0x0000008000000000)
+/** All other stateful MSRs not covered by CPUMCTX_EXTRN_EFER,
+ * CPUMCTX_EXTRN_KERNEL_GS_BASE, CPUMCTX_EXTRN_SYSCALL_MSRS,
+ * CPUMCTX_EXTRN_SYSENTER_MSRS, and CPUMCTX_EXTRN_TSC_AUX. */
+#define CPUMCTX_EXTRN_OTHER_MSRS UINT64_C(0x0000010000000000)
+
+/** Mask of all the MSRs. */
+#define CPUMCTX_EXTRN_ALL_MSRS ( CPUMCTX_EXTRN_EFER | CPUMCTX_EXTRN_KERNEL_GS_BASE | CPUMCTX_EXTRN_SYSCALL_MSRS \
+ | CPUMCTX_EXTRN_SYSENTER_MSRS | CPUMCTX_EXTRN_TSC_AUX | CPUMCTX_EXTRN_OTHER_MSRS)
+
+/** Hardware-virtualization (SVM or VMX) state is kept externally. */
+#define CPUMCTX_EXTRN_HWVIRT UINT64_C(0x0000020000000000)
+
+/** Inhibit maskable interrupts (VMCPU_FF_INHIBIT_INTERRUPTS) */
+#define CPUMCTX_EXTRN_INHIBIT_INT UINT64_C(0x0000040000000000)
+/** Inhibit non-maskable interrupts (VMCPU_FF_BLOCK_NMIS). */
+#define CPUMCTX_EXTRN_INHIBIT_NMI UINT64_C(0x0000080000000000)
+
+/** Mask of bits the keepers can use for state tracking. */
+#define CPUMCTX_EXTRN_KEEPER_STATE_MASK UINT64_C(0xffff000000000000)
+
+/** NEM/Win: Event injection (known was interruption) pending state. */
+#define CPUMCTX_EXTRN_NEM_WIN_EVENT_INJECT UINT64_C(0x0001000000000000)
+/** NEM/Win: Mask. */
+#define CPUMCTX_EXTRN_NEM_WIN_MASK UINT64_C(0x0001000000000000)
+
+/** HM/SVM: Nested-guest interrupt pending (VMCPU_FF_INTERRUPT_NESTED_GUEST). */
+#define CPUMCTX_EXTRN_HM_SVM_HWVIRT_VIRQ UINT64_C(0x0001000000000000)
+/** HM/SVM: Mask. */
+#define CPUMCTX_EXTRN_HM_SVM_MASK UINT64_C(0x0001000000000000)
+
+/** All CPUM state bits, not including keeper specific ones. */
+#define CPUMCTX_EXTRN_ALL UINT64_C(0x00000ffffffffffc)
+/** All CPUM state bits, including keeper specific ones. */
+#define CPUMCTX_EXTRN_ABSOLUTELY_ALL UINT64_C(0xfffffffffffffffc)
+/** @} */
+
+
+/** @name CPUMCTX_INHIBIT_XXX - Interrupt inhibiting flags.
+ * @{ */
+/** Interrupt shadow following MOV SS or POP SS.
+ *
+ * When this in effect, both maskable and non-maskable interrupts are blocked
+ * from delivery for one instruction. Same for certain debug exceptions too,
+ * unlike the STI variant.
+ *
+ * It is implementation specific whether a sequence of two or more of these
+ * instructions will have any effect on the instruction following the last one
+ * of them. */
+#define CPUMCTX_INHIBIT_SHADOW_SS RT_BIT_32(0 + CPUMX86EFLAGS_HW_BITS)
+/** Interrupt shadow following STI.
+ * Same as CPUMCTX_INHIBIT_SHADOW_SS but without blocking any debug exceptions. */
+#define CPUMCTX_INHIBIT_SHADOW_STI RT_BIT_32(1 + CPUMX86EFLAGS_HW_BITS)
+/** Mask combining STI and SS shadowing. */
+#define CPUMCTX_INHIBIT_SHADOW (CPUMCTX_INHIBIT_SHADOW_SS | CPUMCTX_INHIBIT_SHADOW_STI)
+
+/** Interrupts blocked by NMI delivery. This condition is cleared by IRET.
+ *
+ * Section "6.7 NONMASKABLE INTERRUPT (NMI)" in Intel SDM Vol 3A states that
+ * "The processor also invokes certain hardware conditions to ensure that no
+ * other interrupts, including NMI interrupts, are received until the NMI
+ * handler has completed executing." This flag indicates that these
+ * conditions are currently active.
+ *
+ * @todo this does not really need to be in the lower 32-bits of EFLAGS.
+ */
+#define CPUMCTX_INHIBIT_NMI RT_BIT_32(2 + CPUMX86EFLAGS_HW_BITS)
+
+/** Mask containing all the interrupt inhibit bits. */
+#define CPUMCTX_INHIBIT_ALL_MASK (CPUMCTX_INHIBIT_SHADOW_SS | CPUMCTX_INHIBIT_SHADOW_STI | CPUMCTX_INHIBIT_NMI)
+AssertCompile(CPUMCTX_INHIBIT_ALL_MASK < UINT32_MAX);
+/** @} */
+
+/** @name CPUMCTX_DBG_XXX - Pending debug events.
+ * @{ */
+/** Hit guest DR0 breakpoint. */
+#define CPUMCTX_DBG_HIT_DR0 RT_BIT_32(CPUMCTX_DBG_HIT_DR0_BIT)
+#define CPUMCTX_DBG_HIT_DR0_BIT (3 + CPUMX86EFLAGS_HW_BITS)
+/** Hit guest DR1 breakpoint. */
+#define CPUMCTX_DBG_HIT_DR1 RT_BIT_32(CPUMCTX_DBG_HIT_DR1_BIT)
+#define CPUMCTX_DBG_HIT_DR1_BIT (4 + CPUMX86EFLAGS_HW_BITS)
+/** Hit guest DR2 breakpoint. */
+#define CPUMCTX_DBG_HIT_DR2 RT_BIT_32(CPUMCTX_DBG_HIT_DR2_BIT)
+#define CPUMCTX_DBG_HIT_DR2_BIT (5 + CPUMX86EFLAGS_HW_BITS)
+/** Hit guest DR3 breakpoint. */
+#define CPUMCTX_DBG_HIT_DR3 RT_BIT_32(CPUMCTX_DBG_HIT_DR3_BIT)
+#define CPUMCTX_DBG_HIT_DR3_BIT (6 + CPUMX86EFLAGS_HW_BITS)
+/** Shift for the CPUMCTX_DBG_HIT_DRx bits. */
+#define CPUMCTX_DBG_HIT_DRX_SHIFT CPUMCTX_DBG_HIT_DR0_BIT
+/** Mask of all guest pending DR0-DR3 breakpoint indicators. */
+#define CPUMCTX_DBG_HIT_DRX_MASK (CPUMCTX_DBG_HIT_DR0 | CPUMCTX_DBG_HIT_DR1 | CPUMCTX_DBG_HIT_DR2 | CPUMCTX_DBG_HIT_DR3)
+/** DBGF event/breakpoint pending. */
+#define CPUMCTX_DBG_DBGF_EVENT RT_BIT_32(CPUMCTX_DBG_DBGF_EVENT_BIT)
+#define CPUMCTX_DBG_DBGF_EVENT_BIT (7 + CPUMX86EFLAGS_HW_BITS)
+/** DBGF event/breakpoint pending. */
+#define CPUMCTX_DBG_DBGF_BP RT_BIT_32(CPUMCTX_DBG_DBGF_BP_BIT)
+#define CPUMCTX_DBG_DBGF_BP_BIT (8 + CPUMX86EFLAGS_HW_BITS)
+/** Mask of all DBGF indicators. */
+#define CPUMCTX_DBG_DBGF_MASK (CPUMCTX_DBG_DBGF_EVENT | CPUMCTX_DBG_DBGF_BP)
+AssertCompile((CPUMCTX_DBG_HIT_DRX_MASK | CPUMCTX_DBG_DBGF_MASK) < UINT32_MAX);
+/** @} */
+
+
+
+/**
+ * Additional guest MSRs (i.e. not part of the CPU context structure).
+ *
+ * @remarks Never change the order here because of the saved stated! The size
+ * can in theory be changed, but keep older VBox versions in mind.
+ */
+typedef union CPUMCTXMSRS
+{
+ struct
+ {
+ uint64_t TscAux; /**< MSR_K8_TSC_AUX */
+ uint64_t MiscEnable; /**< MSR_IA32_MISC_ENABLE */
+ uint64_t MtrrDefType; /**< IA32_MTRR_DEF_TYPE */
+ uint64_t MtrrFix64K_00000; /**< IA32_MTRR_FIX16K_80000 */
+ uint64_t MtrrFix16K_80000; /**< IA32_MTRR_FIX16K_80000 */
+ uint64_t MtrrFix16K_A0000; /**< IA32_MTRR_FIX16K_A0000 */
+ uint64_t MtrrFix4K_C0000; /**< IA32_MTRR_FIX4K_C0000 */
+ uint64_t MtrrFix4K_C8000; /**< IA32_MTRR_FIX4K_C8000 */
+ uint64_t MtrrFix4K_D0000; /**< IA32_MTRR_FIX4K_D0000 */
+ uint64_t MtrrFix4K_D8000; /**< IA32_MTRR_FIX4K_D8000 */
+ uint64_t MtrrFix4K_E0000; /**< IA32_MTRR_FIX4K_E0000 */
+ uint64_t MtrrFix4K_E8000; /**< IA32_MTRR_FIX4K_E8000 */
+ uint64_t MtrrFix4K_F0000; /**< IA32_MTRR_FIX4K_F0000 */
+ uint64_t MtrrFix4K_F8000; /**< IA32_MTRR_FIX4K_F8000 */
+ uint64_t PkgCStateCfgCtrl; /**< MSR_PKG_CST_CONFIG_CONTROL */
+ uint64_t SpecCtrl; /**< IA32_SPEC_CTRL */
+ uint64_t ArchCaps; /**< IA32_ARCH_CAPABILITIES */
+ } msr;
+ uint64_t au64[64];
+} CPUMCTXMSRS;
+/** Pointer to the guest MSR state. */
+typedef CPUMCTXMSRS *PCPUMCTXMSRS;
+/** Pointer to the const guest MSR state. */
+typedef const CPUMCTXMSRS *PCCPUMCTXMSRS;
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !VBOX_INCLUDED_vmm_cpumctx_h */
+
diff --git a/include/VBox/vmm/cpumdis.h b/include/VBox/vmm/cpumdis.h
new file mode 100644
index 00000000..ee09e7b5
--- /dev/null
+++ b/include/VBox/vmm/cpumdis.h
@@ -0,0 +1,61 @@
+/** @file
+ * CPUM - Disassembler.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vmm_cpumdis_h
+#define VBOX_INCLUDED_vmm_cpumdis_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/vmm/cpum.h>
+#include <iprt/x86.h>
+#include <VBox/dis.h>
+
+
+RT_C_DECLS_BEGIN
+/** @addtogroup grp_cpum
+ * @{
+ */
+
+#ifdef IN_RING3
+VMMR3DECL(int) CPUMR3DisasmInstrCPU(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, RTGCPTR GCPtrPC, PDISCPUSTATE pCpu, const char *pszPrefix);
+#endif
+
+/** @} */
+RT_C_DECLS_END
+
+
+#endif /* !VBOX_INCLUDED_vmm_cpumdis_h */
+
diff --git a/include/VBox/vmm/dbgf.h b/include/VBox/vmm/dbgf.h
new file mode 100644
index 00000000..a961a3a5
--- /dev/null
+++ b/include/VBox/vmm/dbgf.h
@@ -0,0 +1,3192 @@
+/** @file
+ * DBGF - Debugger Facility.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vmm_dbgf_h
+#define VBOX_INCLUDED_vmm_dbgf_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/types.h>
+#include <VBox/log.h> /* LOG_ENABLED */
+#include <VBox/vmm/vmm.h>
+#include <VBox/vmm/dbgfsel.h>
+
+#include <iprt/stdarg.h>
+#include <iprt/dbg.h>
+
+RT_C_DECLS_BEGIN
+
+
+/** @defgroup grp_dbgf The Debugger Facility API
+ * @ingroup grp_vmm
+ * @{
+ */
+
+/** @defgroup grp_dbgf_r0 The R0 DBGF API
+ * @{
+ */
+VMMR0_INT_DECL(void) DBGFR0InitPerVMData(PGVM pGVM);
+VMMR0_INT_DECL(void) DBGFR0CleanupVM(PGVM pGVM);
+
+/**
+ * Request buffer for DBGFR0TracerCreateReqHandler / VMMR0_DO_DBGF_TRACER_CREATE.
+ * @see DBGFR0TracerCreateReqHandler.
+ */
+typedef struct DBGFTRACERCREATEREQ
+{
+ /** The header. */
+ SUPVMMR0REQHDR Hdr;
+ /** Out: Where to return the address of the ring-3 tracer instance. */
+ PDBGFTRACERINSR3 pTracerInsR3;
+
+ /** Number of bytes for the shared event ring buffer. */
+ uint32_t cbRingBuf;
+
+ /** Set if the raw-mode component is desired. */
+ bool fRCEnabled;
+ /** Explicit padding. */
+ bool afReserved[3];
+
+} DBGFTRACERCREATEREQ;
+/** Pointer to a DBGFR0TracerCreate / VMMR0_DO_DBGF_TRACER_CREATE request buffer. */
+typedef DBGFTRACERCREATEREQ *PDBGFTRACERCREATEREQ;
+
+VMMR0_INT_DECL(int) DBGFR0TracerCreateReqHandler(PGVM pGVM, PDBGFTRACERCREATEREQ pReq);
+
+/**
+ * Request buffer for DBGFR0BpInitReqHandler / VMMR0_DO_DBGF_BP_INIT and
+ * DBGFR0BpPortIoInitReqHandler / VMMR0_DO_DBGF_BP_PORTIO_INIT.
+ * @see DBGFR0BpInitReqHandler, DBGFR0BpPortIoInitReqHandler.
+ */
+typedef struct DBGFBPINITREQ
+{
+ /** The header. */
+ SUPVMMR0REQHDR Hdr;
+ /** Out: Ring-3 pointer of the L1 lookup table on success. */
+ R3PTRTYPE(volatile uint32_t *) paBpLocL1R3;
+} DBGFBPINITREQ;
+/** Pointer to a DBGFR0BpInitReqHandler / VMMR0_DO_DBGF_BP_INIT request buffer. */
+typedef DBGFBPINITREQ *PDBGFBPINITREQ;
+
+VMMR0_INT_DECL(int) DBGFR0BpInitReqHandler(PGVM pGVM, PDBGFBPINITREQ pReq);
+VMMR0_INT_DECL(int) DBGFR0BpPortIoInitReqHandler(PGVM pGVM, PDBGFBPINITREQ pReq);
+
+/**
+ * Request buffer for DBGFR0BpOwnerInitReqHandler / VMMR0_DO_DBGF_BP_OWNER_INIT.
+ * @see DBGFR0BpOwnerInitReqHandler.
+ */
+typedef struct DBGFBPOWNERINITREQ
+{
+ /** The header. */
+ SUPVMMR0REQHDR Hdr;
+ /** Out: Ring-3 pointer of the breakpoint owner table on success. */
+ R3PTRTYPE(void *) paBpOwnerR3;
+} DBGFBPOWNERINITREQ;
+/** Pointer to a DBGFR0BpOwnerInitReqHandler / VMMR0_DO_DBGF_BP_INIT request buffer. */
+typedef DBGFBPOWNERINITREQ *PDBGFBPOWNERINITREQ;
+
+VMMR0_INT_DECL(int) DBGFR0BpOwnerInitReqHandler(PGVM pGVM, PDBGFBPOWNERINITREQ pReq);
+
+/**
+ * Request buffer for DBGFR0BpChunkAllocReqHandler / VMMR0_DO_DBGF_CHUNK_ALLOC.
+ * @see DBGFR0BpChunkAllocReqHandler.
+ */
+typedef struct DBGFBPCHUNKALLOCREQ
+{
+ /** The header. */
+ SUPVMMR0REQHDR Hdr;
+ /** Out: Ring-3 pointer of the chunk base on success. */
+ R3PTRTYPE(void *) pChunkBaseR3;
+
+ /** The chunk ID to allocate. */
+ uint32_t idChunk;
+} DBGFBPCHUNKALLOCREQ;
+/** Pointer to a DBGFR0BpChunkAllocReqHandler / VMMR0_DO_DBGF_CHUNK_ALLOC request buffer. */
+typedef DBGFBPCHUNKALLOCREQ *PDBGFBPCHUNKALLOCREQ;
+
+VMMR0_INT_DECL(int) DBGFR0BpChunkAllocReqHandler(PGVM pGVM, PDBGFBPCHUNKALLOCREQ pReq);
+
+/**
+ * Request buffer for DBGFR0BpL2TblChunkAllocReqHandler / VMMR0_DO_DBGF_L2_TBL_CHUNK_ALLOC.
+ * @see DBGFR0BpL2TblChunkAllocReqHandler.
+ */
+typedef struct DBGFBPL2TBLCHUNKALLOCREQ
+{
+ /** The header. */
+ SUPVMMR0REQHDR Hdr;
+ /** Out: Ring-3 pointer of the chunk base on success. */
+ R3PTRTYPE(void *) pChunkBaseR3;
+
+ /** The chunk ID to allocate. */
+ uint32_t idChunk;
+} DBGFBPL2TBLCHUNKALLOCREQ;
+/** Pointer to a DBGFR0BpChunkAllocReqHandler / VMMR0_DO_DBGF_L2_TBL_CHUNK_ALLOC request buffer. */
+typedef DBGFBPL2TBLCHUNKALLOCREQ *PDBGFBPL2TBLCHUNKALLOCREQ;
+
+VMMR0_INT_DECL(int) DBGFR0BpL2TblChunkAllocReqHandler(PGVM pGVM, PDBGFBPL2TBLCHUNKALLOCREQ pReq);
+/** @} */
+
+
+#ifdef IN_RING3
+
+/**
+ * Mixed address.
+ */
+typedef struct DBGFADDRESS
+{
+ /** The flat address. */
+ RTGCUINTPTR FlatPtr;
+ /** The selector offset address. */
+ RTGCUINTPTR off;
+ /** The selector. DBGF_SEL_FLAT is a legal value. */
+ RTSEL Sel;
+ /** Flags describing further details about the address. */
+ uint16_t fFlags;
+} DBGFADDRESS;
+/** Pointer to a mixed address. */
+typedef DBGFADDRESS *PDBGFADDRESS;
+/** Pointer to a const mixed address. */
+typedef const DBGFADDRESS *PCDBGFADDRESS;
+
+/** @name DBGFADDRESS Flags.
+ * @{ */
+/** A 16:16 far address. */
+#define DBGFADDRESS_FLAGS_FAR16 0
+/** A 16:32 far address. */
+#define DBGFADDRESS_FLAGS_FAR32 1
+/** A 16:64 far address. */
+#define DBGFADDRESS_FLAGS_FAR64 2
+/** A flat address. */
+#define DBGFADDRESS_FLAGS_FLAT 3
+/** A physical address. */
+#define DBGFADDRESS_FLAGS_PHYS 4
+/** A ring-0 host address (internal use only). */
+#define DBGFADDRESS_FLAGS_RING0 5
+/** The address type mask. */
+#define DBGFADDRESS_FLAGS_TYPE_MASK 7
+
+/** Set if the address is valid. */
+#define DBGFADDRESS_FLAGS_VALID RT_BIT(3)
+
+/** Checks if the mixed address is flat or not. */
+#define DBGFADDRESS_IS_FLAT(pAddress) ( ((pAddress)->fFlags & DBGFADDRESS_FLAGS_TYPE_MASK) == DBGFADDRESS_FLAGS_FLAT )
+/** Checks if the mixed address is flat or not. */
+#define DBGFADDRESS_IS_PHYS(pAddress) ( ((pAddress)->fFlags & DBGFADDRESS_FLAGS_TYPE_MASK) == DBGFADDRESS_FLAGS_PHYS )
+/** Checks if the mixed address is far 16:16 or not. */
+#define DBGFADDRESS_IS_FAR16(pAddress) ( ((pAddress)->fFlags & DBGFADDRESS_FLAGS_TYPE_MASK) == DBGFADDRESS_FLAGS_FAR16 )
+/** Checks if the mixed address is far 16:32 or not. */
+#define DBGFADDRESS_IS_FAR32(pAddress) ( ((pAddress)->fFlags & DBGFADDRESS_FLAGS_TYPE_MASK) == DBGFADDRESS_FLAGS_FAR32 )
+/** Checks if the mixed address is far 16:64 or not. */
+#define DBGFADDRESS_IS_FAR64(pAddress) ( ((pAddress)->fFlags & DBGFADDRESS_FLAGS_TYPE_MASK) == DBGFADDRESS_FLAGS_FAR64 )
+/** Checks if the mixed address is any kind of far address. */
+#define DBGFADDRESS_IS_FAR(pAddress) ( ((pAddress)->fFlags & DBGFADDRESS_FLAGS_TYPE_MASK) <= DBGFADDRESS_FLAGS_FAR64 )
+/** Checks if the mixed address host context ring-0 (special). */
+#define DBGFADDRESS_IS_R0_HC(pAddress) ( ((pAddress)->fFlags & DBGFADDRESS_FLAGS_TYPE_MASK) == DBGFADDRESS_FLAGS_RING0 )
+/** Checks if the mixed address a virtual guest context address (incl HMA). */
+#define DBGFADDRESS_IS_VIRT_GC(pAddress) ( ((pAddress)->fFlags & DBGFADDRESS_FLAGS_TYPE_MASK) <= DBGFADDRESS_FLAGS_FLAT )
+/** Checks if the mixed address is valid. */
+#define DBGFADDRESS_IS_VALID(pAddress) RT_BOOL((pAddress)->fFlags & DBGFADDRESS_FLAGS_VALID)
+/** @} */
+
+VMMR3DECL(int) DBGFR3AddrFromSelOff(PUVM pUVM, VMCPUID idCpu, PDBGFADDRESS pAddress, RTSEL Sel, RTUINTPTR off);
+VMMR3DECL(int) DBGFR3AddrFromSelInfoOff(PUVM pUVM, PDBGFADDRESS pAddress, PCDBGFSELINFO pSelInfo, RTUINTPTR off);
+VMMR3DECL(PDBGFADDRESS) DBGFR3AddrFromFlat(PUVM pUVM, PDBGFADDRESS pAddress, RTGCUINTPTR FlatPtr);
+VMMR3DECL(PDBGFADDRESS) DBGFR3AddrFromPhys(PUVM pUVM, PDBGFADDRESS pAddress, RTGCPHYS PhysAddr);
+VMMR3_INT_DECL(PDBGFADDRESS) DBGFR3AddrFromHostR0(PDBGFADDRESS pAddress, RTR0UINTPTR R0Ptr);
+VMMR3DECL(bool) DBGFR3AddrIsValid(PUVM pUVM, PCDBGFADDRESS pAddress);
+VMMR3DECL(int) DBGFR3AddrToPhys(PUVM pUVM, VMCPUID idCpu, PCDBGFADDRESS pAddress, PRTGCPHYS pGCPhys);
+VMMR3DECL(int) DBGFR3AddrToHostPhys(PUVM pUVM, VMCPUID idCpu, PDBGFADDRESS pAddress, PRTHCPHYS pHCPhys);
+VMMR3DECL(int) DBGFR3AddrToVolatileR3Ptr(PUVM pUVM, VMCPUID idCpu, PDBGFADDRESS pAddress, bool fReadOnly, void **ppvR3Ptr);
+VMMR3DECL(PDBGFADDRESS) DBGFR3AddrAdd(PDBGFADDRESS pAddress, RTGCUINTPTR uAddend);
+VMMR3DECL(PDBGFADDRESS) DBGFR3AddrSub(PDBGFADDRESS pAddress, RTGCUINTPTR uSubtrahend);
+
+#endif /* IN_RING3 */
+
+
+
+/**
+ * VMM Debug Event Type.
+ */
+typedef enum DBGFEVENTTYPE
+{
+ /** Halt completed.
+ * This notifies that a halt command have been successfully completed.
+ */
+ DBGFEVENT_HALT_DONE = 0,
+ /** Detach completed.
+ * This notifies that the detach command have been successfully completed.
+ */
+ DBGFEVENT_DETACH_DONE,
+ /** The command from the debugger is not recognized.
+ * This means internal error or half implemented features.
+ */
+ DBGFEVENT_INVALID_COMMAND,
+
+ /** Fatal error.
+ * This notifies a fatal error in the VMM and that the debugger get's a
+ * chance to first hand information about the the problem.
+ */
+ DBGFEVENT_FATAL_ERROR,
+ /** Breakpoint Hit.
+ * This notifies that a breakpoint installed by the debugger was hit. The
+ * identifier of the breakpoint can be found in the DBGFEVENT::u::Bp::iBp member.
+ */
+ DBGFEVENT_BREAKPOINT,
+ /** I/O port breakpoint.
+ * @todo not yet implemented. */
+ DBGFEVENT_BREAKPOINT_IO,
+ /** MMIO breakpoint.
+ * @todo not yet implemented. */
+ DBGFEVENT_BREAKPOINT_MMIO,
+ /** Breakpoint Hit in the Hypervisor.
+ * This notifies that a breakpoint installed by the debugger was hit. The
+ * identifier of the breakpoint can be found in the DBGFEVENT::u::Bp::iBp member.
+ * @todo raw-mode: remove this
+ */
+ DBGFEVENT_BREAKPOINT_HYPER,
+ /** Assertion in the Hypervisor (breakpoint instruction).
+ * This notifies that a breakpoint instruction was hit in the hypervisor context.
+ */
+ DBGFEVENT_ASSERTION_HYPER,
+ /** Single Stepped.
+ * This notifies that a single step operation was completed.
+ */
+ DBGFEVENT_STEPPED,
+ /** Single Stepped.
+ * This notifies that a hypervisor single step operation was completed.
+ */
+ DBGFEVENT_STEPPED_HYPER,
+ /** The developer have used the DBGFSTOP macro or the PDMDeviceDBGFSTOP function
+ * to bring up the debugger at a specific place.
+ */
+ DBGFEVENT_DEV_STOP,
+ /** The VM is powering off.
+ * When this notification is received, the debugger thread should detach ASAP.
+ */
+ DBGFEVENT_POWERING_OFF,
+
+ /** Hardware Interrupt break.
+ * @todo not yet implemented. */
+ DBGFEVENT_INTERRUPT_HARDWARE,
+ /** Software Interrupt break.
+ * @todo not yet implemented. */
+ DBGFEVENT_INTERRUPT_SOFTWARE,
+
+ /** The first selectable event.
+ * Whether the debugger wants or doesn't want these events can be configured
+ * via DBGFR3xxx and queried via DBGFR3yyy. */
+ DBGFEVENT_FIRST_SELECTABLE,
+ /** Tripple fault. */
+ DBGFEVENT_TRIPLE_FAULT = DBGFEVENT_FIRST_SELECTABLE,
+
+ /** @name Exception events
+ * The exception events normally represents guest exceptions, but depending on
+ * the execution mode some virtualization exceptions may occure (no nested
+ * paging, raw-mode, ++). When necessary, we will request additional VM exits.
+ * @{ */
+ DBGFEVENT_XCPT_FIRST, /**< The first exception event. */
+ DBGFEVENT_XCPT_DE /**< 0x00 - \#DE - Fault - NoErr - Integer divide error (zero/overflow). */
+ = DBGFEVENT_XCPT_FIRST,
+ DBGFEVENT_XCPT_DB, /**< 0x01 - \#DB - trap/fault - NoErr - debug event. */
+ DBGFEVENT_XCPT_02, /**< 0x02 - Reserved for NMI, see interrupt events. */
+ DBGFEVENT_XCPT_BP, /**< 0x03 - \#BP - Trap - NoErr - Breakpoint, INT 3 instruction. */
+ DBGFEVENT_XCPT_OF, /**< 0x04 - \#OF - Trap - NoErr - Overflow, INTO instruction. */
+ DBGFEVENT_XCPT_BR, /**< 0x05 - \#BR - Fault - NoErr - BOUND Range Exceeded, BOUND instruction. */
+ DBGFEVENT_XCPT_UD, /**< 0x06 - \#UD - Fault - NoErr - Undefined(/Invalid) Opcode. */
+ DBGFEVENT_XCPT_NM, /**< 0x07 - \#NM - Fault - NoErr - Device not available, FP or (F)WAIT instruction. */
+ DBGFEVENT_XCPT_DF, /**< 0x08 - \#DF - Abort - Err=0 - Double fault. */
+ DBGFEVENT_XCPT_09, /**< 0x09 - Int9 - Fault - NoErr - Coprocessor Segment Overrun (obsolete). */
+ DBGFEVENT_XCPT_TS, /**< 0x0a - \#TS - Fault - ErrCd - Invalid TSS, Taskswitch or TSS access. */
+ DBGFEVENT_XCPT_NP, /**< 0x0b - \#NP - Fault - ErrCd - Segment not present. */
+ DBGFEVENT_XCPT_SS, /**< 0x0c - \#SS - Fault - ErrCd - Stack-Segment fault. */
+ DBGFEVENT_XCPT_GP, /**< 0x0d - \#GP - Fault - ErrCd - General protection fault. */
+ DBGFEVENT_XCPT_PF, /**< 0x0e - \#PF - Fault - ErrCd - Page fault. - interrupt gate!!! */
+ DBGFEVENT_XCPT_0f, /**< 0x0f - Rsvd - Resvd - Resvd - Intel Reserved. */
+ DBGFEVENT_XCPT_MF, /**< 0x10 - \#MF - Fault - NoErr - x86 FPU Floating-Point Error (Math fault), FP or (F)WAIT instruction. */
+ DBGFEVENT_XCPT_AC, /**< 0x11 - \#AC - Fault - Err=0 - Alignment Check. */
+ DBGFEVENT_XCPT_MC, /**< 0x12 - \#MC - Abort - NoErr - Machine Check. */
+ DBGFEVENT_XCPT_XF, /**< 0x13 - \#XF - Fault - NoErr - SIMD Floating-Point Exception. */
+ DBGFEVENT_XCPT_VE, /**< 0x14 - \#VE - Fault - Noerr - Virtualization exception. */
+ DBGFEVENT_XCPT_15, /**< 0x15 - Intel Reserved. */
+ DBGFEVENT_XCPT_16, /**< 0x16 - Intel Reserved. */
+ DBGFEVENT_XCPT_17, /**< 0x17 - Intel Reserved. */
+ DBGFEVENT_XCPT_18, /**< 0x18 - Intel Reserved. */
+ DBGFEVENT_XCPT_19, /**< 0x19 - Intel Reserved. */
+ DBGFEVENT_XCPT_1a, /**< 0x1a - Intel Reserved. */
+ DBGFEVENT_XCPT_1b, /**< 0x1b - Intel Reserved. */
+ DBGFEVENT_XCPT_1c, /**< 0x1c - Intel Reserved. */
+ DBGFEVENT_XCPT_1d, /**< 0x1d - Intel Reserved. */
+ DBGFEVENT_XCPT_SX, /**< 0x1e - \#SX - Fault - ErrCd - Security Exception. */
+ DBGFEVENT_XCPT_1f, /**< 0x1f - Intel Reserved. */
+ DBGFEVENT_XCPT_LAST /**< The last exception event. */
+ = DBGFEVENT_XCPT_1f,
+ /** @} */
+
+ /** @name Instruction events
+ * The instruction events exerts all possible effort to intercept the
+ * relevant instructions. However, in some execution modes we won't be able
+ * to catch them. So it goes.
+ * @{ */
+ DBGFEVENT_INSTR_FIRST, /**< The first VM instruction event. */
+ DBGFEVENT_INSTR_HALT /**< Instruction: HALT */
+ = DBGFEVENT_INSTR_FIRST,
+ DBGFEVENT_INSTR_MWAIT, /**< Instruction: MWAIT */
+ DBGFEVENT_INSTR_MONITOR, /**< Instruction: MONITOR */
+ DBGFEVENT_INSTR_CPUID, /**< Instruction: CPUID (missing stuff in raw-mode). */
+ DBGFEVENT_INSTR_INVD, /**< Instruction: INVD */
+ DBGFEVENT_INSTR_WBINVD, /**< Instruction: WBINVD */
+ DBGFEVENT_INSTR_INVLPG, /**< Instruction: INVLPG */
+ DBGFEVENT_INSTR_RDTSC, /**< Instruction: RDTSC */
+ DBGFEVENT_INSTR_RDTSCP, /**< Instruction: RDTSCP */
+ DBGFEVENT_INSTR_RDPMC, /**< Instruction: RDPMC */
+ DBGFEVENT_INSTR_RDMSR, /**< Instruction: RDMSR */
+ DBGFEVENT_INSTR_WRMSR, /**< Instruction: WRMSR */
+ DBGFEVENT_INSTR_CRX_READ, /**< Instruction: CRx read instruction (missing smsw in raw-mode, and reads in general in VT-x). */
+ DBGFEVENT_INSTR_CRX_WRITE, /**< Instruction: CRx write */
+ DBGFEVENT_INSTR_DRX_READ, /**< Instruction: DRx read */
+ DBGFEVENT_INSTR_DRX_WRITE, /**< Instruction: DRx write */
+ DBGFEVENT_INSTR_PAUSE, /**< Instruction: PAUSE instruction (not in raw-mode). */
+ DBGFEVENT_INSTR_XSETBV, /**< Instruction: XSETBV */
+ DBGFEVENT_INSTR_SIDT, /**< Instruction: SIDT */
+ DBGFEVENT_INSTR_LIDT, /**< Instruction: LIDT */
+ DBGFEVENT_INSTR_SGDT, /**< Instruction: SGDT */
+ DBGFEVENT_INSTR_LGDT, /**< Instruction: LGDT */
+ DBGFEVENT_INSTR_SLDT, /**< Instruction: SLDT */
+ DBGFEVENT_INSTR_LLDT, /**< Instruction: LLDT */
+ DBGFEVENT_INSTR_STR, /**< Instruction: STR */
+ DBGFEVENT_INSTR_LTR, /**< Instruction: LTR */
+ DBGFEVENT_INSTR_GETSEC, /**< Instruction: GETSEC */
+ DBGFEVENT_INSTR_RSM, /**< Instruction: RSM */
+ DBGFEVENT_INSTR_RDRAND, /**< Instruction: RDRAND */
+ DBGFEVENT_INSTR_RDSEED, /**< Instruction: RDSEED */
+ DBGFEVENT_INSTR_XSAVES, /**< Instruction: XSAVES */
+ DBGFEVENT_INSTR_XRSTORS, /**< Instruction: XRSTORS */
+ DBGFEVENT_INSTR_VMM_CALL, /**< Instruction: VMCALL (intel) or VMMCALL (AMD) */
+ DBGFEVENT_INSTR_LAST_COMMON /**< Instruction: the last common event. */
+ = DBGFEVENT_INSTR_VMM_CALL,
+ DBGFEVENT_INSTR_VMX_FIRST, /**< Instruction: VT-x - First. */
+ DBGFEVENT_INSTR_VMX_VMCLEAR /**< Instruction: VT-x VMCLEAR */
+ = DBGFEVENT_INSTR_VMX_FIRST,
+ DBGFEVENT_INSTR_VMX_VMLAUNCH, /**< Instruction: VT-x VMLAUNCH */
+ DBGFEVENT_INSTR_VMX_VMPTRLD, /**< Instruction: VT-x VMPTRLD */
+ DBGFEVENT_INSTR_VMX_VMPTRST, /**< Instruction: VT-x VMPTRST */
+ DBGFEVENT_INSTR_VMX_VMREAD, /**< Instruction: VT-x VMREAD */
+ DBGFEVENT_INSTR_VMX_VMRESUME, /**< Instruction: VT-x VMRESUME */
+ DBGFEVENT_INSTR_VMX_VMWRITE, /**< Instruction: VT-x VMWRITE */
+ DBGFEVENT_INSTR_VMX_VMXOFF, /**< Instruction: VT-x VMXOFF */
+ DBGFEVENT_INSTR_VMX_VMXON, /**< Instruction: VT-x VMXON */
+ DBGFEVENT_INSTR_VMX_VMFUNC, /**< Instruction: VT-x VMFUNC */
+ DBGFEVENT_INSTR_VMX_INVEPT, /**< Instruction: VT-x INVEPT */
+ DBGFEVENT_INSTR_VMX_INVVPID, /**< Instruction: VT-x INVVPID */
+ DBGFEVENT_INSTR_VMX_INVPCID, /**< Instruction: VT-x INVPCID */
+ DBGFEVENT_INSTR_VMX_LAST /**< Instruction: VT-x - Last. */
+ = DBGFEVENT_INSTR_VMX_INVPCID,
+ DBGFEVENT_INSTR_SVM_FIRST, /**< Instruction: AMD-V - first */
+ DBGFEVENT_INSTR_SVM_VMRUN /**< Instruction: AMD-V VMRUN */
+ = DBGFEVENT_INSTR_SVM_FIRST,
+ DBGFEVENT_INSTR_SVM_VMLOAD, /**< Instruction: AMD-V VMLOAD */
+ DBGFEVENT_INSTR_SVM_VMSAVE, /**< Instruction: AMD-V VMSAVE */
+ DBGFEVENT_INSTR_SVM_STGI, /**< Instruction: AMD-V STGI */
+ DBGFEVENT_INSTR_SVM_CLGI, /**< Instruction: AMD-V CLGI */
+ DBGFEVENT_INSTR_SVM_LAST /**< Instruction: The last ADM-V VM exit event. */
+ = DBGFEVENT_INSTR_SVM_CLGI,
+ DBGFEVENT_INSTR_LAST /**< Instruction: The last instruction event. */
+ = DBGFEVENT_INSTR_SVM_LAST,
+ /** @} */
+
+
+ /** @name VM exit events.
+ * VM exits events for VT-x and AMD-V execution mode. Many of the VM exits
+ * behind these events are also directly translated into instruction events, but
+ * the difference here is that the exit events will not try provoke the exits.
+ * @{ */
+ DBGFEVENT_EXIT_FIRST, /**< The first VM exit event. */
+ DBGFEVENT_EXIT_TASK_SWITCH /**< Exit: Task switch. */
+ = DBGFEVENT_EXIT_FIRST,
+ DBGFEVENT_EXIT_HALT, /**< Exit: HALT instruction. */
+ DBGFEVENT_EXIT_MWAIT, /**< Exit: MWAIT instruction. */
+ DBGFEVENT_EXIT_MONITOR, /**< Exit: MONITOR instruction. */
+ DBGFEVENT_EXIT_CPUID, /**< Exit: CPUID instruction (missing stuff in raw-mode). */
+ DBGFEVENT_EXIT_INVD, /**< Exit: INVD instruction. */
+ DBGFEVENT_EXIT_WBINVD, /**< Exit: WBINVD instruction. */
+ DBGFEVENT_EXIT_INVLPG, /**< Exit: INVLPG instruction. */
+ DBGFEVENT_EXIT_RDTSC, /**< Exit: RDTSC instruction. */
+ DBGFEVENT_EXIT_RDTSCP, /**< Exit: RDTSCP instruction. */
+ DBGFEVENT_EXIT_RDPMC, /**< Exit: RDPMC instruction. */
+ DBGFEVENT_EXIT_RDMSR, /**< Exit: RDMSR instruction. */
+ DBGFEVENT_EXIT_WRMSR, /**< Exit: WRMSR instruction. */
+ DBGFEVENT_EXIT_CRX_READ, /**< Exit: CRx read instruction (missing smsw in raw-mode, and reads in general in VT-x). */
+ DBGFEVENT_EXIT_CRX_WRITE, /**< Exit: CRx write instruction. */
+ DBGFEVENT_EXIT_DRX_READ, /**< Exit: DRx read instruction. */
+ DBGFEVENT_EXIT_DRX_WRITE, /**< Exit: DRx write instruction. */
+ DBGFEVENT_EXIT_PAUSE, /**< Exit: PAUSE instruction (not in raw-mode). */
+ DBGFEVENT_EXIT_XSETBV, /**< Exit: XSETBV instruction. */
+ DBGFEVENT_EXIT_SIDT, /**< Exit: SIDT instruction. */
+ DBGFEVENT_EXIT_LIDT, /**< Exit: LIDT instruction. */
+ DBGFEVENT_EXIT_SGDT, /**< Exit: SGDT instruction. */
+ DBGFEVENT_EXIT_LGDT, /**< Exit: LGDT instruction. */
+ DBGFEVENT_EXIT_SLDT, /**< Exit: SLDT instruction. */
+ DBGFEVENT_EXIT_LLDT, /**< Exit: LLDT instruction. */
+ DBGFEVENT_EXIT_STR, /**< Exit: STR instruction. */
+ DBGFEVENT_EXIT_LTR, /**< Exit: LTR instruction. */
+ DBGFEVENT_EXIT_GETSEC, /**< Exit: GETSEC instruction. */
+ DBGFEVENT_EXIT_RSM, /**< Exit: RSM instruction. */
+ DBGFEVENT_EXIT_RDRAND, /**< Exit: RDRAND instruction. */
+ DBGFEVENT_EXIT_RDSEED, /**< Exit: RDSEED instruction. */
+ DBGFEVENT_EXIT_XSAVES, /**< Exit: XSAVES instruction. */
+ DBGFEVENT_EXIT_XRSTORS, /**< Exit: XRSTORS instruction. */
+ DBGFEVENT_EXIT_VMM_CALL, /**< Exit: VMCALL (intel) or VMMCALL (AMD) instruction. */
+ DBGFEVENT_EXIT_LAST_COMMON /**< Exit: the last common event. */
+ = DBGFEVENT_EXIT_VMM_CALL,
+ DBGFEVENT_EXIT_VMX_FIRST, /**< Exit: VT-x - First. */
+ DBGFEVENT_EXIT_VMX_VMCLEAR /**< Exit: VT-x VMCLEAR instruction. */
+ = DBGFEVENT_EXIT_VMX_FIRST,
+ DBGFEVENT_EXIT_VMX_VMLAUNCH, /**< Exit: VT-x VMLAUNCH instruction. */
+ DBGFEVENT_EXIT_VMX_VMPTRLD, /**< Exit: VT-x VMPTRLD instruction. */
+ DBGFEVENT_EXIT_VMX_VMPTRST, /**< Exit: VT-x VMPTRST instruction. */
+ DBGFEVENT_EXIT_VMX_VMREAD, /**< Exit: VT-x VMREAD instruction. */
+ DBGFEVENT_EXIT_VMX_VMRESUME, /**< Exit: VT-x VMRESUME instruction. */
+ DBGFEVENT_EXIT_VMX_VMWRITE, /**< Exit: VT-x VMWRITE instruction. */
+ DBGFEVENT_EXIT_VMX_VMXOFF, /**< Exit: VT-x VMXOFF instruction. */
+ DBGFEVENT_EXIT_VMX_VMXON, /**< Exit: VT-x VMXON instruction. */
+ DBGFEVENT_EXIT_VMX_VMFUNC, /**< Exit: VT-x VMFUNC instruction. */
+ DBGFEVENT_EXIT_VMX_INVEPT, /**< Exit: VT-x INVEPT instruction. */
+ DBGFEVENT_EXIT_VMX_INVVPID, /**< Exit: VT-x INVVPID instruction. */
+ DBGFEVENT_EXIT_VMX_INVPCID, /**< Exit: VT-x INVPCID instruction. */
+ DBGFEVENT_EXIT_VMX_EPT_VIOLATION, /**< Exit: VT-x EPT violation. */
+ DBGFEVENT_EXIT_VMX_EPT_MISCONFIG, /**< Exit: VT-x EPT misconfiguration. */
+ DBGFEVENT_EXIT_VMX_VAPIC_ACCESS, /**< Exit: VT-x Virtual APIC page access. */
+ DBGFEVENT_EXIT_VMX_VAPIC_WRITE, /**< Exit: VT-x Virtual APIC write. */
+ DBGFEVENT_EXIT_VMX_LAST /**< Exit: VT-x - Last. */
+ = DBGFEVENT_EXIT_VMX_VAPIC_WRITE,
+ DBGFEVENT_EXIT_SVM_FIRST, /**< Exit: AMD-V - first */
+ DBGFEVENT_EXIT_SVM_VMRUN /**< Exit: AMD-V VMRUN instruction. */
+ = DBGFEVENT_EXIT_SVM_FIRST,
+ DBGFEVENT_EXIT_SVM_VMLOAD, /**< Exit: AMD-V VMLOAD instruction. */
+ DBGFEVENT_EXIT_SVM_VMSAVE, /**< Exit: AMD-V VMSAVE instruction. */
+ DBGFEVENT_EXIT_SVM_STGI, /**< Exit: AMD-V STGI instruction. */
+ DBGFEVENT_EXIT_SVM_CLGI, /**< Exit: AMD-V CLGI instruction. */
+ DBGFEVENT_EXIT_SVM_LAST /**< Exit: The last ADM-V VM exit event. */
+ = DBGFEVENT_EXIT_SVM_CLGI,
+ DBGFEVENT_EXIT_LAST /**< Exit: The last VM exit event. */
+ = DBGFEVENT_EXIT_SVM_LAST,
+ /** @} */
+
+
+ /** @name Misc VT-x and AMD-V execution events.
+ * @{ */
+ DBGFEVENT_VMX_SPLIT_LOCK, /**< VT-x: Split-lock \#AC triggered by host having detection enabled. */
+ /** @} */
+
+
+ /** Access to an unassigned I/O port.
+ * @todo not yet implemented. */
+ DBGFEVENT_IOPORT_UNASSIGNED,
+ /** Access to an unused I/O port on a device.
+ * @todo not yet implemented. */
+ DBGFEVENT_IOPORT_UNUSED,
+ /** Unassigned memory event.
+ * @todo not yet implemented. */
+ DBGFEVENT_MEMORY_UNASSIGNED,
+ /** Attempt to write to unshadowed ROM.
+ * @todo not yet implemented. */
+ DBGFEVENT_MEMORY_ROM_WRITE,
+
+ /** Windows guest reported BSOD via hyperv MSRs. */
+ DBGFEVENT_BSOD_MSR,
+ /** Windows guest reported BSOD via EFI variables. */
+ DBGFEVENT_BSOD_EFI,
+ /** Windows guest reported BSOD via VMMDev. */
+ DBGFEVENT_BSOD_VMMDEV,
+
+ /** End of valid event values. */
+ DBGFEVENT_END,
+ /** The usual 32-bit hack. */
+ DBGFEVENT_32BIT_HACK = 0x7fffffff
+} DBGFEVENTTYPE;
+AssertCompile(DBGFEVENT_XCPT_LAST - DBGFEVENT_XCPT_FIRST == 0x1f);
+
+/**
+ * The context of an event.
+ */
+typedef enum DBGFEVENTCTX
+{
+ /** The usual invalid entry. */
+ DBGFEVENTCTX_INVALID = 0,
+ /** Raw mode. */
+ DBGFEVENTCTX_RAW,
+ /** Recompiled mode. */
+ DBGFEVENTCTX_REM,
+ /** VMX / AVT mode. */
+ DBGFEVENTCTX_HM,
+ /** Hypervisor context. */
+ DBGFEVENTCTX_HYPER,
+ /** Other mode */
+ DBGFEVENTCTX_OTHER,
+
+ /** The usual 32-bit hack */
+ DBGFEVENTCTX_32BIT_HACK = 0x7fffffff
+} DBGFEVENTCTX;
+
+/**
+ * VMM Debug Event.
+ */
+typedef struct DBGFEVENT
+{
+ /** Type. */
+ DBGFEVENTTYPE enmType;
+ /** Context */
+ DBGFEVENTCTX enmCtx;
+ /** The vCPU/EMT which generated the event. */
+ VMCPUID idCpu;
+ /** Reserved. */
+ uint32_t uReserved;
+ /** Type specific data. */
+ union
+ {
+ /** Fatal error details. */
+ struct
+ {
+ /** The GC return code. */
+ int rc;
+ } FatalError;
+
+ /** Source location. */
+ struct
+ {
+ /** File name. */
+ R3PTRTYPE(const char *) pszFile;
+ /** Function name. */
+ R3PTRTYPE(const char *) pszFunction;
+ /** Message. */
+ R3PTRTYPE(const char *) pszMessage;
+ /** Line number. */
+ unsigned uLine;
+ } Src;
+
+ /** Assertion messages. */
+ struct
+ {
+ /** The first message. */
+ R3PTRTYPE(const char *) pszMsg1;
+ /** The second message. */
+ R3PTRTYPE(const char *) pszMsg2;
+ } Assert;
+
+ /** Breakpoint. */
+ struct DBGFEVENTBP
+ {
+ /** The handle of the breakpoint which was hit. */
+ DBGFBP hBp;
+ } Bp;
+
+ /** Generic debug event. */
+ struct DBGFEVENTGENERIC
+ {
+ /** Number of arguments. */
+ uint8_t cArgs;
+ /** Alignment padding. */
+ uint8_t uPadding[7];
+ /** Arguments. */
+ uint64_t auArgs[5];
+ } Generic;
+
+ /** Padding for ensuring that the structure is 8 byte aligned. */
+ uint64_t au64Padding[6];
+ } u;
+} DBGFEVENT;
+AssertCompileSizeAlignment(DBGFEVENT, 8);
+AssertCompileSize(DBGFEVENT, 64);
+/** Pointer to VMM Debug Event. */
+typedef DBGFEVENT *PDBGFEVENT;
+/** Pointer to const VMM Debug Event. */
+typedef const DBGFEVENT *PCDBGFEVENT;
+
+#ifdef IN_RING3 /* The event API only works in ring-3. */
+
+/** @def DBGFSTOP
+ * Stops the debugger raising a DBGFEVENT_DEVELOPER_STOP event.
+ *
+ * @returns VBox status code which must be propagated up to EM if not VINF_SUCCESS.
+ * @param pVM The cross context VM structure.
+ */
+# ifdef VBOX_STRICT
+# define DBGFSTOP(pVM) DBGFR3EventSrc(pVM, DBGFEVENT_DEV_STOP, __FILE__, __LINE__, __PRETTY_FUNCTION__, NULL)
+# else
+# define DBGFSTOP(pVM) VINF_SUCCESS
+# endif
+
+VMMR3_INT_DECL(int) DBGFR3Init(PVM pVM);
+VMMR3_INT_DECL(int) DBGFR3Term(PVM pVM);
+VMMR3DECL(void) DBGFR3TermUVM(PUVM pUVM);
+VMMR3_INT_DECL(void) DBGFR3PowerOff(PVM pVM);
+VMMR3_INT_DECL(void) DBGFR3Relocate(PVM pVM, RTGCINTPTR offDelta);
+
+VMMR3_INT_DECL(int) DBGFR3VMMForcedAction(PVM pVM, PVMCPU pVCpu);
+VMMR3_INT_DECL(VBOXSTRICTRC) DBGFR3EventHandlePending(PVM pVM, PVMCPU pVCpu);
+VMMR3DECL(int) DBGFR3Event(PVM pVM, DBGFEVENTTYPE enmEvent);
+VMMR3DECL(int) DBGFR3EventSrc(PVM pVM, DBGFEVENTTYPE enmEvent, const char *pszFile, unsigned uLine,
+ const char *pszFunction, const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR_MAYBE_NULL(6, 7);
+VMMR3DECL(int) DBGFR3EventSrcV(PVM pVM, DBGFEVENTTYPE enmEvent, const char *pszFile, unsigned uLine,
+ const char *pszFunction, const char *pszFormat, va_list args) RT_IPRT_FORMAT_ATTR_MAYBE_NULL(6, 0);
+VMMR3_INT_DECL(int) DBGFR3EventAssertion(PVM pVM, DBGFEVENTTYPE enmEvent, const char *pszMsg1, const char *pszMsg2);
+VMMR3_INT_DECL(int) DBGFR3EventBreakpoint(PVM pVM, DBGFEVENTTYPE enmEvent);
+
+VMMR3_INT_DECL(int) DBGFR3PrgStep(PVMCPU pVCpu);
+
+VMMR3DECL(int) DBGFR3Attach(PUVM pUVM);
+VMMR3DECL(int) DBGFR3Detach(PUVM pUVM);
+VMMR3DECL(int) DBGFR3EventWait(PUVM pUVM, RTMSINTERVAL cMillies, PDBGFEVENT pEvent);
+VMMR3DECL(int) DBGFR3Halt(PUVM pUVM, VMCPUID idCpu);
+VMMR3DECL(bool) DBGFR3IsHalted(PUVM pUVM, VMCPUID idCpu);
+VMMR3DECL(int) DBGFR3QueryWaitable(PUVM pUVM);
+VMMR3DECL(int) DBGFR3Resume(PUVM pUVM, VMCPUID idCpu);
+VMMR3DECL(int) DBGFR3InjectNMI(PUVM pUVM, VMCPUID idCpu);
+VMMR3DECL(int) DBGFR3Step(PUVM pUVM, VMCPUID idCpu);
+VMMR3DECL(int) DBGFR3StepEx(PUVM pUVM, VMCPUID idCpu, uint32_t fFlags, PCDBGFADDRESS pStopPcAddr,
+ PCDBGFADDRESS pStopPopAddr, RTGCUINTPTR cbStopPop, uint32_t cMaxSteps);
+
+/** @name DBGF_STEP_F_XXX - Flags for DBGFR3StepEx.
+ *
+ * @note The stop filters are not applied to the starting instruction.
+ *
+ * @{ */
+/** Step into CALL, INT, SYSCALL and SYSENTER instructions. */
+#define DBGF_STEP_F_INTO RT_BIT_32(0)
+/** Step over CALL, INT, SYSCALL and SYSENTER instruction when considering
+ * what's "next". */
+#define DBGF_STEP_F_OVER RT_BIT_32(1)
+
+/** Stop on the next CALL, INT, SYSCALL, SYSENTER instruction. */
+#define DBGF_STEP_F_STOP_ON_CALL RT_BIT_32(8)
+/** Stop on the next RET, IRET, SYSRET, SYSEXIT instruction. */
+#define DBGF_STEP_F_STOP_ON_RET RT_BIT_32(9)
+/** Stop after the next RET, IRET, SYSRET, SYSEXIT instruction. */
+#define DBGF_STEP_F_STOP_AFTER_RET RT_BIT_32(10)
+/** Stop on the given address.
+ * The comparison will be made using effective (flat) addresses. */
+#define DBGF_STEP_F_STOP_ON_ADDRESS RT_BIT_32(11)
+/** Stop when the stack pointer pops to or past the given address.
+ * The comparison will be made using effective (flat) addresses. */
+#define DBGF_STEP_F_STOP_ON_STACK_POP RT_BIT_32(12)
+/** Mask of stop filter flags. */
+#define DBGF_STEP_F_STOP_FILTER_MASK UINT32_C(0x00001f00)
+
+/** Mask of valid flags. */
+#define DBGF_STEP_F_VALID_MASK UINT32_C(0x00001f03)
+/** @} */
+
+/**
+ * Event configuration array element, see DBGFR3EventConfigEx.
+ */
+typedef struct DBGFEVENTCONFIG
+{
+ /** The event to configure */
+ DBGFEVENTTYPE enmType;
+ /** The new state. */
+ bool fEnabled;
+ /** Unused. */
+ uint8_t abUnused[3];
+} DBGFEVENTCONFIG;
+/** Pointer to an event config. */
+typedef DBGFEVENTCONFIG *PDBGFEVENTCONFIG;
+/** Pointer to a const event config. */
+typedef const DBGFEVENTCONFIG *PCDBGFEVENTCONFIG;
+
+VMMR3DECL(int) DBGFR3EventConfigEx(PUVM pUVM, PCDBGFEVENTCONFIG paConfigs, size_t cConfigs);
+VMMR3DECL(int) DBGFR3EventConfig(PUVM pUVM, DBGFEVENTTYPE enmEvent, bool fEnabled);
+VMMR3DECL(bool) DBGFR3EventIsEnabled(PUVM pUVM, DBGFEVENTTYPE enmEvent);
+VMMR3DECL(int) DBGFR3EventQuery(PUVM pUVM, PDBGFEVENTCONFIG paConfigs, size_t cConfigs);
+
+/** @name DBGFINTERRUPTSTATE_XXX - interrupt break state.
+ * @{ */
+#define DBGFINTERRUPTSTATE_DISABLED 0
+#define DBGFINTERRUPTSTATE_ENABLED 1
+#define DBGFINTERRUPTSTATE_DONT_TOUCH 2
+/** @} */
+
+/**
+ * Interrupt break state configuration entry.
+ */
+typedef struct DBGFINTERRUPTCONFIG
+{
+ /** The interrupt number. */
+ uint8_t iInterrupt;
+ /** The hardware interrupt state (DBGFINTERRUPTSTATE_XXX). */
+ uint8_t enmHardState;
+ /** The software interrupt state (DBGFINTERRUPTSTATE_XXX). */
+ uint8_t enmSoftState;
+} DBGFINTERRUPTCONFIG;
+/** Pointer to an interrupt break state config entyr. */
+typedef DBGFINTERRUPTCONFIG *PDBGFINTERRUPTCONFIG;
+/** Pointer to a const interrupt break state config entyr. */
+typedef DBGFINTERRUPTCONFIG const *PCDBGFINTERRUPTCONFIG;
+
+VMMR3DECL(int) DBGFR3InterruptConfigEx(PUVM pUVM, PCDBGFINTERRUPTCONFIG paConfigs, size_t cConfigs);
+VMMR3DECL(int) DBGFR3InterruptHardwareConfig(PUVM pUVM, uint8_t iInterrupt, bool fEnabled);
+VMMR3DECL(int) DBGFR3InterruptSoftwareConfig(PUVM pUVM, uint8_t iInterrupt, bool fEnabled);
+VMMR3DECL(int) DBGFR3InterruptHardwareIsEnabled(PUVM pUVM, uint8_t iInterrupt);
+VMMR3DECL(int) DBGFR3InterruptSoftwareIsEnabled(PUVM pUVM, uint8_t iInterrupt);
+
+#endif /* IN_RING3 */
+
+/** @def DBGF_IS_EVENT_ENABLED
+ * Checks if a selectable debug event is enabled or not (fast).
+ *
+ * @returns true/false.
+ * @param a_pVM Pointer to the cross context VM structure.
+ * @param a_enmEvent The selectable event to check.
+ * @remarks Only for use internally in the VMM. Use DBGFR3EventIsEnabled elsewhere.
+ */
+#if defined(VBOX_STRICT) && defined(RT_COMPILER_SUPPORTS_LAMBDA)
+# define DBGF_IS_EVENT_ENABLED(a_pVM, a_enmEvent) \
+ ([](PVM a_pLambdaVM, DBGFEVENTTYPE a_enmLambdaEvent) -> bool { \
+ Assert( a_enmLambdaEvent >= DBGFEVENT_FIRST_SELECTABLE \
+ || a_enmLambdaEvent == DBGFEVENT_INTERRUPT_HARDWARE \
+ || a_enmLambdaEvent == DBGFEVENT_INTERRUPT_SOFTWARE); \
+ Assert(a_enmLambdaEvent < DBGFEVENT_END); \
+ return ASMBitTest(&a_pLambdaVM->dbgf.ro.bmSelectedEvents, a_enmLambdaEvent); \
+ }(a_pVM, a_enmEvent))
+#elif defined(VBOX_STRICT) && defined(__GNUC__)
+# define DBGF_IS_EVENT_ENABLED(a_pVM, a_enmEvent) \
+ __extension__ ({ \
+ Assert( (a_enmEvent) >= DBGFEVENT_FIRST_SELECTABLE \
+ || (a_enmEvent) == DBGFEVENT_INTERRUPT_HARDWARE \
+ || (a_enmEvent) == DBGFEVENT_INTERRUPT_SOFTWARE); \
+ Assert((a_enmEvent) < DBGFEVENT_END); \
+ ASMBitTest(&(a_pVM)->dbgf.ro.bmSelectedEvents, (a_enmEvent)); \
+ })
+#else
+# define DBGF_IS_EVENT_ENABLED(a_pVM, a_enmEvent) \
+ ASMBitTest(&(a_pVM)->dbgf.ro.bmSelectedEvents, (a_enmEvent))
+#endif
+
+
+/** @def DBGF_IS_HARDWARE_INT_ENABLED
+ * Checks if hardware interrupt interception is enabled or not for an interrupt.
+ *
+ * @returns true/false.
+ * @param a_pVM Pointer to the cross context VM structure.
+ * @param a_iInterrupt Interrupt to check.
+ * @remarks Only for use internally in the VMM. Use
+ * DBGFR3InterruptHardwareIsEnabled elsewhere.
+ */
+#define DBGF_IS_HARDWARE_INT_ENABLED(a_pVM, a_iInterrupt) \
+ ASMBitTest(&(a_pVM)->dbgf.ro.bmHardIntBreakpoints, (uint8_t)(a_iInterrupt))
+
+/** @def DBGF_IS_SOFTWARE_INT_ENABLED
+ * Checks if software interrupt interception is enabled or not for an interrupt.
+ *
+ * @returns true/false.
+ * @param a_pVM Pointer to the cross context VM structure.
+ * @param a_iInterrupt Interrupt to check.
+ * @remarks Only for use internally in the VMM. Use
+ * DBGFR3InterruptSoftwareIsEnabled elsewhere.
+ */
+#define DBGF_IS_SOFTWARE_INT_ENABLED(a_pVM, a_iInterrupt) \
+ ASMBitTest(&(a_pVM)->dbgf.ro.bmSoftIntBreakpoints, (uint8_t)(a_iInterrupt))
+
+
+
+/** Breakpoint type. */
+typedef enum DBGFBPTYPE
+{
+ /** Invalid breakpoint type. */
+ DBGFBPTYPE_INVALID = 0,
+ /** Debug register. */
+ DBGFBPTYPE_REG,
+ /** INT 3 instruction. */
+ DBGFBPTYPE_INT3,
+ /** Port I/O breakpoint. */
+ DBGFBPTYPE_PORT_IO,
+ /** Memory mapped I/O breakpoint. */
+ DBGFBPTYPE_MMIO,
+ /** ensure 32-bit size. */
+ DBGFBPTYPE_32BIT_HACK = 0x7fffffff
+} DBGFBPTYPE;
+
+
+/** @name DBGFBPIOACCESS_XXX - I/O (port + mmio) access types.
+ * @{ */
+/** Byte sized read accesses. */
+#define DBGFBPIOACCESS_READ_BYTE UINT32_C(0x00000001)
+/** Word sized accesses. */
+#define DBGFBPIOACCESS_READ_WORD UINT32_C(0x00000002)
+/** Double word sized accesses. */
+#define DBGFBPIOACCESS_READ_DWORD UINT32_C(0x00000004)
+/** Quad word sized accesses - not available for I/O ports. */
+#define DBGFBPIOACCESS_READ_QWORD UINT32_C(0x00000008)
+/** Other sized accesses - not available for I/O ports. */
+#define DBGFBPIOACCESS_READ_OTHER UINT32_C(0x00000010)
+/** Read mask. */
+#define DBGFBPIOACCESS_READ_MASK UINT32_C(0x0000001f)
+
+/** Byte sized write accesses. */
+#define DBGFBPIOACCESS_WRITE_BYTE UINT32_C(0x00000100)
+/** Word sized write accesses. */
+#define DBGFBPIOACCESS_WRITE_WORD UINT32_C(0x00000200)
+/** Double word sized write accesses. */
+#define DBGFBPIOACCESS_WRITE_DWORD UINT32_C(0x00000400)
+/** Quad word sized write accesses - not available for I/O ports. */
+#define DBGFBPIOACCESS_WRITE_QWORD UINT32_C(0x00000800)
+/** Other sized write accesses - not available for I/O ports. */
+#define DBGFBPIOACCESS_WRITE_OTHER UINT32_C(0x00001000)
+/** Write mask. */
+#define DBGFBPIOACCESS_WRITE_MASK UINT32_C(0x00001f00)
+
+/** All kind of access (read, write, all sizes). */
+#define DBGFBPIOACCESS_ALL UINT32_C(0x00001f1f)
+/** All kind of access for MMIO (read, write, all sizes). */
+#define DBGFBPIOACCESS_ALL_MMIO DBGFBPIOACCESS_ALL
+/** All kind of access (read, write, all sizes). */
+#define DBGFBPIOACCESS_ALL_PORT_IO UINT32_C(0x00000303)
+
+/** The acceptable mask for I/O ports. */
+#define DBGFBPIOACCESS_VALID_MASK_PORT_IO UINT32_C(0x00000303)
+/** The acceptable mask for MMIO. */
+#define DBGFBPIOACCESS_VALID_MASK_MMIO UINT32_C(0x00001f1f)
+/** @} */
+
+/**
+ * The visible breakpoint state (read-only).
+ */
+typedef struct DBGFBPPUB
+{
+ /** The number of breakpoint hits. */
+ uint64_t cHits;
+ /** The hit number which starts to trigger the breakpoint. */
+ uint64_t iHitTrigger;
+ /** The hit number which stops triggering the breakpoint (disables it).
+ * Use ~(uint64_t)0 if it should never stop. */
+ uint64_t iHitDisable;
+ /** The breakpoint owner handle (a nil owner defers the breakpoint to the
+ * debugger). */
+ DBGFBPOWNER hOwner;
+ /** Breakpoint type stored as a 16bit integer to stay within size limits. */
+ uint16_t u16Type;
+ /** Breakpoint flags. */
+ uint16_t fFlags;
+
+ /** Union of type specific data. */
+ union
+ {
+ /** The flat GC address breakpoint address for REG and INT3 breakpoints. */
+ RTGCUINTPTR GCPtr;
+
+ /** Debug register data. */
+ struct DBGFBPREG
+ {
+ /** The flat GC address of the breakpoint. */
+ RTGCUINTPTR GCPtr;
+ /** The debug register number. */
+ uint8_t iReg;
+ /** The access type (one of the X86_DR7_RW_* value). */
+ uint8_t fType;
+ /** The access size. */
+ uint8_t cb;
+ } Reg;
+
+ /** INT3 breakpoint data. */
+ struct DBGFBPINT3
+ {
+ /** The flat GC address of the breakpoint. */
+ RTGCUINTPTR GCPtr;
+ /** The physical address of the breakpoint. */
+ RTGCPHYS PhysAddr;
+ /** The byte value we replaced by the INT 3 instruction. */
+ uint8_t bOrg;
+ } Int3;
+
+ /** I/O port breakpoint data. */
+ struct DBGFBPPORTIO
+ {
+ /** The first port. */
+ RTIOPORT uPort;
+ /** The number of ports. */
+ RTIOPORT cPorts;
+ /** Valid DBGFBPIOACCESS_XXX selection, max DWORD size. */
+ uint32_t fAccess;
+ } PortIo;
+
+ /** Memory mapped I/O breakpoint data. */
+ struct DBGFBPMMIO
+ {
+ /** The first MMIO address. */
+ RTGCPHYS PhysAddr;
+ /** The size of the MMIO range in bytes. */
+ uint32_t cb;
+ /** Valid DBGFBPIOACCESS_XXX selection, max QWORD size. */
+ uint32_t fAccess;
+ } Mmio;
+
+ /** Padding to the anticipated size. */
+ uint64_t u64Padding[3];
+ } u;
+} DBGFBPPUB;
+AssertCompileSize(DBGFBPPUB, 64 - 8);
+AssertCompileMembersAtSameOffset(DBGFBPPUB, u.GCPtr, DBGFBPPUB, u.Reg.GCPtr);
+AssertCompileMembersAtSameOffset(DBGFBPPUB, u.GCPtr, DBGFBPPUB, u.Int3.GCPtr);
+
+/** Pointer to the visible breakpoint state. */
+typedef DBGFBPPUB *PDBGFBPPUB;
+/** Pointer to a const visible breakpoint state. */
+typedef const DBGFBPPUB *PCDBGFBPPUB;
+
+/** Sets the DBGFPUB::u16Type member. */
+#define DBGF_BP_PUB_MAKE_TYPE(a_enmType) ((uint16_t)(a_enmType))
+/** Returns the type of the DBGFPUB::u16Type member. */
+#define DBGF_BP_PUB_GET_TYPE(a_pBp) ((DBGFBPTYPE)((a_pBp)->u16Type))
+/** Returns the enabled status of DBGFPUB::fFlags member. */
+#define DBGF_BP_PUB_IS_ENABLED(a_pBp) RT_BOOL((a_pBp)->fFlags & DBGF_BP_F_ENABLED)
+/** Returns whether DBGF_BP_F_HIT_EXEC_BEFORE is set for DBGFPUB::fFlags. */
+#define DBGF_BP_PUB_IS_EXEC_BEFORE(a_pBp) RT_BOOL((a_pBp)->fFlags & DBGF_BP_F_HIT_EXEC_BEFORE)
+/** Returns whether DBGF_BP_F_HIT_EXEC_AFTER is set for DBGFPUB::fFlags. */
+#define DBGF_BP_PUB_IS_EXEC_AFTER(a_pBp) RT_BOOL((a_pBp)->fFlags & DBGF_BP_F_HIT_EXEC_AFTER)
+
+
+/** @name Possible DBGFBPPUB::fFlags flags.
+ * @{ */
+/** Default flags, breakpoint is enabled and hits before the instruction is executed. */
+#define DBGF_BP_F_DEFAULT (DBGF_BP_F_ENABLED | DBGF_BP_F_HIT_EXEC_BEFORE)
+/** Flag whether the breakpoint is enabled currently. */
+#define DBGF_BP_F_ENABLED RT_BIT(0)
+/** Flag indicating whether the action assoicated with the breakpoint should be carried out
+ * before the instruction causing the breakpoint to hit was executed. */
+#define DBGF_BP_F_HIT_EXEC_BEFORE RT_BIT(1)
+/** Flag indicating whether the action assoicated with the breakpoint should be carried out
+ * after the instruction causing the breakpoint to hit was executed. */
+#define DBGF_BP_F_HIT_EXEC_AFTER RT_BIT(2)
+/** The acceptable flags mask. */
+#define DBGF_BP_F_VALID_MASK UINT32_C(0x00000007)
+/** @} */
+
+
+/**
+ * Breakpoint hit handler.
+ *
+ * @returns Strict VBox status code.
+ * @retval VINF_SUCCESS if the breakpoint was handled and guest execution can resume.
+ * @retval VINF_DBGF_BP_HALT if guest execution should be stopped and the debugger should be invoked.
+ * @retval VINF_DBGF_R3_BP_OWNER_DEFER return to ring-3 and invoke the owner callback there again.
+ *
+ * @param pVM The cross-context VM structure pointer.
+ * @param idCpu ID of the vCPU triggering the breakpoint.
+ * @param pvUserBp User argument of the set breakpoint.
+ * @param hBp The breakpoint handle.
+ * @param pBpPub Pointer to the readonly public state of the breakpoint.
+ * @param fFlags Flags indicating when the handler was called (DBGF_BP_F_HIT_EXEC_BEFORE vs DBGF_BP_F_HIT_EXEC_AFTER).
+ *
+ * @remarks The handler is called on the EMT of vCPU triggering the breakpoint and no locks are held.
+ * @remarks Any status code returned other than the ones mentioned will send the VM straight into a
+ * guru meditation.
+ */
+typedef DECLCALLBACKTYPE(VBOXSTRICTRC, FNDBGFBPHIT,(PVM pVM, VMCPUID idCpu, void *pvUserBp, DBGFBP hBp, PCDBGFBPPUB pBpPub,
+ uint16_t fFlags));
+/** Pointer to a FNDBGFBPHIT(). */
+typedef FNDBGFBPHIT *PFNDBGFBPHIT;
+
+
+/**
+ * I/O breakpoint hit handler.
+ *
+ * @returns Strict VBox status code.
+ * @retval VINF_SUCCESS if the breakpoint was handled and guest execution can resume.
+ * @retval VINF_DBGF_BP_HALT if guest execution should be stopped and the debugger should be invoked.
+ * @retval VINF_DBGF_R3_BP_OWNER_DEFER return to ring-3 and invoke the owner callback there again.
+ *
+ * @param pVM The cross-context VM structure pointer.
+ * @param idCpu ID of the vCPU triggering the breakpoint.
+ * @param pvUserBp User argument of the set breakpoint.
+ * @param hBp The breakpoint handle.
+ * @param pBpPub Pointer to the readonly public state of the breakpoint.
+ * @param fFlags Flags indicating when the handler was called (DBGF_BP_F_HIT_EXEC_BEFORE vs DBGF_BP_F_HIT_EXEC_AFTER).
+ * @param fAccess Access flags, see DBGFBPIOACCESS_XXX.
+ * @param uAddr The address of the access, for port I/O this will hold the port number.
+ * @param uValue The value read or written (the value for reads is only valid when DBGF_BP_F_HIT_EXEC_AFTER is set).
+ *
+ * @remarks The handler is called on the EMT of vCPU triggering the breakpoint and no locks are held.
+ * @remarks Any status code returned other than the ones mentioned will send the VM straight into a
+ * guru meditation.
+ */
+typedef DECLCALLBACKTYPE(VBOXSTRICTRC, FNDBGFBPIOHIT,(PVM pVM, VMCPUID idCpu, void *pvUserBp, DBGFBP hBp, PCDBGFBPPUB pBpPub,
+ uint16_t fFlags, uint32_t fAccess, uint64_t uAddr, uint64_t uValue));
+/** Pointer to a FNDBGFBPIOHIT(). */
+typedef FNDBGFBPIOHIT *PFNDBGFBPIOHIT;
+
+
+#ifdef IN_RING3
+/** @defgroup grp_dbgf_bp_r3 The DBGF Breakpoint Host Context Ring-3 API
+ * @{ */
+VMMR3DECL(int) DBGFR3BpOwnerCreate(PUVM pUVM, PFNDBGFBPHIT pfnBpHit, PFNDBGFBPIOHIT pfnBpIoHit, PDBGFBPOWNER phBpOwner);
+VMMR3DECL(int) DBGFR3BpOwnerDestroy(PUVM pUVM, DBGFBPOWNER hBpOwner);
+
+VMMR3DECL(int) DBGFR3BpSetInt3(PUVM pUVM, VMCPUID idSrcCpu, PCDBGFADDRESS pAddress,
+ uint64_t iHitTrigger, uint64_t iHitDisable, PDBGFBP phBp);
+VMMR3DECL(int) DBGFR3BpSetInt3Ex(PUVM pUVM, DBGFBPOWNER hOwner, void *pvUser,
+ VMCPUID idSrcCpu, PCDBGFADDRESS pAddress, uint16_t fFlags,
+ uint64_t iHitTrigger, uint64_t iHitDisable, PDBGFBP phBp);
+VMMR3DECL(int) DBGFR3BpSetReg(PUVM pUVM, PCDBGFADDRESS pAddress, uint64_t iHitTrigger,
+ uint64_t iHitDisable, uint8_t fType, uint8_t cb, PDBGFBP phBp);
+VMMR3DECL(int) DBGFR3BpSetRegEx(PUVM pUVM, DBGFBPOWNER hOwner, void *pvUser,
+ PCDBGFADDRESS pAddress, uint16_t fFlags,
+ uint64_t iHitTrigger, uint64_t iHitDisable,
+ uint8_t fType, uint8_t cb, PDBGFBP phBp);
+VMMR3DECL(int) DBGFR3BpSetREM(PUVM pUVM, PCDBGFADDRESS pAddress, uint64_t iHitTrigger,
+ uint64_t iHitDisable, PDBGFBP phBp);
+VMMR3DECL(int) DBGFR3BpSetPortIo(PUVM pUVM, RTIOPORT uPort, RTIOPORT cPorts, uint32_t fAccess,
+ uint64_t iHitTrigger, uint64_t iHitDisable, PDBGFBP phBp);
+VMMR3DECL(int) DBGFR3BpSetPortIoEx(PUVM pUVM, DBGFBPOWNER hOwner, void *pvUser,
+ RTIOPORT uPort, RTIOPORT cPorts, uint32_t fAccess,
+ uint32_t fFlags, uint64_t iHitTrigger, uint64_t iHitDisable, PDBGFBP phBp);
+VMMR3DECL(int) DBGFR3BpSetMmio(PUVM pUVM, RTGCPHYS GCPhys, uint32_t cb, uint32_t fAccess,
+ uint64_t iHitTrigger, uint64_t iHitDisable, PDBGFBP phBp);
+VMMR3DECL(int) DBGFR3BpSetMmioEx(PUVM pUVM, DBGFBPOWNER hOwner, void *pvUser,
+ RTGCPHYS GCPhys, uint32_t cb, uint32_t fAccess,
+ uint32_t fFlags, uint64_t iHitTrigger, uint64_t iHitDisable, PDBGFBP phBp);
+VMMR3DECL(int) DBGFR3BpClear(PUVM pUVM, DBGFBP hBp);
+VMMR3DECL(int) DBGFR3BpEnable(PUVM pUVM, DBGFBP hBp);
+VMMR3DECL(int) DBGFR3BpDisable(PUVM pUVM, DBGFBP hBp);
+
+/**
+ * Breakpoint enumeration callback function.
+ *
+ * @returns VBox status code.
+ * The enumeration stops on failure status and VINF_CALLBACK_RETURN.
+ * @param pUVM The user mode VM handle.
+ * @param pvUser The user argument.
+ * @param hBp The breakpoint handle.
+ * @param pBpPub Pointer to the public breakpoint information. (readonly)
+ */
+typedef DECLCALLBACKTYPE(int, FNDBGFBPENUM,(PUVM pUVM, void *pvUser, DBGFBP hBp, PCDBGFBPPUB pBpPub));
+/** Pointer to a breakpoint enumeration callback function. */
+typedef FNDBGFBPENUM *PFNDBGFBPENUM;
+
+VMMR3DECL(int) DBGFR3BpEnum(PUVM pUVM, PFNDBGFBPENUM pfnCallback, void *pvUser);
+
+VMMR3_INT_DECL(int) DBGFR3BpHit(PVM pVM, PVMCPU pVCpu);
+/** @} */
+#endif /* !IN_RING3 */
+
+
+#if defined(IN_RING0) || defined(DOXYGEN_RUNNING)
+/** @defgroup grp_dbgf_bp_r0 The DBGF Breakpoint Host Context Ring-0 API
+ * @{ */
+VMMR0_INT_DECL(int) DBGFR0BpOwnerSetUpContext(PGVM pGVM, DBGFBPOWNER hBpOwner, PFNDBGFBPHIT pfnBpHit, PFNDBGFBPIOHIT pfnBpIoHit);
+VMMR0_INT_DECL(int) DBGFR0BpOwnerDestroyContext(PGVM pGVM, DBGFBPOWNER hBpOwner);
+
+VMMR0_INT_DECL(int) DBGFR0BpSetUpContext(PGVM pGVM, DBGFBP hBp, void *pvUser);
+VMMR0_INT_DECL(int) DBGFR0BpDestroyContext(PGVM pGVM, DBGFBP hBp);
+/** @} */
+#endif /* IN_RING0 || DOXYGEN_RUNNING */
+
+VMM_INT_DECL(RTGCUINTREG) DBGFBpGetDR7(PVM pVM);
+VMM_INT_DECL(RTGCUINTREG) DBGFBpGetDR0(PVM pVM);
+VMM_INT_DECL(RTGCUINTREG) DBGFBpGetDR1(PVM pVM);
+VMM_INT_DECL(RTGCUINTREG) DBGFBpGetDR2(PVM pVM);
+VMM_INT_DECL(RTGCUINTREG) DBGFBpGetDR3(PVM pVM);
+VMM_INT_DECL(bool) DBGFBpIsHwArmed(PVM pVM);
+VMM_INT_DECL(bool) DBGFBpIsHwIoArmed(PVM pVM);
+VMM_INT_DECL(bool) DBGFBpIsInt3Armed(PVM pVM);
+VMM_INT_DECL(bool) DBGFIsStepping(PVMCPU pVCpu);
+VMM_INT_DECL(VBOXSTRICTRC) DBGFBpCheckInstruction(PVMCC pVM, PVMCPUCC pVCpu, RTGCPTR GCPtrPC);
+VMM_INT_DECL(VBOXSTRICTRC) DBGFBpCheckIo(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, RTIOPORT uIoPort, uint8_t cbValue);
+VMM_INT_DECL(uint32_t) DBGFBpCheckIo2(PVMCC pVM, PVMCPUCC pVCpu, RTIOPORT uIoPort, uint8_t cbValue);
+VMM_INT_DECL(VBOXSTRICTRC) DBGFBpCheckPortIo(PVMCC pVM, PVMCPU pVCpu, RTIOPORT uIoPort,
+ uint32_t fAccess, uint32_t uValue, bool fBefore);
+VMM_INT_DECL(VBOXSTRICTRC) DBGFEventGenericWithArgs(PVM pVM, PVMCPU pVCpu, DBGFEVENTTYPE enmEvent, DBGFEVENTCTX enmCtx,
+ unsigned cArgs, ...);
+VMM_INT_DECL(int) DBGFTrap01Handler(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, RTGCUINTREG uDr6, bool fAltStepping);
+VMM_INT_DECL(VBOXSTRICTRC) DBGFTrap03Handler(PVMCC pVM, PVMCPUCC pVCpu, PCPUMCTX pCtx);
+
+
+#ifdef IN_RING3 /* The CPU mode API only works in ring-3. */
+VMMR3DECL(CPUMMODE) DBGFR3CpuGetMode(PUVM pUVM, VMCPUID idCpu);
+VMMR3DECL(VMCPUID) DBGFR3CpuGetCount(PUVM pUVM);
+VMMR3DECL(bool) DBGFR3CpuIsIn64BitCode(PUVM pUVM, VMCPUID idCpu);
+VMMR3DECL(bool) DBGFR3CpuIsInV86Code(PUVM pUVM, VMCPUID idCpu);
+VMMR3DECL(const char *) DBGFR3CpuGetState(PUVM pUVM, VMCPUID idCpu);
+#endif
+
+
+
+#ifdef IN_RING3 /* The info callbacks API only works in ring-3. */
+
+struct RTGETOPTSTATE;
+union RTGETOPTUNION;
+
+/**
+ * Info helper callback structure.
+ */
+typedef struct DBGFINFOHLP
+{
+ /**
+ * Print formatted string.
+ *
+ * @param pHlp Pointer to this structure.
+ * @param pszFormat The format string.
+ * @param ... Arguments.
+ */
+ DECLCALLBACKMEMBER(void, pfnPrintf,(PCDBGFINFOHLP pHlp, const char *pszFormat, ...)) RT_IPRT_FORMAT_ATTR(2, 3);
+
+ /**
+ * Print formatted string.
+ *
+ * @param pHlp Pointer to this structure.
+ * @param pszFormat The format string.
+ * @param args Argument list.
+ */
+ DECLCALLBACKMEMBER(void, pfnPrintfV,(PCDBGFINFOHLP pHlp, const char *pszFormat, va_list args)) RT_IPRT_FORMAT_ATTR(2, 0);
+
+ /**
+ * Report getopt parsing trouble
+ *
+ * @param pHlp Pointer to this structure.
+ * @param rc The RTGetOpt return value.
+ * @param pValueUnion The value union.
+ * @param pState The getopt state.
+ */
+ DECLCALLBACKMEMBER(void, pfnGetOptError,(PCDBGFINFOHLP pHlp, int rc, union RTGETOPTUNION *pValueUnion,
+ struct RTGETOPTSTATE *pState));
+} DBGFINFOHLP;
+
+
+/**
+ * Info handler, device version.
+ *
+ * @param pDevIns The device instance which registered the info.
+ * @param pHlp Callback functions for doing output.
+ * @param pszArgs Argument string. Optional and specific to the handler.
+ */
+typedef DECLCALLBACKTYPE(void, FNDBGFHANDLERDEV,(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs));
+/** Pointer to a FNDBGFHANDLERDEV function. */
+typedef FNDBGFHANDLERDEV *PFNDBGFHANDLERDEV;
+
+/**
+ * Info handler, driver version.
+ *
+ * @param pDrvIns The driver instance which registered the info.
+ * @param pHlp Callback functions for doing output.
+ * @param pszArgs Argument string. Optional and specific to the handler.
+ */
+typedef DECLCALLBACKTYPE(void, FNDBGFHANDLERDRV,(PPDMDRVINS pDrvIns, PCDBGFINFOHLP pHlp, const char *pszArgs));
+/** Pointer to a FNDBGFHANDLERDRV function. */
+typedef FNDBGFHANDLERDRV *PFNDBGFHANDLERDRV;
+
+/**
+ * Info handler, internal version.
+ *
+ * @param pVM The cross context VM structure.
+ * @param pHlp Callback functions for doing output.
+ * @param pszArgs Argument string. Optional and specific to the handler.
+ */
+typedef DECLCALLBACKTYPE(void, FNDBGFHANDLERINT,(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs));
+/** Pointer to a FNDBGFHANDLERINT function. */
+typedef FNDBGFHANDLERINT *PFNDBGFHANDLERINT;
+
+/**
+ * Info handler, external version.
+ *
+ * @param pvUser User argument.
+ * @param pHlp Callback functions for doing output.
+ * @param pszArgs Argument string. Optional and specific to the handler.
+ */
+typedef DECLCALLBACKTYPE(void, FNDBGFHANDLEREXT,(void *pvUser, PCDBGFINFOHLP pHlp, const char *pszArgs));
+/** Pointer to a FNDBGFHANDLEREXT function. */
+typedef FNDBGFHANDLEREXT *PFNDBGFHANDLEREXT;
+
+/**
+ * Info handler, device version with argv.
+ *
+ * @param pDevIns The device instance which registered the info.
+ * @param pHlp Callback functions for doing output.
+ * @param cArgs Number of arguments.
+ * @param papszArgs Argument vector.
+ */
+typedef DECLCALLBACKTYPE(void, FNDBGFINFOARGVDEV,(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, int cArgs, char **papszArgs));
+/** Pointer to a FNDBGFINFOARGVDEV function. */
+typedef FNDBGFINFOARGVDEV *PFNDBGFINFOARGVDEV;
+
+/**
+ * Info handler, USB device version with argv.
+ *
+ * @param pUsbIns The USB device instance which registered the info.
+ * @param pHlp Callback functions for doing output.
+ * @param cArgs Number of arguments.
+ * @param papszArgs Argument vector.
+ */
+typedef DECLCALLBACKTYPE(void, FNDBGFINFOARGVUSB,(PPDMUSBINS pUsbIns, PCDBGFINFOHLP pHlp, int cArgs, char **papszArgs));
+/** Pointer to a FNDBGFINFOARGVUSB function. */
+typedef FNDBGFINFOARGVUSB *PFNDBGFINFOARGVUSB;
+
+/**
+ * Info handler, driver version with argv.
+ *
+ * @param pDrvIns The driver instance which registered the info.
+ * @param pHlp Callback functions for doing output.
+ * @param cArgs Number of arguments.
+ * @param papszArgs Argument vector.
+ */
+typedef DECLCALLBACKTYPE(void, FNDBGFINFOARGVDRV,(PPDMDRVINS pDrvIns, PCDBGFINFOHLP pHlp, int cArgs, char **papszArgs));
+/** Pointer to a FNDBGFINFOARGVDRV function. */
+typedef FNDBGFINFOARGVDRV *PFNDBGFINFOARGVDRV;
+
+/**
+ * Info handler, internal version with argv.
+ *
+ * @param pVM The cross context VM structure.
+ * @param pHlp Callback functions for doing output.
+ * @param cArgs Number of arguments.
+ * @param papszArgs Argument vector.
+ */
+typedef DECLCALLBACKTYPE(void, FNDBGFINFOARGVINT,(PVM pVM, PCDBGFINFOHLP pHlp, int cArgs, char **papszArgs));
+/** Pointer to a FNDBGFINFOARGVINT function. */
+typedef FNDBGFINFOARGVINT *PFNDBGFINFOARGVINT;
+
+/**
+ * Info handler, external version with argv.
+ *
+ * @param pvUser User argument.
+ * @param pHlp Callback functions for doing output.
+ * @param cArgs Number of arguments.
+ * @param papszArgs Argument vector.
+ */
+typedef DECLCALLBACKTYPE(void, FNDBGFINFOARGVEXT,(void *pvUser, PCDBGFINFOHLP pHlp, int cArgs, char **papszArgs));
+/** Pointer to a FNDBGFINFOARGVEXT function. */
+typedef FNDBGFINFOARGVEXT *PFNDBGFINFOARGVEXT;
+
+
+/** @name Flags for the info registration functions.
+ * @{ */
+/** The handler must run on the EMT. */
+#define DBGFINFO_FLAGS_RUN_ON_EMT RT_BIT(0)
+/** Call on all EMTs when a specific isn't specified. */
+#define DBGFINFO_FLAGS_ALL_EMTS RT_BIT(1)
+/** @} */
+
+VMMR3_INT_DECL(int) DBGFR3InfoRegisterDevice(PVM pVM, const char *pszName, const char *pszDesc, PFNDBGFHANDLERDEV pfnHandler, PPDMDEVINS pDevIns);
+VMMR3_INT_DECL(int) DBGFR3InfoRegisterDriver(PVM pVM, const char *pszName, const char *pszDesc, PFNDBGFHANDLERDRV pfnHandler, PPDMDRVINS pDrvIns);
+VMMR3_INT_DECL(int) DBGFR3InfoRegisterInternal(PVM pVM, const char *pszName, const char *pszDesc, PFNDBGFHANDLERINT pfnHandler);
+VMMR3_INT_DECL(int) DBGFR3InfoRegisterInternalEx(PVM pVM, const char *pszName, const char *pszDesc, PFNDBGFHANDLERINT pfnHandler, uint32_t fFlags);
+VMMR3DECL(int) DBGFR3InfoRegisterExternal(PUVM pUVM, const char *pszName, const char *pszDesc, PFNDBGFHANDLEREXT pfnHandler, void *pvUser);
+
+VMMR3_INT_DECL(int) DBGFR3InfoRegisterDeviceArgv(PVM pVM, const char *pszName, const char *pszDesc, PFNDBGFINFOARGVDEV pfnHandler, PPDMDEVINS pDevIns);
+VMMR3_INT_DECL(int) DBGFR3InfoRegisterDriverArgv(PVM pVM, const char *pszName, const char *pszDesc, PFNDBGFINFOARGVDRV pfnHandler, PPDMDRVINS pDrvIns);
+VMMR3_INT_DECL(int) DBGFR3InfoRegisterUsbArgv(PVM pVM, const char *pszName, const char *pszDesc, PFNDBGFINFOARGVUSB pfnHandler, PPDMUSBINS pUsbIns);
+VMMR3_INT_DECL(int) DBGFR3InfoRegisterInternalArgv(PVM pVM, const char *pszName, const char *pszDesc, PFNDBGFINFOARGVINT pfnHandler, uint32_t fFlags);
+VMMR3DECL(int) DBGFR3InfoRegisterExternalArgv(PUVM pUVM, const char *pszName, const char *pszDesc, PFNDBGFINFOARGVEXT pfnHandler, void *pvUser);
+
+VMMR3_INT_DECL(int) DBGFR3InfoDeregisterDevice(PVM pVM, PPDMDEVINS pDevIns, const char *pszName);
+VMMR3_INT_DECL(int) DBGFR3InfoDeregisterDriver(PVM pVM, PPDMDRVINS pDrvIns, const char *pszName);
+VMMR3_INT_DECL(int) DBGFR3InfoDeregisterUsb(PVM pVM, PPDMUSBINS pDrvIns, const char *pszName);
+VMMR3_INT_DECL(int) DBGFR3InfoDeregisterInternal(PVM pVM, const char *pszName);
+VMMR3DECL(int) DBGFR3InfoDeregisterExternal(PUVM pUVM, const char *pszName);
+
+VMMR3DECL(int) DBGFR3Info(PUVM pUVM, const char *pszName, const char *pszArgs, PCDBGFINFOHLP pHlp);
+VMMR3DECL(int) DBGFR3InfoEx(PUVM pUVM, VMCPUID idCpu, const char *pszName, const char *pszArgs, PCDBGFINFOHLP pHlp);
+VMMR3DECL(int) DBGFR3InfoLogRel(PUVM pUVM, const char *pszName, const char *pszArgs);
+VMMR3DECL(int) DBGFR3InfoStdErr(PUVM pUVM, const char *pszName, const char *pszArgs);
+VMMR3_INT_DECL(int) DBGFR3InfoMulti(PVM pVM, const char *pszIncludePat, const char *pszExcludePat,
+ const char *pszSepFmt, PCDBGFINFOHLP pHlp);
+
+/** @def DBGFR3_INFO_LOG
+ * Display a piece of info writing to the log if enabled.
+ *
+ * This is for execution on EMTs and will only show the items on the calling
+ * EMT. This is to avoid deadlocking against other CPUs if a rendezvous is
+ * initiated in parallel to this call. (Besides, nobody really wants or need
+ * info for the other EMTs when using this macro.)
+ *
+ * @param a_pVM The shared VM handle.
+ * @param a_pVCpu The cross context per CPU structure of the calling EMT.
+ * @param a_pszName The identifier of the info to display.
+ * @param a_pszArgs Arguments to the info handler.
+ */
+#ifdef LOG_ENABLED
+# define DBGFR3_INFO_LOG(a_pVM, a_pVCpu, a_pszName, a_pszArgs) \
+ do { \
+ if (LogIsEnabled()) \
+ DBGFR3InfoEx((a_pVM)->pUVM, (a_pVCpu)->idCpu, a_pszName, a_pszArgs, NULL); \
+ } while (0)
+#else
+# define DBGFR3_INFO_LOG(a_pVM, a_pVCpu, a_pszName, a_pszArgs) do { } while (0)
+#endif
+
+/** @def DBGFR3_INFO_LOG_SAFE
+ * Display a piece of info (rendezvous safe) writing to the log if enabled.
+ *
+ * @param a_pVM The shared VM handle.
+ * @param a_pszName The identifier of the info to display.
+ * @param a_pszArgs Arguments to the info handler.
+ *
+ * @remarks Use DBGFR3_INFO_LOG where ever possible!
+ */
+#ifdef LOG_ENABLED
+# define DBGFR3_INFO_LOG_SAFE(a_pVM, a_pszName, a_pszArgs) \
+ do { \
+ if (LogIsEnabled()) \
+ DBGFR3Info((a_pVM)->pUVM, a_pszName, a_pszArgs, NULL); \
+ } while (0)
+#else
+# define DBGFR3_INFO_LOG_SAFE(a_pVM, a_pszName, a_pszArgs) do { } while (0)
+#endif
+
+/**
+ * Enumeration callback for use with DBGFR3InfoEnum.
+ *
+ * @returns VBox status code.
+ * A status code indicating failure will end the enumeration
+ * and DBGFR3InfoEnum will return with that status code.
+ * @param pUVM The user mode VM handle.
+ * @param pszName Info identifier name.
+ * @param pszDesc The description.
+ * @param pvUser User parameter.
+ */
+typedef DECLCALLBACKTYPE(int, FNDBGFINFOENUM,(PUVM pUVM, const char *pszName, const char *pszDesc, void *pvUser));
+/** Pointer to a FNDBGFINFOENUM function. */
+typedef FNDBGFINFOENUM *PFNDBGFINFOENUM;
+
+VMMR3DECL(int) DBGFR3InfoEnum(PUVM pUVM, PFNDBGFINFOENUM pfnCallback, void *pvUser);
+VMMR3DECL(PCDBGFINFOHLP) DBGFR3InfoLogHlp(void);
+VMMR3DECL(PCDBGFINFOHLP) DBGFR3InfoLogRelHlp(void);
+VMMR3DECL(void) DBGFR3InfoGenericGetOptError(PCDBGFINFOHLP pHlp, int rc, union RTGETOPTUNION *pValueUnion,
+ struct RTGETOPTSTATE *pState);
+
+#endif /* IN_RING3 */
+
+
+#ifdef IN_RING3 /* The log contrl API only works in ring-3. */
+VMMR3DECL(int) DBGFR3LogModifyGroups(PUVM pUVM, const char *pszGroupSettings);
+VMMR3DECL(int) DBGFR3LogModifyFlags(PUVM pUVM, const char *pszFlagSettings);
+VMMR3DECL(int) DBGFR3LogModifyDestinations(PUVM pUVM, const char *pszDestSettings);
+#endif /* IN_RING3 */
+
+#ifdef IN_RING3 /* The debug information management APIs only works in ring-3. */
+
+/** Max length (including '\\0') of a symbol name. */
+#define DBGF_SYMBOL_NAME_LENGTH 512
+
+/**
+ * Debug symbol.
+ */
+typedef struct DBGFSYMBOL
+{
+ /** Symbol value (address). */
+ RTGCUINTPTR Value;
+ /** Symbol size. */
+ uint32_t cb;
+ /** Symbol Flags. (reserved). */
+ uint32_t fFlags;
+ /** Symbol name. */
+ char szName[DBGF_SYMBOL_NAME_LENGTH];
+} DBGFSYMBOL;
+/** Pointer to debug symbol. */
+typedef DBGFSYMBOL *PDBGFSYMBOL;
+/** Pointer to const debug symbol. */
+typedef const DBGFSYMBOL *PCDBGFSYMBOL;
+
+/**
+ * Debug line number information.
+ */
+typedef struct DBGFLINE
+{
+ /** Address. */
+ RTGCUINTPTR Address;
+ /** Line number. */
+ uint32_t uLineNo;
+ /** Filename. */
+ char szFilename[260];
+} DBGFLINE;
+/** Pointer to debug line number. */
+typedef DBGFLINE *PDBGFLINE;
+/** Pointer to const debug line number. */
+typedef const DBGFLINE *PCDBGFLINE;
+
+/** @name Address spaces aliases.
+ * @{ */
+/** The guest global address space. */
+#define DBGF_AS_GLOBAL ((RTDBGAS)-1)
+/** The guest kernel address space.
+ * This is usually resolves to the same as DBGF_AS_GLOBAL. */
+#define DBGF_AS_KERNEL ((RTDBGAS)-2)
+/** The physical address space. */
+#define DBGF_AS_PHYS ((RTDBGAS)-3)
+/** Raw-mode context. */
+#define DBGF_AS_RC ((RTDBGAS)-4)
+/** Ring-0 context. */
+#define DBGF_AS_R0 ((RTDBGAS)-5)
+/** Raw-mode context and then global guest context.
+ * When used for looking up information, it works as if the call was first made
+ * with DBGF_AS_RC and then on failure with DBGF_AS_GLOBAL. When called for
+ * making address space changes, it works as if DBGF_AS_RC was used. */
+#define DBGF_AS_RC_AND_GC_GLOBAL ((RTDBGAS)-6)
+
+/** The first special one. */
+#define DBGF_AS_FIRST DBGF_AS_RC_AND_GC_GLOBAL
+/** The last special one. */
+#define DBGF_AS_LAST DBGF_AS_GLOBAL
+#endif
+/** The number of special address space handles. */
+#define DBGF_AS_COUNT (6U)
+#ifdef IN_RING3
+/** Converts an alias handle to an array index. */
+#define DBGF_AS_ALIAS_2_INDEX(hAlias) \
+ ( (uintptr_t)(hAlias) - (uintptr_t)DBGF_AS_FIRST )
+/** Predicat macro that check if the specified handle is an alias. */
+#define DBGF_AS_IS_ALIAS(hAlias) \
+ ( DBGF_AS_ALIAS_2_INDEX(hAlias) < DBGF_AS_COUNT )
+/** Predicat macro that check if the specified alias is a fixed one or not. */
+#define DBGF_AS_IS_FIXED_ALIAS(hAlias) \
+ ( DBGF_AS_ALIAS_2_INDEX(hAlias) < (uintptr_t)DBGF_AS_PHYS - (uintptr_t)DBGF_AS_FIRST + 1U )
+
+/** @} */
+
+VMMR3DECL(RTDBGCFG) DBGFR3AsGetConfig(PUVM pUVM);
+
+VMMR3DECL(int) DBGFR3AsAdd(PUVM pUVM, RTDBGAS hDbgAs, RTPROCESS ProcId);
+VMMR3DECL(int) DBGFR3AsDelete(PUVM pUVM, RTDBGAS hDbgAs);
+VMMR3DECL(int) DBGFR3AsSetAlias(PUVM pUVM, RTDBGAS hAlias, RTDBGAS hAliasFor);
+VMMR3DECL(RTDBGAS) DBGFR3AsResolve(PUVM pUVM, RTDBGAS hAlias);
+VMMR3DECL(RTDBGAS) DBGFR3AsResolveAndRetain(PUVM pUVM, RTDBGAS hAlias);
+VMMR3DECL(RTDBGAS) DBGFR3AsQueryByName(PUVM pUVM, const char *pszName);
+VMMR3DECL(RTDBGAS) DBGFR3AsQueryByPid(PUVM pUVM, RTPROCESS ProcId);
+
+VMMR3DECL(int) DBGFR3AsLoadImage(PUVM pUVM, RTDBGAS hDbgAs, const char *pszFilename, const char *pszModName,
+ RTLDRARCH enmArch, PCDBGFADDRESS pModAddress, RTDBGSEGIDX iModSeg, uint32_t fFlags);
+VMMR3DECL(int) DBGFR3AsLoadMap(PUVM pUVM, RTDBGAS hDbgAs, const char *pszFilename, const char *pszModName, PCDBGFADDRESS pModAddress, RTDBGSEGIDX iModSeg, RTGCUINTPTR uSubtrahend, uint32_t fFlags);
+VMMR3DECL(int) DBGFR3AsLinkModule(PUVM pUVM, RTDBGAS hDbgAs, RTDBGMOD hMod, PCDBGFADDRESS pModAddress, RTDBGSEGIDX iModSeg, uint32_t fFlags);
+VMMR3DECL(int) DBGFR3AsUnlinkModuleByName(PUVM pUVM, RTDBGAS hDbgAs, const char *pszModName);
+
+VMMR3DECL(int) DBGFR3AsSymbolByAddr(PUVM pUVM, RTDBGAS hDbgAs, PCDBGFADDRESS pAddress, uint32_t fFlags,
+ PRTGCINTPTR poffDisp, PRTDBGSYMBOL pSymbol, PRTDBGMOD phMod);
+VMMR3DECL(PRTDBGSYMBOL) DBGFR3AsSymbolByAddrA(PUVM pUVM, RTDBGAS hDbgAs, PCDBGFADDRESS pAddress, uint32_t Flags,
+ PRTGCINTPTR poffDisp, PRTDBGMOD phMod);
+VMMR3DECL(int) DBGFR3AsSymbolByName(PUVM pUVM, RTDBGAS hDbgAs, const char *pszSymbol, PRTDBGSYMBOL pSymbol, PRTDBGMOD phMod);
+
+VMMR3DECL(int) DBGFR3AsLineByAddr(PUVM pUVM, RTDBGAS hDbgAs, PCDBGFADDRESS pAddress,
+ PRTGCINTPTR poffDisp, PRTDBGLINE pLine, PRTDBGMOD phMod);
+VMMR3DECL(PRTDBGLINE) DBGFR3AsLineByAddrA(PUVM pUVM, RTDBGAS hDbgAs, PCDBGFADDRESS pAddress,
+ PRTGCINTPTR poffDisp, PRTDBGMOD phMod);
+
+/** @name DBGFMOD_PE_F_XXX - flags for
+ * @{ */
+/** NT 3.1 images were a little different, so make allowances for that. */
+#define DBGFMODINMEM_F_PE_NT31 RT_BIT_32(0)
+/** No container fallback. */
+#define DBGFMODINMEM_F_NO_CONTAINER_FALLBACK RT_BIT_32(1)
+/** No in-memory reader fallback. */
+#define DBGFMODINMEM_F_NO_READER_FALLBACK RT_BIT_32(2)
+/** Valid flags. */
+#define DBGFMODINMEM_F_VALID_MASK UINT32_C(0x00000007)
+/** @} */
+VMMR3DECL(int) DBGFR3ModInMem(PUVM pUVM, PCDBGFADDRESS pImageAddr, uint32_t fFlags, const char *pszName,
+ const char *pszFilename, RTLDRARCH enmArch, uint32_t cbImage,
+ PRTDBGMOD phDbgMod, PRTERRINFO pErrInfo);
+
+#endif /* IN_RING3 */
+
+#ifdef IN_RING3 /* The stack API only works in ring-3. */
+
+/** Pointer to stack frame info. */
+typedef struct DBGFSTACKFRAME *PDBGFSTACKFRAME;
+/** Pointer to const stack frame info. */
+typedef struct DBGFSTACKFRAME const *PCDBGFSTACKFRAME;
+/**
+ * Info about a stack frame.
+ */
+typedef struct DBGFSTACKFRAME
+{
+ /** Frame number. */
+ uint32_t iFrame;
+ /** Frame flags (DBGFSTACKFRAME_FLAGS_XXX). */
+ uint32_t fFlags;
+ /** The stack address of the frame.
+ * The off member is [e|r]sp and the Sel member is ss. */
+ DBGFADDRESS AddrStack;
+ /** The program counter (PC) address of the frame.
+ * The off member is [e|r]ip and the Sel member is cs. */
+ DBGFADDRESS AddrPC;
+ /** Pointer to the symbol nearest the program counter (PC). NULL if not found. */
+ PRTDBGSYMBOL pSymPC;
+ /** Pointer to the linenumber nearest the program counter (PC). NULL if not found. */
+ PRTDBGLINE pLinePC;
+ /** The frame address.
+ * The off member is [e|r]bp and the Sel member is ss. */
+ DBGFADDRESS AddrFrame;
+ /** The way this frame returns to the next one. */
+ RTDBGRETURNTYPE enmReturnType;
+
+ /** The way the next frame returns.
+ * Only valid when DBGFSTACKFRAME_FLAGS_UNWIND_INFO_RET is set. */
+ RTDBGRETURNTYPE enmReturnFrameReturnType;
+ /** The return frame address.
+ * The off member is [e|r]bp and the Sel member is ss. */
+ DBGFADDRESS AddrReturnFrame;
+ /** The return stack address.
+ * The off member is [e|r]sp and the Sel member is ss. */
+ DBGFADDRESS AddrReturnStack;
+
+ /** The program counter (PC) address which the frame returns to.
+ * The off member is [e|r]ip and the Sel member is cs. */
+ DBGFADDRESS AddrReturnPC;
+ /** Pointer to the symbol nearest the return PC. NULL if not found. */
+ PRTDBGSYMBOL pSymReturnPC;
+ /** Pointer to the linenumber nearest the return PC. NULL if not found. */
+ PRTDBGLINE pLineReturnPC;
+
+ /** 32-bytes of stack arguments. */
+ union
+ {
+ /** 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];
+ } Args;
+
+ /** Number of registers values we can be sure about.
+ * @note This is generally zero in the first frame. */
+ uint32_t cSureRegs;
+ /** Registers we can be sure about (length given by cSureRegs). */
+ struct DBGFREGVALEX *paSureRegs;
+
+ /** Pointer to the next frame.
+ * Might not be used in some cases, so consider it internal. */
+ PCDBGFSTACKFRAME pNextInternal;
+ /** Pointer to the first frame.
+ * Might not be used in some cases, so consider it internal. */
+ PCDBGFSTACKFRAME pFirstInternal;
+} DBGFSTACKFRAME;
+
+/** @name DBGFSTACKFRAME_FLAGS_XXX - DBGFSTACKFRAME Flags.
+ * @{ */
+/** This is the last stack frame we can read.
+ * This flag is not set if the walk stop because of max dept or recursion. */
+# define DBGFSTACKFRAME_FLAGS_LAST RT_BIT(1)
+/** This is the last record because we detected a loop. */
+# define DBGFSTACKFRAME_FLAGS_LOOP RT_BIT(2)
+/** This is the last record because we reached the maximum depth. */
+# define DBGFSTACKFRAME_FLAGS_MAX_DEPTH RT_BIT(3)
+/** 16-bit frame. */
+# define DBGFSTACKFRAME_FLAGS_16BIT RT_BIT(4)
+/** 32-bit frame. */
+# define DBGFSTACKFRAME_FLAGS_32BIT RT_BIT(5)
+/** 64-bit frame. */
+# define DBGFSTACKFRAME_FLAGS_64BIT RT_BIT(6)
+/** Real mode or V86 frame. */
+# define DBGFSTACKFRAME_FLAGS_REAL_V86 RT_BIT(7)
+/** Is a trap frame (NT term). */
+# define DBGFSTACKFRAME_FLAGS_TRAP_FRAME RT_BIT(8)
+
+/** Used Odd/even heuristics for far/near return. */
+# define DBGFSTACKFRAME_FLAGS_USED_ODD_EVEN RT_BIT(29)
+/** Set if we used unwind info to construct the frame. (Kind of internal.) */
+# define DBGFSTACKFRAME_FLAGS_USED_UNWIND_INFO RT_BIT(30)
+/** Internal: Unwind info used for the return frame. */
+# define DBGFSTACKFRAME_FLAGS_UNWIND_INFO_RET RT_BIT(31)
+/** @} */
+
+/** @name DBGFCODETYPE
+ * @{ */
+typedef enum DBGFCODETYPE
+{
+ /** The usual invalid 0 value. */
+ DBGFCODETYPE_INVALID = 0,
+ /** Stack walk for guest code. */
+ DBGFCODETYPE_GUEST,
+ /** Stack walk for hypervisor code. */
+ DBGFCODETYPE_HYPER,
+ /** Stack walk for ring 0 code. */
+ DBGFCODETYPE_RING0,
+ /** The usual 32-bit blowup. */
+ DBGFCODETYPE_32BIT_HACK = 0x7fffffff
+} DBGFCODETYPE;
+/** @} */
+
+VMMR3DECL(int) DBGFR3StackWalkBegin(PUVM pUVM, VMCPUID idCpu, DBGFCODETYPE enmCodeType,
+ PCDBGFSTACKFRAME *ppFirstFrame);
+VMMR3DECL(int) DBGFR3StackWalkBeginEx(PUVM pUVM, VMCPUID idCpu, DBGFCODETYPE enmCodeType, PCDBGFADDRESS pAddrFrame,
+ PCDBGFADDRESS pAddrStack,PCDBGFADDRESS pAddrPC,
+ RTDBGRETURNTYPE enmReturnType, PCDBGFSTACKFRAME *ppFirstFrame);
+VMMR3DECL(PCDBGFSTACKFRAME) DBGFR3StackWalkNext(PCDBGFSTACKFRAME pCurrent);
+VMMR3DECL(void) DBGFR3StackWalkEnd(PCDBGFSTACKFRAME pFirstFrame);
+
+#endif /* IN_RING3 */
+
+
+#ifdef IN_RING3 /* The disassembly API only works in ring-3. */
+
+/** @name Flags to pass to DBGFR3DisasInstrEx().
+ * @{ */
+/** Disassemble the current guest instruction, with annotations. */
+#define DBGF_DISAS_FLAGS_CURRENT_GUEST RT_BIT(0)
+/** No annotations for current context. */
+#define DBGF_DISAS_FLAGS_NO_ANNOTATION RT_BIT(2)
+/** No symbol lookup. */
+#define DBGF_DISAS_FLAGS_NO_SYMBOLS RT_BIT(3)
+/** No instruction bytes. */
+#define DBGF_DISAS_FLAGS_NO_BYTES RT_BIT(4)
+/** No address in the output. */
+#define DBGF_DISAS_FLAGS_NO_ADDRESS RT_BIT(5)
+/** Disassemble original unpatched bytes (PATM). */
+#define DBGF_DISAS_FLAGS_UNPATCHED_BYTES RT_BIT(7)
+/** Annotate patched instructions. */
+#define DBGF_DISAS_FLAGS_ANNOTATE_PATCHED RT_BIT(8)
+/** Disassemble in the default mode of the specific context. */
+#define DBGF_DISAS_FLAGS_DEFAULT_MODE UINT32_C(0x00000000)
+/** Disassemble in 16-bit mode. */
+#define DBGF_DISAS_FLAGS_16BIT_MODE UINT32_C(0x10000000)
+/** Disassemble in 16-bit mode with real mode address translation. */
+#define DBGF_DISAS_FLAGS_16BIT_REAL_MODE UINT32_C(0x20000000)
+/** Disassemble in 32-bit mode. */
+#define DBGF_DISAS_FLAGS_32BIT_MODE UINT32_C(0x30000000)
+/** Disassemble in 64-bit mode. */
+#define DBGF_DISAS_FLAGS_64BIT_MODE UINT32_C(0x40000000)
+/** The disassembly mode mask. */
+#define DBGF_DISAS_FLAGS_MODE_MASK UINT32_C(0x70000000)
+/** Mask containing the valid flags. */
+#define DBGF_DISAS_FLAGS_VALID_MASK UINT32_C(0x700001ff)
+/** @} */
+
+/** Special flat selector. */
+#define DBGF_SEL_FLAT 1
+
+VMMR3DECL(int) DBGFR3DisasInstrEx(PUVM pUVM, VMCPUID idCpu, RTSEL Sel, RTGCPTR GCPtr, uint32_t fFlags,
+ char *pszOutput, uint32_t cbOutput, uint32_t *pcbInstr);
+VMMR3_INT_DECL(int) DBGFR3DisasInstrCurrent(PVMCPU pVCpu, char *pszOutput, uint32_t cbOutput);
+VMMR3DECL(int) DBGFR3DisasInstrCurrentLogInternal(PVMCPU pVCpu, const char *pszPrefix);
+
+/** @def DBGFR3_DISAS_INSTR_CUR_LOG
+ * Disassembles the current guest context instruction and writes it to the log.
+ * All registers and data will be displayed. Addresses will be attempted resolved to symbols.
+ */
+#ifdef LOG_ENABLED
+# define DBGFR3_DISAS_INSTR_CUR_LOG(pVCpu, pszPrefix) \
+ do { \
+ if (LogIsEnabled()) \
+ DBGFR3DisasInstrCurrentLogInternal(pVCpu, pszPrefix); \
+ } while (0)
+#else
+# define DBGFR3_DISAS_INSTR_CUR_LOG(pVCpu, pszPrefix) do { } while (0)
+#endif
+
+VMMR3DECL(int) DBGFR3DisasInstrLogInternal(PVMCPU pVCpu, RTSEL Sel, RTGCPTR GCPtr, const char *pszPrefix);
+
+/** @def DBGFR3_DISAS_INSTR_LOG
+ * Disassembles the specified guest context instruction and writes it to the log.
+ * Addresses will be attempted resolved to symbols.
+ * @thread Any EMT.
+ */
+# ifdef LOG_ENABLED
+# define DBGFR3_DISAS_INSTR_LOG(pVCpu, Sel, GCPtr, pszPrefix) \
+ do { \
+ if (LogIsEnabled()) \
+ DBGFR3DisasInstrLogInternal(pVCpu, Sel, GCPtr, pszPrefix); \
+ } while (0)
+# else
+# define DBGFR3_DISAS_INSTR_LOG(pVCpu, Sel, GCPtr, pszPrefix) do { } while (0)
+# endif
+#endif
+
+
+#ifdef IN_RING3
+VMMR3DECL(int) DBGFR3MemScan(PUVM pUVM, VMCPUID idCpu, PCDBGFADDRESS pAddress, RTGCUINTPTR cbRange, RTGCUINTPTR uAlign,
+ const void *pvNeedle, size_t cbNeedle, PDBGFADDRESS pHitAddress);
+VMMR3DECL(int) DBGFR3MemRead(PUVM pUVM, VMCPUID idCpu, PCDBGFADDRESS pAddress, void *pvBuf, size_t cbRead);
+VMMR3DECL(int) DBGFR3MemReadString(PUVM pUVM, VMCPUID idCpu, PCDBGFADDRESS pAddress, char *pszBuf, size_t cbBuf);
+VMMR3DECL(int) DBGFR3MemWrite(PUVM pUVM, VMCPUID idCpu, PCDBGFADDRESS pAddress, void const *pvBuf, size_t cbRead);
+#endif
+
+
+/** @name Flags for DBGFR3PagingDumpEx, PGMR3DumpHierarchyHCEx and
+ * PGMR3DumpHierarchyGCEx
+ * @{ */
+/** The CR3 from the current CPU state. */
+#define DBGFPGDMP_FLAGS_CURRENT_CR3 RT_BIT_32(0)
+/** The current CPU paging mode (PSE, PAE, LM, EPT, NX). */
+#define DBGFPGDMP_FLAGS_CURRENT_MODE RT_BIT_32(1)
+/** Whether PSE is enabled (!DBGFPGDMP_FLAGS_CURRENT_STATE).
+ * Same value as X86_CR4_PSE. */
+#define DBGFPGDMP_FLAGS_PSE RT_BIT_32(4) /* */
+/** Whether PAE is enabled (!DBGFPGDMP_FLAGS_CURRENT_STATE).
+ * Same value as X86_CR4_PAE. */
+#define DBGFPGDMP_FLAGS_PAE RT_BIT_32(5) /* */
+/** Whether LME is enabled (!DBGFPGDMP_FLAGS_CURRENT_STATE).
+ * Same value as MSR_K6_EFER_LME. */
+#define DBGFPGDMP_FLAGS_LME RT_BIT_32(8)
+/** Whether nested paging is enabled (!DBGFPGDMP_FLAGS_CURRENT_STATE). */
+#define DBGFPGDMP_FLAGS_NP RT_BIT_32(9)
+/** Whether extended nested page tables are enabled
+ * (!DBGFPGDMP_FLAGS_CURRENT_STATE). */
+#define DBGFPGDMP_FLAGS_EPT RT_BIT_32(10)
+/** Whether no-execution is enabled (!DBGFPGDMP_FLAGS_CURRENT_STATE).
+ * Same value as MSR_K6_EFER_NXE. */
+#define DBGFPGDMP_FLAGS_NXE RT_BIT_32(11)
+/** Whether to print the CR3. */
+#define DBGFPGDMP_FLAGS_PRINT_CR3 RT_BIT_32(27)
+/** Whether to print the header. */
+#define DBGFPGDMP_FLAGS_HEADER RT_BIT_32(28)
+/** Whether to dump additional page information. */
+#define DBGFPGDMP_FLAGS_PAGE_INFO RT_BIT_32(29)
+/** Dump the shadow tables if set.
+ * Cannot be used together with DBGFPGDMP_FLAGS_GUEST. */
+#define DBGFPGDMP_FLAGS_SHADOW RT_BIT_32(30)
+/** Dump the guest tables if set.
+ * Cannot be used together with DBGFPGDMP_FLAGS_SHADOW. */
+#define DBGFPGDMP_FLAGS_GUEST RT_BIT_32(31)
+/** Mask of valid bits. */
+#define DBGFPGDMP_FLAGS_VALID_MASK UINT32_C(0xf8000f33)
+/** The mask of bits controlling the paging mode. */
+#define DBGFPGDMP_FLAGS_MODE_MASK UINT32_C(0x00000f32)
+/** @} */
+VMMDECL(int) DBGFR3PagingDumpEx(PUVM pUVM, VMCPUID idCpu, uint32_t fFlags, uint64_t cr3, uint64_t u64FirstAddr,
+ uint64_t u64LastAddr, uint32_t cMaxDepth, PCDBGFINFOHLP pHlp);
+
+
+/** @name DBGFR3SelQueryInfo flags.
+ * @{ */
+/** Get the info from the guest descriptor table.
+ * @note This is more or less a given now when raw-mode was kicked out. */
+#define DBGFSELQI_FLAGS_DT_GUEST UINT32_C(0)
+/** If currently executing in in 64-bit mode, blow up data selectors. */
+#define DBGFSELQI_FLAGS_DT_ADJ_64BIT_MODE UINT32_C(2)
+/** @} */
+VMMR3DECL(int) DBGFR3SelQueryInfo(PUVM pUVM, VMCPUID idCpu, RTSEL Sel, uint32_t fFlags, PDBGFSELINFO pSelInfo);
+
+
+/**
+ * Register identifiers.
+ */
+typedef enum DBGFREG
+{
+ /* General purpose registers: */
+ DBGFREG_AL = 0,
+ DBGFREG_AX = DBGFREG_AL,
+ DBGFREG_EAX = DBGFREG_AL,
+ DBGFREG_RAX = DBGFREG_AL,
+
+ DBGFREG_CL,
+ DBGFREG_CX = DBGFREG_CL,
+ DBGFREG_ECX = DBGFREG_CL,
+ DBGFREG_RCX = DBGFREG_CL,
+
+ DBGFREG_DL,
+ DBGFREG_DX = DBGFREG_DL,
+ DBGFREG_EDX = DBGFREG_DL,
+ DBGFREG_RDX = DBGFREG_DL,
+
+ DBGFREG_BL,
+ DBGFREG_BX = DBGFREG_BL,
+ DBGFREG_EBX = DBGFREG_BL,
+ DBGFREG_RBX = DBGFREG_BL,
+
+ DBGFREG_SPL,
+ DBGFREG_SP = DBGFREG_SPL,
+ DBGFREG_ESP = DBGFREG_SPL,
+ DBGFREG_RSP = DBGFREG_SPL,
+
+ DBGFREG_BPL,
+ DBGFREG_BP = DBGFREG_BPL,
+ DBGFREG_EBP = DBGFREG_BPL,
+ DBGFREG_RBP = DBGFREG_BPL,
+
+ DBGFREG_SIL,
+ DBGFREG_SI = DBGFREG_SIL,
+ DBGFREG_ESI = DBGFREG_SIL,
+ DBGFREG_RSI = DBGFREG_SIL,
+
+ DBGFREG_DIL,
+ DBGFREG_DI = DBGFREG_DIL,
+ DBGFREG_EDI = DBGFREG_DIL,
+ DBGFREG_RDI = DBGFREG_DIL,
+
+ DBGFREG_R8,
+ DBGFREG_R8B = DBGFREG_R8,
+ DBGFREG_R8W = DBGFREG_R8,
+ DBGFREG_R8D = DBGFREG_R8,
+
+ DBGFREG_R9,
+ DBGFREG_R9B = DBGFREG_R9,
+ DBGFREG_R9W = DBGFREG_R9,
+ DBGFREG_R9D = DBGFREG_R9,
+
+ DBGFREG_R10,
+ DBGFREG_R10B = DBGFREG_R10,
+ DBGFREG_R10W = DBGFREG_R10,
+ DBGFREG_R10D = DBGFREG_R10,
+
+ DBGFREG_R11,
+ DBGFREG_R11B = DBGFREG_R11,
+ DBGFREG_R11W = DBGFREG_R11,
+ DBGFREG_R11D = DBGFREG_R11,
+
+ DBGFREG_R12,
+ DBGFREG_R12B = DBGFREG_R12,
+ DBGFREG_R12W = DBGFREG_R12,
+ DBGFREG_R12D = DBGFREG_R12,
+
+ DBGFREG_R13,
+ DBGFREG_R13B = DBGFREG_R13,
+ DBGFREG_R13W = DBGFREG_R13,
+ DBGFREG_R13D = DBGFREG_R13,
+
+ DBGFREG_R14,
+ DBGFREG_R14B = DBGFREG_R14,
+ DBGFREG_R14W = DBGFREG_R14,
+ DBGFREG_R14D = DBGFREG_R14,
+
+ DBGFREG_R15,
+ DBGFREG_R15B = DBGFREG_R15,
+ DBGFREG_R15W = DBGFREG_R15,
+ DBGFREG_R15D = DBGFREG_R15,
+
+ /* Segments and other special registers: */
+ DBGFREG_CS,
+ DBGFREG_CS_ATTR,
+ DBGFREG_CS_BASE,
+ DBGFREG_CS_LIMIT,
+
+ DBGFREG_DS,
+ DBGFREG_DS_ATTR,
+ DBGFREG_DS_BASE,
+ DBGFREG_DS_LIMIT,
+
+ DBGFREG_ES,
+ DBGFREG_ES_ATTR,
+ DBGFREG_ES_BASE,
+ DBGFREG_ES_LIMIT,
+
+ DBGFREG_FS,
+ DBGFREG_FS_ATTR,
+ DBGFREG_FS_BASE,
+ DBGFREG_FS_LIMIT,
+
+ DBGFREG_GS,
+ DBGFREG_GS_ATTR,
+ DBGFREG_GS_BASE,
+ DBGFREG_GS_LIMIT,
+
+ DBGFREG_SS,
+ DBGFREG_SS_ATTR,
+ DBGFREG_SS_BASE,
+ DBGFREG_SS_LIMIT,
+
+ DBGFREG_IP,
+ DBGFREG_EIP = DBGFREG_IP,
+ DBGFREG_RIP = DBGFREG_IP,
+
+ DBGFREG_FLAGS,
+ DBGFREG_EFLAGS = DBGFREG_FLAGS,
+ DBGFREG_RFLAGS = DBGFREG_FLAGS,
+
+ /* FPU: */
+ DBGFREG_FCW,
+ DBGFREG_FSW,
+ DBGFREG_FTW,
+ DBGFREG_FOP,
+ DBGFREG_FPUIP,
+ DBGFREG_FPUCS,
+ DBGFREG_FPUDP,
+ DBGFREG_FPUDS,
+ DBGFREG_MXCSR,
+ DBGFREG_MXCSR_MASK,
+
+ DBGFREG_ST0,
+ DBGFREG_ST1,
+ DBGFREG_ST2,
+ DBGFREG_ST3,
+ DBGFREG_ST4,
+ DBGFREG_ST5,
+ DBGFREG_ST6,
+ DBGFREG_ST7,
+
+ DBGFREG_MM0,
+ DBGFREG_MM1,
+ DBGFREG_MM2,
+ DBGFREG_MM3,
+ DBGFREG_MM4,
+ DBGFREG_MM5,
+ DBGFREG_MM6,
+ DBGFREG_MM7,
+
+ /* SSE: */
+ DBGFREG_XMM0,
+ DBGFREG_XMM1,
+ DBGFREG_XMM2,
+ DBGFREG_XMM3,
+ DBGFREG_XMM4,
+ DBGFREG_XMM5,
+ DBGFREG_XMM6,
+ DBGFREG_XMM7,
+ DBGFREG_XMM8,
+ DBGFREG_XMM9,
+ DBGFREG_XMM10,
+ DBGFREG_XMM11,
+ DBGFREG_XMM12,
+ DBGFREG_XMM13,
+ DBGFREG_XMM14,
+ DBGFREG_XMM15,
+ /** @todo add XMM aliases. */
+
+ /* AVX: */
+ DBGFREG_YMM0,
+ DBGFREG_YMM1,
+ DBGFREG_YMM2,
+ DBGFREG_YMM3,
+ DBGFREG_YMM4,
+ DBGFREG_YMM5,
+ DBGFREG_YMM6,
+ DBGFREG_YMM7,
+ DBGFREG_YMM8,
+ DBGFREG_YMM9,
+ DBGFREG_YMM10,
+ DBGFREG_YMM11,
+ DBGFREG_YMM12,
+ DBGFREG_YMM13,
+ DBGFREG_YMM14,
+ DBGFREG_YMM15,
+
+ /* System registers: */
+ DBGFREG_GDTR_BASE,
+ DBGFREG_GDTR_LIMIT,
+ DBGFREG_IDTR_BASE,
+ DBGFREG_IDTR_LIMIT,
+ DBGFREG_LDTR,
+ DBGFREG_LDTR_ATTR,
+ DBGFREG_LDTR_BASE,
+ DBGFREG_LDTR_LIMIT,
+ DBGFREG_TR,
+ DBGFREG_TR_ATTR,
+ DBGFREG_TR_BASE,
+ DBGFREG_TR_LIMIT,
+
+ DBGFREG_CR0,
+ DBGFREG_CR2,
+ DBGFREG_CR3,
+ DBGFREG_CR4,
+ DBGFREG_CR8,
+
+ DBGFREG_DR0,
+ DBGFREG_DR1,
+ DBGFREG_DR2,
+ DBGFREG_DR3,
+ DBGFREG_DR6,
+ DBGFREG_DR7,
+
+ /* MSRs: */
+ DBGFREG_MSR_IA32_APICBASE,
+ DBGFREG_MSR_IA32_CR_PAT,
+ DBGFREG_MSR_IA32_PERF_STATUS,
+ DBGFREG_MSR_IA32_SYSENTER_CS,
+ DBGFREG_MSR_IA32_SYSENTER_EIP,
+ DBGFREG_MSR_IA32_SYSENTER_ESP,
+ DBGFREG_MSR_IA32_TSC,
+ DBGFREG_MSR_K6_EFER,
+ DBGFREG_MSR_K6_STAR,
+ DBGFREG_MSR_K8_CSTAR,
+ DBGFREG_MSR_K8_FS_BASE,
+ DBGFREG_MSR_K8_GS_BASE,
+ DBGFREG_MSR_K8_KERNEL_GS_BASE,
+ DBGFREG_MSR_K8_LSTAR,
+ DBGFREG_MSR_K8_SF_MASK,
+ DBGFREG_MSR_K8_TSC_AUX,
+
+ /** The number of registers to pass to DBGFR3RegQueryAll. */
+ DBGFREG_ALL_COUNT,
+
+ /* Misc aliases that doesn't need be part of the 'all' query: */
+ DBGFREG_AH = DBGFREG_ALL_COUNT,
+ DBGFREG_CH,
+ DBGFREG_DH,
+ DBGFREG_BH,
+ DBGFREG_GDTR,
+ DBGFREG_IDTR,
+
+ /** The end of the registers. */
+ DBGFREG_END,
+ /** The usual 32-bit type hack. */
+ DBGFREG_32BIT_HACK = 0x7fffffff
+} DBGFREG;
+/** Pointer to a register identifier. */
+typedef DBGFREG *PDBGFREG;
+/** Pointer to a const register identifier. */
+typedef DBGFREG const *PCDBGFREG;
+
+/**
+ * Register value type.
+ */
+typedef enum DBGFREGVALTYPE
+{
+ DBGFREGVALTYPE_INVALID = 0,
+ /** Unsigned 8-bit register value. */
+ DBGFREGVALTYPE_U8,
+ /** Unsigned 16-bit register value. */
+ DBGFREGVALTYPE_U16,
+ /** Unsigned 32-bit register value. */
+ DBGFREGVALTYPE_U32,
+ /** Unsigned 64-bit register value. */
+ DBGFREGVALTYPE_U64,
+ /** Unsigned 128-bit register value. */
+ DBGFREGVALTYPE_U128,
+ /** Unsigned 256-bit register value. */
+ DBGFREGVALTYPE_U256,
+ /** Unsigned 512-bit register value. */
+ DBGFREGVALTYPE_U512,
+ /** Long double register value. */
+ DBGFREGVALTYPE_R80,
+ /** Descriptor table register value. */
+ DBGFREGVALTYPE_DTR,
+ /** End of the valid register value types. */
+ DBGFREGVALTYPE_END,
+ /** The usual 32-bit type hack. */
+ DBGFREGVALTYPE_32BIT_HACK = 0x7fffffff
+} DBGFREGVALTYPE;
+/** Pointer to a register value type. */
+typedef DBGFREGVALTYPE *PDBGFREGVALTYPE;
+
+/**
+ * A generic register value type.
+ */
+typedef union DBGFREGVAL
+{
+ uint64_t au64[8]; /**< The 64-bit array view. First because of the initializer. */
+ uint32_t au32[16]; /**< The 32-bit array view. */
+ uint16_t au16[32]; /**< The 16-bit array view. */
+ uint8_t au8[64]; /**< The 8-bit array view. */
+
+ uint8_t u8; /**< The 8-bit view. */
+ uint16_t u16; /**< The 16-bit view. */
+ uint32_t u32; /**< The 32-bit view. */
+ uint64_t u64; /**< The 64-bit view. */
+ RTUINT128U u128; /**< The 128-bit view. */
+ RTUINT256U u256; /**< The 256-bit view. */
+ RTUINT512U u512; /**< The 512-bit view. */
+ RTFLOAT80U r80; /**< The 80-bit floating point view. */
+ RTFLOAT80U2 r80Ex; /**< The 80-bit floating point view v2. */
+ /** GDTR or LDTR (DBGFREGVALTYPE_DTR). */
+ struct
+ {
+ /** The table address. */
+ uint64_t u64Base;
+ /** The table limit (length minus 1). */
+ uint32_t u32Limit; /**< @todo Limit should be uint16_t */
+ } dtr;
+} DBGFREGVAL;
+/** Pointer to a generic register value type. */
+typedef DBGFREGVAL *PDBGFREGVAL;
+/** Pointer to a const generic register value type. */
+typedef DBGFREGVAL const *PCDBGFREGVAL;
+
+/** Initialize a DBGFREGVAL variable to all zeros. */
+#define DBGFREGVAL_INITIALIZE_ZERO { { 0, 0, 0, 0, 0, 0, 0, 0 } }
+/** Initialize a DBGFREGVAL variable to all bits set . */
+#define DBGFREGVAL_INITIALIZE_FFFF { { UINT64_MAX, UINT64_MAX, UINT64_MAX, UINT64_MAX, UINT64_MAX, UINT64_MAX, UINT64_MAX, UINT64_MAX } }
+
+/**
+ * Extended register value, including register ID and type.
+ *
+ * This is currently only used by the stack walker.
+ */
+typedef struct DBGFREGVALEX
+{
+ /** The register value. */
+ DBGFREGVAL Value;
+ /** The register value type. */
+ DBGFREGVALTYPE enmType;
+ /** The register ID, DBGFREG_END if not applicable. */
+ DBGFREG enmReg;
+ /** Pointer to read-only register name string if no register ID could be found. */
+ const char *pszName;
+} DBGFREGVALEX;
+/** Pointer to an extended register value struct. */
+typedef DBGFREGVALEX *PDBGFREGVALEX;
+/** Pointer to a const extended register value struct. */
+typedef DBGFREGVALEX const *PCDBGFREGVALEX;
+
+
+VMMDECL(ssize_t) DBGFR3RegFormatValue(char *pszBuf, size_t cbBuf, PCDBGFREGVAL pValue, DBGFREGVALTYPE enmType, bool fSpecial);
+VMMDECL(ssize_t) DBGFR3RegFormatValueEx(char *pszBuf, size_t cbBuf, PCDBGFREGVAL pValue, DBGFREGVALTYPE enmType,
+ unsigned uBase, signed int cchWidth, signed int cchPrecision, uint32_t fFlags);
+
+/**
+ * Register sub-field descriptor.
+ */
+typedef struct DBGFREGSUBFIELD
+{
+ /** The name of the sub-field. NULL is used to terminate the array. */
+ const char *pszName;
+ /** The index of the first bit. Ignored if pfnGet is set. */
+ uint8_t iFirstBit;
+ /** The number of bits. Mandatory. */
+ uint8_t cBits;
+ /** The shift count. Not applied when pfnGet is set, but used to
+ * calculate the minimum type. */
+ int8_t cShift;
+ /** Sub-field flags, DBGFREGSUBFIELD_FLAGS_XXX. */
+ uint8_t fFlags;
+ /** Getter (optional).
+ * @remarks Does not take the device lock or anything like that.
+ */
+ DECLCALLBACKMEMBER(int, pfnGet,(void *pvUser, struct DBGFREGSUBFIELD const *pSubField, PRTUINT128U puValue));
+ /** Setter (optional).
+ * @remarks Does not take the device lock or anything like that.
+ */
+ DECLCALLBACKMEMBER(int, pfnSet,(void *pvUser, struct DBGFREGSUBFIELD const *pSubField, RTUINT128U uValue, RTUINT128U fMask));
+} DBGFREGSUBFIELD;
+/** Pointer to a const register sub-field descriptor. */
+typedef DBGFREGSUBFIELD const *PCDBGFREGSUBFIELD;
+
+/** @name DBGFREGSUBFIELD_FLAGS_XXX
+ * @{ */
+/** The sub-field is read-only. */
+#define DBGFREGSUBFIELD_FLAGS_READ_ONLY UINT8_C(0x01)
+/** @} */
+
+/** Macro for creating a read-write sub-field entry without getters. */
+#define DBGFREGSUBFIELD_RW(a_szName, a_iFirstBit, a_cBits, a_cShift) \
+ { a_szName, a_iFirstBit, a_cBits, a_cShift, 0 /*fFlags*/, NULL /*pfnGet*/, NULL /*pfnSet*/ }
+/** Macro for creating a read-write sub-field entry with getters. */
+#define DBGFREGSUBFIELD_RW_SG(a_szName, a_cBits, a_cShift, a_pfnGet, a_pfnSet) \
+ { a_szName, 0 /*iFirstBit*/, a_cBits, a_cShift, 0 /*fFlags*/, a_pfnGet, a_pfnSet }
+/** Macro for creating a read-only sub-field entry without getters. */
+#define DBGFREGSUBFIELD_RO(a_szName, a_iFirstBit, a_cBits, a_cShift) \
+ { a_szName, a_iFirstBit, a_cBits, a_cShift, DBGFREGSUBFIELD_FLAGS_READ_ONLY, NULL /*pfnGet*/, NULL /*pfnSet*/ }
+/** Macro for creating a terminator sub-field entry. */
+#define DBGFREGSUBFIELD_TERMINATOR() \
+ { NULL, 0, 0, 0, 0, NULL, NULL }
+
+/**
+ * Register alias descriptor.
+ */
+typedef struct DBGFREGALIAS
+{
+ /** The alias name. NULL is used to terminate the array. */
+ const char *pszName;
+ /** Set to a valid type if the alias has a different type. */
+ DBGFREGVALTYPE enmType;
+} DBGFREGALIAS;
+/** Pointer to a const register alias descriptor. */
+typedef DBGFREGALIAS const *PCDBGFREGALIAS;
+
+/**
+ * Register descriptor.
+ */
+typedef struct DBGFREGDESC
+{
+ /** The normal register name. */
+ const char *pszName;
+ /** The register identifier if this is a CPU register. */
+ DBGFREG enmReg;
+ /** The default register type. */
+ DBGFREGVALTYPE enmType;
+ /** Flags, see DBGFREG_FLAGS_XXX. */
+ uint32_t fFlags;
+ /** The internal register indicator.
+ * For CPU registers this is the offset into the CPUMCTX structure,
+ * thuse the 'off' prefix. */
+ uint32_t offRegister;
+ /** Getter.
+ * @remarks Does not take the device lock or anything like that.
+ */
+ DECLCALLBACKMEMBER(int, pfnGet,(void *pvUser, struct DBGFREGDESC const *pDesc, PDBGFREGVAL pValue));
+ /** Setter.
+ * @remarks Does not take the device lock or anything like that.
+ */
+ DECLCALLBACKMEMBER(int, pfnSet,(void *pvUser, struct DBGFREGDESC const *pDesc, PCDBGFREGVAL pValue, PCDBGFREGVAL pfMask));
+ /** Aliases (optional). */
+ PCDBGFREGALIAS paAliases;
+ /** Sub fields (optional). */
+ PCDBGFREGSUBFIELD paSubFields;
+} DBGFREGDESC;
+
+/** @name Macros for constructing DBGFREGDESC arrays.
+ * @{ */
+#define DBGFREGDESC_RW(a_szName, a_TypeSuff, a_offRegister, a_pfnGet, a_pfnSet) \
+ { a_szName, DBGFREG_END, DBGFREGVALTYPE_##a_TypeSuff, 0 /*fFlags*/, a_offRegister, a_pfnGet, a_pfnSet, NULL /*paAlises*/, NULL /*paSubFields*/ }
+#define DBGFREGDESC_RO(a_szName, a_TypeSuff, a_offRegister, a_pfnGet, a_pfnSet) \
+ { a_szName, DBGFREG_END, DBGFREGVALTYPE_##a_TypeSuff, DBGFREG_FLAGS_READ_ONLY, a_offRegister, a_pfnGet, a_pfnSet, NULL /*paAlises*/, NULL /*paSubFields*/ }
+#define DBGFREGDESC_RW_A(a_szName, a_TypeSuff, a_offRegister, a_pfnGet, a_pfnSet, a_paAliases) \
+ { a_szName, DBGFREG_END, DBGFREGVALTYPE_##a_TypeSuff, 0 /*fFlags*/, a_offRegister, a_pfnGet, a_pfnSet, a_paAliases, NULL /*paSubFields*/ }
+#define DBGFREGDESC_RO_A(a_szName, a_TypeSuff, a_offRegister, a_pfnGet, a_pfnSet, a_paAliases) \
+ { a_szName, DBGFREG_END, DBGFREGVALTYPE_##a_TypeSuff, DBGFREG_FLAGS_READ_ONLY, a_offRegister, a_pfnGet, a_pfnSet, a_paAliases, NULL /*paSubFields*/ }
+#define DBGFREGDESC_RW_S(a_szName, a_TypeSuff, a_offRegister, a_pfnGet, a_pfnSet, a_paSubFields) \
+ { a_szName, DBGFREG_END, DBGFREGVALTYPE_##a_TypeSuff, 0 /*fFlags*/, a_offRegister, a_pfnGet, a_pfnSet, /*paAliases*/, a_paSubFields }
+#define DBGFREGDESC_RO_S(a_szName, a_TypeSuff, a_offRegister, a_pfnGet, a_pfnSet, a_paSubFields) \
+ { a_szName, DBGFREG_END, DBGFREGVALTYPE_##a_TypeSuff, DBGFREG_FLAGS_READ_ONLY, a_offRegister, a_pfnGet, a_pfnSet, /*paAliases*/, a_paSubFields }
+#define DBGFREGDESC_RW_AS(a_szName, a_TypeSuff, a_offRegister, a_pfnGet, a_pfnSet, a_paAliases, a_paSubFields) \
+ { a_szName, DBGFREG_END, DBGFREGVALTYPE_##a_TypeSuff, 0 /*fFlags*/, a_offRegister, a_pfnGet, a_pfnSet, a_paAliases, a_paSubFields }
+#define DBGFREGDESC_RO_AS(a_szName, a_TypeSuff, a_offRegister, a_pfnGet, a_pfnSet, a_paAliases, a_paSubFields) \
+ { a_szName, DBGFREG_END, DBGFREGVALTYPE_##a_TypeSuff, DBGFREG_FLAGS_READ_ONLY, a_offRegister, a_pfnGet, a_pfnSet, a_paAliases, a_paSubFields }
+#define DBGFREGDESC_TERMINATOR() \
+ { NULL, DBGFREG_END, DBGFREGVALTYPE_INVALID, 0, 0, NULL, NULL, NULL, NULL }
+/** @} */
+
+
+/** @name DBGFREG_FLAGS_XXX
+ * @{ */
+/** The register is read-only. */
+#define DBGFREG_FLAGS_READ_ONLY RT_BIT_32(0)
+/** @} */
+
+/**
+ * Entry in a batch query or set operation.
+ */
+typedef struct DBGFREGENTRY
+{
+ /** The register identifier. */
+ DBGFREG enmReg;
+ /** The size of the value in bytes. */
+ DBGFREGVALTYPE enmType;
+ /** The register value. The valid view is indicated by enmType. */
+ DBGFREGVAL Val;
+} DBGFREGENTRY;
+/** Pointer to a register entry in a batch operation. */
+typedef DBGFREGENTRY *PDBGFREGENTRY;
+/** Pointer to a const register entry in a batch operation. */
+typedef DBGFREGENTRY const *PCDBGFREGENTRY;
+
+/** Used with DBGFR3Reg* to indicate the hypervisor register set instead of the
+ * guest. */
+#define DBGFREG_HYPER_VMCPUID UINT32_C(0x01000000)
+
+VMMR3DECL(int) DBGFR3RegCpuQueryU8( PUVM pUVM, VMCPUID idCpu, DBGFREG enmReg, uint8_t *pu8);
+VMMR3DECL(int) DBGFR3RegCpuQueryU16( PUVM pUVM, VMCPUID idCpu, DBGFREG enmReg, uint16_t *pu16);
+VMMR3DECL(int) DBGFR3RegCpuQueryU32( PUVM pUVM, VMCPUID idCpu, DBGFREG enmReg, uint32_t *pu32);
+VMMR3DECL(int) DBGFR3RegCpuQueryU64( PUVM pUVM, VMCPUID idCpu, DBGFREG enmReg, uint64_t *pu64);
+VMMR3DECL(int) DBGFR3RegCpuQueryU128(PUVM pUVM, VMCPUID idCpu, DBGFREG enmReg, uint128_t *pu128);
+/*VMMR3DECL(int) DBGFR3RegCpuQueryLrd( PUVM pUVM, VMCPUID idCpu, DBGFREG enmReg, long double *plrd);*/
+VMMR3DECL(int) DBGFR3RegCpuQueryXdtr(PUVM pUVM, VMCPUID idCpu, DBGFREG enmReg, uint64_t *pu64Base, uint16_t *pu16Limit);
+#if 0
+VMMR3DECL(int) DBGFR3RegCpuQueryBatch(PUVM pUVM,VMCPUID idCpu, PDBGFREGENTRY paRegs, size_t cRegs);
+VMMR3DECL(int) DBGFR3RegCpuQueryAll( PUVM pUVM, VMCPUID idCpu, PDBGFREGENTRY paRegs, size_t cRegs);
+
+VMMR3DECL(int) DBGFR3RegCpuSetU8( PUVM pUVM, VMCPUID idCpu, DBGFREG enmReg, uint8_t u8);
+VMMR3DECL(int) DBGFR3RegCpuSetU16( PUVM pUVM, VMCPUID idCpu, DBGFREG enmReg, uint16_t u16);
+VMMR3DECL(int) DBGFR3RegCpuSetU32( PUVM pUVM, VMCPUID idCpu, DBGFREG enmReg, uint32_t u32);
+VMMR3DECL(int) DBGFR3RegCpuSetU64( PUVM pUVM, VMCPUID idCpu, DBGFREG enmReg, uint64_t u64);
+VMMR3DECL(int) DBGFR3RegCpuSetU128( PUVM pUVM, VMCPUID idCpu, DBGFREG enmReg, uint128_t u128);
+VMMR3DECL(int) DBGFR3RegCpuSetLrd( PUVM pUVM, VMCPUID idCpu, DBGFREG enmReg, long double lrd);
+VMMR3DECL(int) DBGFR3RegCpuSetBatch( PUVM pUVM, VMCPUID idCpu, PCDBGFREGENTRY paRegs, size_t cRegs);
+#endif
+
+VMMR3DECL(const char *) DBGFR3RegCpuName(PUVM pUVM, DBGFREG enmReg, DBGFREGVALTYPE enmType);
+
+VMMR3_INT_DECL(int) DBGFR3RegRegisterCpu(PVM pVM, PVMCPU pVCpu, PCDBGFREGDESC paRegisters, bool fGuestRegs);
+VMMR3_INT_DECL(int) DBGFR3RegRegisterDevice(PVM pVM, PCDBGFREGDESC paRegisters, PPDMDEVINS pDevIns,
+ const char *pszPrefix, uint32_t iInstance);
+
+/**
+ * Entry in a named batch query or set operation.
+ */
+typedef struct DBGFREGENTRYNM
+{
+ /** The register name. */
+ const char *pszName;
+ /** The size of the value in bytes. */
+ DBGFREGVALTYPE enmType;
+ /** The register value. The valid view is indicated by enmType. */
+ DBGFREGVAL Val;
+} DBGFREGENTRYNM;
+/** Pointer to a named register entry in a batch operation. */
+typedef DBGFREGENTRYNM *PDBGFREGENTRYNM;
+/** Pointer to a const named register entry in a batch operation. */
+typedef DBGFREGENTRYNM const *PCDBGFREGENTRYNM;
+
+VMMR3DECL(int) DBGFR3RegNmValidate( PUVM pUVM, VMCPUID idDefCpu, const char *pszReg);
+
+VMMR3DECL(int) DBGFR3RegNmQuery( PUVM pUVM, VMCPUID idDefCpu, const char *pszReg, PDBGFREGVAL pValue, PDBGFREGVALTYPE penmType);
+VMMR3DECL(int) DBGFR3RegNmQueryU8( PUVM pUVM, VMCPUID idDefCpu, const char *pszReg, uint8_t *pu8);
+VMMR3DECL(int) DBGFR3RegNmQueryU16( PUVM pUVM, VMCPUID idDefCpu, const char *pszReg, uint16_t *pu16);
+VMMR3DECL(int) DBGFR3RegNmQueryU32( PUVM pUVM, VMCPUID idDefCpu, const char *pszReg, uint32_t *pu32);
+VMMR3DECL(int) DBGFR3RegNmQueryU64( PUVM pUVM, VMCPUID idDefCpu, const char *pszReg, uint64_t *pu64);
+VMMR3DECL(int) DBGFR3RegNmQueryU128(PUVM pUVM, VMCPUID idDefCpu, const char *pszReg, PRTUINT128U pu128);
+/*VMMR3DECL(int) DBGFR3RegNmQueryLrd( PUVM pUVM, VMCPUID idDefCpu, const char *pszReg, long double *plrd);*/
+VMMR3DECL(int) DBGFR3RegNmQueryXdtr(PUVM pUVM, VMCPUID idDefCpu, const char *pszReg, uint64_t *pu64Base, uint16_t *pu16Limit);
+VMMR3DECL(int) DBGFR3RegNmQueryBatch(PUVM pUVM,VMCPUID idDefCpu, PDBGFREGENTRYNM paRegs, size_t cRegs);
+VMMR3DECL(int) DBGFR3RegNmQueryAllCount(PUVM pUVM, size_t *pcRegs);
+VMMR3DECL(int) DBGFR3RegNmQueryAll( PUVM pUVM, PDBGFREGENTRYNM paRegs, size_t cRegs);
+
+VMMR3DECL(int) DBGFR3RegNmSet( PUVM pUVM, VMCPUID idDefCpu, const char *pszReg, PCDBGFREGVAL pValue, DBGFREGVALTYPE enmType);
+VMMR3DECL(int) DBGFR3RegNmSetU8( PUVM pUVM, VMCPUID idDefCpu, const char *pszReg, uint8_t u8);
+VMMR3DECL(int) DBGFR3RegNmSetU16( PUVM pUVM, VMCPUID idDefCpu, const char *pszReg, uint16_t u16);
+VMMR3DECL(int) DBGFR3RegNmSetU32( PUVM pUVM, VMCPUID idDefCpu, const char *pszReg, uint32_t u32);
+VMMR3DECL(int) DBGFR3RegNmSetU64( PUVM pUVM, VMCPUID idDefCpu, const char *pszReg, uint64_t u64);
+VMMR3DECL(int) DBGFR3RegNmSetU128( PUVM pUVM, VMCPUID idDefCpu, const char *pszReg, RTUINT128U u128);
+VMMR3DECL(int) DBGFR3RegNmSetLrd( PUVM pUVM, VMCPUID idDefCpu, const char *pszReg, long double lrd);
+VMMR3DECL(int) DBGFR3RegNmSetBatch( PUVM pUVM, VMCPUID idDefCpu, PCDBGFREGENTRYNM paRegs, size_t cRegs);
+
+/** @todo add enumeration methods. */
+
+VMMR3DECL(int) DBGFR3RegPrintf( PUVM pUVM, VMCPUID idDefCpu, char *pszBuf, size_t cbBuf, const char *pszFormat, ...);
+VMMR3DECL(int) DBGFR3RegPrintfV(PUVM pUVM, VMCPUID idDefCpu, char *pszBuf, size_t cbBuf, const char *pszFormat, va_list va);
+
+
+#ifdef IN_RING3
+
+/**
+ * Guest OS digger interface identifier.
+ *
+ * This is for use together with PDBGFR3QueryInterface and is used to
+ * obtain access to optional interfaces.
+ */
+typedef enum DBGFOSINTERFACE
+{
+ /** The usual invalid entry. */
+ DBGFOSINTERFACE_INVALID = 0,
+ /** Process info. */
+ DBGFOSINTERFACE_PROCESS,
+ /** Thread info. */
+ DBGFOSINTERFACE_THREAD,
+ /** Kernel message log - DBGFOSIDMESG. */
+ DBGFOSINTERFACE_DMESG,
+ /** Windows NT specifics (for the communication with the KD debugger stub). */
+ DBGFOSINTERFACE_WINNT,
+ /** The end of the valid entries. */
+ DBGFOSINTERFACE_END,
+ /** The usual 32-bit type blowup. */
+ DBGFOSINTERFACE_32BIT_HACK = 0x7fffffff
+} DBGFOSINTERFACE;
+/** Pointer to a Guest OS digger interface identifier. */
+typedef DBGFOSINTERFACE *PDBGFOSINTERFACE;
+/** Pointer to a const Guest OS digger interface identifier. */
+typedef DBGFOSINTERFACE const *PCDBGFOSINTERFACE;
+
+
+/**
+ * Guest OS Digger Registration Record.
+ *
+ * This is used with the DBGFR3OSRegister() API.
+ */
+typedef struct DBGFOSREG
+{
+ /** Magic value (DBGFOSREG_MAGIC). */
+ uint32_t u32Magic;
+ /** Flags. Reserved. */
+ uint32_t fFlags;
+ /** The size of the instance data. */
+ uint32_t cbData;
+ /** Operative System name. */
+ char szName[24];
+
+ /**
+ * Constructs the instance.
+ *
+ * @returns VBox status code.
+ * @param pUVM The user mode VM handle.
+ * @param pVMM The VMM function table.
+ * @param pvData Pointer to the instance data.
+ */
+ DECLCALLBACKMEMBER(int, pfnConstruct,(PUVM pUVM, PCVMMR3VTABLE pVMM, void *pvData));
+
+ /**
+ * Destroys the instance.
+ *
+ * @param pUVM The user mode VM handle.
+ * @param pVMM The VMM function table.
+ * @param pvData Pointer to the instance data.
+ */
+ DECLCALLBACKMEMBER(void, pfnDestruct,(PUVM pUVM, PCVMMR3VTABLE pVMM, void *pvData));
+
+ /**
+ * Probes the guest memory for OS finger prints.
+ *
+ * No setup or so is performed, it will be followed by a call to pfnInit
+ * or pfnRefresh that should take care of that.
+ *
+ * @returns true if is an OS handled by this module, otherwise false.
+ * @param pUVM The user mode VM handle.
+ * @param pVMM The VMM function table.
+ * @param pvData Pointer to the instance data.
+ */
+ DECLCALLBACKMEMBER(bool, pfnProbe,(PUVM pUVM, PCVMMR3VTABLE pVMM, void *pvData));
+
+ /**
+ * Initializes a fresly detected guest, loading symbols and such useful stuff.
+ *
+ * This is called after pfnProbe.
+ *
+ * @returns VBox status code.
+ * @param pUVM The user mode VM handle.
+ * @param pVMM The VMM function table.
+ * @param pvData Pointer to the instance data.
+ */
+ DECLCALLBACKMEMBER(int, pfnInit,(PUVM pUVM, PCVMMR3VTABLE pVMM, void *pvData));
+
+ /**
+ * Refreshes symbols and stuff following a redetection of the same OS.
+ *
+ * This is called after pfnProbe.
+ *
+ * @returns VBox status code.
+ * @param pUVM The user mode VM handle.
+ * @param pVMM The VMM function table.
+ * @param pvData Pointer to the instance data.
+ */
+ DECLCALLBACKMEMBER(int, pfnRefresh,(PUVM pUVM, PCVMMR3VTABLE pVMM, void *pvData));
+
+ /**
+ * Terminates an OS when a new (or none) OS has been detected,
+ * and before destruction.
+ *
+ * This is called after pfnProbe and if needed before pfnDestruct.
+ *
+ * @param pUVM The user mode VM handle.
+ * @param pVMM The VMM function table.
+ * @param pvData Pointer to the instance data.
+ */
+ DECLCALLBACKMEMBER(void, pfnTerm,(PUVM pUVM, PCVMMR3VTABLE pVMM, void *pvData));
+
+ /**
+ * Queries the version of the running OS.
+ *
+ * This is only called after pfnInit().
+ *
+ * @returns VBox status code.
+ * @param pUVM The user mode VM handle.
+ * @param pVMM The VMM function table.
+ * @param pvData Pointer to the instance data.
+ * @param pszVersion Where to store the version string.
+ * @param cchVersion The size of the version string buffer.
+ */
+ DECLCALLBACKMEMBER(int, pfnQueryVersion,(PUVM pUVM, PCVMMR3VTABLE pVMM, void *pvData, char *pszVersion, size_t cchVersion));
+
+ /**
+ * Queries the pointer to a interface.
+ *
+ * This is called after pfnProbe.
+ *
+ * The returned interface must be valid until pfnDestruct is called. Two calls
+ * to this method with the same @a enmIf value must return the same pointer.
+ *
+ * @returns Pointer to the interface if available, NULL if not available.
+ * @param pUVM The user mode VM handle.
+ * @param pVMM The VMM function table.
+ * @param pvData Pointer to the instance data.
+ * @param enmIf The interface identifier.
+ */
+ DECLCALLBACKMEMBER(void *, pfnQueryInterface,(PUVM pUVM, PCVMMR3VTABLE pVMM, void *pvData, DBGFOSINTERFACE enmIf));
+
+ /**
+ * Stack unwind assist callback.
+ *
+ * This is only called after pfnInit().
+ *
+ * @returns VBox status code (allocation error or something of similar fatality).
+ * @param pUVM The user mode VM handle.
+ * @param pVMM The VMM function table.
+ * @param pvData Pointer to the instance data.
+ * @param idCpu The CPU that's unwinding it's stack.
+ * @param pFrame The current frame. Okay to modify it a little.
+ * @param pState The unwind state. Okay to modify it.
+ * @param pInitialCtx The initial register context.
+ * @param hAs The address space being used for the unwind.
+ * @param puScratch Scratch area (initialized to zero, no dtor).
+ */
+ DECLCALLBACKMEMBER(int, pfnStackUnwindAssist,(PUVM pUVM, PCVMMR3VTABLE pVMM, void *pvData, VMCPUID idCpu, PDBGFSTACKFRAME pFrame,
+ PRTDBGUNWINDSTATE pState, PCCPUMCTX pInitialCtx, RTDBGAS hAs,
+ uint64_t *puScratch));
+
+ /** Trailing magic (DBGFOSREG_MAGIC). */
+ uint32_t u32EndMagic;
+} DBGFOSREG;
+/** Pointer to a Guest OS digger registration record. */
+typedef DBGFOSREG *PDBGFOSREG;
+/** Pointer to a const Guest OS digger registration record. */
+typedef DBGFOSREG const *PCDBGFOSREG;
+
+/** Magic value for DBGFOSREG::u32Magic and DBGFOSREG::u32EndMagic. (Hitomi Kanehara) */
+#define DBGFOSREG_MAGIC 0x19830808
+
+
+/**
+ * Interface for querying kernel log messages (DBGFOSINTERFACE_DMESG).
+ */
+typedef struct DBGFOSIDMESG
+{
+ /** Trailing magic (DBGFOSIDMESG_MAGIC). */
+ uint32_t u32Magic;
+
+ /**
+ * Query the kernel log.
+ *
+ * @returns VBox status code.
+ * @retval VERR_NOT_FOUND if the messages could not be located.
+ * @retval VERR_INVALID_STATE if the messages was found to have unknown/invalid
+ * format.
+ * @retval VERR_BUFFER_OVERFLOW if the buffer isn't large enough, pcbActual
+ * will be set to the required buffer size. The buffer, however, will
+ * be filled with as much data as it can hold (properly zero terminated
+ * of course).
+ *
+ * @param pThis Pointer to the interface structure.
+ * @param pUVM The user mode VM handle.
+ * @param pVMM The VMM function table.
+ * @param fFlags Flags reserved for future use, MBZ.
+ * @param cMessages The number of messages to retrieve, counting from the
+ * end of the log (i.e. like tail), use UINT32_MAX for all.
+ * @param pszBuf The output buffer.
+ * @param cbBuf The buffer size.
+ * @param pcbActual Where to store the number of bytes actually returned,
+ * including zero terminator. On VERR_BUFFER_OVERFLOW this
+ * holds the necessary buffer size. Optional.
+ */
+ DECLCALLBACKMEMBER(int, pfnQueryKernelLog,(struct DBGFOSIDMESG *pThis, PUVM pUVM, PCVMMR3VTABLE pVMM, uint32_t fFlags,
+ uint32_t cMessages, char *pszBuf, size_t cbBuf, size_t *pcbActual));
+ /** Trailing magic (DBGFOSIDMESG_MAGIC). */
+ uint32_t u32EndMagic;
+} DBGFOSIDMESG;
+/** Pointer to the interface for query kernel log messages (DBGFOSINTERFACE_DMESG). */
+typedef DBGFOSIDMESG *PDBGFOSIDMESG;
+/** Magic value for DBGFOSIDMESG::32Magic and DBGFOSIDMESG::u32EndMagic. (Kenazburo Oe) */
+#define DBGFOSIDMESG_MAGIC UINT32_C(0x19350131)
+
+
+/**
+ * Interface for querying Windows NT guest specifics (DBGFOSINTERFACE_WINNT).
+ */
+typedef struct DBGFOSIWINNT
+{
+ /** Trailing magic (DBGFOSIWINNT_MAGIC). */
+ uint32_t u32Magic;
+
+ /**
+ * Queries version information.
+ *
+ * @returns VBox status code.
+ * @param pThis Pointer to the interface structure.
+ * @param pUVM The user mode VM handle.
+ * @param pVMM The VMM function table.
+ * @param puVersMajor Where to store the major version part, optional.
+ * @param puVersMinor Where to store the minor version part, optional.
+ * @param puBuildNumber Where to store the build number, optional.
+ * @param pf32Bit Where to store the flag whether this is a 32bit Windows NT, optional.
+ */
+ DECLCALLBACKMEMBER(int, pfnQueryVersion,(struct DBGFOSIWINNT *pThis, PUVM pUVM, PCVMMR3VTABLE pVMM,
+ uint32_t *puVersMajor, uint32_t *puVersMinor,
+ uint32_t *puBuildNumber, bool *pf32Bit));
+
+ /**
+ * Queries some base kernel pointers.
+ *
+ * @returns VBox status code.
+ * @param pThis Pointer to the interface structure.
+ * @param pUVM The user mode VM handle.
+ * @param pVMM The VMM function table.
+ * @param pGCPtrKernBase Where to store the kernel base on success.
+ * @param pGCPtrPsLoadedModuleList Where to store the pointer to the laoded module list head on success.
+ */
+ DECLCALLBACKMEMBER(int, pfnQueryKernelPtrs,(struct DBGFOSIWINNT *pThis, PUVM pUVM, PCVMMR3VTABLE pVMM,
+ PRTGCUINTPTR pGCPtrKernBase, PRTGCUINTPTR pGCPtrPsLoadedModuleList));
+
+ /**
+ * Queries KPCR and KPCRB pointers for the given vCPU.
+ *
+ * @returns VBox status code.
+ * @param pThis Pointer to the interface structure.
+ * @param pUVM The user mode VM handle.
+ * @param pVMM The VMM function table.
+ * @param idCpu The vCPU to query the KPCR/KPCRB for.
+ * @param pKpcr Where to store the KPCR pointer on success, optional.
+ * @param pKpcrb Where to store the KPCR pointer on success, optional.
+ */
+ DECLCALLBACKMEMBER(int, pfnQueryKpcrForVCpu,(struct DBGFOSIWINNT *pThis, PUVM pUVM, PCVMMR3VTABLE pVMM, VMCPUID idCpu,
+ PRTGCUINTPTR pKpcr, PRTGCUINTPTR pKpcrb));
+
+ /**
+ * Queries the current thread for the given vCPU.
+ *
+ * @returns VBox status code.
+ * @param pThis Pointer to the interface structure.
+ * @param pUVM The user mode VM handle.
+ * @param pVMM The VMM function table.
+ * @param idCpu The vCPU to query the KPCR/KPCRB for.
+ * @param pCurThrd Where to store the CurrentThread pointer on success.
+ */
+ DECLCALLBACKMEMBER(int, pfnQueryCurThrdForVCpu,(struct DBGFOSIWINNT *pThis, PUVM pUVM, PCVMMR3VTABLE pVMM, VMCPUID idCpu,
+ PRTGCUINTPTR pCurThrd));
+
+ /** Trailing magic (DBGFOSIWINNT_MAGIC). */
+ uint32_t u32EndMagic;
+} DBGFOSIWINNT;
+/** Pointer to the interface for query kernel log messages (DBGFOSINTERFACE_WINNT). */
+typedef DBGFOSIWINNT *PDBGFOSIWINNT;
+/** Magic value for DBGFOSIWINNT::32Magic and DBGFOSIWINNT::u32EndMagic. (Dave Cutler) */
+#define DBGFOSIWINNT_MAGIC UINT32_C(0x19420313)
+
+
+VMMR3DECL(int) DBGFR3OSRegister(PUVM pUVM, PCDBGFOSREG pReg);
+VMMR3DECL(int) DBGFR3OSDeregister(PUVM pUVM, PCDBGFOSREG pReg);
+VMMR3DECL(int) DBGFR3OSDetect(PUVM pUVM, char *pszName, size_t cchName);
+VMMR3DECL(int) DBGFR3OSQueryNameAndVersion(PUVM pUVM, char *pszName, size_t cchName, char *pszVersion, size_t cchVersion);
+VMMR3DECL(void *) DBGFR3OSQueryInterface(PUVM pUVM, DBGFOSINTERFACE enmIf);
+
+
+VMMR3DECL(int) DBGFR3CoreWrite(PUVM pUVM, const char *pszFilename, bool fReplaceFile);
+
+
+
+/** @defgroup grp_dbgf_plug_in The DBGF Plug-in Interface
+ * @{
+ */
+
+/** The plug-in module name prefix. */
+# define DBGF_PLUG_IN_PREFIX "DbgPlugIn"
+
+/** The name of the plug-in entry point (FNDBGFPLUGIN) */
+# define DBGF_PLUG_IN_ENTRYPOINT "DbgPlugInEntry"
+
+/**
+ * DBGF plug-in operations.
+ */
+typedef enum DBGFPLUGINOP
+{
+ /** The usual invalid first value. */
+ DBGFPLUGINOP_INVALID,
+ /** Initialize the plug-in for a VM, register all the stuff.
+ * The plug-in will be unloaded on failure.
+ * uArg: The full VirtualBox version, see VBox/version.h. */
+ DBGFPLUGINOP_INIT,
+ /** Terminate the plug-ing for a VM, deregister all the stuff.
+ * The plug-in will be unloaded after this call regardless of the return
+ * code. */
+ DBGFPLUGINOP_TERM,
+ /** The usual 32-bit hack. */
+ DBGFPLUGINOP_32BIT_HACK = 0x7fffffff
+} DBGFPLUGINOP;
+
+/**
+ * DBGF plug-in main entry point.
+ *
+ * @returns VBox status code.
+ *
+ * @param enmOperation The operation.
+ * @param pUVM The user mode VM handle. This may be NULL.
+ * @param pVMM The VMM function table.
+ * @param uArg Extra argument.
+ */
+typedef DECLCALLBACKTYPE(int, FNDBGFPLUGIN,(DBGFPLUGINOP enmOperation, PUVM pUVM, PCVMMR3VTABLE pVMM, uintptr_t uArg));
+/** Pointer to a FNDBGFPLUGIN. */
+typedef FNDBGFPLUGIN *PFNDBGFPLUGIN;
+
+/** @copydoc FNDBGFPLUGIN */
+DECLEXPORT(int) DbgPlugInEntry(DBGFPLUGINOP enmOperation, PUVM pUVM, PCVMMR3VTABLE pVMM, uintptr_t uArg);
+
+VMMR3DECL(int) DBGFR3PlugInLoad(PUVM pUVM, const char *pszPlugIn, char *pszActual, size_t cbActual, PRTERRINFO pErrInfo);
+VMMR3DECL(int) DBGFR3PlugInUnload(PUVM pUVM, const char *pszName);
+VMMR3DECL(void) DBGFR3PlugInLoadAll(PUVM pUVM);
+VMMR3DECL(void) DBGFR3PlugInUnloadAll(PUVM pUVM);
+
+/** @} */
+
+
+/** @defgroup grp_dbgf_types The DBGF type system Interface.
+ * @{
+ */
+
+/** A few forward declarations. */
+/** Pointer to a type registration structure. */
+typedef struct DBGFTYPEREG *PDBGFTYPEREG;
+/** Pointer to a const type registration structure. */
+typedef const struct DBGFTYPEREG *PCDBGFTYPEREG;
+/** Pointer to a typed buffer. */
+typedef struct DBGFTYPEVAL *PDBGFTYPEVAL;
+
+/**
+ * DBGF built-in types.
+ */
+typedef enum DBGFTYPEBUILTIN
+{
+ /** The usual invalid first value. */
+ DBGFTYPEBUILTIN_INVALID,
+ /** Unsigned 8bit integer. */
+ DBGFTYPEBUILTIN_UINT8,
+ /** Signed 8bit integer. */
+ DBGFTYPEBUILTIN_INT8,
+ /** Unsigned 16bit integer. */
+ DBGFTYPEBUILTIN_UINT16,
+ /** Signed 16bit integer. */
+ DBGFTYPEBUILTIN_INT16,
+ /** Unsigned 32bit integer. */
+ DBGFTYPEBUILTIN_UINT32,
+ /** Signed 32bit integer. */
+ DBGFTYPEBUILTIN_INT32,
+ /** Unsigned 64bit integer. */
+ DBGFTYPEBUILTIN_UINT64,
+ /** Signed 64bit integer. */
+ DBGFTYPEBUILTIN_INT64,
+ /** 32bit Guest pointer */
+ DBGFTYPEBUILTIN_PTR32,
+ /** 64bit Guest pointer */
+ DBGFTYPEBUILTIN_PTR64,
+ /** Guest pointer - size depends on the guest bitness */
+ DBGFTYPEBUILTIN_PTR,
+ /** Type indicating a size, like size_t this can have different sizes
+ * on 32bit and 64bit systems */
+ DBGFTYPEBUILTIN_SIZE,
+ /** 32bit float. */
+ DBGFTYPEBUILTIN_FLOAT32,
+ /** 64bit float (also known as double). */
+ DBGFTYPEBUILTIN_FLOAT64,
+ /** Compund types like structs and unions. */
+ DBGFTYPEBUILTIN_COMPOUND,
+ /** The usual 32-bit hack. */
+ DBGFTYPEBUILTIN_32BIT_HACK = 0x7fffffff
+} DBGFTYPEBUILTIN;
+/** Pointer to a built-in type. */
+typedef DBGFTYPEBUILTIN *PDBGFTYPEBUILTIN;
+/** Pointer to a const built-in type. */
+typedef const DBGFTYPEBUILTIN *PCDBGFTYPEBUILTIN;
+
+/**
+ * DBGF type value buffer.
+ */
+typedef union DBGFTYPEVALBUF
+{
+ uint8_t u8;
+ int8_t i8;
+ uint16_t u16;
+ int16_t i16;
+ uint32_t u32;
+ int32_t i32;
+ uint64_t u64;
+ int64_t i64;
+ float f32;
+ double f64;
+ uint64_t size; /* For the built-in size_t which can be either 32-bit or 64-bit. */
+ RTGCPTR GCPtr;
+ /** For embedded structs. */
+ PDBGFTYPEVAL pVal;
+} DBGFTYPEVALBUF;
+/** Pointer to a value. */
+typedef DBGFTYPEVALBUF *PDBGFTYPEVALBUF;
+
+/**
+ * DBGF type value entry.
+ */
+typedef struct DBGFTYPEVALENTRY
+{
+ /** DBGF built-in type. */
+ DBGFTYPEBUILTIN enmType;
+ /** Size of the type. */
+ size_t cbType;
+ /** Number of entries, for arrays this can be > 1. */
+ uint32_t cEntries;
+ /** Value buffer, depends on whether this is an array. */
+ union
+ {
+ /** Single value. */
+ DBGFTYPEVALBUF Val;
+ /** Pointer to the array of values. */
+ PDBGFTYPEVALBUF pVal;
+ } Buf;
+} DBGFTYPEVALENTRY;
+/** Pointer to a type value entry. */
+typedef DBGFTYPEVALENTRY *PDBGFTYPEVALENTRY;
+/** Pointer to a const type value entry. */
+typedef const DBGFTYPEVALENTRY *PCDBGFTYPEVALENTRY;
+
+/**
+ * DBGF typed value.
+ */
+typedef struct DBGFTYPEVAL
+{
+ /** Pointer to the registration structure for this type. */
+ PCDBGFTYPEREG pTypeReg;
+ /** Number of value entries. */
+ uint32_t cEntries;
+ /** Variable sized array of value entries. */
+ DBGFTYPEVALENTRY aEntries[1];
+} DBGFTYPEVAL;
+
+/**
+ * DBGF type variant.
+ */
+typedef enum DBGFTYPEVARIANT
+{
+ /** The usual invalid first value. */
+ DBGFTYPEVARIANT_INVALID,
+ /** A struct. */
+ DBGFTYPEVARIANT_STRUCT,
+ /** Union. */
+ DBGFTYPEVARIANT_UNION,
+ /** Alias for an existing type. */
+ DBGFTYPEVARIANT_ALIAS,
+ /** The usual 32-bit hack. */
+ DBGFTYPEVARIANT_32BIT_HACK = 0x7fffffff
+} DBGFTYPEVARIANT;
+
+/** @name DBGFTYPEREGMEMBER Flags.
+ * @{ */
+/** The member is an array with a fixed size. */
+# define DBGFTYPEREGMEMBER_F_ARRAY RT_BIT_32(0)
+/** The member denotes a pointer. */
+# define DBGFTYPEREGMEMBER_F_POINTER RT_BIT_32(1)
+/** @} */
+
+/**
+ * DBGF type member.
+ */
+typedef struct DBGFTYPEREGMEMBER
+{
+ /** Name of the member. */
+ const char *pszName;
+ /** Flags for this member, see DBGFTYPEREGMEMBER_F_XXX. */
+ uint32_t fFlags;
+ /** Type identifier. */
+ const char *pszType;
+ /** The number of elements in the array, only valid for arrays. */
+ uint32_t cElements;
+} DBGFTYPEREGMEMBER;
+/** Pointer to a member. */
+typedef DBGFTYPEREGMEMBER *PDBGFTYPEREGMEMBER;
+/** Pointer to a const member. */
+typedef const DBGFTYPEREGMEMBER *PCDBGFTYPEREGMEMBER;
+
+/** @name DBGFTYPEREG Flags.
+ * @{ */
+/** The type is a packed structure. */
+# define DBGFTYPEREG_F_PACKED RT_BIT_32(0)
+/** @} */
+
+/**
+ * New type registration structure.
+ */
+typedef struct DBGFTYPEREG
+{
+ /** Name of the type. */
+ const char *pszType;
+ /** The type variant. */
+ DBGFTYPEVARIANT enmVariant;
+ /** Some registration flags, see DBGFTYPEREG_F_XXX. */
+ uint32_t fFlags;
+ /** Number of members this type has, only valid for structs or unions. */
+ uint32_t cMembers;
+ /** Pointer to the member fields, only valid for structs or unions. */
+ PCDBGFTYPEREGMEMBER paMembers;
+ /** Name of the aliased type for aliases. */
+ const char *pszAliasedType;
+} DBGFTYPEREG;
+
+/**
+ * DBGF typed value dumper callback.
+ *
+ * @returns VBox status code. Any non VINF_SUCCESS status code will abort the dumping.
+ *
+ * @param off The byte offset of the entry from the start of the type.
+ * @param pszField The name of the field for the value.
+ * @param iLvl The current level.
+ * @param enmType The type enum.
+ * @param cbType Size of the type.
+ * @param pValBuf Pointer to the value buffer.
+ * @param cValBufs Number of value buffers (for arrays).
+ * @param pvUser Opaque user data.
+ */
+typedef DECLCALLBACKTYPE(int, FNDBGFR3TYPEVALDUMP,(uint32_t off, const char *pszField, uint32_t iLvl,
+ DBGFTYPEBUILTIN enmType, size_t cbType,
+ PDBGFTYPEVALBUF pValBuf, uint32_t cValBufs, void *pvUser));
+/** Pointer to a FNDBGFR3TYPEVALDUMP. */
+typedef FNDBGFR3TYPEVALDUMP *PFNDBGFR3TYPEVALDUMP;
+
+/**
+ * DBGF type information dumper callback.
+ *
+ * @returns VBox status code. Any non VINF_SUCCESS status code will abort the dumping.
+ *
+ * @param off The byte offset of the entry from the start of the type.
+ * @param pszField The name of the field for the value.
+ * @param iLvl The current level.
+ * @param pszType The type of the field.
+ * @param fTypeFlags Flags for this type, see DBGFTYPEREGMEMBER_F_XXX.
+ * @param cElements Number of for the field ( > 0 for arrays).
+ * @param pvUser Opaque user data.
+ */
+typedef DECLCALLBACKTYPE(int, FNDBGFR3TYPEDUMP,(uint32_t off, const char *pszField, uint32_t iLvl,
+ const char *pszType, uint32_t fTypeFlags,
+ uint32_t cElements, void *pvUser));
+/** Pointer to a FNDBGFR3TYPEDUMP. */
+typedef FNDBGFR3TYPEDUMP *PFNDBGFR3TYPEDUMP;
+
+VMMR3DECL(int) DBGFR3TypeRegister( PUVM pUVM, uint32_t cTypes, PCDBGFTYPEREG paTypes);
+VMMR3DECL(int) DBGFR3TypeDeregister(PUVM pUVM, const char *pszType);
+VMMR3DECL(int) DBGFR3TypeQueryReg( PUVM pUVM, const char *pszType, PCDBGFTYPEREG *ppTypeReg);
+
+VMMR3DECL(int) DBGFR3TypeQuerySize( PUVM pUVM, const char *pszType, size_t *pcbType);
+VMMR3DECL(int) DBGFR3TypeSetSize( PUVM pUVM, const char *pszType, size_t cbType);
+VMMR3DECL(int) DBGFR3TypeDumpEx( PUVM pUVM, const char *pszType, uint32_t fFlags,
+ uint32_t cLvlMax, PFNDBGFR3TYPEDUMP pfnDump, void *pvUser);
+VMMR3DECL(int) DBGFR3TypeQueryValByType(PUVM pUVM, PCDBGFADDRESS pAddress, const char *pszType,
+ PDBGFTYPEVAL *ppVal);
+VMMR3DECL(void) DBGFR3TypeValFree(PDBGFTYPEVAL pVal);
+VMMR3DECL(int) DBGFR3TypeValDumpEx(PUVM pUVM, PCDBGFADDRESS pAddress, const char *pszType, uint32_t fFlags,
+ uint32_t cLvlMax, FNDBGFR3TYPEVALDUMP pfnDump, void *pvUser);
+
+/** @} */
+
+
+/** @defgroup grp_dbgf_flow The DBGF control flow graph Interface.
+ * @{
+ */
+
+/** A DBGF control flow graph handle. */
+typedef struct DBGFFLOWINT *DBGFFLOW;
+/** Pointer to a DBGF control flow graph handle. */
+typedef DBGFFLOW *PDBGFFLOW;
+/** A DBGF control flow graph basic block handle. */
+typedef struct DBGFFLOWBBINT *DBGFFLOWBB;
+/** Pointer to a DBGF control flow graph basic block handle. */
+typedef DBGFFLOWBB *PDBGFFLOWBB;
+/** A DBGF control flow graph branch table handle. */
+typedef struct DBGFFLOWBRANCHTBLINT *DBGFFLOWBRANCHTBL;
+/** Pointer to a DBGF flow control graph branch table handle. */
+typedef DBGFFLOWBRANCHTBL *PDBGFFLOWBRANCHTBL;
+/** A DBGF control flow graph iterator. */
+typedef struct DBGFFLOWITINT *DBGFFLOWIT;
+/** Pointer to a control flow graph iterator. */
+typedef DBGFFLOWIT *PDBGFFLOWIT;
+/** A DBGF control flow graph branch table iterator. */
+typedef struct DBGFFLOWBRANCHTBLITINT *DBGFFLOWBRANCHTBLIT;
+/** Pointer to a control flow graph branch table iterator. */
+typedef DBGFFLOWBRANCHTBLIT *PDBGFFLOWBRANCHTBLIT;
+
+/** @name DBGFFLOWBB Flags.
+ * @{ */
+/** The basic block is the entry into the owning control flow graph. */
+#define DBGF_FLOW_BB_F_ENTRY RT_BIT_32(0)
+/** The basic block was not populated because the limit was reached. */
+#define DBGF_FLOW_BB_F_EMPTY RT_BIT_32(1)
+/** The basic block is not complete because an error happened during disassembly. */
+#define DBGF_FLOW_BB_F_INCOMPLETE_ERR RT_BIT_32(2)
+/** The basic block is reached through a branch table. */
+#define DBGF_FLOW_BB_F_BRANCH_TABLE RT_BIT_32(3)
+/** The basic block consists only of a single call instruction because
+ * DBGF_FLOW_CREATE_F_CALL_INSN_SEPARATE_BB was given. */
+#define DBGF_FLOW_BB_F_CALL_INSN RT_BIT_32(4)
+/** The branch target of the call instruction could be deduced and can be queried with
+ * DBGFR3FlowBbGetBranchAddress(). May only be available when DBGF_FLOW_BB_F_CALL_INSN
+ * is set. */
+#define DBGF_FLOW_BB_F_CALL_INSN_TARGET_KNOWN RT_BIT_32(5)
+/** @} */
+
+/** @name Flags controlling the creating of a control flow graph.
+ * @{ */
+/** Default options. */
+#define DBGF_FLOW_CREATE_F_DEFAULT 0
+/** Tries to resolve indirect branches, useful for code using
+ * jump tables generated for large switch statements by some compilers. */
+#define DBGF_FLOW_CREATE_F_TRY_RESOLVE_INDIRECT_BRANCHES RT_BIT_32(0)
+/** Call instructions are placed in a separate basic block. */
+#define DBGF_FLOW_CREATE_F_CALL_INSN_SEPARATE_BB RT_BIT_32(1)
+/** @} */
+
+/**
+ * DBGF control graph basic block end type.
+ */
+typedef enum DBGFFLOWBBENDTYPE
+{
+ /** Invalid type. */
+ DBGFFLOWBBENDTYPE_INVALID = 0,
+ /** Basic block is the exit block and has no successor. */
+ DBGFFLOWBBENDTYPE_EXIT,
+ /** Basic block is the last disassembled block because the
+ * maximum amount to disassemble was reached but is not an
+ * exit block - no successors.
+ */
+ DBGFFLOWBBENDTYPE_LAST_DISASSEMBLED,
+ /** Unconditional control flow change because the successor is referenced by multiple
+ * basic blocks. - 1 successor. */
+ DBGFFLOWBBENDTYPE_UNCOND,
+ /** Unconditional control flow change because of an direct branch - 1 successor. */
+ DBGFFLOWBBENDTYPE_UNCOND_JMP,
+ /** Unconditional control flow change because of an indirect branch - n successors. */
+ DBGFFLOWBBENDTYPE_UNCOND_INDIRECT_JMP,
+ /** Conditional control flow change - 2 successors. */
+ DBGFFLOWBBENDTYPE_COND,
+ /** 32bit hack. */
+ DBGFFLOWBBENDTYPE_32BIT_HACK = 0x7fffffff
+} DBGFFLOWBBENDTYPE;
+
+/**
+ * DBGF control flow graph iteration order.
+ */
+typedef enum DBGFFLOWITORDER
+{
+ /** Invalid order. */
+ DBGFFLOWITORDER_INVALID = 0,
+ /** From lowest to highest basic block start address. */
+ DBGFFLOWITORDER_BY_ADDR_LOWEST_FIRST,
+ /** From highest to lowest basic block start address. */
+ DBGFFLOWITORDER_BY_ADDR_HIGHEST_FIRST,
+ /** Depth first traversing starting from the entry block. */
+ DBGFFLOWITORDER_DEPTH_FRIST,
+ /** Breadth first traversing starting from the entry block. */
+ DBGFFLOWITORDER_BREADTH_FIRST,
+ /** Usual 32bit hack. */
+ DBGFFLOWITORDER_32BIT_HACK = 0x7fffffff
+} DBGFFLOWITORDER;
+/** Pointer to a iteration order enum. */
+typedef DBGFFLOWITORDER *PDBGFFLOWITORDER;
+
+
+VMMR3DECL(int) DBGFR3FlowCreate(PUVM pUVM, VMCPUID idCpu, PDBGFADDRESS pAddressStart, uint32_t cbDisasmMax,
+ uint32_t fFlagsFlow, uint32_t fFlagsDisasm, PDBGFFLOW phFlow);
+VMMR3DECL(uint32_t) DBGFR3FlowRetain(DBGFFLOW hFlow);
+VMMR3DECL(uint32_t) DBGFR3FlowRelease(DBGFFLOW hFlow);
+VMMR3DECL(int) DBGFR3FlowQueryStartBb(DBGFFLOW hFlow, PDBGFFLOWBB phFlowBb);
+VMMR3DECL(int) DBGFR3FlowQueryBbByAddress(DBGFFLOW hFlow, PDBGFADDRESS pAddr, PDBGFFLOWBB phFlowBb);
+VMMR3DECL(int) DBGFR3FlowQueryBranchTblByAddress(DBGFFLOW hFlow, PDBGFADDRESS pAddr, PDBGFFLOWBRANCHTBL phFlowBranchTbl);
+VMMR3DECL(uint32_t) DBGFR3FlowGetBbCount(DBGFFLOW hFlow);
+VMMR3DECL(uint32_t) DBGFR3FlowGetBranchTblCount(DBGFFLOW hFlow);
+VMMR3DECL(uint32_t) DBGFR3FlowGetCallInsnCount(DBGFFLOW hFlow);
+
+VMMR3DECL(uint32_t) DBGFR3FlowBbRetain(DBGFFLOWBB hFlowBb);
+VMMR3DECL(uint32_t) DBGFR3FlowBbRelease(DBGFFLOWBB hFlowBb);
+VMMR3DECL(PDBGFADDRESS) DBGFR3FlowBbGetStartAddress(DBGFFLOWBB hFlowBb, PDBGFADDRESS pAddrStart);
+VMMR3DECL(PDBGFADDRESS) DBGFR3FlowBbGetEndAddress(DBGFFLOWBB hFlowBb, PDBGFADDRESS pAddrEnd);
+VMMR3DECL(PDBGFADDRESS) DBGFR3FlowBbGetBranchAddress(DBGFFLOWBB hFlowBb, PDBGFADDRESS pAddrTarget);
+VMMR3DECL(PDBGFADDRESS) DBGFR3FlowBbGetFollowingAddress(DBGFFLOWBB hFlowBb, PDBGFADDRESS pAddrFollow);
+VMMR3DECL(DBGFFLOWBBENDTYPE) DBGFR3FlowBbGetType(DBGFFLOWBB hFlowBb);
+VMMR3DECL(uint32_t) DBGFR3FlowBbGetInstrCount(DBGFFLOWBB hFlowBb);
+VMMR3DECL(uint32_t) DBGFR3FlowBbGetFlags(DBGFFLOWBB hFlowBb);
+VMMR3DECL(int) DBGFR3FlowBbQueryBranchTbl(DBGFFLOWBB hFlowBb, PDBGFFLOWBRANCHTBL phBranchTbl);
+VMMR3DECL(int) DBGFR3FlowBbQueryError(DBGFFLOWBB hFlowBb, const char **ppszErr);
+VMMR3DECL(int) DBGFR3FlowBbQueryInstr(DBGFFLOWBB hFlowBb, uint32_t idxInstr, PDBGFADDRESS pAddrInstr,
+ uint32_t *pcbInstr, const char **ppszInstr);
+VMMR3DECL(int) DBGFR3FlowBbQuerySuccessors(DBGFFLOWBB hFlowBb, PDBGFFLOWBB phFlowBbFollow,
+ PDBGFFLOWBB phFlowBbTarget);
+VMMR3DECL(uint32_t) DBGFR3FlowBbGetRefBbCount(DBGFFLOWBB hFlowBb);
+VMMR3DECL(int) DBGFR3FlowBbGetRefBb(DBGFFLOWBB hFlowBb, PDBGFFLOWBB pahFlowBbRef, uint32_t cRef);
+
+VMMR3DECL(uint32_t) DBGFR3FlowBranchTblRetain(DBGFFLOWBRANCHTBL hFlowBranchTbl);
+VMMR3DECL(uint32_t) DBGFR3FlowBranchTblRelease(DBGFFLOWBRANCHTBL hFlowBranchTbl);
+VMMR3DECL(uint32_t) DBGFR3FlowBranchTblGetSlots(DBGFFLOWBRANCHTBL hFlowBranchTbl);
+VMMR3DECL(PDBGFADDRESS) DBGFR3FlowBranchTblGetStartAddress(DBGFFLOWBRANCHTBL hFlowBranchTbl, PDBGFADDRESS pAddrStart);
+VMMR3DECL(PDBGFADDRESS) DBGFR3FlowBranchTblGetAddrAtSlot(DBGFFLOWBRANCHTBL hFlowBranchTbl, uint32_t idxSlot, PDBGFADDRESS pAddrSlot);
+VMMR3DECL(int) DBGFR3FlowBranchTblQueryAddresses(DBGFFLOWBRANCHTBL hFlowBranchTbl, PDBGFADDRESS paAddrs, uint32_t cAddrs);
+
+VMMR3DECL(int) DBGFR3FlowItCreate(DBGFFLOW hFlow, DBGFFLOWITORDER enmOrder, PDBGFFLOWIT phFlowIt);
+VMMR3DECL(void) DBGFR3FlowItDestroy(DBGFFLOWIT hFlowIt);
+VMMR3DECL(DBGFFLOWBB) DBGFR3FlowItNext(DBGFFLOWIT hFlowIt);
+VMMR3DECL(int) DBGFR3FlowItReset(DBGFFLOWIT hFlowIt);
+
+VMMR3DECL(int) DBGFR3FlowBranchTblItCreate(DBGFFLOW hFlow, DBGFFLOWITORDER enmOrder, PDBGFFLOWBRANCHTBLIT phFlowBranchTblIt);
+VMMR3DECL(void) DBGFR3FlowBranchTblItDestroy(DBGFFLOWBRANCHTBLIT hFlowBranchTblIt);
+VMMR3DECL(DBGFFLOWBRANCHTBL) DBGFR3FlowBranchTblItNext(DBGFFLOWBRANCHTBLIT hFlowBranchTblIt);
+VMMR3DECL(int) DBGFR3FlowBranchTblItReset(DBGFFLOWBRANCHTBLIT hFlowBranchTblIt);
+
+/** @} */
+
+
+/** @defgroup grp_dbgf_misc Misc DBGF interfaces.
+ * @{ */
+VMMR3DECL(VBOXSTRICTRC) DBGFR3ReportBugCheck(PVM pVM, PVMCPU pVCpu, DBGFEVENTTYPE enmEvent, uint64_t uBugCheck,
+ uint64_t uP1, uint64_t uP2, uint64_t uP3, uint64_t uP4);
+VMMR3DECL(int) DBGFR3FormatBugCheck(PUVM pUVM, char *pszDetails, size_t cbDetails,
+ uint64_t uP0, uint64_t uP1, uint64_t uP2, uint64_t uP3, uint64_t uP4);
+/** @} */
+#endif /* IN_RING3 */
+
+
+/** @defgroup grp_dbgf_tracer DBGF event tracing.
+ * @{ */
+#ifdef IN_RING3
+VMMR3_INT_DECL(int) DBGFR3TracerRegisterEvtSrc(PVM pVM, const char *pszName, PDBGFTRACEREVTSRC phEvtSrc);
+VMMR3_INT_DECL(int) DBGFR3TracerDeregisterEvtSrc(PVM pVM, DBGFTRACEREVTSRC hEvtSrc);
+VMMR3_INT_DECL(int) DBGFR3TracerEvtIoPortCreate(PVM pVM, DBGFTRACEREVTSRC hEvtSrc, uint64_t hRegion, RTIOPORT cPorts, uint32_t fFlags,
+ uint32_t iPciRegion);
+VMMR3_INT_DECL(int) DBGFR3TracerEvtMmioCreate(PVM pVM, DBGFTRACEREVTSRC hEvtSrc, uint64_t hRegion, RTGCPHYS cbRegion, uint32_t fFlags,
+ uint32_t iPciRegion);
+#endif
+
+VMM_INT_DECL(int) DBGFTracerEvtMmioMap(PVMCC pVM, DBGFTRACEREVTSRC hEvtSrc, uint64_t hRegion, RTGCPHYS GCPhysMmio);
+VMM_INT_DECL(int) DBGFTracerEvtMmioUnmap(PVMCC pVM, DBGFTRACEREVTSRC hEvtSrc, uint64_t hRegion);
+VMM_INT_DECL(int) DBGFTracerEvtMmioRead(PVMCC pVM, DBGFTRACEREVTSRC hEvtSrc, uint64_t hRegion, RTGCPHYS offMmio, const void *pvVal, size_t cbVal);
+VMM_INT_DECL(int) DBGFTracerEvtMmioWrite(PVMCC pVM, DBGFTRACEREVTSRC hEvtSrc, uint64_t hRegion, RTGCPHYS offMmio, const void *pvVal, size_t cbVal);
+VMM_INT_DECL(int) DBGFTracerEvtMmioFill(PVMCC pVM, DBGFTRACEREVTSRC hEvtSrc, uint64_t hRegion, RTGCPHYS offMmio, uint32_t u32Item, uint32_t cbItem, uint32_t cItems);
+VMM_INT_DECL(int) DBGFTracerEvtIoPortMap(PVMCC pVM, DBGFTRACEREVTSRC hEvtSrc, uint64_t hIoPorts, RTIOPORT IoPortBase);
+VMM_INT_DECL(int) DBGFTracerEvtIoPortUnmap(PVMCC pVM, DBGFTRACEREVTSRC hEvtSrc, uint64_t hIoPorts);
+VMM_INT_DECL(int) DBGFTracerEvtIoPortRead(PVMCC pVM, DBGFTRACEREVTSRC hEvtSrc, uint64_t hIoPorts, RTIOPORT offPort, const void *pvVal, size_t cbVal);
+VMM_INT_DECL(int) DBGFTracerEvtIoPortReadStr(PVMCC pVM, DBGFTRACEREVTSRC hEvtSrc, uint64_t hIoPorts, RTIOPORT offPort, const void *pv, size_t cb,
+ uint32_t cTransfersReq, uint32_t cTransfersRet);
+VMM_INT_DECL(int) DBGFTracerEvtIoPortWrite(PVMCC pVM, DBGFTRACEREVTSRC hEvtSrc, uint64_t hIoPorts, RTIOPORT offPort, const void *pvVal, size_t cbVal);
+VMM_INT_DECL(int) DBGFTracerEvtIoPortWriteStr(PVMCC pVM, DBGFTRACEREVTSRC hEvtSrc, uint64_t hIoPorts, RTIOPORT offPort, const void *pv, size_t cb,
+ uint32_t cTransfersReq, uint32_t cTransfersRet);
+VMM_INT_DECL(int) DBGFTracerEvtIrq(PVMCC pVM, DBGFTRACEREVTSRC hEvtSrc, int32_t iIrq, int32_t fIrqLvl);
+VMM_INT_DECL(int) DBGFTracerEvtIoApicMsi(PVMCC pVM, DBGFTRACEREVTSRC hEvtSrc, RTGCPHYS GCPhys, uint32_t u32Val);
+VMM_INT_DECL(int) DBGFTracerEvtGCPhysRead(PVMCC pVM, DBGFTRACEREVTSRC hEvtSrc, RTGCPHYS GCPhys, const void *pvBuf, size_t cbRead);
+VMM_INT_DECL(int) DBGFTracerEvtGCPhysWrite(PVMCC pVM, DBGFTRACEREVTSRC hEvtSrc, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite);
+/** @} */
+
+
+/** @defgroup grp_dbgf_sample_report DBGF sample report.
+ * @{ */
+
+/**
+ * Callback which provides progress information about a currently running
+ * lengthy operation.
+ *
+ * @return VBox status code.
+ * @retval VERR_DBGF_CANCELLED to cancel the operation.
+ * @param pvUser The opaque user data associated with this interface.
+ * @param uPercentage Completion percentage.
+ */
+typedef DECLCALLBACKTYPE(int, FNDBGFPROGRESS,(void *pvUser, unsigned uPercentage));
+/** Pointer to FNDBGFPROGRESS() */
+typedef FNDBGFPROGRESS *PFNDBGFPROGRESS;
+
+/** @name Flags to pass to DBGFR3SampleReportCreate().
+ * @{ */
+/** The report creates the call stack in reverse order (bottom to top). */
+#define DBGF_SAMPLE_REPORT_F_STACK_REVERSE RT_BIT(0)
+/** Mask containing the valid flags. */
+#define DBGF_SAMPLE_REPORT_F_VALID_MASK UINT32_C(0x00000001)
+/** @} */
+
+VMMR3DECL(int) DBGFR3SampleReportCreate(PUVM pUVM, uint32_t cSampleIntervalMs, uint32_t fFlags, PDBGFSAMPLEREPORT phSample);
+VMMR3DECL(uint32_t) DBGFR3SampleReportRetain(DBGFSAMPLEREPORT hSample);
+VMMR3DECL(uint32_t) DBGFR3SampleReportRelease(DBGFSAMPLEREPORT hSample);
+VMMR3DECL(int) DBGFR3SampleReportStart(DBGFSAMPLEREPORT hSample, uint64_t cSampleUs, PFNDBGFPROGRESS pfnProgress, void *pvUser);
+VMMR3DECL(int) DBGFR3SampleReportStop(DBGFSAMPLEREPORT hSample);
+VMMR3DECL(int) DBGFR3SampleReportDumpToFile(DBGFSAMPLEREPORT hSample, const char *pszFilename);
+/** @} */
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !VBOX_INCLUDED_vmm_dbgf_h */
+
diff --git a/include/VBox/vmm/dbgfcorefmt.h b/include/VBox/vmm/dbgfcorefmt.h
new file mode 100644
index 00000000..c2b0cd5e
--- /dev/null
+++ b/include/VBox/vmm/dbgfcorefmt.h
@@ -0,0 +1,188 @@
+/** @file
+ * DBGF - Debugger Facility, VM Core File Format.
+ */
+
+/*
+ * Copyright (C) 2010-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vmm_dbgfcorefmt_h
+#define VBOX_INCLUDED_vmm_dbgfcorefmt_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/types.h>
+#include <VBox/vmm/cpumctx.h>
+#include <iprt/assertcompile.h>
+
+
+RT_C_DECLS_BEGIN
+
+
+/** @defgroup grp_dbgf_corefmt VM Core File Format
+ * @ingroup grp_dbgf
+ *
+ * @todo Add description of the core file format and how the structures in this
+ * file relate to it. Point to X86XSAVEAREA in x86.h for the CPU's
+ * FPU/SSE/AVX/XXX state.
+ * @todo Add the note names.
+ *
+ * @{
+ */
+
+/** DBGCORECOREDESCRIPTOR::u32Magic. */
+#define DBGFCORE_MAGIC UINT32_C(0xc01ac0de)
+/** DBGCORECOREDESCRIPTOR::u32FmtVersion. */
+#define DBGFCORE_FMT_VERSION UINT32_C(0x00010006)
+
+/**
+ * An x86 segment selector.
+ */
+typedef struct DBGFCORESEL
+{
+ uint64_t uBase;
+ uint32_t uLimit;
+ uint32_t uAttr;
+ uint16_t uSel;
+ uint16_t uReserved0;
+ uint32_t uReserved1;
+} DBGFCORESEL;
+AssertCompileSizeAlignment(DBGFCORESEL, 8);
+
+/**
+ * A gdtr/ldtr descriptor.
+ */
+typedef struct DBGFCOREXDTR
+{
+ uint64_t uAddr;
+ uint32_t cb;
+ uint32_t uReserved0;
+} DBGFCOREXDTR;
+AssertCompileSizeAlignment(DBGFCOREXDTR, 8);
+
+/**
+ * A simpler to parse CPU dump than CPUMCTX.
+ *
+ * Please bump DBGFCORE_FMT_VERSION by 1 if you make any changes to this
+ * structure.
+ */
+typedef struct DBGFCORECPU
+{
+ uint64_t rax;
+ uint64_t rbx;
+ uint64_t rcx;
+ uint64_t rdx;
+ uint64_t rsi;
+ uint64_t rdi;
+ uint64_t r8;
+ uint64_t r9;
+ uint64_t r10;
+ uint64_t r11;
+ uint64_t r12;
+ uint64_t r13;
+ uint64_t r14;
+ uint64_t r15;
+ uint64_t rip;
+ uint64_t rsp;
+ uint64_t rbp;
+ uint64_t rflags;
+ DBGFCORESEL cs;
+ DBGFCORESEL ds;
+ DBGFCORESEL es;
+ DBGFCORESEL fs;
+ DBGFCORESEL gs;
+ DBGFCORESEL ss;
+ uint64_t cr0;
+ uint64_t cr2;
+ uint64_t cr3;
+ uint64_t cr4;
+ uint64_t dr[8];
+ DBGFCOREXDTR gdtr;
+ DBGFCOREXDTR idtr;
+ DBGFCORESEL ldtr;
+ DBGFCORESEL tr;
+ struct
+ {
+ uint64_t cs;
+ uint64_t eip;
+ uint64_t esp;
+ } sysenter;
+ uint64_t msrEFER;
+ uint64_t msrSTAR;
+ uint64_t msrPAT;
+ uint64_t msrLSTAR;
+ uint64_t msrCSTAR;
+ uint64_t msrSFMASK;
+ uint64_t msrKernelGSBase;
+ uint64_t msrApicBase;
+ uint64_t msrTscAux;
+ uint64_t aXcr[2];
+ uint32_t cbExt;
+ uint32_t uPadding0;
+ X86XSAVEAREA ext;
+} DBGFCORECPU;
+/** Pointer to a DBGF-core CPU. */
+typedef DBGFCORECPU *PDBGFCORECPU;
+/** Pointer to the const DBGF-core CPU. */
+typedef const DBGFCORECPU *PCDBGFCORECPU;
+AssertCompileMemberAlignment(DBGFCORECPU, cr0, 8);
+AssertCompileMemberAlignment(DBGFCORECPU, msrEFER, 8);
+AssertCompileMemberAlignment(DBGFCORECPU, ext, 8);
+AssertCompileSizeAlignment(DBGFCORECPU, 8);
+
+/**
+ * The DBGF Core descriptor.
+ */
+typedef struct DBGFCOREDESCRIPTOR
+{
+ /** The core file magic (DBGFCORE_MAGIC) */
+ uint32_t u32Magic;
+ /** The core file format version (DBGFCORE_FMT_VERSION). */
+ uint32_t u32FmtVersion;
+ /** Size of this structure (sizeof(DBGFCOREDESCRIPTOR)). */
+ uint32_t cbSelf;
+ /** VirtualBox version. */
+ uint32_t u32VBoxVersion;
+ /** VirtualBox revision. */
+ uint32_t u32VBoxRevision;
+ /** Number of CPUs. */
+ uint32_t cCpus;
+} DBGFCOREDESCRIPTOR;
+AssertCompileSizeAlignment(DBGFCOREDESCRIPTOR, 8);
+/** Pointer to DBGFCOREDESCRIPTOR data. */
+typedef DBGFCOREDESCRIPTOR *PDBGFCOREDESCRIPTOR;
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !VBOX_INCLUDED_vmm_dbgfcorefmt_h */
+
diff --git a/include/VBox/vmm/dbgfflowtrace.h b/include/VBox/vmm/dbgfflowtrace.h
new file mode 100644
index 00000000..4906fe7e
--- /dev/null
+++ b/include/VBox/vmm/dbgfflowtrace.h
@@ -0,0 +1,400 @@
+/** @file
+ * DBGF - Debugger Facility, Guest execution flow tracing.
+ */
+
+/*
+ * Copyright (C) 2020-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vmm_dbgfflowtrace_h
+#define VBOX_INCLUDED_vmm_dbgfflowtrace_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/types.h>
+#include <VBox/vmm/dbgf.h>
+
+RT_C_DECLS_BEGIN
+/** @defgroup grp_dbgf_flowtrace Guest Execution Flow Tracing
+ * @ingroup grp_dbgf
+ *
+ * @{
+ */
+
+/** A DBGF flow trace module handle. */
+typedef struct DBGFFLOWTRACEMODINT *DBGFFLOWTRACEMOD;
+/** Pointer to a DBGF flow trace module handle. */
+typedef DBGFFLOWTRACEMOD *PDBGFFLOWTRACEMOD;
+/** A DBGF flow trace probe handle. */
+typedef struct DBGFFLOWTRACEPROBEINT *DBGFFLOWTRACEPROBE;
+/** Pointer to a DBGF flow trace state probe handle. */
+typedef DBGFFLOWTRACEPROBE *PDBGFFLOWTRACEPROBE;
+/** A DBGF flow trace report handle. */
+typedef struct DBGFFLOWTRACEREPORTINT *DBGFFLOWTRACEREPORT;
+/** Pointer to a DBGF flow trace report handle. */
+typedef DBGFFLOWTRACEREPORT *PDBGFFLOWTRACEREPORT;
+/** A DBGF flow trace record handle. */
+typedef struct DBGFFLOWTRACERECORDINT *DBGFFLOWTRACERECORD;
+/** Pointer to a DBGF flow trace record handle. */
+typedef DBGFFLOWTRACERECORD *PDBGFFLOWTRACERECORD;
+
+
+/** Pointer to a flow trace probe entry. */
+typedef struct DBGFFLOWTRACEPROBEENTRY *PDBGFFLOWTRACEPROBEENTRY;
+/** Pointer to a const flow trace probe entry. */
+typedef const struct DBGFFLOWTRACEPROBEENTRY *PCDBGFFLOWTRACEPROBEENTRY;
+
+/** @name Flags controlling the type of the addition of a single probe.
+ * @{ */
+/** Default options. */
+#define DBGF_FLOW_TRACE_PROBE_ADD_F_DEFAULT DBGF_FLOW_TRACE_PROBE_ADD_F_BEFORE_EXEC
+/** Collects the data specified by the data probe before the instruction is executed. */
+#define DBGF_FLOW_TRACE_PROBE_ADD_F_BEFORE_EXEC RT_BIT_32(0)
+/** Collects the data specified by the data probe after the instruction was executed. */
+#define DBGF_FLOW_TRACE_PROBE_ADD_F_AFTER_EXEC RT_BIT_32(1)
+/** Mask of all valid flags. */
+#define DBGF_FLOW_TRACE_PROBE_ADD_F_VALID_MASK ( DBGF_FLOW_TRACE_PROBE_ADD_F_BEFORE_EXEC \
+ | DBGF_FLOW_TRACE_PROBE_ADD_F_AFTER_EXEC)
+/** @} */
+
+
+/**
+ * Probe entry type.
+ */
+typedef enum DBGFFLOWTRACEPROBEENTRYTYPE
+{
+ /** Invalid type. */
+ DBGFFLOWTRACEPROBEENTRYTYPE_INVALID = 0,
+ /** Register. */
+ DBGFFLOWTRACEPROBEENTRYTYPE_REG,
+ /** Constant memory buffer pointer. */
+ DBGFFLOWTRACEPROBEENTRYTYPE_CONST_MEM,
+ /** Indirect memory buffer pointer, obtained from the base and index register
+ * and a constant scale. */
+ DBGFFLOWTRACEPROBEENTRYTYPE_INDIRECT_MEM,
+ /** Callback. */
+ DBGFFLOWTRACEPROBEENTRYTYPE_CALLBACK,
+ /** Halt in the debugger when the entry is collected. */
+ DBGFFLOWTRACEPROBEENTRYTYPE_DEBUGGER,
+ /** 32bit hack. */
+ DBGFFLOWTRACEPROBEENTRYTYPE_32BIT_HACK = 0x7fffffff
+} DBGFFLOWTRACEPROBEENTRYTYPE;
+
+
+/**
+ * Register descriptor for a probe entry.
+ */
+typedef struct DBGFFLOWTRACEPROBEENTRYREG
+{
+ /** The register name - see DBGFR3RegNm*. */
+ const char *pszName;
+ /** The size of the value in bytes. */
+ DBGFREGVALTYPE enmType;
+} DBGFFLOWTRACEPROBEENTRYREG;
+/** Pointer to data probe register entry. */
+typedef DBGFFLOWTRACEPROBEENTRYREG *PDBGFFLOWTRACEPROBEENTRYREG;
+/** Pointer to a const probe register entry. */
+typedef const DBGFFLOWTRACEPROBEENTRYREG *PCDBGFFLOWTRACEPROBEENTRYREG;
+
+
+/**
+ * Flow trace probe callback.
+ *
+ * @returns VBox status code, any error aborts continuing fetching the data for the
+ * probe containing this callback.
+ * @param pUVM The usermode VM handle.
+ * @param idCpu The ID of the vCPU the probe as fired.
+ * @param hFlowTraceMod The handle to the flow trace module the probe was fired for.
+ * @param pAddrProbe The guest address the probe was fired at.
+ * @param hFlowTraceProbe The flow trace probe handle.this callback is in.
+ * @param pProbeEntry The probe entry this callback is part of.
+ * @param pvUser The opaque user data for the callback.
+ */
+typedef DECLCALLBACKTYPE(int, FNDBGFFLOWTRACEPROBECALLBACK, (PUVM pUVM, VMCPUID idCpu, DBGFFLOWTRACEMOD hFlowTraceMod,
+ PCDBGFADDRESS pAddrProbe, DBGFFLOWTRACEPROBE hFlowTraceProbe,
+ PCDBGFFLOWTRACEPROBEENTRY pProbeEntry,
+ void *pvUser));
+/** Pointer to a flow trace probe callback. */
+typedef FNDBGFFLOWTRACEPROBECALLBACK *PFNDBGFFLOWTRACEPROBECALLBACK;
+
+
+/**
+ * Trace flow probe entry.
+ */
+typedef struct DBGFFLOWTRACEPROBEENTRY
+{
+ /** Entry type. */
+ DBGFFLOWTRACEPROBEENTRYTYPE enmType;
+ /** Description for this entry, optional. */
+ const char *pszDesc;
+ /** The data based on the entry type. */
+ union
+ {
+ /** Register. */
+ DBGFFLOWTRACEPROBEENTRYREG Reg;
+ /** Constant memory pointer. */
+ struct
+ {
+ /** The address of the memory buffer. */
+ DBGFADDRESS AddrMem;
+ /** Number of bytes to log. */
+ size_t cbMem;
+ } ConstMem;
+ /** Indirect memory */
+ struct
+ {
+ /** The base register. */
+ DBGFFLOWTRACEPROBEENTRYREG RegBase;
+ /** The index register. */
+ DBGFFLOWTRACEPROBEENTRYREG RegIndex;
+ /** The scale to apply to the index. */
+ uint8_t uScale;
+ /** A constant offset which is applied at the end. */
+ RTGCINTPTR iOffset;
+ /** Number of bytes to log. */
+ size_t cbMem;
+ } IndirectMem;
+ /** Callback. */
+ struct
+ {
+ /** The callback to call. */
+ PFNDBGFFLOWTRACEPROBECALLBACK pfnCallback;
+ /** The opaque user data to provide. */
+ void *pvUser;
+ } Callback;
+ } Type;
+} DBGFFLOWTRACEPROBEENTRY;
+
+
+/**
+ * Flow trace probe value.
+ */
+typedef struct DBGFFLOWTRACEPROBEVAL
+{
+ /** Pointer to the flow trace probe entry this value is for. */
+ PCDBGFFLOWTRACEPROBEENTRY pProbeEntry;
+ /** Data based on the type in the entry. */
+ union
+ {
+ /** Register value. */
+ DBGFREGENTRYNM Reg;
+ /** Memory value (constant pointer or indirect). */
+ struct
+ {
+ /** The guest address logged. */
+ DBGFADDRESS Addr;
+ /** Pointer to the data logged. */
+ const void *pvBuf;
+ /** Number of bytes logged. */
+ size_t cbBuf;
+ } Mem;
+ } Type;
+} DBGFFLOWTRACEPROBEVAL;
+/** Pointer to a flow trace probe value. */
+typedef DBGFFLOWTRACEPROBEVAL *PDBGFFLOWTRACEPROBEVAL;
+/** Pointer to a const flow trace probe value. */
+typedef const DBGFFLOWTRACEPROBEVAL *PCDBGFFLOWTRACEPROBEVAL;
+
+/**
+ * Flow trace report filter operation.
+ */
+typedef enum DBGFFLOWTRACEREPORTFILTEROP
+{
+ /** Invalid filter operation. */
+ DBGFFLOWTRACEREPORTFILTEROP_INVALID = 0,
+ /** All filters must match with the record. */
+ DBGFFLOWTRACEREPORTFILTEROP_AND,
+ /** Only one filter must match with the record. */
+ DBGFFLOWTRACEREPORTFILTEROP_OR,
+ /** 32bit hack. */
+ DBGFFLOWTRACEREPORTFILTEROP_32BIT_HACK = 0x7fffffff
+} DBGFFLOWTRACEREPORTFILTEROP;
+
+
+/**
+ * Flow trace report filter type.
+ */
+typedef enum DBGFFLOWTRACEREPORTFILTERTYPE
+{
+ /** Invalid filter type. */
+ DBGFFLOWTRACEREPORTFILTERTYPE_INVALID = 0,
+ /** Filter by sequence number. */
+ DBGFFLOWTRACEREPORTFILTERTYPE_SEQ_NUM,
+ /** Filter by timestamp. */
+ DBGFFLOWTRACEREPORTFILTERTYPE_TIMESTAMP,
+ /** Filter by probe address. */
+ DBGFFLOWTRACEREPORTFILTERTYPE_ADDR,
+ /** Filter by CPU ID. */
+ DBGFFLOWTRACEREPORTFILTERTYPE_VMCPU_ID,
+ /** Filter by specific probe data. */
+ DBGFFLOWTRACEREPORTFILTERTYPE_PROBE_DATA,
+ /** 32bit hack. */
+ DBGFFLOWTRACEREPORTFILTERTYPE_32BIT_HACK = 0x7fffffff
+} DBGFFLOWTRACEREPORTFILTERTYPE;
+
+
+/**
+ * Flow trace report filter.
+ */
+typedef struct DBGFFLOWTRACEREPORTFILTER
+{
+ /** Filter type. */
+ DBGFFLOWTRACEREPORTFILTERTYPE enmType;
+ /** Filter data, type dependent. */
+ struct
+ {
+ /** Sequence number filtering. */
+ struct
+ {
+ /** Sequence number filtering, start value. */
+ uint64_t u64SeqNoFirst;
+ /** Sequence number filtering, last value. */
+ uint64_t u64SeqNoLast;
+ } SeqNo;
+ /** Timestamp filtering. */
+ struct
+ {
+ /** Start value. */
+ uint64_t u64TsFirst;
+ /** Last value. */
+ uint64_t u64TsLast;
+ } Timestamp;
+ /** Probe address filtering. */
+ struct
+ {
+ /** Start address. */
+ DBGFADDRESS AddrStart;
+ /** Last address. */
+ DBGFADDRESS AddrLast;
+ } Addr;
+ /** vCPU id filtering. */
+ struct
+ {
+ /** Start CPU id. */
+ VMCPUID idCpuStart;
+ /** Last CPU id. */
+ VMCPUID idCpuLast;
+ } VCpuId;
+ /** Probe data filtering. */
+ struct
+ {
+ /** Pointer to the probe value array. */
+ PCDBGFFLOWTRACEPROBEVAL paVal;
+ /** Number of entries in the array for filtering. */
+ uint32_t cVals;
+ /** Flag whether to look into the common values or the probe specific ones. */
+ bool fValCmn;
+ } ProbeData;
+ } Type;
+} DBGFFLOWTRACEREPORTFILTER;
+/** Pointer to a flow trace report filter. */
+typedef DBGFFLOWTRACEREPORTFILTER *PDBGFFLOWTRACEREPORTFILTER;
+
+
+/** @name Flags controlling filtering records.
+ * @{ */
+/** Add records which don't match the filter. */
+#define DBGF_FLOW_TRACE_REPORT_FILTER_F_REVERSE RT_BIT_32(0)
+/** Mask of all valid flags. */
+#define DBGF_FLOW_TRACE_REPORT_FILTER_F_VALID (DBGF_FLOW_TRACE_REPORT_FILTER_F_REVERSE)
+/** @} */
+
+
+/**
+ * Flow trace report enumeration callback.
+ *
+ * @returns VBox status code, any non VINF_SUCCESS code aborts the enumeration and is returned
+ * by DBGFR3FlowTraceReportEnumRecords().
+ * @param hFlowTraceReport The flow trace report handle being enumerated.
+ * @param hFlowTraceRecord The flow trace record handle.
+ * @param pvUser Opaque user data given in DBGFR3FlowTraceReportEnumRecords().
+ */
+typedef DECLCALLBACKTYPE(int, FNDBGFFLOWTRACEREPORTENUMCLBK,(DBGFFLOWTRACEREPORT hFlowTraceReport,
+ DBGFFLOWTRACERECORD hFlowTraceRecord,
+ void *pvUser));
+/** Pointer to a record enumeration callback. */
+typedef FNDBGFFLOWTRACEREPORTENUMCLBK *PFNDBGFFLOWTRACEREPORTENUMCLBK;
+
+
+VMMR3DECL(int) DBGFR3FlowTraceModCreate(PUVM pUVM, VMCPUID idCpu,
+ DBGFFLOWTRACEPROBE hFlowTraceProbeCommon,
+ PDBGFFLOWTRACEMOD phFlowTraceMod);
+VMMR3DECL(int) DBGFR3FlowTraceModCreateFromFlowGraph(PUVM pUVM, VMCPUID idCpu, DBGFFLOW hFlow,
+ DBGFFLOWTRACEPROBE hFlowTraceProbeCommon,
+ DBGFFLOWTRACEPROBE hFlowTraceProbeEntry,
+ DBGFFLOWTRACEPROBE hFlowTraceProbeRegular,
+ DBGFFLOWTRACEPROBE hFlowTraceProbeExit,
+ PDBGFFLOWTRACEMOD phFlowTraceMod);
+VMMR3DECL(uint32_t) DBGFR3FlowTraceModRetain(DBGFFLOWTRACEMOD hFlowTraceMod);
+VMMR3DECL(uint32_t) DBGFR3FlowTraceModRelease(DBGFFLOWTRACEMOD hFlowTraceMod);
+VMMR3DECL(int) DBGFR3FlowTraceModEnable(DBGFFLOWTRACEMOD hFlowTraceMod, uint32_t cHits, uint32_t cRecordsMax);
+VMMR3DECL(int) DBGFR3FlowTraceModDisable(DBGFFLOWTRACEMOD hFlowTraceMod);
+VMMR3DECL(int) DBGFR3FlowTraceModQueryReport(DBGFFLOWTRACEMOD hFlowTraceMod,
+ PDBGFFLOWTRACEREPORT phFlowTraceReport);
+VMMR3DECL(int) DBGFR3FlowTraceModClear(DBGFFLOWTRACEMOD hFlowTraceMod);
+VMMR3DECL(int) DBGFR3FlowTraceModAddProbe(DBGFFLOWTRACEMOD hFlowTraceMod, PCDBGFADDRESS pAddrProbe,
+ DBGFFLOWTRACEPROBE hFlowTraceProbe, uint32_t fFlags);
+
+VMMR3DECL(int) DBGFR3FlowTraceProbeCreate(PUVM pUVM, const char *pszDescr, PDBGFFLOWTRACEPROBE phFlowTraceProbe);
+VMMR3DECL(uint32_t) DBGFR3FlowTraceProbeRetain(DBGFFLOWTRACEPROBE hFlowTraceProbe);
+VMMR3DECL(uint32_t) DBGFR3FlowTraceProbeRelease(DBGFFLOWTRACEPROBE hFlowTraceProbe);
+VMMR3DECL(int) DBGFR3FlowTraceProbeEntriesAdd(DBGFFLOWTRACEPROBE hFlowTraceProbe,
+ PCDBGFFLOWTRACEPROBEENTRY paEntries, uint32_t cEntries);
+
+VMMR3DECL(uint32_t) DBGFR3FlowTraceReportRetain(DBGFFLOWTRACEREPORT hFlowTraceReport);
+VMMR3DECL(uint32_t) DBGFR3FlowTraceReportRelease(DBGFFLOWTRACEREPORT hFlowTraceReport);
+VMMR3DECL(uint32_t) DBGFR3FlowTraceReportGetRecordCount(DBGFFLOWTRACEREPORT hFlowTraceReport);
+VMMR3DECL(int) DBGFR3FlowTraceReportQueryRecord(DBGFFLOWTRACEREPORT hFlowTraceReport, uint32_t idxRec, PDBGFFLOWTRACERECORD phFlowTraceRec);
+VMMR3DECL(int) DBGFR3FlowTraceReportQueryFiltered(DBGFFLOWTRACEREPORT hFlowTraceReport, uint32_t fFlags,
+ PDBGFFLOWTRACEREPORTFILTER paFilters, uint32_t cFilters,
+ DBGFFLOWTRACEREPORTFILTEROP enmOp,
+ PDBGFFLOWTRACEREPORT phFlowTraceReportFiltered);
+VMMR3DECL(int) DBGFR3FlowTraceReportEnumRecords(DBGFFLOWTRACEREPORT hFlowTraceReport,
+ PFNDBGFFLOWTRACEREPORTENUMCLBK pfnEnum,
+ void *pvUser);
+
+VMMR3DECL(uint32_t) DBGFR3FlowTraceRecordRetain(DBGFFLOWTRACERECORD hFlowTraceRecord);
+VMMR3DECL(uint32_t) DBGFR3FlowTraceRecordRelease(DBGFFLOWTRACERECORD hFlowTraceRecord);
+VMMR3DECL(uint64_t) DBGFR3FlowTraceRecordGetSeqNo(DBGFFLOWTRACERECORD hFlowTraceRecord);
+VMMR3DECL(uint64_t) DBGFR3FlowTraceRecordGetTimestamp(DBGFFLOWTRACERECORD hFlowTraceRecord);
+VMMR3DECL(PDBGFADDRESS) DBGFR3FlowTraceRecordGetAddr(DBGFFLOWTRACERECORD hFlowTraceRecord, PDBGFADDRESS pAddr);
+VMMR3DECL(DBGFFLOWTRACEPROBE) DBGFR3FlowTraceRecordGetProbe(DBGFFLOWTRACERECORD hFlowTraceRecord);
+VMMR3DECL(uint32_t) DBGFR3FlowTraceRecordGetValCount(DBGFFLOWTRACERECORD hFlowTraceRecord);
+VMMR3DECL(uint32_t) DBGFR3FlowTraceRecordGetValCommonCount(DBGFFLOWTRACERECORD hFlowTraceRecord);
+VMMR3DECL(PCDBGFFLOWTRACEPROBEVAL) DBGFR3FlowTraceRecordGetVals(DBGFFLOWTRACERECORD hFlowTraceRecord);
+VMMR3DECL(PCDBGFFLOWTRACEPROBEVAL) DBGFR3FlowTraceRecordGetValsCommon(DBGFFLOWTRACERECORD hFlowTraceRecord);
+VMMR3DECL(VMCPUID) DBGFR3FlowTraceRecordGetCpuId(DBGFFLOWTRACERECORD hFlowTraceRecord);
+
+/** @} */
+RT_C_DECLS_END
+
+#endif /* !VBOX_INCLUDED_vmm_dbgfflowtrace_h */
+
diff --git a/include/VBox/vmm/dbgfsel.h b/include/VBox/vmm/dbgfsel.h
new file mode 100644
index 00000000..a531ec6f
--- /dev/null
+++ b/include/VBox/vmm/dbgfsel.h
@@ -0,0 +1,117 @@
+/** @file
+ * DBGF - Debugger Facility, selector interface partly shared with SELM.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vmm_dbgfsel_h
+#define VBOX_INCLUDED_vmm_dbgfsel_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/types.h>
+#include <iprt/x86.h>
+
+
+/** @addtogroup grp_dbgf
+ * @{ */
+
+/**
+ * Selector information structure.
+ */
+typedef struct DBGFSELINFO
+{
+ /** The base address.
+ * For gate descriptors, this is the target address. */
+ RTGCPTR GCPtrBase;
+ /** The limit (-1).
+ * For gate descriptors, this is set to zero. */
+ RTGCUINTPTR cbLimit;
+ /** The raw descriptor. */
+ union
+ {
+ X86DESC Raw;
+ X86DESC64 Raw64;
+ } u;
+ /** The selector. */
+ RTSEL Sel;
+ /** The target selector for a gate.
+ * This is 0 if non-gate descriptor. */
+ RTSEL SelGate;
+ /** Flags. */
+ uint32_t fFlags;
+} DBGFSELINFO;
+/** Pointer to a SELM selector information struct. */
+typedef DBGFSELINFO *PDBGFSELINFO;
+/** Pointer to a const SELM selector information struct. */
+typedef const DBGFSELINFO *PCDBGFSELINFO;
+
+/** @name DBGFSELINFO::fFlags
+ * @{ */
+/** The CPU is in real mode. */
+#define DBGFSELINFO_FLAGS_REAL_MODE RT_BIT_32(0)
+/** The CPU is in protected mode. */
+#define DBGFSELINFO_FLAGS_PROT_MODE RT_BIT_32(1)
+/** The CPU is in long mode. */
+#define DBGFSELINFO_FLAGS_LONG_MODE RT_BIT_32(2)
+/** The selector is a hyper selector.
+ * @todo remove me! */
+#define DBGFSELINFO_FLAGS_HYPER RT_BIT_32(3)
+/** The selector is a gate selector. */
+#define DBGFSELINFO_FLAGS_GATE RT_BIT_32(4)
+/** The selector is invalid. */
+#define DBGFSELINFO_FLAGS_INVALID RT_BIT_32(5)
+/** The selector not present. */
+#define DBGFSELINFO_FLAGS_NOT_PRESENT RT_BIT_32(6)
+/** @} */
+
+
+/**
+ * Tests whether the selector info describes an expand-down selector or now.
+ *
+ * @returns true / false.
+ * @param pSelInfo The selector info.
+ */
+DECLINLINE(bool) DBGFSelInfoIsExpandDown(PCDBGFSELINFO pSelInfo)
+{
+ return (pSelInfo)->u.Raw.Gen.u1DescType
+ && ((pSelInfo)->u.Raw.Gen.u4Type & (X86_SEL_TYPE_DOWN | X86_SEL_TYPE_CODE)) == X86_SEL_TYPE_DOWN;
+}
+
+
+VMMR3DECL(int) DBGFR3SelInfoValidateCS(PCDBGFSELINFO pSelInfo, RTSEL SelCPL);
+
+/** @} */
+
+#endif /* !VBOX_INCLUDED_vmm_dbgfsel_h */
+
diff --git a/include/VBox/vmm/dbgftrace.h b/include/VBox/vmm/dbgftrace.h
new file mode 100644
index 00000000..254cc677
--- /dev/null
+++ b/include/VBox/vmm/dbgftrace.h
@@ -0,0 +1,168 @@
+/** @file
+ * DBGF - Debugger Facility.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vmm_dbgftrace_h
+#define VBOX_INCLUDED_vmm_dbgftrace_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/trace.h>
+#include <VBox/types.h>
+
+RT_C_DECLS_BEGIN
+/** @defgroup grp_dbgf_trace Tracing
+ * @ingroup grp_dbgf
+ *
+ * @{
+ */
+
+#if (defined(RTTRACE_ENABLED) || defined(DBGFTRACE_ENABLED)) && !defined(DBGFTRACE_DISABLED)
+# undef DBGFTRACE_ENABLED
+# undef DBGFTRACE_DISABLED
+# define DBGFTRACE_ENABLED
+#else
+# undef DBGFTRACE_ENABLED
+# undef DBGFTRACE_DISABLED
+# define DBGFTRACE_DISABLED
+#endif
+
+VMMDECL(int) DBGFR3TraceConfig(PVM pVM, const char *pszConfig);
+
+
+/** @name VMM Internal Trace Macros
+ * @remarks The user of these macros is responsible of including VBox/vmm/vm.h.
+ * @{
+ */
+/**
+ * Records a 64-bit unsigned integer together with a tag string.
+ */
+#ifdef DBGFTRACE_ENABLED
+# define DBGFTRACE_U64_TAG(a_pVM, a_u64, a_pszTag) \
+ do { RTTraceBufAddMsgF((a_pVM)->CTX_SUFF(hTraceBuf), "%'llu %s", (a_u64), (a_pszTag)); } while (0)
+#else
+# define DBGFTRACE_U64_TAG(a_pVM, a_u64, a_pszTag) do { } while (0)
+#endif
+
+/**
+ * Records a 64-bit unsigned integer together with two tag strings.
+ */
+#ifdef DBGFTRACE_ENABLED
+# define DBGFTRACE_U64_TAG2(a_pVM, a_u64, a_pszTag1, a_pszTag2) \
+ do { RTTraceBufAddMsgF((a_pVM)->CTX_SUFF(hTraceBuf), "%'llu %s %s", (a_u64), (a_pszTag1), (a_pszTag2)); } while (0)
+#else
+# define DBGFTRACE_U64_TAG2(a_pVM, a_u64, a_pszTag1, a_pszTag2) do { } while (0)
+#endif
+
+#ifdef RT_COMPILER_SUPPORTS_VA_ARGS
+/**
+ * Add a custom string (req. variadict macro support).
+ */
+# ifdef DBGFTRACE_ENABLED
+# define DBGFTRACE_CUSTOM(a_pVM, ...) \
+ do { RTTraceBufAddMsgF((a_pVM)->CTX_SUFF(hTraceBuf), __VA_ARGS__); } while (0)
+# else
+# define DBGFTRACE_CUSTOM(a_pVM, ...) do { } while (0)
+# endif
+#endif
+
+/**
+ * Records the current source position.
+ */
+#ifdef DBGFTRACE_ENABLED
+# define DBGFTRACE_POS(a_pVM) \
+ do { RTTraceBufAddPos((a_pVM)->CTX_SUFF(hTraceBuf), RT_SRC_POS); } while (0)
+#else
+# define DBGFTRACE_POS(a_pVM) do { } while (0)
+#endif
+
+/**
+ * Records the current source position along with a 64-bit unsigned integer.
+ */
+#ifdef DBGFTRACE_ENABLED
+# define DBGFTRACE_POS_U64(a_pVM, a_u64) \
+ do { RTTraceBufAddPosMsgF((a_pVM)->CTX_SUFF(hTraceBuf), RT_SRC_POS, "%'llu", (a_u64)); } while (0)
+#else
+# define DBGFTRACE_POS_U64(a_pVM, a_u64) do { } while (0)
+#endif
+/** @} */
+
+
+/** @name Tracing Macros for PDM Devices, Drivers and USB Devices.
+ * @{
+ */
+
+/**
+ * Get the trace buffer handle.
+ * @param a_pIns The instance (pDevIns, pDrvIns or pUsbIns).
+ */
+#define DBGFTRACE_PDM_TRACEBUF(a_pIns) ( (a_pIns)->CTX_SUFF(pHlp)->pfnDBGFTraceBuf((a_pIns)) )
+
+/**
+ * Records a tagged 64-bit unsigned integer.
+ */
+#ifdef DBGFTRACE_ENABLED
+# define DBGFTRACE_PDM_U64_TAG(a_pIns, a_u64, a_pszTag) \
+ do { RTTraceBufAddMsgF(DBGFTRACE_PDM_TRACEBUF(a_pIns), "%'llu %s", (a_u64), (a_pszTag)); } while (0)
+#else
+# define DBGFTRACE_PDM_U64_TAG(a_pIns, a_u64, a_pszTag) do { } while (0)
+#endif
+
+/**
+ * Records the current source position.
+ */
+#ifdef DBGFTRACE_ENABLED
+# define DBGFTRACE_PDM_POS(a_pIns) \
+ do { RTTraceBufAddPos(DBGFTRACE_PDM_TRACEBUF(a_pIns), RT_SRC_POS); } while (0)
+#else
+# define DBGFTRACE_PDM_POS(a_pIns) do { } while (0)
+#endif
+
+/**
+ * Records the current source position along with a 64-bit unsigned integer.
+ */
+#ifdef DBGFTRACE_ENABLED
+# define DBGFTRACE_PDM_POS_U64(a_pIns, a_u64) \
+ do { RTTraceBufAddPosMsgF(DBGFTRACE_PDM_TRACEBUF(a_pIns), RT_SRC_POS, "%'llu", (a_u64)); } while (0)
+#else
+# define DBGFTRACE_PDM_POS_U64(a_pIns, a_u64) do { } while (0)
+#endif
+/** @} */
+
+
+/** @} */
+RT_C_DECLS_END
+
+#endif /* !VBOX_INCLUDED_vmm_dbgftrace_h */
diff --git a/include/VBox/vmm/em.h b/include/VBox/vmm/em.h
new file mode 100644
index 00000000..6ea1b65e
--- /dev/null
+++ b/include/VBox/vmm/em.h
@@ -0,0 +1,345 @@
+/** @file
+ * EM - Execution Monitor.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vmm_em_h
+#define VBOX_INCLUDED_vmm_em_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/types.h>
+#include <VBox/vmm/trpm.h>
+#include <VBox/vmm/vmapi.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_em The Execution Monitor / Manager API
+ * @ingroup grp_vmm
+ * @{
+ */
+
+/** Enable to allow V86 code to run in raw mode. */
+#define VBOX_RAW_V86
+
+/**
+ * The Execution Manager State.
+ *
+ * @remarks This is used in the saved state!
+ */
+typedef enum EMSTATE
+{
+ /** Not yet started. */
+ EMSTATE_NONE = 1,
+ /** Raw-mode execution. */
+ EMSTATE_RAW,
+ /** Hardware accelerated raw-mode execution. */
+ EMSTATE_HM,
+ /** Executing in IEM. */
+ EMSTATE_IEM,
+ /** Recompiled mode execution. */
+ EMSTATE_REM,
+ /** Execution is halted. (waiting for interrupt) */
+ EMSTATE_HALTED,
+ /** Application processor execution is halted. (waiting for startup IPI (SIPI)) */
+ EMSTATE_WAIT_SIPI,
+ /** Execution is suspended. */
+ EMSTATE_SUSPENDED,
+ /** The VM is terminating. */
+ EMSTATE_TERMINATING,
+ /** Guest debug event from raw-mode is being processed. */
+ EMSTATE_DEBUG_GUEST_RAW,
+ /** Guest debug event from hardware accelerated mode is being processed. */
+ EMSTATE_DEBUG_GUEST_HM,
+ /** Guest debug event from interpreted execution mode is being processed. */
+ EMSTATE_DEBUG_GUEST_IEM,
+ /** Guest debug event from recompiled-mode is being processed. */
+ EMSTATE_DEBUG_GUEST_REM,
+ /** Hypervisor debug event being processed. */
+ EMSTATE_DEBUG_HYPER,
+ /** The VM has encountered a fatal error. (And everyone is panicing....) */
+ EMSTATE_GURU_MEDITATION,
+ /** Executing in IEM, falling back on REM if we cannot switch back to HM or
+ * RAW after a short while. */
+ EMSTATE_IEM_THEN_REM,
+ /** Executing in native (API) execution monitor. */
+ EMSTATE_NEM,
+ /** Guest debug event from NEM mode is being processed. */
+ EMSTATE_DEBUG_GUEST_NEM,
+ /** Just a hack to ensure that we get a 32-bit integer. */
+ EMSTATE_MAKE_32BIT_HACK = 0x7fffffff
+} EMSTATE;
+
+
+/**
+ * EMInterpretInstructionCPU execution modes.
+ */
+typedef enum
+{
+ /** Only supervisor code (CPL=0). */
+ EMCODETYPE_SUPERVISOR,
+ /** User-level code only. */
+ EMCODETYPE_USER,
+ /** Supervisor and user-level code (use with great care!). */
+ EMCODETYPE_ALL,
+ /** Just a hack to ensure that we get a 32-bit integer. */
+ EMCODETYPE_32BIT_HACK = 0x7fffffff
+} EMCODETYPE;
+
+VMM_INT_DECL(EMSTATE) EMGetState(PVMCPU pVCpu);
+VMM_INT_DECL(void) EMSetState(PVMCPU pVCpu, EMSTATE enmNewState);
+
+/** @name Callback handlers for instruction emulation functions.
+ * These are placed here because IOM wants to use them as well.
+ * @{
+ */
+typedef DECLCALLBACKTYPE(uint32_t, FNEMULATEPARAM2UINT32,(void *pvParam1, uint64_t val2));
+typedef FNEMULATEPARAM2UINT32 *PFNEMULATEPARAM2UINT32;
+typedef DECLCALLBACKTYPE(uint32_t, FNEMULATEPARAM2,(void *pvParam1, size_t val2));
+typedef FNEMULATEPARAM2 *PFNEMULATEPARAM2;
+typedef DECLCALLBACKTYPE(uint32_t, FNEMULATEPARAM3,(void *pvParam1, uint64_t val2, size_t val3));
+typedef FNEMULATEPARAM3 *PFNEMULATEPARAM3;
+typedef DECLCALLBACKTYPE(int, FNEMULATELOCKPARAM2,(void *pvParam1, uint64_t val2, RTGCUINTREG32 *pf));
+typedef FNEMULATELOCKPARAM2 *PFNEMULATELOCKPARAM2;
+typedef DECLCALLBACKTYPE(int, FNEMULATELOCKPARAM3,(void *pvParam1, uint64_t val2, size_t cb, RTGCUINTREG32 *pf));
+typedef FNEMULATELOCKPARAM3 *PFNEMULATELOCKPARAM3;
+/** @} */
+
+VMMDECL(void) EMSetHypercallInstructionsEnabled(PVMCPU pVCpu, bool fEnabled);
+VMMDECL(bool) EMAreHypercallInstructionsEnabled(PVMCPU pVCpu);
+VMM_INT_DECL(bool) EMShouldContinueAfterHalt(PVMCPU pVCpu, PCPUMCTX pCtx);
+VMM_INT_DECL(bool) EMMonitorWaitShouldContinue(PVMCPU pVCpu, PCPUMCTX pCtx);
+VMM_INT_DECL(int) EMMonitorWaitPrepare(PVMCPU pVCpu, uint64_t rax, uint64_t rcx, uint64_t rdx, RTGCPHYS GCPhys);
+VMM_INT_DECL(void) EMMonitorWaitClear(PVMCPU pVCpu);
+VMM_INT_DECL(bool) EMMonitorIsArmed(PVMCPU pVCpu);
+VMM_INT_DECL(unsigned) EMMonitorWaitIsActive(PVMCPU pVCpu);
+VMM_INT_DECL(int) EMMonitorWaitPerform(PVMCPU pVCpu, uint64_t rax, uint64_t rcx);
+VMM_INT_DECL(int) EMUnhaltAndWakeUp(PVMCC pVM, PVMCPUCC pVCpuDst);
+VMMRZ_INT_DECL(VBOXSTRICTRC) EMRZSetPendingIoPortWrite(PVMCPU pVCpu, RTIOPORT uPort, uint8_t cbInstr, uint8_t cbValue, uint32_t uValue);
+VMMRZ_INT_DECL(VBOXSTRICTRC) EMRZSetPendingIoPortRead(PVMCPU pVCpu, RTIOPORT uPort, uint8_t cbInstr, uint8_t cbValue);
+
+/**
+ * Common defined exit types that EM knows what to do about.
+ *
+ * These should be used instead of the VT-x, SVM or NEM specific ones for exits
+ * worth optimizing.
+ */
+typedef enum EMEXITTYPE
+{
+ EMEXITTYPE_INVALID = 0,
+ EMEXITTYPE_IO_PORT_READ,
+ EMEXITTYPE_IO_PORT_WRITE,
+ EMEXITTYPE_IO_PORT_STR_READ,
+ EMEXITTYPE_IO_PORT_STR_WRITE,
+ EMEXITTYPE_MMIO,
+ EMEXITTYPE_MMIO_READ,
+ EMEXITTYPE_MMIO_WRITE,
+ EMEXITTYPE_MSR_READ,
+ EMEXITTYPE_MSR_WRITE,
+ EMEXITTYPE_CPUID,
+ EMEXITTYPE_RDTSC,
+ EMEXITTYPE_MOV_CRX,
+ EMEXITTYPE_MOV_DRX,
+ EMEXITTYPE_VMREAD,
+ EMEXITTYPE_VMWRITE,
+
+ /** @name Raw-mode only (for now), keep at end.
+ * @{ */
+ EMEXITTYPE_INVLPG,
+ EMEXITTYPE_LLDT,
+ EMEXITTYPE_RDPMC,
+ EMEXITTYPE_CLTS,
+ EMEXITTYPE_STI,
+ EMEXITTYPE_INT,
+ EMEXITTYPE_SYSCALL,
+ EMEXITTYPE_SYSENTER,
+ EMEXITTYPE_HLT
+ /** @} */
+} EMEXITTYPE;
+AssertCompileSize(EMEXITTYPE, 4);
+
+/** @name EMEXIT_F_XXX - EM exit flags.
+ *
+ * The flags the exit type are combined to a 32-bit number using the
+ * EMEXIT_MAKE_FT() macro.
+ *
+ * @{ */
+#define EMEXIT_F_TYPE_MASK UINT32_C(0x00000fff) /**< The exit type mask. */
+#define EMEXIT_F_KIND_EM UINT32_C(0x00000000) /**< EMEXITTYPE */
+#define EMEXIT_F_KIND_VMX UINT32_C(0x00001000) /**< VT-x exit codes. */
+#define EMEXIT_F_KIND_SVM UINT32_C(0x00002000) /**< SVM exit codes. */
+#define EMEXIT_F_KIND_NEM UINT32_C(0x00003000) /**< NEMEXITTYPE */
+#define EMEXIT_F_KIND_XCPT UINT32_C(0x00004000) /**< Exception numbers (raw-mode). */
+#define EMEXIT_F_KIND_MASK UINT32_C(0x00007000)
+#define EMEXIT_F_CS_EIP UINT32_C(0x00010000) /**< The PC is EIP in the low dword and CS in the high. */
+#define EMEXIT_F_UNFLATTENED_PC UINT32_C(0x00020000) /**< The PC hasn't had CS.BASE added to it. */
+/** HM is calling (from ring-0). Preemption is currently disabled or we're using preemption hooks. */
+#define EMEXIT_F_HM UINT32_C(0x00040000)
+/** Combines flags and exit type into EMHistoryAddExit() input. */
+#define EMEXIT_MAKE_FT(a_fFlags, a_uType) ((a_fFlags) | (uint32_t)(a_uType))
+/** @} */
+
+typedef enum EMEXITACTION
+{
+ /** The record is free. */
+ EMEXITACTION_FREE_RECORD = 0,
+ /** Take normal action on the exit. */
+ EMEXITACTION_NORMAL,
+ /** Take normal action on the exit, already probed and found nothing. */
+ EMEXITACTION_NORMAL_PROBED,
+ /** Do a probe execution. */
+ EMEXITACTION_EXEC_PROBE,
+ /** Execute using EMEXITREC::cMaxInstructionsWithoutExit. */
+ EMEXITACTION_EXEC_WITH_MAX
+} EMEXITACTION;
+AssertCompileSize(EMEXITACTION, 4);
+
+/**
+ * Accumulative exit record.
+ *
+ * This could perhaps be squeezed down a bit, but there isn't too much point.
+ * We'll probably need more data as time goes by.
+ */
+typedef struct EMEXITREC
+{
+ /** The flat PC of the exit. */
+ uint64_t uFlatPC;
+ /** Flags and type, see EMEXIT_MAKE_FT. */
+ uint32_t uFlagsAndType;
+ /** The action to take (EMEXITACTION). */
+ uint8_t enmAction;
+ uint8_t bUnused;
+ /** Maximum number of instructions to execute without hitting an exit. */
+ uint16_t cMaxInstructionsWithoutExit;
+ /** The exit number (EMCPU::iNextExit) at which it was last updated. */
+ uint64_t uLastExitNo;
+ /** Number of hits. */
+ uint64_t cHits;
+} EMEXITREC;
+AssertCompileSize(EMEXITREC, 32);
+/** Pointer to an accumulative exit record. */
+typedef EMEXITREC *PEMEXITREC;
+/** Pointer to a const accumulative exit record. */
+typedef EMEXITREC const *PCEMEXITREC;
+
+VMM_INT_DECL(PCEMEXITREC) EMHistoryAddExit(PVMCPUCC pVCpu, uint32_t uFlagsAndType, uint64_t uFlatPC, uint64_t uTimestamp);
+#ifdef IN_RC
+VMMRC_INT_DECL(void) EMRCHistoryAddExitCsEip(PVMCPU pVCpu, uint32_t uFlagsAndType, uint16_t uCs, uint32_t uEip,
+ uint64_t uTimestamp);
+#endif
+VMM_INT_DECL(void) EMHistoryUpdatePC(PVMCPUCC pVCpu, uint64_t uFlatPC, bool fFlattened);
+VMM_INT_DECL(PCEMEXITREC) EMHistoryUpdateFlagsAndType(PVMCPUCC pVCpu, uint32_t uFlagsAndType);
+VMM_INT_DECL(PCEMEXITREC) EMHistoryUpdateFlagsAndTypeAndPC(PVMCPUCC pVCpu, uint32_t uFlagsAndType, uint64_t uFlatPC);
+VMM_INT_DECL(VBOXSTRICTRC) EMHistoryExec(PVMCPUCC pVCpu, PCEMEXITREC pExitRec, uint32_t fWillExit);
+
+
+/** @name Deprecated interpretation related APIs (use IEM).
+ * @{ */
+VMM_INT_DECL(int) EMInterpretDisasCurrent(PVMCPUCC pVCpu, PDISCPUSTATE pCpu, unsigned *pcbInstr);
+VMM_INT_DECL(int) EMInterpretDisasOneEx(PVMCPUCC pVCpu, RTGCUINTPTR GCPtrInstr,
+ PDISCPUSTATE pDISState, unsigned *pcbInstr);
+VMM_INT_DECL(VBOXSTRICTRC) EMInterpretInstruction(PVMCPUCC pVCpu);
+VMM_INT_DECL(VBOXSTRICTRC) EMInterpretInstructionDisasState(PVMCPUCC pVCpu, PDISCPUSTATE pDis, uint64_t rip);
+/** @} */
+
+
+/** @name EM_ONE_INS_FLAGS_XXX - flags for EMR3HmSingleInstruction (et al).
+ * @{ */
+/** Return when CS:RIP changes or some other important event happens.
+ * This means running whole REP and LOOP $ sequences for instance. */
+#define EM_ONE_INS_FLAGS_RIP_CHANGE RT_BIT_32(0)
+/** Mask of valid flags. */
+#define EM_ONE_INS_FLAGS_MASK UINT32_C(0x00000001)
+/** @} */
+
+
+#ifdef IN_RING0
+/** @defgroup grp_em_r0 The EM Host Context Ring-0 API
+ * @{ */
+VMMR0_INT_DECL(int) EMR0InitVM(PGVM pGVM);
+/** @} */
+#endif
+
+
+#ifdef IN_RING3
+/** @defgroup grp_em_r3 The EM Host Context Ring-3 API
+ * @{
+ */
+
+/**
+ * Command argument for EMR3RawSetMode().
+ *
+ * It's possible to extend this interface to change several
+ * execution modes at once should the need arise.
+ */
+typedef enum EMEXECPOLICY
+{
+ /** The customary invalid zero entry. */
+ EMEXECPOLICY_INVALID = 0,
+ /** Whether to recompile ring-0 code or execute it in raw/hm. */
+ EMEXECPOLICY_RECOMPILE_RING0,
+ /** Whether to recompile ring-3 code or execute it in raw/hm. */
+ EMEXECPOLICY_RECOMPILE_RING3,
+ /** Whether to only use IEM for execution. */
+ EMEXECPOLICY_IEM_ALL,
+ /** End of valid value (not included). */
+ EMEXECPOLICY_END,
+ /** The customary 32-bit type blowup. */
+ EMEXECPOLICY_32BIT_HACK = 0x7fffffff
+} EMEXECPOLICY;
+VMMR3DECL(int) EMR3SetExecutionPolicy(PUVM pUVM, EMEXECPOLICY enmPolicy, bool fEnforce);
+VMMR3DECL(int) EMR3QueryExecutionPolicy(PUVM pUVM, EMEXECPOLICY enmPolicy, bool *pfEnforced);
+VMMR3DECL(int) EMR3QueryMainExecutionEngine(PUVM pUVM, uint8_t *pbMainExecutionEngine);
+
+VMMR3_INT_DECL(int) EMR3Init(PVM pVM);
+VMMR3_INT_DECL(int) EMR3InitCompleted(PVM pVM, VMINITCOMPLETED enmWhat);
+VMMR3_INT_DECL(void) EMR3Relocate(PVM pVM);
+VMMR3_INT_DECL(void) EMR3ResetCpu(PVMCPU pVCpu);
+VMMR3_INT_DECL(void) EMR3Reset(PVM pVM);
+VMMR3_INT_DECL(int) EMR3Term(PVM pVM);
+VMMR3DECL(DECL_NO_RETURN(void)) EMR3FatalError(PVMCPU pVCpu, int rc);
+VMMR3_INT_DECL(int) EMR3ExecuteVM(PVM pVM, PVMCPU pVCpu);
+VMMR3_INT_DECL(int) EMR3CheckRawForcedActions(PVM pVM, PVMCPU pVCpu);
+VMMR3_INT_DECL(VBOXSTRICTRC) EMR3HmSingleInstruction(PVM pVM, PVMCPU pVCpu, uint32_t fFlags);
+
+/** @} */
+#endif /* IN_RING3 */
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !VBOX_INCLUDED_vmm_em_h */
+
diff --git a/include/VBox/vmm/gcm.h b/include/VBox/vmm/gcm.h
new file mode 100644
index 00000000..0b3102c7
--- /dev/null
+++ b/include/VBox/vmm/gcm.h
@@ -0,0 +1,95 @@
+/** @file
+ * GCM - Guest Compatibility Manager.
+ */
+
+/*
+ * Copyright (C) 2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vmm_gcm_h
+#define VBOX_INCLUDED_vmm_gcm_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/cdefs.h>
+#include <VBox/types.h>
+#include <VBox/param.h>
+
+#include <VBox/vmm/cpum.h>
+#include <VBox/vmm/pdmifs.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_gcm The Guest Compatibility Manager API
+ * @ingroup grp_vmm
+ * @{
+ */
+
+/**
+ * GCM Fixer Identifiers.
+ * @remarks Part of saved state!
+ */
+typedef enum GCMFIXERID
+{
+ /** None. */
+ GCMFIXER_NONE = 0,
+ /** DOS division by zero, the worst. Includes Windows 3.x. */
+ GCMFIXER_DBZ_DOS = RT_BIT(0),
+ /** OS/2 (any version) division by zero. */
+ GCMFIXER_DBZ_OS2 = RT_BIT(1),
+ /** Windows 9x division by zero. */
+ GCMFIXER_DBZ_WIN9X = RT_BIT(2),
+ /** 32-bit hack. */
+ GCMFIXER_32BIT_HACK = 0x7fffffff
+} GCMFIXERID;
+AssertCompileSize(GCMFIXERID, sizeof(uint32_t));
+
+
+#ifdef IN_RING3
+/** @defgroup grp_gcm_r3 The GCM Host Context Ring-3 API
+ * @{
+ */
+VMMR3_INT_DECL(int) GCMR3Init(PVM pVM);
+VMMR3_INT_DECL(void) GCMR3Relocate(PVM pVM, RTGCINTPTR offDelta);
+VMMR3_INT_DECL(int) GCMR3Term(PVM pVM);
+VMMR3_INT_DECL(void) GCMR3Reset(PVM pVM);
+/** @} */
+#endif /* IN_RING3 */
+
+VMMDECL(bool) GCMIsEnabled(PVM pVM);
+VMM_INT_DECL(bool) GCMShouldTrapXcptDE(PVMCPUCC pVCpu);
+VMM_INT_DECL(VBOXSTRICTRC) GCMXcptDE(PVMCPUCC pVCpu, PCPUMCTX pCtx, PDISCPUSTATE pDis, uint8_t *pcbInstr);
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !VBOX_INCLUDED_vmm_gcm_h */
+
diff --git a/include/VBox/vmm/gim.h b/include/VBox/vmm/gim.h
new file mode 100644
index 00000000..b62e1a1e
--- /dev/null
+++ b/include/VBox/vmm/gim.h
@@ -0,0 +1,218 @@
+/** @file
+ * GIM - Guest Interface Manager.
+ */
+
+/*
+ * Copyright (C) 2014-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vmm_gim_h
+#define VBOX_INCLUDED_vmm_gim_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/cdefs.h>
+#include <VBox/types.h>
+#include <VBox/param.h>
+
+#include <VBox/vmm/cpum.h>
+#include <VBox/vmm/pdmifs.h>
+
+/** The value used to specify that VirtualBox must use the newest
+ * implementation version of the GIM provider. */
+#define GIM_VERSION_LATEST UINT32_C(0)
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_gim The Guest Interface Manager API
+ * @ingroup grp_vmm
+ * @{
+ */
+
+/**
+ * GIM Provider Identifiers.
+ * @remarks Part of saved state!
+ */
+typedef enum GIMPROVIDERID
+{
+ /** None. */
+ GIMPROVIDERID_NONE = 0,
+ /** Minimal. */
+ GIMPROVIDERID_MINIMAL,
+ /** Microsoft Hyper-V. */
+ GIMPROVIDERID_HYPERV,
+ /** Linux KVM Interface. */
+ GIMPROVIDERID_KVM
+} GIMPROVIDERID;
+AssertCompileSize(GIMPROVIDERID, sizeof(uint32_t));
+
+
+/**
+ * A GIM MMIO2 region record.
+ */
+typedef struct GIMMMIO2REGION
+{
+ /** The region index. */
+ uint8_t iRegion;
+ /** Whether an RC mapping is required. */
+ bool fRCMapping;
+ /** Whether this region has been registered. */
+ bool fRegistered;
+ /** Whether this region is currently mapped. */
+ bool fMapped;
+ /** Size of the region (must be page aligned). */
+ uint32_t cbRegion;
+ /** The host ring-0 address of the first page in the region. */
+ R0PTRTYPE(void *) pvPageR0;
+ /** The host ring-3 address of the first page in the region. */
+ R3PTRTYPE(void *) pvPageR3;
+# ifdef VBOX_WITH_RAW_MODE_KEEP
+ /** The ring-context address of the first page in the region. */
+ RCPTRTYPE(void *) pvPageRC;
+ RTRCPTR RCPtrAlignment0;
+# endif
+ /** The guest-physical address of the first page in the region. */
+ RTGCPHYS GCPhysPage;
+ /** The MMIO2 handle. */
+ PGMMMIO2HANDLE hMmio2;
+ /** The description of the region. */
+ char szDescription[32];
+} GIMMMIO2REGION;
+/** Pointer to a GIM MMIO2 region. */
+typedef GIMMMIO2REGION *PGIMMMIO2REGION;
+/** Pointer to a const GIM MMIO2 region. */
+typedef GIMMMIO2REGION const *PCGIMMMIO2REGION;
+AssertCompileMemberAlignment(GIMMMIO2REGION, pvPageR0, 8);
+AssertCompileMemberAlignment(GIMMMIO2REGION, GCPhysPage, 8);
+
+/**
+ * Debug data buffer available callback over the GIM debug connection.
+ *
+ * @param pVM The cross context VM structure.
+ */
+typedef DECLCALLBACKTYPE(void, FNGIMDEBUGBUFAVAIL,(PVM pVM));
+/** Pointer to GIM debug buffer available callback. */
+typedef FNGIMDEBUGBUFAVAIL *PFNGIMDEBUGBUFAVAIL;
+
+/**
+ * GIM debug setup.
+ *
+ * These are parameters/options filled in by the GIM provider and passed along
+ * to the GIM device.
+ */
+typedef struct GIMDEBUGSETUP
+{
+ /** The callback to invoke when the receive buffer has data. */
+ PFNGIMDEBUGBUFAVAIL pfnDbgRecvBufAvail;
+ /** The size of the receive buffer as specified by the GIM provider. */
+ uint32_t cbDbgRecvBuf;
+} GIMDEBUGSETUP;
+/** Pointer to a GIM debug setup struct. */
+typedef struct GIMDEBUGSETUP *PGIMDEBUGSETUP;
+/** Pointer to a const GIM debug setup struct. */
+typedef struct GIMDEBUGSETUP const *PCGGIMDEBUGSETUP;
+
+/**
+ * GIM debug structure (common to the GIM device and GIM).
+ *
+ * This is used to exchanging data between the GIM provider and the GIM device.
+ */
+typedef struct GIMDEBUG
+{
+ /** The receive buffer. */
+ void *pvDbgRecvBuf;
+ /** The debug I/O stream driver. */
+ PPDMISTREAM pDbgDrvStream;
+ /** Number of bytes pending to be read from the receive buffer. */
+ size_t cbDbgRecvBufRead;
+ /** The flag synchronizing reads of the receive buffer from EMT. */
+ volatile bool fDbgRecvBufRead;
+ /** The receive thread wakeup semaphore. */
+ RTSEMEVENTMULTI hDbgRecvThreadSem;
+} GIMDEBUG;
+/** Pointer to a GIM debug struct. */
+typedef struct GIMDEBUG *PGIMDEBUG;
+/** Pointer to a const GIM debug struct. */
+typedef struct GIMDEBUG const *PCGIMDEBUG;
+
+
+#ifdef IN_RC
+/** @defgroup grp_gim_rc The GIM Raw-mode Context API
+ * @{
+ */
+/** @} */
+#endif /* IN_RC */
+
+#ifdef IN_RING0
+/** @defgroup grp_gim_r0 The GIM Host Context Ring-0 API
+ * @{
+ */
+VMMR0_INT_DECL(int) GIMR0InitVM(PVMCC pVM);
+VMMR0_INT_DECL(int) GIMR0TermVM(PVMCC pVM);
+VMMR0_INT_DECL(int) GIMR0UpdateParavirtTsc(PVMCC pVM, uint64_t u64Offset);
+/** @} */
+#endif /* IN_RING0 */
+
+
+#ifdef IN_RING3
+/** @defgroup grp_gim_r3 The GIM Host Context Ring-3 API
+ * @{
+ */
+VMMR3_INT_DECL(int) GIMR3Init(PVM pVM);
+VMMR3_INT_DECL(int) GIMR3InitCompleted(PVM pVM);
+VMMR3_INT_DECL(void) GIMR3Relocate(PVM pVM, RTGCINTPTR offDelta);
+VMMR3_INT_DECL(int) GIMR3Term(PVM pVM);
+VMMR3_INT_DECL(void) GIMR3Reset(PVM pVM);
+VMMR3DECL(void) GIMR3GimDeviceRegister(PVM pVM, PPDMDEVINS pDevInsR3, PGIMDEBUG pDbg);
+VMMR3DECL(int) GIMR3GetDebugSetup(PVM pVM, PGIMDEBUGSETUP pDbgSetup);
+/** @} */
+#endif /* IN_RING3 */
+
+VMMDECL(bool) GIMIsEnabled(PVM pVM);
+VMMDECL(GIMPROVIDERID) GIMGetProvider(PVM pVM);
+VMMDECL(PGIMMMIO2REGION) GIMGetMmio2Regions(PVMCC pVM, uint32_t *pcRegions);
+VMM_INT_DECL(bool) GIMIsParavirtTscEnabled(PVMCC pVM);
+VMM_INT_DECL(bool) GIMAreHypercallsEnabled(PVMCPUCC pVCpu);
+VMM_INT_DECL(VBOXSTRICTRC) GIMHypercall(PVMCPUCC pVCpu, PCPUMCTX pCtx);
+VMM_INT_DECL(VBOXSTRICTRC) GIMHypercallEx(PVMCPUCC pVCpu, PCPUMCTX pCtx, unsigned uDisOpcode, uint8_t cbInstr);
+VMM_INT_DECL(VBOXSTRICTRC) GIMExecHypercallInstr(PVMCPUCC pVCpu, PCPUMCTX pCtx, uint8_t *pcbInstr);
+VMM_INT_DECL(VBOXSTRICTRC) GIMXcptUD(PVMCPUCC pVCpu, PCPUMCTX pCtx, PDISCPUSTATE pDis, uint8_t *pcbInstr);
+VMM_INT_DECL(bool) GIMShouldTrapXcptUD(PVMCPUCC pVCpu);
+VMM_INT_DECL(VBOXSTRICTRC) GIMReadMsr(PVMCPUCC pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue);
+VMM_INT_DECL(VBOXSTRICTRC) GIMWriteMsr(PVMCPUCC pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue);
+VMM_INT_DECL(int) GIMQueryHypercallOpcodeBytes(PVM pVM, void *pvBuf, size_t cbBuf,
+ size_t *pcbWritten, uint16_t *puDisOpcode);
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !VBOX_INCLUDED_vmm_gim_h */
+
diff --git a/include/VBox/vmm/gmm.h b/include/VBox/vmm/gmm.h
new file mode 100644
index 00000000..4839b737
--- /dev/null
+++ b/include/VBox/vmm/gmm.h
@@ -0,0 +1,828 @@
+/** @file
+ * GMM - The Global Memory Manager.
+ */
+
+/*
+ * Copyright (C) 2007-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vmm_gmm_h
+#define VBOX_INCLUDED_vmm_gmm_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/vmm/gvmm.h>
+#include <VBox/sup.h>
+#include <VBox/param.h>
+#include <VBox/ostypes.h>
+#include <iprt/avl.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_gmm GMM - The Global Memory Manager
+ * @ingroup grp_vmm
+ * @{
+ */
+
+/** @def IN_GMM_R0
+ * Used to indicate whether we're inside the same link module as the ring 0
+ * part of the Global Memory Manager or not.
+ */
+#ifdef DOXYGEN_RUNNING
+# define IN_GMM_R0
+#endif
+/** @def GMMR0DECL
+ * Ring 0 GMM export or import declaration.
+ * @param type The return type of the function declaration.
+ */
+#ifdef IN_GMM_R0
+# define GMMR0DECL(type) DECLEXPORT(type) VBOXCALL
+#else
+# define GMMR0DECL(type) DECLIMPORT(type) VBOXCALL
+#endif
+
+/** @def IN_GMM_R3
+ * Used to indicate whether we're inside the same link module as the ring 3
+ * part of the Global Memory Manager or not.
+ */
+#ifdef DOXYGEN_RUNNING
+# define IN_GMM_R3
+#endif
+/** @def GMMR3DECL
+ * Ring 3 GMM export or import declaration.
+ * @param type The return type of the function declaration.
+ */
+#ifdef IN_GMM_R3
+# define GMMR3DECL(type) DECLEXPORT(type) VBOXCALL
+#else
+# define GMMR3DECL(type) DECLIMPORT(type) VBOXCALL
+#endif
+
+
+/** The chunk shift. (2^21 = 2 MB) */
+#define GMM_CHUNK_SHIFT 21
+/** The allocation chunk size. */
+#define GMM_CHUNK_SIZE (1U << GMM_CHUNK_SHIFT)
+/** The allocation chunk size in (guest) pages. */
+#define GMM_CHUNK_NUM_PAGES (1U << (GMM_CHUNK_SHIFT - GUEST_PAGE_SHIFT))
+/** The shift factor for converting a page id into a chunk id. */
+#define GMM_CHUNKID_SHIFT (GMM_CHUNK_SHIFT - GUEST_PAGE_SHIFT)
+/** The last valid Chunk ID value. */
+#define GMM_CHUNKID_LAST (GMM_PAGEID_LAST >> GMM_CHUNKID_SHIFT)
+/** The last valid Page ID value. */
+#define GMM_PAGEID_LAST UINT32_C(0xfffffff0)
+/** Mask out the page index from the Page ID. */
+#define GMM_PAGEID_IDX_MASK ((1U << GMM_CHUNKID_SHIFT) - 1)
+/** The NIL Chunk ID value. */
+#define NIL_GMM_CHUNKID 0
+/** The NIL Page ID value. */
+#define NIL_GMM_PAGEID 0
+
+#if 0 /* wrong - these are guest page pfns and not page ids! */
+/** Special Page ID used by unassigned pages. */
+#define GMM_PAGEID_UNASSIGNED 0x0fffffffU
+/** Special Page ID used by unsharable pages.
+ * Like MMIO2, shadow and heap. This is for later, obviously. */
+#define GMM_PAGEID_UNSHARABLE 0x0ffffffeU
+/** The end of the valid Page IDs. This is the first special one. */
+#define GMM_PAGEID_END 0x0ffffff0U
+#endif
+
+
+/** @def GMM_GCPHYS_LAST
+ * The last of the valid guest physical address as it applies to GMM pages.
+ *
+ * This must reflect the constraints imposed by the RTGCPHYS type and
+ * the guest page frame number used internally in GMMPAGE.
+ *
+ * @note Note this corresponds to GMM_PAGE_PFN_LAST. */
+#if HC_ARCH_BITS == 64
+# define GMM_GCPHYS_LAST UINT64_C(0x00000fffffff0000) /* 2^44 (16TB) - 0x10000 */
+#else
+# define GMM_GCPHYS_LAST UINT64_C(0x0000000fffff0000) /* 2^36 (64GB) - 0x10000 */
+#endif
+
+/**
+ * Over-commitment policy.
+ */
+typedef enum GMMOCPOLICY
+{
+ /** The usual invalid 0 value. */
+ GMMOCPOLICY_INVALID = 0,
+ /** No over-commitment, fully backed.
+ * The GMM guarantees that it will be able to allocate all of the
+ * guest RAM for a VM with OC policy. */
+ GMMOCPOLICY_NO_OC,
+ /** to-be-determined. */
+ GMMOCPOLICY_TBD,
+ /** The end of the valid policy range. */
+ GMMOCPOLICY_END,
+ /** The usual 32-bit hack. */
+ GMMOCPOLICY_32BIT_HACK = 0x7fffffff
+} GMMOCPOLICY;
+
+/**
+ * VM / Memory priority.
+ */
+typedef enum GMMPRIORITY
+{
+ /** The usual invalid 0 value. */
+ GMMPRIORITY_INVALID = 0,
+ /** High.
+ * When ballooning, ask these VMs last.
+ * When running out of memory, try not to interrupt these VMs. */
+ GMMPRIORITY_HIGH,
+ /** Normal.
+ * When ballooning, don't wait to ask these.
+ * When running out of memory, pause, save and/or kill these VMs. */
+ GMMPRIORITY_NORMAL,
+ /** Low.
+ * When ballooning, maximize these first.
+ * When running out of memory, save or kill these VMs. */
+ GMMPRIORITY_LOW,
+ /** The end of the valid priority range. */
+ GMMPRIORITY_END,
+ /** The custom 32-bit type blowup. */
+ GMMPRIORITY_32BIT_HACK = 0x7fffffff
+} GMMPRIORITY;
+
+
+/**
+ * GMM Memory Accounts.
+ */
+typedef enum GMMACCOUNT
+{
+ /** The customary invalid zero entry. */
+ GMMACCOUNT_INVALID = 0,
+ /** Account with the base allocations. */
+ GMMACCOUNT_BASE,
+ /** Account with the shadow allocations. */
+ GMMACCOUNT_SHADOW,
+ /** Account with the fixed allocations. */
+ GMMACCOUNT_FIXED,
+ /** The end of the valid values. */
+ GMMACCOUNT_END,
+ /** The usual 32-bit value to finish it off. */
+ GMMACCOUNT_32BIT_HACK = 0x7fffffff
+} GMMACCOUNT;
+
+
+/**
+ * Balloon actions.
+ */
+typedef enum
+{
+ /** Invalid zero entry. */
+ GMMBALLOONACTION_INVALID = 0,
+ /** Inflate the balloon. */
+ GMMBALLOONACTION_INFLATE,
+ /** Deflate the balloon. */
+ GMMBALLOONACTION_DEFLATE,
+ /** Puncture the balloon because of VM reset. */
+ GMMBALLOONACTION_RESET,
+ /** End of the valid actions. */
+ GMMBALLOONACTION_END,
+ /** hack forcing the size of the enum to 32-bits. */
+ GMMBALLOONACTION_MAKE_32BIT_HACK = 0x7fffffff
+} GMMBALLOONACTION;
+
+
+/**
+ * A page descriptor for use when freeing pages.
+ * See GMMR0FreePages, GMMR0BalloonedPages.
+ */
+typedef struct GMMFREEPAGEDESC
+{
+ /** The Page ID of the page to be freed. */
+ uint32_t idPage;
+} GMMFREEPAGEDESC;
+/** Pointer to a page descriptor for freeing pages. */
+typedef GMMFREEPAGEDESC *PGMMFREEPAGEDESC;
+
+
+/**
+ * A page descriptor for use when updating and allocating pages.
+ *
+ * This is a bit complicated because we want to do as much as possible
+ * with the same structure.
+ */
+typedef struct GMMPAGEDESC
+{
+ /** The physical address of the page.
+ *
+ * @input GMMR0AllocateHandyPages expects the guest physical address
+ * to update the GMMPAGE structure with. Pass GMM_GCPHYS_UNSHAREABLE
+ * when appropriate and NIL_GMMPAGEDESC_PHYS when the page wasn't used
+ * for any specific guest address.
+ *
+ * GMMR0AllocatePage expects the guest physical address to put in
+ * the GMMPAGE structure for the page it allocates for this entry.
+ * Pass NIL_GMMPAGEDESC_PHYS and GMM_GCPHYS_UNSHAREABLE as above.
+ *
+ * @output The host physical address of the allocated page.
+ * NIL_GMMPAGEDESC_PHYS on allocation failure.
+ *
+ * ASSUMES: sizeof(RTHCPHYS) >= sizeof(RTGCPHYS) and that physical addresses are
+ * limited to 63 or fewer bits (52 by AMD64 arch spec).
+ */
+ RT_GCC_EXTENSION
+ RTHCPHYS HCPhysGCPhys : 63;
+ /** Set if the memory was zeroed. */
+ RT_GCC_EXTENSION
+ RTHCPHYS fZeroed : 1;
+
+ /** The Page ID.
+ *
+ * @input GMMR0AllocateHandyPages expects the Page ID of the page to
+ * update here. NIL_GMM_PAGEID means no page should be updated.
+ *
+ * GMMR0AllocatePages requires this to be initialized to
+ * NIL_GMM_PAGEID currently.
+ *
+ * @output The ID of the page, NIL_GMM_PAGEID if the allocation failed.
+ */
+ uint32_t idPage;
+
+ /** The Page ID of the shared page was replaced by this page.
+ *
+ * @input GMMR0AllocateHandyPages expects this to indicate a shared
+ * page that has been replaced by this page and should have its
+ * reference counter decremented and perhaps be freed up. Use
+ * NIL_GMM_PAGEID if no shared page was involved.
+ *
+ * All other APIs expects NIL_GMM_PAGEID here.
+ *
+ * @output All APIs sets this to NIL_GMM_PAGEID.
+ */
+ uint32_t idSharedPage;
+} GMMPAGEDESC;
+AssertCompileSize(GMMPAGEDESC, 16);
+/** Pointer to a page allocation. */
+typedef GMMPAGEDESC *PGMMPAGEDESC;
+
+/** Special NIL value for GMMPAGEDESC::HCPhysGCPhys. */
+#define NIL_GMMPAGEDESC_PHYS UINT64_C(0x7fffffffffffffff)
+
+/** GMMPAGEDESC::HCPhysGCPhys value that indicates that the page is unsharable.
+ * @note This corresponds to GMM_PAGE_PFN_UNSHAREABLE. */
+#if HC_ARCH_BITS == 64
+# define GMM_GCPHYS_UNSHAREABLE UINT64_C(0x00000fffffff1000)
+#else
+# define GMM_GCPHYS_UNSHAREABLE UINT64_C(0x0000000fffff1000)
+#endif
+
+
+/**
+ * The allocation sizes.
+ */
+typedef struct GMMVMSIZES
+{
+ /** The number of pages of base memory.
+ * This is the sum of RAM, ROMs and handy pages. */
+ uint64_t cBasePages;
+ /** The number of pages for the shadow pool. (Can be squeezed for memory.) */
+ uint32_t cShadowPages;
+ /** The number of pages for fixed allocations like MMIO2 and the hyper heap. */
+ uint32_t cFixedPages;
+} GMMVMSIZES;
+/** Pointer to a GMMVMSIZES. */
+typedef GMMVMSIZES *PGMMVMSIZES;
+
+
+/**
+ * GMM VM statistics.
+ */
+typedef struct GMMVMSTATS
+{
+ /** The reservations. */
+ GMMVMSIZES Reserved;
+ /** The actual allocations.
+ * This includes both private and shared page allocations. */
+ GMMVMSIZES Allocated;
+
+ /** The current number of private pages. */
+ uint64_t cPrivatePages;
+ /** The current number of shared pages. */
+ uint64_t cSharedPages;
+ /** The current number of ballooned pages. */
+ uint64_t cBalloonedPages;
+ /** The max number of pages that can be ballooned. */
+ uint64_t cMaxBalloonedPages;
+ /** The number of pages we've currently requested the guest to give us.
+ * This is 0 if no pages currently requested. */
+ uint64_t cReqBalloonedPages;
+ /** The number of pages the guest has given us in response to the request.
+ * This is not reset on request completed and may be used in later decisions. */
+ uint64_t cReqActuallyBalloonedPages;
+ /** The number of pages we've currently requested the guest to take back. */
+ uint64_t cReqDeflatePages;
+ /** The number of shareable module tracked by this VM. */
+ uint32_t cShareableModules;
+
+ /** The current over-commitment policy. */
+ GMMOCPOLICY enmPolicy;
+ /** The VM priority for arbitrating VMs in low and out of memory situation.
+ * Like which VMs to start squeezing first. */
+ GMMPRIORITY enmPriority;
+ /** Whether ballooning is enabled or not. */
+ bool fBallooningEnabled;
+ /** Whether shared paging is enabled or not. */
+ bool fSharedPagingEnabled;
+ /** Whether the VM is allowed to allocate memory or not.
+ * This is used when the reservation update request fails or when the VM has
+ * been told to suspend/save/die in an out-of-memory case. */
+ bool fMayAllocate;
+ /** Explicit alignment. */
+ bool afReserved[1];
+
+
+} GMMVMSTATS;
+
+
+/**
+ * The GMM statistics.
+ */
+typedef struct GMMSTATS
+{
+ /** The maximum number of pages we're allowed to allocate
+ * (GMM::cMaxPages). */
+ uint64_t cMaxPages;
+ /** The number of pages that has been reserved (GMM::cReservedPages). */
+ uint64_t cReservedPages;
+ /** The number of pages that we have over-committed in reservations
+ * (GMM::cOverCommittedPages). */
+ uint64_t cOverCommittedPages;
+ /** The number of actually allocated (committed if you like) pages
+ * (GMM::cAllocatedPages). */
+ uint64_t cAllocatedPages;
+ /** The number of pages that are shared. A subset of cAllocatedPages.
+ * (GMM::cSharedPages) */
+ uint64_t cSharedPages;
+ /** The number of pages that are actually shared between VMs.
+ * (GMM:cDuplicatePages) */
+ uint64_t cDuplicatePages;
+ /** The number of pages that are shared that has been left behind by
+ * VMs not doing proper cleanups (GMM::cLeftBehindSharedPages). */
+ uint64_t cLeftBehindSharedPages;
+ /** The number of current ballooned pages (GMM::cBalloonedPages). */
+ uint64_t cBalloonedPages;
+ /** The number of allocation chunks (GMM::cChunks). */
+ uint32_t cChunks;
+ /** The number of freed chunks ever (GMM::cFreedChunks). */
+ uint32_t cFreedChunks;
+ /** The number of shareable modules (GMM:cShareableModules). */
+ uint64_t cShareableModules;
+ /** The current chunk freeing generation use by the per-VM TLB validation (GMM::idFreeGeneration). */
+ uint64_t idFreeGeneration;
+ /** Space reserved for later. */
+ uint64_t au64Reserved[1];
+
+ /** Statistics for the specified VM. (Zero filled if not requested.) */
+ GMMVMSTATS VMStats;
+} GMMSTATS;
+/** Pointer to the GMM statistics. */
+typedef GMMSTATS *PGMMSTATS;
+/** Const pointer to the GMM statistics. */
+typedef const GMMSTATS *PCGMMSTATS;
+
+
+GMMR0DECL(int) GMMR0Init(void);
+GMMR0DECL(void) GMMR0Term(void);
+GMMR0DECL(int) GMMR0InitPerVMData(PGVM pGVM);
+GMMR0DECL(void) GMMR0CleanupVM(PGVM pGVM);
+GMMR0DECL(int) GMMR0InitialReservation(PGVM pGVM, VMCPUID idCpu, uint64_t cBasePages, uint32_t cShadowPages, uint32_t cFixedPages,
+ GMMOCPOLICY enmPolicy, GMMPRIORITY enmPriority);
+GMMR0DECL(int) GMMR0UpdateReservation(PGVM pGVM, VMCPUID idCpu, uint64_t cBasePages, uint32_t cShadowPages, uint32_t cFixedPages);
+GMMR0DECL(int) GMMR0AllocateHandyPages(PGVM pGVM, VMCPUID idCpu, uint32_t cPagesToUpdate,
+ uint32_t cPagesToAlloc, PGMMPAGEDESC paPages);
+GMMR0DECL(int) GMMR0AllocatePages(PGVM pGVM, VMCPUID idCpu, uint32_t cPages, PGMMPAGEDESC paPages, GMMACCOUNT enmAccount);
+GMMR0DECL(int) GMMR0AllocateLargePage(PGVM pGVM, VMCPUID idCpu, uint32_t cbPage, uint32_t *pIdPage, RTHCPHYS *pHCPhys);
+GMMR0DECL(int) GMMR0FreePages(PGVM pGVM, VMCPUID idCpu, uint32_t cPages, PGMMFREEPAGEDESC paPages, GMMACCOUNT enmAccount);
+GMMR0DECL(int) GMMR0FreeLargePage(PGVM pGVM, VMCPUID idCpu, uint32_t idPage);
+GMMR0DECL(int) GMMR0BalloonedPages(PGVM pGVM, VMCPUID idCpu, GMMBALLOONACTION enmAction, uint32_t cBalloonedPages);
+GMMR0DECL(int) GMMR0MapUnmapChunk(PGVM pGVM, uint32_t idChunkMap, uint32_t idChunkUnmap, PRTR3PTR ppvR3);
+GMMR0DECL(int) GMMR0PageIdToVirt(PGVM pGVM, uint32_t idPage, void **ppv);
+GMMR0DECL(int) GMMR0RegisterSharedModule(PGVM pGVM, VMCPUID idCpu, VBOXOSFAMILY enmGuestOS, char *pszModuleName,
+ char *pszVersion, RTGCPTR GCBaseAddr, uint32_t cbModule, uint32_t cRegions,
+ struct VMMDEVSHAREDREGIONDESC const *paRegions);
+GMMR0DECL(int) GMMR0UnregisterSharedModule(PGVM pGVM, VMCPUID idCpu, char *pszModuleName, char *pszVersion,
+ RTGCPTR GCBaseAddr, uint32_t cbModule);
+GMMR0DECL(int) GMMR0UnregisterAllSharedModules(PGVM pGVM, VMCPUID idCpu);
+GMMR0DECL(int) GMMR0CheckSharedModules(PGVM pGVM, VMCPUID idCpu);
+GMMR0DECL(int) GMMR0ResetSharedModules(PGVM pGVM, VMCPUID idCpu);
+GMMR0DECL(int) GMMR0QueryStatistics(PGMMSTATS pStats, PSUPDRVSESSION pSession);
+GMMR0DECL(int) GMMR0ResetStatistics(PCGMMSTATS pStats, PSUPDRVSESSION pSession);
+
+/**
+ * Request buffer for GMMR0InitialReservationReq / VMMR0_DO_GMM_INITIAL_RESERVATION.
+ * @see GMMR0InitialReservation
+ */
+typedef struct GMMINITIALRESERVATIONREQ
+{
+ /** The header. */
+ SUPVMMR0REQHDR Hdr;
+ uint64_t cBasePages; /**< @see GMMR0InitialReservation */
+ uint32_t cShadowPages; /**< @see GMMR0InitialReservation */
+ uint32_t cFixedPages; /**< @see GMMR0InitialReservation */
+ GMMOCPOLICY enmPolicy; /**< @see GMMR0InitialReservation */
+ GMMPRIORITY enmPriority; /**< @see GMMR0InitialReservation */
+} GMMINITIALRESERVATIONREQ;
+/** Pointer to a GMMR0InitialReservationReq / VMMR0_DO_GMM_INITIAL_RESERVATION request buffer. */
+typedef GMMINITIALRESERVATIONREQ *PGMMINITIALRESERVATIONREQ;
+
+GMMR0DECL(int) GMMR0InitialReservationReq(PGVM pGVM, VMCPUID idCpu, PGMMINITIALRESERVATIONREQ pReq);
+
+
+/**
+ * Request buffer for GMMR0UpdateReservationReq / VMMR0_DO_GMM_UPDATE_RESERVATION.
+ * @see GMMR0UpdateReservation
+ */
+typedef struct GMMUPDATERESERVATIONREQ
+{
+ /** The header. */
+ SUPVMMR0REQHDR Hdr;
+ uint64_t cBasePages; /**< @see GMMR0UpdateReservation */
+ uint32_t cShadowPages; /**< @see GMMR0UpdateReservation */
+ uint32_t cFixedPages; /**< @see GMMR0UpdateReservation */
+} GMMUPDATERESERVATIONREQ;
+/** Pointer to a GMMR0InitialReservationReq / VMMR0_DO_GMM_INITIAL_RESERVATION request buffer. */
+typedef GMMUPDATERESERVATIONREQ *PGMMUPDATERESERVATIONREQ;
+
+GMMR0DECL(int) GMMR0UpdateReservationReq(PGVM pGVM, VMCPUID idCpu, PGMMUPDATERESERVATIONREQ pReq);
+
+
+/**
+ * Request buffer for GMMR0AllocatePagesReq / VMMR0_DO_GMM_ALLOCATE_PAGES.
+ * @see GMMR0AllocatePages.
+ */
+typedef struct GMMALLOCATEPAGESREQ
+{
+ /** The header. */
+ SUPVMMR0REQHDR Hdr;
+ /** The account to charge the allocation to. */
+ GMMACCOUNT enmAccount;
+ /** The number of pages to allocate. */
+ uint32_t cPages;
+ /** Array of page descriptors. */
+ GMMPAGEDESC aPages[1];
+} GMMALLOCATEPAGESREQ;
+/** Pointer to a GMMR0AllocatePagesReq / VMMR0_DO_GMM_ALLOCATE_PAGES request buffer. */
+typedef GMMALLOCATEPAGESREQ *PGMMALLOCATEPAGESREQ;
+
+GMMR0DECL(int) GMMR0AllocatePagesReq(PGVM pGVM, VMCPUID idCpu, PGMMALLOCATEPAGESREQ pReq);
+
+
+/**
+ * Request buffer for GMMR0FreePagesReq / VMMR0_DO_GMM_FREE_PAGES.
+ * @see GMMR0FreePages.
+ */
+typedef struct GMMFREEPAGESREQ
+{
+ /** The header. */
+ SUPVMMR0REQHDR Hdr;
+ /** The account this relates to. */
+ GMMACCOUNT enmAccount;
+ /** The number of pages to free. */
+ uint32_t cPages;
+ /** Array of free page descriptors. */
+ GMMFREEPAGEDESC aPages[1];
+} GMMFREEPAGESREQ;
+/** Pointer to a GMMR0FreePagesReq / VMMR0_DO_GMM_FREE_PAGES request buffer. */
+typedef GMMFREEPAGESREQ *PGMMFREEPAGESREQ;
+
+GMMR0DECL(int) GMMR0FreePagesReq(PGVM pGVM, VMCPUID idCpu, PGMMFREEPAGESREQ pReq);
+
+/**
+ * Request buffer for GMMR0BalloonedPagesReq / VMMR0_DO_GMM_BALLOONED_PAGES.
+ * @see GMMR0BalloonedPages.
+ */
+typedef struct GMMBALLOONEDPAGESREQ
+{
+ /** The header. */
+ SUPVMMR0REQHDR Hdr;
+ /** The number of ballooned pages. */
+ uint32_t cBalloonedPages;
+ /** Inflate or deflate the balloon. */
+ GMMBALLOONACTION enmAction;
+} GMMBALLOONEDPAGESREQ;
+/** Pointer to a GMMR0BalloonedPagesReq / VMMR0_DO_GMM_BALLOONED_PAGES request buffer. */
+typedef GMMBALLOONEDPAGESREQ *PGMMBALLOONEDPAGESREQ;
+
+GMMR0DECL(int) GMMR0BalloonedPagesReq(PGVM pGVM, VMCPUID idCpu, PGMMBALLOONEDPAGESREQ pReq);
+
+
+/**
+ * Request buffer for GMMR0QueryHypervisorMemoryStatsReq / VMMR0_DO_GMM_QUERY_VMM_MEM_STATS.
+ * @see GMMR0QueryHypervisorMemoryStatsReq.
+ */
+typedef struct GMMMEMSTATSREQ
+{
+ /** The header. */
+ SUPVMMR0REQHDR Hdr;
+ /** The number of allocated pages (out). */
+ uint64_t cAllocPages;
+ /** The number of free pages (out). */
+ uint64_t cFreePages;
+ /** The number of ballooned pages (out). */
+ uint64_t cBalloonedPages;
+ /** The number of shared pages (out). */
+ uint64_t cSharedPages;
+ /** Maximum nr of pages (out). */
+ uint64_t cMaxPages;
+} GMMMEMSTATSREQ;
+/** Pointer to a GMMR0QueryHypervisorMemoryStatsReq / VMMR0_DO_GMM_QUERY_HYPERVISOR_MEM_STATS request buffer. */
+typedef GMMMEMSTATSREQ *PGMMMEMSTATSREQ;
+
+GMMR0DECL(int) GMMR0QueryHypervisorMemoryStatsReq(PGMMMEMSTATSREQ pReq);
+GMMR0DECL(int) GMMR0QueryMemoryStatsReq(PGVM pGVM, VMCPUID idCpu, PGMMMEMSTATSREQ pReq);
+
+/**
+ * Request buffer for GMMR0MapUnmapChunkReq / VMMR0_DO_GMM_MAP_UNMAP_CHUNK.
+ * @see GMMR0MapUnmapChunk
+ */
+typedef struct GMMMAPUNMAPCHUNKREQ
+{
+ /** The header. */
+ SUPVMMR0REQHDR Hdr;
+ /** The chunk to map, NIL_GMM_CHUNKID if unmap only. (IN) */
+ uint32_t idChunkMap;
+ /** The chunk to unmap, NIL_GMM_CHUNKID if map only. (IN) */
+ uint32_t idChunkUnmap;
+ /** Where the mapping address is returned. (OUT) */
+ RTR3PTR pvR3;
+} GMMMAPUNMAPCHUNKREQ;
+/** Pointer to a GMMR0MapUnmapChunkReq / VMMR0_DO_GMM_MAP_UNMAP_CHUNK request buffer. */
+typedef GMMMAPUNMAPCHUNKREQ *PGMMMAPUNMAPCHUNKREQ;
+
+GMMR0DECL(int) GMMR0MapUnmapChunkReq(PGVM pGVM, PGMMMAPUNMAPCHUNKREQ pReq);
+
+
+/**
+ * Request buffer for GMMR0FreeLargePageReq / VMMR0_DO_GMM_FREE_LARGE_PAGE.
+ * @see GMMR0FreeLargePage.
+ */
+typedef struct GMMFREELARGEPAGEREQ
+{
+ /** The header. */
+ SUPVMMR0REQHDR Hdr;
+ /** The Page ID. */
+ uint32_t idPage;
+} GMMFREELARGEPAGEREQ;
+/** Pointer to a GMMR0FreePagesReq / VMMR0_DO_GMM_FREE_PAGES request buffer. */
+typedef GMMFREELARGEPAGEREQ *PGMMFREELARGEPAGEREQ;
+
+GMMR0DECL(int) GMMR0FreeLargePageReq(PGVM pGVM, VMCPUID idCpu, PGMMFREELARGEPAGEREQ pReq);
+
+/** Maximum length of the shared module name string, terminator included. */
+#define GMM_SHARED_MODULE_MAX_NAME_STRING 128
+/** Maximum length of the shared module version string, terminator included. */
+#define GMM_SHARED_MODULE_MAX_VERSION_STRING 16
+
+/**
+ * Request buffer for GMMR0RegisterSharedModuleReq / VMMR0_DO_GMM_REGISTER_SHARED_MODULE.
+ * @see GMMR0RegisterSharedModule.
+ */
+typedef struct GMMREGISTERSHAREDMODULEREQ
+{
+ /** The header. */
+ SUPVMMR0REQHDR Hdr;
+ /** 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;
+ /** return code. */
+ uint32_t rc;
+ /** Module name */
+ char szName[GMM_SHARED_MODULE_MAX_NAME_STRING];
+ /** Module version */
+ char szVersion[GMM_SHARED_MODULE_MAX_VERSION_STRING];
+ /** Shared region descriptor(s). */
+ VMMDEVSHAREDREGIONDESC aRegions[1];
+} GMMREGISTERSHAREDMODULEREQ;
+/** Pointer to a GMMR0RegisterSharedModuleReq / VMMR0_DO_GMM_REGISTER_SHARED_MODULE request buffer. */
+typedef GMMREGISTERSHAREDMODULEREQ *PGMMREGISTERSHAREDMODULEREQ;
+
+GMMR0DECL(int) GMMR0RegisterSharedModuleReq(PGVM pGVM, VMCPUID idCpu, PGMMREGISTERSHAREDMODULEREQ pReq);
+
+/**
+ * Shared region descriptor
+ */
+typedef struct GMMSHAREDREGIONDESC
+{
+ /** The page offset where the region starts. */
+ uint32_t off;
+ /** Region size - adjusted by the region offset and rounded up to a
+ * page. */
+ uint32_t cb;
+ /** Pointer to physical GMM page ID array. */
+ uint32_t *paidPages;
+} GMMSHAREDREGIONDESC;
+/** Pointer to a GMMSHAREDREGIONDESC. */
+typedef GMMSHAREDREGIONDESC *PGMMSHAREDREGIONDESC;
+
+
+/**
+ * Shared module registration info (global)
+ */
+typedef struct GMMSHAREDMODULE
+{
+ /** Tree node (keyed by a hash of name & version). */
+ AVLLU32NODECORE Core;
+ /** Shared module size. */
+ uint32_t cbModule;
+ /** Number of included region descriptors */
+ uint32_t cRegions;
+ /** Number of users (VMs). */
+ uint32_t cUsers;
+ /** Guest OS family type. */
+ VBOXOSFAMILY enmGuestOS;
+ /** Module name */
+ char szName[GMM_SHARED_MODULE_MAX_NAME_STRING];
+ /** Module version */
+ char szVersion[GMM_SHARED_MODULE_MAX_VERSION_STRING];
+ /** Shared region descriptor(s). */
+ GMMSHAREDREGIONDESC aRegions[1];
+} GMMSHAREDMODULE;
+/** Pointer to a GMMSHAREDMODULE. */
+typedef GMMSHAREDMODULE *PGMMSHAREDMODULE;
+
+/**
+ * Page descriptor for GMMR0SharedModuleCheckRange
+ */
+typedef struct GMMSHAREDPAGEDESC
+{
+ /** HC Physical address (in/out) */
+ RTHCPHYS HCPhys;
+ /** GC Physical address (in) */
+ RTGCPHYS GCPhys;
+ /** GMM page id. (in/out) */
+ uint32_t idPage;
+ /** CRC32 of the page in strict builds (0 if page not available).
+ * In non-strict build this serves as structure alignment. */
+ uint32_t u32StrictChecksum;
+} GMMSHAREDPAGEDESC;
+/** Pointer to a GMMSHAREDPAGEDESC. */
+typedef GMMSHAREDPAGEDESC *PGMMSHAREDPAGEDESC;
+
+GMMR0DECL(int) GMMR0SharedModuleCheckPage(PGVM pGVM, PGMMSHAREDMODULE pModule, uint32_t idxRegion, uint32_t idxPage,
+ PGMMSHAREDPAGEDESC pPageDesc);
+
+/**
+ * Request buffer for GMMR0UnregisterSharedModuleReq / VMMR0_DO_GMM_UNREGISTER_SHARED_MODULE.
+ * @see GMMR0UnregisterSharedModule.
+ */
+typedef struct GMMUNREGISTERSHAREDMODULEREQ
+{
+ /** The header. */
+ SUPVMMR0REQHDR Hdr;
+ /** 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[GMM_SHARED_MODULE_MAX_NAME_STRING];
+ /** Module version */
+ char szVersion[GMM_SHARED_MODULE_MAX_VERSION_STRING];
+} GMMUNREGISTERSHAREDMODULEREQ;
+/** Pointer to a GMMR0UnregisterSharedModuleReq / VMMR0_DO_GMM_UNREGISTER_SHARED_MODULE request buffer. */
+typedef GMMUNREGISTERSHAREDMODULEREQ *PGMMUNREGISTERSHAREDMODULEREQ;
+
+GMMR0DECL(int) GMMR0UnregisterSharedModuleReq(PGVM pGVM, VMCPUID idCpu, PGMMUNREGISTERSHAREDMODULEREQ pReq);
+
+#if defined(VBOX_STRICT) && HC_ARCH_BITS == 64
+/**
+ * Request buffer for GMMR0FindDuplicatePageReq / VMMR0_DO_GMM_FIND_DUPLICATE_PAGE.
+ * @see GMMR0FindDuplicatePage.
+ */
+typedef struct GMMFINDDUPLICATEPAGEREQ
+{
+ /** The header. */
+ SUPVMMR0REQHDR Hdr;
+ /** Page id. */
+ uint32_t idPage;
+ /** Duplicate flag (out) */
+ bool fDuplicate;
+} GMMFINDDUPLICATEPAGEREQ;
+/** Pointer to a GMMR0FindDuplicatePageReq / VMMR0_DO_GMM_FIND_DUPLICATE_PAGE request buffer. */
+typedef GMMFINDDUPLICATEPAGEREQ *PGMMFINDDUPLICATEPAGEREQ;
+
+GMMR0DECL(int) GMMR0FindDuplicatePageReq(PGVM pGVM, PGMMFINDDUPLICATEPAGEREQ pReq);
+#endif /* VBOX_STRICT && HC_ARCH_BITS == 64 */
+
+
+/**
+ * Request buffer for GMMR0QueryStatisticsReq / VMMR0_DO_GMM_QUERY_STATISTICS.
+ * @see GMMR0QueryStatistics.
+ */
+typedef struct GMMQUERYSTATISTICSSREQ
+{
+ /** The header. */
+ SUPVMMR0REQHDR Hdr;
+ /** The support driver session. */
+ PSUPDRVSESSION pSession;
+ /** The statistics. */
+ GMMSTATS Stats;
+} GMMQUERYSTATISTICSSREQ;
+/** Pointer to a GMMR0QueryStatisticsReq / VMMR0_DO_GMM_QUERY_STATISTICS
+ * request buffer. */
+typedef GMMQUERYSTATISTICSSREQ *PGMMQUERYSTATISTICSSREQ;
+
+GMMR0DECL(int) GMMR0QueryStatisticsReq(PGVM pGVM, PGMMQUERYSTATISTICSSREQ pReq);
+
+
+/**
+ * Request buffer for GMMR0ResetStatisticsReq / VMMR0_DO_GMM_RESET_STATISTICS.
+ * @see GMMR0ResetStatistics.
+ */
+typedef struct GMMRESETSTATISTICSSREQ
+{
+ /** The header. */
+ SUPVMMR0REQHDR Hdr;
+ /** The support driver session. */
+ PSUPDRVSESSION pSession;
+ /** The statistics to reset.
+ * Any non-zero entry will be reset (if permitted). */
+ GMMSTATS Stats;
+} GMMRESETSTATISTICSSREQ;
+/** Pointer to a GMMR0ResetStatisticsReq / VMMR0_DO_GMM_RESET_STATISTICS
+ * request buffer. */
+typedef GMMRESETSTATISTICSSREQ *PGMMRESETSTATISTICSSREQ;
+
+GMMR0DECL(int) GMMR0ResetStatisticsReq(PGVM pGVM, PGMMRESETSTATISTICSSREQ pReq);
+
+
+
+#ifdef IN_RING3
+/** @defgroup grp_gmm_r3 The Global Memory Manager Ring-3 API Wrappers
+ * @{
+ */
+GMMR3DECL(int) GMMR3InitialReservation(PVM pVM, uint64_t cBasePages, uint32_t cShadowPages, uint32_t cFixedPages,
+ GMMOCPOLICY enmPolicy, GMMPRIORITY enmPriority);
+GMMR3DECL(int) GMMR3UpdateReservation(PVM pVM, uint64_t cBasePages, uint32_t cShadowPages, uint32_t cFixedPages);
+GMMR3DECL(int) GMMR3AllocatePagesPrepare(PVM pVM, PGMMALLOCATEPAGESREQ *ppReq, uint32_t cPages, GMMACCOUNT enmAccount);
+GMMR3DECL(int) GMMR3AllocatePagesPerform(PVM pVM, PGMMALLOCATEPAGESREQ pReq);
+GMMR3DECL(void) GMMR3AllocatePagesCleanup(PGMMALLOCATEPAGESREQ pReq);
+GMMR3DECL(int) GMMR3FreePagesPrepare(PVM pVM, PGMMFREEPAGESREQ *ppReq, uint32_t cPages, GMMACCOUNT enmAccount);
+GMMR3DECL(void) GMMR3FreePagesRePrep(PVM pVM, PGMMFREEPAGESREQ pReq, uint32_t cPages, GMMACCOUNT enmAccount);
+GMMR3DECL(int) GMMR3FreePagesPerform(PVM pVM, PGMMFREEPAGESREQ pReq, uint32_t cActualPages);
+GMMR3DECL(void) GMMR3FreePagesCleanup(PGMMFREEPAGESREQ pReq);
+GMMR3DECL(void) GMMR3FreeAllocatedPages(PVM pVM, GMMALLOCATEPAGESREQ const *pAllocReq);
+GMMR3DECL(int) GMMR3AllocateLargePage(PVM pVM, uint32_t cbPage);
+GMMR3DECL(int) GMMR3FreeLargePage(PVM pVM, uint32_t idPage);
+GMMR3DECL(int) GMMR3MapUnmapChunk(PVM pVM, uint32_t idChunkMap, uint32_t idChunkUnmap, PRTR3PTR ppvR3);
+GMMR3DECL(int) GMMR3QueryHypervisorMemoryStats(PVM pVM, uint64_t *pcTotalAllocPages, uint64_t *pcTotalFreePages, uint64_t *pcTotalBalloonPages, uint64_t *puTotalBalloonSize);
+GMMR3DECL(int) GMMR3QueryMemoryStats(PVM pVM, uint64_t *pcAllocPages, uint64_t *pcMaxPages, uint64_t *pcBalloonPages);
+GMMR3DECL(int) GMMR3BalloonedPages(PVM pVM, GMMBALLOONACTION enmAction, uint32_t cBalloonedPages);
+GMMR3DECL(int) GMMR3RegisterSharedModule(PVM pVM, PGMMREGISTERSHAREDMODULEREQ pReq);
+GMMR3DECL(int) GMMR3UnregisterSharedModule(PVM pVM, PGMMUNREGISTERSHAREDMODULEREQ pReq);
+GMMR3DECL(int) GMMR3CheckSharedModules(PVM pVM);
+GMMR3DECL(int) GMMR3ResetSharedModules(PVM pVM);
+
+# if defined(VBOX_STRICT) && HC_ARCH_BITS == 64
+GMMR3DECL(bool) GMMR3IsDuplicatePage(PVM pVM, uint32_t idPage);
+# endif
+
+/** @} */
+#endif /* IN_RING3 */
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !VBOX_INCLUDED_vmm_gmm_h */
+
diff --git a/include/VBox/vmm/gvm.h b/include/VBox/vmm/gvm.h
new file mode 100644
index 00000000..8efdcc24
--- /dev/null
+++ b/include/VBox/vmm/gvm.h
@@ -0,0 +1,351 @@
+/* $Id: gvm.h $ */
+/** @file
+ * GVM - The Global VM Data.
+ */
+
+/*
+ * Copyright (C) 2007-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vmm_gvm_h
+#define VBOX_INCLUDED_vmm_gvm_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#ifndef USING_VMM_COMMON_DEFS
+# error "Compile job does not include VMM_COMMON_DEFS from src/VBox/Config.kmk - make sure you really need to include this file!"
+#endif
+#include <VBox/types.h>
+#include <VBox/vmm/vm.h>
+#include <VBox/param.h>
+#include <iprt/thread.h>
+#include <iprt/assertcompile.h>
+
+
+/** @defgroup grp_gvmcpu GVMCPU - The Global VMCPU Data
+ * @ingroup grp_vmm
+ * @{
+ */
+
+#if defined(__cplusplus) && !defined(GVM_C_STYLE_STRUCTURES)
+typedef struct GVMCPU : public VMCPU
+#else
+typedef struct GVMCPU
+#endif
+{
+#if !defined(__cplusplus) || defined(GVM_C_STYLE_STRUCTURES)
+ VMCPU s;
+#endif
+
+ /** VCPU id (0 - (pVM->cCpus - 1). */
+ VMCPUID idCpu;
+ /** Padding. */
+ uint32_t uPadding0;
+
+ /** Handle to the EMT thread. */
+ RTNATIVETHREAD hEMT;
+
+ /** Pointer to the global (ring-0) VM structure this CPU belongs to. */
+ R0PTRTYPE(PGVM) pGVM;
+ /** Pointer to the GVM structure, for CTX_SUFF use in VMMAll code. */
+ PGVM pVMR0;
+ /** The ring-3 address of this structure (only VMCPU part). */
+ PVMCPUR3 pVCpuR3;
+
+ /** Padding so the noisy stuff on a 64 byte boundrary.
+ * @note Keeping this working for 32-bit header syntax checking. */
+ uint8_t abPadding1[HC_ARCH_BITS == 32 ? 40 : 24];
+
+ /** Which host CPU ID is this EMT running on.
+ * Only valid when in RC or HMR0 with scheduling disabled. */
+ RTCPUID volatile idHostCpu;
+ /** The CPU set index corresponding to idHostCpu, UINT32_MAX if not valid.
+ * @remarks Best to make sure iHostCpuSet shares cache line with idHostCpu! */
+ uint32_t volatile iHostCpuSet;
+
+ /** Padding so gvmm starts on a 64 byte boundrary.
+ * @note Keeping this working for 32-bit header syntax checking. */
+ uint8_t abPadding2[56];
+
+ /** The GVMM per vcpu data. */
+ union
+ {
+#ifdef VMM_INCLUDED_SRC_VMMR0_GVMMR0Internal_h
+ struct GVMMPERVCPU s;
+#endif
+ uint8_t padding[256];
+ } gvmm;
+
+ /** The HM per vcpu data. */
+ union
+ {
+#if defined(VMM_INCLUDED_SRC_include_HMInternal_h) && defined(IN_RING0)
+ struct HMR0PERVCPU s;
+#endif
+ uint8_t padding[1024];
+ } hmr0;
+
+#ifdef VBOX_WITH_NEM_R0
+ /** The NEM per vcpu data. */
+ union
+ {
+# if defined(VMM_INCLUDED_SRC_include_NEMInternal_h) && defined(IN_RING0)
+ struct NEMR0PERVCPU s;
+# endif
+ uint8_t padding[64];
+ } nemr0;
+#endif
+
+ union
+ {
+#if defined(VMM_INCLUDED_SRC_include_VMMInternal_h) && defined(IN_RING0)
+ struct VMMR0PERVCPU s;
+#endif
+ uint8_t padding[896];
+ } vmmr0;
+
+ union
+ {
+#if defined(VMM_INCLUDED_SRC_include_PGMInternal_h) && defined(IN_RING0)
+ struct PGMR0PERVCPU s;
+#endif
+ uint8_t padding[64];
+ } pgmr0;
+
+ /** Padding the structure size to page boundrary. */
+#ifdef VBOX_WITH_NEM_R0
+ uint8_t abPadding3[16384 - 64*2 - 256 - 1024 - 64 - 896 - 64];
+#else
+ uint8_t abPadding3[16384 - 64*2 - 256 - 1024 - 896 - 64];
+#endif
+} GVMCPU;
+#if RT_GNUC_PREREQ(4, 6) && defined(__cplusplus)
+# pragma GCC diagnostic push
+#endif
+#if RT_GNUC_PREREQ(4, 3) && defined(__cplusplus)
+# pragma GCC diagnostic ignored "-Winvalid-offsetof"
+#endif
+AssertCompileMemberAlignment(GVMCPU, idCpu, 16384);
+AssertCompileMemberAlignment(GVMCPU, gvmm, 64);
+#ifdef VBOX_WITH_NEM_R0
+AssertCompileMemberAlignment(GVMCPU, nemr0, 64);
+#endif
+AssertCompileSizeAlignment(GVMCPU, 16384);
+#if RT_GNUC_PREREQ(4, 6) && defined(__cplusplus)
+# pragma GCC diagnostic pop
+#endif
+
+/** @} */
+
+/** @defgroup grp_gvm GVM - The Global VM Data
+ * @ingroup grp_vmm
+ * @{
+ */
+
+/**
+ * The Global VM Data.
+ *
+ * This is a ring-0 only structure where we put items we don't need to
+ * share with ring-3 or GC, like for instance various RTR0MEMOBJ handles.
+ *
+ * Unlike VM, there are no special alignment restrictions here. The
+ * paddings are checked by compile time assertions.
+ */
+#if defined(__cplusplus) && !defined(GVM_C_STYLE_STRUCTURES)
+typedef struct GVM : public VM
+#else
+typedef struct GVM
+#endif
+{
+#if !defined(__cplusplus) || defined(GVM_C_STYLE_STRUCTURES)
+ VM s;
+#endif
+ /** Magic / eye-catcher (GVM_MAGIC). */
+ uint32_t u32Magic;
+ /** The global VM handle for this VM. */
+ uint32_t hSelf;
+ /** Pointer to this structure (for validation purposes). */
+ PGVM pSelf;
+ /** The ring-3 mapping of the VM structure. */
+ PVMR3 pVMR3;
+ /** The support driver session the VM is associated with. */
+ PSUPDRVSESSION pSession;
+ /** Number of Virtual CPUs, i.e. how many entries there are in aCpus.
+ * Same same as VM::cCpus. */
+ uint32_t cCpus;
+ /** Padding so gvmm starts on a 64 byte boundrary. */
+ uint8_t abPadding[HC_ARCH_BITS == 32 ? 12 + 28 : 28];
+
+ /** The GVMM per vm data. */
+ union
+ {
+#ifdef VMM_INCLUDED_SRC_VMMR0_GVMMR0Internal_h
+ struct GVMMPERVM s;
+#endif
+ uint8_t padding[4352];
+ } gvmm;
+
+ /** The GMM per vm data. */
+ union
+ {
+#ifdef VMM_INCLUDED_SRC_VMMR0_GMMR0Internal_h
+ struct GMMPERVM s;
+#endif
+ uint8_t padding[1024];
+ } gmm;
+
+ /** The HM per vm data. */
+ union
+ {
+#if defined(VMM_INCLUDED_SRC_include_HMInternal_h) && defined(IN_RING0)
+ struct HMR0PERVM s;
+#endif
+ uint8_t padding[256];
+ } hmr0;
+
+#ifdef VBOX_WITH_NEM_R0
+ /** The NEM per vcpu data. */
+ union
+ {
+# if defined(VMM_INCLUDED_SRC_include_NEMInternal_h) && defined(IN_RING0)
+ struct NEMR0PERVM s;
+# endif
+ uint8_t padding[256];
+ } nemr0;
+#endif
+
+ /** The RAWPCIVM per vm data. */
+ union
+ {
+#ifdef VBOX_INCLUDED_rawpci_h
+ struct RAWPCIPERVM s;
+#endif
+ uint8_t padding[64];
+ } rawpci;
+
+ union
+ {
+#if defined(VMM_INCLUDED_SRC_include_PDMInternal_h) && defined(IN_RING0)
+ struct PDMR0PERVM s;
+#endif
+ uint8_t padding[3008];
+ } pdmr0;
+
+ union
+ {
+#if defined(VMM_INCLUDED_SRC_include_PGMInternal_h) && defined(IN_RING0)
+ struct PGMR0PERVM s;
+#endif
+ uint8_t padding[1920];
+ } pgmr0;
+
+ union
+ {
+#if defined(VMM_INCLUDED_SRC_include_IOMInternal_h) && defined(IN_RING0)
+ struct IOMR0PERVM s;
+#endif
+ uint8_t padding[512];
+ } iomr0;
+
+ union
+ {
+#if defined(VMM_INCLUDED_SRC_include_APICInternal_h) && defined(IN_RING0)
+ struct APICR0PERVM s;
+#endif
+ uint8_t padding[64];
+ } apicr0;
+
+ union
+ {
+#if defined(VMM_INCLUDED_SRC_include_DBGFInternal_h) && defined(IN_RING0)
+ struct DBGFR0PERVM s;
+#endif
+ uint8_t padding[1024];
+ } dbgfr0;
+
+ union
+ {
+#if defined(VMM_INCLUDED_SRC_include_TMInternal_h) && defined(IN_RING0)
+ TMR0PERVM s;
+#endif
+ uint8_t padding[192];
+ } tmr0;
+
+ union
+ {
+#if defined(VMM_INCLUDED_SRC_include_VMMInternal_h) && defined(IN_RING0)
+ VMMR0PERVM s;
+#endif
+ uint8_t padding[704];
+ } vmmr0;
+
+ /** Padding so aCpus starts on a page boundrary. */
+#ifdef VBOX_WITH_NEM_R0
+ uint8_t abPadding2[16384 - 64 - 4352 - 1024 - 256 - 256 - 64 - 3008 - 1920 - 512 - 64 - 1024 - 192 - 704 - sizeof(PGVMCPU) * VMM_MAX_CPU_COUNT];
+#else
+ uint8_t abPadding2[16384 - 64 - 4352 - 1024 - 256 - 64 - 3008 - 1920 - 512 - 64 - 1024 - 192 - 704 - sizeof(PGVMCPU) * VMM_MAX_CPU_COUNT];
+#endif
+
+ /** For simplifying CPU enumeration in VMMAll code. */
+ PGVMCPU apCpusR0[VMM_MAX_CPU_COUNT];
+
+ /** GVMCPU array for the configured number of virtual CPUs. */
+ GVMCPU aCpus[1];
+} GVM;
+#if 0
+#if RT_GNUC_PREREQ(4, 6) && defined(__cplusplus)
+# pragma GCC diagnostic push
+#endif
+#if RT_GNUC_PREREQ(4, 3) && defined(__cplusplus)
+# pragma GCC diagnostic ignored "-Winvalid-offsetof"
+#endif
+AssertCompileMemberAlignment(GVM, u32Magic, 64);
+AssertCompileMemberAlignment(GVM, gvmm, 64);
+AssertCompileMemberAlignment(GVM, gmm, 64);
+#ifdef VBOX_WITH_NEM_R0
+AssertCompileMemberAlignment(GVM, nemr0, 64);
+#endif
+AssertCompileMemberAlignment(GVM, rawpci, 64);
+AssertCompileMemberAlignment(GVM, pdmr0, 64);
+AssertCompileMemberAlignment(GVM, aCpus, 16384);
+AssertCompileSizeAlignment(GVM, 16384);
+#if RT_GNUC_PREREQ(4, 6) && defined(__cplusplus)
+# pragma GCC diagnostic pop
+#endif
+#endif
+
+/** The GVM::u32Magic value (Wayne Shorter). */
+#define GVM_MAGIC 0x19330825
+
+/** @} */
+
+#endif /* !VBOX_INCLUDED_vmm_gvm_h */
+
diff --git a/include/VBox/vmm/gvm.mac b/include/VBox/vmm/gvm.mac
new file mode 100644
index 00000000..af43f6ed
--- /dev/null
+++ b/include/VBox/vmm/gvm.mac
@@ -0,0 +1,118 @@
+;; @file
+; GVM - The Global VM Data.
+;
+
+;
+; Copyright (C) 2006-2022 Oracle and/or its affiliates.
+;
+; This file is part of VirtualBox base platform packages, as
+; available from https://www.virtualbox.org.
+;
+; This program is free software; you can redistribute it and/or
+; modify it under the terms of the GNU General Public License
+; as published by the Free Software Foundation, in version 3 of the
+; License.
+;
+; This program is distributed in the hope that it will be useful, but
+; WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with this program; if not, see <https://www.gnu.org/licenses>.
+;
+; The contents of this file may alternatively be used under the terms
+; of the Common Development and Distribution License Version 1.0
+; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+; in the VirtualBox 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.
+;
+; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+;
+
+%ifndef ___VBox_vmm_gvm_mac
+%define ___VBox_vmm_gvm_mac
+
+%include "VBox/vmm/vm.mac"
+
+struc GVMCPU
+ .s resb VMCPU_size
+
+ .idCpu resd 1
+
+ alignb 8
+ .hEMT RTR0PTR_RES 1
+ .pGVM RTR0PTR_RES 1
+ .pVMR0 RTR0PTR_RES 1
+ .pVCpuR3 RTR3PTR_RES 1
+
+ alignb 64
+ .idHostCpu resd 1
+ .iHostCpuSet resd 1
+
+ alignb 64
+ .gvmm resb 256
+ alignb 64
+ .hmr0 resb 1024
+%ifdef VBOX_WITH_NEM_R0
+ .nemr0 resb 64
+%endif
+ alignb 64
+ .vmmr0 resb 896
+ alignb 64
+ .pgmr0 resb 64
+ alignb 16384
+endstruc
+
+
+struc GVM
+ .s resb VM_size
+
+ .u32Magic resd 1
+ .hSelf resd 1
+ alignb 8
+ .pSelf RTR0PTR_RES 1
+ .pVMR3 RTR3PTR_RES 1
+ .pSession RTR0PTR_RES 1
+ .cCpus resd 1
+
+ alignb 64
+ .gvmm resb 4352
+ alignb 64
+ .gmm resb 1024
+ alignb 64
+ .hmr0 resb 256
+%ifdef VBOX_WITH_NEM_R0
+ alignb 64
+ .nemr0 resb 256
+%endif
+ alignb 64
+ .rawpci resb 64
+ alignb 64
+ .pdmr0 resb 3008
+ alignb 64
+ .pgmr0 resb 1920
+ alignb 64
+ .iomr0 resb 512
+ alignb 64
+ .apicr0 resb 64
+ alignb 64
+ .dbgfr0 resb 1024
+ alignb 64
+ .tmr0 resb 128
+
+ times ((($ + VMM_MAX_CPU_COUNT * RTR0PTR_CB + 16383) & ~16383) - ($ + VMM_MAX_CPU_COUNT * RTR0PTR_CB)) resb 1
+ .apCpusR0 RTR0PTR_RES VMM_MAX_CPU_COUNT
+
+ alignb 16384
+ .aCpus resb GVMCPU_size
+endstruc
+
+%define GVM_MAGIC 0x19330825
+
+
+%endif
+
diff --git a/include/VBox/vmm/gvmm.h b/include/VBox/vmm/gvmm.h
new file mode 100644
index 00000000..788c41d4
--- /dev/null
+++ b/include/VBox/vmm/gvmm.h
@@ -0,0 +1,364 @@
+/* $Id: gvmm.h $ */
+/** @file
+ * GVMM - The Global VM Manager.
+ */
+
+/*
+ * Copyright (C) 2007-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vmm_gvmm_h
+#define VBOX_INCLUDED_vmm_gvmm_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/types.h>
+#include <VBox/vmm/stam.h>
+#include <VBox/sup.h>
+#include <VBox/param.h>
+#include <iprt/cpuset.h> /* RTCPUSET_MAX_CPUS */
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_gvmm GVMM - The Global VM Manager.
+ * @ingroup grp_vmm
+ * @{
+ */
+
+/** @def IN_GVMM_R0
+ * Used to indicate whether we're inside the same link module as the ring 0
+ * part of the Global VM Manager or not.
+ */
+#ifdef DOXYGEN_RUNNING
+# define IN_GVMM_R0
+#endif
+/** @def GVMMR0DECL
+ * Ring 0 VM export or import declaration.
+ * @param type The return type of the function declaration.
+ */
+#ifdef IN_GVMM_R0
+# define GVMMR0DECL(type) DECLEXPORT(type) VBOXCALL
+#else
+# define GVMMR0DECL(type) DECLIMPORT(type) VBOXCALL
+#endif
+
+/** @def NIL_GVM_HANDLE
+ * The nil GVM VM handle value (VM::hSelf).
+ */
+#define NIL_GVM_HANDLE 0
+
+
+/**
+ * The scheduler statistics
+ */
+typedef struct GVMMSTATSSCHED
+{
+ /** The number of calls to GVMMR0SchedHalt. */
+ uint64_t cHaltCalls;
+ /** The number of times we did go to sleep in GVMMR0SchedHalt. */
+ uint64_t cHaltBlocking;
+ /** The number of times we timed out in GVMMR0SchedHalt. */
+ uint64_t cHaltTimeouts;
+ /** The number of times we didn't go to sleep in GVMMR0SchedHalt. */
+ uint64_t cHaltNotBlocking;
+ /** The number of wake ups done during GVMMR0SchedHalt. */
+ uint64_t cHaltWakeUps;
+
+ /** The number of calls to GVMMR0WakeUp. */
+ uint64_t cWakeUpCalls;
+ /** The number of times the EMT thread wasn't actually halted when GVMMR0WakeUp
+ * was called. */
+ uint64_t cWakeUpNotHalted;
+ /** The number of wake ups done during GVMMR0WakeUp (not counting the explicit
+ * one). */
+ uint64_t cWakeUpWakeUps;
+
+ /** The number of calls to GVMMR0Poke. */
+ uint64_t cPokeCalls;
+ /** The number of times the EMT thread wasn't actually busy when
+ * GVMMR0Poke was called. */
+ uint64_t cPokeNotBusy;
+
+ /** The number of calls to GVMMR0SchedPoll. */
+ uint64_t cPollCalls;
+ /** The number of times the EMT has halted in a GVMMR0SchedPoll call. */
+ uint64_t cPollHalts;
+ /** The number of wake ups done during GVMMR0SchedPoll. */
+ uint64_t cPollWakeUps;
+
+ uint64_t u64Alignment; /**< padding */
+} GVMMSTATSSCHED;
+/** Pointer to the GVMM scheduler statistics. */
+typedef GVMMSTATSSCHED *PGVMMSTATSSCHED;
+
+/**
+ * Per host cpu statistics.
+ */
+typedef struct GVMMSTATSHOSTCPU
+{
+ /** The CPU ID. */
+ RTCPUID idCpu;
+ /** The CPU's set index. */
+ uint32_t idxCpuSet;
+ /** The desired PPT frequency. */
+ uint32_t uDesiredHz;
+ /** The current PPT timer frequency. */
+ uint32_t uTimerHz;
+ /** The number of times the PPT was changed. */
+ uint32_t cChanges;
+ /** The number of times the PPT was started. */
+ uint32_t cStarts;
+} GVMMSTATSHOSTCPU;
+/** Pointer to the GVMM per host CPU statistics. */
+typedef GVMMSTATSHOSTCPU *PGVMMSTATSHOSTCPU;
+
+/**
+ * Per VCpu statistics
+ */
+typedef struct GVMMSTATSVMCPU
+{
+ uint32_t cWakeUpTimerHits;
+ uint32_t cWakeUpTimerMisses;
+ uint32_t cWakeUpTimerCanceled;
+ uint32_t cWakeUpTimerSameCpu;
+ STAMPROFILE Start;
+ STAMPROFILE Stop;
+} GVMMSTATSVMCPU;
+/** Ptoiner to the GVMM per VCpu statistics. */
+typedef GVMMSTATSVMCPU *PGVMMSTATSVMCPU;
+
+/**
+ * The GVMM statistics.
+ */
+typedef struct GVMMSTATS
+{
+ /** The VM statistics if a VM was specified. */
+ GVMMSTATSSCHED SchedVM;
+ /** The sum statistics of all VMs accessible to the caller. */
+ GVMMSTATSSCHED SchedSum;
+ /** The number of VMs accessible to the caller. */
+ uint32_t cVMs;
+ /** The number of emulation threads in those VMs. */
+ uint32_t cEMTs;
+ /** Padding. */
+ uint32_t u32Padding;
+ /** The number of valid entries in aHostCpus. */
+ uint32_t cHostCpus;
+ /** Per EMT statistics for the specified VM, zero if non specified. */
+ GVMMSTATSVMCPU aVCpus[VMM_MAX_CPU_COUNT];
+ /** Per host CPU statistics. */
+ GVMMSTATSHOSTCPU aHostCpus[RTCPUSET_MAX_CPUS];
+} GVMMSTATS;
+/** Pointer to the GVMM statistics. */
+typedef GVMMSTATS *PGVMMSTATS;
+/** Const pointer to the GVMM statistics. */
+typedef const GVMMSTATS *PCGVMMSTATS;
+
+/**
+ * Per-VM callback for GVMMR0EnumVMs.
+ *
+ * @note This is called while holding the VM used list lock, so only suitable
+ * for quick and simple jobs!
+ *
+ * @returns VINF_SUCCESS to continue the enumeration, anything stops it and
+ * returns the status code.
+ * @param pGVM The VM
+ * @param pvUser The user parameter.
+ * */
+typedef DECLCALLBACKTYPE(int, FNGVMMR0ENUMCALLBACK,(PGVM pGVM, void *pvUser));
+/** Pointer to an VM enumeration callback function. */
+typedef FNGVMMR0ENUMCALLBACK *PFNGVMMR0ENUMCALLBACK;
+
+/**
+ * Worker thread IDs.
+ */
+typedef enum GVMMWORKERTHREAD
+{
+ /** The usual invalid zero value. */
+ GVMMWORKERTHREAD_INVALID = 0,
+ /** PGM handy page allocator thread. */
+ GVMMWORKERTHREAD_PGM_ALLOCATOR,
+ /** End of valid worker thread values. */
+ GVMMWORKERTHREAD_END,
+ /** Make sure the type size is 32 bits. */
+ GVMMWORKERTHREAD_32_BIT_HACK = 0x7fffffff
+} GVMMWORKERTHREAD;
+
+GVMMR0DECL(int) GVMMR0Init(void);
+GVMMR0DECL(void) GVMMR0Term(void);
+GVMMR0DECL(int) GVMMR0SetConfig(PSUPDRVSESSION pSession, const char *pszName, uint64_t u64Value);
+GVMMR0DECL(int) GVMMR0QueryConfig(PSUPDRVSESSION pSession, const char *pszName, uint64_t *pu64Value);
+
+GVMMR0DECL(int) GVMMR0CreateVM(PSUPDRVSESSION pSession, uint32_t cCpus, PVMCC *ppVM);
+GVMMR0DECL(int) GVMMR0InitVM(PGVM pGVM);
+GVMMR0DECL(void) GVMMR0DoneInitVM(PGVM pGVM);
+GVMMR0DECL(bool) GVMMR0DoingTermVM(PGVM pGVM);
+GVMMR0DECL(int) GVMMR0DestroyVM(PGVM pGVM);
+GVMMR0DECL(int) GVMMR0RegisterVCpu(PGVM pGVM, VMCPUID idCpu);
+GVMMR0DECL(int) GVMMR0DeregisterVCpu(PGVM pGVM, VMCPUID idCpu);
+GVMMR0DECL(int) GVMMR0RegisterWorkerThread(PGVM pGVM, GVMMWORKERTHREAD enmWorker, RTNATIVETHREAD hThreadR3);
+GVMMR0DECL(int) GVMMR0DeregisterWorkerThread(PGVM pGVM, GVMMWORKERTHREAD enmWorker);
+GVMMR0DECL(PGVM) GVMMR0ByHandle(uint32_t hGVM);
+GVMMR0DECL(int) GVMMR0ValidateGVM(PGVM pGVM);
+GVMMR0DECL(int) GVMMR0ValidateGVMandEMT(PGVM pGVM, VMCPUID idCpu);
+GVMMR0DECL(int) GVMMR0ValidateGVMandEMTorWorker(PGVM pGVM, VMCPUID idCpu, GVMMWORKERTHREAD enmWorker);
+GVMMR0DECL(PVMCC) GVMMR0GetVMByEMT(RTNATIVETHREAD hEMT);
+GVMMR0DECL(PGVMCPU) GVMMR0GetGVCpuByEMT(RTNATIVETHREAD hEMT);
+GVMMR0DECL(PGVMCPU) GVMMR0GetGVCpuByGVMandEMT(PGVM pGVM, RTNATIVETHREAD hEMT);
+GVMMR0DECL(RTNATIVETHREAD) GVMMR0GetRing3ThreadForSelf(PGVM pGVM);
+GVMMR0DECL(RTHCPHYS) GVMMR0ConvertGVMPtr2HCPhys(PGVM pGVM, void *pv);
+GVMMR0DECL(int) GVMMR0SchedHalt(PGVM pGVM, PGVMCPU pGVCpu, uint64_t u64ExpireGipTime);
+GVMMR0DECL(int) GVMMR0SchedHaltReq(PGVM pGVM, VMCPUID idCpu, uint64_t u64ExpireGipTime);
+GVMMR0DECL(int) GVMMR0SchedWakeUp(PGVM pGVM, VMCPUID idCpu);
+GVMMR0DECL(int) GVMMR0SchedWakeUpEx(PGVM pGVM, VMCPUID idCpu, bool fTakeUsedLock);
+GVMMR0DECL(int) GVMMR0SchedWakeUpNoGVMNoLock(PGVM pGVM, VMCPUID idCpu);
+GVMMR0DECL(int) GVMMR0SchedPoke(PGVM pGVM, VMCPUID idCpu);
+GVMMR0DECL(int) GVMMR0SchedPokeEx(PGVM pGVM, VMCPUID idCpu, bool fTakeUsedLock);
+GVMMR0DECL(int) GVMMR0SchedPokeNoGVMNoLock(PVMCC pVM, VMCPUID idCpu);
+GVMMR0DECL(int) GVMMR0SchedWakeUpAndPokeCpus(PGVM pGVM, PCVMCPUSET pSleepSet, PCVMCPUSET pPokeSet);
+GVMMR0DECL(int) GVMMR0SchedPoll(PGVM pGVM, VMCPUID idCpu, bool fYield);
+GVMMR0DECL(void) GVMMR0SchedUpdatePeriodicPreemptionTimer(PGVM pGVM, RTCPUID idHostCpu, uint32_t uHz);
+GVMMR0DECL(int) GVMMR0EnumVMs(PFNGVMMR0ENUMCALLBACK pfnCallback, void *pvUser);
+GVMMR0DECL(int) GVMMR0QueryStatistics(PGVMMSTATS pStats, PSUPDRVSESSION pSession, PGVM pGVM);
+GVMMR0DECL(int) GVMMR0ResetStatistics(PCGVMMSTATS pStats, PSUPDRVSESSION pSession, PGVM pGVM);
+
+
+/**
+ * Request packet for calling GVMMR0CreateVM.
+ */
+typedef struct GVMMCREATEVMREQ
+{
+ /** The request header. */
+ SUPVMMR0REQHDR Hdr;
+ /** The support driver session. (IN) */
+ PSUPDRVSESSION pSession;
+ /** Number of virtual CPUs for the new VM. (IN) */
+ uint32_t cCpus;
+ /** Pointer to the ring-3 mapping of the shared VM structure on return. (OUT) */
+ PVMR3 pVMR3;
+ /** Pointer to the ring-0 mapping of the shared VM structure on return. (OUT) */
+ PVMR0 pVMR0;
+} GVMMCREATEVMREQ;
+/** Pointer to a GVMMR0CreateVM request packet. */
+typedef GVMMCREATEVMREQ *PGVMMCREATEVMREQ;
+
+GVMMR0DECL(int) GVMMR0CreateVMReq(PGVMMCREATEVMREQ pReq, PSUPDRVSESSION pSession);
+
+
+/**
+ * Request packet for calling GVMMR0RegisterWorkerThread.
+ */
+typedef struct GVMMREGISTERWORKERTHREADREQ
+{
+ /** The request header. */
+ SUPVMMR0REQHDR Hdr;
+ /** Ring-3 native thread handle of the caller. (IN) */
+ RTNATIVETHREAD hNativeThreadR3;
+} GVMMREGISTERWORKERTHREADREQ;
+/** Pointer to a GVMMR0RegisterWorkerThread request packet. */
+typedef GVMMREGISTERWORKERTHREADREQ *PGVMMREGISTERWORKERTHREADREQ;
+
+
+/**
+ * Request buffer for GVMMR0SchedWakeUpAndPokeCpusReq / VMMR0_DO_GVMM_SCHED_WAKE_UP_AND_POKE_CPUS.
+ * @see GVMMR0SchedWakeUpAndPokeCpus.
+ */
+typedef struct GVMMSCHEDWAKEUPANDPOKECPUSREQ /* nice and unreadable... */
+{
+ /** The header. */
+ SUPVMMR0REQHDR Hdr;
+ /** The sleeper set. */
+ VMCPUSET SleepSet;
+ /** The set of virtual CPUs to poke. */
+ VMCPUSET PokeSet;
+} GVMMSCHEDWAKEUPANDPOKECPUSREQ;
+/** Pointer to a GVMMR0QueryStatisticsReq / VMMR0_DO_GVMM_QUERY_STATISTICS request buffer. */
+typedef GVMMSCHEDWAKEUPANDPOKECPUSREQ *PGVMMSCHEDWAKEUPANDPOKECPUSREQ;
+
+GVMMR0DECL(int) GVMMR0SchedWakeUpAndPokeCpusReq(PGVM pGVM, PGVMMSCHEDWAKEUPANDPOKECPUSREQ pReq);
+
+
+/**
+ * Request buffer for GVMMR0QueryStatisticsReq / VMMR0_DO_GVMM_QUERY_STATISTICS.
+ * @see GVMMR0QueryStatistics.
+ */
+typedef struct GVMMQUERYSTATISTICSSREQ
+{
+ /** The header. */
+ SUPVMMR0REQHDR Hdr;
+ /** The support driver session. */
+ PSUPDRVSESSION pSession;
+ /** The statistics. */
+ GVMMSTATS Stats;
+} GVMMQUERYSTATISTICSSREQ;
+/** Pointer to a GVMMR0QueryStatisticsReq / VMMR0_DO_GVMM_QUERY_STATISTICS request buffer. */
+typedef GVMMQUERYSTATISTICSSREQ *PGVMMQUERYSTATISTICSSREQ;
+
+GVMMR0DECL(int) GVMMR0QueryStatisticsReq(PGVM pGVM, PGVMMQUERYSTATISTICSSREQ pReq, PSUPDRVSESSION pSession);
+
+
+/**
+ * Request buffer for GVMMR0ResetStatisticsReq / VMMR0_DO_GVMM_RESET_STATISTICS.
+ * @see GVMMR0ResetStatistics.
+ */
+typedef struct GVMMRESETSTATISTICSSREQ
+{
+ /** The header. */
+ SUPVMMR0REQHDR Hdr;
+ /** The support driver session. */
+ PSUPDRVSESSION pSession;
+ /** The statistics to reset.
+ * Any non-zero entry will be reset (if permitted). */
+ GVMMSTATS Stats;
+} GVMMRESETSTATISTICSSREQ;
+/** Pointer to a GVMMR0ResetStatisticsReq / VMMR0_DO_GVMM_RESET_STATISTICS request buffer. */
+typedef GVMMRESETSTATISTICSSREQ *PGVMMRESETSTATISTICSSREQ;
+
+GVMMR0DECL(int) GVMMR0ResetStatisticsReq(PGVM pGVM, PGVMMRESETSTATISTICSSREQ pReq, PSUPDRVSESSION pSession);
+
+
+#ifdef IN_RING3
+VMMR3_INT_DECL(int) GVMMR3CreateVM(PUVM pUVM, uint32_t cCpus, PSUPDRVSESSION pSession, PVM *ppVM, PRTR0PTR ppVMR0);
+VMMR3_INT_DECL(int) GVMMR3DestroyVM(PUVM pUVM, PVM pVM);
+VMMR3_INT_DECL(int) GVMMR3RegisterVCpu(PVM pVM, VMCPUID idCpu);
+VMMR3_INT_DECL(int) GVMMR3DeregisterVCpu(PVM pVM, VMCPUID idCpu);
+VMMR3_INT_DECL(int) GVMMR3RegisterWorkerThread(PVM pVM, GVMMWORKERTHREAD enmWorker);
+VMMR3_INT_DECL(int) GVMMR3DeregisterWorkerThread(PVM pVM, GVMMWORKERTHREAD enmWorker);
+#endif
+
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !VBOX_INCLUDED_vmm_gvmm_h */
+
diff --git a/include/VBox/vmm/hm.h b/include/VBox/vmm/hm.h
new file mode 100644
index 00000000..2dc1d976
--- /dev/null
+++ b/include/VBox/vmm/hm.h
@@ -0,0 +1,336 @@
+/** @file
+ * HM - Intel/AMD VM Hardware Assisted Virtualization Manager (VMM)
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vmm_hm_h
+#define VBOX_INCLUDED_vmm_hm_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/vmm/pgm.h>
+#include <VBox/vmm/cpum.h>
+#include <VBox/vmm/vmm.h>
+#include <VBox/vmm/hm_svm.h>
+#include <VBox/vmm/hm_vmx.h>
+#include <VBox/vmm/trpm.h>
+#include <iprt/mp.h>
+
+
+/** @defgroup grp_hm The Hardware Assisted Virtualization Manager API
+ * @ingroup grp_vmm
+ * @{
+ */
+
+RT_C_DECLS_BEGIN
+
+/**
+ * Checks whether HM (VT-x/AMD-V) is being used by this VM.
+ *
+ * @retval true if used.
+ * @retval false if software virtualization (raw-mode) or NEM is used.
+ *
+ * @param a_pVM The cross context VM structure.
+ * @deprecated Please use VM_IS_RAW_MODE_ENABLED, VM_IS_HM_OR_NEM_ENABLED, or
+ * VM_IS_HM_ENABLED instead.
+ * @internal
+ */
+#if defined(VBOX_STRICT) && defined(IN_RING3)
+# define HMIsEnabled(a_pVM) HMIsEnabledNotMacro(a_pVM)
+#else
+# define HMIsEnabled(a_pVM) ((a_pVM)->fHMEnabled)
+#endif
+
+/**
+ * Checks whether raw-mode context is required for HM purposes
+ *
+ * @retval true if required by HM for doing switching the cpu to 64-bit mode.
+ * @retval false if not required by HM.
+ *
+ * @param a_pVM The cross context VM structure.
+ * @internal
+ */
+#if HC_ARCH_BITS == 64
+# define HMIsRawModeCtxNeeded(a_pVM) (false)
+#else
+# define HMIsRawModeCtxNeeded(a_pVM) ((a_pVM)->fHMNeedRawModeCtx)
+#endif
+
+/**
+ * Checks whether we're in the special hardware virtualization context.
+ * @returns true / false.
+ * @param a_pVCpu The caller's cross context virtual CPU structure.
+ * @thread EMT
+ */
+#ifdef IN_RING0
+# define HMIsInHwVirtCtx(a_pVCpu) (VMCPU_GET_STATE(a_pVCpu) == VMCPUSTATE_STARTED_HM)
+#else
+# define HMIsInHwVirtCtx(a_pVCpu) (false)
+#endif
+
+/**
+ * Checks whether we're in the special hardware virtualization context and we
+ * cannot perform long jump without guru meditating and possibly messing up the
+ * host and/or guest state.
+ *
+ * This is after we've turned interrupts off and such.
+ *
+ * @returns true / false.
+ * @param a_pVCpu The caller's cross context virtual CPU structure.
+ * @thread EMT
+ */
+#ifdef IN_RING0
+# define HMIsInHwVirtNoLongJmpCtx(a_pVCpu) (VMCPU_GET_STATE(a_pVCpu) == VMCPUSTATE_STARTED_EXEC)
+#else
+# define HMIsInHwVirtNoLongJmpCtx(a_pVCpu) (false)
+#endif
+
+/** @name All-context HM API.
+ * @{ */
+VMMDECL(bool) HMIsEnabledNotMacro(PVM pVM);
+VMMDECL(bool) HMCanExecuteGuest(PVMCC pVM, PVMCPUCC pVCpu, PCCPUMCTX pCtx);
+VMM_INT_DECL(int) HMInvalidatePage(PVMCPUCC pVCpu, RTGCPTR GCVirt);
+VMM_INT_DECL(bool) HMHasPendingIrq(PVMCC pVM);
+VMM_INT_DECL(bool) HMSetSingleInstruction(PVMCC pVM, PVMCPUCC pVCpu, bool fEnable);
+VMM_INT_DECL(bool) HMIsSvmActive(PVM pVM);
+VMM_INT_DECL(bool) HMIsVmxActive(PVM pVM);
+VMM_INT_DECL(const char *) HMGetVmxDiagDesc(VMXVDIAG enmDiag);
+VMM_INT_DECL(const char *) HMGetVmxExitName(uint32_t uExit);
+VMM_INT_DECL(const char *) HMGetSvmExitName(uint32_t uExit);
+VMM_INT_DECL(void) HMDumpHwvirtVmxState(PVMCPU pVCpu);
+VMM_INT_DECL(void) HMHCChangedPagingMode(PVM pVM, PVMCPUCC pVCpu, PGMMODE enmShadowMode, PGMMODE enmGuestMode);
+VMM_INT_DECL(void) HMGetVmxMsrsFromHwvirtMsrs(PCSUPHWVIRTMSRS pMsrs, PVMXMSRS pVmxMsrs);
+VMM_INT_DECL(void) HMGetSvmMsrsFromHwvirtMsrs(PCSUPHWVIRTMSRS pMsrs, PSVMMSRS pSvmMsrs);
+/** @} */
+
+/** @name All-context VMX helpers.
+ *
+ * These are hardware-assisted VMX functions (used by IEM/REM/CPUM and HM). Helpers
+ * based purely on the Intel VT-x specification (used by IEM/REM and HM) can be
+ * found in CPUM.
+ * @{ */
+#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
+VMM_INT_DECL(bool) HMIsSubjectToVmxPreemptTimerErratum(void);
+#endif
+VMM_INT_DECL(bool) HMCanExecuteVmxGuest(PVMCC pVM, PVMCPUCC pVCpu, PCCPUMCTX pCtx);
+VMM_INT_DECL(TRPMEVENT) HMVmxEventTypeToTrpmEventType(uint32_t uIntInfo);
+VMM_INT_DECL(uint32_t) HMTrpmEventTypeToVmxEventType(uint8_t uVector, TRPMEVENT enmTrpmEvent, bool fIcebp);
+/** @} */
+
+/** @name All-context SVM helpers.
+ *
+ * These are hardware-assisted SVM functions (used by IEM/REM/CPUM and HM). Helpers
+ * based purely on the AMD SVM specification (used by IEM/REM and HM) can be found
+ * in CPUM.
+ * @{ */
+VMM_INT_DECL(TRPMEVENT) HMSvmEventToTrpmEventType(PCSVMEVENT pSvmEvent, uint8_t uVector);
+/** @} */
+
+#ifndef IN_RC
+
+/** @name R0, R3 HM (VMX/SVM agnostic) handlers.
+ * @{ */
+VMM_INT_DECL(int) HMFlushTlb(PVMCPU pVCpu);
+VMM_INT_DECL(int) HMFlushTlbOnAllVCpus(PVMCC pVM);
+VMM_INT_DECL(int) HMInvalidatePageOnAllVCpus(PVMCC pVM, RTGCPTR GCVirt);
+VMM_INT_DECL(int) HMInvalidatePhysPage(PVMCC pVM, RTGCPHYS GCPhys);
+VMM_INT_DECL(bool) HMAreNestedPagingAndFullGuestExecEnabled(PVMCC pVM);
+VMM_INT_DECL(bool) HMIsLongModeAllowed(PVMCC pVM);
+VMM_INT_DECL(bool) HMIsNestedPagingActive(PVMCC pVM);
+VMM_INT_DECL(bool) HMIsMsrBitmapActive(PVM pVM);
+# ifdef VBOX_WITH_NESTED_HWVIRT_VMX
+VMM_INT_DECL(void) HMNotifyVmxNstGstVmexit(PVMCPU pVCpu);
+VMM_INT_DECL(void) HMNotifyVmxNstGstCurrentVmcsChanged(PVMCPU pVCpu);
+# endif
+/** @} */
+
+/** @name R0, R3 SVM handlers.
+ * @{ */
+VMM_INT_DECL(bool) HMIsSvmVGifActive(PCVMCC pVM);
+# ifdef VBOX_WITH_NESTED_HWVIRT_SVM
+VMM_INT_DECL(void) HMNotifySvmNstGstVmexit(PVMCPUCC pVCpu, PCPUMCTX pCtx);
+# endif
+# if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
+VMM_INT_DECL(int) HMIsSubjectToSvmErratum170(uint32_t *pu32Family, uint32_t *pu32Model, uint32_t *pu32Stepping);
+# endif
+VMM_INT_DECL(int) HMHCMaybeMovTprSvmHypercall(PVMCC pVM, PVMCPUCC pVCpu);
+/** @} */
+
+#else /* Nops in RC: */
+
+/** @name RC HM (VMX/SVM agnostic) handlers.
+ * @{ */
+# define HMFlushTlb(pVCpu) do { } while (0)
+# define HMFlushTlbOnAllVCpus(pVM) do { } while (0)
+# define HMInvalidatePageOnAllVCpus(pVM, GCVirt) do { } while (0)
+# define HMInvalidatePhysPage(pVM, GCVirt) do { } while (0)
+# define HMAreNestedPagingAndFullGuestExecEnabled(pVM) false
+# define HMIsLongModeAllowed(pVM) false
+# define HMIsNestedPagingActive(pVM) false
+# define HMIsMsrBitmapsActive(pVM) false
+/** @} */
+
+/** @name RC SVM handlers.
+ * @{ */
+# define HMIsSvmVGifActive(pVM) false
+# define HMNotifySvmNstGstVmexit(pVCpu, pCtx) do { } while (0)
+# if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
+# define HMIsSubjectToSvmErratum170(puFamily, puModel, puStepping) false
+# endif
+# define HMHCMaybeMovTprSvmHypercall(pVM, pVCpu) do { } while (0)
+/** @} */
+
+#endif
+
+/** @name HMVMX_READ_XXX - Flags for reading auxiliary VM-exit VMCS fields.
+ *
+ * These flags allow reading VMCS fields that are not necessarily part of the
+ * guest-CPU state but are needed while handling VM-exits.
+ *
+ * @note If you add any fields here, make sure to update VMXR0GetExitAuxInfo.
+ *
+ * @{
+ */
+#define HMVMX_READ_IDT_VECTORING_INFO RT_BIT_32(0)
+#define HMVMX_READ_IDT_VECTORING_ERROR_CODE RT_BIT_32(1)
+#define HMVMX_READ_EXIT_QUALIFICATION RT_BIT_32(2)
+#define HMVMX_READ_EXIT_INSTR_LEN RT_BIT_32(3)
+#define HMVMX_READ_EXIT_INTERRUPTION_INFO RT_BIT_32(4)
+#define HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE RT_BIT_32(5)
+#define HMVMX_READ_EXIT_INSTR_INFO RT_BIT_32(6)
+#define HMVMX_READ_GUEST_LINEAR_ADDR RT_BIT_32(7)
+#define HMVMX_READ_GUEST_PHYSICAL_ADDR RT_BIT_32(8)
+#define HMVMX_READ_GUEST_PENDING_DBG_XCPTS RT_BIT_32(9)
+
+/** All the VMCS fields required for processing of exception/NMI VM-exits. */
+#define HMVMX_READ_XCPT_INFO ( HMVMX_READ_EXIT_INTERRUPTION_INFO \
+ | HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE \
+ | HMVMX_READ_EXIT_INSTR_LEN \
+ | HMVMX_READ_IDT_VECTORING_INFO \
+ | HMVMX_READ_IDT_VECTORING_ERROR_CODE)
+
+/** Mask of all valid HMVMX_READ_XXX flags. */
+#define HMVMX_READ_VALID_MASK ( HMVMX_READ_IDT_VECTORING_INFO \
+ | HMVMX_READ_IDT_VECTORING_ERROR_CODE \
+ | HMVMX_READ_EXIT_QUALIFICATION \
+ | HMVMX_READ_EXIT_INSTR_LEN \
+ | HMVMX_READ_EXIT_INTERRUPTION_INFO \
+ | HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE \
+ | HMVMX_READ_EXIT_INSTR_INFO \
+ | HMVMX_READ_GUEST_LINEAR_ADDR \
+ | HMVMX_READ_GUEST_PHYSICAL_ADDR \
+ | HMVMX_READ_GUEST_PENDING_DBG_XCPTS)
+/** @} */
+
+#ifdef IN_RING0
+/** @defgroup grp_hm_r0 The HM ring-0 Context API
+ * @{
+ */
+/**
+ * HM VM-exit auxiliary info.
+ */
+typedef union
+{
+ /** VMX VM-exit auxiliary info. */
+ VMXEXITAUX Vmx;
+ /** SVM \#VMEXIT auxiliary info. */
+ SVMEXITAUX Svm;
+} HMEXITAUX;
+/** Pointer to HM-exit auxiliary info union. */
+typedef HMEXITAUX *PHMEXITAUX;
+/** Pointer to a const HM-exit auxiliary info union. */
+typedef const HMEXITAUX *PCHMEXITAUX;
+
+VMMR0_INT_DECL(int) HMR0Init(void);
+VMMR0_INT_DECL(int) HMR0Term(void);
+VMMR0_INT_DECL(int) HMR0InitVM(PVMCC pVM);
+VMMR0_INT_DECL(int) HMR0TermVM(PVMCC pVM);
+VMMR0_INT_DECL(int) HMR0EnableAllCpus(PVMCC pVM);
+# ifdef VBOX_WITH_RAW_MODE
+VMMR0_INT_DECL(int) HMR0EnterSwitcher(PVMCC pVM, VMMSWITCHER enmSwitcher, bool *pfVTxDisabled);
+VMMR0_INT_DECL(void) HMR0LeaveSwitcher(PVMCC pVM, bool fVTxDisabled);
+# endif
+
+VMMR0_INT_DECL(int) HMR0SetupVM(PVMCC pVM);
+VMMR0_INT_DECL(int) HMR0RunGuestCode(PVMCC pVM, PVMCPUCC pVCpu);
+VMMR0_INT_DECL(int) HMR0Enter(PVMCPUCC pVCpu);
+VMMR0_INT_DECL(int) HMR0LeaveCpu(PVMCPUCC pVCpu);
+VMMR0_INT_DECL(void) HMR0ThreadCtxCallback(RTTHREADCTXEVENT enmEvent, void *pvUser);
+VMMR0_INT_DECL(void) HMR0NotifyCpumUnloadedGuestFpuState(PVMCPUCC VCpu);
+VMMR0_INT_DECL(void) HMR0NotifyCpumModifiedHostCr0(PVMCPUCC VCpu);
+VMMR0_INT_DECL(bool) HMR0SuspendPending(void);
+VMMR0_INT_DECL(int) HMR0InvalidatePage(PVMCPUCC pVCpu, RTGCPTR GCVirt);
+VMMR0_INT_DECL(int) HMR0ImportStateOnDemand(PVMCPUCC pVCpu, uint64_t fWhat);
+VMMR0_INT_DECL(int) HMR0GetExitAuxInfo(PVMCPUCC pVCpu, PHMEXITAUX pHmExitAux, uint32_t fWhat);
+/** @} */
+#endif /* IN_RING0 */
+
+
+#ifdef IN_RING3
+/** @defgroup grp_hm_r3 The HM ring-3 Context API
+ * @{
+ */
+VMMR3DECL(bool) HMR3IsEnabled(PUVM pUVM);
+VMMR3DECL(bool) HMR3IsNestedPagingActive(PUVM pUVM);
+VMMR3DECL(bool) HMR3AreVirtApicRegsEnabled(PUVM pUVM);
+VMMR3DECL(bool) HMR3IsPostedIntrsEnabled(PUVM pUVM);
+VMMR3DECL(bool) HMR3IsVpidActive(PUVM pUVM);
+VMMR3DECL(bool) HMR3IsUXActive(PUVM pUVM);
+VMMR3DECL(bool) HMR3IsSvmEnabled(PUVM pUVM);
+VMMR3DECL(bool) HMR3IsVmxEnabled(PUVM pUVM);
+
+VMMR3_INT_DECL(int) HMR3Init(PVM pVM);
+VMMR3_INT_DECL(int) HMR3InitCompleted(PVM pVM, VMINITCOMPLETED enmWhat);
+VMMR3_INT_DECL(void) HMR3Relocate(PVM pVM);
+VMMR3_INT_DECL(int) HMR3Term(PVM pVM);
+VMMR3_INT_DECL(void) HMR3Reset(PVM pVM);
+VMMR3_INT_DECL(void) HMR3ResetCpu(PVMCPU pVCpu);
+VMMR3_INT_DECL(void) HMR3CheckError(PVM pVM, int iStatusCode);
+VMMR3_INT_DECL(void) HMR3NotifyDebugEventChanged(PVM pVM);
+VMMR3_INT_DECL(void) HMR3NotifyDebugEventChangedPerCpu(PVM pVM, PVMCPU pVCpu);
+VMMR3_INT_DECL(bool) HMR3IsActive(PCVMCPU pVCpu);
+VMMR3_INT_DECL(int) HMR3EnablePatching(PVM pVM, RTGCPTR pPatchMem, unsigned cbPatchMem);
+VMMR3_INT_DECL(int) HMR3DisablePatching(PVM pVM, RTGCPTR pPatchMem, unsigned cbPatchMem);
+VMMR3_INT_DECL(int) HMR3PatchTprInstr(PVM pVM, PVMCPU pVCpu);
+VMMR3_INT_DECL(bool) HMR3IsRescheduleRequired(PVM pVM, PCCPUMCTX pCtx);
+VMMR3_INT_DECL(bool) HMR3IsVmxPreemptionTimerUsed(PVM pVM);
+/** @} */
+#endif /* IN_RING3 */
+
+/** @} */
+RT_C_DECLS_END
+
+
+#endif /* !VBOX_INCLUDED_vmm_hm_h */
+
diff --git a/include/VBox/vmm/hm_svm.h b/include/VBox/vmm/hm_svm.h
new file mode 100644
index 00000000..403480c5
--- /dev/null
+++ b/include/VBox/vmm/hm_svm.h
@@ -0,0 +1,1169 @@
+/** @file
+ * HM - SVM (AMD-V) Structures and Definitions. (VMM)
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vmm_hm_svm_h
+#define VBOX_INCLUDED_vmm_hm_svm_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/types.h>
+#include <iprt/assert.h>
+#include <iprt/asm.h>
+
+#ifdef RT_OS_SOLARIS
+# undef ES
+# undef CS
+# undef DS
+# undef SS
+# undef FS
+# undef GS
+#endif
+
+/** @defgroup grp_hm_svm SVM (AMD-V) Types and Definitions
+ * @ingroup grp_hm
+ * @{
+ */
+
+/** @name SVM generic / convenient defines.
+ * @{
+ */
+/** Number of pages required for the VMCB. */
+#define SVM_VMCB_PAGES 1
+/** Number of pages required for the MSR permission bitmap. */
+#define SVM_MSRPM_PAGES 2
+/** Number of pages required for the IO permission bitmap. */
+#define SVM_IOPM_PAGES 3
+/** @} */
+
+/*
+ * Ugly!
+ * When compiling the recompiler, its own svm.h defines clash with
+ * the following defines. Avoid just the duplicates here as we still
+ * require other definitions and structures in this header.
+ */
+#ifndef IN_REM_R3
+/** @name SVM_EXIT_XXX - SVM Basic Exit Reasons.
+ * @{
+ */
+/** Invalid guest state in VMCB. */
+# define SVM_EXIT_INVALID (uint64_t)(-1)
+/** Read from CR0-CR15. */
+# define SVM_EXIT_READ_CR0 0x0
+# define SVM_EXIT_READ_CR1 0x1
+# define SVM_EXIT_READ_CR2 0x2
+# define SVM_EXIT_READ_CR3 0x3
+# define SVM_EXIT_READ_CR4 0x4
+# define SVM_EXIT_READ_CR5 0x5
+# define SVM_EXIT_READ_CR6 0x6
+# define SVM_EXIT_READ_CR7 0x7
+# define SVM_EXIT_READ_CR8 0x8
+# define SVM_EXIT_READ_CR9 0x9
+# define SVM_EXIT_READ_CR10 0xa
+# define SVM_EXIT_READ_CR11 0xb
+# define SVM_EXIT_READ_CR12 0xc
+# define SVM_EXIT_READ_CR13 0xd
+# define SVM_EXIT_READ_CR14 0xe
+# define SVM_EXIT_READ_CR15 0xf
+/** Writes to CR0-CR15. */
+# define SVM_EXIT_WRITE_CR0 0x10
+# define SVM_EXIT_WRITE_CR1 0x11
+# define SVM_EXIT_WRITE_CR2 0x12
+# define SVM_EXIT_WRITE_CR3 0x13
+# define SVM_EXIT_WRITE_CR4 0x14
+# define SVM_EXIT_WRITE_CR5 0x15
+# define SVM_EXIT_WRITE_CR6 0x16
+# define SVM_EXIT_WRITE_CR7 0x17
+# define SVM_EXIT_WRITE_CR8 0x18
+# define SVM_EXIT_WRITE_CR9 0x19
+# define SVM_EXIT_WRITE_CR10 0x1a
+# define SVM_EXIT_WRITE_CR11 0x1b
+# define SVM_EXIT_WRITE_CR12 0x1c
+# define SVM_EXIT_WRITE_CR13 0x1d
+# define SVM_EXIT_WRITE_CR14 0x1e
+# define SVM_EXIT_WRITE_CR15 0x1f
+/** Read from DR0-DR15. */
+# define SVM_EXIT_READ_DR0 0x20
+# define SVM_EXIT_READ_DR1 0x21
+# define SVM_EXIT_READ_DR2 0x22
+# define SVM_EXIT_READ_DR3 0x23
+# define SVM_EXIT_READ_DR4 0x24
+# define SVM_EXIT_READ_DR5 0x25
+# define SVM_EXIT_READ_DR6 0x26
+# define SVM_EXIT_READ_DR7 0x27
+# define SVM_EXIT_READ_DR8 0x28
+# define SVM_EXIT_READ_DR9 0x29
+# define SVM_EXIT_READ_DR10 0x2a
+# define SVM_EXIT_READ_DR11 0x2b
+# define SVM_EXIT_READ_DR12 0x2c
+# define SVM_EXIT_READ_DR13 0x2d
+# define SVM_EXIT_READ_DR14 0x2e
+# define SVM_EXIT_READ_DR15 0x2f
+/** Writes to DR0-DR15. */
+# define SVM_EXIT_WRITE_DR0 0x30
+# define SVM_EXIT_WRITE_DR1 0x31
+# define SVM_EXIT_WRITE_DR2 0x32
+# define SVM_EXIT_WRITE_DR3 0x33
+# define SVM_EXIT_WRITE_DR4 0x34
+# define SVM_EXIT_WRITE_DR5 0x35
+# define SVM_EXIT_WRITE_DR6 0x36
+# define SVM_EXIT_WRITE_DR7 0x37
+# define SVM_EXIT_WRITE_DR8 0x38
+# define SVM_EXIT_WRITE_DR9 0x39
+# define SVM_EXIT_WRITE_DR10 0x3a
+# define SVM_EXIT_WRITE_DR11 0x3b
+# define SVM_EXIT_WRITE_DR12 0x3c
+# define SVM_EXIT_WRITE_DR13 0x3d
+# define SVM_EXIT_WRITE_DR14 0x3e
+# define SVM_EXIT_WRITE_DR15 0x3f
+/* Exception 0-31. */
+# define SVM_EXIT_XCPT_0 0x40
+# define SVM_EXIT_XCPT_1 0x41
+# define SVM_EXIT_XCPT_2 0x42
+# define SVM_EXIT_XCPT_3 0x43
+# define SVM_EXIT_XCPT_4 0x44
+# define SVM_EXIT_XCPT_5 0x45
+# define SVM_EXIT_XCPT_6 0x46
+# define SVM_EXIT_XCPT_7 0x47
+# define SVM_EXIT_XCPT_8 0x48
+# define SVM_EXIT_XCPT_9 0x49
+# define SVM_EXIT_XCPT_10 0x4a
+# define SVM_EXIT_XCPT_11 0x4b
+# define SVM_EXIT_XCPT_12 0x4c
+# define SVM_EXIT_XCPT_13 0x4d
+# define SVM_EXIT_XCPT_14 0x4e
+# define SVM_EXIT_XCPT_15 0x4f
+# define SVM_EXIT_XCPT_16 0x50
+# define SVM_EXIT_XCPT_17 0x51
+# define SVM_EXIT_XCPT_18 0x52
+# define SVM_EXIT_XCPT_19 0x53
+# define SVM_EXIT_XCPT_20 0x54
+# define SVM_EXIT_XCPT_21 0x55
+# define SVM_EXIT_XCPT_22 0x56
+# define SVM_EXIT_XCPT_23 0x57
+# define SVM_EXIT_XCPT_24 0x58
+# define SVM_EXIT_XCPT_25 0x59
+# define SVM_EXIT_XCPT_26 0x5a
+# define SVM_EXIT_XCPT_27 0x5b
+# define SVM_EXIT_XCPT_28 0x5c
+# define SVM_EXIT_XCPT_29 0x5d
+# define SVM_EXIT_XCPT_30 0x5e
+# define SVM_EXIT_XCPT_31 0x5f
+/* Exception (more readable) */
+# define SVM_EXIT_XCPT_DE SVM_EXIT_XCPT_0
+# define SVM_EXIT_XCPT_DB SVM_EXIT_XCPT_1
+# define SVM_EXIT_XCPT_NMI SVM_EXIT_XCPT_2
+# define SVM_EXIT_XCPT_BP SVM_EXIT_XCPT_3
+# define SVM_EXIT_XCPT_OF SVM_EXIT_XCPT_4
+# define SVM_EXIT_XCPT_BR SVM_EXIT_XCPT_5
+# define SVM_EXIT_XCPT_UD SVM_EXIT_XCPT_6
+# define SVM_EXIT_XCPT_NM SVM_EXIT_XCPT_7
+# define SVM_EXIT_XCPT_DF SVM_EXIT_XCPT_8
+# define SVM_EXIT_XCPT_CO_SEG_OVERRUN SVM_EXIT_XCPT_9
+# define SVM_EXIT_XCPT_TS SVM_EXIT_XCPT_10
+# define SVM_EXIT_XCPT_NP SVM_EXIT_XCPT_11
+# define SVM_EXIT_XCPT_SS SVM_EXIT_XCPT_12
+# define SVM_EXIT_XCPT_GP SVM_EXIT_XCPT_13
+# define SVM_EXIT_XCPT_PF SVM_EXIT_XCPT_14
+# define SVM_EXIT_XCPT_MF SVM_EXIT_XCPT_16
+# define SVM_EXIT_XCPT_AC SVM_EXIT_XCPT_17
+# define SVM_EXIT_XCPT_MC SVM_EXIT_XCPT_18
+# define SVM_EXIT_XCPT_XF SVM_EXIT_XCPT_19
+# define SVM_EXIT_XCPT_VE SVM_EXIT_XCPT_20
+# define SVM_EXIT_XCPT_SX SVM_EXIT_XCPT_30
+/** Physical maskable interrupt. */
+# define SVM_EXIT_INTR 0x60
+/** Non-maskable interrupt. */
+# define SVM_EXIT_NMI 0x61
+/** System Management interrupt. */
+# define SVM_EXIT_SMI 0x62
+/** Physical INIT signal. */
+# define SVM_EXIT_INIT 0x63
+/** Virtual interrupt. */
+# define SVM_EXIT_VINTR 0x64
+/** Write to CR0 that changed any bits other than CR0.TS or CR0.MP. */
+# define SVM_EXIT_CR0_SEL_WRITE 0x65
+/** IDTR read. */
+# define SVM_EXIT_IDTR_READ 0x66
+/** GDTR read. */
+# define SVM_EXIT_GDTR_READ 0x67
+/** LDTR read. */
+# define SVM_EXIT_LDTR_READ 0x68
+/** TR read. */
+# define SVM_EXIT_TR_READ 0x69
+/** IDTR write. */
+# define SVM_EXIT_IDTR_WRITE 0x6a
+/** GDTR write. */
+# define SVM_EXIT_GDTR_WRITE 0x6b
+/** LDTR write. */
+# define SVM_EXIT_LDTR_WRITE 0x6c
+/** TR write. */
+# define SVM_EXIT_TR_WRITE 0x6d
+/** RDTSC instruction. */
+# define SVM_EXIT_RDTSC 0x6e
+/** RDPMC instruction. */
+# define SVM_EXIT_RDPMC 0x6f
+/** PUSHF instruction. */
+# define SVM_EXIT_PUSHF 0x70
+/** POPF instruction. */
+# define SVM_EXIT_POPF 0x71
+/** CPUID instruction. */
+# define SVM_EXIT_CPUID 0x72
+/** RSM instruction. */
+# define SVM_EXIT_RSM 0x73
+/** IRET instruction. */
+# define SVM_EXIT_IRET 0x74
+/** Software interrupt (INTn instructions). */
+# define SVM_EXIT_SWINT 0x75
+/** INVD instruction. */
+# define SVM_EXIT_INVD 0x76
+/** PAUSE instruction. */
+# define SVM_EXIT_PAUSE 0x77
+/** HLT instruction. */
+# define SVM_EXIT_HLT 0x78
+/** INVLPG instructions. */
+# define SVM_EXIT_INVLPG 0x79
+/** INVLPGA instruction. */
+# define SVM_EXIT_INVLPGA 0x7a
+/** IN or OUT accessing protected port (the EXITINFO1 field provides more information). */
+# define SVM_EXIT_IOIO 0x7b
+/** RDMSR or WRMSR access to protected MSR. */
+# define SVM_EXIT_MSR 0x7c
+/** task switch. */
+# define SVM_EXIT_TASK_SWITCH 0x7d
+/** FP legacy handling enabled, and processor is frozen in an x87/mmx instruction waiting for an interrupt. */
+# define SVM_EXIT_FERR_FREEZE 0x7e
+/** Shutdown. */
+# define SVM_EXIT_SHUTDOWN 0x7f
+/** VMRUN instruction. */
+# define SVM_EXIT_VMRUN 0x80
+/** VMMCALL instruction. */
+# define SVM_EXIT_VMMCALL 0x81
+/** VMLOAD instruction. */
+# define SVM_EXIT_VMLOAD 0x82
+/** VMSAVE instruction. */
+# define SVM_EXIT_VMSAVE 0x83
+/** STGI instruction. */
+# define SVM_EXIT_STGI 0x84
+/** CLGI instruction. */
+# define SVM_EXIT_CLGI 0x85
+/** SKINIT instruction. */
+# define SVM_EXIT_SKINIT 0x86
+/** RDTSCP instruction. */
+# define SVM_EXIT_RDTSCP 0x87
+/** ICEBP instruction. */
+# define SVM_EXIT_ICEBP 0x88
+/** WBINVD instruction. */
+# define SVM_EXIT_WBINVD 0x89
+/** MONITOR instruction. */
+# define SVM_EXIT_MONITOR 0x8a
+/** MWAIT instruction. */
+# define SVM_EXIT_MWAIT 0x8b
+/** MWAIT instruction, when armed. */
+# define SVM_EXIT_MWAIT_ARMED 0x8c
+/** XSETBV instruction. */
+# define SVM_EXIT_XSETBV 0x8d
+/** RDPRU instruction. */
+# define SVM_EXIT_RDPRU 0x8e
+/** Write to EFER (after guest instruction completes). */
+# define SVM_EXIT_WRITE_EFER_TRAP 0x8f
+/** Write to CR0-CR15 (after guest instruction completes). */
+# define SVM_EXIT_WRITE_CR0_TRAP 0x90
+# define SVM_EXIT_WRITE_CR1_TRAP 0x91
+# define SVM_EXIT_WRITE_CR2_TRAP 0x92
+# define SVM_EXIT_WRITE_CR3_TRAP 0x93
+# define SVM_EXIT_WRITE_CR4_TRAP 0x94
+# define SVM_EXIT_WRITE_CR5_TRAP 0x95
+# define SVM_EXIT_WRITE_CR6_TRAP 0x96
+# define SVM_EXIT_WRITE_CR7_TRAP 0x97
+# define SVM_EXIT_WRITE_CR8_TRAP 0x98
+# define SVM_EXIT_WRITE_CR9_TRAP 0x99
+# define SVM_EXIT_WRITE_CR10_TRAP 0x9a
+# define SVM_EXIT_WRITE_CR11_TRAP 0x9b
+# define SVM_EXIT_WRITE_CR12_TRAP 0x9c
+# define SVM_EXIT_WRITE_CR13_TRAP 0x9d
+# define SVM_EXIT_WRITE_CR14_TRAP 0x9e
+# define SVM_EXIT_WRITE_CR15_TRAP 0x9f
+/** MCOMMIT instruction. */
+# define SVM_EXIT_MCOMMIT 0xa3
+
+/** Nested paging: host-level page fault occurred (EXITINFO1 contains fault errorcode; EXITINFO2 contains the guest physical address causing the fault). */
+# define SVM_EXIT_NPF 0x400
+/** AVIC: Virtual IPI delivery not completed. */
+# define SVM_EXIT_AVIC_INCOMPLETE_IPI 0x401
+/** AVIC: Attempted access by guest to a vAPIC register not handled by AVIC
+ * hardware. */
+# define SVM_EXIT_AVIC_NOACCEL 0x402
+/** The maximum possible exit value. */
+# define SVM_EXIT_MAX (SVM_EXIT_AVIC_NOACCEL)
+/** @} */
+#endif /* !IN_REM_R3*/
+
+
+/** @name SVMVMCB.u64ExitInfo2 for task switches
+ * @{
+ */
+/** Set to 1 if the task switch was caused by an IRET; else cleared to 0. */
+#define SVM_EXIT2_TASK_SWITCH_IRET RT_BIT_64(36)
+/** Set to 1 if the task switch was caused by a far jump; else cleared to 0. */
+#define SVM_EXIT2_TASK_SWITCH_JUMP RT_BIT_64(38)
+/** Set to 1 if the task switch has an error code; else cleared to 0. */
+#define SVM_EXIT2_TASK_SWITCH_HAS_ERROR_CODE RT_BIT_64(44)
+/** The value of EFLAGS.RF that would be saved in the outgoing TSS if the task switch were not intercepted. */
+#define SVM_EXIT2_TASK_SWITCH_EFLAGS_RF RT_BIT_64(48)
+/** @} */
+
+/** @name SVMVMCB.u64ExitInfo1 for MSR accesses
+ * @{
+ */
+/** The access was a read MSR. */
+#define SVM_EXIT1_MSR_READ 0x0
+/** The access was a write MSR. */
+#define SVM_EXIT1_MSR_WRITE 0x1
+/** @} */
+
+/** @name SVMVMCB.u64ExitInfo1 for Mov CRx accesses.
+ * @{
+ */
+/** The mask of whether the access was via a Mov CRx instruction. */
+#define SVM_EXIT1_MOV_CRX_MASK RT_BIT_64(63)
+/** The mask for the GPR number of the Mov CRx instruction. */
+#define SVM_EXIT1_MOV_CRX_GPR_NUMBER 0xf
+/** @} */
+
+/** @name SVMVMCB.u64ExitInfo1 for Mov DRx accesses.
+ * @{
+ */
+/** The mask for the GPR number of the Mov DRx instruction. */
+#define SVM_EXIT1_MOV_DRX_GPR_NUMBER 0xf
+/** @} */
+
+/** @name SVMVMCB.ctrl.u64InterceptCtrl
+ * @{
+ */
+/** Intercept INTR (physical maskable interrupt). */
+#define SVM_CTRL_INTERCEPT_INTR RT_BIT_64(0)
+/** Intercept NMI. */
+#define SVM_CTRL_INTERCEPT_NMI RT_BIT_64(1)
+/** Intercept SMI. */
+#define SVM_CTRL_INTERCEPT_SMI RT_BIT_64(2)
+/** Intercept INIT. */
+#define SVM_CTRL_INTERCEPT_INIT RT_BIT_64(3)
+/** Intercept VINTR (virtual maskable interrupt). */
+#define SVM_CTRL_INTERCEPT_VINTR RT_BIT_64(4)
+/** Intercept CR0 writes that change bits other than CR0.TS or CR0.MP */
+#define SVM_CTRL_INTERCEPT_CR0_SEL_WRITE RT_BIT_64(5)
+/** Intercept reads of IDTR. */
+#define SVM_CTRL_INTERCEPT_IDTR_READS RT_BIT_64(6)
+/** Intercept reads of GDTR. */
+#define SVM_CTRL_INTERCEPT_GDTR_READS RT_BIT_64(7)
+/** Intercept reads of LDTR. */
+#define SVM_CTRL_INTERCEPT_LDTR_READS RT_BIT_64(8)
+/** Intercept reads of TR. */
+#define SVM_CTRL_INTERCEPT_TR_READS RT_BIT_64(9)
+/** Intercept writes of IDTR. */
+#define SVM_CTRL_INTERCEPT_IDTR_WRITES RT_BIT_64(10)
+/** Intercept writes of GDTR. */
+#define SVM_CTRL_INTERCEPT_GDTR_WRITES RT_BIT_64(11)
+/** Intercept writes of LDTR. */
+#define SVM_CTRL_INTERCEPT_LDTR_WRITES RT_BIT_64(12)
+/** Intercept writes of TR. */
+#define SVM_CTRL_INTERCEPT_TR_WRITES RT_BIT_64(13)
+/** Intercept RDTSC instruction. */
+#define SVM_CTRL_INTERCEPT_RDTSC RT_BIT_64(14)
+/** Intercept RDPMC instruction. */
+#define SVM_CTRL_INTERCEPT_RDPMC RT_BIT_64(15)
+/** Intercept PUSHF instruction. */
+#define SVM_CTRL_INTERCEPT_PUSHF RT_BIT_64(16)
+/** Intercept POPF instruction. */
+#define SVM_CTRL_INTERCEPT_POPF RT_BIT_64(17)
+/** Intercept CPUID instruction. */
+#define SVM_CTRL_INTERCEPT_CPUID RT_BIT_64(18)
+/** Intercept RSM instruction. */
+#define SVM_CTRL_INTERCEPT_RSM RT_BIT_64(19)
+/** Intercept IRET instruction. */
+#define SVM_CTRL_INTERCEPT_IRET RT_BIT_64(20)
+/** Intercept INTn instruction. */
+#define SVM_CTRL_INTERCEPT_INTN RT_BIT_64(21)
+/** Intercept INVD instruction. */
+#define SVM_CTRL_INTERCEPT_INVD RT_BIT_64(22)
+/** Intercept PAUSE instruction. */
+#define SVM_CTRL_INTERCEPT_PAUSE RT_BIT_64(23)
+/** Intercept HLT instruction. */
+#define SVM_CTRL_INTERCEPT_HLT RT_BIT_64(24)
+/** Intercept INVLPG instruction. */
+#define SVM_CTRL_INTERCEPT_INVLPG RT_BIT_64(25)
+/** Intercept INVLPGA instruction. */
+#define SVM_CTRL_INTERCEPT_INVLPGA RT_BIT_64(26)
+/** IOIO_PROT Intercept IN/OUT accesses to selected ports. */
+#define SVM_CTRL_INTERCEPT_IOIO_PROT RT_BIT_64(27)
+/** MSR_PROT Intercept RDMSR or WRMSR accesses to selected MSRs. */
+#define SVM_CTRL_INTERCEPT_MSR_PROT RT_BIT_64(28)
+/** Intercept task switches. */
+#define SVM_CTRL_INTERCEPT_TASK_SWITCH RT_BIT_64(29)
+/** FERR_FREEZE: intercept processor "freezing" during legacy FERR handling. */
+#define SVM_CTRL_INTERCEPT_FERR_FREEZE RT_BIT_64(30)
+/** Intercept shutdown events. */
+#define SVM_CTRL_INTERCEPT_SHUTDOWN RT_BIT_64(31)
+/** Intercept VMRUN instruction. */
+#define SVM_CTRL_INTERCEPT_VMRUN RT_BIT_64(32 + 0)
+/** Intercept VMMCALL instruction. */
+#define SVM_CTRL_INTERCEPT_VMMCALL RT_BIT_64(32 + 1)
+/** Intercept VMLOAD instruction. */
+#define SVM_CTRL_INTERCEPT_VMLOAD RT_BIT_64(32 + 2)
+/** Intercept VMSAVE instruction. */
+#define SVM_CTRL_INTERCEPT_VMSAVE RT_BIT_64(32 + 3)
+/** Intercept STGI instruction. */
+#define SVM_CTRL_INTERCEPT_STGI RT_BIT_64(32 + 4)
+/** Intercept CLGI instruction. */
+#define SVM_CTRL_INTERCEPT_CLGI RT_BIT_64(32 + 5)
+/** Intercept SKINIT instruction. */
+#define SVM_CTRL_INTERCEPT_SKINIT RT_BIT_64(32 + 6)
+/** Intercept RDTSCP instruction. */
+#define SVM_CTRL_INTERCEPT_RDTSCP RT_BIT_64(32 + 7)
+/** Intercept ICEBP instruction. */
+#define SVM_CTRL_INTERCEPT_ICEBP RT_BIT_64(32 + 8)
+/** Intercept WBINVD instruction. */
+#define SVM_CTRL_INTERCEPT_WBINVD RT_BIT_64(32 + 9)
+/** Intercept MONITOR instruction. */
+#define SVM_CTRL_INTERCEPT_MONITOR RT_BIT_64(32 + 10)
+/** Intercept MWAIT instruction unconditionally. */
+#define SVM_CTRL_INTERCEPT_MWAIT RT_BIT_64(32 + 11)
+/** Intercept MWAIT instruction when armed. */
+#define SVM_CTRL_INTERCEPT_MWAIT_ARMED RT_BIT_64(32 + 12)
+/** Intercept XSETBV instruction. */
+#define SVM_CTRL_INTERCEPT_XSETBV RT_BIT_64(32 + 13)
+/** Intercept RDPRU instruction. */
+#define SVM_CTRL_INTERCEPT_RDPRU RT_BIT_64(32 + 14)
+/** Intercept EFER writes after guest instruction finishes. */
+#define SVM_CTRL_INTERCEPT_EFER_WRITES_TRAP RT_BIT_64(32 + 15)
+/** Intercept CR0 writes after guest instruction finishes. */
+#define SVM_CTRL_INTERCEPT_CR0_WRITES_TRAP RT_BIT_64(32 + 16)
+/** Intercept CR0 writes after guest instruction finishes. */
+#define SVM_CTRL_INTERCEPT_CR1_WRITES_TRAP RT_BIT_64(32 + 17)
+/** Intercept CR0 writes after guest instruction finishes. */
+#define SVM_CTRL_INTERCEPT_CR2_WRITES_TRAP RT_BIT_64(32 + 18)
+/** Intercept CR0 writes after guest instruction finishes. */
+#define SVM_CTRL_INTERCEPT_CR3_WRITES_TRAP RT_BIT_64(32 + 19)
+/** Intercept CR0 writes after guest instruction finishes. */
+#define SVM_CTRL_INTERCEPT_CR4_WRITES_TRAP RT_BIT_64(32 + 20)
+/** Intercept CR0 writes after guest instruction finishes. */
+#define SVM_CTRL_INTERCEPT_CR5_WRITES_TRAP RT_BIT_64(32 + 21)
+/** Intercept CR0 writes after guest instruction finishes. */
+#define SVM_CTRL_INTERCEPT_CR6_WRITES_TRAP RT_BIT_64(32 + 22)
+/** Intercept CR0 writes after guest instruction finishes. */
+#define SVM_CTRL_INTERCEPT_CR7_WRITES_TRAP RT_BIT_64(32 + 23)
+/** Intercept CR0 writes after guest instruction finishes. */
+#define SVM_CTRL_INTERCEPT_CR8_WRITES_TRAP RT_BIT_64(32 + 24)
+/** Intercept CR0 writes after guest instruction finishes. */
+#define SVM_CTRL_INTERCEPT_CR9_WRITES_TRAP RT_BIT_64(32 + 25)
+/** Intercept CR0 writes after guest instruction finishes. */
+#define SVM_CTRL_INTERCEPT_CR10_WRITES_TRAP RT_BIT_64(32 + 26)
+/** Intercept CR0 writes after guest instruction finishes. */
+#define SVM_CTRL_INTERCEPT_CR11_WRITES_TRAP RT_BIT_64(32 + 27)
+/** Intercept CR0 writes after guest instruction finishes. */
+#define SVM_CTRL_INTERCEPT_CR12_WRITES_TRAP RT_BIT_64(32 + 28)
+/** Intercept CR0 writes after guest instruction finishes. */
+#define SVM_CTRL_INTERCEPT_CR13_WRITES_TRAP RT_BIT_64(32 + 29)
+/** Intercept CR0 writes after guest instruction finishes. */
+#define SVM_CTRL_INTERCEPT_CR14_WRITES_TRAP RT_BIT_64(32 + 30)
+/** Intercept CR0 writes after guest instruction finishes. */
+#define SVM_CTRL_INTERCEPT_CR15_WRITES_TRAP RT_BIT_64(32 + 31)
+/** @} */
+
+/** @name SVMINTCTRL.u3Type
+ * @{
+ */
+/** External or virtual interrupt. */
+#define SVM_EVENT_EXTERNAL_IRQ 0
+/** Non-maskable interrupt. */
+#define SVM_EVENT_NMI 2
+/** Exception; fault or trap. */
+#define SVM_EVENT_EXCEPTION 3
+/** Software interrupt. */
+#define SVM_EVENT_SOFTWARE_INT 4
+/** @} */
+
+/** @name SVMVMCB.ctrl.TLBCtrl.n.u8TLBFlush
+ * @{
+ */
+/** Flush nothing. */
+#define SVM_TLB_FLUSH_NOTHING 0
+/** Flush entire TLB (host+guest entries) */
+#define SVM_TLB_FLUSH_ENTIRE 1
+/** Flush this guest's TLB entries (by ASID) */
+#define SVM_TLB_FLUSH_SINGLE_CONTEXT 3
+/** Flush this guest's non-global TLB entries (by ASID) */
+#define SVM_TLB_FLUSH_SINGLE_CONTEXT_RETAIN_GLOBALS 7
+/** @} */
+
+/**
+ * SVM selector/segment register type.
+ */
+typedef struct
+{
+ uint16_t u16Sel;
+ uint16_t u16Attr;
+ uint32_t u32Limit;
+ uint64_t u64Base; /**< Only lower 32 bits are implemented for CS, DS, ES & SS. */
+} SVMSELREG;
+AssertCompileSize(SVMSELREG, 16);
+/** Pointer to the SVMSELREG struct. */
+typedef SVMSELREG *PSVMSELREG;
+/** Pointer to a const SVMSELREG struct. */
+typedef const SVMSELREG *PCSVMSELREG;
+
+/**
+ * SVM GDTR/IDTR type.
+ */
+typedef struct
+{
+ uint16_t u16Reserved0;
+ uint16_t u16Reserved1;
+ uint32_t u32Limit; /**< Only lower 16 bits are implemented. */
+ uint64_t u64Base;
+} SVMXDTR;
+AssertCompileSize(SVMXDTR, 16);
+typedef SVMXDTR SVMIDTR;
+typedef SVMXDTR SVMGDTR;
+/** Pointer to the SVMXDTR struct. */
+typedef SVMXDTR *PSVMXDTR;
+/** Pointer to a const SVMXDTR struct. */
+typedef const SVMXDTR *PCSVMXDTR;
+
+/**
+ * SVM Event injection structure (EVENTINJ and EXITINTINFO).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t u8Vector : 8;
+ uint32_t u3Type : 3;
+ uint32_t u1ErrorCodeValid : 1;
+ uint32_t u19Reserved : 19;
+ uint32_t u1Valid : 1;
+ uint32_t u32ErrorCode : 32;
+ } n;
+ uint64_t u;
+} SVMEVENT;
+/** Pointer to the SVMEVENT union. */
+typedef SVMEVENT *PSVMEVENT;
+/** Pointer to a const SVMEVENT union. */
+typedef const SVMEVENT *PCSVMEVENT;
+
+/** Gets the event type given an SVMEVENT parameter. */
+#define SVM_EVENT_GET_TYPE(a_SvmEvent) (((a_SvmEvent) >> 8) & 7)
+
+/**
+ * SVM Interrupt control structure (Virtual Interrupt Control).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t u8VTPR : 8; /* V_TPR */
+ uint32_t u1VIrqPending : 1; /* V_IRQ */
+ uint32_t u1VGif : 1; /* VGIF */
+ uint32_t u6Reserved : 6;
+ uint32_t u4VIntrPrio : 4; /* V_INTR_PRIO */
+ uint32_t u1IgnoreTPR : 1; /* V_IGN_TPR */
+ uint32_t u3Reserved : 3;
+ uint32_t u1VIntrMasking : 1; /* V_INTR_MASKING */
+ uint32_t u1VGifEnable : 1; /* VGIF enable */
+ uint32_t u5Reserved : 5;
+ uint32_t u1AvicEnable : 1; /* AVIC enable */
+ uint32_t u8VIntrVector : 8; /* V_INTR_VECTOR */
+ uint32_t u24Reserved : 24;
+ } n;
+ uint64_t u;
+} SVMINTCTRL;
+/** Pointer to an SVMINTCTRL structure. */
+typedef SVMINTCTRL *PSVMINTCTRL;
+/** Pointer to a const SVMINTCTRL structure. */
+typedef const SVMINTCTRL *PCSVMINTCTRL;
+
+/**
+ * SVM TLB control structure.
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t u32ASID : 32;
+ uint32_t u8TLBFlush : 8;
+ uint32_t u24Reserved : 24;
+ } n;
+ uint64_t u;
+} SVMTLBCTRL;
+
+/**
+ * SVM IOIO exit info. structure (EXITINFO1 for IOIO intercepts).
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t u1Type : 1; /**< Bit 0: 0 = out, 1 = in */
+ uint32_t u1Reserved : 1; /**< Bit 1: Reserved */
+ uint32_t u1Str : 1; /**< Bit 2: String I/O (1) or not (0). */
+ uint32_t u1Rep : 1; /**< Bit 3: Repeat prefixed string I/O. */
+ uint32_t u1Op8 : 1; /**< Bit 4: 8-bit operand. */
+ uint32_t u1Op16 : 1; /**< Bit 5: 16-bit operand. */
+ uint32_t u1Op32 : 1; /**< Bit 6: 32-bit operand. */
+ uint32_t u1Addr16 : 1; /**< Bit 7: 16-bit address size. */
+ uint32_t u1Addr32 : 1; /**< Bit 8: 32-bit address size. */
+ uint32_t u1Addr64 : 1; /**< Bit 9: 64-bit address size. */
+ uint32_t u3Seg : 3; /**< Bits 12:10: Effective segment number. Added w/ decode assist in APM v3.17. */
+ uint32_t u3Reserved : 3;
+ uint32_t u16Port : 16; /**< Bits 31:16: Port number. */
+ } n;
+ uint32_t u;
+} SVMIOIOEXITINFO;
+/** Pointer to an SVM IOIO exit info. structure. */
+typedef SVMIOIOEXITINFO *PSVMIOIOEXITINFO;
+/** Pointer to a const SVM IOIO exit info. structure. */
+typedef const SVMIOIOEXITINFO *PCSVMIOIOEXITINFO;
+
+/** 8-bit IO transfer. */
+#define SVM_IOIO_8_BIT_OP RT_BIT_32(4)
+/** 16-bit IO transfer. */
+#define SVM_IOIO_16_BIT_OP RT_BIT_32(5)
+/** 32-bit IO transfer. */
+#define SVM_IOIO_32_BIT_OP RT_BIT_32(6)
+/** Number of bits to shift right to get the operand sizes. */
+#define SVM_IOIO_OP_SIZE_SHIFT 4
+/** Mask of all possible IO transfer sizes. */
+#define SVM_IOIO_OP_SIZE_MASK (SVM_IOIO_8_BIT_OP | SVM_IOIO_16_BIT_OP | SVM_IOIO_32_BIT_OP)
+/** 16-bit address for the IO buffer. */
+#define SVM_IOIO_16_BIT_ADDR RT_BIT_32(7)
+/** 32-bit address for the IO buffer. */
+#define SVM_IOIO_32_BIT_ADDR RT_BIT_32(8)
+/** 64-bit address for the IO buffer. */
+#define SVM_IOIO_64_BIT_ADDR RT_BIT_32(9)
+/** Number of bits to shift right to get the address sizes. */
+#define SVM_IOIO_ADDR_SIZE_SHIFT 7
+/** Mask of all the IO address sizes. */
+#define SVM_IOIO_ADDR_SIZE_MASK (SVM_IOIO_16_BIT_ADDR | SVM_IOIO_32_BIT_ADDR | SVM_IOIO_64_BIT_ADDR)
+/** Number of bits to shift right to get the IO port number. */
+#define SVM_IOIO_PORT_SHIFT 16
+/** IO write. */
+#define SVM_IOIO_WRITE 0
+/** IO read. */
+#define SVM_IOIO_READ 1
+/**
+ * SVM IOIO transfer type.
+ */
+typedef enum
+{
+ SVMIOIOTYPE_OUT = SVM_IOIO_WRITE,
+ SVMIOIOTYPE_IN = SVM_IOIO_READ
+} SVMIOIOTYPE;
+
+/**
+ * SVM AVIC.
+ */
+typedef union
+{
+ struct
+ {
+ RT_GCC_EXTENSION uint64_t u12Reserved0 : 12;
+ RT_GCC_EXTENSION uint64_t u40Addr : 40;
+ RT_GCC_EXTENSION uint64_t u12Reserved1 : 12;
+ } n;
+ uint64_t u;
+} SVMAVIC;
+AssertCompileSize(SVMAVIC, 8);
+
+/**
+ * SVM AVIC PHYSICAL_TABLE pointer.
+ */
+typedef union
+{
+ struct
+ {
+ RT_GCC_EXTENSION uint64_t u8LastGuestCoreId : 8;
+ RT_GCC_EXTENSION uint64_t u4Reserved : 4;
+ RT_GCC_EXTENSION uint64_t u40Addr : 40;
+ RT_GCC_EXTENSION uint64_t u12Reserved : 12;
+ } n;
+ uint64_t u;
+} SVMAVICPHYS;
+AssertCompileSize(SVMAVICPHYS, 8);
+
+/**
+ * SVM Nested Paging struct.
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t u1NestedPaging : 1;
+ uint32_t u1Sev : 1;
+ uint32_t u1SevEs : 1;
+ uint32_t u29Reserved : 29;
+ } n;
+ uint64_t u;
+} SVMNP;
+AssertCompileSize(SVMNP, 8);
+
+/**
+ * SVM Interrupt shadow struct.
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t u1IntShadow : 1;
+ uint32_t u1GuestIntMask : 1;
+ uint32_t u30Reserved : 30;
+ } n;
+ uint64_t u;
+} SVMINTSHADOW;
+AssertCompileSize(SVMINTSHADOW, 8);
+
+/**
+ * SVM LBR virtualization struct.
+ */
+typedef union
+{
+ struct
+ {
+ uint32_t u1LbrVirt : 1;
+ uint32_t u1VirtVmsaveVmload : 1;
+ uint32_t u30Reserved : 30;
+ } n;
+ uint64_t u;
+} SVMLBRVIRT;
+AssertCompileSize(SVMLBRVIRT, 8);
+
+/** Maximum number of bytes in the Guest-instruction bytes field. */
+#define SVM_CTRL_GUEST_INSTR_BYTES_MAX 15
+
+/**
+ * SVM VMCB control area.
+ */
+#pragma pack(1)
+typedef struct
+{
+ /** Offset 0x00 - Intercept reads of CR0-CR15. */
+ uint16_t u16InterceptRdCRx;
+ /** Offset 0x02 - Intercept writes to CR0-CR15. */
+ uint16_t u16InterceptWrCRx;
+ /** Offset 0x04 - Intercept reads of DR0-DR15. */
+ uint16_t u16InterceptRdDRx;
+ /** Offset 0x06 - Intercept writes to DR0-DR15. */
+ uint16_t u16InterceptWrDRx;
+ /** Offset 0x08 - Intercept exception vectors 0-31. */
+ uint32_t u32InterceptXcpt;
+ /** Offset 0x0c - Intercept control. */
+ uint64_t u64InterceptCtrl;
+ /** Offset 0x14-0x3f - Reserved. */
+ uint8_t u8Reserved0[0x3c - 0x14];
+ /** Offset 0x3c - PAUSE filter threshold. */
+ uint16_t u16PauseFilterThreshold;
+ /** Offset 0x3e - PAUSE intercept filter count. */
+ uint16_t u16PauseFilterCount;
+ /** Offset 0x40 - Physical address of IOPM. */
+ uint64_t u64IOPMPhysAddr;
+ /** Offset 0x48 - Physical address of MSRPM. */
+ uint64_t u64MSRPMPhysAddr;
+ /** Offset 0x50 - TSC Offset. */
+ uint64_t u64TSCOffset;
+ /** Offset 0x58 - TLB control field. */
+ SVMTLBCTRL TLBCtrl;
+ /** Offset 0x60 - Interrupt control field. */
+ SVMINTCTRL IntCtrl;
+ /** Offset 0x68 - Interrupt shadow. */
+ SVMINTSHADOW IntShadow;
+ /** Offset 0x70 - Exit code. */
+ uint64_t u64ExitCode;
+ /** Offset 0x78 - Exit info 1. */
+ uint64_t u64ExitInfo1;
+ /** Offset 0x80 - Exit info 2. */
+ uint64_t u64ExitInfo2;
+ /** Offset 0x88 - Exit Interrupt info. */
+ SVMEVENT ExitIntInfo;
+ /** Offset 0x90 - Nested Paging control. */
+ SVMNP NestedPagingCtrl;
+ /** Offset 0x98 - AVIC APIC BAR. */
+ SVMAVIC AvicBar;
+ /** Offset 0xa0-0xa7 - Reserved. */
+ uint8_t u8Reserved1[0xa8 - 0xa0];
+ /** Offset 0xa8 - Event injection. */
+ SVMEVENT EventInject;
+ /** Offset 0xb0 - Host CR3 for nested paging. */
+ uint64_t u64NestedPagingCR3;
+ /** Offset 0xb8 - LBR Virtualization. */
+ SVMLBRVIRT LbrVirt;
+ /** Offset 0xc0 - VMCB Clean Bits. */
+ uint32_t u32VmcbCleanBits;
+ uint32_t u32Reserved0;
+ /** Offset 0xc8 - Next sequential instruction pointer. */
+ uint64_t u64NextRIP;
+ /** Offset 0xd0 - Number of bytes fetched. */
+ uint8_t cbInstrFetched;
+ /** Offset 0xd1 - Guest instruction bytes. */
+ uint8_t abInstr[SVM_CTRL_GUEST_INSTR_BYTES_MAX];
+ /** Offset 0xe0 - AVIC APIC_BACKING_PAGE pointer. */
+ SVMAVIC AvicBackingPagePtr;
+ /** Offset 0xe8-0xef - Reserved. */
+ uint8_t u8Reserved2[0xf0 - 0xe8];
+ /** Offset 0xf0 - AVIC LOGICAL_TABLE pointer. */
+ SVMAVIC AvicLogicalTablePtr;
+ /** Offset 0xf8 - AVIC PHYSICAL_TABLE pointer. */
+ SVMAVICPHYS AvicPhysicalTablePtr;
+} SVMVMCBCTRL;
+#pragma pack()
+/** Pointer to the SVMVMCBSTATESAVE structure. */
+typedef SVMVMCBCTRL *PSVMVMCBCTRL;
+/** Pointer to a const SVMVMCBSTATESAVE structure. */
+typedef const SVMVMCBCTRL *PCSVMVMCBCTRL;
+AssertCompileSize(SVMVMCBCTRL, 0x100);
+AssertCompileMemberOffset(SVMVMCBCTRL, u16InterceptRdCRx, 0x00);
+AssertCompileMemberOffset(SVMVMCBCTRL, u16InterceptWrCRx, 0x02);
+AssertCompileMemberOffset(SVMVMCBCTRL, u16InterceptRdDRx, 0x04);
+AssertCompileMemberOffset(SVMVMCBCTRL, u16InterceptWrDRx, 0x06);
+AssertCompileMemberOffset(SVMVMCBCTRL, u32InterceptXcpt, 0x08);
+AssertCompileMemberOffset(SVMVMCBCTRL, u64InterceptCtrl, 0x0c);
+AssertCompileMemberOffset(SVMVMCBCTRL, u8Reserved0, 0x14);
+AssertCompileMemberOffset(SVMVMCBCTRL, u16PauseFilterThreshold, 0x3c);
+AssertCompileMemberOffset(SVMVMCBCTRL, u16PauseFilterCount, 0x3e);
+AssertCompileMemberOffset(SVMVMCBCTRL, u64IOPMPhysAddr, 0x40);
+AssertCompileMemberOffset(SVMVMCBCTRL, u64MSRPMPhysAddr, 0x48);
+AssertCompileMemberOffset(SVMVMCBCTRL, u64TSCOffset, 0x50);
+AssertCompileMemberOffset(SVMVMCBCTRL, TLBCtrl, 0x58);
+AssertCompileMemberOffset(SVMVMCBCTRL, IntCtrl, 0x60);
+AssertCompileMemberOffset(SVMVMCBCTRL, IntShadow, 0x68);
+AssertCompileMemberOffset(SVMVMCBCTRL, u64ExitCode, 0x70);
+AssertCompileMemberOffset(SVMVMCBCTRL, u64ExitInfo1, 0x78);
+AssertCompileMemberOffset(SVMVMCBCTRL, u64ExitInfo2, 0x80);
+AssertCompileMemberOffset(SVMVMCBCTRL, ExitIntInfo, 0x88);
+AssertCompileMemberOffset(SVMVMCBCTRL, NestedPagingCtrl, 0x90);
+AssertCompileMemberOffset(SVMVMCBCTRL, AvicBar, 0x98);
+AssertCompileMemberOffset(SVMVMCBCTRL, u8Reserved1, 0xa0);
+AssertCompileMemberOffset(SVMVMCBCTRL, EventInject, 0xa8);
+AssertCompileMemberOffset(SVMVMCBCTRL, u64NestedPagingCR3, 0xb0);
+AssertCompileMemberOffset(SVMVMCBCTRL, LbrVirt, 0xb8);
+AssertCompileMemberOffset(SVMVMCBCTRL, u32VmcbCleanBits, 0xc0);
+AssertCompileMemberOffset(SVMVMCBCTRL, u64NextRIP, 0xc8);
+AssertCompileMemberOffset(SVMVMCBCTRL, cbInstrFetched, 0xd0);
+AssertCompileMemberOffset(SVMVMCBCTRL, abInstr, 0xd1);
+AssertCompileMemberOffset(SVMVMCBCTRL, AvicBackingPagePtr, 0xe0);
+AssertCompileMemberOffset(SVMVMCBCTRL, u8Reserved2, 0xe8);
+AssertCompileMemberOffset(SVMVMCBCTRL, AvicLogicalTablePtr, 0xf0);
+AssertCompileMemberOffset(SVMVMCBCTRL, AvicPhysicalTablePtr, 0xf8);
+AssertCompileMemberSize(SVMVMCBCTRL, abInstr, 0x0f);
+
+/**
+ * SVM VMCB state save area.
+ */
+#pragma pack(1)
+typedef struct
+{
+ /** Offset 0x400 - Guest ES register + hidden parts. */
+ SVMSELREG ES;
+ /** Offset 0x410 - Guest CS register + hidden parts. */
+ SVMSELREG CS;
+ /** Offset 0x420 - Guest SS register + hidden parts. */
+ SVMSELREG SS;
+ /** Offset 0x430 - Guest DS register + hidden parts. */
+ SVMSELREG DS;
+ /** Offset 0x440 - Guest FS register + hidden parts. */
+ SVMSELREG FS;
+ /** Offset 0x450 - Guest GS register + hidden parts. */
+ SVMSELREG GS;
+ /** Offset 0x460 - Guest GDTR register. */
+ SVMGDTR GDTR;
+ /** Offset 0x470 - Guest LDTR register + hidden parts. */
+ SVMSELREG LDTR;
+ /** Offset 0x480 - Guest IDTR register. */
+ SVMIDTR IDTR;
+ /** Offset 0x490 - Guest TR register + hidden parts. */
+ SVMSELREG TR;
+ /** Offset 0x4A0-0x4CA - Reserved. */
+ uint8_t u8Reserved0[0x4cb - 0x4a0];
+ /** Offset 0x4CB - CPL. */
+ uint8_t u8CPL;
+ /** Offset 0x4CC-0x4CF - Reserved. */
+ uint8_t u8Reserved1[0x4d0 - 0x4cc];
+ /** Offset 0x4D0 - EFER. */
+ uint64_t u64EFER;
+ /** Offset 0x4D8-0x547 - Reserved. */
+ uint8_t u8Reserved2[0x548 - 0x4d8];
+ /** Offset 0x548 - CR4. */
+ uint64_t u64CR4;
+ /** Offset 0x550 - CR3. */
+ uint64_t u64CR3;
+ /** Offset 0x558 - CR0. */
+ uint64_t u64CR0;
+ /** Offset 0x560 - DR7. */
+ uint64_t u64DR7;
+ /** Offset 0x568 - DR6. */
+ uint64_t u64DR6;
+ /** Offset 0x570 - RFLAGS. */
+ uint64_t u64RFlags;
+ /** Offset 0x578 - RIP. */
+ uint64_t u64RIP;
+ /** Offset 0x580-0x5D7 - Reserved. */
+ uint8_t u8Reserved3[0x5d8 - 0x580];
+ /** Offset 0x5D8 - RSP. */
+ uint64_t u64RSP;
+ /** Offset 0x5E0-0x5F7 - Reserved. */
+ uint8_t u8Reserved4[0x5f8 - 0x5e0];
+ /** Offset 0x5F8 - RAX. */
+ uint64_t u64RAX;
+ /** Offset 0x600 - STAR. */
+ uint64_t u64STAR;
+ /** Offset 0x608 - LSTAR. */
+ uint64_t u64LSTAR;
+ /** Offset 0x610 - CSTAR. */
+ uint64_t u64CSTAR;
+ /** Offset 0x618 - SFMASK. */
+ uint64_t u64SFMASK;
+ /** Offset 0x620 - KernelGSBase. */
+ uint64_t u64KernelGSBase;
+ /** Offset 0x628 - SYSENTER_CS. */
+ uint64_t u64SysEnterCS;
+ /** Offset 0x630 - SYSENTER_ESP. */
+ uint64_t u64SysEnterESP;
+ /** Offset 0x638 - SYSENTER_EIP. */
+ uint64_t u64SysEnterEIP;
+ /** Offset 0x640 - CR2. */
+ uint64_t u64CR2;
+ /** Offset 0x648-0x667 - Reserved. */
+ uint8_t u8Reserved5[0x668 - 0x648];
+ /** Offset 0x668 - PAT (Page Attribute Table) MSR. */
+ uint64_t u64PAT;
+ /** Offset 0x670 - DBGCTL. */
+ uint64_t u64DBGCTL;
+ /** Offset 0x678 - BR_FROM. */
+ uint64_t u64BR_FROM;
+ /** Offset 0x680 - BR_TO. */
+ uint64_t u64BR_TO;
+ /** Offset 0x688 - LASTEXCPFROM. */
+ uint64_t u64LASTEXCPFROM;
+ /** Offset 0x690 - LASTEXCPTO. */
+ uint64_t u64LASTEXCPTO;
+} SVMVMCBSTATESAVE;
+#pragma pack()
+/** Pointer to the SVMVMCBSTATESAVE structure. */
+typedef SVMVMCBSTATESAVE *PSVMVMCBSTATESAVE;
+/** Pointer to a const SVMVMCBSTATESAVE structure. */
+typedef const SVMVMCBSTATESAVE *PCSVMVMCBSTATESAVE;
+AssertCompileSize(SVMVMCBSTATESAVE, 0x298);
+AssertCompileMemberOffset(SVMVMCBSTATESAVE, ES, 0x400 - 0x400);
+AssertCompileMemberOffset(SVMVMCBSTATESAVE, CS, 0x410 - 0x400);
+AssertCompileMemberOffset(SVMVMCBSTATESAVE, SS, 0x420 - 0x400);
+AssertCompileMemberOffset(SVMVMCBSTATESAVE, DS, 0x430 - 0x400);
+AssertCompileMemberOffset(SVMVMCBSTATESAVE, FS, 0x440 - 0x400);
+AssertCompileMemberOffset(SVMVMCBSTATESAVE, GS, 0x450 - 0x400);
+AssertCompileMemberOffset(SVMVMCBSTATESAVE, GDTR, 0x460 - 0x400);
+AssertCompileMemberOffset(SVMVMCBSTATESAVE, LDTR, 0x470 - 0x400);
+AssertCompileMemberOffset(SVMVMCBSTATESAVE, IDTR, 0x480 - 0x400);
+AssertCompileMemberOffset(SVMVMCBSTATESAVE, TR, 0x490 - 0x400);
+AssertCompileMemberOffset(SVMVMCBSTATESAVE, u8Reserved0, 0x4a0 - 0x400);
+AssertCompileMemberOffset(SVMVMCBSTATESAVE, u8CPL, 0x4cb - 0x400);
+AssertCompileMemberOffset(SVMVMCBSTATESAVE, u8Reserved1, 0x4cc - 0x400);
+AssertCompileMemberOffset(SVMVMCBSTATESAVE, u64EFER, 0x4d0 - 0x400);
+AssertCompileMemberOffset(SVMVMCBSTATESAVE, u8Reserved2, 0x4d8 - 0x400);
+AssertCompileMemberOffset(SVMVMCBSTATESAVE, u64CR4, 0x548 - 0x400);
+AssertCompileMemberOffset(SVMVMCBSTATESAVE, u64CR3, 0x550 - 0x400);
+AssertCompileMemberOffset(SVMVMCBSTATESAVE, u64CR0, 0x558 - 0x400);
+AssertCompileMemberOffset(SVMVMCBSTATESAVE, u64DR7, 0x560 - 0x400);
+AssertCompileMemberOffset(SVMVMCBSTATESAVE, u64DR6, 0x568 - 0x400);
+AssertCompileMemberOffset(SVMVMCBSTATESAVE, u64RFlags, 0x570 - 0x400);
+AssertCompileMemberOffset(SVMVMCBSTATESAVE, u64RIP, 0x578 - 0x400);
+AssertCompileMemberOffset(SVMVMCBSTATESAVE, u8Reserved3, 0x580 - 0x400);
+AssertCompileMemberOffset(SVMVMCBSTATESAVE, u64RSP, 0x5d8 - 0x400);
+AssertCompileMemberOffset(SVMVMCBSTATESAVE, u8Reserved4, 0x5e0 - 0x400);
+AssertCompileMemberOffset(SVMVMCBSTATESAVE, u64RAX, 0x5f8 - 0x400);
+AssertCompileMemberOffset(SVMVMCBSTATESAVE, u64STAR, 0x600 - 0x400);
+AssertCompileMemberOffset(SVMVMCBSTATESAVE, u64LSTAR, 0x608 - 0x400);
+AssertCompileMemberOffset(SVMVMCBSTATESAVE, u64CSTAR, 0x610 - 0x400);
+AssertCompileMemberOffset(SVMVMCBSTATESAVE, u64SFMASK, 0x618 - 0x400);
+AssertCompileMemberOffset(SVMVMCBSTATESAVE, u64KernelGSBase, 0x620 - 0x400);
+AssertCompileMemberOffset(SVMVMCBSTATESAVE, u64SysEnterCS, 0x628 - 0x400);
+AssertCompileMemberOffset(SVMVMCBSTATESAVE, u64SysEnterESP, 0x630 - 0x400);
+AssertCompileMemberOffset(SVMVMCBSTATESAVE, u64SysEnterEIP, 0x638 - 0x400);
+AssertCompileMemberOffset(SVMVMCBSTATESAVE, u64CR2, 0x640 - 0x400);
+AssertCompileMemberOffset(SVMVMCBSTATESAVE, u8Reserved5, 0x648 - 0x400);
+AssertCompileMemberOffset(SVMVMCBSTATESAVE, u64PAT, 0x668 - 0x400);
+AssertCompileMemberOffset(SVMVMCBSTATESAVE, u64DBGCTL, 0x670 - 0x400);
+AssertCompileMemberOffset(SVMVMCBSTATESAVE, u64BR_FROM, 0x678 - 0x400);
+AssertCompileMemberOffset(SVMVMCBSTATESAVE, u64BR_TO, 0x680 - 0x400);
+AssertCompileMemberOffset(SVMVMCBSTATESAVE, u64LASTEXCPFROM, 0x688 - 0x400);
+AssertCompileMemberOffset(SVMVMCBSTATESAVE, u64LASTEXCPTO, 0x690 - 0x400);
+
+/**
+ * SVM VM Control Block. (VMCB)
+ */
+#pragma pack(1)
+typedef struct SVMVMCB
+{
+ /** Offset 0x00 - Control area. */
+ SVMVMCBCTRL ctrl;
+ /** Offset 0x100-0x3FF - Reserved. */
+ uint8_t u8Reserved0[0x400 - 0x100];
+ /** Offset 0x400 - State save area. */
+ SVMVMCBSTATESAVE guest;
+ /** Offset 0x698-0xFFF- Reserved. */
+ uint8_t u8Reserved1[0x1000 - 0x698];
+} SVMVMCB;
+#pragma pack()
+/** Pointer to the SVMVMCB structure. */
+typedef SVMVMCB *PSVMVMCB;
+/** Pointer to a const SVMVMCB structure. */
+typedef const SVMVMCB *PCSVMVMCB;
+AssertCompileMemberOffset(SVMVMCB, ctrl, 0x00);
+AssertCompileMemberOffset(SVMVMCB, u8Reserved0, 0x100);
+AssertCompileMemberOffset(SVMVMCB, guest, 0x400);
+AssertCompileMemberOffset(SVMVMCB, u8Reserved1, 0x698);
+AssertCompileSize(SVMVMCB, 0x1000);
+
+/**
+ * SVM MSRs.
+ */
+typedef struct SVMMSRS
+{
+ /** HWCR MSR. */
+ uint64_t u64MsrHwcr;
+ /** Reserved for future. */
+ uint64_t u64Padding[27];
+} SVMMSRS;
+AssertCompileSizeAlignment(SVMMSRS, 8);
+AssertCompileSize(SVMMSRS, 224);
+/** Pointer to a SVMMSRS struct. */
+typedef SVMMSRS *PSVMMSRS;
+/** Pointer to a const SVMMSRS struct. */
+typedef const SVMMSRS *PCSVMMSRS;
+
+/**
+ * SVM VM-exit auxiliary information.
+ *
+ * This includes information that isn't necessarily stored in the guest-CPU
+ * context but provided as part of \#VMEXITs.
+ */
+typedef struct
+{
+ uint64_t u64ExitCode;
+ uint64_t u64ExitInfo1;
+ uint64_t u64ExitInfo2;
+ SVMEVENT ExitIntInfo;
+} SVMEXITAUX;
+/** Pointer to a SVMEXITAUX struct. */
+typedef SVMEXITAUX *PSVMEXITAUX;
+/** Pointer to a const SVMEXITAUX struct. */
+typedef const SVMEXITAUX *PCSVMEXITAUX;
+
+/**
+ * Segment attribute conversion between CPU and AMD-V VMCB format.
+ *
+ * The CPU format of the segment attribute is described in X86DESCATTRBITS
+ * which is 16-bits (i.e. includes 4 bits of the segment limit).
+ *
+ * The AMD-V VMCB format the segment attribute is compact 12-bits (strictly
+ * only the attribute bits and nothing else). Upper 4-bits are unused.
+ */
+#define HMSVM_CPU_2_VMCB_SEG_ATTR(a) ( ((a) & 0xff) | (((a) & 0xf000) >> 4) )
+#define HMSVM_VMCB_2_CPU_SEG_ATTR(a) ( ((a) & 0xff) | (((a) & 0x0f00) << 4) )
+
+/** @def HMSVM_SEG_REG_COPY_TO_VMCB
+ * Copies the specified segment register to a VMCB from a virtual CPU context.
+ *
+ * @param a_pCtx The virtual-CPU context.
+ * @param a_pVmcbStateSave Pointer to the VMCB state-save area.
+ * @param a_REG The segment register in the VMCB state-save
+ * struct (ES/CS/SS/DS).
+ * @param a_reg The segment register in the virtual CPU struct
+ * (es/cs/ss/ds).
+ */
+#define HMSVM_SEG_REG_COPY_TO_VMCB(a_pCtx, a_pVmcbStateSave, a_REG, a_reg) \
+ do \
+ { \
+ Assert((a_pCtx)->a_reg.fFlags & CPUMSELREG_FLAGS_VALID); \
+ Assert((a_pCtx)->a_reg.ValidSel == (a_pCtx)->a_reg.Sel); \
+ (a_pVmcbStateSave)->a_REG.u16Sel = (a_pCtx)->a_reg.Sel; \
+ (a_pVmcbStateSave)->a_REG.u32Limit = (a_pCtx)->a_reg.u32Limit; \
+ (a_pVmcbStateSave)->a_REG.u64Base = (a_pCtx)->a_reg.u64Base; \
+ (a_pVmcbStateSave)->a_REG.u16Attr = HMSVM_CPU_2_VMCB_SEG_ATTR((a_pCtx)->a_reg.Attr.u); \
+ } while (0)
+
+/** @def HMSVM_SEG_REG_COPY_FROM_VMCB
+ * Copies the specified segment register from the VMCB to a virtual CPU
+ * context.
+ *
+ * @param a_pCtx The virtual-CPU context.
+ * @param a_pVmcbStateSave Pointer to the VMCB state-save area.
+ * @param a_REG The segment register in the VMCB state-save
+ * struct (ES/CS/SS/DS).
+ * @param a_reg The segment register in the virtual CPU struct
+ * (es/ds/ss/ds).
+ */
+#define HMSVM_SEG_REG_COPY_FROM_VMCB(a_pCtx, a_pVmcbStateSave, a_REG, a_reg) \
+ do \
+ { \
+ (a_pCtx)->a_reg.Sel = (a_pVmcbStateSave)->a_REG.u16Sel; \
+ (a_pCtx)->a_reg.ValidSel = (a_pVmcbStateSave)->a_REG.u16Sel; \
+ (a_pCtx)->a_reg.fFlags = CPUMSELREG_FLAGS_VALID; \
+ (a_pCtx)->a_reg.u32Limit = (a_pVmcbStateSave)->a_REG.u32Limit; \
+ (a_pCtx)->a_reg.u64Base = (a_pVmcbStateSave)->a_REG.u64Base; \
+ (a_pCtx)->a_reg.Attr.u = HMSVM_VMCB_2_CPU_SEG_ATTR((a_pVmcbStateSave)->a_REG.u16Attr); \
+ } while (0)
+
+
+/** @defgroup grp_hm_svm_hwexec SVM Hardware-assisted execution Helpers
+ *
+ * These functions are only here because the inline functions in cpum.h calls them.
+ * Don't add any more functions here unless there is no other option.
+ * @{
+ */
+VMM_INT_DECL(bool) HMGetGuestSvmCtrlIntercepts(PCVMCPU pVCpu, uint64_t *pu64Intercepts);
+VMM_INT_DECL(bool) HMGetGuestSvmReadCRxIntercepts(PCVMCPU pVCpu, uint16_t *pu16Intercepts);
+VMM_INT_DECL(bool) HMGetGuestSvmWriteCRxIntercepts(PCVMCPU pVCpu, uint16_t *pu16Intercepts);
+VMM_INT_DECL(bool) HMGetGuestSvmReadDRxIntercepts(PCVMCPU pVCpu, uint16_t *pu16Intercepts);
+VMM_INT_DECL(bool) HMGetGuestSvmWriteDRxIntercepts(PCVMCPU pVCpu, uint16_t *pu16Intercepts);
+VMM_INT_DECL(bool) HMGetGuestSvmXcptIntercepts(PCVMCPU pVCpu, uint32_t *pu32Intercepts);
+VMM_INT_DECL(bool) HMGetGuestSvmVirtIntrMasking(PCVMCPU pVCpu, bool *pfVIntrMasking);
+VMM_INT_DECL(bool) HMGetGuestSvmNestedPaging(PCVMCPU pVCpu, bool *pfNestedPagingCtrl);
+VMM_INT_DECL(bool) HMGetGuestSvmPauseFilterCount(PCVMCPU pVCpu, uint16_t *pu16PauseFilterCount);
+VMM_INT_DECL(bool) HMGetGuestSvmTscOffset(PCVMCPU pVCpu, uint64_t *pu64TscOffset);
+/** @} */
+
+
+/** @} */
+
+#endif /* !VBOX_INCLUDED_vmm_hm_svm_h */
+
diff --git a/include/VBox/vmm/hm_vmx.h b/include/VBox/vmm/hm_vmx.h
new file mode 100644
index 00000000..95794dca
--- /dev/null
+++ b/include/VBox/vmm/hm_vmx.h
@@ -0,0 +1,4644 @@
+/** @file
+ * HM - VMX Structures and Definitions. (VMM)
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vmm_hm_vmx_h
+#define VBOX_INCLUDED_vmm_hm_vmx_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/types.h>
+#include <iprt/x86.h>
+#include <iprt/assertcompile.h>
+
+
+/** @defgroup grp_hm_vmx VMX Types and Definitions
+ * @ingroup grp_hm
+ * @{
+ */
+
+/** @name Host-state MSR lazy-restoration flags.
+ * @{
+ */
+/** The host MSRs have been saved. */
+#define VMX_LAZY_MSRS_SAVED_HOST RT_BIT(0)
+/** The guest MSRs are loaded and in effect. */
+#define VMX_LAZY_MSRS_LOADED_GUEST RT_BIT(1)
+/** @} */
+
+/** @name VMX HM-error codes for VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO.
+ * UFC = Unsupported Feature Combination.
+ * @{
+ */
+/** Unsupported pin-based VM-execution controls combo. */
+#define VMX_UFC_CTRL_PIN_EXEC 1
+/** Unsupported processor-based VM-execution controls combo. */
+#define VMX_UFC_CTRL_PROC_EXEC 2
+/** Unsupported move debug register VM-exit combo. */
+#define VMX_UFC_CTRL_PROC_MOV_DRX_EXIT 3
+/** Unsupported VM-entry controls combo. */
+#define VMX_UFC_CTRL_ENTRY 4
+/** Unsupported VM-exit controls combo. */
+#define VMX_UFC_CTRL_EXIT 5
+/** MSR storage capacity of the VMCS autoload/store area is not sufficient
+ * for storing host MSRs. */
+#define VMX_UFC_INSUFFICIENT_HOST_MSR_STORAGE 6
+/** MSR storage capacity of the VMCS autoload/store area is not sufficient
+ * for storing guest MSRs. */
+#define VMX_UFC_INSUFFICIENT_GUEST_MSR_STORAGE 7
+/** Invalid VMCS size. */
+#define VMX_UFC_INVALID_VMCS_SIZE 8
+/** Unsupported secondary processor-based VM-execution controls combo. */
+#define VMX_UFC_CTRL_PROC_EXEC2 9
+/** Invalid unrestricted-guest execution controls combo. */
+#define VMX_UFC_INVALID_UX_COMBO 10
+/** EPT flush type not supported. */
+#define VMX_UFC_EPT_FLUSH_TYPE_UNSUPPORTED 11
+/** EPT paging structure memory type is not write-back. */
+#define VMX_UFC_EPT_MEM_TYPE_NOT_WB 12
+/** EPT requires INVEPT instr. support but it's not available. */
+#define VMX_UFC_EPT_INVEPT_UNAVAILABLE 13
+/** EPT requires page-walk length of 4. */
+#define VMX_UFC_EPT_PAGE_WALK_LENGTH_UNSUPPORTED 14
+/** VMX VMWRITE all feature exposed to the guest but not supported on host. */
+#define VMX_UFC_GST_HOST_VMWRITE_ALL 15
+/** LBR stack size cannot be determined for the current CPU. */
+#define VMX_UFC_LBR_STACK_SIZE_UNKNOWN 16
+/** LBR stack size of the CPU exceeds our buffer size. */
+#define VMX_UFC_LBR_STACK_SIZE_OVERFLOW 17
+/** @} */
+
+/** @name VMX HM-error codes for VERR_VMX_VMCS_FIELD_CACHE_INVALID.
+ * VCI = VMCS-field Cache Invalid.
+ * @{
+ */
+/** Cache of VM-entry controls invalid. */
+#define VMX_VCI_CTRL_ENTRY 300
+/** Cache of VM-exit controls invalid. */
+#define VMX_VCI_CTRL_EXIT 301
+/** Cache of pin-based VM-execution controls invalid. */
+#define VMX_VCI_CTRL_PIN_EXEC 302
+/** Cache of processor-based VM-execution controls invalid. */
+#define VMX_VCI_CTRL_PROC_EXEC 303
+/** Cache of secondary processor-based VM-execution controls invalid. */
+#define VMX_VCI_CTRL_PROC_EXEC2 304
+/** Cache of exception bitmap invalid. */
+#define VMX_VCI_CTRL_XCPT_BITMAP 305
+/** Cache of TSC offset invalid. */
+#define VMX_VCI_CTRL_TSC_OFFSET 306
+/** Cache of tertiary processor-based VM-execution controls invalid. */
+#define VMX_VCI_CTRL_PROC_EXEC3 307
+/** @} */
+
+/** @name VMX HM-error codes for VERR_VMX_INVALID_GUEST_STATE.
+ * IGS = Invalid Guest State.
+ * @{
+ */
+/** An error occurred while checking invalid-guest-state. */
+#define VMX_IGS_ERROR 500
+/** The invalid guest-state checks did not find any reason why. */
+#define VMX_IGS_REASON_NOT_FOUND 501
+/** CR0 fixed1 bits invalid. */
+#define VMX_IGS_CR0_FIXED1 502
+/** CR0 fixed0 bits invalid. */
+#define VMX_IGS_CR0_FIXED0 503
+/** CR0.PE and CR0.PE invalid VT-x/host combination. */
+#define VMX_IGS_CR0_PG_PE_COMBO 504
+/** CR4 fixed1 bits invalid. */
+#define VMX_IGS_CR4_FIXED1 505
+/** CR4 fixed0 bits invalid. */
+#define VMX_IGS_CR4_FIXED0 506
+/** Reserved bits in VMCS' DEBUGCTL MSR field not set to 0 when
+ * VMX_VMCS_CTRL_ENTRY_LOAD_DEBUG is used. */
+#define VMX_IGS_DEBUGCTL_MSR_RESERVED 507
+/** CR0.PG not set for long-mode when not using unrestricted guest. */
+#define VMX_IGS_CR0_PG_LONGMODE 508
+/** CR4.PAE not set for long-mode guest when not using unrestricted guest. */
+#define VMX_IGS_CR4_PAE_LONGMODE 509
+/** CR4.PCIDE set for 32-bit guest. */
+#define VMX_IGS_CR4_PCIDE 510
+/** VMCS' DR7 reserved bits not set to 0. */
+#define VMX_IGS_DR7_RESERVED 511
+/** VMCS' PERF_GLOBAL MSR reserved bits not set to 0. */
+#define VMX_IGS_PERF_GLOBAL_MSR_RESERVED 512
+/** VMCS' EFER MSR reserved bits not set to 0. */
+#define VMX_IGS_EFER_MSR_RESERVED 513
+/** VMCS' EFER MSR.LMA does not match the IA32e mode guest control. */
+#define VMX_IGS_EFER_LMA_GUEST_MODE_MISMATCH 514
+/** VMCS' EFER MSR.LMA does not match EFER.LME of the guest when using paging
+ * without unrestricted guest. */
+#define VMX_IGS_EFER_LMA_LME_MISMATCH 515
+/** CS.Attr.P bit invalid. */
+#define VMX_IGS_CS_ATTR_P_INVALID 516
+/** CS.Attr reserved bits not set to 0. */
+#define VMX_IGS_CS_ATTR_RESERVED 517
+/** CS.Attr.G bit invalid. */
+#define VMX_IGS_CS_ATTR_G_INVALID 518
+/** CS is unusable. */
+#define VMX_IGS_CS_ATTR_UNUSABLE 519
+/** CS and SS DPL unequal. */
+#define VMX_IGS_CS_SS_ATTR_DPL_UNEQUAL 520
+/** CS and SS DPL mismatch. */
+#define VMX_IGS_CS_SS_ATTR_DPL_MISMATCH 521
+/** CS Attr.Type invalid. */
+#define VMX_IGS_CS_ATTR_TYPE_INVALID 522
+/** CS and SS RPL unequal. */
+#define VMX_IGS_SS_CS_RPL_UNEQUAL 523
+/** SS.Attr.DPL and SS RPL unequal. */
+#define VMX_IGS_SS_ATTR_DPL_RPL_UNEQUAL 524
+/** SS.Attr.DPL invalid for segment type. */
+#define VMX_IGS_SS_ATTR_DPL_INVALID 525
+/** SS.Attr.Type invalid. */
+#define VMX_IGS_SS_ATTR_TYPE_INVALID 526
+/** SS.Attr.P bit invalid. */
+#define VMX_IGS_SS_ATTR_P_INVALID 527
+/** SS.Attr reserved bits not set to 0. */
+#define VMX_IGS_SS_ATTR_RESERVED 528
+/** SS.Attr.G bit invalid. */
+#define VMX_IGS_SS_ATTR_G_INVALID 529
+/** DS.Attr.A bit invalid. */
+#define VMX_IGS_DS_ATTR_A_INVALID 530
+/** DS.Attr.P bit invalid. */
+#define VMX_IGS_DS_ATTR_P_INVALID 531
+/** DS.Attr.DPL and DS RPL unequal. */
+#define VMX_IGS_DS_ATTR_DPL_RPL_UNEQUAL 532
+/** DS.Attr reserved bits not set to 0. */
+#define VMX_IGS_DS_ATTR_RESERVED 533
+/** DS.Attr.G bit invalid. */
+#define VMX_IGS_DS_ATTR_G_INVALID 534
+/** DS.Attr.Type invalid. */
+#define VMX_IGS_DS_ATTR_TYPE_INVALID 535
+/** ES.Attr.A bit invalid. */
+#define VMX_IGS_ES_ATTR_A_INVALID 536
+/** ES.Attr.P bit invalid. */
+#define VMX_IGS_ES_ATTR_P_INVALID 537
+/** ES.Attr.DPL and DS RPL unequal. */
+#define VMX_IGS_ES_ATTR_DPL_RPL_UNEQUAL 538
+/** ES.Attr reserved bits not set to 0. */
+#define VMX_IGS_ES_ATTR_RESERVED 539
+/** ES.Attr.G bit invalid. */
+#define VMX_IGS_ES_ATTR_G_INVALID 540
+/** ES.Attr.Type invalid. */
+#define VMX_IGS_ES_ATTR_TYPE_INVALID 541
+/** FS.Attr.A bit invalid. */
+#define VMX_IGS_FS_ATTR_A_INVALID 542
+/** FS.Attr.P bit invalid. */
+#define VMX_IGS_FS_ATTR_P_INVALID 543
+/** FS.Attr.DPL and DS RPL unequal. */
+#define VMX_IGS_FS_ATTR_DPL_RPL_UNEQUAL 544
+/** FS.Attr reserved bits not set to 0. */
+#define VMX_IGS_FS_ATTR_RESERVED 545
+/** FS.Attr.G bit invalid. */
+#define VMX_IGS_FS_ATTR_G_INVALID 546
+/** FS.Attr.Type invalid. */
+#define VMX_IGS_FS_ATTR_TYPE_INVALID 547
+/** GS.Attr.A bit invalid. */
+#define VMX_IGS_GS_ATTR_A_INVALID 548
+/** GS.Attr.P bit invalid. */
+#define VMX_IGS_GS_ATTR_P_INVALID 549
+/** GS.Attr.DPL and DS RPL unequal. */
+#define VMX_IGS_GS_ATTR_DPL_RPL_UNEQUAL 550
+/** GS.Attr reserved bits not set to 0. */
+#define VMX_IGS_GS_ATTR_RESERVED 551
+/** GS.Attr.G bit invalid. */
+#define VMX_IGS_GS_ATTR_G_INVALID 552
+/** GS.Attr.Type invalid. */
+#define VMX_IGS_GS_ATTR_TYPE_INVALID 553
+/** V86 mode CS.Base invalid. */
+#define VMX_IGS_V86_CS_BASE_INVALID 554
+/** V86 mode CS.Limit invalid. */
+#define VMX_IGS_V86_CS_LIMIT_INVALID 555
+/** V86 mode CS.Attr invalid. */
+#define VMX_IGS_V86_CS_ATTR_INVALID 556
+/** V86 mode SS.Base invalid. */
+#define VMX_IGS_V86_SS_BASE_INVALID 557
+/** V86 mode SS.Limit invalid. */
+#define VMX_IGS_V86_SS_LIMIT_INVALID 558
+/** V86 mode SS.Attr invalid. */
+#define VMX_IGS_V86_SS_ATTR_INVALID 559
+/** V86 mode DS.Base invalid. */
+#define VMX_IGS_V86_DS_BASE_INVALID 560
+/** V86 mode DS.Limit invalid. */
+#define VMX_IGS_V86_DS_LIMIT_INVALID 561
+/** V86 mode DS.Attr invalid. */
+#define VMX_IGS_V86_DS_ATTR_INVALID 562
+/** V86 mode ES.Base invalid. */
+#define VMX_IGS_V86_ES_BASE_INVALID 563
+/** V86 mode ES.Limit invalid. */
+#define VMX_IGS_V86_ES_LIMIT_INVALID 564
+/** V86 mode ES.Attr invalid. */
+#define VMX_IGS_V86_ES_ATTR_INVALID 565
+/** V86 mode FS.Base invalid. */
+#define VMX_IGS_V86_FS_BASE_INVALID 566
+/** V86 mode FS.Limit invalid. */
+#define VMX_IGS_V86_FS_LIMIT_INVALID 567
+/** V86 mode FS.Attr invalid. */
+#define VMX_IGS_V86_FS_ATTR_INVALID 568
+/** V86 mode GS.Base invalid. */
+#define VMX_IGS_V86_GS_BASE_INVALID 569
+/** V86 mode GS.Limit invalid. */
+#define VMX_IGS_V86_GS_LIMIT_INVALID 570
+/** V86 mode GS.Attr invalid. */
+#define VMX_IGS_V86_GS_ATTR_INVALID 571
+/** Longmode CS.Base invalid. */
+#define VMX_IGS_LONGMODE_CS_BASE_INVALID 572
+/** Longmode SS.Base invalid. */
+#define VMX_IGS_LONGMODE_SS_BASE_INVALID 573
+/** Longmode DS.Base invalid. */
+#define VMX_IGS_LONGMODE_DS_BASE_INVALID 574
+/** Longmode ES.Base invalid. */
+#define VMX_IGS_LONGMODE_ES_BASE_INVALID 575
+/** SYSENTER ESP is not canonical. */
+#define VMX_IGS_SYSENTER_ESP_NOT_CANONICAL 576
+/** SYSENTER EIP is not canonical. */
+#define VMX_IGS_SYSENTER_EIP_NOT_CANONICAL 577
+/** PAT MSR invalid. */
+#define VMX_IGS_PAT_MSR_INVALID 578
+/** PAT MSR reserved bits not set to 0. */
+#define VMX_IGS_PAT_MSR_RESERVED 579
+/** GDTR.Base is not canonical. */
+#define VMX_IGS_GDTR_BASE_NOT_CANONICAL 580
+/** IDTR.Base is not canonical. */
+#define VMX_IGS_IDTR_BASE_NOT_CANONICAL 581
+/** GDTR.Limit invalid. */
+#define VMX_IGS_GDTR_LIMIT_INVALID 582
+/** IDTR.Limit invalid. */
+#define VMX_IGS_IDTR_LIMIT_INVALID 583
+/** Longmode RIP is invalid. */
+#define VMX_IGS_LONGMODE_RIP_INVALID 584
+/** RFLAGS reserved bits not set to 0. */
+#define VMX_IGS_RFLAGS_RESERVED 585
+/** RFLAGS RA1 reserved bits not set to 1. */
+#define VMX_IGS_RFLAGS_RESERVED1 586
+/** RFLAGS.VM (V86 mode) invalid. */
+#define VMX_IGS_RFLAGS_VM_INVALID 587
+/** RFLAGS.IF invalid. */
+#define VMX_IGS_RFLAGS_IF_INVALID 588
+/** Activity state invalid. */
+#define VMX_IGS_ACTIVITY_STATE_INVALID 589
+/** Activity state HLT invalid when SS.Attr.DPL is not zero. */
+#define VMX_IGS_ACTIVITY_STATE_HLT_INVALID 590
+/** Activity state ACTIVE invalid when block-by-STI or MOV SS. */
+#define VMX_IGS_ACTIVITY_STATE_ACTIVE_INVALID 591
+/** Activity state SIPI WAIT invalid. */
+#define VMX_IGS_ACTIVITY_STATE_SIPI_WAIT_INVALID 592
+/** Interruptibility state reserved bits not set to 0. */
+#define VMX_IGS_INTERRUPTIBILITY_STATE_RESERVED 593
+/** Interruptibility state cannot be block-by-STI -and- MOV SS. */
+#define VMX_IGS_INTERRUPTIBILITY_STATE_STI_MOVSS_INVALID 594
+/** Interruptibility state block-by-STI invalid for EFLAGS. */
+#define VMX_IGS_INTERRUPTIBILITY_STATE_STI_EFL_INVALID 595
+/** Interruptibility state invalid while trying to deliver external
+ * interrupt. */
+#define VMX_IGS_INTERRUPTIBILITY_STATE_EXT_INT_INVALID 596
+/** Interruptibility state block-by-MOVSS invalid while trying to deliver an
+ * NMI. */
+#define VMX_IGS_INTERRUPTIBILITY_STATE_MOVSS_INVALID 597
+/** Interruptibility state block-by-SMI invalid when CPU is not in SMM. */
+#define VMX_IGS_INTERRUPTIBILITY_STATE_SMI_INVALID 598
+/** Interruptibility state block-by-SMI invalid when trying to enter SMM. */
+#define VMX_IGS_INTERRUPTIBILITY_STATE_SMI_SMM_INVALID 599
+/** Interruptibility state block-by-STI (maybe) invalid when trying to
+ * deliver an NMI. */
+#define VMX_IGS_INTERRUPTIBILITY_STATE_STI_INVALID 600
+/** Interruptibility state block-by-NMI invalid when virtual-NMIs control is
+ * active. */
+#define VMX_IGS_INTERRUPTIBILITY_STATE_NMI_INVALID 601
+/** Pending debug exceptions reserved bits not set to 0. */
+#define VMX_IGS_PENDING_DEBUG_RESERVED 602
+/** Longmode pending debug exceptions reserved bits not set to 0. */
+#define VMX_IGS_LONGMODE_PENDING_DEBUG_RESERVED 603
+/** Pending debug exceptions.BS bit is not set when it should be. */
+#define VMX_IGS_PENDING_DEBUG_XCPT_BS_NOT_SET 604
+/** Pending debug exceptions.BS bit is not clear when it should be. */
+#define VMX_IGS_PENDING_DEBUG_XCPT_BS_NOT_CLEAR 605
+/** VMCS link pointer reserved bits not set to 0. */
+#define VMX_IGS_VMCS_LINK_PTR_RESERVED 606
+/** TR cannot index into LDT, TI bit MBZ. */
+#define VMX_IGS_TR_TI_INVALID 607
+/** LDTR cannot index into LDT. TI bit MBZ. */
+#define VMX_IGS_LDTR_TI_INVALID 608
+/** TR.Base is not canonical. */
+#define VMX_IGS_TR_BASE_NOT_CANONICAL 609
+/** FS.Base is not canonical. */
+#define VMX_IGS_FS_BASE_NOT_CANONICAL 610
+/** GS.Base is not canonical. */
+#define VMX_IGS_GS_BASE_NOT_CANONICAL 611
+/** LDTR.Base is not canonical. */
+#define VMX_IGS_LDTR_BASE_NOT_CANONICAL 612
+/** TR is unusable. */
+#define VMX_IGS_TR_ATTR_UNUSABLE 613
+/** TR.Attr.S bit invalid. */
+#define VMX_IGS_TR_ATTR_S_INVALID 614
+/** TR is not present. */
+#define VMX_IGS_TR_ATTR_P_INVALID 615
+/** TR.Attr reserved bits not set to 0. */
+#define VMX_IGS_TR_ATTR_RESERVED 616
+/** TR.Attr.G bit invalid. */
+#define VMX_IGS_TR_ATTR_G_INVALID 617
+/** Longmode TR.Attr.Type invalid. */
+#define VMX_IGS_LONGMODE_TR_ATTR_TYPE_INVALID 618
+/** TR.Attr.Type invalid. */
+#define VMX_IGS_TR_ATTR_TYPE_INVALID 619
+/** CS.Attr.S invalid. */
+#define VMX_IGS_CS_ATTR_S_INVALID 620
+/** CS.Attr.DPL invalid. */
+#define VMX_IGS_CS_ATTR_DPL_INVALID 621
+/** PAE PDPTE reserved bits not set to 0. */
+#define VMX_IGS_PAE_PDPTE_RESERVED 623
+/** VMCS link pointer does not point to a shadow VMCS. */
+#define VMX_IGS_VMCS_LINK_PTR_NOT_SHADOW 624
+/** VMCS link pointer to a shadow VMCS with invalid VMCS revision identifer. */
+#define VMX_IGS_VMCS_LINK_PTR_SHADOW_VMCS_ID_INVALID 625
+/** @} */
+
+/** @name VMX VMCS-Read cache indices.
+ * @{
+ */
+#define VMX_VMCS_GUEST_ES_BASE_CACHE_IDX 0
+#define VMX_VMCS_GUEST_CS_BASE_CACHE_IDX 1
+#define VMX_VMCS_GUEST_SS_BASE_CACHE_IDX 2
+#define VMX_VMCS_GUEST_DS_BASE_CACHE_IDX 3
+#define VMX_VMCS_GUEST_FS_BASE_CACHE_IDX 4
+#define VMX_VMCS_GUEST_GS_BASE_CACHE_IDX 5
+#define VMX_VMCS_GUEST_LDTR_BASE_CACHE_IDX 6
+#define VMX_VMCS_GUEST_TR_BASE_CACHE_IDX 7
+#define VMX_VMCS_GUEST_GDTR_BASE_CACHE_IDX 8
+#define VMX_VMCS_GUEST_IDTR_BASE_CACHE_IDX 9
+#define VMX_VMCS_GUEST_RSP_CACHE_IDX 10
+#define VMX_VMCS_GUEST_RIP_CACHE_IDX 11
+#define VMX_VMCS_GUEST_SYSENTER_ESP_CACHE_IDX 12
+#define VMX_VMCS_GUEST_SYSENTER_EIP_CACHE_IDX 13
+#define VMX_VMCS_RO_EXIT_QUALIFICATION_CACHE_IDX 14
+#define VMX_VMCS_RO_GUEST_LINEAR_ADDR_CACHE_IDX 15
+#define VMX_VMCS_MAX_CACHE_IDX (VMX_VMCS_RO_GUEST_LINEAR_ADDR_CACHE_IDX + 1)
+#define VMX_VMCS_GUEST_CR3_CACHE_IDX 16
+#define VMX_VMCS_MAX_NESTED_PAGING_CACHE_IDX (VMX_VMCS_GUEST_CR3_CACHE_IDX + 1)
+/** @} */
+
+
+/** @name VMX Extended Page Tables (EPT) Common Bits.
+ * @{ */
+/** Bit 0 - Readable (we often think of it as present). */
+#define EPT_E_BIT_READ 0
+#define EPT_E_READ RT_BIT_64(EPT_E_BIT_READ) /**< @see EPT_E_BIT_READ */
+/** Bit 1 - Writable. */
+#define EPT_E_BIT_WRITE 1
+#define EPT_E_WRITE RT_BIT_64(EPT_E_BIT_WRITE) /**< @see EPT_E_BIT_WRITE */
+/** Bit 2 - Executable.
+ * @note This controls supervisor instruction fetching if mode-based
+ * execution control is enabled. */
+#define EPT_E_BIT_EXECUTE 2
+#define EPT_E_EXECUTE RT_BIT_64(EPT_E_BIT_EXECUTE) /**< @see EPT_E_BIT_EXECUTE */
+/** Bits 3-5 - Memory type mask (leaf only, MBZ).
+ * The memory type is only applicable for leaf entries and MBZ for
+ * non-leaf (causes miconfiguration exit). */
+#define EPT_E_MEMTYPE_MASK UINT64_C(0x0038)
+/** Bits 3-5 - Memory type shifted mask. */
+#define EPT_E_MEMTYPE_SMASK UINT64_C(0x0007)
+/** Bits 3-5 - Memory type shift count. */
+#define EPT_E_MEMTYPE_SHIFT 3
+/** Bits 3-5 - Memory type: UC (Uncacheable). */
+#define EPT_E_MEMTYPE_UC (UINT64_C(0) << EPT_E_MEMTYPE_SHIFT)
+/** Bits 3-5 - Memory type: WC (Write Combining). */
+#define EPT_E_MEMTYPE_WC (UINT64_C(1) << EPT_E_MEMTYPE_SHIFT)
+/** Bits 3-5 - Memory type: Invalid (2). */
+#define EPT_E_MEMTYPE_INVALID_2 (UINT64_C(2) << EPT_E_MEMTYPE_SHIFT)
+/** Bits 3-5 - Memory type: Invalid (3). */
+#define EPT_E_MEMTYPE_INVALID_3 (UINT64_C(3) << EPT_E_MEMTYPE_SHIFT)
+/** Bits 3-5 - Memory type: WT (Write Through). */
+#define EPT_E_MEMTYPE_WT (UINT64_C(4) << EPT_E_MEMTYPE_SHIFT)
+/** Bits 3-5 - Memory type: WP (Write Protected). */
+#define EPT_E_MEMTYPE_WP (UINT64_C(5) << EPT_E_MEMTYPE_SHIFT)
+/** Bits 3-5 - Memory type: WB (Write Back). */
+#define EPT_E_MEMTYPE_WB (UINT64_C(6) << EPT_E_MEMTYPE_SHIFT)
+/** Bits 3-5 - Memory type: Invalid (7). */
+#define EPT_E_MEMTYPE_INVALID_7 (UINT64_C(7) << EPT_E_MEMTYPE_SHIFT)
+/** Bit 6 - Ignore page attribute table (leaf, MBZ). */
+#define EPT_E_BIT_IGNORE_PAT 6
+#define EPT_E_IGNORE_PAT RT_BIT_64(EPT_E_BIT_IGNORE_PAT) /**< @see EPT_E_BIT_IGNORE_PAT */
+/** Bit 7 - Leaf entry (MBZ in PML4, ignored in PT). */
+#define EPT_E_BIT_LEAF 7
+#define EPT_E_LEAF RT_BIT_64(EPT_E_BIT_LEAF) /**< @see EPT_E_BIT_LEAF */
+/** Bit 8 - Accessed (all levels).
+ * @note Ignored and not written when EPTP bit 6 is 0. */
+#define EPT_E_BIT_ACCESSED 8
+#define EPT_E_ACCESSED RT_BIT_64(EPT_E_BIT_ACCESSED) /**< @see EPT_E_BIT_ACCESSED */
+/** Bit 9 - Dirty (leaf only).
+ * @note Ignored and not written when EPTP bit 6 is 0. */
+#define EPT_E_BIT_DIRTY 9
+#define EPT_E_DIRTY RT_BIT_64(EPT_E_BIT_DIRTY) /**< @see EPT_E_BIT_DIRTY */
+/** Bit 10 - Executable for usermode.
+ * @note This ignored if mode-based execution control is disabled. */
+#define EPT_E_BIT_USER_EXECUTE 10
+#define EPT_E_USER_EXECUTE RT_BIT_64(EPT_E_BIT_USER_EXECUTE) /**< @see EPT_E_BIT_USER_EXECUTE */
+/* Bit 11 is always ignored. */
+/** Bits 12-51 - Physical Page number of the next level. */
+#define EPT_E_PG_MASK UINT64_C(0x000ffffffffff000)
+/** Bit 58 - Page-write access (leaf only, ignored).
+ * @note Ignored if EPT page-write control is disabled. */
+#define EPT_E_BIT_PAGING_WRITE 58
+#define EPT_E_PAGING_WRITE RT_BIT_64(EPT_E_BIT_PAGING_WRITE) /**< @see EPT_E_BIT_PAGING_WRITE*/
+/* Bit 59 is always ignored. */
+/** Bit 60 - Supervisor shadow stack (leaf only, ignored).
+ * @note Ignored if EPT bit 7 is 0. */
+#define EPT_E_BIT_SUPER_SHW_STACK 60
+#define EPT_E_SUPER_SHW_STACK RT_BIT_64(EPT_E_BIT_SUPER_SHW_STACK) /**< @see EPT_E_BIT_SUPER_SHW_STACK */
+/** Bit 61 - Sub-page write permission (leaf only, ignored).
+ * @note Ignored if sub-page write permission for EPT is disabled. */
+#define EPT_E_BIT_SUBPAGE_WRITE_PERM 61
+#define EPT_E_SUBPAGE_WRITE_PERM RT_BIT_64(EPT_E_BIT_SUBPAGE_WRITE_PERM) /**< @see EPT_E_BIT_SUBPAGE_WRITE_PERM*/
+/* Bit 62 is always ignored. */
+/** Bit 63 - Suppress \#VE (leaf only, ignored).
+ * @note Ignored if EPT violation to \#VE conversion is disabled. */
+#define EPT_E_BIT_SUPPRESS_VE 63
+#define EPT_E_SUPPRESS_VE RT_BIT_64(EPT_E_BIT_SUPPRESS_VE) /**< @see EPT_E_BIT_SUPPRESS_VE */
+/** @} */
+
+
+/**@name Bit fields for common EPT attributes.
+ @{ */
+/** Read access. */
+#define VMX_BF_EPT_PT_READ_SHIFT 0
+#define VMX_BF_EPT_PT_READ_MASK UINT64_C(0x0000000000000001)
+/** Write access. */
+#define VMX_BF_EPT_PT_WRITE_SHIFT 1
+#define VMX_BF_EPT_PT_WRITE_MASK UINT64_C(0x0000000000000002)
+/** Execute access or execute access for supervisor-mode linear-addresses. */
+#define VMX_BF_EPT_PT_EXECUTE_SHIFT 2
+#define VMX_BF_EPT_PT_EXECUTE_MASK UINT64_C(0x0000000000000004)
+/** EPT memory type. */
+#define VMX_BF_EPT_PT_MEMTYPE_SHIFT 3
+#define VMX_BF_EPT_PT_MEMTYPE_MASK UINT64_C(0x0000000000000038)
+/** Ignore PAT. */
+#define VMX_BF_EPT_PT_IGNORE_PAT_SHIFT 6
+#define VMX_BF_EPT_PT_IGNORE_PAT_MASK UINT64_C(0x0000000000000040)
+/** Ignored (bit 7). */
+#define VMX_BF_EPT_PT_IGN_7_SHIFT 7
+#define VMX_BF_EPT_PT_IGN_7_MASK UINT64_C(0x0000000000000080)
+/** Accessed flag. */
+#define VMX_BF_EPT_PT_ACCESSED_SHIFT 8
+#define VMX_BF_EPT_PT_ACCESSED_MASK UINT64_C(0x0000000000000100)
+/** Dirty flag. */
+#define VMX_BF_EPT_PT_DIRTY_SHIFT 9
+#define VMX_BF_EPT_PT_DIRTY_MASK UINT64_C(0x0000000000000200)
+/** Execute access for user-mode linear addresses. */
+#define VMX_BF_EPT_PT_EXECUTE_USER_SHIFT 10
+#define VMX_BF_EPT_PT_EXECUTE_USER_MASK UINT64_C(0x0000000000000400)
+/** Ignored (bit 59:11). */
+#define VMX_BF_EPT_PT_IGN_59_11_SHIFT 11
+#define VMX_BF_EPT_PT_IGN_59_11_MASK UINT64_C(0x0ffffffffffff800)
+/** Supervisor shadow stack. */
+#define VMX_BF_EPT_PT_SUPER_SHW_STACK_SHIFT 60
+#define VMX_BF_EPT_PT_SUPER_SHW_STACK_MASK UINT64_C(0x1000000000000000)
+/** Ignored (bits 62:61). */
+#define VMX_BF_EPT_PT_IGN_62_61_SHIFT 61
+#define VMX_BF_EPT_PT_IGN_62_61_MASK UINT64_C(0x6000000000000000)
+/** Suppress \#VE. */
+#define VMX_BF_EPT_PT_SUPPRESS_VE_SHIFT 63
+#define VMX_BF_EPT_PT_SUPPRESS_VE_MASK UINT64_C(0x8000000000000000)
+RT_BF_ASSERT_COMPILE_CHECKS(VMX_BF_EPT_PT_, UINT64_C(0), UINT64_MAX,
+ (READ, WRITE, EXECUTE, MEMTYPE, IGNORE_PAT, IGN_7, ACCESSED, DIRTY, EXECUTE_USER, IGN_59_11,
+ SUPER_SHW_STACK, IGN_62_61, SUPPRESS_VE));
+/** @} */
+
+
+/** @name VMX Extended Page Tables (EPT) Structures
+ * @{
+ */
+
+/**
+ * Number of page table entries in the EPT. (PDPTE/PDE/PTE)
+ */
+#define EPT_PG_ENTRIES X86_PG_PAE_ENTRIES
+
+/**
+ * EPT present mask.
+ * These are ONLY the common bits in all EPT page-table entries which does
+ * not rely on any CPU feature. It isn't necessarily the complete mask (e.g. when
+ * mode-based excute control is active).
+ */
+#define EPT_PRESENT_MASK (EPT_E_READ | EPT_E_WRITE | EPT_E_EXECUTE)
+
+/**
+ * EPT Page Directory Pointer Entry. Bit view.
+ * In accordance with the VT-x spec.
+ *
+ * @todo uint64_t isn't safe for bitfields (gcc pedantic warnings, and IIRC,
+ * this did cause trouble with one compiler/version).
+ */
+typedef struct EPTPML4EBITS
+{
+ /** Present bit. */
+ RT_GCC_EXTENSION uint64_t u1Present : 1;
+ /** Writable bit. */
+ RT_GCC_EXTENSION uint64_t u1Write : 1;
+ /** Executable bit. */
+ RT_GCC_EXTENSION uint64_t u1Execute : 1;
+ /** Reserved (must be 0). */
+ RT_GCC_EXTENSION uint64_t u5Reserved : 5;
+ /** Available for software. */
+ RT_GCC_EXTENSION uint64_t u4Available : 4;
+ /** Physical address of the next level (PD). Restricted by maximum physical address width of the cpu. */
+ RT_GCC_EXTENSION uint64_t u40PhysAddr : 40;
+ /** Available for software. */
+ RT_GCC_EXTENSION uint64_t u12Available : 12;
+} EPTPML4EBITS;
+AssertCompileSize(EPTPML4EBITS, 8);
+
+/** Bits 12-51 - - EPT - Physical Page number of the next level. */
+#define EPT_PML4E_PG_MASK X86_PML4E_PG_MASK
+/** The page shift to get the PML4 index. */
+#define EPT_PML4_SHIFT X86_PML4_SHIFT
+/** The PML4 index mask (apply to a shifted page address). */
+#define EPT_PML4_MASK X86_PML4_MASK
+/** Bits - - EPT - PML4 MBZ mask. */
+#define EPT_PML4E_MBZ_MASK UINT64_C(0x00000000000000f8)
+/** Mask of all possible EPT PML4E attribute bits. */
+#define EPT_PML4E_ATTR_MASK (EPT_E_READ | EPT_E_WRITE | EPT_E_EXECUTE | EPT_E_ACCESSED | EPT_E_USER_EXECUTE)
+
+/**
+ * EPT PML4E.
+ * In accordance with the VT-x spec.
+ */
+typedef union EPTPML4E
+{
+#ifndef VBOX_WITHOUT_PAGING_BIT_FIELDS
+ /** Normal view. */
+ EPTPML4EBITS n;
+#endif
+ /** Unsigned integer view. */
+ X86PGPAEUINT u;
+ /** 64 bit unsigned integer view. */
+ uint64_t au64[1];
+ /** 32 bit unsigned integer view. */
+ uint32_t au32[2];
+} EPTPML4E;
+AssertCompileSize(EPTPML4E, 8);
+/** Pointer to a PML4 table entry. */
+typedef EPTPML4E *PEPTPML4E;
+/** Pointer to a const PML4 table entry. */
+typedef const EPTPML4E *PCEPTPML4E;
+
+/**
+ * EPT PML4 Table.
+ * In accordance with the VT-x spec.
+ */
+typedef struct EPTPML4
+{
+ EPTPML4E a[EPT_PG_ENTRIES];
+} EPTPML4;
+AssertCompileSize(EPTPML4, 0x1000);
+/** Pointer to an EPT PML4 Table. */
+typedef EPTPML4 *PEPTPML4;
+/** Pointer to a const EPT PML4 Table. */
+typedef const EPTPML4 *PCEPTPML4;
+
+
+/**
+ * EPT Page Directory Pointer Entry. Bit view.
+ * In accordance with the VT-x spec.
+ */
+typedef struct EPTPDPTEBITS
+{
+ /** Present bit. */
+ RT_GCC_EXTENSION uint64_t u1Present : 1;
+ /** Writable bit. */
+ RT_GCC_EXTENSION uint64_t u1Write : 1;
+ /** Executable bit. */
+ RT_GCC_EXTENSION uint64_t u1Execute : 1;
+ /** Reserved (must be 0). */
+ RT_GCC_EXTENSION uint64_t u5Reserved : 5;
+ /** Available for software. */
+ RT_GCC_EXTENSION uint64_t u4Available : 4;
+ /** Physical address of the next level (PD). Restricted by maximum physical address width of the cpu. */
+ RT_GCC_EXTENSION uint64_t u40PhysAddr : 40;
+ /** Available for software. */
+ RT_GCC_EXTENSION uint64_t u12Available : 12;
+} EPTPDPTEBITS;
+AssertCompileSize(EPTPDPTEBITS, 8);
+
+/** Bit 7 - - EPT - PDPTE maps a 1GB page. */
+#define EPT_PDPTE1G_SIZE_MASK RT_BIT_64(7)
+/** Bits 12-51 - - EPT - Physical Page number of the next level. */
+#define EPT_PDPTE_PG_MASK X86_PDPE_PG_MASK
+/** Bits 30-51 - - EPT - Physical Page number of the 1G large page. */
+#define EPT_PDPTE1G_PG_MASK X86_PDPE1G_PG_MASK
+
+/** The page shift to get the PDPT index. */
+#define EPT_PDPT_SHIFT X86_PDPT_SHIFT
+/** The PDPT index mask (apply to a shifted page address). */
+#define EPT_PDPT_MASK X86_PDPT_MASK_AMD64
+/** Bits 3-7 - - EPT - PDPTE MBZ Mask. */
+#define EPT_PDPTE_MBZ_MASK UINT64_C(0x00000000000000f8)
+/** Bits 12-29 - - EPT - 1GB PDPTE MBZ Mask. */
+#define EPT_PDPTE1G_MBZ_MASK UINT64_C(0x000000003ffff000)
+/** Mask of all possible EPT PDPTE (1GB) attribute bits. */
+#define EPT_PDPTE1G_ATTR_MASK ( EPT_E_READ | EPT_E_WRITE | EPT_E_EXECUTE | EPT_E_MEMTYPE_MASK | EPT_E_IGNORE_PAT \
+ | EPT_E_ACCESSED | EPT_E_DIRTY | EPT_E_USER_EXECUTE)
+/** Mask of all possible EPT PDPTE attribute bits. */
+#define EPT_PDPTE_ATTR_MASK (EPT_E_READ | EPT_E_WRITE | EPT_E_EXECUTE | EPT_E_ACCESSED | EPT_E_USER_EXECUTE)
+/** */
+
+/**
+ * EPT Page Directory Pointer.
+ * In accordance with the VT-x spec.
+ */
+typedef union EPTPDPTE
+{
+#ifndef VBOX_WITHOUT_PAGING_BIT_FIELDS
+ /** Normal view. */
+ EPTPDPTEBITS n;
+#endif
+ /** Unsigned integer view. */
+ X86PGPAEUINT u;
+ /** 64 bit unsigned integer view. */
+ uint64_t au64[1];
+ /** 32 bit unsigned integer view. */
+ uint32_t au32[2];
+} EPTPDPTE;
+AssertCompileSize(EPTPDPTE, 8);
+/** Pointer to an EPT Page Directory Pointer Entry. */
+typedef EPTPDPTE *PEPTPDPTE;
+/** Pointer to a const EPT Page Directory Pointer Entry. */
+typedef const EPTPDPTE *PCEPTPDPTE;
+
+/**
+ * EPT Page Directory Pointer Table.
+ * In accordance with the VT-x spec.
+ */
+typedef struct EPTPDPT
+{
+ EPTPDPTE a[EPT_PG_ENTRIES];
+} EPTPDPT;
+AssertCompileSize(EPTPDPT, 0x1000);
+/** Pointer to an EPT Page Directory Pointer Table. */
+typedef EPTPDPT *PEPTPDPT;
+/** Pointer to a const EPT Page Directory Pointer Table. */
+typedef const EPTPDPT *PCEPTPDPT;
+
+
+/**
+ * EPT Page Directory Table Entry. Bit view.
+ * In accordance with the VT-x spec.
+ */
+typedef struct EPTPDEBITS
+{
+ /** Present bit. */
+ RT_GCC_EXTENSION uint64_t u1Present : 1;
+ /** Writable bit. */
+ RT_GCC_EXTENSION uint64_t u1Write : 1;
+ /** Executable bit. */
+ RT_GCC_EXTENSION uint64_t u1Execute : 1;
+ /** Reserved (must be 0). */
+ RT_GCC_EXTENSION uint64_t u4Reserved : 4;
+ /** Big page (must be 0 here). */
+ RT_GCC_EXTENSION uint64_t u1Size : 1;
+ /** Available for software. */
+ RT_GCC_EXTENSION uint64_t u4Available : 4;
+ /** Physical address of page table. Restricted by maximum physical address width of the cpu. */
+ RT_GCC_EXTENSION uint64_t u40PhysAddr : 40;
+ /** Available for software. */
+ RT_GCC_EXTENSION uint64_t u12Available : 12;
+} EPTPDEBITS;
+AssertCompileSize(EPTPDEBITS, 8);
+
+/** Bits 12-51 - - EPT - Physical Page number of the next level. */
+#define EPT_PDE_PG_MASK X86_PDE_PAE_PG_MASK
+/** The page shift to get the PD index. */
+#define EPT_PD_SHIFT X86_PD_PAE_SHIFT
+/** The PD index mask (apply to a shifted page address). */
+#define EPT_PD_MASK X86_PD_PAE_MASK
+/** Bits 3-7 - EPT - PDE MBZ Mask. */
+#define EPT_PDE_MBZ_MASK UINT64_C(0x00000000000000f8)
+/** Mask of all possible EPT PDE (2M) attribute bits. */
+#define EPT_PDE2M_ATTR_MASK ( EPT_E_READ | EPT_E_WRITE | EPT_E_EXECUTE | EPT_E_MEMTYPE_MASK | EPT_E_IGNORE_PAT \
+ | EPT_E_ACCESSED | EPT_E_DIRTY | EPT_E_USER_EXECUTE)
+/** Mask of all possible EPT PDE attribute bits. */
+#define EPT_PDE_ATTR_MASK (EPT_E_READ | EPT_E_WRITE | EPT_E_EXECUTE | EPT_E_ACCESSED | EPT_E_USER_EXECUTE)
+
+
+/**
+ * EPT 2MB Page Directory Table Entry. Bit view.
+ * In accordance with the VT-x spec.
+ */
+typedef struct EPTPDE2MBITS
+{
+ /** Present bit. */
+ RT_GCC_EXTENSION uint64_t u1Present : 1;
+ /** Writable bit. */
+ RT_GCC_EXTENSION uint64_t u1Write : 1;
+ /** Executable bit. */
+ RT_GCC_EXTENSION uint64_t u1Execute : 1;
+ /** EPT Table Memory Type. MBZ for non-leaf nodes. */
+ RT_GCC_EXTENSION uint64_t u3EMT : 3;
+ /** Ignore PAT memory type */
+ RT_GCC_EXTENSION uint64_t u1IgnorePAT : 1;
+ /** Big page (must be 1 here). */
+ RT_GCC_EXTENSION uint64_t u1Size : 1;
+ /** Available for software. */
+ RT_GCC_EXTENSION uint64_t u4Available : 4;
+ /** Reserved (must be 0). */
+ RT_GCC_EXTENSION uint64_t u9Reserved : 9;
+ /** Physical address of the 2MB page. Restricted by maximum physical address width of the cpu. */
+ RT_GCC_EXTENSION uint64_t u31PhysAddr : 31;
+ /** Available for software. */
+ RT_GCC_EXTENSION uint64_t u12Available : 12;
+} EPTPDE2MBITS;
+AssertCompileSize(EPTPDE2MBITS, 8);
+
+/** Bits 21-51 - - EPT - Physical Page number of the next level. */
+#define EPT_PDE2M_PG_MASK X86_PDE2M_PAE_PG_MASK
+/** Bits 20-12 - - EPT - PDE 2M MBZ Mask. */
+#define EPT_PDE2M_MBZ_MASK UINT64_C(0x00000000001ff000)
+
+
+/**
+ * EPT Page Directory Table Entry.
+ * In accordance with the VT-x spec.
+ */
+typedef union EPTPDE
+{
+#ifndef VBOX_WITHOUT_PAGING_BIT_FIELDS
+ /** Normal view. */
+ EPTPDEBITS n;
+ /** 2MB view (big). */
+ EPTPDE2MBITS b;
+#endif
+ /** Unsigned integer view. */
+ X86PGPAEUINT u;
+ /** 64 bit unsigned integer view. */
+ uint64_t au64[1];
+ /** 32 bit unsigned integer view. */
+ uint32_t au32[2];
+} EPTPDE;
+AssertCompileSize(EPTPDE, 8);
+/** Pointer to an EPT Page Directory Table Entry. */
+typedef EPTPDE *PEPTPDE;
+/** Pointer to a const EPT Page Directory Table Entry. */
+typedef const EPTPDE *PCEPTPDE;
+
+/**
+ * EPT Page Directory Table.
+ * In accordance with the VT-x spec.
+ */
+typedef struct EPTPD
+{
+ EPTPDE a[EPT_PG_ENTRIES];
+} EPTPD;
+AssertCompileSize(EPTPD, 0x1000);
+/** Pointer to an EPT Page Directory Table. */
+typedef EPTPD *PEPTPD;
+/** Pointer to a const EPT Page Directory Table. */
+typedef const EPTPD *PCEPTPD;
+
+/**
+ * EPT Page Table Entry. Bit view.
+ * In accordance with the VT-x spec.
+ */
+typedef struct EPTPTEBITS
+{
+ /** 0 - Present bit.
+ * @remarks This is a convenience "misnomer". The bit actually indicates read access
+ * and the CPU will consider an entry with any of the first three bits set
+ * as present. Since all our valid entries will have this bit set, it can
+ * be used as a present indicator and allow some code sharing. */
+ RT_GCC_EXTENSION uint64_t u1Present : 1;
+ /** 1 - Writable bit. */
+ RT_GCC_EXTENSION uint64_t u1Write : 1;
+ /** 2 - Executable bit. */
+ RT_GCC_EXTENSION uint64_t u1Execute : 1;
+ /** 5:3 - EPT Memory Type. MBZ for non-leaf nodes. */
+ RT_GCC_EXTENSION uint64_t u3EMT : 3;
+ /** 6 - Ignore PAT memory type */
+ RT_GCC_EXTENSION uint64_t u1IgnorePAT : 1;
+ /** 11:7 - Available for software. */
+ RT_GCC_EXTENSION uint64_t u5Available : 5;
+ /** 51:12 - Physical address of page. Restricted by maximum physical
+ * address width of the cpu. */
+ RT_GCC_EXTENSION uint64_t u40PhysAddr : 40;
+ /** 63:52 - Available for software. */
+ RT_GCC_EXTENSION uint64_t u12Available : 12;
+} EPTPTEBITS;
+AssertCompileSize(EPTPTEBITS, 8);
+
+/** Bits 12-51 - - EPT - Physical Page number of the next level. */
+#define EPT_PTE_PG_MASK X86_PTE_PAE_PG_MASK
+/** The page shift to get the EPT PTE index. */
+#define EPT_PT_SHIFT X86_PT_PAE_SHIFT
+/** The EPT PT index mask (apply to a shifted page address). */
+#define EPT_PT_MASK X86_PT_PAE_MASK
+/** No bits - - EPT - PTE MBZ bits. */
+#define EPT_PTE_MBZ_MASK UINT64_C(0x0000000000000000)
+/** Mask of all possible EPT PTE attribute bits. */
+#define EPT_PTE_ATTR_MASK ( EPT_E_READ | EPT_E_WRITE | EPT_E_EXECUTE | EPT_E_MEMTYPE_MASK | EPT_E_IGNORE_PAT \
+ | EPT_E_ACCESSED | EPT_E_USER_EXECUTE)
+
+
+/**
+ * EPT Page Table Entry.
+ * In accordance with the VT-x spec.
+ */
+typedef union EPTPTE
+{
+#ifndef VBOX_WITHOUT_PAGING_BIT_FIELDS
+ /** Normal view. */
+ EPTPTEBITS n;
+#endif
+ /** Unsigned integer view. */
+ X86PGPAEUINT u;
+ /** 64 bit unsigned integer view. */
+ uint64_t au64[1];
+ /** 32 bit unsigned integer view. */
+ uint32_t au32[2];
+} EPTPTE;
+AssertCompileSize(EPTPTE, 8);
+/** Pointer to an EPT Page Directory Table Entry. */
+typedef EPTPTE *PEPTPTE;
+/** Pointer to a const EPT Page Directory Table Entry. */
+typedef const EPTPTE *PCEPTPTE;
+
+/**
+ * EPT Page Table.
+ * In accordance with the VT-x spec.
+ */
+typedef struct EPTPT
+{
+ EPTPTE a[EPT_PG_ENTRIES];
+} EPTPT;
+AssertCompileSize(EPTPT, 0x1000);
+/** Pointer to an extended page table. */
+typedef EPTPT *PEPTPT;
+/** Pointer to a const extended table. */
+typedef const EPTPT *PCEPTPT;
+
+/** EPTP page mask for the EPT PML4 table. */
+#define EPT_EPTP_PG_MASK X86_CR3_AMD64_PAGE_MASK
+/** @} */
+
+/**
+ * VMX VPID flush types.
+ * Valid enum members are in accordance with the VT-x spec.
+ */
+typedef enum
+{
+ /** Invalidate a specific page. */
+ VMXTLBFLUSHVPID_INDIV_ADDR = 0,
+ /** Invalidate one context (specific VPID). */
+ VMXTLBFLUSHVPID_SINGLE_CONTEXT = 1,
+ /** Invalidate all contexts (all VPIDs). */
+ VMXTLBFLUSHVPID_ALL_CONTEXTS = 2,
+ /** Invalidate a single VPID context retaining global mappings. */
+ VMXTLBFLUSHVPID_SINGLE_CONTEXT_RETAIN_GLOBALS = 3,
+ /** Unsupported by VirtualBox. */
+ VMXTLBFLUSHVPID_NOT_SUPPORTED = 0xbad0,
+ /** Unsupported by CPU. */
+ VMXTLBFLUSHVPID_NONE = 0xbad1
+} VMXTLBFLUSHVPID;
+AssertCompileSize(VMXTLBFLUSHVPID, 4);
+/** Mask of all valid INVVPID flush types. */
+#define VMX_INVVPID_VALID_MASK ( VMXTLBFLUSHVPID_INDIV_ADDR \
+ | VMXTLBFLUSHVPID_SINGLE_CONTEXT \
+ | VMXTLBFLUSHVPID_ALL_CONTEXTS \
+ | VMXTLBFLUSHVPID_SINGLE_CONTEXT_RETAIN_GLOBALS)
+
+/**
+ * VMX EPT flush types.
+ * @note Valid enums values are in accordance with the VT-x spec.
+ */
+typedef enum
+{
+ /** Invalidate one context (specific EPT). */
+ VMXTLBFLUSHEPT_SINGLE_CONTEXT = 1,
+ /* Invalidate all contexts (all EPTs) */
+ VMXTLBFLUSHEPT_ALL_CONTEXTS = 2,
+ /** Unsupported by VirtualBox. */
+ VMXTLBFLUSHEPT_NOT_SUPPORTED = 0xbad0,
+ /** Unsupported by CPU. */
+ VMXTLBFLUSHEPT_NONE = 0xbad1
+} VMXTLBFLUSHEPT;
+AssertCompileSize(VMXTLBFLUSHEPT, 4);
+/** Mask of all valid INVEPT flush types. */
+#define VMX_INVEPT_VALID_MASK ( VMXTLBFLUSHEPT_SINGLE_CONTEXT \
+ | VMXTLBFLUSHEPT_ALL_CONTEXTS)
+
+/**
+ * VMX Posted Interrupt Descriptor.
+ * In accordance with the VT-x spec.
+ */
+typedef struct VMXPOSTEDINTRDESC
+{
+ uint32_t aVectorBitmap[8];
+ uint32_t fOutstandingNotification : 1;
+ uint32_t uReserved0 : 31;
+ uint8_t au8Reserved0[28];
+} VMXPOSTEDINTRDESC;
+AssertCompileMemberSize(VMXPOSTEDINTRDESC, aVectorBitmap, 32);
+AssertCompileSize(VMXPOSTEDINTRDESC, 64);
+/** Pointer to a posted interrupt descriptor. */
+typedef VMXPOSTEDINTRDESC *PVMXPOSTEDINTRDESC;
+/** Pointer to a const posted interrupt descriptor. */
+typedef const VMXPOSTEDINTRDESC *PCVMXPOSTEDINTRDESC;
+
+/**
+ * VMX VMCS revision identifier.
+ * In accordance with the VT-x spec.
+ */
+typedef union
+{
+ struct
+ {
+ /** Revision identifier. */
+ uint32_t u31RevisionId : 31;
+ /** Whether this is a shadow VMCS. */
+ uint32_t fIsShadowVmcs : 1;
+ } n;
+ /* The unsigned integer view. */
+ uint32_t u;
+} VMXVMCSREVID;
+AssertCompileSize(VMXVMCSREVID, 4);
+/** Pointer to the VMXVMCSREVID union. */
+typedef VMXVMCSREVID *PVMXVMCSREVID;
+/** Pointer to a const VMXVMCSREVID union. */
+typedef const VMXVMCSREVID *PCVMXVMCSREVID;
+
+/**
+ * VMX VM-exit instruction information.
+ * In accordance with the VT-x spec.
+ */
+typedef union
+{
+ /** Plain unsigned int representation. */
+ uint32_t u;
+
+ /** INS and OUTS information. */
+ struct
+ {
+ uint32_t u7Reserved0 : 7;
+ /** The address size; 0=16-bit, 1=32-bit, 2=64-bit, rest undefined. */
+ uint32_t u3AddrSize : 3;
+ uint32_t u5Reserved1 : 5;
+ /** The segment register (X86_SREG_XXX). */
+ uint32_t iSegReg : 3;
+ uint32_t uReserved2 : 14;
+ } StrIo;
+
+ /** INVEPT, INVPCID, INVVPID information. */
+ struct
+ {
+ /** Scaling; 0=no scaling, 1=scale-by-2, 2=scale-by-4, 3=scale-by-8. */
+ uint32_t u2Scaling : 2;
+ uint32_t u5Undef0 : 5;
+ /** The address size; 0=16-bit, 1=32-bit, 2=64-bit, rest undefined. */
+ uint32_t u3AddrSize : 3;
+ /** Cleared to 0. */
+ uint32_t u1Cleared0 : 1;
+ uint32_t u4Undef0 : 4;
+ /** The segment register (X86_SREG_XXX). */
+ uint32_t iSegReg : 3;
+ /** The index register (X86_GREG_XXX). */
+ uint32_t iIdxReg : 4;
+ /** Set if index register is invalid. */
+ uint32_t fIdxRegInvalid : 1;
+ /** The base register (X86_GREG_XXX). */
+ uint32_t iBaseReg : 4;
+ /** Set if base register is invalid. */
+ uint32_t fBaseRegInvalid : 1;
+ /** Register 2 (X86_GREG_XXX). */
+ uint32_t iReg2 : 4;
+ } Inv;
+
+ /** VMCLEAR, VMPTRLD, VMPTRST, VMXON, XRSTORS, XSAVES information. */
+ struct
+ {
+ /** Scaling; 0=no scaling, 1=scale-by-2, 2=scale-by-4, 3=scale-by-8. */
+ uint32_t u2Scaling : 2;
+ uint32_t u5Reserved0 : 5;
+ /** The address size; 0=16-bit, 1=32-bit, 2=64-bit, rest undefined. */
+ uint32_t u3AddrSize : 3;
+ /** Cleared to 0. */
+ uint32_t u1Cleared0 : 1;
+ uint32_t u4Reserved0 : 4;
+ /** The segment register (X86_SREG_XXX). */
+ uint32_t iSegReg : 3;
+ /** The index register (X86_GREG_XXX). */
+ uint32_t iIdxReg : 4;
+ /** Set if index register is invalid. */
+ uint32_t fIdxRegInvalid : 1;
+ /** The base register (X86_GREG_XXX). */
+ uint32_t iBaseReg : 4;
+ /** Set if base register is invalid. */
+ uint32_t fBaseRegInvalid : 1;
+ /** Register 2 (X86_GREG_XXX). */
+ uint32_t iReg2 : 4;
+ } VmxXsave;
+
+ /** LIDT, LGDT, SIDT, SGDT information. */
+ struct
+ {
+ /** Scaling; 0=no scaling, 1=scale-by-2, 2=scale-by-4, 3=scale-by-8. */
+ uint32_t u2Scaling : 2;
+ uint32_t u5Undef0 : 5;
+ /** The address size; 0=16-bit, 1=32-bit, 2=64-bit, rest undefined. */
+ uint32_t u3AddrSize : 3;
+ /** Always cleared to 0. */
+ uint32_t u1Cleared0 : 1;
+ /** Operand size; 0=16-bit, 1=32-bit, undefined for 64-bit. */
+ uint32_t uOperandSize : 1;
+ uint32_t u3Undef0 : 3;
+ /** The segment register (X86_SREG_XXX). */
+ uint32_t iSegReg : 3;
+ /** The index register (X86_GREG_XXX). */
+ uint32_t iIdxReg : 4;
+ /** Set if index register is invalid. */
+ uint32_t fIdxRegInvalid : 1;
+ /** The base register (X86_GREG_XXX). */
+ uint32_t iBaseReg : 4;
+ /** Set if base register is invalid. */
+ uint32_t fBaseRegInvalid : 1;
+ /** Instruction identity (VMX_INSTR_ID_XXX). */
+ uint32_t u2InstrId : 2;
+ uint32_t u2Undef0 : 2;
+ } GdtIdt;
+
+ /** LLDT, LTR, SLDT, STR information. */
+ struct
+ {
+ /** Scaling; 0=no scaling, 1=scale-by-2, 2=scale-by-4, 3=scale-by-8. */
+ uint32_t u2Scaling : 2;
+ uint32_t u1Undef0 : 1;
+ /** Register 1 (X86_GREG_XXX). */
+ uint32_t iReg1 : 4;
+ /** The address size; 0=16-bit, 1=32-bit, 2=64-bit, rest undefined. */
+ uint32_t u3AddrSize : 3;
+ /** Memory/Register - Always cleared to 0 to indicate memory operand. */
+ uint32_t fIsRegOperand : 1;
+ uint32_t u4Undef0 : 4;
+ /** The segment register (X86_SREG_XXX). */
+ uint32_t iSegReg : 3;
+ /** The index register (X86_GREG_XXX). */
+ uint32_t iIdxReg : 4;
+ /** Set if index register is invalid. */
+ uint32_t fIdxRegInvalid : 1;
+ /** The base register (X86_GREG_XXX). */
+ uint32_t iBaseReg : 4;
+ /** Set if base register is invalid. */
+ uint32_t fBaseRegInvalid : 1;
+ /** Instruction identity (VMX_INSTR_ID_XXX). */
+ uint32_t u2InstrId : 2;
+ uint32_t u2Undef0 : 2;
+ } LdtTr;
+
+ /** RDRAND, RDSEED information. */
+ struct
+ {
+ /** Scaling; 0=no scaling, 1=scale-by-2, 2=scale-by-4, 3=scale-by-8. */
+ uint32_t u2Undef0 : 2;
+ /** Destination register (X86_GREG_XXX). */
+ uint32_t iReg1 : 4;
+ uint32_t u4Undef0 : 4;
+ /** Operand size; 0=16-bit, 1=32-bit, 2=64-bit, 3=unused. */
+ uint32_t u2OperandSize : 2;
+ uint32_t u19Def0 : 20;
+ } RdrandRdseed;
+
+ /** VMREAD, VMWRITE information. */
+ struct
+ {
+ /** Scaling; 0=no scaling, 1=scale-by-2, 2=scale-by-4, 3=scale-by-8. */
+ uint32_t u2Scaling : 2;
+ uint32_t u1Undef0 : 1;
+ /** Register 1 (X86_GREG_XXX). */
+ uint32_t iReg1 : 4;
+ /** The address size; 0=16-bit, 1=32-bit, 2=64-bit, rest undefined. */
+ uint32_t u3AddrSize : 3;
+ /** Memory or register operand. */
+ uint32_t fIsRegOperand : 1;
+ /** Operand size; 0=16-bit, 1=32-bit, 2=64-bit, 3=unused. */
+ uint32_t u4Undef0 : 4;
+ /** The segment register (X86_SREG_XXX). */
+ uint32_t iSegReg : 3;
+ /** The index register (X86_GREG_XXX). */
+ uint32_t iIdxReg : 4;
+ /** Set if index register is invalid. */
+ uint32_t fIdxRegInvalid : 1;
+ /** The base register (X86_GREG_XXX). */
+ uint32_t iBaseReg : 4;
+ /** Set if base register is invalid. */
+ uint32_t fBaseRegInvalid : 1;
+ /** Register 2 (X86_GREG_XXX). */
+ uint32_t iReg2 : 4;
+ } VmreadVmwrite;
+
+ struct
+ {
+ uint32_t u2Undef0 : 3;
+ /** First XMM register operand. */
+ uint32_t u4XmmReg1 : 4;
+ uint32_t u23Undef1 : 21;
+ /** Second XMM register operand. */
+ uint32_t u4XmmReg2 : 4;
+ } LoadIwkey;
+
+ /** This is a combination field of all instruction information. Note! Not all field
+ * combinations are valid (e.g., iReg1 is undefined for memory operands) and
+ * specialized fields are overwritten by their generic counterparts (e.g. no
+ * instruction identity field). */
+ struct
+ {
+ /** Scaling; 0=no scaling, 1=scale-by-2, 2=scale-by-4, 3=scale-by-8. */
+ uint32_t u2Scaling : 2;
+ uint32_t u1Undef0 : 1;
+ /** Register 1 (X86_GREG_XXX). */
+ uint32_t iReg1 : 4;
+ /** The address size; 0=16-bit, 1=32-bit, 2=64-bit, rest undefined. */
+ uint32_t u3AddrSize : 3;
+ /** Memory/Register - Always cleared to 0 to indicate memory operand. */
+ uint32_t fIsRegOperand : 1;
+ /** Operand size; 0=16-bit, 1=32-bit, 2=64-bit, 3=unused. */
+ uint32_t uOperandSize : 2;
+ uint32_t u2Undef0 : 2;
+ /** The segment register (X86_SREG_XXX). */
+ uint32_t iSegReg : 3;
+ /** The index register (X86_GREG_XXX). */
+ uint32_t iIdxReg : 4;
+ /** Set if index register is invalid. */
+ uint32_t fIdxRegInvalid : 1;
+ /** The base register (X86_GREG_XXX). */
+ uint32_t iBaseReg : 4;
+ /** Set if base register is invalid. */
+ uint32_t fBaseRegInvalid : 1;
+ /** Register 2 (X86_GREG_XXX) or instruction identity. */
+ uint32_t iReg2 : 4;
+ } All;
+} VMXEXITINSTRINFO;
+AssertCompileSize(VMXEXITINSTRINFO, 4);
+/** Pointer to a VMX VM-exit instruction info. struct. */
+typedef VMXEXITINSTRINFO *PVMXEXITINSTRINFO;
+/** Pointer to a const VMX VM-exit instruction info. struct. */
+typedef const VMXEXITINSTRINFO *PCVMXEXITINSTRINFO;
+
+
+/** @name VM-entry failure reported in Exit qualification.
+ * See Intel spec. 26.7 "VM-entry failures during or after loading guest-state".
+ * @{
+ */
+/** No errors during VM-entry. */
+#define VMX_ENTRY_FAIL_QUAL_NO_ERROR (0)
+/** Not used. */
+#define VMX_ENTRY_FAIL_QUAL_NOT_USED (1)
+/** Error while loading PDPTEs. */
+#define VMX_ENTRY_FAIL_QUAL_PDPTE (2)
+/** NMI injection when blocking-by-STI is set. */
+#define VMX_ENTRY_FAIL_QUAL_NMI_INJECT (3)
+/** Invalid VMCS link pointer. */
+#define VMX_ENTRY_FAIL_QUAL_VMCS_LINK_PTR (4)
+/** @} */
+
+
+/** @name VMXMSRPM_XXX - VMX MSR-bitmap permissions.
+ * These are -not- specified by Intel but used internally by VirtualBox.
+ * @{ */
+/** Guest software reads of this MSR must not cause a VM-exit. */
+#define VMXMSRPM_ALLOW_RD RT_BIT(0)
+/** Guest software reads of this MSR must cause a VM-exit. */
+#define VMXMSRPM_EXIT_RD RT_BIT(1)
+/** Guest software writes to this MSR must not cause a VM-exit. */
+#define VMXMSRPM_ALLOW_WR RT_BIT(2)
+/** Guest software writes to this MSR must cause a VM-exit. */
+#define VMXMSRPM_EXIT_WR RT_BIT(3)
+/** Guest software reads or writes of this MSR must not cause a VM-exit. */
+#define VMXMSRPM_ALLOW_RD_WR (VMXMSRPM_ALLOW_RD | VMXMSRPM_ALLOW_WR)
+/** Guest software reads or writes of this MSR must cause a VM-exit. */
+#define VMXMSRPM_EXIT_RD_WR (VMXMSRPM_EXIT_RD | VMXMSRPM_EXIT_WR)
+/** Mask of valid MSR read permissions. */
+#define VMXMSRPM_RD_MASK (VMXMSRPM_ALLOW_RD | VMXMSRPM_EXIT_RD)
+/** Mask of valid MSR write permissions. */
+#define VMXMSRPM_WR_MASK (VMXMSRPM_ALLOW_WR | VMXMSRPM_EXIT_WR)
+/** Mask of valid MSR permissions. */
+#define VMXMSRPM_MASK (VMXMSRPM_RD_MASK | VMXMSRPM_WR_MASK)
+/** */
+/** Gets whether the MSR permission is valid or not. */
+#define VMXMSRPM_IS_FLAG_VALID(a_Msrpm) ( (a_Msrpm) != 0 \
+ && ((a_Msrpm) & ~VMXMSRPM_MASK) == 0 \
+ && ((a_Msrpm) & VMXMSRPM_RD_MASK) != VMXMSRPM_RD_MASK \
+ && ((a_Msrpm) & VMXMSRPM_WR_MASK) != VMXMSRPM_WR_MASK)
+/** @} */
+
+/**
+ * VMX MSR autoload/store slot.
+ * In accordance with the VT-x spec.
+ */
+typedef struct VMXAUTOMSR
+{
+ /** The MSR Id. */
+ uint32_t u32Msr;
+ /** Reserved (MBZ). */
+ uint32_t u32Reserved;
+ /** The MSR value. */
+ uint64_t u64Value;
+} VMXAUTOMSR;
+AssertCompileSize(VMXAUTOMSR, 16);
+/** Pointer to an MSR load/store element. */
+typedef VMXAUTOMSR *PVMXAUTOMSR;
+/** Pointer to a const MSR load/store element. */
+typedef const VMXAUTOMSR *PCVMXAUTOMSR;
+
+/** VMX auto load-store MSR (VMXAUTOMSR) offset mask. */
+#define VMX_AUTOMSR_OFFSET_MASK 0xf
+
+/**
+ * VMX tagged-TLB flush types.
+ */
+typedef enum
+{
+ VMXTLBFLUSHTYPE_EPT,
+ VMXTLBFLUSHTYPE_VPID,
+ VMXTLBFLUSHTYPE_EPT_VPID,
+ VMXTLBFLUSHTYPE_NONE
+} VMXTLBFLUSHTYPE;
+/** Pointer to a VMXTLBFLUSHTYPE enum. */
+typedef VMXTLBFLUSHTYPE *PVMXTLBFLUSHTYPE;
+/** Pointer to a const VMXTLBFLUSHTYPE enum. */
+typedef const VMXTLBFLUSHTYPE *PCVMXTLBFLUSHTYPE;
+
+/**
+ * VMX controls MSR.
+ * In accordance with the VT-x spec.
+ */
+typedef union
+{
+ struct
+ {
+ /** Bits set here -must- be set in the corresponding VM-execution controls. */
+ uint32_t allowed0;
+ /** Bits cleared here -must- be cleared in the corresponding VM-execution
+ * controls. */
+ uint32_t allowed1;
+ } n;
+ uint64_t u;
+} VMXCTLSMSR;
+AssertCompileSize(VMXCTLSMSR, 8);
+/** Pointer to a VMXCTLSMSR union. */
+typedef VMXCTLSMSR *PVMXCTLSMSR;
+/** Pointer to a const VMXCTLSMSR union. */
+typedef const VMXCTLSMSR *PCVMXCTLSMSR;
+
+/**
+ * VMX MSRs.
+ */
+typedef struct VMXMSRS
+{
+ /** Basic information. */
+ uint64_t u64Basic;
+ /** Pin-based VM-execution controls. */
+ VMXCTLSMSR PinCtls;
+ /** Processor-based VM-execution controls. */
+ VMXCTLSMSR ProcCtls;
+ /** Secondary processor-based VM-execution controls. */
+ VMXCTLSMSR ProcCtls2;
+ /** VM-exit controls. */
+ VMXCTLSMSR ExitCtls;
+ /** VM-entry controls. */
+ VMXCTLSMSR EntryCtls;
+ /** True pin-based VM-execution controls. */
+ VMXCTLSMSR TruePinCtls;
+ /** True processor-based VM-execution controls. */
+ VMXCTLSMSR TrueProcCtls;
+ /** True VM-entry controls. */
+ VMXCTLSMSR TrueEntryCtls;
+ /** True VM-exit controls. */
+ VMXCTLSMSR TrueExitCtls;
+ /** Miscellaneous data. */
+ uint64_t u64Misc;
+ /** CR0 fixed-0 - bits set here must be set in VMX operation. */
+ uint64_t u64Cr0Fixed0;
+ /** CR0 fixed-1 - bits clear here must be clear in VMX operation. */
+ uint64_t u64Cr0Fixed1;
+ /** CR4 fixed-0 - bits set here must be set in VMX operation. */
+ uint64_t u64Cr4Fixed0;
+ /** CR4 fixed-1 - bits clear here must be clear in VMX operation. */
+ uint64_t u64Cr4Fixed1;
+ /** VMCS enumeration. */
+ uint64_t u64VmcsEnum;
+ /** VM Functions. */
+ uint64_t u64VmFunc;
+ /** EPT, VPID capabilities. */
+ uint64_t u64EptVpidCaps;
+ /** Tertiary processor-based VM-execution controls. */
+ uint64_t u64ProcCtls3;
+ /** Secondary VM-exit controls. */
+ uint64_t u64ExitCtls2;
+ /** Reserved for future. */
+ uint64_t a_u64Reserved[8];
+} VMXMSRS;
+AssertCompileSizeAlignment(VMXMSRS, 8);
+AssertCompileSize(VMXMSRS, 224);
+/** Pointer to a VMXMSRS struct. */
+typedef VMXMSRS *PVMXMSRS;
+/** Pointer to a const VMXMSRS struct. */
+typedef const VMXMSRS *PCVMXMSRS;
+
+
+/**
+ * LBR MSRs.
+ */
+typedef struct LBRMSRS
+{
+ /** List of LastBranch-From-IP MSRs. */
+ uint64_t au64BranchFromIpMsr[32];
+ /** List of LastBranch-To-IP MSRs. */
+ uint64_t au64BranchToIpMsr[32];
+ /** The MSR containing the index to the most recent branch record. */
+ uint64_t uBranchTosMsr;
+} LBRMSRS;
+AssertCompileSizeAlignment(LBRMSRS, 8);
+/** Pointer to a VMXMSRS struct. */
+typedef LBRMSRS *PLBRMSRS;
+/** Pointer to a const VMXMSRS struct. */
+typedef const LBRMSRS *PCLBRMSRS;
+
+
+/** @name VMX Basic Exit Reasons.
+ * In accordance with the VT-x spec.
+ * Update g_aVMExitHandlers if new VM-exit reasons are added.
+ * @{
+ */
+/** Invalid exit code */
+#define VMX_EXIT_INVALID (-1)
+/** Exception or non-maskable interrupt (NMI). */
+#define VMX_EXIT_XCPT_OR_NMI 0
+/** External interrupt. */
+#define VMX_EXIT_EXT_INT 1
+/** Triple fault. */
+#define VMX_EXIT_TRIPLE_FAULT 2
+/** INIT signal. */
+#define VMX_EXIT_INIT_SIGNAL 3
+/** Start-up IPI (SIPI). */
+#define VMX_EXIT_SIPI 4
+/** I/O system-management interrupt (SMI). */
+#define VMX_EXIT_IO_SMI 5
+/** Other SMI. */
+#define VMX_EXIT_SMI 6
+/** Interrupt window exiting. */
+#define VMX_EXIT_INT_WINDOW 7
+/** NMI window exiting. */
+#define VMX_EXIT_NMI_WINDOW 8
+/** Task switch. */
+#define VMX_EXIT_TASK_SWITCH 9
+/** CPUID. */
+#define VMX_EXIT_CPUID 10
+/** GETSEC. */
+#define VMX_EXIT_GETSEC 11
+/** HLT. */
+#define VMX_EXIT_HLT 12
+/** INVD. */
+#define VMX_EXIT_INVD 13
+/** INVLPG. */
+#define VMX_EXIT_INVLPG 14
+/** RDPMC. */
+#define VMX_EXIT_RDPMC 15
+/** RDTSC. */
+#define VMX_EXIT_RDTSC 16
+/** RSM in SMM. */
+#define VMX_EXIT_RSM 17
+/** VMCALL. */
+#define VMX_EXIT_VMCALL 18
+/** VMCLEAR. */
+#define VMX_EXIT_VMCLEAR 19
+/** VMLAUNCH. */
+#define VMX_EXIT_VMLAUNCH 20
+/** VMPTRLD. */
+#define VMX_EXIT_VMPTRLD 21
+/** VMPTRST. */
+#define VMX_EXIT_VMPTRST 22
+/** VMREAD. */
+#define VMX_EXIT_VMREAD 23
+/** VMRESUME. */
+#define VMX_EXIT_VMRESUME 24
+/** VMWRITE. */
+#define VMX_EXIT_VMWRITE 25
+/** VMXOFF. */
+#define VMX_EXIT_VMXOFF 26
+/** VMXON. */
+#define VMX_EXIT_VMXON 27
+/** Control-register accesses. */
+#define VMX_EXIT_MOV_CRX 28
+/** Debug-register accesses. */
+#define VMX_EXIT_MOV_DRX 29
+/** I/O instruction. */
+#define VMX_EXIT_IO_INSTR 30
+/** RDMSR. */
+#define VMX_EXIT_RDMSR 31
+/** WRMSR. */
+#define VMX_EXIT_WRMSR 32
+/** VM-entry failure due to invalid guest state. */
+#define VMX_EXIT_ERR_INVALID_GUEST_STATE 33
+/** VM-entry failure due to MSR loading. */
+#define VMX_EXIT_ERR_MSR_LOAD 34
+/** MWAIT. */
+#define VMX_EXIT_MWAIT 36
+/** VM-exit due to monitor trap flag. */
+#define VMX_EXIT_MTF 37
+/** MONITOR. */
+#define VMX_EXIT_MONITOR 39
+/** PAUSE. */
+#define VMX_EXIT_PAUSE 40
+/** VM-entry failure due to machine-check. */
+#define VMX_EXIT_ERR_MACHINE_CHECK 41
+/** TPR below threshold. Guest software executed MOV to CR8. */
+#define VMX_EXIT_TPR_BELOW_THRESHOLD 43
+/** VM-exit due to guest accessing physical address in the APIC-access page. */
+#define VMX_EXIT_APIC_ACCESS 44
+/** VM-exit due to EOI virtualization. */
+#define VMX_EXIT_VIRTUALIZED_EOI 45
+/** Access to GDTR/IDTR using LGDT, LIDT, SGDT or SIDT. */
+#define VMX_EXIT_GDTR_IDTR_ACCESS 46
+/** Access to LDTR/TR due to LLDT, LTR, SLDT, or STR. */
+#define VMX_EXIT_LDTR_TR_ACCESS 47
+/** EPT violation. */
+#define VMX_EXIT_EPT_VIOLATION 48
+/** EPT misconfiguration. */
+#define VMX_EXIT_EPT_MISCONFIG 49
+/** INVEPT. */
+#define VMX_EXIT_INVEPT 50
+/** RDTSCP. */
+#define VMX_EXIT_RDTSCP 51
+/** VMX-preemption timer expired. */
+#define VMX_EXIT_PREEMPT_TIMER 52
+/** INVVPID. */
+#define VMX_EXIT_INVVPID 53
+/** WBINVD. */
+#define VMX_EXIT_WBINVD 54
+/** XSETBV. */
+#define VMX_EXIT_XSETBV 55
+/** Guest completed write to virtual-APIC. */
+#define VMX_EXIT_APIC_WRITE 56
+/** RDRAND. */
+#define VMX_EXIT_RDRAND 57
+/** INVPCID. */
+#define VMX_EXIT_INVPCID 58
+/** VMFUNC. */
+#define VMX_EXIT_VMFUNC 59
+/** ENCLS. */
+#define VMX_EXIT_ENCLS 60
+/** RDSEED. */
+#define VMX_EXIT_RDSEED 61
+/** Page-modification log full. */
+#define VMX_EXIT_PML_FULL 62
+/** XSAVES. */
+#define VMX_EXIT_XSAVES 63
+/** XRSTORS. */
+#define VMX_EXIT_XRSTORS 64
+/** SPP-related event (SPP miss or misconfiguration). */
+#define VMX_EXIT_SPP_EVENT 66
+/* UMWAIT. */
+#define VMX_EXIT_UMWAIT 67
+/** TPAUSE. */
+#define VMX_EXIT_TPAUSE 68
+/** LOADIWKEY. */
+#define VMX_EXIT_LOADIWKEY 69
+/** The maximum VM-exit value (inclusive). */
+#define VMX_EXIT_MAX (VMX_EXIT_LOADIWKEY)
+/** @} */
+
+
+/** @name VM Instruction Errors.
+ * In accordance with the VT-x spec.
+ * See Intel spec. "30.4 VM Instruction Error Numbers"
+ * @{
+ */
+typedef enum
+{
+ /** VMCALL executed in VMX root operation. */
+ VMXINSTRERR_VMCALL_VMXROOTMODE = 1,
+ /** VMCLEAR with invalid physical address. */
+ VMXINSTRERR_VMCLEAR_INVALID_PHYSADDR = 2,
+ /** VMCLEAR with VMXON pointer. */
+ VMXINSTRERR_VMCLEAR_VMXON_PTR = 3,
+ /** VMLAUNCH with non-clear VMCS. */
+ VMXINSTRERR_VMLAUNCH_NON_CLEAR_VMCS = 4,
+ /** VMRESUME with non-launched VMCS. */
+ VMXINSTRERR_VMRESUME_NON_LAUNCHED_VMCS = 5,
+ /** VMRESUME after VMXOFF (VMXOFF and VMXON between VMLAUNCH and VMRESUME). */
+ VMXINSTRERR_VMRESUME_AFTER_VMXOFF = 6,
+ /** VM-entry with invalid control field(s). */
+ VMXINSTRERR_VMENTRY_INVALID_CTLS = 7,
+ /** VM-entry with invalid host-state field(s). */
+ VMXINSTRERR_VMENTRY_INVALID_HOST_STATE = 8,
+ /** VMPTRLD with invalid physical address. */
+ VMXINSTRERR_VMPTRLD_INVALID_PHYSADDR = 9,
+ /** VMPTRLD with VMXON pointer. */
+ VMXINSTRERR_VMPTRLD_VMXON_PTR = 10,
+ /** VMPTRLD with incorrect VMCS revision identifier. */
+ VMXINSTRERR_VMPTRLD_INCORRECT_VMCS_REV = 11,
+ /** VMREAD from unsupported VMCS component. */
+ VMXINSTRERR_VMREAD_INVALID_COMPONENT = 12,
+ /** VMWRITE to unsupported VMCS component. */
+ VMXINSTRERR_VMWRITE_INVALID_COMPONENT = 12,
+ /** VMWRITE to read-only VMCS component. */
+ VMXINSTRERR_VMWRITE_RO_COMPONENT = 13,
+ /** VMXON executed in VMX root operation. */
+ VMXINSTRERR_VMXON_IN_VMXROOTMODE = 15,
+ /** VM-entry with invalid executive-VMCS pointer. */
+ VMXINSTRERR_VMENTRY_EXEC_VMCS_INVALID_PTR = 16,
+ /** VM-entry with non-launched executive VMCS. */
+ VMXINSTRERR_VMENTRY_EXEC_VMCS_NON_LAUNCHED = 17,
+ /** VM-entry with executive-VMCS pointer not VMXON pointer. */
+ VMXINSTRERR_VMENTRY_EXEC_VMCS_PTR = 18,
+ /** VMCALL with non-clear VMCS. */
+ VMXINSTRERR_VMCALL_NON_CLEAR_VMCS = 19,
+ /** VMCALL with invalid VM-exit control fields. */
+ VMXINSTRERR_VMCALL_INVALID_EXITCTLS = 20,
+ /** VMCALL with incorrect MSEG revision identifier. */
+ VMXINSTRERR_VMCALL_INVALID_MSEG_ID = 22,
+ /** VMXOFF under dual-monitor treatment of SMIs and SMM. */
+ VMXINSTRERR_VMXOFF_DUAL_MON = 23,
+ /** VMCALL with invalid SMM-monitor features. */
+ VMXINSTRERR_VMCALL_INVALID_SMMCTLS = 24,
+ /** VM-entry with invalid VM-execution control fields in executive VMCS. */
+ VMXINSTRERR_VMENTRY_EXEC_VMCS_INVALID_CTLS = 25,
+ /** VM-entry with events blocked by MOV SS. */
+ VMXINSTRERR_VMENTRY_BLOCK_MOVSS = 26,
+ /** Invalid operand to INVEPT/INVVPID. */
+ VMXINSTRERR_INVEPT_INVVPID_INVALID_OPERAND = 28
+} VMXINSTRERR;
+/** @} */
+
+
+/** @name VMX abort reasons.
+ * In accordance with the VT-x spec.
+ * See Intel spec. "27.7 VMX Aborts".
+ * Update HMGetVmxAbortDesc() if new reasons are added.
+ * @{
+ */
+typedef enum
+{
+ /** None - don't use this / uninitialized value. */
+ VMXABORT_NONE = 0,
+ /** VMX abort caused during saving of guest MSRs. */
+ VMXABORT_SAVE_GUEST_MSRS = 1,
+ /** VMX abort caused during host PDPTE checks. */
+ VMXBOART_HOST_PDPTE = 2,
+ /** VMX abort caused due to current VMCS being corrupted. */
+ VMXABORT_CURRENT_VMCS_CORRUPT = 3,
+ /** VMX abort caused during loading of host MSRs. */
+ VMXABORT_LOAD_HOST_MSR = 4,
+ /** VMX abort caused due to a machine-check exception during VM-exit. */
+ VMXABORT_MACHINE_CHECK_XCPT = 5,
+ /** VMX abort caused due to invalid return from long mode. */
+ VMXABORT_HOST_NOT_IN_LONG_MODE = 6,
+ /* Type size hack. */
+ VMXABORT_32BIT_HACK = 0x7fffffff
+} VMXABORT;
+AssertCompileSize(VMXABORT, 4);
+/** @} */
+
+
+/** @name VMX MSR - Basic VMX information.
+ * @{
+ */
+/** VMCS (and related regions) memory type - Uncacheable. */
+#define VMX_BASIC_MEM_TYPE_UC 0
+/** VMCS (and related regions) memory type - Write back. */
+#define VMX_BASIC_MEM_TYPE_WB 6
+/** Width of physical addresses used for VMCS and associated memory regions
+ * (1=32-bit, 0=processor's physical address width). */
+#define VMX_BASIC_PHYSADDR_WIDTH_32BIT RT_BIT_64(48)
+
+/** Bit fields for MSR_IA32_VMX_BASIC. */
+/** VMCS revision identifier used by the processor. */
+#define VMX_BF_BASIC_VMCS_ID_SHIFT 0
+#define VMX_BF_BASIC_VMCS_ID_MASK UINT64_C(0x000000007fffffff)
+/** Bit 31 is reserved and RAZ. */
+#define VMX_BF_BASIC_RSVD_32_SHIFT 31
+#define VMX_BF_BASIC_RSVD_32_MASK UINT64_C(0x0000000080000000)
+/** VMCS size in bytes. */
+#define VMX_BF_BASIC_VMCS_SIZE_SHIFT 32
+#define VMX_BF_BASIC_VMCS_SIZE_MASK UINT64_C(0x00001fff00000000)
+/** Bits 45:47 are reserved. */
+#define VMX_BF_BASIC_RSVD_45_47_SHIFT 45
+#define VMX_BF_BASIC_RSVD_45_47_MASK UINT64_C(0x0000e00000000000)
+/** Width of physical addresses used for the VMCS and associated memory regions
+ * (always 0 on CPUs that support Intel 64 architecture). */
+#define VMX_BF_BASIC_PHYSADDR_WIDTH_SHIFT 48
+#define VMX_BF_BASIC_PHYSADDR_WIDTH_MASK UINT64_C(0x0001000000000000)
+/** Dual-monitor treatment of SMI and SMM supported. */
+#define VMX_BF_BASIC_DUAL_MON_SHIFT 49
+#define VMX_BF_BASIC_DUAL_MON_MASK UINT64_C(0x0002000000000000)
+/** Memory type that must be used for the VMCS and associated memory regions. */
+#define VMX_BF_BASIC_VMCS_MEM_TYPE_SHIFT 50
+#define VMX_BF_BASIC_VMCS_MEM_TYPE_MASK UINT64_C(0x003c000000000000)
+/** VM-exit instruction information for INS/OUTS. */
+#define VMX_BF_BASIC_VMCS_INS_OUTS_SHIFT 54
+#define VMX_BF_BASIC_VMCS_INS_OUTS_MASK UINT64_C(0x0040000000000000)
+/** Whether 'true' VMX controls MSRs are supported for handling of default1 class
+ * bits in VMX control MSRs. */
+#define VMX_BF_BASIC_TRUE_CTLS_SHIFT 55
+#define VMX_BF_BASIC_TRUE_CTLS_MASK UINT64_C(0x0080000000000000)
+/** Whether VM-entry can delivery error code for all hardware exception vectors. */
+#define VMX_BF_BASIC_XCPT_ERRCODE_SHIFT 56
+#define VMX_BF_BASIC_XCPT_ERRCODE_MASK UINT64_C(0x0100000000000000)
+/** Bits 57:63 are reserved and RAZ. */
+#define VMX_BF_BASIC_RSVD_56_63_SHIFT 57
+#define VMX_BF_BASIC_RSVD_56_63_MASK UINT64_C(0xfe00000000000000)
+RT_BF_ASSERT_COMPILE_CHECKS(VMX_BF_BASIC_, UINT64_C(0), UINT64_MAX,
+ (VMCS_ID, RSVD_32, VMCS_SIZE, RSVD_45_47, PHYSADDR_WIDTH, DUAL_MON, VMCS_MEM_TYPE,
+ VMCS_INS_OUTS, TRUE_CTLS, XCPT_ERRCODE, RSVD_56_63));
+/** @} */
+
+
+/** @name VMX MSR - Miscellaneous data.
+ * @{
+ */
+/** Whether VM-exit stores EFER.LMA into the "IA32e mode guest" field. */
+#define VMX_MISC_EXIT_SAVE_EFER_LMA RT_BIT(5)
+/** Whether Intel PT is supported in VMX operation. */
+#define VMX_MISC_INTEL_PT RT_BIT(14)
+/** Whether VMWRITE to any valid VMCS field incl. read-only fields, otherwise
+ * VMWRITE cannot modify read-only VM-exit information fields. */
+#define VMX_MISC_VMWRITE_ALL RT_BIT(29)
+/** Whether VM-entry can inject software interrupts, INT1 (ICEBP) with 0-length
+ * instructions. */
+#define VMX_MISC_ENTRY_INJECT_SOFT_INT RT_BIT(30)
+/** Maximum number of MSRs in the auto-load/store MSR areas, (n+1) * 512. */
+#define VMX_MISC_MAX_MSRS(a_MiscMsr) (512 * (RT_BF_GET((a_MiscMsr), VMX_BF_MISC_MAX_MSRS) + 1))
+/** Maximum CR3-target count supported by the CPU. */
+#define VMX_MISC_CR3_TARGET_COUNT(a_MiscMsr) (((a) >> 16) & 0xff)
+
+/** Bit fields for MSR_IA32_VMX_MISC. */
+/** Relationship between the preemption timer and tsc. */
+#define VMX_BF_MISC_PREEMPT_TIMER_TSC_SHIFT 0
+#define VMX_BF_MISC_PREEMPT_TIMER_TSC_MASK UINT64_C(0x000000000000001f)
+/** Whether VM-exit stores EFER.LMA into the "IA32e mode guest" field. */
+#define VMX_BF_MISC_EXIT_SAVE_EFER_LMA_SHIFT 5
+#define VMX_BF_MISC_EXIT_SAVE_EFER_LMA_MASK UINT64_C(0x0000000000000020)
+/** Activity states supported by the implementation. */
+#define VMX_BF_MISC_ACTIVITY_STATES_SHIFT 6
+#define VMX_BF_MISC_ACTIVITY_STATES_MASK UINT64_C(0x00000000000001c0)
+/** Bits 9:13 is reserved and RAZ. */
+#define VMX_BF_MISC_RSVD_9_13_SHIFT 9
+#define VMX_BF_MISC_RSVD_9_13_MASK UINT64_C(0x0000000000003e00)
+/** Whether Intel PT (Processor Trace) can be used in VMX operation. */
+#define VMX_BF_MISC_INTEL_PT_SHIFT 14
+#define VMX_BF_MISC_INTEL_PT_MASK UINT64_C(0x0000000000004000)
+/** Whether RDMSR can be used to read IA32_SMBASE MSR in SMM. */
+#define VMX_BF_MISC_SMM_READ_SMBASE_MSR_SHIFT 15
+#define VMX_BF_MISC_SMM_READ_SMBASE_MSR_MASK UINT64_C(0x0000000000008000)
+/** Number of CR3 target values supported by the processor. (0-256) */
+#define VMX_BF_MISC_CR3_TARGET_SHIFT 16
+#define VMX_BF_MISC_CR3_TARGET_MASK UINT64_C(0x0000000001ff0000)
+/** Maximum number of MSRs in the VMCS. */
+#define VMX_BF_MISC_MAX_MSRS_SHIFT 25
+#define VMX_BF_MISC_MAX_MSRS_MASK UINT64_C(0x000000000e000000)
+/** Whether IA32_SMM_MONITOR_CTL MSR can be modified to allow VMXOFF to block
+ * SMIs. */
+#define VMX_BF_MISC_VMXOFF_BLOCK_SMI_SHIFT 28
+#define VMX_BF_MISC_VMXOFF_BLOCK_SMI_MASK UINT64_C(0x0000000010000000)
+/** Whether VMWRITE to any valid VMCS field incl. read-only fields, otherwise
+ * VMWRITE cannot modify read-only VM-exit information fields. */
+#define VMX_BF_MISC_VMWRITE_ALL_SHIFT 29
+#define VMX_BF_MISC_VMWRITE_ALL_MASK UINT64_C(0x0000000020000000)
+/** Whether VM-entry can inject software interrupts, INT1 (ICEBP) with 0-length
+ * instructions. */
+#define VMX_BF_MISC_ENTRY_INJECT_SOFT_INT_SHIFT 30
+#define VMX_BF_MISC_ENTRY_INJECT_SOFT_INT_MASK UINT64_C(0x0000000040000000)
+/** Bit 31 is reserved and RAZ. */
+#define VMX_BF_MISC_RSVD_31_SHIFT 31
+#define VMX_BF_MISC_RSVD_31_MASK UINT64_C(0x0000000080000000)
+/** 32-bit MSEG revision ID used by the processor. */
+#define VMX_BF_MISC_MSEG_ID_SHIFT 32
+#define VMX_BF_MISC_MSEG_ID_MASK UINT64_C(0xffffffff00000000)
+RT_BF_ASSERT_COMPILE_CHECKS(VMX_BF_MISC_, UINT64_C(0), UINT64_MAX,
+ (PREEMPT_TIMER_TSC, EXIT_SAVE_EFER_LMA, ACTIVITY_STATES, RSVD_9_13, INTEL_PT, SMM_READ_SMBASE_MSR,
+ CR3_TARGET, MAX_MSRS, VMXOFF_BLOCK_SMI, VMWRITE_ALL, ENTRY_INJECT_SOFT_INT, RSVD_31, MSEG_ID));
+/** @} */
+
+/** @name VMX MSR - VMCS enumeration.
+ * Bit fields for MSR_IA32_VMX_VMCS_ENUM.
+ * @{
+ */
+/** Bit 0 is reserved and RAZ. */
+#define VMX_BF_VMCS_ENUM_RSVD_0_SHIFT 0
+#define VMX_BF_VMCS_ENUM_RSVD_0_MASK UINT64_C(0x0000000000000001)
+/** Highest index value used in VMCS field encoding. */
+#define VMX_BF_VMCS_ENUM_HIGHEST_IDX_SHIFT 1
+#define VMX_BF_VMCS_ENUM_HIGHEST_IDX_MASK UINT64_C(0x00000000000003fe)
+/** Bit 10:63 is reserved and RAZ. */
+#define VMX_BF_VMCS_ENUM_RSVD_10_63_SHIFT 10
+#define VMX_BF_VMCS_ENUM_RSVD_10_63_MASK UINT64_C(0xfffffffffffffc00)
+RT_BF_ASSERT_COMPILE_CHECKS(VMX_BF_VMCS_ENUM_, UINT64_C(0), UINT64_MAX,
+ (RSVD_0, HIGHEST_IDX, RSVD_10_63));
+/** @} */
+
+
+/** @name VMX MSR - VM Functions.
+ * Bit fields for MSR_IA32_VMX_VMFUNC.
+ * @{
+ */
+/** EPTP-switching function changes the value of the EPTP to one chosen from the EPTP list. */
+#define VMX_BF_VMFUNC_EPTP_SWITCHING_SHIFT 0
+#define VMX_BF_VMFUNC_EPTP_SWITCHING_MASK UINT64_C(0x0000000000000001)
+/** Bits 1:63 are reserved and RAZ. */
+#define VMX_BF_VMFUNC_RSVD_1_63_SHIFT 1
+#define VMX_BF_VMFUNC_RSVD_1_63_MASK UINT64_C(0xfffffffffffffffe)
+RT_BF_ASSERT_COMPILE_CHECKS(VMX_BF_VMFUNC_, UINT64_C(0), UINT64_MAX,
+ (EPTP_SWITCHING, RSVD_1_63));
+/** @} */
+
+
+/** @name VMX MSR - EPT/VPID capabilities.
+ * @{
+ */
+/** Supports execute-only translations by EPT. */
+#define MSR_IA32_VMX_EPT_VPID_CAP_RWX_X_ONLY RT_BIT_64(0)
+/** Supports page-walk length of 4. */
+#define MSR_IA32_VMX_EPT_VPID_CAP_PAGE_WALK_LENGTH_4 RT_BIT_64(6)
+/** Supports page-walk length of 5. */
+#define MSR_IA32_VMX_EPT_VPID_CAP_PAGE_WALK_LENGTH_5 RT_BIT_64(7)
+/** Supports EPT paging-structure memory type to be uncacheable. */
+#define MSR_IA32_VMX_EPT_VPID_CAP_MEMTYPE_UC RT_BIT_64(8)
+/** Supports EPT paging structure memory type to be write-back. */
+#define MSR_IA32_VMX_EPT_VPID_CAP_MEMTYPE_WB RT_BIT_64(14)
+/** Supports EPT PDE to map a 2 MB page. */
+#define MSR_IA32_VMX_EPT_VPID_CAP_PDE_2M RT_BIT_64(16)
+/** Supports EPT PDPTE to map a 1 GB page. */
+#define MSR_IA32_VMX_EPT_VPID_CAP_PDPTE_1G RT_BIT_64(17)
+/** Supports INVEPT instruction. */
+#define MSR_IA32_VMX_EPT_VPID_CAP_INVEPT RT_BIT_64(20)
+/** Supports accessed and dirty flags for EPT. */
+#define MSR_IA32_VMX_EPT_VPID_CAP_ACCESS_DIRTY RT_BIT_64(21)
+/** Supports advanced VM-exit info. for EPT violations. */
+#define MSR_IA32_VMX_EPT_VPID_CAP_ADVEXITINFO_EPT_VIOLATION RT_BIT_64(22)
+/** Supports supervisor shadow-stack control. */
+#define MSR_IA32_VMX_EPT_VPID_CAP_SUPER_SHW_STACK RT_BIT_64(23)
+/** Supports single-context INVEPT type. */
+#define MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_SINGLE_CONTEXT RT_BIT_64(25)
+/** Supports all-context INVEPT type. */
+#define MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_ALL_CONTEXTS RT_BIT_64(26)
+/** Supports INVVPID instruction. */
+#define MSR_IA32_VMX_EPT_VPID_CAP_INVVPID RT_BIT_64(32)
+/** Supports individual-address INVVPID type. */
+#define MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_INDIV_ADDR RT_BIT_64(40)
+/** Supports single-context INVVPID type. */
+#define MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT RT_BIT_64(41)
+/** Supports all-context INVVPID type. */
+#define MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_ALL_CONTEXTS RT_BIT_64(42)
+/** Supports singe-context-retaining-globals INVVPID type. */
+#define MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT_RETAIN_GLOBALS RT_BIT_64(43)
+
+/** Bit fields for MSR_IA32_VMX_EPT_VPID_CAP. */
+#define VMX_BF_EPT_VPID_CAP_EXEC_ONLY_SHIFT 0
+#define VMX_BF_EPT_VPID_CAP_EXEC_ONLY_MASK UINT64_C(0x0000000000000001)
+#define VMX_BF_EPT_VPID_CAP_RSVD_1_5_SHIFT 1
+#define VMX_BF_EPT_VPID_CAP_RSVD_1_5_MASK UINT64_C(0x000000000000003e)
+#define VMX_BF_EPT_VPID_CAP_PAGE_WALK_LENGTH_4_SHIFT 6
+#define VMX_BF_EPT_VPID_CAP_PAGE_WALK_LENGTH_4_MASK UINT64_C(0x0000000000000040)
+#define VMX_BF_EPT_VPID_CAP_RSVD_7_SHIFT 7
+#define VMX_BF_EPT_VPID_CAP_RSVD_7_MASK UINT64_C(0x0000000000000080)
+#define VMX_BF_EPT_VPID_CAP_MEMTYPE_UC_SHIFT 8
+#define VMX_BF_EPT_VPID_CAP_MEMTYPE_UC_MASK UINT64_C(0x0000000000000100)
+#define VMX_BF_EPT_VPID_CAP_RSVD_9_13_SHIFT 9
+#define VMX_BF_EPT_VPID_CAP_RSVD_9_13_MASK UINT64_C(0x0000000000003e00)
+#define VMX_BF_EPT_VPID_CAP_MEMTYPE_WB_SHIFT 14
+#define VMX_BF_EPT_VPID_CAP_MEMTYPE_WB_MASK UINT64_C(0x0000000000004000)
+#define VMX_BF_EPT_VPID_CAP_RSVD_15_SHIFT 15
+#define VMX_BF_EPT_VPID_CAP_RSVD_15_MASK UINT64_C(0x0000000000008000)
+#define VMX_BF_EPT_VPID_CAP_PDE_2M_SHIFT 16
+#define VMX_BF_EPT_VPID_CAP_PDE_2M_MASK UINT64_C(0x0000000000010000)
+#define VMX_BF_EPT_VPID_CAP_PDPTE_1G_SHIFT 17
+#define VMX_BF_EPT_VPID_CAP_PDPTE_1G_MASK UINT64_C(0x0000000000020000)
+#define VMX_BF_EPT_VPID_CAP_RSVD_18_19_SHIFT 18
+#define VMX_BF_EPT_VPID_CAP_RSVD_18_19_MASK UINT64_C(0x00000000000c0000)
+#define VMX_BF_EPT_VPID_CAP_INVEPT_SHIFT 20
+#define VMX_BF_EPT_VPID_CAP_INVEPT_MASK UINT64_C(0x0000000000100000)
+#define VMX_BF_EPT_VPID_CAP_ACCESS_DIRTY_SHIFT 21
+#define VMX_BF_EPT_VPID_CAP_ACCESS_DIRTY_MASK UINT64_C(0x0000000000200000)
+#define VMX_BF_EPT_VPID_CAP_ADVEXITINFO_EPT_VIOLATION_SHIFT 22
+#define VMX_BF_EPT_VPID_CAP_ADVEXITINFO_EPT_VIOLATION_MASK UINT64_C(0x0000000000400000)
+#define VMX_BF_EPT_VPID_CAP_SUPER_SHW_STACK_SHIFT 23
+#define VMX_BF_EPT_VPID_CAP_SUPER_SHW_STACK_MASK UINT64_C(0x0000000000800000)
+#define VMX_BF_EPT_VPID_CAP_RSVD_24_SHIFT 24
+#define VMX_BF_EPT_VPID_CAP_RSVD_24_MASK UINT64_C(0x0000000001000000)
+#define VMX_BF_EPT_VPID_CAP_INVEPT_SINGLE_CTX_SHIFT 25
+#define VMX_BF_EPT_VPID_CAP_INVEPT_SINGLE_CTX_MASK UINT64_C(0x0000000002000000)
+#define VMX_BF_EPT_VPID_CAP_INVEPT_ALL_CTX_SHIFT 26
+#define VMX_BF_EPT_VPID_CAP_INVEPT_ALL_CTX_MASK UINT64_C(0x0000000004000000)
+#define VMX_BF_EPT_VPID_CAP_RSVD_27_31_SHIFT 27
+#define VMX_BF_EPT_VPID_CAP_RSVD_27_31_MASK UINT64_C(0x00000000f8000000)
+#define VMX_BF_EPT_VPID_CAP_INVVPID_SHIFT 32
+#define VMX_BF_EPT_VPID_CAP_INVVPID_MASK UINT64_C(0x0000000100000000)
+#define VMX_BF_EPT_VPID_CAP_RSVD_33_39_SHIFT 33
+#define VMX_BF_EPT_VPID_CAP_RSVD_33_39_MASK UINT64_C(0x000000fe00000000)
+#define VMX_BF_EPT_VPID_CAP_INVVPID_INDIV_ADDR_SHIFT 40
+#define VMX_BF_EPT_VPID_CAP_INVVPID_INDIV_ADDR_MASK UINT64_C(0x0000010000000000)
+#define VMX_BF_EPT_VPID_CAP_INVVPID_SINGLE_CTX_SHIFT 41
+#define VMX_BF_EPT_VPID_CAP_INVVPID_SINGLE_CTX_MASK UINT64_C(0x0000020000000000)
+#define VMX_BF_EPT_VPID_CAP_INVVPID_ALL_CTX_SHIFT 42
+#define VMX_BF_EPT_VPID_CAP_INVVPID_ALL_CTX_MASK UINT64_C(0x0000040000000000)
+#define VMX_BF_EPT_VPID_CAP_INVVPID_SINGLE_CTX_RETAIN_GLOBALS_SHIFT 43
+#define VMX_BF_EPT_VPID_CAP_INVVPID_SINGLE_CTX_RETAIN_GLOBALS_MASK UINT64_C(0x0000080000000000)
+#define VMX_BF_EPT_VPID_CAP_RSVD_44_63_SHIFT 44
+#define VMX_BF_EPT_VPID_CAP_RSVD_44_63_MASK UINT64_C(0xfffff00000000000)
+RT_BF_ASSERT_COMPILE_CHECKS(VMX_BF_EPT_VPID_CAP_, UINT64_C(0), UINT64_MAX,
+ (EXEC_ONLY, RSVD_1_5, PAGE_WALK_LENGTH_4, RSVD_7, MEMTYPE_UC, RSVD_9_13, MEMTYPE_WB, RSVD_15, PDE_2M,
+ PDPTE_1G, RSVD_18_19, INVEPT, ACCESS_DIRTY, ADVEXITINFO_EPT_VIOLATION, SUPER_SHW_STACK, RSVD_24,
+ INVEPT_SINGLE_CTX, INVEPT_ALL_CTX, RSVD_27_31, INVVPID, RSVD_33_39, INVVPID_INDIV_ADDR,
+ INVVPID_SINGLE_CTX, INVVPID_ALL_CTX, INVVPID_SINGLE_CTX_RETAIN_GLOBALS, RSVD_44_63));
+/** @} */
+
+
+/** @name Extended Page Table Pointer (EPTP)
+ * In accordance with the VT-x spec.
+ * See Intel spec. 23.6.11 "Extended-Page-Table Pointer (EPTP)".
+ * @{
+ */
+/** EPTP memory type: Uncachable. */
+#define VMX_EPTP_MEMTYPE_UC 0
+/** EPTP memory type: Write Back. */
+#define VMX_EPTP_MEMTYPE_WB 6
+/** Page-walk length for PML4 (4-level paging). */
+#define VMX_EPTP_PAGE_WALK_LENGTH_4 3
+
+/** Bit fields for EPTP. */
+#define VMX_BF_EPTP_MEMTYPE_SHIFT 0
+#define VMX_BF_EPTP_MEMTYPE_MASK UINT64_C(0x0000000000000007)
+#define VMX_BF_EPTP_PAGE_WALK_LENGTH_SHIFT 3
+#define VMX_BF_EPTP_PAGE_WALK_LENGTH_MASK UINT64_C(0x0000000000000038)
+#define VMX_BF_EPTP_ACCESS_DIRTY_SHIFT 6
+#define VMX_BF_EPTP_ACCESS_DIRTY_MASK UINT64_C(0x0000000000000040)
+#define VMX_BF_EPTP_SUPER_SHW_STACK_SHIFT 7
+#define VMX_BF_EPTP_SUPER_SHW_STACK_MASK UINT64_C(0x0000000000000080)
+#define VMX_BF_EPTP_RSVD_8_11_SHIFT 8
+#define VMX_BF_EPTP_RSVD_8_11_MASK UINT64_C(0x0000000000000f00)
+#define VMX_BF_EPTP_PML4_TABLE_ADDR_SHIFT 12
+#define VMX_BF_EPTP_PML4_TABLE_ADDR_MASK UINT64_C(0xfffffffffffff000)
+RT_BF_ASSERT_COMPILE_CHECKS(VMX_BF_EPTP_, UINT64_C(0), UINT64_MAX,
+ (MEMTYPE, PAGE_WALK_LENGTH, ACCESS_DIRTY, SUPER_SHW_STACK, RSVD_8_11, PML4_TABLE_ADDR));
+
+/* Mask of valid EPTP bits sans physically non-addressable bits. */
+#define VMX_EPTP_VALID_MASK ( VMX_BF_EPTP_MEMTYPE_MASK \
+ | VMX_BF_EPTP_PAGE_WALK_LENGTH_MASK \
+ | VMX_BF_EPTP_ACCESS_DIRTY_MASK \
+ | VMX_BF_EPTP_SUPER_SHW_STACK_MASK \
+ | VMX_BF_EPTP_PML4_TABLE_ADDR_MASK)
+/** @} */
+
+
+/** @name VMCS fields and encoding.
+ *
+ * When adding a new field:
+ * - Always add it to g_aVmcsFields.
+ * - Consider if it needs to be added to VMXVVMCS.
+ * @{
+ */
+/** 16-bit control fields. */
+#define VMX_VMCS16_VPID 0x0000
+#define VMX_VMCS16_POSTED_INT_NOTIFY_VECTOR 0x0002
+#define VMX_VMCS16_EPTP_INDEX 0x0004
+#define VMX_VMCS16_HLAT_PREFIX_SIZE 0x0006
+
+/** 16-bit guest-state fields. */
+#define VMX_VMCS16_GUEST_ES_SEL 0x0800
+#define VMX_VMCS16_GUEST_CS_SEL 0x0802
+#define VMX_VMCS16_GUEST_SS_SEL 0x0804
+#define VMX_VMCS16_GUEST_DS_SEL 0x0806
+#define VMX_VMCS16_GUEST_FS_SEL 0x0808
+#define VMX_VMCS16_GUEST_GS_SEL 0x080a
+#define VMX_VMCS16_GUEST_LDTR_SEL 0x080c
+#define VMX_VMCS16_GUEST_TR_SEL 0x080e
+#define VMX_VMCS16_GUEST_INTR_STATUS 0x0810
+#define VMX_VMCS16_GUEST_PML_INDEX 0x0812
+
+/** 16-bits host-state fields. */
+#define VMX_VMCS16_HOST_ES_SEL 0x0c00
+#define VMX_VMCS16_HOST_CS_SEL 0x0c02
+#define VMX_VMCS16_HOST_SS_SEL 0x0c04
+#define VMX_VMCS16_HOST_DS_SEL 0x0c06
+#define VMX_VMCS16_HOST_FS_SEL 0x0c08
+#define VMX_VMCS16_HOST_GS_SEL 0x0c0a
+#define VMX_VMCS16_HOST_TR_SEL 0x0c0c
+
+/** 64-bit control fields. */
+#define VMX_VMCS64_CTRL_IO_BITMAP_A_FULL 0x2000
+#define VMX_VMCS64_CTRL_IO_BITMAP_A_HIGH 0x2001
+#define VMX_VMCS64_CTRL_IO_BITMAP_B_FULL 0x2002
+#define VMX_VMCS64_CTRL_IO_BITMAP_B_HIGH 0x2003
+#define VMX_VMCS64_CTRL_MSR_BITMAP_FULL 0x2004
+#define VMX_VMCS64_CTRL_MSR_BITMAP_HIGH 0x2005
+#define VMX_VMCS64_CTRL_EXIT_MSR_STORE_FULL 0x2006
+#define VMX_VMCS64_CTRL_EXIT_MSR_STORE_HIGH 0x2007
+#define VMX_VMCS64_CTRL_EXIT_MSR_LOAD_FULL 0x2008
+#define VMX_VMCS64_CTRL_EXIT_MSR_LOAD_HIGH 0x2009
+#define VMX_VMCS64_CTRL_ENTRY_MSR_LOAD_FULL 0x200a
+#define VMX_VMCS64_CTRL_ENTRY_MSR_LOAD_HIGH 0x200b
+#define VMX_VMCS64_CTRL_EXEC_VMCS_PTR_FULL 0x200c
+#define VMX_VMCS64_CTRL_EXEC_VMCS_PTR_HIGH 0x200d
+#define VMX_VMCS64_CTRL_EXEC_PML_ADDR_FULL 0x200e
+#define VMX_VMCS64_CTRL_EXEC_PML_ADDR_HIGH 0x200f
+#define VMX_VMCS64_CTRL_TSC_OFFSET_FULL 0x2010
+#define VMX_VMCS64_CTRL_TSC_OFFSET_HIGH 0x2011
+#define VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_FULL 0x2012
+#define VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_HIGH 0x2013
+#define VMX_VMCS64_CTRL_APIC_ACCESSADDR_FULL 0x2014
+#define VMX_VMCS64_CTRL_APIC_ACCESSADDR_HIGH 0x2015
+#define VMX_VMCS64_CTRL_POSTED_INTR_DESC_FULL 0x2016
+#define VMX_VMCS64_CTRL_POSTED_INTR_DESC_HIGH 0x2017
+#define VMX_VMCS64_CTRL_VMFUNC_CTRLS_FULL 0x2018
+#define VMX_VMCS64_CTRL_VMFUNC_CTRLS_HIGH 0x2019
+#define VMX_VMCS64_CTRL_EPTP_FULL 0x201a
+#define VMX_VMCS64_CTRL_EPTP_HIGH 0x201b
+#define VMX_VMCS64_CTRL_EOI_BITMAP_0_FULL 0x201c
+#define VMX_VMCS64_CTRL_EOI_BITMAP_0_HIGH 0x201d
+#define VMX_VMCS64_CTRL_EOI_BITMAP_1_FULL 0x201e
+#define VMX_VMCS64_CTRL_EOI_BITMAP_1_HIGH 0x201f
+#define VMX_VMCS64_CTRL_EOI_BITMAP_2_FULL 0x2020
+#define VMX_VMCS64_CTRL_EOI_BITMAP_2_HIGH 0x2021
+#define VMX_VMCS64_CTRL_EOI_BITMAP_3_FULL 0x2022
+#define VMX_VMCS64_CTRL_EOI_BITMAP_3_HIGH 0x2023
+#define VMX_VMCS64_CTRL_EPTP_LIST_FULL 0x2024
+#define VMX_VMCS64_CTRL_EPTP_LIST_HIGH 0x2025
+#define VMX_VMCS64_CTRL_VMREAD_BITMAP_FULL 0x2026
+#define VMX_VMCS64_CTRL_VMREAD_BITMAP_HIGH 0x2027
+#define VMX_VMCS64_CTRL_VMWRITE_BITMAP_FULL 0x2028
+#define VMX_VMCS64_CTRL_VMWRITE_BITMAP_HIGH 0x2029
+#define VMX_VMCS64_CTRL_VE_XCPT_INFO_ADDR_FULL 0x202a
+#define VMX_VMCS64_CTRL_VE_XCPT_INFO_ADDR_HIGH 0x202b
+#define VMX_VMCS64_CTRL_XSS_EXITING_BITMAP_FULL 0x202c
+#define VMX_VMCS64_CTRL_XSS_EXITING_BITMAP_HIGH 0x202d
+#define VMX_VMCS64_CTRL_ENCLS_EXITING_BITMAP_FULL 0x202e
+#define VMX_VMCS64_CTRL_ENCLS_EXITING_BITMAP_HIGH 0x202f
+#define VMX_VMCS64_CTRL_SPPTP_FULL 0x2030
+#define VMX_VMCS64_CTRL_SPPTP_HIGH 0x2031
+#define VMX_VMCS64_CTRL_TSC_MULTIPLIER_FULL 0x2032
+#define VMX_VMCS64_CTRL_TSC_MULTIPLIER_HIGH 0x2033
+#define VMX_VMCS64_CTRL_PROC_EXEC3_FULL 0x2034
+#define VMX_VMCS64_CTRL_PROC_EXEC3_HIGH 0x2035
+#define VMX_VMCS64_CTRL_ENCLV_EXITING_BITMAP_FULL 0x2036
+#define VMX_VMCS64_CTRL_ENCLV_EXITING_BITMAP_HIGH 0x2037
+#define VMX_VMCS64_CTRL_PCONFIG_EXITING_BITMAP_FULL 0x203e
+#define VMX_VMCS64_CTRL_PCONFIG_EXITING_BITMAP_HIGH 0x203f
+#define VMX_VMCS64_CTRL_HLAT_PTR_FULL 0x2040
+#define VMX_VMCS64_CTRL_HLAT_PTR_HIGH 0x2041
+#define VMX_VMCS64_CTRL_EXIT2_FULL 0x2044
+#define VMX_VMCS64_CTRL_EXIT2_HIGH 0x2045
+
+/** 64-bit read-only data fields. */
+#define VMX_VMCS64_RO_GUEST_PHYS_ADDR_FULL 0x2400
+#define VMX_VMCS64_RO_GUEST_PHYS_ADDR_HIGH 0x2401
+
+/** 64-bit guest-state fields. */
+#define VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL 0x2800
+#define VMX_VMCS64_GUEST_VMCS_LINK_PTR_HIGH 0x2801
+#define VMX_VMCS64_GUEST_DEBUGCTL_FULL 0x2802
+#define VMX_VMCS64_GUEST_DEBUGCTL_HIGH 0x2803
+#define VMX_VMCS64_GUEST_PAT_FULL 0x2804
+#define VMX_VMCS64_GUEST_PAT_HIGH 0x2805
+#define VMX_VMCS64_GUEST_EFER_FULL 0x2806
+#define VMX_VMCS64_GUEST_EFER_HIGH 0x2807
+#define VMX_VMCS64_GUEST_PERF_GLOBAL_CTRL_FULL 0x2808
+#define VMX_VMCS64_GUEST_PERF_GLOBAL_CTRL_HIGH 0x2809
+#define VMX_VMCS64_GUEST_PDPTE0_FULL 0x280a
+#define VMX_VMCS64_GUEST_PDPTE0_HIGH 0x280b
+#define VMX_VMCS64_GUEST_PDPTE1_FULL 0x280c
+#define VMX_VMCS64_GUEST_PDPTE1_HIGH 0x280d
+#define VMX_VMCS64_GUEST_PDPTE2_FULL 0x280e
+#define VMX_VMCS64_GUEST_PDPTE2_HIGH 0x280f
+#define VMX_VMCS64_GUEST_PDPTE3_FULL 0x2810
+#define VMX_VMCS64_GUEST_PDPTE3_HIGH 0x2811
+#define VMX_VMCS64_GUEST_BNDCFGS_FULL 0x2812
+#define VMX_VMCS64_GUEST_BNDCFGS_HIGH 0x2813
+#define VMX_VMCS64_GUEST_RTIT_CTL_FULL 0x2814
+#define VMX_VMCS64_GUEST_RTIT_CTL_HIGH 0x2815
+#define VMX_VMCS64_GUEST_PKRS_FULL 0x2818
+#define VMX_VMCS64_GUEST_PKRS_HIGH 0x2819
+
+/** 64-bit host-state fields. */
+#define VMX_VMCS64_HOST_PAT_FULL 0x2c00
+#define VMX_VMCS64_HOST_PAT_HIGH 0x2c01
+#define VMX_VMCS64_HOST_EFER_FULL 0x2c02
+#define VMX_VMCS64_HOST_EFER_HIGH 0x2c03
+#define VMX_VMCS64_HOST_PERF_GLOBAL_CTRL_FULL 0x2c04
+#define VMX_VMCS64_HOST_PERF_GLOBAL_CTRL_HIGH 0x2c05
+#define VMX_VMCS64_HOST_PKRS_FULL 0x2c06
+#define VMX_VMCS64_HOST_PKRS_HIGH 0x2c07
+
+/** 32-bit control fields. */
+#define VMX_VMCS32_CTRL_PIN_EXEC 0x4000
+#define VMX_VMCS32_CTRL_PROC_EXEC 0x4002
+#define VMX_VMCS32_CTRL_EXCEPTION_BITMAP 0x4004
+#define VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK 0x4006
+#define VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH 0x4008
+#define VMX_VMCS32_CTRL_CR3_TARGET_COUNT 0x400a
+#define VMX_VMCS32_CTRL_EXIT 0x400c
+#define VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT 0x400e
+#define VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT 0x4010
+#define VMX_VMCS32_CTRL_ENTRY 0x4012
+#define VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT 0x4014
+#define VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO 0x4016
+#define VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE 0x4018
+#define VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH 0x401a
+#define VMX_VMCS32_CTRL_TPR_THRESHOLD 0x401c
+#define VMX_VMCS32_CTRL_PROC_EXEC2 0x401e
+#define VMX_VMCS32_CTRL_PLE_GAP 0x4020
+#define VMX_VMCS32_CTRL_PLE_WINDOW 0x4022
+
+/** 32-bits read-only fields. */
+#define VMX_VMCS32_RO_VM_INSTR_ERROR 0x4400
+#define VMX_VMCS32_RO_EXIT_REASON 0x4402
+#define VMX_VMCS32_RO_EXIT_INTERRUPTION_INFO 0x4404
+#define VMX_VMCS32_RO_EXIT_INTERRUPTION_ERROR_CODE 0x4406
+#define VMX_VMCS32_RO_IDT_VECTORING_INFO 0x4408
+#define VMX_VMCS32_RO_IDT_VECTORING_ERROR_CODE 0x440a
+#define VMX_VMCS32_RO_EXIT_INSTR_LENGTH 0x440c
+#define VMX_VMCS32_RO_EXIT_INSTR_INFO 0x440e
+
+/** 32-bit guest-state fields. */
+#define VMX_VMCS32_GUEST_ES_LIMIT 0x4800
+#define VMX_VMCS32_GUEST_CS_LIMIT 0x4802
+#define VMX_VMCS32_GUEST_SS_LIMIT 0x4804
+#define VMX_VMCS32_GUEST_DS_LIMIT 0x4806
+#define VMX_VMCS32_GUEST_FS_LIMIT 0x4808
+#define VMX_VMCS32_GUEST_GS_LIMIT 0x480a
+#define VMX_VMCS32_GUEST_LDTR_LIMIT 0x480c
+#define VMX_VMCS32_GUEST_TR_LIMIT 0x480e
+#define VMX_VMCS32_GUEST_GDTR_LIMIT 0x4810
+#define VMX_VMCS32_GUEST_IDTR_LIMIT 0x4812
+#define VMX_VMCS32_GUEST_ES_ACCESS_RIGHTS 0x4814
+#define VMX_VMCS32_GUEST_CS_ACCESS_RIGHTS 0x4816
+#define VMX_VMCS32_GUEST_SS_ACCESS_RIGHTS 0x4818
+#define VMX_VMCS32_GUEST_DS_ACCESS_RIGHTS 0x481a
+#define VMX_VMCS32_GUEST_FS_ACCESS_RIGHTS 0x481c
+#define VMX_VMCS32_GUEST_GS_ACCESS_RIGHTS 0x481e
+#define VMX_VMCS32_GUEST_LDTR_ACCESS_RIGHTS 0x4820
+#define VMX_VMCS32_GUEST_TR_ACCESS_RIGHTS 0x4822
+#define VMX_VMCS32_GUEST_INT_STATE 0x4824
+#define VMX_VMCS32_GUEST_ACTIVITY_STATE 0x4826
+#define VMX_VMCS32_GUEST_SMBASE 0x4828
+#define VMX_VMCS32_GUEST_SYSENTER_CS 0x482a
+#define VMX_VMCS32_PREEMPT_TIMER_VALUE 0x482e
+
+/** 32-bit host-state fields. */
+#define VMX_VMCS32_HOST_SYSENTER_CS 0x4C00
+
+/** Natural-width control fields. */
+#define VMX_VMCS_CTRL_CR0_MASK 0x6000
+#define VMX_VMCS_CTRL_CR4_MASK 0x6002
+#define VMX_VMCS_CTRL_CR0_READ_SHADOW 0x6004
+#define VMX_VMCS_CTRL_CR4_READ_SHADOW 0x6006
+#define VMX_VMCS_CTRL_CR3_TARGET_VAL0 0x6008
+#define VMX_VMCS_CTRL_CR3_TARGET_VAL1 0x600a
+#define VMX_VMCS_CTRL_CR3_TARGET_VAL2 0x600c
+#define VMX_VMCS_CTRL_CR3_TARGET_VAL3 0x600e
+
+/** Natural-width read-only data fields. */
+#define VMX_VMCS_RO_EXIT_QUALIFICATION 0x6400
+#define VMX_VMCS_RO_IO_RCX 0x6402
+#define VMX_VMCS_RO_IO_RSI 0x6404
+#define VMX_VMCS_RO_IO_RDI 0x6406
+#define VMX_VMCS_RO_IO_RIP 0x6408
+#define VMX_VMCS_RO_GUEST_LINEAR_ADDR 0x640a
+
+/** Natural-width guest-state fields. */
+#define VMX_VMCS_GUEST_CR0 0x6800
+#define VMX_VMCS_GUEST_CR3 0x6802
+#define VMX_VMCS_GUEST_CR4 0x6804
+#define VMX_VMCS_GUEST_ES_BASE 0x6806
+#define VMX_VMCS_GUEST_CS_BASE 0x6808
+#define VMX_VMCS_GUEST_SS_BASE 0x680a
+#define VMX_VMCS_GUEST_DS_BASE 0x680c
+#define VMX_VMCS_GUEST_FS_BASE 0x680e
+#define VMX_VMCS_GUEST_GS_BASE 0x6810
+#define VMX_VMCS_GUEST_LDTR_BASE 0x6812
+#define VMX_VMCS_GUEST_TR_BASE 0x6814
+#define VMX_VMCS_GUEST_GDTR_BASE 0x6816
+#define VMX_VMCS_GUEST_IDTR_BASE 0x6818
+#define VMX_VMCS_GUEST_DR7 0x681a
+#define VMX_VMCS_GUEST_RSP 0x681c
+#define VMX_VMCS_GUEST_RIP 0x681e
+#define VMX_VMCS_GUEST_RFLAGS 0x6820
+#define VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS 0x6822
+#define VMX_VMCS_GUEST_SYSENTER_ESP 0x6824
+#define VMX_VMCS_GUEST_SYSENTER_EIP 0x6826
+#define VMX_VMCS_GUEST_S_CET 0x6828
+#define VMX_VMCS_GUEST_SSP 0x682a
+#define VMX_VMCS_GUEST_INTR_SSP_TABLE_ADDR 0x682c
+
+/** Natural-width host-state fields. */
+#define VMX_VMCS_HOST_CR0 0x6c00
+#define VMX_VMCS_HOST_CR3 0x6c02
+#define VMX_VMCS_HOST_CR4 0x6c04
+#define VMX_VMCS_HOST_FS_BASE 0x6c06
+#define VMX_VMCS_HOST_GS_BASE 0x6c08
+#define VMX_VMCS_HOST_TR_BASE 0x6c0a
+#define VMX_VMCS_HOST_GDTR_BASE 0x6c0c
+#define VMX_VMCS_HOST_IDTR_BASE 0x6c0e
+#define VMX_VMCS_HOST_SYSENTER_ESP 0x6c10
+#define VMX_VMCS_HOST_SYSENTER_EIP 0x6c12
+#define VMX_VMCS_HOST_RSP 0x6c14
+#define VMX_VMCS_HOST_RIP 0x6c16
+#define VMX_VMCS_HOST_S_CET 0x6c18
+#define VMX_VMCS_HOST_SSP 0x6c1a
+#define VMX_VMCS_HOST_INTR_SSP_TABLE_ADDR 0x6c1c
+
+#define VMX_VMCS16_GUEST_SEG_SEL(a_iSegReg) (VMX_VMCS16_GUEST_ES_SEL + (a_iSegReg) * 2)
+#define VMX_VMCS_GUEST_SEG_BASE(a_iSegReg) (VMX_VMCS_GUEST_ES_BASE + (a_iSegReg) * 2)
+#define VMX_VMCS32_GUEST_SEG_LIMIT(a_iSegReg) (VMX_VMCS32_GUEST_ES_LIMIT + (a_iSegReg) * 2)
+#define VMX_VMCS32_GUEST_SEG_ACCESS_RIGHTS(a_iSegReg) (VMX_VMCS32_GUEST_ES_ACCESS_RIGHTS + (a_iSegReg) * 2)
+
+/**
+ * VMCS field.
+ * In accordance with the VT-x spec.
+ */
+typedef union
+{
+ struct
+ {
+ /** The access type; 0=full, 1=high of 64-bit fields. */
+ uint32_t fAccessType : 1;
+ /** The index. */
+ uint32_t u8Index : 8;
+ /** The type; 0=control, 1=VM-exit info, 2=guest-state, 3=host-state. */
+ uint32_t u2Type : 2;
+ /** Reserved (MBZ). */
+ uint32_t u1Reserved0 : 1;
+ /** The width; 0=16-bit, 1=64-bit, 2=32-bit, 3=natural-width. */
+ uint32_t u2Width : 2;
+ /** Reserved (MBZ). */
+ uint32_t u18Reserved0 : 18;
+ } n;
+
+ /* The unsigned integer view. */
+ uint32_t u;
+} VMXVMCSFIELD;
+AssertCompileSize(VMXVMCSFIELD, 4);
+/** Pointer to a VMCS field. */
+typedef VMXVMCSFIELD *PVMXVMCSFIELD;
+/** Pointer to a const VMCS field. */
+typedef const VMXVMCSFIELD *PCVMXVMCSFIELD;
+
+/** VMCS field: Mask of reserved bits (bits 63:15 MBZ), bit 12 is not included! */
+#define VMX_VMCSFIELD_RSVD_MASK UINT64_C(0xffffffffffff8000)
+
+/** Bits fields for a VMCS field. */
+#define VMX_BF_VMCSFIELD_ACCESS_TYPE_SHIFT 0
+#define VMX_BF_VMCSFIELD_ACCESS_TYPE_MASK UINT32_C(0x00000001)
+#define VMX_BF_VMCSFIELD_INDEX_SHIFT 1
+#define VMX_BF_VMCSFIELD_INDEX_MASK UINT32_C(0x000003fe)
+#define VMX_BF_VMCSFIELD_TYPE_SHIFT 10
+#define VMX_BF_VMCSFIELD_TYPE_MASK UINT32_C(0x00000c00)
+#define VMX_BF_VMCSFIELD_RSVD_12_SHIFT 12
+#define VMX_BF_VMCSFIELD_RSVD_12_MASK UINT32_C(0x00001000)
+#define VMX_BF_VMCSFIELD_WIDTH_SHIFT 13
+#define VMX_BF_VMCSFIELD_WIDTH_MASK UINT32_C(0x00006000)
+#define VMX_BF_VMCSFIELD_RSVD_15_31_SHIFT 15
+#define VMX_BF_VMCSFIELD_RSVD_15_31_MASK UINT32_C(0xffff8000)
+RT_BF_ASSERT_COMPILE_CHECKS(VMX_BF_VMCSFIELD_, UINT32_C(0), UINT32_MAX,
+ (ACCESS_TYPE, INDEX, TYPE, RSVD_12, WIDTH, RSVD_15_31));
+
+/**
+ * VMCS field encoding: Access type.
+ * In accordance with the VT-x spec.
+ */
+typedef enum
+{
+ VMXVMCSFIELDACCESS_FULL = 0,
+ VMXVMCSFIELDACCESS_HIGH
+} VMXVMCSFIELDACCESS;
+AssertCompileSize(VMXVMCSFIELDACCESS, 4);
+/** VMCS field encoding type: Full. */
+#define VMX_VMCSFIELD_ACCESS_FULL 0
+/** VMCS field encoding type: High. */
+#define VMX_VMCSFIELD_ACCESS_HIGH 1
+
+/**
+ * VMCS field encoding: Type.
+ * In accordance with the VT-x spec.
+ */
+typedef enum
+{
+ VMXVMCSFIELDTYPE_CONTROL = 0,
+ VMXVMCSFIELDTYPE_VMEXIT_INFO,
+ VMXVMCSFIELDTYPE_GUEST_STATE,
+ VMXVMCSFIELDTYPE_HOST_STATE
+} VMXVMCSFIELDTYPE;
+AssertCompileSize(VMXVMCSFIELDTYPE, 4);
+/** VMCS field encoding type: Control. */
+#define VMX_VMCSFIELD_TYPE_CONTROL 0
+/** VMCS field encoding type: VM-exit information / read-only fields. */
+#define VMX_VMCSFIELD_TYPE_VMEXIT_INFO 1
+/** VMCS field encoding type: Guest-state. */
+#define VMX_VMCSFIELD_TYPE_GUEST_STATE 2
+/** VMCS field encoding type: Host-state. */
+#define VMX_VMCSFIELD_TYPE_HOST_STATE 3
+
+/**
+ * VMCS field encoding: Width.
+ * In accordance with the VT-x spec.
+ */
+typedef enum
+{
+ VMXVMCSFIELDWIDTH_16BIT = 0,
+ VMXVMCSFIELDWIDTH_64BIT,
+ VMXVMCSFIELDWIDTH_32BIT,
+ VMXVMCSFIELDWIDTH_NATURAL
+} VMXVMCSFIELDWIDTH;
+AssertCompileSize(VMXVMCSFIELDWIDTH, 4);
+/** VMCS field encoding width: 16-bit. */
+#define VMX_VMCSFIELD_WIDTH_16BIT 0
+/** VMCS field encoding width: 64-bit. */
+#define VMX_VMCSFIELD_WIDTH_64BIT 1
+/** VMCS field encoding width: 32-bit. */
+#define VMX_VMCSFIELD_WIDTH_32BIT 2
+/** VMCS field encoding width: Natural width. */
+#define VMX_VMCSFIELD_WIDTH_NATURAL 3
+/** @} */
+
+
+/** @name VM-entry instruction length.
+ * @{ */
+/** The maximum valid value for VM-entry instruction length while injecting a
+ * software interrupt, software exception or privileged software exception. */
+#define VMX_ENTRY_INSTR_LEN_MAX 15
+/** @} */
+
+
+/** @name VM-entry register masks.
+ * @{ */
+/** CR0 bits ignored on VM-entry while loading guest CR0 (ET, CD, NW, bits 6:15,
+ * bit 17 and bits 19:28). */
+#define VMX_ENTRY_GUEST_CR0_IGNORE_MASK UINT64_C(0x7ffaffd0)
+/** DR7 bits set here are always cleared on VM-entry while loading guest DR7 (bit
+ * 12, bits 14:15). */
+#define VMX_ENTRY_GUEST_DR7_MBZ_MASK UINT64_C(0xd000)
+/** DR7 bits set here are always set on VM-entry while loading guest DR7 (bit
+ * 10). */
+#define VMX_ENTRY_GUEST_DR7_MB1_MASK UINT64_C(0x400)
+/** @} */
+
+
+/** @name VM-exit register masks.
+ * @{ */
+/** CR0 bits ignored on VM-exit while loading host CR0 (ET, CD, NW, bits 6:15,
+ * bit 17, bits 19:28 and bits 32:63). */
+#define VMX_EXIT_HOST_CR0_IGNORE_MASK UINT64_C(0xffffffff7ffaffd0)
+/** @} */
+
+
+/** @name Pin-based VM-execution controls.
+ * @{
+ */
+/** External interrupt exiting. */
+#define VMX_PIN_CTLS_EXT_INT_EXIT RT_BIT(0)
+/** NMI exiting. */
+#define VMX_PIN_CTLS_NMI_EXIT RT_BIT(3)
+/** Virtual NMIs. */
+#define VMX_PIN_CTLS_VIRT_NMI RT_BIT(5)
+/** Activate VMX preemption timer. */
+#define VMX_PIN_CTLS_PREEMPT_TIMER RT_BIT(6)
+/** Process interrupts with the posted-interrupt notification vector. */
+#define VMX_PIN_CTLS_POSTED_INT RT_BIT(7)
+/** Default1 class when true capability MSRs are not supported. */
+#define VMX_PIN_CTLS_DEFAULT1 UINT32_C(0x00000016)
+
+/** Bit fields for MSR_IA32_VMX_PINBASED_CTLS and Pin-based VM-execution
+ * controls field in the VMCS. */
+#define VMX_BF_PIN_CTLS_EXT_INT_EXIT_SHIFT 0
+#define VMX_BF_PIN_CTLS_EXT_INT_EXIT_MASK UINT32_C(0x00000001)
+#define VMX_BF_PIN_CTLS_RSVD_1_2_SHIFT 1
+#define VMX_BF_PIN_CTLS_RSVD_1_2_MASK UINT32_C(0x00000006)
+#define VMX_BF_PIN_CTLS_NMI_EXIT_SHIFT 3
+#define VMX_BF_PIN_CTLS_NMI_EXIT_MASK UINT32_C(0x00000008)
+#define VMX_BF_PIN_CTLS_RSVD_4_SHIFT 4
+#define VMX_BF_PIN_CTLS_RSVD_4_MASK UINT32_C(0x00000010)
+#define VMX_BF_PIN_CTLS_VIRT_NMI_SHIFT 5
+#define VMX_BF_PIN_CTLS_VIRT_NMI_MASK UINT32_C(0x00000020)
+#define VMX_BF_PIN_CTLS_PREEMPT_TIMER_SHIFT 6
+#define VMX_BF_PIN_CTLS_PREEMPT_TIMER_MASK UINT32_C(0x00000040)
+#define VMX_BF_PIN_CTLS_POSTED_INT_SHIFT 7
+#define VMX_BF_PIN_CTLS_POSTED_INT_MASK UINT32_C(0x00000080)
+#define VMX_BF_PIN_CTLS_RSVD_8_31_SHIFT 8
+#define VMX_BF_PIN_CTLS_RSVD_8_31_MASK UINT32_C(0xffffff00)
+RT_BF_ASSERT_COMPILE_CHECKS(VMX_BF_PIN_CTLS_, UINT32_C(0), UINT32_MAX,
+ (EXT_INT_EXIT, RSVD_1_2, NMI_EXIT, RSVD_4, VIRT_NMI, PREEMPT_TIMER, POSTED_INT, RSVD_8_31));
+/** @} */
+
+
+/** @name Processor-based VM-execution controls.
+ * @{
+ */
+/** VM-exit as soon as RFLAGS.IF=1 and no blocking is active. */
+#define VMX_PROC_CTLS_INT_WINDOW_EXIT RT_BIT(2)
+/** Use timestamp counter offset. */
+#define VMX_PROC_CTLS_USE_TSC_OFFSETTING RT_BIT(3)
+/** VM-exit when executing the HLT instruction. */
+#define VMX_PROC_CTLS_HLT_EXIT RT_BIT(7)
+/** VM-exit when executing the INVLPG instruction. */
+#define VMX_PROC_CTLS_INVLPG_EXIT RT_BIT(9)
+/** VM-exit when executing the MWAIT instruction. */
+#define VMX_PROC_CTLS_MWAIT_EXIT RT_BIT(10)
+/** VM-exit when executing the RDPMC instruction. */
+#define VMX_PROC_CTLS_RDPMC_EXIT RT_BIT(11)
+/** VM-exit when executing the RDTSC/RDTSCP instruction. */
+#define VMX_PROC_CTLS_RDTSC_EXIT RT_BIT(12)
+/** VM-exit when executing the MOV to CR3 instruction. (forced to 1 on the
+ * 'first' VT-x capable CPUs; this actually includes the newest Nehalem CPUs) */
+#define VMX_PROC_CTLS_CR3_LOAD_EXIT RT_BIT(15)
+/** VM-exit when executing the MOV from CR3 instruction. (forced to 1 on the
+ * 'first' VT-x capable CPUs; this actually includes the newest Nehalem CPUs) */
+#define VMX_PROC_CTLS_CR3_STORE_EXIT RT_BIT(16)
+/** Whether the secondary processor based VM-execution controls are used. */
+#define VMX_PROC_CTLS_USE_TERTIARY_CTLS RT_BIT(17)
+/** VM-exit on CR8 loads. */
+#define VMX_PROC_CTLS_CR8_LOAD_EXIT RT_BIT(19)
+/** VM-exit on CR8 stores. */
+#define VMX_PROC_CTLS_CR8_STORE_EXIT RT_BIT(20)
+/** Use TPR shadow. */
+#define VMX_PROC_CTLS_USE_TPR_SHADOW RT_BIT(21)
+/** VM-exit when virtual NMI blocking is disabled. */
+#define VMX_PROC_CTLS_NMI_WINDOW_EXIT RT_BIT(22)
+/** VM-exit when executing a MOV DRx instruction. */
+#define VMX_PROC_CTLS_MOV_DR_EXIT RT_BIT(23)
+/** VM-exit when executing IO instructions. */
+#define VMX_PROC_CTLS_UNCOND_IO_EXIT RT_BIT(24)
+/** Use IO bitmaps. */
+#define VMX_PROC_CTLS_USE_IO_BITMAPS RT_BIT(25)
+/** Monitor trap flag. */
+#define VMX_PROC_CTLS_MONITOR_TRAP_FLAG RT_BIT(27)
+/** Use MSR bitmaps. */
+#define VMX_PROC_CTLS_USE_MSR_BITMAPS RT_BIT(28)
+/** VM-exit when executing the MONITOR instruction. */
+#define VMX_PROC_CTLS_MONITOR_EXIT RT_BIT(29)
+/** VM-exit when executing the PAUSE instruction. */
+#define VMX_PROC_CTLS_PAUSE_EXIT RT_BIT(30)
+/** Whether the secondary processor based VM-execution controls are used. */
+#define VMX_PROC_CTLS_USE_SECONDARY_CTLS RT_BIT(31)
+/** Default1 class when true-capability MSRs are not supported. */
+#define VMX_PROC_CTLS_DEFAULT1 UINT32_C(0x0401e172)
+
+/** Bit fields for MSR_IA32_VMX_PROCBASED_CTLS and Processor-based VM-execution
+ * controls field in the VMCS. */
+#define VMX_BF_PROC_CTLS_RSVD_0_1_SHIFT 0
+#define VMX_BF_PROC_CTLS_RSVD_0_1_MASK UINT32_C(0x00000003)
+#define VMX_BF_PROC_CTLS_INT_WINDOW_EXIT_SHIFT 2
+#define VMX_BF_PROC_CTLS_INT_WINDOW_EXIT_MASK UINT32_C(0x00000004)
+#define VMX_BF_PROC_CTLS_USE_TSC_OFFSETTING_SHIFT 3
+#define VMX_BF_PROC_CTLS_USE_TSC_OFFSETTING_MASK UINT32_C(0x00000008)
+#define VMX_BF_PROC_CTLS_RSVD_4_6_SHIFT 4
+#define VMX_BF_PROC_CTLS_RSVD_4_6_MASK UINT32_C(0x00000070)
+#define VMX_BF_PROC_CTLS_HLT_EXIT_SHIFT 7
+#define VMX_BF_PROC_CTLS_HLT_EXIT_MASK UINT32_C(0x00000080)
+#define VMX_BF_PROC_CTLS_RSVD_8_SHIFT 8
+#define VMX_BF_PROC_CTLS_RSVD_8_MASK UINT32_C(0x00000100)
+#define VMX_BF_PROC_CTLS_INVLPG_EXIT_SHIFT 9
+#define VMX_BF_PROC_CTLS_INVLPG_EXIT_MASK UINT32_C(0x00000200)
+#define VMX_BF_PROC_CTLS_MWAIT_EXIT_SHIFT 10
+#define VMX_BF_PROC_CTLS_MWAIT_EXIT_MASK UINT32_C(0x00000400)
+#define VMX_BF_PROC_CTLS_RDPMC_EXIT_SHIFT 11
+#define VMX_BF_PROC_CTLS_RDPMC_EXIT_MASK UINT32_C(0x00000800)
+#define VMX_BF_PROC_CTLS_RDTSC_EXIT_SHIFT 12
+#define VMX_BF_PROC_CTLS_RDTSC_EXIT_MASK UINT32_C(0x00001000)
+#define VMX_BF_PROC_CTLS_RSVD_13_14_SHIFT 13
+#define VMX_BF_PROC_CTLS_RSVD_13_14_MASK UINT32_C(0x00006000)
+#define VMX_BF_PROC_CTLS_CR3_LOAD_EXIT_SHIFT 15
+#define VMX_BF_PROC_CTLS_CR3_LOAD_EXIT_MASK UINT32_C(0x00008000)
+#define VMX_BF_PROC_CTLS_CR3_STORE_EXIT_SHIFT 16
+#define VMX_BF_PROC_CTLS_CR3_STORE_EXIT_MASK UINT32_C(0x00010000)
+#define VMX_BF_PROC_CTLS_USE_TERTIARY_CTLS_SHIFT 17
+#define VMX_BF_PROC_CTLS_USE_TERTIARY_CTLS_MASK UINT32_C(0x00020000)
+#define VMX_BF_PROC_CTLS_RSVD_18_SHIFT 18
+#define VMX_BF_PROC_CTLS_RSVD_18_MASK UINT32_C(0x00040000)
+#define VMX_BF_PROC_CTLS_CR8_LOAD_EXIT_SHIFT 19
+#define VMX_BF_PROC_CTLS_CR8_LOAD_EXIT_MASK UINT32_C(0x00080000)
+#define VMX_BF_PROC_CTLS_CR8_STORE_EXIT_SHIFT 20
+#define VMX_BF_PROC_CTLS_CR8_STORE_EXIT_MASK UINT32_C(0x00100000)
+#define VMX_BF_PROC_CTLS_USE_TPR_SHADOW_SHIFT 21
+#define VMX_BF_PROC_CTLS_USE_TPR_SHADOW_MASK UINT32_C(0x00200000)
+#define VMX_BF_PROC_CTLS_NMI_WINDOW_EXIT_SHIFT 22
+#define VMX_BF_PROC_CTLS_NMI_WINDOW_EXIT_MASK UINT32_C(0x00400000)
+#define VMX_BF_PROC_CTLS_MOV_DR_EXIT_SHIFT 23
+#define VMX_BF_PROC_CTLS_MOV_DR_EXIT_MASK UINT32_C(0x00800000)
+#define VMX_BF_PROC_CTLS_UNCOND_IO_EXIT_SHIFT 24
+#define VMX_BF_PROC_CTLS_UNCOND_IO_EXIT_MASK UINT32_C(0x01000000)
+#define VMX_BF_PROC_CTLS_USE_IO_BITMAPS_SHIFT 25
+#define VMX_BF_PROC_CTLS_USE_IO_BITMAPS_MASK UINT32_C(0x02000000)
+#define VMX_BF_PROC_CTLS_RSVD_26_SHIFT 26
+#define VMX_BF_PROC_CTLS_RSVD_26_MASK UINT32_C(0x4000000)
+#define VMX_BF_PROC_CTLS_MONITOR_TRAP_FLAG_SHIFT 27
+#define VMX_BF_PROC_CTLS_MONITOR_TRAP_FLAG_MASK UINT32_C(0x08000000)
+#define VMX_BF_PROC_CTLS_USE_MSR_BITMAPS_SHIFT 28
+#define VMX_BF_PROC_CTLS_USE_MSR_BITMAPS_MASK UINT32_C(0x10000000)
+#define VMX_BF_PROC_CTLS_MONITOR_EXIT_SHIFT 29
+#define VMX_BF_PROC_CTLS_MONITOR_EXIT_MASK UINT32_C(0x20000000)
+#define VMX_BF_PROC_CTLS_PAUSE_EXIT_SHIFT 30
+#define VMX_BF_PROC_CTLS_PAUSE_EXIT_MASK UINT32_C(0x40000000)
+#define VMX_BF_PROC_CTLS_USE_SECONDARY_CTLS_SHIFT 31
+#define VMX_BF_PROC_CTLS_USE_SECONDARY_CTLS_MASK UINT32_C(0x80000000)
+RT_BF_ASSERT_COMPILE_CHECKS(VMX_BF_PROC_CTLS_, UINT32_C(0), UINT32_MAX,
+ (RSVD_0_1, INT_WINDOW_EXIT, USE_TSC_OFFSETTING, RSVD_4_6, HLT_EXIT, RSVD_8, INVLPG_EXIT,
+ MWAIT_EXIT, RDPMC_EXIT, RDTSC_EXIT, RSVD_13_14, CR3_LOAD_EXIT, CR3_STORE_EXIT, USE_TERTIARY_CTLS,
+ RSVD_18, CR8_LOAD_EXIT, CR8_STORE_EXIT, USE_TPR_SHADOW, NMI_WINDOW_EXIT, MOV_DR_EXIT, UNCOND_IO_EXIT,
+ USE_IO_BITMAPS, RSVD_26, MONITOR_TRAP_FLAG, USE_MSR_BITMAPS, MONITOR_EXIT, PAUSE_EXIT,
+ USE_SECONDARY_CTLS));
+/** @} */
+
+
+/** @name Secondary Processor-based VM-execution controls.
+ * @{
+ */
+/** Virtualize APIC accesses. */
+#define VMX_PROC_CTLS2_VIRT_APIC_ACCESS RT_BIT(0)
+/** EPT supported/enabled. */
+#define VMX_PROC_CTLS2_EPT RT_BIT(1)
+/** Descriptor table instructions cause VM-exits. */
+#define VMX_PROC_CTLS2_DESC_TABLE_EXIT RT_BIT(2)
+/** RDTSCP supported/enabled. */
+#define VMX_PROC_CTLS2_RDTSCP RT_BIT(3)
+/** Virtualize x2APIC mode. */
+#define VMX_PROC_CTLS2_VIRT_X2APIC_MODE RT_BIT(4)
+/** VPID supported/enabled. */
+#define VMX_PROC_CTLS2_VPID RT_BIT(5)
+/** VM-exit when executing the WBINVD instruction. */
+#define VMX_PROC_CTLS2_WBINVD_EXIT RT_BIT(6)
+/** Unrestricted guest execution. */
+#define VMX_PROC_CTLS2_UNRESTRICTED_GUEST RT_BIT(7)
+/** APIC register virtualization. */
+#define VMX_PROC_CTLS2_APIC_REG_VIRT RT_BIT(8)
+/** Virtual-interrupt delivery. */
+#define VMX_PROC_CTLS2_VIRT_INT_DELIVERY RT_BIT(9)
+/** A specified number of pause loops cause a VM-exit. */
+#define VMX_PROC_CTLS2_PAUSE_LOOP_EXIT RT_BIT(10)
+/** VM-exit when executing RDRAND instructions. */
+#define VMX_PROC_CTLS2_RDRAND_EXIT RT_BIT(11)
+/** Enables INVPCID instructions. */
+#define VMX_PROC_CTLS2_INVPCID RT_BIT(12)
+/** Enables VMFUNC instructions. */
+#define VMX_PROC_CTLS2_VMFUNC RT_BIT(13)
+/** Enables VMCS shadowing. */
+#define VMX_PROC_CTLS2_VMCS_SHADOWING RT_BIT(14)
+/** Enables ENCLS VM-exits. */
+#define VMX_PROC_CTLS2_ENCLS_EXIT RT_BIT(15)
+/** VM-exit when executing RDSEED. */
+#define VMX_PROC_CTLS2_RDSEED_EXIT RT_BIT(16)
+/** Enables page-modification logging. */
+#define VMX_PROC_CTLS2_PML RT_BIT(17)
+/** Controls whether EPT-violations may cause \#VE instead of exits. */
+#define VMX_PROC_CTLS2_EPT_XCPT_VE RT_BIT(18)
+/** Conceal VMX non-root operation from Intel processor trace (PT). */
+#define VMX_PROC_CTLS2_CONCEAL_VMX_FROM_PT RT_BIT(19)
+/** Enables XSAVES/XRSTORS instructions. */
+#define VMX_PROC_CTLS2_XSAVES_XRSTORS RT_BIT(20)
+/** Enables supervisor/user mode based EPT execute permission for linear
+ * addresses. */
+#define VMX_PROC_CTLS2_MODE_BASED_EPT_PERM RT_BIT(22)
+/** Enables EPT write permissions to be specified at granularity of 128 bytes. */
+#define VMX_PROC_CTLS2_SPP_EPT RT_BIT(23)
+/** Intel PT output addresses are treated as guest-physical addresses and
+ * translated using EPT. */
+#define VMX_PROC_CTLS2_PT_EPT RT_BIT(24)
+/** Use TSC scaling. */
+#define VMX_PROC_CTLS2_TSC_SCALING RT_BIT(25)
+/** Enables TPAUSE, UMONITOR and UMWAIT instructions. */
+#define VMX_PROC_CTLS2_USER_WAIT_PAUSE RT_BIT(26)
+/** Enables consulting ENCLV-exiting bitmap when executing ENCLV. */
+#define VMX_PROC_CTLS2_ENCLV_EXIT RT_BIT(28)
+
+/** Bit fields for MSR_IA32_VMX_PROCBASED_CTLS2 and Secondary processor-based
+ * VM-execution controls field in the VMCS. */
+#define VMX_BF_PROC_CTLS2_VIRT_APIC_ACCESS_SHIFT 0
+#define VMX_BF_PROC_CTLS2_VIRT_APIC_ACCESS_MASK UINT32_C(0x00000001)
+#define VMX_BF_PROC_CTLS2_EPT_SHIFT 1
+#define VMX_BF_PROC_CTLS2_EPT_MASK UINT32_C(0x00000002)
+#define VMX_BF_PROC_CTLS2_DESC_TABLE_EXIT_SHIFT 2
+#define VMX_BF_PROC_CTLS2_DESC_TABLE_EXIT_MASK UINT32_C(0x00000004)
+#define VMX_BF_PROC_CTLS2_RDTSCP_SHIFT 3
+#define VMX_BF_PROC_CTLS2_RDTSCP_MASK UINT32_C(0x00000008)
+#define VMX_BF_PROC_CTLS2_VIRT_X2APIC_MODE_SHIFT 4
+#define VMX_BF_PROC_CTLS2_VIRT_X2APIC_MODE_MASK UINT32_C(0x00000010)
+#define VMX_BF_PROC_CTLS2_VPID_SHIFT 5
+#define VMX_BF_PROC_CTLS2_VPID_MASK UINT32_C(0x00000020)
+#define VMX_BF_PROC_CTLS2_WBINVD_EXIT_SHIFT 6
+#define VMX_BF_PROC_CTLS2_WBINVD_EXIT_MASK UINT32_C(0x00000040)
+#define VMX_BF_PROC_CTLS2_UNRESTRICTED_GUEST_SHIFT 7
+#define VMX_BF_PROC_CTLS2_UNRESTRICTED_GUEST_MASK UINT32_C(0x00000080)
+#define VMX_BF_PROC_CTLS2_APIC_REG_VIRT_SHIFT 8
+#define VMX_BF_PROC_CTLS2_APIC_REG_VIRT_MASK UINT32_C(0x00000100)
+#define VMX_BF_PROC_CTLS2_VIRT_INT_DELIVERY_SHIFT 9
+#define VMX_BF_PROC_CTLS2_VIRT_INT_DELIVERY_MASK UINT32_C(0x00000200)
+#define VMX_BF_PROC_CTLS2_PAUSE_LOOP_EXIT_SHIFT 10
+#define VMX_BF_PROC_CTLS2_PAUSE_LOOP_EXIT_MASK UINT32_C(0x00000400)
+#define VMX_BF_PROC_CTLS2_RDRAND_EXIT_SHIFT 11
+#define VMX_BF_PROC_CTLS2_RDRAND_EXIT_MASK UINT32_C(0x00000800)
+#define VMX_BF_PROC_CTLS2_INVPCID_SHIFT 12
+#define VMX_BF_PROC_CTLS2_INVPCID_MASK UINT32_C(0x00001000)
+#define VMX_BF_PROC_CTLS2_VMFUNC_SHIFT 13
+#define VMX_BF_PROC_CTLS2_VMFUNC_MASK UINT32_C(0x00002000)
+#define VMX_BF_PROC_CTLS2_VMCS_SHADOWING_SHIFT 14
+#define VMX_BF_PROC_CTLS2_VMCS_SHADOWING_MASK UINT32_C(0x00004000)
+#define VMX_BF_PROC_CTLS2_ENCLS_EXIT_SHIFT 15
+#define VMX_BF_PROC_CTLS2_ENCLS_EXIT_MASK UINT32_C(0x00008000)
+#define VMX_BF_PROC_CTLS2_RDSEED_EXIT_SHIFT 16
+#define VMX_BF_PROC_CTLS2_RDSEED_EXIT_MASK UINT32_C(0x00010000)
+#define VMX_BF_PROC_CTLS2_PML_SHIFT 17
+#define VMX_BF_PROC_CTLS2_PML_MASK UINT32_C(0x00020000)
+#define VMX_BF_PROC_CTLS2_EPT_VE_SHIFT 18
+#define VMX_BF_PROC_CTLS2_EPT_VE_MASK UINT32_C(0x00040000)
+#define VMX_BF_PROC_CTLS2_CONCEAL_VMX_FROM_PT_SHIFT 19
+#define VMX_BF_PROC_CTLS2_CONCEAL_VMX_FROM_PT_MASK UINT32_C(0x00080000)
+#define VMX_BF_PROC_CTLS2_XSAVES_XRSTORS_SHIFT 20
+#define VMX_BF_PROC_CTLS2_XSAVES_XRSTORS_MASK UINT32_C(0x00100000)
+#define VMX_BF_PROC_CTLS2_RSVD_21_SHIFT 21
+#define VMX_BF_PROC_CTLS2_RSVD_21_MASK UINT32_C(0x00200000)
+#define VMX_BF_PROC_CTLS2_MODE_BASED_EPT_PERM_SHIFT 22
+#define VMX_BF_PROC_CTLS2_MODE_BASED_EPT_PERM_MASK UINT32_C(0x00400000)
+#define VMX_BF_PROC_CTLS2_SPP_EPT_SHIFT 23
+#define VMX_BF_PROC_CTLS2_SPP_EPT_MASK UINT32_C(0x00800000)
+#define VMX_BF_PROC_CTLS2_PT_EPT_SHIFT 24
+#define VMX_BF_PROC_CTLS2_PT_EPT_MASK UINT32_C(0x01000000)
+#define VMX_BF_PROC_CTLS2_TSC_SCALING_SHIFT 25
+#define VMX_BF_PROC_CTLS2_TSC_SCALING_MASK UINT32_C(0x02000000)
+#define VMX_BF_PROC_CTLS2_USER_WAIT_PAUSE_SHIFT 26
+#define VMX_BF_PROC_CTLS2_USER_WAIT_PAUSE_MASK UINT32_C(0x04000000)
+#define VMX_BF_PROC_CTLS2_RSVD_27_SHIFT 27
+#define VMX_BF_PROC_CTLS2_RSVD_27_MASK UINT32_C(0x08000000)
+#define VMX_BF_PROC_CTLS2_ENCLV_EXIT_SHIFT 28
+#define VMX_BF_PROC_CTLS2_ENCLV_EXIT_MASK UINT32_C(0x10000000)
+#define VMX_BF_PROC_CTLS2_RSVD_29_31_SHIFT 29
+#define VMX_BF_PROC_CTLS2_RSVD_29_31_MASK UINT32_C(0xe0000000)
+
+RT_BF_ASSERT_COMPILE_CHECKS(VMX_BF_PROC_CTLS2_, UINT32_C(0), UINT32_MAX,
+ (VIRT_APIC_ACCESS, EPT, DESC_TABLE_EXIT, RDTSCP, VIRT_X2APIC_MODE, VPID, WBINVD_EXIT,
+ UNRESTRICTED_GUEST, APIC_REG_VIRT, VIRT_INT_DELIVERY, PAUSE_LOOP_EXIT, RDRAND_EXIT, INVPCID, VMFUNC,
+ VMCS_SHADOWING, ENCLS_EXIT, RDSEED_EXIT, PML, EPT_VE, CONCEAL_VMX_FROM_PT, XSAVES_XRSTORS, RSVD_21,
+ MODE_BASED_EPT_PERM, SPP_EPT, PT_EPT, TSC_SCALING, USER_WAIT_PAUSE, RSVD_27, ENCLV_EXIT,
+ RSVD_29_31));
+/** @} */
+
+
+/** @name Tertiary Processor-based VM-execution controls.
+ * @{
+ */
+/** VM-exit when executing LOADIWKEY. */
+#define VMX_PROC_CTLS3_LOADIWKEY_EXIT RT_BIT_64(0)
+
+/** Bit fields for Tertiary processor-based VM-execution controls field in the VMCS. */
+#define VMX_BF_PROC_CTLS3_LOADIWKEY_EXIT_SHIFT 0
+#define VMX_BF_PROC_CTLS3_LOADIWKEY_EXIT_MASK UINT64_C(0x0000000000000001)
+#define VMX_BF_PROC_CTLS3_RSVD_1_63_SHIFT 1
+#define VMX_BF_PROC_CTLS3_RSVD_1_63_MASK UINT64_C(0xfffffffffffffffe)
+
+RT_BF_ASSERT_COMPILE_CHECKS(VMX_BF_PROC_CTLS3_, UINT64_C(0), UINT64_MAX,
+ (LOADIWKEY_EXIT, RSVD_1_63));
+/** @} */
+
+
+/** @name VM-entry controls.
+ * @{
+ */
+/** Load guest debug controls (dr7 & IA32_DEBUGCTL_MSR) (forced to 1 on the
+ * 'first' VT-x capable CPUs; this actually includes the newest Nehalem CPUs) */
+#define VMX_ENTRY_CTLS_LOAD_DEBUG RT_BIT(2)
+/** 64-bit guest mode. Must be 0 for CPUs that don't support AMD64. */
+#define VMX_ENTRY_CTLS_IA32E_MODE_GUEST RT_BIT(9)
+/** In SMM mode after VM-entry. */
+#define VMX_ENTRY_CTLS_ENTRY_TO_SMM RT_BIT(10)
+/** Disable dual treatment of SMI and SMM; must be zero for VM-entry outside of SMM. */
+#define VMX_ENTRY_CTLS_DEACTIVATE_DUAL_MON RT_BIT(11)
+/** Whether the guest IA32_PERF_GLOBAL_CTRL MSR is loaded on VM-entry. */
+#define VMX_ENTRY_CTLS_LOAD_PERF_MSR RT_BIT(13)
+/** Whether the guest IA32_PAT MSR is loaded on VM-entry. */
+#define VMX_ENTRY_CTLS_LOAD_PAT_MSR RT_BIT(14)
+/** Whether the guest IA32_EFER MSR is loaded on VM-entry. */
+#define VMX_ENTRY_CTLS_LOAD_EFER_MSR RT_BIT(15)
+/** Whether the guest IA32_BNDCFGS MSR is loaded on VM-entry. */
+#define VMX_ENTRY_CTLS_LOAD_BNDCFGS_MSR RT_BIT(16)
+/** Whether to conceal VMX from Intel PT (Processor Trace). */
+#define VMX_ENTRY_CTLS_CONCEAL_VMX_FROM_PT RT_BIT(17)
+/** Whether the guest IA32_RTIT MSR is loaded on VM-entry. */
+#define VMX_ENTRY_CTLS_LOAD_RTIT_CTL_MSR RT_BIT(18)
+/** Whether the guest CET-related MSRs and SPP are loaded on VM-entry. */
+#define VMX_ENTRY_CTLS_LOAD_CET_STATE RT_BIT(20)
+/** Whether the guest IA32_PKRS MSR is loaded on VM-entry. */
+#define VMX_ENTRY_CTLS_LOAD_PKRS_MSR RT_BIT(22)
+/** Default1 class when true-capability MSRs are not supported. */
+#define VMX_ENTRY_CTLS_DEFAULT1 UINT32_C(0x000011ff)
+
+/** Bit fields for MSR_IA32_VMX_ENTRY_CTLS and VM-entry controls field in the
+ * VMCS. */
+#define VMX_BF_ENTRY_CTLS_RSVD_0_1_SHIFT 0
+#define VMX_BF_ENTRY_CTLS_RSVD_0_1_MASK UINT32_C(0x00000003)
+#define VMX_BF_ENTRY_CTLS_LOAD_DEBUG_SHIFT 2
+#define VMX_BF_ENTRY_CTLS_LOAD_DEBUG_MASK UINT32_C(0x00000004)
+#define VMX_BF_ENTRY_CTLS_RSVD_3_8_SHIFT 3
+#define VMX_BF_ENTRY_CTLS_RSVD_3_8_MASK UINT32_C(0x000001f8)
+#define VMX_BF_ENTRY_CTLS_IA32E_MODE_GUEST_SHIFT 9
+#define VMX_BF_ENTRY_CTLS_IA32E_MODE_GUEST_MASK UINT32_C(0x00000200)
+#define VMX_BF_ENTRY_CTLS_ENTRY_SMM_SHIFT 10
+#define VMX_BF_ENTRY_CTLS_ENTRY_SMM_MASK UINT32_C(0x00000400)
+#define VMX_BF_ENTRY_CTLS_DEACTIVATE_DUAL_MON_SHIFT 11
+#define VMX_BF_ENTRY_CTLS_DEACTIVATE_DUAL_MON_MASK UINT32_C(0x00000800)
+#define VMX_BF_ENTRY_CTLS_RSVD_12_SHIFT 12
+#define VMX_BF_ENTRY_CTLS_RSVD_12_MASK UINT32_C(0x00001000)
+#define VMX_BF_ENTRY_CTLS_LOAD_PERF_MSR_SHIFT 13
+#define VMX_BF_ENTRY_CTLS_LOAD_PERF_MSR_MASK UINT32_C(0x00002000)
+#define VMX_BF_ENTRY_CTLS_LOAD_PAT_MSR_SHIFT 14
+#define VMX_BF_ENTRY_CTLS_LOAD_PAT_MSR_MASK UINT32_C(0x00004000)
+#define VMX_BF_ENTRY_CTLS_LOAD_EFER_MSR_SHIFT 15
+#define VMX_BF_ENTRY_CTLS_LOAD_EFER_MSR_MASK UINT32_C(0x00008000)
+#define VMX_BF_ENTRY_CTLS_LOAD_BNDCFGS_MSR_SHIFT 16
+#define VMX_BF_ENTRY_CTLS_LOAD_BNDCFGS_MSR_MASK UINT32_C(0x00010000)
+#define VMX_BF_ENTRY_CTLS_CONCEAL_VMX_FROM_PT_SHIFT 17
+#define VMX_BF_ENTRY_CTLS_CONCEAL_VMX_FROM_PT_MASK UINT32_C(0x00020000)
+#define VMX_BF_ENTRY_CTLS_LOAD_RTIT_CTL_MSR_SHIFT 18
+#define VMX_BF_ENTRY_CTLS_LOAD_RTIT_CTL_MSR_MASK UINT32_C(0x00040000)
+#define VMX_BF_ENTRY_CTLS_RSVD_19_SHIFT 19
+#define VMX_BF_ENTRY_CTLS_RSVD_19_MASK UINT32_C(0x00080000)
+#define VMX_BF_ENTRY_CTLS_LOAD_CET_SHIFT 20
+#define VMX_BF_ENTRY_CTLS_LOAD_CET_MASK UINT32_C(0x00100000)
+#define VMX_BF_ENTRY_CTLS_RSVD_21_SHIFT 21
+#define VMX_BF_ENTRY_CTLS_RSVD_21_MASK UINT32_C(0x00200000)
+#define VMX_BF_ENTRY_CTLS_LOAD_PKRS_MSR_SHIFT 22
+#define VMX_BF_ENTRY_CTLS_LOAD_PKRS_MSR_MASK UINT32_C(0x00400000)
+#define VMX_BF_ENTRY_CTLS_RSVD_23_31_SHIFT 23
+#define VMX_BF_ENTRY_CTLS_RSVD_23_31_MASK UINT32_C(0xff800000)
+
+RT_BF_ASSERT_COMPILE_CHECKS(VMX_BF_ENTRY_CTLS_, UINT32_C(0), UINT32_MAX,
+ (RSVD_0_1, LOAD_DEBUG, RSVD_3_8, IA32E_MODE_GUEST, ENTRY_SMM, DEACTIVATE_DUAL_MON, RSVD_12,
+ LOAD_PERF_MSR, LOAD_PAT_MSR, LOAD_EFER_MSR, LOAD_BNDCFGS_MSR, CONCEAL_VMX_FROM_PT,
+ LOAD_RTIT_CTL_MSR, RSVD_19, LOAD_CET, RSVD_21, LOAD_PKRS_MSR, RSVD_23_31));
+/** @} */
+
+
+/** @name VM-exit controls.
+ * @{
+ */
+/** Save guest debug controls (dr7 & IA32_DEBUGCTL_MSR) (forced to 1 on the
+ * 'first' VT-x capable CPUs; this actually includes the newest Nehalem CPUs) */
+#define VMX_EXIT_CTLS_SAVE_DEBUG RT_BIT(2)
+/** Return to long mode after a VM-exit. */
+#define VMX_EXIT_CTLS_HOST_ADDR_SPACE_SIZE RT_BIT(9)
+/** Whether the host IA32_PERF_GLOBAL_CTRL MSR is loaded on VM-exit. */
+#define VMX_EXIT_CTLS_LOAD_PERF_MSR RT_BIT(12)
+/** Acknowledge external interrupts with the irq controller if one caused a VM-exit. */
+#define VMX_EXIT_CTLS_ACK_EXT_INT RT_BIT(15)
+/** Whether the guest IA32_PAT MSR is saved on VM-exit. */
+#define VMX_EXIT_CTLS_SAVE_PAT_MSR RT_BIT(18)
+/** Whether the host IA32_PAT MSR is loaded on VM-exit. */
+#define VMX_EXIT_CTLS_LOAD_PAT_MSR RT_BIT(19)
+/** Whether the guest IA32_EFER MSR is saved on VM-exit. */
+#define VMX_EXIT_CTLS_SAVE_EFER_MSR RT_BIT(20)
+/** Whether the host IA32_EFER MSR is loaded on VM-exit. */
+#define VMX_EXIT_CTLS_LOAD_EFER_MSR RT_BIT(21)
+/** Whether the value of the VMX preemption timer is saved on every VM-exit. */
+#define VMX_EXIT_CTLS_SAVE_PREEMPT_TIMER RT_BIT(22)
+/** Whether IA32_BNDCFGS MSR is cleared on VM-exit. */
+#define VMX_EXIT_CTLS_CLEAR_BNDCFGS_MSR RT_BIT(23)
+/** Whether to conceal VMX from Intel PT. */
+#define VMX_EXIT_CTLS_CONCEAL_VMX_FROM_PT RT_BIT(24)
+/** Whether IA32_RTIT_CTL MSR is cleared on VM-exit. */
+#define VMX_EXIT_CTLS_CLEAR_RTIT_CTL_MSR RT_BIT(25)
+/** Whether CET-related MSRs and SPP are loaded on VM-exit. */
+#define VMX_EXIT_CTLS_LOAD_CET_STATE RT_BIT(28)
+/** Whether the host IA32_PKRS MSR is loaded on VM-exit. */
+#define VMX_EXIT_CTLS_LOAD_PKRS_MSR RT_BIT(29)
+/** Whether the host IA32_PERF_GLOBAL_CTRL MSR is saved on VM-exit. */
+#define VMX_EXIT_CTLS_SAVE_PERF_MSR RT_BIT(30)
+/** Whether secondary VM-exit controls are used. */
+#define VMX_EXIT_CTLS_USE_SECONDARY_CTLS RT_BIT(31)
+/** Default1 class when true-capability MSRs are not supported. */
+#define VMX_EXIT_CTLS_DEFAULT1 UINT32_C(0x00036dff)
+
+/** Bit fields for MSR_IA32_VMX_EXIT_CTLS and VM-exit controls field in the
+ * VMCS. */
+#define VMX_BF_EXIT_CTLS_RSVD_0_1_SHIFT 0
+#define VMX_BF_EXIT_CTLS_RSVD_0_1_MASK UINT32_C(0x00000003)
+#define VMX_BF_EXIT_CTLS_SAVE_DEBUG_SHIFT 2
+#define VMX_BF_EXIT_CTLS_SAVE_DEBUG_MASK UINT32_C(0x00000004)
+#define VMX_BF_EXIT_CTLS_RSVD_3_8_SHIFT 3
+#define VMX_BF_EXIT_CTLS_RSVD_3_8_MASK UINT32_C(0x000001f8)
+#define VMX_BF_EXIT_CTLS_HOST_ADDR_SPACE_SIZE_SHIFT 9
+#define VMX_BF_EXIT_CTLS_HOST_ADDR_SPACE_SIZE_MASK UINT32_C(0x00000200)
+#define VMX_BF_EXIT_CTLS_RSVD_10_11_SHIFT 10
+#define VMX_BF_EXIT_CTLS_RSVD_10_11_MASK UINT32_C(0x00000c00)
+#define VMX_BF_EXIT_CTLS_LOAD_PERF_MSR_SHIFT 12
+#define VMX_BF_EXIT_CTLS_LOAD_PERF_MSR_MASK UINT32_C(0x00001000)
+#define VMX_BF_EXIT_CTLS_RSVD_13_14_SHIFT 13
+#define VMX_BF_EXIT_CTLS_RSVD_13_14_MASK UINT32_C(0x00006000)
+#define VMX_BF_EXIT_CTLS_ACK_EXT_INT_SHIFT 15
+#define VMX_BF_EXIT_CTLS_ACK_EXT_INT_MASK UINT32_C(0x00008000)
+#define VMX_BF_EXIT_CTLS_RSVD_16_17_SHIFT 16
+#define VMX_BF_EXIT_CTLS_RSVD_16_17_MASK UINT32_C(0x00030000)
+#define VMX_BF_EXIT_CTLS_SAVE_PAT_MSR_SHIFT 18
+#define VMX_BF_EXIT_CTLS_SAVE_PAT_MSR_MASK UINT32_C(0x00040000)
+#define VMX_BF_EXIT_CTLS_LOAD_PAT_MSR_SHIFT 19
+#define VMX_BF_EXIT_CTLS_LOAD_PAT_MSR_MASK UINT32_C(0x00080000)
+#define VMX_BF_EXIT_CTLS_SAVE_EFER_MSR_SHIFT 20
+#define VMX_BF_EXIT_CTLS_SAVE_EFER_MSR_MASK UINT32_C(0x00100000)
+#define VMX_BF_EXIT_CTLS_LOAD_EFER_MSR_SHIFT 21
+#define VMX_BF_EXIT_CTLS_LOAD_EFER_MSR_MASK UINT32_C(0x00200000)
+#define VMX_BF_EXIT_CTLS_SAVE_PREEMPT_TIMER_SHIFT 22
+#define VMX_BF_EXIT_CTLS_SAVE_PREEMPT_TIMER_MASK UINT32_C(0x00400000)
+#define VMX_BF_EXIT_CTLS_CLEAR_BNDCFGS_MSR_SHIFT 23
+#define VMX_BF_EXIT_CTLS_CLEAR_BNDCFGS_MSR_MASK UINT32_C(0x00800000)
+#define VMX_BF_EXIT_CTLS_CONCEAL_VMX_FROM_PT_SHIFT 24
+#define VMX_BF_EXIT_CTLS_CONCEAL_VMX_FROM_PT_MASK UINT32_C(0x01000000)
+#define VMX_BF_EXIT_CTLS_CLEAR_RTIT_CTL_MSR_SHIFT 25
+#define VMX_BF_EXIT_CTLS_CLEAR_RTIT_CTL_MSR_MASK UINT32_C(0x02000000)
+#define VMX_BF_EXIT_CTLS_RSVD_26_27_SHIFT 26
+#define VMX_BF_EXIT_CTLS_RSVD_26_27_MASK UINT32_C(0x0c000000)
+#define VMX_BF_EXIT_CTLS_LOAD_CET_SHIFT 28
+#define VMX_BF_EXIT_CTLS_LOAD_CET_MASK UINT32_C(0x10000000)
+#define VMX_BF_EXIT_CTLS_LOAD_PKRS_MSR_SHIFT 29
+#define VMX_BF_EXIT_CTLS_LOAD_PKRS_MSR_MASK UINT32_C(0x20000000)
+#define VMX_BF_EXIT_CTLS_SAVE_PERF_MSR_SHIFT 30
+#define VMX_BF_EXIT_CTLS_SAVE_PERF_MSR_MASK UINT32_C(0x40000000)
+#define VMX_BF_EXIT_CTLS_USE_SECONDARY_CTLS_SHIFT 31
+#define VMX_BF_EXIT_CTLS_USE_SECONDARY_CTLS_MASK UINT32_C(0x80000000)
+RT_BF_ASSERT_COMPILE_CHECKS(VMX_BF_EXIT_CTLS_, UINT32_C(0), UINT32_MAX,
+ (RSVD_0_1, SAVE_DEBUG, RSVD_3_8, HOST_ADDR_SPACE_SIZE, RSVD_10_11, LOAD_PERF_MSR, RSVD_13_14,
+ ACK_EXT_INT, RSVD_16_17, SAVE_PAT_MSR, LOAD_PAT_MSR, SAVE_EFER_MSR, LOAD_EFER_MSR,
+ SAVE_PREEMPT_TIMER, CLEAR_BNDCFGS_MSR, CONCEAL_VMX_FROM_PT, CLEAR_RTIT_CTL_MSR, RSVD_26_27,
+ LOAD_CET, LOAD_PKRS_MSR, SAVE_PERF_MSR, USE_SECONDARY_CTLS));
+/** @} */
+
+
+/** @name VM-exit reason.
+ * @{
+ */
+#define VMX_EXIT_REASON_BASIC(a) ((a) & 0xffff)
+#define VMX_EXIT_REASON_HAS_ENTRY_FAILED(a) (((a) >> 31) & 1)
+#define VMX_EXIT_REASON_ENTRY_FAILED RT_BIT(31)
+
+/** Bit fields for VM-exit reason. */
+/** The exit reason. */
+#define VMX_BF_EXIT_REASON_BASIC_SHIFT 0
+#define VMX_BF_EXIT_REASON_BASIC_MASK UINT32_C(0x0000ffff)
+/** Bits 16:26 are reseved and MBZ. */
+#define VMX_BF_EXIT_REASON_RSVD_16_26_SHIFT 16
+#define VMX_BF_EXIT_REASON_RSVD_16_26_MASK UINT32_C(0x07ff0000)
+/** Whether the VM-exit was incident to enclave mode. */
+#define VMX_BF_EXIT_REASON_ENCLAVE_MODE_SHIFT 27
+#define VMX_BF_EXIT_REASON_ENCLAVE_MODE_MASK UINT32_C(0x08000000)
+/** Pending MTF (Monitor Trap Flag) during VM-exit (only applicable in SMM mode). */
+#define VMX_BF_EXIT_REASON_SMM_PENDING_MTF_SHIFT 28
+#define VMX_BF_EXIT_REASON_SMM_PENDING_MTF_MASK UINT32_C(0x10000000)
+/** VM-exit from VMX root operation (only possible with SMM). */
+#define VMX_BF_EXIT_REASON_VMX_ROOT_MODE_SHIFT 29
+#define VMX_BF_EXIT_REASON_VMX_ROOT_MODE_MASK UINT32_C(0x20000000)
+/** Bit 30 is reserved and MBZ. */
+#define VMX_BF_EXIT_REASON_RSVD_30_SHIFT 30
+#define VMX_BF_EXIT_REASON_RSVD_30_MASK UINT32_C(0x40000000)
+/** Whether VM-entry failed (currently only happens during loading guest-state
+ * or MSRs or machine check exceptions). */
+#define VMX_BF_EXIT_REASON_ENTRY_FAILED_SHIFT 31
+#define VMX_BF_EXIT_REASON_ENTRY_FAILED_MASK UINT32_C(0x80000000)
+RT_BF_ASSERT_COMPILE_CHECKS(VMX_BF_EXIT_REASON_, UINT32_C(0), UINT32_MAX,
+ (BASIC, RSVD_16_26, ENCLAVE_MODE, SMM_PENDING_MTF, VMX_ROOT_MODE, RSVD_30, ENTRY_FAILED));
+/** @} */
+
+
+/** @name VM-entry interruption information.
+ * @{
+ */
+#define VMX_ENTRY_INT_INFO_IS_VALID(a) (((a) >> 31) & 1)
+#define VMX_ENTRY_INT_INFO_VECTOR(a) ((a) & 0xff)
+#define VMX_ENTRY_INT_INFO_TYPE_SHIFT 8
+#define VMX_ENTRY_INT_INFO_TYPE(a) (((a) >> 8) & 7)
+#define VMX_ENTRY_INT_INFO_ERROR_CODE_VALID RT_BIT(11)
+#define VMX_ENTRY_INT_INFO_IS_ERROR_CODE_VALID(a) (((a) >> 11) & 1)
+#define VMX_ENTRY_INT_INFO_NMI_UNBLOCK_IRET 12
+#define VMX_ENTRY_INT_INFO_IS_NMI_UNBLOCK_IRET(a) (((a) >> 12) & 1)
+#define VMX_ENTRY_INT_INFO_VALID RT_BIT(31)
+#define VMX_ENTRY_INT_INFO_IS_VALID(a) (((a) >> 31) & 1)
+/** Construct an VM-entry interruption information field from a VM-exit interruption
+ * info value (same except that bit 12 is reserved). */
+#define VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(a) ((a) & ~RT_BIT(12))
+/** Construct a VM-entry interruption information field from an IDT-vectoring
+ * information field (same except that bit 12 is reserved). */
+#define VMX_ENTRY_INT_INFO_FROM_EXIT_IDT_INFO(a) ((a) & ~RT_BIT(12))
+/** If the VM-entry interruption information field indicates a page-fault. */
+#define VMX_ENTRY_INT_INFO_IS_XCPT_PF(a) (((a) & ( VMX_BF_ENTRY_INT_INFO_VALID_MASK \
+ | VMX_BF_ENTRY_INT_INFO_TYPE_MASK \
+ | VMX_BF_ENTRY_INT_INFO_VECTOR_MASK)) \
+ == ( RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1) \
+ | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_HW_XCPT) \
+ | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_PF)))
+/** If the VM-entry interruption information field indicates an external
+ * interrupt. */
+#define VMX_ENTRY_INT_INFO_IS_EXT_INT(a) (((a) & ( VMX_BF_ENTRY_INT_INFO_VALID_MASK \
+ | VMX_BF_ENTRY_INT_INFO_TYPE_MASK)) \
+ == ( RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1) \
+ | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_EXT_INT)))
+/** If the VM-entry interruption information field indicates an NMI. */
+#define VMX_ENTRY_INT_INFO_IS_XCPT_NMI(a) (((a) & ( VMX_BF_ENTRY_INT_INFO_VALID_MASK \
+ | VMX_BF_ENTRY_INT_INFO_TYPE_MASK \
+ | VMX_BF_ENTRY_INT_INFO_VECTOR_MASK)) \
+ == ( RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1) \
+ | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_NMI) \
+ | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_NMI)))
+
+/** Bit fields for VM-entry interruption information. */
+/** The VM-entry interruption vector. */
+#define VMX_BF_ENTRY_INT_INFO_VECTOR_SHIFT 0
+#define VMX_BF_ENTRY_INT_INFO_VECTOR_MASK UINT32_C(0x000000ff)
+/** The VM-entry interruption type (see VMX_ENTRY_INT_INFO_TYPE_XXX). */
+#define VMX_BF_ENTRY_INT_INFO_TYPE_SHIFT 8
+#define VMX_BF_ENTRY_INT_INFO_TYPE_MASK UINT32_C(0x00000700)
+/** Whether this event has an error code. */
+#define VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID_SHIFT 11
+#define VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID_MASK UINT32_C(0x00000800)
+/** Bits 12:30 are reserved and MBZ. */
+#define VMX_BF_ENTRY_INT_INFO_RSVD_12_30_SHIFT 12
+#define VMX_BF_ENTRY_INT_INFO_RSVD_12_30_MASK UINT32_C(0x7ffff000)
+/** Whether this VM-entry interruption info is valid. */
+#define VMX_BF_ENTRY_INT_INFO_VALID_SHIFT 31
+#define VMX_BF_ENTRY_INT_INFO_VALID_MASK UINT32_C(0x80000000)
+RT_BF_ASSERT_COMPILE_CHECKS(VMX_BF_ENTRY_INT_INFO_, UINT32_C(0), UINT32_MAX,
+ (VECTOR, TYPE, ERR_CODE_VALID, RSVD_12_30, VALID));
+/** @} */
+
+
+/** @name VM-entry exception error code.
+ * @{ */
+/** Error code valid mask. */
+/** @todo r=ramshankar: Intel spec. 26.2.1.3 "VM-Entry Control Fields" states that
+ * bits 31:15 MBZ. However, Intel spec. 6.13 "Error Code" states "To keep the
+ * stack aligned for doubleword pushes, the upper half of the error code is
+ * reserved" which implies bits 31:16 MBZ (and not 31:15) which is what we
+ * use below. */
+#define VMX_ENTRY_INT_XCPT_ERR_CODE_VALID_MASK UINT32_C(0xffff)
+/** @} */
+
+/** @name VM-entry interruption information types.
+ * @{
+ */
+#define VMX_ENTRY_INT_INFO_TYPE_EXT_INT 0
+#define VMX_ENTRY_INT_INFO_TYPE_RSVD 1
+#define VMX_ENTRY_INT_INFO_TYPE_NMI 2
+#define VMX_ENTRY_INT_INFO_TYPE_HW_XCPT 3
+#define VMX_ENTRY_INT_INFO_TYPE_SW_INT 4
+#define VMX_ENTRY_INT_INFO_TYPE_PRIV_SW_XCPT 5
+#define VMX_ENTRY_INT_INFO_TYPE_SW_XCPT 6
+#define VMX_ENTRY_INT_INFO_TYPE_OTHER_EVENT 7
+/** @} */
+
+
+/** @name VM-entry interruption information vector types for
+ * VMX_ENTRY_INT_INFO_TYPE_OTHER_EVENT.
+ * @{ */
+#define VMX_ENTRY_INT_INFO_VECTOR_MTF 0
+/** @} */
+
+
+/** @name VM-exit interruption information.
+ * @{
+ */
+#define VMX_EXIT_INT_INFO_VECTOR(a) ((a) & 0xff)
+#define VMX_EXIT_INT_INFO_TYPE_SHIFT 8
+#define VMX_EXIT_INT_INFO_TYPE(a) (((a) >> 8) & 7)
+#define VMX_EXIT_INT_INFO_ERROR_CODE_VALID RT_BIT(11)
+#define VMX_EXIT_INT_INFO_IS_ERROR_CODE_VALID(a) (((a) >> 11) & 1)
+#define VMX_EXIT_INT_INFO_NMI_UNBLOCK_IRET 12
+#define VMX_EXIT_INT_INFO_IS_NMI_UNBLOCK_IRET(a) (((a) >> 12) & 1)
+#define VMX_EXIT_INT_INFO_VALID RT_BIT(31)
+#define VMX_EXIT_INT_INFO_IS_VALID(a) (((a) >> 31) & 1)
+
+/** If the VM-exit interruption information field indicates an page-fault. */
+#define VMX_EXIT_INT_INFO_IS_XCPT_PF(a) (((a) & ( VMX_BF_EXIT_INT_INFO_VALID_MASK \
+ | VMX_BF_EXIT_INT_INFO_TYPE_MASK \
+ | VMX_BF_EXIT_INT_INFO_VECTOR_MASK)) \
+ == ( RT_BF_MAKE(VMX_BF_EXIT_INT_INFO_VALID, 1) \
+ | RT_BF_MAKE(VMX_BF_EXIT_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT) \
+ | RT_BF_MAKE(VMX_BF_EXIT_INT_INFO_VECTOR, X86_XCPT_PF)))
+/** If the VM-exit interruption information field indicates an double-fault. */
+#define VMX_EXIT_INT_INFO_IS_XCPT_DF(a) (((a) & ( VMX_BF_EXIT_INT_INFO_VALID_MASK \
+ | VMX_BF_EXIT_INT_INFO_TYPE_MASK \
+ | VMX_BF_EXIT_INT_INFO_VECTOR_MASK)) \
+ == ( RT_BF_MAKE(VMX_BF_EXIT_INT_INFO_VALID, 1) \
+ | RT_BF_MAKE(VMX_BF_EXIT_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT) \
+ | RT_BF_MAKE(VMX_BF_EXIT_INT_INFO_VECTOR, X86_XCPT_DF)))
+/** If the VM-exit interruption information field indicates an NMI. */
+#define VMX_EXIT_INT_INFO_IS_XCPT_NMI(a) (((a) & ( VMX_BF_EXIT_INT_INFO_VALID_MASK \
+ | VMX_BF_EXIT_INT_INFO_TYPE_MASK \
+ | VMX_BF_EXIT_INT_INFO_VECTOR_MASK)) \
+ == ( RT_BF_MAKE(VMX_BF_EXIT_INT_INFO_VALID, 1) \
+ | RT_BF_MAKE(VMX_BF_EXIT_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_NMI) \
+ | RT_BF_MAKE(VMX_BF_EXIT_INT_INFO_VECTOR, X86_XCPT_NMI)))
+
+
+/** Bit fields for VM-exit interruption infomration. */
+/** The VM-exit interruption vector. */
+#define VMX_BF_EXIT_INT_INFO_VECTOR_SHIFT 0
+#define VMX_BF_EXIT_INT_INFO_VECTOR_MASK UINT32_C(0x000000ff)
+/** The VM-exit interruption type (see VMX_EXIT_INT_INFO_TYPE_XXX). */
+#define VMX_BF_EXIT_INT_INFO_TYPE_SHIFT 8
+#define VMX_BF_EXIT_INT_INFO_TYPE_MASK UINT32_C(0x00000700)
+/** Whether this event has an error code. */
+#define VMX_BF_EXIT_INT_INFO_ERR_CODE_VALID_SHIFT 11
+#define VMX_BF_EXIT_INT_INFO_ERR_CODE_VALID_MASK UINT32_C(0x00000800)
+/** Whether NMI-unblocking due to IRET is active. */
+#define VMX_BF_EXIT_INT_INFO_NMI_UNBLOCK_IRET_SHIFT 12
+#define VMX_BF_EXIT_INT_INFO_NMI_UNBLOCK_IRET_MASK UINT32_C(0x00001000)
+/** Bits 13:30 is reserved (MBZ). */
+#define VMX_BF_EXIT_INT_INFO_RSVD_13_30_SHIFT 13
+#define VMX_BF_EXIT_INT_INFO_RSVD_13_30_MASK UINT32_C(0x7fffe000)
+/** Whether this VM-exit interruption info is valid. */
+#define VMX_BF_EXIT_INT_INFO_VALID_SHIFT 31
+#define VMX_BF_EXIT_INT_INFO_VALID_MASK UINT32_C(0x80000000)
+RT_BF_ASSERT_COMPILE_CHECKS(VMX_BF_EXIT_INT_INFO_, UINT32_C(0), UINT32_MAX,
+ (VECTOR, TYPE, ERR_CODE_VALID, NMI_UNBLOCK_IRET, RSVD_13_30, VALID));
+/** @} */
+
+
+/** @name VM-exit interruption information types.
+ * @{
+ */
+#define VMX_EXIT_INT_INFO_TYPE_EXT_INT 0
+#define VMX_EXIT_INT_INFO_TYPE_NMI 2
+#define VMX_EXIT_INT_INFO_TYPE_HW_XCPT 3
+#define VMX_EXIT_INT_INFO_TYPE_SW_INT 4
+#define VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT 5
+#define VMX_EXIT_INT_INFO_TYPE_SW_XCPT 6
+#define VMX_EXIT_INT_INFO_TYPE_UNUSED 7
+/** @} */
+
+
+/** @name VM-exit instruction identity.
+ *
+ * These are found in VM-exit instruction information fields for certain
+ * instructions.
+ * @{ */
+typedef uint32_t VMXINSTRID;
+/** Whether the instruction ID field is valid. */
+#define VMXINSTRID_VALID RT_BIT_32(31)
+/** Whether the instruction's primary operand in the Mod R/M byte (bits 0:3) is a
+ * read or write. */
+#define VMXINSTRID_MODRM_PRIMARY_OP_W RT_BIT_32(30)
+/** Gets whether the instruction ID is valid or not. */
+#define VMXINSTRID_IS_VALID(a) (((a) >> 31) & 1)
+#define VMXINSTRID_IS_MODRM_PRIMARY_OP_W(a) (((a) >> 30) & 1)
+/** Gets the instruction ID. */
+#define VMXINSTRID_GET_ID(a) ((a) & ~(VMXINSTRID_VALID | VMXINSTRID_MODRM_PRIMARY_OP_W))
+/** No instruction ID info. */
+#define VMXINSTRID_NONE 0
+
+/** The OR'd rvalues are from the VT-x spec (valid bit is VBox specific): */
+#define VMXINSTRID_SGDT (0x0 | VMXINSTRID_VALID | VMXINSTRID_MODRM_PRIMARY_OP_W)
+#define VMXINSTRID_SIDT (0x1 | VMXINSTRID_VALID | VMXINSTRID_MODRM_PRIMARY_OP_W)
+#define VMXINSTRID_LGDT (0x2 | VMXINSTRID_VALID)
+#define VMXINSTRID_LIDT (0x3 | VMXINSTRID_VALID)
+
+#define VMXINSTRID_SLDT (0x0 | VMXINSTRID_VALID | VMXINSTRID_MODRM_PRIMARY_OP_W)
+#define VMXINSTRID_STR (0x1 | VMXINSTRID_VALID | VMXINSTRID_MODRM_PRIMARY_OP_W)
+#define VMXINSTRID_LLDT (0x2 | VMXINSTRID_VALID)
+#define VMXINSTRID_LTR (0x3 | VMXINSTRID_VALID)
+
+/** The following IDs are used internally (some for logging, others for conveying
+ * the ModR/M primary operand write bit): */
+#define VMXINSTRID_VMLAUNCH (0x10 | VMXINSTRID_VALID)
+#define VMXINSTRID_VMRESUME (0x11 | VMXINSTRID_VALID)
+#define VMXINSTRID_VMREAD (0x12 | VMXINSTRID_VALID)
+#define VMXINSTRID_VMWRITE (0x13 | VMXINSTRID_VALID | VMXINSTRID_MODRM_PRIMARY_OP_W)
+#define VMXINSTRID_IO_IN (0x14 | VMXINSTRID_VALID)
+#define VMXINSTRID_IO_INS (0x15 | VMXINSTRID_VALID)
+#define VMXINSTRID_IO_OUT (0x16 | VMXINSTRID_VALID)
+#define VMXINSTRID_IO_OUTS (0x17 | VMXINSTRID_VALID)
+#define VMXINSTRID_MOV_TO_DRX (0x18 | VMXINSTRID_VALID)
+#define VMXINSTRID_MOV_FROM_DRX (0x19 | VMXINSTRID_VALID)
+/** @} */
+
+
+/** @name IDT-vectoring information.
+ * @{
+ */
+#define VMX_IDT_VECTORING_INFO_VECTOR(a) ((a) & 0xff)
+#define VMX_IDT_VECTORING_INFO_TYPE_SHIFT 8
+#define VMX_IDT_VECTORING_INFO_TYPE(a) (((a) >> 8) & 7)
+#define VMX_IDT_VECTORING_INFO_ERROR_CODE_VALID RT_BIT(11)
+#define VMX_IDT_VECTORING_INFO_IS_ERROR_CODE_VALID(a) (((a) >> 11) & 1)
+#define VMX_IDT_VECTORING_INFO_IS_VALID(a) (((a) >> 31) & 1)
+#define VMX_IDT_VECTORING_INFO_VALID RT_BIT(31)
+
+/** Construct an IDT-vectoring information field from an VM-entry interruption
+ * information field (same except that bit 12 is reserved). */
+#define VMX_IDT_VECTORING_INFO_FROM_ENTRY_INT_INFO(a) ((a) & ~RT_BIT(12))
+/** If the IDT-vectoring information field indicates a page-fault. */
+#define VMX_IDT_VECTORING_INFO_IS_XCPT_PF(a) (((a) & ( VMX_BF_IDT_VECTORING_INFO_VALID_MASK \
+ | VMX_BF_IDT_VECTORING_INFO_TYPE_MASK \
+ | VMX_BF_IDT_VECTORING_INFO_VECTOR_MASK)) \
+ == ( RT_BF_MAKE(VMX_BF_IDT_VECTORING_INFO_VALID, 1) \
+ | RT_BF_MAKE(VMX_BF_IDT_VECTORING_INFO_TYPE, VMX_IDT_VECTORING_INFO_TYPE_HW_XCPT) \
+ | RT_BF_MAKE(VMX_BF_IDT_VECTORING_INFO_VECTOR, X86_XCPT_PF)))
+/** If the IDT-vectoring information field indicates an NMI. */
+#define VMX_IDT_VECTORING_INFO_IS_XCPT_NMI(a) (((a) & ( VMX_BF_IDT_VECTORING_INFO_VALID_MASK \
+ | VMX_BF_IDT_VECTORING_INFO_TYPE_MASK \
+ | VMX_BF_IDT_VECTORING_INFO_VECTOR_MASK)) \
+ == ( RT_BF_MAKE(VMX_BF_IDT_VECTORING_INFO_VALID, 1) \
+ | RT_BF_MAKE(VMX_BF_IDT_VECTORING_INFO_TYPE, VMX_IDT_VECTORING_INFO_TYPE_NMI) \
+ | RT_BF_MAKE(VMX_BF_IDT_VECTORING_INFO_VECTOR, X86_XCPT_NMI)))
+
+
+/** Bit fields for IDT-vectoring information. */
+/** The IDT-vectoring info vector. */
+#define VMX_BF_IDT_VECTORING_INFO_VECTOR_SHIFT 0
+#define VMX_BF_IDT_VECTORING_INFO_VECTOR_MASK UINT32_C(0x000000ff)
+/** The IDT-vectoring info type (see VMX_IDT_VECTORING_INFO_TYPE_XXX). */
+#define VMX_BF_IDT_VECTORING_INFO_TYPE_SHIFT 8
+#define VMX_BF_IDT_VECTORING_INFO_TYPE_MASK UINT32_C(0x00000700)
+/** Whether the event has an error code. */
+#define VMX_BF_IDT_VECTORING_INFO_ERR_CODE_VALID_SHIFT 11
+#define VMX_BF_IDT_VECTORING_INFO_ERR_CODE_VALID_MASK UINT32_C(0x00000800)
+/** Bit 12 is undefined. */
+#define VMX_BF_IDT_VECTORING_INFO_UNDEF_12_SHIFT 12
+#define VMX_BF_IDT_VECTORING_INFO_UNDEF_12_MASK UINT32_C(0x00001000)
+/** Bits 13:30 is reserved (MBZ). */
+#define VMX_BF_IDT_VECTORING_INFO_RSVD_13_30_SHIFT 13
+#define VMX_BF_IDT_VECTORING_INFO_RSVD_13_30_MASK UINT32_C(0x7fffe000)
+/** Whether this IDT-vectoring info is valid. */
+#define VMX_BF_IDT_VECTORING_INFO_VALID_SHIFT 31
+#define VMX_BF_IDT_VECTORING_INFO_VALID_MASK UINT32_C(0x80000000)
+RT_BF_ASSERT_COMPILE_CHECKS(VMX_BF_IDT_VECTORING_INFO_, UINT32_C(0), UINT32_MAX,
+ (VECTOR, TYPE, ERR_CODE_VALID, UNDEF_12, RSVD_13_30, VALID));
+/** @} */
+
+
+/** @name IDT-vectoring information vector types.
+ * @{
+ */
+#define VMX_IDT_VECTORING_INFO_TYPE_EXT_INT 0
+#define VMX_IDT_VECTORING_INFO_TYPE_NMI 2
+#define VMX_IDT_VECTORING_INFO_TYPE_HW_XCPT 3
+#define VMX_IDT_VECTORING_INFO_TYPE_SW_INT 4
+#define VMX_IDT_VECTORING_INFO_TYPE_PRIV_SW_XCPT 5
+#define VMX_IDT_VECTORING_INFO_TYPE_SW_XCPT 6
+#define VMX_IDT_VECTORING_INFO_TYPE_UNUSED 7
+/** @} */
+
+
+/** @name TPR threshold.
+ * @{ */
+/** Mask of the TPR threshold field (bits 31:4 MBZ). */
+#define VMX_TPR_THRESHOLD_MASK UINT32_C(0xf)
+
+/** Bit fields for TPR threshold. */
+#define VMX_BF_TPR_THRESHOLD_TPR_SHIFT 0
+#define VMX_BF_TPR_THRESHOLD_TPR_MASK UINT32_C(0x0000000f)
+#define VMX_BF_TPR_THRESHOLD_RSVD_4_31_SHIFT 4
+#define VMX_BF_TPR_THRESHOLD_RSVD_4_31_MASK UINT32_C(0xfffffff0)
+RT_BF_ASSERT_COMPILE_CHECKS(VMX_BF_TPR_THRESHOLD_, UINT32_C(0), UINT32_MAX,
+ (TPR, RSVD_4_31));
+/** @} */
+
+
+/** @name Guest-activity states.
+ * @{
+ */
+/** The logical processor is active. */
+#define VMX_VMCS_GUEST_ACTIVITY_ACTIVE 0x0
+/** The logical processor is inactive, because it executed a HLT instruction. */
+#define VMX_VMCS_GUEST_ACTIVITY_HLT 0x1
+/** The logical processor is inactive, because of a triple fault or other serious error. */
+#define VMX_VMCS_GUEST_ACTIVITY_SHUTDOWN 0x2
+/** The logical processor is inactive, because it's waiting for a startup-IPI */
+#define VMX_VMCS_GUEST_ACTIVITY_SIPI_WAIT 0x3
+/** @} */
+
+
+/** @name Guest-interruptibility states.
+ * @{
+ */
+#define VMX_VMCS_GUEST_INT_STATE_BLOCK_STI RT_BIT(0)
+#define VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS RT_BIT(1)
+#define VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI RT_BIT(2)
+#define VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI RT_BIT(3)
+#define VMX_VMCS_GUEST_INT_STATE_ENCLAVE RT_BIT(4)
+
+/** Mask of the guest-interruptibility state field (bits 31:5 MBZ). */
+#define VMX_VMCS_GUEST_INT_STATE_MASK UINT32_C(0x1f)
+/** @} */
+
+
+/** @name Exit qualification for debug exceptions.
+ * @{
+ */
+/** Hardware breakpoint 0 was met. */
+#define VMX_VMCS_EXIT_QUAL_DEBUG_XCPT_BP0 RT_BIT_64(0)
+/** Hardware breakpoint 1 was met. */
+#define VMX_VMCS_EXIT_QUAL_DEBUG_XCPT_BP1 RT_BIT_64(1)
+/** Hardware breakpoint 2 was met. */
+#define VMX_VMCS_EXIT_QUAL_DEBUG_XCPT_BP2 RT_BIT_64(2)
+/** Hardware breakpoint 3 was met. */
+#define VMX_VMCS_EXIT_QUAL_DEBUG_XCPT_BP3 RT_BIT_64(3)
+/** Debug register access detected. */
+#define VMX_VMCS_EXIT_QUAL_DEBUG_XCPT_BD RT_BIT_64(13)
+/** A debug exception would have been triggered by single-step execution mode. */
+#define VMX_VMCS_EXIT_QUAL_DEBUG_XCPT_BS RT_BIT_64(14)
+/** Mask of all valid bits. */
+#define VMX_VMCS_EXIT_QUAL_VALID_MASK ( VMX_VMCS_EXIT_QUAL_DEBUG_XCPT_BP0 \
+ | VMX_VMCS_EXIT_QUAL_DEBUG_XCPT_BP1 \
+ | VMX_VMCS_EXIT_QUAL_DEBUG_XCPT_BP2 \
+ | VMX_VMCS_EXIT_QUAL_DEBUG_XCPT_BP3 \
+ | VMX_VMCS_EXIT_QUAL_DEBUG_XCPT_BD \
+ | VMX_VMCS_EXIT_QUAL_DEBUG_XCPT_BS)
+
+/** Bit fields for Exit qualifications due to debug exceptions. */
+#define VMX_BF_EXIT_QUAL_DEBUG_XCPT_BP0_SHIFT 0
+#define VMX_BF_EXIT_QUAL_DEBUG_XCPT_BP0_MASK UINT64_C(0x0000000000000001)
+#define VMX_BF_EXIT_QUAL_DEBUG_XCPT_BP1_SHIFT 1
+#define VMX_BF_EXIT_QUAL_DEBUG_XCPT_BP1_MASK UINT64_C(0x0000000000000002)
+#define VMX_BF_EXIT_QUAL_DEBUG_XCPT_BP2_SHIFT 2
+#define VMX_BF_EXIT_QUAL_DEBUG_XCPT_BP2_MASK UINT64_C(0x0000000000000004)
+#define VMX_BF_EXIT_QUAL_DEBUG_XCPT_BP3_SHIFT 3
+#define VMX_BF_EXIT_QUAL_DEBUG_XCPT_BP3_MASK UINT64_C(0x0000000000000008)
+#define VMX_BF_EXIT_QUAL_DEBUG_XCPT_RSVD_4_12_SHIFT 4
+#define VMX_BF_EXIT_QUAL_DEBUG_XCPT_RSVD_4_12_MASK UINT64_C(0x0000000000001ff0)
+#define VMX_BF_EXIT_QUAL_DEBUG_XCPT_BD_SHIFT 13
+#define VMX_BF_EXIT_QUAL_DEBUG_XCPT_BD_MASK UINT64_C(0x0000000000002000)
+#define VMX_BF_EXIT_QUAL_DEBUG_XCPT_BS_SHIFT 14
+#define VMX_BF_EXIT_QUAL_DEBUG_XCPT_BS_MASK UINT64_C(0x0000000000004000)
+#define VMX_BF_EXIT_QUAL_DEBUG_XCPT_RSVD_15_63_SHIFT 15
+#define VMX_BF_EXIT_QUAL_DEBUG_XCPT_RSVD_15_63_MASK UINT64_C(0xffffffffffff8000)
+RT_BF_ASSERT_COMPILE_CHECKS(VMX_BF_EXIT_QUAL_DEBUG_XCPT_, UINT64_C(0), UINT64_MAX,
+ (BP0, BP1, BP2, BP3, RSVD_4_12, BD, BS, RSVD_15_63));
+/** @} */
+
+/** @name Exit qualification for Mov DRx.
+ * @{
+ */
+/** 0-2: Debug register number */
+#define VMX_EXIT_QUAL_DRX_REGISTER(a) ((a) & 7)
+/** 3: Reserved; cleared to 0. */
+#define VMX_EXIT_QUAL_DRX_RES1(a) (((a) >> 3) & 1)
+/** 4: Direction of move (0 = write, 1 = read) */
+#define VMX_EXIT_QUAL_DRX_DIRECTION(a) (((a) >> 4) & 1)
+/** 5-7: Reserved; cleared to 0. */
+#define VMX_EXIT_QUAL_DRX_RES2(a) (((a) >> 5) & 7)
+/** 8-11: General purpose register number. */
+#define VMX_EXIT_QUAL_DRX_GENREG(a) (((a) >> 8) & 0xf)
+
+/** Bit fields for Exit qualification due to Mov DRx. */
+#define VMX_BF_EXIT_QUAL_DRX_REGISTER_SHIFT 0
+#define VMX_BF_EXIT_QUAL_DRX_REGISTER_MASK UINT64_C(0x0000000000000007)
+#define VMX_BF_EXIT_QUAL_DRX_RSVD_1_SHIFT 3
+#define VMX_BF_EXIT_QUAL_DRX_RSVD_1_MASK UINT64_C(0x0000000000000008)
+#define VMX_BF_EXIT_QUAL_DRX_DIRECTION_SHIFT 4
+#define VMX_BF_EXIT_QUAL_DRX_DIRECTION_MASK UINT64_C(0x0000000000000010)
+#define VMX_BF_EXIT_QUAL_DRX_RSVD_5_7_SHIFT 5
+#define VMX_BF_EXIT_QUAL_DRX_RSVD_5_7_MASK UINT64_C(0x00000000000000e0)
+#define VMX_BF_EXIT_QUAL_DRX_GENREG_SHIFT 8
+#define VMX_BF_EXIT_QUAL_DRX_GENREG_MASK UINT64_C(0x0000000000000f00)
+#define VMX_BF_EXIT_QUAL_DRX_RSVD_12_63_SHIFT 12
+#define VMX_BF_EXIT_QUAL_DRX_RSVD_12_63_MASK UINT64_C(0xfffffffffffff000)
+RT_BF_ASSERT_COMPILE_CHECKS(VMX_BF_EXIT_QUAL_DRX_, UINT64_C(0), UINT64_MAX,
+ (REGISTER, RSVD_1, DIRECTION, RSVD_5_7, GENREG, RSVD_12_63));
+/** @} */
+
+
+/** @name Exit qualification for debug exceptions types.
+ * @{
+ */
+#define VMX_EXIT_QUAL_DRX_DIRECTION_WRITE 0
+#define VMX_EXIT_QUAL_DRX_DIRECTION_READ 1
+/** @} */
+
+
+/** @name Exit qualification for control-register accesses.
+ * @{
+ */
+/** 0-3: Control register number (0 for CLTS & LMSW) */
+#define VMX_EXIT_QUAL_CRX_REGISTER(a) ((a) & 0xf)
+/** 4-5: Access type. */
+#define VMX_EXIT_QUAL_CRX_ACCESS(a) (((a) >> 4) & 3)
+/** 6: LMSW operand type memory (1 for memory, 0 for register). */
+#define VMX_EXIT_QUAL_CRX_LMSW_OP_MEM(a) (((a) >> 6) & 1)
+/** 7: Reserved; cleared to 0. */
+#define VMX_EXIT_QUAL_CRX_RES1(a) (((a) >> 7) & 1)
+/** 8-11: General purpose register number (0 for CLTS & LMSW). */
+#define VMX_EXIT_QUAL_CRX_GENREG(a) (((a) >> 8) & 0xf)
+/** 12-15: Reserved; cleared to 0. */
+#define VMX_EXIT_QUAL_CRX_RES2(a) (((a) >> 12) & 0xf)
+/** 16-31: LMSW source data (else 0). */
+#define VMX_EXIT_QUAL_CRX_LMSW_DATA(a) (((a) >> 16) & 0xffff)
+
+/** Bit fields for Exit qualification for control-register accesses. */
+#define VMX_BF_EXIT_QUAL_CRX_REGISTER_SHIFT 0
+#define VMX_BF_EXIT_QUAL_CRX_REGISTER_MASK UINT64_C(0x000000000000000f)
+#define VMX_BF_EXIT_QUAL_CRX_ACCESS_SHIFT 4
+#define VMX_BF_EXIT_QUAL_CRX_ACCESS_MASK UINT64_C(0x0000000000000030)
+#define VMX_BF_EXIT_QUAL_CRX_LMSW_OP_SHIFT 6
+#define VMX_BF_EXIT_QUAL_CRX_LMSW_OP_MASK UINT64_C(0x0000000000000040)
+#define VMX_BF_EXIT_QUAL_CRX_RSVD_7_SHIFT 7
+#define VMX_BF_EXIT_QUAL_CRX_RSVD_7_MASK UINT64_C(0x0000000000000080)
+#define VMX_BF_EXIT_QUAL_CRX_GENREG_SHIFT 8
+#define VMX_BF_EXIT_QUAL_CRX_GENREG_MASK UINT64_C(0x0000000000000f00)
+#define VMX_BF_EXIT_QUAL_CRX_RSVD_12_15_SHIFT 12
+#define VMX_BF_EXIT_QUAL_CRX_RSVD_12_15_MASK UINT64_C(0x000000000000f000)
+#define VMX_BF_EXIT_QUAL_CRX_LMSW_DATA_SHIFT 16
+#define VMX_BF_EXIT_QUAL_CRX_LMSW_DATA_MASK UINT64_C(0x00000000ffff0000)
+#define VMX_BF_EXIT_QUAL_CRX_RSVD_32_63_SHIFT 32
+#define VMX_BF_EXIT_QUAL_CRX_RSVD_32_63_MASK UINT64_C(0xffffffff00000000)
+RT_BF_ASSERT_COMPILE_CHECKS(VMX_BF_EXIT_QUAL_CRX_, UINT64_C(0), UINT64_MAX,
+ (REGISTER, ACCESS, LMSW_OP, RSVD_7, GENREG, RSVD_12_15, LMSW_DATA, RSVD_32_63));
+/** @} */
+
+
+/** @name Exit qualification for control-register access types.
+ * @{
+ */
+#define VMX_EXIT_QUAL_CRX_ACCESS_WRITE 0
+#define VMX_EXIT_QUAL_CRX_ACCESS_READ 1
+#define VMX_EXIT_QUAL_CRX_ACCESS_CLTS 2
+#define VMX_EXIT_QUAL_CRX_ACCESS_LMSW 3
+/** @} */
+
+
+/** @name Exit qualification for task switch.
+ * @{
+ */
+#define VMX_EXIT_QUAL_TASK_SWITCH_SELECTOR(a) ((a) & 0xffff)
+#define VMX_EXIT_QUAL_TASK_SWITCH_TYPE(a) (((a) >> 30) & 0x3)
+/** Task switch caused by a call instruction. */
+#define VMX_EXIT_QUAL_TASK_SWITCH_TYPE_CALL 0
+/** Task switch caused by an iret instruction. */
+#define VMX_EXIT_QUAL_TASK_SWITCH_TYPE_IRET 1
+/** Task switch caused by a jmp instruction. */
+#define VMX_EXIT_QUAL_TASK_SWITCH_TYPE_JMP 2
+/** Task switch caused by an interrupt gate. */
+#define VMX_EXIT_QUAL_TASK_SWITCH_TYPE_IDT 3
+
+/** Bit fields for Exit qualification for task switches. */
+#define VMX_BF_EXIT_QUAL_TASK_SWITCH_NEW_TSS_SHIFT 0
+#define VMX_BF_EXIT_QUAL_TASK_SWITCH_NEW_TSS_MASK UINT64_C(0x000000000000ffff)
+#define VMX_BF_EXIT_QUAL_TASK_SWITCH_RSVD_16_29_SHIFT 16
+#define VMX_BF_EXIT_QUAL_TASK_SWITCH_RSVD_16_29_MASK UINT64_C(0x000000003fff0000)
+#define VMX_BF_EXIT_QUAL_TASK_SWITCH_SOURCE_SHIFT 30
+#define VMX_BF_EXIT_QUAL_TASK_SWITCH_SOURCE_MASK UINT64_C(0x00000000c0000000)
+#define VMX_BF_EXIT_QUAL_TASK_SWITCH_RSVD_32_63_SHIFT 32
+#define VMX_BF_EXIT_QUAL_TASK_SWITCH_RSVD_32_63_MASK UINT64_C(0xffffffff00000000)
+RT_BF_ASSERT_COMPILE_CHECKS(VMX_BF_EXIT_QUAL_TASK_SWITCH_, UINT64_C(0), UINT64_MAX,
+ (NEW_TSS, RSVD_16_29, SOURCE, RSVD_32_63));
+/** @} */
+
+
+/** @name Exit qualification for EPT violations.
+ * @{
+ */
+/** Set if acess causing the violation was a data read. */
+#define VMX_EXIT_QUAL_EPT_ACCESS_READ RT_BIT_64(0)
+/** Set if acess causing the violation was a data write. */
+#define VMX_EXIT_QUAL_EPT_ACCESS_WRITE RT_BIT_64(1)
+/** Set if the violation was caused by an instruction fetch. */
+#define VMX_EXIT_QUAL_EPT_ACCESS_INSTR_FETCH RT_BIT_64(2)
+/** AND of the read bit of all EPT structures. */
+#define VMX_EXIT_QUAL_EPT_ENTRY_READ RT_BIT_64(3)
+/** AND of the write bit of all EPT structures. */
+#define VMX_EXIT_QUAL_EPT_ENTRY_WRITE RT_BIT_64(4)
+/** AND of the execute bit of all EPT structures. */
+#define VMX_EXIT_QUAL_EPT_ENTRY_EXECUTE RT_BIT_64(5)
+/** And of the execute bit of all EPT structures for user-mode addresses
+ * (requires mode-based execute control). */
+#define VMX_EXIT_QUAL_EPT_ENTRY_EXECUTE_USER RT_BIT_64(6)
+/** Set if the guest linear address field is valid. */
+#define VMX_EXIT_QUAL_EPT_LINEAR_ADDR_VALID RT_BIT_64(7)
+/** If bit 7 is one: (reserved otherwise)
+ * 1 - violation due to physical address access.
+ * 0 - violation caused by page walk or access/dirty bit updates.
+ */
+#define VMX_EXIT_QUAL_EPT_LINEAR_TO_PHYS_ADDR RT_BIT_64(8)
+/** If bit 7, 8 and advanced VM-exit info. for EPT is one: (reserved otherwise)
+ * 1 - linear address is user-mode address.
+ * 0 - linear address is supervisor-mode address.
+ */
+#define VMX_EXIT_QUAL_EPT_LINEAR_ADDR_USER RT_BIT_64(9)
+/** If bit 7, 8 and advanced VM-exit info. for EPT is one: (reserved otherwise)
+ * 1 - linear address translates to read-only page.
+ * 0 - linear address translates to read-write page.
+ */
+#define VMX_EXIT_QUAL_EPT_LINEAR_ADDR_RO RT_BIT_64(10)
+/** If bit 7, 8 and advanced VM-exit info. for EPT is one: (reserved otherwise)
+ * 1 - linear address translates to executable-disabled page.
+ * 0 - linear address translates to executable page.
+ */
+#define VMX_EXIT_QUAL_EPT_LINEAR_ADDR_XD RT_BIT_64(11)
+/** NMI unblocking due to IRET. */
+#define VMX_EXIT_QUAL_EPT_NMI_UNBLOCK_IRET RT_BIT_64(12)
+/** Set if acess causing the violation was a shadow-stack access. */
+#define VMX_EXIT_QUAL_EPT_ACCESS_SHW_STACK RT_BIT_64(13)
+/** If supervisor-shadow stack is enabled: (reserved otherwise)
+ * 1 - supervisor shadow-stack access allowed.
+ * 0 - supervisor shadow-stack access disallowed.
+ */
+#define VMX_EXIT_QUAL_EPT_ENTRY_SHW_STACK_SUPER RT_BIT_64(14)
+/** Set if access is related to trace output by Intel PT (reserved otherwise). */
+#define VMX_EXIT_QUAL_EPT_ACCESS_PT_TRACE RT_BIT_64(16)
+
+/** Checks whether NMI unblocking due to IRET. */
+#define VMX_EXIT_QUAL_EPT_IS_NMI_UNBLOCK_IRET(a) (((a) >> 12) & 1)
+
+/** Bit fields for Exit qualification for EPT violations. */
+#define VMX_BF_EXIT_QUAL_EPT_ACCESS_READ_SHIFT 0
+#define VMX_BF_EXIT_QUAL_EPT_ACCESS_READ_MASK UINT64_C(0x0000000000000001)
+#define VMX_BF_EXIT_QUAL_EPT_ACCESS_WRITE_SHIFT 1
+#define VMX_BF_EXIT_QUAL_EPT_ACCESS_WRITE_MASK UINT64_C(0x0000000000000002)
+#define VMX_BF_EXIT_QUAL_EPT_ACCESS_INSTR_FETCH_SHIFT 2
+#define VMX_BF_EXIT_QUAL_EPT_ACCESS_INSTR_FETCH_MASK UINT64_C(0x0000000000000004)
+#define VMX_BF_EXIT_QUAL_EPT_ENTRY_READ_SHIFT 3
+#define VMX_BF_EXIT_QUAL_EPT_ENTRY_READ_MASK UINT64_C(0x0000000000000008)
+#define VMX_BF_EXIT_QUAL_EPT_ENTRY_WRITE_SHIFT 4
+#define VMX_BF_EXIT_QUAL_EPT_ENTRY_WRITE_MASK UINT64_C(0x0000000000000010)
+#define VMX_BF_EXIT_QUAL_EPT_ENTRY_EXECUTE_SHIFT 5
+#define VMX_BF_EXIT_QUAL_EPT_ENTRY_EXECUTE_MASK UINT64_C(0x0000000000000020)
+#define VMX_BF_EXIT_QUAL_EPT_ENTRY_EXECUTE_USER_SHIFT 6
+#define VMX_BF_EXIT_QUAL_EPT_ENTRY_EXECUTE_USER_MASK UINT64_C(0x0000000000000040)
+#define VMX_BF_EXIT_QUAL_EPT_LINEAR_ADDR_VALID_SHIFT 7
+#define VMX_BF_EXIT_QUAL_EPT_LINEAR_ADDR_VALID_MASK UINT64_C(0x0000000000000080)
+#define VMX_BF_EXIT_QUAL_EPT_LINEAR_TO_PHYS_ADDR_SHIFT 8
+#define VMX_BF_EXIT_QUAL_EPT_LINEAR_TO_PHYS_ADDR_MASK UINT64_C(0x0000000000000100)
+#define VMX_BF_EXIT_QUAL_EPT_LINEAR_ADDR_USER_SHIFT 9
+#define VMX_BF_EXIT_QUAL_EPT_LINEAR_ADDR_USER_MASK UINT64_C(0x0000000000000200)
+#define VMX_BF_EXIT_QUAL_EPT_LINEAR_ADDR_RO_SHIFT 10
+#define VMX_BF_EXIT_QUAL_EPT_LINEAR_ADDR_RO_MASK UINT64_C(0x0000000000000400)
+#define VMX_BF_EXIT_QUAL_EPT_LINEAR_ADDR_XD_SHIFT 11
+#define VMX_BF_EXIT_QUAL_EPT_LINEAR_ADDR_XD_MASK UINT64_C(0x0000000000000800)
+#define VMX_BF_EXIT_QUAL_EPT_NMI_UNBLOCK_IRET_SHIFT 12
+#define VMX_BF_EXIT_QUAL_EPT_NMI_UNBLOCK_IRET_MASK UINT64_C(0x0000000000001000)
+#define VMX_BF_EXIT_QUAL_EPT_ACCESS_SHW_STACK_SHIFT 13
+#define VMX_BF_EXIT_QUAL_EPT_ACCESS_SHW_STACK_MASK UINT64_C(0x0000000000002000)
+#define VMX_BF_EXIT_QUAL_EPT_ENTRY_SHW_STACK_SUPER_SHIFT 14
+#define VMX_BF_EXIT_QUAL_EPT_ENTRY_SHW_STACK_SUPER_MASK UINT64_C(0x0000000000004000)
+#define VMX_BF_EXIT_QUAL_EPT_RSVD_15_SHIFT 15
+#define VMX_BF_EXIT_QUAL_EPT_RSVD_15_MASK UINT64_C(0x0000000000008000)
+#define VMX_BF_EXIT_QUAL_EPT_ACCESS_PT_TRACE_SHIFT 16
+#define VMX_BF_EXIT_QUAL_EPT_ACCESS_PT_TRACE_MASK UINT64_C(0x0000000000010000)
+#define VMX_BF_EXIT_QUAL_EPT_RSVD_17_63_SHIFT 17
+#define VMX_BF_EXIT_QUAL_EPT_RSVD_17_63_MASK UINT64_C(0xfffffffffffe0000)
+RT_BF_ASSERT_COMPILE_CHECKS(VMX_BF_EXIT_QUAL_EPT_, UINT64_C(0), UINT64_MAX,
+ (ACCESS_READ, ACCESS_WRITE, ACCESS_INSTR_FETCH, ENTRY_READ, ENTRY_WRITE, ENTRY_EXECUTE,
+ ENTRY_EXECUTE_USER, LINEAR_ADDR_VALID, LINEAR_TO_PHYS_ADDR, LINEAR_ADDR_USER, LINEAR_ADDR_RO,
+ LINEAR_ADDR_XD, NMI_UNBLOCK_IRET, ACCESS_SHW_STACK, ENTRY_SHW_STACK_SUPER, RSVD_15,
+ ACCESS_PT_TRACE, RSVD_17_63));
+/** @} */
+
+
+/** @name Exit qualification for I/O instructions.
+ * @{
+ */
+/** 0-2: IO operation size 0(=1 byte), 1(=2 bytes) and 3(=4 bytes). */
+#define VMX_EXIT_QUAL_IO_SIZE(a) ((a) & 7)
+/** 3: IO operation direction. */
+#define VMX_EXIT_QUAL_IO_DIRECTION(a) (((a) >> 3) & 1)
+/** 4: String IO operation (INS / OUTS). */
+#define VMX_EXIT_QUAL_IO_IS_STRING(a) (((a) >> 4) & 1)
+/** 5: Repeated IO operation. */
+#define VMX_EXIT_QUAL_IO_IS_REP(a) (((a) >> 5) & 1)
+/** 6: Operand encoding. */
+#define VMX_EXIT_QUAL_IO_ENCODING(a) (((a) >> 6) & 1)
+/** 16-31: IO Port (0-0xffff). */
+#define VMX_EXIT_QUAL_IO_PORT(a) (((a) >> 16) & 0xffff)
+
+/** Bit fields for Exit qualification for I/O instructions. */
+#define VMX_BF_EXIT_QUAL_IO_WIDTH_SHIFT 0
+#define VMX_BF_EXIT_QUAL_IO_WIDTH_MASK UINT64_C(0x0000000000000007)
+#define VMX_BF_EXIT_QUAL_IO_DIRECTION_SHIFT 3
+#define VMX_BF_EXIT_QUAL_IO_DIRECTION_MASK UINT64_C(0x0000000000000008)
+#define VMX_BF_EXIT_QUAL_IO_IS_STRING_SHIFT 4
+#define VMX_BF_EXIT_QUAL_IO_IS_STRING_MASK UINT64_C(0x0000000000000010)
+#define VMX_BF_EXIT_QUAL_IO_IS_REP_SHIFT 5
+#define VMX_BF_EXIT_QUAL_IO_IS_REP_MASK UINT64_C(0x0000000000000020)
+#define VMX_BF_EXIT_QUAL_IO_ENCODING_SHIFT 6
+#define VMX_BF_EXIT_QUAL_IO_ENCODING_MASK UINT64_C(0x0000000000000040)
+#define VMX_BF_EXIT_QUAL_IO_RSVD_7_15_SHIFT 7
+#define VMX_BF_EXIT_QUAL_IO_RSVD_7_15_MASK UINT64_C(0x000000000000ff80)
+#define VMX_BF_EXIT_QUAL_IO_PORT_SHIFT 16
+#define VMX_BF_EXIT_QUAL_IO_PORT_MASK UINT64_C(0x00000000ffff0000)
+#define VMX_BF_EXIT_QUAL_IO_RSVD_32_63_SHIFT 32
+#define VMX_BF_EXIT_QUAL_IO_RSVD_32_63_MASK UINT64_C(0xffffffff00000000)
+RT_BF_ASSERT_COMPILE_CHECKS(VMX_BF_EXIT_QUAL_IO_, UINT64_C(0), UINT64_MAX,
+ (WIDTH, DIRECTION, IS_STRING, IS_REP, ENCODING, RSVD_7_15, PORT, RSVD_32_63));
+/** @} */
+
+
+/** @name Exit qualification for I/O instruction types.
+ * @{
+ */
+#define VMX_EXIT_QUAL_IO_DIRECTION_OUT 0
+#define VMX_EXIT_QUAL_IO_DIRECTION_IN 1
+/** @} */
+
+
+/** @name Exit qualification for I/O instruction encoding.
+ * @{
+ */
+#define VMX_EXIT_QUAL_IO_ENCODING_DX 0
+#define VMX_EXIT_QUAL_IO_ENCODING_IMM 1
+/** @} */
+
+
+/** @name Exit qualification for APIC-access VM-exits from linear and
+ * guest-physical accesses.
+ * @{
+ */
+/** 0-11: If the APIC-access VM-exit is due to a linear access, the offset of
+ * access within the APIC page. */
+#define VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(a) ((a) & 0xfff)
+/** 12-15: Access type. */
+#define VMX_EXIT_QUAL_APIC_ACCESS_TYPE(a) (((a) & 0xf000) >> 12)
+/* Rest reserved. */
+
+/** Bit fields for Exit qualification for APIC-access VM-exits. */
+#define VMX_BF_EXIT_QUAL_APIC_ACCESS_OFFSET_SHIFT 0
+#define VMX_BF_EXIT_QUAL_APIC_ACCESS_OFFSET_MASK UINT64_C(0x0000000000000fff)
+#define VMX_BF_EXIT_QUAL_APIC_ACCESS_TYPE_SHIFT 12
+#define VMX_BF_EXIT_QUAL_APIC_ACCESS_TYPE_MASK UINT64_C(0x000000000000f000)
+#define VMX_BF_EXIT_QUAL_APIC_ACCESS_RSVD_16_63_SHIFT 16
+#define VMX_BF_EXIT_QUAL_APIC_ACCESS_RSVD_16_63_MASK UINT64_C(0xffffffffffff0000)
+RT_BF_ASSERT_COMPILE_CHECKS(VMX_BF_EXIT_QUAL_APIC_ACCESS_, UINT64_C(0), UINT64_MAX,
+ (OFFSET, TYPE, RSVD_16_63));
+/** @} */
+
+
+/** @name Exit qualification for linear address APIC-access types.
+ * @{
+ */
+/** Linear access for a data read during instruction execution. */
+#define VMX_APIC_ACCESS_TYPE_LINEAR_READ 0
+/** Linear access for a data write during instruction execution. */
+#define VMX_APIC_ACCESS_TYPE_LINEAR_WRITE 1
+/** Linear access for an instruction fetch. */
+#define VMX_APIC_ACCESS_TYPE_LINEAR_INSTR_FETCH 2
+/** Linear read/write access during event delivery. */
+#define VMX_APIC_ACCESS_TYPE_LINEAR_EVENT_DELIVERY 3
+/** Physical read/write access during event delivery. */
+#define VMX_APIC_ACCESS_TYPE_PHYSICAL_EVENT_DELIVERY 10
+/** Physical access for an instruction fetch or during instruction execution. */
+#define VMX_APIC_ACCESS_TYPE_PHYSICAL_INSTR 15
+
+/**
+ * APIC-access type.
+ * In accordance with the VT-x spec.
+ */
+typedef enum
+{
+ VMXAPICACCESS_LINEAR_READ = VMX_APIC_ACCESS_TYPE_LINEAR_READ,
+ VMXAPICACCESS_LINEAR_WRITE = VMX_APIC_ACCESS_TYPE_LINEAR_WRITE,
+ VMXAPICACCESS_LINEAR_INSTR_FETCH = VMX_APIC_ACCESS_TYPE_LINEAR_INSTR_FETCH,
+ VMXAPICACCESS_LINEAR_EVENT_DELIVERY = VMX_APIC_ACCESS_TYPE_LINEAR_EVENT_DELIVERY,
+ VMXAPICACCESS_PHYSICAL_EVENT_DELIVERY = VMX_APIC_ACCESS_TYPE_PHYSICAL_EVENT_DELIVERY,
+ VMXAPICACCESS_PHYSICAL_INSTR = VMX_APIC_ACCESS_TYPE_PHYSICAL_INSTR
+} VMXAPICACCESS;
+AssertCompileSize(VMXAPICACCESS, 4);
+/** @} */
+
+
+/** @name VMX_BF_XXTR_INSINFO_XXX - VMX_EXIT_XDTR_ACCESS instruction information.
+ * Found in VMX_VMCS32_RO_EXIT_INSTR_INFO.
+ * @{
+ */
+/** Address calculation scaling field (powers of two). */
+#define VMX_BF_XDTR_INSINFO_SCALE_SHIFT 0
+#define VMX_BF_XDTR_INSINFO_SCALE_MASK UINT32_C(0x00000003)
+/** Bits 2 thru 6 are undefined. */
+#define VMX_BF_XDTR_INSINFO_UNDEF_2_6_SHIFT 2
+#define VMX_BF_XDTR_INSINFO_UNDEF_2_6_MASK UINT32_C(0x0000007c)
+/** Address size, only 0(=16), 1(=32) and 2(=64) are defined.
+ * @remarks anyone's guess why this is a 3 bit field... */
+#define VMX_BF_XDTR_INSINFO_ADDR_SIZE_SHIFT 7
+#define VMX_BF_XDTR_INSINFO_ADDR_SIZE_MASK UINT32_C(0x00000380)
+/** Bit 10 is defined as zero. */
+#define VMX_BF_XDTR_INSINFO_ZERO_10_SHIFT 10
+#define VMX_BF_XDTR_INSINFO_ZERO_10_MASK UINT32_C(0x00000400)
+/** Operand size, either (1=)32-bit or (0=)16-bit, but get this, it's undefined
+ * for exits from 64-bit code as the operand size there is fixed. */
+#define VMX_BF_XDTR_INSINFO_OP_SIZE_SHIFT 11
+#define VMX_BF_XDTR_INSINFO_OP_SIZE_MASK UINT32_C(0x00000800)
+/** Bits 12 thru 14 are undefined. */
+#define VMX_BF_XDTR_INSINFO_UNDEF_12_14_SHIFT 12
+#define VMX_BF_XDTR_INSINFO_UNDEF_12_14_MASK UINT32_C(0x00007000)
+/** Applicable segment register (X86_SREG_XXX values). */
+#define VMX_BF_XDTR_INSINFO_SREG_SHIFT 15
+#define VMX_BF_XDTR_INSINFO_SREG_MASK UINT32_C(0x00038000)
+/** Index register (X86_GREG_XXX values). Undefined if HAS_INDEX_REG is clear. */
+#define VMX_BF_XDTR_INSINFO_INDEX_REG_SHIFT 18
+#define VMX_BF_XDTR_INSINFO_INDEX_REG_MASK UINT32_C(0x003c0000)
+/** Is VMX_BF_XDTR_INSINFO_INDEX_REG_XXX valid (=1) or not (=0). */
+#define VMX_BF_XDTR_INSINFO_HAS_INDEX_REG_SHIFT 22
+#define VMX_BF_XDTR_INSINFO_HAS_INDEX_REG_MASK UINT32_C(0x00400000)
+/** Base register (X86_GREG_XXX values). Undefined if HAS_BASE_REG is clear. */
+#define VMX_BF_XDTR_INSINFO_BASE_REG_SHIFT 23
+#define VMX_BF_XDTR_INSINFO_BASE_REG_MASK UINT32_C(0x07800000)
+/** Is VMX_XDTR_INSINFO_BASE_REG_XXX valid (=1) or not (=0). */
+#define VMX_BF_XDTR_INSINFO_HAS_BASE_REG_SHIFT 27
+#define VMX_BF_XDTR_INSINFO_HAS_BASE_REG_MASK UINT32_C(0x08000000)
+/** The instruction identity (VMX_XDTR_INSINFO_II_XXX values). */
+#define VMX_BF_XDTR_INSINFO_INSTR_ID_SHIFT 28
+#define VMX_BF_XDTR_INSINFO_INSTR_ID_MASK UINT32_C(0x30000000)
+#define VMX_XDTR_INSINFO_II_SGDT 0 /**< Instruction ID: SGDT */
+#define VMX_XDTR_INSINFO_II_SIDT 1 /**< Instruction ID: SIDT */
+#define VMX_XDTR_INSINFO_II_LGDT 2 /**< Instruction ID: LGDT */
+#define VMX_XDTR_INSINFO_II_LIDT 3 /**< Instruction ID: LIDT */
+/** Bits 30 & 31 are undefined. */
+#define VMX_BF_XDTR_INSINFO_UNDEF_30_31_SHIFT 30
+#define VMX_BF_XDTR_INSINFO_UNDEF_30_31_MASK UINT32_C(0xc0000000)
+RT_BF_ASSERT_COMPILE_CHECKS(VMX_BF_XDTR_INSINFO_, UINT32_C(0), UINT32_MAX,
+ (SCALE, UNDEF_2_6, ADDR_SIZE, ZERO_10, OP_SIZE, UNDEF_12_14, SREG, INDEX_REG, HAS_INDEX_REG,
+ BASE_REG, HAS_BASE_REG, INSTR_ID, UNDEF_30_31));
+/** @} */
+
+
+/** @name VMX_BF_YYTR_INSINFO_XXX - VMX_EXIT_TR_ACCESS instruction information.
+ * Found in VMX_VMCS32_RO_EXIT_INSTR_INFO.
+ * This is similar to VMX_BF_XDTR_INSINFO_XXX.
+ * @{
+ */
+/** Address calculation scaling field (powers of two). */
+#define VMX_BF_YYTR_INSINFO_SCALE_SHIFT 0
+#define VMX_BF_YYTR_INSINFO_SCALE_MASK UINT32_C(0x00000003)
+/** Bit 2 is undefined. */
+#define VMX_BF_YYTR_INSINFO_UNDEF_2_SHIFT 2
+#define VMX_BF_YYTR_INSINFO_UNDEF_2_MASK UINT32_C(0x00000004)
+/** Register operand 1. Undefined if VMX_YYTR_INSINFO_HAS_REG1 is clear. */
+#define VMX_BF_YYTR_INSINFO_REG1_SHIFT 3
+#define VMX_BF_YYTR_INSINFO_REG1_MASK UINT32_C(0x00000078)
+/** Address size, only 0(=16), 1(=32) and 2(=64) are defined.
+ * @remarks anyone's guess why this is a 3 bit field... */
+#define VMX_BF_YYTR_INSINFO_ADDR_SIZE_SHIFT 7
+#define VMX_BF_YYTR_INSINFO_ADDR_SIZE_MASK UINT32_C(0x00000380)
+/** Is VMX_YYTR_INSINFO_REG1_XXX valid (=1) or not (=0). */
+#define VMX_BF_YYTR_INSINFO_HAS_REG1_SHIFT 10
+#define VMX_BF_YYTR_INSINFO_HAS_REG1_MASK UINT32_C(0x00000400)
+/** Bits 11 thru 14 are undefined. */
+#define VMX_BF_YYTR_INSINFO_UNDEF_11_14_SHIFT 11
+#define VMX_BF_YYTR_INSINFO_UNDEF_11_14_MASK UINT32_C(0x00007800)
+/** Applicable segment register (X86_SREG_XXX values). */
+#define VMX_BF_YYTR_INSINFO_SREG_SHIFT 15
+#define VMX_BF_YYTR_INSINFO_SREG_MASK UINT32_C(0x00038000)
+/** Index register (X86_GREG_XXX values). Undefined if HAS_INDEX_REG is clear. */
+#define VMX_BF_YYTR_INSINFO_INDEX_REG_SHIFT 18
+#define VMX_BF_YYTR_INSINFO_INDEX_REG_MASK UINT32_C(0x003c0000)
+/** Is VMX_YYTR_INSINFO_INDEX_REG_XXX valid (=1) or not (=0). */
+#define VMX_BF_YYTR_INSINFO_HAS_INDEX_REG_SHIFT 22
+#define VMX_BF_YYTR_INSINFO_HAS_INDEX_REG_MASK UINT32_C(0x00400000)
+/** Base register (X86_GREG_XXX values). Undefined if HAS_BASE_REG is clear. */
+#define VMX_BF_YYTR_INSINFO_BASE_REG_SHIFT 23
+#define VMX_BF_YYTR_INSINFO_BASE_REG_MASK UINT32_C(0x07800000)
+/** Is VMX_YYTR_INSINFO_BASE_REG_XXX valid (=1) or not (=0). */
+#define VMX_BF_YYTR_INSINFO_HAS_BASE_REG_SHIFT 27
+#define VMX_BF_YYTR_INSINFO_HAS_BASE_REG_MASK UINT32_C(0x08000000)
+/** The instruction identity (VMX_YYTR_INSINFO_II_XXX values) */
+#define VMX_BF_YYTR_INSINFO_INSTR_ID_SHIFT 28
+#define VMX_BF_YYTR_INSINFO_INSTR_ID_MASK UINT32_C(0x30000000)
+#define VMX_YYTR_INSINFO_II_SLDT 0 /**< Instruction ID: SLDT */
+#define VMX_YYTR_INSINFO_II_STR 1 /**< Instruction ID: STR */
+#define VMX_YYTR_INSINFO_II_LLDT 2 /**< Instruction ID: LLDT */
+#define VMX_YYTR_INSINFO_II_LTR 3 /**< Instruction ID: LTR */
+/** Bits 30 & 31 are undefined. */
+#define VMX_BF_YYTR_INSINFO_UNDEF_30_31_SHIFT 30
+#define VMX_BF_YYTR_INSINFO_UNDEF_30_31_MASK UINT32_C(0xc0000000)
+RT_BF_ASSERT_COMPILE_CHECKS(VMX_BF_YYTR_INSINFO_, UINT32_C(0), UINT32_MAX,
+ (SCALE, UNDEF_2, REG1, ADDR_SIZE, HAS_REG1, UNDEF_11_14, SREG, INDEX_REG, HAS_INDEX_REG,
+ BASE_REG, HAS_BASE_REG, INSTR_ID, UNDEF_30_31));
+/** @} */
+
+
+/** @name Format of Pending-Debug-Exceptions.
+ * Bits 4-11, 13, 15 and 17-63 are reserved.
+ * Similar to DR6 except bit 12 (breakpoint enabled) and bit 16 (RTM) are both
+ * possibly valid here but not in DR6.
+ * @{
+ */
+/** Hardware breakpoint 0 was met. */
+#define VMX_VMCS_GUEST_PENDING_DEBUG_XCPT_BP0 RT_BIT_64(0)
+/** Hardware breakpoint 1 was met. */
+#define VMX_VMCS_GUEST_PENDING_DEBUG_XCPT_BP1 RT_BIT_64(1)
+/** Hardware breakpoint 2 was met. */
+#define VMX_VMCS_GUEST_PENDING_DEBUG_XCPT_BP2 RT_BIT_64(2)
+/** Hardware breakpoint 3 was met. */
+#define VMX_VMCS_GUEST_PENDING_DEBUG_XCPT_BP3 RT_BIT_64(3)
+/** At least one data or IO breakpoint was hit. */
+#define VMX_VMCS_GUEST_PENDING_DEBUG_XCPT_EN_BP RT_BIT_64(12)
+/** A debug exception would have been triggered by single-step execution mode. */
+#define VMX_VMCS_GUEST_PENDING_DEBUG_XCPT_BS RT_BIT_64(14)
+/** A debug exception occurred inside an RTM region. */
+#define VMX_VMCS_GUEST_PENDING_DEBUG_RTM RT_BIT_64(16)
+/** Mask of valid bits. */
+#define VMX_VMCS_GUEST_PENDING_DEBUG_VALID_MASK ( VMX_VMCS_GUEST_PENDING_DEBUG_XCPT_BP0 \
+ | VMX_VMCS_GUEST_PENDING_DEBUG_XCPT_BP1 \
+ | VMX_VMCS_GUEST_PENDING_DEBUG_XCPT_BP2 \
+ | VMX_VMCS_GUEST_PENDING_DEBUG_XCPT_BP3 \
+ | VMX_VMCS_GUEST_PENDING_DEBUG_XCPT_EN_BP \
+ | VMX_VMCS_GUEST_PENDING_DEBUG_XCPT_BS \
+ | VMX_VMCS_GUEST_PENDING_DEBUG_RTM)
+#define VMX_VMCS_GUEST_PENDING_DEBUG_RTM_MASK ( VMX_VMCS_GUEST_PENDING_DEBUG_XCPT_EN_BP \
+ | VMX_VMCS_GUEST_PENDING_DEBUG_XCPT_BS \
+ | VMX_VMCS_GUEST_PENDING_DEBUG_RTM)
+/** Bit fields for Pending debug exceptions. */
+#define VMX_BF_VMCS_PENDING_DBG_XCPT_BP0_SHIFT 0
+#define VMX_BF_VMCS_PENDING_DBG_XCPT_BP0_MASK UINT64_C(0x0000000000000001)
+#define VMX_BF_VMCS_PENDING_DBG_XCPT_BP1_SHIFT 1
+#define VMX_BF_VMCS_PENDING_DBG_XCPT_BP1_MASK UINT64_C(0x0000000000000002)
+#define VMX_BF_VMCS_PENDING_DBG_XCPT_BP2_SHIFT 2
+#define VMX_BF_VMCS_PENDING_DBG_XCPT_BP2_MASK UINT64_C(0x0000000000000004)
+#define VMX_BF_VMCS_PENDING_DBG_XCPT_BP3_SHIFT 3
+#define VMX_BF_VMCS_PENDING_DBG_XCPT_BP3_MASK UINT64_C(0x0000000000000008)
+#define VMX_BF_VMCS_PENDING_DBG_XCPT_RSVD_4_11_SHIFT 4
+#define VMX_BF_VMCS_PENDING_DBG_XCPT_RSVD_4_11_MASK UINT64_C(0x0000000000000ff0)
+#define VMX_BF_VMCS_PENDING_DBG_XCPT_EN_BP_SHIFT 12
+#define VMX_BF_VMCS_PENDING_DBG_XCPT_EN_BP_MASK UINT64_C(0x0000000000001000)
+#define VMX_BF_VMCS_PENDING_DBG_XCPT_RSVD_13_SHIFT 13
+#define VMX_BF_VMCS_PENDING_DBG_XCPT_RSVD_13_MASK UINT64_C(0x0000000000002000)
+#define VMX_BF_VMCS_PENDING_DBG_XCPT_BS_SHIFT 14
+#define VMX_BF_VMCS_PENDING_DBG_XCPT_BS_MASK UINT64_C(0x0000000000004000)
+#define VMX_BF_VMCS_PENDING_DBG_XCPT_RSVD_15_SHIFT 15
+#define VMX_BF_VMCS_PENDING_DBG_XCPT_RSVD_15_MASK UINT64_C(0x0000000000008000)
+#define VMX_BF_VMCS_PENDING_DBG_XCPT_RTM_SHIFT 16
+#define VMX_BF_VMCS_PENDING_DBG_XCPT_RTM_MASK UINT64_C(0x0000000000010000)
+#define VMX_BF_VMCS_PENDING_DBG_XCPT_RSVD_17_63_SHIFT 17
+#define VMX_BF_VMCS_PENDING_DBG_XCPT_RSVD_17_63_MASK UINT64_C(0xfffffffffffe0000)
+RT_BF_ASSERT_COMPILE_CHECKS(VMX_BF_VMCS_PENDING_DBG_XCPT_, UINT64_C(0), UINT64_MAX,
+ (BP0, BP1, BP2, BP3, RSVD_4_11, EN_BP, RSVD_13, BS, RSVD_15, RTM, RSVD_17_63));
+/** @} */
+
+
+/**
+ * VM-exit auxiliary information.
+ *
+ * This includes information that isn't necessarily stored in the guest-CPU
+ * context but provided as part of VM-exits.
+ */
+typedef struct
+{
+ /** The VM-exit reason. */
+ uint32_t uReason;
+ /** The Exit qualification field. */
+ uint64_t u64Qual;
+ /** The Guest-linear address field. */
+ uint64_t u64GuestLinearAddr;
+ /** The Guest-physical address field. */
+ uint64_t u64GuestPhysAddr;
+ /** The guest pending-debug exceptions. */
+ uint64_t u64GuestPendingDbgXcpts;
+ /** The VM-exit instruction length. */
+ uint32_t cbInstr;
+ /** The VM-exit instruction information. */
+ VMXEXITINSTRINFO InstrInfo;
+ /** VM-exit interruption information. */
+ uint32_t uExitIntInfo;
+ /** VM-exit interruption error code. */
+ uint32_t uExitIntErrCode;
+ /** IDT-vectoring information. */
+ uint32_t uIdtVectoringInfo;
+ /** IDT-vectoring error code. */
+ uint32_t uIdtVectoringErrCode;
+} VMXEXITAUX;
+/** Pointer to a VMXEXITAUX struct. */
+typedef VMXEXITAUX *PVMXEXITAUX;
+/** Pointer to a const VMXEXITAUX struct. */
+typedef const VMXEXITAUX *PCVMXEXITAUX;
+
+
+/** @defgroup grp_hm_vmx_virt VMX virtualization.
+ * @{
+ */
+
+/** @name Virtual VMX MSR - Miscellaneous data.
+ * @{ */
+/** Number of CR3-target values supported. */
+#define VMX_V_CR3_TARGET_COUNT 4
+/** Activity states supported. */
+#define VMX_V_GUEST_ACTIVITY_STATE_MASK (VMX_VMCS_GUEST_ACTIVITY_HLT | VMX_VMCS_GUEST_ACTIVITY_SHUTDOWN)
+/** VMX preemption-timer shift (Core i7-2600 taken as reference). */
+#define VMX_V_PREEMPT_TIMER_SHIFT 5
+/** Maximum number of MSRs in the auto-load/store MSR areas, (n+1) * 512. */
+#define VMX_V_AUTOMSR_COUNT_MAX 0
+/** SMM MSEG revision ID. */
+#define VMX_V_MSEG_REV_ID 0
+/** @} */
+
+/** @name VMX_V_VMCS_STATE_XXX - Virtual VMCS launch state.
+ * @{ */
+/** VMCS launch state clear. */
+#define VMX_V_VMCS_LAUNCH_STATE_CLEAR RT_BIT(0)
+/** VMCS launch state active. */
+#define VMX_V_VMCS_LAUNCH_STATE_ACTIVE RT_BIT(1)
+/** VMCS launch state current. */
+#define VMX_V_VMCS_LAUNCH_STATE_CURRENT RT_BIT(2)
+/** VMCS launch state launched. */
+#define VMX_V_VMCS_LAUNCH_STATE_LAUNCHED RT_BIT(3)
+/** The mask of valid VMCS launch states. */
+#define VMX_V_VMCS_LAUNCH_STATE_MASK ( VMX_V_VMCS_LAUNCH_STATE_CLEAR \
+ | VMX_V_VMCS_LAUNCH_STATE_ACTIVE \
+ | VMX_V_VMCS_LAUNCH_STATE_CURRENT \
+ | VMX_V_VMCS_LAUNCH_STATE_LAUNCHED)
+/** @} */
+
+/** CR0 bits set here must always be set when in VMX operation. */
+#define VMX_V_CR0_FIXED0 (X86_CR0_PE | X86_CR0_NE | X86_CR0_PG)
+/** CR0 bits set here must always be set when in VMX non-root operation with
+ * unrestricted-guest control enabled. */
+#define VMX_V_CR0_FIXED0_UX (X86_CR0_NE)
+/** CR0 bits cleared here must always be cleared when in VMX operation. */
+#define VMX_V_CR0_FIXED1 UINT32_C(0xffffffff)
+/** CR4 bits set here must always be set when in VMX operation. */
+#define VMX_V_CR4_FIXED0 (X86_CR4_VMXE)
+
+/** Virtual VMCS revision ID. Bump this arbitarily chosen identifier if incompatible
+ * changes to the layout of VMXVVMCS is done. Bit 31 MBZ. */
+#define VMX_V_VMCS_REVISION_ID UINT32_C(0x40000001)
+AssertCompile(!(VMX_V_VMCS_REVISION_ID & RT_BIT(31)));
+
+/** The size of the virtual VMCS region (we use the maximum allowed size to avoid
+ * complications when teleporation may be implemented). */
+#define VMX_V_VMCS_SIZE X86_PAGE_4K_SIZE
+/** The size of the virtual VMCS region (in pages). */
+#define VMX_V_VMCS_PAGES 1
+
+/** The size of the virtual shadow VMCS region. */
+#define VMX_V_SHADOW_VMCS_SIZE VMX_V_VMCS_SIZE
+/** The size of the virtual shadow VMCS region (in pages). */
+#define VMX_V_SHADOW_VMCS_PAGES VMX_V_VMCS_PAGES
+
+/** The size of the Virtual-APIC page (in bytes). */
+#define VMX_V_VIRT_APIC_SIZE X86_PAGE_4K_SIZE
+/** The size of the Virtual-APIC page (in pages). */
+#define VMX_V_VIRT_APIC_PAGES 1
+
+/** The size of the VMREAD/VMWRITE bitmap (in bytes). */
+#define VMX_V_VMREAD_VMWRITE_BITMAP_SIZE X86_PAGE_4K_SIZE
+/** The size of the VMREAD/VMWRITE-bitmap (in pages). */
+#define VMX_V_VMREAD_VMWRITE_BITMAP_PAGES 1
+
+/** The size of the MSR bitmap (in bytes). */
+#define VMX_V_MSR_BITMAP_SIZE X86_PAGE_4K_SIZE
+/** The size of the MSR bitmap (in pages). */
+#define VMX_V_MSR_BITMAP_PAGES 1
+
+/** The size of I/O bitmap A (in bytes). */
+#define VMX_V_IO_BITMAP_A_SIZE X86_PAGE_4K_SIZE
+/** The size of I/O bitmap A (in pages). */
+#define VMX_V_IO_BITMAP_A_PAGES 1
+
+/** The size of I/O bitmap B (in bytes). */
+#define VMX_V_IO_BITMAP_B_SIZE X86_PAGE_4K_SIZE
+/** The size of I/O bitmap B (in pages). */
+#define VMX_V_IO_BITMAP_B_PAGES 1
+
+/** The size of the auto-load/store MSR area (in bytes). */
+#define VMX_V_AUTOMSR_AREA_SIZE ((512 * (VMX_V_AUTOMSR_COUNT_MAX + 1)) * sizeof(VMXAUTOMSR))
+/* Assert that the size is page aligned or adjust the VMX_V_AUTOMSR_AREA_PAGES macro below. */
+AssertCompile(RT_ALIGN_Z(VMX_V_AUTOMSR_AREA_SIZE, X86_PAGE_4K_SIZE) == VMX_V_AUTOMSR_AREA_SIZE);
+/** The size of the auto-load/store MSR area (in pages). */
+#define VMX_V_AUTOMSR_AREA_PAGES ((VMX_V_AUTOMSR_AREA_SIZE) >> X86_PAGE_4K_SHIFT)
+
+/** The highest index value used for supported virtual VMCS field encoding. */
+#define VMX_V_VMCS_MAX_INDEX RT_BF_GET(VMX_VMCS64_CTRL_EXIT2_HIGH, VMX_BF_VMCSFIELD_INDEX)
+
+/**
+ * Virtual VM-exit information.
+ *
+ * This is a convenience structure that bundles some VM-exit information related
+ * fields together.
+ */
+typedef struct
+{
+ /** The VM-exit reason. */
+ uint32_t uReason;
+ /** The VM-exit instruction length. */
+ uint32_t cbInstr;
+ /** The VM-exit instruction information. */
+ VMXEXITINSTRINFO InstrInfo;
+ /** The VM-exit instruction ID. */
+ VMXINSTRID uInstrId;
+
+ /** The Exit qualification field. */
+ uint64_t u64Qual;
+ /** The Guest-linear address field. */
+ uint64_t u64GuestLinearAddr;
+ /** The Guest-physical address field. */
+ uint64_t u64GuestPhysAddr;
+ /** The guest pending-debug exceptions. */
+ uint64_t u64GuestPendingDbgXcpts;
+ /** The effective guest-linear address if @a InstrInfo indicates a memory-based
+ * instruction VM-exit. */
+ RTGCPTR GCPtrEffAddr;
+} VMXVEXITINFO;
+/** Pointer to the VMXVEXITINFO struct. */
+typedef VMXVEXITINFO *PVMXVEXITINFO;
+/** Pointer to a const VMXVEXITINFO struct. */
+typedef const VMXVEXITINFO *PCVMXVEXITINFO;
+AssertCompileMemberAlignment(VMXVEXITINFO, u64Qual, 8);
+
+/** Initialize a VMXVEXITINFO structure from only an exit reason. */
+#define VMXVEXITINFO_INIT_ONLY_REASON(a_uReason) \
+ { (a_uReason), 0, { 0 }, VMXINSTRID_NONE, 0, 0, 0, 0, 0 }
+
+/** Initialize a VMXVEXITINFO structure from exit reason and instruction length (no info). */
+#define VMXVEXITINFO_INIT_WITH_INSTR_LEN(a_uReason, a_cbInstr) \
+ { (a_uReason), (a_cbInstr), { 0 }, VMXINSTRID_NONE, 0, 0, 0, 0, 0 }
+
+/** Initialize a VMXVEXITINFO structure from exit reason and exit qualification. */
+#define VMXVEXITINFO_INIT_WITH_QUAL(a_uReason, a_uQual) \
+ { (a_uReason), 0, { 0 }, VMXINSTRID_NONE, (a_uQual), 0, 0, 0, 0 }
+
+/** Initialize a VMXVEXITINFO structure from exit reason, exit qualification,
+ * instruction info and length. */
+#define VMXVEXITINFO_INIT_WITH_QUAL_AND_INSTR_INFO(a_uReason, a_uQual, a_uInstrInfo, a_cbInstr) \
+ { (a_uReason), (a_cbInstr), { a_uInstrInfo }, VMXINSTRID_NONE, (a_uQual), 0, 0, 0, 0 }
+
+/** Initialize a VMXVEXITINFO structure from exit reason, exit qualification,
+ * instruction info and length all copied from a VMXTRANSIENT structure. */
+#define VMXVEXITINFO_INIT_WITH_QUAL_AND_INSTR_INFO_FROM_TRANSIENT(a_pVmxTransient) \
+ VMXVEXITINFO_INIT_WITH_QUAL_AND_INSTR_INFO((a_pVmxTransient)->uExitReason, \
+ (a_pVmxTransient)->uExitQual, \
+ (a_pVmxTransient)->ExitInstrInfo.u, \
+ (a_pVmxTransient)->cbExitInstr)
+
+/** Initialize a VMXVEXITINFO structure from exit reason, exit qualification,
+ * instruction length (no info). */
+#define VMXVEXITINFO_INIT_WITH_QUAL_AND_INSTR_LEN(a_uReason, a_uQual, a_cbInstr) \
+ { (a_uReason), (a_cbInstr), { 0 }, VMXINSTRID_NONE, (a_uQual), 0, 0, 0, 0 }
+
+/** Initialize a VMXVEXITINFO structure from exit reason, exit qualification and
+ * instruction length (no info) all copied from a VMXTRANSIENT structure. */
+#define VMXVEXITINFO_INIT_WITH_QUAL_AND_INSTR_LEN_FROM_TRANSIENT(a_pVmxTransient) \
+ VMXVEXITINFO_INIT_WITH_QUAL_AND_INSTR_LEN((a_pVmxTransient)->uExitReason, \
+ (a_pVmxTransient)->uExitQual, \
+ (a_pVmxTransient)->cbExitInstr)
+
+/** Initialize a VMXVEXITINFO structure from exit reason, exit qualification,
+ * instruction info, instruction length and guest linear address. */
+#define VMXVEXITINFO_INIT_WITH_QUAL_AND_INSTR_INFO_AND_LIN_ADDR(a_uReason, a_uQual, a_uInstrInfo, \
+ a_cbInstr, a_uGstLinAddr) \
+ { (a_uReason), (a_cbInstr), { (a_uInstrInfo) }, VMXINSTRID_NONE, (a_uQual), (a_uGstLinAddr), 0, 0, 0 }
+
+/** Initialize a VMXVEXITINFO structure from exit reason, exit qualification,
+ * instruction info, instruction length and guest linear address all copied
+ * from a VMXTRANSIENT structure. */
+#define VMXVEXITINFO_INIT_WITH_QUAL_AND_INSTR_INFO_AND_LIN_ADDR_FROM_TRANSIENT(a_pVmxTransient) \
+ VMXVEXITINFO_INIT_WITH_QUAL_AND_INSTR_INFO_AND_LIN_ADDR((a_pVmxTransient)->uExitReason, \
+ (a_pVmxTransient)->uExitQual, \
+ (a_pVmxTransient)->ExitInstrInfo.u, \
+ (a_pVmxTransient)->cbExitInstr, \
+ (a_pVmxTransient)->uGuestLinearAddr)
+
+/** Initialize a VMXVEXITINFO structure from exit reason and pending debug
+ * exceptions. */
+#define VMXVEXITINFO_INIT_WITH_DBG_XCPTS(a_uReason, a_uPendingDbgXcpts) \
+ { (a_uReason), 0, { 0 }, VMXINSTRID_NONE, 0, 0, 0, (a_uPendingDbgXcpts), 0 }
+
+/** Initialize a VMXVEXITINFO structure from exit reason and pending debug
+ * exceptions both copied from a VMXTRANSIENT structure. */
+#define VMXVEXITINFO_INIT_WITH_DBG_XCPTS_FROM_TRANSIENT(a_pVmxTransient) \
+ VMXVEXITINFO_INIT_WITH_DBG_XCPTS((a_pVmxTransient)->uExitReason, (a_pVmxTransient)->uGuestPendingDbgXcpts)
+
+
+/** Initialize a VMXVEXITINFO structure from exit reason, exit qualification,
+ * instruction length, guest linear address and guest physical address. */
+#define VMXVEXITINFO_INIT_WITH_QUAL_AND_INSTR_LEN_AND_GST_ADDRESSES(a_uReason, a_uQual, a_cbInstr, \
+ a_uGstLinAddr, a_uGstPhysAddr) \
+ { (a_uReason), (a_cbInstr), { 0 }, VMXINSTRID_NONE, (a_uQual), (a_uGstLinAddr), (a_uGstPhysAddr), 0, 0 }
+
+
+/**
+ * Virtual VM-exit information for events.
+ *
+ * This is a convenience structure that bundles some event-based VM-exit information
+ * related fields together that are not included in VMXVEXITINFO.
+ *
+ * This is kept as a separate structure and not included in VMXVEXITINFO, to make it
+ * easier to distinguish that IEM VM-exit handlers will set one or more of the
+ * following fields in the virtual VMCS. Including it in the VMXVEXITINFO will not
+ * make it ovbious which fields may get set (or cleared).
+ */
+typedef struct
+{
+ /** VM-exit interruption information. */
+ uint32_t uExitIntInfo;
+ /** VM-exit interruption error code. */
+ uint32_t uExitIntErrCode;
+ /** IDT-vectoring information. */
+ uint32_t uIdtVectoringInfo;
+ /** IDT-vectoring error code. */
+ uint32_t uIdtVectoringErrCode;
+} VMXVEXITEVENTINFO;
+/** Pointer to the VMXVEXITEVENTINFO struct. */
+typedef VMXVEXITEVENTINFO *PVMXVEXITEVENTINFO;
+/** Pointer to a const VMXVEXITEVENTINFO struct. */
+typedef const VMXVEXITEVENTINFO *PCVMXVEXITEVENTINFO;
+
+/** Initialize a VMXVEXITEVENTINFO. */
+#define VMXVEXITEVENTINFO_INIT(a_uExitIntInfo, a_uExitIntErrCode, a_uIdtVectoringInfo, a_uIdtVectoringErrCode) \
+ { (a_uExitIntInfo), (a_uExitIntErrCode), (a_uIdtVectoringInfo), (a_uIdtVectoringErrCode) }
+
+/** Initialize a VMXVEXITEVENTINFO with VM-exit interruption info and VM-exit
+ * interruption error code. */
+#define VMXVEXITEVENTINFO_INIT_ONLY_INT(a_uExitIntInfo, a_uExitIntErrCode) \
+ VMXVEXITEVENTINFO_INIT(a_uExitIntInfo, a_uExitIntErrCode, 0, 0)
+
+/** Initialize a VMXVEXITEVENTINFO with IDT vectoring info and IDT
+ * vectoring error code. */
+#define VMXVEXITEVENTINFO_INIT_ONLY_IDT(a_uIdtVectoringInfo, a_uIdtVectoringErrCode) \
+ VMXVEXITEVENTINFO_INIT(0, 0, a_uIdtVectoringInfo, a_uIdtVectoringErrCode)
+
+/**
+ * Virtual VMCS.
+ *
+ * This is our custom format. Relevant fields from this VMCS will be merged into the
+ * actual/shadow VMCS when we execute nested-guest code using hardware-assisted
+ * VMX.
+ *
+ * The first 8 bytes must be in accordance with the Intel VT-x spec.
+ * See Intel spec. 24.2 "Format of the VMCS Region".
+ *
+ * The offset and size of the VMCS state field (@a fVmcsState) is also fixed (not by
+ * the Intel spec. but for our own requirements) as we use it to offset into guest
+ * memory.
+ *
+ * Although the guest is supposed to access the VMCS only through the execution of
+ * VMX instructions (VMREAD, VMWRITE etc.), since the VMCS may reside in guest
+ * memory (e.g, active but not current VMCS), for saved-states compatibility, and
+ * for teleportation purposes, any newly added fields should be added to the
+ * appropriate reserved sections or at the end of the structure.
+ *
+ * We always treat natural-width fields as 64-bit in our implementation since
+ * it's easier, allows for teleporation in the future and does not affect guest
+ * software.
+ *
+ * @note Any fields that are added or modified here, make sure to update the
+ * corresponding fields in IEM (g_aoffVmcsMap), the corresponding saved
+ * state structure in CPUM (g_aVmxHwvirtVmcs) and bump the SSM version.
+ * Also consider updating CPUMIsGuestVmxVmcsFieldValid and cpumR3InfoVmxVmcs.
+ */
+#pragma pack(1)
+typedef struct
+{
+ /** @name Header.
+ * @{
+ */
+ VMXVMCSREVID u32VmcsRevId; /**< 0x000 - VMX VMCS revision identifier. */
+ VMXABORT enmVmxAbort; /**< 0x004 - VMX-abort indicator. */
+ uint8_t fVmcsState; /**< 0x008 - VMCS launch state, see VMX_V_VMCS_LAUNCH_STATE_XXX. */
+ uint8_t au8Padding0[3]; /**< 0x009 - Reserved for future. */
+ uint32_t au32Reserved0[12]; /**< 0x00c - Reserved for future. */
+ /** @} */
+
+ /** @name Read-only fields.
+ * @{ */
+ /** 16-bit fields. */
+ uint16_t u16Reserved0[14]; /**< 0x03c - Reserved for future. */
+
+ /** 32-bit fields. */
+ uint32_t u32RoVmInstrError; /**< 0x058 - VM-instruction error. */
+ uint32_t u32RoExitReason; /**< 0x05c - VM-exit reason. */
+ uint32_t u32RoExitIntInfo; /**< 0x060 - VM-exit interruption information. */
+ uint32_t u32RoExitIntErrCode; /**< 0x064 - VM-exit interruption error code. */
+ uint32_t u32RoIdtVectoringInfo; /**< 0x068 - IDT-vectoring information. */
+ uint32_t u32RoIdtVectoringErrCode; /**< 0x06c - IDT-vectoring error code. */
+ uint32_t u32RoExitInstrLen; /**< 0x070 - VM-exit instruction length. */
+ uint32_t u32RoExitInstrInfo; /**< 0x074 - VM-exit instruction information. */
+ uint32_t au32RoReserved2[16]; /**< 0x078 - Reserved for future. */
+
+ /** 64-bit fields. */
+ RTUINT64U u64RoGuestPhysAddr; /**< 0x0b8 - Guest-physical address. */
+ RTUINT64U au64Reserved1[8]; /**< 0x0c0 - Reserved for future. */
+
+ /** Natural-width fields. */
+ RTUINT64U u64RoExitQual; /**< 0x100 - Exit qualification. */
+ RTUINT64U u64RoIoRcx; /**< 0x108 - I/O RCX. */
+ RTUINT64U u64RoIoRsi; /**< 0x110 - I/O RSI. */
+ RTUINT64U u64RoIoRdi; /**< 0x118 - I/O RDI. */
+ RTUINT64U u64RoIoRip; /**< 0x120 - I/O RIP. */
+ RTUINT64U u64RoGuestLinearAddr; /**< 0x128 - Guest-linear address. */
+ RTUINT64U au64Reserved5[16]; /**< 0x130 - Reserved for future. */
+ /** @} */
+
+ /** @name Control fields.
+ * @{ */
+ /** 16-bit fields. */
+ uint16_t u16Vpid; /**< 0x1b0 - Virtual processor ID. */
+ uint16_t u16PostIntNotifyVector; /**< 0x1b2 - Posted interrupt notify vector. */
+ uint16_t u16EptpIndex; /**< 0x1b4 - EPTP index. */
+ uint16_t u16HlatPrefixSize; /**< 0x1b6 - HLAT prefix size. */
+ uint16_t au16Reserved0[12]; /**< 0x1b8 - Reserved for future. */
+
+ /** 32-bit fields. */
+ uint32_t u32PinCtls; /**< 0x1d0 - Pin-based VM-execution controls. */
+ uint32_t u32ProcCtls; /**< 0x1d4 - Processor-based VM-execution controls. */
+ uint32_t u32XcptBitmap; /**< 0x1d8 - Exception bitmap. */
+ uint32_t u32XcptPFMask; /**< 0x1dc - Page-fault exception error mask. */
+ uint32_t u32XcptPFMatch; /**< 0x1e0 - Page-fault exception error match. */
+ uint32_t u32Cr3TargetCount; /**< 0x1e4 - CR3-target count. */
+ uint32_t u32ExitCtls; /**< 0x1e8 - VM-exit controls. */
+ uint32_t u32ExitMsrStoreCount; /**< 0x1ec - VM-exit MSR store count. */
+ uint32_t u32ExitMsrLoadCount; /**< 0x1f0 - VM-exit MSR load count. */
+ uint32_t u32EntryCtls; /**< 0x1f4 - VM-entry controls. */
+ uint32_t u32EntryMsrLoadCount; /**< 0x1f8 - VM-entry MSR load count. */
+ uint32_t u32EntryIntInfo; /**< 0x1fc - VM-entry interruption information. */
+ uint32_t u32EntryXcptErrCode; /**< 0x200 - VM-entry exception error code. */
+ uint32_t u32EntryInstrLen; /**< 0x204 - VM-entry instruction length. */
+ uint32_t u32TprThreshold; /**< 0x208 - TPR-threshold. */
+ uint32_t u32ProcCtls2; /**< 0x20c - Secondary-processor based VM-execution controls. */
+ uint32_t u32PleGap; /**< 0x210 - Pause-loop exiting Gap. */
+ uint32_t u32PleWindow; /**< 0x214 - Pause-loop exiting Window. */
+ uint32_t au32Reserved1[16]; /**< 0x218 - Reserved for future. */
+
+ /** 64-bit fields. */
+ RTUINT64U u64AddrIoBitmapA; /**< 0x258 - I/O bitmap A address. */
+ RTUINT64U u64AddrIoBitmapB; /**< 0x260 - I/O bitmap B address. */
+ RTUINT64U u64AddrMsrBitmap; /**< 0x268 - MSR bitmap address. */
+ RTUINT64U u64AddrExitMsrStore; /**< 0x270 - VM-exit MSR-store area address. */
+ RTUINT64U u64AddrExitMsrLoad; /**< 0x278 - VM-exit MSR-load area address. */
+ RTUINT64U u64AddrEntryMsrLoad; /**< 0x280 - VM-entry MSR-load area address. */
+ RTUINT64U u64ExecVmcsPtr; /**< 0x288 - Executive-VMCS pointer. */
+ RTUINT64U u64AddrPml; /**< 0x290 - Page-modification log address (PML). */
+ RTUINT64U u64TscOffset; /**< 0x298 - TSC offset. */
+ RTUINT64U u64AddrVirtApic; /**< 0x2a0 - Virtual-APIC address. */
+ RTUINT64U u64AddrApicAccess; /**< 0x2a8 - APIC-access address. */
+ RTUINT64U u64AddrPostedIntDesc; /**< 0x2b0 - Posted-interrupt descriptor address. */
+ RTUINT64U u64VmFuncCtls; /**< 0x2b8 - VM-functions control. */
+ RTUINT64U u64EptPtr; /**< 0x2c0 - EPT pointer. */
+ RTUINT64U u64EoiExitBitmap0; /**< 0x2c8 - EOI-exit bitmap 0. */
+ RTUINT64U u64EoiExitBitmap1; /**< 0x2d0 - EOI-exit bitmap 1. */
+ RTUINT64U u64EoiExitBitmap2; /**< 0x2d8 - EOI-exit bitmap 2. */
+ RTUINT64U u64EoiExitBitmap3; /**< 0x2e0 - EOI-exit bitmap 3. */
+ RTUINT64U u64AddrEptpList; /**< 0x2e8 - EPTP-list address. */
+ RTUINT64U u64AddrVmreadBitmap; /**< 0x2f0 - VMREAD-bitmap address. */
+ RTUINT64U u64AddrVmwriteBitmap; /**< 0x2f8 - VMWRITE-bitmap address. */
+ RTUINT64U u64AddrXcptVeInfo; /**< 0x300 - Virtualization-exception information address. */
+ RTUINT64U u64XssExitBitmap; /**< 0x308 - XSS-exiting bitmap. */
+ RTUINT64U u64EnclsExitBitmap; /**< 0x310 - ENCLS-exiting bitmap address. */
+ RTUINT64U u64SppTablePtr; /**< 0x318 - Sub-page-permission-table pointer (SPPTP). */
+ RTUINT64U u64TscMultiplier; /**< 0x320 - TSC multiplier. */
+ RTUINT64U u64ProcCtls3; /**< 0x328 - Tertiary-Processor based VM-execution controls. */
+ RTUINT64U u64EnclvExitBitmap; /**< 0x330 - ENCLV-exiting bitmap. */
+ RTUINT64U u64PconfigExitBitmap; /**< 0x338 - PCONFIG-exiting bitmap. */
+ RTUINT64U u64HlatPtr; /**< 0x340 - HLAT pointer. */
+ RTUINT64U u64ExitCtls2; /**< 0x348 - Secondary VM-exit controls. */
+ RTUINT64U au64Reserved0[10]; /**< 0x350 - Reserved for future. */
+
+ /** Natural-width fields. */
+ RTUINT64U u64Cr0Mask; /**< 0x3a0 - CR0 guest/host Mask. */
+ RTUINT64U u64Cr4Mask; /**< 0x3a8 - CR4 guest/host Mask. */
+ RTUINT64U u64Cr0ReadShadow; /**< 0x3b0 - CR0 read shadow. */
+ RTUINT64U u64Cr4ReadShadow; /**< 0x3b8 - CR4 read shadow. */
+ RTUINT64U u64Cr3Target0; /**< 0x3c0 - CR3-target value 0. */
+ RTUINT64U u64Cr3Target1; /**< 0x3c8 - CR3-target value 1. */
+ RTUINT64U u64Cr3Target2; /**< 0x3d0 - CR3-target value 2. */
+ RTUINT64U u64Cr3Target3; /**< 0x3d8 - CR3-target value 3. */
+ RTUINT64U au64Reserved4[32]; /**< 0x3e0 - Reserved for future. */
+ /** @} */
+
+ /** @name Host-state fields.
+ * @{ */
+ /** 16-bit fields. */
+ /* Order of [Es..Gs] fields below must match [X86_SREG_ES..X86_SREG_GS]. */
+ RTSEL HostEs; /**< 0x4e0 - Host ES selector. */
+ RTSEL HostCs; /**< 0x4e2 - Host CS selector. */
+ RTSEL HostSs; /**< 0x4e4 - Host SS selector. */
+ RTSEL HostDs; /**< 0x4e6 - Host DS selector. */
+ RTSEL HostFs; /**< 0x4e8 - Host FS selector. */
+ RTSEL HostGs; /**< 0x4ea - Host GS selector. */
+ RTSEL HostTr; /**< 0x4ec - Host TR selector. */
+ uint16_t au16Reserved2[13]; /**< 0x4ee - Reserved for future. */
+
+ /** 32-bit fields. */
+ uint32_t u32HostSysenterCs; /**< 0x508 - Host SYSENTER CS. */
+ uint32_t au32Reserved4[11]; /**< 0x50c - Reserved for future. */
+
+ /** 64-bit fields. */
+ RTUINT64U u64HostPatMsr; /**< 0x538 - Host PAT MSR. */
+ RTUINT64U u64HostEferMsr; /**< 0x540 - Host EFER MSR. */
+ RTUINT64U u64HostPerfGlobalCtlMsr; /**< 0x548 - Host global performance-control MSR. */
+ RTUINT64U u64HostPkrsMsr; /**< 0x550 - Host PKRS MSR. */
+ RTUINT64U au64Reserved3[15]; /**< 0x558 - Reserved for future. */
+
+ /** Natural-width fields. */
+ RTUINT64U u64HostCr0; /**< 0x5d0 - Host CR0. */
+ RTUINT64U u64HostCr3; /**< 0x5d8 - Host CR3. */
+ RTUINT64U u64HostCr4; /**< 0x5e0 - Host CR4. */
+ RTUINT64U u64HostFsBase; /**< 0x5e8 - Host FS base. */
+ RTUINT64U u64HostGsBase; /**< 0x5f0 - Host GS base. */
+ RTUINT64U u64HostTrBase; /**< 0x5f8 - Host TR base. */
+ RTUINT64U u64HostGdtrBase; /**< 0x600 - Host GDTR base. */
+ RTUINT64U u64HostIdtrBase; /**< 0x608 - Host IDTR base. */
+ RTUINT64U u64HostSysenterEsp; /**< 0x610 - Host SYSENTER ESP base. */
+ RTUINT64U u64HostSysenterEip; /**< 0x618 - Host SYSENTER ESP base. */
+ RTUINT64U u64HostRsp; /**< 0x620 - Host RSP. */
+ RTUINT64U u64HostRip; /**< 0x628 - Host RIP. */
+ RTUINT64U u64HostSCetMsr; /**< 0x630 - Host S_CET MSR. */
+ RTUINT64U u64HostSsp; /**< 0x638 - Host SSP. */
+ RTUINT64U u64HostIntrSspTableAddrMsr; /**< 0x640 - Host Interrupt SSP table address MSR. */
+ RTUINT64U au64Reserved7[29]; /**< 0x648 - Reserved for future. */
+ /** @} */
+
+ /** @name Guest-state fields.
+ * @{ */
+ /** 16-bit fields. */
+ /* Order of [Es..Gs] fields below must match [X86_SREG_ES..X86_SREG_GS]. */
+ RTSEL GuestEs; /**< 0x730 - Guest ES selector. */
+ RTSEL GuestCs; /**< 0x732 - Guest ES selector. */
+ RTSEL GuestSs; /**< 0x734 - Guest ES selector. */
+ RTSEL GuestDs; /**< 0x736 - Guest ES selector. */
+ RTSEL GuestFs; /**< 0x738 - Guest ES selector. */
+ RTSEL GuestGs; /**< 0x73a - Guest ES selector. */
+ RTSEL GuestLdtr; /**< 0x73c - Guest LDTR selector. */
+ RTSEL GuestTr; /**< 0x73e - Guest TR selector. */
+ uint16_t u16GuestIntStatus; /**< 0x740 - Guest interrupt status (virtual-interrupt delivery). */
+ uint16_t u16PmlIndex; /**< 0x742 - PML index. */
+ uint16_t au16Reserved1[14]; /**< 0x744 - Reserved for future. */
+
+ /** 32-bit fields. */
+ /* Order of [Es..Gs] fields below must match [X86_SREG_ES..X86_SREG_GS]. */
+ uint32_t u32GuestEsLimit; /**< 0x760 - Guest ES limit. */
+ uint32_t u32GuestCsLimit; /**< 0x764 - Guest CS limit. */
+ uint32_t u32GuestSsLimit; /**< 0x768 - Guest SS limit. */
+ uint32_t u32GuestDsLimit; /**< 0x76c - Guest DS limit. */
+ uint32_t u32GuestFsLimit; /**< 0x770 - Guest FS limit. */
+ uint32_t u32GuestGsLimit; /**< 0x774 - Guest GS limit. */
+ uint32_t u32GuestLdtrLimit; /**< 0x778 - Guest LDTR limit. */
+ uint32_t u32GuestTrLimit; /**< 0x77c - Guest TR limit. */
+ uint32_t u32GuestGdtrLimit; /**< 0x780 - Guest GDTR limit. */
+ uint32_t u32GuestIdtrLimit; /**< 0x784 - Guest IDTR limit. */
+ uint32_t u32GuestEsAttr; /**< 0x788 - Guest ES attributes. */
+ uint32_t u32GuestCsAttr; /**< 0x78c - Guest CS attributes. */
+ uint32_t u32GuestSsAttr; /**< 0x790 - Guest SS attributes. */
+ uint32_t u32GuestDsAttr; /**< 0x794 - Guest DS attributes. */
+ uint32_t u32GuestFsAttr; /**< 0x798 - Guest FS attributes. */
+ uint32_t u32GuestGsAttr; /**< 0x79c - Guest GS attributes. */
+ uint32_t u32GuestLdtrAttr; /**< 0x7a0 - Guest LDTR attributes. */
+ uint32_t u32GuestTrAttr; /**< 0x7a4 - Guest TR attributes. */
+ uint32_t u32GuestIntrState; /**< 0x7a8 - Guest interruptibility state. */
+ uint32_t u32GuestActivityState; /**< 0x7ac - Guest activity state. */
+ uint32_t u32GuestSmBase; /**< 0x7b0 - Guest SMBASE. */
+ uint32_t u32GuestSysenterCS; /**< 0x7b4 - Guest SYSENTER CS. */
+ uint32_t u32PreemptTimer; /**< 0x7b8 - Preemption timer value. */
+ uint32_t au32Reserved3[11]; /**< 0x7bc - Reserved for future. */
+
+ /** 64-bit fields. */
+ RTUINT64U u64VmcsLinkPtr; /**< 0x7e8 - VMCS link pointer. */
+ RTUINT64U u64GuestDebugCtlMsr; /**< 0x7f0 - Guest debug-control MSR. */
+ RTUINT64U u64GuestPatMsr; /**< 0x7f8 - Guest PAT MSR. */
+ RTUINT64U u64GuestEferMsr; /**< 0x800 - Guest EFER MSR. */
+ RTUINT64U u64GuestPerfGlobalCtlMsr; /**< 0x808 - Guest global performance-control MSR. */
+ RTUINT64U u64GuestPdpte0; /**< 0x810 - Guest PDPTE 0. */
+ RTUINT64U u64GuestPdpte1; /**< 0x818 - Guest PDPTE 0. */
+ RTUINT64U u64GuestPdpte2; /**< 0x820 - Guest PDPTE 1. */
+ RTUINT64U u64GuestPdpte3; /**< 0x828 - Guest PDPTE 2. */
+ RTUINT64U u64GuestBndcfgsMsr; /**< 0x830 - Guest Bounds config MPX MSR (Intel Memory Protection Extensions). */
+ RTUINT64U u64GuestRtitCtlMsr; /**< 0x838 - Guest RTIT control MSR (Intel Real Time Instruction Trace). */
+ RTUINT64U u64GuestPkrsMsr; /**< 0x840 - Guest PKRS MSR. */
+ RTUINT64U au64Reserved2[31]; /**< 0x848 - Reserved for future. */
+
+ /** Natural-width fields. */
+ RTUINT64U u64GuestCr0; /**< 0x940 - Guest CR0. */
+ RTUINT64U u64GuestCr3; /**< 0x948 - Guest CR3. */
+ RTUINT64U u64GuestCr4; /**< 0x950 - Guest CR4. */
+ RTUINT64U u64GuestEsBase; /**< 0x958 - Guest ES base. */
+ RTUINT64U u64GuestCsBase; /**< 0x960 - Guest CS base. */
+ RTUINT64U u64GuestSsBase; /**< 0x968 - Guest SS base. */
+ RTUINT64U u64GuestDsBase; /**< 0x970 - Guest DS base. */
+ RTUINT64U u64GuestFsBase; /**< 0x978 - Guest FS base. */
+ RTUINT64U u64GuestGsBase; /**< 0x980 - Guest GS base. */
+ RTUINT64U u64GuestLdtrBase; /**< 0x988 - Guest LDTR base. */
+ RTUINT64U u64GuestTrBase; /**< 0x990 - Guest TR base. */
+ RTUINT64U u64GuestGdtrBase; /**< 0x998 - Guest GDTR base. */
+ RTUINT64U u64GuestIdtrBase; /**< 0x9a0 - Guest IDTR base. */
+ RTUINT64U u64GuestDr7; /**< 0x9a8 - Guest DR7. */
+ RTUINT64U u64GuestRsp; /**< 0x9b0 - Guest RSP. */
+ RTUINT64U u64GuestRip; /**< 0x9b8 - Guest RIP. */
+ RTUINT64U u64GuestRFlags; /**< 0x9c0 - Guest RFLAGS. */
+ RTUINT64U u64GuestPendingDbgXcpts; /**< 0x9c8 - Guest pending debug exceptions. */
+ RTUINT64U u64GuestSysenterEsp; /**< 0x9d0 - Guest SYSENTER ESP. */
+ RTUINT64U u64GuestSysenterEip; /**< 0x9d8 - Guest SYSENTER EIP. */
+ RTUINT64U u64GuestSCetMsr; /**< 0x9e0 - Guest S_CET MSR. */
+ RTUINT64U u64GuestSsp; /**< 0x9e8 - Guest SSP. */
+ RTUINT64U u64GuestIntrSspTableAddrMsr; /**< 0x9f0 - Guest Interrupt SSP table address MSR. */
+ RTUINT64U au64Reserved6[29]; /**< 0x9f8 - Reserved for future. */
+ /** @} */
+
+ /** 0xae0 - Padding / reserved for future use. */
+ uint8_t abPadding[X86_PAGE_4K_SIZE - 0xae0];
+} VMXVVMCS;
+#pragma pack()
+/** Pointer to the VMXVVMCS struct. */
+typedef VMXVVMCS *PVMXVVMCS;
+/** Pointer to a const VMXVVMCS struct. */
+typedef const VMXVVMCS *PCVMXVVMCS;
+AssertCompileSize(VMXVVMCS, X86_PAGE_4K_SIZE);
+AssertCompileMemberSize(VMXVVMCS, fVmcsState, sizeof(uint8_t));
+AssertCompileMemberOffset(VMXVVMCS, enmVmxAbort, 0x004);
+AssertCompileMemberOffset(VMXVVMCS, fVmcsState, 0x008);
+AssertCompileMemberOffset(VMXVVMCS, u32RoVmInstrError, 0x058);
+AssertCompileMemberOffset(VMXVVMCS, u64RoGuestPhysAddr, 0x0b8);
+AssertCompileMemberOffset(VMXVVMCS, u64RoExitQual, 0x100);
+AssertCompileMemberOffset(VMXVVMCS, u16Vpid, 0x1b0);
+AssertCompileMemberOffset(VMXVVMCS, u32PinCtls, 0x1d0);
+AssertCompileMemberOffset(VMXVVMCS, u64AddrIoBitmapA, 0x258);
+AssertCompileMemberOffset(VMXVVMCS, u64Cr0Mask, 0x3a0);
+AssertCompileMemberOffset(VMXVVMCS, HostEs, 0x4e0);
+AssertCompileMemberOffset(VMXVVMCS, u32HostSysenterCs, 0x508);
+AssertCompileMemberOffset(VMXVVMCS, u64HostPatMsr, 0x538);
+AssertCompileMemberOffset(VMXVVMCS, u64HostCr0, 0x5d0);
+AssertCompileMemberOffset(VMXVVMCS, GuestEs, 0x730);
+AssertCompileMemberOffset(VMXVVMCS, u32GuestEsLimit, 0x760);
+AssertCompileMemberOffset(VMXVVMCS, u64VmcsLinkPtr, 0x7e8);
+AssertCompileMemberOffset(VMXVVMCS, u64GuestCr0, 0x940);
+
+/**
+ * Virtual VMX-instruction and VM-exit diagnostics.
+ *
+ * These are not the same as VM instruction errors that are enumerated in the Intel
+ * spec. These are purely internal, fine-grained definitions used for diagnostic
+ * purposes and are not reported to guest software under the VM-instruction error
+ * field in its VMCS.
+ *
+ * @note Members of this enum are used as array indices, so no gaps are allowed.
+ * Please update g_apszVmxVDiagDesc when you add new fields to this enum.
+ */
+typedef enum
+{
+ /* Internal processing errors. */
+ kVmxVDiag_None = 0,
+ kVmxVDiag_Ipe_1,
+ kVmxVDiag_Ipe_2,
+ kVmxVDiag_Ipe_3,
+ kVmxVDiag_Ipe_4,
+ kVmxVDiag_Ipe_5,
+ kVmxVDiag_Ipe_6,
+ kVmxVDiag_Ipe_7,
+ kVmxVDiag_Ipe_8,
+ kVmxVDiag_Ipe_9,
+ kVmxVDiag_Ipe_10,
+ kVmxVDiag_Ipe_11,
+ kVmxVDiag_Ipe_12,
+ kVmxVDiag_Ipe_13,
+ kVmxVDiag_Ipe_14,
+ kVmxVDiag_Ipe_15,
+ kVmxVDiag_Ipe_16,
+ /* VMXON. */
+ kVmxVDiag_Vmxon_A20M,
+ kVmxVDiag_Vmxon_Cpl,
+ kVmxVDiag_Vmxon_Cr0Fixed0,
+ kVmxVDiag_Vmxon_Cr0Fixed1,
+ kVmxVDiag_Vmxon_Cr4Fixed0,
+ kVmxVDiag_Vmxon_Cr4Fixed1,
+ kVmxVDiag_Vmxon_Intercept,
+ kVmxVDiag_Vmxon_LongModeCS,
+ kVmxVDiag_Vmxon_MsrFeatCtl,
+ kVmxVDiag_Vmxon_PtrAbnormal,
+ kVmxVDiag_Vmxon_PtrAlign,
+ kVmxVDiag_Vmxon_PtrMap,
+ kVmxVDiag_Vmxon_PtrReadPhys,
+ kVmxVDiag_Vmxon_PtrWidth,
+ kVmxVDiag_Vmxon_RealOrV86Mode,
+ kVmxVDiag_Vmxon_ShadowVmcs,
+ kVmxVDiag_Vmxon_VmxAlreadyRoot,
+ kVmxVDiag_Vmxon_Vmxe,
+ kVmxVDiag_Vmxon_VmcsRevId,
+ kVmxVDiag_Vmxon_VmxRootCpl,
+ /* VMXOFF. */
+ kVmxVDiag_Vmxoff_Cpl,
+ kVmxVDiag_Vmxoff_Intercept,
+ kVmxVDiag_Vmxoff_LongModeCS,
+ kVmxVDiag_Vmxoff_RealOrV86Mode,
+ kVmxVDiag_Vmxoff_Vmxe,
+ kVmxVDiag_Vmxoff_VmxRoot,
+ /* VMPTRLD. */
+ kVmxVDiag_Vmptrld_Cpl,
+ kVmxVDiag_Vmptrld_LongModeCS,
+ kVmxVDiag_Vmptrld_PtrAbnormal,
+ kVmxVDiag_Vmptrld_PtrAlign,
+ kVmxVDiag_Vmptrld_PtrMap,
+ kVmxVDiag_Vmptrld_PtrReadPhys,
+ kVmxVDiag_Vmptrld_PtrVmxon,
+ kVmxVDiag_Vmptrld_PtrWidth,
+ kVmxVDiag_Vmptrld_RealOrV86Mode,
+ kVmxVDiag_Vmptrld_RevPtrReadPhys,
+ kVmxVDiag_Vmptrld_ShadowVmcs,
+ kVmxVDiag_Vmptrld_VmcsRevId,
+ kVmxVDiag_Vmptrld_VmxRoot,
+ /* VMPTRST. */
+ kVmxVDiag_Vmptrst_Cpl,
+ kVmxVDiag_Vmptrst_LongModeCS,
+ kVmxVDiag_Vmptrst_PtrMap,
+ kVmxVDiag_Vmptrst_RealOrV86Mode,
+ kVmxVDiag_Vmptrst_VmxRoot,
+ /* VMCLEAR. */
+ kVmxVDiag_Vmclear_Cpl,
+ kVmxVDiag_Vmclear_LongModeCS,
+ kVmxVDiag_Vmclear_PtrAbnormal,
+ kVmxVDiag_Vmclear_PtrAlign,
+ kVmxVDiag_Vmclear_PtrMap,
+ kVmxVDiag_Vmclear_PtrReadPhys,
+ kVmxVDiag_Vmclear_PtrVmxon,
+ kVmxVDiag_Vmclear_PtrWidth,
+ kVmxVDiag_Vmclear_RealOrV86Mode,
+ kVmxVDiag_Vmclear_VmxRoot,
+ /* VMWRITE. */
+ kVmxVDiag_Vmwrite_Cpl,
+ kVmxVDiag_Vmwrite_FieldInvalid,
+ kVmxVDiag_Vmwrite_FieldRo,
+ kVmxVDiag_Vmwrite_LinkPtrInvalid,
+ kVmxVDiag_Vmwrite_LongModeCS,
+ kVmxVDiag_Vmwrite_PtrInvalid,
+ kVmxVDiag_Vmwrite_PtrMap,
+ kVmxVDiag_Vmwrite_RealOrV86Mode,
+ kVmxVDiag_Vmwrite_VmxRoot,
+ /* VMREAD. */
+ kVmxVDiag_Vmread_Cpl,
+ kVmxVDiag_Vmread_FieldInvalid,
+ kVmxVDiag_Vmread_LinkPtrInvalid,
+ kVmxVDiag_Vmread_LongModeCS,
+ kVmxVDiag_Vmread_PtrInvalid,
+ kVmxVDiag_Vmread_PtrMap,
+ kVmxVDiag_Vmread_RealOrV86Mode,
+ kVmxVDiag_Vmread_VmxRoot,
+ /* INVVPID. */
+ kVmxVDiag_Invvpid_Cpl,
+ kVmxVDiag_Invvpid_DescRsvd,
+ kVmxVDiag_Invvpid_LongModeCS,
+ kVmxVDiag_Invvpid_RealOrV86Mode,
+ kVmxVDiag_Invvpid_TypeInvalid,
+ kVmxVDiag_Invvpid_Type0InvalidAddr,
+ kVmxVDiag_Invvpid_Type0InvalidVpid,
+ kVmxVDiag_Invvpid_Type1InvalidVpid,
+ kVmxVDiag_Invvpid_Type3InvalidVpid,
+ kVmxVDiag_Invvpid_VmxRoot,
+ /* INVEPT. */
+ kVmxVDiag_Invept_Cpl,
+ kVmxVDiag_Invept_DescRsvd,
+ kVmxVDiag_Invept_EptpInvalid,
+ kVmxVDiag_Invept_LongModeCS,
+ kVmxVDiag_Invept_RealOrV86Mode,
+ kVmxVDiag_Invept_TypeInvalid,
+ kVmxVDiag_Invept_VmxRoot,
+ /* VMLAUNCH/VMRESUME. */
+ kVmxVDiag_Vmentry_AddrApicAccess,
+ kVmxVDiag_Vmentry_AddrApicAccessEqVirtApic,
+ kVmxVDiag_Vmentry_AddrApicAccessHandlerReg,
+ kVmxVDiag_Vmentry_AddrEntryMsrLoad,
+ kVmxVDiag_Vmentry_AddrExitMsrLoad,
+ kVmxVDiag_Vmentry_AddrExitMsrStore,
+ kVmxVDiag_Vmentry_AddrIoBitmapA,
+ kVmxVDiag_Vmentry_AddrIoBitmapB,
+ kVmxVDiag_Vmentry_AddrMsrBitmap,
+ kVmxVDiag_Vmentry_AddrVirtApicPage,
+ kVmxVDiag_Vmentry_AddrVmcsLinkPtr,
+ kVmxVDiag_Vmentry_AddrVmreadBitmap,
+ kVmxVDiag_Vmentry_AddrVmwriteBitmap,
+ kVmxVDiag_Vmentry_ApicRegVirt,
+ kVmxVDiag_Vmentry_BlocKMovSS,
+ kVmxVDiag_Vmentry_Cpl,
+ kVmxVDiag_Vmentry_Cr3TargetCount,
+ kVmxVDiag_Vmentry_EntryCtlsAllowed1,
+ kVmxVDiag_Vmentry_EntryCtlsDisallowed0,
+ kVmxVDiag_Vmentry_EntryInstrLen,
+ kVmxVDiag_Vmentry_EntryInstrLenZero,
+ kVmxVDiag_Vmentry_EntryIntInfoErrCodePe,
+ kVmxVDiag_Vmentry_EntryIntInfoErrCodeVec,
+ kVmxVDiag_Vmentry_EntryIntInfoTypeVecRsvd,
+ kVmxVDiag_Vmentry_EntryXcptErrCodeRsvd,
+ kVmxVDiag_Vmentry_EptpAccessDirty,
+ kVmxVDiag_Vmentry_EptpPageWalkLength,
+ kVmxVDiag_Vmentry_EptpMemType,
+ kVmxVDiag_Vmentry_EptpRsvd,
+ kVmxVDiag_Vmentry_ExitCtlsAllowed1,
+ kVmxVDiag_Vmentry_ExitCtlsDisallowed0,
+ kVmxVDiag_Vmentry_GuestActStateHlt,
+ kVmxVDiag_Vmentry_GuestActStateRsvd,
+ kVmxVDiag_Vmentry_GuestActStateShutdown,
+ kVmxVDiag_Vmentry_GuestActStateSsDpl,
+ kVmxVDiag_Vmentry_GuestActStateStiMovSs,
+ kVmxVDiag_Vmentry_GuestCr0Fixed0,
+ kVmxVDiag_Vmentry_GuestCr0Fixed1,
+ kVmxVDiag_Vmentry_GuestCr0PgPe,
+ kVmxVDiag_Vmentry_GuestCr3,
+ kVmxVDiag_Vmentry_GuestCr4Fixed0,
+ kVmxVDiag_Vmentry_GuestCr4Fixed1,
+ kVmxVDiag_Vmentry_GuestDebugCtl,
+ kVmxVDiag_Vmentry_GuestDr7,
+ kVmxVDiag_Vmentry_GuestEferMsr,
+ kVmxVDiag_Vmentry_GuestEferMsrRsvd,
+ kVmxVDiag_Vmentry_GuestGdtrBase,
+ kVmxVDiag_Vmentry_GuestGdtrLimit,
+ kVmxVDiag_Vmentry_GuestIdtrBase,
+ kVmxVDiag_Vmentry_GuestIdtrLimit,
+ kVmxVDiag_Vmentry_GuestIntStateEnclave,
+ kVmxVDiag_Vmentry_GuestIntStateExtInt,
+ kVmxVDiag_Vmentry_GuestIntStateNmi,
+ kVmxVDiag_Vmentry_GuestIntStateRFlagsSti,
+ kVmxVDiag_Vmentry_GuestIntStateRsvd,
+ kVmxVDiag_Vmentry_GuestIntStateSmi,
+ kVmxVDiag_Vmentry_GuestIntStateStiMovSs,
+ kVmxVDiag_Vmentry_GuestIntStateVirtNmi,
+ kVmxVDiag_Vmentry_GuestPae,
+ kVmxVDiag_Vmentry_GuestPatMsr,
+ kVmxVDiag_Vmentry_GuestPcide,
+ kVmxVDiag_Vmentry_GuestPdpte,
+ kVmxVDiag_Vmentry_GuestPndDbgXcptBsNoTf,
+ kVmxVDiag_Vmentry_GuestPndDbgXcptBsTf,
+ kVmxVDiag_Vmentry_GuestPndDbgXcptRsvd,
+ kVmxVDiag_Vmentry_GuestPndDbgXcptRtm,
+ kVmxVDiag_Vmentry_GuestRip,
+ kVmxVDiag_Vmentry_GuestRipRsvd,
+ kVmxVDiag_Vmentry_GuestRFlagsIf,
+ kVmxVDiag_Vmentry_GuestRFlagsRsvd,
+ kVmxVDiag_Vmentry_GuestRFlagsVm,
+ kVmxVDiag_Vmentry_GuestSegAttrCsDefBig,
+ kVmxVDiag_Vmentry_GuestSegAttrCsDplEqSs,
+ kVmxVDiag_Vmentry_GuestSegAttrCsDplLtSs,
+ kVmxVDiag_Vmentry_GuestSegAttrCsDplZero,
+ kVmxVDiag_Vmentry_GuestSegAttrCsType,
+ kVmxVDiag_Vmentry_GuestSegAttrCsTypeRead,
+ kVmxVDiag_Vmentry_GuestSegAttrDescTypeCs,
+ kVmxVDiag_Vmentry_GuestSegAttrDescTypeDs,
+ kVmxVDiag_Vmentry_GuestSegAttrDescTypeEs,
+ kVmxVDiag_Vmentry_GuestSegAttrDescTypeFs,
+ kVmxVDiag_Vmentry_GuestSegAttrDescTypeGs,
+ kVmxVDiag_Vmentry_GuestSegAttrDescTypeSs,
+ kVmxVDiag_Vmentry_GuestSegAttrDplRplCs,
+ kVmxVDiag_Vmentry_GuestSegAttrDplRplDs,
+ kVmxVDiag_Vmentry_GuestSegAttrDplRplEs,
+ kVmxVDiag_Vmentry_GuestSegAttrDplRplFs,
+ kVmxVDiag_Vmentry_GuestSegAttrDplRplGs,
+ kVmxVDiag_Vmentry_GuestSegAttrDplRplSs,
+ kVmxVDiag_Vmentry_GuestSegAttrGranCs,
+ kVmxVDiag_Vmentry_GuestSegAttrGranDs,
+ kVmxVDiag_Vmentry_GuestSegAttrGranEs,
+ kVmxVDiag_Vmentry_GuestSegAttrGranFs,
+ kVmxVDiag_Vmentry_GuestSegAttrGranGs,
+ kVmxVDiag_Vmentry_GuestSegAttrGranSs,
+ kVmxVDiag_Vmentry_GuestSegAttrLdtrDescType,
+ kVmxVDiag_Vmentry_GuestSegAttrLdtrGran,
+ kVmxVDiag_Vmentry_GuestSegAttrLdtrPresent,
+ kVmxVDiag_Vmentry_GuestSegAttrLdtrRsvd,
+ kVmxVDiag_Vmentry_GuestSegAttrLdtrType,
+ kVmxVDiag_Vmentry_GuestSegAttrPresentCs,
+ kVmxVDiag_Vmentry_GuestSegAttrPresentDs,
+ kVmxVDiag_Vmentry_GuestSegAttrPresentEs,
+ kVmxVDiag_Vmentry_GuestSegAttrPresentFs,
+ kVmxVDiag_Vmentry_GuestSegAttrPresentGs,
+ kVmxVDiag_Vmentry_GuestSegAttrPresentSs,
+ kVmxVDiag_Vmentry_GuestSegAttrRsvdCs,
+ kVmxVDiag_Vmentry_GuestSegAttrRsvdDs,
+ kVmxVDiag_Vmentry_GuestSegAttrRsvdEs,
+ kVmxVDiag_Vmentry_GuestSegAttrRsvdFs,
+ kVmxVDiag_Vmentry_GuestSegAttrRsvdGs,
+ kVmxVDiag_Vmentry_GuestSegAttrRsvdSs,
+ kVmxVDiag_Vmentry_GuestSegAttrSsDplEqRpl,
+ kVmxVDiag_Vmentry_GuestSegAttrSsDplZero,
+ kVmxVDiag_Vmentry_GuestSegAttrSsType,
+ kVmxVDiag_Vmentry_GuestSegAttrTrDescType,
+ kVmxVDiag_Vmentry_GuestSegAttrTrGran,
+ kVmxVDiag_Vmentry_GuestSegAttrTrPresent,
+ kVmxVDiag_Vmentry_GuestSegAttrTrRsvd,
+ kVmxVDiag_Vmentry_GuestSegAttrTrType,
+ kVmxVDiag_Vmentry_GuestSegAttrTrUnusable,
+ kVmxVDiag_Vmentry_GuestSegAttrTypeAccCs,
+ kVmxVDiag_Vmentry_GuestSegAttrTypeAccDs,
+ kVmxVDiag_Vmentry_GuestSegAttrTypeAccEs,
+ kVmxVDiag_Vmentry_GuestSegAttrTypeAccFs,
+ kVmxVDiag_Vmentry_GuestSegAttrTypeAccGs,
+ kVmxVDiag_Vmentry_GuestSegAttrTypeAccSs,
+ kVmxVDiag_Vmentry_GuestSegAttrV86Cs,
+ kVmxVDiag_Vmentry_GuestSegAttrV86Ds,
+ kVmxVDiag_Vmentry_GuestSegAttrV86Es,
+ kVmxVDiag_Vmentry_GuestSegAttrV86Fs,
+ kVmxVDiag_Vmentry_GuestSegAttrV86Gs,
+ kVmxVDiag_Vmentry_GuestSegAttrV86Ss,
+ kVmxVDiag_Vmentry_GuestSegBaseCs,
+ kVmxVDiag_Vmentry_GuestSegBaseDs,
+ kVmxVDiag_Vmentry_GuestSegBaseEs,
+ kVmxVDiag_Vmentry_GuestSegBaseFs,
+ kVmxVDiag_Vmentry_GuestSegBaseGs,
+ kVmxVDiag_Vmentry_GuestSegBaseLdtr,
+ kVmxVDiag_Vmentry_GuestSegBaseSs,
+ kVmxVDiag_Vmentry_GuestSegBaseTr,
+ kVmxVDiag_Vmentry_GuestSegBaseV86Cs,
+ kVmxVDiag_Vmentry_GuestSegBaseV86Ds,
+ kVmxVDiag_Vmentry_GuestSegBaseV86Es,
+ kVmxVDiag_Vmentry_GuestSegBaseV86Fs,
+ kVmxVDiag_Vmentry_GuestSegBaseV86Gs,
+ kVmxVDiag_Vmentry_GuestSegBaseV86Ss,
+ kVmxVDiag_Vmentry_GuestSegLimitV86Cs,
+ kVmxVDiag_Vmentry_GuestSegLimitV86Ds,
+ kVmxVDiag_Vmentry_GuestSegLimitV86Es,
+ kVmxVDiag_Vmentry_GuestSegLimitV86Fs,
+ kVmxVDiag_Vmentry_GuestSegLimitV86Gs,
+ kVmxVDiag_Vmentry_GuestSegLimitV86Ss,
+ kVmxVDiag_Vmentry_GuestSegSelCsSsRpl,
+ kVmxVDiag_Vmentry_GuestSegSelLdtr,
+ kVmxVDiag_Vmentry_GuestSegSelTr,
+ kVmxVDiag_Vmentry_GuestSysenterEspEip,
+ kVmxVDiag_Vmentry_VmcsLinkPtrCurVmcs,
+ kVmxVDiag_Vmentry_VmcsLinkPtrReadPhys,
+ kVmxVDiag_Vmentry_VmcsLinkPtrRevId,
+ kVmxVDiag_Vmentry_VmcsLinkPtrShadow,
+ kVmxVDiag_Vmentry_HostCr0Fixed0,
+ kVmxVDiag_Vmentry_HostCr0Fixed1,
+ kVmxVDiag_Vmentry_HostCr3,
+ kVmxVDiag_Vmentry_HostCr4Fixed0,
+ kVmxVDiag_Vmentry_HostCr4Fixed1,
+ kVmxVDiag_Vmentry_HostCr4Pae,
+ kVmxVDiag_Vmentry_HostCr4Pcide,
+ kVmxVDiag_Vmentry_HostCsTr,
+ kVmxVDiag_Vmentry_HostEferMsr,
+ kVmxVDiag_Vmentry_HostEferMsrRsvd,
+ kVmxVDiag_Vmentry_HostGuestLongMode,
+ kVmxVDiag_Vmentry_HostGuestLongModeNoCpu,
+ kVmxVDiag_Vmentry_HostLongMode,
+ kVmxVDiag_Vmentry_HostPatMsr,
+ kVmxVDiag_Vmentry_HostRip,
+ kVmxVDiag_Vmentry_HostRipRsvd,
+ kVmxVDiag_Vmentry_HostSel,
+ kVmxVDiag_Vmentry_HostSegBase,
+ kVmxVDiag_Vmentry_HostSs,
+ kVmxVDiag_Vmentry_HostSysenterEspEip,
+ kVmxVDiag_Vmentry_IoBitmapAPtrReadPhys,
+ kVmxVDiag_Vmentry_IoBitmapBPtrReadPhys,
+ kVmxVDiag_Vmentry_LongModeCS,
+ kVmxVDiag_Vmentry_MsrBitmapPtrReadPhys,
+ kVmxVDiag_Vmentry_MsrLoad,
+ kVmxVDiag_Vmentry_MsrLoadCount,
+ kVmxVDiag_Vmentry_MsrLoadPtrReadPhys,
+ kVmxVDiag_Vmentry_MsrLoadRing3,
+ kVmxVDiag_Vmentry_MsrLoadRsvd,
+ kVmxVDiag_Vmentry_NmiWindowExit,
+ kVmxVDiag_Vmentry_PinCtlsAllowed1,
+ kVmxVDiag_Vmentry_PinCtlsDisallowed0,
+ kVmxVDiag_Vmentry_ProcCtlsAllowed1,
+ kVmxVDiag_Vmentry_ProcCtlsDisallowed0,
+ kVmxVDiag_Vmentry_ProcCtls2Allowed1,
+ kVmxVDiag_Vmentry_ProcCtls2Disallowed0,
+ kVmxVDiag_Vmentry_PtrInvalid,
+ kVmxVDiag_Vmentry_PtrShadowVmcs,
+ kVmxVDiag_Vmentry_RealOrV86Mode,
+ kVmxVDiag_Vmentry_SavePreemptTimer,
+ kVmxVDiag_Vmentry_TprThresholdRsvd,
+ kVmxVDiag_Vmentry_TprThresholdVTpr,
+ kVmxVDiag_Vmentry_VirtApicPagePtrReadPhys,
+ kVmxVDiag_Vmentry_VirtIntDelivery,
+ kVmxVDiag_Vmentry_VirtNmi,
+ kVmxVDiag_Vmentry_VirtX2ApicTprShadow,
+ kVmxVDiag_Vmentry_VirtX2ApicVirtApic,
+ kVmxVDiag_Vmentry_VmcsClear,
+ kVmxVDiag_Vmentry_VmcsLaunch,
+ kVmxVDiag_Vmentry_VmreadBitmapPtrReadPhys,
+ kVmxVDiag_Vmentry_VmwriteBitmapPtrReadPhys,
+ kVmxVDiag_Vmentry_VmxRoot,
+ kVmxVDiag_Vmentry_Vpid,
+ kVmxVDiag_Vmexit_HostPdpte,
+ kVmxVDiag_Vmexit_MsrLoad,
+ kVmxVDiag_Vmexit_MsrLoadCount,
+ kVmxVDiag_Vmexit_MsrLoadPtrReadPhys,
+ kVmxVDiag_Vmexit_MsrLoadRing3,
+ kVmxVDiag_Vmexit_MsrLoadRsvd,
+ kVmxVDiag_Vmexit_MsrStore,
+ kVmxVDiag_Vmexit_MsrStoreCount,
+ kVmxVDiag_Vmexit_MsrStorePtrReadPhys,
+ kVmxVDiag_Vmexit_MsrStorePtrWritePhys,
+ kVmxVDiag_Vmexit_MsrStoreRing3,
+ kVmxVDiag_Vmexit_MsrStoreRsvd,
+ kVmxVDiag_Vmexit_VirtApicPagePtrWritePhys,
+ /* Last member for determining array index limit. */
+ kVmxVDiag_End
+} VMXVDIAG;
+AssertCompileSize(VMXVDIAG, 4);
+
+/** @} */
+
+/** @} */
+
+#endif /* !VBOX_INCLUDED_vmm_hm_vmx_h */
+
diff --git a/include/VBox/vmm/hm_vmx.mac b/include/VBox/vmm/hm_vmx.mac
new file mode 100644
index 00000000..15373887
--- /dev/null
+++ b/include/VBox/vmm/hm_vmx.mac
@@ -0,0 +1,163 @@
+;; @file
+; HM - VMX Structures and Definitions.
+;
+
+;
+; Copyright (C) 2006-2022 Oracle and/or its affiliates.
+;
+; This file is part of VirtualBox base platform packages, as
+; available from https://www.virtualbox.org.
+;
+; This program is free software; you can redistribute it and/or
+; modify it under the terms of the GNU General Public License
+; as published by the Free Software Foundation, in version 3 of the
+; License.
+;
+; This program is distributed in the hope that it will be useful, but
+; WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with this program; if not, see <https://www.gnu.org/licenses>.
+;
+; The contents of this file may alternatively be used under the terms
+; of the Common Development and Distribution License Version 1.0
+; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+; in the VirtualBox 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.
+;
+; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+;
+
+%define VMX_VMCS_GUEST_FIELD_ES 0800h
+%define VMX_VMCS_GUEST_FIELD_CS 0802h
+%define VMX_VMCS_GUEST_FIELD_SS 0804h
+%define VMX_VMCS_GUEST_FIELD_DS 0806h
+%define VMX_VMCS_GUEST_FIELD_FS 0808h
+%define VMX_VMCS_GUEST_FIELD_GS 080Ah
+%define VMX_VMCS_GUEST_FIELD_LDTR 080Ch
+%define VMX_VMCS_GUEST_FIELD_TR 080Eh
+%define VMX_VMCS_HOST_FIELD_ES 0C00h
+%define VMX_VMCS_HOST_FIELD_CS 0C02h
+%define VMX_VMCS_HOST_FIELD_SS 0C04h
+%define VMX_VMCS_HOST_FIELD_DS 0C06h
+%define VMX_VMCS_HOST_FIELD_FS 0C08h
+%define VMX_VMCS_HOST_FIELD_GS 0C0Ah
+%define VMX_VMCS_HOST_FIELD_TR 0C0Ch
+%define VMX_VMCS_CTRL_IO_BITMAP_A_FULL 02000h
+%define VMX_VMCS_CTRL_IO_BITMAP_A_HIGH 02001h
+%define VMX_VMCS_CTRL_IO_BITMAP_B_FULL 02002h
+%define VMX_VMCS_CTRL_IO_BITMAP_B_HIGH 02003h
+%define VMX_VMCS_CTRL_MSR_BITMAP_FULL 02004h
+%define VMX_VMCS_CTRL_MSR_BITMAP_HIGH 02005h
+%define VMX_VMCS_CTRL_VMEXIT_MSR_STORE_FULL 02006h
+%define VMX_VMCS_CTRL_VMEXIT_MSR_STORE_HIGH 02007h
+%define VMX_VMCS_CTRL_VMEXIT_MSR_LOAD_FULL 02008h
+%define VMX_VMCS_CTRL_VMEXIT_MSR_LOAD_HIGH 02009h
+%define VMX_VMCS_CTRL_VMENTRY_MSR_LOAD_FULL 0200Ah
+%define VMX_VMCS_CTRL_VMENTRY_MSR_LOAD_HIGH 0200Bh
+%define VMX_VMCS_CTRL_EXEC_VMCS_PTR_FULL 0200Ch
+%define VMX_VMCS_CTRL_EXEC_VMCS_PTR_HIGH 0200Dh
+%define VMX_VMCS_CTRL_TSC_OFFSET_FULL 02010h
+%define VMX_VMCS_CTRL_TSC_OFFSET_HIGH 02011h
+%define VMX_VMCS_CTRL_VAPIC_PAGEADDR_FULL 02012h
+%define VMX_VMCS_CTRL_VAPIC_PAGEADDR_HIGH 02013h
+%define VMX_VMCS_GUEST_LINK_PTR_FULL 02800h
+%define VMX_VMCS_GUEST_LINK_PTR_HIGH 02801h
+%define VMX_VMCS_GUEST_DEBUGCTL_FULL 02802h
+%define VMX_VMCS_GUEST_DEBUGCTL_HIGH 02803h
+%define VMX_VMCS_CTRL_PIN_EXEC 04000h
+%define VMX_VMCS_CTRL_PROC_EXEC 04002h
+%define VMX_VMCS_CTRL_EXCEPTION_BITMAP 04004h
+%define VMX_VMCS_CTRL_PAGEFAULT_ERROR_MASK 04006h
+%define VMX_VMCS_CTRL_PAGEFAULT_ERROR_MATCH 04008h
+%define VMX_VMCS_CTRL_CR3_TARGET_COUNT 0400Ah
+%define VMX_VMCS_CTRL_EXIT 0400Ch
+%define VMX_VMCS_CTRL_EXIT_MSR_STORE_COUNT 0400Eh
+%define VMX_VMCS_CTRL_EXIT_MSR_LOAD_COUNT 04010h
+%define VMX_VMCS_CTRL_ENTRY 04012h
+%define VMX_VMCS_CTRL_ENTRY_MSR_LOAD_COUNT 04014h
+%define VMX_VMCS_CTRL_ENTRY_IRQ_INFO 04016h
+%define VMX_VMCS_CTRL_ENTRY_EXCEPTION_ERRCODE 04018h
+%define VMX_VMCS_CTRL_ENTRY_INSTR_LENGTH 0401Ah
+%define VMX_VMCS_CTRL_TRP_TRESHOLD 0401Ch
+%define VMX_VMCS_RO_VM_INSTR_ERROR 04400h
+%define VMX_VMCS_RO_EXIT_REASON 04402h
+%define VMX_VMCS_RO_EXIT_INTERRUPTION_INFO 04404h
+%define VMX_VMCS_RO_EXIT_INTERRUPTION_ERRCODE 04406h
+%define VMX_VMCS_RO_IDT_INFO 04408h
+%define VMX_VMCS_RO_IDT_ERRCODE 0440Ah
+%define VMX_VMCS_RO_EXIT_INSTR_LENGTH 0440Ch
+%define VMX_VMCS_RO_EXIT_INSTR_INFO 0440Eh
+%define VMX_VMCS_GUEST_ES_LIMIT 04800h
+%define VMX_VMCS_GUEST_CS_LIMIT 04802h
+%define VMX_VMCS_GUEST_SS_LIMIT 04804h
+%define VMX_VMCS_GUEST_DS_LIMIT 04806h
+%define VMX_VMCS_GUEST_FS_LIMIT 04808h
+%define VMX_VMCS_GUEST_GS_LIMIT 0480Ah
+%define VMX_VMCS_GUEST_LDTR_LIMIT 0480Ch
+%define VMX_VMCS_GUEST_TR_LIMIT 0480Eh
+%define VMX_VMCS_GUEST_GDTR_LIMIT 04810h
+%define VMX_VMCS_GUEST_IDTR_LIMIT 04812h
+%define VMX_VMCS_GUEST_ES_ACCESS_RIGHTS 04814h
+%define VMX_VMCS_GUEST_CS_ACCESS_RIGHTS 04816h
+%define VMX_VMCS_GUEST_SS_ACCESS_RIGHTS 04818h
+%define VMX_VMCS_GUEST_DS_ACCESS_RIGHTS 0481Ah
+%define VMX_VMCS_GUEST_FS_ACCESS_RIGHTS 0481Ch
+%define VMX_VMCS_GUEST_GS_ACCESS_RIGHTS 0481Eh
+%define VMX_VMCS_GUEST_LDTR_ACCESS_RIGHTS 04820h
+%define VMX_VMCS_GUEST_TR_ACCESS_RIGHTS 04822h
+%define VMX_VMCS_GUEST_INTERRUPTIBILITY_STATE 04824h
+%define VMX_VMCS_GUEST_ACTIVITY_STATE 04826h
+%define VMX_VMCS_GUEST_SYSENTER_CS 0482Ah
+%define VMX_VMCS_CTRL_CR0_MASK 06000h
+%define VMX_VMCS_CTRL_CR4_MASK 06002h
+%define VMX_VMCS_CTRL_CR0_READ_SHADOW 06004h
+%define VMX_VMCS_CTRL_CR4_READ_SHADOW 06006h
+%define VMX_VMCS_CTRL_CR3_TARGET_VAL0 06008h
+%define VMX_VMCS_CTRL_CR3_TARGET_VAL1 0600Ah
+%define VMX_VMCS_CTRL_CR3_TARGET_VAL2 0600Ch
+%define VMX_VMCS_CTRL_CR3_TARGET_VAL31 0600Eh
+%define VMX_VMCS_RO_EXIT_QUALIFICATION 06400h
+%define VMX_VMCS_RO_IO_RCX 06402h
+%define VMX_VMCS_RO_IO_RSX 06404h
+%define VMX_VMCS_RO_IO_RDI 06406h
+%define VMX_VMCS_RO_IO_RIP 06408h
+%define VMX_VMCS_GUEST_LINEAR_ADDR 0640Ah
+%define VMX_VMCS64_GUEST_CR0 06800h
+%define VMX_VMCS64_GUEST_CR3 06802h
+%define VMX_VMCS64_GUEST_CR4 06804h
+%define VMX_VMCS64_GUEST_ES_BASE 06806h
+%define VMX_VMCS64_GUEST_CS_BASE 06808h
+%define VMX_VMCS64_GUEST_SS_BASE 0680Ah
+%define VMX_VMCS64_GUEST_DS_BASE 0680Ch
+%define VMX_VMCS64_GUEST_FS_BASE 0680Eh
+%define VMX_VMCS64_GUEST_GS_BASE 06810h
+%define VMX_VMCS64_GUEST_LDTR_BASE 06812h
+%define VMX_VMCS64_GUEST_TR_BASE 06814h
+%define VMX_VMCS64_GUEST_GDTR_BASE 06816h
+%define VMX_VMCS64_GUEST_IDTR_BASE 06818h
+%define VMX_VMCS64_GUEST_DR7 0681Ah
+%define VMX_VMCS64_GUEST_RSP 0681Ch
+%define VMX_VMCS64_GUEST_RIP 0681Eh
+%define VMX_VMCS64_GUEST_RFLAGS 06820h
+%define VMX_VMCS_GUEST_DEBUG_EXCEPTIONS 06822h
+%define VMX_VMCS64_GUEST_SYSENTER_ESP 06824h
+%define VMX_VMCS64_GUEST_SYSENTER_EIP 06826h
+%define VMX_VMCS_HOST_CR0 06C00h
+%define VMX_VMCS_HOST_CR3 06C02h
+%define VMX_VMCS_HOST_CR4 06C04h
+%define VMX_VMCS_HOST_FS_BASE 06C06h
+%define VMX_VMCS_HOST_GS_BASE 06C08h
+%define VMX_VMCS_HOST_TR_BASE 06C0Ah
+%define VMX_VMCS_HOST_GDTR_BASE 06C0Ch
+%define VMX_VMCS_HOST_IDTR_BASE 06C0Eh
+%define VMX_VMCS_HOST_SYSENTER_ESP 06C10h
+%define VMX_VMCS_HOST_SYSENTER_EIP 06C12h
+%define VMX_VMCS_HOST_RSP 06C14h
+%define VMX_VMCS_HOST_RIP 06C16h
+
diff --git a/include/VBox/vmm/hmvmxinline.h b/include/VBox/vmm/hmvmxinline.h
new file mode 100644
index 00000000..a0103786
--- /dev/null
+++ b/include/VBox/vmm/hmvmxinline.h
@@ -0,0 +1,1172 @@
+/** @file
+ * HM - VMX Structures and Definitions. (VMM)
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vmm_hmvmxinline_h
+#define VBOX_INCLUDED_vmm_hmvmxinline_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/vmm/hm_vmx.h>
+#include <VBox/err.h>
+
+/* In Visual C++ versions prior to 2012, the vmx intrinsics are only available
+ when targeting AMD64. */
+#if RT_INLINE_ASM_USES_INTRIN >= RT_MSC_VER_VS2010 && defined(RT_ARCH_AMD64)
+# include <iprt/sanitized/intrin.h>
+/* We always want them as intrinsics, no functions. */
+# pragma intrinsic(__vmx_on)
+# pragma intrinsic(__vmx_off)
+# pragma intrinsic(__vmx_vmclear)
+# pragma intrinsic(__vmx_vmptrld)
+# pragma intrinsic(__vmx_vmread)
+# pragma intrinsic(__vmx_vmwrite)
+# define VMX_USE_MSC_INTRINSICS 1
+#else
+# define VMX_USE_MSC_INTRINSICS 0
+#endif
+
+/**
+ * Whether we think the assembler supports VMX instructions.
+ *
+ * Guess that GCC 5 should have sufficient recent enough binutils.
+ */
+#if RT_INLINE_ASM_GNU_STYLE && RT_GNUC_PREREQ(5,0)
+# define VMX_USE_GNU_STYLE_INLINE_VMX_INSTRUCTIONS 1
+#else
+# define VMX_USE_GNU_STYLE_INLINE_VMX_INSTRUCTIONS 0
+#endif
+
+/** Whether we can use the subsection trick to put error handling code
+ * elsewhere. */
+#if VMX_USE_GNU_STYLE_INLINE_VMX_INSTRUCTIONS && defined(__ELF__)
+# define VMX_USE_GNU_STYLE_INLINE_SECTION_TRICK 1
+#else
+# define VMX_USE_GNU_STYLE_INLINE_SECTION_TRICK 0
+#endif
+
+/* Skip checking VMREAD/VMWRITE failures on non-strict builds. */
+#ifndef VBOX_STRICT
+# define VBOX_WITH_VMREAD_VMWRITE_NOCHECK
+#endif
+
+
+/** @defgroup grp_hm_vmx_inline VMX Inline Helpers
+ * @ingroup grp_hm_vmx
+ * @{
+ */
+/**
+ * Gets the effective width of a VMCS field given it's encoding adjusted for
+ * HIGH/FULL access for 64-bit fields.
+ *
+ * @returns The effective VMCS field width.
+ * @param uFieldEnc The VMCS field encoding.
+ *
+ * @remarks Warning! This function does not verify the encoding is for a valid and
+ * supported VMCS field.
+ */
+DECLINLINE(uint8_t) VMXGetVmcsFieldWidthEff(uint32_t uFieldEnc)
+{
+ /* Only the "HIGH" parts of all 64-bit fields have bit 0 set. */
+ if (uFieldEnc & RT_BIT(0))
+ return VMXVMCSFIELDWIDTH_32BIT;
+
+ /* Bits 13:14 contains the width of the VMCS field, see VMXVMCSFIELDWIDTH_XXX. */
+ return (uFieldEnc >> 13) & 0x3;
+}
+
+
+/**
+ * Returns whether the given VMCS field is a read-only VMCS field or not.
+ *
+ * @returns @c true if it's a read-only field, @c false otherwise.
+ * @param uFieldEnc The VMCS field encoding.
+ *
+ * @remarks Warning! This function does not verify that the encoding is for a valid
+ * and/or supported VMCS field.
+ */
+DECLINLINE(bool) VMXIsVmcsFieldReadOnly(uint32_t uFieldEnc)
+{
+ /* See Intel spec. B.4.2 "Natural-Width Read-Only Data Fields". */
+ return (RT_BF_GET(uFieldEnc, VMX_BF_VMCSFIELD_TYPE) == VMXVMCSFIELDTYPE_VMEXIT_INFO);
+}
+
+
+/**
+ * Returns whether the given VM-entry interruption-information type is valid or not.
+ *
+ * @returns @c true if it's a valid type, @c false otherwise.
+ * @param fSupportsMTF Whether the Monitor-Trap Flag CPU feature is supported.
+ * @param uType The VM-entry interruption-information type.
+ */
+DECLINLINE(bool) VMXIsEntryIntInfoTypeValid(bool fSupportsMTF, uint8_t uType)
+{
+ /* See Intel spec. 26.2.1.3 "VM-Entry Control Fields". */
+ switch (uType)
+ {
+ case VMX_ENTRY_INT_INFO_TYPE_EXT_INT:
+ case VMX_ENTRY_INT_INFO_TYPE_NMI:
+ case VMX_ENTRY_INT_INFO_TYPE_HW_XCPT:
+ case VMX_ENTRY_INT_INFO_TYPE_SW_INT:
+ case VMX_ENTRY_INT_INFO_TYPE_PRIV_SW_XCPT:
+ case VMX_ENTRY_INT_INFO_TYPE_SW_XCPT: return true;
+ case VMX_ENTRY_INT_INFO_TYPE_OTHER_EVENT: return fSupportsMTF;
+ default:
+ return false;
+ }
+}
+
+
+/**
+ * Returns whether the given VM-entry interruption-information vector and type
+ * combination is valid or not.
+ *
+ * @returns @c true if it's a valid vector/type combination, @c false otherwise.
+ * @param uVector The VM-entry interruption-information vector.
+ * @param uType The VM-entry interruption-information type.
+ *
+ * @remarks Warning! This function does not validate the type field individually.
+ * Use it after verifying type is valid using HMVmxIsEntryIntInfoTypeValid.
+ */
+DECLINLINE(bool) VMXIsEntryIntInfoVectorValid(uint8_t uVector, uint8_t uType)
+{
+ /* See Intel spec. 26.2.1.3 "VM-Entry Control Fields". */
+ if ( uType == VMX_ENTRY_INT_INFO_TYPE_NMI
+ && uVector != X86_XCPT_NMI)
+ return false;
+ if ( uType == VMX_ENTRY_INT_INFO_TYPE_HW_XCPT
+ && uVector > X86_XCPT_LAST)
+ return false;
+ if ( uType == VMX_ENTRY_INT_INFO_TYPE_OTHER_EVENT
+ && uVector != VMX_ENTRY_INT_INFO_VECTOR_MTF)
+ return false;
+ return true;
+}
+
+
+/**
+ * Returns whether or not the VM-exit is trap-like or fault-like.
+ *
+ * @returns @c true if it's a trap-like VM-exit, @c false otherwise.
+ * @param uExitReason The VM-exit reason.
+ *
+ * @remarks Warning! This does not validate the VM-exit reason.
+ */
+DECLINLINE(bool) VMXIsVmexitTrapLike(uint32_t uExitReason)
+{
+ /*
+ * Trap-like VM-exits - The instruction causing the VM-exit completes before the
+ * VM-exit occurs.
+ *
+ * Fault-like VM-exits - The instruction causing the VM-exit is not completed before
+ * the VM-exit occurs.
+ *
+ * See Intel spec. 25.5.2 "Monitor Trap Flag".
+ * See Intel spec. 29.1.4 "EOI Virtualization".
+ * See Intel spec. 29.4.3.3 "APIC-Write VM Exits".
+ * See Intel spec. 29.1.2 "TPR Virtualization".
+ */
+ /** @todo NSTVMX: r=ramshankar: What about VM-exits due to debug traps (single-step,
+ * I/O breakpoints, data breakpoints), debug exceptions (data breakpoint)
+ * delayed by MovSS blocking, machine-check exceptions. */
+ switch (uExitReason)
+ {
+ case VMX_EXIT_MTF:
+ case VMX_EXIT_VIRTUALIZED_EOI:
+ case VMX_EXIT_APIC_WRITE:
+ case VMX_EXIT_TPR_BELOW_THRESHOLD:
+ return true;
+ }
+ return false;
+}
+
+
+/**
+ * Returns whether the VM-entry is vectoring or not given the VM-entry interruption
+ * information field.
+ *
+ * @returns @c true if the VM-entry is vectoring, @c false otherwise.
+ * @param uEntryIntInfo The VM-entry interruption information field.
+ * @param pEntryIntInfoType The VM-entry interruption information type field.
+ * Optional, can be NULL. Only updated when this
+ * function returns @c true.
+ */
+DECLINLINE(bool) VMXIsVmentryVectoring(uint32_t uEntryIntInfo, uint8_t *pEntryIntInfoType)
+{
+ /*
+ * The definition of what is a vectoring VM-entry is taken
+ * from Intel spec. 26.6 "Special Features of VM Entry".
+ */
+ if (!VMX_ENTRY_INT_INFO_IS_VALID(uEntryIntInfo))
+ return false;
+
+ /* Scope and keep variable defines on top to satisy archaic c89 nonsense. */
+ {
+ uint8_t const uType = VMX_ENTRY_INT_INFO_TYPE(uEntryIntInfo);
+ switch (uType)
+ {
+ case VMX_ENTRY_INT_INFO_TYPE_EXT_INT:
+ case VMX_ENTRY_INT_INFO_TYPE_NMI:
+ case VMX_ENTRY_INT_INFO_TYPE_HW_XCPT:
+ case VMX_ENTRY_INT_INFO_TYPE_SW_INT:
+ case VMX_ENTRY_INT_INFO_TYPE_PRIV_SW_XCPT:
+ case VMX_ENTRY_INT_INFO_TYPE_SW_XCPT:
+ {
+ if (pEntryIntInfoType)
+ *pEntryIntInfoType = uType;
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+
+/**
+ * Gets the description for a VMX abort reason.
+ *
+ * @returns The descriptive string.
+ * @param enmAbort The VMX abort reason.
+ */
+DECLINLINE(const char *) VMXGetAbortDesc(VMXABORT enmAbort)
+{
+ switch (enmAbort)
+ {
+ case VMXABORT_NONE: return "VMXABORT_NONE";
+ case VMXABORT_SAVE_GUEST_MSRS: return "VMXABORT_SAVE_GUEST_MSRS";
+ case VMXBOART_HOST_PDPTE: return "VMXBOART_HOST_PDPTE";
+ case VMXABORT_CURRENT_VMCS_CORRUPT: return "VMXABORT_CURRENT_VMCS_CORRUPT";
+ case VMXABORT_LOAD_HOST_MSR: return "VMXABORT_LOAD_HOST_MSR";
+ case VMXABORT_MACHINE_CHECK_XCPT: return "VMXABORT_MACHINE_CHECK_XCPT";
+ case VMXABORT_HOST_NOT_IN_LONG_MODE: return "VMXABORT_HOST_NOT_IN_LONG_MODE";
+ default:
+ break;
+ }
+ return "Unknown/invalid";
+}
+
+
+/**
+ * Gets the description for a virtual VMCS state.
+ *
+ * @returns The descriptive string.
+ * @param fVmcsState The virtual-VMCS state.
+ */
+DECLINLINE(const char *) VMXGetVmcsStateDesc(uint8_t fVmcsState)
+{
+ switch (fVmcsState)
+ {
+ case VMX_V_VMCS_LAUNCH_STATE_CLEAR: return "Clear";
+ case VMX_V_VMCS_LAUNCH_STATE_LAUNCHED: return "Launched";
+ default: return "Unknown";
+ }
+}
+
+
+/**
+ * Gets the description for a VM-entry interruption information event type.
+ *
+ * @returns The descriptive string.
+ * @param uType The event type.
+ */
+DECLINLINE(const char *) VMXGetEntryIntInfoTypeDesc(uint8_t uType)
+{
+ switch (uType)
+ {
+ case VMX_ENTRY_INT_INFO_TYPE_EXT_INT: return "External Interrupt";
+ case VMX_ENTRY_INT_INFO_TYPE_NMI: return "NMI";
+ case VMX_ENTRY_INT_INFO_TYPE_HW_XCPT: return "Hardware Exception";
+ case VMX_ENTRY_INT_INFO_TYPE_SW_INT: return "Software Interrupt";
+ case VMX_ENTRY_INT_INFO_TYPE_PRIV_SW_XCPT: return "Priv. Software Exception";
+ case VMX_ENTRY_INT_INFO_TYPE_SW_XCPT: return "Software Exception";
+ case VMX_ENTRY_INT_INFO_TYPE_OTHER_EVENT: return "Other Event";
+ default:
+ break;
+ }
+ return "Unknown/invalid";
+}
+
+
+/**
+ * Gets the description for a VM-exit interruption information event type.
+ *
+ * @returns The descriptive string.
+ * @param uType The event type.
+ */
+DECLINLINE(const char *) VMXGetExitIntInfoTypeDesc(uint8_t uType)
+{
+ switch (uType)
+ {
+ case VMX_EXIT_INT_INFO_TYPE_EXT_INT: return "External Interrupt";
+ case VMX_EXIT_INT_INFO_TYPE_NMI: return "NMI";
+ case VMX_EXIT_INT_INFO_TYPE_HW_XCPT: return "Hardware Exception";
+ case VMX_EXIT_INT_INFO_TYPE_SW_INT: return "Software Interrupt";
+ case VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT: return "Priv. Software Exception";
+ case VMX_EXIT_INT_INFO_TYPE_SW_XCPT: return "Software Exception";
+ default:
+ break;
+ }
+ return "Unknown/invalid";
+}
+
+
+/**
+ * Gets the description for an IDT-vectoring information event type.
+ *
+ * @returns The descriptive string.
+ * @param uType The event type.
+ */
+DECLINLINE(const char *) VMXGetIdtVectoringInfoTypeDesc(uint8_t uType)
+{
+ switch (uType)
+ {
+ case VMX_IDT_VECTORING_INFO_TYPE_EXT_INT: return "External Interrupt";
+ case VMX_IDT_VECTORING_INFO_TYPE_NMI: return "NMI";
+ case VMX_IDT_VECTORING_INFO_TYPE_HW_XCPT: return "Hardware Exception";
+ case VMX_IDT_VECTORING_INFO_TYPE_SW_INT: return "Software Interrupt";
+ case VMX_IDT_VECTORING_INFO_TYPE_PRIV_SW_XCPT: return "Priv. Software Exception";
+ case VMX_IDT_VECTORING_INFO_TYPE_SW_XCPT: return "Software Exception";
+ default:
+ break;
+ }
+ return "Unknown/invalid";
+}
+
+
+/** @} */
+
+
+/** @defgroup grp_hm_vmx_asm VMX Assembly Helpers
+ * @{
+ */
+#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
+
+/**
+ * Dispatches an NMI to the host.
+ */
+DECLASM(int) VMXDispatchHostNmi(void);
+
+
+/**
+ * Executes VMXON.
+ *
+ * @returns VBox status code.
+ * @param HCPhysVmxOn Physical address of VMXON structure.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !VMX_USE_MSC_INTRINSICS
+DECLASM(int) VMXEnable(RTHCPHYS HCPhysVmxOn);
+#else
+DECLINLINE(int) VMXEnable(RTHCPHYS HCPhysVmxOn)
+{
+# if VMX_USE_MSC_INTRINSICS
+ unsigned char rcMsc = __vmx_on(&HCPhysVmxOn);
+ if (RT_LIKELY(rcMsc == 0))
+ return VINF_SUCCESS;
+ return rcMsc == 2 ? VERR_VMX_INVALID_VMXON_PTR : VERR_VMX_VMXON_FAILED;
+
+# elif RT_INLINE_ASM_GNU_STYLE
+# ifdef RT_ARCH_AMD64
+ int rc;
+ __asm__ __volatile__ (
+ "pushq %2 \n\t"
+ ".byte 0xf3, 0x0f, 0xc7, 0x34, 0x24 # VMXON [esp] \n\t"
+ "ja 2f \n\t"
+ "je 1f \n\t"
+ "movl $" RT_XSTR(VERR_VMX_INVALID_VMXON_PTR)", %0 \n\t"
+ "jmp 2f \n\t"
+ "1: \n\t"
+ "movl $" RT_XSTR(VERR_VMX_VMXON_FAILED)", %0 \n\t"
+ "2: \n\t"
+ "add $8, %%rsp \n\t"
+ :"=rm"(rc)
+ :"0"(VINF_SUCCESS),
+ "ir"(HCPhysVmxOn) /* don't allow direct memory reference here, */
+ /* this would not work with -fomit-frame-pointer */
+ :"memory"
+ );
+ return rc;
+# else
+ int rc;
+ __asm__ __volatile__ (
+ "push %3 \n\t"
+ "push %2 \n\t"
+ ".byte 0xf3, 0x0f, 0xc7, 0x34, 0x24 # VMXON [esp] \n\t"
+ "ja 2f \n\t"
+ "je 1f \n\t"
+ "movl $" RT_XSTR(VERR_VMX_INVALID_VMXON_PTR)", %0 \n\t"
+ "jmp 2f \n\t"
+ "1: \n\t"
+ "movl $" RT_XSTR(VERR_VMX_VMXON_FAILED)", %0 \n\t"
+ "2: \n\t"
+ "add $8, %%esp \n\t"
+ :"=rm"(rc)
+ :"0"(VINF_SUCCESS),
+ "ir"((uint32_t)HCPhysVmxOn), /* don't allow direct memory reference here, */
+ "ir"((uint32_t)(HCPhysVmxOn >> 32)) /* this would not work with -fomit-frame-pointer */
+ :"memory"
+ );
+ return rc;
+# endif
+
+# elif defined(RT_ARCH_X86)
+ int rc = VINF_SUCCESS;
+ __asm
+ {
+ push dword ptr [HCPhysVmxOn + 4]
+ push dword ptr [HCPhysVmxOn]
+ _emit 0xf3
+ _emit 0x0f
+ _emit 0xc7
+ _emit 0x34
+ _emit 0x24 /* VMXON [esp] */
+ jnc vmxon_good
+ mov dword ptr [rc], VERR_VMX_INVALID_VMXON_PTR
+ jmp the_end
+
+vmxon_good:
+ jnz the_end
+ mov dword ptr [rc], VERR_VMX_VMXON_FAILED
+the_end:
+ add esp, 8
+ }
+ return rc;
+
+# else
+# error "Shouldn't be here..."
+# endif
+}
+#endif
+
+
+/**
+ * Executes VMXOFF.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !VMX_USE_MSC_INTRINSICS
+DECLASM(void) VMXDisable(void);
+#else
+DECLINLINE(void) VMXDisable(void)
+{
+# if VMX_USE_MSC_INTRINSICS
+ __vmx_off();
+
+# elif RT_INLINE_ASM_GNU_STYLE
+ __asm__ __volatile__ (
+ ".byte 0x0f, 0x01, 0xc4 # VMXOFF \n\t"
+ );
+
+# elif defined(RT_ARCH_X86)
+ __asm
+ {
+ _emit 0x0f
+ _emit 0x01
+ _emit 0xc4 /* VMXOFF */
+ }
+
+# else
+# error "Shouldn't be here..."
+# endif
+}
+#endif
+
+
+/**
+ * Executes VMCLEAR.
+ *
+ * @returns VBox status code.
+ * @param HCPhysVmcs Physical address of VM control structure.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !VMX_USE_MSC_INTRINSICS
+DECLASM(int) VMXClearVmcs(RTHCPHYS HCPhysVmcs);
+#else
+DECLINLINE(int) VMXClearVmcs(RTHCPHYS HCPhysVmcs)
+{
+# if VMX_USE_MSC_INTRINSICS
+ unsigned char rcMsc = __vmx_vmclear(&HCPhysVmcs);
+ if (RT_LIKELY(rcMsc == 0))
+ return VINF_SUCCESS;
+ return VERR_VMX_INVALID_VMCS_PTR;
+
+# elif RT_INLINE_ASM_GNU_STYLE
+# ifdef RT_ARCH_AMD64
+ int rc;
+ __asm__ __volatile__ (
+ "pushq %2 \n\t"
+ ".byte 0x66, 0x0f, 0xc7, 0x34, 0x24 # VMCLEAR [esp] \n\t"
+ "jnc 1f \n\t"
+ "movl $" RT_XSTR(VERR_VMX_INVALID_VMCS_PTR)", %0 \n\t"
+ "1: \n\t"
+ "add $8, %%rsp \n\t"
+ :"=rm"(rc)
+ :"0"(VINF_SUCCESS),
+ "ir"(HCPhysVmcs) /* don't allow direct memory reference here, */
+ /* this would not work with -fomit-frame-pointer */
+ :"memory"
+ );
+ return rc;
+# else
+ int rc;
+ __asm__ __volatile__ (
+ "push %3 \n\t"
+ "push %2 \n\t"
+ ".byte 0x66, 0x0f, 0xc7, 0x34, 0x24 # VMCLEAR [esp] \n\t"
+ "jnc 1f \n\t"
+ "movl $" RT_XSTR(VERR_VMX_INVALID_VMCS_PTR)", %0 \n\t"
+ "1: \n\t"
+ "add $8, %%esp \n\t"
+ :"=rm"(rc)
+ :"0"(VINF_SUCCESS),
+ "ir"((uint32_t)HCPhysVmcs), /* don't allow direct memory reference here, */
+ "ir"((uint32_t)(HCPhysVmcs >> 32)) /* this would not work with -fomit-frame-pointer */
+ :"memory"
+ );
+ return rc;
+# endif
+
+# elif defined(RT_ARCH_X86)
+ int rc = VINF_SUCCESS;
+ __asm
+ {
+ push dword ptr [HCPhysVmcs + 4]
+ push dword ptr [HCPhysVmcs]
+ _emit 0x66
+ _emit 0x0f
+ _emit 0xc7
+ _emit 0x34
+ _emit 0x24 /* VMCLEAR [esp] */
+ jnc success
+ mov dword ptr [rc], VERR_VMX_INVALID_VMCS_PTR
+success:
+ add esp, 8
+ }
+ return rc;
+
+# else
+# error "Shouldn't be here..."
+# endif
+}
+#endif
+
+
+/**
+ * Executes VMPTRLD.
+ *
+ * @returns VBox status code.
+ * @param HCPhysVmcs Physical address of VMCS structure.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !VMX_USE_MSC_INTRINSICS
+DECLASM(int) VMXLoadVmcs(RTHCPHYS HCPhysVmcs);
+#else
+DECLINLINE(int) VMXLoadVmcs(RTHCPHYS HCPhysVmcs)
+{
+# if VMX_USE_MSC_INTRINSICS
+ unsigned char rcMsc = __vmx_vmptrld(&HCPhysVmcs);
+ if (RT_LIKELY(rcMsc == 0))
+ return VINF_SUCCESS;
+ return VERR_VMX_INVALID_VMCS_PTR;
+
+# elif RT_INLINE_ASM_GNU_STYLE
+# ifdef RT_ARCH_AMD64
+ int rc;
+ __asm__ __volatile__ (
+ "pushq %2 \n\t"
+ ".byte 0x0f, 0xc7, 0x34, 0x24 # VMPTRLD [esp] \n\t"
+ "jnc 1f \n\t"
+ "movl $" RT_XSTR(VERR_VMX_INVALID_VMCS_PTR)", %0 \n\t"
+ "1: \n\t"
+ "add $8, %%rsp \n\t"
+ :"=rm"(rc)
+ :"0"(VINF_SUCCESS),
+ "ir"(HCPhysVmcs) /* don't allow direct memory reference here, */
+ /* this will not work with -fomit-frame-pointer */
+ :"memory"
+ );
+ return rc;
+# else
+ int rc;
+ __asm__ __volatile__ (
+ "push %3 \n\t"
+ "push %2 \n\t"
+ ".byte 0x0f, 0xc7, 0x34, 0x24 # VMPTRLD [esp] \n\t"
+ "jnc 1f \n\t"
+ "movl $" RT_XSTR(VERR_VMX_INVALID_VMCS_PTR)", %0 \n\t"
+ "1: \n\t"
+ "add $8, %%esp \n\t"
+ :"=rm"(rc)
+ :"0"(VINF_SUCCESS),
+ "ir"((uint32_t)HCPhysVmcs), /* don't allow direct memory reference here, */
+ "ir"((uint32_t)(HCPhysVmcs >> 32)) /* this will not work with -fomit-frame-pointer */
+ :"memory"
+ );
+ return rc;
+# endif
+
+# elif defined(RT_ARCH_X86)
+ int rc = VINF_SUCCESS;
+ __asm
+ {
+ push dword ptr [HCPhysVmcs + 4]
+ push dword ptr [HCPhysVmcs]
+ _emit 0x0f
+ _emit 0xc7
+ _emit 0x34
+ _emit 0x24 /* VMPTRLD [esp] */
+ jnc success
+ mov dword ptr [rc], VERR_VMX_INVALID_VMCS_PTR
+success:
+ add esp, 8
+ }
+ return rc;
+
+# else
+# error "Shouldn't be here..."
+# endif
+}
+#endif
+
+
+/**
+ * Executes VMPTRST.
+ *
+ * @returns VBox status code.
+ * @param pHCPhysVmcs Where to store the physical address of the current
+ * VMCS.
+ */
+DECLASM(int) VMXGetCurrentVmcs(RTHCPHYS *pHCPhysVmcs);
+
+
+/**
+ * Executes VMWRITE for a 32-bit field.
+ *
+ * @returns VBox status code.
+ * @retval VINF_SUCCESS.
+ * @retval VERR_VMX_INVALID_VMCS_PTR.
+ * @retval VERR_VMX_INVALID_VMCS_FIELD.
+ *
+ * @param uFieldEnc VMCS field encoding.
+ * @param u32Val The 32-bit value to set.
+ *
+ * @remarks The values of the two status codes can be OR'ed together, the result
+ * will be VERR_VMX_INVALID_VMCS_PTR.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !VMX_USE_MSC_INTRINSICS
+DECLASM(int) VMXWriteVmcs32(uint32_t uFieldEnc, uint32_t u32Val);
+#else
+DECLINLINE(int) VMXWriteVmcs32(uint32_t uFieldEnc, uint32_t u32Val)
+{
+# if VMX_USE_MSC_INTRINSICS
+# ifdef VBOX_WITH_VMREAD_VMWRITE_NOCHECK
+ __vmx_vmwrite(uFieldEnc, u32Val);
+ return VINF_SUCCESS;
+# else
+ unsigned char rcMsc = __vmx_vmwrite(uFieldEnc, u32Val);
+ if (RT_LIKELY(rcMsc == 0))
+ return VINF_SUCCESS;
+ return rcMsc == 2 ? VERR_VMX_INVALID_VMCS_PTR : VERR_VMX_INVALID_VMCS_FIELD;
+# endif
+
+# elif RT_INLINE_ASM_GNU_STYLE
+# ifdef VBOX_WITH_VMREAD_VMWRITE_NOCHECK
+ __asm__ __volatile__ (
+ ".byte 0x0f, 0x79, 0xc2 # VMWRITE eax, edx \n\t"
+ :
+ :"a"(uFieldEnc),
+ "d"(u32Val)
+ );
+ return VINF_SUCCESS;
+# else
+ int rc;
+ __asm__ __volatile__ (
+ ".byte 0x0f, 0x79, 0xc2 # VMWRITE eax, edx \n\t"
+ "ja 2f \n\t"
+ "je 1f \n\t"
+ "movl $" RT_XSTR(VERR_VMX_INVALID_VMCS_PTR)", %0 \n\t"
+ "jmp 2f \n\t"
+ "1: \n\t"
+ "movl $" RT_XSTR(VERR_VMX_INVALID_VMCS_FIELD)", %0 \n\t"
+ "2: \n\t"
+ :"=rm"(rc)
+ :"0"(VINF_SUCCESS),
+ "a"(uFieldEnc),
+ "d"(u32Val)
+ );
+ return rc;
+# endif
+
+# elif defined(RT_ARCH_X86)
+ int rc = VINF_SUCCESS;
+ __asm
+ {
+ push dword ptr [u32Val]
+ mov eax, [uFieldEnc]
+ _emit 0x0f
+ _emit 0x79
+ _emit 0x04
+ _emit 0x24 /* VMWRITE eax, [esp] */
+ jnc valid_vmcs
+ mov dword ptr [rc], VERR_VMX_INVALID_VMCS_PTR
+ jmp the_end
+valid_vmcs:
+ jnz the_end
+ mov dword ptr [rc], VERR_VMX_INVALID_VMCS_FIELD
+the_end:
+ add esp, 4
+ }
+ return rc;
+
+# else
+# error "Shouldn't be here..."
+# endif
+}
+#endif
+
+
+/**
+ * Executes VMWRITE for a 64-bit field.
+ *
+ * @returns VBox status code.
+ * @retval VINF_SUCCESS.
+ * @retval VERR_VMX_INVALID_VMCS_PTR.
+ * @retval VERR_VMX_INVALID_VMCS_FIELD.
+ *
+ * @param uFieldEnc The VMCS field encoding.
+ * @param u64Val The 16, 32 or 64-bit value to set.
+ *
+ * @remarks The values of the two status codes can be OR'ed together, the result
+ * will be VERR_VMX_INVALID_VMCS_PTR.
+ */
+#if defined(RT_ARCH_X86) || (RT_INLINE_ASM_EXTERNAL && !VMX_USE_MSC_INTRINSICS)
+DECLASM(int) VMXWriteVmcs64(uint32_t uFieldEnc, uint64_t u64Val);
+#else
+DECLINLINE(int) VMXWriteVmcs64(uint32_t uFieldEnc, uint64_t u64Val)
+{
+# if VMX_USE_MSC_INTRINSICS
+# ifdef VBOX_WITH_VMREAD_VMWRITE_NOCHECK
+ __vmx_vmwrite(uFieldEnc, u64Val);
+ return VINF_SUCCESS;
+# else
+ unsigned char rcMsc = __vmx_vmwrite(uFieldEnc, u64Val);
+ if (RT_LIKELY(rcMsc == 0))
+ return VINF_SUCCESS;
+ return rcMsc == 2 ? VERR_VMX_INVALID_VMCS_PTR : VERR_VMX_INVALID_VMCS_FIELD;
+# endif
+
+# elif RT_INLINE_ASM_GNU_STYLE
+# ifdef VBOX_WITH_VMREAD_VMWRITE_NOCHECK
+ __asm__ __volatile__ (
+ ".byte 0x0f, 0x79, 0xc2 # VMWRITE eax, edx \n\t"
+ :
+ :"a"(uFieldEnc),
+ "d"(u64Val)
+ );
+ return VINF_SUCCESS;
+# else
+ int rc;
+ __asm__ __volatile__ (
+ ".byte 0x0f, 0x79, 0xc2 # VMWRITE eax, edx \n\t"
+ "ja 2f \n\t"
+ "je 1f \n\t"
+ "movl $" RT_XSTR(VERR_VMX_INVALID_VMCS_PTR)", %0 \n\t"
+ "jmp 2f \n\t"
+ "1: \n\t"
+ "movl $" RT_XSTR(VERR_VMX_INVALID_VMCS_FIELD)", %0 \n\t"
+ "2: \n\t"
+ :"=rm"(rc)
+ :"0"(VINF_SUCCESS),
+ "a"(uFieldEnc),
+ "d"(u64Val)
+ );
+ return rc;
+# endif
+
+# else
+# error "Shouldn't be here..."
+# endif
+}
+#endif
+
+
+/**
+ * Executes VMWRITE for a 16-bit VMCS field.
+ *
+ * @returns VBox status code.
+ * @retval VINF_SUCCESS.
+ * @retval VERR_VMX_INVALID_VMCS_PTR.
+ * @retval VERR_VMX_INVALID_VMCS_FIELD.
+ *
+ * @param uVmcsField The VMCS field.
+ * @param u16Val The 16-bit value to set.
+ *
+ * @remarks The values of the two status codes can be OR'ed together, the result
+ * will be VERR_VMX_INVALID_VMCS_PTR.
+ */
+DECLINLINE(int) VMXWriteVmcs16(uint32_t uVmcsField, uint16_t u16Val)
+{
+ AssertMsg(RT_BF_GET(uVmcsField, VMX_BF_VMCSFIELD_WIDTH) == VMX_VMCSFIELD_WIDTH_16BIT, ("%#RX32\n", uVmcsField));
+ return VMXWriteVmcs32(uVmcsField, u16Val);
+}
+
+
+/**
+ * Executes VMWRITE for a natural-width VMCS field.
+ */
+#ifdef RT_ARCH_AMD64
+# define VMXWriteVmcsNw VMXWriteVmcs64
+#else
+# define VMXWriteVmcsNw VMXWriteVmcs32
+#endif
+
+
+/**
+ * Invalidate a page using INVEPT.
+ *
+ * @returns VBox status code.
+ * @param enmFlush Type of flush.
+ * @param pDescriptor Pointer to the descriptor.
+ */
+DECLASM(int) VMXR0InvEPT(VMXTLBFLUSHEPT enmFlush, uint64_t *pDescriptor);
+
+
+/**
+ * Invalidate a page using INVVPID.
+ *
+ * @returns VBox status code.
+ * @param enmFlush Type of flush.
+ * @param pDescriptor Pointer to the descriptor.
+ */
+DECLASM(int) VMXR0InvVPID(VMXTLBFLUSHVPID enmFlush, uint64_t *pDescriptor);
+
+
+/**
+ * Executes VMREAD for a 32-bit field.
+ *
+ * @returns VBox status code.
+ * @retval VINF_SUCCESS.
+ * @retval VERR_VMX_INVALID_VMCS_PTR.
+ * @retval VERR_VMX_INVALID_VMCS_FIELD.
+ *
+ * @param uFieldEnc The VMCS field encoding.
+ * @param pData Where to store VMCS field value.
+ *
+ * @remarks The values of the two status codes can be OR'ed together, the result
+ * will be VERR_VMX_INVALID_VMCS_PTR.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !VMX_USE_MSC_INTRINSICS
+DECLASM(int) VMXReadVmcs32(uint32_t uFieldEnc, uint32_t *pData);
+#else
+DECLINLINE(int) VMXReadVmcs32(uint32_t uFieldEnc, uint32_t *pData)
+{
+# if VMX_USE_MSC_INTRINSICS
+# ifdef VBOX_WITH_VMREAD_VMWRITE_NOCHECK
+ uint64_t u64Tmp = 0;
+ __vmx_vmread(uFieldEnc, &u64Tmp);
+ *pData = (uint32_t)u64Tmp;
+ return VINF_SUCCESS;
+# else
+ unsigned char rcMsc;
+ uint64_t u64Tmp;
+ rcMsc = __vmx_vmread(uFieldEnc, &u64Tmp);
+ *pData = (uint32_t)u64Tmp;
+ if (RT_LIKELY(rcMsc == 0))
+ return VINF_SUCCESS;
+ return rcMsc == 2 ? VERR_VMX_INVALID_VMCS_PTR : VERR_VMX_INVALID_VMCS_FIELD;
+# endif
+
+# elif VMX_USE_GNU_STYLE_INLINE_VMX_INSTRUCTIONS
+ RTCCUINTREG uTmp = 0;
+# ifdef VBOX_WITH_VMREAD_VMWRITE_NOCHECK
+ __asm__ __volatile__("vmread %[uField],%[uDst]"
+ : [uDst] "=mr" (uTmp)
+ : [uField] "r" ((RTCCUINTREG)uFieldEnc));
+ *pData = (uint32_t)uTmp;
+ return VINF_SUCCESS;
+# else
+#if 0
+ int rc;
+ __asm__ __volatile__("vmread %[uField],%[uDst]\n\t"
+ "movl %[rcSuccess],%[rc]\n\t"
+# if VMX_USE_GNU_STYLE_INLINE_SECTION_TRICK
+ "jna 1f\n\t"
+ ".section .text.vmread_failures, \"ax?\"\n\t"
+ "1:\n\t"
+ "movl %[rcInvalidVmcsPtr],%[rc]\n\t"
+ "jnz 2f\n\t"
+ "movl %[rcInvalidVmcsField],%[rc]\n\t"
+ "2:\n\t"
+ "jmp 3f\n\t"
+ ".previous\n\t"
+ "3:\n\t"
+# else
+ "ja 1f\n\t"
+ "movl %[rcInvalidVmcsPtr],%[rc]\n\t"
+ "jnz 1f\n\t"
+ "movl %[rcInvalidVmcsField],%[rc]\n\t"
+ "1:\n\t"
+# endif
+ : [uDst] "=mr" (uTmp)
+ , [rc] "=r" (rc)
+ : [uField] "r" ((RTCCUINTREG)uFieldEnc)
+ , [rcSuccess] "i" (VINF_SUCCESS)
+ , [rcInvalidVmcsPtr] "i" (VERR_VMX_INVALID_VMCS_PTR)
+ , [rcInvalidVmcsField] "i" (VERR_VMX_INVALID_VMCS_FIELD));
+ *pData = uTmp;
+ return rc;
+#else
+ int fSuccess, fFieldError;
+ __asm__ __volatile__("vmread %[uField],%[uDst]"
+ : [uDst] "=mr" (uTmp)
+ , "=@cca" (fSuccess)
+ , "=@ccnc" (fFieldError)
+ : [uField] "r" ((RTCCUINTREG)uFieldEnc));
+ *pData = uTmp;
+ return RT_LIKELY(fSuccess) ? VINF_SUCCESS : fFieldError ? VERR_VMX_INVALID_VMCS_FIELD : VERR_VMX_INVALID_VMCS_PTR;
+#endif
+# endif
+
+# elif RT_INLINE_ASM_GNU_STYLE
+# ifdef VBOX_WITH_VMREAD_VMWRITE_NOCHECK
+ __asm__ __volatile__ (
+ ".byte 0x0f, 0x78, 0xc2 # VMREAD eax, edx \n\t"
+ :"=d"(*pData)
+ :"a"(uFieldEnc),
+ "d"(0)
+ );
+ return VINF_SUCCESS;
+# else
+ int rc;
+ __asm__ __volatile__ (
+ "movl $" RT_XSTR(VINF_SUCCESS)", %0 \n\t"
+ ".byte 0x0f, 0x78, 0xc2 # VMREAD eax, edx \n\t"
+ "ja 2f \n\t"
+ "je 1f \n\t"
+ "movl $" RT_XSTR(VERR_VMX_INVALID_VMCS_PTR)", %0 \n\t"
+ "jmp 2f \n\t"
+ "1: \n\t"
+ "movl $" RT_XSTR(VERR_VMX_INVALID_VMCS_FIELD)", %0 \n\t"
+ "2: \n\t"
+ :"=&r"(rc),
+ "=d"(*pData)
+ :"a"(uFieldEnc),
+ "d"(0)
+ );
+ return rc;
+# endif
+
+# elif defined(RT_ARCH_X86)
+ int rc = VINF_SUCCESS;
+ __asm
+ {
+ sub esp, 4
+ mov dword ptr [esp], 0
+ mov eax, [uFieldEnc]
+ _emit 0x0f
+ _emit 0x78
+ _emit 0x04
+ _emit 0x24 /* VMREAD eax, [esp] */
+ mov edx, pData
+ pop dword ptr [edx]
+ jnc valid_vmcs
+ mov dword ptr [rc], VERR_VMX_INVALID_VMCS_PTR
+ jmp the_end
+valid_vmcs:
+ jnz the_end
+ mov dword ptr [rc], VERR_VMX_INVALID_VMCS_FIELD
+the_end:
+ }
+ return rc;
+
+# else
+# error "Shouldn't be here..."
+# endif
+}
+#endif
+
+
+/**
+ * Executes VMREAD for a 64-bit field.
+ *
+ * @returns VBox status code.
+ * @retval VINF_SUCCESS.
+ * @retval VERR_VMX_INVALID_VMCS_PTR.
+ * @retval VERR_VMX_INVALID_VMCS_FIELD.
+ *
+ * @param uFieldEnc The VMCS field encoding.
+ * @param pData Where to store VMCS field value.
+ *
+ * @remarks The values of the two status codes can be OR'ed together, the result
+ * will be VERR_VMX_INVALID_VMCS_PTR.
+ */
+#if defined(RT_ARCH_X86) || (RT_INLINE_ASM_EXTERNAL && !VMX_USE_MSC_INTRINSICS)
+DECLASM(int) VMXReadVmcs64(uint32_t uFieldEnc, uint64_t *pData);
+#else
+DECLINLINE(int) VMXReadVmcs64(uint32_t uFieldEnc, uint64_t *pData)
+{
+# if VMX_USE_MSC_INTRINSICS
+# ifdef VBOX_WITH_VMREAD_VMWRITE_NOCHECK
+ __vmx_vmread(uFieldEnc, pData);
+ return VINF_SUCCESS;
+# else
+ unsigned char rcMsc;
+ rcMsc = __vmx_vmread(uFieldEnc, pData);
+ if (RT_LIKELY(rcMsc == 0))
+ return VINF_SUCCESS;
+ return rcMsc == 2 ? VERR_VMX_INVALID_VMCS_PTR : VERR_VMX_INVALID_VMCS_FIELD;
+# endif
+
+# elif VMX_USE_GNU_STYLE_INLINE_VMX_INSTRUCTIONS
+ uint64_t uTmp = 0;
+# ifdef VBOX_WITH_VMREAD_VMWRITE_NOCHECK
+ __asm__ __volatile__("vmreadq %[uField],%[uDst]"
+ : [uDst] "=m" (uTmp)
+ : [uField] "r" ((uint64_t)uFieldEnc));
+ *pData = uTmp;
+ return VINF_SUCCESS;
+# elif 0
+ int rc;
+ __asm__ __volatile__("vmreadq %[uField],%[uDst]\n\t"
+ "movl %[rcSuccess],%[rc]\n\t"
+# if VMX_USE_GNU_STYLE_INLINE_SECTION_TRICK
+ "jna 1f\n\t"
+ ".section .text.vmread_failures, \"ax?\"\n\t"
+ "1:\n\t"
+ "movl %[rcInvalidVmcsPtr],%[rc]\n\t"
+ "jnz 2f\n\t"
+ "movl %[rcInvalidVmcsField],%[rc]\n\t"
+ "2:\n\t"
+ "jmp 3f\n\t"
+ ".previous\n\t"
+ "3:\n\t"
+# else
+ "ja 1f\n\t"
+ "movl %[rcInvalidVmcsPtr],%[rc]\n\t"
+ "jnz 1f\n\t"
+ "movl %[rcInvalidVmcsField],%[rc]\n\t"
+ "1:\n\t"
+# endif
+ : [uDst] "=mr" (uTmp)
+ , [rc] "=r" (rc)
+ : [uField] "r" ((uint64_t)uFieldEnc)
+ , [rcSuccess] "i" (VINF_SUCCESS)
+ , [rcInvalidVmcsPtr] "i" (VERR_VMX_INVALID_VMCS_PTR)
+ , [rcInvalidVmcsField] "i" (VERR_VMX_INVALID_VMCS_FIELD)
+ );
+ *pData = uTmp;
+ return rc;
+# else
+ int fSuccess, fFieldError;
+ __asm__ __volatile__("vmread %[uField],%[uDst]"
+ : [uDst] "=mr" (uTmp)
+ , "=@cca" (fSuccess)
+ , "=@ccnc" (fFieldError)
+ : [uField] "r" ((RTCCUINTREG)uFieldEnc));
+ *pData = uTmp;
+ return RT_LIKELY(fSuccess) ? VINF_SUCCESS : fFieldError ? VERR_VMX_INVALID_VMCS_FIELD : VERR_VMX_INVALID_VMCS_PTR;
+# endif
+
+# elif RT_INLINE_ASM_GNU_STYLE
+# ifdef VBOX_WITH_VMREAD_VMWRITE_NOCHECK
+ __asm__ __volatile__ (
+ ".byte 0x0f, 0x78, 0xc2 # VMREAD eax, edx \n\t"
+ :"=d"(*pData)
+ :"a"(uFieldEnc),
+ "d"(0)
+ );
+ return VINF_SUCCESS;
+# else
+ int rc;
+ __asm__ __volatile__ (
+ "movl $" RT_XSTR(VINF_SUCCESS)", %0 \n\t"
+ ".byte 0x0f, 0x78, 0xc2 # VMREAD eax, edx \n\t"
+ "ja 2f \n\t"
+ "je 1f \n\t"
+ "movl $" RT_XSTR(VERR_VMX_INVALID_VMCS_PTR)", %0 \n\t"
+ "jmp 2f \n\t"
+ "1: \n\t"
+ "movl $" RT_XSTR(VERR_VMX_INVALID_VMCS_FIELD)", %0 \n\t"
+ "2: \n\t"
+ :"=&r"(rc),
+ "=d"(*pData)
+ :"a"(uFieldEnc),
+ "d"(0)
+ );
+ return rc;
+# endif
+
+# else
+# error "Shouldn't be here..."
+# endif
+}
+#endif
+
+
+/**
+ * Executes VMREAD for a 16-bit field.
+ *
+ * @returns VBox status code.
+ * @retval VINF_SUCCESS.
+ * @retval VERR_VMX_INVALID_VMCS_PTR.
+ * @retval VERR_VMX_INVALID_VMCS_FIELD.
+ *
+ * @param uVmcsField The VMCS field.
+ * @param pData Where to store VMCS field value.
+ *
+ * @remarks The values of the two status codes can be OR'ed together, the result
+ * will be VERR_VMX_INVALID_VMCS_PTR.
+ */
+DECLINLINE(int) VMXReadVmcs16(uint32_t uVmcsField, uint16_t *pData)
+{
+ uint32_t u32Tmp;
+ int rc;
+ AssertMsg(RT_BF_GET(uVmcsField, VMX_BF_VMCSFIELD_WIDTH) == VMX_VMCSFIELD_WIDTH_16BIT, ("%#RX32\n", uVmcsField));
+ rc = VMXReadVmcs32(uVmcsField, &u32Tmp);
+ *pData = (uint16_t)u32Tmp;
+ return rc;
+}
+
+
+/**
+ * Executes VMREAD for a natural-width VMCS field.
+ */
+#ifdef RT_ARCH_AMD64
+# define VMXReadVmcsNw VMXReadVmcs64
+#else
+# define VMXReadVmcsNw VMXReadVmcs32
+#endif
+
+#endif /* RT_ARCH_AMD64 || RT_ARCH_X86 */
+
+/** @} */
+
+#endif /* !VBOX_INCLUDED_vmm_hmvmxinline_h */
+
diff --git a/include/VBox/vmm/iem.h b/include/VBox/vmm/iem.h
new file mode 100644
index 00000000..ef50970d
--- /dev/null
+++ b/include/VBox/vmm/iem.h
@@ -0,0 +1,422 @@
+/** @file
+ * IEM - Interpreted Execution Manager.
+ */
+
+/*
+ * Copyright (C) 2011-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vmm_iem_h
+#define VBOX_INCLUDED_vmm_iem_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/types.h>
+#include <VBox/vmm/trpm.h>
+#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
+# include <VBox/vmm/hm_vmx.h>
+#endif
+#include <iprt/assert.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_iem The Interpreted Execution Manager API.
+ * @ingroup grp_vmm
+ * @{
+ */
+
+/** @name IEMXCPTRAISEINFO_XXX - Extra info. on a recursive exception situation.
+ *
+ * This is primarily used by HM for working around a PGM limitation (see
+ * @bugref{6607}) and special NMI/IRET handling. In the future, this may be
+ * used for diagnostics.
+ *
+ * @{
+ */
+typedef uint32_t IEMXCPTRAISEINFO;
+/** Pointer to a IEMXCPTINFO type. */
+typedef IEMXCPTRAISEINFO *PIEMXCPTRAISEINFO;
+/** No addition info. available. */
+#define IEMXCPTRAISEINFO_NONE RT_BIT_32(0)
+/** Delivery of a \#AC caused another \#AC. */
+#define IEMXCPTRAISEINFO_AC_AC RT_BIT_32(1)
+/** Delivery of a \#PF caused another \#PF. */
+#define IEMXCPTRAISEINFO_PF_PF RT_BIT_32(2)
+/** Delivery of a \#PF caused some contributory exception. */
+#define IEMXCPTRAISEINFO_PF_CONTRIBUTORY_XCPT RT_BIT_32(3)
+/** Delivery of an external interrupt caused an exception. */
+#define IEMXCPTRAISEINFO_EXT_INT_XCPT RT_BIT_32(4)
+/** Delivery of an external interrupt caused an \#PF. */
+#define IEMXCPTRAISEINFO_EXT_INT_PF RT_BIT_32(5)
+/** Delivery of a software interrupt caused an exception. */
+#define IEMXCPTRAISEINFO_SOFT_INT_XCPT RT_BIT_32(6)
+/** Delivery of an NMI caused an exception. */
+#define IEMXCPTRAISEINFO_NMI_XCPT RT_BIT_32(7)
+/** Delivery of an NMI caused a \#PF. */
+#define IEMXCPTRAISEINFO_NMI_PF RT_BIT_32(8)
+/** Can re-execute the instruction at CS:RIP. */
+#define IEMXCPTRAISEINFO_CAN_REEXEC_INSTR RT_BIT_32(9)
+/** @} */
+
+
+/** @name IEMXCPTRAISE_XXX - Ways to handle a recursive exception condition.
+ * @{ */
+typedef enum IEMXCPTRAISE
+{
+ /** Raise the current (second) exception. */
+ IEMXCPTRAISE_CURRENT_XCPT = 0,
+ /** Re-raise the previous (first) event (for HM, unused by IEM). */
+ IEMXCPTRAISE_PREV_EVENT,
+ /** Re-execute instruction at CS:RIP (for HM, unused by IEM). */
+ IEMXCPTRAISE_REEXEC_INSTR,
+ /** Raise a \#DF exception. */
+ IEMXCPTRAISE_DOUBLE_FAULT,
+ /** Raise a triple fault. */
+ IEMXCPTRAISE_TRIPLE_FAULT,
+ /** Cause a CPU hang. */
+ IEMXCPTRAISE_CPU_HANG,
+ /** Invalid sequence of events. */
+ IEMXCPTRAISE_INVALID = 0x7fffffff
+} IEMXCPTRAISE;
+/** Pointer to a IEMXCPTRAISE type. */
+typedef IEMXCPTRAISE *PIEMXCPTRAISE;
+/** @} */
+
+
+/** @name Operand or addressing mode.
+ * @{ */
+typedef uint8_t IEMMODE;
+#define IEMMODE_16BIT 0
+#define IEMMODE_32BIT 1
+#define IEMMODE_64BIT 2
+/** @} */
+
+
+/** @name IEM_XCPT_FLAGS_XXX - flags for iemRaiseXcptOrInt.
+ * @{ */
+/** CPU exception. */
+#define IEM_XCPT_FLAGS_T_CPU_XCPT RT_BIT_32(0)
+/** External interrupt (from PIC, APIC, whatever). */
+#define IEM_XCPT_FLAGS_T_EXT_INT RT_BIT_32(1)
+/** Software interrupt (int or into, not bound).
+ * Returns to the following instruction */
+#define IEM_XCPT_FLAGS_T_SOFT_INT RT_BIT_32(2)
+/** Takes an error code. */
+#define IEM_XCPT_FLAGS_ERR RT_BIT_32(3)
+/** Takes a CR2. */
+#define IEM_XCPT_FLAGS_CR2 RT_BIT_32(4)
+/** Generated by the breakpoint instruction. */
+#define IEM_XCPT_FLAGS_BP_INSTR RT_BIT_32(5)
+/** Generated by a DRx instruction breakpoint and RF should be cleared. */
+#define IEM_XCPT_FLAGS_DRx_INSTR_BP RT_BIT_32(6)
+/** Generated by the icebp instruction. */
+#define IEM_XCPT_FLAGS_ICEBP_INSTR RT_BIT_32(7)
+/** Generated by the overflow instruction. */
+#define IEM_XCPT_FLAGS_OF_INSTR RT_BIT_32(8)
+/** @} */
+
+
+/** @name IEMTARGETCPU_XXX - IEM target CPU specification.
+ *
+ * This is a gross simpliciation of CPUMMICROARCH for dealing with really old
+ * CPUs which didn't have much in the way of hinting at supported instructions
+ * and features. This slowly changes with the introduction of CPUID with the
+ * Intel Pentium.
+ *
+ * @{
+ */
+/** The dynamic target CPU mode is for getting thru the BIOS and then use
+ * the debugger or modifying instruction behaviour (e.g. HLT) to switch to a
+ * different target CPU. */
+#define IEMTARGETCPU_DYNAMIC UINT32_C(0)
+/** Intel 8086/8088. */
+#define IEMTARGETCPU_8086 UINT32_C(1)
+/** NEC V20/V30.
+ * @remarks must be between 8086 and 80186. */
+#define IEMTARGETCPU_V20 UINT32_C(2)
+/** Intel 80186/80188. */
+#define IEMTARGETCPU_186 UINT32_C(3)
+/** Intel 80286. */
+#define IEMTARGETCPU_286 UINT32_C(4)
+/** Intel 80386. */
+#define IEMTARGETCPU_386 UINT32_C(5)
+/** Intel 80486. */
+#define IEMTARGETCPU_486 UINT32_C(6)
+/** Intel Pentium . */
+#define IEMTARGETCPU_PENTIUM UINT32_C(7)
+/** Intel PentiumPro. */
+#define IEMTARGETCPU_PPRO UINT32_C(8)
+/** A reasonably current CPU, probably newer than the pentium pro when it comes
+ * to the feature set and behaviour. Generally the CPUID info and CPU vendor
+ * dicates the behaviour here. */
+#define IEMTARGETCPU_CURRENT UINT32_C(9)
+/** @} */
+
+
+/** @name IEM status codes.
+ *
+ * Not quite sure how this will play out in the end, just aliasing safe status
+ * codes for now.
+ *
+ * @{ */
+#define VINF_IEM_RAISED_XCPT VINF_EM_RESCHEDULE
+/** @} */
+
+
+/** The CPUMCTX_EXTRN_XXX mask required to be cleared when interpreting anything.
+ * IEM will ASSUME the caller of IEM APIs has ensured these are already present. */
+#define IEM_CPUMCTX_EXTRN_MUST_MASK ( CPUMCTX_EXTRN_GPRS_MASK \
+ | CPUMCTX_EXTRN_RIP \
+ | CPUMCTX_EXTRN_RFLAGS \
+ | CPUMCTX_EXTRN_SS \
+ | CPUMCTX_EXTRN_CS \
+ | CPUMCTX_EXTRN_CR0 \
+ | CPUMCTX_EXTRN_CR3 \
+ | CPUMCTX_EXTRN_CR4 \
+ | CPUMCTX_EXTRN_APIC_TPR \
+ | CPUMCTX_EXTRN_EFER \
+ | CPUMCTX_EXTRN_DR7 )
+/** The CPUMCTX_EXTRN_XXX mask needed when injecting an exception/interrupt.
+ * IEM will import missing bits, callers are encouraged to make these registers
+ * available prior to injection calls if fetching state anyway. */
+#define IEM_CPUMCTX_EXTRN_XCPT_MASK ( IEM_CPUMCTX_EXTRN_MUST_MASK \
+ | CPUMCTX_EXTRN_CR2 \
+ | CPUMCTX_EXTRN_SREG_MASK \
+ | CPUMCTX_EXTRN_TABLE_MASK )
+/** The CPUMCTX_EXTRN_XXX mask required to be cleared when calling any
+ * IEMExecDecoded API not using memory. IEM will ASSUME the caller of IEM
+ * APIs has ensured these are already present.
+ * @note ASSUMES execution engine has checked for instruction breakpoints
+ * during decoding. */
+#define IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK ( CPUMCTX_EXTRN_RIP \
+ | CPUMCTX_EXTRN_RFLAGS \
+ | CPUMCTX_EXTRN_SS /* for CPL */ \
+ | CPUMCTX_EXTRN_CS /* for mode */ \
+ | CPUMCTX_EXTRN_CR0 /* for mode */ \
+ | CPUMCTX_EXTRN_EFER /* for mode */ )
+/** The CPUMCTX_EXTRN_XXX mask required to be cleared when calling any
+ * IEMExecDecoded API using memory. IEM will ASSUME the caller of IEM
+ * APIs has ensured these are already present.
+ * @note ASSUMES execution engine has checked for instruction breakpoints
+ * during decoding. */
+#define IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK ( IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK \
+ | CPUMCTX_EXTRN_CR3 /* for page tables */ \
+ | CPUMCTX_EXTRN_CR4 /* for mode paging mode */ \
+ | CPUMCTX_EXTRN_DR7 /* for memory breakpoints */ )
+
+#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
+/** The CPUMCTX_EXTRN_XXX mask needed when calling IEMExecDecodedVmlaunchVmresume().
+ * IEM will ASSUME the caller has ensured these are already present. */
+# define IEM_CPUMCTX_EXTRN_VMX_VMENTRY_MASK ( IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK \
+ | CPUMCTX_EXTRN_CR2 \
+ | CPUMCTX_EXTRN_HWVIRT )
+
+/** The CPUMCTX_EXTRN_XXX mask that the IEM VM-exit code will import on-demand when
+ * needed, primarily because there are several IEM VM-exit interface functions and
+ * some of which may not cause a VM-exit at all.
+ *
+ * This is currently unused, but keeping it here in case we can get away a bit more
+ * fine-grained state handling.
+ *
+ * @note Update HM_CHANGED_VMX_VMEXIT_MASK if something here changes. */
+# define IEM_CPUMCTX_EXTRN_VMX_VMEXIT_MASK ( CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_CR3 | CPUMCTX_EXTRN_CR4 \
+ | CPUMCTX_EXTRN_DR7 | CPUMCTX_EXTRN_DR6 \
+ | CPUMCTX_EXTRN_EFER \
+ | CPUMCTX_EXTRN_SYSENTER_MSRS \
+ | CPUMCTX_EXTRN_OTHER_MSRS /* for PAT MSR */ \
+ | CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_RFLAGS \
+ | CPUMCTX_EXTRN_SREG_MASK \
+ | CPUMCTX_EXTRN_TR \
+ | CPUMCTX_EXTRN_LDTR | CPUMCTX_EXTRN_GDTR | CPUMCTX_EXTRN_IDTR \
+ | CPUMCTX_EXTRN_HWVIRT )
+#endif
+
+#ifdef VBOX_WITH_NESTED_HWVIRT_SVM
+/** The CPUMCTX_EXTRN_XXX mask needed when calling IEMExecSvmVmexit().
+ * IEM will ASSUME the caller has ensured these are already present. */
+# define IEM_CPUMCTX_EXTRN_SVM_VMEXIT_MASK ( CPUMCTX_EXTRN_RSP \
+ | CPUMCTX_EXTRN_RAX \
+ | CPUMCTX_EXTRN_RIP \
+ | CPUMCTX_EXTRN_RFLAGS \
+ | CPUMCTX_EXTRN_CS \
+ | CPUMCTX_EXTRN_SS \
+ | CPUMCTX_EXTRN_DS \
+ | CPUMCTX_EXTRN_ES \
+ | CPUMCTX_EXTRN_GDTR \
+ | CPUMCTX_EXTRN_IDTR \
+ | CPUMCTX_EXTRN_CR_MASK \
+ | CPUMCTX_EXTRN_EFER \
+ | CPUMCTX_EXTRN_DR6 \
+ | CPUMCTX_EXTRN_DR7 \
+ | CPUMCTX_EXTRN_OTHER_MSRS \
+ | CPUMCTX_EXTRN_HWVIRT \
+ | CPUMCTX_EXTRN_APIC_TPR \
+ | CPUMCTX_EXTRN_HM_SVM_HWVIRT_VIRQ)
+
+/** The CPUMCTX_EXTRN_XXX mask needed when calling IEMExecDecodedVmrun().
+ * IEM will ASSUME the caller has ensured these are already present. */
+# define IEM_CPUMCTX_EXTRN_SVM_VMRUN_MASK IEM_CPUMCTX_EXTRN_SVM_VMEXIT_MASK
+#endif
+
+VMMDECL(VBOXSTRICTRC) IEMExecOne(PVMCPUCC pVCpu);
+VMMDECL(VBOXSTRICTRC) IEMExecOneEx(PVMCPUCC pVCpu, uint32_t *pcbWritten);
+VMMDECL(VBOXSTRICTRC) IEMExecOneWithPrefetchedByPC(PVMCPUCC pVCpu, uint64_t OpcodeBytesPC,
+ const void *pvOpcodeBytes, size_t cbOpcodeBytes);
+VMMDECL(VBOXSTRICTRC) IEMExecOneBypassEx(PVMCPUCC pVCpu, uint32_t *pcbWritten);
+VMMDECL(VBOXSTRICTRC) IEMExecOneBypassWithPrefetchedByPC(PVMCPUCC pVCpu, uint64_t OpcodeBytesPC,
+ const void *pvOpcodeBytes, size_t cbOpcodeBytes);
+VMMDECL(VBOXSTRICTRC) IEMExecOneIgnoreLock(PVMCPUCC pVCpu);
+VMMDECL(VBOXSTRICTRC) IEMExecLots(PVMCPUCC pVCpu, uint32_t cMaxInstructions, uint32_t cPollRate, uint32_t *pcInstructions);
+/** Statistics returned by IEMExecForExits. */
+typedef struct IEMEXECFOREXITSTATS
+{
+ uint32_t cInstructions;
+ uint32_t cExits;
+ uint32_t cMaxExitDistance;
+ uint32_t cReserved;
+} IEMEXECFOREXITSTATS;
+/** Pointer to statistics returned by IEMExecForExits. */
+typedef IEMEXECFOREXITSTATS *PIEMEXECFOREXITSTATS;
+VMMDECL(VBOXSTRICTRC) IEMExecForExits(PVMCPUCC pVCpu, uint32_t fWillExit, uint32_t cMinInstructions, uint32_t cMaxInstructions,
+ uint32_t cMaxInstructionsWithoutExits, PIEMEXECFOREXITSTATS pStats);
+VMMDECL(VBOXSTRICTRC) IEMInjectTrpmEvent(PVMCPUCC pVCpu);
+VMM_INT_DECL(VBOXSTRICTRC) IEMInjectTrap(PVMCPUCC pVCpu, uint8_t u8TrapNo, TRPMEVENT enmType, uint16_t uErrCode, RTGCPTR uCr2,
+ uint8_t cbInstr);
+
+VMM_INT_DECL(int) IEMBreakpointSet(PVM pVM, RTGCPTR GCPtrBp);
+VMM_INT_DECL(int) IEMBreakpointClear(PVM pVM, RTGCPTR GCPtrBp);
+
+VMM_INT_DECL(void) IEMTlbInvalidateAll(PVMCPUCC pVCpu);
+VMM_INT_DECL(void) IEMTlbInvalidatePage(PVMCPUCC pVCpu, RTGCPTR GCPtr);
+VMM_INT_DECL(void) IEMTlbInvalidateAllPhysical(PVMCPUCC pVCpu);
+VMM_INT_DECL(void) IEMTlbInvalidateAllPhysicalAllCpus(PVMCC pVM, VMCPUID idCpuCaller);
+VMM_INT_DECL(bool) IEMGetCurrentXcpt(PVMCPUCC pVCpu, uint8_t *puVector, uint32_t *pfFlags, uint32_t *puErr,
+ uint64_t *puCr2);
+VMM_INT_DECL(IEMXCPTRAISE) IEMEvaluateRecursiveXcpt(PVMCPUCC pVCpu, uint32_t fPrevFlags, uint8_t uPrevVector, uint32_t fCurFlags,
+ uint8_t uCurVector, PIEMXCPTRAISEINFO pXcptRaiseInfo);
+
+/** @name Given Instruction Interpreters
+ * @{ */
+VMM_INT_DECL(VBOXSTRICTRC) IEMExecStringIoWrite(PVMCPUCC pVCpu, uint8_t cbValue, IEMMODE enmAddrMode,
+ bool fRepPrefix, uint8_t cbInstr, uint8_t iEffSeg, bool fIoChecked);
+VMM_INT_DECL(VBOXSTRICTRC) IEMExecStringIoRead(PVMCPUCC pVCpu, uint8_t cbValue, IEMMODE enmAddrMode,
+ bool fRepPrefix, uint8_t cbInstr, bool fIoChecked);
+VMM_INT_DECL(VBOXSTRICTRC) IEMExecDecodedOut(PVMCPUCC pVCpu, uint8_t cbInstr, uint16_t u16Port, bool fImm, uint8_t cbReg);
+VMM_INT_DECL(VBOXSTRICTRC) IEMExecDecodedIn(PVMCPUCC pVCpu, uint8_t cbInstr, uint16_t u16Port, bool fImm, uint8_t cbReg);
+VMM_INT_DECL(VBOXSTRICTRC) IEMExecDecodedMovCRxWrite(PVMCPUCC pVCpu, uint8_t cbInstr, uint8_t iCrReg, uint8_t iGReg);
+VMM_INT_DECL(VBOXSTRICTRC) IEMExecDecodedMovCRxRead(PVMCPUCC pVCpu, uint8_t cbInstr, uint8_t iGReg, uint8_t iCrReg);
+VMM_INT_DECL(VBOXSTRICTRC) IEMExecDecodedMovDRxWrite(PVMCPUCC pVCpu, uint8_t cbInstr, uint8_t iDrReg, uint8_t iGReg);
+VMM_INT_DECL(VBOXSTRICTRC) IEMExecDecodedMovDRxRead(PVMCPUCC pVCpu, uint8_t cbInstr, uint8_t iGReg, uint8_t iDrReg);
+VMM_INT_DECL(VBOXSTRICTRC) IEMExecDecodedClts(PVMCPUCC pVCpu, uint8_t cbInstr);
+VMM_INT_DECL(VBOXSTRICTRC) IEMExecDecodedLmsw(PVMCPUCC pVCpu, uint8_t cbInstr, uint16_t uValue, RTGCPTR GCPtrEffDst);
+VMM_INT_DECL(VBOXSTRICTRC) IEMExecDecodedXsetbv(PVMCPUCC pVCpu, uint8_t cbInstr);
+VMM_INT_DECL(VBOXSTRICTRC) IEMExecDecodedWbinvd(PVMCPUCC pVCpu, uint8_t cbInstr);
+VMM_INT_DECL(VBOXSTRICTRC) IEMExecDecodedInvd(PVMCPUCC pVCpu, uint8_t cbInstr);
+VMM_INT_DECL(VBOXSTRICTRC) IEMExecDecodedInvlpg(PVMCPUCC pVCpu, uint8_t cbInstr, RTGCPTR GCPtrPage);
+VMM_INT_DECL(VBOXSTRICTRC) IEMExecDecodedInvpcid(PVMCPUCC pVCpu, uint8_t cbInstr, uint8_t iEffSeg, RTGCPTR GCPtrDesc,
+ uint64_t uType);
+VMM_INT_DECL(VBOXSTRICTRC) IEMExecDecodedCpuid(PVMCPUCC pVCpu, uint8_t cbInstr);
+VMM_INT_DECL(VBOXSTRICTRC) IEMExecDecodedRdpmc(PVMCPUCC pVCpu, uint8_t cbInstr);
+VMM_INT_DECL(VBOXSTRICTRC) IEMExecDecodedRdtsc(PVMCPUCC pVCpu, uint8_t cbInstr);
+VMM_INT_DECL(VBOXSTRICTRC) IEMExecDecodedRdtscp(PVMCPUCC pVCpu, uint8_t cbInstr);
+VMM_INT_DECL(VBOXSTRICTRC) IEMExecDecodedRdmsr(PVMCPUCC pVCpu, uint8_t cbInstr);
+VMM_INT_DECL(VBOXSTRICTRC) IEMExecDecodedWrmsr(PVMCPUCC pVCpu, uint8_t cbInstr);
+VMM_INT_DECL(VBOXSTRICTRC) IEMExecDecodedMonitor(PVMCPUCC pVCpu, uint8_t cbInstr);
+VMM_INT_DECL(VBOXSTRICTRC) IEMExecDecodedMwait(PVMCPUCC pVCpu, uint8_t cbInstr);
+VMM_INT_DECL(VBOXSTRICTRC) IEMExecDecodedHlt(PVMCPUCC pVCpu, uint8_t cbInstr);
+
+#ifdef VBOX_WITH_NESTED_HWVIRT_SVM
+VMM_INT_DECL(VBOXSTRICTRC) IEMExecDecodedClgi(PVMCPUCC pVCpu, uint8_t cbInstr);
+VMM_INT_DECL(VBOXSTRICTRC) IEMExecDecodedStgi(PVMCPUCC pVCpu, uint8_t cbInstr);
+VMM_INT_DECL(VBOXSTRICTRC) IEMExecDecodedVmload(PVMCPUCC pVCpu, uint8_t cbInstr);
+VMM_INT_DECL(VBOXSTRICTRC) IEMExecDecodedVmsave(PVMCPUCC pVCpu, uint8_t cbInstr);
+VMM_INT_DECL(VBOXSTRICTRC) IEMExecDecodedInvlpga(PVMCPUCC pVCpu, uint8_t cbInstr);
+VMM_INT_DECL(VBOXSTRICTRC) IEMExecDecodedVmrun(PVMCPUCC pVCpu, uint8_t cbInstr);
+VMM_INT_DECL(VBOXSTRICTRC) IEMExecSvmVmexit(PVMCPUCC pVCpu, uint64_t uExitCode, uint64_t uExitInfo1, uint64_t uExitInfo2);
+#endif
+
+#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
+VMM_INT_DECL(void) IEMReadVmxVmcsField(PCVMXVVMCS pVmcs, uint64_t u64VmcsField, uint64_t *pu64Dst);
+VMM_INT_DECL(void) IEMWriteVmxVmcsField(PVMXVVMCS pVmcs, uint64_t u64VmcsField, uint64_t u64Val);
+VMM_INT_DECL(VBOXSTRICTRC) IEMExecVmxVirtApicAccessMsr(PVMCPUCC pVCpu, uint32_t idMsr, uint64_t *pu64Val, bool fWrite);
+VMM_INT_DECL(VBOXSTRICTRC) IEMExecVmxVmexitApicWrite(PVMCPUCC pVCpu);
+VMM_INT_DECL(VBOXSTRICTRC) IEMExecVmxVmexitPreemptTimer(PVMCPUCC pVCpu);
+VMM_INT_DECL(VBOXSTRICTRC) IEMExecVmxVmexitExtInt(PVMCPUCC pVCpu, uint8_t uVector, bool fIntPending);
+VMM_INT_DECL(VBOXSTRICTRC) IEMExecVmxVmexitXcpt(PVMCPUCC pVCpu, PCVMXVEXITINFO pExitInfo, PCVMXVEXITEVENTINFO pExitEventInfo);
+VMM_INT_DECL(VBOXSTRICTRC) IEMExecVmxVmexitXcptNmi(PVMCPUCC pVCpu);
+VMM_INT_DECL(VBOXSTRICTRC) IEMExecVmxVmexitTripleFault(PVMCPUCC pVCpu);
+VMM_INT_DECL(VBOXSTRICTRC) IEMExecVmxVmexitStartupIpi(PVMCPUCC pVCpu, uint8_t uVector);
+VMM_INT_DECL(VBOXSTRICTRC) IEMExecVmxVmexitInstrWithInfo(PVMCPUCC pVCpu, PCVMXVEXITINFO pExitInfo);
+VMM_INT_DECL(VBOXSTRICTRC) IEMExecVmxVmexitInstr(PVMCPUCC pVCpu, uint32_t uExitReason, uint8_t cbInstr);
+VMM_INT_DECL(VBOXSTRICTRC) IEMExecVmxVmexitTrapLike(PVMCPUCC pVCpu, PCVMXVEXITINFO pExitInfo);
+VMM_INT_DECL(VBOXSTRICTRC) IEMExecVmxVmexitTaskSwitch(PVMCPUCC pVCpu, PCVMXVEXITINFO pExitInfo, PCVMXVEXITEVENTINFO pExitEventInfo);
+VMM_INT_DECL(VBOXSTRICTRC) IEMExecVmxVmexitApicAccess(PVMCPUCC pVCpu, PCVMXVEXITINFO pExitInfo, PCVMXVEXITEVENTINFO pExitEventInfo);
+VMM_INT_DECL(VBOXSTRICTRC) IEMExecVmxVmexit(PVMCPUCC pVCpu, uint32_t uExitReason, uint64_t uExitQual);
+VMM_INT_DECL(VBOXSTRICTRC) IEMExecDecodedVmread(PVMCPUCC pVCpu, PCVMXVEXITINFO pExitInfo);
+VMM_INT_DECL(VBOXSTRICTRC) IEMExecDecodedVmwrite(PVMCPUCC pVCpu, PCVMXVEXITINFO pExitInfo);
+VMM_INT_DECL(VBOXSTRICTRC) IEMExecDecodedVmptrld(PVMCPUCC pVCpu, PCVMXVEXITINFO pExitInfo);
+VMM_INT_DECL(VBOXSTRICTRC) IEMExecDecodedVmptrst(PVMCPUCC pVCpu, PCVMXVEXITINFO pExitInfo);
+VMM_INT_DECL(VBOXSTRICTRC) IEMExecDecodedVmclear(PVMCPUCC pVCpu, PCVMXVEXITINFO pExitInfo);
+VMM_INT_DECL(VBOXSTRICTRC) IEMExecDecodedVmlaunchVmresume(PVMCPUCC pVCpu, uint8_t cbInstr, VMXINSTRID uInstrId);
+VMM_INT_DECL(VBOXSTRICTRC) IEMExecDecodedVmxon(PVMCPUCC pVCpu, PCVMXVEXITINFO pExitInfo);
+VMM_INT_DECL(VBOXSTRICTRC) IEMExecDecodedVmxoff(PVMCPUCC pVCpu, uint8_t cbInstr);
+VMM_INT_DECL(VBOXSTRICTRC) IEMExecDecodedInvvpid(PVMCPUCC pVCpu, PCVMXVEXITINFO pExitInfo);
+# ifdef VBOX_WITH_NESTED_HWVIRT_VMX_EPT
+VMM_INT_DECL(VBOXSTRICTRC) IEMExecDecodedInvept(PVMCPUCC pVCpu, PCVMXVEXITINFO pExitInfo);
+VMM_INT_DECL(VBOXSTRICTRC) IEMExecVmxVmexitEptViolation(PVMCPUCC pVCpu, PCVMXVEXITINFO pExitInfo, PCVMXVEXITEVENTINFO pExitEventInfo);
+VMM_INT_DECL(VBOXSTRICTRC) IEMExecVmxVmexitEptMisconfig(PVMCPUCC pVCpu, RTGCPHYS GCPhysAddr, PCVMXVEXITEVENTINFO pExitEventInfo);
+# endif
+#endif
+/** @} */
+
+/** @defgroup grp_iem_r3 The IEM Host Context Ring-3 API.
+ * @{
+ */
+VMMR0_INT_DECL(int) IEMR0InitVM(PGVM pGVM);
+/** @} */
+
+
+/** @defgroup grp_iem_r3 The IEM Host Context Ring-3 API.
+ * @{
+ */
+VMMR3DECL(int) IEMR3Init(PVM pVM);
+VMMR3DECL(int) IEMR3Term(PVM pVM);
+VMMR3DECL(void) IEMR3Relocate(PVM pVM);
+VMMR3_INT_DECL(VBOXSTRICTRC) IEMR3ProcessForceFlag(PVM pVM, PVMCPUCC pVCpu, VBOXSTRICTRC rcStrict);
+/** @} */
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !VBOX_INCLUDED_vmm_iem_h */
+
diff --git a/include/VBox/vmm/iom.h b/include/VBox/vmm/iom.h
new file mode 100644
index 00000000..a2ff5891
--- /dev/null
+++ b/include/VBox/vmm/iom.h
@@ -0,0 +1,550 @@
+/** @file
+ * IOM - Input / Output Monitor.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vmm_iom_h
+#define VBOX_INCLUDED_vmm_iom_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/types.h>
+#include <VBox/dis.h>
+#include <VBox/vmm/dbgf.h>
+
+RT_C_DECLS_BEGIN
+
+
+/** @defgroup grp_iom The Input / Ouput Monitor API
+ * @ingroup grp_vmm
+ * @{
+ */
+
+/** @def IOM_NO_PDMINS_CHECKS
+ * Until all devices have been fully adjusted to PDM style, the pPdmIns
+ * parameter is not checked by IOM.
+ * @todo Check this again, now.
+ */
+#define IOM_NO_PDMINS_CHECKS
+
+/**
+ * Macro for checking if an I/O or MMIO emulation call succeeded.
+ *
+ * This macro shall only be used with the IOM APIs where it's mentioned
+ * in the return value description. And there it must be used to correctly
+ * determine if the call succeeded and things like the RIP needs updating.
+ *
+ *
+ * @returns Success indicator (true/false).
+ *
+ * @param rc The status code. This may be evaluated
+ * more than once!
+ *
+ * @remarks To avoid making assumptions about the layout of the
+ * VINF_EM_FIRST...VINF_EM_LAST range we're checking explicitly for
+ * each exact exception. However, for efficiency we ASSUME that the
+ * VINF_EM_LAST is smaller than most of the relevant status codes. We
+ * also ASSUME that the VINF_EM_RESCHEDULE_REM status code is the
+ * most frequent status code we'll enounter in this range.
+ *
+ * @todo Will have to add VINF_EM_DBG_HYPER_BREAKPOINT if the
+ * I/O port and MMIO breakpoints should trigger before
+ * the I/O is done. Currently, we don't implement these
+ * kind of breakpoints.
+ */
+#ifdef IN_RING3
+# define IOM_SUCCESS(rc) ( (rc) == VINF_SUCCESS \
+ || ( (rc) <= VINF_EM_LAST \
+ && (rc) != VINF_EM_RESCHEDULE_REM \
+ && (rc) >= VINF_EM_FIRST \
+ && (rc) != VINF_EM_RESCHEDULE_RAW \
+ && (rc) != VINF_EM_RESCHEDULE_HM \
+ ) \
+ )
+#else
+# define IOM_SUCCESS(rc) ( (rc) == VINF_SUCCESS \
+ || ( (rc) <= VINF_EM_LAST \
+ && (rc) != VINF_EM_RESCHEDULE_REM \
+ && (rc) >= VINF_EM_FIRST \
+ && (rc) != VINF_EM_RESCHEDULE_RAW \
+ && (rc) != VINF_EM_RESCHEDULE_HM \
+ ) \
+ || (rc) == VINF_IOM_R3_IOPORT_COMMIT_WRITE \
+ || (rc) == VINF_IOM_R3_MMIO_COMMIT_WRITE \
+ )
+#endif
+
+/** @name IOMMMIO_FLAGS_XXX
+ * @{ */
+/** Pass all reads thru unmodified. */
+#define IOMMMIO_FLAGS_READ_PASSTHRU UINT32_C(0x00000000)
+/** All read accesses are DWORD sized (32-bit). */
+#define IOMMMIO_FLAGS_READ_DWORD UINT32_C(0x00000001)
+/** All read accesses are DWORD (32-bit) or QWORD (64-bit) sized.
+ * Only accesses that are both QWORD sized and aligned are performed as QWORD.
+ * All other access will be done DWORD fashion (because it is way simpler). */
+#define IOMMMIO_FLAGS_READ_DWORD_QWORD UINT32_C(0x00000002)
+/** The read access mode mask. */
+#define IOMMMIO_FLAGS_READ_MODE UINT32_C(0x00000003)
+
+/** Pass all writes thru unmodified. */
+#define IOMMMIO_FLAGS_WRITE_PASSTHRU UINT32_C(0x00000000)
+/** All write accesses are DWORD (32-bit) sized and unspecified bytes are
+ * written as zero. */
+#define IOMMMIO_FLAGS_WRITE_DWORD_ZEROED UINT32_C(0x00000010)
+/** All write accesses are either DWORD (32-bit) or QWORD (64-bit) sized,
+ * missing bytes will be written as zero. Only accesses that are both QWORD
+ * sized and aligned are performed as QWORD, all other accesses will be done
+ * DWORD fashion (because it's way simpler). */
+#define IOMMMIO_FLAGS_WRITE_DWORD_QWORD_ZEROED UINT32_C(0x00000020)
+/** All write accesses are DWORD (32-bit) sized and unspecified bytes are
+ * read from the device first as DWORDs.
+ * @remarks This isn't how it happens on real hardware, but it allows
+ * simplifications of devices where reads doesn't change the device
+ * state in any way. */
+#define IOMMMIO_FLAGS_WRITE_DWORD_READ_MISSING UINT32_C(0x00000030)
+/** All write accesses are DWORD (32-bit) or QWORD (64-bit) sized and
+ * unspecified bytes are read from the device first as DWORDs. Only accesses
+ * that are both QWORD sized and aligned are performed as QWORD, all other
+ * accesses will be done DWORD fashion (because it's way simpler).
+ * @remarks This isn't how it happens on real hardware, but it allows
+ * simplifications of devices where reads doesn't change the device
+ * state in any way. */
+#define IOMMMIO_FLAGS_WRITE_DWORD_QWORD_READ_MISSING UINT32_C(0x00000040)
+/** All write accesses are DWORD (32-bit) sized and aligned, attempts at other
+ * accesses are ignored.
+ * @remarks E1000, APIC */
+#define IOMMMIO_FLAGS_WRITE_ONLY_DWORD UINT32_C(0x00000050)
+/** All write accesses are DWORD (32-bit) or QWORD (64-bit) sized and aligned,
+ * attempts at other accesses are ignored.
+ * @remarks Seemingly required by AHCI (although I doubt it's _really_
+ * required as EM/REM doesn't do the right thing in ring-3 anyway,
+ * esp. not in raw-mode). */
+#define IOMMMIO_FLAGS_WRITE_ONLY_DWORD_QWORD UINT32_C(0x00000060)
+/** The read access mode mask. */
+#define IOMMMIO_FLAGS_WRITE_MODE UINT32_C(0x00000070)
+
+/** Whether to do a DBGSTOP on complicated reads.
+ * What this includes depends on the read mode, but generally all misaligned
+ * reads as well as word and byte reads and maybe qword reads. */
+#define IOMMMIO_FLAGS_DBGSTOP_ON_COMPLICATED_READ UINT32_C(0x00000100)
+/** Whether to do a DBGSTOP on complicated writes.
+ * This depends on the write mode, but generally all writes where we have to
+ * supply bytes (zero them or read them). */
+#define IOMMMIO_FLAGS_DBGSTOP_ON_COMPLICATED_WRITE UINT32_C(0x00000200)
+
+/** Pass the absolute physical address (GC) to the callback rather than the
+ * relative one.
+ * @note New-style only, is implicit in old-style interface. */
+#define IOMMMIO_FLAGS_ABS UINT32_C(0x00001000)
+
+/** Mask of valid flags. */
+#define IOMMMIO_FLAGS_VALID_MASK UINT32_C(0x00001373)
+/** @} */
+
+/**
+ * Checks whether the write mode allows aligned QWORD accesses to be passed
+ * thru to the device handler.
+ * @param a_fFlags The MMIO handler flags.
+ */
+#define IOMMMIO_DOES_WRITE_MODE_ALLOW_QWORD(a_fFlags) \
+ ( ((a_fFlags) & IOMMMIO_FLAGS_WRITE_MODE) == IOMMMIO_FLAGS_WRITE_DWORD_QWORD_ZEROED \
+ || ((a_fFlags) & IOMMMIO_FLAGS_WRITE_MODE) == IOMMMIO_FLAGS_WRITE_DWORD_QWORD_READ_MISSING \
+ || ((a_fFlags) & IOMMMIO_FLAGS_WRITE_MODE) == IOMMMIO_FLAGS_WRITE_ONLY_DWORD_QWORD )
+
+
+/**
+ * Port I/O Handler for IN operations.
+ *
+ * @returns VINF_SUCCESS or VINF_EM_*.
+ * @returns VERR_IOM_IOPORT_UNUSED if the port is really unused and a ~0 value should be returned.
+ *
+ * @param pDevIns The device instance.
+ * @param pvUser User argument.
+ * @param uPort Port number used for the IN operation.
+ * @param pu32 Where to store the result. This is always a 32-bit
+ * variable regardless of what @a cb might say.
+ * @param cb Number of bytes read.
+ * @remarks Caller enters the device critical section.
+ */
+typedef DECLCALLBACKTYPE(int, FNIOMIOPORTIN,(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT uPort, uint32_t *pu32, unsigned cb));
+/** Pointer to a FNIOMIOPORTIN(). */
+typedef FNIOMIOPORTIN *PFNIOMIOPORTIN;
+
+/**
+ * Port I/O Handler for string IN operations.
+ *
+ * @returns VINF_SUCCESS or VINF_EM_*.
+ * @returns VERR_IOM_IOPORT_UNUSED if the port is really unused and a ~0 value should be returned.
+ *
+ * @param pDevIns The device instance.
+ * @param pvUser User argument.
+ * @param uPort Port number used for the IN operation.
+ * @param pbDst Pointer to the destination buffer.
+ * @param pcTransfers Pointer to the number of transfer units to read, on
+ * return remaining transfer units.
+ * @param cb Size of the transfer unit (1, 2 or 4 bytes).
+ * @remarks Caller enters the device critical section.
+ */
+typedef DECLCALLBACKTYPE(int, FNIOMIOPORTINSTRING,(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT uPort, uint8_t *pbDst,
+ uint32_t *pcTransfers, unsigned cb));
+/** Pointer to a FNIOMIOPORTINSTRING(). */
+typedef FNIOMIOPORTINSTRING *PFNIOMIOPORTINSTRING;
+
+/**
+ * Port I/O Handler for OUT operations.
+ *
+ * @returns VINF_SUCCESS or VINF_EM_*.
+ *
+ * @param pDevIns The device instance.
+ * @param pvUser User argument.
+ * @param uPort Port number used for the OUT operation.
+ * @param u32 The value to output.
+ * @param cb The value size in bytes.
+ * @remarks Caller enters the device critical section.
+ */
+typedef DECLCALLBACKTYPE(int, FNIOMIOPORTOUT,(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT uPort, uint32_t u32, unsigned cb));
+/** Pointer to a FNIOMIOPORTOUT(). */
+typedef FNIOMIOPORTOUT *PFNIOMIOPORTOUT;
+
+/**
+ * Port I/O Handler for string OUT operations.
+ *
+ * @returns VINF_SUCCESS or VINF_EM_*.
+ *
+ * @param pDevIns The device instance.
+ * @param pvUser User argument.
+ * @param uPort Port number used for the OUT operation.
+ * @param pbSrc Pointer to the source buffer.
+ * @param pcTransfers Pointer to the number of transfer units to write, on
+ * return remaining transfer units.
+ * @param cb Size of the transfer unit (1, 2 or 4 bytes).
+ * @remarks Caller enters the device critical section.
+ */
+typedef DECLCALLBACKTYPE(int, FNIOMIOPORTOUTSTRING,(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT uPort, const uint8_t *pbSrc,
+ uint32_t *pcTransfers, unsigned cb));
+/** Pointer to a FNIOMIOPORTOUTSTRING(). */
+typedef FNIOMIOPORTOUTSTRING *PFNIOMIOPORTOUTSTRING;
+
+
+/**
+ * Port I/O Handler for IN operations.
+ *
+ * @returns VINF_SUCCESS or VINF_EM_*.
+ * @returns VERR_IOM_IOPORT_UNUSED if the port is really unused and a ~0 value should be returned.
+ *
+ * @param pDevIns The device instance.
+ * @param pvUser User argument.
+ * @param offPort The port number if IOM_IOPORT_F_ABS is used, otherwise
+ * relative to the mapping base.
+ * @param pu32 Where to store the result. This is always a 32-bit
+ * variable regardless of what @a cb might say.
+ * @param cb Number of bytes read.
+ * @remarks Caller enters the device critical section.
+ */
+typedef DECLCALLBACKTYPE(VBOXSTRICTRC, FNIOMIOPORTNEWIN,(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort,
+ uint32_t *pu32, unsigned cb));
+/** Pointer to a FNIOMIOPORTNEWIN(). */
+typedef FNIOMIOPORTNEWIN *PFNIOMIOPORTNEWIN;
+
+/**
+ * Port I/O Handler for string IN operations.
+ *
+ * @returns VINF_SUCCESS or VINF_EM_*.
+ * @returns VERR_IOM_IOPORT_UNUSED if the port is really unused and a ~0 value should be returned.
+ *
+ * @param pDevIns The device instance.
+ * @param pvUser User argument.
+ * @param offPort The port number if IOM_IOPORT_F_ABS is used, otherwise
+ * relative to the mapping base.
+ * @param pbDst Pointer to the destination buffer.
+ * @param pcTransfers Pointer to the number of transfer units to read, on
+ * return remaining transfer units.
+ * @param cb Size of the transfer unit (1, 2 or 4 bytes).
+ * @remarks Caller enters the device critical section.
+ */
+typedef DECLCALLBACKTYPE(VBOXSTRICTRC, FNIOMIOPORTNEWINSTRING,(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint8_t *pbDst,
+ uint32_t *pcTransfers, unsigned cb));
+/** Pointer to a FNIOMIOPORTNEWINSTRING(). */
+typedef FNIOMIOPORTNEWINSTRING *PFNIOMIOPORTNEWINSTRING;
+
+/**
+ * Port I/O Handler for OUT operations.
+ *
+ * @returns VINF_SUCCESS or VINF_EM_*.
+ *
+ * @param pDevIns The device instance.
+ * @param pvUser User argument.
+ * @param offPort The port number if IOM_IOPORT_F_ABS is used, otherwise
+ * relative to the mapping base.
+ * @param u32 The value to output.
+ * @param cb The value size in bytes.
+ * @remarks Caller enters the device critical section.
+ */
+typedef DECLCALLBACKTYPE(VBOXSTRICTRC, FNIOMIOPORTNEWOUT,(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort,
+ uint32_t u32, unsigned cb));
+/** Pointer to a FNIOMIOPORTNEWOUT(). */
+typedef FNIOMIOPORTNEWOUT *PFNIOMIOPORTNEWOUT;
+
+/**
+ * Port I/O Handler for string OUT operations.
+ *
+ * @returns VINF_SUCCESS or VINF_EM_*.
+ *
+ * @param pDevIns The device instance.
+ * @param pvUser User argument.
+ * @param offPort The port number if IOM_IOPORT_F_ABS is used, otherwise
+ * relative to the mapping base.
+ * @param pbSrc Pointer to the source buffer.
+ * @param pcTransfers Pointer to the number of transfer units to write, on
+ * return remaining transfer units.
+ * @param cb Size of the transfer unit (1, 2 or 4 bytes).
+ * @remarks Caller enters the device critical section.
+ */
+typedef DECLCALLBACKTYPE(VBOXSTRICTRC, FNIOMIOPORTNEWOUTSTRING,(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort,
+ const uint8_t *pbSrc, uint32_t *pcTransfers, unsigned cb));
+/** Pointer to a FNIOMIOPORTNEWOUTSTRING(). */
+typedef FNIOMIOPORTNEWOUTSTRING *PFNIOMIOPORTNEWOUTSTRING;
+
+/**
+ * I/O port description.
+ *
+ * If both pszIn and pszOut are NULL, the entry is considered a terminator.
+ */
+typedef struct IOMIOPORTDESC
+{
+ /** Brief description / name of the IN port. */
+ const char *pszIn;
+ /** Brief description / name of the OUT port. */
+ const char *pszOut;
+ /** Detailed description of the IN port, optional. */
+ const char *pszInDetail;
+ /** Detialed description of the OUT port, optional. */
+ const char *pszOutDetail;
+} IOMIOPORTDESC;
+/** Pointer to an I/O port description. */
+typedef IOMIOPORTDESC const *PCIOMIOPORTDESC;
+
+
+/**
+ * Memory mapped I/O Handler for read operations.
+ *
+ * @returns VBox status code.
+ *
+ * @param pDevIns The device instance.
+ * @param pvUser User argument.
+ * @param GCPhysAddr Physical address (in GC) where the read starts.
+ * @param pv Where to store the result.
+ * @param cb Number of bytes read.
+ * @remarks Caller enters the device critical section.
+ */
+typedef DECLCALLBACKTYPE(int, FNIOMMMIOREAD,(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb));
+/** Pointer to a FNIOMMMIOREAD(). */
+typedef FNIOMMMIOREAD *PFNIOMMMIOREAD;
+
+/**
+ * Memory mapped I/O Handler for write operations.
+ *
+ * @returns VBox status code.
+ *
+ * @param pDevIns The device instance.
+ * @param pvUser User argument.
+ * @param GCPhysAddr Physical address (in GC) where the read starts.
+ * @param pv Where to fetch the result.
+ * @param cb Number of bytes to write.
+ * @remarks Caller enters the device critical section.
+ */
+typedef DECLCALLBACKTYPE(int, FNIOMMMIOWRITE,(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void const *pv, unsigned cb));
+/** Pointer to a FNIOMMMIOWRITE(). */
+typedef FNIOMMMIOWRITE *PFNIOMMMIOWRITE;
+
+/**
+ * Memory mapped I/O Handler for memset operations, actually for REP STOS* instructions handling.
+ *
+ * @returns VBox status code.
+ *
+ * @param pDevIns The device instance.
+ * @param pvUser User argument.
+ * @param GCPhysAddr Physical address (in GC) where the write starts.
+ * @param u32Item Byte/Word/Dword data to fill.
+ * @param cbItem Size of data in u32Item parameter, restricted to 1/2/4 bytes.
+ * @param cItems Number of iterations.
+ * @remarks Caller enters the device critical section.
+ */
+typedef DECLCALLBACKTYPE(int, FNIOMMMIOFILL,(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr,
+ uint32_t u32Item, unsigned cbItem, unsigned cItems));
+/** Pointer to a FNIOMMMIOFILL(). */
+typedef FNIOMMMIOFILL *PFNIOMMMIOFILL;
+
+
+/**
+ * Memory mapped I/O Handler for read operations.
+ *
+ * @returns Strict VBox status code.
+ *
+ * @param pDevIns The device instance.
+ * @param pvUser User argument.
+ * @param off Offset into the mapping of the read,
+ * or the physical address if IOMMMIO_FLAGS_ABS is active.
+ * @param pv Where to store the result.
+ * @param cb Number of bytes read.
+ * @remarks Caller enters the device critical section.
+ */
+typedef DECLCALLBACKTYPE(VBOXSTRICTRC, FNIOMMMIONEWREAD,(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS off, void *pv, uint32_t cb));
+/** Pointer to a FNIOMMMIONEWREAD(). */
+typedef FNIOMMMIONEWREAD *PFNIOMMMIONEWREAD;
+
+/**
+ * Memory mapped I/O Handler for write operations.
+ *
+ * @returns Strict VBox status code.
+ *
+ * @param pDevIns The device instance.
+ * @param pvUser User argument.
+ * @param off Offset into the mapping of the write,
+ * or the physical address if IOMMMIO_FLAGS_ABS is active.
+ * @param pv Where to fetch the result.
+ * @param cb Number of bytes to write.
+ * @remarks Caller enters the device critical section.
+ */
+typedef DECLCALLBACKTYPE(VBOXSTRICTRC, FNIOMMMIONEWWRITE,(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS off,
+ void const *pv, uint32_t cb));
+/** Pointer to a FNIOMMMIONEWWRITE(). */
+typedef FNIOMMMIONEWWRITE *PFNIOMMMIONEWWRITE;
+
+/**
+ * Memory mapped I/O Handler for memset operations, actually for REP STOS* instructions handling.
+ *
+ * @returns Strict VBox status code.
+ *
+ * @param pDevIns The device instance.
+ * @param pvUser User argument.
+ * @param off Offset into the mapping of the fill,
+ * or the physical address if IOMMMIO_FLAGS_ABS is active.
+ * @param u32Item Byte/Word/Dword data to fill.
+ * @param cbItem Size of data in u32Item parameter, restricted to 1/2/4 bytes.
+ * @param cItems Number of iterations.
+ * @remarks Caller enters the device critical section.
+ */
+typedef DECLCALLBACKTYPE(VBOXSTRICTRC, FNIOMMMIONEWFILL,(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS off,
+ uint32_t u32Item, uint32_t cbItem, uint32_t cItems));
+/** Pointer to a FNIOMMMIONEWFILL(). */
+typedef FNIOMMMIONEWFILL *PFNIOMMMIONEWFILL;
+
+VMMDECL(VBOXSTRICTRC) IOMIOPortRead(PVMCC pVM, PVMCPU pVCpu, RTIOPORT Port, uint32_t *pu32Value, size_t cbValue);
+VMMDECL(VBOXSTRICTRC) IOMIOPortWrite(PVMCC pVM, PVMCPU pVCpu, RTIOPORT Port, uint32_t u32Value, size_t cbValue);
+VMM_INT_DECL(VBOXSTRICTRC) IOMIOPortReadString(PVMCC pVM, PVMCPU pVCpu, RTIOPORT Port, void *pvDst,
+ uint32_t *pcTransfers, unsigned cb);
+VMM_INT_DECL(VBOXSTRICTRC) IOMIOPortWriteString(PVMCC pVM, PVMCPU pVCpu, RTIOPORT uPort, void const *pvSrc,
+ uint32_t *pcTransfers, unsigned cb);
+VMM_INT_DECL(VBOXSTRICTRC) IOMR0MmioPhysHandler(PVMCC pVM, PVMCPUCC pVCpu, uint32_t uErrorCode, RTGCPHYS GCPhysFault);
+VMMDECL(int) IOMMmioMapMmio2Page(PVMCC pVM, PPDMDEVINS pDevIns, IOMMMIOHANDLE hRegion, RTGCPHYS offRegion,
+ uint64_t hMmio2, RTGCPHYS offMmio2, uint64_t fPageFlags);
+VMMR0_INT_DECL(int) IOMR0MmioMapMmioHCPage(PVMCC pVM, PVMCPUCC pVCpu, RTGCPHYS GCPhys, RTHCPHYS HCPhys, uint64_t fPageFlags);
+VMMDECL(int) IOMMmioResetRegion(PVMCC pVM, PPDMDEVINS pDevIns, IOMMMIOHANDLE hRegion);
+
+
+/** @name IOM_IOPORT_F_XXX - Flags for IOMR3IoPortCreate() and PDMDevHlpIoPortCreateEx().
+ * @{ */
+/** Pass the absolute I/O port to the callback rather than the relative one. */
+#define IOM_IOPORT_F_ABS RT_BIT_32(0)
+/** Valid flags for IOMR3IoPortCreate(). */
+#define IOM_IOPORT_F_VALID_MASK UINT32_C(0x00000001)
+/** @} */
+
+#ifdef IN_RING3
+/** @defgroup grp_iom_r3 The IOM Host Context Ring-3 API
+ * @{
+ */
+VMMR3_INT_DECL(int) IOMR3Init(PVM pVM);
+VMMR3_INT_DECL(int) IOMR3InitCompleted(PVM pVM, VMINITCOMPLETED enmWhat);
+VMMR3_INT_DECL(void) IOMR3Reset(PVM pVM);
+VMMR3_INT_DECL(void) IOMR3Relocate(PVM pVM, RTGCINTPTR offDelta);
+VMMR3_INT_DECL(int) IOMR3Term(PVM pVM);
+
+VMMR3_INT_DECL(int) IOMR3IoPortCreate(PVM pVM, PPDMDEVINS pDevIns, RTIOPORT cPorts, uint32_t fFlags, PPDMPCIDEV pPciDev,
+ uint32_t iPciRegion, PFNIOMIOPORTNEWOUT pfnOut, PFNIOMIOPORTNEWIN pfnIn,
+ PFNIOMIOPORTNEWOUTSTRING pfnOutStr, PFNIOMIOPORTNEWINSTRING pfnInStr, RTR3PTR pvUser,
+ const char *pszDesc, PCIOMIOPORTDESC paExtDescs, PIOMIOPORTHANDLE phIoPorts);
+VMMR3_INT_DECL(int) IOMR3IoPortMap(PVM pVM, PPDMDEVINS pDevIns, IOMIOPORTHANDLE hIoPorts, RTIOPORT Port);
+VMMR3_INT_DECL(int) IOMR3IoPortUnmap(PVM pVM, PPDMDEVINS pDevIns, IOMIOPORTHANDLE hIoPorts);
+VMMR3_INT_DECL(int) IOMR3IoPortValidateHandle(PVM pVM, PPDMDEVINS pDevIns, IOMIOPORTHANDLE hIoPorts);
+VMMR3_INT_DECL(uint32_t) IOMR3IoPortGetMappingAddress(PVM pVM, PPDMDEVINS pDevIns, IOMIOPORTHANDLE hIoPorts);
+
+VMMR3_INT_DECL(int) IOMR3MmioCreate(PVM pVM, PPDMDEVINS pDevIns, RTGCPHYS cbRegion, uint32_t fFlags, PPDMPCIDEV pPciDev,
+ uint32_t iPciRegion, PFNIOMMMIONEWWRITE pfnWrite, PFNIOMMMIONEWREAD pfnRead,
+ PFNIOMMMIONEWFILL pfnFill, void *pvUser, const char *pszDesc, PIOMMMIOHANDLE phRegion);
+VMMR3_INT_DECL(int) IOMR3MmioMap(PVM pVM, PPDMDEVINS pDevIns, IOMMMIOHANDLE hRegion, RTGCPHYS GCPhys);
+VMMR3_INT_DECL(int) IOMR3MmioUnmap(PVM pVM, PPDMDEVINS pDevIns, IOMMMIOHANDLE hRegion);
+VMMR3_INT_DECL(int) IOMR3MmioReduce(PVM pVM, PPDMDEVINS pDevIns, IOMMMIOHANDLE hRegion, RTGCPHYS cbRegion);
+VMMR3_INT_DECL(int) IOMR3MmioValidateHandle(PVM pVM, PPDMDEVINS pDevIns, IOMMMIOHANDLE hRegion);
+VMMR3_INT_DECL(RTGCPHYS) IOMR3MmioGetMappingAddress(PVM pVM, PPDMDEVINS pDevIns, IOMMMIOHANDLE hRegion);
+
+VMMR3_INT_DECL(VBOXSTRICTRC) IOMR3ProcessForceFlag(PVM pVM, PVMCPU pVCpu, VBOXSTRICTRC rcStrict);
+
+VMMR3_INT_DECL(void) IOMR3NotifyBreakpointCountChange(PVM pVM, bool fPortIo, bool fMmio);
+VMMR3_INT_DECL(void) IOMR3NotifyDebugEventChange(PVM pVM, DBGFEVENT enmEvent, bool fEnabled);
+/** @} */
+#endif /* IN_RING3 */
+
+
+#if defined(IN_RING0) || defined(DOXYGEN_RUNNING)
+/** @defgroup grpm_iom_r0 The IOM Host Context Ring-0 API
+ * @{ */
+VMMR0_INT_DECL(void) IOMR0InitPerVMData(PGVM pGVM);
+VMMR0_INT_DECL(int) IOMR0InitVM(PGVM pGVM);
+VMMR0_INT_DECL(void) IOMR0CleanupVM(PGVM pGVM);
+
+VMMR0_INT_DECL(int) IOMR0IoPortSetUpContext(PGVM pGVM, PPDMDEVINS pDevIns, IOMIOPORTHANDLE hIoPorts,
+ PFNIOMIOPORTNEWOUT pfnOut, PFNIOMIOPORTNEWIN pfnIn,
+ PFNIOMIOPORTNEWOUTSTRING pfnOutStr, PFNIOMIOPORTNEWINSTRING pfnInStr, void *pvUser);
+VMMR0_INT_DECL(int) IOMR0IoPortGrowRegistrationTables(PGVM pGVM, uint64_t cMinEntries);
+VMMR0_INT_DECL(int) IOMR0IoPortGrowStatisticsTable(PGVM pGVM, uint64_t cMinEntries);
+VMMR0_INT_DECL(int) IOMR0IoPortSyncStatisticsIndices(PGVM pGVM);
+
+VMMR0_INT_DECL(int) IOMR0MmioSetUpContext(PGVM pGVM, PPDMDEVINS pDevIns, IOMMMIOHANDLE hRegion, PFNIOMMMIONEWWRITE pfnWrite,
+ PFNIOMMMIONEWREAD pfnRead, PFNIOMMMIONEWFILL pfnFill, void *pvUser);
+VMMR0_INT_DECL(int) IOMR0MmioGrowRegistrationTables(PGVM pGVM, uint64_t cMinEntries);
+VMMR0_INT_DECL(int) IOMR0MmioGrowStatisticsTable(PGVM pGVM, uint64_t cMinEntries);
+VMMR0_INT_DECL(int) IOMR0MmioSyncStatisticsIndices(PGVM pGVM);
+
+/** @} */
+#endif /* IN_RING0 || DOXYGEN_RUNNING */
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !VBOX_INCLUDED_vmm_iom_h */
+
diff --git a/include/VBox/vmm/mm.h b/include/VBox/vmm/mm.h
new file mode 100644
index 00000000..540ba6d2
--- /dev/null
+++ b/include/VBox/vmm/mm.h
@@ -0,0 +1,244 @@
+/** @file
+ * MM - The Memory Manager.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vmm_mm_h
+#define VBOX_INCLUDED_vmm_mm_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/types.h>
+#include <iprt/x86.h>
+#include <VBox/sup.h>
+#include <iprt/stdarg.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_mm The Memory Manager API
+ * @ingroup grp_vmm
+ * @{
+ */
+
+/**
+ * Memory Allocation Tags.
+ * For use with MMHyperAlloc(), MMR3HeapAlloc(), MMR3HeapAllocEx(),
+ * MMR3HeapAllocZ() and MMR3HeapAllocZEx().
+ *
+ * @remark Don't forget to update the dump command in MMHeap.cpp!
+ */
+typedef enum MMTAG
+{
+ MM_TAG_INVALID = 0,
+
+ MM_TAG_CFGM,
+ MM_TAG_CFGM_BYTES,
+ MM_TAG_CFGM_STRING,
+ MM_TAG_CFGM_USER,
+
+ MM_TAG_CSAM,
+ MM_TAG_CSAM_PATCH,
+
+ MM_TAG_CPUM_CTX,
+ MM_TAG_CPUM_CPUID,
+ MM_TAG_CPUM_MSRS,
+
+ MM_TAG_DBGF,
+ MM_TAG_DBGF_AS,
+ MM_TAG_DBGF_CORE_WRITE,
+ MM_TAG_DBGF_INFO,
+ MM_TAG_DBGF_LINE,
+ MM_TAG_DBGF_LINE_DUP,
+ MM_TAG_DBGF_MODULE,
+ MM_TAG_DBGF_OS,
+ MM_TAG_DBGF_REG,
+ MM_TAG_DBGF_STACK,
+ MM_TAG_DBGF_SYMBOL,
+ MM_TAG_DBGF_SYMBOL_DUP,
+ MM_TAG_DBGF_TYPE,
+ MM_TAG_DBGF_TRACER,
+ MM_TAG_DBGF_FLOWTRACE,
+
+ MM_TAG_EM,
+
+ MM_TAG_IEM,
+
+ MM_TAG_IOM,
+ MM_TAG_IOM_STATS,
+
+ MM_TAG_MM,
+ MM_TAG_MM_LOOKUP_GUEST,
+ MM_TAG_MM_LOOKUP_PHYS,
+ MM_TAG_MM_LOOKUP_VIRT,
+ MM_TAG_MM_PAGE,
+
+ MM_TAG_PARAV,
+
+ MM_TAG_PATM,
+ MM_TAG_PATM_PATCH,
+
+ MM_TAG_PDM,
+ MM_TAG_PDM_ASYNC_COMPLETION,
+ MM_TAG_PDM_DEVICE,
+ MM_TAG_PDM_DEVICE_DESC,
+ MM_TAG_PDM_DEVICE_USER,
+ MM_TAG_PDM_DRIVER,
+ MM_TAG_PDM_DRIVER_DESC,
+ MM_TAG_PDM_DRIVER_USER,
+ MM_TAG_PDM_USB,
+ MM_TAG_PDM_USB_DESC,
+ MM_TAG_PDM_USB_USER,
+ MM_TAG_PDM_LUN,
+#ifdef VBOX_WITH_NETSHAPER
+ MM_TAG_PDM_NET_SHAPER,
+#endif /* VBOX_WITH_NETSHAPER */
+ MM_TAG_PDM_QUEUE,
+ MM_TAG_PDM_THREAD,
+
+ MM_TAG_PGM,
+ MM_TAG_PGM_CHUNK_MAPPING,
+ MM_TAG_PGM_HANDLERS,
+ MM_TAG_PGM_HANDLER_TYPES,
+ MM_TAG_PGM_MAPPINGS,
+ MM_TAG_PGM_PHYS,
+ MM_TAG_PGM_POOL,
+
+ MM_TAG_REM,
+
+ MM_TAG_SELM,
+
+ MM_TAG_SSM,
+
+ MM_TAG_STAM,
+
+ MM_TAG_TM,
+
+ MM_TAG_TRPM,
+
+ MM_TAG_VM,
+ MM_TAG_VM_REQ,
+
+ MM_TAG_VMM,
+
+ MM_TAG_HM,
+
+ MM_TAG_32BIT_HACK = 0x7fffffff
+} MMTAG;
+
+
+
+
+/** @defgroup grp_mm_hyper Hypervisor Memory Management
+ * @{ */
+
+VMMDECL(RTR0PTR) MMHyperR3ToR0(PVM pVM, RTR3PTR R3Ptr);
+
+#ifndef IN_RING3
+VMMDECL(void *) MMHyperR3ToCC(PVM pVM, RTR3PTR R3Ptr);
+#else
+DECLINLINE(void *) MMHyperR3ToCC(PVM pVM, RTR3PTR R3Ptr)
+{
+ NOREF(pVM);
+ return R3Ptr;
+}
+#endif
+
+
+/** @def MMHYPER_RC_ASSERT_RCPTR
+ * Asserts that an address is either NULL or inside the hypervisor memory area.
+ * This assertion only works while IN_RC, it's a NOP everywhere else.
+ * @thread The Emulation Thread.
+ */
+#define MMHYPER_RC_ASSERT_RCPTR(pVM, RCPtr) do { } while (0)
+
+/** @} */
+
+
+#if defined(IN_RING3) || defined(DOXYGEN_RUNNING)
+/** @defgroup grp_mm_r3 The MM Host Context Ring-3 API
+ * @{
+ */
+
+VMMR3DECL(int) MMR3InitUVM(PUVM pUVM);
+VMMR3DECL(int) MMR3Init(PVM pVM);
+VMMR3DECL(int) MMR3InitPaging(PVM pVM);
+VMMR3DECL(int) MMR3Term(PVM pVM);
+VMMR3DECL(void) MMR3TermUVM(PUVM pUVM);
+VMMR3DECL(int) MMR3ReserveHandyPages(PVM pVM, uint32_t cHandyPages);
+VMMR3DECL(int) MMR3IncreaseBaseReservation(PVM pVM, uint64_t cAddBasePages);
+VMMR3DECL(int) MMR3AdjustFixedReservation(PVM pVM, int32_t cDeltaFixedPages, const char *pszDesc);
+VMMR3DECL(int) MMR3UpdateShadowReservation(PVM pVM, uint32_t cShadowPages);
+/** @} */
+
+
+/** @defgroup grp_mm_phys Guest Physical Memory Manager
+ * @todo retire this group, elimintating or moving MMR3PhysGetRamSize to PGMPhys.
+ * @{ */
+VMMR3DECL(uint64_t) MMR3PhysGetRamSize(PVM pVM);
+VMMR3DECL(uint32_t) MMR3PhysGetRamSizeBelow4GB(PVM pVM);
+VMMR3DECL(uint64_t) MMR3PhysGetRamSizeAbove4GB(PVM pVM);
+VMMR3DECL(uint32_t) MMR3PhysGet4GBRamHoleSize(PVM pVM);
+/** @} */
+
+
+/** @defgroup grp_mm_heap Heap Manager
+ * @{ */
+VMMR3DECL(void *) MMR3HeapAlloc(PVM pVM, MMTAG enmTag, size_t cbSize);
+VMMR3DECL(void *) MMR3HeapAllocU(PUVM pUVM, MMTAG enmTag, size_t cbSize);
+VMMR3DECL(int) MMR3HeapAllocEx(PVM pVM, MMTAG enmTag, size_t cbSize, void **ppv);
+VMMR3DECL(int) MMR3HeapAllocExU(PUVM pUVM, MMTAG enmTag, size_t cbSize, void **ppv);
+VMMR3DECL(void *) MMR3HeapAllocZ(PVM pVM, MMTAG enmTag, size_t cbSize);
+VMMR3DECL(void *) MMR3HeapAllocZU(PUVM pUVM, MMTAG enmTag, size_t cbSize);
+VMMR3DECL(int) MMR3HeapAllocZEx(PVM pVM, MMTAG enmTag, size_t cbSize, void **ppv);
+VMMR3DECL(int) MMR3HeapAllocZExU(PUVM pUVM, MMTAG enmTag, size_t cbSize, void **ppv);
+VMMR3DECL(void *) MMR3HeapRealloc(void *pv, size_t cbNewSize);
+VMMR3DECL(char *) MMR3HeapStrDup(PVM pVM, MMTAG enmTag, const char *psz);
+VMMR3DECL(char *) MMR3HeapStrDupU(PUVM pUVM, MMTAG enmTag, const char *psz);
+VMMR3DECL(char *) MMR3HeapAPrintf(PVM pVM, MMTAG enmTag, const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(3, 4);
+VMMR3DECL(char *) MMR3HeapAPrintfU(PUVM pUVM, MMTAG enmTag, const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(3, 4);
+VMMR3DECL(char *) MMR3HeapAPrintfV(PVM pVM, MMTAG enmTag, const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(3, 0);
+VMMR3DECL(char *) MMR3HeapAPrintfVU(PUVM pUVM, MMTAG enmTag, const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(3, 0);
+VMMR3DECL(void) MMR3HeapFree(void *pv);
+/** @} */
+
+#endif /* IN_RING3 || DOXYGEN_RUNNING */
+
+
+/** @} */
+RT_C_DECLS_END
+
+
+#endif /* !VBOX_INCLUDED_vmm_mm_h */
+
diff --git a/include/VBox/vmm/nem.h b/include/VBox/vmm/nem.h
new file mode 100644
index 00000000..3004efa5
--- /dev/null
+++ b/include/VBox/vmm/nem.h
@@ -0,0 +1,256 @@
+/** @file
+ * NEM - The Native Execution Manager.
+ */
+
+/*
+ * Copyright (C) 2018-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vmm_nem_h
+#define VBOX_INCLUDED_vmm_nem_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/types.h>
+#include <VBox/vmm/vmapi.h>
+#include <VBox/vmm/pgm.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_nem The Native Execution Manager API
+ * @ingroup grp_vmm
+ * @{
+ */
+
+/** @defgroup grp_nem_r3 The NEM ring-3 Context API
+ * @{
+ */
+VMMR3_INT_DECL(int) NEMR3InitConfig(PVM pVM);
+VMMR3_INT_DECL(int) NEMR3Init(PVM pVM, bool fFallback, bool fForced);
+VMMR3_INT_DECL(int) NEMR3InitAfterCPUM(PVM pVM);
+#ifdef IN_RING3
+VMMR3_INT_DECL(int) NEMR3InitCompleted(PVM pVM, VMINITCOMPLETED enmWhat);
+#endif
+VMMR3_INT_DECL(int) NEMR3Term(PVM pVM);
+VMMR3DECL(bool) NEMR3IsEnabled(PUVM pVM);
+VMMR3_INT_DECL(bool) NEMR3NeedSpecialTscMode(PVM pVM);
+VMMR3_INT_DECL(void) NEMR3Reset(PVM pVM);
+VMMR3_INT_DECL(void) NEMR3ResetCpu(PVMCPU pVCpu, bool fInitIpi);
+VMMR3DECL(const char *) NEMR3GetExitName(uint32_t uExit);
+VMMR3_INT_DECL(VBOXSTRICTRC) NEMR3RunGC(PVM pVM, PVMCPU pVCpu);
+VMMR3_INT_DECL(bool) NEMR3CanExecuteGuest(PVM pVM, PVMCPU pVCpu);
+VMMR3_INT_DECL(bool) NEMR3SetSingleInstruction(PVM pVM, PVMCPU pVCpu, bool fEnable);
+VMMR3_INT_DECL(void) NEMR3NotifyFF(PVM pVM, PVMCPU pVCpu, uint32_t fFlags);
+
+/**
+ * Checks if dirty page tracking for MMIO2 ranges is supported.
+ *
+ * If it is, PGM will not install a physical write access handler for the MMIO2
+ * region and instead just forward dirty bit queries NEMR3QueryMmio2DirtyBits.
+ * The enable/disable control of the tracking will be ignored, and PGM will
+ * always set NEM_NOTIFY_PHYS_MMIO_EX_F_TRACK_DIRTY_PAGES for such ranges.
+ *
+ * @retval true if supported.
+ * @retval false if not.
+ * @param pVM The cross context VM structure.
+ */
+VMMR3_INT_DECL(bool) NEMR3IsMmio2DirtyPageTrackingSupported(PVM pVM);
+
+/**
+ * Worker for PGMR3PhysMmio2QueryAndResetDirtyBitmap.
+ *
+ * @returns VBox status code.
+ * @param pVM The cross context VM structure.
+ * @param GCPhys The address of the MMIO2 range.
+ * @param cb The size of the MMIO2 range.
+ * @param uNemRange The NEM internal range number.
+ * @param pvBitmap The output bitmap. Must be 8-byte aligned. Ignored
+ * when @a cbBitmap is zero.
+ * @param cbBitmap The size of the bitmap. Must be the size of the whole
+ * MMIO2 range, rounded up to the nearest 8 bytes.
+ * When zero only a reset is done.
+ */
+VMMR3_INT_DECL(int) NEMR3PhysMmio2QueryAndResetDirtyBitmap(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, uint32_t uNemRange,
+ void *pvBitmap, size_t cbBitmap);
+
+VMMR3_INT_DECL(int) NEMR3NotifyPhysRamRegister(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, void *pvR3,
+ uint8_t *pu2State, uint32_t *puNemRange);
+VMMR3_INT_DECL(int) NEMR3NotifyPhysMmioExMapEarly(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, uint32_t fFlags,
+ void *pvRam, void *pvMmio2, uint8_t *pu2State, uint32_t *puNemRange);
+VMMR3_INT_DECL(int) NEMR3NotifyPhysMmioExMapLate(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, uint32_t fFlags,
+ void *pvRam, void *pvMmio2, uint32_t *puNemRange);
+VMMR3_INT_DECL(int) NEMR3NotifyPhysMmioExUnmap(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, uint32_t fFlags,
+ void *pvRam, void *pvMmio2, uint8_t *pu2State, uint32_t *puNemRange);
+/** @name Flags for NEMR3NotifyPhysMmioExMap and NEMR3NotifyPhysMmioExUnmap.
+ * @{ */
+/** Set if the range is replacing RAM rather that unused space. */
+#define NEM_NOTIFY_PHYS_MMIO_EX_F_REPLACE RT_BIT(0)
+/** Set if it's MMIO2 being mapped or unmapped. */
+#define NEM_NOTIFY_PHYS_MMIO_EX_F_MMIO2 RT_BIT(1)
+/** Set if MMIO2 and dirty page tracking is configured. */
+#define NEM_NOTIFY_PHYS_MMIO_EX_F_TRACK_DIRTY_PAGES RT_BIT(2)
+/** @} */
+
+/**
+ * Called very early during ROM registration, basically so an existing RAM range
+ * can be adjusted if desired.
+ *
+ * It will be succeeded by a number of NEMHCNotifyPhysPageProtChanged()
+ * calls and finally a call to NEMR3NotifyPhysRomRegisterLate().
+ *
+ * @returns VBox status code
+ * @param pVM The cross context VM structure.
+ * @param GCPhys The ROM address (page aligned).
+ * @param cb The size (page aligned).
+ * @param pvPages Pointer to the ROM (RAM) pages in simplified mode
+ * when NEM_NOTIFY_PHYS_ROM_F_REPLACE is set, otherwise
+ * NULL.
+ * @param fFlags NEM_NOTIFY_PHYS_ROM_F_XXX.
+ * @param pu2State New page state or UINT8_MAX to leave as-is.
+ * @param puNemRange Access to the relevant PGMRAMRANGE::uNemRange field.
+ */
+VMMR3_INT_DECL(int) NEMR3NotifyPhysRomRegisterEarly(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, void *pvPages,
+ uint32_t fFlags, uint8_t *pu2State, uint32_t *puNemRange);
+
+/**
+ * Called after the ROM range has been fully completed.
+ *
+ * This will be preceeded by a NEMR3NotifyPhysRomRegisterEarly() call as well a
+ * number of NEMHCNotifyPhysPageProtChanged calls.
+ *
+ * @returns VBox status code
+ * @param pVM The cross context VM structure.
+ * @param GCPhys The ROM address (page aligned).
+ * @param cb The size (page aligned).
+ * @param pvPages Pointer to the ROM pages.
+ * @param fFlags NEM_NOTIFY_PHYS_ROM_F_XXX.
+ * @param pu2State Where to return the new NEM page state, UINT8_MAX
+ * for unchanged.
+ * @param puNemRange Access to the relevant PGMRAMRANGE::uNemRange field.
+ */
+VMMR3_INT_DECL(int) NEMR3NotifyPhysRomRegisterLate(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, void *pvPages,
+ uint32_t fFlags, uint8_t *pu2State, uint32_t *puNemRange);
+
+/** @name Flags for NEMR3NotifyPhysRomRegisterEarly and NEMR3NotifyPhysRomRegisterLate.
+ * @{ */
+/** Set if the range is replacing RAM rather that unused space. */
+#define NEM_NOTIFY_PHYS_ROM_F_REPLACE RT_BIT(1)
+/** Set if it's MMIO2 being mapped or unmapped. */
+#define NEM_NOTIFY_PHYS_ROM_F_SHADOW RT_BIT(2)
+/** @} */
+
+/**
+ * Called when the A20 state changes.
+ *
+ * Windows: Hyper-V doesn't seem to offer a simple way of implementing the A20
+ * line features of PCs. So, we do a very minimal emulation of the HMA to make
+ * DOS happy.
+ *
+ * @param pVCpu The CPU the A20 state changed on.
+ * @param fEnabled Whether it was enabled (true) or disabled.
+ */
+VMMR3_INT_DECL(void) NEMR3NotifySetA20(PVMCPU pVCpu, bool fEnabled);
+VMMR3_INT_DECL(void) NEMR3NotifyDebugEventChanged(PVM pVM);
+VMMR3_INT_DECL(void) NEMR3NotifyDebugEventChangedPerCpu(PVM pVM, PVMCPU pVCpu);
+/** @} */
+
+
+/** @defgroup grp_nem_r0 The NEM ring-0 Context API
+ * @{ */
+VMMR0_INT_DECL(int) NEMR0Init(void);
+VMMR0_INT_DECL(void) NEMR0Term(void);
+VMMR0_INT_DECL(int) NEMR0InitVM(PGVM pGVM);
+VMMR0_INT_DECL(int) NEMR0InitVMPart2(PGVM pGVM);
+VMMR0_INT_DECL(void) NEMR0CleanupVM(PGVM pGVM);
+VMMR0_INT_DECL(int) NEMR0MapPages(PGVM pGVM, VMCPUID idCpu);
+VMMR0_INT_DECL(int) NEMR0UnmapPages(PGVM pGVM, VMCPUID idCpu);
+VMMR0_INT_DECL(int) NEMR0ExportState(PGVM pGVM, VMCPUID idCpu);
+VMMR0_INT_DECL(int) NEMR0ImportState(PGVM pGVM, VMCPUID idCpu, uint64_t fWhat);
+VMMR0_INT_DECL(int) NEMR0QueryCpuTick(PGVM pGVM, VMCPUID idCpu);
+VMMR0_INT_DECL(int) NEMR0ResumeCpuTickOnAll(PGVM pGVM, VMCPUID idCpu, uint64_t uPausedTscValue);
+VMMR0_INT_DECL(VBOXSTRICTRC) NEMR0RunGuestCode(PGVM pGVM, VMCPUID idCpu);
+VMMR0_INT_DECL(int) NEMR0UpdateStatistics(PGVM pGVM, VMCPUID idCpu);
+VMMR0_INT_DECL(int) NEMR0DoExperiment(PGVM pGVM, VMCPUID idCpu, uint64_t u64Arg);
+#ifdef RT_OS_WINDOWS
+VMMR0_INT_DECL(int) NEMR0WinGetPartitionId(PGVM pGVM, uintptr_t uHandle);
+#endif
+/** @} */
+
+
+/** @defgroup grp_nem_hc The NEM Host Context API
+ * @{
+ */
+VMM_INT_DECL(bool) NEMHCIsLongModeAllowed(PVMCC pVM);
+VMM_INT_DECL(uint32_t) NEMHCGetFeatures(PVMCC pVM);
+VMM_INT_DECL(int) NEMImportStateOnDemand(PVMCPUCC pVCpu, uint64_t fWhat);
+
+/** @name NEM_FEAT_F_XXX - Features supported by the NEM backend
+ * @{ */
+/** NEM backend uses nested paging for the guest. */
+#define NEM_FEAT_F_NESTED_PAGING RT_BIT(0)
+/** NEM backend uses full (unrestricted) guest execution. */
+#define NEM_FEAT_F_FULL_GST_EXEC RT_BIT(1)
+/** NEM backend offers an xsave/xrstor interface. */
+#define NEM_FEAT_F_XSAVE_XRSTOR RT_BIT(2)
+/** @} */
+
+VMM_INT_DECL(void) NEMHCNotifyHandlerPhysicalRegister(PVMCC pVM, PGMPHYSHANDLERKIND enmKind, RTGCPHYS GCPhys, RTGCPHYS cb);
+VMM_INT_DECL(void) NEMHCNotifyHandlerPhysicalDeregister(PVMCC pVM, PGMPHYSHANDLERKIND enmKind, RTGCPHYS GCPhys, RTGCPHYS cb,
+ RTR3PTR pvMemR3, uint8_t *pu2State);
+VMM_INT_DECL(void) NEMHCNotifyHandlerPhysicalModify(PVMCC pVM, PGMPHYSHANDLERKIND enmKind, RTGCPHYS GCPhysOld,
+ RTGCPHYS GCPhysNew, RTGCPHYS cb, bool fRestoreAsRAM);
+
+VMM_INT_DECL(int) NEMHCNotifyPhysPageAllocated(PVMCC pVM, RTGCPHYS GCPhys, RTHCPHYS HCPhys, uint32_t fPageProt,
+ PGMPAGETYPE enmType, uint8_t *pu2State);
+VMM_INT_DECL(void) NEMHCNotifyPhysPageProtChanged(PVMCC pVM, RTGCPHYS GCPhys, RTHCPHYS HCPhys, RTR3PTR pvR3, uint32_t fPageProt,
+ PGMPAGETYPE enmType, uint8_t *pu2State);
+VMM_INT_DECL(void) NEMHCNotifyPhysPageChanged(PVMCC pVM, RTGCPHYS GCPhys, RTHCPHYS HCPhysPrev, RTHCPHYS HCPhysNew,
+ RTR3PTR pvNewR3, uint32_t fPageProt, PGMPAGETYPE enmType, uint8_t *pu2State);
+/** @name NEM_PAGE_PROT_XXX - Page protection
+ * @{ */
+#define NEM_PAGE_PROT_NONE UINT32_C(0) /**< All access causes VM exits. */
+#define NEM_PAGE_PROT_READ RT_BIT(0) /**< Read access. */
+#define NEM_PAGE_PROT_EXECUTE RT_BIT(1) /**< Execute access. */
+#define NEM_PAGE_PROT_WRITE RT_BIT(2) /**< write access. */
+/** @} */
+
+VMM_INT_DECL(int) NEMHCQueryCpuTick(PVMCPUCC pVCpu, uint64_t *pcTicks, uint32_t *puAux);
+VMM_INT_DECL(int) NEMHCResumeCpuTickOnAll(PVMCC pVM, PVMCPUCC pVCpu, uint64_t uPausedTscValue);
+
+/** @} */
+
+/** @} */
+RT_C_DECLS_END
+
+
+#endif /* !VBOX_INCLUDED_vmm_nem_h */
+
diff --git a/include/VBox/vmm/pdm.h b/include/VBox/vmm/pdm.h
new file mode 100644
index 00000000..be46e570
--- /dev/null
+++ b/include/VBox/vmm/pdm.h
@@ -0,0 +1,54 @@
+/** @file
+ * PDM - Pluggable Device Manager.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vmm_pdm_h
+#define VBOX_INCLUDED_vmm_pdm_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/vmm/pdmapi.h>
+#include <VBox/vmm/pdmqueue.h>
+#include <VBox/vmm/pdmcritsect.h>
+#include <VBox/vmm/pdmcritsectrw.h>
+#include <VBox/vmm/pdmthread.h>
+#include <VBox/vmm/pdmifs.h>
+#include <VBox/vmm/pdmdrv.h>
+#include <VBox/vmm/pdmdev.h>
+#include <VBox/vmm/pdmusb.h>
+#include <VBox/vmm/pdmsrv.h>
+
+#endif /* !VBOX_INCLUDED_vmm_pdm_h */
+
diff --git a/include/VBox/vmm/pdmapi.h b/include/VBox/vmm/pdmapi.h
new file mode 100644
index 00000000..bf25f043
--- /dev/null
+++ b/include/VBox/vmm/pdmapi.h
@@ -0,0 +1,393 @@
+/** @file
+ * PDM - Pluggable Device Manager, Core API.
+ *
+ * The 'Core API' has been put in a different header because everyone
+ * is currently including pdm.h. So, pdm.h is for including all of the
+ * PDM stuff, while pdmapi.h is for the core stuff.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vmm_pdmapi_h
+#define VBOX_INCLUDED_vmm_pdmapi_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/vmm/pdmcommon.h>
+#ifdef IN_RING3
+# include <VBox/vmm/vmapi.h>
+#endif
+#include <VBox/sup.h>
+
+struct PDMDEVMODREGR0;
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_pdm The Pluggable Device Manager API
+ * @ingroup grp_vmm
+ * @{
+ */
+
+VMMDECL(int) PDMGetInterrupt(PVMCPUCC pVCpu, uint8_t *pu8Interrupt);
+VMMDECL(int) PDMIsaSetIrq(PVMCC pVM, uint8_t u8Irq, uint8_t u8Level, uint32_t uTagSrc);
+VMM_INT_DECL(bool) PDMHasIoApic(PVM pVM);
+VMM_INT_DECL(bool) PDMHasApic(PVM pVM);
+VMM_INT_DECL(PPDMDEVINS) PDMDeviceRing0IdxToInstance(PVMCC pVM, uint64_t idxR0Device);
+VMM_INT_DECL(int) PDMIoApicSetIrq(PVM pVM, PCIBDF uBusDevFn, uint8_t u8Irq, uint8_t u8Level, uint32_t uTagSrc);
+VMM_INT_DECL(void) PDMIoApicBroadcastEoi(PVMCC pVM, uint8_t uVector);
+VMM_INT_DECL(void) PDMIoApicSendMsi(PVMCC pVM, PCIBDF uBusDevFn, PCMSIMSG pMsi, uint32_t uTagSrc);
+VMM_INT_DECL(int) PDMVmmDevHeapR3ToGCPhys(PVM pVM, RTR3PTR pv, RTGCPHYS *pGCPhys);
+VMM_INT_DECL(bool) PDMVmmDevHeapIsEnabled(PVM pVM);
+
+/**
+ * Mapping/unmapping callback for an VMMDev heap allocation.
+ *
+ * @param pVM The cross context VM structure.
+ * @param pvAllocation The allocation address (ring-3).
+ * @param GCPhysAllocation The guest physical address of the mapping if
+ * it's being mapped, NIL_RTGCPHYS if it's being
+ * unmapped.
+ */
+typedef DECLCALLBACKTYPE(void, FNPDMVMMDEVHEAPNOTIFY,(PVM pVM, void *pvAllocation, RTGCPHYS GCPhysAllocation));
+/** Pointer (ring-3) to a FNPDMVMMDEVHEAPNOTIFY function. */
+typedef R3PTRTYPE(FNPDMVMMDEVHEAPNOTIFY *) PFNPDMVMMDEVHEAPNOTIFY;
+
+
+#if defined(IN_RING3) || defined(DOXYGEN_RUNNING)
+/** @defgroup grp_pdm_r3 The PDM Host Context Ring-3 API
+ * @{
+ */
+VMMR3_INT_DECL(int) PDMR3InitUVM(PUVM pUVM);
+VMMR3_INT_DECL(int) PDMR3LdrLoadVMMR0U(PUVM pUVM);
+VMMR3_INT_DECL(int) PDMR3Init(PVM pVM);
+VMMR3_INT_DECL(int) PDMR3InitCompleted(PVM pVM, VMINITCOMPLETED enmWhat);
+VMMR3DECL(void) PDMR3PowerOn(PVM pVM);
+VMMR3_INT_DECL(bool) PDMR3GetResetInfo(PVM pVM, uint32_t fOverride, uint32_t *pfResetFlags);
+VMMR3_INT_DECL(void) PDMR3ResetCpu(PVMCPU pVCpu);
+VMMR3_INT_DECL(void) PDMR3Reset(PVM pVM);
+VMMR3_INT_DECL(void) PDMR3MemSetup(PVM pVM, bool fAtReset);
+VMMR3_INT_DECL(void) PDMR3SoftReset(PVM pVM, uint32_t fResetFlags);
+VMMR3_INT_DECL(void) PDMR3Suspend(PVM pVM);
+VMMR3_INT_DECL(void) PDMR3Resume(PVM pVM);
+VMMR3DECL(void) PDMR3PowerOff(PVM pVM);
+VMMR3_INT_DECL(void) PDMR3Relocate(PVM pVM, RTGCINTPTR offDelta);
+VMMR3_INT_DECL(int) PDMR3Term(PVM pVM);
+VMMR3_INT_DECL(void) PDMR3TermUVM(PUVM pUVM);
+VMMR3_INT_DECL(bool) PDMR3HasLoadedState(PVM pVM);
+
+/** PDM loader context indicator. */
+typedef enum PDMLDRCTX
+{
+ /** Invalid zero value. */
+ PDMLDRCTX_INVALID = 0,
+ /** Ring-0 context. */
+ PDMLDRCTX_RING_0,
+ /** Ring-3 context. */
+ PDMLDRCTX_RING_3,
+ /** Raw-mode context. */
+ PDMLDRCTX_RAW_MODE,
+ /** End of valid context values. */
+ PDMLDRCTX_END,
+ /** 32-bit type hack. */
+ PDMLDRCTX_32BIT_HACK = 0x7fffffff
+} PDMLDRCTX;
+
+/**
+ * Module enumeration callback function.
+ *
+ * @returns VBox status.
+ * Failure will stop the search and return the return code.
+ * Warnings will be ignored and not returned.
+ * @param pVM The cross context VM structure.
+ * @param pszFilename Module filename.
+ * @param pszName Module name. (short and unique)
+ * @param ImageBase Address where to executable image is loaded.
+ * @param cbImage Size of the executable image.
+ * @param enmCtx The context the module is loaded into.
+ * @param pvArg User argument.
+ */
+typedef DECLCALLBACKTYPE(int, FNPDMR3ENUM,(PVM pVM, const char *pszFilename, const char *pszName,
+ RTUINTPTR ImageBase, size_t cbImage, PDMLDRCTX enmCtx, void *pvArg));
+/** Pointer to a FNPDMR3ENUM() function. */
+typedef FNPDMR3ENUM *PFNPDMR3ENUM;
+VMMR3DECL(int) PDMR3LdrEnumModules(PVM pVM, PFNPDMR3ENUM pfnCallback, void *pvArg);
+VMMR3_INT_DECL(void) PDMR3LdrRelocateU(PUVM pUVM, RTGCINTPTR offDelta);
+VMMR3_INT_DECL(int) PDMR3LdrLoadR0(PUVM pUVM, const char *pszModule, const char *pszSearchPath);
+VMMR3_INT_DECL(int) PDMR3LdrGetSymbolR3(PVM pVM, const char *pszModule, const char *pszSymbol, void **ppvValue);
+VMMR3DECL(int) PDMR3LdrGetSymbolR0(PVM pVM, const char *pszModule, const char *pszSymbol, PRTR0PTR ppvValue);
+VMMR3DECL(int) PDMR3LdrGetSymbolR0Lazy(PVM pVM, const char *pszModule, const char *pszSearchPath, const char *pszSymbol, PRTR0PTR ppvValue);
+VMMR3DECL(int) PDMR3LdrLoadRC(PVM pVM, const char *pszFilename, const char *pszName);
+VMMR3DECL(int) PDMR3LdrGetSymbolRC(PVM pVM, const char *pszModule, const char *pszSymbol, PRTRCPTR pRCPtrValue);
+VMMR3DECL(int) PDMR3LdrGetSymbolRCLazy(PVM pVM, const char *pszModule, const char *pszSearchPath, const char *pszSymbol,
+ PRTRCPTR pRCPtrValue);
+VMMR3_INT_DECL(int) PDMR3LdrQueryRCModFromPC(PVM pVM, RTRCPTR uPC,
+ char *pszModName, size_t cchModName, PRTRCPTR pMod,
+ char *pszNearSym1, size_t cchNearSym1, PRTRCPTR pNearSym1,
+ char *pszNearSym2, size_t cchNearSym2, PRTRCPTR pNearSym2);
+VMMR3_INT_DECL(int) PDMR3LdrQueryR0ModFromPC(PVM pVM, RTR0PTR uPC,
+ char *pszModName, size_t cchModName, PRTR0PTR pMod,
+ char *pszNearSym1, size_t cchNearSym1, PRTR0PTR pNearSym1,
+ char *pszNearSym2, size_t cchNearSym2, PRTR0PTR pNearSym2);
+VMMR3_INT_DECL(int) PDMR3LdrGetInterfaceSymbols(PVM pVM, void *pvInterface, size_t cbInterface,
+ const char *pszModule, const char *pszSearchPath,
+ const char *pszSymPrefix, const char *pszSymList,
+ bool fRing0OrRC);
+
+VMMR3DECL(int) PDMR3QueryDevice(PUVM pUVM, const char *pszDevice, unsigned iInstance, PPPDMIBASE ppBase);
+VMMR3DECL(int) PDMR3QueryDeviceLun(PUVM pUVM, const char *pszDevice, unsigned iInstance, unsigned iLun, PPPDMIBASE ppBase);
+VMMR3DECL(int) PDMR3QueryLun(PUVM pUVM, const char *pszDevice, unsigned iInstance, unsigned iLun, PPPDMIBASE ppBase);
+VMMR3DECL(int) PDMR3QueryDriverOnLun(PUVM pUVM, const char *pszDevice, unsigned iInstance, unsigned iLun,
+ const char *pszDriver, PPPDMIBASE ppBase);
+VMMR3DECL(int) PDMR3DeviceAttach(PUVM pUVM, const char *pszDevice, unsigned iInstance, unsigned iLun, uint32_t fFlags,
+ PPDMIBASE *ppBase);
+VMMR3DECL(int) PDMR3DeviceDetach(PUVM pUVM, const char *pszDevice, unsigned iInstance, unsigned iLun, uint32_t fFlags);
+VMMR3_INT_DECL(PPDMCRITSECT) PDMR3DevGetCritSect(PVM pVM, PPDMDEVINS pDevIns);
+VMMR3DECL(int) PDMR3DriverAttach(PUVM pUVM, const char *pszDevice, unsigned iDevIns, unsigned iLun, uint32_t fFlags,
+ PPPDMIBASE ppBase);
+VMMR3DECL(int) PDMR3DriverDetach(PUVM pUVM, const char *pszDevice, unsigned iDevIns, unsigned iLun,
+ const char *pszDriver, unsigned iOccurrence, uint32_t fFlags);
+VMMR3DECL(int) PDMR3DriverReattach(PUVM pVM, const char *pszDevice, unsigned iDevIns, unsigned iLun,
+ const char *pszDriver, unsigned iOccurrence, uint32_t fFlags, PCFGMNODE pCfg,
+ PPPDMIBASE ppBase);
+VMMR3DECL(void) PDMR3DmaRun(PVM pVM);
+
+VMMR3_INT_DECL(int) PDMR3VmmDevHeapAlloc(PVM pVM, size_t cbSize, PFNPDMVMMDEVHEAPNOTIFY pfnNotify, RTR3PTR *ppv);
+VMMR3_INT_DECL(int) PDMR3VmmDevHeapFree(PVM pVM, RTR3PTR pv);
+VMMR3_INT_DECL(int) PDMR3TracingConfig(PVM pVM, const char *pszName, size_t cchName, bool fEnable, bool fApply);
+VMMR3_INT_DECL(bool) PDMR3TracingAreAll(PVM pVM, bool fEnabled);
+VMMR3_INT_DECL(int) PDMR3TracingQueryConfig(PVM pVM, char *pszConfig, size_t cbConfig);
+/** @} */
+#endif /* IN_RING3 */
+
+
+
+/** @defgroup grp_pdm_rc The PDM Raw-Mode Context API
+ * @{
+ */
+/** @} */
+
+
+
+/** @defgroup grp_pdm_r0 The PDM Ring-0 Context API
+ * @{
+ */
+VMMR0_INT_DECL(void) PDMR0Init(void *hMod);
+VMMR0DECL(int) PDMR0DeviceRegisterModule(void *hMod, struct PDMDEVMODREGR0 *pModReg);
+VMMR0DECL(int) PDMR0DeviceDeregisterModule(void *hMod, struct PDMDEVMODREGR0 *pModReg);
+
+VMMR0_INT_DECL(void) PDMR0InitPerVMData(PGVM pGVM);
+VMMR0_INT_DECL(void) PDMR0CleanupVM(PGVM pGVM);
+
+/**
+ * Request buffer for PDMR0DriverCallReqHandler / VMMR0_DO_PDM_DRIVER_CALL_REQ_HANDLER.
+ * @see PDMR0DriverCallReqHandler.
+ */
+typedef struct PDMDRIVERCALLREQHANDLERREQ
+{
+ /** The header. */
+ SUPVMMR0REQHDR Hdr;
+ /** The driver instance. */
+ PPDMDRVINSR0 pDrvInsR0;
+ /** The operation. */
+ uint32_t uOperation;
+ /** Explicit alignment padding. */
+ uint32_t u32Alignment;
+ /** Optional 64-bit integer argument. */
+ uint64_t u64Arg;
+} PDMDRIVERCALLREQHANDLERREQ;
+/** Pointer to a PDMR0DriverCallReqHandler / VMMR0_DO_PDM_DRIVER_CALL_REQ_HANDLER
+ * request buffer. */
+typedef PDMDRIVERCALLREQHANDLERREQ *PPDMDRIVERCALLREQHANDLERREQ;
+
+VMMR0_INT_DECL(int) PDMR0DriverCallReqHandler(PGVM pGVM, PPDMDRIVERCALLREQHANDLERREQ pReq);
+
+
+/**
+ * Request buffer for PDMR0DeviceCreateReqHandler / VMMR0_DO_PDM_DEVICE_CREATE.
+ * @see PDMR0DeviceCreateReqHandler.
+ */
+typedef struct PDMDEVICECREATEREQ
+{
+ /** The header. */
+ SUPVMMR0REQHDR Hdr;
+ /** Out: Where to return the address of the ring-3 device instance. */
+ PPDMDEVINSR3 pDevInsR3;
+
+ /** Copy of PDMDEVREGR3::fFlags for matching with PDMDEVREGR0::fFlags. */
+ uint32_t fFlags;
+ /** Copy of PDMDEVREGR3::fClass for matching with PDMDEVREGR0::fFlags. */
+ uint32_t fClass;
+ /** Copy of PDMDEVREGR3::cMaxInstances for matching with
+ * PDMDEVREGR0::cMaxInstances. */
+ uint32_t cMaxInstances;
+ /** Copy of PDMDEVREGR3::uSharedVersion for matching with
+ * PDMDEVREGR0::uSharedVersion. */
+ uint32_t uSharedVersion;
+ /** Copy of PDMDEVREGR3::cbInstanceShared for matching with
+ * PDMDEVREGR0::cbInstanceShared. */
+ uint32_t cbInstanceShared;
+ /** Copy of PDMDEVREGR3::cbInstanceCC. */
+ uint32_t cbInstanceR3;
+ /** Copy of PDMDEVREGR3::cbInstanceRC for matching with
+ * PDMDEVREGR0::cbInstanceRC. */
+ uint32_t cbInstanceRC;
+ /** Copy of PDMDEVREGR3::cMaxPciDevices for matching with
+ * PDMDEVREGR0::cMaxPciDevices. */
+ uint16_t cMaxPciDevices;
+ /** Copy of PDMDEVREGR3::cMaxMsixVectors for matching with
+ * PDMDEVREGR0::cMaxMsixVectors. */
+ uint16_t cMaxMsixVectors;
+
+ /** The device instance ordinal. */
+ uint32_t iInstance;
+ /** Set if the raw-mode component is desired. */
+ bool fRCEnabled;
+ /** Explicit padding. */
+ bool afReserved[3];
+ /** DBGF tracer event source handle if configured. */
+ DBGFTRACEREVTSRC hDbgfTracerEvtSrc;
+
+ /** In: Device name. */
+ char szDevName[32];
+ /** In: The module name (no path). */
+ char szModName[32];
+} PDMDEVICECREATEREQ;
+/** Pointer to a PDMR0DeviceCreate / VMMR0_DO_PDM_DEVICE_CREATE request buffer. */
+typedef PDMDEVICECREATEREQ *PPDMDEVICECREATEREQ;
+
+VMMR0_INT_DECL(int) PDMR0DeviceCreateReqHandler(PGVM pGVM, PPDMDEVICECREATEREQ pReq);
+
+/**
+ * The ring-0 device call to make.
+ */
+typedef enum PDMDEVICEGENCALL
+{
+ PDMDEVICEGENCALL_INVALID = 0,
+ PDMDEVICEGENCALL_CONSTRUCT,
+ PDMDEVICEGENCALL_DESTRUCT,
+ PDMDEVICEGENCALL_REQUEST,
+ PDMDEVICEGENCALL_END,
+ PDMDEVICEGENCALL_32BIT_HACK = 0x7fffffff
+} PDMDEVICEGENCALL;
+
+/**
+ * Request buffer for PDMR0DeviceGenCallReqHandler / VMMR0_DO_PDM_DEVICE_GEN_CALL.
+ * @see PDMR0DeviceGenCallReqHandler.
+ */
+typedef struct PDMDEVICEGENCALLREQ
+{
+ /** The header. */
+ SUPVMMR0REQHDR Hdr;
+ /** The ring-3 device instance. */
+ PPDMDEVINSR3 pDevInsR3;
+ /** The ring-0 device handle. */
+ uint32_t idxR0Device;
+ /** The call to make. */
+ PDMDEVICEGENCALL enmCall;
+ union
+ {
+ /** PDMDEVICEGENCALL_REQUEST: */
+ struct
+ {
+ /** The request argument. */
+ uint64_t uArg;
+ /** The request number. */
+ uint32_t uReq;
+ } Req;
+ /** Size padding. */
+ uint64_t au64[3];
+ } Params;
+} PDMDEVICEGENCALLREQ;
+/** Pointer to a PDMR0DeviceGenCallReqHandler / VMMR0_DO_PDM_DEVICE_GEN_CALL request buffer. */
+typedef PDMDEVICEGENCALLREQ *PPDMDEVICEGENCALLREQ;
+
+VMMR0_INT_DECL(int) PDMR0DeviceGenCallReqHandler(PGVM pGVM, PPDMDEVICEGENCALLREQ pReq, VMCPUID idCpu);
+
+/**
+ * Request buffer for PDMR0DeviceCompatSetCritSectReqHandler / VMMR0_DO_PDM_DEVICE_COMPAT_SET_CRITSECT
+ * @see PDMR0DeviceCompatSetCritSectReqHandler.
+ */
+typedef struct PDMDEVICECOMPATSETCRITSECTREQ
+{
+ /** The header. */
+ SUPVMMR0REQHDR Hdr;
+ /** The ring-3 device instance. */
+ PPDMDEVINSR3 pDevInsR3;
+ /** The ring-0 device handle. */
+ uint32_t idxR0Device;
+ /** The critical section address (ring-3). */
+ R3PTRTYPE(PPDMCRITSECT) pCritSectR3;
+} PDMDEVICECOMPATSETCRITSECTREQ;
+/** Pointer to a PDMR0DeviceGenCallReqHandler / VMMR0_DO_PDM_DEVICE_GEN_CALL request buffer. */
+typedef PDMDEVICECOMPATSETCRITSECTREQ *PPDMDEVICECOMPATSETCRITSECTREQ;
+
+VMMR0_INT_DECL(int) PDMR0DeviceCompatSetCritSectReqHandler(PGVM pGVM, PPDMDEVICECOMPATSETCRITSECTREQ pReq);
+
+
+/**
+ * Request buffer for PDMR0QueueCreateReqHandler / VMMR0_DO_PDM_QUEUE_CREATE.
+ * @see PDMR0QueueCreateReqHandler.
+ */
+typedef struct PDMQUEUECREATEREQ
+{
+ /** The header. */
+ SUPVMMR0REQHDR Hdr;
+
+ /** Number of queue items. */
+ uint32_t cItems;
+ /** Queue item size. */
+ uint32_t cbItem;
+ /** Owner type (PDMQUEUETYPE). */
+ uint32_t enmType;
+ /** The ring-3 owner pointer. */
+ RTR3PTR pvOwner;
+ /** The ring-3 callback function address. */
+ RTR3PTR pfnCallback;
+ /** The queue name. */
+ char szName[40];
+
+ /** Output: The queue handle. */
+ PDMQUEUEHANDLE hQueue;
+} PDMQUEUECREATEREQ;
+/** Pointer to a PDMR0QueueCreateReqHandler / VMMR0_DO_PDM_QUEUE_CREATE request buffer. */
+typedef PDMQUEUECREATEREQ *PPDMQUEUECREATEREQ;
+
+VMMR0_INT_DECL(int) PDMR0QueueCreateReqHandler(PGVM pGVM, PPDMQUEUECREATEREQ pReq);
+
+/** @} */
+
+RT_C_DECLS_END
+
+/** @} */
+
+#endif /* !VBOX_INCLUDED_vmm_pdmapi_h */
diff --git a/include/VBox/vmm/pdmasynccompletion.h b/include/VBox/vmm/pdmasynccompletion.h
new file mode 100644
index 00000000..f46d7910
--- /dev/null
+++ b/include/VBox/vmm/pdmasynccompletion.h
@@ -0,0 +1,160 @@
+/** @file
+ * PDM - Pluggable Device Manager, Async I/O Completion.
+ */
+
+/*
+ * Copyright (C) 2007-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vmm_pdmasynccompletion_h
+#define VBOX_INCLUDED_vmm_pdmasynccompletion_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/types.h>
+#include <iprt/sg.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_pdm_async_completion The PDM Async I/O Completion API
+ * @ingroup grp_pdm
+ * @{
+ */
+
+/** Pointer to a PDM async completion template handle. */
+typedef struct PDMASYNCCOMPLETIONTEMPLATE *PPDMASYNCCOMPLETIONTEMPLATE;
+/** Pointer to a PDM async completion template handle pointer. */
+typedef PPDMASYNCCOMPLETIONTEMPLATE *PPPDMASYNCCOMPLETIONTEMPLATE;
+
+/** Pointer to a PDM async completion task handle. */
+typedef struct PDMASYNCCOMPLETIONTASK *PPDMASYNCCOMPLETIONTASK;
+/** Pointer to a PDM async completion task handle pointer. */
+typedef PPDMASYNCCOMPLETIONTASK *PPPDMASYNCCOMPLETIONTASK;
+
+/** Pointer to a PDM async completion endpoint handle. */
+typedef struct PDMASYNCCOMPLETIONENDPOINT *PPDMASYNCCOMPLETIONENDPOINT;
+/** Pointer to a PDM async completion endpoint handle pointer. */
+typedef PPDMASYNCCOMPLETIONENDPOINT *PPPDMASYNCCOMPLETIONENDPOINT;
+
+
+/**
+ * Completion callback for devices.
+ *
+ * @param pDevIns The device instance.
+ * @param pvUser User argument.
+ * @param rc The status code of the completed request.
+ */
+typedef DECLCALLBACKTYPE(void, FNPDMASYNCCOMPLETEDEV,(PPDMDEVINS pDevIns, void *pvUser, int rc));
+/** Pointer to a FNPDMASYNCCOMPLETEDEV(). */
+typedef FNPDMASYNCCOMPLETEDEV *PFNPDMASYNCCOMPLETEDEV;
+
+
+/**
+ * Completion callback for drivers.
+ *
+ * @param pDrvIns The driver instance.
+ * @param pvTemplateUser User argument given when creating the template.
+ * @param pvUser User argument given during request initiation.
+ * @param rc The status code of the completed request.
+ */
+typedef DECLCALLBACKTYPE(void, FNPDMASYNCCOMPLETEDRV,(PPDMDRVINS pDrvIns, void *pvTemplateUser, void *pvUser, int rc));
+/** Pointer to a FNPDMASYNCCOMPLETEDRV(). */
+typedef FNPDMASYNCCOMPLETEDRV *PFNPDMASYNCCOMPLETEDRV;
+
+
+/**
+ * Completion callback for USB devices.
+ *
+ * @param pUsbIns The USB device instance.
+ * @param pvUser User argument.
+ * @param rc The status code of the completed request.
+ */
+typedef DECLCALLBACKTYPE(void, FNPDMASYNCCOMPLETEUSB,(PPDMUSBINS pUsbIns, void *pvUser, int rc));
+/** Pointer to a FNPDMASYNCCOMPLETEUSB(). */
+typedef FNPDMASYNCCOMPLETEUSB *PFNPDMASYNCCOMPLETEUSB;
+
+
+/**
+ * Completion callback for internal.
+ *
+ * @param pVM The cross context VM structure.
+ * @param pvUser User argument for the task.
+ * @param pvUser2 User argument for the template.
+ * @param rc The status code of the completed request.
+ */
+typedef DECLCALLBACKTYPE(void, FNPDMASYNCCOMPLETEINT,(PVM pVM, void *pvUser, void *pvUser2, int rc));
+/** Pointer to a FNPDMASYNCCOMPLETEINT(). */
+typedef FNPDMASYNCCOMPLETEINT *PFNPDMASYNCCOMPLETEINT;
+
+VMMR3DECL(int) PDMR3AsyncCompletionTemplateCreateInternal(PVM pVM, PPPDMASYNCCOMPLETIONTEMPLATE ppTemplate,
+ PFNPDMASYNCCOMPLETEINT pfnCompleted, void *pvUser2, const char *pszDesc);
+VMMR3DECL(int) PDMR3AsyncCompletionTemplateDestroy(PPDMASYNCCOMPLETIONTEMPLATE pTemplate);
+VMMR3DECL(int) PDMR3AsyncCompletionEpCreateForFile(PPPDMASYNCCOMPLETIONENDPOINT ppEndpoint,
+ const char *pszFilename, uint32_t fFlags,
+ PPDMASYNCCOMPLETIONTEMPLATE pTemplate);
+
+/** @defgroup grp_pdmacep_file_flags Flags for PDMR3AsyncCompletionEpCreateForFile
+ * @{ */
+/** Open the file in read-only mode. */
+#define PDMACEP_FILE_FLAGS_READ_ONLY RT_BIT_32(0)
+/** Whether the file should not be write protected.
+ * The default is to protect the file against writes by other processes
+ * when opened in read/write mode to prevent data corruption by
+ * concurrent access which can occur if the local writeback cache is enabled.
+ */
+#define PDMACEP_FILE_FLAGS_DONT_LOCK RT_BIT_32(2)
+/** Open the endpoint with the host cache enabled. */
+#define PDMACEP_FILE_FLAGS_HOST_CACHE_ENABLED RT_BIT_32(3)
+/** @} */
+
+VMMR3DECL(void) PDMR3AsyncCompletionEpClose(PPDMASYNCCOMPLETIONENDPOINT pEndpoint);
+VMMR3DECL(int) PDMR3AsyncCompletionEpRead(PPDMASYNCCOMPLETIONENDPOINT pEndpoint, RTFOFF off,
+ PCRTSGSEG paSegments, unsigned cSegments,
+ size_t cbRead, void *pvUser,
+ PPPDMASYNCCOMPLETIONTASK ppTask);
+VMMR3DECL(int) PDMR3AsyncCompletionEpWrite(PPDMASYNCCOMPLETIONENDPOINT pEndpoint, RTFOFF off,
+ PCRTSGSEG paSegments, unsigned cSegments,
+ size_t cbWrite, void *pvUser,
+ PPPDMASYNCCOMPLETIONTASK ppTask);
+VMMR3DECL(int) PDMR3AsyncCompletionEpFlush(PPDMASYNCCOMPLETIONENDPOINT pEndpoint, void *pvUser, PPPDMASYNCCOMPLETIONTASK ppTask);
+VMMR3DECL(int) PDMR3AsyncCompletionEpGetSize(PPDMASYNCCOMPLETIONENDPOINT pEndpoint, uint64_t *pcbSize);
+VMMR3DECL(int) PDMR3AsyncCompletionEpSetSize(PPDMASYNCCOMPLETIONENDPOINT pEndpoint, uint64_t cbSize);
+VMMR3DECL(int) PDMR3AsyncCompletionEpSetBwMgr(PPDMASYNCCOMPLETIONENDPOINT pEndpoint, const char *pszBwMgr);
+VMMR3DECL(int) PDMR3AsyncCompletionTaskCancel(PPDMASYNCCOMPLETIONTASK pTask);
+VMMR3DECL(int) PDMR3AsyncCompletionBwMgrSetMaxForFile(PUVM pUVM, const char *pszBwMgr, uint32_t cbMaxNew);
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !VBOX_INCLUDED_vmm_pdmasynccompletion_h */
+
diff --git a/include/VBox/vmm/pdmasynctask.h b/include/VBox/vmm/pdmasynctask.h
new file mode 100644
index 00000000..422f9727
--- /dev/null
+++ b/include/VBox/vmm/pdmasynctask.h
@@ -0,0 +1,74 @@
+/** @file
+ * PDM - Pluggable Device Manager, Async Task.
+ */
+
+/*
+ * Copyright (C) 2007-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vmm_pdmasynctask_h
+#define VBOX_INCLUDED_vmm_pdmasynctask_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/types.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_pdm_async_task The PDM Async Task API
+ * @ingroup grp_pdm
+ * @{
+ */
+
+/** Pointer to a PDM async task template handle. */
+typedef struct PDMASYNCTASKTEMPLATE *PPDMASYNCTASKTEMPLATE;
+/** Pointer to a PDM async task template handle pointer. */
+typedef PPDMASYNCTASKTEMPLATE *PPPDMASYNCTASKTEMPLATE;
+
+/** Pointer to a PDM async task handle. */
+typedef struct PDMASYNCTASK *PPDMASYNCTASK;
+/** Pointer to a PDM async task handle pointer. */
+typedef PPDMASYNCTASK *PPPDMASYNCTASK;
+
+/* This should be similar to VMReq, only difference there will be a pool
+ of worker threads instead of EMT. The actual implementation should be
+ made in IPRT so we can reuse it for other stuff later. The reason why
+ it should be put in PDM is because we need to manage it wrt to VM
+ state changes (need exception - add a flag for this). */
+
+/** @} */
+
+
+RT_C_DECLS_END
+
+#endif /* !VBOX_INCLUDED_vmm_pdmasynctask_h */
+
diff --git a/include/VBox/vmm/pdmaudiohostenuminline.h b/include/VBox/vmm/pdmaudiohostenuminline.h
new file mode 100644
index 00000000..538c3bd6
--- /dev/null
+++ b/include/VBox/vmm/pdmaudiohostenuminline.h
@@ -0,0 +1,463 @@
+/* $Id: pdmaudiohostenuminline.h $ */
+/** @file
+ * PDM - Audio Helpers for host audio device enumeration, Inlined Code. (DEV,++)
+ *
+ * This is all inlined because it's too tedious to create a couple libraries to
+ * contain it all (same bad excuse as for intnetinline.h & pdmnetinline.h).
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vmm_pdmaudiohostenuminline_h
+#define VBOX_INCLUDED_vmm_pdmaudiohostenuminline_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#include <VBox/err.h>
+#include <VBox/log.h>
+#include <VBox/vmm/pdmaudioifs.h>
+#include <VBox/vmm/pdmaudioinline.h>
+
+#include <iprt/assert.h>
+#include <iprt/mem.h>
+#include <iprt/string.h>
+
+
+/** @defgroup grp_pdm_audio_host_enum_inline The PDM Host Audio Enumeration Helper APIs
+ * @ingroup grp_pdm
+ * @{
+ */
+
+
+/**
+ * Allocates a host audio device for an enumeration result.
+ *
+ * @returns Newly allocated audio device, or NULL on failure.
+ * @param cb The total device structure size. This must be at least the
+ * size of PDMAUDIOHOSTDEV. The idea is that the caller extends
+ * the PDMAUDIOHOSTDEV structure and appends additional data
+ * after it in its private structure.
+ * @param cbName The number of bytes to allocate for the name field
+ * (including the terminator). Pass zero if RTStrAlloc and
+ * friends will be used.
+ * @param cbId The number of bytes to allocate for the ID field. Pass
+ * zero if RTStrAlloc and friends will be used.
+ */
+DECLINLINE(PPDMAUDIOHOSTDEV) PDMAudioHostDevAlloc(size_t cb, size_t cbName, size_t cbId)
+{
+ AssertReturn(cb >= sizeof(PDMAUDIOHOSTDEV), NULL);
+ AssertReturn(cb < _4M, NULL);
+ AssertReturn(cbName < _4K, NULL);
+ AssertReturn(cbId < _16K, NULL);
+
+ PPDMAUDIOHOSTDEV pDev = (PPDMAUDIOHOSTDEV)RTMemAllocZ(RT_ALIGN_Z(cb + cbName + cbId, 64));
+ if (pDev)
+ {
+ pDev->uMagic = PDMAUDIOHOSTDEV_MAGIC;
+ pDev->cbSelf = (uint32_t)cb;
+ RTListInit(&pDev->ListEntry);
+ if (cbName)
+ pDev->pszName = (char *)pDev + cb;
+ if (cbId)
+ pDev->pszId = (char *)pDev + cb + cbName;
+ }
+ return pDev;
+}
+
+/**
+ * Frees a host audio device allocated by PDMAudioHostDevAlloc.
+ *
+ * @param pDev The device to free. NULL is ignored.
+ */
+DECLINLINE(void) PDMAudioHostDevFree(PPDMAUDIOHOSTDEV pDev)
+{
+ if (pDev)
+ {
+ Assert(pDev->uMagic == PDMAUDIOHOSTDEV_MAGIC);
+ pDev->uMagic = ~PDMAUDIOHOSTDEV_MAGIC;
+ pDev->cbSelf = 0;
+
+ if (pDev->fFlags & PDMAUDIOHOSTDEV_F_NAME_ALLOC)
+ {
+ RTStrFree(pDev->pszName);
+ pDev->pszName = NULL;
+ }
+
+ if (pDev->fFlags & PDMAUDIOHOSTDEV_F_ID_ALLOC)
+ {
+ RTStrFree(pDev->pszId);
+ pDev->pszId = NULL;
+ }
+
+ RTMemFree(pDev);
+ }
+}
+
+/**
+ * Duplicates a host audio device enumeration entry.
+ *
+ * @returns Duplicated audio device entry on success, or NULL on failure.
+ * @param pDev The audio device enum entry to duplicate.
+ * @param fOnlyCoreData
+ */
+DECLINLINE(PPDMAUDIOHOSTDEV) PDMAudioHostDevDup(PCPDMAUDIOHOSTDEV pDev, bool fOnlyCoreData)
+{
+ AssertPtrReturn(pDev, NULL);
+ Assert(pDev->uMagic == PDMAUDIOHOSTDEV_MAGIC);
+ Assert(fOnlyCoreData || !(pDev->fFlags & PDMAUDIOHOSTDEV_F_NO_DUP));
+
+ uint32_t cbToDup = fOnlyCoreData ? sizeof(PDMAUDIOHOSTDEV) : pDev->cbSelf;
+ AssertReturn(cbToDup >= sizeof(*pDev), NULL);
+
+ PPDMAUDIOHOSTDEV pDevDup = PDMAudioHostDevAlloc(cbToDup, 0, 0);
+ if (pDevDup)
+ {
+ memcpy(pDevDup, pDev, cbToDup);
+ RTListInit(&pDevDup->ListEntry);
+ pDevDup->cbSelf = cbToDup;
+
+ if (pDev->pszName)
+ {
+ uintptr_t off;
+ if ( (pDevDup->fFlags & PDMAUDIOHOSTDEV_F_NAME_ALLOC)
+ || (off = (uintptr_t)pDev->pszName - (uintptr_t)pDev) >= pDevDup->cbSelf)
+ {
+ pDevDup->fFlags |= PDMAUDIOHOSTDEV_F_NAME_ALLOC;
+ pDevDup->pszName = RTStrDup(pDev->pszName);
+ AssertReturnStmt(pDevDup->pszName, PDMAudioHostDevFree(pDevDup), NULL);
+ }
+ else
+ pDevDup->pszName = (char *)pDevDup + off;
+ }
+
+ if (pDev->pszId)
+ {
+ uintptr_t off;
+ if ( (pDevDup->fFlags & PDMAUDIOHOSTDEV_F_ID_ALLOC)
+ || (off = (uintptr_t)pDev->pszId - (uintptr_t)pDev) >= pDevDup->cbSelf)
+ {
+ pDevDup->fFlags |= PDMAUDIOHOSTDEV_F_ID_ALLOC;
+ pDevDup->pszId = RTStrDup(pDev->pszId);
+ AssertReturnStmt(pDevDup->pszId, PDMAudioHostDevFree(pDevDup), NULL);
+ }
+ else
+ pDevDup->pszId = (char *)pDevDup + off;
+ }
+ }
+
+ return pDevDup;
+}
+
+/**
+ * Initializes a host audio device enumeration.
+ *
+ * @param pDevEnm The enumeration to initialize.
+ */
+DECLINLINE(void) PDMAudioHostEnumInit(PPDMAUDIOHOSTENUM pDevEnm)
+{
+ AssertPtr(pDevEnm);
+
+ pDevEnm->uMagic = PDMAUDIOHOSTENUM_MAGIC;
+ pDevEnm->cDevices = 0;
+ RTListInit(&pDevEnm->LstDevices);
+}
+
+/**
+ * Deletes the host audio device enumeration and frees all device entries
+ * associated with it.
+ *
+ * The user must call PDMAudioHostEnumInit again to use it again.
+ *
+ * @param pDevEnm The host audio device enumeration to delete.
+ */
+DECLINLINE(void) PDMAudioHostEnumDelete(PPDMAUDIOHOSTENUM pDevEnm)
+{
+ if (pDevEnm)
+ {
+ AssertPtr(pDevEnm);
+ AssertReturnVoid(pDevEnm->uMagic == PDMAUDIOHOSTENUM_MAGIC);
+
+ PPDMAUDIOHOSTDEV pDev, pDevNext;
+ RTListForEachSafe(&pDevEnm->LstDevices, pDev, pDevNext, PDMAUDIOHOSTDEV, ListEntry)
+ {
+ RTListNodeRemove(&pDev->ListEntry);
+
+ PDMAudioHostDevFree(pDev);
+
+ pDevEnm->cDevices--;
+ }
+
+ /* Sanity. */
+ Assert(RTListIsEmpty(&pDevEnm->LstDevices));
+ Assert(pDevEnm->cDevices == 0);
+
+ pDevEnm->uMagic = ~PDMAUDIOHOSTENUM_MAGIC;
+ }
+}
+
+/**
+ * Adds an audio device to a device enumeration.
+ *
+ * @param pDevEnm Device enumeration to add device to.
+ * @param pDev Device to add. The pointer will be owned by the device enumeration then.
+ */
+DECLINLINE(void) PDMAudioHostEnumAppend(PPDMAUDIOHOSTENUM pDevEnm, PPDMAUDIOHOSTDEV pDev)
+{
+ AssertPtr(pDevEnm);
+ AssertPtr(pDev);
+ Assert(pDevEnm->uMagic == PDMAUDIOHOSTENUM_MAGIC);
+
+ RTListAppend(&pDevEnm->LstDevices, &pDev->ListEntry);
+ pDevEnm->cDevices++;
+}
+
+/**
+ * Appends copies of matching host device entries from one to another enumeration.
+ *
+ * @returns VBox status code.
+ * @param pDstDevEnm The target to append copies of matching device to.
+ * @param pSrcDevEnm The source to copy matching devices from.
+ * @param enmUsage The usage to match for copying.
+ * Use PDMAUDIODIR_INVALID to match all entries.
+ * @param fOnlyCoreData Set this to only copy the PDMAUDIOHOSTDEV part.
+ * Careful with passing @c false here as not all
+ * backends have data that can be copied.
+ */
+DECLINLINE(int) PDMAudioHostEnumCopy(PPDMAUDIOHOSTENUM pDstDevEnm, PCPDMAUDIOHOSTENUM pSrcDevEnm,
+ PDMAUDIODIR enmUsage, bool fOnlyCoreData)
+{
+ AssertPtrReturn(pDstDevEnm, VERR_INVALID_POINTER);
+ AssertReturn(pDstDevEnm->uMagic == PDMAUDIOHOSTENUM_MAGIC, VERR_WRONG_ORDER);
+
+ AssertPtrReturn(pSrcDevEnm, VERR_INVALID_POINTER);
+ AssertReturn(pSrcDevEnm->uMagic == PDMAUDIOHOSTENUM_MAGIC, VERR_WRONG_ORDER);
+
+ PPDMAUDIOHOSTDEV pSrcDev;
+ RTListForEach(&pSrcDevEnm->LstDevices, pSrcDev, PDMAUDIOHOSTDEV, ListEntry)
+ {
+ if ( enmUsage == pSrcDev->enmUsage
+ || enmUsage == PDMAUDIODIR_INVALID /*all*/)
+ {
+ PPDMAUDIOHOSTDEV pDstDev = PDMAudioHostDevDup(pSrcDev, fOnlyCoreData);
+ AssertReturn(pDstDev, VERR_NO_MEMORY);
+
+ PDMAudioHostEnumAppend(pDstDevEnm, pDstDev);
+ }
+ }
+
+ return VINF_SUCCESS;
+}
+
+/**
+ * Moves all the device entries from one enumeration to another, destroying the
+ * former.
+ *
+ * @returns VBox status code.
+ * @param pDstDevEnm The target to put move @a pSrcDevEnm to. This
+ * does not need to be initialized, but if it is it
+ * must not have any device entries.
+ * @param pSrcDevEnm The source to move from. This will be empty
+ * upon successful return.
+ */
+DECLINLINE(int) PDMAudioHostEnumMove(PPDMAUDIOHOSTENUM pDstDevEnm, PPDMAUDIOHOSTENUM pSrcDevEnm)
+{
+ AssertPtrReturn(pDstDevEnm, VERR_INVALID_POINTER);
+ AssertReturn(pDstDevEnm->uMagic != PDMAUDIOHOSTENUM_MAGIC || pDstDevEnm->cDevices == 0, VERR_WRONG_ORDER);
+
+ AssertPtrReturn(pSrcDevEnm, VERR_INVALID_POINTER);
+ AssertReturn(pSrcDevEnm->uMagic == PDMAUDIOHOSTENUM_MAGIC, VERR_WRONG_ORDER);
+
+ pDstDevEnm->uMagic = PDMAUDIOHOSTENUM_MAGIC;
+ RTListInit(&pDstDevEnm->LstDevices);
+ pDstDevEnm->cDevices = pSrcDevEnm->cDevices;
+ if (pSrcDevEnm->cDevices)
+ {
+ PPDMAUDIOHOSTDEV pCur;
+ while ((pCur = RTListRemoveFirst(&pSrcDevEnm->LstDevices, PDMAUDIOHOSTDEV, ListEntry)) != NULL)
+ RTListAppend(&pDstDevEnm->LstDevices, &pCur->ListEntry);
+ }
+ return VINF_SUCCESS;
+}
+
+/**
+ * Get the default device with the given usage.
+ *
+ * This assumes that only one default device per usage is set, if there should
+ * be more than one, the first one is returned.
+ *
+ * @returns Default device if found, or NULL if not.
+ * @param pDevEnm Device enumeration to get default device for.
+ * @param enmUsage Usage to get default device for.
+ * Pass PDMAUDIODIR_INVALID to get the first device with
+ * either PDMAUDIOHOSTDEV_F_DEFAULT_OUT or
+ * PDMAUDIOHOSTDEV_F_DEFAULT_IN set.
+ */
+DECLINLINE(PPDMAUDIOHOSTDEV) PDMAudioHostEnumGetDefault(PCPDMAUDIOHOSTENUM pDevEnm, PDMAUDIODIR enmUsage)
+{
+ AssertPtrReturn(pDevEnm, NULL);
+ AssertReturn(pDevEnm->uMagic == PDMAUDIOHOSTENUM_MAGIC, NULL);
+
+ Assert(enmUsage == PDMAUDIODIR_IN || enmUsage == PDMAUDIODIR_OUT || enmUsage == PDMAUDIODIR_INVALID);
+ uint32_t const fFlags = enmUsage == PDMAUDIODIR_IN ? PDMAUDIOHOSTDEV_F_DEFAULT_IN
+ : enmUsage == PDMAUDIODIR_OUT ? PDMAUDIOHOSTDEV_F_DEFAULT_OUT
+ : enmUsage == PDMAUDIODIR_INVALID ? PDMAUDIOHOSTDEV_F_DEFAULT_IN | PDMAUDIOHOSTDEV_F_DEFAULT_OUT
+ : 0;
+
+ PPDMAUDIOHOSTDEV pDev;
+ RTListForEach(&pDevEnm->LstDevices, pDev, PDMAUDIOHOSTDEV, ListEntry)
+ {
+ if (pDev->fFlags & fFlags)
+ {
+ Assert(pDev->enmUsage == enmUsage || pDev->enmUsage == PDMAUDIODIR_DUPLEX || enmUsage == PDMAUDIODIR_INVALID);
+ return pDev;
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ * Get the number of device with the given usage.
+ *
+ * @returns Number of matching devices.
+ * @param pDevEnm Device enumeration to get default device for.
+ * @param enmUsage Usage to count devices for.
+ * Pass PDMAUDIODIR_INVALID to get the total number of devices.
+ */
+DECLINLINE(uint32_t) PDMAudioHostEnumCountMatching(PCPDMAUDIOHOSTENUM pDevEnm, PDMAUDIODIR enmUsage)
+{
+ AssertPtrReturn(pDevEnm, 0);
+ AssertReturn(pDevEnm->uMagic == PDMAUDIOHOSTENUM_MAGIC, 0);
+
+ if (enmUsage == PDMAUDIODIR_INVALID)
+ return pDevEnm->cDevices;
+
+ uint32_t cDevs = 0;
+ PPDMAUDIOHOSTDEV pDev;
+ RTListForEach(&pDevEnm->LstDevices, pDev, PDMAUDIOHOSTDEV, ListEntry)
+ {
+ if (enmUsage == pDev->enmUsage)
+ cDevs++;
+ }
+
+ return cDevs;
+}
+
+/** The max string length for all PDMAUDIOHOSTDEV_F_XXX.
+ * @sa PDMAudioHostDevFlagsToString */
+#define PDMAUDIOHOSTDEV_MAX_FLAGS_STRING_LEN sizeof("DEFAULT_OUT DEFAULT_IN HOTPLUG BUGGY IGNORE LOCKED DEAD NAME_ALLOC ID_ALLOC NO_DUP ")
+
+/**
+ * Converts an audio device flags to a string.
+ *
+ * @returns
+ * @param pszDst Destination buffer with a size of at least
+ * PDMAUDIOHOSTDEV_MAX_FLAGS_STRING_LEN bytes (including
+ * the string terminator).
+ * @param fFlags Audio flags (PDMAUDIOHOSTDEV_F_XXX) to convert.
+ */
+DECLINLINE(const char *) PDMAudioHostDevFlagsToString(char pszDst[PDMAUDIOHOSTDEV_MAX_FLAGS_STRING_LEN], uint32_t fFlags)
+{
+ static const struct { const char *pszMnemonic; uint32_t cchMnemonic; uint32_t fFlag; } s_aFlags[] =
+ {
+ { RT_STR_TUPLE("DEFAULT_OUT "), PDMAUDIOHOSTDEV_F_DEFAULT_OUT },
+ { RT_STR_TUPLE("DEFAULT_IN "), PDMAUDIOHOSTDEV_F_DEFAULT_IN },
+ { RT_STR_TUPLE("HOTPLUG "), PDMAUDIOHOSTDEV_F_HOTPLUG },
+ { RT_STR_TUPLE("BUGGY "), PDMAUDIOHOSTDEV_F_BUGGY },
+ { RT_STR_TUPLE("IGNORE "), PDMAUDIOHOSTDEV_F_IGNORE },
+ { RT_STR_TUPLE("LOCKED "), PDMAUDIOHOSTDEV_F_LOCKED },
+ { RT_STR_TUPLE("DEAD "), PDMAUDIOHOSTDEV_F_DEAD },
+ { RT_STR_TUPLE("NAME_ALLOC "), PDMAUDIOHOSTDEV_F_NAME_ALLOC },
+ { RT_STR_TUPLE("ID_ALLOC "), PDMAUDIOHOSTDEV_F_ID_ALLOC },
+ { RT_STR_TUPLE("NO_DUP "), PDMAUDIOHOSTDEV_F_NO_DUP },
+ };
+ size_t offDst = 0;
+ for (uint32_t i = 0; i < RT_ELEMENTS(s_aFlags); i++)
+ if (fFlags & s_aFlags[i].fFlag)
+ {
+ fFlags &= ~s_aFlags[i].fFlag;
+ memcpy(&pszDst[offDst], s_aFlags[i].pszMnemonic, s_aFlags[i].cchMnemonic);
+ offDst += s_aFlags[i].cchMnemonic;
+ }
+ Assert(fFlags == 0);
+ Assert(offDst < PDMAUDIOHOSTDEV_MAX_FLAGS_STRING_LEN);
+
+ if (offDst)
+ pszDst[offDst - 1] = '\0';
+ else
+ memcpy(pszDst, "NONE", sizeof("NONE"));
+ return pszDst;
+}
+
+/**
+ * Logs an audio device enumeration.
+ *
+ * @param pDevEnm Device enumeration to log.
+ * @param pszDesc Logging description (prefix).
+ */
+DECLINLINE(void) PDMAudioHostEnumLog(PCPDMAUDIOHOSTENUM pDevEnm, const char *pszDesc)
+{
+#ifdef LOG_ENABLED
+ AssertPtrReturnVoid(pDevEnm);
+ AssertPtrReturnVoid(pszDesc);
+ AssertReturnVoid(pDevEnm->uMagic == PDMAUDIOHOSTENUM_MAGIC);
+
+ if (LogIsEnabled())
+ {
+ LogFunc(("%s: %RU32 devices\n", pszDesc, pDevEnm->cDevices));
+
+ PPDMAUDIOHOSTDEV pDev;
+ RTListForEach(&pDevEnm->LstDevices, pDev, PDMAUDIOHOSTDEV, ListEntry)
+ {
+ char szFlags[PDMAUDIOHOSTDEV_MAX_FLAGS_STRING_LEN];
+ LogFunc(("Device '%s':\n", pDev->pszName));
+ LogFunc((" ID = %s\n", pDev->pszId ? pDev->pszId : "<none>"));
+ LogFunc((" Usage = %s\n", PDMAudioDirGetName(pDev->enmUsage)));
+ LogFunc((" Flags = %s\n", PDMAudioHostDevFlagsToString(szFlags, pDev->fFlags)));
+ LogFunc((" Input channels = %RU8\n", pDev->cMaxInputChannels));
+ LogFunc((" Output channels = %RU8\n", pDev->cMaxOutputChannels));
+ LogFunc((" cbExtra = %RU32 bytes\n", pDev->cbSelf - sizeof(PDMAUDIOHOSTDEV)));
+ }
+ }
+#else
+ RT_NOREF(pDevEnm, pszDesc);
+#endif
+}
+
+/** @} */
+
+#endif /* !VBOX_INCLUDED_vmm_pdmaudiohostenuminline_h */
diff --git a/include/VBox/vmm/pdmaudioifs.h b/include/VBox/vmm/pdmaudioifs.h
new file mode 100644
index 00000000..11735f25
--- /dev/null
+++ b/include/VBox/vmm/pdmaudioifs.h
@@ -0,0 +1,1567 @@
+/** @file
+ * PDM - Pluggable Device Manager, Audio interfaces.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+/** @page pg_pdm_audio PDM Audio
+ *
+ * PDM provides audio device emulations and their driver chains with the
+ * interfaces they need to communicate with each other.
+ *
+ *
+ * @section sec_pdm_audio_overview Overview
+ *
+@startuml
+skinparam componentStyle rectangle
+
+node VM {
+ [Music Player App] --> [Guest Audio Driver]
+ [Recording App] <-- [Guest Audio Driver]
+}
+
+component "DevAudio (DevHda / DevIchAc97 / DevSB16)" as DevAudio {
+ [Output DMA Engine]
+ [Input DMA Engine]
+ () LUN0
+ () LUN1
+
+ component "AudioMixer" {
+ component "Output Sink" {
+ () "Output Stream #0" as DrvStreamOut0
+ () "Output Stream #1" as DrvStreamOut1
+ [Output Mixer Buffer] --> DrvStreamOut0
+ [Output Mixer Buffer] --> DrvStreamOut1
+ [Output DMA Engine] --> [Output Mixer Buffer]
+ DrvStreamOut0 --> LUN0
+ DrvStreamOut1 --> LUN1
+ }
+ component "Input Sink" {
+ () "Input Stream #2" as DrvStreamIn0
+ () "Input Stream #3" as DrvStreamIn1
+ [Input Mixer Buffer] <-- DrvStreamIn0
+ [Input Mixer Buffer] <-- DrvStreamIn1
+ [Input DMA Engine] --> [Input Mixer Buffer]
+ DrvStreamIn0 <-- LUN0
+ DrvStreamIn1 <-- LUN1
+ }
+ }
+}
+[Guest Audio Driver] <..> DevAudio : " MMIO or Port I/O, DMA"
+
+node "Driver Chain #0" {
+ component "DrvAudio#0" {
+ () PDMIHOSTAUDIOPORT0
+ () PDMIAUDIOCONNECTOR0
+ }
+ component "DrvHostAudioWasApi" {
+ () PDMIHOSTAUDIO0
+ }
+}
+PDMIHOSTAUDIOPORT0 <--> PDMIHOSTAUDIO0
+
+node "Driver Chain #1" {
+ component "DrvAudio#1" {
+ () PDMIAUDIOCONNECTOR1
+ () PDMIHOSTAUDIOPORT1
+ }
+ component "DrvAudioVRDE" {
+ () PDMIHOSTAUDIO1
+ }
+}
+note bottom of DrvAudioVRDE
+ The backend driver is sometimes not configured if the component it represents
+ is not configured for the VM. However, Main will still set up the LUN but
+ with just DrvAudio attached to simplify runtime activation of the component.
+ In the meanwhile, the DrvAudio instance works as if DrvHostAudioNull were attached.
+end note
+
+LUN1 <--> PDMIAUDIOCONNECTOR1
+LUN0 <--> PDMIAUDIOCONNECTOR0
+
+PDMIHOSTAUDIOPORT1 <--> PDMIHOSTAUDIO1
+
+@enduml
+ *
+ * Actors:
+ * - An audio device implementation: "DevAudio"
+ * - Mixer instance (AudioMixer.cpp) with one or more mixer
+ * sinks: "Output Sink", "Input Sink"
+ * - One DMA engine teamed up with each mixer sink: "Output DMA
+ * Engine", "Input DMA Engine"
+ * - The audio driver "DrvAudio" instances attached to LUN0 and LUN1
+ * respectively: "DrvAudio#0", "DrvAudio#1"
+ * - The Windows host audio driver attached to "DrvAudio0": "DrvHostAudioWas"
+ * - The VRDE/VRDP host audio driver attached to "DrvAudio1": "DrvAudioVRDE"
+ *
+ * Both "Output Sink" and "Input Sink" talks to all the attached driver chains
+ * ("DrvAudio #0" and "DrvAudio #1"), but using different PDMAUDIOSTREAM
+ * instances. There can be an arbritrary number of driver chains attached to an
+ * audio device, the mixer sinks will multiplex output to each of them and blend
+ * input from all of them, taking care of format and rate conversions. The
+ * mixer and mixer sinks does not fit into the PDM device/driver model, because
+ * a driver can only have exactly one or zero other drivers attached, so it is
+ * implemented as a separate component that all the audio devices share (see
+ * AudioMixer.h, AudioMixer.cpp, AudioMixBuffer.h and AudioMixBuffer.cpp).
+ *
+ * The driver chains attached to LUN0, LUN1, ... LUNn typically have two
+ * drivers attached, first DrvAudio and then a backend driver like
+ * DrvHostAudioWasApi, DrvHostAudioPulseAudio, or DrvAudioVRDE. DrvAudio
+ * exposes PDMIAUDIOCONNECTOR upwards towards the device and mixer component,
+ * and PDMIHOSTAUDIOPORT downwards towards DrvHostAudioWasApi and the other
+ * backends.
+ *
+ * The backend exposes the PDMIHOSTAUDIO upwards towards DrvAudio. It is
+ * possible, though, to only have the DrvAudio instance and not backend, in
+ * which case DrvAudio works as if the NULL backend was attached. Main does
+ * such setups when the main component we're interfacing with isn't currently
+ * active, as this simplifies runtime activation.
+ *
+ * The purpose of DrvAudio is to make the work of the backend as simple as
+ * possible and try avoid needing to write the same code over and over again for
+ * each backend. It takes care of:
+ * - Stream creation, operation, re-initialization and destruction.
+ * - Pre-buffering.
+ * - Thread pool.
+ *
+ * The purpose of a host audio driver (aka backend) is to interface with the
+ * host audio system (or other audio systems like VRDP and video recording).
+ * The backend will optionally provide a list of host audio devices, switch
+ * between them, and monitor changes to them. By default our host backends use
+ * the default host device and will trigger stream re-initialization if this
+ * changes while we're using it.
+ *
+ *
+ * @section sec_pdm_audio_device Virtual Audio Device
+ *
+ * The virtual device translates the settings of the emulated device into mixing
+ * sinks with sample format, sample rate, volume control, and whatnot.
+ *
+ * It also implements a DMA engine for transfering samples to (input) or from
+ * (output) the guest memory. The starting and stopping of the DMA engines are
+ * communicated to the associated mixing sinks and by then onto the
+ * PDMAUDIOSTREAM instance for each driver chain. A RTCIRCBUF is used as an
+ * intermediary between the DMA engine and the asynchronous worker thread of the
+ * mixing sink.
+ *
+ *
+ * @section sec_pdm_audio_mixing Audio Mixing
+ *
+ * The audio mixer is a mandatory component in an audio device. It consists of
+ * a mixer and one or more sinks with mixer buffers. The sinks are typically
+ * one per virtual output/input connector, so for instance you could have a
+ * device with a "PCM Output" sink and a "PCM Input" sink.
+ *
+ * The audio mixer takes care of:
+ * - Much of the driver chain (LUN) management work.
+ * - Multiplexing output to each active driver chain.
+ * - Blending input from each active driver chain into a single audio
+ * stream.
+ * - Do format conversion (it uses signed 32-bit PCM internally) between
+ * the audio device and all of the LUNs (no common format needed).
+ * - Do sample rate conversions between the device rate and that of the
+ * individual driver chains.
+ * - Apply the volume settings of the device to the audio stream.
+ * - Provide the asynchronous thread that pushes data from the device's
+ * internal DMA buffer and all the way to the backend for output sinks,
+ * and vice versa for input.
+ *
+ * The term active LUNs above means that not all LUNs will actually produce
+ * (input) or consume (output) audio. The mixer checks the return of
+ * PDMIHOSTAUDIO::pfnStreamGetState each time it's processing samples to see
+ * which streams are currently active and which aren't. Inactive streams are
+ * ignored.
+ *
+ * For more info: @ref pg_audio_mixer, @ref pg_audio_mixing_buffers
+ *
+ * The AudioMixer API reference can be found here:
+ * - @ref grp_pdm_ifs_audio_mixing
+ * - @ref grp_pdm_ifs_audio_mixing_buffers
+ *
+ *
+ * @section sec_pdm_audio_timing Timing
+ *
+ * Handling audio data in a virtual environment is hard, as the human perception
+ * is very sensitive to the slightest cracks and stutters in the audible data,
+ * and the task of playing back and recording audio is in the real-time domain.
+ *
+ * The virtual machine is not executed with any real-time guarentees, only best
+ * effort, mainly because it is subject to preemptive scheduling on the host
+ * side. The audio processing done on the guest side is typically also subject
+ * to preemptive scheduling on the guest side and available CPU processing power
+ * there.
+ *
+ * Thus, the guest may be lagging behind because the host prioritizes other
+ * processes/threads over the virtual machine. This will, if it's too servere,
+ * cause the virtual machine to speed up it's time sense while it's trying to
+ * catch up. So, we can easily have a bit of a seesaw execution going on here,
+ * where in the playback case, the guest produces data too slowly for while and
+ * then switches to producing it too quickly for a while to catch up.
+ *
+ * Our working principle is that the backends and the guest are producing and
+ * consuming samples at the same rate, but we have to deal with the uneven
+ * execution.
+ *
+ * To deal with this we employ (by default) 300ms of backend buffer and
+ * pre-buffer 150ms of that for both input and output audio streams. This means
+ * we have about 150ms worth of samples to feed to the host audio device should
+ * the virtual machine be starving and lagging behind. Likewise, we have about
+ * 150ms of buffer space will can fill when the VM is in a catch-up mode. Now,
+ * 300ms and 150 ms isn't much for the purpose of glossing over
+ * scheduling/timing differences here, but we can't do too much more or the lag
+ * will grow rather annoying. The pre-buffering is implemented by DrvAudio.
+ *
+ * In addition to the backend buffer that defaults to 300ms, we have the
+ * internal DMA buffer of the device and the mixing buffer of the mixing sink.
+ * The latter two are typically rather small, sized to fit the anticipated DMA
+ * period currently in use by the guest.
+ */
+
+#ifndef VBOX_INCLUDED_vmm_pdmaudioifs_h
+#define VBOX_INCLUDED_vmm_pdmaudioifs_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/assertcompile.h>
+#include <iprt/critsect.h>
+#include <iprt/circbuf.h>
+#include <iprt/list.h>
+#include <iprt/path.h>
+
+#include <VBox/types.h>
+#include <VBox/vmm/pdmcommon.h>
+#include <VBox/vmm/stam.h>
+
+RT_C_DECLS_BEGIN
+
+
+/** @defgroup grp_pdm_ifs_audio PDM Audio Interfaces
+ * @ingroup grp_pdm_interfaces
+ * @{
+ */
+
+/** The maximum number of channels PDM supports. */
+#define PDMAUDIO_MAX_CHANNELS 12
+
+/**
+ * Audio direction.
+ */
+typedef enum PDMAUDIODIR
+{
+ /** Invalid zero value as per usual (guards against using unintialized values). */
+ PDMAUDIODIR_INVALID = 0,
+ /** Unknown direction. */
+ PDMAUDIODIR_UNKNOWN,
+ /** Input. */
+ PDMAUDIODIR_IN,
+ /** Output. */
+ PDMAUDIODIR_OUT,
+ /** Duplex handling. */
+ PDMAUDIODIR_DUPLEX,
+ /** End of valid values. */
+ PDMAUDIODIR_END,
+ /** Hack to blow the type up to 32-bit. */
+ PDMAUDIODIR_32BIT_HACK = 0x7fffffff
+} PDMAUDIODIR;
+
+
+/** @name PDMAUDIOHOSTDEV_F_XXX
+ * @{ */
+/** No flags set. */
+#define PDMAUDIOHOSTDEV_F_NONE UINT32_C(0)
+/** The default input (capture/recording) device (for the user). */
+#define PDMAUDIOHOSTDEV_F_DEFAULT_IN RT_BIT_32(0)
+/** The default output (playback) device (for the user). */
+#define PDMAUDIOHOSTDEV_F_DEFAULT_OUT RT_BIT_32(1)
+/** The device can be removed at any time and we have to deal with it. */
+#define PDMAUDIOHOSTDEV_F_HOTPLUG RT_BIT_32(2)
+/** The device is known to be buggy and needs special treatment. */
+#define PDMAUDIOHOSTDEV_F_BUGGY RT_BIT_32(3)
+/** Ignore the device, no matter what. */
+#define PDMAUDIOHOSTDEV_F_IGNORE RT_BIT_32(4)
+/** The device is present but marked as locked by some other application. */
+#define PDMAUDIOHOSTDEV_F_LOCKED RT_BIT_32(5)
+/** The device is present but not in an alive state (dead). */
+#define PDMAUDIOHOSTDEV_F_DEAD RT_BIT_32(6)
+/** Set if the PDMAUDIOHOSTDEV::pszName is allocated. */
+#define PDMAUDIOHOSTDEV_F_NAME_ALLOC RT_BIT_32(29)
+/** Set if the PDMAUDIOHOSTDEV::pszId is allocated. */
+#define PDMAUDIOHOSTDEV_F_ID_ALLOC RT_BIT_32(30)
+/** Set if the extra backend specific data cannot be duplicated. */
+#define PDMAUDIOHOSTDEV_F_NO_DUP RT_BIT_32(31)
+/** @} */
+
+/**
+ * Audio device type.
+ */
+typedef enum PDMAUDIODEVICETYPE
+{
+ /** Invalid zero value as per usual (guards against using unintialized values). */
+ PDMAUDIODEVICETYPE_INVALID = 0,
+ /** Unknown device type. This is the default. */
+ PDMAUDIODEVICETYPE_UNKNOWN,
+ /** Dummy device; for backends which are not able to report
+ * actual device information (yet). */
+ PDMAUDIODEVICETYPE_DUMMY,
+ /** The device is built into the host (non-removable). */
+ PDMAUDIODEVICETYPE_BUILTIN,
+ /** The device is an (external) USB device. */
+ PDMAUDIODEVICETYPE_USB,
+ /** End of valid values. */
+ PDMAUDIODEVICETYPE_END,
+ /** Hack to blow the type up to 32-bit. */
+ PDMAUDIODEVICETYPE_32BIT_HACK = 0x7fffffff
+} PDMAUDIODEVICETYPE;
+
+/**
+ * Host audio device info, part of enumeration result.
+ *
+ * @sa PDMAUDIOHOSTENUM, PDMIHOSTAUDIO::pfnGetDevices
+ */
+typedef struct PDMAUDIOHOSTDEV
+{
+ /** List entry (like PDMAUDIOHOSTENUM::LstDevices). */
+ RTLISTNODE ListEntry;
+ /** Magic value (PDMAUDIOHOSTDEV_MAGIC). */
+ uint32_t uMagic;
+ /** Size of this structure and whatever backend specific data that follows it. */
+ uint32_t cbSelf;
+ /** The device type. */
+ PDMAUDIODEVICETYPE enmType;
+ /** Usage of the device. */
+ PDMAUDIODIR enmUsage;
+ /** Device flags, PDMAUDIOHOSTDEV_F_XXX. */
+ uint32_t fFlags;
+ /** Maximum number of input audio channels the device supports. */
+ uint8_t cMaxInputChannels;
+ /** Maximum number of output audio channels the device supports. */
+ uint8_t cMaxOutputChannels;
+ uint8_t abAlignment[ARCH_BITS == 32 ? 2 + 8 : 2 + 8];
+ /** Backend specific device identifier, can be NULL, used to select device.
+ * This can either point into some non-public part of this structure or to a
+ * RTStrAlloc allocation. PDMAUDIOHOSTDEV_F_ID_ALLOC is set in the latter
+ * case.
+ * @sa PDMIHOSTAUDIO::pfnSetDevice */
+ char *pszId;
+ /** The friendly device name. */
+ char *pszName;
+} PDMAUDIOHOSTDEV;
+AssertCompileSizeAlignment(PDMAUDIOHOSTDEV, 16);
+/** Pointer to audio device info (enumeration result). */
+typedef PDMAUDIOHOSTDEV *PPDMAUDIOHOSTDEV;
+/** Pointer to a const audio device info (enumeration result). */
+typedef PDMAUDIOHOSTDEV const *PCPDMAUDIOHOSTDEV;
+
+/** Magic value for PDMAUDIOHOSTDEV. */
+#define PDMAUDIOHOSTDEV_MAGIC PDM_VERSION_MAKE(0xa0d0, 3, 0)
+
+
+/**
+ * A host audio device enumeration result.
+ *
+ * @sa PDMIHOSTAUDIO::pfnGetDevices
+ */
+typedef struct PDMAUDIOHOSTENUM
+{
+ /** Magic value (PDMAUDIOHOSTENUM_MAGIC). */
+ uint32_t uMagic;
+ /** Number of audio devices in the list. */
+ uint32_t cDevices;
+ /** List of audio devices (PDMAUDIOHOSTDEV). */
+ RTLISTANCHOR LstDevices;
+} PDMAUDIOHOSTENUM;
+/** Pointer to an audio device enumeration result. */
+typedef PDMAUDIOHOSTENUM *PPDMAUDIOHOSTENUM;
+/** Pointer to a const audio device enumeration result. */
+typedef PDMAUDIOHOSTENUM const *PCPDMAUDIOHOSTENUM;
+
+/** Magic for the host audio device enumeration. */
+#define PDMAUDIOHOSTENUM_MAGIC PDM_VERSION_MAKE(0xa0d1, 1, 0)
+
+
+/**
+ * Audio configuration (static) of an audio host backend.
+ */
+typedef struct PDMAUDIOBACKENDCFG
+{
+ /** The backend's friendly name. */
+ char szName[32];
+ /** The size of the backend specific stream data (in bytes). */
+ uint32_t cbStream;
+ /** PDMAUDIOBACKEND_F_XXX. */
+ uint32_t fFlags;
+ /** Number of concurrent output (playback) streams supported on the host.
+ * UINT32_MAX for unlimited concurrent streams, 0 if no concurrent input streams are supported. */
+ uint32_t cMaxStreamsOut;
+ /** Number of concurrent input (recording) streams supported on the host.
+ * UINT32_MAX for unlimited concurrent streams, 0 if no concurrent input streams are supported. */
+ uint32_t cMaxStreamsIn;
+} PDMAUDIOBACKENDCFG;
+/** Pointer to a static host audio audio configuration. */
+typedef PDMAUDIOBACKENDCFG *PPDMAUDIOBACKENDCFG;
+
+/** @name PDMAUDIOBACKEND_F_XXX - PDMAUDIOBACKENDCFG::fFlags
+ * @{ */
+/** PDMIHOSTAUDIO::pfnStreamConfigHint should preferably be called on a
+ * worker thread rather than EMT as it may take a good while. */
+#define PDMAUDIOBACKEND_F_ASYNC_HINT RT_BIT_32(0)
+/** PDMIHOSTAUDIO::pfnStreamDestroy and any preceeding
+ * PDMIHOSTAUDIO::pfnStreamControl/DISABLE should be preferably be called on a
+ * worker thread rather than EMT as it may take a good while. */
+#define PDMAUDIOBACKEND_F_ASYNC_STREAM_DESTROY RT_BIT_32(1)
+/** @} */
+
+
+/**
+ * Audio path: input sources and playback destinations.
+ *
+ * Think of this as the name of the socket you plug the virtual audio stream
+ * jack into.
+ *
+ * @note Not quite sure what the purpose of this type is. It used to be two
+ * separate enums (PDMAUDIOPLAYBACKDST & PDMAUDIORECSRC) without overlapping
+ * values and most commonly used in a union (PDMAUDIODSTSRCUNION). The output
+ * values were designated "channel" (e.g. "Front channel"), whereas this was not
+ * done to the input ones. So, I'm (bird) a little confused what the actual
+ * meaning was.
+ */
+typedef enum PDMAUDIOPATH
+{
+ /** Customary invalid zero value. */
+ PDMAUDIOPATH_INVALID = 0,
+
+ /** Unknown path / Doesn't care. */
+ PDMAUDIOPATH_UNKNOWN,
+
+ /** First output value. */
+ PDMAUDIOPATH_OUT_FIRST,
+ /** Output: Front. */
+ PDMAUDIOPATH_OUT_FRONT = PDMAUDIOPATH_OUT_FIRST,
+ /** Output: Center / LFE (Subwoofer). */
+ PDMAUDIOPATH_OUT_CENTER_LFE,
+ /** Output: Rear. */
+ PDMAUDIOPATH_OUT_REAR,
+ /** Last output value (inclusive) */
+ PDMAUDIOPATH_OUT_END = PDMAUDIOPATH_OUT_REAR,
+
+ /** First input value. */
+ PDMAUDIOPATH_IN_FIRST,
+ /** Input: Microphone. */
+ PDMAUDIOPATH_IN_MIC = PDMAUDIOPATH_IN_FIRST,
+ /** Input: CD. */
+ PDMAUDIOPATH_IN_CD,
+ /** Input: Video-In. */
+ PDMAUDIOPATH_IN_VIDEO,
+ /** Input: AUX. */
+ PDMAUDIOPATH_IN_AUX,
+ /** Input: Line-In. */
+ PDMAUDIOPATH_IN_LINE,
+ /** Input: Phone-In. */
+ PDMAUDIOPATH_IN_PHONE,
+ /** Last intput value (inclusive). */
+ PDMAUDIOPATH_IN_LAST = PDMAUDIOPATH_IN_PHONE,
+
+ /** End of valid values. */
+ PDMAUDIOPATH_END,
+ /** Hack to blow the typ up to 32 bits. */
+ PDMAUDIOPATH_32BIT_HACK = 0x7fffffff
+} PDMAUDIOPATH;
+
+
+/**
+ * Standard speaker channel IDs.
+ */
+typedef enum PDMAUDIOCHANNELID
+{
+ /** Invalid zero value as per usual (guards against using unintialized values). */
+ PDMAUDIOCHANNELID_INVALID = 0,
+
+ /** Unused channel - fill with zero when encoding, ignore when decoding. */
+ PDMAUDIOCHANNELID_UNUSED_ZERO,
+ /** Unused channel - fill with silence when encoding, ignore when decoding. */
+ PDMAUDIOCHANNELID_UNUSED_SILENCE,
+
+ /** Unknown channel ID (unable to map to PDM terms). */
+ PDMAUDIOCHANNELID_UNKNOWN,
+
+ /** The first ID in the standard WAV-file assignment block. */
+ PDMAUDIOCHANNELID_FIRST_STANDARD,
+ /** Front left channel (FR). */
+ PDMAUDIOCHANNELID_FRONT_LEFT = PDMAUDIOCHANNELID_FIRST_STANDARD,
+ /** Front right channel (FR). */
+ PDMAUDIOCHANNELID_FRONT_RIGHT,
+ /** Front center channel (FC). */
+ PDMAUDIOCHANNELID_FRONT_CENTER,
+ /** Mono channel (alias for front center). */
+ PDMAUDIOCHANNELID_MONO = PDMAUDIOCHANNELID_FRONT_CENTER,
+ /** Low frequency effects (subwoofer) channel. */
+ PDMAUDIOCHANNELID_LFE,
+ /** Rear left channel (BL). */
+ PDMAUDIOCHANNELID_REAR_LEFT,
+ /** Rear right channel (BR). */
+ PDMAUDIOCHANNELID_REAR_RIGHT,
+ /** Front left of center channel (FLC). */
+ PDMAUDIOCHANNELID_FRONT_LEFT_OF_CENTER,
+ /** Front right of center channel (FLR). */
+ PDMAUDIOCHANNELID_FRONT_RIGHT_OF_CENTER,
+ /** Rear center channel (BC). */
+ PDMAUDIOCHANNELID_REAR_CENTER,
+ /** Side left channel (SL). */
+ PDMAUDIOCHANNELID_SIDE_LEFT,
+ /** Side right channel (SR). */
+ PDMAUDIOCHANNELID_SIDE_RIGHT,
+ /** Top center (TC). */
+ PDMAUDIOCHANNELID_TOP_CENTER,
+ /** Front left height channel (TFL). */
+ PDMAUDIOCHANNELID_FRONT_LEFT_HEIGHT,
+ /** Front center height channel (TFC). */
+ PDMAUDIOCHANNELID_FRONT_CENTER_HEIGHT,
+ /** Front right height channel (TFR). */
+ PDMAUDIOCHANNELID_FRONT_RIGHT_HEIGHT,
+ /** Rear left height channel (TBL). */
+ PDMAUDIOCHANNELID_REAR_LEFT_HEIGHT,
+ /** Rear center height channel (TBC). */
+ PDMAUDIOCHANNELID_REAR_CENTER_HEIGHT,
+ /** Rear right height channel (TBR). */
+ PDMAUDIOCHANNELID_REAR_RIGHT_HEIGHT,
+ /** The end of the standard WAV-file assignment block. */
+ PDMAUDIOCHANNELID_END_STANDARD,
+
+ /** End of valid values. */
+ PDMAUDIOCHANNELID_END = PDMAUDIOCHANNELID_END_STANDARD,
+ /** Hack to blow the type up to 32-bit. */
+ PDMAUDIOCHANNELID_32BIT_HACK = 0x7fffffff
+} PDMAUDIOCHANNELID;
+AssertCompile(PDMAUDIOCHANNELID_FRONT_LEFT - PDMAUDIOCHANNELID_FIRST_STANDARD == 0);
+AssertCompile(PDMAUDIOCHANNELID_LFE - PDMAUDIOCHANNELID_FIRST_STANDARD == 3);
+AssertCompile(PDMAUDIOCHANNELID_REAR_CENTER - PDMAUDIOCHANNELID_FIRST_STANDARD == 8);
+AssertCompile(PDMAUDIOCHANNELID_REAR_RIGHT_HEIGHT - PDMAUDIOCHANNELID_FIRST_STANDARD == 17);
+
+
+/**
+ * Properties of audio streams for host/guest for in or out directions.
+ */
+typedef struct PDMAUDIOPCMPROPS
+{
+ /** The frame size. */
+ uint8_t cbFrame;
+ /** Shift count used with PDMAUDIOPCMPROPS_F2B and PDMAUDIOPCMPROPS_B2F.
+ * Depends on number of stream channels and the stream format being used, calc
+ * value using PDMAUDIOPCMPROPS_MAKE_SHIFT.
+ * @sa PDMAUDIOSTREAMCFG_B2F, PDMAUDIOSTREAMCFG_F2B */
+ uint8_t cShiftX;
+ /** Sample width (in bytes). */
+ RT_GCC_EXTENSION
+ uint8_t cbSampleX : 4;
+ /** Number of audio channels. */
+ RT_GCC_EXTENSION
+ uint8_t cChannelsX : 4;
+ /** Signed or unsigned sample. */
+ bool fSigned : 1;
+ /** Whether the endianness is swapped or not. */
+ bool fSwapEndian : 1;
+ /** Raw mixer frames, only applicable for signed 64-bit samples.
+ * The raw mixer samples are really just signed 32-bit samples stored as 64-bit
+ * integers without any change in the value.
+ *
+ * @todo Get rid of this, only VRDE needs it an it should use the common
+ * mixer code rather than cooking its own stuff. */
+ bool fRaw : 1;
+ /** Sample frequency in Hertz (Hz). */
+ uint32_t uHz;
+ /** PDMAUDIOCHANNELID mappings for each channel.
+ * This ASSUMES all channels uses the same sample size. */
+ uint8_t aidChannels[PDMAUDIO_MAX_CHANNELS];
+ /** Padding the structure up to 32 bytes. */
+ uint32_t auPadding[3];
+} PDMAUDIOPCMPROPS;
+AssertCompileSize(PDMAUDIOPCMPROPS, 32);
+AssertCompileSizeAlignment(PDMAUDIOPCMPROPS, 8);
+/** Pointer to audio stream properties. */
+typedef PDMAUDIOPCMPROPS *PPDMAUDIOPCMPROPS;
+/** Pointer to const audio stream properties. */
+typedef PDMAUDIOPCMPROPS const *PCPDMAUDIOPCMPROPS;
+
+/** @name Macros for use with PDMAUDIOPCMPROPS
+ * @{ */
+/** Initializer for PDMAUDIOPCMPROPS.
+ * @note The default channel mapping here is very simple and doesn't always
+ * match that of PDMAudioPropsInit and PDMAudioPropsInitEx. */
+#define PDMAUDIOPCMPROPS_INITIALIZER(a_cbSample, a_fSigned, a_cChannels, a_uHz, a_fSwapEndian) \
+ { \
+ (uint8_t)((a_cbSample) * (a_cChannels)), PDMAUDIOPCMPROPS_MAKE_SHIFT_PARMS(a_cbSample, a_cChannels), \
+ (uint8_t)(a_cbSample), (uint8_t)(a_cChannels), a_fSigned, a_fSwapEndian, false /*fRaw*/, a_uHz, \
+ /*aidChannels =*/ { \
+ (a_cChannels) > 1 ? PDMAUDIOCHANNELID_FRONT_LEFT : PDMAUDIOCHANNELID_MONO, \
+ (a_cChannels) >= 2 ? PDMAUDIOCHANNELID_FRONT_RIGHT : PDMAUDIOCHANNELID_INVALID, \
+ (a_cChannels) >= 3 ? PDMAUDIOCHANNELID_FRONT_CENTER : PDMAUDIOCHANNELID_INVALID, \
+ (a_cChannels) >= 4 ? PDMAUDIOCHANNELID_LFE : PDMAUDIOCHANNELID_INVALID, \
+ (a_cChannels) >= 5 ? PDMAUDIOCHANNELID_REAR_LEFT : PDMAUDIOCHANNELID_INVALID, \
+ (a_cChannels) >= 6 ? PDMAUDIOCHANNELID_REAR_RIGHT : PDMAUDIOCHANNELID_INVALID, \
+ (a_cChannels) >= 7 ? PDMAUDIOCHANNELID_FRONT_LEFT_OF_CENTER : PDMAUDIOCHANNELID_INVALID, \
+ (a_cChannels) >= 8 ? PDMAUDIOCHANNELID_FRONT_RIGHT_OF_CENTER : PDMAUDIOCHANNELID_INVALID, \
+ (a_cChannels) >= 9 ? PDMAUDIOCHANNELID_REAR_CENTER : PDMAUDIOCHANNELID_INVALID, \
+ (a_cChannels) >= 10 ? PDMAUDIOCHANNELID_SIDE_LEFT : PDMAUDIOCHANNELID_INVALID, \
+ (a_cChannels) >= 11 ? PDMAUDIOCHANNELID_SIDE_RIGHT : PDMAUDIOCHANNELID_INVALID, \
+ (a_cChannels) >= 12 ? PDMAUDIOCHANNELID_UNKNOWN : PDMAUDIOCHANNELID_INVALID, \
+ }, \
+ /* auPadding = */ { 0, 0, 0 } \
+ }
+
+/** Calculates the cShift value of given sample bits and audio channels.
+ * @note Does only support mono/stereo channels for now, for non-stereo/mono we
+ * returns a special value which the two conversion functions detect
+ * and make them fall back on cbSample * cChannels. */
+#define PDMAUDIOPCMPROPS_MAKE_SHIFT_PARMS(cbSample, cChannels) \
+ ( RT_IS_POWER_OF_TWO((unsigned)((cChannels) * (cbSample))) \
+ ? (uint8_t)(ASMBitFirstSetU32((unsigned)((cChannels) * (cbSample))) - 1) : (uint8_t)UINT8_MAX )
+/** Calculates the cShift value of a PDMAUDIOPCMPROPS structure. */
+#define PDMAUDIOPCMPROPS_MAKE_SHIFT(pProps) \
+ PDMAUDIOPCMPROPS_MAKE_SHIFT_PARMS((pProps)->cbSampleX, (pProps)->cChannelsX)
+/** Converts (audio) frames to bytes.
+ * @note Requires properly initialized properties, i.e. cbFrames correctly calculated
+ * and cShift set using PDMAUDIOPCMPROPS_MAKE_SHIFT. */
+#define PDMAUDIOPCMPROPS_F2B(pProps, cFrames) \
+ ( (pProps)->cShiftX != UINT8_MAX ? (cFrames) << (pProps)->cShiftX : (cFrames) * (pProps)->cbFrame )
+/** Converts bytes to (audio) frames.
+ * @note Requires properly initialized properties, i.e. cbFrames correctly calculated
+ * and cShift set using PDMAUDIOPCMPROPS_MAKE_SHIFT. */
+#define PDMAUDIOPCMPROPS_B2F(pProps, cb) \
+ ( (pProps)->cShiftX != UINT8_MAX ? (cb) >> (pProps)->cShiftX : (cb) / (pProps)->cbFrame )
+/** @} */
+
+/**
+ * An audio stream configuration.
+ */
+typedef struct PDMAUDIOSTREAMCFG
+{
+ /** The stream's PCM properties. */
+ PDMAUDIOPCMPROPS Props;
+ /** Direction of the stream. */
+ PDMAUDIODIR enmDir;
+ /** Destination / source path. */
+ PDMAUDIOPATH enmPath;
+ /** Device emulation-specific data needed for the audio connector. */
+ struct
+ {
+ /** Scheduling hint set by the device emulation about when this stream is being served on average (in ms).
+ * Can be 0 if not hint given or some other mechanism (e.g. callbacks) is being used. */
+ uint32_t cMsSchedulingHint;
+ } Device;
+ /**
+ * Backend-specific data for the stream.
+ * On input (requested configuration) those values are set by the audio connector to let the backend know what we expect.
+ * On output (acquired configuration) those values reflect the values set and used by the backend.
+ * Set by the backend on return. Not all backends support all values / features.
+ */
+ struct
+ {
+ /** Period size of the stream (in audio frames).
+ * This value reflects the number of audio frames in between each hardware interrupt on the
+ * backend (host) side. 0 if not set / available by the backend. */
+ uint32_t cFramesPeriod;
+ /** (Ring) buffer size (in audio frames). Often is a multiple of cFramesPeriod.
+ * 0 if not set / available by the backend. */
+ uint32_t cFramesBufferSize;
+ /** Pre-buffering size (in audio frames). Frames needed in buffer before the stream becomes active (pre buffering).
+ * The bigger this value is, the more latency for the stream will occur.
+ * 0 if not set / available by the backend. UINT32_MAX if not defined (yet). */
+ uint32_t cFramesPreBuffering;
+ } Backend;
+ /** Friendly name of the stream. */
+ char szName[64];
+} PDMAUDIOSTREAMCFG;
+AssertCompileSizeAlignment(PDMAUDIOSTREAMCFG, 8);
+/** Pointer to audio stream configuration keeper. */
+typedef PDMAUDIOSTREAMCFG *PPDMAUDIOSTREAMCFG;
+/** Pointer to a const audio stream configuration keeper. */
+typedef PDMAUDIOSTREAMCFG const *PCPDMAUDIOSTREAMCFG;
+
+/** Converts (audio) frames to bytes. */
+#define PDMAUDIOSTREAMCFG_F2B(pCfg, frames) PDMAUDIOPCMPROPS_F2B(&(pCfg)->Props, (frames))
+/** Converts bytes to (audio) frames. */
+#define PDMAUDIOSTREAMCFG_B2F(pCfg, cb) PDMAUDIOPCMPROPS_B2F(&(pCfg)->Props, (cb))
+
+/**
+ * Audio stream commands.
+ *
+ * Used in the audio connector as well as in the actual host backends.
+ */
+typedef enum PDMAUDIOSTREAMCMD
+{
+ /** Invalid zero value as per usual (guards against using unintialized values). */
+ PDMAUDIOSTREAMCMD_INVALID = 0,
+ /** Enables the stream. */
+ PDMAUDIOSTREAMCMD_ENABLE,
+ /** Pauses the stream.
+ * This is currently only issued when the VM is suspended (paused).
+ * @remarks This is issued by DrvAudio, never by the mixer or devices. */
+ PDMAUDIOSTREAMCMD_PAUSE,
+ /** Resumes the stream.
+ * This is currently only issued when the VM is resumed.
+ * @remarks This is issued by DrvAudio, never by the mixer or devices. */
+ PDMAUDIOSTREAMCMD_RESUME,
+ /** Drain the stream, that is, play what's in the buffers and then stop.
+ *
+ * There will be no more samples written after this command is issued.
+ * PDMIAUDIOCONNECTOR::pfnStreamIterate will drive progress for DrvAudio and
+ * calls to PDMIHOSTAUDIO::pfnStreamPlay with a zero sized buffer will provide
+ * the backend with a way to drive it forwards. These calls will come at a
+ * frequency set by the device and be on an asynchronous I/O thread.
+ *
+ * A DISABLE command maybe submitted if the device/mixer wants to re-enable the
+ * stream while it's still draining or if it gets impatient and thinks the
+ * draining has been going on too long, in which case the stream should stop
+ * immediately.
+ *
+ * @note This should not wait for the stream to finish draining, just change
+ * the state. (The caller could be an EMT and it must not block for
+ * hundreds of milliseconds of buffer to finish draining.)
+ *
+ * @note Does not apply to input streams. Backends should refuse such requests. */
+ PDMAUDIOSTREAMCMD_DRAIN,
+ /** Stops the stream immediately w/o any draining. */
+ PDMAUDIOSTREAMCMD_DISABLE,
+ /** End of valid values. */
+ PDMAUDIOSTREAMCMD_END,
+ /** Hack to blow the type up to 32-bit. */
+ PDMAUDIOSTREAMCMD_32BIT_HACK = 0x7fffffff
+} PDMAUDIOSTREAMCMD;
+
+/**
+ * Backend status.
+ */
+typedef enum PDMAUDIOBACKENDSTS
+{
+ /** Unknown/invalid status. */
+ PDMAUDIOBACKENDSTS_UNKNOWN = 0,
+ /** No backend attached. */
+ PDMAUDIOBACKENDSTS_NOT_ATTACHED,
+ /** The backend is in its initialization phase.
+ * Not all backends support this status. */
+ PDMAUDIOBACKENDSTS_INITIALIZING,
+ /** The backend has stopped its operation. */
+ PDMAUDIOBACKENDSTS_STOPPED,
+ /** The backend is up and running. */
+ PDMAUDIOBACKENDSTS_RUNNING,
+ /** The backend ran into an error and is unable to recover.
+ * A manual re-initialization might help. */
+ PDMAUDIOBACKENDSTS_ERROR,
+ /** Hack to blow the type up to 32-bit. */
+ PDMAUDIOBACKENDSTS_32BIT_HACK = 0x7fffffff
+} PDMAUDIOBACKENDSTS;
+
+/**
+ * PDM audio stream state.
+ *
+ * This is all the mixer/device needs. The PDMAUDIOSTREAM_STS_XXX stuff will
+ * become DrvAudio internal state once the backend stuff is destilled out of it.
+ *
+ * @note The value order is significant, don't change it willy-nilly.
+ */
+typedef enum PDMAUDIOSTREAMSTATE
+{
+ /** Invalid state value. */
+ PDMAUDIOSTREAMSTATE_INVALID = 0,
+ /** The stream is not operative and cannot be enabled. */
+ PDMAUDIOSTREAMSTATE_NOT_WORKING,
+ /** The stream needs to be re-initialized by the device/mixer
+ * (i.e. call PDMIAUDIOCONNECTOR::pfnStreamReInit). */
+ PDMAUDIOSTREAMSTATE_NEED_REINIT,
+ /** The stream is inactive (not enabled). */
+ PDMAUDIOSTREAMSTATE_INACTIVE,
+ /** The stream is enabled but nothing to read/write.
+ * @todo not sure if we need this variant... */
+ PDMAUDIOSTREAMSTATE_ENABLED,
+ /** The stream is enabled and captured samples can be read. */
+ PDMAUDIOSTREAMSTATE_ENABLED_READABLE,
+ /** The stream is enabled and samples can be written for playback. */
+ PDMAUDIOSTREAMSTATE_ENABLED_WRITABLE,
+ /** End of valid states. */
+ PDMAUDIOSTREAMSTATE_END,
+ /** Make sure the type is 32-bit wide. */
+ PDMAUDIOSTREAMSTATE_32BIT_HACK = 0x7fffffff
+} PDMAUDIOSTREAMSTATE;
+
+/** @name PDMAUDIOSTREAM_CREATE_F_XXX
+ * @{ */
+/** Does not need any mixing buffers, the device takes care of all conversion.
+ * @note this is now default and assumed always set. */
+#define PDMAUDIOSTREAM_CREATE_F_NO_MIXBUF RT_BIT_32(0)
+/** @} */
+
+/** @name PDMAUDIOSTREAM_WARN_FLAGS_XXX
+ * @{ */
+/** No stream warning flags set. */
+#define PDMAUDIOSTREAM_WARN_FLAGS_NONE 0
+/** Warned about a disabled stream. */
+#define PDMAUDIOSTREAM_WARN_FLAGS_DISABLED RT_BIT(0)
+/** @} */
+
+/**
+ * An input or output audio stream.
+ */
+typedef struct PDMAUDIOSTREAM
+{
+ /** Critical section protecting the stream.
+ *
+ * When not otherwise stated, DrvAudio will enter this before calling the
+ * backend. The backend and device/mixer can normally safely enter it prior to
+ * a DrvAudio call, however not to pfnStreamDestroy, pfnStreamRelease or
+ * anything that may access the stream list.
+ *
+ * @note Lock ordering:
+ * - After DRVAUDIO::CritSectGlobals.
+ * - Before DRVAUDIO::CritSectHotPlug. */
+ RTCRITSECT CritSect;
+ /** Stream configuration. */
+ PDMAUDIOSTREAMCFG Cfg;
+ /** Magic value (PDMAUDIOSTREAM_MAGIC). */
+ uint32_t uMagic;
+ /** Size (in bytes) of the backend-specific stream data. */
+ uint32_t cbBackend;
+ /** Warnings shown already in the release log.
+ * See PDMAUDIOSTREAM_WARN_FLAGS_XXX. */
+ uint32_t fWarningsShown;
+} PDMAUDIOSTREAM;
+/** Pointer to an audio stream. */
+typedef struct PDMAUDIOSTREAM *PPDMAUDIOSTREAM;
+/** Pointer to a const audio stream. */
+typedef struct PDMAUDIOSTREAM const *PCPDMAUDIOSTREAM;
+
+/** Magic value for PDMAUDIOSTREAM. */
+#define PDMAUDIOSTREAM_MAGIC PDM_VERSION_MAKE(0xa0d3, 5, 0)
+
+
+
+/** Pointer to a audio connector interface. */
+typedef struct PDMIAUDIOCONNECTOR *PPDMIAUDIOCONNECTOR;
+
+/**
+ * Audio connector interface (up).
+ */
+typedef struct PDMIAUDIOCONNECTOR
+{
+ /**
+ * Enables or disables the given audio direction for this driver.
+ *
+ * When disabled, assiociated output streams consume written audio without passing them further down to the backends.
+ * Associated input streams then return silence when read from those.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param enmDir Audio direction to enable or disable driver for.
+ * @param fEnable Whether to enable or disable the specified audio direction.
+ *
+ * @note Be very careful when using this function, as this could
+ * violate / run against the (global) VM settings. See @bugref{9882}.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnEnable, (PPDMIAUDIOCONNECTOR pInterface, PDMAUDIODIR enmDir, bool fEnable));
+
+ /**
+ * Returns whether the given audio direction for this driver is enabled or not.
+ *
+ * @returns True if audio is enabled for the given direction, false if not.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param enmDir Audio direction to retrieve enabled status for.
+ */
+ DECLR3CALLBACKMEMBER(bool, pfnIsEnabled, (PPDMIAUDIOCONNECTOR pInterface, PDMAUDIODIR enmDir));
+
+ /**
+ * Retrieves the current configuration of the host audio backend.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pCfg Where to store the host audio backend configuration data.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnGetConfig, (PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOBACKENDCFG pCfg));
+
+ /**
+ * Retrieves the current status of the host audio backend.
+ *
+ * @returns Status of the host audio backend.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param enmDir Audio direction to check host audio backend for. Specify PDMAUDIODIR_DUPLEX for the overall
+ * backend status.
+ */
+ DECLR3CALLBACKMEMBER(PDMAUDIOBACKENDSTS, pfnGetStatus, (PPDMIAUDIOCONNECTOR pInterface, PDMAUDIODIR enmDir));
+
+ /**
+ * Gives the audio drivers a hint about a typical configuration.
+ *
+ * This is a little hack for windows (and maybe other hosts) where stream
+ * creation can take a relatively long time, making it very unsuitable for EMT.
+ * The audio backend can use this hint to cache pre-configured stream setups,
+ * so that when the guest actually wants to play something EMT won't be blocked
+ * configuring host audio.
+ *
+ * @param pInterface Pointer to this interface.
+ * @param pCfg The typical configuration. Can be modified by the
+ * drivers in unspecified ways.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnStreamConfigHint, (PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAMCFG pCfg));
+
+ /**
+ * Creates an audio stream.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to this interface.
+ * @param fFlags PDMAUDIOSTREAM_CREATE_F_XXX.
+ * @param pCfgReq The requested stream configuration. The actual stream
+ * configuration can be found in pStream->Cfg on success.
+ * @param ppStream Pointer where to return the created audio stream on
+ * success.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnStreamCreate, (PPDMIAUDIOCONNECTOR pInterface, uint32_t fFlags, PCPDMAUDIOSTREAMCFG pCfgReq,
+ PPDMAUDIOSTREAM *ppStream));
+
+
+ /**
+ * Destroys an audio stream.
+ *
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pStream Pointer to audio stream.
+ * @param fImmediate Whether to immdiately stop and destroy a draining
+ * stream (@c true), or to allow it to complete
+ * draining first (@c false) if that's feasable.
+ * The latter depends on the draining stage and what
+ * the backend is capable of.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnStreamDestroy, (PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAM pStream, bool fImmediate));
+
+ /**
+ * Re-initializes the stream in response to PDMAUDIOSTREAM_STS_NEED_REINIT.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to this interface.
+ * @param pStream The audio stream needing re-initialization.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnStreamReInit, (PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAM pStream));
+
+ /**
+ * Adds a reference to the specified audio stream.
+ *
+ * @returns New reference count. UINT32_MAX on error.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pStream Pointer to audio stream adding the reference to.
+ */
+ DECLR3CALLBACKMEMBER(uint32_t, pfnStreamRetain, (PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAM pStream));
+
+ /**
+ * Releases a reference from the specified stream.
+ *
+ * @returns New reference count. UINT32_MAX on error.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pStream Pointer to audio stream releasing a reference from.
+ */
+ DECLR3CALLBACKMEMBER(uint32_t, pfnStreamRelease, (PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAM pStream));
+
+ /**
+ * Controls a specific audio stream.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pStream Pointer to audio stream.
+ * @param enmStreamCmd The stream command to issue.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnStreamControl, (PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAM pStream,
+ PDMAUDIOSTREAMCMD enmStreamCmd));
+
+ /**
+ * Processes stream data.
+ *
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pStream Pointer to audio stream.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnStreamIterate, (PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAM pStream));
+
+ /**
+ * Returns the state of a specific audio stream (destilled status).
+ *
+ * @returns PDMAUDIOSTREAMSTATE value.
+ * @retval PDMAUDIOSTREAMSTATE_INVALID if the input isn't valid (w/ assertion).
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pStream Pointer to audio stream.
+ */
+ DECLR3CALLBACKMEMBER(PDMAUDIOSTREAMSTATE, pfnStreamGetState, (PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAM pStream));
+
+ /**
+ * Returns the number of bytes that can be written to an audio output stream.
+ *
+ * @returns Number of bytes writable data.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pStream Pointer to audio stream.
+ */
+ DECLR3CALLBACKMEMBER(uint32_t, pfnStreamGetWritable, (PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAM pStream));
+
+ /**
+ * Plays (writes to) an audio output stream.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pStream Pointer to audio stream to read from.
+ * @param pvBuf Audio data to be written.
+ * @param cbBuf Number of bytes to be written.
+ * @param pcbWritten Bytes of audio data written. Optional.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnStreamPlay, (PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAM pStream,
+ const void *pvBuf, uint32_t cbBuf, uint32_t *pcbWritten));
+
+ /**
+ * Returns the number of bytes that can be read from an input stream.
+ *
+ * @returns Number of bytes of readable data.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pStream Pointer to audio stream.
+ */
+ DECLR3CALLBACKMEMBER(uint32_t, pfnStreamGetReadable, (PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAM pStream));
+
+ /**
+ * Captures (reads) samples from an audio input stream.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pStream Pointer to audio stream to write to.
+ * @param pvBuf Where to store the read data.
+ * @param cbBuf Number of bytes to read.
+ * @param pcbRead Bytes of audio data read. Optional.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnStreamCapture, (PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOSTREAM pStream,
+ void *pvBuf, uint32_t cbBuf, uint32_t *pcbRead));
+} PDMIAUDIOCONNECTOR;
+
+/** PDMIAUDIOCONNECTOR interface ID. */
+#define PDMIAUDIOCONNECTOR_IID "2900fe2a-6aeb-4953-ac12-f8965612f446"
+
+
+/**
+ * Host audio backend specific stream data.
+ *
+ * The backend will put this as the first member of it's own data structure.
+ */
+typedef struct PDMAUDIOBACKENDSTREAM
+{
+ /** Magic value (PDMAUDIOBACKENDSTREAM_MAGIC). */
+ uint32_t uMagic;
+ /** Explicit zero padding - do not touch! */
+ uint32_t uReserved;
+ /** Pointer to the stream this backend data is associated with. */
+ PPDMAUDIOSTREAM pStream;
+ /** Reserved for future use (zeroed) - do not touch. */
+ void *apvReserved[2];
+} PDMAUDIOBACKENDSTREAM;
+/** Pointer to host audio specific stream data! */
+typedef PDMAUDIOBACKENDSTREAM *PPDMAUDIOBACKENDSTREAM;
+
+/** Magic value for PDMAUDIOBACKENDSTREAM. */
+#define PDMAUDIOBACKENDSTREAM_MAGIC PDM_VERSION_MAKE(0xa0d4, 1, 0)
+
+/**
+ * Host audio (backend) stream state returned by PDMIHOSTAUDIO::pfnStreamGetState.
+ */
+typedef enum PDMHOSTAUDIOSTREAMSTATE
+{
+ /** Invalid zero value, as per usual. */
+ PDMHOSTAUDIOSTREAMSTATE_INVALID = 0,
+ /** The stream is being initialized.
+ * This should also be used when switching to a new device and the stream
+ * stops to work with the old device while the new one being configured. */
+ PDMHOSTAUDIOSTREAMSTATE_INITIALIZING,
+ /** The stream does not work (async init failed, audio subsystem gone
+ * fishing, or similar). */
+ PDMHOSTAUDIOSTREAMSTATE_NOT_WORKING,
+ /** Backend is working okay. */
+ PDMHOSTAUDIOSTREAMSTATE_OKAY,
+ /** Backend is working okay, but currently draining the stream. */
+ PDMHOSTAUDIOSTREAMSTATE_DRAINING,
+ /** Backend is working but doesn't want any commands or data reads/writes. */
+ PDMHOSTAUDIOSTREAMSTATE_INACTIVE,
+ /** End of valid values. */
+ PDMHOSTAUDIOSTREAMSTATE_END,
+ /** Blow the type up to 32 bits. */
+ PDMHOSTAUDIOSTREAMSTATE_32BIT_HACK = 0x7fffffff
+} PDMHOSTAUDIOSTREAMSTATE;
+
+
+/** Pointer to a host audio interface. */
+typedef struct PDMIHOSTAUDIO *PPDMIHOSTAUDIO;
+
+/**
+ * PDM host audio interface.
+ */
+typedef struct PDMIHOSTAUDIO
+{
+ /**
+ * Returns the host backend's configuration (backend).
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pBackendCfg Where to store the backend audio configuration to.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnGetConfig, (PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDCFG pBackendCfg));
+
+ /**
+ * Returns (enumerates) host audio device information (optional).
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pDeviceEnum Where to return the enumerated audio devices.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnGetDevices, (PPDMIHOSTAUDIO pInterface, PPDMAUDIOHOSTENUM pDeviceEnum));
+
+ /**
+ * Changes the output or input device.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to this interface.
+ * @param enmDir The direction to set the device for: PDMAUDIODIR_IN,
+ * PDMAUDIODIR_OUT or PDMAUDIODIR_DUPLEX (both the
+ * previous).
+ * @param pszId The PDMAUDIOHOSTDEV::pszId value of the device to
+ * use, or NULL / empty string for the default device.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSetDevice, (PPDMIHOSTAUDIO pInterface, PDMAUDIODIR enmDir, const char *pszId));
+
+ /**
+ * Returns the current status from the audio backend (optional).
+ *
+ * @returns PDMAUDIOBACKENDSTS enum.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param enmDir Audio direction to get status for. Pass PDMAUDIODIR_DUPLEX for overall status.
+ */
+ DECLR3CALLBACKMEMBER(PDMAUDIOBACKENDSTS, pfnGetStatus, (PPDMIHOSTAUDIO pInterface, PDMAUDIODIR enmDir));
+
+ /**
+ * Callback for genric on-worker-thread requests initiated by the backend itself.
+ *
+ * This is the counterpart to PDMIHOSTAUDIOPORT::pfnDoOnWorkerThread that will
+ * be invoked on a worker thread when the backend requests it - optional.
+ *
+ * This does not return a value, so the backend must keep track of
+ * failure/success on its own.
+ *
+ * This method is optional. A non-NULL will, together with pfnStreamInitAsync
+ * and PDMAUDIOBACKEND_F_ASYNC_HINT, force DrvAudio to create the thread pool.
+ *
+ * @param pInterface Pointer to this interface.
+ * @param pStream Optionally a backend stream if specified in the
+ * PDMIHOSTAUDIOPORT::pfnDoOnWorkerThread() call.
+ * @param uUser User specific value as specified in the
+ * PDMIHOSTAUDIOPORT::pfnDoOnWorkerThread() call.
+ * @param pvUser User specific pointer as specified in the
+ * PDMIHOSTAUDIOPORT::pfnDoOnWorkerThread() call.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnDoOnWorkerThread,(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream,
+ uintptr_t uUser, void *pvUser));
+
+ /**
+ * Gives the audio backend a hint about a typical configuration (optional).
+ *
+ * This is a little hack for windows (and maybe other hosts) where stream
+ * creation can take a relatively long time, making it very unsuitable for EMT.
+ * The audio backend can use this hint to cache pre-configured stream setups,
+ * so that when the guest actually wants to play something EMT won't be blocked
+ * configuring host audio.
+ *
+ * The backend can return PDMAUDIOBACKEND_F_ASYNC_HINT in
+ * PDMIHOSTAUDIO::pfnGetConfig to avoid having EMT making this call and thereby
+ * speeding up VM construction.
+ *
+ * @param pInterface Pointer to this interface.
+ * @param pCfg The typical configuration. (Feel free to change it
+ * to the actual stream config that would be used,
+ * however caller will probably ignore this.)
+ */
+ DECLR3CALLBACKMEMBER(void, pfnStreamConfigHint, (PPDMIHOSTAUDIO pInterface, PPDMAUDIOSTREAMCFG pCfg));
+
+ /**
+ * Creates an audio stream using the requested stream configuration.
+ *
+ * If a backend is not able to create this configuration, it will return its
+ * best match in the acquired configuration structure on success.
+ *
+ * @returns VBox status code.
+ * @retval VINF_AUDIO_STREAM_ASYNC_INIT_NEEDED if
+ * PDMIHOSTAUDIO::pfnStreamInitAsync should be called.
+ * @param pInterface Pointer to this interface.
+ * @param pStream Pointer to the audio stream.
+ * @param pCfgReq The requested stream configuration.
+ * @param pCfgAcq The acquired stream configuration - output. This is
+ * the same as @a *pCfgReq when called, the
+ * implementation will adjust it to make the actual
+ * stream configuration as needed.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnStreamCreate, (PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream,
+ PCPDMAUDIOSTREAMCFG pCfgReq, PPDMAUDIOSTREAMCFG pCfgAcq));
+
+ /**
+ * Asynchronous stream initialization step, optional.
+ *
+ * This is called on a worker thread iff the PDMIHOSTAUDIO::pfnStreamCreate
+ * method returns VINF_AUDIO_STREAM_ASYNC_INIT_NEEDED.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to this interface.
+ * @param pStream Pointer to audio stream to continue
+ * initialization of.
+ * @param fDestroyed Set to @c true if the stream has been destroyed
+ * before the worker thread got to making this
+ * call. The backend should just ready the stream
+ * for destruction in that case.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnStreamInitAsync, (PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream, bool fDestroyed));
+
+ /**
+ * Destroys an audio stream.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface containing the called function.
+ * @param pStream Pointer to audio stream.
+ * @param fImmediate Whether to immdiately stop and destroy a draining
+ * stream (@c true), or to allow it to complete
+ * draining first (@c false) if that's feasable.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnStreamDestroy, (PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream, bool fImmediate));
+
+ /**
+ * Called from PDMIHOSTAUDIOPORT::pfnNotifyDeviceChanged so the backend can start
+ * the device change for a stream.
+ *
+ * This is mainly to avoid the need for a list of streams in the backend.
+ *
+ * @param pInterface Pointer to this interface.
+ * @param pStream Pointer to audio stream (locked).
+ * @param pvUser Backend specific parameter from the call to
+ * PDMIHOSTAUDIOPORT::pfnNotifyDeviceChanged.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnStreamNotifyDeviceChanged,(PPDMIHOSTAUDIO pInterface,
+ PPDMAUDIOBACKENDSTREAM pStream, void *pvUser));
+
+ /**
+ * Enables (starts) the stream.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to this interface.
+ * @param pStream Pointer to the audio stream to enable.
+ * @sa PDMAUDIOSTREAMCMD_ENABLE
+ */
+ DECLR3CALLBACKMEMBER(int, pfnStreamEnable, (PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream));
+
+ /**
+ * Disables (stops) the stream immediately.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to this interface.
+ * @param pStream Pointer to the audio stream to disable.
+ * @sa PDMAUDIOSTREAMCMD_DISABLE
+ */
+ DECLR3CALLBACKMEMBER(int, pfnStreamDisable, (PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream));
+
+ /**
+ * Pauses the stream - called when the VM is suspended.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to this interface.
+ * @param pStream Pointer to the audio stream to pause.
+ * @sa PDMAUDIOSTREAMCMD_PAUSE
+ */
+ DECLR3CALLBACKMEMBER(int, pfnStreamPause, (PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream));
+
+ /**
+ * Resumes a paused stream - called when the VM is resumed.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to this interface.
+ * @param pStream Pointer to the audio stream to resume.
+ * @sa PDMAUDIOSTREAMCMD_RESUME
+ */
+ DECLR3CALLBACKMEMBER(int, pfnStreamResume, (PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream));
+
+ /**
+ * Drain the stream, that is, play what's in the buffers and then stop.
+ *
+ * There will be no more samples written after this command is issued.
+ * PDMIHOSTAUDIO::pfnStreamPlay with a zero sized buffer will provide the
+ * backend with a way to drive it forwards. These calls will come at a
+ * frequency set by the device and be on an asynchronous I/O thread.
+ *
+ * The PDMIHOSTAUDIO::pfnStreamDisable method maybe called if the device/mixer
+ * wants to re-enable the stream while it's still draining or if it gets
+ * impatient and thinks the draining has been going on too long, in which case
+ * the stream should stop immediately.
+ *
+ * @note This should not wait for the stream to finish draining, just change
+ * the state. (The caller could be an EMT and it must not block for
+ * hundreds of milliseconds of buffer to finish draining.)
+ *
+ * @note Does not apply to input streams. Backends should refuse such
+ * requests.
+ *
+ * @returns VBox status code.
+ * @retval VERR_WRONG_ORDER if not output stream.
+ * @param pInterface Pointer to this interface.
+ * @param pStream Pointer to the audio stream to drain.
+ * @sa PDMAUDIOSTREAMCMD_DRAIN
+ */
+ DECLR3CALLBACKMEMBER(int, pfnStreamDrain, (PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream));
+
+ /**
+ * Returns the current state of the given backend stream.
+ *
+ * @returns PDMHOSTAUDIOSTREAMSTATE value.
+ * @retval PDMHOSTAUDIOSTREAMSTATE_INVALID if invalid stream.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pStream Pointer to audio stream.
+ */
+ DECLR3CALLBACKMEMBER(PDMHOSTAUDIOSTREAMSTATE, pfnStreamGetState, (PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream));
+
+ /**
+ * Returns the number of buffered bytes that hasn't been played yet (optional).
+ *
+ * Is not valid on an input stream, implementions shall assert and return zero.
+ *
+ * @returns Number of pending bytes.
+ * @param pInterface Pointer to this interface.
+ * @param pStream Pointer to the audio stream.
+ *
+ * @todo This is no longer not used by DrvAudio and can probably be removed.
+ */
+ DECLR3CALLBACKMEMBER(uint32_t, pfnStreamGetPending, (PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream));
+
+ /**
+ * Returns the amount which is writable to the audio (output) stream.
+ *
+ * @returns Number of writable bytes.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pStream Pointer to audio stream.
+ */
+ DECLR3CALLBACKMEMBER(uint32_t, pfnStreamGetWritable, (PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream));
+
+ /**
+ * Plays (writes to) an audio (output) stream.
+ *
+ * This is always called with data in the buffer, except after
+ * PDMAUDIOSTREAMCMD_DRAIN is issued when it's called every so often to assist
+ * the backend with moving the draining operation forward (kind of like
+ * PDMIAUDIOCONNECTOR::pfnStreamIterate).
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pStream Pointer to audio stream.
+ * @param pvBuf Pointer to audio data buffer to play. This will be NULL
+ * when called to assist draining the stream.
+ * @param cbBuf The number of bytes of audio data to play. This will be
+ * zero when called to assist draining the stream.
+ * @param pcbWritten Where to return the actual number of bytes played.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnStreamPlay, (PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream,
+ const void *pvBuf, uint32_t cbBuf, uint32_t *pcbWritten));
+
+ /**
+ * Returns the amount which is readable from the audio (input) stream.
+ *
+ * @returns For non-raw layout streams: Number of readable bytes.
+ * for raw layout streams : Number of readable audio frames.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pStream Pointer to audio stream.
+ */
+ DECLR3CALLBACKMEMBER(uint32_t, pfnStreamGetReadable, (PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream));
+
+ /**
+ * Captures (reads from) an audio (input) stream.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pStream Pointer to audio stream.
+ * @param pvBuf Buffer where to store read audio data.
+ * @param cbBuf Size of the audio data buffer in bytes.
+ * @param pcbRead Where to return the number of bytes actually captured.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnStreamCapture, (PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream,
+ void *pvBuf, uint32_t cbBuf, uint32_t *pcbRead));
+} PDMIHOSTAUDIO;
+
+/** PDMIHOSTAUDIO interface ID. */
+#define PDMIHOSTAUDIO_IID "c0875b91-a4f9-48be-8595-31d27048432d"
+
+
+/** Pointer to a audio notify from host interface. */
+typedef struct PDMIHOSTAUDIOPORT *PPDMIHOSTAUDIOPORT;
+
+/**
+ * PDM host audio port interface, upwards sibling of PDMIHOSTAUDIO.
+ */
+typedef struct PDMIHOSTAUDIOPORT
+{
+ /**
+ * Ask DrvAudio to call PDMIHOSTAUDIO::pfnDoOnWorkerThread on a worker thread.
+ *
+ * Generic method for doing asynchronous work using the DrvAudio thread pool.
+ *
+ * This function will not wait for PDMIHOSTAUDIO::pfnDoOnWorkerThread to
+ * complete, but returns immediately after submitting the request to the thread
+ * pool.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to this interface.
+ * @param pStream Optional backend stream structure to pass along. The
+ * reference count will be increased till the call
+ * completes to make sure the stream stays valid.
+ * @param uUser User specific value.
+ * @param pvUser User specific pointer.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnDoOnWorkerThread,(PPDMIHOSTAUDIOPORT pInterface, PPDMAUDIOBACKENDSTREAM pStream,
+ uintptr_t uUser, void *pvUser));
+
+ /**
+ * The device for the given direction changed.
+ *
+ * The driver above backend (DrvAudio) will call the backend back
+ * (PDMIHOSTAUDIO::pfnStreamNotifyDeviceChanged) for all open streams in the
+ * given direction. (This ASSUMES the backend uses one output device and one
+ * input devices for all streams.)
+ *
+ * @param pInterface Pointer to this interface.
+ * @param enmDir The audio direction.
+ * @param pvUser Backend specific parameter for
+ * PDMIHOSTAUDIO::pfnStreamNotifyDeviceChanged.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnNotifyDeviceChanged,(PPDMIHOSTAUDIOPORT pInterface, PDMAUDIODIR enmDir, void *pvUser));
+
+ /**
+ * Notification that the stream is about to change device in a bit.
+ *
+ * This will assume PDMAUDIOSTREAM_STS_PREPARING_SWITCH will be set when
+ * PDMIHOSTAUDIO::pfnStreamGetStatus is next called and change the stream state
+ * accordingly.
+ *
+ * @param pInterface Pointer to this interface.
+ * @param pStream The stream that changed device (backend variant).
+ */
+ DECLR3CALLBACKMEMBER(void, pfnStreamNotifyPreparingDeviceSwitch,(PPDMIHOSTAUDIOPORT pInterface,
+ PPDMAUDIOBACKENDSTREAM pStream));
+
+ /**
+ * The stream has changed its device and left the
+ * PDMAUDIOSTREAM_STS_PREPARING_SWITCH state (if it entered it at all).
+ *
+ * @param pInterface Pointer to this interface.
+ * @param pStream The stream that changed device (backend variant).
+ * @param fReInit Set if a re-init is required, clear if not.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnStreamNotifyDeviceChanged,(PPDMIHOSTAUDIOPORT pInterface,
+ PPDMAUDIOBACKENDSTREAM pStream, bool fReInit));
+
+ /**
+ * One or more audio devices have changed in some way.
+ *
+ * The upstream driver/device should re-evaluate the devices they're using.
+ *
+ * @todo r=bird: The upstream driver/device does not know which host audio
+ * devices they are using. This is mainly for triggering enumeration and
+ * logging of the audio devices.
+ *
+ * @param pInterface Pointer to this interface.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnNotifyDevicesChanged,(PPDMIHOSTAUDIOPORT pInterface));
+} PDMIHOSTAUDIOPORT;
+
+/** PDMIHOSTAUDIOPORT interface ID. */
+#define PDMIHOSTAUDIOPORT_IID "92ea5169-8271-402d-99a7-9de26a52acaf"
+
+
+/**
+ * Audio mixer controls.
+ *
+ * @note This isn't part of any official PDM interface as such, it's more of a
+ * common thing that all the devices seem to need.
+ */
+typedef enum PDMAUDIOMIXERCTL
+{
+ /** Invalid zero value as per usual (guards against using unintialized values). */
+ PDMAUDIOMIXERCTL_INVALID = 0,
+ /** Unknown mixer control. */
+ PDMAUDIOMIXERCTL_UNKNOWN,
+ /** Master volume. */
+ PDMAUDIOMIXERCTL_VOLUME_MASTER,
+ /** Front. */
+ PDMAUDIOMIXERCTL_FRONT,
+ /** Center / LFE (Subwoofer). */
+ PDMAUDIOMIXERCTL_CENTER_LFE,
+ /** Rear. */
+ PDMAUDIOMIXERCTL_REAR,
+ /** Line-In. */
+ PDMAUDIOMIXERCTL_LINE_IN,
+ /** Microphone-In. */
+ PDMAUDIOMIXERCTL_MIC_IN,
+ /** End of valid values. */
+ PDMAUDIOMIXERCTL_END,
+ /** Hack to blow the type up to 32-bit. */
+ PDMAUDIOMIXERCTL_32BIT_HACK = 0x7fffffff
+} PDMAUDIOMIXERCTL;
+
+/**
+ * Audio volume parameters.
+ *
+ * @note This isn't part of any official PDM interface any more (it used to be
+ * used to PDMIAUDIOCONNECTOR). It's currently only used by the mixer API.
+ */
+typedef struct PDMAUDIOVOLUME
+{
+ /** Set to @c true if this stream is muted, @c false if not. */
+ bool fMuted;
+ /** The volume for each channel.
+ * The values zero is the most silent one (although not quite muted), and 255
+ * the loudest. */
+ uint8_t auChannels[PDMAUDIO_MAX_CHANNELS];
+} PDMAUDIOVOLUME;
+/** Pointer to audio volume settings. */
+typedef PDMAUDIOVOLUME *PPDMAUDIOVOLUME;
+/** Pointer to const audio volume settings. */
+typedef PDMAUDIOVOLUME const *PCPDMAUDIOVOLUME;
+
+/** Defines the minimum volume allowed. */
+#define PDMAUDIO_VOLUME_MIN (0)
+/** Defines the maximum volume allowed. */
+#define PDMAUDIO_VOLUME_MAX (255)
+/** Initializator for max volume on all channels. */
+#define PDMAUDIOVOLUME_INITIALIZER_MAX \
+ { /* .fMuted = */ false, \
+ /* .auChannels = */ { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } }
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !VBOX_INCLUDED_vmm_pdmaudioifs_h */
+
diff --git a/include/VBox/vmm/pdmaudioinline.h b/include/VBox/vmm/pdmaudioinline.h
new file mode 100644
index 00000000..5d3175c0
--- /dev/null
+++ b/include/VBox/vmm/pdmaudioinline.h
@@ -0,0 +1,1507 @@
+/* $Id: pdmaudioinline.h $ */
+/** @file
+ * PDM - Audio Helpers, Inlined Code. (DEV,++)
+ *
+ * This is all inlined because it's too tedious to create a couple libraries to
+ * contain it all (same bad excuse as for intnetinline.h & pdmnetinline.h).
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vmm_pdmaudioinline_h
+#define VBOX_INCLUDED_vmm_pdmaudioinline_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#include <VBox/err.h>
+#include <VBox/log.h>
+#include <VBox/vmm/pdmaudioifs.h>
+
+#include <iprt/asm.h>
+#include <iprt/asm-math.h>
+#include <iprt/assert.h>
+#include <iprt/mem.h>
+#include <iprt/string.h>
+
+
+/** @defgroup grp_pdm_audio_inline The PDM Audio Helper APIs
+ * @ingroup grp_pdm
+ * @{
+ */
+
+
+/**
+ * Gets the name of an audio direction enum value.
+ *
+ * @returns Pointer to read-only name string on success, "bad" if passed an
+ * invalid enum value.
+ * @param enmDir The audio direction value to name.
+ */
+DECLINLINE(const char *) PDMAudioDirGetName(PDMAUDIODIR enmDir)
+{
+ switch (enmDir)
+ {
+ case PDMAUDIODIR_INVALID: return "invalid";
+ case PDMAUDIODIR_UNKNOWN: return "unknown";
+ case PDMAUDIODIR_IN: return "input";
+ case PDMAUDIODIR_OUT: return "output";
+ case PDMAUDIODIR_DUPLEX: return "duplex";
+
+ /* no default */
+ case PDMAUDIODIR_END:
+ case PDMAUDIODIR_32BIT_HACK:
+ break;
+ }
+ AssertMsgFailedReturn(("Invalid audio direction %d\n", enmDir), "bad");
+}
+
+/**
+ * Gets the name of an audio mixer control enum value.
+ *
+ * @returns Pointer to read-only name, "bad" if invalid input.
+ * @param enmMixerCtl The audio mixer control value.
+ */
+DECLINLINE(const char *) PDMAudioMixerCtlGetName(PDMAUDIOMIXERCTL enmMixerCtl)
+{
+ switch (enmMixerCtl)
+ {
+ case PDMAUDIOMIXERCTL_INVALID: return "Invalid";
+ case PDMAUDIOMIXERCTL_UNKNOWN: return "Unknown";
+ case PDMAUDIOMIXERCTL_VOLUME_MASTER: return "Master Volume";
+ case PDMAUDIOMIXERCTL_FRONT: return "Front";
+ case PDMAUDIOMIXERCTL_CENTER_LFE: return "Center / LFE";
+ case PDMAUDIOMIXERCTL_REAR: return "Rear";
+ case PDMAUDIOMIXERCTL_LINE_IN: return "Line-In";
+ case PDMAUDIOMIXERCTL_MIC_IN: return "Microphone-In";
+
+ /* no default */
+ case PDMAUDIOMIXERCTL_END:
+ case PDMAUDIOMIXERCTL_32BIT_HACK:
+ break;
+ }
+ AssertMsgFailedReturn(("Invalid mixer control %ld\n", enmMixerCtl), "bad");
+}
+
+/**
+ * Gets the name of a path enum value.
+ *
+ * @returns Pointer to read-only name, "bad" if invalid input.
+ * @param enmPath The path value to name.
+ */
+DECLINLINE(const char *) PDMAudioPathGetName(PDMAUDIOPATH enmPath)
+{
+ switch (enmPath)
+ {
+ case PDMAUDIOPATH_INVALID: return "invalid";
+ case PDMAUDIOPATH_UNKNOWN: return "unknown";
+
+ case PDMAUDIOPATH_OUT_FRONT: return "front";
+ case PDMAUDIOPATH_OUT_CENTER_LFE: return "center-lfe";
+ case PDMAUDIOPATH_OUT_REAR: return "rear";
+
+ case PDMAUDIOPATH_IN_MIC: return "mic";
+ case PDMAUDIOPATH_IN_CD: return "cd";
+ case PDMAUDIOPATH_IN_VIDEO: return "video-in";
+ case PDMAUDIOPATH_IN_AUX: return "aux-in";
+ case PDMAUDIOPATH_IN_LINE: return "line-in";
+ case PDMAUDIOPATH_IN_PHONE: return "phone";
+
+ /* no default */
+ case PDMAUDIOPATH_END:
+ case PDMAUDIOPATH_32BIT_HACK:
+ break;
+ }
+ AssertMsgFailedReturn(("Unknown enmPath=%d\n", enmPath), "bad");
+}
+
+/**
+ * Gets the name of a channel.
+ *
+ * @returns Pointer to read-only name, "bad" if invalid input.
+ * @param enmChannelId The channel ID to name.
+ */
+DECLINLINE(const char *) PDMAudioChannelIdGetName(PDMAUDIOCHANNELID enmChannelId)
+{
+ switch (enmChannelId)
+ {
+ case PDMAUDIOCHANNELID_INVALID: return "invalid";
+ case PDMAUDIOCHANNELID_UNUSED_ZERO: return "unused-zero";
+ case PDMAUDIOCHANNELID_UNUSED_SILENCE: return "unused-silence";
+ case PDMAUDIOCHANNELID_UNKNOWN: return "unknown";
+
+ case PDMAUDIOCHANNELID_FRONT_LEFT: return "FL";
+ case PDMAUDIOCHANNELID_FRONT_RIGHT: return "FR";
+ case PDMAUDIOCHANNELID_FRONT_CENTER: return "FC";
+ case PDMAUDIOCHANNELID_LFE: return "LFE";
+ case PDMAUDIOCHANNELID_REAR_LEFT: return "BL";
+ case PDMAUDIOCHANNELID_REAR_RIGHT: return "BR";
+ case PDMAUDIOCHANNELID_FRONT_LEFT_OF_CENTER: return "FLC";
+ case PDMAUDIOCHANNELID_FRONT_RIGHT_OF_CENTER: return "FRC";
+ case PDMAUDIOCHANNELID_REAR_CENTER: return "BC";
+ case PDMAUDIOCHANNELID_SIDE_LEFT: return "SL";
+ case PDMAUDIOCHANNELID_SIDE_RIGHT: return "SR";
+ case PDMAUDIOCHANNELID_TOP_CENTER: return "TC";
+ case PDMAUDIOCHANNELID_FRONT_LEFT_HEIGHT: return "TFL";
+ case PDMAUDIOCHANNELID_FRONT_CENTER_HEIGHT: return "TFC";
+ case PDMAUDIOCHANNELID_FRONT_RIGHT_HEIGHT: return "TFR";
+ case PDMAUDIOCHANNELID_REAR_LEFT_HEIGHT: return "TBL";
+ case PDMAUDIOCHANNELID_REAR_CENTER_HEIGHT: return "TBC";
+ case PDMAUDIOCHANNELID_REAR_RIGHT_HEIGHT: return "TBR";
+
+ /* no default */
+ case PDMAUDIOCHANNELID_END:
+ case PDMAUDIOCHANNELID_32BIT_HACK:
+ break;
+ }
+ AssertMsgFailedReturn(("Unknown enmChannelId=%d\n", enmChannelId), "bad");
+}
+
+
+/*********************************************************************************************************************************
+* Volume Helpers *
+*********************************************************************************************************************************/
+
+/**
+ * Initializes a PDMAUDIOVOLUME structure to max.
+ *
+ * @param pVol The structure to initialize.
+ */
+DECLINLINE(void) PDMAudioVolumeInitMax(PPDMAUDIOVOLUME pVol)
+{
+ pVol->fMuted = false;
+ for (uintptr_t i = 0; i < RT_ELEMENTS(pVol->auChannels); i++)
+ pVol->auChannels[i] = PDMAUDIO_VOLUME_MAX;
+}
+
+
+/**
+ * Initializes a PDMAUDIOVOLUME structure from a simple stereo setting.
+ *
+ * The additional channels will simply be assigned the higer of the two.
+ *
+ * @param pVol The structure to initialize.
+ * @param fMuted Muted.
+ * @param bLeft The left channel volume.
+ * @param bRight The right channel volume.
+ */
+DECLINLINE(void) PDMAudioVolumeInitFromStereo(PPDMAUDIOVOLUME pVol, bool fMuted, uint8_t bLeft, uint8_t bRight)
+{
+ pVol->fMuted = fMuted;
+ pVol->auChannels[0] = bLeft;
+ pVol->auChannels[1] = bRight;
+
+ uint8_t const bOther = RT_MAX(bLeft, bRight);
+ for (uintptr_t i = 2; i < RT_ELEMENTS(pVol->auChannels); i++)
+ pVol->auChannels[i] = bOther;
+}
+
+
+/**
+ * Combines two volume settings (typically master and sink).
+ *
+ * @param pVol Where to return the combined volume
+ * @param pVol1 The first volume settings to combine.
+ * @param pVol2 The second volume settings.
+ */
+DECLINLINE(void) PDMAudioVolumeCombine(PPDMAUDIOVOLUME pVol, PCPDMAUDIOVOLUME pVol1, PCPDMAUDIOVOLUME pVol2)
+{
+ if (pVol1->fMuted || pVol2->fMuted)
+ {
+ pVol->fMuted = true;
+ for (uintptr_t i = 0; i < RT_ELEMENTS(pVol->auChannels); i++)
+ pVol->auChannels[i] = 0;
+ }
+ else
+ {
+ pVol->fMuted = false;
+ /** @todo Very crude implementation for now -- needs more work! (At least
+ * when used in audioMixerSinkUpdateVolume it was considered as such.) */
+ for (uintptr_t i = 0; i < RT_ELEMENTS(pVol->auChannels); i++)
+ {
+#if 0 /* bird: I think the shift variant should produce the exact same result, w/o two conditionals per iteration. */
+ /* 255 * 255 / 255 = 0xFF (255) */
+ /* 17 * 127 / 255 = 8 */
+ /* 39 * 39 / 255 = 5 */
+ pVol->auChannels[i] = (uint8_t)( (RT_MAX(pVol1->auChannels[i], 1U) * RT_MAX(pVol2->auChannels[i], 1U))
+ / PDMAUDIO_VOLUME_MAX);
+#else
+ /* (((255 + 1) * (255 + 1)) >> 8) - 1 = 0xFF (255) */
+ /* ((( 17 + 1) * (127 + 1)) >> 8) - 1 = 0x8 (8) */
+ /* ((( 39 + 1) * ( 39 + 1)) >> 8) - 1 = 0x5 (5) */
+ pVol->auChannels[i] = (uint8_t)((((1U + pVol1->auChannels[i]) * (1U + pVol2->auChannels[i])) >> 8) - 1U);
+#endif
+ }
+ }
+}
+
+
+/*********************************************************************************************************************************
+* PCM Property Helpers *
+*********************************************************************************************************************************/
+
+/**
+ * Assigns default channel IDs according to the channel count.
+ *
+ * The assignments are taken from the standard speaker channel layouts table
+ * in the wikipedia article on surround sound:
+ * https://en.wikipedia.org/wiki/Surround_sound#Standard_speaker_channels
+ */
+DECLINLINE(void) PDMAudioPropsSetDefaultChannelIds(PPDMAUDIOPCMPROPS pProps)
+{
+ unsigned cChannels = pProps->cChannelsX;
+ switch (cChannels)
+ {
+ case 1:
+ pProps->aidChannels[0] = PDMAUDIOCHANNELID_MONO;
+ break;
+ case 2:
+ pProps->aidChannels[0] = PDMAUDIOCHANNELID_FRONT_LEFT;
+ pProps->aidChannels[1] = PDMAUDIOCHANNELID_FRONT_RIGHT;
+ break;
+ case 3: /* 2.1 */
+ pProps->aidChannels[0] = PDMAUDIOCHANNELID_FRONT_LEFT;
+ pProps->aidChannels[1] = PDMAUDIOCHANNELID_FRONT_RIGHT;
+ pProps->aidChannels[2] = PDMAUDIOCHANNELID_LFE;
+ break;
+ case 4: /* 4.0 */
+ pProps->aidChannels[0] = PDMAUDIOCHANNELID_FRONT_LEFT;
+ pProps->aidChannels[1] = PDMAUDIOCHANNELID_FRONT_RIGHT;
+ pProps->aidChannels[2] = PDMAUDIOCHANNELID_REAR_LEFT;
+ pProps->aidChannels[3] = PDMAUDIOCHANNELID_REAR_RIGHT;
+ break;
+ case 5: /* 4.1 */
+ pProps->aidChannels[0] = PDMAUDIOCHANNELID_FRONT_LEFT;
+ pProps->aidChannels[1] = PDMAUDIOCHANNELID_FRONT_RIGHT;
+ pProps->aidChannels[2] = PDMAUDIOCHANNELID_FRONT_CENTER;
+ pProps->aidChannels[3] = PDMAUDIOCHANNELID_LFE;
+ pProps->aidChannels[4] = PDMAUDIOCHANNELID_REAR_CENTER;
+ break;
+ case 6: /* 5.1 */
+ pProps->aidChannels[0] = PDMAUDIOCHANNELID_FRONT_LEFT;
+ pProps->aidChannels[1] = PDMAUDIOCHANNELID_FRONT_RIGHT;
+ pProps->aidChannels[2] = PDMAUDIOCHANNELID_FRONT_CENTER;
+ pProps->aidChannels[3] = PDMAUDIOCHANNELID_LFE;
+ pProps->aidChannels[4] = PDMAUDIOCHANNELID_REAR_LEFT;
+ pProps->aidChannels[5] = PDMAUDIOCHANNELID_REAR_RIGHT;
+ break;
+ case 7: /* 6.1 */
+ pProps->aidChannels[0] = PDMAUDIOCHANNELID_FRONT_LEFT;
+ pProps->aidChannels[1] = PDMAUDIOCHANNELID_FRONT_RIGHT;
+ pProps->aidChannels[2] = PDMAUDIOCHANNELID_FRONT_CENTER;
+ pProps->aidChannels[3] = PDMAUDIOCHANNELID_LFE;
+ pProps->aidChannels[4] = PDMAUDIOCHANNELID_REAR_LEFT;
+ pProps->aidChannels[5] = PDMAUDIOCHANNELID_REAR_RIGHT;
+ pProps->aidChannels[6] = PDMAUDIOCHANNELID_REAR_CENTER;
+ break;
+ case 8: /* 7.1 */
+ pProps->aidChannels[0] = PDMAUDIOCHANNELID_FRONT_LEFT;
+ pProps->aidChannels[1] = PDMAUDIOCHANNELID_FRONT_RIGHT;
+ pProps->aidChannels[2] = PDMAUDIOCHANNELID_FRONT_CENTER;
+ pProps->aidChannels[3] = PDMAUDIOCHANNELID_LFE;
+ pProps->aidChannels[4] = PDMAUDIOCHANNELID_REAR_LEFT;
+ pProps->aidChannels[5] = PDMAUDIOCHANNELID_REAR_RIGHT;
+ pProps->aidChannels[6] = PDMAUDIOCHANNELID_FRONT_LEFT_OF_CENTER;
+ pProps->aidChannels[7] = PDMAUDIOCHANNELID_FRONT_RIGHT_OF_CENTER;
+ break;
+ case 9: /* 9.0 */
+ pProps->aidChannels[0] = PDMAUDIOCHANNELID_FRONT_LEFT;
+ pProps->aidChannels[1] = PDMAUDIOCHANNELID_FRONT_RIGHT;
+ pProps->aidChannels[2] = PDMAUDIOCHANNELID_FRONT_CENTER;
+ pProps->aidChannels[3] = PDMAUDIOCHANNELID_REAR_LEFT;
+ pProps->aidChannels[4] = PDMAUDIOCHANNELID_REAR_RIGHT;
+ pProps->aidChannels[5] = PDMAUDIOCHANNELID_SIDE_LEFT;
+ pProps->aidChannels[6] = PDMAUDIOCHANNELID_SIDE_RIGHT;
+ pProps->aidChannels[7] = PDMAUDIOCHANNELID_FRONT_LEFT_HEIGHT;
+ pProps->aidChannels[8] = PDMAUDIOCHANNELID_FRONT_RIGHT_HEIGHT;
+ break;
+ case 10: /* 9.1 */
+ pProps->aidChannels[0] = PDMAUDIOCHANNELID_FRONT_LEFT;
+ pProps->aidChannels[1] = PDMAUDIOCHANNELID_FRONT_RIGHT;
+ pProps->aidChannels[2] = PDMAUDIOCHANNELID_FRONT_CENTER;
+ pProps->aidChannels[3] = PDMAUDIOCHANNELID_LFE;
+ pProps->aidChannels[4] = PDMAUDIOCHANNELID_REAR_LEFT;
+ pProps->aidChannels[5] = PDMAUDIOCHANNELID_REAR_RIGHT;
+ pProps->aidChannels[6] = PDMAUDIOCHANNELID_SIDE_LEFT;
+ pProps->aidChannels[7] = PDMAUDIOCHANNELID_SIDE_RIGHT;
+ pProps->aidChannels[8] = PDMAUDIOCHANNELID_FRONT_LEFT_HEIGHT;
+ pProps->aidChannels[9] = PDMAUDIOCHANNELID_FRONT_RIGHT_HEIGHT;
+ break;
+ case 11: /* 11.0 */
+ pProps->aidChannels[0] = PDMAUDIOCHANNELID_FRONT_LEFT;
+ pProps->aidChannels[1] = PDMAUDIOCHANNELID_FRONT_RIGHT;
+ pProps->aidChannels[2] = PDMAUDIOCHANNELID_FRONT_CENTER;
+ pProps->aidChannels[3] = PDMAUDIOCHANNELID_REAR_LEFT;
+ pProps->aidChannels[4] = PDMAUDIOCHANNELID_REAR_RIGHT;
+ pProps->aidChannels[5] = PDMAUDIOCHANNELID_FRONT_LEFT_OF_CENTER;
+ pProps->aidChannels[6] = PDMAUDIOCHANNELID_FRONT_RIGHT_OF_CENTER;
+ pProps->aidChannels[7] = PDMAUDIOCHANNELID_SIDE_LEFT;
+ pProps->aidChannels[8] = PDMAUDIOCHANNELID_SIDE_RIGHT;
+ pProps->aidChannels[9] = PDMAUDIOCHANNELID_FRONT_LEFT_HEIGHT;
+ pProps->aidChannels[10]= PDMAUDIOCHANNELID_FRONT_RIGHT_HEIGHT;
+ break;
+ default:
+ AssertFailed();
+ cChannels = 12;
+ RT_FALL_THROUGH();
+ case 12: /* 11.1 */
+ pProps->aidChannels[0] = PDMAUDIOCHANNELID_FRONT_LEFT;
+ pProps->aidChannels[1] = PDMAUDIOCHANNELID_FRONT_RIGHT;
+ pProps->aidChannels[2] = PDMAUDIOCHANNELID_FRONT_CENTER;
+ pProps->aidChannels[3] = PDMAUDIOCHANNELID_LFE;
+ pProps->aidChannels[4] = PDMAUDIOCHANNELID_REAR_LEFT;
+ pProps->aidChannels[5] = PDMAUDIOCHANNELID_REAR_RIGHT;
+ pProps->aidChannels[6] = PDMAUDIOCHANNELID_FRONT_LEFT_OF_CENTER;
+ pProps->aidChannels[7] = PDMAUDIOCHANNELID_FRONT_RIGHT_OF_CENTER;
+ pProps->aidChannels[8] = PDMAUDIOCHANNELID_SIDE_LEFT;
+ pProps->aidChannels[9] = PDMAUDIOCHANNELID_SIDE_RIGHT;
+ pProps->aidChannels[10]= PDMAUDIOCHANNELID_FRONT_LEFT_HEIGHT;
+ pProps->aidChannels[11]= PDMAUDIOCHANNELID_FRONT_RIGHT_HEIGHT;
+ break;
+ case 0:
+ break;
+ }
+ AssertCompile(RT_ELEMENTS(pProps->aidChannels) >= 12);
+
+ while (cChannels < RT_ELEMENTS(pProps->aidChannels))
+ pProps->aidChannels[cChannels++] = PDMAUDIOCHANNELID_INVALID;
+}
+
+
+/**
+ * Initialize PCM audio properties.
+ */
+DECLINLINE(void) PDMAudioPropsInit(PPDMAUDIOPCMPROPS pProps, uint8_t cbSample, bool fSigned, uint8_t cChannels, uint32_t uHz)
+{
+ pProps->cbFrame = cbSample * cChannels;
+ pProps->cbSampleX = cbSample;
+ pProps->cChannelsX = cChannels;
+ pProps->cShiftX = PDMAUDIOPCMPROPS_MAKE_SHIFT_PARMS(cbSample, cChannels);
+ pProps->fSigned = fSigned;
+ pProps->fSwapEndian = false;
+ pProps->fRaw = false;
+ pProps->uHz = uHz;
+
+ Assert(pProps->cbFrame == (uint32_t)cbSample * cChannels);
+ Assert(pProps->cbSampleX == cbSample);
+ Assert(pProps->cChannelsX == cChannels);
+
+ PDMAudioPropsSetDefaultChannelIds(pProps);
+}
+
+/**
+ * Initialize PCM audio properties, extended version.
+ */
+DECLINLINE(void) PDMAudioPropsInitEx(PPDMAUDIOPCMPROPS pProps, uint8_t cbSample, bool fSigned, uint8_t cChannels, uint32_t uHz,
+ bool fLittleEndian, bool fRaw)
+{
+ Assert(!fRaw || cbSample == sizeof(int64_t));
+ pProps->cbFrame = cbSample * cChannels;
+ pProps->cbSampleX = cbSample;
+ pProps->cChannelsX = cChannels;
+ pProps->cShiftX = PDMAUDIOPCMPROPS_MAKE_SHIFT_PARMS(cbSample, cChannels);
+ pProps->fSigned = fSigned;
+#ifdef RT_LITTLE_ENDIAN
+ pProps->fSwapEndian = !fLittleEndian;
+#else
+ pProps->fSwapEndian = fLittleEndian;
+#endif
+ pProps->fRaw = fRaw;
+ pProps->uHz = uHz;
+
+ Assert(pProps->cbFrame == (uint32_t)cbSample * cChannels);
+ Assert(pProps->cbSampleX == cbSample);
+ Assert(pProps->cChannelsX == cChannels);
+
+ PDMAudioPropsSetDefaultChannelIds(pProps);
+}
+
+/**
+ * Modifies the channel count.
+ *
+ * @note This will reset the channel IDs to defaults.
+ *
+ * @param pProps The PCM properties to update.
+ * @param cChannels The new channel count.
+ */
+DECLINLINE(void) PDMAudioPropsSetChannels(PPDMAUDIOPCMPROPS pProps, uint8_t cChannels)
+{
+ Assert(cChannels > 0); Assert(cChannels < 16);
+ pProps->cChannelsX = cChannels;
+ pProps->cbFrame = pProps->cbSampleX * cChannels;
+ pProps->cShiftX = PDMAUDIOPCMPROPS_MAKE_SHIFT_PARMS(pProps->cbSampleX, cChannels);
+
+ PDMAudioPropsSetDefaultChannelIds(pProps);
+}
+
+/**
+ * Modifies the sample size.
+ *
+ * @param pProps The PCM properties to update.
+ * @param cbSample The new sample size (in bytes).
+ */
+DECLINLINE(void) PDMAudioPropsSetSampleSize(PPDMAUDIOPCMPROPS pProps, uint8_t cbSample)
+{
+ Assert(cbSample == 1 || cbSample == 2 || cbSample == 4 || cbSample == 8);
+ pProps->cbSampleX = cbSample;
+ pProps->cbFrame = cbSample * pProps->cChannelsX;
+ pProps->cShiftX = PDMAUDIOPCMPROPS_MAKE_SHIFT_PARMS(cbSample, pProps->cChannelsX);
+}
+
+/**
+ * Gets the bitrate.
+ *
+ * Divide the result by 8 to get the byte rate.
+ *
+ * @returns Bit rate.
+ * @param pProps PCM properties to calculate bitrate for.
+ */
+DECLINLINE(uint32_t) PDMAudioPropsGetBitrate(PCPDMAUDIOPCMPROPS pProps)
+{
+ Assert(pProps->cbFrame == pProps->cbSampleX * pProps->cChannelsX);
+ return pProps->cbFrame * pProps->uHz * 8;
+}
+
+/**
+ * Gets the number of channels.
+ * @returns The channel count.
+ * @param pProps The PCM properties.
+ */
+DECL_FORCE_INLINE(uint8_t) PDMAudioPropsChannels(PCPDMAUDIOPCMPROPS pProps)
+{
+ return pProps->cChannelsX;
+}
+
+/**
+ * Gets the sample size in bytes.
+ * @returns Number of bytes per sample.
+ * @param pProps The PCM properties.
+ */
+DECL_FORCE_INLINE(uint8_t) PDMAudioPropsSampleSize(PCPDMAUDIOPCMPROPS pProps)
+{
+ return pProps->cbSampleX;
+}
+
+/**
+ * Gets the sample size in bits.
+ * @returns Number of bits per sample.
+ * @param pProps The PCM properties.
+ */
+DECLINLINE(uint8_t) PDMAudioPropsSampleBits(PCPDMAUDIOPCMPROPS pProps)
+{
+ return pProps->cbSampleX * 8;
+}
+
+/**
+ * Gets the frame size in bytes.
+ * @returns Number of bytes per frame.
+ * @param pProps The PCM properties.
+ */
+DECL_FORCE_INLINE(uint8_t) PDMAudioPropsFrameSize(PCPDMAUDIOPCMPROPS pProps)
+{
+ return pProps->cbFrame;
+}
+
+/**
+ * Gets the frequency.
+ * @returns Frequency.
+ * @param pProps The PCM properties.
+ */
+DECL_FORCE_INLINE(uint32_t) PDMAudioPropsHz(PCPDMAUDIOPCMPROPS pProps)
+{
+ return pProps->uHz;
+}
+
+/**
+ * Checks if the format is signed or unsigned.
+ * @returns true if signed, false if unsigned.
+ * @param pProps The PCM properties.
+ */
+DECL_FORCE_INLINE(bool) PDMAudioPropsIsSigned(PCPDMAUDIOPCMPROPS pProps)
+{
+ return pProps->fSigned;
+}
+
+/**
+ * Checks if the format is little-endian or not.
+ * @returns true if little-endian (or if 8-bit), false if big-endian.
+ * @param pProps The PCM properties.
+ */
+DECL_FORCE_INLINE(bool) PDMAudioPropsIsLittleEndian(PCPDMAUDIOPCMPROPS pProps)
+{
+#ifdef RT_LITTLE_ENDIAN
+ return !pProps->fSwapEndian || pProps->cbSampleX < 2;
+#else
+ return pProps->fSwapEndian || pProps->cbSampleX < 2;
+#endif
+}
+
+/**
+ * Checks if the format is big-endian or not.
+ * @returns true if big-endian (or if 8-bit), false if little-endian.
+ * @param pProps The PCM properties.
+ */
+DECL_FORCE_INLINE(bool) PDMAudioPropsIsBigEndian(PCPDMAUDIOPCMPROPS pProps)
+{
+#ifdef RT_LITTLE_ENDIAN
+ return pProps->fSwapEndian || pProps->cbSampleX < 2;
+#else
+ return !pProps->fSwapEndian || pProps->cbSampleX < 2;
+#endif
+}
+
+/**
+ * Rounds down the given byte amount to the nearest frame boundrary.
+ *
+ * @returns Rounded byte amount.
+ * @param pProps PCM properties to use.
+ * @param cb The size (in bytes) to round.
+ */
+DECLINLINE(uint32_t) PDMAudioPropsFloorBytesToFrame(PCPDMAUDIOPCMPROPS pProps, uint32_t cb)
+{
+ AssertPtrReturn(pProps, 0);
+ return PDMAUDIOPCMPROPS_F2B(pProps, PDMAUDIOPCMPROPS_B2F(pProps, cb));
+}
+
+/**
+ * Rounds up the given byte amount to the nearest frame boundrary.
+ *
+ * @returns Rounded byte amount.
+ * @param pProps PCM properties to use.
+ * @param cb The size (in bytes) to round.
+ */
+DECLINLINE(uint32_t) PDMAudioPropsRoundUpBytesToFrame(PCPDMAUDIOPCMPROPS pProps, uint32_t cb)
+{
+ AssertPtrReturn(pProps, 0);
+ uint32_t const cbFrame = PDMAudioPropsFrameSize(pProps);
+ AssertReturn(cbFrame, 0);
+ return PDMAUDIOPCMPROPS_F2B(pProps, PDMAUDIOPCMPROPS_B2F(pProps, cb + cbFrame - 1));
+}
+
+/**
+ * Checks if the given size is aligned on a frame boundrary.
+ *
+ * @returns @c true if properly aligned, @c false if not.
+ * @param pProps PCM properties to use.
+ * @param cb The size (in bytes) to check.
+ */
+DECLINLINE(bool) PDMAudioPropsIsSizeAligned(PCPDMAUDIOPCMPROPS pProps, uint32_t cb)
+{
+ AssertPtrReturn(pProps, false);
+ uint32_t const cbFrame = PDMAudioPropsFrameSize(pProps);
+ AssertReturn(cbFrame, false);
+ return cb % cbFrame == 0;
+}
+
+/**
+ * Converts bytes to frames (rounding down of course).
+ *
+ * @returns Number of frames.
+ * @param pProps PCM properties to use.
+ * @param cb The number of bytes to convert.
+ */
+DECLINLINE(uint32_t) PDMAudioPropsBytesToFrames(PCPDMAUDIOPCMPROPS pProps, uint32_t cb)
+{
+ AssertPtrReturn(pProps, 0);
+ return PDMAUDIOPCMPROPS_B2F(pProps, cb);
+}
+
+/**
+ * Converts bytes to milliseconds.
+ *
+ * @return Number milliseconds @a cb takes to play or record.
+ * @param pProps PCM properties to use.
+ * @param cb The number of bytes to convert.
+ *
+ * @note Rounds up the result.
+ */
+DECLINLINE(uint64_t) PDMAudioPropsBytesToMilli(PCPDMAUDIOPCMPROPS pProps, uint32_t cb)
+{
+ AssertPtrReturn(pProps, 0);
+
+ /* Check parameters to prevent division by chainsaw: */
+ uint32_t const uHz = pProps->uHz;
+ if (uHz)
+ {
+ const unsigned cbFrame = PDMAudioPropsFrameSize(pProps);
+ if (cbFrame)
+ {
+ /* Round cb up to closest frame size: */
+ cb = (cb + cbFrame - 1) / cbFrame;
+
+ /* Convert to milliseconds. */
+ return (cb * (uint64_t)RT_MS_1SEC + uHz - 1) / uHz;
+ }
+ }
+ return 0;
+}
+
+/**
+ * Converts bytes to microseconds.
+ *
+ * @return Number microseconds @a cb takes to play or record.
+ * @param pProps PCM properties to use.
+ * @param cb The number of bytes to convert.
+ *
+ * @note Rounds up the result.
+ */
+DECLINLINE(uint64_t) PDMAudioPropsBytesToMicro(PCPDMAUDIOPCMPROPS pProps, uint32_t cb)
+{
+ AssertPtrReturn(pProps, 0);
+
+ /* Check parameters to prevent division by chainsaw: */
+ uint32_t const uHz = pProps->uHz;
+ if (uHz)
+ {
+ const unsigned cbFrame = PDMAudioPropsFrameSize(pProps);
+ if (cbFrame)
+ {
+ /* Round cb up to closest frame size: */
+ cb = (cb + cbFrame - 1) / cbFrame;
+
+ /* Convert to microseconds. */
+ return (cb * (uint64_t)RT_US_1SEC + uHz - 1) / uHz;
+ }
+ }
+ return 0;
+}
+
+/**
+ * Converts bytes to nanoseconds.
+ *
+ * @return Number nanoseconds @a cb takes to play or record.
+ * @param pProps PCM properties to use.
+ * @param cb The number of bytes to convert.
+ *
+ * @note Rounds up the result.
+ */
+DECLINLINE(uint64_t) PDMAudioPropsBytesToNano(PCPDMAUDIOPCMPROPS pProps, uint32_t cb)
+{
+ AssertPtrReturn(pProps, 0);
+
+ /* Check parameters to prevent division by chainsaw: */
+ uint32_t const uHz = pProps->uHz;
+ if (uHz)
+ {
+ const unsigned cbFrame = PDMAudioPropsFrameSize(pProps);
+ if (cbFrame)
+ {
+ /* Round cb up to closest frame size: */
+ cb = (cb + cbFrame - 1) / cbFrame;
+
+ /* Convert to nanoseconds. */
+ return (cb * (uint64_t)RT_NS_1SEC + uHz - 1) / uHz;
+ }
+ }
+ return 0;
+}
+
+/**
+ * Converts bytes to nanoseconds, 64-bit version.
+ *
+ * @return Number nanoseconds @a cb takes to play or record.
+ * @param pProps PCM properties to use.
+ * @param cb The number of bytes to convert (64-bit).
+ *
+ * @note Rounds up the result.
+ */
+DECLINLINE(uint64_t) PDMAudioPropsBytesToNano64(PCPDMAUDIOPCMPROPS pProps, uint64_t cb)
+{
+ AssertPtrReturn(pProps, 0);
+
+ /* Check parameters to prevent division by chainsaw: */
+ uint32_t const uHz = pProps->uHz;
+ if (uHz)
+ {
+ const unsigned cbFrame = PDMAudioPropsFrameSize(pProps);
+ if (cbFrame)
+ {
+ /* Round cb up to closest frame size: */
+ cb = (cb + cbFrame - 1) / cbFrame;
+
+ /* Convert to nanoseconds. */
+ return (cb * RT_NS_1SEC + uHz - 1) / uHz;
+ }
+ }
+ return 0;
+}
+
+/**
+ * Converts frames to bytes.
+ *
+ * @returns Number of bytes.
+ * @param pProps The PCM properties to use.
+ * @param cFrames Number of audio frames to convert.
+ * @sa PDMAUDIOPCMPROPS_F2B
+ */
+DECLINLINE(uint32_t) PDMAudioPropsFramesToBytes(PCPDMAUDIOPCMPROPS pProps, uint32_t cFrames)
+{
+ AssertPtrReturn(pProps, 0);
+ return PDMAUDIOPCMPROPS_F2B(pProps, cFrames);
+}
+
+/**
+ * Converts frames to milliseconds.
+ *
+ * @returns milliseconds.
+ * @param pProps The PCM properties to use.
+ * @param cFrames Number of audio frames to convert.
+ * @note No rounding here, result is floored.
+ */
+DECLINLINE(uint64_t) PDMAudioPropsFramesToMilli(PCPDMAUDIOPCMPROPS pProps, uint32_t cFrames)
+{
+ AssertPtrReturn(pProps, 0);
+
+ /* Check input to prevent division by chainsaw: */
+ uint32_t const uHz = pProps->uHz;
+ if (uHz)
+ return ASMMultU32ByU32DivByU32(cFrames, RT_MS_1SEC, uHz);
+ return 0;
+}
+
+/**
+ * Converts frames to milliseconds, but not returning more than @a cMsMax
+ *
+ * This is a convenience for logging and such.
+ *
+ * @returns milliseconds (32-bit).
+ * @param pProps The PCM properties to use.
+ * @param cFrames Number of audio frames to convert.
+ * @param cMsMax Max return value (32-bit).
+ * @note No rounding here, result is floored.
+ */
+DECLINLINE(uint32_t) PDMAudioPropsFramesToMilliMax(PCPDMAUDIOPCMPROPS pProps, uint32_t cFrames, uint32_t cMsMax)
+{
+ AssertPtrReturn(pProps, 0);
+
+ /* Check input to prevent division by chainsaw: */
+ uint32_t const uHz = pProps->uHz;
+ if (uHz)
+ {
+ uint32_t const cMsResult = ASMMultU32ByU32DivByU32(cFrames, RT_MS_1SEC, uHz);
+ return RT_MIN(cMsResult, cMsMax);
+ }
+ return 0;
+}
+
+/**
+ * Converts frames to microseconds.
+ *
+ * @returns microseconds.
+ * @param pProps The PCM properties to use.
+ * @param cFrames Number of audio frames to convert.
+ * @note No rounding here, result is floored.
+ */
+DECLINLINE(uint64_t) PDMAudioPropsFramesToMicro(PCPDMAUDIOPCMPROPS pProps, uint32_t cFrames)
+{
+ AssertPtrReturn(pProps, 0);
+
+ /* Check input to prevent division by chainsaw: */
+ uint32_t const uHz = pProps->uHz;
+ if (uHz)
+ return ASMMultU32ByU32DivByU32(cFrames, RT_US_1SEC, uHz);
+ return 0;
+}
+
+/**
+ * Converts frames to nanoseconds.
+ *
+ * @returns Nanoseconds.
+ * @param pProps The PCM properties to use.
+ * @param cFrames Number of audio frames to convert.
+ * @note No rounding here, result is floored.
+ */
+DECLINLINE(uint64_t) PDMAudioPropsFramesToNano(PCPDMAUDIOPCMPROPS pProps, uint32_t cFrames)
+{
+ AssertPtrReturn(pProps, 0);
+
+ /* Check input to prevent division by chainsaw: */
+ uint32_t const uHz = pProps->uHz;
+ if (uHz)
+ return ASMMultU32ByU32DivByU32(cFrames, RT_NS_1SEC, uHz);
+ return 0;
+}
+
+/**
+ * Converts frames to NT ticks (100 ns units).
+ *
+ * @returns NT ticks.
+ * @param pProps The PCM properties to use.
+ * @param cFrames Number of audio frames to convert.
+ * @note No rounding here, result is floored.
+ */
+DECLINLINE(uint64_t) PDMAudioPropsFramesToNtTicks(PCPDMAUDIOPCMPROPS pProps, uint32_t cFrames)
+{
+ AssertPtrReturn(pProps, 0);
+
+ /* Check input to prevent division by chainsaw: */
+ uint32_t const uHz = pProps->uHz;
+ if (uHz)
+ return ASMMultU32ByU32DivByU32(cFrames, RT_NS_1SEC / 100, uHz);
+ return 0;
+}
+
+/**
+ * Converts milliseconds to frames.
+ *
+ * @returns Number of frames
+ * @param pProps The PCM properties to use.
+ * @param cMs The number of milliseconds to convert.
+ *
+ * @note The result is rounded rather than floored (hysterical raisins).
+ */
+DECLINLINE(uint32_t) PDMAudioPropsMilliToFrames(PCPDMAUDIOPCMPROPS pProps, uint64_t cMs)
+{
+ AssertPtrReturn(pProps, 0);
+
+ uint32_t const uHz = pProps->uHz;
+ uint32_t cFrames;
+ if (cMs < RT_MS_1SEC)
+ cFrames = 0;
+ else
+ {
+ cFrames = cMs / RT_MS_1SEC * uHz;
+ cMs %= RT_MS_1SEC;
+ }
+ cFrames += (ASMMult2xU32RetU64(uHz, (uint32_t)cMs) + RT_MS_1SEC - 1) / RT_MS_1SEC;
+ return cFrames;
+}
+
+/**
+ * Converts milliseconds to bytes.
+ *
+ * @returns Number of bytes (frame aligned).
+ * @param pProps The PCM properties to use.
+ * @param cMs The number of milliseconds to convert.
+ *
+ * @note The result is rounded rather than floored (hysterical raisins).
+ */
+DECLINLINE(uint32_t) PDMAudioPropsMilliToBytes(PCPDMAUDIOPCMPROPS pProps, uint64_t cMs)
+{
+ return PDMAUDIOPCMPROPS_F2B(pProps, PDMAudioPropsMilliToFrames(pProps, cMs));
+}
+
+/**
+ * Converts nanoseconds to frames.
+ *
+ * @returns Number of frames.
+ * @param pProps The PCM properties to use.
+ * @param cNs The number of nanoseconds to convert.
+ *
+ * @note The result is rounded rather than floored (hysterical raisins).
+ */
+DECLINLINE(uint32_t) PDMAudioPropsNanoToFrames(PCPDMAUDIOPCMPROPS pProps, uint64_t cNs)
+{
+ AssertPtrReturn(pProps, 0);
+
+ uint32_t const uHz = pProps->uHz;
+ uint32_t cFrames;
+ if (cNs < RT_NS_1SEC)
+ cFrames = 0;
+ else
+ {
+ cFrames = cNs / RT_NS_1SEC * uHz;
+ cNs %= RT_NS_1SEC;
+ }
+ cFrames += (ASMMult2xU32RetU64(uHz, (uint32_t)cNs) + RT_NS_1SEC - 1) / RT_NS_1SEC;
+ return cFrames;
+}
+
+/**
+ * Converts nanoseconds to frames, 64-bit return.
+ *
+ * @returns Number of frames (64-bit).
+ * @param pProps The PCM properties to use.
+ * @param cNs The number of nanoseconds to convert.
+ *
+ * @note The result is floored!
+ */
+DECLINLINE(uint64_t) PDMAudioPropsNanoToFrames64(PCPDMAUDIOPCMPROPS pProps, uint64_t cNs)
+{
+ AssertPtrReturn(pProps, 0);
+
+ uint32_t const uHz = pProps->uHz;
+ uint64_t cFrames;
+ if (cNs < RT_NS_1SEC)
+ cFrames = 0;
+ else
+ {
+ cFrames = cNs / RT_NS_1SEC * uHz;
+ cNs %= RT_NS_1SEC;
+ }
+ cFrames += ASMMult2xU32RetU64(uHz, (uint32_t)cNs) / RT_NS_1SEC;
+ return cFrames;
+}
+
+/**
+ * Converts nanoseconds to bytes.
+ *
+ * @returns Number of bytes (frame aligned).
+ * @param pProps The PCM properties to use.
+ * @param cNs The number of nanoseconds to convert.
+ *
+ * @note The result is rounded rather than floored (hysterical raisins).
+ */
+DECLINLINE(uint32_t) PDMAudioPropsNanoToBytes(PCPDMAUDIOPCMPROPS pProps, uint64_t cNs)
+{
+ return PDMAUDIOPCMPROPS_F2B(pProps, PDMAudioPropsNanoToFrames(pProps, cNs));
+}
+
+/**
+ * Converts nanoseconds to bytes, 64-bit version.
+ *
+ * @returns Number of bytes (frame aligned), 64-bit.
+ * @param pProps The PCM properties to use.
+ * @param cNs The number of nanoseconds to convert.
+ *
+ * @note The result is floored.
+ */
+DECLINLINE(uint64_t) PDMAudioPropsNanoToBytes64(PCPDMAUDIOPCMPROPS pProps, uint64_t cNs)
+{
+ return PDMAUDIOPCMPROPS_F2B(pProps, PDMAudioPropsNanoToFrames(pProps, cNs));
+}
+
+/**
+ * Clears a sample buffer by the given amount of audio frames with silence (according to the format
+ * given by the PCM properties).
+ *
+ * @param pProps The PCM properties to apply.
+ * @param pvBuf The buffer to clear.
+ * @param cbBuf The buffer size in bytes.
+ * @param cFrames The number of audio frames to clear. Capped at @a cbBuf
+ * if exceeding the buffer. If the size is an unaligned
+ * number of frames, the extra bytes may be left
+ * uninitialized in some configurations.
+ */
+DECLINLINE(void) PDMAudioPropsClearBuffer(PCPDMAUDIOPCMPROPS pProps, void *pvBuf, size_t cbBuf, uint32_t cFrames)
+{
+ /*
+ * Validate input
+ */
+ AssertPtrReturnVoid(pProps);
+ Assert(pProps->cbSampleX);
+ if (!cbBuf || !cFrames)
+ return;
+ AssertPtrReturnVoid(pvBuf);
+
+ /*
+ * Decide how much needs clearing.
+ */
+ size_t cbToClear = PDMAudioPropsFramesToBytes(pProps, cFrames);
+ AssertStmt(cbToClear <= cbBuf, cbToClear = cbBuf);
+
+ Log2Func(("pProps=%p, pvBuf=%p, cFrames=%RU32, fSigned=%RTbool, cbSample=%RU8\n",
+ pProps, pvBuf, cFrames, pProps->fSigned, pProps->cbSampleX));
+
+ /*
+ * Do the job.
+ */
+ if (pProps->fSigned)
+ RT_BZERO(pvBuf, cbToClear);
+ else /* Unsigned formats. */
+ {
+ switch (pProps->cbSampleX)
+ {
+ case 1: /* 8 bit */
+ memset(pvBuf, 0x80, cbToClear);
+ break;
+
+ case 2: /* 16 bit */
+ {
+ uint16_t *pu16Dst = (uint16_t *)pvBuf;
+ uint16_t const u16Offset = !pProps->fSwapEndian ? UINT16_C(0x8000) : UINT16_C(0x80);
+ cbBuf /= sizeof(*pu16Dst);
+ while (cbBuf-- > 0)
+ *pu16Dst++ = u16Offset;
+ break;
+ }
+
+ case 4: /* 32 bit */
+ ASMMemFill32(pvBuf, cbToClear & ~(size_t)(sizeof(uint32_t) - 1),
+ !pProps->fSwapEndian ? UINT32_C(0x80000000) : UINT32_C(0x80));
+ break;
+
+ default:
+ AssertMsgFailed(("Invalid bytes per sample: %RU8\n", pProps->cbSampleX));
+ }
+ }
+}
+
+/**
+ * Checks if the given buffer is silence.
+ *
+ * @param pProps The PCM properties to use checking the buffer.
+ * @param pvBuf The buffer to check.
+ * @param cbBuf The number of bytes to check (must be frame aligned).
+ */
+DECLINLINE(bool) PDMAudioPropsIsBufferSilence(PCPDMAUDIOPCMPROPS pProps, void const *pvBuf, size_t cbBuf)
+{
+ /*
+ * Validate input
+ */
+ AssertPtrReturn(pProps, false);
+ if (!cbBuf)
+ return false;
+ AssertPtrReturn(pvBuf, false);
+
+ /*
+ * Do the job.
+ */
+ if (pProps->fSigned)
+ return ASMMemIsZero(pvBuf, cbBuf);
+
+ switch (pProps->cbSampleX)
+ {
+ case 1: /* 8 bit */
+ return ASMMemIsAllU8(pvBuf, cbBuf, 0x80);
+
+ case 2: /* 16 bit */
+ {
+ uint16_t const *pu16 = (uint16_t const *)pvBuf;
+ uint16_t const u16Offset = !pProps->fSwapEndian ? UINT16_C(0x8000) : UINT16_C(0x80);
+ cbBuf /= sizeof(*pu16);
+ while (cbBuf-- > 0)
+ if (*pu16 != u16Offset)
+ return false;
+ return true;
+ }
+
+ case 4: /* 32 bit */
+ {
+ uint32_t const *pu32 = (uint32_t const *)pvBuf;
+ uint32_t const u32Offset = !pProps->fSwapEndian ? UINT32_C(0x80000000) : UINT32_C(0x80);
+ cbBuf /= sizeof(*pu32);
+ while (cbBuf-- > 0)
+ if (*pu32 != u32Offset)
+ return false;
+ return true;
+ }
+
+ default:
+ AssertMsgFailed(("Invalid bytes per sample: %RU8\n", pProps->cbSampleX));
+ return false;
+ }
+}
+
+/**
+ * Compares two sets of PCM properties.
+ *
+ * @returns @c true if the same, @c false if not.
+ * @param pProps1 The first set of properties to compare.
+ * @param pProps2 The second set of properties to compare.
+ */
+DECLINLINE(bool) PDMAudioPropsAreEqual(PCPDMAUDIOPCMPROPS pProps1, PCPDMAUDIOPCMPROPS pProps2)
+{
+ uintptr_t idxCh;
+ AssertPtrReturn(pProps1, false);
+ AssertPtrReturn(pProps2, false);
+
+ if (pProps1 == pProps2) /* If the pointers match, take a shortcut. */
+ return true;
+
+ if (pProps1->uHz != pProps2->uHz)
+ return false;
+ if (pProps1->cChannelsX != pProps2->cChannelsX)
+ return false;
+ if (pProps1->cbSampleX != pProps2->cbSampleX)
+ return false;
+ if (pProps1->fSigned != pProps2->fSigned)
+ return false;
+ if (pProps1->fSwapEndian != pProps2->fSwapEndian)
+ return false;
+ if (pProps1->fRaw != pProps2->fRaw)
+ return false;
+
+ idxCh = pProps1->cChannelsX;
+ while (idxCh-- > 0)
+ if (pProps1->aidChannels[idxCh] != pProps2->aidChannels[idxCh])
+ return false;
+
+ return true;
+}
+
+/**
+ * Checks whether the given PCM properties are valid or not.
+ *
+ * @returns true/false accordingly.
+ * @param pProps The PCM properties to check.
+ *
+ * @remarks This just performs a generic check of value ranges.
+ *
+ * @sa PDMAudioStrmCfgIsValid
+ */
+DECLINLINE(bool) PDMAudioPropsAreValid(PCPDMAUDIOPCMPROPS pProps)
+{
+ AssertPtrReturn(pProps, false);
+
+ /* Channels. */
+ if ( pProps->cChannelsX != 0
+ && pProps->cChannelsX <= PDMAUDIO_MAX_CHANNELS
+ /* Sample size. */
+ && ( pProps->cbSampleX == 1
+ || pProps->cbSampleX == 2
+ || pProps->cbSampleX == 4
+ || (pProps->cbSampleX == 8 && pProps->fRaw))
+ /* Hertz rate. */
+ && pProps->uHz >= 1000
+ && pProps->uHz < 1000000
+ /* Raw format: Here we only support int64_t as sample size currently, if enabled. */
+ && ( !pProps->fRaw
+ || (pProps->fSigned && pProps->cbSampleX == sizeof(int64_t)))
+ )
+ {
+ /* A few more sanity checks to see if the structure has been properly initialized (via PDMAudioPropsInit[Ex]). */
+ AssertMsgReturn(pProps->cShiftX == PDMAUDIOPCMPROPS_MAKE_SHIFT(pProps),
+ ("cShift=%u cbSample=%u cChannels=%u\n", pProps->cShiftX, pProps->cbSampleX, pProps->cChannelsX),
+ false);
+ AssertMsgReturn(pProps->cbFrame == pProps->cbSampleX * pProps->cChannelsX,
+ ("cbFrame=%u cbSample=%u cChannels=%u\n", pProps->cbFrame, pProps->cbSampleX, pProps->cChannelsX),
+ false);
+
+ return true;
+ }
+
+ return false;
+}
+
+/**
+ * Get number of bytes per frame.
+ *
+ * @returns Number of bytes per audio frame.
+ * @param pProps PCM properties to use.
+ * @sa PDMAUDIOPCMPROPS_F2B
+ */
+DECLINLINE(uint32_t) PDMAudioPropsBytesPerFrame(PCPDMAUDIOPCMPROPS pProps)
+{
+ return PDMAUDIOPCMPROPS_F2B(pProps, 1 /*cFrames*/);
+}
+
+/**
+ * Prints PCM properties to the debug log.
+ *
+ * @param pProps PCM properties to use.
+ */
+DECLINLINE(void) PDMAudioPropsLog(PCPDMAUDIOPCMPROPS pProps)
+{
+ AssertPtrReturnVoid(pProps);
+
+ Log(("uHz=%RU32, cChannels=%RU8, cBits=%RU8%s",
+ pProps->uHz, pProps->cChannelsX, pProps->cbSampleX * 8, pProps->fSigned ? "S" : "U"));
+}
+
+/** Max necessary buffer space for PDMAudioPropsToString */
+#define PDMAUDIOPROPSTOSTRING_MAX sizeof("16ch S64 4294967296Hz swap raw")
+
+/**
+ * Formats the PCM audio properties into a string buffer.
+ *
+ * @returns pszDst
+ * @param pProps PCM properties to use.
+ * @param pszDst The destination buffer.
+ * @param cchDst The size of the destination buffer. Recommended to be at
+ * least PDMAUDIOPROPSTOSTRING_MAX bytes.
+ */
+DECLINLINE(char *) PDMAudioPropsToString(PCPDMAUDIOPCMPROPS pProps, char *pszDst, size_t cchDst)
+{
+ /* 2ch S64 44100Hz swap raw */
+ RTStrPrintf(pszDst, cchDst, "%uch %c%u %RU32Hz%s%s",
+ PDMAudioPropsChannels(pProps), PDMAudioPropsIsSigned(pProps) ? 'S' : 'U', PDMAudioPropsSampleBits(pProps),
+ PDMAudioPropsHz(pProps), pProps->fSwapEndian ? " swap" : "", pProps->fRaw ? " raw" : "");
+ return pszDst;
+}
+
+
+/*********************************************************************************************************************************
+* Stream Configuration Helpers *
+*********************************************************************************************************************************/
+
+/**
+ * Initializes a stream configuration from PCM properties.
+ *
+ * @returns VBox status code.
+ * @param pCfg The stream configuration to initialize.
+ * @param pProps The PCM properties to use.
+ */
+DECLINLINE(int) PDMAudioStrmCfgInitWithProps(PPDMAUDIOSTREAMCFG pCfg, PCPDMAUDIOPCMPROPS pProps)
+{
+ AssertPtrReturn(pProps, VERR_INVALID_POINTER);
+ AssertPtrReturn(pCfg, VERR_INVALID_POINTER);
+
+ RT_ZERO(*pCfg);
+ pCfg->Backend.cFramesPreBuffering = UINT32_MAX; /* Explicitly set to "undefined". */
+
+ memcpy(&pCfg->Props, pProps, sizeof(PDMAUDIOPCMPROPS));
+
+ return VINF_SUCCESS;
+}
+
+/**
+ * Checks whether stream configuration matches the given PCM properties.
+ *
+ * @returns @c true if equal, @c false if not.
+ * @param pCfg The stream configuration.
+ * @param pProps The PCM properties to match with.
+ */
+DECLINLINE(bool) PDMAudioStrmCfgMatchesProps(PCPDMAUDIOSTREAMCFG pCfg, PCPDMAUDIOPCMPROPS pProps)
+{
+ AssertPtrReturn(pCfg, false);
+ return PDMAudioPropsAreEqual(pProps, &pCfg->Props);
+}
+
+/**
+ * Checks whether two stream configuration matches.
+ *
+ * @returns @c true if equal, @c false if not.
+ * @param pCfg1 The first stream configuration.
+ * @param pCfg2 The second stream configuration.
+ */
+DECLINLINE(bool) PDMAudioStrmCfgEquals(PCPDMAUDIOSTREAMCFG pCfg1, PCPDMAUDIOSTREAMCFG pCfg2)
+{
+ if (!pCfg1 || !pCfg2)
+ return false;
+ if (pCfg1 == pCfg2)
+ return pCfg1 != NULL;
+ if (PDMAudioPropsAreEqual(&pCfg1->Props, &pCfg2->Props))
+ return pCfg1->enmDir == pCfg2->enmDir
+ && pCfg1->enmPath == pCfg2->enmPath
+ && pCfg1->Device.cMsSchedulingHint == pCfg2->Device.cMsSchedulingHint
+ && pCfg1->Backend.cFramesPeriod == pCfg2->Backend.cFramesPeriod
+ && pCfg1->Backend.cFramesBufferSize == pCfg2->Backend.cFramesBufferSize
+ && pCfg1->Backend.cFramesPreBuffering == pCfg2->Backend.cFramesPreBuffering
+ && strcmp(pCfg1->szName, pCfg2->szName) == 0;
+ return false;
+}
+
+/**
+ * Frees an audio stream allocated by PDMAudioStrmCfgDup().
+ *
+ * @param pCfg The stream configuration to free.
+ */
+DECLINLINE(void) PDMAudioStrmCfgFree(PPDMAUDIOSTREAMCFG pCfg)
+{
+ if (pCfg)
+ RTMemFree(pCfg);
+}
+
+/**
+ * Checks whether the given stream configuration is valid or not.
+ *
+ * @returns true/false accordingly.
+ * @param pCfg Stream configuration to check.
+ *
+ * @remarks This just performs a generic check of value ranges. Further, it
+ * will assert if the input is invalid.
+ *
+ * @sa PDMAudioPropsAreValid
+ */
+DECLINLINE(bool) PDMAudioStrmCfgIsValid(PCPDMAUDIOSTREAMCFG pCfg)
+{
+ AssertPtrReturn(pCfg, false);
+ AssertMsgReturn(pCfg->enmDir >= PDMAUDIODIR_UNKNOWN && pCfg->enmDir < PDMAUDIODIR_END, ("%d\n", pCfg->enmDir), false);
+ return PDMAudioPropsAreValid(&pCfg->Props);
+}
+
+/**
+ * Copies one stream configuration to another.
+ *
+ * @returns VBox status code.
+ * @param pDstCfg The destination stream configuration.
+ * @param pSrcCfg The source stream configuration.
+ */
+DECLINLINE(int) PDMAudioStrmCfgCopy(PPDMAUDIOSTREAMCFG pDstCfg, PCPDMAUDIOSTREAMCFG pSrcCfg)
+{
+ AssertPtrReturn(pDstCfg, VERR_INVALID_POINTER);
+ AssertPtrReturn(pSrcCfg, VERR_INVALID_POINTER);
+
+ /* This used to be VBOX_STRICT only and return VERR_INVALID_PARAMETER, but
+ that's making release builds work differently from debug & strict builds,
+ which is a terrible idea: */
+ Assert(PDMAudioStrmCfgIsValid(pSrcCfg));
+
+ memcpy(pDstCfg, pSrcCfg, sizeof(PDMAUDIOSTREAMCFG));
+
+ return VINF_SUCCESS;
+}
+
+/**
+ * Duplicates an audio stream configuration.
+ *
+ * @returns Pointer to duplicate on success, NULL on failure. Must be freed
+ * using PDMAudioStrmCfgFree().
+ *
+ * @param pCfg The audio stream configuration to duplicate.
+ */
+DECLINLINE(PPDMAUDIOSTREAMCFG) PDMAudioStrmCfgDup(PCPDMAUDIOSTREAMCFG pCfg)
+{
+ AssertPtrReturn(pCfg, NULL);
+
+ PPDMAUDIOSTREAMCFG pDst = (PPDMAUDIOSTREAMCFG)RTMemAllocZ(sizeof(PDMAUDIOSTREAMCFG));
+ if (pDst)
+ {
+ int rc = PDMAudioStrmCfgCopy(pDst, pCfg);
+ if (RT_SUCCESS(rc))
+ return pDst;
+
+ PDMAudioStrmCfgFree(pDst);
+ }
+ return NULL;
+}
+
+/**
+ * Logs an audio stream configuration.
+ *
+ * @param pCfg The stream configuration to log.
+ */
+DECLINLINE(void) PDMAudioStrmCfgLog(PCPDMAUDIOSTREAMCFG pCfg)
+{
+ if (pCfg)
+ LogFunc(("szName=%s enmDir=%RU32 uHz=%RU32 cBits=%RU8%s cChannels=%RU8\n", pCfg->szName, pCfg->enmDir,
+ pCfg->Props.uHz, pCfg->Props.cbSampleX * 8, pCfg->Props.fSigned ? "S" : "U", pCfg->Props.cChannelsX));
+}
+
+/**
+ * Converts a stream command enum value to a string.
+ *
+ * @returns Pointer to read-only stream command name on success,
+ * "bad" if invalid command value.
+ * @param enmCmd The stream command to name.
+ */
+DECLINLINE(const char *) PDMAudioStrmCmdGetName(PDMAUDIOSTREAMCMD enmCmd)
+{
+ switch (enmCmd)
+ {
+ case PDMAUDIOSTREAMCMD_INVALID: return "Invalid";
+ case PDMAUDIOSTREAMCMD_ENABLE: return "Enable";
+ case PDMAUDIOSTREAMCMD_DISABLE: return "Disable";
+ case PDMAUDIOSTREAMCMD_PAUSE: return "Pause";
+ case PDMAUDIOSTREAMCMD_RESUME: return "Resume";
+ case PDMAUDIOSTREAMCMD_DRAIN: return "Drain";
+ case PDMAUDIOSTREAMCMD_END:
+ case PDMAUDIOSTREAMCMD_32BIT_HACK:
+ break;
+ /* no default! */
+ }
+ AssertMsgFailedReturn(("Invalid stream command %d\n", enmCmd), "bad");
+}
+
+/** Max necessary buffer space for PDMAudioStrmCfgToString */
+#define PDMAUDIOSTRMCFGTOSTRING_MAX \
+ sizeof("'01234567890123456789012345678901234567890123456789012345678901234' unknown 16ch S64 4294967295Hz swap raw, 9999999ms buffer, 9999999ms period, 9999999ms pre-buffer, 4294967295ms sched, center-lfe")
+
+/**
+ * Formats an audio stream configuration.
+ *
+ * @param pCfg The stream configuration to stringify.
+ * @param pszDst The destination buffer.
+ * @param cbDst The size of the destination buffer. Recommend this be
+ * at least PDMAUDIOSTRMCFGTOSTRING_MAX bytes.
+ */
+DECLINLINE(const char *) PDMAudioStrmCfgToString(PCPDMAUDIOSTREAMCFG pCfg, char *pszDst, size_t cbDst)
+{
+ /* 'front' output 2ch 44100Hz raw, 300ms buffer, 75ms period, 150ms pre-buffer, 10ms sched */
+ RTStrPrintf(pszDst, cbDst,
+ "'%s' %s %uch %c%u %RU32Hz%s%s, %RU32ms buffer, %RU32ms period, %RU32ms pre-buffer, %RU32ms sched%s%s",
+ pCfg->szName, PDMAudioDirGetName(pCfg->enmDir), PDMAudioPropsChannels(&pCfg->Props),
+ PDMAudioPropsIsSigned(&pCfg->Props) ? 'S' : 'U', PDMAudioPropsSampleBits(&pCfg->Props),
+ PDMAudioPropsHz(&pCfg->Props), pCfg->Props.fSwapEndian ? " swap" : "", pCfg->Props.fRaw ? " raw" : "",
+ PDMAudioPropsFramesToMilliMax(&pCfg->Props, pCfg->Backend.cFramesBufferSize, 9999999),
+ PDMAudioPropsFramesToMilliMax(&pCfg->Props, pCfg->Backend.cFramesPeriod, 9999999),
+ PDMAudioPropsFramesToMilliMax(&pCfg->Props, pCfg->Backend.cFramesPreBuffering, 9999999),
+ pCfg->Device.cMsSchedulingHint,
+ pCfg->enmPath == PDMAUDIOPATH_UNKNOWN ? "" : ", ",
+ pCfg->enmPath == PDMAUDIOPATH_UNKNOWN ? "" : PDMAudioPathGetName(pCfg->enmPath) );
+ return pszDst;
+}
+
+
+/*********************************************************************************************************************************
+* Stream Status Helpers *
+*********************************************************************************************************************************/
+
+/**
+ * Converts a audio stream state enum value to a string.
+ *
+ * @returns Pointer to read-only audio stream state string on success,
+ * "illegal" if invalid command value.
+ * @param enmStreamState The state to convert.
+ */
+DECLINLINE(const char *) PDMAudioStreamStateGetName(PDMAUDIOSTREAMSTATE enmStreamState)
+{
+ switch (enmStreamState)
+ {
+ case PDMAUDIOSTREAMSTATE_INVALID: return "invalid";
+ case PDMAUDIOSTREAMSTATE_NOT_WORKING: return "not-working";
+ case PDMAUDIOSTREAMSTATE_NEED_REINIT: return "need-reinit";
+ case PDMAUDIOSTREAMSTATE_INACTIVE: return "inactive";
+ case PDMAUDIOSTREAMSTATE_ENABLED: return "enabled";
+ case PDMAUDIOSTREAMSTATE_ENABLED_READABLE: return "enabled-readable";
+ case PDMAUDIOSTREAMSTATE_ENABLED_WRITABLE: return "enabled-writable";
+ /* no default: */
+ case PDMAUDIOSTREAMSTATE_END:
+ case PDMAUDIOSTREAMSTATE_32BIT_HACK:
+ break;
+ }
+ AssertMsgFailedReturn(("Invalid audio stream state: %d\n", enmStreamState), "illegal");
+}
+
+/**
+ * Converts a host audio (backend) stream state enum value to a string.
+ *
+ * @returns Pointer to read-only host audio stream state string on success,
+ * "illegal" if invalid command value.
+ * @param enmHostAudioStreamState The state to convert.
+ */
+DECLINLINE(const char *) PDMHostAudioStreamStateGetName(PDMHOSTAUDIOSTREAMSTATE enmHostAudioStreamState)
+{
+ switch (enmHostAudioStreamState)
+ {
+ case PDMHOSTAUDIOSTREAMSTATE_INVALID: return "invalid";
+ case PDMHOSTAUDIOSTREAMSTATE_INITIALIZING: return "initializing";
+ case PDMHOSTAUDIOSTREAMSTATE_NOT_WORKING: return "not-working";
+ case PDMHOSTAUDIOSTREAMSTATE_OKAY: return "okay";
+ case PDMHOSTAUDIOSTREAMSTATE_DRAINING: return "draining";
+ case PDMHOSTAUDIOSTREAMSTATE_INACTIVE: return "inactive";
+ /* no default: */
+ case PDMHOSTAUDIOSTREAMSTATE_END:
+ case PDMHOSTAUDIOSTREAMSTATE_32BIT_HACK:
+ break;
+ }
+ AssertMsgFailedReturn(("Invalid host audio stream state: %d\n", enmHostAudioStreamState), "illegal");
+}
+
+/** @} */
+
+#endif /* !VBOX_INCLUDED_vmm_pdmaudioinline_h */
diff --git a/include/VBox/vmm/pdmblkcache.h b/include/VBox/vmm/pdmblkcache.h
new file mode 100644
index 00000000..c9ff51d1
--- /dev/null
+++ b/include/VBox/vmm/pdmblkcache.h
@@ -0,0 +1,432 @@
+/** @file
+ * PDM - Pluggable Device Manager, Block cache.
+ */
+
+/*
+ * Copyright (C) 2007-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vmm_pdmblkcache_h
+#define VBOX_INCLUDED_vmm_pdmblkcache_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/types.h>
+#include <iprt/sg.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_pdm_blk_cache The PDM Block Cache API
+ * @ingroup grp_pdm
+ * @{
+ */
+
+/** Pointer to a PDM block cache. */
+typedef struct PDMBLKCACHE *PPDMBLKCACHE;
+/** Pointer to a PDM block cache pointer. */
+typedef PPDMBLKCACHE *PPPDMBLKCACHE;
+
+/** I/O transfer handle. */
+typedef struct PDMBLKCACHEIOXFER *PPDMBLKCACHEIOXFER;
+
+/**
+ * Block cache I/O request transfer direction.
+ */
+typedef enum PDMBLKCACHEXFERDIR
+{
+ /** Read */
+ PDMBLKCACHEXFERDIR_READ = 0,
+ /** Write */
+ PDMBLKCACHEXFERDIR_WRITE,
+ /** Flush */
+ PDMBLKCACHEXFERDIR_FLUSH,
+ /** Discard */
+ PDMBLKCACHEXFERDIR_DISCARD
+} PDMBLKCACHEXFERDIR;
+
+/**
+ * Completion callback for drivers.
+ *
+ * @param pDrvIns The driver instance.
+ * @param pvUser User argument given during request initiation.
+ * @param rc The status code of the completed request.
+ */
+typedef DECLCALLBACKTYPE(void, FNPDMBLKCACHEXFERCOMPLETEDRV,(PPDMDRVINS pDrvIns, void *pvUser, int rc));
+/** Pointer to a FNPDMBLKCACHEXFERCOMPLETEDRV(). */
+typedef FNPDMBLKCACHEXFERCOMPLETEDRV *PFNPDMBLKCACHEXFERCOMPLETEDRV;
+
+/**
+ * I/O enqueue callback for drivers.
+ *
+ * @param pDrvIns The driver instance.
+ * @param enmXferDir Transfer direction.
+ * @param off Transfer offset.
+ * @param cbXfer Transfer size.
+ * @param pSgBuf Scather / gather buffer for the transfer.
+ * @param hIoXfer I/O transfer handle to ping on completion.
+ */
+typedef DECLCALLBACKTYPE(int, FNPDMBLKCACHEXFERENQUEUEDRV,(PPDMDRVINS pDrvIns, PDMBLKCACHEXFERDIR enmXferDir, uint64_t off,
+ size_t cbXfer, PCRTSGBUF pSgBuf, PPDMBLKCACHEIOXFER hIoXfer));
+/** Pointer to a FNPDMBLKCACHEXFERENQUEUEDRV(). */
+typedef FNPDMBLKCACHEXFERENQUEUEDRV *PFNPDMBLKCACHEXFERENQUEUEDRV;
+
+/**
+ * Discard enqueue callback for drivers.
+ *
+ * @param pDrvIns The driver instance.
+ * @param paRanges Ranges to discard.
+ * @param cRanges Number of range entries.
+ * @param hIoXfer I/O handle to return on completion.
+ */
+typedef DECLCALLBACKTYPE(int, FNPDMBLKCACHEXFERENQUEUEDISCARDDRV,(PPDMDRVINS pDrvIns, PCRTRANGE paRanges, unsigned cRanges,
+ PPDMBLKCACHEIOXFER hIoXfer));
+/** Pointer to a FNPDMBLKCACHEXFERENQUEUEDISCARDDRV(). */
+typedef FNPDMBLKCACHEXFERENQUEUEDISCARDDRV *PFNPDMBLKCACHEXFERENQUEUEDISCARDDRV;
+
+/**
+ * Completion callback for devices.
+ *
+ * @param pDevIns The device instance.
+ * @param pvUser User argument given during request initiation.
+ * @param rc The status code of the completed request.
+ */
+typedef DECLCALLBACKTYPE(void, FNPDMBLKCACHEXFERCOMPLETEDEV,(PPDMDEVINS pDevIns, void *pvUser, int rc));
+/** Pointer to a FNPDMBLKCACHEXFERCOMPLETEDEV(). */
+typedef FNPDMBLKCACHEXFERCOMPLETEDEV *PFNPDMBLKCACHEXFERCOMPLETEDEV;
+
+/**
+ * I/O enqueue callback for devices.
+ *
+ * @param pDevIns The device instance.
+ * @param enmXferDir Transfer direction.
+ * @param off Transfer offset.
+ * @param cbXfer Transfer size.
+ * @param pSgBuf Scather / gather buffer for the transfer.
+ * @param hIoXfer I/O transfer handle to ping on completion.
+ */
+typedef DECLCALLBACKTYPE(int, FNPDMBLKCACHEXFERENQUEUEDEV,(PPDMDEVINS pDevIns, PDMBLKCACHEXFERDIR enmXferDir, uint64_t off,
+ size_t cbXfer, PCRTSGBUF pSgBuf, PPDMBLKCACHEIOXFER hIoXfer));
+/** Pointer to a FNPDMBLKCACHEXFERENQUEUEDEV(). */
+typedef FNPDMBLKCACHEXFERENQUEUEDEV *PFNPDMBLKCACHEXFERENQUEUEDEV;
+
+/**
+ * Discard enqueue callback for devices.
+ *
+ * @param pDevIns The device instance.
+ * @param paRanges Ranges to discard.
+ * @param cRanges Number of range entries.
+ * @param hIoXfer I/O handle to return on completion.
+ */
+typedef DECLCALLBACKTYPE(int, FNPDMBLKCACHEXFERENQUEUEDISCARDDEV,(PPDMDEVINS pDevIns, PCRTRANGE paRanges, unsigned cRanges,
+ PPDMBLKCACHEIOXFER hIoXfer));
+/** Pointer to a FNPDMBLKCACHEXFERENQUEUEDISCARDDEV(). */
+typedef FNPDMBLKCACHEXFERENQUEUEDISCARDDEV *PFNPDMBLKCACHEXFERENQUEUEDISCARDDEV;
+
+/**
+ * Completion callback for drivers.
+ *
+ * @param pvUserInt User argument given to PDMR3BlkCacheRetainInt.
+ * @param pvUser User argument given during request initiation.
+ * @param rc The status code of the completed request.
+ */
+typedef DECLCALLBACKTYPE(void, FNPDMBLKCACHEXFERCOMPLETEINT,(void *pvUserInt, void *pvUser, int rc));
+/** Pointer to a FNPDMBLKCACHEXFERCOMPLETEINT(). */
+typedef FNPDMBLKCACHEXFERCOMPLETEINT *PFNPDMBLKCACHEXFERCOMPLETEINT;
+
+/**
+ * I/O enqueue callback for internal users.
+ *
+ * @param pvUser User data.
+ * @param enmXferDir Transfer direction.
+ * @param off Transfer offset.
+ * @param cbXfer Transfer size.
+ * @param pSgBuf Scather / gather buffer for the transfer.
+ * @param hIoXfer I/O transfer handle to ping on completion.
+ */
+typedef DECLCALLBACKTYPE(int, FNPDMBLKCACHEXFERENQUEUEINT,(void *pvUser, PDMBLKCACHEXFERDIR enmXferDir, uint64_t off,
+ size_t cbXfer, PCRTSGBUF pSgBuf, PPDMBLKCACHEIOXFER hIoXfer));
+/** Pointer to a FNPDMBLKCACHEXFERENQUEUEINT(). */
+typedef FNPDMBLKCACHEXFERENQUEUEINT *PFNPDMBLKCACHEXFERENQUEUEINT;
+
+/**
+ * Discard enqueue callback for VMM internal users.
+ *
+ * @param pvUser User data.
+ * @param paRanges Ranges to discard.
+ * @param cRanges Number of range entries.
+ * @param hIoXfer I/O handle to return on completion.
+ */
+typedef DECLCALLBACKTYPE(int, FNPDMBLKCACHEXFERENQUEUEDISCARDINT,(void *pvUser, PCRTRANGE paRanges, unsigned cRanges,
+ PPDMBLKCACHEIOXFER hIoXfer));
+/** Pointer to a FNPDMBLKCACHEXFERENQUEUEDISCARDINT(). */
+typedef FNPDMBLKCACHEXFERENQUEUEDISCARDINT *PFNPDMBLKCACHEXFERENQUEUEDISCARDINT;
+
+/**
+ * Completion callback for USB devices.
+ *
+ * @param pUsbIns The USB device instance.
+ * @param pvUser User argument given during request initiation.
+ * @param rc The status code of the completed request.
+ */
+typedef DECLCALLBACKTYPE(void, FNPDMBLKCACHEXFERCOMPLETEUSB,(PPDMUSBINS pUsbIns, void *pvUser, int rc));
+/** Pointer to a FNPDMBLKCACHEXFERCOMPLETEUSB(). */
+typedef FNPDMBLKCACHEXFERCOMPLETEUSB *PFNPDMBLKCACHEXFERCOMPLETEUSB;
+
+/**
+ * I/O enqueue callback for USB devices.
+ *
+ * @param pUsbIns The USB device instance.
+ * @param enmXferDir Transfer direction.
+ * @param off Transfer offset.
+ * @param cbXfer Transfer size.
+ * @param pSgBuf Scather / gather buffer for the transfer.
+ * @param hIoXfer I/O transfer handle to ping on completion.
+ */
+typedef DECLCALLBACKTYPE(int, FNPDMBLKCACHEXFERENQUEUEUSB,(PPDMUSBINS pUsbIns, PDMBLKCACHEXFERDIR enmXferDir, uint64_t off,
+ size_t cbXfer, PCRTSGBUF pSgBuf, PPDMBLKCACHEIOXFER hIoXfer));
+/** Pointer to a FNPDMBLKCACHEXFERENQUEUEUSB(). */
+typedef FNPDMBLKCACHEXFERENQUEUEUSB *PFNPDMBLKCACHEXFERENQUEUEUSB;
+
+/**
+ * Discard enqueue callback for USB devices.
+ *
+ * @param pUsbIns The USB device instance.
+ * @param paRanges Ranges to discard.
+ * @param cRanges Number of range entries.
+ * @param hIoXfer I/O handle to return on completion.
+ */
+typedef DECLCALLBACKTYPE(int, FNPDMBLKCACHEXFERENQUEUEDISCARDUSB,(PPDMUSBINS pUsbIns, PCRTRANGE paRanges, unsigned cRanges,
+ PPDMBLKCACHEIOXFER hIoXfer));
+/** Pointer to a FNPDMBLKCACHEXFERENQUEUEDISCARDUSB(). */
+typedef FNPDMBLKCACHEXFERENQUEUEDISCARDUSB *PFNPDMBLKCACHEXFERENQUEUEDISCARDUSB;
+
+/**
+ * Create a block cache user for a driver instance.
+ *
+ * @returns VBox status code.
+ * @param pVM The cross context VM structure.
+ * @param pDrvIns The driver instance.
+ * @param ppBlkCache Where to store the handle to the block cache.
+ * @param pfnXferComplete The I/O transfer complete callback.
+ * @param pfnXferEnqueue The I/O request enqueue callback.
+ * @param pfnXferEnqueueDiscard The discard request enqueue callback.
+ * @param pcszId Unique ID used to identify the user.
+ */
+VMMR3DECL(int) PDMR3BlkCacheRetainDriver(PVM pVM, PPDMDRVINS pDrvIns, PPPDMBLKCACHE ppBlkCache,
+ PFNPDMBLKCACHEXFERCOMPLETEDRV pfnXferComplete,
+ PFNPDMBLKCACHEXFERENQUEUEDRV pfnXferEnqueue,
+ PFNPDMBLKCACHEXFERENQUEUEDISCARDDRV pfnXferEnqueueDiscard,
+ const char *pcszId);
+
+/**
+ * Create a block cache user for a device instance.
+ *
+ * @returns VBox status code.
+ * @param pVM The cross context VM structure.
+ * @param pDevIns The device instance.
+ * @param ppBlkCache Where to store the handle to the block cache.
+ * @param pfnXferComplete The I/O transfer complete callback.
+ * @param pfnXferEnqueue The I/O request enqueue callback.
+ * @param pfnXferEnqueueDiscard The discard request enqueue callback.
+ * @param pcszId Unique ID used to identify the user.
+ */
+VMMR3DECL(int) PDMR3BlkCacheRetainDevice(PVM pVM, PPDMDEVINS pDevIns, PPPDMBLKCACHE ppBlkCache,
+ PFNPDMBLKCACHEXFERCOMPLETEDEV pfnXferComplete,
+ PFNPDMBLKCACHEXFERENQUEUEDEV pfnXferEnqueue,
+ PFNPDMBLKCACHEXFERENQUEUEDISCARDDEV pfnXferEnqueueDiscard,
+ const char *pcszId);
+
+/**
+ * Create a block cache user for a USB instance.
+ *
+ * @returns VBox status code.
+ * @param pVM The cross context VM structure.
+ * @param pUsbIns The USB device instance.
+ * @param ppBlkCache Where to store the handle to the block cache.
+ * @param pfnXferComplete The I/O transfer complete callback.
+ * @param pfnXferEnqueue The I/O request enqueue callback.
+ * @param pfnXferEnqueueDiscard The discard request enqueue callback.
+ * @param pcszId Unique ID used to identify the user.
+ */
+VMMR3DECL(int) PDMR3BlkCacheRetainUsb(PVM pVM, PPDMUSBINS pUsbIns, PPPDMBLKCACHE ppBlkCache,
+ PFNPDMBLKCACHEXFERCOMPLETEUSB pfnXferComplete,
+ PFNPDMBLKCACHEXFERENQUEUEUSB pfnXferEnqueue,
+ PFNPDMBLKCACHEXFERENQUEUEDISCARDUSB pfnXferEnqueueDiscard,
+ const char *pcszId);
+
+/**
+ * Create a block cache user for internal use by VMM.
+ *
+ * @returns VBox status code.
+ * @param pVM The cross context VM structure.
+ * @param pvUser Opaque user data.
+ * @param ppBlkCache Where to store the handle to the block cache.
+ * @param pfnXferComplete The I/O transfer complete callback.
+ * @param pfnXferEnqueue The I/O request enqueue callback.
+ * @param pfnXferEnqueueDiscard The discard request enqueue callback.
+ * @param pcszId Unique ID used to identify the user.
+ */
+VMMR3DECL(int) PDMR3BlkCacheRetainInt(PVM pVM, void *pvUser, PPPDMBLKCACHE ppBlkCache,
+ PFNPDMBLKCACHEXFERCOMPLETEINT pfnXferComplete,
+ PFNPDMBLKCACHEXFERENQUEUEINT pfnXferEnqueue,
+ PFNPDMBLKCACHEXFERENQUEUEDISCARDINT pfnXferEnqueueDiscard,
+ const char *pcszId);
+
+/**
+ * Releases a block cache handle.
+ *
+ * @returns nothing.
+ * @param pBlkCache Block cache handle.
+ */
+VMMR3DECL(void) PDMR3BlkCacheRelease(PPDMBLKCACHE pBlkCache);
+
+/**
+ * Releases all block cache handles for a device instance.
+ *
+ * @returns nothing.
+ * @param pVM The cross context VM structure.
+ * @param pDevIns The device instance.
+ */
+VMMR3DECL(void) PDMR3BlkCacheReleaseDevice(PVM pVM, PPDMDEVINS pDevIns);
+
+/**
+ * Releases all block cache handles for a driver instance.
+ *
+ * @returns nothing.
+ * @param pVM The cross context VM structure.
+ * @param pDrvIns The driver instance.
+ */
+VMMR3DECL(void) PDMR3BlkCacheReleaseDriver(PVM pVM, PPDMDRVINS pDrvIns);
+
+/**
+ * Releases all block cache handles for a USB device instance.
+ *
+ * @returns nothing.
+ * @param pVM The cross context VM structure.
+ * @param pUsbIns The USB device instance.
+ */
+VMMR3DECL(void) PDMR3BlkCacheReleaseUsb(PVM pVM, PPDMUSBINS pUsbIns);
+
+/**
+ * Creates a read task on the given endpoint.
+ *
+ * @returns VBox status code.
+ * @param pBlkCache The cache instance.
+ * @param off Where to start reading from.
+ * @param pSgBuf Scatter gather buffer store the data in.
+ * @param cbRead The overall number of bytes to read.
+ * @param pvUser Opaque user data returned in the completion callback
+ * upon completion of the read.
+ */
+VMMR3DECL(int) PDMR3BlkCacheRead(PPDMBLKCACHE pBlkCache, uint64_t off, PCRTSGBUF pSgBuf, size_t cbRead, void *pvUser);
+
+/**
+ * Creates a write task on the given endpoint.
+ *
+ * @returns VBox status code.
+ * @param pBlkCache The cache instance.
+ * @param off Where to start writing at.
+ * @param pSgBuf Scatter gather buffer gather the data from.
+ * @param cbWrite The overall number of bytes to write.
+ * @param pvUser Opaque user data returned in the completion callback
+ * upon completion of the task.
+ */
+VMMR3DECL(int) PDMR3BlkCacheWrite(PPDMBLKCACHE pBlkCache, uint64_t off, PCRTSGBUF pSgBuf, size_t cbWrite, void *pvUser);
+
+/**
+ * Creates a flush task on the given endpoint.
+ *
+ * @returns VBox status code.
+ * @param pBlkCache The cache instance.
+ * @param pvUser Opaque user data returned in the completion callback
+ * upon completion of the task.
+ */
+VMMR3DECL(int) PDMR3BlkCacheFlush(PPDMBLKCACHE pBlkCache, void *pvUser);
+
+/**
+ * Discards the given ranges from the cache.
+ *
+ * @returns VBox status code.
+ * @param pBlkCache The cache instance.
+ * @param paRanges Array of ranges to discard.
+ * @param cRanges Number of ranges in the array.
+ * @param pvUser Opaque user data returned in the completion callback
+ * upon completion of the task.
+ */
+VMMR3DECL(int) PDMR3BlkCacheDiscard(PPDMBLKCACHE pBlkCache, PCRTRANGE paRanges, unsigned cRanges, void *pvUser);
+
+/**
+ * Notify the cache of a complete I/O transfer.
+ *
+ * @returns nothing.
+ * @param pBlkCache The cache instance.
+ * @param hIoXfer The I/O transfer handle which completed.
+ * @param rcIoXfer The status code of the completed request.
+ */
+VMMR3DECL(void) PDMR3BlkCacheIoXferComplete(PPDMBLKCACHE pBlkCache, PPDMBLKCACHEIOXFER hIoXfer, int rcIoXfer);
+
+/**
+ * Suspends the block cache.
+ *
+ * The cache waits until all I/O transfers completed and stops to enqueue new
+ * requests after the call returned but will not accept reads, write or flushes
+ * either.
+ *
+ * @returns VBox status code.
+ * @param pBlkCache The cache instance.
+ */
+VMMR3DECL(int) PDMR3BlkCacheSuspend(PPDMBLKCACHE pBlkCache);
+
+/**
+ * Resumes operation of the block cache.
+ *
+ * @returns VBox status code.
+ * @param pBlkCache The cache instance.
+ */
+VMMR3DECL(int) PDMR3BlkCacheResume(PPDMBLKCACHE pBlkCache);
+
+/**
+ * Clears the block cache and removes all entries.
+ *
+ * The cache waits until all I/O transfers completed.
+ *
+ * @returns VBox status code.
+ * @param pBlkCache The cache instance.
+ */
+VMMR3DECL(int) PDMR3BlkCacheClear(PPDMBLKCACHE pBlkCache);
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !VBOX_INCLUDED_vmm_pdmblkcache_h */
+
diff --git a/include/VBox/vmm/pdmcardreaderinfs.h b/include/VBox/vmm/pdmcardreaderinfs.h
new file mode 100644
index 00000000..c0949c9d
--- /dev/null
+++ b/include/VBox/vmm/pdmcardreaderinfs.h
@@ -0,0 +1,136 @@
+/* $Id: pdmcardreaderinfs.h $ */
+/** @file
+ * cardreaderinfs - interface between USB Card Reader device and its driver.
+ */
+
+/*
+ * Copyright (C) 2011-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vmm_pdmcardreaderinfs_h
+#define VBOX_INCLUDED_vmm_pdmcardreaderinfs_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/types.h>
+
+
+/** @defgroup grp_pdm_ifs_cardreader PDM USB Card Reader Interfaces
+ * @ingroup grp_pdm_interfaces
+ * @{
+ */
+
+
+typedef struct PDMICARDREADER_IO_REQUEST
+{
+ uint32_t u32Protocol; /**< Protocol identifier */
+ uint32_t cbPciLength; /**< Protocol Control Information Length */
+ /* 'cbPciLength - 8' bytes of control info may follow. */
+} PDMICARDREADER_IO_REQUEST;
+
+typedef struct PDMICARDREADER_READERSTATE
+{
+ char *pszReaderName;
+ uint32_t u32CurrentState; /**< Current state of reader at time of call. */
+ uint32_t u32EventState; /**< State of reader after state change */
+ uint32_t cbAtr; /**< Number of bytes in the returned ATR. */
+ uint8_t au8Atr[36]; /**< Atr of inserted card, (extra alignment bytes) */
+} PDMICARDREADER_READERSTATE;
+
+
+#define PDMICARDREADERDOWN_IID "78d65378-889c-4418-8bc2-7a89a5af2817"
+typedef struct PDMICARDREADERDOWN PDMICARDREADERDOWN;
+typedef PDMICARDREADERDOWN *PPDMICARDREADERDOWN;
+struct PDMICARDREADERDOWN
+{
+ DECLR3CALLBACKMEMBER(int, pfnEstablishContext,(PPDMICARDREADERDOWN pInterface));
+ DECLR3CALLBACKMEMBER(int, pfnConnect,(PPDMICARDREADERDOWN pInterface, void *pvUser, const char *pszCardReaderName,
+ uint32_t u32ShareMode, uint32_t u32PreferredProtocols));
+ DECLR3CALLBACKMEMBER(int, pfnDisconnect,(PPDMICARDREADERDOWN pInterface, void *pvUser, uint32_t u32Disposition));
+ DECLR3CALLBACKMEMBER(int, pfnStatus,(PPDMICARDREADERDOWN pInterface, void *pvUser, uint32_t cchReaderName, uint32_t cbAtrLen));
+ DECLR3CALLBACKMEMBER(int, pfnReleaseContext,(PPDMICARDREADERDOWN pInterface, void *pvUser));
+ DECLR3CALLBACKMEMBER(int, pfnGetStatusChange,(PPDMICARDREADERDOWN pInterface, void *pvUser, uint32_t u32Timeout,
+ PDMICARDREADER_READERSTATE *paReaderStats, uint32_t cReaderStats));
+ DECLR3CALLBACKMEMBER(int, pfnBeginTransaction,(PPDMICARDREADERDOWN pInterface, void *pvUser));
+ DECLR3CALLBACKMEMBER(int, pfnEndTransaction,(PPDMICARDREADERDOWN pInterface, void *pvUser, uint32_t u32Disposition));
+ DECLR3CALLBACKMEMBER(int, pfnTransmit,(PPDMICARDREADERDOWN pInterface, void *pvUser,
+ const PDMICARDREADER_IO_REQUEST *pioSendRequest,
+ const uint8_t *pu8SendBuffer, uint32_t cbSendBuffer, uint32_t cbRecvBuffer));
+ /**
+ * Up level provides pvInBuffer of cbInBuffer bytes to call SCardControl, also it specify bytes it expects to receive
+ * @note Device/driver implementation should copy buffers before execution in
+ * async mode, and both layers shouldn't expect permanent storage for the
+ * buffer.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnControl,(PPDMICARDREADERDOWN pInterface, void *pvUser,
+ uint32_t u32ControlCode, const void *pvInBuffer,
+ uint32_t cbInBuffer, uint32_t cbOutBuffer));
+ /**
+ * This function ask driver to provide attribute (dwAttribId) and provide limit (cbAttrib) of buffer size for attribute value,
+ * Callback UpGetAttrib returns buffer containing the value and altered size of the buffer.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnGetAttr,(PPDMICARDREADERDOWN pInterface, void *pvUser,
+ uint32_t u32AttribId, uint32_t cbAttrib));
+ DECLR3CALLBACKMEMBER(int, pfnSetAttr,(PPDMICARDREADERDOWN pInterface, void *pvUser,
+ uint32_t u32AttribId, const void *pvAttrib, uint32_t cbAttrib));
+};
+
+#define PDMICARDREADERUP_IID "c0d7498e-0635-48ca-aab1-b11b6a55cf7d"
+typedef struct PDMICARDREADERUP PDMICARDREADERUP;
+typedef PDMICARDREADERUP *PPDMICARDREADERUP;
+struct PDMICARDREADERUP
+{
+ DECLR3CALLBACKMEMBER(int, pfnEstablishContext,(PPDMICARDREADERUP pInterface, int32_t lSCardRc));
+ DECLR3CALLBACKMEMBER(int, pfnStatus,(PPDMICARDREADERUP pInterface, void *pvUser, int32_t lSCardRc,
+ char *pszReaderName, uint32_t cchReaderName, uint32_t u32CardState,
+ uint32_t u32Protocol, uint8_t *pu8Atr, uint32_t cbAtr));
+ DECLR3CALLBACKMEMBER(int, pfnConnect,(PPDMICARDREADERUP pInterface, void *pvUser, int32_t lSCardRc,
+ uint32_t u32ActiveProtocol));
+ DECLR3CALLBACKMEMBER(int, pfnDisconnect,(PPDMICARDREADERUP pInterface, void *pvUser, int32_t lSCardRc));
+ DECLR3CALLBACKMEMBER(int, pfnSetStatusChange,(PPDMICARDREADERUP pInterface, void *pvUser, int32_t lSCardRc,
+ PDMICARDREADER_READERSTATE *paReaderStats, uint32_t cReaderStats));
+ DECLR3CALLBACKMEMBER(int, pfnBeginTransaction,(PPDMICARDREADERUP pInterface, void *pvUser, int32_t lSCardRc));
+ DECLR3CALLBACKMEMBER(int, pfnEndTransaction,(PPDMICARDREADERUP pInterface, void *pvUser, int32_t lSCardRc));
+ /* Note: pioRecvPci stack variable */
+ DECLR3CALLBACKMEMBER(int, pfnTransmit,(PPDMICARDREADERUP pInterface, void *pvUser, int32_t lSCardRc,
+ const PDMICARDREADER_IO_REQUEST *pioRecvPci,
+ uint8_t *pu8RecvBuffer, uint32_t cbRecvBuffer));
+ DECLR3CALLBACKMEMBER(int, pfnControl,(PPDMICARDREADERUP pInterface, void *pvUser, int32_t lSCardRc,
+ uint32_t u32ControlCode, void *pvOutBuffer, uint32_t cbOutBuffer));
+ DECLR3CALLBACKMEMBER(int, pfnGetAttrib,(PPDMICARDREADERUP pInterface, void *pvUser, int32_t lSCardRc,
+ uint32_t u32AttribId, void *pvAttrib, uint32_t cbAttrib));
+ DECLR3CALLBACKMEMBER(int, pfnSetAttrib,(PPDMICARDREADERUP pInterface, void *pvUser, int32_t lSCardRc, uint32_t u32AttribId));
+};
+
+/** @} */
+
+#endif /* !VBOX_INCLUDED_vmm_pdmcardreaderinfs_h */
+
diff --git a/include/VBox/vmm/pdmcommon.h b/include/VBox/vmm/pdmcommon.h
new file mode 100644
index 00000000..7257ff0b
--- /dev/null
+++ b/include/VBox/vmm/pdmcommon.h
@@ -0,0 +1,192 @@
+/** @file
+ * PDM - Pluggable Device Manager, Common Definitions & Types.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vmm_pdmcommon_h
+#define VBOX_INCLUDED_vmm_pdmcommon_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/types.h>
+
+
+/** @defgroup grp_pdm_common Common Definitions & Types
+ * @ingroup grp_pdm
+ *
+ * Not all the types here are "common", they are here to work around header
+ * ordering issues.
+ *
+ * @{
+ */
+
+/** Makes a PDM structure version out of an unique magic value and major &
+ * minor version numbers.
+ *
+ * @returns 32-bit structure version number.
+ *
+ * @param uMagic 16-bit magic value. This must be unique.
+ * @param uMajor 12-bit major version number. Structures with different
+ * major numbers are not compatible.
+ * @param uMinor 4-bit minor version number. When only the minor version
+ * differs, the structures will be 100% backwards
+ * compatible.
+ */
+#define PDM_VERSION_MAKE(uMagic, uMajor, uMinor) \
+ ( ((uint32_t)(uMagic) << 16) | ((uint32_t)((uMajor) & 0xff) << 4) | ((uint32_t)((uMinor) & 0xf) << 0) )
+
+/**
+ * Version of PDM_VERSION_MAKE that's compatible with the preprocessor.
+ *
+ * @returns 32-bit structure version number.
+ *
+ * @param uMagic 16-bit magic value, no suffix. This must be unique.
+ * @param uMajor 12-bit major version number, no suffix. Structures with
+ * different major numbers are not compatible.
+ * @param uMinor 4-bit minor version number, no suffix. When only the
+ * minor version differs, the structures will be 100%
+ * backwards compatible.
+ */
+#define PDM_VERSION_MAKE_PP(uMagic, uMajor, uMinor) \
+ ( (UINT32_C(uMagic) << 16) | ((UINT32_C(uMajor) & UINT32_C(0xff)) << 4) | ((UINT32_C(uMinor) & UINT32_C(0xf)) << 0) )
+
+/** Checks if @a uVerMagic1 is compatible with @a uVerMagic2.
+ *
+ * @returns true / false.
+ * @param uVerMagic1 Typically the runtime version of the struct. This must
+ * have the same magic and major version as @a uVerMagic2
+ * and the minor version must be greater or equal to that
+ * of @a uVerMagic2.
+ * @param uVerMagic2 Typically the version the code was compiled against.
+ *
+ * @remarks The parameters will be referenced more than once.
+ */
+#define PDM_VERSION_ARE_COMPATIBLE(uVerMagic1, uVerMagic2) \
+ ( (uVerMagic1) == (uVerMagic2) \
+ || ( (uVerMagic1) >= (uVerMagic2) \
+ && ((uVerMagic1) & UINT32_C(0xfffffff0)) == ((uVerMagic2) & UINT32_C(0xfffffff0)) ) \
+ )
+
+
+/** @name PDM Attach/Detach Callback Flags.
+ * Used by PDMDeviceAttach, PDMDeviceDetach, PDMDriverAttach, PDMDriverDetach,
+ * FNPDMDEVATTACH, FNPDMDEVDETACH, FNPDMDRVATTACH, FNPDMDRVDETACH and
+ * FNPDMDRVCONSTRUCT.
+ * @{ */
+/** The attach/detach command is not a hotplug event. */
+#define PDM_TACH_FLAGS_NOT_HOT_PLUG RT_BIT_32(0)
+/** Indicates that no attach or detach callbacks should be made.
+ * This is mostly for internal use. */
+#define PDM_TACH_FLAGS_NO_CALLBACKS RT_BIT_32(1)
+/** @} */
+
+
+/**
+ * Is asynchronous handling of suspend or power off notification completed?
+ *
+ * This is called to check whether the USB device has quiesced. Don't deadlock.
+ * Avoid blocking. Do NOT wait for anything.
+ *
+ * @returns true if done, false if more work to be done.
+ *
+ * @param pUsbIns The USB device instance.
+ *
+ * @thread EMT(0)
+ */
+typedef DECLCALLBACKTYPE(bool, FNPDMUSBASYNCNOTIFY,(PPDMUSBINS pUsbIns));
+/** Pointer to a FNPDMUSBASYNCNOTIFY. */
+typedef FNPDMUSBASYNCNOTIFY *PFNPDMUSBASYNCNOTIFY;
+
+/**
+ * Is asynchronous handling of suspend or power off notification completed?
+ *
+ * This is called to check whether the device has quiesced. Don't deadlock.
+ * Avoid blocking. Do NOT wait for anything.
+ *
+ * @returns true if done, false if more work to be done.
+ *
+ * @param pDevIns The device instance.
+ * @remarks The caller will enter the device critical section.
+ * @thread EMT(0)
+ */
+typedef DECLCALLBACKTYPE(bool, FNPDMDEVASYNCNOTIFY,(PPDMDEVINS pDevIns));
+/** Pointer to a FNPDMDEVASYNCNOTIFY. */
+typedef FNPDMDEVASYNCNOTIFY *PFNPDMDEVASYNCNOTIFY;
+
+/**
+ * Is asynchronous handling of suspend or power off notification completed?
+ *
+ * This is called to check whether the driver has quiesced. Don't deadlock.
+ * Avoid blocking. Do NOT wait for anything.
+ *
+ * @returns true if done, false if more work to be done.
+ *
+ * @param pDrvIns The driver instance.
+ *
+ * @thread EMT(0)
+ */
+typedef DECLCALLBACKTYPE(bool, FNPDMDRVASYNCNOTIFY,(PPDMDRVINS pDrvIns));
+/** Pointer to a FNPDMDRVASYNCNOTIFY. */
+typedef FNPDMDRVASYNCNOTIFY *PFNPDMDRVASYNCNOTIFY;
+
+
+/**
+ * The ring-0 driver request handler.
+ *
+ * @returns VBox status code. PDMDevHlpCallR0 will return this.
+ * @param pDevIns The device instance (the ring-0 mapping).
+ * @param uOperation The operation.
+ * @param u64Arg Optional integer argument for the operation.
+ */
+typedef DECLCALLBACKTYPE(int, FNPDMDEVREQHANDLERR0,(PPDMDEVINS pDevIns, uint32_t uOperation, uint64_t u64Arg));
+/** Ring-0 pointer to a FNPDMDEVREQHANDLERR0. */
+typedef R0PTRTYPE(FNPDMDEVREQHANDLERR0 *) PFNPDMDEVREQHANDLERR0;
+
+/**
+ * The ring-0 driver request handler.
+ *
+ * @returns VBox status code. PDMDrvHlpCallR0 will return this.
+ * @param pDrvIns The driver instance (the ring-0 mapping).
+ * @param uOperation The operation.
+ * @param u64Arg Optional integer argument for the operation.
+ */
+typedef DECLCALLBACKTYPE(int, FNPDMDRVREQHANDLERR0,(PPDMDRVINS pDrvIns, uint32_t uOperation, uint64_t u64Arg));
+/** Ring-0 pointer to a FNPDMDRVREQHANDLERR0. */
+typedef R0PTRTYPE(FNPDMDRVREQHANDLERR0 *) PFNPDMDRVREQHANDLERR0;
+
+
+/** @} */
+
+#endif /* !VBOX_INCLUDED_vmm_pdmcommon_h */
+
diff --git a/include/VBox/vmm/pdmcritsect.h b/include/VBox/vmm/pdmcritsect.h
new file mode 100644
index 00000000..79445ecb
--- /dev/null
+++ b/include/VBox/vmm/pdmcritsect.h
@@ -0,0 +1,143 @@
+/** @file
+ * PDM - Pluggable Device Manager, Critical Sections.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vmm_pdmcritsect_h
+#define VBOX_INCLUDED_vmm_pdmcritsect_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/types.h>
+#include <iprt/critsect.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_pdm_critsect The PDM Critical Section API
+ * @ingroup grp_pdm
+ * @{
+ */
+
+/**
+ * A PDM critical section.
+ * Initialize using PDMDRVHLP::pfnCritSectInit().
+ */
+typedef union PDMCRITSECT
+{
+ /** Padding. */
+ uint8_t padding[HC_ARCH_BITS == 32 ? 0xc0 : 0x100];
+#ifdef PDMCRITSECTINT_DECLARED
+ /** The internal structure (not normally visible). */
+ struct PDMCRITSECTINT s;
+#endif
+} PDMCRITSECT;
+
+VMMR3_INT_DECL(int) PDMR3CritSectBothTerm(PVM pVM);
+VMMR3_INT_DECL(void) PDMR3CritSectLeaveAll(PVM pVM);
+VMM_INT_DECL(void) PDMCritSectBothFF(PVMCC pVM, PVMCPUCC pVCpu);
+
+
+VMMR3DECL(uint32_t) PDMR3CritSectCountOwned(PVM pVM, char *pszNames, size_t cbNames);
+
+VMMR3DECL(int) PDMR3CritSectInit(PVM pVM, PPDMCRITSECT pCritSect, RT_SRC_POS_DECL,
+ const char *pszNameFmt, ...) RT_IPRT_FORMAT_ATTR(6, 7);
+VMMR3DECL(int) PDMR3CritSectEnterEx(PVM pVM, PPDMCRITSECT pCritSect, bool fCallRing3);
+VMMR3DECL(bool) PDMR3CritSectYield(PVM pVM, PPDMCRITSECT pCritSect);
+VMMR3DECL(const char *) PDMR3CritSectName(PCPDMCRITSECT pCritSect);
+VMMR3DECL(int) PDMR3CritSectDelete(PVM pVM, PPDMCRITSECT pCritSect);
+#if defined(IN_RING0) || defined(IN_RING3)
+VMMDECL(int) PDMHCCritSectScheduleExitEvent(PPDMCRITSECT pCritSect, SUPSEMEVENT hEventToSignal);
+#endif
+
+VMMDECL(DECL_CHECK_RETURN_NOT_R3(int))
+ PDMCritSectEnter(PVMCC pVM, PPDMCRITSECT pCritSect, int rcBusy);
+VMMDECL(DECL_CHECK_RETURN_NOT_R3(int))
+ PDMCritSectEnterDebug(PVMCC pVM, PPDMCRITSECT pCritSect, int rcBusy, RTHCUINTPTR uId, RT_SRC_POS_DECL);
+VMMDECL(DECL_CHECK_RETURN(int))
+ PDMCritSectTryEnter(PVMCC pVM, PPDMCRITSECT pCritSect);
+VMMDECL(DECL_CHECK_RETURN(int))
+ PDMCritSectTryEnterDebug(PVMCC pVM, PPDMCRITSECT pCritSect, RTHCUINTPTR uId, RT_SRC_POS_DECL);
+VMMDECL(int) PDMCritSectLeave(PVMCC pVM, PPDMCRITSECT pCritSect);
+
+VMMDECL(bool) PDMCritSectIsOwner(PVMCC pVM, PCPDMCRITSECT pCritSect);
+VMMDECL(bool) PDMCritSectIsOwnerEx(PVMCPUCC pVCpu, PCPDMCRITSECT pCritSect);
+VMMDECL(bool) PDMCritSectIsInitialized(PCPDMCRITSECT pCritSect);
+VMMDECL(bool) PDMCritSectHasWaiters(PVMCC pVM, PCPDMCRITSECT pCritSect);
+VMMDECL(uint32_t) PDMCritSectGetRecursion(PCPDMCRITSECT pCritSect);
+
+VMMR3DECL(PPDMCRITSECT) PDMR3CritSectGetNop(PVM pVM);
+
+/* Strict build: Remap the two enter calls to the debug versions. */
+#ifdef VBOX_STRICT
+# ifdef IPRT_INCLUDED_asm_h
+# define PDMCritSectEnter(a_pVM, pCritSect, rcBusy) PDMCritSectEnterDebug((a_pVM), (pCritSect), (rcBusy), (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
+# define PDMCritSectTryEnter(a_pVM, pCritSect) PDMCritSectTryEnterDebug((a_pVM), (pCritSect), (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
+# else
+# define PDMCritSectEnter(a_pVM, pCritSect, rcBusy) PDMCritSectEnterDebug((a_pVM), (pCritSect), (rcBusy), 0, RT_SRC_POS)
+# define PDMCritSectTryEnter(a_pVM, pCritSect) PDMCritSectTryEnterDebug((a_pVM), (pCritSect), 0, RT_SRC_POS)
+# endif
+#endif
+
+/** @def PDM_CRITSECT_RELEASE_ASSERT_RC
+ * Helper for PDMCritSectEnter w/ rcBusy VINF_SUCCESS when there is no way
+ * to forward failures to the caller. */
+#define PDM_CRITSECT_RELEASE_ASSERT_RC(a_pVM, a_pCritSect, a_rc) \
+ AssertReleaseMsg(RT_SUCCESS(a_rc), ("pVM=%p pCritSect=%p: %Rrc\n", (a_pVM), (a_pCritSect), (a_rc)))
+
+/** @def PDM_CRITSECT_RELEASE_ASSERT_RC_DEV
+ * Helper for PDMCritSectEnter w/ rcBusy VINF_SUCCESS when there is no way
+ * to forward failures to the caller, device edition. */
+#define PDM_CRITSECT_RELEASE_ASSERT_RC_DEV(a_pDevIns, a_pCritSect, a_rc) \
+ AssertReleaseMsg(RT_SUCCESS(a_rc), ("pDevIns=%p pCritSect=%p: %Rrc\n", (a_pDevIns), (a_pCritSect), (a_rc)))
+
+/** @def PDM_CRITSECT_RELEASE_ASSERT_RC_DRV
+ * Helper for PDMCritSectEnter w/ rcBusy VINF_SUCCESS when there is no way
+ * to forward failures to the caller, driver edition. */
+#define PDM_CRITSECT_RELEASE_ASSERT_RC_DRV(a_pDrvIns, a_pCritSect, a_rc) \
+ AssertReleaseMsg(RT_SUCCESS(a_rc), ("pDrvIns=%p pCritSect=%p: %Rrc\n", (a_pDrvIns), (a_pCritSect), (a_rc)))
+
+/** @def PDM_CRITSECT_RELEASE_ASSERT_RC_USB
+ * Helper for PDMCritSectEnter w/ rcBusy VINF_SUCCESS when there is no way
+ * to forward failures to the caller, USB device edition. */
+#define PDM_CRITSECT_RELEASE_ASSERT_RC_USB(a_pUsbIns, a_pCritSect, a_rc) \
+ AssertReleaseMsg(RT_SUCCESS(a_rc), ("pUsbIns=%p pCritSect=%p: %Rrc\n", (a_pUsbIns), (a_pCritSect), (a_rc)))
+
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !VBOX_INCLUDED_vmm_pdmcritsect_h */
+
diff --git a/include/VBox/vmm/pdmcritsectrw.h b/include/VBox/vmm/pdmcritsectrw.h
new file mode 100644
index 00000000..8b3eb319
--- /dev/null
+++ b/include/VBox/vmm/pdmcritsectrw.h
@@ -0,0 +1,111 @@
+/** @file
+ * PDM - Pluggable Device Manager, Read/Write Critical Section.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vmm_pdmcritsectrw_h
+#define VBOX_INCLUDED_vmm_pdmcritsectrw_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/types.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_pdm_critsectrw The PDM Read/Write Critical Section API
+ * @ingroup grp_pdm
+ * @{
+ */
+
+/**
+ * A PDM read/write critical section.
+ * Initialize using PDMDRVHLP::pfnCritSectRwInit().
+ */
+typedef union PDMCRITSECTRW
+{
+ /** Padding. */
+ uint8_t padding[HC_ARCH_BITS == 32 ? 0xc0 : 0x100];
+#ifdef PDMCRITSECTRWINT_DECLARED
+ /** The internal structure (not normally visible). */
+ struct PDMCRITSECTRWINT s;
+#endif
+} PDMCRITSECTRW;
+
+VMMR3DECL(int) PDMR3CritSectRwInit(PVM pVM, PPDMCRITSECTRW pCritSect, RT_SRC_POS_DECL,
+ const char *pszNameFmt, ...) RT_IPRT_FORMAT_ATTR(6, 7);
+VMMR3DECL(int) PDMR3CritSectRwDelete(PVM pVM, PPDMCRITSECTRW pCritSect);
+VMMR3DECL(const char *) PDMR3CritSectRwName(PCPDMCRITSECTRW pCritSect);
+VMMR3DECL(int) PDMR3CritSectRwEnterSharedEx(PVM pVM, PPDMCRITSECTRW pThis, bool fCallRing3);
+VMMR3DECL(int) PDMR3CritSectRwEnterExclEx(PVM pVM, PPDMCRITSECTRW pThis, bool fCallRing3);
+
+VMMDECL(int) PDMCritSectRwEnterShared(PVMCC pVM, PPDMCRITSECTRW pCritSect, int rcBusy);
+VMMDECL(int) PDMCritSectRwEnterSharedDebug(PVMCC pVM, PPDMCRITSECTRW pCritSect, int rcBusy, RTHCUINTPTR uId, RT_SRC_POS_DECL);
+VMMDECL(int) PDMCritSectRwTryEnterShared(PVMCC pVM, PPDMCRITSECTRW pCritSect);
+VMMDECL(int) PDMCritSectRwTryEnterSharedDebug(PVMCC pVM, PPDMCRITSECTRW pCritSect, RTHCUINTPTR uId, RT_SRC_POS_DECL);
+VMMDECL(int) PDMCritSectRwLeaveShared(PVMCC pVM, PPDMCRITSECTRW pCritSect);
+VMMDECL(int) PDMCritSectRwEnterExcl(PVMCC pVM, PPDMCRITSECTRW pCritSect, int rcBusy);
+VMMDECL(int) PDMCritSectRwEnterExclDebug(PVMCC pVM, PPDMCRITSECTRW pCritSect, int rcBusy, RTHCUINTPTR uId, RT_SRC_POS_DECL);
+VMMDECL(int) PDMCritSectRwTryEnterExcl(PVMCC pVM, PPDMCRITSECTRW pCritSect);
+VMMDECL(int) PDMCritSectRwTryEnterExclDebug(PVMCC pVM, PPDMCRITSECTRW pCritSect, RTHCUINTPTR uId, RT_SRC_POS_DECL);
+VMMDECL(int) PDMCritSectRwLeaveExcl(PVMCC pVM, PPDMCRITSECTRW pCritSect);
+
+VMMDECL(bool) PDMCritSectRwIsWriteOwner(PVMCC pVM, PPDMCRITSECTRW pCritSect);
+VMMDECL(bool) PDMCritSectRwIsReadOwner(PVMCC pVM, PPDMCRITSECTRW pCritSect, bool fWannaHear);
+VMMDECL(uint32_t) PDMCritSectRwGetWriteRecursion(PPDMCRITSECTRW pCritSect);
+VMMDECL(uint32_t) PDMCritSectRwGetWriterReadRecursion(PPDMCRITSECTRW pCritSect);
+VMMDECL(uint32_t) PDMCritSectRwGetReadCount(PPDMCRITSECTRW pCritSect);
+VMMDECL(bool) PDMCritSectRwIsInitialized(PCPDMCRITSECTRW pCritSect);
+
+/* Lock strict build: Remap the three enter calls to the debug versions. */
+#ifdef VBOX_STRICT
+# ifdef IPRT_INCLUDED_asm_h
+# define PDMCritSectRwEnterExcl(a_pVM, pCritSect, rcBusy) PDMCritSectRwEnterExclDebug((a_pVM), pCritSect, rcBusy, (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
+# define PDMCritSectRwTryEnterExcl(a_pVM, pCritSect) PDMCritSectRwTryEnterExclDebug((a_pVM), pCritSect, (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
+# define PDMCritSectRwEnterShared(a_pVM, pCritSect, rcBusy) PDMCritSectRwEnterSharedDebug((a_pVM), pCritSect, rcBusy, (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
+# define PDMCritSectRwTryEnterShared(a_pVM, pCritSect) PDMCritSectRwTryEnterSharedDebug((a_pVM), pCritSect, (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
+# else
+# define PDMCritSectRwEnterExcl(a_pVM, pCritSect, rcBusy) PDMCritSectRwEnterExclDebug((a_pVM), pCritSect, rcBusy, 0, RT_SRC_POS)
+# define PDMCritSectRwTryEnterExcl(a_pVM, pCritSect) PDMCritSectRwTryEnterExclDebug((a_pVM), pCritSect, 0, RT_SRC_POS)
+# define PDMCritSectRwEnterShared(a_pVM, pCritSect, rcBusy) PDMCritSectRwEnterSharedDebug((a_pVM), pCritSect, rcBusy, 0, RT_SRC_POS)
+# define PDMCritSectRwTryEnterShared(a_pVM, pCritSect) PDMCritSectRwTryEnterSharedDebug((a_pVM), pCritSect, 0, RT_SRC_POS)
+# endif
+#endif
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !VBOX_INCLUDED_vmm_pdmcritsectrw_h */
+
diff --git a/include/VBox/vmm/pdmdev.h b/include/VBox/vmm/pdmdev.h
new file mode 100644
index 00000000..fd92fef8
--- /dev/null
+++ b/include/VBox/vmm/pdmdev.h
@@ -0,0 +1,9690 @@
+/** @file
+ * PDM - Pluggable Device Manager, Devices.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vmm_pdmdev_h
+#define VBOX_INCLUDED_vmm_pdmdev_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/vmm/pdmcritsect.h>
+#include <VBox/vmm/pdmcritsectrw.h>
+#include <VBox/vmm/pdmqueue.h>
+#include <VBox/vmm/pdmtask.h>
+#ifdef IN_RING3
+# include <VBox/vmm/pdmthread.h>
+#endif
+#include <VBox/vmm/pdmifs.h>
+#include <VBox/vmm/pdmins.h>
+#include <VBox/vmm/pdmcommon.h>
+#include <VBox/vmm/pdmpcidev.h>
+#include <VBox/vmm/iom.h>
+#include <VBox/vmm/mm.h>
+#include <VBox/vmm/tm.h>
+#include <VBox/vmm/ssm.h>
+#include <VBox/vmm/cfgm.h>
+#include <VBox/vmm/cpum.h>
+#include <VBox/vmm/dbgf.h>
+#include <VBox/vmm/pgm.h> /* PGMR3HandlerPhysicalTypeRegister() argument types. */
+#include <VBox/vmm/gim.h>
+#include <VBox/err.h> /* VINF_EM_DBG_STOP, also 120+ source files expecting this. */
+#include <VBox/msi.h>
+#include <iprt/stdarg.h>
+#include <iprt/list.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_pdm_device The PDM Devices API
+ * @ingroup grp_pdm
+ * @{
+ */
+
+/**
+ * Construct a device instance for a VM.
+ *
+ * @returns VBox status.
+ * @param pDevIns The device instance data. If the registration structure
+ * is needed, it can be accessed thru pDevIns->pReg.
+ * @param iInstance Instance number. Use this to figure out which registers
+ * and such to use. The instance number is also found in
+ * pDevIns->iInstance, but since it's likely to be
+ * frequently used PDM passes it as parameter.
+ * @param pCfg Configuration node handle for the driver. This is
+ * expected to be in high demand in the constructor and is
+ * therefore passed as an argument. When using it at other
+ * times, it can be found in pDevIns->pCfg.
+ */
+typedef DECLCALLBACKTYPE(int, FNPDMDEVCONSTRUCT,(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg));
+/** Pointer to a FNPDMDEVCONSTRUCT() function. */
+typedef FNPDMDEVCONSTRUCT *PFNPDMDEVCONSTRUCT;
+
+/**
+ * Destruct a device instance.
+ *
+ * Most VM resources are freed by the VM. This callback is provided so that any non-VM
+ * resources can be freed correctly.
+ *
+ * @returns VBox status.
+ * @param pDevIns The device instance data.
+ *
+ * @remarks The device critical section is not entered. The routine may delete
+ * the critical section, so the caller cannot exit it.
+ */
+typedef DECLCALLBACKTYPE(int, FNPDMDEVDESTRUCT,(PPDMDEVINS pDevIns));
+/** Pointer to a FNPDMDEVDESTRUCT() function. */
+typedef FNPDMDEVDESTRUCT *PFNPDMDEVDESTRUCT;
+
+/**
+ * Device relocation callback.
+ *
+ * This is called when the instance data has been relocated in raw-mode context
+ * (RC). It is also called when the RC hypervisor selects changes. The device
+ * must fixup all necessary pointers and re-query all interfaces to other RC
+ * devices and drivers.
+ *
+ * Before the RC code is executed the first time, this function will be called
+ * with a 0 delta so RC pointer calculations can be one in one place.
+ *
+ * @param pDevIns Pointer to the device instance.
+ * @param offDelta The relocation delta relative to the old location.
+ *
+ * @remarks A relocation CANNOT fail.
+ *
+ * @remarks The device critical section is not entered. The relocations should
+ * not normally require any locking.
+ */
+typedef DECLCALLBACKTYPE(void, FNPDMDEVRELOCATE,(PPDMDEVINS pDevIns, RTGCINTPTR offDelta));
+/** Pointer to a FNPDMDEVRELOCATE() function. */
+typedef FNPDMDEVRELOCATE *PFNPDMDEVRELOCATE;
+
+/**
+ * Power On notification.
+ *
+ * @returns VBox status.
+ * @param pDevIns The device instance data.
+ *
+ * @remarks Caller enters the device critical section.
+ */
+typedef DECLCALLBACKTYPE(void, FNPDMDEVPOWERON,(PPDMDEVINS pDevIns));
+/** Pointer to a FNPDMDEVPOWERON() function. */
+typedef FNPDMDEVPOWERON *PFNPDMDEVPOWERON;
+
+/**
+ * Reset notification.
+ *
+ * @returns VBox status.
+ * @param pDevIns The device instance data.
+ *
+ * @remarks Caller enters the device critical section.
+ */
+typedef DECLCALLBACKTYPE(void, FNPDMDEVRESET,(PPDMDEVINS pDevIns));
+/** Pointer to a FNPDMDEVRESET() function. */
+typedef FNPDMDEVRESET *PFNPDMDEVRESET;
+
+/**
+ * Soft reset notification.
+ *
+ * This is mainly for emulating the 286 style protected mode exits, in which
+ * most devices should remain in their current state.
+ *
+ * @returns VBox status.
+ * @param pDevIns The device instance data.
+ * @param fFlags PDMVMRESET_F_XXX (only bits relevant to soft resets).
+ *
+ * @remarks Caller enters the device critical section.
+ */
+typedef DECLCALLBACKTYPE(void, FNPDMDEVSOFTRESET,(PPDMDEVINS pDevIns, uint32_t fFlags));
+/** Pointer to a FNPDMDEVSOFTRESET() function. */
+typedef FNPDMDEVSOFTRESET *PFNPDMDEVSOFTRESET;
+
+/** @name PDMVMRESET_F_XXX - VM reset flags.
+ * These flags are used both for FNPDMDEVSOFTRESET and for hardware signalling
+ * reset via PDMDevHlpVMReset.
+ * @{ */
+/** Unknown reason. */
+#define PDMVMRESET_F_UNKNOWN UINT32_C(0x00000000)
+/** GIM triggered reset. */
+#define PDMVMRESET_F_GIM UINT32_C(0x00000001)
+/** The last source always causing hard resets. */
+#define PDMVMRESET_F_LAST_ALWAYS_HARD PDMVMRESET_F_GIM
+/** ACPI triggered reset. */
+#define PDMVMRESET_F_ACPI UINT32_C(0x0000000c)
+/** PS/2 system port A (92h) reset. */
+#define PDMVMRESET_F_PORT_A UINT32_C(0x0000000d)
+/** Keyboard reset. */
+#define PDMVMRESET_F_KBD UINT32_C(0x0000000e)
+/** Tripple fault. */
+#define PDMVMRESET_F_TRIPLE_FAULT UINT32_C(0x0000000f)
+/** Reset source mask. */
+#define PDMVMRESET_F_SRC_MASK UINT32_C(0x0000000f)
+/** @} */
+
+/**
+ * Suspend notification.
+ *
+ * @returns VBox status.
+ * @param pDevIns The device instance data.
+ * @thread EMT(0)
+ *
+ * @remarks Caller enters the device critical section.
+ */
+typedef DECLCALLBACKTYPE(void, FNPDMDEVSUSPEND,(PPDMDEVINS pDevIns));
+/** Pointer to a FNPDMDEVSUSPEND() function. */
+typedef FNPDMDEVSUSPEND *PFNPDMDEVSUSPEND;
+
+/**
+ * Resume notification.
+ *
+ * @returns VBox status.
+ * @param pDevIns The device instance data.
+ *
+ * @remarks Caller enters the device critical section.
+ */
+typedef DECLCALLBACKTYPE(void, FNPDMDEVRESUME,(PPDMDEVINS pDevIns));
+/** Pointer to a FNPDMDEVRESUME() function. */
+typedef FNPDMDEVRESUME *PFNPDMDEVRESUME;
+
+/**
+ * Power Off notification.
+ *
+ * This is always called when VMR3PowerOff is called.
+ * There will be no callback when hot plugging devices.
+ *
+ * @param pDevIns The device instance data.
+ * @thread EMT(0)
+ *
+ * @remarks Caller enters the device critical section.
+ */
+typedef DECLCALLBACKTYPE(void, FNPDMDEVPOWEROFF,(PPDMDEVINS pDevIns));
+/** Pointer to a FNPDMDEVPOWEROFF() function. */
+typedef FNPDMDEVPOWEROFF *PFNPDMDEVPOWEROFF;
+
+/**
+ * Attach command.
+ *
+ * This is called to let the device attach to a driver for a specified LUN
+ * at runtime. This is not called during VM construction, the device
+ * constructor has to attach to all the available drivers.
+ *
+ * This is like plugging in the keyboard or mouse after turning on the PC.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param iLUN The logical unit which is being attached.
+ * @param fFlags Flags, combination of the PDM_TACH_FLAGS_* \#defines.
+ *
+ * @remarks Caller enters the device critical section.
+ */
+typedef DECLCALLBACKTYPE(int, FNPDMDEVATTACH,(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t fFlags));
+/** Pointer to a FNPDMDEVATTACH() function. */
+typedef FNPDMDEVATTACH *PFNPDMDEVATTACH;
+
+/**
+ * Detach notification.
+ *
+ * This is called when a driver is detaching itself from a LUN of the device.
+ * The device should adjust its state to reflect this.
+ *
+ * This is like unplugging the network cable to use it for the laptop or
+ * something while the PC is still running.
+ *
+ * @param pDevIns The device instance.
+ * @param iLUN The logical unit which is being detached.
+ * @param fFlags Flags, combination of the PDMDEVATT_FLAGS_* \#defines.
+ *
+ * @remarks Caller enters the device critical section.
+ */
+typedef DECLCALLBACKTYPE(void, FNPDMDEVDETACH,(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t fFlags));
+/** Pointer to a FNPDMDEVDETACH() function. */
+typedef FNPDMDEVDETACH *PFNPDMDEVDETACH;
+
+/**
+ * Query the base interface of a logical unit.
+ *
+ * @returns VBOX status code.
+ * @param pDevIns The device instance.
+ * @param iLUN The logicial unit to query.
+ * @param ppBase Where to store the pointer to the base interface of the LUN.
+ *
+ * @remarks The device critical section is not entered.
+ */
+typedef DECLCALLBACKTYPE(int, FNPDMDEVQUERYINTERFACE,(PPDMDEVINS pDevIns, unsigned iLUN, PPDMIBASE *ppBase));
+/** Pointer to a FNPDMDEVQUERYINTERFACE() function. */
+typedef FNPDMDEVQUERYINTERFACE *PFNPDMDEVQUERYINTERFACE;
+
+/**
+ * Init complete notification (after ring-0 & RC init since 5.1).
+ *
+ * This can be done to do communication with other devices and other
+ * initialization which requires everything to be in place.
+ *
+ * @returns VBOX status code.
+ * @param pDevIns The device instance.
+ *
+ * @remarks Caller enters the device critical section.
+ */
+typedef DECLCALLBACKTYPE(int, FNPDMDEVINITCOMPLETE,(PPDMDEVINS pDevIns));
+/** Pointer to a FNPDMDEVINITCOMPLETE() function. */
+typedef FNPDMDEVINITCOMPLETE *PFNPDMDEVINITCOMPLETE;
+
+
+/**
+ * The context of a pfnMemSetup call.
+ */
+typedef enum PDMDEVMEMSETUPCTX
+{
+ /** Invalid zero value. */
+ PDMDEVMEMSETUPCTX_INVALID = 0,
+ /** After construction. */
+ PDMDEVMEMSETUPCTX_AFTER_CONSTRUCTION,
+ /** After reset. */
+ PDMDEVMEMSETUPCTX_AFTER_RESET,
+ /** Type size hack. */
+ PDMDEVMEMSETUPCTX_32BIT_HACK = 0x7fffffff
+} PDMDEVMEMSETUPCTX;
+
+
+/**
+ * PDM Device Registration Structure.
+ *
+ * This structure is used when registering a device from VBoxInitDevices() in HC
+ * Ring-3. PDM will continue use till the VM is terminated.
+ *
+ * @note The first part is the same in every context.
+ */
+typedef struct PDMDEVREGR3
+{
+ /** Structure version. PDM_DEVREGR3_VERSION defines the current version. */
+ uint32_t u32Version;
+ /** Reserved, must be zero. */
+ uint32_t uReserved0;
+ /** Device name, must match the ring-3 one. */
+ char szName[32];
+ /** Flags, combination of the PDM_DEVREG_FLAGS_* \#defines. */
+ uint32_t fFlags;
+ /** Device class(es), combination of the PDM_DEVREG_CLASS_* \#defines. */
+ uint32_t fClass;
+ /** Maximum number of instances (per VM). */
+ uint32_t cMaxInstances;
+ /** The shared data structure version number. */
+ uint32_t uSharedVersion;
+ /** Size of the instance data. */
+ uint32_t cbInstanceShared;
+ /** Size of the ring-0 instance data. */
+ uint32_t cbInstanceCC;
+ /** Size of the raw-mode instance data. */
+ uint32_t cbInstanceRC;
+ /** Max number of PCI devices. */
+ uint16_t cMaxPciDevices;
+ /** Max number of MSI-X vectors in any of the PCI devices. */
+ uint16_t cMaxMsixVectors;
+ /** The description of the device. The UTF-8 string pointed to shall, like this structure,
+ * remain unchanged from registration till VM destruction. */
+ const char *pszDescription;
+
+ /** Name of the raw-mode context module (no path).
+ * Only evalutated if PDM_DEVREG_FLAGS_RC is set. */
+ const char *pszRCMod;
+ /** Name of the ring-0 module (no path).
+ * Only evalutated if PDM_DEVREG_FLAGS_R0 is set. */
+ const char *pszR0Mod;
+
+ /** Construct instance - required. */
+ PFNPDMDEVCONSTRUCT pfnConstruct;
+ /** Destruct instance - optional.
+ * Critical section NOT entered (will be destroyed). */
+ PFNPDMDEVDESTRUCT pfnDestruct;
+ /** Relocation command - optional.
+ * Critical section NOT entered. */
+ PFNPDMDEVRELOCATE pfnRelocate;
+ /**
+ * Memory setup callback.
+ *
+ * @param pDevIns The device instance data.
+ * @param enmCtx Indicates the context of the call.
+ * @remarks The critical section is entered prior to calling this method.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnMemSetup, (PPDMDEVINS pDevIns, PDMDEVMEMSETUPCTX enmCtx));
+ /** Power on notification - optional.
+ * Critical section is entered. */
+ PFNPDMDEVPOWERON pfnPowerOn;
+ /** Reset notification - optional.
+ * Critical section is entered. */
+ PFNPDMDEVRESET pfnReset;
+ /** Suspend notification - optional.
+ * Critical section is entered. */
+ PFNPDMDEVSUSPEND pfnSuspend;
+ /** Resume notification - optional.
+ * Critical section is entered. */
+ PFNPDMDEVRESUME pfnResume;
+ /** Attach command - optional.
+ * Critical section is entered. */
+ PFNPDMDEVATTACH pfnAttach;
+ /** Detach notification - optional.
+ * Critical section is entered. */
+ PFNPDMDEVDETACH pfnDetach;
+ /** Query a LUN base interface - optional.
+ * Critical section is NOT entered. */
+ PFNPDMDEVQUERYINTERFACE pfnQueryInterface;
+ /** Init complete notification - optional.
+ * Critical section is entered. */
+ PFNPDMDEVINITCOMPLETE pfnInitComplete;
+ /** Power off notification - optional.
+ * Critical section is entered. */
+ PFNPDMDEVPOWEROFF pfnPowerOff;
+ /** Software system reset notification - optional.
+ * Critical section is entered. */
+ PFNPDMDEVSOFTRESET pfnSoftReset;
+
+ /** @name Reserved for future extensions, must be zero.
+ * @{ */
+ DECLR3CALLBACKMEMBER(int, pfnReserved0, (PPDMDEVINS pDevIns));
+ DECLR3CALLBACKMEMBER(int, pfnReserved1, (PPDMDEVINS pDevIns));
+ DECLR3CALLBACKMEMBER(int, pfnReserved2, (PPDMDEVINS pDevIns));
+ DECLR3CALLBACKMEMBER(int, pfnReserved3, (PPDMDEVINS pDevIns));
+ DECLR3CALLBACKMEMBER(int, pfnReserved4, (PPDMDEVINS pDevIns));
+ DECLR3CALLBACKMEMBER(int, pfnReserved5, (PPDMDEVINS pDevIns));
+ DECLR3CALLBACKMEMBER(int, pfnReserved6, (PPDMDEVINS pDevIns));
+ DECLR3CALLBACKMEMBER(int, pfnReserved7, (PPDMDEVINS pDevIns));
+ /** @} */
+
+ /** Initialization safty marker. */
+ uint32_t u32VersionEnd;
+} PDMDEVREGR3;
+/** Pointer to a PDM Device Structure. */
+typedef PDMDEVREGR3 *PPDMDEVREGR3;
+/** Const pointer to a PDM Device Structure. */
+typedef PDMDEVREGR3 const *PCPDMDEVREGR3;
+/** Current DEVREGR3 version number. */
+#define PDM_DEVREGR3_VERSION PDM_VERSION_MAKE(0xffff, 4, 0)
+
+
+/** PDM Device Flags.
+ * @{ */
+/** This flag is used to indicate that the device has a R0 component. */
+#define PDM_DEVREG_FLAGS_R0 UINT32_C(0x00000001)
+/** Requires the ring-0 component, ignore configuration values. */
+#define PDM_DEVREG_FLAGS_REQUIRE_R0 UINT32_C(0x00000002)
+/** Requires the ring-0 component, ignore configuration values. */
+#define PDM_DEVREG_FLAGS_OPT_IN_R0 UINT32_C(0x00000004)
+
+/** This flag is used to indicate that the device has a RC component. */
+#define PDM_DEVREG_FLAGS_RC UINT32_C(0x00000010)
+/** Requires the raw-mode component, ignore configuration values. */
+#define PDM_DEVREG_FLAGS_REQUIRE_RC UINT32_C(0x00000020)
+/** Requires the raw-mode component, ignore configuration values. */
+#define PDM_DEVREG_FLAGS_OPT_IN_RC UINT32_C(0x00000040)
+
+/** Convenience: PDM_DEVREG_FLAGS_R0 + PDM_DEVREG_FLAGS_RC */
+#define PDM_DEVREG_FLAGS_RZ (PDM_DEVREG_FLAGS_R0 | PDM_DEVREG_FLAGS_RC)
+
+/** @def PDM_DEVREG_FLAGS_HOST_BITS_DEFAULT
+ * The bit count for the current host.
+ * @note Superfluous, but still around for hysterical raisins. */
+#if HC_ARCH_BITS == 32
+# define PDM_DEVREG_FLAGS_HOST_BITS_DEFAULT UINT32_C(0x00000100)
+#elif HC_ARCH_BITS == 64
+# define PDM_DEVREG_FLAGS_HOST_BITS_DEFAULT UINT32_C(0x00000200)
+#else
+# error Unsupported HC_ARCH_BITS value.
+#endif
+/** The host bit count mask. */
+#define PDM_DEVREG_FLAGS_HOST_BITS_MASK UINT32_C(0x00000300)
+
+/** The device support only 32-bit guests. */
+#define PDM_DEVREG_FLAGS_GUEST_BITS_32 UINT32_C(0x00001000)
+/** The device support only 64-bit guests. */
+#define PDM_DEVREG_FLAGS_GUEST_BITS_64 UINT32_C(0x00002000)
+/** The device support both 32-bit & 64-bit guests. */
+#define PDM_DEVREG_FLAGS_GUEST_BITS_32_64 UINT32_C(0x00003000)
+/** @def PDM_DEVREG_FLAGS_GUEST_BITS_DEFAULT
+ * The guest bit count for the current compilation. */
+#if GC_ARCH_BITS == 32
+# define PDM_DEVREG_FLAGS_GUEST_BITS_DEFAULT PDM_DEVREG_FLAGS_GUEST_BITS_32
+#elif GC_ARCH_BITS == 64
+# define PDM_DEVREG_FLAGS_GUEST_BITS_DEFAULT PDM_DEVREG_FLAGS_GUEST_BITS_32_64
+#else
+# error Unsupported GC_ARCH_BITS value.
+#endif
+/** The guest bit count mask. */
+#define PDM_DEVREG_FLAGS_GUEST_BITS_MASK UINT32_C(0x00003000)
+
+/** A convenience. */
+#define PDM_DEVREG_FLAGS_DEFAULT_BITS (PDM_DEVREG_FLAGS_GUEST_BITS_DEFAULT | PDM_DEVREG_FLAGS_HOST_BITS_DEFAULT)
+
+/** Indicates that the device needs to be notified before the drivers when suspending. */
+#define PDM_DEVREG_FLAGS_FIRST_SUSPEND_NOTIFICATION UINT32_C(0x00010000)
+/** Indicates that the device needs to be notified before the drivers when powering off. */
+#define PDM_DEVREG_FLAGS_FIRST_POWEROFF_NOTIFICATION UINT32_C(0x00020000)
+/** Indicates that the device needs to be notified before the drivers when resetting. */
+#define PDM_DEVREG_FLAGS_FIRST_RESET_NOTIFICATION UINT32_C(0x00040000)
+
+/** This flag is used to indicate that the device has been converted to the
+ * new device style. */
+#define PDM_DEVREG_FLAGS_NEW_STYLE UINT32_C(0x80000000)
+
+/** @} */
+
+
+/** PDM Device Classes.
+ * The order is important, lower bit earlier instantiation.
+ * @{ */
+/** Architecture device. */
+#define PDM_DEVREG_CLASS_ARCH RT_BIT(0)
+/** Architecture BIOS device. */
+#define PDM_DEVREG_CLASS_ARCH_BIOS RT_BIT(1)
+/** PCI bus brigde. */
+#define PDM_DEVREG_CLASS_BUS_PCI RT_BIT(2)
+/** PCI built-in device (e.g. PCI root complex devices). */
+#define PDM_DEVREG_CLASS_PCI_BUILTIN RT_BIT(3)
+/** Input device (mouse, keyboard, joystick, HID, ...). */
+#define PDM_DEVREG_CLASS_INPUT RT_BIT(4)
+/** Interrupt controller (PIC). */
+#define PDM_DEVREG_CLASS_PIC RT_BIT(5)
+/** Interval controoler (PIT). */
+#define PDM_DEVREG_CLASS_PIT RT_BIT(6)
+/** RTC/CMOS. */
+#define PDM_DEVREG_CLASS_RTC RT_BIT(7)
+/** DMA controller. */
+#define PDM_DEVREG_CLASS_DMA RT_BIT(8)
+/** VMM Device. */
+#define PDM_DEVREG_CLASS_VMM_DEV RT_BIT(9)
+/** Graphics device, like VGA. */
+#define PDM_DEVREG_CLASS_GRAPHICS RT_BIT(10)
+/** Storage controller device. */
+#define PDM_DEVREG_CLASS_STORAGE RT_BIT(11)
+/** Network interface controller. */
+#define PDM_DEVREG_CLASS_NETWORK RT_BIT(12)
+/** Audio. */
+#define PDM_DEVREG_CLASS_AUDIO RT_BIT(13)
+/** USB HIC. */
+#define PDM_DEVREG_CLASS_BUS_USB RT_BIT(14)
+/** ACPI. */
+#define PDM_DEVREG_CLASS_ACPI RT_BIT(15)
+/** Serial controller device. */
+#define PDM_DEVREG_CLASS_SERIAL RT_BIT(16)
+/** Parallel controller device */
+#define PDM_DEVREG_CLASS_PARALLEL RT_BIT(17)
+/** Host PCI pass-through device */
+#define PDM_DEVREG_CLASS_HOST_DEV RT_BIT(18)
+/** Misc devices (always last). */
+#define PDM_DEVREG_CLASS_MISC RT_BIT(31)
+/** @} */
+
+
+/**
+ * PDM Device Registration Structure, ring-0.
+ *
+ * This structure is used when registering a device from VBoxInitDevices() in HC
+ * Ring-0. PDM will continue use till the VM is terminated.
+ */
+typedef struct PDMDEVREGR0
+{
+ /** Structure version. PDM_DEVREGR0_VERSION defines the current version. */
+ uint32_t u32Version;
+ /** Reserved, must be zero. */
+ uint32_t uReserved0;
+ /** Device name, must match the ring-3 one. */
+ char szName[32];
+ /** Flags, combination of the PDM_DEVREG_FLAGS_* \#defines. */
+ uint32_t fFlags;
+ /** Device class(es), combination of the PDM_DEVREG_CLASS_* \#defines. */
+ uint32_t fClass;
+ /** Maximum number of instances (per VM). */
+ uint32_t cMaxInstances;
+ /** The shared data structure version number. */
+ uint32_t uSharedVersion;
+ /** Size of the instance data. */
+ uint32_t cbInstanceShared;
+ /** Size of the ring-0 instance data. */
+ uint32_t cbInstanceCC;
+ /** Size of the raw-mode instance data. */
+ uint32_t cbInstanceRC;
+ /** Max number of PCI devices. */
+ uint16_t cMaxPciDevices;
+ /** Max number of MSI-X vectors in any of the PCI devices. */
+ uint16_t cMaxMsixVectors;
+ /** The description of the device. The UTF-8 string pointed to shall, like this structure,
+ * remain unchanged from registration till VM destruction. */
+ const char *pszDescription;
+
+ /**
+ * Early construction callback (optional).
+ *
+ * This is called right after the device instance structure has been allocated
+ * and before the ring-3 constructor gets called.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance data.
+ * @note The destructure is always called, regardless of the return status.
+ */
+ DECLR0CALLBACKMEMBER(int, pfnEarlyConstruct, (PPDMDEVINS pDevIns));
+
+ /**
+ * Regular construction callback (optional).
+ *
+ * This is called after (or during) the ring-3 constructor.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance data.
+ * @note The destructure is always called, regardless of the return status.
+ */
+ DECLR0CALLBACKMEMBER(int, pfnConstruct, (PPDMDEVINS pDevIns));
+
+ /**
+ * Destructor (optional).
+ *
+ * This is called after the ring-3 destruction. This is not called if ring-3
+ * fails to trigger it (e.g. process is killed or crashes).
+ *
+ * @param pDevIns The device instance data.
+ */
+ DECLR0CALLBACKMEMBER(void, pfnDestruct, (PPDMDEVINS pDevIns));
+
+ /**
+ * Final destructor (optional).
+ *
+ * This is called right before the memory is freed, which happens when the
+ * VM/GVM object is destroyed. This is always called.
+ *
+ * @param pDevIns The device instance data.
+ */
+ DECLR0CALLBACKMEMBER(void, pfnFinalDestruct, (PPDMDEVINS pDevIns));
+
+ /**
+ * Generic request handler (optional).
+ *
+ * @param pDevIns The device instance data.
+ * @param uReq Device specific request.
+ * @param uArg Request argument.
+ */
+ DECLR0CALLBACKMEMBER(int, pfnRequest, (PPDMDEVINS pDevIns, uint32_t uReq, uint64_t uArg));
+
+ /** @name Reserved for future extensions, must be zero.
+ * @{ */
+ DECLR0CALLBACKMEMBER(int, pfnReserved0, (PPDMDEVINS pDevIns));
+ DECLR0CALLBACKMEMBER(int, pfnReserved1, (PPDMDEVINS pDevIns));
+ DECLR0CALLBACKMEMBER(int, pfnReserved2, (PPDMDEVINS pDevIns));
+ DECLR0CALLBACKMEMBER(int, pfnReserved3, (PPDMDEVINS pDevIns));
+ DECLR0CALLBACKMEMBER(int, pfnReserved4, (PPDMDEVINS pDevIns));
+ DECLR0CALLBACKMEMBER(int, pfnReserved5, (PPDMDEVINS pDevIns));
+ DECLR0CALLBACKMEMBER(int, pfnReserved6, (PPDMDEVINS pDevIns));
+ DECLR0CALLBACKMEMBER(int, pfnReserved7, (PPDMDEVINS pDevIns));
+ /** @} */
+
+ /** Initialization safty marker. */
+ uint32_t u32VersionEnd;
+} PDMDEVREGR0;
+/** Pointer to a ring-0 PDM device registration structure. */
+typedef PDMDEVREGR0 *PPDMDEVREGR0;
+/** Pointer to a const ring-0 PDM device registration structure. */
+typedef PDMDEVREGR0 const *PCPDMDEVREGR0;
+/** Current DEVREGR0 version number. */
+#define PDM_DEVREGR0_VERSION PDM_VERSION_MAKE(0xff80, 1, 0)
+
+
+/**
+ * PDM Device Registration Structure, raw-mode
+ *
+ * At the moment, this structure is mostly here to match the other two contexts.
+ */
+typedef struct PDMDEVREGRC
+{
+ /** Structure version. PDM_DEVREGRC_VERSION defines the current version. */
+ uint32_t u32Version;
+ /** Reserved, must be zero. */
+ uint32_t uReserved0;
+ /** Device name, must match the ring-3 one. */
+ char szName[32];
+ /** Flags, combination of the PDM_DEVREG_FLAGS_* \#defines. */
+ uint32_t fFlags;
+ /** Device class(es), combination of the PDM_DEVREG_CLASS_* \#defines. */
+ uint32_t fClass;
+ /** Maximum number of instances (per VM). */
+ uint32_t cMaxInstances;
+ /** The shared data structure version number. */
+ uint32_t uSharedVersion;
+ /** Size of the instance data. */
+ uint32_t cbInstanceShared;
+ /** Size of the ring-0 instance data. */
+ uint32_t cbInstanceCC;
+ /** Size of the raw-mode instance data. */
+ uint32_t cbInstanceRC;
+ /** Max number of PCI devices. */
+ uint16_t cMaxPciDevices;
+ /** Max number of MSI-X vectors in any of the PCI devices. */
+ uint16_t cMaxMsixVectors;
+ /** The description of the device. The UTF-8 string pointed to shall, like this structure,
+ * remain unchanged from registration till VM destruction. */
+ const char *pszDescription;
+
+ /**
+ * Constructor callback.
+ *
+ * This is called much later than both the ring-0 and ring-3 constructors, since
+ * raw-mode v2 require a working VMM to run actual code.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance data.
+ * @note The destructure is always called, regardless of the return status.
+ */
+ DECLRGCALLBACKMEMBER(int, pfnConstruct, (PPDMDEVINS pDevIns));
+
+ /** @name Reserved for future extensions, must be zero.
+ * @{ */
+ DECLRCCALLBACKMEMBER(int, pfnReserved0, (PPDMDEVINS pDevIns));
+ DECLRCCALLBACKMEMBER(int, pfnReserved1, (PPDMDEVINS pDevIns));
+ DECLRCCALLBACKMEMBER(int, pfnReserved2, (PPDMDEVINS pDevIns));
+ DECLRCCALLBACKMEMBER(int, pfnReserved3, (PPDMDEVINS pDevIns));
+ DECLRCCALLBACKMEMBER(int, pfnReserved4, (PPDMDEVINS pDevIns));
+ DECLRCCALLBACKMEMBER(int, pfnReserved5, (PPDMDEVINS pDevIns));
+ DECLRCCALLBACKMEMBER(int, pfnReserved6, (PPDMDEVINS pDevIns));
+ DECLRCCALLBACKMEMBER(int, pfnReserved7, (PPDMDEVINS pDevIns));
+ /** @} */
+
+ /** Initialization safty marker. */
+ uint32_t u32VersionEnd;
+} PDMDEVREGRC;
+/** Pointer to a raw-mode PDM device registration structure. */
+typedef PDMDEVREGRC *PPDMDEVREGRC;
+/** Pointer to a const raw-mode PDM device registration structure. */
+typedef PDMDEVREGRC const *PCPDMDEVREGRC;
+/** Current DEVREGRC version number. */
+#define PDM_DEVREGRC_VERSION PDM_VERSION_MAKE(0xff81, 1, 0)
+
+
+
+/** @def PDM_DEVREG_VERSION
+ * Current DEVREG version number. */
+/** @typedef PDMDEVREGR3
+ * A current context PDM device registration structure. */
+/** @typedef PPDMDEVREGR3
+ * Pointer to a current context PDM device registration structure. */
+/** @typedef PCPDMDEVREGR3
+ * Pointer to a const current context PDM device registration structure. */
+#if defined(IN_RING3) || defined(DOXYGEN_RUNNING)
+# define PDM_DEVREG_VERSION PDM_DEVREGR3_VERSION
+typedef PDMDEVREGR3 PDMDEVREG;
+typedef PPDMDEVREGR3 PPDMDEVREG;
+typedef PCPDMDEVREGR3 PCPDMDEVREG;
+#elif defined(IN_RING0)
+# define PDM_DEVREG_VERSION PDM_DEVREGR0_VERSION
+typedef PDMDEVREGR0 PDMDEVREG;
+typedef PPDMDEVREGR0 PPDMDEVREG;
+typedef PCPDMDEVREGR0 PCPDMDEVREG;
+#elif defined(IN_RC)
+# define PDM_DEVREG_VERSION PDM_DEVREGRC_VERSION
+typedef PDMDEVREGRC PDMDEVREG;
+typedef PPDMDEVREGRC PPDMDEVREG;
+typedef PCPDMDEVREGRC PCPDMDEVREG;
+#else
+# error "Not IN_RING3, IN_RING0 or IN_RC"
+#endif
+
+
+/**
+ * Device registrations for ring-0 modules.
+ *
+ * This structure is used directly and must therefore reside in persistent
+ * memory (i.e. the data section).
+ */
+typedef struct PDMDEVMODREGR0
+{
+ /** The structure version (PDM_DEVMODREGR0_VERSION). */
+ uint32_t u32Version;
+ /** Number of devices in the array papDevRegs points to. */
+ uint32_t cDevRegs;
+ /** Pointer to device registration structures. */
+ PCPDMDEVREGR0 *papDevRegs;
+ /** The ring-0 module handle - PDM internal, fingers off. */
+ void *hMod;
+ /** List entry - PDM internal, fingers off. */
+ RTLISTNODE ListEntry;
+} PDMDEVMODREGR0;
+/** Pointer to device registriations for a ring-0 module. */
+typedef PDMDEVMODREGR0 *PPDMDEVMODREGR0;
+/** Current PDMDEVMODREGR0 version number. */
+#define PDM_DEVMODREGR0_VERSION PDM_VERSION_MAKE(0xff85, 1, 0)
+
+
+/** @name IRQ Level for use with the *SetIrq APIs.
+ * @{
+ */
+/** Assert the IRQ (can assume value 1). */
+#define PDM_IRQ_LEVEL_HIGH RT_BIT(0)
+/** Deassert the IRQ (can assume value 0). */
+#define PDM_IRQ_LEVEL_LOW 0
+/** flip-flop - deassert and then assert the IRQ again immediately (PIC) /
+ * automatically deasserts it after delivery to the APIC (IOAPIC).
+ * @note Only suitable for edge trigger interrupts. */
+#define PDM_IRQ_LEVEL_FLIP_FLOP (RT_BIT(1) | PDM_IRQ_LEVEL_HIGH)
+/** @} */
+
+/**
+ * Registration record for MSI/MSI-X emulation.
+ */
+typedef struct PDMMSIREG
+{
+ /** Number of MSI interrupt vectors, 0 if MSI not supported */
+ uint16_t cMsiVectors;
+ /** Offset of MSI capability */
+ uint8_t iMsiCapOffset;
+ /** Offset of next capability to MSI */
+ uint8_t iMsiNextOffset;
+ /** If we support 64-bit MSI addressing */
+ bool fMsi64bit;
+ /** If we do not support per-vector masking */
+ bool fMsiNoMasking;
+
+ /** Number of MSI-X interrupt vectors, 0 if MSI-X not supported */
+ uint16_t cMsixVectors;
+ /** Offset of MSI-X capability */
+ uint8_t iMsixCapOffset;
+ /** Offset of next capability to MSI-X */
+ uint8_t iMsixNextOffset;
+ /** Value of PCI BAR (base addresss register) assigned by device for MSI-X page access */
+ uint8_t iMsixBar;
+} PDMMSIREG;
+typedef PDMMSIREG *PPDMMSIREG;
+
+/**
+ * PCI Bus registration structure.
+ * All the callbacks, except the PCIBIOS hack, are working on PCI devices.
+ */
+typedef struct PDMPCIBUSREGR3
+{
+ /** Structure version number. PDM_PCIBUSREGR3_VERSION defines the current version. */
+ uint32_t u32Version;
+
+ /**
+ * Registers the device with the default PCI bus.
+ *
+ * @returns VBox status code.
+ * @param pDevIns Device instance of the PCI Bus.
+ * @param pPciDev The PCI device structure.
+ * @param fFlags Reserved for future use, PDMPCIDEVREG_F_MBZ.
+ * @param uPciDevNo PDMPCIDEVREG_DEV_NO_FIRST_UNUSED, or a specific
+ * device number (0-31).
+ * @param uPciFunNo PDMPCIDEVREG_FUN_NO_FIRST_UNUSED, or a specific
+ * function number (0-7).
+ * @param pszName Device name (static but not unique).
+ *
+ * @remarks Caller enters the PDM critical section.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnRegisterR3,(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t fFlags,
+ uint8_t uPciDevNo, uint8_t uPciFunNo, const char *pszName));
+
+ /**
+ * Initialize MSI or MSI-X emulation support in a PCI device.
+ *
+ * This cannot handle all corner cases of the MSI/MSI-X spec, but for the
+ * vast majority of device emulation it covers everything necessary. It's
+ * fully automatic, taking care of all BAR and config space requirements,
+ * and interrupt delivery is done using PDMDevHlpPCISetIrq and friends.
+ * When MSI/MSI-X is enabled then the iIrq parameter is redefined to take
+ * the vector number (otherwise it has the usual INTA-D meaning for PCI).
+ *
+ * A device not using this can still offer MSI/MSI-X. In this case it's
+ * completely up to the device (in the MSI-X case) to create/register the
+ * necessary MMIO BAR, handle all config space/BAR updating and take care
+ * of delivering the interrupts appropriately.
+ *
+ * @returns VBox status code.
+ * @param pDevIns Device instance of the PCI Bus.
+ * @param pPciDev The PCI device structure.
+ * @param pMsiReg MSI emulation registration structure
+ * @remarks Caller enters the PDM critical section.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnRegisterMsiR3,(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, PPDMMSIREG pMsiReg));
+
+ /**
+ * Registers a I/O region (memory mapped or I/O ports) for a PCI device.
+ *
+ * @returns VBox status code.
+ * @param pDevIns Device instance of the PCI Bus.
+ * @param pPciDev The PCI device structure.
+ * @param iRegion The region number.
+ * @param cbRegion Size of the region.
+ * @param enmType PCI_ADDRESS_SPACE_MEM, PCI_ADDRESS_SPACE_IO or
+ * PCI_ADDRESS_SPACE_MEM_PREFETCH, optionally with
+ * PCI_ADDRESS_SPACE_BAR64 or'ed in.
+ * @param fFlags PDMPCIDEV_IORGN_F_XXX.
+ * @param hHandle An I/O port, MMIO or MMIO2 handle according to
+ * @a fFlags, UINT64_MAX if no handle is passed
+ * (old style).
+ * @param pfnMapUnmap Callback for doing the mapping. Optional if a handle
+ * is given.
+ * @remarks Caller enters the PDM critical section.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnIORegionRegisterR3,(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t iRegion,
+ RTGCPHYS cbRegion, PCIADDRESSSPACE enmType, uint32_t fFlags,
+ uint64_t hHandle, PFNPCIIOREGIONMAP pfnMapUnmap));
+
+ /**
+ * Register PCI configuration space read/write intercept callbacks.
+ *
+ * @param pDevIns Device instance of the PCI Bus.
+ * @param pPciDev The PCI device structure.
+ * @param pfnRead Pointer to the user defined PCI config read function.
+ * @param pfnWrite Pointer to the user defined PCI config write function.
+ * to call default PCI config write function. Can be NULL.
+ * @remarks Caller enters the PDM critical section.
+ * @thread EMT
+ */
+ DECLR3CALLBACKMEMBER(void, pfnInterceptConfigAccesses,(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev,
+ PFNPCICONFIGREAD pfnRead, PFNPCICONFIGWRITE pfnWrite));
+
+ /**
+ * Perform a PCI configuration space write, bypassing interception.
+ *
+ * This is for devices that make use of PDMDevHlpPCIInterceptConfigAccesses().
+ *
+ * @returns Strict VBox status code (mainly DBGFSTOP).
+ * @param pDevIns Device instance of the PCI Bus.
+ * @param pPciDev The PCI device which config space is being read.
+ * @param uAddress The config space address.
+ * @param cb The size of the read: 1, 2 or 4 bytes.
+ * @param u32Value The value to write.
+ * @note The caller (PDM) does not enter the PDM critsect, but it is possible
+ * that the (root) bus will have done that already.
+ */
+ DECLR3CALLBACKMEMBER(VBOXSTRICTRC, pfnConfigWrite,(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev,
+ uint32_t uAddress, unsigned cb, uint32_t u32Value));
+
+ /**
+ * Perform a PCI configuration space read, bypassing interception.
+ *
+ * This is for devices that make use of PDMDevHlpPCIInterceptConfigAccesses().
+ *
+ * @returns Strict VBox status code (mainly DBGFSTOP).
+ * @param pDevIns Device instance of the PCI Bus.
+ * @param pPciDev The PCI device which config space is being read.
+ * @param uAddress The config space address.
+ * @param cb The size of the read: 1, 2 or 4 bytes.
+ * @param pu32Value Where to return the value.
+ * @note The caller (PDM) does not enter the PDM critsect, but it is possible
+ * that the (root) bus will have done that already.
+ */
+ DECLR3CALLBACKMEMBER(VBOXSTRICTRC, pfnConfigRead,(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev,
+ uint32_t uAddress, unsigned cb, uint32_t *pu32Value));
+
+ /**
+ * Set the IRQ for a PCI device.
+ *
+ * @param pDevIns Device instance of the PCI Bus.
+ * @param pPciDev The PCI device structure.
+ * @param iIrq IRQ number to set.
+ * @param iLevel IRQ level. See the PDM_IRQ_LEVEL_* \#defines.
+ * @param uTagSrc The IRQ tag and source (for tracing).
+ * @remarks Caller enters the PDM critical section.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnSetIrqR3,(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, int iIrq, int iLevel, uint32_t uTagSrc));
+
+ /** Marks the end of the structure with PDM_PCIBUSREGR3_VERSION. */
+ uint32_t u32EndVersion;
+} PDMPCIBUSREGR3;
+/** Pointer to a PCI bus registration structure. */
+typedef PDMPCIBUSREGR3 *PPDMPCIBUSREGR3;
+/** Current PDMPCIBUSREGR3 version number. */
+#define PDM_PCIBUSREGR3_VERSION PDM_VERSION_MAKE(0xff86, 2, 0)
+
+/**
+ * PCI Bus registration structure for ring-0.
+ */
+typedef struct PDMPCIBUSREGR0
+{
+ /** Structure version number. PDM_PCIBUSREGR0_VERSION defines the current version. */
+ uint32_t u32Version;
+ /** The PCI bus number (from ring-3 registration). */
+ uint32_t iBus;
+ /**
+ * Set the IRQ for a PCI device.
+ *
+ * @param pDevIns Device instance of the PCI Bus.
+ * @param pPciDev The PCI device structure.
+ * @param iIrq IRQ number to set.
+ * @param iLevel IRQ level. See the PDM_IRQ_LEVEL_* \#defines.
+ * @param uTagSrc The IRQ tag and source (for tracing).
+ * @remarks Caller enters the PDM critical section.
+ */
+ DECLR0CALLBACKMEMBER(void, pfnSetIrq,(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, int iIrq, int iLevel, uint32_t uTagSrc));
+ /** Marks the end of the structure with PDM_PCIBUSREGR0_VERSION. */
+ uint32_t u32EndVersion;
+} PDMPCIBUSREGR0;
+/** Pointer to a PCI bus ring-0 registration structure. */
+typedef PDMPCIBUSREGR0 *PPDMPCIBUSREGR0;
+/** Current PDMPCIBUSREGR0 version number. */
+#define PDM_PCIBUSREGR0_VERSION PDM_VERSION_MAKE(0xff87, 1, 0)
+
+/**
+ * PCI Bus registration structure for raw-mode.
+ */
+typedef struct PDMPCIBUSREGRC
+{
+ /** Structure version number. PDM_PCIBUSREGRC_VERSION defines the current version. */
+ uint32_t u32Version;
+ /** The PCI bus number (from ring-3 registration). */
+ uint32_t iBus;
+ /**
+ * Set the IRQ for a PCI device.
+ *
+ * @param pDevIns Device instance of the PCI Bus.
+ * @param pPciDev The PCI device structure.
+ * @param iIrq IRQ number to set.
+ * @param iLevel IRQ level. See the PDM_IRQ_LEVEL_* \#defines.
+ * @param uTagSrc The IRQ tag and source (for tracing).
+ * @remarks Caller enters the PDM critical section.
+ */
+ DECLRCCALLBACKMEMBER(void, pfnSetIrq,(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, int iIrq, int iLevel, uint32_t uTagSrc));
+ /** Marks the end of the structure with PDM_PCIBUSREGRC_VERSION. */
+ uint32_t u32EndVersion;
+} PDMPCIBUSREGRC;
+/** Pointer to a PCI bus raw-mode registration structure. */
+typedef PDMPCIBUSREGRC *PPDMPCIBUSREGRC;
+/** Current PDMPCIBUSREGRC version number. */
+#define PDM_PCIBUSREGRC_VERSION PDM_VERSION_MAKE(0xff88, 1, 0)
+
+/** PCI bus registration structure for the current context. */
+typedef CTX_SUFF(PDMPCIBUSREG) PDMPCIBUSREGCC;
+/** Pointer to a PCI bus registration structure for the current context. */
+typedef CTX_SUFF(PPDMPCIBUSREG) PPDMPCIBUSREGCC;
+/** PCI bus registration structure version for the current context. */
+#define PDM_PCIBUSREGCC_VERSION CTX_MID(PDM_PCIBUSREG,_VERSION)
+
+
+/**
+ * PCI Bus RC helpers.
+ */
+typedef struct PDMPCIHLPRC
+{
+ /** Structure version. PDM_PCIHLPRC_VERSION defines the current version. */
+ uint32_t u32Version;
+
+ /**
+ * Set an ISA IRQ.
+ *
+ * @param pDevIns PCI device instance.
+ * @param iIrq IRQ number to set.
+ * @param iLevel IRQ level. See the PDM_IRQ_LEVEL_* \#defines.
+ * @param uTagSrc The IRQ tag and source (for tracing).
+ * @thread EMT only.
+ */
+ DECLRCCALLBACKMEMBER(void, pfnIsaSetIrq,(PPDMDEVINS pDevIns, int iIrq, int iLevel, uint32_t uTagSrc));
+
+ /**
+ * Set an I/O-APIC IRQ.
+ *
+ * @param pDevIns PCI device instance.
+ * @param uBusDevFn The bus:device:function of the device initiating the
+ * IRQ. Pass NIL_PCIBDF when it's not a PCI device or
+ * interrupt.
+ * @param iIrq IRQ number to set.
+ * @param iLevel IRQ level. See the PDM_IRQ_LEVEL_* \#defines.
+ * @param uTagSrc The IRQ tag and source (for tracing).
+ * @thread EMT only.
+ */
+ DECLRCCALLBACKMEMBER(void, pfnIoApicSetIrq,(PPDMDEVINS pDevIns, PCIBDF uBusDevFn, int iIrq, int iLevel, uint32_t uTagSrc));
+
+ /**
+ * Send an MSI.
+ *
+ * @param pDevIns PCI device instance.
+ * @param uBusDevFn The bus:device:function of the device initiating the
+ * MSI. Cannot be NIL_PCIBDF.
+ * @param pMsi The MSI to send.
+ * @param uTagSrc The IRQ tag and source (for tracing).
+ * @thread EMT only.
+ */
+ DECLRCCALLBACKMEMBER(void, pfnIoApicSendMsi,(PPDMDEVINS pDevIns, PCIBDF uBusDevFn, PCMSIMSG pMsi, uint32_t uTagSrc));
+
+
+ /**
+ * Acquires the PDM lock.
+ *
+ * @returns VINF_SUCCESS on success.
+ * @returns rc if we failed to acquire the lock.
+ * @param pDevIns The PCI device instance.
+ * @param rc What to return if we fail to acquire the lock.
+ *
+ * @sa PDMCritSectEnter
+ */
+ DECLRCCALLBACKMEMBER(int, pfnLock,(PPDMDEVINS pDevIns, int rc));
+
+ /**
+ * Releases the PDM lock.
+ *
+ * @param pDevIns The PCI device instance.
+ */
+ DECLRCCALLBACKMEMBER(void, pfnUnlock,(PPDMDEVINS pDevIns));
+
+ /**
+ * Gets a bus by it's PDM ordinal (typically the parent bus).
+ *
+ * @returns Pointer to the device instance of the bus.
+ * @param pDevIns The PCI bus device instance.
+ * @param idxPdmBus The PDM ordinal value of the bus to get.
+ */
+ DECLRCCALLBACKMEMBER(PPDMDEVINS, pfnGetBusByNo,(PPDMDEVINS pDevIns, uint32_t idxPdmBus));
+
+ /** Just a safety precaution. */
+ uint32_t u32TheEnd;
+} PDMPCIHLPRC;
+/** Pointer to PCI helpers. */
+typedef RCPTRTYPE(PDMPCIHLPRC *) PPDMPCIHLPRC;
+/** Pointer to const PCI helpers. */
+typedef RCPTRTYPE(const PDMPCIHLPRC *) PCPDMPCIHLPRC;
+
+/** Current PDMPCIHLPRC version number. */
+#define PDM_PCIHLPRC_VERSION PDM_VERSION_MAKE(0xfffd, 4, 0)
+
+
+/**
+ * PCI Bus R0 helpers.
+ */
+typedef struct PDMPCIHLPR0
+{
+ /** Structure version. PDM_PCIHLPR0_VERSION defines the current version. */
+ uint32_t u32Version;
+
+ /**
+ * Set an ISA IRQ.
+ *
+ * @param pDevIns PCI device instance.
+ * @param iIrq IRQ number to set.
+ * @param iLevel IRQ level. See the PDM_IRQ_LEVEL_* \#defines.
+ * @param uTagSrc The IRQ tag and source (for tracing).
+ * @thread EMT only.
+ */
+ DECLR0CALLBACKMEMBER(void, pfnIsaSetIrq,(PPDMDEVINS pDevIns, int iIrq, int iLevel, uint32_t uTagSrc));
+
+ /**
+ * Set an I/O-APIC IRQ.
+ *
+ * @param pDevIns PCI device instance.
+ * @param uBusDevFn The bus:device:function of the device initiating the
+ * IRQ. Pass NIL_PCIBDF when it's not a PCI device or
+ * interrupt.
+ * @param iIrq IRQ number to set.
+ * @param iLevel IRQ level. See the PDM_IRQ_LEVEL_* \#defines.
+ * @param uTagSrc The IRQ tag and source (for tracing).
+ * @thread EMT only.
+ */
+ DECLR0CALLBACKMEMBER(void, pfnIoApicSetIrq,(PPDMDEVINS pDevIns, PCIBDF uBusDevFn, int iIrq, int iLevel, uint32_t uTagSrc));
+
+ /**
+ * Send an MSI.
+ *
+ * @param pDevIns PCI device instance.
+ * @param uBusDevFn The bus:device:function of the device initiating the
+ * MSI. Cannot be NIL_PCIBDF.
+ * @param pMsi The MSI to send.
+ * @param uTagSrc The IRQ tag and source (for tracing).
+ * @thread EMT only.
+ */
+ DECLR0CALLBACKMEMBER(void, pfnIoApicSendMsi,(PPDMDEVINS pDevIns, PCIBDF uBusDevFn, PCMSIMSG pMsi, uint32_t uTagSrc));
+
+ /**
+ * Acquires the PDM lock.
+ *
+ * @returns VINF_SUCCESS on success.
+ * @returns rc if we failed to acquire the lock.
+ * @param pDevIns The PCI device instance.
+ * @param rc What to return if we fail to acquire the lock.
+ *
+ * @sa PDMCritSectEnter
+ */
+ DECLR0CALLBACKMEMBER(int, pfnLock,(PPDMDEVINS pDevIns, int rc));
+
+ /**
+ * Releases the PDM lock.
+ *
+ * @param pDevIns The PCI device instance.
+ */
+ DECLR0CALLBACKMEMBER(void, pfnUnlock,(PPDMDEVINS pDevIns));
+
+ /**
+ * Gets a bus by it's PDM ordinal (typically the parent bus).
+ *
+ * @returns Pointer to the device instance of the bus.
+ * @param pDevIns The PCI bus device instance.
+ * @param idxPdmBus The PDM ordinal value of the bus to get.
+ */
+ DECLR0CALLBACKMEMBER(PPDMDEVINS, pfnGetBusByNo,(PPDMDEVINS pDevIns, uint32_t idxPdmBus));
+
+ /** Just a safety precaution. */
+ uint32_t u32TheEnd;
+} PDMPCIHLPR0;
+/** Pointer to PCI helpers. */
+typedef R0PTRTYPE(PDMPCIHLPR0 *) PPDMPCIHLPR0;
+/** Pointer to const PCI helpers. */
+typedef R0PTRTYPE(const PDMPCIHLPR0 *) PCPDMPCIHLPR0;
+
+/** Current PDMPCIHLPR0 version number. */
+#define PDM_PCIHLPR0_VERSION PDM_VERSION_MAKE(0xfffc, 6, 0)
+
+/**
+ * PCI device helpers.
+ */
+typedef struct PDMPCIHLPR3
+{
+ /** Structure version. PDM_PCIHLPR3_VERSION defines the current version. */
+ uint32_t u32Version;
+
+ /**
+ * Set an ISA IRQ.
+ *
+ * @param pDevIns The PCI device instance.
+ * @param iIrq IRQ number to set.
+ * @param iLevel IRQ level. See the PDM_IRQ_LEVEL_* \#defines.
+ * @param uTagSrc The IRQ tag and source (for tracing).
+ */
+ DECLR3CALLBACKMEMBER(void, pfnIsaSetIrq,(PPDMDEVINS pDevIns, int iIrq, int iLevel, uint32_t uTagSrc));
+
+ /**
+ * Set an I/O-APIC IRQ.
+ *
+ * @param pDevIns The PCI device instance.
+ * @param uBusDevFn The bus:device:function of the device initiating the
+ * IRQ. Pass NIL_PCIBDF when it's not a PCI device or
+ * interrupt.
+ * @param iIrq IRQ number to set.
+ * @param iLevel IRQ level. See the PDM_IRQ_LEVEL_* \#defines.
+ * @param uTagSrc The IRQ tag and source (for tracing).
+ */
+ DECLR3CALLBACKMEMBER(void, pfnIoApicSetIrq,(PPDMDEVINS pDevIns, PCIBDF uBusDevFn, int iIrq, int iLevel, uint32_t uTagSrc));
+
+ /**
+ * Send an MSI.
+ *
+ * @param pDevIns PCI device instance.
+ * @param uBusDevFn The bus:device:function of the device initiating the
+ * MSI. Cannot be NIL_PCIBDF.
+ * @param pMsi The MSI to send.
+ * @param uTagSrc The IRQ tag and source (for tracing).
+ */
+ DECLR3CALLBACKMEMBER(void, pfnIoApicSendMsi,(PPDMDEVINS pDevIns, PCIBDF uBusDevFn, PCMSIMSG pMsi, uint32_t uTagSrc));
+
+ /**
+ * Acquires the PDM lock.
+ *
+ * @returns VINF_SUCCESS on success.
+ * @returns Fatal error on failure.
+ * @param pDevIns The PCI device instance.
+ * @param rc Dummy for making the interface identical to the RC and R0 versions.
+ *
+ * @sa PDMCritSectEnter
+ */
+ DECLR3CALLBACKMEMBER(int, pfnLock,(PPDMDEVINS pDevIns, int rc));
+
+ /**
+ * Releases the PDM lock.
+ *
+ * @param pDevIns The PCI device instance.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnUnlock,(PPDMDEVINS pDevIns));
+
+ /**
+ * Gets a bus by it's PDM ordinal (typically the parent bus).
+ *
+ * @returns Pointer to the device instance of the bus.
+ * @param pDevIns The PCI bus device instance.
+ * @param idxPdmBus The PDM ordinal value of the bus to get.
+ */
+ DECLR3CALLBACKMEMBER(PPDMDEVINS, pfnGetBusByNo,(PPDMDEVINS pDevIns, uint32_t idxPdmBus));
+
+ /** Just a safety precaution. */
+ uint32_t u32TheEnd;
+} PDMPCIHLPR3;
+/** Pointer to PCI helpers. */
+typedef R3PTRTYPE(PDMPCIHLPR3 *) PPDMPCIHLPR3;
+/** Pointer to const PCI helpers. */
+typedef R3PTRTYPE(const PDMPCIHLPR3 *) PCPDMPCIHLPR3;
+
+/** Current PDMPCIHLPR3 version number. */
+#define PDM_PCIHLPR3_VERSION PDM_VERSION_MAKE(0xfffb, 5, 0)
+
+
+/** @name PDMIOMMU_MEM_F_XXX - IOMMU memory access transaction flags.
+ * These flags are used for memory access transactions via the IOMMU interface.
+ * @{ */
+/** Memory read. */
+#define PDMIOMMU_MEM_F_READ RT_BIT_32(0)
+/** Memory write. */
+#define PDMIOMMU_MEM_F_WRITE RT_BIT_32(1)
+/** Valid flag mask. */
+#define PDMIOMMU_MEM_F_VALID_MASK (PDMIOMMU_MEM_F_READ | PDMIOMMU_MEM_F_WRITE)
+/** @} */
+
+/**
+ * IOMMU registration structure for ring-0.
+ */
+typedef struct PDMIOMMUREGR0
+{
+ /** Structure version number. PDM_IOMMUREG_VERSION defines the current
+ * version. */
+ uint32_t u32Version;
+ /** Index into the PDM IOMMU array (PDM::aIommus) from ring-3. */
+ uint32_t idxIommu;
+
+ /**
+ * Translates the physical address for a memory transaction through the IOMMU.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The IOMMU device instance.
+ * @param idDevice The device identifier (bus, device, function).
+ * @param uIova The I/O virtual address being accessed.
+ * @param cbIova The size of the access.
+ * @param fFlags Access flags, see PDMIOMMU_MEM_F_XXX.
+ * @param pGCPhysSpa Where to store the translated system physical address.
+ * @param pcbContiguous Where to store the number of contiguous bytes translated
+ * and permission-checked.
+ *
+ * @thread Any.
+ */
+ DECLR0CALLBACKMEMBER(int, pfnMemAccess,(PPDMDEVINS pDevIns, uint16_t idDevice, uint64_t uIova, size_t cbIova,
+ uint32_t fFlags, PRTGCPHYS pGCPhysSpa, size_t *pcbContiguous));
+
+ /**
+ * Translates in bulk physical page addresses for memory transactions through the
+ * IOMMU.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The IOMMU device instance.
+ * @param idDevice The device identifier (bus, device, function).
+ * @param cIovas The number of I/O virtual addresses being accessed.
+ * @param pauIovas The I/O virtual addresses being accessed.
+ * @param fFlags Access flags, see PDMIOMMU_MEM_F_XXX.
+ * @param paGCPhysSpa Where to store the translated system physical page
+ * addresses.
+ *
+ * @thread Any.
+ */
+ DECLR0CALLBACKMEMBER(int, pfnMemBulkAccess,(PPDMDEVINS pDevIns, uint16_t idDevice, size_t cIovas, uint64_t const *pauIovas,
+ uint32_t fFlags, PRTGCPHYS paGCPhysSpa));
+
+ /**
+ * Performs an interrupt remap request through the IOMMU.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The IOMMU device instance.
+ * @param idDevice The device identifier (bus, device, function).
+ * @param pMsiIn The source MSI.
+ * @param pMsiOut Where to store the remapped MSI.
+ *
+ * @thread Any.
+ */
+ DECLR0CALLBACKMEMBER(int, pfnMsiRemap,(PPDMDEVINS pDevIns, uint16_t idDevice, PCMSIMSG pMsiIn, PMSIMSG pMsiOut));
+
+ /** Just a safety precaution. */
+ uint32_t u32TheEnd;
+} PDMIOMMUREGR0;
+/** Pointer to a IOMMU registration structure. */
+typedef PDMIOMMUREGR0 *PPDMIOMMUREGR0;
+
+/** Current PDMIOMMUREG version number. */
+#define PDM_IOMMUREGR0_VERSION PDM_VERSION_MAKE(0xff10, 3, 0)
+
+
+/**
+ * IOMMU registration structure for raw-mode.
+ */
+typedef struct PDMIOMMUREGRC
+{
+ /** Structure version number. PDM_IOMMUREG_VERSION defines the current
+ * version. */
+ uint32_t u32Version;
+ /** Index into the PDM IOMMU array (PDM::aIommus) from ring-3. */
+ uint32_t idxIommu;
+
+ /**
+ * Translates the physical address for a memory transaction through the IOMMU.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The IOMMU device instance.
+ * @param idDevice The device identifier (bus, device, function).
+ * @param uIova The I/O virtual address being accessed.
+ * @param cbIova The size of the access.
+ * @param fFlags Access flags, see PDMIOMMU_MEM_F_XXX.
+ * @param pGCPhysSpa Where to store the translated system physical address.
+ * @param pcbContiguous Where to store the number of contiguous bytes translated
+ * and permission-checked.
+ *
+ * @thread Any.
+ */
+ DECLRCCALLBACKMEMBER(int, pfnMemAccess,(PPDMDEVINS pDevIns, uint16_t idDevice, uint64_t uIova, size_t cbIova,
+ uint32_t fFlags, PRTGCPHYS pGCPhysSpa, size_t *pcbContiguous));
+
+ /**
+ * Translates in bulk physical page addresses for memory transactions through the
+ * IOMMU.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The IOMMU device instance.
+ * @param idDevice The device identifier (bus, device, function).
+ * @param cIovas The number of I/O virtual addresses being accessed.
+ * @param pauIovas The I/O virtual addresses being accessed.
+ * @param fFlags Access flags, see PDMIOMMU_MEM_F_XXX.
+ * @param paGCPhysSpa Where to store the translated system physical page
+ * addresses.
+ *
+ * @thread Any.
+ */
+ DECLRCCALLBACKMEMBER(int, pfnMemBulkAccess,(PPDMDEVINS pDevIns, uint16_t idDevice, size_t cIovas, uint64_t const *pauIovas,
+ uint32_t fFlags, PRTGCPHYS paGCPhysSpa));
+
+ /**
+ * Performs an interrupt remap request through the IOMMU.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The IOMMU device instance.
+ * @param idDevice The device identifier (bus, device, function).
+ * @param pMsiIn The source MSI.
+ * @param pMsiOut Where to store the remapped MSI.
+ *
+ * @thread Any.
+ */
+ DECLRCCALLBACKMEMBER(int, pfnMsiRemap,(PPDMDEVINS pDevIns, uint16_t idDevice, PCMSIMSG pMsiIn, PMSIMSG pMsiOut));
+
+ /** Just a safety precaution. */
+ uint32_t u32TheEnd;
+} PDMIOMMUREGRC;
+/** Pointer to a IOMMU registration structure. */
+typedef PDMIOMMUREGRC *PPDMIOMMUREGRC;
+
+/** Current PDMIOMMUREG version number. */
+#define PDM_IOMMUREGRC_VERSION PDM_VERSION_MAKE(0xff11, 3, 0)
+
+
+/**
+ * IOMMU registration structure for ring-3.
+ */
+typedef struct PDMIOMMUREGR3
+{
+ /** Structure version number. PDM_IOMMUREG_VERSION defines the current
+ * version. */
+ uint32_t u32Version;
+ /** Padding. */
+ uint32_t uPadding0;
+
+ /**
+ * Translates the physical address for a memory transaction through the IOMMU.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The IOMMU device instance.
+ * @param idDevice The device identifier (bus, device, function).
+ * @param uIova The I/O virtual address being accessed.
+ * @param cbIova The size of the access.
+ * @param fFlags Access flags, see PDMIOMMU_MEM_F_XXX.
+ * @param pGCPhysSpa Where to store the translated system physical address.
+ * @param pcbContiguous Where to store the number of contiguous bytes translated
+ * and permission-checked.
+ *
+ * @thread Any.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnMemAccess,(PPDMDEVINS pDevIns, uint16_t idDevice, uint64_t uIova, size_t cbIova,
+ uint32_t fFlags, PRTGCPHYS pGCPhysSpa, size_t *pcbContiguous));
+
+ /**
+ * Translates in bulk physical page addresses for memory transactions through the
+ * IOMMU.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The IOMMU device instance.
+ * @param idDevice The device identifier (bus, device, function).
+ * @param cIovas The number of I/O virtual addresses being accessed.
+ * @param pauIovas The I/O virtual addresses being accessed.
+ * @param fFlags Access flags, see PDMIOMMU_MEM_F_XXX.
+ * @param paGCPhysSpa Where to store the translated system physical page
+ * addresses.
+ *
+ * @thread Any.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnMemBulkAccess,(PPDMDEVINS pDevIns, uint16_t idDevice, size_t cIovas, uint64_t const *pauIovas,
+ uint32_t fFlags, PRTGCPHYS paGCPhysSpa));
+
+ /**
+ * Performs an interrupt remap request through the IOMMU.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The IOMMU device instance.
+ * @param idDevice The device identifier (bus, device, function).
+ * @param pMsiIn The source MSI.
+ * @param pMsiOut Where to store the remapped MSI.
+ *
+ * @thread Any.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnMsiRemap,(PPDMDEVINS pDevIns, uint16_t idDevice, PCMSIMSG pMsiIn, PMSIMSG pMsiOut));
+
+ /** Just a safety precaution. */
+ uint32_t u32TheEnd;
+} PDMIOMMUREGR3;
+/** Pointer to a IOMMU registration structure. */
+typedef PDMIOMMUREGR3 *PPDMIOMMUREGR3;
+
+/** Current PDMIOMMUREG version number. */
+#define PDM_IOMMUREGR3_VERSION PDM_VERSION_MAKE(0xff12, 3, 0)
+
+/** IOMMU registration structure for the current context. */
+typedef CTX_SUFF(PDMIOMMUREG) PDMIOMMUREGCC;
+/** Pointer to an IOMMU registration structure for the current context. */
+typedef CTX_SUFF(PPDMIOMMUREG) PPDMIOMMUREGCC;
+/** IOMMU registration structure version for the current context. */
+#define PDM_IOMMUREGCC_VERSION CTX_MID(PDM_IOMMUREG,_VERSION)
+
+
+/**
+ * IOMMU helpers for ring-0.
+ */
+typedef struct PDMIOMMUHLPR0
+{
+ /** Structure version. PDM_IOMMUHLP_VERSION defines the current version. */
+ uint32_t u32Version;
+
+ /**
+ * Acquires the PDM lock.
+ *
+ * @returns VINF_SUCCESS on success.
+ * @returns rc if we failed to acquire the lock.
+ * @param pDevIns The PCI device instance.
+ * @param rc What to return if we fail to acquire the lock.
+ *
+ * @sa PDMCritSectEnter
+ */
+ DECLR0CALLBACKMEMBER(int, pfnLock,(PPDMDEVINS pDevIns, int rc));
+
+ /**
+ * Releases the PDM lock.
+ *
+ * @param pDevIns The PCI device instance.
+ */
+ DECLR0CALLBACKMEMBER(void, pfnUnlock,(PPDMDEVINS pDevIns));
+
+ /**
+ * Check whether the calling thread owns the PDM lock.
+ *
+ * @returns @c true if the PDM lock is owned, @c false otherwise.
+ * @param pDevIns The PCI device instance.
+ */
+ DECLR0CALLBACKMEMBER(bool, pfnLockIsOwner,(PPDMDEVINS pDevIns));
+
+ /**
+ * Send an MSI (when generated by the IOMMU device itself).
+ *
+ * @param pDevIns PCI device instance.
+ * @param pMsi The MSI to send.
+ * @param uTagSrc The IRQ tag and source (for tracing).
+ */
+ DECLR0CALLBACKMEMBER(void, pfnSendMsi,(PPDMDEVINS pDevIns, PCMSIMSG pMsi, uint32_t uTagSrc));
+
+ /** Just a safety precaution. */
+ uint32_t u32TheEnd;
+} PDMIOMMUHLPR0;
+/** Pointer to IOMMU helpers for ring-0. */
+typedef PDMIOMMUHLPR0 *PPDMIOMMUHLPR0;
+/** Pointer to const IOMMU helpers for ring-0. */
+typedef const PDMIOMMUHLPR0 *PCPDMIOMMUHLPR0;
+
+/** Current PDMIOMMUHLPR0 version number. */
+#define PDM_IOMMUHLPR0_VERSION PDM_VERSION_MAKE(0xff13, 5, 0)
+
+
+/**
+ * IOMMU helpers for raw-mode.
+ */
+typedef struct PDMIOMMUHLPRC
+{
+ /** Structure version. PDM_IOMMUHLP_VERSION defines the current version. */
+ uint32_t u32Version;
+
+ /**
+ * Acquires the PDM lock.
+ *
+ * @returns VINF_SUCCESS on success.
+ * @returns rc if we failed to acquire the lock.
+ * @param pDevIns The PCI device instance.
+ * @param rc What to return if we fail to acquire the lock.
+ *
+ * @sa PDMCritSectEnter
+ */
+ DECLRCCALLBACKMEMBER(int, pfnLock,(PPDMDEVINS pDevIns, int rc));
+
+ /**
+ * Releases the PDM lock.
+ *
+ * @param pDevIns The PCI device instance.
+ */
+ DECLRCCALLBACKMEMBER(void, pfnUnlock,(PPDMDEVINS pDevIns));
+
+ /**
+ * Check whether the threads owns the PDM lock.
+ *
+ * @returns @c true if the PDM lock is owned, @c false otherwise.
+ * @param pDevIns The PCI device instance.
+ */
+ DECLRCCALLBACKMEMBER(bool, pfnLockIsOwner,(PPDMDEVINS pDevIns));
+
+ /**
+ * Send an MSI (when generated by the IOMMU device itself).
+ *
+ * @param pDevIns PCI device instance.
+ * @param pMsi The MSI to send.
+ * @param uTagSrc The IRQ tag and source (for tracing).
+ */
+ DECLRCCALLBACKMEMBER(void, pfnSendMsi,(PPDMDEVINS pDevIns, PCMSIMSG pMsi, uint32_t uTagSrc));
+
+ /** Just a safety precaution. */
+ uint32_t u32TheEnd;
+} PDMIOMMUHLPRC;
+/** Pointer to IOMMU helpers for raw-mode. */
+typedef PDMIOMMUHLPRC *PPDMIOMMUHLPRC;
+/** Pointer to const IOMMU helpers for raw-mode. */
+typedef const PDMIOMMUHLPRC *PCPDMIOMMUHLPRC;
+
+/** Current PDMIOMMUHLPRC version number. */
+#define PDM_IOMMUHLPRC_VERSION PDM_VERSION_MAKE(0xff14, 5, 0)
+
+
+/**
+ * IOMMU helpers for ring-3.
+ */
+typedef struct PDMIOMMUHLPR3
+{
+ /** Structure version. PDM_IOMMUHLP_VERSION defines the current version. */
+ uint32_t u32Version;
+
+ /**
+ * Acquires the PDM lock.
+ *
+ * @returns VINF_SUCCESS on success.
+ * @returns rc if we failed to acquire the lock.
+ * @param pDevIns The PCI device instance.
+ * @param rc What to return if we fail to acquire the lock.
+ *
+ * @sa PDMCritSectEnter
+ */
+ DECLR3CALLBACKMEMBER(int, pfnLock,(PPDMDEVINS pDevIns, int rc));
+
+ /**
+ * Releases the PDM lock.
+ *
+ * @param pDevIns The PCI device instance.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnUnlock,(PPDMDEVINS pDevIns));
+
+ /**
+ * Check whether the threads owns the PDM lock.
+ *
+ * @returns @c true if the PDM lock is owned, @c false otherwise.
+ * @param pDevIns The PCI device instance.
+ */
+ DECLR3CALLBACKMEMBER(bool, pfnLockIsOwner,(PPDMDEVINS pDevIns));
+
+ /**
+ * Send an MSI (when generated by the IOMMU device itself).
+ *
+ * @param pDevIns PCI device instance.
+ * @param pMsi The MSI to send.
+ * @param uTagSrc The IRQ tag and source (for tracing).
+ */
+ DECLR3CALLBACKMEMBER(void, pfnSendMsi,(PPDMDEVINS pDevIns, PCMSIMSG pMsi, uint32_t uTagSrc));
+
+ /** Just a safety precaution. */
+ uint32_t u32TheEnd;
+} PDMIOMMUHLPR3;
+/** Pointer to IOMMU helpers for raw-mode. */
+typedef PDMIOMMUHLPR3 *PPDMIOMMUHLPR3;
+/** Pointer to const IOMMU helpers for raw-mode. */
+typedef const PDMIOMMUHLPR3 *PCPDMIOMMUHLPR3;
+
+/** Current PDMIOMMUHLPR3 version number. */
+#define PDM_IOMMUHLPR3_VERSION PDM_VERSION_MAKE(0xff15, 5, 0)
+
+
+/**
+ * Programmable Interrupt Controller registration structure (all contexts).
+ */
+typedef struct PDMPICREG
+{
+ /** Structure version number. PDM_PICREG_VERSION defines the current version. */
+ uint32_t u32Version;
+
+ /**
+ * Set the an IRQ.
+ *
+ * @param pDevIns Device instance of the PIC.
+ * @param iIrq IRQ number to set.
+ * @param iLevel IRQ level. See the PDM_IRQ_LEVEL_* \#defines.
+ * @param uTagSrc The IRQ tag and source (for tracing).
+ * @remarks Caller enters the PDM critical section.
+ */
+ DECLCALLBACKMEMBER(void, pfnSetIrq,(PPDMDEVINS pDevIns, int iIrq, int iLevel, uint32_t uTagSrc));
+
+ /**
+ * Get a pending interrupt.
+ *
+ * @returns Pending interrupt number.
+ * @param pDevIns Device instance of the PIC.
+ * @param puTagSrc Where to return the IRQ tag and source.
+ * @remarks Caller enters the PDM critical section.
+ */
+ DECLCALLBACKMEMBER(int, pfnGetInterrupt,(PPDMDEVINS pDevIns, uint32_t *puTagSrc));
+
+ /** Just a safety precaution. */
+ uint32_t u32TheEnd;
+} PDMPICREG;
+/** Pointer to a PIC registration structure. */
+typedef PDMPICREG *PPDMPICREG;
+
+/** Current PDMPICREG version number. */
+#define PDM_PICREG_VERSION PDM_VERSION_MAKE(0xfffa, 3, 0)
+
+/**
+ * PIC helpers, same in all contexts.
+ */
+typedef struct PDMPICHLP
+{
+ /** Structure version. PDM_PICHLP_VERSION defines the current version. */
+ uint32_t u32Version;
+
+ /**
+ * Set the interrupt force action flag.
+ *
+ * @param pDevIns Device instance of the PIC.
+ */
+ DECLCALLBACKMEMBER(void, pfnSetInterruptFF,(PPDMDEVINS pDevIns));
+
+ /**
+ * Clear the interrupt force action flag.
+ *
+ * @param pDevIns Device instance of the PIC.
+ */
+ DECLCALLBACKMEMBER(void, pfnClearInterruptFF,(PPDMDEVINS pDevIns));
+
+ /**
+ * Acquires the PDM lock.
+ *
+ * @returns VINF_SUCCESS on success.
+ * @returns rc if we failed to acquire the lock.
+ * @param pDevIns The PIC device instance.
+ * @param rc What to return if we fail to acquire the lock.
+ *
+ * @sa PDMCritSectEnter
+ */
+ DECLCALLBACKMEMBER(int, pfnLock,(PPDMDEVINS pDevIns, int rc));
+
+ /**
+ * Releases the PDM lock.
+ *
+ * @param pDevIns The PIC device instance.
+ */
+ DECLCALLBACKMEMBER(void, pfnUnlock,(PPDMDEVINS pDevIns));
+
+ /** Just a safety precaution. */
+ uint32_t u32TheEnd;
+} PDMPICHLP;
+/** Pointer to PIC helpers. */
+typedef PDMPICHLP *PPDMPICHLP;
+/** Pointer to const PIC helpers. */
+typedef const PDMPICHLP *PCPDMPICHLP;
+
+/** Current PDMPICHLP version number. */
+#define PDM_PICHLP_VERSION PDM_VERSION_MAKE(0xfff9, 3, 0)
+
+
+/**
+ * Firmware registration structure.
+ */
+typedef struct PDMFWREG
+{
+ /** Struct version+magic number (PDM_FWREG_VERSION). */
+ uint32_t u32Version;
+
+ /**
+ * Checks whether this is a hard or soft reset.
+ *
+ * The current definition of soft reset is what the PC BIOS does when CMOS[0xF]
+ * is 5, 9 or 0xA.
+ *
+ * @returns true if hard reset, false if soft.
+ * @param pDevIns Device instance of the firmware.
+ * @param fFlags PDMRESET_F_XXX passed to the PDMDevHlpVMReset API.
+ */
+ DECLR3CALLBACKMEMBER(bool, pfnIsHardReset,(PPDMDEVINS pDevIns, uint32_t fFlags));
+
+ /** Just a safety precaution. */
+ uint32_t u32TheEnd;
+} PDMFWREG;
+/** Pointer to a FW registration structure. */
+typedef PDMFWREG *PPDMFWREG;
+/** Pointer to a const FW registration structure. */
+typedef PDMFWREG const *PCPDMFWREG;
+
+/** Current PDMFWREG version number. */
+#define PDM_FWREG_VERSION PDM_VERSION_MAKE(0xffdd, 1, 0)
+
+/**
+ * Firmware R3 helpers.
+ */
+typedef struct PDMFWHLPR3
+{
+ /** Structure version. PDM_FWHLP_VERSION defines the current version. */
+ uint32_t u32Version;
+
+ /** Just a safety precaution. */
+ uint32_t u32TheEnd;
+} PDMFWHLPR3;
+
+/** Pointer to FW R3 helpers. */
+typedef R3PTRTYPE(PDMFWHLPR3 *) PPDMFWHLPR3;
+/** Pointer to const FW R3 helpers. */
+typedef R3PTRTYPE(const PDMFWHLPR3 *) PCPDMFWHLPR3;
+
+/** Current PDMFWHLPR3 version number. */
+#define PDM_FWHLPR3_VERSION PDM_VERSION_MAKE(0xffdb, 1, 0)
+
+
+/**
+ * APIC mode argument for apicR3SetCpuIdFeatureLevel.
+ *
+ * Also used in saved-states, CFGM don't change existing values.
+ */
+typedef enum PDMAPICMODE
+{
+ /** Invalid 0 entry. */
+ PDMAPICMODE_INVALID = 0,
+ /** No APIC. */
+ PDMAPICMODE_NONE,
+ /** Standard APIC (X86_CPUID_FEATURE_EDX_APIC). */
+ PDMAPICMODE_APIC,
+ /** Intel X2APIC (X86_CPUID_FEATURE_ECX_X2APIC). */
+ PDMAPICMODE_X2APIC,
+ /** The usual 32-bit paranoia. */
+ PDMAPICMODE_32BIT_HACK = 0x7fffffff
+} PDMAPICMODE;
+
+/**
+ * APIC irq argument for pfnSetInterruptFF and pfnClearInterruptFF.
+ */
+typedef enum PDMAPICIRQ
+{
+ /** Invalid 0 entry. */
+ PDMAPICIRQ_INVALID = 0,
+ /** Normal hardware interrupt. */
+ PDMAPICIRQ_HARDWARE,
+ /** NMI. */
+ PDMAPICIRQ_NMI,
+ /** SMI. */
+ PDMAPICIRQ_SMI,
+ /** ExtINT (HW interrupt via PIC). */
+ PDMAPICIRQ_EXTINT,
+ /** Interrupt arrived, needs to be updated to the IRR. */
+ PDMAPICIRQ_UPDATE_PENDING,
+ /** The usual 32-bit paranoia. */
+ PDMAPICIRQ_32BIT_HACK = 0x7fffffff
+} PDMAPICIRQ;
+
+
+/**
+ * I/O APIC registration structure (all contexts).
+ */
+typedef struct PDMIOAPICREG
+{
+ /** Struct version+magic number (PDM_IOAPICREG_VERSION). */
+ uint32_t u32Version;
+
+ /**
+ * Set an IRQ.
+ *
+ * @param pDevIns Device instance of the I/O APIC.
+ * @param uBusDevFn The bus:device:function of the device initiating the
+ * IRQ. Can be NIL_PCIBDF.
+ * @param iIrq IRQ number to set.
+ * @param iLevel IRQ level. See the PDM_IRQ_LEVEL_* \#defines.
+ * @param uTagSrc The IRQ tag and source (for tracing).
+ *
+ * @remarks Caller enters the PDM critical section
+ * Actually, as per 2018-07-21 this isn't true (bird).
+ */
+ DECLCALLBACKMEMBER(void, pfnSetIrq,(PPDMDEVINS pDevIns, PCIBDF uBusDevFn, int iIrq, int iLevel, uint32_t uTagSrc));
+
+ /**
+ * Send a MSI.
+ *
+ * @param pDevIns Device instance of the I/O APIC.
+ * @param uBusDevFn The bus:device:function of the device initiating the
+ * MSI. Cannot be NIL_PCIBDF.
+ * @param pMsi The MSI to send.
+ * @param uTagSrc The IRQ tag and source (for tracing).
+ *
+ * @remarks Caller enters the PDM critical section
+ * Actually, as per 2018-07-21 this isn't true (bird).
+ */
+ DECLCALLBACKMEMBER(void, pfnSendMsi,(PPDMDEVINS pDevIns, PCIBDF uBusDevFn, PCMSIMSG pMsi, uint32_t uTagSrc));
+
+ /**
+ * Set the EOI for an interrupt vector.
+ *
+ * @param pDevIns Device instance of the I/O APIC.
+ * @param u8Vector The vector.
+ *
+ * @remarks Caller enters the PDM critical section
+ * Actually, as per 2018-07-21 this isn't true (bird).
+ */
+ DECLCALLBACKMEMBER(void, pfnSetEoi,(PPDMDEVINS pDevIns, uint8_t u8Vector));
+
+ /** Just a safety precaution. */
+ uint32_t u32TheEnd;
+} PDMIOAPICREG;
+/** Pointer to an APIC registration structure. */
+typedef PDMIOAPICREG *PPDMIOAPICREG;
+
+/** Current PDMAPICREG version number. */
+#define PDM_IOAPICREG_VERSION PDM_VERSION_MAKE(0xfff2, 8, 0)
+
+
+/**
+ * IOAPIC helpers, same in all contexts.
+ */
+typedef struct PDMIOAPICHLP
+{
+ /** Structure version. PDM_IOAPICHLP_VERSION defines the current version. */
+ uint32_t u32Version;
+
+ /**
+ * Private interface between the IOAPIC and APIC.
+ *
+ * @returns status code.
+ * @param pDevIns Device instance of the IOAPIC.
+ * @param u8Dest See APIC implementation.
+ * @param u8DestMode See APIC implementation.
+ * @param u8DeliveryMode See APIC implementation.
+ * @param uVector See APIC implementation.
+ * @param u8Polarity See APIC implementation.
+ * @param u8TriggerMode See APIC implementation.
+ * @param uTagSrc The IRQ tag and source (for tracing).
+ *
+ * @sa APICBusDeliver()
+ */
+ DECLCALLBACKMEMBER(int, pfnApicBusDeliver,(PPDMDEVINS pDevIns, uint8_t u8Dest, uint8_t u8DestMode, uint8_t u8DeliveryMode,
+ uint8_t uVector, uint8_t u8Polarity, uint8_t u8TriggerMode, uint32_t uTagSrc));
+
+ /**
+ * Acquires the PDM lock.
+ *
+ * @returns VINF_SUCCESS on success.
+ * @returns rc if we failed to acquire the lock.
+ * @param pDevIns The IOAPIC device instance.
+ * @param rc What to return if we fail to acquire the lock.
+ *
+ * @sa PDMCritSectEnter
+ */
+ DECLCALLBACKMEMBER(int, pfnLock,(PPDMDEVINS pDevIns, int rc));
+
+ /**
+ * Releases the PDM lock.
+ *
+ * @param pDevIns The IOAPIC device instance.
+ */
+ DECLCALLBACKMEMBER(void, pfnUnlock,(PPDMDEVINS pDevIns));
+
+ /**
+ * Checks if the calling thread owns the PDM lock.
+ *
+ * @param pDevIns The IOAPIC device instance.
+ */
+ DECLCALLBACKMEMBER(bool, pfnLockIsOwner,(PPDMDEVINS pDevIns));
+
+ /**
+ * Private interface between the IOAPIC and IOMMU.
+ *
+ * @returns status code.
+ * @param pDevIns Device instance of the IOAPIC.
+ * @param idDevice The device identifier (bus, device, function).
+ * @param pMsiIn The source MSI.
+ * @param pMsiOut Where to store the remapped MSI (only updated when
+ * VINF_SUCCESS is returned).
+ */
+ DECLCALLBACKMEMBER(int, pfnIommuMsiRemap,(PPDMDEVINS pDevIns, uint16_t idDevice, PCMSIMSG pMsiIn, PMSIMSG pMsiOut));
+
+ /** Just a safety precaution. */
+ uint32_t u32TheEnd;
+} PDMIOAPICHLP;
+/** Pointer to IOAPIC helpers. */
+typedef PDMIOAPICHLP * PPDMIOAPICHLP;
+/** Pointer to const IOAPIC helpers. */
+typedef const PDMIOAPICHLP * PCPDMIOAPICHLP;
+
+/** Current PDMIOAPICHLP version number. */
+#define PDM_IOAPICHLP_VERSION PDM_VERSION_MAKE(0xfff0, 3, 1)
+
+
+/**
+ * HPET registration structure.
+ */
+typedef struct PDMHPETREG
+{
+ /** Struct version+magic number (PDM_HPETREG_VERSION). */
+ uint32_t u32Version;
+} PDMHPETREG;
+/** Pointer to an HPET registration structure. */
+typedef PDMHPETREG *PPDMHPETREG;
+
+/** Current PDMHPETREG version number. */
+#define PDM_HPETREG_VERSION PDM_VERSION_MAKE(0xffe2, 1, 0)
+
+/**
+ * HPET RC helpers.
+ *
+ * @remarks Keep this around in case HPET will need PDM interaction in again RC
+ * at some later point.
+ */
+typedef struct PDMHPETHLPRC
+{
+ /** Structure version. PDM_HPETHLPRC_VERSION defines the current version. */
+ uint32_t u32Version;
+
+ /** Just a safety precaution. */
+ uint32_t u32TheEnd;
+} PDMHPETHLPRC;
+
+/** Pointer to HPET RC helpers. */
+typedef RCPTRTYPE(PDMHPETHLPRC *) PPDMHPETHLPRC;
+/** Pointer to const HPET RC helpers. */
+typedef RCPTRTYPE(const PDMHPETHLPRC *) PCPDMHPETHLPRC;
+
+/** Current PDMHPETHLPRC version number. */
+#define PDM_HPETHLPRC_VERSION PDM_VERSION_MAKE(0xffee, 2, 0)
+
+
+/**
+ * HPET R0 helpers.
+ *
+ * @remarks Keep this around in case HPET will need PDM interaction in again R0
+ * at some later point.
+ */
+typedef struct PDMHPETHLPR0
+{
+ /** Structure version. PDM_HPETHLPR0_VERSION defines the current version. */
+ uint32_t u32Version;
+
+ /** Just a safety precaution. */
+ uint32_t u32TheEnd;
+} PDMHPETHLPR0;
+
+/** Pointer to HPET R0 helpers. */
+typedef R0PTRTYPE(PDMHPETHLPR0 *) PPDMHPETHLPR0;
+/** Pointer to const HPET R0 helpers. */
+typedef R0PTRTYPE(const PDMHPETHLPR0 *) PCPDMHPETHLPR0;
+
+/** Current PDMHPETHLPR0 version number. */
+#define PDM_HPETHLPR0_VERSION PDM_VERSION_MAKE(0xffed, 2, 0)
+
+/**
+ * HPET R3 helpers.
+ */
+typedef struct PDMHPETHLPR3
+{
+ /** Structure version. PDM_HPETHLP_VERSION defines the current version. */
+ uint32_t u32Version;
+
+ /**
+ * Set legacy mode on PIT and RTC.
+ *
+ * @returns VINF_SUCCESS on success.
+ * @returns rc if we failed to set legacy mode.
+ * @param pDevIns Device instance of the HPET.
+ * @param fActivated Whether legacy mode is activated or deactivated.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSetLegacyMode,(PPDMDEVINS pDevIns, bool fActivated));
+
+
+ /**
+ * Set IRQ, bypassing ISA bus override rules.
+ *
+ * @returns VINF_SUCCESS on success.
+ * @returns rc if we failed to set legacy mode.
+ * @param pDevIns Device instance of the HPET.
+ * @param iIrq IRQ number to set.
+ * @param iLevel IRQ level. See the PDM_IRQ_LEVEL_* \#defines.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSetIrq,(PPDMDEVINS pDevIns, int iIrq, int iLevel));
+
+ /** Just a safety precaution. */
+ uint32_t u32TheEnd;
+} PDMHPETHLPR3;
+
+/** Pointer to HPET R3 helpers. */
+typedef R3PTRTYPE(PDMHPETHLPR3 *) PPDMHPETHLPR3;
+/** Pointer to const HPET R3 helpers. */
+typedef R3PTRTYPE(const PDMHPETHLPR3 *) PCPDMHPETHLPR3;
+
+/** Current PDMHPETHLPR3 version number. */
+#define PDM_HPETHLPR3_VERSION PDM_VERSION_MAKE(0xffec, 3, 0)
+
+
+/**
+ * Raw PCI device registration structure.
+ */
+typedef struct PDMPCIRAWREG
+{
+ /** Struct version+magic number (PDM_PCIRAWREG_VERSION). */
+ uint32_t u32Version;
+ /** Just a safety precaution. */
+ uint32_t u32TheEnd;
+} PDMPCIRAWREG;
+/** Pointer to a raw PCI registration structure. */
+typedef PDMPCIRAWREG *PPDMPCIRAWREG;
+
+/** Current PDMPCIRAWREG version number. */
+#define PDM_PCIRAWREG_VERSION PDM_VERSION_MAKE(0xffe1, 1, 0)
+
+/**
+ * Raw PCI device raw-mode context helpers.
+ */
+typedef struct PDMPCIRAWHLPRC
+{
+ /** Structure version and magic number (PDM_PCIRAWHLPRC_VERSION). */
+ uint32_t u32Version;
+ /** Just a safety precaution. */
+ uint32_t u32TheEnd;
+} PDMPCIRAWHLPRC;
+/** Pointer to a raw PCI deviec raw-mode context helper structure. */
+typedef RCPTRTYPE(PDMPCIRAWHLPRC *) PPDMPCIRAWHLPRC;
+/** Pointer to a const raw PCI deviec raw-mode context helper structure. */
+typedef RCPTRTYPE(const PDMPCIRAWHLPRC *) PCPDMPCIRAWHLPRC;
+
+/** Current PDMPCIRAWHLPRC version number. */
+#define PDM_PCIRAWHLPRC_VERSION PDM_VERSION_MAKE(0xffe0, 1, 0)
+
+/**
+ * Raw PCI device ring-0 context helpers.
+ */
+typedef struct PDMPCIRAWHLPR0
+{
+ /** Structure version and magic number (PDM_PCIRAWHLPR0_VERSION). */
+ uint32_t u32Version;
+ /** Just a safety precaution. */
+ uint32_t u32TheEnd;
+} PDMPCIRAWHLPR0;
+/** Pointer to a raw PCI deviec ring-0 context helper structure. */
+typedef R0PTRTYPE(PDMPCIRAWHLPR0 *) PPDMPCIRAWHLPR0;
+/** Pointer to a const raw PCI deviec ring-0 context helper structure. */
+typedef R0PTRTYPE(const PDMPCIRAWHLPR0 *) PCPDMPCIRAWHLPR0;
+
+/** Current PDMPCIRAWHLPR0 version number. */
+#define PDM_PCIRAWHLPR0_VERSION PDM_VERSION_MAKE(0xffdf, 1, 0)
+
+
+/**
+ * Raw PCI device ring-3 context helpers.
+ */
+typedef struct PDMPCIRAWHLPR3
+{
+ /** Undefined structure version and magic number. */
+ uint32_t u32Version;
+
+ /**
+ * Gets the address of the RC raw PCI device helpers.
+ *
+ * This should be called at both construction and relocation time to obtain
+ * the correct address of the RC helpers.
+ *
+ * @returns RC pointer to the raw PCI device helpers.
+ * @param pDevIns Device instance of the raw PCI device.
+ */
+ DECLR3CALLBACKMEMBER(PCPDMPCIRAWHLPRC, pfnGetRCHelpers,(PPDMDEVINS pDevIns));
+
+ /**
+ * Gets the address of the R0 raw PCI device helpers.
+ *
+ * This should be called at both construction and relocation time to obtain
+ * the correct address of the R0 helpers.
+ *
+ * @returns R0 pointer to the raw PCI device helpers.
+ * @param pDevIns Device instance of the raw PCI device.
+ */
+ DECLR3CALLBACKMEMBER(PCPDMPCIRAWHLPR0, pfnGetR0Helpers,(PPDMDEVINS pDevIns));
+
+ /** Just a safety precaution. */
+ uint32_t u32TheEnd;
+} PDMPCIRAWHLPR3;
+/** Pointer to raw PCI R3 helpers. */
+typedef R3PTRTYPE(PDMPCIRAWHLPR3 *) PPDMPCIRAWHLPR3;
+/** Pointer to const raw PCI R3 helpers. */
+typedef R3PTRTYPE(const PDMPCIRAWHLPR3 *) PCPDMPCIRAWHLPR3;
+
+/** Current PDMPCIRAWHLPR3 version number. */
+#define PDM_PCIRAWHLPR3_VERSION PDM_VERSION_MAKE(0xffde, 1, 0)
+
+
+#ifdef IN_RING3
+
+/**
+ * DMA Transfer Handler.
+ *
+ * @returns Number of bytes transferred.
+ * @param pDevIns The device instance that registered the handler.
+ * @param pvUser User pointer.
+ * @param uChannel Channel number.
+ * @param off DMA position.
+ * @param cb Block size.
+ * @remarks The device lock is take before the callback (in fact, the locks of
+ * DMA devices and the DMA controller itself are taken).
+ */
+typedef DECLCALLBACKTYPE(uint32_t, FNDMATRANSFERHANDLER,(PPDMDEVINS pDevIns, void *pvUser, unsigned uChannel,
+ uint32_t off, uint32_t cb));
+/** Pointer to a FNDMATRANSFERHANDLER(). */
+typedef FNDMATRANSFERHANDLER *PFNDMATRANSFERHANDLER;
+
+/**
+ * DMA Controller registration structure.
+ */
+typedef struct PDMDMAREG
+{
+ /** Structure version number. PDM_DMACREG_VERSION defines the current version. */
+ uint32_t u32Version;
+
+ /**
+ * Execute pending transfers.
+ *
+ * @returns A more work indiciator. I.e. 'true' if there is more to be done, and 'false' if all is done.
+ * @param pDevIns Device instance of the DMAC.
+ * @remarks No locks held, called on EMT(0) as a form of serialization.
+ */
+ DECLR3CALLBACKMEMBER(bool, pfnRun,(PPDMDEVINS pDevIns));
+
+ /**
+ * Register transfer function for DMA channel.
+ *
+ * @param pDevIns Device instance of the DMAC.
+ * @param uChannel Channel number.
+ * @param pDevInsHandler The device instance of the device making the
+ * regstration (will be passed to the callback).
+ * @param pfnTransferHandler Device specific transfer function.
+ * @param pvUser User pointer to be passed to the callback.
+ * @remarks No locks held, called on an EMT.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnRegister,(PPDMDEVINS pDevIns, unsigned uChannel, PPDMDEVINS pDevInsHandler,
+ PFNDMATRANSFERHANDLER pfnTransferHandler, void *pvUser));
+
+ /**
+ * Read memory
+ *
+ * @returns Number of bytes read.
+ * @param pDevIns Device instance of the DMAC.
+ * @param uChannel Channel number.
+ * @param pvBuffer Pointer to target buffer.
+ * @param off DMA position.
+ * @param cbBlock Block size.
+ * @remarks No locks held, called on an EMT.
+ */
+ DECLR3CALLBACKMEMBER(uint32_t, pfnReadMemory,(PPDMDEVINS pDevIns, unsigned uChannel, void *pvBuffer, uint32_t off, uint32_t cbBlock));
+
+ /**
+ * Write memory
+ *
+ * @returns Number of bytes written.
+ * @param pDevIns Device instance of the DMAC.
+ * @param uChannel Channel number.
+ * @param pvBuffer Memory to write.
+ * @param off DMA position.
+ * @param cbBlock Block size.
+ * @remarks No locks held, called on an EMT.
+ */
+ DECLR3CALLBACKMEMBER(uint32_t, pfnWriteMemory,(PPDMDEVINS pDevIns, unsigned uChannel, const void *pvBuffer, uint32_t off, uint32_t cbBlock));
+
+ /**
+ * Set the DREQ line.
+ *
+ * @param pDevIns Device instance of the DMAC.
+ * @param uChannel Channel number.
+ * @param uLevel Level of the line.
+ * @remarks No locks held, called on an EMT.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnSetDREQ,(PPDMDEVINS pDevIns, unsigned uChannel, unsigned uLevel));
+
+ /**
+ * Get channel mode
+ *
+ * @returns Channel mode.
+ * @param pDevIns Device instance of the DMAC.
+ * @param uChannel Channel number.
+ * @remarks No locks held, called on an EMT.
+ */
+ DECLR3CALLBACKMEMBER(uint8_t, pfnGetChannelMode,(PPDMDEVINS pDevIns, unsigned uChannel));
+
+} PDMDMACREG;
+/** Pointer to a DMAC registration structure. */
+typedef PDMDMACREG *PPDMDMACREG;
+
+/** Current PDMDMACREG version number. */
+#define PDM_DMACREG_VERSION PDM_VERSION_MAKE(0xffeb, 2, 0)
+
+
+/**
+ * DMA Controller device helpers.
+ */
+typedef struct PDMDMACHLP
+{
+ /** Structure version. PDM_DMACHLP_VERSION defines the current version. */
+ uint32_t u32Version;
+
+ /* to-be-defined */
+
+} PDMDMACHLP;
+/** Pointer to DMAC helpers. */
+typedef PDMDMACHLP *PPDMDMACHLP;
+/** Pointer to const DMAC helpers. */
+typedef const PDMDMACHLP *PCPDMDMACHLP;
+
+/** Current PDMDMACHLP version number. */
+#define PDM_DMACHLP_VERSION PDM_VERSION_MAKE(0xffea, 1, 0)
+
+#endif /* IN_RING3 */
+
+
+
+/**
+ * RTC registration structure.
+ */
+typedef struct PDMRTCREG
+{
+ /** Structure version number. PDM_RTCREG_VERSION defines the current version. */
+ uint32_t u32Version;
+ uint32_t u32Alignment; /**< structure size alignment. */
+
+ /**
+ * Write to a CMOS register and update the checksum if necessary.
+ *
+ * @returns VBox status code.
+ * @param pDevIns Device instance of the RTC.
+ * @param iReg The CMOS register index.
+ * @param u8Value The CMOS register value.
+ * @remarks Caller enters the device critical section.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnWrite,(PPDMDEVINS pDevIns, unsigned iReg, uint8_t u8Value));
+
+ /**
+ * Read a CMOS register.
+ *
+ * @returns VBox status code.
+ * @param pDevIns Device instance of the RTC.
+ * @param iReg The CMOS register index.
+ * @param pu8Value Where to store the CMOS register value.
+ * @remarks Caller enters the device critical section.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnRead,(PPDMDEVINS pDevIns, unsigned iReg, uint8_t *pu8Value));
+
+} PDMRTCREG;
+/** Pointer to a RTC registration structure. */
+typedef PDMRTCREG *PPDMRTCREG;
+/** Pointer to a const RTC registration structure. */
+typedef const PDMRTCREG *PCPDMRTCREG;
+
+/** Current PDMRTCREG version number. */
+#define PDM_RTCREG_VERSION PDM_VERSION_MAKE(0xffe9, 2, 0)
+
+
+/**
+ * RTC device helpers.
+ */
+typedef struct PDMRTCHLP
+{
+ /** Structure version. PDM_RTCHLP_VERSION defines the current version. */
+ uint32_t u32Version;
+
+ /* to-be-defined */
+
+} PDMRTCHLP;
+/** Pointer to RTC helpers. */
+typedef PDMRTCHLP *PPDMRTCHLP;
+/** Pointer to const RTC helpers. */
+typedef const PDMRTCHLP *PCPDMRTCHLP;
+
+/** Current PDMRTCHLP version number. */
+#define PDM_RTCHLP_VERSION PDM_VERSION_MAKE(0xffe8, 1, 0)
+
+
+
+/** @name Flags for PCI I/O region registration
+ * @{ */
+/** No handle is passed. */
+#define PDMPCIDEV_IORGN_F_NO_HANDLE UINT32_C(0x00000000)
+/** An I/O port handle is passed. */
+#define PDMPCIDEV_IORGN_F_IOPORT_HANDLE UINT32_C(0x00000001)
+/** An MMIO range handle is passed. */
+#define PDMPCIDEV_IORGN_F_MMIO_HANDLE UINT32_C(0x00000002)
+/** An MMIO2 handle is passed. */
+#define PDMPCIDEV_IORGN_F_MMIO2_HANDLE UINT32_C(0x00000003)
+/** Handle type mask. */
+#define PDMPCIDEV_IORGN_F_HANDLE_MASK UINT32_C(0x00000003)
+/** New-style (mostly wrt callbacks). */
+#define PDMPCIDEV_IORGN_F_NEW_STYLE UINT32_C(0x00000004)
+/** Mask of valid flags. */
+#define PDMPCIDEV_IORGN_F_VALID_MASK UINT32_C(0x00000007)
+/** @} */
+
+
+/** @name Flags for the guest physical read/write helpers
+ * @{ */
+/** Default flag with no indication whether the data is processed by the device or just passed through. */
+#define PDM_DEVHLP_PHYS_RW_F_DEFAULT UINT32_C(0x00000000)
+/** The data is user data which is just passed through between the guest and the source or destination and not processed
+ * by the device in any way. */
+#define PDM_DEVHLP_PHYS_RW_F_DATA_USER RT_BIT_32(0)
+/** The data is metadata and being processed by the device in some way. */
+#define PDM_DEVHLP_PHYS_RW_F_DATA_META RT_BIT_32(1)
+/** @} */
+
+
+#ifdef IN_RING3
+
+/** @name Special values for PDMDEVHLPR3::pfnPCIRegister parameters.
+ * @{ */
+/** Same device number (and bus) as the previous PCI device registered with the PDM device.
+ * This is handy when registering multiple PCI device functions and the device
+ * number is left up to the PCI bus. In order to facilitate one PDM device
+ * instance for each PCI function, this searches earlier PDM device
+ * instances as well. */
+# define PDMPCIDEVREG_DEV_NO_SAME_AS_PREV UINT8_C(0xfd)
+/** Use the first unused device number (all functions must be unused). */
+# define PDMPCIDEVREG_DEV_NO_FIRST_UNUSED UINT8_C(0xfe)
+/** Use the first unused device function. */
+# define PDMPCIDEVREG_FUN_NO_FIRST_UNUSED UINT8_C(0xff)
+
+/** The device and function numbers are not mandatory, just suggestions. */
+# define PDMPCIDEVREG_F_NOT_MANDATORY_NO RT_BIT_32(0)
+/** Registering a PCI bridge device. */
+# define PDMPCIDEVREG_F_PCI_BRIDGE RT_BIT_32(1)
+/** Valid flag mask. */
+# define PDMPCIDEVREG_F_VALID_MASK UINT32_C(0x00000003)
+/** @} */
+
+/** Current PDMDEVHLPR3 version number. */
+#define PDM_DEVHLPR3_VERSION PDM_VERSION_MAKE_PP(0xffe7, 65, 0)
+
+/**
+ * PDM Device API.
+ */
+typedef struct PDMDEVHLPR3
+{
+ /** Structure version. PDM_DEVHLPR3_VERSION defines the current version. */
+ uint32_t u32Version;
+
+ /** @name I/O ports
+ * @{ */
+ /**
+ * Creates a range of I/O ports for a device.
+ *
+ * The I/O port range must be mapped in a separately call. Any ring-0 and
+ * raw-mode context callback handlers needs to be set up in the respective
+ * contexts.
+ *
+ * @returns VBox status.
+ * @param pDevIns The device instance to register the ports with.
+ * @param cPorts Number of ports to register.
+ * @param fFlags IOM_IOPORT_F_XXX.
+ * @param pPciDev The PCI device the range is associated with, if
+ * applicable.
+ * @param iPciRegion The PCI device region in the high 16-bit word and
+ * sub-region in the low 16-bit word. UINT32_MAX if NA.
+ * @param pfnOut Pointer to function which is gonna handle OUT
+ * operations. Optional.
+ * @param pfnIn Pointer to function which is gonna handle IN operations.
+ * Optional.
+ * @param pfnOutStr Pointer to function which is gonna handle string OUT
+ * operations. Optional.
+ * @param pfnInStr Pointer to function which is gonna handle string IN
+ * operations. Optional.
+ * @param pvUser User argument to pass to the callbacks.
+ * @param pszDesc Pointer to description string. This must not be freed.
+ * @param paExtDescs Extended per-port descriptions, optional. Partial range
+ * coverage is allowed. This must not be freed.
+ * @param phIoPorts Where to return the I/O port range handle.
+ *
+ * @remarks Caller enters the device critical section prior to invoking the
+ * registered callback methods.
+ *
+ * @sa PDMDevHlpIoPortSetUpContext, PDMDevHlpIoPortMap,
+ * PDMDevHlpIoPortUnmap.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnIoPortCreateEx,(PPDMDEVINS pDevIns, RTIOPORT cPorts, uint32_t fFlags, PPDMPCIDEV pPciDev,
+ uint32_t iPciRegion, PFNIOMIOPORTNEWOUT pfnOut, PFNIOMIOPORTNEWIN pfnIn,
+ PFNIOMIOPORTNEWOUTSTRING pfnOutStr, PFNIOMIOPORTNEWINSTRING pfnInStr, RTR3PTR pvUser,
+ const char *pszDesc, PCIOMIOPORTDESC paExtDescs, PIOMIOPORTHANDLE phIoPorts));
+
+ /**
+ * Maps an I/O port range.
+ *
+ * @returns VBox status.
+ * @param pDevIns The device instance to register the ports with.
+ * @param hIoPorts The I/O port range handle.
+ * @param Port Where to map the range.
+ * @sa PDMDevHlpIoPortUnmap, PDMDevHlpIoPortSetUpContext,
+ * PDMDevHlpIoPortCreate, PDMDevHlpIoPortCreateEx.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnIoPortMap,(PPDMDEVINS pDevIns, IOMIOPORTHANDLE hIoPorts, RTIOPORT Port));
+
+ /**
+ * Unmaps an I/O port range.
+ *
+ * @returns VBox status.
+ * @param pDevIns The device instance to register the ports with.
+ * @param hIoPorts The I/O port range handle.
+ * @sa PDMDevHlpIoPortMap, PDMDevHlpIoPortSetUpContext,
+ * PDMDevHlpIoPortCreate, PDMDevHlpIoPortCreateEx.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnIoPortUnmap,(PPDMDEVINS pDevIns, IOMIOPORTHANDLE hIoPorts));
+
+ /**
+ * Gets the mapping address of the I/O port range @a hIoPorts.
+ *
+ * @returns Mapping address (0..65535) or UINT32_MAX if not mapped (or invalid
+ * parameters).
+ * @param pDevIns The device instance to register the ports with.
+ * @param hIoPorts The I/O port range handle.
+ */
+ DECLR3CALLBACKMEMBER(uint32_t, pfnIoPortGetMappingAddress,(PPDMDEVINS pDevIns, IOMIOPORTHANDLE hIoPorts));
+
+ /**
+ * Writes to an I/O port register.
+ *
+ * @returns Strict VBox status code. Informational status codes other than the one documented
+ * here are to be treated as internal failure. Use IOM_SUCCESS() to check for success.
+ * @retval VINF_SUCCESS Success.
+ * @retval VINF_EM_FIRST-VINF_EM_LAST Success with some exceptions (see IOM_SUCCESS()), the
+ * status code must be passed on to EM.
+ *
+ * @param pDevIns The device instance to register the ports with.
+ * @param Port The port to write to.
+ * @param u32Value The value to write.
+ * @param cbValue The size of the register to read in bytes. 1, 2 or 4 bytes.
+ *
+ * @thread EMT
+ * @todo r=aeichner This is only used by DevPCI.cpp to write the ELCR of the PIC. This shouldn't be done that way
+ * and removed again as soon as possible (no time right now)...
+ */
+ DECLR3CALLBACKMEMBER(VBOXSTRICTRC, pfnIoPortWrite,(PPDMDEVINS pDevIns, RTIOPORT Port, uint32_t u32Value, size_t cbValue));
+ /** @} */
+
+ /** @name MMIO
+ * @{ */
+ /**
+ * Creates a memory mapped I/O (MMIO) region for a device.
+ *
+ * The MMIO region must be mapped in a separately call. Any ring-0 and
+ * raw-mode context callback handlers needs to be set up in the respective
+ * contexts.
+ *
+ * @returns VBox status.
+ * @param pDevIns The device instance to register the ports with.
+ * @param cbRegion The size of the region in bytes.
+ * @param fFlags Flags, IOMMMIO_FLAGS_XXX.
+ * @param pPciDev The PCI device the range is associated with, if
+ * applicable.
+ * @param iPciRegion The PCI device region in the high 16-bit word and
+ * sub-region in the low 16-bit word. UINT32_MAX if NA.
+ * @param pfnWrite Pointer to function which is gonna handle Write
+ * operations.
+ * @param pfnRead Pointer to function which is gonna handle Read
+ * operations.
+ * @param pfnFill Pointer to function which is gonna handle Fill/memset
+ * operations. (optional)
+ * @param pvUser User argument to pass to the callbacks.
+ * @param pszDesc Pointer to description string. This must not be freed.
+ * @param phRegion Where to return the MMIO region handle.
+ *
+ * @remarks Caller enters the device critical section prior to invoking the
+ * registered callback methods.
+ *
+ * @sa PDMDevHlpMmioSetUpContext, PDMDevHlpMmioMap, PDMDevHlpMmioUnmap.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnMmioCreateEx,(PPDMDEVINS pDevIns, RTGCPHYS cbRegion,
+ uint32_t fFlags, PPDMPCIDEV pPciDev, uint32_t iPciRegion,
+ PFNIOMMMIONEWWRITE pfnWrite, PFNIOMMMIONEWREAD pfnRead, PFNIOMMMIONEWFILL pfnFill,
+ void *pvUser, const char *pszDesc, PIOMMMIOHANDLE phRegion));
+
+ /**
+ * Maps a memory mapped I/O (MMIO) region (into the guest physical address space).
+ *
+ * @returns VBox status.
+ * @param pDevIns The device instance the region is associated with.
+ * @param hRegion The MMIO region handle.
+ * @param GCPhys Where to map the region.
+ * @note An MMIO range may overlap with base memory if a lot of RAM is
+ * configured for the VM, in which case we'll drop the base memory
+ * pages. Presently we will make no attempt to preserve anything that
+ * happens to be present in the base memory that is replaced, this is
+ * technically incorrect but it's just not worth the effort to do
+ * right, at least not at this point.
+ * @sa PDMDevHlpMmioUnmap, PDMDevHlpMmioCreate, PDMDevHlpMmioCreateEx,
+ * PDMDevHlpMmioSetUpContext
+ */
+ DECLR3CALLBACKMEMBER(int, pfnMmioMap,(PPDMDEVINS pDevIns, IOMMMIOHANDLE hRegion, RTGCPHYS GCPhys));
+
+ /**
+ * Unmaps a memory mapped I/O (MMIO) region.
+ *
+ * @returns VBox status.
+ * @param pDevIns The device instance the region is associated with.
+ * @param hRegion The MMIO region handle.
+ * @sa PDMDevHlpMmioMap, PDMDevHlpMmioCreate, PDMDevHlpMmioCreateEx,
+ * PDMDevHlpMmioSetUpContext
+ */
+ DECLR3CALLBACKMEMBER(int, pfnMmioUnmap,(PPDMDEVINS pDevIns, IOMMMIOHANDLE hRegion));
+
+ /**
+ * Reduces the length of a MMIO range.
+ *
+ * This is for implementations of PDMPCIDEV::pfnRegionLoadChangeHookR3 and will
+ * only work during saved state restore. It will not call the PCI bus code, as
+ * that is expected to restore the saved resource configuration.
+ *
+ * It just adjusts the mapping length of the region so that when pfnMmioMap is
+ * called it will only map @a cbRegion bytes and not the value set during
+ * registration.
+ *
+ * @return VBox status code.
+ * @param pDevIns The device owning the range.
+ * @param hRegion The MMIO region handle.
+ * @param cbRegion The new size, must be smaller.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnMmioReduce,(PPDMDEVINS pDevIns, IOMMMIOHANDLE hRegion, RTGCPHYS cbRegion));
+
+ /**
+ * Gets the mapping address of the MMIO region @a hRegion.
+ *
+ * @returns Mapping address, NIL_RTGCPHYS if not mapped (or invalid parameters).
+ * @param pDevIns The device instance to register the ports with.
+ * @param hRegion The MMIO region handle.
+ */
+ DECLR3CALLBACKMEMBER(RTGCPHYS, pfnMmioGetMappingAddress,(PPDMDEVINS pDevIns, IOMMMIOHANDLE hRegion));
+ /** @} */
+
+ /** @name MMIO2
+ * @{ */
+ /**
+ * Creates a MMIO2 region.
+ *
+ * As mentioned elsewhere, MMIO2 is just RAM spelled differently. It's RAM
+ * associated with a device. It is also non-shared memory with a permanent
+ * ring-3 mapping and page backing (presently).
+ *
+ * @returns VBox status.
+ * @param pDevIns The device instance.
+ * @param pPciDev The PCI device the region is associated with, or
+ * NULL if no PCI device association.
+ * @param iPciRegion The region number. Use the PCI region number as
+ * this must be known to the PCI bus device too. If
+ * it's not associated with the PCI device, then
+ * any number up to UINT8_MAX is fine.
+ * @param cbRegion The size (in bytes) of the region.
+ * @param fFlags PGMPHYS_MMIO2_FLAGS_XXX (see pgm.h).
+ * @param pszDesc Pointer to description string. This must not be
+ * freed.
+ * @param ppvMapping Where to store the address of the ring-3 mapping
+ * of the memory.
+ * @param phRegion Where to return the MMIO2 region handle.
+ *
+ * @thread EMT(0)
+ */
+ DECLR3CALLBACKMEMBER(int, pfnMmio2Create,(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t iPciRegion, RTGCPHYS cbRegion,
+ uint32_t fFlags, const char *pszDesc, void **ppvMapping, PPGMMMIO2HANDLE phRegion));
+
+ /**
+ * Destroys a MMIO2 region, unmapping it and freeing the memory.
+ *
+ * Any physical access handlers registered for the region must be deregistered
+ * before calling this function.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param hRegion The MMIO2 region handle.
+ * @thread EMT.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnMmio2Destroy,(PPDMDEVINS pDevIns, PGMMMIO2HANDLE hRegion));
+
+ /**
+ * Maps a MMIO2 region (into the guest physical address space).
+ *
+ * @returns VBox status.
+ * @param pDevIns The device instance the region is associated with.
+ * @param hRegion The MMIO2 region handle.
+ * @param GCPhys Where to map the region.
+ * @note A MMIO2 region overlap with base memory if a lot of RAM is
+ * configured for the VM, in which case we'll drop the base memory
+ * pages. Presently we will make no attempt to preserve anything that
+ * happens to be present in the base memory that is replaced, this is
+ * technically incorrect but it's just not worth the effort to do
+ * right, at least not at this point.
+ * @sa PDMDevHlpMmio2Unmap, PDMDevHlpMmio2Create, PDMDevHlpMmio2SetUpContext
+ */
+ DECLR3CALLBACKMEMBER(int, pfnMmio2Map,(PPDMDEVINS pDevIns, PGMMMIO2HANDLE hRegion, RTGCPHYS GCPhys));
+
+ /**
+ * Unmaps a MMIO2 region.
+ *
+ * @returns VBox status.
+ * @param pDevIns The device instance the region is associated with.
+ * @param hRegion The MMIO2 region handle.
+ * @sa PDMDevHlpMmio2Map, PDMDevHlpMmio2Create, PDMDevHlpMmio2SetUpContext
+ */
+ DECLR3CALLBACKMEMBER(int, pfnMmio2Unmap,(PPDMDEVINS pDevIns, PGMMMIO2HANDLE hRegion));
+
+ /**
+ * Reduces the length of a MMIO range.
+ *
+ * This is for implementations of PDMPCIDEV::pfnRegionLoadChangeHookR3 and will
+ * only work during saved state restore. It will not call the PCI bus code, as
+ * that is expected to restore the saved resource configuration.
+ *
+ * It just adjusts the mapping length of the region so that when pfnMmioMap is
+ * called it will only map @a cbRegion bytes and not the value set during
+ * registration.
+ *
+ * @return VBox status code.
+ * @param pDevIns The device owning the range.
+ * @param hRegion The MMIO2 region handle.
+ * @param cbRegion The new size, must be smaller.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnMmio2Reduce,(PPDMDEVINS pDevIns, PGMMMIO2HANDLE hRegion, RTGCPHYS cbRegion));
+
+ /**
+ * Gets the mapping address of the MMIO region @a hRegion.
+ *
+ * @returns Mapping address, NIL_RTGCPHYS if not mapped (or invalid parameters).
+ * @param pDevIns The device instance to register the ports with.
+ * @param hRegion The MMIO2 region handle.
+ */
+ DECLR3CALLBACKMEMBER(RTGCPHYS, pfnMmio2GetMappingAddress,(PPDMDEVINS pDevIns, PGMMMIO2HANDLE hRegion));
+
+ /**
+ * Queries and resets the dirty bitmap for an MMIO2 region.
+ *
+ * The MMIO2 region must have been created with the
+ * PGMPHYS_MMIO2_FLAGS_TRACK_DIRTY_PAGES flag for this to work.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param hRegion The MMIO2 region handle.
+ * @param pvBitmap Where to return the bitmap. Must be 8-byte aligned.
+ * Can be NULL if only resetting the tracking is desired.
+ * @param cbBitmap The bitmap size. One bit per page in the region,
+ * rounded up to 8-bytes. If pvBitmap is NULL this must
+ * also be zero.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnMmio2QueryAndResetDirtyBitmap, (PPDMDEVINS pDevIns, PGMMMIO2HANDLE hRegion,
+ void *pvBitmap, size_t cbBitmap));
+
+ /**
+ * Controls the dirty page tracking for an MMIO2 region.
+ *
+ * The MMIO2 region must have been created with the
+ * PGMPHYS_MMIO2_FLAGS_TRACK_DIRTY_PAGES flag for this to work.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param hRegion The MMIO2 region handle.
+ * @param fEnabled When set to @c true the dirty page tracking will be
+ * enabled if currently disabled (bitmap is reset). When
+ * set to @c false the dirty page tracking will be
+ * disabled.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnMmio2ControlDirtyPageTracking, (PPDMDEVINS pDevIns, PGMMMIO2HANDLE hRegion, bool fEnabled));
+
+ /**
+ * Changes the number of an MMIO2 or pre-registered MMIO region.
+ *
+ * This should only be used to deal with saved state problems, so there is no
+ * convenience inline wrapper for this method.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param hRegion The MMIO2 region handle.
+ * @param iNewRegion The new region index.
+ *
+ * @sa @bugref{9359}
+ */
+ DECLR3CALLBACKMEMBER(int, pfnMmio2ChangeRegionNo,(PPDMDEVINS pDevIns, PGMMMIO2HANDLE hRegion, uint32_t iNewRegion));
+
+ /**
+ * Mapping an MMIO2 page in place of an MMIO page for direct access.
+ *
+ * This is a special optimization used by the VGA device. Call
+ * PDMDevHlpMmioResetRegion() to undo the mapping.
+ *
+ * @returns VBox status code. This API may return VINF_SUCCESS even if no
+ * remapping is made.
+ * @retval VERR_SEM_BUSY in ring-0 if we cannot get the IOM lock.
+ *
+ * @param pDevIns The device instance @a hRegion and @a hMmio2 are
+ * associated with.
+ * @param hRegion The handle to the MMIO region.
+ * @param offRegion The offset into @a hRegion of the page to be
+ * remapped.
+ * @param hMmio2 The MMIO2 handle.
+ * @param offMmio2 Offset into @a hMmio2 of the page to be use for the
+ * mapping.
+ * @param fPageFlags Page flags to set. Must be (X86_PTE_RW | X86_PTE_P)
+ * for the time being.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnMmioMapMmio2Page,(PPDMDEVINS pDevIns, IOMMMIOHANDLE hRegion, RTGCPHYS offRegion,
+ uint64_t hMmio2, RTGCPHYS offMmio2, uint64_t fPageFlags));
+
+ /**
+ * Reset a previously modified MMIO region; restore the access flags.
+ *
+ * This undoes the effects of PDMDevHlpMmioMapMmio2Page() and is currently only
+ * intended for some ancient VGA hack. However, it would be great to extend it
+ * beyond VT-x and/or nested-paging.
+ *
+ * @returns VBox status code.
+ *
+ * @param pDevIns The device instance @a hRegion is associated with.
+ * @param hRegion The handle to the MMIO region.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnMmioResetRegion, (PPDMDEVINS pDevIns, IOMMMIOHANDLE hRegion));
+ /** @} */
+
+ /**
+ * Register a ROM (BIOS) region.
+ *
+ * It goes without saying that this is read-only memory. The memory region must be
+ * in unassigned memory. I.e. from the top of the address space or on the PC in
+ * the 0xa0000-0xfffff range.
+ *
+ * @returns VBox status.
+ * @param pDevIns The device instance owning the ROM region.
+ * @param GCPhysStart First physical address in the range.
+ * Must be page aligned!
+ * @param cbRange The size of the range (in bytes).
+ * Must be page aligned!
+ * @param pvBinary Pointer to the binary data backing the ROM image.
+ * @param cbBinary The size of the binary pointer. This must
+ * be equal or smaller than @a cbRange.
+ * @param fFlags PGMPHYS_ROM_FLAGS_XXX (see pgm.h).
+ * @param pszDesc Pointer to description string. This must not be freed.
+ *
+ * @remark There is no way to remove the rom, automatically on device cleanup or
+ * manually from the device yet. At present I doubt we need such features...
+ */
+ DECLR3CALLBACKMEMBER(int, pfnROMRegister,(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, uint32_t cbRange,
+ const void *pvBinary, uint32_t cbBinary, uint32_t fFlags, const char *pszDesc));
+
+ /**
+ * Changes the protection of shadowed ROM mapping.
+ *
+ * This is intented for use by the system BIOS, chipset or device in question to
+ * change the protection of shadowed ROM code after init and on reset.
+ *
+ * @param pDevIns The device instance.
+ * @param GCPhysStart Where the mapping starts.
+ * @param cbRange The size of the mapping.
+ * @param enmProt The new protection type.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnROMProtectShadow,(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, uint32_t cbRange, PGMROMPROT enmProt));
+
+ /**
+ * Register a save state data unit.
+ *
+ * @returns VBox status.
+ * @param pDevIns The device instance.
+ * @param uVersion Data layout version number.
+ * @param cbGuess The approximate amount of data in the unit.
+ * Only for progress indicators.
+ * @param pszBefore Name of data unit which we should be put in
+ * front of. Optional (NULL).
+ *
+ * @param pfnLivePrep Prepare live save callback, optional.
+ * @param pfnLiveExec Execute live save callback, optional.
+ * @param pfnLiveVote Vote live save callback, optional.
+ *
+ * @param pfnSavePrep Prepare save callback, optional.
+ * @param pfnSaveExec Execute save callback, optional.
+ * @param pfnSaveDone Done save callback, optional.
+ *
+ * @param pfnLoadPrep Prepare load callback, optional.
+ * @param pfnLoadExec Execute load callback, optional.
+ * @param pfnLoadDone Done load callback, optional.
+ * @remarks Caller enters the device critical section prior to invoking the
+ * registered callback methods.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSSMRegister,(PPDMDEVINS pDevIns, uint32_t uVersion, size_t cbGuess, const char *pszBefore,
+ PFNSSMDEVLIVEPREP pfnLivePrep, PFNSSMDEVLIVEEXEC pfnLiveExec, PFNSSMDEVLIVEVOTE pfnLiveVote,
+ PFNSSMDEVSAVEPREP pfnSavePrep, PFNSSMDEVSAVEEXEC pfnSaveExec, PFNSSMDEVSAVEDONE pfnSaveDone,
+ PFNSSMDEVLOADPREP pfnLoadPrep, PFNSSMDEVLOADEXEC pfnLoadExec, PFNSSMDEVLOADDONE pfnLoadDone));
+
+ /**
+ * Register a save state data unit for backward compatibility.
+ *
+ * This is for migrating from an old device name to a new one or for merging
+ * devices. It will only help loading old saved states.
+ *
+ * @returns VBox status.
+ * @param pDevIns The device instance.
+ * @param pszOldName The old unit name.
+ * @param pfnLoadPrep Prepare load callback, optional.
+ * @param pfnLoadExec Execute load callback, optional.
+ * @param pfnLoadDone Done load callback, optional.
+ * @remarks Caller enters the device critical section prior to invoking the
+ * registered callback methods.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSSMRegisterLegacy,(PPDMDEVINS pDevIns, const char *pszOldName, PFNSSMDEVLOADPREP pfnLoadPrep,
+ PFNSSMDEVLOADEXEC pfnLoadExec, PFNSSMDEVLOADDONE pfnLoadDone));
+
+ /** @name Exported SSM Functions
+ * @{ */
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutStruct,(PSSMHANDLE pSSM, const void *pvStruct, PCSSMFIELD paFields));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutStructEx,(PSSMHANDLE pSSM, const void *pvStruct, size_t cbStruct, uint32_t fFlags, PCSSMFIELD paFields, void *pvUser));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutBool,(PSSMHANDLE pSSM, bool fBool));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutU8,(PSSMHANDLE pSSM, uint8_t u8));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutS8,(PSSMHANDLE pSSM, int8_t i8));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutU16,(PSSMHANDLE pSSM, uint16_t u16));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutS16,(PSSMHANDLE pSSM, int16_t i16));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutU32,(PSSMHANDLE pSSM, uint32_t u32));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutS32,(PSSMHANDLE pSSM, int32_t i32));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutU64,(PSSMHANDLE pSSM, uint64_t u64));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutS64,(PSSMHANDLE pSSM, int64_t i64));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutU128,(PSSMHANDLE pSSM, uint128_t u128));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutS128,(PSSMHANDLE pSSM, int128_t i128));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutUInt,(PSSMHANDLE pSSM, RTUINT u));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutSInt,(PSSMHANDLE pSSM, RTINT i));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutGCUInt,(PSSMHANDLE pSSM, RTGCUINT u));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutGCUIntReg,(PSSMHANDLE pSSM, RTGCUINTREG u));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutGCPhys32,(PSSMHANDLE pSSM, RTGCPHYS32 GCPhys));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutGCPhys64,(PSSMHANDLE pSSM, RTGCPHYS64 GCPhys));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutGCPhys,(PSSMHANDLE pSSM, RTGCPHYS GCPhys));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutGCPtr,(PSSMHANDLE pSSM, RTGCPTR GCPtr));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutGCUIntPtr,(PSSMHANDLE pSSM, RTGCUINTPTR GCPtr));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutRCPtr,(PSSMHANDLE pSSM, RTRCPTR RCPtr));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutIOPort,(PSSMHANDLE pSSM, RTIOPORT IOPort));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutSel,(PSSMHANDLE pSSM, RTSEL Sel));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutMem,(PSSMHANDLE pSSM, const void *pv, size_t cb));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutStrZ,(PSSMHANDLE pSSM, const char *psz));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetStruct,(PSSMHANDLE pSSM, void *pvStruct, PCSSMFIELD paFields));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetStructEx,(PSSMHANDLE pSSM, void *pvStruct, size_t cbStruct, uint32_t fFlags, PCSSMFIELD paFields, void *pvUser));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetBool,(PSSMHANDLE pSSM, bool *pfBool));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetBoolV,(PSSMHANDLE pSSM, bool volatile *pfBool));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetU8,(PSSMHANDLE pSSM, uint8_t *pu8));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetU8V,(PSSMHANDLE pSSM, uint8_t volatile *pu8));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetS8,(PSSMHANDLE pSSM, int8_t *pi8));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetS8V,(PSSMHANDLE pSSM, int8_t volatile *pi8));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetU16,(PSSMHANDLE pSSM, uint16_t *pu16));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetU16V,(PSSMHANDLE pSSM, uint16_t volatile *pu16));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetS16,(PSSMHANDLE pSSM, int16_t *pi16));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetS16V,(PSSMHANDLE pSSM, int16_t volatile *pi16));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetU32,(PSSMHANDLE pSSM, uint32_t *pu32));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetU32V,(PSSMHANDLE pSSM, uint32_t volatile *pu32));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetS32,(PSSMHANDLE pSSM, int32_t *pi32));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetS32V,(PSSMHANDLE pSSM, int32_t volatile *pi32));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetU64,(PSSMHANDLE pSSM, uint64_t *pu64));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetU64V,(PSSMHANDLE pSSM, uint64_t volatile *pu64));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetS64,(PSSMHANDLE pSSM, int64_t *pi64));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetS64V,(PSSMHANDLE pSSM, int64_t volatile *pi64));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetU128,(PSSMHANDLE pSSM, uint128_t *pu128));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetU128V,(PSSMHANDLE pSSM, uint128_t volatile *pu128));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetS128,(PSSMHANDLE pSSM, int128_t *pi128));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetS128V,(PSSMHANDLE pSSM, int128_t volatile *pi128));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetGCPhys32,(PSSMHANDLE pSSM, PRTGCPHYS32 pGCPhys));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetGCPhys32V,(PSSMHANDLE pSSM, RTGCPHYS32 volatile *pGCPhys));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetGCPhys64,(PSSMHANDLE pSSM, PRTGCPHYS64 pGCPhys));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetGCPhys64V,(PSSMHANDLE pSSM, RTGCPHYS64 volatile *pGCPhys));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetGCPhys,(PSSMHANDLE pSSM, PRTGCPHYS pGCPhys));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetGCPhysV,(PSSMHANDLE pSSM, RTGCPHYS volatile *pGCPhys));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetUInt,(PSSMHANDLE pSSM, PRTUINT pu));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetSInt,(PSSMHANDLE pSSM, PRTINT pi));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetGCUInt,(PSSMHANDLE pSSM, PRTGCUINT pu));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetGCUIntReg,(PSSMHANDLE pSSM, PRTGCUINTREG pu));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetGCPtr,(PSSMHANDLE pSSM, PRTGCPTR pGCPtr));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetGCUIntPtr,(PSSMHANDLE pSSM, PRTGCUINTPTR pGCPtr));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetRCPtr,(PSSMHANDLE pSSM, PRTRCPTR pRCPtr));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetIOPort,(PSSMHANDLE pSSM, PRTIOPORT pIOPort));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetSel,(PSSMHANDLE pSSM, PRTSEL pSel));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetMem,(PSSMHANDLE pSSM, void *pv, size_t cb));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetStrZ,(PSSMHANDLE pSSM, char *psz, size_t cbMax));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetStrZEx,(PSSMHANDLE pSSM, char *psz, size_t cbMax, size_t *pcbStr));
+ DECLR3CALLBACKMEMBER(int, pfnSSMSkip,(PSSMHANDLE pSSM, size_t cb));
+ DECLR3CALLBACKMEMBER(int, pfnSSMSkipToEndOfUnit,(PSSMHANDLE pSSM));
+ DECLR3CALLBACKMEMBER(int, pfnSSMSetLoadError,(PSSMHANDLE pSSM, int rc, RT_SRC_POS_DECL, const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(6, 7));
+ DECLR3CALLBACKMEMBER(int, pfnSSMSetLoadErrorV,(PSSMHANDLE pSSM, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(6, 0));
+ DECLR3CALLBACKMEMBER(int, pfnSSMSetCfgError,(PSSMHANDLE pSSM, RT_SRC_POS_DECL, const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(5, 6));
+ DECLR3CALLBACKMEMBER(int, pfnSSMSetCfgErrorV,(PSSMHANDLE pSSM, RT_SRC_POS_DECL, const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(5, 0));
+ DECLR3CALLBACKMEMBER(int, pfnSSMHandleGetStatus,(PSSMHANDLE pSSM));
+ DECLR3CALLBACKMEMBER(SSMAFTER, pfnSSMHandleGetAfter,(PSSMHANDLE pSSM));
+ DECLR3CALLBACKMEMBER(bool, pfnSSMHandleIsLiveSave,(PSSMHANDLE pSSM));
+ DECLR3CALLBACKMEMBER(uint32_t, pfnSSMHandleMaxDowntime,(PSSMHANDLE pSSM));
+ DECLR3CALLBACKMEMBER(uint32_t, pfnSSMHandleHostBits,(PSSMHANDLE pSSM));
+ DECLR3CALLBACKMEMBER(uint32_t, pfnSSMHandleRevision,(PSSMHANDLE pSSM));
+ DECLR3CALLBACKMEMBER(uint32_t, pfnSSMHandleVersion,(PSSMHANDLE pSSM));
+ DECLR3CALLBACKMEMBER(const char *, pfnSSMHandleHostOSAndArch,(PSSMHANDLE pSSM));
+ /** @} */
+
+ /**
+ * Creates a timer w/ a cross context handle.
+ *
+ * @returns VBox status.
+ * @param pDevIns The device instance.
+ * @param enmClock The clock to use on this timer.
+ * @param pfnCallback Callback function.
+ * @param pvUser User argument for the callback.
+ * @param fFlags Flags, see TMTIMER_FLAGS_*.
+ * @param pszDesc Pointer to description string which must stay around
+ * until the timer is fully destroyed (i.e. a bit after TMTimerDestroy()).
+ * @param phTimer Where to store the timer handle on success.
+ * @remarks Caller enters the device critical section prior to invoking the
+ * callback.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnTimerCreate,(PPDMDEVINS pDevIns, TMCLOCK enmClock, PFNTMTIMERDEV pfnCallback,
+ void *pvUser, uint32_t fFlags, const char *pszDesc, PTMTIMERHANDLE phTimer));
+
+ /** @name Timer handle method wrappers
+ * @{ */
+ DECLR3CALLBACKMEMBER(uint64_t, pfnTimerFromMicro,(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint64_t cMicroSecs));
+ DECLR3CALLBACKMEMBER(uint64_t, pfnTimerFromMilli,(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint64_t cMilliSecs));
+ DECLR3CALLBACKMEMBER(uint64_t, pfnTimerFromNano,(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint64_t cNanoSecs));
+ DECLR3CALLBACKMEMBER(uint64_t, pfnTimerGet,(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer));
+ DECLR3CALLBACKMEMBER(uint64_t, pfnTimerGetFreq,(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer));
+ DECLR3CALLBACKMEMBER(uint64_t, pfnTimerGetNano,(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer));
+ DECLR3CALLBACKMEMBER(bool, pfnTimerIsActive,(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer));
+ DECLR3CALLBACKMEMBER(bool, pfnTimerIsLockOwner,(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer));
+ DECLR3CALLBACKMEMBER(VBOXSTRICTRC, pfnTimerLockClock,(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, int rcBusy));
+ /** Takes the clock lock then enters the specified critical section. */
+ DECLR3CALLBACKMEMBER(VBOXSTRICTRC, pfnTimerLockClock2,(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, PPDMCRITSECT pCritSect, int rcBusy));
+ DECLR3CALLBACKMEMBER(int, pfnTimerSet,(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint64_t uExpire));
+ DECLR3CALLBACKMEMBER(int, pfnTimerSetFrequencyHint,(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint32_t uHz));
+ DECLR3CALLBACKMEMBER(int, pfnTimerSetMicro,(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint64_t cMicrosToNext));
+ DECLR3CALLBACKMEMBER(int, pfnTimerSetMillies,(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint64_t cMilliesToNext));
+ DECLR3CALLBACKMEMBER(int, pfnTimerSetNano,(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint64_t cNanosToNext));
+ DECLR3CALLBACKMEMBER(int, pfnTimerSetRelative,(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint64_t cTicksToNext, uint64_t *pu64Now));
+ DECLR3CALLBACKMEMBER(int, pfnTimerStop,(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer));
+ DECLR3CALLBACKMEMBER(void, pfnTimerUnlockClock,(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer));
+ DECLR3CALLBACKMEMBER(void, pfnTimerUnlockClock2,(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, PPDMCRITSECT pCritSect));
+ DECLR3CALLBACKMEMBER(int, pfnTimerSetCritSect,(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, PPDMCRITSECT pCritSect));
+ DECLR3CALLBACKMEMBER(int, pfnTimerSave,(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, PSSMHANDLE pSSM));
+ DECLR3CALLBACKMEMBER(int, pfnTimerLoad,(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, PSSMHANDLE pSSM));
+ DECLR3CALLBACKMEMBER(int, pfnTimerDestroy,(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer));
+ /** @sa TMR3TimerSkip */
+ DECLR3CALLBACKMEMBER(int, pfnTimerSkipLoad,(PSSMHANDLE pSSM, bool *pfActive));
+ /** @} */
+
+ /**
+ * Get the real world UTC time adjusted for VM lag, user offset and warpdrive.
+ *
+ * @returns pTime.
+ * @param pDevIns The device instance.
+ * @param pTime Where to store the time.
+ */
+ DECLR3CALLBACKMEMBER(PRTTIMESPEC, pfnTMUtcNow,(PPDMDEVINS pDevIns, PRTTIMESPEC pTime));
+
+ /** @name Exported CFGM Functions.
+ * @{ */
+ DECLR3CALLBACKMEMBER(bool, pfnCFGMExists,( PCFGMNODE pNode, const char *pszName));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryType,( PCFGMNODE pNode, const char *pszName, PCFGMVALUETYPE penmType));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQuerySize,( PCFGMNODE pNode, const char *pszName, size_t *pcb));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryInteger,( PCFGMNODE pNode, const char *pszName, uint64_t *pu64));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryIntegerDef,( PCFGMNODE pNode, const char *pszName, uint64_t *pu64, uint64_t u64Def));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryString,( PCFGMNODE pNode, const char *pszName, char *pszString, size_t cchString));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryStringDef,( PCFGMNODE pNode, const char *pszName, char *pszString, size_t cchString, const char *pszDef));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryPassword,( PCFGMNODE pNode, const char *pszName, char *pszString, size_t cchString));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryPasswordDef,( PCFGMNODE pNode, const char *pszName, char *pszString, size_t cchString, const char *pszDef));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryBytes,( PCFGMNODE pNode, const char *pszName, void *pvData, size_t cbData));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryU64,( PCFGMNODE pNode, const char *pszName, uint64_t *pu64));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryU64Def,( PCFGMNODE pNode, const char *pszName, uint64_t *pu64, uint64_t u64Def));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryS64,( PCFGMNODE pNode, const char *pszName, int64_t *pi64));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryS64Def,( PCFGMNODE pNode, const char *pszName, int64_t *pi64, int64_t i64Def));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryU32,( PCFGMNODE pNode, const char *pszName, uint32_t *pu32));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryU32Def,( PCFGMNODE pNode, const char *pszName, uint32_t *pu32, uint32_t u32Def));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryS32,( PCFGMNODE pNode, const char *pszName, int32_t *pi32));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryS32Def,( PCFGMNODE pNode, const char *pszName, int32_t *pi32, int32_t i32Def));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryU16,( PCFGMNODE pNode, const char *pszName, uint16_t *pu16));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryU16Def,( PCFGMNODE pNode, const char *pszName, uint16_t *pu16, uint16_t u16Def));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryS16,( PCFGMNODE pNode, const char *pszName, int16_t *pi16));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryS16Def,( PCFGMNODE pNode, const char *pszName, int16_t *pi16, int16_t i16Def));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryU8,( PCFGMNODE pNode, const char *pszName, uint8_t *pu8));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryU8Def,( PCFGMNODE pNode, const char *pszName, uint8_t *pu8, uint8_t u8Def));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryS8,( PCFGMNODE pNode, const char *pszName, int8_t *pi8));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryS8Def,( PCFGMNODE pNode, const char *pszName, int8_t *pi8, int8_t i8Def));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryBool,( PCFGMNODE pNode, const char *pszName, bool *pf));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryBoolDef,( PCFGMNODE pNode, const char *pszName, bool *pf, bool fDef));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryPort,( PCFGMNODE pNode, const char *pszName, PRTIOPORT pPort));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryPortDef,( PCFGMNODE pNode, const char *pszName, PRTIOPORT pPort, RTIOPORT PortDef));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryUInt,( PCFGMNODE pNode, const char *pszName, unsigned int *pu));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryUIntDef,( PCFGMNODE pNode, const char *pszName, unsigned int *pu, unsigned int uDef));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQuerySInt,( PCFGMNODE pNode, const char *pszName, signed int *pi));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQuerySIntDef,( PCFGMNODE pNode, const char *pszName, signed int *pi, signed int iDef));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryGCPtr,( PCFGMNODE pNode, const char *pszName, PRTGCPTR pGCPtr));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryGCPtrDef,( PCFGMNODE pNode, const char *pszName, PRTGCPTR pGCPtr, RTGCPTR GCPtrDef));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryGCPtrU,( PCFGMNODE pNode, const char *pszName, PRTGCUINTPTR pGCPtr));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryGCPtrUDef,( PCFGMNODE pNode, const char *pszName, PRTGCUINTPTR pGCPtr, RTGCUINTPTR GCPtrDef));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryGCPtrS,( PCFGMNODE pNode, const char *pszName, PRTGCINTPTR pGCPtr));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryGCPtrSDef,( PCFGMNODE pNode, const char *pszName, PRTGCINTPTR pGCPtr, RTGCINTPTR GCPtrDef));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryStringAlloc,( PCFGMNODE pNode, const char *pszName, char **ppszString));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryStringAllocDef,(PCFGMNODE pNode, const char *pszName, char **ppszString, const char *pszDef));
+ DECLR3CALLBACKMEMBER(PCFGMNODE, pfnCFGMGetParent,(PCFGMNODE pNode));
+ DECLR3CALLBACKMEMBER(PCFGMNODE, pfnCFGMGetChild,(PCFGMNODE pNode, const char *pszPath));
+ DECLR3CALLBACKMEMBER(PCFGMNODE, pfnCFGMGetChildF,(PCFGMNODE pNode, const char *pszPathFormat, ...) RT_IPRT_FORMAT_ATTR(2, 3));
+ DECLR3CALLBACKMEMBER(PCFGMNODE, pfnCFGMGetChildFV,(PCFGMNODE pNode, const char *pszPathFormat, va_list Args) RT_IPRT_FORMAT_ATTR(3, 0));
+ DECLR3CALLBACKMEMBER(PCFGMNODE, pfnCFGMGetFirstChild,(PCFGMNODE pNode));
+ DECLR3CALLBACKMEMBER(PCFGMNODE, pfnCFGMGetNextChild,(PCFGMNODE pCur));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMGetName,(PCFGMNODE pCur, char *pszName, size_t cchName));
+ DECLR3CALLBACKMEMBER(size_t, pfnCFGMGetNameLen,(PCFGMNODE pCur));
+ DECLR3CALLBACKMEMBER(bool, pfnCFGMAreChildrenValid,(PCFGMNODE pNode, const char *pszzValid));
+ DECLR3CALLBACKMEMBER(PCFGMLEAF, pfnCFGMGetFirstValue,(PCFGMNODE pCur));
+ DECLR3CALLBACKMEMBER(PCFGMLEAF, pfnCFGMGetNextValue,(PCFGMLEAF pCur));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMGetValueName,(PCFGMLEAF pCur, char *pszName, size_t cchName));
+ DECLR3CALLBACKMEMBER(size_t, pfnCFGMGetValueNameLen,(PCFGMLEAF pCur));
+ DECLR3CALLBACKMEMBER(CFGMVALUETYPE, pfnCFGMGetValueType,(PCFGMLEAF pCur));
+ DECLR3CALLBACKMEMBER(bool, pfnCFGMAreValuesValid,(PCFGMNODE pNode, const char *pszzValid));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMValidateConfig,(PCFGMNODE pNode, const char *pszNode,
+ const char *pszValidValues, const char *pszValidNodes,
+ const char *pszWho, uint32_t uInstance));
+ /** @} */
+
+ /**
+ * Read physical memory.
+ *
+ * @returns VINF_SUCCESS (for now).
+ * @param pDevIns The device instance.
+ * @param GCPhys Physical address start reading from.
+ * @param pvBuf Where to put the read bits.
+ * @param cbRead How many bytes to read.
+ * @param fFlags Combination of PDM_DEVHLP_PHYS_RW_F_XXX.
+ * @thread Any thread, but the call may involve the emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPhysRead,(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead, uint32_t fFlags));
+
+ /**
+ * Write to physical memory.
+ *
+ * @returns VINF_SUCCESS for now, and later maybe VERR_EM_MEMORY.
+ * @param pDevIns The device instance.
+ * @param GCPhys Physical address to write to.
+ * @param pvBuf What to write.
+ * @param cbWrite How many bytes to write.
+ * @param fFlags Combination of PDM_DEVHLP_PHYS_RW_F_XXX.
+ * @thread Any thread, but the call may involve the emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPhysWrite,(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite, uint32_t fFlags));
+
+ /**
+ * Requests the mapping of a guest page into ring-3.
+ *
+ * When you're done with the page, call pfnPhysReleasePageMappingLock() ASAP to
+ * release it.
+ *
+ * This API will assume your intention is to write to the page, and will
+ * therefore replace shared and zero pages. If you do not intend to modify the
+ * page, use the pfnPhysGCPhys2CCPtrReadOnly() API.
+ *
+ * @returns VBox status code.
+ * @retval VINF_SUCCESS on success.
+ * @retval VERR_PGM_PHYS_PAGE_RESERVED it it's a valid page but has no physical
+ * backing or if the page has any active access handlers. The caller
+ * must fall back on using PGMR3PhysWriteExternal.
+ * @retval VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS if it's not a valid physical address.
+ *
+ * @param pDevIns The device instance.
+ * @param GCPhys The guest physical address of the page that
+ * should be mapped.
+ * @param fFlags Flags reserved for future use, MBZ.
+ * @param ppv Where to store the address corresponding to
+ * GCPhys.
+ * @param pLock Where to store the lock information that
+ * pfnPhysReleasePageMappingLock needs.
+ *
+ * @remark Avoid calling this API from within critical sections (other than the
+ * PGM one) because of the deadlock risk when we have to delegating the
+ * task to an EMT.
+ * @thread Any.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPhysGCPhys2CCPtr,(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, uint32_t fFlags, void **ppv,
+ PPGMPAGEMAPLOCK pLock));
+
+ /**
+ * Requests the mapping of a guest page into ring-3, external threads.
+ *
+ * When you're done with the page, call pfnPhysReleasePageMappingLock() ASAP to
+ * release it.
+ *
+ * @returns VBox status code.
+ * @retval VINF_SUCCESS on success.
+ * @retval VERR_PGM_PHYS_PAGE_RESERVED it it's a valid page but has no physical
+ * backing or if the page as an active ALL access handler. The caller
+ * must fall back on using PGMPhysRead.
+ * @retval VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS if it's not a valid physical address.
+ *
+ * @param pDevIns The device instance.
+ * @param GCPhys The guest physical address of the page that
+ * should be mapped.
+ * @param fFlags Flags reserved for future use, MBZ.
+ * @param ppv Where to store the address corresponding to
+ * GCPhys.
+ * @param pLock Where to store the lock information that
+ * pfnPhysReleasePageMappingLock needs.
+ *
+ * @remark Avoid calling this API from within critical sections.
+ * @thread Any.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPhysGCPhys2CCPtrReadOnly,(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, uint32_t fFlags,
+ void const **ppv, PPGMPAGEMAPLOCK pLock));
+
+ /**
+ * Release the mapping of a guest page.
+ *
+ * This is the counter part of pfnPhysGCPhys2CCPtr and
+ * pfnPhysGCPhys2CCPtrReadOnly.
+ *
+ * @param pDevIns The device instance.
+ * @param pLock The lock structure initialized by the mapping
+ * function.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnPhysReleasePageMappingLock,(PPDMDEVINS pDevIns, PPGMPAGEMAPLOCK pLock));
+
+ /**
+ * Read guest physical memory by virtual address.
+ *
+ * @param pDevIns The device instance.
+ * @param pvDst Where to put the read bits.
+ * @param GCVirtSrc Guest virtual address to start reading from.
+ * @param cb How many bytes to read.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPhysReadGCVirt,(PPDMDEVINS pDevIns, void *pvDst, RTGCPTR GCVirtSrc, size_t cb));
+
+ /**
+ * Write to guest physical memory by virtual address.
+ *
+ * @param pDevIns The device instance.
+ * @param GCVirtDst Guest virtual address to write to.
+ * @param pvSrc What to write.
+ * @param cb How many bytes to write.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPhysWriteGCVirt,(PPDMDEVINS pDevIns, RTGCPTR GCVirtDst, const void *pvSrc, size_t cb));
+
+ /**
+ * Convert a guest virtual address to a guest physical address.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param GCPtr Guest virtual address.
+ * @param pGCPhys Where to store the GC physical address
+ * corresponding to GCPtr.
+ * @thread The emulation thread.
+ * @remark Careful with page boundaries.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPhysGCPtr2GCPhys, (PPDMDEVINS pDevIns, RTGCPTR GCPtr, PRTGCPHYS pGCPhys));
+
+ /**
+ * Checks if a GC physical address is a normal page,
+ * i.e. not ROM, MMIO or reserved.
+ *
+ * @returns true if normal.
+ * @returns false if invalid, ROM, MMIO or reserved page.
+ * @param pDevIns The device instance.
+ * @param GCPhys The physical address to check.
+ */
+ DECLR3CALLBACKMEMBER(bool, pfnPhysIsGCPhysNormal,(PPDMDEVINS pDevIns, RTGCPHYS GCPhys));
+
+ /**
+ * Inflate or deflate a memory balloon
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param fInflate Inflate or deflate memory balloon
+ * @param cPages Number of pages to free
+ * @param paPhysPage Array of guest physical addresses
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPhysChangeMemBalloon,(PPDMDEVINS pDevIns, bool fInflate, unsigned cPages, RTGCPHYS *paPhysPage));
+
+ /**
+ * Allocate memory which is associated with current VM instance
+ * and automatically freed on it's destruction.
+ *
+ * @returns Pointer to allocated memory. The memory is *NOT* zero-ed.
+ * @param pDevIns The device instance.
+ * @param cb Number of bytes to allocate.
+ */
+ DECLR3CALLBACKMEMBER(void *, pfnMMHeapAlloc,(PPDMDEVINS pDevIns, size_t cb));
+
+ /**
+ * Allocate memory which is associated with current VM instance
+ * and automatically freed on it's destruction. The memory is ZEROed.
+ *
+ * @returns Pointer to allocated memory. The memory is *NOT* zero-ed.
+ * @param pDevIns The device instance.
+ * @param cb Number of bytes to allocate.
+ */
+ DECLR3CALLBACKMEMBER(void *, pfnMMHeapAllocZ,(PPDMDEVINS pDevIns, size_t cb));
+
+ /**
+ * Allocating string printf.
+ *
+ * @returns Pointer to the string.
+ * @param pDevIns The device instance.
+ * @param enmTag The statistics tag.
+ * @param pszFormat The format string.
+ * @param va Format arguments.
+ */
+ DECLR3CALLBACKMEMBER(char *, pfnMMHeapAPrintfV,(PPDMDEVINS pDevIns, MMTAG enmTag, const char *pszFormat, va_list va));
+
+ /**
+ * Free memory allocated with pfnMMHeapAlloc() and pfnMMHeapAllocZ().
+ *
+ * @param pDevIns The device instance.
+ * @param pv Pointer to the memory to free.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnMMHeapFree,(PPDMDEVINS pDevIns, void *pv));
+
+ /**
+ * Returns the physical RAM size of the VM.
+ *
+ * @returns RAM size in bytes.
+ * @param pDevIns The device instance.
+ */
+ DECLR3CALLBACKMEMBER(uint64_t, pfnMMPhysGetRamSize,(PPDMDEVINS pDevIns));
+
+ /**
+ * Returns the physical RAM size of the VM below the 4GB boundary.
+ *
+ * @returns RAM size in bytes.
+ * @param pDevIns The device instance.
+ */
+ DECLR3CALLBACKMEMBER(uint32_t, pfnMMPhysGetRamSizeBelow4GB,(PPDMDEVINS pDevIns));
+
+ /**
+ * Returns the physical RAM size of the VM above the 4GB boundary.
+ *
+ * @returns RAM size in bytes.
+ * @param pDevIns The device instance.
+ */
+ DECLR3CALLBACKMEMBER(uint64_t, pfnMMPhysGetRamSizeAbove4GB,(PPDMDEVINS pDevIns));
+
+ /**
+ * Gets the VM state.
+ *
+ * @returns VM state.
+ * @param pDevIns The device instance.
+ * @thread Any thread (just keep in mind that it's volatile info).
+ */
+ DECLR3CALLBACKMEMBER(VMSTATE, pfnVMState, (PPDMDEVINS pDevIns));
+
+ /**
+ * Checks if the VM was teleported and hasn't been fully resumed yet.
+ *
+ * @returns true / false.
+ * @param pDevIns The device instance.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(bool, pfnVMTeleportedAndNotFullyResumedYet,(PPDMDEVINS pDevIns));
+
+ /**
+ * Set the VM error message
+ *
+ * @returns rc.
+ * @param pDevIns The device instance.
+ * @param rc VBox status code.
+ * @param SRC_POS Use RT_SRC_POS.
+ * @param pszFormat Error message format string.
+ * @param va Error message arguments.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnVMSetErrorV,(PPDMDEVINS pDevIns, int rc, RT_SRC_POS_DECL,
+ const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(6, 0));
+
+ /**
+ * Set the VM runtime error message
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param fFlags The action flags. See VMSETRTERR_FLAGS_*.
+ * @param pszErrorId Error ID string.
+ * @param pszFormat Error message format string.
+ * @param va Error message arguments.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnVMSetRuntimeErrorV,(PPDMDEVINS pDevIns, uint32_t fFlags, const char *pszErrorId,
+ const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(4, 0));
+
+ /**
+ * Special interface for implementing a HLT-like port on a device.
+ *
+ * This can be called directly from device code, provide the device is trusted
+ * to access the VMM directly. Since we may not have an accurate register set
+ * and the caller certainly shouldn't (device code does not access CPU
+ * registers), this function will return when interrupts are pending regardless
+ * of the actual EFLAGS.IF state.
+ *
+ * @returns VBox error status (never informational statuses).
+ * @param pDevIns The device instance.
+ * @param idCpu The id of the calling EMT.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnVMWaitForDeviceReady,(PPDMDEVINS pDevIns, VMCPUID idCpu));
+
+ /**
+ * Wakes up a CPU that has called PDMDEVHLPR3::pfnVMWaitForDeviceReady.
+ *
+ * @returns VBox error status (never informational statuses).
+ * @param pDevIns The device instance.
+ * @param idCpu The id of the calling EMT.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnVMNotifyCpuDeviceReady,(PPDMDEVINS pDevIns, VMCPUID idCpu));
+
+ /**
+ * Convenience wrapper for VMR3ReqCallU.
+ *
+ * This assumes (1) you're calling a function that returns an VBox status code
+ * and that you do not wish to wait for it to complete.
+ *
+ * @returns VBox status code returned by VMR3ReqCallVU.
+ *
+ * @param pDevIns The device instance.
+ * @param idDstCpu The destination CPU(s). Either a specific CPU ID or
+ * one of the following special values:
+ * VMCPUID_ANY, VMCPUID_ANY_QUEUE, VMCPUID_ALL or VMCPUID_ALL_REVERSE.
+ * @param pfnFunction Pointer to the function to call.
+ * @param cArgs Number of arguments following in the ellipsis.
+ * @param Args Argument vector.
+ *
+ * @remarks See remarks on VMR3ReqCallVU.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnVMReqCallNoWaitV,(PPDMDEVINS pDevIns, VMCPUID idDstCpu, PFNRT pfnFunction, unsigned cArgs, va_list Args));
+
+ /**
+ * Convenience wrapper for VMR3ReqCallU.
+ *
+ * This assumes (1) you're calling a function that returns void, (2) that you
+ * wish to wait for ever for it to return, and (3) that it's priority request
+ * that can be safely be handled during async suspend and power off.
+ *
+ * @returns VBox status code of VMR3ReqCallVU.
+ *
+ * @param pDevIns The device instance.
+ * @param idDstCpu The destination CPU(s). Either a specific CPU ID or
+ * one of the following special values:
+ * VMCPUID_ANY, VMCPUID_ANY_QUEUE, VMCPUID_ALL or VMCPUID_ALL_REVERSE.
+ * @param pfnFunction Pointer to the function to call.
+ * @param cArgs Number of arguments following in the ellipsis.
+ * @param Args Argument vector.
+ *
+ * @remarks See remarks on VMR3ReqCallVU.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnVMReqPriorityCallWaitV,(PPDMDEVINS pDevIns, VMCPUID idDstCpu, PFNRT pfnFunction, unsigned cArgs, va_list Args));
+
+ /**
+ * Stops the VM and enters the debugger to look at the guest state.
+ *
+ * Use the PDMDeviceDBGFStop() inline function with the RT_SRC_POS macro instead of
+ * invoking this function directly.
+ *
+ * @returns VBox status code which must be passed up to the VMM.
+ * @param pDevIns The device instance.
+ * @param pszFile Filename of the assertion location.
+ * @param iLine The linenumber of the assertion location.
+ * @param pszFunction Function of the assertion location.
+ * @param pszFormat Message. (optional)
+ * @param args Message parameters.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnDBGFStopV,(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction,
+ const char *pszFormat, va_list args) RT_IPRT_FORMAT_ATTR(5, 0));
+
+ /**
+ * Register a info handler with DBGF.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param pszName The identifier of the info.
+ * @param pszDesc The description of the info and any arguments
+ * the handler may take.
+ * @param pfnHandler The handler function to be called to display the
+ * info.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnDBGFInfoRegister,(PPDMDEVINS pDevIns, const char *pszName, const char *pszDesc, PFNDBGFHANDLERDEV pfnHandler));
+
+ /**
+ * Register a info handler with DBGF, argv style.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param pszName The identifier of the info.
+ * @param pszDesc The description of the info and any arguments
+ * the handler may take.
+ * @param pfnHandler The handler function to be called to display the
+ * info.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnDBGFInfoRegisterArgv,(PPDMDEVINS pDevIns, const char *pszName, const char *pszDesc, PFNDBGFINFOARGVDEV pfnHandler));
+
+ /**
+ * Registers a set of registers for a device.
+ *
+ * The @a pvUser argument of the getter and setter callbacks will be
+ * @a pDevIns. The register names will be prefixed by the device name followed
+ * immediately by the instance number.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param paRegisters The register descriptors.
+ *
+ * @remarks The device critical section is NOT entered prior to working the
+ * callbacks registered via this helper!
+ */
+ DECLR3CALLBACKMEMBER(int, pfnDBGFRegRegister,(PPDMDEVINS pDevIns, PCDBGFREGDESC paRegisters));
+
+ /**
+ * Gets the trace buffer handle.
+ *
+ * This is used by the macros found in VBox/vmm/dbgftrace.h and is not
+ * really inteded for direct usage, thus no inline wrapper function.
+ *
+ * @returns Trace buffer handle or NIL_RTTRACEBUF.
+ * @param pDevIns The device instance.
+ */
+ DECLR3CALLBACKMEMBER(RTTRACEBUF, pfnDBGFTraceBuf,(PPDMDEVINS pDevIns));
+
+ /**
+ * Report a bug check.
+ *
+ * @returns
+ * @param pDevIns The device instance.
+ * @param enmEvent The kind of BSOD event this is.
+ * @param uBugCheck The bug check number.
+ * @param uP1 The bug check parameter \#1.
+ * @param uP2 The bug check parameter \#2.
+ * @param uP3 The bug check parameter \#3.
+ * @param uP4 The bug check parameter \#4.
+ *
+ * @thread EMT
+ */
+ DECLR3CALLBACKMEMBER(VBOXSTRICTRC, pfnDBGFReportBugCheck,(PPDMDEVINS pDevIns, DBGFEVENTTYPE enmEvent, uint64_t uBugCheck,
+ uint64_t uP1, uint64_t uP2, uint64_t uP3, uint64_t uP4));
+
+ /**
+ * Write core dump of the guest.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param pszFilename The name of the file to which the guest core
+ * dump should be written.
+ * @param fReplaceFile Whether to replace the file or not.
+ *
+ * @remarks The VM may need to be suspended before calling this function in
+ * order to truly stop all device threads and drivers. This function
+ * only synchronizes EMTs.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnDBGFCoreWrite,(PPDMDEVINS pDevIns, const char *pszFilename, bool fReplaceFile));
+
+ /**
+ * Gets the logger info helper.
+ * The returned info helper will unconditionally write all output to the log.
+ *
+ * @returns Pointer to the logger info helper.
+ * @param pDevIns The device instance.
+ */
+ DECLR3CALLBACKMEMBER(PCDBGFINFOHLP, pfnDBGFInfoLogHlp,(PPDMDEVINS pDevIns));
+
+ /**
+ * Queries a 64-bit register value.
+ *
+ * @retval VINF_SUCCESS
+ * @retval VERR_INVALID_VM_HANDLE
+ * @retval VERR_INVALID_CPU_ID
+ * @retval VERR_DBGF_REGISTER_NOT_FOUND
+ * @retval VERR_DBGF_UNSUPPORTED_CAST
+ * @retval VINF_DBGF_TRUNCATED_REGISTER
+ * @retval VINF_DBGF_ZERO_EXTENDED_REGISTER
+ *
+ * @param pDevIns The device instance.
+ * @param idDefCpu The default target CPU ID, VMCPUID_ANY if not
+ * applicable. Can be OR'ed with
+ * DBGFREG_HYPER_VMCPUID.
+ * @param pszReg The register that's being queried. Except for
+ * CPU registers, this must be on the form
+ * "set.reg[.sub]".
+ * @param pu64 Where to store the register value.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnDBGFRegNmQueryU64,(PPDMDEVINS pDevIns, VMCPUID idDefCpu, const char *pszReg, uint64_t *pu64));
+
+ /**
+ * Format a set of registers.
+ *
+ * This is restricted to registers from one CPU, that specified by @a idCpu.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param idCpu The CPU ID of any CPU registers that may be
+ * printed, pass VMCPUID_ANY if not applicable.
+ * @param pszBuf The output buffer.
+ * @param cbBuf The size of the output buffer.
+ * @param pszFormat The format string. Register names are given by
+ * %VR{name}, they take no arguments.
+ * @param va Other format arguments.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnDBGFRegPrintfV,(PPDMDEVINS pDevIns, VMCPUID idCpu, char *pszBuf, size_t cbBuf,
+ const char *pszFormat, va_list va));
+
+ /**
+ * Registers a statistics sample.
+ *
+ * @param pDevIns Device instance of the DMA.
+ * @param pvSample Pointer to the sample.
+ * @param enmType Sample type. This indicates what pvSample is
+ * pointing at.
+ * @param pszName Sample name, unix path style. If this does not
+ * start with a '/', the default prefix will be
+ * prepended, otherwise it will be used as-is.
+ * @param enmUnit Sample unit.
+ * @param pszDesc Sample description.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnSTAMRegister,(PPDMDEVINS pDevIns, void *pvSample, STAMTYPE enmType, const char *pszName, STAMUNIT enmUnit, const char *pszDesc));
+
+ /**
+ * Same as pfnSTAMRegister except that the name is specified in a
+ * RTStrPrintfV like fashion.
+ *
+ * @returns VBox status.
+ * @param pDevIns Device instance of the DMA.
+ * @param pvSample Pointer to the sample.
+ * @param enmType Sample type. This indicates what pvSample is
+ * pointing at.
+ * @param enmVisibility Visibility type specifying whether unused
+ * statistics should be visible or not.
+ * @param enmUnit Sample unit.
+ * @param pszDesc Sample description.
+ * @param pszName Sample name format string, unix path style. If
+ * this does not start with a '/', the default
+ * prefix will be prepended, otherwise it will be
+ * used as-is.
+ * @param args Arguments to the format string.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnSTAMRegisterV,(PPDMDEVINS pDevIns, void *pvSample, STAMTYPE enmType,
+ STAMVISIBILITY enmVisibility, STAMUNIT enmUnit, const char *pszDesc,
+ const char *pszName, va_list args) RT_IPRT_FORMAT_ATTR(7, 0));
+
+ /**
+ * Registers a PCI device with the default PCI bus.
+ *
+ * If a PDM device has more than one PCI device, they must be registered in the
+ * order of PDMDEVINSR3::apPciDevs.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param pPciDev The PCI device structure.
+ * This must be kept in the instance data.
+ * The PCI configuration must be initialized before registration.
+ * @param fFlags 0, PDMPCIDEVREG_F_PCI_BRIDGE or
+ * PDMPCIDEVREG_F_NOT_MANDATORY_NO.
+ * @param uPciDevNo PDMPCIDEVREG_DEV_NO_FIRST_UNUSED,
+ * PDMPCIDEVREG_DEV_NO_SAME_AS_PREV, or a specific
+ * device number (0-31). This will be ignored if
+ * the CFGM configuration contains a PCIDeviceNo
+ * value.
+ * @param uPciFunNo PDMPCIDEVREG_FUN_NO_FIRST_UNUSED, or a specific
+ * function number (0-7). This will be ignored if
+ * the CFGM configuration contains a PCIFunctionNo
+ * value.
+ * @param pszName Device name, if NULL PDMDEVREG::szName is used.
+ * The pointer is saved, so don't free or changed.
+ * @note The PCI device configuration is now implicit from the apPciDevs
+ * index, meaning that the zero'th entry is the primary one and
+ * subsequent uses CFGM subkeys "PciDev1", "PciDev2" and so on.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPCIRegister,(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t fFlags,
+ uint8_t uPciDevNo, uint8_t uPciFunNo, const char *pszName));
+
+ /**
+ * Initialize MSI or MSI-X emulation support for the given PCI device.
+ *
+ * @see PDMPCIBUSREG::pfnRegisterMsiR3 for details.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param pPciDev The PCI device. NULL is an alias for the first
+ * one registered.
+ * @param pMsiReg MSI emulation registration structure.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPCIRegisterMsi,(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, PPDMMSIREG pMsiReg));
+
+ /**
+ * Registers a I/O region (memory mapped or I/O ports) for a PCI device.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param pPciDev The PCI device structure. If NULL the default
+ * PCI device for this device instance is used.
+ * @param iRegion The region number.
+ * @param cbRegion Size of the region.
+ * @param enmType PCI_ADDRESS_SPACE_MEM, PCI_ADDRESS_SPACE_IO or PCI_ADDRESS_SPACE_MEM_PREFETCH.
+ * @param fFlags PDMPCIDEV_IORGN_F_XXX.
+ * @param hHandle An I/O port, MMIO or MMIO2 handle according to
+ * @a fFlags, UINT64_MAX if no handle is passed
+ * (old style).
+ * @param pfnMapUnmap Callback for doing the mapping, optional when a
+ * handle is specified. The callback will be
+ * invoked holding only the PDM lock. The device
+ * lock will _not_ be taken (due to lock order).
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPCIIORegionRegister,(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t iRegion,
+ RTGCPHYS cbRegion, PCIADDRESSSPACE enmType, uint32_t fFlags,
+ uint64_t hHandle, PFNPCIIOREGIONMAP pfnMapUnmap));
+
+ /**
+ * Register PCI configuration space read/write callbacks.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param pPciDev The PCI device structure. If NULL the default
+ * PCI device for this device instance is used.
+ * @param pfnRead Pointer to the user defined PCI config read function.
+ * to call default PCI config read function. Can be NULL.
+ * @param pfnWrite Pointer to the user defined PCI config write function.
+ * @remarks The callbacks will be invoked holding the PDM lock. The device lock
+ * is NOT take because that is very likely be a lock order violation.
+ * @thread EMT(0)
+ * @note Only callable during VM creation.
+ * @sa PDMDevHlpPCIConfigRead, PDMDevHlpPCIConfigWrite
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPCIInterceptConfigAccesses,(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev,
+ PFNPCICONFIGREAD pfnRead, PFNPCICONFIGWRITE pfnWrite));
+
+ /**
+ * Perform a PCI configuration space write.
+ *
+ * This is for devices that make use of PDMDevHlpPCIInterceptConfigAccesses().
+ *
+ * @returns Strict VBox status code (mainly DBGFSTOP).
+ * @param pDevIns The device instance.
+ * @param pPciDev The PCI device which config space is being read.
+ * @param uAddress The config space address.
+ * @param cb The size of the read: 1, 2 or 4 bytes.
+ * @param u32Value The value to write.
+ */
+ DECLR3CALLBACKMEMBER(VBOXSTRICTRC, pfnPCIConfigWrite,(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev,
+ uint32_t uAddress, unsigned cb, uint32_t u32Value));
+
+ /**
+ * Perform a PCI configuration space read.
+ *
+ * This is for devices that make use of PDMDevHlpPCIInterceptConfigAccesses().
+ *
+ * @returns Strict VBox status code (mainly DBGFSTOP).
+ * @param pDevIns The device instance.
+ * @param pPciDev The PCI device which config space is being read.
+ * @param uAddress The config space address.
+ * @param cb The size of the read: 1, 2 or 4 bytes.
+ * @param pu32Value Where to return the value.
+ */
+ DECLR3CALLBACKMEMBER(VBOXSTRICTRC, pfnPCIConfigRead,(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev,
+ uint32_t uAddress, unsigned cb, uint32_t *pu32Value));
+
+ /**
+ * Bus master physical memory read.
+ *
+ * @returns VINF_SUCCESS or VERR_PGM_PCI_PHYS_READ_BM_DISABLED, later maybe
+ * VERR_EM_MEMORY. The informational status shall NOT be propagated!
+ * @param pDevIns The device instance.
+ * @param pPciDev The PCI device structure. If NULL the default
+ * PCI device for this device instance is used.
+ * @param GCPhys Physical address start reading from.
+ * @param pvBuf Where to put the read bits.
+ * @param cbRead How many bytes to read.
+ * @param fFlags Combination of PDM_DEVHLP_PHYS_RW_F_XXX.
+ * @thread Any thread, but the call may involve the emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPCIPhysRead,(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead, uint32_t fFlags));
+
+ /**
+ * Bus master physical memory write.
+ *
+ * @returns VINF_SUCCESS or VERR_PGM_PCI_PHYS_WRITE_BM_DISABLED, later maybe
+ * VERR_EM_MEMORY. The informational status shall NOT be propagated!
+ * @param pDevIns The device instance.
+ * @param pPciDev The PCI device structure. If NULL the default
+ * PCI device for this device instance is used.
+ * @param GCPhys Physical address to write to.
+ * @param pvBuf What to write.
+ * @param cbWrite How many bytes to write.
+ * @param fFlags Combination of PDM_DEVHLP_PHYS_RW_F_XXX.
+ * @thread Any thread, but the call may involve the emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPCIPhysWrite,(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite, uint32_t fFlags));
+
+ /**
+ * Requests the mapping of a guest page into ring-3 in preparation for a bus master
+ * physical memory write operation.
+ *
+ * Refer pfnPhysGCPhys2CCPtr() for further details.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param pPciDev The PCI device structure. If NULL the default
+ * PCI device for this device instance is used.
+ * @param GCPhys The guest physical address of the page that should be
+ * mapped.
+ * @param fFlags Flags reserved for future use, MBZ.
+ * @param ppv Where to store the address corresponding to GCPhys.
+ * @param pLock Where to store the lock information that
+ * pfnPhysReleasePageMappingLock needs.
+ *
+ * @remarks Avoid calling this API from within critical sections (other than the PGM
+ * one) because of the deadlock risk when we have to delegating the task to
+ * an EMT.
+ * @thread Any.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPCIPhysGCPhys2CCPtr,(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, RTGCPHYS GCPhys, uint32_t fFlags,
+ void **ppv, PPGMPAGEMAPLOCK pLock));
+
+ /**
+ * Requests the mapping of a guest page into ring-3, external threads, in prepartion
+ * for a bus master physical memory read operation.
+ *
+ * Refer pfnPhysGCPhys2CCPtrReadOnly() for further details.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param pPciDev The PCI device structure. If NULL the default
+ * PCI device for this device instance is used.
+ * @param GCPhys The guest physical address of the page that
+ * should be mapped.
+ * @param fFlags Flags reserved for future use, MBZ.
+ * @param ppv Where to store the address corresponding to
+ * GCPhys.
+ * @param pLock Where to store the lock information that
+ * pfnPhysReleasePageMappingLock needs.
+ *
+ * @remarks Avoid calling this API from within critical sections.
+ * @thread Any.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPCIPhysGCPhys2CCPtrReadOnly,(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, RTGCPHYS GCPhys,
+ uint32_t fFlags, void const **ppv, PPGMPAGEMAPLOCK pLock));
+
+ /**
+ * Requests the mapping of multiple guest pages into ring-3 in prepartion for a bus
+ * master physical memory write operation.
+ *
+ * When you're done with the pages, call pfnPhysBulkReleasePageMappingLocks()
+ * ASAP to release them.
+ *
+ * Refer pfnPhysBulkGCPhys2CCPtr() for further details.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param pPciDev The PCI device structure. If NULL the default
+ * PCI device for this device instance is used.
+ * @param cPages Number of pages to lock.
+ * @param paGCPhysPages The guest physical address of the pages that
+ * should be mapped (@a cPages entries).
+ * @param fFlags Flags reserved for future use, MBZ.
+ * @param papvPages Where to store the ring-3 mapping addresses
+ * corresponding to @a paGCPhysPages.
+ * @param paLocks Where to store the locking information that
+ * pfnPhysBulkReleasePageMappingLock needs (@a cPages
+ * in length).
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPCIPhysBulkGCPhys2CCPtr,(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t cPages,
+ PCRTGCPHYS paGCPhysPages, uint32_t fFlags, void **papvPages,
+ PPGMPAGEMAPLOCK paLocks));
+
+ /**
+ * Requests the mapping of multiple guest pages into ring-3 in preparation for a bus
+ * master physical memory read operation.
+ *
+ * When you're done with the pages, call pfnPhysBulkReleasePageMappingLocks()
+ * ASAP to release them.
+ *
+ * Refer pfnPhysBulkGCPhys2CCPtrReadOnly() for further details.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param pPciDev The PCI device structure. If NULL the default
+ * PCI device for this device instance is used.
+ * @param cPages Number of pages to lock.
+ * @param paGCPhysPages The guest physical address of the pages that
+ * should be mapped (@a cPages entries).
+ * @param fFlags Flags reserved for future use, MBZ.
+ * @param papvPages Where to store the ring-3 mapping addresses
+ * corresponding to @a paGCPhysPages.
+ * @param paLocks Where to store the lock information that
+ * pfnPhysReleasePageMappingLock needs (@a cPages
+ * in length).
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPCIPhysBulkGCPhys2CCPtrReadOnly,(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t cPages,
+ PCRTGCPHYS paGCPhysPages, uint32_t fFlags,
+ void const **papvPages, PPGMPAGEMAPLOCK paLocks));
+
+ /**
+ * Sets the IRQ for the given PCI device.
+ *
+ * @param pDevIns The device instance.
+ * @param pPciDev The PCI device structure. If NULL the default
+ * PCI device for this device instance is used.
+ * @param iIrq IRQ number to set.
+ * @param iLevel IRQ level. See the PDM_IRQ_LEVEL_* \#defines.
+ * @thread Any thread, but will involve the emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnPCISetIrq,(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, int iIrq, int iLevel));
+
+ /**
+ * Sets the IRQ for the given PCI device, but doesn't wait for EMT to process
+ * the request when not called from EMT.
+ *
+ * @param pDevIns The device instance.
+ * @param pPciDev The PCI device structure. If NULL the default
+ * PCI device for this device instance is used.
+ * @param iIrq IRQ number to set.
+ * @param iLevel IRQ level.
+ * @thread Any thread, but will involve the emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnPCISetIrqNoWait,(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, int iIrq, int iLevel));
+
+ /**
+ * Set ISA IRQ for a device.
+ *
+ * @param pDevIns The device instance.
+ * @param iIrq IRQ number to set.
+ * @param iLevel IRQ level. See the PDM_IRQ_LEVEL_* \#defines.
+ * @thread Any thread, but will involve the emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnISASetIrq,(PPDMDEVINS pDevIns, int iIrq, int iLevel));
+
+ /**
+ * Set the ISA IRQ for a device, but don't wait for EMT to process
+ * the request when not called from EMT.
+ *
+ * @param pDevIns The device instance.
+ * @param iIrq IRQ number to set.
+ * @param iLevel IRQ level. See the PDM_IRQ_LEVEL_* \#defines.
+ * @thread Any thread, but will involve the emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnISASetIrqNoWait,(PPDMDEVINS pDevIns, int iIrq, int iLevel));
+
+ /**
+ * Attaches a driver (chain) to the device.
+ *
+ * The first call for a LUN this will serve as a registration of the LUN. The pBaseInterface and
+ * the pszDesc string will be registered with that LUN and kept around for PDMR3QueryDeviceLun().
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param iLun The logical unit to attach.
+ * @param pBaseInterface Pointer to the base interface for that LUN. (device side / down)
+ * @param ppBaseInterface Where to store the pointer to the base interface. (driver side / up)
+ * @param pszDesc Pointer to a string describing the LUN. This string must remain valid
+ * for the live of the device instance.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnDriverAttach,(PPDMDEVINS pDevIns, uint32_t iLun, PPDMIBASE pBaseInterface,
+ PPDMIBASE *ppBaseInterface, const char *pszDesc));
+
+ /**
+ * Detaches an attached driver (chain) from the device again.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param pDrvIns The driver instance to detach.
+ * @param fFlags Flags, combination of the PDMDEVATT_FLAGS_* \#defines.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnDriverDetach,(PPDMDEVINS pDevIns, PPDMDRVINS pDrvIns, uint32_t fFlags));
+
+ /**
+ * Reconfigures the driver chain for a LUN, detaching any driver currently
+ * present there.
+ *
+ * Caller will have attach it, of course.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param iLun The logical unit to reconfigure.
+ * @param cDepth The depth of the driver chain. Determins the
+ * size of @a papszDrivers and @a papConfigs.
+ * @param papszDrivers The names of the drivers to configure in the
+ * chain, first entry is the one immediately
+ * below the device/LUN
+ * @param papConfigs The configurations for each of the drivers
+ * in @a papszDrivers array. NULL entries
+ * corresponds to empty 'Config' nodes. This
+ * function will take ownership of non-NULL
+ * CFGM sub-trees and set the array member to
+ * NULL, so the caller can do cleanups on
+ * failure. This parameter is optional.
+ * @param fFlags Reserved, MBZ.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnDriverReconfigure,(PPDMDEVINS pDevIns, uint32_t iLun, uint32_t cDepth,
+ const char * const *papszDrivers, PCFGMNODE *papConfigs, uint32_t fFlags));
+
+ /** @name Exported PDM Queue Functions
+ * @{ */
+ /**
+ * Create a queue.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param cbItem The size of a queue item.
+ * @param cItems The number of items in the queue.
+ * @param cMilliesInterval The number of milliseconds between polling the queue.
+ * If 0 then the emulation thread will be notified whenever an item arrives.
+ * @param pfnCallback The consumer function.
+ * @param fRZEnabled Set if the queue should work in RC and R0.
+ * @param pszName The queue base name. The instance number will be
+ * appended automatically.
+ * @param phQueue Where to store the queue handle on success.
+ * @thread EMT(0)
+ * @remarks The device critical section will NOT be entered before calling the
+ * callback. No locks will be held, but for now it's safe to assume
+ * that only one EMT will do queue callbacks at any one time.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnQueueCreate,(PPDMDEVINS pDevIns, size_t cbItem, uint32_t cItems, uint32_t cMilliesInterval,
+ PFNPDMQUEUEDEV pfnCallback, bool fRZEnabled, const char *pszName,
+ PDMQUEUEHANDLE *phQueue));
+
+ DECLR3CALLBACKMEMBER(PPDMQUEUEITEMCORE, pfnQueueAlloc,(PPDMDEVINS pDevIns, PDMQUEUEHANDLE hQueue));
+ DECLR3CALLBACKMEMBER(int, pfnQueueInsert,(PPDMDEVINS pDevIns, PDMQUEUEHANDLE hQueue, PPDMQUEUEITEMCORE pItem));
+ DECLR3CALLBACKMEMBER(bool, pfnQueueFlushIfNecessary,(PPDMDEVINS pDevIns, PDMQUEUEHANDLE hQueue));
+ /** @} */
+
+ /** @name PDM Task
+ * @{ */
+ /**
+ * Create an asynchronous ring-3 task.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param fFlags PDMTASK_F_XXX
+ * @param pszName The function name or similar. Used for statistics,
+ * so no slashes.
+ * @param pfnCallback The task function.
+ * @param pvUser User argument for the task function.
+ * @param phTask Where to return the task handle.
+ * @thread EMT(0)
+ */
+ DECLR3CALLBACKMEMBER(int, pfnTaskCreate,(PPDMDEVINS pDevIns, uint32_t fFlags, const char *pszName,
+ PFNPDMTASKDEV pfnCallback, void *pvUser, PDMTASKHANDLE *phTask));
+ /**
+ * Triggers the running the given task.
+ *
+ * @returns VBox status code.
+ * @retval VINF_ALREADY_POSTED is the task is already pending.
+ * @param pDevIns The device instance.
+ * @param hTask The task to trigger.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnTaskTrigger,(PPDMDEVINS pDevIns, PDMTASKHANDLE hTask));
+ /** @} */
+
+ /** @name SUP Event Semaphore Wrappers (single release / auto reset)
+ * These semaphores can be signalled from ring-0.
+ * @{ */
+ /** @sa SUPSemEventCreate */
+ DECLR3CALLBACKMEMBER(int, pfnSUPSemEventCreate,(PPDMDEVINS pDevIns, PSUPSEMEVENT phEvent));
+ /** @sa SUPSemEventClose */
+ DECLR3CALLBACKMEMBER(int, pfnSUPSemEventClose,(PPDMDEVINS pDevIns, SUPSEMEVENT hEvent));
+ /** @sa SUPSemEventSignal */
+ DECLR3CALLBACKMEMBER(int, pfnSUPSemEventSignal,(PPDMDEVINS pDevIns, SUPSEMEVENT hEvent));
+ /** @sa SUPSemEventWaitNoResume */
+ DECLR3CALLBACKMEMBER(int, pfnSUPSemEventWaitNoResume,(PPDMDEVINS pDevIns, SUPSEMEVENT hEvent, uint32_t cMillies));
+ /** @sa SUPSemEventWaitNsAbsIntr */
+ DECLR3CALLBACKMEMBER(int, pfnSUPSemEventWaitNsAbsIntr,(PPDMDEVINS pDevIns, SUPSEMEVENT hEvent, uint64_t uNsTimeout));
+ /** @sa SUPSemEventWaitNsRelIntr */
+ DECLR3CALLBACKMEMBER(int, pfnSUPSemEventWaitNsRelIntr,(PPDMDEVINS pDevIns, SUPSEMEVENT hEvent, uint64_t cNsTimeout));
+ /** @sa SUPSemEventGetResolution */
+ DECLR3CALLBACKMEMBER(uint32_t, pfnSUPSemEventGetResolution,(PPDMDEVINS pDevIns));
+ /** @} */
+
+ /** @name SUP Multi Event Semaphore Wrappers (multiple release / manual reset)
+ * These semaphores can be signalled from ring-0.
+ * @{ */
+ /** @sa SUPSemEventMultiCreate */
+ DECLR3CALLBACKMEMBER(int, pfnSUPSemEventMultiCreate,(PPDMDEVINS pDevIns, PSUPSEMEVENTMULTI phEventMulti));
+ /** @sa SUPSemEventMultiClose */
+ DECLR3CALLBACKMEMBER(int, pfnSUPSemEventMultiClose,(PPDMDEVINS pDevIns, SUPSEMEVENTMULTI hEventMulti));
+ /** @sa SUPSemEventMultiSignal */
+ DECLR3CALLBACKMEMBER(int, pfnSUPSemEventMultiSignal,(PPDMDEVINS pDevIns, SUPSEMEVENTMULTI hEventMulti));
+ /** @sa SUPSemEventMultiReset */
+ DECLR3CALLBACKMEMBER(int, pfnSUPSemEventMultiReset,(PPDMDEVINS pDevIns, SUPSEMEVENTMULTI hEventMulti));
+ /** @sa SUPSemEventMultiWaitNoResume */
+ DECLR3CALLBACKMEMBER(int, pfnSUPSemEventMultiWaitNoResume,(PPDMDEVINS pDevIns, SUPSEMEVENTMULTI hEventMulti, uint32_t cMillies));
+ /** @sa SUPSemEventMultiWaitNsAbsIntr */
+ DECLR3CALLBACKMEMBER(int, pfnSUPSemEventMultiWaitNsAbsIntr,(PPDMDEVINS pDevIns, SUPSEMEVENTMULTI hEventMulti, uint64_t uNsTimeout));
+ /** @sa SUPSemEventMultiWaitNsRelIntr */
+ DECLR3CALLBACKMEMBER(int, pfnSUPSemEventMultiWaitNsRelIntr,(PPDMDEVINS pDevIns, SUPSEMEVENTMULTI hEventMulti, uint64_t cNsTimeout));
+ /** @sa SUPSemEventMultiGetResolution */
+ DECLR3CALLBACKMEMBER(uint32_t, pfnSUPSemEventMultiGetResolution,(PPDMDEVINS pDevIns));
+ /** @} */
+
+ /**
+ * Initializes a PDM critical section.
+ *
+ * The PDM critical sections are derived from the IPRT critical sections, but
+ * works in RC and R0 as well.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param pCritSect Pointer to the critical section.
+ * @param SRC_POS Use RT_SRC_POS.
+ * @param pszNameFmt Format string for naming the critical section.
+ * For statistics and lock validation.
+ * @param va Arguments for the format string.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnCritSectInit,(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, RT_SRC_POS_DECL,
+ const char *pszNameFmt, va_list va) RT_IPRT_FORMAT_ATTR(6, 0));
+
+ /**
+ * Gets the NOP critical section.
+ *
+ * @returns The ring-3 address of the NOP critical section.
+ * @param pDevIns The device instance.
+ */
+ DECLR3CALLBACKMEMBER(PPDMCRITSECT, pfnCritSectGetNop,(PPDMDEVINS pDevIns));
+
+ /**
+ * Changes the device level critical section from the automatically created
+ * default to one desired by the device constructor.
+ *
+ * For ring-0 and raw-mode capable devices, the call must be repeated in each of
+ * the additional contexts.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param pCritSect The critical section to use. NULL is not
+ * valid, instead use the NOP critical
+ * section.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSetDeviceCritSect,(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect));
+
+ /** @name Exported PDM Critical Section Functions
+ * @{ */
+ DECLR3CALLBACKMEMBER(bool, pfnCritSectYield,(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect));
+ DECLR3CALLBACKMEMBER(int, pfnCritSectEnter,(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, int rcBusy));
+ DECLR3CALLBACKMEMBER(int, pfnCritSectEnterDebug,(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, int rcBusy, RTHCUINTPTR uId, RT_SRC_POS_DECL));
+ DECLR3CALLBACKMEMBER(int, pfnCritSectTryEnter,(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect));
+ DECLR3CALLBACKMEMBER(int, pfnCritSectTryEnterDebug,(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, RTHCUINTPTR uId, RT_SRC_POS_DECL));
+ DECLR3CALLBACKMEMBER(int, pfnCritSectLeave,(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect));
+ DECLR3CALLBACKMEMBER(bool, pfnCritSectIsOwner,(PPDMDEVINS pDevIns, PCPDMCRITSECT pCritSect));
+ DECLR3CALLBACKMEMBER(bool, pfnCritSectIsInitialized,(PPDMDEVINS pDevIns, PCPDMCRITSECT pCritSect));
+ DECLR3CALLBACKMEMBER(bool, pfnCritSectHasWaiters,(PPDMDEVINS pDevIns, PCPDMCRITSECT pCritSect));
+ DECLR3CALLBACKMEMBER(uint32_t, pfnCritSectGetRecursion,(PPDMDEVINS pDevIns, PCPDMCRITSECT pCritSect));
+ DECLR3CALLBACKMEMBER(int, pfnCritSectScheduleExitEvent,(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, SUPSEMEVENT hEventToSignal));
+ DECLR3CALLBACKMEMBER(int, pfnCritSectDelete,(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect));
+ /** @} */
+
+ /** @name Exported PDM Read/Write Critical Section Functions
+ * @{ */
+ DECLR3CALLBACKMEMBER(int, pfnCritSectRwInit,(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect, RT_SRC_POS_DECL,
+ const char *pszNameFmt, va_list va) RT_IPRT_FORMAT_ATTR(6, 0));
+ DECLR3CALLBACKMEMBER(int, pfnCritSectRwDelete,(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect));
+
+ DECLR3CALLBACKMEMBER(int, pfnCritSectRwEnterShared,(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect, int rcBusy));
+ DECLR3CALLBACKMEMBER(int, pfnCritSectRwEnterSharedDebug,(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect, int rcBusy, RTHCUINTPTR uId, RT_SRC_POS_DECL));
+ DECLR3CALLBACKMEMBER(int, pfnCritSectRwTryEnterShared,(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect));
+ DECLR3CALLBACKMEMBER(int, pfnCritSectRwTryEnterSharedDebug,(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect, RTHCUINTPTR uId, RT_SRC_POS_DECL));
+ DECLR3CALLBACKMEMBER(int, pfnCritSectRwLeaveShared,(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect));
+
+ DECLR3CALLBACKMEMBER(int, pfnCritSectRwEnterExcl,(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect, int rcBusy));
+ DECLR3CALLBACKMEMBER(int, pfnCritSectRwEnterExclDebug,(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect, int rcBusy, RTHCUINTPTR uId, RT_SRC_POS_DECL));
+ DECLR3CALLBACKMEMBER(int, pfnCritSectRwTryEnterExcl,(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect));
+ DECLR3CALLBACKMEMBER(int, pfnCritSectRwTryEnterExclDebug,(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect, RTHCUINTPTR uId, RT_SRC_POS_DECL));
+ DECLR3CALLBACKMEMBER(int, pfnCritSectRwLeaveExcl,(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect));
+
+ DECLR3CALLBACKMEMBER(bool, pfnCritSectRwIsWriteOwner,(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect));
+ DECLR3CALLBACKMEMBER(bool, pfnCritSectRwIsReadOwner,(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect, bool fWannaHear));
+ DECLR3CALLBACKMEMBER(uint32_t, pfnCritSectRwGetWriteRecursion,(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect));
+ DECLR3CALLBACKMEMBER(uint32_t, pfnCritSectRwGetWriterReadRecursion,(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect));
+ DECLR3CALLBACKMEMBER(uint32_t, pfnCritSectRwGetReadCount,(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect));
+ DECLR3CALLBACKMEMBER(bool, pfnCritSectRwIsInitialized,(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect));
+ /** @} */
+
+ /**
+ * Creates a PDM thread.
+ *
+ * This differs from the RTThreadCreate() API in that PDM takes care of suspending,
+ * resuming, and destroying the thread as the VM state changes.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param ppThread Where to store the thread 'handle'.
+ * @param pvUser The user argument to the thread function.
+ * @param pfnThread The thread function.
+ * @param pfnWakeup The wakup callback. This is called on the EMT
+ * thread when a state change is pending.
+ * @param cbStack See RTThreadCreate.
+ * @param enmType See RTThreadCreate.
+ * @param pszName See RTThreadCreate.
+ * @remarks The device critical section will NOT be entered prior to invoking
+ * the function pointers.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnThreadCreate,(PPDMDEVINS pDevIns, PPPDMTHREAD ppThread, void *pvUser, PFNPDMTHREADDEV pfnThread,
+ PFNPDMTHREADWAKEUPDEV pfnWakeup, size_t cbStack, RTTHREADTYPE enmType, const char *pszName));
+
+ /** @name Exported PDM Thread Functions
+ * @{ */
+ DECLR3CALLBACKMEMBER(int, pfnThreadDestroy,(PPDMTHREAD pThread, int *pRcThread));
+ DECLR3CALLBACKMEMBER(int, pfnThreadIAmSuspending,(PPDMTHREAD pThread));
+ DECLR3CALLBACKMEMBER(int, pfnThreadIAmRunning,(PPDMTHREAD pThread));
+ DECLR3CALLBACKMEMBER(int, pfnThreadSleep,(PPDMTHREAD pThread, RTMSINTERVAL cMillies));
+ DECLR3CALLBACKMEMBER(int, pfnThreadSuspend,(PPDMTHREAD pThread));
+ DECLR3CALLBACKMEMBER(int, pfnThreadResume,(PPDMTHREAD pThread));
+ /** @} */
+
+ /**
+ * Set up asynchronous handling of a suspend, reset or power off notification.
+ *
+ * This shall only be called when getting the notification. It must be called
+ * for each one.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param pfnAsyncNotify The callback.
+ * @thread EMT(0)
+ * @remarks The caller will enter the device critical section prior to invoking
+ * the callback.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSetAsyncNotification, (PPDMDEVINS pDevIns, PFNPDMDEVASYNCNOTIFY pfnAsyncNotify));
+
+ /**
+ * Notify EMT(0) that the device has completed the asynchronous notification
+ * handling.
+ *
+ * This can be called at any time, spurious calls will simply be ignored.
+ *
+ * @param pDevIns The device instance.
+ * @thread Any
+ */
+ DECLR3CALLBACKMEMBER(void, pfnAsyncNotificationCompleted, (PPDMDEVINS pDevIns));
+
+ /**
+ * Register the RTC device.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param pRtcReg Pointer to a RTC registration structure.
+ * @param ppRtcHlp Where to store the pointer to the helper
+ * functions.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnRTCRegister,(PPDMDEVINS pDevIns, PCPDMRTCREG pRtcReg, PCPDMRTCHLP *ppRtcHlp));
+
+ /**
+ * Register a PCI Bus.
+ *
+ * @returns VBox status code, but the positive values 0..31 are used to indicate
+ * bus number rather than informational status codes.
+ * @param pDevIns The device instance.
+ * @param pPciBusReg Pointer to PCI bus registration structure.
+ * @param ppPciHlp Where to store the pointer to the PCI Bus
+ * helpers.
+ * @param piBus Where to return the PDM bus number. Optional.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPCIBusRegister,(PPDMDEVINS pDevIns, PPDMPCIBUSREGR3 pPciBusReg,
+ PCPDMPCIHLPR3 *ppPciHlp, uint32_t *piBus));
+
+ /**
+ * Register the IOMMU device.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param pIommuReg Pointer to a IOMMU registration structure.
+ * @param ppIommuHlp Where to store the pointer to the ring-3 IOMMU
+ * helpers.
+ * @param pidxIommu Where to return the IOMMU index. Optional.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnIommuRegister,(PPDMDEVINS pDevIns, PPDMIOMMUREGR3 pIommuReg, PCPDMIOMMUHLPR3 *ppIommuHlp,
+ uint32_t *pidxIommu));
+
+ /**
+ * Register the PIC device.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param pPicReg Pointer to a PIC registration structure.
+ * @param ppPicHlp Where to store the pointer to the ring-3 PIC
+ * helpers.
+ * @sa PDMDevHlpPICSetUpContext
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPICRegister,(PPDMDEVINS pDevIns, PPDMPICREG pPicReg, PCPDMPICHLP *ppPicHlp));
+
+ /**
+ * Register the APIC device.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnApicRegister,(PPDMDEVINS pDevIns));
+
+ /**
+ * Register the I/O APIC device.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param pIoApicReg Pointer to a I/O APIC registration structure.
+ * @param ppIoApicHlp Where to store the pointer to the IOAPIC
+ * helpers.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnIoApicRegister,(PPDMDEVINS pDevIns, PPDMIOAPICREG pIoApicReg, PCPDMIOAPICHLP *ppIoApicHlp));
+
+ /**
+ * Register the HPET device.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param pHpetReg Pointer to a HPET registration structure.
+ * @param ppHpetHlpR3 Where to store the pointer to the HPET
+ * helpers.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnHpetRegister,(PPDMDEVINS pDevIns, PPDMHPETREG pHpetReg, PCPDMHPETHLPR3 *ppHpetHlpR3));
+
+ /**
+ * Register a raw PCI device.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param pPciRawReg Pointer to a raw PCI registration structure.
+ * @param ppPciRawHlpR3 Where to store the pointer to the raw PCI
+ * device helpers.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPciRawRegister,(PPDMDEVINS pDevIns, PPDMPCIRAWREG pPciRawReg, PCPDMPCIRAWHLPR3 *ppPciRawHlpR3));
+
+ /**
+ * Register the DMA device.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param pDmacReg Pointer to a DMAC registration structure.
+ * @param ppDmacHlp Where to store the pointer to the DMA helpers.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnDMACRegister,(PPDMDEVINS pDevIns, PPDMDMACREG pDmacReg, PCPDMDMACHLP *ppDmacHlp));
+
+ /**
+ * Register transfer function for DMA channel.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param uChannel Channel number.
+ * @param pfnTransferHandler Device specific transfer callback function.
+ * @param pvUser User pointer to pass to the callback.
+ * @thread EMT
+ */
+ DECLR3CALLBACKMEMBER(int, pfnDMARegister,(PPDMDEVINS pDevIns, unsigned uChannel, PFNDMATRANSFERHANDLER pfnTransferHandler, void *pvUser));
+
+ /**
+ * Read memory.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param uChannel Channel number.
+ * @param pvBuffer Pointer to target buffer.
+ * @param off DMA position.
+ * @param cbBlock Block size.
+ * @param pcbRead Where to store the number of bytes which was
+ * read. optional.
+ * @thread EMT
+ */
+ DECLR3CALLBACKMEMBER(int, pfnDMAReadMemory,(PPDMDEVINS pDevIns, unsigned uChannel, void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbRead));
+
+ /**
+ * Write memory.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param uChannel Channel number.
+ * @param pvBuffer Memory to write.
+ * @param off DMA position.
+ * @param cbBlock Block size.
+ * @param pcbWritten Where to store the number of bytes which was
+ * written. optional.
+ * @thread EMT
+ */
+ DECLR3CALLBACKMEMBER(int, pfnDMAWriteMemory,(PPDMDEVINS pDevIns, unsigned uChannel, const void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbWritten));
+
+ /**
+ * Set the DREQ line.
+ *
+ * @returns VBox status code.
+ * @param pDevIns Device instance.
+ * @param uChannel Channel number.
+ * @param uLevel Level of the line.
+ * @thread EMT
+ */
+ DECLR3CALLBACKMEMBER(int, pfnDMASetDREQ,(PPDMDEVINS pDevIns, unsigned uChannel, unsigned uLevel));
+
+ /**
+ * Get channel mode.
+ *
+ * @returns Channel mode. See specs.
+ * @param pDevIns The device instance.
+ * @param uChannel Channel number.
+ * @thread EMT
+ */
+ DECLR3CALLBACKMEMBER(uint8_t, pfnDMAGetChannelMode,(PPDMDEVINS pDevIns, unsigned uChannel));
+
+ /**
+ * Schedule DMA execution.
+ *
+ * @param pDevIns The device instance.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnDMASchedule,(PPDMDEVINS pDevIns));
+
+ /**
+ * Write CMOS value and update the checksum(s).
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param iReg The CMOS register index.
+ * @param u8Value The CMOS register value.
+ * @thread EMT
+ */
+ DECLR3CALLBACKMEMBER(int, pfnCMOSWrite,(PPDMDEVINS pDevIns, unsigned iReg, uint8_t u8Value));
+
+ /**
+ * Read CMOS value.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param iReg The CMOS register index.
+ * @param pu8Value Where to store the CMOS register value.
+ * @thread EMT
+ */
+ DECLR3CALLBACKMEMBER(int, pfnCMOSRead,(PPDMDEVINS pDevIns, unsigned iReg, uint8_t *pu8Value));
+
+ /**
+ * Assert that the current thread is the emulation thread.
+ *
+ * @returns True if correct.
+ * @returns False if wrong.
+ * @param pDevIns The device instance.
+ * @param pszFile Filename of the assertion location.
+ * @param iLine The linenumber of the assertion location.
+ * @param pszFunction Function of the assertion location.
+ */
+ DECLR3CALLBACKMEMBER(bool, pfnAssertEMT,(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction));
+
+ /**
+ * Assert that the current thread is NOT the emulation thread.
+ *
+ * @returns True if correct.
+ * @returns False if wrong.
+ * @param pDevIns The device instance.
+ * @param pszFile Filename of the assertion location.
+ * @param iLine The linenumber of the assertion location.
+ * @param pszFunction Function of the assertion location.
+ */
+ DECLR3CALLBACKMEMBER(bool, pfnAssertOther,(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction));
+
+ /**
+ * Resolves the symbol for a raw-mode context interface.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param pvInterface The interface structure.
+ * @param cbInterface The size of the interface structure.
+ * @param pszSymPrefix What to prefix the symbols in the list with
+ * before resolving them. This must start with
+ * 'dev' and contain the driver name.
+ * @param pszSymList List of symbols corresponding to the interface.
+ * There is generally a there is generally a define
+ * holding this list associated with the interface
+ * definition (INTERFACE_SYM_LIST). For more
+ * details see PDMR3LdrGetInterfaceSymbols.
+ * @thread EMT
+ */
+ DECLR3CALLBACKMEMBER(int, pfnLdrGetRCInterfaceSymbols,(PPDMDEVINS pDevIns, void *pvInterface, size_t cbInterface,
+ const char *pszSymPrefix, const char *pszSymList));
+
+ /**
+ * Resolves the symbol for a ring-0 context interface.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param pvInterface The interface structure.
+ * @param cbInterface The size of the interface structure.
+ * @param pszSymPrefix What to prefix the symbols in the list with
+ * before resolving them. This must start with
+ * 'dev' and contain the driver name.
+ * @param pszSymList List of symbols corresponding to the interface.
+ * There is generally a there is generally a define
+ * holding this list associated with the interface
+ * definition (INTERFACE_SYM_LIST). For more
+ * details see PDMR3LdrGetInterfaceSymbols.
+ * @thread EMT
+ */
+ DECLR3CALLBACKMEMBER(int, pfnLdrGetR0InterfaceSymbols,(PPDMDEVINS pDevIns, void *pvInterface, size_t cbInterface,
+ const char *pszSymPrefix, const char *pszSymList));
+
+ /**
+ * Calls the PDMDEVREGR0::pfnRequest callback (in ring-0 context).
+ *
+ * @returns VBox status code.
+ * @retval VERR_INVALID_FUNCTION if the callback member is NULL.
+ * @retval VERR_ACCESS_DENIED if the device isn't ring-0 capable.
+ *
+ * @param pDevIns The device instance.
+ * @param uOperation The operation to perform.
+ * @param u64Arg 64-bit integer argument.
+ * @thread EMT
+ */
+ DECLR3CALLBACKMEMBER(int, pfnCallR0,(PPDMDEVINS pDevIns, uint32_t uOperation, uint64_t u64Arg));
+
+ /**
+ * Gets the reason for the most recent VM suspend.
+ *
+ * @returns The suspend reason. VMSUSPENDREASON_INVALID is returned if no
+ * suspend has been made or if the pDevIns is invalid.
+ * @param pDevIns The device instance.
+ */
+ DECLR3CALLBACKMEMBER(VMSUSPENDREASON, pfnVMGetSuspendReason,(PPDMDEVINS pDevIns));
+
+ /**
+ * Gets the reason for the most recent VM resume.
+ *
+ * @returns The resume reason. VMRESUMEREASON_INVALID is returned if no
+ * resume has been made or if the pDevIns is invalid.
+ * @param pDevIns The device instance.
+ */
+ DECLR3CALLBACKMEMBER(VMRESUMEREASON, pfnVMGetResumeReason,(PPDMDEVINS pDevIns));
+
+ /**
+ * Requests the mapping of multiple guest page into ring-3.
+ *
+ * When you're done with the pages, call pfnPhysBulkReleasePageMappingLocks()
+ * ASAP to release them.
+ *
+ * This API will assume your intention is to write to the pages, and will
+ * therefore replace shared and zero pages. If you do not intend to modify the
+ * pages, use the pfnPhysBulkGCPhys2CCPtrReadOnly() API.
+ *
+ * @returns VBox status code.
+ * @retval VINF_SUCCESS on success.
+ * @retval VERR_PGM_PHYS_PAGE_RESERVED if any of the pages has no physical
+ * backing or if any of the pages the page has any active access
+ * handlers. The caller must fall back on using PGMR3PhysWriteExternal.
+ * @retval VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS if @a paGCPhysPages contains
+ * an invalid physical address.
+ *
+ * @param pDevIns The device instance.
+ * @param cPages Number of pages to lock.
+ * @param paGCPhysPages The guest physical address of the pages that
+ * should be mapped (@a cPages entries).
+ * @param fFlags Flags reserved for future use, MBZ.
+ * @param papvPages Where to store the ring-3 mapping addresses
+ * corresponding to @a paGCPhysPages.
+ * @param paLocks Where to store the locking information that
+ * pfnPhysBulkReleasePageMappingLock needs (@a cPages
+ * in length).
+ *
+ * @remark Avoid calling this API from within critical sections (other than the
+ * PGM one) because of the deadlock risk when we have to delegating the
+ * task to an EMT.
+ * @thread Any.
+ * @since 6.0.6
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPhysBulkGCPhys2CCPtr,(PPDMDEVINS pDevIns, uint32_t cPages, PCRTGCPHYS paGCPhysPages,
+ uint32_t fFlags, void **papvPages, PPGMPAGEMAPLOCK paLocks));
+
+ /**
+ * Requests the mapping of multiple guest page into ring-3, for reading only.
+ *
+ * When you're done with the pages, call pfnPhysBulkReleasePageMappingLocks()
+ * ASAP to release them.
+ *
+ * @returns VBox status code.
+ * @retval VINF_SUCCESS on success.
+ * @retval VERR_PGM_PHYS_PAGE_RESERVED if any of the pages has no physical
+ * backing or if any of the pages the page has an active ALL access
+ * handler. The caller must fall back on using PGMR3PhysWriteExternal.
+ * @retval VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS if @a paGCPhysPages contains
+ * an invalid physical address.
+ *
+ * @param pDevIns The device instance.
+ * @param cPages Number of pages to lock.
+ * @param paGCPhysPages The guest physical address of the pages that
+ * should be mapped (@a cPages entries).
+ * @param fFlags Flags reserved for future use, MBZ.
+ * @param papvPages Where to store the ring-3 mapping addresses
+ * corresponding to @a paGCPhysPages.
+ * @param paLocks Where to store the lock information that
+ * pfnPhysReleasePageMappingLock needs (@a cPages
+ * in length).
+ *
+ * @remark Avoid calling this API from within critical sections.
+ * @thread Any.
+ * @since 6.0.6
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPhysBulkGCPhys2CCPtrReadOnly,(PPDMDEVINS pDevIns, uint32_t cPages, PCRTGCPHYS paGCPhysPages,
+ uint32_t fFlags, void const **papvPages, PPGMPAGEMAPLOCK paLocks));
+
+ /**
+ * Release the mappings of multiple guest pages.
+ *
+ * This is the counter part of pfnPhysBulkGCPhys2CCPtr and
+ * pfnPhysBulkGCPhys2CCPtrReadOnly.
+ *
+ * @param pDevIns The device instance.
+ * @param cPages Number of pages to unlock.
+ * @param paLocks The lock structures initialized by the mapping
+ * function (@a cPages in length).
+ * @thread Any.
+ * @since 6.0.6
+ */
+ DECLR3CALLBACKMEMBER(void, pfnPhysBulkReleasePageMappingLocks,(PPDMDEVINS pDevIns, uint32_t cPages, PPGMPAGEMAPLOCK paLocks));
+
+ /**
+ * Returns the micro architecture used for the guest.
+ *
+ * @returns CPU micro architecture enum.
+ * @param pDevIns The device instance.
+ */
+ DECLR3CALLBACKMEMBER(CPUMMICROARCH, pfnCpuGetGuestMicroarch,(PPDMDEVINS pDevIns));
+
+ /**
+ * Get the number of physical and linear address bits supported by the guest.
+ *
+ * @param pDevIns The device instance.
+ * @param pcPhysAddrWidth Where to store the number of physical address bits
+ * supported by the guest.
+ * @param pcLinearAddrWidth Where to store the number of linear address bits
+ * supported by the guest.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnCpuGetGuestAddrWidths,(PPDMDEVINS pDevIns, uint8_t *pcPhysAddrWidth,
+ uint8_t *pcLinearAddrWidth));
+
+ /**
+ * Gets the scalable bus frequency.
+ *
+ * The bus frequency is used as a base in several MSRs that gives the CPU and
+ * other frequency ratios.
+ *
+ * @returns Scalable bus frequency in Hz. Will not return CPUM_SBUSFREQ_UNKNOWN.
+ * @param pDevIns The device instance.
+ */
+ DECLR3CALLBACKMEMBER(uint64_t, pfnCpuGetGuestScalableBusFrequency,(PPDMDEVINS pDevIns));
+
+ /** Space reserved for future members.
+ * @{ */
+ /**
+ * Deregister zero or more samples given their name prefix.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param pszPrefix The name prefix of the samples to remove. If this does
+ * not start with a '/', the default prefix will be
+ * prepended, otherwise it will be used as-is.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSTAMDeregisterByPrefix,(PPDMDEVINS pDevIns, const char *pszPrefix));
+ DECLR3CALLBACKMEMBER(void, pfnReserved2,(void));
+ DECLR3CALLBACKMEMBER(void, pfnReserved3,(void));
+ DECLR3CALLBACKMEMBER(void, pfnReserved4,(void));
+ DECLR3CALLBACKMEMBER(void, pfnReserved5,(void));
+ DECLR3CALLBACKMEMBER(void, pfnReserved6,(void));
+ DECLR3CALLBACKMEMBER(void, pfnReserved7,(void));
+ DECLR3CALLBACKMEMBER(void, pfnReserved8,(void));
+ DECLR3CALLBACKMEMBER(void, pfnReserved9,(void));
+ DECLR3CALLBACKMEMBER(void, pfnReserved10,(void));
+ /** @} */
+
+
+ /** API available to trusted devices only.
+ *
+ * These APIs are providing unrestricted access to the guest and the VM,
+ * or they are interacting intimately with PDM.
+ *
+ * @{
+ */
+
+ /**
+ * Gets the user mode VM handle. Restricted API.
+ *
+ * @returns User mode VM Handle.
+ * @param pDevIns The device instance.
+ */
+ DECLR3CALLBACKMEMBER(PUVM, pfnGetUVM,(PPDMDEVINS pDevIns));
+
+ /**
+ * Gets the global VM handle. Restricted API.
+ *
+ * @returns VM Handle.
+ * @param pDevIns The device instance.
+ */
+ DECLR3CALLBACKMEMBER(PVMCC, pfnGetVM,(PPDMDEVINS pDevIns));
+
+ /**
+ * Gets the VMCPU handle. Restricted API.
+ *
+ * @returns VMCPU Handle.
+ * @param pDevIns The device instance.
+ */
+ DECLR3CALLBACKMEMBER(PVMCPU, pfnGetVMCPU,(PPDMDEVINS pDevIns));
+
+ /**
+ * The the VM CPU ID of the current thread (restricted API).
+ *
+ * @returns The VMCPUID of the calling thread, NIL_VMCPUID if not EMT.
+ * @param pDevIns The device instance.
+ */
+ DECLR3CALLBACKMEMBER(VMCPUID, pfnGetCurrentCpuId,(PPDMDEVINS pDevIns));
+
+ /**
+ * Registers the VMM device heap or notifies about mapping/unmapping.
+ *
+ * This interface serves three purposes:
+ *
+ * -# Register the VMM device heap during device construction
+ * for the HM to use.
+ * -# Notify PDM/HM that it's mapped into guest address
+ * space (i.e. usable).
+ * -# Notify PDM/HM that it is being unmapped from the guest
+ * address space (i.e. not usable).
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param GCPhys The physical address if mapped, NIL_RTGCPHYS if
+ * not mapped.
+ * @param pvHeap Ring 3 heap pointer.
+ * @param cbHeap Size of the heap.
+ * @thread EMT.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnRegisterVMMDevHeap,(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTR3PTR pvHeap, unsigned cbHeap));
+
+ /**
+ * Registers the firmware (BIOS, EFI) device with PDM.
+ *
+ * The firmware provides a callback table and gets a special PDM helper table.
+ * There can only be one firmware device for a VM.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param pFwReg Firmware registration structure.
+ * @param ppFwHlp Where to return the firmware helper structure.
+ * @remarks Only valid during device construction.
+ * @thread EMT(0)
+ */
+ DECLR3CALLBACKMEMBER(int, pfnFirmwareRegister,(PPDMDEVINS pDevIns, PCPDMFWREG pFwReg, PCPDMFWHLPR3 *ppFwHlp));
+
+ /**
+ * Resets the VM.
+ *
+ * @returns The appropriate VBox status code to pass around on reset.
+ * @param pDevIns The device instance.
+ * @param fFlags PDMVMRESET_F_XXX flags.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnVMReset,(PPDMDEVINS pDevIns, uint32_t fFlags));
+
+ /**
+ * Suspends the VM.
+ *
+ * @returns The appropriate VBox status code to pass around on suspend.
+ * @param pDevIns The device instance.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnVMSuspend,(PPDMDEVINS pDevIns));
+
+ /**
+ * Suspends, saves and powers off the VM.
+ *
+ * @returns The appropriate VBox status code to pass around.
+ * @param pDevIns The device instance.
+ * @thread An emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnVMSuspendSaveAndPowerOff,(PPDMDEVINS pDevIns));
+
+ /**
+ * Power off the VM.
+ *
+ * @returns The appropriate VBox status code to pass around on power off.
+ * @param pDevIns The device instance.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnVMPowerOff,(PPDMDEVINS pDevIns));
+
+ /**
+ * Checks if the Gate A20 is enabled or not.
+ *
+ * @returns true if A20 is enabled.
+ * @returns false if A20 is disabled.
+ * @param pDevIns The device instance.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(bool, pfnA20IsEnabled,(PPDMDEVINS pDevIns));
+
+ /**
+ * Enables or disables the Gate A20.
+ *
+ * @param pDevIns The device instance.
+ * @param fEnable Set this flag to enable the Gate A20; clear it
+ * to disable.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnA20Set,(PPDMDEVINS pDevIns, bool fEnable));
+
+ /**
+ * Get the specified CPUID leaf for the virtual CPU associated with the calling
+ * thread.
+ *
+ * @param pDevIns The device instance.
+ * @param iLeaf The CPUID leaf to get.
+ * @param pEax Where to store the EAX value.
+ * @param pEbx Where to store the EBX value.
+ * @param pEcx Where to store the ECX value.
+ * @param pEdx Where to store the EDX value.
+ * @thread EMT.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnGetCpuId,(PPDMDEVINS pDevIns, uint32_t iLeaf, uint32_t *pEax, uint32_t *pEbx, uint32_t *pEcx, uint32_t *pEdx));
+
+ /**
+ * Gets the main execution engine for the VM.
+ *
+ * @returns VM_EXEC_ENGINE_XXX
+ * @param pDevIns The device instance.
+ */
+ DECLR3CALLBACKMEMBER(uint8_t, pfnGetMainExecutionEngine,(PPDMDEVINS pDevIns));
+
+ /**
+ * Get the current virtual clock time in a VM. The clock frequency must be
+ * queried separately.
+ *
+ * @returns Current clock time.
+ * @param pDevIns The device instance.
+ */
+ DECLR3CALLBACKMEMBER(uint64_t, pfnTMTimeVirtGet,(PPDMDEVINS pDevIns));
+
+ /**
+ * Get the frequency of the virtual clock.
+ *
+ * @returns The clock frequency (not variable at run-time).
+ * @param pDevIns The device instance.
+ */
+ DECLR3CALLBACKMEMBER(uint64_t, pfnTMTimeVirtGetFreq,(PPDMDEVINS pDevIns));
+
+ /**
+ * Get the current virtual clock time in a VM, in nanoseconds.
+ *
+ * @returns Current clock time (in ns).
+ * @param pDevIns The device instance.
+ */
+ DECLR3CALLBACKMEMBER(uint64_t, pfnTMTimeVirtGetNano,(PPDMDEVINS pDevIns));
+
+ /**
+ * Get the timestamp frequency.
+ *
+ * @returns Number of ticks per second.
+ * @param pDevIns The device instance.
+ */
+ DECLR3CALLBACKMEMBER(uint64_t, pfnTMCpuTicksPerSecond,(PPDMDEVINS pDevIns));
+
+ /**
+ * Gets the support driver session.
+ *
+ * This is intended for working with the semaphore API.
+ *
+ * @returns Support driver session handle.
+ * @param pDevIns The device instance.
+ */
+ DECLR3CALLBACKMEMBER(PSUPDRVSESSION, pfnGetSupDrvSession,(PPDMDEVINS pDevIns));
+
+ /**
+ * Queries a generic object from the VMM user.
+ *
+ * @returns Pointer to the object if found, NULL if not.
+ * @param pDevIns The device instance.
+ * @param pUuid The UUID of what's being queried. The UUIDs and
+ * the usage conventions are defined by the user.
+ *
+ * @note It is strictly forbidden to call this internally in VBox! This
+ * interface is exclusively for hacks in externally developed devices.
+ */
+ DECLR3CALLBACKMEMBER(void *, pfnQueryGenericUserObject,(PPDMDEVINS pDevIns, PCRTUUID pUuid));
+
+ /**
+ * Register a physical page access handler type.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param enmKind The kind of access handler.
+ * @param pfnHandler Pointer to the ring-3 handler callback.
+ * @param pszDesc The type description.
+ * @param phType Where to return the type handle (cross context safe).
+ * @sa PDMDevHlpPGMHandlerPhysicalTypeSetUpContext
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPGMHandlerPhysicalTypeRegister, (PPDMDEVINS pDevIns, PGMPHYSHANDLERKIND enmKind,
+ PFNPGMPHYSHANDLER pfnHandler,
+ const char *pszDesc, PPGMPHYSHANDLERTYPE phType));
+
+ /**
+ * Register a access handler for a physical range.
+ *
+ * @returns VBox status code.
+ * @retval VINF_SUCCESS when successfully installed.
+ * @retval VINF_PGM_GCPHYS_ALIASED when the shadow PTs could be updated because
+ * the guest page aliased or/and mapped by multiple PTs. A CR3 sync has been
+ * flagged together with a pool clearing.
+ * @retval VERR_PGM_HANDLER_PHYSICAL_CONFLICT if the range conflicts with an existing
+ * one. A debug assertion is raised.
+ *
+ * @param pDevIns The device instance.
+ * @param GCPhys Start physical address.
+ * @param GCPhysLast Last physical address. (inclusive)
+ * @param hType The handler type registration handle.
+ * @param pszDesc Description of this handler. If NULL, the type
+ * description will be used instead.
+ * @note There is no @a uUser argument, because it will be set to the pDevIns
+ * in the context the handler is called.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPGMHandlerPhysicalRegister, (PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTGCPHYS GCPhysLast,
+ PGMPHYSHANDLERTYPE hType, R3PTRTYPE(const char *) pszDesc));
+
+ /**
+ * Deregister a physical page access handler.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param GCPhys Start physical address.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPGMHandlerPhysicalDeregister,(PPDMDEVINS pDevIns, RTGCPHYS GCPhys));
+
+ /**
+ * Temporarily turns off the access monitoring of a page within a monitored
+ * physical write/all page access handler region.
+ *
+ * Use this when no further \#PFs are required for that page. Be aware that
+ * a page directory sync might reset the flags, and turn on access monitoring
+ * for the page.
+ *
+ * The caller must do required page table modifications.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param GCPhys The start address of the access handler. This
+ * must be a fully page aligned range or we risk
+ * messing up other handlers installed for the
+ * start and end pages.
+ * @param GCPhysPage The physical address of the page to turn off
+ * access monitoring for.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPGMHandlerPhysicalPageTempOff,(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTGCPHYS GCPhysPage));
+
+ /**
+ * Resets any modifications to individual pages in a physical page access
+ * handler region.
+ *
+ * This is used in pair with PGMHandlerPhysicalPageTempOff(),
+ * PGMHandlerPhysicalPageAliasMmio2() or PGMHandlerPhysicalPageAliasHC().
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param GCPhys The start address of the handler regions, i.e. what you
+ * passed to PGMR3HandlerPhysicalRegister(),
+ * PGMHandlerPhysicalRegisterEx() or
+ * PGMHandlerPhysicalModify().
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPGMHandlerPhysicalReset,(PPDMDEVINS pDevIns, RTGCPHYS GCPhys));
+
+ /**
+ * Registers the guest memory range that can be used for patching.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param GCPtrPatchMem Patch memory range.
+ * @param cbPatchMem Size of the memory range.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnVMMRegisterPatchMemory, (PPDMDEVINS pDevIns, RTGCPTR GCPtrPatchMem, uint32_t cbPatchMem));
+
+ /**
+ * Deregisters the guest memory range that can be used for patching.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param GCPtrPatchMem Patch memory range.
+ * @param cbPatchMem Size of the memory range.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnVMMDeregisterPatchMemory, (PPDMDEVINS pDevIns, RTGCPTR GCPtrPatchMem, uint32_t cbPatchMem));
+
+ /**
+ * Registers a new shared module for the VM
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param enmGuestOS Guest OS type.
+ * @param pszModuleName Module name.
+ * @param pszVersion Module version.
+ * @param GCBaseAddr Module base address.
+ * @param cbModule Module size.
+ * @param cRegions Number of shared region descriptors.
+ * @param paRegions Shared region(s).
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSharedModuleRegister,(PPDMDEVINS pDevIns, VBOXOSFAMILY enmGuestOS, char *pszModuleName, char *pszVersion,
+ RTGCPTR GCBaseAddr, uint32_t cbModule,
+ uint32_t cRegions, VMMDEVSHAREDREGIONDESC const *paRegions));
+
+ /**
+ * Unregisters a shared module for the VM
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param pszModuleName Module name.
+ * @param pszVersion Module version.
+ * @param GCBaseAddr Module base address.
+ * @param cbModule Module size.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSharedModuleUnregister,(PPDMDEVINS pDevIns, char *pszModuleName, char *pszVersion,
+ RTGCPTR GCBaseAddr, uint32_t cbModule));
+
+ /**
+ * Query the state of a page in a shared module
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param GCPtrPage Page address.
+ * @param pfShared Shared status (out).
+ * @param pfPageFlags Page flags (out).
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSharedModuleGetPageState, (PPDMDEVINS pDevIns, RTGCPTR GCPtrPage, bool *pfShared, uint64_t *pfPageFlags));
+
+ /**
+ * Check all registered modules for changes.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSharedModuleCheckAll,(PPDMDEVINS pDevIns));
+
+ /**
+ * Query the interface of the top level driver on a LUN.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param pszDevice Device name.
+ * @param iInstance Device instance.
+ * @param iLun The Logical Unit to obtain the interface of.
+ * @param ppBase Where to store the base interface pointer.
+ *
+ * @remark We're not doing any locking ATM, so don't try call this at times when the
+ * device chain is known to be updated.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnQueryLun,(PPDMDEVINS pDevIns, const char *pszDevice, unsigned iInstance, unsigned iLun, PPPDMIBASE ppBase));
+
+ /**
+ * Registers the GIM device with VMM.
+ *
+ * @param pDevIns Pointer to the GIM device instance.
+ * @param pDbg Pointer to the GIM device debug structure, can be
+ * NULL.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnGIMDeviceRegister,(PPDMDEVINS pDevIns, PGIMDEBUG pDbg));
+
+ /**
+ * Gets debug setup specified by the provider.
+ *
+ * @returns VBox status code.
+ * @param pDevIns Pointer to the GIM device instance.
+ * @param pDbgSetup Where to store the debug setup details.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnGIMGetDebugSetup,(PPDMDEVINS pDevIns, PGIMDEBUGSETUP pDbgSetup));
+
+ /**
+ * Returns the array of MMIO2 regions that are expected to be registered and
+ * later mapped into the guest-physical address space for the GIM provider
+ * configured for the VM.
+ *
+ * @returns Pointer to an array of GIM MMIO2 regions, may return NULL.
+ * @param pDevIns Pointer to the GIM device instance.
+ * @param pcRegions Where to store the number of items in the array.
+ *
+ * @remarks The caller does not own and therefore must -NOT- try to free the
+ * returned pointer.
+ */
+ DECLR3CALLBACKMEMBER(PGIMMMIO2REGION, pfnGIMGetMmio2Regions,(PPDMDEVINS pDevIns, uint32_t *pcRegions));
+
+ /** @} */
+
+ /** Just a safety precaution. (PDM_DEVHLPR3_VERSION) */
+ uint32_t u32TheEnd;
+} PDMDEVHLPR3;
+#endif /* !IN_RING3 || DOXYGEN_RUNNING */
+/** Pointer to the R3 PDM Device API. */
+typedef R3PTRTYPE(struct PDMDEVHLPR3 *) PPDMDEVHLPR3;
+/** Pointer to the R3 PDM Device API, const variant. */
+typedef R3PTRTYPE(const struct PDMDEVHLPR3 *) PCPDMDEVHLPR3;
+
+
+/**
+ * PDM Device API - RC Variant.
+ */
+typedef struct PDMDEVHLPRC
+{
+ /** Structure version. PDM_DEVHLPRC_VERSION defines the current version. */
+ uint32_t u32Version;
+
+ /**
+ * Sets up raw-mode context callback handlers for an I/O port range.
+ *
+ * The range must have been registered in ring-3 first using
+ * PDMDevHlpIoPortCreate() or PDMDevHlpIoPortCreateEx().
+ *
+ * @returns VBox status.
+ * @param pDevIns The device instance to register the ports with.
+ * @param hIoPorts The I/O port range handle.
+ * @param pfnOut Pointer to function which is gonna handle OUT
+ * operations. Optional.
+ * @param pfnIn Pointer to function which is gonna handle IN operations.
+ * Optional.
+ * @param pfnOutStr Pointer to function which is gonna handle string OUT
+ * operations. Optional.
+ * @param pfnInStr Pointer to function which is gonna handle string IN
+ * operations. Optional.
+ * @param pvUser User argument to pass to the callbacks.
+ *
+ * @remarks Caller enters the device critical section prior to invoking the
+ * registered callback methods.
+ *
+ * @sa PDMDevHlpIoPortCreate, PDMDevHlpIoPortCreateEx, PDMDevHlpIoPortMap,
+ * PDMDevHlpIoPortUnmap.
+ */
+ DECLRCCALLBACKMEMBER(int, pfnIoPortSetUpContextEx,(PPDMDEVINS pDevIns, IOMIOPORTHANDLE hIoPorts,
+ PFNIOMIOPORTNEWOUT pfnOut, PFNIOMIOPORTNEWIN pfnIn,
+ PFNIOMIOPORTNEWOUTSTRING pfnOutStr, PFNIOMIOPORTNEWINSTRING pfnInStr,
+ void *pvUser));
+
+ /**
+ * Sets up raw-mode context callback handlers for an MMIO region.
+ *
+ * The region must have been registered in ring-3 first using
+ * PDMDevHlpMmioCreate() or PDMDevHlpMmioCreateEx().
+ *
+ * @returns VBox status.
+ * @param pDevIns The device instance to register the ports with.
+ * @param hRegion The MMIO region handle.
+ * @param pfnWrite Pointer to function which is gonna handle Write
+ * operations.
+ * @param pfnRead Pointer to function which is gonna handle Read
+ * operations.
+ * @param pfnFill Pointer to function which is gonna handle Fill/memset
+ * operations. (optional)
+ * @param pvUser User argument to pass to the callbacks.
+ *
+ * @remarks Caller enters the device critical section prior to invoking the
+ * registered callback methods.
+ *
+ * @sa PDMDevHlpMmioCreate, PDMDevHlpMmioCreateEx, PDMDevHlpMmioMap,
+ * PDMDevHlpMmioUnmap.
+ */
+ DECLRCCALLBACKMEMBER(int, pfnMmioSetUpContextEx,(PPDMDEVINS pDevIns, IOMMMIOHANDLE hRegion, PFNIOMMMIONEWWRITE pfnWrite,
+ PFNIOMMMIONEWREAD pfnRead, PFNIOMMMIONEWFILL pfnFill, void *pvUser));
+
+ /**
+ * Sets up a raw-mode mapping for an MMIO2 region.
+ *
+ * The region must have been created in ring-3 first using
+ * PDMDevHlpMmio2Create().
+ *
+ * @returns VBox status.
+ * @param pDevIns The device instance to register the ports with.
+ * @param hRegion The MMIO2 region handle.
+ * @param offSub Start of what to map into raw-mode. Must be page aligned.
+ * @param cbSub Number of bytes to map into raw-mode. Must be page
+ * aligned. Zero is an alias for everything.
+ * @param ppvMapping Where to return the mapping corresponding to @a offSub.
+ * @thread EMT(0)
+ * @note Only available at VM creation time.
+ *
+ * @sa PDMDevHlpMmio2Create().
+ */
+ DECLRCCALLBACKMEMBER(int, pfnMmio2SetUpContext,(PPDMDEVINS pDevIns, PGMMMIO2HANDLE hRegion,
+ size_t offSub, size_t cbSub, void **ppvMapping));
+
+ /**
+ * Bus master physical memory read from the given PCI device.
+ *
+ * @returns VINF_SUCCESS or VERR_PGM_PCI_PHYS_READ_BM_DISABLED, later maybe
+ * VERR_EM_MEMORY. The informational status shall NOT be propagated!
+ * @param pDevIns The device instance.
+ * @param pPciDev The PCI device structure. If NULL the default
+ * PCI device for this device instance is used.
+ * @param GCPhys Physical address start reading from.
+ * @param pvBuf Where to put the read bits.
+ * @param cbRead How many bytes to read.
+ * @param fFlags Combination of PDM_DEVHLP_PHYS_RW_F_XXX.
+ * @thread Any thread, but the call may involve the emulation thread.
+ */
+ DECLRCCALLBACKMEMBER(int, pfnPCIPhysRead,(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, RTGCPHYS GCPhys,
+ void *pvBuf, size_t cbRead, uint32_t fFlags));
+
+ /**
+ * Bus master physical memory write from the given PCI device.
+ *
+ * @returns VINF_SUCCESS or VERR_PGM_PCI_PHYS_WRITE_BM_DISABLED, later maybe
+ * VERR_EM_MEMORY. The informational status shall NOT be propagated!
+ * @param pDevIns The device instance.
+ * @param pPciDev The PCI device structure. If NULL the default
+ * PCI device for this device instance is used.
+ * @param GCPhys Physical address to write to.
+ * @param pvBuf What to write.
+ * @param cbWrite How many bytes to write.
+ * @param fFlags Combination of PDM_DEVHLP_PHYS_RW_F_XXX.
+ * @thread Any thread, but the call may involve the emulation thread.
+ */
+ DECLRCCALLBACKMEMBER(int, pfnPCIPhysWrite,(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, RTGCPHYS GCPhys,
+ const void *pvBuf, size_t cbWrite, uint32_t fFlags));
+
+ /**
+ * Set the IRQ for the given PCI device.
+ *
+ * @param pDevIns Device instance.
+ * @param pPciDev The PCI device structure. If NULL the default
+ * PCI device for this device instance is used.
+ * @param iIrq IRQ number to set.
+ * @param iLevel IRQ level. See the PDM_IRQ_LEVEL_* \#defines.
+ * @thread Any thread, but will involve the emulation thread.
+ */
+ DECLRCCALLBACKMEMBER(void, pfnPCISetIrq,(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, int iIrq, int iLevel));
+
+ /**
+ * Set ISA IRQ for a device.
+ *
+ * @param pDevIns Device instance.
+ * @param iIrq IRQ number to set.
+ * @param iLevel IRQ level. See the PDM_IRQ_LEVEL_* \#defines.
+ * @thread Any thread, but will involve the emulation thread.
+ */
+ DECLRCCALLBACKMEMBER(void, pfnISASetIrq,(PPDMDEVINS pDevIns, int iIrq, int iLevel));
+
+ /**
+ * Read physical memory.
+ *
+ * @returns VINF_SUCCESS (for now).
+ * @param pDevIns Device instance.
+ * @param GCPhys Physical address start reading from.
+ * @param pvBuf Where to put the read bits.
+ * @param cbRead How many bytes to read.
+ * @param fFlags Combination of PDM_DEVHLP_PHYS_RW_F_XXX.
+ */
+ DECLRCCALLBACKMEMBER(int, pfnPhysRead,(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead, uint32_t fFlags));
+
+ /**
+ * Write to physical memory.
+ *
+ * @returns VINF_SUCCESS for now, and later maybe VERR_EM_MEMORY.
+ * @param pDevIns Device instance.
+ * @param GCPhys Physical address to write to.
+ * @param pvBuf What to write.
+ * @param cbWrite How many bytes to write.
+ * @param fFlags Combination of PDM_DEVHLP_PHYS_RW_F_XXX.
+ */
+ DECLRCCALLBACKMEMBER(int, pfnPhysWrite,(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite, uint32_t fFlags));
+
+ /**
+ * Checks if the Gate A20 is enabled or not.
+ *
+ * @returns true if A20 is enabled.
+ * @returns false if A20 is disabled.
+ * @param pDevIns Device instance.
+ * @thread The emulation thread.
+ */
+ DECLRCCALLBACKMEMBER(bool, pfnA20IsEnabled,(PPDMDEVINS pDevIns));
+
+ /**
+ * Gets the VM state.
+ *
+ * @returns VM state.
+ * @param pDevIns The device instance.
+ * @thread Any thread (just keep in mind that it's volatile info).
+ */
+ DECLRCCALLBACKMEMBER(VMSTATE, pfnVMState, (PPDMDEVINS pDevIns));
+
+ /**
+ * Gets the VM handle. Restricted API.
+ *
+ * @returns VM Handle.
+ * @param pDevIns Device instance.
+ */
+ DECLRCCALLBACKMEMBER(PVMCC, pfnGetVM,(PPDMDEVINS pDevIns));
+
+ /**
+ * Gets the VMCPU handle. Restricted API.
+ *
+ * @returns VMCPU Handle.
+ * @param pDevIns The device instance.
+ */
+ DECLRCCALLBACKMEMBER(PVMCPUCC, pfnGetVMCPU,(PPDMDEVINS pDevIns));
+
+ /**
+ * The the VM CPU ID of the current thread (restricted API).
+ *
+ * @returns The VMCPUID of the calling thread, NIL_VMCPUID if not EMT.
+ * @param pDevIns The device instance.
+ */
+ DECLRCCALLBACKMEMBER(VMCPUID, pfnGetCurrentCpuId,(PPDMDEVINS pDevIns));
+
+ /**
+ * Gets the main execution engine for the VM.
+ *
+ * @returns VM_EXEC_ENGINE_XXX
+ * @param pDevIns The device instance.
+ */
+ DECLRCCALLBACKMEMBER(uint8_t, pfnGetMainExecutionEngine,(PPDMDEVINS pDevIns));
+
+ /**
+ * Get the current virtual clock time in a VM. The clock frequency must be
+ * queried separately.
+ *
+ * @returns Current clock time.
+ * @param pDevIns The device instance.
+ */
+ DECLRCCALLBACKMEMBER(uint64_t, pfnTMTimeVirtGet,(PPDMDEVINS pDevIns));
+
+ /**
+ * Get the frequency of the virtual clock.
+ *
+ * @returns The clock frequency (not variable at run-time).
+ * @param pDevIns The device instance.
+ */
+ DECLRCCALLBACKMEMBER(uint64_t, pfnTMTimeVirtGetFreq,(PPDMDEVINS pDevIns));
+
+ /**
+ * Get the current virtual clock time in a VM, in nanoseconds.
+ *
+ * @returns Current clock time (in ns).
+ * @param pDevIns The device instance.
+ */
+ DECLRCCALLBACKMEMBER(uint64_t, pfnTMTimeVirtGetNano,(PPDMDEVINS pDevIns));
+
+ /**
+ * Gets the NOP critical section.
+ *
+ * @returns The ring-3 address of the NOP critical section.
+ * @param pDevIns The device instance.
+ */
+ DECLRCCALLBACKMEMBER(PPDMCRITSECT, pfnCritSectGetNop,(PPDMDEVINS pDevIns));
+
+ /**
+ * Changes the device level critical section from the automatically created
+ * default to one desired by the device constructor.
+ *
+ * Must first be done in ring-3.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param pCritSect The critical section to use. NULL is not
+ * valid, instead use the NOP critical
+ * section.
+ */
+ DECLRCCALLBACKMEMBER(int, pfnSetDeviceCritSect,(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect));
+
+ /** @name Exported PDM Critical Section Functions
+ * @{ */
+ DECLRCCALLBACKMEMBER(int, pfnCritSectEnter,(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, int rcBusy));
+ DECLRCCALLBACKMEMBER(int, pfnCritSectEnterDebug,(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, int rcBusy, RTHCUINTPTR uId, RT_SRC_POS_DECL));
+ DECLRCCALLBACKMEMBER(int, pfnCritSectTryEnter,(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect));
+ DECLRCCALLBACKMEMBER(int, pfnCritSectTryEnterDebug,(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, RTHCUINTPTR uId, RT_SRC_POS_DECL));
+ DECLRCCALLBACKMEMBER(int, pfnCritSectLeave,(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect));
+ DECLRCCALLBACKMEMBER(bool, pfnCritSectIsOwner,(PPDMDEVINS pDevIns, PCPDMCRITSECT pCritSect));
+ DECLRCCALLBACKMEMBER(bool, pfnCritSectIsInitialized,(PPDMDEVINS pDevIns, PCPDMCRITSECT pCritSect));
+ DECLRCCALLBACKMEMBER(bool, pfnCritSectHasWaiters,(PPDMDEVINS pDevIns, PCPDMCRITSECT pCritSect));
+ DECLRCCALLBACKMEMBER(uint32_t, pfnCritSectGetRecursion,(PPDMDEVINS pDevIns, PCPDMCRITSECT pCritSect));
+ /** @} */
+
+ /** @name Exported PDM Read/Write Critical Section Functions
+ * @{ */
+ DECLRCCALLBACKMEMBER(int, pfnCritSectRwEnterShared,(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect, int rcBusy));
+ DECLRCCALLBACKMEMBER(int, pfnCritSectRwEnterSharedDebug,(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect, int rcBusy, RTHCUINTPTR uId, RT_SRC_POS_DECL));
+ DECLRCCALLBACKMEMBER(int, pfnCritSectRwTryEnterShared,(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect));
+ DECLRCCALLBACKMEMBER(int, pfnCritSectRwTryEnterSharedDebug,(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect, RTHCUINTPTR uId, RT_SRC_POS_DECL));
+ DECLRCCALLBACKMEMBER(int, pfnCritSectRwLeaveShared,(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect));
+
+ DECLRCCALLBACKMEMBER(int, pfnCritSectRwEnterExcl,(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect, int rcBusy));
+ DECLRCCALLBACKMEMBER(int, pfnCritSectRwEnterExclDebug,(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect, int rcBusy, RTHCUINTPTR uId, RT_SRC_POS_DECL));
+ DECLRCCALLBACKMEMBER(int, pfnCritSectRwTryEnterExcl,(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect));
+ DECLRCCALLBACKMEMBER(int, pfnCritSectRwTryEnterExclDebug,(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect, RTHCUINTPTR uId, RT_SRC_POS_DECL));
+ DECLRCCALLBACKMEMBER(int, pfnCritSectRwLeaveExcl,(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect));
+
+ DECLRCCALLBACKMEMBER(bool, pfnCritSectRwIsWriteOwner,(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect));
+ DECLRCCALLBACKMEMBER(bool, pfnCritSectRwIsReadOwner,(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect, bool fWannaHear));
+ DECLRCCALLBACKMEMBER(uint32_t, pfnCritSectRwGetWriteRecursion,(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect));
+ DECLRCCALLBACKMEMBER(uint32_t, pfnCritSectRwGetWriterReadRecursion,(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect));
+ DECLRCCALLBACKMEMBER(uint32_t, pfnCritSectRwGetReadCount,(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect));
+ DECLRCCALLBACKMEMBER(bool, pfnCritSectRwIsInitialized,(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect));
+ /** @} */
+
+ /**
+ * Gets the trace buffer handle.
+ *
+ * This is used by the macros found in VBox/vmm/dbgftrace.h and is not
+ * really inteded for direct usage, thus no inline wrapper function.
+ *
+ * @returns Trace buffer handle or NIL_RTTRACEBUF.
+ * @param pDevIns The device instance.
+ */
+ DECLRCCALLBACKMEMBER(RTTRACEBUF, pfnDBGFTraceBuf,(PPDMDEVINS pDevIns));
+
+ /**
+ * Sets up the PCI bus for the raw-mode context.
+ *
+ * This must be called after ring-3 has registered the PCI bus using
+ * PDMDevHlpPCIBusRegister().
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param pPciBusReg The PCI bus registration information for raw-mode,
+ * considered volatile.
+ * @param ppPciHlp Where to return the raw-mode PCI bus helpers.
+ */
+ DECLRCCALLBACKMEMBER(int, pfnPCIBusSetUpContext,(PPDMDEVINS pDevIns, PPDMPCIBUSREGRC pPciBusReg, PCPDMPCIHLPRC *ppPciHlp));
+
+ /**
+ * Sets up the IOMMU for the raw-mode context.
+ *
+ * This must be called after ring-3 has registered the IOMMU using
+ * PDMDevHlpIommuRegister().
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param pIommuReg The IOMMU registration information for raw-mode,
+ * considered volatile.
+ * @param ppIommuHlp Where to return the raw-mode IOMMU helpers.
+ */
+ DECLRCCALLBACKMEMBER(int, pfnIommuSetUpContext,(PPDMDEVINS pDevIns, PPDMIOMMUREGRC pIommuReg, PCPDMIOMMUHLPRC *ppIommuHlp));
+
+ /**
+ * Sets up the PIC for the ring-0 context.
+ *
+ * This must be called after ring-3 has registered the PIC using
+ * PDMDevHlpPICRegister().
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param pPicReg The PIC registration information for ring-0,
+ * considered volatile and copied.
+ * @param ppPicHlp Where to return the ring-0 PIC helpers.
+ */
+ DECLRCCALLBACKMEMBER(int, pfnPICSetUpContext,(PPDMDEVINS pDevIns, PPDMPICREG pPicReg, PCPDMPICHLP *ppPicHlp));
+
+ /**
+ * Sets up the APIC for the raw-mode context.
+ *
+ * This must be called after ring-3 has registered the APIC using
+ * PDMDevHlpApicRegister().
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ */
+ DECLRCCALLBACKMEMBER(int, pfnApicSetUpContext,(PPDMDEVINS pDevIns));
+
+ /**
+ * Sets up the IOAPIC for the ring-0 context.
+ *
+ * This must be called after ring-3 has registered the PIC using
+ * PDMDevHlpIoApicRegister().
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param pIoApicReg The PIC registration information for ring-0,
+ * considered volatile and copied.
+ * @param ppIoApicHlp Where to return the ring-0 IOAPIC helpers.
+ */
+ DECLRCCALLBACKMEMBER(int, pfnIoApicSetUpContext,(PPDMDEVINS pDevIns, PPDMIOAPICREG pIoApicReg, PCPDMIOAPICHLP *ppIoApicHlp));
+
+ /**
+ * Sets up the HPET for the raw-mode context.
+ *
+ * This must be called after ring-3 has registered the PIC using
+ * PDMDevHlpHpetRegister().
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param pHpetReg The PIC registration information for raw-mode,
+ * considered volatile and copied.
+ * @param ppHpetHlp Where to return the raw-mode HPET helpers.
+ */
+ DECLRCCALLBACKMEMBER(int, pfnHpetSetUpContext,(PPDMDEVINS pDevIns, PPDMHPETREG pHpetReg, PCPDMHPETHLPRC *ppHpetHlp));
+
+ /** Space reserved for future members.
+ * @{ */
+ DECLRCCALLBACKMEMBER(void, pfnReserved1,(void));
+ DECLRCCALLBACKMEMBER(void, pfnReserved2,(void));
+ DECLRCCALLBACKMEMBER(void, pfnReserved3,(void));
+ DECLRCCALLBACKMEMBER(void, pfnReserved4,(void));
+ DECLRCCALLBACKMEMBER(void, pfnReserved5,(void));
+ DECLRCCALLBACKMEMBER(void, pfnReserved6,(void));
+ DECLRCCALLBACKMEMBER(void, pfnReserved7,(void));
+ DECLRCCALLBACKMEMBER(void, pfnReserved8,(void));
+ DECLRCCALLBACKMEMBER(void, pfnReserved9,(void));
+ DECLRCCALLBACKMEMBER(void, pfnReserved10,(void));
+ /** @} */
+
+ /** Just a safety precaution. */
+ uint32_t u32TheEnd;
+} PDMDEVHLPRC;
+/** Pointer PDM Device RC API. */
+typedef RGPTRTYPE(struct PDMDEVHLPRC *) PPDMDEVHLPRC;
+/** Pointer PDM Device RC API. */
+typedef RGPTRTYPE(const struct PDMDEVHLPRC *) PCPDMDEVHLPRC;
+
+/** Current PDMDEVHLP version number. */
+#define PDM_DEVHLPRC_VERSION PDM_VERSION_MAKE(0xffe6, 19, 0)
+
+
+/**
+ * PDM Device API - R0 Variant.
+ */
+typedef struct PDMDEVHLPR0
+{
+ /** Structure version. PDM_DEVHLPR0_VERSION defines the current version. */
+ uint32_t u32Version;
+
+ /**
+ * Sets up ring-0 callback handlers for an I/O port range.
+ *
+ * The range must have been created in ring-3 first using
+ * PDMDevHlpIoPortCreate() or PDMDevHlpIoPortCreateEx().
+ *
+ * @returns VBox status.
+ * @param pDevIns The device instance to register the ports with.
+ * @param hIoPorts The I/O port range handle.
+ * @param pfnOut Pointer to function which is gonna handle OUT
+ * operations. Optional.
+ * @param pfnIn Pointer to function which is gonna handle IN operations.
+ * Optional.
+ * @param pfnOutStr Pointer to function which is gonna handle string OUT
+ * operations. Optional.
+ * @param pfnInStr Pointer to function which is gonna handle string IN
+ * operations. Optional.
+ * @param pvUser User argument to pass to the callbacks.
+ *
+ * @remarks Caller enters the device critical section prior to invoking the
+ * registered callback methods.
+ *
+ * @sa PDMDevHlpIoPortCreate(), PDMDevHlpIoPortCreateEx(),
+ * PDMDevHlpIoPortMap(), PDMDevHlpIoPortUnmap().
+ */
+ DECLR0CALLBACKMEMBER(int, pfnIoPortSetUpContextEx,(PPDMDEVINS pDevIns, IOMIOPORTHANDLE hIoPorts,
+ PFNIOMIOPORTNEWOUT pfnOut, PFNIOMIOPORTNEWIN pfnIn,
+ PFNIOMIOPORTNEWOUTSTRING pfnOutStr, PFNIOMIOPORTNEWINSTRING pfnInStr,
+ void *pvUser));
+
+ /**
+ * Sets up ring-0 callback handlers for an MMIO region.
+ *
+ * The region must have been created in ring-3 first using
+ * PDMDevHlpMmioCreate(), PDMDevHlpMmioCreateEx(), PDMDevHlpMmioCreateAndMap(),
+ * PDMDevHlpMmioCreateExAndMap() or PDMDevHlpPCIIORegionCreateMmio().
+ *
+ * @returns VBox status.
+ * @param pDevIns The device instance to register the ports with.
+ * @param hRegion The MMIO region handle.
+ * @param pfnWrite Pointer to function which is gonna handle Write
+ * operations.
+ * @param pfnRead Pointer to function which is gonna handle Read
+ * operations.
+ * @param pfnFill Pointer to function which is gonna handle Fill/memset
+ * operations. (optional)
+ * @param pvUser User argument to pass to the callbacks.
+ *
+ * @remarks Caller enters the device critical section prior to invoking the
+ * registered callback methods.
+ *
+ * @sa PDMDevHlpMmioCreate(), PDMDevHlpMmioCreateEx(), PDMDevHlpMmioMap(),
+ * PDMDevHlpMmioUnmap().
+ */
+ DECLR0CALLBACKMEMBER(int, pfnMmioSetUpContextEx,(PPDMDEVINS pDevIns, IOMMMIOHANDLE hRegion, PFNIOMMMIONEWWRITE pfnWrite,
+ PFNIOMMMIONEWREAD pfnRead, PFNIOMMMIONEWFILL pfnFill, void *pvUser));
+
+ /**
+ * Sets up a ring-0 mapping for an MMIO2 region.
+ *
+ * The region must have been created in ring-3 first using
+ * PDMDevHlpMmio2Create().
+ *
+ * @returns VBox status.
+ * @param pDevIns The device instance to register the ports with.
+ * @param hRegion The MMIO2 region handle.
+ * @param offSub Start of what to map into ring-0. Must be page aligned.
+ * @param cbSub Number of bytes to map into ring-0. Must be page
+ * aligned. Zero is an alias for everything.
+ * @param ppvMapping Where to return the mapping corresponding to @a offSub.
+ *
+ * @thread EMT(0)
+ * @note Only available at VM creation time.
+ *
+ * @sa PDMDevHlpMmio2Create().
+ */
+ DECLR0CALLBACKMEMBER(int, pfnMmio2SetUpContext,(PPDMDEVINS pDevIns, PGMMMIO2HANDLE hRegion, size_t offSub, size_t cbSub,
+ void **ppvMapping));
+
+ /**
+ * Bus master physical memory read from the given PCI device.
+ *
+ * @returns VINF_SUCCESS or VERR_PDM_NOT_PCI_BUS_MASTER, later maybe
+ * VERR_EM_MEMORY.
+ * @param pDevIns The device instance.
+ * @param pPciDev The PCI device structure. If NULL the default
+ * PCI device for this device instance is used.
+ * @param GCPhys Physical address start reading from.
+ * @param pvBuf Where to put the read bits.
+ * @param cbRead How many bytes to read.
+ * @param fFlags Combination of PDM_DEVHLP_PHYS_RW_F_XXX.
+ * @thread Any thread, but the call may involve the emulation thread.
+ */
+ DECLR0CALLBACKMEMBER(int, pfnPCIPhysRead,(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, RTGCPHYS GCPhys,
+ void *pvBuf, size_t cbRead, uint32_t fFlags));
+
+ /**
+ * Bus master physical memory write from the given PCI device.
+ *
+ * @returns VINF_SUCCESS or VERR_PDM_NOT_PCI_BUS_MASTER, later maybe
+ * VERR_EM_MEMORY.
+ * @param pDevIns The device instance.
+ * @param pPciDev The PCI device structure. If NULL the default
+ * PCI device for this device instance is used.
+ * @param GCPhys Physical address to write to.
+ * @param pvBuf What to write.
+ * @param cbWrite How many bytes to write.
+ * @param fFlags Combination of PDM_DEVHLP_PHYS_RW_F_XXX.
+ * @thread Any thread, but the call may involve the emulation thread.
+ */
+ DECLR0CALLBACKMEMBER(int, pfnPCIPhysWrite,(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, RTGCPHYS GCPhys,
+ const void *pvBuf, size_t cbWrite, uint32_t fFlags));
+
+ /**
+ * Set the IRQ for the given PCI device.
+ *
+ * @param pDevIns Device instance.
+ * @param pPciDev The PCI device structure. If NULL the default
+ * PCI device for this device instance is used.
+ * @param iIrq IRQ number to set.
+ * @param iLevel IRQ level. See the PDM_IRQ_LEVEL_* \#defines.
+ * @thread Any thread, but will involve the emulation thread.
+ */
+ DECLR0CALLBACKMEMBER(void, pfnPCISetIrq,(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, int iIrq, int iLevel));
+
+ /**
+ * Set ISA IRQ for a device.
+ *
+ * @param pDevIns Device instance.
+ * @param iIrq IRQ number to set.
+ * @param iLevel IRQ level. See the PDM_IRQ_LEVEL_* \#defines.
+ * @thread Any thread, but will involve the emulation thread.
+ */
+ DECLR0CALLBACKMEMBER(void, pfnISASetIrq,(PPDMDEVINS pDevIns, int iIrq, int iLevel));
+
+ /**
+ * Read physical memory.
+ *
+ * @returns VINF_SUCCESS (for now).
+ * @param pDevIns Device instance.
+ * @param GCPhys Physical address start reading from.
+ * @param pvBuf Where to put the read bits.
+ * @param cbRead How many bytes to read.
+ * @param fFlags Combination of PDM_DEVHLP_PHYS_RW_F_XXX.
+ */
+ DECLR0CALLBACKMEMBER(int, pfnPhysRead,(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead, uint32_t fFlags));
+
+ /**
+ * Write to physical memory.
+ *
+ * @returns VINF_SUCCESS for now, and later maybe VERR_EM_MEMORY.
+ * @param pDevIns Device instance.
+ * @param GCPhys Physical address to write to.
+ * @param pvBuf What to write.
+ * @param cbWrite How many bytes to write.
+ * @param fFlags Combination of PDM_DEVHLP_PHYS_RW_F_XXX.
+ */
+ DECLR0CALLBACKMEMBER(int, pfnPhysWrite,(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite, uint32_t fFlags));
+
+ /**
+ * Checks if the Gate A20 is enabled or not.
+ *
+ * @returns true if A20 is enabled.
+ * @returns false if A20 is disabled.
+ * @param pDevIns Device instance.
+ * @thread The emulation thread.
+ */
+ DECLR0CALLBACKMEMBER(bool, pfnA20IsEnabled,(PPDMDEVINS pDevIns));
+
+ /**
+ * Gets the VM state.
+ *
+ * @returns VM state.
+ * @param pDevIns The device instance.
+ * @thread Any thread (just keep in mind that it's volatile info).
+ */
+ DECLR0CALLBACKMEMBER(VMSTATE, pfnVMState, (PPDMDEVINS pDevIns));
+
+ /**
+ * Gets the VM handle. Restricted API.
+ *
+ * @returns VM Handle.
+ * @param pDevIns Device instance.
+ */
+ DECLR0CALLBACKMEMBER(PVMCC, pfnGetVM,(PPDMDEVINS pDevIns));
+
+ /**
+ * Gets the VMCPU handle. Restricted API.
+ *
+ * @returns VMCPU Handle.
+ * @param pDevIns The device instance.
+ */
+ DECLR0CALLBACKMEMBER(PVMCPUCC, pfnGetVMCPU,(PPDMDEVINS pDevIns));
+
+ /**
+ * The the VM CPU ID of the current thread (restricted API).
+ *
+ * @returns The VMCPUID of the calling thread, NIL_VMCPUID if not EMT.
+ * @param pDevIns The device instance.
+ */
+ DECLR0CALLBACKMEMBER(VMCPUID, pfnGetCurrentCpuId,(PPDMDEVINS pDevIns));
+
+ /**
+ * Gets the main execution engine for the VM.
+ *
+ * @returns VM_EXEC_ENGINE_XXX
+ * @param pDevIns The device instance.
+ */
+ DECLR0CALLBACKMEMBER(uint8_t, pfnGetMainExecutionEngine,(PPDMDEVINS pDevIns));
+
+ /** @name Timer handle method wrappers
+ * @{ */
+ DECLR0CALLBACKMEMBER(uint64_t, pfnTimerFromMicro,(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint64_t cMicroSecs));
+ DECLR0CALLBACKMEMBER(uint64_t, pfnTimerFromMilli,(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint64_t cMilliSecs));
+ DECLR0CALLBACKMEMBER(uint64_t, pfnTimerFromNano,(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint64_t cNanoSecs));
+ DECLR0CALLBACKMEMBER(uint64_t, pfnTimerGet,(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer));
+ DECLR0CALLBACKMEMBER(uint64_t, pfnTimerGetFreq,(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer));
+ DECLR0CALLBACKMEMBER(uint64_t, pfnTimerGetNano,(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer));
+ DECLR0CALLBACKMEMBER(bool, pfnTimerIsActive,(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer));
+ DECLR0CALLBACKMEMBER(bool, pfnTimerIsLockOwner,(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer));
+ DECLR0CALLBACKMEMBER(VBOXSTRICTRC, pfnTimerLockClock,(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, int rcBusy));
+ /** Takes the clock lock then enters the specified critical section. */
+ DECLR0CALLBACKMEMBER(VBOXSTRICTRC, pfnTimerLockClock2,(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, PPDMCRITSECT pCritSect, int rcBusy));
+ DECLR0CALLBACKMEMBER(int, pfnTimerSet,(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint64_t uExpire));
+ DECLR0CALLBACKMEMBER(int, pfnTimerSetFrequencyHint,(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint32_t uHz));
+ DECLR0CALLBACKMEMBER(int, pfnTimerSetMicro,(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint64_t cMicrosToNext));
+ DECLR0CALLBACKMEMBER(int, pfnTimerSetMillies,(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint64_t cMilliesToNext));
+ DECLR0CALLBACKMEMBER(int, pfnTimerSetNano,(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint64_t cNanosToNext));
+ DECLR0CALLBACKMEMBER(int, pfnTimerSetRelative,(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint64_t cTicksToNext, uint64_t *pu64Now));
+ DECLR0CALLBACKMEMBER(int, pfnTimerStop,(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer));
+ DECLR0CALLBACKMEMBER(void, pfnTimerUnlockClock,(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer));
+ DECLR0CALLBACKMEMBER(void, pfnTimerUnlockClock2,(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, PPDMCRITSECT pCritSect));
+ /** @} */
+
+ /**
+ * Get the current virtual clock time in a VM. The clock frequency must be
+ * queried separately.
+ *
+ * @returns Current clock time.
+ * @param pDevIns The device instance.
+ */
+ DECLR0CALLBACKMEMBER(uint64_t, pfnTMTimeVirtGet,(PPDMDEVINS pDevIns));
+
+ /**
+ * Get the frequency of the virtual clock.
+ *
+ * @returns The clock frequency (not variable at run-time).
+ * @param pDevIns The device instance.
+ */
+ DECLR0CALLBACKMEMBER(uint64_t, pfnTMTimeVirtGetFreq,(PPDMDEVINS pDevIns));
+
+ /**
+ * Get the current virtual clock time in a VM, in nanoseconds.
+ *
+ * @returns Current clock time (in ns).
+ * @param pDevIns The device instance.
+ */
+ DECLR0CALLBACKMEMBER(uint64_t, pfnTMTimeVirtGetNano,(PPDMDEVINS pDevIns));
+
+ /** @name Exported PDM Queue Functions
+ * @{ */
+ DECLR0CALLBACKMEMBER(PPDMQUEUEITEMCORE, pfnQueueAlloc,(PPDMDEVINS pDevIns, PDMQUEUEHANDLE hQueue));
+ DECLR0CALLBACKMEMBER(int, pfnQueueInsert,(PPDMDEVINS pDevIns, PDMQUEUEHANDLE hQueue, PPDMQUEUEITEMCORE pItem));
+ DECLR0CALLBACKMEMBER(bool, pfnQueueFlushIfNecessary,(PPDMDEVINS pDevIns, PDMQUEUEHANDLE hQueue));
+ /** @} */
+
+ /** @name PDM Task
+ * @{ */
+ /**
+ * Triggers the running the given task.
+ *
+ * @returns VBox status code.
+ * @retval VINF_ALREADY_POSTED is the task is already pending.
+ * @param pDevIns The device instance.
+ * @param hTask The task to trigger.
+ * @thread Any thread.
+ */
+ DECLR0CALLBACKMEMBER(int, pfnTaskTrigger,(PPDMDEVINS pDevIns, PDMTASKHANDLE hTask));
+ /** @} */
+
+ /** @name SUP Event Semaphore Wrappers (single release / auto reset)
+ * These semaphores can be signalled from ring-0.
+ * @{ */
+ /** @sa SUPSemEventSignal */
+ DECLR0CALLBACKMEMBER(int, pfnSUPSemEventSignal,(PPDMDEVINS pDevIns, SUPSEMEVENT hEvent));
+ /** @sa SUPSemEventWaitNoResume */
+ DECLR0CALLBACKMEMBER(int, pfnSUPSemEventWaitNoResume,(PPDMDEVINS pDevIns, SUPSEMEVENT hEvent, uint32_t cMillies));
+ /** @sa SUPSemEventWaitNsAbsIntr */
+ DECLR0CALLBACKMEMBER(int, pfnSUPSemEventWaitNsAbsIntr,(PPDMDEVINS pDevIns, SUPSEMEVENT hEvent, uint64_t uNsTimeout));
+ /** @sa SUPSemEventWaitNsRelIntr */
+ DECLR0CALLBACKMEMBER(int, pfnSUPSemEventWaitNsRelIntr,(PPDMDEVINS pDevIns, SUPSEMEVENT hEvent, uint64_t cNsTimeout));
+ /** @sa SUPSemEventGetResolution */
+ DECLR0CALLBACKMEMBER(uint32_t, pfnSUPSemEventGetResolution,(PPDMDEVINS pDevIns));
+ /** @} */
+
+ /** @name SUP Multi Event Semaphore Wrappers (multiple release / manual reset)
+ * These semaphores can be signalled from ring-0.
+ * @{ */
+ /** @sa SUPSemEventMultiSignal */
+ DECLR0CALLBACKMEMBER(int, pfnSUPSemEventMultiSignal,(PPDMDEVINS pDevIns, SUPSEMEVENTMULTI hEventMulti));
+ /** @sa SUPSemEventMultiReset */
+ DECLR0CALLBACKMEMBER(int, pfnSUPSemEventMultiReset,(PPDMDEVINS pDevIns, SUPSEMEVENTMULTI hEventMulti));
+ /** @sa SUPSemEventMultiWaitNoResume */
+ DECLR0CALLBACKMEMBER(int, pfnSUPSemEventMultiWaitNoResume,(PPDMDEVINS pDevIns, SUPSEMEVENTMULTI hEventMulti, uint32_t cMillies));
+ /** @sa SUPSemEventMultiWaitNsAbsIntr */
+ DECLR0CALLBACKMEMBER(int, pfnSUPSemEventMultiWaitNsAbsIntr,(PPDMDEVINS pDevIns, SUPSEMEVENTMULTI hEventMulti, uint64_t uNsTimeout));
+ /** @sa SUPSemEventMultiWaitNsRelIntr */
+ DECLR0CALLBACKMEMBER(int, pfnSUPSemEventMultiWaitNsRelIntr,(PPDMDEVINS pDevIns, SUPSEMEVENTMULTI hEventMulti, uint64_t cNsTimeout));
+ /** @sa SUPSemEventMultiGetResolution */
+ DECLR0CALLBACKMEMBER(uint32_t, pfnSUPSemEventMultiGetResolution,(PPDMDEVINS pDevIns));
+ /** @} */
+
+ /**
+ * Gets the NOP critical section.
+ *
+ * @returns The ring-3 address of the NOP critical section.
+ * @param pDevIns The device instance.
+ */
+ DECLR0CALLBACKMEMBER(PPDMCRITSECT, pfnCritSectGetNop,(PPDMDEVINS pDevIns));
+
+ /**
+ * Changes the device level critical section from the automatically created
+ * default to one desired by the device constructor.
+ *
+ * Must first be done in ring-3.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param pCritSect The critical section to use. NULL is not
+ * valid, instead use the NOP critical
+ * section.
+ */
+ DECLR0CALLBACKMEMBER(int, pfnSetDeviceCritSect,(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect));
+
+ /** @name Exported PDM Critical Section Functions
+ * @{ */
+ DECLR0CALLBACKMEMBER(int, pfnCritSectEnter,(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, int rcBusy));
+ DECLR0CALLBACKMEMBER(int, pfnCritSectEnterDebug,(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, int rcBusy, RTHCUINTPTR uId, RT_SRC_POS_DECL));
+ DECLR0CALLBACKMEMBER(int, pfnCritSectTryEnter,(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect));
+ DECLR0CALLBACKMEMBER(int, pfnCritSectTryEnterDebug,(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, RTHCUINTPTR uId, RT_SRC_POS_DECL));
+ DECLR0CALLBACKMEMBER(int, pfnCritSectLeave,(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect));
+ DECLR0CALLBACKMEMBER(bool, pfnCritSectIsOwner,(PPDMDEVINS pDevIns, PCPDMCRITSECT pCritSect));
+ DECLR0CALLBACKMEMBER(bool, pfnCritSectIsInitialized,(PPDMDEVINS pDevIns, PCPDMCRITSECT pCritSect));
+ DECLR0CALLBACKMEMBER(bool, pfnCritSectHasWaiters,(PPDMDEVINS pDevIns, PCPDMCRITSECT pCritSect));
+ DECLR0CALLBACKMEMBER(uint32_t, pfnCritSectGetRecursion,(PPDMDEVINS pDevIns, PCPDMCRITSECT pCritSect));
+ DECLR0CALLBACKMEMBER(int, pfnCritSectScheduleExitEvent,(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, SUPSEMEVENT hEventToSignal));
+ /** @} */
+
+ /** @name Exported PDM Read/Write Critical Section Functions
+ * @{ */
+ DECLR0CALLBACKMEMBER(int, pfnCritSectRwEnterShared,(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect, int rcBusy));
+ DECLR0CALLBACKMEMBER(int, pfnCritSectRwEnterSharedDebug,(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect, int rcBusy, RTHCUINTPTR uId, RT_SRC_POS_DECL));
+ DECLR0CALLBACKMEMBER(int, pfnCritSectRwTryEnterShared,(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect));
+ DECLR0CALLBACKMEMBER(int, pfnCritSectRwTryEnterSharedDebug,(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect, RTHCUINTPTR uId, RT_SRC_POS_DECL));
+ DECLR0CALLBACKMEMBER(int, pfnCritSectRwLeaveShared,(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect));
+
+ DECLR0CALLBACKMEMBER(int, pfnCritSectRwEnterExcl,(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect, int rcBusy));
+ DECLR0CALLBACKMEMBER(int, pfnCritSectRwEnterExclDebug,(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect, int rcBusy, RTHCUINTPTR uId, RT_SRC_POS_DECL));
+ DECLR0CALLBACKMEMBER(int, pfnCritSectRwTryEnterExcl,(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect));
+ DECLR0CALLBACKMEMBER(int, pfnCritSectRwTryEnterExclDebug,(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect, RTHCUINTPTR uId, RT_SRC_POS_DECL));
+ DECLR0CALLBACKMEMBER(int, pfnCritSectRwLeaveExcl,(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect));
+
+ DECLR0CALLBACKMEMBER(bool, pfnCritSectRwIsWriteOwner,(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect));
+ DECLR0CALLBACKMEMBER(bool, pfnCritSectRwIsReadOwner,(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect, bool fWannaHear));
+ DECLR0CALLBACKMEMBER(uint32_t, pfnCritSectRwGetWriteRecursion,(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect));
+ DECLR0CALLBACKMEMBER(uint32_t, pfnCritSectRwGetWriterReadRecursion,(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect));
+ DECLR0CALLBACKMEMBER(uint32_t, pfnCritSectRwGetReadCount,(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect));
+ DECLR0CALLBACKMEMBER(bool, pfnCritSectRwIsInitialized,(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect));
+ /** @} */
+
+ /**
+ * Gets the trace buffer handle.
+ *
+ * This is used by the macros found in VBox/vmm/dbgftrace.h and is not
+ * really inteded for direct usage, thus no inline wrapper function.
+ *
+ * @returns Trace buffer handle or NIL_RTTRACEBUF.
+ * @param pDevIns The device instance.
+ */
+ DECLR0CALLBACKMEMBER(RTTRACEBUF, pfnDBGFTraceBuf,(PPDMDEVINS pDevIns));
+
+ /**
+ * Sets up the PCI bus for the ring-0 context.
+ *
+ * This must be called after ring-3 has registered the PCI bus using
+ * PDMDevHlpPCIBusRegister().
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param pPciBusReg The PCI bus registration information for ring-0,
+ * considered volatile and copied.
+ * @param ppPciHlp Where to return the ring-0 PCI bus helpers.
+ */
+ DECLR0CALLBACKMEMBER(int, pfnPCIBusSetUpContext,(PPDMDEVINS pDevIns, PPDMPCIBUSREGR0 pPciBusReg, PCPDMPCIHLPR0 *ppPciHlp));
+
+ /**
+ * Sets up the IOMMU for the ring-0 context.
+ *
+ * This must be called after ring-3 has registered the IOMMU using
+ * PDMDevHlpIommuRegister().
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param pIommuReg The IOMMU registration information for ring-0,
+ * considered volatile and copied.
+ * @param ppIommuHlp Where to return the ring-0 IOMMU helpers.
+ */
+ DECLR0CALLBACKMEMBER(int, pfnIommuSetUpContext,(PPDMDEVINS pDevIns, PPDMIOMMUREGR0 pIommuReg, PCPDMIOMMUHLPR0 *ppIommuHlp));
+
+ /**
+ * Sets up the PIC for the ring-0 context.
+ *
+ * This must be called after ring-3 has registered the PIC using
+ * PDMDevHlpPICRegister().
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param pPicReg The PIC registration information for ring-0,
+ * considered volatile and copied.
+ * @param ppPicHlp Where to return the ring-0 PIC helpers.
+ */
+ DECLR0CALLBACKMEMBER(int, pfnPICSetUpContext,(PPDMDEVINS pDevIns, PPDMPICREG pPicReg, PCPDMPICHLP *ppPicHlp));
+
+ /**
+ * Sets up the APIC for the ring-0 context.
+ *
+ * This must be called after ring-3 has registered the APIC using
+ * PDMDevHlpApicRegister().
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ */
+ DECLR0CALLBACKMEMBER(int, pfnApicSetUpContext,(PPDMDEVINS pDevIns));
+
+ /**
+ * Sets up the IOAPIC for the ring-0 context.
+ *
+ * This must be called after ring-3 has registered the PIC using
+ * PDMDevHlpIoApicRegister().
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param pIoApicReg The PIC registration information for ring-0,
+ * considered volatile and copied.
+ * @param ppIoApicHlp Where to return the ring-0 IOAPIC helpers.
+ */
+ DECLR0CALLBACKMEMBER(int, pfnIoApicSetUpContext,(PPDMDEVINS pDevIns, PPDMIOAPICREG pIoApicReg, PCPDMIOAPICHLP *ppIoApicHlp));
+
+ /**
+ * Sets up the HPET for the ring-0 context.
+ *
+ * This must be called after ring-3 has registered the PIC using
+ * PDMDevHlpHpetRegister().
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param pHpetReg The PIC registration information for ring-0,
+ * considered volatile and copied.
+ * @param ppHpetHlp Where to return the ring-0 HPET helpers.
+ */
+ DECLR0CALLBACKMEMBER(int, pfnHpetSetUpContext,(PPDMDEVINS pDevIns, PPDMHPETREG pHpetReg, PCPDMHPETHLPR0 *ppHpetHlp));
+
+ /**
+ * Sets up a physical page access handler type for ring-0 callbacks.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param enmKind The kind of access handler.
+ * @param pfnHandler Pointer to the ring-0 handler callback. NULL if
+ * the ring-3 handler should be called.
+ * @param pfnPfHandler The name of the ring-0 \#PF handler, NULL if the
+ * ring-3 handler should be called.
+ * @param pszDesc The type description.
+ * @param hType The type handle registered in ring-3 already.
+ * @sa PDMDevHlpPGMHandlerPhysicalTypeRegister
+ */
+ DECLR0CALLBACKMEMBER(int, pfnPGMHandlerPhysicalTypeSetUpContext, (PPDMDEVINS pDevIns, PGMPHYSHANDLERKIND enmKind,
+ PFNPGMPHYSHANDLER pfnHandler,
+ PFNPGMRZPHYSPFHANDLER pfnPfHandler,
+ const char *pszDesc, PGMPHYSHANDLERTYPE hType));
+
+ /**
+ * Temporarily turns off the access monitoring of a page within a monitored
+ * physical write/all page access handler region.
+ *
+ * Use this when no further \#PFs are required for that page. Be aware that
+ * a page directory sync might reset the flags, and turn on access monitoring
+ * for the page.
+ *
+ * The caller must do required page table modifications.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param GCPhys The start address of the access handler. This
+ * must be a fully page aligned range or we risk
+ * messing up other handlers installed for the
+ * start and end pages.
+ * @param GCPhysPage The physical address of the page to turn off
+ * access monitoring for.
+ */
+ DECLR0CALLBACKMEMBER(int, pfnPGMHandlerPhysicalPageTempOff,(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTGCPHYS GCPhysPage));
+
+ /**
+ * Mapping an MMIO2 page in place of an MMIO page for direct access.
+ *
+ * This is a special optimization used by the VGA device. Call
+ * PDMDevHlpMmioResetRegion() to undo the mapping.
+ *
+ * @returns VBox status code. This API may return VINF_SUCCESS even if no
+ * remapping is made.
+ * @retval VERR_SEM_BUSY in ring-0 if we cannot get the IOM lock.
+ *
+ * @param pDevIns The device instance @a hRegion and @a hMmio2 are
+ * associated with.
+ * @param hRegion The handle to the MMIO region.
+ * @param offRegion The offset into @a hRegion of the page to be
+ * remapped.
+ * @param hMmio2 The MMIO2 handle.
+ * @param offMmio2 Offset into @a hMmio2 of the page to be use for the
+ * mapping.
+ * @param fPageFlags Page flags to set. Must be (X86_PTE_RW | X86_PTE_P)
+ * for the time being.
+ */
+ DECLR0CALLBACKMEMBER(int, pfnMmioMapMmio2Page,(PPDMDEVINS pDevIns, IOMMMIOHANDLE hRegion, RTGCPHYS offRegion,
+ uint64_t hMmio2, RTGCPHYS offMmio2, uint64_t fPageFlags));
+
+ /**
+ * Reset a previously modified MMIO region; restore the access flags.
+ *
+ * This undoes the effects of PDMDevHlpMmioMapMmio2Page() and is currently only
+ * intended for some ancient VGA hack. However, it would be great to extend it
+ * beyond VT-x and/or nested-paging.
+ *
+ * @returns VBox status code.
+ *
+ * @param pDevIns The device instance @a hRegion is associated with.
+ * @param hRegion The handle to the MMIO region.
+ */
+ DECLR0CALLBACKMEMBER(int, pfnMmioResetRegion, (PPDMDEVINS pDevIns, IOMMMIOHANDLE hRegion));
+
+ /**
+ * Returns the array of MMIO2 regions that are expected to be registered and
+ * later mapped into the guest-physical address space for the GIM provider
+ * configured for the VM.
+ *
+ * @returns Pointer to an array of GIM MMIO2 regions, may return NULL.
+ * @param pDevIns Pointer to the GIM device instance.
+ * @param pcRegions Where to store the number of items in the array.
+ *
+ * @remarks The caller does not own and therefore must -NOT- try to free the
+ * returned pointer.
+ */
+ DECLR0CALLBACKMEMBER(PGIMMMIO2REGION, pfnGIMGetMmio2Regions,(PPDMDEVINS pDevIns, uint32_t *pcRegions));
+
+ /** Space reserved for future members.
+ * @{ */
+ DECLR0CALLBACKMEMBER(void, pfnReserved1,(void));
+ DECLR0CALLBACKMEMBER(void, pfnReserved2,(void));
+ DECLR0CALLBACKMEMBER(void, pfnReserved3,(void));
+ DECLR0CALLBACKMEMBER(void, pfnReserved4,(void));
+ DECLR0CALLBACKMEMBER(void, pfnReserved5,(void));
+ DECLR0CALLBACKMEMBER(void, pfnReserved6,(void));
+ DECLR0CALLBACKMEMBER(void, pfnReserved7,(void));
+ DECLR0CALLBACKMEMBER(void, pfnReserved8,(void));
+ DECLR0CALLBACKMEMBER(void, pfnReserved9,(void));
+ DECLR0CALLBACKMEMBER(void, pfnReserved10,(void));
+ /** @} */
+
+ /** Just a safety precaution. */
+ uint32_t u32TheEnd;
+} PDMDEVHLPR0;
+/** Pointer PDM Device R0 API. */
+typedef R0PTRTYPE(struct PDMDEVHLPR0 *) PPDMDEVHLPR0;
+/** Pointer PDM Device GC API. */
+typedef R0PTRTYPE(const struct PDMDEVHLPR0 *) PCPDMDEVHLPR0;
+
+/** Current PDMDEVHLP version number. */
+#define PDM_DEVHLPR0_VERSION PDM_VERSION_MAKE(0xffe5, 27, 0)
+
+
+/**
+ * PDM Device Instance.
+ */
+typedef struct PDMDEVINSR3
+{
+ /** Structure version. PDM_DEVINSR3_VERSION defines the current version. */
+ uint32_t u32Version;
+ /** Device instance number. */
+ uint32_t iInstance;
+ /** Size of the ring-3, raw-mode and shared bits. */
+ uint32_t cbRing3;
+ /** Set if ring-0 context is enabled. */
+ bool fR0Enabled;
+ /** Set if raw-mode context is enabled. */
+ bool fRCEnabled;
+ /** Alignment padding. */
+ bool afReserved[2];
+ /** Pointer the HC PDM Device API. */
+ PCPDMDEVHLPR3 pHlpR3;
+ /** Pointer to the shared device instance data. */
+ RTR3PTR pvInstanceDataR3;
+ /** Pointer to the device instance data for ring-3. */
+ RTR3PTR pvInstanceDataForR3;
+ /** The critical section for the device.
+ *
+ * TM and IOM will enter this critical section before calling into the device
+ * code. PDM will when doing power on, power off, reset, suspend and resume
+ * notifications. SSM will currently not, but this will be changed later on.
+ *
+ * The device gets a critical section automatically assigned to it before
+ * the constructor is called. If the constructor wishes to use a different
+ * critical section, it calls PDMDevHlpSetDeviceCritSect() to change it
+ * very early on.
+ */
+ R3PTRTYPE(PPDMCRITSECT) pCritSectRoR3;
+ /** Pointer to device registration structure. */
+ R3PTRTYPE(PCPDMDEVREG) pReg;
+ /** Configuration handle. */
+ R3PTRTYPE(PCFGMNODE) pCfg;
+ /** The base interface of the device.
+ *
+ * The device constructor initializes this if it has any
+ * device level interfaces to export. To obtain this interface
+ * call PDMR3QueryDevice(). */
+ PDMIBASE IBase;
+
+ /** Tracing indicator. */
+ uint32_t fTracing;
+ /** The tracing ID of this device. */
+ uint32_t idTracing;
+
+ /** Ring-3 pointer to the raw-mode device instance. */
+ R3PTRTYPE(struct PDMDEVINSRC *) pDevInsForRCR3;
+ /** Raw-mode address of the raw-mode device instance. */
+ RTRGPTR pDevInsForRC;
+ /** Ring-3 pointer to the raw-mode instance data. */
+ RTR3PTR pvInstanceDataForRCR3;
+
+ /** PCI device structure size. */
+ uint32_t cbPciDev;
+ /** Number of PCI devices in apPciDevs. */
+ uint32_t cPciDevs;
+ /** Pointer to the PCI devices for this device.
+ * (Allocated after the shared instance data.)
+ * @note If we want to extend this beyond 8 sub-functions/devices, those 1 or
+ * two devices ever needing it can use cbPciDev and do the address
+ * calculations that for entries 8+. */
+ R3PTRTYPE(struct PDMPCIDEV *) apPciDevs[8];
+
+ /** Temporarily. */
+ R0PTRTYPE(struct PDMDEVINSR0 *) pDevInsR0RemoveMe;
+ /** Temporarily. */
+ RTR0PTR pvInstanceDataR0;
+ /** Temporarily. */
+ RTRCPTR pvInstanceDataRC;
+ /** Align the internal data more naturally. */
+ uint32_t au32Padding[HC_ARCH_BITS == 32 ? 13 : 11];
+
+ /** Internal data. */
+ union
+ {
+#ifdef PDMDEVINSINT_DECLARED
+ PDMDEVINSINTR3 s;
+#endif
+ uint8_t padding[HC_ARCH_BITS == 32 ? 0x40 : 0x90];
+ } Internal;
+
+ /** Device instance data for ring-3. The size of this area is defined
+ * in the PDMDEVREG::cbInstanceR3 field. */
+ char achInstanceData[8];
+} PDMDEVINSR3;
+
+/** Current PDMDEVINSR3 version number. */
+#define PDM_DEVINSR3_VERSION PDM_VERSION_MAKE(0xff82, 4, 0)
+
+/** Converts a pointer to the PDMDEVINSR3::IBase to a pointer to PDMDEVINS. */
+#define PDMIBASE_2_PDMDEV(pInterface) ( (PPDMDEVINS)((char *)(pInterface) - RT_UOFFSETOF(PDMDEVINS, IBase)) )
+
+
+/**
+ * PDM ring-0 device instance.
+ */
+typedef struct PDMDEVINSR0
+{
+ /** Structure version. PDM_DEVINSR0_VERSION defines the current version. */
+ uint32_t u32Version;
+ /** Device instance number. */
+ uint32_t iInstance;
+
+ /** Pointer the HC PDM Device API. */
+ PCPDMDEVHLPR0 pHlpR0;
+ /** Pointer to the shared device instance data. */
+ RTR0PTR pvInstanceDataR0;
+ /** Pointer to the device instance data for ring-0. */
+ RTR0PTR pvInstanceDataForR0;
+ /** The critical section for the device.
+ *
+ * TM and IOM will enter this critical section before calling into the device
+ * code. PDM will when doing power on, power off, reset, suspend and resume
+ * notifications. SSM will currently not, but this will be changed later on.
+ *
+ * The device gets a critical section automatically assigned to it before
+ * the constructor is called. If the constructor wishes to use a different
+ * critical section, it calls PDMDevHlpSetDeviceCritSect() to change it
+ * very early on.
+ */
+ R0PTRTYPE(PPDMCRITSECT) pCritSectRoR0;
+ /** Pointer to the ring-0 device registration structure. */
+ R0PTRTYPE(PCPDMDEVREGR0) pReg;
+ /** Ring-3 address of the ring-3 device instance. */
+ R3PTRTYPE(struct PDMDEVINSR3 *) pDevInsForR3;
+ /** Ring-0 pointer to the ring-3 device instance. */
+ R0PTRTYPE(struct PDMDEVINSR3 *) pDevInsForR3R0;
+ /** Ring-0 pointer to the ring-3 instance data. */
+ RTR0PTR pvInstanceDataForR3R0;
+ /** Raw-mode address of the raw-mode device instance. */
+ RGPTRTYPE(struct PDMDEVINSRC *) pDevInsForRC;
+ /** Ring-0 pointer to the raw-mode device instance. */
+ R0PTRTYPE(struct PDMDEVINSRC *) pDevInsForRCR0;
+ /** Ring-0 pointer to the raw-mode instance data. */
+ RTR0PTR pvInstanceDataForRCR0;
+
+ /** PCI device structure size. */
+ uint32_t cbPciDev;
+ /** Number of PCI devices in apPciDevs. */
+ uint32_t cPciDevs;
+ /** Pointer to the PCI devices for this device.
+ * (Allocated after the shared instance data.)
+ * @note If we want to extend this beyond 8 sub-functions/devices, those 1 or
+ * two devices ever needing it can use cbPciDev and do the address
+ * calculations that for entries 8+. */
+ R0PTRTYPE(struct PDMPCIDEV *) apPciDevs[8];
+
+ /** Align the internal data more naturally. */
+ uint32_t au32Padding[HC_ARCH_BITS == 32 ? 3 : 2 + 4];
+
+ /** Internal data. */
+ union
+ {
+#ifdef PDMDEVINSINT_DECLARED
+ PDMDEVINSINTR0 s;
+#endif
+ uint8_t padding[HC_ARCH_BITS == 32 ? 0x40 : 0x80];
+ } Internal;
+
+ /** Device instance data for ring-0. The size of this area is defined
+ * in the PDMDEVREG::cbInstanceR0 field. */
+ char achInstanceData[8];
+} PDMDEVINSR0;
+
+/** Current PDMDEVINSR0 version number. */
+#define PDM_DEVINSR0_VERSION PDM_VERSION_MAKE(0xff83, 4, 0)
+
+
+/**
+ * PDM raw-mode device instance.
+ */
+typedef struct PDMDEVINSRC
+{
+ /** Structure version. PDM_DEVINSRC_VERSION defines the current version. */
+ uint32_t u32Version;
+ /** Device instance number. */
+ uint32_t iInstance;
+
+ /** Pointer the HC PDM Device API. */
+ PCPDMDEVHLPRC pHlpRC;
+ /** Pointer to the shared device instance data. */
+ RTRGPTR pvInstanceDataRC;
+ /** Pointer to the device instance data for raw-mode. */
+ RTRGPTR pvInstanceDataForRC;
+ /** The critical section for the device.
+ *
+ * TM and IOM will enter this critical section before calling into the device
+ * code. PDM will when doing power on, power off, reset, suspend and resume
+ * notifications. SSM will currently not, but this will be changed later on.
+ *
+ * The device gets a critical section automatically assigned to it before
+ * the constructor is called. If the constructor wishes to use a different
+ * critical section, it calls PDMDevHlpSetDeviceCritSect() to change it
+ * very early on.
+ */
+ RGPTRTYPE(PPDMCRITSECT) pCritSectRoRC;
+ /** Pointer to the raw-mode device registration structure. */
+ RGPTRTYPE(PCPDMDEVREGRC) pReg;
+
+ /** PCI device structure size. */
+ uint32_t cbPciDev;
+ /** Number of PCI devices in apPciDevs. */
+ uint32_t cPciDevs;
+ /** Pointer to the PCI devices for this device.
+ * (Allocated after the shared instance data.) */
+ RGPTRTYPE(struct PDMPCIDEV *) apPciDevs[8];
+
+ /** Align the internal data more naturally. */
+ uint32_t au32Padding[14];
+
+ /** Internal data. */
+ union
+ {
+#ifdef PDMDEVINSINT_DECLARED
+ PDMDEVINSINTRC s;
+#endif
+ uint8_t padding[0x10];
+ } Internal;
+
+ /** Device instance data for ring-0. The size of this area is defined
+ * in the PDMDEVREG::cbInstanceR0 field. */
+ char achInstanceData[8];
+} PDMDEVINSRC;
+
+/** Current PDMDEVINSR0 version number. */
+#define PDM_DEVINSRC_VERSION PDM_VERSION_MAKE(0xff84, 4, 0)
+
+
+/** @def PDM_DEVINS_VERSION
+ * Current PDMDEVINS version number. */
+/** @typedef PDMDEVINS
+ * The device instance structure for the current context. */
+#ifdef IN_RING3
+# define PDM_DEVINS_VERSION PDM_DEVINSR3_VERSION
+typedef PDMDEVINSR3 PDMDEVINS;
+#elif defined(IN_RING0)
+# define PDM_DEVINS_VERSION PDM_DEVINSR0_VERSION
+typedef PDMDEVINSR0 PDMDEVINS;
+#elif defined(IN_RC)
+# define PDM_DEVINS_VERSION PDM_DEVINSRC_VERSION
+typedef PDMDEVINSRC PDMDEVINS;
+#else
+# error "Missing context defines: IN_RING0, IN_RING3, IN_RC"
+#endif
+
+/**
+ * Get the pointer to an PCI device.
+ * @note Returns NULL if @a a_idxPciDev is out of bounds.
+ */
+#define PDMDEV_GET_PPCIDEV(a_pDevIns, a_idxPciDev) \
+ ( (uintptr_t)(a_idxPciDev) < RT_ELEMENTS((a_pDevIns)->apPciDevs) ? (a_pDevIns)->apPciDevs[(uintptr_t)(a_idxPciDev)] \
+ : PDMDEV_CALC_PPCIDEV(a_pDevIns, a_idxPciDev) )
+
+/**
+ * Calc the pointer to of a given PCI device.
+ * @note Returns NULL if @a a_idxPciDev is out of bounds.
+ */
+#define PDMDEV_CALC_PPCIDEV(a_pDevIns, a_idxPciDev) \
+ ( (uintptr_t)(a_idxPciDev) < (a_pDevIns)->cPciDevs \
+ ? (PPDMPCIDEV)((uint8_t *)((a_pDevIns)->apPciDevs[0]) + (a_pDevIns->cbPciDev) * (uintptr_t)(a_idxPciDev)) \
+ : (PPDMPCIDEV)NULL )
+
+
+/**
+ * Checks the structure versions of the device instance and device helpers,
+ * returning if they are incompatible.
+ *
+ * This is for use in the constructor.
+ *
+ * @param pDevIns The device instance pointer.
+ */
+#define PDMDEV_CHECK_VERSIONS_RETURN(pDevIns) \
+ do \
+ { \
+ PPDMDEVINS pDevInsTypeCheck = (pDevIns); NOREF(pDevInsTypeCheck); \
+ AssertLogRelMsgReturn(PDM_VERSION_ARE_COMPATIBLE((pDevIns)->u32Version, PDM_DEVINS_VERSION), \
+ ("DevIns=%#x mine=%#x\n", (pDevIns)->u32Version, PDM_DEVINS_VERSION), \
+ VERR_PDM_DEVINS_VERSION_MISMATCH); \
+ AssertLogRelMsgReturn(PDM_VERSION_ARE_COMPATIBLE((pDevIns)->CTX_SUFF(pHlp)->u32Version, CTX_MID(PDM_DEVHLP,_VERSION)), \
+ ("DevHlp=%#x mine=%#x\n", (pDevIns)->CTX_SUFF(pHlp)->u32Version, CTX_MID(PDM_DEVHLP,_VERSION)), \
+ VERR_PDM_DEVHLP_VERSION_MISMATCH); \
+ } while (0)
+
+/**
+ * Quietly checks the structure versions of the device instance and device
+ * helpers, returning if they are incompatible.
+ *
+ * This is for use in the destructor.
+ *
+ * @param pDevIns The device instance pointer.
+ */
+#define PDMDEV_CHECK_VERSIONS_RETURN_QUIET(pDevIns) \
+ do \
+ { \
+ PPDMDEVINS pDevInsTypeCheck = (pDevIns); NOREF(pDevInsTypeCheck); \
+ if (RT_LIKELY(PDM_VERSION_ARE_COMPATIBLE((pDevIns)->u32Version, PDM_DEVINS_VERSION) )) \
+ { /* likely */ } else return VERR_PDM_DEVINS_VERSION_MISMATCH; \
+ if (RT_LIKELY(PDM_VERSION_ARE_COMPATIBLE((pDevIns)->CTX_SUFF(pHlp)->u32Version, CTX_MID(PDM_DEVHLP,_VERSION)) )) \
+ { /* likely */ } else return VERR_PDM_DEVHLP_VERSION_MISMATCH; \
+ } while (0)
+
+/**
+ * Wrapper around CFGMR3ValidateConfig for the root config for use in the
+ * constructor - returns on failure.
+ *
+ * This should be invoked after having initialized the instance data
+ * sufficiently for the correct operation of the destructor. The destructor is
+ * always called!
+ *
+ * @param pDevIns Pointer to the PDM device instance.
+ * @param pszValidValues Patterns describing the valid value names. See
+ * RTStrSimplePatternMultiMatch for details on the
+ * pattern syntax.
+ * @param pszValidNodes Patterns describing the valid node (key) names.
+ * Pass empty string if no valid nodes.
+ */
+#define PDMDEV_VALIDATE_CONFIG_RETURN(pDevIns, pszValidValues, pszValidNodes) \
+ do \
+ { \
+ int rcValCfg = pDevIns->pHlpR3->pfnCFGMValidateConfig((pDevIns)->pCfg, "/", pszValidValues, pszValidNodes, \
+ (pDevIns)->pReg->szName, (pDevIns)->iInstance); \
+ if (RT_SUCCESS(rcValCfg)) \
+ { /* likely */ } else return rcValCfg; \
+ } while (0)
+
+/** @def PDMDEV_ASSERT_EMT
+ * Assert that the current thread is the emulation thread.
+ */
+#ifdef VBOX_STRICT
+# define PDMDEV_ASSERT_EMT(pDevIns) pDevIns->pHlpR3->pfnAssertEMT(pDevIns, __FILE__, __LINE__, __FUNCTION__)
+#else
+# define PDMDEV_ASSERT_EMT(pDevIns) do { } while (0)
+#endif
+
+/** @def PDMDEV_ASSERT_OTHER
+ * Assert that the current thread is NOT the emulation thread.
+ */
+#ifdef VBOX_STRICT
+# define PDMDEV_ASSERT_OTHER(pDevIns) pDevIns->pHlpR3->pfnAssertOther(pDevIns, __FILE__, __LINE__, __FUNCTION__)
+#else
+# define PDMDEV_ASSERT_OTHER(pDevIns) do { } while (0)
+#endif
+
+/** @def PDMDEV_ASSERT_VMLOCK_OWNER
+ * Assert that the current thread is owner of the VM lock.
+ */
+#ifdef VBOX_STRICT
+# define PDMDEV_ASSERT_VMLOCK_OWNER(pDevIns) pDevIns->pHlpR3->pfnAssertVMLock(pDevIns, __FILE__, __LINE__, __FUNCTION__)
+#else
+# define PDMDEV_ASSERT_VMLOCK_OWNER(pDevIns) do { } while (0)
+#endif
+
+/** @def PDMDEV_SET_ERROR
+ * Set the VM error. See PDMDevHlpVMSetError() for printf like message formatting.
+ */
+#define PDMDEV_SET_ERROR(pDevIns, rc, pszError) \
+ PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS, "%s", pszError)
+
+/** @def PDMDEV_SET_RUNTIME_ERROR
+ * Set the VM runtime error. See PDMDevHlpVMSetRuntimeError() for printf like message formatting.
+ */
+#define PDMDEV_SET_RUNTIME_ERROR(pDevIns, fFlags, pszErrorId, pszError) \
+ PDMDevHlpVMSetRuntimeError(pDevIns, fFlags, pszErrorId, "%s", pszError)
+
+/** @def PDMDEVINS_2_RCPTR
+ * Converts a PDM Device instance pointer to a RC PDM Device instance pointer.
+ */
+#ifdef IN_RC
+# define PDMDEVINS_2_RCPTR(pDevIns) (pDevIns)
+#else
+# define PDMDEVINS_2_RCPTR(pDevIns) ( (pDevIns)->pDevInsForRC )
+#endif
+
+/** @def PDMDEVINS_2_R3PTR
+ * Converts a PDM Device instance pointer to a R3 PDM Device instance pointer.
+ */
+#ifdef IN_RING3
+# define PDMDEVINS_2_R3PTR(pDevIns) (pDevIns)
+#else
+# define PDMDEVINS_2_R3PTR(pDevIns) ( (pDevIns)->pDevInsForR3 )
+#endif
+
+/** @def PDMDEVINS_2_R0PTR
+ * Converts a PDM Device instance pointer to a R0 PDM Device instance pointer.
+ */
+#ifdef IN_RING0
+# define PDMDEVINS_2_R0PTR(pDevIns) (pDevIns)
+#else
+# define PDMDEVINS_2_R0PTR(pDevIns) ( (pDevIns)->pDevInsR0RemoveMe )
+#endif
+
+/** @def PDMDEVINS_DATA_2_R0_REMOVE_ME
+ * Converts a PDM device instance data pointer to a ring-0 one.
+ * @deprecated
+ */
+#ifdef IN_RING0
+# define PDMDEVINS_DATA_2_R0_REMOVE_ME(pDevIns, pvCC) (pvCC)
+#else
+# define PDMDEVINS_DATA_2_R0_REMOVE_ME(pDevIns, pvCC) ( (pDevIns)->pvInstanceDataR0 + (uintptr_t)(pvCC) - (uintptr_t)(pDevIns)->CTX_SUFF(pvInstanceData) )
+#endif
+
+
+/** @def PDMDEVINS_2_DATA
+ * This is a safer edition of PDMINS_2_DATA that checks that the size of the
+ * target type is same as PDMDEVREG::cbInstanceShared in strict builds.
+ *
+ * @note Do no use this macro in common code working on a core structure which
+ * device specific code has expanded.
+ */
+#if defined(VBOX_STRICT) && defined(RT_COMPILER_SUPPORTS_LAMBDA)
+# define PDMDEVINS_2_DATA(a_pDevIns, a_PtrType) \
+ ([](PPDMDEVINS a_pLambdaDevIns) -> a_PtrType \
+ { \
+ a_PtrType pLambdaRet = (a_PtrType)(a_pLambdaDevIns)->CTX_SUFF(pvInstanceData); \
+ Assert(sizeof(*pLambdaRet) == a_pLambdaDevIns->pReg->cbInstanceShared); \
+ return pLambdaRet; \
+ }(a_pDevIns))
+#else
+# define PDMDEVINS_2_DATA(a_pDevIns, a_PtrType) ( (a_PtrType)(a_pDevIns)->CTX_SUFF(pvInstanceData) )
+#endif
+
+/** @def PDMDEVINS_2_DATA_CC
+ * This is a safer edition of PDMINS_2_DATA_CC that checks that the size of the
+ * target type is same as PDMDEVREG::cbInstanceCC in strict builds.
+ *
+ * @note Do no use this macro in common code working on a core structure which
+ * device specific code has expanded.
+ */
+#if defined(VBOX_STRICT) && defined(RT_COMPILER_SUPPORTS_LAMBDA)
+# define PDMDEVINS_2_DATA_CC(a_pDevIns, a_PtrType) \
+ ([](PPDMDEVINS a_pLambdaDevIns) -> a_PtrType \
+ { \
+ a_PtrType pLambdaRet = (a_PtrType)&(a_pLambdaDevIns)->achInstanceData[0]; \
+ Assert(sizeof(*pLambdaRet) == a_pLambdaDevIns->pReg->cbInstanceCC); \
+ return pLambdaRet; \
+ }(a_pDevIns))
+#else
+# define PDMDEVINS_2_DATA_CC(a_pDevIns, a_PtrType) ( (a_PtrType)(void *)&(a_pDevIns)->achInstanceData[0] )
+#endif
+
+
+#ifdef IN_RING3
+
+/**
+ * Combines PDMDevHlpIoPortCreate() & PDMDevHlpIoPortMap().
+ */
+DECLINLINE(int) PDMDevHlpIoPortCreateAndMap(PPDMDEVINS pDevIns, RTIOPORT Port, RTIOPORT cPorts, PFNIOMIOPORTNEWOUT pfnOut,
+ PFNIOMIOPORTNEWIN pfnIn, const char *pszDesc, PCIOMIOPORTDESC paExtDescs,
+ PIOMIOPORTHANDLE phIoPorts)
+{
+ int rc = pDevIns->pHlpR3->pfnIoPortCreateEx(pDevIns, cPorts, 0, NULL, UINT32_MAX,
+ pfnOut, pfnIn, NULL, NULL, NULL, pszDesc, paExtDescs, phIoPorts);
+ if (RT_SUCCESS(rc))
+ rc = pDevIns->pHlpR3->pfnIoPortMap(pDevIns, *phIoPorts, Port);
+ return rc;
+}
+
+/**
+ * Combines PDMDevHlpIoPortCreate() & PDMDevHlpIoPortMap(), but with pvUser.
+ */
+DECLINLINE(int) PDMDevHlpIoPortCreateUAndMap(PPDMDEVINS pDevIns, RTIOPORT Port, RTIOPORT cPorts, PFNIOMIOPORTNEWOUT pfnOut,
+ PFNIOMIOPORTNEWIN pfnIn, void *pvUser,
+ const char *pszDesc, PCIOMIOPORTDESC paExtDescs, PIOMIOPORTHANDLE phIoPorts)
+{
+ int rc = pDevIns->pHlpR3->pfnIoPortCreateEx(pDevIns, cPorts, 0, NULL, UINT32_MAX,
+ pfnOut, pfnIn, NULL, NULL, pvUser, pszDesc, paExtDescs, phIoPorts);
+ if (RT_SUCCESS(rc))
+ rc = pDevIns->pHlpR3->pfnIoPortMap(pDevIns, *phIoPorts, Port);
+ return rc;
+}
+
+/**
+ * Combines PDMDevHlpIoPortCreate() & PDMDevHlpIoPortMap(), but with flags.
+ */
+DECLINLINE(int) PDMDevHlpIoPortCreateFlagsAndMap(PPDMDEVINS pDevIns, RTIOPORT Port, RTIOPORT cPorts, uint32_t fFlags,
+ PFNIOMIOPORTNEWOUT pfnOut, PFNIOMIOPORTNEWIN pfnIn,
+ const char *pszDesc, PCIOMIOPORTDESC paExtDescs, PIOMIOPORTHANDLE phIoPorts)
+{
+ int rc = pDevIns->pHlpR3->pfnIoPortCreateEx(pDevIns, cPorts, fFlags, NULL, UINT32_MAX,
+ pfnOut, pfnIn, NULL, NULL, NULL, pszDesc, paExtDescs, phIoPorts);
+ if (RT_SUCCESS(rc))
+ rc = pDevIns->pHlpR3->pfnIoPortMap(pDevIns, *phIoPorts, Port);
+ return rc;
+}
+
+/**
+ * Combines PDMDevHlpIoPortCreateEx() & PDMDevHlpIoPortMap().
+ */
+DECLINLINE(int) PDMDevHlpIoPortCreateExAndMap(PPDMDEVINS pDevIns, RTIOPORT Port, RTIOPORT cPorts, uint32_t fFlags,
+ PFNIOMIOPORTNEWOUT pfnOut, PFNIOMIOPORTNEWIN pfnIn,
+ PFNIOMIOPORTNEWOUTSTRING pfnOutStr, PFNIOMIOPORTNEWINSTRING pfnInStr, void *pvUser,
+ const char *pszDesc, PCIOMIOPORTDESC paExtDescs, PIOMIOPORTHANDLE phIoPorts)
+{
+ int rc = pDevIns->pHlpR3->pfnIoPortCreateEx(pDevIns, cPorts, fFlags, NULL, UINT32_MAX,
+ pfnOut, pfnIn, pfnOutStr, pfnInStr, pvUser, pszDesc, paExtDescs, phIoPorts);
+ if (RT_SUCCESS(rc))
+ rc = pDevIns->pHlpR3->pfnIoPortMap(pDevIns, *phIoPorts, Port);
+ return rc;
+}
+
+/**
+ * @sa PDMDevHlpIoPortCreateEx
+ */
+DECLINLINE(int) PDMDevHlpIoPortCreate(PPDMDEVINS pDevIns, RTIOPORT cPorts, PPDMPCIDEV pPciDev, uint32_t iPciRegion,
+ PFNIOMIOPORTNEWOUT pfnOut, PFNIOMIOPORTNEWIN pfnIn, void *pvUser, const char *pszDesc,
+ PCIOMIOPORTDESC paExtDescs, PIOMIOPORTHANDLE phIoPorts)
+{
+ return pDevIns->pHlpR3->pfnIoPortCreateEx(pDevIns, cPorts, 0, pPciDev, iPciRegion,
+ pfnOut, pfnIn, NULL, NULL, pvUser, pszDesc, paExtDescs, phIoPorts);
+}
+
+
+/**
+ * @sa PDMDevHlpIoPortCreateEx
+ */
+DECLINLINE(int) PDMDevHlpIoPortCreateIsa(PPDMDEVINS pDevIns, RTIOPORT cPorts, PFNIOMIOPORTNEWOUT pfnOut,
+ PFNIOMIOPORTNEWIN pfnIn, void *pvUser, const char *pszDesc,
+ PCIOMIOPORTDESC paExtDescs, PIOMIOPORTHANDLE phIoPorts)
+{
+ return pDevIns->pHlpR3->pfnIoPortCreateEx(pDevIns, cPorts, 0, NULL, UINT32_MAX,
+ pfnOut, pfnIn, NULL, NULL, pvUser, pszDesc, paExtDescs, phIoPorts);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnIoPortCreateEx
+ */
+DECLINLINE(int) PDMDevHlpIoPortCreateEx(PPDMDEVINS pDevIns, RTIOPORT cPorts, uint32_t fFlags, PPDMPCIDEV pPciDev,
+ uint32_t iPciRegion, PFNIOMIOPORTNEWOUT pfnOut, PFNIOMIOPORTNEWIN pfnIn,
+ PFNIOMIOPORTNEWOUTSTRING pfnOutStr, PFNIOMIOPORTNEWINSTRING pfnInStr, void *pvUser,
+ const char *pszDesc, PCIOMIOPORTDESC paExtDescs, PIOMIOPORTHANDLE phIoPorts)
+{
+ return pDevIns->pHlpR3->pfnIoPortCreateEx(pDevIns, cPorts, fFlags, pPciDev, iPciRegion,
+ pfnOut, pfnIn, pfnOutStr, pfnInStr, pvUser, pszDesc, paExtDescs, phIoPorts);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnIoPortMap
+ */
+DECLINLINE(int) PDMDevHlpIoPortMap(PPDMDEVINS pDevIns, IOMIOPORTHANDLE hIoPorts, RTIOPORT Port)
+{
+ return pDevIns->pHlpR3->pfnIoPortMap(pDevIns, hIoPorts, Port);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnIoPortUnmap
+ */
+DECLINLINE(int) PDMDevHlpIoPortUnmap(PPDMDEVINS pDevIns, IOMIOPORTHANDLE hIoPorts)
+{
+ return pDevIns->pHlpR3->pfnIoPortUnmap(pDevIns, hIoPorts);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnIoPortGetMappingAddress
+ */
+DECLINLINE(uint32_t) PDMDevHlpIoPortGetMappingAddress(PPDMDEVINS pDevIns, IOMIOPORTHANDLE hIoPorts)
+{
+ return pDevIns->pHlpR3->pfnIoPortGetMappingAddress(pDevIns, hIoPorts);
+}
+
+
+#endif /* IN_RING3 */
+#if !defined(IN_RING3) || defined(DOXYGEN_RUNNING)
+
+/**
+ * @sa PDMDevHlpIoPortSetUpContextEx
+ */
+DECLINLINE(int) PDMDevHlpIoPortSetUpContext(PPDMDEVINS pDevIns, IOMIOPORTHANDLE hIoPorts,
+ PFNIOMIOPORTNEWOUT pfnOut, PFNIOMIOPORTNEWIN pfnIn, void *pvUser)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnIoPortSetUpContextEx(pDevIns, hIoPorts, pfnOut, pfnIn, NULL, NULL, pvUser);
+}
+
+/**
+ * @copydoc PDMDEVHLPR0::pfnIoPortSetUpContextEx
+ */
+DECLINLINE(int) PDMDevHlpIoPortSetUpContextEx(PPDMDEVINS pDevIns, IOMIOPORTHANDLE hIoPorts,
+ PFNIOMIOPORTNEWOUT pfnOut, PFNIOMIOPORTNEWIN pfnIn,
+ PFNIOMIOPORTNEWOUTSTRING pfnOutStr, PFNIOMIOPORTNEWINSTRING pfnInStr, void *pvUser)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnIoPortSetUpContextEx(pDevIns, hIoPorts, pfnOut, pfnIn, pfnOutStr, pfnInStr, pvUser);
+}
+
+#endif /* !IN_RING3 || DOXYGEN_RUNNING */
+#ifdef IN_RING3
+
+/**
+ * @sa PDMDevHlpMmioCreateEx
+ */
+DECLINLINE(int) PDMDevHlpMmioCreate(PPDMDEVINS pDevIns, RTGCPHYS cbRegion, PPDMPCIDEV pPciDev, uint32_t iPciRegion,
+ PFNIOMMMIONEWWRITE pfnWrite, PFNIOMMMIONEWREAD pfnRead, void *pvUser,
+ uint32_t fFlags, const char *pszDesc, PIOMMMIOHANDLE phRegion)
+{
+ return pDevIns->pHlpR3->pfnMmioCreateEx(pDevIns, cbRegion, fFlags, pPciDev, iPciRegion,
+ pfnWrite, pfnRead, NULL, pvUser, pszDesc, phRegion);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnMmioCreateEx
+ */
+DECLINLINE(int) PDMDevHlpMmioCreateEx(PPDMDEVINS pDevIns, RTGCPHYS cbRegion,
+ uint32_t fFlags, PPDMPCIDEV pPciDev, uint32_t iPciRegion,
+ PFNIOMMMIONEWWRITE pfnWrite, PFNIOMMMIONEWREAD pfnRead, PFNIOMMMIONEWFILL pfnFill,
+ void *pvUser, const char *pszDesc, PIOMMMIOHANDLE phRegion)
+{
+ return pDevIns->pHlpR3->pfnMmioCreateEx(pDevIns, cbRegion, fFlags, pPciDev, iPciRegion,
+ pfnWrite, pfnRead, pfnFill, pvUser, pszDesc, phRegion);
+}
+
+/**
+ * @sa PDMDevHlpMmioCreate and PDMDevHlpMmioMap
+ */
+DECLINLINE(int) PDMDevHlpMmioCreateAndMap(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTGCPHYS cbRegion,
+ PFNIOMMMIONEWWRITE pfnWrite, PFNIOMMMIONEWREAD pfnRead,
+ uint32_t fFlags, const char *pszDesc, PIOMMMIOHANDLE phRegion)
+{
+ int rc = pDevIns->pHlpR3->pfnMmioCreateEx(pDevIns, cbRegion, fFlags, NULL /*pPciDev*/, UINT32_MAX /*iPciRegion*/,
+ pfnWrite, pfnRead, NULL /*pfnFill*/, NULL /*pvUser*/, pszDesc, phRegion);
+ if (RT_SUCCESS(rc))
+ rc = pDevIns->pHlpR3->pfnMmioMap(pDevIns, *phRegion, GCPhys);
+ return rc;
+}
+
+/**
+ * @sa PDMDevHlpMmioCreateEx and PDMDevHlpMmioMap
+ */
+DECLINLINE(int) PDMDevHlpMmioCreateExAndMap(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTGCPHYS cbRegion, uint32_t fFlags,
+ PPDMPCIDEV pPciDev, uint32_t iPciRegion, PFNIOMMMIONEWWRITE pfnWrite,
+ PFNIOMMMIONEWREAD pfnRead, PFNIOMMMIONEWFILL pfnFill, void *pvUser,
+ const char *pszDesc, PIOMMMIOHANDLE phRegion)
+{
+ int rc = pDevIns->pHlpR3->pfnMmioCreateEx(pDevIns, cbRegion, fFlags, pPciDev, iPciRegion,
+ pfnWrite, pfnRead, pfnFill, pvUser, pszDesc, phRegion);
+ if (RT_SUCCESS(rc))
+ rc = pDevIns->pHlpR3->pfnMmioMap(pDevIns, *phRegion, GCPhys);
+ return rc;
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnMmioMap
+ */
+DECLINLINE(int) PDMDevHlpMmioMap(PPDMDEVINS pDevIns, IOMMMIOHANDLE hRegion, RTGCPHYS GCPhys)
+{
+ return pDevIns->pHlpR3->pfnMmioMap(pDevIns, hRegion, GCPhys);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnMmioUnmap
+ */
+DECLINLINE(int) PDMDevHlpMmioUnmap(PPDMDEVINS pDevIns, IOMMMIOHANDLE hRegion)
+{
+ return pDevIns->pHlpR3->pfnMmioUnmap(pDevIns, hRegion);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnMmioReduce
+ */
+DECLINLINE(int) PDMDevHlpMmioReduce(PPDMDEVINS pDevIns, IOMMMIOHANDLE hRegion, RTGCPHYS cbRegion)
+{
+ return pDevIns->pHlpR3->pfnMmioReduce(pDevIns, hRegion, cbRegion);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnMmioGetMappingAddress
+ */
+DECLINLINE(RTGCPHYS) PDMDevHlpMmioGetMappingAddress(PPDMDEVINS pDevIns, IOMMMIOHANDLE hRegion)
+{
+ return pDevIns->pHlpR3->pfnMmioGetMappingAddress(pDevIns, hRegion);
+}
+
+#endif /* IN_RING3 */
+#if !defined(IN_RING3) || defined(DOXYGEN_RUNNING)
+
+/**
+ * @sa PDMDevHlpMmioSetUpContextEx
+ */
+DECLINLINE(int) PDMDevHlpMmioSetUpContext(PPDMDEVINS pDevIns, IOMMMIOHANDLE hRegion,
+ PFNIOMMMIONEWWRITE pfnWrite, PFNIOMMMIONEWREAD pfnRead, void *pvUser)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnMmioSetUpContextEx(pDevIns, hRegion, pfnWrite, pfnRead, NULL, pvUser);
+}
+
+/**
+ * @copydoc PDMDEVHLPR0::pfnMmioSetUpContextEx
+ */
+DECLINLINE(int) PDMDevHlpMmioSetUpContextEx(PPDMDEVINS pDevIns, IOMMMIOHANDLE hRegion, PFNIOMMMIONEWWRITE pfnWrite,
+ PFNIOMMMIONEWREAD pfnRead, PFNIOMMMIONEWFILL pfnFill, void *pvUser)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnMmioSetUpContextEx(pDevIns, hRegion, pfnWrite, pfnRead, pfnFill, pvUser);
+}
+
+#endif /* !IN_RING3 || DOXYGEN_RUNNING */
+#ifdef IN_RING3
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnMmio2Create
+ */
+DECLINLINE(int) PDMDevHlpMmio2Create(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t iPciRegion, RTGCPHYS cbRegion,
+ uint32_t fFlags, const char *pszDesc, void **ppvMapping, PPGMMMIO2HANDLE phRegion)
+{
+ return pDevIns->pHlpR3->pfnMmio2Create(pDevIns, pPciDev, iPciRegion, cbRegion, fFlags, pszDesc, ppvMapping, phRegion);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnMmio2Map
+ */
+DECLINLINE(int) PDMDevHlpMmio2Map(PPDMDEVINS pDevIns, PGMMMIO2HANDLE hRegion, RTGCPHYS GCPhys)
+{
+ return pDevIns->pHlpR3->pfnMmio2Map(pDevIns, hRegion, GCPhys);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnMmio2Unmap
+ */
+DECLINLINE(int) PDMDevHlpMmio2Unmap(PPDMDEVINS pDevIns, PGMMMIO2HANDLE hRegion)
+{
+ return pDevIns->pHlpR3->pfnMmio2Unmap(pDevIns, hRegion);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnMmio2Reduce
+ */
+DECLINLINE(int) PDMDevHlpMmio2Reduce(PPDMDEVINS pDevIns, PGMMMIO2HANDLE hRegion, RTGCPHYS cbRegion)
+{
+ return pDevIns->pHlpR3->pfnMmio2Reduce(pDevIns, hRegion, cbRegion);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnMmio2GetMappingAddress
+ */
+DECLINLINE(RTGCPHYS) PDMDevHlpMmio2GetMappingAddress(PPDMDEVINS pDevIns, PGMMMIO2HANDLE hRegion)
+{
+ return pDevIns->pHlpR3->pfnMmio2GetMappingAddress(pDevIns, hRegion);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnMmio2QueryAndResetDirtyBitmap
+ */
+DECLINLINE(int) PDMDevHlpMmio2QueryAndResetDirtyBitmap(PPDMDEVINS pDevIns, PGMMMIO2HANDLE hRegion,
+ void *pvBitmap, size_t cbBitmap)
+{
+ return pDevIns->pHlpR3->pfnMmio2QueryAndResetDirtyBitmap(pDevIns, hRegion, pvBitmap, cbBitmap);
+}
+
+/**
+ * Reset the dirty bitmap tracking for an MMIO2 region.
+ *
+ * The MMIO2 region must have been created with the
+ * PGMPHYS_MMIO2_FLAGS_TRACK_DIRTY_PAGES flag for this to work.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param hRegion The MMIO2 region handle.
+ */
+DECLINLINE(int) PDMDevHlpMmio2ResetDirtyBitmap(PPDMDEVINS pDevIns, PGMMMIO2HANDLE hRegion)
+{
+ return pDevIns->pHlpR3->pfnMmio2QueryAndResetDirtyBitmap(pDevIns, hRegion, NULL, 0);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnMmio2ControlDirtyPageTracking
+ */
+DECLINLINE(int) PDMDevHlpMmio2ControlDirtyPageTracking(PPDMDEVINS pDevIns, PGMMMIO2HANDLE hRegion, bool fEnabled)
+{
+ return pDevIns->pHlpR3->pfnMmio2ControlDirtyPageTracking(pDevIns, hRegion, fEnabled);
+}
+
+#endif /* IN_RING3 */
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnMmioMapMmio2Page
+ */
+DECLINLINE(int) PDMDevHlpMmioMapMmio2Page(PPDMDEVINS pDevIns, IOMMMIOHANDLE hRegion, RTGCPHYS offRegion,
+ uint64_t hMmio2, RTGCPHYS offMmio2, uint64_t fPageFlags)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnMmioMapMmio2Page(pDevIns, hRegion, offRegion, hMmio2, offMmio2, fPageFlags);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnMmioResetRegion
+ */
+DECLINLINE(int) PDMDevHlpMmioResetRegion(PPDMDEVINS pDevIns, IOMMMIOHANDLE hRegion)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnMmioResetRegion(pDevIns, hRegion);
+}
+
+#if !defined(IN_RING3) || defined(DOXYGEN_RUNNING)
+
+/**
+ * @copydoc PDMDEVHLPR0::pfnMmio2SetUpContext
+ */
+DECLINLINE(int) PDMDevHlpMmio2SetUpContext(PPDMDEVINS pDevIns, PGMMMIO2HANDLE hRegion,
+ size_t offSub, size_t cbSub, void **ppvMapping)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnMmio2SetUpContext(pDevIns, hRegion, offSub, cbSub, ppvMapping);
+}
+
+#endif /* !IN_RING3 || DOXYGEN_RUNNING */
+#ifdef IN_RING3
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnROMRegister
+ */
+DECLINLINE(int) PDMDevHlpROMRegister(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, uint32_t cbRange,
+ const void *pvBinary, uint32_t cbBinary, uint32_t fFlags, const char *pszDesc)
+{
+ return pDevIns->pHlpR3->pfnROMRegister(pDevIns, GCPhysStart, cbRange, pvBinary, cbBinary, fFlags, pszDesc);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnROMProtectShadow
+ */
+DECLINLINE(int) PDMDevHlpROMProtectShadow(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, uint32_t cbRange, PGMROMPROT enmProt)
+{
+ return pDevIns->pHlpR3->pfnROMProtectShadow(pDevIns, GCPhysStart, cbRange, enmProt);
+}
+
+/**
+ * Register a save state data unit.
+ *
+ * @returns VBox status.
+ * @param pDevIns The device instance.
+ * @param uVersion Data layout version number.
+ * @param cbGuess The approximate amount of data in the unit.
+ * Only for progress indicators.
+ * @param pfnSaveExec Execute save callback, optional.
+ * @param pfnLoadExec Execute load callback, optional.
+ */
+DECLINLINE(int) PDMDevHlpSSMRegister(PPDMDEVINS pDevIns, uint32_t uVersion, size_t cbGuess,
+ PFNSSMDEVSAVEEXEC pfnSaveExec, PFNSSMDEVLOADEXEC pfnLoadExec)
+{
+ return pDevIns->pHlpR3->pfnSSMRegister(pDevIns, uVersion, cbGuess, NULL /*pszBefore*/,
+ NULL /*pfnLivePrep*/, NULL /*pfnLiveExec*/, NULL /*pfnLiveDone*/,
+ NULL /*pfnSavePrep*/, pfnSaveExec, NULL /*pfnSaveDone*/,
+ NULL /*pfnLoadPrep*/, pfnLoadExec, NULL /*pfnLoadDone*/);
+}
+
+/**
+ * Register a save state data unit with a live save callback as well.
+ *
+ * @returns VBox status.
+ * @param pDevIns The device instance.
+ * @param uVersion Data layout version number.
+ * @param cbGuess The approximate amount of data in the unit.
+ * Only for progress indicators.
+ * @param pfnLiveExec Execute live callback, optional.
+ * @param pfnSaveExec Execute save callback, optional.
+ * @param pfnLoadExec Execute load callback, optional.
+ */
+DECLINLINE(int) PDMDevHlpSSMRegister3(PPDMDEVINS pDevIns, uint32_t uVersion, size_t cbGuess,
+ PFNSSMDEVLIVEEXEC pfnLiveExec, PFNSSMDEVSAVEEXEC pfnSaveExec, PFNSSMDEVLOADEXEC pfnLoadExec)
+{
+ return pDevIns->pHlpR3->pfnSSMRegister(pDevIns, uVersion, cbGuess, NULL /*pszBefore*/,
+ NULL /*pfnLivePrep*/, pfnLiveExec, NULL /*pfnLiveDone*/,
+ NULL /*pfnSavePrep*/, pfnSaveExec, NULL /*pfnSaveDone*/,
+ NULL /*pfnLoadPrep*/, pfnLoadExec, NULL /*pfnLoadDone*/);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnSSMRegister
+ */
+DECLINLINE(int) PDMDevHlpSSMRegisterEx(PPDMDEVINS pDevIns, uint32_t uVersion, size_t cbGuess, const char *pszBefore,
+ PFNSSMDEVLIVEPREP pfnLivePrep, PFNSSMDEVLIVEEXEC pfnLiveExec, PFNSSMDEVLIVEVOTE pfnLiveVote,
+ PFNSSMDEVSAVEPREP pfnSavePrep, PFNSSMDEVSAVEEXEC pfnSaveExec, PFNSSMDEVSAVEDONE pfnSaveDone,
+ PFNSSMDEVLOADPREP pfnLoadPrep, PFNSSMDEVLOADEXEC pfnLoadExec, PFNSSMDEVLOADDONE pfnLoadDone)
+{
+ return pDevIns->pHlpR3->pfnSSMRegister(pDevIns, uVersion, cbGuess, pszBefore,
+ pfnLivePrep, pfnLiveExec, pfnLiveVote,
+ pfnSavePrep, pfnSaveExec, pfnSaveDone,
+ pfnLoadPrep, pfnLoadExec, pfnLoadDone);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnSSMRegisterLegacy
+ */
+DECLINLINE(int) PDMDevHlpSSMRegisterLegacy(PPDMDEVINS pDevIns, const char *pszOldName, PFNSSMDEVLOADPREP pfnLoadPrep,
+ PFNSSMDEVLOADEXEC pfnLoadExec, PFNSSMDEVLOADDONE pfnLoadDone)
+{
+ return pDevIns->pHlpR3->pfnSSMRegisterLegacy(pDevIns, pszOldName, pfnLoadPrep, pfnLoadExec, pfnLoadDone);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnTimerCreate
+ */
+DECLINLINE(int) PDMDevHlpTimerCreate(PPDMDEVINS pDevIns, TMCLOCK enmClock, PFNTMTIMERDEV pfnCallback, void *pvUser,
+ uint32_t fFlags, const char *pszDesc, PTMTIMERHANDLE phTimer)
+{
+ return pDevIns->pHlpR3->pfnTimerCreate(pDevIns, enmClock, pfnCallback, pvUser, fFlags, pszDesc, phTimer);
+}
+
+#endif /* IN_RING3 */
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnTimerFromMicro
+ */
+DECLINLINE(uint64_t) PDMDevHlpTimerFromMicro(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint64_t cMicroSecs)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnTimerFromMicro(pDevIns, hTimer, cMicroSecs);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnTimerFromMilli
+ */
+DECLINLINE(uint64_t) PDMDevHlpTimerFromMilli(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint64_t cMilliSecs)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnTimerFromMilli(pDevIns, hTimer, cMilliSecs);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnTimerFromNano
+ */
+DECLINLINE(uint64_t) PDMDevHlpTimerFromNano(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint64_t cNanoSecs)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnTimerFromNano(pDevIns, hTimer, cNanoSecs);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnTimerGet
+ */
+DECLINLINE(uint64_t) PDMDevHlpTimerGet(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnTimerGet(pDevIns, hTimer);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnTimerGetFreq
+ */
+DECLINLINE(uint64_t) PDMDevHlpTimerGetFreq(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnTimerGetFreq(pDevIns, hTimer);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnTimerGetNano
+ */
+DECLINLINE(uint64_t) PDMDevHlpTimerGetNano(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnTimerGetNano(pDevIns, hTimer);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnTimerIsActive
+ */
+DECLINLINE(bool) PDMDevHlpTimerIsActive(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnTimerIsActive(pDevIns, hTimer);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnTimerIsLockOwner
+ */
+DECLINLINE(bool) PDMDevHlpTimerIsLockOwner(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnTimerIsLockOwner(pDevIns, hTimer);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnTimerLockClock
+ */
+DECLINLINE(VBOXSTRICTRC) PDMDevHlpTimerLockClock(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, int rcBusy)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnTimerLockClock(pDevIns, hTimer, rcBusy);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnTimerLockClock2
+ */
+DECLINLINE(VBOXSTRICTRC) PDMDevHlpTimerLockClock2(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, PPDMCRITSECT pCritSect, int rcBusy)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnTimerLockClock2(pDevIns, hTimer, pCritSect, rcBusy);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnTimerSet
+ */
+DECLINLINE(int) PDMDevHlpTimerSet(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint64_t uExpire)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnTimerSet(pDevIns, hTimer, uExpire);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnTimerSetFrequencyHint
+ */
+DECLINLINE(int) PDMDevHlpTimerSetFrequencyHint(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint32_t uHz)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnTimerSetFrequencyHint(pDevIns, hTimer, uHz);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnTimerSetMicro
+ */
+DECLINLINE(int) PDMDevHlpTimerSetMicro(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint64_t cMicrosToNext)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnTimerSetMicro(pDevIns, hTimer, cMicrosToNext);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnTimerSetMillies
+ */
+DECLINLINE(int) PDMDevHlpTimerSetMillies(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint64_t cMilliesToNext)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnTimerSetMillies(pDevIns, hTimer, cMilliesToNext);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnTimerSetNano
+ */
+DECLINLINE(int) PDMDevHlpTimerSetNano(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint64_t cNanosToNext)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnTimerSetNano(pDevIns, hTimer, cNanosToNext);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnTimerSetRelative
+ */
+DECLINLINE(int) PDMDevHlpTimerSetRelative(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint64_t cTicksToNext, uint64_t *pu64Now)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnTimerSetRelative(pDevIns, hTimer, cTicksToNext, pu64Now);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnTimerStop
+ */
+DECLINLINE(int) PDMDevHlpTimerStop(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnTimerStop(pDevIns, hTimer);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnTimerUnlockClock
+ */
+DECLINLINE(void) PDMDevHlpTimerUnlockClock(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer)
+{
+ pDevIns->CTX_SUFF(pHlp)->pfnTimerUnlockClock(pDevIns, hTimer);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnTimerUnlockClock2
+ */
+DECLINLINE(void) PDMDevHlpTimerUnlockClock2(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, PPDMCRITSECT pCritSect)
+{
+ pDevIns->CTX_SUFF(pHlp)->pfnTimerUnlockClock2(pDevIns, hTimer, pCritSect);
+}
+
+#ifdef IN_RING3
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnTimerSetCritSect
+ */
+DECLINLINE(int) PDMDevHlpTimerSetCritSect(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, PPDMCRITSECT pCritSect)
+{
+ return pDevIns->pHlpR3->pfnTimerSetCritSect(pDevIns, hTimer, pCritSect);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnTimerSave
+ */
+DECLINLINE(int) PDMDevHlpTimerSave(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, PSSMHANDLE pSSM)
+{
+ return pDevIns->pHlpR3->pfnTimerSave(pDevIns, hTimer, pSSM);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnTimerLoad
+ */
+DECLINLINE(int) PDMDevHlpTimerLoad(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, PSSMHANDLE pSSM)
+{
+ return pDevIns->pHlpR3->pfnTimerLoad(pDevIns, hTimer, pSSM);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnTimerDestroy
+ */
+DECLINLINE(int) PDMDevHlpTimerDestroy(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer)
+{
+ return pDevIns->pHlpR3->pfnTimerDestroy(pDevIns, hTimer);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnTMUtcNow
+ */
+DECLINLINE(PRTTIMESPEC) PDMDevHlpTMUtcNow(PPDMDEVINS pDevIns, PRTTIMESPEC pTime)
+{
+ return pDevIns->pHlpR3->pfnTMUtcNow(pDevIns, pTime);
+}
+
+#endif
+
+/**
+ * Read physical memory - unknown data usage.
+ *
+ * @returns VINF_SUCCESS (for now).
+ * @param pDevIns The device instance.
+ * @param GCPhys Physical address start reading from.
+ * @param pvBuf Where to put the read bits.
+ * @param cbRead How many bytes to read.
+ * @thread Any thread, but the call may involve the emulation thread.
+ */
+DECLINLINE(int) PDMDevHlpPhysRead(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnPhysRead(pDevIns, GCPhys, pvBuf, cbRead, PDM_DEVHLP_PHYS_RW_F_DEFAULT);
+}
+
+/**
+ * Write to physical memory - unknown data usage.
+ *
+ * @returns VINF_SUCCESS for now, and later maybe VERR_EM_MEMORY.
+ * @param pDevIns The device instance.
+ * @param GCPhys Physical address to write to.
+ * @param pvBuf What to write.
+ * @param cbWrite How many bytes to write.
+ * @thread Any thread, but the call may involve the emulation thread.
+ */
+DECLINLINE(int) PDMDevHlpPhysWrite(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnPhysWrite(pDevIns, GCPhys, pvBuf, cbWrite, PDM_DEVHLP_PHYS_RW_F_DEFAULT);
+}
+
+/**
+ * Read physical memory - reads meta data processed by the device.
+ *
+ * @returns VINF_SUCCESS (for now).
+ * @param pDevIns The device instance.
+ * @param GCPhys Physical address start reading from.
+ * @param pvBuf Where to put the read bits.
+ * @param cbRead How many bytes to read.
+ * @thread Any thread, but the call may involve the emulation thread.
+ */
+DECLINLINE(int) PDMDevHlpPhysReadMeta(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnPhysRead(pDevIns, GCPhys, pvBuf, cbRead, PDM_DEVHLP_PHYS_RW_F_DATA_META);
+}
+
+/**
+ * Write to physical memory - written data was created/altered by the device.
+ *
+ * @returns VINF_SUCCESS for now, and later maybe VERR_EM_MEMORY.
+ * @param pDevIns The device instance.
+ * @param GCPhys Physical address to write to.
+ * @param pvBuf What to write.
+ * @param cbWrite How many bytes to write.
+ * @thread Any thread, but the call may involve the emulation thread.
+ */
+DECLINLINE(int) PDMDevHlpPhysWriteMeta(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnPhysWrite(pDevIns, GCPhys, pvBuf, cbWrite, PDM_DEVHLP_PHYS_RW_F_DATA_META);
+}
+
+/**
+ * Read physical memory - read data will not be touched by the device.
+ *
+ * @returns VINF_SUCCESS (for now).
+ * @param pDevIns The device instance.
+ * @param GCPhys Physical address start reading from.
+ * @param pvBuf Where to put the read bits.
+ * @param cbRead How many bytes to read.
+ * @thread Any thread, but the call may involve the emulation thread.
+ */
+DECLINLINE(int) PDMDevHlpPhysReadUser(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnPhysRead(pDevIns, GCPhys, pvBuf, cbRead, PDM_DEVHLP_PHYS_RW_F_DATA_USER);
+}
+
+/**
+ * Write to physical memory - written data was not touched/created by the device.
+ *
+ * @returns VINF_SUCCESS for now, and later maybe VERR_EM_MEMORY.
+ * @param pDevIns The device instance.
+ * @param GCPhys Physical address to write to.
+ * @param pvBuf What to write.
+ * @param cbWrite How many bytes to write.
+ * @thread Any thread, but the call may involve the emulation thread.
+ */
+DECLINLINE(int) PDMDevHlpPhysWriteUser(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnPhysWrite(pDevIns, GCPhys, pvBuf, cbWrite, PDM_DEVHLP_PHYS_RW_F_DATA_USER);
+}
+
+#ifdef IN_RING3
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnPhysGCPhys2CCPtr
+ */
+DECLINLINE(int) PDMDevHlpPhysGCPhys2CCPtr(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, uint32_t fFlags, void **ppv, PPGMPAGEMAPLOCK pLock)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnPhysGCPhys2CCPtr(pDevIns, GCPhys, fFlags, ppv, pLock);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnPhysGCPhys2CCPtrReadOnly
+ */
+DECLINLINE(int) PDMDevHlpPhysGCPhys2CCPtrReadOnly(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, uint32_t fFlags, void const **ppv,
+ PPGMPAGEMAPLOCK pLock)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnPhysGCPhys2CCPtrReadOnly(pDevIns, GCPhys, fFlags, ppv, pLock);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnPhysReleasePageMappingLock
+ */
+DECLINLINE(void) PDMDevHlpPhysReleasePageMappingLock(PPDMDEVINS pDevIns, PPGMPAGEMAPLOCK pLock)
+{
+ pDevIns->CTX_SUFF(pHlp)->pfnPhysReleasePageMappingLock(pDevIns, pLock);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnPhysBulkGCPhys2CCPtr
+ */
+DECLINLINE(int) PDMDevHlpPhysBulkGCPhys2CCPtr(PPDMDEVINS pDevIns, uint32_t cPages, PCRTGCPHYS paGCPhysPages,
+ uint32_t fFlags, void **papvPages, PPGMPAGEMAPLOCK paLocks)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnPhysBulkGCPhys2CCPtr(pDevIns, cPages, paGCPhysPages, fFlags, papvPages, paLocks);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnPhysBulkGCPhys2CCPtrReadOnly
+ */
+DECLINLINE(int) PDMDevHlpPhysBulkGCPhys2CCPtrReadOnly(PPDMDEVINS pDevIns, uint32_t cPages, PCRTGCPHYS paGCPhysPages,
+ uint32_t fFlags, void const **papvPages, PPGMPAGEMAPLOCK paLocks)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnPhysBulkGCPhys2CCPtrReadOnly(pDevIns, cPages, paGCPhysPages, fFlags, papvPages, paLocks);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnPhysBulkReleasePageMappingLocks
+ */
+DECLINLINE(void) PDMDevHlpPhysBulkReleasePageMappingLocks(PPDMDEVINS pDevIns, uint32_t cPages, PPGMPAGEMAPLOCK paLocks)
+{
+ pDevIns->CTX_SUFF(pHlp)->pfnPhysBulkReleasePageMappingLocks(pDevIns, cPages, paLocks);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnPhysIsGCPhysNormal
+ */
+DECLINLINE(bool) PDMDevHlpPhysIsGCPhysNormal(PPDMDEVINS pDevIns, RTGCPHYS GCPhys)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnPhysIsGCPhysNormal(pDevIns, GCPhys);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnPhysChangeMemBalloon
+ */
+DECLINLINE(int) PDMDevHlpPhysChangeMemBalloon(PPDMDEVINS pDevIns, bool fInflate, unsigned cPages, RTGCPHYS *paPhysPage)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnPhysChangeMemBalloon(pDevIns, fInflate, cPages, paPhysPage);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnCpuGetGuestMicroarch
+ */
+DECLINLINE(CPUMMICROARCH) PDMDevHlpCpuGetGuestMicroarch(PPDMDEVINS pDevIns)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnCpuGetGuestMicroarch(pDevIns);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnCpuGetGuestScalableBusFrequency
+ */
+DECLINLINE(uint64_t) PDMDevHlpCpuGetGuestScalableBusFrequency(PPDMDEVINS pDevIns)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnCpuGetGuestScalableBusFrequency(pDevIns);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnCpuGetGuestAddrWidths
+ */
+DECLINLINE(void) PDMDevHlpCpuGetGuestAddrWidths(PPDMDEVINS pDevIns, uint8_t *pcPhysAddrWidth, uint8_t *pcLinearAddrWidth)
+{
+ pDevIns->CTX_SUFF(pHlp)->pfnCpuGetGuestAddrWidths(pDevIns, pcPhysAddrWidth, pcLinearAddrWidth);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnPhysReadGCVirt
+ */
+DECLINLINE(int) PDMDevHlpPhysReadGCVirt(PPDMDEVINS pDevIns, void *pvDst, RTGCPTR GCVirtSrc, size_t cb)
+{
+ return pDevIns->pHlpR3->pfnPhysReadGCVirt(pDevIns, pvDst, GCVirtSrc, cb);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnPhysWriteGCVirt
+ */
+DECLINLINE(int) PDMDevHlpPhysWriteGCVirt(PPDMDEVINS pDevIns, RTGCPTR GCVirtDst, const void *pvSrc, size_t cb)
+{
+ return pDevIns->pHlpR3->pfnPhysWriteGCVirt(pDevIns, GCVirtDst, pvSrc, cb);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnPhysGCPtr2GCPhys
+ */
+DECLINLINE(int) PDMDevHlpPhysGCPtr2GCPhys(PPDMDEVINS pDevIns, RTGCPTR GCPtr, PRTGCPHYS pGCPhys)
+{
+ return pDevIns->pHlpR3->pfnPhysGCPtr2GCPhys(pDevIns, GCPtr, pGCPhys);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnMMHeapAlloc
+ */
+DECLINLINE(void *) PDMDevHlpMMHeapAlloc(PPDMDEVINS pDevIns, size_t cb)
+{
+ return pDevIns->pHlpR3->pfnMMHeapAlloc(pDevIns, cb);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnMMHeapAllocZ
+ */
+DECLINLINE(void *) PDMDevHlpMMHeapAllocZ(PPDMDEVINS pDevIns, size_t cb)
+{
+ return pDevIns->pHlpR3->pfnMMHeapAllocZ(pDevIns, cb);
+}
+
+/**
+ * Allocating string printf.
+ *
+ * @returns Pointer to the string.
+ * @param pDevIns The device instance.
+ * @param enmTag The statistics tag.
+ * @param pszFormat The format string.
+ * @param ... Format arguments.
+ */
+DECLINLINE(char *) RT_IPRT_FORMAT_ATTR(2, 3) PDMDevHlpMMHeapAPrintf(PPDMDEVINS pDevIns, MMTAG enmTag, const char *pszFormat, ...)
+{
+ va_list va;
+ va_start(va, pszFormat);
+ char *psz = pDevIns->pHlpR3->pfnMMHeapAPrintfV(pDevIns, enmTag, pszFormat, va);
+ va_end(va);
+
+ return psz;
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnMMHeapFree
+ */
+DECLINLINE(void) PDMDevHlpMMHeapFree(PPDMDEVINS pDevIns, void *pv)
+{
+ pDevIns->pHlpR3->pfnMMHeapFree(pDevIns, pv);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnMMPhysGetRamSize
+ */
+DECLINLINE(uint64_t) PDMDevHlpMMPhysGetRamSize(PPDMDEVINS pDevIns)
+{
+ return pDevIns->pHlpR3->pfnMMPhysGetRamSize(pDevIns);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnMMPhysGetRamSizeBelow4GB
+ */
+DECLINLINE(uint32_t) PDMDevHlpMMPhysGetRamSizeBelow4GB(PPDMDEVINS pDevIns)
+{
+ return pDevIns->pHlpR3->pfnMMPhysGetRamSizeBelow4GB(pDevIns);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnMMPhysGetRamSizeAbove4GB
+ */
+DECLINLINE(uint64_t) PDMDevHlpMMPhysGetRamSizeAbove4GB(PPDMDEVINS pDevIns)
+{
+ return pDevIns->pHlpR3->pfnMMPhysGetRamSizeAbove4GB(pDevIns);
+}
+#endif /* IN_RING3 */
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnVMState
+ */
+DECLINLINE(VMSTATE) PDMDevHlpVMState(PPDMDEVINS pDevIns)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnVMState(pDevIns);
+}
+
+#ifdef IN_RING3
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnVMTeleportedAndNotFullyResumedYet
+ */
+DECLINLINE(bool) PDMDevHlpVMTeleportedAndNotFullyResumedYet(PPDMDEVINS pDevIns)
+{
+ return pDevIns->pHlpR3->pfnVMTeleportedAndNotFullyResumedYet(pDevIns);
+}
+
+/**
+ * Set the VM error message
+ *
+ * @returns rc.
+ * @param pDevIns The device instance.
+ * @param rc VBox status code.
+ * @param SRC_POS Use RT_SRC_POS.
+ * @param pszFormat Error message format string.
+ * @param ... Error message arguments.
+ * @sa VMSetError
+ */
+DECLINLINE(int) RT_IPRT_FORMAT_ATTR(6, 7) PDMDevHlpVMSetError(PPDMDEVINS pDevIns, const int rc, RT_SRC_POS_DECL,
+ const char *pszFormat, ...)
+{
+ va_list va;
+ va_start(va, pszFormat);
+ pDevIns->CTX_SUFF(pHlp)->pfnVMSetErrorV(pDevIns, rc, RT_SRC_POS_ARGS, pszFormat, va);
+ va_end(va);
+ return rc;
+}
+
+/**
+ * Set the VM runtime error message
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param fFlags The action flags. See VMSETRTERR_FLAGS_*.
+ * @param pszErrorId Error ID string.
+ * @param pszFormat Error message format string.
+ * @param ... Error message arguments.
+ * @sa VMSetRuntimeError
+ */
+DECLINLINE(int) RT_IPRT_FORMAT_ATTR(4, 5) PDMDevHlpVMSetRuntimeError(PPDMDEVINS pDevIns, uint32_t fFlags, const char *pszErrorId,
+ const char *pszFormat, ...)
+{
+ va_list va;
+ int rc;
+ va_start(va, pszFormat);
+ rc = pDevIns->CTX_SUFF(pHlp)->pfnVMSetRuntimeErrorV(pDevIns, fFlags, pszErrorId, pszFormat, va);
+ va_end(va);
+ return rc;
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnVMWaitForDeviceReady
+ */
+DECLINLINE(int) PDMDevHlpVMWaitForDeviceReady(PPDMDEVINS pDevIns, VMCPUID idCpu)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnVMWaitForDeviceReady(pDevIns, idCpu);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnVMNotifyCpuDeviceReady
+ */
+DECLINLINE(int) PDMDevHlpVMNotifyCpuDeviceReady(PPDMDEVINS pDevIns, VMCPUID idCpu)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnVMNotifyCpuDeviceReady(pDevIns, idCpu);
+}
+
+/**
+ * Convenience wrapper for VMR3ReqCallU.
+ *
+ * This assumes (1) you're calling a function that returns an VBox status code
+ * and that you do not wish to wait for it to complete.
+ *
+ * @returns VBox status code returned by VMR3ReqCallVU.
+ *
+ * @param pDevIns The device instance.
+ * @param idDstCpu The destination CPU(s). Either a specific CPU ID or
+ * one of the following special values:
+ * VMCPUID_ANY, VMCPUID_ANY_QUEUE, VMCPUID_ALL or VMCPUID_ALL_REVERSE.
+ * @param pfnFunction Pointer to the function to call.
+ * @param cArgs Number of arguments following in the ellipsis.
+ * @param ... Argument list.
+ *
+ * @remarks See remarks on VMR3ReqCallVU.
+ */
+DECLINLINE(int) PDMDevHlpVMReqCallNoWait(PPDMDEVINS pDevIns, VMCPUID idDstCpu, PFNRT pfnFunction, unsigned cArgs, ...)
+{
+ va_list Args;
+ va_start(Args, cArgs);
+ int rc = pDevIns->CTX_SUFF(pHlp)->pfnVMReqCallNoWaitV(pDevIns, idDstCpu, pfnFunction, cArgs, Args);
+ va_end(Args);
+ return rc;
+}
+
+/**
+ * Convenience wrapper for VMR3ReqCallU.
+ *
+ * This assumes (1) you're calling a function that returns void, (2) that you
+ * wish to wait for ever for it to return, and (3) that it's priority request
+ * that can be safely be handled during async suspend and power off.
+ *
+ * @returns VBox status code of VMR3ReqCallVU.
+ *
+ * @param pDevIns The device instance.
+ * @param idDstCpu The destination CPU(s). Either a specific CPU ID or
+ * one of the following special values:
+ * VMCPUID_ANY, VMCPUID_ANY_QUEUE, VMCPUID_ALL or VMCPUID_ALL_REVERSE.
+ * @param pfnFunction Pointer to the function to call.
+ * @param cArgs Number of arguments following in the ellipsis.
+ * @param ... Argument list.
+ *
+ * @remarks See remarks on VMR3ReqCallVU.
+ */
+DECLINLINE(int) PDMDevHlpVMReqPriorityCallWait(PPDMDEVINS pDevIns, VMCPUID idDstCpu, PFNRT pfnFunction, unsigned cArgs, ...)
+{
+ va_list Args;
+ va_start(Args, cArgs);
+ int rc = pDevIns->CTX_SUFF(pHlp)->pfnVMReqPriorityCallWaitV(pDevIns, idDstCpu, pfnFunction, cArgs, Args);
+ va_end(Args);
+ return rc;
+}
+
+#endif /* IN_RING3 */
+
+/**
+ * VBOX_STRICT wrapper for pHlp->pfnDBGFStopV.
+ *
+ * @returns VBox status code which must be passed up to the VMM. This will be
+ * VINF_SUCCESS in non-strict builds.
+ * @param pDevIns The device instance.
+ * @param SRC_POS Use RT_SRC_POS.
+ * @param pszFormat Message. (optional)
+ * @param ... Message parameters.
+ */
+DECLINLINE(int) RT_IPRT_FORMAT_ATTR(5, 6) PDMDevHlpDBGFStop(PPDMDEVINS pDevIns, RT_SRC_POS_DECL, const char *pszFormat, ...)
+{
+#ifdef VBOX_STRICT
+# ifdef IN_RING3
+ int rc;
+ va_list args;
+ va_start(args, pszFormat);
+ rc = pDevIns->pHlpR3->pfnDBGFStopV(pDevIns, RT_SRC_POS_ARGS, pszFormat, args);
+ va_end(args);
+ return rc;
+# else
+ NOREF(pDevIns);
+ NOREF(pszFile);
+ NOREF(iLine);
+ NOREF(pszFunction);
+ NOREF(pszFormat);
+ return VINF_EM_DBG_STOP;
+# endif
+#else
+ NOREF(pDevIns);
+ NOREF(pszFile);
+ NOREF(iLine);
+ NOREF(pszFunction);
+ NOREF(pszFormat);
+ return VINF_SUCCESS;
+#endif
+}
+
+#ifdef IN_RING3
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnDBGFInfoRegister
+ */
+DECLINLINE(int) PDMDevHlpDBGFInfoRegister(PPDMDEVINS pDevIns, const char *pszName, const char *pszDesc, PFNDBGFHANDLERDEV pfnHandler)
+{
+ return pDevIns->pHlpR3->pfnDBGFInfoRegister(pDevIns, pszName, pszDesc, pfnHandler);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnDBGFInfoRegisterArgv
+ */
+DECLINLINE(int) PDMDevHlpDBGFInfoRegisterArgv(PPDMDEVINS pDevIns, const char *pszName, const char *pszDesc, PFNDBGFINFOARGVDEV pfnHandler)
+{
+ return pDevIns->pHlpR3->pfnDBGFInfoRegisterArgv(pDevIns, pszName, pszDesc, pfnHandler);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnDBGFRegRegister
+ */
+DECLINLINE(int) PDMDevHlpDBGFRegRegister(PPDMDEVINS pDevIns, PCDBGFREGDESC paRegisters)
+{
+ return pDevIns->pHlpR3->pfnDBGFRegRegister(pDevIns, paRegisters);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnDBGFReportBugCheck
+ */
+DECLINLINE(VBOXSTRICTRC) PDMDevHlpDBGFReportBugCheck(PPDMDEVINS pDevIns, DBGFEVENTTYPE enmEvent, uint64_t uBugCheck,
+ uint64_t uP1, uint64_t uP2, uint64_t uP3, uint64_t uP4)
+{
+ return pDevIns->pHlpR3->pfnDBGFReportBugCheck(pDevIns, enmEvent, uBugCheck, uP1, uP2, uP3, uP4);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnDBGFCoreWrite
+ */
+DECLINLINE(int) PDMDevHlpDBGFCoreWrite(PPDMDEVINS pDevIns, const char *pszFilename, bool fReplaceFile)
+{
+ return pDevIns->pHlpR3->pfnDBGFCoreWrite(pDevIns, pszFilename, fReplaceFile);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnDBGFInfoLogHlp
+ */
+DECLINLINE(PCDBGFINFOHLP) PDMDevHlpDBGFInfoLogHlp(PPDMDEVINS pDevIns)
+{
+ return pDevIns->pHlpR3->pfnDBGFInfoLogHlp(pDevIns);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnDBGFRegNmQueryU64
+ */
+DECLINLINE(int) PDMDevHlpDBGFRegNmQueryU64(PPDMDEVINS pDevIns, VMCPUID idDefCpu, const char *pszReg, uint64_t *pu64)
+{
+ return pDevIns->pHlpR3->pfnDBGFRegNmQueryU64(pDevIns, idDefCpu, pszReg, pu64);
+}
+
+ /**
+ * Format a set of registers.
+ *
+ * This is restricted to registers from one CPU, that specified by @a idCpu.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param idCpu The CPU ID of any CPU registers that may be
+ * printed, pass VMCPUID_ANY if not applicable.
+ * @param pszBuf The output buffer.
+ * @param cbBuf The size of the output buffer.
+ * @param pszFormat The format string. Register names are given by
+ * %VR{name}, they take no arguments.
+ * @param ... Argument list.
+ */
+DECLINLINE(int) RT_IPRT_FORMAT_ATTR(4, 5) PDMDevHlpDBGFRegPrintf(PPDMDEVINS pDevIns, VMCPUID idCpu, char *pszBuf, size_t cbBuf,
+ const char *pszFormat, ...)
+{
+ va_list Args;
+ va_start(Args, pszFormat);
+ int rc = pDevIns->pHlpR3->pfnDBGFRegPrintfV(pDevIns, idCpu, pszBuf, cbBuf, pszFormat, Args);
+ va_end(Args);
+ return rc;
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnSTAMRegister
+ */
+DECLINLINE(void) PDMDevHlpSTAMRegister(PPDMDEVINS pDevIns, void *pvSample, STAMTYPE enmType, const char *pszName, STAMUNIT enmUnit, const char *pszDesc)
+{
+ pDevIns->pHlpR3->pfnSTAMRegister(pDevIns, pvSample, enmType, pszName, enmUnit, pszDesc);
+}
+
+/**
+ * Same as pfnSTAMRegister except that the name is specified in a
+ * RTStrPrintf like fashion.
+ *
+ * @returns VBox status.
+ * @param pDevIns Device instance of the DMA.
+ * @param pvSample Pointer to the sample.
+ * @param enmType Sample type. This indicates what pvSample is
+ * pointing at.
+ * @param enmVisibility Visibility type specifying whether unused
+ * statistics should be visible or not.
+ * @param enmUnit Sample unit.
+ * @param pszDesc Sample description.
+ * @param pszName Sample name format string, unix path style. If
+ * this does not start with a '/', the default
+ * prefix will be prepended, otherwise it will be
+ * used as-is.
+ * @param ... Arguments to the format string.
+ */
+DECLINLINE(void) RT_IPRT_FORMAT_ATTR(7, 8) PDMDevHlpSTAMRegisterF(PPDMDEVINS pDevIns, void *pvSample, STAMTYPE enmType,
+ STAMVISIBILITY enmVisibility, STAMUNIT enmUnit,
+ const char *pszDesc, const char *pszName, ...)
+{
+ va_list va;
+ va_start(va, pszName);
+ pDevIns->pHlpR3->pfnSTAMRegisterV(pDevIns, pvSample, enmType, enmVisibility, enmUnit, pszDesc, pszName, va);
+ va_end(va);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnSTAMDeregisterByPrefix
+ */
+DECLINLINE(int) PDMDevHlpSTAMDeregisterByPrefix(PPDMDEVINS pDevIns, const char *pszPrefix)
+{
+ return pDevIns->pHlpR3->pfnSTAMDeregisterByPrefix(pDevIns, pszPrefix);
+}
+
+/**
+ * Registers the device with the default PCI bus.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param pPciDev The PCI device structure.
+ * This must be kept in the instance data.
+ * The PCI configuration must be initialized before registration.
+ */
+DECLINLINE(int) PDMDevHlpPCIRegister(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev)
+{
+ return pDevIns->pHlpR3->pfnPCIRegister(pDevIns, pPciDev, 0 /*fFlags*/,
+ PDMPCIDEVREG_DEV_NO_FIRST_UNUSED, PDMPCIDEVREG_FUN_NO_FIRST_UNUSED, NULL);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnPCIRegister
+ */
+DECLINLINE(int) PDMDevHlpPCIRegisterEx(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t fFlags,
+ uint8_t uPciDevNo, uint8_t uPciFunNo, const char *pszName)
+{
+ return pDevIns->pHlpR3->pfnPCIRegister(pDevIns, pPciDev, fFlags, uPciDevNo, uPciFunNo, pszName);
+}
+
+/**
+ * Initialize MSI emulation support for the first PCI device.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param pMsiReg MSI emulation registration structure.
+ */
+DECLINLINE(int) PDMDevHlpPCIRegisterMsi(PPDMDEVINS pDevIns, PPDMMSIREG pMsiReg)
+{
+ return pDevIns->pHlpR3->pfnPCIRegisterMsi(pDevIns, NULL, pMsiReg);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnPCIRegisterMsi
+ */
+DECLINLINE(int) PDMDevHlpPCIRegisterMsiEx(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, PPDMMSIREG pMsiReg)
+{
+ return pDevIns->pHlpR3->pfnPCIRegisterMsi(pDevIns, pPciDev, pMsiReg);
+}
+
+/**
+ * Registers a I/O port region for the default PCI device.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param iRegion The region number.
+ * @param cbRegion Size of the region.
+ * @param hIoPorts Handle to the I/O port region.
+ */
+DECLINLINE(int) PDMDevHlpPCIIORegionRegisterIo(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS cbRegion, IOMIOPORTHANDLE hIoPorts)
+{
+ return pDevIns->pHlpR3->pfnPCIIORegionRegister(pDevIns, NULL, iRegion, cbRegion, PCI_ADDRESS_SPACE_IO,
+ PDMPCIDEV_IORGN_F_IOPORT_HANDLE | PDMPCIDEV_IORGN_F_NEW_STYLE, hIoPorts, NULL);
+}
+
+/**
+ * Registers a I/O port region for the default PCI device, custom map/unmap.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param iRegion The region number.
+ * @param cbRegion Size of the region.
+ * @param pfnMapUnmap Callback for doing the mapping, optional. The
+ * callback will be invoked holding only the PDM lock.
+ * The device lock will _not_ be taken (due to lock
+ * order).
+ */
+DECLINLINE(int) PDMDevHlpPCIIORegionRegisterIoCustom(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS cbRegion,
+ PFNPCIIOREGIONMAP pfnMapUnmap)
+{
+ return pDevIns->pHlpR3->pfnPCIIORegionRegister(pDevIns, NULL, iRegion, cbRegion, PCI_ADDRESS_SPACE_IO,
+ PDMPCIDEV_IORGN_F_NO_HANDLE | PDMPCIDEV_IORGN_F_NEW_STYLE,
+ UINT64_MAX, pfnMapUnmap);
+}
+
+/**
+ * Combines PDMDevHlpIoPortCreate and PDMDevHlpPCIIORegionRegisterIo, creating
+ * and registering an I/O port region for the default PCI device.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance to register the ports with.
+ * @param cPorts The count of I/O ports in the region (the size).
+ * @param iPciRegion The PCI device region.
+ * @param pfnOut Pointer to function which is gonna handle OUT
+ * operations. Optional.
+ * @param pfnIn Pointer to function which is gonna handle IN operations.
+ * Optional.
+ * @param pvUser User argument to pass to the callbacks.
+ * @param pszDesc Pointer to description string. This must not be freed.
+ * @param paExtDescs Extended per-port descriptions, optional. Partial range
+ * coverage is allowed. This must not be freed.
+ * @param phIoPorts Where to return the I/O port range handle.
+ *
+ */
+DECLINLINE(int) PDMDevHlpPCIIORegionCreateIo(PPDMDEVINS pDevIns, uint32_t iPciRegion, RTIOPORT cPorts,
+ PFNIOMIOPORTNEWOUT pfnOut, PFNIOMIOPORTNEWIN pfnIn, void *pvUser,
+ const char *pszDesc, PCIOMIOPORTDESC paExtDescs, PIOMIOPORTHANDLE phIoPorts)
+
+{
+ int rc = pDevIns->pHlpR3->pfnIoPortCreateEx(pDevIns, cPorts, 0 /*fFlags*/, pDevIns->apPciDevs[0], iPciRegion << 16,
+ pfnOut, pfnIn, NULL, NULL, pvUser, pszDesc, paExtDescs, phIoPorts);
+ if (RT_SUCCESS(rc))
+ rc = pDevIns->pHlpR3->pfnPCIIORegionRegister(pDevIns, pDevIns->apPciDevs[0], iPciRegion, cPorts, PCI_ADDRESS_SPACE_IO,
+ PDMPCIDEV_IORGN_F_IOPORT_HANDLE | PDMPCIDEV_IORGN_F_NEW_STYLE,
+ *phIoPorts, NULL /*pfnMapUnmap*/);
+ return rc;
+}
+
+/**
+ * Registers an MMIO region for the default PCI device.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param iRegion The region number.
+ * @param cbRegion Size of the region.
+ * @param enmType PCI_ADDRESS_SPACE_MEM or
+ * PCI_ADDRESS_SPACE_MEM_PREFETCH, optionally or-ing in
+ * PCI_ADDRESS_SPACE_BAR64 or PCI_ADDRESS_SPACE_BAR32.
+ * @param hMmioRegion Handle to the MMIO region.
+ * @param pfnMapUnmap Callback for doing the mapping, optional. The
+ * callback will be invoked holding only the PDM lock.
+ * The device lock will _not_ be taken (due to lock
+ * order).
+ */
+DECLINLINE(int) PDMDevHlpPCIIORegionRegisterMmio(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS cbRegion, PCIADDRESSSPACE enmType,
+ IOMMMIOHANDLE hMmioRegion, PFNPCIIOREGIONMAP pfnMapUnmap)
+{
+ return pDevIns->pHlpR3->pfnPCIIORegionRegister(pDevIns, NULL, iRegion, cbRegion, enmType,
+ PDMPCIDEV_IORGN_F_MMIO_HANDLE | PDMPCIDEV_IORGN_F_NEW_STYLE,
+ hMmioRegion, pfnMapUnmap);
+}
+
+/**
+ * Registers an MMIO region for the default PCI device, extended version.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param pPciDev The PCI device structure.
+ * @param iRegion The region number.
+ * @param cbRegion Size of the region.
+ * @param enmType PCI_ADDRESS_SPACE_MEM or
+ * PCI_ADDRESS_SPACE_MEM_PREFETCH, optionally or-ing in
+ * PCI_ADDRESS_SPACE_BAR64 or PCI_ADDRESS_SPACE_BAR32.
+ * @param hMmioRegion Handle to the MMIO region.
+ * @param pfnMapUnmap Callback for doing the mapping, optional. The
+ * callback will be invoked holding only the PDM lock.
+ * The device lock will _not_ be taken (due to lock
+ * order).
+ */
+DECLINLINE(int) PDMDevHlpPCIIORegionRegisterMmioEx(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t iRegion,
+ RTGCPHYS cbRegion, PCIADDRESSSPACE enmType, IOMMMIOHANDLE hMmioRegion,
+ PFNPCIIOREGIONMAP pfnMapUnmap)
+{
+ return pDevIns->pHlpR3->pfnPCIIORegionRegister(pDevIns, pPciDev, iRegion, cbRegion, enmType,
+ PDMPCIDEV_IORGN_F_MMIO_HANDLE | PDMPCIDEV_IORGN_F_NEW_STYLE,
+ hMmioRegion, pfnMapUnmap);
+}
+
+/**
+ * Combines PDMDevHlpMmioCreate and PDMDevHlpPCIIORegionRegisterMmio, creating
+ * and registering an MMIO region for the default PCI device.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance to register the ports with.
+ * @param cbRegion The size of the region in bytes.
+ * @param iPciRegion The PCI device region.
+ * @param enmType PCI_ADDRESS_SPACE_MEM or
+ * PCI_ADDRESS_SPACE_MEM_PREFETCH, optionally or-ing in
+ * PCI_ADDRESS_SPACE_BAR64 or PCI_ADDRESS_SPACE_BAR32.
+ * @param fFlags Flags, IOMMMIO_FLAGS_XXX.
+ * @param pfnWrite Pointer to function which is gonna handle Write
+ * operations.
+ * @param pfnRead Pointer to function which is gonna handle Read
+ * operations.
+ * @param pvUser User argument to pass to the callbacks.
+ * @param pszDesc Pointer to description string. This must not be freed.
+ * @param phRegion Where to return the MMIO region handle.
+ *
+ */
+DECLINLINE(int) PDMDevHlpPCIIORegionCreateMmio(PPDMDEVINS pDevIns, uint32_t iPciRegion, RTGCPHYS cbRegion, PCIADDRESSSPACE enmType,
+ PFNIOMMMIONEWWRITE pfnWrite, PFNIOMMMIONEWREAD pfnRead, void *pvUser,
+ uint32_t fFlags, const char *pszDesc, PIOMMMIOHANDLE phRegion)
+
+{
+ int rc = pDevIns->pHlpR3->pfnMmioCreateEx(pDevIns, cbRegion, fFlags, pDevIns->apPciDevs[0], iPciRegion << 16,
+ pfnWrite, pfnRead, NULL /*pfnFill*/, pvUser, pszDesc, phRegion);
+ if (RT_SUCCESS(rc))
+ rc = pDevIns->pHlpR3->pfnPCIIORegionRegister(pDevIns, pDevIns->apPciDevs[0], iPciRegion, cbRegion, enmType,
+ PDMPCIDEV_IORGN_F_MMIO_HANDLE | PDMPCIDEV_IORGN_F_NEW_STYLE,
+ *phRegion, NULL /*pfnMapUnmap*/);
+ return rc;
+}
+
+
+/**
+ * Registers an MMIO2 region for the default PCI device.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param iRegion The region number.
+ * @param cbRegion Size of the region.
+ * @param enmType PCI_ADDRESS_SPACE_MEM or
+ * PCI_ADDRESS_SPACE_MEM_PREFETCH, optionally or-ing in
+ * PCI_ADDRESS_SPACE_BAR64 or PCI_ADDRESS_SPACE_BAR32.
+ * @param hMmio2Region Handle to the MMIO2 region.
+ */
+DECLINLINE(int) PDMDevHlpPCIIORegionRegisterMmio2(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS cbRegion,
+ PCIADDRESSSPACE enmType, PGMMMIO2HANDLE hMmio2Region)
+{
+ return pDevIns->pHlpR3->pfnPCIIORegionRegister(pDevIns, NULL, iRegion, cbRegion, enmType,
+ PDMPCIDEV_IORGN_F_MMIO2_HANDLE | PDMPCIDEV_IORGN_F_NEW_STYLE,
+ hMmio2Region, NULL);
+}
+
+/**
+ * Combines PDMDevHlpMmio2Create and PDMDevHlpPCIIORegionRegisterMmio2, creating
+ * and registering an MMIO2 region for the default PCI device, extended edition.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance to register the ports with.
+ * @param cbRegion The size of the region in bytes.
+ * @param iPciRegion The PCI device region.
+ * @param enmType PCI_ADDRESS_SPACE_MEM or
+ * PCI_ADDRESS_SPACE_MEM_PREFETCH, optionally or-ing in
+ * PCI_ADDRESS_SPACE_BAR64 or PCI_ADDRESS_SPACE_BAR32.
+ * @param pszDesc Pointer to description string. This must not be freed.
+ * @param ppvMapping Where to store the address of the ring-3 mapping of
+ * the memory.
+ * @param phRegion Where to return the MMIO2 region handle.
+ *
+ */
+DECLINLINE(int) PDMDevHlpPCIIORegionCreateMmio2(PPDMDEVINS pDevIns, uint32_t iPciRegion, RTGCPHYS cbRegion,
+ PCIADDRESSSPACE enmType, const char *pszDesc,
+ void **ppvMapping, PPGMMMIO2HANDLE phRegion)
+
+{
+ int rc = pDevIns->pHlpR3->pfnMmio2Create(pDevIns, pDevIns->apPciDevs[0], iPciRegion << 16, cbRegion, 0 /*fFlags*/,
+ pszDesc, ppvMapping, phRegion);
+ if (RT_SUCCESS(rc))
+ rc = pDevIns->pHlpR3->pfnPCIIORegionRegister(pDevIns, pDevIns->apPciDevs[0], iPciRegion, cbRegion, enmType,
+ PDMPCIDEV_IORGN_F_MMIO2_HANDLE | PDMPCIDEV_IORGN_F_NEW_STYLE,
+ *phRegion, NULL /*pfnCallback*/);
+ return rc;
+}
+
+/**
+ * Combines PDMDevHlpMmio2Create and PDMDevHlpPCIIORegionRegisterMmio2, creating
+ * and registering an MMIO2 region for the default PCI device.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance to register the ports with.
+ * @param cbRegion The size of the region in bytes.
+ * @param iPciRegion The PCI device region.
+ * @param enmType PCI_ADDRESS_SPACE_MEM or
+ * PCI_ADDRESS_SPACE_MEM_PREFETCH, optionally or-ing in
+ * PCI_ADDRESS_SPACE_BAR64 or PCI_ADDRESS_SPACE_BAR32.
+ * @param fMmio2Flags PGMPHYS_MMIO2_FLAGS_XXX (see pgm.h).
+ * @param pfnMapUnmap Callback for doing the mapping, optional. The
+ * callback will be invoked holding only the PDM lock.
+ * The device lock will _not_ be taken (due to lock
+ * order).
+ * @param pszDesc Pointer to description string. This must not be freed.
+ * @param ppvMapping Where to store the address of the ring-3 mapping of
+ * the memory.
+ * @param phRegion Where to return the MMIO2 region handle.
+ *
+ */
+DECLINLINE(int) PDMDevHlpPCIIORegionCreateMmio2Ex(PPDMDEVINS pDevIns, uint32_t iPciRegion, RTGCPHYS cbRegion,
+ PCIADDRESSSPACE enmType, uint32_t fMmio2Flags, PFNPCIIOREGIONMAP pfnMapUnmap,
+ const char *pszDesc, void **ppvMapping, PPGMMMIO2HANDLE phRegion)
+
+{
+ int rc = pDevIns->pHlpR3->pfnMmio2Create(pDevIns, pDevIns->apPciDevs[0], iPciRegion << 16, cbRegion, fMmio2Flags,
+ pszDesc, ppvMapping, phRegion);
+ if (RT_SUCCESS(rc))
+ rc = pDevIns->pHlpR3->pfnPCIIORegionRegister(pDevIns, pDevIns->apPciDevs[0], iPciRegion, cbRegion, enmType,
+ PDMPCIDEV_IORGN_F_MMIO2_HANDLE | PDMPCIDEV_IORGN_F_NEW_STYLE,
+ *phRegion, pfnMapUnmap);
+ return rc;
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnPCIInterceptConfigAccesses
+ */
+DECLINLINE(int) PDMDevHlpPCIInterceptConfigAccesses(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev,
+ PFNPCICONFIGREAD pfnRead, PFNPCICONFIGWRITE pfnWrite)
+{
+ return pDevIns->pHlpR3->pfnPCIInterceptConfigAccesses(pDevIns, pPciDev, pfnRead, pfnWrite);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnPCIConfigRead
+ */
+DECLINLINE(VBOXSTRICTRC) PDMDevHlpPCIConfigRead(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t uAddress,
+ unsigned cb, uint32_t *pu32Value)
+{
+ return pDevIns->pHlpR3->pfnPCIConfigRead(pDevIns, pPciDev, uAddress, cb, pu32Value);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnPCIConfigWrite
+ */
+DECLINLINE(VBOXSTRICTRC) PDMDevHlpPCIConfigWrite(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t uAddress,
+ unsigned cb, uint32_t u32Value)
+{
+ return pDevIns->pHlpR3->pfnPCIConfigWrite(pDevIns, pPciDev, uAddress, cb, u32Value);
+}
+
+#endif /* IN_RING3 */
+
+/**
+ * Bus master physical memory read from the default PCI device.
+ *
+ * @returns VINF_SUCCESS or VERR_PGM_PCI_PHYS_READ_BM_DISABLED, later maybe
+ * VERR_EM_MEMORY. The informational status shall NOT be propagated!
+ * @param pDevIns The device instance.
+ * @param GCPhys Physical address start reading from.
+ * @param pvBuf Where to put the read bits.
+ * @param cbRead How many bytes to read.
+ * @thread Any thread, but the call may involve the emulation thread.
+ */
+DECLINLINE(int) PDMDevHlpPCIPhysRead(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnPCIPhysRead(pDevIns, NULL, GCPhys, pvBuf, cbRead, PDM_DEVHLP_PHYS_RW_F_DEFAULT);
+}
+
+/**
+ * Bus master physical memory read - unknown data usage.
+ *
+ * @returns VINF_SUCCESS or VERR_PGM_PCI_PHYS_READ_BM_DISABLED, later maybe
+ * VERR_EM_MEMORY. The informational status shall NOT be propagated!
+ * @param pDevIns The device instance.
+ * @param pPciDev The PCI device structure. If NULL the default
+ * PCI device for this device instance is used.
+ * @param GCPhys Physical address start reading from.
+ * @param pvBuf Where to put the read bits.
+ * @param cbRead How many bytes to read.
+ * @thread Any thread, but the call may involve the emulation thread.
+ */
+DECLINLINE(int) PDMDevHlpPCIPhysReadEx(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnPCIPhysRead(pDevIns, pPciDev, GCPhys, pvBuf, cbRead, PDM_DEVHLP_PHYS_RW_F_DEFAULT);
+}
+
+/**
+ * Bus master physical memory read from the default PCI device.
+ *
+ * @returns VINF_SUCCESS or VERR_PGM_PCI_PHYS_READ_BM_DISABLED, later maybe
+ * VERR_EM_MEMORY. The informational status shall NOT be propagated!
+ * @param pDevIns The device instance.
+ * @param GCPhys Physical address start reading from.
+ * @param pvBuf Where to put the read bits.
+ * @param cbRead How many bytes to read.
+ * @thread Any thread, but the call may involve the emulation thread.
+ */
+DECLINLINE(int) PDMDevHlpPCIPhysReadMeta(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnPCIPhysRead(pDevIns, NULL, GCPhys, pvBuf, cbRead, PDM_DEVHLP_PHYS_RW_F_DATA_META);
+}
+
+/**
+ * Bus master physical memory read - reads meta data processed by the device.
+ *
+ * @returns VINF_SUCCESS or VERR_PGM_PCI_PHYS_READ_BM_DISABLED, later maybe
+ * VERR_EM_MEMORY. The informational status shall NOT be propagated!
+ * @param pDevIns The device instance.
+ * @param pPciDev The PCI device structure. If NULL the default
+ * PCI device for this device instance is used.
+ * @param GCPhys Physical address start reading from.
+ * @param pvBuf Where to put the read bits.
+ * @param cbRead How many bytes to read.
+ * @thread Any thread, but the call may involve the emulation thread.
+ */
+DECLINLINE(int) PDMDevHlpPCIPhysReadMetaEx(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnPCIPhysRead(pDevIns, pPciDev, GCPhys, pvBuf, cbRead, PDM_DEVHLP_PHYS_RW_F_DATA_META);
+}
+
+/**
+ * Bus master physical memory read from the default PCI device - read data will not be touched by the device.
+ *
+ * @returns VINF_SUCCESS or VERR_PGM_PCI_PHYS_READ_BM_DISABLED, later maybe
+ * VERR_EM_MEMORY. The informational status shall NOT be propagated!
+ * @param pDevIns The device instance.
+ * @param GCPhys Physical address start reading from.
+ * @param pvBuf Where to put the read bits.
+ * @param cbRead How many bytes to read.
+ * @thread Any thread, but the call may involve the emulation thread.
+ */
+DECLINLINE(int) PDMDevHlpPCIPhysReadUser(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnPCIPhysRead(pDevIns, NULL, GCPhys, pvBuf, cbRead, PDM_DEVHLP_PHYS_RW_F_DATA_USER);
+}
+
+/**
+ * Bus master physical memory read - read data will not be touched by the device.
+ *
+ * @returns VINF_SUCCESS or VERR_PGM_PCI_PHYS_READ_BM_DISABLED, later maybe
+ * VERR_EM_MEMORY. The informational status shall NOT be propagated!
+ * @param pDevIns The device instance.
+ * @param pPciDev The PCI device structure. If NULL the default
+ * PCI device for this device instance is used.
+ * @param GCPhys Physical address start reading from.
+ * @param pvBuf Where to put the read bits.
+ * @param cbRead How many bytes to read.
+ * @thread Any thread, but the call may involve the emulation thread.
+ */
+DECLINLINE(int) PDMDevHlpPCIPhysReadUserEx(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnPCIPhysRead(pDevIns, pPciDev, GCPhys, pvBuf, cbRead, PDM_DEVHLP_PHYS_RW_F_DATA_USER);
+}
+
+/**
+ * Bus master physical memory write from the default PCI device - unknown data usage.
+ *
+ * @returns VINF_SUCCESS or VERR_PGM_PCI_PHYS_WRITE_BM_DISABLED, later maybe
+ * VERR_EM_MEMORY. The informational status shall NOT be propagated!
+ * @param pDevIns The device instance.
+ * @param GCPhys Physical address to write to.
+ * @param pvBuf What to write.
+ * @param cbWrite How many bytes to write.
+ * @thread Any thread, but the call may involve the emulation thread.
+ */
+DECLINLINE(int) PDMDevHlpPCIPhysWrite(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnPCIPhysWrite(pDevIns, NULL, GCPhys, pvBuf, cbWrite, PDM_DEVHLP_PHYS_RW_F_DEFAULT);
+}
+
+/**
+ * Bus master physical memory write - unknown data usage.
+ *
+ * @returns VINF_SUCCESS or VERR_PGM_PCI_PHYS_WRITE_BM_DISABLED, later maybe
+ * VERR_EM_MEMORY. The informational status shall NOT be propagated!
+ * @param pDevIns The device instance.
+ * @param pPciDev The PCI device structure. If NULL the default
+ * PCI device for this device instance is used.
+ * @param GCPhys Physical address to write to.
+ * @param pvBuf What to write.
+ * @param cbWrite How many bytes to write.
+ * @thread Any thread, but the call may involve the emulation thread.
+ */
+DECLINLINE(int) PDMDevHlpPCIPhysWriteEx(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnPCIPhysWrite(pDevIns, pPciDev, GCPhys, pvBuf, cbWrite, PDM_DEVHLP_PHYS_RW_F_DEFAULT);
+}
+
+/**
+ * Bus master physical memory write from the default PCI device.
+ *
+ * @returns VINF_SUCCESS or VERR_PGM_PCI_PHYS_WRITE_BM_DISABLED, later maybe
+ * VERR_EM_MEMORY. The informational status shall NOT be propagated!
+ * @param pDevIns The device instance.
+ * @param GCPhys Physical address to write to.
+ * @param pvBuf What to write.
+ * @param cbWrite How many bytes to write.
+ * @thread Any thread, but the call may involve the emulation thread.
+ */
+DECLINLINE(int) PDMDevHlpPCIPhysWriteMeta(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnPCIPhysWrite(pDevIns, NULL, GCPhys, pvBuf, cbWrite, PDM_DEVHLP_PHYS_RW_F_DATA_META);
+}
+
+/**
+ * Bus master physical memory write - written data was created/altered by the device.
+ *
+ * @returns VINF_SUCCESS or VERR_PGM_PCI_PHYS_WRITE_BM_DISABLED, later maybe
+ * VERR_EM_MEMORY. The informational status shall NOT be propagated!
+ * @param pDevIns The device instance.
+ * @param pPciDev The PCI device structure. If NULL the default
+ * PCI device for this device instance is used.
+ * @param GCPhys Physical address to write to.
+ * @param pvBuf What to write.
+ * @param cbWrite How many bytes to write.
+ * @thread Any thread, but the call may involve the emulation thread.
+ */
+DECLINLINE(int) PDMDevHlpPCIPhysWriteMetaEx(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnPCIPhysWrite(pDevIns, pPciDev, GCPhys, pvBuf, cbWrite, PDM_DEVHLP_PHYS_RW_F_DATA_META);
+}
+
+/**
+ * Bus master physical memory write from the default PCI device.
+ *
+ * @returns VINF_SUCCESS or VERR_PGM_PCI_PHYS_WRITE_BM_DISABLED, later maybe
+ * VERR_EM_MEMORY. The informational status shall NOT be propagated!
+ * @param pDevIns The device instance.
+ * @param GCPhys Physical address to write to.
+ * @param pvBuf What to write.
+ * @param cbWrite How many bytes to write.
+ * @thread Any thread, but the call may involve the emulation thread.
+ */
+DECLINLINE(int) PDMDevHlpPCIPhysWriteUser(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnPCIPhysWrite(pDevIns, NULL, GCPhys, pvBuf, cbWrite, PDM_DEVHLP_PHYS_RW_F_DATA_USER);
+}
+
+/**
+ * Bus master physical memory write - written data was not touched/created by the device.
+ *
+ * @returns VINF_SUCCESS or VERR_PGM_PCI_PHYS_WRITE_BM_DISABLED, later maybe
+ * VERR_EM_MEMORY. The informational status shall NOT be propagated!
+ * @param pDevIns The device instance.
+ * @param pPciDev The PCI device structure. If NULL the default
+ * PCI device for this device instance is used.
+ * @param GCPhys Physical address to write to.
+ * @param pvBuf What to write.
+ * @param cbWrite How many bytes to write.
+ * @thread Any thread, but the call may involve the emulation thread.
+ */
+DECLINLINE(int) PDMDevHlpPCIPhysWriteUserEx(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnPCIPhysWrite(pDevIns, pPciDev, GCPhys, pvBuf, cbWrite, PDM_DEVHLP_PHYS_RW_F_DATA_USER);
+}
+
+#ifdef IN_RING3
+/**
+ * @copydoc PDMDEVHLPR3::pfnPCIPhysGCPhys2CCPtr
+ */
+DECLINLINE(int) PDMDevHlpPCIPhysGCPhys2CCPtr(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, RTGCPHYS GCPhys, uint32_t fFlags,
+ void **ppv, PPGMPAGEMAPLOCK pLock)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnPCIPhysGCPhys2CCPtr(pDevIns, pPciDev, GCPhys, fFlags, ppv, pLock);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnPCIPhysGCPhys2CCPtrReadOnly
+ */
+DECLINLINE(int) PDMDevHlpPCIPhysGCPhys2CCPtrReadOnly(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, RTGCPHYS GCPhys, uint32_t fFlags,
+ void const **ppv, PPGMPAGEMAPLOCK pLock)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnPCIPhysGCPhys2CCPtrReadOnly(pDevIns, pPciDev, GCPhys, fFlags, ppv, pLock);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnPCIPhysBulkGCPhys2CCPtr
+ */
+DECLINLINE(int) PDMDevHlpPCIPhysBulkGCPhys2CCPtr(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t cPages,
+ PCRTGCPHYS paGCPhysPages, uint32_t fFlags, void **papvPages,
+ PPGMPAGEMAPLOCK paLocks)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnPCIPhysBulkGCPhys2CCPtr(pDevIns, pPciDev, cPages, paGCPhysPages, fFlags, papvPages,
+ paLocks);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnPCIPhysBulkGCPhys2CCPtrReadOnly
+ */
+DECLINLINE(int) PDMDevHlpPCIPhysBulkGCPhys2CCPtrReadOnly(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t cPages,
+ PCRTGCPHYS paGCPhysPages, uint32_t fFlags, void const **papvPages,
+ PPGMPAGEMAPLOCK paLocks)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnPCIPhysBulkGCPhys2CCPtrReadOnly(pDevIns, pPciDev, cPages, paGCPhysPages, fFlags,
+ papvPages, paLocks);
+}
+#endif /* IN_RING3 */
+
+/**
+ * Sets the IRQ for the default PCI device.
+ *
+ * @param pDevIns The device instance.
+ * @param iIrq IRQ number to set.
+ * @param iLevel IRQ level. See the PDM_IRQ_LEVEL_* \#defines.
+ * @thread Any thread, but will involve the emulation thread.
+ */
+DECLINLINE(void) PDMDevHlpPCISetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel)
+{
+ pDevIns->CTX_SUFF(pHlp)->pfnPCISetIrq(pDevIns, NULL, iIrq, iLevel);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnPCISetIrq
+ */
+DECLINLINE(void) PDMDevHlpPCISetIrqEx(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, int iIrq, int iLevel)
+{
+ pDevIns->CTX_SUFF(pHlp)->pfnPCISetIrq(pDevIns, pPciDev, iIrq, iLevel);
+}
+
+/**
+ * Sets the IRQ for the given PCI device, but doesn't wait for EMT to process
+ * the request when not called from EMT.
+ *
+ * @param pDevIns The device instance.
+ * @param iIrq IRQ number to set.
+ * @param iLevel IRQ level.
+ * @thread Any thread, but will involve the emulation thread.
+ */
+DECLINLINE(void) PDMDevHlpPCISetIrqNoWait(PPDMDEVINS pDevIns, int iIrq, int iLevel)
+{
+ pDevIns->CTX_SUFF(pHlp)->pfnPCISetIrq(pDevIns, NULL, iIrq, iLevel);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnPCISetIrqNoWait
+ */
+DECLINLINE(void) PDMDevHlpPCISetIrqNoWaitEx(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, int iIrq, int iLevel)
+{
+ pDevIns->CTX_SUFF(pHlp)->pfnPCISetIrq(pDevIns, pPciDev, iIrq, iLevel);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnISASetIrq
+ */
+DECLINLINE(void) PDMDevHlpISASetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel)
+{
+ pDevIns->CTX_SUFF(pHlp)->pfnISASetIrq(pDevIns, iIrq, iLevel);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnISASetIrqNoWait
+ */
+DECLINLINE(void) PDMDevHlpISASetIrqNoWait(PPDMDEVINS pDevIns, int iIrq, int iLevel)
+{
+ pDevIns->CTX_SUFF(pHlp)->pfnISASetIrq(pDevIns, iIrq, iLevel);
+}
+
+#ifdef IN_RING3
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnDriverAttach
+ */
+DECLINLINE(int) PDMDevHlpDriverAttach(PPDMDEVINS pDevIns, uint32_t iLun, PPDMIBASE pBaseInterface, PPDMIBASE *ppBaseInterface, const char *pszDesc)
+{
+ return pDevIns->pHlpR3->pfnDriverAttach(pDevIns, iLun, pBaseInterface, ppBaseInterface, pszDesc);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnDriverDetach
+ */
+DECLINLINE(int) PDMDevHlpDriverDetach(PPDMDEVINS pDevIns, PPDMDRVINS pDrvIns, uint32_t fFlags)
+{
+ return pDevIns->pHlpR3->pfnDriverDetach(pDevIns, pDrvIns, fFlags);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnDriverReconfigure
+ */
+DECLINLINE(int) PDMDevHlpDriverReconfigure(PPDMDEVINS pDevIns, uint32_t iLun, uint32_t cDepth,
+ const char * const *papszDrivers, PCFGMNODE *papConfigs, uint32_t fFlags)
+{
+ return pDevIns->pHlpR3->pfnDriverReconfigure(pDevIns, iLun, cDepth, papszDrivers, papConfigs, fFlags);
+}
+
+/**
+ * Reconfigures with a single driver reattachement, no config, noflags.
+ * @sa PDMDevHlpDriverReconfigure
+ */
+DECLINLINE(int) PDMDevHlpDriverReconfigure1(PPDMDEVINS pDevIns, uint32_t iLun, const char *pszDriver0)
+{
+ return pDevIns->pHlpR3->pfnDriverReconfigure(pDevIns, iLun, 1, &pszDriver0, NULL, 0);
+}
+
+/**
+ * Reconfigures with a two drivers reattachement, no config, noflags.
+ * @sa PDMDevHlpDriverReconfigure
+ */
+DECLINLINE(int) PDMDevHlpDriverReconfigure2(PPDMDEVINS pDevIns, uint32_t iLun, const char *pszDriver0, const char *pszDriver1)
+{
+ char const * apszDrivers[2];
+ apszDrivers[0] = pszDriver0;
+ apszDrivers[1] = pszDriver1;
+ return pDevIns->pHlpR3->pfnDriverReconfigure(pDevIns, iLun, 2, apszDrivers, NULL, 0);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnQueueCreate
+ */
+DECLINLINE(int) PDMDevHlpQueueCreate(PPDMDEVINS pDevIns, size_t cbItem, uint32_t cItems, uint32_t cMilliesInterval,
+ PFNPDMQUEUEDEV pfnCallback, bool fRZEnabled, const char *pszName, PDMQUEUEHANDLE *phQueue)
+{
+ return pDevIns->pHlpR3->pfnQueueCreate(pDevIns, cbItem, cItems, cMilliesInterval, pfnCallback, fRZEnabled, pszName, phQueue);
+}
+
+#endif /* IN_RING3 */
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnQueueAlloc
+ */
+DECLINLINE(PPDMQUEUEITEMCORE) PDMDevHlpQueueAlloc(PPDMDEVINS pDevIns, PDMQUEUEHANDLE hQueue)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnQueueAlloc(pDevIns, hQueue);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnQueueInsert
+ */
+DECLINLINE(int) PDMDevHlpQueueInsert(PPDMDEVINS pDevIns, PDMQUEUEHANDLE hQueue, PPDMQUEUEITEMCORE pItem)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnQueueInsert(pDevIns, hQueue, pItem);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnQueueFlushIfNecessary
+ */
+DECLINLINE(bool) PDMDevHlpQueueFlushIfNecessary(PPDMDEVINS pDevIns, PDMQUEUEHANDLE hQueue)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnQueueFlushIfNecessary(pDevIns, hQueue);
+}
+
+#ifdef IN_RING3
+/**
+ * @copydoc PDMDEVHLPR3::pfnTaskCreate
+ */
+DECLINLINE(int) PDMDevHlpTaskCreate(PPDMDEVINS pDevIns, uint32_t fFlags, const char *pszName,
+ PFNPDMTASKDEV pfnCallback, void *pvUser, PDMTASKHANDLE *phTask)
+{
+ return pDevIns->pHlpR3->pfnTaskCreate(pDevIns, fFlags, pszName, pfnCallback, pvUser, phTask);
+}
+#endif
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnTaskTrigger
+ */
+DECLINLINE(int) PDMDevHlpTaskTrigger(PPDMDEVINS pDevIns, PDMTASKHANDLE hTask)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnTaskTrigger(pDevIns, hTask);
+}
+
+#ifdef IN_RING3
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnSUPSemEventCreate
+ */
+DECLINLINE(int) PDMDevHlpSUPSemEventCreate(PPDMDEVINS pDevIns, PSUPSEMEVENT phEvent)
+{
+ return pDevIns->pHlpR3->pfnSUPSemEventCreate(pDevIns, phEvent);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnSUPSemEventClose
+ */
+DECLINLINE(int) PDMDevHlpSUPSemEventClose(PPDMDEVINS pDevIns, SUPSEMEVENT hEvent)
+{
+ return pDevIns->pHlpR3->pfnSUPSemEventClose(pDevIns, hEvent);
+}
+
+#endif /* IN_RING3 */
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnSUPSemEventSignal
+ */
+DECLINLINE(int) PDMDevHlpSUPSemEventSignal(PPDMDEVINS pDevIns, SUPSEMEVENT hEvent)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnSUPSemEventSignal(pDevIns, hEvent);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnSUPSemEventWaitNoResume
+ */
+DECLINLINE(int) PDMDevHlpSUPSemEventWaitNoResume(PPDMDEVINS pDevIns, SUPSEMEVENT hEvent, uint32_t cMillies)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnSUPSemEventWaitNoResume(pDevIns, hEvent, cMillies);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnSUPSemEventWaitNsAbsIntr
+ */
+DECLINLINE(int) PDMDevHlpSUPSemEventWaitNsAbsIntr(PPDMDEVINS pDevIns, SUPSEMEVENT hEvent, uint64_t uNsTimeout)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnSUPSemEventWaitNsAbsIntr(pDevIns, hEvent, uNsTimeout);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnSUPSemEventWaitNsRelIntr
+ */
+DECLINLINE(int) PDMDevHlpSUPSemEventWaitNsRelIntr(PPDMDEVINS pDevIns, SUPSEMEVENT hEvent, uint64_t cNsTimeout)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnSUPSemEventWaitNsRelIntr(pDevIns, hEvent, cNsTimeout);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnSUPSemEventGetResolution
+ */
+DECLINLINE(uint32_t) PDMDevHlpSUPSemEventGetResolution(PPDMDEVINS pDevIns)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnSUPSemEventGetResolution(pDevIns);
+}
+
+#ifdef IN_RING3
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnSUPSemEventMultiCreate
+ */
+DECLINLINE(int) PDMDevHlpSUPSemEventMultiCreate(PPDMDEVINS pDevIns, PSUPSEMEVENTMULTI phEventMulti)
+{
+ return pDevIns->pHlpR3->pfnSUPSemEventMultiCreate(pDevIns, phEventMulti);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnSUPSemEventMultiClose
+ */
+DECLINLINE(int) PDMDevHlpSUPSemEventMultiClose(PPDMDEVINS pDevIns, SUPSEMEVENTMULTI hEventMulti)
+{
+ return pDevIns->pHlpR3->pfnSUPSemEventMultiClose(pDevIns, hEventMulti);
+}
+
+#endif /* IN_RING3 */
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnSUPSemEventMultiSignal
+ */
+DECLINLINE(int) PDMDevHlpSUPSemEventMultiSignal(PPDMDEVINS pDevIns, SUPSEMEVENTMULTI hEventMulti)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnSUPSemEventMultiSignal(pDevIns, hEventMulti);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnSUPSemEventMultiReset
+ */
+DECLINLINE(int) PDMDevHlpSUPSemEventMultiReset(PPDMDEVINS pDevIns, SUPSEMEVENTMULTI hEventMulti)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnSUPSemEventMultiReset(pDevIns, hEventMulti);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnSUPSemEventMultiWaitNoResume
+ */
+DECLINLINE(int) PDMDevHlpSUPSemEventMultiWaitNoResume(PPDMDEVINS pDevIns, SUPSEMEVENTMULTI hEventMulti, uint32_t cMillies)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnSUPSemEventMultiWaitNsRelIntr(pDevIns, hEventMulti, cMillies);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnSUPSemEventMultiWaitNsAbsIntr
+ */
+DECLINLINE(int) PDMDevHlpSUPSemEventMultiWaitNsAbsIntr(PPDMDEVINS pDevIns, SUPSEMEVENTMULTI hEventMulti, uint64_t uNsTimeout)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnSUPSemEventMultiWaitNsAbsIntr(pDevIns, hEventMulti, uNsTimeout);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnSUPSemEventMultiWaitNsRelIntr
+ */
+DECLINLINE(int) PDMDevHlpSUPSemEventMultiWaitNsRelIntr(PPDMDEVINS pDevIns, SUPSEMEVENTMULTI hEventMulti, uint64_t cNsTimeout)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnSUPSemEventMultiWaitNsRelIntr(pDevIns, hEventMulti, cNsTimeout);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnSUPSemEventMultiGetResolution
+ */
+DECLINLINE(uint32_t) PDMDevHlpSUPSemEventMultiGetResolution(PPDMDEVINS pDevIns)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnSUPSemEventMultiGetResolution(pDevIns);
+}
+
+#ifdef IN_RING3
+
+/**
+ * Initializes a PDM critical section.
+ *
+ * The PDM critical sections are derived from the IPRT critical sections, but
+ * works in RC and R0 as well.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param pCritSect Pointer to the critical section.
+ * @param SRC_POS Use RT_SRC_POS.
+ * @param pszNameFmt Format string for naming the critical section.
+ * For statistics and lock validation.
+ * @param ... Arguments for the format string.
+ */
+DECLINLINE(int) RT_IPRT_FORMAT_ATTR(6, 7) PDMDevHlpCritSectInit(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, RT_SRC_POS_DECL,
+ const char *pszNameFmt, ...)
+{
+ int rc;
+ va_list va;
+ va_start(va, pszNameFmt);
+ rc = pDevIns->pHlpR3->pfnCritSectInit(pDevIns, pCritSect, RT_SRC_POS_ARGS, pszNameFmt, va);
+ va_end(va);
+ return rc;
+}
+
+#endif /* IN_RING3 */
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnCritSectGetNop
+ */
+DECLINLINE(PPDMCRITSECT) PDMDevHlpCritSectGetNop(PPDMDEVINS pDevIns)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnCritSectGetNop(pDevIns);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnSetDeviceCritSect
+ */
+DECLINLINE(int) PDMDevHlpSetDeviceCritSect(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnSetDeviceCritSect(pDevIns, pCritSect);
+}
+
+/**
+ * Enters a PDM critical section.
+ *
+ * @returns VINF_SUCCESS if entered successfully.
+ * @returns rcBusy when encountering a busy critical section in RC/R0.
+ * @retval VERR_SEM_DESTROYED if the critical section is delete before or
+ * during the operation.
+ *
+ * @param pDevIns The device instance.
+ * @param pCritSect The PDM critical section to enter.
+ * @param rcBusy The status code to return when we're in RC or R0
+ * and the section is busy. Pass VINF_SUCCESS to
+ * acquired the critical section thru a ring-3
+ * call if necessary.
+ *
+ * @note Even callers setting @a rcBusy to VINF_SUCCESS must either handle
+ * possible failures in ring-0 or at least apply
+ * PDM_CRITSECT_RELEASE_ASSERT_RC_DEV() to the return value of this
+ * function.
+ *
+ * @sa PDMCritSectEnter
+ */
+DECLINLINE(DECL_CHECK_RETURN(int)) PDMDevHlpCritSectEnter(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, int rcBusy)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnCritSectEnter(pDevIns, pCritSect, rcBusy);
+}
+
+/**
+ * Enters a PDM critical section, with location information for debugging.
+ *
+ * @returns VINF_SUCCESS if entered successfully.
+ * @returns rcBusy when encountering a busy critical section in RC/R0.
+ * @retval VERR_SEM_DESTROYED if the critical section is delete before or
+ * during the operation.
+ *
+ * @param pDevIns The device instance.
+ * @param pCritSect The PDM critical section to enter.
+ * @param rcBusy The status code to return when we're in RC or R0
+ * and the section is busy. Pass VINF_SUCCESS to
+ * acquired the critical section thru a ring-3
+ * call if necessary.
+ * @param uId Some kind of locking location ID. Typically a
+ * return address up the stack. Optional (0).
+ * @param SRC_POS The source position where to lock is being
+ * acquired from. Optional.
+ * @sa PDMCritSectEnterDebug
+ */
+DECLINLINE(DECL_CHECK_RETURN(int))
+PDMDevHlpCritSectEnterDebug(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, int rcBusy, RTHCUINTPTR uId, RT_SRC_POS_DECL)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnCritSectEnterDebug(pDevIns, pCritSect, rcBusy, uId, RT_SRC_POS_ARGS);
+}
+
+/**
+ * Try enter a critical section.
+ *
+ * @retval VINF_SUCCESS on success.
+ * @retval VERR_SEM_BUSY if the critsect was owned.
+ * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
+ * @retval VERR_SEM_DESTROYED if the critical section is delete before or
+ * during the operation.
+ *
+ * @param pDevIns The device instance.
+ * @param pCritSect The critical section.
+ * @sa PDMCritSectTryEnter
+ */
+DECLINLINE(DECL_CHECK_RETURN(int))
+PDMDevHlpCritSectTryEnter(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnCritSectTryEnter(pDevIns, pCritSect);
+}
+
+/**
+ * Try enter a critical section, with location information for debugging.
+ *
+ * @retval VINF_SUCCESS on success.
+ * @retval VERR_SEM_BUSY if the critsect was owned.
+ * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
+ * @retval VERR_SEM_DESTROYED if the critical section is delete before or
+ * during the operation.
+ *
+ * @param pDevIns The device instance.
+ * @param pCritSect The critical section.
+ * @param uId Some kind of locking location ID. Typically a
+ * return address up the stack. Optional (0).
+ * @param SRC_POS The source position where to lock is being
+ * acquired from. Optional.
+ * @sa PDMCritSectTryEnterDebug
+ */
+DECLINLINE(DECL_CHECK_RETURN(int))
+PDMDevHlpCritSectTryEnterDebug(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, RTHCUINTPTR uId, RT_SRC_POS_DECL)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnCritSectTryEnterDebug(pDevIns, pCritSect, uId, RT_SRC_POS_ARGS);
+}
+
+/**
+ * Leaves a critical section entered with PDMCritSectEnter().
+ *
+ * @returns Indication whether we really exited the critical section.
+ * @retval VINF_SUCCESS if we really exited.
+ * @retval VINF_SEM_NESTED if we only reduced the nesting count.
+ * @retval VERR_NOT_OWNER if you somehow ignore release assertions.
+ *
+ * @param pDevIns The device instance.
+ * @param pCritSect The PDM critical section to leave.
+ * @sa PDMCritSectLeave
+ */
+DECLINLINE(int) PDMDevHlpCritSectLeave(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnCritSectLeave(pDevIns, pCritSect);
+}
+
+/**
+ * @see PDMCritSectIsOwner
+ */
+DECLINLINE(bool) PDMDevHlpCritSectIsOwner(PPDMDEVINS pDevIns, PCPDMCRITSECT pCritSect)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnCritSectIsOwner(pDevIns, pCritSect);
+}
+
+/**
+ * @see PDMCritSectIsInitialized
+ */
+DECLINLINE(bool) PDMDevHlpCritSectIsInitialized(PPDMDEVINS pDevIns, PCPDMCRITSECT pCritSect)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnCritSectIsInitialized(pDevIns, pCritSect);
+}
+
+/**
+ * @see PDMCritSectHasWaiters
+ */
+DECLINLINE(bool) PDMDevHlpCritSectHasWaiters(PPDMDEVINS pDevIns, PCPDMCRITSECT pCritSect)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnCritSectHasWaiters(pDevIns, pCritSect);
+}
+
+/**
+ * @see PDMCritSectGetRecursion
+ */
+DECLINLINE(uint32_t) PDMDevHlpCritSectGetRecursion(PPDMDEVINS pDevIns, PCPDMCRITSECT pCritSect)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnCritSectGetRecursion(pDevIns, pCritSect);
+}
+
+#if defined(IN_RING3) || defined(IN_RING0)
+/**
+ * @see PDMHCCritSectScheduleExitEvent
+ */
+DECLINLINE(int) PDMDevHlpCritSectScheduleExitEvent(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, SUPSEMEVENT hEventToSignal)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnCritSectScheduleExitEvent(pDevIns, pCritSect, hEventToSignal);
+}
+#endif
+
+/* Strict build: Remap the two enter calls to the debug versions. */
+#ifdef VBOX_STRICT
+# ifdef IPRT_INCLUDED_asm_h
+# define PDMDevHlpCritSectEnter(pDevIns, pCritSect, rcBusy) PDMDevHlpCritSectEnterDebug((pDevIns), (pCritSect), (rcBusy), (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
+# define PDMDevHlpCritSectTryEnter(pDevIns, pCritSect) PDMDevHlpCritSectTryEnterDebug((pDevIns), (pCritSect), (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
+# else
+# define PDMDevHlpCritSectEnter(pDevIns, pCritSect, rcBusy) PDMDevHlpCritSectEnterDebug((pDevIns), (pCritSect), (rcBusy), 0, RT_SRC_POS)
+# define PDMDevHlpCritSectTryEnter(pDevIns, pCritSect) PDMDevHlpCritSectTryEnterDebug((pDevIns), (pCritSect), 0, RT_SRC_POS)
+# endif
+#endif
+
+#if defined(IN_RING3) || defined(DOXYGEN_RUNNING)
+
+/**
+ * Deletes the critical section.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param pCritSect The PDM critical section to destroy.
+ * @sa PDMR3CritSectDelete
+ */
+DECLINLINE(int) PDMDevHlpCritSectDelete(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect)
+{
+ return pDevIns->pHlpR3->pfnCritSectDelete(pDevIns, pCritSect);
+}
+
+/**
+ * Initializes a PDM read/write critical section.
+ *
+ * The PDM read/write critical sections are derived from the IPRT critical
+ * sections, but works in RC and R0 as well.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param pCritSect Pointer to the read/write critical section.
+ * @param SRC_POS Use RT_SRC_POS.
+ * @param pszNameFmt Format string for naming the critical section.
+ * For statistics and lock validation.
+ * @param ... Arguments for the format string.
+ */
+DECLINLINE(int) RT_IPRT_FORMAT_ATTR(6, 7) PDMDevHlpCritSectRwInit(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect, RT_SRC_POS_DECL,
+ const char *pszNameFmt, ...)
+{
+ int rc;
+ va_list va;
+ va_start(va, pszNameFmt);
+ rc = pDevIns->pHlpR3->pfnCritSectRwInit(pDevIns, pCritSect, RT_SRC_POS_ARGS, pszNameFmt, va);
+ va_end(va);
+ return rc;
+}
+
+/**
+ * Deletes the read/write critical section.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param pCritSect The PDM read/write critical section to destroy.
+ * @sa PDMR3CritSectRwDelete
+ */
+DECLINLINE(int) PDMDevHlpCritSectRwDelete(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect)
+{
+ return pDevIns->pHlpR3->pfnCritSectRwDelete(pDevIns, pCritSect);
+}
+
+#endif /* IN_RING3 */
+
+/**
+ * @sa PDMCritSectRwEnterShared, PDM_CRITSECT_RELEASE_ASSERT_RC_DEV
+ */
+DECLINLINE(DECL_CHECK_RETURN(int)) PDMDevHlpCritSectRwEnterShared(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect, int rcBusy)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnCritSectRwEnterShared(pDevIns, pCritSect, rcBusy);
+}
+
+/**
+ * @sa PDMCritSectRwEnterSharedDebug, PDM_CRITSECT_RELEASE_ASSERT_RC_DEV
+ */
+DECLINLINE(DECL_CHECK_RETURN(int))
+PDMDevHlpCritSectRwEnterSharedDebug(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect, int rcBusy, RTHCUINTPTR uId, RT_SRC_POS_DECL)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnCritSectRwEnterSharedDebug(pDevIns, pCritSect, rcBusy, uId, RT_SRC_POS_ARGS);
+}
+
+/**
+ * @sa PDMCritSectRwTryEnterShared
+ */
+DECLINLINE(DECL_CHECK_RETURN(int))
+PDMDevHlpCritSectRwTryEnterShared(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnCritSectRwTryEnterShared(pDevIns, pCritSect);
+}
+
+/**
+ * @sa PDMCritSectRwTryEnterSharedDebug
+ */
+DECLINLINE(DECL_CHECK_RETURN(int))
+PDMDevHlpCritSectRwTryEnterSharedDebug(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect, RTHCUINTPTR uId, RT_SRC_POS_DECL)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnCritSectRwTryEnterSharedDebug(pDevIns, pCritSect, uId, RT_SRC_POS_ARGS);
+}
+
+/**
+ * @sa PDMCritSectRwLeaveShared
+ */
+DECLINLINE(int) PDMDevHlpCritSectRwLeaveShared(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnCritSectRwLeaveShared(pDevIns, pCritSect);
+}
+
+/**
+ * @sa PDMCritSectRwEnterExcl, PDM_CRITSECT_RELEASE_ASSERT_RC_DEV
+ */
+DECLINLINE(DECL_CHECK_RETURN(int)) PDMDevHlpCritSectRwEnterExcl(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect, int rcBusy)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnCritSectRwEnterExcl(pDevIns, pCritSect, rcBusy);
+}
+
+/**
+ * @sa PDMCritSectRwEnterExclDebug, PDM_CRITSECT_RELEASE_ASSERT_RC_DEV
+ */
+DECLINLINE(DECL_CHECK_RETURN(int))
+PDMDevHlpCritSectRwEnterExclDebug(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect, int rcBusy, RTHCUINTPTR uId, RT_SRC_POS_DECL)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnCritSectRwEnterExclDebug(pDevIns, pCritSect, rcBusy, uId, RT_SRC_POS_ARGS);
+}
+
+/**
+ * @sa PDMCritSectRwTryEnterExcl
+ */
+DECLINLINE(DECL_CHECK_RETURN(int))
+PDMDevHlpCritSectRwTryEnterExcl(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnCritSectRwTryEnterExcl(pDevIns, pCritSect);
+}
+
+/**
+ * @sa PDMCritSectRwTryEnterExclDebug
+ */
+DECLINLINE(DECL_CHECK_RETURN(int))
+PDMDevHlpCritSectRwTryEnterExclDebug(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect, RTHCUINTPTR uId, RT_SRC_POS_DECL)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnCritSectRwTryEnterExclDebug(pDevIns, pCritSect, uId, RT_SRC_POS_ARGS);
+}
+
+/**
+ * @sa PDMCritSectRwLeaveExcl
+ */
+DECLINLINE(int) PDMDevHlpCritSectRwLeaveExcl(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnCritSectRwLeaveExcl(pDevIns, pCritSect);
+}
+
+/**
+ * @see PDMCritSectRwIsWriteOwner
+ */
+DECLINLINE(bool) PDMDevHlpCritSectRwIsWriteOwner(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnCritSectRwIsWriteOwner(pDevIns, pCritSect);
+}
+
+/**
+ * @see PDMCritSectRwIsReadOwner
+ */
+DECLINLINE(bool) PDMDevHlpCritSectRwIsReadOwner(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect, bool fWannaHear)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnCritSectRwIsReadOwner(pDevIns, pCritSect, fWannaHear);
+}
+
+/**
+ * @see PDMCritSectRwGetWriteRecursion
+ */
+DECLINLINE(uint32_t) PDMDevHlpCritSectRwGetWriteRecursion(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnCritSectRwGetWriteRecursion(pDevIns, pCritSect);
+}
+
+/**
+ * @see PDMCritSectRwGetWriterReadRecursion
+ */
+DECLINLINE(uint32_t) PDMDevHlpCritSectRwGetWriterReadRecursion(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnCritSectRwGetWriterReadRecursion(pDevIns, pCritSect);
+}
+
+/**
+ * @see PDMCritSectRwGetReadCount
+ */
+DECLINLINE(uint32_t) PDMDevHlpCritSectRwGetReadCount(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnCritSectRwGetReadCount(pDevIns, pCritSect);
+}
+
+/**
+ * @see PDMCritSectRwIsInitialized
+ */
+DECLINLINE(bool) PDMDevHlpCritSectRwIsInitialized(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnCritSectRwIsInitialized(pDevIns, pCritSect);
+}
+
+/* Strict build: Remap the two enter calls to the debug versions. */
+#ifdef VBOX_STRICT
+# ifdef IPRT_INCLUDED_asm_h
+# define PDMDevHlpCritSectRwEnterShared(pDevIns, pCritSect, rcBusy) PDMDevHlpCritSectRwEnterSharedDebug((pDevIns), (pCritSect), (rcBusy), (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
+# define PDMDevHlpCritSectRwTryEnterShared(pDevIns, pCritSect) PDMDevHlpCritSectRwTryEnterSharedDebug((pDevIns), (pCritSect), (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
+# define PDMDevHlpCritSectRwEnterExcl(pDevIns, pCritSect, rcBusy) PDMDevHlpCritSectRwEnterExclDebug((pDevIns), (pCritSect), (rcBusy), (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
+# define PDMDevHlpCritSectRwTryEnterExcl(pDevIns, pCritSect) PDMDevHlpCritSectRwTryEnterExclDebug((pDevIns), (pCritSect), (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
+# else
+# define PDMDevHlpCritSectRwEnterShared(pDevIns, pCritSect, rcBusy) PDMDevHlpCritSectRwEnterSharedDebug((pDevIns), (pCritSect), (rcBusy), 0, RT_SRC_POS)
+# define PDMDevHlpCritSectRwTryEnterShared(pDevIns, pCritSect) PDMDevHlpCritSectRwTryEnterSharedDebug((pDevIns), (pCritSect), 0, RT_SRC_POS)
+# define PDMDevHlpCritSectRwEnterExcl(pDevIns, pCritSect, rcBusy) PDMDevHlpCritSectRwEnterExclDebug((pDevIns), (pCritSect), (rcBusy), 0, RT_SRC_POS)
+# define PDMDevHlpCritSectRwTryEnterExcl(pDevIns, pCritSect) PDMDevHlpCritSectRwTryEnterExclDebug((pDevIns), (pCritSect), 0, RT_SRC_POS)
+# endif
+#endif
+
+#if defined(IN_RING3) || defined(DOXYGEN_RUNNING)
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnThreadCreate
+ */
+DECLINLINE(int) PDMDevHlpThreadCreate(PPDMDEVINS pDevIns, PPPDMTHREAD ppThread, void *pvUser, PFNPDMTHREADDEV pfnThread,
+ PFNPDMTHREADWAKEUPDEV pfnWakeup, size_t cbStack, RTTHREADTYPE enmType, const char *pszName)
+{
+ return pDevIns->pHlpR3->pfnThreadCreate(pDevIns, ppThread, pvUser, pfnThread, pfnWakeup, cbStack, enmType, pszName);
+}
+
+/**
+ * @copydoc PDMR3ThreadDestroy
+ * @param pDevIns The device instance.
+ */
+DECLINLINE(int) PDMDevHlpThreadDestroy(PPDMDEVINS pDevIns, PPDMTHREAD pThread, int *pRcThread)
+{
+ return pDevIns->pHlpR3->pfnThreadDestroy(pThread, pRcThread);
+}
+
+/**
+ * @copydoc PDMR3ThreadIAmSuspending
+ * @param pDevIns The device instance.
+ */
+DECLINLINE(int) PDMDevHlpThreadIAmSuspending(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
+{
+ return pDevIns->pHlpR3->pfnThreadIAmSuspending(pThread);
+}
+
+/**
+ * @copydoc PDMR3ThreadIAmRunning
+ * @param pDevIns The device instance.
+ */
+DECLINLINE(int) PDMDevHlpThreadIAmRunning(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
+{
+ return pDevIns->pHlpR3->pfnThreadIAmRunning(pThread);
+}
+
+/**
+ * @copydoc PDMR3ThreadSleep
+ * @param pDevIns The device instance.
+ */
+DECLINLINE(int) PDMDevHlpThreadSleep(PPDMDEVINS pDevIns, PPDMTHREAD pThread, RTMSINTERVAL cMillies)
+{
+ return pDevIns->pHlpR3->pfnThreadSleep(pThread, cMillies);
+}
+
+/**
+ * @copydoc PDMR3ThreadSuspend
+ * @param pDevIns The device instance.
+ */
+DECLINLINE(int) PDMDevHlpThreadSuspend(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
+{
+ return pDevIns->pHlpR3->pfnThreadSuspend(pThread);
+}
+
+/**
+ * @copydoc PDMR3ThreadResume
+ * @param pDevIns The device instance.
+ */
+DECLINLINE(int) PDMDevHlpThreadResume(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
+{
+ return pDevIns->pHlpR3->pfnThreadResume(pThread);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnSetAsyncNotification
+ */
+DECLINLINE(int) PDMDevHlpSetAsyncNotification(PPDMDEVINS pDevIns, PFNPDMDEVASYNCNOTIFY pfnAsyncNotify)
+{
+ return pDevIns->pHlpR3->pfnSetAsyncNotification(pDevIns, pfnAsyncNotify);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnAsyncNotificationCompleted
+ */
+DECLINLINE(void) PDMDevHlpAsyncNotificationCompleted(PPDMDEVINS pDevIns)
+{
+ pDevIns->pHlpR3->pfnAsyncNotificationCompleted(pDevIns);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnA20Set
+ */
+DECLINLINE(void) PDMDevHlpA20Set(PPDMDEVINS pDevIns, bool fEnable)
+{
+ pDevIns->pHlpR3->pfnA20Set(pDevIns, fEnable);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnRTCRegister
+ */
+DECLINLINE(int) PDMDevHlpRTCRegister(PPDMDEVINS pDevIns, PCPDMRTCREG pRtcReg, PCPDMRTCHLP *ppRtcHlp)
+{
+ return pDevIns->pHlpR3->pfnRTCRegister(pDevIns, pRtcReg, ppRtcHlp);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnPCIBusRegister
+ */
+DECLINLINE(int) PDMDevHlpPCIBusRegister(PPDMDEVINS pDevIns, PPDMPCIBUSREGR3 pPciBusReg, PCPDMPCIHLPR3 *ppPciHlp, uint32_t *piBus)
+{
+ return pDevIns->pHlpR3->pfnPCIBusRegister(pDevIns, pPciBusReg, ppPciHlp, piBus);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnIommuRegister
+ */
+DECLINLINE(int) PDMDevHlpIommuRegister(PPDMDEVINS pDevIns, PPDMIOMMUREGR3 pIommuReg, PCPDMIOMMUHLPR3 *ppIommuHlp, uint32_t *pidxIommu)
+{
+ return pDevIns->pHlpR3->pfnIommuRegister(pDevIns, pIommuReg, ppIommuHlp, pidxIommu);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnPICRegister
+ */
+DECLINLINE(int) PDMDevHlpPICRegister(PPDMDEVINS pDevIns, PPDMPICREG pPicReg, PCPDMPICHLP *ppPicHlp)
+{
+ return pDevIns->pHlpR3->pfnPICRegister(pDevIns, pPicReg, ppPicHlp);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnApicRegister
+ */
+DECLINLINE(int) PDMDevHlpApicRegister(PPDMDEVINS pDevIns)
+{
+ return pDevIns->pHlpR3->pfnApicRegister(pDevIns);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnIoApicRegister
+ */
+DECLINLINE(int) PDMDevHlpIoApicRegister(PPDMDEVINS pDevIns, PPDMIOAPICREG pIoApicReg, PCPDMIOAPICHLP *ppIoApicHlp)
+{
+ return pDevIns->pHlpR3->pfnIoApicRegister(pDevIns, pIoApicReg, ppIoApicHlp);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnHpetRegister
+ */
+DECLINLINE(int) PDMDevHlpHpetRegister(PPDMDEVINS pDevIns, PPDMHPETREG pHpetReg, PCPDMHPETHLPR3 *ppHpetHlpR3)
+{
+ return pDevIns->pHlpR3->pfnHpetRegister(pDevIns, pHpetReg, ppHpetHlpR3);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnPciRawRegister
+ */
+DECLINLINE(int) PDMDevHlpPciRawRegister(PPDMDEVINS pDevIns, PPDMPCIRAWREG pPciRawReg, PCPDMPCIRAWHLPR3 *ppPciRawHlpR3)
+{
+ return pDevIns->pHlpR3->pfnPciRawRegister(pDevIns, pPciRawReg, ppPciRawHlpR3);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnDMACRegister
+ */
+DECLINLINE(int) PDMDevHlpDMACRegister(PPDMDEVINS pDevIns, PPDMDMACREG pDmacReg, PCPDMDMACHLP *ppDmacHlp)
+{
+ return pDevIns->pHlpR3->pfnDMACRegister(pDevIns, pDmacReg, ppDmacHlp);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnDMARegister
+ */
+DECLINLINE(int) PDMDevHlpDMARegister(PPDMDEVINS pDevIns, unsigned uChannel, PFNDMATRANSFERHANDLER pfnTransferHandler, void *pvUser)
+{
+ return pDevIns->pHlpR3->pfnDMARegister(pDevIns, uChannel, pfnTransferHandler, pvUser);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnDMAReadMemory
+ */
+DECLINLINE(int) PDMDevHlpDMAReadMemory(PPDMDEVINS pDevIns, unsigned uChannel, void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbRead)
+{
+ return pDevIns->pHlpR3->pfnDMAReadMemory(pDevIns, uChannel, pvBuffer, off, cbBlock, pcbRead);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnDMAWriteMemory
+ */
+DECLINLINE(int) PDMDevHlpDMAWriteMemory(PPDMDEVINS pDevIns, unsigned uChannel, const void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbWritten)
+{
+ return pDevIns->pHlpR3->pfnDMAWriteMemory(pDevIns, uChannel, pvBuffer, off, cbBlock, pcbWritten);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnDMASetDREQ
+ */
+DECLINLINE(int) PDMDevHlpDMASetDREQ(PPDMDEVINS pDevIns, unsigned uChannel, unsigned uLevel)
+{
+ return pDevIns->pHlpR3->pfnDMASetDREQ(pDevIns, uChannel, uLevel);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnDMAGetChannelMode
+ */
+DECLINLINE(uint8_t) PDMDevHlpDMAGetChannelMode(PPDMDEVINS pDevIns, unsigned uChannel)
+{
+ return pDevIns->pHlpR3->pfnDMAGetChannelMode(pDevIns, uChannel);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnDMASchedule
+ */
+DECLINLINE(void) PDMDevHlpDMASchedule(PPDMDEVINS pDevIns)
+{
+ pDevIns->pHlpR3->pfnDMASchedule(pDevIns);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnCMOSWrite
+ */
+DECLINLINE(int) PDMDevHlpCMOSWrite(PPDMDEVINS pDevIns, unsigned iReg, uint8_t u8Value)
+{
+ return pDevIns->pHlpR3->pfnCMOSWrite(pDevIns, iReg, u8Value);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnCMOSRead
+ */
+DECLINLINE(int) PDMDevHlpCMOSRead(PPDMDEVINS pDevIns, unsigned iReg, uint8_t *pu8Value)
+{
+ return pDevIns->pHlpR3->pfnCMOSRead(pDevIns, iReg, pu8Value);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnCallR0
+ */
+DECLINLINE(int) PDMDevHlpCallR0(PPDMDEVINS pDevIns, uint32_t uOperation, uint64_t u64Arg)
+{
+ return pDevIns->pHlpR3->pfnCallR0(pDevIns, uOperation, u64Arg);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnVMGetSuspendReason
+ */
+DECLINLINE(VMSUSPENDREASON) PDMDevHlpVMGetSuspendReason(PPDMDEVINS pDevIns)
+{
+ return pDevIns->pHlpR3->pfnVMGetSuspendReason(pDevIns);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnVMGetResumeReason
+ */
+DECLINLINE(VMRESUMEREASON) PDMDevHlpVMGetResumeReason(PPDMDEVINS pDevIns)
+{
+ return pDevIns->pHlpR3->pfnVMGetResumeReason(pDevIns);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnGetUVM
+ */
+DECLINLINE(PUVM) PDMDevHlpGetUVM(PPDMDEVINS pDevIns)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnGetUVM(pDevIns);
+}
+
+#endif /* IN_RING3 || DOXYGEN_RUNNING */
+
+#if !defined(IN_RING3) || defined(DOXYGEN_RUNNING)
+
+/**
+ * @copydoc PDMDEVHLPR0::pfnPCIBusSetUpContext
+ */
+DECLINLINE(int) PDMDevHlpPCIBusSetUpContext(PPDMDEVINS pDevIns, CTX_SUFF(PPDMPCIBUSREG) pPciBusReg, CTX_SUFF(PCPDMPCIHLP) *ppPciHlp)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnPCIBusSetUpContext(pDevIns, pPciBusReg, ppPciHlp);
+}
+
+/**
+ * @copydoc PDMDEVHLPR0::pfnIommuSetUpContext
+ */
+DECLINLINE(int) PDMDevHlpIommuSetUpContext(PPDMDEVINS pDevIns, CTX_SUFF(PPDMIOMMUREG) pIommuReg, CTX_SUFF(PCPDMIOMMUHLP) *ppIommuHlp)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnIommuSetUpContext(pDevIns, pIommuReg, ppIommuHlp);
+}
+
+/**
+ * @copydoc PDMDEVHLPR0::pfnPICSetUpContext
+ */
+DECLINLINE(int) PDMDevHlpPICSetUpContext(PPDMDEVINS pDevIns, PPDMPICREG pPicReg, PCPDMPICHLP *ppPicHlp)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnPICSetUpContext(pDevIns, pPicReg, ppPicHlp);
+}
+
+/**
+ * @copydoc PDMDEVHLPR0::pfnApicSetUpContext
+ */
+DECLINLINE(int) PDMDevHlpApicSetUpContext(PPDMDEVINS pDevIns)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnApicSetUpContext(pDevIns);
+}
+
+/**
+ * @copydoc PDMDEVHLPR0::pfnIoApicSetUpContext
+ */
+DECLINLINE(int) PDMDevHlpIoApicSetUpContext(PPDMDEVINS pDevIns, PPDMIOAPICREG pIoApicReg, PCPDMIOAPICHLP *ppIoApicHlp)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnIoApicSetUpContext(pDevIns, pIoApicReg, ppIoApicHlp);
+}
+
+/**
+ * @copydoc PDMDEVHLPR0::pfnHpetSetUpContext
+ */
+DECLINLINE(int) PDMDevHlpHpetSetUpContext(PPDMDEVINS pDevIns, PPDMHPETREG pHpetReg, CTX_SUFF(PCPDMHPETHLP) *ppHpetHlp)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnHpetSetUpContext(pDevIns, pHpetReg, ppHpetHlp);
+}
+
+#endif /* !IN_RING3 || DOXYGEN_RUNNING */
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnGetVM
+ */
+DECLINLINE(PVMCC) PDMDevHlpGetVM(PPDMDEVINS pDevIns)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnGetVM(pDevIns);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnGetVMCPU
+ */
+DECLINLINE(PVMCPUCC) PDMDevHlpGetVMCPU(PPDMDEVINS pDevIns)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnGetVMCPU(pDevIns);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnGetCurrentCpuId
+ */
+DECLINLINE(VMCPUID) PDMDevHlpGetCurrentCpuId(PPDMDEVINS pDevIns)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnGetCurrentCpuId(pDevIns);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnTMTimeVirtGet
+ */
+DECLINLINE(uint64_t) PDMDevHlpTMTimeVirtGet(PPDMDEVINS pDevIns)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnTMTimeVirtGet(pDevIns);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnTMTimeVirtGetFreq
+ */
+DECLINLINE(uint64_t) PDMDevHlpTMTimeVirtGetFreq(PPDMDEVINS pDevIns)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnTMTimeVirtGetFreq(pDevIns);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnTMTimeVirtGetFreq
+ */
+DECLINLINE(uint64_t) PDMDevHlpTMTimeVirtGetNano(PPDMDEVINS pDevIns)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnTMTimeVirtGetNano(pDevIns);
+}
+
+#ifdef IN_RING3
+/**
+ * @copydoc PDMDEVHLPR3::pfnTMCpuTicksPerSecond
+ */
+DECLINLINE(uint64_t) PDMDevHlpTMCpuTicksPerSecond(PPDMDEVINS pDevIns)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnTMCpuTicksPerSecond(pDevIns);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnRegisterVMMDevHeap
+ */
+DECLINLINE(int) PDMDevHlpRegisterVMMDevHeap(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTR3PTR pvHeap, unsigned cbHeap)
+{
+ return pDevIns->pHlpR3->pfnRegisterVMMDevHeap(pDevIns, GCPhys, pvHeap, cbHeap);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnFirmwareRegister
+ */
+DECLINLINE(int) PDMDevHlpFirmwareRegister(PPDMDEVINS pDevIns, PCPDMFWREG pFwReg, PCPDMFWHLPR3 *ppFwHlp)
+{
+ return pDevIns->pHlpR3->pfnFirmwareRegister(pDevIns, pFwReg, ppFwHlp);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnVMReset
+ */
+DECLINLINE(int) PDMDevHlpVMReset(PPDMDEVINS pDevIns, uint32_t fFlags)
+{
+ return pDevIns->pHlpR3->pfnVMReset(pDevIns, fFlags);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnVMSuspend
+ */
+DECLINLINE(int) PDMDevHlpVMSuspend(PPDMDEVINS pDevIns)
+{
+ return pDevIns->pHlpR3->pfnVMSuspend(pDevIns);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnVMSuspendSaveAndPowerOff
+ */
+DECLINLINE(int) PDMDevHlpVMSuspendSaveAndPowerOff(PPDMDEVINS pDevIns)
+{
+ return pDevIns->pHlpR3->pfnVMSuspendSaveAndPowerOff(pDevIns);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnVMPowerOff
+ */
+DECLINLINE(int) PDMDevHlpVMPowerOff(PPDMDEVINS pDevIns)
+{
+ return pDevIns->pHlpR3->pfnVMPowerOff(pDevIns);
+}
+
+#endif /* IN_RING3 */
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnA20IsEnabled
+ */
+DECLINLINE(bool) PDMDevHlpA20IsEnabled(PPDMDEVINS pDevIns)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnA20IsEnabled(pDevIns);
+}
+
+#ifdef IN_RING3
+/**
+ * @copydoc PDMDEVHLPR3::pfnGetCpuId
+ */
+DECLINLINE(void) PDMDevHlpGetCpuId(PPDMDEVINS pDevIns, uint32_t iLeaf, uint32_t *pEax, uint32_t *pEbx, uint32_t *pEcx, uint32_t *pEdx)
+{
+ pDevIns->pHlpR3->pfnGetCpuId(pDevIns, iLeaf, pEax, pEbx, pEcx, pEdx);
+}
+#endif
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnGetMainExecutionEngine
+ */
+DECLINLINE(uint8_t) PDMDevHlpGetMainExecutionEngine(PPDMDEVINS pDevIns)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnGetMainExecutionEngine(pDevIns);
+}
+
+#ifdef IN_RING3
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnGetSupDrvSession
+ */
+DECLINLINE(PSUPDRVSESSION) PDMDevHlpGetSupDrvSession(PPDMDEVINS pDevIns)
+{
+ return pDevIns->pHlpR3->pfnGetSupDrvSession(pDevIns);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnQueryGenericUserObject
+ */
+DECLINLINE(void *) PDMDevHlpQueryGenericUserObject(PPDMDEVINS pDevIns, PCRTUUID pUuid)
+{
+ return pDevIns->pHlpR3->pfnQueryGenericUserObject(pDevIns, pUuid);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnPGMHandlerPhysicalTypeRegister
+ */
+DECLINLINE(int) PDMDevHlpPGMHandlerPhysicalTypeRegister(PPDMDEVINS pDevIns, PGMPHYSHANDLERKIND enmKind,
+ PFNPGMPHYSHANDLER pfnHandler, const char *pszDesc,
+ PPGMPHYSHANDLERTYPE phType)
+{
+ return pDevIns->pHlpR3->pfnPGMHandlerPhysicalTypeRegister(pDevIns, enmKind, pfnHandler, pszDesc, phType);
+}
+
+#elif defined(IN_RING0)
+
+/**
+ * @copydoc PDMDEVHLPR0::pfnPGMHandlerPhysicalTypeSetUpContext
+ */
+DECLINLINE(int) PDMDevHlpPGMHandlerPhysicalTypeSetUpContext(PPDMDEVINS pDevIns, PGMPHYSHANDLERKIND enmKind,
+ PFNPGMPHYSHANDLER pfnHandler, PFNPGMRZPHYSPFHANDLER pfnPfHandler,
+ const char *pszDesc, PGMPHYSHANDLERTYPE hType)
+{
+ return pDevIns->pHlpR0->pfnPGMHandlerPhysicalTypeSetUpContext(pDevIns, enmKind, pfnHandler, pfnPfHandler, pszDesc, hType);
+}
+
+#endif
+#ifdef IN_RING3
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnPGMHandlerPhysicalRegister
+ */
+DECLINLINE(int) PDMDevHlpPGMHandlerPhysicalRegister(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTGCPHYS GCPhysLast,
+ PGMPHYSHANDLERTYPE hType, R3PTRTYPE(const char *) pszDesc)
+{
+ return pDevIns->pHlpR3->pfnPGMHandlerPhysicalRegister(pDevIns, GCPhys, GCPhysLast, hType, pszDesc);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnPGMHandlerPhysicalDeregister
+ */
+DECLINLINE(int) PDMDevHlpPGMHandlerPhysicalDeregister(PPDMDEVINS pDevIns, RTGCPHYS GCPhys)
+{
+ return pDevIns->pHlpR3->pfnPGMHandlerPhysicalDeregister(pDevIns, GCPhys);
+}
+
+#endif /* IN_RING3 */
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnPGMHandlerPhysicalPageTempOff
+ */
+DECLINLINE(int) PDMDevHlpPGMHandlerPhysicalPageTempOff(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTGCPHYS GCPhysPage)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnPGMHandlerPhysicalPageTempOff(pDevIns, GCPhys, GCPhysPage);
+}
+
+#ifdef IN_RING3
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnPGMHandlerPhysicalReset
+ */
+DECLINLINE(int) PDMDevHlpPGMHandlerPhysicalReset(PPDMDEVINS pDevIns, RTGCPHYS GCPhys)
+{
+ return pDevIns->pHlpR3->pfnPGMHandlerPhysicalReset(pDevIns, GCPhys);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnVMMRegisterPatchMemory
+ */
+DECLINLINE(int) PDMDevHlpVMMRegisterPatchMemory(PPDMDEVINS pDevIns, RTGCPTR GCPtrPatchMem, uint32_t cbPatchMem)
+{
+ return pDevIns->pHlpR3->pfnVMMRegisterPatchMemory(pDevIns, GCPtrPatchMem, cbPatchMem);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnVMMDeregisterPatchMemory
+ */
+DECLINLINE(int) PDMDevHlpVMMDeregisterPatchMemory(PPDMDEVINS pDevIns, RTGCPTR GCPtrPatchMem, uint32_t cbPatchMem)
+{
+ return pDevIns->pHlpR3->pfnVMMDeregisterPatchMemory(pDevIns, GCPtrPatchMem, cbPatchMem);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnSharedModuleRegister
+ */
+DECLINLINE(int) PDMDevHlpSharedModuleRegister(PPDMDEVINS pDevIns, VBOXOSFAMILY enmGuestOS, char *pszModuleName, char *pszVersion,
+ RTGCPTR GCBaseAddr, uint32_t cbModule,
+ uint32_t cRegions, VMMDEVSHAREDREGIONDESC const *paRegions)
+{
+ return pDevIns->pHlpR3->pfnSharedModuleRegister(pDevIns, enmGuestOS, pszModuleName, pszVersion,
+ GCBaseAddr, cbModule, cRegions, paRegions);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnSharedModuleUnregister
+ */
+DECLINLINE(int) PDMDevHlpSharedModuleUnregister(PPDMDEVINS pDevIns, char *pszModuleName, char *pszVersion,
+ RTGCPTR GCBaseAddr, uint32_t cbModule)
+{
+ return pDevIns->pHlpR3->pfnSharedModuleUnregister(pDevIns, pszModuleName, pszVersion, GCBaseAddr, cbModule);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnSharedModuleGetPageState
+ */
+DECLINLINE(int) PDMDevHlpSharedModuleGetPageState(PPDMDEVINS pDevIns, RTGCPTR GCPtrPage, bool *pfShared,
+ uint64_t *pfPageFlags)
+{
+ return pDevIns->pHlpR3->pfnSharedModuleGetPageState(pDevIns, GCPtrPage, pfShared, pfPageFlags);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnSharedModuleCheckAll
+ */
+DECLINLINE(int) PDMDevHlpSharedModuleCheckAll(PPDMDEVINS pDevIns)
+{
+ return pDevIns->pHlpR3->pfnSharedModuleCheckAll(pDevIns);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnQueryLun
+ */
+DECLINLINE(int) PDMDevHlpQueryLun(PPDMDEVINS pDevIns, const char *pszDevice, unsigned iInstance, unsigned iLun, PPDMIBASE *ppBase)
+{
+ return pDevIns->pHlpR3->pfnQueryLun(pDevIns, pszDevice, iInstance, iLun, ppBase);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnGIMDeviceRegister
+ */
+DECLINLINE(void) PDMDevHlpGIMDeviceRegister(PPDMDEVINS pDevIns, PGIMDEBUG pDbg)
+{
+ pDevIns->pHlpR3->pfnGIMDeviceRegister(pDevIns, pDbg);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnGIMGetDebugSetup
+ */
+DECLINLINE(int) PDMDevHlpGIMGetDebugSetup(PPDMDEVINS pDevIns, PGIMDEBUGSETUP pDbgSetup)
+{
+ return pDevIns->pHlpR3->pfnGIMGetDebugSetup(pDevIns, pDbgSetup);
+}
+
+#endif /* IN_RING3 */
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnGIMGetMmio2Regions
+ */
+DECLINLINE(PGIMMMIO2REGION) PDMDevHlpGIMGetMmio2Regions(PPDMDEVINS pDevIns, uint32_t *pcRegions)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnGIMGetMmio2Regions(pDevIns, pcRegions);
+}
+
+#ifdef IN_RING3
+
+/** Wrapper around SSMR3GetU32 for simplifying getting enum values saved as uint32_t. */
+# define PDMDEVHLP_SSM_GET_ENUM32_RET(a_pHlp, a_pSSM, a_enmDst, a_EnumType) \
+ do { \
+ uint32_t u32GetEnumTmp = 0; \
+ int rcGetEnum32Tmp = (a_pHlp)->pfnSSMGetU32((a_pSSM), &u32GetEnumTmp); \
+ AssertRCReturn(rcGetEnum32Tmp, rcGetEnum32Tmp); \
+ (a_enmDst) = (a_EnumType)u32GetEnumTmp; \
+ AssertCompile(sizeof(a_EnumType) == sizeof(u32GetEnumTmp)); \
+ } while (0)
+
+/** Wrapper around SSMR3GetU8 for simplifying getting enum values saved as uint8_t. */
+# define PDMDEVHLP_SSM_GET_ENUM8_RET(a_pHlp, a_pSSM, a_enmDst, a_EnumType) \
+ do { \
+ uint8_t bGetEnumTmp = 0; \
+ int rcGetEnum32Tmp = (a_pHlp)->pfnSSMGetU8((a_pSSM), &bGetEnumTmp); \
+ AssertRCReturn(rcGetEnum32Tmp, rcGetEnum32Tmp); \
+ (a_enmDst) = (a_EnumType)bGetEnumTmp; \
+ } while (0)
+
+#endif /* IN_RING3 */
+
+/** Pointer to callbacks provided to the VBoxDeviceRegister() call. */
+typedef struct PDMDEVREGCB *PPDMDEVREGCB;
+
+/**
+ * Callbacks for VBoxDeviceRegister().
+ */
+typedef struct PDMDEVREGCB
+{
+ /** Interface version.
+ * This is set to PDM_DEVREG_CB_VERSION. */
+ uint32_t u32Version;
+
+ /**
+ * Registers a device with the current VM instance.
+ *
+ * @returns VBox status code.
+ * @param pCallbacks Pointer to the callback table.
+ * @param pReg Pointer to the device registration record.
+ * This data must be permanent and readonly.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnRegister,(PPDMDEVREGCB pCallbacks, PCPDMDEVREG pReg));
+} PDMDEVREGCB;
+
+/** Current version of the PDMDEVREGCB structure. */
+#define PDM_DEVREG_CB_VERSION PDM_VERSION_MAKE(0xffe3, 1, 0)
+
+
+/**
+ * The VBoxDevicesRegister callback function.
+ *
+ * PDM will invoke this function after loading a device module and letting
+ * the module decide which devices to register and how to handle conflicts.
+ *
+ * @returns VBox status code.
+ * @param pCallbacks Pointer to the callback table.
+ * @param u32Version VBox version number.
+ */
+typedef DECLCALLBACKTYPE(int, FNPDMVBOXDEVICESREGISTER,(PPDMDEVREGCB pCallbacks, uint32_t u32Version));
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !VBOX_INCLUDED_vmm_pdmdev_h */
diff --git a/include/VBox/vmm/pdmdrv.h b/include/VBox/vmm/pdmdrv.h
new file mode 100644
index 00000000..6c0ee40f
--- /dev/null
+++ b/include/VBox/vmm/pdmdrv.h
@@ -0,0 +1,2497 @@
+/** @file
+ * PDM - Pluggable Device Manager, Drivers.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vmm_pdmdrv_h
+#define VBOX_INCLUDED_vmm_pdmdrv_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/vmm/pdmqueue.h>
+#include <VBox/vmm/pdmcritsect.h>
+#include <VBox/vmm/pdmifs.h>
+#include <VBox/vmm/pdmins.h>
+#include <VBox/vmm/pdmcommon.h>
+#ifdef IN_RING3
+# include <VBox/vmm/pdmthread.h>
+# include <VBox/vmm/pdmasynccompletion.h>
+# include <VBox/vmm/pdmblkcache.h>
+#endif
+#include <VBox/vmm/tm.h>
+#include <VBox/vmm/ssm.h>
+#include <VBox/vmm/cfgm.h>
+#include <VBox/vmm/dbgf.h>
+#include <VBox/vmm/mm.h>
+#include <iprt/stdarg.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_pdm_driver The PDM Drivers API
+ * @ingroup grp_pdm
+ * @{
+ */
+
+/** Pointer const PDM Driver API, ring-3. */
+typedef R3PTRTYPE(struct PDMDRVHLPR3 const *) PCPDMDRVHLPR3;
+/** Pointer const PDM Driver API, ring-0. */
+typedef R0PTRTYPE(struct PDMDRVHLPR0 const *) PCPDMDRVHLPR0;
+/** Pointer const PDM Driver API, raw-mode context. */
+typedef RCPTRTYPE(struct PDMDRVHLPRC const *) PCPDMDRVHLPRC;
+
+
+/**
+ * Construct a driver instance for a VM.
+ *
+ * @returns VBox status.
+ * @param pDrvIns The driver instance data. If the registration structure
+ * is needed, it can be accessed thru pDrvIns->pReg.
+ * @param pCfg Configuration node handle for the driver. This is
+ * expected to be in high demand in the constructor and is
+ * therefore passed as an argument. When using it at other
+ * times, it can be accessed via pDrvIns->pCfg.
+ * @param fFlags Flags, combination of the PDM_TACH_FLAGS_* \#defines.
+ */
+typedef DECLCALLBACKTYPE(int, FNPDMDRVCONSTRUCT,(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags));
+/** Pointer to a FNPDMDRVCONSTRUCT() function. */
+typedef FNPDMDRVCONSTRUCT *PFNPDMDRVCONSTRUCT;
+
+/**
+ * Destruct a driver instance.
+ *
+ * Most VM resources are freed by the VM. This callback is provided so that
+ * any non-VM resources can be freed correctly.
+ *
+ * @param pDrvIns The driver instance data.
+ */
+typedef DECLCALLBACKTYPE(void, FNPDMDRVDESTRUCT,(PPDMDRVINS pDrvIns));
+/** Pointer to a FNPDMDRVDESTRUCT() function. */
+typedef FNPDMDRVDESTRUCT *PFNPDMDRVDESTRUCT;
+
+/**
+ * Driver relocation callback.
+ *
+ * This is called when the instance data has been relocated in raw-mode context
+ * (RC). It is also called when the RC hypervisor selects changes. The driver
+ * must fixup all necessary pointers and re-query all interfaces to other RC
+ * devices and drivers.
+ *
+ * Before the RC code is executed the first time, this function will be called
+ * with a 0 delta so RC pointer calculations can be one in one place.
+ *
+ * @param pDrvIns Pointer to the driver instance.
+ * @param offDelta The relocation delta relative to the old location.
+ *
+ * @remark A relocation CANNOT fail.
+ */
+typedef DECLCALLBACKTYPE(void, FNPDMDRVRELOCATE,(PPDMDRVINS pDrvIns, RTGCINTPTR offDelta));
+/** Pointer to a FNPDMDRVRELOCATE() function. */
+typedef FNPDMDRVRELOCATE *PFNPDMDRVRELOCATE;
+
+/**
+ * Driver I/O Control interface.
+ *
+ * This is used by external components, such as the COM interface, to
+ * communicate with a driver using a driver specific interface. Generally,
+ * the driver interfaces are used for this task.
+ *
+ * @returns VBox status code.
+ * @param pDrvIns Pointer to the driver instance.
+ * @param uFunction Function to perform.
+ * @param pvIn Pointer to input data.
+ * @param cbIn Size of input data.
+ * @param pvOut Pointer to output data.
+ * @param cbOut Size of output data.
+ * @param pcbOut Where to store the actual size of the output data.
+ */
+typedef DECLCALLBACKTYPE(int, FNPDMDRVIOCTL,(PPDMDRVINS pDrvIns, uint32_t uFunction,
+ void *pvIn, uint32_t cbIn,
+ void *pvOut, uint32_t cbOut, uint32_t *pcbOut));
+/** Pointer to a FNPDMDRVIOCTL() function. */
+typedef FNPDMDRVIOCTL *PFNPDMDRVIOCTL;
+
+/**
+ * Power On notification.
+ *
+ * @param pDrvIns The driver instance data.
+ */
+typedef DECLCALLBACKTYPE(void, FNPDMDRVPOWERON,(PPDMDRVINS pDrvIns));
+/** Pointer to a FNPDMDRVPOWERON() function. */
+typedef FNPDMDRVPOWERON *PFNPDMDRVPOWERON;
+
+/**
+ * Reset notification.
+ *
+ * @returns VBox status.
+ * @param pDrvIns The driver instance data.
+ */
+typedef DECLCALLBACKTYPE(void, FNPDMDRVRESET,(PPDMDRVINS pDrvIns));
+/** Pointer to a FNPDMDRVRESET() function. */
+typedef FNPDMDRVRESET *PFNPDMDRVRESET;
+
+/**
+ * Suspend notification.
+ *
+ * @returns VBox status.
+ * @param pDrvIns The driver instance data.
+ */
+typedef DECLCALLBACKTYPE(void, FNPDMDRVSUSPEND,(PPDMDRVINS pDrvIns));
+/** Pointer to a FNPDMDRVSUSPEND() function. */
+typedef FNPDMDRVSUSPEND *PFNPDMDRVSUSPEND;
+
+/**
+ * Resume notification.
+ *
+ * @returns VBox status.
+ * @param pDrvIns The driver instance data.
+ */
+typedef DECLCALLBACKTYPE(void, FNPDMDRVRESUME,(PPDMDRVINS pDrvIns));
+/** Pointer to a FNPDMDRVRESUME() function. */
+typedef FNPDMDRVRESUME *PFNPDMDRVRESUME;
+
+/**
+ * Power Off notification.
+ *
+ * This is always called when VMR3PowerOff is called.
+ * There will be no callback when hot plugging devices or when replumbing the driver
+ * stack.
+ *
+ * @param pDrvIns The driver instance data.
+ */
+typedef DECLCALLBACKTYPE(void, FNPDMDRVPOWEROFF,(PPDMDRVINS pDrvIns));
+/** Pointer to a FNPDMDRVPOWEROFF() function. */
+typedef FNPDMDRVPOWEROFF *PFNPDMDRVPOWEROFF;
+
+/**
+ * Attach command.
+ *
+ * This is called to let the driver attach to a driver at runtime. This is not
+ * called during VM construction, the driver constructor have to do this by
+ * calling PDMDrvHlpAttach.
+ *
+ * This is like plugging in the keyboard or mouse after turning on the PC.
+ *
+ * @returns VBox status code.
+ * @param pDrvIns The driver instance.
+ * @param fFlags Flags, combination of the PDM_TACH_FLAGS_* \#defines.
+ */
+typedef DECLCALLBACKTYPE(int, FNPDMDRVATTACH,(PPDMDRVINS pDrvIns, uint32_t fFlags));
+/** Pointer to a FNPDMDRVATTACH() function. */
+typedef FNPDMDRVATTACH *PFNPDMDRVATTACH;
+
+/**
+ * Detach notification.
+ *
+ * This is called when a driver below it in the chain is detaching itself
+ * from it. The driver should adjust it's state to reflect this.
+ *
+ * This is like ejecting a cdrom or floppy.
+ *
+ * @param pDrvIns The driver instance.
+ * @param fFlags PDM_TACH_FLAGS_NOT_HOT_PLUG or 0.
+ */
+typedef DECLCALLBACKTYPE(void, FNPDMDRVDETACH,(PPDMDRVINS pDrvIns, uint32_t fFlags));
+/** Pointer to a FNPDMDRVDETACH() function. */
+typedef FNPDMDRVDETACH *PFNPDMDRVDETACH;
+
+
+
+/**
+ * PDM Driver Registration Structure.
+ *
+ * This structure is used when registering a driver from VBoxInitDrivers() (in
+ * host ring-3 context). PDM will continue use till the VM is terminated.
+ */
+typedef struct PDMDRVREG
+{
+ /** Structure version. PDM_DRVREG_VERSION defines the current version. */
+ uint32_t u32Version;
+ /** Driver name. */
+ char szName[32];
+ /** Name of the raw-mode context module (no path).
+ * Only evalutated if PDM_DRVREG_FLAGS_RC is set. */
+ char szRCMod[32];
+ /** Name of the ring-0 module (no path).
+ * Only evalutated if PDM_DRVREG_FLAGS_R0 is set. */
+ char szR0Mod[32];
+ /** The description of the driver. The UTF-8 string pointed to shall, like this structure,
+ * remain unchanged from registration till VM destruction. */
+ const char *pszDescription;
+
+ /** Flags, combination of the PDM_DRVREG_FLAGS_* \#defines. */
+ uint32_t fFlags;
+ /** Driver class(es), combination of the PDM_DRVREG_CLASS_* \#defines. */
+ uint32_t fClass;
+ /** Maximum number of instances (per VM). */
+ uint32_t cMaxInstances;
+ /** Size of the instance data. */
+ uint32_t cbInstance;
+
+ /** Construct instance - required. */
+ PFNPDMDRVCONSTRUCT pfnConstruct;
+ /** Destruct instance - optional. */
+ PFNPDMDRVDESTRUCT pfnDestruct;
+ /** Relocation command - optional. */
+ PFNPDMDRVRELOCATE pfnRelocate;
+ /** I/O control - optional. */
+ PFNPDMDRVIOCTL pfnIOCtl;
+ /** Power on notification - optional. */
+ PFNPDMDRVPOWERON pfnPowerOn;
+ /** Reset notification - optional. */
+ PFNPDMDRVRESET pfnReset;
+ /** Suspend notification - optional. */
+ PFNPDMDRVSUSPEND pfnSuspend;
+ /** Resume notification - optional. */
+ PFNPDMDRVRESUME pfnResume;
+ /** Attach command - optional. */
+ PFNPDMDRVATTACH pfnAttach;
+ /** Detach notification - optional. */
+ PFNPDMDRVDETACH pfnDetach;
+ /** Power off notification - optional. */
+ PFNPDMDRVPOWEROFF pfnPowerOff;
+ /** @todo */
+ PFNRT pfnSoftReset;
+ /** Initialization safty marker. */
+ uint32_t u32VersionEnd;
+} PDMDRVREG;
+/** Pointer to a PDM Driver Structure. */
+typedef PDMDRVREG *PPDMDRVREG;
+/** Const pointer to a PDM Driver Structure. */
+typedef PDMDRVREG const *PCPDMDRVREG;
+
+/** Current DRVREG version number. */
+#define PDM_DRVREG_VERSION PDM_VERSION_MAKE(0xf0ff, 1, 0)
+
+/** PDM Driver Flags.
+ * @{ */
+/** @def PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT
+ * The bit count for the current host. */
+#if HC_ARCH_BITS == 32
+# define PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT UINT32_C(0x00000001)
+#elif HC_ARCH_BITS == 64
+# define PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT UINT32_C(0x00000002)
+#else
+# error Unsupported HC_ARCH_BITS value.
+#endif
+/** The host bit count mask. */
+#define PDM_DRVREG_FLAGS_HOST_BITS_MASK UINT32_C(0x00000003)
+/** This flag is used to indicate that the driver has a RC component. */
+#define PDM_DRVREG_FLAGS_RC UINT32_C(0x00000010)
+/** This flag is used to indicate that the driver has a R0 component. */
+#define PDM_DRVREG_FLAGS_R0 UINT32_C(0x00000020)
+
+/** @} */
+
+
+/** PDM Driver Classes.
+ * @{ */
+/** Mouse input driver. */
+#define PDM_DRVREG_CLASS_MOUSE RT_BIT(0)
+/** Keyboard input driver. */
+#define PDM_DRVREG_CLASS_KEYBOARD RT_BIT(1)
+/** Display driver. */
+#define PDM_DRVREG_CLASS_DISPLAY RT_BIT(2)
+/** Network transport driver. */
+#define PDM_DRVREG_CLASS_NETWORK RT_BIT(3)
+/** Block driver. */
+#define PDM_DRVREG_CLASS_BLOCK RT_BIT(4)
+/** Media driver. */
+#define PDM_DRVREG_CLASS_MEDIA RT_BIT(5)
+/** Mountable driver. */
+#define PDM_DRVREG_CLASS_MOUNTABLE RT_BIT(6)
+/** Audio driver. */
+#define PDM_DRVREG_CLASS_AUDIO RT_BIT(7)
+/** VMMDev driver. */
+#define PDM_DRVREG_CLASS_VMMDEV RT_BIT(8)
+/** Status driver. */
+#define PDM_DRVREG_CLASS_STATUS RT_BIT(9)
+/** ACPI driver. */
+#define PDM_DRVREG_CLASS_ACPI RT_BIT(10)
+/** USB related driver. */
+#define PDM_DRVREG_CLASS_USB RT_BIT(11)
+/** ISCSI Transport related driver. */
+#define PDM_DRVREG_CLASS_ISCSITRANSPORT RT_BIT(12)
+/** Char driver. */
+#define PDM_DRVREG_CLASS_CHAR RT_BIT(13)
+/** Stream driver. */
+#define PDM_DRVREG_CLASS_STREAM RT_BIT(14)
+/** SCSI driver. */
+#define PDM_DRVREG_CLASS_SCSI RT_BIT(15)
+/** Generic raw PCI device driver. */
+#define PDM_DRVREG_CLASS_PCIRAW RT_BIT(16)
+/** @} */
+
+
+/**
+ * PDM Driver Instance.
+ *
+ * @implements PDMIBASE
+ */
+typedef struct PDMDRVINS
+{
+ /** Structure version. PDM_DRVINS_VERSION defines the current version. */
+ uint32_t u32Version;
+ /** Driver instance number. */
+ uint32_t iInstance;
+
+ /** Pointer the PDM Driver API. */
+ RCPTRTYPE(PCPDMDRVHLPRC) pHlpRC;
+ /** Pointer to driver instance data. */
+ RCPTRTYPE(void *) pvInstanceDataRC;
+
+ /** Pointer the PDM Driver API. */
+ R0PTRTYPE(PCPDMDRVHLPR0) pHlpR0;
+ /** Pointer to driver instance data. */
+ R0PTRTYPE(void *) pvInstanceDataR0;
+
+ /** Pointer the PDM Driver API. */
+ R3PTRTYPE(PCPDMDRVHLPR3) pHlpR3;
+ /** Pointer to driver instance data. */
+ R3PTRTYPE(void *) pvInstanceDataR3;
+
+ /** Pointer to driver registration structure. */
+ R3PTRTYPE(PCPDMDRVREG) pReg;
+ /** Configuration handle. */
+ R3PTRTYPE(PCFGMNODE) pCfg;
+
+ /** Pointer to the base interface of the device/driver instance above. */
+ R3PTRTYPE(PPDMIBASE) pUpBase;
+ /** Pointer to the base interface of the driver instance below. */
+ R3PTRTYPE(PPDMIBASE) pDownBase;
+
+ /** The base interface of the driver.
+ * The driver constructor initializes this. */
+ PDMIBASE IBase;
+
+ /** Tracing indicator. */
+ uint32_t fTracing;
+ /** The tracing ID of this device. */
+ uint32_t idTracing;
+#if HC_ARCH_BITS == 32
+ /** Align the internal data more naturally. */
+ uint32_t au32Padding[HC_ARCH_BITS == 32 ? 7 : 0];
+#endif
+
+ /** Internal data. */
+ union
+ {
+#ifdef PDMDRVINSINT_DECLARED
+ PDMDRVINSINT s;
+#endif
+ uint8_t padding[HC_ARCH_BITS == 32 ? 40 + 32 : 72 + 24];
+ } Internal;
+
+ /** Driver instance data. The size of this area is defined
+ * in the PDMDRVREG::cbInstanceData field. */
+ char achInstanceData[4];
+} PDMDRVINS;
+
+/** Current DRVREG version number. */
+#define PDM_DRVINS_VERSION PDM_VERSION_MAKE(0xf0fe, 2, 0)
+
+/** Converts a pointer to the PDMDRVINS::IBase to a pointer to PDMDRVINS. */
+#define PDMIBASE_2_PDMDRV(pInterface) ( (PPDMDRVINS)((char *)(pInterface) - RT_UOFFSETOF(PDMDRVINS, IBase)) )
+
+/** @def PDMDRVINS_2_RCPTR
+ * Converts a PDM Driver instance pointer a RC PDM Driver instance pointer.
+ */
+#define PDMDRVINS_2_RCPTR(pDrvIns) ( (RCPTRTYPE(PPDMDRVINS))((RTRCUINTPTR)(pDrvIns)->pvInstanceDataRC - (RTRCUINTPTR)RT_UOFFSETOF(PDMDRVINS, achInstanceData)) )
+
+/** @def PDMDRVINS_2_R3PTR
+ * Converts a PDM Driver instance pointer a R3 PDM Driver instance pointer.
+ */
+#define PDMDRVINS_2_R3PTR(pDrvIns) ( (R3PTRTYPE(PPDMDRVINS))((RTHCUINTPTR)(pDrvIns)->pvInstanceDataR3 - RT_UOFFSETOF(PDMDRVINS, achInstanceData)) )
+
+/** @def PDMDRVINS_2_R0PTR
+ * Converts a PDM Driver instance pointer a R0 PDM Driver instance pointer.
+ */
+#define PDMDRVINS_2_R0PTR(pDrvIns) ( (R0PTRTYPE(PPDMDRVINS))((RTR0UINTPTR)(pDrvIns)->pvInstanceDataR0 - RT_UOFFSETOF(PDMDRVINS, achInstanceData)) )
+
+
+
+/**
+ * Checks the structure versions of the drive instance and driver helpers,
+ * returning if they are incompatible.
+ *
+ * Intended for the constructor.
+ *
+ * @param pDrvIns Pointer to the PDM driver instance.
+ */
+#define PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns) \
+ do \
+ { \
+ PPDMDRVINS pDrvInsTypeCheck = (pDrvIns); NOREF(pDrvInsTypeCheck); \
+ AssertLogRelMsgReturn(PDM_VERSION_ARE_COMPATIBLE((pDrvIns)->u32Version, PDM_DRVINS_VERSION), \
+ ("DrvIns=%#x mine=%#x\n", (pDrvIns)->u32Version, PDM_DRVINS_VERSION), \
+ VERR_PDM_DRVINS_VERSION_MISMATCH); \
+ AssertLogRelMsgReturn(PDM_VERSION_ARE_COMPATIBLE((pDrvIns)->pHlpR3->u32Version, PDM_DRVHLPR3_VERSION), \
+ ("DrvHlp=%#x mine=%#x\n", (pDrvIns)->pHlpR3->u32Version, PDM_DRVHLPR3_VERSION), \
+ VERR_PDM_DRVHLPR3_VERSION_MISMATCH); \
+ } while (0)
+
+/**
+ * Quietly checks the structure versions of the drive instance and driver
+ * helpers, returning if they are incompatible.
+ *
+ * Intended for the destructor.
+ *
+ * @param pDrvIns Pointer to the PDM driver instance.
+ */
+#define PDMDRV_CHECK_VERSIONS_RETURN_VOID(pDrvIns) \
+ do \
+ { \
+ PPDMDRVINS pDrvInsTypeCheck = (pDrvIns); NOREF(pDrvInsTypeCheck); \
+ if (RT_LIKELY( PDM_VERSION_ARE_COMPATIBLE((pDrvIns)->u32Version, PDM_DRVINS_VERSION) \
+ && PDM_VERSION_ARE_COMPATIBLE((pDrvIns)->pHlpR3->u32Version, PDM_DRVHLPR3_VERSION)) ) \
+ { /* likely */ } else return; \
+ } while (0)
+
+/**
+ * Wrapper around CFGMR3ValidateConfig for the root config for use in the
+ * constructor - returns on failure.
+ *
+ * This should be invoked after having initialized the instance data
+ * sufficiently for the correct operation of the destructor. The destructor is
+ * always called!
+ *
+ * @param pDrvIns Pointer to the PDM driver instance.
+ * @param pszValidValues Patterns describing the valid value names. See
+ * RTStrSimplePatternMultiMatch for details on the
+ * pattern syntax.
+ * @param pszValidNodes Patterns describing the valid node (key) names.
+ * Pass empty string if no valid nodess.
+ */
+#define PDMDRV_VALIDATE_CONFIG_RETURN(pDrvIns, pszValidValues, pszValidNodes) \
+ do \
+ { \
+ int rcValCfg = pDrvIns->pHlpR3->pfnCFGMValidateConfig((pDrvIns)->pCfg, "/", pszValidValues, pszValidNodes, \
+ (pDrvIns)->pReg->szName, (pDrvIns)->iInstance); \
+ if (RT_SUCCESS(rcValCfg)) \
+ { /* likely */ } else return rcValCfg; \
+ } while (0)
+
+
+
+/**
+ * USB hub registration structure.
+ */
+typedef struct PDMUSBHUBREG
+{
+ /** Structure version number. PDM_USBHUBREG_VERSION defines the current version. */
+ uint32_t u32Version;
+
+ /**
+ * Request the hub to attach of the specified device.
+ *
+ * @returns VBox status code.
+ * @param pDrvIns The hub instance.
+ * @param pUsbIns The device to attach.
+ * @param pszCaptureFilename Path to the file for USB traffic capturing, optional.
+ * @param piPort Where to store the port number the device was attached to.
+ * @thread EMT.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnAttachDevice,(PPDMDRVINS pDrvIns, PPDMUSBINS pUsbIns, const char *pszCaptureFilename, uint32_t *piPort));
+
+ /**
+ * Request the hub to detach of the specified device.
+ *
+ * The device has previously been attached to the hub with the
+ * pfnAttachDevice call. This call is not currently expected to
+ * fail.
+ *
+ * @returns VBox status code.
+ * @param pDrvIns The hub instance.
+ * @param pUsbIns The device to detach.
+ * @param iPort The port number returned by the attach call.
+ * @thread EMT.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnDetachDevice,(PPDMDRVINS pDrvIns, PPDMUSBINS pUsbIns, uint32_t iPort));
+
+ /** Counterpart to u32Version, same value. */
+ uint32_t u32TheEnd;
+} PDMUSBHUBREG;
+/** Pointer to a const USB hub registration structure. */
+typedef const PDMUSBHUBREG *PCPDMUSBHUBREG;
+
+/** Current PDMUSBHUBREG version number. */
+#define PDM_USBHUBREG_VERSION PDM_VERSION_MAKE(0xf0fd, 2, 0)
+
+
+/**
+ * USB hub helpers.
+ * This is currently just a place holder.
+ */
+typedef struct PDMUSBHUBHLP
+{
+ /** Structure version. PDM_USBHUBHLP_VERSION defines the current version. */
+ uint32_t u32Version;
+
+ /** Just a safety precaution. */
+ uint32_t u32TheEnd;
+} PDMUSBHUBHLP;
+/** Pointer to PCI helpers. */
+typedef PDMUSBHUBHLP *PPDMUSBHUBHLP;
+/** Pointer to const PCI helpers. */
+typedef const PDMUSBHUBHLP *PCPDMUSBHUBHLP;
+/** Pointer to const PCI helpers pointer. */
+typedef PCPDMUSBHUBHLP *PPCPDMUSBHUBHLP;
+
+/** Current PDMUSBHUBHLP version number. */
+#define PDM_USBHUBHLP_VERSION PDM_VERSION_MAKE(0xf0fc, 1, 0)
+
+
+/**
+ * PDM Driver API - raw-mode context variant.
+ */
+typedef struct PDMDRVHLPRC
+{
+ /** Structure version. PDM_DRVHLPRC_VERSION defines the current version. */
+ uint32_t u32Version;
+
+ /**
+ * Assert that the current thread is the emulation thread.
+ *
+ * @returns True if correct.
+ * @returns False if wrong.
+ * @param pDrvIns Driver instance.
+ * @param pszFile Filename of the assertion location.
+ * @param iLine Linenumber of the assertion location.
+ * @param pszFunction Function of the assertion location.
+ */
+ DECLRCCALLBACKMEMBER(bool, pfnAssertEMT,(PPDMDRVINS pDrvIns, const char *pszFile, unsigned iLine, const char *pszFunction));
+
+ /**
+ * Assert that the current thread is NOT the emulation thread.
+ *
+ * @returns True if correct.
+ * @returns False if wrong.
+ * @param pDrvIns Driver instance.
+ * @param pszFile Filename of the assertion location.
+ * @param iLine Linenumber of the assertion location.
+ * @param pszFunction Function of the assertion location.
+ */
+ DECLRCCALLBACKMEMBER(bool, pfnAssertOther,(PPDMDRVINS pDrvIns, const char *pszFile, unsigned iLine, const char *pszFunction));
+
+ /** @name Exported PDM Critical Section Functions
+ * @{ */
+ DECLRCCALLBACKMEMBER(int, pfnCritSectEnter,(PPDMDRVINS pDrvIns, PPDMCRITSECT pCritSect, int rcBusy));
+ DECLRCCALLBACKMEMBER(int, pfnCritSectEnterDebug,(PPDMDRVINS pDrvIns, PPDMCRITSECT pCritSect, int rcBusy, RTHCUINTPTR uId, RT_SRC_POS_DECL));
+ DECLRCCALLBACKMEMBER(int, pfnCritSectTryEnter,(PPDMDRVINS pDrvIns, PPDMCRITSECT pCritSect));
+ DECLRCCALLBACKMEMBER(int, pfnCritSectTryEnterDebug,(PPDMDRVINS pDrvIns, PPDMCRITSECT pCritSect, RTHCUINTPTR uId, RT_SRC_POS_DECL));
+ DECLRCCALLBACKMEMBER(int, pfnCritSectLeave,(PPDMDRVINS pDrvIns, PPDMCRITSECT pCritSect));
+ DECLRCCALLBACKMEMBER(bool, pfnCritSectIsOwner,(PPDMDRVINS pDrvIns, PCPDMCRITSECT pCritSect));
+ DECLRCCALLBACKMEMBER(bool, pfnCritSectIsInitialized,(PPDMDRVINS pDrvIns, PCPDMCRITSECT pCritSect));
+ DECLRCCALLBACKMEMBER(bool, pfnCritSectHasWaiters,(PPDMDRVINS pDrvIns, PCPDMCRITSECT pCritSect));
+ DECLRCCALLBACKMEMBER(uint32_t, pfnCritSectGetRecursion,(PPDMDRVINS pDrvIns, PCPDMCRITSECT pCritSect));
+ /** @} */
+
+ /**
+ * Obtains bandwidth in a bandwidth group.
+ *
+ * @returns True if bandwidth was allocated, false if not.
+ * @param pDrvIns The driver instance.
+ * @param pFilter Pointer to the filter that allocates bandwidth.
+ * @param cbTransfer Number of bytes to allocate.
+ */
+ DECLRCCALLBACKMEMBER(bool, pfnNetShaperAllocateBandwidth,(PPDMDRVINS pDrvIns, PPDMNSFILTER pFilter, size_t cbTransfer));
+
+ /** Just a safety precaution. */
+ uint32_t u32TheEnd;
+} PDMDRVHLPRC;
+/** Current PDMDRVHLPRC version number. */
+#define PDM_DRVHLPRC_VERSION PDM_VERSION_MAKE(0xf0f9, 6, 0)
+
+
+/**
+ * PDM Driver API, ring-0 context.
+ */
+typedef struct PDMDRVHLPR0
+{
+ /** Structure version. PDM_DRVHLPR0_VERSION defines the current version. */
+ uint32_t u32Version;
+
+ /**
+ * Assert that the current thread is the emulation thread.
+ *
+ * @returns True if correct.
+ * @returns False if wrong.
+ * @param pDrvIns Driver instance.
+ * @param pszFile Filename of the assertion location.
+ * @param iLine Linenumber of the assertion location.
+ * @param pszFunction Function of the assertion location.
+ */
+ DECLR0CALLBACKMEMBER(bool, pfnAssertEMT,(PPDMDRVINS pDrvIns, const char *pszFile, unsigned iLine, const char *pszFunction));
+
+ /**
+ * Assert that the current thread is NOT the emulation thread.
+ *
+ * @returns True if correct.
+ * @returns False if wrong.
+ * @param pDrvIns Driver instance.
+ * @param pszFile Filename of the assertion location.
+ * @param iLine Linenumber of the assertion location.
+ * @param pszFunction Function of the assertion location.
+ */
+ DECLR0CALLBACKMEMBER(bool, pfnAssertOther,(PPDMDRVINS pDrvIns, const char *pszFile, unsigned iLine, const char *pszFunction));
+
+ /** @name Exported PDM Critical Section Functions
+ * @{ */
+ DECLR0CALLBACKMEMBER(int, pfnCritSectEnter,(PPDMDRVINS pDrvIns, PPDMCRITSECT pCritSect, int rcBusy));
+ DECLR0CALLBACKMEMBER(int, pfnCritSectEnterDebug,(PPDMDRVINS pDrvIns, PPDMCRITSECT pCritSect, int rcBusy, RTHCUINTPTR uId, RT_SRC_POS_DECL));
+ DECLR0CALLBACKMEMBER(int, pfnCritSectTryEnter,(PPDMDRVINS pDrvIns, PPDMCRITSECT pCritSect));
+ DECLR0CALLBACKMEMBER(int, pfnCritSectTryEnterDebug,(PPDMDRVINS pDrvIns, PPDMCRITSECT pCritSect, RTHCUINTPTR uId, RT_SRC_POS_DECL));
+ DECLR0CALLBACKMEMBER(int, pfnCritSectLeave,(PPDMDRVINS pDrvIns, PPDMCRITSECT pCritSect));
+ DECLR0CALLBACKMEMBER(bool, pfnCritSectIsOwner,(PPDMDRVINS pDrvIns, PCPDMCRITSECT pCritSect));
+ DECLR0CALLBACKMEMBER(bool, pfnCritSectIsInitialized,(PPDMDRVINS pDrvIns, PCPDMCRITSECT pCritSect));
+ DECLR0CALLBACKMEMBER(bool, pfnCritSectHasWaiters,(PPDMDRVINS pDrvIns, PCPDMCRITSECT pCritSect));
+ DECLR0CALLBACKMEMBER(uint32_t, pfnCritSectGetRecursion,(PPDMDRVINS pDrvIns, PCPDMCRITSECT pCritSect));
+ DECLR0CALLBACKMEMBER(int, pfnCritSectScheduleExitEvent,(PPDMDRVINS pDrvIns, PPDMCRITSECT pCritSect, SUPSEMEVENT hEventToSignal));
+ /** @} */
+
+ /**
+ * Obtains bandwidth in a bandwidth group.
+ *
+ * @returns True if bandwidth was allocated, false if not.
+ * @param pDrvIns The driver instance.
+ * @param pFilter Pointer to the filter that allocates bandwidth.
+ * @param cbTransfer Number of bytes to allocate.
+ */
+ DECLR0CALLBACKMEMBER(bool, pfnNetShaperAllocateBandwidth,(PPDMDRVINS pDrvIns, PPDMNSFILTER pFilter, size_t cbTransfer));
+
+ /** Just a safety precaution. */
+ uint32_t u32TheEnd;
+} PDMDRVHLPR0;
+/** Current DRVHLP version number. */
+#define PDM_DRVHLPR0_VERSION PDM_VERSION_MAKE(0xf0f8, 6, 0)
+
+
+#ifdef IN_RING3
+
+/**
+ * PDM Driver API.
+ */
+typedef struct PDMDRVHLPR3
+{
+ /** Structure version. PDM_DRVHLPR3_VERSION defines the current version. */
+ uint32_t u32Version;
+
+ /**
+ * Attaches a driver (chain) to the driver.
+ *
+ * @returns VBox status code.
+ * @param pDrvIns Driver instance.
+ * @param fFlags PDM_TACH_FLAGS_NOT_HOT_PLUG or 0.
+ * @param ppBaseInterface Where to store the pointer to the base interface.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnAttach,(PPDMDRVINS pDrvIns, uint32_t fFlags, PPDMIBASE *ppBaseInterface));
+
+ /**
+ * Detach the driver the drivers below us.
+ *
+ * @returns VBox status code.
+ * @param pDrvIns Driver instance.
+ * @param fFlags PDM_TACH_FLAGS_NOT_HOT_PLUG or 0.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnDetach,(PPDMDRVINS pDrvIns, uint32_t fFlags));
+
+ /**
+ * Detach the driver from the driver above it and destroy this
+ * driver and all drivers below it.
+ *
+ * @returns VBox status code.
+ * @param pDrvIns Driver instance.
+ * @param fFlags PDM_TACH_FLAGS_NOT_HOT_PLUG or 0.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnDetachSelf,(PPDMDRVINS pDrvIns, uint32_t fFlags));
+
+ /**
+ * Prepare a media mount.
+ *
+ * The driver must not have anything attached to itself
+ * when calling this function as the purpose is to set up the configuration
+ * of an future attachment.
+ *
+ * @returns VBox status code
+ * @param pDrvIns Driver instance.
+ * @param pszFilename Pointer to filename. If this is NULL it assumed that the caller have
+ * constructed a configuration which can be attached to the bottom driver.
+ * @param pszCoreDriver Core driver name. NULL will cause autodetection. Ignored if pszFilanem is NULL.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnMountPrepare,(PPDMDRVINS pDrvIns, const char *pszFilename, const char *pszCoreDriver));
+
+ /**
+ * Assert that the current thread is the emulation thread.
+ *
+ * @returns True if correct.
+ * @returns False if wrong.
+ * @param pDrvIns Driver instance.
+ * @param pszFile Filename of the assertion location.
+ * @param iLine Linenumber of the assertion location.
+ * @param pszFunction Function of the assertion location.
+ */
+ DECLR3CALLBACKMEMBER(bool, pfnAssertEMT,(PPDMDRVINS pDrvIns, const char *pszFile, unsigned iLine, const char *pszFunction));
+
+ /**
+ * Assert that the current thread is NOT the emulation thread.
+ *
+ * @returns True if correct.
+ * @returns False if wrong.
+ * @param pDrvIns Driver instance.
+ * @param pszFile Filename of the assertion location.
+ * @param iLine Linenumber of the assertion location.
+ * @param pszFunction Function of the assertion location.
+ */
+ DECLR3CALLBACKMEMBER(bool, pfnAssertOther,(PPDMDRVINS pDrvIns, const char *pszFile, unsigned iLine, const char *pszFunction));
+
+ /**
+ * Set the VM error message
+ *
+ * @returns rc.
+ * @param pDrvIns Driver instance.
+ * @param rc VBox status code.
+ * @param SRC_POS Use RT_SRC_POS.
+ * @param pszFormat Error message format string.
+ * @param va Error message arguments.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnVMSetErrorV,(PPDMDRVINS pDrvIns, int rc, RT_SRC_POS_DECL,
+ const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(6, 0));
+
+ /**
+ * Set the VM runtime error message
+ *
+ * @returns VBox status code.
+ * @param pDrvIns Driver instance.
+ * @param fFlags The action flags. See VMSETRTERR_FLAGS_*.
+ * @param pszErrorId Error ID string.
+ * @param pszFormat Error message format string.
+ * @param va Error message arguments.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnVMSetRuntimeErrorV,(PPDMDRVINS pDrvIns, uint32_t fFlags, const char *pszErrorId,
+ const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(4, 0));
+
+ /**
+ * Gets the VM state.
+ *
+ * @returns VM state.
+ * @param pDrvIns The driver instance.
+ * @thread Any thread (just keep in mind that it's volatile info).
+ */
+ DECLR3CALLBACKMEMBER(VMSTATE, pfnVMState, (PPDMDRVINS pDrvIns));
+
+ /**
+ * Checks if the VM was teleported and hasn't been fully resumed yet.
+ *
+ * @returns true / false.
+ * @param pDrvIns The driver instance.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(bool, pfnVMTeleportedAndNotFullyResumedYet,(PPDMDRVINS pDrvIns));
+
+ /**
+ * Gets the support driver session.
+ *
+ * This is intended for working using the semaphore API.
+ *
+ * @returns Support driver session handle.
+ * @param pDrvIns The driver instance.
+ */
+ DECLR3CALLBACKMEMBER(PSUPDRVSESSION, pfnGetSupDrvSession,(PPDMDRVINS pDrvIns));
+
+ /** @name Exported PDM Queue Functions
+ * @{ */
+ /**
+ * Create a queue.
+ *
+ * @returns VBox status code.
+ * @param pDrvIns Driver instance.
+ * @param cbItem Size a queue item.
+ * @param cItems Number of items in the queue.
+ * @param cMilliesInterval Number of milliseconds between polling the queue.
+ * If 0 then the emulation thread will be notified whenever an item arrives.
+ * @param pfnCallback The consumer function.
+ * @param pszName The queue base name. The instance number will be
+ * appended automatically.
+ * @param phQueue Where to store the queue handle on success.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnQueueCreate,(PPDMDRVINS pDrvIns, uint32_t cbItem, uint32_t cItems, uint32_t cMilliesInterval,
+ PFNPDMQUEUEDRV pfnCallback, const char *pszName, PDMQUEUEHANDLE *phQueue));
+
+ DECLR3CALLBACKMEMBER(PPDMQUEUEITEMCORE, pfnQueueAlloc,(PPDMDRVINS pDrvIns, PDMQUEUEHANDLE hQueue));
+ DECLR3CALLBACKMEMBER(int, pfnQueueInsert,(PPDMDRVINS pDrvIns, PDMQUEUEHANDLE hQueue, PPDMQUEUEITEMCORE pItem));
+ DECLR3CALLBACKMEMBER(bool, pfnQueueFlushIfNecessary,(PPDMDRVINS pDrvIns, PDMQUEUEHANDLE hQueue));
+ /** @} */
+
+ /**
+ * Query the virtual timer frequency.
+ *
+ * @returns Frequency in Hz.
+ * @param pDrvIns Driver instance.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(uint64_t, pfnTMGetVirtualFreq,(PPDMDRVINS pDrvIns));
+
+ /**
+ * Query the virtual time.
+ *
+ * @returns The current virtual time.
+ * @param pDrvIns Driver instance.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(uint64_t, pfnTMGetVirtualTime,(PPDMDRVINS pDrvIns));
+
+ /**
+ * Creates a timer.
+ *
+ * @returns VBox status.
+ * @param pDrvIns Driver instance.
+ * @param enmClock The clock to use on this timer.
+ * @param pfnCallback Callback function.
+ * @param pvUser The user argument to the callback.
+ * @param fFlags Timer creation flags, see grp_tm_timer_flags.
+ * @param pszDesc Pointer to description string which must stay around
+ * until the timer is fully destroyed (i.e. a bit after TMTimerDestroy()).
+ * @param phTimer Where to store the timer handle on success.
+ * @thread EMT
+ *
+ * @todo Need to add a bunch of timer helpers for this to be useful again.
+ * Will do when required.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnTimerCreate,(PPDMDRVINS pDrvIns, TMCLOCK enmClock, PFNTMTIMERDRV pfnCallback, void *pvUser,
+ uint32_t fFlags, const char *pszDesc, PTMTIMERHANDLE phTimer));
+
+ /**
+ * Destroys a timer.
+ *
+ * @returns VBox status.
+ * @param pDrvIns Driver instance.
+ * @param hTimer The timer handle to destroy.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnTimerDestroy,(PPDMDRVINS pDrvIns, TMTIMERHANDLE hTimer));
+
+ /**
+ * Register a save state data unit.
+ *
+ * @returns VBox status.
+ * @param pDrvIns Driver instance.
+ * @param uVersion Data layout version number.
+ * @param cbGuess The approximate amount of data in the unit.
+ * Only for progress indicators.
+ *
+ * @param pfnLivePrep Prepare live save callback, optional.
+ * @param pfnLiveExec Execute live save callback, optional.
+ * @param pfnLiveVote Vote live save callback, optional.
+ *
+ * @param pfnSavePrep Prepare save callback, optional.
+ * @param pfnSaveExec Execute save callback, optional.
+ * @param pfnSaveDone Done save callback, optional.
+ *
+ * @param pfnLoadPrep Prepare load callback, optional.
+ * @param pfnLoadExec Execute load callback, optional.
+ * @param pfnLoadDone Done load callback, optional.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSSMRegister,(PPDMDRVINS pDrvIns, uint32_t uVersion, size_t cbGuess,
+ PFNSSMDRVLIVEPREP pfnLivePrep, PFNSSMDRVLIVEEXEC pfnLiveExec, PFNSSMDRVLIVEVOTE pfnLiveVote,
+ PFNSSMDRVSAVEPREP pfnSavePrep, PFNSSMDRVSAVEEXEC pfnSaveExec, PFNSSMDRVSAVEDONE pfnSaveDone,
+ PFNSSMDRVLOADPREP pfnLoadPrep, PFNSSMDRVLOADEXEC pfnLoadExec, PFNSSMDRVLOADDONE pfnLoadDone));
+
+ /**
+ * Deregister a save state data unit.
+ *
+ * @returns VBox status.
+ * @param pDrvIns Driver instance.
+ * @param pszName Data unit name.
+ * @param uInstance The instance identifier of the data unit.
+ * This must together with the name be unique.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSSMDeregister,(PPDMDRVINS pDrvIns, const char *pszName, uint32_t uInstance));
+
+ /** @name Exported SSM Functions
+ * @{ */
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutStruct,(PSSMHANDLE pSSM, const void *pvStruct, PCSSMFIELD paFields));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutStructEx,(PSSMHANDLE pSSM, const void *pvStruct, size_t cbStruct, uint32_t fFlags, PCSSMFIELD paFields, void *pvUser));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutBool,(PSSMHANDLE pSSM, bool fBool));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutU8,(PSSMHANDLE pSSM, uint8_t u8));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutS8,(PSSMHANDLE pSSM, int8_t i8));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutU16,(PSSMHANDLE pSSM, uint16_t u16));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutS16,(PSSMHANDLE pSSM, int16_t i16));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutU32,(PSSMHANDLE pSSM, uint32_t u32));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutS32,(PSSMHANDLE pSSM, int32_t i32));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutU64,(PSSMHANDLE pSSM, uint64_t u64));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutS64,(PSSMHANDLE pSSM, int64_t i64));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutU128,(PSSMHANDLE pSSM, uint128_t u128));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutS128,(PSSMHANDLE pSSM, int128_t i128));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutUInt,(PSSMHANDLE pSSM, RTUINT u));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutSInt,(PSSMHANDLE pSSM, RTINT i));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutGCUInt,(PSSMHANDLE pSSM, RTGCUINT u));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutGCUIntReg,(PSSMHANDLE pSSM, RTGCUINTREG u));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutGCPhys32,(PSSMHANDLE pSSM, RTGCPHYS32 GCPhys));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutGCPhys64,(PSSMHANDLE pSSM, RTGCPHYS64 GCPhys));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutGCPhys,(PSSMHANDLE pSSM, RTGCPHYS GCPhys));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutGCPtr,(PSSMHANDLE pSSM, RTGCPTR GCPtr));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutGCUIntPtr,(PSSMHANDLE pSSM, RTGCUINTPTR GCPtr));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutRCPtr,(PSSMHANDLE pSSM, RTRCPTR RCPtr));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutIOPort,(PSSMHANDLE pSSM, RTIOPORT IOPort));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutSel,(PSSMHANDLE pSSM, RTSEL Sel));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutMem,(PSSMHANDLE pSSM, const void *pv, size_t cb));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutStrZ,(PSSMHANDLE pSSM, const char *psz));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetStruct,(PSSMHANDLE pSSM, void *pvStruct, PCSSMFIELD paFields));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetStructEx,(PSSMHANDLE pSSM, void *pvStruct, size_t cbStruct, uint32_t fFlags, PCSSMFIELD paFields, void *pvUser));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetBool,(PSSMHANDLE pSSM, bool *pfBool));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetBoolV,(PSSMHANDLE pSSM, bool volatile *pfBool));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetU8,(PSSMHANDLE pSSM, uint8_t *pu8));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetU8V,(PSSMHANDLE pSSM, uint8_t volatile *pu8));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetS8,(PSSMHANDLE pSSM, int8_t *pi8));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetS8V,(PSSMHANDLE pSSM, int8_t volatile *pi8));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetU16,(PSSMHANDLE pSSM, uint16_t *pu16));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetU16V,(PSSMHANDLE pSSM, uint16_t volatile *pu16));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetS16,(PSSMHANDLE pSSM, int16_t *pi16));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetS16V,(PSSMHANDLE pSSM, int16_t volatile *pi16));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetU32,(PSSMHANDLE pSSM, uint32_t *pu32));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetU32V,(PSSMHANDLE pSSM, uint32_t volatile *pu32));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetS32,(PSSMHANDLE pSSM, int32_t *pi32));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetS32V,(PSSMHANDLE pSSM, int32_t volatile *pi32));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetU64,(PSSMHANDLE pSSM, uint64_t *pu64));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetU64V,(PSSMHANDLE pSSM, uint64_t volatile *pu64));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetS64,(PSSMHANDLE pSSM, int64_t *pi64));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetS64V,(PSSMHANDLE pSSM, int64_t volatile *pi64));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetU128,(PSSMHANDLE pSSM, uint128_t *pu128));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetU128V,(PSSMHANDLE pSSM, uint128_t volatile *pu128));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetS128,(PSSMHANDLE pSSM, int128_t *pi128));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetS128V,(PSSMHANDLE pSSM, int128_t volatile *pi128));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetGCPhys32,(PSSMHANDLE pSSM, PRTGCPHYS32 pGCPhys));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetGCPhys32V,(PSSMHANDLE pSSM, RTGCPHYS32 volatile *pGCPhys));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetGCPhys64,(PSSMHANDLE pSSM, PRTGCPHYS64 pGCPhys));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetGCPhys64V,(PSSMHANDLE pSSM, RTGCPHYS64 volatile *pGCPhys));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetGCPhys,(PSSMHANDLE pSSM, PRTGCPHYS pGCPhys));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetGCPhysV,(PSSMHANDLE pSSM, RTGCPHYS volatile *pGCPhys));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetUInt,(PSSMHANDLE pSSM, PRTUINT pu));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetSInt,(PSSMHANDLE pSSM, PRTINT pi));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetGCUInt,(PSSMHANDLE pSSM, PRTGCUINT pu));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetGCUIntReg,(PSSMHANDLE pSSM, PRTGCUINTREG pu));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetGCPtr,(PSSMHANDLE pSSM, PRTGCPTR pGCPtr));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetGCUIntPtr,(PSSMHANDLE pSSM, PRTGCUINTPTR pGCPtr));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetRCPtr,(PSSMHANDLE pSSM, PRTRCPTR pRCPtr));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetIOPort,(PSSMHANDLE pSSM, PRTIOPORT pIOPort));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetSel,(PSSMHANDLE pSSM, PRTSEL pSel));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetMem,(PSSMHANDLE pSSM, void *pv, size_t cb));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetStrZ,(PSSMHANDLE pSSM, char *psz, size_t cbMax));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetStrZEx,(PSSMHANDLE pSSM, char *psz, size_t cbMax, size_t *pcbStr));
+ DECLR3CALLBACKMEMBER(int, pfnSSMSkip,(PSSMHANDLE pSSM, size_t cb));
+ DECLR3CALLBACKMEMBER(int, pfnSSMSkipToEndOfUnit,(PSSMHANDLE pSSM));
+ DECLR3CALLBACKMEMBER(int, pfnSSMSetLoadError,(PSSMHANDLE pSSM, int rc, RT_SRC_POS_DECL, const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(6, 7));
+ DECLR3CALLBACKMEMBER(int, pfnSSMSetLoadErrorV,(PSSMHANDLE pSSM, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(6, 0));
+ DECLR3CALLBACKMEMBER(int, pfnSSMSetCfgError,(PSSMHANDLE pSSM, RT_SRC_POS_DECL, const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(5, 6));
+ DECLR3CALLBACKMEMBER(int, pfnSSMSetCfgErrorV,(PSSMHANDLE pSSM, RT_SRC_POS_DECL, const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(5, 0));
+ DECLR3CALLBACKMEMBER(int, pfnSSMHandleGetStatus,(PSSMHANDLE pSSM));
+ DECLR3CALLBACKMEMBER(SSMAFTER, pfnSSMHandleGetAfter,(PSSMHANDLE pSSM));
+ DECLR3CALLBACKMEMBER(bool, pfnSSMHandleIsLiveSave,(PSSMHANDLE pSSM));
+ DECLR3CALLBACKMEMBER(uint32_t, pfnSSMHandleMaxDowntime,(PSSMHANDLE pSSM));
+ DECLR3CALLBACKMEMBER(uint32_t, pfnSSMHandleHostBits,(PSSMHANDLE pSSM));
+ DECLR3CALLBACKMEMBER(uint32_t, pfnSSMHandleRevision,(PSSMHANDLE pSSM));
+ DECLR3CALLBACKMEMBER(uint32_t, pfnSSMHandleVersion,(PSSMHANDLE pSSM));
+ DECLR3CALLBACKMEMBER(const char *, pfnSSMHandleHostOSAndArch,(PSSMHANDLE pSSM));
+ /** @} */
+
+ /** @name Exported CFGM Functions.
+ * @{ */
+ DECLR3CALLBACKMEMBER(bool, pfnCFGMExists,( PCFGMNODE pNode, const char *pszName));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryType,( PCFGMNODE pNode, const char *pszName, PCFGMVALUETYPE penmType));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQuerySize,( PCFGMNODE pNode, const char *pszName, size_t *pcb));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryInteger,( PCFGMNODE pNode, const char *pszName, uint64_t *pu64));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryIntegerDef,( PCFGMNODE pNode, const char *pszName, uint64_t *pu64, uint64_t u64Def));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryString,( PCFGMNODE pNode, const char *pszName, char *pszString, size_t cchString));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryStringDef,( PCFGMNODE pNode, const char *pszName, char *pszString, size_t cchString, const char *pszDef));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryPassword,( PCFGMNODE pNode, const char *pszName, char *pszString, size_t cchString));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryPasswordDef,( PCFGMNODE pNode, const char *pszName, char *pszString, size_t cchString, const char *pszDef));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryBytes,( PCFGMNODE pNode, const char *pszName, void *pvData, size_t cbData));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryU64,( PCFGMNODE pNode, const char *pszName, uint64_t *pu64));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryU64Def,( PCFGMNODE pNode, const char *pszName, uint64_t *pu64, uint64_t u64Def));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryS64,( PCFGMNODE pNode, const char *pszName, int64_t *pi64));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryS64Def,( PCFGMNODE pNode, const char *pszName, int64_t *pi64, int64_t i64Def));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryU32,( PCFGMNODE pNode, const char *pszName, uint32_t *pu32));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryU32Def,( PCFGMNODE pNode, const char *pszName, uint32_t *pu32, uint32_t u32Def));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryS32,( PCFGMNODE pNode, const char *pszName, int32_t *pi32));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryS32Def,( PCFGMNODE pNode, const char *pszName, int32_t *pi32, int32_t i32Def));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryU16,( PCFGMNODE pNode, const char *pszName, uint16_t *pu16));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryU16Def,( PCFGMNODE pNode, const char *pszName, uint16_t *pu16, uint16_t u16Def));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryS16,( PCFGMNODE pNode, const char *pszName, int16_t *pi16));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryS16Def,( PCFGMNODE pNode, const char *pszName, int16_t *pi16, int16_t i16Def));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryU8,( PCFGMNODE pNode, const char *pszName, uint8_t *pu8));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryU8Def,( PCFGMNODE pNode, const char *pszName, uint8_t *pu8, uint8_t u8Def));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryS8,( PCFGMNODE pNode, const char *pszName, int8_t *pi8));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryS8Def,( PCFGMNODE pNode, const char *pszName, int8_t *pi8, int8_t i8Def));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryBool,( PCFGMNODE pNode, const char *pszName, bool *pf));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryBoolDef,( PCFGMNODE pNode, const char *pszName, bool *pf, bool fDef));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryPort,( PCFGMNODE pNode, const char *pszName, PRTIOPORT pPort));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryPortDef,( PCFGMNODE pNode, const char *pszName, PRTIOPORT pPort, RTIOPORT PortDef));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryUInt,( PCFGMNODE pNode, const char *pszName, unsigned int *pu));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryUIntDef,( PCFGMNODE pNode, const char *pszName, unsigned int *pu, unsigned int uDef));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQuerySInt,( PCFGMNODE pNode, const char *pszName, signed int *pi));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQuerySIntDef,( PCFGMNODE pNode, const char *pszName, signed int *pi, signed int iDef));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryGCPtr,( PCFGMNODE pNode, const char *pszName, PRTGCPTR pGCPtr));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryGCPtrDef,( PCFGMNODE pNode, const char *pszName, PRTGCPTR pGCPtr, RTGCPTR GCPtrDef));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryGCPtrU,( PCFGMNODE pNode, const char *pszName, PRTGCUINTPTR pGCPtr));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryGCPtrUDef,( PCFGMNODE pNode, const char *pszName, PRTGCUINTPTR pGCPtr, RTGCUINTPTR GCPtrDef));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryGCPtrS,( PCFGMNODE pNode, const char *pszName, PRTGCINTPTR pGCPtr));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryGCPtrSDef,( PCFGMNODE pNode, const char *pszName, PRTGCINTPTR pGCPtr, RTGCINTPTR GCPtrDef));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryStringAlloc,( PCFGMNODE pNode, const char *pszName, char **ppszString));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryStringAllocDef,(PCFGMNODE pNode, const char *pszName, char **ppszString, const char *pszDef));
+ DECLR3CALLBACKMEMBER(PCFGMNODE, pfnCFGMGetParent,(PCFGMNODE pNode));
+ DECLR3CALLBACKMEMBER(PCFGMNODE, pfnCFGMGetChild,(PCFGMNODE pNode, const char *pszPath));
+ DECLR3CALLBACKMEMBER(PCFGMNODE, pfnCFGMGetChildF,(PCFGMNODE pNode, const char *pszPathFormat, ...) RT_IPRT_FORMAT_ATTR(2, 3));
+ DECLR3CALLBACKMEMBER(PCFGMNODE, pfnCFGMGetChildFV,(PCFGMNODE pNode, const char *pszPathFormat, va_list Args) RT_IPRT_FORMAT_ATTR(3, 0));
+ DECLR3CALLBACKMEMBER(PCFGMNODE, pfnCFGMGetFirstChild,(PCFGMNODE pNode));
+ DECLR3CALLBACKMEMBER(PCFGMNODE, pfnCFGMGetNextChild,(PCFGMNODE pCur));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMGetName,(PCFGMNODE pCur, char *pszName, size_t cchName));
+ DECLR3CALLBACKMEMBER(size_t, pfnCFGMGetNameLen,(PCFGMNODE pCur));
+ DECLR3CALLBACKMEMBER(bool, pfnCFGMAreChildrenValid,(PCFGMNODE pNode, const char *pszzValid));
+ DECLR3CALLBACKMEMBER(PCFGMLEAF, pfnCFGMGetFirstValue,(PCFGMNODE pCur));
+ DECLR3CALLBACKMEMBER(PCFGMLEAF, pfnCFGMGetNextValue,(PCFGMLEAF pCur));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMGetValueName,(PCFGMLEAF pCur, char *pszName, size_t cchName));
+ DECLR3CALLBACKMEMBER(size_t, pfnCFGMGetValueNameLen,(PCFGMLEAF pCur));
+ DECLR3CALLBACKMEMBER(CFGMVALUETYPE, pfnCFGMGetValueType,(PCFGMLEAF pCur));
+ DECLR3CALLBACKMEMBER(bool, pfnCFGMAreValuesValid,(PCFGMNODE pNode, const char *pszzValid));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMValidateConfig,(PCFGMNODE pNode, const char *pszNode,
+ const char *pszValidValues, const char *pszValidNodes,
+ const char *pszWho, uint32_t uInstance));
+ /** @} */
+
+ /**
+ * Free memory allocated with pfnMMHeapAlloc() and pfnMMHeapAllocZ().
+ *
+ * @param pDrvIns Driver instance.
+ * @param pv Pointer to the memory to free.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnMMHeapFree,(PPDMDRVINS pDrvIns, void *pv));
+
+ /**
+ * Register an info handler with DBGF.
+ *
+ * @returns VBox status code.
+ * @param pDrvIns Driver instance.
+ * @param pszName Data unit name.
+ * @param pszDesc The description of the info and any arguments
+ * the handler may take.
+ * @param pfnHandler The handler function to be called to display the
+ * info.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnDBGFInfoRegister,(PPDMDRVINS pDrvIns, const char *pszName, const char *pszDesc, PFNDBGFHANDLERDRV pfnHandler));
+
+ /**
+ * Register an info handler with DBGF, argv style.
+ *
+ * @returns VBox status code.
+ * @param pDrvIns Driver instance.
+ * @param pszName Data unit name.
+ * @param pszDesc The description of the info and any arguments
+ * the handler may take.
+ * @param pfnHandler The handler function to be called to display the
+ * info.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnDBGFInfoRegisterArgv,(PPDMDRVINS pDrvIns, const char *pszName, const char *pszDesc, PFNDBGFINFOARGVDRV pfnHandler));
+
+ /**
+ * Deregister an info handler from DBGF.
+ *
+ * @returns VBox status code.
+ * @param pDrvIns Driver instance.
+ * @param pszName Data unit name.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnDBGFInfoDeregister,(PPDMDRVINS pDrvIns, const char *pszName));
+
+ /**
+ * Registers a statistics sample if statistics are enabled.
+ *
+ * @param pDrvIns Driver instance.
+ * @param pvSample Pointer to the sample.
+ * @param enmType Sample type. This indicates what pvSample is pointing at.
+ * @param pszName Sample name. The name is on this form "/<component>/<sample>".
+ * Further nesting is possible. If this does not start
+ * with a '/', the default prefix will be prepended,
+ * otherwise it will be used as-is.
+ * @param enmUnit Sample unit.
+ * @param pszDesc Sample description.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnSTAMRegister,(PPDMDRVINS pDrvIns, void *pvSample, STAMTYPE enmType, const char *pszName,
+ STAMUNIT enmUnit, const char *pszDesc));
+
+ /**
+ * Same as pfnSTAMRegister except that the name is specified in a
+ * RTStrPrintf like fashion.
+ *
+ * @param pDrvIns Driver instance.
+ * @param pvSample Pointer to the sample.
+ * @param enmType Sample type. This indicates what pvSample is pointing at.
+ * @param enmVisibility Visibility type specifying whether unused statistics should be visible or not.
+ * @param enmUnit Sample unit.
+ * @param pszDesc Sample description.
+ * @param pszName The sample name format string. If this does not start
+ * with a '/', the default prefix will be prepended,
+ * otherwise it will be used as-is.
+ * @param ... Arguments to the format string.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnSTAMRegisterF,(PPDMDRVINS pDrvIns, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility,
+ STAMUNIT enmUnit, const char *pszDesc,
+ const char *pszName, ...) RT_IPRT_FORMAT_ATTR(7, 8));
+
+ /**
+ * Same as pfnSTAMRegister except that the name is specified in a
+ * RTStrPrintfV like fashion.
+ *
+ * @param pDrvIns Driver instance.
+ * @param pvSample Pointer to the sample.
+ * @param enmType Sample type. This indicates what pvSample is pointing at.
+ * @param enmVisibility Visibility type specifying whether unused statistics should be visible or not.
+ * @param enmUnit Sample unit.
+ * @param pszDesc Sample description.
+ * @param pszName The sample name format string. If this does not
+ * start with a '/', the default prefix will be prepended,
+ * otherwise it will be used as-is.
+ * @param args Arguments to the format string.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnSTAMRegisterV,(PPDMDRVINS pDrvIns, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility,
+ STAMUNIT enmUnit, const char *pszDesc,
+ const char *pszName, va_list args) RT_IPRT_FORMAT_ATTR(7, 0));
+
+ /**
+ * Deregister a statistic item previously registered with pfnSTAMRegister,
+ * pfnSTAMRegisterF or pfnSTAMRegisterV
+ *
+ * @returns VBox status.
+ * @param pDrvIns Driver instance.
+ * @param pvSample Pointer to the sample.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSTAMDeregister,(PPDMDRVINS pDrvIns, void *pvSample));
+
+ /**
+ * Calls the HC R0 VMM entry point, in a safer but slower manner than
+ * SUPR3CallVMMR0.
+ *
+ * When entering using this call the R0 components can call into the host kernel
+ * (i.e. use the SUPR0 and RT APIs).
+ *
+ * See VMMR0Entry() for more details.
+ *
+ * @returns error code specific to uFunction.
+ * @param pDrvIns The driver instance.
+ * @param uOperation Operation to execute.
+ * This is limited to services.
+ * @param pvArg Pointer to argument structure or if cbArg is 0 just an value.
+ * @param cbArg The size of the argument. This is used to copy whatever the argument
+ * points at into a kernel buffer to avoid problems like the user page
+ * being invalidated while we're executing the call.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSUPCallVMMR0Ex,(PPDMDRVINS pDrvIns, unsigned uOperation, void *pvArg, unsigned cbArg));
+
+ /**
+ * Registers a USB HUB.
+ *
+ * @returns VBox status code.
+ * @param pDrvIns The driver instance.
+ * @param fVersions Indicates the kinds of USB devices that can be attached to this HUB.
+ * @param cPorts The number of ports.
+ * @param pUsbHubReg The hub callback structure that PDMUsb uses to interact with it.
+ * @param ppUsbHubHlp The helper callback structure that the hub uses to talk to PDMUsb.
+ *
+ * @thread EMT.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnUSBRegisterHub,(PPDMDRVINS pDrvIns, uint32_t fVersions, uint32_t cPorts, PCPDMUSBHUBREG pUsbHubReg, PPCPDMUSBHUBHLP ppUsbHubHlp));
+
+ /**
+ * Set up asynchronous handling of a suspend, reset or power off notification.
+ *
+ * This shall only be called when getting the notification. It must be called
+ * for each one.
+ *
+ * @returns VBox status code.
+ * @param pDrvIns The driver instance.
+ * @param pfnAsyncNotify The callback.
+ * @thread EMT(0)
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSetAsyncNotification, (PPDMDRVINS pDrvIns, PFNPDMDRVASYNCNOTIFY pfnAsyncNotify));
+
+ /**
+ * Notify EMT(0) that the driver has completed the asynchronous notification
+ * handling.
+ *
+ * This can be called at any time, spurious calls will simply be ignored.
+ *
+ * @param pDrvIns The driver instance.
+ * @thread Any
+ */
+ DECLR3CALLBACKMEMBER(void, pfnAsyncNotificationCompleted, (PPDMDRVINS pDrvIns));
+
+ /**
+ * Creates a PDM thread.
+ *
+ * This differs from the RTThreadCreate() API in that PDM takes care of suspending,
+ * resuming, and destroying the thread as the VM state changes.
+ *
+ * @returns VBox status code.
+ * @param pDrvIns The driver instance.
+ * @param ppThread Where to store the thread 'handle'.
+ * @param pvUser The user argument to the thread function.
+ * @param pfnThread The thread function.
+ * @param pfnWakeup The wakup callback. This is called on the EMT thread when
+ * a state change is pending.
+ * @param cbStack See RTThreadCreate.
+ * @param enmType See RTThreadCreate.
+ * @param pszName See RTThreadCreate.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnThreadCreate,(PPDMDRVINS pDrvIns, PPPDMTHREAD ppThread, void *pvUser, PFNPDMTHREADDRV pfnThread,
+ PFNPDMTHREADWAKEUPDRV pfnWakeup, size_t cbStack, RTTHREADTYPE enmType, const char *pszName));
+
+ /** @name Exported PDM Thread Functions
+ * @{ */
+ DECLR3CALLBACKMEMBER(int, pfnThreadDestroy,(PPDMTHREAD pThread, int *pRcThread));
+ DECLR3CALLBACKMEMBER(int, pfnThreadIAmSuspending,(PPDMTHREAD pThread));
+ DECLR3CALLBACKMEMBER(int, pfnThreadIAmRunning,(PPDMTHREAD pThread));
+ DECLR3CALLBACKMEMBER(int, pfnThreadSleep,(PPDMTHREAD pThread, RTMSINTERVAL cMillies));
+ DECLR3CALLBACKMEMBER(int, pfnThreadSuspend,(PPDMTHREAD pThread));
+ DECLR3CALLBACKMEMBER(int, pfnThreadResume,(PPDMTHREAD pThread));
+ /** @} */
+
+ /**
+ * Creates an async completion template for a driver instance.
+ *
+ * The template is used when creating new completion tasks.
+ *
+ * @returns VBox status code.
+ * @param pDrvIns The driver instance.
+ * @param ppTemplate Where to store the template pointer on success.
+ * @param pfnCompleted The completion callback routine.
+ * @param pvTemplateUser Template user argument.
+ * @param pszDesc Description.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnAsyncCompletionTemplateCreate,(PPDMDRVINS pDrvIns, PPPDMASYNCCOMPLETIONTEMPLATE ppTemplate,
+ PFNPDMASYNCCOMPLETEDRV pfnCompleted, void *pvTemplateUser,
+ const char *pszDesc));
+
+ /** @name Exported PDM Async Completion Functions
+ * @{ */
+ DECLR3CALLBACKMEMBER(int, pfnAsyncCompletionTemplateDestroy,(PPDMASYNCCOMPLETIONTEMPLATE pTemplate));
+ DECLR3CALLBACKMEMBER(int, pfnAsyncCompletionEpCreateForFile,(PPPDMASYNCCOMPLETIONENDPOINT ppEndpoint,
+ const char *pszFilename, uint32_t fFlags,
+ PPDMASYNCCOMPLETIONTEMPLATE pTemplate));
+ DECLR3CALLBACKMEMBER(void, pfnAsyncCompletionEpClose,(PPDMASYNCCOMPLETIONENDPOINT pEndpoint));
+ DECLR3CALLBACKMEMBER(int, pfnAsyncCompletionEpGetSize,(PPDMASYNCCOMPLETIONENDPOINT pEndpoint, uint64_t *pcbSize));
+ DECLR3CALLBACKMEMBER(int, pfnAsyncCompletionEpSetSize,(PPDMASYNCCOMPLETIONENDPOINT pEndpoint, uint64_t cbSize));
+ DECLR3CALLBACKMEMBER(int, pfnAsyncCompletionEpSetBwMgr,(PPDMASYNCCOMPLETIONENDPOINT pEndpoint, const char *pszBwMgr));
+ DECLR3CALLBACKMEMBER(int, pfnAsyncCompletionEpFlush,(PPDMASYNCCOMPLETIONENDPOINT pEndpoint, void *pvUser, PPPDMASYNCCOMPLETIONTASK ppTask));
+ DECLR3CALLBACKMEMBER(int, pfnAsyncCompletionEpRead,(PPDMASYNCCOMPLETIONENDPOINT pEndpoint, RTFOFF off,
+ PCRTSGSEG paSegments, unsigned cSegments,
+ size_t cbRead, void *pvUser,
+ PPPDMASYNCCOMPLETIONTASK ppTask));
+ DECLR3CALLBACKMEMBER(int, pfnAsyncCompletionEpWrite,(PPDMASYNCCOMPLETIONENDPOINT pEndpoint, RTFOFF off,
+ PCRTSGSEG paSegments, unsigned cSegments,
+ size_t cbWrite, void *pvUser,
+ PPPDMASYNCCOMPLETIONTASK ppTask));
+ /** @} */
+
+
+ /**
+ * Attaches a network filter driver to a named bandwidth group.
+ *
+ * @returns VBox status code.
+ * @retval VERR_ALREADY_INITIALIZED if already attached to a group.
+ * @param pDrvIns The driver instance.
+ * @param pszBwGroup Name of the bandwidth group to attach to.
+ * @param pFilter Pointer to the filter we attach.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnNetShaperAttach,(PPDMDRVINS pDrvIns, const char *pszBwGroup, PPDMNSFILTER pFilter));
+
+ /**
+ * Detaches a network filter driver from its current bandwidth group (if any).
+ *
+ * @returns VBox status code.
+ * @param pDrvIns The driver instance.
+ * @param pFilter Pointer to the filter we attach.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnNetShaperDetach,(PPDMDRVINS pDrvIns, PPDMNSFILTER pFilter));
+
+ /**
+ * Obtains bandwidth in a bandwidth group.
+ *
+ * @returns True if bandwidth was allocated, false if not.
+ * @param pDrvIns The driver instance.
+ * @param pFilter Pointer to the filter that allocates bandwidth.
+ * @param cbTransfer Number of bytes to allocate.
+ */
+ DECLR3CALLBACKMEMBER(bool, pfnNetShaperAllocateBandwidth,(PPDMDRVINS pDrvIns, PPDMNSFILTER pFilter, size_t cbTransfer));
+
+ /**
+ * Resolves the symbol for a raw-mode context interface.
+ *
+ * @returns VBox status code.
+ * @param pDrvIns The driver instance.
+ * @param pvInterface The interface structure.
+ * @param cbInterface The size of the interface structure.
+ * @param pszSymPrefix What to prefix the symbols in the list with before
+ * resolving them. This must start with 'drv' and
+ * contain the driver name.
+ * @param pszSymList List of symbols corresponding to the interface.
+ * There is generally a there is generally a define
+ * holding this list associated with the interface
+ * definition (INTERFACE_SYM_LIST). For more details
+ * see PDMR3LdrGetInterfaceSymbols.
+ * @thread EMT
+ */
+ DECLR3CALLBACKMEMBER(int, pfnLdrGetRCInterfaceSymbols,(PPDMDRVINS pDrvIns, void *pvInterface, size_t cbInterface,
+ const char *pszSymPrefix, const char *pszSymList));
+
+ /**
+ * Resolves the symbol for a ring-0 context interface.
+ *
+ * @returns VBox status code.
+ * @param pDrvIns The driver instance.
+ * @param pvInterface The interface structure.
+ * @param cbInterface The size of the interface structure.
+ * @param pszSymPrefix What to prefix the symbols in the list with before
+ * resolving them. This must start with 'drv' and
+ * contain the driver name.
+ * @param pszSymList List of symbols corresponding to the interface.
+ * There is generally a there is generally a define
+ * holding this list associated with the interface
+ * definition (INTERFACE_SYM_LIST). For more details
+ * see PDMR3LdrGetInterfaceSymbols.
+ * @thread EMT
+ */
+ DECLR3CALLBACKMEMBER(int, pfnLdrGetR0InterfaceSymbols,(PPDMDRVINS pDrvIns, void *pvInterface, size_t cbInterface,
+ const char *pszSymPrefix, const char *pszSymList));
+ /**
+ * Initializes a PDM critical section.
+ *
+ * The PDM critical sections are derived from the IPRT critical sections, but
+ * works in both RC and R0 as well as R3.
+ *
+ * @returns VBox status code.
+ * @param pDrvIns The driver instance.
+ * @param pCritSect Pointer to the critical section.
+ * @param SRC_POS Use RT_SRC_POS.
+ * @param pszName The base name of the critical section. Will be
+ * mangeled with the instance number. For
+ * statistics and lock validation.
+ * @thread EMT
+ */
+ DECLR3CALLBACKMEMBER(int, pfnCritSectInit,(PPDMDRVINS pDrvIns, PPDMCRITSECT pCritSect, RT_SRC_POS_DECL, const char *pszName));
+
+ /** @name Exported PDM Critical Section Functions
+ * @{ */
+ DECLR3CALLBACKMEMBER(bool, pfnCritSectYield,(PPDMDRVINS pDrvIns, PPDMCRITSECT pCritSect));
+ DECLR3CALLBACKMEMBER(int, pfnCritSectEnter,(PPDMDRVINS pDrvIns, PPDMCRITSECT pCritSect, int rcBusy));
+ DECLR3CALLBACKMEMBER(int, pfnCritSectEnterDebug,(PPDMDRVINS pDrvIns, PPDMCRITSECT pCritSect, int rcBusy, RTHCUINTPTR uId, RT_SRC_POS_DECL));
+ DECLR3CALLBACKMEMBER(int, pfnCritSectTryEnter,(PPDMDRVINS pDrvIns, PPDMCRITSECT pCritSect));
+ DECLR3CALLBACKMEMBER(int, pfnCritSectTryEnterDebug,(PPDMDRVINS pDrvIns, PPDMCRITSECT pCritSect, RTHCUINTPTR uId, RT_SRC_POS_DECL));
+ DECLR3CALLBACKMEMBER(int, pfnCritSectLeave,(PPDMDRVINS pDrvIns, PPDMCRITSECT pCritSect));
+ DECLR3CALLBACKMEMBER(bool, pfnCritSectIsOwner,(PPDMDRVINS pDrvIns, PCPDMCRITSECT pCritSect));
+ DECLR3CALLBACKMEMBER(bool, pfnCritSectIsInitialized,(PPDMDRVINS pDrvIns, PCPDMCRITSECT pCritSect));
+ DECLR3CALLBACKMEMBER(bool, pfnCritSectHasWaiters,(PPDMDRVINS pDrvIns, PCPDMCRITSECT pCritSect));
+ DECLR3CALLBACKMEMBER(uint32_t, pfnCritSectGetRecursion,(PPDMDRVINS pDrvIns, PCPDMCRITSECT pCritSect));
+ DECLR3CALLBACKMEMBER(int, pfnCritSectScheduleExitEvent,(PPDMDRVINS pDrvIns, PPDMCRITSECT pCritSect, SUPSEMEVENT hEventToSignal));
+ DECLR3CALLBACKMEMBER(int, pfnCritSectDelete,(PPDMDRVINS pDrvIns, PPDMCRITSECT pCritSect));
+ /** @} */
+
+ /**
+ * Call the ring-0 request handler routine of the driver.
+ *
+ * For this to work, the driver must be ring-0 enabled and export a request
+ * handler function. The name of the function must be the driver name in the
+ * PDMDRVREG struct prefixed with 'drvR0' and suffixed with 'ReqHandler'.
+ * The driver name will be capitalized. It shall take the exact same
+ * arguments as this function and be declared using PDMBOTHCBDECL. See
+ * FNPDMDRVREQHANDLERR0.
+ *
+ * @returns VBox status code.
+ * @retval VERR_SYMBOL_NOT_FOUND if the driver doesn't export the required
+ * handler function.
+ * @retval VERR_ACCESS_DENIED if the driver isn't ring-0 capable.
+ *
+ * @param pDrvIns The driver instance.
+ * @param uOperation The operation to perform.
+ * @param u64Arg 64-bit integer argument.
+ * @thread Any
+ */
+ DECLR3CALLBACKMEMBER(int, pfnCallR0,(PPDMDRVINS pDrvIns, uint32_t uOperation, uint64_t u64Arg));
+
+ /**
+ * Creates a block cache for a driver driver instance.
+ *
+ * @returns VBox status code.
+ * @param pDrvIns The driver instance.
+ * @param ppBlkCache Where to store the handle to the block cache.
+ * @param pfnXferComplete The I/O transfer complete callback.
+ * @param pfnXferEnqueue The I/O request enqueue callback.
+ * @param pfnXferEnqueueDiscard The discard request enqueue callback.
+ * @param pcszId Unique ID used to identify the user.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnBlkCacheRetain, (PPDMDRVINS pDrvIns, PPPDMBLKCACHE ppBlkCache,
+ PFNPDMBLKCACHEXFERCOMPLETEDRV pfnXferComplete,
+ PFNPDMBLKCACHEXFERENQUEUEDRV pfnXferEnqueue,
+ PFNPDMBLKCACHEXFERENQUEUEDISCARDDRV pfnXferEnqueueDiscard,
+ const char *pcszId));
+
+ /** @name Exported PDM Block Cache Functions
+ * @{ */
+ DECLR3CALLBACKMEMBER(void, pfnBlkCacheRelease,(PPDMBLKCACHE pBlkCache));
+ DECLR3CALLBACKMEMBER(int, pfnBlkCacheClear,(PPDMBLKCACHE pBlkCache));
+ DECLR3CALLBACKMEMBER(int, pfnBlkCacheSuspend,(PPDMBLKCACHE pBlkCache));
+ DECLR3CALLBACKMEMBER(int, pfnBlkCacheResume,(PPDMBLKCACHE pBlkCache));
+ DECLR3CALLBACKMEMBER(void, pfnBlkCacheIoXferComplete,(PPDMBLKCACHE pBlkCache, PPDMBLKCACHEIOXFER hIoXfer, int rcIoXfer));
+ DECLR3CALLBACKMEMBER(int, pfnBlkCacheRead,(PPDMBLKCACHE pBlkCache, uint64_t off, PCRTSGBUF pSgBuf, size_t cbRead, void *pvUser));
+ DECLR3CALLBACKMEMBER(int, pfnBlkCacheWrite,(PPDMBLKCACHE pBlkCache, uint64_t off, PCRTSGBUF pSgBuf, size_t cbRead, void *pvUser));
+ DECLR3CALLBACKMEMBER(int, pfnBlkCacheFlush,(PPDMBLKCACHE pBlkCache, void *pvUser));
+ DECLR3CALLBACKMEMBER(int, pfnBlkCacheDiscard,(PPDMBLKCACHE pBlkCache, PCRTRANGE paRanges, unsigned cRanges, void *pvUser));
+ /** @} */
+
+ /**
+ * Gets the reason for the most recent VM suspend.
+ *
+ * @returns The suspend reason. VMSUSPENDREASON_INVALID is returned if no
+ * suspend has been made or if the pDrvIns is invalid.
+ * @param pDrvIns The driver instance.
+ */
+ DECLR3CALLBACKMEMBER(VMSUSPENDREASON, pfnVMGetSuspendReason,(PPDMDRVINS pDrvIns));
+
+ /**
+ * Gets the reason for the most recent VM resume.
+ *
+ * @returns The resume reason. VMRESUMEREASON_INVALID is returned if no
+ * resume has been made or if the pDrvIns is invalid.
+ * @param pDrvIns The driver instance.
+ */
+ DECLR3CALLBACKMEMBER(VMRESUMEREASON, pfnVMGetResumeReason,(PPDMDRVINS pDrvIns));
+
+ /** @name Space reserved for minor interface changes.
+ * @{ */
+ DECLR3CALLBACKMEMBER(int, pfnTimerSetMillies,(PPDMDRVINS pDrvIns, TMTIMERHANDLE hTimer, uint64_t cMilliesToNext));
+
+ /**
+ * Deregister zero or more samples given their name prefix.
+ *
+ * @returns VBox status code.
+ * @param pDrvIns The driver instance.
+ * @param pszPrefix The name prefix of the samples to remove. If this does
+ * not start with a '/', the default prefix will be
+ * prepended, otherwise it will be used as-is.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSTAMDeregisterByPrefix,(PPDMDRVINS pDrvIns, const char *pszPrefix));
+
+ /**
+ * Queries a generic object from the VMM user.
+ *
+ * @returns Pointer to the object if found, NULL if not.
+ * @param pDrvIns The driver instance.
+ * @param pUuid The UUID of what's being queried. The UUIDs and
+ * the usage conventions are defined by the user.
+ */
+ DECLR3CALLBACKMEMBER(void *, pfnQueryGenericUserObject,(PPDMDRVINS pDrvIns, PCRTUUID pUuid));
+
+ DECLR3CALLBACKMEMBER(void, pfnReserved0,(PPDMDRVINS pDrvIns));
+ DECLR3CALLBACKMEMBER(void, pfnReserved1,(PPDMDRVINS pDrvIns));
+ DECLR3CALLBACKMEMBER(void, pfnReserved2,(PPDMDRVINS pDrvIns));
+ DECLR3CALLBACKMEMBER(void, pfnReserved3,(PPDMDRVINS pDrvIns));
+ DECLR3CALLBACKMEMBER(void, pfnReserved4,(PPDMDRVINS pDrvIns));
+ DECLR3CALLBACKMEMBER(void, pfnReserved5,(PPDMDRVINS pDrvIns));
+ DECLR3CALLBACKMEMBER(void, pfnReserved6,(PPDMDRVINS pDrvIns));
+ DECLR3CALLBACKMEMBER(void, pfnReserved7,(PPDMDRVINS pDrvIns));
+ DECLR3CALLBACKMEMBER(void, pfnReserved8,(PPDMDRVINS pDrvIns));
+ /** @} */
+
+ /** Just a safety precaution. */
+ uint32_t u32TheEnd;
+} PDMDRVHLPR3;
+/** Current DRVHLP version number. */
+#define PDM_DRVHLPR3_VERSION PDM_VERSION_MAKE(0xf0fb, 16, 0)
+
+
+/**
+ * Set the VM error message
+ *
+ * @returns rc.
+ * @param pDrvIns Driver instance.
+ * @param rc VBox status code.
+ * @param SRC_POS Use RT_SRC_POS.
+ * @param pszFormat Error message format string.
+ * @param ... Error message arguments.
+ * @sa PDMDRV_SET_ERROR, PDMDrvHlpVMSetErrorV, VMSetError
+ */
+DECLINLINE(int) RT_IPRT_FORMAT_ATTR(6, 7) PDMDrvHlpVMSetError(PPDMDRVINS pDrvIns, const int rc, RT_SRC_POS_DECL,
+ const char *pszFormat, ...)
+{
+ va_list va;
+ va_start(va, pszFormat);
+ pDrvIns->CTX_SUFF(pHlp)->pfnVMSetErrorV(pDrvIns, rc, RT_SRC_POS_ARGS, pszFormat, va);
+ va_end(va);
+ return rc;
+}
+
+/** @def PDMDRV_SET_ERROR
+ * Set the VM error. See PDMDrvHlpVMSetError() for printf like message formatting.
+ */
+#define PDMDRV_SET_ERROR(pDrvIns, rc, pszError) \
+ PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, "%s", pszError)
+
+/**
+ * @copydoc PDMDRVHLPR3::pfnVMSetErrorV
+ */
+DECLINLINE(int) RT_IPRT_FORMAT_ATTR(6, 0) PDMDrvHlpVMSetErrorV(PPDMDRVINS pDrvIns, const int rc, RT_SRC_POS_DECL,
+ const char *pszFormat, va_list va)
+{
+ return pDrvIns->CTX_SUFF(pHlp)->pfnVMSetErrorV(pDrvIns, rc, RT_SRC_POS_ARGS, pszFormat, va);
+}
+
+
+/**
+ * Set the VM runtime error message
+ *
+ * @returns VBox status code.
+ * @param pDrvIns Driver instance.
+ * @param fFlags The action flags. See VMSETRTERR_FLAGS_*.
+ * @param pszErrorId Error ID string.
+ * @param pszFormat Error message format string.
+ * @param ... Error message arguments.
+ * @sa PDMDRV_SET_RUNTIME_ERROR, PDMDrvHlpVMSetRuntimeErrorV,
+ * VMSetRuntimeError
+ */
+DECLINLINE(int) RT_IPRT_FORMAT_ATTR(4, 5) PDMDrvHlpVMSetRuntimeError(PPDMDRVINS pDrvIns, uint32_t fFlags, const char *pszErrorId,
+ const char *pszFormat, ...)
+{
+ va_list va;
+ int rc;
+ va_start(va, pszFormat);
+ rc = pDrvIns->CTX_SUFF(pHlp)->pfnVMSetRuntimeErrorV(pDrvIns, fFlags, pszErrorId, pszFormat, va);
+ va_end(va);
+ return rc;
+}
+
+/** @def PDMDRV_SET_RUNTIME_ERROR
+ * Set the VM runtime error. See PDMDrvHlpVMSetRuntimeError() for printf like message formatting.
+ */
+#define PDMDRV_SET_RUNTIME_ERROR(pDrvIns, fFlags, pszErrorId, pszError) \
+ PDMDrvHlpVMSetRuntimeError(pDrvIns, fFlags, pszErrorId, "%s", pszError)
+
+/**
+ * @copydoc PDMDRVHLPR3::pfnVMSetRuntimeErrorV
+ */
+DECLINLINE(int) RT_IPRT_FORMAT_ATTR(4, 0) PDMDrvHlpVMSetRuntimeErrorV(PPDMDRVINS pDrvIns, uint32_t fFlags,
+ const char *pszErrorId, const char *pszFormat, va_list va)
+{
+ return pDrvIns->CTX_SUFF(pHlp)->pfnVMSetRuntimeErrorV(pDrvIns, fFlags, pszErrorId, pszFormat, va);
+}
+
+#endif /* IN_RING3 */
+
+/** @def PDMDRV_ASSERT_EMT
+ * Assert that the current thread is the emulation thread.
+ */
+#ifdef VBOX_STRICT
+# define PDMDRV_ASSERT_EMT(pDrvIns) pDrvIns->CTX_SUFF(pHlp)->pfnAssertEMT(pDrvIns, __FILE__, __LINE__, __FUNCTION__)
+#else
+# define PDMDRV_ASSERT_EMT(pDrvIns) do { } while (0)
+#endif
+
+/** @def PDMDRV_ASSERT_OTHER
+ * Assert that the current thread is NOT the emulation thread.
+ */
+#ifdef VBOX_STRICT
+# define PDMDRV_ASSERT_OTHER(pDrvIns) pDrvIns->CTX_SUFF(pHlp)->pfnAssertOther(pDrvIns, __FILE__, __LINE__, __FUNCTION__)
+#else
+# define PDMDRV_ASSERT_OTHER(pDrvIns) do { } while (0)
+#endif
+
+
+#ifdef IN_RING3
+
+/**
+ * @copydoc PDMDRVHLPR3::pfnAttach
+ */
+DECLINLINE(int) PDMDrvHlpAttach(PPDMDRVINS pDrvIns, uint32_t fFlags, PPDMIBASE *ppBaseInterface)
+{
+ return pDrvIns->pHlpR3->pfnAttach(pDrvIns, fFlags, ppBaseInterface);
+}
+
+/**
+ * Check that there is no driver below the us that we should attach to.
+ *
+ * @returns VERR_PDM_NO_ATTACHED_DRIVER if there is no driver.
+ * @param pDrvIns The driver instance.
+ */
+DECLINLINE(int) PDMDrvHlpNoAttach(PPDMDRVINS pDrvIns)
+{
+ return pDrvIns->pHlpR3->pfnAttach(pDrvIns, 0, NULL);
+}
+
+/**
+ * @copydoc PDMDRVHLPR3::pfnDetach
+ */
+DECLINLINE(int) PDMDrvHlpDetach(PPDMDRVINS pDrvIns, uint32_t fFlags)
+{
+ return pDrvIns->pHlpR3->pfnDetach(pDrvIns, fFlags);
+}
+
+/**
+ * @copydoc PDMDRVHLPR3::pfnDetachSelf
+ */
+DECLINLINE(int) PDMDrvHlpDetachSelf(PPDMDRVINS pDrvIns, uint32_t fFlags)
+{
+ return pDrvIns->pHlpR3->pfnDetachSelf(pDrvIns, fFlags);
+}
+
+/**
+ * @copydoc PDMDRVHLPR3::pfnMountPrepare
+ */
+DECLINLINE(int) PDMDrvHlpMountPrepare(PPDMDRVINS pDrvIns, const char *pszFilename, const char *pszCoreDriver)
+{
+ return pDrvIns->pHlpR3->pfnMountPrepare(pDrvIns, pszFilename, pszCoreDriver);
+}
+
+/**
+ * @copydoc PDMDRVHLPR3::pfnVMState
+ */
+DECLINLINE(VMSTATE) PDMDrvHlpVMState(PPDMDRVINS pDrvIns)
+{
+ return pDrvIns->CTX_SUFF(pHlp)->pfnVMState(pDrvIns);
+}
+
+/**
+ * @copydoc PDMDRVHLPR3::pfnVMTeleportedAndNotFullyResumedYet
+ */
+DECLINLINE(bool) PDMDrvHlpVMTeleportedAndNotFullyResumedYet(PPDMDRVINS pDrvIns)
+{
+ return pDrvIns->pHlpR3->pfnVMTeleportedAndNotFullyResumedYet(pDrvIns);
+}
+
+/**
+ * @copydoc PDMDRVHLPR3::pfnGetSupDrvSession
+ */
+DECLINLINE(PSUPDRVSESSION) PDMDrvHlpGetSupDrvSession(PPDMDRVINS pDrvIns)
+{
+ return pDrvIns->pHlpR3->pfnGetSupDrvSession(pDrvIns);
+}
+
+/**
+ * @copydoc PDMDRVHLPR3::pfnQueueCreate
+ */
+DECLINLINE(int) PDMDrvHlpQueueCreate(PPDMDRVINS pDrvIns, uint32_t cbItem, uint32_t cItems, uint32_t cMilliesInterval,
+ PFNPDMQUEUEDRV pfnCallback, const char *pszName, PDMQUEUEHANDLE *phQueue)
+{
+ return pDrvIns->pHlpR3->pfnQueueCreate(pDrvIns, cbItem, cItems, cMilliesInterval, pfnCallback, pszName, phQueue);
+}
+
+/**
+ * @copydoc PDMDRVHLPR3::pfnQueueAlloc
+ */
+DECLINLINE(PPDMQUEUEITEMCORE) PDMDrvHlpQueueAlloc(PPDMDRVINS pDrvIns, PDMQUEUEHANDLE hQueue)
+{
+ return pDrvIns->CTX_SUFF(pHlp)->pfnQueueAlloc(pDrvIns, hQueue);
+}
+
+/**
+ * @copydoc PDMDRVHLPR3::pfnQueueInsert
+ */
+DECLINLINE(int) PDMDrvHlpQueueInsert(PPDMDRVINS pDrvIns, PDMQUEUEHANDLE hQueue, PPDMQUEUEITEMCORE pItem)
+{
+ return pDrvIns->CTX_SUFF(pHlp)->pfnQueueInsert(pDrvIns, hQueue, pItem);
+}
+
+/**
+ * @copydoc PDMDRVHLPR3::pfnQueueFlushIfNecessary
+ */
+DECLINLINE(bool) PDMDrvHlpQueueFlushIfNecessary(PPDMDRVINS pDrvIns, PDMQUEUEHANDLE hQueue)
+{
+ return pDrvIns->CTX_SUFF(pHlp)->pfnQueueFlushIfNecessary(pDrvIns, hQueue);
+}
+
+/**
+ * @copydoc PDMDRVHLPR3::pfnTMGetVirtualFreq
+ */
+DECLINLINE(uint64_t) PDMDrvHlpTMGetVirtualFreq(PPDMDRVINS pDrvIns)
+{
+ return pDrvIns->pHlpR3->pfnTMGetVirtualFreq(pDrvIns);
+}
+
+/**
+ * @copydoc PDMDRVHLPR3::pfnTMGetVirtualTime
+ */
+DECLINLINE(uint64_t) PDMDrvHlpTMGetVirtualTime(PPDMDRVINS pDrvIns)
+{
+ return pDrvIns->pHlpR3->pfnTMGetVirtualTime(pDrvIns);
+}
+
+/**
+ * @copydoc PDMDRVHLPR3::pfnTimerCreate
+ */
+DECLINLINE(int) PDMDrvHlpTMTimerCreate(PPDMDRVINS pDrvIns, TMCLOCK enmClock, PFNTMTIMERDRV pfnCallback, void *pvUser,
+ uint32_t fFlags, const char *pszDesc, PTMTIMERHANDLE phTimer)
+
+{
+ return pDrvIns->pHlpR3->pfnTimerCreate(pDrvIns, enmClock, pfnCallback, pvUser, fFlags, pszDesc, phTimer);
+}
+
+/**
+ * @copydoc PDMDRVHLPR3::pfnTimerDestroy
+ */
+DECLINLINE(int) PDMDrvHlpTimerDestroy(PPDMDRVINS pDrvIns, TMTIMERHANDLE hTimer)
+
+{
+ return pDrvIns->pHlpR3->pfnTimerDestroy(pDrvIns, hTimer);
+}
+
+/**
+ * @copydoc PDMDRVHLPR3::pfnTimerSetMillies
+ */
+DECLINLINE(int) PDMDrvHlpTimerSetMillies(PPDMDRVINS pDrvIns, TMTIMERHANDLE hTimer, uint64_t cMilliesToNext)
+
+{
+ return pDrvIns->pHlpR3->pfnTimerSetMillies(pDrvIns, hTimer, cMilliesToNext);
+}
+
+/**
+ * Register a save state data unit.
+ *
+ * @returns VBox status.
+ * @param pDrvIns Driver instance.
+ * @param uVersion Data layout version number.
+ * @param cbGuess The approximate amount of data in the unit.
+ * Only for progress indicators.
+ * @param pfnSaveExec Execute save callback, optional.
+ * @param pfnLoadExec Execute load callback, optional.
+ */
+DECLINLINE(int) PDMDrvHlpSSMRegister(PPDMDRVINS pDrvIns, uint32_t uVersion, size_t cbGuess,
+ PFNSSMDRVSAVEEXEC pfnSaveExec, PFNSSMDRVLOADEXEC pfnLoadExec)
+{
+ return pDrvIns->pHlpR3->pfnSSMRegister(pDrvIns, uVersion, cbGuess,
+ NULL /*pfnLivePrep*/, NULL /*pfnLiveExec*/, NULL /*pfnLiveVote*/,
+ NULL /*pfnSavePrep*/, pfnSaveExec, NULL /*pfnSaveDone*/,
+ NULL /*pfnLoadPrep*/, pfnLoadExec, NULL /*pfnLoadDone*/);
+}
+
+/**
+ * @copydoc PDMDRVHLPR3::pfnSSMRegister
+ */
+DECLINLINE(int) PDMDrvHlpSSMRegisterEx(PPDMDRVINS pDrvIns, uint32_t uVersion, size_t cbGuess,
+ PFNSSMDRVLIVEPREP pfnLivePrep, PFNSSMDRVLIVEEXEC pfnLiveExec, PFNSSMDRVLIVEVOTE pfnLiveVote,
+ PFNSSMDRVSAVEPREP pfnSavePrep, PFNSSMDRVSAVEEXEC pfnSaveExec, PFNSSMDRVSAVEDONE pfnSaveDone,
+ PFNSSMDRVLOADPREP pfnLoadPrep, PFNSSMDRVLOADEXEC pfnLoadExec, PFNSSMDRVLOADDONE pfnLoadDone)
+{
+ return pDrvIns->pHlpR3->pfnSSMRegister(pDrvIns, uVersion, cbGuess,
+ pfnLivePrep, pfnLiveExec, pfnLiveVote,
+ pfnSavePrep, pfnSaveExec, pfnSaveDone,
+ pfnLoadPrep, pfnLoadExec, pfnLoadDone);
+}
+
+/**
+ * Register a load done callback.
+ *
+ * @returns VBox status.
+ * @param pDrvIns Driver instance.
+ * @param pfnLoadDone Done load callback, optional.
+ */
+DECLINLINE(int) PDMDrvHlpSSMRegisterLoadDone(PPDMDRVINS pDrvIns, PFNSSMDRVLOADDONE pfnLoadDone)
+{
+ return pDrvIns->pHlpR3->pfnSSMRegister(pDrvIns, 0 /*uVersion*/, 0 /*cbGuess*/,
+ NULL /*pfnLivePrep*/, NULL /*pfnLiveExec*/, NULL /*pfnLiveVote*/,
+ NULL /*pfnSavePrep*/, NULL /*pfnSaveExec*/, NULL /*pfnSaveDone*/,
+ NULL /*pfnLoadPrep*/, NULL /*pfnLoadExec*/, pfnLoadDone);
+}
+
+/**
+ * @copydoc PDMDRVHLPR3::pfnMMHeapFree
+ */
+DECLINLINE(void) PDMDrvHlpMMHeapFree(PPDMDRVINS pDrvIns, void *pv)
+{
+ pDrvIns->pHlpR3->pfnMMHeapFree(pDrvIns, pv);
+}
+
+/**
+ * @copydoc PDMDRVHLPR3::pfnDBGFInfoRegister
+ */
+DECLINLINE(int) PDMDrvHlpDBGFInfoRegister(PPDMDRVINS pDrvIns, const char *pszName, const char *pszDesc, PFNDBGFHANDLERDRV pfnHandler)
+{
+ return pDrvIns->pHlpR3->pfnDBGFInfoRegister(pDrvIns, pszName, pszDesc, pfnHandler);
+}
+
+/**
+ * @copydoc PDMDRVHLPR3::pfnDBGFInfoRegisterArgv
+ */
+DECLINLINE(int) PDMDrvHlpDBGFInfoRegisterArgv(PPDMDRVINS pDrvIns, const char *pszName, const char *pszDesc, PFNDBGFINFOARGVDRV pfnHandler)
+{
+ return pDrvIns->pHlpR3->pfnDBGFInfoRegisterArgv(pDrvIns, pszName, pszDesc, pfnHandler);
+}
+
+/**
+ * @copydoc PDMDRVHLPR3::pfnDBGFInfoRegister
+ */
+DECLINLINE(int) PDMDrvHlpDBGFInfoDeregister(PPDMDRVINS pDrvIns, const char *pszName, const char *pszDesc, PFNDBGFHANDLERDRV pfnHandler)
+{
+ return pDrvIns->pHlpR3->pfnDBGFInfoRegister(pDrvIns, pszName, pszDesc, pfnHandler);
+}
+
+/**
+ * @copydoc PDMDRVHLPR3::pfnSTAMRegister
+ */
+DECLINLINE(void) PDMDrvHlpSTAMRegister(PPDMDRVINS pDrvIns, void *pvSample, STAMTYPE enmType, const char *pszName, STAMUNIT enmUnit, const char *pszDesc)
+{
+ pDrvIns->pHlpR3->pfnSTAMRegister(pDrvIns, pvSample, enmType, pszName, enmUnit, pszDesc);
+}
+
+/**
+ * @copydoc PDMDRVHLPR3::pfnSTAMRegisterF
+ */
+DECLINLINE(void) RT_IPRT_FORMAT_ATTR(7, 8) PDMDrvHlpSTAMRegisterF(PPDMDRVINS pDrvIns, void *pvSample, STAMTYPE enmType,
+ STAMVISIBILITY enmVisibility, STAMUNIT enmUnit,
+ const char *pszDesc, const char *pszName, ...)
+{
+ va_list va;
+ va_start(va, pszName);
+ pDrvIns->pHlpR3->pfnSTAMRegisterV(pDrvIns, pvSample, enmType, enmVisibility, enmUnit, pszDesc, pszName, va);
+ va_end(va);
+}
+
+/**
+ * Convenience wrapper that registers counter which is always visible.
+ *
+ * @param pDrvIns The driver instance.
+ * @param pCounter Pointer to the counter variable.
+ * @param pszName The name of the sample. This is prefixed with
+ * "/Drivers/<drivername>-<instance no>/".
+ * @param enmUnit The unit.
+ * @param pszDesc The description.
+ */
+DECLINLINE(void) PDMDrvHlpSTAMRegCounterEx(PPDMDRVINS pDrvIns, PSTAMCOUNTER pCounter, const char *pszName, STAMUNIT enmUnit, const char *pszDesc)
+{
+ pDrvIns->pHlpR3->pfnSTAMRegisterF(pDrvIns, pCounter, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, enmUnit, pszDesc,
+ "/Drivers/%s-%u/%s", pDrvIns->pReg->szName, pDrvIns->iInstance, pszName);
+}
+
+/**
+ * Convenience wrapper that registers counter which is always visible and has
+ * the STAMUNIT_COUNT unit.
+ *
+ * @param pDrvIns The driver instance.
+ * @param pCounter Pointer to the counter variable.
+ * @param pszName The name of the sample. This is prefixed with
+ * "/Drivers/<drivername>-<instance no>/".
+ * @param pszDesc The description.
+ */
+DECLINLINE(void) PDMDrvHlpSTAMRegCounter(PPDMDRVINS pDrvIns, PSTAMCOUNTER pCounter, const char *pszName, const char *pszDesc)
+{
+ PDMDrvHlpSTAMRegCounterEx(pDrvIns, pCounter, pszName, STAMUNIT_COUNT, pszDesc);
+}
+
+/**
+ * Convenience wrapper that registers profiling sample which is always visible.
+ *
+ * @param pDrvIns The driver instance.
+ * @param pProfile Pointer to the profiling variable.
+ * @param pszName The name of the sample. This is prefixed with
+ * "/Drivers/<drivername>-<instance no>/".
+ * @param enmUnit The unit.
+ * @param pszDesc The description.
+ */
+DECLINLINE(void) PDMDrvHlpSTAMRegProfileEx(PPDMDRVINS pDrvIns, PSTAMPROFILE pProfile, const char *pszName, STAMUNIT enmUnit, const char *pszDesc)
+{
+ pDrvIns->pHlpR3->pfnSTAMRegisterF(pDrvIns, pProfile, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, enmUnit, pszDesc,
+ "/Drivers/%s-%u/%s", pDrvIns->pReg->szName, pDrvIns->iInstance, pszName);
+}
+
+/**
+ * Convenience wrapper that registers profiling sample which is always visible
+ * hand counts ticks per call (STAMUNIT_TICKS_PER_CALL).
+ *
+ * @param pDrvIns The driver instance.
+ * @param pProfile Pointer to the profiling variable.
+ * @param pszName The name of the sample. This is prefixed with
+ * "/Drivers/<drivername>-<instance no>/".
+ * @param pszDesc The description.
+ */
+DECLINLINE(void) PDMDrvHlpSTAMRegProfile(PPDMDRVINS pDrvIns, PSTAMPROFILE pProfile, const char *pszName, const char *pszDesc)
+{
+ PDMDrvHlpSTAMRegProfileEx(pDrvIns, pProfile, pszName, STAMUNIT_TICKS_PER_CALL, pszDesc);
+}
+
+/**
+ * Convenience wrapper that registers an advanced profiling sample which is
+ * always visible.
+ *
+ * @param pDrvIns The driver instance.
+ * @param pProfile Pointer to the profiling variable.
+ * @param enmUnit The unit.
+ * @param pszName The name of the sample. This is prefixed with
+ * "/Drivers/<drivername>-<instance no>/".
+ * @param pszDesc The description.
+ */
+DECLINLINE(void) PDMDrvHlpSTAMRegProfileAdvEx(PPDMDRVINS pDrvIns, PSTAMPROFILEADV pProfile, const char *pszName, STAMUNIT enmUnit, const char *pszDesc)
+{
+ pDrvIns->pHlpR3->pfnSTAMRegisterF(pDrvIns, pProfile, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, enmUnit, pszDesc,
+ "/Drivers/%s-%u/%s", pDrvIns->pReg->szName, pDrvIns->iInstance, pszName);
+}
+
+/**
+ * Convenience wrapper that registers an advanced profiling sample which is
+ * always visible.
+ *
+ * @param pDrvIns The driver instance.
+ * @param pProfile Pointer to the profiling variable.
+ * @param pszName The name of the sample. This is prefixed with
+ * "/Drivers/<drivername>-<instance no>/".
+ * @param pszDesc The description.
+ */
+DECLINLINE(void) PDMDrvHlpSTAMRegProfileAdv(PPDMDRVINS pDrvIns, PSTAMPROFILEADV pProfile, const char *pszName, const char *pszDesc)
+{
+ PDMDrvHlpSTAMRegProfileAdvEx(pDrvIns, pProfile, pszName, STAMUNIT_TICKS_PER_CALL, pszDesc);
+}
+
+/**
+ * @copydoc PDMDRVHLPR3::pfnSTAMDeregister
+ */
+DECLINLINE(int) PDMDrvHlpSTAMDeregister(PPDMDRVINS pDrvIns, void *pvSample)
+{
+ return pDrvIns->pHlpR3->pfnSTAMDeregister(pDrvIns, pvSample);
+}
+
+/**
+ * @copydoc PDMDRVHLPR3::pfnSTAMDeregisterByPrefix
+ */
+DECLINLINE(int) PDMDrvHlpSTAMDeregisterByPrefix(PPDMDRVINS pDrvIns, const char *pszPrefix)
+{
+ return pDrvIns->pHlpR3->pfnSTAMDeregisterByPrefix(pDrvIns, pszPrefix);
+}
+
+/**
+ * @copydoc PDMDRVHLPR3::pfnSUPCallVMMR0Ex
+ */
+DECLINLINE(int) PDMDrvHlpSUPCallVMMR0Ex(PPDMDRVINS pDrvIns, unsigned uOperation, void *pvArg, unsigned cbArg)
+{
+ return pDrvIns->pHlpR3->pfnSUPCallVMMR0Ex(pDrvIns, uOperation, pvArg, cbArg);
+}
+
+/**
+ * @copydoc PDMDRVHLPR3::pfnUSBRegisterHub
+ */
+DECLINLINE(int) PDMDrvHlpUSBRegisterHub(PPDMDRVINS pDrvIns, uint32_t fVersions, uint32_t cPorts, PCPDMUSBHUBREG pUsbHubReg, PPCPDMUSBHUBHLP ppUsbHubHlp)
+{
+ return pDrvIns->pHlpR3->pfnUSBRegisterHub(pDrvIns, fVersions, cPorts, pUsbHubReg, ppUsbHubHlp);
+}
+
+/**
+ * @copydoc PDMDRVHLPR3::pfnSetAsyncNotification
+ */
+DECLINLINE(int) PDMDrvHlpSetAsyncNotification(PPDMDRVINS pDrvIns, PFNPDMDRVASYNCNOTIFY pfnAsyncNotify)
+{
+ return pDrvIns->pHlpR3->pfnSetAsyncNotification(pDrvIns, pfnAsyncNotify);
+}
+
+/**
+ * @copydoc PDMDRVHLPR3::pfnAsyncNotificationCompleted
+ */
+DECLINLINE(void) PDMDrvHlpAsyncNotificationCompleted(PPDMDRVINS pDrvIns)
+{
+ pDrvIns->pHlpR3->pfnAsyncNotificationCompleted(pDrvIns);
+}
+
+/**
+ * @copydoc PDMDRVHLPR3::pfnThreadCreate
+ */
+DECLINLINE(int) PDMDrvHlpThreadCreate(PPDMDRVINS pDrvIns, PPPDMTHREAD ppThread, void *pvUser, PFNPDMTHREADDRV pfnThread,
+ PFNPDMTHREADWAKEUPDRV pfnWakeup, size_t cbStack, RTTHREADTYPE enmType, const char *pszName)
+{
+ return pDrvIns->pHlpR3->pfnThreadCreate(pDrvIns, ppThread, pvUser, pfnThread, pfnWakeup, cbStack, enmType, pszName);
+}
+
+/**
+ * @copydoc PDMR3ThreadDestroy
+ * @param pDrvIns The driver instance.
+ */
+DECLINLINE(int) PDMDrvHlpThreadDestroy(PPDMDRVINS pDrvIns, PPDMTHREAD pThread, int *pRcThread)
+{
+ return pDrvIns->pHlpR3->pfnThreadDestroy(pThread, pRcThread);
+}
+
+/**
+ * @copydoc PDMR3ThreadIAmSuspending
+ * @param pDrvIns The driver instance.
+ */
+DECLINLINE(int) PDMDrvHlpThreadIAmSuspending(PPDMDRVINS pDrvIns, PPDMTHREAD pThread)
+{
+ return pDrvIns->pHlpR3->pfnThreadIAmSuspending(pThread);
+}
+
+/**
+ * @copydoc PDMR3ThreadIAmRunning
+ * @param pDrvIns The driver instance.
+ */
+DECLINLINE(int) PDMDrvHlpThreadIAmRunning(PPDMDRVINS pDrvIns, PPDMTHREAD pThread)
+{
+ return pDrvIns->pHlpR3->pfnThreadIAmRunning(pThread);
+}
+
+/**
+ * @copydoc PDMR3ThreadSleep
+ * @param pDrvIns The driver instance.
+ */
+DECLINLINE(int) PDMDrvHlpThreadSleep(PPDMDRVINS pDrvIns, PPDMTHREAD pThread, RTMSINTERVAL cMillies)
+{
+ return pDrvIns->pHlpR3->pfnThreadSleep(pThread, cMillies);
+}
+
+/**
+ * @copydoc PDMR3ThreadSuspend
+ * @param pDrvIns The driver instance.
+ */
+DECLINLINE(int) PDMDrvHlpThreadSuspend(PPDMDRVINS pDrvIns, PPDMTHREAD pThread)
+{
+ return pDrvIns->pHlpR3->pfnThreadSuspend(pThread);
+}
+
+/**
+ * @copydoc PDMR3ThreadResume
+ * @param pDrvIns The driver instance.
+ */
+DECLINLINE(int) PDMDrvHlpThreadResume(PPDMDRVINS pDrvIns, PPDMTHREAD pThread)
+{
+ return pDrvIns->pHlpR3->pfnThreadResume(pThread);
+}
+
+# ifdef VBOX_WITH_PDM_ASYNC_COMPLETION
+/**
+ * @copydoc PDMDRVHLPR3::pfnAsyncCompletionTemplateCreate
+ */
+DECLINLINE(int) PDMDrvHlpAsyncCompletionTemplateCreate(PPDMDRVINS pDrvIns, PPPDMASYNCCOMPLETIONTEMPLATE ppTemplate,
+ PFNPDMASYNCCOMPLETEDRV pfnCompleted, void *pvTemplateUser, const char *pszDesc)
+{
+ return pDrvIns->pHlpR3->pfnAsyncCompletionTemplateCreate(pDrvIns, ppTemplate, pfnCompleted, pvTemplateUser, pszDesc);
+}
+
+/**
+ * @copydoc PDMDRVHLPR3::pfnAsyncCompletionTemplateDestroy
+ */
+DECLINLINE(int) PDMDrvHlpAsyncCompletionTemplateDestroy(PPDMDRVINS pDrvIns, PPDMASYNCCOMPLETIONTEMPLATE pTemplate)
+{
+ return pDrvIns->pHlpR3->pfnAsyncCompletionTemplateDestroy(pTemplate);
+}
+
+/**
+ * @copydoc PDMDRVHLPR3::pfnAsyncCompletionEpCreateForFile
+ */
+DECLINLINE(int) PDMDrvHlpAsyncCompletionEpCreateForFile(PPDMDRVINS pDrvIns, PPPDMASYNCCOMPLETIONENDPOINT ppEndpoint,
+ const char *pszFilename, uint32_t fFlags,
+ PPDMASYNCCOMPLETIONTEMPLATE pTemplate)
+{
+ return pDrvIns->pHlpR3->pfnAsyncCompletionEpCreateForFile(ppEndpoint, pszFilename, fFlags, pTemplate);
+}
+
+/**
+ * @copydoc PDMDRVHLPR3::pfnAsyncCompletionEpClose
+ */
+DECLINLINE(void) PDMDrvHlpAsyncCompletionEpClose(PPDMDRVINS pDrvIns, PPDMASYNCCOMPLETIONENDPOINT pEndpoint)
+{
+ pDrvIns->pHlpR3->pfnAsyncCompletionEpClose(pEndpoint);
+}
+
+/**
+ * @copydoc PDMDRVHLPR3::pfnAsyncCompletionEpGetSize
+ */
+DECLINLINE(int) PDMDrvHlpAsyncCompletionEpGetSize(PPDMDRVINS pDrvIns, PPDMASYNCCOMPLETIONENDPOINT pEndpoint, uint64_t *pcbSize)
+{
+ return pDrvIns->pHlpR3->pfnAsyncCompletionEpGetSize(pEndpoint, pcbSize);
+}
+
+/**
+ * @copydoc PDMDRVHLPR3::pfnAsyncCompletionEpSetSize
+ */
+DECLINLINE(int) PDMDrvHlpAsyncCompletionEpSetSize(PPDMDRVINS pDrvIns, PPDMASYNCCOMPLETIONENDPOINT pEndpoint, uint64_t cbSize)
+{
+ return pDrvIns->pHlpR3->pfnAsyncCompletionEpSetSize(pEndpoint, cbSize);
+}
+
+/**
+ * @copydoc PDMDRVHLPR3::pfnAsyncCompletionEpSetBwMgr
+ */
+DECLINLINE(int) PDMDrvHlpAsyncCompletionEpSetBwMgr(PPDMDRVINS pDrvIns, PPDMASYNCCOMPLETIONENDPOINT pEndpoint, const char *pszBwMgr)
+{
+ return pDrvIns->pHlpR3->pfnAsyncCompletionEpSetBwMgr(pEndpoint, pszBwMgr);
+}
+
+/**
+ * @copydoc PDMDRVHLPR3::pfnAsyncCompletionEpFlush
+ */
+DECLINLINE(int) PDMDrvHlpAsyncCompletionEpFlush(PPDMDRVINS pDrvIns, PPDMASYNCCOMPLETIONENDPOINT pEndpoint, void *pvUser,
+ PPPDMASYNCCOMPLETIONTASK ppTask)
+{
+ return pDrvIns->pHlpR3->pfnAsyncCompletionEpFlush(pEndpoint, pvUser, ppTask);
+}
+
+/**
+ * @copydoc PDMDRVHLPR3::pfnAsyncCompletionEpRead
+ */
+DECLINLINE(int) PDMDrvHlpAsyncCompletionEpRead(PPDMDRVINS pDrvIns, PPDMASYNCCOMPLETIONENDPOINT pEndpoint, RTFOFF off,
+ PCRTSGSEG paSegments, unsigned cSegments,
+ size_t cbRead, void *pvUser,
+ PPPDMASYNCCOMPLETIONTASK ppTask)
+{
+ return pDrvIns->pHlpR3->pfnAsyncCompletionEpRead(pEndpoint, off, paSegments, cSegments, cbRead, pvUser, ppTask);
+}
+
+/**
+ * @copydoc PDMDRVHLPR3::pfnAsyncCompletionEpWrite
+ */
+DECLINLINE(int) PDMDrvHlpAsyncCompletionEpWrite(PPDMDRVINS pDrvIns, PPDMASYNCCOMPLETIONENDPOINT pEndpoint, RTFOFF off,
+ PCRTSGSEG paSegments, unsigned cSegments,
+ size_t cbWrite, void *pvUser,
+ PPPDMASYNCCOMPLETIONTASK ppTask)
+{
+ return pDrvIns->pHlpR3->pfnAsyncCompletionEpWrite(pEndpoint, off, paSegments, cSegments, cbWrite, pvUser, ppTask);
+}
+# endif
+
+#endif /* IN_RING3 */
+
+#ifdef VBOX_WITH_NETSHAPER
+# ifdef IN_RING3
+
+/**
+ * @copydoc PDMDRVHLPR3::pfnNetShaperAttach
+ */
+DECLINLINE(int) PDMDrvHlpNetShaperAttach(PPDMDRVINS pDrvIns, const char *pcszBwGroup, PPDMNSFILTER pFilter)
+{
+ return pDrvIns->pHlpR3->pfnNetShaperAttach(pDrvIns, pcszBwGroup, pFilter);
+}
+
+/**
+ * @copydoc PDMDRVHLPR3::pfnNetShaperDetach
+ */
+DECLINLINE(int) PDMDrvHlpNetShaperDetach(PPDMDRVINS pDrvIns, PPDMNSFILTER pFilter)
+{
+ return pDrvIns->pHlpR3->pfnNetShaperDetach(pDrvIns, pFilter);
+}
+
+# endif /* IN_RING3 */
+
+/**
+ * @copydoc PDMDRVHLPR3::pfnNetShaperAllocateBandwidth
+ */
+DECLINLINE(bool) PDMDrvHlpNetShaperAllocateBandwidth(PPDMDRVINS pDrvIns, PPDMNSFILTER pFilter, size_t cbTransfer)
+{
+ return pDrvIns->CTX_SUFF(pHlp)->pfnNetShaperAllocateBandwidth(pDrvIns, pFilter, cbTransfer);
+}
+
+#endif /* VBOX_WITH_NETSHAPER*/
+
+#ifdef IN_RING3
+/**
+ * @copydoc PDMDRVHLPR3::pfnCritSectInit
+ */
+DECLINLINE(int) PDMDrvHlpCritSectInit(PPDMDRVINS pDrvIns, PPDMCRITSECT pCritSect, RT_SRC_POS_DECL, const char *pszName)
+{
+ return pDrvIns->pHlpR3->pfnCritSectInit(pDrvIns, pCritSect, RT_SRC_POS_ARGS, pszName);
+}
+#endif /* IN_RING3 */
+
+/**
+ * @see PDMCritSectEnter
+ */
+DECLINLINE(int) PDMDrvHlpCritSectEnter(PPDMDRVINS pDrvIns, PPDMCRITSECT pCritSect, int rcBusy)
+{
+ return pDrvIns->CTX_SUFF(pHlp)->pfnCritSectEnter(pDrvIns, pCritSect, rcBusy);
+}
+
+/**
+ * @see PDMCritSectEnterDebug
+ */
+DECLINLINE(int) PDMDrvHlpCritSectEnterDebug(PPDMDRVINS pDrvIns, PPDMCRITSECT pCritSect, int rcBusy, RTHCUINTPTR uId, RT_SRC_POS_DECL)
+{
+ return pDrvIns->CTX_SUFF(pHlp)->pfnCritSectEnterDebug(pDrvIns, pCritSect, rcBusy, uId, RT_SRC_POS_ARGS);
+}
+
+/**
+ * @see PDMCritSectTryEnter
+ */
+DECLINLINE(int) PDMDrvHlpCritSectTryEnter(PPDMDRVINS pDrvIns, PPDMCRITSECT pCritSect)
+{
+ return pDrvIns->CTX_SUFF(pHlp)->pfnCritSectTryEnter(pDrvIns, pCritSect);
+}
+
+/**
+ * @see PDMCritSectTryEnterDebug
+ */
+DECLINLINE(int) PDMDrvHlpCritSectTryEnterDebug(PPDMDRVINS pDrvIns, PPDMCRITSECT pCritSect, RTHCUINTPTR uId, RT_SRC_POS_DECL)
+{
+ return pDrvIns->CTX_SUFF(pHlp)->pfnCritSectTryEnterDebug(pDrvIns, pCritSect, uId, RT_SRC_POS_ARGS);
+}
+
+/**
+ * @see PDMCritSectLeave
+ */
+DECLINLINE(int) PDMDrvHlpCritSectLeave(PPDMDRVINS pDrvIns, PPDMCRITSECT pCritSect)
+{
+ return pDrvIns->CTX_SUFF(pHlp)->pfnCritSectLeave(pDrvIns, pCritSect);
+}
+
+/**
+ * @see PDMCritSectIsOwner
+ */
+DECLINLINE(bool) PDMDrvHlpCritSectIsOwner(PPDMDRVINS pDrvIns, PCPDMCRITSECT pCritSect)
+{
+ return pDrvIns->CTX_SUFF(pHlp)->pfnCritSectIsOwner(pDrvIns, pCritSect);
+}
+
+/**
+ * @see PDMCritSectIsInitialized
+ */
+DECLINLINE(bool) PDMDrvHlpCritSectIsInitialized(PPDMDRVINS pDrvIns, PCPDMCRITSECT pCritSect)
+{
+ return pDrvIns->CTX_SUFF(pHlp)->pfnCritSectIsInitialized(pDrvIns, pCritSect);
+}
+
+/**
+ * @see PDMCritSectHasWaiters
+ */
+DECLINLINE(bool) PDMDrvHlpCritSectHasWaiters(PPDMDRVINS pDrvIns, PCPDMCRITSECT pCritSect)
+{
+ return pDrvIns->CTX_SUFF(pHlp)->pfnCritSectHasWaiters(pDrvIns, pCritSect);
+}
+
+/**
+ * @see PDMCritSectGetRecursion
+ */
+DECLINLINE(uint32_t) PDMDrvHlpCritSectGetRecursion(PPDMDRVINS pDrvIns, PCPDMCRITSECT pCritSect)
+{
+ return pDrvIns->CTX_SUFF(pHlp)->pfnCritSectGetRecursion(pDrvIns, pCritSect);
+}
+
+#if defined(IN_RING3) || defined(IN_RING0)
+/**
+ * @see PDMHCCritSectScheduleExitEvent
+ */
+DECLINLINE(int) PDMDrvHlpCritSectScheduleExitEvent(PPDMDRVINS pDrvIns, PPDMCRITSECT pCritSect, SUPSEMEVENT hEventToSignal)
+{
+ return pDrvIns->CTX_SUFF(pHlp)->pfnCritSectScheduleExitEvent(pDrvIns, pCritSect, hEventToSignal);
+}
+#endif
+
+/* Strict build: Remap the two enter calls to the debug versions. */
+#ifdef VBOX_STRICT
+# ifdef IPRT_INCLUDED_asm_h
+# define PDMDrvHlpCritSectEnter(pDrvIns, pCritSect, rcBusy) PDMDrvHlpCritSectEnterDebug((pDrvIns), (pCritSect), (rcBusy), (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
+# define PDMDrvHlpCritSectTryEnter(pDrvIns, pCritSect) PDMDrvHlpCritSectTryEnterDebug((pDrvIns), (pCritSect), (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
+# else
+# define PDMDrvHlpCritSectEnter(pDrvIns, pCritSect, rcBusy) PDMDrvHlpCritSectEnterDebug((pDrvIns), (pCritSect), (rcBusy), 0, RT_SRC_POS)
+# define PDMDrvHlpCritSectTryEnter(pDrvIns, pCritSect) PDMDrvHlpCritSectTryEnterDebug((pDrvIns), (pCritSect), 0, RT_SRC_POS)
+# endif
+#endif
+
+#if defined(IN_RING3) || defined(DOXYGEN_RUNNING)
+
+/**
+ * @see PDMR3CritSectDelete
+ */
+DECLINLINE(int) PDMDrvHlpCritSectDelete(PPDMDRVINS pDrvIns, PPDMCRITSECT pCritSect)
+{
+ return pDrvIns->pHlpR3->pfnCritSectDelete(pDrvIns, pCritSect);
+}
+
+/**
+ * @copydoc PDMDRVHLPR3::pfnCallR0
+ */
+DECLINLINE(int) PDMDrvHlpCallR0(PPDMDRVINS pDrvIns, uint32_t uOperation, uint64_t u64Arg)
+{
+ return pDrvIns->pHlpR3->pfnCallR0(pDrvIns, uOperation, u64Arg);
+}
+
+/**
+ * @copydoc PDMDRVHLPR3::pfnBlkCacheRetain
+ */
+DECLINLINE(int) PDMDrvHlpBlkCacheRetain(PPDMDRVINS pDrvIns, PPPDMBLKCACHE ppBlkCache,
+ PFNPDMBLKCACHEXFERCOMPLETEDRV pfnXferComplete,
+ PFNPDMBLKCACHEXFERENQUEUEDRV pfnXferEnqueue,
+ PFNPDMBLKCACHEXFERENQUEUEDISCARDDRV pfnXferEnqueueDiscard,
+ const char *pcszId)
+{
+ return pDrvIns->pHlpR3->pfnBlkCacheRetain(pDrvIns, ppBlkCache, pfnXferComplete, pfnXferEnqueue, pfnXferEnqueueDiscard, pcszId);
+}
+
+/**
+ * @copydoc PDMDRVHLPR3::pfnBlkCacheRelease
+ */
+DECLINLINE(void) PDMDrvHlpBlkCacheRelease(PPDMDRVINS pDrvIns, PPDMBLKCACHE pBlkCache)
+{
+ pDrvIns->pHlpR3->pfnBlkCacheRelease(pBlkCache);
+}
+
+/**
+ * @copydoc PDMDRVHLPR3::pfnBlkCacheClear
+ */
+DECLINLINE(int) PDMDrvHlpBlkCacheClear(PPDMDRVINS pDrvIns, PPDMBLKCACHE pBlkCache)
+{
+ return pDrvIns->pHlpR3->pfnBlkCacheClear(pBlkCache);
+}
+
+/**
+ * @copydoc PDMDRVHLPR3::pfnBlkCacheSuspend
+ */
+DECLINLINE(int) PDMDrvHlpBlkCacheSuspend(PPDMDRVINS pDrvIns, PPDMBLKCACHE pBlkCache)
+{
+ return pDrvIns->pHlpR3->pfnBlkCacheSuspend(pBlkCache);
+}
+
+/**
+ * @copydoc PDMDRVHLPR3::pfnBlkCacheResume
+ */
+DECLINLINE(int) PDMDrvHlpBlkCacheResume(PPDMDRVINS pDrvIns, PPDMBLKCACHE pBlkCache)
+{
+ return pDrvIns->pHlpR3->pfnBlkCacheResume(pBlkCache);
+}
+
+/**
+ * @copydoc PDMDRVHLPR3::pfnBlkCacheIoXferComplete
+ */
+DECLINLINE(void) PDMDrvHlpBlkCacheIoXferComplete(PPDMDRVINS pDrvIns, PPDMBLKCACHE pBlkCache,
+ PPDMBLKCACHEIOXFER hIoXfer, int rcIoXfer)
+{
+ pDrvIns->pHlpR3->pfnBlkCacheIoXferComplete(pBlkCache, hIoXfer, rcIoXfer);
+}
+
+/**
+ * @copydoc PDMDRVHLPR3::pfnBlkCacheRead
+ */
+DECLINLINE(int) PDMDrvHlpBlkCacheRead(PPDMDRVINS pDrvIns, PPDMBLKCACHE pBlkCache, uint64_t off,
+ PCRTSGBUF pSgBuf, size_t cbRead, void *pvUser)
+{
+ return pDrvIns->pHlpR3->pfnBlkCacheRead(pBlkCache, off, pSgBuf, cbRead, pvUser);
+}
+
+/**
+ * @copydoc PDMDRVHLPR3::pfnBlkCacheWrite
+ */
+DECLINLINE(int) PDMDrvHlpBlkCacheWrite(PPDMDRVINS pDrvIns, PPDMBLKCACHE pBlkCache, uint64_t off,
+ PCRTSGBUF pSgBuf, size_t cbRead, void *pvUser)
+{
+ return pDrvIns->pHlpR3->pfnBlkCacheWrite(pBlkCache, off, pSgBuf, cbRead, pvUser);
+}
+
+/**
+ * @copydoc PDMDRVHLPR3::pfnBlkCacheFlush
+ */
+DECLINLINE(int) PDMDrvHlpBlkCacheFlush(PPDMDRVINS pDrvIns, PPDMBLKCACHE pBlkCache, void *pvUser)
+{
+ return pDrvIns->pHlpR3->pfnBlkCacheFlush(pBlkCache, pvUser);
+}
+
+/**
+ * @copydoc PDMDRVHLPR3::pfnBlkCacheDiscard
+ */
+DECLINLINE(int) PDMDrvHlpBlkCacheDiscard(PPDMDRVINS pDrvIns, PPDMBLKCACHE pBlkCache, PCRTRANGE paRanges,
+ unsigned cRanges, void *pvUser)
+{
+ return pDrvIns->pHlpR3->pfnBlkCacheDiscard(pBlkCache, paRanges, cRanges, pvUser);
+}
+
+/**
+ * @copydoc PDMDRVHLPR3::pfnVMGetSuspendReason
+ */
+DECLINLINE(VMSUSPENDREASON) PDMDrvHlpVMGetSuspendReason(PPDMDRVINS pDrvIns)
+{
+ return pDrvIns->pHlpR3->pfnVMGetSuspendReason(pDrvIns);
+}
+
+/**
+ * @copydoc PDMDRVHLPR3::pfnVMGetResumeReason
+ */
+DECLINLINE(VMRESUMEREASON) PDMDrvHlpVMGetResumeReason(PPDMDRVINS pDrvIns)
+{
+ return pDrvIns->pHlpR3->pfnVMGetResumeReason(pDrvIns);
+}
+
+/**
+ * @copydoc PDMDRVHLPR3::pfnQueryGenericUserObject
+ */
+DECLINLINE(void *) PDMDrvHlpQueryGenericUserObject(PPDMDRVINS pDrvIns, PCRTUUID pUuid)
+{
+ return pDrvIns->pHlpR3->pfnQueryGenericUserObject(pDrvIns, pUuid);
+}
+
+
+/** Pointer to callbacks provided to the VBoxDriverRegister() call. */
+typedef struct PDMDRVREGCB *PPDMDRVREGCB;
+/** Pointer to const callbacks provided to the VBoxDriverRegister() call. */
+typedef const struct PDMDRVREGCB *PCPDMDRVREGCB;
+
+/**
+ * Callbacks for VBoxDriverRegister().
+ */
+typedef struct PDMDRVREGCB
+{
+ /** Interface version.
+ * This is set to PDM_DRVREG_CB_VERSION. */
+ uint32_t u32Version;
+
+ /**
+ * Registers a driver with the current VM instance.
+ *
+ * @returns VBox status code.
+ * @param pCallbacks Pointer to the callback table.
+ * @param pReg Pointer to the driver registration record.
+ * This data must be permanent and readonly.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnRegister,(PCPDMDRVREGCB pCallbacks, PCPDMDRVREG pReg));
+} PDMDRVREGCB;
+
+/** Current version of the PDMDRVREGCB structure. */
+#define PDM_DRVREG_CB_VERSION PDM_VERSION_MAKE(0xf0fa, 1, 0)
+
+
+/**
+ * The VBoxDriverRegister callback function.
+ *
+ * PDM will invoke this function after loading a driver module and letting
+ * the module decide which drivers to register and how to handle conflicts.
+ *
+ * @returns VBox status code.
+ * @param pCallbacks Pointer to the callback table.
+ * @param u32Version VBox version number.
+ */
+typedef DECLCALLBACKTYPE(int, FNPDMVBOXDRIVERSREGISTER,(PCPDMDRVREGCB pCallbacks, uint32_t u32Version));
+
+VMMR3DECL(int) PDMR3DrvStaticRegistration(PVM pVM, FNPDMVBOXDRIVERSREGISTER pfnCallback);
+
+#endif /* IN_RING3 */
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !VBOX_INCLUDED_vmm_pdmdrv_h */
diff --git a/include/VBox/vmm/pdmifs.h b/include/VBox/vmm/pdmifs.h
new file mode 100644
index 00000000..57ad02f2
--- /dev/null
+++ b/include/VBox/vmm/pdmifs.h
@@ -0,0 +1,2366 @@
+/** @file
+ * PDM - Pluggable Device Manager, Interfaces.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vmm_pdmifs_h
+#define VBOX_INCLUDED_vmm_pdmifs_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/sg.h>
+#include <VBox/types.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_pdm_interfaces The PDM Interface Definitions
+ * @ingroup grp_pdm
+ *
+ * For historical reasons (the PDMINTERFACE enum) a lot of interface was stuffed
+ * together in this group instead, dragging stuff into global space that didn't
+ * need to be there and making this file huge (>2500 lines). Since we're using
+ * UUIDs as interface identifiers (IIDs) now, no only generic PDM interface will
+ * be added to this file. Component specific interface should be defined in the
+ * header file of that component.
+ *
+ * Interfaces consists of a method table (typedef'ed struct) and an interface
+ * ID. The typename of the method table should have an 'I' in it, be all
+ * capitals and according to the rules, no underscores. The interface ID is a
+ * \#define constructed by appending '_IID' to the typename. The IID value is a
+ * UUID string on the form "a2299c0d-b709-4551-aa5a-73f59ffbed74". If you stick
+ * to these rules, you can make use of the PDMIBASE_QUERY_INTERFACE and
+ * PDMIBASE_RETURN_INTERFACE when querying interface and implementing
+ * PDMIBASE::pfnQueryInterface respectively.
+ *
+ * In most interface descriptions the orientation of the interface is given as
+ * 'down' or 'up'. This refers to a model with the device on the top and the
+ * drivers stacked below it. Sometimes there is mention of 'main' or 'external'
+ * which normally means the same, i.e. the Main or VBoxBFE API. Picture the
+ * orientation of 'main' as horizontal.
+ *
+ * @{
+ */
+
+
+/** @name PDMIBASE
+ * @{
+ */
+
+/**
+ * PDM Base Interface.
+ *
+ * Everyone implements this.
+ */
+typedef struct PDMIBASE
+{
+ /**
+ * Queries an interface to the driver.
+ *
+ * @returns Pointer to interface.
+ * @returns NULL if the interface was not supported by the driver.
+ * @param pInterface Pointer to this interface structure.
+ * @param pszIID The interface ID, a UUID string.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(void *, pfnQueryInterface,(struct PDMIBASE *pInterface, const char *pszIID));
+} PDMIBASE;
+/** PDMIBASE interface ID. */
+#define PDMIBASE_IID "a2299c0d-b709-4551-aa5a-73f59ffbed74"
+
+/**
+ * Helper macro for querying an interface from PDMIBASE.
+ *
+ * @returns Correctly typed PDMIBASE::pfnQueryInterface return value.
+ *
+ * @param pIBase Pointer to the base interface.
+ * @param InterfaceType The interface type name. The interface ID is
+ * derived from this by appending _IID.
+ */
+#define PDMIBASE_QUERY_INTERFACE(pIBase, InterfaceType) \
+ ( (InterfaceType *)(pIBase)->pfnQueryInterface(pIBase, InterfaceType##_IID ) )
+
+/**
+ * Helper macro for implementing PDMIBASE::pfnQueryInterface.
+ *
+ * Return @a pInterface if @a pszIID matches the @a InterfaceType. This will
+ * perform basic type checking.
+ *
+ * @param pszIID The ID of the interface that is being queried.
+ * @param InterfaceType The interface type name. The interface ID is
+ * derived from this by appending _IID.
+ * @param pInterface The interface address expression.
+ */
+#define PDMIBASE_RETURN_INTERFACE(pszIID, InterfaceType, pInterface) \
+ do { \
+ if (RTUuidCompare2Strs((pszIID), InterfaceType##_IID) == 0) \
+ { \
+ P##InterfaceType pReturnInterfaceTypeCheck = (pInterface); \
+ return pReturnInterfaceTypeCheck; \
+ } \
+ } while (0)
+
+/** @} */
+
+
+/** @name PDMIBASERC
+ * @{
+ */
+
+/**
+ * PDM Base Interface for querying ring-mode context interfaces in
+ * ring-3.
+ *
+ * This is mandatory for drivers present in raw-mode context.
+ */
+typedef struct PDMIBASERC
+{
+ /**
+ * Queries an ring-mode context interface to the driver.
+ *
+ * @returns Pointer to interface.
+ * @returns NULL if the interface was not supported by the driver.
+ * @param pInterface Pointer to this interface structure.
+ * @param pszIID The interface ID, a UUID string.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(RTRCPTR, pfnQueryInterface,(struct PDMIBASERC *pInterface, const char *pszIID));
+} PDMIBASERC;
+/** Pointer to a PDM Base Interface for query ring-mode context interfaces. */
+typedef PDMIBASERC *PPDMIBASERC;
+/** PDMIBASERC interface ID. */
+#define PDMIBASERC_IID "f6a6c649-6cb3-493f-9737-4653f221aeca"
+
+/**
+ * Helper macro for querying an interface from PDMIBASERC.
+ *
+ * @returns PDMIBASERC::pfnQueryInterface return value.
+ *
+ * @param pIBaseRC Pointer to the base raw-mode context interface. Can
+ * be NULL.
+ * @param InterfaceType The interface type base name, no trailing RC. The
+ * interface ID is derived from this by appending _IID.
+ *
+ * @remarks Unlike PDMIBASE_QUERY_INTERFACE, this macro is not able to do any
+ * implicit type checking for you.
+ */
+#define PDMIBASERC_QUERY_INTERFACE(pIBaseRC, InterfaceType) \
+ ( (P##InterfaceType##RC)((pIBaseRC) ? (pIBaseRC)->pfnQueryInterface(pIBaseRC, InterfaceType##_IID) : NIL_RTRCPTR) )
+
+/**
+ * Helper macro for implementing PDMIBASERC::pfnQueryInterface.
+ *
+ * Return @a pInterface if @a pszIID matches the @a InterfaceType. This will
+ * perform basic type checking.
+ *
+ * @param pIns Pointer to the instance data.
+ * @param pszIID The ID of the interface that is being queried.
+ * @param InterfaceType The interface type base name, no trailing RC. The
+ * interface ID is derived from this by appending _IID.
+ * @param pInterface The interface address expression. This must resolve
+ * to some address within the instance data.
+ * @remarks Don't use with PDMIBASE.
+ */
+#define PDMIBASERC_RETURN_INTERFACE(pIns, pszIID, InterfaceType, pInterface) \
+ do { \
+ Assert((uintptr_t)pInterface - PDMINS_2_DATA(pIns, uintptr_t) < _4M); \
+ if (RTUuidCompare2Strs((pszIID), InterfaceType##_IID) == 0) \
+ { \
+ InterfaceType##RC *pReturnInterfaceTypeCheck = (pInterface); \
+ return (uintptr_t)pReturnInterfaceTypeCheck \
+ - PDMINS_2_DATA(pIns, uintptr_t) \
+ + PDMINS_2_DATA_RCPTR(pIns); \
+ } \
+ } while (0)
+
+/** @} */
+
+
+/** @name PDMIBASER0
+ * @{
+ */
+
+/**
+ * PDM Base Interface for querying ring-0 interfaces in ring-3.
+ *
+ * This is mandatory for drivers present in ring-0 context.
+ */
+typedef struct PDMIBASER0
+{
+ /**
+ * Queries an ring-0 interface to the driver.
+ *
+ * @returns Pointer to interface.
+ * @returns NULL if the interface was not supported by the driver.
+ * @param pInterface Pointer to this interface structure.
+ * @param pszIID The interface ID, a UUID string.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(RTR0PTR, pfnQueryInterface,(struct PDMIBASER0 *pInterface, const char *pszIID));
+} PDMIBASER0;
+/** Pointer to a PDM Base Interface for query ring-0 context interfaces. */
+typedef PDMIBASER0 *PPDMIBASER0;
+/** PDMIBASER0 interface ID. */
+#define PDMIBASER0_IID "9c9b99b8-7f53-4f59-a3c2-5bc9659c7944"
+
+/**
+ * Helper macro for querying an interface from PDMIBASER0.
+ *
+ * @returns PDMIBASER0::pfnQueryInterface return value.
+ *
+ * @param pIBaseR0 Pointer to the base ring-0 interface. Can be NULL.
+ * @param InterfaceType The interface type base name, no trailing R0. The
+ * interface ID is derived from this by appending _IID.
+ *
+ * @remarks Unlike PDMIBASE_QUERY_INTERFACE, this macro is not able to do any
+ * implicit type checking for you.
+ */
+#define PDMIBASER0_QUERY_INTERFACE(pIBaseR0, InterfaceType) \
+ ( (P##InterfaceType##R0)((pIBaseR0) ? (pIBaseR0)->pfnQueryInterface(pIBaseR0, InterfaceType##_IID) : NIL_RTR0PTR) )
+
+/**
+ * Helper macro for implementing PDMIBASER0::pfnQueryInterface.
+ *
+ * Return @a pInterface if @a pszIID matches the @a InterfaceType. This will
+ * perform basic type checking.
+ *
+ * @param pIns Pointer to the instance data.
+ * @param pszIID The ID of the interface that is being queried.
+ * @param InterfaceType The interface type base name, no trailing R0. The
+ * interface ID is derived from this by appending _IID.
+ * @param pInterface The interface address expression. This must resolve
+ * to some address within the instance data.
+ * @remarks Don't use with PDMIBASE.
+ */
+#define PDMIBASER0_RETURN_INTERFACE(pIns, pszIID, InterfaceType, pInterface) \
+ do { \
+ Assert((uintptr_t)pInterface - PDMINS_2_DATA(pIns, uintptr_t) < _4M); \
+ if (RTUuidCompare2Strs((pszIID), InterfaceType##_IID) == 0) \
+ { \
+ InterfaceType##R0 *pReturnInterfaceTypeCheck = (pInterface); \
+ return (uintptr_t)pReturnInterfaceTypeCheck \
+ - PDMINS_2_DATA(pIns, uintptr_t) \
+ + PDMINS_2_DATA_R0PTR(pIns); \
+ } \
+ } while (0)
+
+/** @} */
+
+
+/**
+ * Dummy interface.
+ *
+ * This is used to typedef other dummy interfaces. The purpose of a dummy
+ * interface is to validate the logical function of a driver/device and
+ * full a natural interface pair.
+ */
+typedef struct PDMIDUMMY
+{
+ RTHCPTR pvDummy;
+} PDMIDUMMY;
+
+
+/** Pointer to a mouse port interface. */
+typedef struct PDMIMOUSEPORT *PPDMIMOUSEPORT;
+/**
+ * Mouse port interface (down).
+ * Pair with PDMIMOUSECONNECTOR.
+ */
+typedef struct PDMIMOUSEPORT
+{
+ /**
+ * Puts a mouse event.
+ *
+ * This is called by the source of mouse events. The event will be passed up
+ * until the topmost driver, which then calls the registered event handler.
+ *
+ * @returns VBox status code. Return VERR_TRY_AGAIN if you cannot process the
+ * event now and want it to be repeated at a later point.
+ *
+ * @param pInterface Pointer to this interface structure.
+ * @param dx The X delta.
+ * @param dy The Y delta.
+ * @param dz The Z delta.
+ * @param dw The W (horizontal scroll button) delta.
+ * @param fButtons The button states, see the PDMIMOUSEPORT_BUTTON_* \#defines.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPutEvent,(PPDMIMOUSEPORT pInterface,
+ int32_t dx, int32_t dy, int32_t dz,
+ int32_t dw, uint32_t fButtons));
+ /**
+ * Puts an absolute mouse event.
+ *
+ * This is called by the source of mouse events. The event will be passed up
+ * until the topmost driver, which then calls the registered event handler.
+ *
+ * @returns VBox status code. Return VERR_TRY_AGAIN if you cannot process the
+ * event now and want it to be repeated at a later point.
+ *
+ * @param pInterface Pointer to this interface structure.
+ * @param x The X value, in the range 0 to 0xffff.
+ * @param y The Y value, in the range 0 to 0xffff.
+ * @param dz The Z delta.
+ * @param dw The W (horizontal scroll button) delta.
+ * @param fButtons The button states, see the PDMIMOUSEPORT_BUTTON_* \#defines.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPutEventAbs,(PPDMIMOUSEPORT pInterface,
+ uint32_t x, uint32_t y,
+ int32_t dz, int32_t dw,
+ uint32_t fButtons));
+ /**
+ * Puts a multi-touch absolute (touchscreen) event.
+ *
+ * @returns VBox status code. Return VERR_TRY_AGAIN if you cannot process the
+ * event now and want it to be repeated at a later point.
+ *
+ * @param pInterface Pointer to this interface structure.
+ * @param cContacts How many touch contacts in this event.
+ * @param pau64Contacts Pointer to array of packed contact information.
+ * Each 64bit element contains:
+ * Bits 0..15: X coordinate in pixels (signed).
+ * Bits 16..31: Y coordinate in pixels (signed).
+ * Bits 32..39: contact identifier.
+ * Bit 40: "in contact" flag, which indicates that
+ * there is a contact with the touch surface.
+ * Bit 41: "in range" flag, the contact is close enough
+ * to the touch surface.
+ * All other bits are reserved for future use and must be set to 0.
+ * @param u32ScanTime Timestamp of this event in milliseconds. Only relative
+ * time between event is important.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPutEventTouchScreen,(PPDMIMOUSEPORT pInterface,
+ uint8_t cContacts,
+ const uint64_t *pau64Contacts,
+ uint32_t u32ScanTime));
+
+ /**
+ * Puts a multi-touch relative (touchpad) event.
+ *
+ * @returns VBox status code. Return VERR_TRY_AGAIN if you cannot process the
+ * event now and want it to be repeated at a later point.
+ *
+ * @param pInterface Pointer to this interface structure.
+ * @param cContacts How many touch contacts in this event.
+ * @param pau64Contacts Pointer to array of packed contact information.
+ * Each 64bit element contains:
+ * Bits 0..15: Normalized X coordinate (range: 0 - 0xffff).
+ * Bits 16..31: Normalized Y coordinate (range: 0 - 0xffff).
+ * Bits 32..39: contact identifier.
+ * Bit 40: "in contact" flag, which indicates that
+ * there is a contact with the touch surface.
+ * All other bits are reserved for future use and must be set to 0.
+ * @param u32ScanTime Timestamp of this event in milliseconds. Only relative
+ * time between event is important.
+ */
+
+ DECLR3CALLBACKMEMBER(int, pfnPutEventTouchPad,(PPDMIMOUSEPORT pInterface,
+ uint8_t cContacts,
+ const uint64_t *pau64Contacts,
+ uint32_t u32ScanTime));
+} PDMIMOUSEPORT;
+/** PDMIMOUSEPORT interface ID. */
+#define PDMIMOUSEPORT_IID "d2bb54b7-d877-441b-9d25-d2d3329465c2"
+
+/** Mouse button defines for PDMIMOUSEPORT::pfnPutEvent.
+ * @{ */
+#define PDMIMOUSEPORT_BUTTON_LEFT RT_BIT(0)
+#define PDMIMOUSEPORT_BUTTON_RIGHT RT_BIT(1)
+#define PDMIMOUSEPORT_BUTTON_MIDDLE RT_BIT(2)
+#define PDMIMOUSEPORT_BUTTON_X1 RT_BIT(3)
+#define PDMIMOUSEPORT_BUTTON_X2 RT_BIT(4)
+/** @} */
+
+
+/** Pointer to a mouse connector interface. */
+typedef struct PDMIMOUSECONNECTOR *PPDMIMOUSECONNECTOR;
+/**
+ * Mouse connector interface (up).
+ * Pair with PDMIMOUSEPORT.
+ */
+typedef struct PDMIMOUSECONNECTOR
+{
+ /**
+ * Notifies the the downstream driver of changes to the reporting modes
+ * supported by the driver
+ *
+ * @param pInterface Pointer to this interface structure.
+ * @param fRelative Whether relative mode is currently supported.
+ * @param fAbsolute Whether absolute mode is currently supported.
+ * @param fMTAbsolute Whether absolute multi-touch mode is currently supported.
+ * @param fMTRelative Whether relative multi-touch mode is currently supported.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnReportModes,(PPDMIMOUSECONNECTOR pInterface, bool fRelative, bool fAbsolute, bool fMTAbsolute, bool fMTRelative));
+
+ /**
+ * Flushes the mouse queue if it contains pending events.
+ *
+ * @param pInterface Pointer to this interface structure.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnFlushQueue,(PPDMIMOUSECONNECTOR pInterface));
+
+} PDMIMOUSECONNECTOR;
+/** PDMIMOUSECONNECTOR interface ID. */
+#define PDMIMOUSECONNECTOR_IID "ce64d7bd-fa8f-41d1-a6fb-d102a2d6bffe"
+
+
+/** Flags for PDMIKEYBOARDPORT::pfnPutEventHid.
+ * @{ */
+#define PDMIKBDPORT_KEY_UP RT_BIT(31) /** Key release event if set. */
+#define PDMIKBDPORT_RELEASE_KEYS RT_BIT(30) /** Force all keys to be released. */
+/** @} */
+
+/** USB HID usage pages understood by PDMIKEYBOARDPORT::pfnPutEventHid.
+ * @{ */
+#define USB_HID_DC_PAGE 1 /** USB HID Generic Desktop Control Usage Page. */
+#define USB_HID_KB_PAGE 7 /** USB HID Keyboard Usage Page. */
+#define USB_HID_CC_PAGE 12 /** USB HID Consumer Control Usage Page. */
+/** @} */
+
+
+/** Pointer to a keyboard port interface. */
+typedef struct PDMIKEYBOARDPORT *PPDMIKEYBOARDPORT;
+/**
+ * Keyboard port interface (down).
+ * Pair with PDMIKEYBOARDCONNECTOR.
+ */
+typedef struct PDMIKEYBOARDPORT
+{
+ /**
+ * Puts a scan code based keyboard event.
+ *
+ * This is called by the source of keyboard events. The event will be passed up
+ * until the topmost driver, which then calls the registered event handler.
+ *
+ * @returns VBox status code. Return VERR_TRY_AGAIN if you cannot process the
+ * event now and want it to be repeated at a later point.
+ *
+ * @param pInterface Pointer to this interface structure.
+ * @param u8ScanCode The scan code to queue.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPutEventScan,(PPDMIKEYBOARDPORT pInterface, uint8_t u8KeyCode));
+
+ /**
+ * Puts a USB HID usage ID based keyboard event.
+ *
+ * This is called by the source of keyboard events. The event will be passed up
+ * until the topmost driver, which then calls the registered event handler.
+ *
+ * @returns VBox status code. Return VERR_TRY_AGAIN if you cannot process the
+ * event now and want it to be repeated at a later point.
+ *
+ * @param pInterface Pointer to this interface structure.
+ * @param idUsage The HID usage code event to queue.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPutEventHid,(PPDMIKEYBOARDPORT pInterface, uint32_t idUsage));
+
+ /**
+ * Forcibly releases any pressed keys.
+ *
+ * This is called by the source of keyboard events in situations when a full
+ * release of all currently pressed keys must be forced, e.g. when activating
+ * a different keyboard, or when key-up events may have been lost.
+ *
+ * @returns VBox status code.
+ *
+ * @param pInterface Pointer to this interface structure.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnReleaseKeys,(PPDMIKEYBOARDPORT pInterface));
+} PDMIKEYBOARDPORT;
+/** PDMIKEYBOARDPORT interface ID. */
+#define PDMIKEYBOARDPORT_IID "2a0844f0-410b-40ab-a6ed-6575f3aa3e29"
+
+
+/**
+ * Keyboard LEDs.
+ */
+typedef enum PDMKEYBLEDS
+{
+ /** No leds. */
+ PDMKEYBLEDS_NONE = 0x0000,
+ /** Num Lock */
+ PDMKEYBLEDS_NUMLOCK = 0x0001,
+ /** Caps Lock */
+ PDMKEYBLEDS_CAPSLOCK = 0x0002,
+ /** Scroll Lock */
+ PDMKEYBLEDS_SCROLLLOCK = 0x0004
+} PDMKEYBLEDS;
+
+/** Pointer to keyboard connector interface. */
+typedef struct PDMIKEYBOARDCONNECTOR *PPDMIKEYBOARDCONNECTOR;
+/**
+ * Keyboard connector interface (up).
+ * Pair with PDMIKEYBOARDPORT
+ */
+typedef struct PDMIKEYBOARDCONNECTOR
+{
+ /**
+ * Notifies the the downstream driver about an LED change initiated by the guest.
+ *
+ * @param pInterface Pointer to this interface structure.
+ * @param enmLeds The new led mask.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnLedStatusChange,(PPDMIKEYBOARDCONNECTOR pInterface, PDMKEYBLEDS enmLeds));
+
+ /**
+ * Notifies the the downstream driver of changes in driver state.
+ *
+ * @param pInterface Pointer to this interface structure.
+ * @param fActive Whether interface wishes to get "focus".
+ */
+ DECLR3CALLBACKMEMBER(void, pfnSetActive,(PPDMIKEYBOARDCONNECTOR pInterface, bool fActive));
+
+ /**
+ * Flushes the keyboard queue if it contains pending events.
+ *
+ * @param pInterface Pointer to this interface structure.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnFlushQueue,(PPDMIKEYBOARDCONNECTOR pInterface));
+
+} PDMIKEYBOARDCONNECTOR;
+/** PDMIKEYBOARDCONNECTOR interface ID. */
+#define PDMIKEYBOARDCONNECTOR_IID "db3f7bd5-953e-436f-9f8e-077905a92d82"
+
+
+
+/** Pointer to a display port interface. */
+typedef struct PDMIDISPLAYPORT *PPDMIDISPLAYPORT;
+/**
+ * Display port interface (down).
+ * Pair with PDMIDISPLAYCONNECTOR.
+ */
+typedef struct PDMIDISPLAYPORT
+{
+ /**
+ * Update the display with any changed regions.
+ *
+ * Flushes any display changes to the memory pointed to by the
+ * PDMIDISPLAYCONNECTOR interface and calles PDMIDISPLAYCONNECTOR::pfnUpdateRect()
+ * while doing so.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to this interface.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnUpdateDisplay,(PPDMIDISPLAYPORT pInterface));
+
+ /**
+ * Update the entire display.
+ *
+ * Flushes the entire display content to the memory pointed to by the
+ * PDMIDISPLAYCONNECTOR interface and calles PDMIDISPLAYCONNECTOR::pfnUpdateRect().
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to this interface.
+ * @param fFailOnResize Fail is a resize is pending.
+ * @thread The emulation thread - bird sees no need for EMT here!
+ */
+ DECLR3CALLBACKMEMBER(int, pfnUpdateDisplayAll,(PPDMIDISPLAYPORT pInterface, bool fFailOnResize));
+
+ /**
+ * Return the current guest resolution and color depth in bits per pixel (bpp).
+ *
+ * As the graphics card is able to provide display updates with the bpp
+ * requested by the host, this method can be used to query the actual
+ * guest color depth.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to this interface.
+ * @param pcBits Where to store the current guest color depth.
+ * @param pcx Where to store the horizontal resolution.
+ * @param pcy Where to store the vertical resolution.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnQueryVideoMode,(PPDMIDISPLAYPORT pInterface, uint32_t *pcBits, uint32_t *pcx, uint32_t *pcy));
+
+ /**
+ * Sets the refresh rate and restart the timer.
+ * The rate is defined as the minimum interval between the return of
+ * one PDMIDISPLAYPORT::pfnRefresh() call to the next one.
+ *
+ * The interval timer will be restarted by this call. So at VM startup
+ * this function must be called to start the refresh cycle. The refresh
+ * rate is not saved, but have to be when resuming a loaded VM state.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to this interface.
+ * @param cMilliesInterval Number of millis between two refreshes.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSetRefreshRate,(PPDMIDISPLAYPORT pInterface, uint32_t cMilliesInterval));
+
+ /**
+ * Create a 32-bbp screenshot of the display.
+ *
+ * This will allocate and return a 32-bbp bitmap. Size of the bitmap scanline in bytes is 4*width.
+ *
+ * The allocated bitmap buffer must be freed with pfnFreeScreenshot.
+ *
+ * @param pInterface Pointer to this interface.
+ * @param ppbData Where to store the pointer to the allocated
+ * buffer.
+ * @param pcbData Where to store the actual size of the bitmap.
+ * @param pcx Where to store the width of the bitmap.
+ * @param pcy Where to store the height of the bitmap.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnTakeScreenshot,(PPDMIDISPLAYPORT pInterface, uint8_t **ppbData, size_t *pcbData, uint32_t *pcx, uint32_t *pcy));
+
+ /**
+ * Free screenshot buffer.
+ *
+ * This will free the memory buffer allocated by pfnTakeScreenshot.
+ *
+ * @param pInterface Pointer to this interface.
+ * @param pbData Pointer to the buffer returned by
+ * pfnTakeScreenshot.
+ * @thread Any.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnFreeScreenshot,(PPDMIDISPLAYPORT pInterface, uint8_t *pbData));
+
+ /**
+ * Copy bitmap to the display.
+ *
+ * This will convert and copy a 32-bbp bitmap (with dword aligned scanline length) to
+ * the memory pointed to by the PDMIDISPLAYCONNECTOR interface.
+ *
+ * @param pInterface Pointer to this interface.
+ * @param pvData Pointer to the bitmap bits.
+ * @param x The upper left corner x coordinate of the destination rectangle.
+ * @param y The upper left corner y coordinate of the destination rectangle.
+ * @param cx The width of the source and destination rectangles.
+ * @param cy The height of the source and destination rectangles.
+ * @thread The emulation thread.
+ * @remark This is just a convenience for using the bitmap conversions of the
+ * graphics device.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnDisplayBlt,(PPDMIDISPLAYPORT pInterface, const void *pvData, uint32_t x, uint32_t y, uint32_t cx, uint32_t cy));
+
+ /**
+ * Render a rectangle from guest VRAM to Framebuffer.
+ *
+ * @param pInterface Pointer to this interface.
+ * @param x The upper left corner x coordinate of the rectangle to be updated.
+ * @param y The upper left corner y coordinate of the rectangle to be updated.
+ * @param cx The width of the rectangle to be updated.
+ * @param cy The height of the rectangle to be updated.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnUpdateDisplayRect,(PPDMIDISPLAYPORT pInterface, int32_t x, int32_t y, uint32_t cx, uint32_t cy));
+
+ /**
+ * Inform the VGA device whether the Display is directly using the guest VRAM and there is no need
+ * to render the VRAM to the framebuffer memory.
+ *
+ * @param pInterface Pointer to this interface.
+ * @param fRender Whether the VRAM content must be rendered to the framebuffer.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnSetRenderVRAM,(PPDMIDISPLAYPORT pInterface, bool fRender));
+
+ /**
+ * Render a bitmap rectangle from source to target buffer.
+ *
+ * @param pInterface Pointer to this interface.
+ * @param cx The width of the rectangle to be copied.
+ * @param cy The height of the rectangle to be copied.
+ * @param pbSrc Source frame buffer 0,0.
+ * @param xSrc The upper left corner x coordinate of the source rectangle.
+ * @param ySrc The upper left corner y coordinate of the source rectangle.
+ * @param cxSrc The width of the source frame buffer.
+ * @param cySrc The height of the source frame buffer.
+ * @param cbSrcLine The line length of the source frame buffer.
+ * @param cSrcBitsPerPixel The pixel depth of the source.
+ * @param pbDst Destination frame buffer 0,0.
+ * @param xDst The upper left corner x coordinate of the destination rectangle.
+ * @param yDst The upper left corner y coordinate of the destination rectangle.
+ * @param cxDst The width of the destination frame buffer.
+ * @param cyDst The height of the destination frame buffer.
+ * @param cbDstLine The line length of the destination frame buffer.
+ * @param cDstBitsPerPixel The pixel depth of the destination.
+ * @thread The emulation thread - bird sees no need for EMT here!
+ */
+ DECLR3CALLBACKMEMBER(int, pfnCopyRect,(PPDMIDISPLAYPORT pInterface, uint32_t cx, uint32_t cy,
+ const uint8_t *pbSrc, int32_t xSrc, int32_t ySrc, uint32_t cxSrc, uint32_t cySrc, uint32_t cbSrcLine, uint32_t cSrcBitsPerPixel,
+ uint8_t *pbDst, int32_t xDst, int32_t yDst, uint32_t cxDst, uint32_t cyDst, uint32_t cbDstLine, uint32_t cDstBitsPerPixel));
+
+ /**
+ * Inform the VGA device of viewport changes (as a result of e.g. scrolling).
+ *
+ * @param pInterface Pointer to this interface.
+ * @param idScreen The screen updates are for.
+ * @param x The upper left corner x coordinate of the new viewport rectangle
+ * @param y The upper left corner y coordinate of the new viewport rectangle
+ * @param cx The width of the new viewport rectangle
+ * @param cy The height of the new viewport rectangle
+ * @thread GUI thread?
+ *
+ * @remarks Is allowed to be NULL.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnSetViewport,(PPDMIDISPLAYPORT pInterface,
+ uint32_t idScreen, uint32_t x, uint32_t y, uint32_t cx, uint32_t cy));
+
+ /**
+ * Send a video mode hint to the VGA device.
+ *
+ * @param pInterface Pointer to this interface.
+ * @param cx The X resolution.
+ * @param cy The Y resolution.
+ * @param cBPP The bit count.
+ * @param iDisplay The screen number.
+ * @param dx X offset into the virtual framebuffer or ~0.
+ * @param dy Y offset into the virtual framebuffer or ~0.
+ * @param fEnabled Is this screen currently enabled?
+ * @param fNotifyGuest Should the device send the guest an IRQ?
+ * Set for the last hint of a series.
+ * @thread Schedules on the emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSendModeHint, (PPDMIDISPLAYPORT pInterface, uint32_t cx, uint32_t cy,
+ uint32_t cBPP, uint32_t iDisplay, uint32_t dx,
+ uint32_t dy, uint32_t fEnabled, uint32_t fNotifyGuest));
+
+ /**
+ * Send the guest a notification about host cursor capabilities changes.
+ *
+ * @param pInterface Pointer to this interface.
+ * @param fSupportsRenderCursor Whether the host can draw the guest cursor
+ * using the host one provided the location matches.
+ * @param fSupportsMoveCursor Whether the host can draw the guest cursor
+ * itself at any position. Implies RenderCursor.
+ * @thread Any.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnReportHostCursorCapabilities, (PPDMIDISPLAYPORT pInterface, bool fSupportsRenderCursor, bool fSupportsMoveCursor));
+
+ /**
+ * Tell the graphics device about the host cursor position.
+ *
+ * @param pInterface Pointer to this interface.
+ * @param x X offset into the cursor range.
+ * @param y Y offset into the cursor range.
+ * @param fOutOfRange The host pointer is out of all guest windows, so
+ * X and Y do not currently have meaningful value.
+ * @thread Any.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnReportHostCursorPosition, (PPDMIDISPLAYPORT pInterface, uint32_t x, uint32_t y, bool fOutOfRange));
+
+ /**
+ * Notify the graphics device about the monitor positions since the ones we get
+ * from vmwgfx FIFO are not correct.
+ *
+ * In an ideal universe this method should not be here.
+ *
+ * @param pInterface Pointer to this interface.
+ * @param cPositions Number of monitor positions.
+ * @param paPositions Monitor positions (offsets/origins) array.
+ * @thread Any (EMT).
+ * @sa PDMIVMMDEVCONNECTOR::pfnUpdateMonitorPositions
+ */
+ DECLR3CALLBACKMEMBER(void, pfnReportMonitorPositions, (PPDMIDISPLAYPORT pInterface, uint32_t cPositions,
+ PCRTPOINT paPositions));
+
+} PDMIDISPLAYPORT;
+/** PDMIDISPLAYPORT interface ID. */
+#define PDMIDISPLAYPORT_IID "471b0520-338c-11e9-bb84-6ff2c956da45"
+
+/** @name Flags for PDMIDISPLAYCONNECTOR::pfnVBVAReportCursorPosition.
+ * @{ */
+/** Is the data in the report valid? */
+#define VBVA_CURSOR_VALID_DATA RT_BIT(0)
+/** Is the cursor position reported relative to a particular guest screen? */
+#define VBVA_CURSOR_SCREEN_RELATIVE RT_BIT(1)
+/** @} */
+
+/** Pointer to a 3D graphics notification. */
+typedef struct VBOX3DNOTIFY VBOX3DNOTIFY;
+/** Pointer to a 2D graphics acceleration command. */
+typedef struct VBOXVHWACMD VBOXVHWACMD;
+/** Pointer to a VBVA command header. */
+typedef struct VBVACMDHDR *PVBVACMDHDR;
+/** Pointer to a const VBVA command header. */
+typedef const struct VBVACMDHDR *PCVBVACMDHDR;
+/** Pointer to a VBVA screen information. */
+typedef struct VBVAINFOSCREEN *PVBVAINFOSCREEN;
+/** Pointer to a const VBVA screen information. */
+typedef const struct VBVAINFOSCREEN *PCVBVAINFOSCREEN;
+/** Pointer to a VBVA guest VRAM area information. */
+typedef struct VBVAINFOVIEW *PVBVAINFOVIEW;
+/** Pointer to a const VBVA guest VRAM area information. */
+typedef const struct VBVAINFOVIEW *PCVBVAINFOVIEW;
+typedef struct VBVAHOSTFLAGS *PVBVAHOSTFLAGS;
+
+/** Pointer to a display connector interface. */
+typedef struct PDMIDISPLAYCONNECTOR *PPDMIDISPLAYCONNECTOR;
+
+/**
+ * Display connector interface (up).
+ * Pair with PDMIDISPLAYPORT.
+ */
+typedef struct PDMIDISPLAYCONNECTOR
+{
+ /**
+ * Resize the display.
+ * This is called when the resolution changes. This usually happens on
+ * request from the guest os, but may also happen as the result of a reset.
+ * If the callback returns VINF_VGA_RESIZE_IN_PROGRESS, the caller (VGA device)
+ * must not access the connector and return.
+ *
+ * @returns VINF_SUCCESS if the framebuffer resize was completed,
+ * VINF_VGA_RESIZE_IN_PROGRESS if resize takes time and not yet finished.
+ * @param pInterface Pointer to this interface.
+ * @param cBits Color depth (bits per pixel) of the new video mode.
+ * @param pvVRAM Address of the guest VRAM.
+ * @param cbLine Size in bytes of a single scan line.
+ * @param cx New display width.
+ * @param cy New display height.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnResize,(PPDMIDISPLAYCONNECTOR pInterface, uint32_t cBits, void *pvVRAM, uint32_t cbLine,
+ uint32_t cx, uint32_t cy));
+
+ /**
+ * Update a rectangle of the display.
+ * PDMIDISPLAYPORT::pfnUpdateDisplay is the caller.
+ *
+ * @param pInterface Pointer to this interface.
+ * @param x The upper left corner x coordinate of the rectangle.
+ * @param y The upper left corner y coordinate of the rectangle.
+ * @param cx The width of the rectangle.
+ * @param cy The height of the rectangle.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnUpdateRect,(PPDMIDISPLAYCONNECTOR pInterface, uint32_t x, uint32_t y, uint32_t cx, uint32_t cy));
+
+ /**
+ * Refresh the display.
+ *
+ * The interval between these calls is set by
+ * PDMIDISPLAYPORT::pfnSetRefreshRate(). The driver should call
+ * PDMIDISPLAYPORT::pfnUpdateDisplay() if it wishes to refresh the
+ * display. PDMIDISPLAYPORT::pfnUpdateDisplay calls pfnUpdateRect with
+ * the changed rectangles.
+ *
+ * @param pInterface Pointer to this interface.
+ * @thread The emulation thread or timer queue thread.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnRefresh,(PPDMIDISPLAYCONNECTOR pInterface));
+
+ /**
+ * Reset the display.
+ *
+ * Notification message when the graphics card has been reset.
+ *
+ * @param pInterface Pointer to this interface.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnReset,(PPDMIDISPLAYCONNECTOR pInterface));
+
+ /**
+ * LFB video mode enter/exit.
+ *
+ * Notification message when LinearFrameBuffer video mode is enabled/disabled.
+ *
+ * @param pInterface Pointer to this interface.
+ * @param fEnabled false - LFB mode was disabled,
+ * true - an LFB mode was disabled
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnLFBModeChange,(PPDMIDISPLAYCONNECTOR pInterface, bool fEnabled));
+
+ /**
+ * Process the guest graphics adapter information.
+ *
+ * Direct notification from guest to the display connector.
+ *
+ * @param pInterface Pointer to this interface.
+ * @param pvVRAM Address of the guest VRAM.
+ * @param u32VRAMSize Size of the guest VRAM.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnProcessAdapterData,(PPDMIDISPLAYCONNECTOR pInterface, void *pvVRAM, uint32_t u32VRAMSize));
+
+ /**
+ * Process the guest display information.
+ *
+ * Direct notification from guest to the display connector.
+ *
+ * @param pInterface Pointer to this interface.
+ * @param pvVRAM Address of the guest VRAM.
+ * @param uScreenId The index of the guest display to be processed.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnProcessDisplayData,(PPDMIDISPLAYCONNECTOR pInterface, void *pvVRAM, unsigned uScreenId));
+
+ /**
+ * Process the guest Video HW Acceleration command.
+ *
+ * @param pInterface Pointer to this interface.
+ * @param enmCmd The command type (don't re-read from pCmd).
+ * @param fGuestCmd Set if the command origins with the guest and
+ * pCmd must be considered volatile.
+ * @param pCmd Video HW Acceleration Command to be processed.
+ * @retval VINF_SUCCESS - command is completed,
+ * @retval VINF_CALLBACK_RETURN if command will by asynchronously completed via
+ * complete callback.
+ * @retval VERR_INVALID_STATE if the command could not be processed (most
+ * likely because the framebuffer was disconnected) - the post should
+ * be retried later.
+ * @thread EMT
+ */
+ DECLR3CALLBACKMEMBER(int, pfnVHWACommandProcess,(PPDMIDISPLAYCONNECTOR pInterface, int enmCmd, bool fGuestCmd,
+ VBOXVHWACMD RT_UNTRUSTED_VOLATILE_GUEST *pCmd));
+
+ /**
+ * The specified screen enters VBVA mode.
+ *
+ * @param pInterface Pointer to this interface.
+ * @param uScreenId The screen updates are for.
+ * @param pHostFlags Undocumented!
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnVBVAEnable,(PPDMIDISPLAYCONNECTOR pInterface, unsigned uScreenId,
+ struct VBVAHOSTFLAGS RT_UNTRUSTED_VOLATILE_GUEST *pHostFlags));
+
+ /**
+ * The specified screen leaves VBVA mode.
+ *
+ * @param pInterface Pointer to this interface.
+ * @param uScreenId The screen updates are for.
+ * @thread if render thread mode is on (fRenderThreadMode that was passed to pfnVBVAEnable is TRUE) - the render thread pfnVBVAEnable was called in,
+ * otherwise - the emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnVBVADisable,(PPDMIDISPLAYCONNECTOR pInterface, unsigned uScreenId));
+
+ /**
+ * A sequence of pfnVBVAUpdateProcess calls begins.
+ *
+ * @param pInterface Pointer to this interface.
+ * @param uScreenId The screen updates are for.
+ * @thread if render thread mode is on (fRenderThreadMode that was passed to pfnVBVAEnable is TRUE) - the render thread pfnVBVAEnable was called in,
+ * otherwise - the emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnVBVAUpdateBegin,(PPDMIDISPLAYCONNECTOR pInterface, unsigned uScreenId));
+
+ /**
+ * Process the guest VBVA command.
+ *
+ * @param pInterface Pointer to this interface.
+ * @param uScreenId The screen updates are for.
+ * @param pCmd Video HW Acceleration Command to be processed.
+ * @param cbCmd Undocumented!
+ * @thread if render thread mode is on (fRenderThreadMode that was passed to pfnVBVAEnable is TRUE) - the render thread pfnVBVAEnable was called in,
+ * otherwise - the emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnVBVAUpdateProcess,(PPDMIDISPLAYCONNECTOR pInterface, unsigned uScreenId,
+ struct VBVACMDHDR const RT_UNTRUSTED_VOLATILE_GUEST *pCmd, size_t cbCmd));
+
+ /**
+ * A sequence of pfnVBVAUpdateProcess calls ends.
+ *
+ * @param pInterface Pointer to this interface.
+ * @param uScreenId The screen updates are for.
+ * @param x The upper left corner x coordinate of the combined rectangle of all VBVA updates.
+ * @param y The upper left corner y coordinate of the rectangle.
+ * @param cx The width of the rectangle.
+ * @param cy The height of the rectangle.
+ * @thread if render thread mode is on (fRenderThreadMode that was passed to pfnVBVAEnable is TRUE) - the render thread pfnVBVAEnable was called in,
+ * otherwise - the emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnVBVAUpdateEnd,(PPDMIDISPLAYCONNECTOR pInterface, unsigned uScreenId, int32_t x, int32_t y,
+ uint32_t cx, uint32_t cy));
+
+ /**
+ * Resize the display.
+ * This is called when the resolution changes. This usually happens on
+ * request from the guest os, but may also happen as the result of a reset.
+ * If the callback returns VINF_VGA_RESIZE_IN_PROGRESS, the caller (VGA device)
+ * must not access the connector and return.
+ *
+ * @todo Merge with pfnResize.
+ *
+ * @returns VINF_SUCCESS if the framebuffer resize was completed,
+ * VINF_VGA_RESIZE_IN_PROGRESS if resize takes time and not yet finished.
+ * @param pInterface Pointer to this interface.
+ * @param pView The description of VRAM block for this screen.
+ * @param pScreen The data of screen being resized.
+ * @param pvVRAM Address of the guest VRAM.
+ * @param fResetInputMapping Whether to reset the absolute pointing device to screen position co-ordinate
+ * mapping. Needed for real resizes, as the caller on the guest may not know how
+ * to set the mapping. Not wanted when we restore a saved state and are resetting
+ * the mode.
+ * @thread if render thread mode is on (fRenderThreadMode that was passed to pfnVBVAEnable is TRUE) - the render thread pfnVBVAEnable was called in,
+ * otherwise - the emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnVBVAResize,(PPDMIDISPLAYCONNECTOR pInterface, PCVBVAINFOVIEW pView, PCVBVAINFOSCREEN pScreen,
+ void *pvVRAM, bool fResetInputMapping));
+
+ /**
+ * Update the pointer shape.
+ * This is called when the mouse pointer shape changes. The new shape
+ * is passed as a caller allocated buffer that will be freed after returning
+ *
+ * @param pInterface Pointer to this interface.
+ * @param fVisible Visibility indicator (if false, the other parameters are undefined).
+ * @param fAlpha Flag whether alpha channel is being passed.
+ * @param xHot Pointer hot spot x coordinate.
+ * @param yHot Pointer hot spot y coordinate.
+ * @param cx Pointer width in pixels.
+ * @param cy Pointer height in pixels.
+ * @param pvShape New shape buffer.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnVBVAMousePointerShape,(PPDMIDISPLAYCONNECTOR pInterface, bool fVisible, bool fAlpha,
+ uint32_t xHot, uint32_t yHot, uint32_t cx, uint32_t cy,
+ const void *pvShape));
+
+ /**
+ * The guest capabilities were updated.
+ *
+ * @param pInterface Pointer to this interface.
+ * @param fCapabilities The new capability flag state.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnVBVAGuestCapabilityUpdate,(PPDMIDISPLAYCONNECTOR pInterface, uint32_t fCapabilities));
+
+ /** Read-only attributes.
+ * For preformance reasons some readonly attributes are kept in the interface.
+ * We trust the interface users to respect the readonlyness of these.
+ * @{
+ */
+ /** Pointer to the display data buffer. */
+ uint8_t *pbData;
+ /** Size of a scanline in the data buffer. */
+ uint32_t cbScanline;
+ /** The color depth (in bits) the graphics card is supposed to provide. */
+ uint32_t cBits;
+ /** The display width. */
+ uint32_t cx;
+ /** The display height. */
+ uint32_t cy;
+ /** @} */
+
+ /**
+ * The guest display input mapping rectangle was updated.
+ *
+ * @param pInterface Pointer to this interface.
+ * @param xOrigin Upper left X co-ordinate relative to the first screen.
+ * @param yOrigin Upper left Y co-ordinate relative to the first screen.
+ * @param cx Rectangle width.
+ * @param cy Rectangle height.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnVBVAInputMappingUpdate,(PPDMIDISPLAYCONNECTOR pInterface, int32_t xOrigin, int32_t yOrigin, uint32_t cx, uint32_t cy));
+
+ /**
+ * The guest is reporting the requested location of the host pointer.
+ *
+ * @param pInterface Pointer to this interface.
+ * @param fFlags VBVA_CURSOR_*
+ * @param uScreenId The screen to which X and Y are relative if VBVA_CURSOR_SCREEN_RELATIVE is set.
+ * @param x Cursor X offset.
+ * @param y Cursor Y offset.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnVBVAReportCursorPosition,(PPDMIDISPLAYCONNECTOR pInterface, uint32_t fFlags, uint32_t uScreen, uint32_t x, uint32_t y));
+
+ /**
+ * Process the graphics device HW Acceleration command.
+ *
+ * @param pInterface Pointer to this interface.
+ * @param p3DNotify Acceleration Command to be processed.
+ * @thread The graphics device thread: FIFO for the VMSVGA device.
+ */
+ DECLR3CALLBACKMEMBER(int, pfn3DNotifyProcess,(PPDMIDISPLAYCONNECTOR pInterface,
+ VBOX3DNOTIFY *p3DNotify));
+} PDMIDISPLAYCONNECTOR;
+/** PDMIDISPLAYCONNECTOR interface ID. */
+#define PDMIDISPLAYCONNECTOR_IID "cdd562e4-8030-11ea-8d40-bbc8e146c565"
+
+
+/** Pointer to a secret key interface. */
+typedef struct PDMISECKEY *PPDMISECKEY;
+
+/**
+ * Secret key interface to retrieve secret keys.
+ */
+typedef struct PDMISECKEY
+{
+ /**
+ * Retains a key identified by the ID. The caller will only hold a reference
+ * to the key and must not modify the key buffer in any way.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to this interface.
+ * @param pszId The alias/id for the key to retrieve.
+ * @param ppbKey Where to store the pointer to the key buffer on success.
+ * @param pcbKey Where to store the size of the key in bytes on success.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnKeyRetain, (PPDMISECKEY pInterface, const char *pszId,
+ const uint8_t **pbKey, size_t *pcbKey));
+
+ /**
+ * Releases one reference of the key identified by the given identifier.
+ * The caller must not access the key buffer after calling this operation.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to this interface.
+ * @param pszId The alias/id for the key to release.
+ *
+ * @note: It is advised to release the key whenever it is not used anymore so the entity
+ * storing the key can do anything to make retrieving the key from memory more
+ * difficult like scrambling the memory buffer for instance.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnKeyRelease, (PPDMISECKEY pInterface, const char *pszId));
+
+ /**
+ * Retains a password identified by the ID. The caller will only hold a reference
+ * to the password and must not modify the buffer in any way.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to this interface.
+ * @param pszId The alias/id for the password to retrieve.
+ * @param ppszPassword Where to store the pointer to the password on success.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPasswordRetain, (PPDMISECKEY pInterface, const char *pszId,
+ const char **ppszPassword));
+
+ /**
+ * Releases one reference of the password identified by the given identifier.
+ * The caller must not access the password after calling this operation.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to this interface.
+ * @param pszId The alias/id for the password to release.
+ *
+ * @note: It is advised to release the password whenever it is not used anymore so the entity
+ * storing the password can do anything to make retrieving the password from memory more
+ * difficult like scrambling the memory buffer for instance.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPasswordRelease, (PPDMISECKEY pInterface, const char *pszId));
+} PDMISECKEY;
+/** PDMISECKEY interface ID. */
+#define PDMISECKEY_IID "3d698355-d995-453d-960f-31566a891df2"
+
+/** Pointer to a secret key helper interface. */
+typedef struct PDMISECKEYHLP *PPDMISECKEYHLP;
+
+/**
+ * Secret key helper interface for non critical functionality.
+ */
+typedef struct PDMISECKEYHLP
+{
+ /**
+ * Notifies the interface provider that a key couldn't be retrieved from the key store.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to this interface.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnKeyMissingNotify, (PPDMISECKEYHLP pInterface));
+
+} PDMISECKEYHLP;
+/** PDMISECKEY interface ID. */
+#define PDMISECKEYHLP_IID "7be96168-4156-40ac-86d2-3073bf8b318e"
+
+
+/** Pointer to a stream interface. */
+typedef struct PDMISTREAM *PPDMISTREAM;
+/**
+ * Stream interface (up).
+ * Makes up the foundation for PDMICHARCONNECTOR. No pair interface.
+ */
+typedef struct PDMISTREAM
+{
+ /**
+ * Polls for the specified events.
+ *
+ * @returns VBox status code.
+ * @retval VERR_INTERRUPTED if the poll was interrupted.
+ * @retval VERR_TIMEOUT if the maximum waiting time was reached.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param fEvts The events to poll for, see RTPOLL_EVT_XXX.
+ * @param pfEvts Where to return details about the events that occurred.
+ * @param cMillies Number of milliseconds to wait. Use
+ * RT_INDEFINITE_WAIT to wait for ever.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPoll,(PPDMISTREAM pInterface, uint32_t fEvts, uint32_t *pfEvts, RTMSINTERVAL cMillies));
+
+ /**
+ * Interrupts the current poll call.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPollInterrupt,(PPDMISTREAM pInterface));
+
+ /**
+ * Read bits.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pvBuf Where to store the read bits.
+ * @param pcbRead Number of bytes to read/bytes actually read.
+ * @thread Any thread.
+ *
+ * @note: This is non blocking, use the poll callback to block when there is nothing to read.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnRead,(PPDMISTREAM pInterface, void *pvBuf, size_t *pcbRead));
+
+ /**
+ * Write bits.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pvBuf Where to store the write bits.
+ * @param pcbWrite Number of bytes to write/bytes actually written.
+ * @thread Any thread.
+ *
+ * @note: This is non blocking, use the poll callback to block until there is room to write.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnWrite,(PPDMISTREAM pInterface, const void *pvBuf, size_t *pcbWrite));
+} PDMISTREAM;
+/** PDMISTREAM interface ID. */
+#define PDMISTREAM_IID "f9bd1ba6-c134-44cc-8259-febe14393952"
+
+
+/** Mode of the parallel port */
+typedef enum PDMPARALLELPORTMODE
+{
+ /** First invalid mode. */
+ PDM_PARALLEL_PORT_MODE_INVALID = 0,
+ /** SPP (Compatibility mode). */
+ PDM_PARALLEL_PORT_MODE_SPP,
+ /** EPP Data mode. */
+ PDM_PARALLEL_PORT_MODE_EPP_DATA,
+ /** EPP Address mode. */
+ PDM_PARALLEL_PORT_MODE_EPP_ADDR,
+ /** ECP mode (not implemented yet). */
+ PDM_PARALLEL_PORT_MODE_ECP,
+ /** 32bit hack. */
+ PDM_PARALLEL_PORT_MODE_32BIT_HACK = 0x7fffffff
+} PDMPARALLELPORTMODE;
+
+/** Pointer to a host parallel port interface. */
+typedef struct PDMIHOSTPARALLELPORT *PPDMIHOSTPARALLELPORT;
+/**
+ * Host parallel port interface (down).
+ * Pair with PDMIHOSTPARALLELCONNECTOR.
+ */
+typedef struct PDMIHOSTPARALLELPORT
+{
+ /**
+ * Notify device/driver that an interrupt has occurred.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnNotifyInterrupt,(PPDMIHOSTPARALLELPORT pInterface));
+} PDMIHOSTPARALLELPORT;
+/** PDMIHOSTPARALLELPORT interface ID. */
+#define PDMIHOSTPARALLELPORT_IID "f24b8668-e7f6-4eaa-a14c-4aa2a5f7048e"
+
+
+
+/** Pointer to a Host Parallel connector interface. */
+typedef struct PDMIHOSTPARALLELCONNECTOR *PPDMIHOSTPARALLELCONNECTOR;
+/**
+ * Host parallel connector interface (up).
+ * Pair with PDMIHOSTPARALLELPORT.
+ */
+typedef struct PDMIHOSTPARALLELCONNECTOR
+{
+ /**
+ * Write bits.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pvBuf Where to store the write bits.
+ * @param cbWrite Number of bytes to write.
+ * @param enmMode Mode to write the data.
+ * @thread Any thread.
+ * @todo r=klaus cbWrite only defines buffer length, method needs a way top return actually written amount of data.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnWrite,(PPDMIHOSTPARALLELCONNECTOR pInterface, const void *pvBuf,
+ size_t cbWrite, PDMPARALLELPORTMODE enmMode));
+
+ /**
+ * Read bits.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pvBuf Where to store the read bits.
+ * @param cbRead Number of bytes to read.
+ * @param enmMode Mode to read the data.
+ * @thread Any thread.
+ * @todo r=klaus cbRead only defines buffer length, method needs a way top return actually read amount of data.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnRead,(PPDMIHOSTPARALLELCONNECTOR pInterface, void *pvBuf,
+ size_t cbRead, PDMPARALLELPORTMODE enmMode));
+
+ /**
+ * Set data direction of the port (forward/reverse).
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param fForward Flag whether to indicate whether the port is operated in forward or reverse mode.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSetPortDirection,(PPDMIHOSTPARALLELCONNECTOR pInterface, bool fForward));
+
+ /**
+ * Write control register bits.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param fReg The new control register value.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnWriteControl,(PPDMIHOSTPARALLELCONNECTOR pInterface, uint8_t fReg));
+
+ /**
+ * Read control register bits.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pfReg Where to store the control register bits.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnReadControl,(PPDMIHOSTPARALLELCONNECTOR pInterface, uint8_t *pfReg));
+
+ /**
+ * Read status register bits.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pfReg Where to store the status register bits.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnReadStatus,(PPDMIHOSTPARALLELCONNECTOR pInterface, uint8_t *pfReg));
+
+} PDMIHOSTPARALLELCONNECTOR;
+/** PDMIHOSTPARALLELCONNECTOR interface ID. */
+#define PDMIHOSTPARALLELCONNECTOR_IID "7c532602-7438-4fbc-9265-349d9f0415f9"
+
+
+/** ACPI power source identifier */
+typedef enum PDMACPIPOWERSOURCE
+{
+ PDM_ACPI_POWER_SOURCE_UNKNOWN = 0,
+ PDM_ACPI_POWER_SOURCE_OUTLET,
+ PDM_ACPI_POWER_SOURCE_BATTERY
+} PDMACPIPOWERSOURCE;
+/** Pointer to ACPI battery state. */
+typedef PDMACPIPOWERSOURCE *PPDMACPIPOWERSOURCE;
+
+/** ACPI battey capacity */
+typedef enum PDMACPIBATCAPACITY
+{
+ PDM_ACPI_BAT_CAPACITY_MIN = 0,
+ PDM_ACPI_BAT_CAPACITY_MAX = 100,
+ PDM_ACPI_BAT_CAPACITY_UNKNOWN = 255
+} PDMACPIBATCAPACITY;
+/** Pointer to ACPI battery capacity. */
+typedef PDMACPIBATCAPACITY *PPDMACPIBATCAPACITY;
+
+/** ACPI battery state. See ACPI 3.0 spec '_BST (Battery Status)' */
+typedef enum PDMACPIBATSTATE
+{
+ PDM_ACPI_BAT_STATE_CHARGED = 0x00,
+ PDM_ACPI_BAT_STATE_DISCHARGING = 0x01,
+ PDM_ACPI_BAT_STATE_CHARGING = 0x02,
+ PDM_ACPI_BAT_STATE_CRITICAL = 0x04
+} PDMACPIBATSTATE;
+/** Pointer to ACPI battery state. */
+typedef PDMACPIBATSTATE *PPDMACPIBATSTATE;
+
+/** Pointer to an ACPI port interface. */
+typedef struct PDMIACPIPORT *PPDMIACPIPORT;
+/**
+ * ACPI port interface (down). Used by both the ACPI driver and (grumble) main.
+ * Pair with PDMIACPICONNECTOR.
+ */
+typedef struct PDMIACPIPORT
+{
+ /**
+ * Send an ACPI power off event.
+ *
+ * @returns VBox status code
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPowerButtonPress,(PPDMIACPIPORT pInterface));
+
+ /**
+ * Send an ACPI sleep button event.
+ *
+ * @returns VBox status code
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSleepButtonPress,(PPDMIACPIPORT pInterface));
+
+ /**
+ * Check if the last power button event was handled by the guest.
+ *
+ * @returns VBox status code
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pfHandled Is set to true if the last power button event was handled, false otherwise.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnGetPowerButtonHandled,(PPDMIACPIPORT pInterface, bool *pfHandled));
+
+ /**
+ * Check if the guest entered the ACPI mode.
+ *
+ * @returns VBox status code
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pfEntered Is set to true if the guest entered the ACPI mode, false otherwise.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnGetGuestEnteredACPIMode,(PPDMIACPIPORT pInterface, bool *pfEntered));
+
+ /**
+ * Check if the given CPU is still locked by the guest.
+ *
+ * @returns VBox status code
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param uCpu The CPU to check for.
+ * @param pfLocked Is set to true if the CPU is still locked by the guest, false otherwise.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnGetCpuStatus,(PPDMIACPIPORT pInterface, unsigned uCpu, bool *pfLocked));
+
+ /**
+ * Send an ACPI monitor hot-plug event.
+ *
+ * @returns VBox status code
+ * @param pInterface Pointer to the interface structure containing
+ * the called function pointer.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnMonitorHotPlugEvent,(PPDMIACPIPORT pInterface));
+
+ /**
+ * Send a battery status change event.
+ *
+ * @returns VBox status code
+ * @param pInterface Pointer to the interface structure containing
+ * the called function pointer.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnBatteryStatusChangeEvent,(PPDMIACPIPORT pInterface));
+} PDMIACPIPORT;
+/** PDMIACPIPORT interface ID. */
+#define PDMIACPIPORT_IID "974cb8fb-7fda-408c-f9b4-7ff4e3b2a699"
+
+
+/** Pointer to an ACPI connector interface. */
+typedef struct PDMIACPICONNECTOR *PPDMIACPICONNECTOR;
+/**
+ * ACPI connector interface (up).
+ * Pair with PDMIACPIPORT.
+ */
+typedef struct PDMIACPICONNECTOR
+{
+ /**
+ * Get the current power source of the host system.
+ *
+ * @returns VBox status code
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param penmPowerSource Pointer to the power source result variable.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnQueryPowerSource,(PPDMIACPICONNECTOR, PPDMACPIPOWERSOURCE penmPowerSource));
+
+ /**
+ * Query the current battery status of the host system.
+ *
+ * @returns VBox status code?
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pfPresent Is set to true if battery is present, false otherwise.
+ * @param penmRemainingCapacity Pointer to the battery remaining capacity (0 - 100 or 255 for unknown).
+ * @param penmBatteryState Pointer to the battery status.
+ * @param pu32PresentRate Pointer to the present rate (0..1000 of the total capacity).
+ */
+ DECLR3CALLBACKMEMBER(int, pfnQueryBatteryStatus,(PPDMIACPICONNECTOR, bool *pfPresent, PPDMACPIBATCAPACITY penmRemainingCapacity,
+ PPDMACPIBATSTATE penmBatteryState, uint32_t *pu32PresentRate));
+} PDMIACPICONNECTOR;
+/** PDMIACPICONNECTOR interface ID. */
+#define PDMIACPICONNECTOR_IID "5f14bf8d-1edf-4e3a-a1e1-cca9fd08e359"
+
+struct VMMDevDisplayDef;
+
+/** Pointer to a VMMDevice port interface. */
+typedef struct PDMIVMMDEVPORT *PPDMIVMMDEVPORT;
+/**
+ * VMMDevice port interface (down).
+ * Pair with PDMIVMMDEVCONNECTOR.
+ */
+typedef struct PDMIVMMDEVPORT
+{
+ /**
+ * Return the current absolute mouse position in pixels
+ *
+ * @returns VBox status code
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pxAbs Pointer of result value, can be NULL
+ * @param pyAbs Pointer of result value, can be NULL
+ */
+ DECLR3CALLBACKMEMBER(int, pfnQueryAbsoluteMouse,(PPDMIVMMDEVPORT pInterface, int32_t *pxAbs, int32_t *pyAbs));
+
+ /**
+ * Set the new absolute mouse position in pixels
+ *
+ * @returns VBox status code
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param xAbs New absolute X position
+ * @param yAbs New absolute Y position
+ * @param dz New mouse wheel vertical movement offset
+ * @param dw New mouse wheel horizontal movement offset
+ * @param fButtons New buttons state
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSetAbsoluteMouse,(PPDMIVMMDEVPORT pInterface, int32_t xAbs, int32_t yAbs,
+ int32_t dz, int32_t dw, uint32_t fButtons));
+
+ /**
+ * Return the current mouse capability flags
+ *
+ * @returns VBox status code
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pfCapabilities Pointer of result value
+ */
+ DECLR3CALLBACKMEMBER(int, pfnQueryMouseCapabilities,(PPDMIVMMDEVPORT pInterface, uint32_t *pfCapabilities));
+
+ /**
+ * Set the current mouse capability flag (host side)
+ *
+ * @returns VBox status code
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param fCapsAdded Mask of capabilities to add to the flag
+ * @param fCapsRemoved Mask of capabilities to remove from the flag
+ */
+ DECLR3CALLBACKMEMBER(int, pfnUpdateMouseCapabilities,(PPDMIVMMDEVPORT pInterface, uint32_t fCapsAdded, uint32_t fCapsRemoved));
+
+ /**
+ * Issue a display resolution change request.
+ *
+ * Note that there can only one request in the queue and that in case the guest does
+ * not process it, issuing another request will overwrite the previous.
+ *
+ * @returns VBox status code
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param cDisplays Number of displays. Can be either 1 or the number of VM virtual monitors.
+ * @param paDisplays Definitions of guest screens to be applied. See VMMDev.h
+ * @param fForce Whether to deliver the request to the guest even if the guest has
+ * the requested resolution already.
+ * @param fMayNotify Whether to send a hotplug notification to the guest if appropriate.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnRequestDisplayChange,(PPDMIVMMDEVPORT pInterface, uint32_t cDisplays,
+ struct VMMDevDisplayDef const *paDisplays, bool fForce, bool fMayNotify));
+
+ /**
+ * Pass credentials to guest.
+ *
+ * Note that there can only be one set of credentials and the guest may or may not
+ * query them and may do whatever it wants with them.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pszUsername User name, may be empty (UTF-8).
+ * @param pszPassword Password, may be empty (UTF-8).
+ * @param pszDomain Domain name, may be empty (UTF-8).
+ * @param fFlags VMMDEV_SETCREDENTIALS_*.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSetCredentials,(PPDMIVMMDEVPORT pInterface, const char *pszUsername,
+ const char *pszPassword, const char *pszDomain,
+ uint32_t fFlags));
+
+ /**
+ * Notify the driver about a VBVA status change.
+ *
+ * @returns Nothing. Because it is informational callback.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param fEnabled Current VBVA status.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnVBVAChange, (PPDMIVMMDEVPORT pInterface, bool fEnabled));
+
+ /**
+ * Issue a seamless mode change request.
+ *
+ * Note that there can only one request in the queue and that in case the guest does
+ * not process it, issuing another request will overwrite the previous.
+ *
+ * @returns VBox status code
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param fEnabled Seamless mode enabled or not
+ */
+ DECLR3CALLBACKMEMBER(int, pfnRequestSeamlessChange,(PPDMIVMMDEVPORT pInterface, bool fEnabled));
+
+ /**
+ * Issue a memory balloon change request.
+ *
+ * Note that there can only one request in the queue and that in case the guest does
+ * not process it, issuing another request will overwrite the previous.
+ *
+ * @returns VBox status code
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param cMbBalloon Balloon size in megabytes
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSetMemoryBalloon,(PPDMIVMMDEVPORT pInterface, uint32_t cMbBalloon));
+
+ /**
+ * Issue a statistcs interval change request.
+ *
+ * Note that there can only one request in the queue and that in case the guest does
+ * not process it, issuing another request will overwrite the previous.
+ *
+ * @returns VBox status code
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param cSecsStatInterval Statistics query interval in seconds
+ * (0=disable).
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSetStatisticsInterval,(PPDMIVMMDEVPORT pInterface, uint32_t cSecsStatInterval));
+
+ /**
+ * Notify the guest about a VRDP status change.
+ *
+ * @returns VBox status code
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param fVRDPEnabled Current VRDP status.
+ * @param uVRDPExperienceLevel Which visual effects to be disabled in
+ * the guest.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnVRDPChange, (PPDMIVMMDEVPORT pInterface, bool fVRDPEnabled, uint32_t uVRDPExperienceLevel));
+
+ /**
+ * Notify the guest of CPU hot-unplug event.
+ *
+ * @returns VBox status code
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param idCpuCore The core id of the CPU to remove.
+ * @param idCpuPackage The package id of the CPU to remove.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnCpuHotUnplug, (PPDMIVMMDEVPORT pInterface, uint32_t idCpuCore, uint32_t idCpuPackage));
+
+ /**
+ * Notify the guest of CPU hot-plug event.
+ *
+ * @returns VBox status code
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param idCpuCore The core id of the CPU to add.
+ * @param idCpuPackage The package id of the CPU to add.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnCpuHotPlug, (PPDMIVMMDEVPORT pInterface, uint32_t idCpuCore, uint32_t idCpuPackage));
+
+} PDMIVMMDEVPORT;
+/** PDMIVMMDEVPORT interface ID. */
+#define PDMIVMMDEVPORT_IID "9e004f1a-875d-11e9-a673-c77c30f53623"
+
+
+/** Pointer to a HPET legacy notification interface. */
+typedef struct PDMIHPETLEGACYNOTIFY *PPDMIHPETLEGACYNOTIFY;
+/**
+ * HPET legacy notification interface.
+ */
+typedef struct PDMIHPETLEGACYNOTIFY
+{
+ /**
+ * Notify about change of HPET legacy mode.
+ *
+ * @param pInterface Pointer to the interface structure containing the
+ * called function pointer.
+ * @param fActivated If HPET legacy mode is activated (@c true) or
+ * deactivated (@c false).
+ */
+ DECLR3CALLBACKMEMBER(void, pfnModeChanged,(PPDMIHPETLEGACYNOTIFY pInterface, bool fActivated));
+} PDMIHPETLEGACYNOTIFY;
+/** PDMIHPETLEGACYNOTIFY interface ID. */
+#define PDMIHPETLEGACYNOTIFY_IID "c9ada595-4b65-4311-8b21-b10498997774"
+
+
+/** @name Flags for PDMIVMMDEVPORT::pfnSetCredentials.
+ * @{ */
+/** The guest should perform a logon with the credentials. */
+#define VMMDEV_SETCREDENTIALS_GUESTLOGON RT_BIT(0)
+/** The guest should prevent local logons. */
+#define VMMDEV_SETCREDENTIALS_NOLOCALLOGON RT_BIT(1)
+/** The guest should verify the credentials. */
+#define VMMDEV_SETCREDENTIALS_JUDGE RT_BIT(15)
+/** @} */
+
+/** Forward declaration of the guest information structure. */
+struct VBoxGuestInfo;
+/** Forward declaration of the guest information-2 structure. */
+struct VBoxGuestInfo2;
+/** Forward declaration of the guest statistics structure */
+struct VBoxGuestStatistics;
+/** Forward declaration of the guest status structure */
+struct VBoxGuestStatus;
+
+/** Forward declaration of the video accelerator command memory. */
+struct VBVAMEMORY;
+/** Pointer to video accelerator command memory. */
+typedef struct VBVAMEMORY *PVBVAMEMORY;
+
+/** Pointer to a VMMDev connector interface. */
+typedef struct PDMIVMMDEVCONNECTOR *PPDMIVMMDEVCONNECTOR;
+/**
+ * VMMDev connector interface (up).
+ * Pair with PDMIVMMDEVPORT.
+ */
+typedef struct PDMIVMMDEVCONNECTOR
+{
+ /**
+ * Update guest facility status.
+ *
+ * Called in response to VMMDevReq_ReportGuestStatus, reset or state restore.
+ *
+ * @param pInterface Pointer to this interface.
+ * @param uFacility The facility.
+ * @param uStatus The status.
+ * @param fFlags Flags assoicated with the update. Currently
+ * reserved and should be ignored.
+ * @param pTimeSpecTS Pointer to the timestamp of this report.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnUpdateGuestStatus,(PPDMIVMMDEVCONNECTOR pInterface, uint32_t uFacility, uint16_t uStatus,
+ uint32_t fFlags, PCRTTIMESPEC pTimeSpecTS));
+
+ /**
+ * Updates a guest user state.
+ *
+ * Called in response to VMMDevReq_ReportGuestUserState.
+ *
+ * @param pInterface Pointer to this interface.
+ * @param pszUser Guest user name to update status for.
+ * @param pszDomain Domain the guest user is bound to. Optional.
+ * @param uState New guest user state to notify host about.
+ * @param pabDetails Pointer to optional state data.
+ * @param cbDetails Size (in bytes) of optional state data.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnUpdateGuestUserState,(PPDMIVMMDEVCONNECTOR pInterface, const char *pszUser,
+ const char *pszDomain, uint32_t uState,
+ const uint8_t *pabDetails, uint32_t cbDetails));
+
+ /**
+ * Reports the guest API and OS version.
+ * Called whenever the Additions issue a guest info report request.
+ *
+ * @param pInterface Pointer to this interface.
+ * @param pGuestInfo Pointer to guest information structure
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnUpdateGuestInfo,(PPDMIVMMDEVCONNECTOR pInterface, const struct VBoxGuestInfo *pGuestInfo));
+
+ /**
+ * Reports the detailed Guest Additions version.
+ *
+ * @param pInterface Pointer to this interface.
+ * @param uFullVersion The guest additions version as a full version.
+ * Use VBOX_FULL_VERSION_GET_MAJOR,
+ * VBOX_FULL_VERSION_GET_MINOR and
+ * VBOX_FULL_VERSION_GET_BUILD to access it.
+ * (This will not be zero, so turn down the
+ * paranoia level a notch.)
+ * @param pszName Pointer to the sanitized version name. This can
+ * be empty, but will not be NULL. If not empty,
+ * it will contain a build type tag and/or a
+ * publisher tag. If both, then they are separated
+ * by an underscore (VBOX_VERSION_STRING fashion).
+ * @param uRevision The SVN revision. Can be 0.
+ * @param fFeatures Feature mask, currently none are defined.
+ *
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnUpdateGuestInfo2,(PPDMIVMMDEVCONNECTOR pInterface, uint32_t uFullVersion,
+ const char *pszName, uint32_t uRevision, uint32_t fFeatures));
+
+ /**
+ * Update the guest additions capabilities.
+ * This is called when the guest additions capabilities change. The new capabilities
+ * are given and the connector should update its internal state.
+ *
+ * @param pInterface Pointer to this interface.
+ * @param newCapabilities New capabilities.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnUpdateGuestCapabilities,(PPDMIVMMDEVCONNECTOR pInterface, uint32_t newCapabilities));
+
+ /**
+ * Update the mouse capabilities.
+ * This is called when the mouse capabilities change. The new capabilities
+ * are given and the connector should update its internal state.
+ *
+ * @param pInterface Pointer to this interface.
+ * @param newCapabilities New capabilities.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnUpdateMouseCapabilities,(PPDMIVMMDEVCONNECTOR pInterface, uint32_t newCapabilities));
+
+ /**
+ * Update the pointer shape.
+ * This is called when the mouse pointer shape changes. The new shape
+ * is passed as a caller allocated buffer that will be freed after returning
+ *
+ * @param pInterface Pointer to this interface.
+ * @param fVisible Visibility indicator (if false, the other parameters are undefined).
+ * @param fAlpha Flag whether alpha channel is being passed.
+ * @param xHot Pointer hot spot x coordinate.
+ * @param yHot Pointer hot spot y coordinate.
+ * @param x Pointer new x coordinate on screen.
+ * @param y Pointer new y coordinate on screen.
+ * @param cx Pointer width in pixels.
+ * @param cy Pointer height in pixels.
+ * @param cbScanline Size of one scanline in bytes.
+ * @param pvShape New shape buffer.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnUpdatePointerShape,(PPDMIVMMDEVCONNECTOR pInterface, bool fVisible, bool fAlpha,
+ uint32_t xHot, uint32_t yHot,
+ uint32_t cx, uint32_t cy,
+ void *pvShape));
+
+ /**
+ * Enable or disable video acceleration on behalf of guest.
+ *
+ * @param pInterface Pointer to this interface.
+ * @param fEnable Whether to enable acceleration.
+ * @param pVbvaMemory Video accelerator memory.
+
+ * @return VBox rc. VINF_SUCCESS if VBVA was enabled.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnVideoAccelEnable,(PPDMIVMMDEVCONNECTOR pInterface, bool fEnable, PVBVAMEMORY pVbvaMemory));
+
+ /**
+ * Force video queue processing.
+ *
+ * @param pInterface Pointer to this interface.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnVideoAccelFlush,(PPDMIVMMDEVCONNECTOR pInterface));
+
+ /**
+ * Return whether the given video mode is supported/wanted by the host.
+ *
+ * @returns VBox status code
+ * @param pInterface Pointer to this interface.
+ * @param display The guest monitor, 0 for primary.
+ * @param cy Video mode horizontal resolution in pixels.
+ * @param cx Video mode vertical resolution in pixels.
+ * @param cBits Video mode bits per pixel.
+ * @param pfSupported Where to put the indicator for whether this mode is supported. (output)
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnVideoModeSupported,(PPDMIVMMDEVCONNECTOR pInterface, uint32_t display, uint32_t cx, uint32_t cy, uint32_t cBits, bool *pfSupported));
+
+ /**
+ * Queries by how many pixels the height should be reduced when calculating video modes
+ *
+ * @returns VBox status code
+ * @param pInterface Pointer to this interface.
+ * @param pcyReduction Pointer to the result value.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnGetHeightReduction,(PPDMIVMMDEVCONNECTOR pInterface, uint32_t *pcyReduction));
+
+ /**
+ * Informs about a credentials judgement result from the guest.
+ *
+ * @returns VBox status code
+ * @param pInterface Pointer to this interface.
+ * @param fFlags Judgement result flags.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSetCredentialsJudgementResult,(PPDMIVMMDEVCONNECTOR pInterface, uint32_t fFlags));
+
+ /**
+ * Set the visible region of the display
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to this interface.
+ * @param cRect Number of rectangles in pRect
+ * @param pRect Rectangle array
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSetVisibleRegion,(PPDMIVMMDEVCONNECTOR pInterface, uint32_t cRect, PRTRECT pRect));
+
+ /**
+ * Update monitor positions (offsets).
+ *
+ * Passing monitor positions from the guest to host exclusively since vmwgfx
+ * (linux driver) fails to do so thru the FIFO.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to this interface.
+ * @param cPositions Number of monitor positions
+ * @param paPositions Positions array
+ * @remarks Is allowed to be NULL.
+ * @thread The emulation thread.
+ * @sa PDMIDISPLAYPORT::pfnReportMonitorPositions
+ */
+ DECLR3CALLBACKMEMBER(int, pfnUpdateMonitorPositions,(PPDMIVMMDEVCONNECTOR pInterface,
+ uint32_t cPositions, PCRTPOINT paPositions));
+
+ /**
+ * Query the visible region of the display
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to this interface.
+ * @param pcRects Where to return the number of rectangles in
+ * paRects.
+ * @param paRects Rectangle array (set to NULL to query the number
+ * of rectangles)
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnQueryVisibleRegion,(PPDMIVMMDEVCONNECTOR pInterface, uint32_t *pcRects, PRTRECT paRects));
+
+ /**
+ * Request the statistics interval
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to this interface.
+ * @param pulInterval Pointer to interval in seconds
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnQueryStatisticsInterval,(PPDMIVMMDEVCONNECTOR pInterface, uint32_t *pulInterval));
+
+ /**
+ * Report new guest statistics
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to this interface.
+ * @param pGuestStats Guest statistics
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnReportStatistics,(PPDMIVMMDEVCONNECTOR pInterface, struct VBoxGuestStatistics *pGuestStats));
+
+ /**
+ * Query the current balloon size
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to this interface.
+ * @param pcbBalloon Balloon size
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnQueryBalloonSize,(PPDMIVMMDEVCONNECTOR pInterface, uint32_t *pcbBalloon));
+
+ /**
+ * Query the current page fusion setting
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to this interface.
+ * @param pfPageFusionEnabled Pointer to boolean
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnIsPageFusionEnabled,(PPDMIVMMDEVCONNECTOR pInterface, bool *pfPageFusionEnabled));
+
+} PDMIVMMDEVCONNECTOR;
+/** PDMIVMMDEVCONNECTOR interface ID. */
+#define PDMIVMMDEVCONNECTOR_IID "aff90240-a443-434e-9132-80c186ab97d4"
+
+
+/**
+ * Generic status LED core.
+ * Note that a unit doesn't have to support all the indicators.
+ */
+typedef union PDMLEDCORE
+{
+ /** 32-bit view. */
+ uint32_t volatile u32;
+ /** Bit view. */
+ struct
+ {
+ /** Reading/Receiving indicator. */
+ uint32_t fReading : 1;
+ /** Writing/Sending indicator. */
+ uint32_t fWriting : 1;
+ /** Busy indicator. */
+ uint32_t fBusy : 1;
+ /** Error indicator. */
+ uint32_t fError : 1;
+ } s;
+} PDMLEDCORE;
+
+/** LED bit masks for the u32 view.
+ * @{ */
+/** Reading/Receiving indicator. */
+#define PDMLED_READING RT_BIT(0)
+/** Writing/Sending indicator. */
+#define PDMLED_WRITING RT_BIT(1)
+/** Busy indicator. */
+#define PDMLED_BUSY RT_BIT(2)
+/** Error indicator. */
+#define PDMLED_ERROR RT_BIT(3)
+/** @} */
+
+
+/**
+ * Generic status LED.
+ * Note that a unit doesn't have to support all the indicators.
+ */
+typedef struct PDMLED
+{
+ /** Just a magic for sanity checking. */
+ uint32_t u32Magic;
+ uint32_t u32Alignment; /**< structure size alignment. */
+ /** The actual LED status.
+ * Only the device is allowed to change this. */
+ PDMLEDCORE Actual;
+ /** The asserted LED status which is cleared by the reader.
+ * The device will assert the bits but never clear them.
+ * The driver clears them as it sees fit. */
+ PDMLEDCORE Asserted;
+} PDMLED;
+
+/** Pointer to an LED. */
+typedef PDMLED *PPDMLED;
+/** Pointer to a const LED. */
+typedef const PDMLED *PCPDMLED;
+
+/** Magic value for PDMLED::u32Magic. */
+#define PDMLED_MAGIC UINT32_C(0x11335577)
+
+/** Pointer to an LED ports interface. */
+typedef struct PDMILEDPORTS *PPDMILEDPORTS;
+/**
+ * Interface for exporting LEDs (down).
+ * Pair with PDMILEDCONNECTORS.
+ */
+typedef struct PDMILEDPORTS
+{
+ /**
+ * Gets the pointer to the status LED of a unit.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param iLUN The unit which status LED we desire.
+ * @param ppLed Where to store the LED pointer.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnQueryStatusLed,(PPDMILEDPORTS pInterface, unsigned iLUN, PPDMLED *ppLed));
+
+} PDMILEDPORTS;
+/** PDMILEDPORTS interface ID. */
+#define PDMILEDPORTS_IID "435e0cec-8549-4ca0-8c0d-98e52f1dc038"
+
+
+/** Pointer to an LED connectors interface. */
+typedef struct PDMILEDCONNECTORS *PPDMILEDCONNECTORS;
+/**
+ * Interface for reading LEDs (up).
+ * Pair with PDMILEDPORTS.
+ */
+typedef struct PDMILEDCONNECTORS
+{
+ /**
+ * Notification about a unit which have been changed.
+ *
+ * The driver must discard any pointers to data owned by
+ * the unit and requery it.
+ *
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param iLUN The unit number.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnUnitChanged,(PPDMILEDCONNECTORS pInterface, unsigned iLUN));
+} PDMILEDCONNECTORS;
+/** PDMILEDCONNECTORS interface ID. */
+#define PDMILEDCONNECTORS_IID "8ed63568-82a7-4193-b57b-db8085ac4495"
+
+
+/** Pointer to a Media Notification interface. */
+typedef struct PDMIMEDIANOTIFY *PPDMIMEDIANOTIFY;
+/**
+ * Interface for exporting Medium eject information (up). No interface pair.
+ */
+typedef struct PDMIMEDIANOTIFY
+{
+ /**
+ * Signals that the medium was ejected.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param iLUN The unit which had the medium ejected.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnEjected,(PPDMIMEDIANOTIFY pInterface, unsigned iLUN));
+
+} PDMIMEDIANOTIFY;
+/** PDMIMEDIANOTIFY interface ID. */
+#define PDMIMEDIANOTIFY_IID "fc22d53e-feb1-4a9c-b9fb-0a990a6ab288"
+
+
+/** The special status unit number */
+#define PDM_STATUS_LUN 999
+
+
+#ifdef VBOX_WITH_HGCM
+
+/** Abstract HGCM command structure. Used only to define a typed pointer. */
+struct VBOXHGCMCMD;
+
+/** Pointer to HGCM command structure. This pointer is unique and identifies
+ * the command being processed. The pointer is passed to HGCM connector methods,
+ * and must be passed back to HGCM port when command is completed.
+ */
+typedef struct VBOXHGCMCMD *PVBOXHGCMCMD;
+
+/** Pointer to a HGCM port interface. */
+typedef struct PDMIHGCMPORT *PPDMIHGCMPORT;
+/**
+ * Host-Guest communication manager port interface (down). Normally implemented
+ * by VMMDev.
+ * Pair with PDMIHGCMCONNECTOR.
+ */
+typedef struct PDMIHGCMPORT
+{
+ /**
+ * Notify the guest on a command completion.
+ *
+ * @returns VINF_SUCCESS or VERR_CANCELLED if the guest canceled the call.
+ * @param pInterface Pointer to this interface.
+ * @param rc The return code (VBox error code).
+ * @param pCmd A pointer that identifies the completed command.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnCompleted,(PPDMIHGCMPORT pInterface, int32_t rc, PVBOXHGCMCMD pCmd));
+
+ /**
+ * Checks if @a pCmd was restored & resubmitted from saved state.
+ *
+ * @returns true if restored, false if not.
+ * @param pInterface Pointer to this interface.
+ * @param pCmd The command we're checking on.
+ */
+ DECLR3CALLBACKMEMBER(bool, pfnIsCmdRestored,(PPDMIHGCMPORT pInterface, PVBOXHGCMCMD pCmd));
+
+ /**
+ * Checks if @a pCmd was cancelled.
+ *
+ * @returns true if cancelled, false if not.
+ * @param pInterface Pointer to this interface.
+ * @param pCmd The command we're checking on.
+ */
+ DECLR3CALLBACKMEMBER(bool, pfnIsCmdCancelled,(PPDMIHGCMPORT pInterface, PVBOXHGCMCMD pCmd));
+
+ /**
+ * Gets the VMMDevRequestHeader::fRequestor value for @a pCmd.
+ *
+ * @returns The fRequestor value, VMMDEV_REQUESTOR_LEGACY if guest does not
+ * support it, VMMDEV_REQUESTOR_LOWEST if invalid parameters.
+ * @param pInterface Pointer to this interface.
+ * @param pCmd The command we're in checking on.
+ */
+ DECLR3CALLBACKMEMBER(uint32_t, pfnGetRequestor,(PPDMIHGCMPORT pInterface, PVBOXHGCMCMD pCmd));
+
+ /**
+ * Gets the VMMDevState::idSession value.
+ *
+ * @returns VMMDevState::idSession.
+ * @param pInterface Pointer to this interface.
+ */
+ DECLR3CALLBACKMEMBER(uint64_t, pfnGetVMMDevSessionId,(PPDMIHGCMPORT pInterface));
+
+} PDMIHGCMPORT;
+/** PDMIHGCMPORT interface ID. */
+# define PDMIHGCMPORT_IID "28c0a201-68cd-4752-9404-bb42a0c09eb7"
+
+/* forward decl to hgvmsvc.h. */
+struct VBOXHGCMSVCPARM;
+/** Pointer to a HGCM service location structure. */
+typedef struct HGCMSERVICELOCATION *PHGCMSERVICELOCATION;
+/** Pointer to a HGCM connector interface. */
+typedef struct PDMIHGCMCONNECTOR *PPDMIHGCMCONNECTOR;
+/**
+ * The Host-Guest communication manager connector interface (up). Normally
+ * implemented by Main::VMMDevInterface.
+ * Pair with PDMIHGCMPORT.
+ */
+typedef struct PDMIHGCMCONNECTOR
+{
+ /**
+ * Locate a service and inform it about a client connection.
+ *
+ * @param pInterface Pointer to this interface.
+ * @param pCmd A pointer that identifies the command.
+ * @param pServiceLocation Pointer to the service location structure.
+ * @param pu32ClientID Where to store the client id for the connection.
+ * @return VBox status code.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnConnect,(PPDMIHGCMCONNECTOR pInterface, PVBOXHGCMCMD pCmd, PHGCMSERVICELOCATION pServiceLocation, uint32_t *pu32ClientID));
+
+ /**
+ * Disconnect from service.
+ *
+ * @param pInterface Pointer to this interface.
+ * @param pCmd A pointer that identifies the command.
+ * @param u32ClientID The client id returned by the pfnConnect call.
+ * @return VBox status code.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnDisconnect,(PPDMIHGCMCONNECTOR pInterface, PVBOXHGCMCMD pCmd, uint32_t u32ClientID));
+
+ /**
+ * Process a guest issued command.
+ *
+ * @param pInterface Pointer to this interface.
+ * @param pCmd A pointer that identifies the command.
+ * @param u32ClientID The client id returned by the pfnConnect call.
+ * @param u32Function Function to be performed by the service.
+ * @param cParms Number of parameters in the array pointed to by paParams.
+ * @param paParms Pointer to an array of parameters.
+ * @param tsArrival The STAM_GET_TS() value when the request arrived.
+ * @return VBox status code.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnCall,(PPDMIHGCMCONNECTOR pInterface, PVBOXHGCMCMD pCmd, uint32_t u32ClientID, uint32_t u32Function,
+ uint32_t cParms, struct VBOXHGCMSVCPARM *paParms, uint64_t tsArrival));
+
+ /**
+ * Notification about the guest cancelling a pending request.
+ * @param pInterface Pointer to this interface.
+ * @param pCmd A pointer that identifies the command.
+ * @param idclient The client id returned by the pfnConnect call.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnCancelled,(PPDMIHGCMCONNECTOR pInterface, PVBOXHGCMCMD pCmd, uint32_t idClient));
+
+} PDMIHGCMCONNECTOR;
+/** PDMIHGCMCONNECTOR interface ID. */
+# define PDMIHGCMCONNECTOR_IID "33cb5c91-6a4a-4ad9-3fec-d1f7d413c4a5"
+
+#endif /* VBOX_WITH_HGCM */
+
+
+/** Pointer to a display VBVA callbacks interface. */
+typedef struct PDMIDISPLAYVBVACALLBACKS *PPDMIDISPLAYVBVACALLBACKS;
+/**
+ * Display VBVA callbacks interface (up).
+ */
+typedef struct PDMIDISPLAYVBVACALLBACKS
+{
+
+ /**
+ * Informs guest about completion of processing the given Video HW Acceleration
+ * command, does not wait for the guest to process the command.
+ *
+ * @returns ???
+ * @param pInterface Pointer to this interface.
+ * @param pCmd The Video HW Acceleration Command that was
+ * completed.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnVHWACommandCompleteAsync,(PPDMIDISPLAYVBVACALLBACKS pInterface,
+ VBOXVHWACMD RT_UNTRUSTED_VOLATILE_GUEST *pCmd));
+} PDMIDISPLAYVBVACALLBACKS;
+/** PDMIDISPLAYVBVACALLBACKS */
+#define PDMIDISPLAYVBVACALLBACKS_IID "37f34c9c-0491-47dc-a0b3-81697c44a416"
+
+/** Pointer to a PCI raw connector interface. */
+typedef struct PDMIPCIRAWCONNECTOR *PPDMIPCIRAWCONNECTOR;
+/**
+ * PCI raw connector interface (up).
+ */
+typedef struct PDMIPCIRAWCONNECTOR
+{
+
+ /**
+ *
+ */
+ DECLR3CALLBACKMEMBER(int, pfnDeviceConstructComplete, (PPDMIPCIRAWCONNECTOR pInterface, const char *pcszName,
+ uint32_t uHostPciAddress, uint32_t uGuestPciAddress,
+ int rc));
+
+} PDMIPCIRAWCONNECTOR;
+/** PDMIPCIRAWCONNECTOR interface ID. */
+#define PDMIPCIRAWCONNECTOR_IID "14aa9c6c-8869-4782-9dfc-910071a6aebf"
+
+
+/** Pointer to a VFS connector interface. */
+typedef struct PDMIVFSCONNECTOR *PPDMIVFSCONNECTOR;
+/**
+ * VFS connector interface (up).
+ */
+typedef struct PDMIVFSCONNECTOR
+{
+ /**
+ * Queries the size of the given path.
+ *
+ * @returns VBox status code.
+ * @retval VERR_NOT_FOUND if the path is not available.
+ * @param pInterface Pointer to this interface.
+ * @param pszNamespace The namespace for the path (usually driver/device name) or NULL for default namespace.
+ * @param pszPath The path to query the size for.
+ * @param pcb Where to store the size of the path in bytes on success.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnQuerySize, (PPDMIVFSCONNECTOR pInterface, const char *pszNamespace, const char *pszPath,
+ uint64_t *pcb));
+
+ /**
+ * Reads everything from the given path and stores the data into the supplied buffer.
+ *
+ * @returns VBox status code.
+ * @retval VERR_NOT_FOUND if the path is not available.
+ * @retval VERR_BUFFER_OVERFLOW if the supplied buffer is too small to read everything.
+ * @retval VINF_BUFFER_UNDERFLOW if the supplied buffer is too large.
+ * @param pInterface Pointer to this interface.
+ * @param pszNamespace The namespace for the path (usually driver/device name) or NULL for default namespace.
+ * @param pszPath The path to read everything for.
+ * @param pvBuf Where to store the data.
+ * @param cbRead How much to read.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnReadAll, (PPDMIVFSCONNECTOR pInterface, const char *pszNamespace, const char *pszPath,
+ void *pvBuf, size_t cbRead));
+
+ /**
+ * Writes the supplied data to the given path, overwriting any previously existing data.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to this interface.
+ * @param pszNamespace The namespace for the path (usually driver/device name) or NULL for default namespace.
+ * @param pszPath The path to write everything to.
+ * @param pvBuf The data to store.
+ * @param cbWrite How many bytes to write.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnWriteAll, (PPDMIVFSCONNECTOR pInterface, const char *pszNamespace, const char *pszPath,
+ const void *pvBuf, size_t cbWrite));
+
+ /**
+ * Deletes the given path.
+ *
+ * @returns VBox status code.
+ * @retval VERR_NOT_FOUND if the path is not available.
+ * @param pszNamespace The namespace for the path (usually driver/device name) or NULL for default namespace.
+ * @param pszPath The path to delete.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnDelete, (PPDMIVFSCONNECTOR pInterface, const char *pszNamespace, const char *pszPath));
+
+ /** @todo Add standard open/read/write/close callbacks when the need arises. */
+
+} PDMIVFSCONNECTOR;
+/** PDMIVFSCONNECTOR interface ID. */
+#define PDMIVFSCONNECTOR_IID "a1fc51e0-414a-4e78-8388-8053b9dc6521"
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !VBOX_INCLUDED_vmm_pdmifs_h */
diff --git a/include/VBox/vmm/pdmins.h b/include/VBox/vmm/pdmins.h
new file mode 100644
index 00000000..9e50b723
--- /dev/null
+++ b/include/VBox/vmm/pdmins.h
@@ -0,0 +1,99 @@
+/** @file
+ * PDM - Pluggable Device Manager, Common Instance Macros.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vmm_pdmins_h
+#define VBOX_INCLUDED_vmm_pdmins_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+
+/** @defgroup grp_pdm_ins Common PDM Instance Macros
+ * @ingroup grp_pdm
+ * @{
+ */
+
+/** @def PDMBOTHCBDECL
+ * Macro for declaring a callback which is static in HC and exported in GC.
+ */
+#if defined(IN_RC) || defined(IN_RING0)
+# ifdef __cplusplus
+# define PDMBOTHCBDECL(type) extern "C" DECLEXPORT(type)
+# else
+# define PDMBOTHCBDECL(type) DECLEXPORT(type)
+# endif
+#else
+# define PDMBOTHCBDECL(type) static DECLCALLBACK(type)
+#endif
+
+/** @def PDMINS_2_DATA
+ * Gets the shared instance data for a PDM device, USB device, or driver instance.
+ * @note For devices using PDMDEVINS_2_DATA is highly recommended.
+ */
+#define PDMINS_2_DATA(pIns, type) ( (type)(pIns)->CTX_SUFF(pvInstanceData) )
+
+/** @def PDMINS_2_DATA_CC
+ * Gets the current context instance data for a PDM device, USB device, or driver instance.
+ * @note For devices using PDMDEVINS_2_DATA_CC is highly recommended.
+ */
+#define PDMINS_2_DATA_CC(pIns, type) ( (type)(void *)&(pIns)->achInstanceData[0] )
+
+/* @def PDMINS_2_DATA_RC
+ * Gets the raw-mode context instance data for a PDM device instance.
+ */
+#define PDMINS_2_DATA_RC(pIns, type) ( (type)(pIns)->CTX_SUFF(pvInstanceDataForRC) )
+
+
+/** @def PDMINS_2_DATA_RCPTR
+ * Converts a PDM Device, USB Device, or Driver instance pointer to a RC pointer to the instance data.
+ * @deprecated
+ */
+#define PDMINS_2_DATA_RCPTR(pIns) ( (pIns)->pvInstanceDataRC )
+
+/** @def PDMINS_2_DATA_R3PTR
+ * Converts a PDM Device, USB Device, or Driver instance pointer to a HC pointer to the instance data.
+ * @deprecated
+ */
+#define PDMINS_2_DATA_R3PTR(pIns) ( (pIns)->pvInstanceDataR3 )
+
+/** @def PDMINS_2_DATA_R0PTR
+ * Converts a PDM Device, USB Device, or Driver instance pointer to a R0 pointer to the instance data.
+ * @deprecated
+ */
+#define PDMINS_2_DATA_R0PTR(pIns) ( (pIns)->pvInstanceDataR0 )
+
+/** @} */
+
+#endif /* !VBOX_INCLUDED_vmm_pdmins_h */
diff --git a/include/VBox/vmm/pdmnetifs.h b/include/VBox/vmm/pdmnetifs.h
new file mode 100644
index 00000000..49e93cb5
--- /dev/null
+++ b/include/VBox/vmm/pdmnetifs.h
@@ -0,0 +1,456 @@
+/** @file
+ * PDM - Pluggable Device Manager, Network Interfaces.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vmm_pdmnetifs_h
+#define VBOX_INCLUDED_vmm_pdmnetifs_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/types.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_pdm_ifs_net PDM Network Interfaces
+ * @ingroup grp_pdm_interfaces
+ * @{
+ */
+
+
+/**
+ * PDM scatter/gather buffer.
+ *
+ * @todo Promote this to VBox/types.h, VBox/vmm/pdmcommon.h or some such place.
+ */
+typedef struct PDMSCATTERGATHER
+{
+ /** Flags. */
+ size_t fFlags;
+ /** The number of bytes used.
+ * This is cleared on alloc and set by the user. */
+ size_t cbUsed;
+ /** The number of bytes available.
+ * This is set on alloc and not changed by the user. */
+ size_t cbAvailable;
+ /** Private data member for the allocator side. */
+ void *pvAllocator;
+ /** Private data member for the user side. */
+ void *pvUser;
+ /** The number of segments
+ * This is set on alloc and not changed by the user. */
+ size_t cSegs;
+ /** Variable sized array of segments. */
+ PDMDATASEG aSegs[1];
+} PDMSCATTERGATHER;
+/** Pointer to a PDM scatter/gather buffer. */
+typedef PDMSCATTERGATHER *PPDMSCATTERGATHER;
+/** Pointer to a PDM scatter/gather buffer pointer. */
+typedef PPDMSCATTERGATHER *PPPDMSCATTERGATHER;
+
+
+/** @name PDMSCATTERGATHER::fFlags
+ * @{ */
+/** Magic value. */
+#define PDMSCATTERGATHER_FLAGS_MAGIC UINT32_C(0xb1b10000)
+/** Magic mask. */
+#define PDMSCATTERGATHER_FLAGS_MAGIC_MASK UINT32_C(0xffff0000)
+/** Owned by owner number 1. */
+#define PDMSCATTERGATHER_FLAGS_OWNER_1 UINT32_C(0x00000001)
+/** Owned by owner number 2. */
+#define PDMSCATTERGATHER_FLAGS_OWNER_2 UINT32_C(0x00000002)
+/** Owned by owner number 3. */
+#define PDMSCATTERGATHER_FLAGS_OWNER_3 UINT32_C(0x00000002)
+/** Owner mask. */
+#define PDMSCATTERGATHER_FLAGS_OWNER_MASK UINT32_C(0x00000003)
+/** Mask of flags available to general use.
+ * The parties using the SG must all agree upon how to use these of course. */
+#define PDMSCATTERGATHER_FLAGS_AVL_MASK UINT32_C(0x0000f000)
+/** Flags reserved for future use, MBZ. */
+#define PDMSCATTERGATHER_FLAGS_RVD_MASK UINT32_C(0x00000ff8)
+/** @} */
+
+
+/**
+ * Sets the owner of a scatter/gather buffer.
+ *
+ * @param pSgBuf .
+ * @param uNewOwner The new owner.
+ */
+DECLINLINE(void) PDMScatterGatherSetOwner(PPDMSCATTERGATHER pSgBuf, uint32_t uNewOwner)
+{
+ pSgBuf->fFlags = (pSgBuf->fFlags & ~PDMSCATTERGATHER_FLAGS_OWNER_MASK) | uNewOwner;
+}
+
+
+
+/** Pointer to a network port interface */
+typedef struct PDMINETWORKDOWN *PPDMINETWORKDOWN;
+/**
+ * Network port interface (down).
+ * Pair with PDMINETWORKUP.
+ */
+typedef struct PDMINETWORKDOWN
+{
+ /**
+ * Wait until there is space for receiving data. We do not care how much space is available
+ * because pfnReceive() will re-check and notify the guest if necessary.
+ *
+ * This function must be called before the pfnRecieve() method is called.
+ *
+ * @returns VBox status code. VINF_SUCCESS means there is at least one receive descriptor available.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param cMillies Number of milliseconds to wait. 0 means return immediately.
+ *
+ * @thread Non-EMT.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnWaitReceiveAvail,(PPDMINETWORKDOWN pInterface, RTMSINTERVAL cMillies));
+
+ /**
+ * Receive data from the network.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pvBuf The available data.
+ * @param cb Number of bytes available in the buffer.
+ *
+ * @thread Non-EMT.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnReceive,(PPDMINETWORKDOWN pInterface, const void *pvBuf, size_t cb));
+
+ /**
+ * Receive data with segmentation context from the network.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pvBuf The available data.
+ * @param cb Number of bytes available in the buffer.
+ * @param pGso Segmentation context.
+ *
+ * @thread Non-EMT.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnReceiveGso,(PPDMINETWORKDOWN pInterface, const void *pvBuf, size_t cb, PCPDMNETWORKGSO pGso));
+
+ /**
+ * Do pending transmit work on the leaf driver's XMIT thread.
+ *
+ * When a PDMINETWORKUP::pfnBeginTransmit or PDMINETWORKUP::pfnAllocBuf call
+ * fails with VERR_TRY_AGAIN, the leaf drivers XMIT thread will offer to process
+ * the upstream device/driver when the the VERR_TRY_AGAIN condition has been
+ * removed. In some cases the VERR_TRY_AGAIN condition is simply being in an
+ * inconvenient context and the XMIT thread will start working ASAP.
+ *
+ * @param pInterface Pointer to this interface.
+ * @thread Non-EMT.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnXmitPending,(PPDMINETWORKDOWN pInterface));
+
+} PDMINETWORKDOWN;
+/** PDMINETWORKDOWN interface ID. */
+#define PDMINETWORKDOWN_IID "52b8cdbb-a087-493b-baa7-81ec3b803e06"
+
+
+/**
+ * Network link state.
+ */
+typedef enum PDMNETWORKLINKSTATE
+{
+ /** Invalid state. */
+ PDMNETWORKLINKSTATE_INVALID = 0,
+ /** The link is up. */
+ PDMNETWORKLINKSTATE_UP,
+ /** The link is down. */
+ PDMNETWORKLINKSTATE_DOWN,
+ /** The link is temporarily down while resuming. */
+ PDMNETWORKLINKSTATE_DOWN_RESUME
+} PDMNETWORKLINKSTATE;
+
+
+/** Pointer to a network connector interface */
+typedef R3PTRTYPE(struct PDMINETWORKUP *) PPDMINETWORKUPR3;
+/** Pointer to a network connector interface, ring-0 context. */
+typedef R0PTRTYPE(struct PDMINETWORKUPR0 *) PPDMINETWORKUPR0;
+/** Pointer to a network connector interface, raw-mode context. */
+typedef RCPTRTYPE(struct PDMINETWORKUPRC *) PPDMINETWORKUPRC;
+/** Pointer to a current context network connector interface. */
+typedef CTX_SUFF(PPDMINETWORKUP) PPDMINETWORKUP;
+
+/**
+ * Network connector interface (up).
+ * Pair with PDMINETWORKDOWN.
+ */
+typedef struct PDMINETWORKUP
+{
+ /**
+ * Begins a transmit session.
+ *
+ * The leaf driver guarantees that there are no concurrent sessions.
+ *
+ * @retval VINF_SUCCESS on success. Must always call
+ * PDMINETWORKUP::pfnEndXmit.
+ * @retval VERR_TRY_AGAIN if there is already an open transmit session or some
+ * important resource was unavailable (like buffer space). If it's a
+ * resources issue, the driver will signal its XMIT thread and have it
+ * work the device thru the PDMINETWORKDOWN::pfnNotifyBufAvailable
+ * callback method.
+ *
+ * @param pInterface Pointer to the interface structure containing the
+ * called function pointer.
+ * @param fOnWorkerThread Set if we're being called on a work thread. Clear
+ * if an EMT.
+ *
+ * @thread Any, but normally EMT or the XMIT thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnBeginXmit,(PPDMINETWORKUP pInterface, bool fOnWorkerThread));
+
+ /**
+ * Get a send buffer for passing to pfnSendBuf.
+ *
+ * @retval VINF_SUCCESS on success.
+ * @retval VERR_TRY_AGAIN if temporarily out of buffer space. After this
+ * happens, the driver will call PDMINETWORKDOWN::pfnNotifyBufAvailable
+ * when this is a buffer of the required size available.
+ * @retval VERR_NO_MEMORY if really out of buffer space.
+ * @retval VERR_NET_DOWN if we cannot send anything to the network at this
+ * point in time. Drop the frame with a xmit error. This is typically
+ * only seen when pausing the VM since the device keeps the link state,
+ * but there could of course be races.
+ *
+ * @param pInterface Pointer to the interface structure containing the
+ * called function pointer.
+ * @param cbMin The minimum buffer size.
+ * @param pGso Pointer to a GSO context (only reference while in
+ * this call). NULL indicates no segmentation
+ * offloading. PDMSCATTERGATHER::pvUser is used to
+ * indicate that a network SG uses GSO, usually by
+ * pointing to a copy of @a pGso.
+ * @param ppSgBuf Where to return the buffer. The buffer will be
+ * owned by the caller, designation owner number 1.
+ *
+ * @thread Any, but normally EMT or the XMIT thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnAllocBuf,(PPDMINETWORKUP pInterface, size_t cbMin, PCPDMNETWORKGSO pGso,
+ PPPDMSCATTERGATHER ppSgBuf));
+
+ /**
+ * Frees an unused buffer.
+ *
+ * @retval VINF_SUCCESS on success.
+ *
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pSgBuf A buffer from PDMINETWORKUP::pfnAllocBuf or
+ * PDMINETWORKDOWN::pfnNotifyBufAvailable. The buffer
+ * ownership shall be 1.
+ *
+ * @thread Any, but normally EMT or the XMIT thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnFreeBuf,(PPDMINETWORKUP pInterface, PPDMSCATTERGATHER pSgBuf));
+
+ /**
+ * Send data to the network.
+ *
+ * @retval VINF_SUCCESS on success.
+ * @retval VERR_NET_DOWN if the NIC is not connected to a network. pSgBuf will
+ * be freed.
+ * @retval VERR_NET_NO_BUFFER_SPACE if we're out of resources. pSgBuf will be
+ * freed.
+ *
+ * @param pInterface Pointer to the interface structure containing the
+ * called function pointer.
+ * @param pSgBuf The buffer containing the data to send. The buffer
+ * ownership shall be 1. The buffer will always be
+ * consumed, regardless of the status code.
+ *
+ * @param fOnWorkerThread Set if we're being called on a work thread. Clear
+ * if an EMT.
+ *
+ * @thread Any, but normally EMT or the XMIT thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSendBuf,(PPDMINETWORKUP pInterface, PPDMSCATTERGATHER pSgBuf, bool fOnWorkerThread));
+
+ /**
+ * Ends a transmit session.
+ *
+ * Pairs with successful PDMINETWORKUP::pfnBeginXmit calls.
+ *
+ * @param pInterface Pointer to the interface structure containing the
+ * called function pointer.
+ *
+ * @thread Any, but normally EMT or the XMIT thread.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnEndXmit,(PPDMINETWORKUP pInterface));
+
+ /**
+ * Set promiscuous mode.
+ *
+ * This is called when the promiscuous mode is set. This means that there doesn't have
+ * to be a mode change when it's called.
+ *
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param fPromiscuous Set if the adaptor is now in promiscuous mode. Clear if it is not.
+ * @thread EMT ??
+ */
+ DECLR3CALLBACKMEMBER(void, pfnSetPromiscuousMode,(PPDMINETWORKUP pInterface, bool fPromiscuous));
+
+ /**
+ * Notification on link status changes.
+ *
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param enmLinkState The new link state.
+ * @thread EMT ??
+ */
+ DECLR3CALLBACKMEMBER(void, pfnNotifyLinkChanged,(PPDMINETWORKUP pInterface, PDMNETWORKLINKSTATE enmLinkState));
+
+ /** @todo Add a callback that informs the driver chain about MAC address changes if we ever implement that. */
+
+} PDMINETWORKUP;
+
+/** Ring-0 edition of PDMINETWORKUP. */
+typedef struct PDMINETWORKUPR0
+{
+ /** @copydoc PDMINETWORKUP::pfnBeginXmit */
+ DECLR0CALLBACKMEMBER(int, pfnBeginXmit,(PPDMINETWORKUPR0 pInterface, bool fOnWorkerThread));
+ /** @copydoc PDMINETWORKUP::pfnAllocBuf */
+ DECLR0CALLBACKMEMBER(int, pfnAllocBuf,(PPDMINETWORKUPR0 pInterface, size_t cbMin, PCPDMNETWORKGSO pGso,
+ PPPDMSCATTERGATHER ppSgBuf));
+ /** @copydoc PDMINETWORKUP::pfnFreeBuf */
+ DECLR0CALLBACKMEMBER(int, pfnFreeBuf,(PPDMINETWORKUPR0 pInterface, PPDMSCATTERGATHER pSgBuf));
+ /** @copydoc PDMINETWORKUP::pfnSendBuf */
+ DECLR0CALLBACKMEMBER(int, pfnSendBuf,(PPDMINETWORKUPR0 pInterface, PPDMSCATTERGATHER pSgBuf, bool fOnWorkerThread));
+ /** @copydoc PDMINETWORKUP::pfnEndXmit */
+ DECLR0CALLBACKMEMBER(void, pfnEndXmit,(PPDMINETWORKUPR0 pInterface));
+ /** @copydoc PDMINETWORKUP::pfnSetPromiscuousMode */
+ DECLR0CALLBACKMEMBER(void, pfnSetPromiscuousMode,(PPDMINETWORKUPR0 pInterface, bool fPromiscuous));
+} PDMINETWORKUPR0;
+
+/** Raw-mode context edition of PDMINETWORKUP. */
+typedef struct PDMINETWORKUPRC
+{
+ /** @copydoc PDMINETWORKUP::pfnBeginXmit */
+ DECLRCCALLBACKMEMBER(int, pfnBeginXmit,(PPDMINETWORKUPRC pInterface, bool fOnWorkerThread));
+ /** @copydoc PDMINETWORKUP::pfnAllocBuf */
+ DECLRCCALLBACKMEMBER(int, pfnAllocBuf,(PPDMINETWORKUPRC pInterface, size_t cbMin, PCPDMNETWORKGSO pGso,
+ PPPDMSCATTERGATHER ppSgBuf));
+ /** @copydoc PDMINETWORKUP::pfnFreeBuf */
+ DECLRCCALLBACKMEMBER(int, pfnFreeBuf,(PPDMINETWORKUPRC pInterface, PPDMSCATTERGATHER pSgBuf));
+ /** @copydoc PDMINETWORKUP::pfnSendBuf */
+ DECLRCCALLBACKMEMBER(int, pfnSendBuf,(PPDMINETWORKUPRC pInterface, PPDMSCATTERGATHER pSgBuf, bool fOnWorkerThread));
+ /** @copydoc PDMINETWORKUP::pfnEndXmit */
+ DECLRCCALLBACKMEMBER(void, pfnEndXmit,(PPDMINETWORKUPRC pInterface));
+ /** @copydoc PDMINETWORKUP::pfnSetPromiscuousMode */
+ DECLRCCALLBACKMEMBER(void, pfnSetPromiscuousMode,(PPDMINETWORKUPRC pInterface, bool fPromiscuous));
+} PDMINETWORKUPRC;
+
+/** PDMINETWORKUP interface ID. */
+#define PDMINETWORKUP_IID "67e7e7a8-2594-4649-a1e3-7cee680c6083"
+/** PDMINETWORKUP interface method names. */
+#define PDMINETWORKUP_SYM_LIST "BeginXmit;AllocBuf;FreeBuf;SendBuf;EndXmit;SetPromiscuousMode"
+
+
+/** Pointer to a network config port interface */
+typedef struct PDMINETWORKCONFIG *PPDMINETWORKCONFIG;
+/**
+ * Network config port interface (main).
+ * No interface pair.
+ */
+typedef struct PDMINETWORKCONFIG
+{
+ /**
+ * Gets the current Media Access Control (MAC) address.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pMac Where to store the MAC address.
+ * @thread EMT
+ */
+ DECLR3CALLBACKMEMBER(int, pfnGetMac,(PPDMINETWORKCONFIG pInterface, PRTMAC pMac));
+
+ /**
+ * Gets the new link state.
+ *
+ * @returns The current link state.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @thread EMT
+ */
+ DECLR3CALLBACKMEMBER(PDMNETWORKLINKSTATE, pfnGetLinkState,(PPDMINETWORKCONFIG pInterface));
+
+ /**
+ * Sets the new link state.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param enmState The new link state
+ * @thread EMT
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSetLinkState,(PPDMINETWORKCONFIG pInterface, PDMNETWORKLINKSTATE enmState));
+
+} PDMINETWORKCONFIG;
+/** PDMINETWORKCONFIG interface ID. */
+#define PDMINETWORKCONFIG_IID "d6d909e8-716d-415d-b109-534e4478ff4e"
+
+
+/** Pointer to a NAT configuration port. */
+typedef struct PDMINETWORKNATCONFIG *PPDMINETWORKNATCONFIG;
+/**
+ * Network config port interface (main).
+ * No interface pair.
+ */
+typedef struct PDMINETWORKNATCONFIG
+{
+ /**
+ * Inform NAT about the adding/removing redirection rule
+ *
+ * @todo D O C U M E N T M E !
+ * @todo s/u16/u/g
+ */
+ DECLR3CALLBACKMEMBER(int, pfnRedirectRuleCommand ,(PPDMINETWORKNATCONFIG pInterface, bool fRemove,
+ bool fUdp, const char *pHostIp, uint16_t u16HostPort,
+ const char *pGuestIp, uint16_t u16GuestPort));
+ /**
+ * Inform NAT about host DNS settings change.
+ *
+ * IHostNameResolutionConfigurationChangeEvent.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnNotifyDnsChanged, (PPDMINETWORKNATCONFIG pInterface));
+
+} PDMINETWORKNATCONFIG;
+/** PDMINETWORKNATCONFIG interface ID. */
+#define PDMINETWORKNATCONFIG_IID "dc961028-3523-4b52-a93b-e38168a4a9fa"
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !VBOX_INCLUDED_vmm_pdmnetifs_h */
+
diff --git a/include/VBox/vmm/pdmnetinline.h b/include/VBox/vmm/pdmnetinline.h
new file mode 100644
index 00000000..0acd5fb9
--- /dev/null
+++ b/include/VBox/vmm/pdmnetinline.h
@@ -0,0 +1,724 @@
+/** @file
+ * PDM - Networking Helpers, Inlined Code. (DEV,++)
+ *
+ * This is all inlined because it's too tedious to create 2-3 libraries to
+ * contain it all (same bad excuse as for intnetinline.h).
+ */
+
+/*
+ * Copyright (C) 2010-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vmm_pdmnetinline_h
+#define VBOX_INCLUDED_vmm_pdmnetinline_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+
+/*******************************************************************************
+* Header Files *
+*******************************************************************************/
+#include <VBox/log.h>
+#include <VBox/types.h>
+#include <iprt/asm.h>
+#include <iprt/assert.h>
+#include <iprt/net.h>
+#include <iprt/string.h>
+
+
+/** @defgroup grp_pdm_net_inline The PDM Networking Helper APIs
+ * @ingroup grp_pdm
+ * @{
+ */
+
+
+/**
+ * Checksum type.
+ */
+typedef enum PDMNETCSUMTYPE
+{
+ /** No checksum. */
+ PDMNETCSUMTYPE_NONE = 0,
+ /** Normal TCP checksum. */
+ PDMNETCSUMTYPE_COMPLETE,
+ /** Checksum on pseudo header (used with GSO). */
+ PDMNETCSUMTYPE_PSEUDO,
+ /** The usual 32-bit hack. */
+ PDMNETCSUMTYPE_32_BIT_HACK = 0x7fffffff
+} PDMNETCSUMTYPE;
+
+
+/**
+ * Validates the GSO context.
+ *
+ * @returns true if valid, false if not (not asserted or logged).
+ * @param pGso The GSO context.
+ * @param cbGsoMax The max size of the GSO context.
+ * @param cbFrame The max size of the GSO frame (use to validate
+ * the MSS).
+ */
+DECLINLINE(bool) PDMNetGsoIsValid(PCPDMNETWORKGSO pGso, size_t cbGsoMax, size_t cbFrame)
+{
+#define CHECK_COND_RETURN_FALSE(expr) if (RT_LIKELY(expr)) { /* likely */ } else return false
+ PDMNETWORKGSOTYPE enmType;
+
+ CHECK_COND_RETURN_FALSE(cbGsoMax >= sizeof(*pGso));
+
+ enmType = (PDMNETWORKGSOTYPE)pGso->u8Type;
+ CHECK_COND_RETURN_FALSE(enmType > PDMNETWORKGSOTYPE_INVALID && enmType < PDMNETWORKGSOTYPE_END);
+
+ /* all types requires both headers. */
+ CHECK_COND_RETURN_FALSE(pGso->offHdr1 >= sizeof(RTNETETHERHDR));
+ CHECK_COND_RETURN_FALSE(pGso->offHdr2 > pGso->offHdr1);
+ CHECK_COND_RETURN_FALSE(pGso->cbHdrsTotal > pGso->offHdr2);
+
+ /* min size of the 1st header(s). */
+ switch (enmType)
+ {
+ case PDMNETWORKGSOTYPE_IPV4_TCP:
+ case PDMNETWORKGSOTYPE_IPV4_UDP:
+ CHECK_COND_RETURN_FALSE((unsigned)pGso->offHdr2 - pGso->offHdr1 >= RTNETIPV4_MIN_LEN);
+ break;
+ case PDMNETWORKGSOTYPE_IPV6_TCP:
+ case PDMNETWORKGSOTYPE_IPV6_UDP:
+ CHECK_COND_RETURN_FALSE((unsigned)pGso->offHdr2 - pGso->offHdr1 >= RTNETIPV6_MIN_LEN);
+ break;
+ case PDMNETWORKGSOTYPE_IPV4_IPV6_TCP:
+ case PDMNETWORKGSOTYPE_IPV4_IPV6_UDP:
+ CHECK_COND_RETURN_FALSE((unsigned)pGso->offHdr2 - pGso->offHdr1 >= RTNETIPV4_MIN_LEN + RTNETIPV6_MIN_LEN);
+ break;
+ /* These two have been rejected above already, but we need to include them to avoid gcc warnings. */
+ case PDMNETWORKGSOTYPE_INVALID:
+ case PDMNETWORKGSOTYPE_END:
+ break;
+ /* No default case! Want gcc warnings. */
+ }
+
+ /* min size of the 2nd header. */
+ switch (enmType)
+ {
+ case PDMNETWORKGSOTYPE_IPV4_TCP:
+ case PDMNETWORKGSOTYPE_IPV6_TCP:
+ case PDMNETWORKGSOTYPE_IPV4_IPV6_TCP:
+ CHECK_COND_RETURN_FALSE((unsigned)pGso->cbHdrsTotal - pGso->offHdr2 >= RTNETTCP_MIN_LEN);
+ break;
+ case PDMNETWORKGSOTYPE_IPV4_UDP:
+ case PDMNETWORKGSOTYPE_IPV6_UDP:
+ case PDMNETWORKGSOTYPE_IPV4_IPV6_UDP:
+ CHECK_COND_RETURN_FALSE((unsigned)pGso->cbHdrsTotal - pGso->offHdr2 >= RTNETUDP_MIN_LEN);
+ break;
+ /* These two have been rejected above already, but we need to include them to avoid gcc warnings. */
+ case PDMNETWORKGSOTYPE_INVALID:
+ case PDMNETWORKGSOTYPE_END:
+ break;
+ /* No default case! Want gcc warnings. */
+ }
+
+ /* There must be at more than one segment. */
+ CHECK_COND_RETURN_FALSE(cbFrame > pGso->cbHdrsTotal);
+ CHECK_COND_RETURN_FALSE(cbFrame - pGso->cbHdrsTotal >= pGso->cbMaxSeg);
+
+ /* Make sure the segment size is enough to fit a UDP header. */
+ CHECK_COND_RETURN_FALSE(enmType != PDMNETWORKGSOTYPE_IPV4_UDP || pGso->cbMaxSeg >= RTNETUDP_MIN_LEN);
+
+ /* Make sure the segment size is not zero. */
+ CHECK_COND_RETURN_FALSE(pGso->cbMaxSeg > 0);
+
+ return true;
+#undef CHECK_COND_RETURN_FALSE
+}
+
+
+/**
+ * Returns the length of header for a particular segment/fragment.
+ *
+ * We cannot simply treat UDP header as a part of payload because we do not
+ * want to modify the payload but still need to modify the checksum field in
+ * UDP header. So we want to include UDP header when calculating the length
+ * of headers in the first segment getting it copied to a temporary buffer
+ * along with other headers.
+ *
+ * @returns Length of headers (including UDP header for the first fragment).
+ * @param pGso The GSO context.
+ * @param iSeg The segment index.
+ */
+DECLINLINE(uint8_t) pdmNetSegHdrLen(PCPDMNETWORKGSO pGso, uint32_t iSeg)
+{
+ return iSeg ? pGso->cbHdrsSeg : pGso->cbHdrsTotal;
+}
+
+/**
+ * Returns the length of payload for a particular segment/fragment.
+ *
+ * The first segment does not contain UDP header. The size of UDP header is
+ * determined as the difference between the total headers size and the size
+ * used during segmentation.
+ *
+ * @returns Length of payload (including UDP header for the first fragment).
+ * @param pGso The GSO context.
+ * @param iSeg The segment that we're carving out (0-based).
+ * @param cSegs The number of segments in the GSO frame.
+ * @param cbFrame The size of the GSO frame.
+ */
+DECLINLINE(uint32_t) pdmNetSegPayloadLen(PCPDMNETWORKGSO pGso, uint32_t iSeg, uint32_t cSegs, uint32_t cbFrame)
+{
+ if (iSeg + 1 == cSegs)
+ return cbFrame - iSeg * pGso->cbMaxSeg - pdmNetSegHdrLen(pGso, iSeg);
+ return pGso->cbMaxSeg - (iSeg ? 0 : pGso->cbHdrsTotal - pGso->cbHdrsSeg);
+}
+
+/**
+ * Calculates the number of segments a GSO frame will be segmented into.
+ *
+ * @returns Segment count.
+ * @param pGso The GSO context.
+ * @param cbFrame The GSO frame size (header proto + payload).
+ */
+DECLINLINE(uint32_t) PDMNetGsoCalcSegmentCount(PCPDMNETWORKGSO pGso, size_t cbFrame)
+{
+ size_t cbPayload;
+ Assert(PDMNetGsoIsValid(pGso, sizeof(*pGso), cbFrame));
+ cbPayload = cbFrame - pGso->cbHdrsSeg;
+ return (uint32_t)((cbPayload + pGso->cbMaxSeg - 1) / pGso->cbMaxSeg);
+}
+
+
+/**
+ * Used to find the IPv6 header when handling 4to6 tunneling.
+ *
+ * @returns Offset of the IPv6 header.
+ * @param pbSegHdrs The headers / frame start.
+ * @param offIPv4Hdr The offset of the IPv4 header.
+ */
+DECLINLINE(uint8_t) pgmNetGsoCalcIpv6Offset(uint8_t *pbSegHdrs, uint8_t offIPv4Hdr)
+{
+ PCRTNETIPV4 pIPv4Hdr = (PCRTNETIPV4)&pbSegHdrs[offIPv4Hdr];
+ return offIPv4Hdr + pIPv4Hdr->ip_hl * 4;
+}
+
+
+/**
+ * Update an UDP header after carving out a segment
+ *
+ * @param u32PseudoSum The pseudo checksum.
+ * @param pbSegHdrs Pointer to the header bytes / frame start.
+ * @param offUdpHdr The offset into @a pbSegHdrs of the UDP header.
+ * @param pbPayload Pointer to the payload bytes.
+ * @param cbPayload The amount of payload.
+ * @param cbHdrs The size of all the headers.
+ * @param enmCsumType Whether to checksum the payload, the pseudo
+ * header or nothing.
+ * @internal
+ */
+DECLINLINE(void) pdmNetGsoUpdateUdpHdr(uint32_t u32PseudoSum, uint8_t *pbSegHdrs, uint8_t offUdpHdr,
+ uint8_t const *pbPayload, uint32_t cbPayload, uint8_t cbHdrs,
+ PDMNETCSUMTYPE enmCsumType)
+{
+ PRTNETUDP pUdpHdr = (PRTNETUDP)&pbSegHdrs[offUdpHdr];
+ pUdpHdr->uh_ulen = RT_H2N_U16(cbPayload + cbHdrs - offUdpHdr);
+ switch (enmCsumType)
+ {
+ case PDMNETCSUMTYPE_NONE:
+ pUdpHdr->uh_sum = 0;
+ break;
+ case PDMNETCSUMTYPE_COMPLETE:
+ pUdpHdr->uh_sum = RTNetUDPChecksum(u32PseudoSum, pUdpHdr);
+ break;
+ case PDMNETCSUMTYPE_PSEUDO:
+ pUdpHdr->uh_sum = ~RTNetIPv4FinalizeChecksum(u32PseudoSum);
+ break;
+ default:
+ NOREF(pbPayload);
+ AssertFailed();
+ break;
+ }
+}
+
+
+/**
+ * Update an UDP header after carving out an IP fragment
+ *
+ * @param u32PseudoSum The pseudo checksum.
+ * @param pbSegHdrs Pointer to the header bytes copy
+ * @param pbFrame Pointer to the frame start.
+ * @param offUdpHdr The offset into @a pbSegHdrs of the UDP header.
+ *
+ * @internal
+ */
+DECLINLINE(void) pdmNetGsoUpdateUdpHdrUfo(uint32_t u32PseudoSum, uint8_t *pbSegHdrs, const uint8_t *pbFrame, uint8_t offUdpHdr)
+{
+ PCRTNETUDP pcUdpHdrOrig = (PCRTNETUDP)&pbFrame[offUdpHdr];
+ PRTNETUDP pUdpHdr = (PRTNETUDP)&pbSegHdrs[offUdpHdr];
+ pUdpHdr->uh_sum = RTNetUDPChecksum(u32PseudoSum, pcUdpHdrOrig);
+}
+
+
+/**
+ * Update a TCP header after carving out a segment.
+ *
+ * @param u32PseudoSum The pseudo checksum.
+ * @param pbSegHdrs Pointer to the header bytes / frame start.
+ * @param offTcpHdr The offset into @a pbSegHdrs of the TCP header.
+ * @param pbPayload Pointer to the payload bytes.
+ * @param cbPayload The amount of payload.
+ * @param offPayload The offset into the payload that we're splitting
+ * up. We're ASSUMING that the payload follows
+ * immediately after the TCP header w/ options.
+ * @param cbHdrs The size of all the headers.
+ * @param fLastSeg Set if this is the last segment.
+ * @param enmCsumType Whether to checksum the payload, the pseudo
+ * header or nothing.
+ * @internal
+ */
+DECLINLINE(void) pdmNetGsoUpdateTcpHdr(uint32_t u32PseudoSum, uint8_t *pbSegHdrs, uint8_t offTcpHdr,
+ uint8_t const *pbPayload, uint32_t cbPayload, uint32_t offPayload, uint8_t cbHdrs,
+ bool fLastSeg, PDMNETCSUMTYPE enmCsumType)
+{
+ PRTNETTCP pTcpHdr = (PRTNETTCP)&pbSegHdrs[offTcpHdr];
+ pTcpHdr->th_seq = RT_H2N_U32(RT_N2H_U32(pTcpHdr->th_seq) + offPayload);
+ if (!fLastSeg)
+ pTcpHdr->th_flags &= ~(RTNETTCP_F_FIN | RTNETTCP_F_PSH);
+ switch (enmCsumType)
+ {
+ case PDMNETCSUMTYPE_NONE:
+ pTcpHdr->th_sum = 0;
+ break;
+ case PDMNETCSUMTYPE_COMPLETE:
+ pTcpHdr->th_sum = RTNetTCPChecksum(u32PseudoSum, pTcpHdr, pbPayload, cbPayload);
+ break;
+ case PDMNETCSUMTYPE_PSEUDO:
+ pTcpHdr->th_sum = ~RTNetIPv4FinalizeChecksum(u32PseudoSum);
+ break;
+ default:
+ NOREF(cbHdrs);
+ AssertFailed();
+ break;
+ }
+}
+
+
+/**
+ * Updates a IPv6 header after carving out a segment.
+ *
+ * @returns 32-bit intermediary checksum value for the pseudo header.
+ * @param pbSegHdrs Pointer to the header bytes.
+ * @param offIpHdr The offset into @a pbSegHdrs of the IP header.
+ * @param cbSegPayload The amount of segmented payload. Not to be
+ * confused with the IP payload.
+ * @param cbHdrs The size of all the headers.
+ * @param offPktHdr Offset of the protocol packet header. For the
+ * pseudo header checksum calulation.
+ * @param bProtocol The protocol type. For the pseudo header.
+ * @internal
+ */
+DECLINLINE(uint32_t) pdmNetGsoUpdateIPv6Hdr(uint8_t *pbSegHdrs, uint8_t offIpHdr, uint32_t cbSegPayload, uint8_t cbHdrs,
+ uint8_t offPktHdr, uint8_t bProtocol)
+{
+ PRTNETIPV6 pIpHdr = (PRTNETIPV6)&pbSegHdrs[offIpHdr];
+ uint16_t cbPayload = (uint16_t)(cbHdrs - (offIpHdr + sizeof(RTNETIPV6)) + cbSegPayload);
+ pIpHdr->ip6_plen = RT_H2N_U16(cbPayload);
+ return RTNetIPv6PseudoChecksumEx(pIpHdr, bProtocol, (uint16_t)(cbHdrs - offPktHdr + cbSegPayload));
+}
+
+
+/**
+ * Updates a IPv4 header after carving out a segment.
+ *
+ * @returns 32-bit intermediary checksum value for the pseudo header.
+ * @param pbSegHdrs Pointer to the header bytes.
+ * @param offIpHdr The offset into @a pbSegHdrs of the IP header.
+ * @param cbSegPayload The amount of segmented payload.
+ * @param iSeg The segment index.
+ * @param cbHdrs The size of all the headers.
+ * @internal
+ */
+DECLINLINE(uint32_t) pdmNetGsoUpdateIPv4Hdr(uint8_t *pbSegHdrs, uint8_t offIpHdr, uint32_t cbSegPayload,
+ uint32_t iSeg, uint8_t cbHdrs)
+{
+ PRTNETIPV4 pIpHdr = (PRTNETIPV4)&pbSegHdrs[offIpHdr];
+ pIpHdr->ip_len = RT_H2N_U16(cbHdrs - offIpHdr + cbSegPayload);
+ pIpHdr->ip_id = RT_H2N_U16(RT_N2H_U16(pIpHdr->ip_id) + iSeg);
+ pIpHdr->ip_sum = RTNetIPv4HdrChecksum(pIpHdr);
+ return RTNetIPv4PseudoChecksum(pIpHdr);
+}
+
+
+/**
+ * Updates a IPv4 header after carving out an IP fragment.
+ *
+ * @param pbSegHdrs Pointer to the header bytes.
+ * @param offIpHdr The offset into @a pbSegHdrs of the IP header.
+ * @param cbSegPayload The amount of segmented payload.
+ * @param offFragment The offset of this fragment for reassembly.
+ * @param cbHdrs The size of all the headers.
+ * @param fLastFragment True if this is the last fragment of datagram.
+ * @internal
+ */
+DECLINLINE(void) pdmNetGsoUpdateIPv4HdrUfo(uint8_t *pbSegHdrs, uint8_t offIpHdr, uint32_t cbSegPayload,
+ uint32_t offFragment, uint8_t cbHdrs, bool fLastFragment)
+{
+ PRTNETIPV4 pIpHdr = (PRTNETIPV4)&pbSegHdrs[offIpHdr];
+ pIpHdr->ip_len = RT_H2N_U16(cbHdrs - offIpHdr + cbSegPayload);
+ pIpHdr->ip_off = RT_H2N_U16((offFragment / 8) | (fLastFragment ? 0 : RTNETIPV4_FLAGS_MF));
+ pIpHdr->ip_sum = RTNetIPv4HdrChecksum(pIpHdr);
+}
+
+
+/**
+ * Carves out the specified segment in a destructive manner.
+ *
+ * This is for sequentially carving out segments and pushing them along for
+ * processing or sending. To avoid allocating a temporary buffer for
+ * constructing the segment in, we trash the previous frame by putting the
+ * header at the end of it.
+ *
+ * @returns Pointer to the segment frame that we've carved out.
+ * @param pGso The GSO context data.
+ * @param pbFrame Pointer to the GSO frame.
+ * @param cbFrame The size of the GSO frame.
+ * @param pbHdrScatch Pointer to a pGso->cbHdrs sized area where we
+ * can save the original header prototypes on the
+ * first call (@a iSeg is 0) and retrieve it on
+ * susequent calls. (Just use a 256 bytes
+ * buffer to make life easy.)
+ * @param iSeg The segment that we're carving out (0-based).
+ * @param cSegs The number of segments in the GSO frame. Use
+ * PDMNetGsoCalcSegmentCount to find this.
+ * @param pcbSegFrame Where to return the size of the returned segment
+ * frame.
+ */
+DECLINLINE(void *) PDMNetGsoCarveSegmentQD(PCPDMNETWORKGSO pGso, uint8_t *pbFrame, size_t cbFrame, uint8_t *pbHdrScatch,
+ uint32_t iSeg, uint32_t cSegs, uint32_t *pcbSegFrame)
+{
+ /*
+ * Figure out where the payload is and where the header starts before we
+ * do the protocol specific carving.
+ *
+ * UDP GSO uses IPv4 fragmentation, meaning that UDP header is present in
+ * the first fragment only. When computing the total frame size of the
+ * first fragment we need to use PDMNETWORKGSO::cbHdrsTotal instead of
+ * PDMNETWORKGSO::cbHdrsSeg. In case of TCP GSO both cbHdrsTotal and
+ * cbHdrsSeg have the same value, so it will work as well.
+ */
+ uint8_t * const pbSegHdrs = pbFrame + pGso->cbMaxSeg * iSeg;
+ uint8_t * const pbSegPayload = pbSegHdrs + pGso->cbHdrsSeg;
+ uint32_t const cbSegPayload = pdmNetSegPayloadLen(pGso, iSeg, cSegs, (uint32_t)cbFrame);
+ uint32_t const cbSegFrame = cbSegPayload + (iSeg ? pGso->cbHdrsSeg : pGso->cbHdrsTotal);
+
+ /*
+ * Check assumptions (doing it after declaring the variables because of C).
+ */
+ Assert(iSeg < cSegs);
+ Assert(cSegs == PDMNetGsoCalcSegmentCount(pGso, cbFrame));
+ Assert(PDMNetGsoIsValid(pGso, sizeof(*pGso), cbFrame));
+
+ /*
+ * Copy the header and do the protocol specific massaging of it.
+ */
+ if (iSeg != 0)
+ memcpy(pbSegHdrs, pbHdrScatch, pGso->cbHdrsSeg);
+ else
+ memcpy(pbHdrScatch, pbSegHdrs, pGso->cbHdrsSeg); /* There is no need to save UDP header */
+
+ switch ((PDMNETWORKGSOTYPE)pGso->u8Type)
+ {
+ case PDMNETWORKGSOTYPE_IPV4_TCP:
+ pdmNetGsoUpdateTcpHdr(pdmNetGsoUpdateIPv4Hdr(pbSegHdrs, pGso->offHdr1, cbSegPayload, iSeg, pGso->cbHdrsSeg),
+ pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, iSeg * pGso->cbMaxSeg,
+ pGso->cbHdrsSeg, iSeg + 1 == cSegs, PDMNETCSUMTYPE_COMPLETE);
+ break;
+ case PDMNETWORKGSOTYPE_IPV4_UDP:
+ if (iSeg == 0)
+ {
+ /* uh_ulen shall not exceed cbFrame - pGso->offHdr2 (offset of UDP header) */
+ PRTNETUDP pUdpHdr = (PRTNETUDP)&pbFrame[pGso->offHdr2];
+ Assert(pGso->offHdr2 + RT_UOFFSET_AFTER(RTNETUDP, uh_ulen) <= cbFrame);
+ if ((unsigned)(pGso->offHdr2 + RT_BE2H_U16(pUdpHdr->uh_ulen)) > cbFrame)
+ {
+ size_t cbUdp = cbFrame - pGso->offHdr2;
+ if (cbUdp >= UINT16_MAX)
+ pUdpHdr->uh_ulen = UINT16_MAX;
+ else
+ pUdpHdr->uh_ulen = RT_H2BE_U16((uint16_t)cbUdp);
+ }
+ /* uh_ulen shall be at least the size of UDP header */
+ if (RT_BE2H_U16(pUdpHdr->uh_ulen) < sizeof(RTNETUDP))
+ pUdpHdr->uh_ulen = RT_H2BE_U16(sizeof(RTNETUDP));
+ pdmNetGsoUpdateUdpHdrUfo(RTNetIPv4PseudoChecksum((PRTNETIPV4)&pbFrame[pGso->offHdr1]),
+ pbSegHdrs, pbFrame, pGso->offHdr2);
+ }
+ pdmNetGsoUpdateIPv4HdrUfo(pbSegHdrs, pGso->offHdr1, cbSegPayload, iSeg * pGso->cbMaxSeg,
+ pdmNetSegHdrLen(pGso, iSeg), iSeg + 1 == cSegs);
+ break;
+ case PDMNETWORKGSOTYPE_IPV6_TCP:
+ pdmNetGsoUpdateTcpHdr(pdmNetGsoUpdateIPv6Hdr(pbSegHdrs, pGso->offHdr1, cbSegPayload, pGso->cbHdrsSeg,
+ pGso->offHdr2, RTNETIPV4_PROT_TCP),
+ pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, iSeg * pGso->cbMaxSeg,
+ pGso->cbHdrsSeg, iSeg + 1 == cSegs, PDMNETCSUMTYPE_COMPLETE);
+ break;
+ case PDMNETWORKGSOTYPE_IPV6_UDP:
+ pdmNetGsoUpdateUdpHdr(pdmNetGsoUpdateIPv6Hdr(pbSegHdrs, pGso->offHdr1, cbSegPayload, pGso->cbHdrsSeg,
+ pGso->offHdr2, RTNETIPV4_PROT_UDP),
+ pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, pGso->cbHdrsSeg, PDMNETCSUMTYPE_COMPLETE);
+ break;
+ case PDMNETWORKGSOTYPE_IPV4_IPV6_TCP:
+ pdmNetGsoUpdateIPv4Hdr(pbSegHdrs, pGso->offHdr1, cbSegPayload, iSeg, pGso->cbHdrsSeg);
+ pdmNetGsoUpdateTcpHdr(pdmNetGsoUpdateIPv6Hdr(pbSegHdrs, pgmNetGsoCalcIpv6Offset(pbSegHdrs, pGso->offHdr1),
+ cbSegPayload, pGso->cbHdrsSeg, pGso->offHdr2, RTNETIPV4_PROT_TCP),
+ pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, iSeg * pGso->cbMaxSeg,
+ pGso->cbHdrsSeg, iSeg + 1 == cSegs, PDMNETCSUMTYPE_COMPLETE);
+ break;
+ case PDMNETWORKGSOTYPE_IPV4_IPV6_UDP:
+ pdmNetGsoUpdateIPv4Hdr(pbSegHdrs, pGso->offHdr1, cbSegPayload, iSeg, pGso->cbHdrsSeg);
+ pdmNetGsoUpdateUdpHdr(pdmNetGsoUpdateIPv6Hdr(pbSegHdrs, pgmNetGsoCalcIpv6Offset(pbSegHdrs, pGso->offHdr1),
+ cbSegPayload, pGso->cbHdrsSeg, pGso->offHdr2, RTNETIPV4_PROT_UDP),
+ pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, pGso->cbHdrsSeg, PDMNETCSUMTYPE_COMPLETE);
+ break;
+ case PDMNETWORKGSOTYPE_INVALID:
+ case PDMNETWORKGSOTYPE_END:
+ /* no default! wnat gcc warnings. */
+ break;
+ }
+
+ *pcbSegFrame = cbSegFrame;
+ return pbSegHdrs;
+}
+
+
+/**
+ * Carves out the specified segment in a non-destructive manner.
+ *
+ * The segment headers and segment payload is kept separate here. The GSO frame
+ * is still expected to be one linear chunk of data, but we don't modify any of
+ * it.
+ *
+ * @returns The offset into the GSO frame of the payload.
+ * @param pGso The GSO context data.
+ * @param pbFrame Pointer to the GSO frame. Used for retrieving
+ * the header prototype and for checksumming the
+ * payload. The buffer is not modified.
+ * @param cbFrame The size of the GSO frame.
+ * @param iSeg The segment that we're carving out (0-based).
+ * @param cSegs The number of segments in the GSO frame. Use
+ * PDMNetGsoCalcSegmentCount to find this.
+ * @param pbSegHdrs Where to return the headers for the segment
+ * that's been carved out. The buffer must be at
+ * least pGso->cbHdrs in size, using a 256 byte
+ * buffer is a recommended simplification.
+ * @param pcbSegHdrs Where to return the size of the returned
+ * segment headers.
+ * @param pcbSegPayload Where to return the size of the returned
+ * segment payload.
+ */
+DECLINLINE(uint32_t) PDMNetGsoCarveSegment(PCPDMNETWORKGSO pGso, const uint8_t *pbFrame, size_t cbFrame,
+ uint32_t iSeg, uint32_t cSegs, uint8_t *pbSegHdrs,
+ uint32_t *pcbSegHdrs, uint32_t *pcbSegPayload)
+{
+ /*
+ * Figure out where the payload is and where the header starts before we
+ * do the protocol specific carving.
+ */
+ uint32_t const cbSegHdrs = pdmNetSegHdrLen(pGso, iSeg);
+ uint8_t const * const pbSegPayload = pbFrame + cbSegHdrs + iSeg * pGso->cbMaxSeg;
+ uint32_t const cbSegPayload = pdmNetSegPayloadLen(pGso, iSeg, cSegs, (uint32_t)cbFrame);
+
+ /*
+ * Check assumptions (doing it after declaring the variables because of C).
+ */
+ Assert(iSeg < cSegs);
+ Assert(cSegs == PDMNetGsoCalcSegmentCount(pGso, cbFrame));
+ Assert(PDMNetGsoIsValid(pGso, sizeof(*pGso), cbFrame));
+
+ /*
+ * Copy the header and do the protocol specific massaging of it.
+ */
+ memcpy(pbSegHdrs, pbFrame, pGso->cbHdrsTotal); /* include UDP header */
+
+ switch ((PDMNETWORKGSOTYPE)pGso->u8Type)
+ {
+ case PDMNETWORKGSOTYPE_IPV4_TCP:
+ pdmNetGsoUpdateTcpHdr(pdmNetGsoUpdateIPv4Hdr(pbSegHdrs, pGso->offHdr1, cbSegPayload, iSeg, cbSegHdrs),
+ pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, iSeg * pGso->cbMaxSeg,
+ cbSegHdrs, iSeg + 1 == cSegs, PDMNETCSUMTYPE_COMPLETE);
+ break;
+ case PDMNETWORKGSOTYPE_IPV4_UDP:
+ if (iSeg == 0)
+ {
+ /* uh_ulen shall not exceed cbFrame - pGso->offHdr2 (offset of UDP header) */
+ PRTNETUDP pUdpHdr = (PRTNETUDP)&pbFrame[pGso->offHdr2];
+ Assert(pGso->offHdr2 + RT_UOFFSET_AFTER(RTNETUDP, uh_ulen) <= cbFrame);
+ if ((unsigned)(pGso->offHdr2 + RT_BE2H_U16(pUdpHdr->uh_ulen)) > cbFrame)
+ {
+ size_t cbUdp = cbFrame - pGso->offHdr2;
+ if (cbUdp >= UINT16_MAX)
+ pUdpHdr->uh_ulen = UINT16_MAX;
+ else
+ pUdpHdr->uh_ulen = RT_H2BE_U16((uint16_t)cbUdp);
+ }
+ /* uh_ulen shall be at least the size of UDP header */
+ if (RT_BE2H_U16(pUdpHdr->uh_ulen) < sizeof(RTNETUDP))
+ pUdpHdr->uh_ulen = RT_H2BE_U16(sizeof(RTNETUDP));
+ pdmNetGsoUpdateUdpHdrUfo(RTNetIPv4PseudoChecksum((PRTNETIPV4)&pbFrame[pGso->offHdr1]),
+ pbSegHdrs, pbFrame, pGso->offHdr2);
+ }
+ pdmNetGsoUpdateIPv4HdrUfo(pbSegHdrs, pGso->offHdr1, cbSegPayload, iSeg * pGso->cbMaxSeg,
+ cbSegHdrs, iSeg + 1 == cSegs);
+ break;
+ case PDMNETWORKGSOTYPE_IPV6_TCP:
+ pdmNetGsoUpdateTcpHdr(pdmNetGsoUpdateIPv6Hdr(pbSegHdrs, pGso->offHdr1, cbSegPayload, cbSegHdrs,
+ pGso->offHdr2, RTNETIPV4_PROT_TCP),
+ pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, iSeg * pGso->cbMaxSeg,
+ cbSegHdrs, iSeg + 1 == cSegs, PDMNETCSUMTYPE_COMPLETE);
+ break;
+ case PDMNETWORKGSOTYPE_IPV6_UDP:
+ pdmNetGsoUpdateUdpHdr(pdmNetGsoUpdateIPv6Hdr(pbSegHdrs, pGso->offHdr1, cbSegPayload, cbSegHdrs,
+ pGso->offHdr2, RTNETIPV4_PROT_UDP),
+ pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, cbSegHdrs, PDMNETCSUMTYPE_COMPLETE);
+ break;
+ case PDMNETWORKGSOTYPE_IPV4_IPV6_TCP:
+ pdmNetGsoUpdateIPv4Hdr(pbSegHdrs, pGso->offHdr1, cbSegPayload, iSeg, cbSegHdrs);
+ pdmNetGsoUpdateTcpHdr(pdmNetGsoUpdateIPv6Hdr(pbSegHdrs, pgmNetGsoCalcIpv6Offset(pbSegHdrs, pGso->offHdr1),
+ cbSegPayload, cbSegHdrs, pGso->offHdr2, RTNETIPV4_PROT_TCP),
+ pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, iSeg * pGso->cbMaxSeg,
+ cbSegHdrs, iSeg + 1 == cSegs, PDMNETCSUMTYPE_COMPLETE);
+ break;
+ case PDMNETWORKGSOTYPE_IPV4_IPV6_UDP:
+ pdmNetGsoUpdateIPv4Hdr(pbSegHdrs, pGso->offHdr1, cbSegPayload, iSeg, cbSegHdrs);
+ pdmNetGsoUpdateUdpHdr(pdmNetGsoUpdateIPv6Hdr(pbSegHdrs, pgmNetGsoCalcIpv6Offset(pbSegHdrs, pGso->offHdr1),
+ cbSegPayload, cbSegHdrs, pGso->offHdr2, RTNETIPV4_PROT_UDP),
+ pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, cbSegHdrs, PDMNETCSUMTYPE_COMPLETE);
+ break;
+ case PDMNETWORKGSOTYPE_INVALID:
+ case PDMNETWORKGSOTYPE_END:
+ /* no default! wnat gcc warnings. */
+ break;
+ }
+
+ *pcbSegHdrs = cbSegHdrs;
+ *pcbSegPayload = cbSegPayload;
+ return cbSegHdrs + iSeg * pGso->cbMaxSeg;
+}
+
+
+/**
+ * Prepares the GSO frame for direct use without any segmenting.
+ *
+ * @param pGso The GSO context.
+ * @param pvFrame The frame to prepare.
+ * @param cbFrame The frame size.
+ * @param enmCsumType Whether to checksum the payload, the pseudo
+ * header or nothing.
+ */
+DECLINLINE(void) PDMNetGsoPrepForDirectUse(PCPDMNETWORKGSO pGso, void *pvFrame, size_t cbFrame, PDMNETCSUMTYPE enmCsumType)
+{
+ /*
+ * Figure out where the payload is and where the header starts before we
+ * do the protocol bits.
+ */
+ uint8_t * const pbHdrs = (uint8_t *)pvFrame;
+ uint8_t * const pbPayload = pbHdrs + pGso->cbHdrsTotal;
+ uint32_t const cbFrame32 = (uint32_t)cbFrame;
+ uint32_t const cbPayload = cbFrame32 - pGso->cbHdrsTotal;
+
+ /*
+ * Check assumptions (doing it after declaring the variables because of C).
+ */
+ Assert(PDMNetGsoIsValid(pGso, sizeof(*pGso), cbFrame));
+
+ /*
+ * Get down to busienss.
+ */
+ switch ((PDMNETWORKGSOTYPE)pGso->u8Type)
+ {
+ case PDMNETWORKGSOTYPE_IPV4_TCP:
+ pdmNetGsoUpdateTcpHdr(pdmNetGsoUpdateIPv4Hdr(pbHdrs, pGso->offHdr1, cbFrame32 - pGso->cbHdrsTotal, 0, pGso->cbHdrsTotal),
+ pbHdrs, pGso->offHdr2, pbPayload, cbPayload, 0, pGso->cbHdrsTotal, true, enmCsumType);
+ break;
+ case PDMNETWORKGSOTYPE_IPV4_UDP:
+ pdmNetGsoUpdateUdpHdr(pdmNetGsoUpdateIPv4Hdr(pbHdrs, pGso->offHdr1, cbFrame32 - pGso->cbHdrsTotal, 0, pGso->cbHdrsTotal),
+ pbHdrs, pGso->offHdr2, pbPayload, cbPayload, pGso->cbHdrsTotal, enmCsumType);
+ break;
+ case PDMNETWORKGSOTYPE_IPV6_TCP:
+ pdmNetGsoUpdateTcpHdr(pdmNetGsoUpdateIPv6Hdr(pbHdrs, pGso->offHdr1, cbPayload, pGso->cbHdrsTotal,
+ pGso->offHdr2, RTNETIPV4_PROT_TCP),
+ pbHdrs, pGso->offHdr2, pbPayload, cbPayload, 0, pGso->cbHdrsTotal, true, enmCsumType);
+ break;
+ case PDMNETWORKGSOTYPE_IPV6_UDP:
+ pdmNetGsoUpdateUdpHdr(pdmNetGsoUpdateIPv6Hdr(pbHdrs, pGso->offHdr1, cbPayload, pGso->cbHdrsTotal,
+ pGso->offHdr2, RTNETIPV4_PROT_UDP),
+ pbHdrs, pGso->offHdr2, pbPayload, cbPayload, pGso->cbHdrsTotal, enmCsumType);
+ break;
+ case PDMNETWORKGSOTYPE_IPV4_IPV6_TCP:
+ pdmNetGsoUpdateIPv4Hdr(pbHdrs, pGso->offHdr1, cbPayload, 0, pGso->cbHdrsTotal);
+ pdmNetGsoUpdateTcpHdr(pdmNetGsoUpdateIPv6Hdr(pbHdrs, pgmNetGsoCalcIpv6Offset(pbHdrs, pGso->offHdr1),
+ cbPayload, pGso->cbHdrsTotal, pGso->offHdr2, RTNETIPV4_PROT_TCP),
+ pbHdrs, pGso->offHdr2, pbPayload, cbPayload, 0, pGso->cbHdrsTotal, true, enmCsumType);
+ break;
+ case PDMNETWORKGSOTYPE_IPV4_IPV6_UDP:
+ pdmNetGsoUpdateIPv4Hdr(pbHdrs, pGso->offHdr1, cbPayload, 0, pGso->cbHdrsTotal);
+ pdmNetGsoUpdateUdpHdr(pdmNetGsoUpdateIPv6Hdr(pbHdrs, pgmNetGsoCalcIpv6Offset(pbHdrs, pGso->offHdr1),
+ cbPayload, pGso->cbHdrsTotal, pGso->offHdr2, RTNETIPV4_PROT_UDP),
+ pbHdrs, pGso->offHdr2, pbPayload, cbPayload, pGso->cbHdrsTotal, enmCsumType);
+ break;
+ case PDMNETWORKGSOTYPE_INVALID:
+ case PDMNETWORKGSOTYPE_END:
+ /* no default! wnat gcc warnings. */
+ break;
+ }
+}
+
+
+/**
+ * Gets the GSO type name string.
+ *
+ * @returns Pointer to read only name string.
+ * @param enmType The type.
+ */
+DECLINLINE(const char *) PDMNetGsoTypeName(PDMNETWORKGSOTYPE enmType)
+{
+ switch (enmType)
+ {
+ case PDMNETWORKGSOTYPE_IPV4_TCP: return "TCPv4";
+ case PDMNETWORKGSOTYPE_IPV6_TCP: return "TCPv6";
+ case PDMNETWORKGSOTYPE_IPV4_UDP: return "UDPv4";
+ case PDMNETWORKGSOTYPE_IPV6_UDP: return "UDPv6";
+ case PDMNETWORKGSOTYPE_IPV4_IPV6_TCP: return "4to6TCP";
+ case PDMNETWORKGSOTYPE_IPV4_IPV6_UDP: return "4to6UDP";
+ case PDMNETWORKGSOTYPE_INVALID: return "invalid";
+ case PDMNETWORKGSOTYPE_END: return "end";
+ }
+ return "bad-gso-type";
+}
+
+/** @} */
+
+#endif /* !VBOX_INCLUDED_vmm_pdmnetinline_h */
+
diff --git a/include/VBox/vmm/pdmnetshaper.h b/include/VBox/vmm/pdmnetshaper.h
new file mode 100644
index 00000000..dc6932bd
--- /dev/null
+++ b/include/VBox/vmm/pdmnetshaper.h
@@ -0,0 +1,93 @@
+/** @file
+ * PDM - Pluggable Device Manager, Network Shaper.
+ */
+
+/*
+ * Copyright (C) 2011-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vmm_pdmnetshaper_h
+#define VBOX_INCLUDED_vmm_pdmnetshaper_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/types.h>
+#include <VBox/vmm/pdmnetifs.h>
+#include <iprt/list.h>
+#include <iprt/sg.h>
+
+
+/** @defgroup grp_pdm_net_shaper The PDM Network Shaper API
+ * @ingroup grp_pdm
+ * @{
+ */
+
+
+#define PDM_NETSHAPER_MIN_BUCKET_SIZE UINT32_C(65536) /**< bytes */
+#define PDM_NETSHAPER_MAX_LATENCY UINT32_C(100) /**< milliseconds */
+
+RT_C_DECLS_BEGIN
+
+/**
+ * A network shaper filter entry.
+ *
+ * This is used by DrvNetShaper and any similar drivers.
+ */
+typedef struct PDMNSFILTER
+{
+ /** Entry in the group's filter list.
+ * Both members are NULL when not associated with a group. */
+ RTLISTNODER3 ListEntry;
+ /** The group index + 1.
+ * @note For safety reasons the value zero is invalid and this is 1-based
+ * (like pascal) rather than 0-based indexing.
+ * @note Volatile to prevent re-reading after validation. */
+ uint32_t volatile iGroup;
+ /** Set when the filter fails to obtain bandwidth.
+ * This will then cause pIDrvNetR3 to be called before long. */
+ bool fChoked;
+ /** Aligment padding. */
+ bool afPadding[3];
+ /** The driver this filter is aggregated into (ring-3). */
+ R3PTRTYPE(PPDMINETWORKDOWN) pIDrvNetR3;
+} PDMNSFILTER;
+
+VMM_INT_DECL(bool) PDMNetShaperAllocateBandwidth(PVMCC pVM, PPDMNSFILTER pFilter, size_t cbTransfer);
+VMMR3_INT_DECL(int) PDMR3NsAttach(PVM pVM, PPDMDRVINS pDrvIns, const char *pszName, PPDMNSFILTER pFilter);
+VMMR3_INT_DECL(int) PDMR3NsDetach(PVM pVM, PPDMDRVINS pDrvIns, PPDMNSFILTER pFilter);
+VMMR3DECL(int) PDMR3NsBwGroupSetLimit(PUVM pUVM, const char *pszName, uint64_t cbPerSecMax);
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !VBOX_INCLUDED_vmm_pdmnetshaper_h */
+
diff --git a/include/VBox/vmm/pdmpci.h b/include/VBox/vmm/pdmpci.h
new file mode 100644
index 00000000..61493eb8
--- /dev/null
+++ b/include/VBox/vmm/pdmpci.h
@@ -0,0 +1,408 @@
+/** @file
+ * PDM - Pluggable Device Manager, raw PCI Devices. (VMM)
+ */
+
+/*
+ * Copyright (C) 2010-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vmm_pdmpci_h
+#define VBOX_INCLUDED_vmm_pdmpci_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/types.h>
+#include <VBox/rawpci.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_pdm_pciraw The raw PCI Devices API
+ * @ingroup grp_pdm
+ * @{
+ */
+
+typedef struct PDMIPCIRAW *PPDMIPCIRAW;
+typedef struct PDMIPCIRAW
+{
+ /**
+ * Notify virtual device that interrupt has arrived.
+ * For this callback to be called, interface have to be
+ * registered with PDMIPCIRAWUP::pfnRegisterInterruptListener.
+ *
+ * @note no level parameter, as we can only support flip-flop.
+ *
+ * @param pInterface Pointer to this interface structure.
+ * @param iGuestIrq Guest interrupt number, passed earlier when registering listener.
+ *
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnInterruptRequest,(PPDMIPCIRAW pInterface, int32_t iGuestIrq));
+} PDMIPCIRAW;
+
+typedef struct PDMIPCIRAWUP *PPDMIPCIRAWUP;
+typedef struct PDMIPCIRAWUP
+{
+ /**
+ * Host PCI MMIO access function.
+ */
+
+ /**
+ * Request driver info about PCI region on host PCI device.
+ *
+ * @returns true, if region is present, and out parameters are correct
+ * @param pInterface Pointer to this interface structure.
+ * @param iRegion Region number.
+ * @param pGCPhysRegion Where to store region base address (guest).
+ * @param pcbRegion Where to store region size.
+ *
+ * @param pfFlags If region is MMIO or IO.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(bool, pfnGetRegionInfo, (PPDMIPCIRAWUP pInterface,
+ uint32_t iRegion,
+ RTGCPHYS *pGCPhysRegion,
+ uint64_t *pcbRegion,
+ uint32_t *pfFlags));
+
+ /**
+ * Request driver to map part of host device's MMIO region to the VM process and maybe kernel.
+ * Shall only be issued within earlier obtained with pfnGetRegionInfo()
+ * host physical address ranges for the device BARs. Even if failed, device still may function
+ * using pfnMmio* and pfnPio* operations, just much slower.
+ *
+ * @returns status code
+ * @param pInterface Pointer to this interface structure.
+ * @param iRegion Number of the region.
+ * @param StartAddress Host physical address of start.
+ * @param cbRegion Size of the region.
+ * @param fFlags Flags, currently lowest significant bit set if R0 mapping requested too
+ * @param ppvAddressR3 Where to store mapped region address for R3 (can be 0, if cannot map into userland)
+ * @param ppvAddressR0 Where to store mapped region address for R0 (can be 0, if cannot map into kernel)
+ *
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnMapRegion, (PPDMIPCIRAWUP pInterface,
+ uint32_t iRegion,
+ RTHCPHYS StartAddress,
+ uint64_t cbRegion,
+ uint32_t fFlags,
+ PRTR3PTR ppvAddressR3,
+ PRTR0PTR ppvAddressR0));
+
+ /**
+ * Request driver to unmap part of host device's MMIO region to the VM process.
+ * Shall only be issued with pointer earlier obtained with pfnMapRegion().
+ *
+ * @returns status code
+ * @param pInterface Pointer to this interface structure
+ * @param iRegion Number of the region.
+ * @param StartAddress Host physical address of start.
+ * @param cbRegion Size of the region.
+ * @param pvAddressR3 R3 address of mapped region.
+ * @param pvAddressR0 R0 address of mapped region.
+ *
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnUnmapRegion, (PPDMIPCIRAWUP pInterface,
+ uint32_t iRegion,
+ RTHCPHYS StartAddress,
+ uint64_t cbRegion,
+ RTR3PTR pvAddressR3,
+ RTR0PTR pvAddressR0));
+
+ /**
+ * Request port IO write.
+ *
+ * @returns status code
+ * @param pInterface Pointer to this interface structure.
+ * @param uPort I/O port address.
+ * @param uValue Value to write.
+ * @param cb Access width.
+ *
+ * @thread EMT thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPioWrite, (PPDMIPCIRAWUP pInterface,
+ RTIOPORT uPort,
+ uint32_t uValue,
+ unsigned cb));
+
+ /**
+ * Request port IO read.
+ *
+ * @returns status code
+ * @param pInterface Pointer to this interface structure.
+ * @param uPort I/O port address.
+ * @param puValue Place to store read value.
+ * @param cb Access width.
+ *
+ * @thread EMT thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPioRead, (PPDMIPCIRAWUP pInterface,
+ RTIOPORT uPort,
+ uint32_t *puValue,
+ unsigned cb));
+
+
+ /**
+ * Request MMIO write.
+ *
+ * This callback is only called if driver wants to receive MMIO via pu32Flags
+ * argument of pfnPciDeviceConstructStart().
+ *
+ * @returns status code
+ * @param pInterface Pointer to this interface structure.
+ * @param Address Guest physical address.
+ * @param pvValue Address of value to write.
+ * @param cb Access width.
+ *
+ * @todo Why is this @a Address documented as guest physical
+ * address and given a host ring-0 address type?
+ *
+ * @thread EMT thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnMmioWrite, (PPDMIPCIRAWUP pInterface,
+ RTR0PTR Address,
+ void const *pvValue,
+ unsigned cb));
+
+ /**
+ * Request MMIO read.
+ *
+ * @returns status code
+ * @param pInterface Pointer to this interface structure.
+ * @param Address Guest physical address.
+ * @param pvValue Place to store read value.
+ * @param cb Access width.
+ *
+ * @todo Why is this @a Address documented as guest physical
+ * address and given a host ring-0 address type?
+ *
+ * @thread EMT thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnMmioRead, (PPDMIPCIRAWUP pInterface,
+ RTR0PTR Address,
+ void *pvValue,
+ unsigned cb));
+
+ /**
+ * Host PCI config space accessors.
+ */
+ /**
+ * Request driver to write value to host device's PCI config space.
+ * Host specific way (PIO or MCFG) is used to perform actual operation.
+ *
+ * @returns status code
+ * @param pInterface Pointer to this interface structure.
+ * @param offCfgSpace Offset in PCI config space.
+ * @param pvValue Value to write.
+ * @param cb Access width.
+ *
+ * @thread EMT thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPciCfgWrite, (PPDMIPCIRAWUP pInterface,
+ uint32_t offCfgSpace,
+ void *pvValue,
+ unsigned cb));
+ /**
+ * Request driver to read value from host device's PCI config space.
+ * Host specific way (PIO or MCFG) is used to perform actual operation.
+ *
+ * @returns status code
+ * @param pInterface Pointer to this interface structure.
+ * @param offCfgSpace Offset in PCI config space.
+ * @param pvValue Where to store read value.
+ * @param cb Access width.
+ *
+ * @thread EMT thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPciCfgRead, (PPDMIPCIRAWUP pInterface,
+ uint32_t offCfgSpace,
+ void *pvValue,
+ unsigned cb));
+
+ /**
+ * Request to enable interrupt notifications. Please note that this is purely
+ * R3 interface, so it's up to implementor to perform necessary machinery
+ * for communications with host OS kernel driver. Typical implementation will start
+ * userland thread waiting on shared semaphore (such as using SUPSEMEVENT),
+ * notified by the kernel interrupt handler, and then will call
+ * upper port pfnInterruptRequest() based on data provided by the driver.
+ * This apporach is taken, as calling VBox code from an asyncronous R0
+ * interrupt handler when VMM may not be even running doesn't look
+ * like a good idea.
+ *
+ * @returns status code
+ * @param pInterface Pointer to this interface structure.
+ * @param uGuestIrq Guest IRQ to be passed to pfnInterruptRequest().
+ *
+ * @thread Any thread, pfnInterruptRequest() will be usually invoked on a dedicated thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnEnableInterruptNotifications, (PPDMIPCIRAWUP pInterface, uint8_t uGuestIrq));
+
+ /**
+ * Request to disable interrupt notifications.
+ *
+ * @returns status code
+ * @param pInterface Pointer to this interface structure.
+ *
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnDisableInterruptNotifications, (PPDMIPCIRAWUP pInterface));
+
+ /** @name Notification APIs.
+ * @{
+ */
+
+ /**
+ * Notify driver when raw PCI device construction starts.
+ *
+ * Have to be the first operation as initializes internal state and opens host
+ * device driver.
+ *
+ * @returns status code
+ * @param pInterface Pointer to this interface structure.
+ * @param uHostPciAddress Host PCI address of device attached.
+ * @param uGuestPciAddress Guest PCI address of device attached.
+ * @param pszDeviceName Human readable device name.
+ * @param fDeviceFlags Flags for the host device.
+ * @param pfFlags Flags for virtual device, from the upper driver.
+ *
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPciDeviceConstructStart, (PPDMIPCIRAWUP pInterface,
+ uint32_t uHostPciAddress,
+ uint32_t uGuestPciAddress,
+ const char *pszDeviceName,
+ uint32_t fDeviceFlags,
+ uint32_t *pfFlags));
+
+ /**
+ * Notify driver when raw PCI device construction completes, so that it may
+ * perform further actions depending on success or failure of this operation.
+ * Standard action is to raise global IHostPciDevicePlugEvent.
+ *
+ * @param pInterface Pointer to this interface structure.
+ * @param rc Result code of the operation.
+ *
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnPciDeviceConstructComplete, (PPDMIPCIRAWUP pInterface, int rc));
+
+ /**
+ * Notify driver on finalization of raw PCI device.
+ *
+ * @param pInterface Pointer to this interface structure.
+ * @param fFlags Flags.
+ *
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPciDeviceDestruct, (PPDMIPCIRAWUP pInterface, uint32_t fFlags));
+
+ /**
+ * Notify driver on guest power state change.
+ *
+ * @param pInterface Pointer to this interface structure.
+ * @param enmState New power state.
+ * @param pu64Param State-specific in/out parameter. For now only used during power-on to provide VM caps.
+ *
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPciDevicePowerStateChange, (PPDMIPCIRAWUP pInterface,
+ PCIRAWPOWERSTATE enmState,
+ uint64_t *pu64Param));
+
+ /**
+ * Notify driver about runtime error.
+ *
+ * @param pInterface Pointer to this interface structure.
+ * @param fFatal If error is fatal.
+ * @param pszErrorId Error ID.
+ * @param pszMessage Error message.
+ *
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnReportRuntimeError, (PPDMIPCIRAWUP pInterface,
+ bool fFatal,
+ const char *pszErrorId,
+ const char *pszMessage));
+ /** @} */
+} PDMIPCIRAWUP;
+
+/**
+ * Init R0 PCI module.
+ */
+PCIRAWR0DECL(int) PciRawR0Init(void);
+/**
+ * Process request (in R0).
+ */
+PCIRAWR0DECL(int) PciRawR0ProcessReq(PGVM pGVM, PSUPDRVSESSION pSession, PPCIRAWSENDREQ pReq);
+/**
+ * Terminate R0 PCI module.
+ */
+PCIRAWR0DECL(void) PciRawR0Term(void);
+
+/**
+ * Per-VM R0 module init.
+ */
+PCIRAWR0DECL(int) PciRawR0InitVM(PGVM pGVM);
+
+/**
+ * Per-VM R0 module termination routine.
+ */
+PCIRAWR0DECL(void) PciRawR0TermVM(PGVM pGVM);
+
+/**
+ * Flags returned by pfnPciDeviceConstructStart(), to notify device
+ * how it shall handle device IO traffic.
+ */
+typedef enum PCIRAWDEVICEFLAGS
+{
+ /** Intercept port IO (R3 PIO always go to the driver). */
+ PCIRAWRFLAG_CAPTURE_PIO = (1 << 0),
+ /** Intercept MMIO. */
+ PCIRAWRFLAG_CAPTURE_MMIO = (1 << 1),
+ /** Allow bus mastering by physical device (requires IOMMU). */
+ PCIRAWRFLAG_ALLOW_BM = (1 << 2),
+ /** Allow R3 MMIO mapping. */
+ PCIRAWRFLAG_ALLOW_R3MAP = (1 << 3),
+
+ /** The usual 32-bit type blow up. */
+ PCIRAWRFLAG_32BIT_HACK = 0x7fffffff
+} PCIRAWDEVICEFLAGS;
+
+#define PDMIPCIRAWUP_IID "06daa17f-097b-4ebe-a626-15f467b1de12"
+#define PDMIPCIRAW_IID "68c6e4c4-4223-47e0-9134-e3c297992543"
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !VBOX_INCLUDED_vmm_pdmpci_h */
diff --git a/include/VBox/vmm/pdmpcidev.h b/include/VBox/vmm/pdmpcidev.h
new file mode 100644
index 00000000..077c5525
--- /dev/null
+++ b/include/VBox/vmm/pdmpcidev.h
@@ -0,0 +1,803 @@
+/** @file
+ * PCI - The PCI Controller And Devices. (DEV)
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vmm_pdmpcidev_h
+#define VBOX_INCLUDED_vmm_pdmpcidev_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/pci.h>
+#include <iprt/assert.h>
+
+
+/** @defgroup grp_pdm_pcidev PDM PCI Device
+ * @ingroup grp_pdm_device
+ * @{
+ */
+
+/**
+ * Callback function for intercept reading from the PCI configuration space.
+ *
+ * @returns VINF_SUCCESS or PDMDevHlpDBGFStop status (maybe others later).
+ * @retval VINF_PDM_PCI_DO_DEFAULT to do default read (same as calling
+ * PDMDevHlpPCIConfigRead()).
+ *
+ * @param pDevIns Pointer to the device instance the PCI device
+ * belongs to.
+ * @param pPciDev Pointer to PCI device. Use pPciDev->pDevIns to get the device instance.
+ * @param uAddress The configuration space register address. [0..4096]
+ * @param cb The register size. [1,2,4]
+ * @param pu32Value Where to return the register value.
+ *
+ * @remarks Called with the PDM lock held. The device lock is NOT take because
+ * that is very likely be a lock order violation.
+ */
+typedef DECLCALLBACKTYPE(VBOXSTRICTRC, FNPCICONFIGREAD,(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev,
+ uint32_t uAddress, unsigned cb, uint32_t *pu32Value));
+/** Pointer to a FNPCICONFIGREAD() function. */
+typedef FNPCICONFIGREAD *PFNPCICONFIGREAD;
+#if !RT_CLANG_PREREQ(11, 0) /* Clang 11 (at least) has trouble with nothrow and pointers to function pointers. */
+/** Pointer to a PFNPCICONFIGREAD. */
+typedef PFNPCICONFIGREAD *PPFNPCICONFIGREAD;
+#endif
+
+/**
+ * Callback function for writing to the PCI configuration space.
+ *
+ * @returns VINF_SUCCESS or PDMDevHlpDBGFStop status (maybe others later).
+ * @retval VINF_PDM_PCI_DO_DEFAULT to do default read (same as calling
+ * PDMDevHlpPCIConfigWrite()).
+ *
+ * @param pDevIns Pointer to the device instance the PCI device
+ * belongs to.
+ * @param pPciDev Pointer to PCI device. Use pPciDev->pDevIns to get the device instance.
+ * @param uAddress The configuration space register address. [0..4096]
+ * @param cb The register size. [1,2,4]
+ * @param u32Value The value that's being written. The number of bits actually used from
+ * this value is determined by the cb parameter.
+ *
+ * @remarks Called with the PDM lock held. The device lock is NOT take because
+ * that is very likely be a lock order violation.
+ */
+typedef DECLCALLBACKTYPE(VBOXSTRICTRC, FNPCICONFIGWRITE,(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev,
+ uint32_t uAddress, unsigned cb, uint32_t u32Value));
+/** Pointer to a FNPCICONFIGWRITE() function. */
+typedef FNPCICONFIGWRITE *PFNPCICONFIGWRITE;
+#if !RT_CLANG_PREREQ(11, 0) /* Clang 11 (at least) has trouble with nothrow and pointers to function pointers. */
+/** Pointer to a PFNPCICONFIGWRITE. */
+typedef PFNPCICONFIGWRITE *PPFNPCICONFIGWRITE;
+#endif
+
+/**
+ * Callback function for mapping an PCI I/O region.
+ *
+ * This is called when a PCI I/O region is mapped, and for new-style devices
+ * also when unmapped (address set to NIL_RTGCPHYS). For new-style devices,
+ * this callback is optional as the PCI bus calls IOM to map and unmap the
+ * regions.
+ *
+ * Old style devices have to call IOM to map the region themselves, while
+ * unmapping is done by the PCI bus like with the new style devices.
+ *
+ * @returns VBox status code.
+ * @retval VINF_PCI_MAPPING_DONE if the caller already did the mapping and the
+ * PCI bus should not use the handle it got to do the registration
+ * again. (Only allowed when @a GCPhysAddress is not NIL_RTGCPHYS.)
+ *
+ * @param pDevIns Pointer to the device instance the PCI device
+ * belongs to.
+ * @param pPciDev Pointer to the PCI device.
+ * @param iRegion The region number.
+ * @param GCPhysAddress Physical address of the region. If @a enmType is
+ * PCI_ADDRESS_SPACE_IO, this is an I/O port, otherwise
+ * it's a physical address.
+ *
+ * NIL_RTGCPHYS indicates that a mapping is about to be
+ * unmapped and that the device deregister access
+ * handlers for it and update its internal state to
+ * reflect this.
+ *
+ * @param cb Size of the region in bytes.
+ * @param enmType One of the PCI_ADDRESS_SPACE_* values.
+ *
+ * @remarks Called with the PDM lock held. The device lock is NOT take because
+ * that is very likely be a lock order violation.
+ */
+typedef DECLCALLBACKTYPE(int, FNPCIIOREGIONMAP,(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t iRegion,
+ RTGCPHYS GCPhysAddress, RTGCPHYS cb, PCIADDRESSSPACE enmType));
+/** Pointer to a FNPCIIOREGIONMAP() function. */
+typedef FNPCIIOREGIONMAP *PFNPCIIOREGIONMAP;
+
+
+/**
+ * Sets the size and type for old saved states from within a
+ * PDMPCIDEV::pfnRegionLoadChangeHookR3 callback.
+ *
+ * @returns VBox status code.
+ * @param pPciDev Pointer to the PCI device.
+ * @param iRegion The region number.
+ * @param cbRegion The region size.
+ * @param enmType Combination of the PCI_ADDRESS_SPACE_* values.
+ */
+typedef DECLCALLBACKTYPE(int, FNPCIIOREGIONOLDSETTER,(PPDMPCIDEV pPciDev, uint32_t iRegion, RTGCPHYS cbRegion,
+ PCIADDRESSSPACE enmType));
+/** Pointer to a FNPCIIOREGIONOLDSETTER() function. */
+typedef FNPCIIOREGIONOLDSETTER *PFNPCIIOREGIONOLDSETTER;
+
+/**
+ * Swaps two PCI I/O regions from within a PDMPCIDEV::pfnRegionLoadChangeHookR3
+ * callback.
+ *
+ * @returns VBox status code.
+ * @param pPciDev Pointer to the PCI device.
+ * @param iRegion The region number.
+ * @param iOtherRegion The number of the region swap with.
+ * @sa @bugref{9359}
+ */
+typedef DECLCALLBACKTYPE(int, FNPCIIOREGIONSWAP,(PPDMPCIDEV pPciDev, uint32_t iRegion, uint32_t iOtherRegion));
+/** Pointer to a FNPCIIOREGIONSWAP() function. */
+typedef FNPCIIOREGIONSWAP *PFNPCIIOREGIONSWAP;
+
+
+/*
+ * Hack to include the PDMPCIDEVINT structure at the right place
+ * to avoid duplications of FNPCIIOREGIONMAP and such.
+ */
+#ifdef PDMPCIDEV_INCLUDE_PRIVATE
+# include "pdmpcidevint.h"
+#endif
+
+/**
+ * PDM PCI Device structure.
+ *
+ * A PCI device belongs to a PDM device. A PDM device may have zero or more PCI
+ * devices associated with it. The first PCI device that it registers
+ * automatically becomes the default PCI device and can be used implicitly
+ * with the device helper APIs. Subsequent PCI devices must be specified
+ * explicitly to the device helper APIs when used.
+ */
+typedef struct PDMPCIDEV
+{
+ /** @name Read only data.
+ * @{
+ */
+ /** Magic number (PDMPCIDEV_MAGIC). */
+ uint32_t u32Magic;
+ /** PCI device number [11:3] and function [2:0] on the pci bus.
+ * @sa VBOX_PCI_DEVFN_MAKE, VBOX_PCI_DEVFN_FUN_MASK, VBOX_PCI_DEVFN_DEV_SHIFT */
+ uint32_t uDevFn;
+ /** Size of the valid config space (we always allocate 4KB). */
+ uint16_t cbConfig;
+ /** Size of the MSI-X state data optionally following the config space. */
+ uint16_t cbMsixState;
+ /** Index into the PDMDEVINS::apPciDev array. */
+ uint16_t idxSubDev;
+ uint16_t u16Padding;
+ /** Device name. */
+ R3PTRTYPE(const char *) pszNameR3;
+ /** @} */
+
+ /**
+ * Callback for dealing with size changes.
+ *
+ * This is set by the PCI device when needed. It is only needed if any changes
+ * in the PCI resources have been made that may be incompatible with saved state
+ * (i.e. does not reflect configuration, but configuration defaults changed).
+ *
+ * The implementation can use PDMDevHlpMMIOExReduce to adjust the resource
+ * allocation down in size. There is currently no way of growing resources.
+ * Dropping a resource is automatic.
+ *
+ * @returns VBox status code.
+ * @param pDevIns Pointer to the device instance the PCI device
+ * belongs to.
+ * @param pPciDev Pointer to the PCI device.
+ * @param iRegion The region number or UINT32_MAX if old saved state call.
+ * @param cbRegion The size being loaded, RTGCPHYS_MAX if old saved state
+ * call, or 0 for dummy 64-bit top half region.
+ * @param enmType The type being loaded, -1 if old saved state call, or
+ * 0xff if dummy 64-bit top half region.
+ * @param pfnOldSetter Callback for setting size and type for call
+ * regarding old saved states. NULL otherwise.
+ * @param pfnSwapRegions Used to swaps two regions. The second one must be a
+ * higher number than @a iRegion. NULL if old saved
+ * state.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnRegionLoadChangeHookR3,(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t iRegion,
+ uint64_t cbRegion, PCIADDRESSSPACE enmType,
+ PFNPCIIOREGIONOLDSETTER pfnOldSetter,
+ PFNPCIIOREGIONSWAP pfnSwapRegion));
+
+ /** Reserved for future stuff. */
+ uint64_t au64Reserved[4 + (R3_ARCH_BITS == 32 ? 1 : 0)];
+
+ /** Internal data. */
+ union
+ {
+#ifdef PDMPCIDEVINT_DECLARED
+ PDMPCIDEVINT s;
+#endif
+ uint8_t padding[0x180];
+ } Int;
+
+ /** PCI config space.
+ * This is either 256 or 4096 in size. In the latter case it may be
+ * followed by a MSI-X state area. */
+ uint8_t abConfig[4096];
+ /** The MSI-X state data. Optional. */
+ RT_FLEXIBLE_ARRAY_EXTENSION
+ uint8_t abMsixState[RT_FLEXIBLE_ARRAY];
+} PDMPCIDEV;
+#ifdef PDMPCIDEVINT_DECLARED
+AssertCompile(RT_SIZEOFMEMB(PDMPCIDEV, Int.s) <= RT_SIZEOFMEMB(PDMPCIDEV, Int.padding));
+#endif
+/** Magic number of PDMPCIDEV::u32Magic (Margaret Eleanor Atwood). */
+#define PDMPCIDEV_MAGIC UINT32_C(0x19391118)
+
+/** Checks that the PCI device structure is valid and belongs to the device
+ * instance, but does not return. */
+#ifdef VBOX_STRICT
+# define PDMPCIDEV_ASSERT_VALID(a_pDevIns, a_pPciDev) \
+ do { \
+ uintptr_t const offPciDevInTable = (uintptr_t)(a_pPciDev) - (uintptr_t)pDevIns->apPciDevs[0]; \
+ uint32_t const cbPciDevTmp = pDevIns->cbPciDev; \
+ ASMCompilerBarrier(); \
+ AssertMsg( offPciDevInTable < pDevIns->cPciDevs * cbPciDevTmp \
+ && cbPciDevTmp >= RT_UOFFSETOF(PDMPCIDEV, abConfig) + 256 \
+ && offPciDevInTable % cbPciDevTmp == 0, \
+ ("pPciDev=%p apPciDevs[0]=%p offPciDevInTable=%p cPciDevs=%#x cbPciDev=%#x\n", \
+ (a_pPciDev), pDevIns->apPciDevs[0], offPciDevInTable, pDevIns->cPciDevs, cbPciDevTmp)); \
+ AssertPtr((a_pPciDev)); \
+ AssertMsg((a_pPciDev)->u32Magic == PDMPCIDEV_MAGIC, ("%#x\n", (a_pPciDev)->u32Magic)); \
+ } while (0)
+#else
+# define PDMPCIDEV_ASSERT_VALID(a_pDevIns, a_pPciDev) do { } while (0)
+#endif
+
+/** Checks that the PCI device structure is valid, belongs to the device
+ * instance and that it is registered, but does not return. */
+#ifdef VBOX_STRICT
+# define PDMPCIDEV_ASSERT_VALID_AND_REGISTERED(a_pDevIns, a_pPciDev) \
+ do { \
+ PDMPCIDEV_ASSERT_VALID(a_pDevIns, a_pPciDev); \
+ Assert((a_pPciDev)->Int.s.fRegistered); \
+ } while (0)
+#else
+# define PDMPCIDEV_ASSERT_VALID_AND_REGISTERED(a_pDevIns, a_pPciDev) do { } while (0)
+#endif
+
+/** Checks that the PCI device structure is valid and belongs to the device
+ * instance, returns appropriate status code if not valid. */
+#define PDMPCIDEV_ASSERT_VALID_RET(a_pDevIns, a_pPciDev) \
+ do { \
+ uintptr_t const offPciDevInTable = (uintptr_t)(a_pPciDev) - (uintptr_t)pDevIns->apPciDevs[0]; \
+ uint32_t const cbPciDevTmp = pDevIns->cbPciDev; \
+ ASMCompilerBarrier(); \
+ AssertMsgReturn( offPciDevInTable < pDevIns->cPciDevs * cbPciDevTmp \
+ && cbPciDevTmp >= RT_UOFFSETOF(PDMPCIDEV, abConfig) + 256 \
+ && offPciDevInTable % cbPciDevTmp == 0, \
+ ("pPciDev=%p apPciDevs[0]=%p offPciDevInTable=%p cPciDevs=%#x cbPciDev=%#x\n", \
+ (a_pPciDev), pDevIns->apPciDevs[0], offPciDevInTable, pDevIns->cPciDevs, cbPciDevTmp), \
+ VERR_PDM_NOT_PCI_DEVICE); \
+ AssertMsgReturn((a_pPciDev)->u32Magic == PDMPCIDEV_MAGIC, ("%#x\n", (a_pPciDev)->u32Magic), VERR_PDM_NOT_PCI_DEVICE); \
+ AssertReturn((a_pPciDev)->Int.s.fRegistered, VERR_PDM_NOT_PCI_DEVICE); \
+ } while (0)
+
+
+
+/** @name PDM PCI config space accessor function.
+ * @{
+ */
+
+/** @todo handle extended space access. */
+
+DECLINLINE(void) PDMPciDevSetByte(PPDMPCIDEV pPciDev, uint32_t offReg, uint8_t u8Value)
+{
+ Assert(offReg < sizeof(pPciDev->abConfig));
+ pPciDev->abConfig[offReg] = u8Value;
+}
+
+DECLINLINE(uint8_t) PDMPciDevGetByte(PCPDMPCIDEV pPciDev, uint32_t offReg)
+{
+ Assert(offReg < sizeof(pPciDev->abConfig));
+ return pPciDev->abConfig[offReg];
+}
+
+DECLINLINE(void) PDMPciDevSetWord(PPDMPCIDEV pPciDev, uint32_t offReg, uint16_t u16Value)
+{
+ Assert(offReg <= sizeof(pPciDev->abConfig) - sizeof(uint16_t));
+ *(uint16_t*)&pPciDev->abConfig[offReg] = RT_H2LE_U16(u16Value);
+}
+
+DECLINLINE(uint16_t) PDMPciDevGetWord(PCPDMPCIDEV pPciDev, uint32_t offReg)
+{
+ uint16_t u16Value;
+ Assert(offReg <= sizeof(pPciDev->abConfig) - sizeof(uint16_t));
+ u16Value = *(uint16_t*)&pPciDev->abConfig[offReg];
+ return RT_H2LE_U16(u16Value);
+}
+
+DECLINLINE(void) PDMPciDevSetDWord(PPDMPCIDEV pPciDev, uint32_t offReg, uint32_t u32Value)
+{
+ Assert(offReg <= sizeof(pPciDev->abConfig) - sizeof(uint32_t));
+ *(uint32_t*)&pPciDev->abConfig[offReg] = RT_H2LE_U32(u32Value);
+}
+
+DECLINLINE(uint32_t) PDMPciDevGetDWord(PCPDMPCIDEV pPciDev, uint32_t offReg)
+{
+ uint32_t u32Value;
+ Assert(offReg <= sizeof(pPciDev->abConfig) - sizeof(uint32_t));
+ u32Value = *(uint32_t*)&pPciDev->abConfig[offReg];
+ return RT_H2LE_U32(u32Value);
+}
+
+DECLINLINE(void) PDMPciDevSetQWord(PPDMPCIDEV pPciDev, uint32_t offReg, uint64_t u64Value)
+{
+ Assert(offReg <= sizeof(pPciDev->abConfig) - sizeof(uint64_t));
+ *(uint64_t*)&pPciDev->abConfig[offReg] = RT_H2LE_U64(u64Value);
+}
+
+DECLINLINE(uint64_t) PDMPciDevGetQWord(PCPDMPCIDEV pPciDev, uint32_t offReg)
+{
+ uint64_t u64Value;
+ Assert(offReg <= sizeof(pPciDev->abConfig) - sizeof(uint64_t));
+ u64Value = *(uint64_t*)&pPciDev->abConfig[offReg];
+ return RT_H2LE_U64(u64Value);
+}
+
+/**
+ * Sets the vendor id config register.
+ * @param pPciDev The PCI device.
+ * @param u16VendorId The vendor id.
+ */
+DECLINLINE(void) PDMPciDevSetVendorId(PPDMPCIDEV pPciDev, uint16_t u16VendorId)
+{
+ PDMPciDevSetWord(pPciDev, VBOX_PCI_VENDOR_ID, u16VendorId);
+}
+
+/**
+ * Gets the vendor id config register.
+ * @returns the vendor id.
+ * @param pPciDev The PCI device.
+ */
+DECLINLINE(uint16_t) PDMPciDevGetVendorId(PCPDMPCIDEV pPciDev)
+{
+ return PDMPciDevGetWord(pPciDev, VBOX_PCI_VENDOR_ID);
+}
+
+
+/**
+ * Sets the device id config register.
+ * @param pPciDev The PCI device.
+ * @param u16DeviceId The device id.
+ */
+DECLINLINE(void) PDMPciDevSetDeviceId(PPDMPCIDEV pPciDev, uint16_t u16DeviceId)
+{
+ PDMPciDevSetWord(pPciDev, VBOX_PCI_DEVICE_ID, u16DeviceId);
+}
+
+/**
+ * Gets the device id config register.
+ * @returns the device id.
+ * @param pPciDev The PCI device.
+ */
+DECLINLINE(uint16_t) PDMPciDevGetDeviceId(PCPDMPCIDEV pPciDev)
+{
+ return PDMPciDevGetWord(pPciDev, VBOX_PCI_DEVICE_ID);
+}
+
+/**
+ * Sets the command config register.
+ *
+ * @param pPciDev The PCI device.
+ * @param u16Command The command register value.
+ */
+DECLINLINE(void) PDMPciDevSetCommand(PPDMPCIDEV pPciDev, uint16_t u16Command)
+{
+ PDMPciDevSetWord(pPciDev, VBOX_PCI_COMMAND, u16Command);
+}
+
+
+/**
+ * Gets the command config register.
+ * @returns The command register value.
+ * @param pPciDev The PCI device.
+ */
+DECLINLINE(uint16_t) PDMPciDevGetCommand(PCPDMPCIDEV pPciDev)
+{
+ return PDMPciDevGetWord(pPciDev, VBOX_PCI_COMMAND);
+}
+
+/**
+ * Checks if the given PCI device is a bus master.
+ * @returns true if the device is a bus master, false if not.
+ * @param pPciDev The PCI device.
+ */
+DECLINLINE(bool) PDMPciDevIsBusmaster(PCPDMPCIDEV pPciDev)
+{
+ return (PDMPciDevGetCommand(pPciDev) & VBOX_PCI_COMMAND_MASTER) != 0;
+}
+
+/**
+ * Checks if INTx interrupts disabled in the command config register.
+ * @returns true if disabled.
+ * @param pPciDev The PCI device.
+ */
+DECLINLINE(bool) PDMPciDevIsIntxDisabled(PCPDMPCIDEV pPciDev)
+{
+ return (PDMPciDevGetCommand(pPciDev) & VBOX_PCI_COMMAND_INTX_DISABLE) != 0;
+}
+
+/**
+ * Gets the status config register.
+ *
+ * @returns status config register.
+ * @param pPciDev The PCI device.
+ */
+DECLINLINE(uint16_t) PDMPciDevGetStatus(PCPDMPCIDEV pPciDev)
+{
+ return PDMPciDevGetWord(pPciDev, VBOX_PCI_STATUS);
+}
+
+/**
+ * Sets the status config register.
+ *
+ * @param pPciDev The PCI device.
+ * @param u16Status The status register value.
+ */
+DECLINLINE(void) PDMPciDevSetStatus(PPDMPCIDEV pPciDev, uint16_t u16Status)
+{
+ PDMPciDevSetWord(pPciDev, VBOX_PCI_STATUS, u16Status);
+}
+
+
+/**
+ * Sets the revision id config register.
+ *
+ * @param pPciDev The PCI device.
+ * @param u8RevisionId The revision id.
+ */
+DECLINLINE(void) PDMPciDevSetRevisionId(PPDMPCIDEV pPciDev, uint8_t u8RevisionId)
+{
+ PDMPciDevSetByte(pPciDev, VBOX_PCI_REVISION_ID, u8RevisionId);
+}
+
+
+/**
+ * Sets the register level programming class config register.
+ *
+ * @param pPciDev The PCI device.
+ * @param u8ClassProg The new value.
+ */
+DECLINLINE(void) PDMPciDevSetClassProg(PPDMPCIDEV pPciDev, uint8_t u8ClassProg)
+{
+ PDMPciDevSetByte(pPciDev, VBOX_PCI_CLASS_PROG, u8ClassProg);
+}
+
+
+/**
+ * Sets the sub-class (aka device class) config register.
+ *
+ * @param pPciDev The PCI device.
+ * @param u8SubClass The sub-class.
+ */
+DECLINLINE(void) PDMPciDevSetClassSub(PPDMPCIDEV pPciDev, uint8_t u8SubClass)
+{
+ PDMPciDevSetByte(pPciDev, VBOX_PCI_CLASS_SUB, u8SubClass);
+}
+
+
+/**
+ * Sets the base class config register.
+ *
+ * @param pPciDev The PCI device.
+ * @param u8BaseClass The base class.
+ */
+DECLINLINE(void) PDMPciDevSetClassBase(PPDMPCIDEV pPciDev, uint8_t u8BaseClass)
+{
+ PDMPciDevSetByte(pPciDev, VBOX_PCI_CLASS_BASE, u8BaseClass);
+}
+
+/**
+ * Sets the header type config register.
+ *
+ * @param pPciDev The PCI device.
+ * @param u8HdrType The header type.
+ */
+DECLINLINE(void) PDMPciDevSetHeaderType(PPDMPCIDEV pPciDev, uint8_t u8HdrType)
+{
+ PDMPciDevSetByte(pPciDev, VBOX_PCI_HEADER_TYPE, u8HdrType);
+}
+
+/**
+ * Gets the header type config register.
+ *
+ * @param pPciDev The PCI device.
+ * @returns u8HdrType The header type.
+ */
+DECLINLINE(uint8_t) PDMPciDevGetHeaderType(PCPDMPCIDEV pPciDev)
+{
+ return PDMPciDevGetByte(pPciDev, VBOX_PCI_HEADER_TYPE);
+}
+
+/**
+ * Sets the BIST (built-in self-test) config register.
+ *
+ * @param pPciDev The PCI device.
+ * @param u8Bist The BIST value.
+ */
+DECLINLINE(void) PDMPciDevSetBIST(PPDMPCIDEV pPciDev, uint8_t u8Bist)
+{
+ PDMPciDevSetByte(pPciDev, VBOX_PCI_BIST, u8Bist);
+}
+
+/**
+ * Gets the BIST (built-in self-test) config register.
+ *
+ * @param pPciDev The PCI device.
+ * @returns u8Bist The BIST.
+ */
+DECLINLINE(uint8_t) PDMPciDevGetBIST(PCPDMPCIDEV pPciDev)
+{
+ return PDMPciDevGetByte(pPciDev, VBOX_PCI_BIST);
+}
+
+
+/**
+ * Sets a base address config register.
+ *
+ * @param pPciDev The PCI device.
+ * @param iReg Base address register number (0..5).
+ * @param fIOSpace Whether it's I/O (true) or memory (false) space.
+ * @param fPrefetchable Whether the memory is prefetachable. Must be false if fIOSpace == true.
+ * @param f64Bit Whether the memory can be mapped anywhere in the 64-bit address space. Otherwise restrict to 32-bit.
+ * @param u32Addr The address value.
+ */
+DECLINLINE(void) PDMPciDevSetBaseAddress(PPDMPCIDEV pPciDev, uint8_t iReg, bool fIOSpace, bool fPrefetchable, bool f64Bit,
+ uint32_t u32Addr)
+{
+ if (fIOSpace)
+ {
+ Assert(!(u32Addr & 0x3)); Assert(!fPrefetchable); Assert(!f64Bit);
+ u32Addr |= RT_BIT_32(0);
+ }
+ else
+ {
+ Assert(!(u32Addr & 0xf));
+ if (fPrefetchable)
+ u32Addr |= RT_BIT_32(3);
+ if (f64Bit)
+ u32Addr |= 0x2 << 1;
+ }
+ switch (iReg)
+ {
+ case 0: iReg = VBOX_PCI_BASE_ADDRESS_0; break;
+ case 1: iReg = VBOX_PCI_BASE_ADDRESS_1; break;
+ case 2: iReg = VBOX_PCI_BASE_ADDRESS_2; break;
+ case 3: iReg = VBOX_PCI_BASE_ADDRESS_3; break;
+ case 4: iReg = VBOX_PCI_BASE_ADDRESS_4; break;
+ case 5: iReg = VBOX_PCI_BASE_ADDRESS_5; break;
+ default: AssertFailedReturnVoid();
+ }
+
+ PDMPciDevSetDWord(pPciDev, iReg, u32Addr);
+}
+
+/**
+ * Please document me. I don't seem to be getting as much as calculating
+ * the address of some PCI region.
+ */
+DECLINLINE(uint32_t) PDMPciDevGetRegionReg(uint32_t iRegion)
+{
+ return iRegion == VBOX_PCI_ROM_SLOT
+ ? VBOX_PCI_ROM_ADDRESS : (VBOX_PCI_BASE_ADDRESS_0 + iRegion * 4);
+}
+
+/**
+ * Sets the sub-system vendor id config register.
+ *
+ * @param pPciDev The PCI device.
+ * @param u16SubSysVendorId The sub-system vendor id.
+ */
+DECLINLINE(void) PDMPciDevSetSubSystemVendorId(PPDMPCIDEV pPciDev, uint16_t u16SubSysVendorId)
+{
+ PDMPciDevSetWord(pPciDev, VBOX_PCI_SUBSYSTEM_VENDOR_ID, u16SubSysVendorId);
+}
+
+/**
+ * Gets the sub-system vendor id config register.
+ * @returns the sub-system vendor id.
+ * @param pPciDev The PCI device.
+ */
+DECLINLINE(uint16_t) PDMPciDevGetSubSystemVendorId(PCPDMPCIDEV pPciDev)
+{
+ return PDMPciDevGetWord(pPciDev, VBOX_PCI_SUBSYSTEM_VENDOR_ID);
+}
+
+
+/**
+ * Sets the sub-system id config register.
+ *
+ * @param pPciDev The PCI device.
+ * @param u16SubSystemId The sub-system id.
+ */
+DECLINLINE(void) PDMPciDevSetSubSystemId(PPDMPCIDEV pPciDev, uint16_t u16SubSystemId)
+{
+ PDMPciDevSetWord(pPciDev, VBOX_PCI_SUBSYSTEM_ID, u16SubSystemId);
+}
+
+/**
+ * Gets the sub-system id config register.
+ * @returns the sub-system id.
+ * @param pPciDev The PCI device.
+ */
+DECLINLINE(uint16_t) PDMPciDevGetSubSystemId(PCPDMPCIDEV pPciDev)
+{
+ return PDMPciDevGetWord(pPciDev, VBOX_PCI_SUBSYSTEM_ID);
+}
+
+/**
+ * Sets offset to capability list.
+ *
+ * @param pPciDev The PCI device.
+ * @param u8Offset The offset to capability list.
+ */
+DECLINLINE(void) PDMPciDevSetCapabilityList(PPDMPCIDEV pPciDev, uint8_t u8Offset)
+{
+ PDMPciDevSetByte(pPciDev, VBOX_PCI_CAPABILITY_LIST, u8Offset);
+}
+
+/**
+ * Returns offset to capability list.
+ *
+ * @returns offset to capability list.
+ * @param pPciDev The PCI device.
+ */
+DECLINLINE(uint8_t) PDMPciDevGetCapabilityList(PCPDMPCIDEV pPciDev)
+{
+ return PDMPciDevGetByte(pPciDev, VBOX_PCI_CAPABILITY_LIST);
+}
+
+/**
+ * Sets the interrupt line config register.
+ *
+ * @param pPciDev The PCI device.
+ * @param u8Line The interrupt line.
+ */
+DECLINLINE(void) PDMPciDevSetInterruptLine(PPDMPCIDEV pPciDev, uint8_t u8Line)
+{
+ PDMPciDevSetByte(pPciDev, VBOX_PCI_INTERRUPT_LINE, u8Line);
+}
+
+/**
+ * Gets the interrupt line config register.
+ *
+ * @returns The interrupt line.
+ * @param pPciDev The PCI device.
+ */
+DECLINLINE(uint8_t) PDMPciDevGetInterruptLine(PCPDMPCIDEV pPciDev)
+{
+ return PDMPciDevGetByte(pPciDev, VBOX_PCI_INTERRUPT_LINE);
+}
+
+/**
+ * Sets the interrupt pin config register.
+ *
+ * @param pPciDev The PCI device.
+ * @param u8Pin The interrupt pin.
+ */
+DECLINLINE(void) PDMPciDevSetInterruptPin(PPDMPCIDEV pPciDev, uint8_t u8Pin)
+{
+ PDMPciDevSetByte(pPciDev, VBOX_PCI_INTERRUPT_PIN, u8Pin);
+}
+
+/**
+ * Gets the interrupt pin config register.
+ *
+ * @returns The interrupt pin.
+ * @param pPciDev The PCI device.
+ */
+DECLINLINE(uint8_t) PDMPciDevGetInterruptPin(PCPDMPCIDEV pPciDev)
+{
+ return PDMPciDevGetByte(pPciDev, VBOX_PCI_INTERRUPT_PIN);
+}
+
+/** @} */
+
+/** @name Aliases for old function names.
+ * @{
+ */
+#if !defined(PDMPCIDEVICE_NO_DEPRECATED) || defined(DOXYGEN_RUNNING)
+# define PCIDevSetByte PDMPciDevSetByte
+# define PCIDevGetByte PDMPciDevGetByte
+# define PCIDevSetWord PDMPciDevSetWord
+# define PCIDevGetWord PDMPciDevGetWord
+# define PCIDevSetDWord PDMPciDevSetDWord
+# define PCIDevGetDWord PDMPciDevGetDWord
+# define PCIDevSetQWord PDMPciDevSetQWord
+# define PCIDevGetQWord PDMPciDevGetQWord
+# define PCIDevSetVendorId PDMPciDevSetVendorId
+# define PCIDevGetVendorId PDMPciDevGetVendorId
+# define PCIDevSetDeviceId PDMPciDevSetDeviceId
+# define PCIDevGetDeviceId PDMPciDevGetDeviceId
+# define PCIDevSetCommand PDMPciDevSetCommand
+# define PCIDevGetCommand PDMPciDevGetCommand
+# define PCIDevIsBusmaster PDMPciDevIsBusmaster
+# define PCIDevIsIntxDisabled PDMPciDevIsIntxDisabled
+# define PCIDevGetStatus PDMPciDevGetStatus
+# define PCIDevSetStatus PDMPciDevSetStatus
+# define PCIDevSetRevisionId PDMPciDevSetRevisionId
+# define PCIDevSetClassProg PDMPciDevSetClassProg
+# define PCIDevSetClassSub PDMPciDevSetClassSub
+# define PCIDevSetClassBase PDMPciDevSetClassBase
+# define PCIDevSetHeaderType PDMPciDevSetHeaderType
+# define PCIDevGetHeaderType PDMPciDevGetHeaderType
+# define PCIDevSetBIST PDMPciDevSetBIST
+# define PCIDevGetBIST PDMPciDevGetBIST
+# define PCIDevSetBaseAddress PDMPciDevSetBaseAddress
+# define PCIDevGetRegionReg PDMPciDevGetRegionReg
+# define PCIDevSetSubSystemVendorId PDMPciDevSetSubSystemVendorId
+# define PCIDevGetSubSystemVendorId PDMPciDevGetSubSystemVendorId
+# define PCIDevSetSubSystemId PDMPciDevSetSubSystemId
+# define PCIDevGetSubSystemId PDMPciDevGetSubSystemId
+# define PCIDevSetCapabilityList PDMPciDevSetCapabilityList
+# define PCIDevGetCapabilityList PDMPciDevGetCapabilityList
+# define PCIDevSetInterruptLine PDMPciDevSetInterruptLine
+# define PCIDevGetInterruptLine PDMPciDevGetInterruptLine
+# define PCIDevSetInterruptPin PDMPciDevSetInterruptPin
+# define PCIDevGetInterruptPin PDMPciDevGetInterruptPin
+#endif
+/** @} */
+
+
+/** @name PDMIICH9BRIDGEPDMPCIDEV_IID - Ugly 3rd party bridge/raw PCI hack.
+ *
+ * When querying this IID via IBase::pfnQueryInterface on a ICH9 bridge, you
+ * will get a pointer to a PDMPCIDEV rather pointer to an interface function
+ * table as is the custom. This was needed by some unusual 3rd-party raw and/or
+ * pass-through implementation which need to provide different PCI configuration
+ * space content for bridges (as long as we don't allow pass-through of bridges
+ * or custom bridge device implementations). So, HACK ALERT to all of this!
+ * @{ */
+#define PDMIICH9BRIDGEPDMPCIDEV_IID "785c74b1-8510-4458-9422-56750bf221db"
+typedef PPDMPCIDEV PPDMIICH9BRIDGEPDMPCIDEV;
+typedef PDMPCIDEV PDMIICH9BRIDGEPDMPCIDEV;
+/** @} */
+
+
+/** @} */
+
+#endif /* !VBOX_INCLUDED_vmm_pdmpcidev_h */
diff --git a/include/VBox/vmm/pdmpcidevint.h b/include/VBox/vmm/pdmpcidevint.h
new file mode 100644
index 00000000..b678bf05
--- /dev/null
+++ b/include/VBox/vmm/pdmpcidevint.h
@@ -0,0 +1,238 @@
+/* $Id: pdmpcidevint.h $ */
+/** @file
+ * DevPCI - PDM PCI Internal header - Only for hiding bits of PDMPCIDEV.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vmm_pdmpcidevint_h
+#define VBOX_INCLUDED_vmm_pdmpcidevint_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/vmm/pdmdev.h>
+
+/** @defgroup grp_pdm_pcidev_int The PDM PCI Device Internals
+ * @ingroup grp_pdm_pcidev
+ *
+ * @remarks The PDM PCI device internals are visible to both PDM and the PCI Bus
+ * implementation, thus it lives among the the public headers despite
+ * being rather private and internal.
+ *
+ * @{
+ */
+
+
+/**
+ * PCI I/O region.
+ */
+typedef struct PCIIOREGION
+{
+ /** Current PCI mapping address, INVALID_PCI_ADDRESS (0xffffffff) means not mapped. */
+ uint64_t addr;
+ /** The region size. Power of 2. */
+ uint64_t size;
+ /** Handle or UINT64_MAX (see PDMPCIDEV_IORGN_F_HANDLE_MASK in fFlags). */
+ uint64_t hHandle;
+ /** PDMPCIDEV_IORGN_F_XXXX. */
+ uint32_t fFlags;
+ /** PCIADDRESSSPACE */
+ uint8_t type;
+ uint8_t abPadding0[3];
+ /** Callback called when the region is mapped or unmapped (new style devs). */
+ R3PTRTYPE(PFNPCIIOREGIONMAP) pfnMap;
+#if R3_ARCH_BITS == 32
+ uint32_t u32Padding2;
+#endif
+} PCIIOREGION;
+AssertCompileSize(PCIIOREGION, 5*8);
+/** Pointer to a PCI I/O region. */
+typedef PCIIOREGION *PPCIIOREGION;
+/** Pointer to a const PCI I/O region. */
+typedef PCIIOREGION const *PCPCIIOREGION;
+
+/**
+ * Callback function for reading from the PCI configuration space.
+ *
+ * @returns Strict VBox status code.
+ * @param pDevIns Pointer to the device instance of the PCI bus.
+ * @param iBus The bus number this device is on.
+ * @param iDevice The number of the device on the bus.
+ * @param u32Address The configuration space register address. [0..255]
+ * @param cb The register size. [1,2,4]
+ * @param pu32Value Where to return the register value.
+ */
+typedef DECLCALLBACKTYPE(VBOXSTRICTRC, FNPCIBRIDGECONFIGREAD,(PPDMDEVINSR3 pDevIns, uint8_t iBus, uint8_t iDevice,
+ uint32_t u32Address, unsigned cb, uint32_t *pu32Value));
+/** Pointer to a FNPCICONFIGREAD() function. */
+typedef FNPCIBRIDGECONFIGREAD *PFNPCIBRIDGECONFIGREAD;
+#if !RT_CLANG_PREREQ(11, 0) /* Clang 11 (at least) has trouble with nothrow and pointers to function pointers. */
+/** Pointer to a PFNPCICONFIGREAD. */
+typedef PFNPCIBRIDGECONFIGREAD *PPFNPCIBRIDGECONFIGREAD;
+#endif
+
+/**
+ * Callback function for writing to the PCI configuration space.
+ *
+ * @returns Strict VBox status code.
+ * @param pDevIns Pointer to the device instance of the PCI bus.
+ * @param iBus The bus number this device is on.
+ * @param iDevice The number of the device on the bus.
+ * @param u32Address The configuration space register address. [0..255]
+ * @param cb The register size. [1,2,4]
+ * @param u32Value The value that's being written. The number of bits actually used from
+ * this value is determined by the cb parameter.
+ */
+typedef DECLCALLBACKTYPE(VBOXSTRICTRC, FNPCIBRIDGECONFIGWRITE,(PPDMDEVINSR3 pDevIns, uint8_t iBus, uint8_t iDevice,
+ uint32_t u32Address, unsigned cb, uint32_t u32Value));
+/** Pointer to a FNPCICONFIGWRITE() function. */
+typedef FNPCIBRIDGECONFIGWRITE *PFNPCIBRIDGECONFIGWRITE;
+#if !RT_CLANG_PREREQ(11, 0) /* Clang 11 (at least) has trouble with nothrow and pointers to function pointers. */
+/** Pointer to a PFNPCICONFIGWRITE. */
+typedef PFNPCIBRIDGECONFIGWRITE *PPFNPCIBRIDGECONFIGWRITE;
+#endif
+
+/* Forward declaration */
+struct DEVPCIBUS;
+
+enum {
+ /** Flag whether the device is a pci-to-pci bridge.
+ * This is set prior to device registration. */
+ PCIDEV_FLAG_PCI_TO_PCI_BRIDGE = RT_BIT_32(1),
+ /** Flag whether the device is a PCI Express device.
+ * This is set prior to device registration. */
+ PCIDEV_FLAG_PCI_EXPRESS_DEVICE = RT_BIT_32(2),
+ /** Flag whether the device is capable of MSI.
+ * This one is set by MsiInit(). */
+ PCIDEV_FLAG_MSI_CAPABLE = RT_BIT_32(3),
+ /** Flag whether the device is capable of MSI-X.
+ * This one is set by MsixInit(). */
+ PCIDEV_FLAG_MSIX_CAPABLE = RT_BIT_32(4),
+ /** Flag if device represents real physical device in passthrough mode. */
+ PCIDEV_FLAG_PASSTHROUGH = RT_BIT_32(5),
+ /** Flag whether the device is capable of MSI using 64-bit address. */
+ PCIDEV_FLAG_MSI64_CAPABLE = RT_BIT_32(6)
+
+};
+
+
+/**
+ * PDM PCI Device - Internal data.
+ *
+ * @sa PDMPCIDEV
+ */
+typedef struct PDMPCIDEVINT
+{
+ /** @name Owned by PDM.
+ * @remarks The bus may use the device instance pointers.
+ * @{
+ */
+ /** Pointer to the PDM device the PCI device belongs to. (R3 ptr) */
+ PPDMDEVINSR3 pDevInsR3;
+ /** The CFGM device configuration index (default, PciDev1..255).
+ * This also works as the internal sub-device ordinal with MMIOEx.
+ * @note Same value as idxSubDev, can therefore be removed later. */
+ uint8_t idxDevCfg;
+ /** Set if the it can be reassigned to a different PCI device number. */
+ bool fReassignableDevNo;
+ /** Set if the it can be reassigned to a different PCI function number. */
+ bool fReassignableFunNo;
+ /** Alignment padding - used by ICH9 for region swapping (DevVGA hack). */
+ uint8_t bPadding0;
+ /** Index into the PDM internal bus array (PDM::aPciBuses). */
+ uint8_t idxPdmBus;
+ /** Set if this device has been registered. */
+ bool fRegistered;
+ /** Index into PDMDEVINSR3::apPciDevs (same as PDMPCIDEV::idxSubDev). */
+ uint16_t idxSubDev;
+ /** @} */
+
+ /** @name Owned by the PCI Bus
+ * @remarks PDM will not touch anything here (includes not relocating anything).
+ * @{
+ */
+ /** Pointer to the PCI bus of the device. (R3 ptr) */
+ R3PTRTYPE(struct DEVPCIBUS *) pBusR3;
+ /** Read config callback. */
+ R3PTRTYPE(PFNPCICONFIGREAD) pfnConfigRead;
+ /** Write config callback. */
+ R3PTRTYPE(PFNPCICONFIGWRITE) pfnConfigWrite;
+ /** Read config callback for PCI bridges to pass requests
+ * to devices on another bus. */
+ R3PTRTYPE(PFNPCIBRIDGECONFIGREAD) pfnBridgeConfigRead;
+ /** Write config callback for PCI bridges to pass requests
+ * to devices on another bus. */
+ R3PTRTYPE(PFNPCIBRIDGECONFIGWRITE) pfnBridgeConfigWrite;
+
+ /** Flags of this PCI device, see PCIDEV_FLAG_XXX constants. */
+ uint32_t fFlags;
+ /** Current state of the IRQ pin of the device. */
+ int32_t uIrqPinState;
+
+ /** Offset of MSI PCI capability in config space, or 0.
+ * @todo fix non-standard naming. */
+ uint8_t u8MsiCapOffset;
+ /** Size of MSI PCI capability in config space, or 0.
+ * @todo fix non-standard naming. */
+ uint8_t u8MsiCapSize;
+ /** Offset of MSI-X PCI capability in config space, or 0.
+ * @todo fix non-standard naming. */
+ uint8_t u8MsixCapOffset;
+ /** Size of MSI-X PCI capability in config space, or 0.
+ * @todo fix non-standard naming. */
+ uint8_t u8MsixCapSize;
+ /** Size of the MSI-X region. */
+ uint16_t cbMsixRegion;
+ /** Offset to the PBA for MSI-X. */
+ uint16_t offMsixPba;
+ /** Add padding to align aIORegions to an 16 byte boundary. */
+ uint8_t abPadding2[HC_ARCH_BITS == 32 ? 12 : 8];
+ /** The MMIO handle for the MSI-X MMIO bar. */
+ IOMMMIOHANDLE hMmioMsix;
+
+ /** Pointer to bus specific data. (R3 ptr) */
+ R3PTRTYPE(const void *) pvPciBusPtrR3;
+ /** I/O regions. */
+ PCIIOREGION aIORegions[VBOX_PCI_NUM_REGIONS];
+ /** @} */
+} PDMPCIDEVINT;
+AssertCompileMemberAlignment(PDMPCIDEVINT, aIORegions, 8);
+AssertCompileSize(PDMPCIDEVINT, HC_ARCH_BITS == 32 ? 0x98 : 0x178);
+
+/** Indicate that PDMPCIDEV::Int.s can be declared. */
+#define PDMPCIDEVINT_DECLARED
+
+/** @} */
+
+#endif /* !VBOX_INCLUDED_vmm_pdmpcidevint_h */
+
diff --git a/include/VBox/vmm/pdmqueue.h b/include/VBox/vmm/pdmqueue.h
new file mode 100644
index 00000000..a932ec28
--- /dev/null
+++ b/include/VBox/vmm/pdmqueue.h
@@ -0,0 +1,169 @@
+/** @file
+ * PDM - Pluggable Device Manager, Queues.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vmm_pdmqueue_h
+#define VBOX_INCLUDED_vmm_pdmqueue_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/types.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_pdm_queue The PDM Queues API
+ * @ingroup grp_pdm
+ * @{
+ */
+
+/** Pointer to a PDM queue. */
+typedef struct PDMQUEUE *PPDMQUEUE;
+
+/** Pointer to a PDM queue item core. */
+typedef union PDMQUEUEITEMCORE *PPDMQUEUEITEMCORE;
+
+/**
+ * PDM queue item core.
+ */
+typedef union PDMQUEUEITEMCORE
+{
+ /** The next queue item on the pending list (UINT32_MAX for NIL). */
+ uint32_t volatile iNext;
+ /** The next item about to be flushed. */
+ R3PTRTYPE(PPDMQUEUEITEMCORE) pNext;
+ /** Make sure the core is 64-bit wide. */
+ uint64_t u64View;
+} PDMQUEUEITEMCORE;
+
+
+/**
+ * Queue consumer callback for devices.
+ *
+ * @returns Success indicator.
+ * If false the item will not be removed and the flushing will stop.
+ * @param pDevIns The device instance.
+ * @param pItem The item to consume. Upon return this item will be freed.
+ * @remarks The device critical section will NOT be entered before calling the
+ * callback. No locks will be held, but for now it's safe to assume
+ * that only one EMT will do queue callbacks at any one time.
+ */
+typedef DECLCALLBACKTYPE(bool, FNPDMQUEUEDEV,(PPDMDEVINS pDevIns, PPDMQUEUEITEMCORE pItem));
+/** Pointer to a FNPDMQUEUEDEV(). */
+typedef FNPDMQUEUEDEV *PFNPDMQUEUEDEV;
+
+/**
+ * Queue consumer callback for USB devices.
+ *
+ * @returns Success indicator.
+ * If false the item will not be removed and the flushing will stop.
+ * @param pUsbIns The USB device instance.
+ * @param pItem The item to consume. Upon return this item will be freed.
+ * @remarks No locks will be held, but for now it's safe to assume that only one
+ * EMT will do queue callbacks at any one time.
+ */
+typedef DECLCALLBACKTYPE(bool, FNPDMQUEUEUSB,(PPDMUSBINS pUsbIns, PPDMQUEUEITEMCORE pItem));
+/** Pointer to a FNPDMQUEUEUSB(). */
+typedef FNPDMQUEUEUSB *PFNPDMQUEUEUSB;
+
+/**
+ * Queue consumer callback for drivers.
+ *
+ * @returns Success indicator.
+ * If false the item will not be removed and the flushing will stop.
+ * @param pDrvIns The driver instance.
+ * @param pItem The item to consume. Upon return this item will be freed.
+ * @remarks No locks will be held, but for now it's safe to assume that only one
+ * EMT will do queue callbacks at any one time.
+ */
+typedef DECLCALLBACKTYPE(bool, FNPDMQUEUEDRV,(PPDMDRVINS pDrvIns, PPDMQUEUEITEMCORE pItem));
+/** Pointer to a FNPDMQUEUEDRV(). */
+typedef FNPDMQUEUEDRV *PFNPDMQUEUEDRV;
+
+/**
+ * Queue consumer callback for internal component.
+ *
+ * @returns Success indicator.
+ * If false the item will not be removed and the flushing will stop.
+ * @param pVM The cross context VM structure.
+ * @param pItem The item to consume. Upon return this item will be freed.
+ * @remarks No locks will be held, but for now it's safe to assume that only one
+ * EMT will do queue callbacks at any one time.
+ */
+typedef DECLCALLBACKTYPE(bool, FNPDMQUEUEINT,(PVM pVM, PPDMQUEUEITEMCORE pItem));
+/** Pointer to a FNPDMQUEUEINT(). */
+typedef FNPDMQUEUEINT *PFNPDMQUEUEINT;
+
+/**
+ * Queue consumer callback for external component.
+ *
+ * @returns Success indicator.
+ * If false the item will not be removed and the flushing will stop.
+ * @param pvUser User argument.
+ * @param pItem The item to consume. Upon return this item will be freed.
+ * @remarks No locks will be held, but for now it's safe to assume that only one
+ * EMT will do queue callbacks at any one time.
+ */
+typedef DECLCALLBACKTYPE(bool, FNPDMQUEUEEXT,(void *pvUser, PPDMQUEUEITEMCORE pItem));
+/** Pointer to a FNPDMQUEUEEXT(). */
+typedef FNPDMQUEUEEXT *PFNPDMQUEUEEXT;
+
+#ifdef VBOX_IN_VMM
+VMMR3_INT_DECL(int) PDMR3QueueCreateDevice(PVM pVM, PPDMDEVINS pDevIns, size_t cbItem, uint32_t cItems,
+ uint32_t cMilliesInterval, PFNPDMQUEUEDEV pfnCallback,
+ bool fRZEnabled, const char *pszName, PDMQUEUEHANDLE *phQueue);
+VMMR3_INT_DECL(int) PDMR3QueueCreateDriver(PVM pVM, PPDMDRVINS pDrvIns, size_t cbItem, uint32_t cItems,
+ uint32_t cMilliesInterval, PFNPDMQUEUEDRV pfnCallback,
+ const char *pszName, PDMQUEUEHANDLE *phQueue);
+VMMR3_INT_DECL(int) PDMR3QueueCreateInternal(PVM pVM, size_t cbItem, uint32_t cItems,
+ uint32_t cMilliesInterval, PFNPDMQUEUEINT pfnCallback,
+ bool fRZEnabled, const char *pszName, PDMQUEUEHANDLE *phQueue);
+VMMR3DECL(int) PDMR3QueueCreateExternal(PVM pVM, size_t cbItem, uint32_t cItems, uint32_t cMilliesInterval,
+ PFNPDMQUEUEEXT pfnCallback, void *pvUser, const char *pszName, PDMQUEUEHANDLE *phQueue);
+VMMR3DECL(int) PDMR3QueueDestroy(PVM pVM, PDMQUEUEHANDLE hQueue, void *pvOwner);
+VMMR3_INT_DECL(int) PDMR3QueueDestroyDevice(PVM pVM, PPDMDEVINS pDevIns);
+VMMR3_INT_DECL(int) PDMR3QueueDestroyDriver(PVM pVM, PPDMDRVINS pDrvIns);
+VMMR3DECL(void) PDMR3QueueFlushAll(PVM pVM);
+#endif /* VBOX_IN_VMM */
+
+VMMDECL(PPDMQUEUEITEMCORE) PDMQueueAlloc(PVMCC pVM, PDMQUEUEHANDLE hQueue, void *pvOwner);
+VMMDECL(int) PDMQueueInsert(PVMCC pVM, PDMQUEUEHANDLE hQueue, void *pvOwner, PPDMQUEUEITEMCORE pInsert);
+VMMDECL(int) PDMQueueFlushIfNecessary(PVMCC pVM, PDMQUEUEHANDLE hQueue, void *pvOwner);
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !VBOX_INCLUDED_vmm_pdmqueue_h */
+
diff --git a/include/VBox/vmm/pdmserialifs.h b/include/VBox/vmm/pdmserialifs.h
new file mode 100644
index 00000000..3917e0e5
--- /dev/null
+++ b/include/VBox/vmm/pdmserialifs.h
@@ -0,0 +1,249 @@
+/** @file
+ * PDM - Pluggable Device Manager, Serial port related interfaces.
+ */
+
+/*
+ * Copyright (C) 2018-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vmm_pdmserialifs_h
+#define VBOX_INCLUDED_vmm_pdmserialifs_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/types.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_pdm_ifs_serial PDM Serial Port Interfaces
+ * @ingroup grp_pdm_interfaces
+ * @{
+ */
+
+
+/** @name Bit mask definitions for status line type.
+ * @{ */
+#define PDMISERIALPORT_STS_LINE_DCD RT_BIT(0)
+#define PDMISERIALPORT_STS_LINE_RI RT_BIT(1)
+#define PDMISERIALPORT_STS_LINE_DSR RT_BIT(2)
+#define PDMISERIALPORT_STS_LINE_CTS RT_BIT(3)
+/** @} */
+
+/** Pointer to a serial port interface. */
+typedef struct PDMISERIALPORT *PPDMISERIALPORT;
+/**
+ * Serial port interface (down).
+ */
+typedef struct PDMISERIALPORT
+{
+ /**
+ * Notifies the upper device/driver that data is available for reading.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param cbAvail The amount of data available to be written.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnDataAvailRdrNotify, (PPDMISERIALPORT pInterface, size_t cbAvail));
+
+ /**
+ * Notifies the upper device/driver that all data was sent.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnDataSentNotify, (PPDMISERIALPORT pInterface));
+
+ /**
+ * Try to read data from the device/driver above for writing.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pvBuf Where to store the read data.
+ * @param cbRead How much to read.
+ * @param pcbRead Where to store the amount of data actually read on success.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnReadWr, (PPDMISERIALPORT pInterface, void *pvBuf, size_t cbRead, size_t *pcbRead));
+
+ /**
+ * Notify the device/driver when the status lines changed.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param fNewStatusLines New state of the status line pins.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnNotifyStsLinesChanged, (PPDMISERIALPORT pInterface, uint32_t fNewStatusLines));
+
+ /**
+ * Notify the device/driver that a break condition occurred.
+ *
+ * @returns VBox statsus code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnNotifyBrk, (PPDMISERIALPORT pInterface));
+
+} PDMISERIALPORT;
+/** PDMISERIALPORT interface ID. */
+#define PDMISERIALPORT_IID "44540323-06ca-44c1-8eb2-f5a387704dbd"
+
+
+/**
+ * Supported parity modes.
+ */
+typedef enum PDMSERIALPARITY
+{
+ /** Invalid parity setting. */
+ PDMSERIALPARITY_INVALID = 0,
+ /** No parity. */
+ PDMSERIALPARITY_NONE,
+ /** Even parity. */
+ PDMSERIALPARITY_EVEN,
+ /** Odd parity. */
+ PDMSERIALPARITY_ODD,
+ /** Mark parity. */
+ PDMSERIALPARITY_MARK,
+ /** Space parity. */
+ PDMSERIALPARITY_SPACE,
+ /** 32bit hack. */
+ PDMSERIALPARITY_32BIT_HACK = 0x7fffffff
+} PDMSERIALPARITY;
+
+
+/**
+ * Supported number of stop bits.
+ */
+typedef enum PDMSERIALSTOPBITS
+{
+ /** Invalid stop bits setting. */
+ PDMSERIALSTOPBITS_INVALID = 0,
+ /** One stop bit is used. */
+ PDMSERIALSTOPBITS_ONE,
+ /** 1.5 stop bits are used. */
+ PDMSERIALSTOPBITS_ONEPOINTFIVE,
+ /** 2 stop bits are used. */
+ PDMSERIALSTOPBITS_TWO,
+ /** 32bit hack. */
+ PDMSERIALSTOPBITS_32BIT_HACK = 0x7fffffff
+} PDMSERIALSTOPBITS;
+
+
+/** Pointer to a serial interface. */
+typedef struct PDMISERIALCONNECTOR *PPDMISERIALCONNECTOR;
+/**
+ * Serial interface (up).
+ * Pairs with PDMISERIALPORT.
+ */
+typedef struct PDMISERIALCONNECTOR
+{
+ /**
+ * Notifies the lower layer that data is available for writing.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnDataAvailWrNotify, (PPDMISERIALCONNECTOR pInterface));
+
+ /**
+ * Try to read data from the underyling driver.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pvBuf Where to store the read data.
+ * @param cbRead How much to read.
+ * @param pcbRead Where to store the amount of data actually read on success.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnReadRdr, (PPDMISERIALCONNECTOR pInterface, void *pvBuf, size_t cbRead, size_t *pcbRead));
+
+ /**
+ * Change device parameters.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param uBps Speed of the serial connection. (bits per second)
+ * @param enmParity Parity method.
+ * @param cDataBits Number of data bits.
+ * @param enmStopBits Number of stop bits.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnChgParams, (PPDMISERIALCONNECTOR pInterface, uint32_t uBps,
+ PDMSERIALPARITY enmParity, unsigned cDataBits,
+ PDMSERIALSTOPBITS enmStopBits));
+
+ /**
+ * Set the state of the modem lines.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param fRts Set to true to make the Request to Send line active otherwise to 0.
+ * @param fDtr Set to true to make the Data Terminal Ready line active otherwise 0.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnChgModemLines, (PPDMISERIALCONNECTOR pInterface, bool fRts, bool fDtr));
+
+ /**
+ * Changes the TD line into the requested break condition.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param fBrk Set to true to let the device send a break false to put into normal operation.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnChgBrk, (PPDMISERIALCONNECTOR pInterface, bool fBrk));
+
+ /**
+ * Queries the current state of the status lines.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pfStsLines Where to store the status line states on success.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnQueryStsLines, (PPDMISERIALCONNECTOR pInterface, uint32_t *pfStsLines));
+
+ /**
+ * Flushes the indicated queues.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param fQueueRecv Flag whether to flush the receive queue.
+ * @param fQueueXmit Flag whether to flush the transmit queue.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnQueuesFlush, (PPDMISERIALCONNECTOR pInterface, bool fQueueRecv, bool fQueueXmit));
+
+} PDMISERIALCONNECTOR;
+/** PDMIMEDIA interface ID. */
+#define PDMISERIALCONNECTOR_IID "d024f170-c00d-11e8-b568-0800200c9a66"
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !VBOX_INCLUDED_vmm_pdmserialifs_h */
diff --git a/include/VBox/vmm/pdmsrv.h b/include/VBox/vmm/pdmsrv.h
new file mode 100644
index 00000000..e0b3f7ce
--- /dev/null
+++ b/include/VBox/vmm/pdmsrv.h
@@ -0,0 +1,350 @@
+/** @file
+ * PDM - Pluggable Device Manager, VM Services.
+ *
+ * @todo This has not been implemented, consider dropping the concept.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vmm_pdmsrv_h
+#define VBOX_INCLUDED_vmm_pdmsrv_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/vmm/pdmifs.h>
+#include <VBox/vmm/ssm.h>
+#include <VBox/vmm/cfgm.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_pdm_services The PDM Services API
+ * @ingroup grp_pdm
+ * @{
+ */
+
+/**
+ * Construct a service instance for a VM.
+ *
+ * @returns VBox status.
+ * @param pSrvIns The service instance data.
+ * If the registration structure is needed, pSrvIns->pReg points to it.
+ * @param pCfg Configuration node handle for the service. Use this to obtain the configuration
+ * of the driver instance. It's also found in pSrvIns->pCfg, but since it's primary
+ * usage is expected in this function it is passed as a parameter.
+ */
+typedef DECLCALLBACKTYPE(int, FNPDMSRVCONSTRUCT,(PPDMSRVINS pSrvIns, PCFGMNODE pCfg));
+/** Pointer to a FNPDMSRVCONSTRUCT() function. */
+typedef FNPDMSRVCONSTRUCT *PFNPDMSRVCONSTRUCT;
+
+/**
+ * Destruct a driver instance.
+ *
+ * Most VM resources are freed by the VM. This callback is provided so that any non-VM
+ * resources can be freed correctly.
+ *
+ * @param pSrvIns The service instance data.
+ */
+typedef DECLCALLBACKTYPE(void, FNPDMSRVDESTRUCT,(PPDMSRVINS pSrvIns));
+/** Pointer to a FNPDMSRVDESTRUCT() function. */
+typedef FNPDMSRVDESTRUCT *PFNPDMSRVDESTRUCT;
+
+/**
+ * Power On notification.
+ *
+ * @param pSrvIns The service instance data.
+ */
+typedef DECLCALLBACKTYPE(void, FNPDMSRVPOWERON,(PPDMSRVINS pSrvIns));
+/** Pointer to a FNPDMSRVPOWERON() function. */
+typedef FNPDMSRVPOWERON *PFNPDMSRVPOWERON;
+
+/**
+ * Reset notification.
+ *
+ * @returns VBox status.
+ * @param pSrvIns The service instance data.
+ */
+typedef DECLCALLBACKTYPE(void, FNPDMSRVRESET,(PPDMSRVINS pSrvIns));
+/** Pointer to a FNPDMSRVRESET() function. */
+typedef FNPDMSRVRESET *PFNPDMSRVRESET;
+
+/**
+ * Suspend notification.
+ *
+ * @returns VBox status.
+ * @param pSrvIns The service instance data.
+ */
+typedef DECLCALLBACKTYPE(void, FNPDMSRVSUSPEND,(PPDMSRVINS pSrvIns));
+/** Pointer to a FNPDMSRVSUSPEND() function. */
+typedef FNPDMSRVSUSPEND *PFNPDMSRVSUSPEND;
+
+/**
+ * Resume notification.
+ *
+ * @returns VBox status.
+ * @param pSrvIns The service instance data.
+ */
+typedef DECLCALLBACKTYPE(void, FNPDMSRVRESUME,(PPDMSRVINS pSrvIns));
+/** Pointer to a FNPDMSRVRESUME() function. */
+typedef FNPDMSRVRESUME *PFNPDMSRVRESUME;
+
+/**
+ * Power Off notification.
+ *
+ * @param pSrvIns The service instance data.
+ */
+typedef DECLCALLBACKTYPE(void, FNPDMSRVPOWEROFF,(PPDMSRVINS pSrvIns));
+/** Pointer to a FNPDMSRVPOWEROFF() function. */
+typedef FNPDMSRVPOWEROFF *PFNPDMSRVPOWEROFF;
+
+/**
+ * Detach notification.
+ *
+ * This is called when a driver or device is detached from the service
+ *
+ * @param pSrvIns The service instance data.
+ * @param pDevIns The device instance to detach.
+ * @param pDrvIns The driver instance to detach.
+ */
+typedef DECLCALLBACKTYPE(void, FNPDMSRVDETACH,(PPDMSRVINS pSrvIns, PPDMDEVINS pDevIns, PPDMDRVINS pDrvIns));
+/** Pointer to a FNPDMSRVDETACH() function. */
+typedef FNPDMSRVDETACH *PFNPDMSRVDETACH;
+
+
+
+/** PDM Service Registration Structure,
+ * This structure is used when registering a driver from
+ * VBoxServicesRegister() (HC Ring-3). PDM will continue use till
+ * the VM is terminated.
+ */
+typedef struct PDMSRVREG
+{
+ /** Structure version. PDM_SRVREG_VERSION defines the current version. */
+ uint32_t u32Version;
+ /** Driver name. */
+ char szServiceName[32];
+ /** The description of the driver. The UTF-8 string pointed to shall, like this structure,
+ * remain unchanged from registration till VM destruction. */
+ const char *pszDescription;
+
+ /** Flags, combination of the PDM_SRVREG_FLAGS_* \#defines. */
+ RTUINT fFlags;
+ /** Size of the instance data. */
+ RTUINT cbInstance;
+
+ /** Construct instance - required. */
+ PFNPDMSRVCONSTRUCT pfnConstruct;
+ /** Destruct instance - optional. */
+ PFNPDMSRVDESTRUCT pfnDestruct;
+ /** Power on notification - optional. */
+ PFNPDMSRVPOWERON pfnPowerOn;
+ /** Reset notification - optional. */
+ PFNPDMSRVRESET pfnReset;
+ /** Suspend notification - optional. */
+ PFNPDMSRVSUSPEND pfnSuspend;
+ /** Resume notification - optional. */
+ PFNPDMSRVRESUME pfnResume;
+ /** Detach notification - optional. */
+ PFNPDMSRVDETACH pfnDetach;
+ /** Power off notification - optional. */
+ PFNPDMSRVPOWEROFF pfnPowerOff;
+
+} PDMSRVREG;
+/** Pointer to a PDM Driver Structure. */
+typedef PDMSRVREG *PPDMSRVREG;
+/** Const pointer to a PDM Driver Structure. */
+typedef PDMSRVREG const *PCPDMSRVREG;
+
+
+
+/**
+ * PDM Service API.
+ */
+typedef struct PDMSRVHLP
+{
+ /** Structure version. PDM_SRVHLP_VERSION defines the current version. */
+ uint32_t u32Version;
+
+ /**
+ * Assert that the current thread is the emulation thread.
+ *
+ * @returns True if correct.
+ * @returns False if wrong.
+ * @param pSrvIns Service instance.
+ * @param pszFile Filename of the assertion location.
+ * @param iLine Linenumber of the assertion location.
+ * @param pszFunction Function of the assertion location.
+ */
+ DECLR3CALLBACKMEMBER(bool, pfnAssertEMT,(PPDMSRVINS pSrvIns, const char *pszFile, unsigned iLine, const char *pszFunction));
+
+ /**
+ * Assert that the current thread is NOT the emulation thread.
+ *
+ * @returns True if correct.
+ * @returns False if wrong.
+ * @param pSrvIns Service instance.
+ * @param pszFile Filename of the assertion location.
+ * @param iLine Linenumber of the assertion location.
+ * @param pszFunction Function of the assertion location.
+ */
+ DECLR3CALLBACKMEMBER(bool, pfnAssertOther,(PPDMSRVINS pSrvIns, const char *pszFile, unsigned iLine, const char *pszFunction));
+
+ /**
+ * Creates a timer.
+ *
+ * @returns VBox status.
+ * @param pVM The cross context VM structure.
+ * @param pSrvIns Service instance.
+ * @param enmClock The clock to use on this timer.
+ * @param pfnCallback Callback function.
+ * @param pszDesc Pointer to description string which must stay around
+ * until the timer is fully destroyed (i.e. a bit after TMTimerDestroy()).
+ * @param ppTimer Where to store the timer on success.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnTMTimerCreate,(PPDMSRVINS pSrvIns, TMCLOCK enmClock, PFNTMTIMERDEV pfnCallback, const char *pszDesc, PPTMTIMERR3 ppTimer));
+
+ /**
+ * Query the virtual timer frequency.
+ *
+ * @returns Frequency in Hz.
+ * @param pSrvIns Service instance.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(uint64_t, pfnTMGetVirtualFreq,(PPDMSRVINS pSrvIns));
+
+ /**
+ * Query the virtual time.
+ *
+ * @returns The current virtual time.
+ * @param pSrvIns Service instance.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(uint64_t, pfnTMGetVirtualTime,(PPDMSRVINS pSrvIns));
+
+} PDMSRVHLP;
+/** Pointer PDM Service API. */
+typedef PDMSRVHLP *PPDMSRVHLP;
+/** Pointer const PDM Service API. */
+typedef const PDMSRVHLP *PCPDMSRVHLP;
+
+/** Current SRVHLP version number. */
+#define PDM_SRVHLP_VERSION PDM_VERSION_MAKE(0xdfff, 1, 0)
+
+
+/**
+ * PDM Service Instance.
+ */
+typedef struct PDMSRVINS
+{
+ /** Structure version. PDM_SRVINS_VERSION defines the current version. */
+ uint32_t u32Version;
+
+ /** Internal data. */
+ union
+ {
+#ifdef PDMSRVINSINT_DECLARED
+ PDMSRVINSINT s;
+#endif
+ uint8_t padding[HC_ARCH_BITS == 32 ? 32 : 32];
+ } Internal;
+
+ /** Pointer the PDM Service API. */
+ R3PTRTYPE(PCPDMSRVHLP) pHlp;
+ /** Pointer to driver registration structure. */
+ R3PTRTYPE(PCPDMSRVREG) pReg;
+ /** Configuration handle. */
+ R3PTRTYPE(PCFGMNODE) pCfg;
+ /** The base interface of the service.
+ * The service constructor initializes this. */
+ PDMIBASE IBase;
+ /* padding to make achInstanceData aligned at 16 byte boundary. */
+ uint32_t au32Padding[2];
+ /** Pointer to driver instance data. */
+ R3PTRTYPE(void *) pvInstanceData;
+ /** Driver instance data. The size of this area is defined
+ * in the PDMSRVREG::cbInstanceData field. */
+ char achInstanceData[4];
+} PDMSRVINS;
+
+/** Current PDMSRVREG version number. */
+#define PDM_SRVINS_VERSION PDM_VERSION_MAKE(0xdffe, 1, 0)
+
+/** Converts a pointer to the PDMSRVINS::IBase to a pointer to PDMSRVINS. */
+#define PDMIBASE_2_PDMSRV(pInterface) ( (PPDMSRVINS)((char *)(pInterface) - RT_UOFFSETOF(PDMSRVINS, IBase)) )
+
+
+
+/** Pointer to callbacks provided to the VBoxServiceRegister() call. */
+typedef struct PDMSRVREGCB *PPDMSRVREGCB;
+
+/**
+ * Callbacks for VBoxServiceRegister().
+ */
+typedef struct PDMSRVREGCB
+{
+ /** Interface version.
+ * This is set to PDM_SRVREG_CB_VERSION. */
+ uint32_t u32Version;
+
+ /**
+ * Registers a service with the current VM instance.
+ *
+ * @returns VBox status code.
+ * @param pCallbacks Pointer to the callback table.
+ * @param pSrvReg Pointer to the device registration record.
+ * This data must be permanent and readonly.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnRegister,(PPDMSRVREGCB pCallbacks, PCPDMSRVREG pSrvReg));
+} PDMSRVREGCB;
+
+/** Current version of the PDMSRVREGCB structure. */
+#define PDM_SRVREG_CB_VERSION PDM_VERSION_MAKE(0xdffd, 1, 0)
+
+
+/**
+ * The VBoxServicesRegister callback function.
+ *
+ * PDM will invoke this function after loading a device module and letting
+ * the module decide which devices to register and how to handle conflicts.
+ *
+ * @returns VBox status code.
+ * @param pCallbacks Pointer to the callback table.
+ * @param u32Version VBox version number.
+ */
+typedef DECLCALLBACKTYPE(int, FNPDMVBOXSERVICESREGISTER,(PPDMSRVREGCB pCallbacks, uint32_t u32Version));
+
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !VBOX_INCLUDED_vmm_pdmsrv_h */
diff --git a/include/VBox/vmm/pdmstorageifs.h b/include/VBox/vmm/pdmstorageifs.h
new file mode 100644
index 00000000..2aeeed99
--- /dev/null
+++ b/include/VBox/vmm/pdmstorageifs.h
@@ -0,0 +1,1059 @@
+/** @file
+ * PDM - Pluggable Device Manager, Storage related interfaces.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vmm_pdmstorageifs_h
+#define VBOX_INCLUDED_vmm_pdmstorageifs_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/sg.h>
+#include <VBox/types.h>
+#include <VBox/vdmedia.h>
+
+RT_C_DECLS_BEGIN
+
+struct PDMISECKEY;
+struct PDMISECKEYHLP;
+
+
+/** @defgroup grp_pdm_ifs_storage PDM Storage Interfaces
+ * @ingroup grp_pdm_interfaces
+ * @{
+ */
+
+
+/** Pointer to a mount interface. */
+typedef struct PDMIMOUNTNOTIFY *PPDMIMOUNTNOTIFY;
+/**
+ * Block interface (up).
+ * Pair with PDMIMOUNT.
+ */
+typedef struct PDMIMOUNTNOTIFY
+{
+ /**
+ * Called when a media is mounted.
+ *
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnMountNotify,(PPDMIMOUNTNOTIFY pInterface));
+
+ /**
+ * Called when a media is unmounted
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnUnmountNotify,(PPDMIMOUNTNOTIFY pInterface));
+} PDMIMOUNTNOTIFY;
+/** PDMIMOUNTNOTIFY interface ID. */
+#define PDMIMOUNTNOTIFY_IID "fa143ac9-9fc6-498e-997f-945380a558f9"
+
+
+/** Pointer to mount interface. */
+typedef struct PDMIMOUNT *PPDMIMOUNT;
+/**
+ * Mount interface (down).
+ * Pair with PDMIMOUNTNOTIFY.
+ */
+typedef struct PDMIMOUNT
+{
+ /**
+ * Unmount the media.
+ *
+ * The driver will validate and pass it on. On the rebounce it will decide whether or not to detach it self.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @thread The emulation thread.
+ * @param fForce Force the unmount, even for locked media.
+ * @param fEject Eject the medium. Only relevant for host drives.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnUnmount,(PPDMIMOUNT pInterface, bool fForce, bool fEject));
+
+ /**
+ * Checks if a media is mounted.
+ *
+ * @returns true if mounted.
+ * @returns false if not mounted.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(bool, pfnIsMounted,(PPDMIMOUNT pInterface));
+
+ /**
+ * Locks the media, preventing any unmounting of it.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnLock,(PPDMIMOUNT pInterface));
+
+ /**
+ * Unlocks the media, canceling previous calls to pfnLock().
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnUnlock,(PPDMIMOUNT pInterface));
+
+ /**
+ * Checks if a media is locked.
+ *
+ * @returns true if locked.
+ * @returns false if not locked.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(bool, pfnIsLocked,(PPDMIMOUNT pInterface));
+} PDMIMOUNT;
+/** PDMIMOUNT interface ID. */
+#define PDMIMOUNT_IID "34fc7a4c-623a-4806-a6bf-5be1be33c99f"
+
+
+/**
+ * Callback which provides progress information.
+ *
+ * @return VBox status code.
+ * @param pvUser Opaque user data.
+ * @param uPercentage Completion percentage.
+ */
+typedef DECLCALLBACKTYPE(int, FNSIMPLEPROGRESS,(void *pvUser, unsigned uPercentage));
+/** Pointer to FNSIMPLEPROGRESS() */
+typedef FNSIMPLEPROGRESS *PFNSIMPLEPROGRESS;
+
+
+/**
+ * Media type.
+ */
+typedef enum PDMMEDIATYPE
+{
+ /** Error (for the query function). */
+ PDMMEDIATYPE_ERROR = 1,
+ /** 360KB 5 1/4" floppy drive. */
+ PDMMEDIATYPE_FLOPPY_360,
+ /** 720KB 3 1/2" floppy drive. */
+ PDMMEDIATYPE_FLOPPY_720,
+ /** 1.2MB 5 1/4" floppy drive. */
+ PDMMEDIATYPE_FLOPPY_1_20,
+ /** 1.44MB 3 1/2" floppy drive. */
+ PDMMEDIATYPE_FLOPPY_1_44,
+ /** 2.88MB 3 1/2" floppy drive. */
+ PDMMEDIATYPE_FLOPPY_2_88,
+ /** Fake drive that can take up to 15.6 MB images.
+ * C=255, H=2, S=63. */
+ PDMMEDIATYPE_FLOPPY_FAKE_15_6,
+ /** Fake drive that can take up to 63.5 MB images.
+ * C=255, H=2, S=255. */
+ PDMMEDIATYPE_FLOPPY_FAKE_63_5,
+ /** CDROM drive. */
+ PDMMEDIATYPE_CDROM,
+ /** DVD drive. */
+ PDMMEDIATYPE_DVD,
+ /** Hard disk drive. */
+ PDMMEDIATYPE_HARD_DISK
+} PDMMEDIATYPE;
+
+/** Check if the given block type is a floppy. */
+#define PDMMEDIATYPE_IS_FLOPPY(a_enmType) ( (a_enmType) >= PDMMEDIATYPE_FLOPPY_360 && (a_enmType) <= PDMMEDIATYPE_FLOPPY_2_88 )
+
+/**
+ * Raw command data transfer direction.
+ */
+typedef enum PDMMEDIATXDIR
+{
+ PDMMEDIATXDIR_NONE = 0,
+ PDMMEDIATXDIR_FROM_DEVICE,
+ PDMMEDIATXDIR_TO_DEVICE
+} PDMMEDIATXDIR;
+
+/**
+ * Media geometry structure.
+ */
+typedef struct PDMMEDIAGEOMETRY
+{
+ /** Number of cylinders. */
+ uint32_t cCylinders;
+ /** Number of heads. */
+ uint32_t cHeads;
+ /** Number of sectors. */
+ uint32_t cSectors;
+} PDMMEDIAGEOMETRY;
+
+/** Pointer to media geometry structure. */
+typedef PDMMEDIAGEOMETRY *PPDMMEDIAGEOMETRY;
+/** Pointer to constant media geometry structure. */
+typedef const PDMMEDIAGEOMETRY *PCPDMMEDIAGEOMETRY;
+
+/** Pointer to a media port interface. */
+typedef struct PDMIMEDIAPORT *PPDMIMEDIAPORT;
+/**
+ * Media port interface (down).
+ */
+typedef struct PDMIMEDIAPORT
+{
+ /**
+ * Returns the storage controller name, instance and LUN of the attached medium.
+ *
+ * @returns VBox status.
+ * @param pInterface Pointer to this interface.
+ * @param ppcszController Where to store the name of the storage controller.
+ * @param piInstance Where to store the instance number of the controller.
+ * @param piLUN Where to store the LUN of the attached device.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnQueryDeviceLocation, (PPDMIMEDIAPORT pInterface, const char **ppcszController,
+ uint32_t *piInstance, uint32_t *piLUN));
+
+
+ /**
+ * Queries the vendor and product ID and revision to report for INQUIRY commands in underlying devices, optional.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to this interface.
+ * @param ppszVendorId Where to store the pointer to the vendor ID string to report.
+ * @param ppszProductId Where to store the pointer to the product ID string to report.
+ * @param ppszRevision Where to store the pointer to the revision string to report.
+ *
+ * @note The strings for the inquiry data are stored in the storage controller rather than in the device
+ * because if device attachments change (virtual CD/DVD drive versus host drive) there is currently no
+ * way to keep the INQUIRY data in extradata keys without causing trouble when the attachment is changed.
+ * Also Main currently doesn't has any settings for the attachment to store such information in the settings
+ * properly. Last reason (but not the most important one) is to stay compatible with older versions
+ * where the drive emulation was in AHCI but it now uses VSCSI and the settings overwrite should still work.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnQueryScsiInqStrings, (PPDMIMEDIAPORT pInterface, const char **ppszVendorId,
+ const char **ppszProductId, const char **ppszRevision));
+
+} PDMIMEDIAPORT;
+/** PDMIMEDIAPORT interface ID. */
+#define PDMIMEDIAPORT_IID "77180ab8-6485-454f-b440-efca322b7bd7"
+
+/** Pointer to a media interface. */
+typedef struct PDMIMEDIA *PPDMIMEDIA;
+/**
+ * Media interface (up).
+ * Pairs with PDMIMEDIAPORT.
+ */
+typedef struct PDMIMEDIA
+{
+ /**
+ * Read bits.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param off Offset to start reading from. The offset must be aligned to a sector boundary.
+ * @param pvBuf Where to store the read bits.
+ * @param cbRead Number of bytes to read. Must be aligned to a sector boundary.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnRead,(PPDMIMEDIA pInterface, uint64_t off, void *pvBuf, size_t cbRead));
+
+ /**
+ * Read bits - version for DevPcBios.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param off Offset to start reading from. The offset must be aligned to a sector boundary.
+ * @param pvBuf Where to store the read bits.
+ * @param cbRead Number of bytes to read. Must be aligned to a sector boundary.
+ * @thread Any thread.
+ *
+ * @note: Special version of pfnRead which doesn't try to suspend the VM when the DEKs for encrypted disks
+ * are missing but just returns an error.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnReadPcBios,(PPDMIMEDIA pInterface, uint64_t off, void *pvBuf, size_t cbRead));
+
+ /**
+ * Write bits.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param off Offset to start writing at. The offset must be aligned to a sector boundary.
+ * @param pvBuf Where to store the write bits.
+ * @param cbWrite Number of bytes to write. Must be aligned to a sector boundary.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnWrite,(PPDMIMEDIA pInterface, uint64_t off, const void *pvBuf, size_t cbWrite));
+
+ /**
+ * Make sure that the bits written are actually on the storage medium.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnFlush,(PPDMIMEDIA pInterface));
+
+ /**
+ * Send a raw command to the underlying device (CDROM).
+ * This method is optional (i.e. the function pointer may be NULL).
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pbCdb The command to process.
+ * @param cbCdb The length of the command in bytes.
+ * @param enmTxDir Direction of transfer.
+ * @param pvBuf Pointer tp the transfer buffer.
+ * @param pcbBuf Size of the transfer buffer.
+ * @param pabSense Status of the command (when return value is VERR_DEV_IO_ERROR).
+ * @param cbSense Size of the sense buffer in bytes.
+ * @param cTimeoutMillies Command timeout in milliseconds.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSendCmd,(PPDMIMEDIA pInterface, const uint8_t *pbCdb, size_t cbCdb,
+ PDMMEDIATXDIR enmTxDir, void *pvBuf, uint32_t *pcbBuf,
+ uint8_t *pabSense, size_t cbSense, uint32_t cTimeoutMillies));
+
+ /**
+ * Merge medium contents during a live snapshot deletion. All details
+ * must have been configured through CFGM or this will fail.
+ * This method is optional (i.e. the function pointer may be NULL).
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pfnProgress Function pointer for progress notification.
+ * @param pvUser Opaque user data for progress notification.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnMerge,(PPDMIMEDIA pInterface, PFNSIMPLEPROGRESS pfnProgress, void *pvUser));
+
+ /**
+ * Sets the secret key retrieval interface to use to get secret keys.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pIfSecKey The secret key interface to use.
+ * Use NULL to clear the currently set interface and clear all secret
+ * keys from the user.
+ * @param pIfSecKeyHlp The secret key helper interface to use.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSetSecKeyIf,(PPDMIMEDIA pInterface, struct PDMISECKEY *pIfSecKey,
+ struct PDMISECKEYHLP *pIfSecKeyHlp));
+
+ /**
+ * Get the media size in bytes.
+ *
+ * @returns Media size in bytes.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(uint64_t, pfnGetSize,(PPDMIMEDIA pInterface));
+
+ /**
+ * Gets the media sector size in bytes.
+ *
+ * @returns Media sector size in bytes.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(uint32_t, pfnGetSectorSize,(PPDMIMEDIA pInterface));
+
+ /**
+ * Check if the media is readonly or not.
+ *
+ * @returns true if readonly.
+ * @returns false if read/write.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(bool, pfnIsReadOnly,(PPDMIMEDIA pInterface));
+
+ /**
+ * Returns whether the medium should be marked as rotational or not.
+ *
+ * @returns true if non rotating medium.
+ * @returns false if rotating medium.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(bool, pfnIsNonRotational,(PPDMIMEDIA pInterface));
+
+ /**
+ * Get stored media geometry (physical CHS, PCHS) - BIOS property.
+ * This is an optional feature of a media.
+ *
+ * @returns VBox status code.
+ * @returns VERR_NOT_IMPLEMENTED if the media doesn't support storing the geometry.
+ * @returns VERR_PDM_GEOMETRY_NOT_SET if the geometry hasn't been set using pfnBiosSetPCHSGeometry() yet.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pPCHSGeometry Pointer to PCHS geometry (cylinders/heads/sectors).
+ * @remark This has no influence on the read/write operations.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnBiosGetPCHSGeometry,(PPDMIMEDIA pInterface, PPDMMEDIAGEOMETRY pPCHSGeometry));
+
+ /**
+ * Store the media geometry (physical CHS, PCHS) - BIOS property.
+ * This is an optional feature of a media.
+ *
+ * @returns VBox status code.
+ * @returns VERR_NOT_IMPLEMENTED if the media doesn't support storing the geometry.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pPCHSGeometry Pointer to PCHS geometry (cylinders/heads/sectors).
+ * @remark This has no influence on the read/write operations.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnBiosSetPCHSGeometry,(PPDMIMEDIA pInterface, PCPDMMEDIAGEOMETRY pPCHSGeometry));
+
+ /**
+ * Get stored media geometry (logical CHS, LCHS) - BIOS property.
+ * This is an optional feature of a media.
+ *
+ * @returns VBox status code.
+ * @returns VERR_NOT_IMPLEMENTED if the media doesn't support storing the geometry.
+ * @returns VERR_PDM_GEOMETRY_NOT_SET if the geometry hasn't been set using pfnBiosSetLCHSGeometry() yet.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pLCHSGeometry Pointer to LCHS geometry (cylinders/heads/sectors).
+ * @remark This has no influence on the read/write operations.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnBiosGetLCHSGeometry,(PPDMIMEDIA pInterface, PPDMMEDIAGEOMETRY pLCHSGeometry));
+
+ /**
+ * Store the media geometry (logical CHS, LCHS) - BIOS property.
+ * This is an optional feature of a media.
+ *
+ * @returns VBox status code.
+ * @returns VERR_NOT_IMPLEMENTED if the media doesn't support storing the geometry.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pLCHSGeometry Pointer to LCHS geometry (cylinders/heads/sectors).
+ * @remark This has no influence on the read/write operations.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnBiosSetLCHSGeometry,(PPDMIMEDIA pInterface, PCPDMMEDIAGEOMETRY pLCHSGeometry));
+
+ /**
+ * Checks if the device should be visible to the BIOS or not.
+ *
+ * @returns true if the device is visible to the BIOS.
+ * @returns false if the device is not visible to the BIOS.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(bool, pfnBiosIsVisible,(PPDMIMEDIA pInterface));
+
+ /**
+ * Gets the media type.
+ *
+ * @returns media type.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(PDMMEDIATYPE, pfnGetType,(PPDMIMEDIA pInterface));
+
+ /**
+ * Gets the UUID of the media drive.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pUuid Where to store the UUID on success.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnGetUuid,(PPDMIMEDIA pInterface, PRTUUID pUuid));
+
+ /**
+ * Discards the given range.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param paRanges Array of ranges to discard.
+ * @param cRanges Number of entries in the array.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnDiscard,(PPDMIMEDIA pInterface, PCRTRANGE paRanges, unsigned cRanges));
+
+ /**
+ * Returns the number of regions for the medium.
+ *
+ * @returns Number of regions.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ */
+ DECLR3CALLBACKMEMBER(uint32_t, pfnGetRegionCount,(PPDMIMEDIA pInterface));
+
+ /**
+ * Queries the properties for the given region.
+ *
+ * @returns VBox status code.
+ * @retval VERR_NOT_FOUND if the region index is not known.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param uRegion The region index to query the properties of.
+ * @param pu64LbaStart Where to store the starting LBA for the region on success.
+ * @param pcBlocks Where to store the number of blocks for the region on success.
+ * @param pcbBlock Where to store the size of one block in bytes on success.
+ * @param penmDataForm WHere to store the data form for the region on success.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnQueryRegionProperties,(PPDMIMEDIA pInterface, uint32_t uRegion, uint64_t *pu64LbaStart,
+ uint64_t *pcBlocks, uint64_t *pcbBlock,
+ PVDREGIONDATAFORM penmDataForm));
+
+ /**
+ * Queries the properties for the region covering the given LBA.
+ *
+ * @returns VBox status code.
+ * @retval VERR_NOT_FOUND if the region index is not known.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param u64LbaStart Where to store the starting LBA for the region on success.
+ * @param puRegion Where to store the region number on success.
+ * @param pcBlocks Where to store the number of blocks left in this region starting from the given LBA.
+ * @param pcbBlock Where to store the size of one block in bytes on success.
+ * @param penmDataForm WHere to store the data form for the region on success.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnQueryRegionPropertiesForLba,(PPDMIMEDIA pInterface, uint64_t u64LbaStart,
+ uint32_t *puRegion, uint64_t *pcBlocks,
+ uint64_t *pcbBlock, PVDREGIONDATAFORM penmDataForm));
+
+} PDMIMEDIA;
+/** PDMIMEDIA interface ID. */
+#define PDMIMEDIA_IID "8ec68c48-dd20-4430-8386-f0d628a5aca6"
+
+
+/**
+ * Opaque I/O request handle.
+ *
+ * The specific content depends on the driver implementing this interface.
+ */
+typedef struct PDMMEDIAEXIOREQINT *PDMMEDIAEXIOREQ;
+/** Pointer to an I/O request handle. */
+typedef PDMMEDIAEXIOREQ *PPDMMEDIAEXIOREQ;
+/** NIL I/O request handle. */
+#define NIL_PDMMEDIAEXIOREQ ((PDMMEDIAEXIOREQ)0)
+
+/** A I/O request ID. */
+typedef uint64_t PDMMEDIAEXIOREQID;
+
+/**
+ * I/O Request Type.
+ */
+typedef enum PDMMEDIAEXIOREQTYPE
+{
+ /** Invalid tpe. */
+ PDMMEDIAEXIOREQTYPE_INVALID = 0,
+ /** Flush request. */
+ PDMMEDIAEXIOREQTYPE_FLUSH,
+ /** Write request. */
+ PDMMEDIAEXIOREQTYPE_WRITE,
+ /** Read request. */
+ PDMMEDIAEXIOREQTYPE_READ,
+ /** Discard request. */
+ PDMMEDIAEXIOREQTYPE_DISCARD,
+ /** SCSI command. */
+ PDMMEDIAEXIOREQTYPE_SCSI
+} PDMMEDIAEXIOREQTYPE;
+/** Pointer to a I/O request type. */
+typedef PDMMEDIAEXIOREQTYPE *PPDMMEDIAEXIOREQTYPE;
+
+/**
+ * Data direction for raw SCSI commands.
+ */
+typedef enum PDMMEDIAEXIOREQSCSITXDIR
+{
+ /** Invalid data direction. */
+ PDMMEDIAEXIOREQSCSITXDIR_INVALID = 0,
+ /** Direction is unknown. */
+ PDMMEDIAEXIOREQSCSITXDIR_UNKNOWN,
+ /** Direction is from device to host. */
+ PDMMEDIAEXIOREQSCSITXDIR_FROM_DEVICE,
+ /** Direction is from host to device. */
+ PDMMEDIAEXIOREQSCSITXDIR_TO_DEVICE,
+ /** No data transfer associated with this request. */
+ PDMMEDIAEXIOREQSCSITXDIR_NONE,
+ /** 32bit hack. */
+ PDMMEDIAEXIOREQSCSITXDIR_32BIT_HACK = 0x7fffffff
+} PDMMEDIAEXIOREQSCSITXDIR;
+
+/**
+ * I/O request state.
+ */
+typedef enum PDMMEDIAEXIOREQSTATE
+{
+ /** Invalid state. */
+ PDMMEDIAEXIOREQSTATE_INVALID = 0,
+ /** The request is active and being processed. */
+ PDMMEDIAEXIOREQSTATE_ACTIVE,
+ /** The request is suspended due to an error and no processing will take place. */
+ PDMMEDIAEXIOREQSTATE_SUSPENDED,
+ /** 32bit hack. */
+ PDMMEDIAEXIOREQSTATE_32BIT_HACK = 0x7fffffff
+} PDMMEDIAEXIOREQSTATE;
+/** Pointer to a I/O request state. */
+typedef PDMMEDIAEXIOREQSTATE *PPDMMEDIAEXIOREQSTATE;
+
+/** @name Supported feature flags
+ * @{ */
+/** I/O requests will execute asynchronously by default. */
+#define PDMIMEDIAEX_FEATURE_F_ASYNC RT_BIT_32(0)
+/** The discard request is supported. */
+#define PDMIMEDIAEX_FEATURE_F_DISCARD RT_BIT_32(1)
+/** The send raw SCSI command request is supported. */
+#define PDMIMEDIAEX_FEATURE_F_RAWSCSICMD RT_BIT_32(2)
+/** Mask of valid flags. */
+#define PDMIMEDIAEX_FEATURE_F_VALID (PDMIMEDIAEX_FEATURE_F_ASYNC | PDMIMEDIAEX_FEATURE_F_DISCARD | PDMIMEDIAEX_FEATURE_F_RAWSCSICMD)
+/** @} */
+
+/** @name I/O request specific flags
+ * @{ */
+/** Default behavior (async I/O).*/
+#define PDMIMEDIAEX_F_DEFAULT (0)
+/** The I/O request will be executed synchronously. */
+#define PDMIMEDIAEX_F_SYNC RT_BIT_32(0)
+/** Whether to suspend the VM on a recoverable error with
+ * an appropriate error message (disk full, etc.).
+ * The request will be retried by the driver implementing the interface
+ * when the VM resumes the next time. However before suspending the request
+ * the owner of the request will be notified using the PDMMEDIAEXPORT::pfnIoReqStateChanged.
+ * The same goes for resuming the request after the VM was resumed.
+ */
+#define PDMIMEDIAEX_F_SUSPEND_ON_RECOVERABLE_ERR RT_BIT_32(1)
+ /** Mask of valid flags. */
+#define PDMIMEDIAEX_F_VALID (PDMIMEDIAEX_F_SYNC | PDMIMEDIAEX_F_SUSPEND_ON_RECOVERABLE_ERR)
+/** @} */
+
+/** Pointer to an extended media notification interface. */
+typedef struct PDMIMEDIAEXPORT *PPDMIMEDIAEXPORT;
+
+/**
+ * Asynchronous version of the media interface (up).
+ * Pair with PDMIMEDIAEXPORT.
+ */
+typedef struct PDMIMEDIAEXPORT
+{
+ /**
+ * Notify completion of a I/O request.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param hIoReq The I/O request handle.
+ * @param pvIoReqAlloc The allocator specific memory for this request.
+ * @param rcReq IPRT Status code of the completed request.
+ * VERR_PDM_MEDIAEX_IOREQ_CANCELED if the request was canceled by a call to
+ * PDMIMEDIAEX::pfnIoReqCancel.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnIoReqCompleteNotify, (PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
+ void *pvIoReqAlloc, int rcReq));
+
+ /**
+ * Copy data from the memory buffer of the caller to the callees memory buffer for the given request.
+ *
+ * @returns VBox status code.
+ * @retval VERR_PDM_MEDIAEX_IOBUF_OVERFLOW if there is not enough room to store the data.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param hIoReq The I/O request handle.
+ * @param pvIoReqAlloc The allocator specific memory for this request.
+ * @param offDst The destination offset from the start to write the data to.
+ * @param pSgBuf The S/G buffer to read the data from.
+ * @param cbCopy How many bytes to copy.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnIoReqCopyFromBuf, (PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
+ void *pvIoReqAlloc, uint32_t offDst, PRTSGBUF pSgBuf,
+ size_t cbCopy));
+
+ /**
+ * Copy data to the memory buffer of the caller from the callees memory buffer for the given request.
+ *
+ * @returns VBox status code.
+ * @retval VERR_PDM_MEDIAEX_IOBUF_UNDERRUN if there is not enough data to copy from the buffer.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param hIoReq The I/O request handle.
+ * @param pvIoReqAlloc The allocator specific memory for this request.
+ * @param offSrc The offset from the start of the buffer to read the data from.
+ * @param pSgBuf The S/G buffer to write the data to.
+ * @param cbCopy How many bytes to copy.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnIoReqCopyToBuf, (PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
+ void *pvIoReqAlloc, uint32_t offSrc, PRTSGBUF pSgBuf,
+ size_t cbCopy));
+
+ /**
+ * Queries a pointer to the memory buffer for the request from the drive/device above.
+ *
+ * @returns VBox status code.
+ * @retval VERR_NOT_SUPPORTED if this is not supported for this request.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param hIoReq The I/O request handle.
+ * @param pvIoReqAlloc The allocator specific memory for this request.
+ * @param ppvBuf Where to store the pointer to the guest buffer on success.
+ * @param pcbBuf Where to store the size of the buffer on success.
+ *
+ * @note This is an optional feature of the entity implementing this interface to avoid overhead
+ * by copying the data between buffers. If NULL it is not supported at all and the caller
+ * has to resort to PDMIMEDIAEXPORT::pfnIoReqCopyToBuf and PDMIMEDIAEXPORT::pfnIoReqCopyFromBuf.
+ * The same holds when VERR_NOT_SUPPORTED is returned.
+ *
+ * On the upside the caller of this interface might not call this method at all and just
+ * use the before mentioned methods to copy the data between the buffers.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnIoReqQueryBuf, (PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
+ void *pvIoReqAlloc, void **ppvBuf, size_t *pcbBuf));
+
+ /**
+ * Queries the specified amount of ranges to discard from the callee for the given I/O request.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param hIoReq The I/O request handle.
+ * @param pvIoReqAlloc The allocator specific memory for this request.
+ * @param idxRangeStart The range index to start with.
+ * @param cRanges How man ranges can be stored in the provided array.
+ * @param paRanges Where to store the ranges on success.
+ * @param *pcRanges Where to store the number of ranges copied over on success.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnIoReqQueryDiscardRanges, (PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
+ void *pvIoReqAlloc, uint32_t idxRangeStart,
+ uint32_t cRanges, PRTRANGE paRanges,
+ uint32_t *pcRanges));
+
+ /**
+ * Notify the request owner about a state change for the request.
+ *
+ * @returns nothing.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param hIoReq The I/O request handle.
+ * @param pvIoReqAlloc The allocator specific memory for this request.
+ * @param enmState The new state of the request.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnIoReqStateChanged, (PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
+ void *pvIoReqAlloc, PDMMEDIAEXIOREQSTATE enmState));
+
+ /**
+ * Informs the device that the underlying medium was ejected.
+ *
+ * @returns nothing.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnMediumEjected, (PPDMIMEDIAEXPORT pInterface));
+
+} PDMIMEDIAEXPORT;
+
+/** PDMIMEDIAAEXPORT interface ID. */
+#define PDMIMEDIAEXPORT_IID "0ae2e534-6c28-41d6-9a88-7f88f2cb2ff8"
+
+
+/** Pointer to an extended media interface. */
+typedef struct PDMIMEDIAEX *PPDMIMEDIAEX;
+
+/**
+ * Extended version of PDMIMEDIA (down).
+ * Pair with PDMIMEDIAEXPORT.
+ */
+typedef struct PDMIMEDIAEX
+{
+ /**
+ * Queries the features supported by the entity implementing this interface.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pfFeatures Where to store the supported feature flags on success.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnQueryFeatures, (PPDMIMEDIAEX pInterface, uint32_t *pfFeatures));
+
+ /**
+ * Notifies the driver below that the device received a suspend notification.
+ *
+ * @returns nothing.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ *
+ * @note this is required because the PDM drivers in the storage area usually get their suspend notification
+ * only after the device finished suspending. For some cases it is useful for the driver to know
+ * as early as possible that a suspend is in progress to stop issuing deferred requests or other things.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnNotifySuspend, (PPDMIMEDIAEX pInterface));
+
+ /**
+ * Sets the size of the allocator specific memory for a I/O request.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param cbIoReqAlloc The size of the allocator specific memory in bytes.
+ * @thread EMT.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnIoReqAllocSizeSet, (PPDMIMEDIAEX pInterface, size_t cbIoReqAlloc));
+
+ /**
+ * Allocates a new I/O request.
+ *
+ * @returns VBox status code.
+ * @retval VERR_PDM_MEDIAEX_IOREQID_CONFLICT if the ID belongs to a still active request.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param phIoReq Where to store the handle to the new I/O request on success.
+ * @param ppvIoReqAlloc Where to store the pointer to the allocator specific memory on success.
+ * NULL if the memory size was not set or set to 0.
+ * @param uIoReqId A custom request ID which can be used to cancel the request.
+ * @param fFlags A combination of PDMIMEDIAEX_F_* flags.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnIoReqAlloc, (PPDMIMEDIAEX pInterface, PPDMMEDIAEXIOREQ phIoReq, void **ppvIoReqAlloc,
+ PDMMEDIAEXIOREQID uIoReqId, uint32_t fFlags));
+
+ /**
+ * Frees a given I/O request.
+ *
+ * @returns VBox status code.
+ * @retval VERR_PDM_MEDIAEX_IOREQ_INVALID_STATE if the given request is still active.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param hIoReq The I/O request to free.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnIoReqFree, (PPDMIMEDIAEX pInterface, PDMMEDIAEXIOREQ hIoReq));
+
+ /**
+ * Queries the residual amount of data not transfered when the request completed.
+ *
+ * @returns VBox status code.
+ * @retval VERR_PDM_MEDIAEX_IOREQ_INVALID_STATE has not completed yet.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param hIoReq The I/O request.
+ * @param pcbResidual Where to store the amount of resdiual data in bytes.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnIoReqQueryResidual, (PPDMIMEDIAEX pInterface, PDMMEDIAEXIOREQ hIoReq, size_t *pcbResidual));
+
+ /**
+ * Queries the residual amount of data not transfered when the request completed.
+ *
+ * @returns VBox status code.
+ * @retval VERR_PDM_MEDIAEX_IOREQ_INVALID_STATE has not completed yet.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param hIoReq The I/O request.
+ * @param pcbXfer Where to store the amount of resdiual data in bytes.
+ * @thread Any thread.
+ *
+ * @note For simple read/write requests this returns the amount to read/write as given to the
+ * PDMIMEDIAEX::pfnIoReqRead or PDMIMEDIAEX::pfnIoReqWrite call.
+ * For SCSI commands this returns the transfer size as given in the provided CDB.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnIoReqQueryXferSize, (PPDMIMEDIAEX pInterface, PDMMEDIAEXIOREQ hIoReq, size_t *pcbXfer));
+
+ /**
+ * Cancels all I/O active requests.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnIoReqCancelAll, (PPDMIMEDIAEX pInterface));
+
+ /**
+ * Cancels a I/O request identified by the ID.
+ *
+ * @returns VBox status code.
+ * @retval VERR_PDM_MEDIAEX_IOREQID_NOT_FOUND if the given ID could not be found in the active request list.
+ * (The request has either completed already or an invalid ID was given).
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param uIoReqId The I/O request ID
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnIoReqCancel, (PPDMIMEDIAEX pInterface, PDMMEDIAEXIOREQID uIoReqId));
+
+ /**
+ * Start a reading request.
+ *
+ * @returns VBox status code.
+ * @retval VERR_PDM_MEDIAEX_IOREQ_CANCELED if the request was canceled by a call to
+ * PDMIMEDIAEX::pfnIoReqCancel.
+ * @retval VINF_PDM_MEDIAEX_IOREQ_IN_PROGRESS if the request was successfully submitted but is still in progress.
+ * Completion will be notified through PDMIMEDIAEXPORT::pfnIoReqCompleteNotify with the appropriate status code.
+ * @retval VINF_SUCCESS if the request completed successfully.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param hIoReq The I/O request to associate the read with.
+ * @param off Offset to start reading from. Must be aligned to a sector boundary.
+ * @param cbRead Number of bytes to read. Must be aligned to a sector boundary.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnIoReqRead, (PPDMIMEDIAEX pInterface, PDMMEDIAEXIOREQ hIoReq, uint64_t off, size_t cbRead));
+
+ /**
+ * Start a writing request.
+ *
+ * @returns VBox status code.
+ * @retval VERR_PDM_MEDIAEX_IOREQ_CANCELED if the request was canceled by a call to
+ * PDMIMEDIAEX::pfnIoReqCancel.
+ * @retval VINF_PDM_MEDIAEX_IOREQ_IN_PROGRESS if the request was successfully submitted but is still in progress.
+ * Completion will be notified through PDMIMEDIAEXPORT::pfnIoReqCompleteNotify with the appropriate status code.
+ * @retval VINF_SUCCESS if the request completed successfully.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param hIoReq The I/O request to associate the write with.
+ * @param off Offset to start reading from. Must be aligned to a sector boundary.
+ * @param cbWrite Number of bytes to write. Must be aligned to a sector boundary.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnIoReqWrite, (PPDMIMEDIAEX pInterface, PDMMEDIAEXIOREQ hIoReq, uint64_t off, size_t cbWrite));
+
+ /**
+ * Flush everything to disk.
+ *
+ * @returns VBox status code.
+ * @retval VERR_PDM_MEDIAEX_IOREQ_CANCELED if the request was canceled by a call to
+ * PDMIMEDIAEX::pfnIoReqCancel.
+ * @retval VINF_PDM_MEDIAEX_IOREQ_IN_PROGRESS if the request was successfully submitted but is still in progress.
+ * Completion will be notified through PDMIMEDIAEXPORT::pfnIoReqCompleteNotify with the appropriate status code.
+ * @retval VINF_SUCCESS if the request completed successfully.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param hIoReq The I/O request to associate the flush with.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnIoReqFlush, (PPDMIMEDIAEX pInterface, PDMMEDIAEXIOREQ hIoReq));
+
+ /**
+ * Discards the given range.
+ *
+ * @returns VBox status code.
+ * @retval VERR_PDM_MEDIAEX_IOREQ_CANCELED if the request was canceled by a call to
+ * PDMIMEDIAEX::pfnIoReqCancel.
+ * @retval VINF_PDM_MEDIAEX_IOREQ_IN_PROGRESS if the request was successfully submitted but is still in progress.
+ * Completion will be notified through PDMIMEDIAEXPORT::pfnIoReqCompleteNotify with the appropriate status code.
+ * @retval VINF_SUCCESS if the request completed successfully.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param hIoReq The I/O request to associate the discard with.
+ * @param cRangesMax The maximum number of ranges this request has associated, this must not be accurate
+ * but can actually be bigger than the amount of ranges actually available.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnIoReqDiscard, (PPDMIMEDIAEX pInterface, PDMMEDIAEXIOREQ hIoReq, unsigned cRangesMax));
+
+ /**
+ * Send a raw command to the underlying device (CDROM).
+ *
+ * @returns VBox status code.
+ * @retval VERR_PDM_MEDIAEX_IOREQ_CANCELED if the request was canceled by a call to
+ * PDMIMEDIAEX::pfnIoReqCancel.
+ * @retval VINF_PDM_MEDIAEX_IOREQ_IN_PROGRESS if the request was successfully submitted but is still in progress.
+ * Completion will be notified through PDMIMEDIAEXPORT::pfnIoReqCompleteNotify with the appropriate status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param hIoReq The I/O request to associate the command with.
+ * @param uLun The LUN the command is for.
+ * @param pbCdb The SCSI CDB containing the command.
+ * @param cbCdb Size of the CDB in bytes.
+ * @param enmTxDir Direction of transfer.
+ * @param penmTxDirRet Where to store the transfer direction as parsed from the CDB, optional.
+ * @param cbBuf Size of the transfer buffer.
+ * @param pabSense Where to store the optional sense key.
+ * @param cbSense Size of the sense key buffer.
+ * @param pcbSenseRet Where to store the amount of sense data written, optional.
+ * @param pu8ScsiSts Where to store the SCSI status on success.
+ * @param cTimeoutMillies Command timeout in milliseconds.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnIoReqSendScsiCmd,(PPDMIMEDIAEX pInterface, PDMMEDIAEXIOREQ hIoReq,
+ uint32_t uLun, const uint8_t *pbCdb, size_t cbCdb,
+ PDMMEDIAEXIOREQSCSITXDIR enmTxDir, PDMMEDIAEXIOREQSCSITXDIR *penmTxDirRet,
+ size_t cbBuf, uint8_t *pabSense, size_t cbSense, size_t *pcbSenseRet,
+ uint8_t *pu8ScsiSts, uint32_t cTimeoutMillies));
+
+ /**
+ * Returns the number of active I/O requests.
+ *
+ * @returns Number of active I/O requests.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(uint32_t, pfnIoReqGetActiveCount, (PPDMIMEDIAEX pInterface));
+
+ /**
+ * Returns the number of suspended requests.
+ *
+ * @returns Number of suspended I/O requests.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(uint32_t, pfnIoReqGetSuspendedCount, (PPDMIMEDIAEX pInterface));
+
+ /**
+ * Gets the first suspended request handle.
+ *
+ * @returns VBox status code.
+ * @retval VERR_NOT_FOUND if there is no suspended request waiting.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param phIoReq Where to store the request handle on success.
+ * @param ppvIoReqAlloc Where to store the pointer to the allocator specific memory on success.
+ * @thread Any thread.
+ *
+ * @note This should only be called when the VM is suspended to make sure the request doesn't suddenly
+ * changes into the active state again. The only purpose for this method for now is to make saving the state
+ * possible without breaking saved state versions.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnIoReqQuerySuspendedStart, (PPDMIMEDIAEX pInterface, PPDMMEDIAEXIOREQ phIoReq, void **ppvIoReqAlloc));
+
+ /**
+ * Gets the next suspended request handle.
+ *
+ * @returns VBox status code.
+ * @retval VERR_NOT_FOUND if there is no suspended request waiting.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param hIoReq The current request handle.
+ * @param phIoReqNext Where to store the request handle on success.
+ * @param ppvIoReqAllocNext Where to store the pointer to the allocator specific memory on success.
+ * @thread Any thread.
+ *
+ * @note This should only be called when the VM is suspended to make sure the request doesn't suddenly
+ * changes into the active state again. The only purpose for this method for now is to make saving the state
+ * possible without breaking saved state versions.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnIoReqQuerySuspendedNext, (PPDMIMEDIAEX pInterface, PDMMEDIAEXIOREQ hIoReq,
+ PPDMMEDIAEXIOREQ phIoReqNext, void **ppvIoReqAllocNext));
+
+ /**
+ * Saves the given I/O request state in the provided saved state unit.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pSSM The SSM handle.
+ * @param hIoReq The request handle to save.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnIoReqSuspendedSave, (PPDMIMEDIAEX pInterface, PSSMHANDLE pSSM, PDMMEDIAEXIOREQ hIoReq));
+
+ /**
+ * Load a suspended request state from the given saved state unit and link it into the suspended list.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pSSM The SSM handle to read the state from.
+ * @param hIoReq The request handle to load the state into.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnIoReqSuspendedLoad, (PPDMIMEDIAEX pInterface, PSSMHANDLE pSSM, PDMMEDIAEXIOREQ hIoReq));
+
+} PDMIMEDIAEX;
+/** PDMIMEDIAEX interface ID. */
+#define PDMIMEDIAEX_IID "29c9e82b-934e-45c5-bb84-0d871c3cc9dd"
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !VBOX_INCLUDED_vmm_pdmstorageifs_h */
diff --git a/include/VBox/vmm/pdmtask.h b/include/VBox/vmm/pdmtask.h
new file mode 100644
index 00000000..d3b48e99
--- /dev/null
+++ b/include/VBox/vmm/pdmtask.h
@@ -0,0 +1,162 @@
+/** @file
+ * PDM - Pluggable Device Manager, Tasks.
+ */
+
+/*
+ * Copyright (C) 2019-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vmm_pdmtask_h
+#define VBOX_INCLUDED_vmm_pdmtask_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/types.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_pdm_task The PDM Tasks API
+ * @ingroup grp_pdm
+ *
+ * A task is a predefined asynchronous procedure call that can be triggered from
+ * any context.
+ *
+ * @{
+ */
+
+/** PDM task handle. */
+typedef uint64_t PDMTASKHANDLE;
+/** NIL PDM task handle. */
+#define NIL_PDMTASKHANDLE UINT64_MAX
+
+
+/**
+ * Task worker callback for devices.
+ *
+ * @param pDevIns The device instance.
+ * @param pvUser The user parameter.
+ * @thread Task worker thread.
+ * @remarks The device critical section will NOT be entered before calling the
+ * callback. No other locks will be held either.
+ */
+typedef DECLCALLBACKTYPE(void, FNPDMTASKDEV,(PPDMDEVINS pDevIns, void *pvUser));
+/** Pointer to a FNPDMTASKDEV(). */
+typedef FNPDMTASKDEV *PFNPDMTASKDEV;
+
+/**
+ * Task worker callback for drivers.
+ *
+ * @param pDrvIns The driver instance.
+ * @param pvUser The user parameter.
+ * @thread Task worker thread.
+ * @remarks No other locks will be held.
+ */
+typedef DECLCALLBACKTYPE(void, FNPDMTASKDRV,(PPDMDRVINS pDrvIns, void *pvUser));
+/** Pointer to a FNPDMTASKDRV(). */
+typedef FNPDMTASKDRV *PFNPDMTASKDRV;
+
+/**
+ * Task worker callback for USB devices.
+ *
+ * @param pUsbIns The USB device instance.
+ * @param pvUser The user parameter.
+ * @thread Task worker thread.
+ * @remarks No other locks will be held.
+ */
+typedef DECLCALLBACKTYPE(void, FNPDMTASKUSB,(PPDMUSBINS pUsbIns, void *pvUser));
+/** Pointer to a FNPDMTASKUSB(). */
+typedef FNPDMTASKUSB *PFNPDMTASKUSB;
+
+/**
+ * Task worker callback for internal components.
+ *
+ * @param pVM The cross context VM structure.
+ * @param pvUser The user parameter.
+ * @thread Task worker thread.
+ * @remarks No other locks will be held.
+ */
+typedef DECLCALLBACKTYPE(void, FNPDMTASKINT,(PVM pVM, void *pvUser));
+/** Pointer to a FNPDMTASKINT(). */
+typedef FNPDMTASKINT *PFNPDMTASKINT;
+
+
+/** @name PDMTASK_F_XXX - Task creation flags.
+ * @{ */
+/** Create a ring-0 triggerable task. */
+#define PDMTASK_F_R0 RT_BIT_32(0)
+/** Create a raw-mode triggerable task. */
+#define PDMTASK_F_RC RT_BIT_32(1)
+/** Create a ring-0 and raw-mode triggerable task. */
+#define PDMTASK_F_RZ (PDMTASK_F_R0 | PDMTASK_F_RC)
+/** Valid flags. */
+#define PDMTASK_F_VALID_MASK UINT32_C(0x00000003)
+/** @} */
+
+#ifdef VBOX_IN_VMM
+/**
+ * Task owner type.
+ */
+typedef enum PDMTASKTYPE
+{
+ /** Invalid zero value. */
+ PDMTASKTYPE_INVALID = 0,
+ /** Device consumer. */
+ PDMTASKTYPE_DEV,
+ /** Driver consumer. */
+ PDMTASKTYPE_DRV,
+ /** USB device consumer. */
+ PDMTASKTYPE_USB,
+ /** Internal consumer. */
+ PDMTASKTYPE_INTERNAL,
+ /** End of valid values. */
+ PDMTASKTYPE_END,
+ /** Typical 32-bit type blowup. */
+ PDMTASKTYPE_32BIT_HACK = 0x7fffffff
+} PDMTASKTYPE;
+
+VMMR3_INT_DECL(int) PDMR3TaskCreate(PVM pVM, uint32_t fFlags, const char *pszName, PDMTASKTYPE enmType, void *pvOwner,
+ PFNRT pfnCallback, void *pvUser, PDMTASKHANDLE *phTask);
+VMMR3_INT_DECL(int) PDMR3TaskCreateInternal(PVM pVM, uint32_t fFlags, const char *pszName,
+ PFNPDMTASKINT pfnCallback, void *pvUser, PDMTASKHANDLE *phTask);
+VMMR3_INT_DECL(int) PDMR3TaskDestroyAllByOwner(PVM pVM, PDMTASKTYPE enmType, void *pvOwner);
+VMMR3_INT_DECL(int) PDMR3TaskDestroySpecific(PVM pVM, PDMTASKTYPE enmType, void *pvOwner, PDMTASKHANDLE hTask);
+VMMR3_INT_DECL(int) PDMR3TaskDestroyInternal(PVM pVM, PDMTASKHANDLE hTask);
+
+VMM_INT_DECL(int) PDMTaskTrigger(PVMCC pVM, PDMTASKTYPE enmType, RTR3PTR pvOwner, PDMTASKHANDLE hTask);
+VMM_INT_DECL(int) PDMTaskTriggerInternal(PVMCC pVM, PDMTASKHANDLE hTask);
+#endif /* VBOX_IN_VMM */
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !VBOX_INCLUDED_vmm_pdmtask_h */
+
diff --git a/include/VBox/vmm/pdmthread.h b/include/VBox/vmm/pdmthread.h
new file mode 100644
index 00000000..1163f163
--- /dev/null
+++ b/include/VBox/vmm/pdmthread.h
@@ -0,0 +1,311 @@
+/** @file
+ * PDM - Pluggable Device Manager, Threads.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vmm_pdmthread_h
+#define VBOX_INCLUDED_vmm_pdmthread_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/cdefs.h>
+#include <VBox/types.h>
+#ifdef IN_RING3
+# include <iprt/thread.h>
+#endif
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_pdm_thread The PDM Threads API
+ * @ingroup grp_pdm
+ * @{
+ */
+
+/**
+ * The thread state
+ */
+typedef enum PDMTHREADSTATE
+{
+ /** The usual invalid 0 entry. */
+ PDMTHREADSTATE_INVALID = 0,
+ /** The thread is initializing.
+ * Prev state: none
+ * Next state: suspended, terminating (error) */
+ PDMTHREADSTATE_INITIALIZING,
+ /** The thread has been asked to suspend.
+ * Prev state: running
+ * Next state: suspended */
+ PDMTHREADSTATE_SUSPENDING,
+ /** The thread is supended.
+ * Prev state: suspending, initializing
+ * Next state: resuming, terminated. */
+ PDMTHREADSTATE_SUSPENDED,
+ /** The thread is active.
+ * Prev state: suspended
+ * Next state: running, terminating. */
+ PDMTHREADSTATE_RESUMING,
+ /** The thread is active.
+ * Prev state: resuming
+ * Next state: suspending, terminating. */
+ PDMTHREADSTATE_RUNNING,
+ /** The thread has been asked to terminate.
+ * Prev state: initializing, suspended, resuming, running
+ * Next state: terminated. */
+ PDMTHREADSTATE_TERMINATING,
+ /** The thread is terminating / has terminated.
+ * Prev state: terminating
+ * Next state: none */
+ PDMTHREADSTATE_TERMINATED,
+ /** The usual 32-bit hack. */
+ PDMTHREADSTATE_32BIT_HACK = 0x7fffffff
+} PDMTHREADSTATE;
+
+/** A pointer to a PDM thread. */
+typedef R3PTRTYPE(struct PDMTHREAD *) PPDMTHREAD;
+/** A pointer to a pointer to a PDM thread. */
+typedef PPDMTHREAD *PPPDMTHREAD;
+
+/**
+ * PDM thread, device variation.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param pThread The PDM thread data.
+ */
+typedef DECLCALLBACKTYPE(int, FNPDMTHREADDEV,(PPDMDEVINS pDevIns, PPDMTHREAD pThread));
+/** Pointer to a FNPDMTHREADDEV(). */
+typedef FNPDMTHREADDEV *PFNPDMTHREADDEV;
+
+/**
+ * PDM thread, USB device variation.
+ *
+ * @returns VBox status code.
+ * @param pUsbIns The USB device instance.
+ * @param pThread The PDM thread data.
+ */
+typedef DECLCALLBACKTYPE(int, FNPDMTHREADUSB,(PPDMUSBINS pUsbIns, PPDMTHREAD pThread));
+/** Pointer to a FNPDMTHREADUSB(). */
+typedef FNPDMTHREADUSB *PFNPDMTHREADUSB;
+
+/**
+ * PDM thread, driver variation.
+ *
+ * @returns VBox status code.
+ * @param pDrvIns The driver instance.
+ * @param pThread The PDM thread data.
+ */
+typedef DECLCALLBACKTYPE(int, FNPDMTHREADDRV,(PPDMDRVINS pDrvIns, PPDMTHREAD pThread));
+/** Pointer to a FNPDMTHREADDRV(). */
+typedef FNPDMTHREADDRV *PFNPDMTHREADDRV;
+
+/**
+ * PDM thread, driver variation.
+ *
+ * @returns VBox status code.
+ * @param pVM The cross context VM structure.
+ * @param pThread The PDM thread data.
+ */
+typedef DECLCALLBACKTYPE(int, FNPDMTHREADINT,(PVM pVM, PPDMTHREAD pThread));
+/** Pointer to a FNPDMTHREADINT(). */
+typedef FNPDMTHREADINT *PFNPDMTHREADINT;
+
+/**
+ * PDM thread, driver variation.
+ *
+ * @returns VBox status code.
+ * @param pThread The PDM thread data.
+ */
+typedef int FNPDMTHREADEXT(PPDMTHREAD pThread);
+/** Pointer to a FNPDMTHREADEXT(). */
+typedef FNPDMTHREADEXT *PFNPDMTHREADEXT;
+
+
+
+/**
+ * PDM thread wakeup call, device variation.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param pThread The PDM thread data.
+ */
+typedef DECLCALLBACKTYPE(int, FNPDMTHREADWAKEUPDEV,(PPDMDEVINS pDevIns, PPDMTHREAD pThread));
+/** Pointer to a FNPDMTHREADDEV(). */
+typedef FNPDMTHREADWAKEUPDEV *PFNPDMTHREADWAKEUPDEV;
+
+/**
+ * PDM thread wakeup call, device variation.
+ *
+ * @returns VBox status code.
+ * @param pUsbIns The USB device instance.
+ * @param pThread The PDM thread data.
+ */
+typedef DECLCALLBACKTYPE(int, FNPDMTHREADWAKEUPUSB,(PPDMUSBINS pUsbIns, PPDMTHREAD pThread));
+/** Pointer to a FNPDMTHREADUSB(). */
+typedef FNPDMTHREADWAKEUPUSB *PFNPDMTHREADWAKEUPUSB;
+
+/**
+ * PDM thread wakeup call, driver variation.
+ *
+ * @returns VBox status code.
+ * @param pDrvIns The driver instance.
+ * @param pThread The PDM thread data.
+ */
+typedef DECLCALLBACKTYPE(int, FNPDMTHREADWAKEUPDRV,(PPDMDRVINS pDrvIns, PPDMTHREAD pThread));
+/** Pointer to a FNPDMTHREADDRV(). */
+typedef FNPDMTHREADWAKEUPDRV *PFNPDMTHREADWAKEUPDRV;
+
+/**
+ * PDM thread wakeup call, internal variation.
+ *
+ * @returns VBox status code.
+ * @param pVM The cross context VM structure.
+ * @param pThread The PDM thread data.
+ */
+typedef DECLCALLBACKTYPE(int, FNPDMTHREADWAKEUPINT,(PVM pVM, PPDMTHREAD pThread));
+/** Pointer to a FNPDMTHREADWAKEUPINT(). */
+typedef FNPDMTHREADWAKEUPINT *PFNPDMTHREADWAKEUPINT;
+
+/**
+ * PDM thread wakeup call, external variation.
+ *
+ * @returns VBox status code.
+ * @param pThread The PDM thread data.
+ */
+typedef int FNPDMTHREADWAKEUPEXT(PPDMTHREAD pThread);
+/** Pointer to a FNPDMTHREADEXT(). */
+typedef FNPDMTHREADWAKEUPEXT *PFNPDMTHREADWAKEUPEXT;
+
+
+/**
+ * PDM Thread instance data.
+ */
+typedef struct PDMTHREAD
+{
+ /** PDMTHREAD_VERSION. */
+ uint32_t u32Version;
+ /** The thread state. */
+ PDMTHREADSTATE volatile enmState;
+ /** The thread handle. */
+ RTTHREAD Thread;
+ /** The user parameter. */
+ R3PTRTYPE(void *) pvUser;
+ /** Data specific to the kind of thread.
+ * This should really be in PDMTHREADINT, but is placed here because of the
+ * function pointer typedefs. So, don't touch these, please.
+ */
+ union
+ {
+ /** PDMTHREADTYPE_DEVICE data. */
+ struct
+ {
+ /** The device instance. */
+ PPDMDEVINSR3 pDevIns;
+ /** The thread function. */
+ R3PTRTYPE(PFNPDMTHREADDEV) pfnThread;
+ /** Thread. */
+ R3PTRTYPE(PFNPDMTHREADWAKEUPDEV) pfnWakeUp;
+ } Dev;
+
+ /** PDMTHREADTYPE_USB data. */
+ struct
+ {
+ /** The device instance. */
+ PPDMUSBINS pUsbIns;
+ /** The thread function. */
+ R3PTRTYPE(PFNPDMTHREADUSB) pfnThread;
+ /** Thread. */
+ R3PTRTYPE(PFNPDMTHREADWAKEUPUSB) pfnWakeUp;
+ } Usb;
+
+ /** PDMTHREADTYPE_DRIVER data. */
+ struct
+ {
+ /** The driver instance. */
+ R3PTRTYPE(PPDMDRVINS) pDrvIns;
+ /** The thread function. */
+ R3PTRTYPE(PFNPDMTHREADDRV) pfnThread;
+ /** Thread. */
+ R3PTRTYPE(PFNPDMTHREADWAKEUPDRV) pfnWakeUp;
+ } Drv;
+
+ /** PDMTHREADTYPE_INTERNAL data. */
+ struct
+ {
+ /** The thread function. */
+ R3PTRTYPE(PFNPDMTHREADINT) pfnThread;
+ /** Thread. */
+ R3PTRTYPE(PFNPDMTHREADWAKEUPINT) pfnWakeUp;
+ } Int;
+
+ /** PDMTHREADTYPE_EXTERNAL data. */
+ struct
+ {
+ /** The thread function. */
+ R3PTRTYPE(PFNPDMTHREADEXT) pfnThread;
+ /** Thread. */
+ R3PTRTYPE(PFNPDMTHREADWAKEUPEXT) pfnWakeUp;
+ } Ext;
+ } u;
+
+ /** Internal data. */
+ union
+ {
+#ifdef PDMTHREADINT_DECLARED
+ PDMTHREADINT s;
+#endif
+ uint8_t padding[64];
+ } Internal;
+} PDMTHREAD;
+
+/** PDMTHREAD::u32Version value. */
+#define PDMTHREAD_VERSION PDM_VERSION_MAKE(0xefff, 1, 0)
+
+#ifdef IN_RING3
+VMMR3DECL(int) PDMR3ThreadCreate(PVM pVM, PPPDMTHREAD ppThread, void *pvUser, PFNPDMTHREADINT pfnThread,
+ PFNPDMTHREADWAKEUPINT pfnWakeUp, size_t cbStack, RTTHREADTYPE enmType, const char *pszName);
+VMMR3DECL(int) PDMR3ThreadCreateExternal(PVM pVM, PPPDMTHREAD ppThread, void *pvUser, PFNPDMTHREADEXT pfnThread,
+ PFNPDMTHREADWAKEUPEXT pfnWakeUp, size_t cbStack, RTTHREADTYPE enmType, const char *pszName);
+VMMR3DECL(int) PDMR3ThreadDestroy(PPDMTHREAD pThread, int *pRcThread);
+VMMR3DECL(int) PDMR3ThreadIAmSuspending(PPDMTHREAD pThread);
+VMMR3DECL(int) PDMR3ThreadIAmRunning(PPDMTHREAD pThread);
+VMMR3DECL(int) PDMR3ThreadSleep(PPDMTHREAD pThread, RTMSINTERVAL cMillies);
+VMMR3DECL(int) PDMR3ThreadSuspend(PPDMTHREAD pThread);
+VMMR3DECL(int) PDMR3ThreadResume(PPDMTHREAD pThread);
+#endif /* IN_RING3 */
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !VBOX_INCLUDED_vmm_pdmthread_h */
diff --git a/include/VBox/vmm/pdmtpmifs.h b/include/VBox/vmm/pdmtpmifs.h
new file mode 100644
index 00000000..22a15839
--- /dev/null
+++ b/include/VBox/vmm/pdmtpmifs.h
@@ -0,0 +1,163 @@
+/** @file
+ * PDM - Pluggable Device Manager, TPM related interfaces.
+ */
+
+/*
+ * Copyright (C) 2021-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vmm_pdmtpmifs_h
+#define VBOX_INCLUDED_vmm_pdmtpmifs_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/types.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_pdm_ifs_tpm PDM TPM Interfaces
+ * @ingroup grp_pdm_interfaces
+ * @{
+ */
+
+
+/** Pointer to a TPM port interface. */
+typedef struct PDMITPMPORT *PPDMITPMPORT;
+/**
+ * TPM port interface (down).
+ */
+typedef struct PDMITPMPORT
+{
+ /**
+ * @todo
+ */
+ DECLR3CALLBACKMEMBER(int, pfnDummy, (PPDMITPMPORT pInterface));
+
+} PDMITPMPORT;
+/** PDMITPMPORT interface ID. */
+#define PDMITPMPORT_IID "1e57710f-f820-47ec-afa6-2713195f8f94"
+
+
+/**
+ * TPM version enumeration.
+ */
+typedef enum TPMVERSION
+{
+ /** Invalid TPM version, don't use. */
+ TPMVERSION_INVALID = 0,
+ /** TPM works according to version 1.2 of the specification. */
+ TPMVERSION_1_2,
+ /** TPM works according to version 2.0 of the specification. */
+ TPMVERSION_2_0,
+ /** TPM version is unknown. */
+ TPMVERSION_UNKNOWN
+} TPMVERSION;
+
+
+/** Pointer to a TPM interface. */
+typedef struct PDMITPMCONNECTOR *PPDMITPMCONNECTOR;
+/**
+ * TPM interface (up).
+ * Pairs with PDMITPMPORT.
+ */
+typedef struct PDMITPMCONNECTOR
+{
+ /**
+ * Returns the version of the TPM implemented by the driver below.
+ *
+ * @returns The TPM version.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ */
+ DECLR3CALLBACKMEMBER(TPMVERSION, pfnGetVersion, (PPDMITPMCONNECTOR pInterface));
+
+ /**
+ * Returns the maximum supported locality of the driver below.
+ *
+ * @returns The maximum supported locality (0-4).
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ */
+ DECLR3CALLBACKMEMBER(uint32_t, pfnGetLocalityMax, (PPDMITPMCONNECTOR pInterface));
+
+ /**
+ * Returns the command/response buffer size of the driver below.
+ *
+ * @returns Buffer size in bytes.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ */
+ DECLR3CALLBACKMEMBER(uint32_t, pfnGetBufferSize, (PPDMITPMCONNECTOR pInterface));
+
+ /**
+ * Returns the status of the established flag.
+ *
+ * @returns Status of the established flag.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ */
+ DECLR3CALLBACKMEMBER(bool, pfnGetEstablishedFlag, (PPDMITPMCONNECTOR pInterface));
+
+ /**
+ * Resets the TPM established flag.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param bLoc The locality issuing this request.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnResetEstablishedFlag, (PPDMITPMCONNECTOR pInterface, uint8_t bLoc));
+
+ /**
+ * Executes the given command.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param bLoc The locality the command is issued from.
+ * @param pvCmd Pointer to the command data.
+ * @param cbCmd Size of the command in bytes.
+ * @param pvResp Where to store the response data.
+ * @param cbResp Size of the response buffer in bytes.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnCmdExec, (PPDMITPMCONNECTOR pInterface, uint8_t bLoc, const void *pvCmd, size_t cbCmd, void *pvResp, size_t cbResp));
+
+ /**
+ * Cancels the currently executed command.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnCmdCancel, (PPDMITPMCONNECTOR pInterface));
+
+} PDMITPMCONNECTOR;
+/** PDMITPMCONNECTOR interface ID. */
+#define PDMITPMCONNECTOR_IID "30afefd8-c11f-4e2a-a746-424e3d99fa86"
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !VBOX_INCLUDED_vmm_pdmtpmifs_h */
diff --git a/include/VBox/vmm/pdmusb.h b/include/VBox/vmm/pdmusb.h
new file mode 100644
index 00000000..c27c33a7
--- /dev/null
+++ b/include/VBox/vmm/pdmusb.h
@@ -0,0 +1,1502 @@
+/** @file
+ * PDM - Pluggable Device Manager, USB Devices.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vmm_pdmusb_h
+#define VBOX_INCLUDED_vmm_pdmusb_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/vmm/pdmqueue.h>
+#include <VBox/vmm/pdmcritsect.h>
+#include <VBox/vmm/pdmthread.h>
+#include <VBox/vmm/pdmifs.h>
+#include <VBox/vmm/pdmins.h>
+#include <VBox/vmm/pdmcommon.h>
+#include <VBox/vmm/tm.h>
+#include <VBox/vmm/ssm.h>
+#include <VBox/vmm/cfgm.h>
+#include <VBox/vmm/dbgf.h>
+#include <VBox/vmm/mm.h>
+#include <VBox/vusb.h>
+#include <iprt/errcore.h>
+#include <iprt/stdarg.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_pdm_usbdev The USB Devices API
+ * @ingroup grp_pdm
+ * @{
+ */
+
+
+/**
+ * A string entry for the USB descriptor cache.
+ */
+typedef struct PDMUSBDESCCACHESTRING
+{
+ /** The string index. */
+ uint8_t idx;
+ /** The UTF-8 representation of the string. */
+ const char *psz;
+} PDMUSBDESCCACHESTRING;
+/** Pointer to a const string entry. */
+typedef PDMUSBDESCCACHESTRING const *PCPDMUSBDESCCACHESTRING;
+
+
+/**
+ * A language entry for the USB descriptor cache.
+ */
+typedef struct PDMUSBDESCCACHELANG
+{
+ /** The language ID for the strings in this block. */
+ uint16_t idLang;
+ /** The number of strings in the array. */
+ uint16_t cStrings;
+ /** Pointer to an array of associated strings.
+ * This must be sorted in ascending order by string index as a binary lookup
+ * will be performed. */
+ PCPDMUSBDESCCACHESTRING paStrings;
+} PDMUSBDESCCACHELANG;
+/** Pointer to a const language entry. */
+typedef PDMUSBDESCCACHELANG const *PCPDMUSBDESCCACHELANG;
+
+
+/**
+ * USB descriptor cache.
+ *
+ * This structure is owned by the USB device but provided to the PDM/VUSB layer
+ * thru the PDMUSBREG::pfnGetDescriptorCache method. PDM/VUSB will use the
+ * information here to map addresses to endpoints, perform SET_CONFIGURATION
+ * requests, and optionally perform GET_DESCRIPTOR requests (see flag).
+ *
+ * Currently, only device and configuration descriptors are cached.
+ */
+typedef struct PDMUSBDESCCACHE
+{
+ /** USB device descriptor */
+ PCVUSBDESCDEVICE pDevice;
+ /** USB Descriptor arrays (pDev->bNumConfigurations) */
+ PCVUSBDESCCONFIGEX paConfigs;
+ /** Language IDs and their associated strings.
+ * This must be sorted in ascending order by language ID as a binary lookup
+ * will be used. */
+ PCPDMUSBDESCCACHELANG paLanguages;
+ /** The number of entries in the array pointed to by paLanguages. */
+ uint16_t cLanguages;
+ /** Use the cached descriptors for GET_DESCRIPTOR requests. */
+ bool fUseCachedDescriptors;
+ /** Use the cached string descriptors. */
+ bool fUseCachedStringsDescriptors;
+} PDMUSBDESCCACHE;
+/** Pointer to an USB descriptor cache. */
+typedef PDMUSBDESCCACHE *PPDMUSBDESCCACHE;
+/** Pointer to a const USB descriptor cache. */
+typedef const PDMUSBDESCCACHE *PCPDMUSBDESCCACHE;
+
+
+/** PDM Device Flags.
+ * @{ */
+/** A high-speed capable USB 2.0 device (also required to support full-speed). */
+#define PDM_USBREG_HIGHSPEED_CAPABLE RT_BIT(0)
+/** Indicates that the device implements the saved state handlers. */
+#define PDM_USBREG_SAVED_STATE_SUPPORTED RT_BIT(1)
+/** A SuperSpeed USB 3.0 device. */
+#define PDM_USBREG_SUPERSPEED_CAPABLE RT_BIT(2)
+/** @} */
+
+/** PDM USB Device Registration Structure,
+ *
+ * This structure is used when registering a device from VBoxUsbRegister() in HC Ring-3.
+ * The PDM will make use of this structure until the VM is destroyed.
+ */
+typedef struct PDMUSBREG
+{
+ /** Structure version. PDM_DEVREG_VERSION defines the current version. */
+ uint32_t u32Version;
+ /** Device name. */
+ char szName[32];
+ /** The description of the device. The UTF-8 string pointed to shall, like this structure,
+ * remain unchanged from registration till VM destruction. */
+ const char *pszDescription;
+
+ /** Flags, combination of the PDM_USBREG_FLAGS_* \#defines. */
+ RTUINT fFlags;
+ /** Maximum number of instances (per VM). */
+ RTUINT cMaxInstances;
+ /** Size of the instance data. */
+ RTUINT cbInstance;
+
+
+ /**
+ * Construct an USB device instance for a VM.
+ *
+ * @returns VBox status.
+ * @param pUsbIns The USB device instance data.
+ * If the registration structure is needed, it will be
+ * accessible thru pUsbDev->pReg.
+ * @param iInstance Instance number. Use this to figure out which registers
+ * and such to use. The instance number is also found in
+ * pUsbDev->iInstance, but since it's likely to be
+ * frequently used PDM passes it as parameter.
+ * @param pCfg Configuration node handle for the device. Use this to
+ * obtain the configuration of the device instance. It is
+ * also found in pUsbDev->pCfg, but since it is primary
+ * usage will in this function it is passed as a parameter.
+ * @param pCfgGlobal Handle to the global device configuration. Also found
+ * in pUsbDev->pCfgGlobal.
+ * @remarks This callback is required.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnConstruct,(PPDMUSBINS pUsbIns, int iInstance, PCFGMNODE pCfg, PCFGMNODE pCfgGlobal));
+
+ /**
+ * Destruct an USB device instance.
+ *
+ * Most VM resources are freed by the VM. This callback is provided so that any non-VM
+ * resources can be freed correctly.
+ *
+ * This method will be called regardless of the pfnConstruct result to avoid
+ * complicated failure paths.
+ *
+ * @param pUsbIns The USB device instance data.
+ * @remarks Optional.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnDestruct,(PPDMUSBINS pUsbIns));
+
+
+ /**
+ * Init complete notification.
+ *
+ * This can be done to do communication with other devices and other
+ * initialization which requires everything to be in place.
+ *
+ * @returns VBOX status code.
+ * @param pUsbIns The USB device instance data.
+ * @remarks Optional.
+ * @remarks Not called when hotplugged.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnVMInitComplete,(PPDMUSBINS pUsbIns));
+
+ /**
+ * VM Power On notification.
+ *
+ * @returns VBox status.
+ * @param pUsbIns The USB device instance data.
+ * @remarks Optional.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnVMPowerOn,(PPDMUSBINS pUsbIns));
+
+ /**
+ * VM Reset notification.
+ *
+ * @returns VBox status.
+ * @param pUsbIns The USB device instance data.
+ * @remarks Optional.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnVMReset,(PPDMUSBINS pUsbIns));
+
+ /**
+ * VM Suspend notification.
+ *
+ * @returns VBox status.
+ * @param pUsbIns The USB device instance data.
+ * @remarks Optional.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnVMSuspend,(PPDMUSBINS pUsbIns));
+
+ /**
+ * VM Resume notification.
+ *
+ * @returns VBox status.
+ * @param pUsbIns The USB device instance data.
+ * @remarks Optional.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnVMResume,(PPDMUSBINS pUsbIns));
+
+ /**
+ * VM Power Off notification.
+ *
+ * This is only called when the VMR3PowerOff call is made on a running VM. This
+ * means that there is no notification if the VM was suspended before being
+ * powered of. There will also be no callback when hot plugging devices.
+ *
+ * @param pUsbIns The USB device instance data.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnVMPowerOff,(PPDMUSBINS pUsbIns));
+
+ /**
+ * Called after the constructor when attaching a device at run time.
+ *
+ * This can be used to do tasks normally assigned to pfnInitComplete and/or pfnVMPowerOn.
+ *
+ * @returns VBox status.
+ * @param pUsbIns The USB device instance data.
+ * @remarks Optional.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnHotPlugged,(PPDMUSBINS pUsbIns));
+
+ /**
+ * Called before the destructor when a device is unplugged at run time.
+ *
+ * This can be used to do tasks normally assigned to pfnVMSuspend and/or pfnVMPowerOff.
+ *
+ * @returns VBox status.
+ * @param pUsbIns The USB device instance data.
+ * @remarks Optional.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnHotUnplugged,(PPDMUSBINS pUsbIns));
+ /**
+ * Driver Attach command.
+ *
+ * This is called to let the USB device attach to a driver for a specified LUN
+ * at runtime. This is not called during VM construction, the device constructor
+ * have to attach to all the available drivers.
+ *
+ * @returns VBox status code.
+ * @param pUsbIns The USB device instance data.
+ * @param iLUN The logical unit which is being detached.
+ * @param fFlags Flags, combination of the PDM_TACH_FLAGS_* \#defines.
+ * @remarks Optional.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnDriverAttach,(PPDMUSBINS pUsbIns, unsigned iLUN, uint32_t fFlags));
+
+ /**
+ * Driver Detach notification.
+ *
+ * This is called when a driver is detaching itself from a LUN of the device.
+ * The device should adjust it's state to reflect this.
+ *
+ * @param pUsbIns The USB device instance data.
+ * @param iLUN The logical unit which is being detached.
+ * @param fFlags Flags, combination of the PDM_TACH_FLAGS_* \#defines.
+ * @remarks Optional.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnDriverDetach,(PPDMUSBINS pUsbIns, unsigned iLUN, uint32_t fFlags));
+
+ /**
+ * Query the base interface of a logical unit.
+ *
+ * @returns VBOX status code.
+ * @param pUsbIns The USB device instance data.
+ * @param iLUN The logicial unit to query.
+ * @param ppBase Where to store the pointer to the base interface of the LUN.
+ * @remarks Optional.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnQueryInterface,(PPDMUSBINS pUsbIns, unsigned iLUN, PPDMIBASE *ppBase));
+
+ /**
+ * Requests the USB device to reset.
+ *
+ * @returns VBox status code.
+ * @param pUsbIns The USB device instance.
+ * @param fResetOnLinux A hint to the usb proxy.
+ * Don't use this unless you're the linux proxy device.
+ * @thread Any thread.
+ * @remarks Optional.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnUsbReset,(PPDMUSBINS pUsbIns, bool fResetOnLinux));
+
+ /**
+ * Query device and configuration descriptors for the caching and servicing
+ * relevant GET_DESCRIPTOR requests.
+ *
+ * @returns Pointer to the descriptor cache (read-only).
+ * @param pUsbIns The USB device instance.
+ * @remarks Mandatory.
+ */
+ DECLR3CALLBACKMEMBER(PCPDMUSBDESCCACHE, pfnUsbGetDescriptorCache,(PPDMUSBINS pUsbIns));
+
+ /**
+ * SET_CONFIGURATION request.
+ *
+ * @returns VBox status code.
+ * @param pUsbIns The USB device instance.
+ * @param bConfigurationValue The bConfigurationValue of the new configuration.
+ * @param pvOldCfgDesc Internal - for the device proxy.
+ * @param pvOldIfState Internal - for the device proxy.
+ * @param pvNewCfgDesc Internal - for the device proxy.
+ * @remarks Optional.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnUsbSetConfiguration,(PPDMUSBINS pUsbIns, uint8_t bConfigurationValue,
+ const void *pvOldCfgDesc, const void *pvOldIfState, const void *pvNewCfgDesc));
+
+ /**
+ * SET_INTERFACE request.
+ *
+ * @returns VBox status code.
+ * @param pUsbIns The USB device instance.
+ * @param bInterfaceNumber The interface number.
+ * @param bAlternateSetting The alternate setting.
+ * @remarks Optional.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnUsbSetInterface,(PPDMUSBINS pUsbIns, uint8_t bInterfaceNumber, uint8_t bAlternateSetting));
+
+ /**
+ * Clears the halted state of an endpoint. (Optional)
+ *
+ * This called when VUSB sees a CLEAR_FEATURE(ENDPOINT_HALT) on request
+ * on the zero pipe.
+ *
+ * @returns VBox status code.
+ * @param pUsbIns The USB device instance.
+ * @param uEndpoint The endpoint to clear.
+ * @remarks Optional.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnUsbClearHaltedEndpoint,(PPDMUSBINS pUsbIns, unsigned uEndpoint));
+
+ /**
+ * Allocates an URB.
+ *
+ * This can be used to make use of shared user/kernel mode buffers.
+ *
+ * @returns VBox status code.
+ * @param pUsbIns The USB device instance.
+ * @param cbData The size of the data buffer.
+ * @param cTds The number of TDs.
+ * @param enmType The type of URB.
+ * @param ppUrb Where to store the allocated URB.
+ * @remarks Optional.
+ * @remarks Not implemented yet.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnUrbNew,(PPDMUSBINS pUsbIns, size_t cbData, size_t cTds, VUSBXFERTYPE enmType, PVUSBURB *ppUrb));
+
+ /**
+ * Queues an URB for processing.
+ *
+ * @returns VBox status code.
+ * @retval VINF_SUCCESS on success.
+ * @retval VERR_VUSB_DEVICE_NOT_ATTACHED if the device has been disconnected.
+ * @retval VERR_VUSB_FAILED_TO_QUEUE_URB as a general failure kind of thing.
+ * @retval TBD - document new stuff!
+ *
+ * @param pUsbIns The USB device instance.
+ * @param pUrb The URB to process.
+ * @remarks Mandatory.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnUrbQueue,(PPDMUSBINS pUsbIns, PVUSBURB pUrb));
+
+ /**
+ * Cancels an URB.
+ *
+ * @returns VBox status code.
+ * @param pUsbIns The USB device instance.
+ * @param pUrb The URB to cancel.
+ * @remarks Mandatory.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnUrbCancel,(PPDMUSBINS pUsbIns, PVUSBURB pUrb));
+
+ /**
+ * Reaps an URB.
+ *
+ * @returns A ripe URB, NULL if none.
+ * @param pUsbIns The USB device instance.
+ * @param cMillies How log to wait for an URB to become ripe.
+ * @remarks Mandatory.
+ */
+ DECLR3CALLBACKMEMBER(PVUSBURB, pfnUrbReap,(PPDMUSBINS pUsbIns, RTMSINTERVAL cMillies));
+
+ /**
+ * Wakes a thread waiting in pfnUrbReap.
+ *
+ * @returns VBox status code.
+ * @param pUsbIns The USB device instance.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnWakeup,(PPDMUSBINS pUsbIns));
+
+ /** Just some init precaution. Must be set to PDM_USBREG_VERSION. */
+ uint32_t u32TheEnd;
+} PDMUSBREG;
+/** Pointer to a PDM USB Device Structure. */
+typedef PDMUSBREG *PPDMUSBREG;
+/** Const pointer to a PDM USB Device Structure. */
+typedef PDMUSBREG const *PCPDMUSBREG;
+
+/** Current USBREG version number. */
+#define PDM_USBREG_VERSION PDM_VERSION_MAKE(0xeeff, 2, 0)
+
+/** PDM USB Device Flags.
+ * @{ */
+/* none yet */
+/** @} */
+
+
+#ifdef IN_RING3
+
+/**
+ * PDM USB Device API.
+ */
+typedef struct PDMUSBHLP
+{
+ /** Structure version. PDM_USBHLP_VERSION defines the current version. */
+ uint32_t u32Version;
+
+ /**
+ * Attaches a driver (chain) to the USB device.
+ *
+ * The first call for a LUN this will serve as a registration of the LUN. The pBaseInterface and
+ * the pszDesc string will be registered with that LUN and kept around for PDMR3QueryUSBDeviceLun().
+ *
+ * @returns VBox status code.
+ * @param pUsbIns The USB device instance.
+ * @param iLun The logical unit to attach.
+ * @param pBaseInterface Pointer to the base interface for that LUN. (device side / down)
+ * @param ppBaseInterface Where to store the pointer to the base interface. (driver side / up)
+ * @param pszDesc Pointer to a string describing the LUN. This string must remain valid
+ * for the live of the device instance.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnDriverAttach,(PPDMUSBINS pUsbIns, RTUINT iLun, PPDMIBASE pBaseInterface, PPDMIBASE *ppBaseInterface, const char *pszDesc));
+
+ /**
+ * Assert that the current thread is the emulation thread.
+ *
+ * @returns True if correct.
+ * @returns False if wrong.
+ * @param pUsbIns The USB device instance.
+ * @param pszFile Filename of the assertion location.
+ * @param iLine Linenumber of the assertion location.
+ * @param pszFunction Function of the assertion location.
+ */
+ DECLR3CALLBACKMEMBER(bool, pfnAssertEMT,(PPDMUSBINS pUsbIns, const char *pszFile, unsigned iLine, const char *pszFunction));
+
+ /**
+ * Assert that the current thread is NOT the emulation thread.
+ *
+ * @returns True if correct.
+ * @returns False if wrong.
+ * @param pUsbIns The USB device instance.
+ * @param pszFile Filename of the assertion location.
+ * @param iLine Linenumber of the assertion location.
+ * @param pszFunction Function of the assertion location.
+ */
+ DECLR3CALLBACKMEMBER(bool, pfnAssertOther,(PPDMUSBINS pUsbIns, const char *pszFile, unsigned iLine, const char *pszFunction));
+
+ /**
+ * Stops the VM and enters the debugger to look at the guest state.
+ *
+ * Use the PDMUsbDBGFStop() inline function with the RT_SRC_POS macro instead of
+ * invoking this function directly.
+ *
+ * @returns VBox status code which must be passed up to the VMM.
+ * @param pUsbIns The USB device instance.
+ * @param pszFile Filename of the assertion location.
+ * @param iLine The linenumber of the assertion location.
+ * @param pszFunction Function of the assertion location.
+ * @param pszFormat Message. (optional)
+ * @param va Message parameters.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnDBGFStopV,(PPDMUSBINS pUsbIns, const char *pszFile, unsigned iLine, const char *pszFunction,
+ const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(5, 0));
+
+ /**
+ * Register a info handler with DBGF, argv style.
+ *
+ * @returns VBox status code.
+ * @param pUsbIns The USB device instance.
+ * @param pszName The identifier of the info.
+ * @param pszDesc The description of the info and any arguments the handler may take.
+ * @param pfnHandler The handler function to be called to display the info.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnDBGFInfoRegisterArgv,(PPDMUSBINS pUsbIns, const char *pszName, const char *pszDesc, PFNDBGFINFOARGVUSB pfnHandler));
+
+ /**
+ * Allocate memory which is associated with current VM instance
+ * and automatically freed on it's destruction.
+ *
+ * @returns Pointer to allocated memory. The memory is *NOT* zero-ed.
+ * @param pUsbIns The USB device instance.
+ * @param cb Number of bytes to allocate.
+ */
+ DECLR3CALLBACKMEMBER(void *, pfnMMHeapAlloc,(PPDMUSBINS pUsbIns, size_t cb));
+
+ /**
+ * Allocate memory which is associated with current VM instance
+ * and automatically freed on it's destruction. The memory is ZEROed.
+ *
+ * @returns Pointer to allocated memory. The memory is *NOT* zero-ed.
+ * @param pUsbIns The USB device instance.
+ * @param cb Number of bytes to allocate.
+ */
+ DECLR3CALLBACKMEMBER(void *, pfnMMHeapAllocZ,(PPDMUSBINS pUsbIns, size_t cb));
+
+ /**
+ * Free memory allocated with pfnMMHeapAlloc() and pfnMMHeapAllocZ().
+ *
+ * @param pUsbIns The USB device instance.
+ * @param pv Pointer to the memory to free.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnMMHeapFree,(PPDMUSBINS pUsbIns, void *pv));
+
+ /**
+ * Create a queue.
+ *
+ * @returns VBox status code.
+ * @param pUsbIns The USB device instance.
+ * @param cbItem Size a queue item.
+ * @param cItems Number of items in the queue.
+ * @param cMilliesInterval Number of milliseconds between polling the queue.
+ * If 0 then the emulation thread will be notified whenever an item arrives.
+ * @param pfnCallback The consumer function.
+ * @param pszName The queue base name. The instance number will be
+ * appended automatically.
+ * @param ppQueue Where to store the queue handle on success.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPDMQueueCreate,(PPDMUSBINS pUsbIns, RTUINT cbItem, RTUINT cItems, uint32_t cMilliesInterval,
+ PFNPDMQUEUEUSB pfnCallback, const char *pszName, PPDMQUEUE *ppQueue));
+
+ /**
+ * Register a save state data unit.
+ *
+ * @returns VBox status.
+ * @param pUsbIns The USB device instance.
+ * @param uVersion Data layout version number.
+ * @param cbGuess The approximate amount of data in the unit.
+ * Only for progress indicators.
+ *
+ * @param pfnLivePrep Prepare live save callback, optional.
+ * @param pfnLiveExec Execute live save callback, optional.
+ * @param pfnLiveVote Vote live save callback, optional.
+ *
+ * @param pfnSavePrep Prepare save callback, optional.
+ * @param pfnSaveExec Execute save callback, optional.
+ * @param pfnSaveDone Done save callback, optional.
+ *
+ * @param pfnLoadPrep Prepare load callback, optional.
+ * @param pfnLoadExec Execute load callback, optional.
+ * @param pfnLoadDone Done load callback, optional.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSSMRegister,(PPDMUSBINS pUsbIns, uint32_t uVersion, size_t cbGuess,
+ PFNSSMUSBLIVEPREP pfnLivePrep, PFNSSMUSBLIVEEXEC pfnLiveExec, PFNSSMUSBLIVEVOTE pfnLiveVote,
+ PFNSSMUSBSAVEPREP pfnSavePrep, PFNSSMUSBSAVEEXEC pfnSaveExec, PFNSSMUSBSAVEDONE pfnSaveDone,
+ PFNSSMUSBLOADPREP pfnLoadPrep, PFNSSMUSBLOADEXEC pfnLoadExec, PFNSSMUSBLOADDONE pfnLoadDone));
+
+ /** @name Exported SSM Functions
+ * @{ */
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutStruct,(PSSMHANDLE pSSM, const void *pvStruct, PCSSMFIELD paFields));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutStructEx,(PSSMHANDLE pSSM, const void *pvStruct, size_t cbStruct, uint32_t fFlags, PCSSMFIELD paFields, void *pvUser));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutBool,(PSSMHANDLE pSSM, bool fBool));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutU8,(PSSMHANDLE pSSM, uint8_t u8));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutS8,(PSSMHANDLE pSSM, int8_t i8));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutU16,(PSSMHANDLE pSSM, uint16_t u16));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutS16,(PSSMHANDLE pSSM, int16_t i16));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutU32,(PSSMHANDLE pSSM, uint32_t u32));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutS32,(PSSMHANDLE pSSM, int32_t i32));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutU64,(PSSMHANDLE pSSM, uint64_t u64));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutS64,(PSSMHANDLE pSSM, int64_t i64));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutU128,(PSSMHANDLE pSSM, uint128_t u128));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutS128,(PSSMHANDLE pSSM, int128_t i128));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutUInt,(PSSMHANDLE pSSM, RTUINT u));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutSInt,(PSSMHANDLE pSSM, RTINT i));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutGCUInt,(PSSMHANDLE pSSM, RTGCUINT u));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutGCUIntReg,(PSSMHANDLE pSSM, RTGCUINTREG u));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutGCPhys32,(PSSMHANDLE pSSM, RTGCPHYS32 GCPhys));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutGCPhys64,(PSSMHANDLE pSSM, RTGCPHYS64 GCPhys));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutGCPhys,(PSSMHANDLE pSSM, RTGCPHYS GCPhys));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutGCPtr,(PSSMHANDLE pSSM, RTGCPTR GCPtr));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutGCUIntPtr,(PSSMHANDLE pSSM, RTGCUINTPTR GCPtr));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutRCPtr,(PSSMHANDLE pSSM, RTRCPTR RCPtr));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutIOPort,(PSSMHANDLE pSSM, RTIOPORT IOPort));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutSel,(PSSMHANDLE pSSM, RTSEL Sel));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutMem,(PSSMHANDLE pSSM, const void *pv, size_t cb));
+ DECLR3CALLBACKMEMBER(int, pfnSSMPutStrZ,(PSSMHANDLE pSSM, const char *psz));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetStruct,(PSSMHANDLE pSSM, void *pvStruct, PCSSMFIELD paFields));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetStructEx,(PSSMHANDLE pSSM, void *pvStruct, size_t cbStruct, uint32_t fFlags, PCSSMFIELD paFields, void *pvUser));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetBool,(PSSMHANDLE pSSM, bool *pfBool));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetBoolV,(PSSMHANDLE pSSM, bool volatile *pfBool));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetU8,(PSSMHANDLE pSSM, uint8_t *pu8));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetU8V,(PSSMHANDLE pSSM, uint8_t volatile *pu8));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetS8,(PSSMHANDLE pSSM, int8_t *pi8));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetS8V,(PSSMHANDLE pSSM, int8_t volatile *pi8));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetU16,(PSSMHANDLE pSSM, uint16_t *pu16));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetU16V,(PSSMHANDLE pSSM, uint16_t volatile *pu16));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetS16,(PSSMHANDLE pSSM, int16_t *pi16));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetS16V,(PSSMHANDLE pSSM, int16_t volatile *pi16));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetU32,(PSSMHANDLE pSSM, uint32_t *pu32));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetU32V,(PSSMHANDLE pSSM, uint32_t volatile *pu32));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetS32,(PSSMHANDLE pSSM, int32_t *pi32));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetS32V,(PSSMHANDLE pSSM, int32_t volatile *pi32));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetU64,(PSSMHANDLE pSSM, uint64_t *pu64));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetU64V,(PSSMHANDLE pSSM, uint64_t volatile *pu64));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetS64,(PSSMHANDLE pSSM, int64_t *pi64));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetS64V,(PSSMHANDLE pSSM, int64_t volatile *pi64));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetU128,(PSSMHANDLE pSSM, uint128_t *pu128));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetU128V,(PSSMHANDLE pSSM, uint128_t volatile *pu128));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetS128,(PSSMHANDLE pSSM, int128_t *pi128));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetS128V,(PSSMHANDLE pSSM, int128_t volatile *pi128));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetGCPhys32,(PSSMHANDLE pSSM, PRTGCPHYS32 pGCPhys));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetGCPhys32V,(PSSMHANDLE pSSM, RTGCPHYS32 volatile *pGCPhys));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetGCPhys64,(PSSMHANDLE pSSM, PRTGCPHYS64 pGCPhys));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetGCPhys64V,(PSSMHANDLE pSSM, RTGCPHYS64 volatile *pGCPhys));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetGCPhys,(PSSMHANDLE pSSM, PRTGCPHYS pGCPhys));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetGCPhysV,(PSSMHANDLE pSSM, RTGCPHYS volatile *pGCPhys));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetUInt,(PSSMHANDLE pSSM, PRTUINT pu));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetSInt,(PSSMHANDLE pSSM, PRTINT pi));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetGCUInt,(PSSMHANDLE pSSM, PRTGCUINT pu));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetGCUIntReg,(PSSMHANDLE pSSM, PRTGCUINTREG pu));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetGCPtr,(PSSMHANDLE pSSM, PRTGCPTR pGCPtr));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetGCUIntPtr,(PSSMHANDLE pSSM, PRTGCUINTPTR pGCPtr));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetRCPtr,(PSSMHANDLE pSSM, PRTRCPTR pRCPtr));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetIOPort,(PSSMHANDLE pSSM, PRTIOPORT pIOPort));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetSel,(PSSMHANDLE pSSM, PRTSEL pSel));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetMem,(PSSMHANDLE pSSM, void *pv, size_t cb));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetStrZ,(PSSMHANDLE pSSM, char *psz, size_t cbMax));
+ DECLR3CALLBACKMEMBER(int, pfnSSMGetStrZEx,(PSSMHANDLE pSSM, char *psz, size_t cbMax, size_t *pcbStr));
+ DECLR3CALLBACKMEMBER(int, pfnSSMSkip,(PSSMHANDLE pSSM, size_t cb));
+ DECLR3CALLBACKMEMBER(int, pfnSSMSkipToEndOfUnit,(PSSMHANDLE pSSM));
+ DECLR3CALLBACKMEMBER(int, pfnSSMSetLoadError,(PSSMHANDLE pSSM, int rc, RT_SRC_POS_DECL, const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(6, 7));
+ DECLR3CALLBACKMEMBER(int, pfnSSMSetLoadErrorV,(PSSMHANDLE pSSM, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(6, 0));
+ DECLR3CALLBACKMEMBER(int, pfnSSMSetCfgError,(PSSMHANDLE pSSM, RT_SRC_POS_DECL, const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(5, 6));
+ DECLR3CALLBACKMEMBER(int, pfnSSMSetCfgErrorV,(PSSMHANDLE pSSM, RT_SRC_POS_DECL, const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(5, 0));
+ DECLR3CALLBACKMEMBER(int, pfnSSMHandleGetStatus,(PSSMHANDLE pSSM));
+ DECLR3CALLBACKMEMBER(SSMAFTER, pfnSSMHandleGetAfter,(PSSMHANDLE pSSM));
+ DECLR3CALLBACKMEMBER(bool, pfnSSMHandleIsLiveSave,(PSSMHANDLE pSSM));
+ DECLR3CALLBACKMEMBER(uint32_t, pfnSSMHandleMaxDowntime,(PSSMHANDLE pSSM));
+ DECLR3CALLBACKMEMBER(uint32_t, pfnSSMHandleHostBits,(PSSMHANDLE pSSM));
+ DECLR3CALLBACKMEMBER(uint32_t, pfnSSMHandleRevision,(PSSMHANDLE pSSM));
+ DECLR3CALLBACKMEMBER(uint32_t, pfnSSMHandleVersion,(PSSMHANDLE pSSM));
+ DECLR3CALLBACKMEMBER(const char *, pfnSSMHandleHostOSAndArch,(PSSMHANDLE pSSM));
+ /** @} */
+
+ /** @name Exported CFGM Functions.
+ * @{ */
+ DECLR3CALLBACKMEMBER(bool, pfnCFGMExists,( PCFGMNODE pNode, const char *pszName));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryType,( PCFGMNODE pNode, const char *pszName, PCFGMVALUETYPE penmType));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQuerySize,( PCFGMNODE pNode, const char *pszName, size_t *pcb));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryInteger,( PCFGMNODE pNode, const char *pszName, uint64_t *pu64));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryIntegerDef,( PCFGMNODE pNode, const char *pszName, uint64_t *pu64, uint64_t u64Def));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryString,( PCFGMNODE pNode, const char *pszName, char *pszString, size_t cchString));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryStringDef,( PCFGMNODE pNode, const char *pszName, char *pszString, size_t cchString, const char *pszDef));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryBytes,( PCFGMNODE pNode, const char *pszName, void *pvData, size_t cbData));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryU64,( PCFGMNODE pNode, const char *pszName, uint64_t *pu64));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryU64Def,( PCFGMNODE pNode, const char *pszName, uint64_t *pu64, uint64_t u64Def));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryS64,( PCFGMNODE pNode, const char *pszName, int64_t *pi64));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryS64Def,( PCFGMNODE pNode, const char *pszName, int64_t *pi64, int64_t i64Def));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryU32,( PCFGMNODE pNode, const char *pszName, uint32_t *pu32));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryU32Def,( PCFGMNODE pNode, const char *pszName, uint32_t *pu32, uint32_t u32Def));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryS32,( PCFGMNODE pNode, const char *pszName, int32_t *pi32));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryS32Def,( PCFGMNODE pNode, const char *pszName, int32_t *pi32, int32_t i32Def));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryU16,( PCFGMNODE pNode, const char *pszName, uint16_t *pu16));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryU16Def,( PCFGMNODE pNode, const char *pszName, uint16_t *pu16, uint16_t u16Def));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryS16,( PCFGMNODE pNode, const char *pszName, int16_t *pi16));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryS16Def,( PCFGMNODE pNode, const char *pszName, int16_t *pi16, int16_t i16Def));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryU8,( PCFGMNODE pNode, const char *pszName, uint8_t *pu8));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryU8Def,( PCFGMNODE pNode, const char *pszName, uint8_t *pu8, uint8_t u8Def));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryS8,( PCFGMNODE pNode, const char *pszName, int8_t *pi8));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryS8Def,( PCFGMNODE pNode, const char *pszName, int8_t *pi8, int8_t i8Def));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryBool,( PCFGMNODE pNode, const char *pszName, bool *pf));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryBoolDef,( PCFGMNODE pNode, const char *pszName, bool *pf, bool fDef));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryPort,( PCFGMNODE pNode, const char *pszName, PRTIOPORT pPort));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryPortDef,( PCFGMNODE pNode, const char *pszName, PRTIOPORT pPort, RTIOPORT PortDef));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryUInt,( PCFGMNODE pNode, const char *pszName, unsigned int *pu));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryUIntDef,( PCFGMNODE pNode, const char *pszName, unsigned int *pu, unsigned int uDef));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQuerySInt,( PCFGMNODE pNode, const char *pszName, signed int *pi));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQuerySIntDef,( PCFGMNODE pNode, const char *pszName, signed int *pi, signed int iDef));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryGCPtr,( PCFGMNODE pNode, const char *pszName, PRTGCPTR pGCPtr));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryGCPtrDef,( PCFGMNODE pNode, const char *pszName, PRTGCPTR pGCPtr, RTGCPTR GCPtrDef));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryGCPtrU,( PCFGMNODE pNode, const char *pszName, PRTGCUINTPTR pGCPtr));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryGCPtrUDef,( PCFGMNODE pNode, const char *pszName, PRTGCUINTPTR pGCPtr, RTGCUINTPTR GCPtrDef));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryGCPtrS,( PCFGMNODE pNode, const char *pszName, PRTGCINTPTR pGCPtr));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryGCPtrSDef,( PCFGMNODE pNode, const char *pszName, PRTGCINTPTR pGCPtr, RTGCINTPTR GCPtrDef));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryStringAlloc,( PCFGMNODE pNode, const char *pszName, char **ppszString));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMQueryStringAllocDef,(PCFGMNODE pNode, const char *pszName, char **ppszString, const char *pszDef));
+ DECLR3CALLBACKMEMBER(PCFGMNODE, pfnCFGMGetParent,(PCFGMNODE pNode));
+ DECLR3CALLBACKMEMBER(PCFGMNODE, pfnCFGMGetChild,(PCFGMNODE pNode, const char *pszPath));
+ DECLR3CALLBACKMEMBER(PCFGMNODE, pfnCFGMGetChildF,(PCFGMNODE pNode, const char *pszPathFormat, ...) RT_IPRT_FORMAT_ATTR(2, 3));
+ DECLR3CALLBACKMEMBER(PCFGMNODE, pfnCFGMGetChildFV,(PCFGMNODE pNode, const char *pszPathFormat, va_list Args) RT_IPRT_FORMAT_ATTR(3, 0));
+ DECLR3CALLBACKMEMBER(PCFGMNODE, pfnCFGMGetFirstChild,(PCFGMNODE pNode));
+ DECLR3CALLBACKMEMBER(PCFGMNODE, pfnCFGMGetNextChild,(PCFGMNODE pCur));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMGetName,(PCFGMNODE pCur, char *pszName, size_t cchName));
+ DECLR3CALLBACKMEMBER(size_t, pfnCFGMGetNameLen,(PCFGMNODE pCur));
+ DECLR3CALLBACKMEMBER(bool, pfnCFGMAreChildrenValid,(PCFGMNODE pNode, const char *pszzValid));
+ DECLR3CALLBACKMEMBER(PCFGMLEAF, pfnCFGMGetFirstValue,(PCFGMNODE pCur));
+ DECLR3CALLBACKMEMBER(PCFGMLEAF, pfnCFGMGetNextValue,(PCFGMLEAF pCur));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMGetValueName,(PCFGMLEAF pCur, char *pszName, size_t cchName));
+ DECLR3CALLBACKMEMBER(size_t, pfnCFGMGetValueNameLen,(PCFGMLEAF pCur));
+ DECLR3CALLBACKMEMBER(CFGMVALUETYPE, pfnCFGMGetValueType,(PCFGMLEAF pCur));
+ DECLR3CALLBACKMEMBER(bool, pfnCFGMAreValuesValid,(PCFGMNODE pNode, const char *pszzValid));
+ DECLR3CALLBACKMEMBER(int, pfnCFGMValidateConfig,(PCFGMNODE pNode, const char *pszNode,
+ const char *pszValidValues, const char *pszValidNodes,
+ const char *pszWho, uint32_t uInstance));
+ /** @} */
+
+ /**
+ * Register a STAM sample.
+ *
+ * Use the PDMUsbHlpSTAMRegister wrapper.
+ *
+ * @returns VBox status.
+ * @param pUsbIns The USB device instance.
+ * @param pvSample Pointer to the sample.
+ * @param enmType Sample type. This indicates what pvSample is pointing at.
+ * @param enmVisibility Visibility type specifying whether unused statistics should be visible or not.
+ * @param enmUnit Sample unit.
+ * @param pszDesc Sample description.
+ * @param pszName The sample name format string.
+ * @param va Arguments to the format string.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnSTAMRegisterV,(PPDMUSBINS pUsbIns, void *pvSample, STAMTYPE enmType,
+ STAMVISIBILITY enmVisibility, STAMUNIT enmUnit, const char *pszDesc,
+ const char *pszName, va_list va) RT_IPRT_FORMAT_ATTR(7, 0));
+
+ /**
+ * Creates a timer.
+ *
+ * @returns VBox status.
+ * @param pUsbIns The USB device instance.
+ * @param enmClock The clock to use on this timer.
+ * @param pfnCallback Callback function.
+ * @param pvUser User argument for the callback.
+ * @param fFlags Flags, see TMTIMER_FLAGS_*.
+ * @param pszDesc Pointer to description string which must stay around
+ * until the timer is fully destroyed (i.e. a bit after TMTimerDestroy()).
+ * @param phTimer Where to store the timer handle on success.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnTimerCreate,(PPDMUSBINS pUsbIns, TMCLOCK enmClock, PFNTMTIMERUSB pfnCallback, void *pvUser,
+ uint32_t fFlags, const char *pszDesc, PTMTIMERHANDLE phTimer));
+
+ /** @name Timer handle method wrappers
+ * @{ */
+ DECLR3CALLBACKMEMBER(uint64_t, pfnTimerFromMicro,(PPDMUSBINS pUsbIns, TMTIMERHANDLE hTimer, uint64_t cMicroSecs));
+ DECLR3CALLBACKMEMBER(uint64_t, pfnTimerFromMilli,(PPDMUSBINS pUsbIns, TMTIMERHANDLE hTimer, uint64_t cMilliSecs));
+ DECLR3CALLBACKMEMBER(uint64_t, pfnTimerFromNano,(PPDMUSBINS pUsbIns, TMTIMERHANDLE hTimer, uint64_t cNanoSecs));
+ DECLR3CALLBACKMEMBER(uint64_t, pfnTimerGet,(PPDMUSBINS pUsbIns, TMTIMERHANDLE hTimer));
+ DECLR3CALLBACKMEMBER(uint64_t, pfnTimerGetFreq,(PPDMUSBINS pUsbIns, TMTIMERHANDLE hTimer));
+ DECLR3CALLBACKMEMBER(uint64_t, pfnTimerGetNano,(PPDMUSBINS pUsbIns, TMTIMERHANDLE hTimer));
+ DECLR3CALLBACKMEMBER(bool, pfnTimerIsActive,(PPDMUSBINS pUsbIns, TMTIMERHANDLE hTimer));
+ DECLR3CALLBACKMEMBER(bool, pfnTimerIsLockOwner,(PPDMUSBINS pUsbIns, TMTIMERHANDLE hTimer));
+ DECLR3CALLBACKMEMBER(int, pfnTimerLockClock,(PPDMUSBINS pUsbIns, TMTIMERHANDLE hTimer));
+ /** Takes the clock lock then enters the specified critical section. */
+ DECLR3CALLBACKMEMBER(int, pfnTimerLockClock2,(PPDMUSBINS pUsbIns, TMTIMERHANDLE hTimer, PPDMCRITSECT pCritSect));
+ DECLR3CALLBACKMEMBER(int, pfnTimerSet,(PPDMUSBINS pUsbIns, TMTIMERHANDLE hTimer, uint64_t uExpire));
+ DECLR3CALLBACKMEMBER(int, pfnTimerSetFrequencyHint,(PPDMUSBINS pUsbIns, TMTIMERHANDLE hTimer, uint32_t uHz));
+ DECLR3CALLBACKMEMBER(int, pfnTimerSetMicro,(PPDMUSBINS pUsbIns, TMTIMERHANDLE hTimer, uint64_t cMicrosToNext));
+ DECLR3CALLBACKMEMBER(int, pfnTimerSetMillies,(PPDMUSBINS pUsbIns, TMTIMERHANDLE hTimer, uint64_t cMilliesToNext));
+ DECLR3CALLBACKMEMBER(int, pfnTimerSetNano,(PPDMUSBINS pUsbIns, TMTIMERHANDLE hTimer, uint64_t cNanosToNext));
+ DECLR3CALLBACKMEMBER(int, pfnTimerSetRelative,(PPDMUSBINS pUsbIns, TMTIMERHANDLE hTimer, uint64_t cTicksToNext, uint64_t *pu64Now));
+ DECLR3CALLBACKMEMBER(int, pfnTimerStop,(PPDMUSBINS pUsbIns, TMTIMERHANDLE hTimer));
+ DECLR3CALLBACKMEMBER(void, pfnTimerUnlockClock,(PPDMUSBINS pUsbIns, TMTIMERHANDLE hTimer));
+ DECLR3CALLBACKMEMBER(void, pfnTimerUnlockClock2,(PPDMUSBINS pUsbIns, TMTIMERHANDLE hTimer, PPDMCRITSECT pCritSect));
+ DECLR3CALLBACKMEMBER(int, pfnTimerSetCritSect,(PPDMUSBINS pUsbIns, TMTIMERHANDLE hTimer, PPDMCRITSECT pCritSect));
+ DECLR3CALLBACKMEMBER(int, pfnTimerSave,(PPDMUSBINS pUsbIns, TMTIMERHANDLE hTimer, PSSMHANDLE pSSM));
+ DECLR3CALLBACKMEMBER(int, pfnTimerLoad,(PPDMUSBINS pUsbIns, TMTIMERHANDLE hTimer, PSSMHANDLE pSSM));
+ DECLR3CALLBACKMEMBER(int, pfnTimerDestroy,(PPDMUSBINS pUsbIns, TMTIMERHANDLE hTimer));
+ /** @sa TMR3TimerSkip */
+ DECLR3CALLBACKMEMBER(int, pfnTimerSkipLoad,(PSSMHANDLE pSSM, bool *pfActive));
+ /** @} */
+
+ /**
+ * Set the VM error message
+ *
+ * @returns rc.
+ * @param pUsbIns The USB device instance.
+ * @param rc VBox status code.
+ * @param SRC_POS Use RT_SRC_POS.
+ * @param pszFormat Error message format string.
+ * @param va Error message arguments.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnVMSetErrorV,(PPDMUSBINS pUsbIns, int rc, RT_SRC_POS_DECL,
+ const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(6, 0));
+
+ /**
+ * Set the VM runtime error message
+ *
+ * @returns VBox status code.
+ * @param pUsbIns The USB device instance.
+ * @param fFlags The action flags. See VMSETRTERR_FLAGS_*.
+ * @param pszErrorId Error ID string.
+ * @param pszFormat Error message format string.
+ * @param va Error message arguments.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnVMSetRuntimeErrorV,(PPDMUSBINS pUsbIns, uint32_t fFlags, const char *pszErrorId,
+ const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(4, 0));
+
+ /**
+ * Gets the VM state.
+ *
+ * @returns VM state.
+ * @param pUsbIns The USB device instance.
+ * @thread Any thread (just keep in mind that it's volatile info).
+ */
+ DECLR3CALLBACKMEMBER(VMSTATE, pfnVMState, (PPDMUSBINS pUsbIns));
+
+ /**
+ * Creates a PDM thread.
+ *
+ * This differs from the RTThreadCreate() API in that PDM takes care of suspending,
+ * resuming, and destroying the thread as the VM state changes.
+ *
+ * @returns VBox status code.
+ * @param pUsbIns The USB device instance.
+ * @param ppThread Where to store the thread 'handle'.
+ * @param pvUser The user argument to the thread function.
+ * @param pfnThread The thread function.
+ * @param pfnWakeup The wakup callback. This is called on the EMT
+ * thread when a state change is pending.
+ * @param cbStack See RTThreadCreate.
+ * @param enmType See RTThreadCreate.
+ * @param pszName See RTThreadCreate.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnThreadCreate,(PPDMUSBINS pUsbIns, PPPDMTHREAD ppThread, void *pvUser, PFNPDMTHREADUSB pfnThread,
+ PFNPDMTHREADWAKEUPUSB pfnWakeup, size_t cbStack, RTTHREADTYPE enmType, const char *pszName));
+
+ /** @name Exported PDM Thread Functions
+ * @{ */
+ DECLR3CALLBACKMEMBER(int, pfnThreadDestroy,(PPDMTHREAD pThread, int *pRcThread));
+ DECLR3CALLBACKMEMBER(int, pfnThreadIAmSuspending,(PPDMTHREAD pThread));
+ DECLR3CALLBACKMEMBER(int, pfnThreadIAmRunning,(PPDMTHREAD pThread));
+ DECLR3CALLBACKMEMBER(int, pfnThreadSleep,(PPDMTHREAD pThread, RTMSINTERVAL cMillies));
+ DECLR3CALLBACKMEMBER(int, pfnThreadSuspend,(PPDMTHREAD pThread));
+ DECLR3CALLBACKMEMBER(int, pfnThreadResume,(PPDMTHREAD pThread));
+ /** @} */
+
+ /**
+ * Set up asynchronous handling of a suspend, reset or power off notification.
+ *
+ * This shall only be called when getting the notification. It must be called
+ * for each one.
+ *
+ * @returns VBox status code.
+ * @param pUsbIns The USB device instance.
+ * @param pfnAsyncNotify The callback.
+ * @thread EMT(0)
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSetAsyncNotification, (PPDMUSBINS pUSbIns, PFNPDMUSBASYNCNOTIFY pfnAsyncNotify));
+
+ /**
+ * Notify EMT(0) that the device has completed the asynchronous notification
+ * handling.
+ *
+ * This can be called at any time, spurious calls will simply be ignored.
+ *
+ * @param pUsbIns The USB device instance.
+ * @thread Any
+ */
+ DECLR3CALLBACKMEMBER(void, pfnAsyncNotificationCompleted, (PPDMUSBINS pUsbIns));
+
+ /**
+ * Gets the reason for the most recent VM suspend.
+ *
+ * @returns The suspend reason. VMSUSPENDREASON_INVALID is returned if no
+ * suspend has been made or if the pUsbIns is invalid.
+ * @param pUsbIns The driver instance.
+ */
+ DECLR3CALLBACKMEMBER(VMSUSPENDREASON, pfnVMGetSuspendReason,(PPDMUSBINS pUsbIns));
+
+ /**
+ * Gets the reason for the most recent VM resume.
+ *
+ * @returns The resume reason. VMRESUMEREASON_INVALID is returned if no
+ * resume has been made or if the pUsbIns is invalid.
+ * @param pUsbIns The driver instance.
+ */
+ DECLR3CALLBACKMEMBER(VMRESUMEREASON, pfnVMGetResumeReason,(PPDMUSBINS pUsbIns));
+
+ /**
+ * Queries a generic object from the VMM user.
+ *
+ * @returns Pointer to the object if found, NULL if not.
+ * @param pUsbIns The USB device instance.
+ * @param pUuid The UUID of what's being queried. The UUIDs and
+ * the usage conventions are defined by the user.
+ */
+ DECLR3CALLBACKMEMBER(void *, pfnQueryGenericUserObject,(PPDMUSBINS pUsbIns, PCRTUUID pUuid));
+
+ /** @name Space reserved for minor interface changes.
+ * @{ */
+ DECLR3CALLBACKMEMBER(void, pfnReserved0,(PPDMUSBINS pUsbIns));
+ DECLR3CALLBACKMEMBER(void, pfnReserved1,(PPDMUSBINS pUsbIns));
+ DECLR3CALLBACKMEMBER(void, pfnReserved2,(PPDMUSBINS pUsbIns));
+ DECLR3CALLBACKMEMBER(void, pfnReserved3,(PPDMUSBINS pUsbIns));
+ DECLR3CALLBACKMEMBER(void, pfnReserved4,(PPDMUSBINS pUsbIns));
+ DECLR3CALLBACKMEMBER(void, pfnReserved5,(PPDMUSBINS pUsbIns));
+ DECLR3CALLBACKMEMBER(void, pfnReserved6,(PPDMUSBINS pUsbIns));
+ DECLR3CALLBACKMEMBER(void, pfnReserved7,(PPDMUSBINS pUsbIns));
+ DECLR3CALLBACKMEMBER(void, pfnReserved8,(PPDMUSBINS pUsbIns));
+ /** @} */
+
+ /** Just a safety precaution. */
+ uint32_t u32TheEnd;
+} PDMUSBHLP;
+/** Pointer PDM USB Device API. */
+typedef PDMUSBHLP *PPDMUSBHLP;
+/** Pointer const PDM USB Device API. */
+typedef const PDMUSBHLP *PCPDMUSBHLP;
+
+/** Current USBHLP version number. */
+#define PDM_USBHLP_VERSION PDM_VERSION_MAKE(0xeefe, 7, 0)
+
+#endif /* IN_RING3 */
+
+/**
+ * PDM USB Device Instance.
+ */
+typedef struct PDMUSBINS
+{
+ /** Structure version. PDM_USBINS_VERSION defines the current version. */
+ uint32_t u32Version;
+ /** USB device instance number. */
+ uint32_t iInstance;
+ /** The base interface of the device.
+ * The device constructor initializes this if it has any device level
+ * interfaces to export. To obtain this interface call PDMR3QueryUSBDevice(). */
+ PDMIBASE IBase;
+#if HC_ARCH_BITS == 32
+ uint32_t u32Alignment; /**< Alignment padding. */
+#endif
+
+ /** Internal data. */
+ union
+ {
+#ifdef PDMUSBINSINT_DECLARED
+ PDMUSBINSINT s;
+#endif
+ uint8_t padding[HC_ARCH_BITS == 32 ? 96 : 128];
+ } Internal;
+
+ /** Pointer the PDM USB Device API. */
+ R3PTRTYPE(PCPDMUSBHLP) pHlpR3;
+ /** Pointer to the USB device registration structure. */
+ R3PTRTYPE(PCPDMUSBREG) pReg;
+ /** Configuration handle. */
+ R3PTRTYPE(PCFGMNODE) pCfg;
+ /** The (device) global configuration handle. */
+ R3PTRTYPE(PCFGMNODE) pCfgGlobal;
+ /** Pointer to device instance data. */
+ R3PTRTYPE(void *) pvInstanceDataR3;
+ /** Pointer to the VUSB Device structure.
+ * Internal to VUSB, don't touch.
+ * @todo Moved this to PDMUSBINSINT. */
+ R3PTRTYPE(void *) pvVUsbDev2;
+ /** Device name for using when logging.
+ * The constructor sets this and the destructor frees it. */
+ R3PTRTYPE(char *) pszName;
+ /** Tracing indicator. */
+ uint32_t fTracing;
+ /** The tracing ID of this device. */
+ uint32_t idTracing;
+ /** The port/device speed. HCs and emulated devices need to know. */
+ VUSBSPEED enmSpeed;
+
+ /** Padding to make achInstanceData aligned at 32 byte boundary. */
+ uint32_t au32Padding[HC_ARCH_BITS == 32 ? 2 : 3];
+
+ /** Device instance data. The size of this area is defined
+ * in the PDMUSBREG::cbInstanceData field. */
+ char achInstanceData[8];
+} PDMUSBINS;
+
+/** Current USBINS version number. */
+#define PDM_USBINS_VERSION PDM_VERSION_MAKE(0xeefd, 3, 0)
+
+/**
+ * Checks the structure versions of the USB device instance and USB device
+ * helpers, returning if they are incompatible.
+ *
+ * This shall be the first statement of the constructor!
+ *
+ * @param pUsbIns The USB device instance pointer.
+ */
+#define PDMUSB_CHECK_VERSIONS_RETURN(pUsbIns) \
+ do \
+ { \
+ PPDMUSBINS pUsbInsTypeCheck = (pUsbIns); NOREF(pUsbInsTypeCheck); \
+ AssertLogRelMsgReturn(PDM_VERSION_ARE_COMPATIBLE((pUsbIns)->u32Version, PDM_USBINS_VERSION), \
+ ("DevIns=%#x mine=%#x\n", (pUsbIns)->u32Version, PDM_USBINS_VERSION), \
+ VERR_PDM_USBINS_VERSION_MISMATCH); \
+ AssertLogRelMsgReturn(PDM_VERSION_ARE_COMPATIBLE((pUsbIns)->pHlpR3->u32Version, PDM_USBHLP_VERSION), \
+ ("DevHlp=%#x mine=%#x\n", (pUsbIns)->pHlpR3->u32Version, PDM_USBHLP_VERSION), \
+ VERR_PDM_USBHLPR3_VERSION_MISMATCH); \
+ } while (0)
+
+/**
+ * Quietly checks the structure versions of the USB device instance and
+ * USB device helpers, returning if they are incompatible.
+ *
+ * This shall be invoked as the first statement in the destructor!
+ *
+ * @param pUsbIns The USB device instance pointer.
+ */
+#define PDMUSB_CHECK_VERSIONS_RETURN_VOID(pUsbIns) \
+ do \
+ { \
+ PPDMUSBINS pUsbInsTypeCheck = (pUsbIns); NOREF(pUsbInsTypeCheck); \
+ if (RT_LIKELY(PDM_VERSION_ARE_COMPATIBLE((pUsbIns)->u32Version, PDM_USBINS_VERSION) )) \
+ { /* likely */ } else return; \
+ if (RT_LIKELY(PDM_VERSION_ARE_COMPATIBLE((pUsbIns)->pHlpR3->u32Version, PDM_USBHLP_VERSION) )) \
+ { /* likely */ } else return; \
+ } while (0)
+
+
+/** Converts a pointer to the PDMUSBINS::IBase to a pointer to PDMUSBINS. */
+#define PDMIBASE_2_PDMUSB(pInterface) ( (PPDMUSBINS)((char *)(pInterface) - RT_UOFFSETOF(PDMUSBINS, IBase)) )
+
+
+/** @def PDMUSB_ASSERT_EMT
+ * Assert that the current thread is the emulation thread.
+ */
+#ifdef VBOX_STRICT
+# define PDMUSB_ASSERT_EMT(pUsbIns) pUsbIns->pHlpR3->pfnAssertEMT(pUsbIns, __FILE__, __LINE__, __FUNCTION__)
+#else
+# define PDMUSB_ASSERT_EMT(pUsbIns) do { } while (0)
+#endif
+
+/** @def PDMUSB_ASSERT_OTHER
+ * Assert that the current thread is NOT the emulation thread.
+ */
+#ifdef VBOX_STRICT
+# define PDMUSB_ASSERT_OTHER(pUsbIns) pUsbIns->pHlpR3->pfnAssertOther(pUsbIns, __FILE__, __LINE__, __FUNCTION__)
+#else
+# define PDMUSB_ASSERT_OTHER(pUsbIns) do { } while (0)
+#endif
+
+/** @def PDMUSB_SET_ERROR
+ * Set the VM error. See PDMUsbHlpVMSetError() for printf like message
+ * formatting.
+ */
+#define PDMUSB_SET_ERROR(pUsbIns, rc, pszError) \
+ PDMUsbHlpVMSetError(pUsbIns, rc, RT_SRC_POS, "%s", pszError)
+
+/** @def PDMUSB_SET_RUNTIME_ERROR
+ * Set the VM runtime error. See PDMUsbHlpVMSetRuntimeError() for printf like
+ * message formatting.
+ */
+#define PDMUSB_SET_RUNTIME_ERROR(pUsbIns, fFlags, pszErrorId, pszError) \
+ PDMUsbHlpVMSetRuntimeError(pUsbIns, fFlags, pszErrorId, "%s", pszError)
+
+
+#ifdef IN_RING3
+
+/**
+ * @copydoc PDMUSBHLP::pfnDriverAttach
+ */
+DECLINLINE(int) PDMUsbHlpDriverAttach(PPDMUSBINS pUsbIns, RTUINT iLun, PPDMIBASE pBaseInterface, PPDMIBASE *ppBaseInterface, const char *pszDesc)
+{
+ return pUsbIns->pHlpR3->pfnDriverAttach(pUsbIns, iLun, pBaseInterface, ppBaseInterface, pszDesc);
+}
+
+/**
+ * VBOX_STRICT wrapper for pHlpR3->pfnDBGFStopV.
+ *
+ * @returns VBox status code which must be passed up to the VMM.
+ * @param pUsbIns Device instance.
+ * @param SRC_POS Use RT_SRC_POS.
+ * @param pszFormat Message. (optional)
+ * @param ... Message parameters.
+ */
+DECLINLINE(int) RT_IPRT_FORMAT_ATTR(5, 6) PDMUsbDBGFStop(PPDMUSBINS pUsbIns, RT_SRC_POS_DECL, const char *pszFormat, ...)
+{
+#ifdef VBOX_STRICT
+ int rc;
+ va_list va;
+ va_start(va, pszFormat);
+ rc = pUsbIns->pHlpR3->pfnDBGFStopV(pUsbIns, RT_SRC_POS_ARGS, pszFormat, va);
+ va_end(va);
+ return rc;
+#else
+ NOREF(pUsbIns);
+ NOREF(pszFile);
+ NOREF(iLine);
+ NOREF(pszFunction);
+ NOREF(pszFormat);
+ return VINF_SUCCESS;
+#endif
+}
+
+/**
+ * @copydoc PDMUSBHLP::pfnVMState
+ */
+DECLINLINE(VMSTATE) PDMUsbHlpVMState(PPDMUSBINS pUsbIns)
+{
+ return pUsbIns->pHlpR3->pfnVMState(pUsbIns);
+}
+
+/**
+ * @copydoc PDMUSBHLP::pfnThreadCreate
+ */
+DECLINLINE(int) PDMUsbHlpThreadCreate(PPDMUSBINS pUsbIns, PPPDMTHREAD ppThread, void *pvUser, PFNPDMTHREADUSB pfnThread,
+ PFNPDMTHREADWAKEUPUSB pfnWakeup, size_t cbStack, RTTHREADTYPE enmType, const char *pszName)
+{
+ return pUsbIns->pHlpR3->pfnThreadCreate(pUsbIns, ppThread, pvUser, pfnThread, pfnWakeup, cbStack, enmType, pszName);
+}
+
+
+/**
+ * @copydoc PDMUSBHLP::pfnSetAsyncNotification
+ */
+DECLINLINE(int) PDMUsbHlpSetAsyncNotification(PPDMUSBINS pUsbIns, PFNPDMUSBASYNCNOTIFY pfnAsyncNotify)
+{
+ return pUsbIns->pHlpR3->pfnSetAsyncNotification(pUsbIns, pfnAsyncNotify);
+}
+
+/**
+ * @copydoc PDMUSBHLP::pfnAsyncNotificationCompleted
+ */
+DECLINLINE(void) PDMUsbHlpAsyncNotificationCompleted(PPDMUSBINS pUsbIns)
+{
+ pUsbIns->pHlpR3->pfnAsyncNotificationCompleted(pUsbIns);
+}
+
+/**
+ * Set the VM error message
+ *
+ * @returns rc.
+ * @param pUsbIns The USB device instance.
+ * @param rc VBox status code.
+ * @param SRC_POS Use RT_SRC_POS.
+ * @param pszFormat Error message format string.
+ * @param ... Error message arguments.
+ */
+DECLINLINE(int) RT_IPRT_FORMAT_ATTR(6, 7) PDMUsbHlpVMSetError(PPDMUSBINS pUsbIns, int rc, RT_SRC_POS_DECL,
+ const char *pszFormat, ...)
+{
+ va_list va;
+ va_start(va, pszFormat);
+ rc = pUsbIns->pHlpR3->pfnVMSetErrorV(pUsbIns, rc, RT_SRC_POS_ARGS, pszFormat, va);
+ va_end(va);
+ return rc;
+}
+
+/**
+ * @copydoc PDMUSBHLP::pfnMMHeapAlloc
+ */
+DECLINLINE(void *) PDMUsbHlpMMHeapAlloc(PPDMUSBINS pUsbIns, size_t cb)
+{
+ return pUsbIns->pHlpR3->pfnMMHeapAlloc(pUsbIns, cb);
+}
+
+/**
+ * @copydoc PDMUSBHLP::pfnMMHeapAllocZ
+ */
+DECLINLINE(void *) PDMUsbHlpMMHeapAllocZ(PPDMUSBINS pUsbIns, size_t cb)
+{
+ return pUsbIns->pHlpR3->pfnMMHeapAllocZ(pUsbIns, cb);
+}
+
+/**
+ * Frees memory allocated by PDMUsbHlpMMHeapAlloc or PDMUsbHlpMMHeapAllocZ.
+ *
+ * @param pUsbIns The USB device instance.
+ * @param pv The memory to free. NULL is fine.
+ */
+DECLINLINE(void) PDMUsbHlpMMHeapFree(PPDMUSBINS pUsbIns, void *pv)
+{
+ pUsbIns->pHlpR3->pfnMMHeapFree(pUsbIns, pv);
+}
+
+/**
+ * @copydoc PDMUSBHLP::pfnDBGFInfoRegisterArgv
+ */
+DECLINLINE(int) PDMUsbHlpDBGFInfoRegisterArgv(PPDMUSBINS pUsbIns, const char *pszName, const char *pszDesc, PFNDBGFINFOARGVUSB pfnHandler)
+{
+ return pUsbIns->pHlpR3->pfnDBGFInfoRegisterArgv(pUsbIns, pszName, pszDesc, pfnHandler);
+}
+
+/**
+ * @copydoc PDMUSBHLP::pfnTimerCreate
+ */
+DECLINLINE(int) PDMUsbHlpTimerCreate(PPDMUSBINS pUsbIns, TMCLOCK enmClock, PFNTMTIMERUSB pfnCallback, void *pvUser,
+ uint32_t fFlags, const char *pszDesc, PTMTIMERHANDLE phTimer)
+{
+ return pUsbIns->pHlpR3->pfnTimerCreate(pUsbIns, enmClock, pfnCallback, pvUser, fFlags, pszDesc, phTimer);
+}
+
+/**
+ * @copydoc PDMUSBHLP::pfnTimerFromMicro
+ */
+DECLINLINE(uint64_t) PDMUsbHlpTimerFromMicro(PPDMUSBINS pUsbIns, TMTIMERHANDLE hTimer, uint64_t cMicroSecs)
+{
+ return pUsbIns->pHlpR3->pfnTimerFromMicro(pUsbIns, hTimer, cMicroSecs);
+}
+
+/**
+ * @copydoc PDMUSBHLP::pfnTimerFromMilli
+ */
+DECLINLINE(uint64_t) PDMUsbHlpTimerFromMilli(PPDMUSBINS pUsbIns, TMTIMERHANDLE hTimer, uint64_t cMilliSecs)
+{
+ return pUsbIns->pHlpR3->pfnTimerFromMilli(pUsbIns, hTimer, cMilliSecs);
+}
+
+/**
+ * @copydoc PDMUSBHLP::pfnTimerFromNano
+ */
+DECLINLINE(uint64_t) PDMUsbHlpTimerFromNano(PPDMUSBINS pUsbIns, TMTIMERHANDLE hTimer, uint64_t cNanoSecs)
+{
+ return pUsbIns->pHlpR3->pfnTimerFromNano(pUsbIns, hTimer, cNanoSecs);
+}
+
+/**
+ * @copydoc PDMUSBHLP::pfnTimerGet
+ */
+DECLINLINE(uint64_t) PDMUsbHlpTimerGet(PPDMUSBINS pUsbIns, TMTIMERHANDLE hTimer)
+{
+ return pUsbIns->pHlpR3->pfnTimerGet(pUsbIns, hTimer);
+}
+
+/**
+ * @copydoc PDMUSBHLP::pfnTimerGetFreq
+ */
+DECLINLINE(uint64_t) PDMUsbHlpTimerGetFreq(PPDMUSBINS pUsbIns, TMTIMERHANDLE hTimer)
+{
+ return pUsbIns->pHlpR3->pfnTimerGetFreq(pUsbIns, hTimer);
+}
+
+/**
+ * @copydoc PDMUSBHLP::pfnTimerGetNano
+ */
+DECLINLINE(uint64_t) PDMUsbHlpTimerGetNano(PPDMUSBINS pUsbIns, TMTIMERHANDLE hTimer)
+{
+ return pUsbIns->pHlpR3->pfnTimerGetNano(pUsbIns, hTimer);
+}
+
+/**
+ * @copydoc PDMUSBHLP::pfnTimerIsActive
+ */
+DECLINLINE(bool) PDMUsbHlpTimerIsActive(PPDMUSBINS pUsbIns, TMTIMERHANDLE hTimer)
+{
+ return pUsbIns->pHlpR3->pfnTimerIsActive(pUsbIns, hTimer);
+}
+
+/**
+ * @copydoc PDMUSBHLP::pfnTimerIsLockOwner
+ */
+DECLINLINE(bool) PDMUsbHlpTimerIsLockOwner(PPDMUSBINS pUsbIns, TMTIMERHANDLE hTimer)
+{
+ return pUsbIns->pHlpR3->pfnTimerIsLockOwner(pUsbIns, hTimer);
+}
+
+/**
+ * @copydoc PDMUSBHLP::pfnTimerLockClock
+ */
+DECLINLINE(int) PDMUsbHlpTimerLockClock(PPDMUSBINS pUsbIns, TMTIMERHANDLE hTimer)
+{
+ return pUsbIns->pHlpR3->pfnTimerLockClock(pUsbIns, hTimer);
+}
+
+/**
+ * @copydoc PDMUSBHLP::pfnTimerLockClock2
+ */
+DECLINLINE(int) PDMUsbHlpTimerLockClock2(PPDMUSBINS pUsbIns, TMTIMERHANDLE hTimer, PPDMCRITSECT pCritSect)
+{
+ return pUsbIns->pHlpR3->pfnTimerLockClock2(pUsbIns, hTimer, pCritSect);
+}
+
+/**
+ * @copydoc PDMUSBHLP::pfnTimerSet
+ */
+DECLINLINE(int) PDMUsbHlpTimerSet(PPDMUSBINS pUsbIns, TMTIMERHANDLE hTimer, uint64_t uExpire)
+{
+ return pUsbIns->pHlpR3->pfnTimerSet(pUsbIns, hTimer, uExpire);
+}
+
+/**
+ * @copydoc PDMUSBHLP::pfnTimerSetFrequencyHint
+ */
+DECLINLINE(int) PDMUsbHlpTimerSetFrequencyHint(PPDMUSBINS pUsbIns, TMTIMERHANDLE hTimer, uint32_t uHz)
+{
+ return pUsbIns->pHlpR3->pfnTimerSetFrequencyHint(pUsbIns, hTimer, uHz);
+}
+
+/**
+ * @copydoc PDMUSBHLP::pfnTimerSetMicro
+ */
+DECLINLINE(int) PDMUsbHlpTimerSetMicro(PPDMUSBINS pUsbIns, TMTIMERHANDLE hTimer, uint64_t cMicrosToNext)
+{
+ return pUsbIns->pHlpR3->pfnTimerSetMicro(pUsbIns, hTimer, cMicrosToNext);
+}
+
+/**
+ * @copydoc PDMUSBHLP::pfnTimerSetMillies
+ */
+DECLINLINE(int) PDMUsbHlpTimerSetMillies(PPDMUSBINS pUsbIns, TMTIMERHANDLE hTimer, uint64_t cMilliesToNext)
+{
+ return pUsbIns->pHlpR3->pfnTimerSetMillies(pUsbIns, hTimer, cMilliesToNext);
+}
+
+/**
+ * @copydoc PDMUSBHLP::pfnTimerSetNano
+ */
+DECLINLINE(int) PDMUsbHlpTimerSetNano(PPDMUSBINS pUsbIns, TMTIMERHANDLE hTimer, uint64_t cNanosToNext)
+{
+ return pUsbIns->pHlpR3->pfnTimerSetNano(pUsbIns, hTimer, cNanosToNext);
+}
+
+/**
+ * @copydoc PDMUSBHLP::pfnTimerSetRelative
+ */
+DECLINLINE(int) PDMUsbHlpTimerSetRelative(PPDMUSBINS pUsbIns, TMTIMERHANDLE hTimer, uint64_t cTicksToNext, uint64_t *pu64Now)
+{
+ return pUsbIns->pHlpR3->pfnTimerSetRelative(pUsbIns, hTimer, cTicksToNext, pu64Now);
+}
+
+/**
+ * @copydoc PDMUSBHLP::pfnTimerStop
+ */
+DECLINLINE(int) PDMUsbHlpTimerStop(PPDMUSBINS pUsbIns, TMTIMERHANDLE hTimer)
+{
+ return pUsbIns->pHlpR3->pfnTimerStop(pUsbIns, hTimer);
+}
+
+/**
+ * @copydoc PDMUSBHLP::pfnTimerUnlockClock
+ */
+DECLINLINE(void) PDMUsbHlpTimerUnlockClock(PPDMUSBINS pUsbIns, TMTIMERHANDLE hTimer)
+{
+ pUsbIns->pHlpR3->pfnTimerUnlockClock(pUsbIns, hTimer);
+}
+
+/**
+ * @copydoc PDMUSBHLP::pfnTimerUnlockClock2
+ */
+DECLINLINE(void) PDMUsbHlpTimerUnlockClock2(PPDMUSBINS pUsbIns, TMTIMERHANDLE hTimer, PPDMCRITSECT pCritSect)
+{
+ pUsbIns->pHlpR3->pfnTimerUnlockClock2(pUsbIns, hTimer, pCritSect);
+}
+
+/**
+ * @copydoc PDMUSBHLP::pfnTimerSetCritSect
+ */
+DECLINLINE(int) PDMUsbHlpTimerSetCritSect(PPDMUSBINS pUsbIns, TMTIMERHANDLE hTimer, PPDMCRITSECT pCritSect)
+{
+ return pUsbIns->pHlpR3->pfnTimerSetCritSect(pUsbIns, hTimer, pCritSect);
+}
+
+/**
+ * @copydoc PDMUSBHLP::pfnTimerSave
+ */
+DECLINLINE(int) PDMUsbHlpTimerSave(PPDMUSBINS pUsbIns, TMTIMERHANDLE hTimer, PSSMHANDLE pSSM)
+{
+ return pUsbIns->pHlpR3->pfnTimerSave(pUsbIns, hTimer, pSSM);
+}
+
+/**
+ * @copydoc PDMUSBHLP::pfnTimerLoad
+ */
+DECLINLINE(int) PDMUsbHlpTimerLoad(PPDMUSBINS pUsbIns, TMTIMERHANDLE hTimer, PSSMHANDLE pSSM)
+{
+ return pUsbIns->pHlpR3->pfnTimerLoad(pUsbIns, hTimer, pSSM);
+}
+
+/**
+ * @copydoc PDMUSBHLP::pfnTimerDestroy
+ */
+DECLINLINE(int) PDMUsbHlpTimerDestroy(PPDMUSBINS pUsbIns, TMTIMERHANDLE hTimer)
+{
+ return pUsbIns->pHlpR3->pfnTimerDestroy(pUsbIns, hTimer);
+}
+
+/**
+ * @copydoc PDMUSBHLP::pfnSSMRegister
+ */
+DECLINLINE(int) PDMUsbHlpSSMRegister(PPDMUSBINS pUsbIns, uint32_t uVersion, size_t cbGuess,
+ PFNSSMUSBLIVEPREP pfnLivePrep, PFNSSMUSBLIVEEXEC pfnLiveExec, PFNSSMUSBLIVEVOTE pfnLiveVote,
+ PFNSSMUSBSAVEPREP pfnSavePrep, PFNSSMUSBSAVEEXEC pfnSaveExec, PFNSSMUSBSAVEDONE pfnSaveDone,
+ PFNSSMUSBLOADPREP pfnLoadPrep, PFNSSMUSBLOADEXEC pfnLoadExec, PFNSSMUSBLOADDONE pfnLoadDone)
+{
+ return pUsbIns->pHlpR3->pfnSSMRegister(pUsbIns, uVersion, cbGuess,
+ pfnLivePrep, pfnLiveExec, pfnLiveVote,
+ pfnSavePrep, pfnSaveExec, pfnSaveDone,
+ pfnLoadPrep, pfnLoadExec, pfnLoadDone);
+}
+
+/**
+ * @copydoc PDMUSBHLP::pfnQueryGenericUserObject
+ */
+DECLINLINE(void *) PDMUsbHlpQueryGenericUserObject(PPDMUSBINS pUsbIns, PCRTUUID pUuid)
+{
+ return pUsbIns->pHlpR3->pfnQueryGenericUserObject(pUsbIns, pUuid);
+}
+
+#endif /* IN_RING3 */
+
+
+
+/** Pointer to callbacks provided to the VBoxUsbRegister() call. */
+typedef const struct PDMUSBREGCB *PCPDMUSBREGCB;
+
+/**
+ * Callbacks for VBoxUSBDeviceRegister().
+ */
+typedef struct PDMUSBREGCB
+{
+ /** Interface version.
+ * This is set to PDM_USBREG_CB_VERSION. */
+ uint32_t u32Version;
+
+ /**
+ * Registers a device with the current VM instance.
+ *
+ * @returns VBox status code.
+ * @param pCallbacks Pointer to the callback table.
+ * @param pReg Pointer to the USB device registration record.
+ * This data must be permanent and readonly.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnRegister,(PCPDMUSBREGCB pCallbacks, PCPDMUSBREG pReg));
+} PDMUSBREGCB;
+
+/** Current version of the PDMUSBREGCB structure. */
+#define PDM_USBREG_CB_VERSION PDM_VERSION_MAKE(0xeefc, 1, 0)
+
+
+/**
+ * The VBoxUsbRegister callback function.
+ *
+ * PDM will invoke this function after loading a USB device module and letting
+ * the module decide which devices to register and how to handle conflicts.
+ *
+ * @returns VBox status code.
+ * @param pCallbacks Pointer to the callback table.
+ * @param u32Version VBox version number.
+ */
+typedef DECLCALLBACKTYPE(int, FNPDMVBOXUSBREGISTER,(PCPDMUSBREGCB pCallbacks, uint32_t u32Version));
+
+VMMR3DECL(int) PDMR3UsbCreateEmulatedDevice(PUVM pUVM, const char *pszDeviceName, PCFGMNODE pDeviceNode, PCRTUUID pUuid,
+ const char *pszCaptureFilename);
+VMMR3DECL(int) PDMR3UsbCreateProxyDevice(PUVM pUVM, PCRTUUID pUuid, const char *pszBackend, const char *pszAddress, PCFGMNODE pSubTree,
+ VUSBSPEED enmSpeed, uint32_t fMaskedIfs, const char *pszCaptureFilename);
+VMMR3DECL(int) PDMR3UsbDetachDevice(PUVM pUVM, PCRTUUID pUuid);
+VMMR3DECL(bool) PDMR3UsbHasHub(PUVM pUVM);
+VMMR3DECL(int) PDMR3UsbDriverAttach(PUVM pUVM, const char *pszDevice, unsigned iDevIns, unsigned iLun, uint32_t fFlags,
+ PPPDMIBASE ppBase);
+VMMR3DECL(int) PDMR3UsbDriverDetach(PUVM pUVM, const char *pszDevice, unsigned iDevIns, unsigned iLun,
+ const char *pszDriver, unsigned iOccurrence, uint32_t fFlags);
+VMMR3DECL(int) PDMR3UsbQueryLun(PUVM pUVM, const char *pszDevice, unsigned iInstance, unsigned iLun, PPDMIBASE *ppBase);
+VMMR3DECL(int) PDMR3UsbQueryDriverOnLun(PUVM pUVM, const char *pszDevice, unsigned iInstance, unsigned iLun,
+ const char *pszDriver, PPPDMIBASE ppBase);
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !VBOX_INCLUDED_vmm_pdmusb_h */
diff --git a/include/VBox/vmm/pdmwebcaminfs.h b/include/VBox/vmm/pdmwebcaminfs.h
new file mode 100644
index 00000000..3c1fe35f
--- /dev/null
+++ b/include/VBox/vmm/pdmwebcaminfs.h
@@ -0,0 +1,156 @@
+/* $Id: pdmwebcaminfs.h $ */
+/** @file
+ * webcaminfs - interfaces between dev and driver.
+ */
+
+/*
+ * Copyright (C) 2011-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vmm_pdmwebcaminfs_h
+#define VBOX_INCLUDED_vmm_pdmwebcaminfs_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/types.h>
+
+struct VRDEVIDEOINDEVICEDESC;
+struct VRDEVIDEOINPAYLOADHDR;
+struct VRDEVIDEOINCTRLHDR;
+
+
+/** @defgroup grp_pdm_ifs_webcam PDM Web Camera Interfaces
+ * @ingroup grp_pdm_interfaces
+ * @{
+ */
+
+/** Pointer to the web camera driver (up) interface. */
+typedef struct PDMIWEBCAMDRV *PPDMIWEBCAMDRV;
+/**
+ * Web camera interface driver provided by the driver to the device,
+ * i.e. facing upwards.
+ */
+typedef struct PDMIWEBCAMDRV
+{
+ /**
+ * The PDM device is ready to get webcam notifications.
+ *
+ * @param pInterface Pointer to the interface.
+ * @param fReady Whether the device is ready.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnReady,(PPDMIWEBCAMDRV pInterface, bool fReady));
+
+ /**
+ * Send a control request to the webcam.
+ *
+ * Async response will be returned by pfnWebcamUpControl callback.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface.
+ * @param pvUser The callers context.
+ * @param idDevice Unique id for the reported webcam assigned by the driver.
+ * @param pCtrl The control data.
+ * @param cbCtrl The size of the control data.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnControl,(PPDMIWEBCAMDRV pInterface, void *pvUser, uint64_t idDevice,
+ struct VRDEVIDEOINCTRLHDR const *pCtrl, uint32_t cbCtrl));
+} PDMIWEBCAMDRV;
+/** Interface ID for PDMIWEBCAMDRV. */
+#define PDMIWEBCAMDRV_IID "0d29b9a1-f4cd-4719-a564-38d5634ba9f8"
+
+
+/** Pointer to the web camera driver/device (down) interface. */
+typedef struct PDMIWEBCAMDEV *PPDMIWEBCAMDEV;
+/**
+ * Web camera interface provided by the device(/driver) interface,
+ * i.e. facing downwards.
+ */
+typedef struct PDMIWEBCAMDEV
+{
+ /**
+ * A webcam is available.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface.
+ * @param idDevice Unique id for the reported webcam assigned by the driver.
+ * @param pDeviceDesc The device description.
+ * @param cbDeviceDesc The size of the device description.
+ * @param uVersion The remote video input protocol version.
+ * @param fCapabilities The remote video input protocol capabilities.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnAttached,(PPDMIWEBCAMDEV pInterface, uint64_t idDevice,
+ struct VRDEVIDEOINDEVICEDESC const *pDeviceDesc, uint32_t cbDeviceDesc,
+ uint32_t uVersion, uint32_t fCapabilities));
+
+ /**
+ * The webcam is not available anymore.
+ *
+ * @param pInterface Pointer to the interface.
+ * @param idDevice Unique id for the reported webcam assigned by the
+ * driver.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnDetached,(PPDMIWEBCAMDEV pInterface, uint64_t idDevice));
+
+ /**
+ * There is a control response or a control change for the webcam.
+ *
+ * @param pInterface Pointer to the interface.
+ * @param fResponse True if this is a response for a previous pfnWebcamDownControl call.
+ * @param pvUser The pvUser parameter of the pfnWebcamDownControl call. Undefined if fResponse == false.
+ * @param idDevice Unique id for the reported webcam assigned by the
+ * driver.
+ * @param pCtrl The control data (defined in VRDE).
+ * @param cbCtrl The size of the control data.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnControl,(PPDMIWEBCAMDEV pInterface, bool fResponse, void *pvUser,
+ uint64_t idDevice, struct VRDEVIDEOINCTRLHDR const *pCtrl, uint32_t cbCtrl));
+
+ /**
+ * A new frame.
+ *
+ * @param pInterface Pointer to the interface.
+ * @param idDevice Unique id for the reported webcam assigned by the driver.
+ * @param pHeader Payload header (defined in VRDE).
+ * @param cbHeader Size of the payload header.
+ * @param pvFrame Frame (image) data.
+ * @param cbFrame Size of the image data.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnFrame,(PPDMIWEBCAMDEV pInterface, uint64_t idDevice,
+ struct VRDEVIDEOINPAYLOADHDR const *pHeader, uint32_t cbHeader,
+ const void *pvFrame, uint32_t cbFrame));
+} PDMIWEBCAMDEV;
+/** Interface ID for PDMIWEBCAMDEV. */
+#define PDMIWEBCAMDEV_IID "6ac03e3c-f56c-4a35-80af-c13ce47a9dd7"
+
+/** @} */
+
+#endif /* !VBOX_INCLUDED_vmm_pdmwebcaminfs_h */
+
diff --git a/include/VBox/vmm/pgm.h b/include/VBox/vmm/pgm.h
new file mode 100644
index 00000000..133ad827
--- /dev/null
+++ b/include/VBox/vmm/pgm.h
@@ -0,0 +1,1129 @@
+/** @file
+ * PGM - Page Monitor / Monitor.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vmm_pgm_h
+#define VBOX_INCLUDED_vmm_pgm_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/types.h>
+#include <VBox/sup.h>
+#include <VBox/vmm/vmapi.h>
+#include <VBox/vmm/gmm.h> /* for PGMMREGISTERSHAREDMODULEREQ */
+#include <VBox/vmm/hm_vmx.h>
+#include <iprt/x86.h>
+#include <VBox/param.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_pgm The Page Monitor / Manager API
+ * @ingroup grp_vmm
+ * @{
+ */
+
+/**
+ * FNPGMRELOCATE callback mode.
+ */
+typedef enum PGMRELOCATECALL
+{
+ /** The callback is for checking if the suggested address is suitable. */
+ PGMRELOCATECALL_SUGGEST = 1,
+ /** The callback is for executing the relocation. */
+ PGMRELOCATECALL_RELOCATE
+} PGMRELOCATECALL;
+
+
+/**
+ * Callback function which will be called when PGM is trying to find
+ * a new location for the mapping.
+ *
+ * The callback is called in two modes, 1) the check mode and 2) the relocate mode.
+ * In 1) the callback should say if it objects to a suggested new location. If it
+ * accepts the new location, it is called again for doing it's relocation.
+ *
+ *
+ * @returns true if the location is ok.
+ * @returns false if another location should be found.
+ * @param pVM The cross context VM structure.
+ * @param GCPtrOld The old virtual address.
+ * @param GCPtrNew The new virtual address.
+ * @param enmMode Used to indicate the callback mode.
+ * @param pvUser User argument.
+ * @remark The return value is no a failure indicator, it's an acceptance
+ * indicator. Relocation can not fail!
+ */
+typedef DECLCALLBACKTYPE(bool, FNPGMRELOCATE,(PVM pVM, RTGCPTR GCPtrOld, RTGCPTR GCPtrNew, PGMRELOCATECALL enmMode, void *pvUser));
+/** Pointer to a relocation callback function. */
+typedef FNPGMRELOCATE *PFNPGMRELOCATE;
+
+
+/**
+ * Memory access origin.
+ */
+typedef enum PGMACCESSORIGIN
+{
+ /** Invalid zero value. */
+ PGMACCESSORIGIN_INVALID = 0,
+ /** IEM is access memory. */
+ PGMACCESSORIGIN_IEM,
+ /** HM is access memory. */
+ PGMACCESSORIGIN_HM,
+ /** Some device is access memory. */
+ PGMACCESSORIGIN_DEVICE,
+ /** Someone debugging is access memory. */
+ PGMACCESSORIGIN_DEBUGGER,
+ /** SELM is access memory. */
+ PGMACCESSORIGIN_SELM,
+ /** FTM is access memory. */
+ PGMACCESSORIGIN_FTM,
+ /** REM is access memory. */
+ PGMACCESSORIGIN_REM,
+ /** IOM is access memory. */
+ PGMACCESSORIGIN_IOM,
+ /** End of valid values. */
+ PGMACCESSORIGIN_END,
+ /** Type size hack. */
+ PGMACCESSORIGIN_32BIT_HACK = 0x7fffffff
+} PGMACCESSORIGIN;
+
+
+/**
+ * Physical page access handler kind.
+ */
+typedef enum PGMPHYSHANDLERKIND
+{
+ /** Invalid zero value. */
+ PGMPHYSHANDLERKIND_INVALID = 0,
+ /** MMIO range. Pages are not present, all access is done in interpreter or recompiler. */
+ PGMPHYSHANDLERKIND_MMIO,
+ /** Handler all write access to a physical page range. */
+ PGMPHYSHANDLERKIND_WRITE,
+ /** Handler all access to a physical page range. */
+ PGMPHYSHANDLERKIND_ALL,
+ /** End of the valid values. */
+ PGMPHYSHANDLERKIND_END,
+ /** Type size hack. */
+ PGMPHYSHANDLERKIND_32BIT_HACK = 0x7fffffff
+} PGMPHYSHANDLERKIND;
+
+/**
+ * Guest Access type
+ */
+typedef enum PGMACCESSTYPE
+{
+ /** Read access. */
+ PGMACCESSTYPE_READ = 1,
+ /** Write access. */
+ PGMACCESSTYPE_WRITE
+} PGMACCESSTYPE;
+
+
+/** @def PGM_ALL_CB_DECL
+ * Macro for declaring a handler callback for all contexts. The handler
+ * callback is static in ring-3, and exported in RC and R0.
+ * @sa PGM_ALL_CB2_DECL.
+ */
+#if defined(IN_RC) || defined(IN_RING0)
+# ifdef __cplusplus
+# define PGM_ALL_CB_DECL(type) extern "C" DECLCALLBACK(DECLEXPORT(type))
+# else
+# define PGM_ALL_CB_DECL(type) DECLCALLBACK(DECLEXPORT(type))
+# endif
+#else
+# define PGM_ALL_CB_DECL(type) static DECLCALLBACK(type)
+#endif
+
+/** @def PGM_ALL_CB2_DECL
+ * Macro for declaring a handler callback for all contexts. The handler
+ * callback is hidden in ring-3, and exported in RC and R0.
+ * @sa PGM_ALL_CB2_DECL.
+ */
+#if defined(IN_RC) || defined(IN_RING0)
+# ifdef __cplusplus
+# define PGM_ALL_CB2_DECL(type) extern "C" DECLCALLBACK(DECLEXPORT(type))
+# else
+# define PGM_ALL_CB2_DECL(type) DECLCALLBACK(DECLEXPORT(type))
+# endif
+#else
+# define PGM_ALL_CB2_DECL(type) DECL_HIDDEN_CALLBACK(type)
+#endif
+
+/** @def PGM_ALL_CB2_PROTO
+ * Macro for declaring a handler callback for all contexts. The handler
+ * callback is hidden in ring-3, and exported in RC and R0.
+ * @param fnType The callback function type.
+ * @sa PGM_ALL_CB2_DECL.
+ */
+#if defined(IN_RC) || defined(IN_RING0)
+# ifdef __cplusplus
+# define PGM_ALL_CB2_PROTO(fnType) extern "C" DECLEXPORT(fnType)
+# else
+# define PGM_ALL_CB2_PROTO(fnType) DECLEXPORT(fnType)
+# endif
+#else
+# define PGM_ALL_CB2_PROTO(fnType) DECLHIDDEN(fnType)
+#endif
+
+
+/**
+ * \#PF Handler callback for physical access handler ranges in RC and R0.
+ *
+ * @returns Strict VBox status code (appropriate for ring-0 and raw-mode).
+ * @param pVM The cross context VM structure.
+ * @param pVCpu The cross context virtual CPU structure of the calling EMT.
+ * @param uErrorCode CPU Error code.
+ * @param pCtx Pointer to the register context for the CPU.
+ * @param pvFault The fault address (cr2).
+ * @param GCPhysFault The GC physical address corresponding to pvFault.
+ * @param uUser User argument (not a pointer).
+ * @thread EMT(pVCpu)
+ */
+typedef DECLCALLBACKTYPE(VBOXSTRICTRC, FNPGMRZPHYSPFHANDLER,(PVMCC pVM, PVMCPUCC pVCpu, RTGCUINT uErrorCode, PCPUMCTX pCtx,
+ RTGCPTR pvFault, RTGCPHYS GCPhysFault, uint64_t uUser));
+/** Pointer to PGM access callback. */
+typedef FNPGMRZPHYSPFHANDLER *PFNPGMRZPHYSPFHANDLER;
+
+
+/**
+ * Access handler callback for physical access handler ranges.
+ *
+ * The handler can not raise any faults, it's mainly for monitoring write access
+ * to certain pages (like MMIO).
+ *
+ * @returns Strict VBox status code in ring-0 and raw-mode context, in ring-3
+ * the only supported informational status code is
+ * VINF_PGM_HANDLER_DO_DEFAULT.
+ * @retval VINF_SUCCESS if the handler have carried out the operation.
+ * @retval VINF_PGM_HANDLER_DO_DEFAULT if the caller should carry out the
+ * access operation.
+ * @retval VINF_EM_XXX in ring-0 and raw-mode context.
+ *
+ * @param pVM The cross context VM structure.
+ * @param pVCpu The cross context virtual CPU structure of the calling EMT.
+ * @param GCPhys The physical address the guest is writing to.
+ * @param pvPhys The HC mapping of that address.
+ * @param pvBuf What the guest is reading/writing.
+ * @param cbBuf How much it's reading/writing.
+ * @param enmAccessType The access type.
+ * @param enmOrigin The origin of this call.
+ * @param uUser User argument (not a pointer).
+ * @thread EMT(pVCpu)
+ */
+typedef DECLCALLBACKTYPE(VBOXSTRICTRC, FNPGMPHYSHANDLER,(PVMCC pVM, PVMCPUCC pVCpu, RTGCPHYS GCPhys, void *pvPhys,
+ void *pvBuf, size_t cbBuf, PGMACCESSTYPE enmAccessType,
+ PGMACCESSORIGIN enmOrigin, uint64_t uUser));
+/** Pointer to PGM access callback. */
+typedef FNPGMPHYSHANDLER *PFNPGMPHYSHANDLER;
+
+
+/**
+ * Paging mode.
+ *
+ * @note Part of saved state. Change with extreme care.
+ */
+typedef enum PGMMODE
+{
+ /** The usual invalid value. */
+ PGMMODE_INVALID = 0,
+ /** Real mode. */
+ PGMMODE_REAL,
+ /** Protected mode, no paging. */
+ PGMMODE_PROTECTED,
+ /** 32-bit paging. */
+ PGMMODE_32_BIT,
+ /** PAE paging. */
+ PGMMODE_PAE,
+ /** PAE paging with NX enabled. */
+ PGMMODE_PAE_NX,
+ /** 64-bit AMD paging (long mode). */
+ PGMMODE_AMD64,
+ /** 64-bit AMD paging (long mode) with NX enabled. */
+ PGMMODE_AMD64_NX,
+ /** 32-bit nested paging mode (shadow only; guest physical to host physical). */
+ PGMMODE_NESTED_32BIT,
+ /** PAE nested paging mode (shadow only; guest physical to host physical). */
+ PGMMODE_NESTED_PAE,
+ /** AMD64 nested paging mode (shadow only; guest physical to host physical). */
+ PGMMODE_NESTED_AMD64,
+ /** Extended paging (Intel) mode. */
+ PGMMODE_EPT,
+ /** Special mode used by NEM to indicate no shadow paging necessary. */
+ PGMMODE_NONE,
+ /** The max number of modes */
+ PGMMODE_MAX,
+ /** 32bit hackishness. */
+ PGMMODE_32BIT_HACK = 0x7fffffff
+} PGMMODE;
+
+/**
+ * Second level address translation (SLAT) mode.
+ */
+typedef enum PGMSLAT
+{
+ /** The usual invalid value. */
+ PGMSLAT_INVALID = 0,
+ /** No second level translation. */
+ PGMSLAT_DIRECT,
+ /** Intel Extended Page Tables (EPT). */
+ PGMSLAT_EPT,
+ /** AMD-V Nested Paging 32-bit. */
+ PGMSLAT_32BIT,
+ /** AMD-V Nested Paging PAE. */
+ PGMSLAT_PAE,
+ /** AMD-V Nested Paging 64-bit. */
+ PGMSLAT_AMD64,
+ /** 32bit hackishness. */
+ PGMSLAT_32BIT_HACK = 0x7fffffff
+} PGMSLAT;
+
+
+/** @name PGMPTWALK::fFailed flags.
+ * These flags indicate the type of a page-walk failure.
+ * @{
+ */
+typedef uint32_t PGMWALKFAIL;
+/** Regular page fault (MBZ since guest Walk code don't set these explicitly). */
+#define PGM_WALKFAIL_PAGE_FAULT UINT32_C(0)
+/** EPT violation - Intel. */
+#define PGM_WALKFAIL_EPT_VIOLATION RT_BIT_32(0)
+/** EPT violation, convertible to \#VE exception - Intel. */
+#define PGM_WALKFAIL_EPT_VIOLATION_CONVERTIBLE RT_BIT_32(1)
+/** EPT misconfiguration - Intel. */
+#define PGM_WALKFAIL_EPT_MISCONFIG RT_BIT_32(2)
+
+/** Mask of all EPT induced page-walk failures - Intel. */
+#define PGM_WALKFAIL_EPT ( PGM_WALKFAIL_EPT_VIOLATION \
+ | PGM_WALKFAIL_EPT_VIOLATION_CONVERTIBLE \
+ | PGM_WALKFAIL_EPT_MISCONFIG)
+/** @} */
+
+
+/** @name PGMPTATTRS - PGM page-table attributes.
+ *
+ * This is VirtualBox's combined page table attributes. It combines regular page
+ * table and Intel EPT attributes. It's 64-bit in size so there's ample room for
+ * bits added in the future to EPT or regular page tables (for e.g. Protection Key).
+ *
+ * The following bits map 1:1 (shifted by PGM_PTATTRS_EPT_SHIFT) to the Intel EPT
+ * attributes as these are unique to EPT and fit within 64-bits despite the shift:
+ * - EPT_R : Read access.
+ * - EPT_W : Write access.
+ * - EPT_X_SUPER : Execute or execute for supervisor-mode linear addr access.
+ * - EPT_MEMTYPE : EPT memory type.
+ * - EPT_IGNORE_PAT: Ignore PAT memory type.
+ * - EPT_X_USER : Execute access for user-mode linear addresses.
+ *
+ * For regular page tables, the R bit is always 1 (same as P bit).
+ * For Intel EPT, the EPT_R and EPT_W bits are copied to R and W bits respectively.
+ *
+ * The following EPT attributes are mapped to the following positions because they
+ * exist in the regular page tables at these positions OR are exclusive to EPT and
+ * have been mapped to arbitrarily chosen positions:
+ * - EPT_A : Accessed (EPT bit 8 maps to bit 5).
+ * - EPT_D : Dirty (EPT bit 9 maps to bit 6).
+ * - EPT_SUPER_SHW_STACK : Supervisor Shadow Stack (EPT bit 60 maps to bit 24).
+ * - EPT_SUPPRESS_VE_XCPT: Suppress \#VE exception (EPT bit 63 maps to bit 25).
+ *
+ * Bits 12, 11:9 and 43 are deliberately kept unused (correspond to bit PS and bits
+ * 11:9 in the regular page-table structures and to bit 11 in the EPT structures
+ * respectively) as bit 12 is the page-size bit and bits 11:9 are reserved for
+ * use by software and we may want to use/preserve them in the future.
+ *
+ * @{ */
+typedef uint64_t PGMPTATTRS;
+/** Pointer to a PGMPTATTRS type. */
+typedef PGMPTATTRS *PPGMPTATTRS;
+
+/** Read bit (always 1 for regular PT, copy of EPT_R for EPT). */
+#define PGM_PTATTRS_R_SHIFT 0
+#define PGM_PTATTRS_R_MASK RT_BIT_64(PGM_PTATTRS_R_SHIFT)
+/** Write access bit (aka read/write bit for regular PT). */
+#define PGM_PTATTRS_W_SHIFT 1
+#define PGM_PTATTRS_W_MASK RT_BIT_64(PGM_PTATTRS_W_SHIFT)
+/** User-mode access bit. */
+#define PGM_PTATTRS_US_SHIFT 2
+#define PGM_PTATTRS_US_MASK RT_BIT_64(PGM_PTATTRS_US_SHIFT)
+/** Write through cache bit. */
+#define PGM_PTATTRS_PWT_SHIFT 3
+#define PGM_PTATTRS_PWT_MASK RT_BIT_64(PGM_PTATTRS_PWT_SHIFT)
+/** Cache disabled bit. */
+#define PGM_PTATTRS_PCD_SHIFT 4
+#define PGM_PTATTRS_PCD_MASK RT_BIT_64(PGM_PTATTRS_PCD_SHIFT)
+/** Accessed bit. */
+#define PGM_PTATTRS_A_SHIFT 5
+#define PGM_PTATTRS_A_MASK RT_BIT_64(PGM_PTATTRS_A_SHIFT)
+/** Dirty bit. */
+#define PGM_PTATTRS_D_SHIFT 6
+#define PGM_PTATTRS_D_MASK RT_BIT_64(PGM_PTATTRS_D_SHIFT)
+/** The PAT bit. */
+#define PGM_PTATTRS_PAT_SHIFT 7
+#define PGM_PTATTRS_PAT_MASK RT_BIT_64(PGM_PTATTRS_PAT_SHIFT)
+/** The global bit. */
+#define PGM_PTATTRS_G_SHIFT 8
+#define PGM_PTATTRS_G_MASK RT_BIT_64(PGM_PTATTRS_G_SHIFT)
+/** Reserved (bits 12:9) unused. */
+#define PGM_PTATTRS_RSVD_12_9_SHIFT 9
+#define PGM_PTATTRS_RSVD_12_9_MASK UINT64_C(0x0000000000001e00)
+/** Read access bit - EPT only. */
+#define PGM_PTATTRS_EPT_R_SHIFT 13
+#define PGM_PTATTRS_EPT_R_MASK RT_BIT_64(PGM_PTATTRS_EPT_R_SHIFT)
+/** Write access bit - EPT only. */
+#define PGM_PTATTRS_EPT_W_SHIFT 14
+#define PGM_PTATTRS_EPT_W_MASK RT_BIT_64(PGM_PTATTRS_EPT_W_SHIFT)
+/** Execute or execute access for supervisor-mode linear addresses - EPT only. */
+#define PGM_PTATTRS_EPT_X_SUPER_SHIFT 15
+#define PGM_PTATTRS_EPT_X_SUPER_MASK RT_BIT_64(PGM_PTATTRS_EPT_X_SUPER_SHIFT)
+/** EPT memory type - EPT only. */
+#define PGM_PTATTRS_EPT_MEMTYPE_SHIFT 16
+#define PGM_PTATTRS_EPT_MEMTYPE_MASK UINT64_C(0x0000000000070000)
+/** Ignore PAT memory type - EPT only. */
+#define PGM_PTATTRS_EPT_IGNORE_PAT_SHIFT 19
+#define PGM_PTATTRS_EPT_IGNORE_PAT_MASK RT_BIT_64(PGM_PTATTRS_EPT_IGNORE_PAT_SHIFT)
+/** Leaf paging entry (big or regular) - EPT only. */
+#define PGM_PTATTRS_EPT_LEAF_SHIFT 20
+#define PGM_PTATTRS_EPT_LEAF_MASK RT_BIT_64(PGM_PTATTRS_EPT_LEAF_SHIFT)
+/** Accessed bit - EPT only. */
+#define PGM_PTATTRS_EPT_A_SHIFT 21
+#define PGM_PTATTRS_EPT_A_MASK RT_BIT_64(PGM_PTATTRS_EPT_A_SHIFT)
+/** Dirty bit - EPT only. */
+#define PGM_PTATTRS_EPT_D_SHIFT 22
+#define PGM_PTATTRS_EPT_D_MASK RT_BIT_64(PGM_PTATTRS_EPT_D_SHIFT)
+/** Execute access for user-mode linear addresses - EPT only. */
+#define PGM_PTATTRS_EPT_X_USER_SHIFT 23
+#define PGM_PTATTRS_EPT_X_USER_MASK RT_BIT_64(PGM_PTATTRS_EPT_X_USER_SHIFT)
+/** Reserved (bits 29:24) - unused. */
+#define PGM_PTATTRS_RSVD_29_24_SHIFT 24
+#define PGM_PTATTRS_RSVD_29_24_MASK UINT64_C(0x000000003f000000)
+/** Verify Guest Paging - EPT only. */
+#define PGM_PTATTRS_EPT_VGP_SHIFT 30
+#define PGM_PTATTRS_EPT_VGP_MASK RT_BIT_64(PGM_PTATTRS_EPT_VGP_SHIFT)
+/** Paging-write - EPT only. */
+#define PGM_PTATTRS_EPT_PW_SHIFT 31
+#define PGM_PTATTRS_EPT_PW_MASK RT_BIT_64(PGM_PTATTRS_EPT_PW_SHIFT)
+/** Reserved (bit 32) - unused. */
+#define PGM_PTATTRS_RSVD_32_SHIFT 32
+#define PGM_PTATTRS_RSVD_32_MASK UINT64_C(0x0000000100000000)
+/** Supervisor shadow stack - EPT only. */
+#define PGM_PTATTRS_EPT_SSS_SHIFT 33
+#define PGM_PTATTRS_EPT_SSS_MASK RT_BIT_64(PGM_PTATTRS_EPT_SSS_SHIFT)
+/** Sub-page write permission - EPT only. */
+#define PGM_PTATTRS_EPT_SPP_SHIFT 34
+#define PGM_PTATTRS_EPT_SPP_MASK RT_BIT_64(PGM_PTATTRS_EPT_SPP_SHIFT)
+/** Reserved (bit 35) - unused. */
+#define PGM_PTATTRS_RSVD_35_SHIFT 35
+#define PGM_PTATTRS_RSVD_35_MASK UINT64_C(0x0000000800000000)
+/** Suppress \#VE exception - EPT only. */
+#define PGM_PTATTRS_EPT_SVE_SHIFT 36
+#define PGM_PTATTRS_EPT_SVE_MASK RT_BIT_64(PGM_PTATTRS_EPT_SVE_SHIFT)
+/** Reserved (bits 62:37) - unused. */
+#define PGM_PTATTRS_RSVD_62_37_SHIFT 37
+#define PGM_PTATTRS_RSVD_62_37_MASK UINT64_C(0x7fffffe000000000)
+/** No-execute bit. */
+#define PGM_PTATTRS_NX_SHIFT 63
+#define PGM_PTATTRS_NX_MASK RT_BIT_64(PGM_PTATTRS_NX_SHIFT)
+
+RT_BF_ASSERT_COMPILE_CHECKS(PGM_PTATTRS_, UINT64_C(0), UINT64_MAX,
+ (R, W, US, PWT, PCD, A, D, PAT, G, RSVD_12_9, EPT_R, EPT_W, EPT_X_SUPER, EPT_MEMTYPE, EPT_IGNORE_PAT,
+ EPT_LEAF, EPT_A, EPT_D, EPT_X_USER, RSVD_29_24, EPT_VGP, EPT_PW, RSVD_32, EPT_SSS, EPT_SPP,
+ RSVD_35, EPT_SVE, RSVD_62_37, NX));
+
+/** The bit position where the EPT specific attributes begin. */
+#define PGM_PTATTRS_EPT_SHIFT PGM_PTATTRS_EPT_R_SHIFT
+/** The mask of EPT bits (bits 36:ATTR_SHIFT). In the future we might choose to
+ * use higher unused bits for something else, in that case adjust this mask. */
+#define PGM_PTATTRS_EPT_MASK UINT64_C(0x0000001fffffe000)
+
+/** The mask of all PGM page attribute bits for regular page-tables. */
+#define PGM_PTATTRS_PT_VALID_MASK ( PGM_PTATTRS_R_MASK \
+ | PGM_PTATTRS_W_MASK \
+ | PGM_PTATTRS_US_MASK \
+ | PGM_PTATTRS_PWT_MASK \
+ | PGM_PTATTRS_PCD_MASK \
+ | PGM_PTATTRS_A_MASK \
+ | PGM_PTATTRS_D_MASK \
+ | PGM_PTATTRS_PAT_MASK \
+ | PGM_PTATTRS_G_MASK \
+ | PGM_PTATTRS_NX_MASK)
+
+/** The mask of all PGM page attribute bits for EPT. */
+#define PGM_PTATTRS_EPT_VALID_MASK ( PGM_PTATTRS_EPT_R_MASK \
+ | PGM_PTATTRS_EPT_W_MASK \
+ | PGM_PTATTRS_EPT_X_SUPER_MASK \
+ | PGM_PTATTRS_EPT_MEMTYPE_MASK \
+ | PGM_PTATTRS_EPT_IGNORE_PAT_MASK \
+ | PGM_PTATTRS_EPT_LEAF_MASK \
+ | PGM_PTATTRS_EPT_A_MASK \
+ | PGM_PTATTRS_EPT_D_MASK \
+ | PGM_PTATTRS_EPT_X_USER_MASK \
+ | PGM_PTATTRS_EPT_VGP_MASK \
+ | PGM_PTATTRS_EPT_PW_MASK \
+ | PGM_PTATTRS_EPT_SSS_MASK \
+ | PGM_PTATTRS_EPT_SPP_MASK \
+ | PGM_PTATTRS_EPT_SVE_MASK)
+
+/* The mask of all PGM page attribute bits (combined). */
+#define PGM_PTATTRS_VALID_MASK (PGM_PTATTRS_PT_VALID_MASK | PGM_PTATTRS_EPT_VALID_MASK)
+
+/* Verify bits match the regular PT bits. */
+AssertCompile(PGM_PTATTRS_W_SHIFT == X86_PTE_BIT_RW);
+AssertCompile(PGM_PTATTRS_US_SHIFT == X86_PTE_BIT_US);
+AssertCompile(PGM_PTATTRS_PWT_SHIFT == X86_PTE_BIT_PWT);
+AssertCompile(PGM_PTATTRS_PCD_SHIFT == X86_PTE_BIT_PCD);
+AssertCompile(PGM_PTATTRS_A_SHIFT == X86_PTE_BIT_A);
+AssertCompile(PGM_PTATTRS_D_SHIFT == X86_PTE_BIT_D);
+AssertCompile(PGM_PTATTRS_PAT_SHIFT == X86_PTE_BIT_PAT);
+AssertCompile(PGM_PTATTRS_G_SHIFT == X86_PTE_BIT_G);
+AssertCompile(PGM_PTATTRS_W_MASK == X86_PTE_RW);
+AssertCompile(PGM_PTATTRS_US_MASK == X86_PTE_US);
+AssertCompile(PGM_PTATTRS_PWT_MASK == X86_PTE_PWT);
+AssertCompile(PGM_PTATTRS_PCD_MASK == X86_PTE_PCD);
+AssertCompile(PGM_PTATTRS_A_MASK == X86_PTE_A);
+AssertCompile(PGM_PTATTRS_D_MASK == X86_PTE_D);
+AssertCompile(PGM_PTATTRS_PAT_MASK == X86_PTE_PAT);
+AssertCompile(PGM_PTATTRS_G_MASK == X86_PTE_G);
+AssertCompile(PGM_PTATTRS_NX_MASK == X86_PTE_PAE_NX);
+
+/* Verify those EPT bits that must map 1:1 (after shifting). */
+AssertCompile(PGM_PTATTRS_EPT_R_SHIFT - PGM_PTATTRS_EPT_SHIFT == EPT_E_BIT_READ);
+AssertCompile(PGM_PTATTRS_EPT_W_SHIFT - PGM_PTATTRS_EPT_SHIFT == EPT_E_BIT_WRITE);
+AssertCompile(PGM_PTATTRS_EPT_X_SUPER_SHIFT - PGM_PTATTRS_EPT_SHIFT == EPT_E_BIT_EXECUTE);
+AssertCompile(PGM_PTATTRS_EPT_IGNORE_PAT_SHIFT - PGM_PTATTRS_EPT_SHIFT == EPT_E_BIT_IGNORE_PAT);
+AssertCompile(PGM_PTATTRS_EPT_X_USER_SHIFT - PGM_PTATTRS_EPT_SHIFT == EPT_E_BIT_USER_EXECUTE);
+/** @} */
+
+
+/**
+ * Page table walk information.
+ *
+ * This provides extensive information regarding page faults (or EPT
+ * violations/misconfigurations) while traversing page tables.
+ */
+typedef struct PGMPTWALK
+{
+ /** The linear address that is being resolved (input). */
+ RTGCPTR GCPtr;
+
+ /** The second-level physical address (input/output).
+ * @remarks only valid if fIsSlat is set. */
+ RTGCPHYS GCPhysNested;
+
+ /** The physical address that is the result of the walk (output). */
+ RTGCPHYS GCPhys;
+
+ /** Set if the walk succeeded. */
+ bool fSucceeded;
+ /** Whether this is a second-level address translation. */
+ bool fIsSlat;
+ /** Whether the linear address (GCPtr) caused the second-level
+ * address translation. */
+ bool fIsLinearAddrValid;
+ /** The level problem arrised at.
+ * PTE is level 1, PDE is level 2, PDPE is level 3, PML4 is level 4, CR3 is
+ * level 8. This is 0 on success. */
+ uint8_t uLevel;
+ /** Set if the page isn't present. */
+ bool fNotPresent;
+ /** Encountered a bad physical address. */
+ bool fBadPhysAddr;
+ /** Set if there was reserved bit violations. */
+ bool fRsvdError;
+ /** Set if it involves a big page (2/4 MB). */
+ bool fBigPage;
+ /** Set if it involves a gigantic page (1 GB). */
+ bool fGigantPage;
+ bool afPadding[3];
+ /** Page-walk failure type, PGM_WALKFAIL_XXX. */
+ PGMWALKFAIL fFailed;
+
+ /** The effective page-table attributes, PGM_PTATTRS_XXX. */
+ PGMPTATTRS fEffective;
+} PGMPTWALK;
+/** Pointer to page walk information. */
+typedef PGMPTWALK *PPGMPTWALK;
+/** Pointer to const page walk information. */
+typedef PGMPTWALK const *PCPGMPTWALK;
+
+
+/** Macro for checking if the guest is using paging.
+ * @param enmMode PGMMODE_*.
+ * @remark ASSUMES certain order of the PGMMODE_* values.
+ */
+#define PGMMODE_WITH_PAGING(enmMode) ((enmMode) >= PGMMODE_32_BIT)
+
+/** Macro for checking if it's one of the long mode modes.
+ * @param enmMode PGMMODE_*.
+ */
+#define PGMMODE_IS_LONG_MODE(enmMode) ((enmMode) == PGMMODE_AMD64_NX || (enmMode) == PGMMODE_AMD64)
+
+/** Macro for checking if it's one of the AMD64 nested modes.
+ * @param enmMode PGMMODE_*.
+ */
+#define PGMMODE_IS_NESTED(enmMode) ( (enmMode) == PGMMODE_NESTED_32BIT \
+ || (enmMode) == PGMMODE_NESTED_PAE \
+ || (enmMode) == PGMMODE_NESTED_AMD64)
+
+/** Macro for checking if it's one of the PAE modes.
+ * @param enmMode PGMMODE_*.
+ */
+#define PGMMODE_IS_PAE(enmMode) ( (enmMode) == PGMMODE_PAE \
+ || (enmMode) == PGMMODE_PAE_NX)
+
+/**
+ * Is the ROM mapped (true) or is the shadow RAM mapped (false).
+ *
+ * @returns boolean.
+ * @param enmProt The PGMROMPROT value, must be valid.
+ */
+#define PGMROMPROT_IS_ROM(enmProt) \
+ ( (enmProt) == PGMROMPROT_READ_ROM_WRITE_IGNORE \
+ || (enmProt) == PGMROMPROT_READ_ROM_WRITE_RAM )
+
+
+VMMDECL(bool) PGMIsLockOwner(PVMCC pVM);
+
+VMMDECL(int) PGMRegisterStringFormatTypes(void);
+VMMDECL(void) PGMDeregisterStringFormatTypes(void);
+VMMDECL(RTHCPHYS) PGMGetHyperCR3(PVMCPU pVCpu);
+VMMDECL(int) PGMTrap0eHandler(PVMCPUCC pVCpu, RTGCUINT uErr, PCPUMCTX pCtx, RTGCPTR pvFault);
+VMMDECL(int) PGMPrefetchPage(PVMCPUCC pVCpu, RTGCPTR GCPtrPage);
+VMMDECL(VBOXSTRICTRC) PGMInterpretInstruction(PVMCPUCC pVCpu, RTGCPTR pvFault);
+VMMDECL(int) PGMShwGetPage(PVMCPUCC pVCpu, RTGCPTR GCPtr, uint64_t *pfFlags, PRTHCPHYS pHCPhys);
+VMMDECL(int) PGMShwMakePageReadonly(PVMCPUCC pVCpu, RTGCPTR GCPtr, uint32_t fFlags);
+VMMDECL(int) PGMShwMakePageWritable(PVMCPUCC pVCpu, RTGCPTR GCPtr, uint32_t fFlags);
+VMMDECL(int) PGMShwMakePageNotPresent(PVMCPUCC pVCpu, RTGCPTR GCPtr, uint32_t fFlags);
+/** @name Flags for PGMShwMakePageReadonly, PGMShwMakePageWritable and
+ * PGMShwMakePageNotPresent
+ * @{ */
+/** The call is from an access handler for dealing with the a faulting write
+ * operation. The virtual address is within the same page. */
+#define PGM_MK_PG_IS_WRITE_FAULT RT_BIT(0)
+/** The page is an MMIO2. */
+#define PGM_MK_PG_IS_MMIO2 RT_BIT(1)
+/** @}*/
+VMMDECL(int) PGMGstGetPage(PVMCPUCC pVCpu, RTGCPTR GCPtr, PPGMPTWALK pWalk);
+VMMDECL(int) PGMGstModifyPage(PVMCPUCC pVCpu, RTGCPTR GCPtr, size_t cb, uint64_t fFlags, uint64_t fMask);
+VMM_INT_DECL(bool) PGMGstArePaePdpesValid(PVMCPUCC pVCpu, PCX86PDPE paPaePdpes);
+VMM_INT_DECL(int) PGMGstMapPaePdpes(PVMCPUCC pVCpu, PCX86PDPE paPaePdpes);
+VMM_INT_DECL(int) PGMGstMapPaePdpesAtCr3(PVMCPUCC pVCpu, uint64_t cr3);
+
+VMMDECL(int) PGMInvalidatePage(PVMCPUCC pVCpu, RTGCPTR GCPtrPage);
+VMMDECL(int) PGMFlushTLB(PVMCPUCC pVCpu, uint64_t cr3, bool fGlobal);
+VMMDECL(int) PGMSyncCR3(PVMCPUCC pVCpu, uint64_t cr0, uint64_t cr3, uint64_t cr4, bool fGlobal);
+VMMDECL(int) PGMUpdateCR3(PVMCPUCC pVCpu, uint64_t cr3);
+VMMDECL(int) PGMChangeMode(PVMCPUCC pVCpu, uint64_t cr0, uint64_t cr4, uint64_t efer, bool fForce);
+VMM_INT_DECL(int) PGMHCChangeMode(PVMCC pVM, PVMCPUCC pVCpu, PGMMODE enmGuestMode, bool fForce);
+VMMDECL(void) PGMCr0WpEnabled(PVMCPUCC pVCpu);
+VMMDECL(PGMMODE) PGMGetGuestMode(PVMCPU pVCpu);
+VMMDECL(PGMMODE) PGMGetShadowMode(PVMCPU pVCpu);
+VMMDECL(PGMMODE) PGMGetHostMode(PVM pVM);
+VMMDECL(const char *) PGMGetModeName(PGMMODE enmMode);
+#ifdef VBOX_WITH_NESTED_HWVIRT_VMX_EPT
+VMM_INT_DECL(const char *) PGMGetSlatModeName(PGMSLAT enmSlatMode);
+#endif
+VMM_INT_DECL(RTGCPHYS) PGMGetGuestCR3Phys(PVMCPU pVCpu);
+VMM_INT_DECL(void) PGMNotifyNxeChanged(PVMCPU pVCpu, bool fNxe);
+VMMDECL(bool) PGMHasDirtyPages(PVM pVM);
+VMM_INT_DECL(void) PGMSetGuestEptPtr(PVMCPUCC pVCpu, uint64_t uEptPtr);
+
+/** PGM physical access handler type registration handle (heap offset, valid
+ * cross contexts without needing fixing up). Callbacks and handler type is
+ * associated with this and it is shared by all handler registrations. */
+typedef uint64_t PGMPHYSHANDLERTYPE;
+/** Pointer to a PGM physical handler type registration handle. */
+typedef PGMPHYSHANDLERTYPE *PPGMPHYSHANDLERTYPE;
+/** NIL value for PGM physical access handler type handle. */
+#define NIL_PGMPHYSHANDLERTYPE UINT64_MAX
+VMMDECL(int) PGMHandlerPhysicalRegister(PVMCC pVM, RTGCPHYS GCPhys, RTGCPHYS GCPhysLast, PGMPHYSHANDLERTYPE hType,
+ uint64_t uUser, R3PTRTYPE(const char *) pszDesc);
+VMMDECL(int) PGMHandlerPhysicalModify(PVMCC pVM, RTGCPHYS GCPhysCurrent, RTGCPHYS GCPhys, RTGCPHYS GCPhysLast);
+VMMDECL(int) PGMHandlerPhysicalDeregister(PVMCC pVM, RTGCPHYS GCPhys);
+VMMDECL(int) PGMHandlerPhysicalChangeUserArg(PVMCC pVM, RTGCPHYS GCPhys, uint64_t uUser);
+VMMDECL(int) PGMHandlerPhysicalSplit(PVMCC pVM, RTGCPHYS GCPhys, RTGCPHYS GCPhysSplit);
+VMMDECL(int) PGMHandlerPhysicalJoin(PVMCC pVM, RTGCPHYS GCPhys1, RTGCPHYS GCPhys2);
+VMMDECL(int) PGMHandlerPhysicalPageTempOff(PVMCC pVM, RTGCPHYS GCPhys, RTGCPHYS GCPhysPage);
+VMMDECL(int) PGMHandlerPhysicalPageAliasMmio2(PVMCC pVM, RTGCPHYS GCPhys, RTGCPHYS GCPhysPage,
+ PPDMDEVINS pDevIns, PGMMMIO2HANDLE hMmio2, RTGCPHYS offMMio2PageRemap);
+VMMDECL(int) PGMHandlerPhysicalPageAliasHC(PVMCC pVM, RTGCPHYS GCPhys, RTGCPHYS GCPhysPage, RTHCPHYS HCPhysPageRemap);
+VMMDECL(int) PGMHandlerPhysicalReset(PVMCC pVM, RTGCPHYS GCPhys);
+VMMDECL(bool) PGMHandlerPhysicalIsRegistered(PVMCC pVM, RTGCPHYS GCPhys);
+
+/** @name PGMPHYSHANDLER_F_XXX - flags for PGMR3HandlerPhysicalTypeRegister and PGMR0HandlerPhysicalTypeRegister
+ * @{ */
+/** Whether to hold the PGM lock while calling the handler or not.
+ * Mainly an optimization for PGM callers. */
+#define PGMPHYSHANDLER_F_KEEP_PGM_LOCK RT_BIT_32(0)
+/** The uUser value is a ring-0 device instance index that needs translating
+ * into a PDMDEVINS pointer before calling the handler. This is a hack to make
+ * it possible to use access handlers in devices. */
+#define PGMPHYSHANDLER_F_R0_DEVINS_IDX RT_BIT_32(1)
+/** Don't apply the access handler to VT-x and AMD-V. Only works with full pages.
+ * This is a trick for the VT-x APIC access page in nested VT-x setups. */
+#define PGMPHYSHANDLER_F_NOT_IN_HM RT_BIT_32(2)
+/** Mask of valid bits. */
+#define PGMPHYSHANDLER_F_VALID_MASK UINT32_C(7)
+/** @} */
+
+
+/**
+ * Page type.
+ *
+ * @remarks This enum has to fit in a 3-bit field (see PGMPAGE::u3Type).
+ * @remarks This is used in the saved state, so changes to it requires bumping
+ * the saved state version.
+ * @todo So, convert to \#defines!
+ */
+typedef enum PGMPAGETYPE
+{
+ /** The usual invalid zero entry. */
+ PGMPAGETYPE_INVALID = 0,
+ /** RAM page. (RWX) */
+ PGMPAGETYPE_RAM,
+ /** MMIO2 page. (RWX) */
+ PGMPAGETYPE_MMIO2,
+ /** MMIO2 page aliased over an MMIO page. (RWX)
+ * See PGMHandlerPhysicalPageAlias(). */
+ PGMPAGETYPE_MMIO2_ALIAS_MMIO,
+ /** Special page aliased over an MMIO page. (RWX)
+ * See PGMHandlerPhysicalPageAliasHC(), but this is generally only used for
+ * VT-x's APIC access page at the moment. Treated as MMIO by everyone except
+ * the shadow paging code. */
+ PGMPAGETYPE_SPECIAL_ALIAS_MMIO,
+ /** Shadowed ROM. (RWX) */
+ PGMPAGETYPE_ROM_SHADOW,
+ /** ROM page. (R-X) */
+ PGMPAGETYPE_ROM,
+ /** MMIO page. (---) */
+ PGMPAGETYPE_MMIO,
+ /** End of valid entries. */
+ PGMPAGETYPE_END
+} PGMPAGETYPE;
+AssertCompile(PGMPAGETYPE_END == 8);
+
+/** @name PGM page type predicates.
+ * @{ */
+#define PGMPAGETYPE_IS_READABLE(a_enmType) ( (a_enmType) <= PGMPAGETYPE_ROM )
+#define PGMPAGETYPE_IS_WRITEABLE(a_enmType) ( (a_enmType) <= PGMPAGETYPE_ROM_SHADOW )
+#define PGMPAGETYPE_IS_RWX(a_enmType) ( (a_enmType) <= PGMPAGETYPE_ROM_SHADOW )
+#define PGMPAGETYPE_IS_ROX(a_enmType) ( (a_enmType) == PGMPAGETYPE_ROM )
+#define PGMPAGETYPE_IS_NP(a_enmType) ( (a_enmType) == PGMPAGETYPE_MMIO )
+/** @} */
+
+
+VMM_INT_DECL(PGMPAGETYPE) PGMPhysGetPageType(PVMCC pVM, RTGCPHYS GCPhys);
+
+VMM_INT_DECL(int) PGMPhysGCPhys2HCPhys(PVMCC pVM, RTGCPHYS GCPhys, PRTHCPHYS pHCPhys);
+VMM_INT_DECL(int) PGMPhysGCPtr2HCPhys(PVMCPUCC pVCpu, RTGCPTR GCPtr, PRTHCPHYS pHCPhys);
+VMM_INT_DECL(int) PGMPhysGCPhys2CCPtr(PVMCC pVM, RTGCPHYS GCPhys, void **ppv, PPGMPAGEMAPLOCK pLock);
+VMM_INT_DECL(int) PGMPhysGCPhys2CCPtrReadOnly(PVMCC pVM, RTGCPHYS GCPhys, void const **ppv, PPGMPAGEMAPLOCK pLock);
+VMM_INT_DECL(int) PGMPhysGCPtr2CCPtr(PVMCPU pVCpu, RTGCPTR GCPtr, void **ppv, PPGMPAGEMAPLOCK pLock);
+VMM_INT_DECL(int) PGMPhysGCPtr2CCPtrReadOnly(PVMCPUCC pVCpu, RTGCPTR GCPtr, void const **ppv, PPGMPAGEMAPLOCK pLock);
+
+VMMDECL(bool) PGMPhysIsA20Enabled(PVMCPU pVCpu);
+VMMDECL(bool) PGMPhysIsGCPhysValid(PVMCC pVM, RTGCPHYS GCPhys);
+VMMDECL(bool) PGMPhysIsGCPhysNormal(PVMCC pVM, RTGCPHYS GCPhys);
+VMMDECL(int) PGMPhysGCPtr2GCPhys(PVMCPUCC pVCpu, RTGCPTR GCPtr, PRTGCPHYS pGCPhys);
+VMMDECL(void) PGMPhysReleasePageMappingLock(PVMCC pVM, PPGMPAGEMAPLOCK pLock);
+VMMDECL(void) PGMPhysBulkReleasePageMappingLocks(PVMCC pVM, uint32_t cPages, PPGMPAGEMAPLOCK paLock);
+
+/** @def PGM_PHYS_RW_IS_SUCCESS
+ * Check whether a PGMPhysRead, PGMPhysWrite, PGMPhysReadGCPtr or
+ * PGMPhysWriteGCPtr call completed the given task.
+ *
+ * @returns true if completed, false if not.
+ * @param a_rcStrict The status code.
+ * @sa IOM_SUCCESS
+ */
+#ifdef IN_RING3
+# define PGM_PHYS_RW_IS_SUCCESS(a_rcStrict) \
+ ( (a_rcStrict) == VINF_SUCCESS \
+ || (a_rcStrict) == VINF_EM_DBG_STOP \
+ || (a_rcStrict) == VINF_EM_DBG_EVENT \
+ || (a_rcStrict) == VINF_EM_DBG_BREAKPOINT \
+ )
+#elif defined(IN_RING0)
+# define PGM_PHYS_RW_IS_SUCCESS(a_rcStrict) \
+ ( (a_rcStrict) == VINF_SUCCESS \
+ || (a_rcStrict) == VINF_IOM_R3_MMIO_COMMIT_WRITE \
+ || (a_rcStrict) == VINF_EM_OFF \
+ || (a_rcStrict) == VINF_EM_SUSPEND \
+ || (a_rcStrict) == VINF_EM_RESET \
+ || (a_rcStrict) == VINF_EM_HALT \
+ || (a_rcStrict) == VINF_EM_DBG_STOP \
+ || (a_rcStrict) == VINF_EM_DBG_EVENT \
+ || (a_rcStrict) == VINF_EM_DBG_BREAKPOINT \
+ )
+#elif defined(IN_RC)
+# define PGM_PHYS_RW_IS_SUCCESS(a_rcStrict) \
+ ( (a_rcStrict) == VINF_SUCCESS \
+ || (a_rcStrict) == VINF_IOM_R3_MMIO_COMMIT_WRITE \
+ || (a_rcStrict) == VINF_EM_OFF \
+ || (a_rcStrict) == VINF_EM_SUSPEND \
+ || (a_rcStrict) == VINF_EM_RESET \
+ || (a_rcStrict) == VINF_EM_HALT \
+ || (a_rcStrict) == VINF_SELM_SYNC_GDT \
+ || (a_rcStrict) == VINF_EM_RAW_EMULATE_INSTR_GDT_FAULT \
+ || (a_rcStrict) == VINF_EM_DBG_STOP \
+ || (a_rcStrict) == VINF_EM_DBG_EVENT \
+ || (a_rcStrict) == VINF_EM_DBG_BREAKPOINT \
+ )
+#endif
+/** @def PGM_PHYS_RW_DO_UPDATE_STRICT_RC
+ * Updates the return code with a new result.
+ *
+ * Both status codes must be successes according to PGM_PHYS_RW_IS_SUCCESS.
+ *
+ * @param a_rcStrict The current return code, to be updated.
+ * @param a_rcStrict2 The new return code to merge in.
+ */
+#ifdef IN_RING3
+# define PGM_PHYS_RW_DO_UPDATE_STRICT_RC(a_rcStrict, a_rcStrict2) \
+ do { \
+ Assert(rcStrict == VINF_SUCCESS); \
+ Assert(rcStrict2 == VINF_SUCCESS); \
+ } while (0)
+#elif defined(IN_RING0)
+# define PGM_PHYS_RW_DO_UPDATE_STRICT_RC(a_rcStrict, a_rcStrict2) \
+ do { \
+ Assert(PGM_PHYS_RW_IS_SUCCESS(rcStrict)); \
+ Assert(PGM_PHYS_RW_IS_SUCCESS(rcStrict2)); \
+ AssertCompile(VINF_IOM_R3_MMIO_COMMIT_WRITE > VINF_EM_LAST); \
+ if ((a_rcStrict2) == VINF_SUCCESS || (a_rcStrict) == (a_rcStrict2)) \
+ { /* likely */ } \
+ else if ( (a_rcStrict) == VINF_SUCCESS \
+ || (a_rcStrict) > (a_rcStrict2)) \
+ (a_rcStrict) = (a_rcStrict2); \
+ } while (0)
+#elif defined(IN_RC)
+# define PGM_PHYS_RW_DO_UPDATE_STRICT_RC(a_rcStrict, a_rcStrict2) \
+ do { \
+ Assert(PGM_PHYS_RW_IS_SUCCESS(rcStrict)); \
+ Assert(PGM_PHYS_RW_IS_SUCCESS(rcStrict2)); \
+ AssertCompile(VINF_SELM_SYNC_GDT > VINF_EM_LAST); \
+ AssertCompile(VINF_EM_RAW_EMULATE_INSTR_GDT_FAULT > VINF_EM_LAST); \
+ AssertCompile(VINF_EM_RAW_EMULATE_INSTR_GDT_FAULT < VINF_SELM_SYNC_GDT); \
+ AssertCompile(VINF_IOM_R3_MMIO_COMMIT_WRITE > VINF_EM_LAST); \
+ AssertCompile(VINF_IOM_R3_MMIO_COMMIT_WRITE > VINF_SELM_SYNC_GDT); \
+ AssertCompile(VINF_IOM_R3_MMIO_COMMIT_WRITE > VINF_EM_RAW_EMULATE_INSTR_GDT_FAULT); \
+ if ((a_rcStrict2) == VINF_SUCCESS || (a_rcStrict) == (a_rcStrict2)) \
+ { /* likely */ } \
+ else if ((a_rcStrict) == VINF_SUCCESS) \
+ (a_rcStrict) = (a_rcStrict2); \
+ else if ( ( (a_rcStrict) > (a_rcStrict2) \
+ && ( (a_rcStrict2) <= VINF_EM_RESET \
+ || (a_rcStrict) != VINF_EM_RAW_EMULATE_INSTR_GDT_FAULT) ) \
+ || ( (a_rcStrict2) == VINF_EM_RAW_EMULATE_INSTR_GDT_FAULT \
+ && (a_rcStrict) > VINF_EM_RESET) ) \
+ (a_rcStrict) = (a_rcStrict2); \
+ } while (0)
+#endif
+
+VMMDECL(VBOXSTRICTRC) PGMPhysRead(PVMCC pVM, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead, PGMACCESSORIGIN enmOrigin);
+VMMDECL(VBOXSTRICTRC) PGMPhysWrite(PVMCC pVM, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite, PGMACCESSORIGIN enmOrigin);
+VMMDECL(VBOXSTRICTRC) PGMPhysReadGCPtr(PVMCPUCC pVCpu, void *pvDst, RTGCPTR GCPtrSrc, size_t cb, PGMACCESSORIGIN enmOrigin);
+VMMDECL(VBOXSTRICTRC) PGMPhysWriteGCPtr(PVMCPUCC pVCpu, RTGCPTR GCPtrDst, const void *pvSrc, size_t cb, PGMACCESSORIGIN enmOrigin);
+
+VMMDECL(int) PGMPhysSimpleReadGCPhys(PVMCC pVM, void *pvDst, RTGCPHYS GCPhysSrc, size_t cb);
+VMMDECL(int) PGMPhysSimpleWriteGCPhys(PVMCC pVM, RTGCPHYS GCPhysDst, const void *pvSrc, size_t cb);
+VMMDECL(int) PGMPhysSimpleReadGCPtr(PVMCPUCC pVCpu, void *pvDst, RTGCPTR GCPtrSrc, size_t cb);
+VMMDECL(int) PGMPhysSimpleWriteGCPtr(PVMCPUCC pVCpu, RTGCPTR GCPtrDst, const void *pvSrc, size_t cb);
+VMMDECL(int) PGMPhysSimpleDirtyWriteGCPtr(PVMCPUCC pVCpu, RTGCPTR GCPtrDst, const void *pvSrc, size_t cb);
+
+VMM_INT_DECL(int) PGMPhysIemGCPhys2Ptr(PVMCC pVM, PVMCPUCC pVCpu, RTGCPHYS GCPhys, bool fWritable, bool fByPassHandlers, void **ppv, PPGMPAGEMAPLOCK pLock);
+VMM_INT_DECL(int) PGMPhysIemQueryAccess(PVMCC pVM, RTGCPHYS GCPhys, bool fWritable, bool fByPassHandlers);
+VMM_INT_DECL(int) PGMPhysIemGCPhys2PtrNoLock(PVMCC pVM, PVMCPUCC pVCpu, RTGCPHYS GCPhys, uint64_t const volatile *puTlbPhysRev,
+#if defined(IN_RC)
+ R3PTRTYPE(uint8_t *) *ppb,
+#else
+ R3R0PTRTYPE(uint8_t *) *ppb,
+#endif
+ uint64_t *pfTlb);
+/** @name Flags returned by PGMPhysIemGCPhys2PtrNoLock
+ * @{ */
+#define PGMIEMGCPHYS2PTR_F_NO_WRITE RT_BIT_32(3) /**< Not writable (IEMTLBE_F_PG_NO_WRITE). */
+#define PGMIEMGCPHYS2PTR_F_NO_READ RT_BIT_32(4) /**< Not readable (IEMTLBE_F_PG_NO_READ). */
+#define PGMIEMGCPHYS2PTR_F_NO_MAPPINGR3 RT_BIT_32(7) /**< No ring-3 mapping (IEMTLBE_F_NO_MAPPINGR3). */
+#define PGMIEMGCPHYS2PTR_F_UNASSIGNED RT_BIT_32(8) /**< Unassgined memory (IEMTLBE_F_PG_UNASSIGNED). */
+/** @} */
+
+/** Information returned by PGMPhysNemQueryPageInfo. */
+typedef struct PGMPHYSNEMPAGEINFO
+{
+ /** The host physical address of the page, NIL_HCPHYS if invalid page. */
+ RTHCPHYS HCPhys;
+ /** The NEM access mode for the page, NEM_PAGE_PROT_XXX */
+ uint32_t fNemProt : 8;
+ /** The NEM state associated with the PAGE. */
+ uint32_t u2NemState : 2;
+ /** The NEM state associated with the PAGE before pgmPhysPageMakeWritable was called. */
+ uint32_t u2OldNemState : 2;
+ /** Set if the page has handler. */
+ uint32_t fHasHandlers : 1;
+ /** Set if is the zero page backing it. */
+ uint32_t fZeroPage : 1;
+ /** Set if the page has handler. */
+ PGMPAGETYPE enmType;
+} PGMPHYSNEMPAGEINFO;
+/** Pointer to page information for NEM. */
+typedef PGMPHYSNEMPAGEINFO *PPGMPHYSNEMPAGEINFO;
+/**
+ * Callback for checking that the page is in sync while under the PGM lock.
+ *
+ * NEM passes this callback to PGMPhysNemQueryPageInfo to check that the page is
+ * in-sync between PGM and the native hypervisor API in an atomic fashion.
+ *
+ * @returns VBox status code.
+ * @param pVM The cross context VM structure.
+ * @param pVCpu The cross context per virtual CPU structure. Optional,
+ * see PGMPhysNemQueryPageInfo.
+ * @param GCPhys The guest physical address (not A20 masked).
+ * @param pInfo The page info structure. This function updates the
+ * u2NemState memory and the caller will update the PGMPAGE
+ * copy accordingly.
+ * @param pvUser Callback user argument.
+ */
+typedef DECLCALLBACKTYPE(int, FNPGMPHYSNEMCHECKPAGE,(PVMCC pVM, PVMCPUCC pVCpu, RTGCPHYS GCPhys, PPGMPHYSNEMPAGEINFO pInfo, void *pvUser));
+/** Pointer to a FNPGMPHYSNEMCHECKPAGE function. */
+typedef FNPGMPHYSNEMCHECKPAGE *PFNPGMPHYSNEMCHECKPAGE;
+
+VMM_INT_DECL(int) PGMPhysNemPageInfoChecker(PVMCC pVM, PVMCPUCC pVCpu, RTGCPHYS GCPhys, bool fMakeWritable,
+ PPGMPHYSNEMPAGEINFO pInfo, PFNPGMPHYSNEMCHECKPAGE pfnChecker, void *pvUser);
+
+/**
+ * Callback for use with PGMPhysNemEnumPagesByState.
+ * @returns VBox status code.
+ * Failure status will stop enumeration immediately and return.
+ * @param pVM The cross context VM structure.
+ * @param pVCpu The cross context per virtual CPU structure. Optional,
+ * see PGMPhysNemEnumPagesByState.
+ * @param GCPhys The guest physical address (not A20 masked).
+ * @param pu2NemState Pointer to variable with the NEM state. This can be
+ * update.
+ * @param pvUser The user argument.
+ */
+typedef DECLCALLBACKTYPE(int, FNPGMPHYSNEMENUMCALLBACK,(PVMCC pVM, PVMCPUCC pVCpu, RTGCPHYS GCPhys,
+ uint8_t *pu2NemState, void *pvUser));
+/** Pointer to a FNPGMPHYSNEMENUMCALLBACK function. */
+typedef FNPGMPHYSNEMENUMCALLBACK *PFNPGMPHYSNEMENUMCALLBACK;
+VMM_INT_DECL(int) PGMPhysNemEnumPagesByState(PVMCC pVM, PVMCPUCC VCpu, uint8_t uMinState,
+ PFNPGMPHYSNEMENUMCALLBACK pfnCallback, void *pvUser);
+
+
+#ifdef VBOX_STRICT
+VMMDECL(unsigned) PGMAssertHandlerAndFlagsInSync(PVMCC pVM);
+VMMDECL(unsigned) PGMAssertNoMappingConflicts(PVM pVM);
+VMMDECL(unsigned) PGMAssertCR3(PVMCC pVM, PVMCPUCC pVCpu, uint64_t cr3, uint64_t cr4);
+#endif /* VBOX_STRICT */
+
+VMMDECL(int) PGMSetLargePageUsage(PVMCC pVM, bool fUseLargePages);
+
+/**
+ * Query large page usage state
+ *
+ * @returns 0 - disabled, 1 - enabled
+ * @param pVM The cross context VM structure.
+ */
+#define PGMIsUsingLargePages(pVM) ((pVM)->pgm.s.fUseLargePages)
+
+
+#ifdef IN_RING0
+/** @defgroup grp_pgm_r0 The PGM Host Context Ring-0 API
+ * @{
+ */
+VMMR0_INT_DECL(int) PGMR0InitPerVMData(PGVM pGVM, RTR0MEMOBJ hMemObj);
+VMMR0_INT_DECL(int) PGMR0InitVM(PGVM pGVM);
+VMMR0_INT_DECL(void) PGMR0DoneInitVM(PGVM pGVM);
+VMMR0_INT_DECL(void) PGMR0CleanupVM(PGVM pGVM);
+VMMR0_INT_DECL(int) PGMR0PhysAllocateHandyPages(PGVM pGVM, VMCPUID idCpu);
+VMMR0_INT_DECL(int) PGMR0PhysFlushHandyPages(PGVM pGVM, VMCPUID idCpu);
+VMMR0_INT_DECL(int) PGMR0PhysAllocateLargePage(PGVM pGVM, VMCPUID idCpu, RTGCPHYS GCPhys);
+VMMR0_INT_DECL(int) PGMR0PhysMMIO2MapKernel(PGVM pGVM, PPDMDEVINS pDevIns, PGMMMIO2HANDLE hMmio2,
+ size_t offSub, size_t cbSub, void **ppvMapping);
+VMMR0_INT_DECL(int) PGMR0PhysSetupIoMmu(PGVM pGVM);
+VMMR0_INT_DECL(int) PGMR0PhysHandlerInitReqHandler(PGVM pGVM, uint32_t cEntries);
+VMMR0_INT_DECL(int) PGMR0HandlerPhysicalTypeSetUpContext(PGVM pGVM, PGMPHYSHANDLERKIND enmKind, uint32_t fFlags,
+ PFNPGMPHYSHANDLER pfnHandler, PFNPGMRZPHYSPFHANDLER pfnPfHandler,
+ const char *pszDesc, PGMPHYSHANDLERTYPE hType);
+
+VMMR0DECL(int) PGMR0SharedModuleCheck(PVMCC pVM, PGVM pGVM, VMCPUID idCpu, PGMMSHAREDMODULE pModule,
+ PCRTGCPTR64 paRegionsGCPtrs);
+VMMR0DECL(int) PGMR0Trap0eHandlerNestedPaging(PGVM pGVM, PGVMCPU pGVCpu, PGMMODE enmShwPagingMode, RTGCUINT uErr,
+ PCPUMCTX pCtx, RTGCPHYS pvFault);
+VMMR0DECL(VBOXSTRICTRC) PGMR0Trap0eHandlerNPMisconfig(PGVM pGVM, PGVMCPU pGVCpu, PGMMODE enmShwPagingMode,
+ PCPUMCTX pCtx, RTGCPHYS GCPhysFault, uint32_t uErr);
+VMMR0_INT_DECL(int) PGMR0PoolGrow(PGVM pGVM, VMCPUID idCpu);
+
+# ifdef VBOX_WITH_NESTED_HWVIRT_VMX_EPT
+VMMR0DECL(VBOXSTRICTRC) PGMR0NestedTrap0eHandlerNestedPaging(PGVMCPU pGVCpu, PGMMODE enmShwPagingMode, RTGCUINT uErr,
+ PCPUMCTX pCtx, RTGCPHYS GCPhysNestedFault,
+ bool fIsLinearAddrValid, RTGCPTR GCPtrNestedFault, PPGMPTWALK pWalk);
+# endif
+/** @} */
+#endif /* IN_RING0 */
+
+
+
+#ifdef IN_RING3
+/** @defgroup grp_pgm_r3 The PGM Host Context Ring-3 API
+ * @{
+ */
+VMMR3_INT_DECL(void) PGMR3EnableNemMode(PVM pVM);
+VMMR3_INT_DECL(bool) PGMR3IsNemModeEnabled(PVM pVM);
+VMMR3DECL(int) PGMR3Init(PVM pVM);
+VMMR3DECL(int) PGMR3InitFinalize(PVM pVM);
+VMMR3_INT_DECL(int) PGMR3InitCompleted(PVM pVM, VMINITCOMPLETED enmWhat);
+VMMR3DECL(void) PGMR3Relocate(PVM pVM, RTGCINTPTR offDelta);
+VMMR3DECL(void) PGMR3ResetCpu(PVM pVM, PVMCPU pVCpu);
+VMMR3_INT_DECL(void) PGMR3Reset(PVM pVM);
+VMMR3_INT_DECL(void) PGMR3ResetNoMorePhysWritesFlag(PVM pVM);
+VMMR3_INT_DECL(void) PGMR3MemSetup(PVM pVM, bool fReset);
+VMMR3DECL(int) PGMR3Term(PVM pVM);
+
+VMMR3DECL(int) PGMR3PhysRegisterRam(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, const char *pszDesc);
+VMMR3DECL(int) PGMR3PhysChangeMemBalloon(PVM pVM, bool fInflate, unsigned cPages, RTGCPHYS *paPhysPage);
+VMMR3DECL(int) PGMR3PhysWriteProtectRAM(PVM pVM);
+VMMR3DECL(uint32_t) PGMR3PhysGetRamRangeCount(PVM pVM);
+VMMR3DECL(int) PGMR3PhysGetRange(PVM pVM, uint32_t iRange, PRTGCPHYS pGCPhysStart, PRTGCPHYS pGCPhysLast,
+ const char **ppszDesc, bool *pfIsMmio);
+VMMR3DECL(int) PGMR3QueryMemoryStats(PUVM pUVM, uint64_t *pcbTotalMem, uint64_t *pcbPrivateMem, uint64_t *pcbSharedMem, uint64_t *pcbZeroMem);
+VMMR3DECL(int) PGMR3QueryGlobalMemoryStats(PUVM pUVM, uint64_t *pcbAllocMem, uint64_t *pcbFreeMem, uint64_t *pcbBallonedMem, uint64_t *pcbSharedMem);
+
+VMMR3DECL(int) PGMR3PhysMMIORegister(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, PGMPHYSHANDLERTYPE hType,
+ uint64_t uUser, const char *pszDesc);
+VMMR3DECL(int) PGMR3PhysMMIODeregister(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb);
+
+/** @name PGMPHYS_MMIO2_FLAGS_XXX - MMIO2 registration flags.
+ * @see PGMR3PhysMmio2Register, PDMDevHlpMmio2Create
+ * @{ */
+/** Track dirty pages.
+ * @see PGMR3PhysMmio2QueryAndResetDirtyBitmap(), PGMR3PhysMmio2ControlDirtyPageTracking(). */
+#define PGMPHYS_MMIO2_FLAGS_TRACK_DIRTY_PAGES RT_BIT_32(0)
+/** Valid flags. */
+#define PGMPHYS_MMIO2_FLAGS_VALID_MASK UINT32_C(0x00000001)
+/** @} */
+
+VMMR3_INT_DECL(int) PGMR3PhysMmio2Register(PVM pVM, PPDMDEVINS pDevIns, uint32_t iSubDev, uint32_t iRegion, RTGCPHYS cb,
+ uint32_t fFlags, const char *pszDesc, void **ppv, PGMMMIO2HANDLE *phRegion);
+VMMR3_INT_DECL(int) PGMR3PhysMmio2Deregister(PVM pVM, PPDMDEVINS pDevIns, PGMMMIO2HANDLE hMmio2);
+VMMR3_INT_DECL(int) PGMR3PhysMmio2Map(PVM pVM, PPDMDEVINS pDevIns, PGMMMIO2HANDLE hMmio2, RTGCPHYS GCPhys);
+VMMR3_INT_DECL(int) PGMR3PhysMmio2Unmap(PVM pVM, PPDMDEVINS pDevIns, PGMMMIO2HANDLE hMmio2, RTGCPHYS GCPhys);
+VMMR3_INT_DECL(int) PGMR3PhysMmio2Reduce(PVM pVM, PPDMDEVINS pDevIns, PGMMMIO2HANDLE hMmio2, RTGCPHYS cbRegion);
+VMMR3_INT_DECL(int) PGMR3PhysMmio2ValidateHandle(PVM pVM, PPDMDEVINS pDevIns, PGMMMIO2HANDLE hMmio2);
+VMMR3_INT_DECL(RTGCPHYS) PGMR3PhysMmio2GetMappingAddress(PVM pVM, PPDMDEVINS pDevIns, PGMMMIO2HANDLE hMmio2);
+VMMR3_INT_DECL(int) PGMR3PhysMmio2ChangeRegionNo(PVM pVM, PPDMDEVINS pDevIns, PGMMMIO2HANDLE hMmio2, uint32_t iNewRegion);
+VMMR3_INT_DECL(int) PGMR3PhysMmio2QueryAndResetDirtyBitmap(PVM pVM, PPDMDEVINS pDevIns, PGMMMIO2HANDLE hMmio2,
+ void *pvBitmap, size_t cbBitmap);
+VMMR3_INT_DECL(int) PGMR3PhysMmio2ControlDirtyPageTracking(PVM pVM, PPDMDEVINS pDevIns, PGMMMIO2HANDLE hMmio2, bool fEnabled);
+
+/** @name PGMPHYS_ROM_FLAGS_XXX - ROM registration flags.
+ * @see PGMR3PhysRegisterRom, PDMDevHlpROMRegister
+ * @{ */
+/** Inidicates that ROM shadowing should be enabled. */
+#define PGMPHYS_ROM_FLAGS_SHADOWED UINT8_C(0x01)
+/** Indicates that what pvBinary points to won't go away
+ * and can be used for strictness checks. */
+#define PGMPHYS_ROM_FLAGS_PERMANENT_BINARY UINT8_C(0x02)
+/** Indicates that the ROM is allowed to be missing from saved state.
+ * @note This is a hack for EFI, see @bugref{6940} */
+#define PGMPHYS_ROM_FLAGS_MAYBE_MISSING_FROM_STATE UINT8_C(0x04)
+/** Valid flags. */
+#define PGMPHYS_ROM_FLAGS_VALID_MASK UINT8_C(0x07)
+/** @} */
+
+VMMR3DECL(int) PGMR3PhysRomRegister(PVM pVM, PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTGCPHYS cb,
+ const void *pvBinary, uint32_t cbBinary, uint8_t fFlags, const char *pszDesc);
+VMMR3DECL(int) PGMR3PhysRomProtect(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, PGMROMPROT enmProt);
+VMMDECL(void) PGMR3PhysSetA20(PVMCPU pVCpu, bool fEnable);
+
+VMMR3_INT_DECL(int) PGMR3HandlerPhysicalTypeRegister(PVM pVM, PGMPHYSHANDLERKIND enmKind, uint32_t fFlags,
+ PFNPGMPHYSHANDLER pfnHandlerR3, const char *pszDesc,
+ PPGMPHYSHANDLERTYPE phType);
+
+VMMR3_INT_DECL(int) PGMR3PoolGrow(PVM pVM, PVMCPU pVCpu);
+
+VMMR3DECL(int) PGMR3PhysTlbGCPhys2Ptr(PVM pVM, RTGCPHYS GCPhys, bool fWritable, void **ppv);
+VMMR3DECL(uint8_t) PGMR3PhysReadU8(PVM pVM, RTGCPHYS GCPhys, PGMACCESSORIGIN enmOrigin);
+VMMR3DECL(uint16_t) PGMR3PhysReadU16(PVM pVM, RTGCPHYS GCPhys, PGMACCESSORIGIN enmOrigin);
+VMMR3DECL(uint32_t) PGMR3PhysReadU32(PVM pVM, RTGCPHYS GCPhys, PGMACCESSORIGIN enmOrigin);
+VMMR3DECL(uint64_t) PGMR3PhysReadU64(PVM pVM, RTGCPHYS GCPhys, PGMACCESSORIGIN enmOrigin);
+VMMR3DECL(void) PGMR3PhysWriteU8(PVM pVM, RTGCPHYS GCPhys, uint8_t Value, PGMACCESSORIGIN enmOrigin);
+VMMR3DECL(void) PGMR3PhysWriteU16(PVM pVM, RTGCPHYS GCPhys, uint16_t Value, PGMACCESSORIGIN enmOrigin);
+VMMR3DECL(void) PGMR3PhysWriteU32(PVM pVM, RTGCPHYS GCPhys, uint32_t Value, PGMACCESSORIGIN enmOrigin);
+VMMR3DECL(void) PGMR3PhysWriteU64(PVM pVM, RTGCPHYS GCPhys, uint64_t Value, PGMACCESSORIGIN enmOrigin);
+VMMR3DECL(int) PGMR3PhysReadExternal(PVM pVM, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead, PGMACCESSORIGIN enmOrigin);
+VMMR3DECL(int) PGMR3PhysWriteExternal(PVM pVM, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite, PGMACCESSORIGIN enmOrigin);
+VMMR3DECL(int) PGMR3PhysGCPhys2CCPtrExternal(PVM pVM, RTGCPHYS GCPhys, void **ppv, PPGMPAGEMAPLOCK pLock);
+VMMR3DECL(int) PGMR3PhysGCPhys2CCPtrReadOnlyExternal(PVM pVM, RTGCPHYS GCPhys, void const **ppv, PPGMPAGEMAPLOCK pLock);
+VMMR3DECL(int) PGMR3PhysBulkGCPhys2CCPtrExternal(PVM pVM, uint32_t cPages, PCRTGCPHYS paGCPhysPages,
+ void **papvPages, PPGMPAGEMAPLOCK paLocks);
+VMMR3DECL(int) PGMR3PhysBulkGCPhys2CCPtrReadOnlyExternal(PVM pVM, uint32_t cPages, PCRTGCPHYS paGCPhysPages,
+ void const **papvPages, PPGMPAGEMAPLOCK paLocks);
+VMMR3DECL(void) PGMR3PhysChunkInvalidateTLB(PVM pVM);
+VMMR3DECL(int) PGMR3PhysAllocateHandyPages(PVM pVM);
+
+VMMR3DECL(int) PGMR3CheckIntegrity(PVM pVM);
+
+VMMR3DECL(int) PGMR3DbgR3Ptr2GCPhys(PUVM pUVM, RTR3PTR R3Ptr, PRTGCPHYS pGCPhys);
+VMMR3DECL(int) PGMR3DbgR3Ptr2HCPhys(PUVM pUVM, RTR3PTR R3Ptr, PRTHCPHYS pHCPhys);
+VMMR3DECL(int) PGMR3DbgHCPhys2GCPhys(PUVM pUVM, RTHCPHYS HCPhys, PRTGCPHYS pGCPhys);
+VMMR3_INT_DECL(int) PGMR3DbgReadGCPhys(PVM pVM, void *pvDst, RTGCPHYS GCPhysSrc, size_t cb, uint32_t fFlags, size_t *pcbRead);
+VMMR3_INT_DECL(int) PGMR3DbgWriteGCPhys(PVM pVM, RTGCPHYS GCPhysDst, const void *pvSrc, size_t cb, uint32_t fFlags, size_t *pcbWritten);
+VMMR3_INT_DECL(int) PGMR3DbgReadGCPtr(PVM pVM, void *pvDst, RTGCPTR GCPtrSrc, size_t cb, uint32_t fFlags, size_t *pcbRead);
+VMMR3_INT_DECL(int) PGMR3DbgWriteGCPtr(PVM pVM, RTGCPTR GCPtrDst, void const *pvSrc, size_t cb, uint32_t fFlags, size_t *pcbWritten);
+VMMR3_INT_DECL(int) PGMR3DbgScanPhysical(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cbRange, RTGCPHYS GCPhysAlign, const uint8_t *pabNeedle, size_t cbNeedle, PRTGCPHYS pGCPhysHit);
+VMMR3_INT_DECL(int) PGMR3DbgScanVirtual(PVM pVM, PVMCPU pVCpu, RTGCPTR GCPtr, RTGCPTR cbRange, RTGCPTR GCPtrAlign, const uint8_t *pabNeedle, size_t cbNeedle, PRTGCUINTPTR pGCPhysHit);
+VMMR3_INT_DECL(int) PGMR3DumpHierarchyShw(PVM pVM, uint64_t cr3, uint32_t fFlags, uint64_t u64FirstAddr, uint64_t u64LastAddr, uint32_t cMaxDepth, PCDBGFINFOHLP pHlp);
+VMMR3_INT_DECL(int) PGMR3DumpHierarchyGst(PVM pVM, uint64_t cr3, uint32_t fFlags, RTGCPTR FirstAddr, RTGCPTR LastAddr, uint32_t cMaxDepth, PCDBGFINFOHLP pHlp);
+
+
+/** @name Page sharing
+ * @{ */
+VMMR3DECL(int) PGMR3SharedModuleRegister(PVM pVM, VBOXOSFAMILY enmGuestOS, char *pszModuleName, char *pszVersion,
+ RTGCPTR GCBaseAddr, uint32_t cbModule,
+ uint32_t cRegions, VMMDEVSHAREDREGIONDESC const *paRegions);
+VMMR3DECL(int) PGMR3SharedModuleUnregister(PVM pVM, char *pszModuleName, char *pszVersion,
+ RTGCPTR GCBaseAddr, uint32_t cbModule);
+VMMR3DECL(int) PGMR3SharedModuleCheckAll(PVM pVM);
+VMMR3DECL(int) PGMR3SharedModuleGetPageState(PVM pVM, RTGCPTR GCPtrPage, bool *pfShared, uint64_t *pfPageFlags);
+/** @} */
+
+/** @} */
+#endif /* IN_RING3 */
+
+RT_C_DECLS_END
+
+/** @} */
+#endif /* !VBOX_INCLUDED_vmm_pgm_h */
+
diff --git a/include/VBox/vmm/selm.h b/include/VBox/vmm/selm.h
new file mode 100644
index 00000000..1b68e3f5
--- /dev/null
+++ b/include/VBox/vmm/selm.h
@@ -0,0 +1,114 @@
+/** @file
+ * SELM - The Selector Manager.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vmm_selm_h
+#define VBOX_INCLUDED_vmm_selm_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/types.h>
+#include <iprt/x86.h>
+#include <VBox/dis.h>
+#include <VBox/vmm/dbgfsel.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_selm The Selector Monitor(/Manager) API
+ * @ingroup grp_vmm
+ * @{
+ */
+
+VMMDECL(int) SELMGetTSSInfo(PVM pVM, PVMCPU pVCpu, PRTGCUINTPTR pGCPtrTss, PRTGCUINTPTR pcbTss, bool *pfCanHaveIOBitmap);
+VMMDECL(RTGCPTR) SELMToFlat(PVMCPUCC pVCpu, unsigned idxSeg, PCPUMCTX pCtx, RTGCPTR Addr);
+VMMDECL(RTGCPTR) SELMToFlatBySel(PVM pVM, RTSEL Sel, RTGCPTR Addr);
+
+/** Flags for SELMToFlatEx().
+ * @{ */
+/** Don't check the RPL,DPL or CPL. */
+#define SELMTOFLAT_FLAGS_NO_PL RT_BIT(8)
+/** Flags contains CPL information. */
+#define SELMTOFLAT_FLAGS_HAVE_CPL RT_BIT(9)
+/** CPL is 3. */
+#define SELMTOFLAT_FLAGS_CPL3 3
+/** CPL is 2. */
+#define SELMTOFLAT_FLAGS_CPL2 2
+/** CPL is 1. */
+#define SELMTOFLAT_FLAGS_CPL1 1
+/** CPL is 0. */
+#define SELMTOFLAT_FLAGS_CPL0 0
+/** Get the CPL from the flags. */
+#define SELMTOFLAT_FLAGS_CPL(fFlags) ((fFlags) & X86_SEL_RPL)
+#define SELMTOFLAT_FLAGS_HYPER RT_BIT(10)
+/** @} */
+
+VMMDECL(int) SELMToFlatEx(PVMCPU pVCpu, unsigned idxSeg, PCPUMCTX pCtx, RTGCPTR Addr, uint32_t fFlags, PRTGCPTR ppvGC);
+VMMDECL(int) SELMValidateAndConvertCSAddr(PVMCPU pVCpu, uint32_t fEFlags, RTSEL SelCPL, RTSEL SelCS,
+ PCPUMSELREG pSRegCS, RTGCPTR Addr, PRTGCPTR ppvFlat);
+#ifdef VBOX_WITH_RAW_MODE
+VMM_INT_DECL(void) SELMLoadHiddenSelectorReg(PVMCPU pVCpu, PCCPUMCTX pCtx, PCPUMSELREG pSReg);
+#endif
+
+
+#ifdef IN_RING3
+/** @defgroup grp_selm_r3 The SELM ring-3 Context API
+ * @{
+ */
+VMMR3DECL(int) SELMR3Init(PVM pVM);
+VMMR3DECL(void) SELMR3Relocate(PVM pVM);
+VMMR3DECL(int) SELMR3Term(PVM pVM);
+VMMR3DECL(void) SELMR3Reset(PVM pVM);
+VMMR3DECL(int) SELMR3GetSelectorInfo(PVMCPU pVCpu, RTSEL Sel, PDBGFSELINFO pSelInfo);
+VMMR3DECL(void) SELMR3DumpDescriptor(X86DESC Desc, RTSEL Sel, const char *pszMsg);
+VMMR3DECL(void) SELMR3DumpGuestGDT(PVM pVM);
+VMMR3DECL(void) SELMR3DumpGuestLDT(PVM pVM);
+
+/** @def SELMR3_DEBUG_CHECK
+ * Invokes SELMR3DebugCheck in stricts builds. */
+# ifdef VBOX_STRICT
+# define SELMR3_DEBUG_CHECK(pVM) SELMR3DebugCheck(pVM)
+# else
+# define SELMR3_DEBUG_CHECK(pVM) do { } while (0)
+# endif
+/** @} */
+#endif /* IN_RING3 */
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !VBOX_INCLUDED_vmm_selm_h */
+
diff --git a/include/VBox/vmm/ssm.h b/include/VBox/vmm/ssm.h
new file mode 100644
index 00000000..591b5d7e
--- /dev/null
+++ b/include/VBox/vmm/ssm.h
@@ -0,0 +1,1354 @@
+/** @file
+ * SSM - The Save State Manager.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vmm_ssm_h
+#define VBOX_INCLUDED_vmm_ssm_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/types.h>
+#include <VBox/vmm/tm.h>
+#include <VBox/vmm/vmapi.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_ssm The Saved State Manager API
+ * @ingroup grp_vmm
+ * @{
+ */
+
+/**
+ * Determine the major version of the SSM version. If the major SSM version of two snapshots is
+ * different, the snapshots are incompatible.
+ */
+#define SSM_VERSION_MAJOR(ver) ((ver) & 0xffff0000)
+
+/**
+ * Determine the minor version of the SSM version. If the major SSM version of two snapshots is
+ * the same, the code must handle incompatibilies between minor version changes (e.g. use dummy
+ * values for non-existent fields).
+ */
+#define SSM_VERSION_MINOR(ver) ((ver) & 0x0000ffff)
+
+/**
+ * Determine if the major version changed between two SSM versions.
+ */
+#define SSM_VERSION_MAJOR_CHANGED(ver1,ver2) (SSM_VERSION_MAJOR(ver1) != SSM_VERSION_MAJOR(ver2))
+
+/** The special value for the final pass. */
+#define SSM_PASS_FINAL UINT32_MAX
+
+
+#ifdef IN_RING3
+/** @defgroup grp_ssm_r3 The SSM Host Context Ring-3 API
+ * @{
+ */
+
+
+/**
+ * What to do after the save/load operation.
+ */
+typedef enum SSMAFTER
+{
+ /** Invalid. */
+ SSMAFTER_INVALID = 0,
+ /** Will resume the loaded state. */
+ SSMAFTER_RESUME,
+ /** Will destroy the VM after saving. */
+ SSMAFTER_DESTROY,
+ /** Will continue execution after saving the VM. */
+ SSMAFTER_CONTINUE,
+ /** Will teleport the VM.
+ * The source VM will be destroyed (then one saving), the destination VM
+ * will continue execution. */
+ SSMAFTER_TELEPORT,
+ /** Will debug the saved state.
+ * This is used to drop some of the stricter consitentcy checks so it'll
+ * load fine in the debugger or animator. */
+ SSMAFTER_DEBUG_IT,
+ /** The file was opened using SSMR3Open() and we have no idea what the plan is. */
+ SSMAFTER_OPENED
+} SSMAFTER;
+
+
+/** Pointer to a structure field description. */
+typedef struct SSMFIELD *PSSMFIELD;
+/** Pointer to a const structure field description. */
+typedef const struct SSMFIELD *PCSSMFIELD;
+
+/**
+ * SSMFIELD Get/Put callback function.
+ *
+ * This is call for getting and putting the field it is associated with. It's
+ * up to the callback to work the saved state correctly.
+ *
+ * @returns VBox status code.
+ *
+ * @param pSSM The saved state handle.
+ * @param pField The field that is being processed.
+ * @param pvStruct Pointer to the structure.
+ * @param fFlags SSMSTRUCT_FLAGS_XXX.
+ * @param fGetOrPut True if getting, false if putting.
+ * @param pvUser The user argument specified to SSMR3GetStructEx or
+ * SSMR3PutStructEx.
+ */
+typedef DECLCALLBACKTYPE(int, FNSSMFIELDGETPUT,(PSSMHANDLE pSSM, const struct SSMFIELD *pField, void *pvStruct,
+ uint32_t fFlags, bool fGetOrPut, void *pvUser));
+/** Pointer to a SSMFIELD Get/Put callback. */
+typedef FNSSMFIELDGETPUT *PFNSSMFIELDGETPUT;
+
+/**
+ * SSM field transformers.
+ *
+ * These are stored in the SSMFIELD::pfnGetPutOrTransformer and must therefore
+ * have values outside the valid pointer range.
+ */
+typedef enum SSMFIELDTRANS
+{
+ /** Invalid. */
+ SSMFIELDTRANS_INVALID = 0,
+ /** No transformation. */
+ SSMFIELDTRANS_NO_TRANSFORMATION,
+ /** Guest context (GC) physical address. */
+ SSMFIELDTRANS_GCPHYS,
+ /** Guest context (GC) virtual address. */
+ SSMFIELDTRANS_GCPTR,
+ /** Raw-mode context (RC) virtual address. */
+ SSMFIELDTRANS_RCPTR,
+ /** Array of raw-mode context (RC) virtual addresses. */
+ SSMFIELDTRANS_RCPTR_ARRAY,
+ /** Host context (HC) virtual address used as a NULL indicator. See
+ * SSMFIELD_ENTRY_HCPTR_NI. */
+ SSMFIELDTRANS_HCPTR_NI,
+ /** Array of SSMFIELDTRANS_HCPTR_NI. */
+ SSMFIELDTRANS_HCPTR_NI_ARRAY,
+ /** Host context (HC) virtual address used to hold a unsigned 32-bit value. */
+ SSMFIELDTRANS_HCPTR_HACK_U32,
+ /** Load a 32-bit unsigned filed from the state and zero extend it into a 64-bit
+ * structure member. */
+ SSMFIELDTRANS_U32_ZX_U64,
+
+ /** Ignorable field. See SSMFIELD_ENTRY_IGNORE. */
+ SSMFIELDTRANS_IGNORE,
+ /** Ignorable guest context (GC) physical address. */
+ SSMFIELDTRANS_IGN_GCPHYS,
+ /** Ignorable guest context (GC) virtual address. */
+ SSMFIELDTRANS_IGN_GCPTR,
+ /** Ignorable raw-mode context (RC) virtual address. */
+ SSMFIELDTRANS_IGN_RCPTR,
+ /** Ignorable host context (HC) virtual address. */
+ SSMFIELDTRANS_IGN_HCPTR,
+
+ /** Old field.
+ * Save as zeros and skip on restore (nowhere to restore it any longer). */
+ SSMFIELDTRANS_OLD,
+ /** Old guest context (GC) physical address. */
+ SSMFIELDTRANS_OLD_GCPHYS,
+ /** Old guest context (GC) virtual address. */
+ SSMFIELDTRANS_OLD_GCPTR,
+ /** Old raw-mode context (RC) virtual address. */
+ SSMFIELDTRANS_OLD_RCPTR,
+ /** Old host context (HC) virtual address. */
+ SSMFIELDTRANS_OLD_HCPTR,
+ /** Old host context specific padding.
+ * The lower word is the size of 32-bit hosts, the upper for 64-bit hosts. */
+ SSMFIELDTRANS_OLD_PAD_HC,
+ /** Old padding specific to the 32-bit Microsoft C Compiler. */
+ SSMFIELDTRANS_OLD_PAD_MSC32,
+
+ /** Padding that differs between 32-bit and 64-bit hosts.
+ * The first byte of SSMFIELD::cb contains the size for 32-bit hosts.
+ * The second byte of SSMFIELD::cb contains the size for 64-bit hosts.
+ * The upper word of SSMFIELD::cb contains the actual field size.
+ */
+ SSMFIELDTRANS_PAD_HC,
+ /** Padding for 32-bit hosts only.
+ * SSMFIELD::cb has the same format as for SSMFIELDTRANS_PAD_HC. */
+ SSMFIELDTRANS_PAD_HC32,
+ /** Padding for 64-bit hosts only.
+ * SSMFIELD::cb has the same format as for SSMFIELDTRANS_PAD_HC. */
+ SSMFIELDTRANS_PAD_HC64,
+ /** Automatic compiler padding that may differ between 32-bit and
+ * 64-bit hosts. SSMFIELD::cb has the same format as for
+ * SSMFIELDTRANS_PAD_HC. */
+ SSMFIELDTRANS_PAD_HC_AUTO,
+ /** Automatic compiler padding specific to the 32-bit Microsoft C
+ * compiler.
+ * SSMFIELD::cb has the same format as for SSMFIELDTRANS_PAD_HC. */
+ SSMFIELDTRANS_PAD_MSC32_AUTO
+} SSMFIELDTRANS;
+
+/** Tests if it's a padding field with the special SSMFIELD::cb format.
+ * @returns true / false.
+ * @param pfn The SSMFIELD::pfnGetPutOrTransformer value.
+ */
+#define SSMFIELDTRANS_IS_PADDING(pfn) \
+ ( (uintptr_t)(pfn) >= SSMFIELDTRANS_PAD_HC && (uintptr_t)(pfn) <= SSMFIELDTRANS_PAD_MSC32_AUTO )
+
+/** Tests if it's an entry for an old field.
+ *
+ * @returns true / false.
+ * @param pfn The SSMFIELD::pfnGetPutOrTransformer value.
+ */
+#define SSMFIELDTRANS_IS_OLD(pfn) \
+ ( (uintptr_t)(pfn) >= SSMFIELDTRANS_OLD && (uintptr_t)(pfn) <= SSMFIELDTRANS_OLD_PAD_MSC32 )
+
+/**
+ * A structure field description.
+ */
+typedef struct SSMFIELD
+{
+ /** Getter and putter callback or transformer index. */
+ PFNSSMFIELDGETPUT pfnGetPutOrTransformer;
+ /** Field offset into the structure. */
+ uint32_t off;
+ /** The size of the field. */
+ uint32_t cb;
+ /** This field was first saved by this unit version number. */
+ uint32_t uFirstVer;
+ /** Field name. */
+ const char *pszName;
+} SSMFIELD;
+
+/** Emit a SSMFIELD array entry.
+ * @internal */
+#define SSMFIELD_ENTRY_INT(Name, off, cb, enmTransformer, uFirstVer) \
+ { (PFNSSMFIELDGETPUT)(uintptr_t)(enmTransformer), (uint32_t)(off), (uint32_t)(cb), (uFirstVer), Name }
+/** Emit a SSMFIELD array entry.
+ * @internal */
+#define SSMFIELD_ENTRY_TF_INT(Type, Field, enmTransformer, uFirstVer) \
+ SSMFIELD_ENTRY_INT(#Type "::" #Field, RT_UOFFSETOF(Type, Field), RT_SIZEOFMEMB(Type, Field), enmTransformer, uFirstVer)
+/** Emit a SSMFIELD array entry for an old field.
+ * @internal */
+#define SSMFIELD_ENTRY_OLD_INT(Field, cb, enmTransformer) \
+ SSMFIELD_ENTRY_INT("old::" #Field, UINT32_MAX / 2, (cb), enmTransformer, 0)
+/** Emit a SSMFIELD array entry for an alignment padding.
+ * @internal */
+#define SSMFIELD_ENTRY_PAD_INT(Type, Field, cb32, cb64, enmTransformer) \
+ SSMFIELD_ENTRY_INT(#Type "::" #Field, RT_UOFFSETOF(Type, Field), \
+ (RT_SIZEOFMEMB(Type, Field) << 16) | (cb32) | ((cb64) << 8), enmTransformer, 0)
+/** Emit a SSMFIELD array entry for an alignment padding.
+ * @internal */
+#define SSMFIELD_ENTRY_PAD_OTHER_INT(Type, Field, cb32, cb64, enmTransformer) \
+ SSMFIELD_ENTRY_INT(#Type "::" #Field, UINT32_MAX / 2, 0 | (cb32) | ((cb64) << 8), enmTransformer, 0)
+
+/** Emit a SSMFIELD array entry. */
+#define SSMFIELD_ENTRY(Type, Field) SSMFIELD_ENTRY_TF_INT(Type, Field, SSMFIELDTRANS_NO_TRANSFORMATION, 0)
+/** Emit a SSMFIELD array entry with first version. */
+#define SSMFIELD_ENTRY_VER(Type, Field, uFirstVer) SSMFIELD_ENTRY_TF_INT(Type, Field, SSMFIELDTRANS_NO_TRANSFORMATION, uFirstVer)
+/** Emit a SSMFIELD array entry for a custom made field. This is intended
+ * for working around bitfields in old structures. */
+#define SSMFIELD_ENTRY_CUSTOM(Field, off, cb) SSMFIELD_ENTRY_INT("custom::" #Field, off, cb, \
+ SSMFIELDTRANS_NO_TRANSFORMATION, 0)
+/** Emit a SSMFIELD array entry for a RTGCPHYS type. */
+#define SSMFIELD_ENTRY_GCPHYS(Type, Field) SSMFIELD_ENTRY_TF_INT(Type, Field, SSMFIELDTRANS_GCPHYS, 0)
+/** Emit a SSMFIELD array entry for a RTGCPTR type. */
+#define SSMFIELD_ENTRY_GCPTR(Type, Field) SSMFIELD_ENTRY_TF_INT(Type, Field, SSMFIELDTRANS_GCPTR, 0)
+/** Emit a SSMFIELD array entry for a raw-mode context pointer. */
+#define SSMFIELD_ENTRY_RCPTR(Type, Field) SSMFIELD_ENTRY_TF_INT(Type, Field, SSMFIELDTRANS_RCPTR, 0)
+/** Emit a SSMFIELD array entry for a raw-mode context pointer. */
+#define SSMFIELD_ENTRY_RCPTR_ARRAY(Type, Field) SSMFIELD_ENTRY_TF_INT(Type, Field, SSMFIELDTRANS_RCPTR_ARRAY, 0)
+/** Emit a SSMFIELD array entry for a ring-0 or ring-3 pointer type that is only
+ * of interest as a NULL indicator.
+ *
+ * This is always restored as a 0 (NULL) or 1 value. When
+ * SSMSTRUCT_FLAGS_DONT_IGNORE is set, the pointer will be saved in its
+ * entirety, when clear it will be saved as a boolean. */
+#define SSMFIELD_ENTRY_HCPTR_NI(Type, Field) SSMFIELD_ENTRY_TF_INT(Type, Field, SSMFIELDTRANS_HCPTR_NI, 0)
+/** Same as SSMFIELD_ENTRY_HCPTR_NI, except it's an array of the buggers. */
+#define SSMFIELD_ENTRY_HCPTR_NI_ARRAY(Type, Field) SSMFIELD_ENTRY_TF_INT(Type, Field, SSMFIELDTRANS_HCPTR_NI_ARRAY, 0)
+/** Emit a SSMFIELD array entry for a ring-0 or ring-3 pointer type that has
+ * been hacked such that it will never exceed 32-bit. No sign extending. */
+#define SSMFIELD_ENTRY_HCPTR_HACK_U32(Type, Field) SSMFIELD_ENTRY_TF_INT(Type, Field, SSMFIELDTRANS_HCPTR_HACK_U32, 0)
+/** Emit a SSMFIELD array entry for loading a 32-bit field into a 64-bit
+ * structure member, zero extending the value. */
+#define SSMFIELD_ENTRY_U32_ZX_U64(Type, Field) SSMFIELD_ENTRY_TF_INT(Type, Field, SSMFIELDTRANS_U32_ZX_U64, 0)
+
+/** Emit a SSMFIELD array entry for a field that can be ignored.
+ * It is stored as zeros if SSMSTRUCT_FLAGS_DONT_IGNORE is specified to
+ * SSMR3PutStructEx. The member is never touched upon restore. */
+#define SSMFIELD_ENTRY_IGNORE(Type, Field) SSMFIELD_ENTRY_TF_INT(Type, Field, SSMFIELDTRANS_IGNORE, 0)
+/** Emit a SSMFIELD array entry for an ignorable RTGCPHYS type. */
+#define SSMFIELD_ENTRY_IGN_GCPHYS(Type, Field) SSMFIELD_ENTRY_TF_INT(Type, Field, SSMFIELDTRANS_IGN_GCPHYS, 0)
+/** Emit a SSMFIELD array entry for an ignorable RTGCPHYS type. */
+#define SSMFIELD_ENTRY_IGN_GCPTR(Type, Field) SSMFIELD_ENTRY_TF_INT(Type, Field, SSMFIELDTRANS_IGN_GCPTR, 0)
+/** Emit a SSMFIELD array entry for an ignorable raw-mode context pointer. */
+#define SSMFIELD_ENTRY_IGN_RCPTR(Type, Field) SSMFIELD_ENTRY_TF_INT(Type, Field, SSMFIELDTRANS_IGN_RCPTR, 0)
+/** Emit a SSMFIELD array entry for an ignorable ring-3 or/and ring-0 pointer. */
+#define SSMFIELD_ENTRY_IGN_HCPTR(Type, Field) SSMFIELD_ENTRY_TF_INT(Type, Field, SSMFIELDTRANS_IGN_HCPTR, 0)
+
+/** Emit a SSMFIELD array entry for an old field that should be ignored now.
+ * It is stored as zeros and skipped on load. */
+#define SSMFIELD_ENTRY_OLD(Field, cb) SSMFIELD_ENTRY_OLD_INT(Field, cb, SSMFIELDTRANS_OLD)
+/** Same as SSMFIELD_ENTRY_IGN_GCPHYS, except there is no structure field. */
+#define SSMFIELD_ENTRY_OLD_GCPHYS(Field) SSMFIELD_ENTRY_OLD_INT(Field, sizeof(RTGCPHYS), SSMFIELDTRANS_OLD_GCPHYS)
+/** Same as SSMFIELD_ENTRY_IGN_GCPTR, except there is no structure field. */
+#define SSMFIELD_ENTRY_OLD_GCPTR(Field) SSMFIELD_ENTRY_OLD_INT(Field, sizeof(RTGCPTR), SSMFIELDTRANS_OLD_GCPTR)
+/** Same as SSMFIELD_ENTRY_IGN_RCPTR, except there is no structure field. */
+#define SSMFIELD_ENTRY_OLD_RCPTR(Field) SSMFIELD_ENTRY_OLD_INT(Field, sizeof(RTRCPTR), SSMFIELDTRANS_OLD_RCPTR)
+/** Same as SSMFIELD_ENTRY_IGN_HCPTR, except there is no structure field. */
+#define SSMFIELD_ENTRY_OLD_HCPTR(Field) SSMFIELD_ENTRY_OLD_INT(Field, sizeof(RTHCPTR), SSMFIELDTRANS_OLD_HCPTR)
+/** Same as SSMFIELD_ENTRY_PAD_HC, except there is no structure field. */
+#define SSMFIELD_ENTRY_OLD_PAD_HC(Field, cb32, cb64) \
+ SSMFIELD_ENTRY_OLD_INT(Field, RT_MAKE_U32((cb32), (cb64)), SSMFIELDTRANS_OLD_PAD_HC)
+/** Same as SSMFIELD_ENTRY_PAD_HC64, except there is no structure field. */
+#define SSMFIELD_ENTRY_OLD_PAD_HC64(Field, cb) SSMFIELD_ENTRY_OLD_PAD_HC(Field, 0, cb)
+/** Same as SSMFIELD_ENTRY_PAD_HC32, except there is no structure field. */
+#define SSMFIELD_ENTRY_OLD_PAD_HC32(Field, cb) SSMFIELD_ENTRY_OLD_PAD_HC(Field, cb, 0)
+/** Same as SSMFIELD_ENTRY_PAD_HC, except there is no structure field. */
+#define SSMFIELD_ENTRY_OLD_PAD_MSC32(Field, cb) SSMFIELD_ENTRY_OLD_INT(Field, cb, SSMFIELDTRANS_OLD_PAD_MSC32)
+
+/** Emit a SSMFIELD array entry for a padding that differs in size between
+ * 64-bit and 32-bit hosts. */
+#define SSMFIELD_ENTRY_PAD_HC(Type, Field, cb32, cb64) SSMFIELD_ENTRY_PAD_INT( Type, Field, cb32, cb64, SSMFIELDTRANS_PAD_HC)
+/** Emit a SSMFIELD array entry for a padding that is exclusive to 64-bit hosts. */
+#if HC_ARCH_BITS == 64
+# define SSMFIELD_ENTRY_PAD_HC64(Type, Field, cb) SSMFIELD_ENTRY_PAD_INT( Type, Field, 0, cb, SSMFIELDTRANS_PAD_HC64)
+#else
+# define SSMFIELD_ENTRY_PAD_HC64(Type, Field, cb) SSMFIELD_ENTRY_PAD_OTHER_INT(Type, Field, 0, cb, SSMFIELDTRANS_PAD_HC64)
+#endif
+/** Emit a SSMFIELD array entry for a 32-bit padding for on 64-bits hosts. */
+#if HC_ARCH_BITS == 32
+# define SSMFIELD_ENTRY_PAD_HC32(Type, Field, cb) SSMFIELD_ENTRY_PAD_INT( Type, Field, cb, 0, SSMFIELDTRANS_PAD_HC32)
+#else
+# define SSMFIELD_ENTRY_PAD_HC32(Type, Field, cb) SSMFIELD_ENTRY_PAD_OTHER_INT(Type, Field, cb, 0, SSMFIELDTRANS_PAD_HC32)
+#endif
+/** Emit a SSMFIELD array entry for an automatic compiler padding that may
+ * differ in size between 64-bit and 32-bit hosts. */
+#if HC_ARCH_BITS == 64
+# define SSMFIELD_ENTRY_PAD_HC_AUTO(cb32, cb64) \
+ { \
+ (PFNSSMFIELDGETPUT)(uintptr_t)(SSMFIELDTRANS_PAD_HC_AUTO), \
+ UINT32_MAX / 2, (cb64 << 16) | (cb32) | ((cb64) << 8), 0, "<compiler-padding>" \
+ }
+#else
+# define SSMFIELD_ENTRY_PAD_HC_AUTO(cb32, cb64) \
+ { \
+ (PFNSSMFIELDGETPUT)(uintptr_t)(SSMFIELDTRANS_PAD_HC_AUTO), \
+ UINT32_MAX / 2, (cb32 << 16) | (cb32) | ((cb64) << 8), 0, "<compiler-padding>" \
+ }
+#endif
+/** Emit a SSMFIELD array entry for an automatic compiler padding that is unique
+ * to the 32-bit microsoft compiler. This is usually used together with
+ * SSMFIELD_ENTRY_PAD_HC*. */
+#if HC_ARCH_BITS == 32 && defined(_MSC_VER)
+# define SSMFIELD_ENTRY_PAD_MSC32_AUTO(cb) \
+ { \
+ (PFNSSMFIELDGETPUT)(uintptr_t)(SSMFIELDTRANS_PAD_MSC32_AUTO), \
+ UINT32_MAX / 2, ((cb) << 16) | (cb), 0, "<msc32-padding>" \
+ }
+#else
+# define SSMFIELD_ENTRY_PAD_MSC32_AUTO(cb) \
+ { \
+ (PFNSSMFIELDGETPUT)(uintptr_t)(SSMFIELDTRANS_PAD_MSC32_AUTO), \
+ UINT32_MAX / 2, (cb), 0, "<msc32-padding>" \
+ }
+#endif
+
+/** Emit a SSMFIELD array entry for a field with a custom callback. */
+#define SSMFIELD_ENTRY_CALLBACK(Type, Field, pfnGetPut) \
+ { (pfnGetPut), RT_UOFFSETOF(Type, Field), RT_SIZEOFMEMB(Type, Field), 0, #Type "::" #Field }
+/** Emit the terminating entry of a SSMFIELD array. */
+#define SSMFIELD_ENTRY_TERM() \
+ { (PFNSSMFIELDGETPUT)(uintptr_t)SSMFIELDTRANS_INVALID, UINT32_MAX, UINT32_MAX, UINT32_MAX, NULL }
+
+
+/** @name SSMR3GetStructEx and SSMR3PutStructEx flags.
+ * @{ */
+/** The field descriptors must exactly cover the entire struct, A to Z. */
+#define SSMSTRUCT_FLAGS_FULL_STRUCT RT_BIT_32(0)
+/** No start and end markers, just the raw bits. */
+#define SSMSTRUCT_FLAGS_NO_MARKERS RT_BIT_32(1)
+/** Do not ignore any ignorable fields. */
+#define SSMSTRUCT_FLAGS_DONT_IGNORE RT_BIT_32(2)
+/** Saved using SSMR3PutMem, don't be too strict. */
+#define SSMSTRUCT_FLAGS_SAVED_AS_MEM RT_BIT_32(3)
+/** No introductory structure marker. Use when splitting up structures. */
+#define SSMSTRUCT_FLAGS_NO_LEAD_MARKER RT_BIT_32(4)
+/** No trailing structure marker. Use when splitting up structures. */
+#define SSMSTRUCT_FLAGS_NO_TAIL_MARKER RT_BIT_32(5)
+
+/** Band-aid for old SSMR3PutMem/SSMR3GetMem of structurs with host pointers.
+ * @remarks This type is normally only used up to the first changes to the
+ * structures take place in order to make sure the conversion from
+ * SSMR3PutMem to field descriptors went smoothly. Replace with
+ * SSMSTRUCT_FLAGS_MEM_BAND_AID_RELAXED when changing the structure. */
+#define SSMSTRUCT_FLAGS_MEM_BAND_AID ( SSMSTRUCT_FLAGS_DONT_IGNORE | SSMSTRUCT_FLAGS_FULL_STRUCT \
+ | SSMSTRUCT_FLAGS_NO_MARKERS | SSMSTRUCT_FLAGS_SAVED_AS_MEM)
+/** Band-aid for old SSMR3PutMem/SSMR3GetMem of structurs with host
+ * pointers, with relaxed checks. */
+#define SSMSTRUCT_FLAGS_MEM_BAND_AID_RELAXED ( SSMSTRUCT_FLAGS_DONT_IGNORE \
+ | SSMSTRUCT_FLAGS_NO_MARKERS | SSMSTRUCT_FLAGS_SAVED_AS_MEM)
+/** Mask of the valid bits. */
+#define SSMSTRUCT_FLAGS_VALID_MASK UINT32_C(0x0000003f)
+/** @} */
+
+
+/** The PDM Device callback variants.
+ * @{
+ */
+
+/**
+ * Prepare state live save operation.
+ *
+ * @returns VBox status code.
+ * @param pDevIns Device instance of the device which registered the data unit.
+ * @param pSSM SSM operation handle.
+ * @remarks The caller enters the device critical section prior to the call.
+ * @thread Any.
+ */
+typedef DECLCALLBACKTYPE(int, FNSSMDEVLIVEPREP,(PPDMDEVINS pDevIns, PSSMHANDLE pSSM));
+/** Pointer to a FNSSMDEVLIVEPREP() function. */
+typedef FNSSMDEVLIVEPREP *PFNSSMDEVLIVEPREP;
+
+/**
+ * Execute state live save operation.
+ *
+ * This will be called repeatedly until all units vote that the live phase has
+ * been concluded.
+ *
+ * @returns VBox status code.
+ * @param pDevIns Device instance of the device which registered the data unit.
+ * @param pSSM SSM operation handle.
+ * @param uPass The pass.
+ * @remarks The caller enters the device critical section prior to the call.
+ * @thread Any.
+ */
+typedef DECLCALLBACKTYPE(int, FNSSMDEVLIVEEXEC,(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uPass));
+/** Pointer to a FNSSMDEVLIVEEXEC() function. */
+typedef FNSSMDEVLIVEEXEC *PFNSSMDEVLIVEEXEC;
+
+/**
+ * Vote on whether the live part of the saving has been concluded.
+ *
+ * The vote stops once a unit has vetoed the decision, so don't rely upon this
+ * being called every time.
+ *
+ * @returns VBox status code.
+ * @retval VINF_SUCCESS if done.
+ * @retval VINF_SSM_VOTE_FOR_ANOTHER_PASS if another pass is needed.
+ * @retval VINF_SSM_VOTE_DONE_DONT_CALL_AGAIN if the live saving of the unit is
+ * done and there is not need calling it again before the final pass.
+ * @retval VERR_SSM_VOTE_FOR_GIVING_UP if its time to give up.
+ *
+ * @param pDevIns Device instance of the device which registered the data unit.
+ * @param pSSM SSM operation handle.
+ * @param uPass The data pass.
+ * @remarks The caller enters the device critical section prior to the call.
+ * @thread Any.
+ */
+typedef DECLCALLBACKTYPE(int, FNSSMDEVLIVEVOTE,(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uPass));
+/** Pointer to a FNSSMDEVLIVEVOTE() function. */
+typedef FNSSMDEVLIVEVOTE *PFNSSMDEVLIVEVOTE;
+
+/**
+ * Prepare state save operation.
+ *
+ * @returns VBox status code.
+ * @param pDevIns Device instance of the device which registered the data unit.
+ * @param pSSM SSM operation handle.
+ * @remarks The caller enters the device critical section prior to the call.
+ */
+typedef DECLCALLBACKTYPE(int, FNSSMDEVSAVEPREP,(PPDMDEVINS pDevIns, PSSMHANDLE pSSM));
+/** Pointer to a FNSSMDEVSAVEPREP() function. */
+typedef FNSSMDEVSAVEPREP *PFNSSMDEVSAVEPREP;
+
+/**
+ * Execute state save operation.
+ *
+ * @returns VBox status code.
+ * @param pDevIns Device instance of the device which registered the data unit.
+ * @param pSSM SSM operation handle.
+ * @remarks The caller enters the device critical section prior to the call.
+ */
+typedef DECLCALLBACKTYPE(int, FNSSMDEVSAVEEXEC,(PPDMDEVINS pDevIns, PSSMHANDLE pSSM));
+/** Pointer to a FNSSMDEVSAVEEXEC() function. */
+typedef FNSSMDEVSAVEEXEC *PFNSSMDEVSAVEEXEC;
+
+/**
+ * Done state save operation.
+ *
+ * @returns VBox status code.
+ * @param pDevIns Device instance of the device which registered the data unit.
+ * @param pSSM SSM operation handle.
+ * @remarks The caller enters the device critical section prior to the call.
+ */
+typedef DECLCALLBACKTYPE(int, FNSSMDEVSAVEDONE,(PPDMDEVINS pDevIns, PSSMHANDLE pSSM));
+/** Pointer to a FNSSMDEVSAVEDONE() function. */
+typedef FNSSMDEVSAVEDONE *PFNSSMDEVSAVEDONE;
+
+/**
+ * Prepare state load operation.
+ *
+ * @returns VBox status code.
+ * @param pDevIns Device instance of the device which registered the data unit.
+ * @param pSSM SSM operation handle.
+ * @remarks The caller enters the device critical section prior to the call.
+ */
+typedef DECLCALLBACKTYPE(int, FNSSMDEVLOADPREP,(PPDMDEVINS pDevIns, PSSMHANDLE pSSM));
+/** Pointer to a FNSSMDEVLOADPREP() function. */
+typedef FNSSMDEVLOADPREP *PFNSSMDEVLOADPREP;
+
+/**
+ * Execute state load operation.
+ *
+ * @returns VBox status code.
+ * @param pDevIns Device instance of the device which registered the data unit.
+ * @param pSSM SSM operation handle.
+ * @param uVersion Data layout version.
+ * @param uPass The pass. This is always SSM_PASS_FINAL for units
+ * that doesn't specify a pfnSaveLive callback.
+ * @remarks The caller enters the device critical section prior to the call.
+ */
+typedef DECLCALLBACKTYPE(int, FNSSMDEVLOADEXEC,(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass));
+/** Pointer to a FNSSMDEVLOADEXEC() function. */
+typedef FNSSMDEVLOADEXEC *PFNSSMDEVLOADEXEC;
+
+/**
+ * Done state load operation.
+ *
+ * @returns VBox load code.
+ * @param pDevIns Device instance of the device which registered the data unit.
+ * @param pSSM SSM operation handle.
+ * @remarks The caller enters the device critical section prior to the call.
+ */
+typedef DECLCALLBACKTYPE(int, FNSSMDEVLOADDONE,(PPDMDEVINS pDevIns, PSSMHANDLE pSSM));
+/** Pointer to a FNSSMDEVLOADDONE() function. */
+typedef FNSSMDEVLOADDONE *PFNSSMDEVLOADDONE;
+
+/** @} */
+
+
+/** The PDM USB device callback variants.
+ * @{
+ */
+
+/**
+ * Prepare state live save operation.
+ *
+ * @returns VBox status code.
+ * @param pUsbIns The USB device instance of the USB device which
+ * registered the data unit.
+ * @param pSSM SSM operation handle.
+ * @thread Any.
+ */
+typedef DECLCALLBACKTYPE(int, FNSSMUSBLIVEPREP,(PPDMUSBINS pUsbIns, PSSMHANDLE pSSM));
+/** Pointer to a FNSSMUSBLIVEPREP() function. */
+typedef FNSSMUSBLIVEPREP *PFNSSMUSBLIVEPREP;
+
+/**
+ * Execute state live save operation.
+ *
+ * This will be called repeatedly until all units vote that the live phase has
+ * been concluded.
+ *
+ * @returns VBox status code.
+ * @param pUsbIns The USB device instance of the USB device which
+ * registered the data unit.
+ * @param pSSM SSM operation handle.
+ * @param uPass The pass.
+ * @thread Any.
+ */
+typedef DECLCALLBACKTYPE(int, FNSSMUSBLIVEEXEC,(PPDMUSBINS pUsbIns, PSSMHANDLE pSSM, uint32_t uPass));
+/** Pointer to a FNSSMUSBLIVEEXEC() function. */
+typedef FNSSMUSBLIVEEXEC *PFNSSMUSBLIVEEXEC;
+
+/**
+ * Vote on whether the live part of the saving has been concluded.
+ *
+ * The vote stops once a unit has vetoed the decision, so don't rely upon this
+ * being called every time.
+ *
+ * @returns VBox status code.
+ * @retval VINF_SUCCESS if done.
+ * @retval VINF_SSM_VOTE_FOR_ANOTHER_PASS if another pass is needed.
+ * @retval VINF_SSM_VOTE_DONE_DONT_CALL_AGAIN if the live saving of the unit is
+ * done and there is not need calling it again before the final pass.
+ * @retval VERR_SSM_VOTE_FOR_GIVING_UP if its time to give up.
+ *
+ * @param pUsbIns The USB device instance of the USB device which
+ * registered the data unit.
+ * @param pSSM SSM operation handle.
+ * @param uPass The data pass.
+ * @thread Any.
+ */
+typedef DECLCALLBACKTYPE(int, FNSSMUSBLIVEVOTE,(PPDMUSBINS pUsbIns, PSSMHANDLE pSSM, uint32_t uPass));
+/** Pointer to a FNSSMUSBLIVEVOTE() function. */
+typedef FNSSMUSBLIVEVOTE *PFNSSMUSBLIVEVOTE;
+
+/**
+ * Prepare state save operation.
+ *
+ * @returns VBox status code.
+ * @param pUsbIns The USB device instance of the USB device which
+ * registered the data unit.
+ * @param pSSM SSM operation handle.
+ */
+typedef DECLCALLBACKTYPE(int, FNSSMUSBSAVEPREP,(PPDMUSBINS pUsbIns, PSSMHANDLE pSSM));
+/** Pointer to a FNSSMUSBSAVEPREP() function. */
+typedef FNSSMUSBSAVEPREP *PFNSSMUSBSAVEPREP;
+
+/**
+ * Execute state save operation.
+ *
+ * @returns VBox status code.
+ * @param pUsbIns The USB device instance of the USB device which
+ * registered the data unit.
+ * @param pSSM SSM operation handle.
+ */
+typedef DECLCALLBACKTYPE(int, FNSSMUSBSAVEEXEC,(PPDMUSBINS pUsbIns, PSSMHANDLE pSSM));
+/** Pointer to a FNSSMUSBSAVEEXEC() function. */
+typedef FNSSMUSBSAVEEXEC *PFNSSMUSBSAVEEXEC;
+
+/**
+ * Done state save operation.
+ *
+ * @returns VBox status code.
+ * @param pUsbIns The USB device instance of the USB device which
+ * registered the data unit.
+ * @param pSSM SSM operation handle.
+ */
+typedef DECLCALLBACKTYPE(int, FNSSMUSBSAVEDONE,(PPDMUSBINS pUsbIns, PSSMHANDLE pSSM));
+/** Pointer to a FNSSMUSBSAVEDONE() function. */
+typedef FNSSMUSBSAVEDONE *PFNSSMUSBSAVEDONE;
+
+/**
+ * Prepare state load operation.
+ *
+ * @returns VBox status code.
+ * @param pUsbIns The USB device instance of the USB device which
+ * registered the data unit.
+ * @param pSSM SSM operation handle.
+ */
+typedef DECLCALLBACKTYPE(int, FNSSMUSBLOADPREP,(PPDMUSBINS pUsbIns, PSSMHANDLE pSSM));
+/** Pointer to a FNSSMUSBLOADPREP() function. */
+typedef FNSSMUSBLOADPREP *PFNSSMUSBLOADPREP;
+
+/**
+ * Execute state load operation.
+ *
+ * @returns VBox status code.
+ * @param pUsbIns The USB device instance of the USB device which
+ * registered the data unit.
+ * @param pSSM SSM operation handle.
+ * @param uVersion Data layout version.
+ * @param uPass The pass. This is always SSM_PASS_FINAL for units
+ * that doesn't specify a pfnSaveLive callback.
+ */
+typedef DECLCALLBACKTYPE(int, FNSSMUSBLOADEXEC,(PPDMUSBINS pUsbIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass));
+/** Pointer to a FNSSMUSBLOADEXEC() function. */
+typedef FNSSMUSBLOADEXEC *PFNSSMUSBLOADEXEC;
+
+/**
+ * Done state load operation.
+ *
+ * @returns VBox load code.
+ * @param pUsbIns The USB device instance of the USB device which
+ * registered the data unit.
+ * @param pSSM SSM operation handle.
+ */
+typedef DECLCALLBACKTYPE(int, FNSSMUSBLOADDONE,(PPDMUSBINS pUsbIns, PSSMHANDLE pSSM));
+/** Pointer to a FNSSMUSBLOADDONE() function. */
+typedef FNSSMUSBLOADDONE *PFNSSMUSBLOADDONE;
+
+/** @} */
+
+
+/** The PDM Driver callback variants.
+ * @{
+ */
+
+/**
+ * Prepare state live save operation.
+ *
+ * @returns VBox status code.
+ * @param pDrvIns Driver instance of the driver which registered the
+ * data unit.
+ * @param pSSM SSM operation handle.
+ * @thread Any.
+ */
+typedef DECLCALLBACKTYPE(int, FNSSMDRVLIVEPREP,(PPDMDRVINS pDrvIns, PSSMHANDLE pSSM));
+/** Pointer to a FNSSMDRVLIVEPREP() function. */
+typedef FNSSMDRVLIVEPREP *PFNSSMDRVLIVEPREP;
+
+/**
+ * Execute state live save operation.
+ *
+ * This will be called repeatedly until all units vote that the live phase has
+ * been concluded.
+ *
+ * @returns VBox status code.
+ * @param pDrvIns Driver instance of the driver which registered the
+ * data unit.
+ * @param pSSM SSM operation handle.
+ * @param uPass The data pass.
+ * @thread Any.
+ */
+typedef DECLCALLBACKTYPE(int, FNSSMDRVLIVEEXEC,(PPDMDRVINS pDrvIns, PSSMHANDLE pSSM, uint32_t uPass));
+/** Pointer to a FNSSMDRVLIVEEXEC() function. */
+typedef FNSSMDRVLIVEEXEC *PFNSSMDRVLIVEEXEC;
+
+/**
+ * Vote on whether the live part of the saving has been concluded.
+ *
+ * The vote stops once a unit has vetoed the decision, so don't rely upon this
+ * being called every time.
+ *
+ * @returns VBox status code.
+ * @retval VINF_SUCCESS if done.
+ * @retval VINF_SSM_VOTE_FOR_ANOTHER_PASS if another pass is needed.
+ * @retval VINF_SSM_VOTE_DONE_DONT_CALL_AGAIN if the live saving of the unit is
+ * done and there is not need calling it again before the final pass.
+ * @retval VERR_SSM_VOTE_FOR_GIVING_UP if its time to give up.
+ *
+ * @param pDrvIns Driver instance of the driver which registered the
+ * data unit.
+ * @param pSSM SSM operation handle.
+ * @param uPass The data pass.
+ * @thread Any.
+ */
+typedef DECLCALLBACKTYPE(int, FNSSMDRVLIVEVOTE,(PPDMDRVINS pDrvIns, PSSMHANDLE pSSM, uint32_t uPass));
+/** Pointer to a FNSSMDRVLIVEVOTE() function. */
+typedef FNSSMDRVLIVEVOTE *PFNSSMDRVLIVEVOTE;
+
+
+/**
+ * Prepare state save operation.
+ *
+ * @returns VBox status code.
+ * @param pDrvIns Driver instance of the driver which registered the data unit.
+ * @param pSSM SSM operation handle.
+ */
+typedef DECLCALLBACKTYPE(int, FNSSMDRVSAVEPREP,(PPDMDRVINS pDrvIns, PSSMHANDLE pSSM));
+/** Pointer to a FNSSMDRVSAVEPREP() function. */
+typedef FNSSMDRVSAVEPREP *PFNSSMDRVSAVEPREP;
+
+/**
+ * Execute state save operation.
+ *
+ * @returns VBox status code.
+ * @param pDrvIns Driver instance of the driver which registered the data unit.
+ * @param pSSM SSM operation handle.
+ */
+typedef DECLCALLBACKTYPE(int, FNSSMDRVSAVEEXEC,(PPDMDRVINS pDrvIns, PSSMHANDLE pSSM));
+/** Pointer to a FNSSMDRVSAVEEXEC() function. */
+typedef FNSSMDRVSAVEEXEC *PFNSSMDRVSAVEEXEC;
+
+/**
+ * Done state save operation.
+ *
+ * @returns VBox status code.
+ * @param pDrvIns Driver instance of the driver which registered the data unit.
+ * @param pSSM SSM operation handle.
+ */
+typedef DECLCALLBACKTYPE(int, FNSSMDRVSAVEDONE,(PPDMDRVINS pDrvIns, PSSMHANDLE pSSM));
+/** Pointer to a FNSSMDRVSAVEDONE() function. */
+typedef FNSSMDRVSAVEDONE *PFNSSMDRVSAVEDONE;
+
+/**
+ * Prepare state load operation.
+ *
+ * @returns VBox status code.
+ * @param pDrvIns Driver instance of the driver which registered the data unit.
+ * @param pSSM SSM operation handle.
+ */
+typedef DECLCALLBACKTYPE(int, FNSSMDRVLOADPREP,(PPDMDRVINS pDrvIns, PSSMHANDLE pSSM));
+/** Pointer to a FNSSMDRVLOADPREP() function. */
+typedef FNSSMDRVLOADPREP *PFNSSMDRVLOADPREP;
+
+/**
+ * Execute state load operation.
+ *
+ * @returns VBox status code.
+ * @param pDrvIns Driver instance of the driver which registered the data unit.
+ * @param pSSM SSM operation handle.
+ * @param uVersion Data layout version.
+ * @param uPass The pass. This is always SSM_PASS_FINAL for units
+ * that doesn't specify a pfnSaveLive callback.
+ */
+typedef DECLCALLBACKTYPE(int, FNSSMDRVLOADEXEC,(PPDMDRVINS pDrvIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass));
+/** Pointer to a FNSSMDRVLOADEXEC() function. */
+typedef FNSSMDRVLOADEXEC *PFNSSMDRVLOADEXEC;
+
+/**
+ * Done state load operation.
+ *
+ * @returns VBox load code.
+ * @param pDrvIns Driver instance of the driver which registered the data unit.
+ * @param pSSM SSM operation handle.
+ */
+typedef DECLCALLBACKTYPE(int, FNSSMDRVLOADDONE,(PPDMDRVINS pDrvIns, PSSMHANDLE pSSM));
+/** Pointer to a FNSSMDRVLOADDONE() function. */
+typedef FNSSMDRVLOADDONE *PFNSSMDRVLOADDONE;
+
+/** @} */
+
+
+/** The internal callback variants.
+ * @{
+ */
+
+
+/**
+ * Prepare state live save operation.
+ *
+ * @returns VBox status code.
+ * @param pVM The cross context VM structure.
+ * @param pSSM SSM operation handle.
+ * @thread Any.
+ */
+typedef DECLCALLBACKTYPE(int, FNSSMINTLIVEPREP,(PVM pVM, PSSMHANDLE pSSM));
+/** Pointer to a FNSSMINTLIVEPREP() function. */
+typedef FNSSMINTLIVEPREP *PFNSSMINTLIVEPREP;
+
+/**
+ * Execute state live save operation.
+ *
+ * This will be called repeatedly until all units vote that the live phase has
+ * been concluded.
+ *
+ * @returns VBox status code.
+ * @param pVM The cross context VM structure.
+ * @param pSSM SSM operation handle.
+ * @param uPass The data pass.
+ * @thread Any.
+ */
+typedef DECLCALLBACKTYPE(int, FNSSMINTLIVEEXEC,(PVM pVM, PSSMHANDLE pSSM, uint32_t uPass));
+/** Pointer to a FNSSMINTLIVEEXEC() function. */
+typedef FNSSMINTLIVEEXEC *PFNSSMINTLIVEEXEC;
+
+/**
+ * Vote on whether the live part of the saving has been concluded.
+ *
+ * The vote stops once a unit has vetoed the decision, so don't rely upon this
+ * being called every time.
+ *
+ * @returns VBox status code.
+ * @retval VINF_SUCCESS if done.
+ * @retval VINF_SSM_VOTE_FOR_ANOTHER_PASS if another pass is needed.
+ * @retval VINF_SSM_VOTE_DONE_DONT_CALL_AGAIN if the live saving of the unit is
+ * done and there is not need calling it again before the final pass.
+ * @retval VERR_SSM_VOTE_FOR_GIVING_UP if its time to give up.
+ *
+ * @param pVM The cross context VM structure.
+ * @param pSSM SSM operation handle.
+ * @param uPass The data pass.
+ * @thread Any.
+ */
+typedef DECLCALLBACKTYPE(int, FNSSMINTLIVEVOTE,(PVM pVM, PSSMHANDLE pSSM, uint32_t uPass));
+/** Pointer to a FNSSMINTLIVEVOTE() function. */
+typedef FNSSMINTLIVEVOTE *PFNSSMINTLIVEVOTE;
+
+/**
+ * Prepare state save operation.
+ *
+ * @returns VBox status code.
+ * @param pVM The cross context VM structure.
+ * @param pSSM SSM operation handle.
+ */
+typedef DECLCALLBACKTYPE(int, FNSSMINTSAVEPREP,(PVM pVM, PSSMHANDLE pSSM));
+/** Pointer to a FNSSMINTSAVEPREP() function. */
+typedef FNSSMINTSAVEPREP *PFNSSMINTSAVEPREP;
+
+/**
+ * Execute state save operation.
+ *
+ * @returns VBox status code.
+ * @param pVM The cross context VM structure.
+ * @param pSSM SSM operation handle.
+ */
+typedef DECLCALLBACKTYPE(int, FNSSMINTSAVEEXEC,(PVM pVM, PSSMHANDLE pSSM));
+/** Pointer to a FNSSMINTSAVEEXEC() function. */
+typedef FNSSMINTSAVEEXEC *PFNSSMINTSAVEEXEC;
+
+/**
+ * Done state save operation.
+ *
+ * @returns VBox status code.
+ * @param pVM The cross context VM structure.
+ * @param pSSM SSM operation handle.
+ */
+typedef DECLCALLBACKTYPE(int, FNSSMINTSAVEDONE,(PVM pVM, PSSMHANDLE pSSM));
+/** Pointer to a FNSSMINTSAVEDONE() function. */
+typedef FNSSMINTSAVEDONE *PFNSSMINTSAVEDONE;
+
+/**
+ * Prepare state load operation.
+ *
+ * @returns VBox status code.
+ * @param pVM The cross context VM structure.
+ * @param pSSM SSM operation handle.
+ */
+typedef DECLCALLBACKTYPE(int, FNSSMINTLOADPREP,(PVM pVM, PSSMHANDLE pSSM));
+/** Pointer to a FNSSMINTLOADPREP() function. */
+typedef FNSSMINTLOADPREP *PFNSSMINTLOADPREP;
+
+/**
+ * Execute state load operation.
+ *
+ * @returns VBox status code.
+ * @param pVM The cross context VM structure.
+ * @param pSSM SSM operation handle.
+ * @param uVersion Data layout version.
+ * @param uPass The pass. This is always SSM_PASS_FINAL for units
+ * that doesn't specify a pfnSaveLive callback.
+ */
+typedef DECLCALLBACKTYPE(int, FNSSMINTLOADEXEC,(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass));
+/** Pointer to a FNSSMINTLOADEXEC() function. */
+typedef FNSSMINTLOADEXEC *PFNSSMINTLOADEXEC;
+
+/**
+ * Done state load operation.
+ *
+ * @returns VBox load code.
+ * @param pVM The cross context VM structure.
+ * @param pSSM SSM operation handle.
+ */
+typedef DECLCALLBACKTYPE(int, FNSSMINTLOADDONE,(PVM pVM, PSSMHANDLE pSSM));
+/** Pointer to a FNSSMINTLOADDONE() function. */
+typedef FNSSMINTLOADDONE *PFNSSMINTLOADDONE;
+
+/** @} */
+
+
+/** The External callback variants.
+ * @{
+ */
+
+/**
+ * Prepare state live save operation.
+ *
+ * @returns VBox status code.
+ * @param pSSM SSM operation handle.
+ * @param pVMM The VMM ring-3 vtable.
+ * @param pvUser User argument.
+ * @thread Any.
+ */
+typedef DECLCALLBACKTYPE(int, FNSSMEXTLIVEPREP,(PSSMHANDLE pSSM, PCVMMR3VTABLE pVMM, void *pvUser));
+/** Pointer to a FNSSMEXTLIVEPREP() function. */
+typedef FNSSMEXTLIVEPREP *PFNSSMEXTLIVEPREP;
+
+/**
+ * Execute state live save operation.
+ *
+ * This will be called repeatedly until all units vote that the live phase has
+ * been concluded.
+ *
+ * @returns VBox status code.
+ * @param pSSM SSM operation handle.
+ * @param pVMM The VMM ring-3 vtable.
+ * @param pvUser User argument.
+ * @param uPass The data pass.
+ * @thread Any.
+ */
+typedef DECLCALLBACKTYPE(int, FNSSMEXTLIVEEXEC,(PSSMHANDLE pSSM, PCVMMR3VTABLE pVMM, void *pvUser, uint32_t uPass));
+/** Pointer to a FNSSMEXTLIVEEXEC() function. */
+typedef FNSSMEXTLIVEEXEC *PFNSSMEXTLIVEEXEC;
+
+/**
+ * Vote on whether the live part of the saving has been concluded.
+ *
+ * The vote stops once a unit has vetoed the decision, so don't rely upon this
+ * being called every time.
+ *
+ * @returns VBox status code.
+ * @retval VINF_SUCCESS if done.
+ * @retval VINF_SSM_VOTE_FOR_ANOTHER_PASS if another pass is needed.
+ * @retval VINF_SSM_VOTE_DONE_DONT_CALL_AGAIN if the live saving of the unit is
+ * done and there is not need calling it again before the final pass.
+ * @retval VERR_SSM_VOTE_FOR_GIVING_UP if its time to give up.
+ *
+ * @param pSSM SSM operation handle.
+ * @param pVMM The VMM ring-3 vtable.
+ * @param pvUser User argument.
+ * @param uPass The data pass.
+ * @thread Any.
+ */
+typedef DECLCALLBACKTYPE(int, FNSSMEXTLIVEVOTE,(PSSMHANDLE pSSM, PCVMMR3VTABLE pVMM, void *pvUser, uint32_t uPass));
+/** Pointer to a FNSSMEXTLIVEVOTE() function. */
+typedef FNSSMEXTLIVEVOTE *PFNSSMEXTLIVEVOTE;
+
+/**
+ * Prepare state save operation.
+ *
+ * @returns VBox status code.
+ * @param pSSM SSM operation handle.
+ * @param pVMM The VMM ring-3 vtable.
+ * @param pvUser User argument.
+ */
+typedef DECLCALLBACKTYPE(int, FNSSMEXTSAVEPREP,(PSSMHANDLE pSSM, PCVMMR3VTABLE pVMM, void *pvUser));
+/** Pointer to a FNSSMEXTSAVEPREP() function. */
+typedef FNSSMEXTSAVEPREP *PFNSSMEXTSAVEPREP;
+
+/**
+ * Execute state save operation.
+ *
+ * @returns VBox status code.
+ * @param pSSM SSM operation handle.
+ * @param pVMM The VMM ring-3 vtable.
+ * @param pvUser User argument.
+ */
+typedef DECLCALLBACKTYPE(int, FNSSMEXTSAVEEXEC,(PSSMHANDLE pSSM, PCVMMR3VTABLE pVMM, void *pvUser));
+/** Pointer to a FNSSMEXTSAVEEXEC() function. */
+typedef FNSSMEXTSAVEEXEC *PFNSSMEXTSAVEEXEC;
+
+/**
+ * Done state save operation.
+ *
+ * @returns VBox status code.
+ * @param pSSM SSM operation handle.
+ * @param pVMM The VMM ring-3 vtable.
+ * @param pvUser User argument.
+ */
+typedef DECLCALLBACKTYPE(int, FNSSMEXTSAVEDONE,(PSSMHANDLE pSSM, PCVMMR3VTABLE pVMM, void *pvUser));
+/** Pointer to a FNSSMEXTSAVEDONE() function. */
+typedef FNSSMEXTSAVEDONE *PFNSSMEXTSAVEDONE;
+
+/**
+ * Prepare state load operation.
+ *
+ * @returns VBox status code.
+ * @param pSSM SSM operation handle.
+ * @param pVMM The VMM ring-3 vtable.
+ * @param pvUser User argument.
+ */
+typedef DECLCALLBACKTYPE(int, FNSSMEXTLOADPREP,(PSSMHANDLE pSSM, PCVMMR3VTABLE pVMM, void *pvUser));
+/** Pointer to a FNSSMEXTLOADPREP() function. */
+typedef FNSSMEXTLOADPREP *PFNSSMEXTLOADPREP;
+
+/**
+ * Execute state load operation.
+ *
+ * @returns VBox status code.
+ * @param pSSM SSM operation handle.
+ * @param pVMM The VMM ring-3 vtable.
+ * @param pvUser User argument.
+ * @param uVersion Data layout version.
+ * @param uPass The pass. This is always SSM_PASS_FINAL for units
+ * that doesn't specify a pfnSaveLive callback.
+ * @remark The odd return value is for legacy reasons.
+ */
+typedef DECLCALLBACKTYPE(int, FNSSMEXTLOADEXEC,(PSSMHANDLE pSSM, PCVMMR3VTABLE pVMM, void *pvUser,
+ uint32_t uVersion, uint32_t uPass));
+/** Pointer to a FNSSMEXTLOADEXEC() function. */
+typedef FNSSMEXTLOADEXEC *PFNSSMEXTLOADEXEC;
+
+/**
+ * Done state load operation.
+ *
+ * @returns VBox load code.
+ * @param pSSM SSM operation handle.
+ * @param pVMM The VMM ring-3 vtable.
+ * @param pvUser User argument.
+ */
+typedef DECLCALLBACKTYPE(int, FNSSMEXTLOADDONE,(PSSMHANDLE pSSM, PCVMMR3VTABLE pVMM, void *pvUser));
+/** Pointer to a FNSSMEXTLOADDONE() function. */
+typedef FNSSMEXTLOADDONE *PFNSSMEXTLOADDONE;
+
+/** @} */
+
+
+/**
+ * SSM stream method table.
+ *
+ * This is used by external parties for teleporting over TCP or any other media.
+ * SSM also uses this internally for file access, thus the 2-3 file centric
+ * methods.
+ */
+typedef struct SSMSTRMOPS
+{
+ /** Struct magic + version (SSMSTRMOPS_VERSION). */
+ uint32_t u32Version;
+
+ /**
+ * Write bytes to the stream.
+ *
+ * @returns VBox status code.
+ * @param pvUser The user argument.
+ * @param offStream The stream offset we're (supposed to be) at.
+ * @param pvBuf Pointer to the data.
+ * @param cbToWrite The number of bytes to write.
+ */
+ DECLCALLBACKMEMBER(int, pfnWrite,(void *pvUser, uint64_t offStream, const void *pvBuf, size_t cbToWrite));
+
+ /**
+ * Read bytes to the stream.
+ *
+ * @returns VBox status code.
+ * @param pvUser The user argument.
+ * @param offStream The stream offset we're (supposed to be) at.
+ * @param pvBuf Where to return the bytes.
+ * @param cbToRead The number of bytes to read.
+ * @param pcbRead Where to return the number of bytes actually
+ * read. This may differ from cbToRead when the
+ * end of the stream is encountered.
+ */
+ DECLCALLBACKMEMBER(int, pfnRead,(void *pvUser, uint64_t offStream, void *pvBuf, size_t cbToRead, size_t *pcbRead));
+
+ /**
+ * Seeks in the stream.
+ *
+ * @returns VBox status code.
+ * @retval VERR_NOT_SUPPORTED if the stream doesn't support this action.
+ *
+ * @param pvUser The user argument.
+ * @param offSeek The seek offset.
+ * @param uMethod RTFILE_SEEK_BEGIN, RTFILE_SEEK_END or
+ * RTFILE_SEEK_CURRENT.
+ * @param poffActual Where to store the new file position. Optional.
+ */
+ DECLCALLBACKMEMBER(int, pfnSeek,(void *pvUser, int64_t offSeek, unsigned uMethod, uint64_t *poffActual));
+
+ /**
+ * Get the current stream position.
+ *
+ * @returns The correct stream position.
+ * @param pvUser The user argument.
+ */
+ DECLCALLBACKMEMBER(uint64_t, pfnTell,(void *pvUser));
+
+ /**
+ * Get the size/length of the stream.
+ *
+ * @returns VBox status code.
+ * @retval VERR_NOT_SUPPORTED if the stream doesn't support this action.
+ *
+ * @param pvUser The user argument.
+ * @param pcb Where to return the size/length.
+ */
+ DECLCALLBACKMEMBER(int, pfnSize,(void *pvUser, uint64_t *pcb));
+
+ /**
+ * Check if the stream is OK or not (cancelled).
+ *
+ * @returns VBox status code.
+ * @param pvUser The user argument.
+ *
+ * @remarks The method is expected to do a LogRel on failure.
+ */
+ DECLCALLBACKMEMBER(int, pfnIsOk,(void *pvUser));
+
+ /**
+ * Close the stream.
+ *
+ * @returns VBox status code.
+ * @param pvUser The user argument.
+ * @param fCancelled True if the operation was cancelled.
+ */
+ DECLCALLBACKMEMBER(int, pfnClose,(void *pvUser, bool fCancelled));
+
+ /** Struct magic + version (SSMSTRMOPS_VERSION). */
+ uint32_t u32EndVersion;
+} SSMSTRMOPS;
+/** Struct magic + version (SSMSTRMOPS_VERSION). */
+#define SSMSTRMOPS_VERSION UINT32_C(0x55aa0001)
+
+
+VMMR3DECL(void) SSMR3Term(PVM pVM);
+VMMR3_INT_DECL(int)
+SSMR3RegisterDevice(PVM pVM, PPDMDEVINS pDevIns, const char *pszName, uint32_t uInstance, uint32_t uVersion,
+ size_t cbGuess, const char *pszBefore,
+ PFNSSMDEVLIVEPREP pfnLivePrep, PFNSSMDEVLIVEEXEC pfnLiveExec, PFNSSMDEVLIVEVOTE pfnLiveVote,
+ PFNSSMDEVSAVEPREP pfnSavePrep, PFNSSMDEVSAVEEXEC pfnSaveExec, PFNSSMDEVSAVEDONE pfnSaveDone,
+ PFNSSMDEVLOADPREP pfnLoadPrep, PFNSSMDEVLOADEXEC pfnLoadExec, PFNSSMDEVLOADDONE pfnLoadDone);
+VMMR3_INT_DECL(int)
+SSMR3RegisterDriver(PVM pVM, PPDMDRVINS pDrvIns, const char *pszName, uint32_t uInstance, uint32_t uVersion, size_t cbGuess,
+ PFNSSMDRVLIVEPREP pfnLivePrep, PFNSSMDRVLIVEEXEC pfnLiveExec, PFNSSMDRVLIVEVOTE pfnLiveVote,
+ PFNSSMDRVSAVEPREP pfnSavePrep, PFNSSMDRVSAVEEXEC pfnSaveExec, PFNSSMDRVSAVEDONE pfnSaveDone,
+ PFNSSMDRVLOADPREP pfnLoadPrep, PFNSSMDRVLOADEXEC pfnLoadExec, PFNSSMDRVLOADDONE pfnLoadDone);
+VMMR3_INT_DECL(int)
+SSMR3RegisterUsb(PVM pVM, PPDMUSBINS pUsbIns, const char *pszName, uint32_t uInstance, uint32_t uVersion, size_t cbGuess,
+ PFNSSMUSBLIVEPREP pfnLivePrep, PFNSSMUSBLIVEEXEC pfnLiveExec, PFNSSMUSBLIVEVOTE pfnLiveVote,
+ PFNSSMUSBSAVEPREP pfnSavePrep, PFNSSMUSBSAVEEXEC pfnSaveExec, PFNSSMUSBSAVEDONE pfnSaveDone,
+ PFNSSMUSBLOADPREP pfnLoadPrep, PFNSSMUSBLOADEXEC pfnLoadExec, PFNSSMUSBLOADDONE pfnLoadDone);
+VMMR3DECL(int)
+SSMR3RegisterInternal(PVM pVM, const char *pszName, uint32_t uInstance, uint32_t uVersion, size_t cbGuess,
+ PFNSSMINTLIVEPREP pfnLivePrep, PFNSSMINTLIVEEXEC pfnLiveExec, PFNSSMINTLIVEVOTE pfnLiveVote,
+ PFNSSMINTSAVEPREP pfnSavePrep, PFNSSMINTSAVEEXEC pfnSaveExec, PFNSSMINTSAVEDONE pfnSaveDone,
+ PFNSSMINTLOADPREP pfnLoadPrep, PFNSSMINTLOADEXEC pfnLoadExec, PFNSSMINTLOADDONE pfnLoadDone);
+VMMR3DECL(int)
+SSMR3RegisterExternal(PUVM pUVM, const char *pszName, uint32_t uInstance, uint32_t uVersion, size_t cbGuess,
+ PFNSSMEXTLIVEPREP pfnLivePrep, PFNSSMEXTLIVEEXEC pfnLiveExec, PFNSSMEXTLIVEVOTE pfnLiveVote,
+ PFNSSMEXTSAVEPREP pfnSavePrep, PFNSSMEXTSAVEEXEC pfnSaveExec, PFNSSMEXTSAVEDONE pfnSaveDone,
+ PFNSSMEXTLOADPREP pfnLoadPrep, PFNSSMEXTLOADEXEC pfnLoadExec, PFNSSMEXTLOADDONE pfnLoadDone, void *pvUser);
+VMMR3DECL(int) SSMR3RegisterStub(PVM pVM, const char *pszName, uint32_t uInstance);
+VMMR3_INT_DECL(int) SSMR3DeregisterDevice(PVM pVM, PPDMDEVINS pDevIns, const char *pszName, uint32_t uInstance);
+VMMR3_INT_DECL(int) SSMR3DeregisterDriver(PVM pVM, PPDMDRVINS pDrvIns, const char *pszName, uint32_t uInstance);
+VMMR3_INT_DECL(int) SSMR3DeregisterUsb(PVM pVM, PPDMUSBINS pUsbIns, const char *pszName, uint32_t uInstance);
+VMMR3DECL(int) SSMR3DeregisterInternal(PVM pVM, const char *pszName);
+VMMR3DECL(int) SSMR3DeregisterExternal(PUVM pUVM, const char *pszName);
+VMMR3DECL(int) SSMR3Save(PVM pVM, const char *pszFilename, PCSSMSTRMOPS pStreamOps, void *pvStreamOpsUser, SSMAFTER enmAfter, PFNVMPROGRESS pfnProgress, void *pvUser);
+VMMR3_INT_DECL(int) SSMR3LiveSave(PVM pVM, uint32_t cMsMaxDowntime,
+ const char *pszFilename, PCSSMSTRMOPS pStreamOps, void *pvStreamOps,
+ SSMAFTER enmAfter, PFNVMPROGRESS pfnProgress, void *pvProgressUser,
+ PSSMHANDLE *ppSSM);
+VMMR3_INT_DECL(int) SSMR3LiveDoStep1(PSSMHANDLE pSSM);
+VMMR3_INT_DECL(int) SSMR3LiveDoStep2(PSSMHANDLE pSSM);
+VMMR3_INT_DECL(int) SSMR3LiveDone(PSSMHANDLE pSSM);
+VMMR3DECL(int) SSMR3Load(PVM pVM, const char *pszFilename, PCSSMSTRMOPS pStreamOps, void *pvStreamOpsUser,
+ SSMAFTER enmAfter, PFNVMPROGRESS pfnProgress, void *pvProgressUser);
+VMMR3DECL(int) SSMR3ValidateFile(const char *pszFilename, PCSSMSTRMOPS pStreamOps, void *pvStreamOps,
+ bool fChecksumIt);
+VMMR3DECL(int) SSMR3Open(const char *pszFilename, PCSSMSTRMOPS pStreamOps, void *pvStreamOps,
+ unsigned fFlags, PSSMHANDLE *ppSSM);
+VMMR3DECL(int) SSMR3Close(PSSMHANDLE pSSM);
+VMMR3DECL(int) SSMR3Seek(PSSMHANDLE pSSM, const char *pszUnit, uint32_t iInstance, uint32_t *piVersion);
+VMMR3DECL(int) SSMR3HandleGetStatus(PSSMHANDLE pSSM);
+VMMR3DECL(int) SSMR3HandleSetStatus(PSSMHANDLE pSSM, int iStatus);
+VMMR3DECL(SSMAFTER) SSMR3HandleGetAfter(PSSMHANDLE pSSM);
+VMMR3DECL(bool) SSMR3HandleIsLiveSave(PSSMHANDLE pSSM);
+VMMR3DECL(uint32_t) SSMR3HandleMaxDowntime(PSSMHANDLE pSSM);
+VMMR3DECL(uint32_t) SSMR3HandleHostBits(PSSMHANDLE pSSM);
+VMMR3DECL(uint32_t) SSMR3HandleRevision(PSSMHANDLE pSSM);
+VMMR3DECL(uint32_t) SSMR3HandleVersion(PSSMHANDLE pSSM);
+VMMR3DECL(const char *) SSMR3HandleHostOSAndArch(PSSMHANDLE pSSM);
+VMMR3_INT_DECL(int) SSMR3HandleSetGCPtrSize(PSSMHANDLE pSSM, unsigned cbGCPtr);
+VMMR3DECL(void) SSMR3HandleReportLivePercent(PSSMHANDLE pSSM, unsigned uPercent);
+#ifdef DEBUG
+VMMR3DECL(uint64_t) SSMR3HandleTellInUnit(PSSMHANDLE pSSM);
+#endif
+VMMR3DECL(int) SSMR3Cancel(PUVM pUVM);
+
+
+/** Save operations.
+ * @{
+ */
+VMMR3DECL(int) SSMR3PutStruct(PSSMHANDLE pSSM, const void *pvStruct, PCSSMFIELD paFields);
+VMMR3DECL(int) SSMR3PutStructEx(PSSMHANDLE pSSM, const void *pvStruct, size_t cbStruct, uint32_t fFlags, PCSSMFIELD paFields, void *pvUser);
+VMMR3DECL(int) SSMR3PutBool(PSSMHANDLE pSSM, bool fBool);
+VMMR3DECL(int) SSMR3PutU8(PSSMHANDLE pSSM, uint8_t u8);
+VMMR3DECL(int) SSMR3PutS8(PSSMHANDLE pSSM, int8_t i8);
+VMMR3DECL(int) SSMR3PutU16(PSSMHANDLE pSSM, uint16_t u16);
+VMMR3DECL(int) SSMR3PutS16(PSSMHANDLE pSSM, int16_t i16);
+VMMR3DECL(int) SSMR3PutU32(PSSMHANDLE pSSM, uint32_t u32);
+VMMR3DECL(int) SSMR3PutS32(PSSMHANDLE pSSM, int32_t i32);
+VMMR3DECL(int) SSMR3PutU64(PSSMHANDLE pSSM, uint64_t u64);
+VMMR3DECL(int) SSMR3PutS64(PSSMHANDLE pSSM, int64_t i64);
+VMMR3DECL(int) SSMR3PutU128(PSSMHANDLE pSSM, uint128_t u128);
+VMMR3DECL(int) SSMR3PutS128(PSSMHANDLE pSSM, int128_t i128);
+VMMR3DECL(int) SSMR3PutUInt(PSSMHANDLE pSSM, RTUINT u);
+VMMR3DECL(int) SSMR3PutSInt(PSSMHANDLE pSSM, RTINT i);
+VMMR3DECL(int) SSMR3PutGCUInt(PSSMHANDLE pSSM, RTGCUINT u);
+VMMR3DECL(int) SSMR3PutGCUIntReg(PSSMHANDLE pSSM, RTGCUINTREG u);
+VMMR3DECL(int) SSMR3PutGCPhys32(PSSMHANDLE pSSM, RTGCPHYS32 GCPhys);
+VMMR3DECL(int) SSMR3PutGCPhys64(PSSMHANDLE pSSM, RTGCPHYS64 GCPhys);
+VMMR3DECL(int) SSMR3PutGCPhys(PSSMHANDLE pSSM, RTGCPHYS GCPhys);
+VMMR3DECL(int) SSMR3PutGCPtr(PSSMHANDLE pSSM, RTGCPTR GCPtr);
+VMMR3DECL(int) SSMR3PutGCUIntPtr(PSSMHANDLE pSSM, RTGCUINTPTR GCPtr);
+VMMR3DECL(int) SSMR3PutRCPtr(PSSMHANDLE pSSM, RTRCPTR RCPtr);
+VMMR3DECL(int) SSMR3PutIOPort(PSSMHANDLE pSSM, RTIOPORT IOPort);
+VMMR3DECL(int) SSMR3PutSel(PSSMHANDLE pSSM, RTSEL Sel);
+VMMR3DECL(int) SSMR3PutMem(PSSMHANDLE pSSM, const void *pv, size_t cb);
+VMMR3DECL(int) SSMR3PutStrZ(PSSMHANDLE pSSM, const char *psz);
+/** @} */
+
+
+
+/** Load operations.
+ * @{
+ */
+VMMR3DECL(int) SSMR3GetStruct(PSSMHANDLE pSSM, void *pvStruct, PCSSMFIELD paFields);
+VMMR3DECL(int) SSMR3GetStructEx(PSSMHANDLE pSSM, void *pvStruct, size_t cbStruct, uint32_t fFlags, PCSSMFIELD paFields, void *pvUser);
+VMMR3DECL(int) SSMR3GetBool(PSSMHANDLE pSSM, bool *pfBool);
+VMMR3DECL(int) SSMR3GetBoolV(PSSMHANDLE pSSM, bool volatile *pfBool);
+VMMR3DECL(int) SSMR3GetU8(PSSMHANDLE pSSM, uint8_t *pu8);
+VMMR3DECL(int) SSMR3GetU8V(PSSMHANDLE pSSM, uint8_t volatile *pu8);
+VMMR3DECL(int) SSMR3GetS8(PSSMHANDLE pSSM, int8_t *pi8);
+VMMR3DECL(int) SSMR3GetS8V(PSSMHANDLE pSSM, int8_t volatile *pi8);
+VMMR3DECL(int) SSMR3GetU16(PSSMHANDLE pSSM, uint16_t *pu16);
+VMMR3DECL(int) SSMR3GetU16V(PSSMHANDLE pSSM, uint16_t volatile *pu16);
+VMMR3DECL(int) SSMR3GetS16(PSSMHANDLE pSSM, int16_t *pi16);
+VMMR3DECL(int) SSMR3GetS16V(PSSMHANDLE pSSM, int16_t volatile *pi16);
+VMMR3DECL(int) SSMR3GetU32(PSSMHANDLE pSSM, uint32_t *pu32);
+VMMR3DECL(int) SSMR3GetU32V(PSSMHANDLE pSSM, uint32_t volatile *pu32);
+VMMR3DECL(int) SSMR3GetS32(PSSMHANDLE pSSM, int32_t *pi32);
+VMMR3DECL(int) SSMR3GetS32V(PSSMHANDLE pSSM, int32_t volatile *pi32);
+VMMR3DECL(int) SSMR3GetU64(PSSMHANDLE pSSM, uint64_t *pu64);
+VMMR3DECL(int) SSMR3GetU64V(PSSMHANDLE pSSM, uint64_t volatile *pu64);
+VMMR3DECL(int) SSMR3GetS64(PSSMHANDLE pSSM, int64_t *pi64);
+VMMR3DECL(int) SSMR3GetS64V(PSSMHANDLE pSSM, int64_t volatile *pi64);
+VMMR3DECL(int) SSMR3GetU128(PSSMHANDLE pSSM, uint128_t *pu128);
+VMMR3DECL(int) SSMR3GetU128V(PSSMHANDLE pSSM, uint128_t volatile *pu128);
+VMMR3DECL(int) SSMR3GetS128(PSSMHANDLE pSSM, int128_t *pi128);
+VMMR3DECL(int) SSMR3GetS128V(PSSMHANDLE pSSM, int128_t volatile *pi128);
+VMMR3DECL(int) SSMR3GetGCPhys32(PSSMHANDLE pSSM, PRTGCPHYS32 pGCPhys);
+VMMR3DECL(int) SSMR3GetGCPhys32V(PSSMHANDLE pSSM, RTGCPHYS32 volatile *pGCPhys);
+VMMR3DECL(int) SSMR3GetGCPhys64(PSSMHANDLE pSSM, PRTGCPHYS64 pGCPhys);
+VMMR3DECL(int) SSMR3GetGCPhys64V(PSSMHANDLE pSSM, RTGCPHYS64 volatile *pGCPhys);
+VMMR3DECL(int) SSMR3GetGCPhys(PSSMHANDLE pSSM, PRTGCPHYS pGCPhys);
+VMMR3DECL(int) SSMR3GetGCPhysV(PSSMHANDLE pSSM, RTGCPHYS volatile *pGCPhys);
+VMMR3DECL(int) SSMR3GetUInt(PSSMHANDLE pSSM, PRTUINT pu);
+VMMR3DECL(int) SSMR3GetSInt(PSSMHANDLE pSSM, PRTINT pi);
+VMMR3DECL(int) SSMR3GetGCUInt(PSSMHANDLE pSSM, PRTGCUINT pu);
+VMMR3DECL(int) SSMR3GetGCUIntReg(PSSMHANDLE pSSM, PRTGCUINTREG pu);
+VMMR3DECL(int) SSMR3GetGCPtr(PSSMHANDLE pSSM, PRTGCPTR pGCPtr);
+VMMR3DECL(int) SSMR3GetGCUIntPtr(PSSMHANDLE pSSM, PRTGCUINTPTR pGCPtr);
+VMMR3DECL(int) SSMR3GetRCPtr(PSSMHANDLE pSSM, PRTRCPTR pRCPtr);
+VMMR3DECL(int) SSMR3GetIOPort(PSSMHANDLE pSSM, PRTIOPORT pIOPort);
+VMMR3DECL(int) SSMR3GetSel(PSSMHANDLE pSSM, PRTSEL pSel);
+VMMR3DECL(int) SSMR3GetMem(PSSMHANDLE pSSM, void *pv, size_t cb);
+VMMR3DECL(int) SSMR3GetStrZ(PSSMHANDLE pSSM, char *psz, size_t cbMax);
+VMMR3DECL(int) SSMR3GetStrZEx(PSSMHANDLE pSSM, char *psz, size_t cbMax, size_t *pcbStr);
+VMMR3DECL(int) SSMR3Skip(PSSMHANDLE pSSM, size_t cb);
+VMMR3DECL(int) SSMR3SkipToEndOfUnit(PSSMHANDLE pSSM);
+VMMR3DECL(int) SSMR3SetLoadError(PSSMHANDLE pSSM, int rc, RT_SRC_POS_DECL, const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(6, 7);
+VMMR3DECL(int) SSMR3SetLoadErrorV(PSSMHANDLE pSSM, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(6, 0);
+VMMR3DECL(int) SSMR3SetCfgError(PSSMHANDLE pSSM, RT_SRC_POS_DECL, const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(5, 6);
+VMMR3DECL(int) SSMR3SetCfgErrorV(PSSMHANDLE pSSM, RT_SRC_POS_DECL, const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(5, 0);
+
+/** Wrapper around SSMR3GetU32 for simplifying getting enum values saved as uint32_t. */
+# define SSM_GET_ENUM32_RET(a_pSSM, a_enmDst, a_EnumType) \
+ do { \
+ uint32_t u32GetEnumTmp = 0; \
+ int rcGetEnum32Tmp = SSMR3GetU32((a_pSSM), &u32GetEnumTmp); \
+ AssertRCReturn(rcGetEnum32Tmp, rcGetEnum32Tmp); \
+ (a_enmDst) = (a_EnumType)u32GetEnumTmp; \
+ AssertCompile(sizeof(a_EnumType) == sizeof(u32GetEnumTmp)); \
+ } while (0)
+
+/** @} */
+
+/** @} */
+#endif /* IN_RING3 */
+
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !VBOX_INCLUDED_vmm_ssm_h */
+
diff --git a/include/VBox/vmm/stam.h b/include/VBox/vmm/stam.h
new file mode 100644
index 00000000..4c5764b4
--- /dev/null
+++ b/include/VBox/vmm/stam.h
@@ -0,0 +1,1376 @@
+/** @file
+ * STAM - Statistics Manager.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vmm_stam_h
+#define VBOX_INCLUDED_vmm_stam_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/types.h>
+#include <iprt/stdarg.h>
+#ifdef _MSC_VER
+# if RT_MSC_PREREQ(RT_MSC_VER_VS2005)
+# include <iprt/sanitized/intrin.h>
+# endif
+#endif
+#if defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32)
+# include <iprt/asm-arm.h>
+#endif
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_stam The Statistics Manager API
+ * @ingroup grp_vmm
+ * @{
+ */
+
+#if defined(VBOX_WITHOUT_RELEASE_STATISTICS) && defined(VBOX_WITH_STATISTICS)
+# error "Both VBOX_WITHOUT_RELEASE_STATISTICS and VBOX_WITH_STATISTICS are defined! Make up your mind!"
+#endif
+
+
+/** @def STAM_GET_TS
+ * Gets the CPU timestamp counter.
+ *
+ * @param u64 The 64-bit variable which the timestamp shall be saved in.
+ */
+#if defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32)
+# define STAM_GET_TS(u64) do { (u64) = ASMReadTSC(); } while (0)
+#elif defined(__GNUC__)
+# if defined(RT_ARCH_X86)
+ /* This produces optimal assembler code for x86 but does not work for AMD64 ('A' means 'either rax or rdx') */
+# define STAM_GET_TS(u64) __asm__ __volatile__ ("rdtsc\n\t" : "=A" (u64))
+# elif defined(RT_ARCH_AMD64)
+# define STAM_GET_TS(u64) \
+ do { uint64_t low; uint64_t high; \
+ __asm__ __volatile__ ("rdtsc\n\t" : "=a"(low), "=d"(high)); \
+ (u64) = ((high << 32) | low); \
+ } while (0)
+# endif
+#else
+# if RT_MSC_PREREQ(RT_MSC_VER_VS2005)
+# pragma intrinsic(__rdtsc)
+# define STAM_GET_TS(u64) \
+ do { (u64) = __rdtsc(); } while (0)
+# else
+# define STAM_GET_TS(u64) \
+ do { \
+ uint64_t u64Tmp; \
+ __asm { \
+ __asm rdtsc \
+ __asm mov dword ptr [u64Tmp], eax \
+ __asm mov dword ptr [u64Tmp + 4], edx \
+ } \
+ (u64) = u64Tmp; \
+ } while (0)
+# endif
+#endif
+
+
+/** @def STAM_REL_STATS
+ * Code for inclusion only when VBOX_WITH_STATISTICS is defined.
+ * @param code A code block enclosed in {}.
+ */
+#ifndef VBOX_WITHOUT_RELEASE_STATISTICS
+# define STAM_REL_STATS(code) do code while(0)
+#else
+# define STAM_REL_STATS(code) do {} while(0)
+#endif
+/** @def STAM_STATS
+ * Code for inclusion only when VBOX_WITH_STATISTICS is defined.
+ * @param code A code block enclosed in {}.
+ */
+#ifdef VBOX_WITH_STATISTICS
+# define STAM_STATS(code) STAM_REL_STATS(code)
+#else
+# define STAM_STATS(code) do {} while(0)
+#endif
+
+
+/**
+ * Sample type.
+ */
+typedef enum STAMTYPE
+{
+ /** Invalid entry. */
+ STAMTYPE_INVALID = 0,
+ /** Generic counter. */
+ STAMTYPE_COUNTER,
+ /** Profiling of an function. */
+ STAMTYPE_PROFILE,
+ /** Profiling of an operation. */
+ STAMTYPE_PROFILE_ADV,
+ /** Ratio of A to B, uint32_t types. Not reset. */
+ STAMTYPE_RATIO_U32,
+ /** Ratio of A to B, uint32_t types. Reset both to 0. */
+ STAMTYPE_RATIO_U32_RESET,
+ /** Callback. */
+ STAMTYPE_CALLBACK,
+ /** Generic unsigned 8-bit value. Not reset. */
+ STAMTYPE_U8,
+ /** Generic unsigned 8-bit value. Reset to 0. */
+ STAMTYPE_U8_RESET,
+ /** Generic hexadecimal unsigned 8-bit value. Not reset. */
+ STAMTYPE_X8,
+ /** Generic hexadecimal unsigned 8-bit value. Reset to 0. */
+ STAMTYPE_X8_RESET,
+ /** Generic unsigned 16-bit value. Not reset. */
+ STAMTYPE_U16,
+ /** Generic unsigned 16-bit value. Reset to 0. */
+ STAMTYPE_U16_RESET,
+ /** Generic hexadecimal unsigned 16-bit value. Not reset. */
+ STAMTYPE_X16,
+ /** Generic hexadecimal unsigned 16-bit value. Reset to 0. */
+ STAMTYPE_X16_RESET,
+ /** Generic unsigned 32-bit value. Not reset. */
+ STAMTYPE_U32,
+ /** Generic unsigned 32-bit value. Reset to 0. */
+ STAMTYPE_U32_RESET,
+ /** Generic hexadecimal unsigned 32-bit value. Not reset. */
+ STAMTYPE_X32,
+ /** Generic hexadecimal unsigned 32-bit value. Reset to 0. */
+ STAMTYPE_X32_RESET,
+ /** Generic unsigned 64-bit value. Not reset. */
+ STAMTYPE_U64,
+ /** Generic unsigned 64-bit value. Reset to 0. */
+ STAMTYPE_U64_RESET,
+ /** Generic hexadecimal unsigned 64-bit value. Not reset. */
+ STAMTYPE_X64,
+ /** Generic hexadecimal unsigned 64-bit value. Reset to 0. */
+ STAMTYPE_X64_RESET,
+ /** Generic boolean value. Not reset. */
+ STAMTYPE_BOOL,
+ /** Generic boolean value. Reset to false. */
+ STAMTYPE_BOOL_RESET,
+ /** The end (exclusive). */
+ STAMTYPE_END
+} STAMTYPE;
+
+/**
+ * Sample visibility type.
+ */
+typedef enum STAMVISIBILITY
+{
+ /** Invalid entry. */
+ STAMVISIBILITY_INVALID = 0,
+ /** Always visible. */
+ STAMVISIBILITY_ALWAYS,
+ /** Only visible when used (/hit). */
+ STAMVISIBILITY_USED,
+ /** Not visible in the GUI. */
+ STAMVISIBILITY_NOT_GUI,
+ /** The end (exclusive). */
+ STAMVISIBILITY_END
+} STAMVISIBILITY;
+
+/**
+ * Sample unit.
+ */
+typedef enum STAMUNIT
+{
+ /** Invalid entry .*/
+ STAMUNIT_INVALID = 0,
+ /** No unit. */
+ STAMUNIT_NONE,
+ /** Number of calls. */
+ STAMUNIT_CALLS,
+ /** Count of whatever. */
+ STAMUNIT_COUNT,
+ /** Count of bytes. */
+ STAMUNIT_BYTES,
+ /** Count of bytes per call. */
+ STAMUNIT_BYTES_PER_CALL,
+ /** Count of bytes. */
+ STAMUNIT_PAGES,
+ /** Error count. */
+ STAMUNIT_ERRORS,
+ /** Number of occurences. */
+ STAMUNIT_OCCURENCES,
+ /** Ticks. */
+ STAMUNIT_TICKS,
+ /** Ticks per call. */
+ STAMUNIT_TICKS_PER_CALL,
+ /** Ticks per occurence. */
+ STAMUNIT_TICKS_PER_OCCURENCE,
+ /** Ratio of good vs. bad. */
+ STAMUNIT_GOOD_BAD,
+ /** Megabytes. */
+ STAMUNIT_MEGABYTES,
+ /** Kilobytes. */
+ STAMUNIT_KILOBYTES,
+ /** Nano seconds. */
+ STAMUNIT_NS,
+ /** Nanoseconds per call. */
+ STAMUNIT_NS_PER_CALL,
+ /** Nanoseconds per call. */
+ STAMUNIT_NS_PER_OCCURENCE,
+ /** Percentage. */
+ STAMUNIT_PCT,
+ /** Hertz. */
+ STAMUNIT_HZ,
+ /** The end (exclusive). */
+ STAMUNIT_END
+} STAMUNIT;
+
+/** @name STAM_REFRESH_GRP_XXX - STAM refresh groups
+ * @{ */
+#define STAM_REFRESH_GRP_NONE UINT8_MAX
+#define STAM_REFRESH_GRP_GVMM 0
+#define STAM_REFRESH_GRP_GMM 1
+#define STAM_REFRESH_GRP_NEM 2
+/** @} */
+
+
+/** @def STAM_REL_U8_INC
+ * Increments a uint8_t sample by one.
+ *
+ * @param pCounter Pointer to the uint8_t variable to operate on.
+ */
+#ifndef VBOX_WITHOUT_RELEASE_STATISTICS
+# define STAM_REL_U8_INC(pCounter) \
+ do { ++*(pCounter); } while (0)
+#else
+# define STAM_REL_U8_INC(pCounter) do { } while (0)
+#endif
+/** @def STAM_U8_INC
+ * Increments a uint8_t sample by one.
+ *
+ * @param pCounter Pointer to the uint8_t variable to operate on.
+ */
+#ifdef VBOX_WITH_STATISTICS
+# define STAM_U8_INC(pCounter) STAM_REL_U8_INC(pCounter)
+#else
+# define STAM_U8_INC(pCounter) do { } while (0)
+#endif
+
+
+/** @def STAM_REL_U8_DEC
+ * Decrements a uint8_t sample by one.
+ *
+ * @param pCounter Pointer to the uint8_t variable to operate on.
+ */
+#ifndef VBOX_WITHOUT_RELEASE_STATISTICS
+# define STAM_REL_U8_DEC(pCounter) \
+ do { --*(pCounter); } while (0)
+#else
+# define STAM_REL_U8_DEC(pCounter) do { } while (0)
+#endif
+/** @def STAM_U8_DEC
+ * Decrements a uint8_t sample by one.
+ *
+ * @param pCounter Pointer to the uint8_t variable to operate on.
+ */
+#ifdef VBOX_WITH_STATISTICS
+# define STAM_U8_DEC(pCounter) STAM_REL_U8_DEC(pCounter)
+#else
+# define STAM_U8_DEC(pCounter) do { } while (0)
+#endif
+
+
+/** @def STAM_REL_U8_ADD
+ * Increments a uint8_t sample by a value.
+ *
+ * @param pCounter Pointer to the uint8_t variable to operate on.
+ * @param Addend The value to add.
+ */
+#ifndef VBOX_WITHOUT_RELEASE_STATISTICS
+# define STAM_REL_U8_ADD(pCounter, Addend) \
+ do { *(pCounter) += (Addend); } while (0)
+#else
+# define STAM_REL_U8_ADD(pCounter, Addend) do { } while (0)
+#endif
+/** @def STAM_U8_ADD
+ * Increments a uint8_t sample by a value.
+ *
+ * @param pCounter Pointer to the uint8_t variable to operate on.
+ * @param Addend The value to add.
+ */
+#ifdef VBOX_WITH_STATISTICS
+# define STAM_U8_ADD(pCounter, Addend) STAM_REL_U8_ADD(pCounter, Addend
+#else
+# define STAM_U8_ADD(pCounter, Addend) do { } while (0)
+#endif
+
+
+/** @def STAM_REL_U16_INC
+ * Increments a uint16_t sample by one.
+ *
+ * @param pCounter Pointer to the uint16_t variable to operate on.
+ */
+#ifndef VBOX_WITHOUT_RELEASE_STATISTICS
+# define STAM_REL_U16_INC(pCounter) \
+ do { ++*(pCounter); } while (0)
+#else
+# define STAM_REL_U16_INC(pCounter) do { } while (0)
+#endif
+/** @def STAM_U16_INC
+ * Increments a uint16_t sample by one.
+ *
+ * @param pCounter Pointer to the uint16_t variable to operate on.
+ */
+#ifdef VBOX_WITH_STATISTICS
+# define STAM_U16_INC(pCounter) STAM_REL_U16_INC(pCounter)
+#else
+# define STAM_U16_INC(pCounter) do { } while (0)
+#endif
+
+
+/** @def STAM_REL_U16_DEC
+ * Decrements a uint16_t sample by one.
+ *
+ * @param pCounter Pointer to the uint16_t variable to operate on.
+ */
+#ifndef VBOX_WITHOUT_RELEASE_STATISTICS
+# define STAM_REL_U16_DEC(pCounter) \
+ do { --*(pCounter); } while (0)
+#else
+# define STAM_REL_U16_DEC(pCounter) do { } while (0)
+#endif
+/** @def STAM_U16_DEC
+ * Decrements a uint16_t sample by one.
+ *
+ * @param pCounter Pointer to the uint16_t variable to operate on.
+ */
+#ifdef VBOX_WITH_STATISTICS
+# define STAM_U16_DEC(pCounter) STAM_REL_U16_DEC(pCounter)
+#else
+# define STAM_U16_DEC(pCounter) do { } while (0)
+#endif
+
+
+/** @def STAM_REL_U16_ADD
+ * Increments a uint16_t sample by a value.
+ *
+ * @param pCounter Pointer to the uint16_t variable to operate on.
+ * @param Addend The value to add.
+ */
+#ifndef VBOX_WITHOUT_RELEASE_STATISTICS
+# define STAM_REL_U16_ADD(pCounter, Addend) \
+ do { *(pCounter) += (Addend); } while (0)
+#else
+# define STAM_REL_U16_ADD(pCounter, Addend) do { } while (0)
+#endif
+/** @def STAM_U16_ADD
+ * Increments a uint16_t sample by a value.
+ *
+ * @param pCounter Pointer to the uint16_t variable to operate on.
+ * @param Addend The value to add.
+ */
+#ifdef VBOX_WITH_STATISTICS
+# define STAM_U16_ADD(pCounter, Addend) STAM_REL_U16_ADD(pCounter, Addend)
+#else
+# define STAM_U16_ADD(pCounter, Addend) do { } while (0)
+#endif
+
+
+/** @def STAM_REL_U32_INC
+ * Increments a uint32_t sample by one.
+ *
+ * @param pCounter Pointer to the uint32_t variable to operate on.
+ */
+#ifndef VBOX_WITHOUT_RELEASE_STATISTICS
+# define STAM_REL_U32_INC(pCounter) \
+ do { ++*(pCounter); } while (0)
+#else
+# define STAM_REL_U32_INC(pCounter) do { } while (0)
+#endif
+/** @def STAM_U32_INC
+ * Increments a uint32_t sample by one.
+ *
+ * @param pCounter Pointer to the uint32_t variable to operate on.
+ */
+#ifdef VBOX_WITH_STATISTICS
+# define STAM_U32_INC(pCounter) STAM_REL_U32_INC(pCounter)
+#else
+# define STAM_U32_INC(pCounter) do { } while (0)
+#endif
+
+
+/** @def STAM_REL_U32_DEC
+ * Decrements a uint32_t sample by one.
+ *
+ * @param pCounter Pointer to the uint32_t variable to operate on.
+ */
+#ifndef VBOX_WITHOUT_RELEASE_STATISTICS
+# define STAM_REL_U32_DEC(pCounter) \
+ do { --*(pCounter); } while (0)
+#else
+# define STAM_REL_U32_DEC(pCounter) do { } while (0)
+#endif
+/** @def STAM_U32_DEC
+ * Decrements a uint32_t sample by one.
+ *
+ * @param pCounter Pointer to the uint32_t variable to operate on.
+ */
+#ifdef VBOX_WITH_STATISTICS
+# define STAM_U32_DEC(pCounter) STAM_REL_U32_DEC(pCounter)
+#else
+# define STAM_U32_DEC(pCounter) do { } while (0)
+#endif
+
+
+/** @def STAM_REL_U32_ADD
+ * Increments a uint32_t sample by value.
+ *
+ * @param pCounter Pointer to the uint32_t variable to operate on.
+ * @param Addend The value to add.
+ */
+#ifndef VBOX_WITHOUT_RELEASE_STATISTICS
+# define STAM_REL_U32_ADD(pCounter, Addend) \
+ do { *(pCounter) += (Addend); } while (0)
+#else
+# define STAM_REL_U32_ADD(pCounter, Addend) do { } while (0)
+#endif
+/** @def STAM_U32_ADD
+ * Increments a uint32_t sample by value.
+ *
+ * @param pCounter Pointer to the uint32_t variable to operate on.
+ * @param Addend The value to add.
+ */
+#ifdef VBOX_WITH_STATISTICS
+# define STAM_U32_ADD(pCounter, Addend) STAM_REL_U32_ADD(pCounter, Addend)
+#else
+# define STAM_U32_ADD(pCounter, Addend) do { } while (0)
+#endif
+
+
+/** @def STAM_REL_U64_INC
+ * Increments a uint64_t sample by one.
+ *
+ * @param pCounter Pointer to the uint64_t variable to operate on.
+ */
+#ifndef VBOX_WITHOUT_RELEASE_STATISTICS
+# define STAM_REL_U64_INC(pCounter) \
+ do { ++*(pCounter); } while (0)
+#else
+# define STAM_REL_U64_INC(pCounter) do { } while (0)
+#endif
+/** @def STAM_U64_INC
+ * Increments a uint64_t sample by one.
+ *
+ * @param pCounter Pointer to the uint64_t variable to operate on.
+ */
+#ifdef VBOX_WITH_STATISTICS
+# define STAM_U64_INC(pCounter) STAM_REL_U64_INC(pCounter)
+#else
+# define STAM_U64_INC(pCounter) do { } while (0)
+#endif
+
+
+/** @def STAM_REL_U64_DEC
+ * Decrements a uint64_t sample by one.
+ *
+ * @param pCounter Pointer to the uint64_t variable to operate on.
+ */
+#ifndef VBOX_WITHOUT_RELEASE_STATISTICS
+# define STAM_REL_U64_DEC(pCounter) \
+ do { --*(pCounter); } while (0)
+#else
+# define STAM_REL_U64_DEC(pCounter) do { } while (0)
+#endif
+/** @def STAM_U64_DEC
+ * Decrements a uint64_t sample by one.
+ *
+ * @param pCounter Pointer to the uint64_t variable to operate on.
+ */
+#ifdef VBOX_WITH_STATISTICS
+# define STAM_U64_DEC(pCounter) STAM_REL_U64_DEC(pCounter)
+#else
+# define STAM_U64_DEC(pCounter) do { } while (0)
+#endif
+
+
+/** @def STAM_REL_U64_ADD
+ * Increments a uint64_t sample by a value.
+ *
+ * @param pCounter Pointer to the uint64_t variable to operate on.
+ * @param Addend The value to add.
+ */
+#ifndef VBOX_WITHOUT_RELEASE_STATISTICS
+# define STAM_REL_U64_ADD(pCounter, Addend) \
+ do { *(pCounter) += (Addend); } while (0)
+#else
+# define STAM_REL_U64_ADD(pCounter, Addend) do { } while (0)
+#endif
+/** @def STAM_U64_ADD
+ * Increments a uint64_t sample by a value.
+ *
+ * @param pCounter Pointer to the uint64_t variable to operate on.
+ * @param Addend The value to add.
+ */
+#ifdef VBOX_WITH_STATISTICS
+# define STAM_U64_ADD(pCounter, Addend) STAM_REL_U64_ADD(pCounter, Addend)
+#else
+# define STAM_U64_ADD(pCounter, Addend) do { } while (0)
+#endif
+
+
+/**
+ * Counter sample - STAMTYPE_COUNTER.
+ */
+typedef struct STAMCOUNTER
+{
+ /** The current count. */
+ volatile uint64_t c;
+} STAMCOUNTER;
+/** Pointer to a counter. */
+typedef STAMCOUNTER *PSTAMCOUNTER;
+/** Pointer to a const counter. */
+typedef const STAMCOUNTER *PCSTAMCOUNTER;
+
+
+/** @def STAM_REL_COUNTER_INC
+ * Increments a counter sample by one.
+ *
+ * @param pCounter Pointer to the STAMCOUNTER structure to operate on.
+ */
+#ifndef VBOX_WITHOUT_RELEASE_STATISTICS
+# define STAM_REL_COUNTER_INC(pCounter) \
+ do { (pCounter)->c++; } while (0)
+#else
+# define STAM_REL_COUNTER_INC(pCounter) do { } while (0)
+#endif
+/** @def STAM_COUNTER_INC
+ * Increments a counter sample by one.
+ *
+ * @param pCounter Pointer to the STAMCOUNTER structure to operate on.
+ */
+#ifdef VBOX_WITH_STATISTICS
+# define STAM_COUNTER_INC(pCounter) STAM_REL_COUNTER_INC(pCounter)
+#else
+# define STAM_COUNTER_INC(pCounter) do { } while (0)
+#endif
+
+
+/** @def STAM_REL_COUNTER_DEC
+ * Decrements a counter sample by one.
+ *
+ * @param pCounter Pointer to the STAMCOUNTER structure to operate on.
+ */
+#ifndef VBOX_WITHOUT_RELEASE_STATISTICS
+# define STAM_REL_COUNTER_DEC(pCounter) \
+ do { (pCounter)->c--; } while (0)
+#else
+# define STAM_REL_COUNTER_DEC(pCounter) do { } while (0)
+#endif
+/** @def STAM_COUNTER_DEC
+ * Decrements a counter sample by one.
+ *
+ * @param pCounter Pointer to the STAMCOUNTER structure to operate on.
+ */
+#ifdef VBOX_WITH_STATISTICS
+# define STAM_COUNTER_DEC(pCounter) STAM_REL_COUNTER_DEC(pCounter)
+#else
+# define STAM_COUNTER_DEC(pCounter) do { } while (0)
+#endif
+
+
+/** @def STAM_REL_COUNTER_ADD
+ * Increments a counter sample by a value.
+ *
+ * @param pCounter Pointer to the STAMCOUNTER structure to operate on.
+ * @param Addend The value to add to the counter.
+ */
+#ifndef VBOX_WITHOUT_RELEASE_STATISTICS
+# define STAM_REL_COUNTER_ADD(pCounter, Addend) \
+ do { (pCounter)->c += (Addend); } while (0)
+#else
+# define STAM_REL_COUNTER_ADD(pCounter, Addend) do { } while (0)
+#endif
+/** @def STAM_COUNTER_ADD
+ * Increments a counter sample by a value.
+ *
+ * @param pCounter Pointer to the STAMCOUNTER structure to operate on.
+ * @param Addend The value to add to the counter.
+ */
+#ifdef VBOX_WITH_STATISTICS
+# define STAM_COUNTER_ADD(pCounter, Addend) STAM_REL_COUNTER_ADD(pCounter, Addend)
+#else
+# define STAM_COUNTER_ADD(pCounter, Addend) do { } while (0)
+#endif
+
+
+/** @def STAM_REL_COUNTER_RESET
+ * Resets the statistics sample.
+ */
+#ifndef VBOX_WITHOUT_RELEASE_STATISTICS
+# define STAM_REL_COUNTER_RESET(pCounter) do { (pCounter)->c = 0; } while (0)
+#else
+# define STAM_REL_COUNTER_RESET(pCounter) do { } while (0)
+#endif
+/** @def STAM_COUNTER_RESET
+ * Resets the statistics sample.
+ */
+#ifdef VBOX_WITH_STATISTICS
+# define STAM_COUNTER_RESET(pCounter) STAM_REL_COUNTER_RESET(pCounter)
+#else
+# define STAM_COUNTER_RESET(pCounter) do { } while (0)
+#endif
+
+
+
+/**
+ * Profiling sample - STAMTYPE_PROFILE.
+ */
+typedef struct STAMPROFILE
+{
+ /** Number of periods. */
+ volatile uint64_t cPeriods;
+ /** Total count of ticks. */
+ volatile uint64_t cTicks;
+ /** Maximum tick count during a sampling. */
+ volatile uint64_t cTicksMax;
+ /** Minimum tick count during a sampling. */
+ volatile uint64_t cTicksMin;
+} STAMPROFILE;
+/** Pointer to a profile sample. */
+typedef STAMPROFILE *PSTAMPROFILE;
+/** Pointer to a const profile sample. */
+typedef const STAMPROFILE *PCSTAMPROFILE;
+
+
+/** @def STAM_REL_PROFILE_ADD_PERIOD
+ * Adds a period.
+ *
+ * @param pProfile Pointer to the STAMPROFILE structure to operate on.
+ * @param cTicksInPeriod The number of tick (or whatever) of the preiod
+ * being added. This is only referenced once.
+ */
+#ifndef VBOX_WITHOUT_RELEASE_STATISTICS
+# define STAM_REL_PROFILE_ADD_PERIOD(pProfile, cTicksInPeriod) \
+ do { \
+ uint64_t const StamPrefix_cTicks = (cTicksInPeriod); \
+ (pProfile)->cTicks += StamPrefix_cTicks; \
+ (pProfile)->cPeriods++; \
+ if ((pProfile)->cTicksMax < StamPrefix_cTicks) \
+ (pProfile)->cTicksMax = StamPrefix_cTicks; \
+ if ((pProfile)->cTicksMin > StamPrefix_cTicks) \
+ (pProfile)->cTicksMin = StamPrefix_cTicks; \
+ } while (0)
+#else
+# define STAM_REL_PROFILE_ADD_PERIOD(pProfile, cTicksInPeriod) do { } while (0)
+#endif
+/** @def STAM_PROFILE_ADD_PERIOD
+ * Adds a period.
+ *
+ * @param pProfile Pointer to the STAMPROFILE structure to operate on.
+ * @param cTicksInPeriod The number of tick (or whatever) of the preiod
+ * being added. This is only referenced once.
+ */
+#ifdef VBOX_WITH_STATISTICS
+# define STAM_PROFILE_ADD_PERIOD(pProfile, cTicksInPeriod) STAM_REL_PROFILE_ADD_PERIOD(pProfile, cTicksInPeriod)
+#else
+# define STAM_PROFILE_ADD_PERIOD(pProfile, cTicksInPeriod) do { } while (0)
+#endif
+
+
+/** @def STAM_REL_PROFILE_START
+ * Samples the start time of a profiling period.
+ *
+ * @param pProfile Pointer to the STAMPROFILE structure to operate on.
+ * @param Prefix Identifier prefix used to internal variables.
+ *
+ * @remarks Declears a stack variable that will be used by related macros.
+ */
+#ifndef VBOX_WITHOUT_RELEASE_STATISTICS
+# define STAM_REL_PROFILE_START(pProfile, Prefix) \
+ uint64_t Prefix##_tsStart; \
+ STAM_GET_TS(Prefix##_tsStart)
+#else
+# define STAM_REL_PROFILE_START(pProfile, Prefix) do { } while (0)
+#endif
+/** @def STAM_PROFILE_START
+ * Samples the start time of a profiling period.
+ *
+ * @param pProfile Pointer to the STAMPROFILE structure to operate on.
+ * @param Prefix Identifier prefix used to internal variables.
+ *
+ * @remarks Declears a stack variable that will be used by related macros.
+ */
+#ifdef VBOX_WITH_STATISTICS
+# define STAM_PROFILE_START(pProfile, Prefix) STAM_REL_PROFILE_START(pProfile, Prefix)
+#else
+# define STAM_PROFILE_START(pProfile, Prefix) do { } while (0)
+#endif
+
+/** @def STAM_REL_PROFILE_STOP
+ * Samples the stop time of a profiling period and updates the sample.
+ *
+ * @param pProfile Pointer to the STAMPROFILE structure to operate on.
+ * @param Prefix Identifier prefix used to internal variables.
+ */
+#ifndef VBOX_WITHOUT_RELEASE_STATISTICS
+# define STAM_REL_PROFILE_STOP(pProfile, Prefix) \
+ do { \
+ uint64_t Prefix##_cTicks; \
+ STAM_GET_TS(Prefix##_cTicks); \
+ Prefix##_cTicks -= Prefix##_tsStart; \
+ (pProfile)->cTicks += Prefix##_cTicks; \
+ (pProfile)->cPeriods++; \
+ if ((pProfile)->cTicksMax < Prefix##_cTicks) \
+ (pProfile)->cTicksMax = Prefix##_cTicks; \
+ if ((pProfile)->cTicksMin > Prefix##_cTicks) \
+ (pProfile)->cTicksMin = Prefix##_cTicks; \
+ } while (0)
+#else
+# define STAM_REL_PROFILE_STOP(pProfile, Prefix) do { } while (0)
+#endif
+/** @def STAM_PROFILE_STOP
+ * Samples the stop time of a profiling period and updates the sample.
+ *
+ * @param pProfile Pointer to the STAMPROFILE structure to operate on.
+ * @param Prefix Identifier prefix used to internal variables.
+ */
+#ifdef VBOX_WITH_STATISTICS
+# define STAM_PROFILE_STOP(pProfile, Prefix) STAM_REL_PROFILE_STOP(pProfile, Prefix)
+#else
+# define STAM_PROFILE_STOP(pProfile, Prefix) do { } while (0)
+#endif
+
+
+/** @def STAM_REL_PROFILE_STOP_EX
+ * Samples the stop time of a profiling period and updates both the sample
+ * and an attribution sample.
+ *
+ * @param pProfile Pointer to the STAMPROFILE structure to operate on.
+ * @param pProfile2 Pointer to the STAMPROFILE structure which this
+ * interval should be attributed to as well. This may be NULL.
+ * @param Prefix Identifier prefix used to internal variables.
+ */
+#ifndef VBOX_WITHOUT_RELEASE_STATISTICS
+# define STAM_REL_PROFILE_STOP_EX(pProfile, pProfile2, Prefix) \
+ do { \
+ uint64_t Prefix##_cTicks; \
+ STAM_GET_TS(Prefix##_cTicks); \
+ Prefix##_cTicks -= Prefix##_tsStart; \
+ (pProfile)->cTicks += Prefix##_cTicks; \
+ (pProfile)->cPeriods++; \
+ if ((pProfile)->cTicksMax < Prefix##_cTicks) \
+ (pProfile)->cTicksMax = Prefix##_cTicks; \
+ if ((pProfile)->cTicksMin > Prefix##_cTicks) \
+ (pProfile)->cTicksMin = Prefix##_cTicks; \
+ \
+ if ((pProfile2)) \
+ { \
+ (pProfile2)->cTicks += Prefix##_cTicks; \
+ (pProfile2)->cPeriods++; \
+ if ((pProfile2)->cTicksMax < Prefix##_cTicks) \
+ (pProfile2)->cTicksMax = Prefix##_cTicks; \
+ if ((pProfile2)->cTicksMin > Prefix##_cTicks) \
+ (pProfile2)->cTicksMin = Prefix##_cTicks; \
+ } \
+ } while (0)
+#else
+# define STAM_REL_PROFILE_STOP_EX(pProfile, pProfile2, Prefix) do { } while (0)
+#endif
+/** @def STAM_PROFILE_STOP_EX
+ * Samples the stop time of a profiling period and updates both the sample
+ * and an attribution sample.
+ *
+ * @param pProfile Pointer to the STAMPROFILE structure to operate on.
+ * @param pProfile2 Pointer to the STAMPROFILE structure which this
+ * interval should be attributed to as well. This may be NULL.
+ * @param Prefix Identifier prefix used to internal variables.
+ */
+#ifdef VBOX_WITH_STATISTICS
+# define STAM_PROFILE_STOP_EX(pProfile, pProfile2, Prefix) STAM_REL_PROFILE_STOP_EX(pProfile, pProfile2, Prefix)
+#else
+# define STAM_PROFILE_STOP_EX(pProfile, pProfile2, Prefix) do { } while (0)
+#endif
+
+
+/** @def STAM_REL_PROFILE_STOP_START
+ * Stops one profile counter (if running) and starts another one.
+ *
+ * @param pProfile1 Pointer to the STAMPROFILE structure to stop.
+ * @param pProfile2 Pointer to the STAMPROFILE structure to start.
+ * @param Prefix Identifier prefix used to internal variables.
+ */
+#ifndef VBOX_WITHOUT_RELEASE_STATISTICS
+# define STAM_REL_PROFILE_STOP_START(pProfile1, pProfile2, Prefix) \
+ do { \
+ uint64_t Prefix##_tsStop; \
+ STAM_GET_TS(Prefix##_tsStop); \
+ STAM_REL_PROFILE_ADD_PERIOD(pProfile1, Prefix##_tsStop - Prefix##_tsStart); \
+ Prefix##_tsStart = Prefix##_tsStop; \
+ } while (0)
+#else
+# define STAM_REL_PROFILE_STOP_START(pProfile1, pProfile2, Prefix) \
+ do { } while (0)
+#endif
+/** @def STAM_PROFILE_STOP_START
+ * Samples the stop time of a profiling period (if running) and updates the
+ * sample.
+ *
+ * @param pProfile1 Pointer to the STAMPROFILE structure to stop.
+ * @param pProfile2 Pointer to the STAMPROFILE structure to start.
+ * @param Prefix Identifier prefix used to internal variables.
+ */
+#ifdef VBOX_WITH_STATISTICS
+# define STAM_PROFILE_STOP_START(pProfile1, pProfile2, Prefix) \
+ STAM_REL_PROFILE_STOP_START(pProfile1, pProfile2, Prefix)
+#else
+# define STAM_PROFILE_STOP_START(pProfile1, pProfile2, Prefix) \
+ do { } while (0)
+#endif
+
+
+/** @def STAM_REL_PROFILE_START_NS
+ * Samples the start time of a profiling period, using RTTimeNanoTS().
+ *
+ * @param pProfile Pointer to the STAMPROFILE structure to operate on.
+ * @param Prefix Identifier prefix used to internal variables.
+ *
+ * @remarks Declears a stack variable that will be used by related macros.
+ */
+#ifndef VBOX_WITHOUT_RELEASE_STATISTICS
+# define STAM_REL_PROFILE_START_NS(pProfile, Prefix) \
+ uint64_t const Prefix##_tsStart = RTTimeNanoTS()
+#else
+# define STAM_REL_PROFILE_START_NS(pProfile, Prefix) do { } while (0)
+#endif
+/** @def STAM_PROFILE_START_NS
+ * Samples the start time of a profiling period, using RTTimeNanoTS().
+ *
+ * @param pProfile Pointer to the STAMPROFILE structure to operate on.
+ * @param Prefix Identifier prefix used to internal variables.
+ *
+ * @remarks Declears a stack variable that will be used by related macros.
+ */
+#ifdef VBOX_WITH_STATISTICS
+# define STAM_PROFILE_START_NS(pProfile, Prefix) STAM_REL_PROFILE_START_NS(pProfile, Prefix)
+#else
+# define STAM_PROFILE_START_NS(pProfile, Prefix) do { } while (0)
+#endif
+
+/** @def STAM_REL_PROFILE_STOP_NS
+ * Samples the stop time of a profiling period and updates the sample, using
+ * RTTimeNanoTS().
+ *
+ * @param pProfile Pointer to the STAMPROFILE structure to operate on.
+ * @param Prefix Identifier prefix used to internal variables.
+ */
+#ifndef VBOX_WITHOUT_RELEASE_STATISTICS
+# define STAM_REL_PROFILE_STOP_NS(pProfile, Prefix) \
+ STAM_REL_PROFILE_ADD_PERIOD(pProfile, RTTimeNanoTS() - Prefix##_tsStart)
+#else
+# define STAM_REL_PROFILE_STOP_NS(pProfile, Prefix) do { } while (0)
+#endif
+/** @def STAM_PROFILE_STOP_NS
+ * Samples the stop time of a profiling period and updates the sample, using
+ * RTTimeNanoTS().
+ *
+ * @param pProfile Pointer to the STAMPROFILE structure to operate on.
+ * @param Prefix Identifier prefix used to internal variables.
+ */
+#ifdef VBOX_WITH_STATISTICS
+# define STAM_PROFILE_STOP_NS(pProfile, Prefix) STAM_REL_PROFILE_STOP_NS(pProfile, Prefix)
+#else
+# define STAM_PROFILE_STOP_NS(pProfile, Prefix) do { } while (0)
+#endif
+
+
+/**
+ * Advanced profiling sample - STAMTYPE_PROFILE_ADV.
+ *
+ * Identical to a STAMPROFILE sample, but the start timestamp
+ * is stored after the STAMPROFILE structure so the sampling
+ * can start and stop in different functions.
+ */
+typedef struct STAMPROFILEADV
+{
+ /** The STAMPROFILE core. */
+ STAMPROFILE Core;
+ /** The start timestamp. */
+ volatile uint64_t tsStart;
+} STAMPROFILEADV;
+/** Pointer to a advanced profile sample. */
+typedef STAMPROFILEADV *PSTAMPROFILEADV;
+/** Pointer to a const advanced profile sample. */
+typedef const STAMPROFILEADV *PCSTAMPROFILEADV;
+
+
+/** @def STAM_REL_PROFILE_ADV_START
+ * Samples the start time of a profiling period.
+ *
+ * @param pProfileAdv Pointer to the STAMPROFILEADV structure to operate on.
+ * @param Prefix Identifier prefix used to internal variables.
+ */
+#ifndef VBOX_WITHOUT_RELEASE_STATISTICS
+# define STAM_REL_PROFILE_ADV_START(pProfileAdv, Prefix) \
+ STAM_GET_TS((pProfileAdv)->tsStart)
+#else
+# define STAM_REL_PROFILE_ADV_START(pProfileAdv, Prefix) do { } while (0)
+#endif
+/** @def STAM_PROFILE_ADV_START
+ * Samples the start time of a profiling period.
+ *
+ * @param pProfileAdv Pointer to the STAMPROFILEADV structure to operate on.
+ * @param Prefix Identifier prefix used to internal variables.
+ */
+#ifdef VBOX_WITH_STATISTICS
+# define STAM_PROFILE_ADV_START(pProfileAdv, Prefix) STAM_REL_PROFILE_ADV_START(pProfileAdv, Prefix)
+#else
+# define STAM_PROFILE_ADV_START(pProfileAdv, Prefix) do { } while (0)
+#endif
+
+
+/** @def STAM_REL_PROFILE_ADV_STOP
+ * Samples the stop time of a profiling period (if running) and updates the
+ * sample.
+ *
+ * @param pProfileAdv Pointer to the STAMPROFILEADV structure to operate on.
+ * @param Prefix Identifier prefix used to internal variables.
+ */
+#ifndef VBOX_WITHOUT_RELEASE_STATISTICS
+# define STAM_REL_PROFILE_ADV_STOP(pProfileAdv, Prefix) \
+ do { \
+ if ((pProfileAdv)->tsStart) \
+ { \
+ uint64_t Prefix##_cTicks; \
+ STAM_GET_TS(Prefix##_cTicks); \
+ Prefix##_cTicks -= (pProfileAdv)->tsStart; \
+ (pProfileAdv)->tsStart = 0; \
+ (pProfileAdv)->Core.cTicks += Prefix##_cTicks; \
+ (pProfileAdv)->Core.cPeriods++; \
+ if ((pProfileAdv)->Core.cTicksMax < Prefix##_cTicks) \
+ (pProfileAdv)->Core.cTicksMax = Prefix##_cTicks; \
+ if ((pProfileAdv)->Core.cTicksMin > Prefix##_cTicks) \
+ (pProfileAdv)->Core.cTicksMin = Prefix##_cTicks; \
+ } \
+ } while (0)
+#else
+# define STAM_REL_PROFILE_ADV_STOP(pProfileAdv, Prefix) do { } while (0)
+#endif
+/** @def STAM_PROFILE_ADV_STOP
+ * Samples the stop time of a profiling period (if running) and updates the
+ * sample.
+ *
+ * @param pProfileAdv Pointer to the STAMPROFILEADV structure to operate on.
+ * @param Prefix Identifier prefix used to internal variables.
+ */
+#ifdef VBOX_WITH_STATISTICS
+# define STAM_PROFILE_ADV_STOP(pProfileAdv, Prefix) STAM_REL_PROFILE_ADV_STOP(pProfileAdv, Prefix)
+#else
+# define STAM_PROFILE_ADV_STOP(pProfileAdv, Prefix) do { } while (0)
+#endif
+
+
+/** @def STAM_REL_PROFILE_ADV_STOP_START
+ * Stops one profile counter (if running) and starts another one.
+ *
+ * @param pProfileAdv1 Pointer to the STAMPROFILEADV structure to stop.
+ * @param pProfileAdv2 Pointer to the STAMPROFILEADV structure to start.
+ * @param Prefix Identifier prefix used to internal variables.
+ */
+#ifndef VBOX_WITHOUT_RELEASE_STATISTICS
+# define STAM_REL_PROFILE_ADV_STOP_START(pProfileAdv1, pProfileAdv2, Prefix) \
+ do { \
+ uint64_t Prefix##_cTicks; \
+ STAM_GET_TS(Prefix##_cTicks); \
+ (pProfileAdv2)->tsStart = Prefix##_cTicks; \
+ if ((pProfileAdv1)->tsStart) \
+ { \
+ Prefix##_cTicks -= (pProfileAdv1)->tsStart; \
+ (pProfileAdv1)->tsStart = 0; \
+ (pProfileAdv1)->Core.cTicks += Prefix##_cTicks; \
+ (pProfileAdv1)->Core.cPeriods++; \
+ if ((pProfileAdv1)->Core.cTicksMax < Prefix##_cTicks) \
+ (pProfileAdv1)->Core.cTicksMax = Prefix##_cTicks; \
+ if ((pProfileAdv1)->Core.cTicksMin > Prefix##_cTicks) \
+ (pProfileAdv1)->Core.cTicksMin = Prefix##_cTicks; \
+ } \
+ } while (0)
+#else
+# define STAM_REL_PROFILE_ADV_STOP_START(pProfileAdv1, pProfileAdv2, Prefix) \
+ do { } while (0)
+#endif
+/** @def STAM_PROFILE_ADV_STOP_START
+ * Samples the stop time of a profiling period (if running) and updates the
+ * sample.
+ *
+ * @param pProfileAdv1 Pointer to the STAMPROFILEADV structure to stop.
+ * @param pProfileAdv2 Pointer to the STAMPROFILEADV structure to start.
+ * @param Prefix Identifier prefix used to internal variables.
+ */
+#ifdef VBOX_WITH_STATISTICS
+# define STAM_PROFILE_ADV_STOP_START(pProfileAdv1, pProfileAdv2, Prefix) \
+ STAM_REL_PROFILE_ADV_STOP_START(pProfileAdv1, pProfileAdv2, Prefix)
+#else
+# define STAM_PROFILE_ADV_STOP_START(pProfileAdv1, pProfileAdv2, Prefix) \
+ do { } while (0)
+#endif
+
+
+/** @def STAM_REL_PROFILE_ADV_SUSPEND
+ * Suspends the sampling for a while. This can be useful to exclude parts
+ * covered by other samples without screwing up the count, and average+min times.
+ *
+ * @param pProfileAdv Pointer to the STAMPROFILEADV structure to operate on.
+ * @param Prefix Identifier prefix used to internal variables. The prefix
+ * must match that of the resume one since it stores the
+ * suspend time in a stack variable.
+ */
+#ifndef VBOX_WITHOUT_RELEASE_STATISTICS
+# define STAM_REL_PROFILE_ADV_SUSPEND(pProfileAdv, Prefix) \
+ uint64_t Prefix##_tsSuspend; \
+ STAM_GET_TS(Prefix##_tsSuspend)
+#else
+# define STAM_REL_PROFILE_ADV_SUSPEND(pProfileAdv, Prefix) do { } while (0)
+#endif
+/** @def STAM_PROFILE_ADV_SUSPEND
+ * Suspends the sampling for a while. This can be useful to exclude parts
+ * covered by other samples without screwing up the count, and average+min times.
+ *
+ * @param pProfileAdv Pointer to the STAMPROFILEADV structure to operate on.
+ * @param Prefix Identifier prefix used to internal variables. The prefix
+ * must match that of the resume one since it stores the
+ * suspend time in a stack variable.
+ */
+#ifdef VBOX_WITH_STATISTICS
+# define STAM_PROFILE_ADV_SUSPEND(pProfileAdv, Prefix) STAM_REL_PROFILE_ADV_SUSPEND(pProfileAdv, Prefix)
+#else
+# define STAM_PROFILE_ADV_SUSPEND(pProfileAdv, Prefix) do { } while (0)
+#endif
+
+
+/** @def STAM_REL_PROFILE_ADV_RESUME
+ * Counter to STAM_REL_PROFILE_ADV_SUSPEND.
+ *
+ * @param pProfileAdv Pointer to the STAMPROFILEADV structure to operate on.
+ * @param Prefix Identifier prefix used to internal variables. This must
+ * match the one used with the SUSPEND!
+ */
+#ifndef VBOX_WITHOUT_RELEASE_STATISTICS
+# define STAM_REL_PROFILE_ADV_RESUME(pProfileAdv, Prefix) \
+ do { \
+ uint64_t Prefix##_tsNow; \
+ STAM_GET_TS(Prefix##_tsNow); \
+ (pProfileAdv)->tsStart += Prefix##_tsNow - Prefix##_tsSuspend; \
+ } while (0)
+#else
+# define STAM_REL_PROFILE_ADV_RESUME(pProfileAdv, Prefix) do { } while (0)
+#endif
+/** @def STAM_PROFILE_ADV_RESUME
+ * Counter to STAM_PROFILE_ADV_SUSPEND.
+ *
+ * @param pProfileAdv Pointer to the STAMPROFILEADV structure to operate on.
+ * @param Prefix Identifier prefix used to internal variables. This must
+ * match the one used with the SUSPEND!
+ */
+#ifdef VBOX_WITH_STATISTICS
+# define STAM_PROFILE_ADV_RESUME(pProfileAdv, Prefix) STAM_REL_PROFILE_ADV_RESUME(pProfileAdv, Prefix)
+#else
+# define STAM_PROFILE_ADV_RESUME(pProfileAdv, Prefix) do { } while (0)
+#endif
+
+
+/** @def STAM_REL_PROFILE_ADV_STOP_EX
+ * Samples the stop time of a profiling period (if running) and updates both
+ * the sample and an attribution sample.
+ *
+ * @param pProfileAdv Pointer to the STAMPROFILEADV structure to operate on.
+ * @param pProfile2 Pointer to the STAMPROFILE structure which this
+ * interval should be attributed to as well. This may be NULL.
+ * @param Prefix Identifier prefix used to internal variables.
+ */
+#ifndef VBOX_WITHOUT_RELEASE_STATISTICS
+# define STAM_REL_PROFILE_ADV_STOP_EX(pProfileAdv, pProfile2, Prefix) \
+ do { \
+ if ((pProfileAdv)->tsStart) \
+ { \
+ uint64_t Prefix##_cTicks; \
+ STAM_GET_TS(Prefix##_cTicks); \
+ Prefix##_cTicks -= (pProfileAdv)->tsStart; \
+ (pProfileAdv)->tsStart = 0; \
+ (pProfileAdv)->Core.cTicks += Prefix##_cTicks; \
+ (pProfileAdv)->Core.cPeriods++; \
+ if ((pProfileAdv)->Core.cTicksMax < Prefix##_cTicks) \
+ (pProfileAdv)->Core.cTicksMax = Prefix##_cTicks; \
+ if ((pProfileAdv)->Core.cTicksMin > Prefix##_cTicks) \
+ (pProfileAdv)->Core.cTicksMin = Prefix##_cTicks; \
+ if ((pProfile2)) \
+ { \
+ (pProfile2)->cTicks += Prefix##_cTicks; \
+ (pProfile2)->cPeriods++; \
+ if ((pProfile2)->cTicksMax < Prefix##_cTicks) \
+ (pProfile2)->cTicksMax = Prefix##_cTicks; \
+ if ((pProfile2)->cTicksMin > Prefix##_cTicks) \
+ (pProfile2)->cTicksMin = Prefix##_cTicks; \
+ } \
+ } \
+ } while (0)
+#else
+# define STAM_REL_PROFILE_ADV_STOP_EX(pProfileAdv, pProfile2, Prefix) do { } while (0)
+#endif
+/** @def STAM_PROFILE_ADV_STOP_EX
+ * Samples the stop time of a profiling period (if running) and updates both
+ * the sample and an attribution sample.
+ *
+ * @param pProfileAdv Pointer to the STAMPROFILEADV structure to operate on.
+ * @param pProfile2 Pointer to the STAMPROFILE structure which this
+ * interval should be attributed to as well. This may be NULL.
+ * @param Prefix Identifier prefix used to internal variables.
+ */
+#ifdef VBOX_WITH_STATISTICS
+# define STAM_PROFILE_ADV_STOP_EX(pProfileAdv, pProfile2, Prefix) STAM_REL_PROFILE_ADV_STOP_EX(pProfileAdv, pProfile2, Prefix)
+#else
+# define STAM_PROFILE_ADV_STOP_EX(pProfileAdv, pProfile2, Prefix) do { } while (0)
+#endif
+
+/** @def STAM_REL_PROFILE_ADV_IS_RUNNING
+ * Checks if it is running.
+ *
+ * @param pProfileAdv Pointer to the STAMPROFILEADV structure to operate on.
+ */
+#ifndef VBOX_WITHOUT_RELEASE_STATISTICS
+# define STAM_REL_PROFILE_ADV_IS_RUNNING(pProfileAdv) (pProfileAdv)->tsStart
+#else
+# define STAM_REL_PROFILE_ADV_IS_RUNNING(pProfileAdv) (false)
+#endif
+/** @def STAM_PROFILE_ADV_IS_RUNNING
+ * Checks if it is running.
+ *
+ * @param pProfileAdv Pointer to the STAMPROFILEADV structure to operate on.
+ */
+#ifdef VBOX_WITH_STATISTICS
+# define STAM_PROFILE_ADV_IS_RUNNING(pProfileAdv) STAM_REL_PROFILE_ADV_IS_RUNNING(pProfileAdv)
+#else
+# define STAM_PROFILE_ADV_IS_RUNNING(pProfileAdv) (false)
+#endif
+
+/** @def STAM_REL_PROFILE_ADV_SET_STOPPED
+ * Marks the profile counter as stopped.
+ *
+ * This is for avoiding screwups in twisty code.
+ *
+ * @param pProfileAdv Pointer to the STAMPROFILEADV structure to operate on.
+ */
+#ifndef VBOX_WITHOUT_RELEASE_STATISTICS
+# define STAM_REL_PROFILE_ADV_SET_STOPPED(pProfileAdv) do { (pProfileAdv)->tsStart = 0; } while (0)
+#else
+# define STAM_REL_PROFILE_ADV_SET_STOPPED(pProfileAdv) do { } while (0)
+#endif
+/** @def STAM_PROFILE_ADV_SET_STOPPED
+ * Marks the profile counter as stopped.
+ *
+ * This is for avoiding screwups in twisty code.
+ *
+ * @param pProfileAdv Pointer to the STAMPROFILEADV structure to operate on.
+ */
+#ifdef VBOX_WITH_STATISTICS
+# define STAM_PROFILE_ADV_SET_STOPPED(pProfileAdv) STAM_REL_PROFILE_ADV_SET_STOPPED(pProfileAdv)
+#else
+# define STAM_PROFILE_ADV_SET_STOPPED(pProfileAdv) do { } while (0)
+#endif
+
+
+/**
+ * Ratio of A to B, uint32_t types.
+ * @remark Use STAM_STATS or STAM_REL_STATS for modifying A & B values.
+ */
+typedef struct STAMRATIOU32
+{
+ /** Sample A. */
+ uint32_t volatile u32A;
+ /** Sample B. */
+ uint32_t volatile u32B;
+} STAMRATIOU32;
+/** Pointer to a uint32_t ratio. */
+typedef STAMRATIOU32 *PSTAMRATIOU32;
+/** Pointer to const a uint32_t ratio. */
+typedef const STAMRATIOU32 *PCSTAMRATIOU32;
+
+
+
+
+/** @defgroup grp_stam_r3 The STAM Host Context Ring 3 API
+ * @{
+ */
+
+VMMR3DECL(int) STAMR3InitUVM(PUVM pUVM);
+VMMR3DECL(void) STAMR3TermUVM(PUVM pUVM);
+VMMR3DECL(int) STAMR3RegisterU(PUVM pUVM, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility,
+ const char *pszName, STAMUNIT enmUnit, const char *pszDesc);
+VMMR3DECL(int) STAMR3Register(PVM pVM, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility,
+ const char *pszName, STAMUNIT enmUnit, const char *pszDesc);
+
+/** @def STAM_REL_REG
+ * Registers a statistics sample.
+ *
+ * @param pVM The cross context VM structure.
+ * @param pvSample Pointer to the sample.
+ * @param enmType Sample type. This indicates what pvSample is pointing at.
+ * @param pszName Sample name. The name is on this form "/<component>/<sample>".
+ * Further nesting is possible.
+ * @param enmUnit Sample unit.
+ * @param pszDesc Sample description.
+ */
+#define STAM_REL_REG(pVM, pvSample, enmType, pszName, enmUnit, pszDesc) \
+ STAM_REL_STATS({ int rcStam = STAMR3Register(pVM, pvSample, enmType, STAMVISIBILITY_ALWAYS, pszName, enmUnit, pszDesc); \
+ AssertRC(rcStam); })
+/** @def STAM_REG
+ * Registers a statistics sample if statistics are enabled.
+ *
+ * @param pVM The cross context VM structure.
+ * @param pvSample Pointer to the sample.
+ * @param enmType Sample type. This indicates what pvSample is pointing at.
+ * @param pszName Sample name. The name is on this form "/<component>/<sample>".
+ * Further nesting is possible.
+ * @param enmUnit Sample unit.
+ * @param pszDesc Sample description.
+ */
+#define STAM_REG(pVM, pvSample, enmType, pszName, enmUnit, pszDesc) \
+ STAM_STATS({STAM_REL_REG(pVM, pvSample, enmType, pszName, enmUnit, pszDesc);})
+
+/** @def STAM_REL_REG_USED
+ * Registers a statistics sample which only shows when used.
+ *
+ * @param pVM The cross context VM structure.
+ * @param pvSample Pointer to the sample.
+ * @param enmType Sample type. This indicates what pvSample is pointing at.
+ * @param pszName Sample name. The name is on this form "/<component>/<sample>".
+ * Further nesting is possible.
+ * @param enmUnit Sample unit.
+ * @param pszDesc Sample description.
+ */
+#define STAM_REL_REG_USED(pVM, pvSample, enmType, pszName, enmUnit, pszDesc) \
+ STAM_REL_STATS({ int rcStam = STAMR3Register(pVM, pvSample, enmType, STAMVISIBILITY_USED, pszName, enmUnit, pszDesc); \
+ AssertRC(rcStam);})
+/** @def STAM_REG_USED
+ * Registers a statistics sample which only shows when used, if statistics are enabled.
+ *
+ * @param pVM The cross context VM structure.
+ * @param pvSample Pointer to the sample.
+ * @param enmType Sample type. This indicates what pvSample is pointing at.
+ * @param pszName Sample name. The name is on this form "/<component>/<sample>".
+ * Further nesting is possible.
+ * @param enmUnit Sample unit.
+ * @param pszDesc Sample description.
+ */
+#define STAM_REG_USED(pVM, pvSample, enmType, pszName, enmUnit, pszDesc) \
+ STAM_STATS({ STAM_REL_REG_USED(pVM, pvSample, enmType, pszName, enmUnit, pszDesc); })
+
+VMMR3DECL(int) STAMR3RegisterFU(PUVM pUVM, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility, STAMUNIT enmUnit,
+ const char *pszDesc, const char *pszName, ...) RT_IPRT_FORMAT_ATTR(7, 8);
+VMMR3DECL(int) STAMR3RegisterF(PVM pVM, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility, STAMUNIT enmUnit,
+ const char *pszDesc, const char *pszName, ...) RT_IPRT_FORMAT_ATTR(7, 8);
+VMMR3DECL(int) STAMR3RegisterVU(PUVM pUVM, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility, STAMUNIT enmUnit,
+ const char *pszDesc, const char *pszName, va_list args) RT_IPRT_FORMAT_ATTR(7, 0);
+VMMR3DECL(int) STAMR3RegisterV(PVM pVM, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility, STAMUNIT enmUnit,
+ const char *pszDesc, const char *pszName, va_list args) RT_IPRT_FORMAT_ATTR(7, 0);
+
+/**
+ * Resets the sample.
+ * @param pVM The cross context VM structure.
+ * @param pvSample The sample registered using STAMR3RegisterCallback.
+ */
+typedef DECLCALLBACKTYPE(void, FNSTAMR3CALLBACKRESET,(PVM pVM, void *pvSample));
+/** Pointer to a STAM sample reset callback. */
+typedef FNSTAMR3CALLBACKRESET *PFNSTAMR3CALLBACKRESET;
+
+/**
+ * Prints the sample into the buffer.
+ *
+ * @param pVM The cross context VM structure.
+ * @param pvSample The sample registered using STAMR3RegisterCallback.
+ * @param pszBuf The buffer to print into.
+ * @param cchBuf The size of the buffer.
+ */
+typedef DECLCALLBACKTYPE(void, FNSTAMR3CALLBACKPRINT,(PVM pVM, void *pvSample, char *pszBuf, size_t cchBuf));
+/** Pointer to a STAM sample print callback. */
+typedef FNSTAMR3CALLBACKPRINT *PFNSTAMR3CALLBACKPRINT;
+
+VMMR3DECL(int) STAMR3RegisterCallback(PVM pVM, void *pvSample, STAMVISIBILITY enmVisibility, STAMUNIT enmUnit,
+ PFNSTAMR3CALLBACKRESET pfnReset, PFNSTAMR3CALLBACKPRINT pfnPrint,
+ const char *pszDesc, const char *pszName, ...) RT_IPRT_FORMAT_ATTR(8, 9);
+VMMR3DECL(int) STAMR3RegisterCallbackV(PVM pVM, void *pvSample, STAMVISIBILITY enmVisibility, STAMUNIT enmUnit,
+ PFNSTAMR3CALLBACKRESET pfnReset, PFNSTAMR3CALLBACKPRINT pfnPrint,
+ const char *pszDesc, const char *pszName, va_list args) RT_IPRT_FORMAT_ATTR(8, 0);
+
+VMMR3DECL(int) STAMR3RegisterRefresh(PUVM pUVM, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility,
+ STAMUNIT enmUnit, uint8_t iRefreshGrp, const char *pszDesc,
+ const char *pszName, ...) RT_IPRT_FORMAT_ATTR(8, 9);
+VMMR3DECL(int) STAMR3RegisterRefreshV(PUVM pUVM, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility,
+ STAMUNIT enmUnit, uint8_t iRefreshGrp, const char *pszDesc,
+ const char *pszName, va_list va) RT_IPRT_FORMAT_ATTR(8, 0);
+
+VMMR3DECL(int) STAMR3Deregister(PUVM pUVM, const char *pszPat);
+VMMR3DECL(int) STAMR3DeregisterF(PUVM pUVM, const char *pszPatFmt, ...) RT_IPRT_FORMAT_ATTR(2, 3);
+VMMR3DECL(int) STAMR3DeregisterV(PUVM pUVM, const char *pszPatFmt, va_list va) RT_IPRT_FORMAT_ATTR(2, 0);
+VMMR3DECL(int) STAMR3DeregisterByPrefix(PUVM pUVM, const char *pszPrefix);
+VMMR3DECL(int) STAMR3DeregisterByAddr(PUVM pUVM, void *pvSample);
+
+VMMR3DECL(int) STAMR3Reset(PUVM pUVM, const char *pszPat);
+VMMR3DECL(int) STAMR3Snapshot(PUVM pUVM, const char *pszPat, char **ppszSnapshot, size_t *pcchSnapshot, bool fWithDesc);
+VMMR3DECL(int) STAMR3SnapshotFree(PUVM pUVM, char *pszSnapshot);
+VMMR3DECL(int) STAMR3Dump(PUVM pUVM, const char *pszPat);
+VMMR3DECL(int) STAMR3DumpToReleaseLog(PUVM pUVM, const char *pszPat);
+VMMR3DECL(int) STAMR3Print(PUVM pUVM, const char *pszPat);
+
+/**
+ * Callback function for STAMR3Enum().
+ *
+ * @returns non-zero to halt the enumeration.
+ *
+ * @param pszName The name of the sample.
+ * @param enmType The type.
+ * @param pvSample Pointer to the data. enmType indicates the format of this data.
+ * @param enmUnit The unit.
+ * @param pszUnit The unit as string. This is a permanent string,
+ * same as returned by STAMR3GetUnit().
+ * @param enmVisibility The visibility.
+ * @param pszDesc The description.
+ * @param pvUser The pvUser argument given to STAMR3Enum().
+ */
+typedef DECLCALLBACKTYPE(int, FNSTAMR3ENUM,(const char *pszName, STAMTYPE enmType, void *pvSample, STAMUNIT enmUnit,
+ const char *pszUnit, STAMVISIBILITY enmVisibility, const char *pszDesc, void *pvUser));
+/** Pointer to a FNSTAMR3ENUM(). */
+typedef FNSTAMR3ENUM *PFNSTAMR3ENUM;
+
+VMMR3DECL(int) STAMR3Enum(PUVM pUVM, const char *pszPat, PFNSTAMR3ENUM pfnEnum, void *pvUser);
+VMMR3DECL(const char *) STAMR3GetUnit(STAMUNIT enmUnit);
+VMMR3DECL(const char *) STAMR3GetUnit1(STAMUNIT enmUnit);
+VMMR3DECL(const char *) STAMR3GetUnit2(STAMUNIT enmUnit);
+
+/** @} */
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !VBOX_INCLUDED_vmm_stam_h */
+
diff --git a/include/VBox/vmm/stam.mac b/include/VBox/vmm/stam.mac
new file mode 100644
index 00000000..b70a881a
--- /dev/null
+++ b/include/VBox/vmm/stam.mac
@@ -0,0 +1,392 @@
+;; @file
+; STAM - Statistics Manager.
+;
+
+;
+; Copyright (C) 2006-2022 Oracle and/or its affiliates.
+;
+; This file is part of VirtualBox base platform packages, as
+; available from https://www.virtualbox.org.
+;
+; This program is free software; you can redistribute it and/or
+; modify it under the terms of the GNU General Public License
+; as published by the Free Software Foundation, in version 3 of the
+; License.
+;
+; This program is distributed in the hope that it will be useful, but
+; WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with this program; if not, see <https://www.gnu.org/licenses>.
+;
+; The contents of this file may alternatively be used under the terms
+; of the Common Development and Distribution License Version 1.0
+; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+; in the VirtualBox 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.
+;
+; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+;
+
+%ifndef ___VBox_vmm_stam_mac__
+%define ___VBox_vmm_stam_mac__
+
+
+%ifndef VBOX_WITH_STATISTICS
+ %ifdef DEBUG
+ %define VBOX_WITH_STATISTICS
+ %endif
+%endif
+
+
+
+;;
+; Counter sample - STAMTYPE_COUNTER.
+struc STAMCOUNTER
+ .c resd 2
+endstruc
+
+;;
+; Increments a counter sample by one.
+; @param %1 Pointer to the STAMCOUNTER structure to operate on.
+%macro STAM32_COUNTER_INC 1
+%ifdef VBOX_WITH_STATISTICS
+ push ebx
+ mov ebx, %1
+ inc dword [ebx + STAMCOUNTER.c]
+ adc dword [ebx + STAMCOUNTER.c + 1], byte 0
+ pop ebx
+%endif
+%endmacro
+
+%macro STAM64_COUNTER_INC 1
+%ifdef VBOX_WITH_STATISTICS
+ push rbx
+ mov rbx, %1
+ inc qword [rbx + STAMCOUNTER.c]
+ pop rbx
+%endif
+%endmacro
+
+%macro STAM_COUNTER_INC 1
+%ifdef VBOX_WITH_STATISTICS
+ %ifdef RT_ARCH_AMD64
+ STAM64_COUNTER_INC %1
+ %else
+ STAM32_COUNTER_INC %1
+ %endif
+%endif
+%endmacro
+
+
+;;
+; Increments a counter sample by a value.
+;
+; @param %1 Pointer to the STAMCOUNTER structure to operate on.
+; @param %2 The value to add to the counter.
+%macro STAM32_COUNTER_ADD 2
+%ifdef VBOX_WITH_STATISTICS
+ push ebx
+ mov ebx, %1
+ push eax
+ mov eax, %2
+
+ add [ebx + STAMCOUNTER.c], eax
+ adc dword [ebx + STAMCOUNTER.c], byte 0
+
+ pop eax
+ pop ebx
+%endif
+%endmacro
+
+%macro STAM64_COUNTER_ADD 2
+%ifdef VBOX_WITH_STATISTICS
+ push rbx
+ mov rbx, %1
+ push rax
+ mov rax, %2
+
+ add [rbx + STAMCOUNTER.c], rax
+
+ pop rax
+ pop rbx
+%endif
+%endmacro
+
+%macro STAM_COUNTER_ADD 2
+%ifdef VBOX_WITH_STATISTICS
+ %ifdef RT_ARCH_AMD64
+ STAM64_COUNTER_ADD %1, %2
+ %else
+ STAM32_COUNTER_ADD %1, %2
+ %endif
+%endif
+%endmacro
+
+
+;;
+; Profiling sample - STAMTYPE_PROFILE.
+struc STAMPROFILE
+ .cPeriods resd 2
+ .cTicks resd 2
+ .cTicksMax resd 2
+ .cTicksMin resd 2
+endstruc
+
+
+;;
+; Samples the start time of a profiling period.
+;
+; @param %1 Pointer to somewhere one can store a 64-bit timestamp until STAM_PROFILE_STOPP
+%macro STAM32_PROFILE_START 1
+%ifdef VBOX_WITH_STATISTICS
+ push ebx
+ mov ebx, %1
+ push eax
+ push edx
+
+ rdtsc
+ mov [ebx], eax
+ mov [ebx + 4], edx
+
+ pop edx
+ pop eax
+ pop ebx
+%endif
+%endmacro
+
+%macro STAM64_PROFILE_START 1
+%ifdef VBOX_WITH_STATISTICS
+ push rbx
+ mov rbx, %1
+ push rax
+ push rdx
+
+ rdtsc
+ mov [rbx], eax
+ mov [rbx + 4], edx
+
+ pop rdx
+ pop rax
+ pop rbx
+%endif
+%endmacro
+
+%macro STAM_PROFILE_START 1
+%ifdef VBOX_WITH_STATISTICS
+ %ifdef RT_ARCH_AMD64
+ STAM64_PROFILE_START %1
+ %else
+ STAM32_PROFILE_START %1
+ %endif
+%endif
+%endmacro
+
+
+;;
+; Samples the stop time of a profiling period and updates the sample.
+;
+; @param %1 Pointer to the STAMPROFILE structure to operate on.
+; @param %2 Pointer to where the 64-bit timestamp from STAM_PROFILE_START was stored.
+%macro STAM32_PROFILE_STOP 2
+%ifdef VBOX_WITH_STATISTICS
+ push ebx
+ mov ebx, %1
+ push eax
+ push edx
+
+ ; calc cTicks
+ push ecx
+ mov ecx, %2
+ rdtsc
+ sub eax, [ecx]
+ sbb edx, [ecx + 4]
+ pop ecx
+
+ ; update STAMPROFILE.cTicks
+ add [ebx + STAMPROFILE.cTicks], eax
+ adc [ebx + STAMPROFILE.cTicks + 4], edx
+ ; update STAMPROFILE.cPeriods
+ inc dword [ebx + STAMPROFILE.cPeriods]
+ adc dword [ebx + STAMPROFILE.cPeriods + 4], byte 0
+
+ ; update max?
+ cmp edx, [ebx + STAMPROFILE.cTicksMax + 4]
+ jb short %%not_update_max
+ ja short %%update_max
+ cmp eax, [ebx + STAMPROFILE.cTicksMax]
+ jbe short %%not_update_max
+%%update_max:
+ mov [ebx + STAMPROFILE.cTicksMax], eax
+ mov [ebx + STAMPROFILE.cTicksMax + 4], edx
+%%not_update_max:
+
+ ; update min?
+ cmp edx, [ebx + STAMPROFILE.cTicksMin + 4]
+ ja short %%not_update_min
+ jb short %%update_min
+ cmp eax, [ebx + STAMPROFILE.cTicksMin]
+ jae short %%not_update_min
+%%update_min:
+ mov [ebx + STAMPROFILE.cTicksMin], eax
+ mov [ebx + STAMPROFILE.cTicksMin + 4], edx
+%%not_update_min:
+
+ pop edx
+ pop eax
+ pop ebx
+%endif
+%endmacro
+
+%macro STAM64_PROFILE_STOP 2
+%ifdef VBOX_WITH_STATISTICS
+ push rbx
+ mov rbx, %1
+ push rax
+ push rdx
+
+ ; calc cTicks
+ push rcx
+ mov rcx, %2
+ rdtsc
+ sub rax, [ecx]
+ sbb rdx, [ecx + 4]
+ pop rcx
+
+ ; update STAMPROFILE.cTicks
+ shl rdx, 32
+ or rdx, rax
+ add [rbx + STAMPROFILE.cTicks], rdx
+ ; update STAMPROFILE.cPeriods
+ inc qword [rbx + STAMPROFILE.cPeriods]
+
+ ; update max?
+ cmp rdx, [rbx + STAMPROFILE.cTicksMax]
+ jbe short %%not_update_max
+ mov [rbx + STAMPROFILE.cTicksMax], rdx
+%%not_update_max:
+
+ ; update min?
+ cmp rdx, [rbx + STAMPROFILE.cTicksMin]
+ jae short %%not_update_min
+ mov [rbx + STAMPROFILE.cTicksMin], rax
+%%not_update_min:
+
+ pop rdx
+ pop rax
+ pop rbx
+%endif
+%endmacro
+
+%macro STAM_PROFILE_STOP 2
+%ifdef VBOX_WITH_STATISTICS
+ %ifdef RT_ARCH_AMD64
+ STAM64_PROFILE_STOP %1, %2
+ %else
+ STAM32_PROFILE_STOP %1, %2
+ %endif
+%endif
+%endmacro
+
+
+
+struc STAMPROFILEADV
+ .cPeriods resd 2
+ .cTicks resd 2
+ .cTicksMax resd 2
+ .cTicksMin resd 2
+ .tsStart resd 2
+endstruc
+
+
+;;
+; Samples the start time of a profiling period.
+;
+; @param %1 Pointer to the STAMPROFILEADV structure to operate on.
+%macro STAM32_PROFILE_ADV_START 1
+%ifdef VBOX_WITH_STATISTICS
+ push ecx
+ mov ecx, %1
+ lea ecx, [ecx + STAMPROFILEADV.tsStart]
+ STAM32_PROFILE_START ecx
+ pop ecx
+%endif
+%endmacro
+
+%macro STAM64_PROFILE_ADV_START 1
+%ifdef VBOX_WITH_STATISTICS
+ push rcx
+ mov rcx, %1
+ lea rcx, [rcx + STAMPROFILEADV.tsStart]
+ STAM64_PROFILE_START rcx
+ pop rcx
+%endif
+%endmacro
+
+%macro STAM_PROFILE_ADV_START 1
+%ifdef VBOX_WITH_STATISTICS
+ %ifdef RT_ARCH_AMD64
+ STAM64_PROFILE_ADV_START %1
+ %else
+ STAM32_PROFILE_ADV_START %1
+ %endif
+%endif
+%endmacro
+
+
+;;
+; Samples the stop time of a profiling period and updates the sample.
+;
+; @param %1 Pointer to the STAMPROFILEADV structure to operate on.
+
+%macro STAM32_PROFILE_ADV_STOP 1
+%ifdef VBOX_WITH_STATISTICS
+ push ecx
+ mov ecx, %1
+ lea ecx, [ecx + STAMPROFILEADV.tsStart]
+ cmp dword [ecx], byte 0
+ jnz short %%doit
+ cmp dword [ecx + 4], byte 0
+ jz short %%dont
+%%doit:
+ STAM32_PROFILE_STOP %1, ecx
+%%dont:
+ mov dword [ecx], 0
+ mov dword [ecx + 4], 0
+ pop ecx
+%endif
+%endmacro
+
+%macro STAM64_PROFILE_ADV_STOP 1
+%ifdef VBOX_WITH_STATISTICS
+ push rcx
+ mov rcx, %1
+ lea rcx, [rcx + STAMPROFILEADV.tsStart]
+ cmp qword [rcx], byte 0
+ jz short %%dont
+%%doit:
+ STAM64_PROFILE_STOP %1, rcx
+%%dont:
+ mov qword [rcx], 0
+ pop rcx
+%endif
+%endmacro
+
+%macro STAM_PROFILE_ADV_STOP 1
+%ifdef VBOX_WITH_STATISTICS
+ %ifdef RT_ARCH_AMD64
+ STAM64_PROFILE_ADV_STOP %1
+ %else
+ STAM32_PROFILE_ADV_STOP %1
+ %endif
+%endif
+%endmacro
+
+
+
+%endif
diff --git a/include/VBox/vmm/tm.h b/include/VBox/vmm/tm.h
new file mode 100644
index 00000000..2bd62d3a
--- /dev/null
+++ b/include/VBox/vmm/tm.h
@@ -0,0 +1,322 @@
+/** @file
+ * TM - Time Manager.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vmm_tm_h
+#define VBOX_INCLUDED_vmm_tm_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/types.h>
+#ifdef IN_RING3
+# include <iprt/time.h>
+#endif
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_tm The Time Manager API
+ * @ingroup grp_vmm
+ * @{
+ */
+
+/** Enable a timer hack which improves the timer response/resolution a bit. */
+#define VBOX_HIGH_RES_TIMERS_HACK
+
+
+/**
+ * Clock type.
+ */
+typedef enum TMCLOCK
+{
+ /** Real host time.
+ * This clock ticks all the time, so use with care. */
+ TMCLOCK_REAL = 0,
+ /** Virtual guest time.
+ * This clock only ticks when the guest is running. It's implemented
+ * as an offset to monotonic real time (GIP). */
+ TMCLOCK_VIRTUAL,
+ /** Virtual guest synchronized timer time.
+ * This is a special clock and timer queue for synchronizing virtual timers
+ * and virtual time sources. This clock is trying to keep up with
+ * TMCLOCK_VIRTUAL, but will wait for timers to be executed. If it lags
+ * too far behind TMCLOCK_VIRTUAL, it will try speed up to close the
+ * distance.
+ * @remarks Do not use this unless you really *must*. */
+ TMCLOCK_VIRTUAL_SYNC,
+ /** Virtual CPU timestamp.
+ * By default this is a function of TMCLOCK_VIRTUAL_SYNC and the virtual
+ * CPU frequency. */
+ TMCLOCK_TSC,
+ /** Number of clocks. */
+ TMCLOCK_MAX
+} TMCLOCK;
+
+
+/** @defgroup grp_tm_timer_flags Timer flags.
+ * @{ */
+/** Use the default critical section for the class of timers. */
+#define TMTIMER_FLAGS_DEFAULT_CRIT_SECT 0
+/** No critical section needed or a custom one is set using
+ * TMR3TimerSetCritSect(). */
+#define TMTIMER_FLAGS_NO_CRIT_SECT RT_BIT_32(0)
+/** Used in ring-0. Must set this or TMTIMER_FLAGS_NO_RING0. */
+#define TMTIMER_FLAGS_RING0 RT_BIT_32(1)
+/** Not used in ring-0 (for refactoring and doc purposes). */
+#define TMTIMER_FLAGS_NO_RING0 RT_BIT_32(31)
+/** @} */
+
+
+VMMDECL(void) TMNotifyStartOfExecution(PVMCC pVM, PVMCPUCC pVCpu);
+VMMDECL(void) TMNotifyEndOfExecution(PVMCC pVM, PVMCPUCC pVCpu, uint64_t uTsc);
+VMM_INT_DECL(void) TMNotifyStartOfHalt(PVMCPUCC pVCpu);
+VMM_INT_DECL(void) TMNotifyEndOfHalt(PVMCPUCC pVCpu);
+#ifdef IN_RING3
+VMMR3DECL(int) TMR3NotifySuspend(PVM pVM, PVMCPU pVCpu);
+VMMR3DECL(int) TMR3NotifyResume(PVM pVM, PVMCPU pVCpu);
+VMMR3DECL(int) TMR3SetWarpDrive(PUVM pUVM, uint32_t u32Percent);
+VMMR3DECL(uint32_t) TMR3GetWarpDrive(PUVM pUVM);
+#endif
+VMM_INT_DECL(uint32_t) TMCalcHostTimerFrequency(PVMCC pVM, PVMCPUCC pVCpu);
+#ifdef IN_RING3
+VMMR3DECL(int) TMR3GetCpuLoadTimes(PVM pVM, VMCPUID idCpu, uint64_t *pcNsTotal, uint64_t *pcNsExecuting,
+ uint64_t *pcNsHalted, uint64_t *pcNsOther);
+VMMR3DECL(int) TMR3GetCpuLoadPercents(PUVM pVUM, VMCPUID idCpu, uint64_t *pcMsInterval, uint8_t *pcPctExecuting,
+ uint8_t *pcPctHalted, uint8_t *pcPctOther);
+#endif
+
+
+/** @name Real Clock Methods
+ * @{
+ */
+VMM_INT_DECL(uint64_t) TMRealGet(PVM pVM);
+VMM_INT_DECL(uint64_t) TMRealGetFreq(PVM pVM);
+/** @} */
+
+
+/** @name Virtual Clock Methods
+ * @{
+ */
+VMM_INT_DECL(uint64_t) TMVirtualGet(PVMCC pVM);
+VMM_INT_DECL(uint64_t) TMVirtualGetNoCheck(PVMCC pVM);
+VMM_INT_DECL(uint64_t) TMVirtualSyncGetLag(PVMCC pVM);
+VMM_INT_DECL(uint32_t) TMVirtualSyncGetCatchUpPct(PVMCC pVM);
+VMM_INT_DECL(uint64_t) TMVirtualGetFreq(PVM pVM);
+VMM_INT_DECL(uint64_t) TMVirtualSyncGet(PVMCC pVM);
+VMM_INT_DECL(uint64_t) TMVirtualSyncGetNoCheck(PVMCC pVM);
+VMM_INT_DECL(uint64_t) TMVirtualSyncGetNoCheckWithTsc(PVMCC pVM, uint64_t *puTscNow);
+VMM_INT_DECL(uint64_t) TMVirtualSyncGetEx(PVMCC pVM, bool fCheckTimers);
+VMM_INT_DECL(uint64_t) TMVirtualSyncGetWithDeadlineNoCheck(PVMCC pVM, uint64_t *pcNsToDeadline,
+ uint64_t *puDeadlineVersion, uint64_t *puTscNow);
+VMMDECL(uint64_t) TMVirtualSyncGetNsToDeadline(PVMCC pVM, uint64_t *puDeadlineVersion, uint64_t *puTscNow);
+VMM_INT_DECL(bool) TMVirtualSyncIsCurrentDeadlineVersion(PVMCC pVM, uint64_t uDeadlineVersion);
+VMM_INT_DECL(uint64_t) TMVirtualToNano(PVM pVM, uint64_t u64VirtualTicks);
+VMM_INT_DECL(uint64_t) TMVirtualToMicro(PVM pVM, uint64_t u64VirtualTicks);
+VMM_INT_DECL(uint64_t) TMVirtualToMilli(PVM pVM, uint64_t u64VirtualTicks);
+VMM_INT_DECL(uint64_t) TMVirtualFromNano(PVM pVM, uint64_t u64NanoTS);
+VMM_INT_DECL(uint64_t) TMVirtualFromMicro(PVM pVM, uint64_t u64MicroTS);
+VMM_INT_DECL(uint64_t) TMVirtualFromMilli(PVM pVM, uint64_t u64MilliTS);
+VMM_INT_DECL(bool) TMVirtualIsTicking(PVM pVM);
+
+VMMR3DECL(uint64_t) TMR3TimeVirtGet(PUVM pUVM);
+VMMR3DECL(uint64_t) TMR3TimeVirtGetMilli(PUVM pUVM);
+VMMR3DECL(uint64_t) TMR3TimeVirtGetMicro(PUVM pUVM);
+VMMR3DECL(uint64_t) TMR3TimeVirtGetNano(PUVM pUVM);
+/** @} */
+
+
+/** @name CPU Clock Methods
+ * @{
+ */
+VMMDECL(uint64_t) TMCpuTickGet(PVMCPUCC pVCpu);
+VMM_INT_DECL(uint64_t) TMCpuTickGetNoCheck(PVMCPUCC pVCpu);
+VMM_INT_DECL(bool) TMCpuTickCanUseRealTSC(PVMCC pVM, PVMCPUCC pVCpu, uint64_t *poffRealTSC, bool *pfParavirtTsc);
+VMM_INT_DECL(uint64_t) TMCpuTickGetDeadlineAndTscOffset(PVMCC pVM, PVMCPUCC pVCpu, uint64_t *poffRealTsc,
+ bool *pfOffsettedTsc, bool *pfParavirtTsc,
+ uint64_t *puTscNow, uint64_t *puDeadlineVersion);
+VMM_INT_DECL(int) TMCpuTickSet(PVMCC pVM, PVMCPUCC pVCpu, uint64_t u64Tick);
+VMM_INT_DECL(int) TMCpuTickSetLastSeen(PVMCPUCC pVCpu, uint64_t u64LastSeenTick);
+VMM_INT_DECL(uint64_t) TMCpuTickGetLastSeen(PVMCPUCC pVCpu);
+VMMDECL(uint64_t) TMCpuTicksPerSecond(PVMCC pVM);
+VMM_INT_DECL(bool) TMCpuTickIsTicking(PVMCPUCC pVCpu);
+/** @} */
+
+
+/** @name Timer Methods
+ * @{
+ */
+/**
+ * Device timer callback function.
+ *
+ * @param pDevIns Device instance of the device which registered the timer.
+ * @param hTimer The timer handle.
+ * @param pvUser User argument specified upon timer creation.
+ */
+typedef DECLCALLBACKTYPE(void, FNTMTIMERDEV,(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, void *pvUser));
+/** Pointer to a device timer callback function. */
+typedef FNTMTIMERDEV *PFNTMTIMERDEV;
+
+/**
+ * USB device timer callback function.
+ *
+ * @param pUsbIns The USB device instance the timer is associated
+ * with.
+ * @param hTimer The timer handle.
+ * @param pvUser User argument specified upon timer creation.
+ */
+typedef DECLCALLBACKTYPE(void, FNTMTIMERUSB,(PPDMUSBINS pUsbIns, TMTIMERHANDLE hTimer, void *pvUser));
+/** Pointer to a timer callback for a USB device. */
+typedef FNTMTIMERUSB *PFNTMTIMERUSB;
+
+/**
+ * Driver timer callback function.
+ *
+ * @param pDrvIns Device instance of the device which registered the timer.
+ * @param hTimer The timer handle.
+ * @param pvUser User argument specified upon timer creation.
+ */
+typedef DECLCALLBACKTYPE(void, FNTMTIMERDRV,(PPDMDRVINS pDrvIns, TMTIMERHANDLE hTimer, void *pvUser));
+/** Pointer to a driver timer callback function. */
+typedef FNTMTIMERDRV *PFNTMTIMERDRV;
+
+/**
+ * Service timer callback function.
+ *
+ * @param pSrvIns Service instance of the device which registered the timer.
+ * @param hTimer The timer handle.
+ */
+typedef DECLCALLBACKTYPE(void, FNTMTIMERSRV,(PPDMSRVINS pSrvIns, TMTIMERHANDLE hTimer));
+/** Pointer to a service timer callback function. */
+typedef FNTMTIMERSRV *PFNTMTIMERSRV;
+
+/**
+ * Internal timer callback function.
+ *
+ * @param pVM The cross context VM structure.
+ * @param hTimer The timer handle.
+ * @param pvUser User argument specified upon timer creation.
+ */
+typedef DECLCALLBACKTYPE(void, FNTMTIMERINT,(PVM pVM, TMTIMERHANDLE hTimer, void *pvUser));
+/** Pointer to internal timer callback function. */
+typedef FNTMTIMERINT *PFNTMTIMERINT;
+
+/**
+ * External timer callback function.
+ *
+ * @param pvUser User argument as specified when the timer was created.
+ */
+typedef DECLCALLBACKTYPE(void, FNTMTIMEREXT,(void *pvUser));
+/** Pointer to an external timer callback function. */
+typedef FNTMTIMEREXT *PFNTMTIMEREXT;
+
+VMMDECL(int) TMTimerLock(PVMCC pVM, TMTIMERHANDLE hTimer, int rcBusy);
+VMMDECL(void) TMTimerUnlock(PVMCC pVM, TMTIMERHANDLE hTimer);
+VMMDECL(bool) TMTimerIsLockOwner(PVMCC pVM, TMTIMERHANDLE hTimer);
+VMMDECL(int) TMTimerSet(PVMCC pVM, TMTIMERHANDLE hTimer, uint64_t u64Expire);
+VMMDECL(int) TMTimerSetRelative(PVMCC pVM, TMTIMERHANDLE hTimer, uint64_t cTicksToNext, uint64_t *pu64Now);
+VMMDECL(int) TMTimerSetFrequencyHint(PVMCC pVM, TMTIMERHANDLE hTimer, uint32_t uHz);
+VMMDECL(uint64_t) TMTimerGet(PVMCC pVM, TMTIMERHANDLE hTimer);
+VMMDECL(int) TMTimerStop(PVMCC pVM, TMTIMERHANDLE hTimer);
+VMMDECL(bool) TMTimerIsActive(PVMCC pVM, TMTIMERHANDLE hTimer);
+
+VMMDECL(int) TMTimerSetMillies(PVMCC pVM, TMTIMERHANDLE hTimer, uint32_t cMilliesToNext);
+VMMDECL(int) TMTimerSetMicro(PVMCC pVM, TMTIMERHANDLE hTimer, uint64_t cMicrosToNext);
+VMMDECL(int) TMTimerSetNano(PVMCC pVM, TMTIMERHANDLE hTimer, uint64_t cNanosToNext);
+VMMDECL(uint64_t) TMTimerGetNano(PVMCC pVM, TMTIMERHANDLE hTimer);
+VMMDECL(uint64_t) TMTimerGetMicro(PVMCC pVM, TMTIMERHANDLE hTimer);
+VMMDECL(uint64_t) TMTimerGetMilli(PVMCC pVM, TMTIMERHANDLE hTimer);
+VMMDECL(uint64_t) TMTimerGetFreq(PVMCC pVM, TMTIMERHANDLE hTimer);
+VMMDECL(uint64_t) TMTimerGetExpire(PVMCC pVM, TMTIMERHANDLE hTimer);
+VMMDECL(uint64_t) TMTimerToNano(PVMCC pVM, TMTIMERHANDLE hTimer, uint64_t cTicks);
+VMMDECL(uint64_t) TMTimerToMicro(PVMCC pVM, TMTIMERHANDLE hTimer, uint64_t cTicks);
+VMMDECL(uint64_t) TMTimerToMilli(PVMCC pVM, TMTIMERHANDLE hTimer, uint64_t cTicks);
+VMMDECL(uint64_t) TMTimerFromNano(PVMCC pVM, TMTIMERHANDLE hTimer, uint64_t cNanoSecs);
+VMMDECL(uint64_t) TMTimerFromMicro(PVMCC pVM, TMTIMERHANDLE hTimer, uint64_t cMicroSecs);
+VMMDECL(uint64_t) TMTimerFromMilli(PVMCC pVM, TMTIMERHANDLE hTimer, uint64_t cMilliSecs);
+
+VMMDECL(bool) TMTimerPollBool(PVMCC pVM, PVMCPUCC pVCpu);
+VMM_INT_DECL(void) TMTimerPollVoid(PVMCC pVM, PVMCPUCC pVCpu);
+VMM_INT_DECL(uint64_t) TMTimerPollGIP(PVMCC pVM, PVMCPUCC pVCpu, uint64_t *pu64Delta);
+/** @} */
+
+
+/** @defgroup grp_tm_r3 The TM Host Context Ring-3 API
+ * @{
+ */
+VMM_INT_DECL(int) TMR3Init(PVM pVM);
+VMM_INT_DECL(int) TMR3InitFinalize(PVM pVM);
+VMM_INT_DECL(void) TMR3Relocate(PVM pVM, RTGCINTPTR offDelta);
+VMM_INT_DECL(int) TMR3Term(PVM pVM);
+VMM_INT_DECL(void) TMR3Reset(PVM pVM);
+VMM_INT_DECL(int) TMR3TimerCreateDevice(PVM pVM, PPDMDEVINS pDevIns, TMCLOCK enmClock, PFNTMTIMERDEV pfnCallback,
+ void *pvUser, uint32_t fFlags, const char *pszName, PTMTIMERHANDLE phTimer);
+VMM_INT_DECL(int) TMR3TimerCreateUsb(PVM pVM, PPDMUSBINS pUsbIns, TMCLOCK enmClock, PFNTMTIMERUSB pfnCallback,
+ void *pvUser, uint32_t fFlags, const char *pszName, PTMTIMERHANDLE phTimer);
+VMM_INT_DECL(int) TMR3TimerCreateDriver(PVM pVM, PPDMDRVINS pDrvIns, TMCLOCK enmClock, PFNTMTIMERDRV pfnCallback,
+ void *pvUser, uint32_t fFlags, const char *pszName, PTMTIMERHANDLE phTimer);
+VMMR3DECL(int) TMR3TimerCreate(PVM pVM, TMCLOCK enmClock, PFNTMTIMERINT pfnCallback, void *pvUser, uint32_t fFlags,
+ const char *pszName, PTMTIMERHANDLE phTimer);
+VMMR3DECL(int) TMR3TimerDestroy(PVM pVM, TMTIMERHANDLE hTimer);
+VMM_INT_DECL(int) TMR3TimerDestroyDevice(PVM pVM, PPDMDEVINS pDevIns);
+VMM_INT_DECL(int) TMR3TimerDestroyUsb(PVM pVM, PPDMUSBINS pUsbIns);
+VMM_INT_DECL(int) TMR3TimerDestroyDriver(PVM pVM, PPDMDRVINS pDrvIns);
+VMMR3DECL(int) TMR3TimerSave(PVMCC pVM, TMTIMERHANDLE hTimer, PSSMHANDLE pSSM);
+VMMR3DECL(int) TMR3TimerLoad(PVMCC pVM, TMTIMERHANDLE hTimer, PSSMHANDLE pSSM);
+VMMR3DECL(int) TMR3TimerSkip(PSSMHANDLE pSSM, bool *pfActive);
+VMMR3DECL(int) TMR3TimerSetCritSect(PVMCC pVM, TMTIMERHANDLE hTimer, PPDMCRITSECT pCritSect);
+VMMR3DECL(void) TMR3TimerQueuesDo(PVM pVM);
+VMMR3_INT_DECL(void) TMR3VirtualSyncFF(PVM pVM, PVMCPU pVCpu);
+VMMR3_INT_DECL(PRTTIMESPEC) TMR3UtcNow(PVM pVM, PRTTIMESPEC pTime);
+
+VMMR3_INT_DECL(int) TMR3CpuTickParavirtEnable(PVM pVM);
+VMMR3_INT_DECL(int) TMR3CpuTickParavirtDisable(PVM pVM);
+VMMR3_INT_DECL(bool) TMR3CpuTickIsFixedRateMonotonic(PVM pVM, bool fWithParavirtEnabled);
+/** @} */
+
+
+/** @defgroup grp_tm_r0 The TM Host Context Ring-0 API
+ * @{
+ */
+VMMR0_INT_DECL(void) TMR0InitPerVMData(PGVM pGVM);
+VMMR0_INT_DECL(void) TMR0CleanupVM(PGVM pGVM);
+VMMR0_INT_DECL(int) TMR0TimerQueueGrow(PGVM pGVM, uint32_t idxQueue, uint32_t cMinTimers);
+/** @} */
+
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !VBOX_INCLUDED_vmm_tm_h */
+
diff --git a/include/VBox/vmm/trpm.h b/include/VBox/vmm/trpm.h
new file mode 100644
index 00000000..0e23dd5b
--- /dev/null
+++ b/include/VBox/vmm/trpm.h
@@ -0,0 +1,102 @@
+/** @file
+ * TRPM - The Trap Monitor.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vmm_trpm_h
+#define VBOX_INCLUDED_vmm_trpm_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/types.h>
+#include <iprt/x86.h>
+
+
+RT_C_DECLS_BEGIN
+/** @defgroup grp_trpm The Trap Monitor API
+ * @ingroup grp_vmm
+ * @{
+ */
+
+/**
+ * TRPM event type.
+ */
+typedef enum
+{
+ TRPM_TRAP = 0,
+ TRPM_HARDWARE_INT = 1,
+ TRPM_SOFTWARE_INT = 2,
+ /** The usual 32-bit paranoia. */
+ TRPM_32BIT_HACK = 0x7fffffff
+} TRPMEVENT;
+/** Pointer to a TRPM event type. */
+typedef TRPMEVENT *PTRPMEVENT;
+/** Pointer to a const TRPM event type. */
+typedef TRPMEVENT const *PCTRPMEVENT;
+
+VMMDECL(int) TRPMQueryTrap(PVMCPU pVCpu, uint8_t *pu8TrapNo, PTRPMEVENT penmType);
+VMMDECL(uint8_t) TRPMGetTrapNo(PVMCPU pVCpu);
+VMMDECL(uint32_t) TRPMGetErrorCode(PVMCPU pVCpu);
+VMMDECL(RTGCUINTPTR) TRPMGetFaultAddress(PVMCPU pVCpu);
+VMMDECL(uint8_t) TRPMGetInstrLength(PVMCPU pVCpu);
+VMMDECL(bool) TRPMIsTrapDueToIcebp(PVMCPU pVCpu);
+VMMDECL(int) TRPMResetTrap(PVMCPU pVCpu);
+VMMDECL(int) TRPMAssertTrap(PVMCPUCC pVCpu, uint8_t u8TrapNo, TRPMEVENT enmType);
+VMMDECL(int) TRPMAssertXcptPF(PVMCPUCC pVCpu, RTGCUINTPTR uCR2, uint32_t uErrorCode);
+VMMDECL(void) TRPMSetErrorCode(PVMCPU pVCpu, uint32_t uErrorCode);
+VMMDECL(void) TRPMSetFaultAddress(PVMCPU pVCpu, RTGCUINTPTR uCR2);
+VMMDECL(void) TRPMSetInstrLength(PVMCPU pVCpu, uint8_t cbInstr);
+VMMDECL(void) TRPMSetTrapDueToIcebp(PVMCPU pVCpu);
+VMMDECL(bool) TRPMIsSoftwareInterrupt(PVMCPU pVCpu);
+VMMDECL(bool) TRPMHasTrap(PVMCPU pVCpu);
+VMMDECL(int) TRPMQueryTrapAll(PVMCPU pVCpu, uint8_t *pu8TrapNo, PTRPMEVENT pEnmType, uint32_t *puErrorCode,
+ PRTGCUINTPTR puCR2, uint8_t *pcbInstr, bool *pfIcebp);
+
+#ifdef IN_RING3
+/** @defgroup grp_trpm_r3 TRPM Host Context Ring 3 API
+ * @{
+ */
+VMMR3DECL(int) TRPMR3Init(PVM pVM);
+VMMR3DECL(void) TRPMR3Relocate(PVM pVM, RTGCINTPTR offDelta);
+VMMR3DECL(void) TRPMR3ResetCpu(PVMCPU pVCpu);
+VMMR3DECL(void) TRPMR3Reset(PVM pVM);
+VMMR3DECL(int) TRPMR3Term(PVM pVM);
+VMMR3DECL(int) TRPMR3InjectEvent(PVM pVM, PVMCPU pVCpu, TRPMEVENT enmEvent, bool *pfInjected);
+/** @} */
+#endif
+
+/** @} */
+RT_C_DECLS_END
+
+#endif /* !VBOX_INCLUDED_vmm_trpm_h */
diff --git a/include/VBox/vmm/trpm.mac b/include/VBox/vmm/trpm.mac
new file mode 100644
index 00000000..6e1c1cd6
--- /dev/null
+++ b/include/VBox/vmm/trpm.mac
@@ -0,0 +1,57 @@
+;; @file
+; TRPM - The Trap Monitor.
+;
+
+;
+; Copyright (C) 2006-2022 Oracle and/or its affiliates.
+;
+; This file is part of VirtualBox base platform packages, as
+; available from https://www.virtualbox.org.
+;
+; This program is free software; you can redistribute it and/or
+; modify it under the terms of the GNU General Public License
+; as published by the Free Software Foundation, in version 3 of the
+; License.
+;
+; This program is distributed in the hope that it will be useful, but
+; WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with this program; if not, see <https://www.gnu.org/licenses>.
+;
+; The contents of this file may alternatively be used under the terms
+; of the Common Development and Distribution License Version 1.0
+; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+; in the VirtualBox 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.
+;
+; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+;
+
+%ifndef ___VBox_vmm_trpm_mac__
+%define ___VBox_vmm_trpm_mac__
+
+
+;/**
+; * TRPM event type
+; */
+;/** Note: must match trpm.mac! */
+;typedef enum
+;{
+; TRPM_TRAP = 0,
+; TRPM_HARDWARE_INT = 1,
+; TRPM_SOFTWARE_INT = 2,
+; /** The usual 32-bit paranoia. */
+; TRPM_32BIT_HACK = 0x7fffffff
+;} TRPMEVENT;
+
+%define TRPM_TRAP 0
+%define TRPM_HARDWARE_INT 1
+%define TRPM_SOFTWARE_INT 2
+%endif
+
diff --git a/include/VBox/vmm/uvm.h b/include/VBox/vmm/uvm.h
new file mode 100644
index 00000000..2edc65db
--- /dev/null
+++ b/include/VBox/vmm/uvm.h
@@ -0,0 +1,195 @@
+/** @file
+ * GVM - The Global VM Data.
+ */
+
+/*
+ * Copyright (C) 2007-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vmm_uvm_h
+#define VBOX_INCLUDED_vmm_uvm_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/types.h>
+#include <iprt/assert.h>
+
+/** @addtogroup grp_vm
+ * @{ */
+
+
+/**
+ * Per virtual CPU ring-3 (user mode) data.
+ */
+typedef struct UVMCPU
+{
+ /** Pointer to the UVM structure. */
+ PUVM pUVM;
+ /** Pointer to the VM structure. */
+ PVM pVM;
+ /** Pointer to the VMCPU structure. */
+ PVMCPU pVCpu;
+ /** The virtual CPU ID. */
+ RTCPUID idCpu;
+ /** Alignment padding. */
+ uint8_t abAlignment0[HC_ARCH_BITS == 32 ? 16 : 4];
+
+ /** The VM internal data. */
+ union
+ {
+#ifdef VMM_INCLUDED_SRC_include_VMInternal_h
+ struct VMINTUSERPERVMCPU s;
+#endif
+ uint8_t padding[512];
+ } vm;
+
+ /** The DBGF data. */
+ union
+ {
+#ifdef VMM_INCLUDED_SRC_include_DBGFInternal_h
+ struct DBGFUSERPERVMCPU s;
+#endif
+ uint8_t padding[64];
+ } dbgf;
+
+} UVMCPU;
+AssertCompileMemberAlignment(UVMCPU, vm, 32);
+
+
+/**
+ * The ring-3 (user mode) VM structure.
+ *
+ * This structure is similar to VM and GVM except that it resides in swappable
+ * user memory. The main purpose is to assist bootstrapping, where it allows us
+ * to start EMT much earlier and gives PDMLdr somewhere to put it's VMMR0 data.
+ * It is also a nice place to put big things that are user mode only.
+ */
+typedef struct UVM
+{
+ /** Magic / eye-catcher (UVM_MAGIC). */
+ uint32_t u32Magic;
+ /** The number of virtual CPUs. */
+ uint32_t cCpus;
+ /** The ring-3 mapping of the shared VM structure. */
+ PVM pVM;
+ /** Pointer to the next VM.
+ * We keep a per process list of VM for the event that a process could
+ * contain more than one VM.
+ * @todo move this into vm.s!
+ */
+ struct UVM *pNext;
+
+ /** Pointer to the optional method table provided by the VMM user. */
+ PCVMM2USERMETHODS pVmm2UserMethods;
+
+#if HC_ARCH_BITS == 32
+ /** Align the next member on a 32 byte boundary. */
+ uint8_t abAlignment0[HC_ARCH_BITS == 32 ? 12 : 0];
+#endif
+
+ /** The VM internal data. */
+ union
+ {
+#ifdef VMM_INCLUDED_SRC_include_VMInternal_h
+ struct VMINTUSERPERVM s;
+#endif
+ uint8_t padding[512];
+ } vm;
+
+ /** The MM data. */
+ union
+ {
+#ifdef VMM_INCLUDED_SRC_include_MMInternal_h
+ struct MMUSERPERVM s;
+#endif
+ uint8_t padding[32];
+ } mm;
+
+ /** The PDM data. */
+ union
+ {
+#ifdef VMM_INCLUDED_SRC_include_PDMInternal_h
+ struct PDMUSERPERVM s;
+#endif
+ uint8_t padding[256];
+ } pdm;
+
+ /** The STAM data. */
+ union
+ {
+#ifdef VMM_INCLUDED_SRC_include_STAMInternal_h
+ struct STAMUSERPERVM s;
+#endif
+ uint8_t padding[30208];
+ } stam;
+
+ /** The DBGF data. */
+ union
+ {
+#ifdef VMM_INCLUDED_SRC_include_DBGFInternal_h
+ struct DBGFUSERPERVM s;
+#endif
+ uint8_t padding[1024];
+ } dbgf;
+
+ /** Per virtual CPU data. */
+ UVMCPU aCpus[1];
+} UVM;
+AssertCompileMemberAlignment(UVM, vm, 32);
+AssertCompileMemberAlignment(UVM, mm, 32);
+AssertCompileMemberAlignment(UVM, pdm, 32);
+AssertCompileMemberAlignment(UVM, stam, 32);
+AssertCompileMemberAlignment(UVM, aCpus, 32);
+
+/** The UVM::u32Magic value (Brad Mehldau). */
+#define UVM_MAGIC 0x19700823
+
+/** @def UVM_ASSERT_VALID_EXT_RETURN
+ * Asserts a user mode VM handle is valid for external access.
+ */
+#define UVM_ASSERT_VALID_EXT_RETURN(a_pUVM, a_rc) \
+ AssertMsgReturn( RT_VALID_ALIGNED_PTR(a_pUVM, PAGE_SIZE) \
+ && (a_pUVM)->u32Magic == UVM_MAGIC, \
+ ("a_pUVM=%p u32Magic=%#x\n", (a_pUVM), \
+ RT_VALID_ALIGNED_PTR(a_pUVM, PAGE_SIZE) ? (a_pUVM)->u32Magic : 0), \
+ (a_rc))
+/** @def UVM_ASSERT_VALID_EXT_RETURN
+ * Asserts a user mode VM handle is valid for external access.
+ */
+#define UVM_ASSERT_VALID_EXT_RETURN_VOID(a_pUVM) \
+ AssertMsgReturnVoid( RT_VALID_ALIGNED_PTR(a_pUVM, PAGE_SIZE) \
+ && (a_pUVM)->u32Magic == UVM_MAGIC, \
+ ("a_pUVM=%p u32Magic=%#x\n", (a_pUVM), \
+ RT_VALID_ALIGNED_PTR(a_pUVM, PAGE_SIZE) ? (a_pUVM)->u32Magic : 0))
+
+/** @} */
+#endif /* !VBOX_INCLUDED_vmm_uvm_h */
+
diff --git a/include/VBox/vmm/vm.h b/include/VBox/vmm/vm.h
new file mode 100644
index 00000000..2ebdda94
--- /dev/null
+++ b/include/VBox/vmm/vm.h
@@ -0,0 +1,1519 @@
+/** @file
+ * VM - The Virtual Machine, data.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vmm_vm_h
+#define VBOX_INCLUDED_vmm_vm_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#ifndef VBOX_FOR_DTRACE_LIB
+# ifndef USING_VMM_COMMON_DEFS
+# error "Compile job does not include VMM_COMMON_DEFS from src/VBox/VMM/Config.kmk - make sure you really need to include this file!"
+# endif
+# include <iprt/param.h>
+# include <VBox/param.h>
+# include <VBox/types.h>
+# include <VBox/vmm/cpum.h>
+# include <VBox/vmm/stam.h>
+# include <VBox/vmm/vmapi.h>
+# include <VBox/vmm/vmm.h>
+# include <VBox/sup.h>
+#else
+# pragma D depends_on library vbox-types.d
+# pragma D depends_on library CPUMInternal.d
+# define VMM_INCLUDED_SRC_include_CPUMInternal_h
+#endif
+
+
+
+/** @defgroup grp_vm The Virtual Machine
+ * @ingroup grp_vmm
+ * @{
+ */
+
+/**
+ * The state of a Virtual CPU.
+ *
+ * The basic state indicated here is whether the CPU has been started or not. In
+ * addition, there are sub-states when started for assisting scheduling (GVMM
+ * mostly).
+ *
+ * The transition out of the STOPPED state is done by a vmR3PowerOn.
+ * The transition back to the STOPPED state is done by vmR3PowerOff.
+ *
+ * (Alternatively we could let vmR3PowerOn start CPU 0 only and let the SPIP
+ * handling switch on the other CPUs. Then vmR3Reset would stop all but CPU 0.)
+ */
+typedef enum VMCPUSTATE
+{
+ /** The customary invalid zero. */
+ VMCPUSTATE_INVALID = 0,
+
+ /** Virtual CPU has not yet been started. */
+ VMCPUSTATE_STOPPED,
+
+ /** CPU started. */
+ VMCPUSTATE_STARTED,
+ /** CPU started in HM context. */
+ VMCPUSTATE_STARTED_HM,
+ /** Executing guest code and can be poked (RC or STI bits of HM). */
+ VMCPUSTATE_STARTED_EXEC,
+ /** Executing guest code using NEM. */
+ VMCPUSTATE_STARTED_EXEC_NEM,
+ VMCPUSTATE_STARTED_EXEC_NEM_WAIT,
+ VMCPUSTATE_STARTED_EXEC_NEM_CANCELED,
+ /** Halted. */
+ VMCPUSTATE_STARTED_HALTED,
+
+ /** The end of valid virtual CPU states. */
+ VMCPUSTATE_END,
+
+ /** Ensure 32-bit type. */
+ VMCPUSTATE_32BIT_HACK = 0x7fffffff
+} VMCPUSTATE;
+
+/** Enables 64-bit FFs. */
+#define VMCPU_WITH_64_BIT_FFS
+
+
+/**
+ * The cross context virtual CPU structure.
+ *
+ * Run 'kmk run-struct-tests' (from src/VBox/VMM if you like) after updating!
+ */
+typedef struct VMCPU
+{
+ /** @name Volatile per-cpu data.
+ * @{ */
+ /** Per CPU forced action.
+ * See the VMCPU_FF_* \#defines. Updated atomically. */
+#ifdef VMCPU_WITH_64_BIT_FFS
+ uint64_t volatile fLocalForcedActions;
+#else
+ uint32_t volatile fLocalForcedActions;
+ uint32_t fForLocalForcedActionsExpansion;
+#endif
+ /** The CPU state. */
+ VMCPUSTATE volatile enmState;
+
+ /** Padding up to 64 bytes. */
+ uint8_t abAlignment0[64 - 12];
+ /** @} */
+
+ /** IEM part.
+ * @remarks This comes first as it allows the use of 8-bit immediates for the
+ * first 64 bytes of the structure, reducing code size a wee bit. */
+#ifdef VMM_INCLUDED_SRC_include_IEMInternal_h /* For PDB hacking. */
+ union VMCPUUNIONIEMFULL
+#else
+ union VMCPUUNIONIEMSTUB
+#endif
+ {
+#ifdef VMM_INCLUDED_SRC_include_IEMInternal_h
+ struct IEMCPU s;
+#endif
+ uint8_t padding[32832]; /* multiple of 64 */
+ } iem;
+
+ /** @name Static per-cpu data.
+ * (Putting this after IEM, hoping that it's less frequently used than it.)
+ * @{ */
+ /** Ring-3 Host Context VM Pointer. */
+ PVMR3 pVMR3;
+ /** Ring-0 Host Context VM Pointer, currently used by VTG/dtrace. */
+ RTR0PTR pVCpuR0ForVtg;
+ /** Raw-mode Context VM Pointer. */
+ uint32_t pVMRC;
+ /** Padding for new raw-mode (long mode). */
+ uint32_t pVMRCPadding;
+ /** Pointer to the ring-3 UVMCPU structure. */
+ PUVMCPU pUVCpu;
+ /** The native thread handle. */
+ RTNATIVETHREAD hNativeThread;
+ /** The native R0 thread handle. (different from the R3 handle!) */
+ RTNATIVETHREAD hNativeThreadR0;
+ /** The IPRT thread handle (for VMMDevTesting). */
+ RTTHREAD hThread;
+ /** The CPU ID.
+ * This is the index into the VM::aCpu array. */
+#ifdef IN_RING0
+ VMCPUID idCpuUnsafe;
+#else
+ VMCPUID idCpu;
+#endif
+
+ /** Align the structures below bit on a 64-byte boundary and make sure it starts
+ * at the same offset in both 64-bit and 32-bit builds.
+ *
+ * @remarks The alignments of the members that are larger than 48 bytes should be
+ * 64-byte for cache line reasons. structs containing small amounts of
+ * data could be lumped together at the end with a < 64 byte padding
+ * following it (to grow into and align the struct size).
+ */
+ uint8_t abAlignment1[64 - 6 * (HC_ARCH_BITS == 32 ? 4 : 8) - 8 - 4];
+ /** @} */
+
+ /** HM part. */
+ union VMCPUUNIONHM
+ {
+#ifdef VMM_INCLUDED_SRC_include_HMInternal_h
+ struct HMCPU s;
+#endif
+ uint8_t padding[9984]; /* multiple of 64 */
+ } hm;
+
+ /** NEM part. */
+ union VMCPUUNIONNEM
+ {
+#ifdef VMM_INCLUDED_SRC_include_NEMInternal_h
+ struct NEMCPU s;
+#endif
+ uint8_t padding[4608]; /* multiple of 64 */
+ } nem;
+
+ /** TRPM part. */
+ union VMCPUUNIONTRPM
+ {
+#ifdef VMM_INCLUDED_SRC_include_TRPMInternal_h
+ struct TRPMCPU s;
+#endif
+ uint8_t padding[128]; /* multiple of 64 */
+ } trpm;
+
+ /** TM part. */
+ union VMCPUUNIONTM
+ {
+#ifdef VMM_INCLUDED_SRC_include_TMInternal_h
+ struct TMCPU s;
+#endif
+ uint8_t padding[5760]; /* multiple of 64 */
+ } tm;
+
+ /** VMM part. */
+ union VMCPUUNIONVMM
+ {
+#ifdef VMM_INCLUDED_SRC_include_VMMInternal_h
+ struct VMMCPU s;
+#endif
+ uint8_t padding[9536]; /* multiple of 64 */
+ } vmm;
+
+ /** PDM part. */
+ union VMCPUUNIONPDM
+ {
+#ifdef VMM_INCLUDED_SRC_include_PDMInternal_h
+ struct PDMCPU s;
+#endif
+ uint8_t padding[256]; /* multiple of 64 */
+ } pdm;
+
+ /** IOM part. */
+ union VMCPUUNIONIOM
+ {
+#ifdef VMM_INCLUDED_SRC_include_IOMInternal_h
+ struct IOMCPU s;
+#endif
+ uint8_t padding[512]; /* multiple of 64 */
+ } iom;
+
+ /** DBGF part.
+ * @todo Combine this with other tiny structures. */
+ union VMCPUUNIONDBGF
+ {
+#ifdef VMM_INCLUDED_SRC_include_DBGFInternal_h
+ struct DBGFCPU s;
+#endif
+ uint8_t padding[512]; /* multiple of 64 */
+ } dbgf;
+
+ /** GIM part. */
+ union VMCPUUNIONGIM
+ {
+#ifdef VMM_INCLUDED_SRC_include_GIMInternal_h
+ struct GIMCPU s;
+#endif
+ uint8_t padding[512]; /* multiple of 64 */
+ } gim;
+
+ /** APIC part. */
+ union VMCPUUNIONAPIC
+ {
+#ifdef VMM_INCLUDED_SRC_include_APICInternal_h
+ struct APICCPU s;
+#endif
+ uint8_t padding[3840]; /* multiple of 64 */
+ } apic;
+
+ /*
+ * Some less frequently used global members that doesn't need to take up
+ * precious space at the head of the structure.
+ */
+
+ /** Trace groups enable flags. */
+ uint32_t fTraceGroups; /* 64 / 44 */
+ /** Number of collisions hashing the ring-0 EMT handle. */
+ uint8_t cEmtHashCollisions;
+ uint8_t abAdHoc[3];
+ /** Profiling samples for use by ad hoc profiling. */
+ STAMPROFILEADV aStatAdHoc[8]; /* size: 40*8 = 320 */
+
+ /** Align the following members on page boundary. */
+ uint8_t abAlignment2[696];
+
+ /** PGM part. */
+ union VMCPUUNIONPGM
+ {
+#ifdef VMM_INCLUDED_SRC_include_PGMInternal_h
+ struct PGMCPU s;
+#endif
+ uint8_t padding[4096 + 28672]; /* multiple of 4096 */
+ } pgm;
+
+ /** CPUM part. */
+ union VMCPUUNIONCPUM
+ {
+#ifdef VMM_INCLUDED_SRC_include_CPUMInternal_h
+ struct CPUMCPU s;
+#endif
+#ifdef VMCPU_INCL_CPUM_GST_CTX
+ /** The guest CPUM context for direct use by execution engines.
+ * This is not for general consumption, but for HM, REM, IEM, and maybe a few
+ * others. The rest will use the function based CPUM API. */
+ CPUMCTX GstCtx;
+#endif
+ uint8_t padding[102400]; /* multiple of 4096 */
+ } cpum;
+
+ /** EM part. */
+ union VMCPUUNIONEM
+ {
+#ifdef VMM_INCLUDED_SRC_include_EMInternal_h
+ struct EMCPU s;
+#endif
+ uint8_t padding[40960]; /* multiple of 4096 */
+ } em;
+
+} VMCPU;
+
+
+#ifndef VBOX_FOR_DTRACE_LIB
+/* Make sure the structure size is aligned on a 16384 boundary for arm64 purposes. */
+AssertCompileSizeAlignment(VMCPU, 16384);
+
+/** @name Operations on VMCPU::enmState
+ * @{ */
+/** Gets the VMCPU state. */
+#define VMCPU_GET_STATE(pVCpu) ( (pVCpu)->enmState )
+/** Sets the VMCPU state. */
+#define VMCPU_SET_STATE(pVCpu, enmNewState) \
+ ASMAtomicWriteU32((uint32_t volatile *)&(pVCpu)->enmState, (enmNewState))
+/** Cmpares and sets the VMCPU state. */
+#define VMCPU_CMPXCHG_STATE(pVCpu, enmNewState, enmOldState) \
+ ASMAtomicCmpXchgU32((uint32_t volatile *)&(pVCpu)->enmState, (enmNewState), (enmOldState))
+/** Checks the VMCPU state. */
+#ifdef VBOX_STRICT
+# define VMCPU_ASSERT_STATE(pVCpu, enmExpectedState) \
+ do { \
+ VMCPUSTATE enmState = VMCPU_GET_STATE(pVCpu); \
+ AssertMsg(enmState == (enmExpectedState), \
+ ("enmState=%d enmExpectedState=%d idCpu=%u\n", \
+ enmState, enmExpectedState, (pVCpu)->idCpu)); \
+ } while (0)
+
+# define VMCPU_ASSERT_STATE_2(pVCpu, enmExpectedState, a_enmExpectedState2) \
+ do { \
+ VMCPUSTATE enmState = VMCPU_GET_STATE(pVCpu); \
+ AssertMsg( enmState == (enmExpectedState) \
+ || enmState == (a_enmExpectedState2), \
+ ("enmState=%d enmExpectedState=%d enmExpectedState2=%d idCpu=%u\n", \
+ enmState, enmExpectedState, a_enmExpectedState2, (pVCpu)->idCpu)); \
+ } while (0)
+#else
+# define VMCPU_ASSERT_STATE(pVCpu, enmExpectedState) do { } while (0)
+# define VMCPU_ASSERT_STATE_2(pVCpu, enmExpectedState, a_enmExpectedState2) do { } while (0)
+#endif
+/** Tests if the state means that the CPU is started. */
+#define VMCPUSTATE_IS_STARTED(enmState) ( (enmState) > VMCPUSTATE_STOPPED )
+/** Tests if the state means that the CPU is stopped. */
+#define VMCPUSTATE_IS_STOPPED(enmState) ( (enmState) == VMCPUSTATE_STOPPED )
+/** @} */
+
+
+/** The name of the raw-mode context VMM Core module. */
+#define VMMRC_MAIN_MODULE_NAME "VMMRC.rc"
+/** The name of the ring-0 context VMM Core module. */
+#define VMMR0_MAIN_MODULE_NAME "VMMR0.r0"
+
+
+/** VM Forced Action Flags.
+ *
+ * Use the VM_FF_SET() and VM_FF_CLEAR() macros to change the force
+ * action mask of a VM.
+ *
+ * Available VM bits:
+ * 0, 1, 5, 6, 7, 13, 14, 15, 16, 17, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30
+ *
+ *
+ * Available VMCPU bits:
+ * 14, 15, 36 to 63
+ *
+ * @todo If we run low on VMCPU, we may consider merging the SELM bits
+ *
+ * @{
+ */
+/** The virtual sync clock has been stopped, go to TM until it has been
+ * restarted... */
+#define VM_FF_TM_VIRTUAL_SYNC RT_BIT_32(VM_FF_TM_VIRTUAL_SYNC_BIT)
+#define VM_FF_TM_VIRTUAL_SYNC_BIT 2
+/** PDM Queues are pending. */
+#define VM_FF_PDM_QUEUES RT_BIT_32(VM_FF_PDM_QUEUES_BIT)
+/** The bit number for VM_FF_PDM_QUEUES. */
+#define VM_FF_PDM_QUEUES_BIT 3
+/** PDM DMA transfers are pending. */
+#define VM_FF_PDM_DMA RT_BIT_32(VM_FF_PDM_DMA_BIT)
+/** The bit number for VM_FF_PDM_DMA. */
+#define VM_FF_PDM_DMA_BIT 4
+/** This action forces the VM to call DBGF so DBGF can service debugger
+ * requests in the emulation thread.
+ * This action flag stays asserted till DBGF clears it.*/
+#define VM_FF_DBGF RT_BIT_32(VM_FF_DBGF_BIT)
+/** The bit number for VM_FF_DBGF. */
+#define VM_FF_DBGF_BIT 8
+/** This action forces the VM to service pending requests from other
+ * thread or requests which must be executed in another context. */
+#define VM_FF_REQUEST RT_BIT_32(VM_FF_REQUEST_BIT)
+#define VM_FF_REQUEST_BIT 9
+/** Check for VM state changes and take appropriate action. */
+#define VM_FF_CHECK_VM_STATE RT_BIT_32(VM_FF_CHECK_VM_STATE_BIT)
+/** The bit number for VM_FF_CHECK_VM_STATE. */
+#define VM_FF_CHECK_VM_STATE_BIT 10
+/** Reset the VM. (postponed) */
+#define VM_FF_RESET RT_BIT_32(VM_FF_RESET_BIT)
+/** The bit number for VM_FF_RESET. */
+#define VM_FF_RESET_BIT 11
+/** EMT rendezvous in VMM. */
+#define VM_FF_EMT_RENDEZVOUS RT_BIT_32(VM_FF_EMT_RENDEZVOUS_BIT)
+/** The bit number for VM_FF_EMT_RENDEZVOUS. */
+#define VM_FF_EMT_RENDEZVOUS_BIT 12
+
+/** PGM needs to allocate handy pages. */
+#define VM_FF_PGM_NEED_HANDY_PAGES RT_BIT_32(VM_FF_PGM_NEED_HANDY_PAGES_BIT)
+#define VM_FF_PGM_NEED_HANDY_PAGES_BIT 18
+/** PGM is out of memory.
+ * Abandon all loops and code paths which can be resumed and get up to the EM
+ * loops. */
+#define VM_FF_PGM_NO_MEMORY RT_BIT_32(VM_FF_PGM_NO_MEMORY_BIT)
+#define VM_FF_PGM_NO_MEMORY_BIT 19
+ /** PGM is about to perform a lightweight pool flush
+ * Guest SMP: all EMT threads should return to ring 3
+ */
+#define VM_FF_PGM_POOL_FLUSH_PENDING RT_BIT_32(VM_FF_PGM_POOL_FLUSH_PENDING_BIT)
+#define VM_FF_PGM_POOL_FLUSH_PENDING_BIT 20
+/** Suspend the VM - debug only. */
+#define VM_FF_DEBUG_SUSPEND RT_BIT_32(VM_FF_DEBUG_SUSPEND_BIT)
+#define VM_FF_DEBUG_SUSPEND_BIT 31
+
+
+/** This action forces the VM to check any pending interrupts on the APIC. */
+#define VMCPU_FF_INTERRUPT_APIC RT_BIT_64(VMCPU_FF_INTERRUPT_APIC_BIT)
+#define VMCPU_FF_INTERRUPT_APIC_BIT 0
+/** This action forces the VM to check any pending interrups on the PIC. */
+#define VMCPU_FF_INTERRUPT_PIC RT_BIT_64(VMCPU_FF_INTERRUPT_PIC_BIT)
+#define VMCPU_FF_INTERRUPT_PIC_BIT 1
+/** This action forces the VM to schedule and run pending timer (TM).
+ * @remarks Don't move - PATM compatibility. */
+#define VMCPU_FF_TIMER RT_BIT_64(VMCPU_FF_TIMER_BIT)
+#define VMCPU_FF_TIMER_BIT 2
+/** This action forces the VM to check any pending NMIs. */
+#define VMCPU_FF_INTERRUPT_NMI RT_BIT_64(VMCPU_FF_INTERRUPT_NMI_BIT)
+#define VMCPU_FF_INTERRUPT_NMI_BIT 3
+/** This action forces the VM to check any pending SMIs. */
+#define VMCPU_FF_INTERRUPT_SMI RT_BIT_64(VMCPU_FF_INTERRUPT_SMI_BIT)
+#define VMCPU_FF_INTERRUPT_SMI_BIT 4
+/** PDM critical section unlocking is pending, process promptly upon return to R3. */
+#define VMCPU_FF_PDM_CRITSECT RT_BIT_64(VMCPU_FF_PDM_CRITSECT_BIT)
+#define VMCPU_FF_PDM_CRITSECT_BIT 5
+/** Special EM internal force flag that is used by EMUnhaltAndWakeUp() to force
+ * the virtual CPU out of the next (/current) halted state. It is not processed
+ * nor cleared by emR3ForcedActions (similar to VMCPU_FF_BLOCK_NMIS), instead it
+ * is cleared the next time EM leaves the HALTED state. */
+#define VMCPU_FF_UNHALT RT_BIT_64(VMCPU_FF_UNHALT_BIT)
+#define VMCPU_FF_UNHALT_BIT 6
+/** Pending IEM action (mask). */
+#define VMCPU_FF_IEM RT_BIT_64(VMCPU_FF_IEM_BIT)
+/** Pending IEM action (bit number). */
+#define VMCPU_FF_IEM_BIT 7
+/** Pending APIC action (bit number). */
+#define VMCPU_FF_UPDATE_APIC_BIT 8
+/** This action forces the VM to update APIC's asynchronously arrived
+ * interrupts as pending interrupts. */
+#define VMCPU_FF_UPDATE_APIC RT_BIT_64(VMCPU_FF_UPDATE_APIC_BIT)
+/** This action forces the VM to service pending requests from other
+ * thread or requests which must be executed in another context. */
+#define VMCPU_FF_REQUEST RT_BIT_64(VMCPU_FF_REQUEST_BIT)
+#define VMCPU_FF_REQUEST_BIT 9
+/** Pending DBGF event (alternative to passing VINF_EM_DBG_EVENT around). */
+#define VMCPU_FF_DBGF RT_BIT_64(VMCPU_FF_DBGF_BIT)
+/** The bit number for VMCPU_FF_DBGF. */
+#define VMCPU_FF_DBGF_BIT 10
+/** Hardware virtualized nested-guest interrupt pending. */
+#define VMCPU_FF_INTERRUPT_NESTED_GUEST RT_BIT_64(VMCPU_FF_INTERRUPT_NESTED_GUEST_BIT)
+#define VMCPU_FF_INTERRUPT_NESTED_GUEST_BIT 11
+/** This action forces PGM to update changes to CR3 when the guest was in HM mode
+ * (when using nested paging). */
+#define VMCPU_FF_HM_UPDATE_CR3 RT_BIT_64(VMCPU_FF_HM_UPDATE_CR3_BIT)
+#define VMCPU_FF_HM_UPDATE_CR3_BIT 12
+/* Bit 13 used to be VMCPU_FF_HM_UPDATE_PAE_PDPES. */
+/** This action forces the VM to resync the page tables before going
+ * back to execute guest code. (GLOBAL FLUSH) */
+#define VMCPU_FF_PGM_SYNC_CR3 RT_BIT_64(VMCPU_FF_PGM_SYNC_CR3_BIT)
+#define VMCPU_FF_PGM_SYNC_CR3_BIT 16
+/** Same as VM_FF_PGM_SYNC_CR3 except that global pages can be skipped.
+ * (NON-GLOBAL FLUSH) */
+#define VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL RT_BIT_64(VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL_BIT)
+#define VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL_BIT 17
+/** Check for pending TLB shootdown actions (deprecated)
+ * Reserved for future HM re-use if necessary / safe.
+ * Consumer: HM */
+#define VMCPU_FF_TLB_SHOOTDOWN_UNUSED RT_BIT_64(VMCPU_FF_TLB_SHOOTDOWN_UNUSED_BIT)
+#define VMCPU_FF_TLB_SHOOTDOWN_UNUSED_BIT 18
+/** Check for pending TLB flush action.
+ * Consumer: HM
+ * @todo rename to VMCPU_FF_HM_TLB_FLUSH */
+#define VMCPU_FF_TLB_FLUSH RT_BIT_64(VMCPU_FF_TLB_FLUSH_BIT)
+/** The bit number for VMCPU_FF_TLB_FLUSH. */
+#define VMCPU_FF_TLB_FLUSH_BIT 19
+/* 20 used to be VMCPU_FF_TRPM_SYNC_IDT (raw-mode only). */
+/* 21 used to be VMCPU_FF_SELM_SYNC_TSS (raw-mode only). */
+/* 22 used to be VMCPU_FF_SELM_SYNC_GDT (raw-mode only). */
+/* 23 used to be VMCPU_FF_SELM_SYNC_LDT (raw-mode only). */
+/* 24 used to be VMCPU_FF_INHIBIT_INTERRUPTS, which moved to CPUMCTX::eflags.uBoth in v7.0.4. */
+/* 25 used to be VMCPU_FF_BLOCK_NMIS, which moved to CPUMCTX::eflags.uBoth in v7.0.4. */
+/** Force return to Ring-3. */
+#define VMCPU_FF_TO_R3 RT_BIT_64(VMCPU_FF_TO_R3_BIT)
+#define VMCPU_FF_TO_R3_BIT 28
+/** Force return to ring-3 to service pending I/O or MMIO write.
+ * This is a backup for mechanism VINF_IOM_R3_IOPORT_COMMIT_WRITE and
+ * VINF_IOM_R3_MMIO_COMMIT_WRITE, allowing VINF_EM_DBG_BREAKPOINT and similar
+ * status codes to be propagated at the same time without loss. */
+#define VMCPU_FF_IOM RT_BIT_64(VMCPU_FF_IOM_BIT)
+#define VMCPU_FF_IOM_BIT 29
+/* 30 used to be VMCPU_FF_CPUM */
+/** VMX-preemption timer expired. */
+#define VMCPU_FF_VMX_PREEMPT_TIMER RT_BIT_64(VMCPU_FF_VMX_PREEMPT_TIMER_BIT)
+#define VMCPU_FF_VMX_PREEMPT_TIMER_BIT 31
+/** Pending MTF (Monitor Trap Flag) event. */
+#define VMCPU_FF_VMX_MTF RT_BIT_64(VMCPU_FF_VMX_MTF_BIT)
+#define VMCPU_FF_VMX_MTF_BIT 32
+/** VMX APIC-write emulation pending.
+ * @todo possible candidate for internal EFLAGS, or maybe just a summary bit
+ * (see also VMCPU_FF_VMX_INT_WINDOW). */
+#define VMCPU_FF_VMX_APIC_WRITE RT_BIT_64(VMCPU_FF_VMX_APIC_WRITE_BIT)
+#define VMCPU_FF_VMX_APIC_WRITE_BIT 33
+/** VMX interrupt-window event pending.
+ *
+ * "Pending" is misleading here, it would be better to say that the event need
+ * to be generated at the next opportunity and that this flag causes it to be
+ * polled for on every instruction boundrary and such.
+ *
+ * @todo Change the IEM side of this to not poll but to track down the places
+ * where it can be generated and set an internal EFLAGS bit that causes it
+ * to be checked out when finishing the current instruction. */
+#define VMCPU_FF_VMX_INT_WINDOW RT_BIT_64(VMCPU_FF_VMX_INT_WINDOW_BIT)
+#define VMCPU_FF_VMX_INT_WINDOW_BIT 34
+/** VMX NMI-window event pending.
+ * Same "pending" comment and todo in VMCPU_FF_VMX_INT_WINDOW. */
+#define VMCPU_FF_VMX_NMI_WINDOW RT_BIT_64(VMCPU_FF_VMX_NMI_WINDOW_BIT)
+#define VMCPU_FF_VMX_NMI_WINDOW_BIT 35
+
+
+/** Externally VM forced actions. Used to quit the idle/wait loop. */
+#define VM_FF_EXTERNAL_SUSPENDED_MASK ( VM_FF_CHECK_VM_STATE | VM_FF_DBGF | VM_FF_REQUEST | VM_FF_EMT_RENDEZVOUS )
+/** Externally VMCPU forced actions. Used to quit the idle/wait loop. */
+#define VMCPU_FF_EXTERNAL_SUSPENDED_MASK ( VMCPU_FF_REQUEST | VMCPU_FF_DBGF )
+
+/** Externally forced VM actions. Used to quit the idle/wait loop. */
+#define VM_FF_EXTERNAL_HALTED_MASK ( VM_FF_CHECK_VM_STATE | VM_FF_DBGF | VM_FF_REQUEST \
+ | VM_FF_PDM_QUEUES | VM_FF_PDM_DMA | VM_FF_EMT_RENDEZVOUS )
+/** Externally forced VMCPU actions. Used to quit the idle/wait loop. */
+#define VMCPU_FF_EXTERNAL_HALTED_MASK ( VMCPU_FF_UPDATE_APIC | VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC \
+ | VMCPU_FF_REQUEST | VMCPU_FF_INTERRUPT_NMI | VMCPU_FF_INTERRUPT_SMI \
+ | VMCPU_FF_UNHALT | VMCPU_FF_TIMER | VMCPU_FF_DBGF \
+ | VMCPU_FF_INTERRUPT_NESTED_GUEST)
+
+/** High priority VM pre-execution actions. */
+#define VM_FF_HIGH_PRIORITY_PRE_MASK ( VM_FF_CHECK_VM_STATE | VM_FF_DBGF | VM_FF_TM_VIRTUAL_SYNC \
+ | VM_FF_DEBUG_SUSPEND | VM_FF_PGM_NEED_HANDY_PAGES | VM_FF_PGM_NO_MEMORY \
+ | VM_FF_EMT_RENDEZVOUS )
+/** High priority VMCPU pre-execution actions. */
+#define VMCPU_FF_HIGH_PRIORITY_PRE_MASK ( VMCPU_FF_TIMER | VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC \
+ | VMCPU_FF_UPDATE_APIC | VMCPU_FF_DBGF \
+ | VMCPU_FF_PGM_SYNC_CR3 | VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL \
+ | VMCPU_FF_INTERRUPT_NESTED_GUEST | VMCPU_FF_VMX_MTF | VMCPU_FF_VMX_APIC_WRITE \
+ | VMCPU_FF_VMX_PREEMPT_TIMER | VMCPU_FF_VMX_NMI_WINDOW | VMCPU_FF_VMX_INT_WINDOW )
+
+/** High priority VM pre raw-mode execution mask. */
+#define VM_FF_HIGH_PRIORITY_PRE_RAW_MASK ( VM_FF_PGM_NEED_HANDY_PAGES | VM_FF_PGM_NO_MEMORY )
+/** High priority VMCPU pre raw-mode execution mask. */
+#define VMCPU_FF_HIGH_PRIORITY_PRE_RAW_MASK ( VMCPU_FF_PGM_SYNC_CR3 | VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL )
+
+/** High priority post-execution actions. */
+#define VM_FF_HIGH_PRIORITY_POST_MASK ( VM_FF_PGM_NO_MEMORY )
+/** High priority post-execution actions. */
+#define VMCPU_FF_HIGH_PRIORITY_POST_MASK ( VMCPU_FF_PDM_CRITSECT | VMCPU_FF_HM_UPDATE_CR3 | VMCPU_FF_IEM | VMCPU_FF_IOM )
+
+/** Normal priority VM post-execution actions. */
+#define VM_FF_NORMAL_PRIORITY_POST_MASK ( VM_FF_CHECK_VM_STATE | VM_FF_DBGF | VM_FF_RESET \
+ | VM_FF_PGM_NO_MEMORY | VM_FF_EMT_RENDEZVOUS)
+/** Normal priority VMCPU post-execution actions. */
+#define VMCPU_FF_NORMAL_PRIORITY_POST_MASK ( VMCPU_FF_DBGF )
+
+/** Normal priority VM actions. */
+#define VM_FF_NORMAL_PRIORITY_MASK ( VM_FF_REQUEST | VM_FF_PDM_QUEUES | VM_FF_PDM_DMA | VM_FF_EMT_RENDEZVOUS)
+/** Normal priority VMCPU actions. */
+#define VMCPU_FF_NORMAL_PRIORITY_MASK ( VMCPU_FF_REQUEST )
+
+/** Flags to clear before resuming guest execution. */
+#define VMCPU_FF_RESUME_GUEST_MASK ( VMCPU_FF_TO_R3 )
+
+
+/** VM flags that cause the REP[|NE|E] STRINS loops to yield immediately. */
+#define VM_FF_HIGH_PRIORITY_POST_REPSTR_MASK ( VM_FF_TM_VIRTUAL_SYNC | VM_FF_PGM_NEED_HANDY_PAGES | VM_FF_PGM_NO_MEMORY \
+ | VM_FF_EMT_RENDEZVOUS | VM_FF_PGM_POOL_FLUSH_PENDING | VM_FF_RESET)
+/** VM flags that cause the REP[|NE|E] STRINS loops to yield. */
+#define VM_FF_YIELD_REPSTR_MASK ( VM_FF_HIGH_PRIORITY_POST_REPSTR_MASK \
+ | VM_FF_PDM_QUEUES | VM_FF_PDM_DMA | VM_FF_DBGF | VM_FF_DEBUG_SUSPEND )
+/** VMCPU flags that cause the REP[|NE|E] STRINS loops to yield immediately. */
+#ifdef IN_RING3
+# define VMCPU_FF_HIGH_PRIORITY_POST_REPSTR_MASK ( VMCPU_FF_PGM_SYNC_CR3 | VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL | VMCPU_FF_DBGF \
+ | VMCPU_FF_VMX_MTF )
+#else
+# define VMCPU_FF_HIGH_PRIORITY_POST_REPSTR_MASK ( VMCPU_FF_TO_R3 | VMCPU_FF_IEM | VMCPU_FF_IOM | VMCPU_FF_PGM_SYNC_CR3 \
+ | VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL | VMCPU_FF_DBGF | VMCPU_FF_VMX_MTF )
+#endif
+/** VMCPU flags that cause the REP[|NE|E] STRINS loops to yield, interrupts
+ * enabled. */
+#define VMCPU_FF_YIELD_REPSTR_MASK ( VMCPU_FF_HIGH_PRIORITY_POST_REPSTR_MASK \
+ | VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_UPDATE_APIC | VMCPU_FF_INTERRUPT_PIC \
+ | VMCPU_FF_INTERRUPT_NMI | VMCPU_FF_INTERRUPT_SMI | VMCPU_FF_PDM_CRITSECT \
+ | VMCPU_FF_TIMER | VMCPU_FF_REQUEST \
+ | VMCPU_FF_INTERRUPT_NESTED_GUEST )
+/** VMCPU flags that cause the REP[|NE|E] STRINS loops to yield, interrupts
+ * disabled. */
+#define VMCPU_FF_YIELD_REPSTR_NOINT_MASK ( VMCPU_FF_YIELD_REPSTR_MASK \
+ & ~( VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_UPDATE_APIC | VMCPU_FF_INTERRUPT_PIC \
+ | VMCPU_FF_INTERRUPT_NESTED_GUEST) )
+
+/** VM Flags that cause the HM loops to go back to ring-3. */
+#define VM_FF_HM_TO_R3_MASK ( VM_FF_TM_VIRTUAL_SYNC | VM_FF_PGM_NEED_HANDY_PAGES | VM_FF_PGM_NO_MEMORY \
+ | VM_FF_PDM_QUEUES | VM_FF_EMT_RENDEZVOUS)
+/** VMCPU Flags that cause the HM loops to go back to ring-3. */
+#define VMCPU_FF_HM_TO_R3_MASK ( VMCPU_FF_TO_R3 | VMCPU_FF_TIMER | VMCPU_FF_PDM_CRITSECT \
+ | VMCPU_FF_IEM | VMCPU_FF_IOM)
+
+/** High priority ring-0 VM pre HM-mode execution mask. */
+#define VM_FF_HP_R0_PRE_HM_MASK (VM_FF_HM_TO_R3_MASK | VM_FF_REQUEST | VM_FF_PGM_POOL_FLUSH_PENDING | VM_FF_PDM_DMA)
+/** High priority ring-0 VMCPU pre HM-mode execution mask. */
+#define VMCPU_FF_HP_R0_PRE_HM_MASK ( VMCPU_FF_HM_TO_R3_MASK | VMCPU_FF_PGM_SYNC_CR3 \
+ | VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL | VMCPU_FF_REQUEST \
+ | VMCPU_FF_VMX_APIC_WRITE | VMCPU_FF_VMX_MTF | VMCPU_FF_VMX_PREEMPT_TIMER)
+/** High priority ring-0 VM pre HM-mode execution mask, single stepping. */
+#define VM_FF_HP_R0_PRE_HM_STEP_MASK (VM_FF_HP_R0_PRE_HM_MASK & ~( VM_FF_TM_VIRTUAL_SYNC | VM_FF_PDM_QUEUES \
+ | VM_FF_EMT_RENDEZVOUS | VM_FF_REQUEST \
+ | VM_FF_PDM_DMA) )
+/** High priority ring-0 VMCPU pre HM-mode execution mask, single stepping. */
+#define VMCPU_FF_HP_R0_PRE_HM_STEP_MASK (VMCPU_FF_HP_R0_PRE_HM_MASK & ~( VMCPU_FF_TO_R3 | VMCPU_FF_TIMER \
+ | VMCPU_FF_PDM_CRITSECT | VMCPU_FF_REQUEST) )
+
+/** All the VMX nested-guest flags. */
+#define VMCPU_FF_VMX_ALL_MASK ( VMCPU_FF_VMX_PREEMPT_TIMER | VMCPU_FF_VMX_MTF | VMCPU_FF_VMX_APIC_WRITE \
+ | VMCPU_FF_VMX_INT_WINDOW | VMCPU_FF_VMX_NMI_WINDOW )
+
+/** All the forced VM flags. */
+#define VM_FF_ALL_MASK (UINT32_MAX)
+/** All the forced VMCPU flags. */
+#define VMCPU_FF_ALL_MASK (UINT32_MAX)
+
+/** All the forced VM flags except those related to raw-mode and hardware
+ * assisted execution. */
+#define VM_FF_ALL_REM_MASK (~(VM_FF_HIGH_PRIORITY_PRE_RAW_MASK) | VM_FF_PGM_NEED_HANDY_PAGES | VM_FF_PGM_NO_MEMORY)
+/** All the forced VMCPU flags except those related to raw-mode and hardware
+ * assisted execution. */
+#define VMCPU_FF_ALL_REM_MASK (~(VMCPU_FF_HIGH_PRIORITY_PRE_RAW_MASK | VMCPU_FF_PDM_CRITSECT | VMCPU_FF_TLB_FLUSH))
+/** @} */
+
+/** @def VM_FF_SET
+ * Sets a single force action flag.
+ *
+ * @param pVM The cross context VM structure.
+ * @param fFlag The flag to set.
+ */
+#define VM_FF_SET(pVM, fFlag) do { \
+ AssertCompile(RT_IS_POWER_OF_TWO(fFlag)); \
+ AssertCompile((fFlag) == RT_BIT_32(fFlag##_BIT)); \
+ ASMAtomicOrU32(&(pVM)->fGlobalForcedActions, (fFlag)); \
+ } while (0)
+
+/** @def VMCPU_FF_SET
+ * Sets a single force action flag for the given VCPU.
+ *
+ * @param pVCpu The cross context virtual CPU structure.
+ * @param fFlag The flag to set.
+ * @sa VMCPU_FF_SET_MASK
+ */
+#ifdef VMCPU_WITH_64_BIT_FFS
+# define VMCPU_FF_SET(pVCpu, fFlag) do { \
+ AssertCompile(RT_IS_POWER_OF_TWO(fFlag)); \
+ AssertCompile((fFlag) == RT_BIT_64(fFlag##_BIT)); \
+ ASMAtomicBitSet(&(pVCpu)->fLocalForcedActions, fFlag##_BIT); \
+ } while (0)
+#else
+# define VMCPU_FF_SET(pVCpu, fFlag) do { \
+ AssertCompile(RT_IS_POWER_OF_TWO(fFlag)); \
+ AssertCompile((fFlag) == RT_BIT_32(fFlag##_BIT)); \
+ ASMAtomicOrU32(&(pVCpu)->fLocalForcedActions, (fFlag)); \
+ } while (0)
+#endif
+
+/** @def VMCPU_FF_SET_MASK
+ * Sets a two or more force action flag for the given VCPU.
+ *
+ * @param pVCpu The cross context virtual CPU structure.
+ * @param fFlags The flags to set.
+ * @sa VMCPU_FF_SET
+ */
+#ifdef VMCPU_WITH_64_BIT_FFS
+# if ARCH_BITS > 32
+# define VMCPU_FF_SET_MASK(pVCpu, fFlags) \
+ do { ASMAtomicOrU64(&pVCpu->fLocalForcedActions, (fFlags)); } while (0)
+# else
+# define VMCPU_FF_SET_MASK(pVCpu, fFlags) do { \
+ if (!((fFlags) >> 32)) ASMAtomicOrU32((uint32_t volatile *)&pVCpu->fLocalForcedActions, (uint32_t)(fFlags)); \
+ else ASMAtomicOrU64(&pVCpu->fLocalForcedActions, (fFlags)); \
+ } while (0)
+# endif
+#else
+# define VMCPU_FF_SET_MASK(pVCpu, fFlags) \
+ do { ASMAtomicOrU32(&pVCpu->fLocalForcedActions, (fFlags)); } while (0)
+#endif
+
+/** @def VM_FF_CLEAR
+ * Clears a single force action flag.
+ *
+ * @param pVM The cross context VM structure.
+ * @param fFlag The flag to clear.
+ */
+#define VM_FF_CLEAR(pVM, fFlag) do { \
+ AssertCompile(RT_IS_POWER_OF_TWO(fFlag)); \
+ AssertCompile((fFlag) == RT_BIT_32(fFlag##_BIT)); \
+ ASMAtomicAndU32(&(pVM)->fGlobalForcedActions, ~(fFlag)); \
+ } while (0)
+
+/** @def VMCPU_FF_CLEAR
+ * Clears a single force action flag for the given VCPU.
+ *
+ * @param pVCpu The cross context virtual CPU structure.
+ * @param fFlag The flag to clear.
+ */
+#ifdef VMCPU_WITH_64_BIT_FFS
+# define VMCPU_FF_CLEAR(pVCpu, fFlag) do { \
+ AssertCompile(RT_IS_POWER_OF_TWO(fFlag)); \
+ AssertCompile((fFlag) == RT_BIT_64(fFlag##_BIT)); \
+ ASMAtomicBitClear(&(pVCpu)->fLocalForcedActions, fFlag##_BIT); \
+ } while (0)
+#else
+# define VMCPU_FF_CLEAR(pVCpu, fFlag) do { \
+ AssertCompile(RT_IS_POWER_OF_TWO(fFlag)); \
+ AssertCompile((fFlag) == RT_BIT_32(fFlag##_BIT)); \
+ ASMAtomicAndU32(&(pVCpu)->fLocalForcedActions, ~(fFlag)); \
+ } while (0)
+#endif
+
+/** @def VMCPU_FF_CLEAR_MASK
+ * Clears two or more force action flags for the given VCPU.
+ *
+ * @param pVCpu The cross context virtual CPU structure.
+ * @param fFlags The flags to clear.
+ */
+#ifdef VMCPU_WITH_64_BIT_FFS
+# if ARCH_BITS > 32
+# define VMCPU_FF_CLEAR_MASK(pVCpu, fFlags) \
+ do { ASMAtomicAndU64(&(pVCpu)->fLocalForcedActions, ~(fFlags)); } while (0)
+# else
+# define VMCPU_FF_CLEAR_MASK(pVCpu, fFlags) do { \
+ if (!((fFlags) >> 32)) ASMAtomicAndU32((uint32_t volatile *)&(pVCpu)->fLocalForcedActions, ~(uint32_t)(fFlags)); \
+ else ASMAtomicAndU64(&(pVCpu)->fLocalForcedActions, ~(fFlags)); \
+ } while (0)
+# endif
+#else
+# define VMCPU_FF_CLEAR_MASK(pVCpu, fFlags) \
+ do { ASMAtomicAndU32(&(pVCpu)->fLocalForcedActions, ~(fFlags)); } while (0)
+#endif
+
+/** @def VM_FF_IS_SET
+ * Checks if single a force action flag is set.
+ *
+ * @param pVM The cross context VM structure.
+ * @param fFlag The flag to check.
+ * @sa VM_FF_IS_ANY_SET
+ */
+#if !defined(VBOX_STRICT) || !defined(RT_COMPILER_SUPPORTS_LAMBDA)
+# define VM_FF_IS_SET(pVM, fFlag) RT_BOOL((pVM)->fGlobalForcedActions & (fFlag))
+#else
+# define VM_FF_IS_SET(pVM, fFlag) \
+ ([](PVM a_pVM) -> bool \
+ { \
+ AssertCompile(RT_IS_POWER_OF_TWO(fFlag)); \
+ AssertCompile((fFlag) == RT_BIT_32(fFlag##_BIT)); \
+ return RT_BOOL(a_pVM->fGlobalForcedActions & (fFlag)); \
+ }(pVM))
+#endif
+
+/** @def VMCPU_FF_IS_SET
+ * Checks if a single force action flag is set for the given VCPU.
+ *
+ * @param pVCpu The cross context virtual CPU structure.
+ * @param fFlag The flag to check.
+ * @sa VMCPU_FF_IS_ANY_SET
+ */
+#if !defined(VBOX_STRICT) || !defined(RT_COMPILER_SUPPORTS_LAMBDA)
+# define VMCPU_FF_IS_SET(pVCpu, fFlag) RT_BOOL((pVCpu)->fLocalForcedActions & (fFlag))
+#else
+# define VMCPU_FF_IS_SET(pVCpu, fFlag) \
+ ([](PCVMCPU a_pVCpu) -> bool \
+ { \
+ AssertCompile(RT_IS_POWER_OF_TWO(fFlag)); \
+ AssertCompile((fFlag) == RT_BIT_64(fFlag##_BIT)); \
+ return RT_BOOL(a_pVCpu->fLocalForcedActions & (fFlag)); \
+ }(pVCpu))
+#endif
+
+/** @def VM_FF_IS_ANY_SET
+ * Checks if one or more force action in the specified set is pending.
+ *
+ * @param pVM The cross context VM structure.
+ * @param fFlags The flags to check for.
+ * @sa VM_FF_IS_SET
+ */
+#define VM_FF_IS_ANY_SET(pVM, fFlags) RT_BOOL((pVM)->fGlobalForcedActions & (fFlags))
+
+/** @def VMCPU_FF_IS_ANY_SET
+ * Checks if two or more force action flags in the specified set is set for the given VCPU.
+ *
+ * @param pVCpu The cross context virtual CPU structure.
+ * @param fFlags The flags to check for.
+ * @sa VMCPU_FF_IS_SET
+ */
+#define VMCPU_FF_IS_ANY_SET(pVCpu, fFlags) RT_BOOL((pVCpu)->fLocalForcedActions & (fFlags))
+
+/** @def VM_FF_TEST_AND_CLEAR
+ * Checks if one (!) force action in the specified set is pending and clears it atomically
+ *
+ * @returns true if the bit was set.
+ * @returns false if the bit was clear.
+ * @param pVM The cross context VM structure.
+ * @param fFlag Flag constant to check and clear (_BIT is appended).
+ */
+#define VM_FF_TEST_AND_CLEAR(pVM, fFlag) (ASMAtomicBitTestAndClear(&(pVM)->fGlobalForcedActions, fFlag##_BIT))
+
+/** @def VMCPU_FF_TEST_AND_CLEAR
+ * Checks if one (!) force action in the specified set is pending and clears it atomically
+ *
+ * @returns true if the bit was set.
+ * @returns false if the bit was clear.
+ * @param pVCpu The cross context virtual CPU structure.
+ * @param fFlag Flag constant to check and clear (_BIT is appended).
+ */
+#define VMCPU_FF_TEST_AND_CLEAR(pVCpu, fFlag) (ASMAtomicBitTestAndClear(&(pVCpu)->fLocalForcedActions, fFlag##_BIT))
+
+/** @def VM_FF_IS_PENDING_EXCEPT
+ * Checks if one or more force action in the specified set is pending while one
+ * or more other ones are not.
+ *
+ * @param pVM The cross context VM structure.
+ * @param fFlags The flags to check for.
+ * @param fExcpt The flags that should not be set.
+ */
+#define VM_FF_IS_PENDING_EXCEPT(pVM, fFlags, fExcpt) \
+ ( ((pVM)->fGlobalForcedActions & (fFlags)) && !((pVM)->fGlobalForcedActions & (fExcpt)) )
+
+/** @def VM_IS_EMT
+ * Checks if the current thread is the emulation thread (EMT).
+ *
+ * @remark The ring-0 variation will need attention if we expand the ring-0
+ * code to let threads other than EMT mess around with the VM.
+ */
+#ifdef IN_RC
+# define VM_IS_EMT(pVM) true
+#else
+# define VM_IS_EMT(pVM) (VMMGetCpu(pVM) != NULL)
+#endif
+
+/** @def VMCPU_IS_EMT
+ * Checks if the current thread is the emulation thread (EMT) for the specified
+ * virtual CPU.
+ */
+#ifdef IN_RC
+# define VMCPU_IS_EMT(pVCpu) true
+#else
+# define VMCPU_IS_EMT(pVCpu) ((pVCpu) && ((pVCpu) == VMMGetCpu((pVCpu)->CTX_SUFF(pVM))))
+#endif
+
+/** @def VM_ASSERT_EMT
+ * Asserts that the current thread IS the emulation thread (EMT).
+ */
+#ifdef IN_RC
+# define VM_ASSERT_EMT(pVM) Assert(VM_IS_EMT(pVM))
+#elif defined(IN_RING0)
+# define VM_ASSERT_EMT(pVM) Assert(VM_IS_EMT(pVM))
+#else
+# define VM_ASSERT_EMT(pVM) \
+ AssertMsg(VM_IS_EMT(pVM), \
+ ("Not emulation thread! Thread=%RTnthrd ThreadEMT=%RTnthrd\n", RTThreadNativeSelf(), VMR3GetVMCPUNativeThread(pVM)))
+#endif
+
+/** @def VMCPU_ASSERT_EMT
+ * Asserts that the current thread IS the emulation thread (EMT) of the
+ * specified virtual CPU.
+ */
+#ifdef IN_RC
+# define VMCPU_ASSERT_EMT(pVCpu) Assert(VMCPU_IS_EMT(pVCpu))
+#elif defined(IN_RING0)
+# define VMCPU_ASSERT_EMT(pVCpu) AssertMsg(VMCPU_IS_EMT(pVCpu), \
+ ("Not emulation thread! Thread=%RTnthrd ThreadEMT=%RTnthrd idCpu=%u\n", \
+ RTThreadNativeSelf(), (pVCpu) ? (pVCpu)->hNativeThreadR0 : 0, \
+ (pVCpu) ? (pVCpu)->idCpu : 0))
+#else
+# define VMCPU_ASSERT_EMT(pVCpu) AssertMsg(VMCPU_IS_EMT(pVCpu), \
+ ("Not emulation thread! Thread=%RTnthrd ThreadEMT=%RTnthrd idCpu=%#x\n", \
+ RTThreadNativeSelf(), (pVCpu)->hNativeThread, (pVCpu)->idCpu))
+#endif
+
+/** @def VM_ASSERT_EMT_RETURN
+ * Asserts that the current thread IS the emulation thread (EMT) and returns if it isn't.
+ */
+#ifdef IN_RC
+# define VM_ASSERT_EMT_RETURN(pVM, rc) AssertReturn(VM_IS_EMT(pVM), (rc))
+#elif defined(IN_RING0)
+# define VM_ASSERT_EMT_RETURN(pVM, rc) AssertReturn(VM_IS_EMT(pVM), (rc))
+#else
+# define VM_ASSERT_EMT_RETURN(pVM, rc) \
+ AssertMsgReturn(VM_IS_EMT(pVM), \
+ ("Not emulation thread! Thread=%RTnthrd ThreadEMT=%RTnthrd\n", RTThreadNativeSelf(), VMR3GetVMCPUNativeThread(pVM)), \
+ (rc))
+#endif
+
+/** @def VMCPU_ASSERT_EMT_RETURN
+ * Asserts that the current thread IS the emulation thread (EMT) and returns if it isn't.
+ */
+#ifdef IN_RC
+# define VMCPU_ASSERT_EMT_RETURN(pVCpu, rc) AssertReturn(VMCPU_IS_EMT(pVCpu), (rc))
+#elif defined(IN_RING0)
+# define VMCPU_ASSERT_EMT_RETURN(pVCpu, rc) AssertReturn(VMCPU_IS_EMT(pVCpu), (rc))
+#else
+# define VMCPU_ASSERT_EMT_RETURN(pVCpu, rc) \
+ AssertMsgReturn(VMCPU_IS_EMT(pVCpu), \
+ ("Not emulation thread! Thread=%RTnthrd ThreadEMT=%RTnthrd idCpu=%#x\n", \
+ RTThreadNativeSelf(), (pVCpu)->hNativeThread, (pVCpu)->idCpu), \
+ (rc))
+#endif
+
+/** @def VMCPU_ASSERT_EMT_OR_GURU
+ * Asserts that the current thread IS the emulation thread (EMT) of the
+ * specified virtual CPU.
+ */
+#if defined(IN_RC) || defined(IN_RING0)
+# define VMCPU_ASSERT_EMT_OR_GURU(pVCpu) Assert( VMCPU_IS_EMT(pVCpu) \
+ || pVCpu->CTX_SUFF(pVM)->enmVMState == VMSTATE_GURU_MEDITATION \
+ || pVCpu->CTX_SUFF(pVM)->enmVMState == VMSTATE_GURU_MEDITATION_LS )
+#else
+# define VMCPU_ASSERT_EMT_OR_GURU(pVCpu) \
+ AssertMsg( VMCPU_IS_EMT(pVCpu) \
+ || pVCpu->CTX_SUFF(pVM)->enmVMState == VMSTATE_GURU_MEDITATION \
+ || pVCpu->CTX_SUFF(pVM)->enmVMState == VMSTATE_GURU_MEDITATION_LS, \
+ ("Not emulation thread! Thread=%RTnthrd ThreadEMT=%RTnthrd idCpu=%#x\n", \
+ RTThreadNativeSelf(), (pVCpu)->hNativeThread, (pVCpu)->idCpu))
+#endif
+
+/** @def VMCPU_ASSERT_EMT_OR_NOT_RUNNING
+ * Asserts that the current thread IS the emulation thread (EMT) of the
+ * specified virtual CPU or the VM is not running.
+ */
+#if defined(IN_RC) || defined(IN_RING0)
+# define VMCPU_ASSERT_EMT_OR_NOT_RUNNING(pVCpu) \
+ Assert( VMCPU_IS_EMT(pVCpu) \
+ || !VM_IS_RUNNING_FOR_ASSERTIONS_ONLY((pVCpu)->CTX_SUFF(pVM)) )
+#else
+# define VMCPU_ASSERT_EMT_OR_NOT_RUNNING(pVCpu) \
+ AssertMsg( VMCPU_IS_EMT(pVCpu) \
+ || !VM_IS_RUNNING_FOR_ASSERTIONS_ONLY((pVCpu)->CTX_SUFF(pVM)), \
+ ("Not emulation thread! Thread=%RTnthrd ThreadEMT=%RTnthrd idCpu=%#x\n", \
+ RTThreadNativeSelf(), (pVCpu)->hNativeThread, (pVCpu)->idCpu))
+#endif
+
+/** @def VMSTATE_IS_RUNNING
+ * Checks if the given state indicates a running VM.
+ */
+#define VMSTATE_IS_RUNNING(a_enmVMState) \
+ ( (enmVMState) == VMSTATE_RUNNING \
+ || (enmVMState) == VMSTATE_RUNNING_LS )
+
+/** @def VM_IS_RUNNING_FOR_ASSERTIONS_ONLY
+ * Checks if the VM is running.
+ * @note This is only for pure debug assertions. No AssertReturn or similar!
+ * @sa VMSTATE_IS_RUNNING
+ */
+#define VM_IS_RUNNING_FOR_ASSERTIONS_ONLY(pVM) \
+ ( (pVM)->enmVMState == VMSTATE_RUNNING \
+ || (pVM)->enmVMState == VMSTATE_RUNNING_LS )
+
+/** @def VM_ASSERT_IS_NOT_RUNNING
+ * Asserts that the VM is not running.
+ */
+#if defined(IN_RC) || defined(IN_RING0)
+#define VM_ASSERT_IS_NOT_RUNNING(pVM) Assert(!VM_IS_RUNNING_FOR_ASSERTIONS_ONLY(pVM))
+#else
+#define VM_ASSERT_IS_NOT_RUNNING(pVM) AssertMsg(!VM_IS_RUNNING_FOR_ASSERTIONS_ONLY(pVM), \
+ ("VM is running. enmVMState=%d\n", (pVM)->enmVMState))
+#endif
+
+/** @def VM_ASSERT_EMT0
+ * Asserts that the current thread IS emulation thread \#0 (EMT0).
+ */
+#ifdef IN_RING3
+# define VM_ASSERT_EMT0(a_pVM) VMCPU_ASSERT_EMT((a_pVM)->apCpusR3[0])
+#else
+# define VM_ASSERT_EMT0(a_pVM) VMCPU_ASSERT_EMT(&(a_pVM)->aCpus[0])
+#endif
+
+/** @def VM_ASSERT_EMT0_RETURN
+ * Asserts that the current thread IS emulation thread \#0 (EMT0) and returns if
+ * it isn't.
+ */
+#ifdef IN_RING3
+# define VM_ASSERT_EMT0_RETURN(pVM, rc) VMCPU_ASSERT_EMT_RETURN((pVM)->apCpusR3[0], (rc))
+#else
+# define VM_ASSERT_EMT0_RETURN(pVM, rc) VMCPU_ASSERT_EMT_RETURN(&(pVM)->aCpus[0], (rc))
+#endif
+
+
+/**
+ * Asserts that the current thread is NOT the emulation thread.
+ */
+#define VM_ASSERT_OTHER_THREAD(pVM) \
+ AssertMsg(!VM_IS_EMT(pVM), ("Not other thread!!\n"))
+
+
+/** @def VM_ASSERT_STATE
+ * Asserts a certain VM state.
+ */
+#define VM_ASSERT_STATE(pVM, _enmState) \
+ AssertMsg((pVM)->enmVMState == (_enmState), \
+ ("state %s, expected %s\n", VMGetStateName((pVM)->enmVMState), VMGetStateName(_enmState)))
+
+/** @def VM_ASSERT_STATE_RETURN
+ * Asserts a certain VM state and returns if it doesn't match.
+ */
+#define VM_ASSERT_STATE_RETURN(pVM, _enmState, rc) \
+ AssertMsgReturn((pVM)->enmVMState == (_enmState), \
+ ("state %s, expected %s\n", VMGetStateName((pVM)->enmVMState), VMGetStateName(_enmState)), \
+ (rc))
+
+/** @def VM_IS_VALID_EXT
+ * Asserts a the VM handle is valid for external access, i.e. not being destroy
+ * or terminated. */
+#define VM_IS_VALID_EXT(pVM) \
+ ( RT_VALID_ALIGNED_PTR(pVM, PAGE_SIZE) \
+ && ( (unsigned)(pVM)->enmVMState < (unsigned)VMSTATE_DESTROYING \
+ || ( (unsigned)(pVM)->enmVMState == (unsigned)VMSTATE_DESTROYING \
+ && VM_IS_EMT(pVM))) )
+
+/** @def VM_ASSERT_VALID_EXT_RETURN
+ * Asserts a the VM handle is valid for external access, i.e. not being
+ * destroy or terminated.
+ */
+#define VM_ASSERT_VALID_EXT_RETURN(pVM, rc) \
+ AssertMsgReturn(VM_IS_VALID_EXT(pVM), \
+ ("pVM=%p state %s\n", (pVM), RT_VALID_ALIGNED_PTR(pVM, PAGE_SIZE) \
+ ? VMGetStateName(pVM->enmVMState) : ""), \
+ (rc))
+
+/** @def VMCPU_ASSERT_VALID_EXT_RETURN
+ * Asserts a the VMCPU handle is valid for external access, i.e. not being
+ * destroy or terminated.
+ */
+#define VMCPU_ASSERT_VALID_EXT_RETURN(pVCpu, rc) \
+ AssertMsgReturn( RT_VALID_ALIGNED_PTR(pVCpu, 64) \
+ && RT_VALID_ALIGNED_PTR((pVCpu)->CTX_SUFF(pVM), PAGE_SIZE) \
+ && (unsigned)(pVCpu)->CTX_SUFF(pVM)->enmVMState < (unsigned)VMSTATE_DESTROYING, \
+ ("pVCpu=%p pVM=%p state %s\n", (pVCpu), RT_VALID_ALIGNED_PTR(pVCpu, 64) ? (pVCpu)->CTX_SUFF(pVM) : NULL, \
+ RT_VALID_ALIGNED_PTR(pVCpu, 64) && RT_VALID_ALIGNED_PTR((pVCpu)->CTX_SUFF(pVM), PAGE_SIZE) \
+ ? VMGetStateName((pVCpu)->pVMR3->enmVMState) : ""), \
+ (rc))
+
+#endif /* !VBOX_FOR_DTRACE_LIB */
+
+
+/**
+ * Helper that HM and NEM uses for safely modifying VM::bMainExecutionEngine.
+ *
+ * ONLY HM and NEM MAY USE THIS!
+ *
+ * @param a_pVM The cross context VM structure.
+ * @param a_bValue The new value.
+ * @internal
+ */
+#define VM_SET_MAIN_EXECUTION_ENGINE(a_pVM, a_bValue) \
+ do { \
+ *const_cast<uint8_t *>(&(a_pVM)->bMainExecutionEngine) = (a_bValue); \
+ ASMCompilerBarrier(); /* just to be on the safe side */ \
+ } while (0)
+
+/**
+ * Checks whether iem-executes-all-mode is used.
+ *
+ * @retval true if IEM is used.
+ * @retval false if not.
+ *
+ * @param a_pVM The cross context VM structure.
+ * @sa VM_IS_HM_OR_NEM_ENABLED, VM_IS_HM_ENABLED, VM_IS_NEM_ENABLED.
+ * @internal
+ */
+#define VM_IS_EXEC_ENGINE_IEM(a_pVM) ((a_pVM)->bMainExecutionEngine == VM_EXEC_ENGINE_IEM)
+
+/**
+ * Checks whether HM (VT-x/AMD-V) or NEM is being used by this VM.
+ *
+ * @retval true if either is used.
+ * @retval false if software virtualization (raw-mode) is used.
+ *
+ * @param a_pVM The cross context VM structure.
+ * @sa VM_IS_EXEC_ENGINE_IEM, VM_IS_HM_ENABLED, VM_IS_NEM_ENABLED.
+ * @internal
+ */
+#define VM_IS_HM_OR_NEM_ENABLED(a_pVM) ((a_pVM)->bMainExecutionEngine != VM_EXEC_ENGINE_IEM)
+
+/**
+ * Checks whether HM is being used by this VM.
+ *
+ * @retval true if HM (VT-x/AMD-v) is used.
+ * @retval false if not.
+ *
+ * @param a_pVM The cross context VM structure.
+ * @sa VM_IS_NEM_ENABLED, VM_IS_EXEC_ENGINE_IEM, VM_IS_HM_OR_NEM_ENABLED.
+ * @internal
+ */
+#define VM_IS_HM_ENABLED(a_pVM) ((a_pVM)->bMainExecutionEngine == VM_EXEC_ENGINE_HW_VIRT)
+
+/**
+ * Checks whether NEM is being used by this VM.
+ *
+ * @retval true if a native hypervisor API is used.
+ * @retval false if not.
+ *
+ * @param a_pVM The cross context VM structure.
+ * @sa VM_IS_HM_ENABLED, VM_IS_EXEC_ENGINE_IEM, VM_IS_HM_OR_NEM_ENABLED.
+ * @internal
+ */
+#define VM_IS_NEM_ENABLED(a_pVM) ((a_pVM)->bMainExecutionEngine == VM_EXEC_ENGINE_NATIVE_API)
+
+
+/**
+ * The cross context VM structure.
+ *
+ * It contains all the VM data which have to be available in all contexts.
+ * Even if it contains all the data the idea is to use APIs not to modify all
+ * the members all around the place. Therefore we make use of unions to hide
+ * everything which isn't local to the current source module. This means we'll
+ * have to pay a little bit of attention when adding new members to structures
+ * in the unions and make sure to keep the padding sizes up to date.
+ *
+ * Run 'kmk run-struct-tests' (from src/VBox/VMM if you like) after updating!
+ */
+typedef struct VM
+{
+ /** The state of the VM.
+ * This field is read only to everyone except the VM and EM. */
+ VMSTATE volatile enmVMState;
+ /** Forced action flags.
+ * See the VM_FF_* \#defines. Updated atomically.
+ */
+ volatile uint32_t fGlobalForcedActions;
+ /** Pointer to the array of page descriptors for the VM structure allocation. */
+ R3PTRTYPE(PSUPPAGE) paVMPagesR3;
+ /** Session handle. For use when calling SUPR0 APIs. */
+#ifdef IN_RING0
+ PSUPDRVSESSION pSessionUnsafe;
+#else
+ PSUPDRVSESSION pSession;
+#endif
+ /** Pointer to the ring-3 VM structure. */
+ PUVM pUVM;
+ /** Ring-3 Host Context VM Pointer. */
+#ifdef IN_RING0
+ R3PTRTYPE(struct VM *) pVMR3Unsafe;
+#else
+ R3PTRTYPE(struct VM *) pVMR3;
+#endif
+ /** Ring-0 Host Context VM pointer for making ring-0 calls. */
+ R0PTRTYPE(struct VM *) pVMR0ForCall;
+ /** Raw-mode Context VM Pointer. */
+ uint32_t pVMRC;
+ /** Padding for new raw-mode (long mode). */
+ uint32_t pVMRCPadding;
+
+ /** The GVM VM handle. Only the GVM should modify this field. */
+#ifdef IN_RING0
+ uint32_t hSelfUnsafe;
+#else
+ uint32_t hSelf;
+#endif
+ /** Number of virtual CPUs. */
+#ifdef IN_RING0
+ uint32_t cCpusUnsafe;
+#else
+ uint32_t cCpus;
+#endif
+ /** CPU excution cap (1-100) */
+ uint32_t uCpuExecutionCap;
+
+ /** Size of the VM structure. */
+ uint32_t cbSelf;
+ /** Size of the VMCPU structure. */
+ uint32_t cbVCpu;
+ /** Structure version number (TBD). */
+ uint32_t uStructVersion;
+
+ /** @name Various items that are frequently accessed.
+ * @{ */
+ /** The main execution engine, VM_EXEC_ENGINE_XXX.
+ * This is set early during vmR3InitRing3 by HM or NEM. */
+ uint8_t const bMainExecutionEngine;
+
+ /** Hardware VM support is available and enabled.
+ * Determined very early during init.
+ * This is placed here for performance reasons.
+ * @todo obsoleted by bMainExecutionEngine, eliminate. */
+ bool fHMEnabled;
+ /** @} */
+
+ /** Alignment padding. */
+ uint8_t uPadding1[6];
+
+ /** @name Debugging
+ * @{ */
+ /** Ring-3 Host Context VM Pointer. */
+ R3PTRTYPE(RTTRACEBUF) hTraceBufR3;
+ /** Ring-0 Host Context VM Pointer. */
+ R0PTRTYPE(RTTRACEBUF) hTraceBufR0;
+ /** @} */
+
+ /** Max EMT hash lookup collisions (in GVMM). */
+ uint8_t cMaxEmtHashCollisions;
+
+ /** Padding - the unions must be aligned on a 64 bytes boundary. */
+ uint8_t abAlignment3[HC_ARCH_BITS == 64 ? 23 : 51];
+
+ /** CPUM part. */
+ union
+ {
+#ifdef VMM_INCLUDED_SRC_include_CPUMInternal_h
+ struct CPUM s;
+#endif
+#ifdef VBOX_INCLUDED_vmm_cpum_h
+ /** Read only info exposed about the host and guest CPUs. */
+ struct
+ {
+ /** Padding for hidden fields. */
+ uint8_t abHidden0[64 + 48];
+ /** Guest CPU feature information. */
+ CPUMFEATURES GuestFeatures;
+ } const ro;
+#endif
+ /** @todo this is rather bloated because of static MSR range allocation.
+ * Probably a good idea to move it to a separate R0 allocation... */
+ uint8_t padding[8832 + 128*8192 + 0x1d00]; /* multiple of 64 */
+ } cpum;
+
+ /** PGM part.
+ * @note 16384 aligned for zero and mmio page storage. */
+ union
+ {
+#ifdef VMM_INCLUDED_SRC_include_PGMInternal_h
+ struct PGM s;
+#endif
+ uint8_t padding[53888]; /* multiple of 64 */
+ } pgm;
+
+ /** VMM part. */
+ union
+ {
+#ifdef VMM_INCLUDED_SRC_include_VMMInternal_h
+ struct VMM s;
+#endif
+ uint8_t padding[1600]; /* multiple of 64 */
+ } vmm;
+
+ /** HM part. */
+ union
+ {
+#ifdef VMM_INCLUDED_SRC_include_HMInternal_h
+ struct HM s;
+#endif
+ uint8_t padding[5504]; /* multiple of 64 */
+ } hm;
+
+ /** TRPM part. */
+ union
+ {
+#ifdef VMM_INCLUDED_SRC_include_TRPMInternal_h
+ struct TRPM s;
+#endif
+ uint8_t padding[2048]; /* multiple of 64 */
+ } trpm;
+
+ /** SELM part. */
+ union
+ {
+#ifdef VMM_INCLUDED_SRC_include_SELMInternal_h
+ struct SELM s;
+#endif
+ uint8_t padding[768]; /* multiple of 64 */
+ } selm;
+
+ /** MM part. */
+ union
+ {
+#ifdef VMM_INCLUDED_SRC_include_MMInternal_h
+ struct MM s;
+#endif
+ uint8_t padding[192]; /* multiple of 64 */
+ } mm;
+
+ /** PDM part. */
+ union
+ {
+#ifdef VMM_INCLUDED_SRC_include_PDMInternal_h
+ struct PDM s;
+#endif
+ uint8_t padding[22400]; /* multiple of 64 */
+ } pdm;
+
+ /** IOM part. */
+ union
+ {
+#ifdef VMM_INCLUDED_SRC_include_IOMInternal_h
+ struct IOM s;
+#endif
+ uint8_t padding[1152]; /* multiple of 64 */
+ } iom;
+
+ /** EM part. */
+ union
+ {
+#ifdef VMM_INCLUDED_SRC_include_EMInternal_h
+ struct EM s;
+#endif
+ uint8_t padding[256]; /* multiple of 64 */
+ } em;
+
+ /** NEM part. */
+ union
+ {
+#ifdef VMM_INCLUDED_SRC_include_NEMInternal_h
+ struct NEM s;
+#endif
+ uint8_t padding[4608]; /* multiple of 64 */
+ } nem;
+
+ /** TM part. */
+ union
+ {
+#ifdef VMM_INCLUDED_SRC_include_TMInternal_h
+ struct TM s;
+#endif
+ uint8_t padding[10112]; /* multiple of 64 */
+ } tm;
+
+ /** DBGF part. */
+ union
+ {
+#ifdef VMM_INCLUDED_SRC_include_DBGFInternal_h
+ struct DBGF s;
+#endif
+#ifdef VBOX_INCLUDED_vmm_dbgf_h
+ /** Read only info exposed about interrupt breakpoints and selected events. */
+ struct
+ {
+ /** Bitmap of enabled hardware interrupt breakpoints. */
+ uint32_t bmHardIntBreakpoints[256 / 32];
+ /** Bitmap of enabled software interrupt breakpoints. */
+ uint32_t bmSoftIntBreakpoints[256 / 32];
+ /** Bitmap of selected events.
+ * This includes non-selectable events too for simplicity, we maintain the
+ * state for some of these, as it may come in handy. */
+ uint64_t bmSelectedEvents[(DBGFEVENT_END + 63) / 64];
+ /** Enabled hardware interrupt breakpoints. */
+ uint32_t cHardIntBreakpoints;
+ /** Enabled software interrupt breakpoints. */
+ uint32_t cSoftIntBreakpoints;
+ /** The number of selected events. */
+ uint32_t cSelectedEvents;
+ /** The number of enabled hardware breakpoints. */
+ uint8_t cEnabledHwBreakpoints;
+ /** The number of enabled hardware I/O breakpoints. */
+ uint8_t cEnabledHwIoBreakpoints;
+ uint8_t au8Alignment1[2]; /**< Alignment padding. */
+ /** The number of enabled INT3 breakpoints. */
+ uint32_t volatile cEnabledInt3Breakpoints;
+ } const ro;
+#endif
+ uint8_t padding[2432]; /* multiple of 64 */
+ } dbgf;
+
+ /** SSM part. */
+ union
+ {
+#ifdef VMM_INCLUDED_SRC_include_SSMInternal_h
+ struct SSM s;
+#endif
+ uint8_t padding[128]; /* multiple of 64 */
+ } ssm;
+
+ union
+ {
+#ifdef VMM_INCLUDED_SRC_include_GIMInternal_h
+ struct GIM s;
+#endif
+ uint8_t padding[448]; /* multiple of 64 */
+ } gim;
+
+ union
+ {
+#ifdef VMM_INCLUDED_SRC_include_APICInternal_h
+ struct APIC s;
+#endif
+ uint8_t padding[128]; /* multiple of 8 */
+ } apic;
+
+ /* ---- begin small stuff ---- */
+
+ /** VM part. */
+ union
+ {
+#ifdef VMM_INCLUDED_SRC_include_VMInternal_h
+ struct VMINT s;
+#endif
+ uint8_t padding[32]; /* multiple of 8 */
+ } vm;
+
+ /** CFGM part. */
+ union
+ {
+#ifdef VMM_INCLUDED_SRC_include_CFGMInternal_h
+ struct CFGM s;
+#endif
+ uint8_t padding[8]; /* multiple of 8 */
+ } cfgm;
+
+ /** IEM part. */
+ union
+ {
+#ifdef VMM_INCLUDED_SRC_include_IEMInternal_h
+ struct IEM s;
+#endif
+ uint8_t padding[16]; /* multiple of 8 */
+ } iem;
+
+ /** Statistics for ring-0 only components. */
+ struct
+ {
+ /** GMMR0 stats. */
+ struct
+ {
+ /** Chunk TLB hits. */
+ uint64_t cChunkTlbHits;
+ /** Chunk TLB misses. */
+ uint64_t cChunkTlbMisses;
+ } gmm;
+ uint64_t au64Padding[6]; /* probably more comming here... */
+ } R0Stats;
+
+ union
+ {
+#ifdef VMM_INCLUDED_SRC_include_GCMInternal_h
+ struct GCM s;
+#endif
+ uint8_t padding[32]; /* multiple of 8 */
+ } gcm;
+
+ /** Padding for aligning the structure size on a page boundrary. */
+ uint8_t abAlignment2[8872 - sizeof(PVMCPUR3) * VMM_MAX_CPU_COUNT];
+
+ /* ---- end small stuff ---- */
+
+ /** Array of VMCPU ring-3 pointers. */
+ PVMCPUR3 apCpusR3[VMM_MAX_CPU_COUNT];
+
+ /* This point is aligned on a 16384 boundrary (for arm64 purposes). */
+} VM;
+#ifndef VBOX_FOR_DTRACE_LIB
+//AssertCompileSizeAlignment(VM, 16384);
+#endif
+
+
+#ifdef IN_RC
+RT_C_DECLS_BEGIN
+
+/** The VM structure.
+ * This is imported from the VMMRCBuiltin module, i.e. it's a one of those magic
+ * globals which we should avoid using.
+ */
+extern DECLIMPORT(VM) g_VM;
+
+/** The VMCPU structure for virtual CPU \#0.
+ * This is imported from the VMMRCBuiltin module, i.e. it's a one of those magic
+ * globals which we should avoid using.
+ */
+extern DECLIMPORT(VMCPU) g_VCpu0;
+
+RT_C_DECLS_END
+#endif
+
+/** @} */
+
+#endif /* !VBOX_INCLUDED_vmm_vm_h */
+
diff --git a/include/VBox/vmm/vm.mac b/include/VBox/vmm/vm.mac
new file mode 100644
index 00000000..2aa4b515
--- /dev/null
+++ b/include/VBox/vmm/vm.mac
@@ -0,0 +1,187 @@
+;; @file
+; VM - The Virtual Machine.
+;
+
+;
+; Copyright (C) 2006-2022 Oracle and/or its affiliates.
+;
+; This file is part of VirtualBox base platform packages, as
+; available from https://www.virtualbox.org.
+;
+; This program is free software; you can redistribute it and/or
+; modify it under the terms of the GNU General Public License
+; as published by the Free Software Foundation, in version 3 of the
+; License.
+;
+; This program is distributed in the hope that it will be useful, but
+; WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with this program; if not, see <https://www.gnu.org/licenses>.
+;
+; The contents of this file may alternatively be used under the terms
+; of the Common Development and Distribution License Version 1.0
+; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+; in the VirtualBox 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.
+;
+; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+;
+
+%ifndef ___VBox_vmm_vm_mac
+%define ___VBox_vmm_vm_mac
+
+%include "VBox/vmm/stam.mac"
+%include "VBox/param.mac"
+
+;/** This action forces the VM to service check and pending interrups on the APIC. */
+%define VMCPU_FF_INTERRUPT_APIC (1 << 0)
+;/** This action forces the VM to service check and pending interrups on the PIC. */
+%define VMCPU_FF_INTERRUPT_PIC (1 << 1)
+;/** This action forces the VM to schedule and run pending timer (TM). */
+%define VMCPU_FF_TIMER (1 << 2)
+;/** This action forces the VM to service pending requests from other
+; * thread or requests which must be executed in another context. */
+%define VMCPU_FF_REQUEST (1 << 9)
+
+;;
+; This is part of the VMCPU structure.
+struc VMCPU
+ .fLocalForcedActions resd 1
+ alignb 8
+ .enmState resd 1
+
+ alignb 64
+ .iem resb 32832
+
+ alignb 64
+ .pVMR3 RTR3PTR_RES 1
+ .pVCpuR0ForVtg RTR0PTR_RES 1
+ .pVMRC resq 1
+ .pUVCpu RTR3PTR_RES 1
+ .hNativeThread RTR3PTR_RES 1
+ .hNativeThreadR0 RTR0PTR_RES 1
+ .hThread RTR3PTR_RES 1
+ .idCpu resd 1
+
+ alignb 64
+ .hm resb 9984
+ alignb 64
+ .nem resb 4608
+ alignb 64
+ .trpm resb 128
+ alignb 64
+ .tm resb 5760
+ alignb 64
+ .vmm resb 9536
+ alignb 64
+ .pdm resb 256
+ alignb 64
+ .iom resb 512
+ alignb 64
+ .dbgf resb 512
+ alignb 64
+ .gim resb 512
+ alignb 64
+ .apic resb 3840
+
+ alignb 64
+ .fTraceGroups resd 1
+ .cEmtHashCollisions resb 1
+ .abAdHoc resb 3
+ alignb 8
+ .aStatAdHoc resb STAMPROFILEADV_size * 8
+
+ alignb 4096
+ .pgm resb 4096+28672
+ alignb 4096
+ .cpum resb 102400
+%define VMCPU.cpum.GstCtx VMCPU.cpum
+ alignb 4096
+ .em resb 40960
+ alignb 16384
+endstruc
+
+;;
+; This is part of the VM structure.
+struc VM
+ .enmVMState resd 1
+ .fGlobalForcedActions resd 1
+ .paVMPagesR3 RTR3PTR_RES 1
+ .pSession RTR0PTR_RES 1
+ .pUVM RTR3PTR_RES 1
+ .pVMR3 RTR3PTR_RES 1
+ .pVMR0ForCall RTR0PTR_RES 1
+ .pVMRC resq 1
+%ifdef IN_RING0
+ .hSelfUnsafe resd 1
+ .cCpusUnsafe resd 1
+%else
+ .hSelf resd 1
+ .cCpus resd 1
+%endif
+ .uCpuExecutionCap resd 1
+ .cbSelf resd 1
+ .cbVCpu resd 1
+ .uStructVersion resd 1
+ .bMainExecutionEngine resb 1
+ .fHMEnabled resb 1
+
+ .uPadding1 resb 6
+
+ .hTraceBufR3 RTR3PTR_RES 1
+ .hTraceBufR0 RTR0PTR_RES 1
+
+ alignb 64
+ .cpum resb 8832 + 128*8192
+ alignb 16384
+ .pgm resb 53888
+ alignb 64
+ .vmm resb 1600
+ alignb 64
+ .hm resb 5504
+ alignb 64
+ .trpm resb 2048
+ alignb 64
+ .selm resb 768
+ alignb 64
+ .mm resb 192
+ alignb 64
+ .pdm resb 22400
+ alignb 64
+ .iom resb 1152
+ alignb 64
+ .em resb 256
+ alignb 64
+ .nem resb 4608
+ alignb 64
+ .tm resb 10112
+ alignb 64
+ .dbgf resb 2432
+ alignb 64
+ .ssm resb 128
+ alignb 64
+ .gim resb 448
+ alignb 64
+ .apic resb 128
+ alignb 64
+ .vm resb 32
+ .cfgm resb 8
+ .iem resb 16
+ .R0Stats resb 64
+ .gcm resb 32
+
+ times ((($ + VMM_MAX_CPU_COUNT * RTR0PTR_CB + 16383) & ~16383) - ($ + VMM_MAX_CPU_COUNT * RTR0PTR_CB)) resb 1
+ .apCpusR3 RTR3PTR_RES VMM_MAX_CPU_COUNT
+ alignb 16384
+
+endstruc
+
+
+%endif
+
diff --git a/include/VBox/vmm/vmapi.h b/include/VBox/vmm/vmapi.h
new file mode 100644
index 00000000..0a1cc09b
--- /dev/null
+++ b/include/VBox/vmm/vmapi.h
@@ -0,0 +1,485 @@
+/** @file
+ * VM - The Virtual Machine, API.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vmm_vmapi_h
+#define VBOX_INCLUDED_vmm_vmapi_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/types.h>
+#include <VBox/vmm/stam.h>
+#include <VBox/vmm/cfgm.h>
+
+#include <iprt/stdarg.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_vm_apis VM All Contexts API
+ * @ingroup grp_vm
+ * @{ */
+
+/** @name VM_EXEC_ENGINE_XXX - VM::bMainExecutionEngine values.
+ * @sa EMR3QueryMainExecutionEngine, VM_IS_RAW_MODE_ENABLED, VM_IS_HM_ENABLED,
+ * VM_IS_HM_OR_NEM_ENABLED, VM_IS_NEM_ENABLED, VM_SET_MAIN_EXECUTION_ENGINE
+ * @{ */
+/** Has not yet been set. */
+#define VM_EXEC_ENGINE_NOT_SET UINT8_C(0)
+/** The interpreter (IEM). */
+#define VM_EXEC_ENGINE_IEM UINT8_C(1)
+/** Hardware assisted virtualization thru HM. */
+#define VM_EXEC_ENGINE_HW_VIRT UINT8_C(2)
+/** Hardware assisted virtualization thru native API (NEM). */
+#define VM_EXEC_ENGINE_NATIVE_API UINT8_C(3)
+/** @} */
+
+
+/**
+ * VM error callback function.
+ *
+ * @param pUVM The user mode VM handle. Can be NULL if an error
+ * occurred before successfully creating a VM.
+ * @param pvUser The user argument.
+ * @param rc VBox status code.
+ * @param SRC_POS The source position arguments. See RT_SRC_POS and RT_SRC_POS_ARGS.
+ * @param pszFormat Error message format string.
+ * @param args Error message arguments.
+ */
+typedef DECLCALLBACKTYPE(void, FNVMATERROR,(PUVM pUVM, void *pvUser, int rc, RT_SRC_POS_DECL,
+ const char *pszFormat, va_list args));
+/** Pointer to a VM error callback. */
+typedef FNVMATERROR *PFNVMATERROR;
+
+#ifdef IN_RING3
+VMMDECL(int) VMSetError(PVMCC pVM, int rc, RT_SRC_POS_DECL, const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(6, 7);
+VMMDECL(int) VMSetErrorV(PVMCC pVM, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list args) RT_IPRT_FORMAT_ATTR(6, 7);
+#endif
+
+/** @def VM_SET_ERROR
+ * Macro for setting a simple VM error message.
+ * Don't use '%' in the message!
+ *
+ * @returns rc. Meaning you can do:
+ * @code
+ * return VM_SET_ERROR(pVM, VERR_OF_YOUR_CHOICE, "descriptive message");
+ * @endcode
+ * @param pVM The cross context VM structure.
+ * @param rc VBox status code.
+ * @param pszMessage Error message string.
+ * @thread Any
+ */
+#define VM_SET_ERROR(pVM, rc, pszMessage) (VMSetError(pVM, rc, RT_SRC_POS, pszMessage))
+
+/** @def VM_SET_ERROR
+ * Macro for setting a simple VM error message.
+ * Don't use '%' in the message!
+ *
+ * @returns rc. Meaning you can do:
+ * @code
+ * return VM_SET_ERROR(pVM, VERR_OF_YOUR_CHOICE, "descriptive message");
+ * @endcode
+ * @param pVM The cross context VM structure.
+ * @param rc VBox status code.
+ * @param pszMessage Error message string.
+ * @thread Any
+ */
+#define VM_SET_ERROR_U(a_pUVM, a_rc, a_pszMessage) (VMR3SetError(a_pUVM, a_rc, RT_SRC_POS, a_pszMessage))
+
+
+/**
+ * VM runtime error callback function.
+ *
+ * See VMSetRuntimeError for the detailed description of parameters.
+ *
+ * @param pUVM The user mode VM handle.
+ * @param pvUser The user argument.
+ * @param fFlags The error flags.
+ * @param pszErrorId Error ID string.
+ * @param pszFormat Error message format string.
+ * @param va Error message arguments.
+ */
+typedef DECLCALLBACKTYPE(void, FNVMATRUNTIMEERROR,(PUVM pUVM, void *pvUser, uint32_t fFlags, const char *pszErrorId,
+ const char *pszFormat, va_list va)) RT_IPRT_FORMAT_ATTR(5, 0);
+/** Pointer to a VM runtime error callback. */
+typedef FNVMATRUNTIMEERROR *PFNVMATRUNTIMEERROR;
+
+#ifdef IN_RING3
+VMMDECL(int) VMSetRuntimeError(PVMCC pVM, uint32_t fFlags, const char *pszErrorId,
+ const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(4, 5);
+VMMDECL(int) VMSetRuntimeErrorV(PVMCC pVM, uint32_t fFlags, const char *pszErrorId,
+ const char *pszFormat, va_list args) RT_IPRT_FORMAT_ATTR(4, 0);
+#endif
+
+/** @name VMSetRuntimeError fFlags
+ * When no flags are given the VM will continue running and it's up to the front
+ * end to take action on the error condition.
+ *
+ * @{ */
+/** The error is fatal.
+ * The VM is not in a state where it can be saved and will enter a state
+ * where it can no longer execute code. The caller <b>must</b> propagate status
+ * codes. */
+#define VMSETRTERR_FLAGS_FATAL RT_BIT_32(0)
+/** Suspend the VM after, or if possible before, raising the error on EMT. The
+ * caller <b>must</b> propagate status codes. */
+#define VMSETRTERR_FLAGS_SUSPEND RT_BIT_32(1)
+/** Don't wait for the EMT to handle the request.
+ * Only valid when on a worker thread and there is a high risk of a dead
+ * lock. Be careful not to flood the user with errors. */
+#define VMSETRTERR_FLAGS_NO_WAIT RT_BIT_32(2)
+/** @} */
+
+/**
+ * VM state change callback function.
+ *
+ * You are not allowed to call any function which changes the VM state from a
+ * state callback, except VMR3Destroy().
+ *
+ * @param pUVM The user mode VM handle.
+ * @param pVMM The VMM ring-3 vtable.
+ * @param enmState The new state.
+ * @param enmOldState The old state.
+ * @param pvUser The user argument.
+ */
+typedef DECLCALLBACKTYPE(void, FNVMATSTATE,(PUVM pUVM, PCVMMR3VTABLE pVMM, VMSTATE enmState, VMSTATE enmOldState, void *pvUser));
+/** Pointer to a VM state callback. */
+typedef FNVMATSTATE *PFNVMATSTATE;
+
+VMMDECL(const char *) VMGetStateName(VMSTATE enmState);
+
+VMMDECL(uint32_t) VMGetResetCount(PVMCC pVM);
+VMMDECL(uint32_t) VMGetSoftResetCount(PVMCC pVM);
+VMMDECL(uint32_t) VMGetHardResetCount(PVMCC pVM);
+
+
+/**
+ * Request type.
+ */
+typedef enum VMREQTYPE
+{
+ /** Invalid request. */
+ VMREQTYPE_INVALID = 0,
+ /** VM: Internal. */
+ VMREQTYPE_INTERNAL,
+ /** Maximum request type (exclusive). Used for validation. */
+ VMREQTYPE_MAX
+} VMREQTYPE;
+
+/**
+ * Request state.
+ */
+typedef enum VMREQSTATE
+{
+ /** The state is invalid. */
+ VMREQSTATE_INVALID = 0,
+ /** The request have been allocated and is in the process of being filed. */
+ VMREQSTATE_ALLOCATED,
+ /** The request is queued by the requester. */
+ VMREQSTATE_QUEUED,
+ /** The request is begin processed. */
+ VMREQSTATE_PROCESSING,
+ /** The request is completed, the requester is begin notified. */
+ VMREQSTATE_COMPLETED,
+ /** The request packet is in the free chain. (The requester */
+ VMREQSTATE_FREE
+} VMREQSTATE;
+
+/**
+ * Request flags.
+ */
+typedef enum VMREQFLAGS
+{
+ /** The request returns a VBox status code. */
+ VMREQFLAGS_VBOX_STATUS = 0,
+ /** The request is a void request and have no status code. */
+ VMREQFLAGS_VOID = 1,
+ /** Return type mask. */
+ VMREQFLAGS_RETURN_MASK = 1,
+ /** Caller does not wait on the packet, EMT will free it. */
+ VMREQFLAGS_NO_WAIT = 2,
+ /** Poke the destination EMT(s) if executing guest code. Use with care. */
+ VMREQFLAGS_POKE = 4,
+ /** Priority request that can safely be processed while doing async
+ * suspend and power off. */
+ VMREQFLAGS_PRIORITY = 8
+} VMREQFLAGS;
+
+
+/**
+ * VM Request packet.
+ *
+ * This is used to request an action in the EMT. Usually the requester is
+ * another thread, but EMT can also end up being the requester in which case
+ * it's carried out synchronously.
+ */
+typedef struct VMREQ
+{
+ /** Pointer to the next request in the chain. */
+ struct VMREQ * volatile pNext;
+ /** Pointer to ring-3 VM structure which this request belongs to. */
+ PUVM pUVM;
+ /** Request state. */
+ volatile VMREQSTATE enmState;
+ /** VBox status code for the completed request. */
+ volatile int32_t iStatus;
+ /** Requester event sem.
+ * The request can use this event semaphore to wait/poll for completion
+ * of the request.
+ */
+ RTSEMEVENT EventSem;
+ /** Set if the event semaphore is clear. */
+ volatile bool fEventSemClear;
+ /** Flags, VMR3REQ_FLAGS_*. */
+ unsigned fFlags;
+ /** Request type. */
+ VMREQTYPE enmType;
+ /** Request destination. */
+ VMCPUID idDstCpu;
+ /** Request specific data. */
+ union VMREQ_U
+ {
+ /** VMREQTYPE_INTERNAL. */
+ struct
+ {
+ /** Pointer to the function to be called. */
+ PFNRT pfn;
+ /** Number of arguments. */
+ unsigned cArgs;
+ /** Array of arguments. */
+ uintptr_t aArgs[64];
+ } Internal;
+ } u;
+} VMREQ;
+/** Pointer to a VM request packet. */
+typedef VMREQ *PVMREQ;
+
+
+#ifndef IN_RC
+/** @defgroup grp_vmm_apis_hc VM Host Context API
+ * @ingroup grp_vm
+ * @{ */
+
+/** @} */
+#endif
+
+
+#ifdef IN_RING3
+/** @defgroup grp_vmm_apis_r3 VM Host Context Ring 3 API
+ * @ingroup grp_vm
+ * @{ */
+
+/**
+ * Completion notification codes.
+ */
+typedef enum VMINITCOMPLETED
+{
+ /** The ring-3 init is completed. */
+ VMINITCOMPLETED_RING3 = 1,
+ /** The ring-0 init is completed. */
+ VMINITCOMPLETED_RING0,
+ /** The hardware accelerated virtualization init is completed.
+ * Used to make decisision depending on HM* bits being completely
+ * initialized. */
+ VMINITCOMPLETED_HM
+} VMINITCOMPLETED;
+
+
+/** Reason for VM resume. */
+typedef enum VMRESUMEREASON
+{
+ VMRESUMEREASON_INVALID = 0,
+ /** User decided to do so. */
+ VMRESUMEREASON_USER,
+ /** VM reconfiguration (like changing DVD). */
+ VMRESUMEREASON_RECONFIG,
+ /** The host resumed. */
+ VMRESUMEREASON_HOST_RESUME,
+ /** Restored state. */
+ VMRESUMEREASON_STATE_RESTORED,
+ /** Snapshot / saved state. */
+ VMRESUMEREASON_STATE_SAVED,
+ /** Teleported to a new box / instance. */
+ VMRESUMEREASON_TELEPORTED,
+ /** Teleportation failed. */
+ VMRESUMEREASON_TELEPORT_FAILED,
+ /** FTM temporarily suspended the VM. */
+ VMRESUMEREASON_FTM_SYNC,
+ /** End of valid reasons. */
+ VMRESUMEREASON_END,
+ /** Blow the type up to 32-bits. */
+ VMRESUMEREASON_32BIT_HACK = 0x7fffffff
+} VMRESUMEREASON;
+
+/** Reason for VM suspend. */
+typedef enum VMSUSPENDREASON
+{
+ VMSUSPENDREASON_INVALID = 0,
+ /** User decided to do so. */
+ VMSUSPENDREASON_USER,
+ /** VM reconfiguration (like changing DVD). */
+ VMSUSPENDREASON_RECONFIG,
+ /** The VM is suspending itself. */
+ VMSUSPENDREASON_VM,
+ /** The Vm is suspending because of a runtime error. */
+ VMSUSPENDREASON_RUNTIME_ERROR,
+ /** The host was suspended. */
+ VMSUSPENDREASON_HOST_SUSPEND,
+ /** The host is running low on battery power. */
+ VMSUSPENDREASON_HOST_BATTERY_LOW,
+ /** FTM is temporarily suspending the VM. */
+ VMSUSPENDREASON_FTM_SYNC,
+ /** End of valid reasons. */
+ VMSUSPENDREASON_END,
+ /** Blow the type up to 32-bits. */
+ VMSUSPENDREASON_32BIT_HACK = 0x7fffffff
+} VMSUSPENDREASON;
+
+
+/**
+ * Progress callback.
+ *
+ * This will report the completion percentage of an operation.
+ *
+ * @returns VINF_SUCCESS.
+ * @returns Error code to cancel the operation with.
+ * @param pUVM The user mode VM handle.
+ * @param uPercent Completion percentage (0-100).
+ * @param pvUser User specified argument.
+ */
+typedef DECLCALLBACKTYPE(int, FNVMPROGRESS,(PUVM pUVM, unsigned uPercent, void *pvUser));
+/** Pointer to a FNVMPROGRESS function. */
+typedef FNVMPROGRESS *PFNVMPROGRESS;
+
+
+VMMR3DECL(int) VMR3Create(uint32_t cCpus, PCVMM2USERMETHODS pVm2UserCbs,
+ PFNVMATERROR pfnVMAtError, void *pvUserVM,
+ PFNCFGMCONSTRUCTOR pfnCFGMConstructor, void *pvUserCFGM,
+ PVM *ppVM, PUVM *ppUVM);
+VMMR3DECL(int) VMR3PowerOn(PUVM pUVM);
+VMMR3DECL(int) VMR3Suspend(PUVM pUVM, VMSUSPENDREASON enmReason);
+VMMR3DECL(VMSUSPENDREASON) VMR3GetSuspendReason(PUVM);
+VMMR3DECL(int) VMR3Resume(PUVM pUVM, VMRESUMEREASON enmReason);
+VMMR3DECL(VMRESUMEREASON) VMR3GetResumeReason(PUVM);
+VMMR3DECL(int) VMR3Reset(PUVM pUVM);
+VMMR3_INT_DECL(VBOXSTRICTRC) VMR3ResetFF(PVM pVM);
+VMMR3_INT_DECL(VBOXSTRICTRC) VMR3ResetTripleFault(PVM pVM);
+VMMR3DECL(int) VMR3Save(PUVM pUVM, const char *pszFilename, PCSSMSTRMOPS pStreamOps, void *pvStreamOpsUser, bool fContinueAfterwards, PFNVMPROGRESS pfnProgress, void *pvUser, bool *pfSuspended);
+VMMR3DECL(int) VMR3Teleport(PUVM pUVM, uint32_t cMsDowntime, PCSSMSTRMOPS pStreamOps, void *pvStreamOpsUser, PFNVMPROGRESS pfnProgress, void *pvProgressUser, bool *pfSuspended);
+VMMR3DECL(int) VMR3LoadFromFile(PUVM pUVM, const char *pszFilename, PFNVMPROGRESS pfnProgress, void *pvUser);
+VMMR3DECL(int) VMR3LoadFromStream(PUVM pUVM, PCSSMSTRMOPS pStreamOps, void *pvStreamOpsUser,
+ PFNVMPROGRESS pfnProgress, void *pvProgressUser, bool fTeleporting);
+
+VMMR3DECL(int) VMR3PowerOff(PUVM pUVM);
+VMMR3DECL(int) VMR3Destroy(PUVM pUVM);
+VMMR3_INT_DECL(void) VMR3Relocate(PVM pVM, RTGCINTPTR offDelta);
+
+VMMR3DECL(PVM) VMR3GetVM(PUVM pUVM);
+VMMR3DECL(PUVM) VMR3GetUVM(PVM pVM);
+VMMR3DECL(uint32_t) VMR3RetainUVM(PUVM pUVM);
+VMMR3DECL(uint32_t) VMR3ReleaseUVM(PUVM pUVM);
+VMMR3DECL(const char *) VMR3GetName(PUVM pUVM);
+VMMR3DECL(PRTUUID) VMR3GetUuid(PUVM pUVM, PRTUUID pUuid);
+VMMR3DECL(VMSTATE) VMR3GetState(PVM pVM);
+VMMR3DECL(VMSTATE) VMR3GetStateU(PUVM pUVM);
+VMMR3DECL(const char *) VMR3GetStateName(VMSTATE enmState);
+VMMR3DECL(int) VMR3AtStateRegister(PUVM pUVM, PFNVMATSTATE pfnAtState, void *pvUser);
+VMMR3DECL(int) VMR3AtStateDeregister(PUVM pUVM, PFNVMATSTATE pfnAtState, void *pvUser);
+VMMR3_INT_DECL(bool) VMR3SetGuruMeditation(PVM pVM);
+VMMR3_INT_DECL(bool) VMR3TeleportedAndNotFullyResumedYet(PVM pVM);
+VMMR3DECL(int) VMR3AtErrorRegister(PUVM pUVM, PFNVMATERROR pfnAtError, void *pvUser);
+VMMR3DECL(int) VMR3AtErrorDeregister(PUVM pUVM, PFNVMATERROR pfnAtError, void *pvUser);
+VMMR3DECL(int) VMR3SetError(PUVM pUVM, int rc, RT_SRC_POS_DECL, const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(6, 7);
+VMMR3DECL(int) VMR3SetErrorV(PUVM pUVM, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(6, 0);
+VMMR3_INT_DECL(void) VMR3SetErrorWorker(PVM pVM);
+VMMR3_INT_DECL(uint32_t) VMR3GetErrorCount(PUVM pUVM);
+VMMR3DECL(int) VMR3AtRuntimeErrorRegister(PUVM pUVM, PFNVMATRUNTIMEERROR pfnAtRuntimeError, void *pvUser);
+VMMR3DECL(int) VMR3AtRuntimeErrorDeregister(PUVM pUVM, PFNVMATRUNTIMEERROR pfnAtRuntimeError, void *pvUser);
+VMMR3_INT_DECL(int) VMR3SetRuntimeErrorWorker(PVM pVM);
+VMMR3_INT_DECL(uint32_t) VMR3GetRuntimeErrorCount(PUVM pUVM);
+
+VMMR3DECL(int) VMR3ReqCallU(PUVM pUVM, VMCPUID idDstCpu, PVMREQ *ppReq, RTMSINTERVAL cMillies, uint32_t fFlags, PFNRT pfnFunction, unsigned cArgs, ...);
+VMMR3DECL(int) VMR3ReqCallVU(PUVM pUVM, VMCPUID idDstCpu, PVMREQ *ppReq, RTMSINTERVAL cMillies, uint32_t fFlags, PFNRT pfnFunction, unsigned cArgs, va_list Args);
+VMMR3_INT_DECL(int) VMR3ReqCallWait(PVM pVM, VMCPUID idDstCpu, PFNRT pfnFunction, unsigned cArgs, ...);
+VMMR3DECL(int) VMR3ReqCallWaitU(PUVM pUVM, VMCPUID idDstCpu, PFNRT pfnFunction, unsigned cArgs, ...);
+VMMR3DECL(int) VMR3ReqCallNoWait(PVM pVM, VMCPUID idDstCpu, PFNRT pfnFunction, unsigned cArgs, ...);
+VMMR3DECL(int) VMR3ReqCallNoWaitU(PUVM pUVM, VMCPUID idDstCpu, PFNRT pfnFunction, unsigned cArgs, ...);
+VMMR3_INT_DECL(int) VMR3ReqCallVoidWait(PVM pVM, VMCPUID idDstCpu, PFNRT pfnFunction, unsigned cArgs, ...);
+VMMR3DECL(int) VMR3ReqCallVoidWaitU(PUVM pUVM, VMCPUID idDstCpu, PFNRT pfnFunction, unsigned cArgs, ...);
+VMMR3DECL(int) VMR3ReqCallVoidNoWait(PVM pVM, VMCPUID idDstCpu, PFNRT pfnFunction, unsigned cArgs, ...);
+VMMR3DECL(int) VMR3ReqPriorityCallWait(PVM pVM, VMCPUID idDstCpu, PFNRT pfnFunction, unsigned cArgs, ...);
+VMMR3DECL(int) VMR3ReqPriorityCallWaitU(PUVM pUVM, VMCPUID idDstCpu, PFNRT pfnFunction, unsigned cArgs, ...);
+VMMR3DECL(int) VMR3ReqPriorityCallVoidWaitU(PUVM pUVM, VMCPUID idDstCpu, PFNRT pfnFunction, unsigned cArgs, ...);
+VMMR3DECL(int) VMR3ReqAlloc(PUVM pUVM, PVMREQ *ppReq, VMREQTYPE enmType, VMCPUID idDstCpu);
+VMMR3DECL(int) VMR3ReqFree(PVMREQ pReq);
+VMMR3DECL(int) VMR3ReqQueue(PVMREQ pReq, RTMSINTERVAL cMillies);
+VMMR3DECL(int) VMR3ReqWait(PVMREQ pReq, RTMSINTERVAL cMillies);
+VMMR3_INT_DECL(int) VMR3ReqProcessU(PUVM pUVM, VMCPUID idDstCpu, bool fPriorityOnly);
+
+/** @name Flags for VMR3NotifyCpuFFU and VMR3NotifyGlobalFFU.
+ * @{ */
+/** Whether we've done REM or not. */
+#define VMNOTIFYFF_FLAGS_DONE_REM RT_BIT_32(0)
+/** Whether we should poke the CPU if it's executing guest code. */
+#define VMNOTIFYFF_FLAGS_POKE RT_BIT_32(1)
+/** @} */
+VMMR3_INT_DECL(void) VMR3NotifyGlobalFFU(PUVM pUVM, uint32_t fFlags);
+VMMR3_INT_DECL(void) VMR3NotifyCpuFFU(PUVMCPU pUVMCpu, uint32_t fFlags);
+VMMR3DECL(int) VMR3NotifyCpuDeviceReady(PVM pVM, VMCPUID idCpu);
+VMMR3_INT_DECL(int) VMR3WaitHalted(PVM pVM, PVMCPU pVCpu, bool fIgnoreInterrupts);
+VMMR3_INT_DECL(int) VMR3WaitU(PUVMCPU pUVMCpu);
+VMMR3DECL(int) VMR3WaitForDeviceReady(PVM pVM, VMCPUID idCpu);
+VMMR3_INT_DECL(int) VMR3AsyncPdmNotificationWaitU(PUVMCPU pUVCpu);
+VMMR3_INT_DECL(void) VMR3AsyncPdmNotificationWakeupU(PUVM pUVM);
+VMMR3_INT_DECL(RTCPUID) VMR3GetVMCPUId(PVM pVM);
+VMMR3_INT_DECL(bool) VMR3IsLongModeAllowed(PVM pVM);
+VMMR3_INT_DECL(RTTHREAD) VMR3GetThreadHandle(PUVMCPU pUVCpu);
+VMMR3DECL(RTTHREAD) VMR3GetVMCPUThread(PUVM pUVM);
+VMMR3DECL(RTNATIVETHREAD) VMR3GetVMCPUNativeThread(PVM pVM);
+VMMR3DECL(RTNATIVETHREAD) VMR3GetVMCPUNativeThreadU(PUVM pUVM);
+VMMR3DECL(int) VMR3GetCpuCoreAndPackageIdFromCpuId(PUVM pUVM, VMCPUID idCpu, uint32_t *pidCpuCore, uint32_t *pidCpuPackage);
+VMMR3_INT_DECL(uint32_t) VMR3GetActiveEmts(PUVM pUVM);
+VMMR3DECL(int) VMR3HotUnplugCpu(PUVM pUVM, VMCPUID idCpu);
+VMMR3DECL(int) VMR3HotPlugCpu(PUVM pUVM, VMCPUID idCpu);
+VMMR3DECL(int) VMR3SetCpuExecutionCap(PUVM pUVM, uint32_t uCpuExecutionCap);
+VMMR3DECL(int) VMR3SetPowerOffInsteadOfReset(PUVM pUVM, bool fPowerOffInsteadOfReset);
+/** @} */
+#endif /* IN_RING3 */
+
+RT_C_DECLS_END
+
+/** @} */
+
+#endif /* !VBOX_INCLUDED_vmm_vmapi_h */
+
diff --git a/include/VBox/vmm/vmcc.h b/include/VBox/vmm/vmcc.h
new file mode 100644
index 00000000..3a143fae
--- /dev/null
+++ b/include/VBox/vmm/vmcc.h
@@ -0,0 +1,148 @@
+/** @file
+ * VM - The Virtual Machine, GVM/GVMCPU or VM/VMCPU depending on context.
+ */
+
+/*
+ * Copyright (C) 2019-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vmm_vmcc_h
+#define VBOX_INCLUDED_vmm_vmcc_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+
+#include <VBox/vmm/vm.h>
+#ifdef IN_RING0
+# include <VBox/vmm/gvm.h>
+#else
+# include <VBox/vmm/uvm.h>
+#endif
+
+/** @typedef VMCC
+ * Context specific VM derived structure.
+ * This is plain VM in ring-3 and GVM (inherits from VM) in ring-0. */
+/** @typedef VMCPUCC
+ * Context specific VMCPU derived structure.
+ * This is plain VM in ring-3 and GVMCPU (inherits from VMCPU) in ring-0. */
+#ifdef IN_RING0
+typedef GVM VMCC;
+typedef GVMCPU VMCPUCC;
+#else
+typedef VM VMCC;
+typedef VMCPU VMCPUCC;
+#endif
+
+/** @def VMCC_GET_CPU_0
+ * Gets the context specfic pointer to virtual CPU \#0.
+ * @param a_pVM The context specfic VM structure.
+ */
+#ifdef IN_RING0
+# define VMCC_GET_CPU_0(a_pVM) (&(a_pVM)->aCpus[0])
+#else
+# define VMCC_GET_CPU_0(a_pVM) ((a_pVM)->CTX_SUFF(apCpus)[0])
+#endif
+
+/** @def VMCC_GET_CPU
+ * Gets the context specfic pointer to a virtual CPU by index (ID).
+ * @param a_pVM The context specfic VM structure.
+ * @param a_idCpu The CPU number to get (caller ensures validity).
+ */
+#ifdef IN_RING0
+# define VMCC_GET_CPU(a_pVM, a_idCpu) (&(a_pVM)->aCpus[(a_idCpu)])
+#else
+# define VMCC_GET_CPU(a_pVM, a_idCpu) ((a_pVM)->CTX_SUFF(apCpus)[(a_idCpu)])
+#endif
+
+/** @def VMCC_FOR_EACH_VMCPU
+ * For enumerating VCpus in ascending order, avoiding unnecessary apCpusR0
+ * access in ring-0, caching the CPU count and not checking for CPU \#0.
+ *
+ * Defines local variables @c idCpu, @c pVCpu and @c cCpus.
+ *
+ * @param a_pVM The VM handle.
+ *
+ * @note Close loop with VMCC_FOR_EACH_VMCPU_END.
+ */
+#define VMCC_FOR_EACH_VMCPU(a_pVM) \
+ do { \
+ VMCPUID idCpu = 0; \
+ VMCPUID const cCpus = (a_pVM)->cCpus; \
+ PVMCPUCC pVCpu = VMCC_GET_CPU_0(a_pVM); \
+ for (;;) \
+ {
+
+/** @def VMCC_FOR_EACH_VMCPU_END
+ * Ends a VMCC_FOR_EACH_VMCPU loop.
+ * @param a_pVM The VM handle.
+ */
+#define VMCC_FOR_EACH_VMCPU_END(a_pVM) \
+ /* advance */ \
+ if (++idCpu >= cCpus) \
+ break; \
+ pVCpu = VMCC_GET_CPU(pVM, idCpu); \
+ } \
+ } while (0)
+
+/**
+ * Execute the given statement for each virtual CPU in an environment with
+ * @c pVCpu and @c idCpu variables.
+ *
+ * @param a_pVM The VM handle.
+ * @param a_Stmt The statement to execute.
+ */
+#define VMCC_FOR_EACH_VMCPU_STMT(a_pVM, a_Stmt) VMCC_FOR_EACH_VMCPU(pVM) { a_Stmt; } VMCC_FOR_EACH_VMCPU_END(pVM)
+
+/** @def VMCC_GET_VMR0_FOR_CALL(pVM) */
+#if defined(IN_RING3)
+# define VMCC_GET_VMR0_FOR_CALL(a_pVM) ((a_pVM)->pVMR0ForCall)
+#elif defined(IN_RING3)
+# define VMCC_GET_VMR0_FOR_CALL(a_pVM) ((a_pVM)->pVMR0)
+#else
+# define VMCC_GET_VMR0_FOR_CALL(a_pVM) ((a_pVM)->ring3_only_macro)
+#endif
+
+
+/**
+ * Used to pick ring-0 or ring-3 VM component data.
+ *
+ * @code{.cpp}
+ * pVM->VMCC_CTX(pdm).s.pfnWorker
+ * @endcode
+ */
+#ifdef IN_RING0
+# define VMCC_CTX(a_Name) a_Name ## r0
+#else
+# define VMCC_CTX(a_Name) a_Name
+#endif
+
+#endif /* !VBOX_INCLUDED_vmm_vmcc_h */
+
diff --git a/include/VBox/vmm/vmcpuset.h b/include/VBox/vmm/vmcpuset.h
new file mode 100644
index 00000000..496721de
--- /dev/null
+++ b/include/VBox/vmm/vmcpuset.h
@@ -0,0 +1,124 @@
+/** @file
+ * VirtualBox - VMCPUSET Operation.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vmm_vmcpuset_h
+#define VBOX_INCLUDED_vmm_vmcpuset_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/types.h>
+#include <iprt/asm.h>
+#include <iprt/string.h>
+
+/** @defgroup grp_vmcpuset VMCPUSET Operations
+ * @ingroup grp_types_both
+ * @sa VMCPUSET
+ * @{
+ */
+
+/** Tests if a valid CPU ID is present in the set. */
+#define VMCPUSET_IS_PRESENT(pSet, idCpu) ASMBitTest( &(pSet)->au32Bitmap[0], (idCpu))
+/** Adds a CPU to the set. */
+#define VMCPUSET_ADD(pSet, idCpu) ASMBitSet( &(pSet)->au32Bitmap[0], (idCpu))
+/** Deletes a CPU from the set. */
+#define VMCPUSET_DEL(pSet, idCpu) ASMBitClear(&(pSet)->au32Bitmap[0], (idCpu))
+/** Adds a CPU to the set, atomically. */
+#define VMCPUSET_ATOMIC_ADD(pSet, idCpu) ASMAtomicBitSet( &(pSet)->au32Bitmap[0], (idCpu))
+/** Deletes a CPU from the set, atomically. */
+#define VMCPUSET_ATOMIC_DEL(pSet, idCpu) ASMAtomicBitClear(&(pSet)->au32Bitmap[0], (idCpu))
+/** Empties the set. */
+#define VMCPUSET_EMPTY(pSet) memset(&(pSet)->au32Bitmap[0], '\0', sizeof((pSet)->au32Bitmap))
+/** Fills the set. */
+#define VMCPUSET_FILL(pSet) memset(&(pSet)->au32Bitmap[0], 0xff, sizeof((pSet)->au32Bitmap))
+/** Checks if two sets are equal to one another. */
+#define VMCPUSET_IS_EQUAL(pSet1, pSet2) (memcmp(&(pSet1)->au32Bitmap[0], &(pSet2)->au32Bitmap[0], sizeof((pSet1)->au32Bitmap)) == 0)
+/** Checks if the set is empty. */
+#define VMCPUSET_IS_EMPTY(a_pSet) ( (a_pSet)->au32Bitmap[0] == 0 \
+ && (a_pSet)->au32Bitmap[1] == 0 \
+ && (a_pSet)->au32Bitmap[2] == 0 \
+ && (a_pSet)->au32Bitmap[3] == 0 \
+ && (a_pSet)->au32Bitmap[4] == 0 \
+ && (a_pSet)->au32Bitmap[5] == 0 \
+ && (a_pSet)->au32Bitmap[6] == 0 \
+ && (a_pSet)->au32Bitmap[7] == 0 \
+ )
+/** Finds the first CPU present in the SET.
+ * @returns CPU index if found, NIL_VMCPUID if not. */
+#define VMCPUSET_FIND_FIRST_PRESENT(a_pSet) VMCpuSetFindFirstPresentInternal(a_pSet)
+
+/** Implements VMCPUSET_FIND_FIRST_PRESENT.
+ *
+ * @returns CPU index of the first CPU present in the set, NIL_VMCPUID if none
+ * are present.
+ * @param pSet The set to scan.
+ */
+DECLINLINE(int32_t) VMCpuSetFindFirstPresentInternal(PCVMCPUSET pSet)
+{
+ int i = ASMBitFirstSet(&pSet->au32Bitmap[0], RT_ELEMENTS(pSet->au32Bitmap) * 32);
+ return i >= 0 ? (VMCPUID)i : NIL_VMCPUID;
+}
+
+/** Finds the first CPU present in the SET.
+ * @returns CPU index if found, NIL_VMCPUID if not. */
+#define VMCPUSET_FIND_LAST_PRESENT(a_pSet) VMCpuSetFindLastPresentInternal(a_pSet)
+
+/** Implements VMCPUSET_FIND_LAST_PRESENT.
+ *
+ * @returns CPU index of the last CPU present in the set, NIL_VMCPUID if none
+ * are present.
+ * @param pSet The set to scan.
+ */
+DECLINLINE(int32_t) VMCpuSetFindLastPresentInternal(PCVMCPUSET pSet)
+{
+ uint32_t i = RT_ELEMENTS(pSet->au32Bitmap);
+ while (i-- > 0)
+ {
+ uint32_t u = pSet->au32Bitmap[i];
+ if (u)
+ {
+ u = ASMBitLastSetU32(u);
+ u--;
+ u |= i << 5;
+ return u;
+ }
+ }
+ return NIL_VMCPUID;
+}
+
+/** @} */
+
+#endif /* !VBOX_INCLUDED_vmm_vmcpuset_h */
+
diff --git a/include/VBox/vmm/vmm.h b/include/VBox/vmm/vmm.h
new file mode 100644
index 00000000..85df7e4c
--- /dev/null
+++ b/include/VBox/vmm/vmm.h
@@ -0,0 +1,639 @@
+/** @file
+ * VMM - The Virtual Machine Monitor.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vmm_vmm_h
+#define VBOX_INCLUDED_vmm_vmm_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/types.h>
+#include <VBox/vmm/vmapi.h>
+#include <VBox/sup.h>
+#include <VBox/log.h>
+#include <iprt/stdarg.h>
+#include <iprt/thread.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_vmm The Virtual Machine Monitor
+ * @{
+ */
+
+/** @defgroup grp_vmm_api The Virtual Machine Monitor API
+ * @{
+ */
+
+
+/**
+ * Ring-0 assertion notification callback.
+ *
+ * @returns VBox status code.
+ * @param pVCpu The cross context virtual CPU structure.
+ * @param pvUser The user argument.
+ */
+typedef DECLCALLBACKTYPE(int, FNVMMR0ASSERTIONNOTIFICATION,(PVMCPUCC pVCpu, void *pvUser));
+/** Pointer to a FNVMMR0ASSERTIONNOTIFICATION(). */
+typedef FNVMMR0ASSERTIONNOTIFICATION *PFNVMMR0ASSERTIONNOTIFICATION;
+
+/**
+ * Rendezvous callback.
+ *
+ * @returns VBox strict status code - EM scheduling. Do not return
+ * informational status code other than the ones used by EM for
+ * scheduling.
+ *
+ * @param pVM The cross context VM structure.
+ * @param pVCpu The cross context virtual CPU structure of the calling EMT.
+ * @param pvUser The user argument.
+ */
+typedef DECLCALLBACKTYPE(VBOXSTRICTRC, FNVMMEMTRENDEZVOUS,(PVM pVM, PVMCPU pVCpu, void *pvUser));
+/** Pointer to a rendezvous callback function. */
+typedef FNVMMEMTRENDEZVOUS *PFNVMMEMTRENDEZVOUS;
+
+/**
+ * Method table that the VMM uses to call back the user of the VMM.
+ */
+typedef struct VMM2USERMETHODS
+{
+ /** Magic value (VMM2USERMETHODS_MAGIC). */
+ uint32_t u32Magic;
+ /** Structure version (VMM2USERMETHODS_VERSION). */
+ uint32_t u32Version;
+
+ /**
+ * Save the VM state.
+ *
+ * @returns VBox status code.
+ * @param pThis Pointer to the callback method table.
+ * @param pUVM The user mode VM handle.
+ *
+ * @remarks This member shall be set to NULL if the operation is not
+ * supported.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSaveState,(PCVMM2USERMETHODS pThis, PUVM pUVM));
+ /** @todo Move pfnVMAtError and pfnCFGMConstructor here? */
+
+ /**
+ * EMT initialization notification callback.
+ *
+ * This is intended for doing per-thread initialization for EMTs (like COM
+ * init).
+ *
+ * @param pThis Pointer to the callback method table.
+ * @param pUVM The user mode VM handle.
+ * @param pUVCpu The user mode virtual CPU handle.
+ *
+ * @remarks This is optional and shall be set to NULL if not wanted.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnNotifyEmtInit,(PCVMM2USERMETHODS pThis, PUVM pUVM, PUVMCPU pUVCpu));
+
+ /**
+ * EMT termination notification callback.
+ *
+ * This is intended for doing per-thread cleanups for EMTs (like COM).
+ *
+ * @param pThis Pointer to the callback method table.
+ * @param pUVM The user mode VM handle.
+ * @param pUVCpu The user mode virtual CPU handle.
+ *
+ * @remarks This is optional and shall be set to NULL if not wanted.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnNotifyEmtTerm,(PCVMM2USERMETHODS pThis, PUVM pUVM, PUVMCPU pUVCpu));
+
+ /**
+ * PDM thread initialization notification callback.
+ *
+ * This is intended for doing per-thread initialization (like COM init).
+ *
+ * @param pThis Pointer to the callback method table.
+ * @param pUVM The user mode VM handle.
+ *
+ * @remarks This is optional and shall be set to NULL if not wanted.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnNotifyPdmtInit,(PCVMM2USERMETHODS pThis, PUVM pUVM));
+
+ /**
+ * EMT termination notification callback.
+ *
+ * This is intended for doing per-thread cleanups for EMTs (like COM).
+ *
+ * @param pThis Pointer to the callback method table.
+ * @param pUVM The user mode VM handle.
+ *
+ * @remarks This is optional and shall be set to NULL if not wanted.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnNotifyPdmtTerm,(PCVMM2USERMETHODS pThis, PUVM pUVM));
+
+ /**
+ * Notification callback that that a VM reset will be turned into a power off.
+ *
+ * @param pThis Pointer to the callback method table.
+ * @param pUVM The user mode VM handle.
+ *
+ * @remarks This is optional and shall be set to NULL if not wanted.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnNotifyResetTurnedIntoPowerOff,(PCVMM2USERMETHODS pThis, PUVM pUVM));
+
+ /**
+ * Generic object query by UUID.
+ *
+ * @returns pointer to queried the object on success, NULL if not found.
+ *
+ * @param pThis Pointer to the callback method table.
+ * @param pUVM The user mode VM handle.
+ * @param pUuid The UUID of what's being queried. The UUIDs and the
+ * usage conventions are defined by the user.
+ *
+ * @remarks This is optional and shall be set to NULL if not wanted.
+ */
+ DECLR3CALLBACKMEMBER(void *, pfnQueryGenericObject,(PCVMM2USERMETHODS pThis, PUVM pUVM, PCRTUUID pUuid));
+
+ /** Magic value (VMM2USERMETHODS_MAGIC) marking the end of the structure. */
+ uint32_t u32EndMagic;
+} VMM2USERMETHODS;
+
+/** Magic value of the VMM2USERMETHODS (Franz Kafka). */
+#define VMM2USERMETHODS_MAGIC UINT32_C(0x18830703)
+/** The VMM2USERMETHODS structure version. */
+#define VMM2USERMETHODS_VERSION UINT32_C(0x00030000)
+
+
+/**
+ * Checks whether we've armed the ring-0 long jump machinery.
+ *
+ * @returns @c true / @c false
+ * @param a_pVCpu The caller's cross context virtual CPU structure.
+ * @thread EMT
+ * @sa VMMR0IsLongJumpArmed
+ */
+#ifdef IN_RING0
+# define VMMIsLongJumpArmed(a_pVCpu) VMMR0IsLongJumpArmed(a_pVCpu)
+#else
+# define VMMIsLongJumpArmed(a_pVCpu) (false)
+#endif
+
+
+VMMDECL(VMCPUID) VMMGetCpuId(PVMCC pVM);
+VMMDECL(PVMCPUCC) VMMGetCpu(PVMCC pVM);
+VMMDECL(PVMCPUCC) VMMGetCpu0(PVMCC pVM);
+VMMDECL(PVMCPUCC) VMMGetCpuById(PVMCC pVM, VMCPUID idCpu);
+VMMR3DECL(PVMCPUCC) VMMR3GetCpuByIdU(PUVM pVM, VMCPUID idCpu);
+VMM_INT_DECL(uint32_t) VMMGetSvnRev(void);
+VMM_INT_DECL(void) VMMTrashVolatileXMMRegs(void);
+
+
+/** @defgroup grp_vmm_api_r0 The VMM Host Context Ring 0 API
+ * @{
+ */
+
+/**
+ * The VMMR0Entry() codes.
+ */
+typedef enum VMMR0OPERATION
+{
+ /** Run guest code using the available hardware acceleration technology. */
+ VMMR0_DO_HM_RUN = SUP_VMMR0_DO_HM_RUN,
+ /** Official NOP that we use for profiling. */
+ VMMR0_DO_NEM_RUN = SUP_VMMR0_DO_NEM_RUN,
+ /** Official NOP that we use for profiling. */
+ VMMR0_DO_NOP = SUP_VMMR0_DO_NOP,
+ /** Official slow iocl NOP that we use for profiling. */
+ VMMR0_DO_SLOW_NOP,
+
+ /** Ask the GVMM to create a new VM. */
+ VMMR0_DO_GVMM_CREATE_VM = 32,
+ /** Ask the GVMM to destroy the VM. */
+ VMMR0_DO_GVMM_DESTROY_VM,
+ /** Call GVMMR0RegisterVCpu(). */
+ VMMR0_DO_GVMM_REGISTER_VMCPU,
+ /** Call GVMMR0DeregisterVCpu(). */
+ VMMR0_DO_GVMM_DEREGISTER_VMCPU,
+ /** Call GVMMR0RegisterWorkerThread(). */
+ VMMR0_DO_GVMM_REGISTER_WORKER_THREAD,
+ /** Call GVMMR0DeregisterWorkerThread(). */
+ VMMR0_DO_GVMM_DEREGISTER_WORKER_THREAD,
+ /** Call GVMMR0SchedHalt(). */
+ VMMR0_DO_GVMM_SCHED_HALT,
+ /** Call GVMMR0SchedWakeUp(). */
+ VMMR0_DO_GVMM_SCHED_WAKE_UP,
+ /** Call GVMMR0SchedPoke(). */
+ VMMR0_DO_GVMM_SCHED_POKE,
+ /** Call GVMMR0SchedWakeUpAndPokeCpus(). */
+ VMMR0_DO_GVMM_SCHED_WAKE_UP_AND_POKE_CPUS,
+ /** Call GVMMR0SchedPoll(). */
+ VMMR0_DO_GVMM_SCHED_POLL,
+ /** Call GVMMR0QueryStatistics(). */
+ VMMR0_DO_GVMM_QUERY_STATISTICS,
+ /** Call GVMMR0ResetStatistics(). */
+ VMMR0_DO_GVMM_RESET_STATISTICS,
+
+ /** Call VMMR0 Per VM Init. */
+ VMMR0_DO_VMMR0_INIT = 64,
+ /** Call VMMR0 Per VM EMT Init */
+ VMMR0_DO_VMMR0_INIT_EMT,
+ /** Call VMMR0 Per VM Termination. */
+ VMMR0_DO_VMMR0_TERM,
+ /** Copy logger settings from userland, VMMR0UpdateLoggersReq(). */
+ VMMR0_DO_VMMR0_UPDATE_LOGGERS,
+ /** Used by the log flusher, VMMR0LogFlusher. */
+ VMMR0_DO_VMMR0_LOG_FLUSHER,
+ /** Used by EMTs to wait for the log flusher to finish, VMMR0LogWaitFlushed. */
+ VMMR0_DO_VMMR0_LOG_WAIT_FLUSHED,
+
+ /** Setup hardware-assisted VM session. */
+ VMMR0_DO_HM_SETUP_VM = 128,
+ /** Attempt to enable or disable hardware-assisted mode. */
+ VMMR0_DO_HM_ENABLE,
+
+ /** Call PGMR0PhysAllocateHandyPages(). */
+ VMMR0_DO_PGM_ALLOCATE_HANDY_PAGES = 192,
+ /** Call PGMR0PhysFlushHandyPages(). */
+ VMMR0_DO_PGM_FLUSH_HANDY_PAGES,
+ /** Call PGMR0AllocateLargePage(). */
+ VMMR0_DO_PGM_ALLOCATE_LARGE_PAGE,
+ /** Call PGMR0PhysSetupIommu(). */
+ VMMR0_DO_PGM_PHYS_SETUP_IOMMU,
+ /** Call PGMR0PoolGrow(). */
+ VMMR0_DO_PGM_POOL_GROW,
+ /** Call PGMR0PhysHandlerInitReqHandler(). */
+ VMMR0_DO_PGM_PHYS_HANDLER_INIT,
+
+ /** Call GMMR0InitialReservation(). */
+ VMMR0_DO_GMM_INITIAL_RESERVATION = 256,
+ /** Call GMMR0UpdateReservation(). */
+ VMMR0_DO_GMM_UPDATE_RESERVATION,
+ /** Call GMMR0AllocatePages(). */
+ VMMR0_DO_GMM_ALLOCATE_PAGES,
+ /** Call GMMR0FreePages(). */
+ VMMR0_DO_GMM_FREE_PAGES,
+ /** Call GMMR0FreeLargePage(). */
+ VMMR0_DO_GMM_FREE_LARGE_PAGE,
+ /** Call GMMR0QueryHypervisorMemoryStatsReq(). */
+ VMMR0_DO_GMM_QUERY_HYPERVISOR_MEM_STATS,
+ /** Call GMMR0QueryMemoryStatsReq(). */
+ VMMR0_DO_GMM_QUERY_MEM_STATS,
+ /** Call GMMR0BalloonedPages(). */
+ VMMR0_DO_GMM_BALLOONED_PAGES,
+ /** Call GMMR0MapUnmapChunk(). */
+ VMMR0_DO_GMM_MAP_UNMAP_CHUNK,
+ /** Call GMMR0RegisterSharedModule. */
+ VMMR0_DO_GMM_REGISTER_SHARED_MODULE,
+ /** Call GMMR0UnregisterSharedModule. */
+ VMMR0_DO_GMM_UNREGISTER_SHARED_MODULE,
+ /** Call GMMR0ResetSharedModules. */
+ VMMR0_DO_GMM_RESET_SHARED_MODULES,
+ /** Call GMMR0CheckSharedModules. */
+ VMMR0_DO_GMM_CHECK_SHARED_MODULES,
+ /** Call GMMR0FindDuplicatePage. */
+ VMMR0_DO_GMM_FIND_DUPLICATE_PAGE,
+ /** Call GMMR0QueryStatistics(). */
+ VMMR0_DO_GMM_QUERY_STATISTICS,
+ /** Call GMMR0ResetStatistics(). */
+ VMMR0_DO_GMM_RESET_STATISTICS,
+
+ /** Call PDMR0DriverCallReqHandler. */
+ VMMR0_DO_PDM_DRIVER_CALL_REQ_HANDLER = 320,
+ /** Call PDMR0DeviceCreateReqHandler. */
+ VMMR0_DO_PDM_DEVICE_CREATE,
+ /** Call PDMR0DeviceGenCallReqHandler. */
+ VMMR0_DO_PDM_DEVICE_GEN_CALL,
+ /** Old style device compat: Set ring-0 critical section. */
+ VMMR0_DO_PDM_DEVICE_COMPAT_SET_CRITSECT,
+ /** Call PDMR0QueueCreateReqHandler. */
+ VMMR0_DO_PDM_QUEUE_CREATE,
+
+ /** Set a GVMM or GMM configuration value. */
+ VMMR0_DO_GCFGM_SET_VALUE = 400,
+ /** Query a GVMM or GMM configuration value. */
+ VMMR0_DO_GCFGM_QUERY_VALUE,
+
+ /** The start of the R0 service operations. */
+ VMMR0_DO_SRV_START = 448,
+ /** Call IntNetR0Open(). */
+ VMMR0_DO_INTNET_OPEN,
+ /** Call IntNetR0IfClose(). */
+ VMMR0_DO_INTNET_IF_CLOSE,
+ /** Call IntNetR0IfGetBufferPtrs(). */
+ VMMR0_DO_INTNET_IF_GET_BUFFER_PTRS,
+ /** Call IntNetR0IfSetPromiscuousMode(). */
+ VMMR0_DO_INTNET_IF_SET_PROMISCUOUS_MODE,
+ /** Call IntNetR0IfSetMacAddress(). */
+ VMMR0_DO_INTNET_IF_SET_MAC_ADDRESS,
+ /** Call IntNetR0IfSetActive(). */
+ VMMR0_DO_INTNET_IF_SET_ACTIVE,
+ /** Call IntNetR0IfSend(). */
+ VMMR0_DO_INTNET_IF_SEND,
+ /** Call IntNetR0IfWait(). */
+ VMMR0_DO_INTNET_IF_WAIT,
+ /** Call IntNetR0IfAbortWait(). */
+ VMMR0_DO_INTNET_IF_ABORT_WAIT,
+
+#if 0
+ /** Forward call to the PCI driver */
+ VMMR0_DO_PCIRAW_REQ = 512,
+#endif
+
+ /** The end of the R0 service operations. */
+ VMMR0_DO_SRV_END,
+
+ /** Call NEMR0InitVM() (host specific). */
+ VMMR0_DO_NEM_INIT_VM = 576,
+ /** Call NEMR0InitVMPart2() (host specific). */
+ VMMR0_DO_NEM_INIT_VM_PART_2,
+ /** Call NEMR0MapPages() (host specific). */
+ VMMR0_DO_NEM_MAP_PAGES,
+ /** Call NEMR0UnmapPages() (host specific). */
+ VMMR0_DO_NEM_UNMAP_PAGES,
+ /** Call NEMR0ExportState() (host specific). */
+ VMMR0_DO_NEM_EXPORT_STATE,
+ /** Call NEMR0ImportState() (host specific). */
+ VMMR0_DO_NEM_IMPORT_STATE,
+ /** Call NEMR0QueryCpuTick() (host specific). */
+ VMMR0_DO_NEM_QUERY_CPU_TICK,
+ /** Call NEMR0ResumeCpuTickOnAll() (host specific). */
+ VMMR0_DO_NEM_RESUME_CPU_TICK_ON_ALL,
+ /** Call NEMR0UpdateStatistics() (host specific). */
+ VMMR0_DO_NEM_UPDATE_STATISTICS,
+ /** Call NEMR0DoExperiment() (host specific, experimental, debug only). */
+ VMMR0_DO_NEM_EXPERIMENT,
+
+ /** Grow the I/O port registration tables. */
+ VMMR0_DO_IOM_GROW_IO_PORTS = 640,
+ /** Grow the I/O port statistics tables. */
+ VMMR0_DO_IOM_GROW_IO_PORT_STATS,
+ /** Grow the MMIO registration tables. */
+ VMMR0_DO_IOM_GROW_MMIO_REGS,
+ /** Grow the MMIO statistics tables. */
+ VMMR0_DO_IOM_GROW_MMIO_STATS,
+ /** Synchronize statistics indices for I/O ports and MMIO regions. */
+ VMMR0_DO_IOM_SYNC_STATS_INDICES,
+
+ /** Call DBGFR0TraceCreateReqHandler. */
+ VMMR0_DO_DBGF_TRACER_CREATE = 704,
+ /** Call DBGFR0TraceCallReqHandler. */
+ VMMR0_DO_DBGF_TRACER_CALL_REQ_HANDLER,
+ /** Call DBGFR0BpInitReqHandler(). */
+ VMMR0_DO_DBGF_BP_INIT,
+ /** Call DBGFR0BpChunkAllocReqHandler(). */
+ VMMR0_DO_DBGF_BP_CHUNK_ALLOC,
+ /** Call DBGFR0BpL2TblChunkAllocReqHandler(). */
+ VMMR0_DO_DBGF_BP_L2_TBL_CHUNK_ALLOC,
+ /** Call DBGFR0BpOwnerInitReqHandler(). */
+ VMMR0_DO_DBGF_BP_OWNER_INIT,
+ /** Call DBGFR0BpPortIoInitReqHandler(). */
+ VMMR0_DO_DBGF_BP_PORTIO_INIT,
+
+ /** Grow a timer queue. */
+ VMMR0_DO_TM_GROW_TIMER_QUEUE = 768,
+
+ /** Official call we use for testing Ring-0 APIs. */
+ VMMR0_DO_TESTS = 2048,
+
+ /** The usual 32-bit type blow up. */
+ VMMR0_DO_32BIT_HACK = 0x7fffffff
+} VMMR0OPERATION;
+
+
+/**
+ * Request buffer for VMMR0_DO_GCFGM_SET_VALUE and VMMR0_DO_GCFGM_QUERY_VALUE.
+ * @todo Move got GCFGM.h when it's implemented.
+ */
+typedef struct GCFGMVALUEREQ
+{
+ /** The request header.*/
+ SUPVMMR0REQHDR Hdr;
+ /** The support driver session handle. */
+ PSUPDRVSESSION pSession;
+ /** The value.
+ * This is input for the set request and output for the query. */
+ uint64_t u64Value;
+ /** The variable name.
+ * This is fixed sized just to make things simple for the mock-up. */
+ char szName[48];
+} GCFGMVALUEREQ;
+/** Pointer to a VMMR0_DO_GCFGM_SET_VALUE and VMMR0_DO_GCFGM_QUERY_VALUE request buffer.
+ * @todo Move got GCFGM.h when it's implemented.
+ */
+typedef GCFGMVALUEREQ *PGCFGMVALUEREQ;
+
+
+/**
+ * Request package for VMMR0_DO_VMMR0_UPDATE_LOGGERS.
+ *
+ * In addition the u64Arg is selects the logger and indicates whether we're only
+ * outputting to the parent VMM. See VMMR0UPDATELOGGER_F_XXX.
+ */
+typedef struct VMMR0UPDATELOGGERSREQ
+{
+ /** The request header. */
+ SUPVMMR0REQHDR Hdr;
+ /** The current logger flags (RTLOGFLAGS). */
+ uint64_t fFlags;
+ /** Groups, assuming same group layout as ring-3. */
+ uint32_t cGroups;
+ /** CRC32 of the group names. */
+ uint32_t uGroupCrc32;
+ /** Per-group settings, variable size. */
+ RT_FLEXIBLE_ARRAY_EXTENSION
+ uint32_t afGroups[RT_FLEXIBLE_ARRAY];
+} VMMR0UPDATELOGGERSREQ;
+/** Pointer to a VMMR0_DO_VMMR0_UPDATE_LOGGERS request. */
+typedef VMMR0UPDATELOGGERSREQ *PVMMR0UPDATELOGGERSREQ;
+
+/** @name VMMR0UPDATELOGGER_F_XXX - u64Arg definitions for VMMR0_DO_VMMR0_UPDATE_LOGGERS.
+ * @{ */
+/** Logger index mask. */
+#define VMMR0UPDATELOGGER_F_LOGGER_MASK UINT64_C(0x0001)
+/** Only flush to the parent VMM's debug log, don't return to ring-3. */
+#define VMMR0UPDATELOGGER_F_TO_PARENT_VMM_DBG UINT64_C(0x0002)
+/** Only flush to the parent VMM's debug log, don't return to ring-3. */
+#define VMMR0UPDATELOGGER_F_TO_PARENT_VMM_REL UINT64_C(0x0004)
+/** Valid flag mask. */
+#define VMMR0UPDATELOGGER_F_VALID_MASK UINT64_C(0x0007)
+/** @} */
+
+#if defined(IN_RING0) || defined(DOXYGEN_RUNNING)
+
+/**
+ * Structure VMMR0EmtPrepareToBlock uses to pass info to
+ * VMMR0EmtResumeAfterBlocking.
+ */
+typedef struct VMMR0EMTBLOCKCTX
+{
+ /** Magic value (VMMR0EMTBLOCKCTX_MAGIC). */
+ uint32_t uMagic;
+ /** Set if we were in HM context, clear if not. */
+ bool fWasInHmContext;
+} VMMR0EMTBLOCKCTX;
+/** Pointer to a VMMR0EmtPrepareToBlock context structure. */
+typedef VMMR0EMTBLOCKCTX *PVMMR0EMTBLOCKCTX;
+/** Magic value for VMMR0EMTBLOCKCTX::uMagic (Paul Desmond). */
+#define VMMR0EMTBLOCKCTX_MAGIC UINT32_C(0x19261125)
+/** Magic value for VMMR0EMTBLOCKCTX::uMagic when its out of context. */
+#define VMMR0EMTBLOCKCTX_MAGIC_DEAD UINT32_C(0x19770530)
+
+VMMR0DECL(void) VMMR0EntryFast(PGVM pGVM, PVMCC pVM, VMCPUID idCpu, VMMR0OPERATION enmOperation);
+VMMR0DECL(int) VMMR0EntryEx(PGVM pGVM, PVMCC pVM, VMCPUID idCpu, VMMR0OPERATION enmOperation,
+ PSUPVMMR0REQHDR pReq, uint64_t u64Arg, PSUPDRVSESSION);
+VMMR0_INT_DECL(int) VMMR0InitPerVMData(PGVM pGVM);
+VMMR0_INT_DECL(int) VMMR0TermVM(PGVM pGVM, VMCPUID idCpu);
+VMMR0_INT_DECL(void) VMMR0CleanupVM(PGVM pGVM);
+VMMR0_INT_DECL(bool) VMMR0IsLongJumpArmed(PVMCPUCC pVCpu);
+VMMR0_INT_DECL(int) VMMR0ThreadCtxHookCreateForEmt(PVMCPUCC pVCpu);
+VMMR0_INT_DECL(void) VMMR0ThreadCtxHookDestroyForEmt(PVMCPUCC pVCpu);
+VMMR0_INT_DECL(void) VMMR0ThreadCtxHookDisable(PVMCPUCC pVCpu);
+VMMR0_INT_DECL(bool) VMMR0ThreadCtxHookIsEnabled(PVMCPUCC pVCpu);
+VMMR0_INT_DECL(int) VMMR0EmtPrepareToBlock(PVMCPUCC pVCpu, int rcBusy, const char *pszCaller, void *pvLock,
+ PVMMR0EMTBLOCKCTX pCtx);
+VMMR0_INT_DECL(void) VMMR0EmtResumeAfterBlocking(PVMCPUCC pVCpu, PVMMR0EMTBLOCKCTX pCtx);
+VMMR0_INT_DECL(int) VMMR0EmtWaitEventInner(PGVMCPU pGVCpu, uint32_t fFlags, RTSEMEVENT hEvent, RTMSINTERVAL cMsTimeout);
+VMMR0_INT_DECL(int) VMMR0EmtSignalSupEvent(PGVM pGVM, PGVMCPU pGVCpu, SUPSEMEVENT hEvent);
+VMMR0_INT_DECL(int) VMMR0EmtSignalSupEventByGVM(PGVM pGVM, SUPSEMEVENT hEvent);
+VMMR0_INT_DECL(int) VMMR0AssertionSetNotification(PVMCPUCC pVCpu, PFNVMMR0ASSERTIONNOTIFICATION pfnCallback, RTR0PTR pvUser);
+VMMR0_INT_DECL(void) VMMR0AssertionRemoveNotification(PVMCPUCC pVCpu);
+VMMR0_INT_DECL(bool) VMMR0AssertionIsNotificationSet(PVMCPUCC pVCpu);
+
+/** @name VMMR0EMTWAIT_F_XXX - flags for VMMR0EmtWaitEventInner and friends.
+ * @{ */
+/** Try suppress VERR_INTERRUPTED for a little while (~10 sec). */
+#define VMMR0EMTWAIT_F_TRY_SUPPRESS_INTERRUPTED RT_BIT_32(0)
+/** @} */
+#endif /* IN_RING0 */
+
+VMMR0_INT_DECL(PRTLOGGER) VMMR0GetReleaseLogger(PVMCPUCC pVCpu);
+/** @} */
+
+
+#if defined(IN_RING3) || defined(DOXYGEN_RUNNING)
+/** @defgroup grp_vmm_api_r3 The VMM Host Context Ring 3 API
+ * @{
+ */
+VMMR3DECL(PCVMMR3VTABLE) VMMR3GetVTable(void);
+VMMR3_INT_DECL(int) VMMR3Init(PVM pVM);
+VMMR3_INT_DECL(int) VMMR3InitR0(PVM pVM);
+VMMR3_INT_DECL(int) VMMR3InitCompleted(PVM pVM, VMINITCOMPLETED enmWhat);
+VMMR3_INT_DECL(int) VMMR3Term(PVM pVM);
+VMMR3_INT_DECL(void) VMMR3Relocate(PVM pVM, RTGCINTPTR offDelta);
+VMMR3_INT_DECL(int) VMMR3UpdateLoggers(PVM pVM);
+VMMR3DECL(const char *) VMMR3GetRZAssertMsg1(PVM pVM);
+VMMR3DECL(const char *) VMMR3GetRZAssertMsg2(PVM pVM);
+VMMR3_INT_DECL(int) VMMR3HmRunGC(PVM pVM, PVMCPU pVCpu);
+VMMR3DECL(int) VMMR3CallR0(PVM pVM, uint32_t uOperation, uint64_t u64Arg, PSUPVMMR0REQHDR pReqHdr);
+VMMR3_INT_DECL(int) VMMR3CallR0Emt(PVM pVM, PVMCPU pVCpu, VMMR0OPERATION enmOperation, uint64_t u64Arg, PSUPVMMR0REQHDR pReqHdr);
+VMMR3_INT_DECL(VBOXSTRICTRC) VMMR3CallR0EmtFast(PVM pVM, PVMCPU pVCpu, VMMR0OPERATION enmOperation);
+VMMR3DECL(void) VMMR3FatalDump(PVM pVM, PVMCPU pVCpu, int rcErr);
+VMMR3_INT_DECL(void) VMMR3YieldSuspend(PVM pVM);
+VMMR3_INT_DECL(void) VMMR3YieldStop(PVM pVM);
+VMMR3_INT_DECL(void) VMMR3YieldResume(PVM pVM);
+VMMR3_INT_DECL(void) VMMR3SendStartupIpi(PVM pVM, VMCPUID idCpu, uint32_t uVector);
+VMMR3_INT_DECL(void) VMMR3SendInitIpi(PVM pVM, VMCPUID idCpu);
+VMMR3DECL(int) VMMR3RegisterPatchMemory(PVM pVM, RTGCPTR pPatchMem, unsigned cbPatchMem);
+VMMR3DECL(int) VMMR3DeregisterPatchMemory(PVM pVM, RTGCPTR pPatchMem, unsigned cbPatchMem);
+VMMR3DECL(int) VMMR3EmtRendezvous(PVM pVM, uint32_t fFlags, PFNVMMEMTRENDEZVOUS pfnRendezvous, void *pvUser);
+/** @defgroup grp_VMMR3EmtRendezvous_fFlags VMMR3EmtRendezvous flags
+ * @{ */
+/** Execution type mask. */
+#define VMMEMTRENDEZVOUS_FLAGS_TYPE_MASK UINT32_C(0x00000007)
+/** Invalid execution type. */
+#define VMMEMTRENDEZVOUS_FLAGS_TYPE_INVALID UINT32_C(0)
+/** Let the EMTs execute the callback one by one (in no particular order).
+ * Recursion from within the callback possible. */
+#define VMMEMTRENDEZVOUS_FLAGS_TYPE_ONE_BY_ONE UINT32_C(1)
+/** Let all the EMTs execute the callback at the same time.
+ * Cannot recurse from the callback. */
+#define VMMEMTRENDEZVOUS_FLAGS_TYPE_ALL_AT_ONCE UINT32_C(2)
+/** Only execute the callback on one EMT (no particular one).
+ * Recursion from within the callback possible. */
+#define VMMEMTRENDEZVOUS_FLAGS_TYPE_ONCE UINT32_C(3)
+/** Let the EMTs execute the callback one by one in ascending order.
+ * Recursion from within the callback possible. */
+#define VMMEMTRENDEZVOUS_FLAGS_TYPE_ASCENDING UINT32_C(4)
+/** Let the EMTs execute the callback one by one in descending order.
+ * Recursion from within the callback possible. */
+#define VMMEMTRENDEZVOUS_FLAGS_TYPE_DESCENDING UINT32_C(5)
+/** Stop after the first error.
+ * This is not valid for any execution type where more than one EMT is active
+ * at a time. */
+#define VMMEMTRENDEZVOUS_FLAGS_STOP_ON_ERROR UINT32_C(0x00000008)
+/** Use VMREQFLAGS_PRIORITY when contacting the EMTs. */
+#define VMMEMTRENDEZVOUS_FLAGS_PRIORITY UINT32_C(0x00000010)
+/** The valid flags. */
+#define VMMEMTRENDEZVOUS_FLAGS_VALID_MASK UINT32_C(0x0000001f)
+/** @} */
+VMMR3_INT_DECL(int) VMMR3EmtRendezvousFF(PVM pVM, PVMCPU pVCpu);
+VMMR3_INT_DECL(void) VMMR3SetMayHaltInRing0(PVMCPU pVCpu, bool fMayHaltInRing0, uint32_t cNsSpinBlockThreshold);
+VMMR3_INT_DECL(int) VMMR3ReadR0Stack(PVM pVM, VMCPUID idCpu, RTHCUINTPTR R0Addr, void *pvBuf, size_t cbRead);
+VMMR3_INT_DECL(void) VMMR3InitR0StackUnwindState(PUVM pUVM, VMCPUID idCpu, PRTDBGUNWINDSTATE pState);
+/** @} */
+#endif /* IN_RING3 */
+
+
+#if defined(IN_RC) || defined(IN_RING0) || defined(DOXYGEN_RUNNING)
+/** @defgroup grp_vmm_api_rz The VMM Raw-Mode and Ring-0 Context API
+ * @{
+ */
+VMMRZDECL(void) VMMRZCallRing3Disable(PVMCPUCC pVCpu);
+VMMRZDECL(void) VMMRZCallRing3Enable(PVMCPUCC pVCpu);
+VMMRZDECL(bool) VMMRZCallRing3IsEnabled(PVMCPUCC pVCpu);
+/** @} */
+#endif
+
+
+/** Wrapper around AssertReleaseMsgReturn that avoid tripping up in the
+ * kernel when we don't have a setjmp in place. */
+#ifdef IN_RING0
+# define VMM_ASSERT_RELEASE_MSG_RETURN(a_pVM, a_Expr, a_Msg, a_rc) do { \
+ if (RT_LIKELY(a_Expr)) { /* likely */ } \
+ else \
+ { \
+ PVMCPUCC pVCpuAssert = VMMGetCpu(a_pVM); \
+ if (pVCpuAssert && VMMR0IsLongJumpArmed(pVCpuAssert)) \
+ AssertReleaseMsg(a_Expr, a_Msg); \
+ else \
+ AssertLogRelMsg(a_Expr, a_Msg); \
+ return (a_rc); \
+ } \
+ } while (0)
+#else
+# define VMM_ASSERT_RELEASE_MSG_RETURN(a_pVM, a_Expr, a_Msg, a_rc) AssertReleaseMsgReturn(a_Expr, a_Msg, a_rc)
+#endif
+
+/** @} */
+
+/** @} */
+RT_C_DECLS_END
+
+#endif /* !VBOX_INCLUDED_vmm_vmm_h */
diff --git a/include/VBox/vmm/vmmr3vtable-def.h b/include/VBox/vmm/vmmr3vtable-def.h
new file mode 100644
index 00000000..b95fdb47
--- /dev/null
+++ b/include/VBox/vmm/vmmr3vtable-def.h
@@ -0,0 +1,711 @@
+/** @file
+ * VM - The Virtual Machine Monitor, VTable ring-3 API, Definition Template.
+ *
+ * This is used by the vmmr3vtable.h header and the VMMR3VTable.cpp source file
+ * that implements it.
+ */
+
+/*
+ * Copyright (C) 2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+
+/** @name VMM
+ * @{ */
+VTABLE_ENTRY(VMMGetSvnRev)
+VTABLE_ENTRY(VMMGetCpu)
+
+VTABLE_RESERVED(pfnVMMR3Reserved1)
+VTABLE_RESERVED(pfnVMMR3Reserved2)
+VTABLE_RESERVED(pfnVMMR3Reserved3)
+VTABLE_RESERVED(pfnVMMR3Reserved4)
+VTABLE_RESERVED(pfnVMMR3Reserved5)
+/** @} */
+
+/** @name VM
+ * @{
+ */
+VTABLE_ENTRY(VMR3Create)
+VTABLE_ENTRY(VMR3PowerOn)
+VTABLE_ENTRY(VMR3Suspend)
+VTABLE_ENTRY(VMR3GetSuspendReason)
+VTABLE_ENTRY(VMR3Resume)
+VTABLE_ENTRY(VMR3GetResumeReason)
+VTABLE_ENTRY(VMR3Reset)
+VTABLE_ENTRY(VMR3Save)
+VTABLE_ENTRY(VMR3Teleport)
+VTABLE_ENTRY(VMR3LoadFromFile)
+VTABLE_ENTRY(VMR3LoadFromStream)
+VTABLE_ENTRY(VMR3PowerOff)
+VTABLE_ENTRY(VMR3Destroy)
+
+VTABLE_ENTRY(VMR3GetVM)
+VTABLE_ENTRY(VMR3GetUVM)
+VTABLE_ENTRY(VMR3RetainUVM)
+VTABLE_ENTRY(VMR3ReleaseUVM)
+VTABLE_ENTRY(VMR3GetName)
+VTABLE_ENTRY(VMR3GetUuid)
+VTABLE_ENTRY(VMR3GetState)
+VTABLE_ENTRY(VMR3GetStateU)
+VTABLE_ENTRY(VMR3GetStateName)
+VTABLE_ENTRY(VMR3AtStateRegister)
+VTABLE_ENTRY(VMR3AtStateDeregister)
+VTABLE_ENTRY(VMR3AtErrorRegister)
+VTABLE_ENTRY(VMR3AtErrorDeregister)
+VTABLE_ENTRY(VMR3SetError)
+VTABLE_ENTRY(VMR3SetErrorV)
+VTABLE_ENTRY(VMR3AtRuntimeErrorRegister)
+VTABLE_ENTRY(VMR3AtRuntimeErrorDeregister)
+
+VTABLE_ENTRY(VMR3ReqCallU)
+VTABLE_ENTRY(VMR3ReqCallVU)
+VTABLE_ENTRY(VMR3ReqCallWaitU)
+VTABLE_ENTRY(VMR3ReqCallNoWait)
+VTABLE_ENTRY(VMR3ReqCallNoWaitU)
+VTABLE_ENTRY(VMR3ReqCallVoidWaitU)
+VTABLE_ENTRY(VMR3ReqCallVoidNoWait)
+VTABLE_ENTRY(VMR3ReqPriorityCallWait)
+VTABLE_ENTRY(VMR3ReqPriorityCallWaitU)
+VTABLE_ENTRY(VMR3ReqPriorityCallVoidWaitU)
+VTABLE_ENTRY(VMR3ReqAlloc)
+VTABLE_ENTRY(VMR3ReqFree)
+VTABLE_ENTRY(VMR3ReqQueue)
+VTABLE_ENTRY(VMR3ReqWait)
+
+VTABLE_ENTRY(VMR3NotifyCpuDeviceReady)
+VTABLE_ENTRY(VMR3WaitForDeviceReady)
+VTABLE_ENTRY(VMR3GetVMCPUThread)
+VTABLE_ENTRY(VMR3GetVMCPUNativeThread)
+VTABLE_ENTRY(VMR3GetVMCPUNativeThreadU)
+VTABLE_ENTRY(VMR3GetCpuCoreAndPackageIdFromCpuId)
+VTABLE_ENTRY(VMR3HotUnplugCpu)
+VTABLE_ENTRY(VMR3HotPlugCpu)
+VTABLE_ENTRY(VMR3SetCpuExecutionCap)
+VTABLE_ENTRY(VMR3SetPowerOffInsteadOfReset)
+
+VTABLE_RESERVED(pfnVMR3Reserved1)
+VTABLE_RESERVED(pfnVMR3Reserved2)
+VTABLE_RESERVED(pfnVMR3Reserved3)
+VTABLE_RESERVED(pfnVMR3Reserved4)
+VTABLE_RESERVED(pfnVMR3Reserved5)
+/** @} */
+
+/** @name CFGM
+ * @{ */
+VTABLE_ENTRY(CFGMR3Init)
+VTABLE_ENTRY(CFGMR3Term)
+VTABLE_ENTRY(CFGMR3ConstructDefaultTree)
+
+VTABLE_ENTRY(CFGMR3CreateTree)
+VTABLE_ENTRY(CFGMR3DestroyTree)
+VTABLE_ENTRY(CFGMR3Dump)
+VTABLE_ENTRY(CFGMR3DuplicateSubTree)
+VTABLE_ENTRY(CFGMR3ReplaceSubTree)
+VTABLE_ENTRY(CFGMR3InsertSubTree)
+VTABLE_ENTRY(CFGMR3InsertNode)
+VTABLE_ENTRY(CFGMR3InsertNodeF)
+VTABLE_ENTRY(CFGMR3InsertNodeFV)
+VTABLE_ENTRY(CFGMR3SetRestrictedRoot)
+VTABLE_ENTRY(CFGMR3RemoveNode)
+VTABLE_ENTRY(CFGMR3InsertInteger)
+VTABLE_ENTRY(CFGMR3InsertString)
+VTABLE_ENTRY(CFGMR3InsertStringN)
+VTABLE_ENTRY(CFGMR3InsertStringF)
+VTABLE_ENTRY(CFGMR3InsertStringFV)
+VTABLE_ENTRY(CFGMR3InsertStringW)
+VTABLE_ENTRY(CFGMR3InsertBytes)
+VTABLE_ENTRY(CFGMR3InsertPassword)
+VTABLE_ENTRY(CFGMR3InsertPasswordN)
+VTABLE_ENTRY(CFGMR3InsertValue)
+VTABLE_ENTRY(CFGMR3RemoveValue)
+VTABLE_ENTRY(CFGMR3CopyTree)
+
+VTABLE_ENTRY(CFGMR3Exists)
+VTABLE_ENTRY(CFGMR3QueryType)
+VTABLE_ENTRY(CFGMR3QuerySize)
+VTABLE_ENTRY(CFGMR3QueryInteger)
+VTABLE_ENTRY(CFGMR3QueryIntegerDef)
+VTABLE_ENTRY(CFGMR3QueryString)
+VTABLE_ENTRY(CFGMR3QueryStringDef)
+VTABLE_ENTRY(CFGMR3QueryPassword)
+VTABLE_ENTRY(CFGMR3QueryPasswordDef)
+VTABLE_ENTRY(CFGMR3QueryBytes)
+
+VTABLE_ENTRY(CFGMR3QueryU64)
+VTABLE_ENTRY(CFGMR3QueryU64Def)
+VTABLE_ENTRY(CFGMR3QueryS64)
+VTABLE_ENTRY(CFGMR3QueryS64Def)
+VTABLE_ENTRY(CFGMR3QueryU32)
+VTABLE_ENTRY(CFGMR3QueryU32Def)
+VTABLE_ENTRY(CFGMR3QueryS32)
+VTABLE_ENTRY(CFGMR3QueryS32Def)
+VTABLE_ENTRY(CFGMR3QueryU16)
+VTABLE_ENTRY(CFGMR3QueryU16Def)
+VTABLE_ENTRY(CFGMR3QueryS16)
+VTABLE_ENTRY(CFGMR3QueryS16Def)
+VTABLE_ENTRY(CFGMR3QueryU8)
+VTABLE_ENTRY(CFGMR3QueryU8Def)
+VTABLE_ENTRY(CFGMR3QueryS8)
+VTABLE_ENTRY(CFGMR3QueryS8Def)
+VTABLE_ENTRY(CFGMR3QueryBool)
+VTABLE_ENTRY(CFGMR3QueryBoolDef)
+VTABLE_ENTRY(CFGMR3QueryPort)
+VTABLE_ENTRY(CFGMR3QueryPortDef)
+VTABLE_ENTRY(CFGMR3QueryUInt)
+VTABLE_ENTRY(CFGMR3QueryUIntDef)
+VTABLE_ENTRY(CFGMR3QuerySInt)
+VTABLE_ENTRY(CFGMR3QuerySIntDef)
+VTABLE_ENTRY(CFGMR3QueryGCPtr)
+VTABLE_ENTRY(CFGMR3QueryGCPtrDef)
+VTABLE_ENTRY(CFGMR3QueryGCPtrU)
+VTABLE_ENTRY(CFGMR3QueryGCPtrUDef)
+VTABLE_ENTRY(CFGMR3QueryGCPtrS)
+VTABLE_ENTRY(CFGMR3QueryGCPtrSDef)
+VTABLE_ENTRY(CFGMR3QueryStringAlloc)
+VTABLE_ENTRY(CFGMR3QueryStringAllocDef)
+
+VTABLE_ENTRY(CFGMR3GetRoot)
+VTABLE_ENTRY(CFGMR3GetRootU)
+VTABLE_ENTRY(CFGMR3GetParent)
+VTABLE_ENTRY(CFGMR3GetParentEx)
+VTABLE_ENTRY(CFGMR3GetChild)
+VTABLE_ENTRY(CFGMR3GetChildF)
+VTABLE_ENTRY(CFGMR3GetChildFV)
+VTABLE_ENTRY(CFGMR3GetFirstChild)
+VTABLE_ENTRY(CFGMR3GetNextChild)
+VTABLE_ENTRY(CFGMR3GetName)
+VTABLE_ENTRY(CFGMR3GetNameLen)
+VTABLE_ENTRY(CFGMR3AreChildrenValid)
+VTABLE_ENTRY(CFGMR3GetFirstValue)
+VTABLE_ENTRY(CFGMR3GetNextValue)
+VTABLE_ENTRY(CFGMR3GetValueName)
+VTABLE_ENTRY(CFGMR3GetValueNameLen)
+VTABLE_ENTRY(CFGMR3GetValueType)
+VTABLE_ENTRY(CFGMR3AreValuesValid)
+VTABLE_ENTRY(CFGMR3ValidateConfig)
+
+VTABLE_RESERVED(pfnCFMGR3Reserved1)
+VTABLE_RESERVED(pfnCFMGR3Reserved2)
+VTABLE_RESERVED(pfnCFMGR3Reserved3)
+VTABLE_RESERVED(pfnCFMGR3Reserved4)
+VTABLE_RESERVED(pfnCFMGR3Reserved5)
+/** @} */
+
+/** @name SSM
+ * @{ */
+VTABLE_ENTRY(SSMR3Term)
+VTABLE_ENTRY(SSMR3RegisterInternal)
+VTABLE_ENTRY(SSMR3RegisterExternal)
+VTABLE_ENTRY(SSMR3RegisterStub)
+VTABLE_ENTRY(SSMR3DeregisterInternal)
+VTABLE_ENTRY(SSMR3DeregisterExternal)
+VTABLE_ENTRY(SSMR3Save)
+VTABLE_ENTRY(SSMR3Load)
+VTABLE_ENTRY(SSMR3ValidateFile)
+VTABLE_ENTRY(SSMR3Open)
+VTABLE_ENTRY(SSMR3Close)
+VTABLE_ENTRY(SSMR3Seek)
+VTABLE_ENTRY(SSMR3HandleGetStatus)
+VTABLE_ENTRY(SSMR3HandleSetStatus)
+VTABLE_ENTRY(SSMR3HandleGetAfter)
+VTABLE_ENTRY(SSMR3HandleIsLiveSave)
+VTABLE_ENTRY(SSMR3HandleMaxDowntime)
+VTABLE_ENTRY(SSMR3HandleHostBits)
+VTABLE_ENTRY(SSMR3HandleRevision)
+VTABLE_ENTRY(SSMR3HandleVersion)
+VTABLE_ENTRY(SSMR3HandleHostOSAndArch)
+VTABLE_ENTRY(SSMR3HandleReportLivePercent)
+VTABLE_ENTRY(SSMR3Cancel)
+
+VTABLE_ENTRY(SSMR3PutStruct)
+VTABLE_ENTRY(SSMR3PutStructEx)
+VTABLE_ENTRY(SSMR3PutBool)
+VTABLE_ENTRY(SSMR3PutU8)
+VTABLE_ENTRY(SSMR3PutS8)
+VTABLE_ENTRY(SSMR3PutU16)
+VTABLE_ENTRY(SSMR3PutS16)
+VTABLE_ENTRY(SSMR3PutU32)
+VTABLE_ENTRY(SSMR3PutS32)
+VTABLE_ENTRY(SSMR3PutU64)
+VTABLE_ENTRY(SSMR3PutS64)
+VTABLE_ENTRY(SSMR3PutU128)
+VTABLE_ENTRY(SSMR3PutS128)
+VTABLE_ENTRY(SSMR3PutUInt)
+VTABLE_ENTRY(SSMR3PutSInt)
+VTABLE_ENTRY(SSMR3PutGCUInt)
+VTABLE_ENTRY(SSMR3PutGCUIntReg)
+VTABLE_ENTRY(SSMR3PutGCPhys32)
+VTABLE_ENTRY(SSMR3PutGCPhys64)
+VTABLE_ENTRY(SSMR3PutGCPhys)
+VTABLE_ENTRY(SSMR3PutGCPtr)
+VTABLE_ENTRY(SSMR3PutGCUIntPtr)
+VTABLE_ENTRY(SSMR3PutRCPtr)
+VTABLE_ENTRY(SSMR3PutIOPort)
+VTABLE_ENTRY(SSMR3PutSel)
+VTABLE_ENTRY(SSMR3PutMem)
+VTABLE_ENTRY(SSMR3PutStrZ)
+
+VTABLE_ENTRY(SSMR3GetStruct)
+VTABLE_ENTRY(SSMR3GetStructEx)
+VTABLE_ENTRY(SSMR3GetBool)
+VTABLE_ENTRY(SSMR3GetBoolV)
+VTABLE_ENTRY(SSMR3GetU8)
+VTABLE_ENTRY(SSMR3GetU8V)
+VTABLE_ENTRY(SSMR3GetS8)
+VTABLE_ENTRY(SSMR3GetS8V)
+VTABLE_ENTRY(SSMR3GetU16)
+VTABLE_ENTRY(SSMR3GetU16V)
+VTABLE_ENTRY(SSMR3GetS16)
+VTABLE_ENTRY(SSMR3GetS16V)
+VTABLE_ENTRY(SSMR3GetU32)
+VTABLE_ENTRY(SSMR3GetU32V)
+VTABLE_ENTRY(SSMR3GetS32)
+VTABLE_ENTRY(SSMR3GetS32V)
+VTABLE_ENTRY(SSMR3GetU64)
+VTABLE_ENTRY(SSMR3GetU64V)
+VTABLE_ENTRY(SSMR3GetS64)
+VTABLE_ENTRY(SSMR3GetS64V)
+VTABLE_ENTRY(SSMR3GetU128)
+VTABLE_ENTRY(SSMR3GetU128V)
+VTABLE_ENTRY(SSMR3GetS128)
+VTABLE_ENTRY(SSMR3GetS128V)
+VTABLE_ENTRY(SSMR3GetGCPhys32)
+VTABLE_ENTRY(SSMR3GetGCPhys32V)
+VTABLE_ENTRY(SSMR3GetGCPhys64)
+VTABLE_ENTRY(SSMR3GetGCPhys64V)
+VTABLE_ENTRY(SSMR3GetGCPhys)
+VTABLE_ENTRY(SSMR3GetGCPhysV)
+VTABLE_ENTRY(SSMR3GetUInt)
+VTABLE_ENTRY(SSMR3GetSInt)
+VTABLE_ENTRY(SSMR3GetGCUInt)
+VTABLE_ENTRY(SSMR3GetGCUIntReg)
+VTABLE_ENTRY(SSMR3GetGCPtr)
+VTABLE_ENTRY(SSMR3GetGCUIntPtr)
+VTABLE_ENTRY(SSMR3GetRCPtr)
+VTABLE_ENTRY(SSMR3GetIOPort)
+VTABLE_ENTRY(SSMR3GetSel)
+VTABLE_ENTRY(SSMR3GetMem)
+VTABLE_ENTRY(SSMR3GetStrZ)
+VTABLE_ENTRY(SSMR3GetStrZEx)
+VTABLE_ENTRY(SSMR3Skip)
+VTABLE_ENTRY(SSMR3SkipToEndOfUnit)
+VTABLE_ENTRY(SSMR3SetLoadError)
+VTABLE_ENTRY(SSMR3SetLoadErrorV)
+VTABLE_ENTRY(SSMR3SetCfgError)
+VTABLE_ENTRY(SSMR3SetCfgErrorV)
+
+VTABLE_RESERVED(pfnSSMR3Reserved1)
+VTABLE_RESERVED(pfnSSMR3Reserved2)
+VTABLE_RESERVED(pfnSSMR3Reserved3)
+VTABLE_RESERVED(pfnSSMR3Reserved4)
+VTABLE_RESERVED(pfnSSMR3Reserved5)
+/** @} */
+
+/** @name STAM
+ * @{ */
+VTABLE_ENTRY(STAMR3InitUVM)
+VTABLE_ENTRY(STAMR3TermUVM)
+VTABLE_ENTRY(STAMR3RegisterU)
+VTABLE_ENTRY(STAMR3Register)
+VTABLE_ENTRY(STAMR3RegisterFU)
+VTABLE_ENTRY(STAMR3RegisterF)
+VTABLE_ENTRY(STAMR3RegisterVU)
+VTABLE_ENTRY(STAMR3RegisterV)
+VTABLE_ENTRY(STAMR3RegisterCallback)
+VTABLE_ENTRY(STAMR3RegisterCallbackV)
+VTABLE_ENTRY(STAMR3RegisterRefresh)
+VTABLE_ENTRY(STAMR3RegisterRefreshV)
+VTABLE_ENTRY(STAMR3Deregister)
+VTABLE_ENTRY(STAMR3DeregisterF)
+VTABLE_ENTRY(STAMR3DeregisterV)
+VTABLE_ENTRY(STAMR3DeregisterByPrefix)
+VTABLE_ENTRY(STAMR3DeregisterByAddr)
+VTABLE_ENTRY(STAMR3Reset)
+VTABLE_ENTRY(STAMR3Snapshot)
+VTABLE_ENTRY(STAMR3SnapshotFree)
+VTABLE_ENTRY(STAMR3Dump)
+VTABLE_ENTRY(STAMR3DumpToReleaseLog)
+VTABLE_ENTRY(STAMR3Print)
+VTABLE_ENTRY(STAMR3Enum)
+VTABLE_ENTRY(STAMR3GetUnit)
+VTABLE_ENTRY(STAMR3GetUnit1)
+VTABLE_ENTRY(STAMR3GetUnit2)
+
+VTABLE_RESERVED(pfnSTAMR3Reserved1)
+VTABLE_RESERVED(pfnSTAMR3Reserved2)
+VTABLE_RESERVED(pfnSTAMR3Reserved3)
+VTABLE_RESERVED(pfnSTAMR3Reserved4)
+VTABLE_RESERVED(pfnSTAMR3Reserved5)
+/** @} */
+
+/** @name CPUM
+ * @{ */
+VTABLE_ENTRY(CPUMGetHostCpuVendor)
+VTABLE_ENTRY(CPUMGetHostMicroarch)
+
+VTABLE_RESERVED(pfnCPUMR3Reserved1)
+VTABLE_RESERVED(pfnCPUMR3Reserved2)
+VTABLE_RESERVED(pfnCPUMR3Reserved3)
+VTABLE_RESERVED(pfnCPUMR3Reserved4)
+VTABLE_RESERVED(pfnCPUMR3Reserved5)
+/** @} */
+
+/** @name DBGC
+ * @{ */
+VTABLE_ENTRY(DBGCCreate)
+
+VTABLE_RESERVED(pfnDBGCR3Reserved1)
+VTABLE_RESERVED(pfnDBGCR3Reserved2)
+VTABLE_RESERVED(pfnDBGCR3Reserved3)
+VTABLE_RESERVED(pfnDBGCR3Reserved4)
+VTABLE_RESERVED(pfnDBGCR3Reserved5)
+/** @} */
+
+/** @name DBGF
+ * @{ */
+VTABLE_ENTRY(DBGFR3BpClear)
+VTABLE_ENTRY(DBGFR3BpDisable)
+VTABLE_ENTRY(DBGFR3BpEnable)
+VTABLE_ENTRY(DBGFR3BpOwnerCreate)
+VTABLE_ENTRY(DBGFR3BpOwnerDestroy)
+VTABLE_ENTRY(DBGFR3BpSetInt3)
+VTABLE_ENTRY(DBGFR3BpSetInt3Ex)
+VTABLE_ENTRY(DBGFR3BpSetMmio)
+VTABLE_ENTRY(DBGFR3BpSetMmioEx)
+VTABLE_ENTRY(DBGFR3BpSetPortIo)
+VTABLE_ENTRY(DBGFR3BpSetPortIoEx)
+VTABLE_ENTRY(DBGFR3BpSetReg)
+VTABLE_ENTRY(DBGFR3BpSetRegEx)
+VTABLE_ENTRY(DBGFR3BpSetREM)
+VTABLE_ENTRY(DBGFR3CoreWrite)
+VTABLE_ENTRY(DBGFR3Info)
+VTABLE_ENTRY(DBGFR3InfoRegisterExternal)
+VTABLE_ENTRY(DBGFR3InfoDeregisterExternal)
+VTABLE_ENTRY(DBGFR3InfoGenericGetOptError)
+VTABLE_ENTRY(DBGFR3InjectNMI)
+VTABLE_ENTRY(DBGFR3LogModifyDestinations)
+VTABLE_ENTRY(DBGFR3LogModifyFlags)
+VTABLE_ENTRY(DBGFR3LogModifyGroups)
+VTABLE_ENTRY(DBGFR3OSDetect)
+VTABLE_ENTRY(DBGFR3OSQueryNameAndVersion)
+VTABLE_ENTRY(DBGFR3RegCpuQueryU8)
+VTABLE_ENTRY(DBGFR3RegCpuQueryU16)
+VTABLE_ENTRY(DBGFR3RegCpuQueryU32)
+VTABLE_ENTRY(DBGFR3RegCpuQueryU64)
+VTABLE_ENTRY(DBGFR3RegCpuQueryXdtr)
+VTABLE_ENTRY(DBGFR3RegFormatValue)
+VTABLE_ENTRY(DBGFR3RegNmQuery)
+VTABLE_ENTRY(DBGFR3RegNmQueryAll)
+VTABLE_ENTRY(DBGFR3RegNmQueryAllCount)
+VTABLE_ENTRY(DBGFR3RegNmSetBatch)
+VTABLE_ENTRY(DBGFR3OSDeregister)
+VTABLE_ENTRY(DBGFR3OSRegister)
+VTABLE_ENTRY(DBGFR3OSQueryInterface)
+VTABLE_ENTRY(DBGFR3MemReadString)
+VTABLE_ENTRY(DBGFR3MemRead)
+VTABLE_ENTRY(DBGFR3MemScan)
+VTABLE_ENTRY(DBGFR3ModInMem)
+VTABLE_ENTRY(DBGFR3AddrFromFlat)
+VTABLE_ENTRY(DBGFR3AsSymbolByName)
+VTABLE_ENTRY(DBGFR3AsResolveAndRetain)
+VTABLE_ENTRY(DBGFR3AsSetAlias)
+VTABLE_ENTRY(DBGFR3AddrAdd)
+VTABLE_ENTRY(DBGFR3AddrSub)
+VTABLE_ENTRY(DBGFR3AsGetConfig)
+VTABLE_ENTRY(DBGFR3CpuGetCount)
+VTABLE_ENTRY(DBGFR3CpuGetMode)
+VTABLE_ENTRY(DBGFR3CpuGetState)
+VTABLE_ENTRY(DBGFR3AddrFromSelOff)
+VTABLE_ENTRY(DBGFR3FlowCreate)
+VTABLE_ENTRY(DBGFR3FlowRetain)
+VTABLE_ENTRY(DBGFR3FlowRelease)
+VTABLE_ENTRY(DBGFR3FlowQueryStartBb)
+VTABLE_ENTRY(DBGFR3FlowQueryBbByAddress)
+VTABLE_ENTRY(DBGFR3FlowQueryBranchTblByAddress)
+VTABLE_ENTRY(DBGFR3FlowGetBbCount)
+VTABLE_ENTRY(DBGFR3FlowGetBranchTblCount)
+VTABLE_ENTRY(DBGFR3FlowGetCallInsnCount)
+VTABLE_ENTRY(DBGFR3FlowBbRetain)
+VTABLE_ENTRY(DBGFR3FlowBbRelease)
+VTABLE_ENTRY(DBGFR3FlowBbGetStartAddress)
+VTABLE_ENTRY(DBGFR3FlowBbGetEndAddress)
+VTABLE_ENTRY(DBGFR3FlowBbGetBranchAddress)
+VTABLE_ENTRY(DBGFR3FlowBbGetFollowingAddress)
+VTABLE_ENTRY(DBGFR3FlowBbGetType)
+VTABLE_ENTRY(DBGFR3FlowBbGetInstrCount)
+VTABLE_ENTRY(DBGFR3FlowBbGetFlags)
+VTABLE_ENTRY(DBGFR3FlowBbQueryBranchTbl)
+VTABLE_ENTRY(DBGFR3FlowBbQueryError)
+VTABLE_ENTRY(DBGFR3FlowBbQueryInstr)
+VTABLE_ENTRY(DBGFR3FlowBbQuerySuccessors)
+VTABLE_ENTRY(DBGFR3FlowBbGetRefBbCount)
+VTABLE_ENTRY(DBGFR3FlowBbGetRefBb)
+VTABLE_ENTRY(DBGFR3FlowBranchTblRetain)
+VTABLE_ENTRY(DBGFR3FlowBranchTblRelease)
+VTABLE_ENTRY(DBGFR3FlowBranchTblGetSlots)
+VTABLE_ENTRY(DBGFR3FlowBranchTblGetStartAddress)
+VTABLE_ENTRY(DBGFR3FlowBranchTblGetAddrAtSlot)
+VTABLE_ENTRY(DBGFR3FlowBranchTblQueryAddresses)
+VTABLE_ENTRY(DBGFR3FlowItCreate)
+VTABLE_ENTRY(DBGFR3FlowItDestroy)
+VTABLE_ENTRY(DBGFR3FlowItNext)
+VTABLE_ENTRY(DBGFR3FlowItReset)
+VTABLE_ENTRY(DBGFR3FlowBranchTblItCreate)
+VTABLE_ENTRY(DBGFR3FlowBranchTblItDestroy)
+VTABLE_ENTRY(DBGFR3FlowBranchTblItNext)
+VTABLE_ENTRY(DBGFR3FlowBranchTblItReset)
+VTABLE_ENTRY(DBGFR3FlowTraceModCreate)
+VTABLE_ENTRY(DBGFR3FlowTraceModCreateFromFlowGraph)
+VTABLE_ENTRY(DBGFR3FlowTraceModRetain)
+VTABLE_ENTRY(DBGFR3FlowTraceModRelease)
+VTABLE_ENTRY(DBGFR3FlowTraceModEnable)
+VTABLE_ENTRY(DBGFR3FlowTraceModDisable)
+VTABLE_ENTRY(DBGFR3FlowTraceModQueryReport)
+VTABLE_ENTRY(DBGFR3FlowTraceModClear)
+VTABLE_ENTRY(DBGFR3FlowTraceModAddProbe)
+VTABLE_ENTRY(DBGFR3FlowTraceProbeCreate)
+VTABLE_ENTRY(DBGFR3FlowTraceProbeRetain)
+VTABLE_ENTRY(DBGFR3FlowTraceProbeRelease)
+VTABLE_ENTRY(DBGFR3FlowTraceProbeEntriesAdd)
+VTABLE_ENTRY(DBGFR3FlowTraceReportRetain)
+VTABLE_ENTRY(DBGFR3FlowTraceReportRelease)
+VTABLE_ENTRY(DBGFR3FlowTraceReportGetRecordCount)
+VTABLE_ENTRY(DBGFR3FlowTraceReportQueryRecord)
+VTABLE_ENTRY(DBGFR3FlowTraceReportQueryFiltered)
+VTABLE_ENTRY(DBGFR3FlowTraceReportEnumRecords)
+VTABLE_ENTRY(DBGFR3FlowTraceRecordRetain)
+VTABLE_ENTRY(DBGFR3FlowTraceRecordRelease)
+VTABLE_ENTRY(DBGFR3FlowTraceRecordGetSeqNo)
+VTABLE_ENTRY(DBGFR3FlowTraceRecordGetTimestamp)
+VTABLE_ENTRY(DBGFR3FlowTraceRecordGetAddr)
+VTABLE_ENTRY(DBGFR3FlowTraceRecordGetProbe)
+VTABLE_ENTRY(DBGFR3FlowTraceRecordGetValCount)
+VTABLE_ENTRY(DBGFR3FlowTraceRecordGetVals)
+VTABLE_ENTRY(DBGFR3FlowTraceRecordGetValsCommon)
+VTABLE_ENTRY(DBGFR3FlowTraceRecordGetCpuId)
+VTABLE_ENTRY(DBGFR3PlugInLoad)
+VTABLE_ENTRY(DBGFR3PlugInUnload)
+VTABLE_ENTRY(DBGFR3PlugInLoadAll)
+VTABLE_ENTRY(DBGFR3PlugInUnloadAll)
+VTABLE_ENTRY(DBGFR3SampleReportCreate)
+VTABLE_ENTRY(DBGFR3SampleReportRetain)
+VTABLE_ENTRY(DBGFR3SampleReportRelease)
+VTABLE_ENTRY(DBGFR3SampleReportStart)
+VTABLE_ENTRY(DBGFR3SampleReportStop)
+VTABLE_ENTRY(DBGFR3SampleReportDumpToFile)
+VTABLE_ENTRY(DBGFR3SelQueryInfo)
+VTABLE_ENTRY(DBGFR3StackWalkBegin)
+VTABLE_ENTRY(DBGFR3StackWalkNext)
+VTABLE_ENTRY(DBGFR3StackWalkEnd)
+VTABLE_ENTRY(DBGFR3TypeDeregister)
+VTABLE_ENTRY(DBGFR3TypeDumpEx)
+VTABLE_ENTRY(DBGFR3TypeQueryReg)
+VTABLE_ENTRY(DBGFR3TypeQuerySize)
+VTABLE_ENTRY(DBGFR3TypeQueryValByType)
+VTABLE_ENTRY(DBGFR3TypeRegister)
+VTABLE_ENTRY(DBGFR3TypeSetSize)
+VTABLE_ENTRY(DBGFR3TypeValFree)
+VTABLE_ENTRY(DBGFR3TypeValDumpEx)
+
+VTABLE_RESERVED(pfnDBGFR3Reserved1)
+VTABLE_RESERVED(pfnDBGFR3Reserved2)
+VTABLE_RESERVED(pfnDBGFR3Reserved3)
+VTABLE_RESERVED(pfnDBGFR3Reserved4)
+VTABLE_RESERVED(pfnDBGFR3Reserved5)
+/** @} */
+
+/** @name EM
+ * @{ */
+VTABLE_ENTRY(EMR3QueryExecutionPolicy)
+VTABLE_ENTRY(EMR3QueryMainExecutionEngine)
+VTABLE_ENTRY(EMR3SetExecutionPolicy)
+
+VTABLE_RESERVED(pfnEMR3Reserved1)
+VTABLE_RESERVED(pfnEMR3Reserved2)
+VTABLE_RESERVED(pfnEMR3Reserved3)
+VTABLE_RESERVED(pfnEMR3Reserved4)
+VTABLE_RESERVED(pfnEMR3Reserved5)
+/** @} */
+
+/** @name HM
+ * @{ */
+VTABLE_ENTRY(HMR3IsEnabled)
+VTABLE_ENTRY(HMR3IsNestedPagingActive)
+VTABLE_ENTRY(HMR3IsUXActive)
+VTABLE_ENTRY(HMR3IsVpidActive)
+
+VTABLE_RESERVED(pfnHMR3Reserved1)
+VTABLE_RESERVED(pfnHMR3Reserved2)
+VTABLE_RESERVED(pfnHMR3Reserved3)
+VTABLE_RESERVED(pfnHMR3Reserved4)
+VTABLE_RESERVED(pfnHMR3Reserved5)
+/** @} */
+
+/** @name MM
+ * @{ */
+VTABLE_ENTRY(MMR3HeapAllocU)
+VTABLE_ENTRY(MMR3HeapAllocExU)
+VTABLE_ENTRY(MMR3HeapAllocZU)
+VTABLE_ENTRY(MMR3HeapAllocZExU)
+VTABLE_ENTRY(MMR3HeapRealloc)
+VTABLE_ENTRY(MMR3HeapStrDupU)
+VTABLE_ENTRY(MMR3HeapAPrintfU)
+VTABLE_ENTRY(MMR3HeapAPrintfVU)
+VTABLE_ENTRY(MMR3HeapFree)
+
+VTABLE_RESERVED(pfnMMR3Reserved1)
+VTABLE_RESERVED(pfnMMR3Reserved2)
+VTABLE_RESERVED(pfnMMR3Reserved3)
+VTABLE_RESERVED(pfnMMR3Reserved4)
+VTABLE_RESERVED(pfnMMR3Reserved5)
+/** @} */
+
+/** @name PDM
+ * @{ */
+VTABLE_ENTRY(PDMR3AsyncCompletionBwMgrSetMaxForFile)
+VTABLE_ENTRY(PDMR3DeviceAttach)
+VTABLE_ENTRY(PDMR3DeviceDetach)
+VTABLE_ENTRY(PDMR3DriverAttach)
+VTABLE_ENTRY(PDMR3DriverDetach)
+VTABLE_ENTRY(PDMR3NsBwGroupSetLimit)
+VTABLE_ENTRY(PDMR3QueryDeviceLun)
+VTABLE_ENTRY(PDMR3QueryDriverOnLun)
+VTABLE_ENTRY(PDMR3QueryLun)
+
+VTABLE_ENTRY(PDMCritSectEnter)
+VTABLE_ENTRY(PDMCritSectEnterDebug)
+VTABLE_ENTRY(PDMCritSectTryEnter)
+VTABLE_ENTRY(PDMCritSectTryEnterDebug)
+VTABLE_ENTRY(PDMR3CritSectEnterEx)
+VTABLE_ENTRY(PDMCritSectLeave)
+VTABLE_ENTRY(PDMCritSectIsOwner)
+VTABLE_ENTRY(PDMCritSectIsOwnerEx)
+VTABLE_ENTRY(PDMCritSectIsInitialized)
+VTABLE_ENTRY(PDMCritSectHasWaiters)
+VTABLE_ENTRY(PDMCritSectGetRecursion)
+VTABLE_ENTRY(PDMR3CritSectYield)
+VTABLE_ENTRY(PDMR3CritSectName)
+VTABLE_ENTRY(PDMR3CritSectDelete)
+
+VTABLE_ENTRY(PDMQueueAlloc)
+VTABLE_ENTRY(PDMQueueInsert)
+VTABLE_RESERVED(pfnPDMR3Reserved11)
+
+VTABLE_ENTRY(PDMR3ThreadDestroy)
+VTABLE_ENTRY(PDMR3ThreadIAmRunning)
+VTABLE_ENTRY(PDMR3ThreadIAmSuspending)
+VTABLE_ENTRY(PDMR3ThreadResume)
+VTABLE_ENTRY(PDMR3ThreadSleep)
+VTABLE_ENTRY(PDMR3ThreadSuspend)
+
+VTABLE_ENTRY(PDMR3UsbCreateEmulatedDevice)
+VTABLE_ENTRY(PDMR3UsbCreateProxyDevice)
+VTABLE_ENTRY(PDMR3UsbDetachDevice)
+VTABLE_ENTRY(PDMR3UsbHasHub)
+VTABLE_ENTRY(PDMR3UsbDriverAttach)
+VTABLE_ENTRY(PDMR3UsbDriverDetach)
+VTABLE_ENTRY(PDMR3UsbQueryLun)
+VTABLE_ENTRY(PDMR3UsbQueryDriverOnLun)
+
+VTABLE_RESERVED(pfnPDMR3Reserved1)
+VTABLE_RESERVED(pfnPDMR3Reserved2)
+VTABLE_RESERVED(pfnPDMR3Reserved3)
+VTABLE_RESERVED(pfnPDMR3Reserved4)
+VTABLE_RESERVED(pfnPDMR3Reserved5)
+VTABLE_RESERVED(pfnPDMR3Reserved6)
+VTABLE_RESERVED(pfnPDMR3Reserved7)
+VTABLE_RESERVED(pfnPDMR3Reserved8)
+VTABLE_RESERVED(pfnPDMR3Reserved9)
+VTABLE_RESERVED(pfnPDMR3Reserved10)
+/** @} */
+
+/** @name PGM
+ * @{ */
+VTABLE_ENTRY(PGMHandlerPhysicalPageTempOff)
+VTABLE_ENTRY(PGMPhysReadGCPtr)
+VTABLE_ENTRY(PGMPhysSimpleDirtyWriteGCPtr)
+VTABLE_ENTRY(PGMPhysSimpleReadGCPtr)
+VTABLE_ENTRY(PGMPhysSimpleWriteGCPhys)
+VTABLE_ENTRY(PGMPhysSimpleWriteGCPtr)
+VTABLE_ENTRY(PGMPhysWriteGCPtr)
+VTABLE_ENTRY(PGMShwMakePageWritable)
+VTABLE_ENTRY(PGMR3QueryGlobalMemoryStats)
+VTABLE_ENTRY(PGMR3QueryMemoryStats)
+
+VTABLE_RESERVED(pfnPGMR3Reserved1)
+VTABLE_RESERVED(pfnPGMR3Reserved2)
+VTABLE_RESERVED(pfnPGMR3Reserved3)
+VTABLE_RESERVED(pfnPGMR3Reserved4)
+VTABLE_RESERVED(pfnPGMR3Reserved5)
+/** @} */
+
+/** @name TM
+ * @{ */
+VTABLE_ENTRY(TMR3GetCpuLoadPercents)
+VTABLE_ENTRY(TMR3TimerSetCritSect)
+VTABLE_ENTRY(TMR3TimerLoad)
+VTABLE_ENTRY(TMR3TimerSave)
+VTABLE_ENTRY(TMR3TimerSkip)
+VTABLE_ENTRY(TMR3TimerDestroy)
+VTABLE_ENTRY(TMTimerFromMicro)
+VTABLE_ENTRY(TMTimerFromMilli)
+VTABLE_ENTRY(TMTimerFromNano)
+VTABLE_ENTRY(TMTimerGet)
+VTABLE_ENTRY(TMTimerGetFreq)
+VTABLE_ENTRY(TMTimerGetMicro)
+VTABLE_ENTRY(TMTimerGetMilli)
+VTABLE_ENTRY(TMTimerGetNano)
+VTABLE_ENTRY(TMTimerIsActive)
+VTABLE_ENTRY(TMTimerIsLockOwner)
+VTABLE_ENTRY(TMTimerLock)
+VTABLE_ENTRY(TMTimerSet)
+VTABLE_ENTRY(TMTimerSetFrequencyHint)
+VTABLE_ENTRY(TMTimerSetMicro)
+VTABLE_ENTRY(TMTimerSetMillies)
+VTABLE_ENTRY(TMTimerSetNano)
+VTABLE_ENTRY(TMTimerSetRelative)
+VTABLE_ENTRY(TMTimerStop)
+VTABLE_ENTRY(TMTimerToMicro)
+VTABLE_ENTRY(TMTimerToMilli)
+VTABLE_ENTRY(TMTimerToNano)
+VTABLE_ENTRY(TMTimerUnlock)
+VTABLE_ENTRY(TMR3GetWarpDrive)
+VTABLE_ENTRY(TMR3SetWarpDrive)
+VTABLE_ENTRY(TMR3TimeVirtGet)
+VTABLE_ENTRY(TMR3TimeVirtGetMicro)
+VTABLE_ENTRY(TMR3TimeVirtGetMilli)
+VTABLE_ENTRY(TMR3TimeVirtGetNano)
+
+VTABLE_RESERVED(pfnTMR3Reserved1)
+VTABLE_RESERVED(pfnTMR3Reserved2)
+VTABLE_RESERVED(pfnTMR3Reserved3)
+VTABLE_RESERVED(pfnTMR3Reserved4)
+VTABLE_RESERVED(pfnTMR3Reserved5)
+/** @} */
diff --git a/include/VBox/vmm/vmmr3vtable.h b/include/VBox/vmm/vmmr3vtable.h
new file mode 100644
index 00000000..96d88636
--- /dev/null
+++ b/include/VBox/vmm/vmmr3vtable.h
@@ -0,0 +1,140 @@
+/** @file
+ * VM - The Virtual Machine Monitor, VTable ring-3 API.
+ */
+
+/*
+ * Copyright (C) 2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vmm_vmmr3vtable_h
+#define VBOX_INCLUDED_vmm_vmmr3vtable_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/types.h>
+#include <VBox/vmm/cfgm.h>
+#include <VBox/vmm/cpum.h>
+#include <VBox/vmm/dbgf.h>
+#include <VBox/vmm/dbgfflowtrace.h>
+#include <VBox/vmm/em.h>
+#include <VBox/vmm/hm.h>
+#include <VBox/vmm/pdmapi.h>
+#include <VBox/vmm/pdmasynccompletion.h>
+#include <VBox/vmm/pdmcritsect.h>
+#include <VBox/vmm/pdmnetshaper.h>
+#include <VBox/vmm/pdmqueue.h>
+#include <VBox/vmm/pdmusb.h>
+#include <VBox/vmm/pdmthread.h>
+#include <VBox/vmm/pgm.h>
+#include <VBox/vmm/ssm.h>
+#include <VBox/vmm/stam.h>
+#include <VBox/vmm/tm.h>
+#include <VBox/vmm/vmm.h>
+#include <VBox/dbg.h>
+
+#include <iprt/stdarg.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_vmm_vtable VMM Function Table
+ * @ingroup grp_vmm
+ * @{ */
+
+
+/** Magic and version for the VMM vtable. (Magic: Emmet Cohen) */
+#define VMMR3VTABLE_MAGIC_VERSION RT_MAKE_U64(0x19900525, 0x00030000)
+/** Compatibility mask: These bits must match - magic and major version. */
+#define VMMR3VTABLE_MAGIC_VERSION_MASK RT_MAKE_U64(0xffffffff, 0xffff0000)
+
+/** Checks if @a a_uTableMagicVersion can be used by code compiled
+ * against @a a_CompiledMagicVersion */
+#define VMMR3VTABLE_IS_COMPATIBLE_EX(a_uTableMagicVersion, a_CompiledMagicVersion) \
+ ( (a_uTableMagicVersion) >= (a_CompiledMagicVersion) /* table must be same or later version */ \
+ && ((a_uTableMagicVersion) & VMMR3VTABLE_MAGIC_VERSION_MASK) == ((a_CompiledMagicVersion) & VMMR3VTABLE_MAGIC_VERSION_MASK) )
+
+/** Checks if @a a_uTableMagicVersion can be used by this us. */
+#define VMMR3VTABLE_IS_COMPATIBLE(a_uTableMagicVersion) \
+ VMMR3VTABLE_IS_COMPATIBLE_EX(a_uTableMagicVersion, VMMR3VTABLE_MAGIC_VERSION)
+
+
+/**
+ * Function for getting the vtable of a VMM DLL/SO/DyLib.
+ *
+ * @returns the pointer to the vtable.
+ */
+typedef DECLCALLBACKTYPE(PCVMMR3VTABLE, FNVMMGETVTABLE,(void));
+/** Pointer to VMM vtable getter. */
+typedef FNVMMGETVTABLE *PFNVMMGETVTABLE;
+/** The name of the FNVMMGETVTABLE function. */
+#define VMMR3VTABLE_GETTER_NAME "VMMR3GetVTable"
+
+
+/**
+ * VTable for the ring-3 VMM API.
+ */
+typedef struct VMMR3VTABLE
+{
+ /** VMMR3VTABLE_MAGIC_VERSION. */
+ uint64_t uMagicVersion;
+ /** Flags (TBD). */
+ uint64_t fFlags;
+ /** The description of this VMM. */
+ const char *pszDescription;
+
+/** @def VTABLE_ENTRY
+ * Define a VTable entry for the given function. */
+#if defined(DOXYGEN_RUNNING) \
+ || (defined(__cplusplus) && (defined(__clang_major__) || RT_GNUC_PREREQ_EX(4, 8, /*non-gcc: */1) /* For 4.8+ we enable c++11 */))
+# define VTABLE_ENTRY(a_Api) /** @copydoc a_Api */ decltype(a_Api) *pfn ## a_Api;
+#elif defined(__GNUC__)
+# define VTABLE_ENTRY(a_Api) /** @copydoc a_Api */ typeof(a_Api) *pfn ## a_Api;
+#else
+# error "Unsupported compiler"
+#endif
+/** @def VTABLE_RESERVED
+ * Define a reserved VTable entry with the given name. */
+#define VTABLE_RESERVED(a_Name) DECLCALLBACKMEMBER(int, a_Name,(void));
+
+#include "vmmr3vtable-def.h"
+
+#undef VTABLE_ENTRY
+#undef VTABLE_RESERVED
+
+ /** VMMR3VTABLE_MAGIC_VERSION. */
+ uint64_t uMagicVersionEnd;
+} VMMR3VTABLE;
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !VBOX_INCLUDED_vmm_vmmr3vtable_h */
+
diff --git a/include/VBox/vrdpusb.h b/include/VBox/vrdpusb.h
new file mode 100644
index 00000000..54da45a6
--- /dev/null
+++ b/include/VBox/vrdpusb.h
@@ -0,0 +1,135 @@
+/** @file
+ * VBox Remote Desktop Protocol - Remote USB backend interface. (VRDP)
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vrdpusb_h
+#define VBOX_INCLUDED_vrdpusb_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/cdefs.h>
+#include <VBox/types.h>
+
+#ifdef IN_RING0
+# error "There are no VRDP APIs available in Ring-0 Host Context!"
+#endif
+#ifdef IN_RC
+# error "There are no VRDP APIs available Guest Context!"
+#endif
+
+
+/** @defgroup grp_vrdpusb Remote USB over VURP
+ * @ingroup grp_vusb
+ * @{
+ */
+
+#define REMOTE_USB_BACKEND_PREFIX_S "REMOTEUSB"
+#define REMOTE_USB_BACKEND_PREFIX_LEN 9
+
+/* Forward declaration. */
+struct _REMOTEUSBDEVICE;
+typedef struct _REMOTEUSBDEVICE *PREMOTEUSBDEVICE;
+
+/* Forward declaration. */
+struct _REMOTEUSBQURB;
+typedef struct _REMOTEUSBQURB *PREMOTEUSBQURB;
+
+/* Forward declaration. Actually a class. */
+struct _REMOTEUSBBACKEND;
+typedef struct _REMOTEUSBBACKEND *PREMOTEUSBBACKEND;
+
+/**
+ * Pointer to this structure is queried from USBREMOTEIF::pfnQueryRemoteUsbBackend.
+ */
+typedef struct REMOTEUSBCALLBACK
+{
+ PREMOTEUSBBACKEND pInstance;
+
+ DECLCALLBACKMEMBER(int, pfnOpen,(PREMOTEUSBBACKEND pInstance, const char *pszAddress, size_t cbAddress, PREMOTEUSBDEVICE *ppDevice));
+ DECLCALLBACKMEMBER(void, pfnClose,(PREMOTEUSBDEVICE pDevice));
+ DECLCALLBACKMEMBER(int, pfnReset,(PREMOTEUSBDEVICE pDevice));
+ DECLCALLBACKMEMBER(int, pfnSetConfig,(PREMOTEUSBDEVICE pDevice, uint8_t u8Cfg));
+ DECLCALLBACKMEMBER(int, pfnClaimInterface,(PREMOTEUSBDEVICE pDevice, uint8_t u8Ifnum));
+ DECLCALLBACKMEMBER(int, pfnReleaseInterface,(PREMOTEUSBDEVICE pDevice, uint8_t u8Ifnum));
+ DECLCALLBACKMEMBER(int, pfnInterfaceSetting,(PREMOTEUSBDEVICE pDevice, uint8_t u8Ifnum, uint8_t u8Setting));
+ DECLCALLBACKMEMBER(int, pfnQueueURB,(PREMOTEUSBDEVICE pDevice, uint8_t u8Type, uint8_t u8Ep, uint8_t u8Direction, uint32_t u32Len, void *pvData, void *pvURB, PREMOTEUSBQURB *ppRemoteURB));
+ DECLCALLBACKMEMBER(int, pfnReapURB,(PREMOTEUSBDEVICE pDevice, uint32_t u32Millies, void **ppvURB, uint32_t *pu32Len, uint32_t *pu32Err));
+ DECLCALLBACKMEMBER(int, pfnClearHaltedEP,(PREMOTEUSBDEVICE pDevice, uint8_t u8Ep));
+ DECLCALLBACKMEMBER(void, pfnCancelURB,(PREMOTEUSBDEVICE pDevice, PREMOTEUSBQURB pRemoteURB));
+ DECLCALLBACKMEMBER(int, pfnWakeup,(PREMOTEUSBDEVICE pDevice));
+} REMOTEUSBCALLBACK;
+/** Pointer to a remote USB callback table. */
+typedef REMOTEUSBCALLBACK *PREMOTEUSBCALLBACK;
+
+/**
+ * Remote USB interface for querying the remote USB callback table for particular client.
+ * Returned from the *QueryGenericUserObject when passing REMOTEUSBIF_OID as the identifier.
+ */
+typedef struct REMOTEUSBIF
+{
+ /** Opaque user data to pass as the first parameter to the callbacks. */
+ void *pvUser;
+
+ /**
+ * Queries the remote USB interface callback table for a given UUID/client ID pair.
+ *
+ * @returns Pointer to the remote USB callback table or NULL if the client ID and or UUID is invalid.
+ * @param pvUser Opaque user data from this interface.
+ * @param pUuid The device UUID to query the interface for.
+ * @param idClient The client ID to query the interface for.
+ */
+ DECLCALLBACKMEMBER(PREMOTEUSBCALLBACK, pfnQueryRemoteUsbBackend, (void *pvUser, PCRTUUID pUuid, uint32_t idClient));
+} REMOTEUSBIF;
+/** Pointer to a remote USB interface. */
+typedef REMOTEUSBIF *PREMOTEUSBIF;
+
+/** The UUID to identify the remote USB interface. */
+#define REMOTEUSBIF_OID "87012f58-2ad6-4f89-b7b1-92f72c7ea8cc"
+
+
+typedef struct EMULATEDUSBIF
+{
+ /** Opaque user data to pass as the first parameter to the callbacks. */
+ void *pvUser;
+
+ DECLCALLBACKMEMBER(int, pfnQueryEmulatedUsbDataById, (void *pvUser, const char *pszId, void **ppvEmUsbCb, void **ppvEmUsbCbData, void **ppvObject));
+} EMULATEDUSBIF;
+typedef EMULATEDUSBIF *PEMULATEDUSBIF;
+
+#define EMULATEDUSBIF_OID "b7b4e194-ada0-4722-8e4e-1700ed9064f3"
+
+/** @} */
+
+#endif /* !VBOX_INCLUDED_vrdpusb_h */
diff --git a/include/VBox/vscsi.h b/include/VBox/vscsi.h
new file mode 100644
index 00000000..dea697e2
--- /dev/null
+++ b/include/VBox/vscsi.h
@@ -0,0 +1,488 @@
+/* $Id: vscsi.h $ */
+/** @file
+ * VBox storage drivers - Virtual SCSI driver
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vscsi_h
+#define VBOX_INCLUDED_vscsi_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/cdefs.h>
+#include <VBox/types.h>
+#include <VBox/vdmedia.h>
+#include <iprt/sg.h>
+
+RT_C_DECLS_BEGIN
+
+#ifdef IN_RING0
+# error "There are no VBox VSCSI APIs available in Ring-0 Host Context!"
+#endif
+
+/** @defgroup grp_drv_vscsi Virtual VSCSI Driver
+ * @ingroup grp_devdrv
+ * @{
+ */
+/** @todo figure better grouping. */
+
+/** A virtual SCSI device handle */
+typedef struct VSCSIDEVICEINT *VSCSIDEVICE;
+/** A pointer to a virtual SCSI device handle. */
+typedef VSCSIDEVICE *PVSCSIDEVICE;
+/** A virtual SCSI LUN handle. */
+typedef struct VSCSILUNINT *VSCSILUN;
+/** A pointer to a virtual SCSI LUN handle. */
+typedef VSCSILUN *PVSCSILUN;
+/** A virtual SCSI request handle. */
+typedef struct VSCSIREQINT *VSCSIREQ;
+/** A pointer to a virtual SCSI request handle. */
+typedef VSCSIREQ *PVSCSIREQ;
+/** A SCSI I/O request handle. */
+typedef struct VSCSIIOREQINT *VSCSIIOREQ;
+/** A pointer to a SCSI I/O request handle. */
+typedef VSCSIIOREQ *PVSCSIIOREQ;
+
+/**
+ * Virtual SCSI I/O request transfer direction.
+ */
+typedef enum VSCSIIOREQTXDIR
+{
+ /** Invalid direction */
+ VSCSIIOREQTXDIR_INVALID = 0,
+ /** Read */
+ VSCSIIOREQTXDIR_READ,
+ /** Write */
+ VSCSIIOREQTXDIR_WRITE,
+ /** Flush */
+ VSCSIIOREQTXDIR_FLUSH,
+ /** Unmap */
+ VSCSIIOREQTXDIR_UNMAP,
+ /** 32bit hack */
+ VSCSIIOREQTXDIR_32BIT_HACK = 0x7fffffff
+} VSCSIIOREQTXDIR;
+/** Pointer to a SCSI LUN type */
+typedef VSCSIIOREQTXDIR *PVSCSIIOREQTXDIR;
+
+/**
+ * Virtual SCSI transfer direction as seen from the initiator.
+ */
+typedef enum VSCSIXFERDIR
+{
+ /** Invalid data direction. */
+ PVSCSIXFERDIR_INVALID = 0,
+ /** Direction is unknown. */
+ VSCSIXFERDIR_UNKNOWN,
+ /** Direction is from target to initiator (aka a read). */
+ VSCSIXFERDIR_T2I,
+ /** Direction is from initiator to device (aka a write). */
+ VSCSIXFERDIR_I2T,
+ /** No data transfer associated with this request. */
+ VSCSIXFERDIR_NONE,
+ /** 32bit hack. */
+ VSCSIXFERDIR_32BIT_HACK = 0x7fffffff
+} VSCSIXFERDIR;
+
+/**
+ * LUN types we support
+ */
+typedef enum VSCSILUNTYPE
+{
+ /** Invalid type */
+ VSCSILUNTYPE_INVALID = 0,
+ /** Hard disk (SBC) */
+ VSCSILUNTYPE_SBC,
+ /** CD/DVD drive (MMC) */
+ VSCSILUNTYPE_MMC,
+ /** Tape drive (SSC) */
+ VSCSILUNTYPE_SSC,
+ /** Last value to indicate an invalid device */
+ VSCSILUNTYPE_LAST,
+ /** 32bit hack */
+ VSCSILUNTYPE_32BIT_HACK = 0x7fffffff
+} VSCSILUNTYPE;
+/** Pointer to a SCSI LUN type */
+typedef VSCSILUNTYPE *PVSCSILUNTYPE;
+
+/** The LUN can handle the UNMAP command. */
+#define VSCSI_LUN_FEATURE_UNMAP RT_BIT(0)
+/** The LUN has a non rotational medium. */
+#define VSCSI_LUN_FEATURE_NON_ROTATIONAL RT_BIT(1)
+/** The medium of the LUN is readonly. */
+#define VSCSI_LUN_FEATURE_READONLY RT_BIT(2)
+
+/**
+ * Virtual SCSI LUN I/O Callback table.
+ */
+typedef struct VSCSILUNIOCALLBACKS
+{
+ /**
+ * Sets the size of the allocator specific memory for a I/O request.
+ *
+ * @returns VBox status code.
+ * @param hVScsiLun Virtual SCSI LUN handle.
+ * @param pvScsiLunUser Opaque user data which may be used to identify the
+ * medium.
+ * @param cbVScsiIoReqAlloc The size of the allocator specific memory in bytes.
+ * @thread EMT.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnVScsiLunReqAllocSizeSet, (VSCSILUN hVScsiLun, void *pvScsiLunUser,
+ size_t cbVScsiIoReqAlloc));
+
+ /**
+ * Allocates a new I/O request.
+ *
+ * @returns VBox status code.
+ * @param hVScsiLun Virtual SCSI LUN handle.
+ * @param pvScsiLunUser Opaque user data which may be used to identify the
+ * medium.
+ * @param u64Tag A tag to assign to the request handle for identification later on.
+ * @param phVScsiIoReq Where to store the handle to the allocated I/O request on success.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnVScsiLunReqAlloc, (VSCSILUN hVScsiLun, void *pvScsiLunUser,
+ uint64_t u64Tag, PVSCSIIOREQ phVScsiIoReq));
+
+ /**
+ * Frees a given I/O request.
+ *
+ * @returns VBox status code.
+ * @param hVScsiLun Virtual SCSI LUN handle.
+ * @param pvScsiLunUser Opaque user data which may be used to identify the
+ * medium.
+ * @param hVScsiIoReq The VSCSI I/O request to free.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnVScsiLunReqFree, (VSCSILUN hVScsiLun, void *pvScsiLunUser, VSCSIIOREQ hVScsiIoReq));
+
+ /**
+ * Returns the number of regions for the medium.
+ *
+ * @returns Number of regions.
+ * @param hVScsiLun Virtual SCSI LUN handle.
+ * @param pvScsiLunUser Opaque user data which may be used to identify the
+ * medium.
+ */
+ DECLR3CALLBACKMEMBER(uint32_t, pfnVScsiLunMediumGetRegionCount,(VSCSILUN hVScsiLun, void *pvScsiLunUser));
+
+ /**
+ * Queries the properties for the given region.
+ *
+ * @returns VBox status code.
+ * @retval VERR_NOT_FOUND if the region index is not known.
+ * @param hVScsiLun Virtual SCSI LUN handle.
+ * @param pvScsiLunUser Opaque user data which may be used to identify the
+ * medium.
+ * @param uRegion The region index to query the properties of.
+ * @param pu64LbaStart Where to store the starting LBA for the region on success.
+ * @param pcBlocks Where to store the number of blocks for the region on success.
+ * @param pcbBlock Where to store the size of one block in bytes on success.
+ * @param penmDataForm WHere to store the data form for the region on success.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnVScsiLunMediumQueryRegionProperties,(VSCSILUN hVScsiLun, void *pvScsiLunUser,
+ uint32_t uRegion, uint64_t *pu64LbaStart,
+ uint64_t *pcBlocks, uint64_t *pcbBlock,
+ PVDREGIONDATAFORM penmDataForm));
+
+ /**
+ * Queries the properties for the region covering the given LBA.
+ *
+ * @returns VBox status code.
+ * @retval VERR_NOT_FOUND if the region index is not known.
+ * @param hVScsiLun Virtual SCSI LUN handle.
+ * @param pvScsiLunUser Opaque user data which may be used to identify the
+ * medium.
+ * @param u64LbaStart Where to store the starting LBA for the region on success.
+ * @param puRegion Where to store the region number on success.
+ * @param pcBlocks Where to store the number of blocks left in this region starting from the given LBA.
+ * @param pcbBlock Where to store the size of one block in bytes on success.
+ * @param penmDataForm WHere to store the data form for the region on success.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnVScsiLunMediumQueryRegionPropertiesForLba,(VSCSILUN hVScsiLun, void *pvScsiLunUser,
+ uint64_t u64LbaStart, uint32_t *puRegion,
+ uint64_t *pcBlocks, uint64_t *pcbBlock,
+ PVDREGIONDATAFORM penmDataForm));
+
+ /**
+ * Set the lock state of the underlying medium.
+ *
+ * @returns VBox status status code.
+ * @param hVScsiLun Virtual SCSI LUN handle.
+ * @param pvScsiLunUser Opaque user data which may be used to identify the
+ * medium.
+ * @param fLocked New lock state (locked/unlocked).
+ */
+ DECLR3CALLBACKMEMBER(int, pfnVScsiLunMediumSetLock,(VSCSILUN hVScsiLun, void *pvScsiLunUser, bool fLocked));
+
+ /**
+ * Eject the attached medium.
+ *
+ * @returns VBox status code.
+ * @param hVScsiLun Virtual SCSI LUN handle.
+ * @param pvScsiLunUser Opaque user data which may be used to identify the
+ * medium.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnVScsiLunMediumEject, (VSCSILUN hVScsiLun, void *pvScsiLunUser));
+
+ /**
+ * Enqueue a read or write request from the medium.
+ *
+ * @returns VBox status status code.
+ * @param hVScsiLun Virtual SCSI LUN handle.
+ * @param pvScsiLunUser Opaque user data which may be used to identify the
+ * medium.
+ * @param hVScsiIoReq Virtual SCSI I/O request handle.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnVScsiLunReqTransferEnqueue,(VSCSILUN hVScsiLun, void *pvScsiLunUser, VSCSIIOREQ hVScsiIoReq));
+
+ /**
+ * Returns flags of supported features.
+ *
+ * @returns VBox status status code.
+ * @param hVScsiLun Virtual SCSI LUN handle.
+ * @param pvScsiLunUser Opaque user data which may be used to identify the
+ * medium.
+ * @param pfFeatures Where to return the queried features.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnVScsiLunGetFeatureFlags,(VSCSILUN hVScsiLun, void *pvScsiLunUser, uint64_t *pfFeatures));
+
+ /**
+ * Queries the vendor and product ID and revision to report for INQUIRY commands of the given LUN.
+ *
+ * @returns VBox status status code.
+ * @retval VERR_NOT_FOUND if the data is not available and some defaults should be sued instead.
+ * @param hVScsiLun Virtual SCSI LUN handle.
+ * @param pvScsiLunUser Opaque user data which may be used to identify the
+ * medium.
+ * @param ppszVendorId Where to store the pointer to the vendor ID string to report.
+ * @param ppszProductId Where to store the pointer to the product ID string to report.
+ * @param ppszProductLevel Where to store the pointer to the product level string to report.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnVScsiLunQueryInqStrings, (VSCSILUN hVScsiLun, void *pvScsiLunUser, const char **ppszVendorId,
+ const char **ppszProductId, const char **ppszProductLevel));
+
+} VSCSILUNIOCALLBACKS;
+/** Pointer to a virtual SCSI LUN I/O callback table. */
+typedef VSCSILUNIOCALLBACKS *PVSCSILUNIOCALLBACKS;
+
+/**
+ * The virtual SCSI request completed callback.
+ */
+typedef DECLCALLBACKTYPE(void, FNVSCSIREQCOMPLETED,(VSCSIDEVICE hVScsiDevice,
+ void *pvVScsiDeviceUser,
+ void *pvVScsiReqUser,
+ int rcScsiCode,
+ bool fRedoPossible,
+ int rcReq,
+ size_t cbXfer,
+ VSCSIXFERDIR enmXferDir,
+ size_t cbSense));
+/** Pointer to a virtual SCSI request completed callback. */
+typedef FNVSCSIREQCOMPLETED *PFNVSCSIREQCOMPLETED;
+
+/**
+ * Create a new empty SCSI device instance.
+ *
+ * @returns VBox status code.
+ * @param phVScsiDevice Where to store the SCSI device handle.
+ * @param pfnVScsiReqCompleted The method call after a request completed.
+ * @param pvVScsiDeviceUser Opaque user data given in the completion callback.
+ */
+VBOXDDU_DECL(int) VSCSIDeviceCreate(PVSCSIDEVICE phVScsiDevice,
+ PFNVSCSIREQCOMPLETED pfnVScsiReqCompleted,
+ void *pvVScsiDeviceUser);
+
+/**
+ * Destroy a SCSI device instance.
+ *
+ * @returns VBox status code.
+ * @param hVScsiDevice The SCSI device handle to destroy.
+ */
+VBOXDDU_DECL(int) VSCSIDeviceDestroy(VSCSIDEVICE hVScsiDevice);
+
+/**
+ * Attach a LUN to the SCSI device.
+ *
+ * @returns VBox status code.
+ * @param hVScsiDevice The SCSI device handle to add the LUN to.
+ * @param hVScsiLun The LUN handle to add.
+ * @param iLun The LUN number.
+ */
+VBOXDDU_DECL(int) VSCSIDeviceLunAttach(VSCSIDEVICE hVScsiDevice, VSCSILUN hVScsiLun, uint32_t iLun);
+
+/**
+ * Detach a LUN from the SCSI device.
+ *
+ * @returns VBox status code.
+ * @param hVScsiDevice The SCSI device handle to add the LUN to.
+ * @param iLun The LUN number to remove.
+ * @param phVScsiLun Where to store the detached LUN handle.
+ */
+VBOXDDU_DECL(int) VSCSIDeviceLunDetach(VSCSIDEVICE hVScsiDevice, uint32_t iLun,
+ PVSCSILUN phVScsiLun);
+
+/**
+ * Query the SCSI LUN type.
+ *
+ * @returns VBox status code.
+ * @param hVScsiDevice The SCSI device handle.
+ * @param iLun The LUN number to get.
+ * @param pEnmLunType Where to store the LUN type.
+ */
+VBOXDDU_DECL(int) VSCSIDeviceLunQueryType(VSCSIDEVICE hVScsiDevice, uint32_t iLun,
+ PVSCSILUNTYPE pEnmLunType);
+
+/**
+ * Enqueue a request to the SCSI device.
+ *
+ * @returns VBox status code.
+ * @param hVScsiDevice The SCSI device handle.
+ * @param hVScsiReq The SCSI request handle to enqueue.
+ */
+VBOXDDU_DECL(int) VSCSIDeviceReqEnqueue(VSCSIDEVICE hVScsiDevice, VSCSIREQ hVScsiReq);
+
+/**
+ * Allocate a new request handle.
+ *
+ * @returns VBox status code.
+ * @param hVScsiDevice The SCSI device handle.
+ * @param phVScsiReq Where to SCSI request handle.
+ * @param iLun The LUN the request is for.
+ * @param pbCDB The CDB for the request.
+ * @param cbCDB The size of the CDB in bytes.
+ * @param cbSGList Number of bytes the S/G list describes.
+ * @param cSGListEntries Number of S/G list entries.
+ * @param paSGList Pointer to the S/G list.
+ * @param pbSense Pointer to the sense buffer.
+ * @param cbSense Size of the sense buffer.
+ * @param pvVScsiReqUser Opqaue user data returned when the request completes.
+ */
+VBOXDDU_DECL(int) VSCSIDeviceReqCreate(VSCSIDEVICE hVScsiDevice, PVSCSIREQ phVScsiReq,
+ uint32_t iLun, uint8_t *pbCDB, size_t cbCDB,
+ size_t cbSGList, unsigned cSGListEntries,
+ PCRTSGSEG paSGList, uint8_t *pbSense,
+ size_t cbSense, void *pvVScsiReqUser);
+
+/**
+ * Create a new LUN.
+ *
+ * @returns VBox status code.
+ * @param phVScsiLun Where to store the SCSI LUN handle.
+ * @param enmLunType The Lun type.
+ * @param pVScsiLunIoCallbacks Pointer to the I/O callbacks to use for his LUN.
+ * @param pvVScsiLunUser Opaque user argument which
+ * is returned in the pvScsiLunUser parameter
+ * when the request completion callback is called.
+ */
+VBOXDDU_DECL(int) VSCSILunCreate(PVSCSILUN phVScsiLun, VSCSILUNTYPE enmLunType,
+ PVSCSILUNIOCALLBACKS pVScsiLunIoCallbacks,
+ void *pvVScsiLunUser);
+
+/**
+ * Destroy virtual SCSI LUN.
+ *
+ * @returns VBox status code.
+ * @param hVScsiLun The virtual SCSI LUN handle to destroy.
+ */
+VBOXDDU_DECL(int) VSCSILunDestroy(VSCSILUN hVScsiLun);
+
+/**
+ * Notify virtual SCSI LUN of medium being mounted.
+ *
+ * @returns VBox status code.
+ * @param hVScsiLun The virtual SCSI LUN handle to destroy.
+ */
+VBOXDDU_DECL(int) VSCSILunMountNotify(VSCSILUN hVScsiLun);
+
+/**
+ * Notify virtual SCSI LUN of medium being unmounted.
+ *
+ * @returns VBox status code.
+ * @param hVScsiLun The virtual SCSI LUN handle to destroy.
+ */
+VBOXDDU_DECL(int) VSCSILunUnmountNotify(VSCSILUN hVScsiLun);
+
+/**
+ * Notify a that a I/O request completed.
+ *
+ * @returns VBox status code.
+ * @param hVScsiIoReq The I/O request handle that completed.
+ * This is given when a I/O callback for
+ * the LUN is called by the virtual SCSI layer.
+ * @param rcIoReq The status code the I/O request completed with.
+ * @param fRedoPossible Flag whether it is possible to redo the request.
+ * If true setting any sense code will be omitted
+ * in case of an error to not alter the device state.
+ */
+VBOXDDU_DECL(int) VSCSIIoReqCompleted(VSCSIIOREQ hVScsiIoReq, int rcIoReq, bool fRedoPossible);
+
+/**
+ * Query the transfer direction of the I/O request.
+ *
+ * @returns Transfer direction.of the given I/O request
+ * @param hVScsiIoReq The SCSI I/O request handle.
+ */
+VBOXDDU_DECL(VSCSIIOREQTXDIR) VSCSIIoReqTxDirGet(VSCSIIOREQ hVScsiIoReq);
+
+/**
+ * Query I/O parameters.
+ *
+ * @returns VBox status code.
+ * @param hVScsiIoReq The SCSI I/O request handle.
+ * @param puOffset Where to store the start offset.
+ * @param pcbTransfer Where to store the amount of bytes to transfer.
+ * @param pcSeg Where to store the number of segments in the S/G list.
+ * @param pcbSeg Where to store the number of bytes the S/G list describes.
+ * @param ppaSeg Where to store the pointer to the S/G list.
+ */
+VBOXDDU_DECL(int) VSCSIIoReqParamsGet(VSCSIIOREQ hVScsiIoReq, uint64_t *puOffset,
+ size_t *pcbTransfer, unsigned *pcSeg,
+ size_t *pcbSeg, PCRTSGSEG *ppaSeg);
+
+/**
+ * Query unmap parameters.
+ *
+ * @returns VBox status code.
+ * @param hVScsiIoReq The SCSI I/O request handle.
+ * @param ppaRanges Where to store the pointer to the range array on success.
+ * @param pcRanges Where to store the number of ranges on success.
+ */
+VBOXDDU_DECL(int) VSCSIIoReqUnmapParamsGet(VSCSIIOREQ hVScsiIoReq, PCRTRANGE *ppaRanges,
+ unsigned *pcRanges);
+
+/** @} */
+RT_C_DECLS_END
+
+#endif /* !VBOX_INCLUDED_vscsi_h */
+
diff --git a/include/VBox/vusb.h b/include/VBox/vusb.h
new file mode 100644
index 00000000..95ae9b0a
--- /dev/null
+++ b/include/VBox/vusb.h
@@ -0,0 +1,1472 @@
+/** @file
+ * VUSB - VirtualBox USB. (DEV,VMM)
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_vusb_h
+#define VBOX_INCLUDED_vusb_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/cdefs.h>
+#include <VBox/types.h>
+#include <iprt/assert.h>
+
+struct PDMLED;
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_vusb VBox USB API
+ * @{
+ */
+
+/** @defgroup grp_vusb_std Standard Stuff
+ * @{ */
+
+/** Frequency of USB bus (from spec). */
+#define VUSB_BUS_HZ 12000000
+
+
+/** @name USB Descriptor types (from spec)
+ * @{ */
+#define VUSB_DT_DEVICE 0x01
+#define VUSB_DT_CONFIG 0x02
+#define VUSB_DT_STRING 0x03
+#define VUSB_DT_INTERFACE 0x04
+#define VUSB_DT_ENDPOINT 0x05
+#define VUSB_DT_DEVICE_QUALIFIER 0x06
+#define VUSB_DT_OTHER_SPEED_CFG 0x07
+#define VUSB_DT_INTERFACE_POWER 0x08
+#define VUSB_DT_INTERFACE_ASSOCIATION 0x0B
+#define VUSB_DT_BOS 0x0F
+#define VUSB_DT_DEVICE_CAPABILITY 0x10
+#define VUSB_DT_SS_ENDPOINT_COMPANION 0x30
+/** @} */
+
+/** @name USB Descriptor minimum sizes (from spec)
+ * @{ */
+#define VUSB_DT_DEVICE_MIN_LEN 18
+#define VUSB_DT_CONFIG_MIN_LEN 9
+#define VUSB_DT_CONFIG_STRING_MIN_LEN 2
+#define VUSB_DT_INTERFACE_MIN_LEN 9
+#define VUSB_DT_ENDPOINT_MIN_LEN 7
+#define VUSB_DT_SSEP_COMPANION_MIN_LEN 6
+/** @} */
+
+/** @name USB Device Capability Type Codes (from spec)
+ * @{ */
+#define VUSB_DCT_WIRELESS_USB 0x01
+#define VUSB_DCT_USB_20_EXTENSION 0x02
+#define VUSB_DCT_SUPERSPEED_USB 0x03
+#define VUSB_DCT_CONTAINER_ID 0x04
+/** @} */
+
+
+#pragma pack(1) /* ensure byte packing of the descriptors. */
+
+/**
+ * USB language id descriptor (from specs).
+ */
+typedef struct VUSBDESCLANGID
+{
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+} VUSBDESCLANGID;
+/** Pointer to a USB language id descriptor. */
+typedef VUSBDESCLANGID *PVUSBDESCLANGID;
+/** Pointer to a const USB language id descriptor. */
+typedef const VUSBDESCLANGID *PCVUSBDESCLANGID;
+
+
+/**
+ * USB string descriptor (from specs).
+ */
+typedef struct VUSBDESCSTRING
+{
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+} VUSBDESCSTRING;
+/** Pointer to a USB string descriptor. */
+typedef VUSBDESCSTRING *PVUSBDESCSTRING;
+/** Pointer to a const USB string descriptor. */
+typedef const VUSBDESCSTRING *PCVUSBDESCSTRING;
+
+
+/**
+ * USB device descriptor (from spec)
+ */
+typedef struct VUSBDESCDEVICE
+{
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint16_t bcdUSB;
+ uint8_t bDeviceClass;
+ uint8_t bDeviceSubClass;
+ uint8_t bDeviceProtocol;
+ uint8_t bMaxPacketSize0;
+ uint16_t idVendor;
+ uint16_t idProduct;
+ uint16_t bcdDevice;
+ uint8_t iManufacturer;
+ uint8_t iProduct;
+ uint8_t iSerialNumber;
+ uint8_t bNumConfigurations;
+} VUSBDESCDEVICE;
+/** Pointer to a USB device descriptor. */
+typedef VUSBDESCDEVICE *PVUSBDESCDEVICE;
+/** Pointer to a const USB device descriptor. */
+typedef const VUSBDESCDEVICE *PCVUSBDESCDEVICE;
+
+/**
+ * USB device qualifier (from spec 9.6.2)
+ */
+struct VUSBDEVICEQUALIFIER
+{
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint16_t bcdUsb;
+ uint8_t bDeviceClass;
+ uint8_t bDeviceSubClass;
+ uint8_t bDeviceProtocol;
+ uint8_t bMaxPacketSize0;
+ uint8_t bNumConfigurations;
+ uint8_t bReserved;
+};
+
+typedef struct VUSBDEVICEQUALIFIER VUSBDEVICEQUALIFIER;
+typedef VUSBDEVICEQUALIFIER *PVUSBDEVICEQUALIFIER;
+
+
+/**
+ * USB configuration descriptor (from spec).
+ */
+typedef struct VUSBDESCCONFIG
+{
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint16_t wTotalLength; /**< recalculated by VUSB when involved in URB. */
+ uint8_t bNumInterfaces;
+ uint8_t bConfigurationValue;
+ uint8_t iConfiguration;
+ uint8_t bmAttributes;
+ uint8_t MaxPower;
+} VUSBDESCCONFIG;
+/** Pointer to a USB configuration descriptor. */
+typedef VUSBDESCCONFIG *PVUSBDESCCONFIG;
+/** Pointer to a readonly USB configuration descriptor. */
+typedef const VUSBDESCCONFIG *PCVUSBDESCCONFIG;
+
+
+/**
+ * USB interface association descriptor (from USB ECN Interface Association Descriptors)
+ */
+typedef struct VUSBDESCIAD
+{
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bFirstInterface;
+ uint8_t bInterfaceCount;
+ uint8_t bFunctionClass;
+ uint8_t bFunctionSubClass;
+ uint8_t bFunctionProtocol;
+ uint8_t iFunction;
+} VUSBDESCIAD;
+/** Pointer to a USB interface association descriptor. */
+typedef VUSBDESCIAD *PVUSBDESCIAD;
+/** Pointer to a readonly USB interface association descriptor. */
+typedef const VUSBDESCIAD *PCVUSBDESCIAD;
+
+
+/**
+ * USB interface descriptor (from spec)
+ */
+typedef struct VUSBDESCINTERFACE
+{
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bInterfaceNumber;
+ uint8_t bAlternateSetting;
+ uint8_t bNumEndpoints;
+ uint8_t bInterfaceClass;
+ uint8_t bInterfaceSubClass;
+ uint8_t bInterfaceProtocol;
+ uint8_t iInterface;
+} VUSBDESCINTERFACE;
+/** Pointer to a USB interface descriptor. */
+typedef VUSBDESCINTERFACE *PVUSBDESCINTERFACE;
+/** Pointer to a const USB interface descriptor. */
+typedef const VUSBDESCINTERFACE *PCVUSBDESCINTERFACE;
+
+
+/**
+ * USB endpoint descriptor (from spec)
+ */
+typedef struct VUSBDESCENDPOINT
+{
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bEndpointAddress;
+ uint8_t bmAttributes;
+ uint16_t wMaxPacketSize;
+ uint8_t bInterval;
+} VUSBDESCENDPOINT;
+/** Pointer to a USB endpoint descriptor. */
+typedef VUSBDESCENDPOINT *PVUSBDESCENDPOINT;
+/** Pointer to a const USB endpoint descriptor. */
+typedef const VUSBDESCENDPOINT *PCVUSBDESCENDPOINT;
+
+
+/**
+ * USB SuperSpeed endpoint companion descriptor (from USB3 spec)
+ */
+typedef struct VUSBDESCSSEPCOMPANION
+{
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bMaxBurst;
+ uint8_t bmAttributes;
+ uint16_t wBytesPerInterval;
+} VUSBDESCSSEPCOMPANION;
+/** Pointer to a USB endpoint companion descriptor. */
+typedef VUSBDESCSSEPCOMPANION *PVUSBDESCSSEPCOMPANION;
+/** Pointer to a const USB endpoint companion descriptor. */
+typedef const VUSBDESCSSEPCOMPANION *PCVUSBDESCSSEPCOMPANION;
+
+
+/**
+ * USB Binary Device Object Store, aka BOS (from USB3 spec)
+ */
+typedef struct VUSBDESCBOS
+{
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint16_t wTotalLength;
+ uint8_t bNumDeviceCaps;
+} VUSBDESCBOS;
+/** Pointer to a USB BOS descriptor. */
+typedef VUSBDESCBOS *PVUSBDESCBOS;
+/** Pointer to a const USB BOS descriptor. */
+typedef const VUSBDESCBOS *PCVUSBDESCBOS;
+
+
+/**
+ * Generic USB Device Capability Descriptor within BOS (from USB3 spec)
+ */
+typedef struct VUSBDESCDEVICECAP
+{
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bDevCapabilityType;
+ uint8_t aCapSpecific[1];
+} VUSBDESCDEVICECAP;
+/** Pointer to a USB device capability descriptor. */
+typedef VUSBDESCDEVICECAP *PVUSBDESCDEVICECAP;
+/** Pointer to a const USB device capability descriptor. */
+typedef const VUSBDESCDEVICECAP *PCVUSBDESCDEVICECAP;
+
+
+/**
+ * SuperSpeed USB Device Capability Descriptor within BOS
+ */
+typedef struct VUSBDESCSSDEVCAP
+{
+ uint8_t bLength;
+ uint8_t bDescriptorType; /* DEVICE CAPABILITY */
+ uint8_t bDevCapabilityType; /* SUPERSPEED_USB */
+ uint8_t bmAttributes;
+ uint16_t wSpeedsSupported;
+ uint8_t bFunctionalitySupport;
+ uint8_t bU1DevExitLat;
+ uint16_t wU2DevExitLat;
+} VUSBDESCSSDEVCAP;
+/** Pointer to an SS USB device capability descriptor. */
+typedef VUSBDESCSSDEVCAP *PVUSBDESCSSDEVCAP;
+/** Pointer to a const SS USB device capability descriptor. */
+typedef const VUSBDESCSSDEVCAP *PCVUSBDESCSSDEVCAP;
+
+
+/**
+ * USB 2.0 Extension Descriptor within BOS
+ */
+typedef struct VUSBDESCUSB2EXT
+{
+ uint8_t bLength;
+ uint8_t bDescriptorType; /* DEVICE CAPABILITY */
+ uint8_t bDevCapabilityType; /* USB 2.0 EXTENSION */
+ uint8_t bmAttributes;
+} VUSBDESCUSB2EXT;
+/** Pointer to a USB 2.0 extension capability descriptor. */
+typedef VUSBDESCUSB2EXT *PVUSBDESCUSB2EXT;
+/** Pointer to a const USB 2.0 extension capability descriptor. */
+typedef const VUSBDESCUSB2EXT *PCVUSBDESCUSB2EXT;
+
+
+#pragma pack() /* end of the byte packing. */
+
+
+/**
+ * USB configuration descriptor, the parsed variant used by VUSB.
+ */
+typedef struct VUSBDESCCONFIGEX
+{
+ /** The USB descriptor data.
+ * @remark The wTotalLength member is recalculated before the data is passed to the guest. */
+ VUSBDESCCONFIG Core;
+ /** Pointer to additional descriptor bytes following what's covered by VUSBDESCCONFIG. */
+ void *pvMore;
+ /** Pointer to additional class- or vendor-specific interface descriptors. */
+ const void *pvClass;
+ /** Size of class- or vendor-specific descriptors. */
+ uint16_t cbClass;
+ /** Pointer to an array of the interfaces referenced in the configuration.
+ * Core.bNumInterfaces in size. */
+ const struct VUSBINTERFACE *paIfs;
+ /** Pointer to the original descriptor data read from the device. */
+ const void *pvOriginal;
+} VUSBDESCCONFIGEX;
+/** Pointer to a parsed USB configuration descriptor. */
+typedef VUSBDESCCONFIGEX *PVUSBDESCCONFIGEX;
+/** Pointer to a const parsed USB configuration descriptor. */
+typedef const VUSBDESCCONFIGEX *PCVUSBDESCCONFIGEX;
+
+
+/**
+ * For tracking the alternate interface settings of a configuration.
+ */
+typedef struct VUSBINTERFACE
+{
+ /** Pointer to an array of interfaces. */
+ const struct VUSBDESCINTERFACEEX *paSettings;
+ /** The number of entries in the array. */
+ uint32_t cSettings;
+} VUSBINTERFACE;
+/** Pointer to a VUSBINTERFACE. */
+typedef VUSBINTERFACE *PVUSBINTERFACE;
+/** Pointer to a const VUSBINTERFACE. */
+typedef const VUSBINTERFACE *PCVUSBINTERFACE;
+
+
+/**
+ * USB interface descriptor, the parsed variant used by VUSB.
+ */
+typedef struct VUSBDESCINTERFACEEX
+{
+ /** The USB descriptor data. */
+ VUSBDESCINTERFACE Core;
+ /** Pointer to additional descriptor bytes following what's covered by VUSBDESCINTERFACE. */
+ const void *pvMore;
+ /** Pointer to additional class- or vendor-specific interface descriptors. */
+ const void *pvClass;
+ /** Size of class- or vendor-specific descriptors. */
+ uint16_t cbClass;
+ /** Pointer to an array of the endpoints referenced by the interface.
+ * Core.bNumEndpoints in size. */
+ const struct VUSBDESCENDPOINTEX *paEndpoints;
+ /** Interface association descriptor, which prepends a group of interfaces,
+ * starting with this interface. */
+ PCVUSBDESCIAD pIAD;
+ /** Size of interface association descriptor. */
+ uint16_t cbIAD;
+} VUSBDESCINTERFACEEX;
+/** Pointer to an prased USB interface descriptor. */
+typedef VUSBDESCINTERFACEEX *PVUSBDESCINTERFACEEX;
+/** Pointer to a const parsed USB interface descriptor. */
+typedef const VUSBDESCINTERFACEEX *PCVUSBDESCINTERFACEEX;
+
+
+/**
+ * USB endpoint descriptor, the parsed variant used by VUSB.
+ */
+typedef struct VUSBDESCENDPOINTEX
+{
+ /** The USB descriptor data.
+ * @remark The wMaxPacketSize member is converted to native endian. */
+ VUSBDESCENDPOINT Core;
+ /** Pointer to additional descriptor bytes following what's covered by VUSBDESCENDPOINT. */
+ const void *pvMore;
+ /** Pointer to additional class- or vendor-specific endpoint descriptors. */
+ const void *pvClass;
+ /** Size of class- or vendor-specific descriptors. */
+ uint16_t cbClass;
+ /** Pointer to SuperSpeed endpoint companion descriptor (SS endpoints only). */
+ const void *pvSsepc;
+ /** Size of SuperSpeed endpoint companion descriptor.
+ * @remark Must be non-zero for SuperSpeed endpoints. */
+ uint16_t cbSsepc;
+} VUSBDESCENDPOINTEX;
+/** Pointer to a parsed USB endpoint descriptor. */
+typedef VUSBDESCENDPOINTEX *PVUSBDESCENDPOINTEX;
+/** Pointer to a const parsed USB endpoint descriptor. */
+typedef const VUSBDESCENDPOINTEX *PCVUSBDESCENDPOINTEX;
+
+
+/** @name USB Control message recipient codes (from spec)
+ * @{ */
+#define VUSB_TO_DEVICE 0x0
+#define VUSB_TO_INTERFACE 0x1
+#define VUSB_TO_ENDPOINT 0x2
+#define VUSB_TO_OTHER 0x3
+#define VUSB_RECIP_MASK 0x1f
+/** @} */
+
+/** @name USB control pipe setup packet structure (from spec)
+ * @{ */
+#define VUSB_REQ_SHIFT (5)
+#define VUSB_REQ_STANDARD (0x0 << VUSB_REQ_SHIFT)
+#define VUSB_REQ_CLASS (0x1 << VUSB_REQ_SHIFT)
+#define VUSB_REQ_VENDOR (0x2 << VUSB_REQ_SHIFT)
+#define VUSB_REQ_RESERVED (0x3 << VUSB_REQ_SHIFT)
+#define VUSB_REQ_MASK (0x3 << VUSB_REQ_SHIFT)
+/** @} */
+
+#define VUSB_DIR_TO_DEVICE 0x00
+#define VUSB_DIR_TO_HOST 0x80
+#define VUSB_DIR_MASK 0x80
+
+/**
+ * USB Setup request (from spec)
+ */
+typedef struct vusb_setup
+{
+ uint8_t bmRequestType;
+ uint8_t bRequest;
+ uint16_t wValue;
+ uint16_t wIndex;
+ uint16_t wLength;
+} VUSBSETUP;
+/** Pointer to a setup request. */
+typedef VUSBSETUP *PVUSBSETUP;
+/** Pointer to a const setup request. */
+typedef const VUSBSETUP *PCVUSBSETUP;
+
+/** @name USB Standard device requests (from spec)
+ * @{ */
+#define VUSB_REQ_GET_STATUS 0x00
+#define VUSB_REQ_CLEAR_FEATURE 0x01
+#define VUSB_REQ_SET_FEATURE 0x03
+#define VUSB_REQ_SET_ADDRESS 0x05
+#define VUSB_REQ_GET_DESCRIPTOR 0x06
+#define VUSB_REQ_SET_DESCRIPTOR 0x07
+#define VUSB_REQ_GET_CONFIGURATION 0x08
+#define VUSB_REQ_SET_CONFIGURATION 0x09
+#define VUSB_REQ_GET_INTERFACE 0x0a
+#define VUSB_REQ_SET_INTERFACE 0x0b
+#define VUSB_REQ_SYNCH_FRAME 0x0c
+#define VUSB_REQ_MAX 0x0d
+/** @} */
+
+/** @} */ /* end of grp_vusb_std */
+
+
+
+/** @name USB Standard version flags.
+ * @{ */
+/** Indicates USB 1.1 support. */
+#define VUSB_STDVER_11 RT_BIT(1)
+/** Indicates USB 2.0 support. */
+#define VUSB_STDVER_20 RT_BIT(2)
+/** Indicates USB 3.0 support. */
+#define VUSB_STDVER_30 RT_BIT(3)
+/** @} */
+
+/**
+ * USB port/device speeds.
+ */
+typedef enum VUSBSPEED
+{
+ /** Undetermined/unknown speed. */
+ VUSB_SPEED_UNKNOWN = 0,
+ /** Low-speed (LS), 1.5 Mbit/s, USB 1.0. */
+ VUSB_SPEED_LOW,
+ /** Full-speed (FS), 12 Mbit/s, USB 1.1. */
+ VUSB_SPEED_FULL,
+ /** High-speed (HS), 480 Mbit/s, USB 2.0. */
+ VUSB_SPEED_HIGH,
+ /** Variable speed, wireless USB 2.5. */
+ VUSB_SPEED_VARIABLE,
+ /** SuperSpeed (SS), 5.0 Gbit/s, USB 3.0. */
+ VUSB_SPEED_SUPER,
+ /** SuperSpeed+ (SS+), 10.0 Gbit/s, USB 3.1. */
+ VUSB_SPEED_SUPERPLUS,
+ /** The usual 32-bit hack. */
+ VUSB_SPEED_32BIT_HACK = 0x7fffffff
+} VUSBSPEED;
+
+/**
+ * VUSB transfer direction.
+ */
+typedef enum VUSBDIRECTION
+{
+ /** Setup */
+ VUSBDIRECTION_SETUP = 0,
+#define VUSB_DIRECTION_SETUP VUSBDIRECTION_SETUP
+ /** In - Device to host. */
+ VUSBDIRECTION_IN = 1,
+#define VUSB_DIRECTION_IN VUSBDIRECTION_IN
+ /** Out - Host to device. */
+ VUSBDIRECTION_OUT = 2,
+#define VUSB_DIRECTION_OUT VUSBDIRECTION_OUT
+ /** Invalid direction */
+ VUSBDIRECTION_INVALID = 0x7f
+} VUSBDIRECTION;
+
+/**
+ * VUSB Transfer types.
+ */
+typedef enum VUSBXFERTYPE
+{
+ /** Control message. Used to represent a single control transfer. */
+ VUSBXFERTYPE_CTRL = 0,
+ /* Isochronous transfer. */
+ VUSBXFERTYPE_ISOC,
+ /** Bulk transfer. */
+ VUSBXFERTYPE_BULK,
+ /** Interrupt transfer. */
+ VUSBXFERTYPE_INTR,
+ /** Complete control message. Used to represent an entire control message. */
+ VUSBXFERTYPE_MSG,
+ /** Invalid transfer type. */
+ VUSBXFERTYPE_INVALID = 0x7f
+} VUSBXFERTYPE;
+
+/** Number of valid USB transfer types - KEEP in sync with VUSBXFERTYPE!. */
+#define VUSBXFERTYPE_ELEMENTS (5)
+
+/** Pointer to a VBox USB device interface. */
+typedef struct VUSBIDEVICE *PVUSBIDEVICE;
+
+/** Pointer to a VUSB RootHub port interface. */
+typedef struct VUSBIROOTHUBPORT *PVUSBIROOTHUBPORT;
+
+/** Pointer to an USB request descriptor. */
+typedef struct VUSBURB *PVUSBURB;
+
+
+/**
+ * VUSB device reset completion callback function.
+ * This is called by the reset thread when the reset has been completed.
+ *
+ * @param pDevice Pointer to the virtual USB device core.
+ * @param uPort The port of the device which completed the reset.
+ * @param rc The VBox status code of the reset operation.
+ * @param pvUser User specific argument.
+ *
+ * @thread The reset thread or EMT.
+ */
+typedef DECLCALLBACKTYPE(void, FNVUSBRESETDONE,(PVUSBIDEVICE pDevice, uint32_t uPort, int rc, void *pvUser));
+/** Pointer to a device reset completion callback function (FNUSBRESETDONE). */
+typedef FNVUSBRESETDONE *PFNVUSBRESETDONE;
+
+
+/**
+ * The state of a VUSB Device.
+ *
+ * @remark The order of these states is vital.
+ */
+typedef enum VUSBDEVICESTATE
+{
+ VUSB_DEVICE_STATE_INVALID = 0,
+ VUSB_DEVICE_STATE_DETACHED,
+ VUSB_DEVICE_STATE_ATTACHED,
+ VUSB_DEVICE_STATE_POWERED,
+ VUSB_DEVICE_STATE_DEFAULT,
+ VUSB_DEVICE_STATE_ADDRESS,
+ VUSB_DEVICE_STATE_CONFIGURED,
+ VUSB_DEVICE_STATE_SUSPENDED,
+ /** The device is being reset. Don't mess with it.
+ * Next states: VUSB_DEVICE_STATE_DEFAULT, VUSB_DEVICE_STATE_DESTROYED
+ */
+ VUSB_DEVICE_STATE_RESET,
+ /** The device has been destroyed. */
+ VUSB_DEVICE_STATE_DESTROYED,
+ /** The usual 32-bit hack. */
+ VUSB_DEVICE_STATE_32BIT_HACK = 0x7fffffff
+} VUSBDEVICESTATE;
+
+
+/** Maximum number of USB devices supported. */
+#define VUSB_DEVICES_MAX 128
+/** An invalid device port. */
+#define VUSB_DEVICE_PORT_INVALID UINT32_MAX
+
+/**
+ * VBox USB port bitmap.
+ *
+ * Bit 0 == Port 0, ... , Bit 127 == Port 127.
+ */
+typedef struct VUSBPORTBITMAP
+{
+ /** 128 bits */
+ char ach[VUSB_DEVICES_MAX / 8];
+} VUSBPORTBITMAP;
+/** Pointer to a VBox USB port bitmap. */
+typedef VUSBPORTBITMAP *PVUSBPORTBITMAP;
+AssertCompile(sizeof(VUSBPORTBITMAP) * 8 >= VUSB_DEVICES_MAX);
+
+#ifndef RDESKTOP
+
+/**
+ * The VUSB RootHub port interface provided by the HCI (down).
+ * Pair with VUSBIROOTCONNECTOR
+ */
+typedef struct VUSBIROOTHUBPORT
+{
+ /**
+ * Get the number of available ports in the hub.
+ *
+ * @returns The number of ports available.
+ * @param pInterface Pointer to this structure.
+ * @param pAvailable Bitmap indicating the available ports. Set bit == available port.
+ */
+ DECLR3CALLBACKMEMBER(unsigned, pfnGetAvailablePorts,(PVUSBIROOTHUBPORT pInterface, PVUSBPORTBITMAP pAvailable));
+
+ /**
+ * Gets the supported USB versions.
+ *
+ * @returns The mask of supported USB versions.
+ * @param pInterface Pointer to this structure.
+ */
+ DECLR3CALLBACKMEMBER(uint32_t, pfnGetUSBVersions,(PVUSBIROOTHUBPORT pInterface));
+
+ /**
+ * A device is being attached to a port in the roothub.
+ *
+ * @param pInterface Pointer to this structure.
+ * @param uPort The port number assigned to the device.
+ * @param enmSpeed The speed of the device being attached.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnAttach,(PVUSBIROOTHUBPORT pInterface, uint32_t uPort, VUSBSPEED enmSpeed));
+
+ /**
+ * A device is being detached from a port in the roothub.
+ *
+ * @param pInterface Pointer to this structure.
+ * @param uPort The port number assigned to the device.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnDetach,(PVUSBIROOTHUBPORT pInterface, uint32_t uPort));
+
+ /**
+ * Reset the root hub.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to this structure.
+ * @param fResetOnLinux Whether or not to do real reset on linux.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnReset,(PVUSBIROOTHUBPORT pInterface, bool fResetOnLinux));
+
+ /**
+ * Transfer completion callback routine.
+ *
+ * VUSB will call this when a transfer have been completed
+ * in a one or another way.
+ *
+ * @param pInterface Pointer to this structure.
+ * @param pUrb Pointer to the URB in question.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnXferCompletion,(PVUSBIROOTHUBPORT pInterface, PVUSBURB pUrb));
+
+ /**
+ * Handle transfer errors.
+ *
+ * VUSB calls this when a transfer attempt failed. This function will respond
+ * indicating whether to retry or complete the URB with failure.
+ *
+ * @returns Retry indicator.
+ * @param pInterface Pointer to this structure.
+ * @param pUrb Pointer to the URB in question.
+ */
+ DECLR3CALLBACKMEMBER(bool, pfnXferError,(PVUSBIROOTHUBPORT pInterface, PVUSBURB pUrb));
+
+ /**
+ * Processes a new frame if periodic frame processing is enabled.
+ *
+ * @returns Flag whether there was activity which influences the frame rate.
+ * @param pInterface Pointer to this structure.
+ * @param u32FrameNo The frame number.
+ */
+ DECLR3CALLBACKMEMBER(bool, pfnStartFrame, (PVUSBIROOTHUBPORT pInterface, uint32_t u32FrameNo));
+
+ /**
+ * Informs the callee about a change in the frame rate due to too many idle cycles or
+ * when seeing activity after some idle time.
+ *
+ * @returns nothing.
+ * @param pInterface Pointer to this structure.
+ * @param u32FrameRate The new frame rate.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnFrameRateChanged, (PVUSBIROOTHUBPORT pInterface, uint32_t u32FrameRate));
+
+ /** Alignment dummy. */
+ RTR3PTR Alignment;
+
+} VUSBIROOTHUBPORT;
+/** VUSBIROOTHUBPORT interface ID. */
+# define VUSBIROOTHUBPORT_IID "2ece01c2-4dbf-4bd5-96ca-09fc14164cd4"
+
+/** Pointer to a VUSB RootHub connector interface. */
+typedef struct VUSBIROOTHUBCONNECTOR *PVUSBIROOTHUBCONNECTOR;
+/**
+ * The VUSB RootHub connector interface provided by the VBox USB RootHub driver
+ * (up).
+ * Pair with VUSBIROOTHUBPORT.
+ */
+typedef struct VUSBIROOTHUBCONNECTOR
+{
+ /**
+ * Sets the URB parameters for the caller.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to this struct.
+ * @param cbHci Size of the data private to the HCI for each URB when allocated.
+ * @param cbHciTd Size of one transfer descriptor. The number of transfer descriptors
+ * is given VUSBIROOTHUBCONNECTOR::pfnNewUrb for each URB to calculate the
+ * final amount of memory required for the TDs.
+ *
+ * @note This must be called before starting to allocate any URB or otherwise there will be no
+ * data available for the HCI.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSetUrbParams, (PVUSBIROOTHUBCONNECTOR pInterface, size_t cbHci, size_t cbHciTd));
+
+ /**
+ * Resets the roothub.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to this struct.
+ * @param fResetOnLinux Whether or not to do real reset on linux.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnReset, (PVUSBIROOTHUBCONNECTOR pInterface, bool fResetOnLinux));
+
+ /**
+ * Powers on the roothub.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to this struct.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPowerOn, (PVUSBIROOTHUBCONNECTOR pInterface));
+
+ /**
+ * Power off the roothub.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to this struct.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPowerOff, (PVUSBIROOTHUBCONNECTOR pInterface));
+
+ /**
+ * Allocates a new URB for a transfer.
+ *
+ * Either submit using pfnSubmitUrb or free using VUSBUrbFree().
+ *
+ * @returns Pointer to a new URB.
+ * @returns NULL on failure - try again later.
+ * This will not fail if the device wasn't found. We'll fail it
+ * at submit time, since that makes the usage of this api simpler.
+ * @param pInterface Pointer to this struct.
+ * @param DstAddress The destination address of the URB.
+ * @param uPort Optional port of the device the URB is for, use VUSB_DEVICE_PORT_INVALID to indicate to use the destination address.
+ * @param enmType Type of the URB.
+ * @param enmDir Data transfer direction.
+ * @param cbData The amount of data space required.
+ * @param cTds The amount of TD space.
+ * @param pszTag Custom URB tag assigned by the caller, only for
+ * logged builds and optional.
+ *
+ * @note pDev should be NULL in most cases. The only useful case is for USB3 where
+ * it is required for the SET_ADDRESS request because USB3 uses unicast traffic.
+ */
+ DECLR3CALLBACKMEMBER(PVUSBURB, pfnNewUrb,(PVUSBIROOTHUBCONNECTOR pInterface, uint8_t DstAddress, uint32_t uPort,
+ VUSBXFERTYPE enmType, VUSBDIRECTION enmDir, uint32_t cbData, uint32_t cTds, const char *pszTag));
+
+ /**
+ * Free an URB not submitted yet.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to this struct.
+ * @param pUrb Pointer to the URB to free returned by VUSBIROOTHUBCONNECTOR::pfnNewUrb.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnFreeUrb, (PVUSBIROOTHUBCONNECTOR pInterface, PVUSBURB pUrb));
+
+ /**
+ * Submits a URB for transfer.
+ * The transfer will do asynchronously if possible.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to this struct.
+ * @param pUrb Pointer to the URB returned by pfnNewUrb.
+ * The URB will be freed in case of failure.
+ * @param pLed Pointer to USB Status LED
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSubmitUrb,(PVUSBIROOTHUBCONNECTOR pInterface, PVUSBURB pUrb, struct PDMLED *pLed));
+
+ /**
+ * Call to service asynchronous URB completions in a polling fashion.
+ *
+ * Reaped URBs will be finished by calling the completion callback,
+ * thus there is no return code or input or anything from this function
+ * except for potential state changes elsewhere.
+ *
+ * @returns VINF_SUCCESS if no URBs are pending upon return.
+ * @returns VERR_TIMEOUT if one or more URBs are still in flight upon returning.
+ * @returns Other VBox status code.
+ *
+ * @param pInterface Pointer to this struct.
+ * @param uPort Port of the device to reap URBs on.
+ * @param cMillies Number of milliseconds to poll for completion.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnReapAsyncUrbs,(PVUSBIROOTHUBCONNECTOR pInterface, uint32_t uPort, RTMSINTERVAL cMillies));
+
+ /**
+ * Cancels and completes - with CRC failure - all URBs queued on an endpoint.
+ * This is done in response to guest URB cancellation.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to this struct.
+ * @param pUrb Pointer to a previously submitted URB.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnCancelUrbsEp,(PVUSBIROOTHUBCONNECTOR pInterface, PVUSBURB pUrb));
+
+ /**
+ * Cancels and completes - with CRC failure - all in-flight async URBs.
+ * This is typically done before saving a state.
+ *
+ * @param pInterface Pointer to this struct.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnCancelAllUrbs,(PVUSBIROOTHUBCONNECTOR pInterface));
+
+ /**
+ * Cancels and completes - with CRC failure - all URBs queued on an endpoint.
+ * This is done in response to a guest endpoint/pipe abort.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to this struct.
+ * @param uPort Port of the device.
+ * @param EndPt Endpoint number.
+ * @param enmDir Endpoint direction.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnAbortEp,(PVUSBIROOTHUBCONNECTOR pInterface, uint32_t uPort, int EndPt, VUSBDIRECTION enmDir));
+
+ /**
+ * Attach the device to the root hub.
+ * The device must not be attached to any hub for this call to succeed.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to this struct.
+ * @param uPort Port of the device to attach.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnAttachDevice,(PVUSBIROOTHUBCONNECTOR pInterface, uint32_t uPort));
+
+ /**
+ * Detach the device from the root hub.
+ * The device must already be attached for this call to succeed.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to this struct.
+ * @param uPort Port of the device to detach.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnDetachDevice,(PVUSBIROOTHUBCONNECTOR pInterface, uint32_t uPort));
+
+ /**
+ * Sets periodic frame processing.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to this struct.
+ * @param uFrameRate The target frame rate in Hertz, 0 disables periodic frame processing.
+ * The real frame rate might be lower if there is no activity for a certain period or
+ * higher if there is a need for catching up with where the guest expects the device to be.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSetPeriodicFrameProcessing, (PVUSBIROOTHUBCONNECTOR pInterface, uint32_t uFrameRate));
+
+ /**
+ * Returns the current frame rate for the periodic frame processing.
+ *
+ * @returns Frame rate for periodic frame processing.
+ * @retval 0 if disabled.
+ * @param pInterface Pointer to this struct.
+ */
+ DECLR3CALLBACKMEMBER(uint32_t, pfnGetPeriodicFrameRate, (PVUSBIROOTHUBCONNECTOR pInterface));
+
+ /**
+ * Updates the internally stored isochronous scheduling frame for a given
+ * endpoint and returns the delta between the current and previous frame.
+ *
+ * @returns Delta between currently and previously scheduled frame.
+ * @retval 0 if no previous frame was set.
+ * @param pInterface Pointer to this struct.
+ * @param uPort Port of the device.
+ * @param EndPt Endpoint number.
+ * @param enmDir Endpoint direction.
+ * @param uNewFrameID The frame ID of a new transfer.
+ * @param uBits The number of significant bits in frame ID.
+ */
+ DECLR3CALLBACKMEMBER(uint32_t, pfnUpdateIsocFrameDelta, (PVUSBIROOTHUBCONNECTOR pInterface, uint32_t uPort,
+ int EndPt, VUSBDIRECTION enmDir, uint16_t uNewFrameID, uint8_t uBits));
+
+ /**
+ * Resets the device.
+ *
+ * Since a device reset shall take at least 10ms from the guest point of view,
+ * it must be performed asynchronously. We create a thread which performs this
+ * operation and ensures it will take at least 10ms.
+ *
+ * At times - like init - a synchronous reset is required, this can be done
+ * by passing NULL for pfnDone.
+ *
+ * -- internal stuff, move it --
+ * While the device is being reset it is in the VUSB_DEVICE_STATE_RESET state.
+ * On completion it will be in the VUSB_DEVICE_STATE_DEFAULT state if successful,
+ * or in the VUSB_DEVICE_STATE_DETACHED state if the rest failed.
+ * -- internal stuff, move it --
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to this struct.
+ * @param uPort Port of the device to reset.
+ * @param fResetOnLinux Set if we can permit a real reset and a potential logical
+ * device reconnect on linux hosts.
+ * @param pfnDone Pointer to the completion routine. If NULL a synchronous
+ * reset is performed not respecting the 10ms.
+ * @param pvUser User argument to the completion routine.
+ * @param pVM The cross context VM structure. Required if pfnDone
+ * is not NULL.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnDevReset,(PVUSBIROOTHUBCONNECTOR pInterface, uint32_t uPort, bool fResetOnLinux,
+ PFNVUSBRESETDONE pfnDone, void *pvUser, PVM pVM));
+
+ /**
+ * Powers on the device.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to this struct.
+ * @param uPort Port of the device to power on.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnDevPowerOn,(PVUSBIROOTHUBCONNECTOR pInterface, uint32_t uPort));
+
+ /**
+ * Powers off the device.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to this struct.
+ * @param uPort Port of the device to power off.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnDevPowerOff,(PVUSBIROOTHUBCONNECTOR pInterface, uint32_t uPort));
+
+ /**
+ * Get the state of the device.
+ *
+ * @returns Device state.
+ * @param pInterface Pointer to this struct.
+ * @param uPort Port of the device to get the state for.
+ */
+ DECLR3CALLBACKMEMBER(VUSBDEVICESTATE, pfnDevGetState,(PVUSBIROOTHUBCONNECTOR pInterface, uint32_t uPort));
+
+ /**
+ * Returns whether the device implements the saved state handlers
+ * and doesn't need to get detached.
+ *
+ * @returns true if the device supports saving the state, false otherwise.
+ * @param pInterface Pointer to this struct.
+ * @param uPort Port of the device to query saved state support for.
+ */
+ DECLR3CALLBACKMEMBER(bool, pfnDevIsSavedStateSupported,(PVUSBIROOTHUBCONNECTOR pInterface, uint32_t uPort));
+
+ /**
+ * Get the speed the device is operating at.
+ *
+ * @returns Device state.
+ * @param pInterface Pointer to this struct.
+ * @param uPort Port of the device to query the speed for.
+ */
+ DECLR3CALLBACKMEMBER(VUSBSPEED, pfnDevGetSpeed,(PVUSBIROOTHUBCONNECTOR pInterface, uint32_t uPort));
+
+} VUSBIROOTHUBCONNECTOR;
+AssertCompileSizeAlignment(VUSBIROOTHUBCONNECTOR, 8);
+/** VUSBIROOTHUBCONNECTOR interface ID. */
+# define VUSBIROOTHUBCONNECTOR_IID "662d7822-b9c6-43b5-88b6-5d59f0106e46"
+
+
+# ifdef IN_RING3
+/** @copydoc VUSBIROOTHUBCONNECTOR::pfnSetUrbParams */
+DECLINLINE(int) VUSBIRhSetUrbParams(PVUSBIROOTHUBCONNECTOR pInterface, size_t cbHci, size_t cbHciTd)
+{
+ return pInterface->pfnSetUrbParams(pInterface, cbHci, cbHciTd);
+}
+
+/** @copydoc VUSBIROOTHUBCONNECTOR::pfnNewUrb */
+DECLINLINE(PVUSBURB) VUSBIRhNewUrb(PVUSBIROOTHUBCONNECTOR pInterface, uint8_t DstAddress, uint32_t uPort,
+ VUSBXFERTYPE enmType, VUSBDIRECTION enmDir, uint32_t cbData, uint32_t cTds, const char *pszTag)
+{
+ return pInterface->pfnNewUrb(pInterface, DstAddress, uPort, enmType, enmDir, cbData, cTds, pszTag);
+}
+
+/** @copydoc VUSBIROOTHUBCONNECTOR::pfnFreeUrb */
+DECLINLINE(int) VUSBIRhFreeUrb(PVUSBIROOTHUBCONNECTOR pInterface, PVUSBURB pUrb)
+{
+ return pInterface->pfnFreeUrb(pInterface, pUrb);
+}
+
+/** @copydoc VUSBIROOTHUBCONNECTOR::pfnSubmitUrb */
+DECLINLINE(int) VUSBIRhSubmitUrb(PVUSBIROOTHUBCONNECTOR pInterface, PVUSBURB pUrb, struct PDMLED *pLed)
+{
+ return pInterface->pfnSubmitUrb(pInterface, pUrb, pLed);
+}
+
+/** @copydoc VUSBIROOTHUBCONNECTOR::pfnReapAsyncUrbs */
+DECLINLINE(void) VUSBIRhReapAsyncUrbs(PVUSBIROOTHUBCONNECTOR pInterface, uint32_t uPort, RTMSINTERVAL cMillies)
+{
+ pInterface->pfnReapAsyncUrbs(pInterface, uPort, cMillies);
+}
+
+/** @copydoc VUSBIROOTHUBCONNECTOR::pfnCancelAllUrbs */
+DECLINLINE(void) VUSBIRhCancelAllUrbs(PVUSBIROOTHUBCONNECTOR pInterface)
+{
+ pInterface->pfnCancelAllUrbs(pInterface);
+}
+
+/** @copydoc VUSBIROOTHUBCONNECTOR::pfnAttachDevice */
+DECLINLINE(int) VUSBIRhAttachDevice(PVUSBIROOTHUBCONNECTOR pInterface, uint32_t uPort)
+{
+ return pInterface->pfnAttachDevice(pInterface, uPort);
+}
+
+/** @copydoc VUSBIROOTHUBCONNECTOR::pfnDetachDevice */
+DECLINLINE(int) VUSBIRhDetachDevice(PVUSBIROOTHUBCONNECTOR pInterface, uint32_t uPort)
+{
+ return pInterface->pfnDetachDevice(pInterface, uPort);
+}
+
+/** @copydoc VUSBIROOTHUBCONNECTOR::pfnSetPeriodicFrameProcessing */
+DECLINLINE(int) VUSBIRhSetPeriodicFrameProcessing(PVUSBIROOTHUBCONNECTOR pInterface, uint32_t uFrameRate)
+{
+ return pInterface->pfnSetPeriodicFrameProcessing(pInterface, uFrameRate);
+}
+
+/** @copydoc VUSBIROOTHUBCONNECTOR::pfnGetPeriodicFrameRate */
+DECLINLINE(uint32_t) VUSBIRhGetPeriodicFrameRate(PVUSBIROOTHUBCONNECTOR pInterface)
+{
+ return pInterface->pfnGetPeriodicFrameRate(pInterface);
+}
+
+/** @copydoc VUSBIROOTHUBCONNECTOR::pfnDevReset */
+DECLINLINE(int) VUSBIRhDevReset(PVUSBIROOTHUBCONNECTOR pInterface, uint32_t uPort, bool fResetOnLinux,
+ PFNVUSBRESETDONE pfnDone, void *pvUser, PVM pVM)
+{
+ return pInterface->pfnDevReset(pInterface, uPort, fResetOnLinux, pfnDone, pvUser, pVM);
+}
+
+/** @copydoc VUSBIROOTHUBCONNECTOR::pfnDevPowerOn */
+DECLINLINE(int) VUSBIRhDevPowerOn(PVUSBIROOTHUBCONNECTOR pInterface, uint32_t uPort)
+{
+ return pInterface->pfnDevPowerOn(pInterface, uPort);
+}
+
+/** @copydoc VUSBIROOTHUBCONNECTOR::pfnDevPowerOff */
+DECLINLINE(int) VUSBIRhDevPowerOff(PVUSBIROOTHUBCONNECTOR pInterface, uint32_t uPort)
+{
+ return pInterface->pfnDevPowerOff(pInterface, uPort);
+}
+
+/** @copydoc VUSBIROOTHUBCONNECTOR::pfnDevGetState */
+DECLINLINE(VUSBDEVICESTATE) VUSBIRhDevGetState(PVUSBIROOTHUBCONNECTOR pInterface, uint32_t uPort)
+{
+ return pInterface->pfnDevGetState(pInterface, uPort);
+}
+
+/** @copydoc VUSBIROOTHUBCONNECTOR::pfnDevGetState */
+DECLINLINE(bool) VUSBIRhDevIsSavedStateSupported(PVUSBIROOTHUBCONNECTOR pInterface, uint32_t uPort)
+{
+ return pInterface->pfnDevIsSavedStateSupported(pInterface, uPort);
+}
+
+/** @copydoc VUSBIROOTHUBCONNECTOR::pfnDevGetSpeed */
+DECLINLINE(VUSBSPEED) VUSBIRhDevGetSpeed(PVUSBIROOTHUBCONNECTOR pInterface, uint32_t uPort)
+{
+ return pInterface->pfnDevGetSpeed(pInterface, uPort);
+}
+# endif /* IN_RING3 */
+
+#endif /* ! RDESKTOP */
+
+
+#ifndef RDESKTOP
+
+/**
+ * USB Device Interface (up).
+ * No interface pair.
+ */
+typedef struct VUSBIDEVICE
+{
+ /**
+ * Resets the device.
+ *
+ * Since a device reset shall take at least 10ms from the guest point of view,
+ * it must be performed asynchronously. We create a thread which performs this
+ * operation and ensures it will take at least 10ms.
+ *
+ * At times - like init - a synchronous reset is required, this can be done
+ * by passing NULL for pfnDone.
+ *
+ * -- internal stuff, move it --
+ * While the device is being reset it is in the VUSB_DEVICE_STATE_RESET state.
+ * On completion it will be in the VUSB_DEVICE_STATE_DEFAULT state if successful,
+ * or in the VUSB_DEVICE_STATE_DETACHED state if the rest failed.
+ * -- internal stuff, move it --
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to this structure.
+ * @param fResetOnLinux Set if we can permit a real reset and a potential logical
+ * device reconnect on linux hosts.
+ * @param pfnDone Pointer to the completion routine. If NULL a synchronous
+ * reset is performed not respecting the 10ms.
+ * @param pvUser User argument to the completion routine.
+ * @param pVM The cross context VM structure. Required if pfnDone
+ * is not NULL.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnReset,(PVUSBIDEVICE pInterface, bool fResetOnLinux,
+ PFNVUSBRESETDONE pfnDone, void *pvUser, PVM pVM));
+
+ /**
+ * Powers on the device.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the device interface structure.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPowerOn,(PVUSBIDEVICE pInterface));
+
+ /**
+ * Powers off the device.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the device interface structure.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPowerOff,(PVUSBIDEVICE pInterface));
+
+ /**
+ * Get the state of the device.
+ *
+ * @returns Device state.
+ * @param pInterface Pointer to the device interface structure.
+ */
+ DECLR3CALLBACKMEMBER(VUSBDEVICESTATE, pfnGetState,(PVUSBIDEVICE pInterface));
+
+ /**
+ * Returns whether the device implements the saved state handlers
+ * and doesn't need to get detached.
+ *
+ * @returns true if the device supports saving the state, false otherwise.
+ * @param pInterface Pointer to the device interface structure.
+ */
+ DECLR3CALLBACKMEMBER(bool, pfnIsSavedStateSupported,(PVUSBIDEVICE pInterface));
+
+ /**
+ * Get the speed the device is operating at.
+ *
+ * @returns Device state.
+ * @param pInterface Pointer to the device interface structure.
+ */
+ DECLR3CALLBACKMEMBER(VUSBSPEED, pfnGetSpeed,(PVUSBIDEVICE pInterface));
+
+} VUSBIDEVICE;
+/** VUSBIDEVICE interface ID. */
+# define VUSBIDEVICE_IID "af576b38-e8ca-4db7-810a-2596d8d57ca0"
+
+
+# ifdef IN_RING3
+/**
+ * Resets the device.
+ *
+ * Since a device reset shall take at least 10ms from the guest point of view,
+ * it must be performed asynchronously. We create a thread which performs this
+ * operation and ensures it will take at least 10ms.
+ *
+ * At times - like init - a synchronous reset is required, this can be done
+ * by passing NULL for pfnDone.
+ *
+ * -- internal stuff, move it --
+ * While the device is being reset it is in the VUSB_DEVICE_STATE_RESET state.
+ * On completion it will be in the VUSB_DEVICE_STATE_DEFAULT state if successful,
+ * or in the VUSB_DEVICE_STATE_DETACHED state if the rest failed.
+ * -- internal stuff, move it --
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the device interface structure.
+ * @param fResetOnLinux Set if we can permit a real reset and a potential logical
+ * device reconnect on linux hosts.
+ * @param pfnDone Pointer to the completion routine. If NULL a
+ * synchronous reset is performed not respecting the
+ * 10ms.
+ * @param pvUser User argument to the completion routine.
+ * @param pVM The cross context VM structure. Required if pfnDone
+ * is not NULL.
+ *
+ * NULL is acceptable Required if callback in EMT is desired, NULL is otherwise
+ * acceptable.
+ */
+DECLINLINE(int) VUSBIDevReset(PVUSBIDEVICE pInterface, bool fResetOnLinux, PFNVUSBRESETDONE pfnDone, void *pvUser, PVM pVM)
+{
+ return pInterface->pfnReset(pInterface, fResetOnLinux, pfnDone, pvUser, pVM);
+}
+
+/**
+ * Powers on the device.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the device interface structure.
+ */
+DECLINLINE(int) VUSBIDevPowerOn(PVUSBIDEVICE pInterface)
+{
+ return pInterface->pfnPowerOn(pInterface);
+}
+
+/**
+ * Powers off the device.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the device interface structure.
+ */
+DECLINLINE(int) VUSBIDevPowerOff(PVUSBIDEVICE pInterface)
+{
+ return pInterface->pfnPowerOff(pInterface);
+}
+
+/**
+ * Get the state of the device.
+ *
+ * @returns Device state.
+ * @param pInterface Pointer to the device interface structure.
+ */
+DECLINLINE(VUSBDEVICESTATE) VUSBIDevGetState(PVUSBIDEVICE pInterface)
+{
+ return pInterface->pfnGetState(pInterface);
+}
+
+/**
+ * @copydoc VUSBIDEVICE::pfnIsSavedStateSupported
+ */
+DECLINLINE(bool) VUSBIDevIsSavedStateSupported(PVUSBIDEVICE pInterface)
+{
+ return pInterface->pfnIsSavedStateSupported(pInterface);
+}
+# endif /* IN_RING3 */
+
+#endif /* ! RDESKTOP */
+
+/** @name URB
+ * @{ */
+
+/**
+ * VUSB Transfer status codes.
+ */
+typedef enum VUSBSTATUS
+{
+ /** Transer was ok. */
+ VUSBSTATUS_OK = 0,
+ /** Transfer stalled, endpoint halted. */
+ VUSBSTATUS_STALL,
+ /** Device not responding. */
+ VUSBSTATUS_DNR,
+ /** CRC error. */
+ VUSBSTATUS_CRC,
+ /** Data underrun error. */
+ VUSBSTATUS_DATA_UNDERRUN,
+ /** Data overrun error. */
+ VUSBSTATUS_DATA_OVERRUN,
+ /** The isochronous buffer hasn't been touched. */
+ VUSBSTATUS_NOT_ACCESSED,
+ /** Canceled/undone URB (VUSB internal). */
+ VUSBSTATUS_UNDO,
+ /** Canceled URB. */
+ VUSBSTATUS_CANCELED,
+ /** Invalid status. */
+ VUSBSTATUS_INVALID = 0x7f
+} VUSBSTATUS;
+
+
+/**
+ * The URB states
+ */
+typedef enum VUSBURBSTATE
+{
+ /** The usual invalid state. */
+ VUSBURBSTATE_INVALID = 0,
+ /** The URB is free, i.e. not in use.
+ * Next state: ALLOCATED */
+ VUSBURBSTATE_FREE,
+ /** The URB is allocated, i.e. being prepared for submission.
+ * Next state: FREE, IN_FLIGHT */
+ VUSBURBSTATE_ALLOCATED,
+ /** The URB is in flight.
+ * Next state: REAPED, CANCELLED */
+ VUSBURBSTATE_IN_FLIGHT,
+ /** The URB has been reaped and is being completed.
+ * Next state: FREE */
+ VUSBURBSTATE_REAPED,
+ /** The URB has been cancelled and is awaiting reaping and immediate freeing.
+ * Next state: FREE */
+ VUSBURBSTATE_CANCELLED,
+ /** The end of the valid states (exclusive). */
+ VUSBURBSTATE_END,
+ /** The usual 32-bit blow up. */
+ VUSBURBSTATE_32BIT_HACK = 0x7fffffff
+} VUSBURBSTATE;
+
+
+/**
+ * Information about a isochronous packet.
+ */
+typedef struct VUSBURBISOCPKT
+{
+ /** The size of the packet.
+ * IN: The packet size. I.e. the number of bytes to the next packet or end of buffer.
+ * OUT: The actual size transferred. */
+ uint32_t cb;
+ /** The offset of the packet. (Relative to VUSBURB::abData[0].)
+ * OUT: This can be changed by the USB device if it does some kind of buffer squeezing. */
+ uint32_t off;
+ /** The status of the transfer.
+ * IN: VUSBSTATUS_INVALID
+ * OUT: VUSBSTATUS_INVALID if nothing was done, otherwise the correct status. */
+ VUSBSTATUS enmStatus;
+} VUSBURBISOCPKT;
+/** Pointer to a isochronous packet. */
+typedef VUSBURBISOCPKT *PVUSBURBISOCPTK;
+/** Pointer to a const isochronous packet. */
+typedef const VUSBURBISOCPKT *PCVUSBURBISOCPKT;
+
+/** Private controller emulation specific data for the associated USB request descriptor. */
+typedef struct VUSBURBHCIINT *PVUSBURBHCI;
+/** Private controller emulation specific TD data. */
+typedef struct VUSBURBHCITDINT *PVUSBURBHCITD;
+/** Private VUSB/roothub related state for the associated URB. */
+typedef struct VUSBURBVUSBINT *PVUSBURBVUSB;
+
+/**
+ * Asynchronous USB request descriptor
+ */
+typedef struct VUSBURB
+{
+ /** URB magic value. */
+ uint32_t u32Magic;
+ /** The USR state. */
+ VUSBURBSTATE enmState;
+ /** Flag whether the URB is about to be completed,
+ * either by the I/O thread or the cancellation worker.
+ */
+ volatile bool fCompleting;
+ /** URB description, can be null. intended for logging. */
+ char *pszDesc;
+
+#ifdef RDESKTOP
+ /** The next URB in rdesktop-vrdp's linked list */
+ PVUSBURB pNext;
+ /** The previous URB in rdesktop-vrdp's linked list */
+ PVUSBURB pPrev;
+ /** The vrdp handle for the URB */
+ uint32_t handle;
+ /** Pointer used to find the usb proxy device */
+ struct VUSBDEV *pDev;
+#endif
+
+ /** The VUSB stack private data. */
+ PVUSBURBVUSB pVUsb;
+ /** Private host controller data associated with this URB. */
+ PVUSBURBHCI pHci;
+ /** Pointer to the host controller transfer descriptor array. */
+ PVUSBURBHCITD paTds;
+
+ /** The device data. */
+ struct VUSBURBDEV
+ {
+ /** Pointer to private device specific data. */
+ void *pvPrivate;
+ /** Used by the device when linking the URB in some list of its own. */
+ PVUSBURB pNext;
+ } Dev;
+
+ /** The device address.
+ * This is set at allocation time. */
+ uint8_t DstAddress;
+
+ /** The endpoint.
+ * IN: Must be set before submitting the URB.
+ * @remark This does not have the high bit (direction) set! */
+ uint8_t EndPt;
+ /** The transfer type.
+ * IN: Set at allocation time. */
+ VUSBXFERTYPE enmType;
+ /** The transfer direction.
+ * IN: Set at allocation time. */
+ VUSBDIRECTION enmDir;
+ /** Indicates whether it is OK to receive/send less data than requested.
+ * IN: Must be initialized before submitting the URB. */
+ bool fShortNotOk;
+ /** The transfer status.
+ * OUT: This is set when reaping the URB. */
+ VUSBSTATUS enmStatus;
+
+ /** The relative starting frame for isochronous transfers.
+ * Zero indicates "transfer ASAP".
+ * This is ignored when enmType isn't VUSBXFERTYPE_ISOC. */
+ uint16_t uStartFrameDelta;
+ /** Flag indicating whether the start frame delta is relative
+ * to the previous transfer (false) or now (true).
+ * This is ignored when enmType isn't VUSBXFERTYPE_ISOC. */
+ bool fStartRelToNow;
+ /** The number of isochronous packets describe in aIsocPkts.
+ * This is ignored when enmType isn't VUSBXFERTYPE_ISOC. */
+ uint8_t cIsocPkts;
+ /** The iso packets within abData.
+ * This is ignored when enmType isn't VUSBXFERTYPE_ISOC. */
+ VUSBURBISOCPKT aIsocPkts[8];
+
+ /** The message length.
+ * IN: The amount of data to send / receive - set at allocation time.
+ * OUT: The amount of data sent / received. */
+ uint32_t cbData;
+ /** The message data.
+ * IN: On host to device transfers, the data to send.
+ * OUT: On device to host transfers, the data to received.
+ * This array has actually a size of VUsb.cbDataAllocated, not 8KB! */
+ uint8_t abData[8*_1K];
+} VUSBURB;
+
+/** The magic value of a valid VUSBURB. (Murakami Haruki) */
+#define VUSBURB_MAGIC UINT32_C(0x19490112)
+
+/** @} */
+
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !VBOX_INCLUDED_vusb_h */
diff --git a/include/VBox/xrandr-calls.h b/include/VBox/xrandr-calls.h
new file mode 100644
index 00000000..5ede4291
--- /dev/null
+++ b/include/VBox/xrandr-calls.h
@@ -0,0 +1,80 @@
+/** @file
+ * Stubs for dynamically loading libXrandr and the symbols which are needed by
+ * VirtualBox.
+ */
+
+/*
+ * Copyright (C) 2008-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+/** The file name of the libXrandr library. */
+#define RT_RUNTIME_LOADER_LIB_NAME "libXrandr.so.2"
+
+/** The name of the loader function. */
+#define RT_RUNTIME_LOADER_FUNCTION RTXrandrLoadLib
+
+/** The following are the symbols which we need from the Xrandr library. */
+#define RT_RUNTIME_LOADER_INSERT_SYMBOLS \
+ RT_PROXY_STUB(XRRQueryExtension, Bool, (Display *dpy, int *event_base_return, int *error_base_return), \
+ (dpy, event_base_return, error_base_return)) \
+ RT_PROXY_STUB(XRRQueryVersion, Bool, (Display *dpy, int *major_version_return, int *minor_version_return), \
+ (dpy, major_version_return, minor_version_return)) \
+ RT_PROXY_STUB(XRRSelectInput, void, (Display *dpy, Window window, int mask), \
+ (dpy, window, mask)) \
+ RT_PROXY_STUB(XRRGetMonitors, XRRMonitorInfo *, (Display *dpy, Window window, Bool get_active, int *nmonitors), \
+ (dpy, window, get_active, nmonitors)) \
+ RT_PROXY_STUB(XRRFreeMonitors, void, (XRRMonitorInfo *monitors), \
+ (monitors)) \
+ RT_PROXY_STUB(XRRGetScreenResources, XRRScreenResources *, (Display *dpy, Window window), \
+ (dpy, window)) \
+ RT_PROXY_STUB(XRRFreeScreenResources, void, (XRRScreenResources *resources), \
+ (resources)) \
+ RT_PROXY_STUB(XRRSetOutputPrimary, void, (Display *dpy, Window window, RROutput output), \
+ (dpy, window, output))
+
+#ifdef VBOX_XRANDR_GENERATE_HEADER
+# define RT_RUNTIME_LOADER_GENERATE_HEADER
+# define RT_RUNTIME_LOADER_GENERATE_DECLS
+# include <iprt/runtime-loader.h>
+# undef RT_RUNTIME_LOADER_GENERATE_HEADER
+# undef RT_RUNTIME_LOADER_GENERATE_DECLS
+
+#elif defined(VBOX_XRANDR_GENERATE_BODY)
+# define RT_RUNTIME_LOADER_GENERATE_BODY_STUBS
+# include <iprt/runtime-loader.h>
+# undef RT_RUNTIME_LOADER_GENERATE_BODY_STUBS
+
+#else
+# error This file should only be included to generate stubs for loading the Xrandr library at runtime
+#endif
+
+#undef RT_RUNTIME_LOADER_LIB_NAME
+#undef RT_RUNTIME_LOADER_INSERT_SYMBOLS
+
diff --git a/include/VBox/xrandr.h b/include/VBox/xrandr.h
new file mode 100644
index 00000000..79adff4a
--- /dev/null
+++ b/include/VBox/xrandr.h
@@ -0,0 +1,125 @@
+/** @file
+ * Module to dynamically load libXrandr and load all symbols which are needed by
+ * VirtualBox.
+ */
+
+/*
+ * Copyright (C) 2008-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_xrandr_h
+#define VBOX_INCLUDED_xrandr_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+#include <iprt/stdarg.h>
+
+#ifndef __cplusplus
+# error "This header requires C++ to avoid name clashes."
+#endif
+
+/* Define missing X11/XRandr structures, types and macros. */
+
+#define Bool int
+#define RRScreenChangeNotifyMask (1L << 0)
+#define RRScreenChangeNotify 0
+
+struct _XDisplay;
+typedef struct _XDisplay Display;
+
+typedef unsigned long Atom;
+typedef unsigned long XID;
+typedef XID RROutput;
+typedef XID Window;
+typedef XID RROutput;
+typedef XID RRCrtc;
+typedef XID RRMode;
+typedef unsigned long XRRModeFlags;
+typedef unsigned long int Time;
+
+struct XRRMonitorInfo
+{
+ Atom name;
+ Bool primary;
+ Bool automatic;
+ int noutput;
+ int x;
+ int y;
+ int width;
+ int height;
+ int mwidth;
+ int mheight;
+ RROutput *outputs;
+};
+typedef struct XRRMonitorInfo XRRMonitorInfo;
+
+struct XRRModeInfo
+{
+ RRMode id;
+ unsigned int width;
+ unsigned int height;
+ unsigned long dotClock;
+ unsigned int hSyncStart;
+ unsigned int hSyncEnd;
+ unsigned int hTotal;
+ unsigned int hSkew;
+ unsigned int vSyncStart;
+ unsigned int vSyncEnd;
+ unsigned int vTotal;
+ char *name;
+ unsigned int nameLength;
+ XRRModeFlags modeFlags;
+};
+typedef struct XRRModeInfo XRRModeInfo;
+
+struct XRRScreenResources
+{
+ Time timestamp;
+ Time configTimestamp;
+ int ncrtc;
+ RRCrtc *crtcs;
+ int noutput;
+ RROutput *outputs;
+ int nmode;
+ XRRModeInfo *modes;
+};
+typedef struct XRRScreenResources XRRScreenResources;
+
+/* Declarations of the functions that we need from libXrandr. */
+#define VBOX_XRANDR_GENERATE_HEADER
+
+#include <VBox/xrandr-calls.h>
+
+#undef VBOX_XRANDR_GENERATE_HEADER
+
+#endif /* !VBOX_INCLUDED_xrandr_h */
+
diff --git a/include/iprt/Makefile.kup b/include/iprt/Makefile.kup
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/include/iprt/Makefile.kup
diff --git a/include/iprt/alloc.h b/include/iprt/alloc.h
new file mode 100644
index 00000000..a0d6561d
--- /dev/null
+++ b/include/iprt/alloc.h
@@ -0,0 +1,46 @@
+/** @file
+ * IPRT - Memory Allocation.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_alloc_h
+#define IPRT_INCLUDED_alloc_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+/* Forwarding to the canonical header. */
+#include <iprt/mem.h>
+
+#endif /* !IPRT_INCLUDED_alloc_h */
+
diff --git a/include/iprt/alloca.h b/include/iprt/alloca.h
new file mode 100644
index 00000000..1866d975
--- /dev/null
+++ b/include/iprt/alloca.h
@@ -0,0 +1,110 @@
+/** @file
+ * IPRT - alloca().
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_alloca_h
+#define IPRT_INCLUDED_alloca_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#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)
+
+#elif defined(IPRT_NO_CRT) && defined(RT_OS_WINDOWS)
+# include <iprt/types.h>
+
+RT_C_DECLS_BEGIN
+# ifdef RT_ARCH_X86
+void * __cdecl _alloca(size_t);
+# else
+void *_alloca(size_t);
+# endif
+# define alloca _alloca
+RT_C_DECLS_END
+
+#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
+
+# if defined(RT_OS_SOLARIS) && (defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)) \
+ && defined(_SYS_REGSET_H) && !defined(IPRT_NO_SOLARIS_UCONTEXT_CLEANUPS)
+/* Solaris' sys/regset.h pollutes the namespace with register constants that
+ frequently conflicts with structure members and variable/parameter names. */
+# undef CS
+# undef DS
+# undef EAX
+# undef EBP
+# undef EBX
+# undef ECX
+# undef EDI
+# undef EDX
+# undef EFL
+# undef EIP
+# undef ERR
+# undef ES
+# undef ESI
+# undef ESP
+# undef FS
+# undef GS
+# undef SS
+# undef TRAPNO
+# undef UESP
+# endif
+#endif
+
+#endif /* !IPRT_INCLUDED_alloca_h */
+
diff --git a/include/iprt/asm-amd64-x86-watcom-16.h b/include/iprt/asm-amd64-x86-watcom-16.h
new file mode 100644
index 00000000..a3fd3ebd
--- /dev/null
+++ b/include/iprt/asm-amd64-x86-watcom-16.h
@@ -0,0 +1,831 @@
+/** @file
+ * IPRT - AMD64 and x86 Specific Assembly Functions, 16-bit Watcom C pragma aux.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_asm_amd64_x86_watcom_16_h
+#define IPRT_INCLUDED_asm_amd64_x86_watcom_16_h
+/* no pragma once */
+
+#ifndef IPRT_INCLUDED_asm_amd64_x86_h
+# error "Don't include this header directly."
+#endif
+
+/*
+ * Turns out we cannot use 'ds' for segment stuff here because the compiler
+ * seems to insists on loading the DGROUP segment into 'ds' before calling
+ * stuff when using -ecc. Using 'es' instead as this seems to work fine.
+ *
+ * Note! The #undef that preceds the #pragma aux statements is for undoing
+ * the mangling, because the symbol in #pragma aux [symbol] statements
+ * doesn't get subjected to preprocessing. This is also why we include
+ * the watcom header at both the top and the bottom of asm-amd64-x86.h file.
+ */
+
+#undef ASMGetIDTR
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_16_INSTANTIATE
+#pragma aux ASMGetIDTR = \
+ ".286p" \
+ "sidt fword ptr es:[bx]" \
+ parm [es bx] \
+ modify exact [];
+#endif
+
+#undef ASMGetIdtrLimit
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_16_INSTANTIATE
+#pragma aux ASMGetIdtrLimit = \
+ ".286p" \
+ "sub sp, 8" \
+ "mov bx, sp" \
+ "sidt fword ptr ss:[bx]" \
+ "mov bx, ss:[bx]" \
+ "add sp, 8" \
+ parm [] \
+ value [bx] \
+ modify exact [bx];
+#endif
+
+#undef ASMSetIDTR
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_16_INSTANTIATE
+#pragma aux ASMSetIDTR = \
+ ".286p" \
+ "lidt fword ptr es:[bx]" \
+ parm [es bx] nomemory \
+ modify nomemory;
+#endif
+
+#undef ASMGetGDTR
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_16_INSTANTIATE
+#pragma aux ASMGetGDTR = \
+ ".286p" \
+ "sgdt fword ptr es:[bx]" \
+ parm [es bx] \
+ modify exact [];
+#endif
+
+#undef ASMSetGDTR
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_16_INSTANTIATE
+#pragma aux ASMSetGDTR = \
+ ".286p" \
+ "lgdt fword ptr es:[bx]" \
+ parm [es bx] nomemory \
+ modify exact [] nomemory;
+#endif
+
+#undef ASMGetCS
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_16_INSTANTIATE
+#pragma aux ASMGetCS = \
+ "mov ax, cs" \
+ parm [] nomemory \
+ value [ax] \
+ modify exact [ax] nomemory;
+#endif
+
+#undef ASMGetDS
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_16_INSTANTIATE
+#pragma aux ASMGetDS = \
+ "mov ax, ds" \
+ parm [] nomemory \
+ value [ax] \
+ modify exact [ax] nomemory;
+#endif
+
+#undef ASMGetES
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_16_INSTANTIATE
+#pragma aux ASMGetES = \
+ "mov ax, es" \
+ parm [] nomemory \
+ value [ax] \
+ modify exact [ax] nomemory;
+#endif
+
+#undef ASMGetFS
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_16_INSTANTIATE
+#pragma aux ASMGetFS = \
+ ".386" \
+ "mov ax, fs" \
+ parm [] nomemory \
+ value [ax] \
+ modify exact [ax] nomemory;
+#endif
+
+#undef ASMGetGS
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_16_INSTANTIATE
+#pragma aux ASMGetGS = \
+ ".386" \
+ "mov ax, gs" \
+ parm [] nomemory \
+ value [ax] \
+ modify exact [ax] nomemory;
+#endif
+
+#undef ASMGetSS
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_16_INSTANTIATE
+#pragma aux ASMGetSS = \
+ "mov ax, ss" \
+ parm [] nomemory \
+ value [ax] \
+ modify exact [ax] nomemory;
+#endif
+
+#undef ASMGetTR
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_16_INSTANTIATE
+#pragma aux ASMGetTR = \
+ ".286" \
+ "str ax" \
+ parm [] nomemory \
+ value [ax] \
+ modify exact [ax] nomemory;
+#endif
+
+#undef ASMGetLDTR
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_16_INSTANTIATE
+#pragma aux ASMGetLDTR = \
+ ".286" \
+ "sldt ax" \
+ parm [] nomemory \
+ value [ax] \
+ modify exact [ax] nomemory;
+#endif
+
+/** @todo ASMGetSegAttr */
+
+#undef ASMGetFlags
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_16_INSTANTIATE
+#pragma aux ASMGetFlags = \
+ "pushf" \
+ "pop ax" \
+ parm [] nomemory \
+ value [ax] \
+ modify exact [ax] nomemory;
+#endif
+
+#undef ASMSetFlags
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_16_INSTANTIATE
+#pragma aux ASMSetFlags = \
+ "push ax" \
+ "popf" \
+ parm [ax] nomemory \
+ modify exact [] nomemory;
+#endif
+
+#undef ASMChangeFlags
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_16_INSTANTIATE
+#pragma aux ASMChangeFlags = \
+ "pushf" \
+ "pop ax" \
+ "and dx, ax" \
+ "or dx, cx" \
+ "push dx" \
+ "popf" \
+ parm [dx] [cx] nomemory \
+ value [ax] \
+ modify exact [dx] nomemory;
+#endif
+
+#undef ASMAddFlags
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_16_INSTANTIATE
+#pragma aux ASMAddFlags = \
+ "pushf" \
+ "pop ax" \
+ "or dx, ax" \
+ "push dx" \
+ "popf" \
+ parm [dx] nomemory \
+ value [ax] \
+ modify exact [dx] nomemory;
+#endif
+
+#undef ASMClearFlags
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_16_INSTANTIATE
+#pragma aux ASMClearFlags = \
+ "pushf" \
+ "pop ax" \
+ "and dx, ax" \
+ "push dx" \
+ "popf" \
+ parm [dx] nomemory \
+ value [ax] \
+ modify exact [dx] nomemory;
+#endif
+
+/* Note! Must use the 64-bit integer return value convension.
+ The order of registers in the value [set] does not seem to mean anything. */
+#undef ASMReadTSC
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_16_INSTANTIATE
+#pragma aux ASMReadTSC = \
+ ".586" \
+ "rdtsc" \
+ "mov ebx, edx" \
+ "mov ecx, eax" \
+ "shr ecx, 16" \
+ "xchg eax, edx" \
+ "shr eax, 16" \
+ parm [] nomemory \
+ value [dx cx bx ax] \
+ modify exact [ax bx cx dx] nomemory;
+#endif
+
+/** @todo ASMReadTscWithAux if needed (rdtscp not recognized by compiler) */
+
+
+/* ASMCpuId: Implemented externally, too many parameters. */
+/* ASMCpuId_Idx_ECX: Implemented externally, too many parameters. */
+/* ASMCpuIdExSlow: Always implemented externally. */
+/* ASMCpuId_ECX_EDX: Implemented externally, too many parameters. */
+
+#undef ASMCpuId_EAX
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_16_INSTANTIATE
+#pragma aux ASMCpuId_EAX = \
+ ".586" \
+ "xchg ax, dx" \
+ "shl eax, 16" \
+ "mov ax, dx" \
+ "cpuid" \
+ "mov edx, eax" \
+ "shr edx, 16" \
+ parm [ax dx] \
+ value [ax dx] \
+ modify exact [ax bx cx dx];
+#endif
+
+#undef ASMCpuId_EBX
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_16_INSTANTIATE
+#pragma aux ASMCpuId_EBX = \
+ ".586" \
+ "xchg ax, dx" \
+ "shl eax, 16" \
+ "mov ax, dx" \
+ "cpuid" \
+ "mov ax, bx" \
+ "shr ebx, 16" \
+ parm [ax dx] \
+ value [ax bx] \
+ modify exact [ax bx cx dx];
+#endif
+
+#undef ASMCpuId_ECX
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_16_INSTANTIATE
+#pragma aux ASMCpuId_ECX = \
+ ".586" \
+ "xchg ax, dx" \
+ "shl eax, 16" \
+ "mov ax, dx" \
+ "cpuid" \
+ "mov ax, cx" \
+ "shr ecx, 16" \
+ parm [ax dx] \
+ value [ax cx] \
+ modify exact [ax bx cx dx];
+#endif
+
+#undef ASMCpuId_EDX
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_16_INSTANTIATE
+#pragma aux ASMCpuId_EDX = \
+ ".586" \
+ "xchg ax, dx" \
+ "shl eax, 16" \
+ "mov ax, dx" \
+ "cpuid" \
+ "mov ax, dx" \
+ "shr edx, 16" \
+ parm [ax dx] \
+ value [ax dx] \
+ modify exact [ax bx cx dx];
+#endif
+
+/* ASMHasCpuId: MSC inline in main source file. */
+/* ASMGetApicId: Implemented externally, lazy bird. */
+
+/* Note! Again, when returning two registers, watcom have certain fixed ordering rules (low:high):
+ ax:bx, ax:cx, ax:dx, ax:si, ax:di
+ bx:cx, bx:dx, bx:si, bx:di
+ dx:cx, si:cx, di:cx
+ si:dx, di:dx
+ si:di
+ This ordering seems to apply to parameter values too. */
+#undef ASMGetCR0
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_16_INSTANTIATE
+#pragma aux ASMGetCR0 = \
+ ".386" \
+ "mov eax, cr0" \
+ "mov edx, eax" \
+ "shr edx, 16" \
+ parm [] nomemory \
+ value [ax dx] \
+ modify exact [ax dx] nomemory;
+#endif
+
+#undef ASMSetCR0
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_16_INSTANTIATE
+#pragma aux ASMSetCR0 = \
+ ".386" \
+ "shl edx, 16" \
+ "mov dx, ax" \
+ "mov cr0, edx" \
+ parm [ax dx] nomemory \
+ modify exact [dx] nomemory;
+#endif
+
+#undef ASMGetCR2
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_16_INSTANTIATE
+#pragma aux ASMGetCR2 = \
+ ".386" \
+ "mov eax, cr2" \
+ "mov edx, eax" \
+ "shr edx, 16" \
+ parm [] nomemory \
+ value [ax dx] \
+ modify exact [ax dx] nomemory;
+#endif
+
+#undef ASMSetCR2
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_16_INSTANTIATE
+#pragma aux ASMSetCR2 = \
+ ".386" \
+ "shl edx, 16" \
+ "mov dx, ax" \
+ "mov cr2, edx" \
+ parm [ax dx] nomemory \
+ modify exact [dx] nomemory;
+#endif
+
+#undef ASMGetCR3
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_16_INSTANTIATE
+#pragma aux ASMGetCR3 = \
+ ".386" \
+ "mov eax, cr3" \
+ "mov edx, eax" \
+ "shr edx, 16" \
+ parm [] nomemory \
+ value [ax dx] \
+ modify exact [ax dx] nomemory;
+#endif
+
+#undef ASMSetCR3
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_16_INSTANTIATE
+#pragma aux ASMSetCR3 = \
+ ".386" \
+ "shl edx, 16" \
+ "mov dx, ax" \
+ "mov cr3, edx" \
+ parm [ax dx] nomemory \
+ modify exact [dx] nomemory;
+#endif
+
+#undef ASMReloadCR3
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_16_INSTANTIATE
+#pragma aux ASMReloadCR3 = \
+ ".386" \
+ "mov eax, cr3" \
+ "mov cr3, eax" \
+ parm [] nomemory \
+ modify exact [ax] nomemory;
+#endif
+
+#undef ASMGetCR4
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_16_INSTANTIATE
+#pragma aux ASMGetCR4 = \
+ ".386" \
+ "mov eax, cr4" \
+ "mov edx, eax" \
+ "shr edx, 16" \
+ parm [] nomemory \
+ value [ax dx] \
+ modify exact [ax dx] nomemory;
+#endif
+
+#undef ASMSetCR4
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_16_INSTANTIATE
+#pragma aux ASMSetCR4 = \
+ ".386" \
+ "shl edx, 16" \
+ "mov dx, ax" \
+ "mov cr4, edx" \
+ parm [ax dx] nomemory \
+ modify exact [dx] nomemory;
+#endif
+
+/* ASMGetCR8: Don't bother for 16-bit. */
+/* ASMSetCR8: Don't bother for 16-bit. */
+
+#undef ASMIntEnable
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_16_INSTANTIATE
+#pragma aux ASMIntEnable = \
+ "sti" \
+ parm [] nomemory \
+ modify exact [] nomemory;
+#endif
+
+#undef ASMIntDisable
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_16_INSTANTIATE
+#pragma aux ASMIntDisable = \
+ "cli" \
+ parm [] nomemory \
+ modify exact [] nomemory;
+#endif
+
+#undef ASMIntDisableFlags
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_16_INSTANTIATE
+#pragma aux ASMIntDisableFlags = \
+ "pushf" \
+ "cli" \
+ "pop ax" \
+ parm [] nomemory \
+ value [ax] \
+ modify exact [] nomemory;
+#endif
+
+#undef ASMHalt
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_16_INSTANTIATE
+#pragma aux ASMHalt = \
+ "hlt" \
+ parm [] nomemory \
+ modify exact [] nomemory;
+#endif
+
+#undef ASMRdMsr
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_16_INSTANTIATE
+#pragma aux ASMRdMsr = \
+ ".586" \
+ "shl ecx, 16" \
+ "mov cx, ax" \
+ "rdmsr" \
+ "mov ebx, edx" \
+ "mov ecx, eax" \
+ "shr ecx, 16" \
+ "xchg eax, edx" \
+ "shr eax, 16" \
+ parm [ax cx] nomemory \
+ value [dx cx bx ax] \
+ modify exact [ax bx cx dx] nomemory;
+#endif
+
+/* ASMWrMsr: Implemented externally, lazy bird. */
+/* ASMRdMsrEx: Implemented externally, lazy bird. */
+/* ASMWrMsrEx: Implemented externally, lazy bird. */
+
+#undef ASMRdMsr_Low
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_16_INSTANTIATE
+#pragma aux ASMRdMsr_Low = \
+ ".586" \
+ "shl ecx, 16" \
+ "mov cx, ax" \
+ "rdmsr" \
+ "mov edx, eax" \
+ "shr edx, 16" \
+ parm [ax cx] nomemory \
+ value [ax dx] \
+ modify exact [ax bx cx dx] nomemory;
+#endif
+
+#undef ASMRdMsr_High
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_16_INSTANTIATE
+#pragma aux ASMRdMsr_High = \
+ ".586" \
+ "shl ecx, 16" \
+ "mov cx, ax" \
+ "rdmsr" \
+ "mov eax, edx" \
+ "shr edx, 16" \
+ parm [ax cx] nomemory \
+ value [ax dx] \
+ modify exact [ax bx cx dx] nomemory;
+#endif
+
+
+#undef ASMGetDR0
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_16_INSTANTIATE
+#pragma aux ASMGetDR0 = \
+ ".386" \
+ "mov eax, dr0" \
+ "mov edx, eax" \
+ "shr edx, 16" \
+ parm [] nomemory \
+ value [ax dx] \
+ modify exact [ax dx] nomemory;
+#endif
+
+#undef ASMGetDR1
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_16_INSTANTIATE
+#pragma aux ASMGetDR1 = \
+ ".386" \
+ "mov eax, dr1" \
+ "mov edx, eax" \
+ "shr edx, 16" \
+ parm [] nomemory \
+ value [ax dx] \
+ modify exact [ax dx] nomemory;
+#endif
+
+#undef ASMGetDR2
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_16_INSTANTIATE
+#pragma aux ASMGetDR2 = \
+ ".386" \
+ "mov eax, dr2" \
+ "mov edx, eax" \
+ "shr edx, 16" \
+ parm [] nomemory \
+ value [ax dx] \
+ modify exact [ax dx] nomemory;
+#endif
+
+#undef ASMGetDR3
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_16_INSTANTIATE
+#pragma aux ASMGetDR3 = \
+ ".386" \
+ "mov eax, dr3" \
+ "mov edx, eax" \
+ "shr edx, 16" \
+ parm [] nomemory \
+ value [ax dx] \
+ modify exact [ax dx] nomemory;
+#endif
+
+#undef ASMGetDR6
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_16_INSTANTIATE
+#pragma aux ASMGetDR6 = \
+ ".386" \
+ "mov eax, dr6" \
+ "mov edx, eax" \
+ "shr edx, 16" \
+ parm [] nomemory \
+ value [ax dx] \
+ modify exact [ax dx] nomemory;
+#endif
+
+#undef ASMGetAndClearDR6
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_16_INSTANTIATE
+#pragma aux ASMGetAndClearDR6 = \
+ ".386" \
+ "mov edx, 0ffff0ff0h" \
+ "mov eax, dr6" \
+ "mov dr6, edx" \
+ "mov edx, eax" \
+ "shr edx, 16" \
+ parm [] nomemory \
+ value [ax dx] \
+ modify exact [ax dx] nomemory;
+#endif
+
+#undef ASMGetDR7
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_16_INSTANTIATE
+#pragma aux ASMGetDR7 = \
+ ".386" \
+ "mov eax, dr7" \
+ "mov edx, eax" \
+ "shr edx, 16" \
+ parm [] nomemory \
+ value [ax dx] \
+ modify exact [ax dx] nomemory;
+#endif
+
+#undef ASMSetDR0
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_16_INSTANTIATE
+#pragma aux ASMSetDR0 = \
+ ".386" \
+ "shl edx, 16" \
+ "mov dx, ax" \
+ "mov dr0, edx" \
+ parm [ax dx] nomemory \
+ modify exact [dx] nomemory;
+#endif
+
+#undef ASMSetDR1
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_16_INSTANTIATE
+#pragma aux ASMSetDR1 = \
+ ".386" \
+ "shl edx, 16" \
+ "mov dx, ax" \
+ "mov dr1, edx" \
+ parm [ax dx] nomemory \
+ modify exact [dx] nomemory;
+#endif
+
+#undef ASMSetDR2
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_16_INSTANTIATE
+#pragma aux ASMSetDR2 = \
+ ".386" \
+ "shl edx, 16" \
+ "mov dx, ax" \
+ "mov dr2, edx" \
+ parm [ax dx] nomemory \
+ modify exact [dx] nomemory;
+#endif
+
+#undef ASMSetDR3
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_16_INSTANTIATE
+#pragma aux ASMSetDR3 = \
+ ".386" \
+ "shl edx, 16" \
+ "mov dx, ax" \
+ "mov dr3, edx" \
+ parm [ax dx] nomemory \
+ modify exact [dx] nomemory;
+#endif
+
+#undef ASMSetDR6
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_16_INSTANTIATE
+#pragma aux ASMSetDR6 = \
+ ".386" \
+ "shl edx, 16" \
+ "mov dx, ax" \
+ "mov dr6, edx" \
+ parm [ax dx] nomemory \
+ modify exact [dx] nomemory;
+#endif
+
+#undef ASMSetDR7
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_16_INSTANTIATE
+#pragma aux ASMSetDR7 = \
+ ".386" \
+ "shl edx, 16" \
+ "mov dx, ax" \
+ "mov dr7, edx" \
+ parm [ax dx] nomemory \
+ modify exact [dx] nomemory;
+#endif
+
+/* Yeah, could've used outp here, but this keeps the main file simpler. */
+#undef ASMOutU8
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_16_INSTANTIATE
+#pragma aux ASMOutU8 = \
+ "out dx, al" \
+ parm [dx] [al] nomemory \
+ modify exact [] nomemory;
+#endif
+
+#undef ASMInU8
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_16_INSTANTIATE
+#pragma aux ASMInU8 = \
+ "in al, dx" \
+ parm [dx] nomemory \
+ value [al] \
+ modify exact [] nomemory;
+#endif
+
+#undef ASMOutU16
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_16_INSTANTIATE
+#pragma aux ASMOutU16 = \
+ "out dx, ax" \
+ parm [dx] [ax] nomemory \
+ modify exact [] nomemory;
+#endif
+
+#undef ASMInU16
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_16_INSTANTIATE
+#pragma aux ASMInU16 = \
+ "in ax, dx" \
+ parm [dx] nomemory \
+ value [ax] \
+ modify exact [] nomemory;
+#endif
+
+#undef ASMOutU32
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_16_INSTANTIATE
+#pragma aux ASMOutU32 = \
+ ".386" \
+ "shl ecx, 16" \
+ "mov cx, ax" \
+ "mov eax, ecx" \
+ "out dx, eax" \
+ parm [dx] [ax cx] nomemory \
+ modify exact [] nomemory;
+#endif
+
+#undef ASMInU32
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_16_INSTANTIATE
+#pragma aux ASMInU32 = \
+ ".386" \
+ "in eax, dx" \
+ "mov ecx, eax" \
+ "shr ecx, 16" \
+ parm [dx] nomemory \
+ value [ax cx] \
+ modify exact [] nomemory;
+#endif
+
+#undef ASMOutStrU8
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_16_INSTANTIATE
+#pragma aux ASMOutStrU8 = \
+ ".186" \
+ "mov ax, ds" \
+ "mov ds, di" \
+ "rep outsb" \
+ "mov ds, ax" \
+ parm [dx] [si di] [cx] nomemory \
+ modify exact [si cx ax] nomemory;
+#endif
+
+#undef ASMInStrU8
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_16_INSTANTIATE
+#pragma aux ASMInStrU8 = \
+ ".186" \
+ "rep insb" \
+ parm [dx] [di es] [cx] \
+ modify exact [di cx];
+#endif
+
+#undef ASMOutStrU16
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_16_INSTANTIATE
+#pragma aux ASMOutStrU16 = \
+ ".186" \
+ "mov ax, ds" \
+ "mov ds, di" \
+ "rep outsw" \
+ "mov ds, ax" \
+ parm [dx] [si di] [cx] nomemory \
+ modify exact [si cx ax] nomemory;
+#endif
+
+#undef ASMInStrU16
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_16_INSTANTIATE
+#pragma aux ASMInStrU16 = \
+ ".186" \
+ "rep insw" \
+ parm [dx] [di es] [cx] \
+ modify exact [di cx];
+#endif
+
+#undef ASMOutStrU32
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_16_INSTANTIATE
+#pragma aux ASMOutStrU32 = \
+ ".386" \
+ "mov ax, ds" \
+ "mov ds, di" \
+ "rep outsd" \
+ "mov ds, ax" \
+ parm [dx] [si di] [cx] nomemory \
+ modify exact [si cx ax] nomemory;
+#endif
+
+#undef ASMInStrU32
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_16_INSTANTIATE
+#pragma aux ASMInStrU32 = \
+ ".386" \
+ "rep insd" \
+ parm [dx] [es di] [cx] \
+ modify exact [di cx];
+#endif
+
+#undef ASMInvalidatePage
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_16_INSTANTIATE
+#pragma aux ASMInvalidatePage = \
+ ".486" \
+ "shl edx, 16" \
+ "mov dx, ax" \
+ "invlpg [edx]" \
+ parm [ax dx] \
+ modify exact [dx];
+#endif
+
+#undef ASMWriteBackAndInvalidateCaches
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_16_INSTANTIATE
+#pragma aux ASMWriteBackAndInvalidateCaches = \
+ ".486" \
+ "wbinvd" \
+ parm [] nomemory \
+ modify exact [] nomemory;
+#endif
+
+#undef ASMInvalidateInternalCaches
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_16_INSTANTIATE
+#pragma aux ASMInvalidateInternalCaches = \
+ ".486" \
+ "invd" \
+ parm [] \
+ modify exact [];
+#endif
+
+#endif /* !IPRT_INCLUDED_asm_amd64_x86_watcom_16_h */
+
diff --git a/include/iprt/asm-amd64-x86-watcom-32.h b/include/iprt/asm-amd64-x86-watcom-32.h
new file mode 100644
index 00000000..4486bb5b
--- /dev/null
+++ b/include/iprt/asm-amd64-x86-watcom-32.h
@@ -0,0 +1,737 @@
+/** @file
+ * IPRT - AMD64 and x86 Specific Assembly Functions, 32-bit Watcom C pragma aux.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_asm_amd64_x86_watcom_32_h
+#define IPRT_INCLUDED_asm_amd64_x86_watcom_32_h
+/* no pragma once */
+
+#ifndef IPRT_INCLUDED_asm_amd64_x86_h
+# error "Don't include this header directly."
+#endif
+
+#ifndef __FLAT__
+# error "Only works with flat pointers! (-mf)"
+#endif
+
+/*
+ * Note! The #undef that preceds the #pragma aux statements is for undoing
+ * the mangling, because the symbol in #pragma aux [symbol] statements
+ * doesn't get subjected to preprocessing. This is also why we include
+ * the watcom header at both the top and the bottom of asm-amd64-x86.h file.
+ */
+
+#undef ASMGetIDTR
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+#pragma aux ASMGetIDTR = \
+ "sidt fword ptr [ecx]" \
+ parm [ecx] \
+ modify exact [];
+#endif
+
+#undef ASMGetIdtrLimit
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+#pragma aux ASMGetIdtrLimit = \
+ "sub esp, 8" \
+ "sidt fword ptr [esp]" \
+ "mov cx, [esp]" \
+ "add esp, 8" \
+ parm [] \
+ value [cx] \
+ modify exact [ecx];
+#endif
+
+#undef ASMSetIDTR
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+#pragma aux ASMSetIDTR = \
+ "lidt fword ptr [ecx]" \
+ parm [ecx] nomemory \
+ modify nomemory;
+#endif
+
+#undef ASMGetGDTR
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+#pragma aux ASMGetGDTR = \
+ "sgdt fword ptr [ecx]" \
+ parm [ecx] \
+ modify exact [];
+#endif
+
+#undef ASMSetGDTR
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+#pragma aux ASMSetGDTR = \
+ "lgdt fword ptr [ecx]" \
+ parm [ecx] nomemory \
+ modify exact [] nomemory;
+#endif
+
+#undef ASMGetCS
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+#pragma aux ASMGetCS = \
+ "mov ax, cs" \
+ parm [] nomemory \
+ value [ax] \
+ modify exact [eax] nomemory;
+#endif
+
+#undef ASMGetDS
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+#pragma aux ASMGetDS = \
+ "mov ax, ds" \
+ parm [] nomemory \
+ value [ax] \
+ modify exact [eax] nomemory;
+#endif
+
+#undef ASMGetES
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+#pragma aux ASMGetES = \
+ "mov ax, es" \
+ parm [] nomemory \
+ value [ax] \
+ modify exact [eax] nomemory;
+#endif
+
+#undef ASMGetFS
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+#pragma aux ASMGetFS = \
+ "mov ax, fs" \
+ parm [] nomemory \
+ value [ax] \
+ modify exact [eax] nomemory;
+#endif
+
+#undef ASMGetGS
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+#pragma aux ASMGetGS = \
+ "mov ax, gs" \
+ parm [] nomemory \
+ value [ax] \
+ modify exact [eax] nomemory;
+#endif
+
+#undef ASMGetSS
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+#pragma aux ASMGetSS = \
+ "mov ax, ss" \
+ parm [] nomemory \
+ value [ax] \
+ modify exact [eax] nomemory;
+#endif
+
+#undef ASMGetTR
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+#pragma aux ASMGetTR = \
+ "str ax" \
+ parm [] nomemory \
+ value [ax] \
+ modify exact [eax] nomemory;
+#endif
+
+#undef ASMGetLDTR
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+#pragma aux ASMGetLDTR = \
+ "sldt ax" \
+ parm [] nomemory \
+ value [ax] \
+ modify exact [eax] nomemory;
+#endif
+
+/** @todo ASMGetSegAttr */
+
+#undef ASMGetFlags
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+#pragma aux ASMGetFlags = \
+ "pushfd" \
+ "pop eax" \
+ parm [] nomemory \
+ value [eax] \
+ modify exact [eax] nomemory;
+#endif
+
+#undef ASMSetFlags
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+#pragma aux ASMSetFlags = \
+ "push eax" \
+ "popfd" \
+ parm [eax] nomemory \
+ modify exact [] nomemory;
+#endif
+
+#undef ASMChangeFlags
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+#pragma aux ASMChangeFlags = \
+ "pushfd" \
+ "pop eax" \
+ "and edx, eax" \
+ "or edx, ecx" \
+ "push edx" \
+ "popfd" \
+ parm [edx] [ecx] nomemory \
+ value [eax] \
+ modify exact [edx] nomemory;
+#endif
+
+#undef ASMAddFlags
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+#pragma aux ASMAddFlags = \
+ "pushfd" \
+ "pop eax" \
+ "or edx, eax" \
+ "push edx" \
+ "popfd" \
+ parm [edx] nomemory \
+ value [eax] \
+ modify exact [edx] nomemory;
+#endif
+
+#undef ASMClearFlags
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+#pragma aux ASMClearFlags = \
+ "pushfd" \
+ "pop eax" \
+ "and edx, eax" \
+ "push edx" \
+ "popfd" \
+ parm [edx] nomemory \
+ value [eax] \
+ modify exact [edx] nomemory;
+#endif
+
+/* Note! Must use the 64-bit integer return value convension.
+ The order of registers in the value [set] does not seem to mean anything. */
+#undef ASMReadTSC
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+#pragma aux ASMReadTSC = \
+ ".586" \
+ "rdtsc" \
+ parm [] nomemory \
+ value [eax edx] \
+ modify exact [edx eax] nomemory;
+#endif
+
+#undef ASMReadTscWithAux
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+#pragma aux ASMReadTscWithAux = \
+ 0x0f 0x01 0xf9 \
+ "mov [ebx], ecx" \
+ parm [ebx] \
+ value [eax edx] \
+ modify exact [eax edx ecx];
+#endif
+
+/* ASMCpuId: Implemented externally, too many parameters. */
+/* ASMCpuId_Idx_ECX: Implemented externally, too many parameters. */
+/* ASMCpuIdExSlow: Always implemented externally. */
+
+#undef ASMCpuId_ECX_EDX
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+#pragma aux ASMCpuId_ECX_EDX = \
+ ".586" \
+ "cpuid" \
+ "mov [edi], ecx" \
+ "mov [esi], edx" \
+ parm [eax] [edi] [esi] \
+ modify exact [eax ebx ecx edx];
+#endif
+
+#undef ASMCpuId_EAX
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+#pragma aux ASMCpuId_EAX = \
+ ".586" \
+ "cpuid" \
+ parm [eax] \
+ value [eax] \
+ modify exact [eax ebx ecx edx];
+#endif
+
+#undef ASMCpuId_EBX
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+#pragma aux ASMCpuId_EBX = \
+ ".586" \
+ "cpuid" \
+ parm [eax] \
+ value [ebx] \
+ modify exact [eax ebx ecx edx];
+#endif
+
+#undef ASMCpuId_ECX
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+#pragma aux ASMCpuId_ECX = \
+ ".586" \
+ "cpuid" \
+ parm [eax] \
+ value [ecx] \
+ modify exact [eax ebx ecx edx];
+#endif
+
+#undef ASMCpuId_EDX
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+#pragma aux ASMCpuId_EDX = \
+ ".586" \
+ "cpuid" \
+ parm [eax] \
+ value [edx] \
+ modify exact [eax ebx ecx edx];
+#endif
+
+/* ASMHasCpuId: MSC inline in main source file. */
+
+#undef ASMGetApicId
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+#pragma aux ASMGetApicId = \
+ ".586" \
+ "xor eax, eax" \
+ "cpuid" \
+ "shr ebx,24" \
+ parm [] \
+ value [bl] \
+ modify exact [eax ebx ecx edx];
+#endif
+
+#undef ASMGetCR0
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+#pragma aux ASMGetCR0 = \
+ "mov eax, cr0" \
+ parm [] nomemory \
+ value [eax] \
+ modify exact [eax] nomemory;
+#endif
+
+#undef ASMSetCR0
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+#pragma aux ASMSetCR0 = \
+ "mov cr0, eax" \
+ parm [eax] nomemory \
+ modify exact [] nomemory;
+#endif
+
+#undef ASMGetCR2
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+#pragma aux ASMGetCR2 = \
+ "mov eax, cr2" \
+ parm [] nomemory \
+ value [eax] \
+ modify exact [eax] nomemory;
+#endif
+
+#undef ASMSetCR2
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+#pragma aux ASMSetCR2 = \
+ "mov cr2, eax" \
+ parm [eax] nomemory \
+ modify exact [] nomemory;
+#endif
+
+#undef ASMGetCR3
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+#pragma aux ASMGetCR3 = \
+ "mov eax, cr3" \
+ parm [] nomemory \
+ value [eax] \
+ modify exact [eax] nomemory;
+#endif
+
+#undef ASMSetCR3
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+#pragma aux ASMSetCR3 = \
+ "mov cr3, eax" \
+ parm [eax] nomemory \
+ modify exact [] nomemory;
+#endif
+
+#undef ASMReloadCR3
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+#pragma aux ASMReloadCR3 = \
+ "mov eax, cr3" \
+ "mov cr3, eax" \
+ parm [] nomemory \
+ modify exact [eax] nomemory;
+#endif
+
+#undef ASMGetCR4
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+#pragma aux ASMGetCR4 = \
+ "mov eax, cr4" \
+ parm [] nomemory \
+ value [eax] \
+ modify exact [eax] nomemory;
+#endif
+
+#undef ASMSetCR4
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+#pragma aux ASMSetCR4 = \
+ "mov cr4, eax" \
+ parm [eax] nomemory \
+ modify exact [] nomemory;
+#endif
+
+/* ASMGetCR8: Don't bother for 32-bit. */
+/* ASMSetCR8: Don't bother for 32-bit. */
+
+#undef ASMIntEnable
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+#pragma aux ASMIntEnable = \
+ "sti" \
+ parm [] nomemory \
+ modify exact [] nomemory;
+#endif
+
+#undef ASMIntDisable
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+#pragma aux ASMIntDisable = \
+ "cli" \
+ parm [] nomemory \
+ modify exact [] nomemory;
+#endif
+
+#undef ASMIntDisableFlags
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+#pragma aux ASMIntDisableFlags = \
+ "pushfd" \
+ "cli" \
+ "pop eax" \
+ parm [] nomemory \
+ value [eax] \
+ modify exact [] nomemory;
+#endif
+
+#undef ASMHalt
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+#pragma aux ASMHalt = \
+ "hlt" \
+ parm [] nomemory \
+ modify exact [] nomemory;
+#endif
+
+#undef ASMRdMsr
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+#pragma aux ASMRdMsr = \
+ ".586" \
+ "rdmsr" \
+ parm [ecx] nomemory \
+ value [eax edx] \
+ modify exact [eax edx] nomemory;
+#endif
+
+#undef ASMWrMsr
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+#pragma aux ASMWrMsr = \
+ ".586" \
+ "wrmsr" \
+ parm [ecx] [eax edx] nomemory \
+ modify exact [] nomemory;
+#endif
+
+#undef ASMRdMsrEx
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+#pragma aux ASMRdMsrEx = \
+ ".586" \
+ "rdmsr" \
+ parm [ecx] [edi] nomemory \
+ value [eax edx] \
+ modify exact [eax edx] nomemory;
+#endif
+
+#undef ASMWrMsrEx
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+#pragma aux ASMWrMsrEx = \
+ ".586" \
+ "wrmsr" \
+ parm [ecx] [edi] [eax edx] nomemory \
+ modify exact [] nomemory;
+#endif
+
+#undef ASMRdMsr_Low
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+#pragma aux ASMRdMsr_Low = \
+ ".586" \
+ "rdmsr" \
+ parm [ecx] nomemory \
+ value [eax] \
+ modify exact [eax edx] nomemory;
+#endif
+
+#undef ASMRdMsr_High
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+#pragma aux ASMRdMsr_High = \
+ ".586" \
+ "rdmsr" \
+ parm [ecx] nomemory \
+ value [edx] \
+ modify exact [eax edx] nomemory;
+#endif
+
+
+#undef ASMGetDR0
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+#pragma aux ASMGetDR0 = \
+ "mov eax, dr0" \
+ parm [] nomemory \
+ value [eax] \
+ modify exact [eax] nomemory;
+#endif
+
+#undef ASMGetDR1
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+#pragma aux ASMGetDR1 = \
+ "mov eax, dr1" \
+ parm [] nomemory \
+ value [eax] \
+ modify exact [eax] nomemory;
+#endif
+
+#undef ASMGetDR2
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+#pragma aux ASMGetDR2 = \
+ "mov eax, dr2" \
+ parm [] nomemory \
+ value [eax] \
+ modify exact [eax] nomemory;
+#endif
+
+#undef ASMGetDR3
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+#pragma aux ASMGetDR3 = \
+ "mov eax, dr3" \
+ parm [] nomemory \
+ value [eax] \
+ modify exact [eax] nomemory;
+#endif
+
+#undef ASMGetDR6
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+#pragma aux ASMGetDR6 = \
+ "mov eax, dr6" \
+ parm [] nomemory \
+ value [eax] \
+ modify exact [eax] nomemory;
+#endif
+
+#undef ASMGetAndClearDR6
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+#pragma aux ASMGetAndClearDR6 = \
+ "mov edx, 0ffff0ff0h" \
+ "mov eax, dr6" \
+ "mov dr6, edx" \
+ parm [] nomemory \
+ value [eax] \
+ modify exact [eax edx] nomemory;
+#endif
+
+#undef ASMGetDR7
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+#pragma aux ASMGetDR7 = \
+ "mov eax, dr7" \
+ parm [] nomemory \
+ value [eax] \
+ modify exact [eax] nomemory;
+#endif
+
+#undef ASMSetDR0
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+#pragma aux ASMSetDR0 = \
+ "mov dr0, eax" \
+ parm [eax] nomemory \
+ modify exact [] nomemory;
+#endif
+
+#undef ASMSetDR1
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+#pragma aux ASMSetDR1 = \
+ "mov dr1, eax" \
+ parm [eax] nomemory \
+ modify exact [] nomemory;
+#endif
+
+#undef ASMSetDR2
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+#pragma aux ASMSetDR2 = \
+ "mov dr2, eax" \
+ parm [eax] nomemory \
+ modify exact [] nomemory;
+#endif
+
+#undef ASMSetDR3
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+#pragma aux ASMSetDR3 = \
+ "mov dr3, eax" \
+ parm [eax] nomemory \
+ modify exact [] nomemory;
+#endif
+
+#undef ASMSetDR6
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+#pragma aux ASMSetDR6 = \
+ "mov dr6, eax" \
+ parm [eax] nomemory \
+ modify exact [] nomemory;
+#endif
+
+#undef ASMSetDR7
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+#pragma aux ASMSetDR7 = \
+ "mov dr7, eax" \
+ parm [eax] nomemory \
+ modify exact [] nomemory;
+#endif
+
+/* Yeah, could've used outp here, but this keeps the main file simpler. */
+#undef ASMOutU8
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+#pragma aux ASMOutU8 = \
+ "out dx, al" \
+ parm [dx] [al] nomemory \
+ modify exact [] nomemory;
+#endif
+
+#undef ASMInU8
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+#pragma aux ASMInU8 = \
+ "in al, dx" \
+ parm [dx] nomemory \
+ value [al] \
+ modify exact [] nomemory;
+#endif
+
+#undef ASMOutU16
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+#pragma aux ASMOutU16 = \
+ "out dx, ax" \
+ parm [dx] [ax] nomemory \
+ modify exact [] nomemory;
+#endif
+
+#undef ASMInU16
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+#pragma aux ASMInU16 = \
+ "in ax, dx" \
+ parm [dx] nomemory \
+ value [ax] \
+ modify exact [] nomemory;
+#endif
+
+#undef ASMOutU32
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+#pragma aux ASMOutU32 = \
+ "out dx, eax" \
+ parm [dx] [eax] nomemory \
+ modify exact [] nomemory;
+#endif
+
+#undef ASMInU32
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+#pragma aux ASMInU32 = \
+ "in eax, dx" \
+ parm [dx] nomemory \
+ value [eax] \
+ modify exact [] nomemory;
+#endif
+
+#undef ASMOutStrU8
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+#pragma aux ASMOutStrU8 = \
+ "rep outsb" \
+ parm [dx] [esi] [ecx] nomemory \
+ modify exact [esi ecx] nomemory;
+#endif
+
+#undef ASMInStrU8
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+#pragma aux ASMInStrU8 = \
+ "rep insb" \
+ parm [dx] [edi] [ecx] \
+ modify exact [edi ecx];
+#endif
+
+#undef ASMOutStrU16
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+#pragma aux ASMOutStrU16 = \
+ "rep outsw" \
+ parm [dx] [esi] [ecx] nomemory \
+ modify exact [esi ecx] nomemory;
+#endif
+
+#undef ASMInStrU16
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+#pragma aux ASMInStrU16 = \
+ "rep insw" \
+ parm [dx] [edi] [ecx] \
+ modify exact [edi ecx];
+#endif
+
+#undef ASMOutStrU32
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+#pragma aux ASMOutStrU32 = \
+ "rep outsd" \
+ parm [dx] [esi] [ecx] nomemory \
+ modify exact [esi ecx] nomemory;
+#endif
+
+#undef ASMInStrU32
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+#pragma aux ASMInStrU32 = \
+ "rep insd" \
+ parm [dx] [edi] [ecx] \
+ modify exact [edi ecx];
+#endif
+
+#undef ASMInvalidatePage
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+#pragma aux ASMInvalidatePage = \
+ "invlpg [eax]" \
+ parm [eax] \
+ modify exact [];
+#endif
+
+#undef ASMWriteBackAndInvalidateCaches
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+#pragma aux ASMWriteBackAndInvalidateCaches = \
+ ".486" \
+ "wbinvd" \
+ parm [] nomemory \
+ modify exact [] nomemory;
+#endif
+
+#undef ASMInvalidateInternalCaches
+#ifdef IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+#pragma aux ASMInvalidateInternalCaches = \
+ ".486" \
+ "invd" \
+ parm [] \
+ modify exact [];
+#endif
+
+#endif /* !IPRT_INCLUDED_asm_amd64_x86_watcom_32_h */
+
diff --git a/include/iprt/asm-amd64-x86.h b/include/iprt/asm-amd64-x86.h
new file mode 100644
index 00000000..0bfa1925
--- /dev/null
+++ b/include/iprt/asm-amd64-x86.h
@@ -0,0 +1,3447 @@
+/** @file
+ * IPRT - AMD64 and x86 Specific Assembly Functions.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_asm_amd64_x86_h
+#define IPRT_INCLUDED_asm_amd64_x86_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+#include <iprt/assert.h>
+#include <iprt/x86-helpers.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
+/* Emit the intrinsics at all optimization levels. */
+# include <iprt/sanitized/intrin.h>
+# pragma intrinsic(_ReadWriteBarrier)
+# pragma intrinsic(__cpuid)
+# if RT_INLINE_ASM_USES_INTRIN >= RT_MSC_VER_VS2010 /*?*/
+# pragma intrinsic(__cpuidex)
+# endif
+# 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 >= RT_MSC_VER_VS2005
+# pragma intrinsic(__halt)
+# endif
+# if RT_INLINE_ASM_USES_INTRIN >= RT_MSC_VER_VS2008
+/*# pragma intrinsic(__readeflags) - buggy intrinsics in VC++ 2010, reordering/optimizers issues
+# pragma intrinsic(__writeeflags) */
+# pragma intrinsic(__rdtscp)
+# endif
+# if defined(RT_ARCH_AMD64) && RT_INLINE_ASM_USES_INTRIN >= RT_MSC_VER_VS2015 /*?*/
+# pragma intrinsic(_readfsbase_u64)
+# pragma intrinsic(_readgsbase_u64)
+# pragma intrinsic(_writefsbase_u64)
+# pragma intrinsic(_writegsbase_u64)
+# endif
+# if RT_INLINE_ASM_USES_INTRIN >= RT_MSC_VER_VS2013
+# pragma intrinsic(__lidt)
+# pragma intrinsic(__sidt)
+# pragma intrinsic(_lgdt)
+# pragma intrinsic(_sgdt)
+# endif
+#endif
+
+
+/*
+ * Undefine all symbols we have Watcom C/C++ #pragma aux'es for.
+ */
+#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, RT_FAR *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 RT_FAR *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, RT_FAR *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 RT_FAR *PRGDTRALIGNED;
+
+
+/**
+ * Gets the content of the IDTR CPU register.
+ * @param pIdtr Where to store the IDTR contents.
+ */
+#if RT_INLINE_ASM_EXTERNAL && RT_INLINE_ASM_USES_INTRIN < RT_MSC_VER_VS2013
+RT_ASM_DECL_PRAGMA_WATCOM(void) ASMGetIDTR(PRTIDTR pIdtr);
+#else
+DECLINLINE(void) ASMGetIDTR(PRTIDTR pIdtr)
+{
+# if RT_INLINE_ASM_USES_INTRIN >= RT_MSC_VER_VS2013
+ __sidt(pIdtr);
+# elif 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 && RT_INLINE_ASM_USES_INTRIN < RT_MSC_VER_VS2013
+RT_ASM_DECL_PRAGMA_WATCOM(uint16_t) ASMGetIdtrLimit(void);
+#else
+DECLINLINE(uint16_t) ASMGetIdtrLimit(void)
+{
+ RTIDTRALIGNED TmpIdtr;
+# if RT_INLINE_ASM_USES_INTRIN >= RT_MSC_VER_VS2013
+ __sidt(&TmpIdtr);
+# elif 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 && RT_INLINE_ASM_USES_INTRIN < RT_MSC_VER_VS2013
+RT_ASM_DECL_PRAGMA_WATCOM(void) ASMSetIDTR(const RTIDTR RT_FAR *pIdtr);
+#else
+DECLINLINE(void) ASMSetIDTR(const RTIDTR RT_FAR *pIdtr)
+{
+# if RT_INLINE_ASM_USES_INTRIN >= RT_MSC_VER_VS2013
+ __lidt((void *)pIdtr);
+# elif 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 && RT_INLINE_ASM_USES_INTRIN < RT_MSC_VER_VS2013
+RT_ASM_DECL_PRAGMA_WATCOM(void) ASMGetGDTR(PRTGDTR pGdtr);
+#else
+DECLINLINE(void) ASMGetGDTR(PRTGDTR pGdtr)
+{
+# if RT_INLINE_ASM_USES_INTRIN >= RT_MSC_VER_VS2013
+ _sgdt(pGdtr);
+# elif 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 && RT_INLINE_ASM_USES_INTRIN < RT_MSC_VER_VS2013
+RT_ASM_DECL_PRAGMA_WATCOM(void) ASMSetGDTR(const RTGDTR RT_FAR *pGdtr);
+#else
+DECLINLINE(void) ASMSetGDTR(const RTGDTR RT_FAR *pGdtr)
+{
+# if RT_INLINE_ASM_USES_INTRIN >= RT_MSC_VER_VS2013
+ _lgdt((void *)pGdtr);
+# elif 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
+RT_ASM_DECL_PRAGMA_WATCOM(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
+RT_ASM_DECL_PRAGMA_WATCOM(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
+RT_ASM_DECL_PRAGMA_WATCOM(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
+RT_ASM_DECL_PRAGMA_WATCOM(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
+
+#ifdef RT_ARCH_AMD64
+
+/**
+ * Get the FS base register.
+ * @returns FS base address.
+ */
+#if RT_INLINE_ASM_EXTERNAL && RT_INLINE_ASM_USES_INTRIN < RT_MSC_VER_VS2015 /*?*/
+DECLASM(uint64_t) ASMGetFSBase(void);
+#else
+DECLINLINE(uint64_t) ASMGetFSBase(void)
+{
+# if RT_INLINE_ASM_USES_INTRIN >= RT_MSC_VER_VS2015
+ return (uint64_t)_readfsbase_u64();
+# elif RT_INLINE_ASM_GNU_STYLE
+ uint64_t uFSBase;
+ __asm__ __volatile__("rdfsbase %0\n\t" : "=r" (uFSBase));
+ return uFSBase;
+# endif
+}
+# endif
+
+
+/**
+ * Set the FS base register.
+ * @param uNewBase The new base value.
+ */
+#if RT_INLINE_ASM_EXTERNAL && RT_INLINE_ASM_USES_INTRIN < RT_MSC_VER_VS2015 /*?*/
+DECLASM(void) ASMSetFSBase(uint64_t uNewBase);
+#else
+DECLINLINE(void) ASMSetFSBase(uint64_t uNewBase)
+{
+# if RT_INLINE_ASM_USES_INTRIN >= RT_MSC_VER_VS2015
+ _writefsbase_u64(uNewBase);
+# elif RT_INLINE_ASM_GNU_STYLE
+ __asm__ __volatile__("wrfsbase %0\n\t" : : "r" (uNewBase));
+# endif
+}
+# endif
+
+#endif /* RT_ARCH_AMD64 */
+
+/**
+ * Get the GS register.
+ * @returns GS.
+ */
+#if RT_INLINE_ASM_EXTERNAL
+RT_ASM_DECL_PRAGMA_WATCOM(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
+
+#ifdef RT_ARCH_AMD64
+
+/**
+ * Get the GS base register.
+ * @returns GS base address.
+ */
+#if RT_INLINE_ASM_EXTERNAL && RT_INLINE_ASM_USES_INTRIN < RT_MSC_VER_VS2015 /*?*/
+DECLASM(uint64_t) ASMGetGSBase(void);
+#else
+DECLINLINE(uint64_t) ASMGetGSBase(void)
+{
+# if RT_INLINE_ASM_USES_INTRIN >= RT_MSC_VER_VS2015
+ return (uint64_t)_readgsbase_u64();
+# elif RT_INLINE_ASM_GNU_STYLE
+ uint64_t uGSBase;
+ __asm__ __volatile__("rdgsbase %0\n\t" : "=r" (uGSBase));
+ return uGSBase;
+# endif
+}
+# endif
+
+
+/**
+ * Set the GS base register.
+ * @param uNewBase The new base value.
+ */
+#if RT_INLINE_ASM_EXTERNAL && RT_INLINE_ASM_USES_INTRIN < RT_MSC_VER_VS2015 /*?*/
+DECLASM(void) ASMSetGSBase(uint64_t uNewBase);
+#else
+DECLINLINE(void) ASMSetGSBase(uint64_t uNewBase)
+{
+# if RT_INLINE_ASM_USES_INTRIN >= RT_MSC_VER_VS2015
+ _writegsbase_u64(uNewBase);
+# elif RT_INLINE_ASM_GNU_STYLE
+ __asm__ __volatile__("wrgsbase %0\n\t" : : "r" (uNewBase));
+# endif
+}
+# endif
+
+#endif /* RT_ARCH_AMD64 */
+
+
+/**
+ * Get the SS register.
+ * @returns SS.
+ */
+#if RT_INLINE_ASM_EXTERNAL
+RT_ASM_DECL_PRAGMA_WATCOM(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
+RT_ASM_DECL_PRAGMA_WATCOM(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
+RT_ASM_DECL_PRAGMA_WATCOM(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
+RT_ASM_DECL_PRAGMA_WATCOM(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 - buggy intrinsics in VC++ 2010, reordering/optimizers issues. */
+RT_ASM_DECL_PRAGMA_WATCOM(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 >= RT_MSC_VER_VS2008
+ 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 - see __readeflags() above. */
+RT_ASM_DECL_PRAGMA_WATCOM(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 >= RT_MSC_VER_VS2008
+ __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 - buggy intrinsics in VC++ 2010, reordering/optimizers issues. */
+RT_ASM_DECL_PRAGMA_WATCOM(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 >= RT_MSC_VER_VS2008
+ 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 - buggy intrinsics in VC++ 2010, reordering/optimizers issues. */
+RT_ASM_DECL_PRAGMA_WATCOM(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 >= RT_MSC_VER_VS2008
+ 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 - buggy intrinsics in VC++ 2010, reordering/optimizers issues. */
+RT_ASM_DECL_PRAGMA_WATCOM(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 >= RT_MSC_VER_VS2008
+ 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
+RT_ASM_DECL_PRAGMA_WATCOM(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 < RT_MSC_VER_VS2008
+RT_ASM_DECL_PRAGMA_WATCOM(uint64_t) ASMReadTscWithAux(uint32_t RT_FAR *puAux);
+#else
+DECLINLINE(uint64_t) ASMReadTscWithAux(uint32_t RT_FAR *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 >= RT_MSC_VER_VS2008
+ 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 RT_FAR *pvEAX, void RT_FAR *pvEBX, void RT_FAR *pvECX, void RT_FAR *pvEDX);
+#else
+DECLINLINE(void) ASMCpuId(uint32_t uOperator, void RT_FAR *pvEAX, void RT_FAR *pvEBX, void RT_FAR *pvECX, void RT_FAR *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 RT_FAR *)pvEAX = (uint32_t)uRAX;
+ *(uint32_t RT_FAR *)pvEBX = (uint32_t)uRBX;
+ *(uint32_t RT_FAR *)pvECX = (uint32_t)uRCX;
+ *(uint32_t RT_FAR *)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 RT_FAR *)pvEAX = aInfo[0];
+ *(uint32_t RT_FAR *)pvEBX = aInfo[1];
+ *(uint32_t RT_FAR *)pvECX = aInfo[2];
+ *(uint32_t RT_FAR *)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 RT_FAR *)pvEAX = uEAX;
+ *(uint32_t RT_FAR *)pvEBX = uEBX;
+ *(uint32_t RT_FAR *)pvECX = uECX;
+ *(uint32_t RT_FAR *)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 RT_FAR *pvEAX, void RT_FAR *pvEBX, void RT_FAR *pvECX, void RT_FAR *pvEDX);
+#else
+DECLINLINE(void) ASMCpuId_Idx_ECX(uint32_t uOperator, uint32_t uIdxECX, void RT_FAR *pvEAX, void RT_FAR *pvEBX, void RT_FAR *pvECX, void RT_FAR *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 RT_FAR *)pvEAX = (uint32_t)uRAX;
+ *(uint32_t RT_FAR *)pvEBX = (uint32_t)uRBX;
+ *(uint32_t RT_FAR *)pvECX = (uint32_t)uRCX;
+ *(uint32_t RT_FAR *)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 RT_FAR *)pvEAX = aInfo[0];
+ *(uint32_t RT_FAR *)pvEBX = aInfo[1];
+ *(uint32_t RT_FAR *)pvECX = aInfo[2];
+ *(uint32_t RT_FAR *)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 RT_FAR *)pvEAX = uEAX;
+ *(uint32_t RT_FAR *)pvEBX = uEBX;
+ *(uint32_t RT_FAR *)pvECX = uECX;
+ *(uint32_t RT_FAR *)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 RT_FAR *pvEAX, void RT_FAR *pvEBX, void RT_FAR *pvECX, void RT_FAR *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
+RT_ASM_DECL_PRAGMA_WATCOM(void) ASMCpuId_ECX_EDX(uint32_t uOperator, void RT_FAR *pvECX, void RT_FAR *pvEDX);
+#else
+DECLINLINE(void) ASMCpuId_ECX_EDX(uint32_t uOperator, void RT_FAR *pvECX, void RT_FAR *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
+RT_ASM_DECL_PRAGMA_WATCOM(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
+RT_ASM_DECL_PRAGMA_WATCOM(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
+RT_ASM_DECL_PRAGMA_WATCOM(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
+RT_ASM_DECL_PRAGMA_WATCOM(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
+RT_ASM_DECL_PRAGMA_WATCOM(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
+
+
+/**
+ * Gets the APIC ID of the current CPU using leaf 0xb.
+ *
+ * @returns the APIC ID.
+ */
+#if RT_INLINE_ASM_EXTERNAL && RT_INLINE_ASM_USES_INTRIN < RT_MSC_VER_VS2010 /*?*/
+RT_ASM_DECL_PRAGMA_WATCOM(uint32_t) ASMGetApicIdExt0B(void);
+#else
+DECLINLINE(uint32_t) ASMGetApicIdExt0B(void)
+{
+# if RT_INLINE_ASM_GNU_STYLE
+ RTCCUINTREG xDX;
+# ifdef RT_ARCH_AMD64
+ RTCCUINTREG uSpillEax, uSpillEcx;
+ __asm__ __volatile__ ("cpuid"
+ : "=a" (uSpillEax),
+ "=c" (uSpillEcx),
+ "=d" (xDX)
+ : "0" (0xb),
+ "1" (0)
+ : "rbx");
+# elif (defined(PIC) || defined(__PIC__)) && defined(__i386__)
+ RTCCUINTREG uSpillEax, uSpillEcx, uSpillEbx;
+ __asm__ __volatile__ ("mov %%ebx,%2\n\t"
+ "cpuid\n\t"
+ "xchgl %%ebx,%2\n\t"
+ : "=a" (uSpillEax),
+ "=c" (uSpillEcx),
+ "=rm" (uSpillEbx),
+ "=d" (xDX)
+ : "0" (0xb),
+ "1" (0));
+# else
+ RTCCUINTREG uSpillEax, uSpillEcx;
+ __asm__ __volatile__ ("cpuid"
+ : "=a" (uSpillEax),
+ "=c" (uSpillEcx),
+ "=d" (xDX)
+ : "0" (0xb),
+ "1" (0)
+ : "ebx");
+# endif
+ return (uint32_t)xDX;
+
+# elif RT_INLINE_ASM_USES_INTRIN >= RT_MSC_VER_VS2010 /*?*/
+
+ int aInfo[4];
+ __cpuidex(aInfo, 0xb, 0);
+ return aInfo[3];
+
+# else
+ RTCCUINTREG xDX;
+ __asm
+ {
+ push ebx
+ mov eax, 0xb
+ xor ecx, ecx
+ cpuid
+ mov [xDX], edx
+ pop ebx
+ }
+ return (uint32_t)xDX;
+# endif
+}
+#endif
+
+
+/**
+ * Gets the APIC ID of the current CPU using leaf 8000001E.
+ *
+ * @returns the APIC ID.
+ */
+DECLINLINE(uint32_t) ASMGetApicIdExt8000001E(void)
+{
+ return ASMCpuId_EAX(0x8000001e);
+}
+
+
+/**
+ * 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 RTX86IsIntelCpu(uEBX, uECX, uEDX);
+}
+
+
+/**
+ * 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 RTX86IsAmdCpu(uEBX, uECX, uEDX);
+}
+
+
+/**
+ * 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 RTX86IsViaCentaurCpu(uEBX, uECX, uEDX);
+}
+
+
+/**
+ * Tests if this is a Shanghai CPU.
+ *
+ * @returns true/false.
+ * @remarks ASSUMES that cpuid is supported by the CPU.
+ */
+DECLINLINE(bool) ASMIsShanghaiCpu(void)
+{
+ uint32_t uEAX, uEBX, uECX, uEDX;
+ ASMCpuId(0, &uEAX, &uEBX, &uECX, &uEDX);
+ return RTX86IsShanghaiCpu(uEBX, uECX, uEDX);
+}
+
+
+/**
+ * Tests if this is a genuine Hygon CPU.
+ *
+ * @returns true/false.
+ * @remarks ASSUMES that cpuid is supported by the CPU.
+ */
+DECLINLINE(bool) ASMIsHygonCpu(void)
+{
+ uint32_t uEAX, uEBX, uECX, uEDX;
+ ASMCpuId(0, &uEAX, &uEBX, &uECX, &uEDX);
+ return RTX86IsHygonCpu(uEBX, uECX, uEDX);
+}
+
+
+/**
+ * Get cr0.
+ * @returns cr0.
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+RT_ASM_DECL_PRAGMA_WATCOM(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
+RT_ASM_DECL_PRAGMA_WATCOM(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
+RT_ASM_DECL_PRAGMA_WATCOM(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
+RT_ASM_DECL_PRAGMA_WATCOM(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
+RT_ASM_DECL_PRAGMA_WATCOM(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
+RT_ASM_DECL_PRAGMA_WATCOM(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
+RT_ASM_DECL_PRAGMA_WATCOM(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
+RT_ASM_DECL_PRAGMA_WATCOM(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
+RT_ASM_DECL_PRAGMA_WATCOM(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 RT_FAR *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 RT_FAR *pXStateArea, uint64_t fComponents);
+
+
+struct X86FXSTATE;
+/**
+ * Save FPU and SSE CPU state.
+ * @param pXStateArea Where to save the state.
+ */
+DECLASM(void) ASMFxSave(struct X86FXSTATE RT_FAR *pXStateArea);
+
+/**
+ * Load FPU and SSE CPU state.
+ * @param pXStateArea Where to load the state from.
+ */
+DECLASM(void) ASMFxRstor(struct X86FXSTATE const RT_FAR *pXStateArea);
+
+
+/**
+ * Enables interrupts (EFLAGS.IF).
+ */
+#if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
+RT_ASM_DECL_PRAGMA_WATCOM(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
+RT_ASM_DECL_PRAGMA_WATCOM(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
+RT_ASM_DECL_PRAGMA_WATCOM(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 < RT_MSC_VER_VS2005
+RT_ASM_DECL_PRAGMA_WATCOM(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
+RT_ASM_DECL_PRAGMA_WATCOM(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
+RT_ASM_DECL_PRAGMA_WATCOM_386(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
+RT_ASM_DECL_PRAGMA_WATCOM_386(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
+RT_ASM_DECL_PRAGMA_WATCOM_386(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
+RT_ASM_DECL_PRAGMA_WATCOM(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
+RT_ASM_DECL_PRAGMA_WATCOM(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
+RT_ASM_DECL_PRAGMA_WATCOM(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
+RT_ASM_DECL_PRAGMA_WATCOM(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
+RT_ASM_DECL_PRAGMA_WATCOM(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
+RT_ASM_DECL_PRAGMA_WATCOM(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
+RT_ASM_DECL_PRAGMA_WATCOM(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
+RT_ASM_DECL_PRAGMA_WATCOM(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
+RT_ASM_DECL_PRAGMA_WATCOM(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
+RT_ASM_DECL_PRAGMA_WATCOM(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
+RT_ASM_DECL_PRAGMA_WATCOM(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
+RT_ASM_DECL_PRAGMA_WATCOM(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
+RT_ASM_DECL_PRAGMA_WATCOM(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
+RT_ASM_DECL_PRAGMA_WATCOM(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
+RT_ASM_DECL_PRAGMA_WATCOM(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
+RT_ASM_DECL_PRAGMA_WATCOM(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
+RT_ASM_DECL_PRAGMA_WATCOM(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
+RT_ASM_DECL_PRAGMA_WATCOM(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
+RT_ASM_DECL_PRAGMA_WATCOM(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
+RT_ASM_DECL_PRAGMA_WATCOM(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
+RT_ASM_DECL_PRAGMA_WATCOM(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
+RT_ASM_DECL_PRAGMA_WATCOM(void) ASMOutStrU8(RTIOPORT Port, uint8_t const RT_FAR *pau8, size_t c);
+#else
+DECLINLINE(void) ASMOutStrU8(RTIOPORT Port, uint8_t const RT_FAR *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 RT_FAR *)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
+RT_ASM_DECL_PRAGMA_WATCOM(void) ASMInStrU8(RTIOPORT Port, uint8_t RT_FAR *pau8, size_t c);
+#else
+DECLINLINE(void) ASMInStrU8(RTIOPORT Port, uint8_t RT_FAR *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
+RT_ASM_DECL_PRAGMA_WATCOM(void) ASMOutStrU16(RTIOPORT Port, uint16_t const RT_FAR *pau16, size_t c);
+#else
+DECLINLINE(void) ASMOutStrU16(RTIOPORT Port, uint16_t const RT_FAR *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 RT_FAR *)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
+RT_ASM_DECL_PRAGMA_WATCOM(void) ASMInStrU16(RTIOPORT Port, uint16_t RT_FAR *pau16, size_t c);
+#else
+DECLINLINE(void) ASMInStrU16(RTIOPORT Port, uint16_t RT_FAR *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
+RT_ASM_DECL_PRAGMA_WATCOM(void) ASMOutStrU32(RTIOPORT Port, uint32_t const RT_FAR *pau32, size_t c);
+#else
+DECLINLINE(void) ASMOutStrU32(RTIOPORT Port, uint32_t const RT_FAR *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 RT_FAR *)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
+RT_ASM_DECL_PRAGMA_WATCOM(void) ASMInStrU32(RTIOPORT Port, uint32_t RT_FAR *pau32, size_t c);
+#else
+DECLINLINE(void) ASMInStrU32(RTIOPORT Port, uint32_t RT_FAR *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 RT_FAR *)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
+RT_ASM_DECL_PRAGMA_WATCOM(void) ASMInvalidatePage(RTCCUINTXREG uPtr);
+#else
+DECLINLINE(void) ASMInvalidatePage(RTCCUINTXREG uPtr)
+{
+# if RT_INLINE_ASM_USES_INTRIN
+ __invlpg((void RT_FAR *)uPtr);
+
+# elif RT_INLINE_ASM_GNU_STYLE
+ __asm__ __volatile__("invlpg %0\n\t"
+ : : "m" (*(uint8_t RT_FAR *)(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
+RT_ASM_DECL_PRAGMA_WATCOM(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
+RT_ASM_DECL_PRAGMA_WATCOM(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 */
+
+
+/*
+ * Include #pragma aux definitions for Watcom C/C++.
+ */
+#if defined(__WATCOMC__) && ARCH_BITS == 16
+# define IPRT_ASM_AMD64_X86_WATCOM_16_INSTANTIATE
+# undef IPRT_INCLUDED_asm_amd64_x86_watcom_16_h
+# include "asm-amd64-x86-watcom-16.h"
+#elif defined(__WATCOMC__) && ARCH_BITS == 32
+# define IPRT_ASM_AMD64_X86_WATCOM_32_INSTANTIATE
+# undef IPRT_INCLUDED_asm_amd64_x86_watcom_32_h
+# include "asm-amd64-x86-watcom-32.h"
+#endif
+
+
+/** @} */
+#endif /* !IPRT_INCLUDED_asm_amd64_x86_h */
+
diff --git a/include/iprt/asm-arm.h b/include/iprt/asm-arm.h
new file mode 100644
index 00000000..b9d287fa
--- /dev/null
+++ b/include/iprt/asm-arm.h
@@ -0,0 +1,321 @@
+/** @file
+ * IPRT - ARM Specific Assembly Functions.
+ */
+
+/*
+ * Copyright (C) 2015-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_asm_arm_h
+#define IPRT_INCLUDED_asm_arm_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+#if !defined(RT_ARCH_ARM64) && !defined(RT_ARCH_ARM32)
+# error "Not on ARM64 or ARM32"
+#endif
+
+/** @defgroup grp_rt_asm_arm ARM Specific ASM Routines
+ * @ingroup grp_rt_asm
+ * @{
+ */
+
+
+#if 0 /* figure out arm64 */
+
+/**
+ * Get the CPSR (Current Program Status) register.
+ * @returns CPSR.
+ */
+#if RT_INLINE_ASM_EXTERNAL
+DECLASM(RTCCUINTREG) ASMGetFlags(void);
+#else
+DECLINLINE(RTCCUINTREG) ASMGetFlags(void)
+{
+ RTCCUINTREG uFlags;
+# if RT_INLINE_ASM_GNU_STYLE
+# ifdef RT_ARCH_ARM64
+ __asm__ __volatile__("mrs %0, nzcv\n\t" : "=r" (uFlags));
+# else
+ __asm__ __volatile__("mrs %0, cpsr\n\t" : "=r" (uFlags));
+# endif
+# else
+# error "Unsupported compiler"
+# endif
+ return uFlags;
+}
+#endif
+
+
+/**
+ * Set the CPSR register.
+ * @param uFlags The new CPSR value.
+ */
+#if RT_INLINE_ASM_EXTERNAL
+DECLASM(void) ASMSetFlags(RTCCUINTREG uFlags);
+#else
+DECLINLINE(void) ASMSetFlags(RTCCUINTREG uFlags)
+{
+# if RT_INLINE_ASM_GNU_STYLE
+ __asm__ __volatile__("msr cpsr_c, %0\n\t"
+ : : "r" (uFlags));
+# else
+# error "Unsupported compiler"
+# endif
+}
+#endif
+
+#endif
+
+
+/**
+ * Gets the content of the CNTVCT_EL0 (or CNTPCT) register.
+ *
+ * @returns CNTVCT_EL0 value.
+ * @note We call this TSC to better fit in with existing x86/amd64 based code.
+ */
+#if RT_INLINE_ASM_EXTERNAL
+DECLASM(uint64_t) ASMReadTSC(void);
+#else
+DECLINLINE(uint64_t) ASMReadTSC(void)
+{
+# if RT_INLINE_ASM_GNU_STYLE
+ uint64_t u64;
+# ifdef RT_ARCH_ARM64
+ __asm__ __volatile__("isb\n\t"
+ "mrs %0, CNTVCT_EL0\n\t"
+ : "=r" (u64));
+# else
+ uint32_t u32Spill;
+ uint32_t u32Comp;
+ __asm__ __volatile__("isb\n"
+ "Lagain:\n\t"
+ "mrrc p15, 0, %[uSpill], %H[uRet], c14\n\t" /* CNTPCT high into uRet.hi */
+ "mrrc p15, 0, %[uRet], %[uSpill], c14\n\t" /* CNTPCT low into uRet.lo */
+ "mrrc p15, 0, %[uSpill], %[uHiComp], c14\n\t" /* CNTPCT high into uHiComp */
+ "cmp %H[uRet], %[uHiComp]\n\t"
+ "b.eq Lagain\n\t" /* Redo if high value changed. */
+ : [uRet] "=r" (u64)
+ , "=r" (uHiComp)
+ , "=r" (uSpill));
+# endif
+ return u64;
+
+# else
+# error "Unsupported compiler"
+# endif
+}
+#endif
+
+#if 0 /* port to arm64, armv7 and check */
+
+/**
+ * Enables interrupts (IRQ and FIQ).
+ */
+#if RT_INLINE_ASM_EXTERNAL
+DECLASM(void) ASMIntEnable(void);
+#else
+DECLINLINE(void) ASMIntEnable(void)
+{
+ RTCCUINTREG uFlags;
+# if RT_INLINE_ASM_GNU_STYLE
+ __asm__ __volatile__("mrs %0, cpsr\n\t"
+ "bic %0, %0, #0xc0\n\t"
+ "msr cpsr_c, %0\n\t"
+ : "=r" (uFlags));
+# else
+# error "Unsupported compiler"
+# endif
+}
+#endif
+
+
+/**
+ * Disables interrupts (IRQ and FIQ).
+ */
+#if RT_INLINE_ASM_EXTERNAL
+DECLASM(void) ASMIntDisable(void);
+#else
+DECLINLINE(void) ASMIntDisable(void)
+{
+ RTCCUINTREG uFlags;
+# if RT_INLINE_ASM_GNU_STYLE
+ __asm__ __volatile__("mrs %0, cpsr\n\t"
+ "orr %0, %0, #0xc0\n\t"
+ "msr cpsr_c, %0\n\t"
+ : "=r" (uFlags));
+# else
+# error "Unsupported compiler"
+# endif
+}
+#endif
+
+
+/**
+ * Disables interrupts and returns previous uFLAGS.
+ */
+#if RT_INLINE_ASM_EXTERNAL
+DECLASM(RTCCUINTREG) ASMIntDisableFlags(void);
+#else
+DECLINLINE(RTCCUINTREG) ASMIntDisableFlags(void)
+{
+ RTCCUINTREG uFlags;
+# if RT_INLINE_ASM_GNU_STYLE
+ RTCCUINTREG uNewFlags;
+ __asm__ __volatile__("mrs %0, cpsr\n\t"
+ "orr %1, %0, #0xc0\n\t"
+ "msr cpsr_c, %1\n\t"
+ : "=r" (uFlags)
+ , "=r" (uNewFlags));
+# else
+# error "Unsupported compiler"
+# endif
+ return uFlags;
+}
+#endif
+
+
+/**
+ * Are interrupts enabled?
+ *
+ * @returns true / false.
+ */
+DECLINLINE(bool) ASMIntAreEnabled(void)
+{
+/** @todo r=bird: reversed, but does both need to be enabled? */
+ return ASMGetFlags() & 0xc0 /* IRQ and FIQ bits */ ? true : false;
+}
+
+#endif
+
+/**
+ * Halts the CPU until interrupted.
+ */
+#if RT_INLINE_ASM_EXTERNAL
+DECLASM(void) ASMHalt(void);
+#else
+DECLINLINE(void) ASMHalt(void)
+{
+# if RT_INLINE_ASM_GNU_STYLE
+ __asm__ __volatile__ ("wfi\n\t"); /* wait for interrupt */
+# else
+# error "Unsupported compiler"
+# endif
+}
+#endif
+
+#if 0
+/**
+ * Gets the CPU ID of the current CPU.
+ *
+ * @returns the CPU ID.
+ * @note the name of this method is a bit misleading but serves the purpose
+ * and prevents #ifdef orgies in other places.
+ */
+#if RT_INLINE_ASM_EXTERNAL
+DECLASM(uint8_t) ASMGetApicId(void);
+#else
+DECLINLINE(uint8_t) ASMGetApicId(void)
+{
+# if RT_INLINE_ASM_GNU_STYLE
+ RTCCUINTREG uCpuId;
+ __asm__ ("mrc p15, 0, %0, c0, c0, 5\n\t" /* CPU ID Register, privileged */
+ : "=r" (uCpuId));
+ return uCpuId;
+# else
+# error "Unsupported compiler"
+# endif
+}
+#endif
+#endif
+
+#if 0
+
+/**
+ * Invalidate page.
+ *
+ * @param pv Address of the page to invalidate.
+ */
+#if RT_INLINE_ASM_EXTERNAL
+DECLASM(void) ASMInvalidatePage(void *pv);
+#else
+DECLINLINE(void) ASMInvalidatePage(void *pv)
+{
+# if RT_INLINE_ASM_GNU_STYLE
+
+# else
+# error "Unsupported compiler"
+# endif
+}
+#endif
+
+
+/**
+ * Write back the internal caches and invalidate them.
+ */
+#if RT_INLINE_ASM_EXTERNAL
+DECLASM(void) ASMWriteBackAndInvalidateCaches(void);
+#else
+DECLINLINE(void) ASMWriteBackAndInvalidateCaches(void)
+{
+# if RT_INLINE_ASM_GNU_STYLE
+
+# else
+# error "Unsupported compiler"
+# 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
+
+# else
+# error "Unsupported compiler"
+# endif
+}
+#endif
+
+#endif
+
+
+/** @} */
+#endif /* !IPRT_INCLUDED_asm_arm_h */
+
diff --git a/include/iprt/asm-math.h b/include/iprt/asm-math.h
new file mode 100644
index 00000000..d379111c
--- /dev/null
+++ b/include/iprt/asm-math.h
@@ -0,0 +1,445 @@
+/** @file
+ * IPRT - Assembly Routines for Optimizing some Integers Math Operations.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_asm_math_h
+#define IPRT_INCLUDED_asm_math_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+
+#if defined(_MSC_VER) && RT_INLINE_ASM_USES_INTRIN
+/* Emit the intrinsics at all optimization levels. */
+# include <iprt/sanitized/intrin.h>
+# 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
+
+
+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
+}
+
+
+
+/**
+ * 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 /* !IPRT_INCLUDED_asm_math_h */
+
diff --git a/include/iprt/asm-watcom-x86-16.h b/include/iprt/asm-watcom-x86-16.h
new file mode 100644
index 00000000..db8d4e69
--- /dev/null
+++ b/include/iprt/asm-watcom-x86-16.h
@@ -0,0 +1,983 @@
+/** @file
+ * IPRT - Assembly Functions, x86 16-bit Watcom C/C++ pragma aux.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_asm_watcom_x86_16_h
+#define IPRT_INCLUDED_asm_watcom_x86_16_h
+/* no pragma once */
+
+#ifndef IPRT_INCLUDED_asm_h
+# error "Don't include this header directly."
+#endif
+
+/*
+ * Turns out we cannot use 'ds' for segment stuff here because the compiler
+ * seems to insists on loading the DGROUP segment into 'ds' before calling
+ * stuff when using -ecc. Using 'es' instead as this seems to work fine.
+ *
+ * Note! The #undef that preceds the #pragma aux statements is for undoing
+ * the mangling, because the symbol in #pragma aux [symbol] statements
+ * doesn't get subjected to preprocessing. This is also why we include
+ * the watcom header at both the top and the bottom of asm.h file.
+ */
+
+#undef ASMCompilerBarrier
+#ifdef IPRT_ASM_WATCOM_X86_16_WITH_PRAGMAS
+# if 0 /* overkill version. */
+# pragma aux ASMCompilerBarrier = \
+ "nop" \
+ parm [] \
+ modify exact [ax bx cx dx es ds];
+# else
+# pragma aux ASMCompilerBarrier = \
+ "" \
+ parm [] \
+ modify exact [];
+# endif
+#endif
+
+#undef ASMNopPause
+#ifdef IPRT_ASM_WATCOM_X86_16_WITH_PRAGMAS
+#pragma aux ASMNopPause = \
+ ".686p" \
+ ".xmm2" \
+ "pause" \
+ parm [] nomemory \
+ modify exact [] nomemory;
+#endif
+
+#undef ASMAtomicXchgU8
+#ifdef IPRT_ASM_WATCOM_X86_16_WITH_PRAGMAS
+#pragma aux ASMAtomicXchgU8 = \
+ "xchg es:[bx], al" \
+ parm [es bx] [al] \
+ value [al] \
+ modify exact [al];
+#endif
+
+#undef ASMAtomicXchgU16
+#ifdef IPRT_ASM_WATCOM_X86_16_WITH_PRAGMAS
+#pragma aux ASMAtomicXchgU16 = \
+ "xchg es:[bx], ax" \
+ parm [es bx] [ax] \
+ value [ax] \
+ modify exact [ax];
+#endif
+
+#undef ASMAtomicXchgU32
+#ifdef IPRT_ASM_WATCOM_X86_16_WITH_PRAGMAS
+#pragma aux ASMAtomicXchgU32 = \
+ ".386" \
+ "shl ecx, 16" \
+ "mov cx, ax" \
+ "xchg es:[bx], ecx" \
+ "mov eax, ecx" \
+ "shr ecx, 16" \
+ parm [es bx] [ax cx] \
+ value [ax cx] \
+ modify exact [ax cx];
+#endif
+
+#undef ASMAtomicXchgU64
+#ifdef IPRT_ASM_WATCOM_X86_16_WITH_PRAGMAS
+#pragma aux ASMAtomicXchgU64 = \
+ ".586" \
+ "shl eax, 16" \
+ "mov ax, bx" /* eax = high dword */ \
+ "shl ecx, 16" \
+ "mov cx, dx" /* ecx = low dword */ \
+ "mov ebx, ecx" /* ebx = low */ \
+ "mov ecx, eax" /* ecx = high */ \
+ "try_again:" \
+ "lock cmpxchg8b es:[si]" \
+ "jnz try_again" \
+ "xchg eax, edx" \
+ "mov ebx, eax" \
+ "shr eax, 16" \
+ "mov ecx, edx" \
+ "shr ecx, 16" \
+ parm [es si] [dx cx bx ax] \
+ value [dx cx bx ax] \
+ modify exact [dx cx bx ax];
+#endif
+
+#undef ASMAtomicCmpXchgU8
+#ifdef IPRT_ASM_WATCOM_X86_16_WITH_PRAGMAS
+#pragma aux ASMAtomicCmpXchgU8 = \
+ ".486" \
+ "lock cmpxchg es:[bx], cl" \
+ "setz al" \
+ parm [es bx] [cl] [al] \
+ value [al] \
+ modify exact [al];
+#endif
+
+#undef ASMAtomicCmpXchgU16
+#ifdef IPRT_ASM_WATCOM_X86_16_WITH_PRAGMAS
+#pragma aux ASMAtomicCmpXchgU16 = \
+ ".486" \
+ "lock cmpxchg es:[bx], cx" \
+ "setz al" \
+ parm [es bx] [cx] [ax] \
+ value [al] \
+ modify exact [ax];
+#endif
+
+#undef ASMAtomicCmpXchgU32
+#ifdef IPRT_ASM_WATCOM_X86_16_WITH_PRAGMAS
+#pragma aux ASMAtomicCmpXchgU32 = \
+ ".486" \
+ "shl ecx, 16" \
+ "mov cx, dx" \
+ "shl eax, 16" \
+ "mov ax, di" \
+ "rol eax, 16" \
+ "lock cmpxchg es:[bx], ecx" \
+ "setz al" \
+ parm [es bx] [cx dx] [ax di] \
+ value [al] \
+ modify exact [ax cx];
+#endif
+
+/* ASMAtomicCmpXchgU64: External assembly implementation, too few registers for parameters. */
+/* ASMAtomicCmpXchgExU32: External assembly implementation, too few registers for parameters. */
+/* ASMAtomicCmpXchgExU64: External assembly implementation, too few registers for parameters. */
+
+#undef ASMSerializeInstructionCpuId
+#ifdef IPRT_ASM_WATCOM_X86_16_WITH_PRAGMAS
+#pragma aux ASMSerializeInstructionCpuId = \
+ ".586" \
+ "xor eax, eax" \
+ "cpuid" \
+ parm [] \
+ modify exact [ax bx cx dx];
+#endif
+
+#undef ASMSerializeInstructionIRet
+#ifdef IPRT_ASM_WATCOM_X86_16_WITH_PRAGMAS
+#pragma aux ASMSerializeInstructionIRet = \
+ "pushf" \
+ "push cs" \
+ "call foo" /* 'push offset done' doesn't work */ \
+ "jmp done" \
+ "foo:" \
+ "iret" \
+ "done:" \
+ parm [] \
+ modify exact [];
+#endif
+
+#undef ASMSerializeInstructionRdTscp
+#ifdef IPRT_ASM_WATCOM_X86_16_WITH_PRAGMAS
+#pragma aux ASMSerializeInstructionRdTscp = \
+ 0x0f 0x01 0xf9 \
+ parm [] \
+ modify exact [ax dx cx];
+#endif
+
+#undef ASMAtomicReadU64
+#ifdef IPRT_ASM_WATCOM_X86_16_WITH_PRAGMAS
+#pragma aux ASMAtomicReadU64 = \
+ ".586" \
+ "xor eax, eax" \
+ "xor edx, edx" \
+ "xor ebx, ebx" \
+ "xor ecx, ecx" \
+ "lock cmpxchg8b es:[si]" \
+ "xchg eax, edx" \
+ "mov ebx, eax" \
+ "shr eax, 16" \
+ "mov ecx, edx" \
+ "shr ecx, 16" \
+ parm [es si] \
+ value [dx cx bx ax] \
+ modify exact [dx cx bx ax];
+#endif
+
+#undef ASMAtomicUoReadU64
+#ifdef IPRT_ASM_WATCOM_X86_16_WITH_PRAGMAS
+#pragma aux ASMAtomicUoReadU64 = \
+ ".586" \
+ "xor eax, eax" \
+ "xor edx, edx" \
+ "xor ebx, ebx" \
+ "xor ecx, ecx" \
+ "lock cmpxchg8b es:[si]" \
+ "xchg eax, edx" \
+ "mov ebx, eax" \
+ "shr eax, 16" \
+ "mov ecx, edx" \
+ "shr ecx, 16" \
+ parm [es si] \
+ value [dx cx bx ax] \
+ modify exact [dx cx bx ax];
+#endif
+
+#undef ASMAtomicAddU16
+#ifdef IPRT_ASM_WATCOM_X86_16_WITH_PRAGMAS
+#pragma aux ASMAtomicAddU16 = \
+ ".486" \
+ "lock xadd es:[bx], ax" \
+ parm [es bx] [ax] \
+ value [ax] \
+ modify exact [ax];
+#endif
+
+#undef ASMAtomicAddU32
+#ifdef IPRT_ASM_WATCOM_X86_16_WITH_PRAGMAS
+#pragma aux ASMAtomicAddU32 = \
+ ".486" \
+ "shl edx, 16" \
+ "mov dx, ax" \
+ "lock xadd es:[bx], edx" \
+ "mov ax, dx" \
+ "shr edx, 16" \
+ parm [es bx] [ax dx] \
+ value [ax dx] \
+ modify exact [ax dx];
+#endif
+
+#undef ASMAtomicIncU16
+#ifdef IPRT_ASM_WATCOM_X86_16_WITH_PRAGMAS
+#pragma aux ASMAtomicIncU16 = \
+ ".486" \
+ "mov ax, 1" \
+ "lock xadd es:[bx], ax" \
+ "inc ax" \
+ parm [es bx] \
+ value [ax] \
+ modify exact [ax];
+#endif
+
+#undef ASMAtomicIncU32
+#ifdef IPRT_ASM_WATCOM_X86_16_WITH_PRAGMAS
+#pragma aux ASMAtomicIncU32 = \
+ ".486" \
+ "mov edx, 1" \
+ "lock xadd es:[bx], edx" \
+ "inc edx" \
+ "mov ax, dx" \
+ "shr edx, 16" \
+ parm [es bx] \
+ value [ax dx] \
+ modify exact [ax dx];
+#endif
+
+/* ASMAtomicIncU64: Should be done by C inline or in external file. */
+
+#undef ASMAtomicDecU16
+#ifdef IPRT_ASM_WATCOM_X86_16_WITH_PRAGMAS
+#pragma aux ASMAtomicDecU16 = \
+ ".486" \
+ "mov ax, 0ffffh" \
+ "lock xadd es:[bx], ax" \
+ "dec ax" \
+ parm [es bx] \
+ value [ax] \
+ modify exact [ax];
+#endif
+
+#undef ASMAtomicDecU32
+#ifdef IPRT_ASM_WATCOM_X86_16_WITH_PRAGMAS
+#pragma aux ASMAtomicDecU32 = \
+ ".486" \
+ "mov edx, 0ffffffffh" \
+ "lock xadd es:[bx], edx" \
+ "dec edx" \
+ "mov ax, dx" \
+ "shr edx, 16" \
+ parm [es bx] \
+ value [ax dx] \
+ modify exact [ax dx];
+#endif
+
+/* ASMAtomicDecU64: Should be done by C inline or in external file. */
+
+#undef ASMAtomicOrU32
+#ifdef IPRT_ASM_WATCOM_X86_16_WITH_PRAGMAS
+#pragma aux ASMAtomicOrU32 = \
+ ".386" \
+ "shl edx, 16" \
+ "mov dx, ax" \
+ "lock or es:[bx], edx" \
+ parm [es bx] [ax dx] \
+ modify exact [dx];
+#endif
+
+/* ASMAtomicOrU64: Should be done by C inline or in external file. */
+
+#undef ASMAtomicAndU32
+#ifdef IPRT_ASM_WATCOM_X86_16_WITH_PRAGMAS
+#pragma aux ASMAtomicAndU32 = \
+ ".386" \
+ "shl edx, 16" \
+ "mov dx, ax" \
+ "lock and es:[bx], edx" \
+ parm [es bx] [ax dx] \
+ modify exact [dx];
+#endif
+
+/* ASMAtomicAndU64: Should be done by C inline or in external file. */
+
+#undef ASMAtomicUoOrU32
+#ifdef IPRT_ASM_WATCOM_X86_16_WITH_PRAGMAS
+#pragma aux ASMAtomicUoOrU32 = \
+ ".386" \
+ "shl edx, 16" \
+ "mov dx, ax" \
+ "or es:[bx], edx" \
+ parm [es bx] [ax dx] \
+ modify exact [dx];
+#endif
+
+/* ASMAtomicUoOrU64: Should be done by C inline or in external file. */
+
+#undef ASMAtomicUoAndU32
+#ifdef IPRT_ASM_WATCOM_X86_16_WITH_PRAGMAS
+#pragma aux ASMAtomicUoAndU32 = \
+ ".386" \
+ "shl edx, 16" \
+ "mov dx, ax" \
+ "and es:[bx], edx" \
+ parm [es bx] [ax dx] \
+ modify exact [dx];
+#endif
+
+/* ASMAtomicUoAndU64: Should be done by C inline or in external file. */
+
+#undef ASMAtomicUoIncU32
+#ifdef IPRT_ASM_WATCOM_X86_16_WITH_PRAGMAS
+#pragma aux ASMAtomicUoIncU32 = \
+ ".486" \
+ "mov edx, 1" \
+ "xadd es:[bx], edx" \
+ "inc edx" \
+ "mov ax, dx" \
+ "shr edx, 16" \
+ parm [es bx] \
+ value [ax dx] \
+ modify exact [ax dx];
+#endif
+
+#undef ASMAtomicUoDecU32
+#ifdef IPRT_ASM_WATCOM_X86_16_WITH_PRAGMAS
+#pragma aux ASMAtomicUoDecU32 = \
+ ".486" \
+ "mov edx, 0ffffffffh" \
+ "xadd es:[bx], edx" \
+ "dec edx" \
+ "mov ax, dx" \
+ "shr edx, 16" \
+ parm [es bx] \
+ value [ax dx] \
+ modify exact [ax dx];
+#endif
+
+#undef ASMMemZeroPage
+#ifdef IPRT_ASM_WATCOM_X86_16_WITH_PRAGMAS
+# if defined(__SW_0) || defined(__SW_1) || defined(__SW_2)
+# pragma aux ASMMemZeroPage = \
+ "mov cx, 2048" \
+ "xor ax, ax" \
+ "rep stosw" \
+ parm [es di] \
+ modify exact [ax cx di];
+# else
+# pragma aux ASMMemZeroPage = \
+ "mov ecx, 1024" \
+ "xor eax, eax" \
+ "rep stosd" \
+ parm [es di] \
+ modify exact [ax cx di];
+# endif
+#endif
+
+#undef ASMMemZero32
+#ifdef IPRT_ASM_WATCOM_X86_16_WITH_PRAGMAS
+# if defined(__SW_0) || defined(__SW_1) || defined(__SW_2)
+# pragma aux ASMMemZero32 = \
+ "xor ax, ax" \
+ "shr cx, 1" \
+ "shr cx, 1" \
+ "rep stosw" \
+ parm [es di] [cx] \
+ modify exact [ax dx cx di];
+# else
+# pragma aux ASMMemZero32 = \
+ "and ecx, 0ffffh" /* probably not necessary, lazy bird should check... */ \
+ "shr ecx, 2" \
+ "xor eax, eax" \
+ "rep stosd" \
+ parm [es di] [cx] \
+ modify exact [ax cx di];
+# endif
+#endif
+
+#undef ASMMemFill32
+#ifdef IPRT_ASM_WATCOM_X86_16_WITH_PRAGMAS
+# if defined(__SW_0) || defined(__SW_1) || defined(__SW_2)
+# pragma aux ASMMemFill32 = \
+ " shr cx, 1" \
+ " shr cx, 1" \
+ " jz done" \
+ "again:" \
+ " stosw" \
+ " xchg ax, dx" \
+ " stosw" \
+ " xchg ax, dx" \
+ " dec cx" \
+ " jnz again" \
+ "done:" \
+ parm [es di] [cx] [ax dx]\
+ modify exact [cx di];
+# else
+# pragma aux ASMMemFill32 = \
+ "and ecx, 0ffffh" /* probably not necessary, lazy bird should check... */ \
+ "shr ecx, 2" \
+ "shl eax, 16" \
+ "mov ax, dx" \
+ "rol eax, 16" \
+ "rep stosd" \
+ parm [es di] [cx] [ax dx]\
+ modify exact [ax cx di];
+# endif
+#endif
+
+#undef ASMProbeReadByte
+#ifdef IPRT_ASM_WATCOM_X86_16_WITH_PRAGMAS
+#pragma aux ASMProbeReadByte = \
+ "mov al, es:[bx]" \
+ parm [es bx] \
+ value [al] \
+ modify exact [al];
+#endif
+
+#undef ASMBitSet
+#ifdef IPRT_ASM_WATCOM_X86_16_WITH_PRAGMAS
+# if defined(__SW_0) || defined(__SW_1) || defined(__SW_2)
+# pragma aux ASMBitSet = \
+ " mov ch, cl" /* Only the three lowest bits are relevant due to 64KB segments */ \
+ " mov cl, 5" \
+ " shl ch, cl" \
+ " add bh, ch" /* Adjust the pointer. */ \
+ " mov cl, al" \
+ " shr ax, 1" /* convert to byte offset */ \
+ " shr ax, 1" \
+ " shr ax, 1" \
+ " add bx, ax" /* adjust pointer again */\
+ " and cl, 7" \
+ " mov al, 1" \
+ " shl al, cl" /* al=bitmask */ \
+ " or es:[bx], al" \
+ parm [es bx] [ax cx] \
+ modify exact [ax bx cx];
+# else
+# pragma aux ASMBitSet = \
+ "shl edx, 16" \
+ "mov dx, ax" \
+ "bts es:[bx], edx" \
+ parm [es bx] [ax dx] \
+ modify exact [dx];
+# endif
+#endif
+
+#undef ASMAtomicBitSet
+#ifdef IPRT_ASM_WATCOM_X86_16_WITH_PRAGMAS
+#pragma aux ASMAtomicBitSet = \
+ ".386" \
+ "shl edx, 16" \
+ "mov dx, ax" \
+ "lock bts es:[bx], edx" \
+ parm [es bx] [ax dx] \
+ modify exact [dx];
+#endif
+
+#undef ASMBitClear
+#ifdef IPRT_ASM_WATCOM_X86_16_WITH_PRAGMAS
+# if defined(__SW_0) || defined(__SW_1) || defined(__SW_2)
+# pragma aux ASMBitClear = \
+ " mov ch, cl" /* Only the three lowest bits are relevant due to 64KB segments */ \
+ " mov cl, 5" \
+ " shl ch, cl" \
+ " add bh, ch" /* Adjust the pointer. */ \
+ " mov cl, al" \
+ " shr ax, 1" /* convert to byte offset */ \
+ " shr ax, 1" \
+ " shr ax, 1" \
+ " add bx, ax" /* adjust pointer again */\
+ " and cl, 7" \
+ " mov al, 1" \
+ " shl al, cl" \
+ " not al" /* al=bitmask */ \
+ " and es:[bx], al" \
+ parm [es bx] [ax cx] \
+ modify exact [ax bx cx];
+# else
+# pragma aux ASMBitClear = \
+ "shl edx, 16" \
+ "mov dx, ax" \
+ "btr es:[bx], edx" \
+ parm [es bx] [ax dx] \
+ modify exact [dx];
+# endif
+#endif
+
+#undef ASMAtomicBitClear
+#ifdef IPRT_ASM_WATCOM_X86_16_WITH_PRAGMAS
+#pragma aux ASMAtomicBitClear = \
+ ".386" \
+ "shl edx, 16" \
+ "mov dx, ax" \
+ "lock btr es:[bx], edx" \
+ parm [es bx] [ax dx] \
+ modify exact [dx];
+#endif
+
+#undef ASMBitToggle
+#ifdef IPRT_ASM_WATCOM_X86_16_WITH_PRAGMAS
+# if defined(__SW_0) || defined(__SW_1) || defined(__SW_2)
+# pragma aux ASMBitToggle = \
+ " mov ch, cl" /* Only the three lowest bits are relevant due to 64KB segments */ \
+ " mov cl, 5" \
+ " shl ch, cl" \
+ " add bh, ch" /* Adjust the pointer. */ \
+ " mov cl, al" \
+ " shr ax, 1" /* convert to byte offset */ \
+ " shr ax, 1" \
+ " shr ax, 1" \
+ " add bx, ax" /* adjust pointer again */\
+ " and cl, 7" \
+ " mov al, 1" \
+ " shl al, cl" /* al=bitmask */ \
+ " xor es:[bx], al" \
+ parm [es bx] [ax cx] \
+ modify exact [ax bx cx];
+# else
+# pragma aux ASMBitToggle = \
+ "shl edx, 16" \
+ "mov dx, ax" \
+ "btc es:[bx], edx" \
+ parm [es bx] [ax dx] \
+ modify exact [dx];
+# endif
+#endif
+
+#undef ASMAtomicBitToggle
+#ifdef IPRT_ASM_WATCOM_X86_16_WITH_PRAGMAS
+#pragma aux ASMAtomicBitToggle = \
+ ".386" \
+ "shl edx, 16" \
+ "mov dx, ax" \
+ "lock btc es:[bx], edx" \
+ parm [es bx] [ax dx] \
+ modify exact [dx];
+#endif
+
+#undef ASMBitTestAndSet
+#ifdef IPRT_ASM_WATCOM_X86_16_WITH_PRAGMAS
+# if defined(__SW_0) || defined(__SW_1) || defined(__SW_2)
+# pragma aux ASMBitTestAndSet = \
+ " mov ch, cl" /* Only the three lowest bits are relevant due to 64KB segments */ \
+ " mov cl, 5" \
+ " shl ch, cl" \
+ " add bh, ch" /* Adjust the pointer. */ \
+ " mov cl, al" \
+ " shr ax, 1" /* convert to byte offset */ \
+ " shr ax, 1" \
+ " shr ax, 1" \
+ " add bx, ax" /* adjust pointer again */\
+ " and cl, 7" /* cl=byte shift count */ \
+ " mov ah, 1" \
+ " shl ah, cl" /* ah=bitmask */ \
+ " mov al, es:[bx]" \
+ " or ah, al" \
+ " mov es:[bx], ah" \
+ " shr al, cl" \
+ " and al, 1" \
+ parm [es bx] [ax cx] \
+ value [al] \
+ modify exact [ax bx cx];
+# else
+# pragma aux ASMBitTestAndSet = \
+ "shl edx, 16" \
+ "mov dx, ax" \
+ "bts es:[bx], edx" \
+ "setc al" \
+ parm [es bx] [ax dx] \
+ value [al] \
+ modify exact [ax dx];
+# endif
+#endif
+
+#undef ASMAtomicBitTestAndSet
+#ifdef IPRT_ASM_WATCOM_X86_16_WITH_PRAGMAS
+#pragma aux ASMAtomicBitTestAndSet = \
+ ".386" \
+ "shl edx, 16" \
+ "mov dx, ax" \
+ "lock bts es:[bx], edx" \
+ "setc al" \
+ parm [es bx] [ax dx] \
+ value [al] \
+ modify exact [ax dx];
+#endif
+
+#undef ASMBitTestAndClear
+#ifdef IPRT_ASM_WATCOM_X86_16_WITH_PRAGMAS
+# if defined(__SW_0) || defined(__SW_1) || defined(__SW_2)
+# pragma aux ASMBitTestAndClear = \
+ " mov ch, cl" /* Only the three lowest bits are relevant due to 64KB segments */ \
+ " mov cl, 5" \
+ " shl ch, cl" \
+ " add bh, ch" /* Adjust the pointer. */ \
+ " mov cl, al" \
+ " shr ax, 1" /* convert to byte offset */ \
+ " shr ax, 1" \
+ " shr ax, 1" \
+ " add bx, ax" /* adjust pointer again */\
+ " and cl, 7" /* cl=byte shift count */ \
+ " mov ah, 1" \
+ " shl ah, cl" \
+ " not ah" /* ah=bitmask */ \
+ " mov al, es:[bx]" \
+ " and ah, al" \
+ " mov es:[bx], ah" \
+ " shr al, cl" \
+ " and al, 1" \
+ parm [es bx] [ax cx] \
+ value [al] \
+ modify exact [ax bx cx];
+# else
+# pragma aux ASMBitTestAndClear = \
+ "shl edx, 16" \
+ "mov dx, ax" \
+ "btr es:[bx], edx" \
+ "setc al" \
+ parm [es bx] [ax dx] \
+ value [al] \
+ modify exact [ax dx];
+# endif
+#endif
+
+#undef ASMAtomicBitTestAndClear
+#ifdef IPRT_ASM_WATCOM_X86_16_WITH_PRAGMAS
+#pragma aux ASMAtomicBitTestAndClear = \
+ ".386" \
+ "shl edx, 16" \
+ "mov dx, ax" \
+ "lock btr es:[bx], edx" \
+ "setc al" \
+ parm [es bx] [ax dx] \
+ value [al] \
+ modify exact [ax dx];
+#endif
+
+#undef ASMBitTestAndToggle
+#ifdef IPRT_ASM_WATCOM_X86_16_WITH_PRAGMAS
+# if defined(__SW_0) || defined(__SW_1) || defined(__SW_2)
+# pragma aux ASMBitTestAndToggle = \
+ " mov ch, cl" /* Only the three lowest bits are relevant due to 64KB segments */ \
+ " mov cl, 5" \
+ " shl ch, cl" \
+ " add bh, ch" /* Adjust the pointer. */ \
+ " mov cl, al" \
+ " shr ax, 1" /* convert to byte offset */ \
+ " shr ax, 1" \
+ " shr ax, 1" \
+ " add bx, ax" /* adjust pointer again */\
+ " and cl, 7" /* cl=byte shift count */ \
+ " mov ah, 1" \
+ " shl ah, cl" /* ah=bitmask */ \
+ " mov al, es:[bx]" \
+ " xor ah, al" \
+ " mov es:[bx], ah" \
+ " shr al, cl" \
+ " and al, 1" \
+ parm [es bx] [ax cx] \
+ value [al] \
+ modify exact [ax bx cx];
+# else
+# pragma aux ASMBitTestAndToggle = \
+ "shl edx, 16" \
+ "mov dx, ax" \
+ "btc es:[bx], edx" \
+ "setc al" \
+ parm [es bx] [ax dx] \
+ value [al] \
+ modify exact [ax dx];
+# endif
+#endif
+
+#undef ASMAtomicBitTestAndToggle
+#ifdef IPRT_ASM_WATCOM_X86_16_WITH_PRAGMAS
+#pragma aux ASMAtomicBitTestAndToggle = \
+ ".386" \
+ "shl edx, 16" \
+ "mov dx, ax" \
+ "lock btc es:[bx], edx" \
+ "setc al" \
+ parm [es bx] [ax dx] \
+ value [al] \
+ modify exact [ax dx];
+#endif
+
+#undef ASMBitTest
+#ifdef IPRT_ASM_WATCOM_X86_16_WITH_PRAGMAS
+# if defined(__SW_0) || defined(__SW_1) || defined(__SW_2)
+# pragma aux ASMBitTest = \
+ " mov ch, cl" /* Only the three lowest bits are relevant due to 64KB segments */ \
+ " mov cl, 5" \
+ " shl ch, cl" \
+ " add bh, ch" /* Adjust the pointer. */ \
+ " mov cl, al" \
+ " shr ax, 1" /* convert to byte offset */ \
+ " shr ax, 1" \
+ " shr ax, 1" \
+ " add bx, ax" /* adjust pointer again */\
+ " and cl, 7" \
+ " mov al, es:[bx]" \
+ " shr al, cl" \
+ " and al, 1" \
+ parm [es bx] [ax cx] \
+ value [al] \
+ modify exact [ax bx cx];
+# else
+# pragma aux ASMBitTest = \
+ "shl edx, 16" \
+ "mov dx, ax" \
+ "bt es:[bx], edx" \
+ "setc al" \
+ parm [es bx] [ax dx] nomemory \
+ value [al] \
+ modify exact [ax dx] nomemory;
+# endif
+#endif
+
+/* ASMBitFirstClear: External file. */
+/* ASMBitNextClear: External file. */
+/* ASMBitFirstSet: External file. */
+/* ASMBitNextSet: External file. */
+
+#if defined(__SW_0) || defined(__SW_1) || defined(__SW_2)
+/* ASMBitFirstSetU32: External file. */
+#else
+# undef ASMBitFirstSetU32
+# ifdef IPRT_ASM_WATCOM_X86_16_WITH_PRAGMAS
+# pragma aux ASMBitFirstSetU32 = \
+ "shl edx, 16" \
+ "mov dx, ax" \
+ "bsf eax, edx" \
+ "jz not_found" \
+ "inc ax" \
+ "jmp done" \
+ "not_found:" \
+ "xor ax, ax" \
+ "done:" \
+ parm [ax dx] nomemory \
+ value [ax] \
+ modify exact [ax dx] nomemory;
+# endif
+#endif
+
+#if defined(__SW_0) || defined(__SW_1) || defined(__SW_2)
+/* ASMBitFirstSetU64: External file. */
+#else
+# undef ASMBitFirstSetU64
+# ifdef IPRT_ASM_WATCOM_X86_16_WITH_PRAGMAS
+# pragma aux ASMBitFirstSetU64 = \
+ ".386" \
+ "shl ecx, 16" \
+ "mov cx, dx" \
+ "bsf ecx, ecx" \
+ "jz not_found_low" \
+ "mov ax, cx" \
+ "inc ax" \
+ "jmp done" \
+ \
+ "not_found_low:" \
+ "shr eax, 16" \
+ "mov ax, bx" \
+ "bsf eax, eax" \
+ "jz not_found_high" \
+ "add ax, 33" \
+ "jmp done" \
+ \
+ "not_found_high:" \
+ "xor ax, ax" \
+ "done:" \
+ parm [dx cx bx ax] nomemory \
+ value [ax] \
+ modify exact [ax cx] nomemory;
+# endif
+#endif
+
+#if defined(__SW_0) || defined(__SW_1) || defined(__SW_2)
+/* ASMBitFirstSetU16: External file. */
+#else
+# undef ASMBitFirstSetU16
+# ifdef IPRT_ASM_WATCOM_X86_16_WITH_PRAGMAS
+# pragma aux ASMBitFirstSetU16 = \
+ "bsf ax, ax" \
+ "jz not_found" \
+ "inc ax" \
+ "jmp done" \
+ "not_found:" \
+ "xor ax, ax" \
+ "done:" \
+ parm [ax] nomemory \
+ value [ax] \
+ modify exact [ax] nomemory;
+# endif
+#endif
+
+#if defined(__SW_0) || defined(__SW_1) || defined(__SW_2)
+/* ASMBitLastSetU32: External file. */
+#else
+# undef ASMBitLastSetU32
+# ifdef IPRT_ASM_WATCOM_X86_16_WITH_PRAGMAS
+# pragma aux ASMBitLastSetU32 = \
+ "shl edx, 16" \
+ "mov dx, ax" \
+ "bsr eax, edx" \
+ "jz not_found" \
+ "inc ax" \
+ "jmp done" \
+ "not_found:" \
+ "xor ax, ax" \
+ "done:" \
+ parm [ax dx] nomemory \
+ value [ax] \
+ modify exact [ax dx] nomemory;
+# endif
+#endif
+
+#if defined(__SW_0) || defined(__SW_1) || defined(__SW_2)
+/* ASMBitLastSetU64: External file. */
+#else
+# undef ASMBitLastSetU64
+# ifdef IPRT_ASM_WATCOM_X86_16_WITH_PRAGMAS
+# pragma aux ASMBitLastSetU64 = \
+ ".386" \
+ "shl ecx, 16" \
+ "mov cx, dx" \
+ "bsf ecx, ecx" \
+ "jz not_found_low" \
+ "mov ax, cx" \
+ "inc ax" \
+ "jmp done" \
+ \
+ "not_found_low:" \
+ "shr eax, 16" \
+ "mov ax, bx" \
+ "bsf eax, eax" \
+ "jz not_found_high" \
+ "add ax, 33" \
+ "jmp done" \
+ \
+ "not_found_high:" \
+ "xor ax, ax" \
+ "done:" \
+ parm [dx cx bx ax] nomemory \
+ value [ax] \
+ modify exact [ax cx] nomemory;
+# endif
+#endif
+
+#if defined(__SW_0) || defined(__SW_1) || defined(__SW_2)
+/* ASMBitLastSetU16: External file. */
+#else
+# undef ASMBitLastSetU16
+# ifdef IPRT_ASM_WATCOM_X86_16_WITH_PRAGMAS
+# pragma aux ASMBitLastSetU16 = \
+ "bsr ax, ax" \
+ "jz not_found" \
+ "inc ax" \
+ "jmp done" \
+ "not_found:" \
+ "xor ax, ax" \
+ "done:" \
+ parm [ax] nomemory \
+ value [ax] \
+ modify exact [ax] nomemory;
+# endif
+#endif
+
+#undef ASMByteSwapU16
+#ifdef IPRT_ASM_WATCOM_X86_16_WITH_PRAGMAS
+#pragma aux ASMByteSwapU16 = \
+ "xchg al, ah" \
+ parm [ax] nomemory \
+ value [ax] \
+ modify exact [ax] nomemory;
+#endif
+
+#undef ASMByteSwapU32
+#ifdef IPRT_ASM_WATCOM_X86_16_WITH_PRAGMAS
+#pragma aux ASMByteSwapU32 = \
+ "xchg dh, al" \
+ "xchg dl, ah" \
+ parm [ax dx] nomemory \
+ value [ax dx] \
+ modify exact [ax dx] nomemory;
+#endif
+
+#undef ASMRotateLeftU32
+#ifdef IPRT_ASM_WATCOM_X86_16_WITH_PRAGMAS
+#pragma aux ASMRotateLeftU32 = \
+ ".386" \
+ "shl edx, 16" \
+ "mov dx, ax" \
+ "rol edx, cl" \
+ "mov eax, edx" \
+ "shr edx, 16" \
+ parm [ax dx] [cx] nomemory \
+ value [ax dx] \
+ modify exact [ax dx] nomemory;
+#endif
+
+#undef ASMRotateRightU32
+#ifdef IPRT_ASM_WATCOM_X86_16_WITH_PRAGMAS
+#pragma aux ASMRotateRightU32 = \
+ ".386" \
+ "shl edx, 16" \
+ "mov dx, ax" \
+ "ror edx, cl" \
+ "mov eax, edx" \
+ "shr edx, 16" \
+ parm [ax dx] [cx] nomemory \
+ value [ax dx] \
+ modify exact [ax dx] nomemory;
+#endif
+
+#endif /* !IPRT_INCLUDED_asm_watcom_x86_16_h */
diff --git a/include/iprt/asm-watcom-x86-32.h b/include/iprt/asm-watcom-x86-32.h
new file mode 100644
index 00000000..e52c59b2
--- /dev/null
+++ b/include/iprt/asm-watcom-x86-32.h
@@ -0,0 +1,741 @@
+/** @file
+ * IPRT - Assembly Functions, x86 32-bit Watcom C/C++ pragma aux.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_asm_watcom_x86_32_h
+#define IPRT_INCLUDED_asm_watcom_x86_32_h
+/* no pragma once */
+
+#ifndef IPRT_INCLUDED_asm_h
+# error "Don't include this header directly."
+#endif
+
+#ifndef __FLAT__
+# error "Only works with flat pointers! (-mf)"
+#endif
+
+/*
+ * Note! The #undef that preceds the #pragma aux statements is for undoing
+ * the mangling, because the symbol in #pragma aux [symbol] statements
+ * doesn't get subjected to preprocessing. This is also why we include
+ * the watcom header at both the top and the bottom of asm.h file.
+ */
+
+#undef ASMCompilerBarrier
+#ifdef IPRT_ASM_WATCOM_X86_32_WITH_PRAGMAS
+# if 0 /* overkill version. */
+# pragma aux ASMCompilerBarrier = \
+ "nop" \
+ parm [] \
+ modify exact [eax ebx ecx edx es ds fs gs];
+# else
+# pragma aux ASMCompilerBarrier = \
+ "" \
+ parm [] \
+ modify exact [];
+# endif
+#endif
+
+#undef ASMNopPause
+#ifdef IPRT_ASM_WATCOM_X86_32_WITH_PRAGMAS
+#pragma aux ASMNopPause = \
+ ".686p" \
+ ".xmm2" \
+ "pause" \
+ parm [] nomemory \
+ modify exact [] nomemory;
+#endif
+
+#undef ASMAtomicXchgU8
+#ifdef IPRT_ASM_WATCOM_X86_32_WITH_PRAGMAS
+#pragma aux ASMAtomicXchgU8 = \
+ "xchg [ecx], al" \
+ parm [ecx] [al] \
+ value [al] \
+ modify exact [al];
+#endif
+
+#undef ASMAtomicXchgU16
+#ifdef IPRT_ASM_WATCOM_X86_32_WITH_PRAGMAS
+#pragma aux ASMAtomicXchgU16 = \
+ "xchg [ecx], ax" \
+ parm [ecx] [ax] \
+ value [ax] \
+ modify exact [ax];
+#endif
+
+#undef ASMAtomicXchgU32
+#ifdef IPRT_ASM_WATCOM_X86_32_WITH_PRAGMAS
+#pragma aux ASMAtomicXchgU32 = \
+ "xchg [ecx], eax" \
+ parm [ecx] [eax] \
+ value [eax] \
+ modify exact [eax];
+#endif
+
+#undef ASMAtomicXchgU64
+#ifdef IPRT_ASM_WATCOM_X86_32_WITH_PRAGMAS
+#pragma aux ASMAtomicXchgU64 = \
+ ".586" \
+ "try_again:" \
+ "lock cmpxchg8b [esi]" \
+ "jnz try_again" \
+ parm [esi] [ebx ecx] \
+ value [eax edx] \
+ modify exact [edx ecx ebx eax];
+#endif
+
+#undef ASMAtomicCmpXchgU8
+#ifdef IPRT_ASM_WATCOM_X86_32_WITH_PRAGMAS
+#pragma aux ASMAtomicCmpXchgU8 = \
+ ".486" \
+ "lock cmpxchg [edx], cl" \
+ "setz al" \
+ parm [edx] [cl] [al] \
+ value [al] \
+ modify exact [al];
+#endif
+
+#undef ASMAtomicCmpXchgU16
+#ifdef IPRT_ASM_WATCOM_X86_32_WITH_PRAGMAS
+#pragma aux ASMAtomicCmpXchgU16 = \
+ ".486" \
+ "lock cmpxchg [edx], cx" \
+ "setz al" \
+ parm [edx] [cx] [ax] \
+ value [al] \
+ modify exact [ax];
+#endif
+
+#undef ASMAtomicCmpXchgU32
+#ifdef IPRT_ASM_WATCOM_X86_32_WITH_PRAGMAS
+#pragma aux ASMAtomicCmpXchgU32 = \
+ ".486" \
+ "lock cmpxchg [edx], ecx" \
+ "setz al" \
+ parm [edx] [ecx] [eax] \
+ value [al] \
+ modify exact [eax];
+#endif
+
+#undef ASMAtomicCmpXchgU64
+#ifdef IPRT_ASM_WATCOM_X86_32_WITH_PRAGMAS
+#pragma aux ASMAtomicCmpXchgU64 = \
+ ".586" \
+ "lock cmpxchg8b [edi]" \
+ "setz al" \
+ parm [edi] [ebx ecx] [eax edx] \
+ value [al] \
+ modify exact [eax edx];
+#endif
+
+#undef ASMAtomicCmpXchgExU32
+#ifdef IPRT_ASM_WATCOM_X86_32_WITH_PRAGMAS
+#pragma aux ASMAtomicCmpXchgExU32 = \
+ ".586" \
+ "lock cmpxchg [edx], ecx" \
+ "mov [edi], eax" \
+ "setz al" \
+ parm [edx] [ecx] [eax] [edi] \
+ value [al] \
+ modify exact [eax];
+#endif
+
+#undef ASMAtomicCmpXchgExU64
+#ifdef IPRT_ASM_WATCOM_X86_32_WITH_PRAGMAS
+#pragma aux ASMAtomicCmpXchgExU64 = \
+ ".586" \
+ "lock cmpxchg8b [edi]" \
+ "mov [esi], eax" \
+ "mov [esi + 4], edx" \
+ "setz al" \
+ parm [edi] [ebx ecx] [eax edx] [esi] \
+ value [al] \
+ modify exact [eax edx];
+#endif
+
+#undef ASMSerializeInstructionCpuId
+#ifdef IPRT_ASM_WATCOM_X86_32_WITH_PRAGMAS
+#pragma aux ASMSerializeInstructionCpuId = \
+ ".586" \
+ "xor eax, eax" \
+ "cpuid" \
+ parm [] \
+ modify exact [eax ebx ecx edx];
+#endif
+
+#undef ASMSerializeInstructionIRet
+#ifdef IPRT_ASM_WATCOM_X86_32_WITH_PRAGMAS
+#pragma aux ASMSerializeInstructionIRet = \
+ "pushf" \
+ "push cs" \
+ "call foo" /* 'push offset done' doesn't work */ \
+ "jmp done" \
+ "foo:" \
+ "iret" \
+ "done:" \
+ parm [] \
+ modify exact [];
+#endif
+
+#undef ASMSerializeInstructionRdTscp
+#ifdef IPRT_ASM_WATCOM_X86_32_WITH_PRAGMAS
+#pragma aux ASMSerializeInstructionRdTscp = \
+ 0x0f 0x01 0xf9 \
+ parm [] \
+ modify exact [eax edx ecx];
+#endif
+
+#undef ASMAtomicReadU64
+#ifdef IPRT_ASM_WATCOM_X86_32_WITH_PRAGMAS
+#pragma aux ASMAtomicReadU64 = \
+ ".586" \
+ "xor eax, eax" \
+ "mov edx, eax" \
+ "mov ebx, eax" \
+ "mov ecx, eax" \
+ "lock cmpxchg8b [edi]" \
+ parm [edi] \
+ value [eax edx] \
+ modify exact [eax ebx ecx edx];
+#endif
+
+#undef ASMAtomicUoReadU64
+#ifdef IPRT_ASM_WATCOM_X86_32_WITH_PRAGMAS
+#pragma aux ASMAtomicUoReadU64 = \
+ ".586" \
+ "xor eax, eax" \
+ "mov edx, eax" \
+ "mov ebx, eax" \
+ "mov ecx, eax" \
+ "lock cmpxchg8b [edi]" \
+ parm [edi] \
+ value [eax edx] \
+ modify exact [eax ebx ecx edx];
+#endif
+
+#undef ASMAtomicAddU16
+#ifdef IPRT_ASM_WATCOM_X86_32_WITH_PRAGMAS
+#pragma aux ASMAtomicAddU16 = \
+ ".486" \
+ "lock xadd [ecx], ax" \
+ parm [ecx] [ax] \
+ value [ax] \
+ modify exact [ax];
+#endif
+
+#undef ASMAtomicAddU32
+#ifdef IPRT_ASM_WATCOM_X86_32_WITH_PRAGMAS
+#pragma aux ASMAtomicAddU32 = \
+ ".486" \
+ "lock xadd [ecx], eax" \
+ parm [ecx] [eax] \
+ value [eax] \
+ modify exact [eax];
+#endif
+
+#undef ASMAtomicIncU16
+#ifdef IPRT_ASM_WATCOM_X86_32_WITH_PRAGMAS
+#pragma aux ASMAtomicIncU16 = \
+ ".486" \
+ "mov ax, 1" \
+ "lock xadd [ecx], ax" \
+ "inc ax" \
+ parm [ecx] \
+ value [ax] \
+ modify exact [ax];
+#endif
+
+#undef ASMAtomicIncU32
+#ifdef IPRT_ASM_WATCOM_X86_32_WITH_PRAGMAS
+#pragma aux ASMAtomicIncU32 = \
+ ".486" \
+ "mov eax, 1" \
+ "lock xadd [ecx], eax" \
+ "inc eax" \
+ parm [ecx] \
+ value [eax] \
+ modify exact [eax];
+#endif
+
+/* ASMAtomicIncU64: Should be done by C inline or in external file. */
+
+#undef ASMAtomicDecU16
+#ifdef IPRT_ASM_WATCOM_X86_32_WITH_PRAGMAS
+#pragma aux ASMAtomicDecU16 = \
+ ".486" \
+ "mov ax, 0ffffh" \
+ "lock xadd [ecx], ax" \
+ "dec ax" \
+ parm [ecx] \
+ value [ax] \
+ modify exact [ax];
+#endif
+
+#undef ASMAtomicDecU32
+#ifdef IPRT_ASM_WATCOM_X86_32_WITH_PRAGMAS
+#pragma aux ASMAtomicDecU32 = \
+ ".486" \
+ "mov eax, 0ffffffffh" \
+ "lock xadd [ecx], eax" \
+ "dec eax" \
+ parm [ecx] \
+ value [eax] \
+ modify exact [eax];
+#endif
+
+/* ASMAtomicDecU64: Should be done by C inline or in external file. */
+
+#undef ASMAtomicOrU32
+#ifdef IPRT_ASM_WATCOM_X86_32_WITH_PRAGMAS
+#pragma aux ASMAtomicOrU32 = \
+ "lock or [ecx], eax" \
+ parm [ecx] [eax] \
+ modify exact [];
+#endif
+
+/* ASMAtomicOrU64: Should be done by C inline or in external file. */
+
+#undef ASMAtomicAndU32
+#ifdef IPRT_ASM_WATCOM_X86_32_WITH_PRAGMAS
+#pragma aux ASMAtomicAndU32 = \
+ "lock and [ecx], eax" \
+ parm [ecx] [eax] \
+ modify exact [];
+#endif
+
+/* ASMAtomicAndU64: Should be done by C inline or in external file. */
+
+#undef ASMAtomicUoOrU32
+#ifdef IPRT_ASM_WATCOM_X86_32_WITH_PRAGMAS
+#pragma aux ASMAtomicUoOrU32 = \
+ "or [ecx], eax" \
+ parm [ecx] [eax] \
+ modify exact [];
+#endif
+
+/* ASMAtomicUoOrU64: Should be done by C inline or in external file. */
+
+#undef ASMAtomicUoAndU32
+#ifdef IPRT_ASM_WATCOM_X86_32_WITH_PRAGMAS
+#pragma aux ASMAtomicUoAndU32 = \
+ "and [ecx], eax" \
+ parm [ecx] [eax] \
+ modify exact [];
+#endif
+
+/* ASMAtomicUoAndU64: Should be done by C inline or in external file. */
+
+#undef ASMAtomicUoIncU32
+#ifdef IPRT_ASM_WATCOM_X86_32_WITH_PRAGMAS
+#pragma aux ASMAtomicUoIncU32 = \
+ ".486" \
+ "xadd [ecx], eax" \
+ "inc eax" \
+ parm [ecx] \
+ value [eax] \
+ modify exact [eax];
+#endif
+
+#undef ASMAtomicUoDecU32
+#ifdef IPRT_ASM_WATCOM_X86_32_WITH_PRAGMAS
+#pragma aux ASMAtomicUoDecU32 = \
+ ".486" \
+ "mov eax, 0ffffffffh" \
+ "xadd [ecx], eax" \
+ "dec eax" \
+ parm [ecx] \
+ value [eax] \
+ modify exact [eax];
+#endif
+
+#undef ASMMemZeroPage
+#ifdef IPRT_ASM_WATCOM_X86_32_WITH_PRAGMAS
+#pragma aux ASMMemZeroPage = \
+ "mov ecx, 1024" \
+ "xor eax, eax" \
+ "rep stosd" \
+ parm [edi] \
+ modify exact [eax ecx edi];
+#endif
+
+#undef ASMMemZero32
+#ifdef IPRT_ASM_WATCOM_X86_32_WITH_PRAGMAS
+#pragma aux ASMMemZero32 = \
+ "shr ecx, 2" \
+ "xor eax, eax" \
+ "rep stosd" \
+ parm [edi] [ecx] \
+ modify exact [eax ecx edi];
+#endif
+
+#undef ASMMemFill32
+#ifdef IPRT_ASM_WATCOM_X86_32_WITH_PRAGMAS
+#pragma aux ASMMemFill32 = \
+ "shr ecx, 2" \
+ "rep stosd" \
+ parm [edi] [ecx] [eax]\
+ modify exact [ecx edi];
+#endif
+
+#undef ASMProbeReadByte
+#ifdef IPRT_ASM_WATCOM_X86_32_WITH_PRAGMAS
+#pragma aux ASMProbeReadByte = \
+ "mov al, [ecx]" \
+ parm [ecx] \
+ value [al] \
+ modify exact [al];
+#endif
+
+#undef ASMBitSet
+#ifdef IPRT_ASM_WATCOM_X86_32_WITH_PRAGMAS
+#pragma aux ASMBitSet = \
+ "bts [ecx], eax" \
+ parm [ecx] [eax] \
+ modify exact [];
+#endif
+
+#undef ASMAtomicBitSet
+#ifdef IPRT_ASM_WATCOM_X86_32_WITH_PRAGMAS
+#pragma aux ASMAtomicBitSet = \
+ "lock bts [ecx], eax" \
+ parm [ecx] [eax] \
+ modify exact [];
+#endif
+
+#undef ASMBitClear
+#ifdef IPRT_ASM_WATCOM_X86_32_WITH_PRAGMAS
+#pragma aux ASMBitClear = \
+ "btr [ecx], eax" \
+ parm [ecx] [eax] \
+ modify exact [];
+#endif
+
+#undef ASMAtomicBitClear
+#ifdef IPRT_ASM_WATCOM_X86_32_WITH_PRAGMAS
+#pragma aux ASMAtomicBitClear = \
+ "lock btr [ecx], eax" \
+ parm [ecx] [eax] \
+ modify exact [];
+#endif
+
+#undef ASMBitToggle
+#ifdef IPRT_ASM_WATCOM_X86_32_WITH_PRAGMAS
+#pragma aux ASMBitToggle = \
+ "btc [ecx], eax" \
+ parm [ecx] [eax] \
+ modify exact [];
+#endif
+
+#undef ASMAtomicBitToggle
+#ifdef IPRT_ASM_WATCOM_X86_32_WITH_PRAGMAS
+#pragma aux ASMAtomicBitToggle = \
+ "lock btc [ecx], eax" \
+ parm [ecx] [eax] \
+ modify exact [];
+#endif
+
+
+#undef ASMBitTestAndSet
+#ifdef IPRT_ASM_WATCOM_X86_32_WITH_PRAGMAS
+#pragma aux ASMBitTestAndSet = \
+ "bts [ecx], eax" \
+ "setc al" \
+ parm [ecx] [eax] \
+ value [al] \
+ modify exact [eax];
+#endif
+
+#undef ASMAtomicBitTestAndSet
+#ifdef IPRT_ASM_WATCOM_X86_32_WITH_PRAGMAS
+#pragma aux ASMAtomicBitTestAndSet = \
+ "lock bts [ecx], eax" \
+ "setc al" \
+ parm [ecx] [eax] \
+ value [al] \
+ modify exact [eax];
+#endif
+
+#undef ASMBitTestAndClear
+#ifdef IPRT_ASM_WATCOM_X86_32_WITH_PRAGMAS
+#pragma aux ASMBitTestAndClear = \
+ "btr [ecx], eax" \
+ "setc al" \
+ parm [ecx] [eax] \
+ value [al] \
+ modify exact [eax];
+#endif
+
+#undef ASMAtomicBitTestAndClear
+#ifdef IPRT_ASM_WATCOM_X86_32_WITH_PRAGMAS
+#pragma aux ASMAtomicBitTestAndClear = \
+ "lock btr [ecx], eax" \
+ "setc al" \
+ parm [ecx] [eax] \
+ value [al] \
+ modify exact [eax];
+#endif
+
+#undef ASMBitTestAndToggle
+#ifdef IPRT_ASM_WATCOM_X86_32_WITH_PRAGMAS
+#pragma aux ASMBitTestAndToggle = \
+ "btc [ecx], eax" \
+ "setc al" \
+ parm [ecx] [eax] \
+ value [al] \
+ modify exact [eax];
+#endif
+
+#undef ASMAtomicBitTestAndToggle
+#ifdef IPRT_ASM_WATCOM_X86_32_WITH_PRAGMAS
+#pragma aux ASMAtomicBitTestAndToggle = \
+ "lock btc [ecx], eax" \
+ "setc al" \
+ parm [ecx] [eax] \
+ value [al] \
+ modify exact [eax];
+#endif
+
+#undef ASMBitTest
+#ifdef IPRT_ASM_WATCOM_X86_32_WITH_PRAGMAS
+#pragma aux ASMBitTest = \
+ "bt [ecx], eax" \
+ "setc al" \
+ parm [ecx] [eax] nomemory \
+ value [al] \
+ modify exact [eax] nomemory;
+#endif
+
+#if 0
+/** @todo this is way to much inline assembly, better off in an external function. */
+#undef ASMBitFirstClear
+#ifdef IPRT_ASM_WATCOM_X86_32_WITH_PRAGMAS
+#pragma aux ASMBitFirstClear = \
+ "mov edx, edi" /* save start of bitmap for later */ \
+ "add ecx, 31" \
+ "shr ecx, 5" /* cDWord = RT_ALIGN_32(cBits, 32) / 32; */ \
+ "mov eax, 0ffffffffh" \
+ "repe scasd" \
+ "je done" \
+ "lea edi, [edi - 4]" /* rewind edi */ \
+ "xor eax, [edi]" /* load inverted bits */ \
+ "sub edi, edx" /* calc byte offset */ \
+ "shl edi, 3" /* convert byte to bit offset */ \
+ "mov edx, eax" \
+ "bsf eax, edx" \
+ "add eax, edi" \
+ "done:" \
+ parm [edi] [ecx] \
+ value [eax] \
+ modify exact [eax ecx edx edi];
+#endif
+
+/* ASMBitNextClear: Too much work, do when needed. */
+
+/** @todo this is way to much inline assembly, better off in an external function. */
+#undef ASMBitFirstSet
+#ifdef IPRT_ASM_WATCOM_X86_32_WITH_PRAGMAS
+#pragma aux ASMBitFirstSet = \
+ "mov edx, edi" /* save start of bitmap for later */ \
+ "add ecx, 31" \
+ "shr ecx, 5" /* cDWord = RT_ALIGN_32(cBits, 32) / 32; */ \
+ "mov eax, 0ffffffffh" \
+ "repe scasd" \
+ "je done" \
+ "lea edi, [edi - 4]" /* rewind edi */ \
+ "mov eax, [edi]" /* reload previous dword */ \
+ "sub edi, edx" /* calc byte offset */ \
+ "shl edi, 3" /* convert byte to bit offset */ \
+ "mov edx, eax" \
+ "bsf eax, edx" \
+ "add eax, edi" \
+ "done:" \
+ parm [edi] [ecx] \
+ value [eax] \
+ modify exact [eax ecx edx edi];
+#endif
+
+/* ASMBitNextSet: Too much work, do when needed. */
+#else
+/* ASMBitFirstClear: External file. */
+/* ASMBitNextClear: External file. */
+/* ASMBitFirstSet: External file. */
+/* ASMBitNextSet: External file. */
+#endif
+
+#undef ASMBitFirstSetU32
+#ifdef IPRT_ASM_WATCOM_X86_32_WITH_PRAGMAS
+#pragma aux ASMBitFirstSetU32 = \
+ "bsf eax, eax" \
+ "jz not_found" \
+ "inc eax" \
+ "jmp done" \
+ "not_found:" \
+ "xor eax, eax" \
+ "done:" \
+ parm [eax] nomemory \
+ value [eax] \
+ modify exact [eax] nomemory;
+#endif
+
+#undef ASMBitFirstSetU64
+#ifdef IPRT_ASM_WATCOM_X86_32_WITH_PRAGMAS
+#pragma aux ASMBitFirstSetU64 = \
+ "bsf eax, eax" \
+ "jz not_found_low" \
+ "inc eax" \
+ "jmp done" \
+ \
+ "not_found_low:" \
+ "bsf eax, edx" \
+ "jz not_found_high" \
+ "add eax, 33" \
+ "jmp done" \
+ \
+ "not_found_high:" \
+ "xor eax, eax" \
+ "done:" \
+ parm [eax edx] nomemory \
+ value [eax] \
+ modify exact [eax] nomemory;
+#endif
+
+#undef ASMBitFirstSetU16
+#ifdef IPRT_ASM_WATCOM_X86_32_WITH_PRAGMAS
+#pragma aux ASMBitFirstSetU16 = \
+ "movzx eax, ax" \
+ "bsf eax, eax" \
+ "jz not_found" \
+ "inc eax" \
+ "jmp done" \
+ "not_found:" \
+ "xor eax, eax" \
+ "done:" \
+ parm [ax] nomemory \
+ value [eax] \
+ modify exact [eax] nomemory;
+#endif
+
+#undef ASMBitLastSetU32
+#ifdef IPRT_ASM_WATCOM_X86_32_WITH_PRAGMAS
+#pragma aux ASMBitLastSetU32 = \
+ "bsr eax, eax" \
+ "jz not_found" \
+ "inc eax" \
+ "jmp done" \
+ "not_found:" \
+ "xor eax, eax" \
+ "done:" \
+ parm [eax] nomemory \
+ value [eax] \
+ modify exact [eax] nomemory;
+#endif
+
+#undef ASMBitLastSetU64
+#ifdef IPRT_ASM_WATCOM_X86_32_WITH_PRAGMAS
+#pragma aux ASMBitLastSetU64 = \
+ "xchg eax, edx" \
+ "bsr eax, eax" \
+ "jz not_found_high" \
+ "add eax, 33" \
+ "jmp done" \
+ \
+ "not_found_high:" \
+ "bsr eax, edx" \
+ "jz not_found" \
+ "inc eax" \
+ "jmp done" \
+ \
+ "not_found:" \
+ "xor eax, eax" \
+ "done:" \
+ parm [eax edx] nomemory \
+ value [eax] \
+ modify exact [eax edx] nomemory;
+#endif
+
+#undef ASMBitLastSetU16
+#ifdef IPRT_ASM_WATCOM_X86_32_WITH_PRAGMAS
+#pragma aux ASMBitLastSetU16 = \
+ "movzx eax, ax" \
+ "bsr eax, eax" \
+ "jz not_found" \
+ "inc eax" \
+ "jmp done" \
+ "not_found:" \
+ "xor eax, eax" \
+ "done:" \
+ parm [ax] nomemory \
+ value [eax] \
+ modify exact [eax] nomemory;
+#endif
+
+#undef ASMByteSwapU16
+#ifdef IPRT_ASM_WATCOM_X86_32_WITH_PRAGMAS
+#pragma aux ASMByteSwapU16 = \
+ "ror ax, 8" \
+ parm [ax] nomemory \
+ value [ax] \
+ modify exact [ax] nomemory;
+#endif
+
+#undef ASMByteSwapU32
+#ifdef IPRT_ASM_WATCOM_X86_32_WITH_PRAGMAS
+#pragma aux ASMByteSwapU32 = \
+ "bswap eax" \
+ parm [eax] nomemory \
+ value [eax] \
+ modify exact [eax] nomemory;
+#endif
+
+#undef ASMRotateLeftU32
+#ifdef IPRT_ASM_WATCOM_X86_32_WITH_PRAGMAS
+#pragma aux ASMRotateLeftU32 = \
+ "rol eax, cl" \
+ parm [eax] [ecx] nomemory \
+ value [eax] \
+ modify exact [eax] nomemory;
+#endif
+
+#undef ASMRotateRightU32
+#ifdef IPRT_ASM_WATCOM_X86_32_WITH_PRAGMAS
+#pragma aux ASMRotateRightU32 = \
+ "ror eax, cl" \
+ parm [eax] [ecx] nomemory \
+ value [eax] \
+ modify exact [eax] nomemory;
+#endif
+
+#endif /* !IPRT_INCLUDED_asm_watcom_x86_32_h */
+
diff --git a/include/iprt/asm.h b/include/iprt/asm.h
new file mode 100644
index 00000000..100555ed
--- /dev/null
+++ b/include/iprt/asm.h
@@ -0,0 +1,8132 @@
+/** @file
+ * IPRT - Assembly Functions.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_asm_h
+#define IPRT_INCLUDED_asm_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#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
+/* Emit the intrinsics at all optimization levels. */
+# include <iprt/sanitized/intrin.h>
+# 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(_InterlockedXor)
+# pragma intrinsic(_InterlockedIncrement)
+# pragma intrinsic(_InterlockedDecrement)
+# pragma intrinsic(_InterlockedExchange)
+# pragma intrinsic(_InterlockedExchangeAdd)
+# pragma intrinsic(_InterlockedCompareExchange)
+# pragma intrinsic(_InterlockedCompareExchange8)
+# pragma intrinsic(_InterlockedCompareExchange16)
+# 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(_InterlockedCompareExchange128)
+# pragma intrinsic(_InterlockedExchange64)
+# pragma intrinsic(_InterlockedExchangeAdd64)
+# pragma intrinsic(_InterlockedAnd64)
+# pragma intrinsic(_InterlockedOr64)
+# pragma intrinsic(_InterlockedIncrement64)
+# pragma intrinsic(_InterlockedDecrement64)
+# endif
+#endif
+
+/*
+ * Undefine all symbols we have Watcom C/C++ #pragma aux'es for.
+ */
+#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).
+ *
+ * Please note that ordered operations does not necessarily imply a
+ * compiler (memory) barrier. The user has to use the
+ * ASMCompilerBarrier() macro when that is deemed necessary.
+ *
+ * @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 RT_INLINE_ASM_EXTERNAL_TMP_ARM
+ * Temporary version of RT_INLINE_ASM_EXTERNAL that excludes ARM. */
+#if RT_INLINE_ASM_EXTERNAL && !(defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32))
+# define RT_INLINE_ASM_EXTERNAL_TMP_ARM 1
+#else
+# define RT_INLINE_ASM_EXTERNAL_TMP_ARM 0
+#endif
+
+/*
+ * ARM is great fun.
+ */
+#if defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32)
+
+# define RTASM_ARM_NO_BARRIER
+# ifdef RT_ARCH_ARM64
+# define RTASM_ARM_NO_BARRIER_IN_REG
+# define RTASM_ARM_NO_BARRIER_COMMA_IN_REG
+# define RTASM_ARM_DSB_SY "dsb sy\n\t"
+# define RTASM_ARM_DSB_SY_IN_REG
+# define RTASM_ARM_DSB_SY_COMMA_IN_REG
+# define RTASM_ARM_DMB_SY "dmb sy\n\t"
+# define RTASM_ARM_DMB_SY_IN_REG
+# define RTASM_ARM_DMB_SY_COMMA_IN_REG
+# define RTASM_ARM_DMB_ST "dmb st\n\t"
+# define RTASM_ARM_DMB_ST_IN_REG
+# define RTASM_ARM_DMB_ST_COMMA_IN_REG
+# define RTASM_ARM_DMB_LD "dmb ld\n\t"
+# define RTASM_ARM_DMB_LD_IN_REG
+# define RTASM_ARM_DMB_LD_COMMA_IN_REG
+# define RTASM_ARM_PICK_6432(expr64, expr32) expr64
+# define RTASM_ARM_LOAD_MODIFY_STORE_RET_NEW_32(name, a_pu32Mem, barrier_type, modify64, modify32, in_reg) \
+ uint32_t rcSpill; \
+ uint32_t u32NewRet; \
+ __asm__ __volatile__(".Ltry_again_" #name "_%=:\n\t" \
+ RTASM_ARM_##barrier_type /* before lable? */ \
+ "ldaxr %w[uNew], %[pMem]\n\t" \
+ modify64 \
+ "stlxr %w[rc], %w[uNew], %[pMem]\n\t" \
+ "cbnz %w[rc], .Ltry_again_" #name "_%=\n\t" \
+ : [pMem] "+Q" (*a_pu32Mem) \
+ , [uNew] "=&r" (u32NewRet) \
+ , [rc] "=&r" (rcSpill) \
+ : in_reg \
+ : "cc")
+# define RTASM_ARM_LOAD_MODIFY_STORE_RET_OLD_32(name, a_pu32Mem, barrier_type, modify64, modify32, in_reg) \
+ uint32_t rcSpill; \
+ uint32_t u32OldRet; \
+ uint32_t u32NewSpill; \
+ __asm__ __volatile__(".Ltry_again_" #name "_%=:\n\t" \
+ RTASM_ARM_##barrier_type /* before lable? */ \
+ "ldaxr %w[uOld], %[pMem]\n\t" \
+ modify64 \
+ "stlxr %w[rc], %w[uNew], %[pMem]\n\t" \
+ "cbnz %w[rc], .Ltry_again_" #name "_%=\n\t" \
+ : [pMem] "+Q" (*a_pu32Mem) \
+ , [uOld] "=&r" (u32OldRet) \
+ , [uNew] "=&r" (u32NewSpill) \
+ , [rc] "=&r" (rcSpill) \
+ : in_reg \
+ : "cc")
+# define RTASM_ARM_LOAD_MODIFY_STORE_RET_NEW_64(name, a_pu64Mem, barrier_type, modify64, modify32, in_reg) \
+ uint32_t rcSpill; \
+ uint64_t u64NewRet; \
+ __asm__ __volatile__(".Ltry_again_" #name "_%=:\n\t" \
+ RTASM_ARM_##barrier_type /* before lable? */ \
+ "ldaxr %[uNew], %[pMem]\n\t" \
+ modify64 \
+ "stlxr %w[rc], %[uNew], %[pMem]\n\t" \
+ "cbnz %w[rc], .Ltry_again_" #name "_%=\n\t" \
+ : [pMem] "+Q" (*a_pu64Mem) \
+ , [uNew] "=&r" (u64NewRet) \
+ , [rc] "=&r" (rcSpill) \
+ : in_reg \
+ : "cc")
+# define RTASM_ARM_LOAD_MODIFY_STORE_RET_OLD_64(name, a_pu64Mem, barrier_type, modify64, modify32, in_reg) \
+ uint32_t rcSpill; \
+ uint64_t u64OldRet; \
+ uint64_t u64NewSpill; \
+ __asm__ __volatile__(".Ltry_again_" #name "_%=:\n\t" \
+ RTASM_ARM_##barrier_type /* before lable? */ \
+ "ldaxr %[uOld], %[pMem]\n\t" \
+ modify64 \
+ "stlxr %w[rc], %[uNew], %[pMem]\n\t" \
+ "cbnz %w[rc], .Ltry_again_" #name "_%=\n\t" \
+ : [pMem] "+Q" (*a_pu64Mem) \
+ , [uOld] "=&r" (u64OldRet) \
+ , [uNew] "=&r" (u64NewSpill) \
+ , [rc] "=&r" (rcSpill) \
+ : in_reg \
+ : "cc")
+
+# else /* RT_ARCH_ARM32 */
+# define RTASM_ARM_PICK_6432(expr64, expr32) expr32
+# if RT_ARCH_ARM32 >= 7
+# warning armv7
+# define RTASM_ARM_NO_BARRIER_IN_REG
+# define RTASM_ARM_NO_BARRIER_COMMA_IN_REG
+# define RTASM_ARM_DSB_SY "dsb sy\n\t"
+# define RTASM_ARM_DSB_SY_IN_REG "X" (0xfade)
+# define RTASM_ARM_DMB_SY "dmb sy\n\t"
+# define RTASM_ARM_DMB_SY_IN_REG "X" (0xfade)
+# define RTASM_ARM_DMB_ST "dmb st\n\t"
+# define RTASM_ARM_DMB_ST_IN_REG "X" (0xfade)
+# define RTASM_ARM_DMB_LD "dmb ld\n\t"
+# define RTASM_ARM_DMB_LD_IN_REG "X" (0xfade)
+
+# elif RT_ARCH_ARM32 >= 6
+# warning armv6
+# define RTASM_ARM_DSB_SY "mcr p15, 0, %[uZero], c7, c10, 4\n\t"
+# define RTASM_ARM_DSB_SY_IN_REG [uZero] "r" (0)
+# define RTASM_ARM_DMB_SY "mcr p15, 0, %[uZero], c7, c10, 5\n\t"
+# define RTASM_ARM_DMB_SY_IN_REG [uZero] "r" (0)
+# define RTASM_ARM_DMB_ST RTASM_ARM_DMB_SY
+# define RTASM_ARM_DMB_ST_IN_REG RTASM_ARM_DMB_SY_IN_REG
+# define RTASM_ARM_DMB_LD RTASM_ARM_DMB_SY
+# define RTASM_ARM_DMB_LD_IN_REG RTASM_ARM_DMB_SY_IN_REG
+# elif RT_ARCH_ARM32 >= 4
+# warning armv5 or older
+# define RTASM_ARM_DSB_SY "mcr p15, 0, %[uZero], c7, c10, 4\n\t"
+# define RTASM_ARM_DSB_SY_IN_REG [uZero] "r" (0)
+# define RTASM_ARM_DMB_SY RTASM_ARM_DSB_SY
+# define RTASM_ARM_DMB_SY_IN_REG RTASM_ARM_DSB_SY_IN_REG
+# define RTASM_ARM_DMB_ST RTASM_ARM_DSB_SY
+# define RTASM_ARM_DMB_ST_IN_REG RTASM_ARM_DSB_SY_IN_REG
+# define RTASM_ARM_DMB_LD RTASM_ARM_DSB_SY
+# define RTASM_ARM_DMB_LD_IN_REG RTASM_ARM_DSB_SY_IN_REG
+# else
+# error "huh? Odd RT_ARCH_ARM32 value!"
+# endif
+# define RTASM_ARM_DSB_SY_COMMA_IN_REG , RTASM_ARM_DSB_SY_IN_REG
+# define RTASM_ARM_DMB_SY_COMMA_IN_REG , RTASM_ARM_DMB_SY_IN_REG
+# define RTASM_ARM_DMB_ST_COMMA_IN_REG , RTASM_ARM_DMB_ST_IN_REG
+# define RTASM_ARM_DMB_LD_COMMA_IN_REG , RTASM_ARM_DMB_LD_IN_REG
+# define RTASM_ARM_LOAD_MODIFY_STORE_RET_NEW_32(name, a_pu32Mem, barrier_type, modify64, modify32, in_reg) \
+ uint32_t rcSpill; \
+ uint32_t u32NewRet; \
+ __asm__ __volatile__(".Ltry_again_" #name "_%=:\n\t" \
+ RT_CONCAT(RTASM_ARM_,barrier_type) /* before lable? */ \
+ "ldrex %[uNew], %[pMem]\n\t" \
+ modify32 \
+ "strex %[rc], %[uNew], %[pMem]\n\t" \
+ "cmp %[rc], #0\n\t" \
+ "bne .Ltry_again_" #name "_%=\n\t" \
+ : [pMem] "+m" (*a_pu32Mem) \
+ , [uNew] "=&r" (u32NewRet) \
+ , [rc] "=&r" (rcSpill) \
+ : RT_CONCAT3(RTASM_ARM_,barrier_type,_IN_REG) \
+ , in_reg \
+ : "cc")
+# define RTASM_ARM_LOAD_MODIFY_STORE_RET_OLD_32(name, a_pu32Mem, barrier_type, modify64, modify32, in_reg) \
+ uint32_t rcSpill; \
+ uint32_t u32OldRet; \
+ uint32_t u32NewSpill; \
+ __asm__ __volatile__(".Ltry_again_" #name "_%=:\n\t" \
+ RT_CONCAT(RTASM_ARM_,barrier_type) /* before lable? */ \
+ "ldrex %[uOld], %[pMem]\n\t" \
+ modify32 \
+ "strex %[rc], %[uNew], %[pMem]\n\t" \
+ "cmp %[rc], #0\n\t" \
+ "bne .Ltry_again_" #name "_%=\n\t" \
+ : [pMem] "+m" (*a_pu32Mem) \
+ , [uOld] "=&r" (u32OldRet) \
+ , [uNew] "=&r" (u32NewSpill) \
+ , [rc] "=&r" (rcSpill) \
+ : RT_CONCAT3(RTASM_ARM_,barrier_type,_IN_REG) \
+ , in_reg \
+ : "cc")
+# define RTASM_ARM_LOAD_MODIFY_STORE_RET_NEW_64(name, a_pu64Mem, barrier_type, modify64, modify32, in_reg) \
+ uint32_t rcSpill; \
+ uint64_t u64NewRet; \
+ __asm__ __volatile__(".Ltry_again_" #name "_%=:\n\t" \
+ RT_CONCAT(RTASM_ARM_,barrier_type) /* before lable? */ \
+ "ldrexd %[uNew], %H[uNew], %[pMem]\n\t" \
+ modify32 \
+ "strexd %[rc], %[uNew], %H[uNew], %[pMem]\n\t" \
+ "cmp %[rc], #0\n\t" \
+ "bne .Ltry_again_" #name "_%=\n\t" \
+ : [pMem] "+m" (*a_pu64Mem), \
+ [uNew] "=&r" (u64NewRet), \
+ [rc] "=&r" (rcSpill) \
+ : RT_CONCAT3(RTASM_ARM_,barrier_type,_IN_REG) \
+ , in_reg \
+ : "cc")
+# define RTASM_ARM_LOAD_MODIFY_STORE_RET_OLD_64(name, a_pu64Mem, barrier_type, modify64, modify32, in_reg) \
+ uint32_t rcSpill; \
+ uint64_t u64OldRet; \
+ uint64_t u64NewSpill; \
+ __asm__ __volatile__(".Ltry_again_" #name "_%=:\n\t" \
+ RT_CONCAT(RTASM_ARM_,barrier_type) /* before lable? */ \
+ "ldrexd %[uOld], %H[uOld], %[pMem]\n\t" \
+ modify32 \
+ "strexd %[rc], %[uNew], %H[uNew], %[pMem]\n\t" \
+ "cmp %[rc], #0\n\t" \
+ "bne .Ltry_again_" #name "_%=\n\t" \
+ : [pMem] "+m" (*a_pu64Mem), \
+ [uOld] "=&r" (u64OldRet), \
+ [uNew] "=&r" (u64NewSpill), \
+ [rc] "=&r" (rcSpill) \
+ : RT_CONCAT3(RTASM_ARM_,barrier_type,_IN_REG) \
+ , in_reg \
+ : "cc")
+# endif /* RT_ARCH_ARM32 */
+#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) RT_NOTHROW_DEF
+{
+ __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_TMP_ARM && (defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86))
+RT_ASM_DECL_PRAGMA_WATCOM(void) ASMNopPause(void) RT_NOTHROW_PROTO;
+#else
+DECLINLINE(void) ASMNopPause(void) RT_NOTHROW_DEF
+{
+# 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
+
+# elif defined(RT_ARCH_ARM32) || defined(RT_ARCH_ARM64)
+ __asm__ __volatile__("yield\n\t"); /* ARMv6K+ */
+
+# 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_TMP_ARM
+RT_ASM_DECL_PRAGMA_WATCOM(uint8_t) ASMAtomicXchgU8(volatile uint8_t RT_FAR *pu8, uint8_t u8) RT_NOTHROW_PROTO;
+#else
+DECLINLINE(uint8_t) ASMAtomicXchgU8(volatile uint8_t RT_FAR *pu8, uint8_t u8) RT_NOTHROW_DEF
+{
+# if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
+# 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;
+
+# elif defined(RT_ARCH_ARM32) || defined(RT_ARCH_ARM64)
+ uint32_t uOld;
+ uint32_t rcSpill;
+ __asm__ __volatile__(".Ltry_again_ASMAtomicXchgU8_%=:\n\t"
+ RTASM_ARM_DMB_SY
+# if defined(RT_ARCH_ARM64)
+ "ldaxrb %w[uOld], %[pMem]\n\t"
+ "stlxrb %w[rc], %w[uNew], %[pMem]\n\t"
+ "cbnz %w[rc], .Ltry_again_ASMAtomicXchgU8_%=\n\t"
+# else
+ "ldrexb %[uOld], %[pMem]\n\t" /* ARMv6+ */
+ "strexb %[rc], %[uNew], %[pMem]\n\t"
+ "cmp %[rc], #0\n\t"
+ "bne .Ltry_again_ASMAtomicXchgU8_%=\n\t"
+# endif
+ : [pMem] "+Q" (*pu8)
+ , [uOld] "=&r" (uOld)
+ , [rc] "=&r" (rcSpill)
+ : [uNew] "r" ((uint32_t)u8)
+ RTASM_ARM_DMB_SY_COMMA_IN_REG
+ : "cc");
+ return (uint8_t)uOld;
+
+# else
+# error "Port me"
+# endif
+}
+#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 RT_FAR *pi8, int8_t i8) RT_NOTHROW_DEF
+{
+ return (int8_t)ASMAtomicXchgU8((volatile uint8_t RT_FAR *)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 RT_FAR *pf, bool f) RT_NOTHROW_DEF
+{
+#ifdef _MSC_VER
+ return !!ASMAtomicXchgU8((volatile uint8_t RT_FAR *)pf, (uint8_t)f);
+#else
+ return (bool)ASMAtomicXchgU8((volatile uint8_t RT_FAR *)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_TMP_ARM
+RT_ASM_DECL_PRAGMA_WATCOM(uint16_t) ASMAtomicXchgU16(volatile uint16_t RT_FAR *pu16, uint16_t u16) RT_NOTHROW_PROTO;
+#else
+DECLINLINE(uint16_t) ASMAtomicXchgU16(volatile uint16_t RT_FAR *pu16, uint16_t u16) RT_NOTHROW_DEF
+{
+# if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
+# 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;
+
+# elif defined(RT_ARCH_ARM32) || defined(RT_ARCH_ARM64)
+ uint32_t uOld;
+ uint32_t rcSpill;
+ __asm__ __volatile__(".Ltry_again_ASMAtomicXchgU16_%=:\n\t"
+ RTASM_ARM_DMB_SY
+# if defined(RT_ARCH_ARM64)
+ "ldaxrh %w[uOld], %[pMem]\n\t"
+ "stlxrh %w[rc], %w[uNew], %[pMem]\n\t"
+ "cbnz %w[rc], .Ltry_again_ASMAtomicXchgU16_%=\n\t"
+# else
+ "ldrexh %[uOld], %[pMem]\n\t" /* ARMv6+ */
+ "strexh %[rc], %[uNew], %[pMem]\n\t"
+ "cmp %[rc], #0\n\t"
+ "bne .Ltry_again_ASMAtomicXchgU16_%=\n\t"
+# endif
+ : [pMem] "+Q" (*pu16)
+ , [uOld] "=&r" (uOld)
+ , [rc] "=&r" (rcSpill)
+ : [uNew] "r" ((uint32_t)u16)
+ RTASM_ARM_DMB_SY_COMMA_IN_REG
+ : "cc");
+ return (uint16_t)uOld;
+
+# else
+# error "Port me"
+# endif
+}
+#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 RT_FAR *pi16, int16_t i16) RT_NOTHROW_DEF
+{
+ return (int16_t)ASMAtomicXchgU16((volatile uint16_t RT_FAR *)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_TMP_ARM && !RT_INLINE_ASM_USES_INTRIN
+RT_ASM_DECL_PRAGMA_WATCOM(uint32_t) ASMAtomicXchgU32(volatile uint32_t RT_FAR *pu32, uint32_t u32) RT_NOTHROW_PROTO;
+#else
+DECLINLINE(uint32_t) ASMAtomicXchgU32(volatile uint32_t RT_FAR *pu32, uint32_t u32) RT_NOTHROW_DEF
+{
+# if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
+# if RT_INLINE_ASM_GNU_STYLE
+ __asm__ __volatile__("xchgl %0, %1\n\t"
+ : "=m" (*pu32) /** @todo r=bird: +m rather than =m here? */
+ , "=r" (u32)
+ : "1" (u32)
+ , "m" (*pu32));
+
+# elif RT_INLINE_ASM_USES_INTRIN
+ u32 = _InterlockedExchange((long RT_FAR *)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;
+
+# elif defined(RT_ARCH_ARM32) || defined(RT_ARCH_ARM64)
+ uint32_t uOld;
+ uint32_t rcSpill;
+ __asm__ __volatile__(".Ltry_again_ASMAtomicXchgU32_%=:\n\t"
+ RTASM_ARM_DMB_SY
+# if defined(RT_ARCH_ARM64)
+ "ldaxr %w[uOld], %[pMem]\n\t"
+ "stlxr %w[rc], %w[uNew], %[pMem]\n\t"
+ "cbnz %w[rc], .Ltry_again_ASMAtomicXchgU32_%=\n\t"
+# else
+ "ldrex %[uOld], %[pMem]\n\t" /* ARMv6+ */
+ "strex %[rc], %[uNew], %[pMem]\n\t"
+ "cmp %[rc], #0\n\t"
+ "bne .Ltry_again_ASMAtomicXchgU32_%=\n\t"
+# endif
+ : [pMem] "+Q" (*pu32)
+ , [uOld] "=&r" (uOld)
+ , [rc] "=&r" (rcSpill)
+ : [uNew] "r" (u32)
+ RTASM_ARM_DMB_SY_COMMA_IN_REG
+ : "cc");
+ return uOld;
+
+# else
+# error "Port me"
+# endif
+}
+#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 RT_FAR *pi32, int32_t i32) RT_NOTHROW_DEF
+{
+ return (int32_t)ASMAtomicXchgU32((volatile uint32_t RT_FAR *)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_TMP_ARM && !RT_INLINE_ASM_USES_INTRIN) \
+ || RT_INLINE_DONT_MIX_CMPXCHG8B_AND_PIC
+RT_ASM_DECL_PRAGMA_WATCOM(uint64_t) ASMAtomicXchgU64(volatile uint64_t RT_FAR *pu64, uint64_t u64) RT_NOTHROW_PROTO;
+#else
+DECLINLINE(uint64_t) ASMAtomicXchgU64(volatile uint64_t RT_FAR *pu64, uint64_t u64) RT_NOTHROW_DEF
+{
+# if defined(RT_ARCH_AMD64)
+# if RT_INLINE_ASM_USES_INTRIN
+ return _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));
+ return u64;
+# else
+ __asm
+ {
+ mov rdx, [pu64]
+ mov rax, [u64]
+ xchg [rdx], rax
+ mov [u64], rax
+ }
+ return u64;
+# endif
+
+# elif defined(RT_ARCH_X86)
+# 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)
+ : "cc");
+# 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) )
+ : "cc");
+# 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
+ return u64;
+
+# elif defined(RT_ARCH_ARM32) || defined(RT_ARCH_ARM64)
+ uint32_t rcSpill;
+ uint64_t uOld;
+ __asm__ __volatile__(".Ltry_again_ASMAtomicXchgU64_%=:\n\t"
+ RTASM_ARM_DMB_SY
+# if defined(RT_ARCH_ARM64)
+ "ldaxr %[uOld], %[pMem]\n\t"
+ "stlxr %w[rc], %[uNew], %[pMem]\n\t"
+ "cbnz %w[rc], .Ltry_again_ASMAtomicXchgU64_%=\n\t"
+# else
+ "ldrexd %[uOld], %H[uOld], %[pMem]\n\t" /* ARMv6+ */
+ "strexd %[rc], %[uNew], %H[uNew], %[pMem]\n\t"
+ "cmp %[rc], #0\n\t"
+ "bne .Ltry_again_ASMAtomicXchgU64_%=\n\t"
+# endif
+ : [pMem] "+Q" (*pu64)
+ , [uOld] "=&r" (uOld)
+ , [rc] "=&r" (rcSpill)
+ : [uNew] "r" (u64)
+ RTASM_ARM_DMB_SY_COMMA_IN_REG
+ : "cc");
+ return uOld;
+
+# else
+# error "Port me"
+# endif
+}
+#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 RT_FAR *pi64, int64_t i64) RT_NOTHROW_DEF
+{
+ return (int64_t)ASMAtomicXchgU64((volatile uint64_t RT_FAR *)pi64, (uint64_t)i64);
+}
+
+
+/**
+ * Atomically Exchange a size_t value, ordered.
+ *
+ * @returns Current *ppv value
+ * @param puDst Pointer to the size_t variable to update.
+ * @param uNew The new value to assign to *puDst.
+ */
+DECLINLINE(size_t) ASMAtomicXchgZ(size_t volatile RT_FAR *puDst, const size_t uNew) RT_NOTHROW_DEF
+{
+#if ARCH_BITS == 16
+ AssertCompile(sizeof(size_t) == 2);
+ return ASMAtomicXchgU16((volatile uint16_t RT_FAR *)puDst, uNew);
+#elif ARCH_BITS == 32
+ return ASMAtomicXchgU32((volatile uint32_t RT_FAR *)puDst, uNew);
+#elif ARCH_BITS == 64
+ return ASMAtomicXchgU64((volatile uint64_t RT_FAR *)puDst, uNew);
+#else
+# error "ARCH_BITS is bogus"
+#endif
+}
+
+
+/**
+ * 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 RT_FAR *) ASMAtomicXchgPtr(void RT_FAR * volatile RT_FAR *ppv, const void RT_FAR *pv) RT_NOTHROW_DEF
+{
+#if ARCH_BITS == 32 || ARCH_BITS == 16
+ return (void RT_FAR *)ASMAtomicXchgU32((volatile uint32_t RT_FAR *)(void RT_FAR *)ppv, (uint32_t)pv);
+#elif ARCH_BITS == 64
+ return (void RT_FAR *)ASMAtomicXchgU64((volatile uint64_t RT_FAR *)(void RT_FAR *)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__ /* 8.2.0 requires -Wno-ignored-qualifiers */
+# 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 RT_FAR * volatile RT_FAR *)(ppv), (void RT_FAR *)(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 RT_FAR *ppvRC, RTRCPTR pvRC) RT_NOTHROW_DEF
+{
+ return (RTRCPTR)ASMAtomicXchgU32((uint32_t volatile RT_FAR *)(void RT_FAR *)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 RT_FAR *ppvR0, RTR0PTR pvR0) RT_NOTHROW_DEF
+{
+#if R0_ARCH_BITS == 32 || ARCH_BITS == 16
+ return (RTR0PTR)ASMAtomicXchgU32((volatile uint32_t RT_FAR *)(void RT_FAR *)ppvR0, (uint32_t)pvR0);
+#elif R0_ARCH_BITS == 64
+ return (RTR0PTR)ASMAtomicXchgU64((volatile uint64_t RT_FAR *)(void RT_FAR *)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 RT_FAR *ppvR3, RTR3PTR pvR3) RT_NOTHROW_DEF
+{
+#if R3_ARCH_BITS == 32 || ARCH_BITS == 16
+ return (RTR3PTR)ASMAtomicXchgU32((volatile uint32_t RT_FAR *)(void RT_FAR *)ppvR3, (uint32_t)pvR3);
+#elif R3_ARCH_BITS == 64
+ return (RTR3PTR)ASMAtomicXchgU64((volatile uint64_t RT_FAR *)(void RT_FAR *)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
+# define ASMAtomicXchgHandle(ph, hNew, phRes) \
+ do { \
+ AssertCompile(sizeof(*(ph)) == sizeof(uint32_t)); \
+ AssertCompile(sizeof(*(phRes)) == sizeof(uint32_t)); \
+ *(uint32_t RT_FAR *)(phRes) = ASMAtomicXchgU32((uint32_t volatile RT_FAR *)(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 RT_FAR *)(phRes) = ASMAtomicXchgU64((uint64_t volatile RT_FAR *)(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 RT_FAR *)(void RT_FAR *)(pu), (uint8_t)(uNew)); break; \
+ case 2: ASMAtomicXchgU16((volatile uint16_t RT_FAR *)(void RT_FAR *)(pu), (uint16_t)(uNew)); break; \
+ case 4: ASMAtomicXchgU32((volatile uint32_t RT_FAR *)(void RT_FAR *)(pu), (uint32_t)(uNew)); break; \
+ case 8: ASMAtomicXchgU64((volatile uint64_t RT_FAR *)(void RT_FAR *)(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 RT_FAR *)(puRes) = ASMAtomicXchgU8( (volatile uint8_t RT_FAR *)(void RT_FAR *)(pu), (uint8_t)(uNew)); break; \
+ case 2: *(uint16_t RT_FAR *)(puRes) = ASMAtomicXchgU16((volatile uint16_t RT_FAR *)(void RT_FAR *)(pu), (uint16_t)(uNew)); break; \
+ case 4: *(uint32_t RT_FAR *)(puRes) = ASMAtomicXchgU32((volatile uint32_t RT_FAR *)(void RT_FAR *)(pu), (uint32_t)(uNew)); break; \
+ case 8: *(uint64_t RT_FAR *)(puRes) = ASMAtomicXchgU64((volatile uint64_t RT_FAR *)(void RT_FAR *)(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.
+ * @todo Rename ASMAtomicCmpWriteU8
+ */
+#if RT_INLINE_ASM_EXTERNAL_TMP_ARM || !RT_INLINE_ASM_GNU_STYLE
+RT_ASM_DECL_PRAGMA_WATCOM(bool) ASMAtomicCmpXchgU8(volatile uint8_t RT_FAR *pu8, const uint8_t u8New, const uint8_t u8Old) RT_NOTHROW_PROTO;
+#else
+DECLINLINE(bool) ASMAtomicCmpXchgU8(volatile uint8_t RT_FAR *pu8, const uint8_t u8New, uint8_t u8Old) RT_NOTHROW_DEF
+{
+# if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
+ 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)
+ : "cc");
+ return (bool)u8Ret;
+
+# elif defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32)
+ union { uint32_t u; bool f; } fXchg;
+ uint32_t u32Spill;
+ uint32_t rcSpill;
+ __asm__ __volatile__(".Ltry_again_ASMAtomicCmpXchgU8_%=:\n\t"
+ RTASM_ARM_DMB_SY
+# if defined(RT_ARCH_ARM64)
+ "ldaxrb %w[uOld], %[pMem]\n\t"
+ "cmp %w[uOld], %w[uCmp]\n\t"
+ "bne 1f\n\t" /* stop here if not equal */
+ "stlxrb %w[rc], %w[uNew], %[pMem]\n\t"
+ "cbnz %w[rc], .Ltry_again_ASMAtomicCmpXchgU8_%=\n\t"
+ "mov %w[fXchg], #1\n\t"
+# else
+ "ldrexb %[uOld], %[pMem]\n\t"
+ "teq %[uOld], %[uCmp]\n\t"
+ "strexbeq %[rc], %[uNew], %[pMem]\n\t"
+ "bne 1f\n\t" /* stop here if not equal */
+ "cmp %[rc], #0\n\t"
+ "bne .Ltry_again_ASMAtomicCmpXchgU8_%=\n\t"
+ "mov %[fXchg], #1\n\t"
+# endif
+ "1:\n\t"
+ : [pMem] "+Q" (*pu8)
+ , [uOld] "=&r" (u32Spill)
+ , [rc] "=&r" (rcSpill)
+ , [fXchg] "=&r" (fXchg.u)
+ : [uCmp] "r" ((uint32_t)u8Old)
+ , [uNew] "r" ((uint32_t)u8New)
+ , "[fXchg]" (0)
+ RTASM_ARM_DMB_SY_COMMA_IN_REG
+ : "cc");
+ return fXchg.f;
+
+# else
+# error "Port me"
+# endif
+}
+#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.
+ * @todo Rename ASMAtomicCmpWriteS8
+ */
+DECLINLINE(bool) ASMAtomicCmpXchgS8(volatile int8_t RT_FAR *pi8, const int8_t i8New, const int8_t i8Old) RT_NOTHROW_DEF
+{
+ return ASMAtomicCmpXchgU8((volatile uint8_t RT_FAR *)pi8, (uint8_t)i8New, (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.
+ * @todo Rename ASMAtomicCmpWriteBool
+ */
+DECLINLINE(bool) ASMAtomicCmpXchgBool(volatile bool RT_FAR *pf, const bool fNew, const bool fOld) RT_NOTHROW_DEF
+{
+ return ASMAtomicCmpXchgU8((volatile uint8_t RT_FAR *)pf, (uint8_t)fNew, (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.
+ * @todo Rename ASMAtomicCmpWriteU32
+ */
+#if RT_INLINE_ASM_EXTERNAL_TMP_ARM && !RT_INLINE_ASM_USES_INTRIN
+RT_ASM_DECL_PRAGMA_WATCOM(bool) ASMAtomicCmpXchgU32(volatile uint32_t RT_FAR *pu32, const uint32_t u32New, const uint32_t u32Old) RT_NOTHROW_PROTO;
+#else
+DECLINLINE(bool) ASMAtomicCmpXchgU32(volatile uint32_t RT_FAR *pu32, const uint32_t u32New, uint32_t u32Old) RT_NOTHROW_DEF
+{
+# if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
+# 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)
+ : "cc");
+ return (bool)u8Ret;
+
+# elif RT_INLINE_ASM_USES_INTRIN
+ return (uint32_t)_InterlockedCompareExchange((long RT_FAR *)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
+
+# elif defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32)
+ union { uint32_t u; bool f; } fXchg;
+ uint32_t u32Spill;
+ uint32_t rcSpill;
+ __asm__ __volatile__(".Ltry_again_ASMAtomicCmpXchgU32_%=:\n\t"
+ RTASM_ARM_DMB_SY
+# if defined(RT_ARCH_ARM64)
+ "ldaxr %w[uOld], %[pMem]\n\t"
+ "cmp %w[uOld], %w[uCmp]\n\t"
+ "bne 1f\n\t" /* stop here if not equal */
+ "stlxr %w[rc], %w[uNew], %[pMem]\n\t"
+ "cbnz %w[rc], .Ltry_again_ASMAtomicCmpXchgU32_%=\n\t"
+ "mov %w[fXchg], #1\n\t"
+# else
+ "ldrex %[uOld], %[pMem]\n\t"
+ "teq %[uOld], %[uCmp]\n\t"
+ "strexeq %[rc], %[uNew], %[pMem]\n\t"
+ "bne 1f\n\t" /* stop here if not equal */
+ "cmp %[rc], #0\n\t"
+ "bne .Ltry_again_ASMAtomicCmpXchgU32_%=\n\t"
+ "mov %[fXchg], #1\n\t"
+# endif
+ "1:\n\t"
+ : [pMem] "+Q" (*pu32)
+ , [uOld] "=&r" (u32Spill)
+ , [rc] "=&r" (rcSpill)
+ , [fXchg] "=&r" (fXchg.u)
+ : [uCmp] "r" (u32Old)
+ , [uNew] "r" (u32New)
+ , "[fXchg]" (0)
+ RTASM_ARM_DMB_SY_COMMA_IN_REG
+ : "cc");
+ return fXchg.f;
+
+# else
+# error "Port me"
+# 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.
+ * @todo Rename ASMAtomicCmpWriteS32
+ */
+DECLINLINE(bool) ASMAtomicCmpXchgS32(volatile int32_t RT_FAR *pi32, const int32_t i32New, const int32_t i32Old) RT_NOTHROW_DEF
+{
+ return ASMAtomicCmpXchgU32((volatile uint32_t RT_FAR *)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.
+ * @todo Rename ASMAtomicCmpWriteU64
+ */
+#if (RT_INLINE_ASM_EXTERNAL_TMP_ARM && !RT_INLINE_ASM_USES_INTRIN) \
+ || RT_INLINE_DONT_MIX_CMPXCHG8B_AND_PIC
+RT_ASM_DECL_PRAGMA_WATCOM(bool) ASMAtomicCmpXchgU64(volatile uint64_t RT_FAR *pu64, const uint64_t u64New, const uint64_t u64Old) RT_NOTHROW_PROTO;
+#else
+DECLINLINE(bool) ASMAtomicCmpXchgU64(volatile uint64_t RT_FAR *pu64, uint64_t u64New, uint64_t u64Old) RT_NOTHROW_DEF
+{
+# if RT_INLINE_ASM_USES_INTRIN
+ return (uint64_t)_InterlockedCompareExchange64((__int64 RT_FAR *)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)
+ : "cc");
+ 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
+
+# elif defined(RT_ARCH_X86)
+ 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)
+ : "cc");
+# 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) )
+ : "cc");
+# 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
+
+# elif defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32)
+ union { uint32_t u; bool f; } fXchg;
+ uint64_t u64Spill;
+ uint32_t rcSpill;
+ __asm__ __volatile__(".Ltry_again_ASMAtomicCmpXchgU64_%=:\n\t"
+ RTASM_ARM_DMB_SY
+# if defined(RT_ARCH_ARM64)
+ "ldaxr %[uOld], %[pMem]\n\t"
+ "cmp %[uOld], %[uCmp]\n\t"
+ "bne 1f\n\t" /* stop here if not equal */
+ "stlxr %w[rc], %[uNew], %[pMem]\n\t"
+ "cbnz %w[rc], .Ltry_again_ASMAtomicCmpXchgU64_%=\n\t"
+ "mov %w[fXchg], #1\n\t"
+# else
+ "ldrexd %[uOld], %H[uOld], %[pMem]\n\t"
+ "teq %[uOld], %[uCmp]\n\t"
+ "teqeq %H[uOld], %H[uCmp]\n\t"
+ "strexdeq %[rc], %[uNew], %H[uNew], %[pMem]\n\t"
+ "bne 1f\n\t" /* stop here if not equal */
+ "cmp %[rc], #0\n\t"
+ "bne .Ltry_again_ASMAtomicCmpXchgU64_%=\n\t"
+ "mov %[fXchg], #1\n\t"
+# endif
+ "1:\n\t"
+ : [pMem] "+Q" (*pu64)
+ , [uOld] "=&r" (u64Spill)
+ , [rc] "=&r" (rcSpill)
+ , [fXchg] "=&r" (fXchg.u)
+ : [uCmp] "r" (u64Old)
+ , [uNew] "r" (u64New)
+ , "[fXchg]" (0)
+ RTASM_ARM_DMB_SY_COMMA_IN_REG
+ : "cc");
+ return fXchg.f;
+
+# else
+# error "Port me"
+# endif
+}
+#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.
+ * @todo Rename ASMAtomicCmpWriteS64
+ */
+DECLINLINE(bool) ASMAtomicCmpXchgS64(volatile int64_t RT_FAR *pi64, const int64_t i64, const int64_t i64Old) RT_NOTHROW_DEF
+{
+ return ASMAtomicCmpXchgU64((volatile uint64_t RT_FAR *)pi64, (uint64_t)i64, (uint64_t)i64Old);
+}
+
+#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_ARM64) || defined(DOXYGEN_RUNNING)
+
+/** @def RTASM_HAVE_CMP_WRITE_U128
+ * Indicates that we've got ASMAtomicCmpWriteU128(), ASMAtomicCmpWriteU128v2()
+ * and ASMAtomicCmpWriteExU128() available. */
+# define RTASM_HAVE_CMP_WRITE_U128 1
+
+
+/**
+ * Atomically compare and write an unsigned 128-bit value, ordered.
+ *
+ * @returns true if write was done.
+ * @returns false if write wasn't done.
+ *
+ * @param pu128 Pointer to the 128-bit variable to update.
+ * @param u64NewHi The high 64 bits of the value to assign to *pu128.
+ * @param u64NewLo The low 64 bits of the value to assign to *pu128.
+ * @param u64OldHi The high 64-bit of the value to compare with.
+ * @param u64OldLo The low 64-bit of the value to compare with.
+ *
+ * @remarks AMD64: Not present in the earliest CPUs, so check CPUID.
+ */
+# if (RT_INLINE_ASM_EXTERNAL_TMP_ARM && !RT_INLINE_ASM_USES_INTRIN)
+DECLASM(bool) ASMAtomicCmpWriteU128v2(volatile uint128_t *pu128, const uint64_t u64NewHi, const uint64_t u64NewLo,
+ const uint64_t u64OldHi, const uint64_t u64OldLo) RT_NOTHROW_PROTO;
+# else
+DECLINLINE(bool) ASMAtomicCmpWriteU128v2(volatile uint128_t *pu128, const uint64_t u64NewHi, const uint64_t u64NewLo,
+ const uint64_t u64OldHi, const uint64_t u64OldLo) RT_NOTHROW_DEF
+{
+# if RT_INLINE_ASM_USES_INTRIN
+ __int64 ai64Cmp[2];
+ ai64Cmp[0] = u64OldLo;
+ ai64Cmp[1] = u64OldHi;
+ return _InterlockedCompareExchange128((__int64 volatile *)pu128, u64NewHi, u64NewLo, ai64Cmp) != 0;
+
+# elif (defined(__clang_major__) || defined(__GNUC__)) && defined(RT_ARCH_ARM64)
+ return __sync_bool_compare_and_swap(pu128, ((uint128_t)u64OldHi << 64) | u64OldLo, ((uint128_t)u64NewHi << 64) | u64NewLo);
+
+# elif defined(RT_ARCH_AMD64)
+# if RT_INLINE_ASM_GNU_STYLE
+ uint64_t u64Ret;
+ uint64_t u64Spill;
+ __asm__ __volatile__("lock; cmpxchg16b %2\n\t"
+ "setz %%al\n\t"
+ "movzbl %%al, %%eax\n\t"
+ : "=a" (u64Ret)
+ , "=d" (u64Spill)
+ , "+m" (*pu128)
+ : "a" (u64OldLo)
+ , "d" (u64OldHi)
+ , "b" (u64NewLo)
+ , "c" (u64NewHi)
+ : "cc");
+
+ return (bool)u64Ret;
+# else
+# error "Port me"
+# endif
+# else
+# error "Port me"
+# endif
+}
+# endif
+
+
+/**
+ * Atomically compare and write an unsigned 128-bit value, ordered.
+ *
+ * @returns true if write was done.
+ * @returns false if write wasn't done.
+ *
+ * @param pu128 Pointer to the 128-bit variable to update.
+ * @param u128New The 128-bit value to assign to *pu128.
+ * @param u128Old The value to compare with.
+ *
+ * @remarks AMD64: Not present in the earliest CPUs, so check CPUID.
+ */
+DECLINLINE(bool) ASMAtomicCmpWriteU128(volatile uint128_t *pu128, const uint128_t u128New, const uint128_t u128Old) RT_NOTHROW_DEF
+{
+# ifdef RT_COMPILER_WITH_128BIT_INT_TYPES
+# if (defined(__clang_major__) || defined(__GNUC__)) && defined(RT_ARCH_ARM64)
+ return __sync_bool_compare_and_swap(pu128, u128Old, u128New);
+# else
+ return ASMAtomicCmpWriteU128v2(pu128, (uint64_t)(u128New >> 64), (uint64_t)u128New,
+ (uint64_t)(u128Old >> 64), (uint64_t)u128Old);
+# endif
+# else
+ return ASMAtomicCmpWriteU128v2(pu128, u128New.Hi, u128New.Lo, u128Old.Hi, u128Old.Lo);
+# endif
+}
+
+
+/**
+ * RTUINT128U wrapper for ASMAtomicCmpWriteU128.
+ */
+DECLINLINE(bool) ASMAtomicCmpWriteU128U(volatile RTUINT128U *pu128, const RTUINT128U u128New,
+ const RTUINT128U u128Old) RT_NOTHROW_DEF
+{
+# if (defined(__clang_major__) || defined(__GNUC__)) && defined(RT_ARCH_ARM64)
+ return ASMAtomicCmpWriteU128(&pu128->u, u128New.u, u128Old.u);
+# else
+ return ASMAtomicCmpWriteU128v2(&pu128->u, u128New.s.Hi, u128New.s.Lo, u128Old.s.Hi, u128Old.s.Lo);
+# endif
+}
+
+#endif /* RT_ARCH_AMD64 || RT_ARCH_ARM64 */
+
+/**
+ * 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.
+ * @todo Rename ASMAtomicCmpWritePtrVoid
+ */
+DECLINLINE(bool) ASMAtomicCmpXchgPtrVoid(void RT_FAR * volatile RT_FAR *ppv, const void RT_FAR *pvNew, const void RT_FAR *pvOld) RT_NOTHROW_DEF
+{
+#if ARCH_BITS == 32 || ARCH_BITS == 16
+ return ASMAtomicCmpXchgU32((volatile uint32_t RT_FAR *)(void RT_FAR *)ppv, (uint32_t)pvNew, (uint32_t)pvOld);
+#elif ARCH_BITS == 64
+ return ASMAtomicCmpXchgU64((volatile uint64_t RT_FAR *)(void RT_FAR *)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.
+ * @todo Rename ASMAtomicCmpWritePtr
+ */
+#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 RT_FAR * volatile RT_FAR *)(ppv), (void RT_FAR *)(pvNew), (void RT_FAR *)(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.
+ * @todo Rename ASMAtomicCmpWriteHandle
+ */
+#if HC_ARCH_BITS == 32 || ARCH_BITS == 16
+# define ASMAtomicCmpXchgHandle(ph, hNew, hOld, fRc) \
+ do { \
+ AssertCompile(sizeof(*(ph)) == sizeof(uint32_t)); \
+ (fRc) = ASMAtomicCmpXchgU32((uint32_t volatile RT_FAR *)(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 RT_FAR *)(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.
+ * @todo Rename ASMAtomicCmpWriteSize
+ */
+#define ASMAtomicCmpXchgSize(pu, uNew, uOld, fRc) \
+ do { \
+ switch (sizeof(*(pu))) { \
+ case 4: (fRc) = ASMAtomicCmpXchgU32((volatile uint32_t RT_FAR *)(void RT_FAR *)(pu), (uint32_t)(uNew), (uint32_t)(uOld)); \
+ break; \
+ case 8: (fRc) = ASMAtomicCmpXchgU64((volatile uint64_t RT_FAR *)(void RT_FAR *)(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 8-bit value, additionally passes
+ * back old 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 *pu32.
+ * @param u8Old The old value to *pu8 compare with.
+ * @param pu8Old Pointer store the old value at.
+ *
+ * @remarks x86: Requires a 486 or later.
+ */
+#if RT_INLINE_ASM_EXTERNAL_TMP_ARM && !RT_INLINE_ASM_USES_INTRIN
+RT_ASM_DECL_PRAGMA_WATCOM(bool) ASMAtomicCmpXchgExU8(volatile uint8_t RT_FAR *pu8, const uint8_t u8New, const uint8_t u8Old, uint8_t RT_FAR *pu8Old) RT_NOTHROW_PROTO;
+#else
+DECLINLINE(bool) ASMAtomicCmpXchgExU8(volatile uint8_t RT_FAR *pu8, const uint8_t u8New, const uint8_t u8Old, uint8_t RT_FAR *pu8Old) RT_NOTHROW_DEF
+{
+# if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
+# if RT_INLINE_ASM_GNU_STYLE
+ uint8_t u8Ret;
+ __asm__ __volatile__("lock; cmpxchgb %3, %0\n\t"
+ "setz %1\n\t"
+ : "=m" (*pu8)
+ , "=qm" (u8Ret)
+ , "=a" (*pu8Old)
+# if defined(RT_ARCH_X86)
+ : "q" (u8New)
+# else
+ : "r" (u8New)
+# endif
+ , "a" (u8Old)
+ , "m" (*pu8)
+ : "cc");
+ return (bool)u8Ret;
+
+# elif RT_INLINE_ASM_USES_INTRIN
+ return (*pu8Old = _InterlockedCompareExchange8((char RT_FAR *)pu8, u8New, u8Old)) == u8Old;
+
+# else
+ uint8_t u8Ret;
+ __asm
+ {
+# ifdef RT_ARCH_AMD64
+ mov rdx, [pu8]
+# else
+ mov edx, [pu8]
+# endif
+ mov eax, [u8Old]
+ mov ecx, [u8New]
+# ifdef RT_ARCH_AMD64
+ lock cmpxchg [rdx], ecx
+ mov rdx, [pu8Old]
+ mov [rdx], eax
+# else
+ lock cmpxchg [edx], ecx
+ mov edx, [pu8Old]
+ mov [edx], eax
+# endif
+ setz al
+ movzx eax, al
+ mov [u8Ret], eax
+ }
+ return !!u8Ret;
+# endif
+
+# elif defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32)
+ union { uint8_t u; bool f; } fXchg;
+ uint8_t u8ActualOld;
+ uint8_t rcSpill;
+ __asm__ __volatile__(".Ltry_again_ASMAtomicCmpXchgExU8_%=:\n\t"
+ RTASM_ARM_DMB_SY
+# if defined(RT_ARCH_ARM64)
+ "ldaxrb %w[uOld], %[pMem]\n\t"
+ "cmp %w[uOld], %w[uCmp]\n\t"
+ "bne 1f\n\t" /* stop here if not equal */
+ "stlxrb %w[rc], %w[uNew], %[pMem]\n\t"
+ "cbnz %w[rc], .Ltry_again_ASMAtomicCmpXchgExU8_%=\n\t"
+ "mov %w[fXchg], #1\n\t"
+# else
+ "ldrexb %[uOld], %[pMem]\n\t"
+ "teq %[uOld], %[uCmp]\n\t"
+ "strexbeq %[rc], %[uNew], %[pMem]\n\t"
+ "bne 1f\n\t" /* stop here if not equal */
+ "cmp %[rc], #0\n\t"
+ "bne .Ltry_again_ASMAtomicCmpXchgExU8_%=\n\t"
+ "mov %[fXchg], #1\n\t"
+# endif
+ "1:\n\t"
+ : [pMem] "+Q" (*pu8)
+ , [uOld] "=&r" (u8ActualOld)
+ , [rc] "=&r" (rcSpill)
+ , [fXchg] "=&r" (fXchg.u)
+ : [uCmp] "r" (u8Old)
+ , [uNew] "r" (u8New)
+ , "[fXchg]" (0)
+ RTASM_ARM_DMB_SY_COMMA_IN_REG
+ : "cc");
+ *pu8Old = u8ActualOld;
+ return fXchg.f;
+
+# else
+# error "Port me"
+# endif
+}
+#endif
+
+
+/**
+ * Atomically Compare and Exchange a signed 8-bit value, additionally
+ * passes back old 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.
+ * @param pi8Old Pointer store the old value at.
+ *
+ * @remarks x86: Requires a 486 or later.
+ */
+DECLINLINE(bool) ASMAtomicCmpXchgExS8(volatile int8_t RT_FAR *pi8, const int8_t i8New, const int8_t i8Old, int8_t RT_FAR *pi8Old) RT_NOTHROW_DEF
+{
+ return ASMAtomicCmpXchgExU8((volatile uint8_t RT_FAR *)pi8, (uint8_t)i8New, (uint8_t)i8Old, (uint8_t RT_FAR *)pi8Old);
+}
+
+
+/**
+ * Atomically Compare and Exchange an unsigned 16-bit value, additionally passes
+ * back old value, ordered.
+ *
+ * @returns true if xchg was done.
+ * @returns false if xchg wasn't done.
+ *
+ * @param pu16 Pointer to the value to update.
+ * @param u16New The new value to assigned to *pu16.
+ * @param u16Old The old value to *pu32 compare with.
+ * @param pu16Old Pointer store the old value at.
+ *
+ * @remarks x86: Requires a 486 or later.
+ */
+#if RT_INLINE_ASM_EXTERNAL_TMP_ARM && !RT_INLINE_ASM_USES_INTRIN
+RT_ASM_DECL_PRAGMA_WATCOM(bool) ASMAtomicCmpXchgExU16(volatile uint16_t RT_FAR *pu16, const uint16_t u16New, const uint16_t u16Old, uint16_t RT_FAR *pu16Old) RT_NOTHROW_PROTO;
+#else
+DECLINLINE(bool) ASMAtomicCmpXchgExU16(volatile uint16_t RT_FAR *pu16, const uint16_t u16New, const uint16_t u16Old, uint16_t RT_FAR *pu16Old) RT_NOTHROW_DEF
+{
+# if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
+# if RT_INLINE_ASM_GNU_STYLE
+ uint8_t u8Ret;
+ __asm__ __volatile__("lock; cmpxchgw %3, %0\n\t"
+ "setz %1\n\t"
+ : "=m" (*pu16)
+ , "=qm" (u8Ret)
+ , "=a" (*pu16Old)
+ : "r" (u16New)
+ , "a" (u16Old)
+ , "m" (*pu16)
+ : "cc");
+ return (bool)u8Ret;
+
+# elif RT_INLINE_ASM_USES_INTRIN
+ return (*pu16Old = _InterlockedCompareExchange16((short RT_FAR *)pu16, u16New, u16Old)) == u16Old;
+
+# else
+ uint16_t u16Ret;
+ __asm
+ {
+# ifdef RT_ARCH_AMD64
+ mov rdx, [pu16]
+# else
+ mov edx, [pu16]
+# endif
+ mov eax, [u16Old]
+ mov ecx, [u16New]
+# ifdef RT_ARCH_AMD64
+ lock cmpxchg [rdx], ecx
+ mov rdx, [pu16Old]
+ mov [rdx], eax
+# else
+ lock cmpxchg [edx], ecx
+ mov edx, [pu16Old]
+ mov [edx], eax
+# endif
+ setz al
+ movzx eax, al
+ mov [u16Ret], eax
+ }
+ return !!u16Ret;
+# endif
+
+# elif defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32)
+ union { uint16_t u; bool f; } fXchg;
+ uint16_t u16ActualOld;
+ uint16_t rcSpill;
+ __asm__ __volatile__(".Ltry_again_ASMAtomicCmpXchgExU16_%=:\n\t"
+ RTASM_ARM_DMB_SY
+# if defined(RT_ARCH_ARM64)
+ "ldaxrh %w[uOld], %[pMem]\n\t"
+ "cmp %w[uOld], %w[uCmp]\n\t"
+ "bne 1f\n\t" /* stop here if not equal */
+ "stlxrh %w[rc], %w[uNew], %[pMem]\n\t"
+ "cbnz %w[rc], .Ltry_again_ASMAtomicCmpXchgExU16_%=\n\t"
+ "mov %w[fXchg], #1\n\t"
+# else
+ "ldrexh %[uOld], %[pMem]\n\t"
+ "teq %[uOld], %[uCmp]\n\t"
+ "strexheq %[rc], %[uNew], %[pMem]\n\t"
+ "bne 1f\n\t" /* stop here if not equal */
+ "cmp %[rc], #0\n\t"
+ "bne .Ltry_again_ASMAtomicCmpXchgExU16_%=\n\t"
+ "mov %[fXchg], #1\n\t"
+# endif
+ "1:\n\t"
+ : [pMem] "+Q" (*pu16)
+ , [uOld] "=&r" (u16ActualOld)
+ , [rc] "=&r" (rcSpill)
+ , [fXchg] "=&r" (fXchg.u)
+ : [uCmp] "r" (u16Old)
+ , [uNew] "r" (u16New)
+ , "[fXchg]" (0)
+ RTASM_ARM_DMB_SY_COMMA_IN_REG
+ : "cc");
+ *pu16Old = u16ActualOld;
+ return fXchg.f;
+
+# else
+# error "Port me"
+# endif
+}
+#endif
+
+
+/**
+ * Atomically Compare and Exchange a signed 16-bit value, additionally
+ * passes back old value, ordered.
+ *
+ * @returns true if xchg was done.
+ * @returns false if xchg wasn't done.
+ *
+ * @param pi16 Pointer to the value to update.
+ * @param i16New The new value to assigned to *pi16.
+ * @param i16Old The old value to *pi16 compare with.
+ * @param pi16Old Pointer store the old value at.
+ *
+ * @remarks x86: Requires a 486 or later.
+ */
+DECLINLINE(bool) ASMAtomicCmpXchgExS16(volatile int16_t RT_FAR *pi16, const int16_t i16New, const int16_t i16Old, int16_t RT_FAR *pi16Old) RT_NOTHROW_DEF
+{
+ return ASMAtomicCmpXchgExU16((volatile uint16_t RT_FAR *)pi16, (uint16_t)i16New, (uint16_t)i16Old, (uint16_t RT_FAR *)pi16Old);
+}
+
+
+/**
+ * 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_TMP_ARM && !RT_INLINE_ASM_USES_INTRIN
+RT_ASM_DECL_PRAGMA_WATCOM(bool) ASMAtomicCmpXchgExU32(volatile uint32_t RT_FAR *pu32, const uint32_t u32New, const uint32_t u32Old, uint32_t RT_FAR *pu32Old) RT_NOTHROW_PROTO;
+#else
+DECLINLINE(bool) ASMAtomicCmpXchgExU32(volatile uint32_t RT_FAR *pu32, const uint32_t u32New, const uint32_t u32Old, uint32_t RT_FAR *pu32Old) RT_NOTHROW_DEF
+{
+# if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
+# 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)
+ : "cc");
+ return (bool)u8Ret;
+
+# elif RT_INLINE_ASM_USES_INTRIN
+ return (*pu32Old = _InterlockedCompareExchange((long RT_FAR *)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
+
+# elif defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32)
+ union { uint32_t u; bool f; } fXchg;
+ uint32_t u32ActualOld;
+ uint32_t rcSpill;
+ __asm__ __volatile__(".Ltry_again_ASMAtomicCmpXchgExU32_%=:\n\t"
+ RTASM_ARM_DMB_SY
+# if defined(RT_ARCH_ARM64)
+ "ldaxr %w[uOld], %[pMem]\n\t"
+ "cmp %w[uOld], %w[uCmp]\n\t"
+ "bne 1f\n\t" /* stop here if not equal */
+ "stlxr %w[rc], %w[uNew], %[pMem]\n\t"
+ "cbnz %w[rc], .Ltry_again_ASMAtomicCmpXchgExU32_%=\n\t"
+ "mov %w[fXchg], #1\n\t"
+# else
+ "ldrex %[uOld], %[pMem]\n\t"
+ "teq %[uOld], %[uCmp]\n\t"
+ "strexeq %[rc], %[uNew], %[pMem]\n\t"
+ "bne 1f\n\t" /* stop here if not equal */
+ "cmp %[rc], #0\n\t"
+ "bne .Ltry_again_ASMAtomicCmpXchgExU32_%=\n\t"
+ "mov %[fXchg], #1\n\t"
+# endif
+ "1:\n\t"
+ : [pMem] "+Q" (*pu32)
+ , [uOld] "=&r" (u32ActualOld)
+ , [rc] "=&r" (rcSpill)
+ , [fXchg] "=&r" (fXchg.u)
+ : [uCmp] "r" (u32Old)
+ , [uNew] "r" (u32New)
+ , "[fXchg]" (0)
+ RTASM_ARM_DMB_SY_COMMA_IN_REG
+ : "cc");
+ *pu32Old = u32ActualOld;
+ return fXchg.f;
+
+# else
+# error "Port me"
+# 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 RT_FAR *pi32, const int32_t i32New, const int32_t i32Old, int32_t RT_FAR *pi32Old) RT_NOTHROW_DEF
+{
+ return ASMAtomicCmpXchgExU32((volatile uint32_t RT_FAR *)pi32, (uint32_t)i32New, (uint32_t)i32Old, (uint32_t RT_FAR *)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_TMP_ARM && !RT_INLINE_ASM_USES_INTRIN) \
+ || RT_INLINE_DONT_MIX_CMPXCHG8B_AND_PIC
+RT_ASM_DECL_PRAGMA_WATCOM(bool) ASMAtomicCmpXchgExU64(volatile uint64_t RT_FAR *pu64, const uint64_t u64New, const uint64_t u64Old, uint64_t RT_FAR *pu64Old) RT_NOTHROW_PROTO;
+#else
+DECLINLINE(bool) ASMAtomicCmpXchgExU64(volatile uint64_t RT_FAR *pu64, const uint64_t u64New, const uint64_t u64Old, uint64_t RT_FAR *pu64Old) RT_NOTHROW_DEF
+{
+# if RT_INLINE_ASM_USES_INTRIN
+ return (*pu64Old =_InterlockedCompareExchange64((__int64 RT_FAR *)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)
+ : "cc");
+ 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
+
+# elif defined(RT_ARCH_X86)
+# if RT_INLINE_ASM_GNU_STYLE
+ uint64_t u64Ret;
+# if defined(PIC) || defined(__PIC__)
+ /* Note #1: 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.
+
+ Note #2: We must prevent gcc from encoding the memory access, as it
+ may go via the GOT if we're working on a global variable (like
+ in the testcase). Thus we request a register (%3) and
+ dereference it ourselves. */
+ __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))
+ , "r" (pu64) /* Do not use "m" here*/
+ , "0" (u64Old)
+ : "memory"
+ , "cc" );
+# 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)
+ : "cc");
+# 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
+
+# elif defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32)
+ union { uint32_t u; bool f; } fXchg;
+ uint64_t u64ActualOld;
+ uint32_t rcSpill;
+ __asm__ __volatile__(".Ltry_again_ASMAtomicCmpXchgU64_%=:\n\t"
+ RTASM_ARM_DMB_SY
+# if defined(RT_ARCH_ARM64)
+ "ldaxr %[uOld], %[pMem]\n\t"
+ "cmp %[uOld], %[uCmp]\n\t"
+ "bne 1f\n\t" /* stop here if not equal */
+ "stlxr %w[rc], %[uNew], %[pMem]\n\t"
+ "cbnz %w[rc], .Ltry_again_ASMAtomicCmpXchgU64_%=\n\t"
+ "mov %w[fXchg], #1\n\t"
+# else
+ "ldrexd %[uOld], %H[uOld], %[pMem]\n\t"
+ "teq %[uOld], %[uCmp]\n\t"
+ "teqeq %H[uOld], %H[uCmp]\n\t"
+ "strexdeq %[rc], %[uNew], %H[uNew], %[pMem]\n\t"
+ "bne 1f\n\t" /* stop here if not equal */
+ "cmp %[rc], #0\n\t"
+ "bne .Ltry_again_ASMAtomicCmpXchgU64_%=\n\t"
+ "mov %[fXchg], #1\n\t"
+# endif
+ "1:\n\t"
+ : [pMem] "+Q" (*pu64)
+ , [uOld] "=&r" (u64ActualOld)
+ , [rc] "=&r" (rcSpill)
+ , [fXchg] "=&r" (fXchg.u)
+ : [uCmp] "r" (u64Old)
+ , [uNew] "r" (u64New)
+ , "[fXchg]" (0)
+ RTASM_ARM_DMB_SY_COMMA_IN_REG
+ : "cc");
+ *pu64Old = u64ActualOld;
+ return fXchg.f;
+
+# else
+# error "Port me"
+# endif
+}
+#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 RT_FAR *pi64, const int64_t i64, const int64_t i64Old, int64_t RT_FAR *pi64Old) RT_NOTHROW_DEF
+{
+ return ASMAtomicCmpXchgExU64((volatile uint64_t RT_FAR *)pi64, (uint64_t)i64, (uint64_t)i64Old, (uint64_t RT_FAR *)pi64Old);
+}
+
+#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_ARM64) || defined(DOXYGEN_RUNNING)
+
+/** @def RTASM_HAVE_CMP_XCHG_U128
+ * Indicates that we've got ASMAtomicCmpSwapU128(), ASMAtomicCmpSwapU128v2()
+ * and ASMAtomicCmpSwapExU128() available. */
+# define RTASM_HAVE_CMP_XCHG_U128 1
+
+
+/**
+ * Atomically compare and exchange an unsigned 128-bit value, ordered.
+ *
+ * @returns true if exchange was done.
+ * @returns false if exchange wasn't done.
+ *
+ * @param pu128 Pointer to the 128-bit variable to update.
+ * @param u64NewHi The high 64 bits of the value to assign to *pu128.
+ * @param u64NewLo The low 64 bits of the value to assign to *pu128.
+ * @param u64OldHi The high 64-bit of the value to compare with.
+ * @param u64OldLo The low 64-bit of the value to compare with.
+ * @param pu128Old Where to return the old value.
+ *
+ * @remarks AMD64: Not present in the earliest CPUs, so check CPUID.
+ */
+# if (RT_INLINE_ASM_EXTERNAL_TMP_ARM && !RT_INLINE_ASM_USES_INTRIN)
+DECLASM(bool) ASMAtomicCmpXchgU128v2(volatile uint128_t *pu128, const uint64_t u64NewHi, const uint64_t u64NewLo,
+ const uint64_t u64OldHi, const uint64_t u64OldLo, uint128_t *pu128Old) RT_NOTHROW_PROTO;
+# else
+DECLINLINE(bool) ASMAtomicCmpXchgU128v2(volatile uint128_t *pu128, const uint64_t u64NewHi, const uint64_t u64NewLo,
+ const uint64_t u64OldHi, const uint64_t u64OldLo, uint128_t *pu128Old) RT_NOTHROW_DEF
+{
+# if RT_INLINE_ASM_USES_INTRIN
+ pu128Old->Hi = u64OldHi;
+ pu128Old->Lo = u64OldLo;
+ AssertCompileMemberOffset(uint128_t, Lo, 0);
+ return _InterlockedCompareExchange128((__int64 volatile *)pu128, u64NewHi, u64NewLo, (__int64 *)&pu128Old->Lo) != 0;
+
+# elif (defined(__clang_major__) || defined(__GNUC__)) && defined(RT_ARCH_ARM64)
+ uint128_t const uCmp = ((uint128_t)u64OldHi << 64) | u64OldLo;
+ uint128_t const uOld = __sync_val_compare_and_swap(pu128, uCmp, ((uint128_t)u64NewHi << 64) | u64NewLo);
+ *pu128Old = uOld;
+ return uCmp == uOld;
+
+# elif defined(RT_ARCH_AMD64)
+# if RT_INLINE_ASM_GNU_STYLE
+ uint8_t bRet;
+ uint64_t u64RetHi, u64RetLo;
+ __asm__ __volatile__("lock; cmpxchg16b %3\n\t"
+ "setz %b0\n\t"
+ : "=r" (bRet)
+ , "=a" (u64RetLo)
+ , "=d" (u64RetHi)
+ , "+m" (*pu128)
+ : "a" (u64OldLo)
+ , "d" (u64OldHi)
+ , "b" (u64NewLo)
+ , "c" (u64NewHi)
+ : "cc");
+ *pu128Old = ((uint128_t)u64RetHi << 64) | u64RetLo;
+ return (bool)bRet;
+# else
+# error "Port me"
+# endif
+# else
+# error "Port me"
+# endif
+}
+# endif
+
+
+/**
+ * Atomically compare and exchange an unsigned 128-bit value, ordered.
+ *
+ * @returns true if exchange was done.
+ * @returns false if exchange wasn't done.
+ *
+ * @param pu128 Pointer to the 128-bit variable to update.
+ * @param u128New The 128-bit value to assign to *pu128.
+ * @param u128Old The value to compare with.
+ * @param pu128Old Where to return the old value.
+ *
+ * @remarks AMD64: Not present in the earliest CPUs, so check CPUID.
+ */
+DECLINLINE(bool) ASMAtomicCmpXchgU128(volatile uint128_t *pu128, const uint128_t u128New,
+ const uint128_t u128Old, uint128_t *pu128Old) RT_NOTHROW_DEF
+{
+# ifdef RT_COMPILER_WITH_128BIT_INT_TYPES
+# if (defined(__clang_major__) || defined(__GNUC__)) && defined(RT_ARCH_ARM64)
+ uint128_t const uSwapped = __sync_val_compare_and_swap(pu128, u128Old, u128New);
+ *pu128Old = uSwapped;
+ return uSwapped == u128Old;
+# else
+ return ASMAtomicCmpXchgU128v2(pu128, (uint64_t)(u128New >> 64), (uint64_t)u128New,
+ (uint64_t)(u128Old >> 64), (uint64_t)u128Old, pu128Old);
+# endif
+# else
+ return ASMAtomicCmpXchgU128v2(pu128, u128New.Hi, u128New.Lo, u128Old.Hi, u128Old.Lo, pu128Old);
+# endif
+}
+
+
+/**
+ * RTUINT128U wrapper for ASMAtomicCmpXchgU128.
+ */
+DECLINLINE(bool) ASMAtomicCmpXchgU128U(volatile RTUINT128U *pu128, const RTUINT128U u128New,
+ const RTUINT128U u128Old, PRTUINT128U pu128Old) RT_NOTHROW_DEF
+{
+# if (defined(__clang_major__) || defined(__GNUC__)) && defined(RT_ARCH_ARM64)
+ return ASMAtomicCmpXchgU128(&pu128->u, u128New.u, u128Old.u, &pu128Old->u);
+# else
+ return ASMAtomicCmpXchgU128v2(&pu128->u, u128New.s.Hi, u128New.s.Lo, u128Old.s.Hi, u128Old.s.Lo, &pu128Old->u);
+# endif
+}
+
+#endif /* RT_ARCH_AMD64 || RT_ARCH_ARM64 */
+
+
+
+/** @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
+# 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 RT_FAR *)(ph), (uint32_t)(hNew), (uint32_t)(hOld), (uint32_t RT_FAR *)(phOldVal)); \
+ } 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 RT_FAR *)(ph), (uint64_t)(hNew), (uint64_t)(hOld), (uint64_t RT_FAR *)(phOldVal)); \
+ } 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 RT_FAR *)(void RT_FAR *)(pu), (uint32_t)(uNew), (uint32_t)(uOld), (uint32_t RT_FAR *)(uOldVal)); \
+ break; \
+ case 8: (fRc) = ASMAtomicCmpXchgExU64((volatile uint64_t RT_FAR *)(void RT_FAR *)(pu), (uint64_t)(uNew), (uint64_t)(uOld), (uint64_t RT_FAR *)(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 RT_FAR * volatile RT_FAR *ppv, const void RT_FAR *pvNew, const void RT_FAR *pvOld,
+ void RT_FAR * RT_FAR *ppvOld) RT_NOTHROW_DEF
+{
+#if ARCH_BITS == 32 || ARCH_BITS == 16
+ return ASMAtomicCmpXchgExU32((volatile uint32_t RT_FAR *)(void RT_FAR *)ppv, (uint32_t)pvNew, (uint32_t)pvOld, (uint32_t RT_FAR *)ppvOld);
+#elif ARCH_BITS == 64
+ return ASMAtomicCmpXchgExU64((volatile uint64_t RT_FAR *)(void RT_FAR *)ppv, (uint64_t)pvNew, (uint64_t)pvOld, (uint64_t RT_FAR *)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 RT_FAR * volatile RT_FAR *)(ppv), (void RT_FAR *)(pvNew), (void RT_FAR *)(pvOld), (void RT_FAR * RT_FAR *)(ppvOld))
+#endif
+
+
+/**
+ * Virtualization unfriendly serializing instruction, always exits.
+ */
+#if (RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN) || (!defined(RT_ARCH_AMD64) && !defined(RT_ARCH_X86))
+RT_ASM_DECL_PRAGMA_WATCOM(void) ASMSerializeInstructionCpuId(void) RT_NOTHROW_PROTO;
+#else
+DECLINLINE(void) ASMSerializeInstructionCpuId(void) RT_NOTHROW_DEF
+{
+# 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 || (!defined(RT_ARCH_AMD64) && !defined(RT_ARCH_X86))
+RT_ASM_DECL_PRAGMA_WATCOM(void) ASMSerializeInstructionIRet(void) RT_NOTHROW_PROTO;
+#else
+DECLINLINE(void) ASMSerializeInstructionIRet(void) RT_NOTHROW_DEF
+{
+# 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", "cc");
+# 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 < RT_MSC_VER_VS2008) || (!defined(RT_ARCH_AMD64) && !defined(RT_ARCH_X86))
+RT_ASM_DECL_PRAGMA_WATCOM(void) ASMSerializeInstructionRdTscp(void) RT_NOTHROW_PROTO;
+#else
+DECLINLINE(void) ASMSerializeInstructionRdTscp(void) RT_NOTHROW_DEF
+{
+# 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 >= RT_MSC_VER_VS2008
+ uint32_t uIgnore;
+ _ReadWriteBarrier();
+ (void)__rdtscp(&uIgnore);
+ (void)uIgnore;
+# else
+ __asm
+ {
+ rdtscp
+ }
+# endif
+# endif
+}
+#endif
+
+
+/**
+ * Serialize Instruction (both data store and instruction flush).
+ */
+#if (defined(RT_ARCH_X86) && ARCH_BITS == 16) || defined(IN_GUEST)
+# define ASMSerializeInstruction() ASMSerializeInstructionIRet()
+#elif defined(RT_ARCH_X86) || defined(RT_ARCH_AMD64)
+# define ASMSerializeInstruction() ASMSerializeInstructionCpuId()
+#elif defined(RT_ARCH_SPARC64)
+RTDECL(void) ASMSerializeInstruction(void) RT_NOTHROW_PROTO;
+#elif defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32)
+DECLINLINE(void) ASMSerializeInstruction(void) RT_NOTHROW_DEF
+{
+ __asm__ __volatile__ (RTASM_ARM_DSB_SY :: RTASM_ARM_DSB_SY_IN_REG :);
+}
+#else
+# error "Port me"
+#endif
+
+
+/**
+ * Memory fence, waits for any pending writes and reads to complete.
+ * @note No implicit compiler barrier (which is probably stupid).
+ */
+DECLINLINE(void) ASMMemoryFence(void) RT_NOTHROW_DEF
+{
+#if defined(RT_ARCH_AMD64) || (defined(RT_ARCH_X86) && !defined(RT_WITH_OLD_CPU_SUPPORT))
+# 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
+#elif defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32)
+ __asm__ __volatile__ (RTASM_ARM_DMB_SY :: RTASM_ARM_DMB_SY_IN_REG :);
+#elif 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.
+ * @note No implicit compiler barrier (which is probably stupid).
+ */
+DECLINLINE(void) ASMWriteFence(void) RT_NOTHROW_DEF
+{
+#if defined(RT_ARCH_AMD64) || (defined(RT_ARCH_X86) && !defined(RT_WITH_OLD_CPU_SUPPORT))
+# 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
+#elif defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32)
+ __asm__ __volatile__ (RTASM_ARM_DMB_ST :: RTASM_ARM_DMB_ST_IN_REG :);
+#else
+ ASMMemoryFence();
+#endif
+}
+
+
+/**
+ * Read fence, waits for any pending reads to complete.
+ * @note No implicit compiler barrier (which is probably stupid).
+ */
+DECLINLINE(void) ASMReadFence(void) RT_NOTHROW_DEF
+{
+#if defined(RT_ARCH_AMD64) || (defined(RT_ARCH_X86) && !defined(RT_WITH_OLD_CPU_SUPPORT))
+# 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
+#elif defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32)
+ __asm__ __volatile__ (RTASM_ARM_DMB_LD :: RTASM_ARM_DMB_LD_IN_REG :);
+#else
+ ASMMemoryFence();
+#endif
+}
+
+
+/**
+ * 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 RT_FAR *pu8) RT_NOTHROW_DEF
+{
+#if defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32)
+ uint32_t u32;
+ __asm__ __volatile__(".Lstart_ASMAtomicReadU8_%=:\n\t"
+ RTASM_ARM_DMB_SY
+# if defined(RT_ARCH_ARM64)
+ "ldxrb %w[uDst], %[pMem]\n\t"
+# else
+ "ldrexb %[uDst], %[pMem]\n\t"
+# endif
+ : [uDst] "=&r" (u32)
+ : [pMem] "Q" (*pu8)
+ RTASM_ARM_DMB_SY_COMMA_IN_REG);
+ return (uint8_t)u32;
+#else
+ ASMMemoryFence();
+ return *pu8; /* byte reads are atomic on x86 */
+#endif
+}
+
+
+/**
+ * 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 RT_FAR *pu8) RT_NOTHROW_DEF
+{
+#if defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32)
+ uint32_t u32;
+ __asm__ __volatile__(".Lstart_ASMAtomicUoReadU8_%=:\n\t"
+# if defined(RT_ARCH_ARM64)
+ "ldxrb %w[uDst], %[pMem]\n\t"
+# else
+ "ldrexb %[uDst], %[pMem]\n\t"
+# endif
+ : [uDst] "=&r" (u32)
+ : [pMem] "Q" (*pu8));
+ return (uint8_t)u32;
+#else
+ return *pu8; /* byte reads are atomic on x86 */
+#endif
+}
+
+
+/**
+ * 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 RT_FAR *pi8) RT_NOTHROW_DEF
+{
+ ASMMemoryFence();
+#if defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32)
+ int32_t i32;
+ __asm__ __volatile__(".Lstart_ASMAtomicReadS8_%=:\n\t"
+ RTASM_ARM_DMB_SY
+# if defined(RT_ARCH_ARM64)
+ "ldxrb %w[iDst], %[pMem]\n\t"
+# else
+ "ldrexb %[iDst], %[pMem]\n\t"
+# endif
+ : [iDst] "=&r" (i32)
+ : [pMem] "Q" (*pi8)
+ RTASM_ARM_DMB_SY_COMMA_IN_REG);
+ return (int8_t)i32;
+#else
+ return *pi8; /* byte reads are atomic on x86 */
+#endif
+}
+
+
+/**
+ * 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 RT_FAR *pi8) RT_NOTHROW_DEF
+{
+#if defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32)
+ int32_t i32;
+ __asm__ __volatile__(".Lstart_ASMAtomicUoReadS8_%=:\n\t"
+# if defined(RT_ARCH_ARM64)
+ "ldxrb %w[iDst], %[pMem]\n\t"
+# else
+ "ldrexb %[iDst], %[pMem]\n\t"
+# endif
+ : [iDst] "=&r" (i32)
+ : [pMem] "Q" (*pi8));
+ return (int8_t)i32;
+#else
+ return *pi8; /* byte reads are atomic on x86 */
+#endif
+}
+
+
+/**
+ * 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 RT_FAR *pu16) RT_NOTHROW_DEF
+{
+ Assert(!((uintptr_t)pu16 & 1));
+#if defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32)
+ uint32_t u32;
+ __asm__ __volatile__(".Lstart_ASMAtomicReadU16_%=:\n\t"
+ RTASM_ARM_DMB_SY
+# if defined(RT_ARCH_ARM64)
+ "ldxrh %w[uDst], %[pMem]\n\t"
+# else
+ "ldrexh %[uDst], %[pMem]\n\t"
+# endif
+ : [uDst] "=&r" (u32)
+ : [pMem] "Q" (*pu16)
+ RTASM_ARM_DMB_SY_COMMA_IN_REG);
+ return (uint16_t)u32;
+#else
+ ASMMemoryFence();
+ return *pu16;
+#endif
+}
+
+
+/**
+ * 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 RT_FAR *pu16) RT_NOTHROW_DEF
+{
+ Assert(!((uintptr_t)pu16 & 1));
+#if defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32)
+ uint32_t u32;
+ __asm__ __volatile__(".Lstart_ASMAtomicUoReadU16_%=:\n\t"
+# if defined(RT_ARCH_ARM64)
+ "ldxrh %w[uDst], %[pMem]\n\t"
+# else
+ "ldrexh %[uDst], %[pMem]\n\t"
+# endif
+ : [uDst] "=&r" (u32)
+ : [pMem] "Q" (*pu16));
+ return (uint16_t)u32;
+#else
+ return *pu16;
+#endif
+}
+
+
+/**
+ * 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 RT_FAR *pi16) RT_NOTHROW_DEF
+{
+ Assert(!((uintptr_t)pi16 & 1));
+#if defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32)
+ int32_t i32;
+ __asm__ __volatile__(".Lstart_ASMAtomicReadS16_%=:\n\t"
+ RTASM_ARM_DMB_SY
+# if defined(RT_ARCH_ARM64)
+ "ldxrh %w[iDst], %[pMem]\n\t"
+# else
+ "ldrexh %[iDst], %[pMem]\n\t"
+# endif
+ : [iDst] "=&r" (i32)
+ : [pMem] "Q" (*pi16)
+ RTASM_ARM_DMB_SY_COMMA_IN_REG);
+ return (int16_t)i32;
+#else
+ ASMMemoryFence();
+ return *pi16;
+#endif
+}
+
+
+/**
+ * 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 RT_FAR *pi16) RT_NOTHROW_DEF
+{
+ Assert(!((uintptr_t)pi16 & 1));
+#if defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32)
+ int32_t i32;
+ __asm__ __volatile__(".Lstart_ASMAtomicUoReadS16_%=:\n\t"
+# if defined(RT_ARCH_ARM64)
+ "ldxrh %w[iDst], %[pMem]\n\t"
+# else
+ "ldrexh %[iDst], %[pMem]\n\t"
+# endif
+ : [iDst] "=&r" (i32)
+ : [pMem] "Q" (*pi16));
+ return (int16_t)i32;
+#else
+ return *pi16;
+#endif
+}
+
+
+/**
+ * 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 RT_FAR *pu32) RT_NOTHROW_DEF
+{
+ Assert(!((uintptr_t)pu32 & 3));
+#if defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32)
+ uint32_t u32;
+ __asm__ __volatile__(".Lstart_ASMAtomicReadU32_%=:\n\t"
+ RTASM_ARM_DMB_SY
+# if defined(RT_ARCH_ARM64)
+ "ldxr %w[uDst], %[pMem]\n\t"
+# else
+ "ldrex %[uDst], %[pMem]\n\t"
+# endif
+ : [uDst] "=&r" (u32)
+ : [pMem] "Q" (*pu32)
+ RTASM_ARM_DMB_SY_COMMA_IN_REG);
+ return u32;
+#else
+ ASMMemoryFence();
+# if ARCH_BITS == 16
+ AssertFailed(); /** @todo 16-bit */
+# endif
+ return *pu32;
+#endif
+}
+
+
+/**
+ * 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 RT_FAR *pu32) RT_NOTHROW_DEF
+{
+ Assert(!((uintptr_t)pu32 & 3));
+#if defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32)
+ uint32_t u32;
+ __asm__ __volatile__(".Lstart_ASMAtomicUoReadU32_%=:\n\t"
+# if defined(RT_ARCH_ARM64)
+ "ldxr %w[uDst], %[pMem]\n\t"
+# else
+ "ldrex %[uDst], %[pMem]\n\t"
+# endif
+ : [uDst] "=&r" (u32)
+ : [pMem] "Q" (*pu32));
+ return u32;
+#else
+# if ARCH_BITS == 16
+ AssertFailed(); /** @todo 16-bit */
+# endif
+ return *pu32;
+#endif
+}
+
+
+/**
+ * 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 RT_FAR *pi32) RT_NOTHROW_DEF
+{
+ Assert(!((uintptr_t)pi32 & 3));
+#if defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32)
+ int32_t i32;
+ __asm__ __volatile__(".Lstart_ASMAtomicReadS32_%=:\n\t"
+ RTASM_ARM_DMB_SY
+# if defined(RT_ARCH_ARM64)
+ "ldxr %w[iDst], %[pMem]\n\t"
+# else
+ "ldrex %[iDst], %[pMem]\n\t"
+# endif
+ : [iDst] "=&r" (i32)
+ : [pMem] "Q" (*pi32)
+ RTASM_ARM_DMB_SY_COMMA_IN_REG);
+ return i32;
+#else
+ ASMMemoryFence();
+# if ARCH_BITS == 16
+ AssertFailed(); /** @todo 16-bit */
+# endif
+ return *pi32;
+#endif
+}
+
+
+/**
+ * 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 RT_FAR *pi32) RT_NOTHROW_DEF
+{
+ Assert(!((uintptr_t)pi32 & 3));
+#if defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32)
+ int32_t i32;
+ __asm__ __volatile__(".Lstart_ASMAtomicUoReadS32_%=:\n\t"
+# if defined(RT_ARCH_ARM64)
+ "ldxr %w[iDst], %[pMem]\n\t"
+# else
+ "ldrex %[iDst], %[pMem]\n\t"
+# endif
+ : [iDst] "=&r" (i32)
+ : [pMem] "Q" (*pi32));
+ return i32;
+
+#else
+# if ARCH_BITS == 16
+ AssertFailed(); /** @todo 16-bit */
+# endif
+ return *pi32;
+#endif
+}
+
+
+/**
+ * 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_TMP_ARM && !defined(RT_ARCH_AMD64)) \
+ || RT_INLINE_DONT_MIX_CMPXCHG8B_AND_PIC
+RT_ASM_DECL_PRAGMA_WATCOM(uint64_t) ASMAtomicReadU64(volatile uint64_t RT_FAR *pu64) RT_NOTHROW_PROTO;
+#else
+DECLINLINE(uint64_t) ASMAtomicReadU64(volatile uint64_t RT_FAR *pu64) RT_NOTHROW_DEF
+{
+ 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;
+
+# elif defined(RT_ARCH_X86)
+# 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)
+ : "cc");
+# else /* !PIC */
+ __asm__ __volatile__("lock; cmpxchg8b %1\n\t"
+ : "=A" (u64)
+ , "+m" (*pu64)
+ : "0" (0ULL)
+ , "b" (0)
+ , "c" (0)
+ : "cc");
+# 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
+
+# elif defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32)
+ Assert(!((uintptr_t)pu64 & 7));
+ __asm__ __volatile__(".Lstart_ASMAtomicReadU64_%=:\n\t"
+ RTASM_ARM_DMB_SY
+# if defined(RT_ARCH_ARM64)
+ "ldxr %[uDst], %[pMem]\n\t"
+# else
+ "ldrexd %[uDst], %H[uDst], %[pMem]\n\t"
+# endif
+ : [uDst] "=&r" (u64)
+ : [pMem] "Q" (*pu64)
+ RTASM_ARM_DMB_SY_COMMA_IN_REG);
+
+# else
+# error "Port me"
+# endif
+ 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_TMP_ARM && !RT_INLINE_ASM_USES_INTRIN) \
+ || RT_INLINE_DONT_MIX_CMPXCHG8B_AND_PIC)
+RT_ASM_DECL_PRAGMA_WATCOM(uint64_t) ASMAtomicUoReadU64(volatile uint64_t RT_FAR *pu64) RT_NOTHROW_PROTO;
+#else
+DECLINLINE(uint64_t) ASMAtomicUoReadU64(volatile uint64_t RT_FAR *pu64) RT_NOTHROW_DEF
+{
+ 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;
+
+# elif defined(RT_ARCH_X86)
+# 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)
+ : "cc");
+# else /* !PIC */
+ __asm__ __volatile__("lock; cmpxchg8b %1\n\t"
+ : "=A" (u64)
+ , "+m" (*pu64)
+ : "0" (0ULL)
+ , "b" (0)
+ , "c" (0)
+ : "cc");
+# 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
+
+# elif defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32)
+ Assert(!((uintptr_t)pu64 & 7));
+ __asm__ __volatile__(".Lstart_ASMAtomicUoReadU64_%=:\n\t"
+# if defined(RT_ARCH_ARM64)
+ "ldxr %[uDst], %[pMem]\n\t"
+# else
+ "ldrexd %[uDst], %H[uDst], %[pMem]\n\t"
+# endif
+ : [uDst] "=&r" (u64)
+ : [pMem] "Q" (*pu64));
+
+# else
+# error "Port me"
+# endif
+ 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 RT_FAR *pi64) RT_NOTHROW_DEF
+{
+ return (int64_t)ASMAtomicReadU64((volatile uint64_t RT_FAR *)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 RT_FAR *pi64) RT_NOTHROW_DEF
+{
+ return (int64_t)ASMAtomicUoReadU64((volatile uint64_t RT_FAR *)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 RT_FAR *pcb) RT_NOTHROW_DEF
+{
+#if ARCH_BITS == 64
+ return ASMAtomicReadU64((uint64_t volatile RT_FAR *)pcb);
+#elif ARCH_BITS == 32
+ return ASMAtomicReadU32((uint32_t volatile RT_FAR *)pcb);
+#elif ARCH_BITS == 16
+ AssertCompileSize(size_t, 2);
+ return ASMAtomicReadU16((uint16_t volatile RT_FAR *)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 RT_FAR *pcb) RT_NOTHROW_DEF
+{
+#if ARCH_BITS == 64 || ARCH_BITS == 16
+ return ASMAtomicUoReadU64((uint64_t volatile RT_FAR *)pcb);
+#elif ARCH_BITS == 32
+ return ASMAtomicUoReadU32((uint32_t volatile RT_FAR *)pcb);
+#elif ARCH_BITS == 16
+ AssertCompileSize(size_t, 2);
+ return ASMAtomicUoReadU16((uint16_t volatile RT_FAR *)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 RT_FAR *) ASMAtomicReadPtr(void RT_FAR * volatile RT_FAR *ppv) RT_NOTHROW_DEF
+{
+#if ARCH_BITS == 32 || ARCH_BITS == 16
+ return (void RT_FAR *)ASMAtomicReadU32((volatile uint32_t RT_FAR *)(void RT_FAR *)ppv);
+#elif ARCH_BITS == 64
+ return (void RT_FAR *)ASMAtomicReadU64((volatile uint64_t RT_FAR *)(void RT_FAR *)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__ /* 8.2.0 requires -Wno-ignored-qualifiers */
+# 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 RT_FAR * volatile RT_FAR *)(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 RT_FAR *) ASMAtomicUoReadPtr(void RT_FAR * volatile RT_FAR *ppv) RT_NOTHROW_DEF
+{
+#if ARCH_BITS == 32 || ARCH_BITS == 16
+ return (void RT_FAR *)ASMAtomicUoReadU32((volatile uint32_t RT_FAR *)(void RT_FAR *)ppv);
+#elif ARCH_BITS == 64
+ return (void RT_FAR *)ASMAtomicUoReadU64((volatile uint64_t RT_FAR *)(void RT_FAR *)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__ /* 8.2.0 requires -Wno-ignored-qualifiers */
+# 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 RT_FAR * volatile RT_FAR *)(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 RT_FAR *pf) RT_NOTHROW_DEF
+{
+ 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 RT_FAR *pf) RT_NOTHROW_DEF
+{
+ 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
+# define ASMAtomicReadHandle(ph, phRes) \
+ do { \
+ AssertCompile(sizeof(*(ph)) == sizeof(uint32_t)); \
+ AssertCompile(sizeof(*(phRes)) == sizeof(uint32_t)); \
+ *(uint32_t RT_FAR *)(phRes) = ASMAtomicReadU32((uint32_t volatile RT_FAR *)(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 RT_FAR *)(phRes) = ASMAtomicReadU64((uint64_t volatile RT_FAR *)(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
+# define ASMAtomicUoReadHandle(ph, phRes) \
+ do { \
+ AssertCompile(sizeof(*(ph)) == sizeof(uint32_t)); \
+ AssertCompile(sizeof(*(phRes)) == sizeof(uint32_t)); \
+ *(uint32_t RT_FAR *)(phRes) = ASMAtomicUoReadU32((uint32_t volatile RT_FAR *)(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 RT_FAR *)(phRes) = ASMAtomicUoReadU64((uint64_t volatile RT_FAR *)(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 RT_FAR *)(puRes) = ASMAtomicReadU8( (volatile uint8_t RT_FAR *)(void RT_FAR *)(pu)); break; \
+ case 2: *(uint16_t RT_FAR *)(puRes) = ASMAtomicReadU16((volatile uint16_t RT_FAR *)(void RT_FAR *)(pu)); break; \
+ case 4: *(uint32_t RT_FAR *)(puRes) = ASMAtomicReadU32((volatile uint32_t RT_FAR *)(void RT_FAR *)(pu)); break; \
+ case 8: *(uint64_t RT_FAR *)(puRes) = ASMAtomicReadU64((volatile uint64_t RT_FAR *)(void RT_FAR *)(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 RT_FAR *)(puRes) = ASMAtomicUoReadU8( (volatile uint8_t RT_FAR *)(void RT_FAR *)(pu)); break; \
+ case 2: *(uint16_t RT_FAR *)(puRes) = ASMAtomicUoReadU16((volatile uint16_t RT_FAR *)(void RT_FAR *)(pu)); break; \
+ case 4: *(uint32_t RT_FAR *)(puRes) = ASMAtomicUoReadU32((volatile uint32_t RT_FAR *)(void RT_FAR *)(pu)); break; \
+ case 8: *(uint64_t RT_FAR *)(puRes) = ASMAtomicUoReadU64((volatile uint64_t RT_FAR *)(void RT_FAR *)(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 RT_FAR *pu8, uint8_t u8) RT_NOTHROW_DEF
+{
+ /** @todo Any possible ARM32/ARM64 optimizations here? */
+ 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 RT_FAR *pu8, uint8_t u8) RT_NOTHROW_DEF
+{
+ /** @todo Any possible ARM32/ARM64 improvements here? */
+ *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 RT_FAR *pi8, int8_t i8) RT_NOTHROW_DEF
+{
+ /** @todo Any possible ARM32/ARM64 optimizations here? */
+ 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 RT_FAR *pi8, int8_t i8) RT_NOTHROW_DEF
+{
+ *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 RT_FAR *pu16, uint16_t u16) RT_NOTHROW_DEF
+{
+ /** @todo Any possible ARM32/ARM64 optimizations here? */
+ 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 RT_FAR *pu16, uint16_t u16) RT_NOTHROW_DEF
+{
+ 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 RT_FAR *pi16, int16_t i16) RT_NOTHROW_DEF
+{
+ /** @todo Any possible ARM32/ARM64 optimizations here? */
+ 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 RT_FAR *pi16, int16_t i16) RT_NOTHROW_DEF
+{
+ 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 RT_FAR *pu32, uint32_t u32) RT_NOTHROW_DEF
+{
+ /** @todo Any possible ARM32/ARM64 optimizations here? */
+ 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 RT_FAR *pu32, uint32_t u32) RT_NOTHROW_DEF
+{
+ 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 RT_FAR *pi32, int32_t i32) RT_NOTHROW_DEF
+{
+ 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 RT_FAR *pi32, int32_t i32) RT_NOTHROW_DEF
+{
+ 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 RT_FAR *pu64, uint64_t u64) RT_NOTHROW_DEF
+{
+ /** @todo Any possible ARM32/ARM64 optimizations here? */
+ 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 RT_FAR *pu64, uint64_t u64) RT_NOTHROW_DEF
+{
+ 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 RT_FAR *pi64, int64_t i64) RT_NOTHROW_DEF
+{
+ /** @todo Any possible ARM32/ARM64 optimizations here? */
+ 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 RT_FAR *pi64, int64_t i64) RT_NOTHROW_DEF
+{
+ Assert(!((uintptr_t)pi64 & 7));
+#if ARCH_BITS == 64
+ *pi64 = i64;
+#else
+ ASMAtomicXchgS64(pi64, i64);
+#endif
+}
+
+
+/**
+ * Atomically writes a size_t value, ordered.
+ *
+ * @returns nothing.
+ * @param pcb Pointer to the size_t variable to write.
+ * @param cb The value to assign to *pcb.
+ */
+DECLINLINE(void) ASMAtomicWriteZ(volatile size_t RT_FAR *pcb, size_t cb) RT_NOTHROW_DEF
+{
+#if ARCH_BITS == 64
+ ASMAtomicWriteU64((uint64_t volatile *)pcb, cb);
+#elif ARCH_BITS == 32
+ ASMAtomicWriteU32((uint32_t volatile *)pcb, cb);
+#elif ARCH_BITS == 16
+ AssertCompileSize(size_t, 2);
+ ASMAtomicWriteU16((uint16_t volatile *)pcb, cb);
+#else
+# error "Unsupported ARCH_BITS value"
+#endif
+}
+
+
+/**
+ * Atomically writes a size_t value, unordered.
+ *
+ * @returns nothing.
+ * @param pcb Pointer to the size_t variable to write.
+ * @param cb The value to assign to *pcb.
+ */
+DECLINLINE(void) ASMAtomicUoWriteZ(volatile size_t RT_FAR *pcb, size_t cb) RT_NOTHROW_DEF
+{
+#if ARCH_BITS == 64
+ ASMAtomicUoWriteU64((uint64_t volatile *)pcb, cb);
+#elif ARCH_BITS == 32
+ ASMAtomicUoWriteU32((uint32_t volatile *)pcb, cb);
+#elif ARCH_BITS == 16
+ AssertCompileSize(size_t, 2);
+ ASMAtomicUoWriteU16((uint16_t volatile *)pcb, cb);
+#else
+# error "Unsupported ARCH_BITS value"
+#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 RT_FAR *pf, bool f) RT_NOTHROW_DEF
+{
+ ASMAtomicWriteU8((uint8_t volatile RT_FAR *)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 RT_FAR *pf, bool f) RT_NOTHROW_DEF
+{
+ *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 RT_FAR * volatile RT_FAR *ppv, const void *pv) RT_NOTHROW_DEF
+{
+#if ARCH_BITS == 32 || ARCH_BITS == 16
+ ASMAtomicWriteU32((volatile uint32_t RT_FAR *)(void RT_FAR *)ppv, (uint32_t)pv);
+#elif ARCH_BITS == 64
+ ASMAtomicWriteU64((volatile uint64_t RT_FAR *)(void RT_FAR *)ppv, (uint64_t)pv);
+#else
+# error "ARCH_BITS is bogus"
+#endif
+}
+
+
+/**
+ * Atomically writes a pointer value, unordered.
+ *
+ * @param ppv Pointer to the pointer variable to write.
+ * @param pv The pointer value to assign to *ppv.
+ */
+DECLINLINE(void) ASMAtomicUoWritePtrVoid(void RT_FAR * volatile RT_FAR *ppv, const void *pv) RT_NOTHROW_DEF
+{
+#if ARCH_BITS == 32 || ARCH_BITS == 16
+ ASMAtomicUoWriteU32((volatile uint32_t RT_FAR *)(void RT_FAR *)ppv, (uint32_t)pv);
+#elif ARCH_BITS == 64
+ ASMAtomicUoWriteU64((volatile uint64_t RT_FAR *)(void RT_FAR *)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 RT_FAR * const ppvTypeChecked = (ppv); \
+ __typeof__(*(ppv)) const pvTypeChecked = (pv); \
+ \
+ AssertCompile(sizeof(*ppv) == sizeof(void RT_FAR *)); \
+ AssertCompile(sizeof(pv) == sizeof(void RT_FAR *)); \
+ Assert(!( (uintptr_t)ppv & ((ARCH_BITS / 8) - 1) )); \
+ \
+ ASMAtomicWritePtrVoid((void RT_FAR * volatile RT_FAR *)(ppvTypeChecked), (void RT_FAR *)(pvTypeChecked)); \
+ } while (0)
+#else
+# define ASMAtomicWritePtr(ppv, pv) \
+ do \
+ { \
+ AssertCompile(sizeof(*ppv) == sizeof(void RT_FAR *)); \
+ AssertCompile(sizeof(pv) == sizeof(void RT_FAR *)); \
+ Assert(!( (uintptr_t)ppv & ((ARCH_BITS / 8) - 1) )); \
+ \
+ ASMAtomicWritePtrVoid((void RT_FAR * volatile RT_FAR *)(ppv), (void RT_FAR *)(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.
+ */
+#if RT_GNUC_PREREQ(4, 2)
+# define ASMAtomicWriteNullPtr(ppv) \
+ do \
+ { \
+ __typeof__(*(ppv)) * const ppvTypeChecked = (ppv); \
+ AssertCompile(sizeof(*ppv) == sizeof(void RT_FAR *)); \
+ Assert(!( (uintptr_t)ppv & ((ARCH_BITS / 8) - 1) )); \
+ ASMAtomicWritePtrVoid((void RT_FAR * volatile RT_FAR *)(ppvTypeChecked), NULL); \
+ } while (0)
+#else
+# define ASMAtomicWriteNullPtr(ppv) \
+ do \
+ { \
+ AssertCompile(sizeof(*ppv) == sizeof(void RT_FAR *)); \
+ Assert(!( (uintptr_t)ppv & ((ARCH_BITS / 8) - 1) )); \
+ ASMAtomicWritePtrVoid((void RT_FAR * volatile RT_FAR *)(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.
+ */
+#if RT_GNUC_PREREQ(4, 2)
+# 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 RT_FAR *)); \
+ AssertCompile(sizeof(pv) == sizeof(void RT_FAR *)); \
+ 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 RT_FAR *)); \
+ 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
+# define ASMAtomicWriteHandle(ph, hNew) \
+ do { \
+ AssertCompile(sizeof(*(ph)) == sizeof(uint32_t)); \
+ ASMAtomicWriteU32((uint32_t volatile RT_FAR *)(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 RT_FAR *)(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
+# define ASMAtomicUoWriteHandle(ph, hNew) \
+ do { \
+ AssertCompile(sizeof(*(ph)) == sizeof(uint32_t)); \
+ ASMAtomicUoWriteU32((uint32_t volatile RT_FAR *)(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 RT_FAR *)(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 RT_FAR *)(void RT_FAR *)(pu), (uint8_t )(uNew)); break; \
+ case 2: ASMAtomicWriteU16((volatile uint16_t RT_FAR *)(void RT_FAR *)(pu), (uint16_t)(uNew)); break; \
+ case 4: ASMAtomicWriteU32((volatile uint32_t RT_FAR *)(void RT_FAR *)(pu), (uint32_t)(uNew)); break; \
+ case 8: ASMAtomicWriteU64((volatile uint64_t RT_FAR *)(void RT_FAR *)(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 RT_FAR *)(void RT_FAR *)(pu), (uint8_t )(uNew)); break; \
+ case 2: ASMAtomicUoWriteU16((volatile uint16_t RT_FAR *)(void RT_FAR *)(pu), (uint16_t)(uNew)); break; \
+ case 4: ASMAtomicUoWriteU32((volatile uint32_t RT_FAR *)(void RT_FAR *)(pu), (uint32_t)(uNew)); break; \
+ case 8: ASMAtomicUoWriteU64((volatile uint64_t RT_FAR *)(void RT_FAR *)(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.
+ */
+RT_ASM_DECL_PRAGMA_WATCOM(uint16_t) ASMAtomicAddU16(uint16_t volatile RT_FAR *pu16, uint32_t u16) RT_NOTHROW_PROTO;
+
+
+/**
+ * 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_TMP_ARM && !RT_INLINE_ASM_USES_INTRIN
+RT_ASM_DECL_PRAGMA_WATCOM(uint32_t) ASMAtomicAddU32(uint32_t volatile RT_FAR *pu32, uint32_t u32) RT_NOTHROW_PROTO;
+#else
+DECLINLINE(uint32_t) ASMAtomicAddU32(uint32_t volatile RT_FAR *pu32, uint32_t u32) RT_NOTHROW_DEF
+{
+# if RT_INLINE_ASM_USES_INTRIN
+ u32 = _InterlockedExchangeAdd((long RT_FAR *)pu32, u32);
+ return u32;
+
+# elif defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
+# if RT_INLINE_ASM_GNU_STYLE
+ __asm__ __volatile__("lock; xaddl %0, %1\n\t"
+ : "=r" (u32)
+ , "=m" (*pu32)
+ : "0" (u32)
+ , "m" (*pu32)
+ : "memory"
+ , "cc");
+ 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
+
+# elif defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32)
+ RTASM_ARM_LOAD_MODIFY_STORE_RET_OLD_32(ASMAtomicAddU32, pu32, DMB_SY,
+ "add %w[uNew], %w[uOld], %w[uVal]\n\t",
+ "add %[uNew], %[uOld], %[uVal]\n\t",
+ [uVal] "r" (u32));
+ return u32OldRet;
+
+# else
+# error "Port me"
+# 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 RT_FAR *pi32, int32_t i32) RT_NOTHROW_DEF
+{
+ return (int32_t)ASMAtomicAddU32((uint32_t volatile RT_FAR *)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_TMP_ARM && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(uint64_t) ASMAtomicAddU64(uint64_t volatile RT_FAR *pu64, uint64_t u64) RT_NOTHROW_PROTO;
+#else
+DECLINLINE(uint64_t) ASMAtomicAddU64(uint64_t volatile RT_FAR *pu64, uint64_t u64) RT_NOTHROW_DEF
+{
+# if RT_INLINE_ASM_USES_INTRIN && defined(RT_ARCH_AMD64)
+ u64 = _InterlockedExchangeAdd64((__int64 RT_FAR *)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"
+ , "cc");
+ return u64;
+
+# elif defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32)
+ RTASM_ARM_LOAD_MODIFY_STORE_RET_OLD_64(ASMAtomicAddU64, pu64, DMB_SY,
+ "add %[uNew], %[uOld], %[uVal]\n\t"
+ ,
+ "add %[uNew], %[uOld], %[uVal]\n\t"
+ "adc %H[uNew], %H[uOld], %H[uVal]\n\t",
+ [uVal] "r" (u64));
+ return u64OldRet;
+
+# 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 RT_FAR *pi64, int64_t i64) RT_NOTHROW_DEF
+{
+ return (int64_t)ASMAtomicAddU64((uint64_t volatile RT_FAR *)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 RT_FAR *pcb, size_t cb) RT_NOTHROW_DEF
+{
+#if ARCH_BITS == 64
+ AssertCompileSize(size_t, 8);
+ return ASMAtomicAddU64((uint64_t volatile RT_FAR *)pcb, cb);
+#elif ARCH_BITS == 32
+ AssertCompileSize(size_t, 4);
+ return ASMAtomicAddU32((uint32_t volatile RT_FAR *)pcb, cb);
+#elif ARCH_BITS == 16
+ AssertCompileSize(size_t, 2);
+ return ASMAtomicAddU16((uint16_t volatile RT_FAR *)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 RT_FAR *)(void RT_FAR *)(pu), (uint32_t)(uNew)); break; \
+ case 8: *(uint64_t *)(puOld) = ASMAtomicAddU64((volatile uint64_t RT_FAR *)(void RT_FAR *)(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 RT_FAR *pu16, uint32_t u16) RT_NOTHROW_DEF
+{
+ 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 RT_FAR *pi16, int16_t i16) RT_NOTHROW_DEF
+{
+ return (int16_t)ASMAtomicAddU16((uint16_t volatile RT_FAR *)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 RT_FAR *pu32, uint32_t u32) RT_NOTHROW_DEF
+{
+ 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 RT_FAR *pi32, int32_t i32) RT_NOTHROW_DEF
+{
+ return (int32_t)ASMAtomicAddU32((uint32_t volatile RT_FAR *)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 RT_FAR *pu64, uint64_t u64) RT_NOTHROW_DEF
+{
+ 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 RT_FAR *pi64, int64_t i64) RT_NOTHROW_DEF
+{
+ return (int64_t)ASMAtomicAddU64((uint64_t volatile RT_FAR *)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 RT_FAR *pcb, size_t cb) RT_NOTHROW_DEF
+{
+#if ARCH_BITS == 64
+ return ASMAtomicSubU64((uint64_t volatile RT_FAR *)pcb, cb);
+#elif ARCH_BITS == 32
+ return ASMAtomicSubU32((uint32_t volatile RT_FAR *)pcb, cb);
+#elif ARCH_BITS == 16
+ AssertCompileSize(size_t, 2);
+ return ASMAtomicSubU16((uint16_t volatile RT_FAR *)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 RT_FAR *)(puOld) = ASMAtomicSubU32((volatile uint32_t RT_FAR *)(void RT_FAR *)(pu), (uint32_t)(uNew)); break; \
+ case 8: *(uint64_t RT_FAR *)(puOld) = ASMAtomicSubU64((volatile uint64_t RT_FAR *)(void RT_FAR *)(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.
+ */
+RT_ASM_DECL_PRAGMA_WATCOM(uint16_t) ASMAtomicIncU16(uint16_t volatile RT_FAR *pu16) RT_NOTHROW_PROTO;
+
+
+/**
+ * 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_TMP_ARM && !RT_INLINE_ASM_USES_INTRIN
+RT_ASM_DECL_PRAGMA_WATCOM(uint32_t) ASMAtomicIncU32(uint32_t volatile RT_FAR *pu32) RT_NOTHROW_PROTO;
+#else
+DECLINLINE(uint32_t) ASMAtomicIncU32(uint32_t volatile RT_FAR *pu32) RT_NOTHROW_DEF
+{
+# if RT_INLINE_ASM_USES_INTRIN
+ return (uint32_t)_InterlockedIncrement((long RT_FAR *)pu32);
+
+# elif defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
+# if RT_INLINE_ASM_GNU_STYLE
+ uint32_t u32;
+ __asm__ __volatile__("lock; xaddl %0, %1\n\t"
+ : "=r" (u32)
+ , "=m" (*pu32)
+ : "0" (1)
+ , "m" (*pu32)
+ : "memory"
+ , "cc");
+ 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
+
+# elif defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32)
+ RTASM_ARM_LOAD_MODIFY_STORE_RET_NEW_32(ASMAtomicIncU32, pu32, DMB_SY,
+ "add %w[uNew], %w[uNew], #1\n\t",
+ "add %[uNew], %[uNew], #1\n\t" /* arm6 / thumb2+ */,
+ "X" (0) /* dummy */);
+ return u32NewRet;
+
+# else
+ return ASMAtomicAddU32(pu32, 1) + 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 RT_FAR *pi32) RT_NOTHROW_DEF
+{
+ return (int32_t)ASMAtomicIncU32((uint32_t volatile RT_FAR *)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_TMP_ARM && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(uint64_t) ASMAtomicIncU64(uint64_t volatile RT_FAR *pu64) RT_NOTHROW_PROTO;
+#else
+DECLINLINE(uint64_t) ASMAtomicIncU64(uint64_t volatile RT_FAR *pu64) RT_NOTHROW_DEF
+{
+# if RT_INLINE_ASM_USES_INTRIN && defined(RT_ARCH_AMD64)
+ return (uint64_t)_InterlockedIncrement64((__int64 RT_FAR *)pu64);
+
+# 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"
+ , "cc");
+ return u64 + 1;
+
+# elif defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32)
+ RTASM_ARM_LOAD_MODIFY_STORE_RET_NEW_64(ASMAtomicIncU64, pu64, DMB_SY,
+ "add %[uNew], %[uNew], #1\n\t"
+ ,
+ "add %[uNew], %[uNew], #1\n\t" /* arm6 / thumb2+ */
+ "adc %H[uNew], %H[uNew], %[uZeroVal]\n\t",
+ RTASM_ARM_PICK_6432("X" (0) /* dummy */, [uZeroVal] "r" (0)) );
+ return u64NewRet;
+
+# 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 RT_FAR *pi64) RT_NOTHROW_DEF
+{
+ return (int64_t)ASMAtomicIncU64((uint64_t volatile RT_FAR *)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(size_t) ASMAtomicIncZ(size_t volatile RT_FAR *pcb) RT_NOTHROW_DEF
+{
+#if ARCH_BITS == 64
+ return ASMAtomicIncU64((uint64_t volatile RT_FAR *)pcb);
+#elif ARCH_BITS == 32
+ return ASMAtomicIncU32((uint32_t volatile RT_FAR *)pcb);
+#elif ARCH_BITS == 16
+ return ASMAtomicIncU16((uint16_t volatile RT_FAR *)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.
+ */
+RT_ASM_DECL_PRAGMA_WATCOM(uint32_t) ASMAtomicDecU16(uint16_t volatile RT_FAR *pu16) RT_NOTHROW_PROTO;
+
+
+/**
+ * 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_TMP_ARM && !RT_INLINE_ASM_USES_INTRIN
+RT_ASM_DECL_PRAGMA_WATCOM(uint32_t) ASMAtomicDecU32(uint32_t volatile RT_FAR *pu32) RT_NOTHROW_PROTO;
+#else
+DECLINLINE(uint32_t) ASMAtomicDecU32(uint32_t volatile RT_FAR *pu32) RT_NOTHROW_DEF
+{
+# if RT_INLINE_ASM_USES_INTRIN
+ return (uint32_t)_InterlockedDecrement((long RT_FAR *)pu32);
+
+# elif RT_INLINE_ASM_GNU_STYLE && defined(RT_ARCH_AMD64)
+# if RT_INLINE_ASM_GNU_STYLE
+ uint32_t u32;
+ __asm__ __volatile__("lock; xaddl %0, %1\n\t"
+ : "=r" (u32)
+ , "=m" (*pu32)
+ : "0" (-1)
+ , "m" (*pu32)
+ : "memory"
+ , "cc");
+ return u32-1;
+# else
+ uint32_t u32;
+ __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
+
+# elif defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32)
+ RTASM_ARM_LOAD_MODIFY_STORE_RET_NEW_32(ASMAtomicDecU32, pu32, DMB_SY,
+ "sub %w[uNew], %w[uNew], #1\n\t",
+ "sub %[uNew], %[uNew], #1\n\t" /* arm6 / thumb2+ */,
+ "X" (0) /* dummy */);
+ return u32NewRet;
+
+# else
+ return ASMAtomicSubU32(pu32, 1) - (uint32_t)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 RT_FAR *pi32) RT_NOTHROW_DEF
+{
+ return (int32_t)ASMAtomicDecU32((uint32_t volatile RT_FAR *)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_TMP_ARM && !RT_INLINE_ASM_USES_INTRIN
+RT_ASM_DECL_PRAGMA_WATCOM(uint64_t) ASMAtomicDecU64(uint64_t volatile RT_FAR *pu64) RT_NOTHROW_PROTO;
+#else
+DECLINLINE(uint64_t) ASMAtomicDecU64(uint64_t volatile RT_FAR *pu64) RT_NOTHROW_DEF
+{
+# if RT_INLINE_ASM_USES_INTRIN && defined(RT_ARCH_AMD64)
+ return (uint64_t)_InterlockedDecrement64((__int64 volatile RT_FAR *)pu64);
+
+# 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"
+ , "cc");
+ return u64-1;
+
+# elif defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32)
+ RTASM_ARM_LOAD_MODIFY_STORE_RET_NEW_64(ASMAtomicDecU64, pu64, DMB_SY,
+ "sub %[uNew], %[uNew], #1\n\t"
+ ,
+ "sub %[uNew], %[uNew], #1\n\t" /* arm6 / thumb2+ */
+ "sbc %H[uNew], %H[uNew], %[uZeroVal]\n\t",
+ RTASM_ARM_PICK_6432("X" (0) /* dummy */, [uZeroVal] "r" (0)) );
+ return u64NewRet;
+
+# 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 RT_FAR *pi64) RT_NOTHROW_DEF
+{
+ return (int64_t)ASMAtomicDecU64((uint64_t volatile RT_FAR *)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(size_t) ASMAtomicDecZ(size_t volatile RT_FAR *pcb) RT_NOTHROW_DEF
+{
+#if ARCH_BITS == 64
+ return ASMAtomicDecU64((uint64_t volatile RT_FAR *)pcb);
+#elif ARCH_BITS == 32
+ return ASMAtomicDecU32((uint32_t volatile RT_FAR *)pcb);
+#elif ARCH_BITS == 16
+ return ASMAtomicDecU16((uint16_t volatile RT_FAR *)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_TMP_ARM && !RT_INLINE_ASM_USES_INTRIN
+RT_ASM_DECL_PRAGMA_WATCOM(void) ASMAtomicOrU32(uint32_t volatile RT_FAR *pu32, uint32_t u32) RT_NOTHROW_PROTO;
+#else
+DECLINLINE(void) ASMAtomicOrU32(uint32_t volatile RT_FAR *pu32, uint32_t u32) RT_NOTHROW_DEF
+{
+# if RT_INLINE_ASM_USES_INTRIN
+ _InterlockedOr((long volatile RT_FAR *)pu32, (long)u32);
+
+# elif defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
+# if RT_INLINE_ASM_GNU_STYLE
+ __asm__ __volatile__("lock; orl %1, %0\n\t"
+ : "=m" (*pu32)
+ : "ir" (u32)
+ , "m" (*pu32)
+ : "cc");
+# 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
+
+# elif defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32)
+ /* For more on Orr see https://en.wikipedia.org/wiki/Orr_(Catch-22) ;-) */
+ RTASM_ARM_LOAD_MODIFY_STORE_RET_NEW_32(ASMAtomicOr32, pu32, DMB_SY,
+ "orr %w[uNew], %w[uNew], %w[uVal]\n\t",
+ "orr %[uNew], %[uNew], %[uVal]\n\t",
+ [uVal] "r" (u32));
+
+# else
+# error "Port me"
+# endif
+}
+#endif
+
+
+/**
+ * Atomically OR an unsigned 32-bit value, ordered, extended version (for bitmap
+ * fallback).
+ *
+ * @returns Old value.
+ * @param pu32 Pointer to the variable to OR @a u32 with.
+ * @param u32 The value to OR @a *pu32 with.
+ */
+DECLINLINE(uint32_t) ASMAtomicOrExU32(uint32_t volatile RT_FAR *pu32, uint32_t u32) RT_NOTHROW_DEF
+{
+#if defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32)
+ RTASM_ARM_LOAD_MODIFY_STORE_RET_OLD_32(ASMAtomicOrEx32, pu32, DMB_SY,
+ "orr %w[uNew], %w[uOld], %w[uVal]\n\t",
+ "orr %[uNew], %[uOld], %[uVal]\n\t",
+ [uVal] "r" (u32));
+ return u32OldRet;
+
+#else
+ uint32_t u32RetOld = ASMAtomicUoReadU32(pu32);
+ uint32_t u32New;
+ do
+ u32New = u32RetOld | u32;
+ while (!ASMAtomicCmpXchgExU32(pu32, u32New, u32RetOld, &u32RetOld));
+ return u32RetOld;
+#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 RT_FAR *pi32, int32_t i32) RT_NOTHROW_DEF
+{
+ ASMAtomicOrU32((uint32_t volatile RT_FAR *)pi32, (uint32_t)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_TMP_ARM && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(void) ASMAtomicOrU64(uint64_t volatile RT_FAR *pu64, uint64_t u64) RT_NOTHROW_PROTO;
+#else
+DECLINLINE(void) ASMAtomicOrU64(uint64_t volatile RT_FAR *pu64, uint64_t u64) RT_NOTHROW_DEF
+{
+# if RT_INLINE_ASM_USES_INTRIN && defined(RT_ARCH_AMD64)
+ _InterlockedOr64((__int64 volatile RT_FAR *)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)
+ : "cc");
+
+# elif defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32)
+ RTASM_ARM_LOAD_MODIFY_STORE_RET_NEW_64(ASMAtomicOrU64, pu64, DMB_SY,
+ "orr %[uNew], %[uNew], %[uVal]\n\t"
+ ,
+ "orr %[uNew], %[uNew], %[uVal]\n\t"
+ "orr %H[uNew], %H[uNew], %H[uVal]\n\t",
+ [uVal] "r" (u64));
+
+# 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 RT_FAR *pi64, int64_t i64) RT_NOTHROW_DEF
+{
+ ASMAtomicOrU64((uint64_t volatile RT_FAR *)pi64, (uint64_t)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_TMP_ARM && !RT_INLINE_ASM_USES_INTRIN
+RT_ASM_DECL_PRAGMA_WATCOM(void) ASMAtomicAndU32(uint32_t volatile RT_FAR *pu32, uint32_t u32) RT_NOTHROW_PROTO;
+#else
+DECLINLINE(void) ASMAtomicAndU32(uint32_t volatile RT_FAR *pu32, uint32_t u32) RT_NOTHROW_DEF
+{
+# if RT_INLINE_ASM_USES_INTRIN
+ _InterlockedAnd((long volatile RT_FAR *)pu32, u32);
+
+# elif defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
+# if RT_INLINE_ASM_GNU_STYLE
+ __asm__ __volatile__("lock; andl %1, %0\n\t"
+ : "=m" (*pu32)
+ : "ir" (u32)
+ , "m" (*pu32)
+ : "cc");
+# 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
+
+# elif defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32)
+ RTASM_ARM_LOAD_MODIFY_STORE_RET_NEW_32(ASMAtomicAnd32, pu32, DMB_SY,
+ "and %w[uNew], %w[uNew], %w[uVal]\n\t",
+ "and %[uNew], %[uNew], %[uVal]\n\t",
+ [uVal] "r" (u32));
+
+# else
+# error "Port me"
+# endif
+}
+#endif
+
+
+/**
+ * Atomically AND an unsigned 32-bit value, ordered, extended version.
+ *
+ * @returns Old value.
+ * @param pu32 Pointer to the variable to AND @a u32 with.
+ * @param u32 The value to AND @a *pu32 with.
+ */
+DECLINLINE(uint32_t) ASMAtomicAndExU32(uint32_t volatile RT_FAR *pu32, uint32_t u32) RT_NOTHROW_DEF
+{
+#if defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32)
+ RTASM_ARM_LOAD_MODIFY_STORE_RET_OLD_32(ASMAtomicAndEx32, pu32, DMB_SY,
+ "and %w[uNew], %w[uOld], %w[uVal]\n\t",
+ "and %[uNew], %[uOld], %[uVal]\n\t",
+ [uVal] "r" (u32));
+ return u32OldRet;
+
+#else
+ uint32_t u32RetOld = ASMAtomicUoReadU32(pu32);
+ uint32_t u32New;
+ do
+ u32New = u32RetOld & u32;
+ while (!ASMAtomicCmpXchgExU32(pu32, u32New, u32RetOld, &u32RetOld));
+ return u32RetOld;
+#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 RT_FAR *pi32, int32_t i32) RT_NOTHROW_DEF
+{
+ ASMAtomicAndU32((uint32_t volatile RT_FAR *)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_TMP_ARM && !RT_INLINE_ASM_USES_INTRIN
+DECLASM(void) ASMAtomicAndU64(uint64_t volatile RT_FAR *pu64, uint64_t u64) RT_NOTHROW_PROTO;
+#else
+DECLINLINE(void) ASMAtomicAndU64(uint64_t volatile RT_FAR *pu64, uint64_t u64) RT_NOTHROW_DEF
+{
+# if RT_INLINE_ASM_USES_INTRIN && defined(RT_ARCH_AMD64)
+ _InterlockedAnd64((__int64 volatile RT_FAR *)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)
+ : "cc");
+
+# elif defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32)
+ RTASM_ARM_LOAD_MODIFY_STORE_RET_NEW_64(ASMAtomicAndU64, pu64, DMB_SY,
+ "and %[uNew], %[uNew], %[uVal]\n\t"
+ ,
+ "and %[uNew], %[uNew], %[uVal]\n\t"
+ "and %H[uNew], %H[uNew], %H[uVal]\n\t",
+ [uVal] "r" (u64));
+
+# 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 RT_FAR *pi64, int64_t i64) RT_NOTHROW_DEF
+{
+ ASMAtomicAndU64((uint64_t volatile RT_FAR *)pi64, (uint64_t)i64);
+}
+
+
+/**
+ * Atomically XOR an unsigned 32-bit value and a memory location, ordered.
+ *
+ * @param pu32 Pointer to the variable to XOR @a u32 with.
+ * @param u32 The value to XOR @a *pu32 with.
+ *
+ * @remarks x86: Requires a 386 or later.
+ */
+#if RT_INLINE_ASM_EXTERNAL_TMP_ARM && !RT_INLINE_ASM_USES_INTRIN
+RT_ASM_DECL_PRAGMA_WATCOM(void) ASMAtomicXorU32(uint32_t volatile RT_FAR *pu32, uint32_t u32) RT_NOTHROW_PROTO;
+#else
+DECLINLINE(void) ASMAtomicXorU32(uint32_t volatile RT_FAR *pu32, uint32_t u32) RT_NOTHROW_DEF
+{
+# if RT_INLINE_ASM_USES_INTRIN
+ _InterlockedXor((long volatile RT_FAR *)pu32, u32);
+
+# elif defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
+# if RT_INLINE_ASM_GNU_STYLE
+ __asm__ __volatile__("lock; xorl %1, %0\n\t"
+ : "=m" (*pu32)
+ : "ir" (u32)
+ , "m" (*pu32)
+ : "cc");
+# else
+ __asm
+ {
+ mov eax, [u32]
+# ifdef RT_ARCH_AMD64
+ mov rdx, [pu32]
+ lock xor [rdx], eax
+# else
+ mov edx, [pu32]
+ lock xor [edx], eax
+# endif
+ }
+# endif
+
+# elif defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32)
+ RTASM_ARM_LOAD_MODIFY_STORE_RET_NEW_32(ASMAtomicXor32, pu32, DMB_SY,
+ "eor %w[uNew], %w[uNew], %w[uVal]\n\t",
+ "eor %[uNew], %[uNew], %[uVal]\n\t",
+ [uVal] "r" (u32));
+
+# else
+# error "Port me"
+# endif
+}
+#endif
+
+
+/**
+ * Atomically XOR an unsigned 32-bit value and a memory location, ordered,
+ * extended version (for bitmaps).
+ *
+ * @returns Old value.
+ * @param pu32 Pointer to the variable to XOR @a u32 with.
+ * @param u32 The value to XOR @a *pu32 with.
+ */
+DECLINLINE(uint32_t) ASMAtomicXorExU32(uint32_t volatile RT_FAR *pu32, uint32_t u32) RT_NOTHROW_DEF
+{
+#if defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32)
+ RTASM_ARM_LOAD_MODIFY_STORE_RET_OLD_32(ASMAtomicXorEx32, pu32, DMB_SY,
+ "eor %w[uNew], %w[uOld], %w[uVal]\n\t",
+ "eor %[uNew], %[uOld], %[uVal]\n\t",
+ [uVal] "r" (u32));
+ return u32OldRet;
+
+#else
+ uint32_t u32RetOld = ASMAtomicUoReadU32(pu32);
+ uint32_t u32New;
+ do
+ u32New = u32RetOld ^ u32;
+ while (!ASMAtomicCmpXchgExU32(pu32, u32New, u32RetOld, &u32RetOld));
+ return u32RetOld;
+#endif
+}
+
+
+/**
+ * Atomically XOR a signed 32-bit value, ordered.
+ *
+ * @param pi32 Pointer to the variable to XOR i32 with.
+ * @param i32 The value to XOR *pi32 with.
+ *
+ * @remarks x86: Requires a 386 or later.
+ */
+DECLINLINE(void) ASMAtomicXorS32(int32_t volatile RT_FAR *pi32, int32_t i32) RT_NOTHROW_DEF
+{
+ ASMAtomicXorU32((uint32_t volatile RT_FAR *)pi32, (uint32_t)i32);
+}
+
+
+/**
+ * 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_TMP_ARM
+RT_ASM_DECL_PRAGMA_WATCOM(void) ASMAtomicUoOrU32(uint32_t volatile RT_FAR *pu32, uint32_t u32) RT_NOTHROW_PROTO;
+#else
+DECLINLINE(void) ASMAtomicUoOrU32(uint32_t volatile RT_FAR *pu32, uint32_t u32) RT_NOTHROW_DEF
+{
+# if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
+# if RT_INLINE_ASM_GNU_STYLE
+ __asm__ __volatile__("orl %1, %0\n\t"
+ : "=m" (*pu32)
+ : "ir" (u32)
+ , "m" (*pu32)
+ : "cc");
+# else
+ __asm
+ {
+ mov eax, [u32]
+# ifdef RT_ARCH_AMD64
+ mov rdx, [pu32]
+ or [rdx], eax
+# else
+ mov edx, [pu32]
+ or [edx], eax
+# endif
+ }
+# endif
+
+# elif defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32)
+ RTASM_ARM_LOAD_MODIFY_STORE_RET_NEW_32(ASMAtomicUoOrU32, pu32, NO_BARRIER,
+ "orr %w[uNew], %w[uNew], %w[uVal]\n\t",
+ "orr %[uNew], %[uNew], %[uVal]\n\t",
+ [uVal] "r" (u32));
+
+# else
+# error "Port me"
+# endif
+}
+#endif
+
+
+/**
+ * Atomically OR an unsigned 32-bit value, unordered but interrupt safe,
+ * extended version (for bitmap fallback).
+ *
+ * @returns Old value.
+ * @param pu32 Pointer to the variable to OR @a u32 with.
+ * @param u32 The value to OR @a *pu32 with.
+ */
+DECLINLINE(uint32_t) ASMAtomicUoOrExU32(uint32_t volatile RT_FAR *pu32, uint32_t u32) RT_NOTHROW_DEF
+{
+#if defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32)
+ RTASM_ARM_LOAD_MODIFY_STORE_RET_OLD_32(ASMAtomicUoOrExU32, pu32, NO_BARRIER,
+ "orr %w[uNew], %w[uOld], %w[uVal]\n\t",
+ "orr %[uNew], %[uOld], %[uVal]\n\t",
+ [uVal] "r" (u32));
+ return u32OldRet;
+
+#else
+ return ASMAtomicOrExU32(pu32, u32); /* (we have no unordered cmpxchg primitive atm.) */
+#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 RT_FAR *pi32, int32_t i32) RT_NOTHROW_DEF
+{
+ ASMAtomicUoOrU32((uint32_t volatile RT_FAR *)pi32, (uint32_t)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_TMP_ARM
+DECLASM(void) ASMAtomicUoOrU64(uint64_t volatile RT_FAR *pu64, uint64_t u64) RT_NOTHROW_PROTO;
+#else
+DECLINLINE(void) ASMAtomicUoOrU64(uint64_t volatile RT_FAR *pu64, uint64_t u64) RT_NOTHROW_DEF
+{
+# if RT_INLINE_ASM_GNU_STYLE && defined(RT_ARCH_AMD64)
+ __asm__ __volatile__("orq %1, %q0\n\t"
+ : "=m" (*pu64)
+ : "r" (u64)
+ , "m" (*pu64)
+ : "cc");
+
+# elif defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32)
+ RTASM_ARM_LOAD_MODIFY_STORE_RET_NEW_64(ASMAtomicUoOrU64, pu64, NO_BARRIER,
+ "orr %[uNew], %[uNew], %[uVal]\n\t"
+ ,
+ "orr %[uNew], %[uNew], %[uVal]\n\t"
+ "orr %H[uNew], %H[uNew], %H[uVal]\n\t",
+ [uVal] "r" (u64));
+
+# 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 RT_FAR *pi64, int64_t i64) RT_NOTHROW_DEF
+{
+ ASMAtomicUoOrU64((uint64_t volatile RT_FAR *)pi64, (uint64_t)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_TMP_ARM
+RT_ASM_DECL_PRAGMA_WATCOM(void) ASMAtomicUoAndU32(uint32_t volatile RT_FAR *pu32, uint32_t u32) RT_NOTHROW_PROTO;
+#else
+DECLINLINE(void) ASMAtomicUoAndU32(uint32_t volatile RT_FAR *pu32, uint32_t u32) RT_NOTHROW_DEF
+{
+# if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
+# if RT_INLINE_ASM_GNU_STYLE
+ __asm__ __volatile__("andl %1, %0\n\t"
+ : "=m" (*pu32)
+ : "ir" (u32)
+ , "m" (*pu32)
+ : "cc");
+# else
+ __asm
+ {
+ mov eax, [u32]
+# ifdef RT_ARCH_AMD64
+ mov rdx, [pu32]
+ and [rdx], eax
+# else
+ mov edx, [pu32]
+ and [edx], eax
+# endif
+ }
+# endif
+
+# elif defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32)
+ RTASM_ARM_LOAD_MODIFY_STORE_RET_NEW_32(ASMAtomicUoAnd32, pu32, NO_BARRIER,
+ "and %w[uNew], %w[uNew], %w[uVal]\n\t",
+ "and %[uNew], %[uNew], %[uVal]\n\t",
+ [uVal] "r" (u32));
+
+# else
+# error "Port me"
+# endif
+}
+#endif
+
+
+/**
+ * Atomically AND an unsigned 32-bit value, unordered, extended version (for
+ * bitmap fallback).
+ *
+ * @returns Old value.
+ * @param pu32 Pointer to the pointer to AND @a u32 with.
+ * @param u32 The value to AND @a *pu32 with.
+ */
+DECLINLINE(uint32_t) ASMAtomicUoAndExU32(uint32_t volatile RT_FAR *pu32, uint32_t u32) RT_NOTHROW_DEF
+{
+#if defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32)
+ RTASM_ARM_LOAD_MODIFY_STORE_RET_OLD_32(ASMAtomicUoAndEx32, pu32, NO_BARRIER,
+ "and %w[uNew], %w[uOld], %w[uVal]\n\t",
+ "and %[uNew], %[uOld], %[uVal]\n\t",
+ [uVal] "r" (u32));
+ return u32OldRet;
+
+#else
+ return ASMAtomicAndExU32(pu32, u32); /* (we have no unordered cmpxchg primitive atm.) */
+#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 RT_FAR *pi32, int32_t i32) RT_NOTHROW_DEF
+{
+ ASMAtomicUoAndU32((uint32_t volatile RT_FAR *)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_TMP_ARM
+DECLASM(void) ASMAtomicUoAndU64(uint64_t volatile RT_FAR *pu64, uint64_t u64) RT_NOTHROW_PROTO;
+#else
+DECLINLINE(void) ASMAtomicUoAndU64(uint64_t volatile RT_FAR *pu64, uint64_t u64) RT_NOTHROW_DEF
+{
+# if RT_INLINE_ASM_GNU_STYLE && defined(RT_ARCH_AMD64)
+ __asm__ __volatile__("andq %1, %0\n\t"
+ : "=m" (*pu64)
+ : "r" (u64)
+ , "m" (*pu64)
+ : "cc");
+
+# elif defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32)
+ RTASM_ARM_LOAD_MODIFY_STORE_RET_NEW_64(ASMAtomicUoAndU64, pu64, NO_BARRIER,
+ "and %[uNew], %[uNew], %[uVal]\n\t"
+ ,
+ "and %[uNew], %[uNew], %[uVal]\n\t"
+ "and %H[uNew], %H[uNew], %H[uVal]\n\t",
+ [uVal] "r" (u64));
+
+# 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 RT_FAR *pi64, int64_t i64) RT_NOTHROW_DEF
+{
+ ASMAtomicUoAndU64((uint64_t volatile RT_FAR *)pi64, (uint64_t)i64);
+}
+
+
+/**
+ * Atomically XOR an unsigned 32-bit value, unordered but interrupt safe.
+ *
+ * @param pu32 Pointer to the variable to XOR @a u32 with.
+ * @param u32 The value to OR @a *pu32 with.
+ *
+ * @remarks x86: Requires a 386 or later.
+ */
+#if RT_INLINE_ASM_EXTERNAL_TMP_ARM
+RT_ASM_DECL_PRAGMA_WATCOM(void) ASMAtomicUoXorU32(uint32_t volatile RT_FAR *pu32, uint32_t u32) RT_NOTHROW_PROTO;
+#else
+DECLINLINE(void) ASMAtomicUoXorU32(uint32_t volatile RT_FAR *pu32, uint32_t u32) RT_NOTHROW_DEF
+{
+# if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
+# if RT_INLINE_ASM_GNU_STYLE
+ __asm__ __volatile__("xorl %1, %0\n\t"
+ : "=m" (*pu32)
+ : "ir" (u32)
+ , "m" (*pu32)
+ : "cc");
+# else
+ __asm
+ {
+ mov eax, [u32]
+# ifdef RT_ARCH_AMD64
+ mov rdx, [pu32]
+ xor [rdx], eax
+# else
+ mov edx, [pu32]
+ xor [edx], eax
+# endif
+ }
+# endif
+
+# elif defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32)
+ RTASM_ARM_LOAD_MODIFY_STORE_RET_NEW_32(ASMAtomicUoXorU32, pu32, NO_BARRIER,
+ "eor %w[uNew], %w[uNew], %w[uVal]\n\t",
+ "eor %[uNew], %[uNew], %[uVal]\n\t",
+ [uVal] "r" (u32));
+
+# else
+# error "Port me"
+# endif
+}
+#endif
+
+
+/**
+ * Atomically XOR an unsigned 32-bit value, unordered but interrupt safe,
+ * extended version (for bitmap fallback).
+ *
+ * @returns Old value.
+ * @param pu32 Pointer to the variable to XOR @a u32 with.
+ * @param u32 The value to OR @a *pu32 with.
+ */
+DECLINLINE(uint32_t) ASMAtomicUoXorExU32(uint32_t volatile RT_FAR *pu32, uint32_t u32) RT_NOTHROW_DEF
+{
+#if defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32)
+ RTASM_ARM_LOAD_MODIFY_STORE_RET_OLD_32(ASMAtomicUoXorExU32, pu32, NO_BARRIER,
+ "eor %w[uNew], %w[uOld], %w[uVal]\n\t",
+ "eor %[uNew], %[uOld], %[uVal]\n\t",
+ [uVal] "r" (u32));
+ return u32OldRet;
+
+#else
+ return ASMAtomicXorExU32(pu32, u32); /* (we have no unordered cmpxchg primitive atm.) */
+#endif
+}
+
+
+/**
+ * Atomically XOR a signed 32-bit value, unordered.
+ *
+ * @param pi32 Pointer to the variable to XOR @a u32 with.
+ * @param i32 The value to XOR @a *pu32 with.
+ *
+ * @remarks x86: Requires a 386 or later.
+ */
+DECLINLINE(void) ASMAtomicUoXorS32(int32_t volatile RT_FAR *pi32, int32_t i32) RT_NOTHROW_DEF
+{
+ ASMAtomicUoXorU32((uint32_t volatile RT_FAR *)pi32, (uint32_t)i32);
+}
+
+
+/**
+ * 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_TMP_ARM
+RT_ASM_DECL_PRAGMA_WATCOM(uint32_t) ASMAtomicUoIncU32(uint32_t volatile RT_FAR *pu32) RT_NOTHROW_PROTO;
+#else
+DECLINLINE(uint32_t) ASMAtomicUoIncU32(uint32_t volatile RT_FAR *pu32) RT_NOTHROW_DEF
+{
+# if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
+ 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" /** @todo why 'memory'? */
+ , "cc");
+ 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
+
+# elif defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32)
+ RTASM_ARM_LOAD_MODIFY_STORE_RET_NEW_32(ASMAtomicUoIncU32, pu32, NO_BARRIER,
+ "add %w[uNew], %w[uNew], #1\n\t",
+ "add %[uNew], %[uNew], #1\n\t" /* arm6 / thumb2+ */,
+ "X" (0) /* dummy */);
+ return u32NewRet;
+
+# else
+# error "Port me"
+# 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_TMP_ARM
+RT_ASM_DECL_PRAGMA_WATCOM(uint32_t) ASMAtomicUoDecU32(uint32_t volatile RT_FAR *pu32) RT_NOTHROW_PROTO;
+#else
+DECLINLINE(uint32_t) ASMAtomicUoDecU32(uint32_t volatile RT_FAR *pu32) RT_NOTHROW_DEF
+{
+# if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
+ 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"
+ , "cc");
+ 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
+
+# elif defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32)
+ RTASM_ARM_LOAD_MODIFY_STORE_RET_NEW_32(ASMAtomicUoDecU32, pu32, NO_BARRIER,
+ "sub %w[uNew], %w[uNew], #1\n\t",
+ "sub %[uNew], %[uNew], #1\n\t" /* arm6 / thumb2+ */,
+ "X" (0) /* dummy */);
+ return u32NewRet;
+
+# else
+# error "Port me"
+# 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
+#elif defined(RT_ARCH_ARM64)
+# define RT_ASM_PAGE_SIZE 0x4000
+# if defined(PAGE_SIZE) && !defined(NT_INCLUDED) && !defined(_MACH_ARM_VM_PARAM_H_)
+# if PAGE_SIZE != 0x4000
+# error "PAGE_SIZE is not 0x4000!"
+# 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) || (!defined(RT_ARCH_AMD64) && !defined(RT_ARCH_X86))
+RT_ASM_DECL_PRAGMA_WATCOM(void) ASMMemZeroPage(volatile void RT_FAR *pv) RT_NOTHROW_PROTO;
+# else
+DECLINLINE(void) ASMMemZeroPage(volatile void RT_FAR *pv) RT_NOTHROW_DEF
+{
+# 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) || (!defined(RT_ARCH_AMD64) && !defined(RT_ARCH_X86))
+RT_ASM_DECL_PRAGMA_WATCOM(void) ASMMemZero32(volatile void RT_FAR *pv, size_t cb) RT_NOTHROW_PROTO;
+#else
+DECLINLINE(void) ASMMemZero32(volatile void RT_FAR *pv, size_t cb) RT_NOTHROW_DEF
+{
+# if RT_INLINE_ASM_USES_INTRIN
+# ifdef RT_ARCH_AMD64
+ if (!(cb & 7))
+ __stosq((unsigned __int64 RT_FAR *)pv, 0, cb / 8);
+ else
+# endif
+ __stosd((unsigned long RT_FAR *)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) || (!defined(RT_ARCH_AMD64) && !defined(RT_ARCH_X86))
+RT_ASM_DECL_PRAGMA_WATCOM(void) ASMMemFill32(volatile void RT_FAR *pv, size_t cb, uint32_t u32) RT_NOTHROW_PROTO;
+#else
+DECLINLINE(void) ASMMemFill32(volatile void RT_FAR *pv, size_t cb, uint32_t u32) RT_NOTHROW_DEF
+{
+# if RT_INLINE_ASM_USES_INTRIN
+# ifdef RT_ARCH_AMD64
+ if (!(cb & 7))
+ __stosq((unsigned __int64 RT_FAR *)pv, RT_MAKE_U64(u32, u32), cb / 8);
+ else
+# endif
+ __stosd((unsigned long RT_FAR *)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.
+ */
+#if !defined(RDESKTOP) && (!defined(RT_OS_LINUX) || !defined(__KERNEL__))
+DECLASM(void RT_FAR *) ASMMemFirstNonZero(void const RT_FAR *pv, size_t cb) RT_NOTHROW_PROTO;
+#else
+DECLINLINE(void RT_FAR *) ASMMemFirstNonZero(void const RT_FAR *pv, size_t cb) RT_NOTHROW_DEF
+{
+/** @todo replace with ASMMemFirstNonZero-generic.cpp in kernel modules. */
+ uint8_t const *pb = (uint8_t const RT_FAR *)pv;
+ for (; cb; cb--, pb++)
+ if (RT_LIKELY(*pb == 0))
+ { /* likely */ }
+ else
+ return (void RT_FAR *)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 RT_FAR *pv, size_t cb) RT_NOTHROW_DEF
+{
+ 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 RT_FAR *pvPage) RT_NOTHROW_DEF
+{
+# 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)
+ : "cc");
+ return uAX.f;
+# else
+ uintptr_t const RT_FAR *puPtr = (uintptr_t const RT_FAR *)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 RT_FAR *pv, size_t cb, uint8_t u8) RT_NOTHROW_PROTO;
+#else
+DECLINLINE(void *) ASMMemFirstMismatchingU8(void const RT_FAR *pv, size_t cb, uint8_t u8) RT_NOTHROW_DEF
+{
+/** @todo replace with ASMMemFirstMismatchingU8-generic.cpp in kernel modules. */
+ uint8_t const *pb = (uint8_t const RT_FAR *)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 RT_FAR *pv, size_t cb, uint8_t u8) RT_NOTHROW_DEF
+{
+ 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 RT_FAR *) ASMMemFirstMismatchingU32(void const RT_FAR *pv, size_t cb, uint32_t u32) RT_NOTHROW_DEF
+{
+/** @todo rewrite this in inline assembly? */
+ uint32_t const RT_FAR *pu32 = (uint32_t const RT_FAR *)pv;
+ for (; cb; cb -= 4, pu32++)
+ if (RT_LIKELY(*pu32 == u32))
+ { /* likely */ }
+ else
+ return (uint32_t RT_FAR *)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_TMP_ARM
+RT_ASM_DECL_PRAGMA_WATCOM(uint8_t) ASMProbeReadByte(const void RT_FAR *pvByte) RT_NOTHROW_PROTO;
+#else
+DECLINLINE(uint8_t) ASMProbeReadByte(const void RT_FAR *pvByte) RT_NOTHROW_DEF
+{
+# if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
+ uint8_t u8;
+# if RT_INLINE_ASM_GNU_STYLE
+ __asm__ __volatile__("movb %1, %0\n\t"
+ : "=q" (u8)
+ : "m" (*(const uint8_t *)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;
+
+# elif defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32)
+ uint32_t u32;
+ __asm__ __volatile__(".Lstart_ASMProbeReadByte_%=:\n\t"
+# if defined(RT_ARCH_ARM64)
+ "ldxrb %w[uDst], %[pMem]\n\t"
+# else
+ "ldrexb %[uDst], %[pMem]\n\t"
+# endif
+ : [uDst] "=&r" (u32)
+ : [pMem] "Q" (*(uint8_t const *)pvByte));
+ return (uint8_t)u32;
+
+# else
+# error "Port me"
+# endif
+}
+#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 RT_FAR *pvBuf, size_t cbBuf) RT_NOTHROW_DEF
+{
+ /** @todo verify that the compiler actually doesn't optimize this away. (intel & gcc) */
+ /* the first byte */
+ const uint8_t RT_FAR *pu8 = (const uint8_t RT_FAR *)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);
+}
+
+
+/**
+ * Reverse the byte order of the given 16-bit integer.
+ *
+ * @returns Revert
+ * @param u16 16-bit integer value.
+ */
+#if RT_INLINE_ASM_EXTERNAL_TMP_ARM && !RT_INLINE_ASM_USES_INTRIN
+RT_ASM_DECL_PRAGMA_WATCOM(uint16_t) ASMByteSwapU16(uint16_t u16) RT_NOTHROW_PROTO;
+#else
+DECLINLINE(uint16_t) ASMByteSwapU16(uint16_t u16) RT_NOTHROW_DEF
+{
+# if RT_INLINE_ASM_USES_INTRIN
+ return _byteswap_ushort(u16);
+
+# elif defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
+# if RT_INLINE_ASM_GNU_STYLE
+ __asm__ ("rorw $8, %0" : "=r" (u16) : "0" (u16) : "cc");
+# else
+ _asm
+ {
+ mov ax, [u16]
+ ror ax, 8
+ mov [u16], ax
+ }
+# endif
+ return u16;
+
+# elif defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32)
+ uint32_t u32Ret;
+ __asm__ __volatile__(
+# if defined(RT_ARCH_ARM64)
+ "rev16 %w[uRet], %w[uVal]\n\t"
+# else
+ "rev16 %[uRet], %[uVal]\n\t"
+# endif
+ : [uRet] "=r" (u32Ret)
+ : [uVal] "r" (u16));
+ return (uint16_t)u32Ret;
+
+# else
+# error "Port me"
+# endif
+}
+#endif
+
+
+/**
+ * Reverse the byte order of the given 32-bit integer.
+ *
+ * @returns Revert
+ * @param u32 32-bit integer value.
+ */
+#if RT_INLINE_ASM_EXTERNAL_TMP_ARM && !RT_INLINE_ASM_USES_INTRIN
+RT_ASM_DECL_PRAGMA_WATCOM(uint32_t) ASMByteSwapU32(uint32_t u32) RT_NOTHROW_PROTO;
+#else
+DECLINLINE(uint32_t) ASMByteSwapU32(uint32_t u32) RT_NOTHROW_DEF
+{
+# if RT_INLINE_ASM_USES_INTRIN
+ return _byteswap_ulong(u32);
+
+# elif defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
+# if 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;
+
+# elif defined(RT_ARCH_ARM64)
+ uint64_t u64Ret;
+ __asm__ __volatile__("rev32 %[uRet], %[uVal]\n\t"
+ : [uRet] "=r" (u64Ret)
+ : [uVal] "r" ((uint64_t)u32));
+ return (uint32_t)u64Ret;
+
+# elif defined(RT_ARCH_ARM32)
+ __asm__ __volatile__("rev %[uRet], %[uVal]\n\t"
+ : [uRet] "=r" (u32)
+ : [uVal] "[uRet]" (u32));
+ return u32;
+
+# else
+# error "Port me"
+# endif
+}
+#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) RT_NOTHROW_DEF
+{
+#if defined(RT_ARCH_AMD64) && RT_INLINE_ASM_USES_INTRIN
+ return _byteswap_uint64(u64);
+
+# elif RT_INLINE_ASM_GNU_STYLE && defined(RT_ARCH_AMD64)
+ __asm__ ("bswapq %0" : "=r" (u64) : "0" (u64));
+ return u64;
+
+# elif defined(RT_ARCH_ARM64)
+ __asm__ __volatile__("rev %[uRet], %[uVal]\n\t"
+ : [uRet] "=r" (u64)
+ : [uVal] "[uRet]" (u64));
+ return u64;
+
+#else
+ return (uint64_t)ASMByteSwapU32((uint32_t)u64) << 32
+ | (uint64_t)ASMByteSwapU32((uint32_t)(u64 >> 32));
+#endif
+}
+
+
+
+/** @defgroup grp_inline_bits Bit Operations
+ * @{
+ */
+
+
+/**
+ * Sets a bit in a bitmap.
+ *
+ * @param pvBitmap Pointer to the bitmap (little endian). 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_TMP_ARM && !RT_INLINE_ASM_USES_INTRIN
+RT_ASM_DECL_PRAGMA_WATCOM(void) ASMBitSet(volatile void RT_FAR *pvBitmap, int32_t iBit) RT_NOTHROW_PROTO;
+#else
+DECLINLINE(void) ASMBitSet(volatile void RT_FAR *pvBitmap, int32_t iBit) RT_NOTHROW_DEF
+{
+# if RT_INLINE_ASM_USES_INTRIN
+ _bittestandset((long RT_FAR *)pvBitmap, iBit);
+
+# elif defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
+# if RT_INLINE_ASM_GNU_STYLE
+ __asm__ __volatile__("btsl %1, %0"
+ : "=m" (*(volatile long RT_FAR *)pvBitmap)
+ : "Ir" (iBit)
+ , "m" (*(volatile long RT_FAR *)pvBitmap)
+ : "memory"
+ , "cc");
+# 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
+
+# else
+ int32_t offBitmap = iBit / 32;
+ AssertStmt(!((uintptr_t)pvBitmap & 3), offBitmap += (uintptr_t)pvBitmap & 3; iBit += ((uintptr_t)pvBitmap & 3) * 8);
+ ASMAtomicUoOrU32(&((uint32_t volatile *)pvBitmap)[offBitmap], RT_H2LE_U32(RT_BIT_32(iBit & 31)));
+# endif
+}
+#endif
+
+
+/**
+ * Atomically sets a bit in a bitmap, ordered.
+ *
+ * @param pvBitmap Pointer to the bitmap (little endian). 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_TMP_ARM && !RT_INLINE_ASM_USES_INTRIN
+RT_ASM_DECL_PRAGMA_WATCOM(void) ASMAtomicBitSet(volatile void RT_FAR *pvBitmap, int32_t iBit) RT_NOTHROW_PROTO;
+#else
+DECLINLINE(void) ASMAtomicBitSet(volatile void RT_FAR *pvBitmap, int32_t iBit) RT_NOTHROW_DEF
+{
+ AssertMsg(!((uintptr_t)pvBitmap & 3), ("address %p not 32-bit aligned", pvBitmap));
+# if RT_INLINE_ASM_USES_INTRIN
+ _interlockedbittestandset((long RT_FAR *)pvBitmap, iBit);
+# elif defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
+# if RT_INLINE_ASM_GNU_STYLE
+ __asm__ __volatile__("lock; btsl %1, %0"
+ : "=m" (*(volatile long *)pvBitmap)
+ : "Ir" (iBit)
+ , "m" (*(volatile long *)pvBitmap)
+ : "memory"
+ , "cc");
+# 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
+
+# else
+ ASMAtomicOrU32(&((uint32_t volatile *)pvBitmap)[iBit / 32], RT_H2LE_U32(RT_BIT_32(iBit & 31)));
+# endif
+}
+#endif
+
+
+/**
+ * Clears a bit in a bitmap.
+ *
+ * @param pvBitmap Pointer to the bitmap (little endian).
+ * @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_TMP_ARM && !RT_INLINE_ASM_USES_INTRIN
+RT_ASM_DECL_PRAGMA_WATCOM(void) ASMBitClear(volatile void RT_FAR *pvBitmap, int32_t iBit) RT_NOTHROW_PROTO;
+#else
+DECLINLINE(void) ASMBitClear(volatile void RT_FAR *pvBitmap, int32_t iBit) RT_NOTHROW_DEF
+{
+# if RT_INLINE_ASM_USES_INTRIN
+ _bittestandreset((long RT_FAR *)pvBitmap, iBit);
+
+# elif defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
+# if RT_INLINE_ASM_GNU_STYLE
+ __asm__ __volatile__("btrl %1, %0"
+ : "=m" (*(volatile long RT_FAR *)pvBitmap)
+ : "Ir" (iBit)
+ , "m" (*(volatile long RT_FAR *)pvBitmap)
+ : "memory"
+ , "cc");
+# 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
+
+# else
+ int32_t offBitmap = iBit / 32;
+ AssertStmt(!((uintptr_t)pvBitmap & 3), offBitmap += (uintptr_t)pvBitmap & 3; iBit += ((uintptr_t)pvBitmap & 3) * 8);
+ ASMAtomicUoAndU32(&((uint32_t volatile *)pvBitmap)[offBitmap], RT_H2LE_U32(~RT_BIT_32(iBit & 31)));
+# endif
+}
+#endif
+
+
+/**
+ * Atomically clears a bit in a bitmap, ordered.
+ *
+ * @param pvBitmap Pointer to the bitmap (little endian). 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_TMP_ARM
+RT_ASM_DECL_PRAGMA_WATCOM(void) ASMAtomicBitClear(volatile void RT_FAR *pvBitmap, int32_t iBit) RT_NOTHROW_PROTO;
+#else
+DECLINLINE(void) ASMAtomicBitClear(volatile void RT_FAR *pvBitmap, int32_t iBit) RT_NOTHROW_DEF
+{
+ AssertMsg(!((uintptr_t)pvBitmap & 3), ("address %p not 32-bit aligned", pvBitmap));
+# if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
+# if RT_INLINE_ASM_GNU_STYLE
+ __asm__ __volatile__("lock; btrl %1, %0"
+ : "=m" (*(volatile long RT_FAR *)pvBitmap)
+ : "Ir" (iBit)
+ , "m" (*(volatile long RT_FAR *)pvBitmap)
+ : "memory"
+ , "cc");
+# 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
+# else
+ ASMAtomicAndU32(&((uint32_t volatile *)pvBitmap)[iBit / 32], RT_H2LE_U32(~RT_BIT_32(iBit & 31)));
+# endif
+}
+#endif
+
+
+/**
+ * Toggles a bit in a bitmap.
+ *
+ * @param pvBitmap Pointer to the bitmap (little endian).
+ * @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_TMP_ARM && !RT_INLINE_ASM_USES_INTRIN
+RT_ASM_DECL_PRAGMA_WATCOM(void) ASMBitToggle(volatile void RT_FAR *pvBitmap, int32_t iBit) RT_NOTHROW_PROTO;
+#else
+DECLINLINE(void) ASMBitToggle(volatile void RT_FAR *pvBitmap, int32_t iBit) RT_NOTHROW_DEF
+{
+# if RT_INLINE_ASM_USES_INTRIN
+ _bittestandcomplement((long RT_FAR *)pvBitmap, iBit);
+# elif defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
+# if RT_INLINE_ASM_GNU_STYLE
+ __asm__ __volatile__("btcl %1, %0"
+ : "=m" (*(volatile long *)pvBitmap)
+ : "Ir" (iBit)
+ , "m" (*(volatile long *)pvBitmap)
+ : "memory"
+ , "cc");
+# 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
+# else
+ int32_t offBitmap = iBit / 32;
+ AssertStmt(!((uintptr_t)pvBitmap & 3), offBitmap += (uintptr_t)pvBitmap & 3; iBit += ((uintptr_t)pvBitmap & 3) * 8);
+ ASMAtomicUoXorU32(&((uint32_t volatile *)pvBitmap)[offBitmap], RT_H2LE_U32(RT_BIT_32(iBit & 31)));
+# endif
+}
+#endif
+
+
+/**
+ * Atomically toggles a bit in a bitmap, ordered.
+ *
+ * @param pvBitmap Pointer to the bitmap (little endian). 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_TMP_ARM
+RT_ASM_DECL_PRAGMA_WATCOM(void) ASMAtomicBitToggle(volatile void RT_FAR *pvBitmap, int32_t iBit) RT_NOTHROW_PROTO;
+#else
+DECLINLINE(void) ASMAtomicBitToggle(volatile void RT_FAR *pvBitmap, int32_t iBit) RT_NOTHROW_DEF
+{
+ AssertMsg(!((uintptr_t)pvBitmap & 3), ("address %p not 32-bit aligned", pvBitmap));
+# if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
+# if RT_INLINE_ASM_GNU_STYLE
+ __asm__ __volatile__("lock; btcl %1, %0"
+ : "=m" (*(volatile long RT_FAR *)pvBitmap)
+ : "Ir" (iBit)
+ , "m" (*(volatile long RT_FAR *)pvBitmap)
+ : "memory"
+ , "cc");
+# 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
+# else
+ ASMAtomicXorU32(&((uint32_t volatile *)pvBitmap)[iBit / 32], RT_H2LE_U32(RT_BIT_32(iBit & 31)));
+# 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 (little endian).
+ * @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_TMP_ARM && !RT_INLINE_ASM_USES_INTRIN
+RT_ASM_DECL_PRAGMA_WATCOM(bool) ASMBitTestAndSet(volatile void RT_FAR *pvBitmap, int32_t iBit) RT_NOTHROW_PROTO;
+#else
+DECLINLINE(bool) ASMBitTestAndSet(volatile void RT_FAR *pvBitmap, int32_t iBit) RT_NOTHROW_DEF
+{
+ union { bool f; uint32_t u32; uint8_t u8; } rc;
+# if RT_INLINE_ASM_USES_INTRIN
+ rc.u8 = _bittestandset((long RT_FAR *)pvBitmap, iBit);
+
+# elif defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
+# if 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 RT_FAR *)pvBitmap)
+ : "Ir" (iBit)
+ , "m" (*(volatile long RT_FAR *)pvBitmap)
+ : "memory"
+ , "cc");
+# 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
+
+# else
+ int32_t offBitmap = iBit / 32;
+ AssertStmt(!((uintptr_t)pvBitmap & 3), offBitmap += (uintptr_t)pvBitmap & 3; iBit += ((uintptr_t)pvBitmap & 3) * 8);
+ rc.u32 = RT_LE2H_U32(ASMAtomicUoOrExU32(&((uint32_t volatile *)pvBitmap)[offBitmap], RT_H2LE_U32(RT_BIT_32(iBit & 31))))
+ >> (iBit & 31);
+ rc.u32 &= 1;
+# 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 (little endian). 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_TMP_ARM && !RT_INLINE_ASM_USES_INTRIN
+RT_ASM_DECL_PRAGMA_WATCOM(bool) ASMAtomicBitTestAndSet(volatile void RT_FAR *pvBitmap, int32_t iBit) RT_NOTHROW_PROTO;
+#else
+DECLINLINE(bool) ASMAtomicBitTestAndSet(volatile void RT_FAR *pvBitmap, int32_t iBit) RT_NOTHROW_DEF
+{
+ 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 RT_FAR *)pvBitmap, iBit);
+# elif defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
+# if 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 RT_FAR *)pvBitmap)
+ : "Ir" (iBit)
+ , "m" (*(volatile long RT_FAR *)pvBitmap)
+ : "memory"
+ , "cc");
+# 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
+
+# else
+ rc.u32 = RT_LE2H_U32(ASMAtomicOrExU32(&((uint32_t volatile *)pvBitmap)[iBit / 32], RT_H2LE_U32(RT_BIT_32(iBit & 31))))
+ >> (iBit & 31);
+ rc.u32 &= 1;
+# 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 (little endian).
+ * @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_TMP_ARM && !RT_INLINE_ASM_USES_INTRIN
+RT_ASM_DECL_PRAGMA_WATCOM(bool) ASMBitTestAndClear(volatile void RT_FAR *pvBitmap, int32_t iBit) RT_NOTHROW_PROTO;
+#else
+DECLINLINE(bool) ASMBitTestAndClear(volatile void RT_FAR *pvBitmap, int32_t iBit) RT_NOTHROW_DEF
+{
+ union { bool f; uint32_t u32; uint8_t u8; } rc;
+# if RT_INLINE_ASM_USES_INTRIN
+ rc.u8 = _bittestandreset((long RT_FAR *)pvBitmap, iBit);
+
+# elif defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
+# if 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 RT_FAR *)pvBitmap)
+ : "Ir" (iBit)
+ , "m" (*(volatile long RT_FAR *)pvBitmap)
+ : "memory"
+ , "cc");
+# 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
+
+# else
+ int32_t offBitmap = iBit / 32;
+ AssertStmt(!((uintptr_t)pvBitmap & 3), offBitmap += (uintptr_t)pvBitmap & 3; iBit += ((uintptr_t)pvBitmap & 3) * 8);
+ rc.u32 = RT_LE2H_U32(ASMAtomicUoAndExU32(&((uint32_t volatile *)pvBitmap)[offBitmap], RT_H2LE_U32(~RT_BIT_32(iBit & 31))))
+ >> (iBit & 31);
+ rc.u32 &= 1;
+# 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 (little endian). 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_TMP_ARM && !RT_INLINE_ASM_USES_INTRIN
+RT_ASM_DECL_PRAGMA_WATCOM(bool) ASMAtomicBitTestAndClear(volatile void RT_FAR *pvBitmap, int32_t iBit) RT_NOTHROW_PROTO;
+#else
+DECLINLINE(bool) ASMAtomicBitTestAndClear(volatile void RT_FAR *pvBitmap, int32_t iBit) RT_NOTHROW_DEF
+{
+ 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 RT_FAR *)pvBitmap, iBit);
+
+# elif defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
+# if 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 RT_FAR *)pvBitmap)
+ : "Ir" (iBit)
+ , "m" (*(volatile long RT_FAR *)pvBitmap)
+ : "memory"
+ , "cc");
+# 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
+
+# else
+ rc.u32 = RT_LE2H_U32(ASMAtomicAndExU32(&((uint32_t volatile *)pvBitmap)[iBit / 32], RT_H2LE_U32(~RT_BIT_32(iBit & 31))))
+ >> (iBit & 31);
+ rc.u32 &= 1;
+# 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 (little endian).
+ * @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_TMP_ARM && !RT_INLINE_ASM_USES_INTRIN
+RT_ASM_DECL_PRAGMA_WATCOM(bool) ASMBitTestAndToggle(volatile void RT_FAR *pvBitmap, int32_t iBit) RT_NOTHROW_PROTO;
+#else
+DECLINLINE(bool) ASMBitTestAndToggle(volatile void RT_FAR *pvBitmap, int32_t iBit) RT_NOTHROW_DEF
+{
+ union { bool f; uint32_t u32; uint8_t u8; } rc;
+# if RT_INLINE_ASM_USES_INTRIN
+ rc.u8 = _bittestandcomplement((long RT_FAR *)pvBitmap, iBit);
+
+# elif defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
+# if 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 RT_FAR *)pvBitmap)
+ : "Ir" (iBit)
+ , "m" (*(volatile long RT_FAR *)pvBitmap)
+ : "memory"
+ , "cc");
+# 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
+
+# else
+ int32_t offBitmap = iBit / 32;
+ AssertStmt(!((uintptr_t)pvBitmap & 3), offBitmap += (uintptr_t)pvBitmap & 3; iBit += ((uintptr_t)pvBitmap & 3) * 8);
+ rc.u32 = RT_LE2H_U32(ASMAtomicUoXorExU32(&((uint32_t volatile *)pvBitmap)[offBitmap], RT_H2LE_U32(RT_BIT_32(iBit & 31))))
+ >> (iBit & 31);
+ rc.u32 &= 1;
+# 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 (little endian). 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_TMP_ARM
+RT_ASM_DECL_PRAGMA_WATCOM(bool) ASMAtomicBitTestAndToggle(volatile void RT_FAR *pvBitmap, int32_t iBit) RT_NOTHROW_PROTO;
+#else
+DECLINLINE(bool) ASMAtomicBitTestAndToggle(volatile void RT_FAR *pvBitmap, int32_t iBit) RT_NOTHROW_DEF
+{
+ union { bool f; uint32_t u32; uint8_t u8; } rc;
+ AssertMsg(!((uintptr_t)pvBitmap & 3), ("address %p not 32-bit aligned", pvBitmap));
+# if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
+# 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 RT_FAR *)pvBitmap)
+ : "Ir" (iBit)
+ , "m" (*(volatile long RT_FAR *)pvBitmap)
+ : "memory"
+ , "cc");
+# 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
+
+# else
+ rc.u32 = RT_H2LE_U32(ASMAtomicXorExU32(&((uint32_t volatile *)pvBitmap)[iBit / 32], RT_LE2H_U32(RT_BIT_32(iBit & 31))))
+ >> (iBit & 31);
+ rc.u32 &= 1;
+# 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 (little endian).
+ * @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_TMP_ARM && !RT_INLINE_ASM_USES_INTRIN
+RT_ASM_DECL_PRAGMA_WATCOM(bool) ASMBitTest(const volatile void RT_FAR *pvBitmap, int32_t iBit) RT_NOTHROW_PROTO;
+#else
+DECLINLINE(bool) ASMBitTest(const volatile void RT_FAR *pvBitmap, int32_t iBit) RT_NOTHROW_DEF
+{
+ union { bool f; uint32_t u32; uint8_t u8; } rc;
+# if RT_INLINE_ASM_USES_INTRIN
+ rc.u32 = _bittest((long *)pvBitmap, iBit);
+
+# elif defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
+# if 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 RT_FAR *)pvBitmap)
+ , "Ir" (iBit)
+ : "memory"
+ , "cc");
+# 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
+
+# else
+ int32_t offBitmap = iBit / 32;
+ AssertStmt(!((uintptr_t)pvBitmap & 3), offBitmap += (uintptr_t)pvBitmap & 3; iBit += ((uintptr_t)pvBitmap & 3) * 8);
+ rc.u32 = RT_LE2H_U32(ASMAtomicUoReadU32(&((uint32_t volatile *)pvBitmap)[offBitmap])) >> (iBit & 31);
+ rc.u32 &= 1;
+# endif
+ return rc.f;
+}
+#endif
+
+
+/**
+ * Clears a bit range within a bitmap.
+ *
+ * @param pvBitmap Pointer to the bitmap (little endian).
+ * @param iBitStart The First bit to clear.
+ * @param iBitEnd The first bit not to clear.
+ */
+DECLINLINE(void) ASMBitClearRange(volatile void RT_FAR *pvBitmap, size_t iBitStart, size_t iBitEnd) RT_NOTHROW_DEF
+{
+ if (iBitStart < iBitEnd)
+ {
+ uint32_t volatile RT_FAR *pu32 = (volatile uint32_t RT_FAR *)pvBitmap + (iBitStart >> 5);
+ size_t iStart = iBitStart & ~(size_t)31;
+ size_t iEnd = iBitEnd & ~(size_t)31;
+ if (iStart == iEnd)
+ *pu32 &= RT_H2LE_U32(((UINT32_C(1) << (iBitStart & 31)) - 1) | ~((UINT32_C(1) << (iBitEnd & 31)) - 1));
+ else
+ {
+ /* bits in first dword. */
+ if (iBitStart & 31)
+ {
+ *pu32 &= RT_H2LE_U32((UINT32_C(1) << (iBitStart & 31)) - 1);
+ pu32++;
+ iBitStart = iStart + 32;
+ }
+
+ /* whole dwords. */
+ if (iBitStart != iEnd)
+ ASMMemZero32(pu32, (iEnd - iBitStart) >> 3);
+
+ /* bits in last dword. */
+ if (iBitEnd & 31)
+ {
+ pu32 = (volatile uint32_t RT_FAR *)pvBitmap + (iBitEnd >> 5);
+ *pu32 &= RT_H2LE_U32(~((UINT32_C(1) << (iBitEnd & 31)) - 1));
+ }
+ }
+ }
+}
+
+
+/**
+ * Sets a bit range within a bitmap.
+ *
+ * @param pvBitmap Pointer to the bitmap (little endian).
+ * @param iBitStart The First bit to set.
+ * @param iBitEnd The first bit not to set.
+ */
+DECLINLINE(void) ASMBitSetRange(volatile void RT_FAR *pvBitmap, size_t iBitStart, size_t iBitEnd) RT_NOTHROW_DEF
+{
+ if (iBitStart < iBitEnd)
+ {
+ uint32_t volatile RT_FAR *pu32 = (volatile uint32_t RT_FAR *)pvBitmap + (iBitStart >> 5);
+ size_t iStart = iBitStart & ~(size_t)31;
+ size_t iEnd = iBitEnd & ~(size_t)31;
+ if (iStart == iEnd)
+ *pu32 |= RT_H2LE_U32(((UINT32_C(1) << (iBitEnd - iBitStart)) - 1) << (iBitStart & 31));
+ else
+ {
+ /* bits in first dword. */
+ if (iBitStart & 31)
+ {
+ *pu32 |= RT_H2LE_U32(~((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 RT_FAR *)pvBitmap + (iBitEnd >> 5);
+ *pu32 |= RT_H2LE_U32((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 (little endian).
+ * @param cBits The number of bits in the bitmap. Multiple of 32.
+ */
+#if RT_INLINE_ASM_EXTERNAL || (!defined(RT_ARCH_AMD64) && !defined(RT_ARCH_X86))
+DECLASM(int32_t) ASMBitFirstClear(const volatile void RT_FAR *pvBitmap, uint32_t cBits) RT_NOTHROW_PROTO;
+#else
+DECLINLINE(int32_t) ASMBitFirstClear(const volatile void RT_FAR *pvBitmap, uint32_t cBits) RT_NOTHROW_DEF
+{
+ 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)
+ : "cc");
+# 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 (little endian).
+ * @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 || (!defined(RT_ARCH_AMD64) && !defined(RT_ARCH_X86))
+DECLASM(int) ASMBitNextClear(const volatile void RT_FAR *pvBitmap, uint32_t cBits, uint32_t iBitPrev) RT_NOTHROW_PROTO;
+#else
+DECLINLINE(int) ASMBitNextClear(const volatile void RT_FAR *pvBitmap, uint32_t cBits, uint32_t iBitPrev) RT_NOTHROW_DEF
+{
+ const volatile uint32_t RT_FAR *pau32Bitmap = (const volatile uint32_t RT_FAR *)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" /** @todo use conditional move for 64-bit? */
+ "1:\n\t"
+ : "=r" (iBit)
+ : "r" (u32)
+ : "cc");
+# else
+ __asm
+ {
+ mov edx, [u32]
+ bsf eax, edx
+ jnz done
+ mov eax, 0ffffffffh
+ done:
+ mov [iBit], eax
+ }
+# endif
+ if (iBit >= 0)
+ return iBit + (int)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 (little endian).
+ * @param cBits The number of bits in the bitmap. Multiple of 32.
+ */
+#if RT_INLINE_ASM_EXTERNAL || (!defined(RT_ARCH_AMD64) && !defined(RT_ARCH_X86))
+DECLASM(int32_t) ASMBitFirstSet(const volatile void RT_FAR *pvBitmap, uint32_t cBits) RT_NOTHROW_PROTO;
+#else
+DECLINLINE(int32_t) ASMBitFirstSet(const volatile void RT_FAR *pvBitmap, uint32_t cBits) RT_NOTHROW_DEF
+{
+ 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)
+ : "cc");
+# 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 (little endian).
+ * @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 || (!defined(RT_ARCH_AMD64) && !defined(RT_ARCH_X86))
+DECLASM(int) ASMBitNextSet(const volatile void RT_FAR *pvBitmap, uint32_t cBits, uint32_t iBitPrev) RT_NOTHROW_PROTO;
+#else
+DECLINLINE(int) ASMBitNextSet(const volatile void RT_FAR *pvBitmap, uint32_t cBits, uint32_t iBitPrev) RT_NOTHROW_DEF
+{
+ const volatile uint32_t RT_FAR *pau32Bitmap = (const volatile uint32_t RT_FAR *)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" /** @todo use conditional move for 64-bit? */
+ "movl $-1, %0\n\t"
+ "1:\n\t"
+ : "=r" (iBit)
+ : "r" (u32)
+ : "cc");
+# else
+ __asm
+ {
+ mov edx, [u32]
+ bsf eax, edx
+ jnz done
+ mov eax, 0ffffffffh
+ done:
+ mov [iBit], eax
+ }
+# endif
+ if (iBit >= 0)
+ return iBit + (int)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_TMP_ARM && !RT_INLINE_ASM_USES_INTRIN
+RT_ASM_DECL_PRAGMA_WATCOM_386(unsigned) ASMBitFirstSetU32(uint32_t u32) RT_NOTHROW_PROTO;
+#else
+DECLINLINE(unsigned) ASMBitFirstSetU32(uint32_t u32) RT_NOTHROW_DEF
+{
+# if RT_INLINE_ASM_USES_INTRIN
+ unsigned long iBit;
+ if (_BitScanForward(&iBit, u32))
+ iBit++;
+ else
+ iBit = 0;
+
+# elif defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
+# if 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)
+ : "cc");
+# else
+ uint32_t iBit;
+ _asm
+ {
+ bsf eax, [u32]
+ jnz found
+ xor eax, eax
+ jmp done
+ found:
+ inc eax
+ done:
+ mov [iBit], eax
+ }
+# endif
+
+# elif defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32)
+ /*
+ * Using the "count leading zeros (clz)" instruction here because there
+ * is no dedicated instruction to get the first set bit.
+ * Need to reverse the bits in the value with "rbit" first because
+ * "clz" starts counting from the most significant bit.
+ */
+ uint32_t iBit;
+ __asm__ __volatile__(
+# if defined(RT_ARCH_ARM64)
+ "rbit %w[uVal], %w[uVal]\n\t"
+ "clz %w[iBit], %w[uVal]\n\t"
+# else
+ "rbit %[uVal], %[uVal]\n\t"
+ "clz %[iBit], %[uVal]\n\t"
+# endif
+ : [uVal] "=r" (u32)
+ , [iBit] "=r" (iBit)
+ : "[uVal]" (u32));
+ if (iBit != 32)
+ iBit++;
+ else
+ iBit = 0; /* No bit set. */
+
+# else
+# error "Port me"
+# 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) RT_NOTHROW_DEF
+{
+ 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_TMP_ARM && !RT_INLINE_ASM_USES_INTRIN
+RT_ASM_DECL_PRAGMA_WATCOM_386(unsigned) ASMBitFirstSetU64(uint64_t u64) RT_NOTHROW_PROTO;
+#else
+DECLINLINE(unsigned) ASMBitFirstSetU64(uint64_t u64) RT_NOTHROW_DEF
+{
+# 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 && defined(RT_ARCH_AMD64)
+ 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)
+ : "cc");
+
+# elif defined(RT_ARCH_ARM64)
+ uint64_t iBit;
+ __asm__ __volatile__("rbit %[uVal], %[uVal]\n\t"
+ "clz %[iBit], %[uVal]\n\t"
+ : [uVal] "=r" (u64)
+ , [iBit] "=r" (iBit)
+ : "[uVal]" (u64));
+ if (iBit != 64)
+ iBit++;
+ else
+ iBit = 0; /* No bit set. */
+
+# 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_TMP_ARM && !RT_INLINE_ASM_USES_INTRIN
+RT_ASM_DECL_PRAGMA_WATCOM_386(unsigned) ASMBitFirstSetU16(uint16_t u16) RT_NOTHROW_PROTO;
+#else
+DECLINLINE(unsigned) ASMBitFirstSetU16(uint16_t u16) RT_NOTHROW_DEF
+{
+ 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_TMP_ARM && !RT_INLINE_ASM_USES_INTRIN
+RT_ASM_DECL_PRAGMA_WATCOM_386(unsigned) ASMBitLastSetU32(uint32_t u32) RT_NOTHROW_PROTO;
+#else
+DECLINLINE(unsigned) ASMBitLastSetU32(uint32_t u32) RT_NOTHROW_DEF
+{
+# if RT_INLINE_ASM_USES_INTRIN
+ unsigned long iBit;
+ if (_BitScanReverse(&iBit, u32))
+ iBit++;
+ else
+ iBit = 0;
+
+# elif defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
+# if 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)
+ : "cc");
+# else
+ uint32_t iBit;
+ _asm
+ {
+ bsr eax, [u32]
+ jnz found
+ xor eax, eax
+ jmp done
+ found:
+ inc eax
+ done:
+ mov [iBit], eax
+ }
+# endif
+
+# elif defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32)
+ uint32_t iBit;
+ __asm__ __volatile__(
+# if defined(RT_ARCH_ARM64)
+ "clz %w[iBit], %w[uVal]\n\t"
+# else
+ "clz %[iBit], %[uVal]\n\t"
+# endif
+ : [iBit] "=r" (iBit)
+ : [uVal] "r" (u32));
+ iBit = 32 - iBit;
+
+# else
+# error "Port me"
+# 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) RT_NOTHROW_DEF
+{
+ 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_TMP_ARM && !RT_INLINE_ASM_USES_INTRIN
+RT_ASM_DECL_PRAGMA_WATCOM_386(unsigned) ASMBitLastSetU64(uint64_t u64) RT_NOTHROW_PROTO;
+#else
+DECLINLINE(unsigned) ASMBitLastSetU64(uint64_t u64) RT_NOTHROW_DEF
+{
+# 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 && defined(RT_ARCH_AMD64)
+ 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)
+ : "cc");
+
+# elif defined(RT_ARCH_ARM64)
+ uint64_t iBit;
+ __asm__ __volatile__("clz %[iBit], %[uVal]\n\t"
+ : [iBit] "=r" (iBit)
+ : [uVal] "r" (u64));
+ iBit = 64 - iBit;
+
+# 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_TMP_ARM && !RT_INLINE_ASM_USES_INTRIN
+RT_ASM_DECL_PRAGMA_WATCOM_386(unsigned) ASMBitLastSetU16(uint16_t u16) RT_NOTHROW_PROTO;
+#else
+DECLINLINE(unsigned) ASMBitLastSetU16(uint16_t u16) RT_NOTHROW_DEF
+{
+ return ASMBitLastSetU32((uint32_t)u16);
+}
+#endif
+
+
+/**
+ * Count the number of leading zero bits in the given 32-bit integer.
+ *
+ * The counting starts with the most significate bit.
+ *
+ * @returns Number of most significant zero bits.
+ * @returns 32 if all bits are cleared.
+ * @param u32 Integer to consider.
+ * @remarks Similar to __builtin_clz() in gcc, except defined zero input result.
+ */
+#if RT_INLINE_ASM_EXTERNAL_TMP_ARM && !RT_INLINE_ASM_USES_INTRIN
+RT_ASM_DECL_PRAGMA_WATCOM_386(unsigned) ASMCountLeadingZerosU32(uint32_t u32) RT_NOTHROW_PROTO;
+#else
+DECLINLINE(unsigned) ASMCountLeadingZerosU32(uint32_t u32) RT_NOTHROW_DEF
+{
+# if RT_INLINE_ASM_USES_INTRIN
+ unsigned long iBit;
+ if (!_BitScanReverse(&iBit, u32))
+ return 32;
+ return 31 - (unsigned)iBit;
+
+# elif defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
+ uint32_t iBit;
+# if RT_INLINE_ASM_GNU_STYLE && defined(RT_ARCH_AMD64) && 0 /* significantly slower on 10980xe; 929 vs 237 ps/call */
+ __asm__ __volatile__("bsrl %1, %0\n\t"
+ "cmovzl %2, %0\n\t"
+ : "=&r" (iBit)
+ : "rm" (u32)
+ , "rm" ((int32_t)-1)
+ : "cc");
+# elif RT_INLINE_ASM_GNU_STYLE
+ __asm__ __volatile__("bsr %1, %0\n\t"
+ "jnz 1f\n\t"
+ "mov $-1, %0\n\t"
+ "1:\n\t"
+ : "=r" (iBit)
+ : "rm" (u32)
+ : "cc");
+# else
+ _asm
+ {
+ bsr eax, [u32]
+ jnz found
+ mov eax, -1
+ found:
+ mov [iBit], eax
+ }
+# endif
+ return 31 - iBit;
+
+# elif defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32)
+ uint32_t iBit;
+ __asm__ __volatile__(
+# if defined(RT_ARCH_ARM64)
+ "clz %w[iBit], %w[uVal]\n\t"
+# else
+ "clz %[iBit], %[uVal]\n\t"
+# endif
+ : [uVal] "=r" (u32)
+ , [iBit] "=r" (iBit)
+ : "[uVal]" (u32));
+ return iBit;
+
+# elif defined(__GNUC__)
+ AssertCompile(sizeof(u32) == sizeof(unsigned int));
+ return u32 ? __builtin_clz(u32) : 32;
+
+# else
+# error "Port me"
+# endif
+}
+#endif
+
+
+/**
+ * Count the number of leading zero bits in the given 64-bit integer.
+ *
+ * The counting starts with the most significate bit.
+ *
+ * @returns Number of most significant zero bits.
+ * @returns 64 if all bits are cleared.
+ * @param u64 Integer to consider.
+ * @remarks Similar to __builtin_clzl() in gcc, except defined zero input
+ * result.
+ */
+#if RT_INLINE_ASM_EXTERNAL_TMP_ARM && !RT_INLINE_ASM_USES_INTRIN
+RT_ASM_DECL_PRAGMA_WATCOM_386(unsigned) ASMCountLeadingZerosU64(uint64_t u64) RT_NOTHROW_PROTO;
+#else
+DECLINLINE(unsigned) ASMCountLeadingZerosU64(uint64_t u64) RT_NOTHROW_DEF
+{
+# if RT_INLINE_ASM_USES_INTRIN
+ unsigned long iBit;
+# if ARCH_BITS == 64
+ if (_BitScanReverse64(&iBit, u64))
+ return 63 - (unsigned)iBit;
+# else
+ if (_BitScanReverse(&iBit, (uint32_t)(u64 >> 32)))
+ return 31 - (unsigned)iBit;
+ if (_BitScanReverse(&iBit, (uint32_t)u64))
+ return 63 - (unsigned)iBit;
+# endif
+ return 64;
+
+# elif RT_INLINE_ASM_GNU_STYLE && defined(RT_ARCH_AMD64)
+ uint64_t iBit;
+# if 0 /* 10980xe benchmark: 932 ps/call - the slower variant */
+ __asm__ __volatile__("bsrq %1, %0\n\t"
+ "cmovzq %2, %0\n\t"
+ : "=&r" (iBit)
+ : "rm" (u64)
+ , "rm" ((int64_t)-1)
+ : "cc");
+# else /* 10980xe benchmark: 262 ps/call */
+ __asm__ __volatile__("bsrq %1, %0\n\t"
+ "jnz 1f\n\t"
+ "mov $-1, %0\n\t"
+ "1:\n\t"
+ : "=&r" (iBit)
+ : "rm" (u64)
+ : "cc");
+# endif
+ return 63 - (unsigned)iBit;
+
+# elif defined(RT_ARCH_ARM64)
+ uint64_t iBit;
+ __asm__ __volatile__("clz %[iBit], %[uVal]\n\t"
+ : [uVal] "=r" (u64)
+ , [iBit] "=r" (iBit)
+ : "[uVal]" (u64));
+ return (unsigned)iBit;
+
+# elif defined(__GNUC__) && ARCH_BITS == 64
+ AssertCompile(sizeof(u64) == sizeof(unsigned long));
+ return u64 ? __builtin_clzl(u64) : 64;
+
+# else
+ unsigned iBit = ASMCountLeadingZerosU32((uint32_t)(u64 >> 32));
+ if (iBit == 32)
+ iBit = ASMCountLeadingZerosU32((uint32_t)u64) + 32;
+ return iBit;
+# endif
+}
+#endif
+
+
+/**
+ * Count the number of leading zero bits in the given 16-bit integer.
+ *
+ * The counting starts with the most significate bit.
+ *
+ * @returns Number of most significant zero bits.
+ * @returns 16 if all bits are cleared.
+ * @param u16 Integer to consider.
+ */
+#if RT_INLINE_ASM_EXTERNAL_TMP_ARM && !RT_INLINE_ASM_USES_INTRIN
+RT_ASM_DECL_PRAGMA_WATCOM_386(unsigned) ASMCountLeadingZerosU16(uint16_t u16) RT_NOTHROW_PROTO;
+#else
+DECLINLINE(unsigned) ASMCountLeadingZerosU16(uint16_t u16) RT_NOTHROW_DEF
+{
+# if RT_INLINE_ASM_GNU_STYLE && (defined(RT_ARCH_X86) || defined(RT_ARCH_AMD64)) && 0 /* slower (10980xe: 987 vs 292 ps/call) */
+ uint16_t iBit;
+ __asm__ __volatile__("bsrw %1, %0\n\t"
+ "jnz 1f\n\t"
+ "mov $-1, %0\n\t"
+ "1:\n\t"
+ : "=r" (iBit)
+ : "rm" (u16)
+ : "cc");
+ return 15 - (int16_t)iBit;
+# else
+ return ASMCountLeadingZerosU32((uint32_t)u16) - 16;
+# endif
+}
+#endif
+
+
+/**
+ * Count the number of trailing zero bits in the given 32-bit integer.
+ *
+ * The counting starts with the least significate bit, i.e. the zero bit.
+ *
+ * @returns Number of lest significant zero bits.
+ * @returns 32 if all bits are cleared.
+ * @param u32 Integer to consider.
+ * @remarks Similar to __builtin_ctz() in gcc, except defined zero input result.
+ */
+#if RT_INLINE_ASM_EXTERNAL_TMP_ARM && !RT_INLINE_ASM_USES_INTRIN
+RT_ASM_DECL_PRAGMA_WATCOM_386(unsigned) ASMCountTrailingZerosU32(uint32_t u32) RT_NOTHROW_PROTO;
+#else
+DECLINLINE(unsigned) ASMCountTrailingZerosU32(uint32_t u32) RT_NOTHROW_DEF
+{
+# if RT_INLINE_ASM_USES_INTRIN
+ unsigned long iBit;
+ if (!_BitScanForward(&iBit, u32))
+ return 32;
+ return (unsigned)iBit;
+
+# elif defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
+ uint32_t iBit;
+# if RT_INLINE_ASM_GNU_STYLE && defined(RT_ARCH_AMD64) && 0 /* significantly slower on 10980xe; 932 vs 240 ps/call */
+ __asm__ __volatile__("bsfl %1, %0\n\t"
+ "cmovzl %2, %0\n\t"
+ : "=&r" (iBit)
+ : "rm" (u32)
+ , "rm" ((int32_t)32)
+ : "cc");
+# elif RT_INLINE_ASM_GNU_STYLE
+ __asm__ __volatile__("bsfl %1, %0\n\t"
+ "jnz 1f\n\t"
+ "mov $32, %0\n\t"
+ "1:\n\t"
+ : "=r" (iBit)
+ : "rm" (u32)
+ : "cc");
+# else
+ _asm
+ {
+ bsf eax, [u32]
+ jnz found
+ mov eax, 32
+ found:
+ mov [iBit], eax
+ }
+# endif
+ return iBit;
+
+# elif defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32)
+ /* Invert the bits and use clz. */
+ uint32_t iBit;
+ __asm__ __volatile__(
+# if defined(RT_ARCH_ARM64)
+ "rbit %w[uVal], %w[uVal]\n\t"
+ "clz %w[iBit], %w[uVal]\n\t"
+# else
+ "rbit %[uVal], %[uVal]\n\t"
+ "clz %[iBit], %[uVal]\n\t"
+# endif
+ : [uVal] "=r" (u32)
+ , [iBit] "=r" (iBit)
+ : "[uVal]" (u32));
+ return iBit;
+
+# elif defined(__GNUC__)
+ AssertCompile(sizeof(u32) == sizeof(unsigned int));
+ return u32 ? __builtin_ctz(u32) : 32;
+
+# else
+# error "Port me"
+# endif
+}
+#endif
+
+
+/**
+ * Count the number of trailing zero bits in the given 64-bit integer.
+ *
+ * The counting starts with the least significate bit.
+ *
+ * @returns Number of least significant zero bits.
+ * @returns 64 if all bits are cleared.
+ * @param u64 Integer to consider.
+ * @remarks Similar to __builtin_ctzl() in gcc, except defined zero input
+ * result.
+ */
+#if RT_INLINE_ASM_EXTERNAL_TMP_ARM && !RT_INLINE_ASM_USES_INTRIN
+RT_ASM_DECL_PRAGMA_WATCOM_386(unsigned) ASMCountTrailingZerosU64(uint64_t u64) RT_NOTHROW_PROTO;
+#else
+DECLINLINE(unsigned) ASMCountTrailingZerosU64(uint64_t u64) RT_NOTHROW_DEF
+{
+# if RT_INLINE_ASM_USES_INTRIN
+ unsigned long iBit;
+# if ARCH_BITS == 64
+ if (_BitScanForward64(&iBit, u64))
+ return (unsigned)iBit;
+# else
+ if (_BitScanForward(&iBit, (uint32_t)u64))
+ return (unsigned)iBit;
+ if (_BitScanForward(&iBit, (uint32_t)(u64 >> 32)))
+ return (unsigned)iBit + 32;
+# endif
+ return 64;
+
+# elif RT_INLINE_ASM_GNU_STYLE && defined(RT_ARCH_AMD64)
+ uint64_t iBit;
+# if 0 /* 10980xe benchmark: 932 ps/call - the slower variant */
+ __asm__ __volatile__("bsfq %1, %0\n\t"
+ "cmovzq %2, %0\n\t"
+ : "=&r" (iBit)
+ : "rm" (u64)
+ , "rm" ((int64_t)64)
+ : "cc");
+# else /* 10980xe benchmark: 262 ps/call */
+ __asm__ __volatile__("bsfq %1, %0\n\t"
+ "jnz 1f\n\t"
+ "mov $64, %0\n\t"
+ "1:\n\t"
+ : "=&r" (iBit)
+ : "rm" (u64)
+ : "cc");
+# endif
+ return (unsigned)iBit;
+
+# elif defined(RT_ARCH_ARM64)
+ /* Invert the bits and use clz. */
+ uint64_t iBit;
+ __asm__ __volatile__("rbit %[uVal], %[uVal]\n\t"
+ "clz %[iBit], %[uVal]\n\t"
+ : [uVal] "=r" (u64)
+ , [iBit] "=r" (iBit)
+ : "[uVal]" (u64));
+ return (unsigned)iBit;
+
+# elif defined(__GNUC__) && ARCH_BITS == 64
+ AssertCompile(sizeof(u64) == sizeof(unsigned long));
+ return u64 ? __builtin_ctzl(u64) : 64;
+
+# else
+ unsigned iBit = ASMCountTrailingZerosU32((uint32_t)u64);
+ if (iBit == 32)
+ iBit = ASMCountTrailingZerosU32((uint32_t)(u64 >> 32)) + 32;
+ return iBit;
+# endif
+}
+#endif
+
+
+/**
+ * Count the number of trailing zero bits in the given 16-bit integer.
+ *
+ * The counting starts with the most significate bit.
+ *
+ * @returns Number of most significant zero bits.
+ * @returns 16 if all bits are cleared.
+ * @param u16 Integer to consider.
+ */
+#if RT_INLINE_ASM_EXTERNAL_TMP_ARM && !RT_INLINE_ASM_USES_INTRIN
+RT_ASM_DECL_PRAGMA_WATCOM_386(unsigned) ASMCountTrailingZerosU16(uint16_t u16) RT_NOTHROW_PROTO;
+#else
+DECLINLINE(unsigned) ASMCountTrailingZerosU16(uint16_t u16) RT_NOTHROW_DEF
+{
+# if RT_INLINE_ASM_GNU_STYLE && (defined(RT_ARCH_X86) || defined(RT_ARCH_AMD64)) && 0 /* slower (10980xe: 992 vs 349 ps/call) */
+ uint16_t iBit;
+ __asm__ __volatile__("bsfw %1, %0\n\t"
+ "jnz 1f\n\t"
+ "mov $16, %0\n\t"
+ "1:\n\t"
+ : "=r" (iBit)
+ : "rm" (u16)
+ : "cc");
+ return iBit;
+# else
+ return ASMCountTrailingZerosU32((uint32_t)u16 | UINT32_C(0x10000));
+#endif
+}
+#endif
+
+
+/**
+ * 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__
+RT_ASM_DECL_PRAGMA_WATCOM(uint32_t) ASMRotateLeftU32(uint32_t u32, unsigned cShift) RT_NOTHROW_PROTO;
+#else
+DECLINLINE(uint32_t) ASMRotateLeftU32(uint32_t u32, uint32_t cShift) RT_NOTHROW_DEF
+{
+# 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) : "cc");
+ return u32;
+
+# elif defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32)
+ __asm__ __volatile__(
+# if defined(RT_ARCH_ARM64)
+ "ror %w[uRet], %w[uVal], %w[cShift]\n\t"
+# else
+ "ror %[uRet], %[uVal], %[cShift]\n\t"
+# endif
+ : [uRet] "=r" (u32)
+ : [uVal] "[uRet]" (u32)
+ , [cShift] "r" (32 - (cShift & 31))); /** @todo there is an immediate form here */
+ 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__
+RT_ASM_DECL_PRAGMA_WATCOM(uint32_t) ASMRotateRightU32(uint32_t u32, unsigned cShift) RT_NOTHROW_PROTO;
+#else
+DECLINLINE(uint32_t) ASMRotateRightU32(uint32_t u32, uint32_t cShift) RT_NOTHROW_DEF
+{
+# 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) : "cc");
+ return u32;
+
+# elif defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32)
+ __asm__ __volatile__(
+# if defined(RT_ARCH_ARM64)
+ "ror %w[uRet], %w[uVal], %w[cShift]\n\t"
+# else
+ "ror %[uRet], %[uVal], %[cShift]\n\t"
+# endif
+ : [uRet] "=r" (u32)
+ : [uVal] "[uRet]" (u32)
+ , [cShift] "r" (cShift & 31)); /** @todo there is an immediate form here */
+ 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) RT_NOTHROW_DEF
+{
+#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) : "cc");
+ 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)
+ : "cc");
+ return u64;
+
+# elif defined(RT_ARCH_ARM64)
+ __asm__ __volatile__("ror %[uRet], %[uVal], %[cShift]\n\t"
+ : [uRet] "=r" (u64)
+ : [uVal] "[uRet]" (u64)
+ , [cShift] "r" ((uint64_t)(64 - (cShift & 63)))); /** @todo there is an immediate form here */
+ 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) RT_NOTHROW_DEF
+{
+#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) : "cc");
+ 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)
+ : "cc");
+ return u64;
+
+# elif defined(RT_ARCH_ARM64)
+ __asm__ __volatile__("ror %[uRet], %[uVal], %[cShift]\n\t"
+ : [uRet] "=r" (u64)
+ : [uVal] "[uRet]" (u64)
+ , [cShift] "r" ((uint64_t)(cShift & 63))); /** @todo there is an immediate form here */
+ return u64;
+
+#else
+ cShift &= 63;
+ return (u64 >> cShift) | (u64 << (64 - cShift));
+#endif
+}
+
+/** @} */
+
+
+/** @} */
+
+/*
+ * Include #pragma aux definitions for Watcom C/C++.
+ */
+#if defined(__WATCOMC__) && ARCH_BITS == 16 && defined(RT_ARCH_X86)
+# define IPRT_ASM_WATCOM_X86_16_WITH_PRAGMAS
+# undef IPRT_INCLUDED_asm_watcom_x86_16_h
+# include "asm-watcom-x86-16.h"
+#elif defined(__WATCOMC__) && ARCH_BITS == 32 && defined(RT_ARCH_X86)
+# define IPRT_ASM_WATCOM_X86_32_WITH_PRAGMAS
+# undef IPRT_INCLUDED_asm_watcom_x86_32_h
+# include "asm-watcom-x86-32.h"
+#endif
+
+#endif /* !IPRT_INCLUDED_asm_h */
+
diff --git a/include/iprt/asmdefs.mac b/include/iprt/asmdefs.mac
new file mode 100644
index 00000000..d798a0c0
--- /dev/null
+++ b/include/iprt/asmdefs.mac
@@ -0,0 +1,1379 @@
+;; @file
+; IPRT - Global YASM/NASM macros
+;
+
+;
+; Copyright (C) 2006-2022 Oracle and/or its affiliates.
+;
+; This file is part of VirtualBox base platform packages, as
+; available from https://www.virtualbox.org.
+;
+; This program is free software; you can redistribute it and/or
+; modify it under the terms of the GNU General Public License
+; as published by the Free Software Foundation, in version 3 of the
+; License.
+;
+; This program is distributed in the hope that it will be useful, but
+; WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with this program; if not, see <https://www.gnu.org/licenses>.
+;
+; The contents of this file may alternatively be used under the terms
+; of the Common Development and Distribution License Version 1.0
+; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+; in the VirtualBox 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.
+;
+; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+;
+
+; Special hack for bs3kit.
+%ifdef RT_ASMDEFS_INC_FIRST_FILE
+ %include "asmdefs-first.mac"
+%endif
+
+%ifndef ___iprt_asmdefs_mac
+%define ___iprt_asmdefs_mac
+
+
+;; @defgroup grp_rt_cdefs_size Size Constants
+; (Of course, these are binary computer terms, not SI.)
+; @{
+;; 1 K (Kilo) (1 024).
+%define _1K 000000400h
+;; 4 K (Kilo) (4 096).
+%define _4K 000001000h
+;; 8 K (Kilo) (8 192).
+%define _8K 000002000h
+;; 16 K (Kilo) (16 384).
+%define _16K 000004000h
+;; 32 K (Kilo) (32 768).
+%define _32K 000008000h
+;; 64 K (Kilo) (65 536).
+%define _64K 000010000h
+;; 128 K (Kilo) (131 072).
+%define _128K 000020000h
+;; 256 K (Kilo) (262 144).
+%define _256K 000040000h
+;; 512 K (Kilo) (524 288).
+%define _512K 000080000h
+;; 1 M (Mega) (1 048 576).
+%define _1M 000100000h
+;; 2 M (Mega) (2 097 152).
+%define _2M 000200000h
+;; 4 M (Mega) (4 194 304).
+%define _4M 000400000h
+;; 1 G (Giga) (1 073 741 824).
+%define _1G 040000000h
+;; 2 G (Giga) (2 147 483 648).
+%define _2G 00000000080000000h
+;; 4 G (Giga) (4 294 967 296).
+%define _4G 00000000100000000h
+;; 1 T (Tera) (1 099 511 627 776).
+%define _1T 00000010000000000h
+;; 1 P (Peta) (1 125 899 906 842 624).
+%define _1P 00004000000000000h
+;; 1 E (Exa) (1 152 921 504 606 846 976).
+%define _1E 01000000000000000h
+;; 2 E (Exa) (2 305 843 009 213 693 952).
+%define _2E 02000000000000000h
+;; @}
+
+
+;;
+; Define RT_STRICT for debug builds like iprt/cdefs.h does.
+%ifndef RT_STRICT
+ %ifdef DEBUG
+ %define RT_STRICT
+ %endif
+%endif
+%ifdef RT_NO_STRICT
+ %undef RT_STRICT
+%endif
+
+;;
+; Make the mask for the given bit.
+%define RT_BIT(bit) (1 << bit)
+
+;;
+; Make the mask for the given bit.
+%define RT_BIT_32(bit) (1 << bit)
+;;
+; Make the mask for the given bit.
+%define RT_BIT_64(bit) (1 << bit)
+
+;;
+; Makes a 32-bit unsigned (not type safe, but whatever) out of four byte values.
+%define RT_MAKE_U32_FROM_U8(b0, b1, b2, b3) ( (b3 << 24) | (b2 << 16) | (b1 << 8) | b0 )
+
+;; Preprocessor concatenation macro.
+%define RT_CONCAT(a_1,a_2) a_1 %+ a_2
+
+;; Preprocessor concatenation macro, three arguments.
+%define RT_CONCAT3(a_1,a_2,a_3) a_1 %+ a_2 %+ a_3
+
+;; Preprocessor concatenation macro, four arguments.
+%define RT_CONCAT4(a_1,a_2,a_3,a_4) a_1 %+ a_2 %+ a_3 %+ a_4
+
+;;
+; Trick for using RT_CONCAT and the like on %define names.
+; @param 1 The name (expression.
+; @param 2 The value.
+%macro RT_DEFINE_EX 2
+ %error 1=%1 2=%2
+ %define %1 %2
+%endmacro
+
+;;
+; Trick for using RT_CONCAT and the like on %xdefine names.
+; @param 1 The name (expression.
+; @param 2 The value.
+%macro RT_XDEFINE_EX 2
+ %xdefine %1 %2
+%endmacro
+
+;;
+; Trick for using RT_CONCAT and the like on %undef names.
+; @param 1 The name (expression.
+%macro RT_UNDEF_EX 1
+ %error 1=%1
+ %undef %1
+%endmacro
+
+;;
+; Empty define
+%define RT_NOTHING
+
+;; Define ASM_FORMAT_PE64 if applicable.
+%ifdef ASM_FORMAT_PE
+ %ifdef RT_ARCH_AMD64
+ %define ASM_FORMAT_PE64 1
+ %endif
+%endif
+
+;;
+; SEH64 macros.
+%ifdef RT_ASM_WITH_SEH64
+ %ifndef ASM_FORMAT_PE64
+ %undef RT_ASM_WITH_SEH64
+ %endif
+%endif
+
+%ifdef RT_ASM_WITH_SEH64_ALT
+ %ifdef ASM_FORMAT_PE64
+ ;; @name Register numbers. Used with RT_CONCAT to convert macro inputs to numbers.
+ ;; @{
+ %define SEH64_PE_GREG_rax 0
+ %define SEH64_PE_GREG_xAX 0
+ %define SEH64_PE_GREG_rcx 1
+ %define SEH64_PE_GREG_xCX 1
+ %define SEH64_PE_GREG_rdx 2
+ %define SEH64_PE_GREG_xDX 2
+ %define SEH64_PE_GREG_rbx 3
+ %define SEH64_PE_GREG_xBX 3
+ %define SEH64_PE_GREG_rsp 4
+ %define SEH64_PE_GREG_xSP 4
+ %define SEH64_PE_GREG_rbp 5
+ %define SEH64_PE_GREG_xBP 5
+ %define SEH64_PE_GREG_rsi 6
+ %define SEH64_PE_GREG_xSI 6
+ %define SEH64_PE_GREG_rdi 7
+ %define SEH64_PE_GREG_xDI 7
+ %define SEH64_PE_GREG_r8 8
+ %define SEH64_PE_GREG_r9 9
+ %define SEH64_PE_GREG_r10 10
+ %define SEH64_PE_GREG_r11 11
+ %define SEH64_PE_GREG_r12 12
+ %define SEH64_PE_GREG_r13 13
+ %define SEH64_PE_GREG_r14 14
+ %define SEH64_PE_GREG_r15 15
+ ;; @}
+
+ ;; @name PE unwind operations.
+ ;; @{
+ %define SEH64_PE_PUSH_NONVOL 0
+ %define SEH64_PE_ALLOC_LARGE 1
+ %define SEH64_PE_ALLOC_SMALL 2
+ %define SEH64_PE_SET_FPREG 3
+ %define SEH64_PE_SAVE_NONVOL 4
+ %define SEH64_PE_SAVE_NONVOL_FAR 5
+ %define SEH64_PE_SAVE_XMM128 8
+ %define SEH64_PE_SAVE_XMM128_FAR 9
+ ;; @}
+
+ ;;
+ ; Starts the unwind info for the manual SEH64 info generation.
+ ; @param 1 Function name.
+ %macro SEH64_ALT_START_UNWIND_INFO 1
+ %assign seh64_idxOps 0
+ %assign seh64_FrameReg SEH64_PE_GREG_rsp
+ %assign seh64_offFrame 0
+ %define asm_seh64_proc %1
+ %undef seh64_slot_bytes
+ %endmacro
+
+ ;; We keep the unwind bytes in the seh64_slot_bytes (x)define, in reverse order as per spec.
+ %macro SEH64_APPEND_SLOT_PAIR 2
+ %ifdef seh64_slot_bytes
+ %xdefine seh64_slot_bytes %1, %2, seh64_slot_bytes
+ %else
+ %xdefine seh64_slot_bytes %1, %2
+ %endif
+ %endmacro
+
+ ;; For multi-slot unwind info.
+ %macro SEH64_APPEND_SLOT_BYTES 2+
+ %rep %0
+ %rotate -1
+ %ifdef seh64_slot_bytes
+ %xdefine seh64_slot_bytes %1, seh64_slot_bytes
+ %else
+ %xdefine seh64_slot_bytes %1
+ %endif
+ %endrep
+ %endmacro
+
+ %else
+ %undef RT_ASM_WITH_SEH64_ALT
+ %endif
+%endif
+
+;;
+; Records a xBP push.
+%macro SEH64_PUSH_xBP 0
+ %ifdef RT_ASM_WITH_SEH64
+ [pushreg rbp]
+
+ %elifdef RT_ASM_WITH_SEH64_ALT
+RT_CONCAT(.seh64_op_label_,seh64_idxOps):
+ %ifdef ASM_FORMAT_PE64
+ SEH64_APPEND_SLOT_PAIR RT_CONCAT(.seh64_op_label_,seh64_idxOps) - .start_of_prologue, \
+ SEH64_PE_PUSH_NONVOL | (SEH64_PE_GREG_rbp << 4)
+ %endif
+ %assign seh64_idxOps seh64_idxOps + 1
+ %endif
+%endmacro
+
+;;
+; Records a general register push.
+; @param 1 Register name.
+%macro SEH64_PUSH_GREG 1
+ %ifdef RT_ASM_WITH_SEH64
+ [pushreg %1]
+
+ %elifdef RT_ASM_WITH_SEH64_ALT
+RT_CONCAT(.seh64_op_label_,seh64_idxOps):
+ %ifdef ASM_FORMAT_PE64
+ SEH64_APPEND_SLOT_PAIR RT_CONCAT(.seh64_op_label_,seh64_idxOps) - .start_of_prologue, \
+ SEH64_PE_PUSH_NONVOL | (RT_CONCAT(SEH64_PE_GREG_,%1) << 4)
+ %endif
+ %assign seh64_idxOps seh64_idxOps + 1
+ %endif
+%endmacro
+
+;;
+; Sets xBP as frame pointer that's pointing to a stack position %1 relative to xBP.
+%macro SEH64_SET_FRAME_xBP 1
+ %ifdef RT_ASM_WITH_SEH64
+ [setframe rbp, %1]
+
+ %elifdef RT_ASM_WITH_SEH64_ALT
+RT_CONCAT(.seh64_op_label_,seh64_idxOps):
+ %ifdef ASM_FORMAT_PE64
+ SEH64_APPEND_SLOT_PAIR RT_CONCAT(.seh64_op_label_,seh64_idxOps) - .start_of_prologue, \
+ SEH64_PE_SET_FPREG | 0 ; vs2019 seems to put the offset in the info field
+ %assign seh64_FrameReg SEH64_PE_GREG_rbp
+ %assign seh64_offFrame %1
+ %endif
+ %assign seh64_idxOps seh64_idxOps + 1
+ %endif
+%endmacro
+
+;;
+; Records an ADD xSP, %1.
+%macro SEH64_ALLOCATE_STACK 1
+ %ifdef RT_ASM_WITH_SEH64
+ [allocstack %1]
+
+ %elifdef RT_ASM_WITH_SEH64_ALT
+RT_CONCAT(.seh64_op_label_,seh64_idxOps):
+ %ifdef ASM_FORMAT_PE64
+ %if (%1) & 7
+ %error "SEH64_ALLOCATE_STACK must be a multiple of 8"
+ %endif
+ %if (%1) < 8
+ %error "SEH64_ALLOCATE_STACK must have an argument that's 8 or higher."
+ %elif (%1) <= 128
+ SEH64_APPEND_SLOT_PAIR RT_CONCAT(.seh64_op_label_,seh64_idxOps) - .start_of_prologue, \
+ SEH64_PE_ALLOC_SMALL | ((((%1) / 8) - 1) << 4)
+ %elif (%1) < 512
+ SEH64_APPEND_SLOT_BYTES RT_CONCAT(.seh64_op_label_,seh64_idxOps) - .start_of_prologue, \
+ SEH64_PE_ALLOC_LARGE | 0, \
+ ((%1) / 8) & 0xff, ((%1) / 8) >> 8
+ %else
+ SEH64_APPEND_SLOT_BYTES RT_CONCAT(.seh64_op_label_,seh64_idxOps) - .start_of_prologue, \
+ SEH64_PE_ALLOC_LARGE | 1, \
+ (%1) & 0xff, ((%1) >> 8) & 0xff, ((%1) >> 16) & 0xff, ((%1) >> 24) & 0xff
+ %endif
+ %endif
+ %assign seh64_idxOps seh64_idxOps + 1
+ %endif
+%endmacro
+
+%macro SEH64_INFO_HELPER 1
+%if defined(%1)
+ dw %1
+%endif
+%endmacro
+
+;;
+; Ends the prologue.
+%macro SEH64_END_PROLOGUE 0
+.end_of_prologue:
+ %ifdef RT_ASM_WITH_SEH64
+ [endprolog]
+
+ %elifdef RT_ASM_WITH_SEH64_ALT
+ %ifdef ASM_FORMAT_PE
+ ; Emit the unwind info now.
+ %ifndef ASM_DEFINED_XDATA_SECTION
+ %define ASM_DEFINED_XDATA_SECTION
+ section .xdata rdata align=4
+ %else
+ section .xdata
+ align 4, db 0
+ %endif
+.unwind_info:
+ db 1 ; version 1 (3 bit), no flags (5 bits)
+ db .end_of_prologue - .start_of_prologue
+
+ db (.unwind_info_array_end - .unwind_info_array) / 2
+ db seh64_FrameReg | (seh64_offFrame & 0xf0) ; framereg and offset/16.
+.unwind_info_array:
+ %ifdef seh64_slot_bytes
+ db seh64_slot_bytes
+ %undef seh64_slot_bytes
+ %endif
+.unwind_info_array_end:
+
+ ; Reset the segment
+ BEGINCODE
+ %endif
+ %endif
+%endmacro
+
+
+;;
+; Align code, pad with INT3.
+%define ALIGNCODE(alignment) align alignment, db 0cch
+
+;;
+; Align data, pad with ZEROs.
+%define ALIGNDATA(alignment) align alignment, db 0
+
+;;
+; Align BSS, pad with ZEROs.
+%define ALIGNBSS(alignment) align alignment, resb 1
+
+;;
+; NAME_OVERLOAD can be defined by a .asm module to modify all the
+; names created using the name macros in this files.
+; This is handy when you've got some kind of template code.
+%ifndef NAME_OVERLOAD
+ %ifdef RT_MANGLER_PREFIX
+ %define NAME_OVERLOAD(name) RT_MANGLER_PREFIX %+ name
+ %else
+ %define NAME_OVERLOAD(name) name
+ %endif
+%endif
+
+;;
+; Mangles the given name so it can be referenced using DECLASM() in the
+; C/C++ world.
+%ifndef ASM_FORMAT_BIN
+ %ifdef RT_ARCH_X86
+ %ifdef RT_OS_OS2
+ %define NAME(name) _ %+ NAME_OVERLOAD(name)
+ %endif
+ %ifdef RT_OS_WINDOWS
+ %define NAME(name) _ %+ NAME_OVERLOAD(name)
+ %endif
+ %endif
+ %ifdef RT_OS_DARWIN
+ %define NAME(name) _ %+ NAME_OVERLOAD(name)
+ %endif
+%endif
+%ifndef NAME
+ %define NAME(name) NAME_OVERLOAD(name)
+%endif
+
+;;
+; Mangles the given C name so it will _import_ the right symbol.
+%ifdef ASM_FORMAT_PE
+ %define IMPNAME(name) __imp_ %+ NAME(name)
+%else
+ %define IMPNAME(name) NAME(name)
+%endif
+
+;;
+; Gets the pointer to an imported object.
+%ifdef ASM_FORMAT_PE
+ %ifdef RT_ARCH_AMD64
+ %define IMP(name) qword [IMPNAME(name) wrt rip]
+ %else
+ %define IMP(name) dword [IMPNAME(name)]
+ %endif
+%else
+ %define IMP(name) IMPNAME(name)
+%endif
+
+;;
+; Gets the pointer to an imported object.
+%ifdef ASM_FORMAT_PE
+ %ifdef RT_ARCH_AMD64
+ %define IMP_SEG(SegOverride, name) qword [SegOverride:IMPNAME(name) wrt rip]
+ %else
+ %define IMP_SEG(SegOverride, name) dword [SegOverride:IMPNAME(name)]
+ %endif
+%else
+ %define IMP_SEG(SegOverride, name) IMPNAME(name)
+%endif
+
+;;
+; Declares an imported object for use with IMP2.
+; @note May change the current section!
+%macro EXTERN_IMP2 1
+ extern IMPNAME(%1)
+ BEGINDATA
+ %ifdef ASM_FORMAT_MACHO
+ g_Imp2_ %+ %1: RTCCPTR_DEF IMPNAME(%1)
+ %endif
+%endmacro
+
+;;
+; Gets the pointer to an imported object, version 2.
+%ifdef ASM_FORMAT_PE
+ %ifdef RT_ARCH_AMD64
+ %define IMP2(name) qword [IMPNAME(name) wrt rip]
+ %else
+ %define IMP2(name) dword [IMPNAME(name)]
+ %endif
+%elifdef ASM_FORMAT_ELF
+ %ifdef PIC
+ %ifdef RT_ARCH_AMD64
+ %define IMP2(name) qword [rel IMPNAME(name) wrt ..got]
+ %else
+ %define IMP2(name) IMPNAME(name) wrt ..plt
+ %endif
+ %endif
+%elifdef ASM_FORMAT_MACHO
+ %define IMP2(name) RTCCPTR_PRE [g_Imp2_ %+ name xWrtRIP]
+%endif
+%ifndef IMP2
+ %define IMP2(name) IMPNAME(name)
+%endif
+
+
+;;
+; Define a label as given, with a '$' prepended to permit using instruction
+; names like fdiv as labels.
+%macro SAFE_LABEL 1
+$%1:
+%endmacro
+
+;;
+; Global marker which is DECLASM() compatible.
+%macro GLOBALNAME 1
+%ifndef ASM_FORMAT_BIN
+global NAME(%1)
+%endif
+SAFE_LABEL NAME(%1)
+%endmacro
+
+;;
+; Global exported marker which is DECLASM() compatible.
+%macro EXPORTEDNAME 1
+ %ifdef ASM_FORMAT_PE
+ export %1=NAME(%1)
+ %endif
+ %ifdef __NASM__
+ %ifdef ASM_FORMAT_OMF
+ export NAME(%1) NAME(%1)
+ %endif
+%endif
+GLOBALNAME %1
+%endmacro
+
+;;
+; Same as GLOBALNAME_EX, but without the name mangling.
+;
+; @param %1 The symbol name - subjected to NAME().
+; @param %2 ELF and PE attributes: 'function', 'object', 'data', 'notype'.
+; PE ignores all but 'function' (yasm only). Other formats ignores
+; this completely.
+; @param %3 Symbol visibility: 'hidden', 'protected', 'internal', and
+; RT_NOTHING (for 'default' visibility).
+; These are ELF attributes, but 'hidden' is translated to
+; 'private_extern' for the Macho-O format.
+; Ignored by other formats.
+;
+%macro GLOBALNAME_RAW 3
+%ifdef ASM_FORMAT_ELF
+global %1:%2 %3
+
+%elifdef ASM_FORMAT_PE
+ %ifidn %2,function
+ %ifdef __YASM__ ; nasm does not support any attributes, it errors out. So, nasm is no good with control flow guard atm.
+global %1:function
+ %else
+global %1
+ %endif
+ %else
+global %1
+ %endif
+
+%elifdef ASM_FORMAT_MACHO
+ %ifidn %3,hidden
+global %1:private_extern
+ %else
+global %1
+ %endif
+
+%elifndef ASM_FORMAT_BIN
+global %1
+
+%endif
+
+%1:
+%endmacro
+
+;;
+; Global marker which is DECLASM() compatible.
+;
+; @param %1 The symbol name - subjected to NAME().
+; @param %2 ELF and PE attributes: 'function', 'object', 'data', 'notype'.
+; PE ignores all but 'function' (yasm only). Other formats ignores
+; this completely.
+; @param %3 Symbol visibility: 'hidden', 'protected', 'internal', and
+; RT_NOTHING (for 'default' visibility).
+; These are ELF attributes, but 'hidden' is translated to
+; 'private_extern' for the Macho-O format.
+; Ignored by other formats.
+;
+%macro GLOBALNAME_EX 3
+GLOBALNAME_RAW NAME(%1), %2, %3
+%endmacro
+
+
+;;
+; Global exported marker, raw version w/o automatic name mangling.
+;
+; @param %1 The internal symbol name.
+; @param %2 The external symbol name.
+; @param %3 ELF and PE attributes: 'function', 'object', 'data', 'notype'.
+; PE ignores all but 'function' (yasm only). Other formats ignores
+; this completely.
+;
+%macro EXPORTEDNAME_RAW 3
+ %ifdef ASM_FORMAT_PE
+ export %2=%1
+ %endif
+ %ifdef __NASM__
+ %ifdef ASM_FORMAT_OMF
+ export %1 %2
+ %endif
+%endif
+GLOBALNAME_RAW %1, %3, RT_NOTHING
+%endmacro
+
+;;
+; Global exported marker which is DECLASM() compatible.
+;
+; @param %1 The symbol name - subjected to NAME().
+; @param %2 ELF and PE attributes: 'function', 'object', 'data', 'notype'.
+; PE ignores all but 'function' (yasm only). Other formats ignores
+; this completely.
+;
+%macro EXPORTEDNAME_EX 2
+EXPORTEDNAME_RAW NAME(%1), %1, %2
+%endmacro
+
+
+;;
+; Begins a procedure, raw version w/o automatic name mangling.
+%macro BEGINPROC_RAW 1
+ %ifdef RT_ASM_WITH_SEH64_ALT
+ SEH64_ALT_START_UNWIND_INFO %1
+ %endif
+ %ifdef RT_ASM_WITH_SEH64
+global %1:function
+proc_frame %1
+ %else
+GLOBALNAME_RAW %1, function, hidden
+ %endif
+.start_of_prologue:
+%endmacro
+
+;;
+; Begins a C callable (DECLASM) procedure.
+%macro BEGINPROC 1
+BEGINPROC_RAW NAME(%1)
+%endmacro
+
+
+;;
+; Begins a exported procedure, raw version w/o automatic name mangling.
+; @param 1 Internal name.
+; @param 2 Exported name.
+%macro BEGINPROC_EXPORTED_RAW 2
+ %ifdef RT_ASM_WITH_SEH64_ALT
+ SEH64_ALT_START_UNWIND_INFO %1
+ %endif
+ %ifdef RT_ASM_WITH_SEH64
+ %ifdef ASM_FORMAT_PE
+export %2=%1
+ %endif
+global %1:function
+proc_frame %1
+ %else
+EXPORTEDNAME_RAW %1, %2, function
+ %endif
+.start_of_prologue:
+%endmacro
+
+;;
+; Begins a C callable (DECLASM) exported procedure.
+%macro BEGINPROC_EXPORTED 1
+BEGINPROC_EXPORTED_RAW NAME(%1), %1
+%endmacro
+
+
+;;
+; Ends a procedure, raw version w/o automatic name mangling.
+%macro ENDPROC_RAW 1
+ %ifdef RT_ASM_WITH_SEH64
+endproc_frame
+ %endif
+GLOBALNAME_RAW %1 %+ _EndProc, , hidden ; no function here, this isn't a valid code flow target.
+%ifdef ASM_FORMAT_ELF
+ %ifndef __NASM__ ; nasm does this in the global directive.
+size %1 %1 %+ _EndProc - %1
+size %1 %+ _EndProc 4 ; make it non-zero to shut up warnigns from Linux's objtool.
+ %endif
+%endif
+ db 0xCC, 0xCC, 0xCC, 0xCC
+
+ %ifdef RT_ASM_WITH_SEH64_ALT
+ %ifdef ASM_FORMAT_PE
+ ; Emit the RUNTIME_FUNCTION entry. The linker is picky here, no label.
+ %ifndef ASM_DEFINED_PDATA_SECTION
+ %define ASM_DEFINED_PDATA_SECTION
+ section .pdata rdata align=4
+ %else
+ section .pdata
+ %endif
+ dd %1 wrt ..imagebase
+ dd %1 %+ _EndProc wrt ..imagebase
+ dd %1 %+ .unwind_info wrt ..imagebase
+
+ ; Restore code section.
+ BEGINCODE
+ %endif
+ %endif
+%endmacro
+
+;;
+; Ends a C callable procedure.
+%macro ENDPROC 1
+ENDPROC_RAW NAME(%1)
+%endmacro
+
+
+;
+; Do OMF and Mach-O/Yasm segment definitions
+;
+; Both format requires this to get the segment order right, in the Mach-O/Yasm case
+; it's only to make sure the .bss section ends up last (it's not declared here).
+;
+%ifdef ASM_FORMAT_OMF
+ %ifndef RT_NOINC_SEGMENTS
+
+ ; 16-bit segments first (OMF / OS/2 specific).
+ %ifdef RT_INCL_16BIT_SEGMENTS
+ segment DATA16 public CLASS=FAR_DATA align=16 use16
+ segment DATA16_INIT public CLASS=FAR_DATA align=16 use16
+ group DGROUP16 DATA16 DATA16_INIT
+
+ ;;
+ ; Begins 16-bit data
+ %macro BEGINDATA16 0
+ segment DATA16
+ %endmacro
+
+ ;;
+ ; Begins 16-bit init data
+ %macro BEGINDATA16INIT 0
+ segment DATA16_INIT
+ %endmacro
+
+ segment CODE16 public CLASS=FAR_CODE align=16 use16
+ segment CODE16_INIT public CLASS=FAR_CODE align=16 use16
+ group CGROUP16 CODE16 CODE16_INIT
+
+ ;;
+ ; Begins 16-bit code
+ %macro BEGINCODE16 0
+ segment CODE16
+ %endmacro
+
+ ;;
+ ; Begins 16-bit init code
+ %macro BEGINCODE16INIT 0
+ segment CODE16_INIT
+ %endmacro
+
+ %endif
+
+ ; 32-bit segments.
+ segment TEXT32 public CLASS=CODE align=16 use32 flat
+ segment DATA32 public CLASS=DATA align=16 use32 flat
+ segment BSS32 public CLASS=BSS align=16 use32 flat
+
+ ; Make the TEXT32 segment default.
+ segment TEXT32
+ %endif ; RT_NOINC_SEGMENTS
+%endif
+
+%ifdef ASM_FORMAT_MACHO
+ %ifdef __YASM__
+ section .text
+ section .data
+ %endif
+%endif
+
+
+;;
+; Begins code
+%ifdef ASM_FORMAT_OMF
+ %macro BEGINCODE 0
+ segment TEXT32
+ %endmacro
+%else
+%macro BEGINCODE 0
+ section .text
+%endmacro
+%endif
+
+;;
+; Begins constant (read-only) data
+;
+; @remarks This is mapped to the CODE section/segment when there isn't
+; any dedicated const section/segment. (There is code that
+; assumes this, so don't try change it.)
+%ifdef ASM_FORMAT_OMF
+ %macro BEGINCONST 0
+ segment TEXT32
+ %endmacro
+%else
+ %macro BEGINCONST 0
+ %ifdef ASM_FORMAT_MACHO ;; @todo check the other guys too.
+ section .rodata
+ %else
+ section .text
+ %endif
+ %endmacro
+%endif
+
+;;
+; Begins initialized data
+%ifdef ASM_FORMAT_OMF
+ %macro BEGINDATA 0
+ segment DATA32
+ %endmacro
+%else
+%macro BEGINDATA 0
+ section .data
+%endmacro
+%endif
+
+;;
+; Begins uninitialized data
+%ifdef ASM_FORMAT_OMF
+ %macro BEGINBSS 0
+ segment BSS32
+ %endmacro
+%else
+%macro BEGINBSS 0
+ section .bss
+%endmacro
+%endif
+
+
+
+;; @def ARCH_BITS
+; Defines the bit count of the current context.
+%ifndef ARCH_BITS
+ %ifdef RT_ARCH_AMD64
+ %define ARCH_BITS 64
+ %else
+ %define ARCH_BITS 32
+ %endif
+%endif
+
+;; @def HC_ARCH_BITS
+; Defines the host architechture bit count.
+%ifndef HC_ARCH_BITS
+ %ifndef IN_RC
+ %define HC_ARCH_BITS ARCH_BITS
+ %else
+ %define HC_ARCH_BITS 32
+ %endif
+%endif
+
+;; @def R3_ARCH_BITS
+; Defines the host ring-3 architechture bit count.
+%ifndef R3_ARCH_BITS
+ %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 architechture bit count.
+%ifndef R0_ARCH_BITS
+ %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 architechture bit count.
+%ifndef GC_ARCH_BITS
+ %ifdef IN_RC
+ %define GC_ARCH_BITS ARCH_BITS
+ %else
+ %define GC_ARCH_BITS 32
+ %endif
+%endif
+
+
+
+;; @def RTHCPTR_DEF
+; The pesudo-instruction used to declare an initialized pointer variable in the host context.
+%if HC_ARCH_BITS == 64
+ %define RTHCPTR_DEF dq
+%else
+ %define RTHCPTR_DEF dd
+%endif
+
+;; @def RTHCPTR_RES
+; The pesudo-instruction used to declare (=reserve space for) an uninitialized pointer
+; variable of the host context.
+%if HC_ARCH_BITS == 64
+ %define RTHCPTR_RES resq
+%else
+ %define RTHCPTR_RES resd
+%endif
+
+;; @def RTHCPTR_PRE
+; The memory operand prefix used for a pointer in the host context.
+%if HC_ARCH_BITS == 64
+ %define RTHCPTR_PRE qword
+%else
+ %define RTHCPTR_PRE dword
+%endif
+
+;; @def RTHCPTR_CB
+; The size in bytes of a pointer in the host context.
+%if HC_ARCH_BITS == 64
+ %define RTHCPTR_CB 8
+%else
+ %define RTHCPTR_CB 4
+%endif
+
+
+
+;; @def RTR0PTR_DEF
+; The pesudo-instruction used to declare an initialized pointer variable in the ring-0 host context.
+%if R0_ARCH_BITS == 64
+ %define RTR0PTR_DEF dq
+%else
+ %define RTR0PTR_DEF dd
+%endif
+
+;; @def RTR0PTR_RES
+; The pesudo-instruction used to declare (=reserve space for) an uninitialized pointer
+; variable of the ring-0 host context.
+%if R0_ARCH_BITS == 64
+ %define RTR0PTR_RES resq
+%else
+ %define RTR0PTR_RES resd
+%endif
+
+;; @def RTR0PTR_PRE
+; The memory operand prefix used for a pointer in the ring-0 host context.
+%if R0_ARCH_BITS == 64
+ %define RTR0PTR_PRE qword
+%else
+ %define RTR0PTR_PRE dword
+%endif
+
+;; @def RTR0PTR_CB
+; The size in bytes of a pointer in the ring-0 host context.
+%if R0_ARCH_BITS == 64
+ %define RTR0PTR_CB 8
+%else
+ %define RTR0PTR_CB 4
+%endif
+
+
+
+;; @def RTR3PTR_DEF
+; The pesudo-instruction used to declare an initialized pointer variable in the ring-3 host context.
+%if R3_ARCH_BITS == 64
+ %define RTR3PTR_DEF dq
+%else
+ %define RTR3PTR_DEF dd
+%endif
+
+;; @def RTR3PTR_RES
+; The pesudo-instruction used to declare (=reserve space for) an uninitialized pointer
+; variable of the ring-3 host context.
+%if R3_ARCH_BITS == 64
+ %define RTR3PTR_RES resq
+%else
+ %define RTR3PTR_RES resd
+%endif
+
+;; @def RTR3PTR_PRE
+; The memory operand prefix used for a pointer in the ring-3 host context.
+%if R3_ARCH_BITS == 64
+ %define RTR3PTR_PRE qword
+%else
+ %define RTR3PTR_PRE dword
+%endif
+
+;; @def RTR3PTR_CB
+; The size in bytes of a pointer in the ring-3 host context.
+%if R3_ARCH_BITS == 64
+ %define RTR3PTR_CB 8
+%else
+ %define RTR3PTR_CB 4
+%endif
+
+
+
+;; @def RTGCPTR_DEF
+; The pesudo-instruction used to declare an initialized pointer variable in the guest context.
+%if GC_ARCH_BITS == 64
+ %define RTGCPTR_DEF dq
+%else
+ %define RTGCPTR_DEF dd
+%endif
+
+;; @def RTGCPTR_RES
+; The pesudo-instruction used to declare (=reserve space for) an uninitialized pointer
+; variable of the guest context.
+%if GC_ARCH_BITS == 64
+ %define RTGCPTR_RES resq
+%else
+ %define RTGCPTR_RES resd
+%endif
+
+%define RTGCPTR32_RES resd
+%define RTGCPTR64_RES resq
+
+;; @def RTGCPTR_PRE
+; The memory operand prefix used for a pointer in the guest context.
+%if GC_ARCH_BITS == 64
+ %define RTGCPTR_PRE qword
+%else
+ %define RTGCPTR_PRE dword
+%endif
+
+;; @def RTGCPTR_CB
+; The size in bytes of a pointer in the guest context.
+%if GC_ARCH_BITS == 64
+ %define RTGCPTR_CB 8
+%else
+ %define RTGCPTR_CB 4
+%endif
+
+
+;; @def RTRCPTR_DEF
+; The pesudo-instruction used to declare an initialized pointer variable in the raw mode context.
+%define RTRCPTR_DEF dd
+
+;; @def RTRCPTR_RES
+; The pesudo-instruction used to declare (=reserve space for) an uninitialized pointer
+; variable of the raw mode context.
+%define RTRCPTR_RES resd
+
+;; @def RTRCPTR_PRE
+; The memory operand prefix used for a pointer in the raw mode context.
+%define RTRCPTR_PRE dword
+
+;; @def RTRCPTR_CB
+; The size in bytes of a pointer in the raw mode context.
+%define RTRCPTR_CB 4
+
+
+;; @def RT_CCPTR_DEF
+; The pesudo-instruction used to declare an initialized pointer variable in the current context.
+
+;; @def RT_CCPTR_RES
+; The pesudo-instruction used to declare (=reserve space for) an uninitialized pointer
+; variable of the current context.
+
+;; @def RT_CCPTR_PRE
+; The memory operand prefix used for a pointer in the current context.
+
+;; @def RT_CCPTR_CB
+; The size in bytes of a pointer in the current context.
+
+%ifdef IN_RC
+ %define RTCCPTR_DEF RTRCPTR_DEF
+ %define RTCCPTR_RES RTRCPTR_RES
+ %define RTCCPTR_PRE RTRCPTR_PRE
+ %define RTCCPTR_CB RTRCPTR_CB
+%else
+ %ifdef IN_RING0
+ %define RTCCPTR_DEF RTR0PTR_DEF
+ %define RTCCPTR_RES RTR0PTR_RES
+ %define RTCCPTR_PRE RTR0PTR_PRE
+ %define RTCCPTR_CB RTR0PTR_CB
+ %else
+ %define RTCCPTR_DEF RTR3PTR_DEF
+ %define RTCCPTR_RES RTR3PTR_RES
+ %define RTCCPTR_PRE RTR3PTR_PRE
+ %define RTCCPTR_CB RTR3PTR_CB
+ %endif
+%endif
+
+
+
+;; @def RTHCPHYS_DEF
+; The pesudo-instruction used to declare an initialized host physical address.
+%define RTHCPHYS_DEF dq
+
+;; @def RTHCPTR_RES
+; The pesudo-instruction used to declare (=reserve space for) an uninitialized
+; host physical address variable
+%define RTHCPHYS_RES resq
+
+;; @def RTHCPTR_PRE
+; The memory operand prefix used for a host physical address.
+%define RTHCPHYS_PRE qword
+
+;; @def RTHCPHYS_CB
+; The size in bytes of a host physical address.
+%define RTHCPHYS_CB 8
+
+
+
+;; @def RTGCPHYS_DEF
+; The pesudo-instruction used to declare an initialized guest physical address.
+%define RTGCPHYS_DEF dq
+
+;; @def RTGCPHYS_RES
+; The pesudo-instruction used to declare (=reserve space for) an uninitialized
+; guest physical address variable
+%define RTGCPHYS_RES resq
+
+;; @def RTGCPTR_PRE
+; The memory operand prefix used for a guest physical address.
+%define RTGCPHYS_PRE qword
+
+;; @def RTGCPHYS_CB
+; The size in bytes of a guest physical address.
+%define RTGCPHYS_CB 8
+
+
+
+;;
+; The size of the long double C/C++ type.
+; On 32-bit Darwin this is 16 bytes, on L4, Linux, OS/2 and Windows
+; it's 12 bytes.
+; @todo figure out what 64-bit Windows does (I don't recall right now).
+%ifdef RT_ARCH_X86
+ %ifdef RT_OS_DARWIN
+ %define RTLRD_CB 16
+ %else
+ %define RTLRD_CB 12
+ %endif
+%else
+ %define RTLRD_CB 16
+%endif
+
+;; @name Floating point constants along the lines of the iprt/types.h types.
+; @note YASM does support special the __Infinity__ and __NaN__ nasm tokens.
+; @{
+%define RTFLOAT32U_QNAN_PLUS 0x7fc00000
+%define RTFLOAT32U_QNAN_MINUS 0xffc00000
+%define RTFLOAT32U_INF_PLUS 0x7f800000
+%define RTFLOAT32U_INF_MINUS 0xff800000
+
+%define RTFLOAT64U_QNAN_PLUS 0x7ff8000000000000
+%define RTFLOAT64U_QNAN_MINUS 0xfff8000000000000
+%define RTFLOAT64U_INF_PLUS 0x7ff0000000000000
+%define RTFLOAT64U_INF_MINUS 0xfff0000000000000
+; @}
+
+
+
+;; @def ASM_CALL64_GCC
+; Indicates that we're using the GCC 64-bit calling convention.
+; @see @ref sec_vboxrem_amd64_compare (in VBoxREMWrapper.cpp) for an ABI description.
+
+;; @def ASM_CALL64_MSC
+; Indicates that we're using the Microsoft 64-bit calling convention (fastcall on steroids).
+; @see @ref sec_vboxrem_amd64_compare (in VBoxREMWrapper.cpp) for an ABI description.
+
+; Note: On X86 we're using cdecl unconditionally. There is not yet any common
+; calling convention on AMD64, that's why we need to support two different ones.)
+
+%ifdef RT_ARCH_AMD64
+ %ifndef ASM_CALL64_GCC
+ %ifndef ASM_CALL64_MSC
+ ; define it based on the object format.
+ %ifdef ASM_FORMAT_PE
+ %define ASM_CALL64_MSC
+ %else
+ %define ASM_CALL64_GCC
+ %endif
+ %endif
+ %else
+ ; sanity check.
+ %ifdef ASM_CALL64_MSC
+ %error "Only one of the ASM_CALL64_* defines should be defined!"
+ %endif
+ %endif
+%else
+ ;later; %ifdef ASM_CALL64_GCC
+ ;later; %error "ASM_CALL64_GCC is defined without RT_ARCH_AMD64!" ASM_CALL64_GCC
+ ;later; %endif
+ ;later; %ifdef ASM_CALL64_MSC
+ ;later; %error "ASM_CALL64_MSC is defined without RT_ARCH_AMD64!" ASM_CALL64_MSC
+ ;later; %endif
+%endif
+
+
+;; @def RT_BEGINPROC
+; Starts an IPRT procedure that should be exported unless IN_RT_STATIC is defined.
+;
+; @param 1 The function name. Will apply NAME macro to it.
+%macro RT_BEGINPROC 1
+ %ifdef IN_RT_STATIC
+BEGINPROC %1
+ %else
+BEGINPROC_EXPORTED %1
+ %endif
+%endmacro ; RT_BEGINPROC
+
+
+;; @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.
+;
+; @remark Always feed the name to this macro first and then pass the result
+; on to the next *NAME* macro.
+;
+%ifndef RT_WITHOUT_NOCRT_WRAPPERS
+ %define RT_NOCRT(name) nocrt_ %+ name
+%else
+ %define RT_NOCRT(name) name
+%endif
+
+;; @def RT_NOCRT_BEGINPROC
+; Starts a NOCRT procedure, taking care of name wrapping and aliasing.
+;
+; Weak aliases for regular crt (%1) names to the nocrt_ prefixed ones will be
+; added when RT_WITH_NOCRT_ALIASES is defined and the output is ELF. If
+; RT_WITH_GENALIAS_NOCRT_ALIASES is undefined, strong aliases will be added for
+; for non-ELF targets, otherwise it's assumed the genalias build tool will do
+; the weak aliasing for us.
+;
+%macro RT_NOCRT_BEGINPROC 1
+ %ifdef RT_WITH_NOCRT_ALIASES
+BEGINPROC_EXPORTED RT_NOCRT(%1)
+ %ifdef ASM_FORMAT_ELF
+ ; ELF
+ %ifdef RT_WITH_NOCRT_UNDERSCORE_ALIASES
+global NAME(_ %+ %1):function
+weak NAME(_ %+ %1)
+SAFE_LABEL NAME(_ %+ %1)
+ %endif
+global NAME(%1):function
+weak NAME(%1)
+SAFE_LABEL NAME(%1)
+
+ %elifndef RT_WITH_GENALIAS_NOCRT_ALIASES
+ ; non-ELF when not using genalias.
+ %ifdef RT_WITH_NOCRT_UNDERSCORE_ALIASES
+GLOBALNAME _%1
+ %endif
+GLOBALNAME %1
+ %endif
+ %else ; !RT_WITH_NOCRT_ALIASES
+BEGINPROC_EXPORTED RT_NOCRT(%1)
+ %endif ; !RT_WITH_NOCRT_ALIASES
+%endmacro ; RT_NOCRT_BEGINPROC
+
+
+
+;; @def xCB
+; The stack unit size / The register unit size.
+
+;; @def xSP
+; The stack pointer register (RSP or ESP).
+
+;; @def xBP
+; The base pointer register (RBP or ESP).
+
+;; @def xAX
+; RAX or EAX depending on context.
+
+;; @def xBX
+; RBX or EBX depending on context.
+
+;; @def xCX
+; RCX or ECX depending on context.
+
+;; @def xDX
+; RDX or EDX depending on context.
+
+;; @def xDI
+; RDI or EDI depending on context.
+
+;; @def xSI
+; RSI or ESI depending on context.
+
+;; @def xWrtRIP
+; 'wrt rip' for AMD64 targets, nothing for x86 ones.
+
+%ifdef RT_ARCH_AMD64
+ %define xCB 8
+ %define xSP rsp
+ %define xBP rbp
+ %define xAX rax
+ %define xBX rbx
+ %define xCX rcx
+ %define xDX rdx
+ %define xDI rdi
+ %define xSI rsi
+ %define xWrtRIP wrt rip
+%else
+ %define xCB 4
+ %define xSP esp
+ %define xBP ebp
+ %define xAX eax
+ %define xBX ebx
+ %define xCX ecx
+ %define xDX edx
+ %define xDI edi
+ %define xSI esi
+ %define xWrtRIP
+%endif
+
+
+;
+; NASM sets __PASS__ to 0 in preprocess-only mode, and to 3 when only generating dependencies.
+; YASM has no such setting which is why we must rely on kBuild to tell us what we're doing.
+; For simplicity, we'll set the kBuild macro when using NASM.
+;
+%ifndef KBUILD_GENERATING_MAKEFILE_DEPENDENCIES
+ %ifdef __NASM__
+ %if __PASS__ == 0 || __PASS__ == 3
+ %define KBUILD_GENERATING_MAKEFILE_DEPENDENCIES
+ %endif
+ %endif
+%endif
+
+
+;
+; Some simple compile time assertions.
+;
+; Note! Requires new kBuild to work with YASM (see above).
+;
+
+;;
+; Structure size assertion macro.
+%define AssertCompileSize(a_Type, a_Size) AssertCompileSizeML a_Type, a_Size
+%macro AssertCompileSizeML 2
+ %ifndef KBUILD_GENERATING_MAKEFILE_DEPENDENCIES
+ %assign AssertVar_cbActual %1 %+ _size
+ %assign AssertVar_cbExpected %2
+ %if AssertVar_cbActual != AssertVar_cbExpected
+ %error %1 is AssertVar_cbActual bytes instead of AssertVar_cbExpected
+ %endif
+ %endif
+%endmacro
+
+;;
+; Structure size alignment assertion macro.
+
+%define AssertCompileSizeAlignment(a_Type, a_Align) AssertCompileSizeAlignmentML a_Type, a_Align
+%macro AssertCompileSizeAlignmentML 2
+ %ifndef KBUILD_GENERATING_MAKEFILE_DEPENDENCIES
+ %assign AssertVar_cbActual %1 %+ _size
+ %assign AssertVar_cbAlignment %2
+ %if (AssertVar_cbActual & (AssertVar_cbAlignment - 1)) != 0
+ %error %1 is AssertVar_cbActual bytes, expected size with AssertVar_cbAlignment bytes alignment.
+ %endif
+ %endif
+%endmacro
+
+;;
+; Structure member offset assertion macro.
+%define AssertCompileMemberOffset(a_Type, a_Member, a_off) AssertCompileMemberOffsetML a_Type, a_Member, a_off
+%macro AssertCompileMemberOffsetML 3
+ %ifndef KBUILD_GENERATING_MAKEFILE_DEPENDENCIES
+ %assign AssertVar_offActual %1 %+ . %+ %2
+ %assign AssertVar_offExpected %3
+ %if AssertVar_offActual != AssertVar_offExpected
+ %error %1 %+ . %+ %2 is at AssertVar_offActual instead of AssertVar_offExpected
+ %endif
+ %endif
+%endmacro
+
+;;
+; Structure member alignment assertion macro.
+%define AssertCompileMemberAlignment(a_Type, a_Member, a_cbAlign) AssertCompileMemberAlignmentML a_Type, a_Member, a_cbAlign
+%macro AssertCompileMemberAlignmentML 3
+ %ifndef KBUILD_GENERATING_MAKEFILE_DEPENDENCIES
+ %assign AssertVar_offActual %1 %+ . %+ %2
+ %assign AssertVar_cbAlign %3
+ %if AssertVar_offActual & (AssertVar_cbAlign - 1)
+ %error %1 %+ . %+ %2 is at AssertVar_offActual, expected AssertVar_cbAlign alignment
+ %endif
+ %endif
+%endmacro
+
+;;
+; Generic compile time expression assertion.
+%define AssertCompile(a_Expr) AssertCompileML { a_Expr }
+%macro AssertCompileML 1
+ %ifndef KBUILD_GENERATING_MAKEFILE_DEPENDENCIES
+ %if (%1) != 1
+ %assign AssertVar_uResult %1
+ %error %1 => AssertVar_uResult
+ %endif
+ %endif
+%endmacro
+
+%endif
+
diff --git a/include/iprt/asn1-generator-asn1-decoder.h b/include/iprt/asn1-generator-asn1-decoder.h
new file mode 100644
index 00000000..bf0d762c
--- /dev/null
+++ b/include/iprt/asn1-generator-asn1-decoder.h
@@ -0,0 +1,40 @@
+/** @file
+ * IPRT - ASN.1 Code Generator, the ASN1 Decoder Passes.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#include <iprt/string.h>
+
+#define RTASN1TMPL_PASS RTASN1TMPL_PASS_DECODE
+#include <iprt/asn1-generator-pass.h>
+
diff --git a/include/iprt/asn1-generator-core.h b/include/iprt/asn1-generator-core.h
new file mode 100644
index 00000000..50dbb700
--- /dev/null
+++ b/include/iprt/asn1-generator-core.h
@@ -0,0 +1,50 @@
+/** @file
+ * IPRT - ASN.1 Code Generator, the ASN.1 Core Code (VTable, Compare, ..).
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#include <iprt/assert.h>
+#include <iprt/err.h>
+#include <iprt/string.h>
+
+#define RTASN1TMPL_PASS RTASN1TMPL_PASS_XTAG
+#include <iprt/asn1-generator-pass.h>
+#define RTASN1TMPL_PASS RTASN1TMPL_PASS_VTABLE
+#include <iprt/asn1-generator-pass.h>
+#define RTASN1TMPL_PASS RTASN1TMPL_PASS_DELETE
+#include <iprt/asn1-generator-pass.h>
+#define RTASN1TMPL_PASS RTASN1TMPL_PASS_ENUM
+#include <iprt/asn1-generator-pass.h>
+#define RTASN1TMPL_PASS RTASN1TMPL_PASS_COMPARE
+#include <iprt/asn1-generator-pass.h>
+
diff --git a/include/iprt/asn1-generator-init.h b/include/iprt/asn1-generator-init.h
new file mode 100644
index 00000000..74665a8a
--- /dev/null
+++ b/include/iprt/asn1-generator-init.h
@@ -0,0 +1,48 @@
+/** @file
+ * IPRT - ASN.1 Code Generator, the ASN1 Init, Clone and Modifier Passes.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#include <iprt/string.h>
+
+#define RTASN1TMPL_PASS RTASN1TMPL_PASS_INIT
+#include <iprt/asn1-generator-pass.h>
+#define RTASN1TMPL_PASS RTASN1TMPL_PASS_CLONE
+#include <iprt/asn1-generator-pass.h>
+#define RTASN1TMPL_PASS RTASN1TMPL_PASS_SETTERS_1
+#include <iprt/asn1-generator-pass.h>
+#define RTASN1TMPL_PASS RTASN1TMPL_PASS_SETTERS_2
+#include <iprt/asn1-generator-pass.h>
+#define RTASN1TMPL_PASS RTASN1TMPL_PASS_ARRAY
+#include <iprt/asn1-generator-pass.h>
+
diff --git a/include/iprt/asn1-generator-internal-header.h b/include/iprt/asn1-generator-internal-header.h
new file mode 100644
index 00000000..9ec72f52
--- /dev/null
+++ b/include/iprt/asn1-generator-internal-header.h
@@ -0,0 +1,39 @@
+/** @file
+ * IPRT - ASN.1 Code Generator, the Internal Header File.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+
+#define RTASN1TMPL_PASS RTASN1TMPL_PASS_INTERNAL_HEADER
+#include <iprt/asn1-generator-pass.h>
+
diff --git a/include/iprt/asn1-generator-pass.h b/include/iprt/asn1-generator-pass.h
new file mode 100644
index 00000000..86cfd3ef
--- /dev/null
+++ b/include/iprt/asn1-generator-pass.h
@@ -0,0 +1,1757 @@
+/** @file
+ * IPRT - ASN.1 Code Generator, One Pass.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef ___iprt_asn1_generator_pass_h /* (special, only part of the file) */
+#define ___iprt_asn1_generator_pass_h
+
+#include <iprt/formats/asn1.h>
+#include <iprt/err.h>
+
+
+/** @def RTASN1TMPL_MEMBER_OPT_ANY
+ * Used for optional entries without any specific type at the end of a
+ * structure.
+ *
+ * For example PolicyQualifierInfo's qualifier member which is defined as:
+ * ANY DEFINED BY policyQualifierId
+ *
+ * Defaults to RTASN1TMPL_MEMBER_EX.
+ */
+
+/** @def RTASN1TMPL_MEMBER_OPT_ITAG_EX
+ * Optional member with implict tag, extended version.
+ *
+ * This is what all the other RTASN1TMPL_MEMBER_OPT_ITAG* macros defere to.
+ */
+/** @def RTASN1TMPL_MEMBER_OPT_ITAG_CP
+ * Optional member of a typical primitive type with an implicit context tag.
+ *
+ * Examples of this can be found in AuthorityKeyIdentifier where the first and
+ * last member are primitive types (normally anyways).:
+ * keyIdentifier [1] OCTET STRING OPTIONAL,
+ * authorityCertSerialNumber [3] INTEGER OPTIONAL
+ */
+/** @def RTASN1TMPL_MEMBER_OPT_ITAG_UC
+ * Optional member of a constructed type from the universal tag class.
+ */
+/** @def RTASN1TMPL_MEMBER_OPT_ITAG_UP
+ * Optional member of a primitive type from the universal tag class.
+ */
+
+
+/** @name Expansion Passes (RTASN1TMPL_PASS values)
+ * @{ */
+#define RTASN1TMPL_PASS_INTERNAL_HEADER 1
+
+#define RTASN1TMPL_PASS_XTAG 2
+#define RTASN1TMPL_PASS_VTABLE 3
+#define RTASN1TMPL_PASS_ENUM 4
+#define RTASN1TMPL_PASS_DELETE 5
+#define RTASN1TMPL_PASS_COMPARE 6
+
+#define RTASN1TMPL_PASS_CHECK_SANITY 8
+
+#define RTASN1TMPL_PASS_INIT 16
+#define RTASN1TMPL_PASS_CLONE 17
+#define RTASN1TMPL_PASS_SETTERS_1 18
+#define RTASN1TMPL_PASS_SETTERS_2 19
+#define RTASN1TMPL_PASS_ARRAY 20
+
+#define RTASN1TMPL_PASS_DECODE 24
+/** @} */
+
+/** @name ITAG clues
+ * @{ */
+#define RTASN1TMPL_ITAG_F_CC 1 /**< context, constructed. */
+#define RTASN1TMPL_ITAG_F_CP 2 /**< context, probably primary. (w/ numeric value) */
+#define RTASN1TMPL_ITAG_F_UP 3 /**< universal, probably primary. (w/ ASN1_TAG_XXX value) */
+#define RTASN1TMPL_ITAG_F_UC 4 /**< universal, constructed. (w/ ASN1_TAG_XXX value) */
+/** @} */
+/** Expands the ITAG clues into tag flag and tag class. */
+#define RTASN1TMPL_ITAG_F_EXPAND(a_fClue) \
+ ( a_fClue == RTASN1TMPL_ITAG_F_CC ? (ASN1_TAGCLASS_CONTEXT | ASN1_TAGFLAG_CONSTRUCTED ) \
+ : a_fClue == RTASN1TMPL_ITAG_F_CP ? (ASN1_TAGCLASS_CONTEXT | ASN1_TAGFLAG_PRIMITIVE) \
+ : a_fClue == RTASN1TMPL_ITAG_F_UP ? (ASN1_TAGCLASS_UNIVERSAL | ASN1_TAGFLAG_PRIMITIVE) \
+ : a_fClue == RTASN1TMPL_ITAG_F_UC ? (ASN1_TAGCLASS_UNIVERSAL | ASN1_TAGFLAG_CONSTRUCTED) \
+ : 0 )
+
+#define RTASN1TMPL_SEMICOLON_DUMMY() typedef unsigned RTASN1TMPLSEMICOLONDUMMY
+
+#endif /* !___iprt_asn1_generator_pass_h */
+
+
+#if RTASN1TMPL_PASS == RTASN1TMPL_PASS_INTERNAL_HEADER
+/*
+ *
+ * Internal header file.
+ *
+ */
+# define RTASN1TMPL_BEGIN_COMMON() extern DECL_HIDDEN_DATA(RTASN1COREVTABLE const) RT_CONCAT3(g_,RTASN1TMPL_INT_NAME,_Vtable)
+
+# define RTASN1TMPL_BEGIN_SEQCORE() RTASN1TMPL_BEGIN_COMMON()
+# define RTASN1TMPL_BEGIN_SETCORE() RTASN1TMPL_BEGIN_COMMON()
+# define RTASN1TMPL_MEMBER_EX(a_Name, a_Type, a_Api, a_Constraints) RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_MEMBER_OPT_XTAG_EX(a_TnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_uTag, a_Constraints) \
+ extern "C" DECL_HIDDEN_DATA(RTASN1COREVTABLE const) RT_CONCAT5(g_,RTASN1TMPL_INT_NAME,_XTAG_,a_Name,_Vtable)
+
+# define RTASN1TMPL_MEMBER_DYN_BEGIN(a_ObjIdMembNm, a_enmType, a_enmMembNm, a_Allocation) RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_MEMBER_DYN_END(a_ObjIdMembNm, a_enmType, a_enmMembNm, a_Allocation) RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_END_SEQCORE() RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_END_SETCORE() RTASN1TMPL_SEMICOLON_DUMMY()
+
+
+# define RTASN1TMPL_BEGIN_PCHOICE() RTASN1TMPL_BEGIN_COMMON()
+# define RTASN1TMPL_PCHOICE_ITAG_EX(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api, a_fClue, a_Constraints) \
+ RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_PCHOICE_XTAG_EX(a_uTag, a_enmChoice, a_PtrTnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_Constraints) \
+ extern "C" DECL_HIDDEN_DATA(RTASN1COREVTABLE const) RT_CONCAT5(g_,RTASN1TMPL_INT_NAME,_PCHOICE_XTAG_,a_Name,_Vtable)
+
+# define RTASN1TMPL_END_PCHOICE() RTASN1TMPL_SEMICOLON_DUMMY()
+
+
+# define RTASN1TMPL_SEQ_OF(a_ItemType, a_ItemApi) RTASN1TMPL_BEGIN_COMMON()
+# define RTASN1TMPL_SET_OF(a_ItemType, a_ItemApi) RTASN1TMPL_BEGIN_COMMON()
+
+
+
+#elif RTASN1TMPL_PASS == RTASN1TMPL_PASS_XTAG
+/*
+ *
+ * Generate a vtable and associated methods for explicitly tagged items (XTAG).
+ *
+ * These turned out to be a little problematic during encoding since there are
+ * two tags, the first encapsulating the second, thus the enumeration has to be
+ * nested or we cannot calculate the size of the first tag.
+ *
+ *
+ */
+# define RTASN1TMPL_BEGIN_COMMON() RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_BEGIN_SEQCORE() RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_BEGIN_SETCORE() RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_MEMBER_EX(a_Name, a_Type, a_Api, a_Constraints) RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_MEMBER_DYN_BEGIN(a_ObjIdMembNm, a_enmType, a_enmMembNm, a_Allocation) RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_MEMBER_DYN_END(a_ObjIdMembNm, a_enmType, a_enmMembNm, a_Allocation) RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_MEMBER_OPT_XTAG_EX(a_TnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_uTag, a_Constraints) \
+ /* This is the method we need to make it work. */ \
+ static DECLCALLBACK(int) RT_CONCAT4(RTASN1TMPL_INT_NAME,_XTAG_,a_Name,_Enum)(PRTASN1CORE pThisCore, \
+ PFNRTASN1ENUMCALLBACK pfnCallback, \
+ uint32_t uDepth, void *pvUser) \
+ { \
+ RTASN1TMPL_TYPE *pThis = RT_FROM_MEMBER(pThisCore, RTASN1TMPL_TYPE, a_TnNm.a_CtxTagN); \
+ if (RTASN1CORE_IS_PRESENT(&pThis->a_TnNm.a_CtxTagN.Asn1Core)) \
+ return pfnCallback(RT_CONCAT(a_Api,_GetAsn1Core)(&pThis->a_TnNm.a_Name), #a_TnNm "." #a_Name, uDepth + 1, pvUser); \
+ return VINF_SUCCESS; \
+ } \
+ /* The reminder of the methods shouldn't normally be needed, just stub them. */ \
+ static DECLCALLBACK(void) RT_CONCAT4(RTASN1TMPL_INT_NAME,_XTAG_,a_Name,_Delete)(PRTASN1CORE pThisCore) \
+ { AssertFailed(); RT_NOREF_PV(pThisCore); } \
+ static DECLCALLBACK(int) RT_CONCAT4(RTASN1TMPL_INT_NAME,_XTAG_,a_Name,_Clone)(PRTASN1CORE pThisCore, PCRTASN1CORE pSrcCore, \
+ PCRTASN1ALLOCATORVTABLE pAllocator) \
+ { AssertFailed(); RT_NOREF_PV(pThisCore); RT_NOREF_PV(pSrcCore); RT_NOREF_PV(pAllocator); return VERR_INTERNAL_ERROR_2; } \
+ static DECLCALLBACK(int) RT_CONCAT4(RTASN1TMPL_INT_NAME,_XTAG_,a_Name,_Compare)(PCRTASN1CORE pLeftCore, \
+ PCRTASN1CORE pRightCore) \
+ { AssertFailed(); RT_NOREF_PV(pLeftCore); RT_NOREF_PV(pRightCore); return VERR_INTERNAL_ERROR_2; } \
+ static DECLCALLBACK(int) RT_CONCAT4(RTASN1TMPL_INT_NAME,_XTAG_,a_Name,_CheckSanity)(PCRTASN1CORE pThisCore, uint32_t fFlags, \
+ PRTERRINFO pErrInfo, const char *pszErrorTag) \
+ { AssertFailed(); RT_NOREF_PV(pThisCore); RT_NOREF_PV(fFlags); RT_NOREF_PV(pErrInfo); RT_NOREF_PV(pszErrorTag); \
+ return VERR_INTERNAL_ERROR_2; } \
+ DECL_HIDDEN_CONST(RTASN1COREVTABLE const) RT_CONCAT5(g_,RTASN1TMPL_INT_NAME,_XTAG_,a_Name,_Vtable) = \
+ { \
+ /* When the Asn1Core is at the start of the structure, we can reuse the _Delete and _Enum APIs here. */ \
+ /* .pszName = */ RT_XSTR(RTASN1TMPL_INT_NAME) "_XTAG_" RT_XSTR(a_Name), \
+ /* .cb = */ RT_SIZEOFMEMB(RTASN1TMPL_TYPE, a_TnNm), \
+ /* .uDefaultTag = */ a_uTag, \
+ /* .fDefaultClass = */ ASN1_TAGCLASS_CONTEXT, \
+ /* .uReserved = */ 0, \
+ RT_CONCAT4(RTASN1TMPL_INT_NAME,_XTAG_,a_Name,_Delete), \
+ RT_CONCAT4(RTASN1TMPL_INT_NAME,_XTAG_,a_Name,_Enum), \
+ RT_CONCAT4(RTASN1TMPL_INT_NAME,_XTAG_,a_Name,_Clone), \
+ RT_CONCAT4(RTASN1TMPL_INT_NAME,_XTAG_,a_Name,_Compare), \
+ RT_CONCAT4(RTASN1TMPL_INT_NAME,_XTAG_,a_Name,_CheckSanity), \
+ /*.pfnEncodePrep */ NULL, \
+ /*.pfnEncodeWrite */ NULL \
+ }
+
+
+# define RTASN1TMPL_END_SEQCORE() RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_END_SETCORE() RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_BEGIN_PCHOICE() RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_PCHOICE_ITAG_EX(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api, a_fClue, a_Constraints) \
+ RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_PCHOICE_XTAG_EX(a_uTag, a_enmChoice, a_PtrTnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_Constraints) \
+ /* This is the method we need to make it work. */ \
+ static DECLCALLBACK(int) RT_CONCAT4(RTASN1TMPL_INT_NAME,_PC_XTAG_,a_Name,_Enum)(PRTASN1CORE pThisCore, \
+ PFNRTASN1ENUMCALLBACK pfnCallback, \
+ uint32_t uDepth, void *pvUser) \
+ { \
+ if (RTASN1CORE_IS_PRESENT(pThisCore)) \
+ { \
+ /** @todo optimize this one day, possibly change the PCHOICE+XTAG representation. */ \
+ RTASN1TMPL_TYPE Tmp; \
+ *(PRTASN1CORE *)&Tmp.a_PtrTnNm = pThisCore; \
+ Assert(&Tmp.a_PtrTnNm->a_CtxTagN.Asn1Core == pThisCore); \
+ return pfnCallback(RT_CONCAT(a_Api,_GetAsn1Core)(&Tmp.a_PtrTnNm->a_Name), "T" #a_uTag "." #a_Name, uDepth + 1, pvUser); \
+ } \
+ return VINF_SUCCESS; \
+ } \
+ /* The reminder of the methods shouldn't normally be needed, just stub them. */ \
+ static DECLCALLBACK(void) RT_CONCAT4(RTASN1TMPL_INT_NAME,_PC_XTAG_,a_Name,_Delete)(PRTASN1CORE pThisCore) \
+ { AssertFailed(); RT_NOREF_PV(pThisCore); } \
+ static DECLCALLBACK(int) RT_CONCAT4(RTASN1TMPL_INT_NAME,_PC_XTAG_,a_Name,_Clone)(PRTASN1CORE pThisCore, PCRTASN1CORE pSrcCore, \
+ PCRTASN1ALLOCATORVTABLE pAllocator) \
+ { AssertFailed(); RT_NOREF_PV(pThisCore); RT_NOREF_PV(pSrcCore); RT_NOREF_PV(pAllocator); return VERR_INTERNAL_ERROR_3; } \
+ static DECLCALLBACK(int) RT_CONCAT4(RTASN1TMPL_INT_NAME,_PC_XTAG_,a_Name,_Compare)(PCRTASN1CORE pLeftCore, \
+ PCRTASN1CORE pRightCore) \
+ { AssertFailed(); RT_NOREF_PV(pLeftCore); RT_NOREF_PV(pRightCore); return VERR_INTERNAL_ERROR_3; } \
+ static DECLCALLBACK(int) RT_CONCAT4(RTASN1TMPL_INT_NAME,_PC_XTAG_,a_Name,_CheckSanity)(PCRTASN1CORE pThisCore, uint32_t fFlags, \
+ PRTERRINFO pErrInfo, const char *pszErrorTag) \
+ { AssertFailed(); RT_NOREF_PV(pThisCore); RT_NOREF_PV(fFlags); RT_NOREF_PV(pErrInfo); RT_NOREF_PV(pszErrorTag); \
+ return VERR_INTERNAL_ERROR_3; } \
+ DECL_HIDDEN_CONST(RTASN1COREVTABLE const) RT_CONCAT5(g_,RTASN1TMPL_INT_NAME,_PCHOICE_XTAG_,a_Name,_Vtable) = \
+ { \
+ /* When the Asn1Core is at the start of the structure, we can reuse the _Delete and _Enum APIs here. */ \
+ /* .pszName = */ RT_XSTR(RTASN1TMPL_INT_NAME) "_PCHOICE_XTAG_" RT_XSTR(a_Name), \
+ /* .cb = */ sizeof(*((RTASN1TMPL_TYPE *)(void *)0)->a_PtrTnNm), \
+ /* .uDefaultTag = */ a_uTag, \
+ /* .fDefaultClass = */ ASN1_TAGCLASS_CONTEXT, \
+ /* .uReserved = */ 0, \
+ RT_CONCAT4(RTASN1TMPL_INT_NAME,_PC_XTAG_,a_Name,_Delete), \
+ RT_CONCAT4(RTASN1TMPL_INT_NAME,_PC_XTAG_,a_Name,_Enum), \
+ RT_CONCAT4(RTASN1TMPL_INT_NAME,_PC_XTAG_,a_Name,_Clone), \
+ RT_CONCAT4(RTASN1TMPL_INT_NAME,_PC_XTAG_,a_Name,_Compare), \
+ RT_CONCAT4(RTASN1TMPL_INT_NAME,_PC_XTAG_,a_Name,_CheckSanity), \
+ /*.pfnEncodePrep */ NULL, \
+ /*.pfnEncodeWrite */ NULL \
+ }
+
+
+
+# define RTASN1TMPL_END_PCHOICE() RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_SEQ_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_SET_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SEMICOLON_DUMMY()
+
+
+
+#elif RTASN1TMPL_PASS == RTASN1TMPL_PASS_VTABLE
+/*
+ *
+ * Internal header file.
+ *
+ */
+# ifndef RTASN1TMPL_VTABLE_FN_ENCODE_PREP
+# define RTASN1TMPL_VTABLE_FN_ENCODE_PREP NULL
+# endif
+# ifndef RTASN1TMPL_VTABLE_FN_ENCODE_WRITE
+# define RTASN1TMPL_VTABLE_FN_ENCODE_WRITE NULL
+# endif
+# define RTASN1TMPL_BEGIN_COMMON(a_uDefaultTag, a_fDefaultClass) \
+ DECL_HIDDEN_CONST(RTASN1COREVTABLE const) RT_CONCAT3(g_,RTASN1TMPL_INT_NAME,_Vtable) = \
+ { \
+ /* When the Asn1Core is at the start of the structure, we can reuse the _Delete and _Enum APIs here. */ \
+ /* .pszName = */ RT_XSTR(RTASN1TMPL_EXT_NAME), \
+ /* .cb = */ sizeof(RTASN1TMPL_TYPE), \
+ /* .uDefaultTag = */ a_uDefaultTag, \
+ /* .fDefaultClass = */ a_fDefaultClass, \
+ /* .uReserved = */ 0, \
+ (PFNRTASN1COREVTDTOR)RT_CONCAT(RTASN1TMPL_EXT_NAME,_Delete), \
+ (PFNRTASN1COREVTENUM)RT_CONCAT(RTASN1TMPL_EXT_NAME,_Enum), \
+ (PFNRTASN1COREVTCLONE)RT_CONCAT(RTASN1TMPL_EXT_NAME,_Clone), \
+ (PFNRTASN1COREVTCOMPARE)RT_CONCAT(RTASN1TMPL_EXT_NAME,_Compare), \
+ (PFNRTASN1COREVTCHECKSANITY)RT_CONCAT(RTASN1TMPL_EXT_NAME,_CheckSanity), \
+ RTASN1TMPL_VTABLE_FN_ENCODE_PREP, \
+ RTASN1TMPL_VTABLE_FN_ENCODE_WRITE \
+ }
+
+# define RTASN1TMPL_BEGIN_SEQCORE() \
+ AssertCompileMemberOffset(RTASN1TMPL_TYPE, SeqCore, 0); \
+ RTASN1TMPL_BEGIN_COMMON(ASN1_TAG_SEQUENCE, ASN1_TAGCLASS_UNIVERSAL | ASN1_TAGFLAG_CONSTRUCTED)
+# define RTASN1TMPL_BEGIN_SETCORE() \
+ AssertCompileMemberOffset(RTASN1TMPL_TYPE, SetCore, 0); \
+ RTASN1TMPL_BEGIN_COMMON(ASN1_TAG_SET, ASN1_TAGCLASS_UNIVERSAL | ASN1_TAGFLAG_CONSTRUCTED)
+# define RTASN1TMPL_MEMBER_EX(a_Name, a_Type, a_Api, a_Constraints) RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_MEMBER_DYN_BEGIN(a_ObjIdMembNm, a_enmType, a_enmMembNm, a_Allocation) RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_MEMBER_DYN_END(a_ObjIdMembNm, a_enmType, a_enmMembNm, a_Allocation) RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_END_SEQCORE() RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_END_SETCORE() RTASN1TMPL_SEMICOLON_DUMMY()
+
+# define RTASN1TMPL_BEGIN_PCHOICE() \
+ AssertCompileMemberOffset(RTASN1TMPL_TYPE, Dummy, 0); \
+ RTASN1TMPL_BEGIN_COMMON(UINT8_MAX, UINT8_MAX)
+# define RTASN1TMPL_PCHOICE_ITAG_EX(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api, a_fClue, a_Constraints) \
+ RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_PCHOICE_XTAG_EX(a_uTag, a_enmChoice, a_PtrTnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_Constraints) \
+ RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_END_PCHOICE() RTASN1TMPL_SEMICOLON_DUMMY()
+
+# define RTASN1TMPL_SEQ_OF(a_ItemType, a_ItemApi) \
+ AssertCompileMemberOffset(RTASN1TMPL_TYPE, SeqCore, 0); \
+ RTASN1TMPL_BEGIN_COMMON(ASN1_TAG_SEQUENCE, ASN1_TAGCLASS_UNIVERSAL | ASN1_TAGFLAG_CONSTRUCTED)
+# define RTASN1TMPL_SET_OF(a_ItemType, a_ItemApi) \
+ AssertCompileMemberOffset(RTASN1TMPL_TYPE, SetCore, 0); \
+ RTASN1TMPL_BEGIN_COMMON(ASN1_TAG_SET, ASN1_TAGCLASS_UNIVERSAL | ASN1_TAGFLAG_CONSTRUCTED)
+
+
+
+#elif RTASN1TMPL_PASS == RTASN1TMPL_PASS_INIT
+/*
+ *
+ * Initialization to standard / default values.
+ *
+ */
+# define RTASN1TMPL_BEGIN_COMMON() \
+RTASN1TMPL_DECL(int) RT_CONCAT(RTASN1TMPL_EXT_NAME,_Init)(RT_CONCAT(P,RTASN1TMPL_TYPE) pThis, PCRTASN1ALLOCATORVTABLE pAllocator) \
+{ \
+ RT_NOREF_PV(pAllocator); \
+ RT_ZERO(*pThis)
+# define RTASN1TMPL_END_COMMON() \
+ return rc; \
+} RTASN1TMPL_SEMICOLON_DUMMY()
+
+# define RTASN1TMPL_BEGIN_SEQCORE() \
+ RTASN1TMPL_BEGIN_COMMON(); \
+ int rc = RTAsn1SequenceCore_Init(&pThis->SeqCore, &RT_CONCAT3(g_,RTASN1TMPL_INT_NAME,_Vtable))
+# define RTASN1TMPL_BEGIN_SETCORE() \
+ RTASN1TMPL_BEGIN_COMMON(); \
+ int rc = RTAsn1SetCore_Init(&pThis->SetCore, &RT_CONCAT3(g_,RTASN1TMPL_INT_NAME,_Vtable))
+# define RTASN1TMPL_MEMBER_EX(a_Name, a_Type, a_Api, a_Constraints) \
+ if (RT_SUCCESS(rc)) \
+ rc = RT_CONCAT(a_Api,_Init)(&pThis->a_Name, pAllocator)
+
+# define RTASN1TMPL_MEMBER_DYN_BEGIN(a_ObjIdMembNm, a_enmType, a_enmMembNm, a_Allocation) \
+ RTAsn1MemInitAllocation(&pThis->Allocation, pAllocator); \
+ pThis->a_enmMembNm = RT_CONCAT(a_enmType,_NOT_PRESENT)
+# define RTASN1TMPL_MEMBER_DYN_COMMON(a_UnionNm, a_PtrName, a_Type, a_Api, a_Allocation, a_enmMembNm, a_enmValue, a_IfStmt) \
+ do { } while (0)
+# define RTASN1TMPL_MEMBER_DYN_END(a_ObjIdMembNm, a_enmType, a_enmMembNm, a_Allocation) do { } while (0)
+
+# define RTASN1TMPL_MEMBER_DEF_ITAG_EX(a_Name, a_Type, a_Api, a_uTag, a_fClue, a_DefVal, a_Constraints) \
+ if (RT_SUCCESS(rc)) \
+ { \
+ rc = RT_CONCAT(a_Api,_InitDefault)(&pThis->a_Name, a_DefVal, pAllocator); \
+ if (RT_SUCCESS(rc)) \
+ rc = RTAsn1Core_SetTagAndFlags(RT_CONCAT(a_Api,_GetAsn1Core)(&pThis->a_Name), \
+ a_uTag, RTASN1TMPL_ITAG_F_EXPAND(a_fClue)); \
+ }
+# define RTASN1TMPL_MEMBER_OPT_EX(a_Name, a_Type, a_Api, a_Constraints) do { } while (0) /* All optional members are left as not-present. */
+# define RTASN1TMPL_END_SEQCORE() \
+ if (RT_FAILURE(rc)) \
+ RT_CONCAT(RTASN1TMPL_EXT_NAME,_Delete)(pThis); \
+ RTASN1TMPL_END_COMMON()
+# define RTASN1TMPL_END_SETCORE() RTASN1TMPL_END_SEQCORE()
+
+/* No choice, just an empty, non-present structure. */
+# define RTASN1TMPL_BEGIN_PCHOICE() \
+ RTASN1TMPL_BEGIN_COMMON(); \
+ RTAsn1MemInitAllocation(&pThis->Allocation, pAllocator); \
+ int rc = VINF_SUCCESS
+# define RTASN1TMPL_PCHOICE_ITAG_EX(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api, a_fClue, a_Constraints) \
+ do { } while (0)
+# define RTASN1TMPL_PCHOICE_XTAG_EX(a_uTag, a_enmChoice, a_PtrTnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_Constraints) \
+ do { } while (0)
+# define RTASN1TMPL_END_PCHOICE() RTASN1TMPL_END_COMMON()
+
+
+# define RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi, a_OfApi, a_OfMember) \
+ RTASN1TMPL_BEGIN_COMMON(); \
+ RTAsn1MemInitArrayAllocation(&pThis->Allocation, pAllocator, sizeof(a_ItemType)); \
+ int rc = RT_CONCAT(a_OfApi,_Init)(&pThis->a_OfMember, &RT_CONCAT3(g_,RTASN1TMPL_INT_NAME,_Vtable)); \
+ if (RT_FAILURE(rc)) \
+ RT_ZERO(*pThis); \
+ RTASN1TMPL_END_COMMON()
+# define RTASN1TMPL_SEQ_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi, RTAsn1SeqOfCore, SeqCore)
+# define RTASN1TMPL_SET_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi, RTAsn1SetOfCore, SetCore)
+
+
+
+#elif RTASN1TMPL_PASS == RTASN1TMPL_PASS_DECODE
+/*
+ *
+ * Decode ASN.1.
+ *
+ */
+# define RTASN1TMPL_BEGIN_COMMON() \
+RTASN1TMPL_DECL(int) RT_CONCAT(RTASN1TMPL_EXT_NAME,_DecodeAsn1)(PRTASN1CURSOR pCursor, uint32_t fFlags, \
+ RT_CONCAT(P,RTASN1TMPL_TYPE) pThis, const char *pszErrorTag) \
+{ \
+ RT_ZERO(*pThis);
+
+# define RTASN1TMPL_END_COMMON() \
+ return rc; \
+} RTASN1TMPL_SEMICOLON_DUMMY()
+
+
+# define RTASN1TMPL_BEGIN_SEQCORE() \
+ RTASN1TMPL_BEGIN_COMMON(); \
+ RTASN1CURSOR ThisCursor; \
+ int rc = RTAsn1CursorGetSequenceCursor(pCursor, fFlags, &pThis->SeqCore, &ThisCursor, pszErrorTag); \
+ if (RT_FAILURE(rc)) \
+ return rc; \
+ pCursor = &ThisCursor; \
+ pThis->SeqCore.Asn1Core.pOps = &RT_CONCAT3(g_,RTASN1TMPL_INT_NAME,_Vtable)
+# define RTASN1TMPL_BEGIN_SETCORE() \
+ RTASN1TMPL_BEGIN_COMMON(); \
+ RTASN1CURSOR ThisCursor; \
+ int rc = RTAsn1CursorGetSetCursor(pCursor, fFlags, &pThis->SetCore, &ThisCursor, pszErrorTag); \
+ if (RT_FAILURE(rc)) \
+ return rc; \
+ pCursor = &ThisCursor; \
+ pThis->SetCore.Asn1Core.pOps = &RT_CONCAT3(g_,RTASN1TMPL_INT_NAME,_Vtable)
+
+# define RTASN1TMPL_MEMBER_EX(a_Name, a_Type, a_Api, a_Constraints) \
+ if (RT_SUCCESS(rc)) \
+ rc = RT_CONCAT(a_Api,_DecodeAsn1)(pCursor, 0, &pThis->a_Name, #a_Name)
+
+# define RTASN1TMPL_MEMBER_DYN_BEGIN(a_ObjIdMembNm, a_enmType, a_enmMembNm, a_Allocation) \
+ if (RT_SUCCESS(rc)) \
+ { \
+ int rc2; /* not initialized! */ \
+ RTAsn1CursorInitAllocation(pCursor, &pThis->a_Allocation); \
+ pThis->a_enmMembNm = RT_CONCAT(a_enmType, _INVALID); \
+ if (false) do { /*nothing*/ } while (0)
+# define RTASN1TMPL_MEMBER_DYN_COMMON(a_UnionNm, a_PtrName, a_Type, a_Api, a_Allocation, a_enmMembNm, a_enmValue, a_IfStmt) \
+ else a_IfStmt \
+ do { \
+ rc2 = RTAsn1MemAllocZ(&pThis->a_Allocation, (void **)&pThis->a_UnionNm.a_PtrName, \
+ sizeof(*pThis->a_UnionNm.a_PtrName)); \
+ if (RT_SUCCESS(rc2)) \
+ { \
+ pThis->a_enmMembNm = a_enmValue; \
+ rc2 = RT_CONCAT(a_Api,_DecodeAsn1)(pCursor, 0, pThis->a_UnionNm.a_PtrName, #a_UnionNm "." #a_PtrName); \
+ } \
+ } while (0)
+# define RTASN1TMPL_MEMBER_DYN_END(a_ObjIdMembNm, a_enmType, a_enmMembNm, a_Allocation) \
+ rc = rc2; /* Should trigger warning if a _DEFAULT is missing. */ \
+ }
+
+# define RTASN1TMPL_MEMBER_OPT_EX(a_Name, a_Type, a_Api, a_Constraints) \
+ Error_Missing_Specific_Macro_In_Decode_Pass()
+
+# define RTASN1TMPL_MEMBER_DEF_ITAG_EX(a_Name, a_Type, a_Api, a_uTag, a_fClue, a_DefVal, a_Constraints) \
+ if (RT_SUCCESS(rc)) \
+ { \
+ if (RTAsn1CursorIsNextEx(pCursor, a_uTag, RTASN1TMPL_ITAG_F_EXPAND(a_fClue))) \
+ rc = RT_CONCAT(a_Api,_DecodeAsn1)(pCursor, 0, &pThis->a_Name, #a_Name); \
+ else \
+ rc = RT_CONCAT(a_Api,_InitDefault)(&pThis->a_Name, a_DefVal, pCursor->pPrimary->pAllocator); \
+ if (RT_SUCCESS(rc)) \
+ rc = RTAsn1Core_SetTagAndFlags(RT_CONCAT(a_Api,_GetAsn1Core)(&pThis->a_Name), \
+ a_uTag, RTASN1TMPL_ITAG_F_EXPAND(a_fClue)); \
+ } do {} while (0)
+
+# define RTASN1TMPL_MEMBER_OPT_UTF8_STRING_EX(a_Name, a_Constraints) \
+ if (RT_SUCCESS(rc) && RTAsn1CursorIsNextEx(pCursor, ASN1_TAG_UTF8_STRING, ASN1_TAGCLASS_CONTEXT | ASN1_TAGFLAG_PRIMITIVE)) \
+ rc = RTAsn1CursorGetUtf8String(pCursor, 0, &pThis->a_Name, #a_Name)
+
+# define RTASN1TMPL_MEMBER_OPT_ITAG_EX(a_Name, a_Type, a_Api, a_uTag, a_fClue, a_Constraints) \
+ if (RT_SUCCESS(rc) && RTAsn1CursorIsNextEx(pCursor, a_uTag, RTASN1TMPL_ITAG_F_EXPAND(a_fClue)) /** @todo || CER */) \
+ rc = RT_CONCAT(a_Api,_DecodeAsn1)(pCursor, RTASN1CURSOR_GET_F_IMPLICIT, &pThis->a_Name, #a_Name)
+
+# define RTASN1TMPL_MEMBER_OPT_ITAG_BITSTRING(a_Name, a_cMaxBits, a_uTag) \
+ if (RT_SUCCESS(rc) && RTAsn1CursorIsNextEx(pCursor, a_uTag, ASN1_TAGCLASS_CONTEXT | ASN1_TAGFLAG_CONSTRUCTED)) \
+ rc = RTAsn1CursorGetBitStringEx(pCursor, RTASN1CURSOR_GET_F_IMPLICIT, a_cMaxBits, &pThis->a_Name, #a_Name)
+
+# define RTASN1TMPL_MEMBER_OPT_XTAG_EX(a_TnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_uTag, a_Constraints) \
+ if (RT_SUCCESS(rc) && RTAsn1CursorIsNextEx(pCursor, a_uTag, ASN1_TAGCLASS_CONTEXT | ASN1_TAGFLAG_CONSTRUCTED)) \
+ { \
+ RTASN1CURSOR CtxCursor; \
+ rc = RT_CONCAT3(RTAsn1CursorGetContextTag,a_uTag,Cursor)(pCursor, 0, \
+ &RT_CONCAT5(g_,RTASN1TMPL_INT_NAME,_XTAG_,a_Name,_Vtable), \
+ &pThis->a_TnNm.a_CtxTagN, &CtxCursor, #a_TnNm); \
+ if (RT_SUCCESS(rc)) \
+ { \
+ rc = RT_CONCAT(a_Api,_DecodeAsn1)(&CtxCursor, 0, &pThis->a_TnNm.a_Name, #a_Name); \
+ if (RT_SUCCESS(rc)) \
+ rc = RTAsn1CursorCheckEnd(&CtxCursor); \
+ } \
+ } do { } while (0)
+
+# define RTASN1TMPL_MEMBER_OPT_ANY(a_Name, a_Type, a_Api) \
+ if (RT_SUCCESS(rc) && pCursor->cbLeft > 0) \
+ RTASN1TMPL_MEMBER_EX(a_Name, a_Type, a_Api, RT_NOTHING)
+
+# define RTASN1TMPL_END_SEQCORE() \
+ if (RT_SUCCESS(rc)) \
+ rc = RTAsn1CursorCheckSeqEnd(&ThisCursor, &pThis->SeqCore); \
+ if (RT_SUCCESS(rc)) \
+ return VINF_SUCCESS; \
+ RT_CONCAT(RTASN1TMPL_EXT_NAME,_Delete)(pThis); \
+ RTASN1TMPL_END_COMMON()
+# define RTASN1TMPL_END_SETCORE() \
+ if (RT_SUCCESS(rc)) \
+ rc = RTAsn1CursorCheckSetEnd(&ThisCursor, &pThis->SetCore); \
+ if (RT_SUCCESS(rc)) \
+ return VINF_SUCCESS; \
+ RT_CONCAT(RTASN1TMPL_EXT_NAME,_Delete)(pThis); \
+ RTASN1TMPL_END_COMMON()
+
+# define RTASN1TMPL_BEGIN_PCHOICE() \
+ RTASN1TMPL_BEGIN_COMMON(); \
+ RT_NOREF_PV(fFlags); \
+ RTAsn1Dummy_InitEx(&pThis->Dummy); \
+ pThis->Dummy.Asn1Core.pOps = &RT_CONCAT3(g_,RTASN1TMPL_INT_NAME,_Vtable); \
+ RTAsn1CursorInitAllocation(pCursor, &pThis->Allocation); \
+ RTASN1CORE Asn1Peek; \
+ int rc = RTAsn1CursorPeek(pCursor, &Asn1Peek); \
+ if (RT_SUCCESS(rc)) \
+ { \
+ if (false) do {} while (0)
+# define RTASN1TMPL_PCHOICE_ITAG_EX(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api, a_fClue, a_Constraints) \
+ else if ( Asn1Peek.uTag == (a_uTag) \
+ && (Asn1Peek.fClass == RTASN1TMPL_ITAG_F_EXPAND(a_fClue) /** @todo || CER */ ) ) \
+ do { \
+ pThis->enmChoice = a_enmChoice; \
+ rc = RTAsn1MemAllocZ(&pThis->Allocation, (void **)&pThis->a_PtrName, sizeof(*pThis->a_PtrName)); \
+ if (RT_SUCCESS(rc)) \
+ rc = RT_CONCAT(a_Api,_DecodeAsn1)(pCursor, RTASN1CURSOR_GET_F_IMPLICIT, pThis->a_PtrName, #a_PtrName); \
+ } while (0)
+# define RTASN1TMPL_PCHOICE_XTAG_EX(a_uTag, a_enmChoice, a_PtrTnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_Constraints) \
+ else if (Asn1Peek.uTag == (a_uTag) && Asn1Peek.fClass == (ASN1_TAGCLASS_CONTEXT | ASN1_TAGFLAG_CONSTRUCTED)) \
+ do { \
+ pThis->enmChoice = a_enmChoice; \
+ rc = RTAsn1MemAllocZ(&pThis->Allocation, (void **)&pThis->a_PtrTnNm, sizeof(*pThis->a_PtrTnNm)); \
+ if (RT_SUCCESS(rc)) \
+ { \
+ RTASN1CURSOR CtxCursor; \
+ rc = RT_CONCAT3(RTAsn1CursorGetContextTag,a_uTag,Cursor)(pCursor, 0, \
+ &RT_CONCAT5(g_,RTASN1TMPL_INT_NAME,_PCHOICE_XTAG_,a_Name,_Vtable), \
+ &pThis->a_PtrTnNm->a_CtxTagN, &CtxCursor, "T" #a_uTag); \
+ if (RT_SUCCESS(rc)) \
+ rc = RT_CONCAT(a_Api,_DecodeAsn1)(&CtxCursor, RTASN1CURSOR_GET_F_IMPLICIT, \
+ &pThis->a_PtrTnNm->a_Name, #a_Name); \
+ if (RT_SUCCESS(rc)) \
+ rc = RTAsn1CursorCheckEnd(&CtxCursor); \
+ } \
+ } while (0)
+#define RTASN1TMPL_END_PCHOICE() \
+ else \
+ rc = RTAsn1CursorSetInfo(pCursor, VERR_GENERAL_FAILURE, "%s: Unknown choice: tag=%#x fClass=%#x", \
+ pszErrorTag, Asn1Peek.uTag, Asn1Peek.fClass); \
+ if (RT_SUCCESS(rc)) \
+ return VINF_SUCCESS; \
+ } \
+ RT_CONCAT(RTASN1TMPL_EXT_NAME,_Delete)(pThis); \
+ RTASN1TMPL_END_COMMON()
+
+
+# define RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi, a_OfApi, a_OfMember, a_fnGetCursor) \
+ RTASN1TMPL_BEGIN_COMMON(); \
+ RTASN1CURSOR ThisCursor; \
+ int rc = a_fnGetCursor(pCursor, fFlags, &pThis->a_OfMember, &ThisCursor, pszErrorTag); \
+ if (RT_SUCCESS(rc)) \
+ { \
+ pCursor = &ThisCursor; \
+ pThis->a_OfMember.Asn1Core.pOps = &RT_CONCAT3(g_,RTASN1TMPL_INT_NAME,_Vtable); \
+ RTAsn1CursorInitArrayAllocation(pCursor, &pThis->Allocation, sizeof(a_ItemType)); \
+ \
+ uint32_t i = 0; \
+ while ( pCursor->cbLeft > 0 \
+ && RT_SUCCESS(rc)) \
+ { \
+ rc = RTAsn1MemResizeArray(&pThis->Allocation, (void ***)&pThis->papItems, i, i + 1); \
+ if (RT_SUCCESS(rc)) \
+ { \
+ rc = RT_CONCAT(a_ItemApi,_DecodeAsn1)(pCursor, 0, pThis->papItems[i], "papItems[#]"); \
+ if (RT_SUCCESS(rc)) \
+ { \
+ i++; \
+ pThis->cItems = i; \
+ continue; \
+ } \
+ } \
+ break; \
+ } \
+ if (RT_SUCCESS(rc)) \
+ { \
+ rc = RTAsn1CursorCheckEnd(pCursor); \
+ if (RT_SUCCESS(rc)) \
+ return VINF_SUCCESS; \
+ } \
+ RT_CONCAT(RTASN1TMPL_EXT_NAME,_Delete)(pThis); \
+ } \
+ RTASN1TMPL_END_COMMON()
+# define RTASN1TMPL_SEQ_OF(a_ItemType, a_ItemApi) \
+ RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi, RTAsn1SeqOfCore, SeqCore, RTAsn1CursorGetSequenceCursor)
+# define RTASN1TMPL_SET_OF(a_ItemType, a_ItemApi) \
+ RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi, RTAsn1SetOfCore, SetCore, RTAsn1CursorGetSetCursor)
+
+
+# define RTASN1TMPL_EXEC_DECODE(a_Expr) if (RT_SUCCESS(rc)) { a_Expr; }
+
+
+
+#elif RTASN1TMPL_PASS == RTASN1TMPL_PASS_ENUM
+/*
+ *
+ * Enumeration.
+ *
+ */
+# define RTASN1TMPL_BEGIN_COMMON() \
+RTASN1TMPL_DECL(int) RT_CONCAT(RTASN1TMPL_EXT_NAME,_Enum)(RT_CONCAT(P,RTASN1TMPL_TYPE) pThis, \
+ PFNRTASN1ENUMCALLBACK pfnCallback, \
+ uint32_t uDepth, void *pvUser) \
+{ \
+ if (!RT_CONCAT(RTASN1TMPL_EXT_NAME,_IsPresent)(pThis)) \
+ return VINF_SUCCESS; \
+ uDepth++; \
+ int rc = VINF_SUCCESS
+
+# define RTASN1TMPL_END_COMMON() \
+ return rc; \
+} RTASN1TMPL_SEMICOLON_DUMMY()
+
+# define RTASN1TMPL_BEGIN_SEQCORE() RTASN1TMPL_BEGIN_COMMON()
+# define RTASN1TMPL_BEGIN_SETCORE() RTASN1TMPL_BEGIN_COMMON()
+# define RTASN1TMPL_MEMBER_EX(a_Name, a_Type, a_Api, a_Constraints) \
+ if (rc == VINF_SUCCESS) \
+ rc = pfnCallback(RT_CONCAT(a_Api,_GetAsn1Core)(&pThis->a_Name), #a_Name, uDepth, pvUser)
+# define RTASN1TMPL_MEMBER_DYN_BEGIN(a_ObjIdMembNm, a_enmType, a_enmMembNm, a_Allocation) \
+ if (rc == VINF_SUCCESS) \
+ switch (pThis->a_enmMembNm) \
+ { \
+ default: rc = VERR_INTERNAL_ERROR_3; break
+# define RTASN1TMPL_MEMBER_DYN_COMMON(a_UnionNm, a_PtrName, a_Type, a_Api, a_Allocation, a_enmMembNm, a_enmValue, a_IfStmt) \
+ case a_enmValue: \
+ rc = pfnCallback(RT_CONCAT(a_Api,_GetAsn1Core)(pThis->a_UnionNm.a_PtrName), #a_UnionNm "." #a_PtrName, \
+ uDepth, pvUser); \
+ break
+# define RTASN1TMPL_MEMBER_DYN_END(a_ObjIdMembNm, a_enmType, a_enmMembNm, a_Allocation) \
+ case RT_CONCAT(a_enmType,_NOT_PRESENT): break; \
+ }
+# define RTASN1TMPL_MEMBER_OPT_EX(a_Name, a_Type, a_Api, a_Constraints) \
+ if (rc == VINF_SUCCESS && RT_CONCAT(a_Api,_IsPresent)(&pThis->a_Name)) \
+ rc = pfnCallback(RT_CONCAT(a_Api,_GetAsn1Core)(&pThis->a_Name), #a_Name, uDepth, pvUser)
+# define RTASN1TMPL_MEMBER_OPT_XTAG_EX(a_TnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_uTag, a_Constraints) \
+ if (rc == VINF_SUCCESS && RTASN1CORE_IS_PRESENT(&pThis->a_TnNm.a_CtxTagN.Asn1Core)) \
+ { \
+ rc = pfnCallback(&pThis->a_TnNm.a_CtxTagN.Asn1Core, #a_Name, uDepth, pvUser); \
+ } do {} while (0)
+# define RTASN1TMPL_END_SEQCORE() RTASN1TMPL_END_COMMON()
+# define RTASN1TMPL_END_SETCORE() RTASN1TMPL_END_COMMON()
+
+
+# define RTASN1TMPL_BEGIN_PCHOICE() \
+ RTASN1TMPL_BEGIN_COMMON(); \
+ switch (pThis->enmChoice) \
+ { \
+ default: rc = VERR_INTERNAL_ERROR_3; break
+# define RTASN1TMPL_PCHOICE_ITAG_EX(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api, a_fClue, a_Constraints) \
+ case a_enmChoice: rc = pfnCallback(RT_CONCAT(a_Api,_GetAsn1Core)(pThis->a_PtrName), #a_PtrName, uDepth, pvUser); break
+# define RTASN1TMPL_PCHOICE_XTAG_EX(a_uTag, a_enmChoice, a_PtrTnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_Constraints) \
+ case a_enmChoice: rc = pfnCallback(&pThis->a_PtrTnNm->a_CtxTagN.Asn1Core, "T" #a_uTag "." #a_CtxTagN, uDepth, pvUser); break
+#define RTASN1TMPL_END_PCHOICE() \
+ } \
+ RTASN1TMPL_END_COMMON()
+
+# define RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi) \
+ RTASN1TMPL_BEGIN_COMMON(); \
+ for (uint32_t i = 0; i < pThis->cItems && rc == VINF_SUCCESS; i++) \
+ rc = pfnCallback(RT_CONCAT(a_ItemApi,_GetAsn1Core)(pThis->papItems[i]), "papItems[#]", uDepth, pvUser); \
+ RTASN1TMPL_END_COMMON()
+# define RTASN1TMPL_SEQ_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi)
+# define RTASN1TMPL_SET_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi)
+
+
+
+#elif RTASN1TMPL_PASS == RTASN1TMPL_PASS_CLONE
+/*
+ *
+ * Clone another instance of the type.
+ *
+ */
+# define RTASN1TMPL_BEGIN_COMMON() \
+RTASN1TMPL_DECL(int) RT_CONCAT(RTASN1TMPL_EXT_NAME,_Clone)(RT_CONCAT(P,RTASN1TMPL_TYPE) pThis, \
+ RT_CONCAT(PC,RTASN1TMPL_TYPE) pSrc, \
+ PCRTASN1ALLOCATORVTABLE pAllocator) \
+{ \
+ RT_ZERO(*pThis); \
+ if (!RT_CONCAT(RTASN1TMPL_EXT_NAME,_IsPresent)(pSrc)) \
+ return VINF_SUCCESS; \
+
+# define RTASN1TMPL_END_COMMON() \
+ return rc; \
+} RTASN1TMPL_SEMICOLON_DUMMY()
+
+# define RTASN1TMPL_BEGIN_SEQCORE() \
+ RTASN1TMPL_BEGIN_COMMON(); \
+ int rc = RTAsn1SequenceCore_Clone(&pThis->SeqCore, &RT_CONCAT3(g_, RTASN1TMPL_INT_NAME, _Vtable), &pSrc->SeqCore)
+# define RTASN1TMPL_BEGIN_SETCORE() \
+ RTASN1TMPL_BEGIN_COMMON(); \
+ int rc = RTAsn1SetCore_Clone(&pThis->SetCore, &RT_CONCAT3(g_, RTASN1TMPL_INT_NAME, _Vtable), &pSrc->SetCore)
+
+# define RTASN1TMPL_MEMBER_EX(a_Name, a_Type, a_Api, a_Constraints) \
+ if (RT_SUCCESS(rc)) \
+ rc = RT_CONCAT(a_Api,_Clone)(&pThis->a_Name, &pSrc->a_Name, pAllocator); \
+
+# define RTASN1TMPL_MEMBER_DYN_BEGIN(a_ObjIdMembNm, a_enmType, a_enmMembNm, a_Allocation) \
+ if (RT_SUCCESS(rc)) \
+ { \
+ RTAsn1MemInitAllocation(&pThis->Allocation, pAllocator); \
+ pThis->a_enmMembNm = pSrc->a_enmMembNm; \
+ switch (pSrc->a_enmMembNm) \
+ { \
+ default: rc = VERR_INTERNAL_ERROR_3; break
+# define RTASN1TMPL_MEMBER_DYN_COMMON(a_UnionNm, a_PtrName, a_Type, a_Api, a_Allocation, a_enmMembNm, a_enmValue, a_IfStmt) \
+ case a_enmValue: \
+ rc = RTAsn1MemAllocZ(&pThis->a_Allocation, (void **)&pThis->a_UnionNm.a_PtrName, \
+ sizeof(*pThis->a_UnionNm.a_PtrName)); \
+ if (RT_SUCCESS(rc)) \
+ rc = RT_CONCAT(a_Api,_Clone)(pThis->a_UnionNm.a_PtrName, pSrc->a_UnionNm.a_PtrName, pAllocator); \
+ break
+# define RTASN1TMPL_MEMBER_DYN_END(a_ObjIdMembNm, a_enmType, a_enmMembNm, a_Allocation) \
+ case RT_CONCAT(a_enmType,_NOT_PRESENT): break; \
+ } \
+ }
+
+/* Optional members and members with defaults are the same as a normal member when cloning. */
+# define RTASN1TMPL_MEMBER_OPT_UTF8_STRING_EX(a_Name, a_Constraints) \
+ RTASN1TMPL_MEMBER_OPT_EX(a_Name, RTASN1STRING, RTAsn1Utf8String, a_Constraints RT_NOTHING)
+# define RTASN1TMPL_MEMBER_OPT_XTAG_EX(a_TnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_uTag, a_Constraints) \
+ if (RTASN1CORE_IS_PRESENT(&pSrc->a_TnNm.a_CtxTagN.Asn1Core) && RT_SUCCESS(rc)) \
+ { \
+ rc = RT_CONCAT3(RTAsn1ContextTag,a_uTag,_Clone)(&pThis->a_TnNm.a_CtxTagN, &pSrc->a_TnNm.a_CtxTagN); \
+ if (RT_SUCCESS(rc)) \
+ rc = RT_CONCAT(a_Api,_Clone)(&pThis->a_TnNm.a_Name, &pSrc->a_TnNm.a_Name, pAllocator); \
+ } do { } while (0)
+
+# define RTASN1TMPL_END_SEQCORE() \
+ if (RT_FAILURE(rc)) \
+ RT_CONCAT(RTASN1TMPL_EXT_NAME,_Delete)(pThis); \
+ RTASN1TMPL_END_COMMON()
+# define RTASN1TMPL_END_SETCORE() RTASN1TMPL_END_SEQCORE()
+
+
+# define RTASN1TMPL_BEGIN_PCHOICE() \
+ RTASN1TMPL_BEGIN_COMMON(); \
+ RTAsn1Dummy_InitEx(&pThis->Dummy); \
+ pThis->Dummy.Asn1Core.pOps = &RT_CONCAT3(g_,RTASN1TMPL_INT_NAME,_Vtable); \
+ RTAsn1MemInitAllocation(&pThis->Allocation, pAllocator); \
+ int rc; \
+ pThis->enmChoice = pSrc->enmChoice; \
+ switch (pSrc->enmChoice) \
+ { \
+ default: rc = VERR_INTERNAL_ERROR_3; break
+# define RTASN1TMPL_PCHOICE_ITAG_EX(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api, a_fClue, a_Constraints) \
+ case a_enmChoice: \
+ rc = RTAsn1MemAllocZ(&pThis->Allocation, (void **)&pThis->a_PtrName, sizeof(*pThis->a_PtrName)); \
+ if (RT_SUCCESS(rc)) \
+ rc = RT_CONCAT(a_Api,_Clone)(pThis->a_PtrName, pSrc->a_PtrName, pAllocator); \
+ break
+# define RTASN1TMPL_PCHOICE_XTAG_EX(a_uTag, a_enmChoice, a_PtrTnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_Constraints) \
+ case a_enmChoice: /* A bit of presence paranoia here, but better safe than sorry... */ \
+ rc = RTAsn1MemAllocZ(&pThis->Allocation, (void **)&pThis->a_PtrTnNm, sizeof(*pThis->a_PtrTnNm)); \
+ if (RT_SUCCESS(rc) && RTASN1CORE_IS_PRESENT(&pSrc->a_PtrTnNm->a_CtxTagN.Asn1Core)) \
+ { \
+ RT_CONCAT3(RTAsn1ContextTag,a_uTag,_Clone)(&pThis->a_PtrTnNm->a_CtxTagN, &pSrc->a_PtrTnNm->a_CtxTagN); \
+ rc = RT_CONCAT(a_Api,_Clone)(&pThis->a_PtrTnNm->a_Name, &pSrc->a_PtrTnNm->a_Name, pAllocator); \
+ } \
+ break
+#define RTASN1TMPL_END_PCHOICE() \
+ } \
+ if (RT_FAILURE(rc)) \
+ RT_CONCAT(RTASN1TMPL_EXT_NAME,_Delete)(pThis); \
+ RTASN1TMPL_END_COMMON()
+
+
+# define RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi, a_OfApi, a_OfMember) \
+ RTASN1TMPL_BEGIN_COMMON(); \
+ int rc = RT_CONCAT(a_OfApi,_Clone)(&pThis->a_OfMember, &RT_CONCAT3(g_,RTASN1TMPL_INT_NAME,_Vtable), &pSrc->a_OfMember); \
+ if (RT_SUCCESS(rc)) \
+ { \
+ RTAsn1MemInitArrayAllocation(&pThis->Allocation, pAllocator, sizeof(a_ItemType)); \
+ uint32_t const cItems = pSrc->cItems; \
+ if (cItems > 0) \
+ { \
+ rc = RTAsn1MemResizeArray(&pThis->Allocation, (void ***)&pThis->papItems, 0, cItems); \
+ if (RT_SUCCESS(rc)) \
+ { \
+ uint32_t i = 0; \
+ while (i < cItems) \
+ { \
+ rc = RT_CONCAT(a_ItemApi,_Clone)(pThis->papItems[i], pSrc->papItems[i], pAllocator); \
+ if (RT_SUCCESS(rc)) \
+ pThis->cItems = ++i; \
+ else \
+ { \
+ pThis->cItems = i; \
+ RT_CONCAT(RTASN1TMPL_EXT_NAME,_Delete)(pThis); \
+ return rc; \
+ } \
+ } \
+ } \
+ else \
+ RT_ZERO(*pThis); \
+ } \
+ } \
+ RTASN1TMPL_END_COMMON()
+# define RTASN1TMPL_SEQ_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi, RTAsn1SeqOfCore, SeqCore)
+# define RTASN1TMPL_SET_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi, RTAsn1SetOfCore, SetCore)
+
+# define RTASN1TMPL_EXEC_CLONE(a_Expr) if (RT_SUCCESS(rc)) { a_Expr; }
+
+
+
+#elif RTASN1TMPL_PASS == RTASN1TMPL_PASS_SETTERS_1
+/*
+ *
+ * Member setter helpers.
+ *
+ */
+# define RTASN1TMPL_BEGIN_SEQCORE() RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_BEGIN_SETCORE() RTASN1TMPL_SEMICOLON_DUMMY()
+#if 1 /** @todo later */
+# define RTASN1TMPL_MEMBER_EX(a_Name, a_Type, a_Api, a_Constraints) RTASN1TMPL_SEMICOLON_DUMMY()
+#else
+# define RTASN1TMPL_MEMBER_EX(a_Name, a_Type, a_Api, a_Constraints) \
+ RTDECL(int) RT_CONCAT3(RTASN1TMPL_EXT_NAME,_Set,a_Name)(RTASN1TMPL_TYPE *pThis, a_Type const *pValue, \
+ PCRTASN1ALLOCATORVTABLE pAllocator) \
+ { \
+ if (RT_CONCAT(a_Api,_IsPresent)(&pThis->a_Name)) \
+ RT_CONCAT(a_Api,_Delete)(&pThis->a_Name); \
+ return RT_CONCAT(a_Api,_Clone)(&pThis->a_Name, pValue, pAllocator, true /* fResetImplicit */); \
+ } RTASN1TMPL_SEMICOLON_DUMMY()
+#endif
+
+# define RTASN1TMPL_MEMBER_DYN_BEGIN(a_ObjIdMembNm, a_enmType, a_enmMembNm, a_Allocation) RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_MEMBER_DYN_END(a_ObjIdMembNm, a_enmType, a_enmMembNm, a_Allocation) RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_END_SEQCORE() RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_END_SETCORE() RTASN1TMPL_SEMICOLON_DUMMY()
+
+
+# define RTASN1TMPL_BEGIN_PCHOICE() RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_PCHOICE_ITAG_EX(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api, a_fClue, a_Constraints) RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_PCHOICE_XTAG_EX(a_uTag, a_enmChoice, a_PtrTnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_Constraints) RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_END_PCHOICE() RTASN1TMPL_SEMICOLON_DUMMY()
+
+
+# define RTASN1TMPL_SEQ_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_SET_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SEMICOLON_DUMMY()
+
+
+
+#elif RTASN1TMPL_PASS == RTASN1TMPL_PASS_SETTERS_2
+/*
+ *
+ * Member setters.
+ *
+ */
+# define RTASN1TMPL_BEGIN_SEQCORE() RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_BEGIN_SETCORE() RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_MEMBER_EX(a_Name, a_Type, a_Api, a_Constraints) RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_MEMBER_DYN_BEGIN(a_ObjIdMembNm, a_enmType, a_enmMembNm, a_Allocation) RTASN1TMPL_SEMICOLON_DUMMY()
+
+# define RTASN1TMPL_MEMBER_DYN(a_UnionNm, a_PtrName, a_Name, a_Type, a_Api, a_Allocation, a_ObjIdMembNm, a_enmMembNm, a_enmValue, a_szObjId) \
+RTASN1TMPL_DECL(int) RT_CONCAT3(RTASN1TMPL_EXT_NAME,_Set,a_Name)(RT_CONCAT(P,RTASN1TMPL_TYPE) pThis, \
+ RT_CONCAT(PC,a_Type) pToClone,\
+ PCRTASN1ALLOCATORVTABLE pAllocator) \
+{ \
+ AssertPtr(pThis); AssertPtrNull(pToClone); Assert(!pToClone || RT_CONCAT(a_Api,_IsPresent)(pToClone)); \
+ AssertReturn(pThis->a_UnionNm.a_PtrName == NULL, VERR_INVALID_STATE); /* for now */ \
+ /* Set the type */ \
+ if (RTAsn1ObjId_IsPresent(&pThis->a_ObjIdMembNm)) \
+ RTAsn1ObjId_Delete(&pThis->a_ObjIdMembNm); \
+ int rc = RTAsn1ObjId_InitFromString(&pThis->a_ObjIdMembNm, a_szObjId, pAllocator); \
+ if (RT_SUCCESS(rc)) \
+ { \
+ pThis->a_enmMembNm = a_enmValue; \
+ \
+ /* Allocate memory for the structure we're targeting. */ \
+ rc = RTAsn1MemAllocZ(&pThis->a_Allocation, (void **)&pThis->a_UnionNm.a_PtrName, sizeof(*pThis->a_UnionNm.a_PtrName)); \
+ if (RT_SUCCESS(rc)) \
+ { \
+ if (pToClone) /* If nothing to clone, just initialize the structure. */ \
+ rc = RT_CONCAT(a_Api,_Clone)(pThis->a_UnionNm.a_PtrName, pToClone, pAllocator); \
+ else \
+ rc = RT_CONCAT(a_Api,_Init)(pThis->a_UnionNm.a_PtrName, pAllocator); \
+ } \
+ } \
+ return rc; \
+} RTASN1TMPL_SEMICOLON_DUMMY()
+
+
+
+# define RTASN1TMPL_MEMBER_DYN_END(a_ObjIdMembNm, a_enmType, a_enmMembNm, a_Allocation) RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_END_SEQCORE() RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_END_SETCORE() RTASN1TMPL_SEMICOLON_DUMMY()
+
+# define RTASN1TMPL_MEMBER_OPT_ITAG_EX(a_Name, a_Type, a_Api, a_uTag, a_fClue, a_Constraints) \
+RTASN1TMPL_DECL(int) RT_CONCAT3(RTASN1TMPL_EXT_NAME,_Set,a_Name)(RT_CONCAT(P,RTASN1TMPL_TYPE) pThis, \
+ RT_CONCAT(PC,a_Type) pToClone,\
+ PCRTASN1ALLOCATORVTABLE pAllocator) \
+{ \
+ AssertPtr(pThis); AssertPtrNull(pToClone); Assert(!pToClone || RT_CONCAT(a_Api,_IsPresent)(pToClone)); \
+ if (RT_CONCAT(a_Api,_IsPresent)(&pThis->a_Name)) \
+ RT_CONCAT(a_Api,_Delete)(&pThis->a_Name); \
+ \
+ int rc; \
+ if (pToClone) \
+ rc = RT_CONCAT(a_Api,_Clone)(&pThis->a_Name, pToClone, pAllocator); \
+ else \
+ rc = RT_CONCAT(a_Api,_Init)(&pThis->a_Name, pAllocator); \
+ if (RT_SUCCESS(rc)) \
+ { \
+ RTAsn1Core_ResetImplict(RT_CONCAT(a_Api,_GetAsn1Core)(&pThis->a_Name)); /* probably not needed */ \
+ rc = RTAsn1Core_SetTagAndFlags(RT_CONCAT(a_Api,_GetAsn1Core)(&pThis->a_Name), \
+ a_uTag, RTASN1TMPL_ITAG_F_EXPAND(a_fClue)); \
+ } \
+ return rc; \
+} RTASN1TMPL_SEMICOLON_DUMMY()
+
+# define RTASN1TMPL_MEMBER_OPT_XTAG_EX(a_TnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_uTag, a_Constraints) \
+RTASN1TMPL_DECL(int) RT_CONCAT3(RTASN1TMPL_EXT_NAME,_Set,a_Name)(RT_CONCAT(P,RTASN1TMPL_TYPE) pThis, \
+ RT_CONCAT(PC,a_Type) pToClone,\
+ PCRTASN1ALLOCATORVTABLE pAllocator) \
+{ \
+ AssertPtr(pThis); AssertPtrNull(pToClone); Assert(!pToClone || RT_CONCAT(a_Api,_IsPresent)(pToClone)); \
+ if (RTASN1CORE_IS_PRESENT(&pThis->a_TnNm.a_CtxTagN.Asn1Core)) \
+ RT_CONCAT(a_Api,_Delete)(&pThis->a_TnNm.a_Name); \
+ \
+ int rc = RT_CONCAT3(RTAsn1ContextTag,a_uTag,_Init)(&pThis->a_TnNm.a_CtxTagN, \
+ &RT_CONCAT5(g_,RTASN1TMPL_INT_NAME,_XTAG_,a_Name,_Vtable), \
+ pAllocator); \
+ if (RT_SUCCESS(rc)) \
+ { \
+ if (pToClone) \
+ rc = RT_CONCAT(a_Api,_Clone)(&pThis->a_TnNm.a_Name, pToClone, pAllocator); \
+ else \
+ rc = RT_CONCAT(a_Api,_Init)(&pThis->a_TnNm.a_Name, pAllocator); \
+ if (RT_SUCCESS(rc) && pToClone) \
+ RTAsn1Core_ResetImplict(RT_CONCAT(a_Api,_GetAsn1Core)(&pThis->a_TnNm.a_Name)); \
+ } \
+ return rc; \
+} RTASN1TMPL_SEMICOLON_DUMMY()
+
+# define RTASN1TMPL_BEGIN_PCHOICE() RTASN1TMPL_SEMICOLON_DUMMY()
+
+# define RTASN1TMPL_PCHOICE_ITAG_EX(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api, a_fClue, a_Constraints) \
+RTASN1TMPL_DECL(int) RT_CONCAT3(RTASN1TMPL_EXT_NAME,_Set,a_Name)(RT_CONCAT(P,RTASN1TMPL_TYPE) pThis, \
+ RT_CONCAT(PC,a_Type) pToClone,\
+ PCRTASN1ALLOCATORVTABLE pAllocator) \
+{ \
+ AssertPtrNull(pToClone); AssertPtr(pThis); \
+ RT_CONCAT(RTASN1TMPL_EXT_NAME,_Delete)(pThis); /* See _Init. */ \
+ RTAsn1Dummy_InitEx(&pThis->Dummy); \
+ pThis->Dummy.Asn1Core.pOps = &RT_CONCAT3(g_,RTASN1TMPL_INT_NAME,_Vtable); \
+ RTAsn1MemInitAllocation(&pThis->Allocation, pAllocator); \
+ pThis->enmChoice = a_enmChoice; \
+ int rc = RTAsn1MemAllocZ(&pThis->Allocation, (void **)&pThis->a_PtrName, sizeof(*pThis->a_PtrName)); \
+ if (RT_SUCCESS(rc)) \
+ { \
+ if (pToClone) \
+ rc = RT_CONCAT(a_Api,_Clone)(pThis->a_PtrName, pToClone, pAllocator); \
+ else \
+ rc = RT_CONCAT(a_Api,_Init)(pThis->a_PtrName, pAllocator); \
+ if (RT_SUCCESS(rc)) \
+ { \
+ if (pToClone) \
+ RTAsn1Core_ResetImplict(RT_CONCAT(a_Api,_GetAsn1Core)(pThis->a_PtrName)); \
+ rc = RTAsn1Core_SetTagAndFlags(RT_CONCAT(a_Api,_GetAsn1Core)(pThis->a_PtrName), \
+ a_uTag, RTASN1TMPL_ITAG_F_EXPAND(a_fClue)); \
+ } \
+ } \
+ return rc; \
+} RTASN1TMPL_SEMICOLON_DUMMY()
+
+# define RTASN1TMPL_PCHOICE_XTAG_EX(a_uTag, a_enmChoice, a_PtrTnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_Constraints) \
+RTASN1TMPL_DECL(int) RT_CONCAT3(RTASN1TMPL_EXT_NAME,_Set,a_Name)(RT_CONCAT(P,RTASN1TMPL_TYPE) pThis, \
+ RT_CONCAT(PC,a_Type) pToClone,\
+ PCRTASN1ALLOCATORVTABLE pAllocator) \
+{ \
+ AssertPtr(pThis); AssertPtrNull(pToClone); Assert(!pToClone || RT_CONCAT(a_Api,_IsPresent)(pToClone)); \
+ RT_CONCAT(RTASN1TMPL_EXT_NAME,_Delete)(pThis); /* See _Init. */ \
+ RTAsn1Dummy_InitEx(&pThis->Dummy); \
+ pThis->Dummy.Asn1Core.pOps = &RT_CONCAT3(g_,RTASN1TMPL_INT_NAME,_Vtable); \
+ RTAsn1MemInitAllocation(&pThis->Allocation, pAllocator); \
+ pThis->enmChoice = a_enmChoice; \
+ int rc = RTAsn1MemAllocZ(&pThis->Allocation, (void **)&pThis->a_PtrTnNm, sizeof(*pThis->a_PtrTnNm)); \
+ if (RT_SUCCESS(rc)) \
+ { \
+ rc = RT_CONCAT3(RTAsn1ContextTag,a_uTag,_Init)(&pThis->a_PtrTnNm->a_CtxTagN, \
+ &RT_CONCAT5(g_,RTASN1TMPL_INT_NAME,_PCHOICE_XTAG_,a_Name,_Vtable), \
+ pAllocator); \
+ if (RT_SUCCESS(rc)) \
+ { \
+ if (pToClone) \
+ rc = RT_CONCAT(a_Api,_Clone)(&pThis->a_PtrTnNm->a_Name, pToClone, pAllocator); \
+ else \
+ rc = RT_CONCAT(a_Api,_Init)(&pThis->a_PtrTnNm->a_Name, pAllocator); \
+ if (RT_SUCCESS(rc) && pToClone) \
+ RTAsn1Core_ResetImplict(RT_CONCAT(a_Api,_GetAsn1Core)(&pThis->a_PtrTnNm->a_Name)); \
+ } \
+ } \
+ return rc; \
+} RTASN1TMPL_SEMICOLON_DUMMY()
+
+# define RTASN1TMPL_END_PCHOICE() RTASN1TMPL_SEMICOLON_DUMMY()
+
+
+# define RTASN1TMPL_SEQ_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_SET_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SEMICOLON_DUMMY()
+
+
+#elif RTASN1TMPL_PASS == RTASN1TMPL_PASS_ARRAY
+/*
+ *
+ * Array operations.
+ *
+ */
+# define RTASN1TMPL_BEGIN_SEQCORE() RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_BEGIN_SETCORE() RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_MEMBER_EX(a_Name, a_Type, a_Api, a_Constraints) RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_MEMBER_DYN_BEGIN(a_ObjIdMembNm, a_enmType, a_enmMembNm, a_Allocation) RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_MEMBER_DYN_END(a_ObjIdMembNm, a_enmType, a_enmMembNm, a_Allocation) RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_END_SEQCORE() RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_END_SETCORE() RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_BEGIN_PCHOICE() RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_PCHOICE_ITAG_EX(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api, a_fClue, a_Constraints) \
+ RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_PCHOICE_XTAG_EX(a_uTag, a_enmChoice, a_PtrTnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_Constraints) \
+ RTASN1TMPL_SEMICOLON_DUMMY()
+# define RTASN1TMPL_END_PCHOICE() RTASN1TMPL_SEMICOLON_DUMMY()
+
+# define RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi) \
+ RTASN1TMPL_DECL(int) RT_CONCAT(RTASN1TMPL_EXT_NAME,_Erase)(RT_CONCAT(P,RTASN1TMPL_TYPE) pThis, uint32_t iPosition) \
+ { \
+ /* Check and adjust iPosition. */ \
+ uint32_t const cItems = pThis->cItems; \
+ if (iPosition < cItems) \
+ { /* likely */ } \
+ else \
+ { \
+ AssertReturn(iPosition == UINT32_MAX, VERR_OUT_OF_RANGE); \
+ AssertReturn(cItems > 0, VERR_OUT_OF_RANGE); \
+ iPosition = cItems - 1; \
+ } \
+ \
+ /* Delete the entry instance. */ \
+ RT_CONCAT(P, a_ItemType) pErased = pThis->papItems[iPosition]; \
+ if (RT_CONCAT(a_ItemApi,_IsPresent)(pErased)) \
+ RT_CONCAT(a_ItemApi,_Delete)(pErased); \
+ \
+ /* If not the final entry, shift the other entries up and place the erased on at the end. */ \
+ if (iPosition < cItems - 1) \
+ { \
+ memmove(&pThis->papItems[iPosition], &pThis->papItems[iPosition + 1], (cItems - iPosition - 1) * sizeof(void *)); \
+ pThis->papItems[cItems - 1] = pErased; \
+ } \
+ /* Commit the new array size. */ \
+ pThis->cItems = cItems - 1; \
+ \
+ /* Call the allocator to resize the array (ignore return). */ \
+ RTAsn1MemResizeArray(&pThis->Allocation, (void ***)&pThis->papItems, cItems - 1, cItems); \
+ return VINF_SUCCESS; \
+ } \
+ \
+ RTASN1TMPL_DECL(int) RT_CONCAT(RTASN1TMPL_EXT_NAME,_InsertEx)(RT_CONCAT(P,RTASN1TMPL_TYPE) pThis, uint32_t iPosition, \
+ RT_CONCAT(PC, a_ItemType) pToClone, \
+ PCRTASN1ALLOCATORVTABLE pAllocator, uint32_t *piActualPos) \
+ { \
+ /* Check and adjust iPosition. */ \
+ uint32_t const cItems = pThis->cItems; \
+ if (iPosition <= cItems) \
+ { /* likely */ } \
+ else \
+ { \
+ AssertReturn(iPosition == UINT32_MAX, VERR_OUT_OF_RANGE); \
+ iPosition = cItems; \
+ } \
+ \
+ /* Ensure we've got space in the array. */ \
+ int rc = RTAsn1MemResizeArray(&pThis->Allocation, (void ***)&pThis->papItems, cItems, cItems + 1); \
+ if (RT_SUCCESS(rc)) \
+ { \
+ /* Initialize the new entry (which is currently at the end of the array) either with defaults or as a clone. */ \
+ RT_CONCAT(P,a_ItemType) pInserted = pThis->papItems[cItems]; \
+ if (RT_CONCAT(a_ItemApi,_IsPresent)(pToClone)) \
+ rc = RT_CONCAT(a_ItemApi,_Clone)(pInserted, pToClone, pAllocator); \
+ else \
+ rc = RT_CONCAT(a_ItemApi,_Init)(pInserted, pAllocator); \
+ if (RT_SUCCESS(rc)) \
+ { \
+ pThis->cItems = cItems + 1; \
+ \
+ /* If not inserting at the end of the array, shift existing items out of the way and insert the new as req. */ \
+ if (iPosition != cItems) \
+ { \
+ memmove(&pThis->papItems[iPosition + 1], &pThis->papItems[iPosition], (cItems - iPosition) * sizeof(void *)); \
+ pThis->papItems[iPosition] = pInserted; \
+ } \
+ \
+ /* Done! */ \
+ if (piActualPos) \
+ *piActualPos = iPosition; \
+ return VINF_SUCCESS; \
+ } \
+ RTAsn1MemResizeArray(&pThis->Allocation, (void ***)&pThis->papItems, cItems + 1, cItems); \
+ } \
+ return rc; \
+ } RTASN1TMPL_SEMICOLON_DUMMY()
+
+# define RTASN1TMPL_SEQ_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi)
+# define RTASN1TMPL_SET_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi)
+
+
+#elif RTASN1TMPL_PASS == RTASN1TMPL_PASS_COMPARE
+/*
+ *
+ * Compare two instances of the type.
+ *
+ */
+# define RTASN1TMPL_BEGIN_COMMON() \
+RTASN1TMPL_DECL(int) RT_CONCAT(RTASN1TMPL_EXT_NAME,_Compare)(RT_CONCAT(PC,RTASN1TMPL_TYPE) pLeft, \
+ RT_CONCAT(PC,RTASN1TMPL_TYPE) pRight) \
+{ \
+ if (!RT_CONCAT(RTASN1TMPL_EXT_NAME,_IsPresent)(pLeft)) \
+ return 0 - (int)RT_CONCAT(RTASN1TMPL_EXT_NAME,_IsPresent)(pRight); \
+ if (!RT_CONCAT(RTASN1TMPL_EXT_NAME,_IsPresent)(pRight)) \
+ return -1; \
+ int iDiff = 0
+
+# define RTASN1TMPL_END_COMMON() \
+ return iDiff; \
+} RTASN1TMPL_SEMICOLON_DUMMY()
+
+# define RTASN1TMPL_BEGIN_SEQCORE() RTASN1TMPL_BEGIN_COMMON()
+# define RTASN1TMPL_BEGIN_SETCORE() RTASN1TMPL_BEGIN_COMMON()
+# define RTASN1TMPL_MEMBER_EX(a_Name, a_Type, a_Api, a_Constraints) \
+ if (!iDiff) \
+ iDiff = RT_CONCAT(a_Api,_Compare)(&pLeft->a_Name, &pRight->a_Name)
+# define RTASN1TMPL_MEMBER_DYN_BEGIN(a_ObjIdMembNm, a_enmType, a_enmMembNm, a_Allocation) \
+ if (!iDiff && pLeft->a_enmMembNm != pRight->a_enmMembNm) \
+ iDiff = pLeft->a_enmMembNm < pRight->a_enmMembNm ? -1 : 1; \
+ else if (!iDiff) \
+ switch (pLeft->a_enmMembNm) \
+ { \
+ default: break
+# define RTASN1TMPL_MEMBER_DYN_COMMON(a_UnionNm, a_PtrName, a_Type, a_Api, a_Allocation, a_enmMembNm, a_enmValue, a_IfStmt) \
+ case a_enmValue: iDiff = RT_CONCAT(a_Api,_Compare)(pLeft->a_UnionNm.a_PtrName, pRight->a_UnionNm.a_PtrName); break
+# define RTASN1TMPL_MEMBER_DYN_END(a_ObjIdMembNm, a_enmType, a_enmMembNm, a_Allocation) \
+ case RT_CONCAT(a_enmType,_NOT_PRESENT): break; \
+ }
+# define RTASN1TMPL_MEMBER_OPT_XTAG_EX(a_TnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_uTag, a_Constraints) \
+ if (!iDiff) \
+ { \
+ if (RTASN1CORE_IS_PRESENT(&pLeft->a_TnNm.a_CtxTagN.Asn1Core)) \
+ { \
+ if (RTASN1CORE_IS_PRESENT(&pRight->a_TnNm.a_CtxTagN.Asn1Core)) \
+ iDiff = RT_CONCAT(a_Api,_Compare)(&pLeft->a_TnNm.a_Name, &pRight->a_TnNm.a_Name); \
+ else \
+ iDiff = -1; \
+ } \
+ else \
+ iDiff = 0 - (int)RTASN1CORE_IS_PRESENT(&pRight->a_TnNm.a_CtxTagN.Asn1Core); \
+ } do { } while (0)
+# define RTASN1TMPL_END_SEQCORE() RTASN1TMPL_END_COMMON()
+# define RTASN1TMPL_END_SETCORE() RTASN1TMPL_END_COMMON()
+
+# define RTASN1TMPL_BEGIN_PCHOICE() \
+ RTASN1TMPL_BEGIN_COMMON(); \
+ if (pLeft->enmChoice != pRight->enmChoice) \
+ return pLeft->enmChoice < pRight->enmChoice ? -1 : 1; \
+ switch (pLeft->enmChoice) \
+ { \
+ default: break
+# define RTASN1TMPL_PCHOICE_ITAG_EX(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api, a_fClue, a_Constraints) \
+ case a_enmChoice: iDiff = RT_CONCAT(a_Api,_Compare)(pLeft->a_PtrName, pRight->a_PtrName); break
+# define RTASN1TMPL_PCHOICE_XTAG_EX(a_uTag, a_enmChoice, a_PtrTnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_Constraints) \
+ case a_enmChoice: iDiff = RT_CONCAT(a_Api,_Compare)(&pLeft->a_PtrTnNm->a_Name, &pRight->a_PtrTnNm->a_Name); break
+#define RTASN1TMPL_END_PCHOICE() \
+ } \
+ RTASN1TMPL_END_COMMON()
+
+
+# define RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi) \
+ RTASN1TMPL_BEGIN_COMMON(); \
+ uint32_t cItems = pLeft->cItems; \
+ if (cItems == pRight->cItems) \
+ for (uint32_t i = 0; iDiff == 0 && i < cItems; i++) \
+ iDiff = RT_CONCAT(a_ItemApi,_Compare)(pLeft->papItems[i], pRight->papItems[i]); \
+ else \
+ iDiff = cItems < pRight->cItems ? -1 : 1; \
+ RTASN1TMPL_END_COMMON()
+# define RTASN1TMPL_SEQ_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi)
+# define RTASN1TMPL_SET_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi)
+
+
+
+#elif RTASN1TMPL_PASS == RTASN1TMPL_PASS_CHECK_SANITY
+/*
+ *
+ * Checks the sanity of the type.
+ *
+ */
+# ifndef RTASN1TMPL_SANITY_CHECK_EXPR
+# define RTASN1TMPL_SANITY_CHECK_EXPR() VINF_SUCCESS
+# endif
+# define RTASN1TMPL_BEGIN_COMMON() \
+RTASN1TMPL_DECL(int) RT_CONCAT(RTASN1TMPL_EXT_NAME,_CheckSanity)(RT_CONCAT(PC,RTASN1TMPL_TYPE) pThis, uint32_t fFlags, \
+ PRTERRINFO pErrInfo, const char *pszErrorTag) \
+{ \
+ if (RT_LIKELY(RT_CONCAT(RTASN1TMPL_EXT_NAME,_IsPresent)(pThis))) \
+ { /* likely */ } \
+ else \
+ return RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE, "%s: Missing (%s).", pszErrorTag, RT_XSTR(RTASN1TMPL_TYPE)); \
+ int rc = VINF_SUCCESS
+
+# define RTASN1TMPL_END_COMMON() \
+ if (RT_SUCCESS(rc)) \
+ rc = (RTASN1TMPL_SANITY_CHECK_EXPR()); \
+ return rc; \
+} RTASN1TMPL_SEMICOLON_DUMMY()
+
+# define RTASN1TMPL_BEGIN_SEQCORE() RTASN1TMPL_BEGIN_COMMON()
+# define RTASN1TMPL_BEGIN_SETCORE() RTASN1TMPL_BEGIN_COMMON()
+# define RTASN1TMPL_MEMBER_EX(a_Name, a_Type, a_Api, a_Constraints) \
+ if (RT_SUCCESS(rc)) \
+ { \
+ if (RT_LIKELY(RT_CONCAT(a_Api,_IsPresent)(&pThis->a_Name))) \
+ { \
+ rc = RT_CONCAT(a_Api,_CheckSanity)(&pThis->a_Name, fFlags & RTASN1_CHECK_SANITY_F_COMMON_MASK, \
+ pErrInfo, RT_XSTR(RTASN1TMPL_TYPE) "::" #a_Name); \
+ { a_Constraints } \
+ } \
+ else \
+ rc = RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE, "%s: Missing member %s (%s).", \
+ pszErrorTag, #a_Name, RT_XSTR(RTASN1TMPL_TYPE)); \
+ } do {} while (0)
+# define RTASN1TMPL_MEMBER_DYN_BEGIN(a_ObjIdMembNm, a_enmType, a_enmMembNm, a_Allocation) \
+ if (RT_SUCCESS(rc)) \
+ switch (pThis->a_enmMembNm) \
+ { \
+ default: \
+ rc = RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE, \
+ "%s: Invalid " #a_enmMembNm " value: %d", pszErrorTag, pThis->a_enmMembNm); \
+ break
+# define RTASN1TMPL_MEMBER_DYN_COMMON(a_UnionNm, a_PtrName, a_Type, a_Api, a_Allocation, a_enmMembNm, a_enmValue, a_IfStmt) \
+ case a_enmValue: \
+ rc = RT_CONCAT(a_Api,_CheckSanity)(pThis->a_UnionNm.a_PtrName, fFlags & RTASN1_CHECK_SANITY_F_COMMON_MASK, \
+ pErrInfo, RT_XSTR(RTASN1TMPL_TYPE) "::" #a_UnionNm "." #a_PtrName); \
+ break
+# define RTASN1TMPL_MEMBER_DYN_END(a_ObjIdMembNm, a_enmType, a_enmMembNm, a_Allocation) \
+ case RT_CONCAT(a_enmType,_NOT_PRESENT): \
+ rc = RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE, \
+ "%s: Invalid " #a_enmMembNm " value: " #a_enmType "_NOT_PRESENT", pszErrorTag); \
+ break; \
+ }
+# define RTASN1TMPL_MEMBER_OPT_EX(a_Name, a_Type, a_Api, a_Constraints) \
+ if (RT_SUCCESS(rc) && RT_CONCAT(a_Api,_IsPresent)(&pThis->a_Name)) \
+ { \
+ rc = RT_CONCAT(a_Api,_CheckSanity)(&pThis->a_Name, fFlags & RTASN1_CHECK_SANITY_F_COMMON_MASK, \
+ pErrInfo, RT_XSTR(RTASN1TMPL_TYPE) "::" #a_Name); \
+ { a_Constraints } \
+ }
+# define RTASN1TMPL_MEMBER_OPT_XTAG_EX(a_TnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_uTag, a_Constraints) \
+ if (RT_SUCCESS(rc)) \
+ { \
+ bool const fOuterPresent = RTASN1CORE_IS_PRESENT(&pThis->a_TnNm.a_CtxTagN.Asn1Core); \
+ bool const fInnerPresent = RT_CONCAT(a_Api,_IsPresent)(&pThis->a_TnNm.a_Name); \
+ if (fOuterPresent && fInnerPresent) \
+ { \
+ rc = RT_CONCAT(a_Api,_CheckSanity)(&pThis->a_TnNm.a_Name, fFlags & RTASN1_CHECK_SANITY_F_COMMON_MASK, \
+ pErrInfo, RT_XSTR(RTASN1TMPL_TYPE) "::" #a_Name); \
+ { a_Constraints } \
+ } \
+ else if (RT_LIKELY(RTASN1CORE_IS_PRESENT(&pThis->a_TnNm.a_CtxTagN.Asn1Core) == fInnerPresent)) \
+ { /* likely */ } \
+ else \
+ rc = RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE, \
+ "%s::" #a_TnNm "." #a_Name ": Explict tag precense mixup; " #a_CtxTagN "=%d " #a_Name "=%d.", \
+ pszErrorTag, fOuterPresent, fInnerPresent); \
+ } do { } while (0)
+# define RTASN1TMPL_END_SEQCORE() RTASN1TMPL_END_COMMON()
+# define RTASN1TMPL_END_SETCORE() RTASN1TMPL_END_COMMON()
+
+
+# define RTASN1TMPL_BEGIN_PCHOICE() \
+ RTASN1TMPL_BEGIN_COMMON(); \
+ switch (pThis->enmChoice) \
+ { \
+ default: \
+ rc = RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE, \
+ "%s: Invalid enmChoice value: %d", pszErrorTag, pThis->enmChoice); \
+ break
+# define RTASN1TMPL_PCHOICE_ITAG_EX(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api, a_fClue, a_Constraints) \
+ case a_enmChoice: \
+ if (pThis->a_PtrName && RT_CONCAT(a_Api,_IsPresent)(pThis->a_PtrName)) \
+ { \
+ PCRTASN1CORE pCore = RT_CONCAT(a_Api,_GetAsn1Core)(pThis->a_PtrName); \
+ if (pCore->uTag == a_uTag && pCore->fClass == RTASN1TMPL_ITAG_F_EXPAND(a_fClue)) \
+ { \
+ rc = RT_CONCAT(a_Api,_CheckSanity)(pThis->a_PtrName, fFlags & RTASN1_CHECK_SANITY_F_COMMON_MASK, \
+ pErrInfo, RT_XSTR(RTASN1TMPL_TYPE) "::" #a_Name); \
+ { a_Constraints } \
+ } \
+ else \
+ rc = RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE, \
+ "%s::" #a_Name ": Tag/class mismatch: expected %#x/%#x, actual %#x/%x.", \
+ pszErrorTag, a_uTag, RTASN1TMPL_ITAG_F_EXPAND(a_fClue), pCore->uTag, pCore->fClass); \
+ } \
+ else \
+ rc = RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE, "%s::" #a_Name ": Not present.", pszErrorTag); \
+ break
+# define RTASN1TMPL_PCHOICE_XTAG_EX(a_uTag, a_enmChoice, a_PtrTnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_Constraints) \
+ case a_enmChoice: \
+ if ( pThis->a_PtrTnNm \
+ && RTASN1CORE_IS_PRESENT(&(pThis->a_PtrTnNm->a_CtxTagN.Asn1Core)) \
+ && RT_CONCAT(a_Api,_IsPresent)(&pThis->a_PtrTnNm->a_Name) ) \
+ { \
+ rc = RT_CONCAT(a_Api,_CheckSanity)(&pThis->a_PtrTnNm->a_Name, fFlags & RTASN1_CHECK_SANITY_F_COMMON_MASK, \
+ pErrInfo, RT_XSTR(RTASN1TMPL_TYPE) "::" #a_Name); \
+ { a_Constraints } \
+ } \
+ else \
+ rc = RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE, "%s::" #a_Name ": Not present.", pszErrorTag); \
+ break
+#define RTASN1TMPL_END_PCHOICE() \
+ } \
+ RTASN1TMPL_END_COMMON()
+
+
+# define RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi) \
+ RTASN1TMPL_BEGIN_COMMON(); \
+ for (uint32_t i = 0; RT_SUCCESS(rc) && i < pThis->cItems; i++) \
+ rc = RT_CONCAT(a_ItemApi,_CheckSanity)(pThis->papItems[i], fFlags & RTASN1_CHECK_SANITY_F_COMMON_MASK, \
+ pErrInfo, RT_XSTR(RTASN1TMPL_TYPE) "::papItems[#]"); \
+ if (RT_SUCCESS(rc)) { RTASN1TMPL_SET_SEQ_EXEC_CHECK_SANITY(); } \
+ RTASN1TMPL_END_COMMON()
+# define RTASN1TMPL_SEQ_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi)
+# define RTASN1TMPL_SET_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi)
+
+/* The constraints. */
+# define RTASN1TMPL_MEMBER_CONSTR_MIN_MAX(a_Name, a_Type, a_Api, cbMin, cbMax, a_MoreConstraints) \
+ if (RT_SUCCESS(rc) && ((cbMin) != 0 || (cbMax) != UINT32_MAX)) \
+ { \
+ PCRTASN1CORE pCore = RT_CONCAT(a_Api,_GetAsn1Core)(&pThis->a_Name); \
+ if (RT_LIKELY(pCore->cb >= (cbMin) && pCore->cb <= (cbMax))) \
+ { /* likely */ } \
+ else \
+ rc = RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE, \
+ "%s::" #a_Name ": Content size is out of range: %#x not in {%#x..%#x}", \
+ pszErrorTag, pCore->cb, cbMin, cbMax); \
+ } \
+ { a_MoreConstraints }
+
+# define RTASN1TMPL_MEMBER_CONSTR_BITSTRING_MIN_MAX(a_Name, cMinBits, cMaxBits, a_MoreConstraints) \
+ if (RT_SUCCESS(rc) && ((cMinBits) != 0 || (cMaxBits) != UINT32_MAX)) \
+ { \
+ if (RT_LIKELY( ((cMinBits) == 0 ? true : pThis->a_Name.cBits + 1U >= (cMinBits) + 1U /* warning avoiding */) \
+ && ((cMaxBits) == UINT32_MAX ? true : pThis->a_Name.cBits + 1U <= (cMaxBits) + 1U /* ditto */) ) ) \
+ { /* likely */ } \
+ else \
+ rc = RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE, \
+ "%s::" #a_Name ": Bit size is out of range: %#x not in {%#x..%#x}", \
+ pszErrorTag, pThis->a_Name.cBits, cMinBits, cMaxBits); \
+ } \
+ { a_MoreConstraints }
+
+# define RTASN1TMPL_MEMBER_CONSTR_U64_MIN_MAX(a_Name, uMin, uMax, a_MoreConstraints) \
+ if (RT_SUCCESS(rc)) \
+ { \
+ if (RT_LIKELY( RTAsn1Integer_UnsignedCompareWithU64(&pThis->a_Name, uMin) >= 0 \
+ && RTAsn1Integer_UnsignedCompareWithU64(&pThis->a_Name, uMax) <= 0) ) \
+ { /* likely */ } \
+ else \
+ rc = RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE, \
+ "%s::" #a_Name ": Out of range: %#x not in {%#llx..%#llx}", \
+ pszErrorTag, pThis->a_Name.Asn1Core.cb > 8 ? UINT64_MAX : pThis->a_Name.uValue.u, \
+ (uint64_t)(uMin), (uint64_t)(uMax)); \
+ } \
+ { a_MoreConstraints }
+
+# define RTASN1TMPL_MEMBER_CONSTR_PRESENT(a_Name, a_Api, a_MoreConstraints) \
+ if (RT_SUCCESS(rc)) \
+ { \
+ if (RT_LIKELY(RT_CONCAT(a_Api,_IsPresent)(&pThis->a_Name))) \
+ { /* likely */ } \
+ else \
+ rc = RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE, "%s::" #a_Name ": Missing.", pszErrorTag); \
+ } \
+ { a_MoreConstraints }
+
+
+
+# define RTASN1TMPL_EXEC_CHECK_SANITY(a_Expr) if (RT_SUCCESS(rc)) { a_Expr; }
+
+
+#elif RTASN1TMPL_PASS == RTASN1TMPL_PASS_DELETE
+/*
+ *
+ * Delete wrappers.
+ *
+ */
+# define RTASN1TMPL_BEGIN_COMMON() \
+RTASN1TMPL_DECL(void) RT_CONCAT(RTASN1TMPL_EXT_NAME,_Delete)(RT_CONCAT(P,RTASN1TMPL_TYPE) pThis) \
+{ \
+ if (RT_CONCAT(RTASN1TMPL_EXT_NAME,_IsPresent)(pThis)) \
+ { do { } while (0)
+
+# define RTASN1TMPL_END_COMMON() \
+ } \
+ RT_ZERO(*pThis); \
+} RTASN1TMPL_SEMICOLON_DUMMY()
+
+# define RTASN1TMPL_BEGIN_SEQCORE() RTASN1TMPL_BEGIN_COMMON()
+# define RTASN1TMPL_BEGIN_SETCORE() RTASN1TMPL_BEGIN_COMMON()
+# define RTASN1TMPL_MEMBER_EX(a_Name, a_Type, a_Api, a_Constraints) RT_CONCAT(a_Api,_Delete)(&pThis->a_Name)
+# define RTASN1TMPL_MEMBER_DYN_BEGIN(a_ObjIdMembNm, a_enmType, a_enmMembNm, a_Allocation) \
+ switch (pThis->a_enmMembNm) \
+ { \
+ default: break
+# define RTASN1TMPL_MEMBER_DYN_COMMON(a_UnionNm, a_PtrName, a_Type, a_Api, a_Allocation, a_enmMembNm, a_enmValue, a_IfStmt) \
+ case a_enmValue: \
+ if (pThis->a_UnionNm.a_PtrName) \
+ { \
+ RT_CONCAT(a_Api,_Delete)(pThis->a_UnionNm.a_PtrName); \
+ RTAsn1MemFree(&pThis->Allocation, pThis->a_UnionNm.a_PtrName); \
+ pThis->a_UnionNm.a_PtrName = NULL; \
+ } \
+ break
+# define RTASN1TMPL_MEMBER_DYN_END(a_ObjIdMembNm, a_enmType, a_enmMembNm, a_Allocation) \
+ }
+# define RTASN1TMPL_END_SEQCORE() RTASN1TMPL_END_COMMON()
+# define RTASN1TMPL_END_SETCORE() RTASN1TMPL_END_COMMON()
+
+
+# define RTASN1TMPL_BEGIN_PCHOICE() \
+ RTASN1TMPL_BEGIN_COMMON(); \
+ switch (pThis->enmChoice) \
+ { \
+ default: break
+# define RTASN1TMPL_PCHOICE_ITAG_EX(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api, a_fClue, a_Constraints) \
+ case a_enmChoice: \
+ if (pThis->a_PtrName) \
+ { \
+ RT_CONCAT(a_Api,_Delete)(pThis->a_PtrName); \
+ RTAsn1MemFree(&pThis->Allocation, pThis->a_PtrName); \
+ pThis->a_PtrName = NULL; \
+ } \
+ break
+# define RTASN1TMPL_PCHOICE_XTAG_EX(a_uTag, a_enmChoice, a_PtrTnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_Constraints) \
+ case a_enmChoice: \
+ if (pThis->a_PtrTnNm) \
+ { \
+ RT_CONCAT(a_Api,_Delete)(&pThis->a_PtrTnNm->a_Name); \
+ RTAsn1MemFree(&pThis->Allocation, pThis->a_PtrTnNm); \
+ pThis->a_PtrTnNm = NULL; \
+ } \
+ break
+# define RTASN1TMPL_END_PCHOICE() \
+ } \
+ RTASN1TMPL_END_COMMON()
+
+
+# define RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi) \
+ RTASN1TMPL_BEGIN_COMMON(); \
+ uint32_t i = pThis->cItems; \
+ while (i-- > 0) \
+ RT_CONCAT(a_ItemApi,_Delete)(pThis->papItems[i]); \
+ RTAsn1MemFreeArray(&pThis->Allocation, (void **)pThis->papItems); \
+ pThis->papItems = NULL; \
+ pThis->cItems = 0; \
+ RTASN1TMPL_END_COMMON()
+# define RTASN1TMPL_SEQ_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi)
+# define RTASN1TMPL_SET_OF(a_ItemType, a_ItemApi) RTASN1TMPL_SET_SEQ_OF_COMMON(a_ItemType, a_ItemApi)
+
+
+#else
+# error "Invalid/missing RTASN1TMPL_PASS value."
+#endif
+
+
+
+/*
+ * Default aliases for simplified versions of macros if no specialization
+ * was required above.
+ */
+/* Non-optional members. */
+#ifndef RTASN1TMPL_MEMBER
+# define RTASN1TMPL_MEMBER(a_Name, a_Type, a_Api) \
+ RTASN1TMPL_MEMBER_EX(a_Name, a_Type, a_Api, RT_NOTHING)
+#endif
+
+#ifndef RTASN1TMPL_MEMBER_UTF8_STRING_MIN_MAX
+# define RTASN1TMPL_MEMBER_UTF8_STRING_MIN_MAX(a_Name) \
+ RTASN1TMPL_MEMBER(a_Name, RTASN1STRING, RTAsn1String)
+#endif
+#ifndef RTASN1TMPL_MEMBER_UTF8_STRING
+# define RTASN1TMPL_MEMBER_UTF8_STRING(a_Name) \
+ RTASN1TMPL_MEMBER_UTF8_STRING_MIN_MAX(a_Name, 0, UINT32_MAX)
+#endif
+
+#ifndef RTASN1TMPL_MEMBER_STRING_MIN_MAX
+# define RTASN1TMPL_MEMBER_STRING_MIN_MAX(a_Name, a_cbMin, a_cbMax) \
+ RTASN1TMPL_MEMBER(a_Name, RTASN1STRING, RTAsn1String)
+#endif
+#ifndef RTASN1TMPL_MEMBER_STRING
+# define RTASN1TMPL_MEMBER_STRING(a_Name) \
+ RTASN1TMPL_MEMBER_STRING_MIN_MAX(a_Name, 0, UINT32_MAX)
+#endif
+#ifndef RTASN1TMPL_MEMBER_XTAG_EX
+# define RTASN1TMPL_MEMBER_XTAG_EX(a_TnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_uTag, a_Constraints) \
+ RTASN1TMPL_MEMBER_EX(a_TnNm.a_Name, a_Type, a_Api, a_Constraints RT_NOTHING)
+#endif
+
+/* Any/dynamic members. */
+#ifndef RTASN1TMPL_MEMBER_DYN_BEGIN
+# define RTASN1TMPL_MEMBER_DYN_BEGIN(a_ObjIdMembNm, a_enmType, a_enmMembNm, a_Allocation) do { } while (0)
+#endif
+#ifndef RTASN1TMPL_MEMBER_DYN_END
+# define RTASN1TMPL_MEMBER_DYN_END(a_ObjIdMembNm, a_enmType, a_enmMembNm, a_Allocation) do { } while (0)
+#endif
+#ifndef RTASN1TMPL_MEMBER_DYN_COMMON
+# define RTASN1TMPL_MEMBER_DYN_COMMON(a_UnionNm, a_PtrName, a_Type, a_Api, a_Allocation, a_enmMembNm, a_enmValue, a_IfStmt) \
+ RTASN1TMPL_MEMBER(a_UnionNm.a_PtrName, a_Type, a_Api)
+#endif
+#ifndef RTASN1TMPL_MEMBER_DYN
+# define RTASN1TMPL_MEMBER_DYN(a_UnionNm, a_PtrName, a_Name, a_Type, a_Api, a_Allocation, a_ObjIdMembNm, a_enmMembNm, a_enmValue, a_szObjId) \
+ RTASN1TMPL_MEMBER_DYN_COMMON(a_UnionNm, a_PtrName, a_Type, a_Api, a_Allocation, a_enmMembNm, a_enmValue, if (RTAsn1ObjId_CompareWithString(&pThis->a_ObjIdMembNm, a_szObjId) == 0))
+#endif
+#ifndef RTASN1TMPL_MEMBER_DYN_DEFAULT
+# define RTASN1TMPL_MEMBER_DYN_DEFAULT(a_UnionNm, a_PtrName, a_Type, a_Api, a_Allocation, a_ObjIdMembNm, a_enmMembNm, a_enmValue) \
+ RTASN1TMPL_MEMBER_DYN_COMMON(a_UnionNm, a_PtrName, a_Type, a_Api, a_Allocation, a_enmMembNm, a_enmValue, RT_NOTHING)
+#endif
+
+/* Optional members. */
+#ifndef RTASN1TMPL_MEMBER_OPT_EX
+# define RTASN1TMPL_MEMBER_OPT_EX(a_Name, a_Type, a_Api, a_Constraints) \
+ RTASN1TMPL_MEMBER_EX(a_Name, a_Type, a_Api, a_Constraints RT_NOTHING)
+#endif
+#ifndef RTASN1TMPL_MEMBER_OPT
+# define RTASN1TMPL_MEMBER_OPT(a_Name, a_Type, a_Api) \
+ RTASN1TMPL_MEMBER_OPT_EX(a_Name, a_Type, a_Api, RT_NOTHING)
+#endif
+
+#ifndef RTASN1TMPL_MEMBER_OPT_XTAG_EX
+# define RTASN1TMPL_MEMBER_OPT_XTAG_EX(a_TnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_uTag, a_Constraints) \
+ RTASN1TMPL_MEMBER_OPT_EX(a_TnNm.a_Name, a_Type, a_Api, a_Constraints RT_NOTHING)
+#endif
+#ifndef RTASN1TMPL_MEMBER_OPT_XTAG
+# define RTASN1TMPL_MEMBER_OPT_XTAG(a_TnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_uTag) \
+ RTASN1TMPL_MEMBER_OPT_XTAG_EX(a_TnNm, a_CtxTagN, a_Name, a_Type, a_Api, a_uTag, RT_NOTHING)
+#endif
+
+#ifndef RTASN1TMPL_MEMBER_OPT_ITAG_EX
+# define RTASN1TMPL_MEMBER_OPT_ITAG_EX(a_Name, a_Type, a_Api, a_uTag, a_fClue, a_Constraints) \
+ RTASN1TMPL_MEMBER_OPT_EX(a_Name, a_Type, a_Api, a_Constraints RT_NOTHING)
+#endif
+#ifndef RTASN1TMPL_MEMBER_OPT_ITAG_UP
+# define RTASN1TMPL_MEMBER_OPT_ITAG_UP(a_Name, a_Type, a_Api, a_uTag) \
+ RTASN1TMPL_MEMBER_OPT_ITAG_EX(a_Name, a_Type, a_Api, a_uTag, RTASN1TMPL_ITAG_F_UP, RT_NOTHING)
+#endif
+#ifndef RTASN1TMPL_MEMBER_OPT_ITAG_UC
+# define RTASN1TMPL_MEMBER_OPT_ITAG_UC(a_Name, a_Type, a_Api, a_uTag) \
+ RTASN1TMPL_MEMBER_OPT_ITAG_EX(a_Name, a_Type, a_Api, a_uTag, RTASN1TMPL_ITAG_F_UC, RT_NOTHING)
+#endif
+#ifndef RTASN1TMPL_MEMBER_OPT_ITAG_CP
+# define RTASN1TMPL_MEMBER_OPT_ITAG_CP(a_Name, a_Type, a_Api, a_uTag) \
+ RTASN1TMPL_MEMBER_OPT_ITAG_EX(a_Name, a_Type, a_Api, a_uTag, RTASN1TMPL_ITAG_F_CP, RT_NOTHING)
+#endif
+#ifndef RTASN1TMPL_MEMBER_OPT_ITAG
+# define RTASN1TMPL_MEMBER_OPT_ITAG(a_Name, a_Type, a_Api, a_uTag) \
+ RTASN1TMPL_MEMBER_OPT_ITAG_EX(a_Name, a_Type, a_Api, a_uTag, RTASN1TMPL_ITAG_F_CC, RT_NOTHING)
+#endif
+#ifndef RTASN1TMPL_MEMBER_OPT_ANY
+# define RTASN1TMPL_MEMBER_OPT_ANY(a_Name, a_Type, a_Api) \
+ RTASN1TMPL_MEMBER_OPT_EX(a_Name, a_Type, a_Api, RT_NOTHING)
+#endif
+
+#ifndef RTASN1TMPL_MEMBER_DEF_ITAG_EX
+# define RTASN1TMPL_MEMBER_DEF_ITAG_EX(a_Name, a_Type, a_Api, a_uTag, a_fClue, a_DefVal, a_Constraints) \
+ RTASN1TMPL_MEMBER_OPT_ITAG_EX(a_Name, a_Type, a_Api, a_uTag, a_fClue, a_Constraints RT_NOTHING)
+#endif
+#ifndef RTASN1TMPL_MEMBER_DEF_ITAG_UP
+# define RTASN1TMPL_MEMBER_DEF_ITAG_UP(a_Name, a_Type, a_Api, a_uTag, a_DefVal) \
+ RTASN1TMPL_MEMBER_DEF_ITAG_EX(a_Name, a_Type, a_Api, a_uTag, RTASN1TMPL_ITAG_F_UP, a_DefVal, RT_NOTHING)
+#endif
+
+#ifndef RTASN1TMPL_MEMBER_OPT_ITAG_BITSTRING
+# define RTASN1TMPL_MEMBER_OPT_ITAG_BITSTRING(a_Name, a_cMaxBits, a_uTag) \
+ RTASN1TMPL_MEMBER_OPT_ITAG_EX(a_Name, RTASN1BITSTRING, RTAsn1BitString, a_uTag, RTASN1TMPL_ITAG_F_CP, \
+ RTASN1TMPL_MEMBER_CONSTR_BITSTRING_MIN_MAX(a_Name, 0, a_cMaxBits, RT_NOTHING))
+#endif
+
+#ifndef RTASN1TMPL_MEMBER_OPT_UTF8_STRING_EX
+# define RTASN1TMPL_MEMBER_OPT_UTF8_STRING_EX(a_Name, a_Constraints) \
+ RTASN1TMPL_MEMBER_OPT_EX(a_Name, RTASN1STRING, RTAsn1String, a_Constraints RT_NOTHING)
+#endif
+#ifndef RTASN1TMPL_MEMBER_OPT_UTF8_STRING
+# define RTASN1TMPL_MEMBER_OPT_UTF8_STRING(a_Name) \
+ RTASN1TMPL_MEMBER_OPT_UTF8_STRING_EX(a_Name, RT_NOTHING)
+#endif
+
+#ifndef RTASN1TMPL_MEMBER_OPT_STRING_EX
+# define RTASN1TMPL_MEMBER_OPT_STRING_EX(a_Name, a_Constraints) \
+ RTASN1TMPL_MEMBER_OPT_EX(a_Name, RTASN1STRING, RTAsn1String, a_Constraints RT_NOTHING)
+#endif
+#ifndef RTASN1TMPL_MEMBER_OPT_STRING
+# define RTASN1TMPL_MEMBER_OPT_STRING(a_Name) \
+ RTASN1TMPL_MEMBER_OPT_STRING_EX(a_Name, RT_NOTHING)
+#endif
+
+/* Pointer choices. */
+#ifndef RTASN1TMPL_PCHOICE_ITAG_UP
+# define RTASN1TMPL_PCHOICE_ITAG_UP(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api) \
+ RTASN1TMPL_PCHOICE_ITAG_EX(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api, RTASN1TMPL_ITAG_F_UP, RT_NOTHING)
+#endif
+#ifndef RTASN1TMPL_PCHOICE_ITAG_UC
+# define RTASN1TMPL_PCHOICE_ITAG_UC(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api) \
+ RTASN1TMPL_PCHOICE_ITAG_EX(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api, RTASN1TMPL_ITAG_F_UC, RT_NOTHING)
+#endif
+#ifndef RTASN1TMPL_PCHOICE_ITAG_CP
+# define RTASN1TMPL_PCHOICE_ITAG_CP(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api) \
+ RTASN1TMPL_PCHOICE_ITAG_EX(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api, RTASN1TMPL_ITAG_F_CP, RT_NOTHING)
+#endif
+#ifndef RTASN1TMPL_PCHOICE_ITAG
+# define RTASN1TMPL_PCHOICE_ITAG(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api) \
+ RTASN1TMPL_PCHOICE_ITAG_EX(a_uTag, a_enmChoice, a_PtrName, a_Name, a_Type, a_Api, RTASN1TMPL_ITAG_F_CC, RT_NOTHING)
+#endif
+
+#ifndef RTASN1TMPL_PCHOICE_XTAG
+# define RTASN1TMPL_PCHOICE_XTAG(a_uTag, a_enmChoice, a_PtrTnNm, a_CtxTagN, a_Name, a_Type, a_Api) \
+ RTASN1TMPL_PCHOICE_XTAG_EX(a_uTag, a_enmChoice, a_PtrTnNm, a_CtxTagN, a_Name, a_Type, a_Api, RT_NOTHING)
+#endif
+
+
+/*
+ * Constraints are only used in the sanity check pass, so provide subs for the
+ * others passes.
+ */
+#ifndef RTASN1TMPL_MEMBER_CONSTR_MIN_MAX
+# define RTASN1TMPL_MEMBER_CONSTR_MIN_MAX(a_Name, a_Type, a_Api, cbMin, cbMax, a_MoreConstraints)
+#endif
+#ifndef RTASN1TMPL_MEMBER_CONSTR_BITSTRING_MIN_MAX
+# define RTASN1TMPL_MEMBER_CONSTR_BITSTRING_MIN_MAX(a_Name, cMinBits, cMaxBits, a_MoreConstraints)
+#endif
+#ifndef RTASN1TMPL_MEMBER_CONSTR_U64_MIN_MAX
+# define RTASN1TMPL_MEMBER_CONSTR_U64_MIN_MAX(a_Name, uMin, uMax, a_MoreConstraints)
+#endif
+#ifndef RTASN1TMPL_MEMBER_CONSTR_PRESENT
+# define RTASN1TMPL_MEMBER_CONSTR_PRESENT(a_Name, a_Api, a_MoreConstraints)
+#endif
+
+
+/*
+ * Stub exec hacks.
+ */
+#ifndef RTASN1TMPL_EXEC_DECODE
+# define RTASN1TMPL_EXEC_DECODE(a_Expr) /* no semi colon allowed after this */
+#endif
+#ifndef RTASN1TMPL_EXEC_CLONE
+# define RTASN1TMPL_EXEC_CLONE(a_Expr) /* no semi colon allowed after this */
+#endif
+#ifndef RTASN1TMPL_EXEC_CHECK_SANITY
+# define RTASN1TMPL_EXEC_CHECK_SANITY(a_Expr) /* no semi colon allowed after this */
+#endif
+
+#define RTASN1TMPL_SET_SEQ_EXEC_CHECK_SANITY() do { } while (0)
+
+
+/*
+ * Generate the requested code.
+ */
+#ifndef RTASN1TMPL_TEMPLATE_FILE
+# error "No template file (RTASN1TMPL_TEMPLATE_FILE) is specified."
+#endif
+#include RTASN1TMPL_TEMPLATE_FILE
+
+
+
+/*
+ * Undo all the macros.
+ */
+#undef RTASN1TMPL_DECL
+#undef RTASN1TMPL_TYPE
+#undef RTASN1TMPL_EXT_NAME
+#undef RTASN1TMPL_INT_NAME
+
+#undef RTASN1TMPL_PASS
+
+#undef RTASN1TMPL_BEGIN_COMMON
+#undef RTASN1TMPL_END_COMMON
+#undef RTASN1TMPL_BEGIN_SEQCORE
+#undef RTASN1TMPL_BEGIN_SETCORE
+#undef RTASN1TMPL_MEMBER
+#undef RTASN1TMPL_MEMBER_EX
+#undef RTASN1TMPL_MEMBER_DYN_BEGIN
+#undef RTASN1TMPL_MEMBER_DYN
+#undef RTASN1TMPL_MEMBER_DYN_DEFAULT
+#undef RTASN1TMPL_MEMBER_DYN_COMMON
+#undef RTASN1TMPL_MEMBER_DYN_END
+#undef RTASN1TMPL_MEMBER_OPT
+#undef RTASN1TMPL_MEMBER_OPT_EX
+#undef RTASN1TMPL_MEMBER_OPT_ITAG
+#undef RTASN1TMPL_MEMBER_OPT_ITAG_EX
+#undef RTASN1TMPL_MEMBER_OPT_ITAG_CP
+#undef RTASN1TMPL_MEMBER_OPT_ITAG_UC
+#undef RTASN1TMPL_MEMBER_OPT_ITAG_UP
+#undef RTASN1TMPL_MEMBER_OPT_ITAG_BITSTRING
+#undef RTASN1TMPL_MEMBER_OPT_UTF8_STRING
+#undef RTASN1TMPL_MEMBER_OPT_UTF8_STRING_EX
+#undef RTASN1TMPL_MEMBER_OPT_XTAG
+#undef RTASN1TMPL_MEMBER_OPT_XTAG_EX
+#undef RTASN1TMPL_MEMBER_OPT_ANY
+#undef RTASN1TMPL_MEMBER_DEF_ITAG_UP
+#undef RTASN1TMPL_MEMBER_DEF_ITAG_EX
+#undef RTASN1TMPL_END_SEQCORE
+#undef RTASN1TMPL_END_SETCORE
+
+#undef RTASN1TMPL_BEGIN_PCHOICE
+#undef RTASN1TMPL_PCHOICE_ITAG
+#undef RTASN1TMPL_PCHOICE_ITAG_UP
+#undef RTASN1TMPL_PCHOICE_ITAG_CP
+#undef RTASN1TMPL_PCHOICE_ITAG_EX
+#undef RTASN1TMPL_PCHOICE_XTAG
+#undef RTASN1TMPL_PCHOICE_XTAG_EX
+#undef RTASN1TMPL_END_PCHOICE
+
+#undef RTASN1TMPL_SET_SEQ_OF_COMMON
+#undef RTASN1TMPL_SEQ_OF
+#undef RTASN1TMPL_SET_OF
+
+#undef RTASN1TMPL_VTABLE_FN_ENCODE_PREP
+#undef RTASN1TMPL_VTABLE_FN_ENCODE_WRITE
+
+#undef RTASN1TMPL_MEMBER_CONSTR_MIN_MAX
+#undef RTASN1TMPL_MEMBER_CONSTR_BITSTRING_MIN_MAX
+#undef RTASN1TMPL_MEMBER_CONSTR_U64_MIN_MAX
+#undef RTASN1TMPL_MEMBER_CONSTR_PRESENT
+
+#undef RTASN1TMPL_SANITY_CHECK_EXPR
+
+#undef RTASN1TMPL_EXEC_DECODE
+#undef RTASN1TMPL_EXEC_CLONE
+#undef RTASN1TMPL_EXEC_CHECK_SANITY
+
+#undef RTASN1TMPL_SET_SEQ_EXEC_CHECK_SANITY
+
diff --git a/include/iprt/asn1-generator-sanity.h b/include/iprt/asn1-generator-sanity.h
new file mode 100644
index 00000000..93ad5036
--- /dev/null
+++ b/include/iprt/asn1-generator-sanity.h
@@ -0,0 +1,38 @@
+/** @file
+ * IPRT - ASN.1 Code Generator, the Sanity Checking.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#define RTASN1TMPL_PASS RTASN1TMPL_PASS_CHECK_SANITY
+#include <iprt/asn1-generator-pass.h>
+
diff --git a/include/iprt/asn1.h b/include/iprt/asn1.h
new file mode 100644
index 00000000..19f200a6
--- /dev/null
+++ b/include/iprt/asn1.h
@@ -0,0 +1,2368 @@
+/** @file
+ * IPRT - Abstract Syntax Notation One (ASN.1).
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_asn1_h
+#define IPRT_INCLUDED_asn1_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/time.h>
+#include <iprt/stdarg.h>
+#include <iprt/errcore.h>
+#include <iprt/formats/asn1.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_asn1 RTAsn1 - Abstract Syntax Notation One
+ * @ingroup grp_rt
+ * @{
+ */
+
+
+/** Pointer to ASN.1 allocation information. */
+typedef struct RTASN1ALLOCATION *PRTASN1ALLOCATION;
+/** Pointer to ASN.1 array allocation information. */
+typedef struct RTASN1ARRAYALLOCATION *PRTASN1ARRAYALLOCATION;
+/** Pointer to a ASN.1 byte decoder cursor. */
+typedef struct RTASN1CURSOR *PRTASN1CURSOR;
+
+
+/**
+ * Sketch of a custom ASN.1 allocator virtual method table.
+ *
+ * Any information required by the allocator should be associated with this
+ * structure, i.e. use this as a kind of parent class. This saves storage in
+ * RTASN1ALLOCATORINFO and possibly reduces the number of parameters by one.
+ */
+typedef struct RTASN1ALLOCATORVTABLE
+{
+ /**
+ * Free a chunk of memory allocated by this allocator.
+ *
+ * @returns IPRT status code.
+ * @param pThis Pointer to the vtable structure.
+ * @param pAllocation Pointer to the allocation info structure.
+ * @param pv Pointer to the memory that shall be freed. Not NULL.
+ */
+ DECLCALLBACKMEMBER(void, pfnFree,(struct RTASN1ALLOCATORVTABLE const *pThis, PRTASN1ALLOCATION pAllocation,
+ void *pv));
+ /**
+ * Allocates a chunk of memory, all initialized to zero.
+ *
+ * @returns IPRT status code.
+ * @param pThis Pointer to the vtable structure.
+ * @param pAllocation Pointer to the allocation info structure.
+ * @param ppv Where to store the pointer on success.
+ * @param cb The minimum number of bytes to allocate. The actual
+ * number of bytes allocated shall be stored in
+ * pInfo->cbAllocated on success.
+ */
+ DECLCALLBACKMEMBER(int, pfnAlloc,(struct RTASN1ALLOCATORVTABLE const *pThis, PRTASN1ALLOCATION pAllocation,
+ void **ppv, size_t cb));
+ /**
+ * Reallocates a memory allocation.
+ *
+ * New memory does not need to be initialized, the caller takes care of that.
+ *
+ * This will not need to deal with free (@a cbNew == 0) or the initial
+ * allocation (@a pvOld == NULL), those calls will be directed to pfnFree and
+ * pfnAlloc respectively.
+ *
+ * @returns IPRT status code.
+ * @param pThis Pointer to the vtable structure.
+ * @param pAllocation Pointer to the allocation info structure.
+ * @param pvOld Pointer to the current allocation. Shall remain
+ * valid on failure, but may be invalid on success.
+ * @param ppvNew Where to store the pointer on success. Shall not be
+ * touched, except on successful returns.
+ * @param cbNew The new minimum allocation size. The actual number
+ * of bytes allocated shall be stored in
+ * pInfo->cbAllocated on success.
+ */
+ DECLCALLBACKMEMBER(int, pfnRealloc,(struct RTASN1ALLOCATORVTABLE const *pThis, PRTASN1ALLOCATION pAllocation,
+ void *pvOld, void **ppvNew, size_t cbNew));
+
+ /**
+ * Frees an array allocation (the array an all instances in it).
+ *
+ * @returns IPRT status code.
+ * @param pThis Pointer to the vtable structure.
+ * @param pAllocation Pointer to the allocation info structure.
+ * @param papvArray Pointer to the pointer array to be freed. Not NULL.
+ */
+ DECLCALLBACKMEMBER(void, pfnFreeArray,(struct RTASN1ALLOCATORVTABLE const *pThis, PRTASN1ARRAYALLOCATION pAllocation,
+ void **papvArray));
+ /**
+ * Grows the array to at least @a cMinEntries.
+ *
+ * The entries are initalized with ZEROs.
+ *
+ * @returns IPRT status code.
+ * @param pThis Pointer to the vtable structure.
+ * @param pAllocation Pointer to the allocation info structure.
+ * @param ppapvArray Pointer to the pointer to the array to be grown (or
+ * allocated).
+ * @param cMinEntries The minimum number of entries (array size and
+ * instantiated entries) that must be available
+ * on successful return.
+ */
+ DECLCALLBACKMEMBER(int, pfnGrowArray,(struct RTASN1ALLOCATORVTABLE const *pThis, PRTASN1ARRAYALLOCATION pAllocation,
+ void ***ppapvArray, uint32_t cMinEntries));
+ /**
+ * Shrinks the array (depends on allocator policy).
+ *
+ * If memory isn't freed, the implementation must fill the entries being
+ * shredded with ZEROs so the growth optimizations in RTAsn1MemResizeArray
+ * returns ZEROed entries.
+ *
+ * @returns IPRT status code.
+ * @param pThis Pointer to the vtable structure.
+ * @param pAllocation Pointer to the allocation info structure.
+ * @param ppapvArray Pointer to the pointer to the array to shrunk.
+ * @param cNew The new entry count.
+ * @param cCurrent The new entry count.
+ */
+ DECLCALLBACKMEMBER(void, pfnShrinkArray,(struct RTASN1ALLOCATORVTABLE const *pThis, PRTASN1ARRAYALLOCATION pAllocation,
+ void ***ppapvArray, uint32_t cNew, uint32_t cCurrent));
+} RTASN1ALLOCATORVTABLE;
+/** Pointer to an ASN.1 allocator vtable. */
+typedef RTASN1ALLOCATORVTABLE *PRTASN1ALLOCATORVTABLE;
+/** Pointer to a const ASN.1 allocator vtable. */
+typedef RTASN1ALLOCATORVTABLE const *PCRTASN1ALLOCATORVTABLE;
+
+/** The default ASN.1 allocator. */
+extern RTDATADECL(RTASN1ALLOCATORVTABLE const) g_RTAsn1DefaultAllocator;
+
+/** The Electric Fence ASN.1 allocator. */
+extern RTDATADECL(RTASN1ALLOCATORVTABLE const) g_RTAsn1EFenceAllocator;
+
+/** The safer ASN.1 allocator for sensitive data. */
+extern RTDATADECL(RTASN1ALLOCATORVTABLE const) g_RTAsn1SaferAllocator;
+
+
+/**
+ * Allocation information.
+ */
+typedef struct RTASN1ALLOCATION
+{
+ /** The number of bytes currently allocated. */
+ uint32_t cbAllocated;
+ /** Number of realloc calls. */
+ uint16_t cReallocs;
+ /** Reserved / padding. */
+ uint16_t uReserved0;
+ /** Allocator vtable, NULL for the default allocator. */
+ PCRTASN1ALLOCATORVTABLE pAllocator;
+} RTASN1ALLOCATION;
+
+
+/**
+ * Pointer array allocation information.
+ *
+ * Used by SET OF and SEQUENCE OF structures (typically automatically
+ * generated).
+ */
+typedef struct RTASN1ARRAYALLOCATION
+{
+ /** The size of the array entry. */
+ uint32_t cbEntry;
+ /** The size of the pointer array allocation. */
+ uint32_t cPointersAllocated;
+ /** Number of entry instances allocated. This can be greater than the
+ * official array size. */
+ uint32_t cEntriesAllocated;
+ /** Number of array resizing calls (for increasing growth rate).
+ * Maintained by RTAsn1MemResizeArray(). */
+ uint16_t cResizeCalls;
+ /** Reserved / padding. */
+ uint16_t uReserved0;
+ /** Allocator vtable, NULL for the default allocator. */
+ PCRTASN1ALLOCATORVTABLE pAllocator;
+} RTASN1ARRAYALLOCATION;
+
+
+/**
+ * Allocate a block of zero initialized memory.
+ *
+ * @returns IPRT status code.
+ * @param pAllocation The allocation record (initialized by
+ * RTAsn1CursorInitAllocation or similar).
+ * @param ppvMem Where to return the pointer to the block.
+ * @param cbMem The minimum number of bytes to allocate.
+ */
+RTDECL(int) RTAsn1MemAllocZ(PRTASN1ALLOCATION pAllocation, void **ppvMem, size_t cbMem);
+
+/**
+ * Allocates a block of memory initialized to the content of @a pvSrc.
+ *
+ * @returns IPRT status code.
+ * @param pAllocation The allocation record (initialized by
+ * RTAsn1CursorInitAllocation or similar).
+ * @param ppvMem Where to return the pointer to the block.
+ * @param pvSrc The source memory.
+ * @param cbMem The minimum number of bytes to allocate.
+ */
+RTDECL(int) RTAsn1MemDup(PRTASN1ALLOCATION pAllocation, void **ppvMem, void const *pvSrc, size_t cbMem);
+
+/**
+ * Free a memory block.
+ *
+ * @param pAllocation The allocation record (initialized by
+ * RTAsn1CursorInitAllocation or similar).
+ * @param pv The memory block to free. NULL will be ignored.
+ */
+RTDECL(void) RTAsn1MemFree(PRTASN1ALLOCATION pAllocation, void *pv);
+
+/**
+ * Initalize an allocation.
+ *
+ * @returns pAllocation
+ * @param pAllocation The allocation record (initialized by
+ * RTAsn1CursorInitAllocation or similar).
+ * @param pAllocator The allocator
+ */
+RTDECL(PRTASN1ALLOCATION) RTAsn1MemInitAllocation(PRTASN1ALLOCATION pAllocation, PCRTASN1ALLOCATORVTABLE pAllocator);
+
+/**
+ * Initalize an array allocation.
+ *
+ * @returns pAllocation
+ * @param pAllocation The allocation record (initialized by
+ * RTAsn1CursorInitAllocation or similar).
+ * @param pAllocator The allocator
+ * @param cbEntry The entry size.
+ */
+RTDECL(PRTASN1ARRAYALLOCATION) RTAsn1MemInitArrayAllocation(PRTASN1ARRAYALLOCATION pAllocation,
+ PCRTASN1ALLOCATORVTABLE pAllocator, size_t cbEntry);
+
+/**
+ * Resize an array with zero initialized memory.
+ *
+ * @returns IPRT status code.
+ * @param pAllocation The allocation record (initialized by
+ * RTAsn1CursorInitAllocation or similar).
+ * @param ppapvArray Pointer to the variable pointing to the array. This is
+ * both input and output. Remains valid on failure.
+ * @param cCurrent The current entry count. (Relevant for zero
+ * initialization of the new entries.)
+ * @param cNew The new entry count.
+ */
+RTDECL(int) RTAsn1MemResizeArray(PRTASN1ARRAYALLOCATION pAllocation, void ***ppapvArray, uint32_t cCurrent, uint32_t cNew);
+
+/**
+ * Frees an array and all its entries.
+ *
+ * @param pAllocation The array allocation record (initialized by
+ * RTAsn1CursorInitArrayAllocation or similar).
+ * @param papvArray The array to free. NULL is ignored.
+ */
+RTDECL(void) RTAsn1MemFreeArray(PRTASN1ARRAYALLOCATION pAllocation, void **papvArray);
+
+
+/** Pointer to a core ASN.1 encoding info structure. */
+typedef struct RTASN1CORE *PRTASN1CORE;
+/** Pointer to a const core ASN.1 encoding info structure. */
+typedef struct RTASN1CORE const *PCRTASN1CORE;
+
+RTDECL(int) RTAsn1ContentAllocZ(struct RTASN1CORE *pAsn1Core, size_t cb, PCRTASN1ALLOCATORVTABLE pAllocator);
+RTDECL(int) RTAsn1ContentDup(struct RTASN1CORE *pAsn1Core, void const *pvSrc, size_t cbSrc, PCRTASN1ALLOCATORVTABLE pAllocator);
+RTDECL(int) RTAsn1ContentReallocZ(struct RTASN1CORE *pAsn1Core, size_t cb, PCRTASN1ALLOCATORVTABLE pAllocator);
+RTDECL(void) RTAsn1ContentFree(struct RTASN1CORE *pAsn1Core);
+
+
+
+/**
+ * ASN.1 object enumeration callback.
+ *
+ * @returns IPRT status code. VINF_SUCCESS continues the enumberation, all
+ * others quit it and is returned to the caller's caller.
+ * @param pAsn1Core The ASN.1 object we're called back about.
+ * @param pszName The member name. Array member names ends with
+ * '[#]'.
+ * @param uDepth The current depth.
+ * @param pvUser Callback user parameter.
+ */
+typedef DECLCALLBACKTYPE(int, FNRTASN1ENUMCALLBACK,(struct RTASN1CORE *pAsn1Core, const char *pszName, uint32_t uDepth,
+ void *pvUser));
+/** Pointer to an ASN.1 object enumeration callback. */
+typedef FNRTASN1ENUMCALLBACK *PFNRTASN1ENUMCALLBACK;
+
+/**
+ * ASN.1 object encoding writer callback.
+ *
+ * @returns IPRT status code.
+ * @param pvBuf Pointer to the bytes to output.
+ * @param cbToWrite The number of bytes to write.
+ * @param pvUser Callback user parameter.
+ * @param pErrInfo Where to store extended error info. Optional.
+ */
+typedef DECLCALLBACKTYPE(int, FNRTASN1ENCODEWRITER,(const void *pvBuf, size_t cbToWrite, void *pvUser, PRTERRINFO pErrInfo));
+/** Pointer to an ASN.1 encoding writer callback. */
+typedef FNRTASN1ENCODEWRITER *PFNRTASN1ENCODEWRITER;
+
+/** @name ASN.1 Vtable Method Types
+ * @{ */
+
+/**
+ * Destructor.
+ *
+ * RTAsn1Destroy will first destroy all children by recursive calls to pfnEnum,
+ * afterwards it will call this method to release any memory or other resources
+ * associated with this object. The memory backing the object structure shall
+ * not be freed by this method.
+ *
+ * @param pThisCore Pointer to the ASN.1 core to destroy.
+ */
+typedef DECLCALLBACKTYPE(void, FNRTASN1COREVTDTOR,(PRTASN1CORE pThisCore));
+/** Pointer to a FNRTASN1COREVTDTOR method. */
+typedef FNRTASN1COREVTDTOR *PFNRTASN1COREVTDTOR;
+
+/**
+ * Enumerate members (not necessary for primitive objects).
+ *
+ * @returns IPRT status code, any non VINF_SUCCESS value stems from pfnCallback.
+ * @param pThisCore Pointer to the ASN.1 core to enumerate members of.
+ * @param pfnCallback The callback.
+ * @param uDepth The depth of this object. Children are at +1.
+ * @param pvUser Callback user argument.
+ */
+typedef DECLCALLBACKTYPE(int, FNRTASN1COREVTENUM,(PRTASN1CORE pThisCore, PFNRTASN1ENUMCALLBACK pfnCallback,
+ uint32_t uDepth, void *pvUser));
+/** Pointer to a FNRTASN1COREVTENUM method. */
+typedef FNRTASN1COREVTENUM *PFNRTASN1COREVTENUM;
+
+/**
+ * Clone method.
+ *
+ * @param pThisCore Pointer to the ASN.1 core to initialize as a clone
+ * of pSrcClone. (The caller is responsible for making
+ * sure there is sufficent space and such.)
+ * @param pSrcCore The object to clone.
+ * @param pAllocator The allocator to use.
+ */
+typedef DECLCALLBACKTYPE(int, FNRTASN1COREVTCLONE,(PRTASN1CORE pThisCore, PCRTASN1CORE pSrcCore,
+ PCRTASN1ALLOCATORVTABLE pAllocator));
+/** Pointer to a FNRTASN1COREVTCLONE method. */
+typedef FNRTASN1COREVTCLONE *PFNRTASN1COREVTCLONE;
+
+/**
+ * Compare method.
+ *
+ * The caller makes sure both cores are present and have the same Vtable.
+ *
+ * @returns 0 if equal, -1 if @a pLeft is smaller, 1 if @a pLeft is larger.
+ * @param pLeftCore Pointer to the ASN.1 core of the left side object.
+ * @param pRightCore Pointer to the ASN.1 core of the right side object.
+ */
+typedef DECLCALLBACKTYPE(int, FNRTASN1COREVTCOMPARE,(PCRTASN1CORE pLeftCore, PCRTASN1CORE pRightCore));
+/** Pointer to a FNRTASN1COREVTCOMPARE method. */
+typedef FNRTASN1COREVTCOMPARE *PFNRTASN1COREVTCOMPARE;
+
+/**
+ * Check sanity method.
+ *
+ * @returns IPRT status code.
+ * @param pThisCore Pointer to the ASN.1 core of the object to check out.
+ * @param fFlags See RTASN1_CHECK_SANITY_F_XXX.
+ * @param pErrInfo Where to return additional error details. Optional.
+ * @param pszErrorTag Tag for the additional error details.
+ */
+typedef DECLCALLBACKTYPE(int, FNRTASN1COREVTCHECKSANITY,(PCRTASN1CORE pThisCore, uint32_t fFlags,
+ PRTERRINFO pErrInfo, const char *pszErrorTag));
+/** Pointer to a FNRTASN1COREVTCHECKSANITY method. */
+typedef FNRTASN1COREVTCHECKSANITY *PFNRTASN1COREVTCHECKSANITY;
+
+/**
+ * Optional encoding preparations.
+ *
+ * On successful return, the pThisCore->cb value shall be valid and up to date.
+ * Will be called for any present object, including ones with default values and
+ * similar.
+ *
+ * @returns IPRT status code
+ * @param pThisCore Pointer to the ASN.1 core to enumerate members of.
+ * @param fFlags Encoding flags, RTASN1ENCODE_F_XXX.
+ * @param pErrInfo Where to return extra error information. Optional.
+ */
+typedef DECLCALLBACKTYPE(int, FNRTASN1COREVTENCODEPREP,(PRTASN1CORE pThisCore, uint32_t fFlags, PRTERRINFO pErrInfo));
+/** Pointer to a FNRTASN1COREVTENCODEWRITE method. */
+typedef FNRTASN1COREVTENCODEPREP *PFNRTASN1COREVTENCODEPREP;
+
+/**
+ * Optional encoder writer.
+ *
+ * This writes the header as well as all the content. Will be called for any
+ * present object, including ones with default values and similar.
+ *
+ * @returns IPRT status code.
+ * @param pThisCore Pointer to the ASN.1 core to enumerate members of.
+ * @param fFlags Encoding flags, RTASN1ENCODE_F_XXX.
+ * @param pfnWriter The output writer function.
+ * @param pvUser The user context for the writer function.
+ * @param pErrInfo Where to return extra error information. Optional.
+ */
+typedef DECLCALLBACKTYPE(int, FNRTASN1COREVTENCODEWRITE,(PRTASN1CORE pThisCore, uint32_t fFlags, PFNRTASN1ENCODEWRITER pfnWriter,
+ void *pvUser, PRTERRINFO pErrInfo));
+/** Pointer to a FNRTASN1COREVTENCODEWRITE method. */
+typedef FNRTASN1COREVTENCODEWRITE *PFNRTASN1COREVTENCODEWRITE;
+/** @} */
+
+/** Mask of common flags. These will be propagated during sanity checking.
+ * Bits not in this mask are type specfic. */
+#define RTASN1_CHECK_SANITY_F_COMMON_MASK UINT32_C(0xffff0000)
+
+/**
+ * ASN.1 core vtable.
+ */
+typedef struct RTASN1COREVTABLE
+{
+ /** The name. */
+ const char *pszName;
+ /** Size of the structure. */
+ uint32_t cbStruct;
+ /** The default tag, UINT8_MAX if not applicable. */
+ uint8_t uDefaultTag;
+ /** The default class and flags. */
+ uint8_t fDefaultClass;
+ /** Reserved for later / alignment. */
+ uint16_t uReserved;
+ /** @copydoc FNRTASN1COREVTDTOR */
+ PFNRTASN1COREVTDTOR pfnDtor;
+ /** @copydoc FNRTASN1COREVTENUM */
+ PFNRTASN1COREVTENUM pfnEnum;
+ /** @copydoc FNRTASN1COREVTCLONE */
+ PFNRTASN1COREVTCLONE pfnClone;
+ /** @copydoc FNRTASN1COREVTCOMPARE */
+ PFNRTASN1COREVTCOMPARE pfnCompare;
+ /** @copydoc FNRTASN1COREVTCHECKSANITY */
+ PFNRTASN1COREVTCHECKSANITY pfnCheckSanity;
+ /** @copydoc FNRTASN1COREVTENCODEPREP */
+ PFNRTASN1COREVTENCODEPREP pfnEncodePrep;
+ /** @copydoc FNRTASN1COREVTENUM */
+ PFNRTASN1COREVTENCODEWRITE pfnEncodeWrite;
+} RTASN1COREVTABLE;
+/** Pointer to an ASN.1 allocator vtable. */
+typedef struct RTASN1COREVTABLE *PRTASN1COREVTABLE;
+/** Pointer to a const ASN.1 allocator vtable. */
+typedef RTASN1COREVTABLE const *PCRTASN1COREVTABLE;
+
+
+/** @name Helper macros for prototyping standard functions for an ASN.1 type.
+ * @{ */
+
+#define RTASN1TYPE_STANDARD_PROTOTYPES_NO_GET_CORE(a_TypeNm, a_DeclMacro, a_ImplExtNm) \
+ a_DeclMacro(int) RT_CONCAT(a_ImplExtNm,_Init)(RT_CONCAT(P,a_TypeNm) pThis, PCRTASN1ALLOCATORVTABLE pAllocator); \
+ a_DeclMacro(int) RT_CONCAT(a_ImplExtNm,_Clone)(RT_CONCAT(P,a_TypeNm) pThis, RT_CONCAT(PC,a_TypeNm) pSrc, \
+ PCRTASN1ALLOCATORVTABLE pAllocator); \
+ a_DeclMacro(void) RT_CONCAT(a_ImplExtNm,_Delete)(RT_CONCAT(P,a_TypeNm) pThis); \
+ a_DeclMacro(int) RT_CONCAT(a_ImplExtNm,_Enum)(RT_CONCAT(P,a_TypeNm) pThis, PFNRTASN1ENUMCALLBACK pfnCallback, \
+ uint32_t uDepth, void *pvUser); \
+ a_DeclMacro(int) RT_CONCAT(a_ImplExtNm,_Compare)(RT_CONCAT(PC,a_TypeNm) pLeft, RT_CONCAT(PC,a_TypeNm) pRight); \
+ a_DeclMacro(int) RT_CONCAT(a_ImplExtNm,_DecodeAsn1)(PRTASN1CURSOR pCursor, uint32_t fFlags, RT_CONCAT(P,a_TypeNm) pThis,\
+ const char *pszErrorTag); \
+ a_DeclMacro(int) RT_CONCAT(a_ImplExtNm,_CheckSanity)(RT_CONCAT(PC,a_TypeNm) pThis, uint32_t fFlags, \
+ PRTERRINFO pErrInfo, const char *pszErrorTag)
+
+
+#define RTASN1TYPE_STANDARD_PROTOTYPES(a_TypeNm, a_DeclMacro, a_ImplExtNm, a_Asn1CoreNm) \
+ DECL_FORCE_INLINE(PRTASN1CORE) RT_CONCAT(a_ImplExtNm,_GetAsn1Core)(RT_CONCAT(PC,a_TypeNm) pThis) \
+ { return (PRTASN1CORE)&pThis->a_Asn1CoreNm; } \
+ DECLINLINE(bool) RT_CONCAT(a_ImplExtNm,_IsPresent)(RT_CONCAT(PC,a_TypeNm) pThis) \
+ { return pThis && RTASN1CORE_IS_PRESENT(&pThis->a_Asn1CoreNm); } \
+ RTASN1TYPE_STANDARD_PROTOTYPES_NO_GET_CORE(a_TypeNm, a_DeclMacro, a_ImplExtNm)
+
+
+/** Aliases two ASN.1 types, no method aliases. */
+#define RTASN1TYPE_ALIAS_TYPE_ONLY(a_TypeNm, a_AliasType) \
+ typedef a_AliasType a_TypeNm; \
+ typedef a_TypeNm *RT_CONCAT(P,a_TypeNm); \
+ typedef a_TypeNm const *RT_CONCAT(PC,a_TypeNm)
+
+/** Aliases two ASN.1 types and methods. */
+#define RTASN1TYPE_ALIAS(a_TypeNm, a_AliasType, a_ImplExtNm, a_AliasExtNm) \
+ typedef a_AliasType a_TypeNm; \
+ typedef a_TypeNm *RT_CONCAT(P,a_TypeNm); \
+ \
+ DECLINLINE(PRTASN1CORE) RT_CONCAT(a_ImplExtNm,_GetAsn1Core)(a_TypeNm const *pThis) \
+ { return RT_CONCAT(a_AliasExtNm,_GetAsn1Core)(pThis); } \
+ DECLINLINE(bool) RT_CONCAT(a_ImplExtNm,_IsPresent)(a_TypeNm const *pThis) \
+ { return RT_CONCAT(a_AliasExtNm,_IsPresent)(pThis); } \
+ \
+ DECLINLINE(int) RT_CONCAT(a_ImplExtNm,_Init)(RT_CONCAT(P,a_TypeNm) pThis, PCRTASN1ALLOCATORVTABLE pAllocator) \
+ { return RT_CONCAT(a_AliasExtNm,_Init)(pThis, pAllocator); } \
+ DECLINLINE(int) RT_CONCAT(a_ImplExtNm,_Clone)(RT_CONCAT(P,a_TypeNm) pThis, a_TypeNm const *pSrc, \
+ PCRTASN1ALLOCATORVTABLE pAllocator) \
+ { return RT_CONCAT(a_AliasExtNm,_Clone)(pThis, pSrc, pAllocator); } \
+ DECLINLINE(void) RT_CONCAT(a_ImplExtNm,_Delete)(RT_CONCAT(P,a_TypeNm) pThis) \
+ { RT_CONCAT(a_AliasExtNm,_Delete)(pThis); } \
+ DECLINLINE(int) RT_CONCAT(a_ImplExtNm,_Enum)(a_TypeNm *pThis, PFNRTASN1ENUMCALLBACK pfnCallback, \
+ uint32_t uDepth, void *pvUser) \
+ { return RT_CONCAT(a_AliasExtNm,_Enum)(pThis, pfnCallback, uDepth, pvUser); } \
+ DECLINLINE(int) RT_CONCAT(a_ImplExtNm,_Compare)(a_TypeNm const *pLeft, a_TypeNm const *pRight) \
+ { return RT_CONCAT(a_AliasExtNm,_Compare)(pLeft, pRight); } \
+ DECLINLINE(int) RT_CONCAT(a_ImplExtNm,_DecodeAsn1)(PRTASN1CURSOR pCursor, uint32_t fFlags, RT_CONCAT(P,a_TypeNm) pThis,\
+ const char *pszErrorTag) \
+ { return RT_CONCAT(a_AliasExtNm,_DecodeAsn1)(pCursor, fFlags, pThis, pszErrorTag); } \
+ DECLINLINE(int) RT_CONCAT(a_ImplExtNm,_CheckSanity)(a_TypeNm const *pThis, uint32_t fFlags, \
+ PRTERRINFO pErrInfo, const char *pszErrorTag) \
+ { return RT_CONCAT(a_AliasExtNm,_CheckSanity)(pThis, fFlags, pErrInfo, pszErrorTag); } \
+ \
+ typedef a_TypeNm const *RT_CONCAT(PC,a_TypeNm)
+
+/** @} */
+
+
+/**
+ * Core ASN.1 structure for storing encoding details and data location.
+ *
+ * This is used as a 'parent' for all other decoded ASN.1 based structures.
+ */
+typedef struct RTASN1CORE
+{
+ /** The tag.
+ * @remarks 32-bit should be enough for everyone... We don't currently
+ * implement decoding tags larger than 30 anyway. :-) */
+ uint32_t uTag;
+ /** Tag class and flags (ASN1_TAGCLASS_XXX and ASN1_TAGFLAG_XXX). */
+ uint8_t fClass;
+ /** The real tag value for IMPLICT tag overrides. */
+ uint8_t uRealTag;
+ /** The real class value for IMPLICT tag overrides. */
+ uint8_t fRealClass;
+ /** The size of the tag and length ASN.1 header. */
+ uint8_t cbHdr;
+ /** Length. */
+ uint32_t cb;
+ /** IPRT flags (RTASN1CORE_F_XXX). */
+ uint32_t fFlags;
+ /** Pointer to the data.
+ * After decoding this generally points to the encoded data content. When
+ * preparting something for encoding or otherwise constructing things in memory,
+ * this generally points heap memory or read-only constants.
+ * @sa RTAsn1ContentAllocZ, RTAsn1ContentReallocZ, RTAsn1ContentDup,
+ * RTAsn1ContentFree. */
+ RTCPTRUNION uData;
+ /** Pointer to the virtual method table for this object. Optional. */
+ PCRTASN1COREVTABLE pOps;
+} RTASN1CORE;
+/** The Vtable for a RTASN1CORE structure when not in some way use used as a
+ * parent type/class. */
+extern RTDATADECL(RTASN1COREVTABLE const) g_RTAsn1Core_Vtable;
+
+RTASN1TYPE_STANDARD_PROTOTYPES_NO_GET_CORE(RTASN1CORE, RTDECL, RTAsn1Core);
+
+/** @name RTASN1CORE_F_XXX - Flags for RTASN1CORE::fFlags
+ * @{ */
+/** Present/valid. */
+#define RTASN1CORE_F_PRESENT RT_BIT_32(0)
+/** Not present in stream, using default value. */
+#define RTASN1CORE_F_DEFAULT RT_BIT_32(1)
+/** The tag was overriden by an implict context tag or some such thing,
+ * RTASN1CORE::uImplicitTag hold the universal tag value if one exists. */
+#define RTASN1CORE_F_TAG_IMPLICIT RT_BIT_32(2)
+/** Primitive tag with the corresponding RTASN1XXX struct. */
+#define RTASN1CORE_F_PRIMITE_TAG_STRUCT RT_BIT_32(3)
+/** Dummy node typically used with choices, has children, not encoded, must be
+ * ignored. */
+#define RTASN1CORE_F_DUMMY RT_BIT_32(4)
+/** Allocated content (pointed to by uData).
+ * The content should is still be considered 104% read-only by anyone other
+ * than then type methods (pOps and associates). */
+#define RTASN1CORE_F_ALLOCATED_CONTENT RT_BIT_32(5)
+/** Decoded content (pointed to by uData).
+ * Mutually exclusive with RTASN1CORE_F_ALLOCATED_CONTENT. If neither is
+ * set, uData might be NULL or point to some shared static memory for
+ * frequently used values. */
+#define RTASN1CORE_F_DECODED_CONTENT RT_BIT_32(6)
+/** Indefinite length, still pending. */
+#define RTASN1CORE_F_INDEFINITE_LENGTH RT_BIT_32(7)
+/** @} */
+
+
+/** Checks whether an ASN.1 core object present in some way (default data,
+ * decoded data, ...). */
+#define RTASN1CORE_IS_PRESENT(a_pAsn1Core) ( RT_BOOL((a_pAsn1Core)->fFlags) )
+
+/** Checks whether an ASN.1 core object is a dummy object (and is present). */
+#define RTASN1CORE_IS_DUMMY(a_pAsn1Core) ( RT_BOOL((a_pAsn1Core)->fFlags & RTASN1CORE_F_DUMMY) )
+
+/**
+ * Calculates pointer to the raw ASN.1 record.
+ *
+ * ASSUMES that it's decoded content and that cbHdr and uData are both valid.
+ *
+ * @returns Byte pointer to the first tag byte.
+ * @param a_pAsn1Core The ASN.1 core.
+ */
+#define RTASN1CORE_GET_RAW_ASN1_PTR(a_pAsn1Core) ( (a_pAsn1Core)->uData.pu8 - (a_pAsn1Core)->cbHdr )
+
+/**
+ * Calculates the length of the raw ASN.1 record to go with the
+ * RTASN1CORE_GET_RAW_ASN1_PTR() result.
+ *
+ * ASSUMES that it's decoded content and that cbHdr and uData are both valid.
+ *
+ * @returns Size in bytes (uint32_t).
+ * @param a_pAsn1Core The ASN.1 core.
+ */
+#define RTASN1CORE_GET_RAW_ASN1_SIZE(a_pAsn1Core) ( (a_pAsn1Core)->cbHdr + (a_pAsn1Core)->cb )
+
+/**
+ * Retrievs the tag or implicit tag depending on the RTASN1CORE_F_TAG_IMPLICIT
+ * flag.
+ *
+ * @returns The ASN.1 tag of the object.
+ * @param a_pAsn1Core The ASN.1 core.
+ */
+#define RTASN1CORE_GET_TAG(a_pAsn1Core) ( !((a_pAsn1Core)->fFlags & RTASN1CORE_F_TAG_IMPLICIT) ? (a_pAsn1Core)->uTag : (a_pAsn1Core)->uRealTag )
+
+
+DECL_FORCE_INLINE(PRTASN1CORE) RTAsn1Core_GetAsn1Core(PCRTASN1CORE pThis)
+{
+ return (PRTASN1CORE)pThis;
+}
+
+
+DECL_FORCE_INLINE(bool) RTAsn1Core_IsPresent(PCRTASN1CORE pThis)
+{
+ return pThis && RTASN1CORE_IS_PRESENT(pThis);
+}
+
+
+RTDECL(int) RTAsn1Core_InitEx(PRTASN1CORE pAsn1Core, uint32_t uTag, uint8_t fClass, PCRTASN1COREVTABLE pOps, uint32_t fFlags);
+/**
+ * Initialize the ASN.1 core object representation to a default value.
+ *
+ * @returns VINF_SUCCESS
+ * @param pAsn1Core The ASN.1 core.
+ * @param uTag The tag number.
+ * @param fClass The tag class and flags.
+ */
+RTDECL(int) RTAsn1Core_InitDefault(PRTASN1CORE pAsn1Core, uint32_t uTag, uint8_t fClass);
+RTDECL(int) RTAsn1Core_CloneContent(PRTASN1CORE pThis, PCRTASN1CORE pSrc, PCRTASN1ALLOCATORVTABLE pAllocator);
+RTDECL(int) RTAsn1Core_CloneNoContent(PRTASN1CORE pThis, PCRTASN1CORE pSrc);
+RTDECL(int) RTAsn1Core_SetTagAndFlags(PRTASN1CORE pAsn1Core, uint32_t uTag, uint8_t fClass);
+RTDECL(int) RTAsn1Core_ChangeTag(PRTASN1CORE pAsn1Core, uint32_t uTag);
+RTDECL(void) RTAsn1Core_ResetImplict(PRTASN1CORE pThis);
+RTDECL(int) RTAsn1Core_CompareEx(PCRTASN1CORE pLeft, PCRTASN1CORE pRight, bool fIgnoreTagAndClass);
+
+
+/**
+ * Dummy ASN.1 object for use in choices and similar non-sequence structures.
+ *
+ * This allows hooking up destructors, enumerators and such, as well as not
+ * needing custom code for sequence-of / set-of collections.
+ */
+typedef struct RTASN1DUMMY
+{
+ /** Core ASN.1. */
+ RTASN1CORE Asn1Core;
+} RTASN1DUMMY;
+/** Pointer to a dummy record. */
+typedef RTASN1DUMMY *PRTASN1DUMMY;
+
+
+/**
+ * Initalizes a dummy ASN.1 object.
+ *
+ * @returns VINF_SUCCESS.
+ * @param pThis The dummy object.
+ */
+RTDECL(int) RTAsn1Dummy_InitEx(PRTASN1DUMMY pThis);
+
+/**
+ * Standard compliant initalizer.
+ *
+ * @returns VINF_SUCCESS.
+ * @param pThis The dummy object.
+ * @param pAllocator Ignored.
+ */
+DECLINLINE(int) RTAsn1Dummy_Init(PRTASN1DUMMY pThis, PCRTASN1ALLOCATORVTABLE pAllocator)
+{
+ NOREF(pAllocator);
+ return RTAsn1Dummy_InitEx(pThis);
+}
+
+
+/**
+ * ASN.1 sequence core (IPRT representation).
+ */
+typedef struct RTASN1SEQUENCECORE
+{
+ /** Core ASN.1 encoding details. */
+ RTASN1CORE Asn1Core;
+} RTASN1SEQUENCECORE;
+/** Pointer to an ASN.1 sequence core (IPRT representation). */
+typedef RTASN1SEQUENCECORE *PRTASN1SEQUENCECORE;
+/** Pointer to a const ASN.1 sequence core (IPRT representation). */
+typedef RTASN1SEQUENCECORE const *PCRTASN1SEQUENCECORE;
+
+RTDECL(int) RTAsn1SequenceCore_Init(PRTASN1SEQUENCECORE pSeqCore, PCRTASN1COREVTABLE pVtable);
+RTDECL(int) RTAsn1SequenceCore_Clone(PRTASN1SEQUENCECORE pSeqCore, PCRTASN1COREVTABLE pVtable, PCRTASN1SEQUENCECORE pSrc);
+
+/**
+ * ASN.1 sequence-of core (IPRT representation).
+ */
+#if 0
+typedef struct RTASN1SEQOFCORE
+{
+ /** Core ASN.1 encoding details. */
+ RTASN1CORE Asn1Core;
+} RTASN1SEQUENCECORE;
+/** Pointer to an ASN.1 sequence-of core (IPRT representation). */
+typedef RTASN1SEQUENCECORE *PRTASN1SEQUENCECORE;
+/** Pointer to a const ASN.1 sequence-of core (IPRT representation). */
+typedef RTASN1SEQUENCECORE const *PCRTASN1SEQUENCECORE;
+#else
+# define RTASN1SEQOFCORE RTASN1SEQUENCECORE
+# define PRTASN1SEQOFCORE PRTASN1SEQUENCECORE
+# define PCRTASN1SEQOFCORE PCRTASN1SEQUENCECORE
+#endif
+RTDECL(int) RTAsn1SeqOfCore_Init(PRTASN1SEQOFCORE pThis, PCRTASN1COREVTABLE pVtable);
+RTDECL(int) RTAsn1SeqOfCore_Clone(PRTASN1SEQOFCORE pThis, PCRTASN1COREVTABLE pVtable, PCRTASN1SEQOFCORE pSrc);
+
+
+/** Defines the typedefs and prototypes for a generic sequence-of/set-of type. */
+#define RTASN1_IMPL_GEN_SEQ_OR_SET_OF_TYPEDEFS_AND_PROTOS(a_CoreType, a_CoreMember, \
+ a_ThisType, a_ItemType, a_DeclMacro, a_ImplExtNm) \
+ typedef struct a_ThisType \
+ { \
+ /** Sequence/set core. */ \
+ a_CoreType a_CoreMember; \
+ /** The array allocation tracker. */ \
+ RTASN1ARRAYALLOCATION Allocation; \
+ /** Items in the array. */ \
+ uint32_t cItems; \
+ /** Array. */ \
+ RT_CONCAT(P,a_ItemType) *papItems; \
+ } a_ThisType; \
+ typedef a_ThisType *RT_CONCAT(P,a_ThisType); \
+ typedef a_ThisType const *RT_CONCAT(PC,a_ThisType); \
+ a_DeclMacro(int) RT_CONCAT(a_ImplExtNm,_Erase)(RT_CONCAT(P,a_ThisType) pThis, uint32_t iPosition); \
+ a_DeclMacro(int) RT_CONCAT(a_ImplExtNm,_InsertEx)(RT_CONCAT(P,a_ThisType) pThis, uint32_t iPosition, \
+ RT_CONCAT(PC,a_ItemType) pToClone, \
+ PCRTASN1ALLOCATORVTABLE pAllocator, uint32_t *piActualPos); \
+ /** Appends entry with default content, returns index or negative error code. */ \
+ DECLINLINE(int32_t) RT_CONCAT(a_ImplExtNm,_Append)(RT_CONCAT(P,a_ThisType) pThis) \
+ { \
+ uint32_t uPos = pThis->cItems; \
+ int rc = RT_CONCAT(a_ImplExtNm,_InsertEx)(pThis, uPos, NULL /*pToClone*/, pThis->Allocation.pAllocator, &uPos); \
+ if (RT_SUCCESS(rc)) \
+ return (int32_t)uPos; \
+ return rc; \
+ } \
+ RTASN1TYPE_STANDARD_PROTOTYPES(a_ThisType, a_DeclMacro, a_ImplExtNm, a_CoreMember.Asn1Core)
+
+/** Defines the typedefs and prototypes for a generic sequence-of type. */
+#define RTASN1_IMPL_GEN_SEQ_OF_TYPEDEFS_AND_PROTOS(a_SeqOfType, a_ItemType, a_DeclMacro, a_ImplExtNm) \
+ RTASN1_IMPL_GEN_SEQ_OR_SET_OF_TYPEDEFS_AND_PROTOS(RTASN1SEQUENCECORE, SeqCore, a_SeqOfType, a_ItemType, a_DeclMacro, a_ImplExtNm)
+
+
+/**
+ * ASN.1 set core (IPRT representation).
+ */
+typedef struct RTASN1SETCORE
+{
+ /** Core ASN.1 encoding details. */
+ RTASN1CORE Asn1Core;
+} RTASN1SETCORE;
+/** Pointer to an ASN.1 set core (IPRT representation). */
+typedef RTASN1SETCORE *PRTASN1SETCORE;
+/** Pointer to a const ASN.1 set core (IPRT representation). */
+typedef RTASN1SETCORE const *PCRTASN1SETCORE;
+
+RTDECL(int) RTAsn1SetCore_Init(PRTASN1SETCORE pThis, PCRTASN1COREVTABLE pVtable);
+RTDECL(int) RTAsn1SetCore_Clone(PRTASN1SETCORE pThis, PCRTASN1COREVTABLE pVtable, PCRTASN1SETCORE pSrc);
+
+/**
+ * ASN.1 set-of core (IPRT representation).
+ */
+#if 0
+typedef struct RTASN1SETOFCORE
+{
+ /** Core ASN.1 encoding details. */
+ RTASN1CORE Asn1Core;
+} RTASN1SETUENCECORE;
+/** Pointer to an ASN.1 set-of core (IPRT representation). */
+typedef RTASN1SETUENCECORE *PRTASN1SETUENCECORE;
+/** Pointer to a const ASN.1 set-of core (IPRT representation). */
+typedef RTASN1SETUENCECORE const *PCRTASN1SETUENCECORE;
+#else
+# define RTASN1SETOFCORE RTASN1SETCORE
+# define PRTASN1SETOFCORE PRTASN1SETCORE
+# define PCRTASN1SETOFCORE PCRTASN1SETCORE
+#endif
+RTDECL(int) RTAsn1SetOfCore_Init(PRTASN1SETOFCORE pThis, PCRTASN1COREVTABLE pVtable);
+RTDECL(int) RTAsn1SetOfCore_Clone(PRTASN1SETOFCORE pThis, PCRTASN1COREVTABLE pVtable, PCRTASN1SETOFCORE pSrc);
+
+
+/** Defines the typedefs and prototypes for a generic set-of type. */
+#define RTASN1_IMPL_GEN_SET_OF_TYPEDEFS_AND_PROTOS(a_SetOfType, a_ItemType, a_DeclMacro, a_ImplExtNm) \
+ RTASN1_IMPL_GEN_SEQ_OR_SET_OF_TYPEDEFS_AND_PROTOS(RTASN1SETCORE, SetCore, a_SetOfType, a_ItemType, a_DeclMacro, a_ImplExtNm)
+
+
+/*
+ * Declare sets and sequences of the core structure.
+ */
+RTASN1_IMPL_GEN_SEQ_OF_TYPEDEFS_AND_PROTOS(RTASN1SEQOFCORES, RTASN1CORE, RTDECL, RTAsn1SeqOfCores);
+RTASN1_IMPL_GEN_SET_OF_TYPEDEFS_AND_PROTOS(RTASN1SETOFCORES, RTASN1CORE, RTDECL, RTAsn1SetOfCores);
+
+
+/**
+ * ASN.1 null (IPRT representation).
+ */
+typedef struct RTASN1NULL
+{
+ /** Core ASN.1 encoding details. */
+ RTASN1CORE Asn1Core;
+} RTASN1NULL;
+/** Pointer to an ASN.1 null (IPRT representation). */
+typedef RTASN1NULL *PRTASN1NULL;
+/** Pointer to a const ASN.1 null (IPRT representation). */
+typedef RTASN1NULL const *PCRTASN1NULL;
+/** The Vtable for a RTASN1NULL structure. */
+extern RTDATADECL(RTASN1COREVTABLE const) g_RTAsn1Null_Vtable;
+
+RTASN1TYPE_STANDARD_PROTOTYPES(RTASN1NULL, RTDECL, RTAsn1Null, Asn1Core);
+
+
+/**
+ * ASN.1 integer (IPRT representation).
+ */
+typedef struct RTASN1INTEGER
+{
+ /** Core ASN.1 encoding details. */
+ RTASN1CORE Asn1Core;
+ /** The unsigned C representation of the 64 least significant bits.
+ * @note A ASN.1 integer doesn't define signed/unsigned and can have any
+ * length you like. Thus, the user needs to check the size and
+ * preferably use the access APIs for signed numbers. */
+ RTUINT64U uValue;
+} RTASN1INTEGER;
+/** Pointer to an ASN.1 integer (IPRT representation). */
+typedef RTASN1INTEGER *PRTASN1INTEGER;
+/** Pointer to a const ASN.1 integer (IPRT representation). */
+typedef RTASN1INTEGER const *PCRTASN1INTEGER;
+/** The Vtable for a RTASN1INTEGER structure. */
+extern RTDATADECL(RTASN1COREVTABLE const) g_RTAsn1Integer_Vtable;
+
+RTASN1TYPE_STANDARD_PROTOTYPES(RTASN1INTEGER, RTDECL, RTAsn1Integer, Asn1Core);
+
+/**
+ * Initializes an interger object to a default value.
+ * @returns VINF_SUCCESS.
+ * @param pInteger The integer object representation.
+ * @param uValue The default value (unsigned 64-bit).
+ * @param pAllocator The allocator (pro forma).
+ */
+RTDECL(int) RTAsn1Integer_InitDefault(PRTASN1INTEGER pInteger, uint64_t uValue, PCRTASN1ALLOCATORVTABLE pAllocator);
+
+RTDECL(int) RTAsn1Integer_InitU64(PRTASN1INTEGER pThis, uint64_t uValue, PCRTASN1ALLOCATORVTABLE pAllocator);
+
+/**
+ * Get the most significat bit that's set (1).
+ *
+ * @returns 0-base bit number, -1 if all clear.
+ * @param pInteger The integer to check.
+ */
+RTDECL(int32_t) RTAsn1Integer_UnsignedLastBit(PCRTASN1INTEGER pInteger);
+
+/**
+ * Compares two ASN.1 unsigned integers.
+ *
+ * @returns 0 if equal, -1 if @a pLeft is smaller, 1 if @a pLeft is larger.
+ * @param pLeft The first ASN.1 integer.
+ * @param pRight The second ASN.1 integer.
+ */
+RTDECL(int) RTAsn1Integer_UnsignedCompare(PCRTASN1INTEGER pLeft, PCRTASN1INTEGER pRight);
+
+/**
+ * Compares an ASN.1 unsigned integer with a uint64_t.
+ *
+ * @returns 0 if equal, -1 if @a pInteger is smaller, 1 if @a pInteger is
+ * larger.
+ * @param pInteger The ASN.1 integer to treat as unsigned.
+ * @param u64Const The uint64_t constant to compare with.
+ */
+RTDECL(int) RTAsn1Integer_UnsignedCompareWithU64(PCRTASN1INTEGER pInteger, uint64_t u64Const);
+
+/**
+ * Compares an ASN.1 unsigned integer with a uint32_t.
+ *
+ * @returns 0 if equal, -1 if @a pInteger is smaller, 1 if @a pInteger is
+ * larger.
+ * @param pInteger The ASN.1 integer to treat as unsigned.
+ * @param u32Const The uint32_t constant to compare with.
+ * @remarks We don't bother with U16 and U8 variants, just use this instead.
+ */
+RTDECL(int) RTAsn1Integer_UnsignedCompareWithU32(PCRTASN1INTEGER pInteger, uint32_t u32Const);
+
+
+/**
+ * Initializes a big integer number from an ASN.1 integer.
+ *
+ * @returns IPRT status code.
+ * @param pInteger The ASN.1 integer.
+ * @param pBigNum The big integer number structure to initialize.
+ * @param fBigNumInit Subset of RTBIGNUMINIT_F_XXX that concerns
+ * senitivity, signedness and endianness.
+ */
+RTDECL(int) RTAsn1Integer_ToBigNum(PCRTASN1INTEGER pInteger, PRTBIGNUM pBigNum, uint32_t fBigNumInit);
+RTDECL(int) RTAsn1Integer_FromBigNum(PRTASN1INTEGER pThis, PCRTBIGNUM pBigNum, PCRTASN1ALLOCATORVTABLE pAllocator);
+
+/**
+ * Converts the integer to a string.
+ *
+ * This will produce a hex represenation of the number. If it fits in 64-bit, a
+ * C style hex number will be produced. If larger than 64-bit, it will be
+ * printed as a space separated string of hex bytes.
+ *
+ * @returns IPRT status code.
+ * @param pThis The ASN.1 integer.
+ * @param pszBuf The output buffer.
+ * @param cbBuf The buffer size.
+ * @param fFlags Flags reserved for future exploits. MBZ.
+ * @param pcbActual Where to return the amount of buffer space used
+ * (i.e. including terminator). Optional.
+ *
+ * @remarks Currently assume unsigned number.
+ */
+RTDECL(int) RTAsn1Integer_ToString(PCRTASN1INTEGER pThis, char *pszBuf, size_t cbBuf, uint32_t fFlags, size_t *pcbActual);
+
+RTASN1_IMPL_GEN_SEQ_OF_TYPEDEFS_AND_PROTOS(RTASN1SEQOFINTEGERS, RTASN1INTEGER, RTDECL, RTAsn1SeqOfIntegers);
+RTASN1_IMPL_GEN_SET_OF_TYPEDEFS_AND_PROTOS(RTASN1SETOFINTEGERS, RTASN1INTEGER, RTDECL, RTAsn1SetOfIntegers);
+
+
+
+/**
+ * ASN.1 boolean (IPRT representation).
+ */
+typedef struct RTASN1BOOLEAN
+{
+ /** Core ASN.1 encoding details. */
+ RTASN1CORE Asn1Core;
+ /** The boolean value. */
+ bool fValue;
+} RTASN1BOOLEAN;
+/** Pointer to the IPRT representation of an ASN.1 boolean. */
+typedef RTASN1BOOLEAN *PRTASN1BOOLEAN;
+/** Pointer to the const IPRT representation of an ASN.1 boolean. */
+typedef RTASN1BOOLEAN const *PCRTASN1BOOLEAN;
+/** The Vtable for a RTASN1BOOLEAN structure. */
+extern RTDATADECL(RTASN1COREVTABLE const) g_RTAsn1Boolean_Vtable;
+
+RTASN1TYPE_STANDARD_PROTOTYPES(RTASN1BOOLEAN, RTDECL, RTAsn1Boolean, Asn1Core);
+
+/**
+ * Initializes a boolean object to a default value.
+ * @returns VINF_SUCCESS
+ * @param pBoolean The boolean object representation.
+ * @param fValue The default value.
+ * @param pAllocator The allocator (pro forma).
+ */
+RTDECL(int) RTAsn1Boolean_InitDefault(PRTASN1BOOLEAN pBoolean, bool fValue, PCRTASN1ALLOCATORVTABLE pAllocator);
+RTDECL(int) RTAsn1Boolean_Set(PRTASN1BOOLEAN pThis, bool fValue);
+
+RTASN1_IMPL_GEN_SEQ_OF_TYPEDEFS_AND_PROTOS(RTASN1SEQOFBOOLEANS, RTASN1BOOLEAN, RTDECL, RTAsn1SeqOfBooleans);
+RTASN1_IMPL_GEN_SET_OF_TYPEDEFS_AND_PROTOS(RTASN1SETOFBOOLEANS, RTASN1BOOLEAN, RTDECL, RTAsn1SetOfBooleans);
+
+
+
+/**
+ * ASN.1 UTC and Generalized Time (IPRT representation).
+ *
+ * The two time types only differs in the precision the render (UTC time being
+ * the one for which you go "WTF were they thinking?!!" for in 2014).
+ */
+typedef struct RTASN1TIME
+{
+ /** The core structure, either ASN1_TAG_UTC_TIME or
+ * ASN1_TAG_GENERALIZED_TIME. */
+ RTASN1CORE Asn1Core;
+ /** The exploded time. */
+ RTTIME Time;
+} RTASN1TIME;
+/** Pointer to an IPRT representation of ASN.1 UTC/Generalized time. */
+typedef RTASN1TIME *PRTASN1TIME;
+/** Pointer to a const IPRT representation of ASN.1 UTC/Generalized time. */
+typedef RTASN1TIME const *PCRTASN1TIME;
+/** The Vtable for a RTASN1TIME structure. */
+extern RTDATADECL(RTASN1COREVTABLE const) g_RTAsn1Time_Vtable;
+
+RTASN1TYPE_STANDARD_PROTOTYPES(RTASN1TIME, RTDECL, RTAsn1Time, Asn1Core);
+
+RTASN1TYPE_STANDARD_PROTOTYPES(RTASN1TIME, RTDECL, RTAsn1UtcTime, Asn1Core);
+RTASN1TYPE_STANDARD_PROTOTYPES(RTASN1TIME, RTDECL, RTAsn1GeneralizedTime, Asn1Core);
+
+/**
+ * Compares two ASN.1 time values.
+ *
+ * @returns 0 if equal, -1 if @a pLeft is smaller, 1 if @a pLeft is larger.
+ * @param pLeft The first ASN.1 time object.
+ * @param pTsRight The second time to compare.
+ */
+RTDECL(int) RTAsn1Time_CompareWithTimeSpec(PCRTASN1TIME pLeft, PCRTTIMESPEC pTsRight);
+
+/**
+ * Extended init function that lets you select the kind of time object (UTC or
+ * generalized).
+ */
+RTDECL(int) RTAsn1Time_InitEx(PRTASN1TIME pThis, uint32_t uTag, PCRTASN1ALLOCATORVTABLE pAllocator);
+
+/**
+ * Combines RTAsn1Time_InitEx() and RTAsn1Time_SetTime().
+ */
+RTDECL(int) RTAsn1Time_InitWithTime(PRTASN1TIME pThis, uint32_t uTag, PCRTASN1ALLOCATORVTABLE pAllocator, PCRTTIME pTime);
+
+/**
+ * Sets the ASN.1 time value to @a pTime.
+ *
+ * @returns IPRT status code.
+ * @param pThis The ASN.1 time object to modify.
+ * @param pAllocator The allocator to use.
+ * @param pTime The time to set.
+ */
+RTDECL(int) RTAsn1Time_SetTime(PRTASN1TIME pThis, PCRTASN1ALLOCATORVTABLE pAllocator, PCRTTIME pTime);
+
+/**
+ * Sets the ASN.1 time value to @a pTimeSpec.
+ *
+ * @returns IPRT status code.
+ * @param pThis The ASN.1 time object to modify.
+ * @param pAllocator The allocator to use.
+ * @param pTimeSpec The time to set.
+ */
+RTDECL(int) RTAsn1Time_SetTimeSpec(PRTASN1TIME pThis, PCRTASN1ALLOCATORVTABLE pAllocator, PCRTTIMESPEC pTimeSpec);
+
+/** @name Predicate macros for determing the exact type of RTASN1TIME.
+ * @{ */
+/** True if UTC time. */
+#define RTASN1TIME_IS_UTC_TIME(a_pAsn1Time) ((a_pAsn1Time)->Asn1Core.uTag == ASN1_TAG_UTC_TIME)
+/** True if generalized time. */
+#define RTASN1TIME_IS_GENERALIZED_TIME(a_pAsn1Time) ((a_pAsn1Time)->Asn1Core.uTag == ASN1_TAG_GENERALIZED_TIME)
+/** @} */
+
+RTASN1_IMPL_GEN_SEQ_OF_TYPEDEFS_AND_PROTOS(RTASN1SEQOFTIMES, RTASN1TIME, RTDECL, RTAsn1SeqOfTimes);
+RTASN1_IMPL_GEN_SET_OF_TYPEDEFS_AND_PROTOS(RTASN1SETOFTIMES, RTASN1TIME, RTDECL, RTAsn1SetOfTimes);
+
+
+
+/**
+ * ASN.1 object identifier (IPRT representation).
+ */
+typedef struct RTASN1OBJID
+{
+ /** Core ASN.1 encoding details. */
+ RTASN1CORE Asn1Core;
+ /** Coverning the paComponents memory allocation if there isn't enough room in
+ * szObjId for both the dottet string and the component values. */
+ RTASN1ALLOCATION Allocation;
+ /** Pointer to an array with the component values.
+ * This may point within szObjId if there is enough space for both there. */
+ uint32_t const *pauComponents;
+ /** The number of components in the object identifier.
+ * This ASSUMES that nobody will be ever needing more than 255 components. */
+ uint8_t cComponents;
+ /** The dotted string representation of the object identifier.
+ * If there is sufficient space after the string, we will place the array that
+ * paComponents points to here and/or the raw content bytes (Asn1Core.uData).
+ *
+ * An analysis of dumpasn1.cfg, hl7.org and our own _OID defines indicates
+ * that we need space for at least 10 components and 30-something chars. We've
+ * allocated 87 bytes, which we ASSUME should be enough for everyone. */
+ char szObjId[87];
+} RTASN1OBJID;
+/** Pointer to an ASN.1 object identifier representation. */
+typedef RTASN1OBJID *PRTASN1OBJID;
+/** Pointer to a const ASN.1 object identifier representation. */
+typedef RTASN1OBJID const *PCRTASN1OBJID;
+/** The Vtable for a RTASN1OBJID structure. */
+extern RTDATADECL(RTASN1COREVTABLE const) g_RTAsn1ObjId_Vtable;
+
+RTASN1TYPE_STANDARD_PROTOTYPES(RTASN1OBJID, RTDECL, RTAsn1ObjId, Asn1Core);
+
+RTDECL(int) RTAsn1ObjId_InitFromString(PRTASN1OBJID pThis, const char *pszObjId, PCRTASN1ALLOCATORVTABLE pAllocator);
+RTDECL(int) RTAsn1ObjId_SetFromString(PRTASN1OBJID pThis, const char *pszObjId, PCRTASN1ALLOCATORVTABLE pAllocator);
+
+/**
+ * Compares an ASN.1 object identifier with a dotted object identifier string.
+ *
+ * @returns 0 if equal, -1 if @a pLeft is smaller, 1 if @a pLeft is larger.
+ * @param pThis The ASN.1 object identifier.
+ * @param pszRight The dotted object identifier string.
+ */
+RTDECL(int) RTAsn1ObjId_CompareWithString(PCRTASN1OBJID pThis, const char *pszRight);
+
+/**
+ * Checks if an ASN.1 object identifier starts with the given dotted object
+ * identifier string.
+ *
+ * The matching is only successful if the given string matches matches the last
+ * component completely.
+ *
+ * @returns true / false.
+ * @param pThis The ASN.1 object identifier.
+ * @param pszStartsWith The dotted object identifier string.
+ */
+RTDECL(bool) RTAsn1ObjId_StartsWith(PCRTASN1OBJID pThis, const char *pszStartsWith);
+
+RTDECL(uint8_t) RTAsn1ObjIdCountComponents(PCRTASN1OBJID pThis);
+RTDECL(uint32_t) RTAsn1ObjIdGetComponentsAsUInt32(PCRTASN1OBJID pThis, uint8_t iComponent);
+RTDECL(uint32_t) RTAsn1ObjIdGetLastComponentsAsUInt32(PCRTASN1OBJID pThis);
+
+RTASN1_IMPL_GEN_SEQ_OF_TYPEDEFS_AND_PROTOS(RTASN1SEQOFOBJIDS, RTASN1OBJID, RTDECL, RTAsn1SeqOfObjIds);
+RTASN1_IMPL_GEN_SET_OF_TYPEDEFS_AND_PROTOS(RTASN1SETOFOBJIDS, RTASN1OBJID, RTDECL, RTAsn1SetOfObjIds);
+RTASN1_IMPL_GEN_SET_OF_TYPEDEFS_AND_PROTOS(RTASN1SETOFOBJIDSEQS, RTASN1SEQOFOBJIDS, RTDECL, RTAsn1SetOfObjIdSeqs);
+
+
+/**
+ * ASN.1 bit string (IPRT representation).
+ */
+typedef struct RTASN1BITSTRING
+{
+ /** Core ASN.1 encoding details. */
+ RTASN1CORE Asn1Core;
+ /** The number of bits. */
+ uint32_t cBits;
+ /** The max number of bits (given at decoding / construction). */
+ uint32_t cMaxBits;
+ /** Pointer to the bits. */
+ RTCPTRUNION uBits;
+ /** Pointer to user structure encapsulated in this string, if dynamically
+ * allocated the EncapsulatedAllocation member can be used to track it and
+ * trigger automatic cleanup on object destruction. If EncapsulatedAllocation
+ * is zero, any object pointed to will only be deleted. */
+ PRTASN1CORE pEncapsulated;
+ /** Allocation tracking structure for pEncapsulated. */
+ RTASN1ALLOCATION EncapsulatedAllocation;
+} RTASN1BITSTRING;
+/** Pointer to the IPRT representation of an ASN.1 bit string. */
+typedef RTASN1BITSTRING *PRTASN1BITSTRING;
+/** Pointer to the const IPRT representation of an ASN.1 bit string. */
+typedef RTASN1BITSTRING const *PCRTASN1BITSTRING;
+/** The Vtable for a RTASN1BITSTRING structure. */
+extern RTDATADECL(RTASN1COREVTABLE const) g_RTAsn1BitString_Vtable;
+
+RTASN1TYPE_STANDARD_PROTOTYPES(RTASN1BITSTRING, RTDECL, RTAsn1BitString, Asn1Core);
+
+/**
+ * Calculates pointer to the first bit.
+ *
+ * @returns Byte pointer to the first bit.
+ * @param a_pBitString The ASN.1 bit string.
+ */
+#define RTASN1BITSTRING_GET_BIT0_PTR(a_pBitString) ( &(a_pBitString)->Asn1Core.uData.pu8[1] )
+
+/**
+ * Calculates the size in bytes.
+ *
+ * @returns Rounded up size in bytes.
+ * @param a_pBitString The ASN.1 bit string.
+ */
+#define RTASN1BITSTRING_GET_BYTE_SIZE(a_pBitString) ( ((a_pBitString)->cBits + 7U) >> 3 )
+
+RTDECL(int) RTAsn1BitString_InitWithData(PRTASN1BITSTRING pThis, void const *pvSrc, uint32_t cSrcBits,
+ PCRTASN1ALLOCATORVTABLE pAllocator);
+RTDECL(int) RTAsn1BitString_DecodeAsn1Ex(PRTASN1CURSOR pCursor, uint32_t fFlags, uint32_t cMaxBits, PRTASN1BITSTRING pThis,
+ const char *pszErrorTag);
+RTDECL(uint64_t) RTAsn1BitString_GetAsUInt64(PCRTASN1BITSTRING pThis);
+RTDECL(int) RTAsn1BitString_RefreshContent(PRTASN1BITSTRING pThis, uint32_t fFlags,
+ PCRTASN1ALLOCATORVTABLE pAllocator, PRTERRINFO pErrInfo);
+RTDECL(bool) RTAsn1BitString_AreContentBitsValid(PCRTASN1BITSTRING pThis, uint32_t fFlags);
+
+RTASN1_IMPL_GEN_SEQ_OF_TYPEDEFS_AND_PROTOS(RTASN1SEQOFBITSTRINGS, RTASN1BITSTRING, RTDECL, RTAsn1SeqOfBitStrings);
+RTASN1_IMPL_GEN_SET_OF_TYPEDEFS_AND_PROTOS(RTASN1SETOFBITSTRINGS, RTASN1BITSTRING, RTDECL, RTAsn1SetOfBitStrings);
+
+
+/**
+ * ASN.1 octet string (IPRT representation).
+ */
+typedef struct RTASN1OCTETSTRING
+{
+ /** Core ASN.1 encoding details. */
+ RTASN1CORE Asn1Core;
+ /** Pointer to user structure encapsulated in this string.
+ *
+ * If dynamically allocated the EncapsulatedAllocation member can be used to
+ * track it and trigger automatic cleanup on object destruction. If
+ * EncapsulatedAllocation is zero, any object pointed to will only be
+ * deleted. */
+ PRTASN1CORE pEncapsulated;
+ /** Allocation tracking structure for pEncapsulated. */
+ RTASN1ALLOCATION EncapsulatedAllocation;
+} RTASN1OCTETSTRING;
+/** Pointer to the IPRT representation of an ASN.1 octet string. */
+typedef RTASN1OCTETSTRING *PRTASN1OCTETSTRING;
+/** Pointer to the const IPRT representation of an ASN.1 octet string. */
+typedef RTASN1OCTETSTRING const *PCRTASN1OCTETSTRING;
+/** The Vtable for a RTASN1OCTETSTRING structure. */
+extern RTDATADECL(RTASN1COREVTABLE const) g_RTAsn1OctetString_Vtable;
+
+RTASN1TYPE_STANDARD_PROTOTYPES(RTASN1OCTETSTRING, RTDECL, RTAsn1OctetString, Asn1Core);
+
+RTDECL(int) RTAsn1OctetString_AllocContent(PRTASN1OCTETSTRING pThis, void const *pvSrc, size_t cb,
+ PCRTASN1ALLOCATORVTABLE pAllocator);
+RTDECL(int) RTAsn1OctetString_SetContent(PRTASN1OCTETSTRING pThis, void const *pvSrc, size_t cbSrc,
+ PCRTASN1ALLOCATORVTABLE pAllocator);
+RTDECL(bool) RTAsn1OctetString_AreContentBytesValid(PCRTASN1OCTETSTRING pThis, uint32_t fFlags);
+RTDECL(int) RTAsn1OctetString_RefreshContent(PRTASN1OCTETSTRING pThis, uint32_t fFlags,
+ PCRTASN1ALLOCATORVTABLE pAllocator, PRTERRINFO pErrInfo);
+
+RTASN1_IMPL_GEN_SEQ_OF_TYPEDEFS_AND_PROTOS(RTASN1SEQOFOCTETSTRINGS, RTASN1OCTETSTRING, RTDECL, RTAsn1SeqOfOctetStrings);
+RTASN1_IMPL_GEN_SET_OF_TYPEDEFS_AND_PROTOS(RTASN1SETOFOCTETSTRINGS, RTASN1OCTETSTRING, RTDECL, RTAsn1SetOfOctetStrings);
+
+
+/**
+ * ASN.1 string (IPRT representation).
+ * All char string types except 'character string (29)'.
+ */
+typedef struct RTASN1STRING
+{
+ /** Core ASN.1 encoding details. */
+ RTASN1CORE Asn1Core;
+ /** Allocation tracking for pszUtf8. */
+ RTASN1ALLOCATION Allocation;
+ /** If conversion to UTF-8 was requested, we cache that here. */
+ char const *pszUtf8;
+ /** The length (chars, not code points) of the above UTF-8 string if
+ * present. */
+ uint32_t cchUtf8;
+} RTASN1STRING;
+/** Pointer to the IPRT representation of an ASN.1 string. */
+typedef RTASN1STRING *PRTASN1STRING;
+/** Pointer to the const IPRT representation of an ASN.1 string. */
+typedef RTASN1STRING const *PCRTASN1STRING;
+/** The Vtable for a RTASN1STRING structure. */
+extern RTDATADECL(RTASN1COREVTABLE const) g_RTAsn1String_Vtable;
+
+RTASN1TYPE_STANDARD_PROTOTYPES(RTASN1STRING, RTDECL, RTAsn1String, Asn1Core);
+
+/** @name String type predicate macros.
+ * @{ */
+#define RTASN1STRING_IS_NUMERIC(a_pAsn1String) ( RTASN1CORE_GET_TAG(&(a_pAsn1String)->Asn1Core) == ASN1_TAG_NUMERIC_STRING )
+#define RTASN1STRING_IS_PRINTABLE(a_pAsn1String) ( RTASN1CORE_GET_TAG(&(a_pAsn1String)->Asn1Core) == ASN1_TAG_PRINTABLE_STRING )
+#define RTASN1STRING_IS_T61(a_pAsn1String) ( RTASN1CORE_GET_TAG(&(a_pAsn1String)->Asn1Core) == ASN1_TAG_T61_STRING )
+#define RTASN1STRING_IS_VIDEOTEX(a_pAsn1String) ( RTASN1CORE_GET_TAG(&(a_pAsn1String)->Asn1Core) == ASN1_TAG_VIDEOTEX_STRING )
+#define RTASN1STRING_IS_VISIBLE(a_pAsn1String) ( RTASN1CORE_GET_TAG(&(a_pAsn1String)->Asn1Core) == ASN1_TAG_VISIBLE_STRING )
+#define RTASN1STRING_IS_IA5(a_pAsn1String) ( RTASN1CORE_GET_TAG(&(a_pAsn1String)->Asn1Core) == ASN1_TAG_IA5_STRING )
+#define RTASN1STRING_IS_GRAPHIC(a_pAsn1String) ( RTASN1CORE_GET_TAG(&(a_pAsn1String)->Asn1Core) == ASN1_TAG_GRAPHIC_STRING )
+#define RTASN1STRING_IS_GENERAL(a_pAsn1String) ( RTASN1CORE_GET_TAG(&(a_pAsn1String)->Asn1Core) == ASN1_TAG_GENERAL_STRING )
+/** UTF-8. */
+#define RTASN1STRING_IS_UTF8(a_pAsn1String) ( RTASN1CORE_GET_TAG(&(a_pAsn1String)->Asn1Core) == ASN1_TAG_UTF8_STRING )
+/** UCS-2. */
+#define RTASN1STRING_IS_BMP(a_pAsn1String) ( RTASN1CORE_GET_TAG(&(a_pAsn1String)->Asn1Core) == ASN1_TAG_BMP_STRING )
+/** UCS-4. */
+#define RTASN1STRING_IS_UNIVERSAL(a_pAsn1String) ( RTASN1CORE_GET_TAG(&(a_pAsn1String)->Asn1Core) == ASN1_TAG_UNIVERSAL_STRING )
+/** @} */
+
+RTASN1TYPE_STANDARD_PROTOTYPES(RTASN1STRING, RTDECL, RTAsn1NumericString, Asn1Core);
+RTASN1TYPE_STANDARD_PROTOTYPES(RTASN1STRING, RTDECL, RTAsn1PrintableString, Asn1Core);
+RTASN1TYPE_STANDARD_PROTOTYPES(RTASN1STRING, RTDECL, RTAsn1T61String, Asn1Core);
+RTASN1TYPE_STANDARD_PROTOTYPES(RTASN1STRING, RTDECL, RTAsn1VideoTexString, Asn1Core);
+RTASN1TYPE_STANDARD_PROTOTYPES(RTASN1STRING, RTDECL, RTAsn1VisibleString, Asn1Core);
+RTASN1TYPE_STANDARD_PROTOTYPES(RTASN1STRING, RTDECL, RTAsn1Ia5String, Asn1Core);
+RTASN1TYPE_STANDARD_PROTOTYPES(RTASN1STRING, RTDECL, RTAsn1GraphicString, Asn1Core);
+RTASN1TYPE_STANDARD_PROTOTYPES(RTASN1STRING, RTDECL, RTAsn1GeneralString, Asn1Core);
+RTASN1TYPE_STANDARD_PROTOTYPES(RTASN1STRING, RTDECL, RTAsn1Utf8String, Asn1Core);
+RTASN1TYPE_STANDARD_PROTOTYPES(RTASN1STRING, RTDECL, RTAsn1BmpString, Asn1Core);
+RTASN1TYPE_STANDARD_PROTOTYPES(RTASN1STRING, RTDECL, RTAsn1UniversalString, Asn1Core);
+
+RTDECL(int) RTAsn1String_InitWithValue(PRTASN1STRING pThis, const char *pszUtf8Value, PCRTASN1ALLOCATORVTABLE pAllocator);
+RTDECL(int) RTAsn1String_InitEx(PRTASN1STRING pThis, uint32_t uTag, void const *pvValue, size_t cbValue,
+ PCRTASN1ALLOCATORVTABLE pAllocator);
+
+/**
+ * Compares two strings values, extended version.
+ *
+ * @returns 0 if equal, -1 if @a pLeft is smaller, 1 if @a pLeft is larger.
+ * @param pLeft The first string.
+ * @param pRight The second string.
+ * @param fTypeToo Set if the string types must match, false if
+ * not.
+ */
+RTDECL(int) RTAsn1String_CompareEx(PCRTASN1STRING pLeft, PCRTASN1STRING pRight, bool fTypeToo);
+RTDECL(int) RTAsn1String_CompareValues(PCRTASN1STRING pLeft, PCRTASN1STRING pRight);
+
+/**
+ * Compares a ASN.1 string object with an UTF-8 string.
+ *
+ * @returns 0 if equal, -1 if @a pThis is smaller, 1 if @a pThis is larger.
+ * @param pThis The ASN.1 string object.
+ * @param pszString The UTF-8 string.
+ * @param cchString The length of @a pszString, or RTSTR_MAX.
+ */
+RTDECL(int) RTAsn1String_CompareWithString(PCRTASN1STRING pThis, const char *pszString, size_t cchString);
+
+/**
+ * Queries the UTF-8 length of an ASN.1 string object.
+ *
+ * This differs from RTAsn1String_QueryUtf8 in that it won't need to allocate
+ * memory for the converted string, but just calculates the length.
+ *
+ * @returns IPRT status code.
+ * @param pThis The ASN.1 string object.
+ * @param pcch Where to return the string length.
+ */
+RTDECL(int) RTAsn1String_QueryUtf8Len(PCRTASN1STRING pThis, size_t *pcch);
+
+/**
+ * Queries the UTF-8 string for an ASN.1 string object.
+ *
+ * This may fail as it may require memory to be allocated for storing the
+ * string.
+ *
+ * @returns IPRT status code.
+ * @param pString The ASN.1 string object. This is a const
+ * parameter for making life easier on the caller,
+ * however be aware that the object may be modified
+ * by this call!
+ * @param ppsz Where to return the pointer to the UTF-8 string.
+ * Optional.
+ * @param pcch Where to return the length (in 8-bit chars) to
+ * of the UTF-8 string. Optional.
+ */
+RTDECL(int) RTAsn1String_QueryUtf8(PCRTASN1STRING pString, const char **ppsz, size_t *pcch);
+RTDECL(int) RTAsn1String_RecodeAsUtf8(PRTASN1STRING pThis, PCRTASN1ALLOCATORVTABLE pAllocator);
+
+RTASN1_IMPL_GEN_SEQ_OF_TYPEDEFS_AND_PROTOS(RTASN1SEQOFSTRINGS, RTASN1STRING, RTDECL, RTAsn1SeqOfStrings);
+RTASN1_IMPL_GEN_SET_OF_TYPEDEFS_AND_PROTOS(RTASN1SETOFSTRINGS, RTASN1STRING, RTDECL, RTAsn1SetOfStrings);
+
+
+
+/**
+ * ASN.1 generic context specific tag (IPRT representation).
+ *
+ * Normally used to tag something that's optional, version specific or such.
+ *
+ * For the purpose of documenting the format with typedefs as well as possibly
+ * making it a little more type safe, there's a set of typedefs for the most
+ * commonly used tag values defined. These typedefs have are identical to
+ * RTASN1CONTEXTTAG, except from the C++ type system point of view.
+ */
+typedef struct RTASN1CONTEXTTAG
+{
+ /** Core ASN.1 encoding details. */
+ RTASN1CORE Asn1Core;
+} RTASN1CONTEXTTAG;
+/** Pointer to an ASN.1 context tag (IPRT thing). */
+typedef RTASN1CONTEXTTAG *PRTASN1CONTEXTTAG;
+/** Pointer to a const ASN.1 context tag (IPRT thing). */
+typedef RTASN1CONTEXTTAG const *PCRTASN1CONTEXTTAG;
+
+RTDECL(int) RTAsn1ContextTagN_Init(PRTASN1CONTEXTTAG pThis, uint32_t uTag, PCRTASN1COREVTABLE pVtable);
+RTDECL(int) RTAsn1ContextTagN_Clone(PRTASN1CONTEXTTAG pThis, PCRTASN1CONTEXTTAG pSrc, uint32_t uTag);
+
+
+/** @internal */
+#define RTASN1CONTEXTTAG_DO_TYPEDEF_AND_INLINE(a_uTag) \
+ typedef struct RT_CONCAT(RTASN1CONTEXTTAG,a_uTag) { RTASN1CORE Asn1Core; } RT_CONCAT(RTASN1CONTEXTTAG,a_uTag); \
+ typedef RT_CONCAT(RTASN1CONTEXTTAG,a_uTag) *RT_CONCAT(PRTASN1CONTEXTTAG,a_uTag); \
+ DECLINLINE(int) RT_CONCAT3(RTAsn1ContextTag,a_uTag,_Init)(RT_CONCAT(PRTASN1CONTEXTTAG,a_uTag) pThis, \
+ PCRTASN1COREVTABLE pVtable, PCRTASN1ALLOCATORVTABLE pAllocator) \
+ { \
+ NOREF(pAllocator); \
+ return RTAsn1ContextTagN_Init((PRTASN1CONTEXTTAG)pThis, a_uTag, pVtable); \
+ } \
+ DECLINLINE(int) RT_CONCAT3(RTAsn1ContextTag,a_uTag,_Clone)(RT_CONCAT(PRTASN1CONTEXTTAG,a_uTag) pThis, \
+ RT_CONCAT(RTASN1CONTEXTTAG,a_uTag) const *pSrc) \
+ { return RTAsn1ContextTagN_Clone((PRTASN1CONTEXTTAG)pThis, (PCRTASN1CONTEXTTAG)pSrc, a_uTag); } \
+ typedef RT_CONCAT(RTASN1CONTEXTTAG,a_uTag) const *RT_CONCAT(PCRTASN1CONTEXTTAG,a_uTag)
+RTASN1CONTEXTTAG_DO_TYPEDEF_AND_INLINE(0);
+RTASN1CONTEXTTAG_DO_TYPEDEF_AND_INLINE(1);
+RTASN1CONTEXTTAG_DO_TYPEDEF_AND_INLINE(2);
+RTASN1CONTEXTTAG_DO_TYPEDEF_AND_INLINE(3);
+RTASN1CONTEXTTAG_DO_TYPEDEF_AND_INLINE(4);
+RTASN1CONTEXTTAG_DO_TYPEDEF_AND_INLINE(5);
+RTASN1CONTEXTTAG_DO_TYPEDEF_AND_INLINE(6);
+RTASN1CONTEXTTAG_DO_TYPEDEF_AND_INLINE(7);
+#undef RTASN1CONTEXTTAG_DO_TYPEDEF_AND_INLINE
+
+/** Helper for comparing optional context tags.
+ * This will return if both are not present or if their precense differs.
+ * @internal */
+#define RTASN1CONTEXTTAG_COMPARE_PRESENT_RETURN_INTERNAL(a_iDiff, a_pLeft, a_pRight, a_uTag) \
+ do { \
+ /* type checks */ \
+ RT_CONCAT(PCRTASN1CONTEXTTAG,a_uTag) const pMyLeftInternal = (a_pLeft); \
+ RT_CONCAT(PCRTASN1CONTEXTTAG,a_uTag) const pMyRightInternal = (a_pRight); \
+ (a_iDiff) = (int)RTASN1CORE_IS_PRESENT(&pMyLeftInternal->Asn1Core) \
+ - (int)RTASN1CORE_IS_PRESENT(&pMyRightInternal->Asn1Core); \
+ if ((a_iDiff) || !RTASN1CORE_IS_PRESENT(&pMyLeftInternal->Asn1Core)) return iDiff; \
+ } while (0)
+
+/** @name Helpers for comparing optional context tags.
+ * This will return if both are not present or if their precense differs.
+ * @{ */
+#define RTASN1CONTEXTTAG0_COMPARE_PRESENT_RETURN(a_iDiff, a_pLeft, a_pRight) RTASN1CONTEXTTAG_COMPARE_PRESENT_RETURN_INTERNAL(a_iDiff, a_pLeft, a_pRight, 0)
+#define RTASN1CONTEXTTAG1_COMPARE_PRESENT_RETURN(a_iDiff, a_pLeft, a_pRight) RTASN1CONTEXTTAG_COMPARE_PRESENT_RETURN_INTERNAL(a_iDiff, a_pLeft, a_pRight, 1)
+#define RTASN1CONTEXTTAG2_COMPARE_PRESENT_RETURN(a_iDiff, a_pLeft, a_pRight) RTASN1CONTEXTTAG_COMPARE_PRESENT_RETURN_INTERNAL(a_iDiff, a_pLeft, a_pRight, 2)
+#define RTASN1CONTEXTTAG3_COMPARE_PRESENT_RETURN(a_iDiff, a_pLeft, a_pRight) RTASN1CONTEXTTAG_COMPARE_PRESENT_RETURN_INTERNAL(a_iDiff, a_pLeft, a_pRight, 3)
+#define RTASN1CONTEXTTAG4_COMPARE_PRESENT_RETURN(a_iDiff, a_pLeft, a_pRight) RTASN1CONTEXTTAG_COMPARE_PRESENT_RETURN_INTERNAL(a_iDiff, a_pLeft, a_pRight, 4)
+#define RTASN1CONTEXTTAG5_COMPARE_PRESENT_RETURN(a_iDiff, a_pLeft, a_pRight) RTASN1CONTEXTTAG_COMPARE_PRESENT_RETURN_INTERNAL(a_iDiff, a_pLeft, a_pRight, 5)
+#define RTASN1CONTEXTTAG6_COMPARE_PRESENT_RETURN(a_iDiff, a_pLeft, a_pRight) RTASN1CONTEXTTAG_COMPARE_PRESENT_RETURN_INTERNAL(a_iDiff, a_pLeft, a_pRight, 6)
+#define RTASN1CONTEXTTAG7_COMPARE_PRESENT_RETURN(a_iDiff, a_pLeft, a_pRight) RTASN1CONTEXTTAG_COMPARE_PRESENT_RETURN_INTERNAL(a_iDiff, a_pLeft, a_pRight, 7)
+/** @} */
+
+
+/**
+ * Type information for dynamically bits (see RTASN1DYNTYPE).
+ */
+typedef enum RTASN1TYPE
+{
+ /** Not present. */
+ RTASN1TYPE_NOT_PRESENT = 0,
+ /** Generic ASN.1 for unknown tag/class. */
+ RTASN1TYPE_CORE,
+ /** ASN.1 NULL. */
+ RTASN1TYPE_NULL,
+ /** ASN.1 integer. */
+ RTASN1TYPE_INTEGER,
+ /** ASN.1 boolean. */
+ RTASN1TYPE_BOOLEAN,
+ /** ASN.1 character string. */
+ RTASN1TYPE_STRING,
+ /** ASN.1 octet string. */
+ RTASN1TYPE_OCTET_STRING,
+ /** ASN.1 bite string. */
+ RTASN1TYPE_BIT_STRING,
+ /** ASN.1 UTC or Generalize time. */
+ RTASN1TYPE_TIME,
+#if 0
+ /** ASN.1 sequence core. */
+ RTASN1TYPE_SEQUENCE_CORE,
+ /** ASN.1 set core. */
+ RTASN1TYPE_SET_CORE,
+#endif
+ /** ASN.1 object identifier. */
+ RTASN1TYPE_OBJID,
+ /** End of valid types. */
+ RTASN1TYPE_END,
+ /** Type size hack. */
+ RTASN1TYPE_32BIT_HACK = 0x7fffffff
+} RTASN1TYPE;
+
+
+/**
+ * ASN.1 dynamic type record.
+ */
+typedef struct RTASN1DYNTYPE
+{
+ /** Alternative interpretation provided by a user.
+ * Before destroying this object, the user must explicitly free this and set
+ * it to NULL, otherwise there will be memory leaks. */
+ PRTASN1CORE pUser;
+ /** The type of data we've got here. */
+ RTASN1TYPE enmType;
+ /** Union with data of the type dictated by enmType. */
+ union
+ {
+ /** RTASN1TYPE_CORE. */
+ RTASN1CORE Core;
+ /** RTASN1TYPE_NULL. */
+ RTASN1NULL Asn1Null;
+ /** RTASN1TYPE_INTEGER. */
+ RTASN1INTEGER Integer;
+ /** RTASN1TYPE_BOOLEAN. */
+ RTASN1BOOLEAN Boolean;
+ /** RTASN1TYPE_STRING. */
+ RTASN1STRING String;
+ /** RTASN1TYPE_OCTET_STRING. */
+ RTASN1OCTETSTRING OctetString;
+ /** RTASN1TYPE_BIT_STRING. */
+ RTASN1BITSTRING BitString;
+ /** RTASN1TYPE_TIME. */
+ RTASN1TIME Time;
+#if 0
+ /** RTASN1TYPE_SEQUENCE_CORE. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** RTASN1TYPE_SET_CORE. */
+ RTASN1SETCORE SetCore;
+#endif
+ /** RTASN1TYPE_OBJID. */
+ RTASN1OBJID ObjId;
+ } u;
+} RTASN1DYNTYPE;
+/** Pointer to an ASN.1 dynamic type record. */
+typedef RTASN1DYNTYPE *PRTASN1DYNTYPE;
+/** Pointer to a const ASN.1 dynamic type record. */
+typedef RTASN1DYNTYPE const *PCRTASN1DYNTYPE;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTASN1DYNTYPE, RTDECL, RTAsn1DynType, u.Core);
+RTDECL(int) RTAsn1DynType_SetToNull(PRTASN1DYNTYPE pThis);
+
+
+/** @name Virtual Method Table Based API
+ * @{ */
+/**
+ * Calls the destructor of the ASN.1 object.
+ *
+ * @param pThisCore The IPRT representation of an ASN.1 object.
+ */
+RTDECL(void) RTAsn1VtDelete(PRTASN1CORE pThisCore);
+
+/**
+ * Deep enumeration of all descendants.
+ *
+ * @returns IPRT status code, any non VINF_SUCCESS value stems from pfnCallback.
+ * @param pThisCore Pointer to the ASN.1 core to enumerate members of.
+ * @param pfnCallback The callback.
+ * @param uDepth The depth of this object. Children are at +1.
+ * @param pvUser Callback user argument.
+ * @param fDepthFirst When set, recurse into child objects before calling
+ * pfnCallback on then. When clear, the child object
+ * is first
+ */
+RTDECL(int) RTAsn1VtDeepEnum(PRTASN1CORE pThisCore, bool fDepthFirst, uint32_t uDepth,
+ PFNRTASN1ENUMCALLBACK pfnCallback, void *pvUser);
+
+/**
+ * Clones @a pSrcCore onto @a pThisCore.
+ *
+ * The caller must be sure that @a pSrcCore and @a pThisCore are of the same
+ * types.
+ *
+ * @returns IPRT status code.
+ * @param pThisCore Pointer to the ASN.1 core to clone onto. This shall
+ * be uninitialized.
+ * @param pSrcCore Pointer to the ASN.1 core to clone.
+ * @param pAllocator The allocator to use.
+ */
+RTDECL(int) RTAsn1VtClone(PRTASN1CORE pThisCore, PRTASN1CORE pSrcCore, PCRTASN1ALLOCATORVTABLE pAllocator);
+
+/**
+ * Compares two objects.
+ *
+ * @returns 0 if equal, -1 if @a pLeft is smaller, 1 if @a pLeft is larger.
+ * @param pLeftCore Pointer to the ASN.1 core of the left side object.
+ * @param pRightCore Pointer to the ASN.1 core of the right side object.
+ */
+RTDECL(int) RTAsn1VtCompare(PCRTASN1CORE pLeftCore, PCRTASN1CORE pRightCore);
+
+/**
+ * Check sanity.
+ *
+ * A primary criteria is that the object is present and initialized.
+ *
+ * @returns IPRT status code.
+ * @param pThisCore Pointer to the ASN.1 core of the object to check out.
+ * @param fFlags See RTASN1_CHECK_SANITY_F_XXX.
+ * @param pErrInfo Where to return additional error details. Optional.
+ * @param pszErrorTag Tag for the additional error details.
+ */
+RTDECL(int) RTAsn1VtCheckSanity(PCRTASN1CORE pThisCore, uint32_t fFlags,
+ PRTERRINFO pErrInfo, const char *pszErrorTag);
+/** @} */
+
+
+/** @defgroup rp_asn1_encode RTAsn1Encode - ASN.1 Encoding
+ * @{ */
+
+/** @name RTASN1ENCODE_F_XXX
+ * @{ */
+/** Use distinguished encoding rules (DER) to encode the object. */
+#define RTASN1ENCODE_F_DER UINT32_C(0x00000001)
+/** Use base encoding rules (BER) to encode the object.
+ * This is currently the same as DER for practical reasons. */
+#define RTASN1ENCODE_F_BER RTASN1ENCODE_F_DER
+/** Mask of valid encoding rules. */
+#define RTASN1ENCODE_F_RULE_MASK UINT32_C(0x00000007)
+/** @} */
+
+
+/**
+ * Recalculates cbHdr of and ASN.1 object.
+ *
+ * @returns IPRT status code.
+ * @retval VINF_ASN1_NOT_ENCODED if the header size is zero (default value,
+ * whatever).
+ * @param pAsn1Core The object in question.
+ * @param fFlags Valid combination of the RTASN1ENCODE_F_XXX
+ * flags. Must include the encoding type.
+ * @param pErrInfo Extended error info. Optional.
+ */
+RTDECL(int) RTAsn1EncodeRecalcHdrSize(PRTASN1CORE pAsn1Core, uint32_t fFlags, PRTERRINFO pErrInfo);
+
+/**
+ * Prepares the ASN.1 structure for encoding.
+ *
+ * The preparations is mainly calculating accurate object size, but may also
+ * involve operations like recoding internal UTF-8 strings to the actual ASN.1
+ * format and other things that may require memory to allocated/reallocated.
+ *
+ * @returns IPRT status code
+ * @param pRoot The root of the ASN.1 object tree to encode.
+ * @param fFlags Valid combination of the RTASN1ENCODE_F_XXX
+ * flags. Must include the encoding type.
+ * @param pcbEncoded Where to return the encoded size. Optional.
+ * @param pErrInfo Where to store extended error information.
+ * Optional.
+ */
+RTDECL(int) RTAsn1EncodePrepare(PRTASN1CORE pRoot, uint32_t fFlags, uint32_t *pcbEncoded, PRTERRINFO pErrInfo);
+
+/**
+ * Encodes and writes the header of an ASN.1 object.
+ *
+ * @returns IPRT status code.
+ * @retval VINF_ASN1_NOT_ENCODED if nothing was written (default value,
+ * whatever).
+ * @param pAsn1Core The object in question.
+ * @param fFlags Valid combination of the RTASN1ENCODE_F_XXX
+ * flags. Must include the encoding type.
+ * @param pfnWriter The output writer callback.
+ * @param pvUser The user argument to pass to @a pfnWriter.
+ * @param pErrInfo Where to store extended error information.
+ * Optional.
+ */
+RTDECL(int) RTAsn1EncodeWriteHeader(PCRTASN1CORE pAsn1Core, uint32_t fFlags, FNRTASN1ENCODEWRITER pfnWriter, void *pvUser,
+ PRTERRINFO pErrInfo);
+
+/**
+ * Encodes and writes an ASN.1 object.
+ *
+ * @returns IPRT status code
+ * @param pRoot The root of the ASN.1 object tree to encode.
+ * @param fFlags Valid combination of the RTASN1ENCODE_F_XXX
+ * flags. Must include the encoding type.
+ * @param pfnWriter The output writer callback.
+ * @param pvUser The user argument to pass to @a pfnWriter.
+ * @param pErrInfo Where to store extended error information.
+ * Optional.
+ */
+RTDECL(int) RTAsn1EncodeWrite(PCRTASN1CORE pRoot, uint32_t fFlags, FNRTASN1ENCODEWRITER pfnWriter, void *pvUser,
+ PRTERRINFO pErrInfo);
+
+/**
+ * Encodes and writes an ASN.1 object into a caller allocated memory buffer.
+ *
+ * @returns IPRT status code
+ * @param pRoot The root of the ASN.1 object tree to encode.
+ * @param fFlags Valid combination of the RTASN1ENCODE_F_XXX
+ * flags. Must include the encoding type.
+ * @param pvBuf The output buffer.
+ * @param cbBuf The buffer size. This should have the size
+ * returned by RTAsn1EncodePrepare().
+ * @param pErrInfo Where to store extended error information.
+ * Optional.
+ */
+RTDECL(int) RTAsn1EncodeToBuffer(PCRTASN1CORE pRoot, uint32_t fFlags, void *pvBuf, size_t cbBuf, PRTERRINFO pErrInfo);
+
+/**
+ * Helper for when DER encoded ASN.1 is needed for something.
+ *
+ * Handy when interfacing with OpenSSL and the many d2i_Xxxxx OpenSSL functions,
+ * but also handy when structures needs to be digested or similar during signing
+ * or verification.
+ *
+ * We sometimes can use the data we've decoded directly, but often we have
+ * encode it into a temporary heap buffer.
+ *
+ * @returns IPRT status code, details in @a pErrInfo if present.
+ * @param pRoot The ASN.1 root of the structure to be passed to OpenSSL.
+ * @param ppbRaw Where to return the pointer to raw encoded data.
+ * @param pcbRaw Where to return the size of the raw encoded data.
+ * @param ppvFree Where to return what to pass to RTMemTmpFree, i.e. NULL
+ * if we use the previously decoded data directly and
+ * non-NULL if we had to allocate heap and encode it.
+ * @param pErrInfo Where to return details about encoding issues. Optional.
+ */
+RTDECL(int) RTAsn1EncodeQueryRawBits(PRTASN1CORE pRoot, const uint8_t **ppbRaw, uint32_t *pcbRaw,
+ void **ppvFree, PRTERRINFO pErrInfo);
+
+/** @} */
+
+
+
+/** @defgroup rp_asn1_cursor RTAsn1Cursor - BER, DER, and CER cursor
+ * @{ */
+
+/**
+ * ASN.1 decoder byte cursor.
+ */
+typedef struct RTASN1CURSOR
+{
+ /** Pointer to the current (next) byte. */
+ uint8_t const *pbCur;
+ /** Number of bytes left to decode. */
+ uint32_t cbLeft;
+ /** RTASN1CURSOR_FLAGS_XXX. */
+ uint8_t fFlags;
+ /** The cursor depth. */
+ uint8_t cDepth;
+ /** Two bytes reserved for future tricks. */
+ uint8_t abReserved[2];
+ /** Pointer to the primary cursor. */
+ struct RTASN1CURSORPRIMARY *pPrimary;
+ /** Pointer to the parent cursor. */
+ struct RTASN1CURSOR *pUp;
+ /** The error tag for this cursor level. */
+ const char *pszErrorTag;
+} RTASN1CURSOR;
+
+/** @name RTASN1CURSOR_FLAGS_XXX - Cursor flags.
+ * @{ */
+/** Enforce DER rules. */
+#define RTASN1CURSOR_FLAGS_DER RT_BIT(1)
+/** Enforce CER rules. */
+#define RTASN1CURSOR_FLAGS_CER RT_BIT(2)
+/** Pending indefinite length encoding. */
+#define RTASN1CURSOR_FLAGS_INDEFINITE_LENGTH RT_BIT(3)
+/** @} */
+
+
+typedef struct RTASN1CURSORPRIMARY
+{
+ /** The normal cursor bits. */
+ RTASN1CURSOR Cursor;
+ /** For error reporting. */
+ PRTERRINFO pErrInfo;
+ /** The allocator virtual method table. */
+ PCRTASN1ALLOCATORVTABLE pAllocator;
+ /** Pointer to the first byte. Useful for calculating offsets. */
+ uint8_t const *pbFirst;
+} RTASN1CURSORPRIMARY;
+typedef RTASN1CURSORPRIMARY *PRTASN1CURSORPRIMARY;
+
+
+/**
+ * Initializes a primary cursor.
+ *
+ * The primary cursor is special in that it stores information shared with the
+ * sub-cursors created by methods like RTAsn1CursorGetContextTagNCursor and
+ * RTAsn1CursorGetSequenceCursor. Even if just sharing a few items at present,
+ * it still important to save every possible byte since stack space is scarce in
+ * some of the execution environments.
+ *
+ * @returns Pointer to pCursor->Cursor.
+ * @param pPrimaryCursor The primary cursor structure to initialize.
+ * @param pvFirst The first byte to decode.
+ * @param cb The number of bytes to decode.
+ * @param pErrInfo Where to store error information.
+ * @param pAllocator The allocator to use.
+ * @param fFlags RTASN1CURSOR_FLAGS_XXX.
+ * @param pszErrorTag The primary error tag.
+ */
+RTDECL(PRTASN1CURSOR) RTAsn1CursorInitPrimary(PRTASN1CURSORPRIMARY pPrimaryCursor, void const *pvFirst, uint32_t cb,
+ PRTERRINFO pErrInfo, PCRTASN1ALLOCATORVTABLE pAllocator, uint32_t fFlags,
+ const char *pszErrorTag);
+
+RTDECL(int) RTAsn1CursorInitSub(PRTASN1CURSOR pParent, uint32_t cb, PRTASN1CURSOR pChild, const char *pszErrorTag);
+
+/**
+ * Initialize a sub-cursor for traversing the content of an ASN.1 object.
+ *
+ * @returns IPRT status code.
+ * @param pParent The parent cursor.
+ * @param pAsn1Core The ASN.1 object which content we should
+ * traverse with the sub-cursor.
+ * @param pChild The sub-cursor to initialize.
+ * @param pszErrorTag The error tag of the sub-cursor.
+ */
+RTDECL(int) RTAsn1CursorInitSubFromCore(PRTASN1CURSOR pParent, PRTASN1CORE pAsn1Core,
+ PRTASN1CURSOR pChild, const char *pszErrorTag);
+
+/**
+ * Initalizes the an allocation structure prior to making an allocation.
+ *
+ * To try unify and optimize memory managment for decoding and in-memory
+ * construction of ASN.1 objects, each allocation has an allocation structure
+ * associated with it. This stores the allocator and keep statistics for
+ * optimizing resizable allocations.
+ *
+ * @returns Pointer to the allocator info (for call in alloc parameter).
+ * @param pCursor The cursor.
+ * @param pAllocation The allocation structure to initialize.
+ */
+RTDECL(PRTASN1ALLOCATION) RTAsn1CursorInitAllocation(PRTASN1CURSOR pCursor, PRTASN1ALLOCATION pAllocation);
+
+/**
+ * Initalizes the an array allocation structure prior to making an allocation.
+ *
+ * This is a special case of RTAsn1CursorInitAllocation. We store a little bit
+ * more detail here in order to optimize growing and shrinking of arrays.
+ *
+ * @returns Pointer to the allocator info (for call in alloc parameter).
+ * @param pCursor The cursor.
+ * @param pAllocation The allocation structure to initialize.
+ * @param cbEntry The array entry size.
+ */
+RTDECL(PRTASN1ARRAYALLOCATION) RTAsn1CursorInitArrayAllocation(PRTASN1CURSOR pCursor, PRTASN1ARRAYALLOCATION pAllocation,
+ size_t cbEntry);
+
+/**
+ * Wrapper around RTErrInfoSetV.
+ *
+ * @returns @a rc
+ * @param pCursor The cursor.
+ * @param rc The return code to return.
+ * @param pszMsg Message format string.
+ * @param ... Format arguments.
+ */
+RTDECL(int) RTAsn1CursorSetInfo(PRTASN1CURSOR pCursor, int rc, const char *pszMsg, ...) RT_IPRT_FORMAT_ATTR(3, 4);
+
+/**
+ * Wrapper around RTErrInfoSetV.
+ *
+ * @returns @a rc
+ * @param pCursor The cursor.
+ * @param rc The return code to return.
+ * @param pszMsg Message format string.
+ * @param va Format arguments.
+ */
+RTDECL(int) RTAsn1CursorSetInfoV(PRTASN1CURSOR pCursor, int rc, const char *pszMsg, va_list va) RT_IPRT_FORMAT_ATTR(3, 0);
+
+/**
+ * Checks that we've reached the end of the data for the cursor.
+ *
+ * This differs from RTAsn1CursorCheckEnd in that it does not consider the end
+ * an error and therefore leaves the error buffer alone.
+ *
+ * @returns True if end, otherwise false.
+ * @param pCursor The cursor we're decoding from.
+ */
+RTDECL(bool) RTAsn1CursorIsEnd(PRTASN1CURSOR pCursor);
+
+/**
+ * Checks that we've reached the end of the data for the cursor.
+ *
+ * @returns IPRT status code.
+ * @param pCursor The cursor we're decoding from.
+ */
+RTDECL(int) RTAsn1CursorCheckEnd(PRTASN1CURSOR pCursor);
+
+/**
+ * Specialization of RTAsn1CursorCheckEnd for handling indefinite length sequences.
+ *
+ * Makes sure we've reached the end of the data for the cursor, and in case of a
+ * an indefinite length sequence it may adjust sequence length and the parent
+ * cursor.
+ *
+ * @returns IPRT status code.
+ * @param pCursor The cursor we're decoding from.
+ * @param pSeqCore The sequence core record.
+ * @sa RTAsn1CursorCheckSetEnd, RTAsn1CursorCheckOctStrEnd,
+ * RTAsn1CursorCheckEnd
+ */
+RTDECL(int) RTAsn1CursorCheckSeqEnd(PRTASN1CURSOR pCursor, PRTASN1SEQUENCECORE pSeqCore);
+
+/**
+ * Specialization of RTAsn1CursorCheckEnd for handling indefinite length sets.
+ *
+ * Makes sure we've reached the end of the data for the cursor, and in case of a
+ * an indefinite length sets it may adjust set length and the parent cursor.
+ *
+ * @returns IPRT status code.
+ * @param pCursor The cursor we're decoding from.
+ * @param pSetCore The set core record.
+ * @sa RTAsn1CursorCheckSeqEnd, RTAsn1CursorCheckOctStrEnd,
+ * RTAsn1CursorCheckEnd
+ */
+RTDECL(int) RTAsn1CursorCheckSetEnd(PRTASN1CURSOR pCursor, PRTASN1SETCORE pSetCore);
+
+/**
+ * Specialization of RTAsn1CursorCheckEnd for handling indefinite length
+ * constructed octet strings.
+ *
+ * This function must used when parsing the content of an octet string, like
+ * for example the Content of a PKCS\#7 ContentInfo structure. It makes sure
+ * we've reached the end of the data for the cursor, and in case of a an
+ * indefinite length sets it may adjust set length and the parent cursor.
+ *
+ * @returns IPRT status code.
+ * @param pCursor The cursor we're decoding from.
+ * @param pOctetString The octet string.
+ * @sa RTAsn1CursorCheckSeqEnd, RTAsn1CursorCheckSetEnd,
+ * RTAsn1CursorCheckEnd
+ */
+RTDECL(int) RTAsn1CursorCheckOctStrEnd(PRTASN1CURSOR pCursor, PRTASN1OCTETSTRING pOctetString);
+
+
+/**
+ * Skips a given number of bytes.
+ *
+ * @returns @a pCursor
+ * @param pCursor The cursor.
+ * @param cb The number of bytes to skip.
+ * @internal
+ */
+DECLINLINE(PRTASN1CURSOR) RTAsn1CursorSkip(PRTASN1CURSOR pCursor, uint32_t cb)
+{
+ if (cb <= pCursor->cbLeft)
+ {
+ pCursor->cbLeft -= cb;
+ pCursor->pbCur += cb;
+ }
+ else
+ {
+ pCursor->pbCur += pCursor->cbLeft;
+ pCursor->cbLeft = 0;
+ }
+
+ return pCursor;
+}
+
+/**
+ * Low-level function for reading an ASN.1 header.
+ *
+ * @returns IPRT status code.
+ * @param pCursor The cursor we're decoding from.
+ * @param pAsn1Core The output object core.
+ * @param pszErrorTag Error tag.
+ * @internal
+ */
+RTDECL(int) RTAsn1CursorReadHdr(PRTASN1CURSOR pCursor, PRTASN1CORE pAsn1Core, const char *pszErrorTag);
+
+/**
+ * Common helper for simple tag matching.
+ *
+ * @returns IPRT status code.
+ * @param pCursor The cursor (for error reporting).
+ * @param pAsn1Core The ASN.1 core structure.
+ * @param uTag The expected tag.
+ * @param fClass The expected class.
+ * @param fString Set if it's a string type that shall follow
+ * special CER and DER rules wrt to constructed and
+ * primitive encoding.
+ * @param fFlags The RTASN1CURSOR_GET_F_XXX flags.
+ * @param pszErrorTag The error tag.
+ * @param pszWhat The type/whatever name.
+ */
+RTDECL(int) RTAsn1CursorMatchTagClassFlagsEx(PRTASN1CURSOR pCursor, PRTASN1CORE pAsn1Core, uint32_t uTag, uint32_t fClass,
+ bool fString, uint32_t fFlags, const char *pszErrorTag, const char *pszWhat);
+
+/**
+ * Common helper for simple tag matching.
+ *
+ * @returns IPRT status code.
+ * @param pCursor The cursor (for error reporting).
+ * @param pAsn1Core The ASN.1 core structure.
+ * @param uTag The expected tag.
+ * @param fClass The expected class.
+ * @param fFlags The RTASN1CURSOR_GET_F_XXX flags.
+ * @param pszErrorTag The error tag.
+ * @param pszWhat The type/whatever name.
+ * @internal
+ */
+DECLINLINE(int) RTAsn1CursorMatchTagClassFlags(PRTASN1CURSOR pCursor, PRTASN1CORE pAsn1Core, uint32_t uTag, uint32_t fClass,
+ uint32_t fFlags, const char *pszErrorTag, const char *pszWhat)
+{
+ if (pAsn1Core->uTag == uTag && pAsn1Core->fClass == fClass)
+ return VINF_SUCCESS;
+ return RTAsn1CursorMatchTagClassFlagsEx(pCursor, pAsn1Core, uTag, fClass, false /*fString*/, fFlags, pszErrorTag, pszWhat);
+}
+
+
+/**
+ * Common helper for simple tag matching for strings.
+ *
+ * Check string encoding considerations.
+ *
+ * @returns IPRT status code.
+ * @param pCursor The cursor (for error reporting).
+ * @param pAsn1Core The ASN.1 core structure.
+ * @param uTag The expected tag.
+ * @param fClass The expected class.
+ * @param fFlags The RTASN1CURSOR_GET_F_XXX flags.
+ * @param pszErrorTag The error tag.
+ * @param pszWhat The type/whatever name.
+ * @internal
+ */
+DECLINLINE(int) RTAsn1CursorMatchTagClassFlagsString(PRTASN1CURSOR pCursor, PRTASN1CORE pAsn1Core, uint32_t uTag, uint32_t fClass,
+ uint32_t fFlags, const char *pszErrorTag, const char *pszWhat)
+{
+ if (pAsn1Core->uTag == uTag && pAsn1Core->fClass == fClass)
+ return VINF_SUCCESS;
+ return RTAsn1CursorMatchTagClassFlagsEx(pCursor, pAsn1Core, uTag, fClass, true /*fString*/, fFlags, pszErrorTag, pszWhat);
+}
+
+
+
+/** @name RTASN1CURSOR_GET_F_XXX - Common flags for all the getters.
+ * @{ */
+/** Used for decoding objects with implicit tags assigned to them. This only
+ * works when calling getters with a unambigious types. */
+#define RTASN1CURSOR_GET_F_IMPLICIT RT_BIT_32(0)
+/** @} */
+
+/**
+ * Read ANY object.
+ *
+ * @returns IPRT status code.
+ * @param pCursor The cursor we're decoding from.
+ * @param fFlags RTASN1CURSOR_GET_F_XXX.
+ * @param pAsn1Core The output object core.
+ * @param pszErrorTag Error tag.
+ */
+RTDECL(int) RTAsn1CursorGetCore(PRTASN1CURSOR pCursor, uint32_t fFlags, PRTASN1CORE pAsn1Core, const char *pszErrorTag);
+
+/**
+ * Read a NULL object.
+ *
+ * @returns IPRT status code.
+ * @param pCursor The cursor we're decoding from.
+ * @param fFlags RTASN1CURSOR_GET_F_XXX.
+ * @param pNull The output NULL object.
+ * @param pszErrorTag Error tag.
+ */
+RTDECL(int) RTAsn1CursorGetNull(PRTASN1CURSOR pCursor, uint32_t fFlags, PRTASN1NULL pNull, const char *pszErrorTag);
+
+/**
+ * Read an INTEGER object.
+ *
+ * @returns IPRT status code.
+ * @param pCursor The cursor we're decoding from.
+ * @param fFlags RTASN1CURSOR_GET_F_XXX.
+ * @param pInteger The output integer object.
+ * @param pszErrorTag Error tag.
+ */
+RTDECL(int) RTAsn1CursorGetInteger(PRTASN1CURSOR pCursor, uint32_t fFlags, PRTASN1INTEGER pInteger, const char *pszErrorTag);
+
+/**
+ * Read an BOOLEAN object.
+ *
+ * @returns IPRT status code.
+ * @param pCursor The cursor we're decoding from.
+ * @param fFlags RTASN1CURSOR_GET_F_XXX.
+ * @param pBoolean The output boolean object.
+ * @param pszErrorTag Error tag.
+ */
+RTDECL(int) RTAsn1CursorGetBoolean(PRTASN1CURSOR pCursor, uint32_t fFlags, PRTASN1BOOLEAN pBoolean, const char *pszErrorTag);
+
+/**
+ * Retrives an object identifier (aka ObjId or OID) item from the ASN.1 stream.
+ *
+ * @returns IPRT status code.
+ * @param pCursor The cursor.
+ * @param fFlags RTASN1CURSOR_GET_F_XXX.
+ * @param pObjId The output ODI object.
+ * @param pszErrorTag Error tag.
+ */
+RTDECL(int) RTAsn1CursorGetObjId(PRTASN1CURSOR pCursor, uint32_t fFlags, PRTASN1OBJID pObjId, const char *pszErrorTag);
+
+/**
+ * Retrives and verifies an object identifier.
+ *
+ * @returns IPRT status code.
+ * @param pCursor The cursor.
+ * @param fFlags RTASN1CURSOR_GET_F_XXX.
+ * @param pObjId Where to return the parsed object ID, optional.
+ * @param pszExpectedObjId The expected object identifier (dotted).
+ * @param pszErrorTag Error tag.
+ */
+RTDECL(int) RTAsn1CursorGetAndCheckObjId(PRTASN1CURSOR pCursor, uint32_t fFlags, PRTASN1OBJID pObjId,
+ const char *pszExpectedObjId, const char *pszErrorTag);
+
+/**
+ * Read an UTC TIME or GENERALIZED TIME object.
+ *
+ * @returns IPRT status code.
+ * @param pCursor The cursor we're decoding from.
+ * @param fFlags RTASN1CURSOR_GET_F_XXX.
+ * @param pTime The output time object.
+ * @param pszErrorTag Error tag.
+ */
+RTDECL(int) RTAsn1CursorGetTime(PRTASN1CURSOR pCursor, uint32_t fFlags, PRTASN1TIME pTime, const char *pszErrorTag);
+
+/**
+ * Read an BIT STRING object (skips past the content).
+ *
+ * @returns IPRT status ocde.
+ * @param pCursor The cursor.
+ * @param fFlags RTASN1CURSOR_GET_F_XXX.
+ * @param pBitString The output bit string object.
+ * @param pszErrorTag Error tag.
+ */
+RTDECL(int) RTAsn1CursorGetBitString(PRTASN1CURSOR pCursor, uint32_t fFlags, PRTASN1BITSTRING pBitString,
+ const char *pszErrorTag);
+
+/**
+ * Read an BIT STRING object (skips past the content), extended version with
+ * cMaxBits.
+ *
+ * @returns IPRT status ocde.
+ * @param pCursor The cursor.
+ * @param fFlags RTASN1CURSOR_GET_F_XXX.
+ * @param cMaxBits The max length of the bit string in bits. Pass
+ * UINT32_MAX if variable size.
+ * @param pBitString The output bit string object.
+ * @param pszErrorTag Error tag.
+ */
+RTDECL(int) RTAsn1CursorGetBitStringEx(PRTASN1CURSOR pCursor, uint32_t fFlags, uint32_t cMaxBits, PRTASN1BITSTRING pBitString,
+ const char *pszErrorTag);
+
+/**
+ * Read an OCTET STRING object (skips past the content).
+ *
+ * @returns IPRT status ocde.
+ * @param pCursor The cursor.
+ * @param fFlags RTASN1CURSOR_GET_F_XXX.
+ * @param pOctetString The output octet string object.
+ * @param pszErrorTag Error tag.
+ */
+RTDECL(int) RTAsn1CursorGetOctetString(PRTASN1CURSOR pCursor, uint32_t fFlags, PRTASN1OCTETSTRING pOctetString,
+ const char *pszErrorTag);
+
+/**
+ * Read any kind of string object, except 'character string (29)'.
+ *
+ * @returns IPRT status code.
+ * @param pCursor The cursor we're decoding from.
+ * @param fFlags RTASN1CURSOR_GET_F_XXX.
+ * @param pString The output boolean object.
+ * @param pszErrorTag Error tag.
+ */
+RTDECL(int) RTAsn1CursorGetString(PRTASN1CURSOR pCursor, uint32_t fFlags, PRTASN1STRING pString, const char *pszErrorTag);
+
+/**
+ * Read a IA5 STRING object.
+ *
+ * @returns IPRT status code.
+ * @param pCursor The cursor we're decoding from.
+ * @param fFlags RTASN1CURSOR_GET_F_XXX.
+ * @param pString The output boolean object.
+ * @param pszErrorTag Error tag.
+ */
+RTDECL(int) RTAsn1CursorGetIa5String(PRTASN1CURSOR pCursor, uint32_t fFlags, PRTASN1STRING pString, const char *pszErrorTag);
+
+/**
+ * Read a UTF8 STRING object.
+ *
+ * @returns IPRT status code.
+ * @param pCursor The cursor we're decoding from.
+ * @param fFlags RTASN1CURSOR_GET_F_XXX.
+ * @param pString The output boolean object.
+ * @param pszErrorTag Error tag.
+ */
+RTDECL(int) RTAsn1CursorGetUtf8String(PRTASN1CURSOR pCursor, uint32_t fFlags, PRTASN1STRING pString, const char *pszErrorTag);
+
+/**
+ * Read a BMP STRING (UCS-2) object.
+ *
+ * @returns IPRT status code.
+ * @param pCursor The cursor we're decoding from.
+ * @param fFlags RTASN1CURSOR_GET_F_XXX.
+ * @param pString The output boolean object.
+ * @param pszErrorTag Error tag.
+ */
+RTDECL(int) RTAsn1CursorGetBmpString(PRTASN1CURSOR pCursor, uint32_t fFlags, PRTASN1STRING pString, const char *pszErrorTag);
+
+/**
+ * Read a SEQUENCE object and create a cursor for its content.
+ *
+ * @returns IPRT status code.
+ * @param pCursor The cursor we're decoding from.
+ * @param fFlags RTASN1CURSOR_GET_F_XXX.
+ * @param pSeqCore The output sequence core object.
+ * @param pSeqCursor The output cursor for the sequence content.
+ * @param pszErrorTag Error tag, this will be associated with the
+ * returned cursor.
+ */
+RTDECL(int) RTAsn1CursorGetSequenceCursor(PRTASN1CURSOR pCursor, uint32_t fFlags,
+ PRTASN1SEQUENCECORE pSeqCore, PRTASN1CURSOR pSeqCursor, const char *pszErrorTag);
+
+/**
+ * Read a SET object and create a cursor for its content.
+ *
+ * @returns IPRT status code.
+ * @param pCursor The cursor we're decoding from.
+ * @param fFlags RTASN1CURSOR_GET_F_XXX.
+ * @param pSetCore The output set core object.
+ * @param pSetCursor The output cursor for the set content.
+ * @param pszErrorTag Error tag, this will be associated with the
+ * returned cursor.
+ */
+RTDECL(int) RTAsn1CursorGetSetCursor(PRTASN1CURSOR pCursor, uint32_t fFlags,
+ PRTASN1SETCORE pSetCore, PRTASN1CURSOR pSetCursor, const char *pszErrorTag);
+
+/**
+ * Read a given constructed context tag and create a cursor for its content.
+ *
+ * @returns IPRT status code.
+ * @param pCursor The cursor we're decoding from.
+ * @param fFlags RTASN1CURSOR_GET_F_XXX.
+ * @param uExpectedTag The expected tag.
+ * @param pVtable The vtable for the context tag node (see
+ * RTASN1TMPL_PASS_XTAG).
+ * @param pCtxTag The output context tag object.
+ * @param pCtxTagCursor The output cursor for the context tag content.
+ * @param pszErrorTag Error tag, this will be associated with the
+ * returned cursor.
+ *
+ * @remarks There are specialized version of this function for each of the
+ * numbered context tag structures, like for RTASN1CONTEXTTAG0 there is
+ * RTAsn1CursorGetContextTag0Cursor.
+ */
+RTDECL(int) RTAsn1CursorGetContextTagNCursor(PRTASN1CURSOR pCursor, uint32_t fFlags, uint32_t uExpectedTag,
+ PCRTASN1COREVTABLE pVtable, PRTASN1CONTEXTTAG pCtxTag, PRTASN1CURSOR pCtxTagCursor,
+ const char *pszErrorTag);
+
+/**
+ * Read a dynamic ASN.1 type.
+ *
+ * @returns IPRT status code.
+ * @param pCursor The cursor we're decoding from.
+ * @param fFlags RTASN1CURSOR_GET_F_XXX.
+ * @param pDynType The output context tag object.
+ * @param pszErrorTag Error tag.
+ */
+RTDECL(int) RTAsn1CursorGetDynType(PRTASN1CURSOR pCursor, uint32_t fFlags, PRTASN1DYNTYPE pDynType, const char *pszErrorTag);
+
+/**
+ * Peeks at the next ASN.1 object.
+ *
+ * @returns IPRT status code.
+ * @param pCursor The cursore we're decoding from.
+ * @param pAsn1Core Where to store the output of the peek.
+ */
+RTDECL(int) RTAsn1CursorPeek(PRTASN1CURSOR pCursor, PRTASN1CORE pAsn1Core);
+
+/**
+ * Checks if the next ASN.1 object matches the given tag and class/flags.
+ *
+ * @returns @c true on match, @c false on mismatch.
+ * @param pCursor The cursore we're decoding from.
+ * @param uTag The tag number to match against.
+ * @param fClass The tag class and flags to match against.
+ */
+RTDECL(bool) RTAsn1CursorIsNextEx(PRTASN1CURSOR pCursor, uint32_t uTag, uint8_t fClass);
+
+
+
+/** @internal */
+#define RTASN1CONTEXTTAG_IMPL_CURSOR_INLINES(a_uTag) \
+ DECLINLINE(int) RT_CONCAT3(RTAsn1CursorGetContextTag,a_uTag,Cursor)(PRTASN1CURSOR pCursor, uint32_t fFlags, \
+ PCRTASN1COREVTABLE pVtable, \
+ RT_CONCAT(PRTASN1CONTEXTTAG,a_uTag) pCtxTag, \
+ PRTASN1CURSOR pCtxTagCursor, const char *pszErrorTag) \
+ { /* Constructed is automatically implied if you need a cursor to it. */ \
+ return RTAsn1CursorGetContextTagNCursor(pCursor, fFlags, a_uTag, pVtable, (PRTASN1CONTEXTTAG)pCtxTag, pCtxTagCursor, pszErrorTag); \
+ } \
+ DECLINLINE(int) RT_CONCAT3(RTAsn1ContextTag,a_uTag,InitDefault)(RT_CONCAT(PRTASN1CONTEXTTAG,a_uTag) pCtxTag) \
+ { /* Constructed is automatically implied if you need to init it with a default value. */ \
+ return RTAsn1Core_InitDefault(&pCtxTag->Asn1Core, a_uTag, ASN1_TAGCLASS_CONTEXT | ASN1_TAGFLAG_CONSTRUCTED); \
+ } \
+ DECLINLINE(int) RT_CONCAT3(RTAsn1CursorIsConstructedContextTag,a_uTag,Next)(PRTASN1CURSOR pCursor) \
+ { \
+ return RTAsn1CursorIsNextEx(pCursor, a_uTag, ASN1_TAGCLASS_CONTEXT | ASN1_TAGFLAG_CONSTRUCTED); \
+ } \
+ DECLINLINE(int) RT_CONCAT3(RTAsn1CursorIsPrimitiveContextTag,a_uTag,Next)(PRTASN1CURSOR pCursor) \
+ { \
+ return RTAsn1CursorIsNextEx(pCursor, a_uTag, ASN1_TAGCLASS_CONTEXT | ASN1_TAGFLAG_PRIMITIVE); \
+ } \
+ DECLINLINE(int) RT_CONCAT3(RTAsn1CursorIsAnyContextTag,a_uTag,Next)(PRTASN1CURSOR pCursor) \
+ { \
+ return RTAsn1CursorIsNextEx(pCursor, a_uTag, ASN1_TAGCLASS_CONTEXT | ASN1_TAGFLAG_CONSTRUCTED) \
+ || RTAsn1CursorIsNextEx(pCursor, a_uTag, ASN1_TAGCLASS_CONTEXT | ASN1_TAGFLAG_PRIMITIVE);\
+ } \
+
+RTASN1CONTEXTTAG_IMPL_CURSOR_INLINES(0)
+RTASN1CONTEXTTAG_IMPL_CURSOR_INLINES(1)
+RTASN1CONTEXTTAG_IMPL_CURSOR_INLINES(2)
+RTASN1CONTEXTTAG_IMPL_CURSOR_INLINES(3)
+RTASN1CONTEXTTAG_IMPL_CURSOR_INLINES(4)
+RTASN1CONTEXTTAG_IMPL_CURSOR_INLINES(5)
+RTASN1CONTEXTTAG_IMPL_CURSOR_INLINES(6)
+RTASN1CONTEXTTAG_IMPL_CURSOR_INLINES(7)
+#undef RTASN1CONTEXTTAG_IMPL_CURSOR_INLINES
+
+
+/**
+ * Checks if the next object is a boolean.
+ *
+ * @returns true / false
+ * @param pCursor The cursor we're decoding from.
+ * @remarks May produce error info output on mismatch.
+ */
+DECLINLINE(bool) RTAsn1CursorIsBooleanNext(PRTASN1CURSOR pCursor)
+{
+ return RTAsn1CursorIsNextEx(pCursor, ASN1_TAG_BOOLEAN, ASN1_TAGFLAG_PRIMITIVE | ASN1_TAGCLASS_UNIVERSAL);
+}
+
+
+/**
+ * Checks if the next object is a set.
+ *
+ * @returns true / false
+ * @param pCursor The cursor we're decoding from.
+ * @remarks May produce error info output on mismatch.
+ */
+DECLINLINE(bool) RTAsn1CursorIsSetNext(PRTASN1CURSOR pCursor)
+{
+ return RTAsn1CursorIsNextEx(pCursor, ASN1_TAG_SET, ASN1_TAGFLAG_CONSTRUCTED | ASN1_TAGCLASS_UNIVERSAL);
+}
+
+
+/** @} */
+
+
+/** @name ASN.1 Utility APIs
+ * @{ */
+
+/**
+ * Dumps an IPRT representation of a ASN.1 object tree.
+ *
+ * @returns IPRT status code.
+ * @param pAsn1Core The ASN.1 object which members should be dumped.
+ * @param fFlags RTASN1DUMP_F_XXX.
+ * @param uLevel The indentation level to start at.
+ * @param pfnPrintfV The output function.
+ * @param pvUser Argument to the output function.
+ */
+RTDECL(int) RTAsn1Dump(PCRTASN1CORE pAsn1Core, uint32_t fFlags, uint32_t uLevel, PFNRTDUMPPRINTFV pfnPrintfV, void *pvUser);
+
+/**
+ * Queries the name for an object identifier.
+ *
+ * This API is very simple due to how we store the data.
+ *
+ * @returns IPRT status code.
+ * @retval VINF_SUCCESS on success.
+ * @retval VERR_NOT_FOUND if not found.
+ * @retval VERR_BUFFER_OVERFLOW if more buffer space is required.
+ *
+ * @param pObjId The object ID to name.
+ * @param pszDst Where to store the name if found.
+ * @param cbDst The size of the destination buffer.
+ */
+RTDECL(int) RTAsn1QueryObjIdName(PCRTASN1OBJID pObjId, char *pszDst, size_t cbDst);
+
+/** @} */
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_asn1_h */
+
diff --git a/include/iprt/assert.h b/include/iprt/assert.h
new file mode 100644
index 00000000..6d0087ee
--- /dev/null
+++ b/include/iprt/assert.h
@@ -0,0 +1,2893 @@
+/** @file
+ * IPRT - Assertions.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_assert_h
+#define IPRT_INCLUDED_assert_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+#include <iprt/stdarg.h>
+#include <iprt/assertcompile.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.
+ *
+ * @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
+
+#if !defined(IPRT_WITHOUT_ASSERT_STACK) \
+ && defined(IN_RING3) \
+ && !defined(IN_RT_STATIC) /* try keep static binaries small */ \
+ && (defined(RT_ARCH_AMD64) /*|| defined(RT_ARCH_X86)*/)
+/** @def IPRT_WITH_ASSERT_STACK
+ * Indicates that we collect a callstack stack on assertion. */
+# define IPRT_WITH_ASSERT_STACK
+#endif
+
+/**
+ * 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 assertion message, 1st part. */
+extern RTDATADECL(char) g_szRTAssertMsg1[1024];
+/** The last assertion message, 2nd part. */
+extern RTDATADECL(char) g_szRTAssertMsg2[4096];
+#ifdef IPRT_WITH_ASSERT_STACK
+/** The last assertion message, stack part. */
+extern RTDATADECL(char) g_szRTAssertStack[4096];
+#endif
+/** The last assertion message, expression. */
+extern RTDATADECL(const char * volatile) g_pszRTAssertExpr;
+/** The last assertion message, file name. */
+extern RTDATADECL(const char * volatile) g_pszRTAssertFile;
+/** The last assertion message, line number. */
+extern RTDATADECL(uint32_t volatile) g_u32RTAssertLine;
+/** The last assertion 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 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)
+# ifdef RT_COMPILER_SUPPORTS_VA_ARGS
+# define RTAssertMsg2Weak(...) do { } while (0)
+# else
+# define RTAssertMsg2Weak if (1) {} else RTAssertMsg2Weak
+# endif
+#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__, RT_GCC_EXTENSION __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__, RT_GCC_EXTENSION __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__, RT_GCC_EXTENSION __PRETTY_FUNCTION__); \
+ RTAssertPanic(); \
+ break; \
+ } else \
+ break
+#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__, RT_GCC_EXTENSION __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__, RT_GCC_EXTENSION __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__, RT_GCC_EXTENSION __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__, RT_GCC_EXTENSION __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__, RT_GCC_EXTENSION __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__, RT_GCC_EXTENSION __PRETTY_FUNCTION__); \
+ RTAssertMsg2Weak a; \
+ RTAssertPanic(); \
+ break; \
+ } else \
+ break
+#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__, RT_GCC_EXTENSION __PRETTY_FUNCTION__); \
+ RTAssertMsg2Weak a; \
+ RTAssertPanic(); \
+ stmt; \
+ break; \
+ } else \
+ break
+#else
+# define AssertMsgBreakStmt(expr, a, stmt) \
+ if (RT_LIKELY(!!(expr))) \
+ { /* likely */ } \
+ else if (1) \
+ { \
+ stmt; \
+ break; \
+ } else \
+ break
+#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__, RT_GCC_EXTENSION __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__, RT_GCC_EXTENSION __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__, RT_GCC_EXTENSION __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__, RT_GCC_EXTENSION __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__, RT_GCC_EXTENSION __PRETTY_FUNCTION__); \
+ RTAssertPanic(); \
+ break; \
+ } else \
+ break
+#else
+# define AssertFailedBreak() \
+ if (1) \
+ break; \
+ else \
+ break
+#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__, RT_GCC_EXTENSION __PRETTY_FUNCTION__); \
+ RTAssertPanic(); \
+ stmt; \
+ break; \
+ } else \
+ break
+#else
+# define AssertFailedBreakStmt(stmt) \
+ if (1) { \
+ stmt; \
+ break; \
+ } else \
+ break
+#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__, RT_GCC_EXTENSION __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__, RT_GCC_EXTENSION __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__, RT_GCC_EXTENSION __PRETTY_FUNCTION__); \
+ RTAssertMsg2Weak a; \
+ RTAssertPanic(); \
+ break; \
+ } else \
+ break
+#else
+# define AssertMsgFailedBreak(a) \
+ if (1) \
+ break; \
+ else \
+ break
+#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__, RT_GCC_EXTENSION __PRETTY_FUNCTION__); \
+ RTAssertMsg2Weak a; \
+ RTAssertPanic(); \
+ stmt; \
+ break; \
+ } else \
+ break
+#else
+# define AssertMsgFailedBreakStmt(a, stmt) \
+ if (1) { \
+ stmt; \
+ break; \
+ } else \
+ break
+#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__, RT_GCC_EXTENSION __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__, RT_GCC_EXTENSION __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__, RT_GCC_EXTENSION __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__, RT_GCC_EXTENSION __PRETTY_FUNCTION__); \
+ RTAssertPanic(); \
+ break; \
+ } \
+ else \
+ break
+
+/** @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__, RT_GCC_EXTENSION __PRETTY_FUNCTION__); \
+ RTAssertPanic(); \
+ stmt; \
+ break; \
+ } else \
+ break
+
+/** @def AssertLogRelStmt
+ * 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 stmt Statement to execute in case of a failed assertion.
+ */
+#define AssertLogRelStmt(expr, stmt) \
+ do { \
+ if (RT_LIKELY(!!(expr))) \
+ { /* likely */ } \
+ else \
+ { \
+ RTAssertLogRelMsg1(#expr, __LINE__, __FILE__, RT_GCC_EXTENSION __PRETTY_FUNCTION__); \
+ RTAssertPanic(); \
+ stmt; \
+ } \
+ } 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__, RT_GCC_EXTENSION __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__, RT_GCC_EXTENSION __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__, RT_GCC_EXTENSION __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__, RT_GCC_EXTENSION __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__, RT_GCC_EXTENSION __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__, RT_GCC_EXTENSION __PRETTY_FUNCTION__); \
+ RTAssertLogRelMsg2(a); \
+ RTAssertPanic(); \
+ break; \
+ } \
+ else \
+ break
+
+/** @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__, RT_GCC_EXTENSION __PRETTY_FUNCTION__); \
+ RTAssertLogRelMsg2(a); \
+ RTAssertPanic(); \
+ stmt; \
+ break; \
+ } else \
+ break
+
+/** @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__, RT_GCC_EXTENSION __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__, RT_GCC_EXTENSION __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__, RT_GCC_EXTENSION __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__, RT_GCC_EXTENSION __PRETTY_FUNCTION__); \
+ RTAssertPanic(); \
+ break; \
+ } else \
+ break
+
+/** @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__, RT_GCC_EXTENSION __PRETTY_FUNCTION__); \
+ RTAssertPanic(); \
+ stmt; \
+ break; \
+ } else \
+ break
+
+/** @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__, RT_GCC_EXTENSION __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__, RT_GCC_EXTENSION __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__, RT_GCC_EXTENSION __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__, RT_GCC_EXTENSION __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__, RT_GCC_EXTENSION __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__, RT_GCC_EXTENSION __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__, RT_GCC_EXTENSION __PRETTY_FUNCTION__); \
+ RTAssertLogRelMsg2(a); \
+ RTAssertPanic(); \
+ break; \
+ } else \
+ break
+
+/** @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__, RT_GCC_EXTENSION __PRETTY_FUNCTION__); \
+ RTAssertLogRelMsg2(a); \
+ RTAssertPanic(); \
+ stmt; \
+ break; \
+ } else \
+ break
+
+/** @} */
+
+
+
+/** @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).
+ */
+#if defined(RT_STRICT) || !defined(RTASSERT_NO_RELEASE_ASSERTIONS)
+# define RTAssertReleasePanic() do { RTAssertShouldPanic(); RTAssertDoPanic(); } while (0)
+#else
+# define RTAssertReleasePanic() do { } while (0)
+#endif
+
+
+/** @def AssertRelease
+ * Assert that an expression is true. If it's not hit a breakpoint.
+ *
+ * @param expr Expression which should be true.
+ */
+#if defined(RT_STRICT) || !defined(RTASSERT_NO_RELEASE_ASSERTIONS)
+# define AssertRelease(expr) \
+ do { \
+ if (RT_LIKELY(!!(expr))) \
+ { /* likely */ } \
+ else \
+ { \
+ RTAssertMsg1Weak(#expr, __LINE__, __FILE__, RT_GCC_EXTENSION __PRETTY_FUNCTION__); \
+ RTAssertReleasePanic(); \
+ } \
+ } while (0)
+#else
+# define AssertRelease(expr) do { } while (0)
+#endif
+
+
+/** @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.
+ */
+#if defined(RT_STRICT) || !defined(RTASSERT_NO_RELEASE_ASSERTIONS)
+# define AssertReleaseReturn(expr, rc) \
+ do { \
+ if (RT_LIKELY(!!(expr))) \
+ { /* likely */ } \
+ else \
+ { \
+ RTAssertMsg1Weak(#expr, __LINE__, __FILE__, RT_GCC_EXTENSION __PRETTY_FUNCTION__); \
+ RTAssertReleasePanic(); \
+ return (rc); \
+ } \
+ } while (0)
+#else
+# define AssertReleaseReturn(expr, rc) \
+ do { \
+ if (RT_LIKELY(!!(expr))) \
+ { /* likely */ } \
+ else \
+ return (rc); \
+ } while (0)
+#endif
+
+/** @def AssertReleaseReturnVoid
+ * Assert that an expression is true, hit a breakpoint and return if it isn't.
+ *
+ * @param expr Expression which should be true.
+ */
+#if defined(RT_STRICT) || !defined(RTASSERT_NO_RELEASE_ASSERTIONS)
+# define AssertReleaseReturnVoid(expr) \
+ do { \
+ if (RT_LIKELY(!!(expr))) \
+ { /* likely */ } \
+ else \
+ { \
+ RTAssertMsg1Weak(#expr, __LINE__, __FILE__, RT_GCC_EXTENSION __PRETTY_FUNCTION__); \
+ RTAssertReleasePanic(); \
+ return; \
+ } \
+ } while (0)
+#else
+# define AssertReleaseReturnVoid(expr) \
+ do { \
+ if (RT_LIKELY(!!(expr))) \
+ { /* likely */ } \
+ else \
+ return; \
+ } while (0)
+#endif
+
+
+/** @def AssertReleaseBreak
+ * Assert that an expression is true, hit a breakpoint and break if it isn't.
+ *
+ * @param expr Expression which should be true.
+ */
+#if defined(RT_STRICT) || !defined(RTASSERT_NO_RELEASE_ASSERTIONS)
+# define AssertReleaseBreak(expr) \
+ if (RT_LIKELY(!!(expr))) \
+ { /* likely */ } \
+ else if (1) \
+ { \
+ RTAssertMsg1Weak(#expr, __LINE__, __FILE__, RT_GCC_EXTENSION __PRETTY_FUNCTION__); \
+ RTAssertReleasePanic(); \
+ break; \
+ } else \
+ break
+#else
+# define AssertReleaseBreak(expr) \
+ if (RT_LIKELY(!!(expr))) \
+ { /* likely */ } \
+ else \
+ break
+#endif
+
+/** @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.
+ */
+#if defined(RT_STRICT) || !defined(RTASSERT_NO_RELEASE_ASSERTIONS)
+# define AssertReleaseBreakStmt(expr, stmt) \
+ if (RT_LIKELY(!!(expr))) \
+ { /* likely */ } \
+ else if (1) \
+ { \
+ RTAssertMsg1Weak(#expr, __LINE__, __FILE__, RT_GCC_EXTENSION __PRETTY_FUNCTION__); \
+ RTAssertReleasePanic(); \
+ stmt; \
+ break; \
+ } else \
+ break
+#else
+# define AssertReleaseBreakStmt(expr, stmt) \
+ if (RT_LIKELY(!!(expr))) \
+ { /* likely */ } \
+ else if (1) \
+ { \
+ stmt; \
+ break; \
+ } else \
+ break
+#endif
+
+
+/** @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).
+ */
+#if defined(RT_STRICT) || !defined(RTASSERT_NO_RELEASE_ASSERTIONS)
+# define AssertReleaseMsg(expr, a) \
+ do { \
+ if (RT_LIKELY(!!(expr))) \
+ { /* likely */ } \
+ else \
+ { \
+ RTAssertMsg1Weak(#expr, __LINE__, __FILE__, RT_GCC_EXTENSION __PRETTY_FUNCTION__); \
+ RTAssertMsg2Weak a; \
+ RTAssertReleasePanic(); \
+ } \
+ } while (0)
+#else
+# define AssertReleaseMsg(expr, a) do { } while (0)
+#endif
+
+/** @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.
+ */
+#if defined(RT_STRICT) || !defined(RTASSERT_NO_RELEASE_ASSERTIONS)
+# define AssertReleaseMsgReturn(expr, a, rc) \
+ do { \
+ if (RT_LIKELY(!!(expr))) \
+ { /* likely */ } \
+ else \
+ { \
+ RTAssertMsg1Weak(#expr, __LINE__, __FILE__, RT_GCC_EXTENSION __PRETTY_FUNCTION__); \
+ RTAssertMsg2Weak a; \
+ RTAssertReleasePanic(); \
+ return (rc); \
+ } \
+ } while (0)
+#else
+# define AssertReleaseMsgReturn(expr, a, rc) \
+ do { \
+ if (RT_LIKELY(!!(expr))) \
+ { /* likely */ } \
+ else \
+ return (rc); \
+ } while (0)
+#endif
+
+/** @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).
+ */
+#if defined(RT_STRICT) || !defined(RTASSERT_NO_RELEASE_ASSERTIONS)
+# define AssertReleaseMsgReturnVoid(expr, a) \
+ do { \
+ if (RT_LIKELY(!!(expr))) \
+ { /* likely */ } \
+ else \
+ { \
+ RTAssertMsg1Weak(#expr, __LINE__, __FILE__, RT_GCC_EXTENSION __PRETTY_FUNCTION__); \
+ RTAssertMsg2Weak a; \
+ RTAssertReleasePanic(); \
+ return; \
+ } \
+ } while (0)
+#else
+# define AssertReleaseMsgReturnVoid(expr, a) \
+ do { \
+ if (RT_LIKELY(!!(expr))) \
+ { /* likely */ } \
+ else \
+ return; \
+ } while (0)
+#endif
+
+
+/** @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).
+ */
+#if defined(RT_STRICT) || !defined(RTASSERT_NO_RELEASE_ASSERTIONS)
+# define AssertReleaseMsgBreak(expr, a) \
+ if (RT_LIKELY(!!(expr))) \
+ { /* likely */ } \
+ else if (1) \
+ { \
+ RTAssertMsg1Weak(#expr, __LINE__, __FILE__, RT_GCC_EXTENSION __PRETTY_FUNCTION__); \
+ RTAssertMsg2Weak a; \
+ RTAssertReleasePanic(); \
+ break; \
+ } else \
+ break
+#else
+# define AssertReleaseMsgBreak(expr, a) \
+ if (RT_LIKELY(!!(expr))) \
+ { /* likely */ } \
+ else if (1) \
+ break; \
+ else \
+ break
+#endif
+
+/** @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.
+ */
+#if defined(RT_STRICT) || !defined(RTASSERT_NO_RELEASE_ASSERTIONS)
+# define AssertReleaseMsgBreakStmt(expr, a, stmt) \
+ if (RT_LIKELY(!!(expr))) \
+ { /* likely */ } \
+ else if (1) \
+ { \
+ RTAssertMsg1Weak(#expr, __LINE__, __FILE__, RT_GCC_EXTENSION __PRETTY_FUNCTION__); \
+ RTAssertMsg2Weak a; \
+ RTAssertReleasePanic(); \
+ stmt; \
+ break; \
+ } else \
+ break
+#else
+# define AssertReleaseMsgBreakStmt(expr, a, stmt) \
+ if (RT_LIKELY(!!(expr))) \
+ { /* likely */ } \
+ else if (1) \
+ { \
+ stmt; \
+ break; \
+ } else \
+ break
+#endif
+
+
+/** @def AssertReleaseFailed
+ * An assertion failed, hit a breakpoint.
+ */
+#if defined(RT_STRICT) || !defined(RTASSERT_NO_RELEASE_ASSERTIONS)
+# define AssertReleaseFailed() \
+ do { \
+ RTAssertMsg1Weak((const char *)0, __LINE__, __FILE__, RT_GCC_EXTENSION __PRETTY_FUNCTION__); \
+ RTAssertReleasePanic(); \
+ } while (0)
+#else
+# define AssertReleaseFailed() do { } while (0)
+#endif
+
+/** @def AssertReleaseFailedReturn
+ * An assertion failed, hit a breakpoint and return.
+ *
+ * @param rc What is to be presented to return.
+ */
+#if defined(RT_STRICT) || !defined(RTASSERT_NO_RELEASE_ASSERTIONS)
+# define AssertReleaseFailedReturn(rc) \
+ do { \
+ RTAssertMsg1Weak((const char *)0, __LINE__, __FILE__, RT_GCC_EXTENSION __PRETTY_FUNCTION__); \
+ RTAssertReleasePanic(); \
+ return (rc); \
+ } while (0)
+#else
+# define AssertReleaseFailedReturn(rc) \
+ do { return (rc); } while (0)
+#endif
+
+/** @def AssertReleaseFailedReturnVoid
+ * An assertion failed, hit a breakpoint and return.
+ */
+#if defined(RT_STRICT) || !defined(RTASSERT_NO_RELEASE_ASSERTIONS)
+# define AssertReleaseFailedReturnVoid() \
+ do { \
+ RTAssertMsg1Weak((const char *)0, __LINE__, __FILE__, RT_GCC_EXTENSION __PRETTY_FUNCTION__); \
+ RTAssertReleasePanic(); \
+ return; \
+ } while (0)
+#else
+# define AssertReleaseFailedReturnVoid() \
+ do { return; } while (0)
+#endif
+
+/** @def AssertReleaseFailedBreak
+ * An assertion failed, hit a breakpoint and break.
+ */
+#if defined(RT_STRICT) || !defined(RTASSERT_NO_RELEASE_ASSERTIONS)
+# define AssertReleaseFailedBreak() \
+ if (1) { \
+ RTAssertMsg1Weak((const char *)0, __LINE__, __FILE__, RT_GCC_EXTENSION __PRETTY_FUNCTION__); \
+ RTAssertReleasePanic(); \
+ break; \
+ } else \
+ break
+#else
+# define AssertReleaseFailedBreak() \
+ if (1) \
+ break; \
+ else \
+ break
+#endif
+
+/** @def AssertReleaseFailedBreakStmt
+ * An assertion failed, hit a breakpoint and break.
+ *
+ * @param stmt Statement to execute before break.
+ */
+#if defined(RT_STRICT) || !defined(RTASSERT_NO_RELEASE_ASSERTIONS)
+# define AssertReleaseFailedBreakStmt(stmt) \
+ if (1) { \
+ RTAssertMsg1Weak((const char *)0, __LINE__, __FILE__, RT_GCC_EXTENSION __PRETTY_FUNCTION__); \
+ RTAssertReleasePanic(); \
+ stmt; \
+ break; \
+ } else \
+ break
+#else
+# define AssertReleaseFailedBreakStmt(stmt) \
+ if (1) { \
+ stmt; \
+ break; \
+ } else \
+ break
+#endif
+
+/** @def AssertReleaseMsgFailed
+ * An assertion failed, print a message and hit a breakpoint.
+ *
+ * @param a printf argument list (in parenthesis).
+ */
+#if defined(RT_STRICT) || !defined(RTASSERT_NO_RELEASE_ASSERTIONS)
+# define AssertReleaseMsgFailed(a) \
+ do { \
+ RTAssertMsg1Weak((const char *)0, __LINE__, __FILE__, RT_GCC_EXTENSION __PRETTY_FUNCTION__); \
+ RTAssertMsg2Weak a; \
+ RTAssertReleasePanic(); \
+ } while (0)
+#else
+# define AssertReleaseMsgFailed(a) do { } while (0)
+#endif
+
+/** @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.
+ */
+#if defined(RT_STRICT) || !defined(RTASSERT_NO_RELEASE_ASSERTIONS)
+# define AssertReleaseMsgFailedReturn(a, rc) \
+ do { \
+ RTAssertMsg1Weak((const char *)0, __LINE__, __FILE__, RT_GCC_EXTENSION __PRETTY_FUNCTION__); \
+ RTAssertMsg2Weak a; \
+ RTAssertReleasePanic(); \
+ return (rc); \
+ } while (0)
+#else
+# define AssertReleaseMsgFailedReturn(a, rc) \
+ do { return (rc); } while (0)
+#endif
+
+/** @def AssertReleaseMsgFailedReturnVoid
+ * An assertion failed, print a message, hit a breakpoint and return.
+ *
+ * @param a printf argument list (in parenthesis).
+ */
+#if defined(RT_STRICT) || !defined(RTASSERT_NO_RELEASE_ASSERTIONS)
+# define AssertReleaseMsgFailedReturnVoid(a) \
+ do { \
+ RTAssertMsg1Weak((const char *)0, __LINE__, __FILE__, RT_GCC_EXTENSION __PRETTY_FUNCTION__); \
+ RTAssertMsg2Weak a; \
+ RTAssertReleasePanic(); \
+ return; \
+ } while (0)
+#else
+# define AssertReleaseMsgFailedReturnVoid(a) \
+ do { return; } while (0)
+#endif
+
+
+/** @def AssertReleaseMsgFailedBreak
+ * An assertion failed, print a message, hit a breakpoint and break.
+ *
+ * @param a printf argument list (in parenthesis).
+ */
+#if defined(RT_STRICT) || !defined(RTASSERT_NO_RELEASE_ASSERTIONS)
+# define AssertReleaseMsgFailedBreak(a) \
+ if (1) { \
+ RTAssertMsg1Weak((const char *)0, __LINE__, __FILE__, RT_GCC_EXTENSION __PRETTY_FUNCTION__); \
+ RTAssertMsg2Weak a; \
+ RTAssertReleasePanic(); \
+ break; \
+ } else \
+ break
+#else
+# define AssertReleaseMsgFailedBreak(a) \
+ if (1) \
+ break; \
+ else \
+ break
+#endif
+
+/** @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.
+ */
+#if defined(RT_STRICT) || !defined(RTASSERT_NO_RELEASE_ASSERTIONS)
+# define AssertReleaseMsgFailedBreakStmt(a, stmt) \
+ if (1) { \
+ RTAssertMsg1Weak((const char *)0, __LINE__, __FILE__, RT_GCC_EXTENSION __PRETTY_FUNCTION__); \
+ RTAssertMsg2Weak a; \
+ RTAssertReleasePanic(); \
+ stmt; \
+ break; \
+ } else \
+ break
+#else
+# define AssertReleaseMsgFailedBreakStmt(a, stmt) \
+ if (1) { \
+ stmt; \
+ break; \
+ } else \
+ break
+#endif
+/** @} */
+
+
+
+/** @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__, RT_GCC_EXTENSION __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__, RT_GCC_EXTENSION __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(RT_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(RT_VALID_PTR(pv), ("%p\n", (pv)), rcRet)
+
+/** @def AssertPtrReturnVoid
+ * Asserts that a pointer is valid.
+ *
+ * @param pv The pointer.
+ */
+#define AssertPtrReturnVoid(pv) AssertMsgReturnVoid(RT_VALID_PTR(pv), ("%p\n", (pv)))
+
+/** @def AssertPtrReturnStmt
+ * Asserts that a pointer is valid.
+ *
+ * @param pv The pointer.
+ * @param stmt Statement to execute before returninig in case of a failed
+ * assertion.
+ * @param rcRet What is to be presented to return.
+ */
+#define AssertPtrReturnStmt(pv, stmt, rcRet) AssertMsgReturnStmt(RT_VALID_PTR(pv), ("%p\n", (pv)), stmt, rcRet)
+
+/** @def AssertPtrReturnVoidStmt
+ * Asserts that a pointer is valid.
+ *
+ * @param pv The pointer.
+ * @param stmt Statement to execute before returninig in case of a failed
+ * assertion.
+ */
+#define AssertPtrReturnVoidStmt(pv, stmt) AssertMsgReturnVoid(RT_VALID_PTR(pv), ("%p\n", (pv)), stmt)
+
+/** @def AssertPtrBreak
+ * Asserts that a pointer is valid.
+ *
+ * @param pv The pointer.
+ */
+#define AssertPtrBreak(pv) AssertMsgBreak(RT_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(RT_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(RT_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(RT_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(RT_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(RT_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(RT_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 /* !IPRT_INCLUDED_assert_h */
+
diff --git a/include/iprt/assertcompile.h b/include/iprt/assertcompile.h
new file mode 100644
index 00000000..dae0840d
--- /dev/null
+++ b/include/iprt/assertcompile.h
@@ -0,0 +1,263 @@
+/** @file
+ * IPRT - Compile Time Assertions.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_assertcompile_h
+#define IPRT_INCLUDED_assertcompile_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cdefs.h>
+
+/** @defgroup grp_rt_assert_compile Compile time assertions
+ * @ingroup grp_rt
+ *
+ * These assertions are used to check structure sizes, member/size alignments
+ * and similar compile time expressions.
+ *
+ * @remarks As you might have noticed, the AssertCompile 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.
+ *
+ * @{
+ */
+
+/**
+ * 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 and IBM VisualAge C/C++ uses this. GCC doesn't technicaly need this
+ * global scope one as it declares it for each use, however things get
+ * complicated in C++ code where most GCC and clang versions gets upset by mixed
+ * "C" and "C++" versions of the symbol when using inside and outside
+ * RT_C_DECLS_BEGIN/END. The GCC 3.3.x and 3.4.x versions we use, OTOH will
+ * always complain about unused RTASSERTVAR for each AssertCompileNS use in a
+ * function if we declare it globally, so we don't do it for those, but we do
+ * for 4.x+ to prevent linkage confusion.
+ */
+#if !defined(__cplusplus) || !defined(__GNUC__)
+extern int RTASSERTVAR[1];
+#elif RT_GNUC_PREREQ(4, 0) || defined(__clang_major__) /* Not sure when they fixed the global scoping __unused__/whatever problem. */
+RT_C_DECLS_BEGIN
+extern int RTASSERTVAR[1];
+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) AssertCompileNS2(expr,RTASSERTVAR)
+# define AssertCompileNS2(expr,a_VarName) extern int a_VarName[ 1 ] __attribute__((__unused__)), \
+ a_VarName[(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
+# ifdef __cplusplus
+# define AssertCompile(expr) static_assert(!!(expr), #expr)
+# else
+# define AssertCompile(expr) _Static_assert(!!(expr), #expr)
+# endif
+#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)
+#elif (defined(__WATCOMC__) && defined(__cplusplus))
+# 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))
+
+/** @} */
+
+#endif /* !IPRT_INCLUDED_assertcompile_h */
+
diff --git a/include/iprt/avl.h b/include/iprt/avl.h
new file mode 100644
index 00000000..af51d0e6
--- /dev/null
+++ b/include/iprt/avl.h
@@ -0,0 +1,1195 @@
+/** @file
+ * IPRT - AVL Trees.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_avl_h
+#define IPRT_INCLUDED_avl_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_avl RTAvl - AVL Trees
+ * @ingroup grp_rt
+ * @{
+ */
+
+
+/** @name 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 DECLCALLBACKTYPE(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);
+
+/** @} */
+
+
+/** @name 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 DECLCALLBACKTYPE(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);
+
+/** @} */
+
+
+
+/** @name 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 DECLCALLBACKTYPE(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);
+
+/** @} */
+
+
+
+/** @name AVL tree of uint32_t
+ * @{
+ */
+
+/** AVL key type. */
+typedef uint32_t AVLU32KEY;
+
+/** AVL Core node. */
+typedef struct _AVLU32NodeCore
+{
+ struct _AVLU32NodeCore *pLeft; /**< Pointer to left leaf node. */
+ struct _AVLU32NodeCore *pRight; /**< Pointer to right leaf node. */
+ AVLU32KEY Key; /**< Key value. */
+ unsigned char uchHeight; /**< Height of this tree: max(height(left), height(right)) + 1 */
+} AVLU32NODECORE, *PAVLU32NODECORE, **PPAVLU32NODECORE;
+
+/** A tree with uint32_t keys. */
+typedef PAVLU32NODECORE AVLU32TREE;
+/** Pointer to a tree with uint32_t keys. */
+typedef PPAVLU32NODECORE PAVLU32TREE;
+
+/** Callback function for AVLU32DoWithAll() & AVLU32Destroy().
+ * @returns IPRT status codes. */
+typedef DECLCALLBACKTYPE(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);
+
+/** @} */
+
+/** @name AVL tree of uint32_t, offset based
+ * @{
+ */
+
+/**
+ * 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 DECLCALLBACKTYPE(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);
+
+/** @} */
+
+
+/** @name 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 DECLCALLBACKTYPE(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);
+
+/** @} */
+
+
+/** @name AVL tree of uint64_t
+ * @{
+ */
+
+/** AVL key type. */
+typedef uint64_t AVLU64KEY;
+
+/** AVL Core node. */
+typedef struct _AVLU64NodeCore
+{
+ struct _AVLU64NodeCore *pLeft; /**< Pointer to left leaf node. */
+ struct _AVLU64NodeCore *pRight; /**< Pointer to right leaf node. */
+ AVLU64KEY Key; /**< Key value. */
+ unsigned char uchHeight; /**< Height of this tree: max(height(left), height(right)) + 1 */
+} AVLU64NODECORE, *PAVLU64NODECORE, **PPAVLU64NODECORE;
+
+/** A tree with uint64_t keys. */
+typedef PAVLU64NODECORE AVLU64TREE;
+/** Pointer to a tree with uint64_t keys. */
+typedef PPAVLU64NODECORE PAVLU64TREE;
+
+/** Callback function for AVLU64DoWithAll() & AVLU64Destroy().
+ * @returns IPRT status codes. */
+typedef DECLCALLBACKTYPE(int, AVLU64CALLBACK,(PAVLU64NODECORE, void*));
+/** Pointer to callback function for AVLU64DoWithAll() & AVLU64Destroy(). */
+typedef AVLU64CALLBACK *PAVLU64CALLBACK;
+
+
+/*
+ * Functions.
+ */
+RTDECL(bool) RTAvlU64Insert(PAVLU64TREE pTree, PAVLU64NODECORE pNode);
+RTDECL(PAVLU64NODECORE) RTAvlU64Remove(PAVLU64TREE pTree, AVLU64KEY Key);
+RTDECL(PAVLU64NODECORE) RTAvlU64Get(PAVLU64TREE pTree, AVLU64KEY Key);
+RTDECL(PAVLU64NODECORE) RTAvlU64GetBestFit(PAVLU64TREE pTree, AVLU64KEY Key, bool fAbove);
+RTDECL(PAVLU64NODECORE) RTAvlU64RemoveBestFit(PAVLU64TREE pTree, AVLU64KEY Key, bool fAbove);
+RTDECL(int) RTAvlU64DoWithAll(PAVLU64TREE pTree, int fFromLeft, PAVLU64CALLBACK pfnCallBack, void *pvParam);
+RTDECL(int) RTAvlU64Destroy(PAVLU64TREE pTree, PAVLU64CALLBACK pfnCallBack, void *pvParam);
+
+/** @} */
+
+
+/** @name 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 uint64_t keys. */
+typedef PAVLRU64NODECORE AVLRU64TREE;
+/** Pointer to a tree with uint64_t keys. */
+typedef PPAVLRU64NODECORE PAVLRU64TREE;
+
+/** Callback function for AVLRU64DoWithAll().
+ * @returns IPRT status codes. */
+typedef DECLCALLBACKTYPE(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);
+
+/** @} */
+
+
+
+/** @name 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 DECLCALLBACKTYPE(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);
+
+/** @} */
+
+
+/** @name 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 DECLCALLBACKTYPE(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);
+
+/** @} */
+
+
+/** @name 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 DECLCALLBACKTYPE(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);
+
+/** @} */
+
+
+/** @name 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 DECLCALLBACKTYPE(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);
+
+/** @} */
+
+
+/** @name 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 DECLCALLBACKTYPE(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);
+
+/** @} */
+
+
+/** @name 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 DECLCALLBACKTYPE(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);
+
+/** @} */
+
+
+/** @name 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 DECLCALLBACKTYPE(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);
+
+/** @} */
+
+
+/** @name 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 DECLCALLBACKTYPE(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);
+
+/** @} */
+
+
+/** @name 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 DECLCALLBACKTYPE(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);
+
+/** @} */
+
+
+/** @name 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 DECLCALLBACKTYPE(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);
+
+/** @} */
+
+
+
+/** @name 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 DECLCALLBACKTYPE(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);
+
+/** @} */
+
+
+/** @name 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 DECLCALLBACKTYPE(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);
+
+/** @} */
+
+
+/** @name 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 DECLCALLBACKTYPE(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);
+
+/** @} */
+
+/** @name 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 DECLCALLBACKTYPE(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);
+
+/** @} */
+
+
+/** @name 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 DECLCALLBACKTYPE(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 /* !IPRT_INCLUDED_avl_h */
+
diff --git a/include/iprt/base64.h b/include/iprt/base64.h
new file mode 100644
index 00000000..441f6e5e
--- /dev/null
+++ b/include/iprt/base64.h
@@ -0,0 +1,353 @@
+/** @file
+ * IPRT - Base64, MIME content transfer encoding.
+ */
+
+/*
+ * Copyright (C) 2009-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_base64_h
+#define IPRT_INCLUDED_base64_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_base64 RTBase64 - Base64, MIME content transfer encoding.
+ * @ingroup grp_rt
+ * @{
+ */
+
+/** @def RTBASE64_EOL_SIZE
+ * The size of the end-of-line marker. */
+#if defined(RT_OS_OS2) || defined(RT_OS_WINDOWS)
+# define RTBASE64_EOL_SIZE (sizeof("\r\n") - 1)
+#else
+# define RTBASE64_EOL_SIZE (sizeof("\n") - 1)
+#endif
+
+
+/** @name Flags for RTBase64EncodeEx() and RTBase64EncodedLengthEx().
+ * @{ */
+/** Insert line breaks into encoded string.
+ * The size of the end-of-line marker is that that of the host platform.
+ */
+#define RTBASE64_FLAGS_EOL_NATIVE UINT32_C(0) /**< Use native newlines. */
+#define RTBASE64_FLAGS_NO_LINE_BREAKS UINT32_C(1) /**< No newlines. */
+#define RTBASE64_FLAGS_EOL_LF UINT32_C(2) /**< Use UNIX-style newlines. */
+#define RTBASE64_FLAGS_EOL_CRLF UINT32_C(3) /**< Use DOS-style newlines. */
+#define RTBASE64_FLAGS_EOL_STYLE_MASK UINT32_C(3) /**< End-of-line style mask. */
+/** @} */
+
+
+/**
+ * Calculates the decoded data size for a Base64 encoded string.
+ *
+ * @returns The length in bytes. -1 if the encoding is bad.
+ *
+ * @param pszString The Base64 encoded string.
+ * @param ppszEnd If not NULL, this will point to the first char
+ * following the Base64 encoded text block. If
+ * NULL the entire string is assumed to be Base64.
+ */
+RTDECL(ssize_t) RTBase64DecodedSize(const char *pszString, char **ppszEnd);
+
+/**
+ * Calculates the decoded data size for a Base64 encoded UTF-16 string.
+ *
+ * @returns The length in bytes. -1 if the encoding is bad.
+ *
+ * @param pwszString The Base64 encoded UTF-16 string.
+ * @param ppwszEnd If not NULL, this will point to the first char
+ * following the Base64 encoded text block. If
+ * NULL the entire string is assumed to be Base64.
+ */
+RTDECL(ssize_t) RTBase64DecodedUtf16Size(PCRTUTF16 pwszString, PRTUTF16 *ppwszEnd);
+
+/**
+ * Calculates the decoded data size for a Base64 encoded string.
+ *
+ * @returns The length in bytes. -1 if the encoding is bad.
+ *
+ * @param pszString The Base64 encoded string.
+ * @param cchStringMax The max length to decode, use RTSTR_MAX if the
+ * length of @a pszString is not known and it is
+ * really zero terminated.
+ * @param ppszEnd If not NULL, this will point to the first char
+ * following the Base64 encoded text block. If
+ * NULL the entire string is assumed to be Base64.
+ */
+RTDECL(ssize_t) RTBase64DecodedSizeEx(const char *pszString, size_t cchStringMax, char **ppszEnd);
+
+/**
+ * Calculates the decoded data size for a Base64 encoded UTF-16 string.
+ *
+ * @returns The length in bytes. -1 if the encoding is bad.
+ *
+ * @param pwszString The Base64 encoded UTF-16 string.
+ * @param cwcStringMax The max length to decode in RTUTF16 units, use
+ * RTSTR_MAX if the length of @a pwszString is not
+ * known and it is really zero terminated.
+ * @param ppwszEnd If not NULL, this will point to the first char
+ * following the Base64 encoded text block. If
+ * NULL the entire string is assumed to be Base64.
+ */
+RTDECL(ssize_t) RTBase64DecodedUtf16SizeEx(PCRTUTF16 pwszString, size_t cwcStringMax, PRTUTF16 *ppwszEnd);
+
+/**
+ * Decodes a Base64 encoded string into the buffer supplied by the caller.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_BUFFER_OVERFLOW if the buffer is too small. pcbActual will not
+ * be set, nor will ppszEnd.
+ * @retval VERR_INVALID_BASE64_ENCODING if the encoding is wrong.
+ *
+ * @param pszString The Base64 string. Whether the entire string or
+ * just the start of the string is in Base64 depends
+ * on whether ppszEnd is specified or not.
+ * @param pvData Where to store the decoded data.
+ * @param cbData The size of the output buffer that pvData points to.
+ * @param pcbActual Where to store the actual number of bytes returned.
+ * Optional.
+ * @param ppszEnd Indicates that the string may contain other stuff
+ * after the Base64 encoded data when not NULL. Will
+ * be set to point to the first char that's not part of
+ * the encoding. If NULL the entire string must be part
+ * of the Base64 encoded data.
+ */
+RTDECL(int) RTBase64Decode(const char *pszString, void *pvData, size_t cbData, size_t *pcbActual, char **ppszEnd);
+
+/**
+ * Decodes a Base64 encoded UTF-16 string into the buffer supplied by the
+ * caller.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_BUFFER_OVERFLOW if the buffer is too small. pcbActual will not
+ * be set, nor will ppszEnd.
+ * @retval VERR_INVALID_BASE64_ENCODING if the encoding is wrong.
+ *
+ * @param pwszString The Base64 UTF-16 string. Whether the entire string
+ * or just the start of the string is in Base64 depends
+ * on whether ppwszEnd is specified or not.
+ * @param pvData Where to store the decoded data.
+ * @param cbData The size of the output buffer that pvData points to.
+ * @param pcbActual Where to store the actual number of bytes returned.
+ * Optional.
+ * @param ppwszEnd Indicates that the string may contain other stuff
+ * after the Base64 encoded data when not NULL. Will
+ * be set to point to the first char that's not part of
+ * the encoding. If NULL the entire string must be part
+ * of the Base64 encoded data.
+ */
+RTDECL(int) RTBase64DecodeUtf16(PCRTUTF16 pwszString, void *pvData, size_t cbData, size_t *pcbActual, PRTUTF16 *ppwszEnd);
+
+/**
+ * Decodes a Base64 encoded string into the buffer supplied by the caller.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_BUFFER_OVERFLOW if the buffer is too small. pcbActual will not
+ * be set, nor will ppszEnd.
+ * @retval VERR_INVALID_BASE64_ENCODING if the encoding is wrong.
+ *
+ * @param pszString The Base64 string. Whether the entire string or
+ * just the start of the string is in Base64 depends
+ * on whether ppszEnd is specified or not.
+ * @param cchStringMax The max length to decode, use RTSTR_MAX if the
+ * length of @a pszString is not known and it is
+ * really zero terminated.
+ * @param pvData Where to store the decoded data.
+ * @param cbData The size of the output buffer that pvData points to.
+ * @param pcbActual Where to store the actual number of bytes returned.
+ * Optional.
+ * @param ppszEnd Indicates that the string may contain other stuff
+ * after the Base64 encoded data when not NULL. Will
+ * be set to point to the first char that's not part of
+ * the encoding. If NULL the entire string must be part
+ * of the Base64 encoded data.
+ */
+RTDECL(int) RTBase64DecodeEx(const char *pszString, size_t cchStringMax, void *pvData, size_t cbData,
+ size_t *pcbActual, char **ppszEnd);
+
+/**
+ * Decodes a Base64 encoded UTF-16 string into the buffer supplied by the
+ * caller.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_BUFFER_OVERFLOW if the buffer is too small. pcbActual will not
+ * be set, nor will ppszEnd.
+ * @retval VERR_INVALID_BASE64_ENCODING if the encoding is wrong.
+ *
+ * @param pwszString The Base64 UTF-16 string. Whether the entire string
+ * or just the start of the string is in Base64 depends
+ * on whether ppszEnd is specified or not.
+ * @param cwcStringMax The max length to decode in RTUTF16 units, use
+ * RTSTR_MAX if the length of @a pwszString is not
+ * known and it is really zero terminated.
+ * @param pvData Where to store the decoded data.
+ * @param cbData The size of the output buffer that pvData points to.
+ * @param pcbActual Where to store the actual number of bytes returned.
+ * Optional.
+ * @param ppwszEnd Indicates that the string may contain other stuff
+ * after the Base64 encoded data when not NULL. Will
+ * be set to point to the first char that's not part of
+ * the encoding. If NULL the entire string must be part
+ * of the Base64 encoded data.
+ */
+RTDECL(int) RTBase64DecodeUtf16Ex(PCRTUTF16 pwszString, size_t cwcStringMax, void *pvData, size_t cbData,
+ size_t *pcbActual, PRTUTF16 *ppwszEnd);
+
+
+/**
+ * Calculates the length of the Base64 encoding of a given number of bytes of
+ * data produced by RTBase64Encode().
+ *
+ * @returns The Base64 string length, excluding the terminator.
+ * @param cbData The number of bytes to encode.
+ */
+RTDECL(size_t) RTBase64EncodedLength(size_t cbData);
+
+/**
+ * Calculates the UTF-16 length of the Base64 encoding of a given number of
+ * bytes of data produced by RTBase64EncodeUtf16().
+ *
+ * @returns The Base64 UTF-16 string length (in RTUTF16 units), excluding the
+ * terminator.
+ * @param cbData The number of bytes to encode.
+ */
+RTDECL(size_t) RTBase64EncodedUtf16Length(size_t cbData);
+
+/**
+ * Calculates the length of the Base64 encoding of a given number of bytes of
+ * data produced by RTBase64EncodeEx() with the same @a fFlags.
+ *
+ * @returns The Base64 string length, excluding the terminator.
+ * @param cbData The number of bytes to encode.
+ * @param fFlags Flags, any combination of the RTBASE64_FLAGS \#defines.
+ */
+RTDECL(size_t) RTBase64EncodedLengthEx(size_t cbData, uint32_t fFlags);
+
+/**
+ * Calculates the UTF-16 length of the Base64 encoding of a given number of
+ * bytes of data produced by RTBase64EncodeUtf16Ex() with the same @a fFlags.
+ *
+ * @returns The Base64 UTF-16 string length (in RTUTF16 units), excluding the
+ * terminator.
+ * @param cbData The number of bytes to encode.
+ * @param fFlags Flags, any combination of the RTBASE64_FLAGS \#defines.
+ */
+RTDECL(size_t) RTBase64EncodedUtf16LengthEx(size_t cbData, uint32_t fFlags);
+
+/**
+ * Encodes the specifed data into a Base64 string, the caller supplies the
+ * output buffer.
+ *
+ * This is equivalent to calling RTBase64EncodeEx() with no flags.
+ *
+ * @returns IRPT status code.
+ * @retval VERR_BUFFER_OVERFLOW if the output buffer is too small. The buffer
+ * may contain an invalid Base64 string.
+ *
+ * @param pvData The data to encode.
+ * @param cbData The number of bytes to encode.
+ * @param pszBuf Where to put the Base64 string.
+ * @param cbBuf The size of the output buffer, including the terminator.
+ * @param pcchActual The actual number of characters returned.
+ */
+RTDECL(int) RTBase64Encode(const void *pvData, size_t cbData, char *pszBuf, size_t cbBuf, size_t *pcchActual);
+
+/**
+ * Encodes the specifed data into a Base64 UTF-16 string, the caller supplies
+ * the output buffer.
+ *
+ * This is equivalent to calling RTBase64EncodeUtf16Ex() with no flags.
+ *
+ * @returns IRPT status code.
+ * @retval VERR_BUFFER_OVERFLOW if the output buffer is too small. The buffer
+ * may contain an invalid Base64 string.
+ *
+ * @param pvData The data to encode.
+ * @param cbData The number of bytes to encode.
+ * @param pwszBuf Where to put the Base64 UTF-16 string.
+ * @param cwcBuf The size of the output buffer in RTUTF16 units,
+ * including the terminator.
+ * @param pcwcActual The actual number of characters returned (excluding the
+ * terminator). Optional.
+ */
+RTDECL(int) RTBase64EncodeUtf16(const void *pvData, size_t cbData, PRTUTF16 pwszBuf, size_t cwcBuf, size_t *pcwcActual);
+
+/**
+ * Encodes the specifed data into a Base64 string, the caller supplies the
+ * output buffer.
+ *
+ * @returns IRPT status code.
+ * @retval VERR_BUFFER_OVERFLOW if the output buffer is too small. The buffer
+ * may contain an invalid Base64 string.
+ *
+ * @param pvData The data to encode.
+ * @param cbData The number of bytes to encode.
+ * @param fFlags Flags, any combination of the RTBASE64_FLAGS \#defines.
+ * @param pszBuf Where to put the Base64 string.
+ * @param cbBuf The size of the output buffer, including the terminator.
+ * @param pcchActual The actual number of characters returned (excluding the
+ * terminator). Optional.
+ */
+RTDECL(int) RTBase64EncodeEx(const void *pvData, size_t cbData, uint32_t fFlags,
+ char *pszBuf, size_t cbBuf, size_t *pcchActual);
+
+/**
+ * Encodes the specifed data into a Base64 UTF-16 string, the caller supplies
+ * the output buffer.
+ *
+ * @returns IRPT status code.
+ * @retval VERR_BUFFER_OVERFLOW if the output buffer is too small. The buffer
+ * may contain an invalid Base64 string.
+ *
+ * @param pvData The data to encode.
+ * @param cbData The number of bytes to encode.
+ * @param fFlags Flags, any combination of the RTBASE64_FLAGS \#defines.
+ * @param pwszBuf Where to put the Base64 UTF-16 string.
+ * @param cwcBuf The size of the output buffer in RTUTF16 units,
+ * including the terminator.
+ * @param pcwcActual The actual number of characters returned (excluding the
+ * terminator). Optional.
+ */
+RTDECL(int) RTBase64EncodeUtf16Ex(const void *pvData, size_t cbData, uint32_t fFlags,
+ PRTUTF16 pwszBuf, size_t cwcBuf, size_t *pcwcActual);
+
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_base64_h */
+
diff --git a/include/iprt/bignum.h b/include/iprt/bignum.h
new file mode 100644
index 00000000..ff1b8c48
--- /dev/null
+++ b/include/iprt/bignum.h
@@ -0,0 +1,197 @@
+/** @file
+ * IPRT - Big Integer Numbers.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_bignum_h
+#define IPRT_INCLUDED_bignum_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rtbignum RTBigNum - Big Integer Numbers
+ * @ingroup grp_rt
+ * @{
+ */
+
+/** The big integer number element type. */
+#if ARCH_BITS == 64
+typedef uint64_t RTBIGNUMELEMENT;
+#else
+typedef uint32_t RTBIGNUMELEMENT;
+#endif
+/** Pointer to a big integer number element. */
+typedef RTBIGNUMELEMENT *PRTBIGNUMELEMENT;
+/** Pointer to a const big integer number element. */
+typedef RTBIGNUMELEMENT const *PCRTBIGNUMELEMENT;
+
+/** The size (in bytes) of one array element. */
+#if ARCH_BITS == 64
+# define RTBIGNUM_ELEMENT_SIZE 8
+#else
+# define RTBIGNUM_ELEMENT_SIZE 4
+#endif
+/** The number of bits in one array element. */
+#define RTBIGNUM_ELEMENT_BITS (RTBIGNUM_ELEMENT_SIZE * 8)
+/** Returns the bitmask corrsponding to given bit number. */
+#if ARCH_BITS == 64
+# define RTBIGNUM_ELEMENT_BIT(iBit) RT_BIT_64(iBit)
+#else
+# define RTBIGNUM_ELEMENT_BIT(iBit) RT_BIT_32(iBit)
+#endif
+/** The maximum value one element can hold. */
+#if ARCH_BITS == 64
+# define RTBIGNUM_ELEMENT_MAX UINT64_MAX
+#else
+# define RTBIGNUM_ELEMENT_MAX UINT32_MAX
+#endif
+/** Mask including all the element bits set to 1. */
+#define RTBIGNUM_ELEMENT_MASK RTBIGNUM_ELEMENT_MAX
+
+
+/**
+ * IPRT big integer number.
+ */
+typedef struct RTBIGNUM
+{
+ /** Elements array where the magnitue of the value is stored. */
+ RTBIGNUMELEMENT *pauElements;
+ /** The current number of elements we're using in the pauElements array. */
+ uint32_t cUsed;
+ /** The current allocation size of pauElements. */
+ uint32_t cAllocated;
+ /** Reserved for future use. */
+ uint32_t uReserved;
+
+ /** Set if it's a negative number, clear if positive or zero. */
+ uint32_t fNegative : 1;
+
+ /** Whether to use a the data is sensitive (RTBIGNUMINIT_F_SENSITIVE). */
+ uint32_t fSensitive : 1;
+ /** The number is currently scrambled */
+ uint32_t fCurScrambled : 1;
+
+ /** Bits reserved for future use. */
+ uint32_t fReserved : 30;
+} RTBIGNUM;
+
+
+RTDECL(int) RTBigNumInit(PRTBIGNUM pBigNum, uint32_t fFlags, void const *pvRaw, size_t cbRaw);
+RTDECL(int) RTBigNumInitZero(PRTBIGNUM pBigNum, uint32_t fFlags);
+
+/** @name RTBIGNUMINIT_F_XXX - RTBigNumInit flags.
+ * @{ */
+/** The number is sensitive so use a safer allocator, scramble it when not
+ * in use, and apply RTMemWipeThoroughly before freeing. The RTMemSafer API
+ * takes care of these things.
+ * @note When using this flag, concurrent access is not possible! */
+#define RTBIGNUMINIT_F_SENSITIVE RT_BIT(0)
+/** Big endian number. */
+#define RTBIGNUMINIT_F_ENDIAN_BIG RT_BIT(1)
+/** Little endian number. */
+#define RTBIGNUMINIT_F_ENDIAN_LITTLE RT_BIT(2)
+/** The raw number is unsigned. */
+#define RTBIGNUMINIT_F_UNSIGNED RT_BIT(3)
+/** The raw number is signed. */
+#define RTBIGNUMINIT_F_SIGNED RT_BIT(4)
+/** @} */
+
+RTDECL(int) RTBigNumClone(PRTBIGNUM pBigNum, PCRTBIGNUM pSrc);
+
+RTDECL(int) RTBigNumDestroy(PRTBIGNUM pBigNum);
+
+
+/**
+ * The minimum number of bits require store the two's complement representation
+ * of the number.
+ *
+ * @returns Width in number of bits.
+ * @param pBigNum The big number.
+ */
+RTDECL(uint32_t) RTBigNumBitWidth(PCRTBIGNUM pBigNum);
+RTDECL(uint32_t) RTBigNumByteWidth(PCRTBIGNUM pBigNum);
+
+
+/**
+ * Converts the big number to a sign-extended big endian byte sequence.
+ *
+ * @returns IPRT status code
+ * @retval VERR_BUFFER_OVERFLOW if the specified buffer is too small.
+ * @param pBigNum The big number.
+ * @param pvBuf The output buffer (size is at least cbWanted).
+ * @param cbWanted The number of bytes wanted.
+ */
+RTDECL(int) RTBigNumToBytesBigEndian(PCRTBIGNUM pBigNum, void *pvBuf, size_t cbWanted);
+
+/**
+ * Compares two numbers.
+ *
+ * @retval -1 if pLeft < pRight.
+ * @retval 0 if pLeft == pRight.
+ * @retval 1 if pLeft > pRight.
+ *
+ * @param pLeft The left side number.
+ * @param pRight The right side number.
+ */
+RTDECL(int) RTBigNumCompare(PRTBIGNUM pLeft, PRTBIGNUM pRight);
+RTDECL(int) RTBigNumCompareWithU64(PRTBIGNUM pLeft, uint64_t uRight);
+RTDECL(int) RTBigNumCompareWithS64(PRTBIGNUM pLeft, int64_t iRight);
+
+RTDECL(int) RTBigNumAssign(PRTBIGNUM pDst, PCRTBIGNUM pSrc);
+RTDECL(int) RTBigNumNegate(PRTBIGNUM pResult, PCRTBIGNUM pBigNum);
+RTDECL(int) RTBigNumNegateThis(PRTBIGNUM pThis);
+
+RTDECL(int) RTBigNumAdd(PRTBIGNUM pResult, PCRTBIGNUM pAugend, PCRTBIGNUM pAddend);
+RTDECL(int) RTBigNumSubtract(PRTBIGNUM pResult, PCRTBIGNUM pMinuend, PCRTBIGNUM pSubtrahend);
+RTDECL(int) RTBigNumMultiply(PRTBIGNUM pResult, PCRTBIGNUM pMultiplicand, PCRTBIGNUM pMultiplier);
+RTDECL(int) RTBigNumDivide(PRTBIGNUM pQuotient, PRTBIGNUM pRemainder, PCRTBIGNUM pDividend, PCRTBIGNUM pDivisor);
+RTDECL(int) RTBigNumDivideKnuth(PRTBIGNUM pQuotient, PRTBIGNUM pRemainder, PCRTBIGNUM pDividend, PCRTBIGNUM pDivisor);
+RTDECL(int) RTBigNumDivideLong(PRTBIGNUM pQuotient, PRTBIGNUM pRemainder, PCRTBIGNUM pDividend, PCRTBIGNUM pDivisor);
+RTDECL(int) RTBigNumModulo(PRTBIGNUM pRemainder, PCRTBIGNUM pDividend, PCRTBIGNUM pDivisor);
+RTDECL(int) RTBigNumExponentiate(PRTBIGNUM pResult, PCRTBIGNUM pBase, PCRTBIGNUM pExponent);
+RTDECL(int) RTBigNumShiftLeft(PRTBIGNUM pResult, PCRTBIGNUM pValue, uint32_t cBits);
+RTDECL(int) RTBigNumShiftRight(PRTBIGNUM pResult, PCRTBIGNUM pValue, uint32_t cBits);
+
+RTDECL(int) RTBigNumModExp(PRTBIGNUM pResult, PRTBIGNUM pBase, PRTBIGNUM pExponent, PRTBIGNUM pModulus);
+
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_bignum_h */
+
diff --git a/include/iprt/bldprog-strtab-template.cpp.h b/include/iprt/bldprog-strtab-template.cpp.h
new file mode 100644
index 00000000..c4d63f4d
--- /dev/null
+++ b/include/iprt/bldprog-strtab-template.cpp.h
@@ -0,0 +1,1335 @@
+/* $Id: bldprog-strtab-template.cpp.h $ */
+/** @file
+ * IPRT - Build Program - String Table Generator.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+
+/*
+ * (Avoid include sanity checks as this is ring-3 only, C++ code.)
+ */
+#if defined(__cplusplus) && defined(IN_RING3)
+
+
+/*********************************************************************************************************************************
+* Defined Constants And Macros *
+*********************************************************************************************************************************/
+/** @def BLDPROG_STRTAB_MAX_STRLEN
+ * The max length of strings in the table. */
+#if !defined(BLDPROG_STRTAB_MAX_STRLEN) || defined(DOXYGEN_RUNNING)
+# define BLDPROG_STRTAB_MAX_STRLEN 256
+#endif
+
+/** @def BLDPROG_STRTAB_WITH_COMPRESSION
+ * Enables very simple string compression.
+ */
+#if defined(DOXYGEN_RUNNING)
+# define BLDPROG_STRTAB_WITH_COMPRESSION
+#endif
+
+/** @def BLDPROG_STRTAB_WITH_CAMEL_WORDS
+ * Modifies the string compression to look for camel case words.
+ */
+#if defined(DOXYGEN_RUNNING)
+# define BLDPROG_STRTAB_WITH_CAMEL_WORDS
+#endif
+
+/** @def BLDPROG_STRTAB_PURE_ASCII
+ * String compression assumes pure 7-bit ASCII and will fail on UTF-8 when this
+ * is defined. Otherwise, the compression code will require IPRT to link.
+ */
+#if defined(DOXYGEN_RUNNING)
+# define BLDPROG_STRTAB_PURE_ASCII
+#endif
+
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#include <iprt/stdarg.h>
+#include <iprt/ctype.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#ifdef BLDPROG_STRTAB_WITH_COMPRESSION
+# include <map>
+# include <iprt/sanitized/string>
+
+# define BLDPROG_STRTAB_WITH_WORD_SEP_ALTERNATIVE
+typedef struct BLDPROGWORDFREQSTATS
+{
+ uint32_t cWithoutSep; /**< Number of occurances without a separator. */
+# ifdef BLDPROG_STRTAB_WITH_WORD_SEP_ALTERNATIVE
+ uint32_t cWithSep; /**< Number of occurance with a separator. */
+ char chSep; /**< The separator. First come basis. */
+# endif
+} BLDPROGWORDFREQSTATS;
+
+typedef std::map<std::string, BLDPROGWORDFREQSTATS> BLDPROGWORDFREQMAP;
+
+#endif
+
+#include "../../src/VBox/Runtime/include/internal/strhash.h" /** @todo make this one public */
+
+
+/*********************************************************************************************************************************
+* Structures and Typedefs *
+*********************************************************************************************************************************/
+/**
+ * Build table string.
+ */
+typedef struct BLDPROGSTRING
+{
+ /** The string.
+ * @note This may be modified or replaced (allocated from heap) when
+ * compressing the string table. */
+ char *pszString;
+ /** The string hash value. */
+ uint32_t uHash;
+ /** The strint table offset. */
+ uint32_t offStrTab;
+ /** The string length. */
+ size_t cchString;
+ /** Pointer to the next string reference (same string table entry). */
+ struct BLDPROGSTRING *pNextRef;
+ /** Pointer to the next string with the same hash value (collision). */
+ struct BLDPROGSTRING *pNextCollision;
+
+} BLDPROGSTRING;
+/** Pointer to a string table string. */
+typedef BLDPROGSTRING *PBLDPROGSTRING;
+
+
+/** String table data. */
+typedef struct BLDPROGSTRTAB
+{
+ /** The size of g_papStrHash. */
+ size_t cStrHash;
+ /** String hash table. */
+ PBLDPROGSTRING *papStrHash;
+ /** Duplicate strings found by AddString. */
+ size_t cDuplicateStrings;
+ /** Total length of the unique strings (no terminators). */
+ size_t cchUniqueStrings;
+ /** Number of unique strings after AddString. */
+ size_t cUniqueStrings;
+ /** Number of collisions. */
+ size_t cCollisions;
+
+ /** Number of entries in apSortedStrings. */
+ size_t cSortedStrings;
+ /** The sorted string table. */
+ PBLDPROGSTRING *papSortedStrings;
+
+#ifdef BLDPROG_STRTAB_WITH_COMPRESSION
+ /** The 256 words we've picked to be indexed by reference. */
+ BLDPROGSTRING aCompDict[256];
+ /** The frequency of the 256 dictionary entries. */
+ size_t auCompDictFreq[256];
+ /** Incoming strings pending compression. */
+ PBLDPROGSTRING *papPendingStrings;
+ /** Current number of entries in papStrPending. */
+ size_t cPendingStrings;
+ /** The allocated size of papPendingStrings. */
+ size_t cMaxPendingStrings;
+ /** Work frequency map.
+ * @todo rewrite in plain C. */
+ BLDPROGWORDFREQMAP Frequencies;
+ /** Map of characters used by input strings. */
+ uint64_t bmUsedChars[256/64];
+#endif
+
+ /** The string table. */
+ char *pachStrTab;
+ /** The actual string table size. */
+ size_t cchStrTab;
+} BLDPROGSTRTAB;
+typedef BLDPROGSTRTAB *PBLDPROGSTRTAB;
+
+#if RT_CLANG_PREREQ(4, 0) || RT_GNUC_PREREQ(4, 6)
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wunused-function"
+#endif
+
+
+#ifdef BLDPROG_STRTAB_WITH_COMPRESSION
+
+/**
+ * Same as ASMBitTest.
+ *
+ * We cannot safely use ASMBitTest here because it must be inline, as this code
+ * is used to build RuntimeBldProg. */
+DECLINLINE(bool) BldProgBitIsSet(uint64_t const *pbmBitmap, size_t iBit)
+{
+ return RT_BOOL(pbmBitmap[iBit / 64] & RT_BIT_64(iBit % 64));
+}
+
+
+/**
+ * Same as ASMBitSet.
+ *
+ * We cannot safely use ASMBitSet here because it must be inline, as this code
+ * is used to build RuntimeBldProg.
+ */
+DECLINLINE(void) BldProgBitSet(uint64_t *pbmBitmap, size_t iBit)
+{
+ pbmBitmap[iBit / 64] |= RT_BIT_64(iBit % 64);
+}
+
+#endif
+
+
+/**
+ * Initializes the strint table compiler.
+ *
+ * @returns success indicator (out of memory if false).
+ * @param pThis The strint table compiler instance.
+ * @param cMaxStrings The max number of strings we'll be adding.
+ */
+static bool BldProgStrTab_Init(PBLDPROGSTRTAB pThis, size_t cMaxStrings)
+{
+ pThis->cStrHash = 0;
+ pThis->papStrHash = NULL;
+ pThis->cDuplicateStrings = 0;
+ pThis->cchUniqueStrings = 0;
+ pThis->cUniqueStrings = 0;
+ pThis->cCollisions = 0;
+ pThis->cSortedStrings = 0;
+ pThis->papSortedStrings = NULL;
+ pThis->pachStrTab = NULL;
+ pThis->cchStrTab = 0;
+#ifdef BLDPROG_STRTAB_WITH_COMPRESSION
+ memset(pThis->aCompDict, 0, sizeof(pThis->aCompDict));
+ pThis->papPendingStrings = NULL;
+ pThis->cPendingStrings = 0;
+ pThis->cMaxPendingStrings = cMaxStrings;
+ memset(pThis->bmUsedChars, 0, sizeof(pThis->bmUsedChars));
+ BldProgBitSet(pThis->bmUsedChars, 0); /* Some parts of the code still thinks zero is a terminator, so don't use it for now. */
+# ifndef BLDPROG_STRTAB_PURE_ASCII
+ BldProgBitSet(pThis->bmUsedChars, 0xff); /* Reserve escape byte for codepoints above 127. */
+# endif
+#endif
+
+ /*
+ * Allocate a hash table double the size of all strings (to avoid too
+ * many collisions). Add all strings to it, finding duplicates in the
+ * process.
+ */
+#ifdef BLDPROG_STRTAB_WITH_COMPRESSION
+ cMaxStrings += RT_ELEMENTS(pThis->aCompDict);
+#endif
+ cMaxStrings *= 2;
+ pThis->papStrHash = (PBLDPROGSTRING *)calloc(sizeof(pThis->papStrHash[0]), cMaxStrings);
+ if (pThis->papStrHash)
+ {
+ pThis->cStrHash = cMaxStrings;
+#ifdef BLDPROG_STRTAB_WITH_COMPRESSION
+ pThis->papPendingStrings = (PBLDPROGSTRING *)calloc(sizeof(pThis->papPendingStrings[0]), pThis->cMaxPendingStrings);
+ if (pThis->papPendingStrings)
+#endif
+ return true;
+
+#ifdef BLDPROG_STRTAB_WITH_COMPRESSION
+ free(pThis->papStrHash);
+ pThis->papStrHash = NULL;
+#endif
+ }
+ return false;
+}
+
+
+#if 0 /* unused */
+static void BldProgStrTab_Delete(PBLDPROGSTRTAB pThis)
+{
+ free(pThis->papStrHash);
+ free(pThis->papSortedStrings);
+ free(pThis->pachStrTab);
+# ifdef BLDPROG_STRTAB_WITH_COMPRESSION
+ free(pThis->papPendingStrings);
+# endif
+ memset(pThis, 0, sizeof(*pThis));
+}
+#endif
+
+#ifdef BLDPROG_STRTAB_WITH_COMPRESSION
+
+DECLINLINE(size_t) bldProgStrTab_compressorFindNextWord(const char *pszSrc, char ch, const char **ppszSrc)
+{
+ /*
+ * Skip leading word separators.
+ */
+# ifdef BLDPROG_STRTAB_WITH_CAMEL_WORDS
+ while ( ch == ' '
+ || ch == '-'
+ || ch == '+'
+ || ch == '_')
+# else
+ while (ch == ' ')
+# endif
+ ch = *++pszSrc;
+ if (ch)
+ {
+ /*
+ * Find end of word.
+ */
+ size_t cchWord = 1;
+# ifdef BLDPROG_STRTAB_WITH_CAMEL_WORDS
+ char chPrev = ch;
+ while ( (ch = pszSrc[cchWord]) != ' '
+ && ch != '\0'
+ && ch != '-'
+ && ch != '+'
+ && ch != '_'
+ && ( ch == chPrev
+ || !RT_C_IS_UPPER(ch)
+ || RT_C_IS_UPPER(chPrev)) )
+ {
+ chPrev = ch;
+ cchWord++;
+ }
+# else
+ while ((ch = pszSrc[cchWord]) != ' ' && ch != '\0')
+ cchWord++;
+# endif
+ *ppszSrc = pszSrc;
+ return cchWord;
+ }
+
+ *ppszSrc = pszSrc;
+ return 0;
+}
+
+
+/**
+ * Analyzes a string.
+ *
+ * @param pThis The strint table compiler instance.
+ * @param pStr The string to analyze.
+ */
+static void bldProgStrTab_compressorAnalyzeString(PBLDPROGSTRTAB pThis, PBLDPROGSTRING pStr)
+{
+ /*
+ * Mark all the string characters as used.
+ */
+ const char *psz = pStr->pszString;
+ char ch;
+ while ((ch = *psz++) != '\0')
+ BldProgBitSet(pThis->bmUsedChars, (uint8_t)ch);
+
+ /*
+ * For now we just consider words.
+ */
+ psz = pStr->pszString;
+ while ((ch = *psz) != '\0')
+ {
+ size_t cchWord = bldProgStrTab_compressorFindNextWord(psz, ch, &psz);
+ if (cchWord > 1)
+ {
+ std::string strWord(psz, cchWord);
+ BLDPROGWORDFREQMAP::iterator it = pThis->Frequencies.find(strWord);
+ if (it != pThis->Frequencies.end())
+ {
+# ifdef BLDPROG_STRTAB_WITH_WORD_SEP_ALTERNATIVE
+ char const chSep = psz[cchWord];
+ if (chSep != '\0' && (it->second.chSep == chSep || it->second.chSep == '\0'))
+ {
+ it->second.chSep = chSep;
+ it->second.cWithSep++;
+ }
+ else
+# endif
+ it->second.cWithoutSep++;
+ }
+ else
+ {
+# ifdef BLDPROG_STRTAB_WITH_WORD_SEP_ALTERNATIVE
+ char const chSep = psz[cchWord];
+ if (chSep != '\0')
+ {
+ BLDPROGWORDFREQSTATS const NewWord = { 0, 0, chSep };
+ pThis->Frequencies[strWord] = NewWord;
+ }
+ else
+ {
+ static BLDPROGWORDFREQSTATS const s_NewWord = { 0, 0, 0 };
+ pThis->Frequencies[strWord] = s_NewWord;
+ }
+# else
+ pThis->Frequencies[strWord].cWithoutSep = 0;
+# endif
+ }
+
+# if 0 /** @todo need better accounting for overlapping alternatives before this can be enabled. */
+ /* Two words - immediate yields calc may lie when this enabled and we may pick the wrong words. */
+ if (ch == ' ')
+ {
+ ch = psz[++cchWord];
+ if (ch != ' ' && ch != '\0')
+ {
+ size_t const cchSaved = cchWord;
+
+ do
+ cchWord++;
+ while ((ch = psz[cchWord]) != ' ' && ch != '\0');
+
+ strWord = std::string(psz, cchWord);
+ BLDPROGWORDFREQMAP::iterator it = pThis->Frequencies.find(strWord);
+ if (it != pThis->Frequencies.end())
+ it->second += cchWord - 1;
+ else
+ pThis->Frequencies[strWord] = 0;
+
+ cchWord = cchSaved;
+ }
+ }
+# endif
+ }
+ else if (!cchWord)
+ break;
+
+ /* Advance. */
+ psz += cchWord;
+ }
+ pStr->cchString = psz - pStr->pszString;
+ if (pStr->cchString > BLDPROG_STRTAB_MAX_STRLEN)
+ {
+ fprintf(stderr, "error: String to long (%u)\n", (unsigned)pStr->cchString);
+ abort();
+ }
+}
+
+#endif /* BLDPROG_STRTAB_WITH_COMPRESSION */
+
+/**
+ * Adds a string to the hash table.
+ * @param pThis The strint table compiler instance.
+ * @param pStr The string.
+ */
+static void bldProgStrTab_AddStringToHashTab(PBLDPROGSTRTAB pThis, PBLDPROGSTRING pStr)
+{
+ pStr->pNextRef = NULL;
+ pStr->pNextCollision = NULL;
+ pStr->offStrTab = 0;
+ pStr->uHash = sdbm(pStr->pszString, &pStr->cchString);
+ if (pStr->cchString > BLDPROG_STRTAB_MAX_STRLEN)
+ {
+ fprintf(stderr, "error: String to long (%u)\n", (unsigned)pStr->cchString);
+ exit(RTEXITCODE_FAILURE);
+ }
+
+ size_t idxHash = pStr->uHash % pThis->cStrHash;
+ PBLDPROGSTRING pCur = pThis->papStrHash[idxHash];
+ if (!pCur)
+ pThis->papStrHash[idxHash] = pStr;
+ else
+ {
+ /* Look for matching string. */
+ do
+ {
+ if ( pCur->uHash == pStr->uHash
+ && pCur->cchString == pStr->cchString
+ && memcmp(pCur->pszString, pStr->pszString, pStr->cchString) == 0)
+ {
+ pStr->pNextRef = pCur->pNextRef;
+ pCur->pNextRef = pStr;
+ pThis->cDuplicateStrings++;
+ return;
+ }
+ pCur = pCur->pNextCollision;
+ } while (pCur != NULL);
+
+ /* No matching string, insert. */
+ pThis->cCollisions++;
+ pStr->pNextCollision = pThis->papStrHash[idxHash];
+ pThis->papStrHash[idxHash] = pStr;
+ }
+
+ pThis->cUniqueStrings++;
+ pThis->cchUniqueStrings += pStr->cchString;
+}
+
+
+/**
+ * Adds a string to the string table.
+ *
+ * @param pThis The strint table compiler instance.
+ * @param pStr The string.
+ */
+static void BldProgStrTab_AddString(PBLDPROGSTRTAB pThis, PBLDPROGSTRING pStr)
+{
+#ifdef BLDPROG_STRTAB_WITH_COMPRESSION
+ bldProgStrTab_compressorAnalyzeString(pThis, pStr);
+ if (pThis->cPendingStrings < pThis->cMaxPendingStrings)
+ pThis->papPendingStrings[pThis->cPendingStrings++] = pStr;
+ else
+ abort();
+#else
+ bldProgStrTab_AddStringToHashTab(pThis, pStr);
+#endif
+}
+
+
+/**
+ * Adds a string to the string table.
+ *
+ * @param pThis The strint table compiler instance.
+ * @param pStr The string entry (uninitialized).
+ * @param psz The string, will be duplicated if compression is enabled.
+ */
+DECLINLINE(void) BldProgStrTab_AddStringDup(PBLDPROGSTRTAB pThis, PBLDPROGSTRING pStr, const char *psz)
+{
+#ifdef BLDPROG_STRTAB_WITH_COMPRESSION
+ pStr->pszString = strdup(psz);
+ if (!pStr->pszString)
+ abort();
+#else
+ pStr->pszString = (char *)psz;
+#endif
+ BldProgStrTab_AddString(pThis, pStr);
+}
+
+#ifdef BLDPROG_STRTAB_WITH_COMPRESSION
+
+/**
+ * Copies @a cchSrc chars from @a pchSrc to @a pszDst, escaping special
+ * sequences.
+ *
+ * @returns New @a pszDst position, NULL if invalid source encoding.
+ * @param pszDst The destination buffer.
+ * @param pszSrc The source buffer.
+ * @param cchSrc How much to copy.
+ */
+static char *bldProgStrTab_compressorCopyAndEscape(char *pszDst, const char *pszSrc, size_t cchSrc)
+{
+ while (cchSrc-- > 0)
+ {
+ char ch = *pszSrc;
+ if (!((unsigned char)ch & 0x80))
+ {
+ *pszDst++ = ch;
+ pszSrc++;
+ }
+ else
+ {
+# ifdef BLDPROG_STRTAB_PURE_ASCII
+ fprintf(stderr, "error: unexpected char value %#x\n", ch);
+ return NULL;
+# else
+ RTUNICP uc;
+ int rc = RTStrGetCpEx(&pszSrc, &uc);
+ if (RT_SUCCESS(rc))
+ {
+ *pszDst++ = (unsigned char)0xff; /* escape single code point. */
+ pszDst = RTStrPutCp(pszDst, uc);
+ }
+ else
+ {
+ fprintf(stderr, "Error: RTStrGetCpEx failed with rc=%d\n", rc);
+ return NULL;
+ }
+# endif
+ }
+ }
+ return pszDst;
+}
+
+
+/**
+ * Replaces the dictionary words and escapes non-ascii chars in a string.
+ *
+ * @param pThis The strint table compiler instance.
+ * @param pString The string to fixup.
+ */
+static bool bldProgStrTab_compressorFixupString(PBLDPROGSTRTAB pThis, PBLDPROGSTRING pStr)
+{
+ char szNew[BLDPROG_STRTAB_MAX_STRLEN * 2];
+ char *pszDst = szNew;
+ const char *pszSrc = pStr->pszString;
+ const char *pszSrcEnd = pszSrc + pStr->cchString;
+
+ char ch;
+ while ((ch = *pszSrc) != '\0')
+ {
+ const char * const pszSrcUncompressed = pszSrc;
+ size_t cchWord = bldProgStrTab_compressorFindNextWord(pszSrc, ch, &pszSrc);
+ size_t cchSrcUncompressed = pszSrc - pszSrcUncompressed;
+ if (cchSrcUncompressed > 0)
+ {
+ pszDst = bldProgStrTab_compressorCopyAndEscape(pszDst, pszSrcUncompressed, cchSrcUncompressed);
+ if (!pszDst)
+ return false;
+ }
+ if (!cchWord)
+ break;
+
+ /* Check for g_aWord matches. */
+ if (cchWord > 1)
+ {
+ size_t cchMax = pszSrcEnd - pszSrc;
+ for (unsigned i = 0; i < RT_ELEMENTS(pThis->aCompDict); i++)
+ {
+ size_t cchLen = pThis->aCompDict[i].cchString;
+ if ( cchLen >= cchWord
+ && cchLen <= cchMax
+ && memcmp(pThis->aCompDict[i].pszString, pszSrc, cchLen) == 0)
+ {
+ *pszDst++ = (unsigned char)i;
+ pszSrc += cchLen;
+ cchWord = 0;
+ break;
+ }
+ }
+ }
+
+ if (cchWord > 0)
+ {
+ /* Copy the current word. */
+ pszDst = bldProgStrTab_compressorCopyAndEscape(pszDst, pszSrc, cchWord);
+ if (!pszDst)
+ return false;
+ pszSrc += cchWord;
+ }
+ }
+
+ /* Just terminate it now. */
+ *pszDst = '\0';
+
+ /*
+ * Update the string.
+ */
+ size_t cchNew = pszDst - &szNew[0];
+ if (cchNew > pStr->cchString)
+ {
+ pStr->pszString = (char *)malloc(cchNew + 1);
+ if (!pStr->pszString)
+ {
+ fprintf(stderr, "Out of memory!\n");
+ return false;
+ }
+ }
+ memcpy(pStr->pszString, szNew, cchNew + 1);
+ pStr->cchString = cchNew;
+
+ return true;
+}
+
+
+/**
+ * Entry in SortedDictionary.
+ *
+ * Uses variable length string member, so not class and allocated via malloc.
+ */
+struct SortedDictionaryEntry
+{
+ size_t m_cchGain;
+ size_t m_cchString;
+ RT_FLEXIBLE_ARRAY_EXTENSION
+ char m_szString[RT_FLEXIBLE_ARRAY];
+
+ /** Allocates and initializes a new entry. */
+ static SortedDictionaryEntry *allocate(const char *a_pch, size_t a_cch, size_t a_cchGain, char a_chSep)
+ {
+ size_t cbString = a_cch + !!a_chSep + 1;
+ SortedDictionaryEntry *pNew = (SortedDictionaryEntry *)malloc(RT_UOFFSETOF(SortedDictionaryEntry, m_szString) + cbString);
+ if (pNew)
+ {
+ pNew->m_cchGain = a_cchGain;
+ memcpy(pNew->m_szString, a_pch, a_cch);
+ if (a_chSep)
+ pNew->m_szString[a_cch++] = a_chSep;
+ pNew->m_szString[a_cch] = '\0';
+ pNew->m_cchString = a_cch;
+ }
+ return pNew;
+ }
+
+
+ /** Compares this dictionary entry with an incoming one.
+ * @retval -1 if this entry is of less worth than the new one.
+ * @retval 0 if this entry is of equal worth to the new one.
+ * @retval +1 if this entry is of more worth than the new one.
+ */
+ int compare(size_t a_cchGain, size_t a_cchString)
+ {
+ /* Higher gain is preferred of course: */
+ if (m_cchGain < a_cchGain)
+ return -1;
+ if (m_cchGain > a_cchGain)
+ return 1;
+
+ /* Gain is the same. Prefer the shorter string, as it will result in a shorter string table: */
+ if (m_cchString > a_cchString)
+ return -1;
+ if (m_cchString < a_cchString)
+ return 1;
+ return 0;
+ }
+};
+
+
+/**
+ * Insertion sort dictionary that keeps the 256 best words.
+ *
+ * Used by bldProgStrTab_compressorDoStringCompression to pick the dictionary
+ * words.
+ */
+class SortedDictionary
+{
+public:
+ size_t m_cEntries;
+ SortedDictionaryEntry *m_apEntries[256];
+
+ SortedDictionary()
+ : m_cEntries(0)
+ {
+ for (size_t i = 0; i < RT_ELEMENTS(m_apEntries); i++)
+ m_apEntries[i] = NULL;
+ }
+
+ ~SortedDictionary()
+ {
+ while (m_cEntries > 0)
+ {
+ free(m_apEntries[--m_cEntries]);
+ m_apEntries[m_cEntries] = NULL;
+ }
+ }
+
+
+ /**
+ * Inserts a new entry, if it's worth it.
+ * @returns true on succes, false if out of memory.
+ */
+ bool insert(const char *a_pchString, size_t a_cchStringBase, size_t a_cchGain, char a_chSep = 0)
+ {
+ size_t const cchString = a_cchStringBase + (a_chSep + 1);
+
+ /*
+ * Drop the insert if the symbol table is full and the insert is less worth the last entry:
+ */
+ if ( m_cEntries >= RT_ELEMENTS(m_apEntries)
+ && m_apEntries[RT_ELEMENTS(m_apEntries) - 1]->compare(a_cchGain, cchString) >= 0)
+ return true;
+
+ /*
+ * Create a new entry to insert.
+ */
+ SortedDictionaryEntry *pNewEntry = SortedDictionaryEntry::allocate(a_pchString, a_cchStringBase, a_cchGain, a_chSep);
+ if (!pNewEntry)
+ return false;
+
+ /*
+ * Find the insert point.
+ */
+ if (m_cEntries == 0)
+ {
+ m_apEntries[0] = pNewEntry;
+ m_cEntries = 1;
+ }
+ else
+ {
+ /* If table is full, drop the last entry before we start (already made
+ sure the incoming entry is preferable to the one were dropping): */
+ if (m_cEntries >= RT_ELEMENTS(m_apEntries))
+ {
+ free(m_apEntries[RT_ELEMENTS(m_apEntries) - 1]);
+ m_apEntries[RT_ELEMENTS(m_apEntries) - 1] = NULL;
+ m_cEntries = RT_ELEMENTS(m_apEntries) - 1;
+ }
+
+ /* Find where to insert the new entry: */
+ /** @todo use binary search. */
+ size_t i = m_cEntries;
+ while (i > 0 && m_apEntries[i - 1]->compare(a_cchGain, cchString) < 0)
+ i--;
+
+ /* Shift entries to make room and insert the new entry. */
+ if (i < m_cEntries)
+ memmove(&m_apEntries[i + 1], &m_apEntries[i], (m_cEntries - i) * sizeof(m_apEntries[0]));
+ m_apEntries[i] = pNewEntry;
+ m_cEntries++;
+ }
+ return true;
+ }
+};
+
+
+/**
+ * Compresses the vendor and product strings.
+ *
+ * This is very very simple (a lot less work than the string table for
+ * instance).
+ */
+static bool bldProgStrTab_compressorDoStringCompression(PBLDPROGSTRTAB pThis, bool fVerbose)
+{
+ /*
+ * Sort the frequency analyzis result and pick the top entries for any
+ * available dictionary slots.
+ */
+ SortedDictionary SortedDict;
+ for (BLDPROGWORDFREQMAP::iterator it = pThis->Frequencies.begin(); it != pThis->Frequencies.end(); ++it)
+ {
+ bool fInsert;
+ size_t const cchString = it->first.length();
+# ifndef BLDPROG_STRTAB_WITH_WORD_SEP_ALTERNATIVE
+ size_t const cchGainWithout = it->second.cWithoutSep * cchString;
+# else
+ size_t const cchGainWithout = (it->second.cWithoutSep + it->second.cWithSep) * cchString;
+ size_t const cchGainWith = it->second.cWithSep * (cchString + 1);
+ if (cchGainWith > cchGainWithout)
+ fInsert = SortedDict.insert(it->first.c_str(), cchString, cchGainWith, it->second.chSep);
+ else
+# endif
+ fInsert = SortedDict.insert(it->first.c_str(), cchString, cchGainWithout);
+ if (!fInsert)
+ return false;
+ }
+
+ size_t cb = 0;
+ size_t cWords = 0;
+ size_t iDict = 0;
+ for (size_t i = 0; i < RT_ELEMENTS(pThis->aCompDict); i++)
+ {
+ char szTmp[2] = { (char)i, '\0' };
+ const char *psz = szTmp;
+ if ( BldProgBitIsSet(pThis->bmUsedChars, i)
+ || iDict >= SortedDict.m_cEntries)
+ {
+ /* character entry */
+ pThis->auCompDictFreq[i] = 0;
+ pThis->aCompDict[i].cchString = 1;
+ }
+ else
+ {
+ /* word entry */
+ cb += SortedDict.m_apEntries[iDict]->m_cchGain;
+ pThis->auCompDictFreq[i] = SortedDict.m_apEntries[iDict]->m_cchGain;
+ pThis->aCompDict[i].cchString = SortedDict.m_apEntries[iDict]->m_cchString;
+ psz = SortedDict.m_apEntries[iDict]->m_szString;
+ cWords++;
+ iDict++;
+ }
+ pThis->aCompDict[i].pszString = (char *)malloc(pThis->aCompDict[i].cchString + 1);
+ if (pThis->aCompDict[i].pszString)
+ memcpy(pThis->aCompDict[i].pszString, psz, pThis->aCompDict[i].cchString + 1);
+ else
+ return false;
+ }
+
+ if (fVerbose)
+ printf("debug: Estimated string compression saving: %u bytes\n"
+ "debug: %u words, %u characters\n"
+ , (unsigned)cb, (unsigned)cWords, (unsigned)(RT_ELEMENTS(pThis->aCompDict) - cWords));
+
+ /*
+ * Rework the strings.
+ */
+ size_t cchOld = 0;
+ size_t cchOldMax = 0;
+ size_t cchOldMin = BLDPROG_STRTAB_MAX_STRLEN;
+ size_t cchNew = 0;
+ size_t cchNewMax = 0;
+ size_t cchNewMin = BLDPROG_STRTAB_MAX_STRLEN;
+ size_t i = pThis->cPendingStrings;
+ while (i-- > 0)
+ {
+ PBLDPROGSTRING pCurStr = pThis->papPendingStrings[i];
+ cchOld += pCurStr->cchString;
+ if (pCurStr->cchString > cchOldMax)
+ cchOldMax = pCurStr->cchString;
+ if (pCurStr->cchString < cchOldMin)
+ cchOldMin = pCurStr->cchString;
+
+ if (!bldProgStrTab_compressorFixupString(pThis, pCurStr))
+ return false;
+
+ cchNew += pCurStr->cchString;
+ if (pCurStr->cchString > cchNewMax)
+ cchNewMax = pCurStr->cchString;
+ if (pCurStr->cchString < cchNewMin)
+ cchNewMin = pCurStr->cchString;
+
+ bldProgStrTab_AddStringToHashTab(pThis, pCurStr);
+ }
+
+ /*
+ * Do debug stats.
+ */
+ if (fVerbose)
+ {
+ for (i = 0; i < RT_ELEMENTS(pThis->aCompDict); i++)
+ cchNew += pThis->aCompDict[i].cchString + 1;
+
+ printf("debug: Strings: original: %u bytes; compressed: %u bytes;", (unsigned)cchOld, (unsigned)cchNew);
+ if (cchNew < cchOld)
+ printf(" saving %u bytes (%u%%)\n", (unsigned)(cchOld - cchNew), (unsigned)((cchOld - cchNew) * 100 / cchOld));
+ else
+ printf(" wasting %u bytes!\n", (unsigned)(cchOld - cchNew));
+ printf("debug: Original string lengths: average %u; min %u; max %u\n",
+ (unsigned)(cchOld / pThis->cPendingStrings), (unsigned)cchOldMin, (unsigned)cchOldMax);
+ printf("debug: Compressed string lengths: average %u; min %u; max %u\n",
+ (unsigned)(cchNew / pThis->cPendingStrings), (unsigned)cchNewMin, (unsigned)cchNewMax);
+ }
+
+ return true;
+}
+
+#endif /* BLDPROG_STRTAB_WITH_COMPRESSION */
+
+/**
+ * Inserts a string into g_apUniqueStrings.
+ * @param pThis The strint table compiler instance.
+ * @param pStr The string.
+ */
+static void bldProgStrTab_InsertUniqueString(PBLDPROGSTRTAB pThis, PBLDPROGSTRING pStr)
+{
+ size_t iIdx;
+ size_t iEnd = pThis->cSortedStrings;
+ if (iEnd)
+ {
+ size_t iStart = 0;
+ for (;;)
+ {
+ iIdx = iStart + (iEnd - iStart) / 2;
+ if (pThis->papSortedStrings[iIdx]->cchString < pStr->cchString)
+ {
+ if (iIdx <= iStart)
+ break;
+ iEnd = iIdx;
+ }
+ else if (pThis->papSortedStrings[iIdx]->cchString > pStr->cchString)
+ {
+ if (++iIdx >= iEnd)
+ break;
+ iStart = iIdx;
+ }
+ else
+ break;
+ }
+
+ if (iIdx != pThis->cSortedStrings)
+ memmove(&pThis->papSortedStrings[iIdx + 1], &pThis->papSortedStrings[iIdx],
+ (pThis->cSortedStrings - iIdx) * sizeof(pThis->papSortedStrings[iIdx]));
+ }
+ else
+ iIdx = 0;
+
+ pThis->papSortedStrings[iIdx] = pStr;
+ pThis->cSortedStrings++;
+}
+
+
+/**
+ * Compiles the string table after the string has been added.
+ *
+ * This will save space by dropping string terminators, eliminating duplicates
+ * and try find strings that are sub-strings of others.
+ *
+ * Will initialize the StrRef of all StrTabString instances.
+ *
+ * @returns success indicator (error flagged).
+ * @param pThis The strint table compiler instance.
+ */
+static bool BldProgStrTab_CompileIt(PBLDPROGSTRTAB pThis, bool fVerbose)
+{
+#ifdef BLDPROG_STRTAB_WITH_COMPRESSION
+ /*
+ * Do the compression and add all the compressed strings to the table.
+ */
+ if (!bldProgStrTab_compressorDoStringCompression(pThis, fVerbose))
+ return false;
+
+ /*
+ * Add the dictionary strings.
+ */
+ for (unsigned i = 0; i < RT_ELEMENTS(pThis->aCompDict); i++)
+ if (pThis->aCompDict[i].cchString > 1)
+ bldProgStrTab_AddStringToHashTab(pThis, &pThis->aCompDict[i]);
+# ifdef RT_STRICT
+ else if (pThis->aCompDict[i].cchString != 1)
+ abort();
+# endif
+#endif
+ if (fVerbose)
+ printf("debug: %u unique strings (%u bytes), %u duplicates, %u collisions\n",
+ (unsigned)pThis->cUniqueStrings, (unsigned)pThis->cchUniqueStrings,
+ (unsigned)pThis->cDuplicateStrings, (unsigned)pThis->cCollisions);
+
+ /*
+ * Create papSortedStrings from the hash table. The table is sorted by
+ * string length, with the longer strings first, so that we increase our
+ * chances of locating duplicate substrings.
+ */
+ pThis->papSortedStrings = (PBLDPROGSTRING *)malloc(sizeof(pThis->papSortedStrings[0]) * pThis->cUniqueStrings);
+ if (!pThis->papSortedStrings)
+ return false;
+ pThis->cSortedStrings = 0;
+ size_t idxHash = pThis->cStrHash;
+ while (idxHash-- > 0)
+ {
+ PBLDPROGSTRING pCur = pThis->papStrHash[idxHash];
+ if (pCur)
+ {
+ do
+ {
+ bldProgStrTab_InsertUniqueString(pThis, pCur);
+ pCur = pCur->pNextCollision;
+ } while (pCur);
+ }
+ }
+
+ /*
+ * Create the actual string table.
+ */
+ pThis->pachStrTab = (char *)malloc(pThis->cchUniqueStrings + 1);
+ if (!pThis->pachStrTab)
+ return false;
+ pThis->cchStrTab = 0;
+ for (size_t i = 0; i < pThis->cSortedStrings; i++)
+ {
+ PBLDPROGSTRING pCur = pThis->papSortedStrings[i];
+ const char * const pszCur = pCur->pszString;
+ size_t const cchCur = pCur->cchString;
+ size_t offStrTab = pThis->cchStrTab;
+
+ /*
+ * See if the string is a substring already found in the string table.
+ * Excluding the zero terminator increases the chances for this.
+ */
+ size_t cchLeft = pThis->cchStrTab >= cchCur ? pThis->cchStrTab - cchCur : 0;
+ const char *pchLeft = pThis->pachStrTab;
+ char const chFirst = *pszCur;
+ while (cchLeft > 0)
+ {
+ const char *pchCandidate = (const char *)memchr(pchLeft, chFirst, cchLeft);
+ if (!pchCandidate)
+ break;
+ if (memcmp(pchCandidate, pszCur, cchCur) == 0)
+ {
+ offStrTab = pchCandidate - pThis->pachStrTab;
+ break;
+ }
+
+ cchLeft -= pchCandidate + 1 - pchLeft;
+ pchLeft = pchCandidate + 1;
+ }
+
+ if (offStrTab == pThis->cchStrTab)
+ {
+ /*
+ * See if the start of the string overlaps the end of the string table.
+ */
+ if (pThis->cchStrTab && cchCur > 1)
+ {
+ cchLeft = RT_MIN(pThis->cchStrTab, cchCur - 1);
+ pchLeft = &pThis->pachStrTab[pThis->cchStrTab - cchLeft];
+ while (cchLeft > 0)
+ {
+ const char *pchCandidate = (const char *)memchr(pchLeft, chFirst, cchLeft);
+ if (!pchCandidate)
+ break;
+ cchLeft -= pchCandidate - pchLeft;
+ pchLeft = pchCandidate;
+ if (memcmp(pchLeft, pszCur, cchLeft) == 0)
+ {
+ size_t cchToCopy = cchCur - cchLeft;
+ memcpy(&pThis->pachStrTab[offStrTab], &pszCur[cchLeft], cchToCopy);
+ pThis->cchStrTab += cchToCopy;
+ offStrTab = pchCandidate - pThis->pachStrTab;
+ break;
+ }
+ cchLeft--;
+ pchLeft++;
+ }
+ }
+
+ /*
+ * If we didn't have any luck above, just append the string.
+ */
+ if (offStrTab == pThis->cchStrTab)
+ {
+ memcpy(&pThis->pachStrTab[offStrTab], pszCur, cchCur);
+ pThis->cchStrTab += cchCur;
+ }
+ }
+
+ /*
+ * Set the string table offset for all the references to this string.
+ */
+ do
+ {
+ pCur->offStrTab = (uint32_t)offStrTab;
+ pCur = pCur->pNextRef;
+ } while (pCur != NULL);
+ }
+
+ if (fVerbose)
+ printf("debug: String table: %u bytes\n", (unsigned)pThis->cchStrTab);
+ return true;
+}
+
+
+#ifdef RT_STRICT
+/**
+ * Sanity checks a string table string.
+ * @param pThis The strint table compiler instance.
+ * @param pStr The string to check.
+ */
+static void BldProgStrTab_CheckStrTabString(PBLDPROGSTRTAB pThis, PBLDPROGSTRING pStr)
+{
+ if (pStr->cchString != strlen(pStr->pszString))
+ abort();
+ if (pStr->offStrTab >= pThis->cchStrTab)
+ abort();
+ if (pStr->offStrTab + pStr->cchString > pThis->cchStrTab)
+ abort();
+ if (memcmp(pStr->pszString, &pThis->pachStrTab[pStr->offStrTab], pStr->cchString) != 0)
+ abort();
+}
+#endif
+
+
+/**
+ * Output the string table string in C string litteral fashion.
+ *
+ * @param pThis The strint table instance.
+ * @param pString The string to print.
+ * @param pOut The output stream.
+ */
+static void BldProgStrTab_PrintCStringLitteral(PBLDPROGSTRTAB pThis, PBLDPROGSTRING pString, FILE *pOut)
+{
+ const unsigned char *psz = (const unsigned char *)pString->pszString;
+ unsigned char uch;
+ while ((uch = *psz++) != '\0')
+ {
+#ifdef BLDPROG_STRTAB_WITH_COMPRESSION
+ if (pThis->aCompDict[uch].cchString == 1)
+#else
+ if (!(uch & 0x80))
+#endif
+ {
+ if (uch != '\'' && uch != '\\')
+ fputc((char)uch, pOut);
+ else
+ {
+ fputc('\\', pOut);
+ fputc((char)uch, pOut);
+ }
+ }
+#ifdef BLDPROG_STRTAB_WITH_COMPRESSION
+# ifndef BLDPROG_STRTAB_PURE_ASCII
+ else if (uch == 0xff)
+ {
+ RTUNICP uc = RTStrGetCp((const char *)psz);
+ psz += RTStrCpSize(uc);
+ fprintf(pOut, "\\u%04x", uc);
+ }
+# else
+ else
+ fputs(pThis->aCompDict[uch].pszString, pOut);
+# endif
+#else
+ else
+ fprintf(pOut, "\\x%02x", (unsigned)uch);
+ NOREF(pThis);
+#endif
+ }
+}
+
+
+/**
+ * Writes the string table code to the output stream.
+ *
+ * @param pThis The strint table compiler instance.
+ * @param pOut The output stream.
+ * @param pszScope The scoping ("static " or empty string),
+ * including trailing space.
+ * @param pszPrefix The variable prefix. Typically "g_" for C programs,
+ * whereas C++ classes normally use "class::s_g".
+ * @param pszBaseName The base name for the variables. The user
+ * accessible variable will end up as just the
+ * prefix and basename concatenated.
+ */
+static void BldProgStrTab_WriteStringTable(PBLDPROGSTRTAB pThis, FILE *pOut,
+ const char *pszScope, const char *pszPrefix, const char *pszBaseName)
+{
+#ifdef RT_STRICT
+ /*
+ * Do some quick sanity checks while we're here.
+ */
+# ifdef BLDPROG_STRTAB_WITH_COMPRESSION
+ for (unsigned i = 0; i < RT_ELEMENTS(pThis->aCompDict); i++)
+ {
+ if (BldProgBitIsSet(pThis->bmUsedChars, i)
+ ? pThis->aCompDict[i].cchString != 1 : pThis->aCompDict[i].cchString < 1)
+ abort();
+ if (pThis->aCompDict[i].cchString > 1)
+ BldProgStrTab_CheckStrTabString(pThis, &pThis->aCompDict[i]);
+ }
+# endif
+#endif
+
+ /*
+ * Create a table for speeding up the character categorization.
+ */
+ uint8_t abCharCat[256];
+ memset(abCharCat, 0, sizeof(abCharCat));
+ abCharCat[(unsigned char)'\\'] = 1;
+ abCharCat[(unsigned char)'\''] = 1;
+ for (unsigned i = 0; i < 0x20; i++)
+ abCharCat[i] = 2;
+ for (unsigned i = 0x7f; i < 0x100; i++)
+ abCharCat[i] = 2;
+#ifdef BLDPROG_STRTAB_WITH_COMPRESSION
+ for (unsigned i = 0; i < 0x100; i++)
+ if (!BldProgBitIsSet(pThis->bmUsedChars, i)) /* Encode table references using '\xYY'. */
+ abCharCat[i] = 2;
+#endif
+
+ /*
+ * We follow the sorted string table, one string per line.
+ */
+ fprintf(pOut,
+ "#include <iprt/bldprog-strtab.h>\n"
+ "\n"
+ "static const char g_achStrTab%s[] =\n"
+ "{\n",
+ pszBaseName);
+
+ uint32_t off = 0;
+ for (uint32_t i = 0; i < pThis->cSortedStrings; i++)
+ {
+ PBLDPROGSTRING pCur = pThis->papSortedStrings[i];
+ uint32_t offEnd = pCur->offStrTab + (uint32_t)pCur->cchString;
+ if (offEnd > off)
+ {
+ /* Comment with an uncompressed and more readable version of the string. */
+ if (off == pCur->offStrTab)
+ fprintf(pOut, "/* 0x%05x = \"", off);
+ else
+ fprintf(pOut, "/* 0X%05x = \"", off);
+ BldProgStrTab_PrintCStringLitteral(pThis, pCur, pOut);
+ fputs("\" */\n", pOut);
+
+ /* Must use char by char here or we may trigger the max string
+ length limit in the compiler, */
+ fputs(" ", pOut);
+ for (; off < offEnd; off++)
+ {
+ unsigned char uch = pThis->pachStrTab[off];
+ fputc('\'', pOut);
+ if (abCharCat[uch] == 0)
+ fputc(uch, pOut);
+ else if (abCharCat[uch] != 1)
+ fprintf(pOut, "\\x%02x", (unsigned)uch);
+ else
+ {
+ fputc('\\', pOut);
+ fputc(uch, pOut);
+ }
+ fputc('\'', pOut);
+ fputc(',', pOut);
+ }
+ fputc('\n', pOut);
+ }
+ }
+
+ fprintf(pOut,
+ "};\n"
+ "AssertCompile(sizeof(g_achStrTab%s) == %#x);\n\n",
+ pszBaseName, (unsigned)pThis->cchStrTab);
+
+#ifdef BLDPROG_STRTAB_WITH_COMPRESSION
+ /*
+ * Write the compression dictionary.
+ */
+ fprintf(pOut,
+ "static const RTBLDPROGSTRREF g_aCompDict%s[%u] = \n"
+ "{\n",
+ pszBaseName, (unsigned)RT_ELEMENTS(pThis->aCompDict));
+ for (unsigned i = 0; i < RT_ELEMENTS(pThis->aCompDict); i++)
+ if (pThis->aCompDict[i].cchString > 1)
+ fprintf(pOut, " /*[%3u]=*/ { %#08x, %#04x }, // %6lu - %s\n", i,
+ pThis->aCompDict[i].offStrTab, (unsigned)pThis->aCompDict[i].cchString,
+ (unsigned long)pThis->auCompDictFreq[i], pThis->aCompDict[i].pszString);
+# ifndef BLDPROG_STRTAB_PURE_ASCII
+ else if (i == 0xff)
+ fprintf(pOut, " /*[%3u]=*/ { 0x000000, 0x00 }, // UTF-8 escape\n", i);
+# endif
+ else if (i == 0)
+ fprintf(pOut, " /*[%3u]=*/ { 0x000000, 0x00 }, // unused, because zero terminator\n", i);
+ else if (i < 0x20)
+ fprintf(pOut, " /*[%3u]=*/ { 0x000000, 0x00 }, // %02x\n", i, i);
+ else
+ fprintf(pOut, " /*[%3u]=*/ { 0x000000, 0x00 }, // '%c'\n", i, (char)i);
+ fprintf(pOut, "};\n\n");
+#endif
+
+
+ /*
+ * Write the string table data structure.
+ */
+ fprintf(pOut,
+ "%sconst RTBLDPROGSTRTAB %s%s = \n"
+ "{\n"
+ " /*.pchStrTab = */ &g_achStrTab%s[0],\n"
+ " /*.cchStrTab = */ sizeof(g_achStrTab%s),\n"
+ ,
+ pszScope, pszPrefix, pszBaseName, pszBaseName, pszBaseName);
+#ifdef BLDPROG_STRTAB_WITH_COMPRESSION
+ fprintf(pOut,
+ " /*.cCompDict = */ %u,\n"
+ " /*.paCompDict = */ &g_aCompDict%s[0]\n"
+ "};\n"
+# ifndef BLDPROG_STRTAB_PURE_ASCII /* 255 or 256 entries is how the decoder knows */
+ , (unsigned)RT_ELEMENTS(pThis->aCompDict) - 1,
+# else
+ , (unsigned)RT_ELEMENTS(pThis->aCompDict),
+# endif
+ pszBaseName);
+#else
+ fprintf(pOut,
+ " /*.cCompDict = */ 0,\n"
+ " /*.paCompDict = */ NULL\n"
+ "};\n");
+#endif
+}
+
+#if RT_CLANG_PREREQ(4, 0) || RT_GNUC_PREREQ(4, 6)
+# pragma GCC diagnostic pop
+#endif
+
+#endif /* __cplusplus && IN_RING3 */
+
diff --git a/include/iprt/bldprog-strtab.h b/include/iprt/bldprog-strtab.h
new file mode 100644
index 00000000..9a40d24a
--- /dev/null
+++ b/include/iprt/bldprog-strtab.h
@@ -0,0 +1,259 @@
+/** @file
+ * IPRT - Build Program - String Table Generator, Accessors.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_bldprog_strtab_h
+#define IPRT_INCLUDED_bldprog_strtab_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/assert.h>
+#include <iprt/err.h>
+#include <iprt/string.h>
+
+
+/**
+ * The default build program string table reference.
+ */
+typedef struct RTBLDPROGSTRREF
+{
+ /** Offset of the string in the string table. */
+ uint32_t off : 22;
+ /** The length of the string. */
+ uint32_t cch : 10;
+} RTBLDPROGSTRREF;
+AssertCompileSize(RTBLDPROGSTRREF, sizeof(uint32_t));
+/** Pointer to a build program string table reference. */
+typedef RTBLDPROGSTRREF const *PCRTBLDPROGSTRREF;
+
+
+typedef struct RTBLDPROGSTRTAB
+{
+ const char *pchStrTab;
+ uint32_t cchStrTab;
+ uint32_t cCompDict;
+ PCRTBLDPROGSTRREF paCompDict;
+} RTBLDPROGSTRTAB;
+typedef const RTBLDPROGSTRTAB *PCRTBLDPROGSTRTAB;
+
+
+/**
+ * Tries to ensure the buffer is terminated when failing.
+ */
+DECLINLINE(ssize_t) RTBldProgStrTabQueryStringFail(int rc, char *pszDstStart, char *pszDst, size_t cbDst)
+{
+ if (cbDst)
+ *pszDst = '\0';
+ else if (pszDstStart != pszDst)
+ pszDst[-1] = '\0';
+ return rc;
+}
+
+
+/**
+ * Retrieves the decompressed string.
+ *
+ * @returns The string size on success, IPRT status code on failure.
+ * @param pStrTab The string table.
+ * @param offString The offset of the string.
+ * @param cchString The length of the string.
+ * @param pszDst The return buffer.
+ * @param cbDst The size of the return buffer.
+ */
+DECLINLINE(ssize_t) RTBldProgStrTabQueryString(PCRTBLDPROGSTRTAB pStrTab, uint32_t offString, size_t cchString,
+ char *pszDst, size_t cbDst)
+{
+ AssertReturn(offString < pStrTab->cchStrTab, VERR_OUT_OF_RANGE);
+ AssertReturn(offString + cchString <= pStrTab->cchStrTab, VERR_OUT_OF_RANGE);
+
+ if (pStrTab->cCompDict)
+ {
+ Assert(pStrTab->cCompDict == 256 || pStrTab->cCompDict == 255);
+
+ /*
+ * Is compressed, decompress it.
+ */
+ char * const pchDstStart = pszDst;
+ const char *pchSrc = &pStrTab->pchStrTab[offString];
+ while (cchString-- > 0)
+ {
+ unsigned char uch = *(unsigned char *)pchSrc++;
+ if (uch != 0xff || pStrTab->cCompDict > 0xff)
+ {
+ /*
+ * Look it up in the dictionary, either a single 7-bit character or a word.
+ * Either way, no UTF-8 unescaping necessary.
+ */
+ PCRTBLDPROGSTRREF pWord = &pStrTab->paCompDict[uch];
+ size_t const cchWord = pWord->cch;
+ if (cchWord <= 1)
+ {
+ Assert(uch != 0);
+ Assert(uch <= 127);
+ AssertReturn(cbDst > 1, RTBldProgStrTabQueryStringFail(VERR_BUFFER_OVERFLOW, pchDstStart, pszDst, cbDst));
+ cbDst -= 1;
+ *pszDst++ = (char)uch;
+ }
+ else
+ {
+ Assert(cchWord > 1);
+ AssertReturn((size_t)pWord->off + cchWord <= pStrTab->cchStrTab,
+ RTBldProgStrTabQueryStringFail(VERR_INVALID_PARAMETER, pchDstStart, pszDst, cbDst));
+ AssertReturn(cbDst > cchWord,
+ RTBldProgStrTabQueryStringFail(VERR_BUFFER_OVERFLOW, pchDstStart, pszDst, cbDst));
+ memcpy(pszDst, &pStrTab->pchStrTab[pWord->off], cchWord);
+ pszDst += cchWord;
+ cbDst -= cchWord;
+ }
+ }
+ else
+ {
+ /*
+ * UTF-8 encoded unicode codepoint.
+ */
+ size_t cchCp;
+ RTUNICP uc = ' ';
+ int rc = RTStrGetCpNEx(&pchSrc, &cchString, &uc);
+ AssertStmt(RT_SUCCESS(rc), (uc = '?', pchSrc++, cchString--));
+
+ cchCp = RTStrCpSize(uc);
+ AssertReturn(cbDst > cchCp,
+ RTBldProgStrTabQueryStringFail(VERR_BUFFER_OVERFLOW, pchDstStart, pszDst, cbDst));
+
+ RTStrPutCp(pszDst, uc);
+ pszDst += cchCp;
+ cbDst -= cchCp;
+ }
+ }
+ AssertReturn(cbDst > 0, RTBldProgStrTabQueryStringFail(VERR_BUFFER_OVERFLOW, pchDstStart, pszDst, cbDst));
+ *pszDst = '\0';
+ return pszDst - pchDstStart;
+ }
+
+ /*
+ * Not compressed.
+ */
+ if (cbDst > cchString)
+ {
+ memcpy(pszDst, &pStrTab->pchStrTab[offString], cchString);
+ pszDst[cchString] = '\0';
+ return (ssize_t)cchString;
+ }
+ if (cbDst > 0)
+ {
+ memcpy(pszDst, &pStrTab->pchStrTab[offString], cbDst - 1);
+ pszDst[cbDst - 1] = '\0';
+ }
+ return VERR_BUFFER_OVERFLOW;
+}
+
+
+/**
+ * Outputs the decompressed string.
+ *
+ * @returns The sum of the pfnOutput return values.
+ * @param pStrTab The string table.
+ * @param offString The offset of the string.
+ * @param cchString The length of the string.
+ * @param pfnOutput The output function.
+ * @param pvArgOutput The argument to pass to the output function.
+ *
+ */
+DECLINLINE(size_t) RTBldProgStrTabQueryOutput(PCRTBLDPROGSTRTAB pStrTab, uint32_t offString, size_t cchString,
+ PFNRTSTROUTPUT pfnOutput, void *pvArgOutput)
+{
+ AssertReturn(offString < pStrTab->cchStrTab, 0);
+ AssertReturn(offString + cchString <= pStrTab->cchStrTab, 0);
+
+ if (pStrTab->cCompDict)
+ {
+ Assert(pStrTab->cCompDict == 256 || pStrTab->cCompDict == 255);
+
+ /*
+ * Could be compressed, decompress it.
+ */
+ size_t cchRet = 0;
+ const char *pchSrc = &pStrTab->pchStrTab[offString];
+ while (cchString-- > 0)
+ {
+ unsigned char uch = *(unsigned char *)pchSrc++;
+ if (uch != 0xff || pStrTab->cCompDict > 0xff)
+ {
+ /*
+ * Look it up in the dictionary, either a single 7-bit character or a word.
+ * Either way, no UTF-8 unescaping necessary.
+ */
+ PCRTBLDPROGSTRREF pWord = &pStrTab->paCompDict[uch];
+ size_t const cchWord = pWord->cch;
+ if (cchWord <= 1)
+ {
+ Assert(uch != 0);
+ Assert(uch <= 127);
+ cchRet += pfnOutput(pvArgOutput, (const char *)&uch, 1);
+ }
+ else
+ {
+ Assert(cchWord > 1);
+ AssertReturn((size_t)pWord->off + cchWord <= pStrTab->cchStrTab, cchRet);
+
+ cchRet += pfnOutput(pvArgOutput, &pStrTab->pchStrTab[pWord->off], cchWord);
+ }
+ }
+ else
+ {
+ /*
+ * UTF-8 encoded unicode codepoint.
+ */
+ const char * const pchUtf8Seq = pchSrc;
+ RTUNICP uc = ' ';
+ int rc = RTStrGetCpNEx(&pchSrc, &cchString, &uc);
+ if (RT_SUCCESS(rc))
+ cchRet += pfnOutput(pvArgOutput, pchUtf8Seq, (size_t)(pchSrc - pchUtf8Seq));
+ else
+ cchRet += pfnOutput(pvArgOutput, "?", 1);
+ }
+ }
+ return cchRet;
+ }
+
+ /*
+ * Not compressed.
+ */
+ return pfnOutput(pvArgOutput, &pStrTab->pchStrTab[offString], cchString);
+}
+
+
+#endif /* !IPRT_INCLUDED_bldprog_strtab_h */
+
diff --git a/include/iprt/buildconfig.h b/include/iprt/buildconfig.h
new file mode 100644
index 00000000..b5292d0c
--- /dev/null
+++ b/include/iprt/buildconfig.h
@@ -0,0 +1,138 @@
+/** @file
+ * IPRT - Build Configuration Information
+ */
+
+/*
+ * Copyright (C) 2009-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_buildconfig_h
+#define IPRT_INCLUDED_buildconfig_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_buildconfig RTBldCfg - Build Configuration Information
+ * @ingroup grp_rt
+ * @{
+ */
+
+/**
+ * Gets the source code management revision of the IPRT build.
+ * @returns Source code management revision number.
+ */
+RTDECL(uint32_t) RTBldCfgRevision(void);
+
+/**
+ * Gets the source code management revision of the IPRT build.
+ * @returns Read only string containing the revision number.
+ */
+RTDECL(const char *) RTBldCfgRevisionStr(void);
+
+/**
+ * Gets the product version string.
+ *
+ * This will be a string on the form "x.y.z[_string]".
+ *
+ * @returns Read only version string.
+ *
+ * @remarks This is a build time configuration thing that the product using IPRT
+ * will set. It is therefore not any IPRT version, but rather the
+ * version of that product.
+ */
+RTDECL(const char *) RTBldCfgVersion(void);
+
+/**
+ * Gets the major product version number.
+ * @returns Major product version number.
+ * @remarks See RTBldCfgVersion.
+ */
+RTDECL(uint32_t) RTBldCfgVersionMajor(void);
+
+/**
+ * Gets the minor product version number.
+ * @returns Minor product version number.
+ * @remarks See RTBldCfgVersion.
+ */
+RTDECL(uint32_t) RTBldCfgVersionMinor(void);
+
+/**
+ * Gets the product build number.
+ * @returns Product build number.
+ * @remarks See RTBldCfgVersion.
+ */
+RTDECL(uint32_t) RTBldCfgVersionBuild(void);
+
+/**
+ * Gets the build target name.
+ *
+ * @returns Read only build target string.
+ */
+RTDECL(const char *) RTBldCfgTarget(void);
+
+/**
+ * Gets the build target architecture name.
+ *
+ * @returns Read only build target architecture string.
+ */
+RTDECL(const char *) RTBldCfgTargetArch(void);
+
+/**
+ * Gets the build target-dot-architecture name.
+ *
+ * @returns Read only build target-dot-architecture string.
+ */
+RTDECL(const char *) RTBldCfgTargetDotArch(void);
+
+/**
+ * Gets the build type name.
+ *
+ * @returns Read only build type string.
+ */
+RTDECL(const char *) RTBldCfgType(void);
+
+/**
+ * Gets the name of the compiler used for building IPRT.
+ *
+ * @returns Read only compiler name.
+ */
+RTDECL(const char *) RTBldCfgCompiler(void);
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_buildconfig_h */
+
diff --git a/include/iprt/cdefs.h b/include/iprt/cdefs.h
new file mode 100644
index 00000000..8fe26f69
--- /dev/null
+++ b/include/iprt/cdefs.h
@@ -0,0 +1,4901 @@
+/** @file
+ * IPRT - Common C and C++ definitions.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_cdefs_h
+#define IPRT_INCLUDED_cdefs_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+
+/** @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 RT_ARCH_ARM32
+# define RT_ARCH_ARM64
+# define IN_RING0
+# define IN_RING3
+# 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_COMPILER_WITH_128BIT_LONG_DOUBLE
+# define RT_COMPILER_WITH_128BIT_INT_TYPES
+# 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).
+ */
+
+/** @def RT_ARCH_ARM32
+ * Indicates that we're compiling for the 32-bit ARM architecture, the value
+ * is the version (i.e. 6 for ARMv6).
+ */
+
+/** @def RT_ARCH_ARM64
+ * Indicates that we're compiling for the 64-bit ARM architecture.
+ */
+
+#if !defined(RT_ARCH_X86) \
+ && !defined(RT_ARCH_AMD64) \
+ && !defined(RT_ARCH_SPARC) \
+ && !defined(RT_ARCH_SPARC64) \
+ && !defined(RT_ARCH_ARM32) \
+ && !defined(RT_ARCH_ARM64)
+# 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(__arm64__) || defined(__aarch64__)
+# define RT_ARCH_ARM64 __ARM_ARCH
+# elif defined(__arm__)
+# define RT_ARCH_ARM32 __ARM_ARCH
+# elif defined(__arm32__)
+# define RT_ARCH_ARM32 __ARM_ARCH
+# 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_ARM32) && defined(RT_ARCH_AMD64)
+# error "Both RT_ARCH_ARM32 and RT_ARCH_AMD64 cannot be defined at the same time!"
+#elif defined(RT_ARCH_ARM32) && defined(RT_ARCH_X86)
+# error "Both RT_ARCH_ARM32 and RT_ARCH_X86 cannot be defined at the same time!"
+#elif defined(RT_ARCH_ARM32) && defined(RT_ARCH_SPARC64)
+# error "Both RT_ARCH_ARM32 and RT_ARCH_SPARC64 cannot be defined at the same time!"
+#elif defined(RT_ARCH_ARM32) && defined(RT_ARCH_SPARC)
+# error "Both RT_ARCH_ARM32 and RT_ARCH_SPARC cannot be defined at the same time!"
+#elif defined(RT_ARCH_ARM64) && defined(RT_ARCH_AMD64)
+# error "Both RT_ARCH_ARM64 and RT_ARCH_AMD64 cannot be defined at the same time!"
+#elif defined(RT_ARCH_ARM64) && defined(RT_ARCH_X86)
+# error "Both RT_ARCH_ARM64 and RT_ARCH_X86 cannot be defined at the same time!"
+#elif defined(RT_ARCH_ARM64) && defined(RT_ARCH_SPARC64)
+# error "Both RT_ARCH_ARM64 and RT_ARCH_SPARC64 cannot be defined at the same time!"
+#elif defined(RT_ARCH_ARM64) && defined(RT_ARCH_SPARC)
+# error "Both RT_ARCH_ARM64 and RT_ARCH_SPARC cannot be defined at the same time!"
+#elif defined(RT_ARCH_ARM64) && defined(RT_ARCH_ARM32)
+# error "Both RT_ARCH_ARM64 and RT_ARCH_ARM32 cannot be defined at the same time!"
+#endif
+#ifdef RT_ARCH_ARM
+# error "RT_ARCH_ARM is now RT_ARCH_ARM32!"
+#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_ARM32) != 0) \
+ + (defined(RT_ARCH_ARM64) != 0) \
+ != 1
+# error "Exactly one RT_ARCH_XXX macro shall be defined"
+#endif
+
+/** @def RT_CPLUSPLUS_PREREQ
+ * Require a minimum __cplusplus value, simplifying dealing with non-C++ code.
+ *
+ * @param a_Min The minimum version, e.g. 201100.
+ */
+#ifdef __cplusplus
+# define RT_CPLUSPLUS_PREREQ(a_Min) (__cplusplus >= (a_Min))
+#else
+# define RT_CPLUSPLUS_PREREQ(a_Min) (0)
+#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. */
+#define RT_MSC_VER_VS2017 (1910) /**< Visual Studio 2017. */
+#define RT_MSC_VER_VC141 RT_MSC_VER_VS2017 /**< Visual C++ 14.1, aka Visual Studio 2017. */
+#define RT_MSC_VER_VS2019 (1920) /**< Visual Studio 2019. */
+#define RT_MSC_VER_VC142 RT_MSC_VER_VS2019 /**< Visual C++ 14.2, aka Visual Studio 2019. */
+#define RT_MSC_VER_VS2019_U6 (1926) /**< Visual Studio 2019, update 6. */
+#define RT_MSC_VER_VC142_U6 RT_MSC_VER_VS2019_U6 /**< Visual C++ 14.2 update 6. */
+#define RT_MSC_VER_VS2019_U8 (1928) /**< Visual Studio 2019, update 8. */
+#define RT_MSC_VER_VC142_U8 RT_MSC_VER_VS2019_U8 /**< Visual C++ 14.2 update 8. */
+#define RT_MSC_VER_VS2019_U11 (1929) /**< Visual Studio 2019, update 11. */
+#define RT_MSC_VER_VC142_U11 RT_MSC_VER_VS2019_U11 /**< Visual C++ 14.2 update 11. */
+/** @} */
+
+/** @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 RT_CLANG_HAS_FEATURE
+ * Wrapper around clang's __has_feature().
+ *
+ * @param a_Feature The feature to check for.
+ */
+#if defined(__clang_major__) && defined(__clang_minor__) && defined(__has_feature)
+# define RT_CLANG_HAS_FEATURE(a_Feature) (__has_feature(a_Feature))
+#else
+# define RT_CLANG_HAS_FEATURE(a_Feature) (0)
+#endif
+
+
+#if !defined(__X86__) && !defined(__AMD64__) && (defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86))
+# if defined(RT_ARCH_AMD64)
+/** Indicates that we're compiling for the AMD64 architecture.
+ * @deprecated
+ */
+# define __AMD64__
+# elif defined(RT_ARCH_X86)
+/** Indicates that we're compiling for the X86 architecture.
+ * @deprecated
+ */
+# 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_ARM32) || defined(RT_ARCH_ARM64)
+# 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)
+# 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) || defined(RT_ARCH_ARM64) || defined(DOXYGEN_RUNNING)
+# 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_ARM32)
+ # error "ARCH_BITS=64 but non-64-bit RT_ARCH_XXX defined."
+ #endif
+ #if !defined(RT_ARCH_AMD64) && !defined(RT_ARCH_SPARC64) && !defined(RT_ARCH_ARM64)
+ # 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) || defined(RT_ARCH_ARM64)
+ # 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_ARM32)
+ # 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_ARM32) || defined(RT_ARCH_ARM64)
+ # 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)
+# if !defined(IN_RC) || defined(DOXYGEN_RUNNING)
+# 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)
+# if defined(VBOX_WITH_64_BITS_GUESTS) || defined(DOXYGEN_RUNNING)
+# 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
+
+
+
+/** @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 a_GCType The GC type.
+ * @param a_R3Type The R3 type.
+ * @param a_R0Type The R0 type.
+ * @remark For pointers used only in one context use RCPTRTYPE(), R3R0PTRTYPE(), R3PTRTYPE() or R0PTRTYPE().
+ */
+#if defined(IN_RC) && !defined(DOXYGEN_RUNNING)
+# define CTXTYPE(a_GCType, a_R3Type, a_R0Type) a_GCType
+#elif defined(IN_RING3) || defined(DOXYGEN_RUNNING)
+# define CTXTYPE(a_GCType, a_R3Type, a_R0Type) a_R3Type
+#else
+# define CTXTYPE(a_GCType, a_R3Type, a_R0Type) a_R0Type
+#endif
+
+/** @def CTX_EXPR
+ * Expression selector for avoiding \#ifdef's.
+ *
+ * @param a_R3Expr The R3 expression.
+ * @param a_R0Expr The R0 expression.
+ * @param a_RCExpr The RC expression.
+ */
+#if defined(IN_RC) && !defined(DOXYGEN_RUNNING)
+# define CTX_EXPR(a_R3Expr, a_R0Expr, a_RCExpr) a_RCExpr
+#elif defined(IN_RING0) && !defined(DOXYGEN_RUNNING)
+# define CTX_EXPR(a_R3Expr, a_R0Expr, a_RCExpr) a_R0Expr
+#else
+# define CTX_EXPR(a_R3Expr, a_R0Expr, a_RCExpr) a_R3Expr
+#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 a_RCType The RC type.
+ */
+#define RCPTRTYPE(a_RCType) CTXTYPE(a_RCType, RTRCPTR, RTRCPTR)
+
+/** @def RGPTRTYPE
+ * This will become RCPTRTYPE once we've converted all uses of RCPTRTYPE to this.
+ *
+ * @param a_RCType The RC type.
+ */
+#define RGPTRTYPE(a_RCType) CTXTYPE(a_RCType, RTGCPTR, RTGCPTR)
+
+/** @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 a_R3R0Type The R3R0 type.
+ * @remarks This used to be called HCPTRTYPE.
+ */
+#define R3R0PTRTYPE(a_R3R0Type) CTXTYPE(RTHCPTR, a_R3R0Type, a_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 a_R3Type The R3 type.
+ */
+#define R3PTRTYPE(a_R3Type) CTXTYPE(RTHCUINTPTR, a_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 a_R0Type The R0 type.
+ */
+#define R0PTRTYPE(a_R0Type) CTXTYPE(RTHCUINTPTR, RTHCUINTPTR, a_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 a_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 a_Var Identifier name.
+ * @deprecated Use CTX_SUFF. Do NOT use this for new code.
+ */
+#if defined(IN_RC) && !defined(DOXYGEN_RUNNING)
+# define CTXSUFF(a_Var) a_Var##GC
+# define OTHERCTXSUFF(a_Var) a_Var##HC
+#else
+# define CTXSUFF(a_Var) a_Var##HC
+# define OTHERCTXSUFF(a_Var) a_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 a_Var Identifier name.
+ * @deprecated Use CTX_SUFF. Do NOT use this for new code.
+ */
+#if defined(IN_RC) && !defined(DOXYGEN_RUNNING)
+# define CTXALLSUFF(a_Var) a_Var##GC
+#elif defined(IN_RING0) && !defined(DOXYGEN_RUNNING)
+# define CTXALLSUFF(a_Var) a_Var##R0
+#else
+# define CTXALLSUFF(a_Var) a_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 a_Var Identifier name.
+ *
+ * @remark This will replace CTXALLSUFF and CTXSUFF before long.
+ */
+#if defined(IN_RC) && !defined(DOXYGEN_RUNNING)
+# define CTX_SUFF(a_Var) a_Var##RC
+#elif defined(IN_RING0) && !defined(DOXYGEN_RUNNING)
+# define CTX_SUFF(a_Var) a_Var##R0
+#else
+# define CTX_SUFF(a_Var) a_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 a_Var Identifier name.
+ *
+ * @remark This will replace CTXALLSUFF and CTXSUFF before long.
+ */
+#if defined(IN_RING3) || defined(DOXYGEN_RUNNING)
+# define CTX_SUFF_Z(a_Var) a_Var##R3
+#else
+# define CTX_SUFF_Z(a_Var) a_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 a_First First name.
+ * @param a_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 a_First First name.
+ * @param a_Last Surname.
+ * @deprecated use CTX_MID or CTX_MID_Z
+ */
+#if defined(IN_RC) && !defined(DOXYGEN_RUNNING)
+# define CTXMID(a_First, a_Last) a_First##GC##a_Last
+# define OTHERCTXMID(a_First, a_Last) a_First##HC##a_Last
+#else
+# define CTXMID(a_First, a_Last) a_First##HC##a_Last
+# define OTHERCTXMID(a_First, a_Last) a_First##GC##a_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 a_First First name.
+ * @param a_Last Surname.
+ * @deprecated use CTX_MID or CTX_MID_Z
+ */
+#if defined(IN_RC) && !defined(DOXYGEN_RUNNING)
+# define CTXALLMID(a_First, a_Last) a_First##GC##a_Last
+#elif defined(IN_RING0) && !defined(DOXYGEN_RUNNING)
+# define CTXALLMID(a_First, a_Last) a_First##R0##a_Last
+#else
+# define CTXALLMID(a_First, a_Last) a_First##R3##a_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 a_First First name.
+ * @param a_Last Surname.
+ */
+#if defined(IN_RC) && !defined(DOXYGEN_RUNNING)
+# define CTX_MID(a_First, a_Last) a_First##RC##a_Last
+#elif defined(IN_RING0) && !defined(DOXYGEN_RUNNING)
+# define CTX_MID(a_First, a_Last) a_First##R0##a_Last
+#else
+# define CTX_MID(a_First, a_Last) a_First##R3##a_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 a_First First name.
+ * @param a_Last Surname.
+ */
+#ifdef IN_RING3
+# define CTX_MID_Z(a_First, a_Last) a_First##R3##a_Last
+#else
+# define CTX_MID_Z(a_First, a_Last) a_First##RZ##a_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 a_pR3String The R3 string. Only referenced in R3.
+ * @see R0STRING and GCSTRING
+ */
+#ifdef IN_RING3
+# define R3STRING(a_pR3String) (a_pR3String)
+#else
+# define R3STRING(a_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 a_pR0String The R0 string. Only referenced in R0.
+ * @see R3STRING and GCSTRING
+ */
+#ifdef IN_RING0
+# define R0STRING(a_pR0String) (a_pR0String)
+#else
+# define R0STRING(a_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 a_pRCString The RC string. Only referenced in RC.
+ * @see R3STRING, R0STRING
+ */
+#ifdef IN_RC
+# define RCSTRING(a_pRCString) (a_pRCString)
+#else
+# define RCSTRING(a_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 and Clang should not warn about
+ * deprecated declarations. */
+/** @def RT_GCC_NO_WARN_DEPRECATED_END
+ * Used to end a block of code where GCC and Clang should not warn about
+ * deprecated declarations. */
+#if RT_CLANG_PREREQ(4, 0)
+# define RT_GCC_NO_WARN_DEPRECATED_BEGIN \
+ _Pragma("clang diagnostic push") \
+ _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
+# define RT_GCC_NO_WARN_DEPRECATED_END \
+ _Pragma("clang diagnostic pop")
+
+#elif RT_GNUC_PREREQ(4, 6)
+# define RT_GCC_NO_WARN_DEPRECATED_BEGIN \
+ _Pragma("GCC diagnostic push") \
+ _Pragma("GCC diagnostic ignored \"-Wdeprecated-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_LONG_DOUBLE_BITS
+ * Number of relevant bits in the long double type: 64, 80 or 128 */
+/** @def RT_COMPILER_WITH_64BIT_LONG_DOUBLE
+ * Macro that is defined if the compiler implements long double as the
+ * IEEE precision floating. */
+/** @def RT_COMPILER_WITH_80BIT_LONG_DOUBLE
+ * Macro that is defined if the compiler implements long double as the
+ * IEEE extended precision floating. */
+/** @def RT_COMPILER_WITH_128BIT_LONG_DOUBLE
+* Macro that is defined if the compiler implements long double as the
+* IEEE quadruple precision floating (128-bit).
+* @note Currently not able to detect this, so must be explicitly defined. */
+#if defined(__LDBL_MANT_DIG__) /* GCC & clang have this defined and should be more reliable. */
+# if __LDBL_MANT_DIG__ == 53
+# define RT_COMPILER_LONG_DOUBLE_BITS 64
+# define RT_COMPILER_WITH_64BIT_LONG_DOUBLE
+# undef RT_COMPILER_WITH_80BIT_LONG_DOUBLE
+# undef RT_COMPILER_WITH_128BIT_LONG_DOUBLE
+# elif __LDBL_MANT_DIG__ == 64
+# define RT_COMPILER_LONG_DOUBLE_BITS 80
+# undef RT_COMPILER_WITH_64BIT_LONG_DOUBLE
+# define RT_COMPILER_WITH_80BIT_LONG_DOUBLE
+# undef RT_COMPILER_WITH_128BIT_LONG_DOUBLE
+# elif __LDBL_MANT_DIG__ == 113
+# define RT_COMPILER_LONG_DOUBLE_BITS 128
+# undef RT_COMPILER_WITH_64BIT_LONG_DOUBLE
+# undef RT_COMPILER_WITH_80BIT_LONG_DOUBLE
+# define RT_COMPILER_WITH_128BIT_LONG_DOUBLE
+# else
+# error "Port me!"
+# endif
+#elif defined(RT_OS_WINDOWS) || defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32) /* the M1 arm64 at least */
+# define RT_COMPILER_LONG_DOUBLE_BITS 64
+# define RT_COMPILER_WITH_64BIT_LONG_DOUBLE
+# undef RT_COMPILER_WITH_80BIT_LONG_DOUBLE
+# undef RT_COMPILER_WITH_128BIT_LONG_DOUBLE
+#elif defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
+# define RT_COMPILER_LONG_DOUBLE_BITS 80
+# undef RT_COMPILER_WITH_64BIT_LONG_DOUBLE
+# define RT_COMPILER_WITH_80BIT_LONG_DOUBLE
+# undef RT_COMPILER_WITH_128BIT_LONG_DOUBLE
+#elif defined(RT_ARCH_SPARC) || defined(RT_ARCH_SPARC64)
+# define RT_COMPILER_LONG_DOUBLE_BITS 128
+# undef RT_COMPILER_WITH_64BIT_LONG_DOUBLE
+# undef RT_COMPILER_WITH_80BIT_LONG_DOUBLE
+# define RT_COMPILER_WITH_128BIT_LONG_DOUBLE
+#else
+# error "Port me!"
+#endif
+
+/** @def RT_COMPILER_WITH_128BIT_INT_TYPES
+ * Defined when uint128_t and int128_t are native integer types. If
+ * undefined, they are structure with Hi & Lo members. */
+#if defined(__SIZEOF_INT128__) || (defined(__GNUC__) && (defined(RT_ARCH_AMD64) || defined(RT_ARCH_ARM64)))
+# define RT_COMPILER_WITH_128BIT_INT_TYPES
+#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 DECL_NOTHROW
+ * How to declare a function which does not throw C++ exceptions.
+ *
+ * @param a_Type The return type.
+ *
+ * @note This macro can be combined with other macros, for example
+ * @code
+ * RTR3DECL(DECL_NOTHROW(void)) foo(void);
+ * @endcode
+ *
+ * @note GCC is currently restricted to 4.2+ given the ominous comments on
+ * RT_NOTHROW_PROTO.
+ */
+#ifdef __cplusplus
+# if RT_MSC_PREREQ(RT_MSC_VER_VS2015) /*?*/
+# define DECL_NOTHROW(a_Type) __declspec(nothrow) a_Type
+# elif RT_CLANG_PREREQ(6,0) || RT_GNUC_PREREQ(4,2)
+# define DECL_NOTHROW(a_Type) __attribute__((__nothrow__)) a_Type
+# else
+# define DECL_NOTHROW(a_Type) a_Type
+# endif
+#else
+# define DECL_NOTHROW(a_Type) a_Type
+#endif
+
+/** @def RT_NOTHROW_PROTO
+ * Function does not throw any C++ exceptions, prototype edition.
+ *
+ * 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 and generate
+ * unwind info. Put this between the closing parenthesis and the semicolon in
+ * function prototypes (and implementation if C++).
+ *
+ * @note This translates to 'noexcept' when compiling in newer C++ mode.
+ *
+ * @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 us to have two
+ * macros, as the nothrow attribute is not for the function definition.
+ */
+/** @def RT_NOTHROW_DEF
+ * Function does not throw any C++ exceptions, definition edition.
+ *
+ * The counter part to RT_NOTHROW_PROTO that is added to the function
+ * definition.
+ */
+#ifdef RT_EXCEPTIONS_ENABLED
+# if RT_MSC_PREREQ_EX(RT_MSC_VER_VS2015, 0) \
+ || RT_CLANG_HAS_FEATURE(cxx_noexcept) \
+ || (RT_GNUC_PREREQ(7, 0) && __cplusplus >= 201100)
+# define RT_NOTHROW_PROTO noexcept
+# define RT_NOTHROW_DEF noexcept
+# elif defined(__GNUC__)
+# if RT_GNUC_PREREQ(3, 3)
+# define RT_NOTHROW_PROTO __attribute__((__nothrow__))
+# else
+# define RT_NOTHROW_PROTO
+# endif
+# define RT_NOTHROW_DEF /* Would need a DECL_NO_THROW like __declspec(nothrow), which we wont do at this point. */
+# else
+# define RT_NOTHROW_PROTO throw()
+# define RT_NOTHROW_DEF throw()
+# endif
+#else
+# define RT_NOTHROW_PROTO
+# define RT_NOTHROW_DEF
+#endif
+/** @def RT_NOTHROW_PROTO
+ * @deprecated Use RT_NOTHROW_PROTO. */
+#define RT_NO_THROW_PROTO RT_NOTHROW_PROTO
+/** @def RT_NOTHROW_DEF
+ * @deprecated Use RT_NOTHROW_DEF. */
+#define RT_NO_THROW_DEF RT_NOTHROW_DEF
+
+/** @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 a_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 (__cplusplus + 0) >= 201700
+# define RT_THROW(a_Type) noexcept(false)
+# elif RT_MSC_PREREQ_EX(RT_MSC_VER_VC71, 0)
+# define RT_THROW(a_Type)
+# elif RT_GNUC_PREREQ(7, 0)
+# define RT_THROW(a_Type)
+# else
+# define RT_THROW(a_Type) throw(a_Type)
+# endif
+#else
+# define RT_THROW(a_Type)
+#endif
+
+
+/** @def RT_OVERRIDE
+ * Wrapper for the C++11 override keyword.
+ *
+ * @remarks Recognized by g++ starting 4.7, however causes pedantic warnings
+ * when used without officially enabling the C++11 features.
+ */
+#ifdef __cplusplus
+# if RT_MSC_PREREQ_EX(RT_MSC_VER_VS2012, 0)
+# define RT_OVERRIDE override
+# elif RT_GNUC_PREREQ(4, 7)
+# if __cplusplus >= 201100
+# define RT_OVERRIDE override
+# else
+# define RT_OVERRIDE
+# endif
+# else
+# define RT_OVERRIDE
+# endif
+#else
+# define RT_OVERRIDE
+#endif
+
+/** @def RT_NOEXCEPT
+ * Wrapper for the C++11 noexcept keyword (only true form).
+ * @note use RT_NOTHROW instead.
+ */
+/** @def RT_NOEXCEPT_EX
+ * Wrapper for the C++11 noexcept keyword with expression.
+ * @param a_Expr The expression.
+ */
+#ifdef __cplusplus
+# if (RT_MSC_PREREQ_EX(RT_MSC_VER_VS2015, 0) && defined(RT_EXCEPTIONS_ENABLED)) \
+ || RT_CLANG_HAS_FEATURE(cxx_noexcept) \
+ || (RT_GNUC_PREREQ(7, 0) && __cplusplus >= 201100)
+# define RT_NOEXCEPT noexcept
+# define RT_NOEXCEPT_EX(a_Expr) noexcept(a_Expr)
+# else
+# define RT_NOEXCEPT
+# define RT_NOEXCEPT_EX(a_Expr)
+# endif
+#else
+# define RT_NOEXCEPT
+# define RT_NOEXCEPT_EX(a_Expr)
+#endif
+
+/** @def RT_ALIGNAS_VAR
+ * Wrapper for the C++ alignas keyword when used on variables.
+ *
+ * This must be put before the storage class and type.
+ *
+ * @param a_cbAlign The alignment. Must be power of two.
+ * @note If C++11 is not enabled/detectable, alternatives will be used where
+ * available. */
+/** @def RT_ALIGNAS_TYPE
+ * Wrapper for the C++ alignas keyword when used on types.
+ *
+ * When using struct, this must follow the struct keyword.
+ *
+ * @param a_cbAlign The alignment. Must be power of two.
+ * @note If C++11 is not enabled/detectable, alternatives will be used where
+ * available. */
+/** @def RT_ALIGNAS_MEMB
+ * Wrapper for the C++ alignas keyword when used on structure members.
+ *
+ * This must be put before the variable type.
+ *
+ * @param a_cbAlign The alignment. Must be power of two.
+ * @note If C++11 is not enabled/detectable, alternatives will be used where
+ * available. */
+#ifdef __cplusplus
+# if __cplusplus >= 201100 || defined(DOXYGEN_RUNNING)
+# define RT_ALIGNAS_VAR(a_cbAlign) alignas(a_cbAlign)
+# define RT_ALIGNAS_TYPE(a_cbAlign) alignas(a_cbAlign)
+# define RT_ALIGNAS_MEMB(a_cbAlign) alignas(a_cbAlign)
+# endif
+#endif
+#ifndef RT_ALIGNAS_VAR
+# ifdef _MSC_VER
+# define RT_ALIGNAS_VAR(a_cbAlign) __declspec(align(a_cbAlign))
+# define RT_ALIGNAS_TYPE(a_cbAlign) __declspec(align(a_cbAlign))
+# define RT_ALIGNAS_MEMB(a_cbAlign) __declspec(align(a_cbAlign))
+# elif defined(__GNUC__)
+# define RT_ALIGNAS_VAR(a_cbAlign) __attribute__((__aligned__(a_cbAlign)))
+# define RT_ALIGNAS_TYPE(a_cbAlign) __attribute__((__aligned__(a_cbAlign)))
+# define RT_ALIGNAS_MEMB(a_cbAlign) __attribute__((__aligned__(a_cbAlign)))
+# else
+# define RT_ALIGNAS_VAR(a_cbAlign)
+# define RT_ALIGNAS_TYPE(a_cbAlign)
+# define RT_ALIGNAS_MEMB(a_cbAlign)
+# endif
+#endif
+
+/** @def RT_CACHELINE_SIZE
+ * The typical cache line size for the target architecture.
+ * @see RT_ALIGNAS_VAR, RT_ALIGNAS_TYPE, RT_ALIGNAS_MEMB
+ */
+#if defined(RT_ARCH_X86) || defined(RT_ARCH_AMD64) \
+ || defined(RT_ARCH_ARM32) || defined(RT_ARCH_ARM64) \
+ || defined(RT_ARCH_SPARC32) || defined(RT_ARCH_SPARC64) \
+ || defined(DOXYGEN_RUNNING)
+# define RT_CACHELINE_SIZE 64
+#else
+# define RT_CACHELINE_SIZE 128 /* better overdo it */
+#endif
+
+/** @def RT_FALL_THROUGH
+ * Tell the compiler that we're falling through to the next case in a switch.
+ * @sa RT_FALL_THRU */
+#if RT_CLANG_PREREQ(4, 0) && RT_CPLUSPLUS_PREREQ(201100)
+# define RT_FALL_THROUGH() [[clang::fallthrough]]
+#elif RT_CLANG_PREREQ(12, 0) || RT_GNUC_PREREQ(7, 0)
+# define RT_FALL_THROUGH() __attribute__((__fallthrough__))
+#else
+# define RT_FALL_THROUGH() (void)0
+#endif
+/** @def RT_FALL_THRU
+ * Tell the compiler that we're falling thru to the next case in a switch.
+ * @sa RT_FALL_THROUGH */
+#define RT_FALL_THRU() RT_FALL_THROUGH()
+
+
+/** @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
+#elif defined(__WATCOMC__)
+# define RT_COMPILER_SUPPORTS_VA_ARGS
+#endif
+
+/** @def RT_CB_LOG_CAST
+ * Helper for logging function pointers to function may throw stuff.
+ *
+ * Not needed for function pointer types declared using our DECLCALLBACK
+ * macros, only external types. */
+#if defined(_MSC_VER) && defined(RT_EXCEPTIONS_ENABLED)
+# define RT_CB_LOG_CAST(a_pfnCallback) ((uintptr_t)(a_pfnCallback) + 1 - 1)
+#else
+# define RT_CB_LOG_CAST(a_pfnCallback) (a_pfnCallback)
+#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 a_RetType The return type of the function declaration.
+ */
+#if defined(_MSC_VER) || defined(RT_OS_OS2)
+# define DECLEXPORT(a_RetType) __declspec(dllexport) a_RetType
+#elif defined(RT_USE_VISIBILITY_DEFAULT)
+# define DECLEXPORT(a_RetType) __attribute__((visibility("default"))) a_RetType
+#else
+# define DECLEXPORT(a_RetType) a_RetType
+#endif
+
+/** @def DECL_EXPORT_NOTHROW
+ * How to declare an exported function that does not throw C++ exceptions.
+ * @param a_RetType The return type of the function declaration.
+ */
+#define DECL_EXPORT_NOTHROW(a_RetType) DECL_NOTHROW(DECLEXPORT(a_RetType))
+
+/** @def DECLIMPORT
+ * How to declare an imported function.
+ * @param a_RetType The return type of the function declaration.
+ */
+#if defined(_MSC_VER) || (defined(RT_OS_OS2) && !defined(__IBMC__) && !defined(__IBMCPP__))
+# define DECLIMPORT(a_RetType) __declspec(dllimport) a_RetType
+#else
+# define DECLIMPORT(a_RetType) a_RetType
+#endif
+
+/** @def DECL_IMPORT_NOTHROW
+ * How to declare an imported function that does not throw C++ exceptions.
+ * @param a_RetType The return type of the function declaration.
+ */
+#define DECL_IMPORT_NOTHROW(a_RetType) DECL_NOTHROW(DECLIMPORT(a_RetType))
+
+/** @def DECL_HIDDEN_ONLY
+ * How to declare a non-exported function or variable.
+ * @param a_Type The return type of the function or the data type of the variable.
+ * @sa DECL_HIDDEN, DECL_HIDDEN_DATA, DECL_HIDDEN_CONST
+ * @internal Considered more or less internal.
+ */
+#if !defined(RT_GCC_SUPPORTS_VISIBILITY_HIDDEN) || defined(RT_NO_VISIBILITY_HIDDEN)
+# define DECL_HIDDEN_ONLY(a_Type) a_Type
+#else
+# define DECL_HIDDEN_ONLY(a_Type) __attribute__((visibility("hidden"))) a_Type
+#endif
+
+/** @def DECLHIDDEN
+ * How to declare a non-exported function or variable.
+ * @param a_Type The return type of the function or the data type of the variable.
+ * @sa DECL_HIDDEN_THROW, DECL_HIDDEN_DATA, DECL_HIDDEN_CONST
+ * @todo split up into data and non-data.
+ */
+#define DECLHIDDEN(a_Type) DECL_NOTHROW(DECL_HIDDEN_ONLY(a_Type))
+
+/** @def DECL_HIDDEN_NOTHROW
+ * How to declare a non-exported function that does not throw C++ exceptions.
+ * @param a_RetType The return type of the function.
+ * @note Same as DECLHIDDEN but provided to go along with DECL_IMPORT_NOTHROW
+ * and DECL_EXPORT_NOTHROW.
+ */
+#define DECL_HIDDEN_NOTHROW(a_RetType) DECL_NOTHROW(DECL_HIDDEN_ONLY(a_RetType))
+
+/** @def DECL_HIDDEN_THROW
+ * How to declare a non-exported function that may throw C++ exceptions.
+ * @param a_RetType The return type of the function.
+ */
+#define DECL_HIDDEN_THROW(a_RetType) DECL_HIDDEN_ONLY(a_Type)
+
+/** @def DECL_HIDDEN_DATA
+ * How to declare a non-exported variable.
+ * @param a_Type The data type of the variable.
+ * @sa DECL_HIDDEN_CONST
+ */
+#if !defined(RT_GCC_SUPPORTS_VISIBILITY_HIDDEN) || defined(RT_NO_VISIBILITY_HIDDEN)
+# define DECL_HIDDEN_DATA(a_Type) a_Type
+#else
+# define DECL_HIDDEN_DATA(a_Type) __attribute__((visibility("hidden"))) a_Type
+#endif
+
+/** @def DECL_HIDDEN_CONST
+ * Workaround for g++ warnings when applying the hidden attribute to a const
+ * definition. Use DECL_HIDDEN_DATA for the declaration.
+ * @param a_Type The data type of the variable.
+ * @sa DECL_HIDDEN_DATA
+ */
+#if defined(__cplusplus) && defined(__GNUC__)
+# define DECL_HIDDEN_CONST(a_Type) a_Type
+#else
+# define DECL_HIDDEN_CONST(a_Type) DECL_HIDDEN_DATA(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 a_RetType The return type of the function.
+ */
+#if defined(_MSC_VER)
+# define DECL_INVALID(a_RetType) __declspec(dllimport) a_RetType __stdcall
+#elif defined(__GNUC__) && defined(__cplusplus)
+# define DECL_INVALID(a_RetType) extern "C++" a_RetType
+#else
+# define DECL_INVALID(a_RetType) a_RetType
+#endif
+
+/** @def DECLASM
+ * How to declare an internal assembly function.
+ * @param a_RetType The return type of the function declaration.
+ * @note DECL_NOTHROW is implied.
+ */
+#ifdef __cplusplus
+# define DECLASM(a_RetType) extern "C" DECL_NOTHROW(a_RetType RTCALL)
+#else
+# define DECLASM(a_RetType) DECL_NOTHROW(a_RetType RTCALL)
+#endif
+
+/** @def RT_ASM_DECL_PRAGMA_WATCOM
+ * How to declare a assembly method prototype with watcom \#pragma aux definition. */
+/** @def RT_ASM_DECL_PRAGMA_WATCOM_386
+ * Same as RT_ASM_DECL_PRAGMA_WATCOM, but there is no 16-bit version when
+ * 8086, 80186 or 80286 is selected as the target CPU. */
+#if defined(__WATCOMC__) && ARCH_BITS == 16 && defined(RT_ARCH_X86)
+# define RT_ASM_DECL_PRAGMA_WATCOM(a_RetType) a_RetType
+# if defined(__SW_0) || defined(__SW_1) || defined(__SW_2)
+# define RT_ASM_DECL_PRAGMA_WATCOM_386(a_RetType) DECLASM(a_RetType)
+# else
+# define RT_ASM_DECL_PRAGMA_WATCOM_386(a_RetType) a_RetType
+# endif
+#elif defined(__WATCOMC__) && ARCH_BITS == 32 && defined(RT_ARCH_X86)
+# define RT_ASM_DECL_PRAGMA_WATCOM(a_RetType) a_RetType
+# define RT_ASM_DECL_PRAGMA_WATCOM_386(a_RetType) a_RetType
+#else
+# define RT_ASM_DECL_PRAGMA_WATCOM(a_RetType) DECLASM(a_RetType)
+# define RT_ASM_DECL_PRAGMA_WATCOM_386(a_RetType) DECLASM(a_RetType)
+#endif
+
+/** @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
+ * RTR3DECL(DECL_NO_RETURN(void)) foo(void);
+ * @endcode
+ */
+#ifdef _MSC_VER
+# define DECL_NO_RETURN(a_RetType) __declspec(noreturn) a_RetType
+#elif defined(__GNUC__)
+# define DECL_NO_RETURN(a_RetType) __attribute__((noreturn)) a_RetType
+#else
+# define DECL_NO_RETURN(a_RetType) a_RetType
+#endif
+
+/** @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
+ * RTR3DECL(DECL_RETURNS_TWICE(void)) MySetJmp(void);
+ * @endcode
+ */
+#if RT_GNUC_PREREQ(4, 1)
+# define DECL_RETURNS_TWICE(a_RetType) __attribute__((returns_twice)) a_RetType
+#else
+# define DECL_RETURNS_TWICE(a_RetType) a_RetType
+#endif
+
+/** @def DECL_CHECK_RETURN
+ * Require a return value to be checked.
+ * @note This macro can be combined with other macros, for example
+ * @code
+ * RTR3DECL(DECL_CHECK_RETURN(int)) MayReturnInfoStatus(void);
+ * @endcode
+ */
+#if RT_GNUC_PREREQ(3, 4)
+# define DECL_CHECK_RETURN(a_RetType) __attribute__((warn_unused_result)) a_RetType
+#elif defined(_MSC_VER)
+# define DECL_CHECK_RETURN(a_RetType) __declspec("SAL_checkReturn") a_RetType
+#else
+# define DECL_CHECK_RETURN(a_RetType) a_RetType
+#endif
+
+/** @def DECL_CHECK_RETURN_NOT_R3
+ * Variation of DECL_CHECK_RETURN that only applies the required to non-ring-3
+ * code.
+ */
+#ifndef IN_RING3
+# define DECL_CHECK_RETURN_NOT_R3(a_RetType) DECL_CHECK_RETURN(a_RetType)
+#else
+# define DECL_CHECK_RETURN_NOT_R3(a_RetType) a_RetType
+#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
+ * RTR3DECL(DECLWEAK(int)) foo;
+ * @endcode
+ */
+#if defined(__GNUC__)
+# define DECLWEAK(a_Type) a_Type __attribute__((weak))
+#else
+# define DECLWEAK(a_Type) a_Type
+#endif
+
+/** @def DECLCALLBACK
+ * How to declare an call back function.
+ * @param a_RetType The return type of the function declaration.
+ * @note DECL_NOTHROW is implied.
+ * @note Use DECLCALLBACKTYPE for typedefs.
+ */
+#define DECLCALLBACK(a_RetType) DECL_NOTHROW(a_RetType RT_FAR_CODE RTCALL)
+
+/** @def DECL_HIDDEN_CALLBACK
+ * How to declare an call back function with hidden visibility.
+ * @param a_RetType The return type of the function declaration.
+ * @note DECL_NOTHROW is implied.
+ * @note Use DECLCALLBACKTYPE for typedefs.
+ */
+#define DECL_HIDDEN_CALLBACK(a_RetType) DECL_HIDDEN_ONLY(DECLCALLBACK(a_RetType))
+
+/** @def DECLCALLBACKTYPE_EX
+ * How to declare an call back function type.
+ * @param a_RetType The return type of the function declaration.
+ * @param a_CallConv Calling convention.
+ * @param a_Name The name of the typedef
+ * @param a_Args The argument list enclosed in parentheses.
+ * @note DECL_NOTHROW is implied, but not supported by all compilers yet.
+ */
+#if RT_CLANG_PREREQ(6,0) && !defined(RT_RELAXED_CALLBACKS_TYPES)
+# define DECLCALLBACKTYPE_EX(a_RetType, a_CallConv, a_Name, a_Args) __attribute__((__nothrow__)) a_RetType a_CallConv a_Name a_Args
+#elif RT_MSC_PREREQ(RT_MSC_VER_VS2015) /*?*/ && defined(__cplusplus) && defined(_MSC_EXTENSIONS) && !defined(RT_RELAXED_CALLBACKS_TYPES)
+# define DECLCALLBACKTYPE_EX(a_RetType, a_CallConv, a_Name, a_Args) a_RetType a_CallConv a_Name a_Args throw()
+#else
+# define DECLCALLBACKTYPE_EX(a_RetType, a_CallConv, a_Name, a_Args) a_RetType a_CallConv a_Name a_Args
+#endif
+/** @def DECLCALLBACKTYPE
+ * How to declare an call back function type.
+ * @param a_RetType The return type of the function declaration.
+ * @param a_Name The name of the typedef
+ * @param a_Args The argument list enclosed in parentheses.
+ * @note DECL_NOTHROW is implied, but not supported by all compilers yet.
+ */
+#define DECLCALLBACKTYPE(a_RetType, a_Name, a_Args) DECLCALLBACKTYPE_EX(a_RetType, RT_FAR_CODE RTCALL, a_Name, a_Args)
+
+/** @def DECLCALLBACKPTR_EX
+ * How to declare an call back function pointer.
+ * @param a_RetType The return type of the function declaration.
+ * @param a_CallConv Calling convention.
+ * @param a_Name The name of the variable member.
+ * @param a_Args The argument list enclosed in parentheses.
+ * @note DECL_NOTHROW is implied, but not supported by all compilers yet.
+ */
+#if defined(__IBMC__) || defined(__IBMCPP__)
+# define DECLCALLBACKPTR_EX(a_RetType, a_CallConv, a_Name, a_Args) a_RetType (* a_CallConv a_Name) a_Args
+#elif RT_CLANG_PREREQ(6,0) && !defined(RT_RELAXED_CALLBACKS_TYPES)
+# define DECLCALLBACKPTR_EX(a_RetType, a_CallConv, a_Name, a_Args) __attribute__((__nothrow__)) a_RetType (a_CallConv * a_Name) a_Args
+#elif RT_MSC_PREREQ(RT_MSC_VER_VS2015) /*?*/ && defined(__cplusplus) && defined(_MSC_EXTENSIONS) && !defined(RT_RELAXED_CALLBACKS_TYPES)
+# define DECLCALLBACKPTR_EX(a_RetType, a_CallConv, a_Name, a_Args) a_RetType (a_CallConv * a_Name) a_Args throw()
+#else
+# define DECLCALLBACKPTR_EX(a_RetType, a_CallConv, a_Name, a_Args) a_RetType (a_CallConv * a_Name) a_Args
+#endif
+/** @def DECLCALLBACKPTR
+ * How to declare an call back function pointer.
+ * @param a_RetType The return type of the function declaration.
+ * @param a_Name The name of the variable member.
+ * @param a_Args The argument list enclosed in parentheses.
+ * @note DECL_NOTHROW is implied, but not supported by all compilers yet.
+ */
+#define DECLCALLBACKPTR(a_RetType, a_Name, a_Args) DECLCALLBACKPTR_EX(a_RetType, RT_FAR_CODE RTCALL, a_Name, a_Args)
+
+/** @def DECLCALLBACKMEMBER_EX
+ * How to declare an call back function pointer member.
+ * @param a_RetType The return type of the function declaration.
+ * @param a_CallConv Calling convention.
+ * @param a_Name The name of the struct/union/class member.
+ * @param a_Args The argument list enclosed in parentheses.
+ * @note DECL_NOTHROW is implied, but not supported by all compilers yet.
+ */
+#if defined(__IBMC__) || defined(__IBMCPP__)
+# define DECLCALLBACKMEMBER_EX(a_RetType, a_CallConv, a_Name, a_Args) a_RetType (* a_CallConv a_Name) a_Args
+#elif RT_CLANG_PREREQ(6,0) && !defined(RT_RELAXED_CALLBACKS_TYPES)
+# define DECLCALLBACKMEMBER_EX(a_RetType, a_CallConv, a_Name, a_Args) __attribute__((__nothrow__)) a_RetType (a_CallConv *a_Name) a_Args
+#elif RT_MSC_PREREQ(RT_MSC_VER_VS2015) /*?*/ && defined(__cplusplus) && defined(_MSC_EXTENSIONS) && !defined(RT_RELAXED_CALLBACKS_TYPES)
+# define DECLCALLBACKMEMBER_EX(a_RetType, a_CallConv, a_Name, a_Args) a_RetType (a_CallConv *a_Name) a_Args throw()
+#else
+# define DECLCALLBACKMEMBER_EX(a_RetType, a_CallConv, a_Name, a_Args) a_RetType (a_CallConv *a_Name) a_Args
+#endif
+/** @def DECLCALLBACKMEMBER
+ * How to declare an call back function pointer member.
+ * @param a_RetType The return type of the function declaration.
+ * @param a_Name The name of the struct/union/class member.
+ * @param a_Args The argument list enclosed in parentheses.
+ * @note DECL_NOTHROW is implied, but not supported by all compilers yet.
+ */
+#define DECLCALLBACKMEMBER(a_RetType, a_Name, a_Args) DECLCALLBACKMEMBER_EX(a_RetType, RT_FAR_CODE RTCALL, a_Name, a_Args)
+
+/** @def DECLR3CALLBACKMEMBER
+ * How to declare an call back function pointer member - R3 Ptr.
+ * @param a_RetType The return type of the function declaration.
+ * @param a_Name The name of the struct/union/class member.
+ * @param a_Args The argument list enclosed in parentheses.
+ * @note DECL_NOTHROW is implied, but not supported by all compilers yet.
+ */
+#if defined(IN_RING3) || defined(DOXYGEN_RUNNING)
+# define DECLR3CALLBACKMEMBER(a_RetType, a_Name, a_Args) DECLCALLBACKMEMBER(a_RetType, a_Name, a_Args)
+#else
+# define DECLR3CALLBACKMEMBER(a_RetType, a_Name, a_Args) RTR3PTR a_Name
+#endif
+
+/** @def DECLRCCALLBACKMEMBER
+ * How to declare an call back function pointer member - RC Ptr.
+ * @param a_RetType The return type of the function declaration.
+ * @param a_Name The name of the struct/union/class member.
+ * @param a_Args The argument list enclosed in parentheses.
+ * @note DECL_NOTHROW is implied, but not supported by all compilers yet.
+ */
+#if defined(IN_RC) || defined(DOXYGEN_RUNNING)
+# define DECLRCCALLBACKMEMBER(a_RetType, a_Name, a_Args) DECLCALLBACKMEMBER(a_RetType, a_Name, a_Args)
+#else
+# define DECLRCCALLBACKMEMBER(a_RetType, a_Name, a_Args) RTRCPTR a_Name
+#endif
+#if defined(IN_RC) || defined(DOXYGEN_RUNNING)
+# define DECLRGCALLBACKMEMBER(a_RetType, a_Name, a_Args) DECLCALLBACKMEMBER(a_RetType, a_Name, a_Args)
+#else
+# define DECLRGCALLBACKMEMBER(a_RetType, a_Name, a_Args) RTRGPTR a_Name
+#endif
+
+/** @def DECLR0CALLBACKMEMBER
+ * How to declare an call back function pointer member - R0 Ptr.
+ * @param a_RetType The return type of the function declaration.
+ * @param a_Name The name of the struct/union/class member.
+ * @param a_Args The argument list enclosed in parentheses.
+ * @note DECL_NOTHROW is implied, but not supported by all compilers yet.
+ */
+#if defined(IN_RING0) || defined(DOXYGEN_RUNNING)
+# define DECLR0CALLBACKMEMBER(a_RetType, a_Name, a_Args) DECLCALLBACKMEMBER(a_RetType, a_Name, a_Args)
+#else
+# define DECLR0CALLBACKMEMBER(a_RetType, a_Name, a_Args) RTR0PTR a_Name
+#endif
+
+/** @def DECLINLINE
+ * How to declare a function as inline that does not throw any C++ exceptions.
+ * @param a_RetType The return type of the function declaration.
+ * @remarks Don't use this macro on C++ methods.
+ * @sa DECL_INLINE_THROW
+ */
+#if defined(__GNUC__) && !defined(DOXYGEN_RUNNING)
+# define DECLINLINE(a_RetType) DECL_NOTHROW(static __inline__ a_RetType)
+#elif defined(__cplusplus) || defined(DOXYGEN_RUNNING)
+# define DECLINLINE(a_RetType) DECL_NOTHROW(static inline a_RetType)
+#elif defined(_MSC_VER)
+# define DECLINLINE(a_RetType) DECL_NOTHROW(static _inline a_RetType)
+#elif defined(__IBMC__)
+# define DECLINLINE(a_RetType) DECL_NOTHROW(_Inline a_RetType)
+#else
+# define DECLINLINE(a_RetType) DECL_NOTHROW(inline a_RetType)
+#endif
+
+/** @def DECL_INLINE_THROW
+ * How to declare a function as inline that throws C++ exceptions.
+ * @param a_RetType The return type of the function declaration.
+ * @remarks Don't use this macro on C++ methods.
+ */
+#if defined(__GNUC__) && !defined(DOXYGEN_RUNNING)
+# define DECL_INLINE_THROW(a_RetType) static __inline__ a_RetType
+#elif defined(__cplusplus) || defined(DOXYGEN_RUNNING)
+# define DECL_INLINE_THROW(a_RetType) static inline a_RetType
+#elif defined(_MSC_VER)
+# define DECL_INLINE_THROW(a_RetType) static _inline a_RetType
+#elif defined(__IBMC__)
+# define DECL_INLINE_THROW(a_RetType) _Inline a_RetType
+#else
+# define DECL_INLINE_THROW(a_RetType) inline a_RetType
+#endif
+
+/** @def DECL_FORCE_INLINE
+ * How to declare a function that does not throw any C++ exceptions as inline
+ * and try convince the compiler to always inline it regardless of optimization
+ * switches.
+ * @param a_RetType The return type of the function declaration.
+ * @remarks Use sparsely and with care. Don't use this macro on C++ methods.
+ * @sa DECL_FORCE_INLINE_THROW
+ */
+#ifdef __GNUC__
+# define DECL_FORCE_INLINE(a_RetType) __attribute__((__always_inline__)) DECLINLINE(a_RetType)
+#elif defined(_MSC_VER)
+# define DECL_FORCE_INLINE(a_RetType) DECL_NOTHROW(__forceinline a_RetType)
+#else
+# define DECL_FORCE_INLINE(a_RetType) DECLINLINE(a_RetType)
+#endif
+
+/** @def DECL_FORCE_INLINE_THROW
+ * How to declare a function throwing C++ exceptions as inline and try convince
+ * the compiler to always inline it regardless of optimization switches.
+ * @param a_RetType 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_THROW(a_RetType) __attribute__((__always_inline__)) DECL_INLINE_THROW(a_RetType)
+#elif defined(_MSC_VER)
+# define DECL_FORCE_INLINE_THROW(a_RetType) __forceinline a_RetType
+#else
+# define DECL_FORCE_INLINE_THROW(a_RetType) DECL_INLINE_THROW(a_RetType)
+#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 a_RetType The return type of the function declaration.
+ * @remarks Don't use this macro on C++ methods.
+ */
+#ifdef __GNUC__
+# define DECL_NO_INLINE(scope, a_RetType) __attribute__((__noinline__)) scope a_RetType
+#elif defined(_MSC_VER)
+# define DECL_NO_INLINE(scope, a_RetType) __declspec(noinline) scope a_RetType
+#else
+# define DECL_NO_INLINE(scope,a_RetType) scope a_RetType
+#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(a_RetType)
+ * Runtime Library host context ring-0 export or import declaration.
+ * @param a_RetType The return a_RetType 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.
+ * @note DECL_NOTHROW is implied.
+ */
+#ifdef IN_RT_R0
+# ifdef IN_RT_STATIC
+# define RTR0DECL(a_RetType) DECL_HIDDEN_NOTHROW(a_RetType) RTCALL
+# else
+# define RTR0DECL(a_RetType) DECL_EXPORT_NOTHROW(a_RetType) RTCALL
+# endif
+#else
+# define RTR0DECL(a_RetType) DECL_IMPORT_NOTHROW(a_RetType) 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(a_RetType)
+ * Runtime Library host context ring-3 export or import declaration.
+ * @param a_RetType 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.
+ * @note DECL_NOTHROW is implied.
+ */
+#ifdef IN_RT_R3
+# ifdef IN_RT_STATIC
+# define RTR3DECL(a_RetType) DECL_HIDDEN_NOTHROW(a_RetType) RTCALL
+# else
+# define RTR3DECL(a_RetType) DECL_EXPORT_NOTHROW(a_RetType) RTCALL
+# endif
+#else
+# define RTR3DECL(a_RetType) DECL_IMPORT_NOTHROW(a_RetType) 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(a_RetType)
+ * Runtime Library raw-mode context export or import declaration.
+ * @param a_RetType 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.
+ * @note DECL_NOTHROW is implied.
+ */
+#ifdef IN_RT_RC
+# ifdef IN_RT_STATIC
+# define RTRCDECL(a_RetType) DECL_HIDDEN_NOTHROW(a_RetType) RTCALL
+# else
+# define RTRCDECL(a_RetType) DECL_EXPORT_NOTHROW(a_RetType) RTCALL
+# endif
+#else
+# define RTRCDECL(a_RetType) DECL_IMPORT_NOTHROW(a_RetType) RTCALL
+#endif
+
+/** @def RTDECL(a_RetType)
+ * Runtime Library export or import declaration.
+ * Functions declared using this macro exists in all contexts.
+ * @param a_RetType 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.
+ * @note DECL_NOTHROW is implied.
+ */
+#if defined(IN_RT_R3) || defined(IN_RT_RC) || defined(IN_RT_R0)
+# ifdef IN_RT_STATIC
+# define RTDECL(a_RetType) DECL_HIDDEN_NOTHROW(a_RetType) RTCALL
+# else
+# define RTDECL(a_RetType) DECL_EXPORT_NOTHROW(a_RetType) RTCALL
+# endif
+#else
+# define RTDECL(a_RetType) DECL_IMPORT_NOTHROW(a_RetType) RTCALL
+#endif
+
+/** @def RTDATADECL(a_Type)
+ * Runtime Library export or import declaration.
+ * Data declared using this macro exists in all contexts.
+ * @param a_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(a_Type)
+ * Definition of a const variable. See DECL_HIDDEN_CONST.
+ * @param a_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(a_Type) DECL_HIDDEN_DATA(a_Type)
+# define RT_DECL_DATA_CONST(a_Type) DECL_HIDDEN_CONST(a_Type)
+# else
+# define RTDATADECL(a_Type) DECLEXPORT(a_Type)
+# if defined(__cplusplus) && defined(__GNUC__)
+# define RT_DECL_DATA_CONST(a_Type) a_Type
+# else
+# define RT_DECL_DATA_CONST(a_Type) DECLEXPORT(a_Type)
+# endif
+# endif
+#else
+# define RTDATADECL(a_Type) DECLIMPORT(a_Type)
+# define RT_DECL_DATA_CONST(a_Type) DECLIMPORT(a_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.
+ */
+#if !defined(RT_WITHOUT_NOCRT_WRAPPERS) || defined(RT_FORCE_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
+
+
+/** @name Untrusted data classifications.
+ * @{ */
+/** @def RT_UNTRUSTED_USER
+ * For marking non-volatile (race free) data from user mode as untrusted.
+ * This is just for visible documentation. */
+#define RT_UNTRUSTED_USER
+/** @def RT_UNTRUSTED_VOLATILE_USER
+ * For marking volatile data shared with user mode as untrusted.
+ * This is more than just documentation as it specifies the 'volatile' keyword,
+ * because the guest could modify the data at any time. */
+#define RT_UNTRUSTED_VOLATILE_USER volatile
+
+/** @def RT_UNTRUSTED_GUEST
+ * For marking non-volatile (race free) data from the guest as untrusted.
+ * This is just for visible documentation. */
+#define RT_UNTRUSTED_GUEST
+/** @def RT_UNTRUSTED_VOLATILE_GUEST
+ * For marking volatile data shared with the guest as untrusted.
+ * This is more than just documentation as it specifies the 'volatile' keyword,
+ * because the guest could modify the data at any time. */
+#define RT_UNTRUSTED_VOLATILE_GUEST volatile
+
+/** @def RT_UNTRUSTED_HOST
+ * For marking non-volatile (race free) data from the host as untrusted.
+ * This is just for visible documentation. */
+#define RT_UNTRUSTED_HOST
+/** @def RT_UNTRUSTED_VOLATILE_HOST
+ * For marking volatile data shared with the host as untrusted.
+ * This is more than just documentation as it specifies the 'volatile' keyword,
+ * because the host could modify the data at any time. */
+#define RT_UNTRUSTED_VOLATILE_HOST volatile
+
+/** @def RT_UNTRUSTED_HSTGST
+ * For marking non-volatile (race free) data from the host/gust as untrusted.
+ * This is just for visible documentation. */
+#define RT_UNTRUSTED_HSTGST
+/** @def RT_UNTRUSTED_VOLATILE_HSTGST
+ * For marking volatile data shared with the host/guest as untrusted.
+ * This is more than just documentation as it specifies the 'volatile' keyword,
+ * because the host could modify the data at any time. */
+#define RT_UNTRUSTED_VOLATILE_HSTGST volatile
+/** @} */
+
+/** @name Fences for use when handling untrusted data.
+ * @{ */
+/** For use after copying untruated volatile data to a non-volatile location.
+ * This translates to a compiler memory barrier and will help ensure that the
+ * compiler uses the non-volatile copy of the data. */
+#define RT_UNTRUSTED_NONVOLATILE_COPY_FENCE() ASMCompilerBarrier()
+/** For use after finished validating guest input.
+ * What this translates to is architecture dependent. On intel it will
+ * translate to a CPU load+store fence as well as a compiler memory barrier. */
+#if defined(RT_ARCH_AMD64) || (defined(RT_ARCH_X86) && !defined(RT_WITH_OLD_CPU_SUPPORT))
+# define RT_UNTRUSTED_VALIDATED_FENCE() do { ASMCompilerBarrier(); ASMReadFence(); } while (0)
+#elif defined(RT_ARCH_X86)
+# define RT_UNTRUSTED_VALIDATED_FENCE() do { ASMCompilerBarrier(); ASMMemoryFence(); } while (0)
+#else
+# define RT_UNTRUSTED_VALIDATED_FENCE() do { ASMCompilerBarrier(); } while (0)
+#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_BIT_Z
+ * Convert a bit number into a size_t bitmask (for avoid MSC warnings).
+ * @param a_iBit The bit number.
+ */
+#define RT_BIT_Z(a_iBit) ( (size_t)(1) << (a_iBit) )
+
+
+/** @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.
+ *
+ * @returns offset into the structure of the specified member. signed.
+ * @param type Structure type.
+ * @param member Member.
+ *
+ * @remarks Only use this for static offset calculations. Please
+ * use RT_UOFFSETOF_DYN for dynamic ones (i.e. involves
+ * non-constant array indexing).
+ *
+ */
+#if RT_GNUC_PREREQ(4, 0)
+# define RT_OFFSETOF(type, member) ( (int)__builtin_offsetof(type, member) )
+#else
+# define RT_OFFSETOF(type, member) ( (int)(intptr_t)&( ((type *)(void *)0)->member) )
+#endif
+
+/** @def RT_UOFFSETOF
+ * Our own offsetof() variant, returns an unsigned result.
+ *
+ * @returns offset into the structure of the specified member. unsigned.
+ * @param type Structure type.
+ * @param member Member.
+ *
+ * @remarks Only use this for static offset calculations. Please
+ * use RT_UOFFSETOF_DYN for dynamic ones (i.e. involves
+ * non-constant array indexing).
+ */
+#if RT_GNUC_PREREQ(4, 0)
+# define RT_UOFFSETOF(type, member) ( (uintptr_t)__builtin_offsetof(type, member) )
+#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.
+ *
+ * @remarks Only use this for static offset calculations.
+ */
+#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.
+ *
+ * @remarks Only use this for static offset calculations.
+ */
+#if RT_GNUC_PREREQ(4, 0)
+# define RT_UOFFSETOF_ADD(type, member, addend) ( (uintptr_t)(__builtin_offsetof(type, member) + (addend)))
+#else
+# define RT_UOFFSETOF_ADD(type, member, addend) ( (uintptr_t)&( ((type *)(void *)(uintptr_t)(addend))->member) )
+#endif
+
+/** @def RT_UOFFSETOF_DYN
+ * Dynamic (runtime) structure offset calculations, involving
+ * indexing of array members via variable.
+ *
+ * @returns offset into the structure of the specified member. signed.
+ * @param type Structure type.
+ * @param memberarray Member.
+ */
+#if defined(__cplusplus) && RT_GNUC_PREREQ(4, 4)
+# define RT_UOFFSETOF_DYN(type, memberarray) ( (uintptr_t)&( ((type *)(void *)0x1000)->memberarray) - 0x1000 )
+#else
+# define RT_UOFFSETOF_DYN(type, memberarray) ( (uintptr_t)&( ((type *)(void *)0)->memberarray) )
+#endif
+
+
+/** @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_FROM_MEMBER_DYN
+ * 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 dynamic size (some array is index by
+ * non-constant value).
+ */
+#define RT_FROM_MEMBER_DYN(pMem, Type, Member) ( (Type *) ((uint8_t *)(void *)(pMem) - RT_UOFFSETOF_DYN(Type, Member)) )
+
+/** @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_SAFE_SUBSCRIPT
+ * Safe array subscript using modulo and size_t cast.
+ * @param a_Array The array.
+ * @param a_idx The array index, cast to size_t to ensure unsigned.
+ */
+#define RT_SAFE_SUBSCRIPT(a_Array, a_idx) (a_Array)[(size_t)(a_idx) % RT_ELEMENTS(a_Array)]
+
+/** @def RT_SAFE_SUBSCRIPT32
+ * Safe array subscript using modulo and uint32_t cast.
+ * @param a_Array The array.
+ * @param a_idx The array index, cast to size_t to ensure unsigned.
+ * @note Only consider using this if array size is not power of two.
+ */
+#define RT_SAFE_SUBSCRIPT32(a_Array, a_idx) (a_Array)[(uint32_t)(a_idx) % RT_ELEMENTS(a_Array)]
+
+/** @def RT_SAFE_SUBSCRIPT16
+ * Safe array subscript using modulo and uint16_t cast.
+ * @param a_Array The array.
+ * @param a_idx The array index, cast to size_t to ensure unsigned.
+ * @note Only consider using this if array size is not power of two.
+ */
+#define RT_SAFE_SUBSCRIPT16(a_Array, a_idx) (a_Array)[(uint16_t)(a_idx) % RT_ELEMENTS(a_Array)]
+
+/** @def RT_SAFE_SUBSCRIPT8
+ * Safe array subscript using modulo and uint8_t cast.
+ * @param a_Array The array.
+ * @param a_idx The array index, cast to size_t to ensure unsigned.
+ * @note Only consider using this if array size is not power of two.
+ */
+#define RT_SAFE_SUBSCRIPT8(a_Array, a_idx) (a_Array)[(uint8_t)(a_idx) % RT_ELEMENTS(a_Array)]
+
+/** @def RT_SAFE_SUBSCRIPT_NC
+ * Safe array subscript using modulo but no cast.
+ * @param a_Array The array.
+ * @param a_idx The array index - assumes unsigned type.
+ * @note Only consider using this if array size is not power of two.
+ */
+#define RT_SAFE_SUBSCRIPT_NC(a_Array, a_idx) (a_Array)[(a_idx) % RT_ELEMENTS(a_Array)]
+
+/** @def RT_FLEXIBLE_ARRAY
+ * What to up inside the square brackets when declaring a structure member
+ * with a flexible size.
+ *
+ * @note RT_FLEXIBLE_ARRAY_EXTENSION must always preceed the type, unless
+ * it's C-only code.
+ *
+ * @note Use RT_UOFFSETOF() to calculate the structure size.
+ *
+ * @note Never do 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)) /* not tested 7.x, but hope it works with __extension__ too. */ \
+ || defined(__WATCOMC__) /* openwatcom 1.9 supports it, we don't care about older atm. */ \
+ || RT_CLANG_PREREQ_EX(3, 4, 0) /* Only tested clang v3.4, support is probably older. */
+# define RT_FLEXIBLE_ARRAY
+# if defined(__cplusplus) && defined(_MSC_VER)
+# pragma warning(disable:4200) /* -wd4200 does not work with VS2010 */
+# pragma warning(disable:4815) /* -wd4815 does not work with VS2019 */
+# 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_EXTENSION
+ * A trick to make GNU C++ quietly accept flexible arrays in C++ code when
+ * pedantic warnings are enabled. Put this on the line before the flexible
+ * array. */
+#if (RT_GNUC_PREREQ(7, 0) && defined(__cplusplus)) || defined(DOXGYEN_RUNNING)
+# define RT_FLEXIBLE_ARRAY_EXTENSION RT_GCC_EXTENSION
+#else
+# define RT_FLEXIBLE_ARRAY_EXTENSION
+#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
+
+/** @def RT_UNION_NM
+ * For compilers (like DTrace) that does not grok nameless unions, we have a
+ * little hack to make them palatable.
+ */
+/** @def RT_STRUCT_NM
+ * For compilers (like DTrace) that does not grok nameless structs (it is
+ * non-standard C++), we have a little hack to make them palatable.
+ */
+#ifdef IPRT_WITHOUT_NAMED_UNIONS_AND_STRUCTS
+# define RT_UNION_NM(a_Nm) a_Nm
+# define RT_STRUCT_NM(a_Nm) a_Nm
+#else
+# define RT_UNION_NM(a_Nm)
+# define RT_STRUCT_NM(a_Nm)
+#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) ( (uint8_t)((a) & 0xff) )
+/** @def RT_BYTE2
+ * Gets the second byte of something. */
+#define RT_BYTE2(a) ( (uint8_t)(((a) >> 8) & 0xff) )
+/** @def RT_BYTE3
+ * Gets the second byte of something. */
+#define RT_BYTE3(a) ( (uint8_t)(((a) >> 16) & 0xff) )
+/** @def RT_BYTE4
+ * Gets the fourth byte of something. */
+#define RT_BYTE4(a) ( (uint8_t)(((a) >> 24) & 0xff) )
+/** @def RT_BYTE5
+ * Gets the fifth byte of something. */
+#define RT_BYTE5(a) ( (uint8_t)(((a) >> 32) & 0xff) )
+/** @def RT_BYTE6
+ * Gets the sixth byte of something. */
+#define RT_BYTE6(a) ( (uint8_t)(((a) >> 40) & 0xff) )
+/** @def RT_BYTE7
+ * Gets the seventh byte of something. */
+#define RT_BYTE7(a) ( (uint8_t)(((a) >> 48) & 0xff) )
+/** @def RT_BYTE8
+ * Gets the eight byte of something. */
+#define RT_BYTE8(a) ( (uint8_t)(((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 \
+ | (uint64_t)((uint8_t)(b3)) << 24 \
+ | (uint64_t)((uint8_t)(b2)) << 16 \
+ | (uint64_t)((uint8_t)(b1)) << 8 \
+ | (uint64_t) (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 \
+ | (uint32_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 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 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 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_S64
+ * Reverses the byte order of an int64_t value. */
+#define RT_BSWAP_S64(i64) ((int64_t)RT_BSWAP_U64((uint64_t)i64))
+
+/** @def RT_BSWAP_S32
+ * Reverses the byte order of an int32_t value. */
+#define RT_BSWAP_S32(i32) ((int32_t)RT_BSWAP_U32((uint32_t)i32))
+
+/** @def RT_BSWAP_S16
+ * Reverses the byte order of an int16_t value. */
+#define RT_BSWAP_S16(i16) ((int16_t)RT_BSWAP_U16((uint16_t)i16))
+
+
+/** @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_BSWAP_S64_C
+ * Reverses the byte order of an int64_t constant. */
+#define RT_BSWAP_S64_C(i64) ((int64_t)RT_MAKE_U64(RT_BSWAP_U32_C((uint64_t)(i64) >> 32), RT_BSWAP_U32_C((uint32_t)(i64))))
+
+/** @def RT_BSWAP_S32_C
+ * Reverses the byte order of an int32_t constant. */
+#define RT_BSWAP_S32_C(i32) ((int32_t)RT_MAKE_U32_FROM_U8(RT_BYTE4(i32), RT_BYTE3(i32), RT_BYTE2(i32), RT_BYTE1(i)))
+
+/** @def RT_BSWAP_S16_C
+ * Reverses the byte order of an uint16_t constant. */
+#define RT_BSWAP_S16_C(i16) ((int16_t)RT_MAKE_U16(RT_HIBYTE(i16), RT_LOBYTE(i16)))
+
+
+
+/** @name Host to/from little endian.
+ * @note Typically requires iprt/asm.h to be included.
+ * @{ */
+
+/** @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_H2LE_S64
+ * Converts an int64_t value from host to little endian byte order. */
+#ifdef RT_BIG_ENDIAN
+# define RT_H2LE_S64(i64) RT_BSWAP_S64(i64)
+#else
+# define RT_H2LE_S64(i64) (i64)
+#endif
+
+/** @def RT_H2LE_S64_C
+ * Converts an int64_t constant from host to little endian byte order. */
+#ifdef RT_BIG_ENDIAN
+# define RT_H2LE_S64_C(i64) RT_BSWAP_S64_C(i64)
+#else
+# define RT_H2LE_S64_C(i64) (i64)
+#endif
+
+/** @def RT_H2LE_S32
+ * Converts an int32_t value from host to little endian byte order. */
+#ifdef RT_BIG_ENDIAN
+# define RT_H2LE_S32(i32) RT_BSWAP_S32(i32)
+#else
+# define RT_H2LE_S32(i32) (i32)
+#endif
+
+/** @def RT_H2LE_S32_C
+ * Converts an int32_t constant from host to little endian byte order. */
+#ifdef RT_BIG_ENDIAN
+# define RT_H2LE_S32_C(i32) RT_BSWAP_S32_C(i32)
+#else
+# define RT_H2LE_S32_C(i32) (i32)
+#endif
+
+/** @def RT_H2LE_S16
+ * Converts an int16_t value from host to little endian byte order. */
+#ifdef RT_BIG_ENDIAN
+# define RT_H2LE_S16(i16) RT_BSWAP_S16(i16)
+#else
+# define RT_H2LE_S16(i16) (i16)
+#endif
+
+/** @def RT_H2LE_S16_C
+ * Converts an int16_t constant from host to little endian byte order. */
+#ifdef RT_BIG_ENDIAN
+# define RT_H2LE_S16_C(i16) RT_BSWAP_S16_C(i16)
+#else
+# define RT_H2LE_S16_C(i16) (i16)
+#endif
+
+/** @def RT_LE2H_S64
+ * Converts an int64_t value from little endian to host byte order. */
+#ifdef RT_BIG_ENDIAN
+# define RT_LE2H_S64(i64) RT_BSWAP_S64(i64)
+#else
+# define RT_LE2H_S64(i64) (i64)
+#endif
+
+/** @def RT_LE2H_S64_C
+ * Converts an int64_t constant from little endian to host byte order. */
+#ifdef RT_BIG_ENDIAN
+# define RT_LE2H_S64_C(i64) RT_BSWAP_S64_C(i64)
+#else
+# define RT_LE2H_S64_C(i64) (i64)
+#endif
+
+/** @def RT_LE2H_S32
+ * Converts an int32_t value from little endian to host byte order. */
+#ifdef RT_BIG_ENDIAN
+# define RT_LE2H_S32(i32) RT_BSWAP_S32(i32)
+#else
+# define RT_LE2H_S32(i32) (i32)
+#endif
+
+/** @def RT_LE2H_S32_C
+ * Converts an int32_t constant from little endian to host byte order. */
+#ifdef RT_BIG_ENDIAN
+# define RT_LE2H_S32_C(i32) RT_BSWAP_S32_C(i32)
+#else
+# define RT_LE2H_S32_C(i32) (i32)
+#endif
+
+/** @def RT_LE2H_S16
+ * Converts an int16_t value from little endian to host byte order. */
+#ifdef RT_BIG_ENDIAN
+# define RT_LE2H_S16(i16) RT_BSWAP_S16(i16)
+#else
+# define RT_LE2H_S16(i16) (i16)
+#endif
+
+/** @def RT_LE2H_S16_C
+ * Converts an int16_t constant from little endian to host byte order. */
+#ifdef RT_BIG_ENDIAN
+# define RT_LE2H_S16_C(i16) RT_BSWAP_S16_C(i16)
+#else
+# define RT_LE2H_S16_C(i16) (i16)
+#endif
+
+/** @} */
+
+/** @name Host to/from big endian.
+ * @note Typically requires iprt/asm.h to be included.
+ * @{ */
+
+/** @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_H2BE_S64
+ * Converts an int64_t value from host to big endian byte order. */
+#ifdef RT_BIG_ENDIAN
+# define RT_H2BE_S64(i64) (i64)
+#else
+# define RT_H2BE_S64(i64) RT_BSWAP_S64(i64)
+#endif
+
+/** @def RT_H2BE_S64_C
+ * Converts an int64_t constant from host to big endian byte order. */
+#ifdef RT_BIG_ENDIAN
+# define RT_H2BE_S64_C(i64) (i64)
+#else
+# define RT_H2BE_S64_C(i64) RT_BSWAP_S64_C(i64)
+#endif
+
+/** @def RT_H2BE_S32
+ * Converts an int32_t value from host to big endian byte order. */
+#ifdef RT_BIG_ENDIAN
+# define RT_H2BE_S32(i32) (i32)
+#else
+# define RT_H2BE_S32(i32) RT_BSWAP_S32(i32)
+#endif
+
+/** @def RT_H2BE_S32_C
+ * Converts an int32_t constant from host to big endian byte order. */
+#ifdef RT_BIG_ENDIAN
+# define RT_H2BE_S32_C(i32) (i32)
+#else
+# define RT_H2BE_S32_C(i32) RT_BSWAP_S32_C(i32)
+#endif
+
+/** @def RT_H2BE_S16
+ * Converts an int16_t value from host to big endian byte order. */
+#ifdef RT_BIG_ENDIAN
+# define RT_H2BE_S16(i16) (i16)
+#else
+# define RT_H2BE_S16(i16) RT_BSWAP_S16(i16)
+#endif
+
+/** @def RT_H2BE_S16_C
+ * Converts an int16_t constant from host to big endian byte order. */
+#ifdef RT_BIG_ENDIAN
+# define RT_H2BE_S16_C(i16) (i16)
+#else
+# define RT_H2BE_S16_C(i16) RT_BSWAP_S16_C(i16)
+#endif
+
+/** @def RT_BE2H_S64
+ * Converts an int64_t value from big endian to host byte order. */
+#ifdef RT_BIG_ENDIAN
+# define RT_BE2H_S64(i64) (i64)
+#else
+# define RT_BE2H_S64(i64) RT_BSWAP_S64(i64)
+#endif
+
+/** @def RT_BE2H_S64
+ * Converts an int64_t constant from big endian to host byte order. */
+#ifdef RT_BIG_ENDIAN
+# define RT_BE2H_S64_C(i64) (i64)
+#else
+# define RT_BE2H_S64_C(i64) RT_BSWAP_S64_C(i64)
+#endif
+
+/** @def RT_BE2H_S32
+ * Converts an int32_t value from big endian to host byte order. */
+#ifdef RT_BIG_ENDIAN
+# define RT_BE2H_S32(i32) (i32)
+#else
+# define RT_BE2H_S32(i32) RT_BSWAP_S32(i32)
+#endif
+
+/** @def RT_BE2H_S32_C
+ * Converts an int32_t value from big endian to host byte order. */
+#ifdef RT_BIG_ENDIAN
+# define RT_BE2H_S32_C(i32) (i32)
+#else
+# define RT_BE2H_S32_C(i32) RT_BSWAP_S32_C(i32)
+#endif
+
+/** @def RT_BE2H_S16
+ * Converts an int16_t value from big endian to host byte order. */
+#ifdef RT_BIG_ENDIAN
+# define RT_BE2H_S16(i16) (i16)
+#else
+# define RT_BE2H_S16(i16) RT_BSWAP_S16(i16)
+#endif
+
+/** @def RT_BE2H_S16_C
+ * Converts an int16_t constant from big endian to host byte order. */
+#ifdef RT_BIG_ENDIAN
+# define RT_BE2H_S16_C(i16) (i16)
+#else
+# define RT_BE2H_S16_C(i16) RT_BSWAP_S16_C(i16)
+#endif
+/** @} */
+
+/** @name Host to/from network byte order.
+ * @note Typically requires iprt/asm.h to be included.
+ * @{ */
+
+/** @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)
+
+/** @def RT_H2N_S64
+ * Converts an int64_t value from host to network byte order. */
+#define RT_H2N_S64(i64) RT_H2BE_S64(i64)
+
+/** @def RT_H2N_S64_C
+ * Converts an int64_t constant from host to network byte order. */
+#define RT_H2N_S64_C(i64) RT_H2BE_S64_C(i64)
+
+/** @def RT_H2N_S32
+ * Converts an int32_t value from host to network byte order. */
+#define RT_H2N_S32(i32) RT_H2BE_S32(i32)
+
+/** @def RT_H2N_S32_C
+ * Converts an int32_t constant from host to network byte order. */
+#define RT_H2N_S32_C(i32) RT_H2BE_S32_C(i32)
+
+/** @def RT_H2N_S16
+ * Converts an int16_t value from host to network byte order. */
+#define RT_H2N_S16(i16) RT_H2BE_S16(i16)
+
+/** @def RT_H2N_S16_C
+ * Converts an int16_t constant from host to network byte order. */
+#define RT_H2N_S16_C(i16) RT_H2BE_S16_C(i16)
+
+/** @def RT_N2H_S64
+ * Converts an int64_t value from network to host byte order. */
+#define RT_N2H_S64(i64) RT_BE2H_S64(i64)
+
+/** @def RT_N2H_S64_C
+ * Converts an int64_t constant from network to host byte order. */
+#define RT_N2H_S64_C(i64) RT_BE2H_S64_C(i64)
+
+/** @def RT_N2H_S32
+ * Converts an int32_t value from network to host byte order. */
+#define RT_N2H_S32(i32) RT_BE2H_S32(i32)
+
+/** @def RT_N2H_S32_C
+ * Converts an int32_t constant from network to host byte order. */
+#define RT_N2H_S32_C(i32) RT_BE2H_S32_C(i32)
+
+/** @def RT_N2H_S16
+ * Converts an int16_t value from network to host byte order. */
+#define RT_N2H_S16(i16) RT_BE2H_S16(i16)
+
+/** @def RT_N2H_S16_C
+ * Converts an int16_t value from network to host byte order. */
+#define RT_N2H_S16_C(i16) RT_BE2H_S16_C(i16)
+
+/** @} */
+
+
+/*
+ * 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, var11)
+/** @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). */
+# elif defined(RT_ARCH_ARM32) || defined(RT_ARCH_ARM64)
+# define RT_BREAKPOINT() __asm__ __volatile__("brk #0x1\n\t")
+# 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 week expressed in nanoseconds (64-bit). */
+#define RT_NS_1WEEK UINT64_C(604800000000000)
+/** 1 day expressed in nanoseconds (64-bit). */
+#define RT_NS_1DAY UINT64_C(86400000000000)
+/** 1 hour expressed in nanoseconds (64-bit). */
+#define RT_NS_1HOUR UINT64_C(3600000000000)
+/** 30 minutes expressed in nanoseconds (64-bit). */
+#define RT_NS_30MIN UINT64_C(1800000000000)
+/** 5 minutes expressed in nanoseconds (64-bit). */
+#define RT_NS_5MIN UINT64_C(300000000000)
+/** 1 minute expressed in nanoseconds (64-bit). */
+#define RT_NS_1MIN UINT64_C(60000000000)
+/** 45 seconds expressed in nanoseconds (64-bit). */
+#define RT_NS_45SEC UINT64_C(45000000000)
+/** 30 seconds expressed in nanoseconds (64-bit). */
+#define RT_NS_30SEC UINT64_C(30000000000)
+/** 20 seconds expressed in nanoseconds (64-bit). */
+#define RT_NS_20SEC UINT64_C(20000000000)
+/** 15 seconds expressed in nanoseconds (64-bit). */
+#define RT_NS_15SEC UINT64_C(15000000000)
+/** 10 seconds expressed in nanoseconds (64-bit). */
+#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)
+/** 8 millsecond expressed in nanoseconds. */
+#define RT_NS_8MS UINT32_C(8000000)
+/** 2 millsecond expressed in nanoseconds. */
+#define RT_NS_2MS UINT32_C(2000000)
+/** 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 week expressed in microseconds (64-bit). */
+#define RT_US_1WEEK UINT64_C(604800000000)
+/** 1 day expressed in microseconds (64-bit). */
+#define RT_US_1DAY UINT64_C(86400000000)
+/** 1 hour expressed in microseconds. */
+#define RT_US_1HOUR UINT32_C(3600000000)
+/** 30 minutes expressed in microseconds. */
+#define RT_US_30MIN UINT32_C(1800000000)
+/** 5 minutes expressed in microseconds. */
+#define RT_US_5MIN UINT32_C(300000000)
+/** 1 minute expressed in microseconds. */
+#define RT_US_1MIN UINT32_C(60000000)
+/** 45 seconds expressed in microseconds. */
+#define RT_US_45SEC UINT32_C(45000000)
+/** 30 seconds expressed in microseconds. */
+#define RT_US_30SEC UINT32_C(30000000)
+/** 20 seconds expressed in microseconds. */
+#define RT_US_20SEC UINT32_C(20000000)
+/** 15 seconds expressed in microseconds. */
+#define RT_US_15SEC UINT32_C(15000000)
+/** 10 seconds expressed in microseconds. */
+#define RT_US_10SEC UINT32_C(10000000)
+/** 5 seconds expressed in microseconds. */
+#define RT_US_5SEC UINT32_C(5000000)
+/** 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)
+/** 30 minutes expressed in microseconds - 64-bit type. */
+#define RT_US_30MIN_64 UINT64_C(1800000000)
+/** 5 minutes expressed in microseconds - 64-bit type. */
+#define RT_US_5MIN_64 UINT64_C(300000000)
+/** 1 minute expressed in microseconds - 64-bit type. */
+#define RT_US_1MIN_64 UINT64_C(60000000)
+/** 45 seconds expressed in microseconds - 64-bit type. */
+#define RT_US_45SEC_64 UINT64_C(45000000)
+/** 30 seconds expressed in microseconds - 64-bit type. */
+#define RT_US_30SEC_64 UINT64_C(30000000)
+/** 20 seconds expressed in microseconds - 64-bit type. */
+#define RT_US_20SEC_64 UINT64_C(20000000)
+/** 15 seconds expressed in microseconds - 64-bit type. */
+#define RT_US_15SEC_64 UINT64_C(15000000)
+/** 10 seconds expressed in microseconds - 64-bit type. */
+#define RT_US_10SEC_64 UINT64_C(10000000)
+/** 5 seconds expressed in microseconds - 64-bit type. */
+#define RT_US_5SEC_64 UINT64_C(5000000)
+/** 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 week expressed in milliseconds. */
+#define RT_MS_1WEEK UINT32_C(604800000)
+/** 1 day expressed in milliseconds. */
+#define RT_MS_1DAY UINT32_C(86400000)
+/** 1 hour expressed in milliseconds. */
+#define RT_MS_1HOUR UINT32_C(3600000)
+/** 30 minutes expressed in milliseconds. */
+#define RT_MS_30MIN UINT32_C(1800000)
+/** 5 minutes expressed in milliseconds. */
+#define RT_MS_5MIN UINT32_C(300000)
+/** 1 minute expressed in milliseconds. */
+#define RT_MS_1MIN UINT32_C(60000)
+/** 45 seconds expressed in milliseconds. */
+#define RT_MS_45SEC UINT32_C(45000)
+/** 30 seconds expressed in milliseconds. */
+#define RT_MS_30SEC UINT32_C(30000)
+/** 20 seconds expressed in milliseconds. */
+#define RT_MS_20SEC UINT32_C(20000)
+/** 15 seconds expressed in milliseconds. */
+#define RT_MS_15SEC UINT32_C(15000)
+/** 10 seconds expressed in milliseconds. */
+#define RT_MS_10SEC UINT32_C(10000)
+/** 5 seconds expressed in milliseconds. */
+#define RT_MS_5SEC UINT32_C(5000)
+/** 1 second expressed in milliseconds. */
+#define RT_MS_1SEC UINT32_C(1000)
+
+/** 1 week expressed in milliseconds - 64-bit type. */
+#define RT_MS_1WEEK_64 UINT64_C(604800000)
+/** 1 day expressed in milliseconds - 64-bit type. */
+#define RT_MS_1DAY_64 UINT64_C(86400000)
+/** 1 hour expressed in milliseconds - 64-bit type. */
+#define RT_MS_1HOUR_64 UINT64_C(3600000)
+/** 30 minutes expressed in milliseconds - 64-bit type. */
+#define RT_MS_30MIN_64 UINT64_C(1800000)
+/** 5 minutes expressed in milliseconds - 64-bit type. */
+#define RT_MS_5MIN_64 UINT64_C(300000)
+/** 1 minute expressed in milliseconds - 64-bit type. */
+#define RT_MS_1MIN_64 UINT64_C(60000)
+/** 45 seconds expressed in milliseconds - 64-bit type. */
+#define RT_MS_45SEC_64 UINT64_C(45000)
+/** 30 seconds expressed in milliseconds - 64-bit type. */
+#define RT_MS_30SEC_64 UINT64_C(30000)
+/** 20 seconds expressed in milliseconds - 64-bit type. */
+#define RT_MS_20SEC_64 UINT64_C(20000)
+/** 15 seconds expressed in milliseconds - 64-bit type. */
+#define RT_MS_15SEC_64 UINT64_C(15000)
+/** 10 seconds expressed in milliseconds - 64-bit type. */
+#define RT_MS_10SEC_64 UINT64_C(10000)
+/** 5 seconds expressed in milliseconds - 64-bit type. */
+#define RT_MS_5SEC_64 UINT64_C(5000)
+/** 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 RT_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) )
+# elif defined(RT_OS_LINUX) /* May use 5-level paging (see Documentation/x86/x86_64/mm.rst). */
+# define RT_VALID_PTR(ptr) ( (uintptr_t)(ptr) >= 0x1000U /* one invalid page at the bottom */ \
+ && !((uintptr_t)(ptr) & 0xff00000000000000ULL) )
+# else
+# define RT_VALID_PTR(ptr) ( (uintptr_t)(ptr) >= 0x1000U \
+ && !((uintptr_t)(ptr) & 0xffff800000000000ULL) )
+# endif
+# else /* !IN_RING3 */
+# if defined(RT_OS_LINUX) /* May use 5-level paging (see Documentation/x86/x86_64/mm.rst). */
+# if 1 /* User address are no longer considered valid in kernel mode (SMAP, etc). */
+# define RT_VALID_PTR(ptr) ((uintptr_t)(ptr) - 0xff00000000000000ULL < 0x00ffffffffe00000ULL) /* 2MB invalid space at the top */
+# else
+# define RT_VALID_PTR(ptr) ( (uintptr_t)(ptr) + 0x200000 >= 0x201000U /* one invalid page at the bottom and 2MB at the top */ \
+ && ( ((uintptr_t)(ptr) & 0xff00000000000000ULL) == 0xff00000000000000ULL \
+ || ((uintptr_t)(ptr) & 0xff00000000000000ULL) == 0) )
+# endif
+# else
+# define RT_VALID_PTR(ptr) ( (uintptr_t)(ptr) + 0x1000U >= 0x2000U \
+ && ( ((uintptr_t)(ptr) & 0xffff800000000000ULL) == 0xffff800000000000ULL \
+ || ((uintptr_t)(ptr) & 0xffff800000000000ULL) == 0) )
+# endif
+# 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_ARM32) || defined(RT_ARCH_ARM64)
+/* 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
+
+/** @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)) \
+ && RT_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)
+
+
+#if (!defined(__GNUC__) && !defined(__PRETTY_FUNCTION__)) || defined(DOXYGEN_RUNNING)
+# if defined(_MSC_VER) || defined(DOXYGEN_RUNNING)
+/** With GNU C we'd like to use the builtin __PRETTY_FUNCTION__, so define that
+ * for the other compilers. */
+# 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(RT_ARCH_ARM64) && !defined(RT_ARCH_ARM32)) \
+ || 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 one of the RT_MSC_VER_XXX MSC version values if the compiler have
+ * and uses intrin.h. Otherwise it is 0. */
+#ifdef _MSC_VER
+# if _MSC_VER >= RT_MSC_VER_VS2019 /* Visual C++ v14.2 */
+# define RT_INLINE_ASM_USES_INTRIN RT_MSC_VER_VS2019
+# elif _MSC_VER >= RT_MSC_VER_VS2017 /* Visual C++ v14.1 */
+# define RT_INLINE_ASM_USES_INTRIN RT_MSC_VER_VS2017
+# elif _MSC_VER >= RT_MSC_VER_VS2015 /* Visual C++ v14.0 */
+# define RT_INLINE_ASM_USES_INTRIN RT_MSC_VER_VS2015
+# elif _MSC_VER >= RT_MSC_VER_VS2013 /* Visual C++ v12.0 */
+# define RT_INLINE_ASM_USES_INTRIN RT_MSC_VER_VS2013
+# elif _MSC_VER >= RT_MSC_VER_VS2012 /* Visual C++ v11.0 */
+# define RT_INLINE_ASM_USES_INTRIN RT_MSC_VER_VS2012
+# elif _MSC_VER >= RT_MSC_VER_VS2010 /* Visual C++ v10.0 */
+# define RT_INLINE_ASM_USES_INTRIN RT_MSC_VER_VS2010
+# elif _MSC_VER >= RT_MSC_VER_VS2008 /* Visual C++ v9.0 */
+# define RT_INLINE_ASM_USES_INTRIN RT_MSC_VER_VS2008
+# elif _MSC_VER >= RT_MSC_VER_VS2005 /* Visual C++ v8.0 */
+# define RT_INLINE_ASM_USES_INTRIN RT_MSC_VER_VS2005
+# endif
+#endif
+#ifndef RT_INLINE_ASM_USES_INTRIN
+# define RT_INLINE_ASM_USES_INTRIN 0
+#endif
+
+#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. */
+#define RT_MSC_VER_VS2017 (1910) /**< Visual Studio 2017. */
+#define RT_MSC_VER_VC141 RT_MSC_VER_VS2017 /**< Visual C++ 14.1, aka Visual Studio 2017. */
+#define RT_MSC_VER_VS2019 (1920) /**< Visual Studio 2017. */
+#define RT_MSC_VER_VC142 RT_MSC_VER_VS2019 /**< Visual C++ 14.2, aka Visual Studio 2019. */
+
+/** @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_DATA_IS_FAR
+ * 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_DATA_IS_FAR 1
+#else
+# define RT_DATA_IS_FAR 0
+#endif
+
+/** @def RT_FAR
+ * For indicating far pointers in 16-bit code.
+ * Does nothing in 32-bit and 64-bit code. */
+/** @def RT_NEAR
+ * For indicating near pointers in 16-bit code.
+ * Does nothing in 32-bit and 64-bit code. */
+/** @def RT_FAR_CODE
+ * For indicating far 16-bit functions.
+ * Does nothing in 32-bit and 64-bit code. */
+/** @def RT_NEAR_CODE
+ * For indicating near 16-bit functions.
+ * Does nothing in 32-bit and 64-bit code. */
+/** @def RT_FAR_DATA
+ * For indicating far 16-bit external data, i.e. in a segment other than DATA16.
+ * Does nothing in 32-bit and 64-bit code. */
+#if ARCH_BITS == 16
+# define RT_FAR __far
+# define RT_NEAR __near
+# define RT_FAR_CODE __far
+# define RT_NEAR_CODE __near
+# define RT_FAR_DATA __far
+#else
+# define RT_FAR
+# define RT_NEAR
+# define RT_FAR_CODE
+# define RT_NEAR_CODE
+# define RT_FAR_DATA
+#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 /* !IPRT_INCLUDED_cdefs_h */
+
diff --git a/include/iprt/cdrom.h b/include/iprt/cdrom.h
new file mode 100644
index 00000000..78dfecba
--- /dev/null
+++ b/include/iprt/cdrom.h
@@ -0,0 +1,195 @@
+/** @file
+ * IPRT CD/DVD/BD-ROM Drive API.
+ */
+
+/*
+ * Copyright (C) 2012-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_cdrom_h
+#define IPRT_INCLUDED_cdrom_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_cdrom IPRT CD/DVD/BD-ROM Drive API
+ * @ingroup grp_rt
+ *
+ * The user of the API is currently resposible for serializing calls to it.
+ *
+ * @{
+ */
+
+/** CD-ROM drive handle. */
+typedef struct RTCDROMINT *RTCDROM;
+/** Pointer to a CD-ROM handle. */
+typedef RTCDROM *PRTCDROM;
+/** NIL CD-ROM handle value. */
+#define NIL_RTCDROM ((RTCDROM)0)
+
+
+/** @name CD-ROM open flags.
+ * @{ */
+#define RTCDROM_O_READ RT_BIT(0)
+#define RTCDROM_O_WRITE RT_BIT(1)
+#define RTCDROM_O_CONTROL RT_BIT(2)
+#define RTCDROM_O_QUERY RT_BIT(3)
+#define RTCDROM_O_ALL_ACCESS (RTCDROM_O_READ | RTCDROM_O_WRITE | RTCDROM_O_CONTROL | RTCDROM_O_QUERY)
+/** @} */
+
+/**
+ * Opens the CD-ROM drive (by name).
+ *
+ * @returns IPRT status code.
+ * @param pszName The CD-ROM name (path).
+ * @param fFlags Open flags, see RTCDROM_O_XXX.
+ * @param phCdrom Where to return the CDROM handle.
+ */
+RTDECL(int) RTCdromOpen(const char *pszName, uint32_t fFlags, PRTCDROM phCdrom);
+
+/**
+ * Retains a reference to the CD-ROM handle.
+ *
+ * @returns New reference count, UINT32_MAX on invalid handle (asserted).
+ * @param hCdrom The CD-ROM handle to retain.
+ */
+RTDECL(uint32_t) RTCdromRetain(RTCDROM hCdrom);
+
+/**
+ * Releases a reference to the CD-ROM handle.
+ *
+ * When the reference count reaches zero, the CD-ROM handle is destroy.
+ *
+ * @returns New reference count, UINT32_MAX on invalid handle (asserted).
+ * @param hCdrom The CD-ROM handle to retain.
+ */
+RTDECL(uint32_t) RTCdromRelease(RTCDROM hCdrom);
+
+/**
+ * Query the primary mount point of the CD-ROM.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_BUFFER_OVERFLOW if the buffer is too small. The buffer will be
+ * set to an empty string if possible.
+ *
+ * @param hCdrom The CD-ROM handle.
+ * @param pszMountPoint Where to return the mount point.
+ * @param cbMountPoint The size of the mount point buffer.
+ */
+RTDECL(int) RTCdromQueryMountPoint(RTCDROM hCdrom, char *pszMountPoint, size_t cbMountPoint);
+
+/**
+ * Unmounts all file-system mounts related to the CD-ROM.
+ *
+ * @returns IPRT status code.
+ * @param hCdrom The CD-ROM handle.
+ */
+RTDECL(int) RTCdromUnmount(RTCDROM hCdrom);
+
+/**
+ * Ejects the CD-ROM from the drive.
+ *
+ * @returns IPRT status code.
+ * @param hCdrom The CD-ROM handle.
+ * @param fForce If set, unmount and unlock will be performed.
+ */
+RTDECL(int) RTCdromEject(RTCDROM hCdrom, bool fForce);
+
+/**
+ * Locks the CD-ROM so it cannot be ejected by the user or system.
+ *
+ * @returns IPRT status code.
+ * @param hCdrom The CD-ROM handle.
+ */
+RTDECL(int) RTCdromLock(RTCDROM hCdrom);
+
+/**
+ * Unlocks the CD-ROM so it can be ejected by the user or system.
+ *
+ * @returns IPRT status code.
+ * @param hCdrom The CD-ROM handle.
+ */
+RTDECL(int) RTCdromUnlock(RTCDROM hCdrom);
+
+
+/** @name Ordinal / Enumeration
+ * @{ */
+/**
+ * Get the current number of CD-ROMs.
+ *
+ * This is handy for using RTCdromOpenByOrdinal() or RTCdromOrdinalToName() to
+ * perform some kind of enumeration of all drives.
+ *
+ * @returns Number of CD-ROM drivers in the system.
+ */
+RTDECL(unsigned) RTCdromCount(void);
+
+/**
+ * Translates an CD-ROM drive ordinal number to a path suitable for RTCdromOpen.
+ *
+ * @returns IRPT status code.
+ * @retval VINF_SUCCESS on success, with the name in the buffer.
+ * @retval VERR_BUFFER_OVERFLOW if the buffer is too small. The buffer will be
+ * set to an empty string if possible, in order to prevent trouble.
+ * @retval VERR_OUT_OF_RANGE if the ordinal number is higher than the current
+ * number of CD-ROM drives.
+ *
+ * @param iCdrom The CD-ROM drive ordinal. Starts at 0.
+ * @param pszName Where to return the name (path).
+ * @param cbName Size of the output buffer.
+ *
+ * @remarks The ordinals are volatile. They may change as drives are attached
+ * or detected from the host.
+ */
+RTDECL(int) RTCdromOrdinalToName(unsigned iCdrom, char *pszName, size_t cbName);
+
+/**
+ * Combination of RTCdromOrdinalToName() and RTCdromOpen().
+ *
+ * @returns IPRT status code.
+ * @param iCdrom The CD-ROM number.
+ * @param fFlags Open flags, see RTCDROM_O_XXX.
+ * @param phCdrom Where to return the CDROM handle .
+ * @remarks See remarks on RTCdromOrdinalToName().
+ */
+RTDECL(int) RTCdromOpenByOrdinal(unsigned iCdrom, uint32_t fFlags, PRTCDROM phCdrom);
+
+/** @} */
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_cdrom_h */
+
diff --git a/include/iprt/cidr.h b/include/iprt/cidr.h
new file mode 100644
index 00000000..ed9d558d
--- /dev/null
+++ b/include/iprt/cidr.h
@@ -0,0 +1,76 @@
+/** @file
+ * IPRT - TCP/IP.
+ */
+
+/*
+ * Copyright (C) 2008-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_cidr_h
+#define IPRT_INCLUDED_cidr_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+#include <iprt/net.h>
+
+/** @defgroup grp_rt_cidr RTCidr - Classless Inter-Domain Routing notation
+ * @ingroup grp_rt
+ * @{
+ */
+RT_C_DECLS_BEGIN
+
+/**
+ * Parse a string which contains an IP address in CIDR (Classless
+ * Inter-Domain Routing) notation.
+ *
+ * @warning The network address and the network mask are returned in
+ * @b host(!) byte order. This is different from all the other
+ * RTNetStrTo* functions.
+ *
+ * @deprecated This function is superseded by RTNetStrToIPv4Cidr()
+ * that provides a better API consistent with other functions
+ * from that family. It returns the prefix length, if you need a
+ * netmask, you can obtain it with RTNetPrefixToMaskIPv4().
+ *
+ * @return iprt status code.
+ *
+ * @param pszAddress The IP address in CIDR specificaion.
+ * @param pNetwork The determined IP address / network in host byte order.
+ * @param pNetmask The determined netmask in host byte order.
+ */
+RTDECL(int) RTCidrStrToIPv4(const char *pszAddress, PRTNETADDRIPV4 pNetwork, PRTNETADDRIPV4 pNetmask);
+
+RT_C_DECLS_END
+/** @} */
+
+#endif /* !IPRT_INCLUDED_cidr_h */
diff --git a/include/iprt/circbuf.h b/include/iprt/circbuf.h
new file mode 100644
index 00000000..bb107189
--- /dev/null
+++ b/include/iprt/circbuf.h
@@ -0,0 +1,165 @@
+/** @file
+ * IPRT - Lock Free Circular Buffer
+ */
+
+/*
+ * Copyright (C) 2010-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_circbuf_h
+#define IPRT_INCLUDED_circbuf_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+
+/** @defgroup grp_rt_circbuf RTCircBuf - Lock Free Circular Buffer
+ * @ingroup grp_rt
+ *
+ * Implementation of a lock free circular buffer which could be used in a multi
+ * threaded environment. Note that only the acquire, release and getter
+ * functions are threading aware. So don't use reset if the circular buffer is
+ * still in use.
+ *
+ * @{
+ */
+
+RT_C_DECLS_BEGIN
+
+/** Pointer to a circular buffer (abstract). */
+typedef struct RTCIRCBUF *PRTCIRCBUF;
+
+/**
+ * Create a circular buffer.
+ *
+ * @returns IPRT status code.
+ *
+ * @param ppBuf Where to store the buffer.
+ * @param cbSize The size of the new buffer.
+ */
+RTDECL(int) RTCircBufCreate(PRTCIRCBUF *ppBuf, size_t cbSize);
+
+/**
+ * Destroy the circular buffer.
+ *
+ * @param pBuf The buffer to destroy. NULL is ignored.
+ */
+RTDECL(void) RTCircBufDestroy(PRTCIRCBUF pBuf);
+
+/**
+ * Reset all position information in the circular buffer.
+ *
+ * @note This function is not multi threading aware.
+ *
+ * @param pBuf The buffer to reset.
+ */
+RTDECL(void) RTCircBufReset(PRTCIRCBUF pBuf);
+
+/**
+ * Returns the current free space of the buffer.
+ *
+ * @param pBuf The buffer to query.
+ */
+RTDECL(size_t) RTCircBufFree(PRTCIRCBUF pBuf);
+
+/**
+ * Returns the current used space of the buffer.
+ *
+ * @param pBuf The buffer to query.
+ */
+RTDECL(size_t) RTCircBufUsed(PRTCIRCBUF pBuf);
+
+/**
+ * Returns the size of the buffer.
+ *
+ * @param pBuf The buffer to query.
+ */
+RTDECL(size_t) RTCircBufSize(PRTCIRCBUF pBuf);
+
+RTDECL(bool) RTCircBufIsReading(PRTCIRCBUF pBuf);
+RTDECL(bool) RTCircBufIsWriting(PRTCIRCBUF pBuf);
+
+/**
+ * Returns the current read offset (in bytes) within the buffer.
+ *
+ * @param pBuf The buffer to query.
+ */
+RTDECL(size_t) RTCircBufOffsetRead(PRTCIRCBUF pBuf);
+
+/**
+ * Returns the current write offset (in bytes) within the buffer.
+ *
+ * @param pBuf The buffer to query.
+ */
+RTDECL(size_t) RTCircBufOffsetWrite(PRTCIRCBUF pBuf);
+
+/**
+ * Acquire a block of the circular buffer for reading.
+ *
+ * @param pBuf The buffer to acquire from.
+ * @param cbReqSize The requested size of the block.
+ * @param ppvStart The resulting memory pointer.
+ * @param pcbSize The resulting size of the memory pointer.
+ */
+RTDECL(void) RTCircBufAcquireReadBlock(PRTCIRCBUF pBuf, size_t cbReqSize, void **ppvStart, size_t *pcbSize);
+
+/**
+ * Release a block which was acquired by RTCircBufAcquireReadBlock.
+ *
+ * @param pBuf The buffer to acquire from.
+ * @param cbSize The size of the block.
+ */
+RTDECL(void) RTCircBufReleaseReadBlock(PRTCIRCBUF pBuf, size_t cbSize);
+
+/**
+ * Acquire a block of the circular buffer for writing.
+ *
+ * @param pBuf The buffer to acquire from.
+ * @param cbReqSize The requested size of the block.
+ * @param ppvStart The resulting memory pointer.
+ * @param pcbSize The resulting size of the memory pointer.
+ */
+RTDECL(void) RTCircBufAcquireWriteBlock(PRTCIRCBUF pBuf, size_t cbReqSize, void **ppvStart, size_t *pcbSize);
+
+/**
+ * Release a block which was acquired by RTCircBufAcquireWriteBlock.
+ *
+ * @param pBuf The buffer to acquire from.
+ * @param cbSize The size of the block.
+ */
+RTDECL(void) RTCircBufReleaseWriteBlock(PRTCIRCBUF pBuf, size_t cbSize);
+
+RT_C_DECLS_END
+
+/** @} */
+
+#endif /* !IPRT_INCLUDED_circbuf_h */
+
diff --git a/include/iprt/condvar.h b/include/iprt/condvar.h
new file mode 100644
index 00000000..8501cb5b
--- /dev/null
+++ b/include/iprt/condvar.h
@@ -0,0 +1,297 @@
+/** @file
+ * IPRT - Condition Variable.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_condvar_h
+#define IPRT_INCLUDED_condvar_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#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_condvar RTCondVar - Condition Variable
+ *
+ * Condition variables combines mutex semaphore or critical sections with event
+ * semaphores. See @ref grp_rt_sems_mutex, @ref grp_rt_critsect,
+ * @ref grp_rt_sems_event and @ref grp_rt_sems_event_multi.
+ *
+ * @ingroup grp_rt
+ * @{
+ */
+
+
+/**
+ * Create a condition variable.
+ *
+ * @returns iprt status code.
+ * @param phCondVar Where to store the handle to the newly created
+ * condition variable.
+ */
+RTDECL(int) RTCondVarCreate(PRTCONDVAR phCondVar);
+
+/**
+ * Create a condition variable.
+ *
+ * @returns iprt status code.
+ * @param phCondVar Where to store the handle to the newly created
+ * condition variable.
+ * @param fFlags Flags, any combination of the
+ * RTCONDVAR_FLAGS_XXX \#defines.
+ * @param hClass The class (no reference consumed). Since we
+ * don't do order checks on condition variables,
+ * 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) RTCondVarCreateEx(PRTCONDVAR phCondVar, uint32_t fFlags, RTLOCKVALCLASS hClass,
+ const char *pszNameFmt, ...) RT_IPRT_FORMAT_ATTR(4, 5);
+
+/** @name RTCondVarCreateEx flags
+ * @{ */
+/** Disables lock validation. */
+#define RTCONDVAR_FLAGS_NO_LOCK_VAL UINT32_C(0x00000001)
+/** @} */
+
+/**
+ * Destroy a condition variable.
+ *
+ * @returns iprt status code.
+ * @param hCondVar Handle of the condition variable. NIL_RTCONDVAR
+ * is quietly ignored (VINF_SUCCESS).
+ */
+RTDECL(int) RTCondVarDestroy(RTCONDVAR hCondVar);
+
+/**
+ * Signal the condition variable, waking up exactly one thread.
+ *
+ * It is recommended that the caller holds the associated lock, but this is not
+ * strictly speaking necessary.
+ *
+ * If no threads are waiting on the condition variable, the call will have no
+ * effect on the variable.
+ *
+ * @returns iprt status code.
+ * @param hCondVar The condition variable to signal.
+ */
+RTDECL(int) RTCondVarSignal(RTCONDVAR hCondVar);
+
+/**
+ * Signal the condition variable, waking up all blocked threads.
+ *
+ * It is recommended that the caller holds the associated lock, but this is not
+ * strictly speaking necessary.
+ *
+ * If no threads are waiting on the condition variable, the call will have no
+ * effect on the variable.
+ *
+ * @returns iprt status code.
+ * @param hCondVar The condition variable to broadcast.
+ */
+RTDECL(int) RTCondVarBroadcast(RTCONDVAR hCondVar);
+
+/**
+ * Wait for the condition variable 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 hCondVar The condition variable to wait on.
+ * @param hMtx The mutex to leave during the wait and which
+ * will be re-enter before returning.
+ * @param cMillies Number of milliseconds to wait. Use
+ * RT_INDEFINITE_WAIT to wait forever.
+ */
+RTDECL(int) RTCondVarMutexWait(RTCONDVAR hCondVar, RTSEMMUTEX hMtx, RTMSINTERVAL cMillies);
+
+/**
+ * Wait for the condition variable to be signaled, return on interruption.
+ *
+ * This function will not resume the wait if interrupted.
+ *
+ * @returns iprt status code.
+ * @param hCondVar The condition variable to wait on.
+ * @param hMtx The mutex to leave during the wait and which
+ * will be re-enter before returning.
+ * @param cMillies Number of milliseconds to wait. Use
+ * RT_INDEFINITE_WAIT to wait forever.
+ */
+RTDECL(int) RTCondVarMutexWaitNoResume(RTCONDVAR hCondVar, RTSEMMUTEX hMtx, RTMSINTERVAL cMillies);
+
+/**
+ * Wait for the condition variable 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 hCondVar The condition variable to wait on.
+ * @param hRWSem The read/write semaphore to write-leave during
+ * the wait and which will be re-enter in write
+ * mode before returning.
+ * @param cMillies Number of milliseconds to wait. Use
+ * RT_INDEFINITE_WAIT to wait forever.
+ */
+RTDECL(int) RTCondVarRWWriteWait(RTCONDVAR hCondVar, RTSEMRW hRWSem, RTMSINTERVAL cMillies);
+
+/**
+ * Wait for the condition variable to be signaled, return on interruption.
+ *
+ * This function will not resume the wait if interrupted.
+ *
+ * @returns iprt status code.
+ * @param hCondVar The condition variable to wait on.
+ * @param hRWSem The read/write semaphore to write-leave during
+ * the wait and which will be re-enter in write
+ * mode before returning.
+ * @param cMillies Number of milliseconds to wait. Use
+ * RT_INDEFINITE_WAIT to wait forever.
+ */
+RTDECL(int) RTCondVarRWWriteWaitNoResume(RTCONDVAR hCondVar, RTSEMRW hRWSem, RTMSINTERVAL cMillies);
+
+/**
+ * Wait for the condition variable 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 hCondVar The condition variable to wait on.
+ * @param hRWSem The read/write semaphore to read-leave during
+ * the wait and which will be re-enter in read mode
+ * before returning.
+ * @param cMillies Number of milliseconds to wait. Use
+ * RT_INDEFINITE_WAIT to wait forever.
+ */
+RTDECL(int) RTCondVarRWReadWait(RTCONDVAR hCondVar, RTSEMRW hRWSem, RTMSINTERVAL cMillies);
+
+/**
+ * Wait for the condition variable to be signaled, return on interruption.
+ *
+ * This function will not resume the wait if interrupted.
+ *
+ * @returns iprt status code.
+ * @param hCondVar The condition variable to wait on.
+ * @param hRWSem The read/write semaphore to read-leave during
+ * the wait and which will be re-enter in read mode
+ * before returning.
+ * @param cMillies Number of milliseconds to wait. Use
+ * RT_INDEFINITE_WAIT to wait forever.
+ */
+RTDECL(int) RTCondVarRWReadWaitNoResume(RTCONDVAR hCondVar, RTSEMRW hRWSem, RTMSINTERVAL cMillies);
+
+/**
+ * Wait for the condition variable 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 hCondVar The condition variable to wait on.
+ * @param pCritSect The critical section to leave during the wait
+ * and which will be re-enter before returning.
+ * @param cMillies Number of milliseconds to wait. Use
+ * RT_INDEFINITE_WAIT to wait forever.
+ */
+RTDECL(int) RTCondVarCritSectWait(RTCONDVAR hCondVar, PRTCRITSECT pCritSect, RTMSINTERVAL cMillies);
+
+/**
+ * Wait for the condition variable to be signaled, return on interruption.
+ *
+ * This function will not resume the wait if interrupted.
+ *
+ * @returns iprt status code.
+ * @param hCondVar The condition variable to wait on.
+ * @param pCritSect The critical section to leave during the wait
+ * and which will be re-enter before returning.
+ * @param cMillies Number of milliseconds to wait. Use
+ * RT_INDEFINITE_WAIT to wait forever.
+ */
+RTDECL(int) RTCondVarCritSectWaitNoResume(RTCONDVAR hCondVar, PRTCRITSECT pCritSect, RTMSINTERVAL cMillies);
+
+/**
+ * Sets the signaller thread to one specific thread.
+ *
+ * This is only used for validating usage and deadlock detection. When used
+ * after calls to RTCondVarAddSignaller, the specified thread will be the only
+ * signalling thread.
+ *
+ * @param hCondVar The condition variable.
+ * @param hThread The thread that will signal it. Pass
+ * NIL_RTTHREAD to indicate that there is no
+ * special signalling thread.
+ */
+RTDECL(void) RTCondVarSetSignaller(RTCONDVAR hCondVar, RTTHREAD hThread);
+
+/**
+ * To add more signalling threads.
+ *
+ * First call RTCondVarSetSignaller then add further threads with this.
+ *
+ * @param hCondVar The condition variable.
+ * @param hThread The thread that will signal it. NIL_RTTHREAD is
+ * not accepted.
+ */
+RTDECL(void) RTCondVarAddSignaller(RTCONDVAR hCondVar, RTTHREAD hThread);
+
+/**
+ * To remove a signalling thread.
+ *
+ * Reverts work done by RTCondVarAddSignaller and RTCondVarSetSignaller.
+ *
+ * @param hCondVar The condition variable.
+ * @param hThread A previously added thread.
+ */
+RTDECL(void) RTCondVarRemoveSignaller(RTCONDVAR hCondVar, RTTHREAD hThread);
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_condvar_h */
+
diff --git a/include/iprt/coredumper.h b/include/iprt/coredumper.h
new file mode 100644
index 00000000..7d1f07c8
--- /dev/null
+++ b/include/iprt/coredumper.h
@@ -0,0 +1,105 @@
+/** @file
+ * IPRT - Core Dumper.
+ */
+
+/*
+ * Copyright (C) 2010-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_coredumper_h
+#define IPRT_INCLUDED_coredumper_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_coredumper RTCoreDumper - Core Dumper.
+ * @ingroup grp_rt
+ * @{
+ */
+
+/** @name RTCoreDumperSetup flags
+ * @{ */
+/** Override system core dumper. Registers handlers for
+ * SIGSEGV/SIGTRAP/SIGBUS. */
+#define RTCOREDUMPER_FLAGS_REPLACE_SYSTEM_DUMP RT_BIT(0)
+/** Allow taking live process dumps (without killing process). Registers handler
+ * for SIGUSR2. */
+#define RTCOREDUMPER_FLAGS_LIVE_CORE RT_BIT(1)
+/** @} */
+
+/**
+ * Take a core dump of the current process without terminating it.
+ *
+ * @returns IPRT status code.
+ * @param pszOutputFile Name of the core file. If NULL use the
+ * default naming scheme.
+ * @param fLiveCore When true, the process is not killed after
+ * taking a core. Otherwise it will be killed. This
+ * works in conjuction with the flags set during
+ * RTCoreDumperSetup().
+ */
+RTDECL(int) RTCoreDumperTakeDump(const char *pszOutputFile, bool fLiveCore);
+
+/**
+ * Sets up and enables the core dumper.
+ *
+ * Installs signal / unhandled exception handlers for catching fatal errors
+ * that should result in a core dump. If you wish to install your own handlers
+ * you should do that after calling this function and make sure you pass on
+ * events you don't handle.
+ *
+ * This can be called multiple times to change the settings without needing to
+ * call RTCoreDumperDisable in between.
+ *
+ * @param pszOutputDir The directory to store the cores in. If NULL
+ * the current directory will be used.
+ * @param fFlags Setup flags, 0 in NOT a valid flag, it must be
+ * one or more of RTCOREDUMPER_FLAGS_*.
+ */
+RTDECL(int) RTCoreDumperSetup(const char *pszOutputDir, uint32_t fFlags);
+
+/**
+ * Disables the core dumper, i.e. undoes what RTCoreDumperSetup did.
+ *
+ * @returns IPRT status code.
+ */
+RTDECL(int) RTCoreDumperDisable(void);
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_coredumper_h */
+
diff --git a/include/iprt/cpp/Makefile.kup b/include/iprt/cpp/Makefile.kup
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/include/iprt/cpp/Makefile.kup
diff --git a/include/iprt/cpp/autores.h b/include/iprt/cpp/autores.h
new file mode 100644
index 00000000..a620de7a
--- /dev/null
+++ b/include/iprt/cpp/autores.h
@@ -0,0 +1,216 @@
+/** @file
+ * IPRT - C++ Resource Management.
+ */
+
+/*
+ * Copyright (C) 2008-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_cpp_autores_h
+#define IPRT_INCLUDED_cpp_autores_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+#include <iprt/assert.h>
+#include <iprt/cpp/utils.h>
+
+
+
+/** @defgroup grp_rt_cpp_autores C++ Resource Management
+ * @ingroup grp_rt_cpp
+ * @{
+ */
+
+/**
+ * A callable class template which returns the correct value against which an
+ * IPRT type must be compared to see if it is invalid.
+ *
+ * @warning This template *must* be specialised for the types it is to work with.
+ */
+template <class T>
+inline T RTAutoResNil(void)
+{
+ AssertFatalMsgFailed(("Unspecialized template!\n"));
+ return (T)0;
+}
+
+/** Specialisation of RTAutoResNil for RTFILE */
+template <>
+inline RTFILE RTAutoResNil(void)
+{
+ return NIL_RTFILE;
+}
+
+/**
+ * A function template which calls the correct destructor for an IPRT type.
+ *
+ * @warning This template *must* be specialised for the types it is to work with.
+ */
+template <class T>
+inline void RTAutoResDestruct(T a_h)
+{
+ AssertFatalMsgFailed(("Unspecialized template!\n"));
+ NOREF(a_h);
+}
+
+/**
+ * An auto pointer-type class for resources which take a C-style destructor
+ * (RTMemFree() or equivalent).
+ *
+ * The idea of this class is to manage resources which the current code is
+ * responsible for freeing. By wrapping the resource in an RTCAutoRes, you
+ * ensure that the resource will be freed when you leave the scope in which
+ * the RTCAutoRes is defined, unless you explicitly release the resource.
+ *
+ * A typical use case is when a function is allocating a number of resources.
+ * If any single allocation fails then all other resources must be freed. If
+ * all allocations succeed, then the resources should be returned to the
+ * caller. By placing all allocated resources in RTCAutoRes containers, you
+ * ensure that they will be freed on failure, and only have to take care of
+ * releasing them when you return them.
+ *
+ * @param T The type of the resource.
+ * @param Destruct The function to be used to free the resource.
+ * This parameter must be supplied if there is no
+ * specialisation of RTAutoDestruct available for @a T.
+ * @param NilRes The function returning the NIL value for T. Required.
+ * This parameter must be supplied if there is no
+ * specialisation of RTAutoResNil available for @a T.
+ *
+ * @note The class can not be initialised directly using assignment, due
+ * to the lack of a copy constructor. This is intentional.
+ */
+template <class T, void Destruct(T) = RTAutoResDestruct<T>, T NilRes(void) = RTAutoResNil<T> >
+class RTCAutoRes
+ : public RTCNonCopyable
+{
+protected:
+ /** The resource handle. */
+ T m_hRes;
+
+public:
+ /**
+ * Constructor
+ *
+ * @param a_hRes The handle to resource to manage. Defaults to NIL.
+ */
+ RTCAutoRes(T a_hRes = NilRes())
+ : m_hRes(a_hRes)
+ {
+ }
+
+ /**
+ * Destructor.
+ *
+ * This destroys any resource currently managed by the object.
+ */
+ ~RTCAutoRes()
+ {
+ if (m_hRes != NilRes())
+ Destruct(m_hRes);
+ }
+
+ /**
+ * Assignment from a value.
+ *
+ * This destroys any resource currently managed by the object
+ * before taking on the new one.
+ *
+ * @param a_hRes The handle to the new resource.
+ */
+ RTCAutoRes &operator=(T a_hRes)
+ {
+ if (m_hRes != NilRes())
+ Destruct(m_hRes);
+ m_hRes = a_hRes;
+ return *this;
+ }
+
+ /**
+ * Checks if the resource handle is NIL or not.
+ */
+ bool operator!()
+ {
+ return m_hRes == NilRes();
+ }
+
+ /**
+ * Give up ownership the current resource, handing it to the caller.
+ *
+ * @returns The current resource handle.
+ *
+ * @note Nothing happens to the resource when the object goes out of scope.
+ */
+ T release(void)
+ {
+ T Tmp = m_hRes;
+ m_hRes = NilRes();
+ return Tmp;
+ }
+
+ /**
+ * Deletes the current resources.
+ *
+ * @param a_hRes Handle to a new resource to manage. Defaults to NIL.
+ */
+ void reset(T a_hRes = NilRes())
+ {
+ if (a_hRes != m_hRes)
+ {
+ if (m_hRes != NilRes())
+ Destruct(m_hRes);
+ m_hRes = a_hRes;
+ }
+ }
+
+ /**
+ * Get the raw resource handle.
+ *
+ * Typically used passing the handle to some IPRT function while
+ * the object remains in scope.
+ *
+ * @returns The raw resource handle.
+ */
+ T get(void)
+ {
+ return m_hRes;
+ }
+};
+
+/** @} */
+
+
+/* include after template definition */
+#include <iprt/mem.h>
+
+#endif /* !IPRT_INCLUDED_cpp_autores_h */
+
diff --git a/include/iprt/cpp/exception.h b/include/iprt/cpp/exception.h
new file mode 100644
index 00000000..0c9f09b7
--- /dev/null
+++ b/include/iprt/cpp/exception.h
@@ -0,0 +1,118 @@
+/** @file
+ * IPRT - C++ Base Exceptions.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_cpp_exception_h
+#define IPRT_INCLUDED_cpp_exception_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cpp/ministring.h>
+#include <exception>
+
+#if RT_MSC_PREREQ(RT_MSC_VER_VC140)
+# pragma warning(push)
+# pragma warning(disable:4275) /* non dll-interface class 'std::exception' used as base for dll-interface class 'RTCError' */
+#endif
+
+
+/** @defgroup grp_rt_cpp_exceptions C++ Exceptions
+ * @ingroup grp_rt_cpp
+ * @{
+ */
+
+/**
+ * Base exception class for IPRT, derived from std::exception.
+ * The XML exceptions are based on this.
+ */
+class RT_DECL_CLASS RTCError
+ : public std::exception
+{
+public:
+
+ RTCError(const char *pszMessage)
+ : m_strMsg(pszMessage)
+ {
+ }
+
+ RTCError(const RTCString &a_rstrMessage)
+ : m_strMsg(a_rstrMessage)
+ {
+ }
+
+ RTCError(const RTCError &a_rSrc)
+ : std::exception(a_rSrc),
+ m_strMsg(a_rSrc.what())
+ {
+ }
+
+ virtual ~RTCError() throw()
+ {
+ }
+
+ void operator=(const RTCError &a_rSrc)
+ {
+ m_strMsg = a_rSrc.what();
+ }
+
+ void setWhat(const char *a_pszMessage)
+ {
+ m_strMsg = a_pszMessage;
+ }
+
+ virtual const char *what() const throw()
+ {
+ return m_strMsg.c_str();
+ }
+
+private:
+ /**
+ * Hidden default constructor making sure that the extended one above is
+ * always used.
+ */
+ RTCError();
+
+protected:
+ /** The exception message. */
+ RTCString m_strMsg;
+};
+
+/** @} */
+
+#if RT_MSC_PREREQ(RT_MSC_VER_VC140)
+# pragma warning(pop)
+#endif
+#endif /* !IPRT_INCLUDED_cpp_exception_h */
+
diff --git a/include/iprt/cpp/hardavlrange.h b/include/iprt/cpp/hardavlrange.h
new file mode 100644
index 00000000..7020968e
--- /dev/null
+++ b/include/iprt/cpp/hardavlrange.h
@@ -0,0 +1,1284 @@
+/** @file
+ * IPRT - Hardened AVL tree, unique key ranges.
+ */
+
+/*
+ * Copyright (C) 2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_cpp_hardavlrange_h
+#define IPRT_INCLUDED_cpp_hardavlrange_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cpp/hardavlslaballocator.h>
+
+/** @defgroup grp_rt_cpp_hardavl Hardened AVL Trees
+ * @{
+ */
+
+/**
+ * Check that the tree heights make sense for the current node.
+ *
+ * This is a RT_STRICT test as it's expensive and we should have sufficient
+ * other checks to ensure safe AVL tree operation.
+ *
+ * @note the a_cStackEntries parameter is a hack to avoid running into gcc's
+ * "the address of 'AVLStack' will never be NULL" errors.
+ */
+#ifdef RT_STRICT
+# define RTHARDAVL_STRICT_CHECK_HEIGHTS(a_pNode, a_pAvlStack, a_cStackEntries) do { \
+ NodeType * const pLeftNodeX = a_pAllocator->ptrFromInt(readIdx(&(a_pNode)->idxLeft)); \
+ AssertReturnStmt(a_pAllocator->isPtrRetOkay(pLeftNodeX), m_cErrors++, a_pAllocator->ptrErrToStatus((a_pNode))); \
+ NodeType * const pRightNodeX = a_pAllocator->ptrFromInt(readIdx(&(a_pNode)->idxRight)); \
+ AssertReturnStmt(a_pAllocator->isPtrRetOkay(pRightNodeX), m_cErrors++, a_pAllocator->ptrErrToStatus((a_pNode))); \
+ uint8_t const cLeftHeightX = pLeftNodeX ? pLeftNodeX->cHeight : 0; \
+ uint8_t const cRightHeightX = pRightNodeX ? pRightNodeX->cHeight : 0; \
+ if (RT_LIKELY((a_pNode)->cHeight == RT_MAX(cLeftHeightX, cRightHeightX) + 1)) { /*likely*/ } \
+ else \
+ { \
+ RTAssertMsg2("line %u: %u l=%u r=%u\n", __LINE__, (a_pNode)->cHeight, cLeftHeightX, cRightHeightX); \
+ if ((a_cStackEntries)) dumpStack(a_pAllocator, (a_pAvlStack)); \
+ AssertMsgReturnStmt((a_pNode)->cHeight == RT_MAX(cLeftHeightX, cRightHeightX) + 1, \
+ ("%u l=%u r=%u\n", (a_pNode)->cHeight, cLeftHeightX, cRightHeightX), \
+ m_cErrors++, VERR_HARDAVL_BAD_HEIGHT); \
+ } \
+ AssertMsgReturnStmt(RT_ABS(cLeftHeightX - cRightHeightX) <= 1, ("l=%u r=%u\n", cLeftHeightX, cRightHeightX), \
+ m_cErrors++, VERR_HARDAVL_UNBALANCED); \
+ Assert(!pLeftNodeX || pLeftNodeX->Key < (a_pNode)->Key); \
+ Assert(!pRightNodeX || pRightNodeX->Key > (a_pNode)->Key); \
+ } while (0)
+#else
+# define RTHARDAVL_STRICT_CHECK_HEIGHTS(a_pNode, a_pAvlStack, a_cStackEntries) do { } while (0)
+#endif
+
+
+/**
+ * Hardened AVL tree for nodes with key ranges.
+ *
+ * This is very crude and therefore expects the NodeType to feature:
+ * - Key and KeyLast members of KeyType.
+ * - idxLeft and idxRight members with type uint32_t.
+ * - cHeight members of type uint8_t.
+ *
+ * The code is very C-ish because of it's sources and initial use (ring-0
+ * without C++ exceptions enabled).
+ */
+template<typename NodeType, typename KeyType>
+struct RTCHardAvlRangeTree
+{
+ /** The root index. */
+ uint32_t m_idxRoot;
+ /** The error count. */
+ uint32_t m_cErrors;
+ /** @name Statistics
+ * @{ */
+ uint64_t m_cInserts;
+ uint64_t m_cRemovals;
+ uint64_t m_cRebalancingOperations;
+ /** @} */
+
+ /** The max stack depth. */
+ enum { kMaxStack = 28 };
+ /** The max height value we allow. */
+ enum { kMaxHeight = kMaxStack + 1 };
+
+ /** A stack used internally to avoid recursive calls.
+ * This is used with operations invoking i_rebalance(). */
+ typedef struct HardAvlStack
+ {
+ /** Number of entries on the stack. */
+ unsigned cEntries;
+ /** The stack. */
+ uint32_t *apidxEntries[kMaxStack];
+ } HardAvlStack;
+
+ /** @name Key comparisons
+ * @{ */
+ static inline int areKeyRangesIntersecting(KeyType a_Key1First, KeyType a_Key2First,
+ KeyType a_Key1Last, KeyType a_Key2Last) RT_NOEXCEPT
+ {
+ return a_Key1First <= a_Key2Last && a_Key1Last >= a_Key2First;
+ }
+
+ static inline int isKeyInRange(KeyType a_Key, KeyType a_KeyFirst, KeyType a_KeyLast) RT_NOEXCEPT
+ {
+ return a_Key <= a_KeyLast && a_Key >= a_KeyFirst;
+ }
+
+ static inline int isKeyGreater(KeyType a_Key1, KeyType a_Key2) RT_NOEXCEPT
+ {
+ return a_Key1 > a_Key2;
+ }
+ /** @} */
+
+ /**
+ * Read an index value trying to prevent the compiler from re-reading it.
+ */
+ DECL_FORCE_INLINE(uint32_t) readIdx(uint32_t volatile *pidx) RT_NOEXCEPT
+ {
+ uint32_t idx = *pidx;
+ ASMCompilerBarrier();
+ return idx;
+ }
+
+ RTCHardAvlRangeTree() RT_NOEXCEPT
+ : m_idxRoot(0)
+ , m_cErrors(0)
+ { }
+
+ RTCHardAvlRangeTree(RTCHardAvlTreeSlabAllocator<NodeType> *a_pAllocator) RT_NOEXCEPT
+ {
+ initWithAllocator(a_pAllocator);
+ }
+
+ void initWithAllocator(RTCHardAvlTreeSlabAllocator<NodeType> *a_pAllocator) RT_NOEXCEPT
+ {
+ m_idxRoot = a_pAllocator->kNilIndex;
+ m_cErrors = 0;
+ }
+
+ /**
+ * Inserts a node into the AVL-tree.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_ALREADY_EXISTS if a node with overlapping key range exists.
+ *
+ * @param a_pAllocator Pointer to the allocator.
+ * @param a_pNode Pointer to the node which is to be added.
+ *
+ * @code
+ * 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.
+ * @endcode
+ */
+ int insert(RTCHardAvlTreeSlabAllocator<NodeType> *a_pAllocator, NodeType *a_pNode) RT_NOEXCEPT
+ {
+ KeyType const Key = a_pNode->Key;
+ KeyType const KeyLast = a_pNode->KeyLast;
+ AssertMsgReturn(Key <= KeyLast, ("Key=%#RX64 KeyLast=%#RX64\n", (uint64_t)Key, (uint64_t)KeyLast),
+ VERR_HARDAVL_INSERT_INVALID_KEY_RANGE);
+
+ uint32_t *pidxCurNode = &m_idxRoot;
+ HardAvlStack AVLStack;
+ AVLStack.cEntries = 0;
+ for (;;)
+ {
+ NodeType *pCurNode = a_pAllocator->ptrFromInt(readIdx(pidxCurNode));
+ AssertMsgReturnStmt(a_pAllocator->isPtrRetOkay(pCurNode), ("*pidxCurNode=%#x pCurNode=%p\n", *pidxCurNode, pCurNode),
+ m_cErrors++, a_pAllocator->ptrErrToStatus(pCurNode));
+ if (!pCurNode)
+ break;
+
+ unsigned const cEntries = AVLStack.cEntries;
+ AssertMsgReturnStmt(cEntries < RT_ELEMENTS(AVLStack.apidxEntries),
+ ("%p[%#x/%p] %p[%#x] %p[%#x] %p[%#x] %p[%#x] %p[%#x]\n", pidxCurNode, *pidxCurNode, pCurNode,
+ AVLStack.apidxEntries[RT_ELEMENTS(AVLStack.apidxEntries) - 1], *AVLStack.apidxEntries[RT_ELEMENTS(AVLStack.apidxEntries) - 1],
+ AVLStack.apidxEntries[RT_ELEMENTS(AVLStack.apidxEntries) - 2], *AVLStack.apidxEntries[RT_ELEMENTS(AVLStack.apidxEntries) - 2],
+ AVLStack.apidxEntries[RT_ELEMENTS(AVLStack.apidxEntries) - 3], *AVLStack.apidxEntries[RT_ELEMENTS(AVLStack.apidxEntries) - 3],
+ AVLStack.apidxEntries[RT_ELEMENTS(AVLStack.apidxEntries) - 4], *AVLStack.apidxEntries[RT_ELEMENTS(AVLStack.apidxEntries) - 4],
+ AVLStack.apidxEntries[RT_ELEMENTS(AVLStack.apidxEntries) - 5], *AVLStack.apidxEntries[RT_ELEMENTS(AVLStack.apidxEntries) - 5]),
+ m_cErrors++, VERR_HARDAVL_STACK_OVERFLOW);
+ AVLStack.apidxEntries[cEntries] = pidxCurNode;
+ AVLStack.cEntries = cEntries + 1;
+
+ RTHARDAVL_STRICT_CHECK_HEIGHTS(pCurNode, &AVLStack, AVLStack.cEntries);
+
+ /* Range check: */
+ if (areKeyRangesIntersecting(pCurNode->Key, Key, pCurNode->KeyLast, KeyLast))
+ return VERR_ALREADY_EXISTS;
+
+ /* Descend: */
+ if (isKeyGreater(pCurNode->Key, Key))
+ pidxCurNode = &pCurNode->idxLeft;
+ else
+ pidxCurNode = &pCurNode->idxRight;
+ }
+
+ a_pNode->idxLeft = a_pAllocator->kNilIndex;
+ a_pNode->idxRight = a_pAllocator->kNilIndex;
+ a_pNode->cHeight = 1;
+
+ uint32_t const idxNode = a_pAllocator->ptrToInt(a_pNode);
+ AssertMsgReturn(a_pAllocator->isIdxRetOkay(idxNode), ("pNode=%p idxNode=%#x\n", a_pNode, idxNode),
+ a_pAllocator->idxErrToStatus(idxNode));
+ *pidxCurNode = idxNode;
+
+ m_cInserts++;
+ return i_rebalance(a_pAllocator, &AVLStack);
+ }
+
+ /**
+ * Removes a node from the AVL-tree by a key value.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_NOT_FOUND if not found.
+ * @param a_pAllocator Pointer to the allocator.
+ * @param a_Key A key value in the range of the node to be removed.
+ * @param a_ppRemoved Where to return the pointer to the removed node.
+ *
+ * @code
+ * 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).
+ * @endcode
+ */
+ int remove(RTCHardAvlTreeSlabAllocator<NodeType> *a_pAllocator, KeyType a_Key, NodeType **a_ppRemoved) RT_NOEXCEPT
+ {
+ *a_ppRemoved = NULL;
+
+ /*
+ * Walk the tree till we locate the node that is to be deleted.
+ */
+ uint32_t *pidxDeleteNode = &m_idxRoot;
+ NodeType *pDeleteNode;
+ HardAvlStack AVLStack;
+ AVLStack.cEntries = 0;
+ for (;;)
+ {
+ pDeleteNode = a_pAllocator->ptrFromInt(readIdx(pidxDeleteNode));
+ AssertMsgReturnStmt(a_pAllocator->isPtrRetOkay(pDeleteNode),
+ ("*pidxCurNode=%#x pDeleteNode=%p\n", *pidxDeleteNode, pDeleteNode),
+ m_cErrors++, a_pAllocator->ptrErrToStatus(pDeleteNode));
+ if (pDeleteNode)
+ { /*likely*/ }
+ else
+ return VERR_NOT_FOUND;
+
+ unsigned const cEntries = AVLStack.cEntries;
+ AssertMsgReturnStmt(cEntries < RT_ELEMENTS(AVLStack.apidxEntries),
+ ("%p[%#x/%p] %p[%#x] %p[%#x] %p[%#x] %p[%#x] %p[%#x]\n",
+ pidxDeleteNode, *pidxDeleteNode, pDeleteNode,
+ AVLStack.apidxEntries[RT_ELEMENTS(AVLStack.apidxEntries) - 1], *AVLStack.apidxEntries[RT_ELEMENTS(AVLStack.apidxEntries) - 1],
+ AVLStack.apidxEntries[RT_ELEMENTS(AVLStack.apidxEntries) - 2], *AVLStack.apidxEntries[RT_ELEMENTS(AVLStack.apidxEntries) - 2],
+ AVLStack.apidxEntries[RT_ELEMENTS(AVLStack.apidxEntries) - 3], *AVLStack.apidxEntries[RT_ELEMENTS(AVLStack.apidxEntries) - 3],
+ AVLStack.apidxEntries[RT_ELEMENTS(AVLStack.apidxEntries) - 4], *AVLStack.apidxEntries[RT_ELEMENTS(AVLStack.apidxEntries) - 4],
+ AVLStack.apidxEntries[RT_ELEMENTS(AVLStack.apidxEntries) - 5], *AVLStack.apidxEntries[RT_ELEMENTS(AVLStack.apidxEntries) - 5]),
+ m_cErrors++, VERR_HARDAVL_STACK_OVERFLOW);
+ AVLStack.apidxEntries[cEntries] = pidxDeleteNode;
+ AVLStack.cEntries = cEntries + 1;
+
+ RTHARDAVL_STRICT_CHECK_HEIGHTS(pDeleteNode, &AVLStack, AVLStack.cEntries);
+
+ /* Range check: */
+ if (isKeyInRange(a_Key, pDeleteNode->Key, pDeleteNode->KeyLast))
+ break;
+
+ /* Descend: */
+ if (isKeyGreater(pDeleteNode->Key, a_Key))
+ pidxDeleteNode = &pDeleteNode->idxLeft;
+ else
+ pidxDeleteNode = &pDeleteNode->idxRight;
+ }
+
+ /*
+ * Do the deletion.
+ */
+ uint32_t const idxDeleteLeftNode = readIdx(&pDeleteNode->idxLeft);
+ if (idxDeleteLeftNode != a_pAllocator->kNilIndex)
+ {
+ /*
+ * Replace the deleted node with the rightmost node in the left subtree.
+ */
+ NodeType * const pDeleteLeftNode = a_pAllocator->ptrFromInt(idxDeleteLeftNode);
+ AssertMsgReturnStmt(a_pAllocator->isPtrRetOkay(pDeleteLeftNode),
+ ("idxDeleteLeftNode=%#x pDeleteLeftNode=%p\n", idxDeleteLeftNode, pDeleteLeftNode),
+ m_cErrors++, a_pAllocator->ptrErrToStatus(pDeleteLeftNode));
+
+ uint32_t const idxDeleteRightNode = readIdx(&pDeleteNode->idxRight);
+ AssertReturnStmt(a_pAllocator->isIntValid(idxDeleteRightNode), m_cErrors++, VERR_HARDAVL_INDEX_OUT_OF_BOUNDS);
+
+ const unsigned iStackEntry = AVLStack.cEntries;
+
+ uint32_t *pidxLeftBiggest = &pDeleteNode->idxLeft;
+ uint32_t idxLeftBiggestNode = idxDeleteLeftNode;
+ NodeType *pLeftBiggestNode = pDeleteLeftNode;
+ RTHARDAVL_STRICT_CHECK_HEIGHTS(pLeftBiggestNode, &AVLStack, AVLStack.cEntries);
+
+ uint32_t idxRightTmp;
+ while ((idxRightTmp = readIdx(&pLeftBiggestNode->idxRight)) != a_pAllocator->kNilIndex)
+ {
+ unsigned const cEntries = AVLStack.cEntries;
+ AssertMsgReturnStmt(cEntries < RT_ELEMENTS(AVLStack.apidxEntries),
+ ("%p[%#x/%p] %p[%#x] %p[%#x] %p[%#x] %p[%#x] %p[%#x]\n",
+ pidxLeftBiggest, *pidxLeftBiggest, pLeftBiggestNode,
+ AVLStack.apidxEntries[RT_ELEMENTS(AVLStack.apidxEntries) - 1], *AVLStack.apidxEntries[RT_ELEMENTS(AVLStack.apidxEntries) - 1],
+ AVLStack.apidxEntries[RT_ELEMENTS(AVLStack.apidxEntries) - 2], *AVLStack.apidxEntries[RT_ELEMENTS(AVLStack.apidxEntries) - 2],
+ AVLStack.apidxEntries[RT_ELEMENTS(AVLStack.apidxEntries) - 3], *AVLStack.apidxEntries[RT_ELEMENTS(AVLStack.apidxEntries) - 3],
+ AVLStack.apidxEntries[RT_ELEMENTS(AVLStack.apidxEntries) - 4], *AVLStack.apidxEntries[RT_ELEMENTS(AVLStack.apidxEntries) - 4],
+ AVLStack.apidxEntries[RT_ELEMENTS(AVLStack.apidxEntries) - 5], *AVLStack.apidxEntries[RT_ELEMENTS(AVLStack.apidxEntries) - 5]),
+ m_cErrors++, VERR_HARDAVL_STACK_OVERFLOW);
+ AVLStack.apidxEntries[cEntries] = pidxLeftBiggest;
+ AVLStack.cEntries = cEntries + 1;
+
+ pidxLeftBiggest = &pLeftBiggestNode->idxRight;
+ idxLeftBiggestNode = idxRightTmp;
+ pLeftBiggestNode = a_pAllocator->ptrFromInt(idxRightTmp);
+ AssertMsgReturnStmt(a_pAllocator->isPtrRetOkay(pLeftBiggestNode),
+ ("idxLeftBiggestNode=%#x pLeftBiggestNode=%p\n", idxLeftBiggestNode, pLeftBiggestNode),
+ m_cErrors++, a_pAllocator->ptrErrToStatus(pLeftBiggestNode));
+ RTHARDAVL_STRICT_CHECK_HEIGHTS(pLeftBiggestNode, &AVLStack, AVLStack.cEntries);
+ }
+
+ uint32_t const idxLeftBiggestLeftNode = readIdx(&pLeftBiggestNode->idxLeft);
+ AssertReturnStmt(a_pAllocator->isIntValid(idxLeftBiggestLeftNode), m_cErrors++, VERR_HARDAVL_INDEX_OUT_OF_BOUNDS);
+
+ /* link out pLeftBiggestNode */
+ *pidxLeftBiggest = idxLeftBiggestLeftNode;
+
+ /* link it in place of the deleted node. */
+ if (idxDeleteLeftNode != idxLeftBiggestNode)
+ pLeftBiggestNode->idxLeft = idxDeleteLeftNode;
+ pLeftBiggestNode->idxRight = idxDeleteRightNode;
+ pLeftBiggestNode->cHeight = AVLStack.cEntries > iStackEntry ? pDeleteNode->cHeight : 0;
+
+ *pidxDeleteNode = idxLeftBiggestNode;
+
+ if (AVLStack.cEntries > iStackEntry)
+ AVLStack.apidxEntries[iStackEntry] = &pLeftBiggestNode->idxLeft;
+ }
+ else
+ {
+ /* No left node, just pull up the right one. */
+ uint32_t const idxDeleteRightNode = readIdx(&pDeleteNode->idxRight);
+ AssertReturnStmt(a_pAllocator->isIntValid(idxDeleteRightNode), m_cErrors++, VERR_HARDAVL_INDEX_OUT_OF_BOUNDS);
+ *pidxDeleteNode = idxDeleteRightNode;
+ AVLStack.cEntries--;
+ }
+ *a_ppRemoved = pDeleteNode;
+
+ m_cRemovals++;
+ return i_rebalance(a_pAllocator, &AVLStack);
+ }
+
+ /**
+ * Looks up a node from the tree.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_NOT_FOUND if not found.
+ *
+ * @param a_pAllocator Pointer to the allocator.
+ * @param a_Key A key value in the range of the desired node.
+ * @param a_ppFound Where to return the pointer to the node.
+ */
+ int lookup(RTCHardAvlTreeSlabAllocator<NodeType> *a_pAllocator, KeyType a_Key, NodeType **a_ppFound) RT_NOEXCEPT
+ {
+ *a_ppFound = NULL;
+
+ NodeType *pNode = a_pAllocator->ptrFromInt(readIdx(&m_idxRoot));
+ AssertMsgReturnStmt(a_pAllocator->isPtrRetOkay(pNode), ("m_idxRoot=%#x pNode=%p\n", m_idxRoot, pNode),
+ m_cErrors++, a_pAllocator->ptrErrToStatus(pNode));
+#ifdef RT_STRICT
+ HardAvlStack AVLStack;
+ AVLStack.apidxEntries[0] = &m_idxRoot;
+ AVLStack.cEntries = 1;
+#endif
+ unsigned cDepth = 0;
+ while (pNode)
+ {
+ RTHARDAVL_STRICT_CHECK_HEIGHTS(pNode, &AVLStack, AVLStack.cEntries);
+ AssertReturn(cDepth <= kMaxHeight, VERR_HARDAVL_LOOKUP_TOO_DEEP);
+ cDepth++;
+
+ if (isKeyInRange(a_Key, pNode->Key, pNode->KeyLast))
+ {
+ *a_ppFound = pNode;
+ return VINF_SUCCESS;
+ }
+ if (isKeyGreater(pNode->Key, a_Key))
+ {
+#ifdef RT_STRICT
+ AVLStack.apidxEntries[AVLStack.cEntries++] = &pNode->idxLeft;
+#endif
+ uint32_t const idxLeft = readIdx(&pNode->idxLeft);
+ pNode = a_pAllocator->ptrFromInt(idxLeft);
+ AssertMsgReturnStmt(a_pAllocator->isPtrRetOkay(pNode), ("idxLeft=%#x pNode=%p\n", idxLeft, pNode),
+ m_cErrors++, a_pAllocator->ptrErrToStatus(pNode));
+ }
+ else
+ {
+#ifdef RT_STRICT
+ AVLStack.apidxEntries[AVLStack.cEntries++] = &pNode->idxRight;
+#endif
+ uint32_t const idxRight = readIdx(&pNode->idxRight);
+ pNode = a_pAllocator->ptrFromInt(idxRight);
+ AssertMsgReturnStmt(a_pAllocator->isPtrRetOkay(pNode), ("idxRight=%#x pNode=%p\n", idxRight, pNode),
+ m_cErrors++, a_pAllocator->ptrErrToStatus(pNode));
+ }
+ }
+
+ return VERR_NOT_FOUND;
+ }
+
+ /**
+ * Looks up node matching @a a_Key or if no exact match the closest smaller than it.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_NOT_FOUND if not found.
+ *
+ * @param a_pAllocator Pointer to the allocator.
+ * @param a_Key A key value in the range of the desired node.
+ * @param a_ppFound Where to return the pointer to the node.
+ */
+ int lookupMatchingOrBelow(RTCHardAvlTreeSlabAllocator<NodeType> *a_pAllocator, KeyType a_Key,
+ NodeType **a_ppFound) RT_NOEXCEPT
+ {
+ *a_ppFound = NULL;
+
+ NodeType *pNode = a_pAllocator->ptrFromInt(readIdx(&m_idxRoot));
+ AssertMsgReturnStmt(a_pAllocator->isPtrRetOkay(pNode), ("m_idxRoot=%#x pNode=%p\n", m_idxRoot, pNode),
+ m_cErrors++, a_pAllocator->ptrErrToStatus(pNode));
+#ifdef RT_STRICT
+ HardAvlStack AVLStack;
+ AVLStack.apidxEntries[0] = &m_idxRoot;
+ AVLStack.cEntries = 1;
+#endif
+ unsigned cDepth = 0;
+ NodeType *pNodeLast = NULL;
+ while (pNode)
+ {
+ RTHARDAVL_STRICT_CHECK_HEIGHTS(pNode, &AVLStack, AVLStack.cEntries);
+ AssertReturn(cDepth <= kMaxHeight, VERR_HARDAVL_LOOKUP_TOO_DEEP);
+ cDepth++;
+
+ if (isKeyInRange(a_Key, pNode->Key, pNode->KeyLast))
+ {
+ *a_ppFound = pNode;
+ return VINF_SUCCESS;
+ }
+ if (isKeyGreater(pNode->Key, a_Key))
+ {
+#ifdef RT_STRICT
+ AVLStack.apidxEntries[AVLStack.cEntries++] = &pNode->idxLeft;
+#endif
+ uint32_t const idxLeft = readIdx(&pNode->idxLeft);
+ NodeType *pLeftNode = a_pAllocator->ptrFromInt(idxLeft);
+ AssertMsgReturnStmt(a_pAllocator->isPtrRetOkay(pLeftNode), ("idxLeft=%#x pLeftNode=%p\n", idxLeft, pLeftNode),
+ m_cErrors++, a_pAllocator->ptrErrToStatus(pLeftNode));
+ if (pLeftNode)
+ pNode = pLeftNode;
+ else if (!pNodeLast)
+ break;
+ else
+ {
+ *a_ppFound = pNodeLast;
+ return VINF_SUCCESS;
+ }
+ }
+ else
+ {
+#ifdef RT_STRICT
+ AVLStack.apidxEntries[AVLStack.cEntries++] = &pNode->idxRight;
+#endif
+ uint32_t const idxRight = readIdx(&pNode->idxRight);
+ NodeType *pRightNode = a_pAllocator->ptrFromInt(idxRight);
+ AssertMsgReturnStmt(a_pAllocator->isPtrRetOkay(pRightNode), ("idxRight=%#x pRightNode=%p\n", idxRight, pRightNode),
+ m_cErrors++, a_pAllocator->ptrErrToStatus(pRightNode));
+ if (pRightNode)
+ {
+ pNodeLast = pNode;
+ pNode = pRightNode;
+ }
+ else
+ {
+ *a_ppFound = pNode;
+ return VINF_SUCCESS;
+ }
+ }
+ }
+
+ return VERR_NOT_FOUND;
+ }
+
+ /**
+ * Looks up node matching @a a_Key or if no exact match the closest larger than it.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_NOT_FOUND if not found.
+ *
+ * @param a_pAllocator Pointer to the allocator.
+ * @param a_Key A key value in the range of the desired node.
+ * @param a_ppFound Where to return the pointer to the node.
+ */
+ int lookupMatchingOrAbove(RTCHardAvlTreeSlabAllocator<NodeType> *a_pAllocator, KeyType a_Key,
+ NodeType **a_ppFound) RT_NOEXCEPT
+ {
+ *a_ppFound = NULL;
+
+ NodeType *pNode = a_pAllocator->ptrFromInt(readIdx(&m_idxRoot));
+ AssertMsgReturnStmt(a_pAllocator->isPtrRetOkay(pNode), ("m_idxRoot=%#x pNode=%p\n", m_idxRoot, pNode),
+ m_cErrors++, a_pAllocator->ptrErrToStatus(pNode));
+#ifdef RT_STRICT
+ HardAvlStack AVLStack;
+ AVLStack.apidxEntries[0] = &m_idxRoot;
+ AVLStack.cEntries = 1;
+#endif
+ unsigned cDepth = 0;
+ NodeType *pNodeLast = NULL;
+ while (pNode)
+ {
+ RTHARDAVL_STRICT_CHECK_HEIGHTS(pNode, &AVLStack, AVLStack.cEntries);
+ AssertReturn(cDepth <= kMaxHeight, VERR_HARDAVL_LOOKUP_TOO_DEEP);
+ cDepth++;
+
+ if (isKeyInRange(a_Key, pNode->Key, pNode->KeyLast))
+ {
+ *a_ppFound = pNode;
+ return VINF_SUCCESS;
+ }
+ if (isKeyGreater(pNode->Key, a_Key))
+ {
+#ifdef RT_STRICT
+ AVLStack.apidxEntries[AVLStack.cEntries++] = &pNode->idxLeft;
+#endif
+ uint32_t const idxLeft = readIdx(&pNode->idxLeft);
+ NodeType *pLeftNode = a_pAllocator->ptrFromInt(idxLeft);
+ AssertMsgReturnStmt(a_pAllocator->isPtrRetOkay(pLeftNode), ("idxLeft=%#x pLeftNode=%p\n", idxLeft, pLeftNode),
+ m_cErrors++, a_pAllocator->ptrErrToStatus(pLeftNode));
+ if (pLeftNode)
+ {
+ pNodeLast = pNode;
+ pNode = pLeftNode;
+ }
+ else
+ {
+ *a_ppFound = pNode;
+ return VINF_SUCCESS;
+ }
+ }
+ else
+ {
+#ifdef RT_STRICT
+ AVLStack.apidxEntries[AVLStack.cEntries++] = &pNode->idxRight;
+#endif
+ uint32_t const idxRight = readIdx(&pNode->idxRight);
+ NodeType *pRightNode = a_pAllocator->ptrFromInt(idxRight);
+ AssertMsgReturnStmt(a_pAllocator->isPtrRetOkay(pRightNode), ("idxRight=%#x pRightNode=%p\n", idxRight, pRightNode),
+ m_cErrors++, a_pAllocator->ptrErrToStatus(pRightNode));
+ if (pRightNode)
+ pNode = pRightNode;
+ else if (!pNodeLast)
+ break;
+ else
+ {
+ *a_ppFound = pNodeLast;
+ return VINF_SUCCESS;
+ }
+ }
+ }
+
+ return VERR_NOT_FOUND;
+ }
+
+ /**
+ * A callback for doWithAllFromLeft and doWithAllFromRight.
+ *
+ * @returns IPRT status code. Any non-zero status causes immediate return from
+ * the enumeration function.
+ * @param pNode The current node.
+ * @param pvUser The user argument.
+ */
+ typedef DECLCALLBACKTYPE(int, FNCALLBACK,(NodeType *pNode, void *pvUser));
+ /** Pointer to a callback for doWithAllFromLeft and doWithAllFromRight. */
+ typedef FNCALLBACK *PFNCALLBACK;
+
+ /**
+ * Iterates thru all nodes in the tree from left (smaller) to right.
+ *
+ * @returns IPRT status code.
+ *
+ * @param a_pAllocator Pointer to the allocator.
+ * @param a_pfnCallBack Pointer to callback function.
+ * @param a_pvUser Callback user argument.
+ *
+ * @note This is very similar code to doWithAllFromRight() and destroy().
+ */
+ int doWithAllFromLeft(RTCHardAvlTreeSlabAllocator<NodeType> *a_pAllocator,
+ PFNCALLBACK a_pfnCallBack, void *a_pvUser) RT_NOEXCEPT
+ {
+ NodeType *pNode = a_pAllocator->ptrFromInt(readIdx(&m_idxRoot));
+ AssertMsgReturnStmt(a_pAllocator->isPtrRetOkay(pNode), ("m_idxRoot=%#x pNode=%p\n", m_idxRoot, pNode),
+ m_cErrors++, a_pAllocator->ptrErrToStatus(pNode));
+ if (!pNode)
+ return VINF_SUCCESS;
+
+ /*
+ * We simulate recursive calling here. For safety reasons, we do not
+ * pop before going down the right tree like the original code did.
+ */
+ uint32_t cNodesLeft = a_pAllocator->m_cNodes;
+ NodeType *apEntries[kMaxStack];
+ uint8_t abState[kMaxStack];
+ unsigned cEntries = 1;
+ abState[0] = 0;
+ apEntries[0] = pNode;
+ while (cEntries > 0)
+ {
+ pNode = apEntries[cEntries - 1];
+ switch (abState[cEntries - 1])
+ {
+ /* Go left. */
+ case 0:
+ {
+ abState[cEntries - 1] = 1;
+
+ NodeType * const pLeftNode = a_pAllocator->ptrFromInt(readIdx(&pNode->idxLeft));
+ AssertMsgReturnStmt(a_pAllocator->isPtrRetOkay(pLeftNode),
+ ("idxLeft=%#x pLeftNode=%p\n", pNode->idxLeft, pLeftNode),
+ m_cErrors++, a_pAllocator->ptrErrToStatus(pLeftNode));
+ if (pLeftNode)
+ {
+#if RT_GNUC_PREREQ_EX(4,7,1) && defined(RTASSERT_HAVE_STATIC_ASSERT) /* 32-bit 4.4.7 has trouble, dunno when it started working */
+ AssertCompile(kMaxStack > 6); /* exactly. Seems having static_assert is required. */
+#endif
+ AssertMsgReturnStmt(cEntries < RT_ELEMENTS(apEntries),
+ ("%p[%#x] %p %p %p %p %p %p\n", pLeftNode, pNode->idxLeft, apEntries[kMaxStack - 1],
+ apEntries[kMaxStack - 2], apEntries[kMaxStack - 3], apEntries[kMaxStack - 4],
+ apEntries[kMaxStack - 5], apEntries[kMaxStack - 6]),
+ m_cErrors++, VERR_HARDAVL_STACK_OVERFLOW);
+ apEntries[cEntries] = pLeftNode;
+ abState[cEntries] = 0;
+ cEntries++;
+
+ AssertReturn(cNodesLeft > 0, VERR_HARDAVL_TRAVERSED_TOO_MANY_NODES);
+ cNodesLeft--;
+ break;
+ }
+ RT_FALL_THROUGH();
+ }
+
+ /* center then right. */
+ case 1:
+ {
+ abState[cEntries - 1] = 2;
+
+ RTHARDAVL_STRICT_CHECK_HEIGHTS(pNode, NULL, 0);
+
+ int rc = a_pfnCallBack(pNode, a_pvUser);
+ if (rc != VINF_SUCCESS)
+ return rc;
+
+ NodeType * const pRightNode = a_pAllocator->ptrFromInt(readIdx(&pNode->idxRight));
+ AssertMsgReturnStmt(a_pAllocator->isPtrRetOkay(pRightNode),
+ ("idxRight=%#x pRightNode=%p\n", pNode->idxRight, pRightNode),
+ m_cErrors++, a_pAllocator->ptrErrToStatus(pRightNode));
+ if (pRightNode)
+ {
+#if RT_GNUC_PREREQ_EX(4,7,1) && defined(RTASSERT_HAVE_STATIC_ASSERT) /* 32-bit 4.4.7 has trouble, dunno when it started working */
+ AssertCompile(kMaxStack > 6); /* exactly. Seems having static_assert is required. */
+#endif
+ AssertMsgReturnStmt(cEntries < RT_ELEMENTS(apEntries),
+ ("%p[%#x] %p %p %p %p %p %p\n", pRightNode, pNode->idxRight, apEntries[kMaxStack - 1],
+ apEntries[kMaxStack - 2], apEntries[kMaxStack - 3], apEntries[kMaxStack - 4],
+ apEntries[kMaxStack - 5], apEntries[kMaxStack - 6]),
+ m_cErrors++, VERR_HARDAVL_STACK_OVERFLOW);
+ apEntries[cEntries] = pRightNode;
+ abState[cEntries] = 0;
+ cEntries++;
+
+ AssertReturn(cNodesLeft > 0, VERR_HARDAVL_TRAVERSED_TOO_MANY_NODES);
+ cNodesLeft--;
+ break;
+ }
+ RT_FALL_THROUGH();
+ }
+
+ default:
+ /* pop it. */
+ cEntries -= 1;
+ break;
+ }
+ }
+ return VINF_SUCCESS;
+ }
+
+ /**
+ * Iterates thru all nodes in the tree from right (larger) to left (smaller).
+ *
+ * @returns IPRT status code.
+ *
+ * @param a_pAllocator Pointer to the allocator.
+ * @param a_pfnCallBack Pointer to callback function.
+ * @param a_pvUser Callback user argument.
+ *
+ * @note This is very similar code to doWithAllFromLeft() and destroy().
+ */
+ int doWithAllFromRight(RTCHardAvlTreeSlabAllocator<NodeType> *a_pAllocator,
+ PFNCALLBACK a_pfnCallBack, void *a_pvUser) RT_NOEXCEPT
+ {
+ NodeType *pNode = a_pAllocator->ptrFromInt(readIdx(&m_idxRoot));
+ AssertMsgReturnStmt(a_pAllocator->isPtrRetOkay(pNode), ("m_idxRoot=%#x pNode=%p\n", m_idxRoot, pNode),
+ m_cErrors++, a_pAllocator->ptrErrToStatus(pNode));
+ if (!pNode)
+ return VINF_SUCCESS;
+
+ /*
+ * We simulate recursive calling here. For safety reasons, we do not
+ * pop before going down the right tree like the original code did.
+ */
+ uint32_t cNodesLeft = a_pAllocator->m_cNodes;
+ NodeType *apEntries[kMaxStack];
+ uint8_t abState[kMaxStack];
+ unsigned cEntries = 1;
+ abState[0] = 0;
+ apEntries[0] = pNode;
+ while (cEntries > 0)
+ {
+ pNode = apEntries[cEntries - 1];
+ switch (abState[cEntries - 1])
+ {
+ /* Go right. */
+ case 0:
+ {
+ abState[cEntries - 1] = 1;
+
+ NodeType * const pRightNode = a_pAllocator->ptrFromInt(readIdx(&pNode->idxRight));
+ AssertMsgReturnStmt(a_pAllocator->isPtrRetOkay(pRightNode),
+ ("idxRight=%#x pRightNode=%p\n", pNode->idxRight, pRightNode),
+ m_cErrors++, a_pAllocator->ptrErrToStatus(pRightNode));
+ if (pRightNode)
+ {
+#if RT_GNUC_PREREQ_EX(4,7,1) && defined(RTASSERT_HAVE_STATIC_ASSERT) /* 32-bit 4.4.7 has trouble, dunno when it started working */
+ AssertCompile(kMaxStack > 6); /* exactly. Seems having static_assert is required. */
+#endif
+ AssertMsgReturnStmt(cEntries < RT_ELEMENTS(apEntries),
+ ("%p[%#x] %p %p %p %p %p %p\n", pRightNode, pNode->idxRight, apEntries[kMaxStack - 1],
+ apEntries[kMaxStack - 2], apEntries[kMaxStack - 3], apEntries[kMaxStack - 4],
+ apEntries[kMaxStack - 5], apEntries[kMaxStack - 6]),
+ m_cErrors++, VERR_HARDAVL_STACK_OVERFLOW);
+ apEntries[cEntries] = pRightNode;
+ abState[cEntries] = 0;
+ cEntries++;
+
+ AssertReturn(cNodesLeft > 0, VERR_HARDAVL_TRAVERSED_TOO_MANY_NODES);
+ cNodesLeft--;
+ break;
+ }
+ RT_FALL_THROUGH();
+ }
+
+ /* center then left. */
+ case 1:
+ {
+ abState[cEntries - 1] = 2;
+
+ RTHARDAVL_STRICT_CHECK_HEIGHTS(pNode, NULL, 0);
+
+ int rc = a_pfnCallBack(pNode, a_pvUser);
+ if (rc != VINF_SUCCESS)
+ return rc;
+
+ NodeType * const pLeftNode = a_pAllocator->ptrFromInt(readIdx(&pNode->idxLeft));
+ AssertMsgReturnStmt(a_pAllocator->isPtrRetOkay(pLeftNode),
+ ("idxLeft=%#x pLeftNode=%p\n", pNode->idxLeft, pLeftNode),
+ m_cErrors++, a_pAllocator->ptrErrToStatus(pLeftNode));
+ if (pLeftNode)
+ {
+#if RT_GNUC_PREREQ_EX(4,7,1) && defined(RTASSERT_HAVE_STATIC_ASSERT) /* 32-bit 4.4.7 has trouble, dunno when it started working */
+ AssertCompile(kMaxStack > 6); /* exactly. Seems having static_assert is required. */
+#endif
+ AssertMsgReturnStmt(cEntries < RT_ELEMENTS(apEntries),
+ ("%p[%#x] %p %p %p %p %p %p\n", pLeftNode, pNode->idxLeft, apEntries[kMaxStack - 1],
+ apEntries[kMaxStack - 2], apEntries[kMaxStack - 3], apEntries[kMaxStack - 4],
+ apEntries[kMaxStack - 5], apEntries[kMaxStack - 6]),
+ m_cErrors++, VERR_HARDAVL_STACK_OVERFLOW);
+ apEntries[cEntries] = pLeftNode;
+ abState[cEntries] = 0;
+ cEntries++;
+
+ AssertReturn(cNodesLeft > 0, VERR_HARDAVL_TRAVERSED_TOO_MANY_NODES);
+ cNodesLeft--;
+ break;
+ }
+ RT_FALL_THROUGH();
+ }
+
+ default:
+ /* pop it. */
+ cEntries -= 1;
+ break;
+ }
+ }
+ return VINF_SUCCESS;
+ }
+
+ /**
+ * A callback for destroy to do additional cleanups before the node is freed.
+ *
+ * @param pNode The current node.
+ * @param pvUser The user argument.
+ */
+ typedef DECLCALLBACKTYPE(void, FNDESTROYCALLBACK,(NodeType *pNode, void *pvUser));
+ /** Pointer to a callback for destroy. */
+ typedef FNDESTROYCALLBACK *PFNDESTROYCALLBACK;
+
+ /**
+ * Destroys the tree, starting with the root node.
+ *
+ * This will invoke the freeNode() method on the allocate for every node after
+ * first doing the callback to let the caller free additional resources
+ * referenced by the node.
+ *
+ * @returns IPRT status code.
+ *
+ * @param a_pAllocator Pointer to the allocator.
+ * @param a_pfnCallBack Pointer to callback function. Optional.
+ * @param a_pvUser Callback user argument.
+ *
+ * @note This is mostly the same code as the doWithAllFromLeft().
+ */
+ int destroy(RTCHardAvlTreeSlabAllocator<NodeType> *a_pAllocator,
+ PFNDESTROYCALLBACK a_pfnCallBack = NULL, void *a_pvUser = NULL) RT_NOEXCEPT
+ {
+ NodeType *pNode = a_pAllocator->ptrFromInt(readIdx(&m_idxRoot));
+ AssertMsgReturnStmt(a_pAllocator->isPtrRetOkay(pNode), ("m_idxRoot=%#x pNode=%p\n", m_idxRoot, pNode),
+ m_cErrors++, a_pAllocator->ptrErrToStatus(pNode));
+ if (!pNode)
+ return VINF_SUCCESS;
+
+ /*
+ * We simulate recursive calling here. For safety reasons, we do not
+ * pop before going down the right tree like the original code did.
+ */
+ uint32_t cNodesLeft = a_pAllocator->m_cNodes;
+ NodeType *apEntries[kMaxStack];
+ uint8_t abState[kMaxStack];
+ unsigned cEntries = 1;
+ abState[0] = 0;
+ apEntries[0] = pNode;
+ while (cEntries > 0)
+ {
+ pNode = apEntries[cEntries - 1];
+ switch (abState[cEntries - 1])
+ {
+ /* Go left. */
+ case 0:
+ {
+ abState[cEntries - 1] = 1;
+
+ NodeType * const pLeftNode = a_pAllocator->ptrFromInt(readIdx(&pNode->idxLeft));
+ AssertMsgReturnStmt(a_pAllocator->isPtrRetOkay(pLeftNode),
+ ("idxLeft=%#x pLeftNode=%p\n", pNode->idxLeft, pLeftNode),
+ m_cErrors++, a_pAllocator->ptrErrToStatus(pLeftNode));
+ if (pLeftNode)
+ {
+#if RT_GNUC_PREREQ_EX(4,7,1) && defined(RTASSERT_HAVE_STATIC_ASSERT) /* 32-bit 4.4.7 has trouble, dunno when it started working */
+ AssertCompile(kMaxStack > 6); /* exactly. Seems having static_assert is required. */
+#endif
+ AssertMsgReturnStmt(cEntries < RT_ELEMENTS(apEntries),
+ ("%p[%#x] %p %p %p %p %p %p\n", pLeftNode, pNode->idxLeft, apEntries[kMaxStack - 1],
+ apEntries[kMaxStack - 2], apEntries[kMaxStack - 3], apEntries[kMaxStack - 4],
+ apEntries[kMaxStack - 5], apEntries[kMaxStack - 6]),
+ m_cErrors++, VERR_HARDAVL_STACK_OVERFLOW);
+ apEntries[cEntries] = pLeftNode;
+ abState[cEntries] = 0;
+ cEntries++;
+
+ AssertReturn(cNodesLeft > 0, VERR_HARDAVL_TRAVERSED_TOO_MANY_NODES);
+ cNodesLeft--;
+ break;
+ }
+ RT_FALL_THROUGH();
+ }
+
+ /* right. */
+ case 1:
+ {
+ abState[cEntries - 1] = 2;
+
+ NodeType * const pRightNode = a_pAllocator->ptrFromInt(readIdx(&pNode->idxRight));
+ AssertMsgReturnStmt(a_pAllocator->isPtrRetOkay(pRightNode),
+ ("idxRight=%#x pRightNode=%p\n", pNode->idxRight, pRightNode),
+ m_cErrors++, a_pAllocator->ptrErrToStatus(pRightNode));
+ if (pRightNode)
+ {
+#if RT_GNUC_PREREQ_EX(4,7,1) && defined(RTASSERT_HAVE_STATIC_ASSERT) /* 32-bit 4.4.7 has trouble, dunno when it started working */
+ AssertCompile(kMaxStack > 6); /* exactly. Seems having static_assert is required. */
+#endif
+ AssertMsgReturnStmt(cEntries < RT_ELEMENTS(apEntries),
+ ("%p[%#x] %p %p %p %p %p %p\n", pRightNode, pNode->idxRight, apEntries[kMaxStack - 1],
+ apEntries[kMaxStack - 2], apEntries[kMaxStack - 3], apEntries[kMaxStack - 4],
+ apEntries[kMaxStack - 5], apEntries[kMaxStack - 6]),
+ m_cErrors++, VERR_HARDAVL_STACK_OVERFLOW);
+ apEntries[cEntries] = pRightNode;
+ abState[cEntries] = 0;
+ cEntries++;
+
+ AssertReturn(cNodesLeft > 0, VERR_HARDAVL_TRAVERSED_TOO_MANY_NODES);
+ cNodesLeft--;
+ break;
+ }
+ RT_FALL_THROUGH();
+ }
+
+ default:
+ {
+ /* pop it and destroy it. */
+ if (a_pfnCallBack)
+ a_pfnCallBack(pNode, a_pvUser);
+
+ int rc = a_pAllocator->freeNode(pNode);
+ AssertRCReturnStmt(rc, m_cErrors++, rc);
+
+ cEntries -= 1;
+ break;
+ }
+ }
+ }
+
+ Assert(m_idxRoot == a_pAllocator->kNilIndex);
+ return VINF_SUCCESS;
+ }
+
+
+ /**
+ * Gets the tree height value (reads cHeigh from the root node).
+ *
+ * @retval UINT8_MAX if bogus tree.
+ */
+ uint8_t getHeight(RTCHardAvlTreeSlabAllocator<NodeType> *a_pAllocator) RT_NOEXCEPT
+ {
+ NodeType *pNode = a_pAllocator->ptrFromInt(readIdx(&m_idxRoot));
+ AssertMsgReturnStmt(a_pAllocator->isPtrRetOkay(pNode), ("m_idxRoot=%#x pNode=%p\n", m_idxRoot, pNode),
+ m_cErrors++, UINT8_MAX);
+ if (pNode)
+ return pNode->cHeight;
+ return 0;
+ }
+
+#ifdef RT_STRICT
+
+ static void dumpStack(RTCHardAvlTreeSlabAllocator<NodeType> *a_pAllocator, HardAvlStack const *pStack) RT_NOEXCEPT
+ {
+ uint32_t const * const *paidx = pStack->apidxEntries;
+ RTAssertMsg2("stack: %u:\n", pStack->cEntries);
+ for (unsigned i = 0; i < pStack->cEntries; i++)
+ {
+ uint32_t idx = *paidx[i];
+ uint32_t idxNext = i + 1 < pStack->cEntries ? *paidx[i + 1] : UINT32_MAX;
+ NodeType const *pNode = a_pAllocator->ptrFromInt(idx);
+ RTAssertMsg2(" #%02u: %p[%#06x] pNode=%p h=%02d l=%#06x%c r=%#06x%c\n", i, paidx[i], idx, pNode, pNode->cHeight,
+ pNode->idxLeft, pNode->idxLeft == idxNext ? '*' : ' ',
+ pNode->idxRight, pNode->idxRight == idxNext ? '*' : ' ');
+ }
+ }
+
+ static void printTree(RTCHardAvlTreeSlabAllocator<NodeType> *a_pAllocator, uint32_t a_idxRoot,
+ unsigned a_uLevel = 0, unsigned a_uMaxLevel = 8, const char *a_pszDir = "") RT_NOEXCEPT
+ {
+ if (a_idxRoot == a_pAllocator->kNilIndex)
+ RTAssertMsg2("%*snil\n", a_uLevel * 6, a_pszDir);
+ else if (a_uLevel < a_uMaxLevel)
+ {
+ NodeType *pNode = a_pAllocator->ptrFromInt(a_idxRoot);
+ printTree(a_pAllocator, readIdx(&pNode->idxRight), a_uLevel + 1, a_uMaxLevel, "/ ");
+ RTAssertMsg2("%*s%#x/%u\n", a_uLevel * 6, a_pszDir, a_idxRoot, pNode->cHeight);
+ printTree(a_pAllocator, readIdx(&pNode->idxLeft), a_uLevel + 1, a_uMaxLevel, "\\ ");
+ }
+ else
+ RTAssertMsg2("%*stoo deep\n", a_uLevel * 6, a_pszDir);
+ }
+
+#endif
+
+private:
+ /**
+ * Rewinds a stack of pointers to pointers to nodes, rebalancing the tree.
+ *
+ * @returns IPRT status code.
+ *
+ * @param a_pAllocator Pointer to the allocator.
+ * @param a_pStack Pointer to stack to rewind.
+ * @param a_fLog Log is done (DEBUG builds only).
+ *
+ * @code
+ * 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
+ * @endcode
+ * @internal
+ */
+ int i_rebalance(RTCHardAvlTreeSlabAllocator<NodeType> *a_pAllocator, HardAvlStack *a_pStack, bool a_fLog = false) RT_NOEXCEPT
+ {
+ RT_NOREF(a_fLog);
+
+ while (a_pStack->cEntries > 0)
+ {
+ /* pop */
+ uint32_t * const pidxNode = a_pStack->apidxEntries[--a_pStack->cEntries];
+ uint32_t const idxNode = readIdx(pidxNode);
+ NodeType * const pNode = a_pAllocator->ptrFromInt(idxNode);
+ AssertMsgReturnStmt(a_pAllocator->isPtrRetOkay(pNode),
+ ("pidxNode=%p[%#x] pNode=%p\n", pidxNode, *pidxNode, pNode),
+ m_cErrors++, a_pAllocator->ptrErrToStatus(pNode));
+
+ /* Read node properties: */
+ uint32_t const idxLeftNode = readIdx(&pNode->idxLeft);
+ NodeType * const pLeftNode = a_pAllocator->ptrFromInt(idxLeftNode);
+ AssertMsgReturnStmt(a_pAllocator->isPtrRetOkay(pLeftNode),
+ ("idxLeftNode=%#x pLeftNode=%p\n", idxLeftNode, pLeftNode),
+ m_cErrors++, a_pAllocator->ptrErrToStatus(pLeftNode));
+
+ uint32_t const idxRightNode = readIdx(&pNode->idxRight);
+ NodeType * const pRightNode = a_pAllocator->ptrFromInt(idxRightNode);
+ AssertMsgReturnStmt(a_pAllocator->isPtrRetOkay(pRightNode),
+ ("idxRight=%#x pRightNode=%p\n", idxRightNode, pRightNode),
+ m_cErrors++, a_pAllocator->ptrErrToStatus(pRightNode));
+
+ uint8_t const cLeftHeight = pLeftNode ? pLeftNode->cHeight : 0;
+ AssertReturnStmt(cLeftHeight <= kMaxHeight, m_cErrors++, VERR_HARDAVL_BAD_LEFT_HEIGHT);
+
+ uint8_t const cRightHeight = pRightNode ? pRightNode->cHeight : 0;
+ AssertReturnStmt(cRightHeight <= kMaxHeight, m_cErrors++, VERR_HARDAVL_BAD_RIGHT_HEIGHT);
+
+ /* Decide what needs doing: */
+ if (cRightHeight + 1 < cLeftHeight)
+ {
+ Assert(cRightHeight + 2 == cLeftHeight);
+ AssertReturnStmt(pLeftNode, m_cErrors++, VERR_HARDAVL_UNEXPECTED_NULL_LEFT);
+
+ uint32_t const idxLeftLeftNode = readIdx(&pLeftNode->idxLeft);
+ NodeType * const pLeftLeftNode = a_pAllocator->ptrFromInt(idxLeftLeftNode);
+ AssertMsgReturnStmt(a_pAllocator->isPtrRetOkay(pLeftLeftNode),
+ ("idxLeftLeftNode=%#x pLeftLeftNode=%p\n", idxLeftLeftNode, pLeftLeftNode),
+ m_cErrors++, a_pAllocator->ptrErrToStatus(pLeftLeftNode));
+
+ uint32_t const idxLeftRightNode = readIdx(&pLeftNode->idxRight);
+ NodeType * const pLeftRightNode = a_pAllocator->ptrFromInt(idxLeftRightNode);
+ AssertMsgReturnStmt(a_pAllocator->isPtrRetOkay(pLeftRightNode),
+ ("idxLeftRightNode=%#x pLeftRightNode=%p\n", idxLeftRightNode, pLeftRightNode),
+ m_cErrors++, a_pAllocator->ptrErrToStatus(pLeftRightNode));
+
+ uint8_t const cLeftRightHeight = pLeftRightNode ? pLeftRightNode->cHeight : 0;
+ if ((pLeftLeftNode ? pLeftLeftNode->cHeight : 0) >= cLeftRightHeight)
+ {
+ AssertReturnStmt(cLeftRightHeight + 2 <= kMaxHeight, m_cErrors++, VERR_HARDAVL_BAD_NEW_HEIGHT);
+ pNode->idxLeft = idxLeftRightNode;
+ pNode->cHeight = (uint8_t)(cLeftRightHeight + 1);
+ pLeftNode->cHeight = (uint8_t)(cLeftRightHeight + 2);
+ pLeftNode->idxRight = idxNode;
+ *pidxNode = idxLeftNode;
+#ifdef DEBUG
+ if (a_fLog) RTAssertMsg2("rebalance: %#2u: op #1\n", a_pStack->cEntries);
+#endif
+ }
+ else
+ {
+ AssertReturnStmt(cLeftRightHeight <= kMaxHeight, m_cErrors++, VERR_HARDAVL_BAD_RIGHT_HEIGHT);
+ AssertReturnStmt(pLeftRightNode, m_cErrors++, VERR_HARDAVL_UNEXPECTED_NULL_RIGHT);
+
+ uint32_t const idxLeftRightLeftNode = readIdx(&pLeftRightNode->idxLeft);
+ AssertReturnStmt(a_pAllocator->isIntValid(idxLeftRightLeftNode), m_cErrors++, VERR_HARDAVL_INDEX_OUT_OF_BOUNDS);
+ uint32_t const idxLeftRightRightNode = readIdx(&pLeftRightNode->idxRight);
+ AssertReturnStmt(a_pAllocator->isIntValid(idxLeftRightRightNode), m_cErrors++, VERR_HARDAVL_INDEX_OUT_OF_BOUNDS);
+ pLeftNode->idxRight = idxLeftRightLeftNode;
+ pNode->idxLeft = idxLeftRightRightNode;
+
+ pLeftRightNode->idxLeft = idxLeftNode;
+ pLeftRightNode->idxRight = idxNode;
+ pLeftNode->cHeight = cLeftRightHeight;
+ pNode->cHeight = cLeftRightHeight;
+ pLeftRightNode->cHeight = cLeftHeight;
+ *pidxNode = idxLeftRightNode;
+#ifdef DEBUG
+ if (a_fLog) RTAssertMsg2("rebalance: %#2u: op #2\n", a_pStack->cEntries);
+#endif
+ }
+ m_cRebalancingOperations++;
+ }
+ else if (cLeftHeight + 1 < cRightHeight)
+ {
+ Assert(cLeftHeight + 2 == cRightHeight);
+ AssertReturnStmt(pRightNode, m_cErrors++, VERR_HARDAVL_UNEXPECTED_NULL_RIGHT);
+
+ uint32_t const idxRightLeftNode = readIdx(&pRightNode->idxLeft);
+ NodeType * const pRightLeftNode = a_pAllocator->ptrFromInt(idxRightLeftNode);
+ AssertMsgReturnStmt(a_pAllocator->isPtrRetOkay(pRightLeftNode),
+ ("idxRightLeftNode=%#x pRightLeftNode=%p\n", idxRightLeftNode, pRightLeftNode),
+ m_cErrors++, a_pAllocator->ptrErrToStatus(pRightLeftNode));
+
+ uint32_t const idxRightRightNode = readIdx(&pRightNode->idxRight);
+ NodeType * const pRightRightNode = a_pAllocator->ptrFromInt(idxRightRightNode);
+ AssertMsgReturnStmt(a_pAllocator->isPtrRetOkay(pRightRightNode),
+ ("idxRightRightNode=%#x pRightRightNode=%p\n", idxRightRightNode, pRightRightNode),
+ m_cErrors++, a_pAllocator->ptrErrToStatus(pRightRightNode));
+
+ uint8_t const cRightLeftHeight = pRightLeftNode ? pRightLeftNode->cHeight : 0;
+ if ((pRightRightNode ? pRightRightNode->cHeight : 0) >= cRightLeftHeight)
+ {
+ AssertReturnStmt(cRightLeftHeight + 2 <= kMaxHeight, m_cErrors++, VERR_HARDAVL_BAD_NEW_HEIGHT);
+
+ pNode->idxRight = idxRightLeftNode;
+ pRightNode->idxLeft = idxNode;
+ pNode->cHeight = (uint8_t)(cRightLeftHeight + 1);
+ pRightNode->cHeight = (uint8_t)(cRightLeftHeight + 2);
+ *pidxNode = idxRightNode;
+#ifdef DEBUG
+ if (a_fLog) RTAssertMsg2("rebalance: %#2u: op #3 h=%d, *pidxNode=%#x\n", a_pStack->cEntries, pRightNode->cHeight, *pidxNode);
+#endif
+ RTHARDAVL_STRICT_CHECK_HEIGHTS(pRightNode, NULL, 0);
+ RTHARDAVL_STRICT_CHECK_HEIGHTS(pNode, NULL, 0);
+ }
+ else
+ {
+ AssertReturnStmt(cRightLeftHeight <= kMaxHeight, m_cErrors++, VERR_HARDAVL_BAD_LEFT_HEIGHT);
+ AssertReturnStmt(pRightLeftNode, m_cErrors++, VERR_HARDAVL_UNEXPECTED_NULL_LEFT);
+
+ uint32_t const idxRightLeftRightNode = readIdx(&pRightLeftNode->idxRight);
+ AssertReturnStmt(a_pAllocator->isIntValid(idxRightLeftRightNode), m_cErrors++, VERR_HARDAVL_INDEX_OUT_OF_BOUNDS);
+ uint32_t const idxRightLeftLeftNode = readIdx(&pRightLeftNode->idxLeft);
+ AssertReturnStmt(a_pAllocator->isIntValid(idxRightLeftLeftNode), m_cErrors++, VERR_HARDAVL_INDEX_OUT_OF_BOUNDS);
+ pRightNode->idxLeft = idxRightLeftRightNode;
+ pNode->idxRight = idxRightLeftLeftNode;
+
+ pRightLeftNode->idxRight = idxRightNode;
+ pRightLeftNode->idxLeft = idxNode;
+ pRightNode->cHeight = cRightLeftHeight;
+ pNode->cHeight = cRightLeftHeight;
+ pRightLeftNode->cHeight = cRightHeight;
+ *pidxNode = idxRightLeftNode;
+#ifdef DEBUG
+ if (a_fLog) RTAssertMsg2("rebalance: %#2u: op #4 h=%d, *pidxNode=%#x\n", a_pStack->cEntries, pRightLeftNode->cHeight, *pidxNode);
+#endif
+ }
+ m_cRebalancingOperations++;
+ }
+ else
+ {
+ uint8_t const cHeight = (uint8_t)(RT_MAX(cLeftHeight, cRightHeight) + 1);
+ AssertReturnStmt(cHeight <= kMaxHeight, m_cErrors++, VERR_HARDAVL_BAD_NEW_HEIGHT);
+ if (cHeight == pNode->cHeight)
+ {
+#ifdef DEBUG
+ if (a_fLog) RTAssertMsg2("rebalance: %#2u: op #5, h=%d - done\n", a_pStack->cEntries, cHeight);
+#endif
+ RTHARDAVL_STRICT_CHECK_HEIGHTS(pNode, NULL, 0);
+ if (pLeftNode)
+ RTHARDAVL_STRICT_CHECK_HEIGHTS(pLeftNode, NULL, 0);
+ if (pRightNode)
+ RTHARDAVL_STRICT_CHECK_HEIGHTS(pRightNode, NULL, 0);
+ break;
+ }
+#ifdef DEBUG
+ if (a_fLog) RTAssertMsg2("rebalance: %#2u: op #5, h=%d - \n", a_pStack->cEntries, cHeight);
+#endif
+ pNode->cHeight = cHeight;
+ }
+ }
+ return VINF_SUCCESS;
+ }
+};
+
+/** @} */
+
+#endif /* !IPRT_INCLUDED_cpp_hardavlrange_h */
+
diff --git a/include/iprt/cpp/hardavlslaballocator.h b/include/iprt/cpp/hardavlslaballocator.h
new file mode 100644
index 00000000..515782b5
--- /dev/null
+++ b/include/iprt/cpp/hardavlslaballocator.h
@@ -0,0 +1,218 @@
+/** @file
+ * IPRT - Hardened AVL tree slab allocator.
+ */
+
+/*
+ * Copyright (C) 2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_cpp_hardavlslaballocator_h
+#define IPRT_INCLUDED_cpp_hardavlslaballocator_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/asm.h>
+#include <iprt/assert.h>
+#include <iprt/err.h>
+#include <iprt/string.h>
+
+/** @addtogroup grp_rt_cpp_hardavl
+ * @{
+ */
+
+
+/**
+ * Slab allocator for the hardened AVL tree.
+ */
+template<typename NodeType>
+struct RTCHardAvlTreeSlabAllocator
+{
+ /** Pointer to an array of nodes. */
+ NodeType *m_paNodes;
+ /** Node allocation bitmap: 1 = free, 0 = allocated. */
+ uint64_t *m_pbmAlloc;
+ /** Max number of nodes in m_paNodes and valid bits in m_pbmAlloc. */
+ uint32_t m_cNodes;
+ /** Pointer error counter. */
+ uint32_t m_cErrors;
+ /** Allocation hint. */
+ uint32_t m_idxAllocHint;
+ uint32_t m_uPadding;
+
+ enum
+ {
+ kNilIndex = 0,
+ kErr_IndexOutOfBound = -1,
+ kErr_PointerOutOfBound = -2,
+ kErr_MisalignedPointer = -3,
+ kErr_NodeIsFree = -4,
+ kErr_Last = kErr_NodeIsFree
+ };
+
+ RTCHardAvlTreeSlabAllocator() RT_NOEXCEPT
+ : m_paNodes(NULL)
+ , m_pbmAlloc(NULL)
+ , m_cNodes(0)
+ , m_cErrors(0)
+ , m_idxAllocHint(0)
+ , m_uPadding(0)
+ {}
+
+ inline void initSlabAllocator(uint32_t a_cNodes, NodeType *a_paNodes, uint64_t *a_pbmAlloc) RT_NOEXCEPT
+ {
+ m_cNodes = a_cNodes;
+ m_paNodes = a_paNodes;
+ m_pbmAlloc = a_pbmAlloc;
+
+ /* Initialize the allocation bit. */
+ RT_BZERO(a_pbmAlloc, (a_cNodes + 63) / 64 * 8);
+ ASMBitSetRange(a_pbmAlloc, 0, a_cNodes);
+ }
+
+ inline NodeType *ptrFromInt(uint32_t a_idxNode1) RT_NOEXCEPT
+ {
+ if (a_idxNode1 == (uint32_t)kNilIndex)
+ return NULL;
+ AssertMsgReturnStmt(a_idxNode1 <= m_cNodes, ("a_idxNode1=%#x m_cNodes=%#x\n", a_idxNode1, m_cNodes),
+ m_cErrors++, (NodeType *)(intptr_t)kErr_IndexOutOfBound);
+ AssertMsgReturnStmt(ASMBitTest(m_pbmAlloc, a_idxNode1 - 1) == false, ("a_idxNode1=%#x\n", a_idxNode1),
+ m_cErrors++, (NodeType *)(intptr_t)kErr_NodeIsFree);
+ return &m_paNodes[a_idxNode1 - 1];
+ }
+
+ static inline bool isPtrRetOkay(NodeType *a_pNode) RT_NOEXCEPT
+ {
+ return (uintptr_t)a_pNode < (uintptr_t)kErr_Last;
+ }
+
+ static inline int ptrErrToStatus(NodeType *a_pNode) RT_NOEXCEPT
+ {
+ return (int)(intptr_t)a_pNode - (VERR_HARDAVL_INDEX_OUT_OF_BOUNDS - kErr_IndexOutOfBound);
+ }
+
+ inline uint32_t ptrToInt(NodeType *a_pNode) RT_NOEXCEPT
+ {
+ if (a_pNode == NULL)
+ return 0;
+ uintptr_t const offNode = (uintptr_t)a_pNode - (uintptr_t)m_paNodes;
+ uintptr_t const idxNode0 = offNode / sizeof(m_paNodes[0]);
+ AssertMsgReturnStmt((offNode % sizeof(m_paNodes[0])) == 0,
+ ("pNode=%p / offNode=%#zx vs m_paNodes=%p L %#x, each %#x bytes\n",
+ a_pNode, offNode, m_paNodes, m_cNodes, sizeof(m_paNodes[0])),
+ m_cErrors++, (uint32_t)kErr_MisalignedPointer);
+ AssertMsgReturnStmt(idxNode0 < m_cNodes,
+ ("pNode=%p vs m_paNodes=%p L %#x\n", a_pNode, m_paNodes, m_cNodes),
+ m_cErrors++, (uint32_t)kErr_PointerOutOfBound);
+ AssertMsgReturnStmt(ASMBitTest(m_pbmAlloc, idxNode0) == false, ("a_pNode=%p idxNode0=%#x\n", a_pNode, idxNode0),
+ m_cErrors++, (uint32_t)kErr_NodeIsFree);
+ return idxNode0 + 1;
+ }
+
+ static inline bool isIdxRetOkay(uint32_t a_idxNode) RT_NOEXCEPT
+ {
+ return a_idxNode < (uint32_t)kErr_Last;
+ }
+
+ static inline int idxErrToStatus(uint32_t a_idxNode) RT_NOEXCEPT
+ {
+ return (int)a_idxNode - (VERR_HARDAVL_INDEX_OUT_OF_BOUNDS - kErr_IndexOutOfBound);
+ }
+
+ inline bool isIntValid(uint32_t a_idxNode1) RT_NOEXCEPT
+ {
+ return a_idxNode1 <= m_cNodes;
+ }
+
+ inline int freeNode(NodeType *a_pNode) RT_NOEXCEPT
+ {
+ uint32_t idxNode1 = ptrToInt(a_pNode);
+ if (idxNode1 == (uint32_t)kNilIndex)
+ return 0;
+ if (idxNode1 < (uint32_t)kErr_Last)
+ {
+ AssertMsgReturnStmt(ASMAtomicBitTestAndSet(m_pbmAlloc, idxNode1 - 1) == false,
+ ("a_pNode=%p idxNode1=%#x\n", a_pNode, idxNode1),
+ m_cErrors++, kErr_NodeIsFree);
+ return 0;
+ }
+ return (int)idxNode1;
+ }
+
+ inline NodeType *allocateNode(void) RT_NOEXCEPT
+ {
+ /*
+ * Use the hint first, then scan the whole bitmap.
+ * Note! We don't expect concurrent allocation calls, so no need to repeat.
+ */
+ uint32_t const idxHint = m_idxAllocHint;
+ uint32_t idxNode0;
+ if ( idxHint >= m_cNodes
+ || (int32_t)(idxNode0 = (uint32_t)ASMBitNextSet(m_pbmAlloc, m_cNodes, idxHint)) < 0)
+ idxNode0 = (uint32_t)ASMBitFirstSet(m_pbmAlloc, m_cNodes);
+ if ((int32_t)idxNode0 >= 0)
+ {
+ if (ASMAtomicBitTestAndClear(m_pbmAlloc, idxNode0) == true)
+ {
+ m_idxAllocHint = idxNode0;
+ return &m_paNodes[idxNode0];
+ }
+ AssertMsgFailed(("idxNode0=%#x\n", idxNode0));
+ m_cErrors++;
+ }
+ return NULL;
+ }
+};
+
+
+/**
+ * Placeholder structure for ring-3 slab allocator.
+ */
+typedef struct RTCHardAvlTreeSlabAllocatorR3_T
+{
+ /** Pointer to an array of nodes. */
+ RTR3PTR m_paNodes;
+ /** Node allocation bitmap: 1 = free, 0 = allocated. */
+ RTR3PTR m_pbmAlloc;
+ /** Max number of nodes in m_paNodes and valid bits in m_pbmAlloc. */
+ uint32_t m_cNodes;
+ /** Pointer error counter. */
+ uint32_t m_cErrors;
+ /** Allocation hint. */
+ uint32_t m_idxAllocHint;
+ uint32_t m_uPadding;
+} RTCHardAvlTreeSlabAllocatorR3_T;
+AssertCompileSize(RTCHardAvlTreeSlabAllocatorR3_T,
+ sizeof(RTCHardAvlTreeSlabAllocator<RTUINT128U>) - (sizeof(void *) - sizeof(RTR3PTR)) * 2);
+
+/** @} */
+
+#endif /* !IPRT_INCLUDED_cpp_hardavlslaballocator_h */
+
diff --git a/include/iprt/cpp/list.h b/include/iprt/cpp/list.h
new file mode 100644
index 00000000..864c3329
--- /dev/null
+++ b/include/iprt/cpp/list.h
@@ -0,0 +1,1143 @@
+/** @file
+ * IPRT - Generic List Class.
+ */
+
+/*
+ * Copyright (C) 2011-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_cpp_list_h
+#define IPRT_INCLUDED_cpp_list_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cpp/meta.h>
+#include <iprt/mem.h>
+#include <iprt/string.h> /* for memcpy */
+#include <iprt/assert.h>
+
+#include <new> /* For std::bad_alloc */
+
+/** @defgroup grp_rt_cpp_list C++ List support
+ * @ingroup grp_rt_cpp
+ *
+ * @brief Generic C++ list class support.
+ *
+ * This list classes manage any amount of data in a fast and easy to use way.
+ * They have no dependencies on STL, only on generic memory management methods
+ * of IRPT. This allows list handling in situations where the use of STL
+ * container classes is forbidden.
+ *
+ * Not all of the functionality of STL container classes is implemented. There
+ * are no iterators or any other high level access/modifier methods (e.g.
+ * std::algorithms).
+ *
+ * The implementation is array based which allows fast access to the items.
+ * Appending items is usually also fast, cause the internal array is
+ * preallocated. To minimize the memory overhead, native types (that is
+ * everything smaller then the size of void*) are directly saved in the array.
+ * If bigger types are used (e.g. RTCString) the internal array is an array of
+ * pointers to the objects.
+ *
+ * The size of the internal array will usually not shrink, but grow
+ * automatically. Only certain methods, like RTCList::clear or the "=" operator
+ * will reset any previously allocated memory. You can call
+ * RTCList::setCapacity for manual adjustment. If the size of an new list will
+ * be known, calling the constructor with the necessary capacity will speed up
+ * the insertion of the new items.
+ *
+ * For the full public interface these list classes offer see RTCListBase.
+ *
+ * There are some requirements for the types used which follow:
+ * -# They need a default and a copy constructor.
+ * -# Some methods (e.g. RTCList::contains) need an equal operator.
+ * -# If the type is some complex class (that is, having a constructor which
+ * allocates members on the heap) it has to be greater than sizeof(void*) to
+ * be used correctly. If this is not the case you can manually overwrite the
+ * list behavior. Just add T* as a second parameter to the list template if
+ * your class is called T. Another possibility is to specialize the list for
+ * your target class. See below for more information.
+ *
+ * The native types like int, bool, ptr, ..., are meeting this criteria, so
+ * they are save to use.
+ *
+ * Please note that the return type of some of the getter methods are slightly
+ * different depending on the list type. Native types return the item by value,
+ * items with a size greater than sizeof(void*) by reference. As native types
+ * saved directly in the internal array, returning a reference to them (and
+ * saving them in a reference as well) would make them invalid (or pointing to
+ * a wrong item) when the list is changed in the meanwhile. Returning a
+ * reference for bigger types isn't problematic and makes sure we get out the
+ * best speed of the list. The one exception to this rule is the index
+ * operator[]. This operator always return a reference to make it possible to
+ * use it as a lvalue. Its your responsibility to make sure the list isn't
+ * changed when using the value as reference returned by this operator.
+ *
+ * The list class is reentrant. For a thread-safe variant see RTCMTList.
+ *
+ * Implementation details:
+ * It is possible to specialize any type. This might be necessary to get the
+ * best speed out of the list. Examples are the 64-bit types, which use the
+ * native (no pointers) implementation even on a 32-bit host. Consult the
+ * source code for more details.
+ *
+ * Current specialized implementations:
+ * - int64_t: RTCList<int64_t>
+ * - uint64_t: RTCList<uint64_t>
+ *
+ * @{
+ */
+
+/**
+ * The guard definition.
+ */
+template <bool G>
+class RTCListGuard;
+
+/**
+ * The default guard which does nothing.
+ */
+template <>
+class RTCListGuard<false>
+{
+public:
+ inline void enterRead() const {}
+ inline void leaveRead() const {}
+ inline void enterWrite() {}
+ inline void leaveWrite() {}
+
+ /* Define our own new and delete. */
+#ifdef RT_NEED_NEW_AND_DELETE
+ RTMEM_IMPLEMENT_NEW_AND_DELETE();
+#else
+ RTMEMEF_NEW_AND_DELETE_OPERATORS();
+#endif
+};
+
+/**
+ * General helper template for managing native values in RTCListBase.
+ */
+template <typename T1, typename T2>
+class RTCListHelper
+{
+public:
+ static inline void set(T2 *p, size_t i, const T1 &v) { p[i] = v; }
+ static inline T1 & at(T2 *p, size_t i) { return p[i]; }
+ static inline const T1 &atConst(T2 const *p, size_t i) { return p[i]; }
+ static inline size_t find(T2 *p, const T1 &v, size_t cElements)
+ {
+ size_t i = cElements;
+ while (i-- > 0)
+ if (p[i] == v)
+ return i;
+ return cElements;
+ }
+ static inline void copyTo(T2 *p, T2 *const p1 , size_t iTo, size_t cSize)
+ {
+ if (cSize > 0)
+ memcpy(&p[iTo], &p1[0], sizeof(T1) * cSize);
+ }
+ static inline void erase(T2 * /* p */, size_t /* i */) { /* Nothing to do here. */ }
+ static inline void eraseRange(T2 * /* p */, size_t /* cFrom */, size_t /* cSize */) { /* Nothing to do here. */ }
+};
+
+/**
+ * Specialized helper template for managing pointer values in RTCListBase.
+ */
+template <typename T1>
+class RTCListHelper<T1, T1*>
+{
+public:
+ static inline void set(T1 **p, size_t i, const T1 &v) { p[i] = new T1(v); }
+ static inline T1 & at(T1 **p, size_t i) { return *p[i]; }
+ static inline const T1 &atConst(T1 * const *p, size_t i) { return *p[i]; }
+ static inline size_t find(T1 **p, const T1 &v, size_t cElements)
+ {
+ size_t i = cElements;
+ while (i-- > 0)
+ if (*p[i] == v)
+ return i;
+ return cElements;
+ }
+ static inline void copyTo(T1 **p, T1 **const p1 , size_t iTo, size_t cSize)
+ {
+ for (size_t i = 0; i < cSize; ++i)
+ p[iTo + i] = new T1(*p1[i]);
+ }
+ static inline void erase(T1 **p, size_t i) { delete p[i]; }
+ static inline void eraseRange(T1 **p, size_t iFrom, size_t cItems)
+ {
+ while (cItems-- > 0)
+ delete p[iFrom++];
+ }
+};
+
+/**
+ * This is the base class for all other list classes. It implements the
+ * necessary list functionality in a type independent way and offers the public
+ * list interface to the user.
+ */
+template <class T, typename ITYPE, bool MT>
+class RTCListBase
+{
+ /** @name Traits.
+ *
+ * Defines the return type of most of the getter methods. If the internal
+ * used type is a pointer, we return a reference. If not we return by
+ * value.
+ *
+ * @{
+ */
+ typedef typename RTCIfPtr<ITYPE, T&, T>::result GET_RTYPE;
+ typedef typename RTCIfPtr<ITYPE, const T&, T>::result GET_CRTYPE;
+ /** @} */
+
+public:
+ /**
+ * Creates a new list.
+ *
+ * This preallocates @a cCapacity elements within the list.
+ *
+ * @param cCapacity The initial capacity the list has.
+ * @throws std::bad_alloc
+ */
+ RTCListBase(size_t cCapacity = kDefaultCapacity)
+ : m_pArray(0)
+ , m_cElements(0)
+ , m_cCapacity(0)
+ {
+ if (cCapacity > 0)
+ growArray(cCapacity);
+ }
+
+ /**
+ * Creates a copy of another list.
+ *
+ * The other list will be fully copied and the capacity will be the same as
+ * the size of the other list.
+ *
+ * @param other The list to copy.
+ * @throws std::bad_alloc
+ */
+ RTCListBase(const RTCListBase<T, ITYPE, MT>& other)
+ : m_pArray(0)
+ , m_cElements(0)
+ , m_cCapacity(0)
+ {
+ other.m_guard.enterRead();
+
+ size_t const cElementsOther = other.m_cElements;
+ resizeArrayNoErase(cElementsOther);
+ RTCListHelper<T, ITYPE>::copyTo(m_pArray, other.m_pArray, 0, cElementsOther);
+ m_cElements = cElementsOther;
+
+ other.m_guard.leaveRead();
+ }
+
+ /**
+ * Destructor.
+ */
+ ~RTCListBase()
+ {
+ RTCListHelper<T, ITYPE>::eraseRange(m_pArray, 0, m_cElements);
+ if (m_pArray)
+ {
+ RTMemFree(m_pArray);
+ m_pArray = NULL;
+ }
+ m_cElements = m_cCapacity = 0;
+ }
+
+ /**
+ * Sets a new capacity within the list.
+ *
+ * If the new capacity is bigger than the old size, it will be simply
+ * preallocated more space for the new items. If the new capacity is
+ * smaller than the previous size, items at the end of the list will be
+ * deleted.
+ *
+ * @param cCapacity The new capacity within the list.
+ * @throws std::bad_alloc
+ */
+ void setCapacity(size_t cCapacity)
+ {
+ m_guard.enterWrite();
+ resizeArray(cCapacity);
+ m_guard.leaveWrite();
+ }
+
+ /**
+ * Return the current capacity of the list.
+ *
+ * @return The actual capacity.
+ */
+ size_t capacity() const
+ {
+ m_guard.enterRead();
+ size_t cRet = m_cCapacity;
+ m_guard.leaveRead();
+ return cRet;
+ }
+
+ /**
+ * Check if an list contains any items.
+ *
+ * @return True if there is more than zero items, false otherwise.
+ */
+ bool isEmpty() const
+ {
+ m_guard.enterRead();
+ bool fEmpty = m_cElements == 0;
+ m_guard.leaveRead();
+ return fEmpty;
+ }
+
+ /**
+ * Return the current count of elements within the list.
+ *
+ * @return The current element count.
+ */
+ size_t size() const
+ {
+ m_guard.enterRead();
+ size_t cRet = m_cElements;
+ m_guard.leaveRead();
+ return cRet;
+ }
+
+ /**
+ * Inserts an item to the list at position @a i.
+ *
+ * @param i The position of the new item. The must be within or at the
+ * exact end of the list. Indexes specified beyond the end of
+ * the list will be changed to an append() operation and strict
+ * builds will raise an assert.
+ * @param val The new item.
+ * @return a reference to this list.
+ * @throws std::bad_alloc
+ */
+ RTCListBase<T, ITYPE, MT> &insert(size_t i, const T &val)
+ {
+ m_guard.enterWrite();
+
+ AssertMsgStmt(i <= m_cElements, ("i=%zu m_cElements=%zu\n", i, m_cElements), i = m_cElements);
+
+ if (m_cElements == m_cCapacity)
+ growArray(m_cCapacity + kDefaultCapacity);
+
+ memmove(&m_pArray[i + 1], &m_pArray[i], (m_cElements - i) * sizeof(ITYPE));
+ RTCListHelper<T, ITYPE>::set(m_pArray, i, val);
+ ++m_cElements;
+
+ m_guard.leaveWrite();
+ return *this;
+ }
+
+ /**
+ * Inserts a list to the list at position @a i.
+ *
+ * @param i The position of the new item. The must be within or at the
+ * exact end of the list. Indexes specified beyond the end of
+ * the list will be changed to an append() operation and strict
+ * builds will raise an assert.
+ * @param other The other list. This MUST not be the same as the destination
+ * list, will assert and return without doing anything if this
+ * happens.
+ * @return a reference to this list.
+ * @throws std::bad_alloc
+ */
+ RTCListBase<T, ITYPE, MT> &insert(size_t i, const RTCListBase<T, ITYPE, MT> &other)
+ {
+ AssertReturn(this != &other, *this);
+
+ other.m_guard.enterRead();
+ m_guard.enterWrite();
+
+ AssertMsgStmt(i <= m_cElements, ("i=%zu m_cElements=%zu\n", i, m_cElements), i = m_cElements);
+
+ size_t cElementsOther = other.m_cElements;
+ if (RT_LIKELY(cElementsOther > 0))
+ {
+ if (m_cCapacity - m_cElements < cElementsOther)
+ growArray(m_cCapacity + (cElementsOther - (m_cCapacity - m_cElements)));
+ if (i < m_cElements)
+ memmove(&m_pArray[i + cElementsOther], &m_pArray[i], (m_cElements - i) * sizeof(ITYPE));
+
+ RTCListHelper<T, ITYPE>::copyTo(&m_pArray[i], other.m_pArray, 0, cElementsOther);
+ m_cElements += cElementsOther;
+ }
+
+ m_guard.leaveWrite();
+ other.m_guard.leaveRead();
+ return *this;
+ }
+
+ /**
+ * Prepend an item to the list.
+ *
+ * @param val The new item.
+ * @return a reference to this list.
+ * @throws std::bad_alloc
+ */
+ RTCListBase<T, ITYPE, MT> &prepend(const T &val)
+ {
+ return insert(0, val);
+ }
+
+ /**
+ * Prepend a list of type T to the list.
+ *
+ * @param other The list to prepend.
+ * @return a reference to this list.
+ * @throws std::bad_alloc
+ */
+ RTCListBase<T, ITYPE, MT> &prepend(const RTCListBase<T, ITYPE, MT> &other)
+ {
+ return insert(0, other);
+ }
+
+ /**
+ * Append a default item to the list.
+ *
+ * @return a mutable reference to the item
+ * @throws std::bad_alloc
+ */
+ GET_RTYPE append()
+ {
+ m_guard.enterWrite();
+ if (m_cElements == m_cCapacity)
+ growArray(m_cCapacity + kDefaultCapacity);
+ RTCListHelper<T, ITYPE>::set(m_pArray, m_cElements, T());
+ GET_RTYPE rRet = RTCListHelper<T, ITYPE>::at(m_pArray, m_cElements);
+ ++m_cElements;
+ m_guard.leaveWrite();
+
+ return rRet;
+ }
+
+ /**
+ * Append an item to the list.
+ *
+ * @param val The new item.
+ * @return a reference to this list.
+ * @throws std::bad_alloc
+ */
+ RTCListBase<T, ITYPE, MT> &append(const T &val)
+ {
+ m_guard.enterWrite();
+ if (m_cElements == m_cCapacity)
+ growArray(m_cCapacity + kDefaultCapacity);
+ RTCListHelper<T, ITYPE>::set(m_pArray, m_cElements, val);
+ ++m_cElements;
+ m_guard.leaveWrite();
+
+ return *this;
+ }
+
+ /**
+ * Append a list of type T to the list.
+ *
+ * @param other The list to append. Must not be the same as the destination
+ * list, will assert and return without doing anything.
+ * @return a reference to this list.
+ * @throws std::bad_alloc
+ */
+ RTCListBase<T, ITYPE, MT> &append(const RTCListBase<T, ITYPE, MT> &other)
+ {
+ AssertReturn(this != &other, *this);
+
+ other.m_guard.enterRead();
+ m_guard.enterWrite();
+
+ insert(m_cElements, other);
+
+ m_guard.leaveWrite();
+ other.m_guard.leaveRead();
+ return *this;
+ }
+
+ /**
+ * Copy the items of the other list into this list.
+ *
+ * All previous items of this list are deleted.
+ *
+ * @param other The list to copy.
+ * @return a reference to this list.
+ */
+ RTCListBase<T, ITYPE, MT> &operator=(const RTCListBase<T, ITYPE, MT>& other)
+ {
+ /* Prevent self assignment */
+ if (RT_LIKELY(this != &other))
+ {
+ other.m_guard.enterRead();
+ m_guard.enterWrite();
+
+ /* Delete all items. */
+ RTCListHelper<T, ITYPE>::eraseRange(m_pArray, 0, m_cElements);
+
+ /* Need we to realloc memory. */
+ if (other.m_cElements != m_cCapacity)
+ resizeArrayNoErase(other.m_cElements);
+ m_cElements = other.m_cElements;
+
+ /* Copy new items. */
+ RTCListHelper<T, ITYPE>::copyTo(m_pArray, other.m_pArray, 0, other.m_cElements);
+
+ m_guard.leaveWrite();
+ other.m_guard.leaveRead();
+ }
+ return *this;
+ }
+
+ /**
+ * Compares if this list's items match the other list.
+ *
+ * @returns \c true if both lists contain the same items, \c false if not.
+ * @param other The list to compare this list with.
+ */
+ bool operator==(const RTCListBase<T, ITYPE, MT>& other)
+ {
+ /* Prevent self comparrison */
+ if (RT_LIKELY(this == &other))
+ return true;
+
+ other.m_guard.enterRead();
+ m_guard.enterRead();
+
+ bool fEqual = true;
+ if (other.m_cElements == m_cElements)
+ {
+ for (size_t i = 0; i < m_cElements; i++)
+ {
+ if (RTCListHelper<T, ITYPE>::at(m_pArray, i) != RTCListHelper<T, ITYPE>::at(other.m_pArray, i))
+ {
+ fEqual = false;
+ break;
+ }
+ }
+ }
+ else
+ fEqual = false;
+
+ m_guard.leaveRead();
+ other.m_guard.leaveRead();
+
+ return fEqual;
+ }
+
+ /**
+ * Compares if this list's items do not match the other list.
+ *
+ * @returns \c true if the lists do not match, \c false if otherwise.
+ * @param other The list to compare this list with.
+ */
+ bool operator!=(const RTCListBase<T, ITYPE, MT>& other)
+ {
+ return !(*this == other);
+ }
+
+ /**
+ * Replace an item in the list.
+ *
+ * @param i The position of the item to replace. If this is out of range,
+ * the request will be ignored, strict builds will assert.
+ * @param val The new value.
+ * @return a reference to this list.
+ */
+ RTCListBase<T, ITYPE, MT> &replace(size_t i, const T &val)
+ {
+ m_guard.enterWrite();
+
+ if (i < m_cElements)
+ {
+ RTCListHelper<T, ITYPE>::erase(m_pArray, i);
+ RTCListHelper<T, ITYPE>::set(m_pArray, i, val);
+ }
+ else
+ AssertMsgFailed(("i=%zu m_cElements=%zu\n", i, m_cElements));
+
+ m_guard.leaveWrite();
+ return *this;
+ }
+
+ /**
+ * Applies a filter of type T to this list.
+ *
+ * @param other The list which contains the elements to filter out from this list.
+ * @return a reference to this list.
+ */
+ RTCListBase<T, ITYPE, MT> &filter(const RTCListBase<T, ITYPE, MT> &other)
+ {
+ AssertReturn(this != &other, *this);
+
+ other.m_guard.enterRead();
+ m_guard.enterWrite();
+
+ for (size_t i = 0; i < m_cElements; i++)
+ {
+ for (size_t f = 0; f < other.m_cElements; f++)
+ {
+ if (RTCListHelper<T, ITYPE>::at(m_pArray, i) == RTCListHelper<T, ITYPE>::at(other.m_pArray, f))
+ removeAtLocked(i);
+ }
+ }
+
+ m_guard.leaveWrite();
+ other.m_guard.leaveRead();
+ return *this;
+ }
+
+ /**
+ * Return the first item as constant object.
+ *
+ * @return A reference or pointer to the first item.
+ *
+ * @note No boundary checks are done. Make sure there is at least one
+ * element.
+ */
+ GET_CRTYPE first() const
+ {
+ m_guard.enterRead();
+ Assert(m_cElements > 0);
+ GET_CRTYPE res = RTCListHelper<T, ITYPE>::at(m_pArray, 0);
+ m_guard.leaveRead();
+ return res;
+ }
+
+ /**
+ * Return the first item.
+ *
+ * @return A reference or pointer to the first item.
+ *
+ * @note No boundary checks are done. Make sure there is at least one
+ * element.
+ */
+ GET_RTYPE first()
+ {
+ m_guard.enterRead();
+ Assert(m_cElements > 0);
+ GET_RTYPE res = RTCListHelper<T, ITYPE>::at(m_pArray, 0);
+ m_guard.leaveRead();
+ return res;
+ }
+
+ /**
+ * Return the last item as constant object.
+ *
+ * @return A reference or pointer to the last item.
+ *
+ * @note No boundary checks are done. Make sure there is at least one
+ * element.
+ */
+ GET_CRTYPE last() const
+ {
+ m_guard.enterRead();
+ Assert(m_cElements > 0);
+ GET_CRTYPE res = RTCListHelper<T, ITYPE>::at(m_pArray, m_cElements - 1);
+ m_guard.leaveRead();
+ return res;
+ }
+
+ /**
+ * Return the last item.
+ *
+ * @return A reference or pointer to the last item.
+ *
+ * @note No boundary checks are done. Make sure there is at least one
+ * element.
+ */
+ GET_RTYPE last()
+ {
+ m_guard.enterRead();
+ Assert(m_cElements > 0);
+ GET_RTYPE res = RTCListHelper<T, ITYPE>::at(m_pArray, m_cElements - 1);
+ m_guard.leaveRead();
+ return res;
+ }
+
+ /**
+ * Return the item at position @a i as constant object.
+ *
+ * @param i The position of the item to return. This better not be out of
+ * bounds, however should it be the last element of the array
+ * will be return and strict builds will raise an assertion.
+ * Should the array be empty, a crash is very likely.
+ * @return The item at position @a i.
+ */
+ GET_CRTYPE at(size_t i) const
+ {
+ m_guard.enterRead();
+ AssertMsgStmt(i < m_cElements, ("i=%zu m_cElements=%zu\n", i, m_cElements), i = m_cElements - 1);
+ GET_CRTYPE res = RTCListHelper<T, ITYPE>::at(m_pArray, i);
+ m_guard.leaveRead();
+ return res;
+ }
+
+ /**
+ * Return the item at position @a i.
+ *
+ * @param i The position of the item to return. This better not be out of
+ * bounds, however should it be the last element of the array
+ * will be return and strict builds will raise an assertion.
+ * Should the array be empty, a crash is very likely.
+ * @return The item at position @a i.
+ */
+ GET_RTYPE at(size_t i)
+ {
+ m_guard.enterRead();
+ AssertMsgStmt(i < m_cElements, ("i=%zu m_cElements=%zu\n", i, m_cElements), i = m_cElements - 1);
+ GET_RTYPE res = RTCListHelper<T, ITYPE>::at(m_pArray, i);
+ m_guard.leaveRead();
+ return res;
+ }
+
+ /**
+ * Return the item at position @a i as mutable reference.
+ *
+ * @param i The position of the item to return. This better not be out of
+ * bounds, however should it be the last element of the array
+ * will be return and strict builds will raise an assertion.
+ * Should the array be empty, a crash is very likely.
+ * @return The item at position @a i.
+ */
+ T &operator[](size_t i)
+ {
+ m_guard.enterRead();
+ AssertMsgStmt(i < m_cElements, ("i=%zu m_cElements=%zu\n", i, m_cElements), i = m_cElements - 1);
+ T &res = RTCListHelper<T, ITYPE>::at(m_pArray, i);
+ m_guard.leaveRead();
+ return res;
+ }
+
+ /**
+ * Return the item at position @a i as immutable reference.
+ *
+ * @param i The position of the item to return. This better not be out of
+ * bounds, however should it be the last element of the array
+ * will be return and strict builds will raise an assertion.
+ * Should the array be empty, a crash is very likely.
+ * @return The item at position @a i.
+ */
+ const T &operator[](size_t i) const
+ {
+ m_guard.enterRead();
+ AssertMsgStmt(i < m_cElements, ("i=%zu m_cElements=%zu\n", i, m_cElements), i = m_cElements - 1);
+ const T &rRet = RTCListHelper<T, ITYPE>::atConst(m_pArray, i);
+ m_guard.leaveRead();
+ return rRet;
+ }
+
+ /**
+ * Return a copy of the item at position @a i or default value if out of range.
+ *
+ * @param i The position of the item to return.
+ * @return Copy of the item at position @a i or default value.
+ */
+ T value(size_t i) const
+ {
+ m_guard.enterRead();
+ if (RT_LIKELY(i < m_cElements))
+ {
+ T res = RTCListHelper<T, ITYPE>::at(m_pArray, i);
+ m_guard.leaveRead();
+ return res;
+ }
+ m_guard.leaveRead();
+ return T();
+ }
+
+ /**
+ * Return a copy of the item at position @a i, or @a defaultVal if out of range.
+ *
+ * @param i The position of the item to return.
+ * @param defaultVal The value to return in case @a i is invalid.
+ * @return Copy of the item at position @a i or @a defaultVal.
+ */
+ T value(size_t i, const T &defaultVal) const
+ {
+ m_guard.enterRead();
+ if (RT_LIKELY(i < m_cElements))
+ {
+ T res = RTCListHelper<T, ITYPE>::at(m_pArray, i);
+ m_guard.leaveRead();
+ return res;
+ }
+ m_guard.leaveRead();
+ return defaultVal;
+ }
+
+ /**
+ * Check if @a val is contained in the array.
+ *
+ * @param val The value to check for.
+ * @return true if it is found, false otherwise.
+ */
+ bool contains(const T &val) const
+ {
+ m_guard.enterRead();
+ bool fRc = RTCListHelper<T, ITYPE>::find(m_pArray, val, m_cElements) < m_cElements;
+ m_guard.leaveRead();
+ return fRc;
+ }
+
+ /**
+ * Remove the first item.
+ *
+ * @note You should make sure the list isn't empty. Strict builds will assert.
+ * The other builds will quietly ignore the request.
+ */
+ void removeFirst()
+ {
+ removeAt(0);
+ }
+
+ /**
+ * Remove the last item.
+ *
+ * @note You should make sure the list isn't empty. Strict builds will assert.
+ * The other builds will quietly ignore the request.
+ */
+ void removeLast()
+ {
+ m_guard.enterWrite();
+ removeAtLocked(m_cElements - 1);
+ m_guard.leaveWrite();
+ }
+
+ /**
+ * Remove the item at position @a i.
+ *
+ * @param i The position of the item to remove. Out of bounds values will
+ * be ignored and an assertion will be raised in strict builds.
+ */
+ void removeAt(size_t i)
+ {
+ m_guard.enterWrite();
+ removeAtLocked(i);
+ m_guard.leaveWrite();
+ }
+
+ /**
+ * Remove a range of items from the list.
+ *
+ * @param iStart The start position of the items to remove.
+ * @param iEnd The end position of the items to remove (excluded).
+ */
+ void removeRange(size_t iStart, size_t iEnd)
+ {
+ AssertReturnVoid(iStart <= iEnd);
+ m_guard.enterWrite();
+
+ AssertMsgStmt(iEnd <= m_cElements, ("iEnd=%zu m_cElements=%zu\n", iEnd, m_cElements), iEnd = m_cElements);
+ AssertMsgStmt(iStart < m_cElements, ("iStart=%zu m_cElements=%zu\n", iStart, m_cElements), iStart = m_cElements);
+ size_t const cElements = iEnd - iStart;
+ if (cElements > 0)
+ {
+ Assert(iStart < m_cElements);
+ RTCListHelper<T, ITYPE>::eraseRange(m_pArray, iStart, cElements);
+ if (m_cElements > iEnd)
+ memmove(&m_pArray[iStart], &m_pArray[iEnd], (m_cElements - iEnd) * sizeof(ITYPE));
+ m_cElements -= cElements;
+ }
+
+ m_guard.leaveWrite();
+ }
+
+ /**
+ * Delete all items in the list.
+ */
+ void clear()
+ {
+ m_guard.enterWrite();
+
+ /* Values cleanup */
+ RTCListHelper<T, ITYPE>::eraseRange(m_pArray, 0, m_cElements);
+ if (m_cElements != kDefaultCapacity)
+ resizeArrayNoErase(kDefaultCapacity);
+ m_cElements = 0;
+
+ m_guard.leaveWrite();
+ }
+
+ /**
+ * Return the raw array.
+ *
+ * For native types this is a pointer to continuous memory of the items. For
+ * pointer types this is a continuous memory of pointers to the items.
+ *
+ * @warning If you change anything in the underlaying list, this memory
+ * will very likely become invalid. So take care when using this
+ * method and better try to avoid using it.
+ *
+ * @returns the raw memory.
+ */
+ ITYPE *raw() const
+ {
+ m_guard.enterRead();
+ ITYPE *pRet = m_pArray;
+ m_guard.leaveRead();
+ return pRet;
+ }
+
+ RTCListBase<T, ITYPE, MT> &operator<<(const T &val)
+ {
+ return append(val);
+ }
+
+ /* Define our own new and delete. */
+#ifdef RT_NEED_NEW_AND_DELETE
+ RTMEM_IMPLEMENT_NEW_AND_DELETE();
+#else
+ RTMEMEF_NEW_AND_DELETE_OPERATORS();
+#endif
+
+ /**
+ * The default capacity of the list. This is also used as grow factor.
+ */
+ static const size_t kDefaultCapacity;
+
+protected:
+
+ /**
+ * Generic resizes the array, surplus elements are erased.
+ *
+ * @param cElementsNew The new array size.
+ * @throws std::bad_alloc.
+ */
+ void resizeArray(size_t cElementsNew)
+ {
+ /* Same size? */
+ if (cElementsNew == m_cCapacity)
+ return;
+
+ /* If we get smaller we have to delete some of the objects at the end
+ of the list. */
+ if ( cElementsNew < m_cElements
+ && m_pArray)
+ RTCListHelper<T, ITYPE>::eraseRange(m_pArray, cElementsNew, m_cElements - cElementsNew);
+
+ resizeArrayNoErase(cElementsNew);
+ }
+
+ /**
+ * Resizes the array without doing the erase() thing on surplus elements.
+ *
+ * @param cElementsNew The new array size.
+ * @throws std::bad_alloc.
+ */
+ void resizeArrayNoErase(size_t cElementsNew)
+ {
+ /* Same size? */
+ if (cElementsNew == m_cCapacity)
+ return;
+
+ /* Resize the array. */
+ if (cElementsNew > 0)
+ {
+ void *pvNew = RTMemRealloc(m_pArray, sizeof(ITYPE) * cElementsNew);
+ if (!pvNew)
+ {
+#ifdef RT_EXCEPTIONS_ENABLED
+ throw std::bad_alloc();
+#endif
+ return;
+ }
+ m_pArray = static_cast<ITYPE*>(pvNew);
+ }
+ /* If we get zero we delete the array it self. */
+ else if (m_pArray)
+ {
+ RTMemFree(m_pArray);
+ m_pArray = NULL;
+ }
+
+ m_cCapacity = cElementsNew;
+ if (m_cElements > cElementsNew)
+ m_cElements = cElementsNew;
+ }
+
+ /**
+ * Special realloc method which require that the array will grow.
+ *
+ * @param cElementsNew The new array size.
+ * @throws std::bad_alloc.
+ * @note No boundary checks are done!
+ */
+ void growArray(size_t cElementsNew)
+ {
+ Assert(cElementsNew > m_cCapacity);
+ void *pvNew = RTMemRealloc(m_pArray, sizeof(ITYPE) * cElementsNew);
+ if (pvNew)
+ {
+ m_cCapacity = cElementsNew;
+ m_pArray = static_cast<ITYPE*>(pvNew);
+ }
+ else
+ {
+#ifdef RT_EXCEPTIONS_ENABLED
+ throw std::bad_alloc();
+#endif
+ }
+ }
+
+ /**
+ * Remove the item at position @a i.
+ *
+ * @param i The position of the item to remove. Out of bounds values will
+ * be ignored and an assertion will be raised in strict builds.
+ * @remarks
+ */
+ void removeAtLocked(size_t i)
+ {
+ AssertMsgReturnVoid(i < m_cElements, ("i=%zu m_cElements=%zu\n", i, m_cElements));
+
+ RTCListHelper<T, ITYPE>::erase(m_pArray, i);
+ if (i < m_cElements - 1)
+ memmove(&m_pArray[i], &m_pArray[i + 1], (m_cElements - i - 1) * sizeof(ITYPE));
+ --m_cElements;
+ }
+
+
+ /** The internal list array. */
+ ITYPE *m_pArray;
+ /** The current count of items in use. */
+ size_t m_cElements;
+ /** The current capacity of the internal array. */
+ size_t m_cCapacity;
+ /** The guard used to serialize the access to the items. */
+ RTCListGuard<MT> m_guard;
+};
+
+template <class T, typename ITYPE, bool MT>
+const size_t RTCListBase<T, ITYPE, MT>::kDefaultCapacity = 10;
+
+/**
+ * Template class which automatically determines the type of list to use.
+ *
+ * @see RTCListBase
+ */
+template <class T, typename ITYPE = typename RTCIf<(sizeof(T) > sizeof(void*)), T*, T>::result>
+class RTCList : public RTCListBase<T, ITYPE, false>
+{
+ /* Traits */
+ typedef RTCListBase<T, ITYPE, false> BASE;
+
+public:
+ /**
+ * Creates a new list.
+ *
+ * This preallocates @a cCapacity elements within the list.
+ *
+ * @param cCapacity The initial capacity the list has.
+ * @throws std::bad_alloc
+ */
+ RTCList(size_t cCapacity = BASE::kDefaultCapacity)
+ : BASE(cCapacity) {}
+
+ RTCList(const BASE &other)
+ : BASE(other) {}
+
+ /* Define our own new and delete. */
+#ifdef RT_NEED_NEW_AND_DELETE
+ RTMEM_IMPLEMENT_NEW_AND_DELETE();
+#else
+ RTMEMEF_NEW_AND_DELETE_OPERATORS();
+#endif
+};
+
+/**
+ * Specialized class for using the native type list for unsigned 64-bit
+ * values even on a 32-bit host.
+ *
+ * @see RTCListBase
+ */
+template <>
+class RTCList<uint64_t>: public RTCListBase<uint64_t, uint64_t, false>
+{
+ /* Traits */
+ typedef RTCListBase<uint64_t, uint64_t, false> BASE;
+
+public:
+ /**
+ * Creates a new list.
+ *
+ * This preallocates @a cCapacity elements within the list.
+ *
+ * @param cCapacity The initial capacity the list has.
+ * @throws std::bad_alloc
+ */
+ RTCList(size_t cCapacity = BASE::kDefaultCapacity)
+ : BASE(cCapacity) {}
+
+ /* Define our own new and delete. */
+#ifdef RT_NEED_NEW_AND_DELETE
+ RTMEM_IMPLEMENT_NEW_AND_DELETE();
+#else
+ RTMEMEF_NEW_AND_DELETE_OPERATORS();
+#endif
+};
+
+/**
+ * Specialized class for using the native type list for signed 64-bit
+ * values even on a 32-bit host.
+ *
+ * @see RTCListBase
+ */
+template <>
+class RTCList<int64_t>: public RTCListBase<int64_t, int64_t, false>
+{
+ /* Traits */
+ typedef RTCListBase<int64_t, int64_t, false> BASE;
+
+public:
+ /**
+ * Creates a new list.
+ *
+ * This preallocates @a cCapacity elements within the list.
+ *
+ * @param cCapacity The initial capacity the list has.
+ * @throws std::bad_alloc
+ */
+ RTCList(size_t cCapacity = BASE::kDefaultCapacity)
+ : BASE(cCapacity) {}
+
+ /* Define our own new and delete. */
+#ifdef RT_NEED_NEW_AND_DELETE
+ RTMEM_IMPLEMENT_NEW_AND_DELETE();
+#else
+ RTMEMEF_NEW_AND_DELETE_OPERATORS();
+#endif
+};
+
+/** @} */
+
+#endif /* !IPRT_INCLUDED_cpp_list_h */
+
diff --git a/include/iprt/cpp/lock.h b/include/iprt/cpp/lock.h
new file mode 100644
index 00000000..3a0c4bcd
--- /dev/null
+++ b/include/iprt/cpp/lock.h
@@ -0,0 +1,179 @@
+/** @file
+ * IPRT - Classes for Scope-based Locking.
+ */
+
+/*
+ * Copyright (C) 2007-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_cpp_lock_h
+#define IPRT_INCLUDED_cpp_lock_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/critsect.h>
+#ifdef RT_LOCK_STRICT
+# include <iprt/lockvalidator.h>
+#endif
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_cpp_lock C++ Scope-based Locking
+ * @ingroup grp_rt_cpp
+ * @{
+ */
+
+class RTCLock;
+
+/**
+ * The mutex lock.
+ *
+ * This is used as an object data member if the intention is to lock
+ * a single object. This can also be used statically, initialized in
+ * a global variable, for class wide purposes.
+ *
+ * This is best used together with RTCLock.
+ */
+class RTCLockMtx
+{
+friend class RTCLock;
+
+private:
+ RTCRITSECT mMtx;
+
+public:
+ RTCLockMtx()
+ {
+#ifdef RT_LOCK_STRICT_ORDER
+ RTCritSectInitEx(&mMtx, 0 /*fFlags*/,
+ RTLockValidatorClassCreateUnique(RT_SRC_POS, NULL),
+ RTLOCKVAL_SUB_CLASS_NONE, NULL);
+#else
+ RTCritSectInit(&mMtx);
+#endif
+ }
+
+ /** Use to when creating locks that belongs in the same "class". */
+ RTCLockMtx(RT_SRC_POS_DECL, uint32_t uSubClass = RTLOCKVAL_SUB_CLASS_NONE)
+ {
+#ifdef RT_LOCK_STRICT_ORDER
+ RTCritSectInitEx(&mMtx, 0 /*fFlags*/,
+ RTLockValidatorClassForSrcPos(RT_SRC_POS_ARGS, NULL),
+ uSubClass, NULL);
+#else
+ NOREF(uSubClass);
+ RTCritSectInit(&mMtx);
+ RT_SRC_POS_NOREF();
+#endif
+ }
+
+ ~RTCLockMtx()
+ {
+ RTCritSectDelete(&mMtx);
+ }
+
+ /* lock() and unlock() are private so that only friend RTCLock can access
+ them. */
+private:
+ inline void lock()
+ {
+ RTCritSectEnter(&mMtx);
+ }
+
+ inline void unlock()
+ {
+ RTCritSectLeave(&mMtx);
+ }
+};
+
+
+/**
+ * The stack object for automatic locking and unlocking.
+ *
+ * This is a helper class for automatic locks, to simplify requesting a
+ * RTCLockMtx and to not forget releasing it. To request a RTCLockMtx, simply
+ * create an instance of RTCLock on the stack and pass the mutex to it:
+ *
+ * @code
+ extern RTCLockMtx gMtx; // wherever this is
+ ...
+ if (...)
+ {
+ RTCLock lock(gMtx);
+ ... // do stuff
+ // when lock goes out of scope, destructor releases the mutex
+ }
+ @endcode
+ *
+ * You can also explicitly release the mutex by calling RTCLock::release().
+ * This might be helpful if the lock doesn't go out of scope early enough
+ * for your mutex to be released.
+ */
+class RTCLock
+{
+private:
+ /** Reference to the lock we're holding. */
+ RTCLockMtx &m_rMtx;
+ /** Whether we're currently holding the lock of if it was already
+ * explictily released by the release() method. */
+ bool m_fLocked;
+
+public:
+ RTCLock(RTCLockMtx &a_rMtx)
+ : m_rMtx(a_rMtx)
+ {
+ m_rMtx.lock();
+ m_fLocked = true;
+ }
+
+ ~RTCLock()
+ {
+ if (m_fLocked)
+ m_rMtx.unlock();
+ }
+
+ inline void release()
+ {
+ if (m_fLocked)
+ {
+ m_rMtx.unlock();
+ m_fLocked = false;
+ }
+ }
+};
+
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_cpp_lock_h */
+
diff --git a/include/iprt/cpp/meta.h b/include/iprt/cpp/meta.h
new file mode 100644
index 00000000..e6b9796e
--- /dev/null
+++ b/include/iprt/cpp/meta.h
@@ -0,0 +1,125 @@
+/** @file
+ * IPRT - C++ Meta programming.
+ */
+
+/*
+ * Copyright (C) 2011-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_cpp_meta_h
+#define IPRT_INCLUDED_cpp_meta_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+
+/** @defgroup grp_rt_cpp_meta C++ Meta programming utilities
+ * @ingroup grp_rt_cpp
+ * @{
+ */
+
+/**
+ * Check for a condition on compile time and dependent of the result TrueResult
+ * or FalseResult will be defined.
+ *
+ * @param Condition Condition to check.
+ * @param TrueResult Result when condition is true.
+ * @param FalseResult Result when condition is false
+ */
+template <bool Condition, typename TrueResult, typename FalseResult>
+struct RTCIf;
+
+/**
+ * Check for a condition on compile time and dependent of the result TrueResult
+ * or FalseResult will be defined.
+ *
+ * True specialization of RTCIf.
+ *
+ * @param TrueResult Result when condition is true.
+ * @param FalseResult Result when condition is false
+ */
+template <typename TrueResult, typename FalseResult>
+struct RTCIf<true, TrueResult, FalseResult>
+{
+ typedef TrueResult result;
+};
+
+/**
+ * Check for a condition on compile time and dependent of the result TrueResult
+ * or FalseResult will be defined.
+ *
+ * False specialization of RTCIf.
+ *
+ * @param TrueResult Result when condition is true.
+ * @param FalseResult Result when condition is false
+ */
+template <typename TrueResult, typename FalseResult>
+struct RTCIf<false, TrueResult, FalseResult>
+{
+ typedef FalseResult result;
+};
+
+/**
+ * Check if @a T is a pointer or not at compile time and dependent of the
+ * result TrueResult or FalseResult will be defined.
+ *
+ * False version of RTCIfPtr.
+ *
+ * @param Condition Condition to check.
+ * @param TrueResult Result when condition is true.
+ * @param FalseResult Result when condition is false
+ */
+template <class T, typename TrueResult, typename FalseResult>
+struct RTCIfPtr
+{
+ typedef FalseResult result;
+};
+
+/**
+ * Check if @a T is a pointer or not at compile time and dependent of the
+ * result TrueResult or FalseResult will be defined.
+ *
+ * True specialization of RTCIfPtr.
+ *
+ * @param Condition Condition to check.
+ * @param TrueResult Result when condition is true.
+ * @param FalseResult Result when condition is false
+ */
+template <class T, typename TrueResult, typename FalseResult>
+struct RTCIfPtr<T*, TrueResult, FalseResult>
+{
+ typedef TrueResult result;
+};
+
+/** @} */
+
+#endif /* !IPRT_INCLUDED_cpp_meta_h */
+
diff --git a/include/iprt/cpp/ministring.h b/include/iprt/cpp/ministring.h
new file mode 100644
index 00000000..80ad7cb5
--- /dev/null
+++ b/include/iprt/cpp/ministring.h
@@ -0,0 +1,1638 @@
+/** @file
+ * IPRT - C++ string class.
+ */
+
+/*
+ * Copyright (C) 2007-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_cpp_ministring_h
+#define IPRT_INCLUDED_cpp_ministring_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/mem.h>
+#include <iprt/string.h>
+#include <iprt/stdarg.h>
+#include <iprt/cpp/list.h>
+
+#include <new>
+
+
+/** @defgroup grp_rt_cpp_string C++ String support
+ * @ingroup grp_rt_cpp
+ * @{
+ */
+
+/** @brief C++ string class.
+ *
+ * This is a C++ string class that does not depend on anything else except IPRT
+ * memory management functions. Semantics are like in std::string, except it
+ * can do a lot less.
+ *
+ * Note that RTCString does not differentiate between NULL strings
+ * and empty strings. In other words, RTCString("") and RTCString(NULL)
+ * behave the same. In both cases, RTCString allocates no memory, reports
+ * a zero length and zero allocated bytes for both, and returns an empty
+ * C-style string from c_str().
+ *
+ * @note RTCString ASSUMES that all strings it deals with are valid UTF-8.
+ * The caller is responsible for not breaking this assumption.
+ */
+#ifdef VBOX
+ /** @remarks Much of the code in here used to be in com::Utf8Str so that
+ * com::Utf8Str can now derive from RTCString and only contain code
+ * that is COM-specific, such as com::Bstr conversions. Compared to
+ * the old Utf8Str though, RTCString always knows the length of its
+ * member string and the size of the buffer so it can use memcpy()
+ * instead of strdup().
+ */
+#endif
+class RT_DECL_CLASS RTCString
+{
+public:
+#if defined(RT_NEED_NEW_AND_DELETE) && ( !defined(RTMEM_WRAP_SOME_NEW_AND_DELETE_TO_EF) \
+ || defined(RTMEM_NO_WRAP_SOME_NEW_AND_DELETE_TO_EF))
+ RTMEM_IMPLEMENT_NEW_AND_DELETE();
+#else
+ RTMEMEF_NEW_AND_DELETE_OPERATORS();
+#endif
+
+ /**
+ * Creates an empty string that has no memory allocated.
+ */
+ RTCString()
+ : m_psz(NULL),
+ m_cch(0),
+ m_cbAllocated(0)
+ {
+ }
+
+ /**
+ * Creates a copy of another RTCString.
+ *
+ * This allocates s.length() + 1 bytes for the new instance, unless s is empty.
+ *
+ * @param a_rSrc The source string.
+ *
+ * @throws std::bad_alloc
+ */
+ RTCString(const RTCString &a_rSrc)
+ {
+ copyFromN(a_rSrc.m_psz, a_rSrc.m_cch);
+ }
+
+ /**
+ * Creates a copy of a C-style string.
+ *
+ * This allocates strlen(pcsz) + 1 bytes for the new instance, unless s is empty.
+ *
+ * @param pcsz The source string.
+ *
+ * @throws std::bad_alloc
+ */
+ RTCString(const char *pcsz)
+ {
+ copyFromN(pcsz, pcsz ? strlen(pcsz) : 0);
+ }
+
+ /**
+ * Create a partial copy of another RTCString.
+ *
+ * @param a_rSrc The source string.
+ * @param a_offSrc The byte offset into the source string.
+ * @param a_cchSrc The max number of chars (encoded UTF-8 bytes)
+ * to copy from the source string.
+ */
+ RTCString(const RTCString &a_rSrc, size_t a_offSrc, size_t a_cchSrc = npos)
+ {
+ if (a_offSrc < a_rSrc.m_cch)
+ copyFromN(&a_rSrc.m_psz[a_offSrc], RT_MIN(a_cchSrc, a_rSrc.m_cch - a_offSrc));
+ else
+ {
+ m_psz = NULL;
+ m_cch = 0;
+ m_cbAllocated = 0;
+ }
+ }
+
+ /**
+ * Create a partial copy of a C-style string.
+ *
+ * @param a_pszSrc The source string (UTF-8).
+ * @param a_cchSrc The max number of chars (encoded UTF-8 bytes)
+ * to copy from the source string. This must not
+ * be '0' as the compiler could easily mistake
+ * that for the va_list constructor.
+ */
+ RTCString(const char *a_pszSrc, size_t a_cchSrc)
+ {
+ size_t cchMax = a_pszSrc ? RTStrNLen(a_pszSrc, a_cchSrc) : 0;
+ copyFromN(a_pszSrc, RT_MIN(a_cchSrc, cchMax));
+ }
+
+ /**
+ * Create a string containing @a a_cTimes repetitions of the character @a
+ * a_ch.
+ *
+ * @param a_cTimes The number of times the character is repeated.
+ * @param a_ch The character to fill the string with.
+ */
+ RTCString(size_t a_cTimes, char a_ch)
+ : m_psz(NULL),
+ m_cch(0),
+ m_cbAllocated(0)
+ {
+ Assert((unsigned)a_ch < 0x80);
+ if (a_cTimes)
+ {
+ reserve(a_cTimes + 1);
+ memset(m_psz, a_ch, a_cTimes);
+ m_psz[a_cTimes] = '\0';
+ m_cch = a_cTimes;
+ }
+ }
+
+ /**
+ * Create a new string given the format string and its arguments.
+ *
+ * @param a_pszFormat Pointer to the format string (UTF-8),
+ * @see pg_rt_str_format.
+ * @param a_va Argument vector containing the arguments
+ * specified by the format string.
+ * @sa printfV
+ * @remarks Not part of std::string.
+ */
+ RTCString(const char *a_pszFormat, va_list a_va) RT_IPRT_FORMAT_ATTR(1, 0)
+ : m_psz(NULL),
+ m_cch(0),
+ m_cbAllocated(0)
+ {
+ printfV(a_pszFormat, a_va);
+ }
+
+ /**
+ * Destructor.
+ */
+ virtual ~RTCString()
+ {
+ cleanup();
+ }
+
+ /**
+ * String length in bytes.
+ *
+ * Returns the length of the member string in bytes, which is equal to strlen(c_str()).
+ * In other words, this does not count unicode codepoints; use utf8length() for that.
+ * The byte length is always cached so calling this is cheap and requires no
+ * strlen() invocation.
+ *
+ * @returns m_cbLength.
+ */
+ size_t length() const
+ {
+ return m_cch;
+ }
+
+ /**
+ * String length in unicode codepoints.
+ *
+ * As opposed to length(), which returns the length in bytes, this counts
+ * the number of unicode codepoints. This is *not* cached so calling this
+ * is expensive.
+ *
+ * @returns Number of codepoints in the member string.
+ */
+ size_t uniLength() const
+ {
+ return m_psz ? RTStrUniLen(m_psz) : 0;
+ }
+
+ /**
+ * The allocated buffer size (in bytes).
+ *
+ * Returns the number of bytes allocated in the internal string buffer, which is
+ * at least length() + 1 if length() > 0; for an empty string, this returns 0.
+ *
+ * @returns m_cbAllocated.
+ */
+ size_t capacity() const
+ {
+ return m_cbAllocated;
+ }
+
+ /**
+ * Make sure at that least cb of buffer space is reserved.
+ *
+ * Requests that the contained memory buffer have at least cb bytes allocated.
+ * This may expand or shrink the string's storage, but will never truncate the
+ * contained string. In other words, cb will be ignored if it's smaller than
+ * length() + 1.
+ *
+ * @param cb New minimum size (in bytes) of member memory buffer.
+ *
+ * @throws std::bad_alloc On allocation error. The object is left unchanged.
+ */
+ void reserve(size_t cb)
+ {
+ if ( ( cb != m_cbAllocated
+ && cb > m_cch + 1)
+ || ( m_psz == NULL
+ && cb > 0))
+ {
+ int rc = RTStrRealloc(&m_psz, cb);
+ if (RT_SUCCESS(rc))
+ m_cbAllocated = cb;
+#ifdef RT_EXCEPTIONS_ENABLED
+ else
+ throw std::bad_alloc();
+#endif
+ }
+ }
+
+ /**
+ * A C like version of the reserve method, i.e. return code instead of throw.
+ *
+ * @returns VINF_SUCCESS or VERR_NO_STRING_MEMORY.
+ * @param cb New minimum size (in bytes) of member memory buffer.
+ */
+ int reserveNoThrow(size_t cb) RT_NOEXCEPT
+ {
+ if ( ( cb != m_cbAllocated
+ && cb > m_cch + 1)
+ || ( m_psz == NULL
+ && cb > 0))
+ {
+ int rc = RTStrRealloc(&m_psz, cb);
+ if (RT_SUCCESS(rc))
+ m_cbAllocated = cb;
+ else
+ return rc;
+ }
+ return VINF_SUCCESS;
+ }
+
+ /**
+ * Deallocates all memory.
+ */
+ inline void setNull()
+ {
+ cleanup();
+ }
+
+ /**
+ * Assigns a copy of pcsz to @a this.
+ *
+ * @param pcsz The source string.
+ *
+ * @throws std::bad_alloc On allocation failure. The object is left describing
+ * a NULL string.
+ *
+ * @returns Reference to the object.
+ */
+ RTCString &operator=(const char *pcsz)
+ {
+ if (m_psz != pcsz)
+ {
+ cleanup();
+ copyFromN(pcsz, pcsz ? strlen(pcsz) : 0);
+ }
+ return *this;
+ }
+
+ /**
+ * Assigns a copy of s to @a this.
+ *
+ * @param s The source string.
+ *
+ * @throws std::bad_alloc On allocation failure. The object is left describing
+ * a NULL string.
+ *
+ * @returns Reference to the object.
+ */
+ RTCString &operator=(const RTCString &s)
+ {
+ if (this != &s)
+ {
+ cleanup();
+ copyFromN(s.m_psz, s.m_cch);
+ }
+ return *this;
+ }
+
+ /**
+ * Assigns a copy of another RTCString.
+ *
+ * @param a_rSrc Reference to the source string.
+ * @throws std::bad_alloc On allocation error. The object is left unchanged.
+ */
+ RTCString &assign(const RTCString &a_rSrc);
+
+ /**
+ * Assigns a copy of another RTCString.
+ *
+ * @param a_rSrc Reference to the source string.
+ * @returns VINF_SUCCESS or VERR_NO_STRING_MEMORY.
+ */
+ int assignNoThrow(const RTCString &a_rSrc) RT_NOEXCEPT;
+
+ /**
+ * Assigns a copy of a C-style string.
+ *
+ * @param a_pszSrc Pointer to the C-style source string.
+ * @throws std::bad_alloc On allocation error. The object is left unchanged.
+ * @remarks ASSUMES valid
+ */
+ RTCString &assign(const char *a_pszSrc);
+
+ /**
+ * Assigns a copy of a C-style string.
+ *
+ * @param a_pszSrc Pointer to the C-style source string.
+ * @returns VINF_SUCCESS or VERR_NO_STRING_MEMORY.
+ * @remarks ASSUMES valid
+ */
+ int assignNoThrow(const char *a_pszSrc) RT_NOEXCEPT;
+
+ /**
+ * Assigns a partial copy of another RTCString.
+ *
+ * @param a_rSrc The source string.
+ * @param a_offSrc The byte offset into the source string.
+ * @param a_cchSrc The max number of chars (encoded UTF-8 bytes)
+ * to copy from the source string.
+ * @throws std::bad_alloc On allocation error. The object is left unchanged.
+ */
+ RTCString &assign(const RTCString &a_rSrc, size_t a_offSrc, size_t a_cchSrc = npos);
+
+ /**
+ * Assigns a partial copy of another RTCString.
+ *
+ * @param a_rSrc The source string.
+ * @param a_offSrc The byte offset into the source string.
+ * @param a_cchSrc The max number of chars (encoded UTF-8 bytes)
+ * to copy from the source string.
+ * @returns VINF_SUCCESS or VERR_NO_STRING_MEMORY.
+ */
+ int assignNoThrow(const RTCString &a_rSrc, size_t a_offSrc, size_t a_cchSrc = npos) RT_NOEXCEPT;
+
+ /**
+ * Assigns a partial copy of a C-style string.
+ *
+ * @param a_pszSrc The source string (UTF-8).
+ * @param a_cchSrc The max number of chars (encoded UTF-8 bytes)
+ * to copy from the source string.
+ * @throws std::bad_alloc On allocation error. The object is left unchanged.
+ */
+ RTCString &assign(const char *a_pszSrc, size_t a_cchSrc);
+
+ /**
+ * Assigns a partial copy of a C-style string.
+ *
+ * @param a_pszSrc The source string (UTF-8).
+ * @param a_cchSrc The max number of chars (encoded UTF-8 bytes)
+ * to copy from the source string.
+ * @returns VINF_SUCCESS or VERR_NO_STRING_MEMORY.
+ */
+ int assignNoThrow(const char *a_pszSrc, size_t a_cchSrc) RT_NOEXCEPT;
+
+ /**
+ * Assigs a string containing @a a_cTimes repetitions of the character @a a_ch.
+ *
+ * @param a_cTimes The number of times the character is repeated.
+ * @param a_ch The character to fill the string with.
+ * @throws std::bad_alloc On allocation error. The object is left unchanged.
+ */
+ RTCString &assign(size_t a_cTimes, char a_ch);
+
+ /**
+ * Assigs a string containing @a a_cTimes repetitions of the character @a a_ch.
+ *
+ * @param a_cTimes The number of times the character is repeated.
+ * @param a_ch The character to fill the string with.
+ * @returns VINF_SUCCESS or VERR_NO_STRING_MEMORY.
+ */
+ int assignNoThrow(size_t a_cTimes, char a_ch) RT_NOEXCEPT;
+
+ /**
+ * Assigns the output of the string format operation (RTStrPrintf).
+ *
+ * @param pszFormat Pointer to the format string,
+ * @see pg_rt_str_format.
+ * @param ... Ellipsis containing the arguments specified by
+ * the format string.
+ *
+ * @throws std::bad_alloc On allocation error. Object state is undefined.
+ *
+ * @returns Reference to the object.
+ */
+ RTCString &printf(const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(1, 2);
+
+ /**
+ * Assigns the output of the string format operation (RTStrPrintf).
+ *
+ * @param pszFormat Pointer to the format string,
+ * @see pg_rt_str_format.
+ * @param ... Ellipsis containing the arguments specified by
+ * the format string.
+ *
+ * @returns VINF_SUCCESS or VERR_NO_STRING_MEMORY.
+ */
+ int printfNoThrow(const char *pszFormat, ...) RT_NOEXCEPT RT_IPRT_FORMAT_ATTR(1, 2);
+
+ /**
+ * Assigns the output of the string format operation (RTStrPrintfV).
+ *
+ * @param pszFormat Pointer to the format string,
+ * @see pg_rt_str_format.
+ * @param va Argument vector containing the arguments
+ * specified by the format string.
+ *
+ * @throws std::bad_alloc On allocation error. Object state is undefined.
+ *
+ * @returns Reference to the object.
+ */
+ RTCString &printfV(const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(1, 0);
+
+ /**
+ * Assigns the output of the string format operation (RTStrPrintfV).
+ *
+ * @param pszFormat Pointer to the format string,
+ * @see pg_rt_str_format.
+ * @param va Argument vector containing the arguments
+ * specified by the format string.
+ *
+ * @returns VINF_SUCCESS or VERR_NO_STRING_MEMORY.
+ */
+ int printfVNoThrow(const char *pszFormat, va_list va) RT_NOEXCEPT RT_IPRT_FORMAT_ATTR(1, 0);
+
+ /**
+ * Appends the string @a that to @a rThat.
+ *
+ * @param rThat The string to append.
+ * @throws std::bad_alloc On allocation error. The object is left unchanged.
+ * @returns Reference to the object.
+ */
+ RTCString &append(const RTCString &rThat);
+
+ /**
+ * Appends the string @a that to @a rThat.
+ *
+ * @param rThat The string to append.
+ * @returns VINF_SUCCESS or VERR_NO_STRING_MEMORY.
+ */
+ int appendNoThrow(const RTCString &rThat) RT_NOEXCEPT;
+
+ /**
+ * Appends the string @a pszSrc to @a this.
+ *
+ * @param pszSrc The C-style string to append.
+ * @throws std::bad_alloc On allocation error. The object is left unchanged.
+ * @returns Reference to the object.
+ */
+ RTCString &append(const char *pszSrc);
+
+ /**
+ * Appends the string @a pszSrc to @a this.
+ *
+ * @param pszSrc The C-style string to append.
+ * @returns VINF_SUCCESS or VERR_NO_STRING_MEMORY.
+ */
+ int appendNoThrow(const char *pszSrc) RT_NOEXCEPT;
+
+ /**
+ * Appends the a substring from @a rThat to @a this.
+ *
+ * @param rThat The string to append a substring from.
+ * @param offStart The start of the substring to append (byte offset,
+ * not codepoint).
+ * @param cchMax The maximum number of bytes to append.
+ * @throws std::bad_alloc On allocation error. The object is left unchanged.
+ * @returns Reference to the object.
+ */
+ RTCString &append(const RTCString &rThat, size_t offStart, size_t cchMax = RTSTR_MAX);
+
+ /**
+ * Appends the a substring from @a rThat to @a this.
+ *
+ * @param rThat The string to append a substring from.
+ * @param offStart The start of the substring to append (byte offset,
+ * not codepoint).
+ * @param cchMax The maximum number of bytes to append.
+ * @returns VINF_SUCCESS or VERR_NO_STRING_MEMORY.
+ */
+ int appendNoThrow(const RTCString &rThat, size_t offStart, size_t cchMax = RTSTR_MAX) RT_NOEXCEPT;
+
+ /**
+ * Appends the first @a cchMax chars from string @a pszThat to @a this.
+ *
+ * @param pszThat The C-style string to append.
+ * @param cchMax The maximum number of bytes to append.
+ * @throws std::bad_alloc On allocation error. The object is left unchanged.
+ * @returns Reference to the object.
+ */
+ RTCString &append(const char *pszThat, size_t cchMax);
+
+ /**
+ * Appends the first @a cchMax chars from string @a pszThat to @a this.
+ *
+ * @param pszThat The C-style string to append.
+ * @param cchMax The maximum number of bytes to append.
+ * @returns VINF_SUCCESS or VERR_NO_STRING_MEMORY.
+ */
+ int appendNoThrow(const char *pszThat, size_t cchMax) RT_NOEXCEPT;
+
+ /**
+ * Appends the given character to @a this.
+ *
+ * @param ch The character to append.
+ * @throws std::bad_alloc On allocation error. The object is left unchanged.
+ * @returns Reference to the object.
+ */
+ RTCString &append(char ch);
+
+ /**
+ * Appends the given character to @a this.
+ *
+ * @param ch The character to append.
+ * @returns VINF_SUCCESS or VERR_NO_STRING_MEMORY.
+ */
+ int appendNoThrow(char ch) RT_NOEXCEPT;
+
+ /**
+ * Appends the given unicode code point to @a this.
+ *
+ * @param uc The unicode code point to append.
+ * @throws std::bad_alloc On allocation error. The object is left unchanged.
+ * @returns Reference to the object.
+ */
+ RTCString &appendCodePoint(RTUNICP uc);
+
+ /**
+ * Appends the given unicode code point to @a this.
+ *
+ * @param uc The unicode code point to append.
+ * @returns VINF_SUCCESS, VERR_INVALID_UTF8_ENCODING or VERR_NO_STRING_MEMORY.
+ */
+ int appendCodePointNoThrow(RTUNICP uc) RT_NOEXCEPT;
+
+ /**
+ * Appends the output of the string format operation (RTStrPrintf).
+ *
+ * @param pszFormat Pointer to the format string,
+ * @see pg_rt_str_format.
+ * @param ... Ellipsis containing the arguments specified by
+ * the format string.
+ *
+ * @throws std::bad_alloc On allocation error. Object state is undefined.
+ *
+ * @returns Reference to the object.
+ */
+ RTCString &appendPrintf(const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(1, 2);
+
+ /**
+ * Appends the output of the string format operation (RTStrPrintf).
+ *
+ * @param pszFormat Pointer to the format string,
+ * @see pg_rt_str_format.
+ * @param ... Ellipsis containing the arguments specified by
+ * the format string.
+ *
+ * @returns VINF_SUCCESS or VERR_NO_STRING_MEMORY.
+ */
+ int appendPrintfNoThrow(const char *pszFormat, ...) RT_NOEXCEPT RT_IPRT_FORMAT_ATTR(1, 2);
+
+ /**
+ * Appends the output of the string format operation (RTStrPrintfV).
+ *
+ * @param pszFormat Pointer to the format string,
+ * @see pg_rt_str_format.
+ * @param va Argument vector containing the arguments
+ * specified by the format string.
+ *
+ * @throws std::bad_alloc On allocation error. Object state is undefined.
+ *
+ * @returns Reference to the object.
+ */
+ RTCString &appendPrintfV(const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(1, 0);
+
+ /**
+ * Appends the output of the string format operation (RTStrPrintfV).
+ *
+ * @param pszFormat Pointer to the format string,
+ * @see pg_rt_str_format.
+ * @param va Argument vector containing the arguments
+ * specified by the format string.
+ *
+ * @returns VINF_SUCCESS or VERR_NO_STRING_MEMORY.
+ */
+ int appendPrintfVNoThrow(const char *pszFormat, va_list va) RT_NOEXCEPT RT_IPRT_FORMAT_ATTR(1, 0);
+
+ /**
+ * Shortcut to append(), RTCString variant.
+ *
+ * @param rThat The string to append.
+ * @returns Reference to the object.
+ */
+ RTCString &operator+=(const RTCString &rThat)
+ {
+ return append(rThat);
+ }
+
+ /**
+ * Shortcut to append(), const char* variant.
+ *
+ * @param pszThat The C-style string to append.
+ * @returns Reference to the object.
+ */
+ RTCString &operator+=(const char *pszThat)
+ {
+ return append(pszThat);
+ }
+
+ /**
+ * Shortcut to append(), char variant.
+ *
+ * @param ch The character to append.
+ *
+ * @returns Reference to the object.
+ */
+ RTCString &operator+=(char ch)
+ {
+ return append(ch);
+ }
+
+ /**
+ * Converts the member string to upper case.
+ *
+ * @returns Reference to the object.
+ */
+ RTCString &toUpper() RT_NOEXCEPT
+ {
+ if (length())
+ {
+ /* Folding an UTF-8 string may result in a shorter encoding (see
+ testcase), so recalculate the length afterwards. */
+ ::RTStrToUpper(m_psz);
+ size_t cchNew = strlen(m_psz);
+ Assert(cchNew <= m_cch);
+ m_cch = cchNew;
+ }
+ return *this;
+ }
+
+ /**
+ * Converts the member string to lower case.
+ *
+ * @returns Reference to the object.
+ */
+ RTCString &toLower() RT_NOEXCEPT
+ {
+ if (length())
+ {
+ /* Folding an UTF-8 string may result in a shorter encoding (see
+ testcase), so recalculate the length afterwards. */
+ ::RTStrToLower(m_psz);
+ size_t cchNew = strlen(m_psz);
+ Assert(cchNew <= m_cch);
+ m_cch = cchNew;
+ }
+ return *this;
+ }
+
+ /**
+ * Erases a sequence from the string.
+ *
+ * @returns Reference to the object.
+ * @param offStart Where in @a this string to start erasing.
+ * @param cchLength How much following @a offStart to erase.
+ */
+ RTCString &erase(size_t offStart = 0, size_t cchLength = npos) RT_NOEXCEPT;
+
+ /**
+ * Replaces a span of @a this string with a replacement string.
+ *
+ * @returns Reference to the object.
+ * @param offStart Where in @a this string to start replacing.
+ * @param cchLength How much following @a offStart to replace. npos is
+ * accepted.
+ * @param rStrReplacement The replacement string.
+ *
+ * @throws std::bad_alloc On allocation error. The object is left unchanged.
+ *
+ * @note Non-standard behaviour if offStart is beyond the end of the string.
+ * No change will occure and strict builds hits a debug assertion.
+ */
+ RTCString &replace(size_t offStart, size_t cchLength, const RTCString &rStrReplacement);
+
+ /**
+ * Replaces a span of @a this string with a replacement string.
+ *
+ * @returns VINF_SUCCESS, VERR_OUT_OF_RANGE or VERR_NO_STRING_MEMORY.
+ * @param offStart Where in @a this string to start replacing.
+ * @param cchLength How much following @a offStart to replace. npos is
+ * accepted.
+ * @param rStrReplacement The replacement string.
+ */
+ int replaceNoThrow(size_t offStart, size_t cchLength, const RTCString &rStrReplacement) RT_NOEXCEPT;
+
+ /**
+ * Replaces a span of @a this string with a replacement substring.
+ *
+ * @returns Reference to the object.
+ * @param offStart Where in @a this string to start replacing.
+ * @param cchLength How much following @a offStart to replace. npos is
+ * accepted.
+ * @param rStrReplacement The string from which a substring is taken.
+ * @param offReplacement The offset into @a rStrReplacement where the
+ * replacement substring starts.
+ * @param cchReplacement The maximum length of the replacement substring.
+ *
+ * @throws std::bad_alloc On allocation error. The object is left unchanged.
+ *
+ * @note Non-standard behaviour if offStart or offReplacement is beyond the
+ * end of the repective strings. No change is made in the former case,
+ * while we consider it an empty string in the latter. In both
+ * situation a debug assertion is raised in strict builds.
+ */
+ RTCString &replace(size_t offStart, size_t cchLength, const RTCString &rStrReplacement,
+ size_t offReplacement, size_t cchReplacement);
+
+ /**
+ * Replaces a span of @a this string with a replacement substring.
+ *
+ * @returns VINF_SUCCESS, VERR_OUT_OF_RANGE or VERR_NO_STRING_MEMORY.
+ * @param offStart Where in @a this string to start replacing.
+ * @param cchLength How much following @a offStart to replace. npos is
+ * accepted.
+ * @param rStrReplacement The string from which a substring is taken.
+ * @param offReplacement The offset into @a rStrReplacement where the
+ * replacement substring starts.
+ * @param cchReplacement The maximum length of the replacement substring.
+ */
+ int replaceNoThrow(size_t offStart, size_t cchLength, const RTCString &rStrReplacement,
+ size_t offReplacement, size_t cchReplacement) RT_NOEXCEPT;
+
+ /**
+ * Replaces a span of @a this string with the replacement string.
+ *
+ * @returns Reference to the object.
+ * @param offStart Where in @a this string to start replacing.
+ * @param cchLength How much following @a offStart to replace. npos is
+ * accepted.
+ * @param pszReplacement The replacement string.
+ *
+ * @throws std::bad_alloc On allocation error. The object is left unchanged.
+ *
+ * @note Non-standard behaviour if offStart is beyond the end of the string.
+ * No change will occure and strict builds hits a debug assertion.
+ */
+ RTCString &replace(size_t offStart, size_t cchLength, const char *pszReplacement);
+
+ /**
+ * Replaces a span of @a this string with the replacement string.
+ *
+ * @returns VINF_SUCCESS, VERR_OUT_OF_RANGE or VERR_NO_STRING_MEMORY.
+ * @param offStart Where in @a this string to start replacing.
+ * @param cchLength How much following @a offStart to replace. npos is
+ * accepted.
+ * @param pszReplacement The replacement string.
+ */
+ int replaceNoThrow(size_t offStart, size_t cchLength, const char *pszReplacement) RT_NOEXCEPT;
+
+ /**
+ * Replaces a span of @a this string with the replacement string.
+ *
+ * @returns Reference to the object.
+ * @param offStart Where in @a this string to start replacing.
+ * @param cchLength How much following @a offStart to replace. npos is
+ * accepted.
+ * @param pszReplacement The replacement string.
+ * @param cchReplacement How much of @a pszReplacement to use at most. If a
+ * zero terminator is found before reaching this value,
+ * we'll stop there.
+ *
+ * @throws std::bad_alloc On allocation error. The object is left unchanged.
+ *
+ * @note Non-standard behaviour if offStart is beyond the end of the string.
+ * No change will occure and strict builds hits a debug assertion.
+ */
+ RTCString &replace(size_t offStart, size_t cchLength, const char *pszReplacement, size_t cchReplacement);
+
+ /**
+ * Replaces a span of @a this string with the replacement string.
+ *
+ * @returns VINF_SUCCESS, VERR_OUT_OF_RANGE or VERR_NO_STRING_MEMORY.
+ * @param offStart Where in @a this string to start replacing.
+ * @param cchLength How much following @a offStart to replace. npos is
+ * accepted.
+ * @param pszReplacement The replacement string.
+ * @param cchReplacement How much of @a pszReplacement to use at most. If a
+ * zero terminator is found before reaching this value,
+ * we'll stop there.
+ */
+ int replaceNoThrow(size_t offStart, size_t cchLength, const char *pszReplacement, size_t cchReplacement) RT_NOEXCEPT;
+
+ /**
+ * Truncates the string to a max length of @a cchMax.
+ *
+ * If the string is shorter than @a cchMax characters, no change is made.
+ *
+ * If the @a cchMax is not at the start of a UTF-8 sequence, it will be adjusted
+ * down to the start of the UTF-8 sequence. Thus, after a truncation, the
+ * length() may be smaller than @a cchMax.
+ *
+ */
+ RTCString &truncate(size_t cchMax) RT_NOEXCEPT;
+
+ /**
+ * Index operator.
+ *
+ * Returns the byte at the given index, or a null byte if the index is not
+ * smaller than length(). This does _not_ count codepoints but simply points
+ * into the member C-style string.
+ *
+ * @param i The index into the string buffer.
+ * @returns char at the index or null.
+ */
+ inline char operator[](size_t i) const RT_NOEXCEPT
+ {
+ if (i < length())
+ return m_psz[i];
+ return '\0';
+ }
+
+ /**
+ * Returns the contained string as a const C-style string pointer.
+ *
+ * This never returns NULL; if the string is empty, this returns a pointer to
+ * static null byte.
+ *
+ * @returns const pointer to C-style string.
+ */
+ inline const char *c_str() const RT_NOEXCEPT
+ {
+ return (m_psz) ? m_psz : "";
+ }
+
+ /**
+ * Returns a non-const raw pointer that allows to modify the string directly.
+ * As opposed to c_str() and raw(), this DOES return NULL for an empty string
+ * because we cannot return a non-const pointer to a static "" global.
+ *
+ * @warning
+ * -# Be sure not to modify data beyond the allocated memory! Call
+ * capacity() to find out how large that buffer is.
+ * -# After any operation that modifies the length of the string,
+ * you _must_ call RTCString::jolt(), or subsequent copy operations
+ * may go nowhere. Better not use mutableRaw() at all.
+ */
+ char *mutableRaw() RT_NOEXCEPT
+ {
+ return m_psz;
+ }
+
+ /**
+ * Clean up after using mutableRaw.
+ *
+ * Intended to be called after something has messed with the internal string
+ * buffer (e.g. after using mutableRaw() or Utf8Str::asOutParam()). Resets the
+ * internal lengths correctly. Otherwise subsequent copy operations may go
+ * nowhere.
+ */
+ void jolt() RT_NOEXCEPT
+ {
+ if (m_psz)
+ {
+ m_cch = strlen(m_psz);
+ m_cbAllocated = m_cch + 1; /* (Required for the Utf8Str::asOutParam case) */
+ }
+ else
+ {
+ m_cch = 0;
+ m_cbAllocated = 0;
+ }
+ }
+
+ /**
+ * Returns @c true if the member string has no length.
+ *
+ * This is @c true for instances created from both NULL and "" input
+ * strings.
+ *
+ * This states nothing about how much memory might be allocated.
+ *
+ * @returns @c true if empty, @c false if not.
+ */
+ bool isEmpty() const RT_NOEXCEPT
+ {
+ return length() == 0;
+ }
+
+ /**
+ * Returns @c false if the member string has no length.
+ *
+ * This is @c false for instances created from both NULL and "" input
+ * strings.
+ *
+ * This states nothing about how much memory might be allocated.
+ *
+ * @returns @c false if empty, @c true if not.
+ */
+ bool isNotEmpty() const RT_NOEXCEPT
+ {
+ return length() != 0;
+ }
+
+ /** Case sensitivity selector. */
+ enum CaseSensitivity
+ {
+ CaseSensitive,
+ CaseInsensitive
+ };
+
+ /**
+ * Compares the member string to a C-string.
+ *
+ * @param pcszThat The string to compare with.
+ * @param cs Whether comparison should be case-sensitive.
+ * @returns 0 if equal, negative if this is smaller than @a pcsz, positive
+ * if larger.
+ */
+ int compare(const char *pcszThat, CaseSensitivity cs = CaseSensitive) const RT_NOEXCEPT
+ {
+ /* This klugde is for m_cch=0 and m_psz=NULL. pcsz=NULL and psz=""
+ are treated the same way so that str.compare(str2.c_str()) works. */
+ if (length() == 0)
+ return pcszThat == NULL || *pcszThat == '\0' ? 0 : -1;
+
+ if (cs == CaseSensitive)
+ return ::RTStrCmp(m_psz, pcszThat);
+ return ::RTStrICmp(m_psz, pcszThat);
+ }
+
+ /**
+ * Compares the member string to another RTCString.
+ *
+ * @param rThat The string to compare with.
+ * @param cs Whether comparison should be case-sensitive.
+ * @returns 0 if equal, negative if this is smaller than @a pcsz, positive
+ * if larger.
+ */
+ int compare(const RTCString &rThat, CaseSensitivity cs = CaseSensitive) const RT_NOEXCEPT
+ {
+ if (cs == CaseSensitive)
+ return ::RTStrCmp(m_psz, rThat.m_psz);
+ return ::RTStrICmp(m_psz, rThat.m_psz);
+ }
+
+ /**
+ * Compares the two strings.
+ *
+ * @returns true if equal, false if not.
+ * @param rThat The string to compare with.
+ */
+ bool equals(const RTCString &rThat) const RT_NOEXCEPT
+ {
+ return rThat.length() == length()
+ && ( length() == 0
+ || memcmp(rThat.m_psz, m_psz, length()) == 0);
+ }
+
+ /**
+ * Compares the two strings.
+ *
+ * @returns true if equal, false if not.
+ * @param pszThat The string to compare with.
+ */
+ bool equals(const char *pszThat) const RT_NOEXCEPT
+ {
+ /* This klugde is for m_cch=0 and m_psz=NULL. pcsz=NULL and psz=""
+ are treated the same way so that str.equals(str2.c_str()) works. */
+ if (length() == 0)
+ return pszThat == NULL || *pszThat == '\0';
+ return RTStrCmp(pszThat, m_psz) == 0;
+ }
+
+ /**
+ * Compares the two strings ignoring differences in case.
+ *
+ * @returns true if equal, false if not.
+ * @param that The string to compare with.
+ */
+ bool equalsIgnoreCase(const RTCString &that) const RT_NOEXCEPT
+ {
+ /* Unfolded upper and lower case characters may require different
+ amount of encoding space, so the length optimization doesn't work. */
+ return RTStrICmp(that.m_psz, m_psz) == 0;
+ }
+
+ /**
+ * Compares the two strings ignoring differences in case.
+ *
+ * @returns true if equal, false if not.
+ * @param pszThat The string to compare with.
+ */
+ bool equalsIgnoreCase(const char *pszThat) const RT_NOEXCEPT
+ {
+ /* This klugde is for m_cch=0 and m_psz=NULL. pcsz=NULL and psz=""
+ are treated the same way so that str.equalsIgnoreCase(str2.c_str()) works. */
+ if (length() == 0)
+ return pszThat == NULL || *pszThat == '\0';
+ return RTStrICmp(pszThat, m_psz) == 0;
+ }
+
+ /** @name Comparison operators.
+ * @{ */
+ bool operator==(const RTCString &that) const { return equals(that); }
+ bool operator!=(const RTCString &that) const { return !equals(that); }
+ bool operator<( const RTCString &that) const { return compare(that) < 0; }
+ bool operator>( const RTCString &that) const { return compare(that) > 0; }
+
+ bool operator==(const char *pszThat) const { return equals(pszThat); }
+ bool operator!=(const char *pszThat) const { return !equals(pszThat); }
+ bool operator<( const char *pszThat) const { return compare(pszThat) < 0; }
+ bool operator>( const char *pszThat) const { return compare(pszThat) > 0; }
+ /** @} */
+
+ /** Max string offset value.
+ *
+ * When returned by a method, this indicates failure. When taken as input,
+ * typically a default, it means all the way to the string terminator.
+ */
+ static const size_t npos;
+
+ /**
+ * Find the given substring.
+ *
+ * Looks for @a pszNeedle in @a this starting at @a offStart and returns its
+ * position as a byte (not codepoint) offset, counting from the beginning of
+ * @a this as 0.
+ *
+ * @param pszNeedle The substring to find.
+ * @param offStart The (byte) offset into the string buffer to start
+ * searching.
+ *
+ * @returns 0 based position of pszNeedle. npos if not found.
+ */
+ size_t find(const char *pszNeedle, size_t offStart = 0) const RT_NOEXCEPT;
+ size_t find_first_of(const char *pszNeedle, size_t offStart = 0) const RT_NOEXCEPT
+ { return find(pszNeedle, offStart); }
+
+ /**
+ * Find the given substring.
+ *
+ * Looks for @a pStrNeedle in @a this starting at @a offStart and returns its
+ * position as a byte (not codepoint) offset, counting from the beginning of
+ * @a this as 0.
+ *
+ * @param pStrNeedle The substring to find.
+ * @param offStart The (byte) offset into the string buffer to start
+ * searching.
+ *
+ * @returns 0 based position of pStrNeedle. npos if not found or pStrNeedle is
+ * NULL or an empty string.
+ */
+ size_t find(const RTCString *pStrNeedle, size_t offStart = 0) const RT_NOEXCEPT;
+
+ /**
+ * Find the given substring.
+ *
+ * Looks for @a rStrNeedle in @a this starting at @a offStart and returns its
+ * position as a byte (not codepoint) offset, counting from the beginning of
+ * @a this as 0.
+ *
+ * @param rStrNeedle The substring to find.
+ * @param offStart The (byte) offset into the string buffer to start
+ * searching.
+ *
+ * @returns 0 based position of pStrNeedle. npos if not found or pStrNeedle is
+ * NULL or an empty string.
+ */
+ size_t find(const RTCString &rStrNeedle, size_t offStart = 0) const RT_NOEXCEPT;
+ size_t find_first_of(const RTCString &rStrNeedle, size_t offStart = 0) const RT_NOEXCEPT
+ { return find(rStrNeedle, offStart); }
+
+ /**
+ * Find the given character (byte).
+ *
+ * @returns 0 based position of chNeedle. npos if not found or pStrNeedle is
+ * NULL or an empty string.
+ * @param chNeedle The character (byte) to find.
+ * @param offStart The (byte) offset into the string buffer to start
+ * searching. Default is start of the string.
+ *
+ * @note This searches for a C character value, not a codepoint. Use the
+ * string version to locate codepoints above U+7F.
+ */
+ size_t find(char chNeedle, size_t offStart = 0) const RT_NOEXCEPT;
+ size_t find_first_of(char chNeedle, size_t offStart = 0) const RT_NOEXCEPT
+ { return find(chNeedle, offStart); }
+
+ /**
+ * Replaces all occurences of cFind with cReplace in the member string.
+ * In order not to produce invalid UTF-8, the characters must be ASCII
+ * values less than 128; this is not verified.
+ *
+ * @param chFind Character to replace. Must be ASCII < 128.
+ * @param chReplace Character to replace cFind with. Must be ASCII < 128.
+ */
+ void findReplace(char chFind, char chReplace) RT_NOEXCEPT;
+
+ /**
+ * Count the occurences of the specified character in the string.
+ *
+ * @param ch What to search for. Must be ASCII < 128.
+ * @remarks QString::count
+ */
+ size_t count(char ch) const RT_NOEXCEPT;
+
+ /**
+ * Count the occurences of the specified sub-string in the string.
+ *
+ * @param psz What to search for.
+ * @param cs Case sensitivity selector.
+ * @remarks QString::count
+ */
+ size_t count(const char *psz, CaseSensitivity cs = CaseSensitive) const RT_NOEXCEPT;
+
+ /**
+ * Count the occurences of the specified sub-string in the string.
+ *
+ * @param pStr What to search for.
+ * @param cs Case sensitivity selector.
+ * @remarks QString::count
+ */
+ size_t count(const RTCString *pStr, CaseSensitivity cs = CaseSensitive) const RT_NOEXCEPT;
+
+ /**
+ * Strips leading and trailing spaces.
+ *
+ * @returns this
+ */
+ RTCString &strip() RT_NOEXCEPT;
+
+ /**
+ * Strips leading spaces.
+ *
+ * @returns this
+ */
+ RTCString &stripLeft() RT_NOEXCEPT;
+
+ /**
+ * Strips trailing spaces.
+ *
+ * @returns this
+ */
+ RTCString &stripRight() RT_NOEXCEPT;
+
+ /**
+ * Returns a substring of @a this as a new Utf8Str.
+ *
+ * Works exactly like its equivalent in std::string. With the default
+ * parameters "0" and "npos", this always copies the entire string. The
+ * "pos" and "n" arguments represent bytes; it is the caller's responsibility
+ * to ensure that the offsets do not copy invalid UTF-8 sequences. When
+ * used in conjunction with find() and length(), this will work.
+ *
+ * @param pos Index of first byte offset to copy from @a this,
+ * counting from 0.
+ * @param n Number of bytes to copy, starting with the one at "pos".
+ * The copying will stop if the null terminator is encountered before
+ * n bytes have been copied.
+ */
+ RTCString substr(size_t pos = 0, size_t n = npos) const
+ {
+ return RTCString(*this, pos, n);
+ }
+
+ /**
+ * Returns a substring of @a this as a new Utf8Str. As opposed to substr(), this
+ * variant takes codepoint offsets instead of byte offsets.
+ *
+ * @param pos Index of first unicode codepoint to copy from
+ * @a this, counting from 0.
+ * @param n Number of unicode codepoints to copy, starting with
+ * the one at "pos". The copying will stop if the null
+ * terminator is encountered before n codepoints have
+ * been copied.
+ */
+ RTCString substrCP(size_t pos = 0, size_t n = npos) const;
+
+ /**
+ * Returns true if @a this ends with @a that.
+ *
+ * @param that Suffix to test for.
+ * @param cs Case sensitivity selector.
+ * @returns true if match, false if mismatch.
+ */
+ bool endsWith(const RTCString &that, CaseSensitivity cs = CaseSensitive) const RT_NOEXCEPT;
+
+ /**
+ * Returns true if @a this begins with @a that.
+ * @param that Prefix to test for.
+ * @param cs Case sensitivity selector.
+ * @returns true if match, false if mismatch.
+ */
+ bool startsWith(const RTCString &that, CaseSensitivity cs = CaseSensitive) const RT_NOEXCEPT;
+
+ /**
+ * Checks if the string starts with the given word, ignoring leading blanks.
+ *
+ * @param pszWord The word to test for.
+ * @param enmCase Case sensitivity selector.
+ * @returns true if match, false if mismatch.
+ */
+ bool startsWithWord(const char *pszWord, CaseSensitivity enmCase = CaseSensitive) const RT_NOEXCEPT;
+
+ /**
+ * Checks if the string starts with the given word, ignoring leading blanks.
+ *
+ * @param rThat Prefix to test for.
+ * @param enmCase Case sensitivity selector.
+ * @returns true if match, false if mismatch.
+ */
+ bool startsWithWord(const RTCString &rThat, CaseSensitivity enmCase = CaseSensitive) const RT_NOEXCEPT;
+
+ /**
+ * Returns true if @a this contains @a that (strstr).
+ *
+ * @param that Substring to look for.
+ * @param cs Case sensitivity selector.
+ * @returns true if found, false if not found.
+ */
+ bool contains(const RTCString &that, CaseSensitivity cs = CaseSensitive) const RT_NOEXCEPT;
+
+ /**
+ * Returns true if @a this contains @a pszNeedle (strstr).
+ *
+ * @param pszNeedle Substring to look for.
+ * @param cs Case sensitivity selector.
+ * @returns true if found, false if not found.
+ */
+ bool contains(const char *pszNeedle, CaseSensitivity cs = CaseSensitive) const RT_NOEXCEPT;
+
+ /**
+ * Attempts to convert the member string into a 32-bit integer.
+ *
+ * @returns 32-bit unsigned number on success.
+ * @returns 0 on failure.
+ */
+ int32_t toInt32() const RT_NOEXCEPT
+ {
+ return RTStrToInt32(c_str());
+ }
+
+ /**
+ * Attempts to convert the member string into an unsigned 32-bit integer.
+ *
+ * @returns 32-bit unsigned number on success.
+ * @returns 0 on failure.
+ */
+ uint32_t toUInt32() const RT_NOEXCEPT
+ {
+ return RTStrToUInt32(c_str());
+ }
+
+ /**
+ * Attempts to convert the member string into an 64-bit integer.
+ *
+ * @returns 64-bit unsigned number on success.
+ * @returns 0 on failure.
+ */
+ int64_t toInt64() const RT_NOEXCEPT
+ {
+ return RTStrToInt64(c_str());
+ }
+
+ /**
+ * Attempts to convert the member string into an unsigned 64-bit integer.
+ *
+ * @returns 64-bit unsigned number on success.
+ * @returns 0 on failure.
+ */
+ uint64_t toUInt64() const RT_NOEXCEPT
+ {
+ return RTStrToUInt64(c_str());
+ }
+
+ /**
+ * Attempts to convert the member string into an unsigned 64-bit integer.
+ *
+ * @param i Where to return the value on success.
+ * @returns IPRT error code, see RTStrToInt64.
+ */
+ int toInt(uint64_t &i) const RT_NOEXCEPT;
+
+ /**
+ * Attempts to convert the member string into an unsigned 32-bit integer.
+ *
+ * @param i Where to return the value on success.
+ * @returns IPRT error code, see RTStrToInt32.
+ */
+ int toInt(uint32_t &i) const RT_NOEXCEPT;
+
+ /** Splitting behavior regarding empty sections in the string. */
+ enum SplitMode
+ {
+ KeepEmptyParts, /**< Empty parts are added as empty strings to the result list. */
+ RemoveEmptyParts /**< Empty parts are skipped. */
+ };
+
+ /**
+ * Splits a string separated by strSep into its parts.
+ *
+ * @param a_rstrSep The separator to search for.
+ * @param a_enmMode How should empty parts be handled.
+ * @returns separated strings as string list.
+ * @throws std::bad_alloc On allocation error.
+ */
+ RTCList<RTCString, RTCString *> split(const RTCString &a_rstrSep,
+ SplitMode a_enmMode = RemoveEmptyParts) const;
+
+ /**
+ * Joins a list of strings together using the provided separator and
+ * an optional prefix for each item in the list.
+ *
+ * @param a_rList The list to join.
+ * @param a_rstrPrefix The prefix used for appending to each item.
+ * @param a_rstrSep The separator used for joining.
+ * @returns joined string.
+ * @throws std::bad_alloc On allocation error.
+ */
+ static RTCString joinEx(const RTCList<RTCString, RTCString *> &a_rList,
+ const RTCString &a_rstrPrefix /* = "" */,
+ const RTCString &a_rstrSep /* = "" */);
+
+ /**
+ * Joins a list of strings together using the provided separator.
+ *
+ * @param a_rList The list to join.
+ * @param a_rstrSep The separator used for joining.
+ * @returns joined string.
+ * @throws std::bad_alloc On allocation error.
+ */
+ static RTCString join(const RTCList<RTCString, RTCString *> &a_rList,
+ const RTCString &a_rstrSep = "");
+
+ /**
+ * Swaps two strings in a fast way.
+ *
+ * Exception safe.
+ *
+ * @param a_rThat The string to swap with.
+ */
+ inline void swap(RTCString &a_rThat) RT_NOEXCEPT
+ {
+ char *pszTmp = m_psz;
+ size_t cchTmp = m_cch;
+ size_t cbAllocatedTmp = m_cbAllocated;
+
+ m_psz = a_rThat.m_psz;
+ m_cch = a_rThat.m_cch;
+ m_cbAllocated = a_rThat.m_cbAllocated;
+
+ a_rThat.m_psz = pszTmp;
+ a_rThat.m_cch = cchTmp;
+ a_rThat.m_cbAllocated = cbAllocatedTmp;
+ }
+
+protected:
+
+ /**
+ * Hide operator bool() to force people to use isEmpty() explicitly.
+ */
+ operator bool() const;
+
+ /**
+ * Destructor implementation, also used to clean up in operator=() before
+ * assigning a new string.
+ */
+ void cleanup() RT_NOEXCEPT
+ {
+ if (m_psz)
+ {
+ RTStrFree(m_psz);
+ m_psz = NULL;
+ m_cch = 0;
+ m_cbAllocated = 0;
+ }
+ }
+
+ /**
+ * Protected internal helper to copy a string.
+ *
+ * This ignores the previous object state, so either call this from a
+ * constructor or call cleanup() first. copyFromN() unconditionally sets
+ * the members to a copy of the given other strings and makes no
+ * assumptions about previous contents. Can therefore be used both in copy
+ * constructors, when member variables have no defined value, and in
+ * assignments after having called cleanup().
+ *
+ * @param pcszSrc The source string.
+ * @param cchSrc The number of chars (bytes) to copy from the
+ * source strings. RTSTR_MAX is NOT accepted.
+ *
+ * @throws std::bad_alloc On allocation failure. The object is left
+ * describing a NULL string.
+ */
+ void copyFromN(const char *pcszSrc, size_t cchSrc)
+ {
+ if (cchSrc)
+ {
+ m_psz = RTStrAlloc(cchSrc + 1);
+ if (RT_LIKELY(m_psz))
+ {
+ m_cch = cchSrc;
+ m_cbAllocated = cchSrc + 1;
+ memcpy(m_psz, pcszSrc, cchSrc);
+ m_psz[cchSrc] = '\0';
+ }
+ else
+ {
+ m_cch = 0;
+ m_cbAllocated = 0;
+#ifdef RT_EXCEPTIONS_ENABLED
+ throw std::bad_alloc();
+#endif
+ }
+ }
+ else
+ {
+ m_cch = 0;
+ m_cbAllocated = 0;
+ m_psz = NULL;
+ }
+ }
+
+ /**
+ * Appends exactly @a cchSrc chars from @a pszSrc to @a this.
+ *
+ * This is an internal worker for the append() methods.
+ *
+ * @returns Reference to the object.
+ * @param pszSrc The source string.
+ * @param cchSrc The source string length (exact).
+ * @throws std::bad_alloc On allocation error. The object is left unchanged.
+ *
+ */
+ RTCString &appendWorker(const char *pszSrc, size_t cchSrc);
+
+ /**
+ * Appends exactly @a cchSrc chars from @a pszSrc to @a this.
+ *
+ * This is an internal worker for the appendNoThrow() methods.
+ *
+ * @returns VINF_SUCCESS or VERR_NO_STRING_MEMORY.
+ * @param pszSrc The source string.
+ * @param cchSrc The source string length (exact).
+ */
+ int appendWorkerNoThrow(const char *pszSrc, size_t cchSrc) RT_NOEXCEPT;
+
+ /**
+ * Replaces exatly @a cchLength chars at @a offStart with @a cchSrc from @a
+ * pszSrc.
+ *
+ * @returns Reference to the object.
+ * @param offStart Where in @a this string to start replacing.
+ * @param cchLength How much following @a offStart to replace. npos is
+ * accepted.
+ * @param pszSrc The replacement string.
+ * @param cchSrc The exactly length of the replacement string.
+ *
+ * @throws std::bad_alloc On allocation error. The object is left unchanged.
+ */
+ RTCString &replaceWorker(size_t offStart, size_t cchLength, const char *pszSrc, size_t cchSrc);
+
+ /**
+ * Replaces exatly @a cchLength chars at @a offStart with @a cchSrc from @a
+ * pszSrc.
+ *
+ * @returns VINF_SUCCESS, VERR_OUT_OF_RANGE or VERR_NO_STRING_MEMORY.
+ * @param offStart Where in @a this string to start replacing.
+ * @param cchLength How much following @a offStart to replace. npos is
+ * accepted.
+ * @param pszSrc The replacement string.
+ * @param cchSrc The exactly length of the replacement string.
+ */
+ int replaceWorkerNoThrow(size_t offStart, size_t cchLength, const char *pszSrc, size_t cchSrc) RT_NOEXCEPT;
+
+ static DECLCALLBACK(size_t) printfOutputCallback(void *pvArg, const char *pachChars, size_t cbChars);
+ static DECLCALLBACK(size_t) printfOutputCallbackNoThrow(void *pvArg, const char *pachChars, size_t cbChars) RT_NOEXCEPT;
+
+ char *m_psz; /**< The string buffer. */
+ size_t m_cch; /**< strlen(m_psz) - i.e. no terminator included. */
+ size_t m_cbAllocated; /**< Size of buffer that m_psz points to; at least m_cbLength + 1. */
+};
+
+/** @} */
+
+
+/** @addtogroup grp_rt_cpp_string
+ * @{
+ */
+
+/**
+ * Concatenate two strings.
+ *
+ * @param a_rstr1 String one.
+ * @param a_rstr2 String two.
+ * @returns the concatenate string.
+ *
+ * @relates RTCString
+ */
+RTDECL(const RTCString) operator+(const RTCString &a_rstr1, const RTCString &a_rstr2);
+
+/**
+ * Concatenate two strings.
+ *
+ * @param a_rstr1 String one.
+ * @param a_psz2 String two.
+ * @returns the concatenate string.
+ *
+ * @relates RTCString
+ */
+RTDECL(const RTCString) operator+(const RTCString &a_rstr1, const char *a_psz2);
+
+/**
+ * Concatenate two strings.
+ *
+ * @param a_psz1 String one.
+ * @param a_rstr2 String two.
+ * @returns the concatenate string.
+ *
+ * @relates RTCString
+ */
+RTDECL(const RTCString) operator+(const char *a_psz1, const RTCString &a_rstr2);
+
+/**
+ * Class with RTCString::printf as constructor for your convenience.
+ *
+ * Constructing a RTCString string object from a format string and a variable
+ * number of arguments can easily be confused with the other RTCString
+ * constructors, thus this child class.
+ *
+ * The usage of this class is like the following:
+ * @code
+ RTCStringFmt strName("program name = %s", argv[0]);
+ @endcode
+ */
+class RTCStringFmt : public RTCString
+{
+public:
+
+ /**
+ * Constructs a new string given the format string and the list of the
+ * arguments for the format string.
+ *
+ * @param a_pszFormat Pointer to the format string (UTF-8),
+ * @see pg_rt_str_format.
+ * @param ... Ellipsis containing the arguments specified by
+ * the format string.
+ */
+ explicit RTCStringFmt(const char *a_pszFormat, ...) RT_IPRT_FORMAT_ATTR(1, 2)
+ {
+ va_list va;
+ va_start(va, a_pszFormat);
+ printfV(a_pszFormat, va);
+ va_end(va);
+ }
+
+ RTMEMEF_NEW_AND_DELETE_OPERATORS();
+
+protected:
+ RTCStringFmt() {}
+};
+
+/** @} */
+
+#endif /* !IPRT_INCLUDED_cpp_ministring_h */
+
diff --git a/include/iprt/cpp/mtlist.h b/include/iprt/cpp/mtlist.h
new file mode 100644
index 00000000..915fcbad
--- /dev/null
+++ b/include/iprt/cpp/mtlist.h
@@ -0,0 +1,185 @@
+/** @file
+ * IPRT - Generic thread-safe list Class.
+ */
+
+/*
+ * Copyright (C) 2011-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_cpp_mtlist_h
+#define IPRT_INCLUDED_cpp_mtlist_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cpp/list.h>
+#include <iprt/semaphore.h>
+
+/** @addtogroup grp_rt_cpp_list
+ * @{
+ */
+
+/**
+ * A guard class for thread-safe read/write access.
+ */
+template <>
+class RTCListGuard<true>
+{
+public:
+ RTCListGuard() : m_hRWSem(NIL_RTSEMRW)
+ {
+#if defined(RT_LOCK_STRICT_ORDER) && defined(IN_RING3)
+ RTLOCKVALCLASS hClass;
+ int rc = RTLockValidatorClassCreate(&hClass, true /*fAutodidact*/, RT_SRC_POS, "RTCListGuard");
+ AssertStmt(RT_SUCCESS(rc), hClass = NIL_RTLOCKVALCLASS);
+ rc = RTSemRWCreateEx(&m_hRWSem, 0 /*fFlags*/, hClass, RTLOCKVAL_SUB_CLASS_NONE, NULL /*pszNameFmt*/);
+ AssertRC(rc);
+#else
+ int rc = RTSemRWCreateEx(&m_hRWSem, 0 /*fFlags*/, NIL_RTLOCKVALCLASS, 0, NULL);
+ AssertRC(rc);
+#endif
+ }
+
+ ~RTCListGuard()
+ {
+ RTSemRWDestroy(m_hRWSem);
+ m_hRWSem = NIL_RTSEMRW;
+ }
+
+ inline void enterRead() const { int rc = RTSemRWRequestRead(m_hRWSem, RT_INDEFINITE_WAIT); AssertRC(rc); }
+ inline void leaveRead() const { int rc = RTSemRWReleaseRead(m_hRWSem); AssertRC(rc); }
+ inline void enterWrite() { int rc = RTSemRWRequestWrite(m_hRWSem, RT_INDEFINITE_WAIT); AssertRC(rc); }
+ inline void leaveWrite() { int rc = RTSemRWReleaseWrite(m_hRWSem); AssertRC(rc); }
+
+ /* Define our own new and delete. */
+ RTMEMEF_NEW_AND_DELETE_OPERATORS();
+
+private:
+ mutable RTSEMRW m_hRWSem;
+};
+
+/**
+ * @brief Generic thread-safe list class.
+ *
+ * RTCMTList is a thread-safe implementation of the list class. It uses a
+ * read/write semaphore to serialize the access to the items. Several readers
+ * can simultaneous access different or the same item. If one thread is writing
+ * to an item, the other accessors are blocked until the write has finished.
+ *
+ * Although the access is guarded, the user has to make sure the list content
+ * is consistent when iterating over the list or doing any other kind of access
+ * which makes assumptions about the list content. For a finer control of access
+ * restrictions, use your own locking mechanism and the standard list
+ * implementation.
+ *
+ * @see RTCListBase
+ */
+template <class T, typename ITYPE = typename RTCIf<(sizeof(T) > sizeof(void*)), T*, T>::result>
+class RTCMTList : public RTCListBase<T, ITYPE, true>
+{
+ /* Traits */
+ typedef RTCListBase<T, ITYPE, true> BASE;
+
+public:
+ /**
+ * Creates a new list.
+ *
+ * This preallocates @a cCapacity elements within the list.
+ *
+ * @param cCapacity The initial capacity the list has.
+ * @throws std::bad_alloc
+ */
+ RTCMTList(size_t cCapacity = BASE::kDefaultCapacity)
+ : BASE(cCapacity) {}
+
+ /* Define our own new and delete. */
+ RTMEMEF_NEW_AND_DELETE_OPERATORS();
+};
+
+/**
+ * Specialized thread-safe list class for using the native type list for
+ * unsigned 64-bit values even on a 32-bit host.
+ *
+ * @see RTCListBase
+ */
+template <>
+class RTCMTList<uint64_t>: public RTCListBase<uint64_t, uint64_t, true>
+{
+ /* Traits */
+ typedef RTCListBase<uint64_t, uint64_t, true> BASE;
+
+public:
+ /**
+ * Creates a new list.
+ *
+ * This preallocates @a cCapacity elements within the list.
+ *
+ * @param cCapacity The initial capacity the list has.
+ * @throws std::bad_alloc
+ */
+ RTCMTList(size_t cCapacity = BASE::kDefaultCapacity)
+ : BASE(cCapacity) {}
+
+ /* Define our own new and delete. */
+ RTMEMEF_NEW_AND_DELETE_OPERATORS();
+};
+
+/**
+ * Specialized thread-safe list class for using the native type list for
+ * signed 64-bit values even on a 32-bit host.
+ *
+ * @see RTCListBase
+ */
+template <>
+class RTCMTList<int64_t>: public RTCListBase<int64_t, int64_t, true>
+{
+ /* Traits */
+ typedef RTCListBase<int64_t, int64_t, true> BASE;
+
+public:
+ /**
+ * Creates a new list.
+ *
+ * This preallocates @a cCapacity elements within the list.
+ *
+ * @param cCapacity The initial capacity the list has.
+ * @throws std::bad_alloc
+ */
+ RTCMTList(size_t cCapacity = BASE::kDefaultCapacity)
+ : BASE(cCapacity) {}
+
+ /* Define our own new and delete. */
+ RTMEMEF_NEW_AND_DELETE_OPERATORS();
+};
+
+/** @} */
+
+#endif /* !IPRT_INCLUDED_cpp_mtlist_h */
+
diff --git a/include/iprt/cpp/path.h b/include/iprt/cpp/path.h
new file mode 100644
index 00000000..1a3c7f99
--- /dev/null
+++ b/include/iprt/cpp/path.h
@@ -0,0 +1,249 @@
+/** @file
+ * IPRT - C++ path utilities.
+ */
+
+/*
+ * Copyright (C) 2017-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_cpp_path_h
+#define IPRT_INCLUDED_cpp_path_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/assert.h>
+#include <iprt/errcore.h>
+#include <iprt/path.h>
+#include <iprt/cpp/ministring.h>
+
+
+/** @defgroup grp_rt_cpp_path C++ Path Utilities
+ * @ingroup grp_rt_cpp
+ * @{
+ */
+
+/**
+ * RTPathAbs() wrapper for working directly on a RTCString instance.
+ *
+ * @returns IPRT status code.
+ * @param rStrAbs Reference to the destination string.
+ * @param pszRelative The relative source string.
+ */
+DECLINLINE(int) RTPathAbsCxx(RTCString &rStrAbs, const char *pszRelative)
+{
+ Assert(rStrAbs.c_str() != pszRelative);
+ int rc = rStrAbs.reserveNoThrow(RTPATH_MAX);
+ if (RT_SUCCESS(rc))
+ {
+ unsigned cTries = 8;
+ for (;;)
+ {
+ char *pszDst = rStrAbs.mutableRaw();
+ size_t cbCap = rStrAbs.capacity();
+ rc = RTPathAbsEx(NULL, pszRelative, RTPATH_STR_F_STYLE_HOST, pszDst, &cbCap);
+ if (RT_SUCCESS(rc))
+ break;
+ *pszDst = '\0';
+ if (rc != VERR_BUFFER_OVERFLOW)
+ break;
+ if (--cTries == 0)
+ break;
+ rc = rStrAbs.reserveNoThrow(RT_MIN(RT_ALIGN_Z(cbCap, 64), RTPATH_MAX));
+ if (RT_FAILURE(rc))
+ break;
+ }
+ rStrAbs.jolt();
+ }
+ return rc;
+}
+
+
+/**
+ * RTPathAbs() wrapper for working directly on a RTCString instance.
+ *
+ * @returns IPRT status code.
+ * @param rStrAbs Reference to the destination string.
+ * @param rStrRelative Reference to the relative source string.
+ */
+DECLINLINE(int) RTPathAbsCxx(RTCString &rStrAbs, RTCString const &rStrRelative)
+{
+ return RTPathAbsCxx(rStrAbs, rStrRelative.c_str());
+}
+
+
+
+/**
+ * RTPathAbsEx() wrapper for working directly on a RTCString instance.
+ *
+ * @returns IPRT status code.
+ * @param rStrAbs Reference to the destination string.
+ * @param pszBase The base path, optional.
+ * @param pszRelative The relative source string.
+ * @param fFlags RTPATH_STR_F_STYLE_XXX and RTPATHABS_F_XXX flags.
+ */
+DECLINLINE(int) RTPathAbsExCxx(RTCString &rStrAbs, const char *pszBase, const char *pszRelative, uint32_t fFlags = RTPATH_STR_F_STYLE_HOST)
+{
+ Assert(rStrAbs.c_str() != pszRelative);
+ int rc = rStrAbs.reserveNoThrow(RTPATH_MAX);
+ if (RT_SUCCESS(rc))
+ {
+ unsigned cTries = 8;
+ for (;;)
+ {
+ char *pszDst = rStrAbs.mutableRaw();
+ size_t cbCap = rStrAbs.capacity();
+ rc = RTPathAbsEx(pszBase, pszRelative, fFlags, pszDst, &cbCap);
+ if (RT_SUCCESS(rc))
+ break;
+ *pszDst = '\0';
+ if (rc != VERR_BUFFER_OVERFLOW)
+ break;
+ if (--cTries == 0)
+ break;
+ rc = rStrAbs.reserveNoThrow(RT_MIN(RT_ALIGN_Z(cbCap, 64), RTPATH_MAX));
+ if (RT_FAILURE(rc))
+ break;
+ }
+ rStrAbs.jolt();
+ }
+ return rc;
+}
+
+
+DECLINLINE(int) RTPathAbsExCxx(RTCString &rStrAbs, RTCString const &rStrBase, RTCString const &rStrRelative, uint32_t fFlags = RTPATH_STR_F_STYLE_HOST)
+{
+ return RTPathAbsExCxx(rStrAbs, rStrBase.c_str(), rStrRelative.c_str(), fFlags);
+}
+
+
+DECLINLINE(int) RTPathAbsExCxx(RTCString &rStrAbs, const char *pszBase, RTCString const &rStrRelative, uint32_t fFlags = RTPATH_STR_F_STYLE_HOST)
+{
+ return RTPathAbsExCxx(rStrAbs, pszBase, rStrRelative.c_str(), fFlags);
+}
+
+
+DECLINLINE(int) RTPathAbsExCxx(RTCString &rStrAbs, RTCString const &rStrBase, const char *pszRelative, uint32_t fFlags = RTPATH_STR_F_STYLE_HOST)
+{
+ return RTPathAbsExCxx(rStrAbs, rStrBase.c_str(), pszRelative, fFlags);
+}
+
+
+
+/**
+ * RTPathAppPrivateNoArch() wrapper for working directly on a RTCString instance.
+ *
+ * @returns IPRT status code.
+ * @param rStrDst Reference to the destination string.
+ */
+DECLINLINE(int) RTPathAppPrivateNoArchCxx(RTCString &rStrDst)
+{
+ int rc = rStrDst.reserveNoThrow(RTPATH_MAX);
+ if (RT_SUCCESS(rc))
+ {
+ char *pszDst = rStrDst.mutableRaw();
+ rc = RTPathAppPrivateNoArch(pszDst, rStrDst.capacity());
+ if (RT_FAILURE(rc))
+ *pszDst = '\0';
+ rStrDst.jolt();
+ }
+ return rc;
+
+}
+
+
+/**
+ * RTPathAppend() wrapper for working directly on a RTCString instance.
+ *
+ * @returns IPRT status code.
+ * @param rStrDst Reference to the destination string.
+ * @param pszAppend One or more components to append to the path already
+ * present in @a rStrDst.
+ */
+DECLINLINE(int) RTPathAppendCxx(RTCString &rStrDst, const char *pszAppend)
+{
+ Assert(rStrDst.c_str() != pszAppend);
+ size_t cbEstimate = rStrDst.length() + 1 + strlen(pszAppend) + 1;
+ int rc;
+ if (rStrDst.capacity() >= cbEstimate)
+ rc = VINF_SUCCESS;
+ else
+ rc = rStrDst.reserveNoThrow(RT_ALIGN_Z(cbEstimate, 8));
+ if (RT_SUCCESS(rc))
+ {
+ rc = RTPathAppend(rStrDst.mutableRaw(), rStrDst.capacity(), pszAppend);
+ if (rc == VERR_BUFFER_OVERFLOW)
+ {
+ rc = rStrDst.reserveNoThrow(RTPATH_MAX);
+ if (RT_SUCCESS(rc))
+ rc = RTPathAppend(rStrDst.mutableRaw(), rStrDst.capacity(), pszAppend);
+ }
+ rStrDst.jolt();
+ }
+ return rc;
+}
+
+
+/**
+ * RTPathAppend() wrapper for working directly on a RTCString instance.
+ *
+ * @returns IPRT status code.
+ * @param rStrDst Reference to the destination string.
+ * @param rStrAppend One or more components to append to the path already
+ * present in @a rStrDst.
+ */
+DECLINLINE(int) RTPathAppendCxx(RTCString &rStrDst, RTCString const &rStrAppend)
+{
+ Assert(&rStrDst != &rStrAppend);
+ size_t cbEstimate = rStrDst.length() + 1 + rStrAppend.length() + 1;
+ int rc;
+ if (rStrDst.capacity() >= cbEstimate)
+ rc = VINF_SUCCESS;
+ else
+ rc = rStrDst.reserveNoThrow(RT_ALIGN_Z(cbEstimate, 8));
+ if (RT_SUCCESS(rc))
+ {
+ rc = RTPathAppend(rStrDst.mutableRaw(), rStrDst.capacity(), rStrAppend.c_str());
+ if (rc == VERR_BUFFER_OVERFLOW)
+ {
+ rc = rStrDst.reserveNoThrow(RTPATH_MAX);
+ if (RT_SUCCESS(rc))
+ rc = RTPathAppend(rStrDst.mutableRaw(), rStrDst.capacity(), rStrAppend.c_str());
+ }
+ rStrDst.jolt();
+ }
+ return rc;
+}
+
+
+/** @} */
+
+#endif /* !IPRT_INCLUDED_cpp_path_h */
+
diff --git a/include/iprt/cpp/restanyobject.h b/include/iprt/cpp/restanyobject.h
new file mode 100644
index 00000000..a83a769b
--- /dev/null
+++ b/include/iprt/cpp/restanyobject.h
@@ -0,0 +1,139 @@
+/** @file
+ * IPRT - C++ Representational State Transfer (REST) Any Object Class.
+ */
+
+/*
+ * Copyright (C) 2008-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_cpp_restanyobject_h
+#define IPRT_INCLUDED_cpp_restanyobject_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cpp/restbase.h>
+#include <iprt/cpp/restarray.h>
+#include <iprt/cpp/reststringmap.h>
+
+
+/** @defgroup grp_rt_cpp_restanyobj C++ Representational State Transfer (REST) Any Object Class.
+ * @ingroup grp_rt_cpp
+ * @{
+ */
+
+/**
+ * Wrapper object that can represent any kind of basic REST object.
+ *
+ * This class is the result of a couple of design choices made in our REST
+ * data model. If could have been avoided if we used pointers all over
+ * the place and didn't rely entirely on the object specific implementations
+ * of deserializeFromJson and fromString to do the deserializing or everything.
+ *
+ * The assumption, though, was that most of the data we're dealing with has a
+ * known structure and maps to fixed types. So, the data model was optimized
+ * for that rather than flexiblity here.
+ */
+class RT_DECL_CLASS RTCRestAnyObject : public RTCRestObjectBase
+{
+public:
+ /** Default constructor. */
+ RTCRestAnyObject() RT_NOEXCEPT;
+ /** Destructor. */
+ virtual ~RTCRestAnyObject();
+
+ /** Copy constructor. */
+ RTCRestAnyObject(RTCRestAnyObject const &a_rThat);
+ /** Copy assignment operator. */
+ RTCRestAnyObject &operator=(RTCRestAnyObject const &a_rThat);
+
+ /** Safe copy assignment method. */
+ int assignCopy(RTCRestAnyObject const &a_rThat) RT_NOEXCEPT;
+ /** Safe copy assignment method, boolean variant. */
+ int assignCopy(RTCRestBool const &a_rThat) RT_NOEXCEPT;
+ /** Safe copy assignment method, int64_t variant. */
+ int assignCopy(RTCRestInt64 const &a_rThat) RT_NOEXCEPT;
+ /** Safe copy assignment method, int32_t variant. */
+ int assignCopy(RTCRestInt32 const &a_rThat) RT_NOEXCEPT;
+ /** Safe copy assignment method, int16_t variant. */
+ int assignCopy(RTCRestInt16 const &a_rThat) RT_NOEXCEPT;
+ /** Safe copy assignment method, double variant. */
+ int assignCopy(RTCRestDouble const &a_rThat) RT_NOEXCEPT;
+ /** Safe copy assignment method, string variant. */
+ int assignCopy(RTCRestString const &a_rThat) RT_NOEXCEPT;
+ /** Safe copy assignment method, array variant. */
+ int assignCopy(RTCRestArray<RTCRestAnyObject> const &a_rThat) RT_NOEXCEPT;
+ /** Safe copy assignment method, string map variant. */
+ int assignCopy(RTCRestStringMap<RTCRestAnyObject> const &a_rThat) RT_NOEXCEPT;
+
+ /** Safe value assignment method, boolean variant. */
+ int assignValue(bool a_fValue) RT_NOEXCEPT;
+ /** Safe value assignment method, int64_t variant. */
+ int assignValue(int64_t a_iValue) RT_NOEXCEPT;
+ /** Safe value assignment method, int32_t variant. */
+ int assignValue(int32_t a_iValue) RT_NOEXCEPT;
+ /** Safe value assignment method, int16_t variant. */
+ int assignValue(int16_t a_iValue) RT_NOEXCEPT;
+ /** Safe value assignment method, double variant. */
+ int assignValue(double a_iValue) RT_NOEXCEPT;
+ /** Safe value assignment method, string variant. */
+ int assignValue(RTCString const &a_rValue) RT_NOEXCEPT;
+ /** Safe value assignment method, C-string variant. */
+ int assignValue(const char *a_pszValue) RT_NOEXCEPT;
+
+ /** Make a clone of this object. */
+ inline RTCRestAnyObject *clone() const RT_NOEXCEPT { return (RTCRestAnyObject *)baseClone(); }
+
+ /* Overridden methods: */
+ virtual RTCRestObjectBase *baseClone() const RT_NOEXCEPT RT_OVERRIDE;
+ virtual int setNull(void) RT_NOEXCEPT RT_OVERRIDE;
+ virtual int resetToDefault() RT_NOEXCEPT RT_OVERRIDE;
+ virtual RTCRestOutputBase &serializeAsJson(RTCRestOutputBase &a_rDst) const RT_NOEXCEPT RT_OVERRIDE;
+ virtual int deserializeFromJson(RTCRestJsonCursor const &a_rCursor) RT_NOEXCEPT RT_OVERRIDE;
+ virtual int toString(RTCString *a_pDst, uint32_t a_fFlags = kCollectionFormat_Unspecified) const RT_NOEXCEPT RT_OVERRIDE;
+ virtual int fromString(RTCString const &a_rValue, const char *a_pszName, PRTERRINFO a_pErrInfo = NULL,
+ uint32_t a_fFlags = kCollectionFormat_Unspecified) RT_NOEXCEPT RT_OVERRIDE;
+ virtual kTypeClass typeClass(void) const RT_NOEXCEPT RT_OVERRIDE;
+ virtual const char *typeName(void) const RT_NOEXCEPT RT_OVERRIDE;
+
+ /** Factory method. */
+ static DECLCALLBACK(RTCRestObjectBase *) createInstance(void) RT_NOEXCEPT;
+ /** Deserialization w/ instantiation. */
+ static FNDESERIALIZEINSTANCEFROMJSON deserializeInstanceFromJson;
+
+protected:
+ /** The data. */
+ RTCRestObjectBase *m_pData;
+};
+
+/** @} */
+
+#endif /* !IPRT_INCLUDED_cpp_restanyobject_h */
+
diff --git a/include/iprt/cpp/restarray.h b/include/iprt/cpp/restarray.h
new file mode 100644
index 00000000..56509c4e
--- /dev/null
+++ b/include/iprt/cpp/restarray.h
@@ -0,0 +1,463 @@
+/** @file
+ * IPRT - C++ Representational State Transfer (REST) Array Template Class.
+ */
+
+/*
+ * Copyright (C) 2008-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_cpp_restarray_h
+#define IPRT_INCLUDED_cpp_restarray_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cpp/restbase.h>
+
+
+/** @defgroup grp_rt_cpp_restarray C++ Representational State Transfer (REST) Array Template Class.
+ * @ingroup grp_rt_cpp
+ * @{
+ */
+
+/**
+ * Abstract base class for the RTCRestArray template.
+ */
+class RT_DECL_CLASS RTCRestArrayBase : public RTCRestObjectBase
+{
+public:
+ /** Default destructor. */
+ RTCRestArrayBase() RT_NOEXCEPT;
+ /** Destructor. */
+ virtual ~RTCRestArrayBase();
+
+ /* Overridden methods: */
+ virtual RTCRestObjectBase *baseClone() const RT_NOEXCEPT RT_OVERRIDE;
+ virtual int resetToDefault() RT_NOEXCEPT RT_OVERRIDE;
+ virtual RTCRestOutputBase &serializeAsJson(RTCRestOutputBase &a_rDst) const RT_NOEXCEPT RT_OVERRIDE;
+ virtual int deserializeFromJson(RTCRestJsonCursor const &a_rCursor) RT_NOEXCEPT RT_OVERRIDE;
+ virtual int toString(RTCString *a_pDst, uint32_t a_fFlags = kCollectionFormat_Unspecified) const RT_NOEXCEPT RT_OVERRIDE;
+ virtual int fromString(RTCString const &a_rValue, const char *a_pszName, PRTERRINFO a_pErrInfo = NULL,
+ uint32_t a_fFlags = kCollectionFormat_Unspecified) RT_NOEXCEPT RT_OVERRIDE;
+ virtual kTypeClass typeClass(void) const RT_NOEXCEPT RT_OVERRIDE;
+ virtual const char *typeName(void) const RT_NOEXCEPT RT_OVERRIDE;
+
+ /**
+ * Clear the content of the map.
+ */
+ void clear() RT_NOEXCEPT;
+
+ /**
+ * Check if an list contains any items.
+ *
+ * @return True if there is more than zero items, false otherwise.
+ */
+ inline bool isEmpty() const RT_NOEXCEPT
+ {
+ return m_cElements == 0;
+ }
+
+ /**
+ * Gets the number of entries in the map.
+ */
+ inline size_t size() const RT_NOEXCEPT
+ {
+ return m_cElements;
+ }
+
+ /**
+ * Returns the base object pointer at a given index.
+ *
+ * @returns The base object at @a a_idx, NULL if out of range.
+ * @param a_idx The array index.
+ */
+ inline RTCRestObjectBase *atBase(size_t a_idx) RT_NOEXCEPT
+ {
+ if (a_idx < m_cElements)
+ return m_papElements[a_idx];
+ return NULL;
+ }
+
+ /**
+ * Returns the const base object pointer at a given index.
+ *
+ * @returns The base object at @a a_idx, NULL if out of range.
+ * @param a_idx The array index.
+ */
+ inline RTCRestObjectBase const *atBase(size_t a_idx) const RT_NOEXCEPT
+ {
+ if (a_idx < m_cElements)
+ return m_papElements[a_idx];
+ return NULL;
+ }
+
+ /**
+ * Removes the element at @a a_idx.
+ * @returns true if @a a_idx is valid, false if out of range.
+ * @param a_idx The index of the element to remove.
+ * The value ~(size_t)0 is an alias for the final element.
+ */
+ bool removeAt(size_t a_idx) RT_NOEXCEPT;
+
+ /**
+ * Makes sure the array can hold at the given number of entries.
+ *
+ * @returns VINF_SUCCESS or VERR_NO_MEMORY.
+ * @param a_cEnsureCapacity The number of elements to ensure capacity to hold.
+ */
+ int ensureCapacity(size_t a_cEnsureCapacity) RT_NOEXCEPT;
+
+
+protected:
+ /** The array. */
+ RTCRestObjectBase **m_papElements;
+ /** Number of elements in the array. */
+ size_t m_cElements;
+ /** The number of elements m_papElements can hold.
+ * The difference between m_cCapacity and m_cElements are all NULLs. */
+ size_t m_cCapacity;
+
+ /**
+ * Helper for creating a clone.
+ *
+ * @returns Pointer to new array on success, NULL if out of memory.
+ */
+ virtual RTCRestArrayBase *createClone(void) const RT_NOEXCEPT = 0;
+
+ /**
+ * Wrapper around the value constructor.
+ *
+ * @returns Pointer to new value object on success, NULL if out of memory.
+ */
+ virtual RTCRestObjectBase *createValue(void) RT_NOEXCEPT = 0;
+
+ /**
+ * For accessing the static deserializeInstanceFromJson() method of the value.
+ */
+ virtual int deserializeValueInstanceFromJson(RTCRestJsonCursor const &a_rCursor, RTCRestObjectBase **a_ppInstance) RT_NOEXCEPT = 0;
+
+ /**
+ * Worker for the copy assignment method and copyArrayWorkerMayThrow().
+ *
+ * This will use createEntryCopy to do the copying.
+ *
+ * @returns VINF_SUCCESS on success, VERR_NO_MEMORY or VERR_NO_STR_MEMORY on failure.
+ * @param a_rThat The array to copy. Caller makes 100% sure the it has
+ * the same type as the destination.
+ */
+ int copyArrayWorkerNoThrow(RTCRestArrayBase const &a_rThat) RT_NOEXCEPT;
+
+ /**
+ * Wrapper around copyArrayWorkerNoThrow for the copy constructor and the
+ * assignment operator.
+ */
+ void copyArrayWorkerMayThrow(RTCRestArrayBase const &a_rThat);
+
+ /**
+ * Worker for performing inserts.
+ *
+ * @returns VINF_SUCCESS or VWRN_ALREADY_EXISTS on success.
+ * VERR_ALREADY_EXISTS, VERR_NO_MEMORY or VERR_NO_STR_MEMORY on failure.
+ * @param a_idx Where to insert it. The value ~(size_t)0 is an alias for m_cElements.
+ * @param a_pValue The value to insert. Ownership is transferred to the map on success.
+ * @param a_fReplace Whether to replace existing entry rather than insert.
+ */
+ int insertWorker(size_t a_idx, RTCRestObjectBase *a_pValue, bool a_fReplace) RT_NOEXCEPT;
+
+ /**
+ * Worker for performing inserts.
+ *
+ * @returns VINF_SUCCESS or VWRN_ALREADY_EXISTS on success.
+ * VERR_ALREADY_EXISTS, VERR_NO_MEMORY or VERR_NO_STR_MEMORY on failure.
+ * @param a_idx Where to insert it. The value ~(size_t)0 is an alias for m_cElements.
+ * @param a_rValue The value to copy into the map.
+ * @param a_fReplace Whether to replace existing key-value pair with matching key.
+ */
+ int insertCopyWorker(size_t a_idx, RTCRestObjectBase const &a_rValue, bool a_fReplace) RT_NOEXCEPT;
+
+private:
+ /** Copy constructor on this class should never be used. */
+ RTCRestArrayBase(RTCRestArrayBase const &a_rThat);
+ /** Copy assignment operator on this class should never be used. */
+ RTCRestArrayBase &operator=(RTCRestArrayBase const &a_rThat);
+};
+
+
+
+/**
+ * Limited array class.
+ */
+template<class ElementType> class RTCRestArray : public RTCRestArrayBase
+{
+public:
+ /** Default constructor - empty array. */
+ RTCRestArray() RT_NOEXCEPT
+ : RTCRestArrayBase()
+ {
+ }
+
+ /** Destructor. */
+ ~RTCRestArray()
+ {
+ }
+
+ /** Copy constructor. */
+ RTCRestArray(RTCRestArray const &a_rThat)
+ : RTCRestArrayBase()
+ {
+ copyArrayWorkerMayThrow(a_rThat);
+ }
+
+ /** Copy assignment operator. */
+ inline RTCRestArray &operator=(RTCRestArray const &a_rThat)
+ {
+ copyArrayWorkerMayThrow(a_rThat);
+ return *this;
+ }
+
+ /** Safe copy assignment method. */
+ inline int assignCopy(RTCRestArray const &a_rThat) RT_NOEXCEPT
+ {
+ return copyArrayWorkerNoThrow(a_rThat);
+ }
+
+ /** Make a clone of this object. */
+ inline RTCRestArray *clone() const RT_NOEXCEPT
+ {
+ return (RTCRestArray *)baseClone();
+ }
+
+ /** Factory method. */
+ static DECLCALLBACK(RTCRestObjectBase *) createInstance(void) RT_NOEXCEPT
+ {
+ return new (std::nothrow) RTCRestArray<ElementType>();
+ }
+
+ /** Factory method for elements. */
+ static DECLCALLBACK(RTCRestObjectBase *) createElementInstance(void) RT_NOEXCEPT
+ {
+ return new (std::nothrow) ElementType();
+ }
+
+ /** @copydoc RTCRestObjectBase::FNDESERIALIZEINSTANCEFROMJSON */
+ static DECLCALLBACK(int) deserializeInstanceFromJson(RTCRestJsonCursor const &a_rCursor, RTCRestObjectBase **a_ppInstance) RT_NOEXCEPT
+ {
+ *a_ppInstance = new (std::nothrow) RTCRestArray<ElementType>();
+ if (*a_ppInstance)
+ return (*a_ppInstance)->deserializeFromJson(a_rCursor);
+ return a_rCursor.m_pPrimary->addError(a_rCursor, VERR_NO_MEMORY, "Out of memory");
+ }
+
+
+ /**
+ * Insert the given object at the specified index.
+ *
+ * @returns VINF_SUCCESS on success.
+ * VERR_INVALID_POINTER, VERR_NO_MEMORY, VERR_NO_STR_MEMORY or VERR_OUT_OF_RANGE on failure.
+ * @param a_idx The insertion index. ~(size_t)0 is an alias for the end.
+ * @param a_pThat The object to insert. The array takes ownership of the object on success.
+ */
+ inline int insert(size_t a_idx, ElementType *a_pThat) RT_NOEXCEPT
+ {
+ return insertWorker(a_idx, a_pThat, false /*a_fReplace*/);
+ }
+
+ /**
+ * Insert a copy of the object at the specified index.
+ *
+ * @returns VINF_SUCCESS on success.
+ * VERR_NO_MEMORY, VERR_NO_STR_MEMORY or VERR_OUT_OF_RANGE on failure.
+ * @param a_idx The insertion index. ~(size_t)0 is an alias for the end.
+ * @param a_rThat The object to insert a copy of.
+ */
+ inline int insertCopy(size_t a_idx, ElementType const &a_rThat) RT_NOEXCEPT
+ {
+ return insertCopyWorker(a_idx, a_rThat, false /*a_fReplace*/);
+ }
+
+ /**
+ * Appends the given object to the array.
+ *
+ * @returns VINF_SUCCESS on success.
+ * VERR_INVALID_POINTER, VERR_NO_MEMORY, VERR_NO_STR_MEMORY or VERR_OUT_OF_RANGE on failure.
+ * @param a_pThat The object to insert. The array takes ownership of the object on success.
+ */
+ inline int append(ElementType *a_pThat) RT_NOEXCEPT
+ {
+ return insertWorker(~(size_t)0, a_pThat, false /*a_fReplace*/);
+ }
+
+ /**
+ * Appends a copy of the object at the specified index.
+ *
+ * @returns VINF_SUCCESS on success.
+ * VERR_NO_MEMORY, VERR_NO_STR_MEMORY or VERR_OUT_OF_RANGE on failure.
+ * @param a_rThat The object to insert a copy of.
+ */
+ inline int appendCopy(ElementType const &a_rThat) RT_NOEXCEPT
+ {
+ return insertCopyWorker(~(size_t)0, a_rThat, false /*a_fReplace*/);
+ }
+
+ /**
+ * Prepends the given object to the array.
+ *
+ * @returns VINF_SUCCESS on success.
+ * VERR_INVALID_POINTER, VERR_NO_MEMORY, VERR_NO_STR_MEMORY or VERR_OUT_OF_RANGE on failure.
+ * @param a_pThat The object to insert. The array takes ownership of the object on success.
+ */
+ inline int prepend(ElementType *a_pThat) RT_NOEXCEPT
+ {
+ return insertWorker(0, a_pThat, false /*a_fReplace*/);
+ }
+
+ /**
+ * Prepends a copy of the object at the specified index.
+ *
+ * @returns VINF_SUCCESS on success.
+ * VERR_NO_MEMORY, VERR_NO_STR_MEMORY or VERR_OUT_OF_RANGE on failure.
+ * @param a_rThat The object to insert a copy of.
+ */
+ inline int prependCopy(ElementType const &a_rThat) RT_NOEXCEPT
+ {
+ return insertCopyWorker(0, a_rThat, false /*a_fReplace*/);
+ }
+
+ /**
+ * Insert the given object at the specified index.
+ *
+ * @returns VINF_SUCCESS on success.
+ * VERR_INVALID_POINTER, VERR_NO_MEMORY, VERR_NO_STR_MEMORY or VERR_OUT_OF_RANGE on failure.
+ * @param a_idx The index of the existing object to replace.
+ * @param a_pThat The replacement object. The array takes ownership of the object on success.
+ */
+ inline int replace(size_t a_idx, ElementType *a_pThat) RT_NOEXCEPT
+ {
+ return insertWorker(a_idx, a_pThat, true /*a_fReplace*/);
+ }
+
+ /**
+ * Insert a copy of the object at the specified index.
+ *
+ * @returns VINF_SUCCESS on success.
+ * VERR_NO_MEMORY, VERR_NO_STR_MEMORY or VERR_OUT_OF_RANGE on failure.
+ * @param a_idx The index of the existing object to replace.
+ * @param a_rThat The object to insert a copy of.
+ */
+ inline int replaceCopy(size_t a_idx, ElementType const &a_rThat) RT_NOEXCEPT
+ {
+ return insertCopyWorker(a_idx, a_rThat, true /*a_fReplace*/);
+ }
+
+ /**
+ * Returns the object at a given index.
+ *
+ * @returns The object at @a a_idx, NULL if out of range.
+ * @param a_idx The array index.
+ */
+ inline ElementType *at(size_t a_idx) RT_NOEXCEPT
+ {
+ if (a_idx < m_cElements)
+ return (ElementType *)m_papElements[a_idx];
+ return NULL;
+ }
+
+ /**
+ * Returns the object at a given index, const variant.
+ *
+ * @returns The object at @a a_idx, NULL if out of range.
+ * @param a_idx The array index.
+ */
+ inline ElementType const *at(size_t a_idx) const RT_NOEXCEPT
+ {
+ if (a_idx < m_cElements)
+ return (ElementType const *)m_papElements[a_idx];
+ return NULL;
+ }
+
+ /**
+ * Returns the first object in the array.
+ * @returns The first object, NULL if empty.
+ */
+ inline ElementType *first() RT_NOEXCEPT
+ {
+ return at(0);
+ }
+
+ /**
+ * Returns the first object in the array, const variant.
+ * @returns The first object, NULL if empty.
+ */
+ inline ElementType const *first() const RT_NOEXCEPT
+ {
+ return at(0);
+ }
+
+ /**
+ * Returns the last object in the array.
+ * @returns The last object, NULL if empty.
+ */
+ inline ElementType *last() RT_NOEXCEPT
+ {
+ return at(m_cElements - 1);
+ }
+
+ /**
+ * Returns the last object in the array, const variant.
+ * @returns The last object, NULL if empty.
+ */
+ inline ElementType const *last() const RT_NOEXCEPT
+ {
+ return at(m_cElements - 1);
+ }
+
+
+protected:
+ virtual RTCRestArrayBase *createClone(void) const RT_NOEXCEPT RT_OVERRIDE
+ {
+ return new (std::nothrow) RTCRestArray();
+ }
+
+ virtual RTCRestObjectBase *createValue(void) RT_NOEXCEPT RT_OVERRIDE
+ {
+ return new (std::nothrow) ElementType();
+ }
+
+ virtual int deserializeValueInstanceFromJson(RTCRestJsonCursor const &a_rCursor, RTCRestObjectBase **a_ppInstance) RT_NOEXCEPT RT_OVERRIDE
+ {
+ return ElementType::deserializeInstanceFromJson(a_rCursor, a_ppInstance);
+ }
+};
+
+
+/** @} */
+
+#endif /* !IPRT_INCLUDED_cpp_restarray_h */
+
diff --git a/include/iprt/cpp/restbase.h b/include/iprt/cpp/restbase.h
new file mode 100644
index 00000000..912610df
--- /dev/null
+++ b/include/iprt/cpp/restbase.h
@@ -0,0 +1,1106 @@
+/** @file
+ * IPRT - C++ Representational State Transfer (REST) Base Classes.
+ */
+
+/*
+ * Copyright (C) 2008-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_cpp_restbase_h
+#define IPRT_INCLUDED_cpp_restbase_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+#include <iprt/errcore.h> /* VERR_NO_MEMORY */
+#include <iprt/json.h>
+#include <iprt/stdarg.h>
+#include <iprt/time.h>
+#include <iprt/cpp/ministring.h>
+
+
+/** @defgroup grp_rt_cpp_restbase C++ Representational State Transfer (REST) Base Classes.
+ * @ingroup grp_rt_cpp
+ * @{
+ */
+
+/* forward decl: */
+class RTCRestOutputBase;
+class RTCRestJsonPrimaryCursor;
+
+/**
+ * JSON cursor structure.
+ *
+ * This reduces the number of parameters passed around when deserializing JSON
+ * input and also helps constructing full object name for logging and error reporting.
+ */
+struct RT_DECL_CLASS RTCRestJsonCursor
+{
+ /** Handle to the value being parsed. */
+ RTJSONVAL m_hValue;
+ /** Name of the value. */
+ const char *m_pszName;
+ /** Pointer to the parent, NULL if primary. */
+ struct RTCRestJsonCursor const *m_pParent;
+ /** Pointer to the primary cursor structure. */
+ RTCRestJsonPrimaryCursor *m_pPrimary;
+
+ RTCRestJsonCursor(struct RTCRestJsonCursor const &a_rParent) RT_NOEXCEPT
+ : m_hValue(NIL_RTJSONVAL), m_pszName(NULL), m_pParent(&a_rParent), m_pPrimary(a_rParent.m_pPrimary)
+ { }
+
+ RTCRestJsonCursor(RTJSONVAL hValue, const char *pszName, struct RTCRestJsonCursor *pParent) RT_NOEXCEPT
+ : m_hValue(hValue), m_pszName(pszName), m_pParent(pParent), m_pPrimary(pParent->m_pPrimary)
+ { }
+
+ RTCRestJsonCursor(RTJSONVAL hValue, const char *pszName) RT_NOEXCEPT
+ : m_hValue(hValue), m_pszName(pszName), m_pParent(NULL), m_pPrimary(NULL)
+ { }
+
+ ~RTCRestJsonCursor()
+ {
+ if (m_hValue != NIL_RTJSONVAL)
+ {
+ RTJsonValueRelease(m_hValue);
+ m_hValue = NIL_RTJSONVAL;
+ }
+ }
+};
+
+
+/**
+ * The primary JSON cursor class.
+ */
+class RT_DECL_CLASS RTCRestJsonPrimaryCursor
+{
+public:
+ /** The cursor for the first level. */
+ RTCRestJsonCursor m_Cursor;
+ /** Error info keeper. */
+ PRTERRINFO m_pErrInfo;
+
+ /** Creates a primary json cursor with optiona error info. */
+ RTCRestJsonPrimaryCursor(RTJSONVAL hValue, const char *pszName, PRTERRINFO pErrInfo = NULL) RT_NOEXCEPT
+ : m_Cursor(hValue, pszName)
+ , m_pErrInfo(pErrInfo)
+ {
+ m_Cursor.m_pPrimary = this;
+ }
+
+ virtual ~RTCRestJsonPrimaryCursor()
+ { }
+
+ /**
+ * Add an error message.
+ *
+ * @returns a_rc
+ * @param a_rCursor The cursor reporting the error.
+ * @param a_rc The status code.
+ * @param a_pszFormat Format string.
+ * @param ... Format string arguments.
+ */
+ virtual int addError(RTCRestJsonCursor const &a_rCursor, int a_rc, const char *a_pszFormat, ...) RT_NOEXCEPT;
+
+ /**
+ * Reports that the current field is not known.
+ *
+ * @returns Status to propagate.
+ * @param a_rCursor The cursor for the field.
+ */
+ virtual int unknownField(RTCRestJsonCursor const &a_rCursor) RT_NOEXCEPT;
+
+ /**
+ * Copies the full path into pszDst.
+ *
+ * @returns pszDst
+ * @param a_rCursor The cursor to start walking at.
+ * @param a_pszDst Where to put the path.
+ * @param a_cbDst Size of the destination buffer.
+ */
+ virtual char *getPath(RTCRestJsonCursor const &a_rCursor, char *a_pszDst, size_t a_cbDst) const RT_NOEXCEPT;
+};
+
+
+/**
+ * Abstract base class for REST primitive types and data objects (via
+ * RTCRestDataObject).
+ *
+ * The only information this keeps is the null indicator.
+ */
+class RT_DECL_CLASS RTCRestObjectBase
+{
+public:
+ RTCRestObjectBase() RT_NOEXCEPT;
+ RTCRestObjectBase(RTCRestObjectBase const &a_rThat) RT_NOEXCEPT;
+ virtual ~RTCRestObjectBase();
+
+ /** Copy assignment operator. */
+ RTCRestObjectBase &operator=(RTCRestObjectBase const &a_rThat) RT_NOEXCEPT;
+
+ /**
+ * Create a copy of this object.
+ *
+ * @returns Pointer to copy.
+ */
+ virtual RTCRestObjectBase *baseClone() const RT_NOEXCEPT = 0;
+
+ /**
+ * Tests if the object is @a null.
+ * @returns true if null, false if not.
+ */
+ inline bool isNull(void) const RT_NOEXCEPT { return m_fNullIndicator; };
+
+ /**
+ * Sets the object to @a null and fills it with defaults.
+ * @returns IPRT status code (from resetToDefault).
+ */
+ virtual int setNull(void) RT_NOEXCEPT;
+
+ /**
+ * Sets the object to not-null state (i.e. undoes setNull()).
+ * @remarks Only really important for strings.
+ */
+ virtual void setNotNull(void) RT_NOEXCEPT;
+
+ /**
+ * Resets the object to all default values.
+ * @returns IPRT status code.
+ */
+ virtual int resetToDefault() RT_NOEXCEPT = 0;
+
+ /**
+ * Serialize the object as JSON.
+ *
+ * @returns a_rDst
+ * @param a_rDst The destination for the serialization.
+ */
+ virtual RTCRestOutputBase &serializeAsJson(RTCRestOutputBase &a_rDst) const RT_NOEXCEPT = 0;
+
+ /**
+ * Deserialize object from the given JSON iterator.
+ *
+ * @returns IPRT status code.
+ * @param a_rCursor The JSON cursor.
+ */
+ virtual int deserializeFromJson(RTCRestJsonCursor const &a_rCursor) RT_NOEXCEPT = 0;
+
+ /**
+ * Polymorphic JSON deserialization helper that instantiate the matching class using
+ * the discriminator field.
+ *
+ * @returns IPRT status code.
+ * @param a_rCursor The JSON cursor.
+ * @param a_ppInstance Where to return the deserialized instance.
+ * May return an object on failure.
+ */
+ typedef DECLCALLBACKTYPE(int, FNDESERIALIZEINSTANCEFROMJSON,(RTCRestJsonCursor const &a_rCursor, RTCRestObjectBase **a_ppInstance));
+ /** Pointer to a FNDESERIALIZEINSTANCEFROMJSON function. */
+ typedef FNDESERIALIZEINSTANCEFROMJSON *PFNDESERIALIZEINSTANCEFROMJSON;
+
+ /**
+ * Flags for toString().
+ *
+ * The kCollectionFormat_xxx bunch controls multiple values in arrays
+ * are formatted. They are ignored by everyone else.
+ *
+ * @note When adding collection format types, make sure to also
+ * update RTCRestArrayBase::toString().
+ * @note Bit 24 is reserved (for kHdrField_MapCollection).
+ */
+ enum
+ {
+ kCollectionFormat_Unspecified = 0, /**< Not specified. */
+ kCollectionFormat_csv, /**< Comma-separated list. */
+ kCollectionFormat_ssv, /**< Space-separated list. */
+ kCollectionFormat_tsv, /**< Tab-separated list. */
+ kCollectionFormat_pipes, /**< Pipe-separated list. */
+ kCollectionFormat_multi, /**< Special collection type that must be handled by caller of toString. */
+ kCollectionFormat_Mask = 7, /**< Collection type mask. */
+
+ kToString_Append = 8 /**< Append to the string/object (rather than assigning). */
+ };
+
+ /**
+ * String conversion.
+ *
+ * The default implementation of is a wrapper around serializeAsJson().
+ *
+ * @returns IPRT status code.
+ * @param a_pDst Pointer to the destionation string.
+ * @param a_fFlags kCollectionFormat_xxx.
+ */
+ virtual int toString(RTCString *a_pDst, uint32_t a_fFlags = kCollectionFormat_Unspecified) const RT_NOEXCEPT;
+
+ /**
+ * String convertsion, naive variant.
+ *
+ * @returns String represenation.
+ */
+ RTCString toString() const;
+
+ /**
+ * Convert from (header) string value.
+ *
+ * The default implementation of is a wrapper around deserializeFromJson().
+ *
+ * @returns IPRT status code.
+ * @param a_rValue The string value string to parse.
+ * @param a_pszName Field name or similar.
+ * @param a_pErrInfo Where to return additional error info. Optional.
+ * @param a_fFlags kCollectionFormat_xxx.
+ */
+ virtual int fromString(RTCString const &a_rValue, const char *a_pszName, PRTERRINFO a_pErrInfo = NULL,
+ uint32_t a_fFlags = kCollectionFormat_Unspecified) RT_NOEXCEPT;
+
+ /** Type classification */
+ typedef enum kTypeClass
+ {
+ kTypeClass_Invalid = 0,
+ kTypeClass_Bool, /**< Primitive: bool. */
+ kTypeClass_Int64, /**< Primitive: int64_t. */
+ kTypeClass_Int32, /**< Primitive: int32_t. */
+ kTypeClass_Int16, /**< Primitive: int16_t. */
+ kTypeClass_Double, /**< Primitive: double. */
+ kTypeClass_String, /**< Primitive: string. */
+ kTypeClass_Date, /**< Date. */
+ kTypeClass_Uuid, /**< UUID. */
+ kTypeClass_Binary, /**< Binary blob. */
+ kTypeClass_DataObject, /**< Data object child (RTCRestDataObject). */
+ kTypeClass_AnyObject, /**< Any kind of object (RTCRestAnyObject). */
+ kTypeClass_Array, /**< Array (containing any kind of object). */
+ kTypeClass_StringMap, /**< String map (containing any kind of object). */
+ kTypeClass_StringEnum /**< String enum. */
+ } kTypeClass;
+
+ /**
+ * Returns the object type class.
+ */
+ virtual kTypeClass typeClass(void) const RT_NOEXCEPT = 0;
+
+ /**
+ * Returns the object type name.
+ */
+ virtual const char *typeName(void) const RT_NOEXCEPT = 0;
+
+protected:
+ /** Null indicator.
+ * @remarks The null values could be mapped onto C/C++ NULL pointer values,
+ * with the consequence that all data members in objects and such would
+ * have had to been allocated individually, even simple @a bool members.
+ * Given that we're overly paranoid about heap allocations (std::bad_alloc),
+ * it's more fitting to use a null indicator for us.
+ */
+ bool m_fNullIndicator;
+};
+
+
+/**
+ * Class wrapping 'bool'.
+ */
+class RT_DECL_CLASS RTCRestBool : public RTCRestObjectBase
+{
+public:
+ /** Default constructor. */
+ RTCRestBool() RT_NOEXCEPT;
+ /** Copy constructor. */
+ RTCRestBool(RTCRestBool const &a_rThat) RT_NOEXCEPT;
+ /** From value constructor. */
+ RTCRestBool(bool fValue) RT_NOEXCEPT;
+ /** Destructor. */
+ virtual ~RTCRestBool();
+ /** Copy assignment operator. */
+ RTCRestBool &operator=(RTCRestBool const &a_rThat) RT_NOEXCEPT;
+ /** Safe copy assignment method. */
+ int assignCopy(RTCRestBool const &a_rThat) RT_NOEXCEPT;
+ /** Assign value and clear null indicator. */
+ void assignValue(bool a_fValue) RT_NOEXCEPT;
+ /** Make a clone of this object. */
+ inline RTCRestBool *clone() const RT_NOEXCEPT { return (RTCRestBool *)baseClone(); }
+
+ /* Overridden methods: */
+ virtual RTCRestObjectBase *baseClone() const RT_NOEXCEPT RT_OVERRIDE;
+ virtual int resetToDefault() RT_NOEXCEPT RT_OVERRIDE;
+ virtual RTCRestOutputBase &serializeAsJson(RTCRestOutputBase &a_rDst) const RT_NOEXCEPT RT_OVERRIDE;
+ virtual int deserializeFromJson(RTCRestJsonCursor const &a_rCursor) RT_NOEXCEPT RT_OVERRIDE;
+ virtual int toString(RTCString *a_pDst, uint32_t a_fFlags = 0) const RT_NOEXCEPT RT_OVERRIDE;
+ virtual int fromString(RTCString const &a_rValue, const char *a_pszName, PRTERRINFO a_pErrInfo = NULL,
+ uint32_t a_fFlags = kCollectionFormat_Unspecified) RT_NOEXCEPT RT_OVERRIDE;
+ virtual kTypeClass typeClass(void) const RT_NOEXCEPT RT_OVERRIDE;
+ virtual const char *typeName(void) const RT_NOEXCEPT RT_OVERRIDE;
+
+ /** Factory method. */
+ static DECLCALLBACK(RTCRestObjectBase *) createInstance(void) RT_NOEXCEPT;
+ /** @copydoc RTCRestObjectBase::FNDESERIALIZEINSTANCEFROMJSON */
+ static DECLCALLBACK(int) deserializeInstanceFromJson(RTCRestJsonCursor const &a_rCursor, RTCRestObjectBase **a_ppInstance) RT_NOEXCEPT;
+
+public:
+ /** The value. */
+ bool m_fValue;
+};
+
+
+/**
+ * Class wrapping 'int64_t'.
+ */
+class RT_DECL_CLASS RTCRestInt64 : public RTCRestObjectBase
+{
+public:
+ /** Default constructor. */
+ RTCRestInt64() RT_NOEXCEPT;
+ /** Copy constructor. */
+ RTCRestInt64(RTCRestInt64 const &a_rThat) RT_NOEXCEPT;
+ /** From value constructor. */
+ RTCRestInt64(int64_t a_iValue) RT_NOEXCEPT;
+ /** Destructor. */
+ virtual ~RTCRestInt64();
+ /** Copy assignment operator. */
+ RTCRestInt64 &operator=(RTCRestInt64 const &a_rThat) RT_NOEXCEPT;
+ /** Safe copy assignment method. */
+ int assignCopy(RTCRestInt64 const &a_rThat) RT_NOEXCEPT;
+ /** Assign value and clear null indicator. */
+ void assignValue(int64_t a_iValue) RT_NOEXCEPT;
+ /** Make a clone of this object. */
+ inline RTCRestInt64 *clone() const RT_NOEXCEPT { return (RTCRestInt64 *)baseClone(); }
+
+ /* Overridden methods: */
+ virtual RTCRestObjectBase *baseClone() const RT_NOEXCEPT RT_OVERRIDE;
+ virtual int resetToDefault() RT_NOEXCEPT RT_OVERRIDE;
+ virtual RTCRestOutputBase &serializeAsJson(RTCRestOutputBase &a_rDst) const RT_NOEXCEPT RT_OVERRIDE;
+ virtual int deserializeFromJson(RTCRestJsonCursor const &a_rCursor) RT_NOEXCEPT RT_OVERRIDE;
+ virtual int toString(RTCString *a_pDst, uint32_t a_fFlags = 0) const RT_NOEXCEPT RT_OVERRIDE;
+ virtual int fromString(RTCString const &a_rValue, const char *a_pszName, PRTERRINFO a_pErrInfo = NULL,
+ uint32_t a_fFlags = kCollectionFormat_Unspecified) RT_NOEXCEPT RT_OVERRIDE;
+ virtual kTypeClass typeClass(void) const RT_NOEXCEPT RT_OVERRIDE;
+ virtual const char *typeName(void) const RT_NOEXCEPT RT_OVERRIDE;
+
+ /** Factory method. */
+ static DECLCALLBACK(RTCRestObjectBase *) createInstance(void) RT_NOEXCEPT;
+ /** @copydoc RTCRestObjectBase::FNDESERIALIZEINSTANCEFROMJSON */
+ static DECLCALLBACK(int) deserializeInstanceFromJson(RTCRestJsonCursor const &a_rCursor, RTCRestObjectBase **a_ppInstance) RT_NOEXCEPT;
+
+public:
+ /** The value. */
+ int64_t m_iValue;
+};
+
+
+/**
+ * Class wrapping 'int32_t'.
+ */
+class RT_DECL_CLASS RTCRestInt32 : public RTCRestObjectBase
+{
+public:
+ /** Default constructor. */
+ RTCRestInt32() RT_NOEXCEPT;
+ /** Copy constructor. */
+ RTCRestInt32(RTCRestInt32 const &a_rThat) RT_NOEXCEPT;
+ /** From value constructor. */
+ RTCRestInt32(int32_t iValue) RT_NOEXCEPT;
+ /** Destructor. */
+ virtual ~RTCRestInt32() RT_NOEXCEPT;
+ /** Copy assignment operator. */
+ RTCRestInt32 &operator=(RTCRestInt32 const &a_rThat) RT_NOEXCEPT;
+ /** Safe copy assignment method. */
+ int assignCopy(RTCRestInt32 const &a_rThat) RT_NOEXCEPT;
+ /** Assign value and clear null indicator. */
+ void assignValue(int32_t a_iValue) RT_NOEXCEPT;
+ /** Make a clone of this object. */
+ inline RTCRestInt32 *clone() const { return (RTCRestInt32 *)baseClone(); }
+
+ /* Overridden methods: */
+ virtual RTCRestObjectBase *baseClone() const RT_NOEXCEPT RT_OVERRIDE;
+ virtual int resetToDefault() RT_NOEXCEPT RT_OVERRIDE;
+ virtual RTCRestOutputBase &serializeAsJson(RTCRestOutputBase &a_rDst) const RT_NOEXCEPT RT_OVERRIDE;
+ virtual int deserializeFromJson(RTCRestJsonCursor const &a_rCursor) RT_NOEXCEPT RT_OVERRIDE;
+ virtual int toString(RTCString *a_pDst, uint32_t a_fFlags = 0) const RT_NOEXCEPT RT_OVERRIDE;
+ virtual int fromString(RTCString const &a_rValue, const char *a_pszName, PRTERRINFO a_pErrInfo = NULL,
+ uint32_t a_fFlags = kCollectionFormat_Unspecified) RT_NOEXCEPT RT_OVERRIDE;
+ virtual kTypeClass typeClass(void) const RT_NOEXCEPT RT_OVERRIDE;
+ virtual const char *typeName(void) const RT_NOEXCEPT RT_OVERRIDE;
+
+ /** Factory method. */
+ static DECLCALLBACK(RTCRestObjectBase *) createInstance(void) RT_NOEXCEPT;
+ /** @copydoc RTCRestObjectBase::FNDESERIALIZEINSTANCEFROMJSON */
+ static DECLCALLBACK(int) deserializeInstanceFromJson(RTCRestJsonCursor const &a_rCursor, RTCRestObjectBase **a_ppInstance) RT_NOEXCEPT;
+
+public:
+ /** The value. */
+ int32_t m_iValue;
+};
+
+
+/**
+ * Class wrapping 'int16_t'.
+ */
+class RT_DECL_CLASS RTCRestInt16 : public RTCRestObjectBase
+{
+public:
+ /** Default constructor. */
+ RTCRestInt16() RT_NOEXCEPT;
+ /** Copy constructor. */
+ RTCRestInt16(RTCRestInt16 const &a_rThat) RT_NOEXCEPT;
+ /** From value constructor. */
+ RTCRestInt16(int16_t iValue) RT_NOEXCEPT;
+ /** Destructor. */
+ virtual ~RTCRestInt16();
+ /** Copy assignment operator. */
+ RTCRestInt16 &operator=(RTCRestInt16 const &a_rThat) RT_NOEXCEPT;
+ /** Safe copy assignment method. */
+ int assignCopy(RTCRestInt16 const &a_rThat) RT_NOEXCEPT;
+ /** Assign value and clear null indicator. */
+ void assignValue(int16_t a_iValue) RT_NOEXCEPT;
+ /** Make a clone of this object. */
+ inline RTCRestInt16 *clone() const RT_NOEXCEPT { return (RTCRestInt16 *)baseClone(); }
+
+ /* Overridden methods: */
+ virtual RTCRestObjectBase *baseClone() const RT_NOEXCEPT RT_OVERRIDE;
+ virtual int resetToDefault() RT_NOEXCEPT RT_OVERRIDE;
+ virtual RTCRestOutputBase &serializeAsJson(RTCRestOutputBase &a_rDst) const RT_NOEXCEPT RT_OVERRIDE;
+ virtual int deserializeFromJson(RTCRestJsonCursor const &a_rCursor) RT_NOEXCEPT RT_OVERRIDE;
+ virtual int toString(RTCString *a_pDst, uint32_t a_fFlags = 0) const RT_NOEXCEPT RT_OVERRIDE;
+ virtual int fromString(RTCString const &a_rValue, const char *a_pszName, PRTERRINFO a_pErrInfo = NULL,
+ uint32_t a_fFlags = kCollectionFormat_Unspecified) RT_NOEXCEPT RT_OVERRIDE;
+ virtual kTypeClass typeClass(void) const RT_NOEXCEPT RT_OVERRIDE;
+ virtual const char *typeName(void) const RT_NOEXCEPT RT_OVERRIDE;
+
+ /** Factory method. */
+ static DECLCALLBACK(RTCRestObjectBase *) createInstance(void) RT_NOEXCEPT;
+ /** @copydoc RTCRestObjectBase::FNDESERIALIZEINSTANCEFROMJSON */
+ static DECLCALLBACK(int) deserializeInstanceFromJson(RTCRestJsonCursor const &a_rCursor, RTCRestObjectBase **a_ppInstance) RT_NOEXCEPT;
+
+public:
+ /** The value. */
+ int16_t m_iValue;
+};
+
+
+/**
+ * Class wrapping 'double'.
+ */
+class RT_DECL_CLASS RTCRestDouble : public RTCRestObjectBase
+{
+public:
+ /** Default constructor. */
+ RTCRestDouble() RT_NOEXCEPT;
+ /** Copy constructor. */
+ RTCRestDouble(RTCRestDouble const &a_rThat) RT_NOEXCEPT;
+ /** From value constructor. */
+ RTCRestDouble(double rdValue) RT_NOEXCEPT;
+ /** Destructor. */
+ virtual ~RTCRestDouble();
+ /** Copy assignment operator. */
+ RTCRestDouble &operator=(RTCRestDouble const &a_rThat) RT_NOEXCEPT;
+ /** Safe copy assignment method. */
+ int assignCopy(RTCRestDouble const &a_rThat) RT_NOEXCEPT;
+ /** Assign value and clear null indicator. */
+ void assignValue(double a_rdValue) RT_NOEXCEPT;
+ /** Make a clone of this object. */
+ inline RTCRestDouble *clone() const RT_NOEXCEPT { return (RTCRestDouble *)baseClone(); }
+
+ /* Overridden methods: */
+ virtual RTCRestObjectBase *baseClone() const RT_NOEXCEPT RT_OVERRIDE;
+ virtual int resetToDefault() RT_NOEXCEPT RT_OVERRIDE;
+ virtual RTCRestOutputBase &serializeAsJson(RTCRestOutputBase &a_rDst) const RT_NOEXCEPT RT_OVERRIDE;
+ virtual int deserializeFromJson(RTCRestJsonCursor const &a_rCursor) RT_NOEXCEPT RT_OVERRIDE;
+ virtual int toString(RTCString *a_pDst, uint32_t a_fFlags = 0) const RT_NOEXCEPT RT_OVERRIDE;
+ virtual int fromString(RTCString const &a_rValue, const char *a_pszName, PRTERRINFO a_pErrInfo = NULL,
+ uint32_t a_fFlags = kCollectionFormat_Unspecified) RT_NOEXCEPT RT_OVERRIDE;
+ virtual kTypeClass typeClass(void) const RT_NOEXCEPT RT_OVERRIDE;
+ virtual const char *typeName(void) const RT_NOEXCEPT RT_OVERRIDE;
+
+ /** Factory method. */
+ static DECLCALLBACK(RTCRestObjectBase *) createInstance(void) RT_NOEXCEPT;
+ /** @copydoc RTCRestObjectBase::FNDESERIALIZEINSTANCEFROMJSON */
+ static DECLCALLBACK(int) deserializeInstanceFromJson(RTCRestJsonCursor const &a_rCursor, RTCRestObjectBase **a_ppInstance) RT_NOEXCEPT;
+
+public:
+ /** The value. */
+ double m_rdValue;
+};
+
+
+/**
+ * Class wrapping 'RTCString'.
+ */
+class RT_DECL_CLASS RTCRestString : public RTCRestObjectBase, public RTCString
+{
+public:
+ /** Default constructor. */
+ RTCRestString() RT_NOEXCEPT;
+ /** Destructor. */
+ virtual ~RTCRestString();
+
+ /** Copy constructor. */
+ RTCRestString(RTCRestString const &a_rThat);
+ /** From value constructor. */
+ RTCRestString(RTCString const &a_rThat);
+ /** From value constructor. */
+ RTCRestString(const char *a_pszSrc);
+ /** Safe copy assignment method. */
+ int assignCopy(RTCRestString const &a_rThat) RT_NOEXCEPT;
+ /** Safe copy assignment method. */
+ int assignCopy(RTCString const &a_rThat) RT_NOEXCEPT;
+ /** Safe copy assignment method. */
+ int assignCopy(const char *a_pszThat) RT_NOEXCEPT;
+ /** Make a clone of this object. */
+ inline RTCRestString *clone() const RT_NOEXCEPT { return (RTCRestString *)baseClone(); }
+
+ /* Overridden methods: */
+ virtual RTCRestObjectBase *baseClone() const RT_NOEXCEPT RT_OVERRIDE;
+ virtual int setNull(void) RT_NOEXCEPT RT_OVERRIDE; /* (ambigious, so overrider it to make sure.) */
+ virtual int resetToDefault() RT_NOEXCEPT RT_OVERRIDE;
+ virtual RTCRestOutputBase &serializeAsJson(RTCRestOutputBase &a_rDst) const RT_NOEXCEPT RT_OVERRIDE;
+ virtual int deserializeFromJson(RTCRestJsonCursor const &a_rCursor) RT_NOEXCEPT RT_OVERRIDE;
+ virtual int toString(RTCString *a_pDst, uint32_t a_fFlags = kCollectionFormat_Unspecified) const RT_NOEXCEPT RT_OVERRIDE;
+ virtual int fromString(RTCString const &a_rValue, const char *a_pszName, PRTERRINFO a_pErrInfo = NULL,
+ uint32_t a_fFlags = kCollectionFormat_Unspecified) RT_NOEXCEPT RT_OVERRIDE;
+ virtual kTypeClass typeClass(void) const RT_NOEXCEPT RT_OVERRIDE;
+ virtual const char *typeName(void) const RT_NOEXCEPT RT_OVERRIDE;
+
+ /** Factory method. */
+ static DECLCALLBACK(RTCRestObjectBase *) createInstance(void) RT_NOEXCEPT;
+ /** @copydoc RTCRestObjectBase::FNDESERIALIZEINSTANCEFROMJSON */
+ static DECLCALLBACK(int) deserializeInstanceFromJson(RTCRestJsonCursor const &a_rCursor, RTCRestObjectBase **a_ppInstance) RT_NOEXCEPT;
+
+ /** @name RTCString assignment methods we need to replace to manage the null indicator
+ * @{ */
+ int assignNoThrow(const RTCString &a_rSrc) RT_NOEXCEPT;
+ int assignNoThrow(const char *a_pszSrc) RT_NOEXCEPT;
+ int assignNoThrow(const RTCString &a_rSrc, size_t a_offSrc, size_t a_cchSrc = npos) RT_NOEXCEPT;
+ int assignNoThrow(const char *a_pszSrc, size_t a_cchSrc) RT_NOEXCEPT;
+ int assignNoThrow(size_t a_cTimes, char a_ch) RT_NOEXCEPT;
+ int printfNoThrow(const char *pszFormat, ...) RT_NOEXCEPT RT_IPRT_FORMAT_ATTR(1, 2);
+ int printfVNoThrow(const char *pszFormat, va_list va) RT_NOEXCEPT RT_IPRT_FORMAT_ATTR(1, 0);
+ RTCRestString &operator=(const char *a_pcsz);
+ RTCRestString &operator=(const RTCString &a_rThat);
+ RTCRestString &operator=(const RTCRestString &a_rThat);
+ RTCRestString &assign(const RTCString &a_rSrc);
+ RTCRestString &assign(const char *a_pszSrc);
+ RTCRestString &assign(const RTCString &a_rSrc, size_t a_offSrc, size_t a_cchSrc = npos);
+ RTCRestString &assign(const char *a_pszSrc, size_t a_cchSrc);
+ RTCRestString &assign(size_t a_cTimes, char a_ch);
+ RTCRestString &printf(const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(1, 2);
+ RTCRestString &printfV(const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(1, 0);
+ /** @} */
+};
+
+
+/**
+ * Date class.
+ *
+ * There are numerous ways of formatting a timestamp and the specifications
+ * we're currently working with doesn't have a way of telling it seems.
+ * Thus, decoding need to have fail safes built in so the user can give hints.
+ * The formatting likewise needs to be told which format to use by the user.
+ *
+ * Two side-effects of the format stuff is that the default constructor creates
+ * an object that is null, and resetToDefault will do the same bug leave the
+ * format as a hint.
+ */
+class RT_DECL_CLASS RTCRestDate : public RTCRestObjectBase
+{
+public:
+ /** Default constructor.
+ * @note The result is a null-object. */
+ RTCRestDate() RT_NOEXCEPT;
+ /** Copy constructor. */
+ RTCRestDate(RTCRestDate const &a_rThat);
+ /** Destructor. */
+ virtual ~RTCRestDate();
+ /** Copy assignment operator. */
+ RTCRestDate &operator=(RTCRestDate const &a_rThat);
+ /** Safe copy assignment method. */
+ int assignCopy(RTCRestDate const &a_rThat) RT_NOEXCEPT;
+ /** Make a clone of this object. */
+ inline RTCRestDate *clone() const RT_NOEXCEPT{ return (RTCRestDate *)baseClone(); }
+
+ /* Overridden methods: */
+ virtual RTCRestObjectBase *baseClone() const RT_NOEXCEPT RT_OVERRIDE;
+ virtual int resetToDefault() RT_NOEXCEPT RT_OVERRIDE;
+ virtual RTCRestOutputBase &serializeAsJson(RTCRestOutputBase &a_rDst) const RT_NOEXCEPT RT_OVERRIDE;
+ virtual int deserializeFromJson(RTCRestJsonCursor const &a_rCursor) RT_NOEXCEPT RT_OVERRIDE;
+ virtual int toString(RTCString *a_pDst, uint32_t a_fFlags = 0) const RT_NOEXCEPT RT_OVERRIDE;
+ virtual int fromString(RTCString const &a_rValue, const char *a_pszName, PRTERRINFO a_pErrInfo = NULL,
+ uint32_t a_fFlags = kCollectionFormat_Unspecified) RT_NOEXCEPT RT_OVERRIDE;
+ virtual kTypeClass typeClass(void) const RT_NOEXCEPT RT_OVERRIDE;
+ virtual const char *typeName(void) const RT_NOEXCEPT RT_OVERRIDE;
+
+ /** Factory method. */
+ static DECLCALLBACK(RTCRestObjectBase *) createInstance(void) RT_NOEXCEPT;
+ /** @copydoc RTCRestObjectBase::FNDESERIALIZEINSTANCEFROMJSON */
+ static DECLCALLBACK(int) deserializeInstanceFromJson(RTCRestJsonCursor const &a_rCursor, RTCRestObjectBase **a_ppInstance) RT_NOEXCEPT;
+
+ /** Date formats. */
+ typedef enum
+ {
+ kFormat_Invalid = 0,
+ kFormat_Rfc2822, /**< Format it according to RFC-2822. */
+ kFormat_Rfc7131, /**< Format it according to RFC-7131 (HTTP). */
+ kFormat_Rfc3339, /**< Format it according to RFC-3339 (ISO-8601) (no fraction). */
+ kFormat_Rfc3339_Fraction_2, /**< Format it according to RFC-3339 (ISO-8601) with two digit fraction (hundreths). */
+ kFormat_Rfc3339_Fraction_3, /**< Format it according to RFC-3339 (ISO-8601) with three digit fraction (milliseconds). */
+ kFormat_Rfc3339_Fraction_6, /**< Format it according to RFC-3339 (ISO-8601) with six digit fraction (microseconds). */
+ kFormat_Rfc3339_Fraction_9, /**< Format it according to RFC-3339 (ISO-8601) with nine digit fraction (nanoseconds). */
+ kFormat_End
+ } kFormat;
+
+ /**
+ * Assigns the value, formats it as a string and clears the null indicator.
+ *
+ * @returns VINF_SUCCESS, VERR_NO_STR_MEMORY or VERR_INVALID_PARAMETER.
+ * @param a_pTimeSpec The time spec to set.
+ * @param a_enmFormat The date format to use when formatting it.
+ */
+ int assignValue(PCRTTIMESPEC a_pTimeSpec, kFormat a_enmFormat) RT_NOEXCEPT;
+ int assignValueRfc2822(PCRTTIMESPEC a_pTimeSpec) RT_NOEXCEPT; /**< Convenience method for email/whatnot. */
+ int assignValueRfc7131(PCRTTIMESPEC a_pTimeSpec) RT_NOEXCEPT; /**< Convenience method for HTTP date. */
+ int assignValueRfc3339(PCRTTIMESPEC a_pTimeSpec) RT_NOEXCEPT; /**< Convenience method for ISO-8601 timstamp. */
+
+ /**
+ * Assigns the current UTC time and clears the null indicator .
+ *
+ * @returns VINF_SUCCESS, VERR_NO_STR_MEMORY or VERR_INVALID_PARAMETER.
+ * @returns VINF_SUCCESS or VERR_NO_STR_MEMORY.
+ * @param a_enmFormat The date format to use when formatting it.
+ */
+ int assignNow(kFormat a_enmFormat) RT_NOEXCEPT;
+ int assignNowRfc2822() RT_NOEXCEPT; /**< Convenience method for email/whatnot. */
+ int assignNowRfc7131() RT_NOEXCEPT; /**< Convenience method for HTTP date. */
+ int assignNowRfc3339() RT_NOEXCEPT; /**< Convenience method for ISO-8601 timstamp. */
+
+ /**
+ * Sets the format to help deal with decoding issues.
+ *
+ * This can also be used to change the date format for an okay timespec.
+ * @returns IPRT status code.
+ * @param a_enmFormat The date format to try/set.
+ */
+ int setFormat(kFormat a_enmFormat) RT_NOEXCEPT;
+
+ /** Check if the value is okay (m_TimeSpec & m_Exploded). */
+ inline bool isOkay() const RT_NOEXCEPT { return m_fTimeSpecOkay; }
+ /** Get the timespec value. */
+ inline RTTIMESPEC const &getTimeSpec() const RT_NOEXCEPT { return m_TimeSpec; }
+ /** Get the exploded time. */
+ inline RTTIME const &getExploded() const RT_NOEXCEPT { return m_Exploded; }
+ /** Gets the format. */
+ inline kFormat getFormat() const RT_NOEXCEPT { return m_enmFormat; }
+ /** Get the formatted/raw string value. */
+ inline RTCString const &getString() const RT_NOEXCEPT { return m_strFormatted; }
+
+ /** Get nanoseconds since unix epoch. */
+ inline int64_t getEpochNano() const RT_NOEXCEPT { return RTTimeSpecGetNano(&m_TimeSpec); }
+ /** Get seconds since unix epoch. */
+ inline int64_t getEpochSeconds() const RT_NOEXCEPT { return RTTimeSpecGetSeconds(&m_TimeSpec); }
+ /** Checks if UTC time. */
+ inline bool isUtc() const RT_NOEXCEPT { return (m_Exploded.fFlags & RTTIME_FLAGS_TYPE_MASK) != RTTIME_FLAGS_TYPE_LOCAL; }
+ /** Checks if local time. */
+ inline bool isLocal() const RT_NOEXCEPT { return (m_Exploded.fFlags & RTTIME_FLAGS_TYPE_MASK) == RTTIME_FLAGS_TYPE_LOCAL; }
+
+protected:
+ /** The value. */
+ RTTIMESPEC m_TimeSpec;
+ /** The exploded time value. */
+ RTTIME m_Exploded;
+ /** Set if m_TimeSpec is okay, consult m_strFormatted if not. */
+ bool m_fTimeSpecOkay;
+ /** The format / format hint. */
+ kFormat m_enmFormat;
+ /** The formatted date string.
+ * This will be the raw input string for a deserialized value, where as for
+ * a value set by the user it will be the formatted value. */
+ RTCString m_strFormatted;
+
+ /**
+ * Explodes and formats the m_TimeSpec value.
+ *
+ * Sets m_Exploded, m_strFormatted, m_fTimeSpecOkay, and m_enmFormat, clears m_fNullIndicator.
+ *
+ * @returns VINF_SUCCESS or VERR_NO_STR_MEMORY.
+ * @param a_enmFormat The format to use.
+ */
+ int explodeAndFormat(kFormat a_enmFormat) RT_NOEXCEPT;
+
+ /**
+ * Formats the m_Exploded value.
+ *
+ * Sets m_strFormatted, m_fTimeSpecOkay, and m_enmFormat, clears m_fNullIndicator.
+ *
+ * @returns VINF_SUCCESS or VERR_NO_STR_MEMORY.
+ * @param a_enmFormat The format to use.
+ */
+ int format(kFormat a_enmFormat) RT_NOEXCEPT;
+
+ /**
+ * Internal worker that attempts to decode m_strFormatted.
+ *
+ * Sets m_fTimeSpecOkay.
+ *
+ * @returns IPRT status code.
+ * @param enmFormat Specific format to try, kFormat_Invalid (default) to try guess it.
+ */
+ int decodeFormattedString(kFormat enmFormat = kFormat_Invalid) RT_NOEXCEPT;
+};
+
+
+/** We should provide a proper UUID class eventually. Currently it is not used. */
+typedef RTCRestString RTCRestUuid;
+
+
+/**
+ * String enum base class.
+ */
+class RT_DECL_CLASS RTCRestStringEnumBase : public RTCRestObjectBase
+{
+public:
+ /** Enum map entry. */
+ typedef struct ENUMMAPENTRY
+ {
+ const char *pszName;
+ uint32_t cchName;
+ int32_t iValue;
+ } ENUMMAPENTRY;
+
+ /** Default constructor. */
+ RTCRestStringEnumBase() RT_NOEXCEPT;
+ /** Destructor. */
+ virtual ~RTCRestStringEnumBase();
+
+ /** Copy constructor. */
+ RTCRestStringEnumBase(RTCRestStringEnumBase const &a_rThat);
+ /** Copy assignment operator. */
+ RTCRestStringEnumBase &operator=(RTCRestStringEnumBase const &a_rThat);
+
+ /** Safe copy assignment method. */
+ int assignCopy(RTCRestStringEnumBase const &a_rThat) RT_NOEXCEPT;
+ /** Safe copy assignment method. */
+ inline int assignCopy(RTCString const &a_rThat) RT_NOEXCEPT { return setByString(a_rThat); }
+ /** Safe copy assignment method. */
+ inline int assignCopy(const char *a_pszThat) RT_NOEXCEPT { return setByString(a_pszThat); }
+
+ /* Overridden methods: */
+ virtual int resetToDefault() RT_NOEXCEPT RT_OVERRIDE;
+ virtual RTCRestOutputBase &serializeAsJson(RTCRestOutputBase &a_rDst) const RT_NOEXCEPT RT_OVERRIDE;
+ virtual int deserializeFromJson(RTCRestJsonCursor const &a_rCursor) RT_NOEXCEPT RT_OVERRIDE;
+ virtual int toString(RTCString *a_pDst, uint32_t a_fFlags = kCollectionFormat_Unspecified) const RT_NOEXCEPT RT_OVERRIDE;
+ virtual int fromString(RTCString const &a_rValue, const char *a_pszName, PRTERRINFO a_pErrInfo = NULL,
+ uint32_t a_fFlags = kCollectionFormat_Unspecified) RT_NOEXCEPT RT_OVERRIDE;
+ virtual kTypeClass typeClass(void) const RT_NOEXCEPT RT_OVERRIDE;
+
+ /**
+ * Sets the value given a C-string value.
+ *
+ * @retval VINF_SUCCESS on success.
+ * @retval VWRN_NOT_FOUND if not mappable to enum value.
+ * @retval VERR_NO_STR_MEMORY if not mappable and we're out of memory.
+ * @param a_pszValue The string value.
+ * @param a_cchValue The string value length. Optional.
+ */
+ int setByString(const char *a_pszValue, size_t a_cchValue = RTSTR_MAX) RT_NOEXCEPT;
+
+ /**
+ * Sets the value given a string value.
+ *
+ * @retval VINF_SUCCESS on success.
+ * @retval VWRN_NOT_FOUND if not mappable to enum value.
+ * @retval VERR_NO_STR_MEMORY if not mappable and we're out of memory.
+ * @param a_rValue The string value.
+ */
+ int setByString(RTCString const &a_rValue) RT_NOEXCEPT;
+
+ /**
+ * Gets the string value.
+ */
+ const char *getString() const RT_NOEXCEPT;
+
+ /** Maps the given string value to an enum. */
+ int stringToEnum(const char *a_pszValue, size_t a_cchValue = RTSTR_MAX) RT_NOEXCEPT;
+ /** Maps the given string value to an enum. */
+ int stringToEnum(RTCString const &a_rStrValue) RT_NOEXCEPT;
+ /** Maps the given string value to an enum. */
+ const char *enumToString(int a_iEnumValue, size_t *a_pcchString) RT_NOEXCEPT;
+
+
+protected:
+ /** The enum value. */
+ int m_iEnumValue;
+ /** The string value if not a match. */
+ RTCString m_strValue;
+
+ /**
+ * Worker for setting the object to the given enum value.
+ *
+ * @retval true on success.
+ * @retval false if a_iEnumValue can't be translated.
+ * @param a_iEnumValue The enum value to set.
+ */
+ bool setWorker(int a_iEnumValue) RT_NOEXCEPT;
+
+ /** Helper for implementing RTCRestObjectBase::clone(). */
+ RTCRestObjectBase *cloneWorker(RTCRestStringEnumBase *a_pDst) const RT_NOEXCEPT;
+
+ /**
+ * Gets the mapping table.
+ *
+ * @returns Pointer to the translation table.
+ * @param pcEntries Where to return the translation table size.
+ */
+ virtual ENUMMAPENTRY const *getMappingTable(size_t *pcEntries) const RT_NOEXCEPT = 0;
+};
+
+
+/**
+ * String enum template class.
+ *
+ * Takes the enum type as argument.
+ */
+template <typename EnumType>
+class RTCRestStringEnum : public RTCRestStringEnumBase
+{
+public:
+ typedef EnumType Type; /**< The enum type. */
+
+ /** Default constructor */
+ RTCRestStringEnum() RT_NOEXCEPT : RTCRestStringEnumBase() { }
+ /** Constructor with initial enum value. */
+ RTCRestStringEnum(Type a_enmValue) RT_NOEXCEPT : RTCRestStringEnumBase() { set(a_enmValue); }
+ /** Constructor with string default. */
+ RTCRestStringEnum(const char *a_pszDefault) : RTCRestStringEnumBase() { setByString(a_pszDefault); }
+ /** Copy constructor */
+ RTCRestStringEnum(RTCRestStringEnum const &a_rThat) : RTCRestStringEnumBase(a_rThat) { }
+ /** Make a clone of this object. */
+ inline RTCRestStringEnum *clone() const RT_NOEXCEPT { return (RTCRestStringEnum *)baseClone(); }
+
+ virtual RTCRestObjectBase *baseClone() const RT_NOEXCEPT RT_OVERRIDE
+ {
+ return cloneWorker(new (std::nothrow) RTCRestStringEnum());
+ }
+
+ /** Copy assignment operator. */
+ RTCRestStringEnum &operator=(RTCRestStringEnum const &a_rThat) RT_NOEXCEPT
+ {
+ RTCRestStringEnumBase::operator=(a_rThat);
+ return *this;
+ }
+
+ /**
+ * Gets the enum value.
+ * @returns enum value.
+ * @retval kXxxxInvalid means there was no mapping for the string, or that
+ * no value has been assigned yet.
+ */
+ Type get() const RT_NOEXCEPT { return (Type)m_iEnumValue; }
+
+ /**
+ * Sets the object value to @a a_enmType
+ *
+ * @returns true if a_enmType is valid, false if not.
+ * @param a_enmType The new value.
+ */
+ bool set(Type a_enmType) RT_NOEXCEPT { return setWorker((int)a_enmType); }
+
+ virtual const char *typeName(void) const RT_NOEXCEPT RT_OVERRIDE { return "RTCRestStringEnum<EnumType>"; }
+
+ /** Factory method. */
+ static DECLCALLBACK(RTCRestObjectBase *) createInstance(void) RT_NOEXCEPT
+ {
+ return new (std::nothrow) RTCRestStringEnum();
+ }
+
+ /** @copydoc RTCRestObjectBase::FNDESERIALIZEINSTANCEFROMJSON */
+ static DECLCALLBACK(int) deserializeInstanceFromJson(RTCRestJsonCursor const &a_rCursor, RTCRestObjectBase **a_ppInstance) RT_NOEXCEPT
+ {
+ *a_ppInstance = new (std::nothrow) RTCRestStringEnum();
+ if (*a_ppInstance)
+ return (*a_ppInstance)->deserializeFromJson(a_rCursor);
+ return a_rCursor.m_pPrimary->addError(a_rCursor, VERR_NO_MEMORY, "Out of memory");
+ }
+
+protected:
+ /** Enum mapping table. */
+ static const ENUMMAPENTRY s_aMappingTable[];
+ /** Enum mapping table size. */
+ static const size_t s_cMappingTable;
+
+ virtual ENUMMAPENTRY const *getMappingTable(size_t *pcEntries) const RT_NOEXCEPT RT_OVERRIDE
+ {
+ *pcEntries = s_cMappingTable;
+ return s_aMappingTable;
+ }
+};
+
+
+/**
+ * Class for handling binary blobs (strings).
+ *
+ * There are specializations of this class for body parameters and responses,
+ * see RTCRestBinaryParameter and RTCRestBinaryResponse.
+ */
+class RT_DECL_CLASS RTCRestBinary : public RTCRestObjectBase
+{
+public:
+ /** Default constructor. */
+ RTCRestBinary() RT_NOEXCEPT;
+ /** Destructor. */
+ virtual ~RTCRestBinary();
+
+ /** Safe copy assignment method. */
+ virtual int assignCopy(RTCRestBinary const &a_rThat) RT_NOEXCEPT;
+ /** Safe buffer copy method. */
+ virtual int assignCopy(void const *a_pvData, size_t a_cbData) RT_NOEXCEPT;
+
+ /** Use the specified data buffer directly. */
+ virtual int assignReadOnly(void const *a_pvData, size_t a_cbData) RT_NOEXCEPT;
+ /** Use the specified data buffer directly. */
+ virtual int assignWriteable(void *a_pvBuf, size_t a_cbBuf) RT_NOEXCEPT;
+ /** Frees the data held by the object and resets it default state. */
+ virtual void freeData() RT_NOEXCEPT;
+
+ /** Returns a pointer to the data blob. */
+ inline const uint8_t *getPtr() const RT_NOEXCEPT { return m_pbData; }
+ /** Gets the size of the data. */
+ inline size_t getSize() const RT_NOEXCEPT { return m_cbData; }
+
+ /** Make a clone of this object. */
+ inline RTCRestBinary *clone() const RT_NOEXCEPT { return (RTCRestBinary *)baseClone(); }
+
+ /* Overridden methods: */
+ virtual RTCRestObjectBase *baseClone() const RT_NOEXCEPT RT_OVERRIDE;
+ virtual int setNull(void) RT_NOEXCEPT RT_OVERRIDE;
+ virtual int resetToDefault(void) RT_NOEXCEPT RT_OVERRIDE;
+ virtual RTCRestOutputBase &serializeAsJson(RTCRestOutputBase &a_rDst) const RT_NOEXCEPT RT_OVERRIDE;
+ virtual int deserializeFromJson(RTCRestJsonCursor const &a_rCursor) RT_NOEXCEPT RT_OVERRIDE;
+ virtual int toString(RTCString *a_pDst, uint32_t a_fFlags = kCollectionFormat_Unspecified) const RT_NOEXCEPT RT_OVERRIDE;
+ virtual int fromString(RTCString const &a_rValue, const char *a_pszName, PRTERRINFO a_pErrInfo = NULL,
+ uint32_t a_fFlags = kCollectionFormat_Unspecified) RT_NOEXCEPT RT_OVERRIDE;
+ virtual kTypeClass typeClass(void) const RT_NOEXCEPT RT_OVERRIDE;
+ virtual const char *typeName(void) const RT_NOEXCEPT RT_OVERRIDE;
+
+ /** Factory method. */
+ static DECLCALLBACK(RTCRestObjectBase *) createInstance(void) RT_NOEXCEPT;
+ /** @copydoc RTCRestObjectBase::FNDESERIALIZEINSTANCEFROMJSON */
+ static DECLCALLBACK(int) deserializeInstanceFromJson(RTCRestJsonCursor const &a_rCursor, RTCRestObjectBase **a_ppInstance) RT_NOEXCEPT;
+
+protected:
+ /** Pointer to data blob. */
+ uint8_t *m_pbData;
+ /** Amount of valid data in the blob. */
+ size_t m_cbData;
+ /** Number of bytes allocated for the m_pbData buffer. */
+ size_t m_cbAllocated;
+ /** Set if the data is freeable, only ever clear if user data. */
+ bool m_fFreeable;
+ /** Set if the data blob is readonly user provided data. */
+ bool m_fReadOnly;
+
+private:
+ /* No copy constructor or copy assignment: */
+ RTCRestBinary(RTCRestBinary const &a_rThat);
+ RTCRestBinary &operator=(RTCRestBinary const &a_rThat);
+};
+
+
+/**
+ * Abstract base class for REST data model classes.
+ */
+class RT_DECL_CLASS RTCRestDataObject : public RTCRestObjectBase
+{
+public:
+ RTCRestDataObject() RT_NOEXCEPT;
+ RTCRestDataObject(RTCRestDataObject const &a_rThat) RT_NOEXCEPT;
+ virtual ~RTCRestDataObject();
+
+ /* Overridden methods:*/
+ virtual int resetToDefault() RT_NOEXCEPT RT_OVERRIDE;
+ virtual RTCRestOutputBase &serializeAsJson(RTCRestOutputBase &a_rDst) const RT_NOEXCEPT RT_OVERRIDE;
+ virtual int deserializeFromJson(RTCRestJsonCursor const &a_rCursor) RT_NOEXCEPT RT_OVERRIDE;
+ virtual kTypeClass typeClass(void) const RT_NOEXCEPT RT_OVERRIDE;
+
+ /**
+ * Serialize the object members as JSON.
+ *
+ * @returns a_rDst
+ * @param a_rDst The destination for the serialization.
+ */
+ virtual RTCRestOutputBase &serializeMembersAsJson(RTCRestOutputBase &a_rDst) const RT_NOEXCEPT;
+
+ /**
+ * Deserialize object from the given JSON iterator.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_NOT_FOUND if field is unknown. Top level caller will do
+ * invoke unknownField() on it.
+ *
+ * @param a_rCursor The JSON cursor with the current member.
+ * @param a_cchName The length of a_rCursor.m_pszName.
+ */
+ virtual int deserializeMemberFromJson(RTCRestJsonCursor const &a_rCursor, size_t a_cchName) RT_NOEXCEPT;
+
+protected:
+ /** The is-set bits for all the fields. */
+ uint64_t m_fIsSet;
+
+ /** Copy assignment operator. */
+ RTCRestDataObject &operator=(RTCRestDataObject const &a_rThat) RT_NOEXCEPT;
+
+ /** Safe copy assignment method. */
+ virtual int assignCopy(RTCRestDataObject const &a_rThat) RT_NOEXCEPT;
+};
+
+
+/**
+ * Abstract base class for polymorphic REST data model classes.
+ */
+class RT_DECL_CLASS RTCRestPolyDataObject : public RTCRestDataObject
+{
+public:
+ RTCRestPolyDataObject() RT_NOEXCEPT;
+ RTCRestPolyDataObject(RTCRestPolyDataObject const &a_rThat) RT_NOEXCEPT;
+ virtual ~RTCRestPolyDataObject();
+
+ /* Overridden methods:*/
+ virtual int resetToDefault() RT_NOEXCEPT RT_OVERRIDE;
+
+ /** Checks if the instance is of a child class (@c true) or of the parent (@c false). */
+ virtual bool isChild() const RT_NOEXCEPT;
+
+protected:
+
+ /** Copy assignment operator. */
+ RTCRestPolyDataObject &operator=(RTCRestPolyDataObject const &a_rThat) RT_NOEXCEPT;
+};
+
+
+/** @} */
+
+#endif /* !IPRT_INCLUDED_cpp_restbase_h */
+
diff --git a/include/iprt/cpp/restclient.h b/include/iprt/cpp/restclient.h
new file mode 100644
index 00000000..b62a89ea
--- /dev/null
+++ b/include/iprt/cpp/restclient.h
@@ -0,0 +1,826 @@
+/** @file
+ * IPRT - C++ Representational State Transfer (REST) Client Classes.
+ */
+
+/*
+ * Copyright (C) 2008-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_cpp_restclient_h
+#define IPRT_INCLUDED_cpp_restclient_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/http.h>
+#include <iprt/cpp/restbase.h>
+#include <iprt/cpp/reststringmap.h>
+
+
+/** @defgroup grp_rt_cpp_restclient C++ Representational State Transfer (REST) Client Classes.
+ * @ingroup grp_rt_cpp
+ * @{
+ */
+
+/**
+ * Specialization of RTCRestBinary for use with body parameters in a client.
+ *
+ * This enables registering data callbacks for provinding data to upload.
+ */
+class RT_DECL_CLASS RTCRestBinaryParameter : public RTCRestBinary
+{
+public:
+ /** Default constructor. */
+ RTCRestBinaryParameter() RT_NOEXCEPT;
+
+ /** Safe copy assignment method. */
+ virtual int assignCopy(RTCRestBinaryParameter const &a_rThat) RT_NOEXCEPT;
+ /** Safe copy assignment method.
+ * @note Resets callbacks and ASSUMES that @a a_cbData is the content length. */
+ virtual int assignCopy(RTCRestBinary const &a_rThat) RT_NOEXCEPT RT_OVERRIDE;
+ /** Safe copy assignment method.
+ * @note Resets callbacks and ASSUMES that @a a_cbData is the content length. */
+ virtual int assignCopy(void const *a_pvData, size_t a_cbData) RT_NOEXCEPT RT_OVERRIDE;
+
+ /**
+ * Use the specified data buffer directly.
+ * @note Resets callbacks and ASSUMES that @a a_cbData is the content length. */
+ virtual int assignReadOnly(void const *a_pvData, size_t a_cbData) RT_NOEXCEPT RT_OVERRIDE;
+ /**
+ * Use the specified data buffer directly.
+ * @note This will assert and work like assignReadOnly. */
+ virtual int assignWriteable(void *a_pvBuf, size_t a_cbBuf) RT_NOEXCEPT RT_OVERRIDE;
+
+ /** Make a clone of this object. */
+ inline RTCRestBinaryParameter *clone() const RT_NOEXCEPT { return (RTCRestBinaryParameter *)baseClone(); }
+
+ /* Overridden methods: */
+ virtual RTCRestObjectBase *baseClone() const RT_NOEXCEPT RT_OVERRIDE;
+ virtual int resetToDefault() RT_NOEXCEPT RT_OVERRIDE;
+ virtual const char *typeName(void) const RT_NOEXCEPT RT_OVERRIDE;
+
+ /** Factory method. */
+ static DECLCALLBACK(RTCRestObjectBase *) createInstance(void) RT_NOEXCEPT;
+
+ /**
+ * Retrieves the callback data.
+ */
+ inline void *getCallbackData() const RT_NOEXCEPT { return m_pvCallbackData; }
+
+ /**
+ * Sets the content-type for an upload.
+ *
+ * @returns VINF_SUCCESS or VERR_NO_STR_MEMORY.
+ * @param a_pszContentType The content type to set.
+ * If NULL, no content type is set.
+ */
+ int setContentType(const char *a_pszContentType) RT_NOEXCEPT;
+
+ /**
+ * Gets the content type that was set.
+ */
+ inline RTCString const &getContentType() const RT_NOEXCEPT { return m_strContentType; }
+
+ /**
+ * Gets the content-length value (UINT64_MAX if not available).
+ */
+ inline uint64_t getContentLength() const RT_NOEXCEPT { return m_cbContentLength; }
+
+ /**
+ * Callback for producing bytes to upload.
+ *
+ * @returns IPRT status code.
+ * @param a_pThis The related string object.
+ * @param a_pvDst Where to put the bytes.
+ * @param a_cbDst Max number of bytes to produce.
+ * @param a_offContent The byte offset corresponding to the start of @a a_pvDst.
+ * @param a_pcbActual Where to return the number of bytes actually produced.
+ *
+ * @remarks Use getCallbackData to get the user data.
+ *
+ * @note The @a a_offContent parameter does not imply random access or anthing
+ * like that, it is just a convenience provided by the caller. The value
+ * is the sum of the previously returned @a *pcbActual values.
+ */
+ typedef DECLCALLBACKTYPE(int, FNPRODUCER,(RTCRestBinaryParameter *a_pThis, void *a_pvDst, size_t a_cbDst,
+ uint64_t a_offContent, size_t *a_pcbActual)) /*RT_NOEXCEPT*/;
+ /** Pointer to a byte producer callback. */
+ typedef FNPRODUCER *PFNPRODUCER;
+
+ /**
+ * Sets the producer callback.
+ *
+ * @param a_pfnProducer The callback function for producing data.
+ * @param a_pvCallbackData Data the can be retrieved from the callback
+ * using getCallbackData().
+ * @param a_cbContentLength The amount of data that will be uploaded and
+ * to be set as the value of the content-length
+ * header field. Pass UINT64_MAX if not known.
+ *
+ * @note This will drop any buffer previously registered using setUploadData().
+ */
+ void setProducerCallback(PFNPRODUCER a_pfnProducer, void *a_pvCallbackData = NULL, uint64_t a_cbContentLength = UINT64_MAX) RT_NOEXCEPT;
+
+ /**
+ * Preprares transmission via the @a a_hHttp client instance.
+ *
+ * @returns IPRT status code.
+ * @param a_hHttp The HTTP client instance.
+ * @internal
+ */
+ virtual int xmitPrepare(RTHTTP a_hHttp) const RT_NOEXCEPT;
+
+ /**
+ * For completing and/or undoing setup from xmitPrepare.
+ *
+ * @param a_hHttp The HTTP client instance.
+ * @internal
+ */
+ virtual void xmitComplete(RTHTTP a_hHttp) const RT_NOEXCEPT;
+
+protected:
+ /** Number of bytes corresponding to content-length.
+ * UINT64_MAX if not known. Used both for unploads and downloads. */
+ uint64_t m_cbContentLength;
+ /** The content type if set (upload only). */
+ RTCString m_strContentType;
+ /** Pointer to user-registered producer callback function (upload only). */
+ PFNPRODUCER m_pfnProducer;
+ /** User argument for both callbacks (both). */
+ void *m_pvCallbackData;
+
+ /** @copydoc FNRTHTTPUPLOADCALLBACK */
+ static DECLCALLBACK(int) xmitHttpCallback(RTHTTP hHttp, void *pvBuf, size_t cbBuf, uint64_t offContent,
+ size_t *pcbActual, void *pvUser) RT_NOEXCEPT;
+
+private:
+ /* No copy constructor or copy assignment: */
+ RTCRestBinaryParameter(RTCRestBinaryParameter const &a_rThat);
+ RTCRestBinaryParameter &operator=(RTCRestBinaryParameter const &a_rThat);
+};
+
+
+/**
+ * Specialization of RTCRestBinary for use with responses in a client.
+ *
+ * This enables registering data callbacks for consuming downloaded data.
+ */
+class RT_DECL_CLASS RTCRestBinaryResponse : public RTCRestBinary
+{
+public:
+ /** Default constructor. */
+ RTCRestBinaryResponse() RT_NOEXCEPT;
+
+ /** Safe copy assignment method. */
+ virtual int assignCopy(RTCRestBinaryResponse const &a_rThat) RT_NOEXCEPT;
+ /** Safe copy assignment method. */
+ virtual int assignCopy(RTCRestBinary const &a_rThat) RT_NOEXCEPT RT_OVERRIDE;
+ /** Safe copy assignment method.
+ * @note This will assert and fail as it makes no sense for a download. */
+ virtual int assignCopy(void const *a_pvData, size_t a_cbData) RT_NOEXCEPT RT_OVERRIDE;
+
+ /**
+ * Use the specified data buffer directly.
+ * @note This will assert and fail as it makes no sense for a download.
+ */
+ virtual int assignReadOnly(void const *a_pvData, size_t a_cbData) RT_NOEXCEPT RT_OVERRIDE;
+ /**
+ * Use the specified data buffer directly.
+ * @note This will drop any previously registered producer callback and user data.
+ */
+ virtual int assignWriteable(void *a_pvBuf, size_t a_cbBuf) RT_NOEXCEPT RT_OVERRIDE;
+
+ /** Make a clone of this object. */
+ inline RTCRestBinaryResponse *clone() const RT_NOEXCEPT { return (RTCRestBinaryResponse *)baseClone(); }
+
+ /* Overridden methods: */
+ virtual RTCRestObjectBase *baseClone() const RT_NOEXCEPT RT_OVERRIDE;
+ virtual int resetToDefault() RT_NOEXCEPT RT_OVERRIDE;
+ virtual const char *typeName(void) const RT_NOEXCEPT RT_OVERRIDE;
+
+ /** Factory method. */
+ static DECLCALLBACK(RTCRestObjectBase *) createInstance(void) RT_NOEXCEPT;
+
+ /**
+ * Retrieves the callback data.
+ */
+ inline void *getCallbackData() const RT_NOEXCEPT { return m_pvCallbackData; }
+
+ /**
+ * Sets the max size to download to memory.
+ *
+ * This also indicates the intention to download to a memory buffer, so it
+ * will drop any previously registered consumer callback and its user data.
+ *
+ * @param a_cbMaxDownload Maximum number of bytes to download to memory.
+ * If 0, a default is selected (currently 32MiB for
+ * 32-bit hosts and 128MiB for 64-bit).
+ */
+ void setMaxDownloadSize(size_t a_cbMaxDownload) RT_NOEXCEPT;
+
+ /**
+ * Gets the content-length value (UINT64_MAX if not available).
+ */
+ inline uint64_t getContentLength() const RT_NOEXCEPT { return m_cbContentLength; }
+
+ /**
+ * Callback for consuming downloaded bytes.
+ *
+ * @returns IPRT status code.
+ * @param a_pThis The related string object.
+ * @param a_pvSrc Buffer containing the bytes.
+ * @param a_cbSrc The number of bytes in the buffer.
+ * @param a_uHttpStatus The HTTP status code.
+ * @param a_offContent The byte offset corresponding to the start of @a a_pvSrc.
+ * @param a_cbContent The content length field value, UINT64_MAX if not available.
+ *
+ * @remarks Use getCallbackData to get the user data.
+ *
+ * @note The @a a_offContent parameter does not imply random access or anthing
+ * like that, it is just a convenience provided by the caller. The value
+ * is the sum of the previous @a a_cbSrc values.
+ */
+ typedef DECLCALLBACKTYPE(int, FNCONSUMER,(RTCRestBinaryResponse *a_pThis, const void *a_pvSrc, size_t a_cbSrc,
+ uint32_t a_uHttpStatus, uint64_t a_offContent, uint64_t a_cbContent)) /*RT_NOEXCEPT*/;
+ /** Pointer to a byte consumer callback. */
+ typedef FNCONSUMER *PFNCONSUMER;
+
+ /**
+ * Sets the consumer callback.
+ *
+ * @param a_pfnConsumer The callback function for consuming downloaded data.
+ * NULL if data should be stored in m_pbData (the default).
+ * @param a_pvCallbackData Data the can be retrieved from the callback
+ * using getCallbackData().
+ */
+ void setConsumerCallback(PFNCONSUMER a_pfnConsumer, void *a_pvCallbackData = NULL) RT_NOEXCEPT;
+
+ /**
+ * Preprares for receiving via the @a a_hHttp client instance.
+ *
+ * @returns IPRT status code.
+ * @param a_hHttp The HTTP client instance.
+ * @param a_fCallbackFlags The HTTP callback flags (status code spec).
+ * @internal
+ */
+ virtual int receivePrepare(RTHTTP a_hHttp, uint32_t a_fCallbackFlags) RT_NOEXCEPT;
+
+ /**
+ * For completing and/or undoing setup from receivePrepare.
+ *
+ * @param a_hHttp The HTTP client instance.
+ * @internal
+ */
+ virtual void receiveComplete(RTHTTP a_hHttp) RT_NOEXCEPT;
+
+protected:
+ /** Number of bytes corresponding to content-length.
+ * UINT64_MAX if not known. Used both for unploads and downloads. */
+ uint64_t m_cbContentLength;
+ /** Number of bytes downloaded thus far. */
+ uint64_t m_cbDownloaded;
+ /** Pointer to user-registered consumer callback function (download only). */
+ PFNCONSUMER m_pfnConsumer;
+ /** User argument for both callbacks (both). */
+ void *m_pvCallbackData;
+ /** Maximum data to download to memory (download only). */
+ size_t m_cbMaxDownload;
+
+ /** @copydoc FNRTHTTPDOWNLOADCALLBACK */
+ static DECLCALLBACK(int) receiveHttpCallback(RTHTTP hHttp, void const *pvBuf, size_t cbBuf, uint32_t uHttpStatus,
+ uint64_t offContent, uint64_t cbContent, void *pvUser) RT_NOEXCEPT;
+
+private:
+ /* No copy constructor or copy assignment: */
+ RTCRestBinaryResponse(RTCRestBinaryResponse const &a_rThat);
+ RTCRestBinaryResponse &operator=(RTCRestBinaryResponse const &a_rThat);
+};
+
+
+/**
+ * Base class for REST client requests.
+ *
+ * This encapsulates parameters and helps transform them into a HTTP request.
+ *
+ * Parameters can be transfered in a number of places:
+ * - Path part of the URL.
+ * - Query part of the URL.
+ * - HTTP header fields.
+ * - FORM body.
+ * - JSON body.
+ * - XML body.
+ * - ...
+ *
+ * They can be require or optional. The latter may have default values. In
+ * swagger 3 they can also be nullable, which means the null-indicator cannot
+ * be used for tracking optional parameters.
+ */
+class RT_DECL_CLASS RTCRestClientRequestBase
+{
+public:
+ RTCRestClientRequestBase() RT_NOEXCEPT;
+ virtual ~RTCRestClientRequestBase();
+ RTCRestClientRequestBase(RTCRestClientRequestBase const &a_rThat) RT_NOEXCEPT;
+ RTCRestClientRequestBase &operator=(RTCRestClientRequestBase const &a_rThat) RT_NOEXCEPT;
+
+ /**
+ * Reset all members to default values.
+ * @returns IPRT status code.
+ */
+ virtual int resetToDefault() RT_NOEXCEPT = 0;
+
+ /**
+ * Getter for the operation name. Provided by the generated
+ * subclasses so that base class code may use it for more
+ * informative logs.
+ */
+ virtual const char *getOperationName() const RT_NOEXCEPT = 0;
+
+ /**
+ * Prepares the HTTP handle for transmitting this request.
+ *
+ * @returns IPRT status code.
+ * @param a_pStrPath Where to set path parameters. Will be appended to the base path.
+ * @param a_pStrQuery Where to set query parameters.
+ * @param a_hHttp Where to set header parameters and such.
+ * @param a_pStrBody Where to set body parameters.
+ */
+ virtual int xmitPrepare(RTCString *a_pStrPath, RTCString *a_pStrQuery, RTHTTP a_hHttp, RTCString *a_pStrBody) const RT_NOEXCEPT = 0;
+
+ /**
+ * Always called after the request has been transmitted.
+ *
+ * @param a_rcStatus Negative numbers are IPRT errors, positive are HTTP status codes.
+ * @param a_hHttp The HTTP handle the request was performed on.
+ */
+ virtual void xmitComplete(int a_rcStatus, RTHTTP a_hHttp) const RT_NOEXCEPT = 0;
+
+ /**
+ * Checks if there are were any assignment errors.
+ */
+ inline bool hasAssignmentErrors() const RT_NOEXCEPT { return m_fErrorSet != 0; }
+
+protected:
+ /** Set of fields that have been explicitly assigned a value. */
+ uint64_t m_fIsSet;
+ /** Set of fields where value assigning failed. */
+ uint64_t m_fErrorSet;
+
+ /** Path parameter descriptor. */
+ typedef struct
+ {
+ const char *pszName; /**< The name string to replace (including {}). */
+ size_t cchName; /**< Length of pszName. */
+ uint32_t fFlags; /**< The toString flags. */
+ uint8_t iBitNo; /**< The parameter bit number. */
+ } PATHPARAMDESC;
+
+ /** Path parameter state. */
+ typedef struct
+ {
+ RTCRestObjectBase const *pObj; /**< Pointer to the parameter object. */
+ size_t offName; /**< Maintained by worker. */
+ } PATHPARAMSTATE;
+
+ /**
+ * Do path parameters.
+ *
+ * @returns IPRT status code
+ * @param a_pStrPath The destination path.
+ * @param a_pszPathTemplate The path template string.
+ * @param a_cchPathTemplate The length of the path template string.
+ * @param a_paPathParams The path parameter descriptors (static).
+ * @param a_paPathParamStates The path parameter objects and states.
+ * @param a_cPathParams Number of path parameters.
+ */
+ int doPathParameters(RTCString *a_pStrPath, const char *a_pszPathTemplate, size_t a_cchPathTemplate,
+ PATHPARAMDESC const *a_paPathParams, PATHPARAMSTATE *a_paPathParamStates, size_t a_cPathParams) const RT_NOEXCEPT;
+
+ /** Query parameter descriptor. */
+ typedef struct
+ {
+ const char *pszName; /**< The parameter name. */
+ uint32_t fFlags; /**< The toString flags. */
+ bool fRequired; /**< Required or not. */
+ uint8_t iBitNo; /**< The parameter bit number. */
+ } QUERYPARAMDESC;
+
+ /**
+ * Do query parameters.
+ *
+ * @returns IPRT status code
+ * @param a_pStrQuery The destination string.
+ * @param a_paQueryParams The query parameter descriptors.
+ * @param a_papQueryParamObjs The query parameter objects, parallel to @a a_paQueryParams.
+ * @param a_cQueryParams Number of query parameters.
+ */
+ int doQueryParameters(RTCString *a_pStrQuery, QUERYPARAMDESC const *a_paQueryParams,
+ RTCRestObjectBase const **a_papQueryParamObjs, size_t a_cQueryParams) const RT_NOEXCEPT;
+
+ /** Header parameter descriptor. */
+ typedef struct
+ {
+ const char *pszName; /**< The parameter name. */
+ uint32_t fFlags; /**< The toString flags. */
+ bool fRequired; /**< Required or not. */
+ uint8_t iBitNo; /**< The parameter bit number. */
+ bool fMapCollection; /**< Collect headers starting with pszName into a map. */
+ } HEADERPARAMDESC;
+
+ /**
+ * Do header parameters.
+ *
+ * @returns IPRT status code
+ * @param a_hHttp Where to set header parameters.
+ * @param a_paHeaderParams The header parameter descriptors.
+ * @param a_papHeaderParamObjs The header parameter objects, parallel to @a a_paHeaderParams.
+ * @param a_cHeaderParams Number of header parameters.
+ */
+ int doHeaderParameters(RTHTTP a_hHttp, HEADERPARAMDESC const *a_paHeaderParams,
+ RTCRestObjectBase const **a_papHeaderParamObjs, size_t a_cHeaderParams) const RT_NOEXCEPT;
+};
+
+
+/**
+ * Base class for REST client responses.
+ */
+class RT_DECL_CLASS RTCRestClientResponseBase
+{
+public:
+ /** Default constructor. */
+ RTCRestClientResponseBase() RT_NOEXCEPT;
+ /** Destructor. */
+ virtual ~RTCRestClientResponseBase();
+ /** Copy constructor. */
+ RTCRestClientResponseBase(RTCRestClientResponseBase const &a_rThat);
+ /** Copy assignment operator. */
+ RTCRestClientResponseBase &operator=(RTCRestClientResponseBase const &a_rThat);
+
+ /**
+ * Resets the object state.
+ */
+ virtual void reset(void) RT_NOEXCEPT;
+
+ /**
+ * Getter for the operation name. Provided by the generated
+ * subclasses so that base class code may use it for more
+ * informative logs.
+ */
+ virtual const char *getOperationName() const RT_NOEXCEPT = 0;
+
+ /**
+ * Prepares the HTTP handle for receiving the response.
+ *
+ * This may install callbacks and such like.
+ *
+ * When overridden, the parent class must always be called.
+ *
+ * @returns IPRT status code.
+ * @param a_hHttp The HTTP handle to prepare for receiving.
+ */
+ virtual int receivePrepare(RTHTTP a_hHttp) RT_NOEXCEPT;
+
+ /**
+ * Called when the HTTP request has been completely received.
+ *
+ * @param a_rcStatus Negative numbers are IPRT errors, positive are HTTP status codes.
+ * @param a_hHttp The HTTP handle the request was performed on.
+ * This can be NIL_RTHTTP should something fail early, in
+ * which case it is possible receivePrepare() wasn't called.
+ *
+ * @note Called before consumeBody() but after consumeHeader().
+ */
+ virtual void receiveComplete(int a_rcStatus, RTHTTP a_hHttp) RT_NOEXCEPT;
+
+ /**
+ * Callback that consumes HTTP body data from the server.
+ *
+ * @param a_pchData Body data.
+ * @param a_cbData Amount of body data.
+ *
+ * @note Called after consumeHeader().
+ */
+ virtual void consumeBody(const char *a_pchData, size_t a_cbData) RT_NOEXCEPT;
+
+ /**
+ * Called after status, headers and body all have been presented.
+ *
+ * @returns IPRT status code.
+ */
+ virtual void receiveFinal() RT_NOEXCEPT;
+
+ /**
+ * Getter for m_rcStatus.
+ * @returns Negative numbers are IPRT errors, positive are HTTP status codes.
+ */
+ inline int getStatus() const RT_NOEXCEPT { return m_rcStatus; }
+
+ /**
+ * Getter for m_rcHttp.
+ * @returns HTTP status code or VERR_NOT_AVAILABLE.
+ */
+ inline int getHttpStatus() const RT_NOEXCEPT { return m_rcHttp; }
+
+ /**
+ * Getter for m_pErrInfo.
+ */
+ inline PCRTERRINFO getErrInfo(void) const RT_NOEXCEPT { return m_pErrInfo; }
+
+ /**
+ * Getter for m_strContentType.
+ */
+ inline RTCString const &getContentType(void) const RT_NOEXCEPT { return m_strContentType; }
+
+
+protected:
+ /** Negative numbers are IPRT errors, positive are HTTP status codes. */
+ int m_rcStatus;
+ /** The HTTP status code, VERR_NOT_AVAILABLE if not set. */
+ int m_rcHttp;
+ /** Error information. */
+ PRTERRINFO m_pErrInfo;
+ /** The value of the Content-Type header field. */
+ RTCString m_strContentType;
+
+ PRTERRINFO getErrInfoInternal(void) RT_NOEXCEPT;
+ void deleteErrInfo(void) RT_NOEXCEPT;
+ void copyErrInfo(PCRTERRINFO pErrInfo) RT_NOEXCEPT;
+
+ /**
+ * Reports an error (or warning if a_rc non-negative).
+ *
+ * @returns a_rc
+ * @param a_rc The status code to report and return. The first
+ * error status is assigned to m_rcStatus, subsequent
+ * ones as well as informational statuses are not
+ * recorded by m_rcStatus.
+ * @param a_pszFormat The message format string.
+ * @param ... Message arguments.
+ */
+ int addError(int a_rc, const char *a_pszFormat, ...) RT_NOEXCEPT;
+
+ /**
+ * Deserializes a header field value.
+ *
+ * @returns IPRT status code.
+ * @param a_pObj The object to deserialize into.
+ * @param a_pchValue Pointer to the value (not zero terminated).
+ * Not necessarily valid UTF-8!
+ * @param a_cchValue The value length.
+ * @param a_fFlags Flags to pass to fromString().
+ * @param a_pszErrorTag The error tag (field name).
+ */
+ int deserializeHeader(RTCRestObjectBase *a_pObj, const char *a_pchValue, size_t a_cchValue,
+ uint32_t a_fFlags, const char *a_pszErrorTag) RT_NOEXCEPT;
+
+ /**
+ * Deserializes a header field value.
+ *
+ * @returns IPRT status code.
+ * @param a_pMap The string map object to deserialize into.
+ * @param a_pchField Pointer to the map field name. (Caller dropped the prefix.)
+ * Not necessarily valid UTF-8!
+ * @param a_cchField Length of field name.
+ * @param a_pchValue Pointer to the value (not zero terminated).
+ * Not necessarily valid UTF-8!
+ * @param a_cchValue The value length.
+ * @param a_fFlags Flags to pass to fromString().
+ * @param a_pszErrorTag The error tag (field name).
+ */
+ int deserializeHeaderIntoMap(RTCRestStringMapBase *a_pMap, const char *a_pchField, size_t a_cchField,
+ const char *a_pchValue, size_t a_cchValue, uint32_t a_fFlags, const char *a_pszErrorTag) RT_NOEXCEPT;
+
+ /**
+ * Helper that does the deserializing of the response body
+ * via deserializeBodyFromJsonCursor().
+ *
+ * @param a_pchData The body blob.
+ * @param a_cbData The size of the body blob.
+ * @param a_pszBodyName The name of the body parameter.
+ */
+ void deserializeBody(const char *a_pchData, size_t a_cbData, const char *a_pszBodyName) RT_NOEXCEPT;
+
+ /**
+ * Called by deserializeBody to do the actual body deserialization.
+ *
+ * @param a_rCursor The JSON cursor.
+ */
+ virtual void deserializeBodyFromJsonCursor(RTCRestJsonCursor const &a_rCursor) RT_NOEXCEPT;
+
+ /**
+ * Primary json cursor for parsing bodies.
+ */
+ class PrimaryJsonCursorForBody : public RTCRestJsonPrimaryCursor
+ {
+ public:
+ RTCRestClientResponseBase *m_pThat; /**< Pointer to response object. */
+ PrimaryJsonCursorForBody(RTJSONVAL hValue, const char *pszName, RTCRestClientResponseBase *a_pThat) RT_NOEXCEPT;
+ virtual int addError(RTCRestJsonCursor const &a_rCursor, int a_rc, const char *a_pszFormat, ...) RT_NOEXCEPT RT_OVERRIDE;
+ virtual int unknownField(RTCRestJsonCursor const &a_rCursor) RT_NOEXCEPT RT_OVERRIDE;
+ };
+
+
+ /**
+ * Consumes a header.
+ *
+ * Child classes can override this to pick up their header fields, but must
+ * always call the parent class.
+ *
+ * @returns IPRT status code.
+ * @param a_uMatchWord Match word constructed by RTHTTP_MAKE_HDR_MATCH_WORD
+ * @param a_pchField The field name (not zero terminated).
+ * Not necessarily valid UTF-8!
+ * @param a_cchField The length of the field.
+ * @param a_pchValue The field value (not zero terminated).
+ * @param a_cchValue The length of the value.
+ */
+ virtual int consumeHeader(uint32_t a_uMatchWord, const char *a_pchField, size_t a_cchField,
+ const char *a_pchValue, size_t a_cchValue) RT_NOEXCEPT;
+
+private:
+ /** Callback for use with RTHttpSetHeaderCallback. */
+ static DECLCALLBACK(int) receiveHttpHeaderCallback(RTHTTP hHttp, uint32_t uMatchWord, const char *pchField, size_t cchField,
+ const char *pchValue, size_t cchValue, void *pvUser) RT_NOEXCEPT;
+};
+
+
+/**
+ * Base class for REST client responses.
+ */
+class RT_DECL_CLASS RTCRestClientApiBase
+{
+public:
+ RTCRestClientApiBase() RT_NOEXCEPT;
+ virtual ~RTCRestClientApiBase();
+
+ /** @name Host and Base path (URL) handling.
+ * @{ */
+ /**
+ * Gets the server URL.
+ */
+ const char *getServerUrl(void) const RT_NOEXCEPT;
+
+ /**
+ * Sets the whole server URL.
+ * @returns IPRT status code.
+ * @param a_pszUrl The new server URL. NULL/empty to reset to default.
+ */
+ int setServerUrl(const char *a_pszUrl) RT_NOEXCEPT;
+
+ /**
+ * Sets the scheme part of the the server URL.
+ * @returns IPRT status code.
+ * @param a_pszScheme The new scheme. Does not accept NULL or empty string.
+ */
+ int setServerScheme(const char *a_pszScheme) RT_NOEXCEPT;
+
+ /**
+ * Sets the authority (hostname + port) part of the the server URL.
+ * @returns IPRT status code.
+ * @param a_pszAuthority The new authority. Does not accept NULL or empty string.
+ */
+ int setServerAuthority(const char *a_pszAuthority) RT_NOEXCEPT;
+
+ /**
+ * Sets the base path part of the the server URL.
+ * @returns IPRT status code.
+ * @param a_pszBasePath The new base path. Does not accept NULL or empty string.
+ */
+ int setServerBasePath(const char *a_pszBasePath) RT_NOEXCEPT;
+
+ /**
+ * Gets the default server URL as specified in the specs.
+ * @returns Server URL.
+ */
+ virtual const char *getDefaultServerUrl() const RT_NOEXCEPT = 0;
+
+ /**
+ * Gets the default server base path as specified in the specs.
+ * @returns Host string (start of URL).
+ */
+ virtual const char *getDefaultServerBasePath() const RT_NOEXCEPT = 0;
+ /** @} */
+
+ /**
+ * Sets the CA file to use for HTTPS.
+ */
+ int setCAFile(const char *pcszCAFile) RT_NOEXCEPT;
+ /** @overload */
+ int setCAFile(const RTCString &strCAFile) RT_NOEXCEPT;
+
+ /** Flags to doCall. */
+ enum
+ {
+ kDoCall_OciReqSignExcludeBody = 1, /**< Exclude the body when doing OCI request signing. */
+ kDoCall_RequireBody = 2 /**< The body is required. */
+ };
+
+protected:
+ /** Handle to the HTTP connection object. */
+ RTHTTP m_hHttp;
+ /** The server URL to use. If empty use the default. */
+ RTCString m_strServerUrl;
+ /** The CA file to use. If empty use the default. */
+ RTCString m_strCAFile;
+
+ /* Make non-copyable (RTCNonCopyable causes warnings): */
+ RTCRestClientApiBase(RTCRestClientApiBase const &);
+ RTCRestClientApiBase *operator=(RTCRestClientApiBase const &);
+
+ /**
+ * Re-initializes the HTTP instance.
+ *
+ * @returns IPRT status code.
+ */
+ virtual int reinitHttpInstance() RT_NOEXCEPT;
+
+ /**
+ * Hook that's called when doCall has fully assembled the request.
+ *
+ * Can be used for request signing and similar final steps.
+ *
+ * @returns IPRT status code.
+ * @param a_hHttp The HTTP client instance.
+ * @param a_rStrFullUrl The full URL.
+ * @param a_enmHttpMethod The HTTP request method.
+ * @param a_rStrXmitBody The body text.
+ * @param a_fFlags kDoCall_XXX.
+ */
+ virtual int xmitReady(RTHTTP a_hHttp, RTCString const &a_rStrFullUrl, RTHTTPMETHOD a_enmHttpMethod,
+ RTCString const &a_rStrXmitBody, uint32_t a_fFlags) RT_NOEXCEPT;
+
+ /**
+ * Implements stuff for making an API call.
+ *
+ * @returns a_pResponse->getStatus()
+ * @param a_rRequest Reference to the request object.
+ * @param a_enmHttpMethod The HTTP request method.
+ * @param a_pResponse Pointer to the response object.
+ * @param a_pszMethod The method name, for logging purposes.
+ * @param a_fFlags kDoCall_XXX.
+ */
+ virtual int doCall(RTCRestClientRequestBase const &a_rRequest, RTHTTPMETHOD a_enmHttpMethod,
+ RTCRestClientResponseBase *a_pResponse, const char *a_pszMethod, uint32_t a_fFlags) RT_NOEXCEPT;
+
+ /**
+ * Implements OCI style request signing.
+ *
+ * @returns IPRT status code.
+ * @param a_hHttp The HTTP client instance.
+ * @param a_rStrFullUrl The full URL.
+ * @param a_enmHttpMethod The HTTP request method.
+ * @param a_rStrXmitBody The body text.
+ * @param a_fFlags kDoCall_XXX.
+ * @param a_hKey The key to use for signing.
+ * @param a_rStrKeyId The key ID.
+ *
+ * @remarks The signing scheme is covered by a series of drafts RFC, the latest being:
+ * https://tools.ietf.org/html/draft-cavage-http-signatures-10
+ */
+ int ociSignRequest(RTHTTP a_hHttp, RTCString const &a_rStrFullUrl, RTHTTPMETHOD a_enmHttpMethod,
+ RTCString const &a_rStrXmitBody, uint32_t a_fFlags, RTCRKEY a_hKey, RTCString const &a_rStrKeyId) RT_NOEXCEPT;
+
+ /**
+ * Worker for the server URL modifiers.
+ *
+ * @returns IPRT status code.
+ * @param a_pszServerUrl The current server URL (for comparing).
+ * @param a_offDst The offset of the component in the current server URL.
+ * @param a_cchDst The current component length.
+ * @param a_pszSrc The new URL component value.
+ * @param a_cchSrc The length of the new component.
+ */
+ int setServerUrlPart(const char *a_pszServerUrl, size_t a_offDst, size_t a_cchDst, const char *a_pszSrc, size_t a_cchSrc) RT_NOEXCEPT;
+};
+
+/** @} */
+
+#endif /* !IPRT_INCLUDED_cpp_restclient_h */
+
diff --git a/include/iprt/cpp/restoutput.h b/include/iprt/cpp/restoutput.h
new file mode 100644
index 00000000..2f2c57d5
--- /dev/null
+++ b/include/iprt/cpp/restoutput.h
@@ -0,0 +1,280 @@
+/** @file
+ * IPRT - C++ Representational State Transfer (REST) Output Classes.
+ */
+
+/*
+ * Copyright (C) 2008-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_cpp_restoutput_h
+#define IPRT_INCLUDED_cpp_restoutput_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+#include <iprt/stdarg.h>
+#include <iprt/cpp/ministring.h>
+
+
+/** @defgroup grp_rt_cpp_restoutput C++ Representational State Transfer (REST) Output Classes.
+ * @ingroup grp_rt_cpp
+ * @{
+ */
+
+
+/**
+ * Abstract base class for serializing data objects.
+ */
+class RT_DECL_CLASS RTCRestOutputBase
+{
+public:
+ RTCRestOutputBase() RT_NOEXCEPT;
+ virtual ~RTCRestOutputBase();
+
+ /**
+ * Raw output function.
+ *
+ * @returns Number of bytes outputted.
+ * @param a_pchString The string to output (not necessarily terminated).
+ * @param a_cchToWrite The length of the string
+ */
+ virtual size_t output(const char *a_pchString, size_t a_cchToWrite) RT_NOEXCEPT = 0;
+
+ /**
+ * RTStrPrintf like function (see @ref pg_rt_str_format).
+ *
+ * @returns Number of bytes outputted.
+ * @param pszFormat The format string.
+ * @param ... Argument specfied in @a pszFormat.
+ */
+ inline size_t printf(const char *pszFormat, ...) RT_NOEXCEPT RT_IPRT_FORMAT_ATTR(2, 3)
+ {
+ va_list va;
+ va_start(va, pszFormat);
+ size_t cchWritten = this->vprintf(pszFormat, va);
+ va_end(va);
+ return cchWritten;
+ }
+
+ /**
+ * RTStrPrintfV like function (see @ref pg_rt_str_format).
+ *
+ * @returns Number of bytes outputted.
+ * @param pszFormat The format string.
+ * @param va Argument specfied in @a pszFormat.
+ */
+ size_t vprintf(const char *pszFormat, va_list va) RT_NOEXCEPT RT_IPRT_FORMAT_ATTR(2, 0);
+
+ /**
+ * Begins an array.
+ * @returns Previous output state. Pass to endArray() when done.
+ */
+ virtual uint32_t beginArray() RT_NOEXCEPT;
+
+ /**
+ * Ends an array.
+ * @param a_uOldState Previous output state (returned by beginArray()).
+ */
+ virtual void endArray(uint32_t a_uOldState) RT_NOEXCEPT;
+
+ /**
+ * Begins an object.
+ * @returns Previous output state. Pass to endObject() when done.
+ */
+ virtual uint32_t beginObject() RT_NOEXCEPT;
+
+ /**
+ * Ends an array.
+ * @param a_uOldState Previous output state (returned by beginObject()).
+ */
+ virtual void endObject(uint32_t a_uOldState) RT_NOEXCEPT;
+
+ /**
+ * Outputs a value separator.
+ * This is called before a value, not after.
+ */
+ virtual void valueSeparator() RT_NOEXCEPT;
+
+ /**
+ * Outputs a value separator, name and name separator.
+ */
+ virtual void valueSeparatorAndName(const char *a_pszName, size_t a_cchName) RT_NOEXCEPT;
+
+ /** Outputs a null-value. */
+ void nullValue() RT_NOEXCEPT;
+
+protected:
+ /** The current indentation level (bits 15:0) and separator state (bit 31). */
+ uint32_t m_uState;
+
+ /** @callback_method_impl{FNRTSTROUTPUT} */
+ static DECLCALLBACK(size_t) printfOutputCallback(void *pvArg, const char *pachChars, size_t cbChars) RT_NOEXCEPT;
+};
+
+
+/**
+ * Abstract base class for pretty output.
+ */
+class RT_DECL_CLASS RTCRestOutputPrettyBase : public RTCRestOutputBase
+{
+public:
+ RTCRestOutputPrettyBase() RT_NOEXCEPT;
+ virtual ~RTCRestOutputPrettyBase();
+
+ /**
+ * Begins an array.
+ * @returns Previous output state. Pass to endArray() when done.
+ */
+ virtual uint32_t beginArray() RT_NOEXCEPT RT_OVERRIDE;
+
+ /**
+ * Ends an array.
+ * @param a_uOldState Previous output state (returned by beginArray()).
+ */
+ virtual void endArray(uint32_t a_uOldState) RT_NOEXCEPT RT_OVERRIDE;
+
+ /**
+ * Begins an object.
+ * @returns Previous output state. Pass to endObject() when done.
+ */
+ virtual uint32_t beginObject() RT_NOEXCEPT RT_OVERRIDE;
+
+ /**
+ * Ends an array.
+ * @param a_uOldState Previous output state (returned by beginObject()).
+ */
+ virtual void endObject(uint32_t a_uOldState) RT_NOEXCEPT RT_OVERRIDE;
+
+ /**
+ * Outputs a value separator.
+ * This is called before a value, not after.
+ */
+ virtual void valueSeparator() RT_NOEXCEPT RT_OVERRIDE;
+
+ /**
+ * Outputs a value separator, name and name separator.
+ */
+ virtual void valueSeparatorAndName(const char *a_pszName, size_t a_cchName) RT_NOEXCEPT RT_OVERRIDE;
+
+protected:
+ /** Helper for outputting the correct amount of indentation. */
+ void outputIndentation() RT_NOEXCEPT;
+};
+
+
+/**
+ * Serialize to a string object.
+ */
+class RT_DECL_CLASS RTCRestOutputToString : public RTCRestOutputBase
+{
+public:
+ /**
+ * Creates an instance that appends to @a a_pDst.
+ * @param a_pDst Pointer to the destination string object.
+ * NULL is not accepted and will assert.
+ * @param a_fAppend Whether to append to the current string value, or
+ * nuke the string content before starting the output.
+ */
+ RTCRestOutputToString(RTCString *a_pDst, bool a_fAppend = false) RT_NOEXCEPT;
+ virtual ~RTCRestOutputToString();
+
+ virtual size_t output(const char *a_pchString, size_t a_cchToWrite) RT_NOEXCEPT RT_OVERRIDE;
+
+ /**
+ * Finalizes the output and releases the string object to the caller.
+ *
+ * @returns The released string object. NULL if we ran out of memory or if
+ * called already.
+ *
+ * @remark This sets m_pDst to NULL and the object cannot be use for any
+ * more output afterwards.
+ */
+ virtual RTCString *finalize() RT_NOEXCEPT;
+
+protected:
+ /** Pointer to the destination string. NULL after finalize(). */
+ RTCString *m_pDst;
+ /** Set if we ran out of memory and should ignore subsequent calls. */
+ bool m_fOutOfMemory;
+
+ /* Make non-copyable (RTCNonCopyable causes warnings): */
+ RTCRestOutputToString(RTCRestOutputToString const &);
+ RTCRestOutputToString *operator=(RTCRestOutputToString const &);
+};
+
+
+/**
+ * Serialize pretty JSON to a string object.
+ */
+class RT_DECL_CLASS RTCRestOutputPrettyToString : public RTCRestOutputPrettyBase
+{
+public:
+ /**
+ * Creates an instance that appends to @a a_pDst.
+ * @param a_pDst Pointer to the destination string object.
+ * NULL is not accepted and will assert.
+ * @param a_fAppend Whether to append to the current string value, or
+ * nuke the string content before starting the output.
+ */
+ RTCRestOutputPrettyToString(RTCString *a_pDst, bool a_fAppend = false) RT_NOEXCEPT;
+ virtual ~RTCRestOutputPrettyToString();
+
+ virtual size_t output(const char *a_pchString, size_t a_cchToWrite) RT_NOEXCEPT RT_OVERRIDE;
+
+ /**
+ * Finalizes the output and releases the string object to the caller.
+ *
+ * @returns The released string object. NULL if we ran out of memory or if
+ * called already.
+ *
+ * @remark This sets m_pDst to NULL and the object cannot be use for any
+ * more output afterwards.
+ */
+ virtual RTCString *finalize() RT_NOEXCEPT;
+
+protected:
+ /** Pointer to the destination string. NULL after finalize(). */
+ RTCString *m_pDst;
+ /** Set if we ran out of memory and should ignore subsequent calls. */
+ bool m_fOutOfMemory;
+
+ /* Make non-copyable (RTCNonCopyable causes warnings): */
+ RTCRestOutputPrettyToString(RTCRestOutputToString const &);
+ RTCRestOutputPrettyToString *operator=(RTCRestOutputToString const &);
+};
+
+
+
+/** @} */
+
+#endif /* !IPRT_INCLUDED_cpp_restoutput_h */
+
diff --git a/include/iprt/cpp/reststringmap.h b/include/iprt/cpp/reststringmap.h
new file mode 100644
index 00000000..cff201bb
--- /dev/null
+++ b/include/iprt/cpp/reststringmap.h
@@ -0,0 +1,499 @@
+/** @file
+ * IPRT - C++ Representational State Transfer (REST) String Map Template.
+ */
+
+/*
+ * Copyright (C) 2008-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_cpp_reststringmap_h
+#define IPRT_INCLUDED_cpp_reststringmap_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/list.h>
+#include <iprt/string.h>
+#include <iprt/cpp/restbase.h>
+
+
+/** @defgroup grp_rt_cpp_reststingmap C++ Representational State Transfer (REST) String Map Template
+ * @ingroup grp_rt_cpp
+ * @{
+ */
+
+/**
+ * Abstract base class for the RTCRestStringMap template.
+ */
+class RT_DECL_CLASS RTCRestStringMapBase : public RTCRestObjectBase
+{
+public:
+ /** Default destructor. */
+ RTCRestStringMapBase() RT_NOEXCEPT;
+ /** Copy constructor. */
+ RTCRestStringMapBase(RTCRestStringMapBase const &a_rThat);
+ /** Destructor. */
+ virtual ~RTCRestStringMapBase();
+ /** Copy assignment operator. */
+ RTCRestStringMapBase &operator=(RTCRestStringMapBase const &a_rThat);
+
+ /* Overridden methods: */
+ virtual RTCRestObjectBase *baseClone() const RT_NOEXCEPT RT_OVERRIDE;
+ virtual int resetToDefault() RT_NOEXCEPT RT_OVERRIDE;
+ virtual RTCRestOutputBase &serializeAsJson(RTCRestOutputBase &a_rDst) const RT_NOEXCEPT RT_OVERRIDE;
+ virtual int deserializeFromJson(RTCRestJsonCursor const &a_rCursor) RT_NOEXCEPT RT_OVERRIDE;
+ // later?
+ //virtual int toString(RTCString *a_pDst, uint32_t a_fFlags = kCollectionFormat_Unspecified) const RT_NOEXCEPT RT_OVERRIDE;
+ //virtual int fromString(RTCString const &a_rValue, const char *a_pszName, PRTERRINFO a_pErrInfo = NULL,
+ // uint32_t a_fFlags = kCollectionFormat_Unspecified) RT_NOEXCEPT RT_OVERRIDE;
+ virtual kTypeClass typeClass(void) const RT_NOEXCEPT RT_OVERRIDE;
+ virtual const char *typeName(void) const RT_NOEXCEPT RT_OVERRIDE;
+
+ /**
+ * Clear the content of the map.
+ */
+ void clear() RT_NOEXCEPT;
+
+ /**
+ * Checks if the map is empty.
+ */
+ inline bool isEmpty() const RT_NOEXCEPT { return m_cEntries == 0; }
+
+ /**
+ * Gets the number of entries in the map.
+ */
+ size_t size() const RT_NOEXCEPT;
+
+ /**
+ * Checks if the map contains the given key.
+ * @returns true if key found, false if not.
+ * @param a_pszKey The key to check fo.
+ */
+ bool containsKey(const char *a_pszKey) const RT_NOEXCEPT;
+
+ /**
+ * Checks if the map contains the given key.
+ * @returns true if key found, false if not.
+ * @param a_rStrKey The key to check fo.
+ */
+ bool containsKey(RTCString const &a_rStrKey) const RT_NOEXCEPT;
+
+ /**
+ * Remove any key-value pair with the given key.
+ * @returns true if anything was removed, false if not found.
+ * @param a_pszKey The key to remove.
+ */
+ bool remove(const char *a_pszKey) RT_NOEXCEPT;
+
+ /**
+ * Remove any key-value pair with the given key.
+ * @returns true if anything was removed, false if not found.
+ * @param a_rStrKey The key to remove.
+ */
+ bool remove(RTCString const &a_rStrKey) RT_NOEXCEPT;
+
+ /**
+ * Creates a new value and inserts it under the given key, returning the new value.
+ *
+ * @returns VINF_SUCCESS or VWRN_ALREADY_EXISTS on success.
+ * VERR_ALREADY_EXISTS, VERR_NO_MEMORY or VERR_NO_STR_MEMORY on failure.
+ * @param a_ppValue Where to return the pointer to the value.
+ * @param a_pszKey The key to put it under.
+ * @param a_cchKey The length of the key. Default is the entire string.
+ * @param a_fReplace Whether to replace or fail on key collision.
+ */
+ int putNewValue(RTCRestObjectBase **a_ppValue, const char *a_pszKey, size_t a_cchKey = RTSTR_MAX, bool a_fReplace = false) RT_NOEXCEPT;
+
+ /**
+ * Creates a new value and inserts it under the given key, returning the new value.
+ *
+ * @returns VINF_SUCCESS or VWRN_ALREADY_EXISTS on success.
+ * VERR_ALREADY_EXISTS, VERR_NO_MEMORY or VERR_NO_STR_MEMORY on failure.
+ * @param a_ppValue Where to return the pointer to the value.
+ * @param a_rStrKey The key to put it under.
+ * @param a_fReplace Whether to replace or fail on key collision.
+ */
+ int putNewValue(RTCRestObjectBase **a_ppValue, RTCString const &a_rStrKey, bool a_fReplace = false) RT_NOEXCEPT;
+
+protected:
+ /** Map entry. */
+ typedef struct MapEntry
+ {
+ /** String space core. */
+ RTSTRSPACECORE Core;
+ /** List node for enumeration. */
+ RTLISTNODE ListEntry;
+ /** The key.
+ * @remarks Core.pszString points to the value of this object. So, consider it const. */
+ RTCString strKey;
+ /** The value. */
+ RTCRestObjectBase *pValue;
+ } MapEntry;
+ /** The map tree. */
+ RTSTRSPACE m_Map;
+ /** The enumeration list head (MapEntry). */
+ RTLISTANCHOR m_ListHead;
+ /** Number of map entries. */
+ size_t m_cEntries;
+
+public:
+ /** @name Map Iteration
+ * @{ */
+ /** Const iterator. */
+ class ConstIterator
+ {
+ private:
+ MapEntry *m_pCur;
+ ConstIterator() RT_NOEXCEPT;
+ protected:
+ ConstIterator(MapEntry *a_pEntry) RT_NOEXCEPT : m_pCur(a_pEntry) { }
+ public:
+ ConstIterator(ConstIterator const &a_rThat) RT_NOEXCEPT : m_pCur(a_rThat.m_pCur) { }
+
+ /** Gets the key string. */
+ inline RTCString const &getKey() RT_NOEXCEPT { return m_pCur->strKey; }
+ /** Gets poitner to the value object. */
+ inline RTCRestObjectBase const *getValue() RT_NOEXCEPT { return m_pCur->pValue; }
+
+ /** Advance to the next map entry. */
+ inline ConstIterator &operator++() RT_NOEXCEPT
+ {
+ m_pCur = RTListNodeGetNextCpp(&m_pCur->ListEntry, MapEntry, ListEntry);
+ return *this;
+ }
+
+ /** Advance to the previous map entry. */
+ inline ConstIterator &operator--() RT_NOEXCEPT
+ {
+ m_pCur = RTListNodeGetPrevCpp(&m_pCur->ListEntry, MapEntry, ListEntry);
+ return *this;
+ }
+
+ /** Compare equal. */
+ inline bool operator==(ConstIterator const &a_rThat) RT_NOEXCEPT { return m_pCur == a_rThat.m_pCur; }
+ /** Compare not equal. */
+ inline bool operator!=(ConstIterator const &a_rThat) RT_NOEXCEPT { return m_pCur != a_rThat.m_pCur; }
+
+ /* Map class must be friend so it can use the MapEntry constructor. */
+ friend class RTCRestStringMapBase;
+ };
+
+ /** Returns iterator for the first map entry (unless it's empty and it's also the end). */
+ inline ConstIterator begin() const RT_NOEXCEPT
+ {
+ if (!RTListIsEmpty(&m_ListHead))
+ return ConstIterator(RTListNodeGetNextCpp(&m_ListHead, MapEntry, ListEntry));
+ return end();
+ }
+ /** Returns iterator for the last map entry (unless it's empty and it's also the end). */
+ inline ConstIterator last() const RT_NOEXCEPT
+ {
+ if (!RTListIsEmpty(&m_ListHead))
+ return ConstIterator(RTListNodeGetPrevCpp(&m_ListHead, MapEntry, ListEntry));
+ return end();
+ }
+ /** Returns the end iterator. This does not ever refer to an actual map entry. */
+ inline ConstIterator end() const RT_NOEXCEPT
+ {
+ return ConstIterator(RT_FROM_CPP_MEMBER(&m_ListHead, MapEntry, ListEntry));
+ }
+ /** @} */
+
+
+protected:
+ /**
+ * Helper for creating a clone.
+ *
+ * @returns Pointer to new map object on success, NULL if out of memory.
+ */
+ virtual RTCRestStringMapBase *createClone(void) const RT_NOEXCEPT = 0;
+
+ /**
+ * Wrapper around the value constructor.
+ *
+ * @returns Pointer to new value object on success, NULL if out of memory.
+ */
+ virtual RTCRestObjectBase *createValue(void) RT_NOEXCEPT = 0;
+
+ /**
+ * For accessing the static deserializeInstanceFromJson() method of the value.
+ */
+ virtual int deserializeValueInstanceFromJson(RTCRestJsonCursor const &a_rCursor, RTCRestObjectBase **a_ppInstance) RT_NOEXCEPT = 0;
+
+ /**
+ * Worker for the copy assignment method and copyMapWorkerMayThrow.
+ *
+ * This will use createEntryCopy to do the copying.
+ *
+ * @returns VINF_SUCCESS on success, VERR_NO_MEMORY or VERR_NO_STR_MEMORY on failure.
+ * @param a_rThat The map to copy. Caller makes 100% sure the it has
+ * the same type as the destination.
+ */
+ int copyMapWorkerNoThrow(RTCRestStringMapBase const &a_rThat) RT_NOEXCEPT;
+
+ /**
+ * Wrapper around copyMapWorkerNoThrow() that throws allocation errors, making
+ * it suitable for copy constructors and assignment operators.
+ */
+ void copyMapWorkerMayThrow(RTCRestStringMapBase const &a_rThat);
+
+ /**
+ * Worker for performing inserts.
+ *
+ * @returns VINF_SUCCESS or VWRN_ALREADY_EXISTS on success.
+ * VERR_ALREADY_EXISTS, VERR_NO_MEMORY or VERR_NO_STR_MEMORY on failure.
+ * @param a_pszKey The key.
+ * @param a_pValue The value to insert. Ownership is transferred to the map on success.
+ * @param a_fReplace Whether to replace existing key-value pair with matching key.
+ * @param a_cchKey The key length, the whole string by default.
+ */
+ int putWorker(const char *a_pszKey, RTCRestObjectBase *a_pValue, bool a_fReplace, size_t a_cchKey = RTSTR_MAX) RT_NOEXCEPT;
+
+ /**
+ * Worker for performing inserts.
+ *
+ * @returns VINF_SUCCESS or VWRN_ALREADY_EXISTS on success.
+ * VERR_ALREADY_EXISTS, VERR_NO_MEMORY or VERR_NO_STR_MEMORY on failure.
+ * @param a_pszKey The key.
+ * @param a_rValue The value to copy into the map.
+ * @param a_fReplace Whether to replace existing key-value pair with matching key.
+ * @param a_cchKey The key length, the whole string by default.
+ */
+ int putCopyWorker(const char *a_pszKey, RTCRestObjectBase const &a_rValue, bool a_fReplace, size_t a_cchKey = RTSTR_MAX) RT_NOEXCEPT;
+
+ /**
+ * Worker for getting the value corresponding to the given key.
+ *
+ * @returns Pointer to the value object if found, NULL if key not in the map.
+ * @param a_pszKey The key which value to look up.
+ */
+ RTCRestObjectBase *getWorker(const char *a_pszKey) RT_NOEXCEPT;
+
+ /**
+ * Worker for getting the value corresponding to the given key, const variant.
+ *
+ * @returns Pointer to the value object if found, NULL if key not in the map.
+ * @param a_pszKey The key which value to look up.
+ */
+ RTCRestObjectBase const *getWorker(const char *a_pszKey) const RT_NOEXCEPT;
+
+private:
+ static DECLCALLBACK(int) stringSpaceDestructorCallback(PRTSTRSPACECORE pStr, void *pvUser) RT_NOEXCEPT;
+};
+
+
+/**
+ * Limited map class.
+ */
+template<class ValueType> class RTCRestStringMap : public RTCRestStringMapBase
+{
+public:
+ /** Default constructor, creates emtpy map. */
+ RTCRestStringMap() RT_NOEXCEPT
+ : RTCRestStringMapBase()
+ {}
+
+ /** Copy constructor. */
+ RTCRestStringMap(RTCRestStringMap const &a_rThat)
+ : RTCRestStringMapBase()
+ {
+ copyMapWorkerMayThrow(a_rThat);
+ }
+
+ /** Destructor. */
+ virtual ~RTCRestStringMap()
+ {
+ /* nothing to do here. */
+ }
+
+ /** Copy assignment operator. */
+ RTCRestStringMap &operator=(RTCRestStringMap const &a_rThat)
+ {
+ copyMapWorkerMayThrow(a_rThat);
+ return *this;
+ }
+
+ /** Safe copy assignment method. */
+ int assignCopy(RTCRestStringMap const &a_rThat) RT_NOEXCEPT
+ {
+ return copyMapWorkerNoThrow(a_rThat);
+ }
+
+ /** Make a clone of this object. */
+ inline RTCRestStringMap *clone() const RT_NOEXCEPT
+ {
+ return (RTCRestStringMap *)baseClone();
+ }
+
+ /** Factory method. */
+ static DECLCALLBACK(RTCRestObjectBase *) createInstance(void) RT_NOEXCEPT
+ {
+ return new (std::nothrow) RTCRestStringMap<ValueType>();
+ }
+
+ /** Factory method for values. */
+ static DECLCALLBACK(RTCRestObjectBase *) createValueInstance(void) RT_NOEXCEPT
+ {
+ return new (std::nothrow) ValueType();
+ }
+
+ /** @copydoc RTCRestObjectBase::FNDESERIALIZEINSTANCEFROMJSON */
+ static DECLCALLBACK(int) deserializeInstanceFromJson(RTCRestJsonCursor const &a_rCursor, RTCRestObjectBase **a_ppInstance) RT_NOEXCEPT
+ {
+ *a_ppInstance = new (std::nothrow) RTCRestStringMap<ValueType>();
+ if (*a_ppInstance)
+ return (*a_ppInstance)->deserializeFromJson(a_rCursor);
+ return a_rCursor.m_pPrimary->addError(a_rCursor, VERR_NO_MEMORY, "Out of memory");
+ }
+
+ /**
+ * Inserts the given object into the map.
+ *
+ * @returns VINF_SUCCESS or VWRN_ALREADY_EXISTS on success.
+ * VERR_ALREADY_EXISTS, VERR_NO_MEMORY or VERR_NO_STR_MEMORY on failure.
+ * @param a_pszKey The key.
+ * @param a_pValue The value to insert. Ownership is transferred to the map on success.
+ * @param a_fReplace Whether to replace existing key-value pair with matching key.
+ */
+ inline int put(const char *a_pszKey, ValueType *a_pValue, bool a_fReplace = false) RT_NOEXCEPT
+ {
+ return putWorker(a_pszKey, a_pValue, a_fReplace);
+ }
+
+ /**
+ * Inserts the given object into the map.
+ *
+ * @returns VINF_SUCCESS or VWRN_ALREADY_EXISTS on success.
+ * VERR_ALREADY_EXISTS, VERR_NO_MEMORY or VERR_NO_STR_MEMORY on failure.
+ * @param a_rStrKey The key.
+ * @param a_pValue The value to insert. Ownership is transferred to the map on success.
+ * @param a_fReplace Whether to replace existing key-value pair with matching key.
+ */
+ inline int put(RTCString const &a_rStrKey, ValueType *a_pValue, bool a_fReplace = false) RT_NOEXCEPT
+ {
+ return putWorker(a_rStrKey.c_str(), a_pValue, a_fReplace, a_rStrKey.length());
+ }
+
+ /**
+ * Inserts a copy of the given object into the map.
+ *
+ * @returns VINF_SUCCESS or VWRN_ALREADY_EXISTS on success.
+ * VERR_ALREADY_EXISTS, VERR_NO_MEMORY or VERR_NO_STR_MEMORY on failure.
+ * @param a_pszKey The key.
+ * @param a_rValue The value to insert a copy of.
+ * @param a_fReplace Whether to replace existing key-value pair with matching key.
+ */
+ inline int putCopy(const char *a_pszKey, const ValueType &a_rValue, bool a_fReplace = false) RT_NOEXCEPT
+ {
+ return putCopyWorker(a_pszKey, a_rValue, a_fReplace);
+ }
+
+ /**
+ * Inserts a copy of the given object into the map.
+ *
+ * @returns VINF_SUCCESS or VWRN_ALREADY_EXISTS on success.
+ * VERR_ALREADY_EXISTS, VERR_NO_MEMORY or VERR_NO_STR_MEMORY on failure.
+ * @param a_rStrKey The key.
+ * @param a_rValue The value to insert a copy of.
+ * @param a_fReplace Whether to replace existing key-value pair with matching key.
+ */
+ inline int putCopy(RTCString const &a_rStrKey, const ValueType &a_rValue, bool a_fReplace = false) RT_NOEXCEPT
+ {
+ return putCopyWorker(a_rStrKey.c_str(), a_rValue, a_fReplace, a_rStrKey.length());
+ }
+
+ /**
+ * Gets the value corresponding to the given key.
+ *
+ * @returns Pointer to the value object if found, NULL if key not in the map.
+ * @param a_pszKey The key which value to look up.
+ */
+ inline ValueType *get(const char *a_pszKey) RT_NOEXCEPT
+ {
+ return (ValueType *)getWorker(a_pszKey);
+ }
+
+ /**
+ * Gets the value corresponding to the given key.
+ *
+ * @returns Pointer to the value object if found, NULL if key not in the map.
+ * @param a_rStrKey The key which value to look up.
+ */
+ inline ValueType *get(RTCString const &a_rStrKey) RT_NOEXCEPT
+ {
+ return (ValueType *)getWorker(a_rStrKey.c_str());
+ }
+
+ /**
+ * Gets the const value corresponding to the given key.
+ *
+ * @returns Pointer to the value object if found, NULL if key not in the map.
+ * @param a_pszKey The key which value to look up.
+ */
+ inline ValueType const *get(const char *a_pszKey) const RT_NOEXCEPT
+ {
+ return (ValueType const *)getWorker(a_pszKey);
+ }
+
+ /**
+ * Gets the const value corresponding to the given key.
+ *
+ * @returns Pointer to the value object if found, NULL if key not in the map.
+ * @param a_rStrKey The key which value to look up.
+ */
+ inline ValueType const *get(RTCString const &a_rStrKey) const RT_NOEXCEPT
+ {
+ return (ValueType const *)getWorker(a_rStrKey.c_str());
+ }
+
+ /** @todo enumerator*/
+
+protected:
+ virtual RTCRestStringMapBase *createClone(void) const RT_NOEXCEPT RT_OVERRIDE
+ {
+ return new (std::nothrow) RTCRestStringMap();
+ }
+
+ virtual RTCRestObjectBase *createValue(void) RT_NOEXCEPT RT_OVERRIDE
+ {
+ return new (std::nothrow) ValueType();
+ }
+
+ virtual int deserializeValueInstanceFromJson(RTCRestJsonCursor const &a_rCursor, RTCRestObjectBase **a_ppInstance) RT_NOEXCEPT RT_OVERRIDE
+ {
+ return ValueType::deserializeInstanceFromJson(a_rCursor, a_ppInstance);
+ }
+};
+
+
+/** @} */
+
+#endif /* !IPRT_INCLUDED_cpp_reststringmap_h */
+
diff --git a/include/iprt/cpp/utils.h b/include/iprt/cpp/utils.h
new file mode 100644
index 00000000..f5b36fa8
--- /dev/null
+++ b/include/iprt/cpp/utils.h
@@ -0,0 +1,149 @@
+/** @file
+ * IPRT - C++ Utilities (useful templates, defines and such).
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_cpp_utils_h
+#define IPRT_INCLUDED_cpp_utils_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+
+/** @defgroup grp_rt_cpp IPRT C++ APIs */
+
+/** @defgroup grp_rt_cpp_util C++ Utilities
+ * @ingroup grp_rt_cpp
+ * @{
+ */
+
+#define DPTR(CLASS) CLASS##Private *d = static_cast<CLASS##Private *>(d_ptr)
+#define QPTR(CLASS) CLASS *q = static_cast<CLASS *>(q_ptr)
+
+/**
+ * A simple class used to prevent copying and assignment.
+ *
+ * Inherit from this class in order to prevent automatic generation
+ * of the copy constructor and assignment operator in your class.
+ */
+class RTCNonCopyable
+{
+protected:
+ RTCNonCopyable() {}
+ ~RTCNonCopyable() {}
+private:
+ RTCNonCopyable(RTCNonCopyable const &);
+ RTCNonCopyable &operator=(RTCNonCopyable const &);
+};
+
+
+/**
+ * Shortcut to |const_cast<C &>()| that automatically derives the correct
+ * type (class) for the const_cast template's argument from its own argument.
+ *
+ * Can be used to temporarily cancel the |const| modifier on the left-hand side
+ * of assignment expressions, like this:
+ * @code
+ * const Class That;
+ * ...
+ * unconst(That) = SomeValue;
+ * @endcode
+ *
+ * @todo What to do about the prefix here?
+ */
+template <class C>
+inline C &unconst(const C &that)
+{
+ return const_cast<C &>(that);
+}
+
+
+/**
+ * Shortcut to |const_cast<C *>()| that automatically derives the correct
+ * type (class) for the const_cast template's argument from its own argument.
+ *
+ * Can be used to temporarily cancel the |const| modifier on the left-hand side
+ * of assignment expressions, like this:
+ * @code
+ * const Class *pThat;
+ * ...
+ * unconst(pThat) = SomeValue;
+ * @endcode
+ *
+ * @todo What to do about the prefix here?
+ */
+template <class C>
+inline C *unconst(const C *that)
+{
+ return const_cast<C *>(that);
+}
+
+
+/**
+ * Macro for generating a non-const getter version from a const getter.
+ *
+ * @param a_RetType The getter return type.
+ * @param a_Class The class name.
+ * @param a_Getter The getter name.
+ * @param a_ArgDecls The argument declaration for the getter method.
+ * @param a_ArgList The argument list for the call.
+ */
+#define RT_CPP_GETTER_UNCONST(a_RetType, a_Class, a_Getter, a_ArgDecls, a_ArgList) \
+ a_RetType a_Getter a_ArgDecls \
+ { \
+ return static_cast< a_Class const *>(this)-> a_Getter a_ArgList; \
+ }
+
+
+/**
+ * Macro for generating a non-const getter version from a const getter,
+ * unconsting the return value as well.
+ *
+ * @param a_RetType The getter return type.
+ * @param a_Class The class name.
+ * @param a_Getter The getter name.
+ * @param a_ArgDecls The argument declaration for the getter method.
+ * @param a_ArgList The argument list for the call.
+ */
+#define RT_CPP_GETTER_UNCONST_RET(a_RetType, a_Class, a_Getter, a_ArgDecls, a_ArgList) \
+ a_RetType a_Getter a_ArgDecls \
+ { \
+ return const_cast<a_RetType>(static_cast< a_Class const *>(this)-> a_Getter a_ArgList); \
+ }
+
+
+/** @} */
+
+#endif /* !IPRT_INCLUDED_cpp_utils_h */
+
diff --git a/include/iprt/cpp/xml.h b/include/iprt/cpp/xml.h
new file mode 100644
index 00000000..9459f9d3
--- /dev/null
+++ b/include/iprt/cpp/xml.h
@@ -0,0 +1,1247 @@
+/** @file
+ * IPRT - XML Helper APIs.
+ */
+
+/*
+ * Copyright (C) 2007-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_cpp_xml_h
+#define IPRT_INCLUDED_cpp_xml_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#ifndef IN_RING3
+# error "There are no XML APIs available in Ring-0 Context!"
+#endif
+#ifdef IPRT_NO_CRT
+# error "Not available in no-CRT mode because it depends on exceptions, std::list, std::map and stdio.h."
+#endif
+
+#include <iprt/list.h>
+#include <iprt/cpp/exception.h>
+#include <iprt/cpp/utils.h>
+
+#include <list>
+#include <memory>
+
+
+/** @defgroup grp_rt_cpp_xml C++ XML support
+ * @ingroup grp_rt_cpp
+ * @{
+ */
+
+/* Forwards */
+typedef struct _xmlParserInput xmlParserInput;
+typedef xmlParserInput *xmlParserInputPtr;
+typedef struct _xmlParserCtxt xmlParserCtxt;
+typedef xmlParserCtxt *xmlParserCtxtPtr;
+typedef struct _xmlError xmlError;
+typedef xmlError *xmlErrorPtr;
+
+typedef struct _xmlAttr xmlAttr;
+typedef struct _xmlNode xmlNode;
+
+#define RT_XML_CONTENT_SMALL _8K
+#define RT_XML_CONTENT_LARGE _128K
+#define RT_XML_ATTR_TINY 64
+#define RT_XML_ATTR_SMALL _1K
+#define RT_XML_ATTR_MEDIUM _8K
+#define RT_XML_ATTR_LARGE _64K
+
+/** @} */
+
+namespace xml
+{
+
+/**
+ * @addtogroup grp_rt_cpp_xml
+ * @{
+ */
+
+// Exceptions
+//////////////////////////////////////////////////////////////////////////////
+
+class RT_DECL_CLASS LogicError : public RTCError
+{
+public:
+
+ LogicError(const char *aMsg = NULL)
+ : RTCError(aMsg)
+ {}
+
+ LogicError(RT_SRC_POS_DECL);
+};
+
+class RT_DECL_CLASS RuntimeError : public RTCError
+{
+public:
+
+ RuntimeError(const char *aMsg = NULL)
+ : RTCError(aMsg)
+ {}
+};
+
+class RT_DECL_CLASS XmlError : public RuntimeError
+{
+public:
+ XmlError(xmlErrorPtr aErr);
+
+ static char* Format(xmlErrorPtr aErr);
+};
+
+// Logical errors
+//////////////////////////////////////////////////////////////////////////////
+
+class RT_DECL_CLASS ENotImplemented : public LogicError
+{
+public:
+ ENotImplemented(const char *aMsg = NULL) : LogicError(aMsg) {}
+ ENotImplemented(RT_SRC_POS_DECL) : LogicError(RT_SRC_POS_ARGS) {}
+};
+
+class RT_DECL_CLASS EInvalidArg : public LogicError
+{
+public:
+ EInvalidArg(const char *aMsg = NULL) : LogicError(aMsg) {}
+ EInvalidArg(RT_SRC_POS_DECL) : LogicError(RT_SRC_POS_ARGS) {}
+};
+
+class RT_DECL_CLASS EDocumentNotEmpty : public LogicError
+{
+public:
+ EDocumentNotEmpty(const char *aMsg = NULL) : LogicError(aMsg) {}
+ EDocumentNotEmpty(RT_SRC_POS_DECL) : LogicError(RT_SRC_POS_ARGS) {}
+};
+
+class RT_DECL_CLASS ENodeIsNotElement : public LogicError
+{
+public:
+ ENodeIsNotElement(const char *aMsg = NULL) : LogicError(aMsg) {}
+ ENodeIsNotElement(RT_SRC_POS_DECL) : LogicError(RT_SRC_POS_ARGS) {}
+};
+
+// Runtime errors
+//////////////////////////////////////////////////////////////////////////////
+
+class RT_DECL_CLASS EIPRTFailure : public RuntimeError
+{
+public:
+
+ EIPRTFailure(int aRC, const char *pszContextFmt, ...);
+
+ int rc() const
+ {
+ return mRC;
+ }
+
+private:
+ int mRC;
+};
+
+/**
+ * The Stream class is a base class for I/O streams.
+ */
+class RT_DECL_CLASS Stream
+{
+public:
+
+ virtual ~Stream() {}
+
+ virtual const char *uri() const = 0;
+
+ /**
+ * Returns the current read/write position in the stream. The returned
+ * position is a zero-based byte offset from the beginning of the file.
+ *
+ * Throws ENotImplemented if this operation is not implemented for the
+ * given stream.
+ */
+ virtual uint64_t pos() const = 0;
+
+ /**
+ * Sets the current read/write position in the stream.
+ *
+ * @param aPos Zero-based byte offset from the beginning of the stream.
+ *
+ * Throws ENotImplemented if this operation is not implemented for the
+ * given stream.
+ */
+ virtual void setPos (uint64_t aPos) = 0;
+};
+
+/**
+ * The Input class represents an input stream.
+ *
+ * This input stream is used to read the settings tree from.
+ * This is an abstract class that must be subclassed in order to fill it with
+ * useful functionality.
+ */
+class RT_DECL_CLASS Input : virtual public Stream
+{
+public:
+
+ /**
+ * Reads from the stream to the supplied buffer.
+ *
+ * @param aBuf Buffer to store read data to.
+ * @param aLen Buffer length.
+ *
+ * @return Number of bytes read.
+ */
+ virtual int read (char *aBuf, int aLen) = 0;
+};
+
+/**
+ *
+ */
+class RT_DECL_CLASS Output : virtual public Stream
+{
+public:
+
+ /**
+ * Writes to the stream from the supplied buffer.
+ *
+ * @param aBuf Buffer to write data from.
+ * @param aLen Buffer length.
+ *
+ * @return Number of bytes written.
+ */
+ virtual int write (const char *aBuf, int aLen) = 0;
+
+ /**
+ * Truncates the stream from the current position and upto the end.
+ * The new file size will become exactly #pos() bytes.
+ *
+ * Throws ENotImplemented if this operation is not implemented for the
+ * given stream.
+ */
+ virtual void truncate() = 0;
+};
+
+
+//////////////////////////////////////////////////////////////////////////////
+
+/**
+ * The File class is a stream implementation that reads from and writes to
+ * regular files.
+ *
+ * The File class uses IPRT File API for file operations. Note that IPRT File
+ * API is not thread-safe. This means that if you pass the same RTFILE handle to
+ * different File instances that may be simultaneously used on different
+ * threads, you should care about serialization; otherwise you will get garbage
+ * when reading from or writing to such File instances.
+ */
+class RT_DECL_CLASS File : public Input, public Output
+{
+public:
+
+ /**
+ * Possible file access modes.
+ */
+ enum Mode { Mode_Read, Mode_WriteCreate, Mode_Overwrite, Mode_ReadWrite };
+
+ /**
+ * Opens a file with the given name in the given mode. If @a aMode is Read
+ * or ReadWrite, the file must exist. If @a aMode is Write, the file must
+ * not exist. Otherwise, an EIPRTFailure exception will be thrown.
+ *
+ * @param aMode File mode.
+ * @param aFileName File name.
+ * @param aFlushIt Whether to flush a writable file before closing it.
+ */
+ File(Mode aMode, const char *aFileName, bool aFlushIt = false);
+
+ /**
+ * Uses the given file handle to perform file operations. This file
+ * handle must be already open in necessary mode (read, or write, or mixed).
+ *
+ * The read/write position of the given handle will be reset to the
+ * beginning of the file on success.
+ *
+ * Note that the given file handle will not be automatically closed upon
+ * this object destruction.
+ *
+ * @note It you pass the same RTFILE handle to more than one File instance,
+ * please make sure you have provided serialization in case if these
+ * instasnces are to be simultaneously used by different threads.
+ * Otherwise you may get garbage when reading or writing.
+ *
+ * @param aHandle Open file handle.
+ * @param aFileName File name (for reference).
+ * @param aFlushIt Whether to flush a writable file before closing it.
+ */
+ File(RTFILE aHandle, const char *aFileName = NULL, bool aFlushIt = false);
+
+ /**
+ * Destroys the File object. If the object was created from a file name
+ * the corresponding file will be automatically closed. If the object was
+ * created from a file handle, it will remain open.
+ */
+ virtual ~File();
+
+ const char *uri() const;
+
+ uint64_t pos() const;
+ void setPos(uint64_t aPos);
+
+ /**
+ * See Input::read(). If this method is called in wrong file mode,
+ * LogicError will be thrown.
+ */
+ int read(char *aBuf, int aLen);
+
+ /**
+ * See Output::write(). If this method is called in wrong file mode,
+ * LogicError will be thrown.
+ */
+ int write(const char *aBuf, int aLen);
+
+ /**
+ * See Output::truncate(). If this method is called in wrong file mode,
+ * LogicError will be thrown.
+ */
+ void truncate();
+
+private:
+
+ /* Obscure class data */
+ struct Data;
+ Data *m;
+
+ /* auto_ptr data doesn't have proper copy semantics */
+ DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP(File);
+};
+
+/**
+ * The MemoryBuf class represents a stream implementation that reads from the
+ * memory buffer.
+ */
+class RT_DECL_CLASS MemoryBuf : public Input
+{
+public:
+
+ MemoryBuf (const char *aBuf, size_t aLen, const char *aURI = NULL);
+
+ virtual ~MemoryBuf();
+
+ const char *uri() const;
+
+ int read(char *aBuf, int aLen);
+ uint64_t pos() const;
+ void setPos(uint64_t aPos);
+
+private:
+ /* Obscure class data */
+ struct Data;
+ Data *m;
+
+ /* auto_ptr data doesn't have proper copy semantics */
+ DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP(MemoryBuf);
+};
+
+
+/*
+ * GlobalLock
+ *
+ *
+ */
+
+
+typedef DECLCALLBACKTYPE_EX(xmlParserInput *, RT_NOTHING, FNEXTERNALENTITYLOADER,(const char *aURI, const char *aID,
+ xmlParserCtxt *aCtxt));
+typedef FNEXTERNALENTITYLOADER *PFNEXTERNALENTITYLOADER; /**< xmlExternalEntityLoader w/ noexcept. */
+
+class RT_DECL_CLASS GlobalLock
+{
+public:
+ GlobalLock();
+ ~GlobalLock();
+
+ void setExternalEntityLoader(PFNEXTERNALENTITYLOADER pFunc);
+
+ static xmlParserInput* callDefaultLoader(const char *aURI,
+ const char *aID,
+ xmlParserCtxt *aCtxt);
+
+private:
+ /* Obscure class data. */
+ struct Data;
+ struct Data *m;
+};
+
+class ElementNode;
+typedef std::list<const ElementNode*> ElementNodesList;
+
+class AttributeNode;
+
+class ContentNode;
+
+/**
+ * Node base class.
+ *
+ * Cannot be used directly, but ElementNode, ContentNode and AttributeNode
+ * derive from this. This does implement useful public methods though.
+ *
+ *
+ */
+class RT_DECL_CLASS Node
+{
+public:
+ virtual ~Node();
+
+ const char *getName() const;
+ const char *getPrefix() const;
+ const char *getNamespaceURI() const;
+ bool nameEqualsNS(const char *pcszNamespace, const char *pcsz) const;
+ bool nameEquals(const char *pcsz) const
+ {
+ return nameEqualsNS(NULL, pcsz);
+ }
+ bool nameEqualsN(const char *pcsz, size_t cchMax, const char *pcszNamespace = NULL) const;
+
+ const char *getValue() const;
+ const char *getValueN(size_t cchValueLimit) const;
+ bool copyValue(int32_t &i) const;
+ bool copyValue(uint32_t &i) const;
+ bool copyValue(int64_t &i) const;
+ bool copyValue(uint64_t &i) const;
+
+ /** @name Introspection.
+ * @{ */
+ /** Is this an ElementNode instance.
+ * @returns true / false */
+ bool isElement() const
+ {
+ return m_Type == IsElement;
+ }
+
+ /** Is this an ContentNode instance.
+ * @returns true / false */
+ bool isContent() const
+ {
+ return m_Type == IsContent;
+ }
+
+ /** Is this an AttributeNode instance.
+ * @returns true / false */
+ bool isAttribute() const
+ {
+ return m_Type == IsAttribute;
+ }
+
+ int getLineNumber() const;
+ /** @} */
+
+ /** @name General tree enumeration.
+ *
+ * Use the introspection methods isElement() and isContent() before doing static
+ * casting. Parents are always or ElementNode type, but siblings and children
+ * can be of both ContentNode and ElementNode types.
+ *
+ * @remarks Attribute node are in the attributes list, while both content and
+ * element nodes are in the list of children. See ElementNode.
+ *
+ * @remarks Careful mixing tree walking with node removal!
+ * @{
+ */
+ /** Get the parent node
+ * @returns Pointer to the parent node, or NULL if root. */
+ const Node *getParent() const
+ {
+ return m_pParent;
+ }
+
+ /** Get the previous sibling.
+ * @returns Pointer to the previous sibling node, NULL if first child.
+ */
+ const Node *getPrevSibiling() const
+ {
+ if (!m_pParentListAnchor)
+ return NULL;
+ return RTListGetPrevCpp(m_pParentListAnchor, this, const Node, m_listEntry);
+ }
+
+ /** Get the next sibling.
+ * @returns Pointer to the next sibling node, NULL if last child. */
+ const Node *getNextSibiling() const
+ {
+ if (!m_pParentListAnchor)
+ return NULL;
+ return RTListGetNextCpp(m_pParentListAnchor, this, const Node, m_listEntry);
+ }
+ /** @} */
+
+protected:
+ /** Node types. */
+ typedef enum { IsElement, IsAttribute, IsContent } EnumType;
+
+ /** The type of node this is an instance of. */
+ EnumType m_Type;
+ /** The parent node (always an element), NULL if root. */
+ Node *m_pParent;
+
+ xmlNode *m_pLibNode; ///< != NULL if this is an element or content node
+ xmlAttr *m_pLibAttr; ///< != NULL if this is an attribute node
+ const char *m_pcszNamespacePrefix; ///< not always set
+ const char *m_pcszNamespaceHref; ///< full http:// spec
+ const char *m_pcszName; ///< element or attribute name, points either into pLibNode or pLibAttr;
+ ///< NULL if this is a content node
+
+ /** Child list entry of this node. (List head m_pParent->m_children or
+ * m_pParent->m_attribute depending on the type.) */
+ RTLISTNODE m_listEntry;
+ /** Pointer to the parent list anchor.
+ * This allows us to use m_listEntry both for children and attributes. */
+ PRTLISTANCHOR m_pParentListAnchor;
+
+ // hide the default constructor so people use only our factory methods
+ Node(EnumType type,
+ Node *pParent,
+ PRTLISTANCHOR pListAnchor,
+ xmlNode *pLibNode,
+ xmlAttr *pLibAttr);
+ Node(const Node &x); // no copying
+
+ friend class AttributeNode;
+ friend class ElementNode; /* C list hack. */
+};
+
+/**
+ * Node subclass that represents an attribute of an element.
+ *
+ * For attributes, Node::getName() returns the attribute name, and Node::getValue()
+ * returns the attribute value, if any.
+ *
+ * Since the Node constructor is private, one can create new attribute nodes
+ * only through the following factory methods:
+ *
+ * -- ElementNode::setAttribute()
+ */
+class RT_DECL_CLASS AttributeNode : public Node
+{
+public:
+
+protected:
+ // hide the default constructor so people use only our factory methods
+ AttributeNode(const ElementNode *pElmRoot,
+ Node *pParent,
+ PRTLISTANCHOR pListAnchor,
+ xmlAttr *pLibAttr);
+ AttributeNode(const AttributeNode &x); // no copying
+
+ friend class Node;
+ friend class ElementNode;
+};
+
+/**
+ * Node subclass that represents an element.
+ *
+ * For elements, Node::getName() returns the element name, and Node::getValue()
+ * returns the text contents, if any.
+ *
+ * Since the Node constructor is private, one can create element nodes
+ * only through the following factory methods:
+ *
+ * -- Document::createRootElement()
+ * -- ElementNode::createChild()
+ */
+class RT_DECL_CLASS ElementNode : public Node
+{
+public:
+ int getChildElements(ElementNodesList &children, const char *pcszMatch = NULL) const;
+
+ const ElementNode *findChildElementNS(const char *pcszNamespace, const char *pcszMatch) const;
+ const ElementNode *findChildElement(const char *pcszMatch) const
+ {
+ return findChildElementNS(NULL, pcszMatch);
+ }
+ const ElementNode *findChildElementFromId(const char *pcszId) const;
+
+ /** Finds the first decendant matching the name at the end of @a pcszPath and
+ * optionally namespace.
+ *
+ * @returns Pointer to the child string value, NULL if not found or no value.
+ * @param pcszPath Path to the child element. Slashes can be used to
+ * make a simple path to any decendant.
+ * @param pcszNamespace The namespace to match, NULL (default) match any
+ * namespace. When using a path, this matches all
+ * elements along the way.
+ * @see findChildElement, findChildElementP
+ */
+ const ElementNode *findChildElementP(const char *pcszPath, const char *pcszNamespace = NULL) const;
+
+ /** Finds the first child with matching the give name and optionally namspace,
+ * returning its value.
+ *
+ * @returns Pointer to the child string value, NULL if not found or no value.
+ * @param pcszPath Path to the child element. Slashes can be used to
+ * make a simple path to any decendant.
+ * @param pcszNamespace The namespace to match, NULL (default) match any
+ * namespace. When using a path, this matches all
+ * elements along the way.
+ * @see findChildElement, findChildElementP
+ */
+ const char *findChildElementValueP(const char *pcszPath, const char *pcszNamespace = NULL) const
+ {
+ const ElementNode *pElem = findChildElementP(pcszPath, pcszNamespace);
+ if (pElem)
+ return pElem->getValue();
+ return NULL;
+ }
+
+ /** Finds the first child with matching the give name and optionally namspace,
+ * returning its value. Checks the length against the limit.
+ *
+ * @returns Pointer to the child string value, NULL if not found or no value.
+ * @param pcszPath Path to the child element. Slashes can be used to
+ * make a simple path to any decendant.
+ * @param cchValueLimit If the length of the returned value exceeds this
+ * limit a EIPRTFailure exception will be thrown.
+ * @param pcszNamespace The namespace to match, NULL (default) match any
+ * namespace. When using a path, this matches all
+ * elements along the way.
+ * @see findChildElement, findChildElementP
+ */
+ const char *findChildElementValuePN(const char *pcszPath, size_t cchValueLimit, const char *pcszNamespace = NULL) const
+ {
+ const ElementNode *pElem = findChildElementP(pcszPath, pcszNamespace);
+ if (pElem)
+ return pElem->getValueN(cchValueLimit);
+ return NULL;
+ }
+
+ /** Combines findChildElementNS and findAttributeValue.
+ *
+ * @returns Pointer to attribute string value, NULL if either the element or
+ * the attribute was not found.
+ * @param pcszChild The child element name.
+ * @param pcszAttribute The attribute name.
+ * @param pcszChildNamespace The namespace to match @a pcszChild with, NULL
+ * (default) match any namespace.
+ * @param pcszAttributeNamespace The namespace prefix to apply to the
+ * attribute, NULL (default) match any namespace.
+ * @see findChildElementNS and findAttributeValue
+ * @note The findChildElementAttributeValueP() method would do the same thing
+ * given the same inputs, but it would be slightly slower, thus the
+ * separate method.
+ */
+ const char *findChildElementAttributeValue(const char *pcszChild, const char *pcszAttribute,
+ const char *pcszChildNamespace = NULL,
+ const char *pcszAttributeNamespace = NULL) const
+ {
+ const ElementNode *pElem = findChildElementNS(pcszChildNamespace, pcszChild);
+ if (pElem)
+ return pElem->findAttributeValue(pcszAttribute, pcszAttributeNamespace);
+ return NULL;
+ }
+
+ /** Combines findChildElementP and findAttributeValue.
+ *
+ * @returns Pointer to attribute string value, NULL if either the element or
+ * the attribute was not found.
+ * @param pcszPath Path to the child element. Slashes can be used
+ * to make a simple path to any decendant.
+ * @param pcszAttribute The attribute name.
+ * @param pcszPathNamespace The namespace to match @a pcszPath with, NULL
+ * (default) match any namespace. When using a
+ * path, this matches all elements along the way.
+ * @param pcszAttributeNamespace The namespace prefix to apply to the
+ * attribute, NULL (default) match any namespace.
+ * @see findChildElementP and findAttributeValue
+ */
+ const char *findChildElementAttributeValueP(const char *pcszPath, const char *pcszAttribute,
+ const char *pcszPathNamespace = NULL,
+ const char *pcszAttributeNamespace = NULL) const
+ {
+ const ElementNode *pElem = findChildElementP(pcszPath, pcszPathNamespace);
+ if (pElem)
+ return pElem->findAttributeValue(pcszAttribute, pcszAttributeNamespace);
+ return NULL;
+ }
+
+ /** Combines findChildElementP and findAttributeValueN.
+ *
+ * @returns Pointer to attribute string value, NULL if either the element or
+ * the attribute was not found.
+ * @param pcszPath The attribute name. Slashes can be used to make a
+ * simple path to any decendant.
+ * @param pcszAttribute The attribute name.
+ * @param cchValueLimit If the length of the returned value exceeds this
+ * limit a EIPRTFailure exception will be thrown.
+ * @param pcszPathNamespace The namespace to match @a pcszPath with, NULL
+ * (default) match any namespace. When using a
+ * path, this matches all elements along the way.
+ * @param pcszAttributeNamespace The namespace prefix to apply to the
+ * attribute, NULL (default) match any namespace.
+ * @see findChildElementP and findAttributeValue
+ */
+ const char *findChildElementAttributeValuePN(const char *pcszPath, const char *pcszAttribute,
+ size_t cchValueLimit,
+ const char *pcszPathNamespace = NULL,
+ const char *pcszAttributeNamespace = NULL) const
+ {
+ const ElementNode *pElem = findChildElementP(pcszPath, pcszPathNamespace);
+ if (pElem)
+ return pElem->findAttributeValueN(pcszAttribute, cchValueLimit, pcszAttributeNamespace);
+ return NULL;
+ }
+
+
+ /** @name Tree enumeration.
+ * @{ */
+
+ /** Get the next tree element in a full tree enumeration.
+ *
+ * By starting with the root node, this can be used to enumerate the entire tree
+ * (or sub-tree if @a pElmRoot is used).
+ *
+ * @returns Pointer to the next element in the tree, NULL if we're done.
+ * @param pElmRoot The root of the tree we're enumerating. NULL if
+ * it's the entire tree.
+ */
+ ElementNode const *getNextTreeElement(ElementNode const *pElmRoot = NULL) const;
+ RT_CPP_GETTER_UNCONST_RET(ElementNode *, ElementNode, getNextTreeElement, (const ElementNode *pElmRoot = NULL), (pElmRoot))
+
+ /** Get the first child node.
+ * @returns Pointer to the first child node, NULL if no children. */
+ const Node *getFirstChild() const
+ {
+ return RTListGetFirstCpp(&m_children, const Node, m_listEntry);
+ }
+ RT_CPP_GETTER_UNCONST_RET(Node *, ElementNode, getFirstChild,(),())
+
+ /** Get the last child node.
+ * @returns Pointer to the last child node, NULL if no children. */
+ const Node *getLastChild() const
+ {
+ return RTListGetLastCpp(&m_children, const Node, m_listEntry);
+ }
+
+ /** Get the first child node.
+ * @returns Pointer to the first child node, NULL if no children. */
+ const ElementNode *getFirstChildElement() const;
+
+ /** Get the last child node.
+ * @returns Pointer to the last child node, NULL if no children. */
+ const ElementNode *getLastChildElement() const;
+
+ /** Get the previous sibling element.
+ * @returns Pointer to the previous sibling element, NULL if first child
+ * element.
+ * @see getNextSibilingElement, getPrevSibling
+ */
+ const ElementNode *getPrevSibilingElement() const;
+
+ /** Get the next sibling element.
+ * @returns Pointer to the next sibling element, NULL if last child element.
+ * @see getPrevSibilingElement, getNextSibling
+ */
+ const ElementNode *getNextSibilingElement() const;
+
+ /** Find the previous element matching the given name and namespace (optionally).
+ * @returns Pointer to the previous sibling element, NULL if first child
+ * element.
+ * @param pcszName The element name to match.
+ * @param pcszNamespace The namespace name, default is NULL which means
+ * anything goes.
+ * @note Changed the order of the arguments.
+ */
+ const ElementNode *findPrevSibilingElement(const char *pcszName, const char *pcszNamespace = NULL) const;
+
+ /** Find the next element matching the given name and namespace (optionally).
+ * @returns Pointer to the previous sibling element, NULL if first child
+ * element.
+ * @param pcszName The element name to match.
+ * @param pcszNamespace The namespace name, default is NULL which means
+ * anything goes.
+ * @note Changed the order of the arguments.
+ */
+ const ElementNode *findNextSibilingElement(const char *pcszName, const char *pcszNamespace = NULL) const;
+ /** @} */
+
+ /** @name Attribute enumeration
+ * @{ */
+
+ /** Get the first attribute node.
+ * @returns Pointer to the first child node, NULL if no attributes. */
+ const AttributeNode *getFirstAttribute() const
+ {
+ return RTListGetFirstCpp(&m_attributes, const AttributeNode, m_listEntry);
+ }
+
+ /** Get the last attribute node.
+ * @returns Pointer to the last child node, NULL if no attributes. */
+ const AttributeNode *getLastAttribute() const
+ {
+ return RTListGetLastCpp(&m_attributes, const AttributeNode, m_listEntry);
+ }
+
+ /** @} */
+
+ const AttributeNode *findAttribute(const char *pcszMatch, const char *pcszNamespace = NULL) const;
+ /** Find the first attribute with the given name, returning its value string.
+ * @returns Pointer to the attribute string value.
+ * @param pcszName The attribute name.
+ * @param pcszNamespace The namespace name, default is NULL which means
+ * anything goes.
+ * @see getAttributeValue
+ */
+ const char *findAttributeValue(const char *pcszName, const char *pcszNamespace = NULL) const
+ {
+ const AttributeNode *pAttr = findAttribute(pcszName, pcszNamespace);
+ if (pAttr)
+ return pAttr->getValue();
+ return NULL;
+ }
+ /** Find the first attribute with the given name, returning its value string.
+ * @returns Pointer to the attribute string value.
+ * @param pcszName The attribute name.
+ * @param cchValueLimit If the length of the returned value exceeds this
+ * limit a EIPRTFailure exception will be thrown.
+ * @param pcszNamespace The namespace name, default is NULL which means
+ * anything goes.
+ * @see getAttributeValue
+ */
+ const char *findAttributeValueN(const char *pcszName, size_t cchValueLimit, const char *pcszNamespace = NULL) const
+ {
+ const AttributeNode *pAttr = findAttribute(pcszName, pcszNamespace);
+ if (pAttr)
+ return pAttr->getValueN(cchValueLimit);
+ return NULL;
+ }
+
+ bool getAttributeValue(const char *pcszMatch, const char *&pcsz, const char *pcszNamespace = NULL) const
+ { return getAttributeValue(pcszMatch, &pcsz, pcszNamespace); }
+ bool getAttributeValue(const char *pcszMatch, RTCString &str, const char *pcszNamespace = NULL) const
+ { return getAttributeValue(pcszMatch, &str, pcszNamespace); }
+ bool getAttributeValuePath(const char *pcszMatch, RTCString &str, const char *pcszNamespace = NULL) const
+ { return getAttributeValue(pcszMatch, &str, pcszNamespace); }
+ bool getAttributeValue(const char *pcszMatch, int32_t &i, const char *pcszNamespace = NULL) const
+ { return getAttributeValue(pcszMatch, &i, pcszNamespace); }
+ bool getAttributeValue(const char *pcszMatch, uint32_t &i, const char *pcszNamespace = NULL) const
+ { return getAttributeValue(pcszMatch, &i, pcszNamespace); }
+ bool getAttributeValue(const char *pcszMatch, int64_t &i, const char *pcszNamespace = NULL) const
+ { return getAttributeValue(pcszMatch, &i, pcszNamespace); }
+ bool getAttributeValue(const char *pcszMatch, uint64_t &u, const char *pcszNamespace = NULL) const
+ { return getAttributeValue(pcszMatch, &u, pcszNamespace); }
+ bool getAttributeValue(const char *pcszMatch, bool &f, const char *pcszNamespace = NULL) const
+ { return getAttributeValue(pcszMatch, &f, pcszNamespace); }
+ bool getAttributeValueN(const char *pcszMatch, const char *&pcsz, size_t cchValueLimit, const char *pcszNamespace = NULL) const
+ { return getAttributeValueN(pcszMatch, &pcsz, cchValueLimit, pcszNamespace); }
+ bool getAttributeValueN(const char *pcszMatch, RTCString &str, size_t cchValueLimit, const char *pcszNamespace = NULL) const
+ { return getAttributeValueN(pcszMatch, &str, cchValueLimit, pcszNamespace); }
+ bool getAttributeValuePathN(const char *pcszMatch, RTCString &str, size_t cchValueLimit, const char *pcszNamespace = NULL) const
+ { return getAttributeValueN(pcszMatch, &str, cchValueLimit, pcszNamespace); }
+
+ /** @name Variants that for clarity does not use references for output params.
+ * @{ */
+ bool getAttributeValue(const char *pcszMatch, const char **ppcsz, const char *pcszNamespace = NULL) const;
+ bool getAttributeValue(const char *pcszMatch, RTCString *pStr, const char *pcszNamespace = NULL) const;
+ bool getAttributeValuePath(const char *pcszMatch, RTCString *pStr, const char *pcszNamespace = NULL) const;
+ bool getAttributeValue(const char *pcszMatch, int32_t *pi, const char *pcszNamespace = NULL) const;
+ bool getAttributeValue(const char *pcszMatch, uint32_t *pu, const char *pcszNamespace = NULL) const;
+ bool getAttributeValue(const char *pcszMatch, int64_t *piValue, const char *pcszNamespace = NULL) const;
+ bool getAttributeValue(const char *pcszMatch, uint64_t *pu, const char *pcszNamespace = NULL) const;
+ bool getAttributeValue(const char *pcszMatch, bool *pf, const char *pcszNamespace = NULL) const;
+ bool getAttributeValueN(const char *pcszMatch, const char **ppcsz, size_t cchValueLimit, const char *pcszNamespace = NULL) const;
+ bool getAttributeValueN(const char *pcszMatch, RTCString *pStr, size_t cchValueLimit, const char *pcszNamespace = NULL) const;
+ bool getAttributeValuePathN(const char *pcszMatch, RTCString *pStr, size_t cchValueLimit, const char *pcszNamespace = NULL) const;
+ /** @} */
+
+ /** @name Convenience methods for convering the element value.
+ * @{ */
+ bool getElementValue(int32_t *piValue) const;
+ bool getElementValue(uint32_t *puValue) const;
+ bool getElementValue(int64_t *piValue) const;
+ bool getElementValue(uint64_t *puValue) const;
+ bool getElementValue(bool *pfValue) const;
+ /** @} */
+
+ /** @name Convenience findChildElementValueP and getElementValue.
+ * @{ */
+ bool getChildElementValueP(const char *pcszPath, int32_t *piValue, const char *pcszNamespace = NULL) const
+ {
+ const ElementNode *pElem = findChildElementP(pcszPath, pcszNamespace);
+ return pElem && pElem->getElementValue(piValue);
+ }
+ bool getChildElementValueP(const char *pcszPath, uint32_t *puValue, const char *pcszNamespace = NULL) const
+ {
+ const ElementNode *pElem = findChildElementP(pcszPath, pcszNamespace);
+ return pElem && pElem->getElementValue(puValue);
+ }
+ bool getChildElementValueP(const char *pcszPath, int64_t *piValue, const char *pcszNamespace = NULL) const
+ {
+ const ElementNode *pElem = findChildElementP(pcszPath, pcszNamespace);
+ return pElem && pElem->getElementValue(piValue);
+ }
+ bool getChildElementValueP(const char *pcszPath, uint64_t *puValue, const char *pcszNamespace = NULL) const
+ {
+ const ElementNode *pElem = findChildElementP(pcszPath, pcszNamespace);
+ return pElem && pElem->getElementValue(puValue);
+ }
+ bool getChildElementValueP(const char *pcszPath, bool *pfValue, const char *pcszNamespace = NULL) const
+ {
+ const ElementNode *pElem = findChildElementP(pcszPath, pcszNamespace);
+ return pElem && pElem->getElementValue(pfValue);
+ }
+
+ /** @} */
+
+ /** @name Convenience findChildElementValueP and getElementValue with a
+ * default value being return if the child element isn't present.
+ *
+ * @remarks These will return false on conversion errors.
+ * @{ */
+ bool getChildElementValueDefP(const char *pcszPath, int32_t iDefault, int32_t *piValue, const char *pcszNamespace = NULL) const
+ {
+ const ElementNode *pElem = findChildElementP(pcszPath, pcszNamespace);
+ if (pElem)
+ return pElem->getElementValue(piValue);
+ *piValue = iDefault;
+ return true;
+ }
+ bool getChildElementValueDefP(const char *pcszPath, uint32_t uDefault, uint32_t *puValue, const char *pcszNamespace = NULL) const
+ {
+ const ElementNode *pElem = findChildElementP(pcszPath, pcszNamespace);
+ if (pElem)
+ return pElem->getElementValue(puValue);
+ *puValue = uDefault;
+ return true;
+ }
+ bool getChildElementValueDefP(const char *pcszPath, int64_t iDefault, int64_t *piValue, const char *pcszNamespace = NULL) const
+ {
+ const ElementNode *pElem = findChildElementP(pcszPath, pcszNamespace);
+ if (pElem)
+ return pElem->getElementValue(piValue);
+ *piValue = iDefault;
+ return true;
+ }
+ bool getChildElementValueDefP(const char *pcszPath, uint64_t uDefault, uint64_t *puValue, const char *pcszNamespace = NULL) const
+ {
+ const ElementNode *pElem = findChildElementP(pcszPath, pcszNamespace);
+ if (pElem)
+ return pElem->getElementValue(puValue);
+ *puValue = uDefault;
+ return true;
+ }
+ bool getChildElementValueDefP(const char *pcszPath, bool fDefault, bool *pfValue, const char *pcszNamespace = NULL) const
+ {
+ const ElementNode *pElem = findChildElementP(pcszPath, pcszNamespace);
+ if (pElem)
+ return pElem->getElementValue(pfValue);
+ *pfValue = fDefault;
+ return true;
+ }
+ /** @} */
+
+ ElementNode *createChild(const char *pcszElementName);
+
+ ContentNode *addContent(const char *pcszContent);
+ ContentNode *addContent(const RTCString &strContent)
+ {
+ return addContent(strContent.c_str());
+ }
+
+ ContentNode *setContent(const char *pcszContent);
+ ContentNode *setContent(const RTCString &strContent)
+ {
+ return setContent(strContent.c_str());
+ }
+
+ AttributeNode *setAttribute(const char *pcszName, const char *pcszValue);
+ AttributeNode *setAttribute(const char *pcszName, const RTCString &strValue)
+ {
+ return setAttribute(pcszName, strValue.c_str());
+ }
+ AttributeNode *setAttributePath(const char *pcszName, const RTCString &strValue);
+ AttributeNode *setAttribute(const char *pcszName, int32_t i);
+ AttributeNode *setAttribute(const char *pcszName, uint32_t i);
+ AttributeNode *setAttribute(const char *pcszName, int64_t i);
+ AttributeNode *setAttribute(const char *pcszName, uint64_t i);
+ AttributeNode *setAttributeHex(const char *pcszName, uint32_t i);
+ AttributeNode *setAttribute(const char *pcszName, bool f);
+
+ virtual ~ElementNode();
+
+protected:
+ // hide the default constructor so people use only our factory methods
+ ElementNode(const ElementNode *pElmRoot, Node *pParent, PRTLISTANCHOR pListAnchor, xmlNode *pLibNode);
+ ElementNode(const ElementNode &x); // no copying
+
+ /** We keep a pointer to the root element for attribute namespace handling. */
+ const ElementNode *m_pElmRoot;
+
+ /** List of child elements and content nodes. */
+ RTLISTANCHOR m_children;
+ /** List of attributes nodes. */
+ RTLISTANCHOR m_attributes;
+
+ static void buildChildren(ElementNode *pElmRoot);
+
+ friend class Node;
+ friend class Document;
+ friend class XmlFileParser;
+};
+
+/**
+ * Node subclass that represents content (non-element text).
+ *
+ * Since the Node constructor is private, one can create new content nodes
+ * only through the following factory methods:
+ *
+ * -- ElementNode::addContent()
+ */
+class RT_DECL_CLASS ContentNode : public Node
+{
+public:
+
+protected:
+ // hide the default constructor so people use only our factory methods
+ ContentNode(Node *pParent, PRTLISTANCHOR pListAnchor, xmlNode *pLibNode);
+ ContentNode(const ContentNode &x); // no copying
+
+ friend class Node;
+ friend class ElementNode;
+};
+
+
+/**
+ * Handy helper class with which one can loop through all or some children
+ * of a particular element. See NodesLoop::forAllNodes() for details.
+ */
+class RT_DECL_CLASS NodesLoop
+{
+public:
+ NodesLoop(const ElementNode &node, const char *pcszMatch = NULL);
+ ~NodesLoop();
+ const ElementNode* forAllNodes() const;
+
+private:
+ /* Obscure class data */
+ struct Data;
+ Data *m;
+};
+
+/**
+ * The XML document class. An instance of this needs to be created by a user
+ * of the XML classes and then passed to
+ *
+ * -- XmlMemParser or XmlFileParser to read an XML document; those classes then
+ * fill the caller's Document with ElementNode, ContentNode and AttributeNode
+ * instances. The typical sequence then is:
+ * @code
+ Document doc;
+ XmlFileParser parser;
+ parser.read("file.xml", doc);
+ Element *pElmRoot = doc.getRootElement();
+ @endcode
+ *
+ * -- XmlMemWriter or XmlFileWriter to write out an XML document after it has
+ * been created and filled. Example:
+ *
+ * @code
+ Document doc;
+ Element *pElmRoot = doc.createRootElement();
+ // add children
+ xml::XmlFileWriter writer(doc);
+ writer.write("file.xml", true);
+ @endcode
+ */
+class RT_DECL_CLASS Document
+{
+public:
+ Document();
+ ~Document();
+
+ Document(const Document &x);
+ Document& operator=(const Document &x);
+
+ const ElementNode* getRootElement() const;
+ ElementNode* getRootElement();
+
+ ElementNode* createRootElement(const char *pcszRootElementName,
+ const char *pcszComment = NULL);
+
+private:
+ friend class XmlMemParser;
+ friend class XmlFileParser;
+ friend class XmlMemWriter;
+ friend class XmlStringWriter;
+ friend class XmlFileWriter;
+
+ void refreshInternals();
+
+ /* Obscure class data */
+ struct Data;
+ Data *m;
+};
+
+/*
+ * XmlParserBase
+ *
+ */
+
+class RT_DECL_CLASS XmlParserBase
+{
+protected:
+ XmlParserBase();
+ ~XmlParserBase();
+
+ xmlParserCtxtPtr m_ctxt;
+};
+
+/*
+ * XmlMemParser
+ *
+ */
+
+class RT_DECL_CLASS XmlMemParser : public XmlParserBase
+{
+public:
+ XmlMemParser();
+ ~XmlMemParser();
+
+ void read(const void* pvBuf, size_t cbSize, const RTCString &strFilename, Document &doc);
+};
+
+/*
+ * XmlFileParser
+ *
+ */
+
+class RT_DECL_CLASS XmlFileParser : public XmlParserBase
+{
+public:
+ XmlFileParser();
+ ~XmlFileParser();
+
+ void read(const RTCString &strFilename, Document &doc);
+
+private:
+ /* Obscure class data */
+ struct Data;
+ struct Data *m;
+
+ static int ReadCallback(void *aCtxt, char *aBuf, int aLen) RT_NOTHROW_PROTO;
+ static int CloseCallback(void *aCtxt) RT_NOTHROW_PROTO;
+};
+
+/**
+ * XmlMemWriter
+ */
+class RT_DECL_CLASS XmlMemWriter
+{
+public:
+ XmlMemWriter();
+ ~XmlMemWriter();
+
+ void write(const Document &doc, void** ppvBuf, size_t *pcbSize);
+
+private:
+ void* m_pBuf;
+};
+
+
+/**
+ * XmlStringWriter - writes the XML to an RTCString instance.
+ */
+class RT_DECL_CLASS XmlStringWriter
+{
+public:
+ XmlStringWriter();
+
+ int write(const Document &rDoc, RTCString *pStrDst);
+
+private:
+ static int WriteCallbackForSize(void *pvUser, const char *pachBuf, int cbToWrite) RT_NOTHROW_PROTO;
+ static int WriteCallbackForReal(void *pvUser, const char *pachBuf, int cbToWrite) RT_NOTHROW_PROTO;
+ static int CloseCallback(void *pvUser) RT_NOTHROW_PROTO;
+
+ /** Pointer to the destination string while we're in the write() call. */
+ RTCString *m_pStrDst;
+ /** Set by WriteCallback if we cannot grow the destination string. */
+ bool m_fOutOfMemory;
+};
+
+
+/**
+ * XmlFileWriter
+ */
+class RT_DECL_CLASS XmlFileWriter
+{
+public:
+ XmlFileWriter(Document &doc);
+ ~XmlFileWriter();
+
+ /**
+ * Writes the XML document to the specified file.
+ *
+ * @param pcszFilename The name of the output file.
+ * @param fSafe If @c true, some extra safety precautions will be
+ * taken when writing the file:
+ * -# The file is written with a '-tmp' suffix.
+ * -# It is flushed to disk after writing.
+ * -# Any original file is renamed to '-prev'.
+ * -# The '-tmp' file is then renamed to the
+ * specified name.
+ * -# The directory changes are flushed to disk.
+ * The suffixes are available via s_pszTmpSuff and
+ * s_pszPrevSuff.
+ */
+ void write(const char *pcszFilename, bool fSafe);
+
+ static int WriteCallback(void *aCtxt, const char *aBuf, int aLen) RT_NOTHROW_PROTO;
+ static int CloseCallback(void *aCtxt) RT_NOTHROW_PROTO;
+
+ /** The suffix used by XmlFileWriter::write() for the temporary file. */
+ static const char * const s_pszTmpSuff;
+ /** The suffix used by XmlFileWriter::write() for the previous (backup) file. */
+ static const char * const s_pszPrevSuff;
+
+private:
+ void writeInternal(const char *pcszFilename, bool fSafe);
+
+ /* Obscure class data */
+ struct Data;
+ Data *m;
+};
+
+#if defined(_MSC_VER)
+#pragma warning (default:4251)
+#endif
+
+/** @} */
+
+} // end namespace xml
+
+#endif /* !IPRT_INCLUDED_cpp_xml_h */
+
diff --git a/include/iprt/cpuset.h b/include/iprt/cpuset.h
new file mode 100644
index 00000000..c5882472
--- /dev/null
+++ b/include/iprt/cpuset.h
@@ -0,0 +1,353 @@
+/** @file
+ * IPRT - CPU Set.
+ */
+
+/*
+ * Copyright (C) 2008-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_cpuset_h
+#define IPRT_INCLUDED_cpuset_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#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 + (int)iBit;
+ }
+ }
+ return 0;
+}
+
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_cpuset_h */
+
diff --git a/include/iprt/crc.h b/include/iprt/crc.h
new file mode 100644
index 00000000..60706493
--- /dev/null
+++ b/include/iprt/crc.h
@@ -0,0 +1,250 @@
+/** @file
+ * IPRT - CRCs and Checksums.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_crc_h
+#define IPRT_INCLUDED_crc_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_crc RTCrc - Checksums and CRCs.
+ * @ingroup grp_rt
+ * @{
+ */
+
+
+/** @defgroup grp_rt_crc32 CRC-32
+ * @{ */
+/**
+ * Calculate CRC-32 for a memory block.
+ *
+ * @returns CRC-32 for the memory block.
+ * @param pv Pointer to the memory block.
+ * @param cb Size of the memory block in bytes.
+ */
+RTDECL(uint32_t) RTCrc32(const void *pv, size_t cb);
+
+/**
+ * Start a multiblock CRC-32 calculation.
+ *
+ * @returns Start CRC-32.
+ */
+RTDECL(uint32_t) RTCrc32Start(void);
+
+/**
+ * Processes a multiblock of a CRC-32 calculation.
+ *
+ * @returns Intermediate CRC-32 value.
+ * @param uCRC32 Current CRC-32 intermediate value.
+ * @param pv The data block to process.
+ * @param cb The size of the data block in bytes.
+ */
+RTDECL(uint32_t) RTCrc32Process(uint32_t uCRC32, const void *pv, size_t cb);
+
+/**
+ * Complete a multiblock CRC-32 calculation.
+ *
+ * @returns CRC-32 value.
+ * @param uCRC32 Current CRC-32 intermediate value.
+ */
+RTDECL(uint32_t) RTCrc32Finish(uint32_t uCRC32);
+/** @} */
+
+
+/** @defgroup grp_rt_crc64 CRC-64 Calculation
+ * @{ */
+/**
+ * Calculate CRC-64 for a memory block.
+ *
+ * @returns CRC-64 for the memory block.
+ * @param pv Pointer to the memory block.
+ * @param cb Size of the memory block in bytes.
+ */
+RTDECL(uint64_t) RTCrc64(const void *pv, size_t cb);
+
+/**
+ * Start a multiblock CRC-64 calculation.
+ *
+ * @returns Start CRC-64.
+ */
+RTDECL(uint64_t) RTCrc64Start(void);
+
+/**
+ * Processes a multiblock of a CRC-64 calculation.
+ *
+ * @returns Intermediate CRC-64 value.
+ * @param uCRC64 Current CRC-64 intermediate value.
+ * @param pv The data block to process.
+ * @param cb The size of the data block in bytes.
+ */
+RTDECL(uint64_t) RTCrc64Process(uint64_t uCRC64, const void *pv, size_t cb);
+
+/**
+ * Complete a multiblock CRC-64 calculation.
+ *
+ * @returns CRC-64 value.
+ * @param uCRC64 Current CRC-64 intermediate value.
+ */
+RTDECL(uint64_t) RTCrc64Finish(uint64_t uCRC64);
+/** @} */
+
+
+/** @defgroup grp_rt_crc_adler32 Adler-32
+ * @{ */
+/**
+ * Calculate Adler-32 for a memory block.
+ *
+ * @returns Adler-32 for the memory block.
+ * @param pv Pointer to the memory block.
+ * @param cb Size of the memory block in bytes.
+ */
+RTDECL(uint32_t) RTCrcAdler32(void const *pv, size_t cb);
+
+/**
+ * Start a multiblock Adler-32 calculation.
+ *
+ * @returns Start Adler-32.
+ */
+RTDECL(uint32_t) RTCrcAdler32Start(void);
+
+/**
+ * Processes a multiblock of a Adler-32 calculation.
+ *
+ * @returns Intermediate Adler-32 value.
+ * @param uCrc Current Adler-32 intermediate value.
+ * @param pv The data block to process.
+ * @param cb The size of the data block in bytes.
+ */
+RTDECL(uint32_t) RTCrcAdler32Process(uint32_t uCrc, void const *pv, size_t cb);
+
+/**
+ * Complete a multiblock Adler-32 calculation.
+ *
+ * @returns Adler-32 value.
+ * @param uCrc Current Adler-32 intermediate value.
+ */
+RTDECL(uint32_t) RTCrcAdler32Finish(uint32_t uCrc);
+
+/** @} */
+
+
+/** @defgroup grp_rt_crc32c CRC-32C
+ * @{ */
+/**
+ * Calculate CRC-32C for a memory block.
+ *
+ * @returns CRC-32C for the memory block.
+ * @param pv Pointer to the memory block.
+ * @param cb Size of the memory block in bytes.
+ */
+RTDECL(uint32_t) RTCrc32C(const void *pv, size_t cb);
+
+/**
+ * Start a multiblock CRC-32 calculation.
+ *
+ * @returns Start CRC-32.
+ */
+RTDECL(uint32_t) RTCrc32CStart(void);
+
+/**
+ * Processes a multiblock of a CRC-32C calculation.
+ *
+ * @returns Intermediate CRC-32C value.
+ * @param uCRC32C Current CRC-32C intermediate value.
+ * @param pv The data block to process.
+ * @param cb The size of the data block in bytes.
+ */
+RTDECL(uint32_t) RTCrc32CProcess(uint32_t uCRC32C, const void *pv, size_t cb);
+
+/**
+ * Complete a multiblock CRC-32 calculation.
+ *
+ * @returns CRC-32 value.
+ * @param uCRC32 Current CRC-32 intermediate value.
+ */
+RTDECL(uint32_t) RTCrc32CFinish(uint32_t uCRC32);
+
+/** @} */
+
+
+/** @defgroup grp_rt_crc16ccitt CRC-16-CCITT
+ * @{ */
+/**
+ * Calculate CRC-16-CCITT for a memory block.
+ *
+ * @returns CRC-16-CCITT for the memory block.
+ * @param pv Pointer to the memory block.
+ * @param cb Size of the memory block in bytes.
+ */
+RTDECL(uint16_t) RTCrc16Ccitt(const void *pv, size_t cb);
+
+/**
+ * Start a multiblock CRC-16-CCITT calculation.
+ *
+ * @returns Start CRC-16-CCITT.
+ */
+RTDECL(uint16_t) RTCrc16CcittStart(void);
+
+/**
+ * Processes a multiblock of a CRC-16-CCITT calculation.
+ *
+ * @returns Intermediate CRC-16-CCITT value.
+ * @param uCrc Current CRC-16-CCITT intermediate value.
+ * @param pv The data block to process.
+ * @param cb The size of the data block in bytes.
+ */
+RTDECL(uint16_t) RTCrc16CcittProcess(uint16_t uCrc, const void *pv, size_t cb);
+
+/**
+ * Complete a multiblock CRC-16-CCITT calculation.
+ *
+ * @returns CRC-16-CCITT value.
+ * @param uCrc Current CRC-16-CCITT intermediate value.
+ */
+RTDECL(uint16_t) RTCrc16CcittFinish(uint16_t uCrc);
+/** @} */
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_crc_h */
+
diff --git a/include/iprt/critsect.h b/include/iprt/critsect.h
new file mode 100644
index 00000000..861cb675
--- /dev/null
+++ b/include/iprt/critsect.h
@@ -0,0 +1,768 @@
+/** @file
+ * IPRT - Critical Sections.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_critsect_h
+#define IPRT_INCLUDED_critsect_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+#include <iprt/assert.h>
+#if defined(IN_RING3) || defined(IN_RING0)
+# include <iprt/thread.h>
+#endif
+#ifdef RT_LOCK_STRICT_ORDER
+# include <iprt/lockvalidator.h>
+#endif
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_critsect RTCritSect - Critical Sections
+ *
+ * "Critical section" synchronization primitives can be used to
+ * 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.
+ *
+ * A critical section is a fast recursive write lock; if the critical
+ * section is not acquired, then entering it is fast (requires no system
+ * call). IPRT uses the Windows terminology here; on other platform, this
+ * might be called a "futex" or a "fast mutex". As opposed to IPRT
+ * "fast mutexes" (see @ref grp_rt_sems_fast_mutex ), critical sections
+ * are recursive.
+ *
+ * Use RTCritSectInit to initialize a critical section; use RTCritSectEnter
+ * and RTCritSectLeave to acquire and release access.
+ *
+ * For an overview of all types of synchronization primitives provided
+ * by IPRT (event, mutex/fast mutex/read-write mutex semaphores), see
+ * @ref grp_rt_sems .
+ *
+ * @ingroup grp_rt
+ * @{
+ */
+
+/**
+ * Critical section.
+ */
+typedef struct RTCRITSECT
+{
+ /** Magic used to validate the section state.
+ * RTCRITSECT_MAGIC is the value of an initialized & operational section. */
+ volatile uint32_t u32Magic;
+ /** Number of lockers.
+ * -1 if the section is free. */
+ volatile int32_t cLockers;
+ /** The owner thread. */
+ volatile RTNATIVETHREAD NativeThreadOwner;
+ /** Number of nested enter operations performed.
+ * Greater or equal to 1 if owned, 0 when free.
+ */
+ volatile int32_t cNestings;
+ /** Section flags - the RTCRITSECT_FLAGS_* \#defines. */
+ uint32_t fFlags;
+ /** The semaphore to block on. */
+ RTSEMEVENT EventSem;
+ /** Lock validator record. Only used in strict builds. */
+ R3R0PTRTYPE(PRTLOCKVALRECEXCL) pValidatorRec;
+ /** Alignment padding. */
+ RTHCPTR Alignment;
+} RTCRITSECT;
+AssertCompileSize(RTCRITSECT, HC_ARCH_BITS == 32 ? 32 : 48);
+
+/** RTCRITSECT::u32Magic value. (Hiromi Uehara) */
+#define RTCRITSECT_MAGIC UINT32_C(0x19790326)
+
+/** @name RTCritSectInitEx flags / RTCRITSECT::fFlags
+ * @{ */
+/** If set, nesting(/recursion) is not allowed. */
+#define RTCRITSECT_FLAGS_NO_NESTING UINT32_C(0x00000001)
+/** Disables lock validation. */
+#define RTCRITSECT_FLAGS_NO_LOCK_VAL UINT32_C(0x00000002)
+/** Bootstrap hack for use with certain memory allocator locks only! */
+#define RTCRITSECT_FLAGS_BOOTSTRAP_HACK UINT32_C(0x00000004)
+/** If set, the critical section becomes a dummy that doesn't serialize any
+ * threads. This flag can only be set at creation time.
+ *
+ * The intended use is avoiding lots of conditional code where some component
+ * might or might not require entering a critical section before access. */
+#define RTCRITSECT_FLAGS_NOP UINT32_C(0x00000008)
+/** Indicates that this is a ring-0 critical section. */
+#define RTCRITSECT_FLAGS_RING0 UINT32_C(0x00000010)
+/** @} */
+
+
+#if defined(IN_RING3) || defined(IN_RING0)
+
+/**
+ * Initialize a critical section.
+ */
+RTDECL(int) RTCritSectInit(PRTCRITSECT pCritSect);
+
+/**
+ * Initialize a critical section.
+ *
+ * @returns iprt status code.
+ * @param pCritSect Pointer to the critical section structure.
+ * @param fFlags Flags, any combination of the RTCRITSECT_FLAGS
+ * \#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) RTCritSectInitEx(PRTCRITSECT pCritSect, uint32_t fFlags, RTLOCKVALCLASS hClass, uint32_t uSubClass,
+ const char *pszNameFmt, ...) RT_IPRT_FORMAT_ATTR_MAYBE_NULL(5, 6);
+
+/**
+ * Changes the lock validator sub-class of the critical section.
+ *
+ * It is recommended to try make sure that nobody is using this critical section
+ * 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 pCritSect The critical section.
+ * @param uSubClass The new sub-class value.
+ */
+RTDECL(uint32_t) RTCritSectSetSubClass(PRTCRITSECT pCritSect, uint32_t uSubClass);
+
+/**
+ * Enter a critical section.
+ *
+ * @returns VINF_SUCCESS on success.
+ * @returns VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
+ * @retval VERR_SEM_DESTROYED if the critical section is delete before or
+ * during the operation.
+ * @param pCritSect The critical section.
+ */
+RTDECL(int) RTCritSectEnter(PRTCRITSECT pCritSect);
+
+/**
+ * Enter a critical section.
+ *
+ * @returns IPRT status code.
+ * @retval VINF_SUCCESS on success.
+ * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
+ * @retval VERR_SEM_DESTROYED if the critical section is delete before or
+ * during the operation.
+ *
+ * @param pCritSect The critical section.
+ * @param uId Where we're entering the section.
+ * @param SRC_POS The source position where call is being made from.
+ * Use RT_SRC_POS when possible. Optional.
+ */
+RTDECL(int) RTCritSectEnterDebug(PRTCRITSECT pCritSect, RTHCUINTPTR uId, RT_SRC_POS_DECL);
+
+/**
+ * Try enter a critical section.
+ *
+ * @retval VINF_SUCCESS on success.
+ * @retval VERR_SEM_BUSY if the critsect was owned.
+ * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
+ * @retval VERR_SEM_DESTROYED if the critical section is delete before or
+ * during the operation.
+ *
+ * @param pCritSect The critical section.
+ */
+RTDECL(int) RTCritSectTryEnter(PRTCRITSECT pCritSect);
+
+/**
+ * Try enter a critical section.
+ *
+ * @retval VINF_SUCCESS on success.
+ * @retval VERR_SEM_BUSY if the critsect was owned.
+ * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
+ * @retval VERR_SEM_DESTROYED if the critical section is delete before or
+ * during the operation.
+ *
+ * @param pCritSect The critical section.
+ * @param uId Where we're entering the section.
+ * @param SRC_POS The source position where call is being made from.
+ * Use RT_SRC_POS when possible. Optional.
+ */
+RTDECL(int) RTCritSectTryEnterDebug(PRTCRITSECT pCritSect, RTHCUINTPTR uId, RT_SRC_POS_DECL);
+
+# ifdef IN_RING3 /* Crazy APIs: ring-3 only. */
+
+/**
+ * Enter multiple critical sections.
+ *
+ * This function will enter ALL the specified critical sections before returning.
+ *
+ * @returns VINF_SUCCESS on success.
+ * @returns VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
+ * @retval VERR_SEM_DESTROYED if the critical section is delete before or
+ * during the operation.
+ * @param cCritSects Number of critical sections in the array.
+ * @param papCritSects Array of critical section pointers.
+ *
+ * @remark Please note that this function will not necessarily come out favourable in a
+ * fight with other threads which are using the normal RTCritSectEnter() function.
+ * Therefore, avoid having to enter multiple critical sections!
+ */
+RTDECL(int) RTCritSectEnterMultiple(size_t cCritSects, PRTCRITSECT *papCritSects);
+
+/**
+ * Enter multiple critical sections.
+ *
+ * This function will enter ALL the specified critical sections before returning.
+ *
+ * @returns VINF_SUCCESS on success.
+ * @returns VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
+ * @retval VERR_SEM_DESTROYED if the critical section is delete before or
+ * during the operation.
+ *
+ * @param cCritSects Number of critical sections in the array.
+ * @param papCritSects Array of critical section pointers.
+ * @param uId Where we're entering the section.
+ * @param SRC_POS The source position where call is being made from.
+ * Use RT_SRC_POS when possible. Optional.
+ *
+ * @remark See RTCritSectEnterMultiple().
+ */
+RTDECL(int) RTCritSectEnterMultipleDebug(size_t cCritSects, PRTCRITSECT *papCritSects, RTHCUINTPTR uId, RT_SRC_POS_DECL);
+
+# endif /* IN_RING3 */
+
+/**
+ * Leave a critical section.
+ *
+ * @returns VINF_SUCCESS.
+ * @param pCritSect The critical section.
+ */
+RTDECL(int) RTCritSectLeave(PRTCRITSECT pCritSect);
+
+/**
+ * Leave multiple critical sections.
+ *
+ * @returns VINF_SUCCESS.
+ * @param cCritSects Number of critical sections in the array.
+ * @param papCritSects Array of critical section pointers.
+ */
+RTDECL(int) RTCritSectLeaveMultiple(size_t cCritSects, PRTCRITSECT *papCritSects);
+
+/**
+ * Deletes a critical section.
+ *
+ * @returns VINF_SUCCESS.
+ * @param pCritSect The critical section.
+ */
+RTDECL(int) RTCritSectDelete(PRTCRITSECT pCritSect);
+
+/**
+ * Checks the caller is the owner of the critical section.
+ *
+ * @returns true if owner.
+ * @returns false if not owner.
+ * @param pCritSect The critical section.
+ */
+DECLINLINE(bool) RTCritSectIsOwner(PCRTCRITSECT pCritSect)
+{
+ return pCritSect->NativeThreadOwner == RTThreadNativeSelf();
+}
+
+#endif /* IN_RING3 || IN_RING0 */
+
+/**
+ * Checks the section is owned by anyone.
+ *
+ * @returns true if owned.
+ * @returns false if not owned.
+ * @param pCritSect The critical section.
+ */
+DECLINLINE(bool) RTCritSectIsOwned(PCRTCRITSECT pCritSect)
+{
+ return pCritSect->NativeThreadOwner != NIL_RTNATIVETHREAD;
+}
+
+/**
+ * Gets the thread id of the critical section owner.
+ *
+ * @returns Thread id of the owner thread if owned.
+ * @returns NIL_RTNATIVETHREAD is not owned.
+ * @param pCritSect The critical section.
+ */
+DECLINLINE(RTNATIVETHREAD) RTCritSectGetOwner(PCRTCRITSECT pCritSect)
+{
+ return pCritSect->NativeThreadOwner;
+}
+
+/**
+ * Checks if a critical section is initialized or not.
+ *
+ * @returns true if initialized.
+ * @returns false if not initialized.
+ * @param pCritSect The critical section.
+ */
+DECLINLINE(bool) RTCritSectIsInitialized(PCRTCRITSECT pCritSect)
+{
+ return pCritSect->u32Magic == RTCRITSECT_MAGIC;
+}
+
+/**
+ * Gets the recursion depth.
+ *
+ * @returns The recursion depth.
+ * @param pCritSect The Critical section
+ */
+DECLINLINE(uint32_t) RTCritSectGetRecursion(PCRTCRITSECT pCritSect)
+{
+ return (uint32_t)pCritSect->cNestings;
+}
+
+/**
+ * Gets the waiter count
+ *
+ * @returns The waiter count
+ * @param pCritSect The Critical section
+ */
+DECLINLINE(int32_t) RTCritSectGetWaiters(PCRTCRITSECT pCritSect)
+{
+ return pCritSect->cLockers;
+}
+
+/* Lock strict build: Remap the three enter calls to the debug versions. */
+#if defined(RT_LOCK_STRICT) && !defined(RTCRITSECT_WITHOUT_REMAPPING) && !defined(RT_WITH_MANGLING)
+# ifdef IPRT_INCLUDED_asm_h
+# define RTCritSectEnter(pCritSect) RTCritSectEnterDebug(pCritSect, (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
+# define RTCritSectTryEnter(pCritSect) RTCritSectTryEnterDebug(pCritSect, (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
+# define RTCritSectEnterMultiple(cCritSects, pCritSect) RTCritSectEnterMultipleDebug((cCritSects), (pCritSect), (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
+# else
+# define RTCritSectEnter(pCritSect) RTCritSectEnterDebug(pCritSect, 0, RT_SRC_POS)
+# define RTCritSectTryEnter(pCritSect) RTCritSectTryEnterDebug(pCritSect, 0, RT_SRC_POS)
+# define RTCritSectEnterMultiple(cCritSects, pCritSect) RTCritSectEnterMultipleDebug((cCritSects), (pCritSect), 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(RTCRITSECT_WITHOUT_REMAPPING) && !defined(RT_WITH_MANGLING)
+# define RTCritSectInit(pCritSect) \
+ RTCritSectInitEx((pCritSect), 0 /*fFlags*/, \
+ RTLockValidatorClassForSrcPos(RT_SRC_POS, NULL), \
+ RTLOCKVAL_SUB_CLASS_NONE, NULL)
+#endif
+
+/** @} */
+
+
+
+/** @defgroup grp_rt_critsectrw RTCritSectRw - Read/Write Critical Sections
+ * @ingroup grp_rt
+ * @{
+ */
+
+/**
+ * Union that allows us to atomically update both the state and
+ * exclusive owner if the hardware supports cmpxchg16b or similar.
+ */
+typedef union RTCRITSECTRWSTATE
+{
+ struct
+ {
+ /** The state variable.
+ * All accesses are atomic and it bits are defined like this:
+ * Bits 0..14 - cReads.
+ * Bit 15 - Unused.
+ * Bits 16..31 - cWrites.
+ * Bit 31 - fDirection; 0=Read, 1=Write.
+ * Bits 32..46 - cWaitingReads
+ * Bit 47 - Unused.
+ * Bits 48..62 - cWaitingWrites - doesn't make sense here, not used.
+ * Bit 63 - Unused.
+ */
+ uint64_t u64State;
+ /** The write owner. */
+ RTNATIVETHREAD hNativeWriter;
+ } s;
+ RTUINT128U u128;
+} RTCRITSECTRWSTATE;
+
+
+/**
+ * Read/write critical section.
+ */
+typedef struct RTCRITSECTRW
+{
+ /** Magic used to validate the section state.
+ * RTCRITSECTRW_MAGIC is the value of an initialized & operational section. */
+ volatile uint32_t u32Magic;
+
+ /** Indicates whether hEvtRead needs resetting. */
+ bool volatile fNeedReset;
+ /** Explicit alignment padding. */
+ bool volatile afPadding[1];
+ /** Section flags - the RTCRITSECT_FLAGS_* \#defines. */
+ uint16_t fFlags;
+
+ /** The number of reads made by the current writer. */
+ uint32_t volatile cWriterReads;
+ /** The number of recursions made by the current writer. (The initial grabbing
+ * of the lock counts as the first one.) */
+ uint32_t volatile cWriteRecursions;
+ /** The core state. */
+ RTCRITSECTRWSTATE volatile u;
+
+ /** What the writer threads are blocking on. */
+ RTSEMEVENT hEvtWrite;
+ /** What the read threads are blocking on when waiting for the writer to
+ * finish. */
+ RTSEMEVENTMULTI hEvtRead;
+
+ /** The validator record for the writer. */
+ R3R0PTRTYPE(PRTLOCKVALRECEXCL) pValidatorWrite;
+ /** The validator record for the readers. */
+ R3R0PTRTYPE(PRTLOCKVALRECSHRD) pValidatorRead;
+} RTCRITSECTRW;
+AssertCompileSize(RTCRITSECTRW, HC_ARCH_BITS == 32 ? 48 : 64);
+
+/** RTCRITSECTRW::u32Magic value. (Eric Allan Dolphy, Jr.) */
+#define RTCRITSECTRW_MAGIC UINT32_C(0x19280620)
+/** RTCRITSECTRW::u32Magic dead value. */
+#define RTCRITSECTRW_MAGIC_DEAD UINT32_C(0x19640629)
+
+/** @name RTCRITSECTRW::u64State values.
+ * @note Using RTCSRW instead of RTCRITSECTRW to save space.
+ * @{ */
+#define RTCSRW_CNT_BITS 15
+#define RTCSRW_CNT_MASK UINT64_C(0x00007fff)
+
+#define RTCSRW_CNT_RD_SHIFT 0
+#define RTCSRW_CNT_RD_MASK (RTCSRW_CNT_MASK << RTCSRW_CNT_RD_SHIFT)
+#define RTCSRW_CNT_WR_SHIFT 16
+#define RTCSRW_CNT_WR_MASK (RTCSRW_CNT_MASK << RTCSRW_CNT_WR_SHIFT)
+
+#define RTCSRW_DIR_SHIFT 31
+#define RTCSRW_DIR_MASK RT_BIT_64(RTCSRW_DIR_SHIFT)
+#define RTCSRW_DIR_READ UINT64_C(0)
+#define RTCSRW_DIR_WRITE UINT64_C(1)
+
+#define RTCSRW_WAIT_CNT_RD_SHIFT 32
+#define RTCSRW_WAIT_CNT_RD_MASK (RTCSRW_CNT_MASK << RTCSRW_WAIT_CNT_RD_SHIFT)
+/* #define RTCSRW_WAIT_CNT_WR_SHIFT 48 */
+/* #define RTCSRW_WAIT_CNT_WR_MASK (RTCSRW_CNT_MASK << RTCSRW_WAIT_CNT_WR_SHIFT) */
+/** @} */
+
+#if defined(IN_RING3) || defined(IN_RING0)
+
+/**
+ * Initialize a critical section.
+ */
+RTDECL(int) RTCritSectRwInit(PRTCRITSECTRW pThis);
+
+/**
+ * Initialize a critical section.
+ *
+ * @returns IPRT status code.
+ * @param pThis Pointer to the read/write critical section.
+ * @param fFlags Flags, any combination of the RTCRITSECT_FLAGS
+ * \#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) RTCritSectRwInitEx(PRTCRITSECTRW pThis, uint32_t fFlags, RTLOCKVALCLASS hClass, uint32_t uSubClass,
+ const char *pszNameFmt, ...) RT_IPRT_FORMAT_ATTR_MAYBE_NULL(5, 6);
+
+/**
+ * Changes the lock validator sub-class of the critical section.
+ *
+ * It is recommended to try make sure that nobody is using this critical section
+ * 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 pThis Pointer to the read/write critical section.
+ * @param uSubClass The new sub-class value.
+ */
+RTDECL(uint32_t) RTCritSectRwSetSubClass(PRTCRITSECTRW pThis, uint32_t uSubClass);
+
+
+/**
+ * Enter a critical section with shared (read) access.
+ *
+ * @returns IPRT status code.
+ * @retval VINF_SUCCESS on success.
+ * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
+ * @retval VERR_SEM_DESTROYED if the critical section is delete before or
+ * during the operation.
+ * @param pThis Pointer to the read/write critical section.
+ */
+RTDECL(int) RTCritSectRwEnterShared(PRTCRITSECTRW pThis);
+
+/**
+ * Enter a critical section with shared (read) access.
+ *
+ * @returns IPRT status code.
+ * @retval VINF_SUCCESS on success.
+ * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
+ * @retval VERR_SEM_DESTROYED if the critical section is delete before or
+ * during the operation.
+ *
+ * @param pThis Pointer to the read/write critical section.
+ * @param uId Where we're entering the section.
+ * @param SRC_POS The source position where call is being made from.
+ * Use RT_SRC_POS when possible. Optional.
+ */
+RTDECL(int) RTCritSectRwEnterSharedDebug(PRTCRITSECTRW pThis, RTHCUINTPTR uId, RT_SRC_POS_DECL);
+
+/**
+ * Try enter a critical section with shared (read) access.
+ *
+ * @returns IPRT status code.
+ * @retval VINF_SUCCESS on success.
+ * @retval VERR_SEM_BUSY if the critsect was owned.
+ * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
+ * @retval VERR_SEM_DESTROYED if the critical section is delete before or
+ * during the operation.
+ *
+ * @param pThis Pointer to the read/write critical section.
+ */
+RTDECL(int) RTCritSectRwTryEnterShared(PRTCRITSECTRW pThis);
+
+/**
+ * Try enter a critical section with shared (read) access.
+ *
+ * @returns IPRT status code.
+ * @retval VINF_SUCCESS on success.
+ * @retval VERR_SEM_BUSY if the critsect was owned.
+ * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
+ * @retval VERR_SEM_DESTROYED if the critical section is delete before or
+ * during the operation.
+ *
+ * @param pThis Pointer to the read/write critical section.
+ * @param uId Where we're entering the section.
+ * @param SRC_POS The source position where call is being made from.
+ * Use RT_SRC_POS when possible. Optional.
+ */
+RTDECL(int) RTCritSectRwTryEnterSharedDebug(PRTCRITSECTRW pThis, RTHCUINTPTR uId, RT_SRC_POS_DECL);
+
+/**
+ * Leave a critical section held with shared access.
+ *
+ * @returns IPRT status code.
+ * @param pThis Pointer to the read/write critical section.
+ */
+RTDECL(int) RTCritSectRwLeaveShared(PRTCRITSECTRW pThis);
+
+
+/**
+ * Enter a critical section with exclusive (write) access.
+ *
+ * @returns IPRT status code.
+ * @retval VINF_SUCCESS on success.
+ * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
+ * @retval VERR_SEM_DESTROYED if the critical section is delete before or
+ * during the operation.
+ * @param pThis Pointer to the read/write critical section.
+ */
+RTDECL(int) RTCritSectRwEnterExcl(PRTCRITSECTRW pThis);
+
+/**
+ * Enter a critical section with exclusive (write) access.
+ *
+ * @retval VINF_SUCCESS on success.
+ * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
+ * @retval VERR_SEM_DESTROYED if the critical section is delete before or
+ * during the operation.
+ *
+ * @param pThis Pointer to the read/write critical section.
+ * @param uId Where we're entering the section.
+ * @param SRC_POS The source position where call is being made from.
+ * Use RT_SRC_POS when possible. Optional.
+ */
+RTDECL(int) RTCritSectRwEnterExclDebug(PRTCRITSECTRW pThis, RTHCUINTPTR uId, RT_SRC_POS_DECL);
+
+/**
+ * Try enter a critical section with exclusive (write) access.
+ *
+ * @returns IPRT status code.
+ * @retval VINF_SUCCESS on success.
+ * @retval VERR_SEM_BUSY if the critsect was owned.
+ * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
+ * @retval VERR_SEM_DESTROYED if the critical section is delete before or
+ * during the operation.
+ *
+ * @param pThis Pointer to the read/write critical section.
+ */
+RTDECL(int) RTCritSectRwTryEnterExcl(PRTCRITSECTRW pThis);
+
+/**
+ * Try enter a critical section with exclusive (write) access.
+ *
+ * @returns IPRT status code.
+ * @retval VINF_SUCCESS on success.
+ * @retval VERR_SEM_BUSY if the critsect was owned.
+ * @retval VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
+ * @retval VERR_SEM_DESTROYED if the critical section is delete before or
+ * during the operation.
+ *
+ * @param pThis Pointer to the read/write critical section.
+ * @param uId Where we're entering the section.
+ * @param SRC_POS The source position where call is being made from.
+ * Use RT_SRC_POS when possible. Optional.
+ */
+RTDECL(int) RTCritSectRwTryEnterExclDebug(PRTCRITSECTRW pThis, RTHCUINTPTR uId, RT_SRC_POS_DECL);
+
+/**
+ * Leave a critical section held exclusively.
+ *
+ * @returns IPRT status code; VINF_SUCCESS, VERR_NOT_OWNER, VERR_SEM_DESTROYED,
+ * or VERR_WRONG_ORDER.
+ * @param pThis Pointer to the read/write critical section.
+ */
+RTDECL(int) RTCritSectRwLeaveExcl(PRTCRITSECTRW pThis);
+
+
+/**
+ * Deletes a critical section.
+ *
+ * @returns VINF_SUCCESS.
+ * @param pThis Pointer to the read/write critical section.
+ */
+RTDECL(int) RTCritSectRwDelete(PRTCRITSECTRW pThis);
+
+/**
+ * Checks the caller is the exclusive (write) owner of the critical section.
+ *
+ * @retval true if owner.
+ * @retval false if not owner.
+ * @param pThis Pointer to the read/write critical section.
+ */
+RTDECL(bool) RTCritSectRwIsWriteOwner(PRTCRITSECTRW pThis);
+
+/**
+ * Checks if the caller is one of the read owners of the critical section.
+ *
+ * @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 RTCRITSECTRW_STRICT was defined at build time.
+ * Also, make sure you do not use RTCRITSECTRW_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 @c true if reader, @c false if not.
+ * @param pThis Pointer to the read/write critical section.
+ * @param fWannaHear What you'd like to hear when lock validation is not
+ * available. (For avoiding asserting all over the
+ * place.)
+ */
+RTDECL(bool) RTCritSectRwIsReadOwner(PRTCRITSECTRW pThis, bool fWannaHear);
+
+/**
+ * Gets the write recursion count.
+ *
+ * @returns The write recursion count (0 if bad critsect).
+ * @param pThis Pointer to the read/write critical section.
+ */
+RTDECL(uint32_t) RTCritSectRwGetWriteRecursion(PRTCRITSECTRW pThis);
+
+/**
+ * Gets the read recursion count of the current writer.
+ *
+ * @returns The read recursion count (0 if bad critsect).
+ * @param pThis Pointer to the read/write critical section.
+ */
+RTDECL(uint32_t) RTCritSectRwGetWriterReadRecursion(PRTCRITSECTRW pThis);
+
+/**
+ * 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 critsect).
+ * @param pThis Pointer to the read/write critical section.
+ */
+RTDECL(uint32_t) RTCritSectRwGetReadCount(PRTCRITSECTRW pThis);
+
+#endif /* IN_RING3 || IN_RING0 */
+
+/**
+ * Checks if a critical section is initialized or not.
+ *
+ * @retval true if initialized.
+ * @retval false if not initialized.
+ * @param pThis Pointer to the read/write critical section.
+ */
+DECLINLINE(bool) RTCritSectRwIsInitialized(PCRTCRITSECTRW pThis)
+{
+ return pThis->u32Magic == RTCRITSECTRW_MAGIC;
+}
+
+/* Lock strict build: Remap the three enter calls to the debug versions. */
+#if defined(RT_LOCK_STRICT) && !defined(RTCRITSECTRW_WITHOUT_REMAPPING) && !defined(RT_WITH_MANGLING)
+# ifdef IPRT_INCLUDED_asm_h
+# define RTCritSectRwEnterExcl(pThis) RTCritSectRwEnterExclDebug(pThis, (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
+# define RTCritSectRwTryEnterExcl(pThis) RTCritSectRwTryEnterExclDebug(pThis, (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
+# define RTCritSectRwEnterShared(pThis) RTCritSectRwEnterSharedDebug(pThis, (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
+# define RTCritSectRwTryEnterShared(pThis) RTCritSectRwTryEnterSharedDebug(pThis, (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
+# else
+# define RTCritSectRwEnterExcl(pThis) RTCritSectRwEnterExclDebug(pThis, 0, RT_SRC_POS)
+# define RTCritSectRwTryEnterExcl(pThis) RTCritSectRwTryEnterExclDebug(pThis, 0, RT_SRC_POS)
+# define RTCritSectRwEnterShared(pThis) RTCritSectRwEnterSharedDebug(pThis, 0, RT_SRC_POS)
+# define RTCritSectRwTryEnterShared(pThis) RTCritSectRwTryEnterSharedDebug(pThis, 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(RTCRITSECTRW_WITHOUT_REMAPPING) && !defined(RT_WITH_MANGLING)
+# define RTCritSectRwInit(a_pThis) \
+ RTCritSectRwInitEx((a_pThis), 0 /*fFlags*/, \
+ RTLockValidatorClassForSrcPos(RT_SRC_POS, NULL), \
+ RTLOCKVAL_SUB_CLASS_NONE, NULL)
+#endif
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_critsect_h */
+
diff --git a/include/iprt/crypto/Makefile.kup b/include/iprt/crypto/Makefile.kup
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/include/iprt/crypto/Makefile.kup
diff --git a/include/iprt/crypto/applecodesign.h b/include/iprt/crypto/applecodesign.h
new file mode 100644
index 00000000..df546e06
--- /dev/null
+++ b/include/iprt/crypto/applecodesign.h
@@ -0,0 +1,290 @@
+/** @file
+ * IPRT - Apple Code Signing Structures and APIs.
+ */
+
+/*
+ * Copyright (C) 2018-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_crypto_applecodesign_h
+#define IPRT_INCLUDED_crypto_applecodesign_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+#include <iprt/assertcompile.h>
+#include <iprt/crypto/pkcs7.h>
+
+/** @defgroup grp_rt_craplcs RTCrAppleCs - Apple Code Signing
+ * @ingroup grp_rt_crypto
+ * @{
+ */
+
+/** Apple developer ID for iPhone application software development signing. */
+#define RTCR_APPLE_CS_DEVID_IPHONE_SW_DEV_OID "1.2.840.113635.100.6.1.2"
+/** Apple developer ID for Mac application software development signing. */
+#define RTCR_APPLE_CS_DEVID_MAC_SW_DEV_OID "1.2.840.113635.100.6.1.12"
+/** Apple developer ID for application signing. */
+#define RTCR_APPLE_CS_DEVID_APPLICATION_OID "1.2.840.113635.100.6.1.13"
+/** Apple developer ID for installer signing. */
+#define RTCR_APPLE_CS_DEVID_INSTALLER_OID "1.2.840.113635.100.6.1.14"
+/** Apple developer ID for kernel extension signing. */
+#define RTCR_APPLE_CS_DEVID_KEXT_OID "1.2.840.113635.100.6.1.18"
+/** Apple certificate policy OID. */
+#define RTCR_APPLE_CS_CERTIFICATE_POLICY_OID "1.2.840.113635.100.5.1"
+
+
+/** @name RTCRAPLCS_MAGIC_XXX - Apple code signing magic values for identifying blobs
+ * @note No byte order conversion required.
+ * @{ */
+#define RTCRAPLCS_MAGIC_BLOBWRAPPER RT_N2H_U32_C(UINT32_C(0xfade0b01))
+#define RTCRAPLCS_MAGIC_EMBEDDED_SIGNATURE_OLD RT_N2H_U32_C(UINT32_C(0xfade0b02))
+#define RTCRAPLCS_MAGIC_REQUIREMENT RT_N2H_U32_C(UINT32_C(0xfade0c00))
+#define RTCRAPLCS_MAGIC_REQUIREMENTS RT_N2H_U32_C(UINT32_C(0xfade0c01))
+#define RTCRAPLCS_MAGIC_CODEDIRECTORY RT_N2H_U32_C(UINT32_C(0xfade0c02))
+#define RTCRAPLCS_MAGIC_EMBEDDED_SIGNATURE RT_N2H_U32_C(UINT32_C(0xfade0cc0))
+#define RTCRAPLCS_MAGIC_DETACHED_SIGNATURE RT_N2H_U32_C(UINT32_C(0xfade0cc1))
+/** @} */
+
+/** @name Apple code signing versions.
+ * @note Requires byte order conversion of the field value. That way
+ * greater-than and less-than comparisons works correctly.
+ * @{ */
+#define RTCRAPLCS_VER_2_0 UINT32_C(0x00020000)
+#define RTCRAPLCS_VER_SUPPORTS_SCATTER UINT32_C(0x00020100)
+#define RTCRAPLCS_VER_SUPPORTS_TEAMID UINT32_C(0x00020200)
+#define RTCRAPLCS_VER_SUPPORTS_CODE_LIMIT_64 UINT32_C(0x00020300)
+#define RTCRAPLCS_VER_SUPPORTS_EXEC_SEG UINT32_C(0x00020400)
+/** @} */
+
+/** @name RTCRAPLCS_SLOT_XXX - Apple code signing slots.
+ * @note No byte order conversion required.
+ * @{ */
+#define RTCRAPLCS_SLOT_CODEDIRECTORY RT_N2H_U32_C(UINT32_C(0x00000000))
+#define RTCRAPLCS_SLOT_INFO RT_N2H_U32_C(UINT32_C(0x00000001))
+#define RTCRAPLCS_SLOT_REQUIREMENTS RT_N2H_U32_C(UINT32_C(0x00000002))
+#define RTCRAPLCS_SLOT_RESOURCEDIR RT_N2H_U32_C(UINT32_C(0x00000003))
+#define RTCRAPLCS_SLOT_APPLICATION RT_N2H_U32_C(UINT32_C(0x00000004))
+#define RTCRAPLCS_SLOT_ENTITLEMENTS RT_N2H_U32_C(UINT32_C(0x00000005))
+#define RTCRAPLCS_SLOT_ALTERNATE_CODEDIRECTORIES RT_N2H_U32_C(UINT32_C(0x00001000))
+#define RTCRAPLCS_SLOT_ALTERNATE_CODEDIRECTORIES_END RT_N2H_U32_C(UINT32_C(0x00001005))
+#define RTCRAPLCS_SLOT_ALTERNATE_CODEDIRECTORIES_COUNT UINT32_C(0x00000005)
+#define RTCRAPLCS_SLOT_ALTERNATE_CODEDIRECTORY_INC RT_N2H_U32_C(UINT32_C(0x00000001))
+/** The signature.
+ * This is simply a RTCRAPLCSHDR/RTCRAPLCS_MAGIC_BLOBWRAPPER followed by a DER
+ * encoded \#PKCS7 ContentInfo structure containing signedData. The inner
+ * signedData structure signs external data, so its ContentInfo member is set
+ * to 1.2.840.113549.1.7.1 and has no data. */
+#define RTCRAPLCS_SLOT_SIGNATURE RT_N2H_U32_C(UINT32_C(0x00010000))
+/** @} */
+
+/** @name RTCRAPLCS_HASHTYPE_XXX - Apple code signing hash types
+ * @note Byte sized field, so no byte order concerns.
+ * @{ */
+#define RTCRAPLCS_HASHTYPE_SHA1 UINT8_C(1)
+#define RTCRAPLCS_HASHTYPE_SHA256 UINT8_C(2)
+#define RTCRAPLCS_HASHTYPE_SHA256_TRUNCATED UINT8_C(3) /**< Truncated to 20 bytes (SHA1 size). */
+#define RTCRAPLCS_HASHTYPE_SHA384 UINT8_C(4)
+/** @} */
+
+
+/**
+ * Apple code signing blob header.
+ */
+typedef struct RTCRAPLCSHDR
+{
+ /** The magic value (RTCRAPLCS_MAGIC_XXX).
+ * (Big endian, but constant are big endian already.) */
+ uint32_t uMagic;
+ /** The total length of the blob. Big endian. */
+ uint32_t cb;
+} RTCRAPLCSHDR;
+AssertCompileSize(RTCRAPLCSHDR, 8);
+/** Pointer to a CS blob header. */
+typedef RTCRAPLCSHDR *PRTCRAPLCSHDR;
+/** Pointer to a const CS blob header. */
+typedef RTCRAPLCSHDR const *PCRTCRAPLCSHDR;
+
+/**
+ * Apple code signing super blob slot.
+ */
+typedef struct RTCRAPLCSBLOBSLOT
+{
+ /** Slot type, RTCRAPLCS_SLOT_XXX.
+ * (Big endian, but so are the constants too). */
+ uint32_t uType;
+ /** Data offset. Big endian. */
+ uint32_t offData;
+} RTCRAPLCSBLOBSLOT;
+AssertCompileSize(RTCRAPLCSBLOBSLOT, 8);
+/** Pointer to a super blob slot. */
+typedef RTCRAPLCSBLOBSLOT *PRTCRAPLCSBLOBSLOT;
+/** Pointer to a const super blob slot. */
+typedef RTCRAPLCSBLOBSLOT const *PCRTCRAPLCSBLOBSLOT;
+
+/**
+ * Apple code signing super blob.
+ */
+typedef struct RTCRAPLCSSUPERBLOB
+{
+ /** Header (uMagic = RTCRAPLCS_MAGIC_EMBEDDED_SIGNATURE?
+ * or RTCRAPLCS_MAGIC_EMBEDDED_SIGNATURE_OLD? ). */
+ RTCRAPLCSHDR Hdr;
+ /** Number of slots. Big endian. */
+ uint32_t cSlots;
+ /** Slots. */
+ RT_FLEXIBLE_ARRAY_EXTENSION
+ RTCRAPLCSBLOBSLOT aSlots[RT_FLEXIBLE_ARRAY];
+} RTCRAPLCSSUPERBLOB;
+AssertCompileMemberOffset(RTCRAPLCSSUPERBLOB, aSlots, 12);
+/** Pointer to a CS super blob. */
+typedef RTCRAPLCSSUPERBLOB *PRTCRAPLCSSUPERBLOB;
+/** Pointer to a const CS super blob. */
+typedef RTCRAPLCSSUPERBLOB const *PCRTCRAPLCSSUPERBLOB;
+
+/**
+ * Code directory (RTCRAPLCS_MAGIC_CODEDIRECTORY).
+ */
+typedef struct RTCRAPLCSCODEDIRECTORY
+{
+ /** 0x00: Header (uMagic = RTCRAPLCS_MAGIC_CODEDIRECTORY). */
+ RTCRAPLCSHDR Hdr;
+ /** 0x08: The version number (RTCRAPLCS_VER_XXX).
+ * @note Big endian, host order constants. */
+ uint32_t uVersion;
+ /** 0x0c: Flags & mode, RTCRAPLCS_???. (Big endian. ) */
+ uint32_t fFlags;
+ /** 0x10: Offset of the hash slots. Big endian.
+ * Special slots found below this offset, code slots at and after. */
+ uint32_t offHashSlots;
+ /** 0x14: Offset of the identifier string. Big endian. */
+ uint32_t offIdentifier;
+ /** 0x18: Number of special hash slots. Hubertus Bigend style. */
+ uint32_t cSpecialSlots;
+ /** 0x1c: Number of code hash slots. Big endian. */
+ uint32_t cCodeSlots;
+ /** 0x20: Number of bytes of code that's covered, 32-bit wide. Big endian. */
+ uint32_t cbCodeLimit32;
+ /** 0x24: The hash size. */
+ uint8_t cbHash;
+ /** 0x25: The hash type (RTCRAPLCS_HASHTYPE_XXX). */
+ uint8_t bHashType;
+ /** 0x26: Platform identifier or zero. */
+ uint8_t idPlatform;
+ /** 0x27: The page shift value. zero if infinite page size. */
+ uint8_t cPageShift;
+ /** 0x28: Spare field, MBZ. */
+ uint32_t uUnused1;
+ /** 0x2c: Offset of scatter vector (optional). Big endian.
+ * @since RTCRAPLCS_VER_SUPPORTS_SCATTER */
+ uint32_t offScatter;
+ /** 0x30: Offset of team identifier (optional). Big endian.
+ * @since RTCRAPLCS_VER_SUPPORTS_TEAMID */
+ uint32_t offTeamId;
+ /** 0x34: Unused field, MBZ.
+ * @since RTCRAPLCS_VER_SUPPORTS_CODE_LIMIT_64 */
+ uint32_t uUnused2;
+ /** 0x38: Number of bytes of code that's covered, 64-bit wide. Big endian.
+ * @since RTCRAPLCS_VER_SUPPORTS_CODE_LIMIT_64 */
+ uint64_t cbCodeLimit64;
+ /** 0x40: File offset of the first segment. Big endian.
+ * @since RTCRAPLCS_VER_SUPPORTS_EXEC_SEG */
+ uint64_t offExecSeg;
+ /** 0x48: The size of the first segment. Big endian.
+ * @since RTCRAPLCS_VER_SUPPORTS_EXEC_SEG */
+ uint64_t cbExecSeg;
+ /** 0x50: Flags for the first segment. Big endian.
+ * @since RTCRAPLCS_VER_SUPPORTS_EXEC_SEG */
+ uint64_t fExecSeg;
+} RTCRAPLCSCODEDIRECTORY;
+AssertCompileSize(RTCRAPLCSCODEDIRECTORY, 0x58);
+/** Pointer to a CS code directory. */
+typedef RTCRAPLCSCODEDIRECTORY *PRTCRAPLCSCODEDIRECTORY;
+/** Pointer to a const CS code directory. */
+typedef RTCRAPLCSCODEDIRECTORY const *PCRTCRAPLCSCODEDIRECTORY;
+
+
+/**
+ * IPRT structure for working with an Apple code signing blob.
+ */
+typedef struct RTCRAPLCS
+{
+ uint8_t const *pbBlob;
+ size_t cbBlob;
+ size_t auReserved[4];
+} RTCRAPLCS;
+/** Pointer to an IPRT CS blob descriptor. */
+typedef RTCRAPLCS *PRTCRAPLCS;
+
+/**
+ * Initialize a RTCRAPLCS descriptor and validate the blob data.
+ *
+ * @returns IPRT status code.
+ * @param pDesc The descirptor to initialize.
+ * @param pvBlob The blob bytes.
+ * @param cbBlob The number of bytes in the blob.
+ * @param fFlags Future validation flags, MBZ.
+ * @param pErrInfo Where to return additional error details. Optional.
+ */
+RTDECL(int) RTCrAppleCsInit(PRTCRAPLCS pDesc, void const *pvBlob, size_t cbBlob, uint32_t fFlags, PRTERRINFO pErrInfo);
+
+/**
+ * Callback used by RTCrAppleCsVerifyImage to digest a section of the image.
+ *
+ * @return IPRT status code.
+ * @param hDigest The digest to feed the bytes to.
+ * @param off The RVA of the bytes to digest.
+ * @param cb Number of bytes to digest.
+ * @param pvUser User argument.
+ */
+typedef DECLCALLBACKTYPE(int, FNRTCRAPPLECSDIGESTAREA,(RTCRDIGEST hDigest, size_t off, size_t cb, void *pvUser));
+/** Pointer to a image digest callback. */
+typedef FNRTCRAPPLECSDIGESTAREA *PFNRTCRAPPLECSDIGESTAREA;
+
+/**
+ * Verifies an image against the given signature blob.
+ *
+ * @return IPRT status code.
+ * @param pDesc The apple code signing blob to verify against.
+ * @param fFlags Future verification flags, MBZ.
+ * @param pfnCallback Image digest callback.
+ * @param pvUser User argument for the callback.
+ * @param pErrInfo Where to return additional error details. Optional.
+ */
+RTDECL(int) RTCrAppleCsVerifyImage(PRTCRAPLCS pDesc, uint32_t fFlags, PFNRTCRAPPLECSDIGESTAREA pfnCallback,
+ void *pvUser, PRTERRINFO pErrInfo);
+
+RTDECL(int) RTCrAppleCsQuerySigneddData(PRTCRAPLCS pDesc, PRTCRPKCS7SIGNEDDATA pSignedData, PRTERRINFO pErrInfo);
+
+/** @} */
+
+#endif /* !IPRT_INCLUDED_crypto_applecodesign_h */
+
diff --git a/include/iprt/crypto/cipher.h b/include/iprt/crypto/cipher.h
new file mode 100644
index 00000000..9fb3cd02
--- /dev/null
+++ b/include/iprt/crypto/cipher.h
@@ -0,0 +1,156 @@
+/** @file
+ * IPRT - Crypto - Symmetric Ciphers.
+ */
+
+/*
+ * Copyright (C) 2018-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_crypto_cipher_h
+#define IPRT_INCLUDED_crypto_cipher_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/asn1.h>
+
+
+RT_C_DECLS_BEGIN
+
+struct RTCRX509SUBJECTPUBLICKEYINFO;
+
+/** @defgroup grp_rt_crcipher RTCrCipher - Symmetric Ciphers
+ * @ingroup grp_rt_crypto
+ * @{
+ */
+
+/**
+ * A symmetric cipher handle.
+ *
+ * @remarks In OpenSSL terms this corresponds to a EVP_CIPHER, while in Microsoft
+ * terms it is an algorithm handle. The latter is why a handle was
+ * choosen rather than constant descriptor structure pointer. */
+typedef struct RTCRCIPHERINT *RTCRCIPHER;
+/** Pointer to a symmetric cipher handle. */
+typedef RTCRCIPHER *PRTCRCIPHER;
+/** Nil symmetric cipher handle. */
+#define NIL_RTCRCIPHER ((RTCRCIPHER)0)
+/** Symmetric cipher context */
+typedef struct RTCRCIPHERCTXINT *RTCRCIPHERCTX;
+/** Pointer to a symmetric cipher context */
+typedef RTCRCIPHERCTX *PRTCRCIPHERCTX;
+/** Nil symmetric cipher context */
+#define NIL_RTCRCIPHERCTX ((RTCRCIPHERCTX)0)
+
+/**
+ * Symmetric cipher types.
+ *
+ * @note Only add new types at the end, existing values must be stable.
+ */
+typedef enum RTCRCIPHERTYPE
+{
+ /** Invalid zero value. */
+ RTCRCIPHERTYPE_INVALID = 0,
+ /** XTS-AES-128 (NIST SP 800-38E). */
+ RTCRCIPHERTYPE_XTS_AES_128,
+ /** XTS-AES-256 (NIST SP 800-38E). */
+ RTCRCIPHERTYPE_XTS_AES_256,
+ /** GCM-AES-128. */
+ RTCRCIPHERTYPE_GCM_AES_128,
+ /** GCM-AES-256. */
+ RTCRCIPHERTYPE_GCM_AES_256,
+ /* CTR-AES-128 */
+ RTCRCIPHERTYPE_CTR_AES_128,
+ /* CTR-AES-256 */
+ RTCRCIPHERTYPE_CTR_AES_256,
+ /** End of valid symmetric cipher types. */
+ RTCRCIPHERTYPE_END,
+ /** Make sure the type is a 32-bit one. */
+ RTCRCIPHERTYPE_32BIT_HACK = 0x7fffffff
+} RTCRCIPHERTYPE;
+
+
+RTDECL(int) RTCrCipherOpenByType(PRTCRCIPHER phCipher, RTCRCIPHERTYPE enmType, uint32_t fFlags);
+RTDECL(uint32_t) RTCrCipherRetain(RTCRCIPHER hCipher);
+RTDECL(uint32_t) RTCrCipherRelease(RTCRCIPHER hCipher);
+RTDECL(uint32_t) RTCrCipherGetKeyLength(RTCRCIPHER hCipher);
+RTDECL(uint32_t) RTCrCipherGetInitializationVectorLength(RTCRCIPHER hCipher);
+RTDECL(uint32_t) RTCrCipherGetBlockSize(RTCRCIPHER hCipher);
+
+RTDECL(int) RTCrCipherCtxFree(RTCRCIPHERCTX phCipherCtx);
+
+RTDECL(int) RTCrCipherCtxEncryptInit(RTCRCIPHER hCipher, void const *pvKey, size_t cbKey,
+ void const *pvInitVector, size_t cbInitVector,
+ void const *pvAuthData, size_t cbAuthData,
+ PRTCRCIPHERCTX phCipherCtx);
+RTDECL(int) RTCrCipherCtxEncryptProcess(RTCRCIPHERCTX hCipherCtx, void const *pvPlainText, size_t cbPlainText,
+ void *pvEncrypted, size_t cbEncrypted, size_t *pcbEncrypted);
+RTDECL(int) RTCrCipherCtxEncryptFinish(RTCRCIPHERCTX hCipherCtx,
+ void *pvEncrypted, size_t *pcbEncrypted,
+ void *pvTag, size_t cbTag, size_t *pcbTag);
+
+RTDECL(int) RTCrCipherCtxDecryptInit(RTCRCIPHER hCipher, void const *pvKey, size_t cbKey,
+ void const *pvInitVector, size_t cbInitVector,
+ void const *pvAuthData, size_t cbAuthData,
+ void *pvTag, size_t cbTag, PRTCRCIPHERCTX phCipherCtx);
+RTDECL(int) RTCrCipherCtxDecryptProcess(RTCRCIPHERCTX hCipherCtx,
+ void const *pvEncrypted, size_t cbEncrypted,
+ void *pvPlainText, size_t cbPlainText, size_t *pcbPlainText);
+RTDECL(int) RTCrCipherCtxDecryptFinish(RTCRCIPHERCTX hCipherCtx,
+ void *pvPlainText, size_t *pcbPlainText);
+
+
+RTDECL(int) RTCrCipherEncrypt(RTCRCIPHER hCipher, void const *pvKey, size_t cbKey,
+ void const *pvInitVector, size_t cbInitVector,
+ void const *pvPlainText, size_t cbPlainText,
+ void *pvEncrypted, size_t cbEncrypted, size_t *pcbEncrypted);
+RTDECL(int) RTCrCipherDecrypt(RTCRCIPHER hCipher, void const *pvKey, size_t cbKey,
+ void const *pvInitVector, size_t cbInitVector,
+ void const *pvEncrypted, size_t cbEncrypted,
+ void *pvPlainText, size_t cbPlainText, size_t *pcbPlainText);
+RTDECL(int) RTCrCipherEncryptEx(RTCRCIPHER hCipher, void const *pvKey, size_t cbKey,
+ void const *pvInitVector, size_t cbInitVector,
+ void const *pvAuthData, size_t cbAuthData,
+ void const *pvPlainText, size_t cbPlainText,
+ void *pvEncrypted, size_t cbEncrypted, size_t *pcbEncrypted,
+ void *pvTag, size_t cbTag, size_t *pcbTag);
+RTDECL(int) RTCrCipherDecryptEx(RTCRCIPHER hCipher, void const *pvKey, size_t cbKey,
+ void const *pvInitVector, size_t cbInitVector,
+ void const *pvAuthData, size_t cbAuthData,
+ void *pvTag, size_t cbTag,
+ void const *pvEncrypted, size_t cbEncrypted,
+ void *pvPlainText, size_t cbPlainText, size_t *pcbPlainText);
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_crypto_cipher_h */
+
diff --git a/include/iprt/crypto/digest.h b/include/iprt/crypto/digest.h
new file mode 100644
index 00000000..bdf3698a
--- /dev/null
+++ b/include/iprt/crypto/digest.h
@@ -0,0 +1,331 @@
+/** @file
+ * IPRT - Crypto - Cryptographic Hash / Message Digest.
+ */
+
+/*
+ * Copyright (C) 2014-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_crypto_digest_h
+#define IPRT_INCLUDED_crypto_digest_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/asn1.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_crdigest RTCrDigest - Crypographic Hash / Message Digest API.
+ * @ingroup grp_rt
+ * @{
+ */
+
+/**
+ * Cryptographic hash / message digest provider descriptor.
+ *
+ * This gives the basic details and identifiers of the algorithm as well as
+ * function pointers to the implementation.
+ */
+typedef struct RTCRDIGESTDESC
+{
+ /** The message digest provider name. */
+ const char *pszName;
+ /** The object ID string. */
+ const char *pszObjId;
+ /** Pointer to a NULL terminated table of alias object IDs (optional). */
+ const char * const *papszObjIdAliases;
+ /** The IPRT digest type. */
+ RTDIGESTTYPE enmType;
+ /** The max size of the final hash (binary). */
+ uint32_t cbHash;
+ /** The size of the state. */
+ uint32_t cbState;
+ /** Flags, RTCRDIGESTDESC_F_XXX. */
+ uint32_t fFlags;
+
+ /**
+ * Allocates the digest data.
+ */
+ DECLCALLBACKMEMBER(void *, pfnNew,(void));
+
+ /**
+ * Frees the digest data.
+ *
+ * @param pvState The opaque message digest state.
+ */
+ DECLCALLBACKMEMBER(void, pfnFree,(void *pvState));
+
+ /**
+ * Updates the digest with more data.
+ *
+ * @param pvState The opaque message digest state.
+ * @param pvData The data to add to the digest.
+ * @param cbData The amount of data to add to the digest.
+ */
+ DECLCALLBACKMEMBER(void, pfnUpdate,(void *pvState, const void *pvData, size_t cbData));
+
+ /**
+ * Finalizes the digest calculation.
+ *
+ * @param pvState The opaque message digest state.
+ * @param pbHash Where to store the output digest. This buffer is at
+ * least RTCRDIGESTDESC::cbHash bytes large.
+ */
+ DECLCALLBACKMEMBER(void, pfnFinal,(void *pvState, uint8_t *pbHash));
+
+ /**
+ * (Re-)Initializes the digest. Optional.
+ *
+ * Optional, RT_BZERO will be used if NULL.
+ *
+ * @returns IPRT status code.
+ * @param pvState The opaque message digest state.
+ * @param pvOpaque Opaque algortihm specific parameter.
+ * @param fReInit Set if this is a re-init call.
+ */
+ DECLCALLBACKMEMBER(int, pfnInit,(void *pvState, void *pvOpaque, bool fReInit));
+
+ /**
+ * Deletes the message digest state.
+ *
+ * Optional, memset will be used if NULL.
+ *
+ * @param pvState The opaque message digest state.
+ */
+ DECLCALLBACKMEMBER(void, pfnDelete,(void *pvState));
+
+ /**
+ * Clones the message digest state.
+ *
+ * Optional, memcpy will be used if NULL.
+ *
+ * @returns IPRT status code.
+ * @param pvState The opaque message digest state (destination).
+ * @param pvSrcState The opaque message digest state to clone (source).
+ */
+ DECLCALLBACKMEMBER(int, pfnClone,(void *pvState, void const *pvSrcState));
+
+ /**
+ * Gets the hash size.
+ *
+ * Optional, if not provided RTCRDIGESTDESC::cbHash will be returned. If
+ * provided though, RTCRDIGESTDESC::cbHash must be set to the largest possible
+ * hash size.
+ *
+ * @returns The hash size.
+ * @param pvState The opaque message digest state.
+ */
+ DECLCALLBACKMEMBER(uint32_t, pfnGetHashSize,(void *pvState));
+
+ /**
+ * Gets the digest type (when enmType is RTDIGESTTYPE_UNKNOWN).
+ *
+ * @returns The hash size.
+ * @param pvState The opaque message digest state.
+ */
+ DECLCALLBACKMEMBER(RTDIGESTTYPE, pfnGetDigestType,(void *pvState));
+} RTCRDIGESTDESC;
+/** Pointer to const message digest details and vtable. */
+typedef RTCRDIGESTDESC const *PCRTCRDIGESTDESC;
+
+/** @name RTCRDIGESTDESC_F_XXX
+ * @{ */
+/** Digest is deprecated. */
+#define RTCRDIGESTDESC_F_DEPRECATED RT_BIT_32(0)
+/** Digest is compromised. */
+#define RTCRDIGESTDESC_F_COMPROMISED RT_BIT_32(1)
+/** Digest is severely compromised. */
+#define RTCRDIGESTDESC_F_SERVERELY_COMPROMISED RT_BIT_32(2)
+/** @} */
+
+/**
+ * Finds a cryptographic hash / message digest descriptor by object identifier
+ * string.
+ *
+ * @returns Pointer to the message digest details & vtable if found. NULL if
+ * not found.
+ * @param pszObjId The dotted object identifier string of the message
+ * digest algorithm.
+ * @param ppvOpaque Where to return an opaque implementation specfici
+ * sub-type indicator that can be passed to
+ * RTCrDigestCreate. This is optional, fewer
+ * algortihms are available if not specified.
+ */
+RTDECL(PCRTCRDIGESTDESC) RTCrDigestFindByObjIdString(const char *pszObjId, void **ppvOpaque);
+
+/**
+ * Finds a cryptographic hash / message digest descriptor by object identifier
+ * ASN.1 object.
+ *
+ * @returns Pointer to the message digest details & vtable if found. NULL if
+ * not found.
+ * @param pObjId The ASN.1 object ID of the message digest algorithm.
+ * @param ppvOpaque Where to return an opaque implementation specfici
+ * sub-type indicator that can be passed to
+ * RTCrDigestCreate. This is optional, fewer
+ * algortihms are available if not specified.
+ */
+RTDECL(PCRTCRDIGESTDESC) RTCrDigestFindByObjId(PCRTASN1OBJID pObjId, void **ppvOpaque);
+
+RTDECL(PCRTCRDIGESTDESC) RTCrDigestFindByType(RTDIGESTTYPE enmDigestType);
+RTDECL(int) RTCrDigestCreateByObjIdString(PRTCRDIGEST phDigest, const char *pszObjId);
+RTDECL(int) RTCrDigestCreateByObjId(PRTCRDIGEST phDigest, PCRTASN1OBJID pObjId);
+RTDECL(int) RTCrDigestCreateByType(PRTCRDIGEST phDigest, RTDIGESTTYPE enmDigestType);
+
+
+/**
+ * @returns IPRT status code.
+ * @retval VINF_SUCCESS on success.
+ * @retval VINF_CR_DIGEST_DEPRECATED on success from a deprecated hash algorithm.
+ * @retval VINF_CR_DIGEST_COMPROMISED on success from a compromised hash algorithm.
+ * @retval VINF_CR_DIGEST_SEVERELY_COMPROMISED on success from a severely compromised hash algorithm.
+ */
+RTDECL(int) RTCrDigestCreate(PRTCRDIGEST phDigest, PCRTCRDIGESTDESC pDesc, void *pvOpaque);
+/**
+ * @returns IPRT status code.
+ * @retval VINF_SUCCESS on success.
+ * @retval VINF_CR_DIGEST_DEPRECATED on success from a deprecated hash algorithm.
+ * @retval VINF_CR_DIGEST_COMPROMISED on success from a compromised hash algorithm.
+ * @retval VINF_CR_DIGEST_SEVERELY_COMPROMISED on success from a severely compromised hash algorithm.
+ */
+RTDECL(int) RTCrDigestClone(PRTCRDIGEST phDigest, RTCRDIGEST hSrc);
+/**
+ * Resets the digest to start calculating a new digest.
+ */
+RTDECL(int) RTCrDigestReset(RTCRDIGEST hDigest);
+
+/**
+ * Retains a references to the digest.
+ *
+ * @returns New reference count. UINT32_MAX if invalid handle.
+ * @param hDigest Handle to the digest.
+ */
+RTDECL(uint32_t) RTCrDigestRetain(RTCRDIGEST hDigest);
+/**
+ * Releases a references to the digest.
+ *
+ * @returns New reference count. UINT32_MAX if invalid handle.
+ * @param hDigest Handle to the digest. NIL is ignored (returns 0).
+ */
+RTDECL(uint32_t) RTCrDigestRelease(RTCRDIGEST hDigest);
+
+/**
+ * Updates the digest with more message data.
+ *
+ * @returns IPRT status code.
+ * @param hDigest Handle to the digest.
+ * @param pvData Pointer to the message data.
+ * @param cbData The number of bytes of data @a pvData points to.
+ */
+RTDECL(int) RTCrDigestUpdate(RTCRDIGEST hDigest, void const *pvData, size_t cbData);
+
+/**
+ * Updates the digest with more message data from the given VFS file handle.
+ *
+ * @returns IPRT status code.
+ * @param hDigest Handle to the digest.
+ * @param hVfsFile Handle to the VFS file.
+ * @param fRewindFile Rewind to the start of the file if @a true, start
+ * consumption at the current file position if @a false.
+ */
+RTDECL(int) RTCrDigestUpdateFromVfsFile(RTCRDIGEST hDigest, RTVFSFILE hVfsFile, bool fRewindFile);
+
+/**
+ * Finalizes the hash calculation, copying out the resulting hash value.
+ *
+ * This can be called more than once and will always return the same result.
+ *
+ * @returns IPRT status code.
+ * @retval VINF_SUCCESS on success.
+ * @retval VINF_CR_DIGEST_DEPRECATED on success from a deprecated hash algorithm.
+ * @retval VINF_CR_DIGEST_COMPROMISED on success from a compromised hash algorithm.
+ * @retval VINF_CR_DIGEST_SEVERELY_COMPROMISED on success from a severely compromised hash algorithm.
+ * @retval VINF_BUFFER_UNDERFLOW if the supplied buffer is too big.
+ * @retval VERR_BUFFER_OVERFLOW if the supplied buffer is too small.
+ * @retval VERR_INVALID_STATE if there is nothing to finalize.
+ *
+ * @param hDigest The digest handle.
+ * @param pvHash Where to return the hash. Optional.
+ * @param cbHash The hash size. Optional.
+ */
+RTDECL(int) RTCrDigestFinal(RTCRDIGEST hDigest, void *pvHash, size_t cbHash);
+
+RTDECL(bool) RTCrDigestMatch(RTCRDIGEST hDigest, void const *pvHash, size_t cbHash);
+RTDECL(uint8_t const *) RTCrDigestGetHash(RTCRDIGEST hDigest);
+RTDECL(uint32_t) RTCrDigestGetHashSize(RTCRDIGEST hDigest);
+RTDECL(uint64_t) RTCrDigestGetConsumedSize(RTCRDIGEST hDigest);
+RTDECL(bool) RTCrDigestIsFinalized(RTCRDIGEST hDigest);
+RTDECL(RTDIGESTTYPE) RTCrDigestGetType(RTCRDIGEST hDigest);
+RTDECL(const char *) RTCrDigestGetAlgorithmOid(RTCRDIGEST hDigest);
+
+/**
+ * Gets the flags for the algorithm.
+ *
+ * @returns RTCRDIGESTDESC_F_XXX, UINT32_MAX on invalid handle.
+ * @param hDigest The digest handle.
+ */
+RTDECL(uint32_t) RTCrDigestGetFlags(RTCRDIGEST hDigest);
+
+
+/**
+ * Translates an IPRT digest type value to an OID.
+ *
+ * @returns Dotted OID string on success, NULL if not translatable.
+ * @param enmDigestType The IPRT digest type value to convert.
+ */
+RTDECL(const char *) RTCrDigestTypeToAlgorithmOid(RTDIGESTTYPE enmDigestType);
+
+/**
+ * Translates an IPRT digest type value to a name/descriptive string.
+ *
+ * The purpose here is for human readable output rather than machine readable
+ * output, i.e. the names aren't set in stone.
+ *
+ * @returns Pointer to read-only string, NULL if unknown type.
+ * @param enmDigestType The IPRT digest type value to convert.
+ */
+RTDECL(const char *) RTCrDigestTypeToName(RTDIGESTTYPE enmDigestType);
+
+/**
+ * Translates an IPRT digest type value to a hash size.
+ *
+ * @returns Hash size (in bytes).
+ * @param enmDigestType The IPRT digest type value to convert.
+ */
+RTDECL(uint32_t) RTCrDigestTypeToHashSize(RTDIGESTTYPE enmDigestType);
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_crypto_digest_h */
+
diff --git a/include/iprt/crypto/key.h b/include/iprt/crypto/key.h
new file mode 100644
index 00000000..a58d8ee6
--- /dev/null
+++ b/include/iprt/crypto/key.h
@@ -0,0 +1,126 @@
+/** @file
+ * IPRT - Cryptographic Keys
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_crypto_key_h
+#define IPRT_INCLUDED_crypto_key_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/crypto/x509.h>
+#include <iprt/crypto/taf.h>
+#include <iprt/sha.h>
+
+
+RT_C_DECLS_BEGIN
+
+struct RTCRPEMSECTION;
+struct RTCRX509SUBJECTPUBLICKEYINFO;
+
+/** @defgroup grp_rt_crkey RTCrKey - Crypotgraphic Keys.
+ * @ingroup grp_rt_crypto
+ * @{
+ */
+
+/**
+ * Key types.
+ */
+typedef enum RTCRKEYTYPE
+{
+ /** Invalid zero value. */
+ RTCRKEYTYPE_INVALID = 0,
+ /** RSA private key. */
+ RTCRKEYTYPE_RSA_PRIVATE,
+ /** RSA public key. */
+ RTCRKEYTYPE_RSA_PUBLIC,
+ /** End of key types. */
+ RTCRKEYTYPE_END,
+ /** The usual type size hack. */
+ RTCRKEYTYPE_32BIT_HACK = 0x7fffffff
+} RTCRKEYTYPE;
+
+
+RTDECL(int) RTCrKeyCreateFromSubjectPublicKeyInfo(PRTCRKEY phKey, struct RTCRX509SUBJECTPUBLICKEYINFO const *pSrc,
+ PRTERRINFO pErrInfo, const char *pszErrorTag);
+RTDECL(int) RTCrKeyCreateFromPublicAlgorithmAndBits(PRTCRKEY phKey, PCRTASN1OBJID pAlgorithm,
+ PCRTASN1BITSTRING pPublicKey,
+ PRTERRINFO pErrInfo, const char *pszErrorTag);
+RTDECL(int) RTCrKeyCreateFromPemSection(PRTCRKEY phKey, uint32_t fFlags, struct RTCRPEMSECTION const *pSection,
+ const char *pszPassword, PRTERRINFO pErrInfo, const char *pszErrorTag);
+RTDECL(int) RTCrKeyCreateFromBuffer(PRTCRKEY phKey, uint32_t fFlags, void const *pvSrc, size_t cbSrc,
+ const char *pszPassword, PRTERRINFO pErrInfo, const char *pszErrorTag);
+RTDECL(int) RTCrKeyCreateFromFile(PRTCRKEY phKey, uint32_t fFlags, const char *pszFilename,
+ const char *pszPassword, PRTERRINFO pErrInfo);
+/** @todo add support for decrypting private keys. */
+/** @name RTCRKEYFROM_F_XXX
+ * @{ */
+/** Only PEM sections, no binary fallback.
+ * @sa RTCRPEMREADFILE_F_ONLY_PEM */
+#define RTCRKEYFROM_F_ONLY_PEM RT_BIT(1)
+/** Valid flags. */
+#define RTCRKEYFROM_F_VALID_MASK UINT32_C(0x00000002)
+/** @} */
+
+RTDECL(int) RTCrKeyCreateNewRsa(PRTCRKEY phKey, uint32_t cBits, uint32_t uPubExp, uint32_t fFlags);
+
+
+RTDECL(uint32_t) RTCrKeyRetain(RTCRKEY hKey);
+RTDECL(uint32_t) RTCrKeyRelease(RTCRKEY hKey);
+RTDECL(RTCRKEYTYPE) RTCrKeyGetType(RTCRKEY hKey);
+RTDECL(bool) RTCrKeyHasPrivatePart(RTCRKEY hKey);
+RTDECL(bool) RTCrKeyHasPublicPart(RTCRKEY hKey);
+RTDECL(uint32_t) RTCrKeyGetBitCount(RTCRKEY hKey);
+RTDECL(int) RTCrKeyQueryRsaModulus(RTCRKEY hKey, PRTBIGNUM pModulus);
+RTDECL(int) RTCrKeyQueryRsaPrivateExponent(RTCRKEY hKey, PRTBIGNUM pPrivateExponent);
+
+/** Public key markers. */
+extern RT_DECL_DATA_CONST(RTCRPEMMARKER const) g_aRTCrKeyPublicMarkers[];
+/** Number of entries in g_aRTCrKeyPublicMarkers. */
+extern RT_DECL_DATA_CONST(uint32_t const) g_cRTCrKeyPublicMarkers;
+/** Private key markers. */
+extern RT_DECL_DATA_CONST(RTCRPEMMARKER const) g_aRTCrKeyPrivateMarkers[];
+/** Number of entries in g_aRTCrKeyPrivateMarkers. */
+extern RT_DECL_DATA_CONST(uint32_t const) g_cRTCrKeyPrivateMarkers;
+/** Private and public key markers. */
+extern RT_DECL_DATA_CONST(RTCRPEMMARKER const) g_aRTCrKeyAllMarkers[];
+/** Number of entries in g_aRTCrKeyAllMarkers. */
+extern RT_DECL_DATA_CONST(uint32_t const) g_cRTCrKeyAllMarkers;
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_crypto_key_h */
+
diff --git a/include/iprt/crypto/misc.h b/include/iprt/crypto/misc.h
new file mode 100644
index 00000000..bc4419fd
--- /dev/null
+++ b/include/iprt/crypto/misc.h
@@ -0,0 +1,76 @@
+/** @file
+ * IPRT - Crypto - Miscellaneous.
+ */
+
+/*
+ * Copyright (C) 2018-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_crypto_misc_h
+#define IPRT_INCLUDED_crypto_misc_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_crmisc RTCrMisc - Miscellaneous
+ * @ingroup grp_rt_crypto
+ * @{
+ */
+
+/**
+ * Get cryptographically strong random bytes.
+ *
+ * The buffer will always be filled with random bytes, however only
+ * on @c VINF_SUCCESS is it guaranteed to be strong random bytes.
+ *
+ * @retval VINF_SUCCESS
+ * @retval VERR_CR_RANDOM_FAILED if insufficient strong random bytes or some similar failure.
+ * @retval VERR_CR_RANDOM_SETUP_FAILED if setting up strong random failed
+ * and no strong bytes returned.
+ *
+ * @param pvDst Where to return the random bytes.
+ * @param cbDst How many random bytes to return.
+ */
+RTDECL(int) RTCrRandBytes(void *pvDst, size_t cbDst);
+
+RTDECL(int) RTCrPkcs5Pbkdf2Hmac(void const *pvInput, size_t cbInput, void const *pvSalt, size_t cbSalt, uint32_t cIterations,
+ RTDIGESTTYPE enmDigestType, size_t cbKeyLen, void *pvOutput);
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_crypto_misc_h */
+
diff --git a/include/iprt/crypto/pem.h b/include/iprt/crypto/pem.h
new file mode 100644
index 00000000..c36bc587
--- /dev/null
+++ b/include/iprt/crypto/pem.h
@@ -0,0 +1,304 @@
+/** @file
+ * IPRT - Crypto - PEM-file Reader & Writer.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_crypto_pem_h
+#define IPRT_INCLUDED_crypto_pem_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+#include <iprt/asn1.h> /* PRTASN1CORE */
+#include <iprt/string.h> /* PFNRTSTROUTPUT */
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_spc RTCrPem - PEM-file Reader & Writer
+ * @ingroup grp_rt_crypto
+ * @{
+ */
+
+
+/**
+ * One PEM marker word (use RT_STR_TUPLE to initialize).
+ */
+typedef struct RTCRPEMMARKERWORD
+{
+ /** The word string. */
+ const char *pszWord;
+ /** The length. */
+ uint32_t cchWord;
+} RTCRPEMMARKERWORD;
+/** Pointer to a const marker word. */
+typedef RTCRPEMMARKERWORD const *PCRTCRPEMMARKERWORD;
+
+
+/**
+ * A PEM marker.
+ *
+ * This is an array of words with lengths, optimized for avoid unnecessary
+ * strlen() while searching the file content. It is ASSUMED that all PEM
+ * section markers starts with either 'BEGIN' or 'END', followed by the words
+ * in the this structure.
+ */
+typedef struct RTCRPEMMARKER
+{
+ /** Pointer to an array of marker words. */
+ PCRTCRPEMMARKERWORD paWords;
+ /** Number of works in the array papszWords points to. */
+ uint32_t cWords;
+} RTCRPEMMARKER;
+/** Pointer to a const PEM marker. */
+typedef RTCRPEMMARKER const *PCRTCRPEMMARKER;
+
+
+/**
+ * A PEM field.
+ */
+typedef struct RTCRPEMFIELD
+{
+ /** Pointer to the next field. */
+ struct RTCRPEMFIELD const *pNext;
+ /** The field value. */
+ char const *pszValue;
+ /** The field value length. */
+ size_t cchValue;
+ /** The field name length. */
+ size_t cchName;
+ /** The field name. */
+ RT_FLEXIBLE_ARRAY_EXTENSION
+ char szName[RT_FLEXIBLE_ARRAY];
+} RTCRPEMFIELD;
+/** Pointer to a PEM field. */
+typedef RTCRPEMFIELD *PRTCRPEMFIELD;
+/** Pointer to a const PEM field. */
+typedef RTCRPEMFIELD const *PCRTCRPEMFIELD;
+
+
+/**
+ * A PEM section.
+ *
+ * The API works on linked lists of these.
+ */
+typedef struct RTCRPEMSECTION
+{
+ /** Pointer to the next file section. */
+ struct RTCRPEMSECTION const *pNext;
+ /** The marker for this section. NULL if binary file. */
+ PCRTCRPEMMARKER pMarker;
+ /** Pointer to the binary data. */
+ uint8_t *pbData;
+ /** The size of the binary data. */
+ size_t cbData;
+ /** List of fields, NULL if none. */
+ PCRTCRPEMFIELD pFieldHead;
+ /** Set if RTCRPEMREADFILE_F_SENSITIVE was specified. */
+ bool fSensitive;
+} RTCRPEMSECTION;
+/** Pointer to a PEM section. */
+typedef RTCRPEMSECTION *PRTCRPEMSECTION;
+/** Pointer to a const PEM section. */
+typedef RTCRPEMSECTION const *PCRTCRPEMSECTION;
+
+
+/**
+ * Frees sections returned by RTCrPemReadFile and RTCrPemParseContent.
+ * @returns IPRT status code.
+ * @param pSectionHead The first section.
+ */
+RTDECL(int) RTCrPemFreeSections(PCRTCRPEMSECTION pSectionHead);
+
+/**
+ * Parses the given data and returns a list of binary sections.
+ *
+ * If the file isn't an ASCII file or if no markers were found, the entire file
+ * content is returned as one single section (with pMarker = NULL).
+ *
+ * @returns IPRT status code.
+ * @retval VINF_EOF if the file is empty. The @a ppSectionHead value will be
+ * NULL.
+ * @retval VWRN_NOT_FOUND no section was found and RTCRPEMREADFILE_F_ONLY_PEM
+ * is specified. The @a ppSectionHead value will be NULL.
+ *
+ * @param pvContent The content bytes to parse.
+ * @param cbContent The number of content bytes.
+ * @param fFlags RTCRPEMREADFILE_F_XXX.
+ * @param paMarkers Array of one or more section markers to look for.
+ * @param cMarkers Number of markers in the array.
+ * @param ppSectionHead Where to return the head of the section list. Call
+ * RTCrPemFreeSections to free.
+ * @param pErrInfo Where to return extend error info. Optional.
+ */
+RTDECL(int) RTCrPemParseContent(void const *pvContent, size_t cbContent, uint32_t fFlags,
+ PCRTCRPEMMARKER paMarkers, size_t cMarkers, PCRTCRPEMSECTION *ppSectionHead, PRTERRINFO pErrInfo);
+
+/**
+ * Reads the content of the given file and returns a list of binary sections
+ * found in the file.
+ *
+ * If the file isn't an ASCII file or if no markers were found, the entire file
+ * content is returned as one single section (with pMarker = NULL).
+ *
+ * @returns IPRT status code.
+ * @retval VINF_EOF if the file is empty. The @a ppSectionHead value will be
+ * NULL.
+ * @retval VWRN_NOT_FOUND no section was found and RTCRPEMREADFILE_F_ONLY_PEM
+ * is specified. The @a ppSectionHead value will be NULL.
+ *
+ * @param pszFilename The path to the file to read.
+ * @param fFlags RTCRPEMREADFILE_F_XXX.
+ * @param paMarkers Array of one or more section markers to look for.
+ * @param cMarkers Number of markers in the array.
+ * @param ppSectionHead Where to return the head of the section list. Call
+ * RTCrPemFreeSections to free.
+ * @param pErrInfo Where to return extend error info. Optional.
+ */
+RTDECL(int) RTCrPemReadFile(const char *pszFilename, uint32_t fFlags, PCRTCRPEMMARKER paMarkers, size_t cMarkers,
+ PCRTCRPEMSECTION *ppSectionHead, PRTERRINFO pErrInfo);
+/** @name RTCRPEMREADFILE_F_XXX - Flags for RTCrPemReadFile and
+ * RTCrPemParseContent.
+ * @{ */
+/** Continue on encoding error. */
+#define RTCRPEMREADFILE_F_CONTINUE_ON_ENCODING_ERROR RT_BIT(0)
+/** Only PEM sections, no binary fallback. */
+#define RTCRPEMREADFILE_F_ONLY_PEM RT_BIT(1)
+/** Sensitive data, use the safer allocator. */
+#define RTCRPEMREADFILE_F_SENSITIVE RT_BIT(2)
+/** Valid flags. */
+#define RTCRPEMREADFILE_F_VALID_MASK UINT32_C(0x00000007)
+/** @} */
+
+/**
+ * Finds the beginning of first PEM section using the specified markers.
+ *
+ * This will not look any further than the first section. Nor will it check for
+ * binaries.
+ *
+ * @returns Pointer to the "-----BEGIN XXXX" sequence on success.
+ * NULL if not found.
+ * @param pvContent The content bytes to parse.
+ * @param cbContent The number of content bytes.
+ * @param paMarkers Array of one or more section markers to look for.
+ * @param cMarkers Number of markers in the array.
+ */
+RTDECL(const char *) RTCrPemFindFirstSectionInContent(void const *pvContent, size_t cbContent,
+ PCRTCRPEMMARKER paMarkers, size_t cMarkers);
+
+
+/**
+ * PEM formatter for a binary data blob.
+ *
+ * @returns Number of output bytes (sum of @a pfnOutput return values).
+ * @param pfnOutput The output callback function.
+ * @param pvUser The user argument to the output callback.
+ * @param pvContent The binary blob to output.
+ * @param cbContent Size of the binary blob.
+ * @param pszMarker The PEM marker, .e.g "PRIVATE KEY", "CERTIFICATE" or
+ * similar.
+ * @sa RTCrPemWriteAsn1, RTCrPemWriteAsn1ToVfsFile,
+ * RTCrPemWriteAsn1ToVfsFile
+ */
+RTDECL(size_t) RTCrPemWriteBlob(PFNRTSTROUTPUT pfnOutput, void *pvUser,
+ const void *pvContent, size_t cbContent, const char *pszMarker);
+
+RTDECL(ssize_t) RTCrPemWriteBlobToVfsIoStrm(RTVFSIOSTREAM hVfsIos, const void *pvContent, size_t cbContent, const char *pszMarker);
+RTDECL(ssize_t) RTCrPemWriteBlobToVfsFile(RTVFSFILE hVfsFile, const void *pvContent, size_t cbContent, const char *pszMarker);
+
+/**
+ * PEM formatter for a generic ASN.1 structure.
+ *
+ * This will call both RTAsn1EncodePrepare() and RTAsn1EncodeWrite() on
+ * @a pRoot. Uses DER encoding.
+ *
+ * @returns Number of outputted chars (sum of @a pfnOutput return values),
+ * negative values are error status codes from the ASN.1 encoding.
+ * @param pfnOutput The output callback function.
+ * @param pvUser The user argument to the output callback.
+ * @param fFlags Reserved, MBZ.
+ * @param pRoot The root of the ASN.1 to encode and format as PEM.
+ * @param pszMarker The PEM marker, .e.g "PRIVATE KEY", "CERTIFICATE" or
+ * similar.
+ * @param pErrInfo For encoding errors. Optional.
+ * @sa RTCrPemWriteAsn1ToVfsFile, RTCrPemWriteAsn1ToVfsFile,
+ * RTCrPemWriteBlob
+ */
+RTDECL(ssize_t) RTCrPemWriteAsn1(PFNRTSTROUTPUT pfnOutput, void *pvUser, PRTASN1CORE pRoot,
+ uint32_t fFlags, const char *pszMarker, PRTERRINFO pErrInfo);
+
+/**
+ * PEM formatter for a generic ASN.1 structure and output it to @a hVfsIos.
+ *
+ * This will call both RTAsn1EncodePrepare() and RTAsn1EncodeWrite() on
+ * @a pRoot. Uses DER encoding.
+ *
+ * @returns Number of chars written, negative values are error status codes from
+ * the ASN.1 encoding or from RTVfsIoStrmWrite().
+ * @param hVfsIos Handle to the I/O stream to write it to.
+ * @param fFlags Reserved, MBZ.
+ * @param pRoot The root of the ASN.1 to encode and format as PEM.
+ * @param pszMarker The PEM marker, .e.g "PRIVATE KEY", "CERTIFICATE" or
+ * similar.
+ * @param pErrInfo For encoding errors. Optional.
+ * @sa RTCrPemWriteAsn1ToVfsFile, RTCrPemWriteAsn1, RTCrPemWriteBlob
+ */
+RTDECL(ssize_t) RTCrPemWriteAsn1ToVfsIoStrm(RTVFSIOSTREAM hVfsIos, PRTASN1CORE pRoot,
+ uint32_t fFlags, const char *pszMarker, PRTERRINFO pErrInfo);
+
+/**
+ * PEM formatter for a generic ASN.1 structure and output it to @a hVfsFile.
+ *
+ * This will call both RTAsn1EncodePrepare() and RTAsn1EncodeWrite() on
+ * @a pRoot. Uses DER encoding.
+ *
+ * @returns Number of chars written, negative values are error status codes from
+ * the ASN.1 encoding or from RTVfsIoStrmWrite().
+ * @param hVfsFile Handle to the file to write it to.
+ * @param fFlags Reserved, MBZ.
+ * @param pRoot The root of the ASN.1 to encode and format as PEM.
+ * @param pszMarker The PEM marker, .e.g "PRIVATE KEY", "CERTIFICATE" or
+ * similar.
+ * @param pErrInfo For encoding errors. Optional.
+ * @sa RTCrPemWriteAsn1ToVfsIoStrm, RTCrPemWriteAsn1, RTCrPemWriteBlob
+ */
+RTDECL(ssize_t) RTCrPemWriteAsn1ToVfsFile(RTVFSFILE hVfsFile, PRTASN1CORE pRoot,
+ uint32_t fFlags, const char *pszMarker, PRTERRINFO pErrInfo);
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_crypto_pem_h */
+
diff --git a/include/iprt/crypto/pkcs7.h b/include/iprt/crypto/pkcs7.h
new file mode 100644
index 00000000..2bc3f950
--- /dev/null
+++ b/include/iprt/crypto/pkcs7.h
@@ -0,0 +1,709 @@
+/** @file
+ * IPRT - PKCS \#7, Cryptographic Message Syntax Standard (aka CMS).
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_crypto_pkcs7_h
+#define IPRT_INCLUDED_crypto_pkcs7_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/asn1.h>
+#include <iprt/crypto/x509.h>
+
+
+RT_C_DECLS_BEGIN
+
+struct RTCRPKCS7CONTENTINFO;
+
+
+/** @defgroup grp_rt_crpkcs7 RTCrPkcs7 - PKCS \#7, Cryptographic Message Syntax Standard (aka CMS).
+ * @ingroup grp_rt_crypto
+ * @{
+ */
+
+/** PKCS \#7 data object ID.*/
+#define RTCR_PKCS7_DATA_OID "1.2.840.113549.1.7.1"
+/** PKCS \#7 signedData object ID. */
+#define RTCR_PKCS7_SIGNED_DATA_OID "1.2.840.113549.1.7.2"
+/** PKCS \#7 envelopedData object ID. */
+#define RTCR_PKCS7_ENVELOPED_DATA_OID "1.2.840.113549.1.7.3"
+/** PKCS \#7 signedAndEnvelopedData object ID. */
+#define RTCR_PKCS7_SIGNED_AND_ENVELOPED_DATA_OID "1.2.840.113549.1.7.4"
+/** PKCS \#7 digestedData object ID. */
+#define RTCR_PKCS7_DIGESTED_DATA_OID "1.2.840.113549.1.7.5"
+/** PKCS \#7 encryptedData object ID. */
+#define RTCR_PKCS7_ENCRYPTED_DATA_OID "1.2.840.113549.1.7.6"
+
+
+/**
+ * PKCS \#7 IssuerAndSerialNumber (IPRT representation).
+ */
+typedef struct RTCRPKCS7ISSUERANDSERIALNUMBER
+{
+ /** Sequence core. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** The certificate name. */
+ RTCRX509NAME Name;
+ /** The certificate serial number. */
+ RTASN1INTEGER SerialNumber;
+} RTCRPKCS7ISSUERANDSERIALNUMBER;
+/** Pointer to the IPRT representation of a PKCS \#7 IssuerAndSerialNumber. */
+typedef RTCRPKCS7ISSUERANDSERIALNUMBER *PRTCRPKCS7ISSUERANDSERIALNUMBER;
+/** Pointer to the const IPRT representation of a PKCS \#7
+ * IssuerAndSerialNumber. */
+typedef RTCRPKCS7ISSUERANDSERIALNUMBER const *PCRTCRPKCS7ISSUERANDSERIALNUMBER;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRPKCS7ISSUERANDSERIALNUMBER, RTDECL, RTCrPkcs7IssuerAndSerialNumber, SeqCore.Asn1Core);
+
+
+/** Pointer to the IPRT representation of a PKCS \#7 SignerInfo. */
+typedef struct RTCRPKCS7SIGNERINFO *PRTCRPKCS7SIGNERINFO;
+/** Pointer to the const IPRT representation of a PKCS \#7 SignerInfo. */
+typedef struct RTCRPKCS7SIGNERINFO const *PCRTCRPKCS7SIGNERINFO;
+RTASN1_IMPL_GEN_SET_OF_TYPEDEFS_AND_PROTOS(RTCRPKCS7SIGNERINFOS, RTCRPKCS7SIGNERINFO, RTDECL, RTCrPkcs7SignerInfos);
+
+
+/**
+ * Attribute value type (for the union).
+ */
+typedef enum RTCRPKCS7ATTRIBUTETYPE
+{
+ /** Zero is invalid. */
+ RTCRPKCS7ATTRIBUTETYPE_INVALID = 0,
+ /** Not present, union is NULL. */
+ RTCRPKCS7ATTRIBUTETYPE_NOT_PRESENT,
+ /** Unknown values, pCores. */
+ RTCRPKCS7ATTRIBUTETYPE_UNKNOWN,
+ /** Object IDs, use pObjIds. */
+ RTCRPKCS7ATTRIBUTETYPE_OBJ_IDS,
+ /** Octet strings, use pOctetStrings. */
+ RTCRPKCS7ATTRIBUTETYPE_OCTET_STRINGS,
+ /** Counter signatures (PKCS \#9), use pCounterSignatures.
+ * RTCR_PKCS9_ID_COUNTER_SIGNATURE_OID - 1.2.840.113549.1.9.6. */
+ RTCRPKCS7ATTRIBUTETYPE_COUNTER_SIGNATURES,
+ /** Signing time (PKCS \#9), use pSigningTime.
+ * RTCR_PKCS9_ID_SIGNING_TIME_OID - 1.2.840.113549.1.9.5. */
+ RTCRPKCS7ATTRIBUTETYPE_SIGNING_TIME,
+ /** Microsoft timestamp info (RFC-3161) signed data, use pContentInfo.
+ * RTCR_PKCS9_ID_MS_TIMESTAMP - 1.3.6.1.4.1.311.3.3.1. */
+ RTCRPKCS7ATTRIBUTETYPE_MS_TIMESTAMP,
+ /** Microsoft nested PKCS\#7 signature (signtool /as).
+ * RTCR_PKCS9_ID_MS_NESTED_SIGNATURE - 1.3.6.1.4.1.311.2.4.1. */
+ RTCRPKCS7ATTRIBUTETYPE_MS_NESTED_SIGNATURE,
+ /** Microsoft statement type, use pObjIdSeqs.
+ * RTCR_PKCS9_ID_MS_STATEMENT_TYPE - 1.3.6.1.4.1.311.2.1.11. */
+ RTCRPKCS7ATTRIBUTETYPE_MS_STATEMENT_TYPE,
+ /** Apple plist with the all code directory digests, use pOctetStrings.
+ * RTCR_PKCS9_ID_APPLE_MULTI_CD_PLIST - 1.2.840.113635.100.9.1. */
+ RTCRPKCS7ATTRIBUTETYPE_APPLE_MULTI_CD_PLIST,
+ /** Blow the type up to 32-bits. */
+ RTCRPKCS7ATTRIBUTETYPE_32BIT_HACK = 0x7fffffff
+} RTCRPKCS7ATTRIBUTETYPE;
+
+/**
+ * PKCS \#7 Attribute (IPRT representation).
+ */
+typedef struct RTCRPKCS7ATTRIBUTE
+{
+ /** Sequence core. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** The attribute type (object ID). */
+ RTASN1OBJID Type;
+ /** The type of data found in the values union. */
+ RTCRPKCS7ATTRIBUTETYPE enmType;
+ /** Value allocation. */
+ RTASN1ALLOCATION Allocation;
+ /** Values. */
+ union
+ {
+ /** ASN.1 cores (RTCRPKCS7ATTRIBUTETYPE_UNKNOWN). */
+ PRTASN1SETOFCORES pCores;
+ /** ASN.1 object identifiers (RTCRPKCS7ATTRIBUTETYPE_OBJ_IDS). */
+ PRTASN1SETOFOBJIDS pObjIds;
+ /** Sequence of ASN.1 object identifiers (RTCRPKCS7ATTRIBUTETYPE_MS_STATEMENT_TYPE). */
+ PRTASN1SETOFOBJIDSEQS pObjIdSeqs;
+ /** ASN.1 octet strings (RTCRPKCS7ATTRIBUTETYPE_OCTET_STRINGS). */
+ PRTASN1SETOFOCTETSTRINGS pOctetStrings;
+ /** Counter signatures RTCRPKCS7ATTRIBUTETYPE_COUNTER_SIGNATURES(). */
+ PRTCRPKCS7SIGNERINFOS pCounterSignatures;
+ /** Signing time(s) (RTCRPKCS7ATTRIBUTETYPE_SIGNING_TIME). */
+ PRTASN1SETOFTIMES pSigningTime;
+ /** Microsoft timestamp (RFC-3161 signed data, RTCRPKCS7ATTRIBUTETYPE_MS_TIMESTAMP),
+ * Microsoft nested signature (RTCRPKCS7ATTRIBUTETYPE_MS_NESTED_SIGNATURE). */
+ struct RTCRPKCS7SETOFCONTENTINFOS *pContentInfos;
+ } uValues;
+} RTCRPKCS7ATTRIBUTE;
+/** Pointer to the IPRT representation of a PKCS \#7 Attribute. */
+typedef RTCRPKCS7ATTRIBUTE *PRTCRPKCS7ATTRIBUTE;
+/** Pointer to the const IPRT representation of a PKCS \#7 Attribute. */
+typedef RTCRPKCS7ATTRIBUTE const *PCRTCRPKCS7ATTRIBUTE;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRPKCS7ATTRIBUTE, RTDECL, RTCrPkcs7Attribute, SeqCore.Asn1Core);
+
+RTDECL(int) RTCrPkcs7Attribute_SetAppleMultiCdPlist(PRTCRPKCS7ATTRIBUTE pThis, PCRTASN1SETOFOCTETSTRINGS pToClone,
+ PCRTASN1ALLOCATORVTABLE pAllocator);
+RTDECL(int) RTCrPkcs7Attribute_SetContentType(PRTCRPKCS7ATTRIBUTE pThis, PCRTASN1SETOFOBJIDS pToClone,
+ PCRTASN1ALLOCATORVTABLE pAllocator);
+RTDECL(int) RTCrPkcs7Attribute_SetCounterSignatures(PRTCRPKCS7ATTRIBUTE pThis, PCRTCRPKCS7SIGNERINFOS pToClone,
+ PCRTASN1ALLOCATORVTABLE pAllocator);
+RTDECL(int) RTCrPkcs7Attribute_SetMessageDigest(PRTCRPKCS7ATTRIBUTE pThis, PCRTASN1SETOFOCTETSTRINGS pToClone,
+ PCRTASN1ALLOCATORVTABLE pAllocator);
+RTDECL(int) RTCrPkcs7Attribute_SetMsStatementType(PRTCRPKCS7ATTRIBUTE pThis, PCRTASN1SETOFOBJIDSEQS pToClone,
+ PCRTASN1ALLOCATORVTABLE pAllocator);
+RTDECL(int) RTCrPkcs7Attribute_SetMsNestedSignature(PRTCRPKCS7ATTRIBUTE pThis, struct RTCRPKCS7SETOFCONTENTINFOS const *pToClone,
+ PCRTASN1ALLOCATORVTABLE pAllocator);
+RTDECL(int) RTCrPkcs7Attribute_SetMsTimestamp(PRTCRPKCS7ATTRIBUTE pThis, struct RTCRPKCS7SETOFCONTENTINFOS const *pToClone,
+ PCRTASN1ALLOCATORVTABLE pAllocator);
+RTDECL(int) RTCrPkcs7Attribute_SetSigningTime(PRTCRPKCS7ATTRIBUTE pThis, PCRTASN1SETOFTIMES pToClone,
+ PCRTASN1ALLOCATORVTABLE pAllocator);
+
+RTASN1_IMPL_GEN_SET_OF_TYPEDEFS_AND_PROTOS(RTCRPKCS7ATTRIBUTES, RTCRPKCS7ATTRIBUTE, RTDECL, RTCrPkcs7Attributes);
+
+RTDECL(int) RTCrPkcs7Attributes_HashAttributes(PRTCRPKCS7ATTRIBUTES pAttributes, RTCRDIGEST hDigest, PRTERRINFO pErrInfo);
+
+
+/**
+ * One PKCS \#7 SignerInfo (IPRT representation).
+ */
+typedef struct RTCRPKCS7SIGNERINFO
+{
+ /** Sequence core. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** The structure version (RTCRPKCS7SIGNERINFO_V1). */
+ RTASN1INTEGER Version;
+ /** The issuer and serial number of the certificate used to produce the
+ * encrypted digest below. */
+ RTCRPKCS7ISSUERANDSERIALNUMBER IssuerAndSerialNumber;
+ /** The digest algorithm use to digest the signed content. */
+ RTCRX509ALGORITHMIDENTIFIER DigestAlgorithm;
+ /** Authenticated attributes, optional [0].
+ * @todo Check how other producers formats this. The microsoft one does not
+ * have explicit tags, but combines it with the SET OF. */
+ RTCRPKCS7ATTRIBUTES AuthenticatedAttributes;
+ /** The digest encryption algorithm use to encrypt the digest of the signed
+ * content. */
+ RTCRX509ALGORITHMIDENTIFIER DigestEncryptionAlgorithm;
+ /** The encrypted digest. */
+ RTASN1OCTETSTRING EncryptedDigest;
+ /** Unauthenticated attributes, optional [1].
+ * @todo Check how other producers formats this. The microsoft one does not
+ * have explicit tags, but combines it with the SET OF. */
+ RTCRPKCS7ATTRIBUTES UnauthenticatedAttributes;
+} RTCRPKCS7SIGNERINFO;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRPKCS7SIGNERINFO, RTDECL, RTCrPkcs7SignerInfo, SeqCore.Asn1Core);
+
+RTDECL(int) RTCrPkcs7SignerInfo_SetAuthenticatedAttributes(PRTCRPKCS7SIGNERINFO pThis, PCRTCRPKCS7ATTRIBUTES pAttributes,
+ PCRTASN1ALLOCATORVTABLE pAllocator);
+RTDECL(int) RTCrPkcs7SignerInfo_SetUnauthenticatedAttributes(PRTCRPKCS7SIGNERINFO pThis, PCRTCRPKCS7ATTRIBUTES pAttributes,
+ PCRTASN1ALLOCATORVTABLE pAllocator);
+
+/** RTCRPKCS7SIGNERINFO::Version value. */
+#define RTCRPKCS7SIGNERINFO_V1 1
+
+/** @name PKCS \#9 Attribute IDs
+ * @{ */
+/** Content type (RFC-2630 11.1).
+ * Value: Object Identifier */
+#define RTCR_PKCS9_ID_CONTENT_TYPE_OID "1.2.840.113549.1.9.3"
+/** Message digest (RFC-2630 11.2).
+ * Value: Octet string. */
+#define RTCR_PKCS9_ID_MESSAGE_DIGEST_OID "1.2.840.113549.1.9.4"
+/** Signing time (RFC-2630 11.3).
+ * Value: Octet string. */
+#define RTCR_PKCS9_ID_SIGNING_TIME_OID "1.2.840.113549.1.9.5"
+/** Counter signature (RFC-2630 11.4).
+ * Value: SignerInfo. */
+#define RTCR_PKCS9_ID_COUNTER_SIGNATURE_OID "1.2.840.113549.1.9.6"
+/** Microsoft timestamp (RTF-3161) counter signature (SignedData).
+ * @remarks This isn't defined by PKCS \#9, but lumped in here for convenience. It's actually listed as SPC by MS. */
+#define RTCR_PKCS9_ID_MS_TIMESTAMP "1.3.6.1.4.1.311.3.3.1"
+/** Microsoft nested PKCS\#7 signature.
+ * @remarks This isn't defined by PKCS \#9, but lumped in here for convenience. */
+#define RTCR_PKCS9_ID_MS_NESTED_SIGNATURE "1.3.6.1.4.1.311.2.4.1"
+/** Microsoft statement type.
+ * @remarks This isn't defined by PKCS \#9, but lumped in here for convenience. It's actually listed as SPC by MS. */
+#define RTCR_PKCS9_ID_MS_STATEMENT_TYPE "1.3.6.1.4.1.311.2.1.11"
+/** Microsoft opus info.
+ * @remarks This isn't defined by PKCS \#9, but lumped in here for convenience. It's actually listed as SPC by MS. */
+#define RTCR_PKCS9_ID_MS_SP_OPUS_INFO "1.3.6.1.4.1.311.2.1.12"
+/** Apple code signing multi-code-directory plist.
+ * @remarks This isn't defined by PKCS \#9, but lumped in here for convenience. */
+#define RTCR_PKCS9_ID_APPLE_MULTI_CD_PLIST "1.2.840.113635.100.9.1"
+/** @} */
+
+
+/**
+ * Get the (next) signing time attribute from the specfied SignerInfo or one of
+ * the immediate counter signatures.
+ *
+ * @returns Pointer to the signing time if found, NULL if not.
+ * @param pThis The SignerInfo to search.
+ * @param ppSignerInfo Pointer to variable keeping track of the
+ * enumeration, optional.
+ *
+ * If specified the input value is taken to the be
+ * SignerInfo of the previously returned signing
+ * time. The value pointed to is NULL, the
+ * search/enum restarts.
+ *
+ * On successful return this is set to the
+ * SignerInfo which we found the signing time in.
+ */
+RTDECL(PCRTASN1TIME) RTCrPkcs7SignerInfo_GetSigningTime(PCRTCRPKCS7SIGNERINFO pThis, PCRTCRPKCS7SIGNERINFO *ppSignerInfo);
+
+
+/**
+ * Get the (first) timestamp from within a Microsoft timestamp server counter
+ * signature.
+ *
+ * @returns Pointer to the signing time if found, NULL if not.
+ * @param pThis The SignerInfo to search.
+ * @param ppContentInfoRet Where to return the pointer to the counter
+ * signature, optional.
+ */
+RTDECL(PCRTASN1TIME) RTCrPkcs7SignerInfo_GetMsTimestamp(PCRTCRPKCS7SIGNERINFO pThis,
+ struct RTCRPKCS7CONTENTINFO const **ppContentInfoRet);
+
+
+
+/**
+ * PKCS \#7 ContentInfo (IPRT representation).
+ */
+typedef struct RTCRPKCS7CONTENTINFO
+{
+ /** Sequence core. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** Object ID identifying the content below. */
+ RTASN1OBJID ContentType;
+ /** Content, optional, explicit tag 0.
+ *
+ * Hack alert! This should've been an explict context tag 0 structure with a
+ * type selected according to ContentType. However, it's simpler to replace the
+ * explicit context with an OCTET STRING with implict tag 0. Then we can tag
+ * along on the encapsulation logic RTASN1OCTETSTRING provides for the dynamic
+ * inner type. The default decoder code will detect known structures as
+ * outlined in the union below, and decode the octet string content as an
+ * anonymous RTASN1CORE if not known.
+ *
+ * If the user want to decode the octet string content differently, it can do so
+ * by destroying and freeing the current encapsulated pointer, replacing it with
+ * it's own. (Of course following the RTASN1OCTETSTRING rules.) Just remember
+ * to also update the value in the union.
+ *
+ * @remarks What's signed and verified is Content.pEncapsulated->uData.pv.
+ */
+ RTASN1OCTETSTRING Content;
+ /** Pointer to the CMS octet string that's inside the Content, NULL if PKCS \#7.
+ *
+ * Hack alert! When transitioning from PKCS \#7 to CMS, the designers decided to
+ * change things and add another wrapper. This time we're talking about a real
+ * octet string, not like the one above which is really an explicit content tag.
+ * When constructing or decoding CMS content, this will be the same pointer as
+ * Content.pEncapsulated, while the union below will be holding the same pointer
+ * as pCmsContent->pEncapsulated.
+ */
+ PRTASN1OCTETSTRING pCmsContent;
+ /** Same as Content.pEncapsulated, except a choice of known types. */
+ union
+ {
+ /** ContentType is RTCRPKCS7SIGNEDDATA_OID. */
+ struct RTCRPKCS7SIGNEDDATA *pSignedData;
+ /** ContentType is RTCRSPCINDIRECTDATACONTENT_OID. */
+ struct RTCRSPCINDIRECTDATACONTENT *pIndirectDataContent;
+ /** ContentType is RTCRTSPTSTINFO_OID. */
+ struct RTCRTSPTSTINFO *pTstInfo;
+ /** Generic / Unknown / User. */
+ PRTASN1CORE pCore;
+ } u;
+} RTCRPKCS7CONTENTINFO;
+/** Pointer to the IPRT representation of a PKCS \#7 ContentInfo. */
+typedef RTCRPKCS7CONTENTINFO *PRTCRPKCS7CONTENTINFO;
+/** Pointer to the const IPRT representation of a PKCS \#7 ContentInfo. */
+typedef RTCRPKCS7CONTENTINFO const *PCRTCRPKCS7CONTENTINFO;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRPKCS7CONTENTINFO, RTDECL, RTCrPkcs7ContentInfo, SeqCore.Asn1Core);
+RTASN1_IMPL_GEN_SET_OF_TYPEDEFS_AND_PROTOS(RTCRPKCS7SETOFCONTENTINFOS, RTCRPKCS7CONTENTINFO, RTDECL, RTCrPkcs7SetOfContentInfos);
+
+RTDECL(bool) RTCrPkcs7ContentInfo_IsSignedData(PCRTCRPKCS7CONTENTINFO pThis);
+
+
+/**
+ * PKCS \#7 Certificate choice.
+ */
+typedef enum RTCRPKCS7CERTCHOICE
+{
+ RTCRPKCS7CERTCHOICE_INVALID = 0,
+ RTCRPKCS7CERTCHOICE_X509,
+ RTCRPKCS7CERTCHOICE_EXTENDED_PKCS6,
+ RTCRPKCS7CERTCHOICE_AC_V1,
+ RTCRPKCS7CERTCHOICE_AC_V2,
+ RTCRPKCS7CERTCHOICE_OTHER,
+ RTCRPKCS7CERTCHOICE_END,
+ RTCRPKCS7CERTCHOICE_32BIT_HACK = 0x7fffffff
+} RTCRPKCS7CERTCHOICE;
+
+
+/**
+ * Common representation for PKCS \#7 ExtendedCertificateOrCertificate and the
+ * CMS CertificateChoices types.
+ */
+typedef struct RTCRPKCS7CERT
+{
+ /** Dummy ASN.1 record, not encoded. */
+ RTASN1DUMMY Dummy;
+ /** The value allocation. */
+ RTASN1ALLOCATION Allocation;
+ /** The choice of value. */
+ RTCRPKCS7CERTCHOICE enmChoice;
+ /** The value union. */
+ union
+ {
+ /** Standard X.509 certificate (RTCRCMSCERTIFICATECHOICE_X509). */
+ PRTCRX509CERTIFICATE pX509Cert;
+ /** Extended PKCS \#6 certificate (RTCRCMSCERTIFICATECHOICE_EXTENDED_PKCS6). */
+ PRTASN1CORE pExtendedCert;
+ /** Attribute certificate version 1 (RTCRCMSCERTIFICATECHOICE_AC_V1). */
+ PRTASN1CORE pAcV1;
+ /** Attribute certificate version 2 (RTCRCMSCERTIFICATECHOICE_AC_V2). */
+ PRTASN1CORE pAcV2;
+ /** Other certificate (RTCRCMSCERTIFICATECHOICE_OTHER). */
+ PRTASN1CORE pOtherCert;
+ } u;
+} RTCRPKCS7CERT;
+/** Pointer to the IPRT representation of PKCS \#7 or CMS certificate. */
+typedef RTCRPKCS7CERT *PRTCRPKCS7CERT;
+/** Pointer to the const IPRT representation of PKCS \#7 or CMS certificate. */
+typedef RTCRPKCS7CERT const *PCRTCRPKCS7CERT;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRPKCS7CERT, RTDECL, RTCrPkcs7Cert, Dummy.Asn1Core);
+RTASN1_IMPL_GEN_SET_OF_TYPEDEFS_AND_PROTOS(RTCRPKCS7SETOFCERTS, RTCRPKCS7CERT, RTDECL, RTCrPkcs7SetOfCerts);
+
+RTDECL(int) RTCrPkcs7Cert_SetX509Cert(PRTCRPKCS7CERT pThis, PCRTCRX509CERTIFICATE pToClone, PCRTASN1ALLOCATORVTABLE pAllocator);
+RTDECL(int) RTCrPkcs7Cert_SetExtendedCert(PRTCRPKCS7CERT pThis, PCRTASN1CORE pToClone, PCRTASN1ALLOCATORVTABLE pAllocator);
+RTDECL(int) RTCrPkcs7Cert_SetAcV1(PRTCRPKCS7CERT pThis, PCRTASN1CORE pToClone, PCRTASN1ALLOCATORVTABLE pAllocator);
+RTDECL(int) RTCrPkcs7Cert_SetAcV2(PRTCRPKCS7CERT pThis, PCRTASN1CORE pToClone, PCRTASN1ALLOCATORVTABLE pAllocator);
+RTDECL(int) RTCrPkcs7Cert_SetOtherCert(PRTCRPKCS7CERT pThis, PCRTASN1CORE pToClone, PCRTASN1ALLOCATORVTABLE pAllocator);
+
+RTDECL(PCRTCRX509CERTIFICATE) RTCrPkcs7SetOfCerts_FindX509ByIssuerAndSerialNumber(PCRTCRPKCS7SETOFCERTS pCertificates,
+ PCRTCRX509NAME pIssuer,
+ PCRTASN1INTEGER pSerialNumber);
+
+
+/**
+ * PKCS \#7 SignedData (IPRT representation).
+ */
+typedef struct RTCRPKCS7SIGNEDDATA
+{
+ /** Sequence core. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** The structure version value (1). */
+ RTASN1INTEGER Version;
+ /** The digest algorithms that are used to signed the content (ContentInfo). */
+ RTCRX509ALGORITHMIDENTIFIERS DigestAlgorithms;
+ /** The content that's being signed. */
+ RTCRPKCS7CONTENTINFO ContentInfo;
+ /** Certificates, optional, implicit tag 0. (Required by Authenticode.) */
+ RTCRPKCS7SETOFCERTS Certificates;
+ /** Certificate revocation lists, optional, implicit tag 1.
+ * Not used by Authenticode, so currently stubbed. */
+ RTASN1CORE Crls;
+ /** Signer infos. */
+ RTCRPKCS7SIGNERINFOS SignerInfos;
+} RTCRPKCS7SIGNEDDATA;
+/** Pointer to the IPRT representation of a PKCS \#7 SignedData. */
+typedef RTCRPKCS7SIGNEDDATA *PRTCRPKCS7SIGNEDDATA;
+/** Pointer to the const IPRT representation of a PKCS \#7 SignedData. */
+typedef RTCRPKCS7SIGNEDDATA const *PCRTCRPKCS7SIGNEDDATA;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRPKCS7SIGNEDDATA, RTDECL, RTCrPkcs7SignedData, SeqCore.Asn1Core);
+RTASN1_IMPL_GEN_SET_OF_TYPEDEFS_AND_PROTOS(RTCRPKCS7SETOFSIGNEDDATA, RTCRPKCS7SIGNEDDATA, RTDECL, RTCrPkcs7SetOfSignedData);
+
+/** PKCS \#7 SignedData object ID. */
+#define RTCRPKCS7SIGNEDDATA_OID RTCR_PKCS7_SIGNED_DATA_OID
+
+/** PKCS \#7 SignedData version number 1. */
+#define RTCRPKCS7SIGNEDDATA_V1 1
+/* No version 2 seems to exist. */
+/** CMS SignedData version number 3.
+ * This should only be used if there are version 1 attribute certificates
+ * present, or if there are version 3 SignerInfo items present, or if
+ * enmcCountInfo is not id-data (RFC-5652, section 5.1). */
+#define RTCRPKCS7SIGNEDDATA_V3 3
+/** CMS SignedData version number 4.
+ * This should only be used if there are version 2 attribute certificates
+ * present (RFC-5652, section 5.1). */
+#define RTCRPKCS7SIGNEDDATA_V4 4
+/** CMS SignedData version number 5.
+ * This should only be used if there are certificates or/and CRLs of the
+ * OTHER type present (RFC-5652, section 5.1). */
+#define RTCRPKCS7SIGNEDDATA_V5 5
+
+RTDECL(int) RTCrPkcs7SignedData_SetCertificates(PRTCRPKCS7SIGNEDDATA pThis, PCRTCRPKCS7SETOFCERTS pCerts, PCRTASN1ALLOCATORVTABLE pAllocator);
+RTDECL(int) RTCrPkcs7SignedData_SetCrls(PRTCRPKCS7SIGNEDDATA pThis, PCRTASN1CORE pCerts, PCRTASN1ALLOCATORVTABLE pAllocator);
+
+/** @name RTCRPKCS7SIGNEDDATA_SANITY_F_XXX - Flags for RTPkcs7SignedDataCheckSantiy.
+ * @{ */
+/** Check for authenticode restrictions. */
+#define RTCRPKCS7SIGNEDDATA_SANITY_F_AUTHENTICODE RT_BIT_32(0)
+/** Check that all the hash algorithms are known to IPRT. */
+#define RTCRPKCS7SIGNEDDATA_SANITY_F_ONLY_KNOWN_HASH RT_BIT_32(1)
+/** Require signing certificate to be present. */
+#define RTCRPKCS7SIGNEDDATA_SANITY_F_SIGNING_CERT_PRESENT RT_BIT_32(2)
+/** @} */
+
+/** PKCS\#7/CMS (content info) markers. */
+extern RTDATADECL(RTCRPEMMARKER const) g_aRTCrPkcs7Markers[];
+/** Number of entries in g_aRTCrPkcs7Markers. */
+extern RTDATADECL(uint32_t const) g_cRTCrPkcs7Markers;
+
+/** @name Flags for RTCrPkcs7ContentInfo_ReadFromBuffer
+ * @{ */
+/** Only allow PEM certificates, not binary ones.
+ * @sa RTCRPEMREADFILE_F_ONLY_PEM */
+#define RTCRPKCS7_READ_F_PEM_ONLY RT_BIT(1)
+/** @} */
+
+RTDECL(int) RTCrPkcs7_ReadFromBuffer(PRTCRPKCS7CONTENTINFO pContentInfo, const void *pvBuf, size_t cbBuf,
+ uint32_t fFlags, PCRTASN1ALLOCATORVTABLE pAllocator,
+ bool *pfCmsLabeled, PRTERRINFO pErrInfo, const char *pszErrorTag);
+
+
+/**
+ * PKCS \#7 DigestInfo (IPRT representation).
+ */
+typedef struct RTCRPKCS7DIGESTINFO
+{
+ /** Sequence core. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** The digest algorithm use to digest the signed content. */
+ RTCRX509ALGORITHMIDENTIFIER DigestAlgorithm;
+ /** The digest. */
+ RTASN1OCTETSTRING Digest;
+} RTCRPKCS7DIGESTINFO;
+/** Pointer to the IPRT representation of a PKCS \#7 DigestInfo object. */
+typedef RTCRPKCS7DIGESTINFO *PRTCRPKCS7DIGESTINFO;
+/** Pointer to the const IPRT representation of a PKCS \#7 DigestInfo object. */
+typedef RTCRPKCS7DIGESTINFO const *PCRTCRPKCS7DIGESTINFO;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRPKCS7DIGESTINFO, RTDECL, RTCrPkcs7DigestInfo, SeqCore.Asn1Core);
+
+
+/**
+ * Callback function for use with RTCrPkcs7VerifySignedData.
+ *
+ * @returns IPRT status code.
+ * @param pCert The certificate to verify.
+ * @param hCertPaths Unless the certificate is trusted directly, this
+ * is a reference to the certificate path builder
+ * and verifier instance that we used to establish
+ * at least valid trusted path to @a pCert. The
+ * callback can use this to enforce additional
+ * certificate lineage requirements, effective
+ * policy checks and whatnot.
+ * This is NIL_RTCRX509CERTPATHS if the certificate
+ * is directly trusted.
+ * @param fFlags Mix of the RTCRPKCS7VCC_F_XXX flags.
+ * @param pvUser The user argument.
+ * @param pErrInfo Optional error info buffer.
+ */
+typedef DECLCALLBACKTYPE(int, FNRTCRPKCS7VERIFYCERTCALLBACK,(PCRTCRX509CERTIFICATE pCert, RTCRX509CERTPATHS hCertPaths,
+ uint32_t fFlags, void *pvUser, PRTERRINFO pErrInfo));
+/** Pointer to a FNRTCRPKCS7VERIFYCERTCALLBACK callback. */
+typedef FNRTCRPKCS7VERIFYCERTCALLBACK *PFNRTCRPKCS7VERIFYCERTCALLBACK;
+
+/** @name RTCRPKCS7VCC_F_XXX - Flags for FNRTCRPKCS7VERIFYCERTCALLBACK.
+ * @{ */
+/** Normal callback for a direct signatory of the signed data. */
+#define RTCRPKCS7VCC_F_SIGNED_DATA RT_BIT_32(0)
+/** Check that the signatory can be trusted for timestamps. */
+#define RTCRPKCS7VCC_F_TIMESTAMP RT_BIT_32(1)
+/** @} */
+
+/**
+ * @callback_method_impl{FNRTCRPKCS7VERIFYCERTCALLBACK,
+ * Default implementation that checks for the DigitalSignature KeyUsage bit.}
+ */
+RTDECL(int) RTCrPkcs7VerifyCertCallbackDefault(PCRTCRX509CERTIFICATE pCert, RTCRX509CERTPATHS hCertPaths, uint32_t fFlags,
+ void *pvUser, PRTERRINFO pErrInfo);
+
+/**
+ * @callback_method_impl{FNRTCRPKCS7VERIFYCERTCALLBACK,
+ * Standard code signing. Use this for Microsoft SPC.}
+ */
+RTDECL(int) RTCrPkcs7VerifyCertCallbackCodeSigning(PCRTCRX509CERTIFICATE pCert, RTCRX509CERTPATHS hCertPaths, uint32_t fFlags,
+ void *pvUser, PRTERRINFO pErrInfo);
+
+/**
+ * Verifies PKCS \#7 SignedData.
+ *
+ * For compatability with alternative crypto providers, the user must work on
+ * the top level PKCS \#7 structure instead directly on the SignedData.
+ *
+ * @returns IPRT status code.
+ * @param pContentInfo PKCS \#7 content info structure.
+ * @param fFlags RTCRPKCS7VERIFY_SD_F_XXX.
+ * @param hAdditionalCerts Store containing additional certificates to
+ * supplement those mentioned in the signed data.
+ * @param hTrustedCerts Store containing trusted certificates.
+ * @param pValidationTime The time we're supposed to validate the
+ * certificates chains at. Ignored for signatures
+ * with valid signing time attributes.
+ * When RTCRPKCS7VERIFY_SD_F_UPDATE_VALIDATION_TIME
+ * is set, this is updated to the actual validation
+ * time used.
+ * @param pfnVerifyCert Callback for checking that a certificate used
+ * for signing the data is suitable.
+ * @param pvUser User argument for the callback.
+ * @param pErrInfo Optional error info buffer.
+ * @sa RTCrPkcs7VerifySignedDataWithExternalData
+ */
+RTDECL(int) RTCrPkcs7VerifySignedData(PCRTCRPKCS7CONTENTINFO pContentInfo, uint32_t fFlags,
+ RTCRSTORE hAdditionalCerts, RTCRSTORE hTrustedCerts,
+ PCRTTIMESPEC pValidationTime, PFNRTCRPKCS7VERIFYCERTCALLBACK pfnVerifyCert, void *pvUser,
+ PRTERRINFO pErrInfo);
+
+
+/**
+ * Verifies PKCS \#7 SignedData with external data.
+ *
+ * For compatability with alternative crypto providers, the user must work on
+ * the top level PKCS \#7 structure instead directly on the SignedData.
+ *
+ * @returns IPRT status code.
+ * @param pContentInfo PKCS \#7 content info structure.
+ * @param fFlags RTCRPKCS7VERIFY_SD_F_XXX.
+ * @param hAdditionalCerts Store containing additional certificates to
+ * supplement those mentioned in the signed data.
+ * @param hTrustedCerts Store containing trusted certificates.
+ * @param pValidationTime The time we're supposed to validate the
+ * certificates chains at. Ignored for signatures
+ * with valid signing time attributes.
+ * When RTCRPKCS7VERIFY_SD_F_UPDATE_VALIDATION_TIME
+ * is set, this is updated to the actual validation
+ * time used.
+ * @param pfnVerifyCert Callback for checking that a certificate used
+ * for signing the data is suitable.
+ * @param pvUser User argument for the callback.
+ * @param pvData The signed external data.
+ * @param cbData The size of the signed external data.
+ * @param pErrInfo Optional error info buffer.
+ * @sa RTCrPkcs7VerifySignedData
+ */
+RTDECL(int) RTCrPkcs7VerifySignedDataWithExternalData(PCRTCRPKCS7CONTENTINFO pContentInfo, uint32_t fFlags,
+ RTCRSTORE hAdditionalCerts, RTCRSTORE hTrustedCerts,
+ PCRTTIMESPEC pValidationTime,
+ PFNRTCRPKCS7VERIFYCERTCALLBACK pfnVerifyCert, void *pvUser,
+ void const *pvData, size_t cbData, PRTERRINFO pErrInfo);
+
+/** @name RTCRPKCS7VERIFY_SD_F_XXX - Flags for RTCrPkcs7VerifySignedData and
+ * RTCrPkcs7VerifySignedDataWithExternalData
+ * @{ */
+/** Always use the signing time attribute if present, requiring it to be
+ * verified as valid. The default behavior is to ignore unverifiable
+ * signing time attributes and use the @a pValidationTime instead. */
+#define RTCRPKCS7VERIFY_SD_F_ALWAYS_USE_SIGNING_TIME_IF_PRESENT RT_BIT_32(0)
+/** Same as RTCRPKCS7VERIFY_SD_F_ALWAYS_USE_SIGNING_TIME_IF_PRESENT for the MS
+ * timestamp counter signatures. */
+#define RTCRPKCS7VERIFY_SD_F_ALWAYS_USE_MS_TIMESTAMP_IF_PRESENT RT_BIT_32(1)
+/** Only use signing time attributes from counter signatures. */
+#define RTCRPKCS7VERIFY_SD_F_COUNTER_SIGNATURE_SIGNING_TIME_ONLY RT_BIT_32(2)
+/** Don't validate the counter signature containing the signing time, just use
+ * it unverified. This is useful if we don't necessarily have the root
+ * certificates for the timestamp server handy, but use with great care.
+ * @sa RTCRPKCS7VERIFY_SD_F_USE_MS_TIMESTAMP_UNVERIFIED */
+#define RTCRPKCS7VERIFY_SD_F_USE_SIGNING_TIME_UNVERIFIED RT_BIT_32(3)
+/** Don't validate the MS counter signature containing the signing timestamp.
+ * @sa RTCRPKCS7VERIFY_SD_F_USE_SIGNING_TIME_UNVERIFIED */
+#define RTCRPKCS7VERIFY_SD_F_USE_MS_TIMESTAMP_UNVERIFIED RT_BIT_32(4)
+/** Do not consider timestamps in microsoft counter signatures. */
+#define RTCRPKCS7VERIFY_SD_F_IGNORE_MS_TIMESTAMP RT_BIT_32(5)
+/** The signed data requires certificates to have the timestamp extended
+ * usage bit present. This is used for recursivly verifying MS timestamp
+ * signatures. */
+#define RTCRPKCS7VERIFY_SD_F_USAGE_TIMESTAMPING RT_BIT_32(6)
+/** Skip the verification of the certificate trust paths, taking all
+ * certificates to be trustworthy. */
+#define RTCRPKCS7VERIFY_SD_F_TRUST_ALL_CERTS RT_BIT_32(7)
+/** Update @a pValidationTime with the actual validation time used.
+ * This requires RTCRPKCS7VERIFY_SD_F_HAS_SIGNER_INDEX to get a consistent
+ * result. And yeah, it unconst the parameter, which is patently ugly. */
+#define RTCRPKCS7VERIFY_SD_F_UPDATE_VALIDATION_TIME RT_BIT_32(8)
+/** Check trust anchors (@sa RTCrX509CertPathsSetTrustAnchorChecks). */
+#define RTCRPKCS7VERIFY_SD_F_CHECK_TRUST_ANCHORS RT_BIT_32(9)
+
+/** This can be used to only verify one given signer info.
+ * Max index value is 15. */
+#define RTCRPKCS7VERIFY_SD_F_SIGNER_INDEX(a_idxSignerInfo) \
+ ( RTCRPKCS7VERIFY_SD_F_HAS_SIGNER_INDEX \
+ | (((a_idxSignerInfo) & RTCRPKCS7VERIFY_SD_F_SIGNER_INDEX_MAX) << RTCRPKCS7VERIFY_SD_F_SIGNER_INDEX_SHIFT) )
+/** Has a valid value in RTCRPKCS7VERIFY_SD_F_SIGNER_INDEX_MASK. */
+#define RTCRPKCS7VERIFY_SD_F_HAS_SIGNER_INDEX RT_BIT_32(23)
+/** Signer index shift value. */
+#define RTCRPKCS7VERIFY_SD_F_SIGNER_INDEX_SHIFT 24
+/** Signer index mask. */
+#define RTCRPKCS7VERIFY_SD_F_SIGNER_INDEX_MASK UINT32_C(0x0f000000)
+/** Max signer index value (inclusive). */
+#define RTCRPKCS7VERIFY_SD_F_SIGNER_INDEX_MAX \
+ (RTCRPKCS7VERIFY_SD_F_SIGNER_INDEX_MASK >> RTCRPKCS7VERIFY_SD_F_SIGNER_INDEX_SHIFT)
+
+/** Indicates internally that we're validating a counter signature and should
+ * use different rules when checking out the authenticated attributes.
+ * @internal */
+#define RTCRPKCS7VERIFY_SD_F_COUNTER_SIGNATURE RT_BIT_32(31)
+/** @} */
+
+
+RTDECL(int) RTCrPkcs7SimpleSignSignedData(uint32_t fFlags, PCRTCRX509CERTIFICATE pSigner, RTCRKEY hPrivateKey,
+ void const *pvData, size_t cbData, RTDIGESTTYPE enmDigestType,
+ RTCRSTORE hAdditionalCerts, PCRTCRPKCS7ATTRIBUTES pAdditionalAuthenticatedAttribs,
+ void *pvResult, size_t *pcbResult, PRTERRINFO pErrInfo);
+
+/** @name RTCRPKCS7SIGN_SD_F_XXX - Flags for RTCrPkcs7SimpleSign.
+ * @{ */
+/** Detached data. */
+#define RTCRPKCS7SIGN_SD_F_DEATCHED RT_BIT_32(0)
+/** No SMIME capabilities attribute. */
+#define RTCRPKCS7SIGN_SD_F_NO_SMIME_CAP RT_BIT_32(1)
+/** Produce version 1 output (PKCS\#7), rather than version 3 (CMS). */
+#define RTCRPKCS7SIGN_SD_F_USE_V1 RT_BIT_32(2)
+/** Avoid extra OCTET STRING encapsulation around the data blob.
+ * This is needed for Authenticode signatures. This requires that the
+ * content type is supplied via the additional authenticated attributes.
+ * @note Currently only works with RTCRPKCS7SIGN_SD_F_USE_V1. */
+#define RTCRPKCS7SIGN_SD_F_NO_DATA_ENCAP RT_BIT_32(3)
+/** Valid flag mask. */
+#define RTCRPKCS7SIGN_SD_F_VALID_MASK UINT32_C(0x0000000f)
+/** @} */
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_crypto_pkcs7_h */
+
diff --git a/include/iprt/crypto/pkix.h b/include/iprt/crypto/pkix.h
new file mode 100644
index 00000000..98120fbf
--- /dev/null
+++ b/include/iprt/crypto/pkix.h
@@ -0,0 +1,582 @@
+/** @file
+ * IPRT - Public Key Infrastructure APIs.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_crypto_pkix_h
+#define IPRT_INCLUDED_crypto_pkix_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/asn1.h>
+
+
+RT_C_DECLS_BEGIN
+
+struct RTCRX509CERTIFICATE;
+struct RTCRX509SUBJECTPUBLICKEYINFO;
+
+/** @defgroup grp_rt_crpkix RTCrPkix - Public Key Infrastructure APIs
+ * @ingroup grp_rt_crypto
+ * @{
+ */
+
+/**
+ * Verifies the signature (@a pSignatureValue) of the give data (@a pvData)
+ * using the specfied public key (@a pPublicKey) and algorithm.
+ *
+ * @returns IPRT status code.
+ * @param pAlgorithm The signature algorithm (digest w/ cipher).
+ * @param hPublicKey The public key.
+ * @param pParameters Parameter to the public key algorithm. Optional.
+ * @param pSignatureValue The signature value.
+ * @param pvData The signed data.
+ * @param cbData The amount of signed data.
+ * @param pErrInfo Where to return extended error info. Optional.
+ *
+ * @remarks Depending on the IPRT build configuration, the verficiation may be
+ * performed more than once using all available crypto implementations.
+ */
+RTDECL(int) RTCrPkixPubKeyVerifySignature(PCRTASN1OBJID pAlgorithm, RTCRKEY hPublicKey, PCRTASN1DYNTYPE pParameters,
+ PCRTASN1BITSTRING pSignatureValue, const void *pvData, size_t cbData,
+ PRTERRINFO pErrInfo);
+
+
+/**
+ * Verifies the signed digest (@a pvSignedDigest) against our digest (@a
+ * hDigest) using the specfied public key (@a pPublicKey) and algorithm.
+ *
+ * @returns IPRT status code.
+ * @param pAlgorithm The signature algorithm (digest w/ cipher).
+ * @param hPublicKey The public key.
+ * @param pParameters Parameter to the public key algorithm. Optional.
+ * @param pvSignedDigest The signed digest.
+ * @param cbSignedDigest The signed digest size.
+ * @param hDigest The digest of the data to compare @a pvSignedDigest
+ * with.
+ * @param pErrInfo Where to return extended error info. Optional.
+ *
+ * @remarks Depending on the IPRT build configuration, the verficiation may be
+ * performed more than once using all available crypto implementations.
+ */
+RTDECL(int) RTCrPkixPubKeyVerifySignedDigest(PCRTASN1OBJID pAlgorithm, RTCRKEY hPublicKey, PCRTASN1DYNTYPE pParameters,
+ void const *pvSignedDigest, size_t cbSignedDigest,
+ RTCRDIGEST hDigest, PRTERRINFO pErrInfo);
+
+/**
+ * Wrapper around RTCrPkixPubKeyVerifySignedDigest & RTCrKeyCreateFromAlgorithmAndBits.
+ *
+ * @note The public key info must include digest type for this to work.
+ */
+RTDECL(int) RTCrPkixPubKeyVerifySignedDigestByCertPubKeyInfo(struct RTCRX509SUBJECTPUBLICKEYINFO const *pCertPubKeyInfo,
+ void const *pvSignedDigest, size_t cbSignedDigest,
+ RTCRDIGEST hDigest, PRTERRINFO pErrInfo);
+
+/**
+ * Checks if the hash size can be handled by the given public key.
+ */
+RTDECL(bool) RTCrPkixPubKeyCanHandleDigestType(struct RTCRX509SUBJECTPUBLICKEYINFO const *pPublicKeyInfo,
+ RTDIGESTTYPE enmDigestType, PRTERRINFO pErrInfo);
+
+/**
+ * Checks if the hash size can be handled by the given certificate's public key.
+ */
+RTDECL(bool) RTCrPkixCanCertHandleDigestType(struct RTCRX509CERTIFICATE const *pCertificate,
+ RTDIGESTTYPE enmDigestType, PRTERRINFO pErrInfo);
+
+/**
+ * Signs a digest (@a hDigest) using the specified private key (@a pPrivateKey) and algorithm.
+ *
+ * @returns IPRT status code.
+ * @param pAlgorithm The signature algorithm (digest w/ cipher).
+ * @param hPrivateKey Handle to the private key to use.
+ * @param pParameters Parameter to the public key algorithm. Optional.
+ * @param hDigest The digest of the data being signed.
+ * @param fFlags Flags for future extensions, MBZ.
+ * @param pvSignature The output signature buffer. Pass NULL to query
+ * the signature size.
+ * @param pcbSignature On input the variable pointed to holds the size of
+ * the buffer @a pvSignature points to.
+ * On return the variable pointed to is set to the size
+ * of the returned signature, or the required size in
+ * case of VERR_BUFFER_OVERFLOW.
+ * @param pErrInfo Where to return extended error info. Optional.
+ *
+ * @remarks Depending on the IPRT build configuration and the algorithm used, the
+ * signing may be performed more than once using all available crypto
+ * implementations.
+ */
+RTDECL(int) RTCrPkixPubKeySignDigest(PCRTASN1OBJID pAlgorithm, RTCRKEY hPrivateKey, PCRTASN1DYNTYPE pParameters,
+ RTCRDIGEST hDigest, uint32_t fFlags,
+ void *pvSignature, size_t *pcbSignature, PRTERRINFO pErrInfo);
+
+/**
+ * Gets the cipher OID matching the given signature algorithm.
+ *
+ * @returns Cipher OID string on success, NULL on failure.
+ * @param pAlgorithm The signature algorithm (digest w/ cipher).
+ */
+RTDECL(const char *) RTCrPkixGetCiperOidFromSignatureAlgorithm(PCRTASN1OBJID pAlgorithm);
+
+
+/** @name PKCS-1 Object Identifiers (OIDs)
+ * @{ */
+#define RTCR_PKCS1_OID "1.2.840.113549.1.1"
+#define RTCR_PKCS1_RSA_OID "1.2.840.113549.1.1.1"
+#define RTCR_PKCS1_MD2_WITH_RSA_OID "1.2.840.113549.1.1.2"
+#define RTCR_PKCS1_MD4_WITH_RSA_OID "1.2.840.113549.1.1.3"
+#define RTCR_PKCS1_MD5_WITH_RSA_OID "1.2.840.113549.1.1.4"
+#define RTCR_PKCS1_SHA1_WITH_RSA_OID "1.2.840.113549.1.1.5"
+#define RTCR_PKCS1_RSA_OAEP_ENCRYPTION_SET_OID "1.2.840.113549.1.1.6"
+#define RTCR_PKCS1_RSA_AES_OAEP_OID "1.2.840.113549.1.1.7"
+#define RTCR_PKCS1_MSGF1_OID "1.2.840.113549.1.1.8"
+#define RTCR_PKCS1_P_SPECIFIED_OID "1.2.840.113549.1.1.9"
+#define RTCR_PKCS1_RSASSA_PSS_OID "1.2.840.113549.1.1.10"
+#define RTCR_PKCS1_SHA256_WITH_RSA_OID "1.2.840.113549.1.1.11"
+#define RTCR_PKCS1_SHA384_WITH_RSA_OID "1.2.840.113549.1.1.12"
+#define RTCR_PKCS1_SHA512_WITH_RSA_OID "1.2.840.113549.1.1.13"
+#define RTCR_PKCS1_SHA224_WITH_RSA_OID "1.2.840.113549.1.1.14"
+#define RTCR_PKCS1_SHA512T224_WITH_RSA_OID "1.2.840.113549.1.1.15"
+#define RTCR_PKCS1_SHA512T256_WITH_RSA_OID "1.2.840.113549.1.1.16"
+/** @} */
+
+
+/**
+ * Public key signature scheme provider descriptor.
+ */
+typedef struct RTCRPKIXSIGNATUREDESC
+{
+ /** The signature scheme provider name. */
+ const char *pszName;
+ /** The object ID string. */
+ const char *pszObjId;
+ /** Pointer to a NULL terminated table of alias object IDs (optional). */
+ const char * const *papszObjIdAliases;
+ /** The size of the state. */
+ uint32_t cbState;
+ /** Reserved for future / explicit padding. */
+ uint32_t uReserved;
+ /** Provider specific field. This generally indicates the kind of padding
+ * scheme to employ with the given OID. */
+ uintptr_t uProviderSpecific;
+
+ /**
+ * Initializes the state of the signature scheme provider.
+ *
+ * Optional, RT_BZERO will be used if NULL.
+ *
+ * @returns IPRT status code.
+ * @param pDesc Pointer to this structure (for uProviderSpecific).
+ * @param pvState The opaque provider state.
+ * @param pvOpaque Opaque provider specific parameter.
+ * @param fSigning Set if a signing operation is going to be performed,
+ * clear if it is a verification. This is a fixed
+ * setting for the lifetime of the instance due to the
+ * algorithm requiring different keys.
+ * @param hKey The key handle. Caller has retained it for the
+ * lifetime of the state being initialize.
+ * @param pParams Algorithm/key parameters, optional. Will be NULL if
+ * none.
+ */
+ DECLCALLBACKMEMBER(int, pfnInit,(struct RTCRPKIXSIGNATUREDESC const *pDesc, void *pvState, void *pvOpaque, bool fSigning,
+ RTCRKEY hKey, PCRTASN1DYNTYPE pParams));
+
+ /**
+ * Resets the state before performing another signing or verification.
+ *
+ * Optional. It is assumed that the provider does not have any state needing to
+ * be re-initialized if this method is not implemented.
+ *
+ * @returns IPRT status code.
+ * @param pDesc Pointer to this structure (for uProviderSpecific).
+ * @param pvState The opaque provider state.
+ * @param fSigning Exactly the same value as the init call.
+ */
+ DECLCALLBACKMEMBER(int, pfnReset,(struct RTCRPKIXSIGNATUREDESC const *pDesc, void *pvState, bool fSigning));
+
+ /**
+ * Deletes the provider state. Optional.
+ *
+ * The state will be securely wiped clean after the call, regardless of whether
+ * the method is implemented or not.
+ *
+ * @param pDesc Pointer to this structure (for uProviderSpecific).
+ * @param pvState The opaque provider state.
+ * @param fSigning Exactly the same value as the init call.
+ */
+ DECLCALLBACKMEMBER(void, pfnDelete,(struct RTCRPKIXSIGNATUREDESC const *pDesc, void *pvState, bool fSigning));
+
+ /**
+ * Verifies a signed message digest (fSigning = false).
+ *
+ * @returns IPRT status code.
+ * @retval VINF_SUCCESS if the signature checked out correctly.
+ * @retval VINF_CR_DIGEST_DEPRECATED if the signature checked out correctly
+ * but the hash algorithm is deprecated.
+ * @retval VINF_CR_DIGEST_COMPROMISED if the signature checked out correctly
+ * but the hash algorithm is compromised.
+ * @retval VINF_CR_DIGEST_SEVERELY_COMPROMISED if the signature checked out
+ * correctly but the hash algorithm is severely compromised.
+ * @retval VERR_PKIX_KEY wrong key or some other key issue.
+ *
+ * @param pDesc Pointer to this structure (for uProviderSpecific).
+ * @param pvState The opaque provider state.
+ * @param hKey The key handle associated with the state at init.
+ * @param hDigest The handle to the digest. Calls RTCrDigestFinal to
+ * complete and retreive the final hash value.
+ * @param pvSignature The signature to validate.
+ * @param cbSignature The size of the signature (in bytes).
+ */
+ DECLCALLBACKMEMBER(int, pfnVerify,(struct RTCRPKIXSIGNATUREDESC const *pDesc, void *pvState, RTCRKEY hKey,
+ RTCRDIGEST hDigest, void const *pvSignature, size_t cbSignature));
+
+ /**
+ * Sign a message digest (fSigning = true).
+ *
+ * @returns IPRT status code.
+ * @retval VINF_SUCCESS on success.
+ * @retval VINF_CR_DIGEST_DEPRECATED on success but the hash algorithm is deprecated.
+ * @retval VINF_CR_DIGEST_COMPROMISED on success but the hash algorithm is compromised.
+ * @retval VINF_CR_DIGEST_SEVERELY_COMPROMISED on success but the hash algorithm
+ * is severely compromised.
+ * @retval VERR_PKIX_KEY wrong key or some other key issue.
+ * @retval VERR_BUFFER_OVERFLOW if the signature buffer is too small, the
+ * require buffer size will be available in @a *pcbSignature.
+ *
+ * @param pDesc Pointer to this structure (for uProviderSpecific).
+ * @param pvState The opaque provider state.
+ * @param hKey The key handle associated with the state at init.
+ * @param hDigest The handle to the digest. Calls RTCrDigestFinal to
+ * complete and retreive the final hash value.
+ * @param pvSignature The output signature buffer.
+ * @param pcbSignature On input the variable pointed to holds the size of
+ * the buffer @a pvSignature points to.
+ * On return the variable pointed to is set to the size
+ * of the returned signature, or the required size in
+ * case of VERR_BUFFER_OVERFLOW.
+ */
+ DECLCALLBACKMEMBER(int, pfnSign,(struct RTCRPKIXSIGNATUREDESC const *pDesc, void *pvState, RTCRKEY hKey,
+ RTCRDIGEST hDigest, void *pvSignature, size_t *pcbSignature));
+
+} RTCRPKIXSIGNATUREDESC;
+/** Pointer to a public key signature scheme provider descriptor. */
+typedef RTCRPKIXSIGNATUREDESC const *PCRTCRPKIXSIGNATUREDESC;
+
+/**
+ * Locates a signature schema provider descriptor by object ID string.
+ * @returns Pointer to descriptor on success, NULL on if not found.
+ * @param pszObjId The ID of the signature to search for.
+ * @param ppvOpaque Where to store an opaque schema parameter. Optional.
+ */
+PCRTCRPKIXSIGNATUREDESC RTCrPkixSignatureFindByObjIdString(const char *pszObjId, void *ppvOpaque);
+
+/**
+ * Locates a signature schema provider descriptor by ASN.1 object ID.
+ * @returns Pointer to descriptor on success, NULL on if not found.
+ * @param pObjId The ID of the signature to search for.
+ * @param ppvOpaque Where to store an opaque schema parameter. Optional.
+ */
+PCRTCRPKIXSIGNATUREDESC RTCrPkixSignatureFindByObjId(PCRTASN1OBJID pObjId, void **ppvOpaque);
+
+/**
+ * Create a signature schema provier instance.
+ *
+ * @returns IPRT status code.
+ * @param phSignature Where to return the handle to the created instance.
+ * @param pDesc The signature schema provider descriptor. Use
+ * RTCrPkixSignatureFindByObjIdString() or RTCrPkixSignatureFindByObjId()
+ * to get this.
+ * @param pvOpaque The opaque schema parameter returned by the find functions.
+ * @param fSigning Set if the intention is to sign stuff, clear if verification only.
+ * @param hKey The key handle. A referenced will be retained.
+ * @param pParams Algorithm/key parameters, optional.
+ */
+RTDECL(int) RTCrPkixSignatureCreate(PRTCRPKIXSIGNATURE phSignature, PCRTCRPKIXSIGNATUREDESC pDesc, void *pvOpaque,
+ bool fSigning, RTCRKEY hKey, PCRTASN1DYNTYPE pParams);
+/** Convenience wrapper function for RTCrPkixSignatureCreate(). */
+RTDECL(int) RTCrPkixSignatureCreateByObjIdString(PRTCRPKIXSIGNATURE phSignature, const char *pszObjId,
+ RTCRKEY hKey, PCRTASN1DYNTYPE pParams, bool fSigning);
+/** Convenience wrapper function for RTCrPkixSignatureCreate(). */
+RTDECL(int) RTCrPkixSignatureCreateByObjId(PRTCRPKIXSIGNATURE phSignature, PCRTASN1OBJID pObjId, RTCRKEY hKey,
+ PCRTASN1DYNTYPE pParams, bool fSigning);
+
+/**
+ * Retains a reference to the signature schema provider instance.
+ *
+ * @returns New reference count on success, UINT32_MAX if invalid handle.
+ * @param hSignature The signature schema provider handle.
+ */
+RTDECL(uint32_t) RTCrPkixSignatureRetain(RTCRPKIXSIGNATURE hSignature);
+
+/**
+ * Releases a reference to the signature schema provider instance.
+ *
+ * @returns New reference count on success, UINT32_MAX if invalid handle.
+ * @param hSignature The signature schema provider handle. NIL is ignored.
+ */
+RTDECL(uint32_t) RTCrPkixSignatureRelease(RTCRPKIXSIGNATURE hSignature);
+
+/**
+ * Verifies a signed message digest.
+ *
+ * @returns IPRT status code.
+ * @retval VINF_SUCCESS if the signature checked out correctly.
+ * @retval VINF_CR_DIGEST_DEPRECATED if the signature checked out correctly
+ * but the hash algorithm is deprecated.
+ * @retval VINF_CR_DIGEST_COMPROMISED if the signature checked out correctly
+ * but the hash algorithm is compromised.
+ * @retval VINF_CR_DIGEST_SEVERELY_COMPROMISED if the signature checked out
+ * correctly but the hash algorithm is severely compromised.
+ * @retval VERR_PKIX_KEY wrong key or some other key issue.
+ *
+ * @param hSignature The signature schema provider handle.
+ * @param hDigest The handle to the digest. All that must have been
+ * feed to it via RTCrDigestUpdate() and friends prior
+ * to calling this function. The function will itself
+ * call RTCrDigestFinal() to complete and retreive the
+ * final hash value.
+ * @param pvSignature The signature to validate.
+ * @param cbSignature The size of the signature (in bytes).
+ */
+RTDECL(int) RTCrPkixSignatureVerify(RTCRPKIXSIGNATURE hSignature, RTCRDIGEST hDigest, void const *pvSignature, size_t cbSignature);
+/** Convenience wrapper function for RTCrPkixSignatureVerify(). */
+RTDECL(int) RTCrPkixSignatureVerifyBitString(RTCRPKIXSIGNATURE hSignature, RTCRDIGEST hDigest, PCRTASN1BITSTRING pSignature);
+/** Convenience wrapper function for RTCrPkixSignatureVerify(). */
+RTDECL(int) RTCrPkixSignatureVerifyOctetString(RTCRPKIXSIGNATURE hSignature, RTCRDIGEST hDigest, PCRTASN1OCTETSTRING pSignature);
+
+/**
+ * Sign a message digest.
+ *
+ * @returns IPRT status code.
+ * @retval VINF_SUCCESS on success.
+ * @retval VINF_CR_DIGEST_DEPRECATED on success but the hash algorithm is deprecated.
+ * @retval VINF_CR_DIGEST_COMPROMISED on success but the hash algorithm is compromised.
+ * @retval VINF_CR_DIGEST_SEVERELY_COMPROMISED on success but the hash algorithm
+ * is severely compromised.
+ * @retval VERR_PKIX_KEY wrong key or some other key issue.
+ * @retval VERR_BUFFER_OVERFLOW if the signature buffer is too small, the
+ * require buffer size will be available in @a *pcbSignature.
+ *
+ * @param hSignature The signature schema provider handle.
+ * @param hDigest The handle to the digest. All that must have been
+ * feed to it via RTCrDigestUpdate() and friends prior
+ * to calling this function. The function will itself
+ * call RTCrDigestFinal() to complete and retreive the
+ * final hash value.
+ * @param pvSignature The output signature buffer.
+ * @param pcbSignature On input the variable pointed to holds the size of
+ * the buffer @a pvSignature points to.
+ * On return the variable pointed to is set to the size
+ * of the returned signature, or the required size in
+ * case of VERR_BUFFER_OVERFLOW.
+ */
+RTDECL(int) RTCrPkixSignatureSign(RTCRPKIXSIGNATURE hSignature, RTCRDIGEST hDigest, void *pvSignature, size_t *pcbSignature);
+
+
+/**
+ * Public key encryption scheme provider descriptor.
+ *
+ * @todo This is just a sketch left over from when the signature code was
+ * chiseled out.
+ */
+typedef struct RTCRPKIXENCRYPTIONDESC
+{
+ /** The encryption scheme provider name. */
+ const char *pszName;
+ /** The object ID string. */
+ const char *pszObjId;
+ /** Pointer to a NULL terminated table of alias object IDs (optional). */
+ const char * const *papszObjIdAliases;
+ /** The size of the state. */
+ uint32_t cbState;
+ /** Reserved for future use / padding. */
+ uint32_t uReserved;
+ /** Provider specific field. */
+ uintptr_t uProviderSpecific;
+
+ /**
+ * Initializes the state for this encryption scheme.
+ *
+ * Optional, RT_BZERO will be used if NULL.
+ *
+ * @returns IPRT status code.
+ * @param pDesc Pointer to this structure (so uProviderSpecific can
+ * be read).
+ * @param pvState The opaque provider state.
+ * @param pvOpaque Opaque provider specific parameter.
+ * @param fEncrypt Set if the instance will be encrypting, clear if it
+ * will be decrypting. This aspect of the instance is
+ * immutable due to the algorithm requiring different
+ * keys for each of the operations.
+ * @param pKey The key to use (whether private or public depends on
+ * the operation type).
+ * @param pParams Algorithm/key parameters, optional. Will be NULL if
+ * none.
+ */
+ DECLCALLBACKMEMBER(int, pfnInit,(struct RTCRPKIXENCRYPTIONDESC const *pDesc, void *pvState, void *pvOpaque, bool fEncrypt,
+ PCRTASN1BITSTRING pKey, PCRTASN1DYNTYPE pParams));
+
+ /**
+ * Re-initializes the provider state.
+ *
+ * Optional. It is assumed that the provider does not have any state needing
+ * to be re-initialized if this method is not implemented. (Do not assume that
+ * a final encrypt/decrypt call has been made prior to this call.)
+ *
+ * @returns IPRT status code.
+ * @param pDesc Pointer to this structure (so uProviderSpecific can
+ * be read).
+ * @param pvState The opaque provider state.
+ * @param enmOperation Same as for the earlier pfnInit call.
+ */
+ DECLCALLBACKMEMBER(int, pfnReset,(struct RTCRPKIXENCRYPTIONDESC const *pDesc, void *pvState, bool fEncrypt));
+
+ /**
+ * Deletes the provider state. Optional.
+ *
+ * The state will be securely wiped clean after the call, regardless of whether
+ * the method is implemented or not.
+ *
+ * @param pDesc Pointer to this structure (so uProviderSpecific can
+ * be read).
+ * @param pvState The opaque provider state.
+ * @param enmOperation Same as for the earlier pfnInit call.
+ */
+ DECLCALLBACKMEMBER(void, pfnDelete,(struct RTCRPKIXENCRYPTIONDESC const *pDesc, void *pvState, bool fEncrypt));
+
+ /**
+ * Encrypt using the public key (fEncrypt = true).
+ *
+ * @returns IPRT status code.
+ * @retval VINF_SUCCESS on success.
+ * @retval VERR_PKIX_KEY wrong key or some other key issue.
+ * @retval VERR_BUFFER_OVERFLOW if the output buffer is too small, the require
+ * buffer size will be available in @a *pcbCiphertext. The caller can
+ * should retry the call with a larger buffer.
+ *
+ * @param pDesc Pointer to this structure (so uProviderSpecific can
+ * be read).
+ * @param pvState The opaque provider state.
+ * @param pvPlaintext The plaintext to encrypt.
+ * @param cbPlaintext The number of bytes of plaintext.
+ * @param pvCiphertext Where to return the ciphertext (if any).
+ * @param cbMaxCiphertext The size of the buffer @a pvCiphertext points to.
+ * @param pcbCiphertext Where to return the actual number of bytes of
+ * ciphertext returned.
+ * @param fFinal Whether this is the final call.
+ */
+ DECLCALLBACKMEMBER(int, pfnEncrypt,(struct RTCRPKIXENCRYPTIONDESC const *pDesc, void *pvState,
+ void const *pvPlaintext, size_t cbPlaintext,
+ void *pvCiphertext, size_t cbMaxCiphertext, size_t *pcbCiphertext, bool fFinal));
+
+ /**
+ * Calculate the output buffer size for the next pfnEncrypt call.
+ *
+ * @returns IPRT status code.
+ * @param pDesc Pointer to this structure (so uProviderSpecific can
+ * be read).
+ * @param pvState The opaque provider state.
+ * @param cbPlaintext The number of bytes of plaintext.
+ * @param pcbCiphertext Where to return the minimum buffer size. This may
+ * be larger than the actual number of bytes return.
+ * @param fFinal Whether this is the final call.
+ */
+ DECLCALLBACKMEMBER(int, pfnEncryptLength,(struct RTCRPKIXENCRYPTIONDESC const *pDesc, void *pvState,
+ size_t cbPlaintext, size_t *pcbCiphertext, bool fFinal));
+
+ /**
+ * Decrypt using the private key (fEncrypt = false).
+ *
+ * @returns IPRT status code.
+ * @retval VINF_SUCCESS on success.
+ * @retval VERR_PKIX_KEY wrong key or some other key issue.
+ * @retval VERR_BUFFER_OVERFLOW if the output buffer is too small, the require
+ * buffer size will be available in @a *pcbCiphertext. The caller can
+ * should retry the call with a larger buffer.
+ *
+ * @param pDesc Pointer to this structure (so uProviderSpecific can
+ * be read).
+ * @param pvState The opaque provider state.
+ * @param pvCiphertext The ciphertext to decrypt.
+ * @param cbCiphertext The number of bytes of ciphertext.
+ * @param pvPlaintext Where to return the plaintext (if any).
+ * @param cbMaxPlaintext The size of the buffer @a pvPlaintext points to.
+ * @param pcbPlaintext Where to return the actual number of bytes of
+ * plaintext returned.
+ * @param fFinal Whether this is the final call.
+ */
+ DECLCALLBACKMEMBER(int, pfnDecrypt,(struct RTCRPKIXENCRYPTIONDESC const *pDesc, void *pvState,
+ void const *pvCiphertext, size_t cbCiphertext,
+ void *pvPlaintext, size_t cbMaxPlaintext, size_t *pcbPlaintext, bool fFinal));
+
+ /**
+ * Calculate the output buffer size for the next pfnDecrypt call.
+ *
+ * @returns IPRT status code.
+ * @param pDesc Pointer to this structure (so uProviderSpecific can
+ * be read).
+ * @param pvState The opaque provider state.
+ * @param cbCiphertext The number of bytes of ciphertext.
+ * @param pcbPlaintext Where to return the minimum buffer size. This may
+ * be larger than the actual number of bytes return.
+ * @param fFinal Whether this is the final call.
+ */
+ DECLCALLBACKMEMBER(int, pfnDecryptLength,(struct RTCRPKIXENCRYPTIONDESC const *pDesc, void *pvState,
+ size_t cbCiphertext, size_t *pcbPlaintext, bool fFinal));
+} RTCRPKIXENCRYPTIONDESC;
+/** Pointer to a public key encryption schema provider descriptor. */
+typedef RTCRPKIXENCRYPTIONDESC const *PCRTCRPKIXENCRYPTIONDESC;
+
+
+PCRTCRPKIXENCRYPTIONDESC RTCrPkixEncryptionFindByObjIdString(const char *pszObjId, void *ppvOpaque);
+PCRTCRPKIXENCRYPTIONDESC RTCrPkixEncryptionFindByObjId(PCRTASN1OBJID pObjId, void *ppvOpaque);
+RTDECL(int) RTCrPkixEncryptionCreateByObjIdString(PRTCRPKIXENCRYPTION phEncryption, const char *pszObjId,
+ bool fEncrypt, RTCRKEY hKey, PCRTASN1DYNTYPE pParams);
+RTDECL(int) RTCrPkixEncryptionCreateByObjId(PRTCRPKIXENCRYPTION phEncryption, PCRTASN1OBJID pObjId, bool fEncrypt,
+ RTCRKEY hKey, PCRTASN1DYNTYPE pParams);
+
+
+RTDECL(int) RTCrPkixEncryptionCreate(PRTCRPKIXENCRYPTION phEncryption, PCRTCRPKIXENCRYPTIONDESC pDesc, void *pvOpaque,
+ bool fEncrypt, PCRTASN1BITSTRING pKey, PCRTASN1DYNTYPE pParams);
+RTDECL(int) RTCrPkixEncryptionReset(RTCRPKIXENCRYPTION hEncryption);
+RTDECL(uint32_t) RTCrPkixEncryptionRetain(RTCRPKIXENCRYPTION hEncryption);
+RTDECL(uint32_t) RTCrPkixEncryptionRelease(RTCRPKIXENCRYPTION hEncryption);
+
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_crypto_pkix_h */
+
diff --git a/include/iprt/crypto/rc4.h b/include/iprt/crypto/rc4.h
new file mode 100644
index 00000000..3576116f
--- /dev/null
+++ b/include/iprt/crypto/rc4.h
@@ -0,0 +1,73 @@
+/** @file
+ * IPRT - Crypto - Alleged RC4 Cipher.
+ */
+
+/*
+ * Copyright (C) 2018-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_crypto_rc4_h
+#define IPRT_INCLUDED_crypto_rc4_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_cr_rc4 RTCrRc4 - Alleged RC4 Cipher.
+ * @ingroup grp_rt_crypto
+ * @{
+ */
+
+/** RC4 key structure. */
+typedef union RTCRRC4KEY
+{
+ uint64_t au64Padding[(2 + 256) / 2];
+#ifdef HEADER_RC4_H
+ RC4_KEY Ossl;
+#endif
+} RTCRRC4KEY;
+/** Pointer to a RC4 key structure. */
+typedef RTCRRC4KEY *PRTCRRC4KEY;
+/** Pointer to a const RC4 key structure. */
+typedef RTCRRC4KEY const *PCRTCRRC4KEY;
+
+RTDECL(void) RTCrRc4SetKey(PRTCRRC4KEY pKey, size_t cbData, void const *pvData);
+RTDECL(void) RTCrRc4(PRTCRRC4KEY pKey, size_t cbData, void const *pvDataIn, void *pvDataOut);
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_crypto_rc4_h */
+
diff --git a/include/iprt/crypto/rsa.h b/include/iprt/crypto/rsa.h
new file mode 100644
index 00000000..34bc4505
--- /dev/null
+++ b/include/iprt/crypto/rsa.h
@@ -0,0 +1,166 @@
+/** @file
+ * IPRT - Crypto - RSA Public Key Cryptosystem .
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_crypto_rsa_h
+#define IPRT_INCLUDED_crypto_rsa_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/asn1.h>
+#include <iprt/crypto/x509.h>
+#include <iprt/crypto/pkcs7.h>
+#include <iprt/md5.h>
+#include <iprt/sha.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_cr_rsa RTCrRsa - RSA Public Key Cryptosystem
+ * @ingroup grp_rt_crypto
+ * @{
+ */
+
+/**
+ * RSA public key - ASN.1 IPRT representation.
+ */
+typedef struct RTCRRSAPUBLICKEY
+{
+ /** Sequence core for the structure. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** The modulus (n). */
+ RTASN1INTEGER Modulus;
+ /** The public exponent (e). */
+ RTASN1INTEGER PublicExponent;
+} RTCRRSAPUBLICKEY;
+/** Pointer to the ASN.1 IPRT representation of an RSA public key. */
+typedef RTCRRSAPUBLICKEY *PRTCRRSAPUBLICKEY;
+/** Pointer to the const ASN.1 IPRT representation of an RSA public key. */
+typedef RTCRRSAPUBLICKEY const *PCRTCRRSAPUBLICKEY;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRRSAPUBLICKEY, RTDECL, RTCrRsaPublicKey, SeqCore.Asn1Core);
+
+RTDECL(bool) RTCrRsaPublicKey_CanHandleDigestType(PCRTCRRSAPUBLICKEY pRsaPublicKey, RTDIGESTTYPE enmDigestType,
+ PRTERRINFO pErrInfo);
+
+
+/**
+ * RSA other prime info (ASN.1 IPRT representation).
+ */
+typedef struct RTCRRSAOTHERPRIMEINFO
+{
+ /** Sequence core for the structure. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** The prime (ri). */
+ RTASN1INTEGER Prime;
+ /** The exponent (di). */
+ RTASN1INTEGER Exponent;
+ /** The coefficient (ti). */
+ RTASN1INTEGER Coefficient;
+} RTCRRSAOTHERPRIMEINFO;
+/** Pointer to the ASN.1 IPRT representation of RSA other prime info. */
+typedef RTCRRSAOTHERPRIMEINFO *PRTCRRSAOTHERPRIMEINFO;
+/** Pointer to the const ASN.1 IPRT representation of RSA other prime info. */
+typedef RTCRRSAOTHERPRIMEINFO const *PCRTCRRSAOTHERPRIMEINFO;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRRSAOTHERPRIMEINFO, RTDECL, RTCrRsaOtherPrimeInfo, SeqCore.Asn1Core);
+RTASN1_IMPL_GEN_SEQ_OF_TYPEDEFS_AND_PROTOS(RTCRRSAOTHERPRIMEINFOS, RTCRRSAOTHERPRIMEINFO, RTDECL, RTCrRsaOtherPrimeInfos);
+
+/**
+ * RSA private key - ASN.1 IPRT representation.
+ */
+typedef struct RTCRRSAPRIVATEKEY
+{
+ /** Sequence core for the structure. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** Key version number. */
+ RTASN1INTEGER Version;
+ /** The modulus (n). */
+ RTASN1INTEGER Modulus;
+ /** The public exponent (e). */
+ RTASN1INTEGER PublicExponent;
+ /** The private exponent (d). */
+ RTASN1INTEGER PrivateExponent;
+ /** The first prime factor (p) of the modulus (n). */
+ RTASN1INTEGER Prime1;
+ /** The second prime factor (q) of the modulus (n). */
+ RTASN1INTEGER Prime2;
+ /** The first exponent (d mod (p-1)). */
+ RTASN1INTEGER Exponent1;
+ /** The second exponent (d mod (q-1)). */
+ RTASN1INTEGER Exponent2;
+ /** The coefficient ((inverse of q) mod p). */
+ RTASN1INTEGER Coefficient;
+ /** Optional other prime information (version must be 'multi' if present). */
+ RTCRRSAOTHERPRIMEINFOS OtherPrimeInfos;
+} RTCRRSAPRIVATEKEY;
+/** Pointer to the ASN.1 IPRT representation of an RSA private key. */
+typedef RTCRRSAPRIVATEKEY *PRTCRRSAPRIVATEKEY;
+/** Pointer to the const ASN.1 IPRT representation of an RSA private key. */
+typedef RTCRRSAPRIVATEKEY const *PCRTCRRSAPRIVATEKEY;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRRSAPRIVATEKEY, RTDECL, RTCrRsaPrivateKey, SeqCore.Asn1Core);
+
+/** @name RSA Private Key Versions
+ * @{ */
+#define RTCRRSAPRIVATEKEY_VERSION_TWO_PRIME 0
+#define RTCRRSAPRIVATEKEY_VERSION_MULTI 1
+/** @} */
+
+RTDECL(bool) RTCrRsaPrivateKey_CanHandleDigestType(PCRTCRRSAPRIVATEKEY pRsaPrivateKey, RTDIGESTTYPE enmDigestType,
+ PRTERRINFO pErrInfo);
+
+
+/**
+ * RSA DigestInfo used by the EMSA-PKCS1-v1_5 encoding method.
+ */
+typedef struct RTCRRSADIGESTINFO
+{
+ /** Sequence core for the structure. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** The digest algorithm. */
+ RTCRX509ALGORITHMIDENTIFIER DigestAlgorithm;
+ /** The digest. */
+ RTASN1OCTETSTRING Digest;
+} RTCRRSADIGESTINFO;
+/** Pointer to the ASN.1 IPRT representation of RSA digest info. */
+typedef RTCRRSADIGESTINFO *PRTCRRSADIGESTINFO;
+/** Pointer to the const ASN.1 IPRT representation of RSA digest info. */
+typedef RTCRRSADIGESTINFO const *PCRTCRRSADIGESTINFO;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRRSADIGESTINFO, RTDECL, RTCrRsaDigestInfo, SeqCore.Asn1Core);
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_crypto_rsa_h */
+
diff --git a/include/iprt/crypto/spc.h b/include/iprt/crypto/spc.h
new file mode 100644
index 00000000..abe7fe36
--- /dev/null
+++ b/include/iprt/crypto/spc.h
@@ -0,0 +1,533 @@
+/** @file
+ * IPRT - Crypto - Microsoft SPC / Authenticode.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_crypto_spc_h
+#define IPRT_INCLUDED_crypto_spc_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/asn1.h>
+#include <iprt/crypto/x509.h>
+#include <iprt/crypto/pkcs7.h>
+#include <iprt/md5.h>
+#include <iprt/sha.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_cr_spc RTCrSpc - Microsoft Authenticode
+ * @ingroup grp_rt_crypto
+ * @{
+ */
+
+/** Value for RTCR_PKCS9_ID_MS_STATEMENT_TYPE. */
+#define RTCRSPC_STMT_TYPE_INDIVIDUAL_CODE_SIGNING "1.3.6.1.4.1.311.2.1.21"
+
+/**
+ * PE Image page hash table, generic union.
+ *
+ * @remarks This table isn't used by ldrPE.cpp, it walks the table in a generic
+ * fashion using the hash size. So, we can ditch it if we feel like it.
+ */
+typedef union RTCRSPCPEIMAGEPAGEHASHES
+{
+ /** MD5 page hashes. */
+ struct
+ {
+ /** The file offset. */
+ uint32_t offFile;
+ /** The hash. */
+ uint8_t abHash[RTSHA1_HASH_SIZE];
+ } aMd5[1];
+
+ /** SHA-1 page hashes. */
+ struct
+ {
+ /** The file offset. */
+ uint32_t offFile;
+ /** The hash. */
+ uint8_t abHash[RTSHA1_HASH_SIZE];
+ } aSha1[1];
+
+ /** SHA-256 page hashes. */
+ struct
+ {
+ /** The file offset. */
+ uint32_t offFile;
+ /** The hash. */
+ uint8_t abHash[RTSHA256_HASH_SIZE];
+ } aSha256[1];
+
+ /** SHA-512 page hashes. */
+ struct
+ {
+ /** The file offset. */
+ uint32_t offFile;
+ /** The hash. */
+ uint8_t abHash[RTSHA512_HASH_SIZE];
+ } aSha512[1];
+
+ /** Generic view of ONE hash. */
+ struct
+ {
+ /** The file offset. */
+ uint32_t offFile;
+ /** Variable length hash field. */
+ uint8_t abHash[1];
+ } Generic;
+} RTCRSPCPEIMAGEPAGEHASHES;
+/** Pointer to a PE image page hash table union. */
+typedef RTCRSPCPEIMAGEPAGEHASHES *PRTCRSPCPEIMAGEPAGEHASHES;
+/** Pointer to a const PE image page hash table union. */
+typedef RTCRSPCPEIMAGEPAGEHASHES const *PCRTCRSPCPEIMAGEPAGEHASHES;
+
+
+/**
+ * Serialization wrapper for raw RTCRSPCPEIMAGEPAGEHASHES data.
+ */
+typedef struct RTCRSPCSERIALIZEDPAGEHASHES
+{
+ /** The page hashes are within a set. Dunno if there could be multiple
+ * entries in this set, never seen it yet, so I doubt it. */
+ RTASN1SETCORE SetCore;
+ /** Octet string containing the raw data. */
+ RTASN1OCTETSTRING RawData;
+
+ /** Pointer to the hash data within that string.
+ * The hash algorithm is given by the object attribute type in
+ * RTCRSPCSERIALIZEDOBJECTATTRIBUTE. It is generally the same as for the
+ * whole image hash. */
+ PCRTCRSPCPEIMAGEPAGEHASHES pData;
+ /** Field the user can use to store the number of pages in pData. */
+ uint32_t cPages;
+} RTCRSPCSERIALIZEDPAGEHASHES;
+/** Pointer to a serialized wrapper for page hashes. */
+typedef RTCRSPCSERIALIZEDPAGEHASHES *PRTCRSPCSERIALIZEDPAGEHASHES;
+/** Pointer to a const serialized wrapper for page hashes. */
+typedef RTCRSPCSERIALIZEDPAGEHASHES const *PCRTCRSPCSERIALIZEDPAGEHASHES;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRSPCSERIALIZEDPAGEHASHES, RTDECL, RTCrSpcSerializedPageHashes, SetCore.Asn1Core);
+
+RTDECL(int) RTCrSpcSerializedPageHashes_UpdateDerivedData(PRTCRSPCSERIALIZEDPAGEHASHES pThis);
+
+
+/**
+ * Data type selection for RTCRSPCSERIALIZEDOBJECTATTRIBUTE.
+ */
+typedef enum RTCRSPCSERIALIZEDOBJECTATTRIBUTETYPE
+{
+ /** Invalid zero entry. */
+ RTCRSPCSERIALIZEDOBJECTATTRIBUTETYPE_INVALID = 0,
+ /** Not present pro forma. */
+ RTCRSPCSERIALIZEDOBJECTATTRIBUTETYPE_NOT_PRESENT,
+ /** Unknown object. */
+ RTCRSPCSERIALIZEDOBJECTATTRIBUTETYPE_UNKNOWN,
+ /** SHA-1 page hashes (pPageHashes). */
+ RTCRSPCSERIALIZEDOBJECTATTRIBUTETYPE_PAGE_HASHES_V1,
+ /** SHA-256 page hashes (pPageHashes). */
+ RTCRSPCSERIALIZEDOBJECTATTRIBUTETYPE_PAGE_HASHES_V2,
+ /** End of valid values. */
+ RTCRSPCSERIALIZEDOBJECTATTRIBUTETYPE_END,
+ /** Blow up the type to at least 32-bits. */
+ RTCRSPCSERIALIZEDOBJECTATTRIBUTETYPE_32BIT_HACK
+} RTCRSPCSERIALIZEDOBJECTATTRIBUTETYPE;
+
+/**
+ * One serialized object attribute (PE image data).
+ */
+typedef struct RTCRSPCSERIALIZEDOBJECTATTRIBUTE
+{
+ /** Sequence core. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** The attribute type. */
+ RTASN1OBJID Type;
+ /** The allocation of the data type. */
+ RTASN1ALLOCATION Allocation;
+ /** Indicates the valid value in the union. */
+ RTCRSPCSERIALIZEDOBJECTATTRIBUTETYPE enmType;
+ /** Union with data format depending on the Type. */
+ union
+ {
+ /** The unknown value (RTCRSPCSERIALIZEDOBJECTATTRIBUTETYPE_UNKNOWN). */
+ PRTASN1CORE pCore;
+ /** Page hashes (RTCRSPCSERIALIZEDOBJECTATTRIBUTETYPE_PAGE_HASHES_V1 or
+ * RTCRSPCSERIALIZEDOBJECTATTRIBUTETYPE_PAGE_HASHES_V2). */
+ PRTCRSPCSERIALIZEDPAGEHASHES pPageHashes;
+ } u;
+} RTCRSPCSERIALIZEDOBJECTATTRIBUTE;
+/** Pointer to a serialized object attribute. */
+typedef RTCRSPCSERIALIZEDOBJECTATTRIBUTE *PRTCRSPCSERIALIZEDOBJECTATTRIBUTE;
+/** Pointer to a const serialized object attribute. */
+typedef RTCRSPCSERIALIZEDOBJECTATTRIBUTE const *PCRTCRSPCSERIALIZEDOBJECTATTRIBUTE;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRSPCSERIALIZEDOBJECTATTRIBUTE, RTDECL, RTCrSpcSerializedObjectAttribute, SeqCore.Asn1Core);
+
+RTDECL(int) RTCrSpcSerializedObjectAttribute_SetV1Hashes(PRTCRSPCSERIALIZEDOBJECTATTRIBUTE pThis,
+ PCRTCRSPCSERIALIZEDPAGEHASHES, PCRTASN1ALLOCATORVTABLE pAllocator);
+RTDECL(int) RTCrSpcSerializedObjectAttribute_SetV2Hashes(PRTCRSPCSERIALIZEDOBJECTATTRIBUTE pThis,
+ PCRTCRSPCSERIALIZEDPAGEHASHES, PCRTASN1ALLOCATORVTABLE pAllocator);
+
+/** @name RTCRSPCSERIALIZEDOBJECTATTRIBUTE::Type values
+ * @{ */
+/** Serialized object attribute type for page hashes version 1. */
+#define RTCRSPC_PE_IMAGE_HASHES_V1_OID "1.3.6.1.4.1.311.2.3.1"
+/** Serialized object attribute type for page hashes version 2. */
+#define RTCRSPC_PE_IMAGE_HASHES_V2_OID "1.3.6.1.4.1.311.2.3.2"
+/** @} */
+
+
+/*
+ * Set of serialized object attributes (PE image data).
+ */
+RTASN1_IMPL_GEN_SET_OF_TYPEDEFS_AND_PROTOS(RTCRSPCSERIALIZEDOBJECTATTRIBUTES, RTCRSPCSERIALIZEDOBJECTATTRIBUTE, RTDECL,
+ RTCrSpcSerializedObjectAttributes);
+
+/** The UUID found in RTCRSPCSERIALIZEDOBJECT::Uuid for
+ * RTCRSPCSERIALIZEDOBJECTATTRIBUTES. */
+#define RTCRSPCSERIALIZEDOBJECT_UUID_STR "d586b5a6-a1b4-6624-ae05-a217da8e60d6"
+
+
+/**
+ * Decoded encapsulated data type selection in RTCRSPCSERIALIZEDOBJECT.
+ */
+typedef enum RTCRSPCSERIALIZEDOBJECTTYPE
+{
+ /** Invalid zero value. */
+ RTCRSPCSERIALIZEDOBJECTTYPE_INVALID = 0,
+ /** Serialized object attributes (RTCRSPCSERIALIZEDOBJECT_UUID_STR / pAttribs). */
+ RTCRSPCSERIALIZEDOBJECTTYPE_ATTRIBUTES,
+ /** End of valid values. */
+ RTCRSPCSERIALIZEDOBJECTTYPE_END,
+ /** MAke sure the type is at least 32-bit wide. */
+ RTCRSPCSERIALIZEDOBJECTTYPE_32BIT_HACK = 0x7fffffff
+} RTCRSPCSERIALIZEDOBJECTTYPE;
+
+/**
+ * A serialized object (PE image data).
+ */
+typedef struct RTCRSPCSERIALIZEDOBJECT
+{
+ /** Sequence core. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** The UUID of the data object. */
+ RTASN1OCTETSTRING Uuid;
+ /** Serialized data object. */
+ RTASN1OCTETSTRING SerializedData;
+
+ /** Indicates the valid pointer in the union. */
+ RTCRSPCSERIALIZEDOBJECTTYPE enmType;
+ /** Union of pointers shadowing SerializedData.pEncapsulated. */
+ union
+ {
+ /** Generic core pointer. */
+ PRTASN1CORE pCore;
+ /** Pointer to decoded data if Uuid is RTCRSPCSERIALIZEDOBJECT_UUID_STR. */
+ PRTCRSPCSERIALIZEDOBJECTATTRIBUTES pData;
+ } u;
+} RTCRSPCSERIALIZEDOBJECT;
+/** Pointer to a serialized object (PE image data). */
+typedef RTCRSPCSERIALIZEDOBJECT *PRTCRSPCSERIALIZEDOBJECT;
+/** Pointer to a const serialized object (PE image data). */
+typedef RTCRSPCSERIALIZEDOBJECT const *PCRTCRSPCSERIALIZEDOBJECT;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRSPCSERIALIZEDOBJECT, RTDECL, RTCrSpcSerializedObject, SeqCore.Asn1Core);
+
+
+/**
+ * RTCRSPCSTRING choices.
+ */
+typedef enum RTCRSPCSTRINGCHOICE
+{
+ /** Invalid zero value. */
+ RTCRSPCSTRINGCHOICE_INVALID = 0,
+ /** Not present. */
+ RTCRSPCSTRINGCHOICE_NOT_PRESENT,
+ /** UCS-2 string (pUcs2). */
+ RTCRSPCSTRINGCHOICE_UCS2,
+ /** ASCII string (pAscii). */
+ RTCRSPCSTRINGCHOICE_ASCII,
+ /** End of valid values. */
+ RTCRSPCSTRINGCHOICE_END,
+ /** Blow the type up to 32-bit. */
+ RTCRSPCSTRINGCHOICE_32BIT_HACK = 0x7fffffff
+} RTCRSPCSTRINGCHOICE;
+
+/**
+ * Stupid microsoft choosy string type.
+ */
+typedef struct RTCRSPCSTRING
+{
+ /** Dummy core. */
+ RTASN1DUMMY Dummy;
+ /** Allocation of what the pointer below points to. */
+ RTASN1ALLOCATION Allocation;
+ /** Pointer choice.*/
+ RTCRSPCSTRINGCHOICE enmChoice;
+ /** Pointer union. */
+ union
+ {
+ /** Tag 0, implicit: UCS-2 (BMP) string. */
+ PRTASN1STRING pUcs2;
+ /** Tag 1, implicit: ASCII (IA5) string. */
+ PRTASN1STRING pAscii;
+ } u;
+} RTCRSPCSTRING;
+/** Pointer to a stupid microsoft string choice. */
+typedef RTCRSPCSTRING *PRTCRSPCSTRING;
+/** Pointer to a const stupid microsoft string choice. */
+typedef RTCRSPCSTRING const *PCRTCRSPCSTRING;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRSPCSTRING, RTDECL, RTCrSpcString, Dummy.Asn1Core);
+
+RTDECL(int) RTCrSpcString_SetUcs2(PRTCRSPCSTRING pThis, PCRTASN1STRING pToClone, PCRTASN1ALLOCATORVTABLE pAllocator);
+RTDECL(int) RTCrSpcString_SetAscii(PRTCRSPCSTRING pThis, PCRTASN1STRING pToClone, PCRTASN1ALLOCATORVTABLE pAllocator);
+
+
+/**
+ * RTCRSPCSTRING choices.
+ */
+typedef enum RTCRSPCLINKCHOICE
+{
+ /** Invalid zero value. */
+ RTCRSPCLINKCHOICE_INVALID = 0,
+ /** Not present. */
+ RTCRSPCLINKCHOICE_NOT_PRESENT,
+ /** URL (ASCII) string (pUrl). */
+ RTCRSPCLINKCHOICE_URL,
+ /** Serialized object (pMoniker). */
+ RTCRSPCLINKCHOICE_MONIKER,
+ /** Filename (pT2). */
+ RTCRSPCLINKCHOICE_FILE,
+ /** End of valid values. */
+ RTCRSPCLINKCHOICE_END,
+ /** Blow the type up to 32-bit. */
+ RTCRSPCLINKCHOICE_32BIT_HACK = 0x7fffffff
+} RTCRSPCLINKCHOICE;
+
+/**
+ * PE image data link.
+ */
+typedef struct RTCRSPCLINK
+{
+ /** Dummy core. */
+ RTASN1DUMMY Dummy;
+ /** Allocation of what the pointer below points to. */
+ RTASN1ALLOCATION Allocation;
+ /** Pointer choice.*/
+ RTCRSPCLINKCHOICE enmChoice;
+ /** Pointer union. */
+ union
+ {
+ /** Tag 0, implicit: An URL encoded as an IA5 STRING. */
+ PRTASN1STRING pUrl;
+ /** Tag 1, implicit: A serialized object. */
+ PRTCRSPCSERIALIZEDOBJECT pMoniker;
+ /** Tag 2, explicit: The default, a file name.
+ * Documented to be set to "<<<Obsolete>>>" when used. */
+ struct
+ {
+ /** Context tag 2. */
+ RTASN1CONTEXTTAG2 CtxTag2;
+ /** The file name string. */
+ RTCRSPCSTRING File;
+ } *pT2;
+ } u;
+} RTCRSPCLINK;
+/** Poitner to a PE image data link. */
+typedef RTCRSPCLINK *PRTCRSPCLINK;
+/** Poitner to a const PE image data link. */
+typedef RTCRSPCLINK const *PCRTCRSPCLINK;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRSPCLINK, RTDECL, RTCrSpcLink, Dummy.Asn1Core);
+
+RTDECL(int) RTCrSpcLink_SetUrl(PRTCRSPCLINK pThis, PCRTASN1STRING pToClone, PCRTASN1ALLOCATORVTABLE pAllocator);
+RTDECL(int) RTCrSpcLink_SetMoniker(PRTCRSPCLINK pThis, PCRTCRSPCSERIALIZEDOBJECT pToClone, PCRTASN1ALLOCATORVTABLE pAllocator);
+RTDECL(int) RTCrSpcLink_SetFile(PRTCRSPCLINK pThis, PCRTCRSPCSTRING pToClone, PCRTASN1ALLOCATORVTABLE pAllocator);
+
+
+#if 0 /** @todo Might not be the correct bit order. */
+/**
+ * Flag values for RTCRSPCPEIMAGEDATA::Flags and RTCRSPCPEIMAGEDATA::fFlags.
+ */
+typedef enum RTCRSPCPEIMAGEFLAGS
+{
+ RTCRSPCPEIMAGEFLAGS_INCLUDE_RESOURCES = 0,
+ RTCRSPCPEIMAGEFLAGS_INCLUDE_DEBUG_INFO = 1,
+ RTCRSPCPEIMAGEFLAGS_IMPORT_ADDRESS_TABLE = 2
+} RTCRSPCPEIMAGEFLAGS;
+#endif
+
+
+/**
+ * Authenticode PE Image data.
+ */
+typedef struct RTCRSPCPEIMAGEDATA
+{
+ /** Sequence core. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** One of the RTCRSPCPEIMAGEFLAGS value, default is
+ * RTCRSPCPEIMAGEFLAGS_INCLUDE_RESOURCES. Obsolete with v2 page hashes? */
+ RTASN1BITSTRING Flags;
+ /** Tag 0, explicit: Link to the data. */
+ struct
+ {
+ /** Context tag 0. */
+ RTASN1CONTEXTTAG0 CtxTag0;
+ /** Link to the data. */
+ RTCRSPCLINK File;
+ } T0;
+} RTCRSPCPEIMAGEDATA;
+/** Pointer to a authenticode PE image data representation. */
+typedef RTCRSPCPEIMAGEDATA *PRTCRSPCPEIMAGEDATA;
+/** Pointer to a const authenticode PE image data representation. */
+typedef RTCRSPCPEIMAGEDATA const *PCRTCRSPCPEIMAGEDATA;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRSPCPEIMAGEDATA, RTDECL, RTCrSpcPeImageData, SeqCore.Asn1Core);
+
+RTDECL(int) RTCrSpcPeImageData_SetFlags(PRTCRSPCPEIMAGEDATA pThis, PCRTASN1BITSTRING pToClone, PCRTASN1ALLOCATORVTABLE pAllocator);
+RTDECL(int) RTCrSpcPeImageData_SetFile(PRTCRSPCPEIMAGEDATA pThis, PCRTCRSPCLINK pToClone, PCRTASN1ALLOCATORVTABLE pAllocator);
+
+/** The object ID for SpcPeImageData. */
+#define RTCRSPCPEIMAGEDATA_OID "1.3.6.1.4.1.311.2.1.15"
+
+
+/**
+ * Data type selection for RTCRSPCATTRIBUTETYPEANDOPTIONALVALUE.
+ */
+typedef enum RTCRSPCAAOVTYPE
+{
+ /** Invalid zero entry. */
+ RTCRSPCAAOVTYPE_INVALID = 0,
+ /** Not present (pro forma). */
+ RTCRSPCAAOVTYPE_NOT_PRESENT,
+ /** Unknown object. */
+ RTCRSPCAAOVTYPE_UNKNOWN,
+ /** PE image data (pPeImage). */
+ RTCRSPCAAOVTYPE_PE_IMAGE_DATA,
+ /** End of valid values. */
+ RTCRSPCAAOVTYPE_END,
+ /** Blow up the type to at least 32-bits. */
+ RTCRSPCAAOVTYPE_32BIT_HACK
+} RTCRSPCAAOVTYPE;
+
+/**
+ * Authenticode attribute type and optional value.
+ *
+ * Note! Spec says the value should be explicitly tagged, but in real life
+ * it isn't. So, not very optional?
+ */
+typedef struct RTCRSPCATTRIBUTETYPEANDOPTIONALVALUE
+{
+ /** Sequence core. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** An object ID indicating the type of the value. */
+ RTASN1OBJID Type;
+ /** Allocation of the optional data value. */
+ RTASN1ALLOCATION Allocation;
+ /** The valid pointer. */
+ RTCRSPCAAOVTYPE enmType;
+ /** The value part depends on the Type. */
+ union
+ {
+ /** RTCRSPCAAOVTYPE_UNKNOWN / Generic. */
+ PRTASN1CORE pCore;
+ /** RTCRSPCAAOVTYPE_PE_IMAGE_DATA / RTCRSPCPEIMAGEDATA_OID. */
+ PRTCRSPCPEIMAGEDATA pPeImage;
+ } uValue;
+} RTCRSPCATTRIBUTETYPEANDOPTIONALVALUE;
+/** Pointer to a authentication attribute type and optional value
+ * representation. */
+typedef RTCRSPCATTRIBUTETYPEANDOPTIONALVALUE *PRTCRSPCATTRIBUTETYPEANDOPTIONALVALUE;
+/** Pointer to a const authentication attribute type and optional value
+ * representation. */
+typedef RTCRSPCATTRIBUTETYPEANDOPTIONALVALUE const *PCRTCRSPCATTRIBUTETYPEANDOPTIONALVALUE;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRSPCATTRIBUTETYPEANDOPTIONALVALUE, RTDECL, RTCrSpcAttributeTypeAndOptionalValue, SeqCore.Asn1Core);
+
+RTDECL(int) RTCrSpcAttributeTypeAndOptionalValue_SetPeImage(PRTCRSPCATTRIBUTETYPEANDOPTIONALVALUE pThis,
+ PCRTCRSPCPEIMAGEDATA pToClone, PCRTASN1ALLOCATORVTABLE pAllocator);
+
+/**
+ * Authenticode indirect data content.
+ */
+typedef struct RTCRSPCINDIRECTDATACONTENT
+{
+ /** Sequence core. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** Additional data. */
+ RTCRSPCATTRIBUTETYPEANDOPTIONALVALUE Data;
+ /** The whole image digest. */
+ RTCRPKCS7DIGESTINFO DigestInfo;
+} RTCRSPCINDIRECTDATACONTENT;
+/** Pointer to a authenticode indirect data content representation. */
+typedef RTCRSPCINDIRECTDATACONTENT *PRTCRSPCINDIRECTDATACONTENT;
+/** Pointer to a const authenticode indirect data content representation. */
+typedef RTCRSPCINDIRECTDATACONTENT const *PCRTCRSPCINDIRECTDATACONTENT;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRSPCINDIRECTDATACONTENT, RTDECL, RTCrSpcIndirectDataContent, SeqCore.Asn1Core);
+
+/** The object ID for SpcIndirectDataContent. */
+#define RTCRSPCINDIRECTDATACONTENT_OID "1.3.6.1.4.1.311.2.1.4"
+
+/**
+ * Check the sanity of an Authenticode SPCIndirectDataContent object.
+ *
+ * @returns IPRT status code
+ * @param pIndData The Authenticode SPCIndirectDataContent to
+ * check.
+ * @param pSignedData The related signed data object.
+ * @param fFlags RTCRSPCINDIRECTDATACONTENT_SANITY_F_XXX.
+ * @param pErrInfo Optional error info.
+ */
+RTDECL(int) RTCrSpcIndirectDataContent_CheckSanityEx(PCRTCRSPCINDIRECTDATACONTENT pIndData, PCRTCRPKCS7SIGNEDDATA pSignedData,
+ uint32_t fFlags, PRTERRINFO pErrInfo);
+/** @name RTCRSPCINDIRECTDATACONTENT_SANITY_F_XXX for RTCrSpcIndirectDataContent_CheckSanityEx.
+ * @{ */
+/** The digest hash algorithm must be known to IPRT. */
+#define RTCRSPCINDIRECTDATACONTENT_SANITY_F_ONLY_KNOWN_HASH RT_BIT_32(0)
+/** PE image signing, check expectations of the spec. */
+#define RTCRSPCINDIRECTDATACONTENT_SANITY_F_PE_IMAGE RT_BIT_32(1)
+/** @} */
+
+/**
+ * Gets the first SPC serialized object attribute in a SPC PE image.
+ *
+ * @returns Pointer to the attribute with the given type, NULL if not found.
+ * @param pThis The Authenticode SpcIndirectDataContent.
+ * @param enmType The type of attribute to get.
+ */
+RTDECL(PCRTCRSPCSERIALIZEDOBJECTATTRIBUTE)
+RTCrSpcIndirectDataContent_GetPeImageObjAttrib(PCRTCRSPCINDIRECTDATACONTENT pThis,
+ RTCRSPCSERIALIZEDOBJECTATTRIBUTETYPE enmType);
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_crypto_spc_h */
+
diff --git a/include/iprt/crypto/ssl.h b/include/iprt/crypto/ssl.h
new file mode 100644
index 00000000..5c69811b
--- /dev/null
+++ b/include/iprt/crypto/ssl.h
@@ -0,0 +1,143 @@
+/** @file
+ * IPRT - Secure Socket Layer (SSL) / Transport Security Layer (TLS)
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_crypto_ssl_h
+#define IPRT_INCLUDED_crypto_ssl_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+#include <iprt/sg.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_crssl RTCrSsl - Secure Socket Layer (SSL) / Transport Security Layer (TLS)
+ * @ingroup grp_rt_crypto
+ * @{
+ */
+
+/** SSL handle. */
+typedef R3PTRTYPE(struct RTCRSSLINT *) RTCRSSL;
+/** Pointer to a SSL handle. */
+typedef RTCRSSL *PRTCRSSL;
+/** Nil SSL handle. */
+#define NIL_RTCRSSL ((RTCRSSL)0)
+
+/** SSL session handle. */
+typedef R3PTRTYPE(struct RTCRSSLSESSIONINT *) RTCRSSLSESSION;
+/** Pointer to a SSL session handle. */
+typedef RTCRSSLSESSION *PRTCRSSLSESSION;
+/** Nil SSL session handle. */
+#define NIL_RTCRSSLSESSION ((RTCRSSLSESSION)0)
+
+
+RTDECL(int) RTCrSslCreate(PRTCRSSL phSsl, uint32_t fFlags);
+
+/**
+ * Retains a reference to the SSL handle.
+ *
+ * @returns New reference count, UINT32_MAX on invalid handle (asserted).
+ *
+ * @param hSsl The SSL handle.
+ */
+RTDECL(uint32_t) RTCrSslRetain(RTCRSSL hSsl);
+
+/**
+ * Release a reference to the SSL handle.
+ *
+ * @returns New reference count, UINT32_MAX on invalid handle (asserted).
+ *
+ * @param hSsl The SSL handle. The NIL handle is quietly
+ * ignored and 0 is returned.
+ */
+RTDECL(uint32_t) RTCrSslRelease(RTCRSSL hSsl);
+
+#define RTCRSSL_FILE_F_PEM 0
+#define RTCRSSL_FILE_F_ASN1 RT_BIT_32(1)
+
+RTDECL(int) RTCrSslSetCertificateFile(RTCRSSL hSsl, const char *pszFile, uint32_t fFlags);
+RTDECL(int) RTCrSslSetPrivateKeyFile(RTCRSSL hSsl, const char *pszFile, uint32_t fFlags);
+RTDECL(int) RTCrSslLoadTrustedRootCerts(RTCRSSL hSsl, const char *pszFile, const char *pszDir);
+RTDECL(int) RTCrSslSetNoPeerVerify(RTCRSSL hSsl);
+/** @todo Min/max protocol setters. */
+
+
+
+RTDECL(int) RTCrSslCreateSession(RTCRSSL hSsl, RTSOCKET hSocket, uint32_t fFlags, PRTCRSSLSESSION phSslSession);
+RTDECL(int) RTCrSslCreateSessionForNativeSocket(RTCRSSL hSsl, RTHCINTPTR hNativeSocket, uint32_t fFlags,
+ PRTCRSSLSESSION phSslSession);
+/** @name RTCRSSLSESSION_F_XXX - Flags for RTCrSslCreateSession and RTCrSslCreateSessionForNativeSocket.
+ * @{ */
+/** The socket is non-blocking. */
+#define RTCRSSLSESSION_F_NON_BLOCKING RT_BIT_32(0)
+/** @} */
+
+/**
+ * Retains a reference to the SSL session handle.
+ *
+ * @returns New reference count, UINT32_MAX on invalid handle (asserted).
+ *
+ * @param hSslSession The SSL session handle.
+ */
+RTDECL(uint32_t) RTCrSslSessionRetain(RTCRSSLSESSION hSslSession);
+
+/**
+ * Release a reference to the SSL handle.
+ *
+ * @returns New reference count, UINT32_MAX on invalid handle (asserted).
+ *
+ * @param hSslSession The SSL session handle. The NIL handle is quietly
+ * ignored and 0 is returned.
+ */
+RTDECL(uint32_t) RTCrSslSessionRelease(RTCRSSLSESSION hSslSession);
+
+RTDECL(int) RTCrSslSessionAccept(RTCRSSLSESSION hSslSession, uint32_t fFlags);
+RTDECL(int) RTCrSslSessionConnect(RTCRSSLSESSION hSslSession, uint32_t fFlags);
+
+RTDECL(const char *) RTCrSslSessionGetVersion(RTCRSSLSESSION hSslSession);
+RTDECL(int) RTCrSslSessionGetCertIssuerNameAsString(RTCRSSLSESSION hSslSession, char *pszBuf, size_t cbBuf, size_t *pcbActual);
+RTDECL(bool) RTCrSslSessionPending(RTCRSSLSESSION hSslSession);
+RTDECL(ssize_t) RTCrSslSessionRead(RTCRSSLSESSION hSslSession, void *pvBuf, size_t cbToRead);
+RTDECL(ssize_t) RTCrSslSessionWrite(RTCRSSLSESSION hSslSession, void const *pvBuf, size_t cbToWrite);
+
+
+/** @} */
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_crypto_ssl_h */
+
diff --git a/include/iprt/crypto/store.h b/include/iprt/crypto/store.h
new file mode 100644
index 00000000..c25e21e7
--- /dev/null
+++ b/include/iprt/crypto/store.h
@@ -0,0 +1,410 @@
+/** @file
+ * IPRT - Cryptographic (Certificate) Store.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_crypto_store_h
+#define IPRT_INCLUDED_crypto_store_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/crypto/x509.h>
+#include <iprt/crypto/taf.h>
+#include <iprt/sha.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_crstore RTCrStore - Crypotgraphic (Certificate) Store.
+ * @ingroup grp_rt_crypto
+ * @{
+ */
+
+
+/**
+ * A certificate store search.
+ *
+ * Used by the store provider to keep track of the current location of a
+ * certificate search.
+ */
+typedef struct RTCRSTORECERTSEARCH
+{
+ /** Opaque provider specific storage.
+ *
+ * Provider restriction: The provider is only allowed to use the two first
+ * entries for the find-all searches, because the front-end API may want the
+ * last two for implementing specific searches on top of it. */
+ uintptr_t auOpaque[4];
+} RTCRSTORECERTSEARCH;
+/** Pointer to a certificate store search. */
+typedef RTCRSTORECERTSEARCH *PRTCRSTORECERTSEARCH;
+
+
+/**
+ * Info about a wanted certificate.
+ *
+ * All the search criteria are optional, but for a safe and efficient search
+ * it's recommended to specify all possible ones. If none are given, the search
+ * function will fail.
+ *
+ * For use with RTCrStoreCertAddFromFishingExpedition and others.
+ */
+typedef struct RTCRCERTWANTED
+{
+ /** The certificate subject name, optional.
+ * The format is: "C=US, ST=California, L=Redwood Shores, O=Oracle Corporation" */
+ const char *pszSubject;
+ /** The size of the DER (ASN.1) encoded certificate, optional (0). */
+ uint16_t cbEncoded;
+ /** Set if abSha1 contains a valid SHA-1 fingerprint. */
+ bool fSha1Fingerprint;
+ /** Set if abSha512 contains a valid SHA-512 fingerprint. */
+ bool fSha512Fingerprint;
+ /** The SHA-1 fingerprint (of the encoded data). */
+ uint8_t abSha1[RTSHA1_HASH_SIZE];
+ /** The SHA-512 fingerprint (of the encoded data). */
+ uint8_t abSha512[RTSHA512_HASH_SIZE];
+ /** User pointer for directly associating other data with the entry.
+ * Subclassing the structure isn't possible because it's passed as an array. */
+ void const *pvUser;
+} RTCRCERTWANTED;
+/** Pointer to a const certificat wanted structure. */
+typedef RTCRCERTWANTED const *PCRTCRCERTWANTED;
+
+
+/**
+ * Standard store identifiers.
+ *
+ * This is a least common denominator approach to system specific certificate
+ * stores, could be extended to include things other than certificates later if
+ * we need it.
+ *
+ * Windows has lots of different stores, they'll be combined by the
+ * implementation, possibly leading to duplicates. The user stores on Windows
+ * seems to be unioned with the system (machine) stores.
+ *
+ * Linux may have different stores depending on the distro/version/installation,
+ * in which case we'll combine them, which will most likely lead to
+ * duplicates just like on windows. Haven't found any easily accessible
+ * per-user certificate stores on linux yet, so they'll all be empty.
+ *
+ * Mac OS X seems a lot simpler, at least from the GUI point of view. Each
+ * keychains as a "Certificates" folder (the "My Certificates" folder seems to
+ * only be a matching of "Keys" and "Certificates"). However, there are two
+ * system keychains that we need to combine, "System" and "System Roots". As
+ * with Windows and Linux, there is a possibility for duplicates here.
+ *
+ * On solaris we have currently no idea where to look for a certificate store,
+ * so that doesn't yet work.
+ *
+ * Because of the OS X setup, we do not provide any purpose specific
+ */
+typedef enum RTCRSTOREID
+{
+ /** Mandatory invalid zero value. */
+ RTCRSTOREID_INVALID = 0,
+ /** Open the certificate store of the current user containing trusted
+ * CAs and certificates.
+ * @remarks This may or may not include all the certificates in the system
+ * store, that's host dependent. So, you better look in both. */
+ RTCRSTOREID_USER_TRUSTED_CAS_AND_CERTIFICATES,
+ /** Open the certificate store of the system containg trusted CAs
+ * and certificates. */
+ RTCRSTOREID_SYSTEM_TRUSTED_CAS_AND_CERTIFICATES,
+ /** Open the certificate store of the current user containing intermediate CAs.
+ * @remarks This may or may not include all the certificates in the system
+ * store, that's host dependent. So, you better look in both. */
+ RTCRSTOREID_USER_INTERMEDIATE_CAS,
+ /** Open the certificate store of the system containg intermediate CAs. */
+ RTCRSTOREID_SYSTEM_INTERMEDIATE_CAS,
+ /** End of valid values. */
+ RTCRSTOREID_END,
+ /** Traditional enum type compression prevention hack. */
+ RTCRSTOREID_32BIT_HACK = 0x7fffffff
+} RTCRSTOREID;
+
+/**
+ * Creates a snapshot of a standard store.
+ *
+ * This will return an in-memory store containing all data from the given store.
+ * There will be no duplicates in this one.
+ *
+ * @returns IPRT status code.
+ * @param phStore Where to return the store handle. Use
+ * RTCrStoreRelease to release it.
+ * @param enmStoreId The store to snapshot.
+ * @param pErrInfo Where to return additional error/warning info.
+ * Optional.
+ */
+RTDECL(int) RTCrStoreCreateSnapshotById(PRTCRSTORE phStore, RTCRSTOREID enmStoreId, PRTERRINFO pErrInfo);
+
+RTDECL(int) RTCrStoreCreateSnapshotOfUserAndSystemTrustedCAsAndCerts(PRTCRSTORE phStore, PRTERRINFO pErrInfo);
+
+RTDECL(int) RTCrStoreCreateInMem(PRTCRSTORE phStore, uint32_t cSizeHint);
+RTDECL(int) RTCrStoreCreateInMemEx(PRTCRSTORE phStore, uint32_t cSizeHint, RTCRSTORE hParentStore);
+
+RTDECL(uint32_t) RTCrStoreRetain(RTCRSTORE hStore);
+RTDECL(uint32_t) RTCrStoreRelease(RTCRSTORE hStore);
+RTDECL(PCRTCRCERTCTX) RTCrStoreCertByIssuerAndSerialNo(RTCRSTORE hStore, PCRTCRX509NAME pIssuer, PCRTASN1INTEGER pSerialNo);
+
+/**
+ * Add a certificate to the store.
+ *
+ * @returns IPRT status code.
+ * @retval VWRN_ALREADY_EXISTS if the certificate is already present and
+ * RTCRCERTCTX_F_ADD_IF_NOT_FOUND was specified.
+ * @retval VERR_WRITE_PROTECT if the store doesn't support adding.
+ * @param hStore The store to add the certificate to.
+ * @param fFlags RTCRCERTCTX_F_XXX. Encoding must be specified.
+ * RTCRCERTCTX_F_ADD_IF_NOT_FOUND is supported.
+ * @param pvSrc The encoded certificate bytes.
+ * @param cbSrc The size of the encoded certificate.
+ * @param pErrInfo Where to return additional error/warning info.
+ * Optional.
+ */
+RTDECL(int) RTCrStoreCertAddEncoded(RTCRSTORE hStore, uint32_t fFlags, void const *pvSrc, size_t cbSrc, PRTERRINFO pErrInfo);
+
+/**
+ * Add an X.509 packaged certificate to the store.
+ *
+ * @returns IPRT status code.
+ * @retval VWRN_ALREADY_EXISTS if the certificate is already present and
+ * RTCRCERTCTX_F_ADD_IF_NOT_FOUND was specified.
+ * @retval VERR_WRITE_PROTECT if the store doesn't support adding.
+ * @param hStore The store to add the certificate to.
+ * @param fFlags RTCRCERTCTX_F_XXX. Encoding must is optional,
+ * but must be RTCRCERTCTX_F_ENC_X509_DER if given.
+ * RTCRCERTCTX_F_ADD_IF_NOT_FOUND is supported.
+ * @param pCertificate The certificate to add. We may have to encode
+ * it, thus not const.
+ * @param pErrInfo Where to return additional error/warning info.
+ * Optional.
+ */
+RTDECL(int) RTCrStoreCertAddX509(RTCRSTORE hStore, uint32_t fFlags, PRTCRX509CERTIFICATE pCertificate, PRTERRINFO pErrInfo);
+
+/**
+ * Adds certificates from files in the specified directory.
+ *
+ * @returns IPRT status code. Even when RTCRCERTCTX_F_ADD_CONTINUE_ON_ERROR is
+ * used, an error is returned as an error (and not a warning).
+ *
+ * @param hStore The store to add the certificate(s) to.
+ * @param fFlags RTCRCERTCTX_F_ADD_IF_NOT_FOUND and/or
+ * RTCRCERTCTX_F_ADD_CONTINUE_ON_ERROR.
+ * @param pszDir The path to the directory.
+ * @param paSuffixes List of suffixes of files to process.
+ * @param cSuffixes Number of suffixes. If this is 0, all files are
+ * processed.
+ * @param pErrInfo Where to return additional error/warning info.
+ * Optional.
+ */
+RTDECL(int) RTCrStoreCertAddFromDir(RTCRSTORE hStore, uint32_t fFlags, const char *pszDir,
+ PCRTSTRTUPLE paSuffixes, size_t cSuffixes, PRTERRINFO pErrInfo);
+
+RTDECL(int) RTCrStoreCertAddWantedFromDir(RTCRSTORE hStore, uint32_t fFlags,
+ const char *pszDir, PCRTSTRTUPLE paSuffixes, size_t cSuffixes,
+ PCRTCRCERTWANTED paWanted, size_t cWanted, bool *pafFound, PRTERRINFO pErrInfo);
+
+/**
+ * Adds certificates from the specified file.
+ *
+ * The supported file formats are:
+ * - PEM (base 64 blobs wrapped in -----BEGIN / END----). Support multiple
+ * certificates in one file.
+ * - Binary DER ASN.1 certificate. Only one per file.
+ * - Java key store version 2.
+ *
+ * @returns IPRT status code. Even when RTCRCERTCTX_F_ADD_CONTINUE_ON_ERROR is
+ * used, an error is returned as an error (and not a warning).
+ *
+ * @param hStore The store to add the certificate(s) to.
+ * @param fFlags RTCRCERTCTX_F_ADD_IF_NOT_FOUND and/or
+ * RTCRCERTCTX_F_ADD_CONTINUE_ON_ERROR.
+ * @param pszFilename The filename.
+ * @param pErrInfo Where to return additional error/warning info.
+ * Optional.
+ */
+RTDECL(int) RTCrStoreCertAddFromFile(RTCRSTORE hStore, uint32_t fFlags, const char *pszFilename, PRTERRINFO pErrInfo);
+
+RTDECL(int) RTCrStoreCertAddWantedFromFile(RTCRSTORE hStore, uint32_t fFlags, const char *pszFilename,
+ PCRTCRCERTWANTED paWanted, size_t cWanted, bool *pafFound, PRTERRINFO pErrInfo);
+
+/**
+ * Adds certificates from the specified java key store file.
+ *
+ * @returns IPRT status code. Even when RTCRCERTCTX_F_ADD_CONTINUE_ON_ERROR is
+ * used, an error is returned as an error (and not a warning).
+ *
+ * @param hStore The store to add the certificate(s) to.
+ * @param fFlags RTCRCERTCTX_F_ADD_IF_NOT_FOUND and/or
+ * RTCRCERTCTX_F_ADD_CONTINUE_ON_ERROR.
+ * @param pszFilename The path to the JKS file.
+ * @param pErrInfo Where to return additional error/warning info.
+ * Optional.
+ */
+RTDECL(int) RTCrStoreCertAddFromJavaKeyStore(RTCRSTORE hStore, uint32_t fFlags, const char *pszFilename, PRTERRINFO pErrInfo);
+
+/**
+ * Adds certificates from an in-memory java key store.
+ *
+ * @returns IPRT status code. Even when RTCRCERTCTX_F_ADD_CONTINUE_ON_ERROR is
+ * used, an error is returned as an error (and not a warning).
+ *
+ * @param hStore The store to add the certificate(s) to.
+ * @param fFlags RTCRCERTCTX_F_ADD_IF_NOT_FOUND and/or
+ * RTCRCERTCTX_F_ADD_CONTINUE_ON_ERROR.
+ * @param pvContent Pointer to the key store bytes.
+ * @param cbContent The size of the key store.
+ * @param pszErrorName The file name or whatever helpful indicator the
+ * caller want in the error messages.
+ * @param pErrInfo Where to return additional error/warning info.
+ * Optional.
+ */
+RTDECL(int) RTCrStoreCertAddFromJavaKeyStoreInMem(RTCRSTORE hStore, uint32_t fFlags, void const *pvContent, size_t cbContent,
+ const char *pszErrorName, PRTERRINFO pErrInfo);
+
+/**
+ * Adds all certificates from @a hStoreSrc into @a hStore.
+ *
+ * @returns IPRT status code. Even when RTCRCERTCTX_F_ADD_CONTINUE_ON_ERROR is
+ * used, an error is returned as an error (and not a warning).
+ *
+ * @param hStore The destination store.
+ * @param fFlags RTCRCERTCTX_F_ADD_IF_NOT_FOUND and/or
+ * RTCRCERTCTX_F_ADD_CONTINUE_ON_ERROR.
+ * @param hStoreSrc The source store.
+ */
+RTDECL(int) RTCrStoreCertAddFromStore(RTCRSTORE hStore, uint32_t fFlags, RTCRSTORE hStoreSrc);
+
+RTDECL(int) RTCrStoreCertAddWantedFromStore(RTCRSTORE hStore, uint32_t fFlags, RTCRSTORE hSrcStore,
+ PCRTCRCERTWANTED paWanted, size_t cWanted, bool *pafFound);
+
+RTDECL(int) RTCrStoreCertCheckWanted(RTCRSTORE hStore, PCRTCRCERTWANTED paWanted, size_t cWanted, bool *pafFound);
+
+
+RTDECL(int) RTCrStoreCertAddWantedFromFishingExpedition(RTCRSTORE hStore, uint32_t fFlags,
+ PCRTCRCERTWANTED paWanted, size_t cWanted,
+ bool *pafFound, PRTERRINFO pErrInfo);
+
+/**
+ * Exports the certificates in the store to a PEM file
+ *
+ * @returns IPRT status code.
+ * @param hStore The store which certificates should be exported.
+ * @param fFlags Reserved for the future, MBZ.
+ * @param pszFilename The name of the destination PEM file. This will
+ * be truncated.
+ */
+RTDECL(int) RTCrStoreCertExportAsPem(RTCRSTORE hStore, uint32_t fFlags, const char *pszFilename);
+
+/**
+ * Counts the number of certificates in the store.
+ *
+ * @returns Certificate count on success, UINT32_MAX on failure.
+ * @param hStore The store which certificates should be counted.
+ */
+RTDECL(uint32_t) RTCrStoreCertCount(RTCRSTORE hStore);
+
+RTDECL(int) RTCrStoreCertFindAll(RTCRSTORE hStore, PRTCRSTORECERTSEARCH pSearch);
+RTDECL(int) RTCrStoreCertFindBySubjectOrAltSubjectByRfc5280(RTCRSTORE hStore, PCRTCRX509NAME pSubject,
+ PRTCRSTORECERTSEARCH pSearch);
+RTDECL(PCRTCRCERTCTX) RTCrStoreCertSearchNext(RTCRSTORE hStore, PRTCRSTORECERTSEARCH pSearch);
+RTDECL(int) RTCrStoreCertSearchDestroy(RTCRSTORE hStore, PRTCRSTORECERTSEARCH pSearch);
+
+RTDECL(int) RTCrStoreConvertToOpenSslCertStore(RTCRSTORE hStore, uint32_t fFlags, void **ppvOpenSslStore, PRTERRINFO pErrInfo);
+RTDECL(int) RTCrStoreConvertToOpenSslCertStack(RTCRSTORE hStore, uint32_t fFlags, void **ppvOpenSslStack, PRTERRINFO pErrInfo);
+
+
+/** @} */
+
+
+/** @defgroup grp_rt_crcertctx RTCrCertCtx - (Store) Certificate Context.
+ * @{ */
+
+
+/**
+ * Certificate context.
+ *
+ * This is returned by the certificate store APIs and is part of a larger
+ * reference counted structure. All the data is read only.
+ */
+typedef struct RTCRCERTCTX
+{
+ /** Flags, RTCRCERTCTX_F_XXX. */
+ uint32_t fFlags;
+ /** The size of the (DER) encoded certificate. */
+ uint32_t cbEncoded;
+ /** Pointer to the (DER) encoded certificate. */
+ uint8_t const *pabEncoded;
+ /** Pointer to the decoded X.509 representation of the certificate.
+ * This can be NULL when pTaInfo is present. */
+ PCRTCRX509CERTIFICATE pCert;
+ /** Pointer to the decoded TrustAnchorInfo for the certificate. This can be
+ * NULL, even for trust anchors, as long as pCert isn't. */
+ PCRTCRTAFTRUSTANCHORINFO pTaInfo;
+ /** Reserved for future use. */
+ void *paReserved[2];
+} RTCRCERTCTX;
+
+/** @name RTCRCERTCTX_F_XXX.
+ * @{ */
+/** Encoding mask. */
+#define RTCRCERTCTX_F_ENC_MASK UINT32_C(0x000000ff)
+/** X.509 certificate, DER encoded. */
+#define RTCRCERTCTX_F_ENC_X509_DER UINT32_C(0x00000000)
+/** RTF-5914 trust anchor info, DER encoded. */
+#define RTCRCERTCTX_F_ENC_TAF_DER UINT32_C(0x00000001)
+#if 0
+/** Extended certificate, DER encoded. */
+#define RTCRCERTCTX_F_ENC_PKCS6_DER UINT32_C(0x00000002)
+#endif
+/** Mask containing the flags that ends up in the certificate context. */
+#define RTCRCERTCTX_F_MASK UINT32_C(0x000000ff)
+
+/** Add APIs: Add the certificate if not found. */
+#define RTCRCERTCTX_F_ADD_IF_NOT_FOUND UINT32_C(0x00010000)
+/** Add APIs: Continue on error when possible. */
+#define RTCRCERTCTX_F_ADD_CONTINUE_ON_ERROR UINT32_C(0x00020000)
+/** @} */
+
+
+RTDECL(uint32_t) RTCrCertCtxRetain(PCRTCRCERTCTX pCertCtx);
+RTDECL(uint32_t) RTCrCertCtxRelease(PCRTCRCERTCTX pCertCtx);
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_crypto_store_h */
+
diff --git a/include/iprt/crypto/taf.h b/include/iprt/crypto/taf.h
new file mode 100644
index 00000000..4966a7b2
--- /dev/null
+++ b/include/iprt/crypto/taf.h
@@ -0,0 +1,202 @@
+/** @file
+ * IPRT - Crypto - Trust Anchor Format (RFC-5914).
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_crypto_taf_h
+#define IPRT_INCLUDED_crypto_taf_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/asn1.h>
+#include <iprt/crypto/x509.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_crtaf RTCrTaf - Trust Anchor Format (RFC-5914)
+ * @ingroup grp_rt_crypto
+ * @{
+ */
+
+
+/**
+ * RFC-5914 CertPathControls (IPRT representation).
+ */
+typedef struct RTCRTAFCERTPATHCONTROLS
+{
+ /** Sequence core. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** The trust anchor subject. For use in path construction. */
+ RTCRX509NAME TaName;
+ /** Certificate, optional, implicit tag 0. */
+ RTCRX509CERTIFICATE Certificate;
+ /** Certificate policies, optional, implicit tag 1.
+ * @remarks This is an ASN.1 SEQUENCE, not an ASN.1 SET as the name
+ * mistakenly might be taken to indicate. */
+ RTCRX509CERTIFICATEPOLICIES PolicySet;
+ /** Policy flags, optional, implicit tag 2. */
+ RTASN1BITSTRING PolicyFlags;
+ /** Name constraints, optional, implicit tag 3. */
+ RTCRX509NAMECONSTRAINTS NameConstr;
+ /** Path length constraints, optional, implicit tag 4. */
+ RTASN1INTEGER PathLenConstraint;
+} RTCRTAFCERTPATHCONTROLS;
+/** Pointer to the IPRT representation of a RFC-5914 CertPathControls. */
+typedef RTCRTAFCERTPATHCONTROLS *PRTCRTAFCERTPATHCONTROLS;
+/** Pointer to the const IPRT representation of a RFC-5914 CertPathControls. */
+typedef RTCRTAFCERTPATHCONTROLS const *PCRTCRTAFCERTPATHCONTROLS;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRTAFCERTPATHCONTROLS, RTDECL, RTCrTafCertPathControls, SeqCore.Asn1Core);
+
+/** @name Bit definitions for RTCRTAFCERTPATHCONTROL::PolicyFlags
+ * @{ */
+#define RTCRTAFCERTPOLICYFLAGS_INHIBIT_POLICY_MAPPING 0
+#define RTCRTAFCERTPOLICYFLAGS_REQUIRE_EXPLICIT_POLICY 1
+#define RTCRTAFCERTPOLICYFLAGS_INHIBIT_ANY_POLICY 2
+/** @} */
+
+
+/**
+ * RFC-5914 TrustAnchorInfo (IPRT representation).
+ */
+typedef struct RTCRTAFTRUSTANCHORINFO
+{
+ /** Sequence core. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** The version number (defaults to v1). */
+ RTASN1INTEGER Version;
+ /** The public key of the trust anchor. */
+ RTCRX509SUBJECTPUBLICKEYINFO PubKey;
+ /** Key identifier. */
+ RTASN1OCTETSTRING KeyIdentifier;
+ /** Trust anchor title, optional, size 1 to 64. */
+ RTASN1STRING TaTitle;
+ /** Certificate path controls, optional. */
+ RTCRTAFCERTPATHCONTROLS CertPath;
+ /** Extensions, explicit optional, context tag 1. */
+ struct
+ {
+ /** Context tag 1. */
+ RTASN1CONTEXTTAG1 CtxTag1;
+ /** The extensions. */
+ RTCRX509EXTENSIONS Exts;
+ } T1;
+ /** Title language tag, implicit optional, context tag 2.
+ * Defaults to "en". */
+ RTASN1STRING TaTitleLangTag;
+} RTCRTAFTRUSTANCHORINFO;
+/** Pointer to the IPRT representation of a RFC-5914 TrustAnchorInfo. */
+typedef RTCRTAFTRUSTANCHORINFO *PRTCRTAFTRUSTANCHORINFO;
+/** Pointer to the const IPRT representation of a RFC-5914 TrustAnchorInfo. */
+typedef RTCRTAFTRUSTANCHORINFO const *PCRTCRTAFTRUSTANCHORINFO;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRTAFTRUSTANCHORINFO, RTDECL, RTCrTafTrustAnchorInfo, SeqCore.Asn1Core);
+
+/** TrustAnchorInfo version 1. */
+#define RTCRTAFTRUSTANCHORINFO_V1 1
+
+
+/** Indicates what kind of value a TrustAnchorChoice structure contains. */
+typedef enum RTCRTAFTRUSTANCHORCHOICEVAL
+{
+ /** Invalid zero value. */
+ RTCRTAFTRUSTANCHORCHOICEVAL_INVALID = 0,
+ /** RTCRTAFTRUSTANCHORCHOICE::u.pCertificate. */
+ RTCRTAFTRUSTANCHORCHOICEVAL_CERTIFICATE,
+ /** RTCRTAFTRUSTANCHORCHOICE::u.pT1. */
+ RTCRTAFTRUSTANCHORCHOICEVAL_TBS_CERTIFICATE,
+ /** RTCRTAFTRUSTANCHORCHOICE::u.pT2. */
+ RTCRTAFTRUSTANCHORCHOICEVAL_TRUST_ANCHOR_INFO,
+ /** End of valid choices. */
+ RTCRTAFTRUSTANCHORCHOICEVAL_END,
+ /** Make sure it's (at least) 32-bit wide. */
+ RTCRTAFTRUSTANCHORCHOICEVAL_32BIT_HACK = 0x7fffffff
+} RTCRTAFTRUSTANCHORCHOICEVAL;
+
+
+/**
+ * RFC-5914 TrustAnchorChoice (IPRT representation).
+ */
+typedef struct RTCRTAFTRUSTANCHORCHOICE
+{
+ /** Dummy object for simplifying everything. */
+ RTASN1DUMMY Dummy;
+ /** Allocation for the valid member (to optimize space usage). */
+ RTASN1ALLOCATION Allocation;
+ /** Indicates which of the pointers are valid. */
+ RTCRTAFTRUSTANCHORCHOICEVAL enmChoice;
+ /** Choice union. */
+ union
+ {
+ /** Generic ASN.1 core pointer for the choice. */
+ PRTASN1CORE pAsn1Core;
+ /** Choice 0: X509 certificate. */
+ PRTCRX509CERTIFICATE pCertificate;
+ /** Choice 1: To-be-signed certificate part. This may differ from the
+ * TBSCertificate member of the original certificate. */
+ struct
+ {
+ /** Explicit context tag. */
+ RTASN1CONTEXTTAG1 CtxTag1;
+ /** Pointer to the TBS certificate structure. */
+ RTCRX509TBSCERTIFICATE TbsCert;
+ } *pT1;
+
+ /** Choice 2: To-be-signed certificate part. This may differ from the
+ * TBSCertificate member of the original certificate. */
+ struct
+ {
+ /** Explicit context tag. */
+ RTASN1CONTEXTTAG2 CtxTag2;
+ /** Pointer to the trust anchor infomration structure. */
+ RTCRTAFTRUSTANCHORINFO TaInfo;
+ } *pT2;
+ } u;
+} RTCRTAFTRUSTANCHORCHOICE;
+/** Pointer to the IPRT representation of a RFC-5914 TrustAnchorChoice. */
+typedef RTCRTAFTRUSTANCHORCHOICE *PRTCRTAFTRUSTANCHORCHOICE;
+/** Pointer to the const IPRT representation of a RFC-5914 TrustAnchorChoice. */
+typedef RTCRTAFTRUSTANCHORCHOICE const *PCRTCRTAFTRUSTANCHORCHOICE;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRTAFTRUSTANCHORCHOICE, RTDECL, RTCrTafTrustAnchorChoice, Dummy.Asn1Core);
+
+/*
+ * RFC-5914 TrustAnchorList (IPRT representation).
+ */
+RTASN1_IMPL_GEN_SEQ_OF_TYPEDEFS_AND_PROTOS(RTCRTAFTRUSTANCHORLIST, RTCRTAFTRUSTANCHORCHOICE, RTDECL, RTCrTafTrustAnchorList);
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_crypto_taf_h */
+
diff --git a/include/iprt/crypto/tsp.h b/include/iprt/crypto/tsp.h
new file mode 100644
index 00000000..8b421044
--- /dev/null
+++ b/include/iprt/crypto/tsp.h
@@ -0,0 +1,148 @@
+/** @file
+ * IPRT - Crypto - Time-Stamp Protocol (RFC-3161).
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_crypto_tsp_h
+#define IPRT_INCLUDED_crypto_tsp_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/asn1.h>
+#include <iprt/crypto/x509.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_cr_tap RTCrTap - Time-Stamp Protocol (RFC-3161)
+ * @ingroup grp_rt_crypto
+ * @{
+ */
+
+
+/**
+ * RFC-3161 MessageImprint (IPRT representation).
+ */
+typedef struct RTCRTSPMESSAGEIMPRINT
+{
+ /** Sequence core. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** The digest algorithm used to produce HashedMessage. */
+ RTCRX509ALGORITHMIDENTIFIER HashAlgorithm;
+ /** The digest of the message being timestamped. */
+ RTASN1OCTETSTRING HashedMessage;
+} RTCRTSPMESSAGEIMPRINT;
+/** Pointer to the IPRT representation of a RFC-3161 MessageImprint. */
+typedef RTCRTSPMESSAGEIMPRINT *PRTCRTSPMESSAGEIMPRINT;
+/** Pointer to the const IPRT representation of a RFC-3161 MessageImprint. */
+typedef RTCRTSPMESSAGEIMPRINT const *PCRTCRTSPMESSAGEIMPRINT;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRTSPMESSAGEIMPRINT, RTDECL, RTCrTspMessageImprint, SeqCore.Asn1Core);
+
+
+/**
+ * RFC-3161 Accuracy (IPRT representation).
+ */
+typedef struct RTCRTSPACCURACY
+{
+ /** Sequence core. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** The seconds accuracy.
+ * This will be larger than 0. If 1 inspect the Millis field. */
+ RTASN1INTEGER Seconds;
+ /** The millisecond accuracy, optional, implicit tag 0.
+ * Range 1..999. If 1 inspect the Micros field. */
+ RTASN1INTEGER Millis;
+ /** The microsecond accuracy, optional, implicit tag 1.
+ * Range 1..999. */
+ RTASN1INTEGER Micros;
+} RTCRTSPACCURACY;
+/** Pointer to the IPRT representation of a RFC-3161 Accuracy. */
+typedef RTCRTSPACCURACY *PRTCRTSPACCURACY;
+/** Pointer to the const IPRT representation of a RFC-3161 Accuracy. */
+typedef RTCRTSPACCURACY const *PCRTCRTSPACCURACY;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRTSPACCURACY, RTDECL, RTCrTspAccuracy, SeqCore.Asn1Core);
+
+
+/**
+ * RFC-3161 TSTInfo (IPRT representation).
+ */
+typedef struct RTCRTSPTSTINFO
+{
+ /** Sequence core. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** The structure version number, current only 1 is valid. */
+ RTASN1INTEGER Version;
+ /** Time authority policy. */
+ RTASN1OBJID Policy;
+ /** The message imprint. */
+ RTCRTSPMESSAGEIMPRINT MessageImprint;
+ /** Timestamp request serial number. */
+ RTASN1INTEGER SerialNumber;
+ /** The timestamp. */
+ RTASN1TIME GenTime;
+ /** The timestamp accuracy, optional. */
+ RTCRTSPACCURACY Accuracy;
+ /** Ordering, whatever that means, defaults to FALSE. */
+ RTASN1BOOLEAN Ordering;
+ /** Nonce, optional. */
+ RTASN1INTEGER Nonce;
+ /** Timestamp authority name, explicit optional.
+ * (Should match a name in the certificate of the signature.) */
+ struct
+ {
+ /** Context tag 0. */
+ RTASN1CONTEXTTAG0 CtxTag0;
+ /** The TSA name. */
+ RTCRX509GENERALNAME Tsa;
+ } T0;
+ /** Extensions, optional, implicit tag 1. */
+ RTCRX509EXTENSION Extensions;
+} RTCRTSPTSTINFO;
+/** Pointer to the IPRT representation of a RFC-3161 TSTInfo. */
+typedef RTCRTSPTSTINFO *PRTCRTSPTSTINFO;
+/** Pointer to the const IPRT representation of a RFC-3161 TSTInfo. */
+typedef RTCRTSPTSTINFO const *PCRTCRTSPTSTINFO;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRTSPTSTINFO, RTDECL, RTCrTspTstInfo, SeqCore.Asn1Core);
+
+/** The object identifier for RTCRTSPTSTINFO.
+ * Found in the ContentType field of PKCS \#7's ContentInfo structure and
+ * the equivalent CMS field. */
+#define RTCRTSPTSTINFO_OID "1.2.840.113549.1.9.16.1.4"
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_crypto_tsp_h */
+
diff --git a/include/iprt/crypto/x509.h b/include/iprt/crypto/x509.h
new file mode 100644
index 00000000..41f5bcc0
--- /dev/null
+++ b/include/iprt/crypto/x509.h
@@ -0,0 +1,1180 @@
+/** @file
+ * IPRT - Crypto - X.509, Public Key and Privilege Management Infrastructure.
+ */
+
+/*
+ * Copyright (C) 2014-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_crypto_x509_h
+#define IPRT_INCLUDED_crypto_x509_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/asn1.h>
+#include <iprt/crypto/pem.h>
+
+
+RT_C_DECLS_BEGIN
+
+struct RTCRPKCS7SETOFCERTS;
+
+
+/** @defgroup grp_rt_crypto Crypto
+ * @ingroup grp_rt
+ * @{
+ */
+
+/** @defgroup grp_rt_crx509 RTCrX509 - Public Key and Privilege Management Infrastructure.
+ * @{
+ */
+
+/**
+ * X.509 algorithm identifier (IPRT representation).
+ */
+typedef struct RTCRX509ALGORITHMIDENTIFIER
+{
+ /** The sequence making up this algorithm identifier. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** The algorithm object ID. */
+ RTASN1OBJID Algorithm;
+ /** Optional parameters specified by the algorithm. */
+ RTASN1DYNTYPE Parameters;
+} RTCRX509ALGORITHMIDENTIFIER;
+/** Poitner to the IPRT representation of a X.509 algorithm identifier. */
+typedef RTCRX509ALGORITHMIDENTIFIER *PRTCRX509ALGORITHMIDENTIFIER;
+/** Poitner to the const IPRT representation of a X.509 algorithm identifier. */
+typedef RTCRX509ALGORITHMIDENTIFIER const *PCRTCRX509ALGORITHMIDENTIFIER;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRX509ALGORITHMIDENTIFIER, RTDECL, RTCrX509AlgorithmIdentifier, SeqCore.Asn1Core);
+RTASN1_IMPL_GEN_SET_OF_TYPEDEFS_AND_PROTOS(RTCRX509ALGORITHMIDENTIFIERS, RTCRX509ALGORITHMIDENTIFIER, RTDECL, RTCrX509AlgorithmIdentifiers);
+
+/**
+ * Tries to convert an X.509 digest algorithm ID into a RTDIGESTTYPE value.
+ *
+ * @returns Valid RTDIGESTTYPE on success, RTDIGESTTYPE_INVALID on failure.
+ * @param pThis The IPRT representation of a X.509 algorithm
+ * identifier object.
+ */
+RTDECL(RTDIGESTTYPE) RTCrX509AlgorithmIdentifier_QueryDigestType(PCRTCRX509ALGORITHMIDENTIFIER pThis);
+
+/**
+ * Tries to figure the digest size of an X.509 digest algorithm ID.
+ *
+ * @returns The digest size in bytes, UINT32_MAX if unknown digest.
+ * @param pThis The IPRT representation of a X.509 algorithm
+ * identifier object.
+ */
+RTDECL(uint32_t) RTCrX509AlgorithmIdentifier_QueryDigestSize(PCRTCRX509ALGORITHMIDENTIFIER pThis);
+
+RTDECL(int) RTCrX509AlgorithmIdentifier_CompareWithString(PCRTCRX509ALGORITHMIDENTIFIER pThis, const char *pszObjId);
+
+/**
+ * Compares a digest with an encrypted digest algorithm, checking if they
+ * specify the same digest.
+ *
+ * @returns 0 if same digest, -1 if the digest is unknown, 1 if the encrypted
+ * digest does not match.
+ * @param pDigest The digest algorithm.
+ * @param pEncryptedDigest The encrypted digest algorithm.
+ */
+RTDECL(int) RTCrX509AlgorithmIdentifier_CompareDigestAndEncryptedDigest(PCRTCRX509ALGORITHMIDENTIFIER pDigest,
+ PCRTCRX509ALGORITHMIDENTIFIER pEncryptedDigest);
+/**
+ * Compares a digest OID with an encrypted digest algorithm OID, checking if
+ * they specify the same digest.
+ *
+ * @returns 0 if same digest, -1 if the digest is unknown, 1 if the encrypted
+ * digest does not match.
+ * @param pszDigestOid The digest algorithm OID.
+ * @param pszEncryptedDigestOid The encrypted digest algorithm OID.
+ */
+RTDECL(int) RTCrX509AlgorithmIdentifier_CompareDigestOidAndEncryptedDigestOid(const char *pszDigestOid,
+ const char *pszEncryptedDigestOid);
+
+
+/**
+ * Combine the encryption algorithm with the digest algorithm.
+ *
+ * @returns OID of encrypted digest algorithm.
+ * @param pEncryption The encryption algorithm. Will work if this is
+ * the OID of an encrypted digest algorithm too, as
+ * long as it matches @a pDigest.
+ * @param pDigest The digest algorithm. Will work if this is the
+ * OID of an encrypted digest algorithm too, as
+ * long as it matches @a pEncryption.
+ */
+RTDECL(const char *) RTCrX509AlgorithmIdentifier_CombineEncryptionAndDigest(PCRTCRX509ALGORITHMIDENTIFIER pEncryption,
+ PCRTCRX509ALGORITHMIDENTIFIER pDigest);
+
+/**
+ * Combine the encryption algorithm OID with the digest algorithm OID.
+ *
+ * @returns OID of encrypted digest algorithm.
+ * @param pszEncryptionOid The encryption algorithm. Will work if this is
+ * the OID of an encrypted digest algorithm too, as
+ * long as it matches @a pszDigestOid.
+ * @param pszDigestOid The digest algorithm. Will work if this is the
+ * OID of an encrypted digest algorithm too, as
+ * long as it matches @a pszEncryptionOid.
+ */
+RTDECL(const char *) RTCrX509AlgorithmIdentifier_CombineEncryptionOidAndDigestOid(const char *pszEncryptionOid,
+ const char *pszDigestOid);
+
+
+/** @name Typical Digest Algorithm OIDs.
+ * @{ */
+#define RTCRX509ALGORITHMIDENTIFIERID_MD2 "1.2.840.113549.2.2"
+#define RTCRX509ALGORITHMIDENTIFIERID_MD4 "1.2.840.113549.2.4"
+#define RTCRX509ALGORITHMIDENTIFIERID_MD5 "1.2.840.113549.2.5"
+#define RTCRX509ALGORITHMIDENTIFIERID_SHA1 "1.3.14.3.2.26"
+#define RTCRX509ALGORITHMIDENTIFIERID_SHA256 "2.16.840.1.101.3.4.2.1"
+#define RTCRX509ALGORITHMIDENTIFIERID_SHA384 "2.16.840.1.101.3.4.2.2"
+#define RTCRX509ALGORITHMIDENTIFIERID_SHA512 "2.16.840.1.101.3.4.2.3"
+#define RTCRX509ALGORITHMIDENTIFIERID_SHA224 "2.16.840.1.101.3.4.2.4"
+#define RTCRX509ALGORITHMIDENTIFIERID_SHA512T224 "2.16.840.1.101.3.4.2.5"
+#define RTCRX509ALGORITHMIDENTIFIERID_SHA512T256 "2.16.840.1.101.3.4.2.6"
+#define RTCRX509ALGORITHMIDENTIFIERID_SHA3_224 "2.16.840.1.101.3.4.2.7"
+#define RTCRX509ALGORITHMIDENTIFIERID_SHA3_256 "2.16.840.1.101.3.4.2.8"
+#define RTCRX509ALGORITHMIDENTIFIERID_SHA3_384 "2.16.840.1.101.3.4.2.9"
+#define RTCRX509ALGORITHMIDENTIFIERID_SHA3_512 "2.16.840.1.101.3.4.2.10"
+#define RTCRX509ALGORITHMIDENTIFIERID_WHIRLPOOL "1.0.10118.3.0.55"
+/** @} */
+
+/** @name Encrypted Digest Algorithm OIDs.
+ * @remarks The PKCS variants are the default ones, alternative OID are marked
+ * as such.
+ * @{ */
+#define RTCRX509ALGORITHMIDENTIFIERID_RSA "1.2.840.113549.1.1.1"
+#define RTCRX509ALGORITHMIDENTIFIERID_MD2_WITH_RSA "1.2.840.113549.1.1.2"
+#define RTCRX509ALGORITHMIDENTIFIERID_MD4_WITH_RSA "1.2.840.113549.1.1.3"
+#define RTCRX509ALGORITHMIDENTIFIERID_MD5_WITH_RSA "1.2.840.113549.1.1.4"
+#define RTCRX509ALGORITHMIDENTIFIERID_SHA1_WITH_RSA "1.2.840.113549.1.1.5"
+#define RTCRX509ALGORITHMIDENTIFIERID_SHA256_WITH_RSA "1.2.840.113549.1.1.11"
+#define RTCRX509ALGORITHMIDENTIFIERID_SHA384_WITH_RSA "1.2.840.113549.1.1.12"
+#define RTCRX509ALGORITHMIDENTIFIERID_SHA512_WITH_RSA "1.2.840.113549.1.1.13"
+#define RTCRX509ALGORITHMIDENTIFIERID_SHA224_WITH_RSA "1.2.840.113549.1.1.14"
+#define RTCRX509ALGORITHMIDENTIFIERID_SHA512T224_WITH_RSA "1.2.840.113549.1.1.15"
+#define RTCRX509ALGORITHMIDENTIFIERID_SHA512T256_WITH_RSA "1.2.840.113549.1.1.16"
+#define RTCRX509ALGORITHMIDENTIFIERID_SHA3_224_WITH_RSA "2.16.840.1.101.3.4.3.13"
+#define RTCRX509ALGORITHMIDENTIFIERID_SHA3_256_WITH_RSA "2.16.840.1.101.3.4.3.14"
+#define RTCRX509ALGORITHMIDENTIFIERID_SHA3_384_WITH_RSA "2.16.840.1.101.3.4.3.15"
+#define RTCRX509ALGORITHMIDENTIFIERID_SHA3_512_WITH_RSA "2.16.840.1.101.3.4.3.16"
+/** @} */
+
+
+
+
+/**
+ * One X.509 AttributeTypeAndValue (IPRT representation).
+ */
+typedef struct RTCRX509ATTRIBUTETYPEANDVALUE
+{
+ /** Sequence core. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** The attribute type (object ID). */
+ RTASN1OBJID Type;
+ /** The attribute value (what it is is defined by Type). */
+ RTASN1DYNTYPE Value;
+} RTCRX509ATTRIBUTETYPEANDVALUE;
+/** Pointer to a X.509 AttributeTypeAndValue (IPRT representation). */
+typedef RTCRX509ATTRIBUTETYPEANDVALUE *PRTCRX509ATTRIBUTETYPEANDVALUE;
+/** Pointer to a const X.509 AttributeTypeAndValue (IPRT representation). */
+typedef RTCRX509ATTRIBUTETYPEANDVALUE const *PCRTCRX509ATTRIBUTETYPEANDVALUE;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRX509ATTRIBUTETYPEANDVALUE, RTDECL, RTCrX509AttributeTypeAndValue, SeqCore.Asn1Core);
+RTASN1_IMPL_GEN_SET_OF_TYPEDEFS_AND_PROTOS(RTCRX509ATTRIBUTETYPEANDVALUES, RTCRX509ATTRIBUTETYPEANDVALUE, RTDECL, RTCrX509AttributeTypeAndValues);
+
+RTASN1TYPE_ALIAS(RTCRX509RELATIVEDISTINGUISHEDNAME, RTCRX509ATTRIBUTETYPEANDVALUES, RTCrX509RelativeDistinguishedName, RTCrX509AttributeTypeAndValues);
+
+
+RTASN1_IMPL_GEN_SEQ_OF_TYPEDEFS_AND_PROTOS(RTCRX509NAME, RTCRX509RELATIVEDISTINGUISHEDNAME, RTDECL, RTCrX509Name);
+RTDECL(int) RTCrX509Name_CheckSanity(PCRTCRX509NAME pName, uint32_t fFlags, PRTERRINFO pErrInfo, const char *pszErrorTag);
+RTDECL(bool) RTCrX509Name_MatchByRfc5280(PCRTCRX509NAME pLeft, PCRTCRX509NAME pRight);
+
+/**
+ * Name constraint matching (RFC-5280).
+ *
+ * @returns true on match, false on mismatch.
+ * @param pConstraint The constraint name.
+ * @param pName The name to match against the constraint.
+ * @sa RTCrX509GeneralName_ConstraintMatch,
+ * RTCrX509RelativeDistinguishedName_ConstraintMatch
+ */
+RTDECL(bool) RTCrX509Name_ConstraintMatch(PCRTCRX509NAME pConstraint, PCRTCRX509NAME pName);
+RTDECL(int) RTCrX509Name_RecodeAsUtf8(PRTCRX509NAME pThis, PCRTASN1ALLOCATORVTABLE pAllocator);
+
+/**
+ * Matches the directory name against a comma separated list of the component
+ * strings (case sensitive).
+ *
+ * @returns true if match, false if mismatch.
+ * @param pThis The name object.
+ * @param pszString The string to match against. For example:
+ * "C=US, ST=California, L=Redwood Shores, O=Oracle Corporation"
+ *
+ * @remarks This is doing a straight compare, no extra effort is expended in
+ * dealing with different component order. If the component order
+ * differs, there won't be any match.
+ */
+RTDECL(bool) RTCrX509Name_MatchWithString(PCRTCRX509NAME pThis, const char *pszString);
+
+/**
+ * Formats the name as a command separated list of components with type
+ * prefixes.
+ *
+ * The output of this function is suitable for use with
+ * RTCrX509Name_MatchWithString.
+ *
+ * @returns IPRT status code.
+ * @param pThis The name object.
+ * @param pszBuf The output buffer.
+ * @param cbBuf The size of the output buffer.
+ * @param pcbActual Where to return the number of bytes required for the
+ * output, including the null terminator character.
+ * Optional.
+ */
+RTDECL(int) RTCrX509Name_FormatAsString(PCRTCRX509NAME pThis, char *pszBuf, size_t cbBuf, size_t *pcbActual);
+
+
+/**
+ * Looks up the RDN ID and returns the short name for it, if found.
+ *
+ * @returns Short name (e.g. 'CN') or NULL.
+ * @param pRdnId The RDN ID to look up.
+ */
+RTDECL(const char *) RTCrX509Name_GetShortRdn(PCRTASN1OBJID pRdnId);
+
+/**
+ * One X.509 OtherName (IPRT representation).
+ */
+typedef struct RTCRX509OTHERNAME
+{
+ /** The sequence core. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** The name type identifier. */
+ RTASN1OBJID TypeId;
+ /** The name value (explicit tag 0). */
+ RTASN1DYNTYPE Value;
+} RTCRX509OTHERNAME;
+/** Pointer to a X.509 OtherName (IPRT representation). */
+typedef RTCRX509OTHERNAME *PRTCRX509OTHERNAME;
+/** Pointer to a const X.509 OtherName (IPRT representation). */
+typedef RTCRX509OTHERNAME const *PCRTCRX509OTHERNAME;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRX509OTHERNAME, RTDECL, RTCrX509OtherName, SeqCore.Asn1Core);
+
+
+typedef enum RTCRX509GENERALNAMECHOICE
+{
+ RTCRX509GENERALNAMECHOICE_INVALID = 0,
+ RTCRX509GENERALNAMECHOICE_OTHER_NAME,
+ RTCRX509GENERALNAMECHOICE_RFC822_NAME,
+ RTCRX509GENERALNAMECHOICE_DNS_NAME,
+ RTCRX509GENERALNAMECHOICE_X400_ADDRESS,
+ RTCRX509GENERALNAMECHOICE_DIRECTORY_NAME,
+ RTCRX509GENERALNAMECHOICE_EDI_PARTY_NAME,
+ RTCRX509GENERALNAMECHOICE_URI,
+ RTCRX509GENERALNAMECHOICE_IP_ADDRESS,
+ RTCRX509GENERALNAMECHOICE_REGISTERED_ID,
+ RTCRX509GENERALNAMECHOICE_END,
+ RTCRX509GENERALNAMECHOICE_32BIT_HACK = 0x7fffffff
+} RTCRX509GENERALNAMECHOICE;
+
+/**
+ * One X.509 GeneralName (IPRT representation).
+ *
+ * This is represented as a union. Use the RTCRX509GENERALNAME_IS_XXX predicate
+ * macros to figure out which member is valid (Asn1Core is always valid).
+ */
+typedef struct RTCRX509GENERALNAME
+{
+ /** Dummy ASN.1 record, not encoded. */
+ RTASN1DUMMY Dummy;
+ /** The value allocation. */
+ RTASN1ALLOCATION Allocation;
+ /** The choice of value. */
+ RTCRX509GENERALNAMECHOICE enmChoice;
+ /** The value union. */
+ union
+ {
+ /** Tag 0: Other Name. */
+ PRTCRX509OTHERNAME pT0_OtherName;
+ /** Tag 1: RFC-822 Name. */
+ PRTASN1STRING pT1_Rfc822;
+ /** Tag 2: DNS name. */
+ PRTASN1STRING pT2_DnsName;
+ /** Tag 3: X.400 Address. */
+ struct
+ {
+ /** Context tag 3. */
+ RTASN1CONTEXTTAG3 CtxTag3;
+ /** Later. */
+ RTASN1DYNTYPE X400Address;
+ } *pT3;
+ /** Tag 4: Directory Name. */
+ struct
+ {
+ /** Context tag 4. */
+ RTASN1CONTEXTTAG4 CtxTag4;
+ /** Directory name. */
+ RTCRX509NAME DirectoryName;
+ } *pT4;
+ /** Tag 5: EDI Party Name. */
+ struct
+ {
+ /** Context tag 5. */
+ RTASN1CONTEXTTAG5 CtxTag5;
+ /** Later. */
+ RTASN1DYNTYPE EdiPartyName;
+ } *pT5;
+ /** Tag 6: URI. */
+ PRTASN1STRING pT6_Uri;
+ /** Tag 7: IP address. Either 4/8 (IPv4) or 16/32 (IPv16) octets long. */
+ PRTASN1OCTETSTRING pT7_IpAddress;
+ /** Tag 8: Registered ID. */
+ PRTASN1OBJID pT8_RegisteredId;
+ } u;
+} RTCRX509GENERALNAME;
+/** Pointer to the IPRT representation of an X.509 general name. */
+typedef RTCRX509GENERALNAME *PRTCRX509GENERALNAME;
+/** Pointer to the const IPRT representation of an X.509 general name. */
+typedef RTCRX509GENERALNAME const *PCRTCRX509GENERALNAME;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRX509GENERALNAME, RTDECL, RTCrX509GeneralName, Dummy.Asn1Core);
+
+/** @name RTCRX509GENERALNAME tag predicates.
+ * @{ */
+#define RTCRX509GENERALNAME_IS_OTHER_NAME(a_GenName) ((a_GenName)->enmChoice == RTCRX509GENERALNAMECHOICE_OTHER_NAME)
+#define RTCRX509GENERALNAME_IS_RFC822_NAME(a_GenName) ((a_GenName)->enmChoice == RTCRX509GENERALNAMECHOICE_RFC822_NAME)
+#define RTCRX509GENERALNAME_IS_DNS_NAME(a_GenName) ((a_GenName)->enmChoice == RTCRX509GENERALNAMECHOICE_DNS_NAME)
+#define RTCRX509GENERALNAME_IS_X400_ADDRESS(a_GenName) ((a_GenName)->enmChoice == RTCRX509GENERALNAMECHOICE_X400_ADDRESS)
+#define RTCRX509GENERALNAME_IS_DIRECTORY_NAME(a_GenName) ((a_GenName)->enmChoice == RTCRX509GENERALNAMECHOICE_DIRECTORY_NAME)
+#define RTCRX509GENERALNAME_IS_EDI_PARTY_NAME(a_GenName) ((a_GenName)->enmChoice == RTCRX509GENERALNAMECHOICE_EDI_PARTY_NAME)
+#define RTCRX509GENERALNAME_IS_URI(a_GenName) ((a_GenName)->enmChoice == RTCRX509GENERALNAMECHOICE_URI)
+#define RTCRX509GENERALNAME_IS_IP_ADDRESS(a_GenName) ((a_GenName)->enmChoice == RTCRX509GENERALNAMECHOICE_IP_ADDRESS)
+#define RTCRX509GENERALNAME_IS_REGISTERED_ID(a_GenName) ((a_GenName)->enmChoice == RTCRX509GENERALNAMECHOICE_REGISTERED_ID)
+/** @} */
+
+
+RTASN1_IMPL_GEN_SEQ_OF_TYPEDEFS_AND_PROTOS(RTCRX509GENERALNAMES, RTCRX509GENERALNAME, RTDECL, RTCrX509GeneralNames);
+RTDECL(bool) RTCrX509GeneralName_ConstraintMatch(PCRTCRX509GENERALNAME pConstraint, PCRTCRX509GENERALNAME pName);
+
+
+/**
+ * X.509 Validity (IPRT representation).
+ */
+typedef struct RTCRX509VALIDITY
+{
+ /** Core sequence bits. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** Effective starting. */
+ RTASN1TIME NotBefore;
+ /** Expires after. */
+ RTASN1TIME NotAfter;
+} RTCRX509VALIDITY;
+/** Pointer to the IPRT representation of an X.509 validity sequence. */
+typedef RTCRX509VALIDITY *PRTCRX509VALIDITY;
+/** Pointer ot the const IPRT representation of an X.509 validity sequence. */
+typedef RTCRX509VALIDITY const *PCRTCRX509VALIDITY;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRX509VALIDITY, RTDECL, RTCrX509Validity, SeqCore.Asn1Core);
+
+RTDECL(bool) RTCrX509Validity_IsValidAtTimeSpec(PCRTCRX509VALIDITY pThis, PCRTTIMESPEC pTimeSpec);
+
+
+#if 0
+/**
+ * X.509 UniqueIdentifier (IPRT representation).
+ */
+typedef struct RTCRX509UNIQUEIDENTIFIER
+{
+ /** Representation is a bit string. */
+ RTASN1BITSTRING BitString;
+} RTCRX509UNIQUEIDENTIFIER;
+/** Pointer to the IPRT representation of an X.509 unique identifier. */
+typedef RTCRX509UNIQUEIDENTIFIER *PRTCRX509UNIQUEIDENTIFIER;
+/** Pointer to the const IPRT representation of an X.509 unique identifier. */
+typedef RTCRX509UNIQUEIDENTIFIER const *PCRTCRX509UNIQUEIDENTIFIER;
+RTASN1TYPE_STANDARD_PROTOTYPES_NO_GET_CORE(RTCRX509UNIQUEIDENTIFIER, RTDECL, RTCrX509UniqueIdentifier);
+#endif
+RTASN1TYPE_ALIAS(RTCRX509UNIQUEIDENTIFIER, RTASN1BITSTRING, RTCrX509UniqueIdentifier, RTAsn1BitString);
+
+
+/**
+ * X.509 SubjectPublicKeyInfo (IPRT representation).
+ */
+typedef struct RTCRX509SUBJECTPUBLICKEYINFO
+{
+ /** Core sequence bits. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** The algorithm used with the public key. */
+ RTCRX509ALGORITHMIDENTIFIER Algorithm;
+ /** A bit string containing the public key.
+ *
+ * For algorithms like rsaEncryption this is generally a sequence of two
+ * integers, where the first one has lots of bits, and the second one being a
+ * modulous value. These are details specific to the algorithm and not relevant
+ * when validating the certificate chain. */
+ RTASN1BITSTRING SubjectPublicKey;
+} RTCRX509SUBJECTPUBLICKEYINFO;
+/** Pointer to the IPRT representation of an X.509 subject public key info
+ * sequence. */
+typedef RTCRX509SUBJECTPUBLICKEYINFO *PRTCRX509SUBJECTPUBLICKEYINFO;
+/** Pointer to the const IPRT representation of an X.509 subject public key info
+ * sequence. */
+typedef RTCRX509SUBJECTPUBLICKEYINFO const *PCRTCRX509SUBJECTPUBLICKEYINFO;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRX509SUBJECTPUBLICKEYINFO, RTDECL, RTCrX509SubjectPublicKeyInfo, SeqCore.Asn1Core);
+
+
+/**
+ * One X.509 AuthorityKeyIdentifier (IPRT representation).
+ */
+typedef struct RTCRX509AUTHORITYKEYIDENTIFIER
+{
+ /** Sequence core. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** Tag 0, optional, implicit: Key identifier. */
+ RTASN1OCTETSTRING KeyIdentifier;
+ /** Tag 1, optional, implicit: Issuer name. */
+ RTCRX509GENERALNAMES AuthorityCertIssuer;
+ /** Tag 2, optional, implicit: Serial number of issuer. */
+ RTASN1INTEGER AuthorityCertSerialNumber;
+} RTCRX509AUTHORITYKEYIDENTIFIER;
+/** Pointer to the IPRT representation of an X.509 AuthorityKeyIdentifier
+ * sequence. */
+typedef RTCRX509AUTHORITYKEYIDENTIFIER *PRTCRX509AUTHORITYKEYIDENTIFIER;
+/** Pointer to the const IPRT representation of an X.509 AuthorityKeyIdentifier
+ * sequence. */
+typedef RTCRX509AUTHORITYKEYIDENTIFIER const *PCRTCRX509AUTHORITYKEYIDENTIFIER;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRX509AUTHORITYKEYIDENTIFIER, RTDECL, RTCrX509AuthorityKeyIdentifier, SeqCore.Asn1Core);
+
+
+/**
+ * One X.509 OldAuthorityKeyIdentifier (IPRT representation).
+ */
+typedef struct RTCRX509OLDAUTHORITYKEYIDENTIFIER
+{
+ /** Sequence core. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** Tag 0, optional, implicit: Key identifier. */
+ RTASN1OCTETSTRING KeyIdentifier;
+ struct
+ {
+ RTASN1CONTEXTTAG1 CtxTag1;
+ /** Tag 1, optional, implicit: Issuer name. */
+ RTCRX509NAME AuthorityCertIssuer;
+ } T1;
+ /** Tag 2, optional, implicit: Serial number of issuer. */
+ RTASN1INTEGER AuthorityCertSerialNumber;
+} RTCRX509OLDAUTHORITYKEYIDENTIFIER;
+/** Pointer to the IPRT representation of an X.509 AuthorityKeyIdentifier
+ * sequence. */
+typedef RTCRX509OLDAUTHORITYKEYIDENTIFIER *PRTCRX509OLDAUTHORITYKEYIDENTIFIER;
+/** Pointer to the const IPRT representation of an X.509 AuthorityKeyIdentifier
+ * sequence. */
+typedef RTCRX509OLDAUTHORITYKEYIDENTIFIER const *PCRTCRX509OLDAUTHORITYKEYIDENTIFIER;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRX509OLDAUTHORITYKEYIDENTIFIER, RTDECL, RTCrX509OldAuthorityKeyIdentifier, SeqCore.Asn1Core);
+
+
+/**
+ * One X.509 PolicyQualifierInfo (IPRT representation).
+ */
+typedef struct RTCRX509POLICYQUALIFIERINFO
+{
+ /** Core sequence bits. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** The policy object ID. */
+ RTASN1OBJID PolicyQualifierId;
+ /** Anything defined by the policy qualifier id. */
+ RTASN1DYNTYPE Qualifier;
+} RTCRX509POLICYQUALIFIERINFO;
+/** Pointer to the IPRT representation of an X.509 PolicyQualifierInfo
+ * sequence. */
+typedef RTCRX509POLICYQUALIFIERINFO *PRTCRX509POLICYQUALIFIERINFO;
+/** Pointer to the const IPRT representation of an X.509 PolicyQualifierInfo
+ * sequence. */
+typedef RTCRX509POLICYQUALIFIERINFO const *PCRTCRX509POLICYQUALIFIERINFO;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRX509POLICYQUALIFIERINFO, RTDECL, RTCrX509PolicyQualifierInfo, SeqCore.Asn1Core);
+RTASN1_IMPL_GEN_SEQ_OF_TYPEDEFS_AND_PROTOS(RTCRX509POLICYQUALIFIERINFOS, RTCRX509POLICYQUALIFIERINFO, RTDECL, RTCrX509PolicyQualifierInfos);
+
+
+/**
+ * One X.509 PolicyInformation (IPRT representation).
+ */
+typedef struct RTCRX509POLICYINFORMATION
+{
+ /** Core sequence bits. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** The policy object ID. */
+ RTASN1OBJID PolicyIdentifier;
+ /** Optional sequence of policy qualifiers. */
+ RTCRX509POLICYQUALIFIERINFOS PolicyQualifiers;
+} RTCRX509POLICYINFORMATION;
+/** Pointer to the IPRT representation of an X.509 PolicyInformation
+ * sequence. */
+typedef RTCRX509POLICYINFORMATION *PRTCRX509POLICYINFORMATION;
+/** Pointer to the const IPRT representation of an X.509 PolicyInformation
+ * sequence. */
+typedef RTCRX509POLICYINFORMATION const *PCRTCRX509POLICYINFORMATION;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRX509POLICYINFORMATION, RTDECL, RTCrX509PolicyInformation, SeqCore.Asn1Core);
+RTASN1_IMPL_GEN_SEQ_OF_TYPEDEFS_AND_PROTOS(RTCRX509CERTIFICATEPOLICIES, RTCRX509POLICYINFORMATION, RTDECL, RTCrX509CertificatePolicies);
+
+/** Sepcial policy object ID that matches any policy. */
+#define RTCRX509_ID_CE_CP_ANY_POLICY_OID "2.5.29.32.0"
+
+
+/**
+ * One X.509 PolicyMapping (IPRT representation).
+ */
+typedef struct RTCRX509POLICYMAPPING
+{
+ /** Core sequence bits. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** Issuer policy ID. */
+ RTASN1OBJID IssuerDomainPolicy;
+ /** Subject policy ID. */
+ RTASN1OBJID SubjectDomainPolicy;
+} RTCRX509POLICYMAPPING;
+/** Pointer to the IPRT representation of a sequence of X.509 PolicyMapping. */
+typedef RTCRX509POLICYMAPPING *PRTCRX509POLICYMAPPING;
+/** Pointer to the const IPRT representation of a sequence of X.509
+ * PolicyMapping. */
+typedef RTCRX509POLICYMAPPING const *PCRTCRX509POLICYMAPPING;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRX509POLICYMAPPING, RTDECL, RTCrX509PolicyMapping, SeqCore.Asn1Core);
+RTASN1_IMPL_GEN_SEQ_OF_TYPEDEFS_AND_PROTOS(RTCRX509POLICYMAPPINGS, RTCRX509POLICYMAPPING, RTDECL, RTCrX509PolicyMappings);
+
+
+/**
+ * X.509 BasicConstraints (IPRT representation).
+ */
+typedef struct RTCRX509BASICCONSTRAINTS
+{
+ /** Core sequence bits. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** Is this ia certficiate authority? Default to false. */
+ RTASN1BOOLEAN CA;
+ /** Path length constraint. */
+ RTASN1INTEGER PathLenConstraint;
+} RTCRX509BASICCONSTRAINTS;
+/** Pointer to the IPRT representation of a sequence of X.509
+ * BasicConstraints. */
+typedef RTCRX509BASICCONSTRAINTS *PRTCRX509BASICCONSTRAINTS;
+/** Pointer to the const IPRT representation of a sequence of X.509
+ * BasicConstraints. */
+typedef RTCRX509BASICCONSTRAINTS const *PCRTCRX509BASICCONSTRAINTS;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRX509BASICCONSTRAINTS, RTDECL, RTCrX509BasicConstraints, SeqCore.Asn1Core);
+
+
+/**
+ * X.509 GeneralSubtree (IPRT representation).
+ */
+typedef struct RTCRX509GENERALSUBTREE
+{
+ /** Core sequence bits. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** Base name. */
+ RTCRX509GENERALNAME Base;
+ /** Tag 0, optional: Minimum, default 0. Fixed at 0 by RFC-5280. */
+ RTASN1INTEGER Minimum;
+ /** Tag 1, optional: Maximum. Fixed as not-present by RFC-5280. */
+ RTASN1INTEGER Maximum;
+} RTCRX509GENERALSUBTREE;
+/** Pointer to the IPRT representation of a sequence of X.509 GeneralSubtree. */
+typedef RTCRX509GENERALSUBTREE *PRTCRX509GENERALSUBTREE;
+/** Pointer to the const IPRT representation of a sequence of X.509
+ * GeneralSubtree. */
+typedef RTCRX509GENERALSUBTREE const *PCRTCRX509GENERALSUBTREE;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRX509GENERALSUBTREE, RTDECL, RTCrX509GeneralSubtree, SeqCore.Asn1Core);
+
+RTDECL(bool) RTCrX509GeneralSubtree_ConstraintMatch(PCRTCRX509GENERALSUBTREE pConstraint, PCRTCRX509GENERALSUBTREE pName);
+
+RTASN1_IMPL_GEN_SEQ_OF_TYPEDEFS_AND_PROTOS(RTCRX509GENERALSUBTREES, RTCRX509GENERALSUBTREE, RTDECL, RTCrX509GeneralSubtrees);
+
+
+/**
+ * X.509 NameConstraints (IPRT representation).
+ */
+typedef struct RTCRX509NAMECONSTRAINTS
+{
+ /** Core sequence bits. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** Tag 0, optional: Permitted subtrees. */
+ struct
+ {
+ /** Context tag. */
+ RTASN1CONTEXTTAG0 CtxTag0;
+ /** The permitted subtrees. */
+ RTCRX509GENERALSUBTREES PermittedSubtrees;
+ } T0;
+ /** Tag 1, optional: Excluded subtrees. */
+ struct
+ {
+ /** Context tag. */
+ RTASN1CONTEXTTAG1 CtxTag1;
+ /** The excluded subtrees. */
+ RTCRX509GENERALSUBTREES ExcludedSubtrees;
+ } T1;
+} RTCRX509NAMECONSTRAINTS;
+/** Pointer to the IPRT representation of a sequence of X.509
+ * NameConstraints. */
+typedef RTCRX509NAMECONSTRAINTS *PRTCRX509NAMECONSTRAINTS;
+/** Pointer to the const IPRT representation of a sequence of X.509
+ * NameConstraints. */
+typedef RTCRX509NAMECONSTRAINTS const *PCRTCRX509NAMECONSTRAINTS;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRX509NAMECONSTRAINTS, RTDECL, RTCrX509NameConstraints, SeqCore.Asn1Core);
+
+
+/**
+ * X.509 PolicyConstraints (IPRT representation).
+ */
+typedef struct RTCRX509POLICYCONSTRAINTS
+{
+ /** Core sequence bits. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** Tag 0, optional: Certificates before an explicit policy is required. */
+ RTASN1INTEGER RequireExplicitPolicy;
+ /** Tag 1, optional: Certificates before policy mapping is inhibited. */
+ RTASN1INTEGER InhibitPolicyMapping;
+} RTCRX509POLICYCONSTRAINTS;
+/** Pointer to the IPRT representation of a sequence of X.509
+ * PolicyConstraints. */
+typedef RTCRX509POLICYCONSTRAINTS *PRTCRX509POLICYCONSTRAINTS;
+/** Pointer to the const IPRT representation of a sequence of X.509
+ * PolicyConstraints. */
+typedef RTCRX509POLICYCONSTRAINTS const *PCRTCRX509POLICYCONSTRAINTS;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRX509POLICYCONSTRAINTS, RTDECL, RTCrX509PolicyConstraints, SeqCore.Asn1Core);
+
+
+/**
+ * Indicates what an X.509 extension value encapsulates.
+ */
+typedef enum RTCRX509EXTENSIONVALUE
+{
+ RTCRX509EXTENSIONVALUE_INVALID = 0,
+ /** Unknown, no decoding available just the octet string. */
+ RTCRX509EXTENSIONVALUE_UNKNOWN,
+ /** Unencapsulated (i.e. octet string). */
+ RTCRX509EXTENSIONVALUE_NOT_ENCAPSULATED,
+
+ /** Bit string (RTASN1BITSTRING). */
+ RTCRX509EXTENSIONVALUE_BIT_STRING,
+ /** Octet string (RTASN1OCTETSTRING). */
+ RTCRX509EXTENSIONVALUE_OCTET_STRING,
+ /** Integer string (RTASN1INTEGER). */
+ RTCRX509EXTENSIONVALUE_INTEGER,
+ /** Sequence of object identifiers (RTASN1SEQOFOBJIDS). */
+ RTCRX509EXTENSIONVALUE_SEQ_OF_OBJ_IDS,
+
+ /** Authority key identifier (RTCRX509AUTHORITYKEYIDENTIFIER). */
+ RTCRX509EXTENSIONVALUE_AUTHORITY_KEY_IDENTIFIER,
+ /** Old Authority key identifier (RTCRX509OLDAUTHORITYKEYIDENTIFIER). */
+ RTCRX509EXTENSIONVALUE_OLD_AUTHORITY_KEY_IDENTIFIER,
+ /** Certificate policies (RTCRX509CERTIFICATEPOLICIES). */
+ RTCRX509EXTENSIONVALUE_CERTIFICATE_POLICIES,
+ /** Sequence of policy mappings (RTCRX509POLICYMAPPINGS). */
+ RTCRX509EXTENSIONVALUE_POLICY_MAPPINGS,
+ /** Basic constraints (RTCRX509BASICCONSTRAINTS). */
+ RTCRX509EXTENSIONVALUE_BASIC_CONSTRAINTS,
+ /** Name constraints (RTCRX509NAMECONSTRAINTS). */
+ RTCRX509EXTENSIONVALUE_NAME_CONSTRAINTS,
+ /** Policy constraints (RTCRX509POLICYCONSTRAINTS). */
+ RTCRX509EXTENSIONVALUE_POLICY_CONSTRAINTS,
+ /** Sequence of general names (RTCRX509GENERALNAMES). */
+ RTCRX509EXTENSIONVALUE_GENERAL_NAMES,
+
+ /** Blow the type up to 32-bits. */
+ RTCRX509EXTENSIONVALUE_32BIT_HACK = 0x7fffffff
+} RTCRX509EXTENSIONVALUE;
+
+/**
+ * One X.509 Extension (IPRT representation).
+ */
+typedef struct RTCRX509EXTENSION
+{
+ /** Core sequence bits. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** Extension ID. */
+ RTASN1OBJID ExtnId;
+ /** Whether this is critical (default @c false). */
+ RTASN1BOOLEAN Critical;
+ /** Indicates what ExtnValue.pEncapsulated points at. */
+ RTCRX509EXTENSIONVALUE enmValue;
+ /** The value.
+ * Contains extension specific data that we don't yet parse. */
+ RTASN1OCTETSTRING ExtnValue;
+} RTCRX509EXTENSION;
+/** Pointer to the IPRT representation of one X.509 extensions. */
+typedef RTCRX509EXTENSION *PRTCRX509EXTENSION;
+/** Pointer to the const IPRT representation of one X.509 extension. */
+typedef RTCRX509EXTENSION const *PCRTCRX509EXTENSION;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRX509EXTENSION, RTDECL, RTCrX509Extension, SeqCore.Asn1Core);
+RTASN1_IMPL_GEN_SEQ_OF_TYPEDEFS_AND_PROTOS(RTCRX509EXTENSIONS, RTCRX509EXTENSION, RTDECL, RTCrX509Extensions);
+
+RTDECL(int) RTCrX509Extension_ExtnValue_DecodeAsn1(PRTASN1CURSOR pCursor, uint32_t fFlags,
+ PRTCRX509EXTENSION pThis, const char *pszErrorTag);
+
+
+/**
+ * X.509 To-be-signed certificate information (IPRT representation).
+ */
+typedef struct RTCRX509TBSCERTIFICATE
+{
+ /** Sequence core. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** Structure version. */
+ struct
+ {
+ /** Context tag with value 0. */
+ RTASN1CONTEXTTAG0 CtxTag0;
+ /** The actual value (RTCRX509TBSCERTIFICATE_V1, ...). */
+ RTASN1INTEGER Version;
+ } T0;
+ /** The serial number of the certificate. */
+ RTASN1INTEGER SerialNumber;
+ /** The signature algorithm. */
+ RTCRX509ALGORITHMIDENTIFIER Signature;
+ /** The issuer name. */
+ RTCRX509NAME Issuer;
+ /** The certificate validity period. */
+ RTCRX509VALIDITY Validity;
+ /** The subject name. */
+ RTCRX509NAME Subject;
+ /** The public key for this certificate. */
+ RTCRX509SUBJECTPUBLICKEYINFO SubjectPublicKeyInfo;
+ /** Issuer unique identifier (optional, version >= v2). */
+ struct
+ {
+ /** Context tag with value 1. */
+ RTASN1CONTEXTTAG1 CtxTag1;
+ /** The unique identifier value. */
+ RTCRX509UNIQUEIDENTIFIER IssuerUniqueId;
+ } T1;
+ /** Subject unique identifier (optional, version >= v2). */
+ struct
+ {
+ /** Context tag with value 2. */
+ RTASN1CONTEXTTAG2 CtxTag2;
+ /** The unique identifier value. */
+ RTCRX509UNIQUEIDENTIFIER SubjectUniqueId;
+ } T2;
+ /** Extensions (optional, version >= v3). */
+ struct
+ {
+ /** Context tag with value 3. */
+ RTASN1CONTEXTTAG3 CtxTag3;
+ /** The unique identifier value. */
+ RTCRX509EXTENSIONS Extensions;
+ /** Extensions summary flags (RTCRX509TBSCERTIFICATE_F_PRESENT_XXX). */
+ uint32_t fFlags;
+ /** Key usage flags (RTCRX509CERT_KEY_USAGE_F_XXX). */
+ uint32_t fKeyUsage;
+ /** Extended key usage flags (RTCRX509CERT_EKU_F_XXX). */
+ uint64_t fExtKeyUsage;
+
+ /** Pointer to the authority key ID extension if present. */
+ PCRTCRX509AUTHORITYKEYIDENTIFIER pAuthorityKeyIdentifier;
+ /** Pointer to the OLD authority key ID extension if present. */
+ PCRTCRX509OLDAUTHORITYKEYIDENTIFIER pOldAuthorityKeyIdentifier;
+ /** Pointer to the subject key ID extension if present. */
+ PCRTASN1OCTETSTRING pSubjectKeyIdentifier;
+ /** Pointer to the alternative subject name extension if present. */
+ PCRTCRX509GENERALNAMES pAltSubjectName;
+ /** Pointer to the alternative issuer name extension if present. */
+ PCRTCRX509GENERALNAMES pAltIssuerName;
+ /** Pointer to the certificate policies extension if present. */
+ PCRTCRX509CERTIFICATEPOLICIES pCertificatePolicies;
+ /** Pointer to the policy mappings extension if present. */
+ PCRTCRX509POLICYMAPPINGS pPolicyMappings;
+ /** Pointer to the basic constraints extension if present. */
+ PCRTCRX509BASICCONSTRAINTS pBasicConstraints;
+ /** Pointer to the name constraints extension if present. */
+ PCRTCRX509NAMECONSTRAINTS pNameConstraints;
+ /** Pointer to the policy constraints extension if present. */
+ PCRTCRX509POLICYCONSTRAINTS pPolicyConstraints;
+ /** Pointer to the inhibit anyPolicy extension if present. */
+ PCRTASN1INTEGER pInhibitAnyPolicy;
+ } T3;
+} RTCRX509TBSCERTIFICATE;
+/** Pointer to the IPRT representation of a X.509 TBSCertificate. */
+typedef RTCRX509TBSCERTIFICATE *PRTCRX509TBSCERTIFICATE;
+/** Pointer to the const IPRT representation of a X.509 TBSCertificate. */
+typedef RTCRX509TBSCERTIFICATE const *PCRTCRX509TBSCERTIFICATE;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRX509TBSCERTIFICATE, RTDECL, RTCrX509TbsCertificate, SeqCore.Asn1Core);
+
+/** @name RTCRX509TBSCERTIFICATE::T0.Version values.
+ * @{ */
+#define RTCRX509TBSCERTIFICATE_V1 0
+#define RTCRX509TBSCERTIFICATE_V2 1
+#define RTCRX509TBSCERTIFICATE_V3 2
+/** @} */
+
+/** @name RTCRX509TBSCERTIFICATE::T3.fFlags values.
+ * @{ */
+#define RTCRX509TBSCERTIFICATE_F_PRESENT_KEY_USAGE RT_BIT_32(0)
+#define RTCRX509TBSCERTIFICATE_F_PRESENT_EXT_KEY_USAGE RT_BIT_32(1)
+#define RTCRX509TBSCERTIFICATE_F_PRESENT_SUBJECT_KEY_IDENTIFIER RT_BIT_32(2)
+#define RTCRX509TBSCERTIFICATE_F_PRESENT_SUBJECT_ALT_NAME RT_BIT_32(3)
+#define RTCRX509TBSCERTIFICATE_F_PRESENT_ISSUER_ALT_NAME RT_BIT_32(4)
+#define RTCRX509TBSCERTIFICATE_F_PRESENT_CERTIFICATE_POLICIES RT_BIT_32(5)
+#define RTCRX509TBSCERTIFICATE_F_PRESENT_POLICY_MAPPINGS RT_BIT_32(6)
+#define RTCRX509TBSCERTIFICATE_F_PRESENT_BASIC_CONSTRAINTS RT_BIT_32(7)
+#define RTCRX509TBSCERTIFICATE_F_PRESENT_NAME_CONSTRAINTS RT_BIT_32(8)
+#define RTCRX509TBSCERTIFICATE_F_PRESENT_POLICY_CONSTRAINTS RT_BIT_32(9)
+#define RTCRX509TBSCERTIFICATE_F_PRESENT_AUTHORITY_KEY_IDENTIFIER RT_BIT_32(10)
+#define RTCRX509TBSCERTIFICATE_F_PRESENT_OLD_AUTHORITY_KEY_IDENTIFIER RT_BIT_32(11)
+#define RTCRX509TBSCERTIFICATE_F_PRESENT_ACCEPTABLE_CERT_POLICIES RT_BIT_32(12)
+#define RTCRX509TBSCERTIFICATE_F_PRESENT_INHIBIT_ANY_POLICY RT_BIT_32(13)
+#define RTCRX509TBSCERTIFICATE_F_PRESENT_OTHER RT_BIT_32(22) /**< Other unknown extension present. */
+#define RTCRX509TBSCERTIFICATE_F_PRESENT_NONE RT_BIT_32(23) /**< No extensions present. */
+/** @} */
+
+/** @name X.509 Key Usage flags. (RFC-5280 section 4.2.1.3.)
+ * @{ */
+#define RTCRX509CERT_KEY_USAGE_F_DIGITAL_SIGNATURE_BIT 0
+#define RTCRX509CERT_KEY_USAGE_F_DIGITAL_SIGNATURE RT_BIT_32(0)
+#define RTCRX509CERT_KEY_USAGE_F_CONTENT_COMMITTMENT_BIT 1
+#define RTCRX509CERT_KEY_USAGE_F_CONTENT_COMMITTMENT RT_BIT_32(1)
+#define RTCRX509CERT_KEY_USAGE_F_KEY_ENCIPHERMENT_BIT 2
+#define RTCRX509CERT_KEY_USAGE_F_KEY_ENCIPHERMENT RT_BIT_32(2)
+#define RTCRX509CERT_KEY_USAGE_F_DATA_ENCIPHERMENT_BIT 3
+#define RTCRX509CERT_KEY_USAGE_F_DATA_ENCIPHERMENT RT_BIT_32(3)
+#define RTCRX509CERT_KEY_USAGE_F_KEY_AGREEMENT_BIT 4
+#define RTCRX509CERT_KEY_USAGE_F_KEY_AGREEMENT RT_BIT_32(4)
+#define RTCRX509CERT_KEY_USAGE_F_KEY_CERT_SIGN_BIT 5
+#define RTCRX509CERT_KEY_USAGE_F_KEY_CERT_SIGN RT_BIT_32(5)
+#define RTCRX509CERT_KEY_USAGE_F_CRL_SIGN_BIT 6
+#define RTCRX509CERT_KEY_USAGE_F_CRL_SIGN RT_BIT_32(6)
+#define RTCRX509CERT_KEY_USAGE_F_ENCIPHERMENT_ONLY_BIT 7
+#define RTCRX509CERT_KEY_USAGE_F_ENCIPHERMENT_ONLY RT_BIT_32(7)
+#define RTCRX509CERT_KEY_USAGE_F_DECIPHERMENT_ONLY_BIT 8
+#define RTCRX509CERT_KEY_USAGE_F_DECIPHERMENT_ONLY RT_BIT_32(8)
+/** @} */
+
+/** @name X.509 Extended Key Usage flags. (RFC-5280 section 4.2.1.12, ++.)
+ * @remarks Needless to say, these flags doesn't cover all possible extended key
+ * usages, because there is a potential unlimited number of them. Only
+ * ones relevant to IPRT and it's users are covered.
+ * @{ */
+#define RTCRX509CERT_EKU_F_ANY RT_BIT_64(0)
+#define RTCRX509CERT_EKU_F_SERVER_AUTH RT_BIT_64(1)
+#define RTCRX509CERT_EKU_F_CLIENT_AUTH RT_BIT_64(2)
+#define RTCRX509CERT_EKU_F_CODE_SIGNING RT_BIT_64(3)
+#define RTCRX509CERT_EKU_F_EMAIL_PROTECTION RT_BIT_64(4)
+#define RTCRX509CERT_EKU_F_IPSEC_END_SYSTEM RT_BIT_64(5)
+#define RTCRX509CERT_EKU_F_IPSEC_TUNNEL RT_BIT_64(6)
+#define RTCRX509CERT_EKU_F_IPSEC_USER RT_BIT_64(7)
+#define RTCRX509CERT_EKU_F_TIMESTAMPING RT_BIT_64(8)
+#define RTCRX509CERT_EKU_F_OCSP_SIGNING RT_BIT_64(9)
+#define RTCRX509CERT_EKU_F_DVCS RT_BIT_64(10)
+#define RTCRX509CERT_EKU_F_SBGP_CERT_AA_SERVICE_AUTH RT_BIT_64(11)
+#define RTCRX509CERT_EKU_F_EAP_OVER_PPP RT_BIT_64(12)
+#define RTCRX509CERT_EKU_F_EAP_OVER_LAN RT_BIT_64(13)
+#define RTCRX509CERT_EKU_F_OTHER RT_BIT_64(16) /**< Other unknown extended key usage present. */
+#define RTCRX509CERT_EKU_F_APPLE_CODE_SIGNING RT_BIT_64(24)
+#define RTCRX509CERT_EKU_F_APPLE_CODE_SIGNING_DEVELOPMENT RT_BIT_64(25)
+#define RTCRX509CERT_EKU_F_APPLE_SOFTWARE_UPDATE_SIGNING RT_BIT_64(26)
+#define RTCRX509CERT_EKU_F_APPLE_CODE_SIGNING_THIRD_PARTY RT_BIT_64(27)
+#define RTCRX509CERT_EKU_F_APPLE_RESOURCE_SIGNING RT_BIT_64(28)
+#define RTCRX509CERT_EKU_F_APPLE_SYSTEM_IDENTITY RT_BIT_64(29)
+#define RTCRX509CERT_EKU_F_MS_TIMESTAMP_SIGNING RT_BIT_64(32)
+#define RTCRX509CERT_EKU_F_MS_NT5_CRYPTO RT_BIT_64(33)
+#define RTCRX509CERT_EKU_F_MS_OEM_WHQL_CRYPTO RT_BIT_64(34)
+#define RTCRX509CERT_EKU_F_MS_EMBEDDED_NT_CRYPTO RT_BIT_64(35)
+#define RTCRX509CERT_EKU_F_MS_KERNEL_MODE_CODE_SIGNING RT_BIT_64(36)
+#define RTCRX509CERT_EKU_F_MS_LIFETIME_SIGNING RT_BIT_64(37)
+#define RTCRX509CERT_EKU_F_MS_DRM RT_BIT_64(38)
+#define RTCRX509CERT_EKU_F_MS_DRM_INDIVIDUALIZATION RT_BIT_64(39)
+#define RTCRX509CERT_EKU_F_MS_WHQL_CRYPTO RT_BIT_64(40)
+#define RTCRX509CERT_EKU_F_MS_ATTEST_WHQL_CRYPTO RT_BIT_64(41)
+/** @} */
+
+/** @name Key purpose OIDs (extKeyUsage)
+ * @{ */
+#define RTCRX509_ANY_EXTENDED_KEY_USAGE_OID "2.5.29.37.0"
+#define RTCRX509_ID_KP_OID "1.3.6.1.5.5.7.3"
+#define RTCRX509_ID_KP_SERVER_AUTH_OID "1.3.6.1.5.5.7.3.1"
+#define RTCRX509_ID_KP_CLIENT_AUTH_OID "1.3.6.1.5.5.7.3.2"
+#define RTCRX509_ID_KP_CODE_SIGNING_OID "1.3.6.1.5.5.7.3.3"
+#define RTCRX509_ID_KP_EMAIL_PROTECTION_OID "1.3.6.1.5.5.7.3.4"
+#define RTCRX509_ID_KP_IPSEC_END_SYSTEM_OID "1.3.6.1.5.5.7.3.5"
+#define RTCRX509_ID_KP_IPSEC_TUNNEL_OID "1.3.6.1.5.5.7.3.6"
+#define RTCRX509_ID_KP_IPSEC_USER_OID "1.3.6.1.5.5.7.3.7"
+#define RTCRX509_ID_KP_TIMESTAMPING_OID "1.3.6.1.5.5.7.3.8"
+#define RTCRX509_ID_KP_OCSP_SIGNING_OID "1.3.6.1.5.5.7.3.9"
+#define RTCRX509_ID_KP_DVCS_OID "1.3.6.1.5.5.7.3.10"
+#define RTCRX509_ID_KP_SBGP_CERT_AA_SERVICE_AUTH_OID "1.3.6.1.5.5.7.3.11"
+#define RTCRX509_ID_KP_EAP_OVER_PPP_OID "1.3.6.1.5.5.7.3.13"
+#define RTCRX509_ID_KP_EAP_OVER_LAN_OID "1.3.6.1.5.5.7.3.14"
+/** @} */
+
+/** @name Microsoft extended key usage OIDs
+ * @{ */
+#define RTCRX509_MS_EKU_CERT_TRUST_LIST_SIGNING_OID "1.3.6.1.4.1.311.10.3.1"
+#define RTCRX509_MS_EKU_TIMESTAMP_SIGNING_OID "1.3.6.1.4.1.311.10.3.2"
+#define RTCRX509_MS_EKU_SERVER_GATED_CRYPTO_OID "1.3.6.1.4.1.311.10.3.3"
+#define RTCRX509_MS_EKU_SGC_SERIALIZED_OID "1.3.6.1.4.1.311.10.3.3.1"
+#define RTCRX509_MS_EKU_ENCRYPTED_FILE_SYSTEM_OID "1.3.6.1.4.1.311.10.3.4"
+#define RTCRX509_MS_EKU_WHQL_CRYPTO_OID "1.3.6.1.4.1.311.10.3.5"
+#define RTCRX509_MS_EKU_ATTEST_WHQL_CRYPTO_OID "1.3.6.1.4.1.311.10.3.5.1"
+#define RTCRX509_MS_EKU_NT5_CRYPTO_OID "1.3.6.1.4.1.311.10.3.6"
+#define RTCRX509_MS_EKU_OEM_WHQL_CRYPTO_OID "1.3.6.1.4.1.311.10.3.7"
+#define RTCRX509_MS_EKU_EMBEDDED_NT_CRYPTO_OID "1.3.6.1.4.1.311.10.3.8"
+#define RTCRX509_MS_EKU_ROOT_LIST_SIGNER_OID "1.3.6.1.4.1.311.10.3.9"
+#define RTCRX509_MS_EKU_QUALIFIED_SUBORDINATE_OID "1.3.6.1.4.1.311.10.3.10"
+#define RTCRX509_MS_EKU_KEY_RECOVERY_3_OID "1.3.6.1.4.1.311.10.3.11"
+#define RTCRX509_MS_EKU_DOCUMENT_SIGNING_OID "1.3.6.1.4.1.311.10.3.12"
+#define RTCRX509_MS_EKU_LIFETIME_SIGNING_OID "1.3.6.1.4.1.311.10.3.13"
+#define RTCRX509_MS_EKU_MOBILE_DEVICE_SOFTWARE_OID "1.3.6.1.4.1.311.10.3.14"
+#define RTCRX509_MS_EKU_SMART_DISPLAY_OID "1.3.6.1.4.1.311.10.3.15"
+#define RTCRX509_MS_EKU_CSP_SIGNATURE_OID "1.3.6.1.4.1.311.10.3.16"
+#define RTCRX509_MS_EKU_EFS_RECOVERY_OID "1.3.6.1.4.1.311.10.3.4.1"
+#define RTCRX509_MS_EKU_DRM_OID "1.3.6.1.4.1.311.10.5.1"
+#define RTCRX509_MS_EKU_DRM_INDIVIDUALIZATION_OID "1.3.6.1.4.1.311.10.5.2"
+#define RTCRX509_MS_EKU_LICENSES_OID "1.3.6.1.4.1.311.10.5.3"
+#define RTCRX509_MS_EKU_LICENSE_SERVER_OID "1.3.6.1.4.1.311.10.5.4"
+#define RTCRX509_MS_EKU_ENROLLMENT_AGENT_OID "1.3.6.1.4.1.311.20.2.1"
+#define RTCRX509_MS_EKU_SMARTCARD_LOGON_OID "1.3.6.1.4.1.311.20.2.2"
+#define RTCRX509_MS_EKU_CA_EXCHANGE_OID "1.3.6.1.4.1.311.21.5"
+#define RTCRX509_MS_EKU_KEY_RECOVERY_21_OID "1.3.6.1.4.1.311.21.6"
+#define RTCRX509_MS_EKU_SYSTEM_HEALTH_OID "1.3.6.1.4.1.311.47.1.1"
+#define RTCRX509_MS_EKU_SYSTEM_HEALTH_LOOPHOLE_OID "1.3.6.1.4.1.311.47.1.3"
+#define RTCRX509_MS_EKU_KERNEL_MODE_CODE_SIGNING_OID "1.3.6.1.4.1.311.61.1.1"
+/** @} */
+
+/** @name Apple extended key usage OIDs
+ * @{ */
+#define RTCRX509_APPLE_EKU_APPLE_EXTENDED_KEY_USAGE_OID "1.2.840.113635.100.4"
+#define RTCRX509_APPLE_EKU_CODE_SIGNING_OID "1.2.840.113635.100.4.1"
+#define RTCRX509_APPLE_EKU_CODE_SIGNING_DEVELOPMENT_OID "1.2.840.113635.100.4.1.1"
+#define RTCRX509_APPLE_EKU_SOFTWARE_UPDATE_SIGNING_OID "1.2.840.113635.100.4.1.2"
+#define RTCRX509_APPLE_EKU_CODE_SIGNING_THRID_PARTY_OID "1.2.840.113635.100.4.1.3"
+#define RTCRX509_APPLE_EKU_RESOURCE_SIGNING_OID "1.2.840.113635.100.4.1.4"
+#define RTCRX509_APPLE_EKU_ICHAT_SIGNING_OID "1.2.840.113635.100.4.2"
+#define RTCRX509_APPLE_EKU_ICHAT_ENCRYPTION_OID "1.2.840.113635.100.4.3"
+#define RTCRX509_APPLE_EKU_SYSTEM_IDENTITY_OID "1.2.840.113635.100.4.4"
+#define RTCRX509_APPLE_EKU_CRYPTO_ENV_OID "1.2.840.113635.100.4.5"
+#define RTCRX509_APPLE_EKU_CRYPTO_PRODUCTION_ENV_OID "1.2.840.113635.100.4.5.1"
+#define RTCRX509_APPLE_EKU_CRYPTO_MAINTENANCE_ENV_OID "1.2.840.113635.100.4.5.2"
+#define RTCRX509_APPLE_EKU_CRYPTO_TEST_ENV_OID "1.2.840.113635.100.4.5.3"
+#define RTCRX509_APPLE_EKU_CRYPTO_DEVELOPMENT_ENV_OID "1.2.840.113635.100.4.5.4"
+#define RTCRX509_APPLE_EKU_CRYPTO_QOS_OID "1.2.840.113635.100.4.6"
+#define RTCRX509_APPLE_EKU_CRYPTO_TIER0_QOS_OID "1.2.840.113635.100.4.6.1"
+#define RTCRX509_APPLE_EKU_CRYPTO_TIER1_QOS_OID "1.2.840.113635.100.4.6.2"
+#define RTCRX509_APPLE_EKU_CRYPTO_TIER2_QOS_OID "1.2.840.113635.100.4.6.3"
+#define RTCRX509_APPLE_EKU_CRYPTO_TIER3_QOS_OID "1.2.840.113635.100.4.6.4"
+/** @} */
+
+/**
+ * Use this to update derived values after changing the certificate
+ * extensions.
+ *
+ * @returns IPRT status code
+ * @param pThis The certificate.
+ * @param pErrInfo Where to return additional error information. Optional.
+ */
+RTDECL(int) RTCrX509TbsCertificate_ReprocessExtensions(PRTCRX509TBSCERTIFICATE pThis, PRTERRINFO pErrInfo);
+
+
+/**
+ * One X.509 Certificate (IPRT representation).
+ */
+typedef struct RTCRX509CERTIFICATE
+{
+ /** Sequence core. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** The to-be-signed certificate information. */
+ RTCRX509TBSCERTIFICATE TbsCertificate;
+ /** The signature algorithm (must match TbsCertificate.Signature). */
+ RTCRX509ALGORITHMIDENTIFIER SignatureAlgorithm;
+ /** The signature value. */
+ RTASN1BITSTRING SignatureValue;
+} RTCRX509CERTIFICATE;
+/** Pointer to the IPRT representation of one X.509 certificate. */
+typedef RTCRX509CERTIFICATE *PRTCRX509CERTIFICATE;
+/** Pointer to the const IPRT representation of one X.509 certificate. */
+typedef RTCRX509CERTIFICATE const *PCRTCRX509CERTIFICATE;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRX509CERTIFICATE, RTDECL, RTCrX509Certificate, SeqCore.Asn1Core);
+
+/**
+ * Checks if a certificate matches a given issuer name and serial number.
+ *
+ * @returns True / false.
+ * @param pCertificate The X.509 certificat.
+ * @param pIssuer The issuer name to match against.
+ * @param pSerialNumber The serial number to match against.
+ */
+RTDECL(bool) RTCrX509Certificate_MatchIssuerAndSerialNumber(PCRTCRX509CERTIFICATE pCertificate,
+ PCRTCRX509NAME pIssuer, PCRTASN1INTEGER pSerialNumber);
+
+RTDECL(bool) RTCrX509Certificate_MatchSubjectOrAltSubjectByRfc5280(PCRTCRX509CERTIFICATE pThis, PCRTCRX509NAME pName);
+RTDECL(bool) RTCrX509Certificate_IsSelfSigned(PCRTCRX509CERTIFICATE pCertificate);
+
+RTDECL(int) RTCrX509Certificate_VerifySignature(PCRTCRX509CERTIFICATE pThis, PCRTASN1OBJID pAlgorithm,
+ PCRTASN1DYNTYPE pParameters, PCRTASN1BITSTRING pPublicKey,
+ PRTERRINFO pErrInfo);
+RTDECL(int) RTCrX509Certificate_VerifySignatureSelfSigned(PCRTCRX509CERTIFICATE pThis, PRTERRINFO pErrInfo);
+RTDECL(int) RTCrX509Certificate_ReadFromFile(PRTCRX509CERTIFICATE pCertificate, const char *pszFilename, uint32_t fFlags,
+ PCRTASN1ALLOCATORVTABLE pAllocator, PRTERRINFO pErrInfo);
+RTDECL(int) RTCrX509Certificate_ReadFromBuffer(PRTCRX509CERTIFICATE pCertificate, const void *pvBuf, size_t cbBuf,
+ uint32_t fFlags, PCRTASN1ALLOCATORVTABLE pAllocator,
+ PRTERRINFO pErrInfo, const char *pszErrorTag);
+/** @name Flags for RTCrX509Certificate_ReadFromFile and
+ * RTCrX509Certificate_ReadFromBuffer
+ * @{ */
+/** Only allow PEM certificates, not binary ones.
+ * @sa RTCRPEMREADFILE_F_ONLY_PEM */
+#define RTCRX509CERT_READ_F_PEM_ONLY RT_BIT(1)
+/** @} */
+
+/** X509 Certificate markers for RTCrPemFindFirstSectionInContent et al. */
+extern RTDATADECL(RTCRPEMMARKER const) g_aRTCrX509CertificateMarkers[];
+/** Number of entries in g_aRTCrX509CertificateMarkers. */
+extern RTDATADECL(uint32_t const) g_cRTCrX509CertificateMarkers;
+
+
+/** Wrapper around RTCrPemWriteAsn1ToVfsIoStrm(). */
+DECLINLINE(ssize_t) RTCrX509Certificate_WriteToVfsIoStrm(RTVFSIOSTREAM hVfsIos, PRTCRX509CERTIFICATE pCertificate,
+ PRTERRINFO pErrInfo)
+{
+ return RTCrPemWriteAsn1ToVfsIoStrm(hVfsIos, &pCertificate->SeqCore.Asn1Core, 0 /*fFlags*/,
+ g_aRTCrX509CertificateMarkers[0].paWords[0].pszWord, pErrInfo);
+}
+
+/** Wrapper around RTCrPemWriteAsn1ToVfsFile(). */
+DECLINLINE(ssize_t) RTCrX509Certificate_WriteToVfsFile(RTVFSFILE hVfsFile, PRTCRX509CERTIFICATE pCertificate,
+ PRTERRINFO pErrInfo)
+{
+ return RTCrPemWriteAsn1ToVfsFile(hVfsFile, &pCertificate->SeqCore.Asn1Core, 0 /*fFlags*/,
+ g_aRTCrX509CertificateMarkers[0].paWords[0].pszWord, pErrInfo);
+}
+
+/** @name X.509 Certificate Extensions
+ * @{ */
+/** Old AuthorityKeyIdentifier OID. */
+#define RTCRX509_ID_CE_OLD_AUTHORITY_KEY_IDENTIFIER_OID "2.5.29.1"
+/** Old CertificatePolicies extension OID. */
+#define RTCRX509_ID_CE_OLD_CERTIFICATE_POLICIES_OID "2.5.29.3"
+/** Old SubjectAltName extension OID. */
+#define RTCRX509_ID_CE_OLD_SUBJECT_ALT_NAME_OID "2.5.29.7"
+/** Old IssuerAltName extension OID. */
+#define RTCRX509_ID_CE_OLD_ISSUER_ALT_NAME_OID "2.5.29.8"
+/** Old BasicContraints extension OID. */
+#define RTCRX509_ID_CE_OLD_BASIC_CONSTRAINTS_OID "2.5.29.10"
+/** SubjectKeyIdentifier OID. */
+#define RTCRX509_ID_CE_SUBJECT_KEY_IDENTIFIER_OID "2.5.29.14"
+/** KeyUsage OID. */
+#define RTCRX509_ID_CE_KEY_USAGE_OID "2.5.29.15"
+/** PrivateKeyUsagePeriod OID. */
+#define RTCRX509_ID_CE_PRIVATE_KEY_USAGE_PERIOD_OID "2.5.29.16"
+/** SubjectAltName extension OID. */
+#define RTCRX509_ID_CE_SUBJECT_ALT_NAME_OID "2.5.29.17"
+/** IssuerAltName extension OID. */
+#define RTCRX509_ID_CE_ISSUER_ALT_NAME_OID "2.5.29.18"
+/** BasicContraints extension OID. */
+#define RTCRX509_ID_CE_BASIC_CONSTRAINTS_OID "2.5.29.19"
+/** NameContraints extension OID. */
+#define RTCRX509_ID_CE_NAME_CONSTRAINTS_OID "2.5.29.30"
+/** CertificatePolicies extension OID. */
+#define RTCRX509_ID_CE_CERTIFICATE_POLICIES_OID "2.5.29.32"
+/** PolicyMappings extension OID. */
+#define RTCRX509_ID_CE_POLICY_MAPPINGS_OID "2.5.29.33"
+/** AuthorityKeyIdentifier OID. */
+#define RTCRX509_ID_CE_AUTHORITY_KEY_IDENTIFIER_OID "2.5.29.35"
+/** PolicyContraints extension OID. */
+#define RTCRX509_ID_CE_POLICY_CONSTRAINTS_OID "2.5.29.36"
+/** ExtKeyUsage (extended key usage) extension OID. */
+#define RTCRX509_ID_CE_EXT_KEY_USAGE_OID "2.5.29.37"
+/** ExtKeyUsage: OID for permitting any unspecified key usage. */
+#define RTCRX509_ID_CE_ANY_EXTENDED_KEY_USAGE_OID "2.5.29.37.0"
+/** AuthorityAttributeIdentifier OID. */
+#define RTCRX509_ID_CE_AUTHORITY_ATTRIBUTE_IDENTIFIER_OID "2.5.29.38"
+/** AcceptableCertPolicies OID. */
+#define RTCRX509_ID_CE_ACCEPTABLE_CERT_POLICIES_OID "2.5.29.52"
+/** InhibitAnyPolicy OID. */
+#define RTCRX509_ID_CE_INHIBIT_ANY_POLICY_OID "2.5.29.54"
+/** @} */
+
+
+/*
+ * Sequence of X.509 Certifcates (IPRT representation).
+ */
+RTASN1_IMPL_GEN_SET_OF_TYPEDEFS_AND_PROTOS(RTCRX509CERTIFICATES, RTCRX509CERTIFICATE, RTDECL, RTCrX509Certificates);
+
+/**
+ * Looks up a certificate by issuer name and serial number.
+ *
+ * @returns Pointer to the given certificate if found, NULL if not.
+ * @param pCertificates The X.509 certificate set to search.
+ * @param pIssuer The issuer name of the wanted certificate.
+ * @param pSerialNumber The serial number of the wanted certificate.
+ */
+RTDECL(PCRTCRX509CERTIFICATE) RTCrX509Certificates_FindByIssuerAndSerialNumber(PCRTCRX509CERTIFICATES pCertificates,
+ PCRTCRX509NAME pIssuer,
+ PCRTASN1INTEGER pSerialNumber);
+
+
+
+RTDECL(int) RTCrX509CertPathsCreate(PRTCRX509CERTPATHS phCertPaths, PCRTCRX509CERTIFICATE pTarget);
+RTDECL(uint32_t) RTCrX509CertPathsRetain(RTCRX509CERTPATHS hCertPaths);
+RTDECL(uint32_t) RTCrX509CertPathsRelease(RTCRX509CERTPATHS hCertPaths);
+RTDECL(int) RTCrX509CertPathsSetTrustedStore(RTCRX509CERTPATHS hCertPaths, RTCRSTORE hTrustedStore);
+RTDECL(int) RTCrX509CertPathsSetUntrustedStore(RTCRX509CERTPATHS hCertPaths, RTCRSTORE hUntrustedStore);
+RTDECL(int) RTCrX509CertPathsSetUntrustedArray(RTCRX509CERTPATHS hCertPaths, PCRTCRX509CERTIFICATE paCerts, uint32_t cCerts);
+RTDECL(int) RTCrX509CertPathsSetUntrustedSet(RTCRX509CERTPATHS hCertPaths, struct RTCRPKCS7SETOFCERTS const *pSetOfCerts);
+RTDECL(int) RTCrX509CertPathsSetValidTime(RTCRX509CERTPATHS hCertPaths, PCRTTIME pTime);
+RTDECL(int) RTCrX509CertPathsSetValidTimeSpec(RTCRX509CERTPATHS hCertPaths, PCRTTIMESPEC pTimeSpec);
+RTDECL(int) RTCrX509CertPathsSetTrustAnchorChecks(RTCRX509CERTPATHS hCertPaths, bool fEnable);
+RTDECL(int) RTCrX509CertPathsCreateEx(PRTCRX509CERTPATHS phCertPaths, PCRTCRX509CERTIFICATE pTarget, RTCRSTORE hTrustedStore,
+ RTCRSTORE hUntrustedStore, PCRTCRX509CERTIFICATE paUntrustedCerts, uint32_t cUntrustedCerts,
+ PCRTTIMESPEC pValidTime);
+RTDECL(int) RTCrX509CertPathsBuild(RTCRX509CERTPATHS hCertPaths, PRTERRINFO pErrInfo);
+RTDECL(int) RTCrX509CertPathsDumpOne(RTCRX509CERTPATHS hCertPaths, uint32_t iPath, uint32_t uVerbosity,
+ PFNRTDUMPPRINTFV pfnPrintfV, void *pvUser);
+RTDECL(int) RTCrX509CertPathsDumpAll(RTCRX509CERTPATHS hCertPaths, uint32_t uVerbosity,
+ PFNRTDUMPPRINTFV pfnPrintfV, void *pvUser);
+
+RTDECL(int) RTCrX509CertPathsValidateOne(RTCRX509CERTPATHS hCertPaths, uint32_t iPath, PRTERRINFO pErrInfo);
+RTDECL(int) RTCrX509CertPathsValidateAll(RTCRX509CERTPATHS hCertPaths, uint32_t *pcValidPaths, PRTERRINFO pErrInfo);
+
+RTDECL(uint32_t) RTCrX509CertPathsGetPathCount(RTCRX509CERTPATHS hCertPaths);
+RTDECL(int) RTCrX509CertPathsQueryPathInfo(RTCRX509CERTPATHS hCertPaths, uint32_t iPath,
+ bool *pfTrusted, uint32_t *pcNodes, PCRTCRX509NAME *ppSubject,
+ PCRTCRX509SUBJECTPUBLICKEYINFO *ppPublicKeyInfo,
+ PCRTCRX509CERTIFICATE *ppCert, PCRTCRCERTCTX *ppCertCtx, int *prcVerify);
+RTDECL(uint32_t) RTCrX509CertPathsGetPathLength(RTCRX509CERTPATHS hCertPaths, uint32_t iPath);
+RTDECL(int) RTCrX509CertPathsGetPathVerifyResult(RTCRX509CERTPATHS hCertPaths, uint32_t iPath);
+RTDECL(PCRTCRX509CERTIFICATE) RTCrX509CertPathsGetPathNodeCert(RTCRX509CERTPATHS hCertPaths, uint32_t iPath, uint32_t iNode);
+
+
+RT_C_DECLS_END
+
+/** @} */
+
+/** @} */
+
+#endif /* !IPRT_INCLUDED_crypto_x509_h */
+
diff --git a/include/iprt/ctype.h b/include/iprt/ctype.h
new file mode 100644
index 00000000..139af524
--- /dev/null
+++ b/include/iprt/ctype.h
@@ -0,0 +1,251 @@
+/** @file
+ * IPRT - Simple character type classiciation and conversion.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_ctype_h
+#define IPRT_INCLUDED_ctype_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#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 - 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 applicable.
+ *
+ * @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 applicable.
+ *
+ * @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 /* !IPRT_INCLUDED_ctype_h */
diff --git a/include/iprt/dbg.h b/include/iprt/dbg.h
new file mode 100644
index 00000000..64a3a94b
--- /dev/null
+++ b/include/iprt/dbg.h
@@ -0,0 +1,2034 @@
+/* $Id: dbg.h $ */
+/** @file
+ * IPRT - Debugging Routines.
+ */
+
+/*
+ * Copyright (C) 2008-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_dbg_h
+#define IPRT_INCLUDED_dbg_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+#include <iprt/stdarg.h>
+#include <iprt/ldr.h>
+
+RT_C_DECLS_BEGIN
+
+
+/** @defgroup grp_rt_dbg RTDbg - Debugging Routines
+ * @ingroup grp_rt
+ * @{
+ */
+
+
+/** Debug segment index. */
+typedef uint32_t RTDBGSEGIDX;
+/** Pointer to a debug segment index. */
+typedef RTDBGSEGIDX *PRTDBGSEGIDX;
+/** Pointer to a const debug segment index. */
+typedef RTDBGSEGIDX const *PCRTDBGSEGIDX;
+/** NIL debug segment index. */
+#define NIL_RTDBGSEGIDX UINT32_C(0xffffffff)
+/** The last normal segment index. */
+#define RTDBGSEGIDX_LAST UINT32_C(0xffffffef)
+/** Special segment index that indicates that the offset is a relative
+ * virtual address (RVA). I.e. an offset from the start of the module. */
+#define RTDBGSEGIDX_RVA UINT32_C(0xfffffff0)
+/** Special segment index that indicates that the offset is a absolute. */
+#define RTDBGSEGIDX_ABS UINT32_C(0xfffffff1)
+/** The last valid special segment index. */
+#define RTDBGSEGIDX_SPECIAL_LAST RTDBGSEGIDX_ABS
+/** The last valid special segment index. */
+#define RTDBGSEGIDX_SPECIAL_FIRST (RTDBGSEGIDX_LAST + 1U)
+
+
+
+/** @name RTDBGSYMADDR_FLAGS_XXX
+ * Flags used when looking up a symbol by address.
+ * @{ */
+/** Less or equal address. (default) */
+#define RTDBGSYMADDR_FLAGS_LESS_OR_EQUAL UINT32_C(0)
+/** Greater or equal address. */
+#define RTDBGSYMADDR_FLAGS_GREATER_OR_EQUAL UINT32_C(1)
+/** Don't consider absolute symbols in deferred modules. */
+#define RTDBGSYMADDR_FLAGS_SKIP_ABS_IN_DEFERRED UINT32_C(2)
+/** Don't search for absolute symbols if it's expensive. */
+#define RTDBGSYMADDR_FLAGS_SKIP_ABS UINT32_C(4)
+/** Mask of valid flags. */
+#define RTDBGSYMADDR_FLAGS_VALID_MASK UINT32_C(7)
+/** @} */
+
+/** @name RTDBGSYMBOLADD_F_XXX - Flags for RTDbgModSymbolAdd and RTDbgAsSymbolAdd.
+ * @{ */
+/** Replace existing symbol with same address. */
+#define RTDBGSYMBOLADD_F_REPLACE_SAME_ADDR UINT32_C(0x00000001)
+/** Replace any existing symbols overlapping the symbol range. */
+#define RTDBGSYMBOLADD_F_REPLACE_ANY UINT32_C(0x00000002)
+/** Adjust sizes on address conflict. This applies to the symbol being added
+ * as well as existing symbols. */
+#define RTDBGSYMBOLADD_F_ADJUST_SIZES_ON_CONFLICT UINT32_C(0x00000004)
+/** Mask of valid flags. */
+#define RTDBGSYMBOLADD_F_VALID_MASK UINT32_C(0x00000007)
+/** @} */
+
+/** Max length (including '\\0') of a segment name. */
+#define RTDBG_SEGMENT_NAME_LENGTH (128 - 8 - 8 - 8 - 4 - 4)
+
+/**
+ * Debug module segment.
+ */
+typedef struct RTDBGSEGMENT
+{
+ /** The load address.
+ * RTUINTPTR_MAX if not applicable. */
+ RTUINTPTR Address;
+ /** The image relative virtual address of the segment.
+ * RTUINTPTR_MAX if not applicable. */
+ RTUINTPTR uRva;
+ /** The segment size. */
+ RTUINTPTR cb;
+ /** The segment flags. (reserved) */
+ uint32_t fFlags;
+ /** The segment index. */
+ RTDBGSEGIDX iSeg;
+ /** Symbol name. */
+ char szName[RTDBG_SEGMENT_NAME_LENGTH];
+} RTDBGSEGMENT;
+/** Pointer to a debug module segment. */
+typedef RTDBGSEGMENT *PRTDBGSEGMENT;
+/** Pointer to a const debug module segment. */
+typedef RTDBGSEGMENT const *PCRTDBGSEGMENT;
+
+
+/**
+ * Return type.
+ */
+typedef enum RTDBGRETURNTYPE
+{
+ /** The usual invalid 0 value. */
+ RTDBGRETURNTYPE_INVALID = 0,
+ /** Near 16-bit return. */
+ RTDBGRETURNTYPE_NEAR16,
+ /** Near 32-bit return. */
+ RTDBGRETURNTYPE_NEAR32,
+ /** Near 64-bit return. */
+ RTDBGRETURNTYPE_NEAR64,
+ /** Far 16:16 return. */
+ RTDBGRETURNTYPE_FAR16,
+ /** Far 16:32 return. */
+ RTDBGRETURNTYPE_FAR32,
+ /** Far 16:64 return. */
+ RTDBGRETURNTYPE_FAR64,
+ /** 16-bit iret return (e.g. real or 286 protect mode). */
+ RTDBGRETURNTYPE_IRET16,
+ /** 32-bit iret return. */
+ RTDBGRETURNTYPE_IRET32,
+ /** 32-bit iret return. */
+ RTDBGRETURNTYPE_IRET32_PRIV,
+ /** 32-bit iret return to V86 mode. */
+ RTDBGRETURNTYPE_IRET32_V86,
+ /** @todo 64-bit iret return. */
+ RTDBGRETURNTYPE_IRET64,
+ /** The end of the valid return types. */
+ RTDBGRETURNTYPE_END,
+ /** The usual 32-bit blowup. */
+ RTDBGRETURNTYPE_32BIT_HACK = 0x7fffffff
+} RTDBGRETURNTYPE;
+
+/**
+ * Figures the size of the return state on the stack.
+ *
+ * @returns number of bytes. 0 if invalid parameter.
+ * @param enmRetType The type of return.
+ */
+DECLINLINE(unsigned) RTDbgReturnTypeSize(RTDBGRETURNTYPE enmRetType)
+{
+ switch (enmRetType)
+ {
+ case RTDBGRETURNTYPE_NEAR16: return 2;
+ case RTDBGRETURNTYPE_NEAR32: return 4;
+ case RTDBGRETURNTYPE_NEAR64: return 8;
+ case RTDBGRETURNTYPE_FAR16: return 4;
+ case RTDBGRETURNTYPE_FAR32: return 4;
+ case RTDBGRETURNTYPE_FAR64: return 8;
+ case RTDBGRETURNTYPE_IRET16: return 6;
+ case RTDBGRETURNTYPE_IRET32: return 4*3;
+ case RTDBGRETURNTYPE_IRET32_PRIV: return 4*5;
+ case RTDBGRETURNTYPE_IRET32_V86: return 4*9;
+ case RTDBGRETURNTYPE_IRET64: return 5*8;
+
+ case RTDBGRETURNTYPE_INVALID:
+ case RTDBGRETURNTYPE_END:
+ case RTDBGRETURNTYPE_32BIT_HACK:
+ break;
+ }
+ return 0;
+}
+
+/**
+ * Check if near return.
+ *
+ * @returns true if near, false if far or iret.
+ * @param enmRetType The type of return.
+ */
+DECLINLINE(bool) RTDbgReturnTypeIsNear(RTDBGRETURNTYPE enmRetType)
+{
+ return enmRetType == RTDBGRETURNTYPE_NEAR32
+ || enmRetType == RTDBGRETURNTYPE_NEAR64
+ || enmRetType == RTDBGRETURNTYPE_NEAR16;
+}
+
+
+
+/** Magic value for RTDBGUNWINDSTATE::u32Magic (James Moody). */
+#define RTDBGUNWINDSTATE_MAGIC UINT32_C(0x19250326)
+/** Magic value for RTDBGUNWINDSTATE::u32Magic after use. */
+#define RTDBGUNWINDSTATE_MAGIC_DEAD UINT32_C(0x20101209)
+
+/**
+ * Unwind machine state.
+ */
+typedef struct RTDBGUNWINDSTATE
+{
+ /** Structure magic (RTDBGUNWINDSTATE_MAGIC) */
+ uint32_t u32Magic;
+ /** The state architecture. */
+ RTLDRARCH enmArch;
+
+ /** The program counter register.
+ * amd64/x86: RIP/EIP/IP
+ * sparc: PC
+ * arm32: PC / R15
+ */
+ uint64_t uPc;
+
+ /** Return type. */
+ RTDBGRETURNTYPE enmRetType;
+
+ /** Register state (see enmArch). */
+ union
+ {
+ /** RTLDRARCH_AMD64, RTLDRARCH_X86_32 and RTLDRARCH_X86_16. */
+ struct
+ {
+ /** General purpose registers indexed by X86_GREG_XXX. */
+ uint64_t auRegs[16];
+ /** The frame address. */
+ RTFAR64 FrameAddr;
+ /** Set if we're in real or virtual 8086 mode. */
+ bool fRealOrV86;
+ /** The flags register. */
+ uint64_t uRFlags;
+ /** Trap error code. */
+ uint64_t uErrCd;
+ /** Segment registers (indexed by X86_SREG_XXX). */
+ uint16_t auSegs[6];
+
+ /** Bitmap tracking register we've loaded and which content can possibly be trusted. */
+ union
+ {
+ /** For effective clearing of the bits. */
+ uint32_t fAll;
+ /** Detailed view. */
+ struct
+ {
+ /** Bitmap indicating whether a GPR was loaded (parallel to auRegs). */
+ uint16_t fRegs;
+ /** Bitmap indicating whether a segment register was loaded (parallel to auSegs). */
+ uint8_t fSegs;
+ /** Set if uPc was loaded. */
+ RT_GCC_EXTENSION uint8_t fPc : 1;
+ /** Set if FrameAddr was loaded. */
+ RT_GCC_EXTENSION uint8_t fFrameAddr : 1;
+ /** Set if uRFlags was loaded. */
+ RT_GCC_EXTENSION uint8_t fRFlags : 1;
+ /** Set if uErrCd was loaded. */
+ RT_GCC_EXTENSION uint8_t fErrCd : 1;
+ } s;
+ } Loaded;
+ } x86;
+
+ /** @todo add ARM and others as needed. */
+ } u;
+
+ /**
+ * Stack read callback.
+ *
+ * @returns IPRT status code.
+ * @param pThis Pointer to this structure.
+ * @param uSp The stack pointer address.
+ * @param cbToRead The number of bytes to read.
+ * @param pvDst Where to put the bytes we read.
+ */
+ DECLCALLBACKMEMBER(int, pfnReadStack,(struct RTDBGUNWINDSTATE *pThis, RTUINTPTR uSp, size_t cbToRead, void *pvDst));
+ /** User argument (useful for pfnReadStack). */
+ void *pvUser;
+
+} RTDBGUNWINDSTATE;
+
+/**
+ * Try read a 16-bit value off the stack.
+ *
+ * @returns pfnReadStack result.
+ * @param pThis The unwind state.
+ * @param uSrcAddr The stack address.
+ * @param puDst The read destination.
+ */
+DECLINLINE(int) RTDbgUnwindLoadStackU16(PRTDBGUNWINDSTATE pThis, RTUINTPTR uSrcAddr, uint16_t *puDst)
+{
+ return pThis->pfnReadStack(pThis, uSrcAddr, sizeof(*puDst), puDst);
+}
+
+/**
+ * Try read a 32-bit value off the stack.
+ *
+ * @returns pfnReadStack result.
+ * @param pThis The unwind state.
+ * @param uSrcAddr The stack address.
+ * @param puDst The read destination.
+ */
+DECLINLINE(int) RTDbgUnwindLoadStackU32(PRTDBGUNWINDSTATE pThis, RTUINTPTR uSrcAddr, uint32_t *puDst)
+{
+ return pThis->pfnReadStack(pThis, uSrcAddr, sizeof(*puDst), puDst);
+}
+
+/**
+ * Try read a 64-bit value off the stack.
+ *
+ * @returns pfnReadStack result.
+ * @param pThis The unwind state.
+ * @param uSrcAddr The stack address.
+ * @param puDst The read destination.
+ */
+DECLINLINE(int) RTDbgUnwindLoadStackU64(PRTDBGUNWINDSTATE pThis, RTUINTPTR uSrcAddr, uint64_t *puDst)
+{
+ return pThis->pfnReadStack(pThis, uSrcAddr, sizeof(*puDst), puDst);
+}
+
+
+
+/** Max length (including '\\0') of a symbol name. */
+#define RTDBG_SYMBOL_NAME_LENGTH (512 - 8 - 8 - 8 - 4 - 4 - 8)
+
+/**
+ * Debug symbol.
+ */
+typedef struct RTDBGSYMBOL
+{
+ /** Symbol value (address).
+ * This depends a bit who you ask. It will be the same as offSeg when you
+ * as RTDbgMod, but the mapping address if you ask RTDbgAs. */
+ RTUINTPTR Value;
+ /** Symbol size. */
+ RTUINTPTR cb;
+ /** Offset into the segment specified by iSeg. */
+ RTUINTPTR offSeg;
+ /** Segment number. */
+ RTDBGSEGIDX iSeg;
+ /** Symbol Flags. (reserved). */
+ uint32_t fFlags;
+ /** Symbol ordinal.
+ * This is set to UINT32_MAX if the ordinals aren't supported. */
+ uint32_t iOrdinal;
+ /** Symbol name. */
+ char szName[RTDBG_SYMBOL_NAME_LENGTH];
+} RTDBGSYMBOL;
+/** Pointer to debug symbol. */
+typedef RTDBGSYMBOL *PRTDBGSYMBOL;
+/** Pointer to const debug symbol. */
+typedef const RTDBGSYMBOL *PCRTDBGSYMBOL;
+
+
+/**
+ * Allocate a new symbol structure.
+ *
+ * @returns Pointer to a new structure on success, NULL on failure.
+ */
+RTDECL(PRTDBGSYMBOL) RTDbgSymbolAlloc(void);
+
+/**
+ * Duplicates a symbol structure.
+ *
+ * @returns Pointer to duplicate on success, NULL on failure.
+ *
+ * @param pSymInfo The symbol info to duplicate.
+ */
+RTDECL(PRTDBGSYMBOL) RTDbgSymbolDup(PCRTDBGSYMBOL pSymInfo);
+
+/**
+ * Free a symbol structure previously allocated by a RTDbg method.
+ *
+ * @param pSymInfo The symbol info to free. NULL is ignored.
+ */
+RTDECL(void) RTDbgSymbolFree(PRTDBGSYMBOL pSymInfo);
+
+
+/** Max length (including '\\0') of a debug info file name. */
+#define RTDBG_FILE_NAME_LENGTH (260)
+
+
+/**
+ * Debug line number information.
+ */
+typedef struct RTDBGLINE
+{
+ /** Address.
+ * This depends a bit who you ask. It will be the same as offSeg when you
+ * as RTDbgMod, but the mapping address if you ask RTDbgAs. */
+ RTUINTPTR Address;
+ /** Offset into the segment specified by iSeg. */
+ RTUINTPTR offSeg;
+ /** Segment number. */
+ RTDBGSEGIDX iSeg;
+ /** Line number. */
+ uint32_t uLineNo;
+ /** Symbol ordinal.
+ * This is set to UINT32_MAX if the ordinals aren't supported. */
+ uint32_t iOrdinal;
+ /** Filename. */
+ char szFilename[RTDBG_FILE_NAME_LENGTH];
+} RTDBGLINE;
+/** Pointer to debug line number. */
+typedef RTDBGLINE *PRTDBGLINE;
+/** Pointer to const debug line number. */
+typedef const RTDBGLINE *PCRTDBGLINE;
+
+/**
+ * Allocate a new line number structure.
+ *
+ * @returns Pointer to a new structure on success, NULL on failure.
+ */
+RTDECL(PRTDBGLINE) RTDbgLineAlloc(void);
+
+/**
+ * Duplicates a line number structure.
+ *
+ * @returns Pointer to duplicate on success, NULL on failure.
+ *
+ * @param pLine The line number to duplicate.
+ */
+RTDECL(PRTDBGLINE) RTDbgLineDup(PCRTDBGLINE pLine);
+
+/**
+ * Free a line number structure previously allocated by a RTDbg method.
+ *
+ * @param pLine The line number to free. NULL is ignored.
+ */
+RTDECL(void) RTDbgLineFree(PRTDBGLINE pLine);
+
+
+/**
+ * Dump the stack of the current thread into @a pszStack.
+ *
+ * This could be a little slow as it reads image and debug info again for each call.
+ *
+ * @returns Length of string returned in @a pszStack.
+ * @param pszStack The output buffer.
+ * @param cbStack The size of the output buffer.
+ * @param fFlags Future flags, MBZ.
+ *
+ * @remarks Not present on all systems and contexts.
+ */
+RTDECL(size_t) RTDbgStackDumpSelf(char *pszStack, size_t cbStack, uint32_t fFlags);
+
+
+# ifdef IN_RING3
+
+/** @defgroup grp_rt_dbgcfg RTDbgCfg - Debugging Configuration
+ *
+ * The settings used when loading and processing debug info is kept in a
+ * RTDBGCFG instance since it's generally shared for a whole debugging session
+ * and anyhow would be a major pain to pass as individual parameters to each
+ * call. The debugging config API not only keeps the settings information but
+ * also provide APIs for making use of it, and in some cases, like for instance
+ * symbol severs, retriving and maintaining it.
+ *
+ * @todo Work in progress - APIs are still missing, adding when needed.
+ *
+ * @{
+ */
+
+/** Debugging configuration handle. */
+typedef struct RTDBGCFGINT *RTDBGCFG;
+/** Pointer to a debugging configuration handle. */
+typedef RTDBGCFG *PRTDBGCFG;
+/** NIL debug configuration handle. */
+#define NIL_RTDBGCFG ((RTDBGCFG)0)
+
+/** @name RTDBGCFG_FLAGS_XXX - Debugging configuration flags.
+ * @{ */
+/** Use deferred loading. */
+#define RTDBGCFG_FLAGS_DEFERRED RT_BIT_64(0)
+/** Don't use the symbol server (http). */
+#define RTDBGCFG_FLAGS_NO_SYM_SRV RT_BIT_64(1)
+/** Don't use system search paths.
+ * On windows this means not using _NT_ALT_SYMBOL_PATH, _NT_SYMBOL_PATH,
+ * _NT_SOURCE_PATH, and _NT_EXECUTABLE_PATH.
+ * On other systems the effect has yet to be determined. */
+#define RTDBGCFG_FLAGS_NO_SYSTEM_PATHS RT_BIT_64(2)
+/** Don't search the debug and image paths recursively. */
+#define RTDBGCFG_FLAGS_NO_RECURSIV_SEARCH RT_BIT_64(3)
+/** Don't search the source paths recursively. */
+#define RTDBGCFG_FLAGS_NO_RECURSIV_SRC_SEARCH RT_BIT_64(4)
+/** @} */
+
+/**
+ * Debugging configuration properties.
+ *
+ * The search paths are using the DOS convention of semicolon as separator
+ * character. The the special 'srv' + asterisk syntax known from the windows
+ * debugger search paths are also supported to some extent, as is 'cache' +
+ * asterisk.
+ */
+typedef enum RTDBGCFGPROP
+{
+ /** The customary invalid 0 value. */
+ RTDBGCFGPROP_INVALID = 0,
+ /** RTDBGCFG_FLAGS_XXX.
+ * Env: _FLAGS
+ * The environment variable can be specified as a unsigned value or one or more
+ * mnemonics separated by spaces. */
+ RTDBGCFGPROP_FLAGS,
+ /** List of paths to search for symbol files and images.
+ * Env: _PATH */
+ RTDBGCFGPROP_PATH,
+ /** List of symbol file suffixes (semicolon separated).
+ * Env: _SUFFIXES */
+ RTDBGCFGPROP_SUFFIXES,
+ /** List of paths to search for source files.
+ * Env: _SRC_PATH */
+ RTDBGCFGPROP_SRC_PATH,
+ /** End of valid values. */
+ RTDBGCFGPROP_END,
+ /** The customary 32-bit type hack. */
+ RTDBGCFGPROP_32BIT_HACK = 0x7fffffff
+} RTDBGCFGPROP;
+
+/**
+ * Configuration property change operation.
+ */
+typedef enum RTDBGCFGOP
+{
+ /** Customary invalid 0 value. */
+ RTDBGCFGOP_INVALID = 0,
+ /** Replace the current value with the given one. */
+ RTDBGCFGOP_SET,
+ /** Append the given value to the existing one. For integer values this is
+ * considered a bitwise OR operation. */
+ RTDBGCFGOP_APPEND,
+ /** Prepend the given value to the existing one. For integer values this is
+ * considered a bitwise OR operation. */
+ RTDBGCFGOP_PREPEND,
+ /** Removes the value from the existing one. For interger values the value is
+ * complemented and ANDed with the existing one, clearing all the specified
+ * flags/bits. */
+ RTDBGCFGOP_REMOVE,
+ /** End of valid values. */
+ RTDBGCFGOP_END,
+ /** Customary 32-bit type hack. */
+ RTDBGCFGOP_32BIT_HACK = 0x7fffffff
+} RTDBGCFGOP;
+
+
+
+/**
+ * Initializes a debugging configuration.
+ *
+ * @returns IPRT status code.
+ * @param phDbgCfg Where to return the configuration handle.
+ * @param pszEnvVarPrefix The environment variable prefix. If NULL, the
+ * environment is not consulted.
+ * @param fNativePaths Whether to pick up native paths from the
+ * environment.
+ *
+ * @sa RTDbgCfgChangeString, RTDbgCfgChangeUInt.
+ */
+RTDECL(int) RTDbgCfgCreate(PRTDBGCFG phDbgCfg, const char *pszEnvVarPrefix, bool fNativePaths);
+
+/**
+ * Retains a new reference to a debugging config.
+ *
+ * @returns New reference count.
+ * UINT32_MAX is returned if the handle is invalid (asserted).
+ * @param hDbgCfg The config handle.
+ */
+RTDECL(uint32_t) RTDbgCfgRetain(RTDBGCFG hDbgCfg);
+
+/**
+ * Releases a references to a debugging config.
+ *
+ * @returns New reference count, if 0 the config was freed. UINT32_MAX is
+ * returned if the handle is invalid (asserted).
+ * @param hDbgCfg The config handle.
+ */
+RTDECL(uint32_t) RTDbgCfgRelease(RTDBGCFG hDbgCfg);
+
+/**
+ * Changes a property value by string.
+ *
+ * For string values the string is used more or less as given. For integer
+ * values and flags, it can contains both values (ORed together) or property
+ * specific mnemonics (ORed / ~ANDed).
+ *
+ * @returns IPRT status code.
+ * @retval VERR_DBG_CFG_INVALID_VALUE
+ * @param hDbgCfg The debugging configuration handle.
+ * @param enmProp The property to change.
+ * @param enmOp How to change the property.
+ * @param pszValue The property value to apply.
+ */
+RTDECL(int) RTDbgCfgChangeString(RTDBGCFG hDbgCfg, RTDBGCFGPROP enmProp, RTDBGCFGOP enmOp, const char *pszValue);
+
+/**
+ * Changes a property value by unsigned integer (64-bit).
+ *
+ * This can only be applied to integer and flag properties.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_DBG_CFG_NOT_UINT_PROP
+ * @param hDbgCfg The debugging configuration handle.
+ * @param enmProp The property to change.
+ * @param enmOp How to change the property.
+ * @param uValue The property value to apply.
+ */
+RTDECL(int) RTDbgCfgChangeUInt(RTDBGCFG hDbgCfg, RTDBGCFGPROP enmProp, RTDBGCFGOP enmOp, uint64_t uValue);
+
+/**
+ * Query a property value as string.
+ *
+ * Integer and flags properties are returned as a list of mnemonics if possible,
+ * otherwise as simple hex values.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_BUFFER_OVERFLOW if there isn't sufficient buffer space. Nothing
+ * is written.
+ * @param hDbgCfg The debugging configuration handle.
+ * @param enmProp The property to change.
+ * @param pszValue The output buffer.
+ * @param cbValue The size of the output buffer.
+ */
+RTDECL(int) RTDbgCfgQueryString(RTDBGCFG hDbgCfg, RTDBGCFGPROP enmProp, char *pszValue, size_t cbValue);
+
+/**
+ * Query a property value as unsigned integer (64-bit).
+ *
+ * Only integer and flags properties can be queried this way.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_DBG_CFG_NOT_UINT_PROP
+ * @param hDbgCfg The debugging configuration handle.
+ * @param enmProp The property to change.
+ * @param puValue Where to return the value.
+ */
+RTDECL(int) RTDbgCfgQueryUInt(RTDBGCFG hDbgCfg, RTDBGCFGPROP enmProp, uint64_t *puValue);
+
+/**
+ * Log callback.
+ *
+ * @param hDbgCfg The debug config instance.
+ * @param iLevel The message level.
+ * @param pszMsg The message.
+ * @param pvUser User argument.
+ */
+typedef DECLCALLBACKTYPE(void, FNRTDBGCFGLOG,(RTDBGCFG hDbgCfg, uint32_t iLevel, const char *pszMsg, void *pvUser));
+/** Pointer to a log callback. */
+typedef FNRTDBGCFGLOG *PFNRTDBGCFGLOG;
+
+/**
+ * Sets the log callback for the configuration.
+ *
+ * This will fail if there is already a log callback present, unless pfnCallback
+ * is NULL.
+ *
+ * @returns IPRT status code.
+ * @param hDbgCfg The debugging configuration handle.
+ * @param pfnCallback The callback function. NULL to unset.
+ * @param pvUser The user argument.
+ */
+RTDECL(int) RTDbgCfgSetLogCallback(RTDBGCFG hDbgCfg, PFNRTDBGCFGLOG pfnCallback, void *pvUser);
+
+/**
+ * Callback used by the RTDbgCfgOpen function to try out a file that was found.
+ *
+ * @returns On statuses other than VINF_CALLBACK_RETURN and
+ * VERR_CALLBACK_RETURN the search will continue till the end of the
+ * list. These status codes will not necessarily be propagated to the
+ * caller in any consistent manner.
+ * @retval VINF_CALLBACK_RETURN if successfully opened the file and it's time
+ * to return
+ * @retval VERR_CALLBACK_RETURN if we should stop searching immediately.
+ *
+ * @param hDbgCfg The debugging configuration handle.
+ * @param pszFilename The path to the file that should be tried out.
+ * @param pvUser1 First user parameter.
+ * @param pvUser2 Second user parameter.
+ */
+typedef DECLCALLBACKTYPE(int, FNRTDBGCFGOPEN,(RTDBGCFG hDbgCfg, const char *pszFilename, void *pvUser1, void *pvUser2));
+/** Pointer to a open-file callback used to the RTDbgCfgOpen functions. */
+typedef FNRTDBGCFGOPEN *PFNRTDBGCFGOPEN;
+
+
+RTDECL(int) RTDbgCfgOpenEx(RTDBGCFG hDbgCfg, const char *pszFilename, const char *pszCacheSubDir,
+ const char *pszUuidMappingSubDir, uint32_t fFlags,
+ PFNRTDBGCFGOPEN pfnCallback, void *pvUser1, void *pvUser2);
+RTDECL(int) RTDbgCfgOpenPeImage(RTDBGCFG hDbgCfg, const char *pszFilename, uint32_t cbImage, uint32_t uTimestamp,
+ PFNRTDBGCFGOPEN pfnCallback, void *pvUser1, void *pvUser2);
+RTDECL(int) RTDbgCfgOpenPdb70(RTDBGCFG hDbgCfg, const char *pszFilename, PCRTUUID pUuid, uint32_t uAge,
+ PFNRTDBGCFGOPEN pfnCallback, void *pvUser1, void *pvUser2);
+RTDECL(int) RTDbgCfgOpenPdb20(RTDBGCFG hDbgCfg, const char *pszFilename, uint32_t cbImage, uint32_t uTimestamp, uint32_t uAge,
+ PFNRTDBGCFGOPEN pfnCallback, void *pvUser1, void *pvUser2);
+RTDECL(int) RTDbgCfgOpenDbg(RTDBGCFG hDbgCfg, const char *pszFilename, uint32_t cbImage, uint32_t uTimestamp,
+ PFNRTDBGCFGOPEN pfnCallback, void *pvUser1, void *pvUser2);
+RTDECL(int) RTDbgCfgOpenDwo(RTDBGCFG hDbgCfg, const char *pszFilename, uint32_t uCrc32,
+ PFNRTDBGCFGOPEN pfnCallback, void *pvUser1, void *pvUser2);
+RTDECL(int) RTDbgCfgOpenDwoBuildId(RTDBGCFG hDbgCfg, const char *pszFilename, const uint8_t *pbBuildId,
+ size_t cbBuildId, PFNRTDBGCFGOPEN pfnCallback, void *pvUser1, void *pvUser2);
+RTDECL(int) RTDbgCfgOpenDsymBundle(RTDBGCFG hDbgCfg, const char *pszFilename, PCRTUUID pUuid,
+ PFNRTDBGCFGOPEN pfnCallback, void *pvUser1, void *pvUser2);
+RTDECL(int) RTDbgCfgOpenMachOImage(RTDBGCFG hDbgCfg, const char *pszFilename, PCRTUUID pUuid,
+ PFNRTDBGCFGOPEN pfnCallback, void *pvUser1, void *pvUser2);
+
+/** @name RTDBGCFG_O_XXX - Open flags for RTDbgCfgOpen.
+ * @{ */
+/** The operative system mask. The values are RT_OPSYS_XXX. */
+#define RTDBGCFG_O_OPSYS_MASK UINT32_C(0x000000ff)
+/** Use debuginfod style symbol servers when encountered in the path. */
+#define RTDBGCFG_O_DEBUGINFOD RT_BIT_32(24)
+/** Same as RTDBGCFG_FLAGS_NO_SYSTEM_PATHS. */
+#define RTDBGCFG_O_NO_SYSTEM_PATHS RT_BIT_32(25)
+/** The files may be compressed MS styled. */
+#define RTDBGCFG_O_MAYBE_COMPRESSED_MS RT_BIT_32(26)
+/** Whether to make a recursive search. */
+#define RTDBGCFG_O_RECURSIVE RT_BIT_32(27)
+/** We're looking for a separate debug file. */
+#define RTDBGCFG_O_EXT_DEBUG_FILE RT_BIT_32(28)
+/** We're looking for an executable image. */
+#define RTDBGCFG_O_EXECUTABLE_IMAGE RT_BIT_32(29)
+/** The file search should be done in an case insensitive fashion. */
+#define RTDBGCFG_O_CASE_INSENSITIVE RT_BIT_32(30)
+/** Use Windbg style symbol servers when encountered in the path. */
+#define RTDBGCFG_O_SYMSRV RT_BIT_32(31)
+/** Mask of valid flags. */
+#define RTDBGCFG_O_VALID_MASK UINT32_C(0xff0000ff)
+/** @} */
+
+
+/** @name Static symbol cache configuration
+ * @{ */
+/** The cache subdirectory containing the UUID mappings for .dSYM bundles.
+ * The UUID mappings implemented by IPRT are splitting the image/dsym UUID up
+ * into five 4 digit parts that maps to directories and one twelve digit part
+ * that maps to a symbolic link. The symlink points to the file in the
+ * Contents/Resources/DWARF/ directory of the .dSYM bundle for a .dSYM map, and
+ * to the image file (Contents/MacOS/bundlename for bundles) for image map.
+ *
+ * According to available documentation, both lldb and gdb are able to use these
+ * UUID maps to find debug info while debugging. See:
+ * http://lldb.llvm.org/symbols.html
+ */
+#define RTDBG_CACHE_UUID_MAP_DIR_DSYMS "dsym-uuids"
+/** The cache subdirectory containing the UUID mappings for image files. */
+#define RTDBG_CACHE_UUID_MAP_DIR_IMAGES "image-uuids"
+/** Suffix used for the cached .dSYM debug files.
+ * In .dSYM bundles only the .dSYM/Contents/Resources/DWARF/debug-file is
+ * copied into the cache, and in order to not clash with the stripped/rich image
+ * file, the cache tool slaps this suffix onto the name. */
+#define RTDBG_CACHE_DSYM_FILE_SUFFIX ".dwarf"
+/** @} */
+
+# endif /* IN_RING3 */
+
+/** @} */
+
+
+/** @defgroup grp_rt_dbgas RTDbgAs - Debug Address Space
+ * @{
+ */
+
+/**
+ * Creates an empty address space.
+ *
+ * @returns IPRT status code.
+ *
+ * @param phDbgAs Where to store the address space handle on success.
+ * @param FirstAddr The first address in the address space.
+ * @param LastAddr The last address in the address space.
+ * @param pszName The name of the address space.
+ */
+RTDECL(int) RTDbgAsCreate(PRTDBGAS phDbgAs, RTUINTPTR FirstAddr, RTUINTPTR LastAddr, const char *pszName);
+
+/**
+ * Variant of RTDbgAsCreate that takes a name format string.
+ *
+ * @returns IPRT status code.
+ *
+ * @param phDbgAs Where to store the address space handle on success.
+ * @param FirstAddr The first address in the address space.
+ * @param LastAddr The last address in the address space.
+ * @param pszNameFmt The name format of the address space.
+ * @param va Format arguments.
+ */
+RTDECL(int) RTDbgAsCreateV(PRTDBGAS phDbgAs, RTUINTPTR FirstAddr, RTUINTPTR LastAddr,
+ const char *pszNameFmt, va_list va) RT_IPRT_FORMAT_ATTR(4, 0);
+
+/**
+ * Variant of RTDbgAsCreate that takes a name format string.
+ *
+ * @returns IPRT status code.
+ *
+ * @param phDbgAs Where to store the address space handle on success.
+ * @param FirstAddr The first address in the address space.
+ * @param LastAddr The last address in the address space.
+ * @param pszNameFmt The name format of the address space.
+ * @param ... Format arguments.
+ */
+RTDECL(int) RTDbgAsCreateF(PRTDBGAS phDbgAs, RTUINTPTR FirstAddr, RTUINTPTR LastAddr,
+ const char *pszNameFmt, ...) RT_IPRT_FORMAT_ATTR(4, 5);
+
+/**
+ * Retains a reference to the address space.
+ *
+ * @returns New reference count, UINT32_MAX on invalid handle (asserted).
+ *
+ * @param hDbgAs The address space handle.
+ *
+ * @remarks Will not take any locks.
+ */
+RTDECL(uint32_t) RTDbgAsRetain(RTDBGAS hDbgAs);
+
+/**
+ * Release a reference to the address space.
+ *
+ * When the reference count reaches zero, the address space is destroyed.
+ * That means unlinking all the modules it currently contains, potentially
+ * causing some or all of them to be destroyed as they are managed by
+ * reference counting.
+ *
+ * @returns New reference count, UINT32_MAX on invalid handle (asserted).
+ *
+ * @param hDbgAs The address space handle. The NIL handle is quietly
+ * ignored and 0 is returned.
+ *
+ * @remarks Will not take any locks.
+ */
+RTDECL(uint32_t) RTDbgAsRelease(RTDBGAS hDbgAs);
+
+/**
+ * Locks the address space for exclusive access.
+ *
+ * @returns IRPT status code
+ * @param hDbgAs The address space handle.
+ */
+RTDECL(int) RTDbgAsLockExcl(RTDBGAS hDbgAs);
+
+/**
+ * Counters the actions of one RTDbgAsUnlockExcl call.
+ *
+ * @returns IRPT status code
+ * @param hDbgAs The address space handle.
+ */
+RTDECL(int) RTDbgAsUnlockExcl(RTDBGAS hDbgAs);
+
+/**
+ * Gets the name of an address space.
+ *
+ * @returns read only address space name.
+ * NULL if hDbgAs is invalid.
+ *
+ * @param hDbgAs The address space handle.
+ *
+ * @remarks Will not take any locks.
+ */
+RTDECL(const char *) RTDbgAsName(RTDBGAS hDbgAs);
+
+/**
+ * Gets the first address in an address space.
+ *
+ * @returns The address.
+ * 0 if hDbgAs is invalid.
+ *
+ * @param hDbgAs The address space handle.
+ *
+ * @remarks Will not take any locks.
+ */
+RTDECL(RTUINTPTR) RTDbgAsFirstAddr(RTDBGAS hDbgAs);
+
+/**
+ * Gets the last address in an address space.
+ *
+ * @returns The address.
+ * 0 if hDbgAs is invalid.
+ *
+ * @param hDbgAs The address space handle.
+ *
+ * @remarks Will not take any locks.
+ */
+RTDECL(RTUINTPTR) RTDbgAsLastAddr(RTDBGAS hDbgAs);
+
+/**
+ * Gets the number of modules in the address space.
+ *
+ * This can be used together with RTDbgAsModuleByIndex
+ * to enumerate the modules.
+ *
+ * @returns The number of modules.
+ *
+ * @param hDbgAs The address space handle.
+ *
+ * @remarks Will not take any locks.
+ */
+RTDECL(uint32_t) RTDbgAsModuleCount(RTDBGAS hDbgAs);
+
+/** @name Flags for RTDbgAsModuleLink and RTDbgAsModuleLinkSeg
+ * @{ */
+/** Replace all conflicting module.
+ * (The conflicting modules will be removed the address space and their
+ * references released.) */
+#define RTDBGASLINK_FLAGS_REPLACE RT_BIT_32(0)
+/** Mask containing the valid flags. */
+#define RTDBGASLINK_FLAGS_VALID_MASK UINT32_C(0x00000001)
+/** @} */
+
+/**
+ * Links a module into the address space at the give address.
+ *
+ * The size of the mapping is determined using RTDbgModImageSize().
+ *
+ * @returns IPRT status code.
+ * @retval VERR_OUT_OF_RANGE if the specified address will put the module
+ * outside the address space.
+ * @retval VERR_ADDRESS_CONFLICT if the mapping clashes with existing mappings.
+ *
+ * @param hDbgAs The address space handle.
+ * @param hDbgMod The module handle of the module to be linked in.
+ * @param ImageAddr The address to link the module at.
+ * @param fFlags See RTDBGASLINK_FLAGS_*.
+ */
+RTDECL(int) RTDbgAsModuleLink(RTDBGAS hDbgAs, RTDBGMOD hDbgMod, RTUINTPTR ImageAddr, uint32_t fFlags);
+
+/**
+ * Links a segment into the address space at the give address.
+ *
+ * The size of the mapping is determined using RTDbgModSegmentSize().
+ *
+ * @returns IPRT status code.
+ * @retval VERR_OUT_OF_RANGE if the specified address will put the module
+ * outside the address space.
+ * @retval VERR_ADDRESS_CONFLICT if the mapping clashes with existing mappings.
+ *
+ * @param hDbgAs The address space handle.
+ * @param hDbgMod The module handle.
+ * @param iSeg The segment number (0-based) of the segment to be
+ * linked in.
+ * @param SegAddr The address to link the segment at.
+ * @param fFlags See RTDBGASLINK_FLAGS_*.
+ */
+RTDECL(int) RTDbgAsModuleLinkSeg(RTDBGAS hDbgAs, RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg, RTUINTPTR SegAddr, uint32_t fFlags);
+
+/**
+ * Unlinks all the mappings of a module from the address space.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_NOT_FOUND if the module wasn't found.
+ *
+ * @param hDbgAs The address space handle.
+ * @param hDbgMod The module handle of the module to be unlinked.
+ */
+RTDECL(int) RTDbgAsModuleUnlink(RTDBGAS hDbgAs, RTDBGMOD hDbgMod);
+
+/**
+ * Unlinks the mapping at the specified address.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_NOT_FOUND if no module or segment is mapped at that address.
+ *
+ * @param hDbgAs The address space handle.
+ * @param Addr The address within the mapping to be unlinked.
+ */
+RTDECL(int) RTDbgAsModuleUnlinkByAddr(RTDBGAS hDbgAs, RTUINTPTR Addr);
+
+/**
+ * Get a the handle of a module in the address space by is index.
+ *
+ * @returns A retained handle to the specified module. The caller must release
+ * the returned reference.
+ * NIL_RTDBGMOD if invalid index or handle.
+ *
+ * @param hDbgAs The address space handle.
+ * @param iModule The index of the module to get.
+ *
+ * @remarks The module indexes may change after calls to RTDbgAsModuleLink,
+ * RTDbgAsModuleLinkSeg, RTDbgAsModuleUnlink and
+ * RTDbgAsModuleUnlinkByAddr.
+ */
+RTDECL(RTDBGMOD) RTDbgAsModuleByIndex(RTDBGAS hDbgAs, uint32_t iModule);
+
+/**
+ * Queries mapping module information by handle.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_NOT_FOUND if no mapping was found at the specified address.
+ *
+ * @param hDbgAs The address space handle.
+ * @param Addr Address within the mapping of the module or segment.
+ * @param phMod Where to the return the retained module handle.
+ * Optional.
+ * @param pAddr Where to return the base address of the mapping.
+ * Optional.
+ * @param piSeg Where to return the segment index. This is set to
+ * NIL if the entire module is mapped as a single
+ * mapping. Optional.
+ */
+RTDECL(int) RTDbgAsModuleByAddr(RTDBGAS hDbgAs, RTUINTPTR Addr, PRTDBGMOD phMod, PRTUINTPTR pAddr, PRTDBGSEGIDX piSeg);
+
+/**
+ * Queries mapping module information by name.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_NOT_FOUND if no mapping was found at the specified address.
+ * @retval VERR_OUT_OF_RANGE if the name index was out of range.
+ *
+ * @param hDbgAs The address space handle.
+ * @param pszName The module name.
+ * @param iName There can be more than one module by the same name
+ * in an address space. This argument indicates which
+ * is meant. (0 based)
+ * @param phMod Where to the return the retained module handle.
+ */
+RTDECL(int) RTDbgAsModuleByName(RTDBGAS hDbgAs, const char *pszName, uint32_t iName, PRTDBGMOD phMod);
+
+/**
+ * Information about a mapping.
+ *
+ * This is used by RTDbgAsModuleGetMapByIndex.
+ */
+typedef struct RTDBGASMAPINFO
+{
+ /** The mapping address. */
+ RTUINTPTR Address;
+ /** The segment mapped there.
+ * This is NIL_RTDBGSEGIDX if the entire module image is mapped here. */
+ RTDBGSEGIDX iSeg;
+} RTDBGASMAPINFO;
+/** Pointer to info about an address space mapping. */
+typedef RTDBGASMAPINFO *PRTDBGASMAPINFO;
+/** Pointer to const info about an address space mapping. */
+typedef RTDBGASMAPINFO const *PCRTDBGASMAPINFO;
+
+/**
+ * Queries mapping information for a module given by index.
+ *
+ * @returns IRPT status code.
+ * @retval VERR_INVALID_HANDLE if hDbgAs is invalid.
+ * @retval VERR_OUT_OF_RANGE if the name index was out of range.
+ * @retval VINF_BUFFER_OVERFLOW if the array is too small and the returned
+ * information is incomplete.
+ *
+ * @param hDbgAs The address space handle.
+ * @param iModule The index of the module to get.
+ * @param paMappings Where to return the mapping information. The buffer
+ * size is given by *pcMappings.
+ * @param pcMappings IN: Size of the paMappings array. OUT: The number of
+ * entries returned.
+ * @param fFlags Flags for reserved for future use. MBZ.
+ *
+ * @remarks See remarks for RTDbgAsModuleByIndex regarding the volatility of the
+ * iModule parameter.
+ */
+RTDECL(int) RTDbgAsModuleQueryMapByIndex(RTDBGAS hDbgAs, uint32_t iModule, PRTDBGASMAPINFO paMappings, uint32_t *pcMappings, uint32_t fFlags);
+
+/**
+ * Adds a symbol to a module in the address space.
+ *
+ * @returns IPRT status code. See RTDbgModSymbolAdd for more specific ones.
+ * @retval VERR_INVALID_HANDLE if hDbgAs is invalid.
+ * @retval VERR_NOT_FOUND if no module was found at the specified address.
+ * @retval VERR_NOT_SUPPORTED if the module interpret doesn't support adding
+ * custom symbols.
+ *
+ * @param hDbgAs The address space handle.
+ * @param pszSymbol The symbol name.
+ * @param Addr The address of the symbol.
+ * @param cb The size of the symbol.
+ * @param fFlags Symbol flags, RTDBGSYMBOLADD_F_XXX.
+ * @param piOrdinal Where to return the symbol ordinal on success. If
+ * the interpreter doesn't do ordinals, this will be set to
+ * UINT32_MAX. Optional
+ */
+RTDECL(int) RTDbgAsSymbolAdd(RTDBGAS hDbgAs, const char *pszSymbol, RTUINTPTR Addr, RTUINTPTR cb, uint32_t fFlags, uint32_t *piOrdinal);
+
+/**
+ * Query a symbol by address.
+ *
+ * @returns IPRT status code. See RTDbgModSymbolAddr for more specific ones.
+ * @retval VERR_INVALID_HANDLE if hDbgAs is invalid.
+ * @retval VERR_NOT_FOUND if the address couldn't be mapped to a module.
+ * @retval VERR_INVALID_PARAMETER if incorrect flags.
+ *
+ * @param hDbgAs The address space handle.
+ * @param Addr The address which closest symbol is requested.
+ * @param fFlags Symbol search flags, see RTDBGSYMADDR_FLAGS_XXX.
+ * @param poffDisp Where to return the distance between the symbol
+ * and address. Optional.
+ * @param pSymbol Where to return the symbol info.
+ * @param phMod Where to return the module handle. Optional.
+ */
+RTDECL(int) RTDbgAsSymbolByAddr(RTDBGAS hDbgAs, RTUINTPTR Addr, uint32_t fFlags,
+ PRTINTPTR poffDisp, PRTDBGSYMBOL pSymbol, PRTDBGMOD phMod);
+
+/**
+ * Query a symbol by address.
+ *
+ * @returns IPRT status code. See RTDbgModSymbolAddrA for more specific ones.
+ * @retval VERR_INVALID_HANDLE if hDbgAs is invalid.
+ * @retval VERR_NOT_FOUND if the address couldn't be mapped to a module.
+ * @retval VERR_INVALID_PARAMETER if incorrect flags.
+ *
+ * @param hDbgAs The address space handle.
+ * @param Addr The address which closest symbol is requested.
+ * @param fFlags Symbol search flags, see RTDBGSYMADDR_FLAGS_XXX.
+ * @param poffDisp Where to return the distance between the symbol
+ * and address. Optional.
+ * @param ppSymInfo Where to return the pointer to the allocated symbol
+ * info. Always set. Free with RTDbgSymbolFree.
+ * @param phMod Where to return the module handle. Optional.
+ */
+RTDECL(int) RTDbgAsSymbolByAddrA(RTDBGAS hDbgAs, RTUINTPTR Addr, uint32_t fFlags,
+ PRTINTPTR poffDisp, PRTDBGSYMBOL *ppSymInfo, PRTDBGMOD phMod);
+
+/**
+ * Query a symbol by name.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_SYMBOL_NOT_FOUND if not found.
+ *
+ * @param hDbgAs The address space handle.
+ * @param pszSymbol The symbol name. It is possible to limit the scope
+ * of the search by prefixing the symbol with a module
+ * name pattern followed by a bang (!) character.
+ * RTStrSimplePatternNMatch is used for the matching.
+ * @param pSymbol Where to return the symbol info.
+ * @param phMod Where to return the module handle. Optional.
+ */
+RTDECL(int) RTDbgAsSymbolByName(RTDBGAS hDbgAs, const char *pszSymbol, PRTDBGSYMBOL pSymbol, PRTDBGMOD phMod);
+
+/**
+ * Query a symbol by name, allocating the returned symbol structure.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_SYMBOL_NOT_FOUND if not found.
+ *
+ * @param hDbgAs The address space handle.
+ * @param pszSymbol The symbol name. See RTDbgAsSymbolByName for more.
+ * @param ppSymbol Where to return the pointer to the allocated
+ * symbol info. Always set. Free with RTDbgSymbolFree.
+ * @param phMod Where to return the module handle. Optional.
+ */
+RTDECL(int) RTDbgAsSymbolByNameA(RTDBGAS hDbgAs, const char *pszSymbol, PRTDBGSYMBOL *ppSymbol, PRTDBGMOD phMod);
+
+/**
+ * Adds a line number to a module in the address space.
+ *
+ * @returns IPRT status code. See RTDbgModLineAdd for more specific ones.
+ * @retval VERR_INVALID_HANDLE if hDbgAs is invalid.
+ * @retval VERR_NOT_FOUND if no module was found at the specified address.
+ * @retval VERR_NOT_SUPPORTED if the module interpret doesn't support adding
+ * custom symbols.
+ *
+ * @param hDbgAs The address space handle.
+ * @param pszFile The file name.
+ * @param uLineNo The line number.
+ * @param Addr The address of the symbol.
+ * @param piOrdinal Where to return the line number ordinal on success.
+ * If the interpreter doesn't do ordinals, this will be
+ * set to UINT32_MAX. Optional.
+ */
+RTDECL(int) RTDbgAsLineAdd(RTDBGAS hDbgAs, const char *pszFile, uint32_t uLineNo, RTUINTPTR Addr, uint32_t *piOrdinal);
+
+/**
+ * Query a line number by address.
+ *
+ * @returns IPRT status code. See RTDbgModLineAddrA for more specific ones.
+ * @retval VERR_INVALID_HANDLE if hDbgAs is invalid.
+ * @retval VERR_NOT_FOUND if the address couldn't be mapped to a module.
+ *
+ * @param hDbgAs The address space handle.
+ * @param Addr The address which closest symbol is requested.
+ * @param poffDisp Where to return the distance between the line
+ * number and address.
+ * @param pLine Where to return the line number information.
+ * @param phMod Where to return the module handle. Optional.
+ */
+RTDECL(int) RTDbgAsLineByAddr(RTDBGAS hDbgAs, RTUINTPTR Addr, PRTINTPTR poffDisp, PRTDBGLINE pLine, PRTDBGMOD phMod);
+
+/**
+ * Query a line number by address.
+ *
+ * @returns IPRT status code. See RTDbgModLineAddrA for more specific ones.
+ * @retval VERR_INVALID_HANDLE if hDbgAs is invalid.
+ * @retval VERR_NOT_FOUND if the address couldn't be mapped to a module.
+ *
+ * @param hDbgAs The address space handle.
+ * @param Addr The address which closest symbol is requested.
+ * @param poffDisp Where to return the distance between the line
+ * number and address.
+ * @param ppLine Where to return the pointer to the allocated line
+ * number info. Always set. Free with RTDbgLineFree.
+ * @param phMod Where to return the module handle. Optional.
+ */
+RTDECL(int) RTDbgAsLineByAddrA(RTDBGAS hDbgAs, RTUINTPTR Addr, PRTINTPTR poffDisp, PRTDBGLINE *ppLine, PRTDBGMOD phMod);
+
+/** @todo Missing some bits here. */
+
+/** @} */
+
+
+# ifdef IN_RING3
+/** @defgroup grp_rt_dbgmod RTDbgMod - Debug Module Interpreter
+ * @{
+ */
+
+/**
+ * Creates a module based on the default debug info container.
+ *
+ * This can be used to manually load a module and its symbol. The primary user
+ * group is the debug info interpreters, which use this API to create an
+ * efficient debug info container behind the scenes and forward all queries to
+ * it once the info has been loaded.
+ *
+ * @returns IPRT status code.
+ *
+ * @param phDbgMod Where to return the module handle.
+ * @param pszName The name of the module (mandatory).
+ * @param cbSeg The size of initial segment. If zero, segments will
+ * have to be added manually using RTDbgModSegmentAdd.
+ * @param fFlags Flags reserved for future extensions, MBZ for now.
+ */
+RTDECL(int) RTDbgModCreate(PRTDBGMOD phDbgMod, const char *pszName, RTUINTPTR cbSeg, uint32_t fFlags);
+
+RTDECL(int) RTDbgModCreateFromImage(PRTDBGMOD phDbgMod, const char *pszFilename, const char *pszName,
+ RTLDRARCH enmArch, RTDBGCFG hDbgCfg);
+RTDECL(int) RTDbgModCreateFromMap(PRTDBGMOD phDbgMod, const char *pszFilename, const char *pszName, RTUINTPTR uSubtrahend,
+ RTDBGCFG hDbgCfg);
+RTDECL(int) RTDbgModCreateFromPeImage(PRTDBGMOD phDbgMod, const char *pszFilename, const char *pszName,
+ PRTLDRMOD phLdrMod, uint32_t cbImage, uint32_t uTimeDateStamp, RTDBGCFG hDbgCfg);
+RTDECL(int) RTDbgModCreateFromDbg(PRTDBGMOD phDbgMod, const char *pszFilename, const char *pszName, uint32_t cbImage,
+ uint32_t uTimeDateStamp, RTDBGCFG hDbgCfg);
+RTDECL(int) RTDbgModCreateFromPdb(PRTDBGMOD phDbgMod, const char *pszFilename, const char *pszName, uint32_t cbImage,
+ PCRTUUID pUuid, uint32_t Age, RTDBGCFG hDbgCfg);
+RTDECL(int) RTDbgModCreateFromDwo(PRTDBGMOD phDbgMod, const char *pszFilename, const char *pszName, uint32_t cbImage,
+ uint32_t uCrc32, RTDBGCFG hDbgCfg);
+RTDECL(int) RTDbgModCreateFromMachOImage(PRTDBGMOD phDbgMod, const char *pszFilename, const char *pszName,
+ RTLDRARCH enmArch, PRTLDRMOD phLdrModIn, uint32_t cbImage, uint32_t cSegs,
+ PCRTDBGSEGMENT paSegs, PCRTUUID pUuid, RTDBGCFG hDbgCfg, uint32_t fFlags);
+
+/** @name Flags for RTDbgModCreate and friends.
+ * @{ */
+/** Overrides the hDbgCfg settings and forces an image and/or symbol file
+ * search. RTDbgModCreate will quietly ignore this flag. */
+#define RTDBGMOD_F_NOT_DEFERRED RT_BIT_32(0)
+/** Mach-O: Load the __LINKEDIT segment (@sa RTLDR_O_MACHO_LOAD_LINKEDIT). */
+#define RTDBGMOD_F_MACHO_LOAD_LINKEDIT RT_BIT_32(1)
+/** Valid flag mask. */
+#define RTDBGMOD_F_VALID_MASK UINT32_C(0x00000003)
+/** @} */
+
+
+/**
+ * Retains another reference to the module.
+ *
+ * @returns New reference count, UINT32_MAX on invalid handle (asserted).
+ *
+ * @param hDbgMod The module handle.
+ *
+ * @remarks Will not take any locks.
+ */
+RTDECL(uint32_t) RTDbgModRetain(RTDBGMOD hDbgMod);
+
+/**
+ * Release a reference to the module.
+ *
+ * When the reference count reaches zero, the module is destroyed.
+ *
+ * @returns New reference count, UINT32_MAX on invalid handle (asserted).
+ *
+ * @param hDbgMod The module handle. The NIL handle is quietly ignored
+ * and 0 is returned.
+ *
+ * @remarks Will not take any locks.
+ */
+RTDECL(uint32_t) RTDbgModRelease(RTDBGMOD hDbgMod);
+
+/**
+ * Removes all content from the debug module (container), optionally only
+ * leaving segments and image size intact.
+ *
+ * This is only possible on container modules, i.e. created by RTDbgModCreate().
+ *
+ * @returns IPRT status code.
+ * @param hDbgMod The module handle.
+ * @param fLeaveSegments Whether to leave segments (and image size) as is.
+ */
+RTDECL(int) RTDbgModRemoveAll(RTDBGMOD hDbgMod, bool fLeaveSegments);
+
+/**
+ * Gets the module name.
+ *
+ * @returns Pointer to a read only string containing the name.
+ *
+ * @param hDbgMod The module handle.
+ */
+RTDECL(const char *) RTDbgModName(RTDBGMOD hDbgMod);
+
+/**
+ * Gets the name of the debug info file we're using.
+ *
+ * @returns Pointer to a read only string containing the filename, NULL if we
+ * don't use one.
+ *
+ * @param hDbgMod The module handle.
+ */
+RTDECL(const char *) RTDbgModDebugFile(RTDBGMOD hDbgMod);
+
+/**
+ * Gets the image filename (as specified by the user).
+ *
+ * @returns Pointer to a read only string containing the filename.
+ *
+ * @param hDbgMod The module handle.
+ */
+RTDECL(const char *) RTDbgModImageFile(RTDBGMOD hDbgMod);
+
+/**
+ * Gets the image filename actually used if it differs from RTDbgModImageFile.
+ *
+ * @returns Pointer to a read only string containing the filename, NULL if same
+ * as RTDBgModImageFile.
+ *
+ * @param hDbgMod The module handle.
+ */
+RTDECL(const char *) RTDbgModImageFileUsed(RTDBGMOD hDbgMod);
+
+/**
+ * Checks if the loading of the debug info has been postponed.
+ *
+ * @returns true if postponed, false if not or invalid handle.
+ * @param hDbgMod The module handle.
+ */
+RTDECL(bool) RTDbgModIsDeferred(RTDBGMOD hDbgMod);
+
+/**
+ * Checks if the debug info is exports only.
+ *
+ * @returns true if exports only, false if not or invalid handle.
+ * @param hDbgMod The module handle.
+ */
+RTDECL(bool) RTDbgModIsExports(RTDBGMOD hDbgMod);
+
+/**
+ * Converts an image relative address to a segment:offset address.
+ *
+ * @returns Segment index on success.
+ * NIL_RTDBGSEGIDX is returned if the module handle or the RVA are
+ * invalid.
+ *
+ * @param hDbgMod The module handle.
+ * @param uRva The image relative address to convert.
+ * @param poffSeg Where to return the segment offset. Optional.
+ */
+RTDECL(RTDBGSEGIDX) RTDbgModRvaToSegOff(RTDBGMOD hDbgMod, RTUINTPTR uRva, PRTUINTPTR poffSeg);
+
+/**
+ * Gets the module tag value if any.
+ *
+ * @returns The tag. 0 if hDbgMod is invalid.
+ *
+ * @param hDbgMod The module handle.
+ */
+RTDECL(uint64_t) RTDbgModGetTag(RTDBGMOD hDbgMod);
+
+/**
+ * Tags or untags the module.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_INVALID_HANDLE if hDbgMod is invalid.
+ *
+ * @param hDbgMod The module handle.
+ * @param uTag The tag value. The convention is that 0 is no tag
+ * and any other value means it's tagged. It's adviced
+ * to use some kind of unique number like an address
+ * (global or string cache for instance) to avoid
+ * collisions with other users
+ */
+RTDECL(int) RTDbgModSetTag(RTDBGMOD hDbgMod, uint64_t uTag);
+
+
+/**
+ * Image size when mapped if segments are mapped adjacently.
+ *
+ * For ELF, PE, and Mach-O images this is (usually) a natural query, for LX and
+ * NE and such it's a bit odder and the answer may not make much sense for them.
+ *
+ * @returns Image mapped size.
+ * RTUINTPTR_MAX is returned if the handle is invalid.
+ *
+ * @param hDbgMod The module handle.
+ */
+RTDECL(RTUINTPTR) RTDbgModImageSize(RTDBGMOD hDbgMod);
+
+/**
+ * Gets the image format.
+ *
+ * @returns Image format.
+ * @retval RTLDRFMT_INVALID if the handle is invalid or if the format isn't known.
+ * @param hDbgMod The debug module handle.
+ * @sa RTLdrGetFormat
+ */
+RTDECL(RTLDRFMT) RTDbgModImageGetFormat(RTDBGMOD hDbgMod);
+
+/**
+ * Gets the image architecture.
+ *
+ * @returns Image architecture.
+ * @retval RTLDRARCH_INVALID if the handle is invalid.
+ * @retval RTLDRARCH_WHATEVER if unknown.
+ * @param hDbgMod The debug module handle.
+ * @sa RTLdrGetArch
+ */
+RTDECL(RTLDRARCH) RTDbgModImageGetArch(RTDBGMOD hDbgMod);
+
+/**
+ * Generic method for querying image properties.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_NOT_SUPPORTED if the property query isn't supported (either all
+ * or that specific property). The caller must handle this result.
+ * @retval VERR_NOT_FOUND the property was not found in the module. The caller
+ * must also normally deal with this.
+ * @retval VERR_INVALID_FUNCTION if the function value is wrong.
+ * @retval VERR_INVALID_PARAMETER if the fixed buffer size is wrong. Correct
+ * size in @a *pcbRet.
+ * @retval VERR_BUFFER_OVERFLOW if the function doesn't have a fixed size
+ * buffer and the buffer isn't big enough. Correct size in @a *pcbRet.
+ * @retval VERR_INVALID_HANDLE if the handle is invalid.
+ *
+ * @param hDbgMod The debug module handle.
+ * @param enmProp The property to query.
+ * @param pvBuf Pointer to the input / output buffer. In most cases
+ * it's only used for returning data.
+ * @param cbBuf The size of the buffer.
+ * @param pcbRet Where to return the amount of data returned. On
+ * buffer size errors, this is set to the correct size.
+ * Optional.
+ * @sa RTLdrQueryPropEx
+ */
+RTDECL(int) RTDbgModImageQueryProp(RTDBGMOD hDbgMod, RTLDRPROP enmProp, void *pvBuf, size_t cbBuf, size_t *pcbRet);
+
+
+/**
+ * Adds a segment to the module. Optional feature.
+ *
+ * This method is intended used for manually constructing debug info for a
+ * module. The main usage is from other debug info interpreters that want to
+ * avoid writing a debug info database and instead uses the standard container
+ * behind the scenes.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_NOT_SUPPORTED if this feature isn't support by the debug info
+ * interpreter. This is a common return code.
+ * @retval VERR_INVALID_HANDLE if hDbgMod is invalid.
+ * @retval VERR_DBG_ADDRESS_WRAP if uRva+cb wraps around.
+ * @retval VERR_DBG_SEGMENT_NAME_OUT_OF_RANGE if pszName is too short or long.
+ * @retval VERR_INVALID_PARAMETER if fFlags contains undefined flags.
+ * @retval VERR_DBG_SPECIAL_SEGMENT if *piSeg is a special segment.
+ * @retval VERR_DBG_INVALID_SEGMENT_INDEX if *piSeg doesn't meet expectations.
+ *
+ * @param hDbgMod The module handle.
+ * @param uRva The image relative address of the segment.
+ * @param cb The size of the segment.
+ * @param pszName The segment name. Does not normally need to be
+ * unique, although this is somewhat up to the
+ * debug interpreter to decide.
+ * @param fFlags Segment flags. Reserved for future used, MBZ.
+ * @param piSeg The segment index or NIL_RTDBGSEGIDX on input.
+ * The assigned segment index on successful return.
+ * Optional.
+ */
+RTDECL(int) RTDbgModSegmentAdd(RTDBGMOD hDbgMod, RTUINTPTR uRva, RTUINTPTR cb, const char *pszName,
+ uint32_t fFlags, PRTDBGSEGIDX piSeg);
+
+/**
+ * Gets the number of segments in the module.
+ *
+ * This is can be used to determine the range which can be passed to
+ * RTDbgModSegmentByIndex and derivates.
+ *
+ * @returns The segment relative address.
+ * NIL_RTDBGSEGIDX if the handle is invalid.
+ *
+ * @param hDbgMod The module handle.
+ */
+RTDECL(RTDBGSEGIDX) RTDbgModSegmentCount(RTDBGMOD hDbgMod);
+
+/**
+ * Query information about a segment.
+ *
+ * This can be used together with RTDbgModSegmentCount to enumerate segments.
+ * The index starts a 0 and stops one below RTDbgModSegmentCount.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_DBG_INVALID_SEGMENT_INDEX if iSeg is too high.
+ * @retval VERR_DBG_SPECIAL_SEGMENT if iSeg indicates a special segment.
+ * @retval VERR_INVALID_HANDLE if hDbgMod is invalid.
+ *
+ * @param hDbgMod The module handle.
+ * @param iSeg The segment index. No special segments.
+ * @param pSegInfo Where to return the segment info. The
+ * RTDBGSEGMENT::Address member will be set to
+ * RTUINTPTR_MAX or the load address used at link time.
+ */
+RTDECL(int) RTDbgModSegmentByIndex(RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg, PRTDBGSEGMENT pSegInfo);
+
+/**
+ * Gets the size of a segment.
+ *
+ * This is a just a wrapper around RTDbgModSegmentByIndex.
+ *
+ * @returns The segment size.
+ * RTUINTPTR_MAX is returned if either the handle and segment index are
+ * invalid.
+ *
+ * @param hDbgMod The module handle.
+ * @param iSeg The segment index. RTDBGSEGIDX_ABS is not allowed.
+ * If RTDBGSEGIDX_RVA is used, the functions returns
+ * the same value as RTDbgModImageSize.
+ */
+RTDECL(RTUINTPTR) RTDbgModSegmentSize(RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg);
+
+/**
+ * Gets the image relative address of a segment.
+ *
+ * This is a just a wrapper around RTDbgModSegmentByIndex.
+ *
+ * @returns The segment relative address.
+ * RTUINTPTR_MAX is returned if either the handle and segment index are
+ * invalid.
+ *
+ * @param hDbgMod The module handle.
+ * @param iSeg The segment index. No special segment indexes
+ * allowed (asserted).
+ */
+RTDECL(RTUINTPTR) RTDbgModSegmentRva(RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg);
+
+
+/**
+ * Adds a line number to the module.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_NOT_SUPPORTED if the module interpret doesn't support adding
+ * custom symbols. This is a common place occurrence.
+ * @retval VERR_INVALID_HANDLE if hDbgMod is invalid.
+ * @retval VERR_DBG_SYMBOL_NAME_OUT_OF_RANGE if the symbol name is too long or
+ * short.
+ * @retval VERR_DBG_INVALID_RVA if an image relative address is specified and
+ * it's not inside any of the segments defined by the module.
+ * @retval VERR_DBG_INVALID_SEGMENT_INDEX if the segment index isn't valid.
+ * @retval VERR_DBG_INVALID_SEGMENT_OFFSET if the segment offset is beyond the
+ * end of the segment.
+ * @retval VERR_DBG_ADDRESS_WRAP if off+cb wraps around.
+ * @retval VERR_INVALID_PARAMETER if the symbol flags sets undefined bits.
+ * @retval VERR_DBG_DUPLICATE_SYMBOL
+ * @retval VERR_DBG_ADDRESS_CONFLICT
+ *
+ * @param hDbgMod The module handle.
+ * @param pszSymbol The symbol name.
+ * @param iSeg The segment index.
+ * @param off The segment offset.
+ * @param cb The size of the symbol. Can be zero, although this
+ * may depend somewhat on the debug interpreter.
+ * @param fFlags Symbol flags, RTDBGSYMBOLADD_F_XXX.
+ * @param piOrdinal Where to return the symbol ordinal on success. If
+ * the interpreter doesn't do ordinals, this will be set to
+ * UINT32_MAX. Optional.
+ */
+RTDECL(int) RTDbgModSymbolAdd(RTDBGMOD hDbgMod, const char *pszSymbol, RTDBGSEGIDX iSeg, RTUINTPTR off,
+ RTUINTPTR cb, uint32_t fFlags, uint32_t *piOrdinal);
+
+/**
+ * Gets the symbol count.
+ *
+ * This can be used together wtih RTDbgModSymbolByOrdinal or
+ * RTDbgModSymbolByOrdinalA to enumerate all the symbols.
+ *
+ * @returns The number of symbols in the module.
+ * UINT32_MAX is returned if the module handle is invalid or some other
+ * error occurs.
+ *
+ * @param hDbgMod The module handle.
+ */
+RTDECL(uint32_t) RTDbgModSymbolCount(RTDBGMOD hDbgMod);
+
+/**
+ * Queries symbol information by ordinal number.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_SYMBOL_NOT_FOUND if there is no symbol at the given number.
+ * @retval VERR_DBG_NO_SYMBOLS if there aren't any symbols.
+ * @retval VERR_INVALID_HANDLE if hDbgMod is invalid.
+ * @retval VERR_NOT_SUPPORTED if lookup by ordinal is not supported.
+ *
+ * @param hDbgMod The module handle.
+ * @param iOrdinal The symbol ordinal number. 0-based. The highest
+ * number is RTDbgModSymbolCount() - 1.
+ * @param pSymInfo Where to store the symbol information.
+ */
+RTDECL(int) RTDbgModSymbolByOrdinal(RTDBGMOD hDbgMod, uint32_t iOrdinal, PRTDBGSYMBOL pSymInfo);
+
+/**
+ * Queries symbol information by ordinal number.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_DBG_NO_SYMBOLS if there aren't any symbols.
+ * @retval VERR_NOT_SUPPORTED if lookup by ordinal is not supported.
+ * @retval VERR_SYMBOL_NOT_FOUND if there is no symbol at the given number.
+ * @retval VERR_NO_MEMORY if RTDbgSymbolAlloc fails.
+ *
+ * @param hDbgMod The module handle.
+ * @param iOrdinal The symbol ordinal number. 0-based. The highest
+ * number is RTDbgModSymbolCount() - 1.
+ * @param ppSymInfo Where to store the pointer to the returned
+ * symbol information. Always set. Free with
+ * RTDbgSymbolFree.
+ */
+RTDECL(int) RTDbgModSymbolByOrdinalA(RTDBGMOD hDbgMod, uint32_t iOrdinal, PRTDBGSYMBOL *ppSymInfo);
+
+/**
+ * Queries symbol information by address.
+ *
+ * The returned symbol is what the debug info interpreter considers the symbol
+ * most applicable to the specified address. This usually means a symbol with an
+ * address equal or lower than the requested.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_SYMBOL_NOT_FOUND if no suitable symbol was found.
+ * @retval VERR_DBG_NO_SYMBOLS if there aren't any symbols.
+ * @retval VERR_INVALID_HANDLE if hDbgMod is invalid.
+ * @retval VERR_DBG_INVALID_RVA if an image relative address is specified and
+ * it's not inside any of the segments defined by the module.
+ * @retval VERR_DBG_INVALID_SEGMENT_INDEX if the segment index isn't valid.
+ * @retval VERR_DBG_INVALID_SEGMENT_OFFSET if the segment offset is beyond the
+ * end of the segment.
+ * @retval VERR_INVALID_PARAMETER if incorrect flags.
+ *
+ * @param hDbgMod The module handle.
+ * @param iSeg The segment number.
+ * @param off The offset into the segment.
+ * @param fFlags Symbol search flags, see RTDBGSYMADDR_FLAGS_XXX.
+ * @param poffDisp Where to store the distance between the
+ * specified address and the returned symbol.
+ * Optional.
+ * @param pSymInfo Where to store the symbol information.
+ */
+RTDECL(int) RTDbgModSymbolByAddr(RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg, RTUINTPTR off, uint32_t fFlags,
+ PRTINTPTR poffDisp, PRTDBGSYMBOL pSymInfo);
+
+/**
+ * Queries symbol information by address.
+ *
+ * The returned symbol is what the debug info interpreter considers the symbol
+ * most applicable to the specified address. This usually means a symbol with an
+ * address equal or lower than the requested.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_SYMBOL_NOT_FOUND if no suitable symbol was found.
+ * @retval VERR_DBG_NO_SYMBOLS if there aren't any symbols.
+ * @retval VERR_INVALID_HANDLE if hDbgMod is invalid.
+ * @retval VERR_DBG_INVALID_RVA if an image relative address is specified and
+ * it's not inside any of the segments defined by the module.
+ * @retval VERR_DBG_INVALID_SEGMENT_INDEX if the segment index isn't valid.
+ * @retval VERR_DBG_INVALID_SEGMENT_OFFSET if the segment offset is beyond the
+ * end of the segment.
+ * @retval VERR_NO_MEMORY if RTDbgSymbolAlloc fails.
+ * @retval VERR_INVALID_PARAMETER if incorrect flags.
+ *
+ * @param hDbgMod The module handle.
+ * @param iSeg The segment index.
+ * @param off The offset into the segment.
+ * @param fFlags Symbol search flags, see RTDBGSYMADDR_FLAGS_XXX.
+ * @param poffDisp Where to store the distance between the
+ * specified address and the returned symbol. Optional.
+ * @param ppSymInfo Where to store the pointer to the returned
+ * symbol information. Always set. Free with
+ * RTDbgSymbolFree.
+ */
+RTDECL(int) RTDbgModSymbolByAddrA(RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg, RTUINTPTR off, uint32_t fFlags,
+ PRTINTPTR poffDisp, PRTDBGSYMBOL *ppSymInfo);
+
+/**
+ * Queries symbol information by symbol name.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_DBG_NO_SYMBOLS if there aren't any symbols.
+ * @retval VERR_SYMBOL_NOT_FOUND if no suitable symbol was found.
+ * @retval VERR_DBG_SYMBOL_NAME_OUT_OF_RANGE if the symbol name is too long or
+ * short.
+ *
+ * @param hDbgMod The module handle.
+ * @param pszSymbol The symbol name.
+ * @param pSymInfo Where to store the symbol information.
+ */
+RTDECL(int) RTDbgModSymbolByName(RTDBGMOD hDbgMod, const char *pszSymbol, PRTDBGSYMBOL pSymInfo);
+
+/**
+ * Queries symbol information by symbol name.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_DBG_NO_SYMBOLS if there aren't any symbols.
+ * @retval VERR_SYMBOL_NOT_FOUND if no suitable symbol was found.
+ * @retval VERR_DBG_SYMBOL_NAME_OUT_OF_RANGE if the symbol name is too long or
+ * short.
+ * @retval VERR_NO_MEMORY if RTDbgSymbolAlloc fails.
+ *
+ * @param hDbgMod The module handle.
+ * @param pszSymbol The symbol name.
+ * @param ppSymInfo Where to store the pointer to the returned
+ * symbol information. Always set. Free with
+ * RTDbgSymbolFree.
+ */
+RTDECL(int) RTDbgModSymbolByNameA(RTDBGMOD hDbgMod, const char *pszSymbol, PRTDBGSYMBOL *ppSymInfo);
+
+/**
+ * Adds a line number to the module.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_NOT_SUPPORTED if the module interpret doesn't support adding
+ * custom symbols. This should be consider a normal response.
+ * @retval VERR_INVALID_HANDLE if hDbgMod is invalid.
+ * @retval VERR_DBG_FILE_NAME_OUT_OF_RANGE if the file name is too longer or
+ * empty.
+ * @retval VERR_DBG_INVALID_RVA if an image relative address is specified and
+ * it's not inside any of the segments defined by the module.
+ * @retval VERR_DBG_INVALID_SEGMENT_INDEX if the segment index isn't valid.
+ * @retval VERR_DBG_INVALID_SEGMENT_OFFSET if the segment offset is beyond the
+ * end of the segment.
+ * @retval VERR_INVALID_PARAMETER if the line number flags sets undefined bits.
+ *
+ * @param hDbgMod The module handle.
+ * @param pszFile The file name.
+ * @param uLineNo The line number.
+ * @param iSeg The segment index.
+ * @param off The segment offset.
+ * @param piOrdinal Where to return the line number ordinal on
+ * success. If the interpreter doesn't do ordinals,
+ * this will be set to UINT32_MAX. Optional.
+ */
+RTDECL(int) RTDbgModLineAdd(RTDBGMOD hDbgMod, const char *pszFile, uint32_t uLineNo,
+ RTDBGSEGIDX iSeg, RTUINTPTR off, uint32_t *piOrdinal);
+
+/**
+ * Gets the line number count.
+ *
+ * This can be used together wtih RTDbgModLineByOrdinal or RTDbgModSymbolByLineA
+ * to enumerate all the line number information.
+ *
+ * @returns The number of line numbers in the module.
+ * UINT32_MAX is returned if the module handle is invalid or some other
+ * error occurs.
+ *
+ * @param hDbgMod The module handle.
+ */
+RTDECL(uint32_t) RTDbgModLineCount(RTDBGMOD hDbgMod);
+
+/**
+ * Queries line number information by ordinal number.
+ *
+ * This can be used to enumerate the line numbers for the module. Use
+ * RTDbgModLineCount() to figure the end of the ordinals.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_DBG_NO_LINE_NUMBERS if there aren't any line numbers.
+ * @retval VERR_DBG_LINE_NOT_FOUND if there is no line number with that
+ * ordinal.
+ * @retval VERR_INVALID_HANDLE if hDbgMod is invalid.
+
+ * @param hDbgMod The module handle.
+ * @param iOrdinal The line number ordinal number.
+ * @param pLineInfo Where to store the information about the line
+ * number.
+ */
+RTDECL(int) RTDbgModLineByOrdinal(RTDBGMOD hDbgMod, uint32_t iOrdinal, PRTDBGLINE pLineInfo);
+
+/**
+ * Queries line number information by ordinal number.
+ *
+ * This can be used to enumerate the line numbers for the module. Use
+ * RTDbgModLineCount() to figure the end of the ordinals.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_DBG_NO_LINE_NUMBERS if there aren't any line numbers.
+ * @retval VERR_DBG_LINE_NOT_FOUND if there is no line number with that
+ * ordinal.
+ * @retval VERR_INVALID_HANDLE if hDbgMod is invalid.
+ * @retval VERR_NO_MEMORY if RTDbgLineAlloc fails.
+ *
+ * @param hDbgMod The module handle.
+ * @param iOrdinal The line number ordinal number.
+ * @param ppLineInfo Where to store the pointer to the returned line
+ * number information. Always set. Free with
+ * RTDbgLineFree.
+ */
+RTDECL(int) RTDbgModLineByOrdinalA(RTDBGMOD hDbgMod, uint32_t iOrdinal, PRTDBGLINE *ppLineInfo);
+
+/**
+ * Queries line number information by address.
+ *
+ * The returned line number is what the debug info interpreter considers the
+ * one most applicable to the specified address. This usually means a line
+ * number with an address equal or lower than the requested.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_DBG_NO_LINE_NUMBERS if there aren't any line numbers.
+ * @retval VERR_DBG_LINE_NOT_FOUND if no suitable line number was found.
+ * @retval VERR_INVALID_HANDLE if hDbgMod is invalid.
+ * @retval VERR_DBG_INVALID_RVA if an image relative address is specified and
+ * it's not inside any of the segments defined by the module.
+ * @retval VERR_DBG_INVALID_SEGMENT_INDEX if the segment index isn't valid.
+ * @retval VERR_DBG_INVALID_SEGMENT_OFFSET if the segment offset is beyond the
+ * end of the segment.
+ *
+ * @param hDbgMod The module handle.
+ * @param iSeg The segment number.
+ * @param off The offset into the segment.
+ * @param poffDisp Where to store the distance between the
+ * specified address and the returned symbol.
+ * Optional.
+ * @param pLineInfo Where to store the line number information.
+ */
+RTDECL(int) RTDbgModLineByAddr(RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg, RTUINTPTR off, PRTINTPTR poffDisp, PRTDBGLINE pLineInfo);
+
+/**
+ * Queries line number information by address.
+ *
+ * The returned line number is what the debug info interpreter considers the
+ * one most applicable to the specified address. This usually means a line
+ * number with an address equal or lower than the requested.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_DBG_NO_LINE_NUMBERS if there aren't any line numbers.
+ * @retval VERR_DBG_LINE_NOT_FOUND if no suitable line number was found.
+ * @retval VERR_INVALID_HANDLE if hDbgMod is invalid.
+ * @retval VERR_DBG_INVALID_RVA if an image relative address is specified and
+ * it's not inside any of the segments defined by the module.
+ * @retval VERR_DBG_INVALID_SEGMENT_INDEX if the segment index isn't valid.
+ * @retval VERR_DBG_INVALID_SEGMENT_OFFSET if the segment offset is beyond the
+ * end of the segment.
+ * @retval VERR_NO_MEMORY if RTDbgLineAlloc fails.
+ *
+ * @param hDbgMod The module handle.
+ * @param iSeg The segment number.
+ * @param off The offset into the segment.
+ * @param poffDisp Where to store the distance between the
+ * specified address and the returned symbol.
+ * Optional.
+ * @param ppLineInfo Where to store the pointer to the returned line
+ * number information. Always set. Free with
+ * RTDbgLineFree.
+ */
+RTDECL(int) RTDbgModLineByAddrA(RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg, RTUINTPTR off, PRTINTPTR poffDisp, PRTDBGLINE *ppLineInfo);
+
+/**
+ * Try use unwind information to unwind one frame.
+ *
+ * @returns IPRT status code. Last informational status from stack reader callback.
+ * @retval VERR_DBG_NO_UNWIND_INFO if the module contains no unwind information.
+ * @retval VERR_DBG_UNWIND_INFO_NOT_FOUND if no unwind information was found
+ * for the location given by iSeg:off.
+ *
+ * @param hDbgMod The module handle.
+ * @param iSeg The segment number of the program counter.
+ * @param off The offset into @a iSeg. Together with @a iSeg
+ * this corresponds to the RTDBGUNWINDSTATE::uPc
+ * value pointed to by @a pState.
+ * @param pState The unwind state to work.
+ *
+ * @sa RTLdrUnwindFrame
+ */
+RTDECL(int) RTDbgModUnwindFrame(RTDBGMOD hDbgMod, RTDBGSEGIDX iSeg, RTUINTPTR off, PRTDBGUNWINDSTATE pState);
+
+/** @} */
+# endif /* IN_RING3 */
+
+
+
+/** @name Kernel Debug Info API
+ *
+ * This is a specialized API for obtaining symbols and structure information
+ * about the running kernel. It is relatively OS specific. Its purpose and
+ * operation is doesn't map all that well onto RTDbgMod, so a few dedicated
+ * functions was created for it.
+ *
+ * @{ */
+
+/** Handle to the kernel debug info. */
+typedef struct RTDBGKRNLINFOINT *RTDBGKRNLINFO;
+/** Pointer to a kernel debug info handle. */
+typedef RTDBGKRNLINFO *PRTDBGKRNLINFO;
+/** Nil kernel debug info handle. */
+#define NIL_RTDBGKRNLINFO ((RTDBGKRNLINFO)0)
+
+/**
+ * Opens the kernel debug info.
+ *
+ * @returns IPRT status code. Can fail for any number of reasons.
+ *
+ * @param phKrnlInfo Where to return the kernel debug info handle on
+ * success.
+ * @param fFlags Flags reserved for future use. Must be zero.
+ */
+RTR0DECL(int) RTR0DbgKrnlInfoOpen(PRTDBGKRNLINFO phKrnlInfo, uint32_t fFlags);
+
+/**
+ * Retains a reference to the kernel debug info handle.
+ *
+ * @returns New reference count, UINT32_MAX on invalid handle (asserted).
+ * @param hKrnlInfo The kernel info handle.
+ */
+RTR0DECL(uint32_t) RTR0DbgKrnlInfoRetain(RTDBGKRNLINFO hKrnlInfo);
+
+
+/**
+ * Releases a reference to the kernel debug info handle, destroying it when the
+ * counter reaches zero.
+ *
+ * @returns New reference count, UINT32_MAX on invalid handle (asserted).
+ * @param hKrnlInfo The kernel info handle. NIL_RTDBGKRNLINFO is
+ * quietly ignored.
+ */
+RTR0DECL(uint32_t) RTR0DbgKrnlInfoRelease(RTDBGKRNLINFO hKrnlInfo);
+
+/**
+ * Queries the offset (in bytes) of a member of a kernel structure.
+ *
+ * @returns IPRT status code.
+ * @retval VINF_SUCCESS and offset at @a poffMember.
+ * @retval VERR_NOT_FOUND if the structure or the member was not found.
+ * @retval VERR_INVALID_HANDLE if hKrnlInfo is bad.
+ * @retval VERR_INVALID_POINTER if any of the pointers are bad.
+ *
+ * @param hKrnlInfo The kernel info handle.
+ * @param pszModule The name of the module to search, pass NULL to
+ * search the default kernel module(s).
+ * @param pszStructure The structure name.
+ * @param pszMember The member name.
+ * @param poffMember Where to return the offset.
+ */
+RTR0DECL(int) RTR0DbgKrnlInfoQueryMember(RTDBGKRNLINFO hKrnlInfo, const char *pszModule, const char *pszStructure,
+ const char *pszMember, size_t *poffMember);
+
+
+/**
+ * Queries the value (usually the address) of a kernel symbol.
+ *
+ * This may go looking for the symbol in other modules, in which case it will
+ * always check the kernel symbol table first.
+ *
+ * @returns IPRT status code.
+ * @retval VINF_SUCCESS and value at @a ppvSymbol.
+ * @retval VERR_SYMBOL_NOT_FOUND
+ * @retval VERR_INVALID_HANDLE if hKrnlInfo is bad.
+ * @retval VERR_INVALID_POINTER if any of the pointers are bad.
+ *
+ * @param hKrnlInfo The kernel info handle.
+ * @param pszModule The name of the module to search, pass NULL to
+ * search the default kernel module(s).
+ * @param pszSymbol The C name of the symbol.
+ * On Windows NT there are the following special symbols:
+ * - __ImageBase: The base address of the module.
+ * - __ImageSize: The size of the module.
+ * - __ImageNtHdrs: Address of the NT headers.
+ * @param ppvSymbol Where to return the symbol value, passing NULL is
+ * OK. This may be modified even on failure, in
+ * particular, it will be set to NULL when
+ * VERR_SYMBOL_NOT_FOUND is returned.
+ *
+ * @sa RTR0DbgKrnlInfoGetSymbol, RTLdrGetSymbol
+ */
+RTR0DECL(int) RTR0DbgKrnlInfoQuerySymbol(RTDBGKRNLINFO hKrnlInfo, const char *pszModule,
+ const char *pszSymbol, void **ppvSymbol);
+
+/**
+ * Wrapper around RTR0DbgKrnlInfoQuerySymbol that returns the symbol.
+ *
+ * @return Symbol address if found, NULL if not found or some invalid parameter
+ * or something.
+ * @param hKrnlInfo The kernel info handle.
+ * @param pszModule The name of the module to search, pass NULL to
+ * search the default kernel module(s).
+ * @param pszSymbol The C name of the symbol.
+ * On Windows NT there are the following special symbols:
+ * - __ImageBase: The base address of the module.
+ * - __ImageSize: The size of the module.
+ * - __ImageNtHdrs: Address of the NT headers.
+ * @sa RTR0DbgKrnlInfoQuerySymbol, RTLdrGetSymbol
+ */
+RTR0DECL(void *) RTR0DbgKrnlInfoGetSymbol(RTDBGKRNLINFO hKrnlInfo, const char *pszModule, const char *pszSymbol);
+
+/**
+ * Queries the size (in bytes) of a kernel data type.
+ *
+ * @returns IPRT status code.
+ * @retval VINF_SUCCESS and size at @a pcbType.
+ * @retval VERR_NOT_FOUND if the type was not found.
+ * @retval VERR_INVALID_HANDLE if hKrnlInfo is bad.
+ * @retval VERR_INVALID_POINTER if any of the pointers are bad.
+ * @retval VERR_WRONG_TYPE if the type was not a valid data type (e.g. a
+ * function)
+ *
+ * @param hKrnlInfo The kernel info handle.
+ * @param pszModule The name of the module to search, pass NULL to
+ * search the default kernel module(s).
+ * @param pszType The type name.
+ * @param pcbType Where to return the size of the type.
+ */
+RTR0DECL(int) RTR0DbgKrnlInfoQuerySize(RTDBGKRNLINFO hKrnlInfo, const char *pszModule,
+ const char *pszType, size_t *pcbType);
+/** @} */
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_dbg_h */
+
diff --git a/include/iprt/dir.h b/include/iprt/dir.h
new file mode 100644
index 00000000..ff47c974
--- /dev/null
+++ b/include/iprt/dir.h
@@ -0,0 +1,894 @@
+/** @file
+ * IPRT - Directory Manipulation.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_dir_h
+#define IPRT_INCLUDED_dir_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+#include <iprt/fs.h>
+#include <iprt/symlink.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_dir RTDir - Directory Manipulation
+ * @ingroup grp_rt
+ * @{
+ */
+
+/**
+ * Check for the existence of a directory.
+ *
+ * All symbolic links will be attemped resolved. If that is undesirable, please
+ * use RTPathQueryInfo instead.
+ *
+ * @returns true if exist and is a directory.
+ * @returns false if not exists or isn't a directory.
+ * @param pszPath Path to the directory.
+ */
+RTDECL(bool) RTDirExists(const char *pszPath);
+
+/** @name RTDirCreate flags.
+ * @{ */
+/** Don't allow symbolic links as part of the path.
+ * @remarks this flag is currently not implemented and will be ignored. */
+#define RTDIRCREATE_FLAGS_NO_SYMLINKS RT_BIT(0)
+/** Set the not-content-indexed flag (default). Windows only atm. */
+#define RTDIRCREATE_FLAGS_NOT_CONTENT_INDEXED_DONT_SET RT_BIT(1)
+/** Do not set the not-content-indexed flag. Windows only atm. */
+#define RTDIRCREATE_FLAGS_NOT_CONTENT_INDEXED_SET UINT32_C(0)
+/** Ignore errors setting the not-content-indexed flag. Windows only atm. */
+#define RTDIRCREATE_FLAGS_NOT_CONTENT_INDEXED_NOT_CRITICAL RT_BIT(2)
+/** Ignore umask when applying the mode. */
+#define RTDIRCREATE_FLAGS_IGNORE_UMASK RT_BIT(3)
+/** Valid mask. */
+#define RTDIRCREATE_FLAGS_VALID_MASK UINT32_C(0x0000000f)
+/** @} */
+
+/**
+ * Creates a directory.
+ *
+ * @returns iprt status code.
+ * @param pszPath Path to the directory to create.
+ * @param fMode The mode of the new directory.
+ * @param fCreate Create flags, RTDIRCREATE_FLAGS_*.
+ */
+RTDECL(int) RTDirCreate(const char *pszPath, RTFMODE fMode, uint32_t fCreate);
+
+/**
+ * Creates a directory including all non-existing parent directories.
+ *
+ * @returns iprt status code.
+ * @param pszPath Path to the directory to create.
+ * @param fMode The mode of the new directories.
+ */
+RTDECL(int) RTDirCreateFullPath(const char *pszPath, RTFMODE fMode);
+
+/**
+ * Creates a directory including all non-existing parent directories.
+ *
+ * @returns iprt status code.
+ * @param pszPath Path to the directory to create.
+ * @param fMode The mode of the new directories.
+ * @param fFlags Create flags, RTDIRCREATE_FLAGS_*.
+ */
+RTDECL(int) RTDirCreateFullPathEx(const char *pszPath, RTFMODE fMode, uint32_t fFlags);
+
+/**
+ * Creates a new directory with a unique name using the given template.
+ *
+ * One or more trailing X'es in the template will be replaced by random alpha
+ * numeric characters until a RTDirCreate succeeds or we run out of patience.
+ * For instance:
+ * "/tmp/myprog-XXXXXX"
+ *
+ * As an alternative to trailing X'es, it
+ * is possible to put 3 or more X'es somewhere inside the directory name. In
+ * the following string only the last bunch of X'es will be modified:
+ * "/tmp/myprog-XXX-XXX.tmp"
+ *
+ * @returns iprt status code.
+ * @param pszTemplate The directory name template on input. The actual
+ * directory name on success. Empty string on failure.
+ * @param fMode The mode to create the directory with. Use 0700
+ * unless you have reason not to.
+ */
+RTDECL(int) RTDirCreateTemp(char *pszTemplate, RTFMODE fMode);
+
+/**
+ * Secure version of @a RTDirCreateTemp with a fixed mode of 0700.
+ *
+ * This function behaves in the same way as @a RTDirCreateTemp with two
+ * additional points. Firstly the mode is fixed to 0700. Secondly it will
+ * fail if it is not possible to perform the operation securely. Possible
+ * reasons include that the directory could be removed by another unprivileged
+ * user before it is used (e.g. if is created in a non-sticky /tmp directory)
+ * or that the path contains symbolic links which another unprivileged user
+ * could manipulate; however the exact criteria will be specified on a
+ * platform-by-platform basis as platform support is added.
+ * @see RTPathIsSecure for the current list of criteria.
+ * @returns iprt status code.
+ * @returns VERR_NOT_SUPPORTED if the interface can not be supported on the
+ * current platform at this time.
+ * @returns VERR_INSECURE if the directory could not be created securely.
+ * @param pszTemplate The directory name template on input. The
+ * actual directory name on success. Empty string
+ * on failure.
+ */
+RTDECL(int) RTDirCreateTempSecure(char *pszTemplate);
+
+/**
+ * Creates a new directory with a unique name by appending a number.
+ *
+ * This API differs from RTDirCreateTemp & RTDirCreateTempSecure in that it
+ * first tries to create the directory without any random bits, thus the best
+ * case result will be prettier. It also differs in that it does not take a
+ * template, but is instead given a template description, and will only use
+ * digits for the filling.
+ *
+ * For sake of convenience and debugging , the current implementation
+ * starts at 0 and will increment sequentally for a while before switching to
+ * random numbers.
+ *
+ * On success @a pszPath contains the path created.
+ *
+ * @returns iprt status code.
+ * @param pszPath The path to the directory. On input the base template
+ * name. On successful return, the unique directory we
+ * created.
+ * @param cbSize The size of the pszPath buffer. Needs enough space for
+ * holding the digits and the optional separator.
+ * @param fMode The mode of the new directory.
+ * @param cchDigits How many digits should the number have (zero padded).
+ * @param chSep The separator used between the path and the number. Can
+ * be zero. (optional)
+ */
+RTDECL(int) RTDirCreateUniqueNumbered(char *pszPath, size_t cbSize, RTFMODE fMode, size_t cchDigits, char chSep);
+
+/**
+ * Removes a directory if empty.
+ *
+ * @returns iprt status code.
+ * @param pszPath Path to the directory to remove.
+ */
+RTDECL(int) RTDirRemove(const char *pszPath);
+
+/**
+ * Removes a directory tree recursively.
+ *
+ * @returns iprt status code.
+ * @param pszPath Path to the directory to remove recursively.
+ * @param fFlags Flags, see RTDIRRMREC_F_XXX.
+ *
+ * @remarks This will not work on a root directory.
+ */
+RTDECL(int) RTDirRemoveRecursive(const char *pszPath, uint32_t fFlags);
+
+/** @name RTDirRemoveRecursive flags.
+ * @{ */
+/** Delete the content of the directory and the directory itself. */
+#define RTDIRRMREC_F_CONTENT_AND_DIR UINT32_C(0)
+/** Only delete the content of the directory, omit the directory it self. */
+#define RTDIRRMREC_F_CONTENT_ONLY RT_BIT_32(0)
+/** Long path hack: Don't apply RTPathAbs to the path. */
+#define RTDIRRMREC_F_NO_ABS_PATH RT_BIT_32(1)
+/** Mask of valid flags. */
+#define RTDIRRMREC_F_VALID_MASK UINT32_C(0x00000003)
+/** @} */
+
+/**
+ * Flushes the specified directory.
+ *
+ * This API is not implemented on all systems. On some systems it may be
+ * unnecessary if you've already flushed the file. If you really care for your
+ * data and is entering dangerous territories, it doesn't hurt calling it after
+ * flushing and closing the file.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_NOT_IMPLEMENTED must be expected.
+ * @retval VERR_NOT_SUPPORTED must be expected.
+ * @param pszPath Path to the directory.
+ */
+RTDECL(int) RTDirFlush(const char *pszPath);
+
+/**
+ * Flushes the parent directory of the specified file.
+ *
+ * This is just a wrapper around RTDirFlush.
+ *
+ * @returns IPRT status code, see RTDirFlush for details.
+ * @param pszChild Path to the file which parent should be flushed.
+ */
+RTDECL(int) RTDirFlushParent(const char *pszChild);
+
+
+
+/**
+ * Filter option for RTDirOpenFiltered().
+ */
+typedef enum RTDIRFILTER
+{
+ /** The usual invalid 0 entry. */
+ RTDIRFILTER_INVALID = 0,
+ /** No filter should be applied (and none was specified). */
+ RTDIRFILTER_NONE,
+ /** The Windows NT filter.
+ * The following wildcard chars: *, ?, <, > and "
+ * The matching is done on the uppercased strings. */
+ RTDIRFILTER_WINNT,
+ /** The UNIX filter.
+ * The following wildcard chars: *, ?, [..]
+ * The matching is done on exact case. */
+ RTDIRFILTER_UNIX,
+ /** The UNIX filter, uppercased matching.
+ * Same as RTDIRFILTER_UNIX except that the strings are uppercased before comparing. */
+ RTDIRFILTER_UNIX_UPCASED,
+
+ /** The usual full 32-bit value. */
+ RTDIRFILTER_32BIT_HACK = 0x7fffffff
+} RTDIRFILTER;
+
+
+/**
+ * Directory entry type.
+ *
+ * This is the RTFS_TYPE_MASK stuff shifted down 12 bits and
+ * identical to the BSD/LINUX ABI. See RTFS_TYPE_DIRENTRYTYPE_SHIFT.
+ */
+typedef enum RTDIRENTRYTYPE
+{
+ /** Unknown type (DT_UNKNOWN). */
+ RTDIRENTRYTYPE_UNKNOWN = 0,
+ /** Named pipe (fifo) (DT_FIFO). */
+ RTDIRENTRYTYPE_FIFO = 001,
+ /** Character device (DT_CHR). */
+ RTDIRENTRYTYPE_DEV_CHAR = 002,
+ /** Directory (DT_DIR). */
+ RTDIRENTRYTYPE_DIRECTORY = 004,
+ /** Block device (DT_BLK). */
+ RTDIRENTRYTYPE_DEV_BLOCK = 006,
+ /** Regular file (DT_REG). */
+ RTDIRENTRYTYPE_FILE = 010,
+ /** Symbolic link (DT_LNK). */
+ RTDIRENTRYTYPE_SYMLINK = 012,
+ /** Socket (DT_SOCK). */
+ RTDIRENTRYTYPE_SOCKET = 014,
+ /** Whiteout (DT_WHT). */
+ RTDIRENTRYTYPE_WHITEOUT = 016
+} RTDIRENTRYTYPE;
+
+
+/**
+ * Directory entry.
+ *
+ * This is inspired by the POSIX interfaces.
+ */
+#pragma pack(1)
+typedef struct RTDIRENTRY
+{
+ /** The unique identifier (within the file system) of this file system object (d_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;
+ /** The entry type. (d_type)
+ *
+ * @warning RTDIRENTRYTYPE_UNKNOWN is a common return value here since not all
+ * file systems (or Unixes) stores the type of a directory entry and
+ * instead expects the user to use stat() to get it. So, when you see
+ * this you should use RTDirQueryUnknownType or RTDirQueryUnknownTypeEx
+ * to get the type, or if if you're lazy, use RTDirReadEx.
+ */
+ RTDIRENTRYTYPE enmType;
+ /** The length of the filename, excluding the terminating nul character. */
+ uint16_t cbName;
+ /** The filename. (no path)
+ * Using the pcbDirEntry parameter of RTDirRead makes this field variable in size. */
+ char szName[260];
+} RTDIRENTRY;
+#pragma pack()
+/** Pointer to a directory entry. */
+typedef RTDIRENTRY *PRTDIRENTRY;
+/** Pointer to a const directory entry. */
+typedef RTDIRENTRY const *PCRTDIRENTRY;
+
+
+/**
+ * Directory entry with extended information.
+ *
+ * This is inspired by the PC interfaces.
+ */
+#pragma pack(1)
+typedef struct RTDIRENTRYEX
+{
+ /** Full information about the object. */
+ RTFSOBJINFO Info;
+ /** The length of the short field (number of RTUTF16 entries (not chars)).
+ * It is 16-bit for reasons of alignment. */
+ uint16_t cwcShortName;
+ /** The short name for 8.3 compatibility.
+ * Empty string if not available.
+ * Since the length is a bit tricky for a UTF-8 encoded name, and since this
+ * is practically speaking only a windows thing, it is encoded as UCS-2. */
+ RTUTF16 wszShortName[14];
+ /** The length of the filename. */
+ uint16_t cbName;
+ /** The filename. (no path)
+ * Using the pcbDirEntry parameter of RTDirReadEx makes this field variable in size. */
+ char szName[260];
+} RTDIRENTRYEX;
+#pragma pack()
+/** Pointer to a directory entry. */
+typedef RTDIRENTRYEX *PRTDIRENTRYEX;
+/** Pointer to a const directory entry. */
+typedef RTDIRENTRYEX const *PCRTDIRENTRYEX;
+
+
+/**
+ * Opens a directory.
+ *
+ * @returns iprt status code.
+ * @param phDir Where to store the open directory handle.
+ * @param pszPath Path to the directory to open.
+ */
+RTDECL(int) RTDirOpen(RTDIR *phDir, const char *pszPath);
+
+/** @name RTDIR_F_XXX - RTDirOpenFiltered flags.
+ * @{ */
+/** Don't allow symbolic links as part of the path.
+ * @remarks this flag is currently not implemented and will be ignored. */
+#define RTDIR_F_NO_SYMLINKS RT_BIT_32(0)
+/** Deny relative opening of anything above this directory. */
+#define RTDIR_F_DENY_ASCENT RT_BIT_32(1)
+/** Don't follow symbolic links in the final component. */
+#define RTDIR_F_NO_FOLLOW RT_BIT_32(2)
+/** Long path hack: Don't apply RTPathAbs to the path. */
+#define RTDIR_F_NO_ABS_PATH RT_BIT_32(3)
+/** Valid flag mask. */
+#define RTDIR_F_VALID_MASK UINT32_C(0x0000000f)
+/** @} */
+
+/**
+ * Opens a directory with flags and optional filtering.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_IS_A_SYMLINK if RTDIR_F_NO_FOLLOW is set, @a enmFilter is
+ * RTDIRFILTER_NONE and @a pszPath points to a symbolic link and does
+ * not end with a slash. Note that on Windows this does not apply to
+ * file symlinks, only directory symlinks, for the file variant
+ * VERR_NOT_A_DIRECTORY will be returned.
+ *
+ * @param phDir Where to store the open directory handle.
+ * @param pszPath Path to the directory to search, this must include wildcards.
+ * @param enmFilter The kind of filter to apply. Setting this to RTDIRFILTER_NONE makes
+ * this function behave like RTDirOpen.
+ * @param fFlags Open flags, RTDIR_F_XXX.
+ *
+ */
+RTDECL(int) RTDirOpenFiltered(RTDIR *phDir, const char *pszPath, RTDIRFILTER enmFilter, uint32_t fFlags);
+
+/**
+ * Closes a directory.
+ *
+ * @returns iprt status code.
+ * @param hDir Handle to open directory returned by RTDirOpen() or
+ * RTDirOpenFiltered().
+ */
+RTDECL(int) RTDirClose(RTDIR hDir);
+
+/**
+ * Checks if the supplied directory handle is valid.
+ *
+ * @returns true if valid.
+ * @returns false if invalid.
+ * @param hDir The directory handle.
+ */
+RTDECL(bool) RTDirIsValid(RTDIR hDir);
+
+/**
+ * Reads the next entry in the directory.
+ *
+ * @returns VINF_SUCCESS and data in pDirEntry on success.
+ * @returns VERR_NO_MORE_FILES when the end of the directory has been reached.
+ * @returns VERR_BUFFER_OVERFLOW if the buffer is too small to contain the filename. If
+ * pcbDirEntry is specified it will be updated with the required buffer size.
+ * @returns suitable iprt status code on other errors.
+ *
+ * @param hDir Handle to the open directory.
+ * @param pDirEntry Where to store the information about the next
+ * directory entry on success.
+ * @param pcbDirEntry Optional parameter used for variable buffer size.
+ *
+ * On input the variable pointed to contains the size of the pDirEntry
+ * structure. This must be at least OFFSET(RTDIRENTRY, szName[2]) bytes.
+ *
+ * On successful output the field is updated to
+ * OFFSET(RTDIRENTRY, szName[pDirEntry->cbName + 1]).
+ *
+ * When the data doesn't fit in the buffer and VERR_BUFFER_OVERFLOW is
+ * returned, this field contains the required buffer size.
+ *
+ * The value is unchanged in all other cases.
+ */
+RTDECL(int) RTDirRead(RTDIR hDir, PRTDIRENTRY pDirEntry, size_t *pcbDirEntry);
+
+/**
+ * Reads the next entry in the directory returning extended information.
+ *
+ * @returns VINF_SUCCESS and data in pDirEntry on success.
+ * @returns VERR_NO_MORE_FILES when the end of the directory has been reached.
+ * @returns VERR_BUFFER_OVERFLOW if the buffer is too small to contain the filename. If
+ * pcbDirEntry is specified it will be updated with the required buffer size.
+ * @returns suitable iprt status code on other errors.
+ *
+ * @param hDir Handle to the open directory.
+ * @param pDirEntry Where to store the information about the next
+ * directory entry on success.
+ * @param pcbDirEntry Optional parameter used for variable buffer size.
+ *
+ * On input the variable pointed to contains the size of the pDirEntry
+ * structure. This must be at least OFFSET(RTDIRENTRYEX, szName[2]) bytes.
+ *
+ * On successful output the field is updated to
+ * OFFSET(RTDIRENTRYEX, szName[pDirEntry->cbName + 1]).
+ *
+ * When the data doesn't fit in the buffer and VERR_BUFFER_OVERFLOW is
+ * returned, this field contains the required buffer size.
+ *
+ * The value is unchanged in all other cases.
+ * @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.
+ */
+RTDECL(int) RTDirReadEx(RTDIR hDir, PRTDIRENTRYEX pDirEntry, size_t *pcbDirEntry, RTFSOBJATTRADD enmAdditionalAttribs, uint32_t fFlags);
+
+/**
+ * Wrapper around RTDirReadEx that does the directory entry buffer handling.
+ *
+ * Call RTDirReadExAFree to free the buffers allocated by this function.
+ *
+ * @returns IPRT status code, see RTDirReadEx() for details.
+ *
+ * @param hDir Handle to the open directory.
+ * @param ppDirEntry Pointer to the directory entry pointer. Initialize this
+ * to NULL before the first call.
+ * @param pcbDirEntry Where the API caches the allocation size. Set this to
+ * zero before the first call.
+ * @param enmAddAttr See RTDirReadEx.
+ * @param fFlags See RTDirReadEx.
+ */
+RTDECL(int) RTDirReadExA(RTDIR hDir, PRTDIRENTRYEX *ppDirEntry, size_t *pcbDirEntry, RTFSOBJATTRADD enmAddAttr, uint32_t fFlags);
+
+/**
+ * Frees the buffer allocated by RTDirReadExA.
+ *
+ * @param ppDirEntry Pointer to the directory entry pointer.
+ * @param pcbDirEntry Where the API caches the allocation size.
+ */
+RTDECL(void) RTDirReadExAFree(PRTDIRENTRYEX *ppDirEntry, size_t *pcbDirEntry);
+
+/**
+ * Resolves RTDIRENTRYTYPE_UNKNOWN values returned by RTDirRead.
+ *
+ * @returns IPRT status code (see RTPathQueryInfo).
+ * @param pszComposedName The path to the directory entry. The caller must
+ * compose this, it's NOT sufficient to pass
+ * RTDIRENTRY::szName!
+ * @param fFollowSymlinks Whether to follow symbolic links or not.
+ * @param penmType Pointer to the RTDIRENTRY::enmType member. If this
+ * is not RTDIRENTRYTYPE_UNKNOWN and, if
+ * @a fFollowSymlinks is false, not
+ * RTDIRENTRYTYPE_SYMLINK, the function will return
+ * immediately without doing anything. Otherwise it
+ * will use RTPathQueryInfo to try figure out the
+ * correct value. On failure, this will be unchanged.
+ */
+RTDECL(int) RTDirQueryUnknownType(const char *pszComposedName, bool fFollowSymlinks, RTDIRENTRYTYPE *penmType);
+
+/**
+ * Resolves RTDIRENTRYTYPE_UNKNOWN values returned by RTDirRead, extended
+ * version.
+ *
+ * @returns IPRT status code (see RTPathQueryInfo).
+ * @param pszComposedName The path to the directory entry. The caller must
+ * compose this, it's NOT sufficient to pass
+ * RTDIRENTRY::szName!
+ * @param fFollowSymlinks Whether to follow symbolic links or not.
+ * @param penmType Pointer to the RTDIRENTRY::enmType member or
+ * similar. Will NOT be checked on input.
+ * @param pObjInfo The object info buffer to use with RTPathQueryInfo.
+ */
+RTDECL(int) RTDirQueryUnknownTypeEx(const char *pszComposedName, bool fFollowSymlinks, RTDIRENTRYTYPE *penmType, PRTFSOBJINFO pObjInfo);
+
+/**
+ * Checks if the directory entry returned by RTDirRead is '.', '..' or similar.
+ *
+ * @returns true / false.
+ * @param pDirEntry The directory entry to check.
+ */
+RTDECL(bool) RTDirEntryIsStdDotLink(PRTDIRENTRY pDirEntry);
+
+/**
+ * Checks if the directory entry returned by RTDirReadEx is '.', '..' or
+ * similar.
+ *
+ * @returns true / false.
+ * @param pDirEntryEx The extended directory entry to check.
+ */
+RTDECL(bool) RTDirEntryExIsStdDotLink(PCRTDIRENTRYEX pDirEntryEx);
+
+/**
+ * Rewind and restart the directory reading.
+ *
+ * @returns IRPT status code.
+ * @param hDir The directory handle to rewind.
+ */
+RTDECL(int) RTDirRewind(RTDIR hDir);
+
+/**
+ * Renames a file.
+ *
+ * Identical to RTPathRename except that it will ensure that the source is a directory.
+ *
+ * @returns IPRT status code.
+ * @returns VERR_ALREADY_EXISTS if the destination file exists.
+ *
+ * @param pszSrc The path to the source file.
+ * @param pszDst The path to the destination file.
+ * This file will be created.
+ * @param fRename See RTPathRename.
+ */
+RTDECL(int) RTDirRename(const char *pszSrc, const char *pszDst, unsigned fRename);
+
+
+/**
+ * Query information about an open directory.
+ *
+ * @returns iprt status code.
+ *
+ * @param hDir Handle to the open directory.
+ * @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) RTDirQueryInfo(RTDIR hDir, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAdditionalAttribs);
+
+
+/**
+ * Changes one or more of the timestamps associated of file system object.
+ *
+ * @returns iprt status code.
+ * @returns VERR_NOT_SUPPORTED is returned if the operation isn't supported by the OS.
+ *
+ * @param hDir Handle to the open directory.
+ * @param pAccessTime Pointer to the new access time. NULL if not to be changed.
+ * @param pModificationTime Pointer to the new modifcation time. NULL if not to be changed.
+ * @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) RTDirSetTimes(RTDIR hDir, PCRTTIMESPEC pAccessTime, PCRTTIMESPEC pModificationTime,
+ PCRTTIMESPEC pChangeTime, PCRTTIMESPEC pBirthTime);
+
+
+/**
+ * Changes the mode flags of an open directory.
+ *
+ * The API requires at least one of the mode flag sets (Unix/Dos) to
+ * be set. The type is ignored.
+ *
+ * @returns iprt status code.
+ * @param hDir Handle to the open directory.
+ * @param fMode The new file mode, see @ref grp_rt_fs for details.
+ */
+RTDECL(int) RTDirSetMode(RTDIR hDir, RTFMODE fMode);
+
+
+/** @defgroup grp_rt_dir_rel Directory relative APIs
+ *
+ * This group of APIs allows working with paths that are relative to an open
+ * directory, therebye eliminating some classic path related race conditions on
+ * systems with native support for these kinds of operations.
+ *
+ * On NT (Windows) there is native support for addressing files, directories and
+ * stuff _below_ the open directory. It is not possible to go upwards
+ * (hDir:../../grandparent), at least not with NTFS, forcing us to use the
+ * directory path as a fallback and opening us to potential races.
+ *
+ * On most unix-like systems here is now native support for all of this.
+ *
+ * @{ */
+
+/**
+ * Open a file relative to @a hDir.
+ *
+ * @returns IPRT status code.
+ * @param hDir The directory to open relative to.
+ * @param pszRelFilename The relative path to the file.
+ * @param fOpen Open flags, i.e a combination of the RTFILE_O_XXX
+ * defines. The ACCESS, ACTION and DENY flags are
+ * mandatory!
+ * @param phFile Where to store the handle to the opened file.
+ *
+ * @sa RTFileOpen
+ */
+RTDECL(int) RTDirRelFileOpen(RTDIR hDir, const char *pszRelFilename, uint64_t fOpen, PRTFILE phFile);
+
+
+
+/**
+ * Opens a directory relative to @a hDir.
+ *
+ * @returns IPRT status code.
+ * @param hDir The directory to open relative to.
+ * @param pszDir The relative path to the directory to open.
+ * @param phDir Where to store the directory handle.
+ *
+ * @sa RTDirOpen
+ */
+RTDECL(int) RTDirRelDirOpen(RTDIR hDir, const char *pszDir, RTDIR *phDir);
+
+/**
+ * Opens a directory relative to @a hDir, with flags and optional filtering.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_IS_A_SYMLINK if RTDIR_F_NO_FOLLOW is set, @a enmFilter is
+ * RTDIRFILTER_NONE and @a pszPath points to a symbolic link and does
+ * not end with a slash. Note that on Windows this does not apply to
+ * file symlinks, only directory symlinks, for the file variant
+ * VERR_NOT_A_DIRECTORY will be returned.
+ *
+ * @param hDir The directory to open relative to.
+ * @param pszDirAndFilter The relative path to the directory to search, this
+ * must include wildcards.
+ * @param enmFilter The kind of filter to apply. Setting this to
+ * RTDIRFILTER_NONE makes this function behave like
+ * RTDirOpen.
+ * @param fFlags Open flags, RTDIR_F_XXX.
+ * @param phDir Where to store the directory handle.
+ *
+ * @sa RTDirOpenFiltered
+ */
+RTDECL(int) RTDirRelDirOpenFiltered(RTDIR hDir, const char *pszDirAndFilter, RTDIRFILTER enmFilter,
+ uint32_t fFlags, RTDIR *phDir);
+
+/**
+ * Creates a directory relative to @a hDir.
+ *
+ * @returns IPRT status code.
+ * @param hDir The directory @a pszRelPath is relative to.
+ * @param pszRelPath The relative path to the directory to create.
+ * @param fMode The mode of the new directory.
+ * @param fCreate Create flags, RTDIRCREATE_FLAGS_XXX.
+ * @param phSubDir Where to return the handle of the created directory.
+ * Optional.
+ *
+ * @sa RTDirCreate
+ */
+RTDECL(int) RTDirRelDirCreate(RTDIR hDir, const char *pszRelPath, RTFMODE fMode, uint32_t fCreate, RTDIR *phSubDir);
+
+/**
+ * Removes a directory relative to @a hDir if empty.
+ *
+ * @returns IPRT status code.
+ * @param hDir The directory @a pszRelPath is relative to.
+ * @param pszRelPath The relative path to the directory to remove.
+ *
+ * @sa RTDirRemove
+ */
+RTDECL(int) RTDirRelDirRemove(RTDIR hDir, const char *pszRelPath);
+
+
+/**
+ * Query information about a file system object relative to @a hDir.
+ *
+ * @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 hDir The directory @a pszRelPath is relative to.
+ * @param pszRelPath The relative path to the file system object.
+ * @param pObjInfo Object information structure to be filled on successful
+ * return.
+ * @param enmAddAttr 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.
+ *
+ * @sa RTPathQueryInfoEx
+ */
+RTDECL(int) RTDirRelPathQueryInfo(RTDIR hDir, const char *pszRelPath, PRTFSOBJINFO pObjInfo,
+ RTFSOBJATTRADD enmAddAttr, uint32_t fFlags);
+
+/**
+ * Changes the mode flags of a file system object relative to @a hDir.
+ *
+ * The API requires at least one of the mode flag sets (Unix/Dos) to
+ * be set. The type is ignored.
+ *
+ * @returns IPRT status code.
+ * @param hDir The directory @a pszRelPath is relative to.
+ * @param pszRelPath The relative path to the file system object.
+ * @param fMode The new file mode, see @ref grp_rt_fs for details.
+ * @param fFlags RTPATH_F_ON_LINK or RTPATH_F_FOLLOW_LINK.
+ *
+ * @sa RTPathSetMode
+ */
+RTDECL(int) RTDirRelPathSetMode(RTDIR hDir, const char *pszRelPath, RTFMODE fMode, uint32_t fFlags);
+
+/**
+ * Changes one or more of the timestamps associated of file system object
+ * relative to @a hDir.
+ *
+ * @returns IPRT status code.
+ * @param hDir The directory @a pszRelPath is relative to.
+ * @param pszRelPath The relative 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.
+ *
+ * @sa RTPathSetTimesEx
+ */
+RTDECL(int) RTDirRelPathSetTimes(RTDIR hDir, const char *pszRelPath, PCRTTIMESPEC pAccessTime, PCRTTIMESPEC pModificationTime,
+ PCRTTIMESPEC pChangeTime, PCRTTIMESPEC pBirthTime, uint32_t fFlags);
+
+/**
+ * Changes the owner and/or group of a file system object relative to @a hDir.
+ *
+ * @returns IPRT status code.
+ * @param hDir The directory @a pszRelPath is relative to.
+ * @param pszRelPath The relative 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.
+ *
+ * @sa RTPathSetOwnerEx
+ */
+RTDECL(int) RTDirRelPathSetOwner(RTDIR hDir, const char *pszRelPath, uint32_t uid, uint32_t gid, uint32_t fFlags);
+
+/**
+ * Renames a directory relative 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 hDirSrc The directory the source path is relative to.
+ * @param pszSrc The source path, relative to @a hDirSrc.
+ * @param hDirDst The directory the destination path is relative to.
+ * @param pszDst The destination path, relative to @a hDirDst.
+ * @param fRename Rename flags, RTPATHRENAME_FLAGS_XXX.
+ *
+ * @sa RTPathRename
+ */
+RTDECL(int) RTDirRelPathRename(RTDIR hDirSrc, const char *pszSrc, RTDIR hDirDst, const char *pszDst, unsigned fRename);
+
+/**
+ * Removes the last component of the directory relative path.
+ *
+ * @returns IPRT status code.
+ * @param hDir The directory @a pszRelPath is relative to.
+ * @param pszRelPath The relative path to the file system object.
+ * @param fUnlink Unlink flags, RTPATHUNLINK_FLAGS_XXX.
+ *
+ * @sa RTPathUnlink
+ */
+RTDECL(int) RTDirRelPathUnlink(RTDIR hDir, const char *pszRelPath, uint32_t fUnlink);
+
+
+
+/**
+ * Creates a symbolic link (@a pszSymlink) relative to @a hDir targeting @a
+ * pszTarget.
+ *
+ * @returns IPRT status code.
+ * @param hDir The directory @a pszSymlink is relative to.
+ * @param pszSymlink The relative path of the symbolic link.
+ * @param pszTarget The path to the symbolic link target. This is
+ * relative to @a pszSymlink or an absolute path.
+ * @param enmType The symbolic link type. For Windows compatability
+ * it is very important to set this correctly. When
+ * RTSYMLINKTYPE_UNKNOWN is used, the API will try
+ * make a guess and may attempt query information
+ * about @a pszTarget in the process.
+ * @param fCreate Create flags, RTSYMLINKCREATE_FLAGS_XXX.
+ *
+ * @sa RTSymlinkCreate
+ */
+RTDECL(int) RTDirRelSymlinkCreate(RTDIR hDir, const char *pszSymlink, const char *pszTarget,
+ RTSYMLINKTYPE enmType, uint32_t fCreate);
+
+/**
+ * Read the symlink target relative to @a hDir.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_NOT_SYMLINK if @a pszSymlink does not specify a symbolic link.
+ * @retval VERR_BUFFER_OVERFLOW if the link is larger than @a cbTarget. The
+ * buffer will contain what all we managed to read, fully terminated
+ * if @a cbTarget > 0.
+ *
+ * @param hDir The directory @a pszSymlink is relative to.
+ * @param pszSymlink The relative path to the symbolic link that should
+ * be read.
+ * @param pszTarget The target buffer.
+ * @param cbTarget The size of the target buffer.
+ * @param fRead Read flags, RTSYMLINKREAD_FLAGS_XXX.
+ *
+ * @sa RTSymlinkRead
+ */
+RTDECL(int) RTDirRelSymlinkRead(RTDIR hDir, const char *pszSymlink, char *pszTarget, size_t cbTarget, uint32_t fRead);
+
+/** @} */
+
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_dir_h */
+
diff --git a/include/iprt/dvm.h b/include/iprt/dvm.h
new file mode 100644
index 00000000..25f12526
--- /dev/null
+++ b/include/iprt/dvm.h
@@ -0,0 +1,639 @@
+/** @file
+ * IPRT Disk Volume Management API (DVM).
+ */
+
+/*
+ * Copyright (C) 2011-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_dvm_h
+#define IPRT_INCLUDED_dvm_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+
+RT_C_DECLS_BEGIN
+
+
+/** @defgroup grp_dvm IPRT Disk Volume Management
+ * @{
+ */
+
+/**
+ * Volume type.
+ * Comparable to the FS type in MBR partition maps
+ * or the partition type GUIDs in GPT tables.
+ */
+typedef enum RTDVMVOLTYPE
+{
+ /** Invalid. */
+ RTDVMVOLTYPE_INVALID = 0,
+ /** Unknown. */
+ RTDVMVOLTYPE_UNKNOWN,
+ /** Volume hosts a NTFS filesystem. */
+ RTDVMVOLTYPE_NTFS,
+ /** Volume hosts a FAT12 filesystem. */
+ RTDVMVOLTYPE_FAT12,
+ /** Volume hosts a FAT16 filesystem. */
+ RTDVMVOLTYPE_FAT16,
+ /** Volume hosts a FAT32 filesystem. */
+ RTDVMVOLTYPE_FAT32,
+
+ /** EFI system partition (c12a7328-f81f-11d2-ba4b-00a0c93ec93b). */
+ RTDVMVOLTYPE_EFI_SYSTEM,
+
+ /** Volume hosts a Mac OS X HFS or HFS+ filesystem. */
+ RTDVMVOLTYPE_DARWIN_HFS,
+ /** Volume hosts a Mac OS X APFS filesystem. */
+ RTDVMVOLTYPE_DARWIN_APFS,
+
+ /** Volume hosts a Linux swap. */
+ RTDVMVOLTYPE_LINUX_SWAP,
+ /** Volume hosts a Linux filesystem. */
+ RTDVMVOLTYPE_LINUX_NATIVE,
+ /** Volume hosts a Linux LVM. */
+ RTDVMVOLTYPE_LINUX_LVM,
+ /** Volume hosts a Linux SoftRaid. */
+ RTDVMVOLTYPE_LINUX_SOFTRAID,
+
+ /** Volume hosts a FreeBSD disklabel. */
+ RTDVMVOLTYPE_FREEBSD,
+ /** Volume hosts a NetBSD disklabel. */
+ RTDVMVOLTYPE_NETBSD,
+ /** Volume hosts a OpenBSD disklabel. */
+ RTDVMVOLTYPE_OPENBSD,
+ /** Volume hosts a Solaris volume. */
+ RTDVMVOLTYPE_SOLARIS,
+
+ /** Volume hosts a Windows basic data partition . */
+ RTDVMVOLTYPE_WIN_BASIC,
+ /** Volume hosts a Microsoft reserved partition (MSR). */
+ RTDVMVOLTYPE_WIN_MSR,
+ /** Volume hosts a Windows logical disk manager (LDM) metadata partition. */
+ RTDVMVOLTYPE_WIN_LDM_META,
+ /** Volume hosts a Windows logical disk manager (LDM) data partition. */
+ RTDVMVOLTYPE_WIN_LDM_DATA,
+ /** Volume hosts a Windows recovery partition. */
+ RTDVMVOLTYPE_WIN_RECOVERY,
+ /** Volume hosts a storage spaces partition. */
+ RTDVMVOLTYPE_WIN_STORAGE_SPACES,
+
+ /** Volume hosts an IBM general parallel file system (GPFS). */
+ RTDVMVOLTYPE_IBM_GPFS,
+
+ /** OS/2 (Arca Noae) type 1 partition. */
+ RTDVMVOLTYPE_ARCA_OS2,
+
+ /** End of the valid values. */
+ RTDVMVOLTYPE_END,
+ /** Usual 32bit hack. */
+ RTDVMVOLTYPE_32BIT_HACK = 0x7fffffff
+} RTDVMVOLTYPE;
+
+/** @defgroup grp_dvm_flags Flags used by RTDvmCreate.
+ * @{ */
+/** DVM flags - Blocks are always marked as unused if the volume has
+ * no block status callback set.
+ * The default is to mark them as used. */
+#define DVM_FLAGS_NO_STATUS_CALLBACK_MARK_AS_UNUSED RT_BIT_32(0)
+/** DVM flags - Space which is unused in the map will be marked as used
+ * when calling RTDvmMapQueryBlockStatus(). */
+#define DVM_FLAGS_UNUSED_SPACE_MARK_AS_USED RT_BIT_32(1)
+/** Mask of all valid flags. */
+#define DVM_FLAGS_VALID_MASK UINT32_C(0x00000003)
+/** @} */
+
+
+/** @defgroup grp_dvm_vol_flags Volume flags used by RTDvmVolumeGetFlags().
+ * @{ */
+/** Volume flags - Volume is bootable. */
+#define DVMVOLUME_FLAGS_BOOTABLE RT_BIT_64(0)
+/** Volume flags - Volume is active. */
+#define DVMVOLUME_FLAGS_ACTIVE RT_BIT_64(1)
+/** Volume is contiguous on the underlying medium and RTDvmVolumeQueryRange(). */
+#define DVMVOLUME_F_CONTIGUOUS RT_BIT_64(2)
+/** @} */
+
+/** A handle to a volume manager. */
+typedef struct RTDVMINTERNAL *RTDVM;
+/** A pointer to a volume manager handle. */
+typedef RTDVM *PRTDVM;
+/** NIL volume manager handle. */
+#define NIL_RTDVM ((RTDVM)~0)
+
+/** A handle to a volume in a volume map. */
+typedef struct RTDVMVOLUMEINTERNAL *RTDVMVOLUME;
+/** A pointer to a volume handle. */
+typedef RTDVMVOLUME *PRTDVMVOLUME;
+/** NIL volume handle. */
+#define NIL_RTDVMVOLUME ((RTDVMVOLUME)~0)
+
+/**
+ * Callback for querying the block allocation status of a volume.
+ *
+ * @returns IPRT status code.
+ * @param pvUser Opaque user data passed when setting the callback.
+ * @param off Offset relative to the start of the volume.
+ * @param cb Range to check in bytes.
+ * @param pfAllocated Where to store the allocation status on success.
+ */
+typedef DECLCALLBACKTYPE(int, FNDVMVOLUMEQUERYBLOCKSTATUS,(void *pvUser, uint64_t off, uint64_t cb, bool *pfAllocated));
+/** Pointer to a query block allocation status callback. */
+typedef FNDVMVOLUMEQUERYBLOCKSTATUS *PFNDVMVOLUMEQUERYBLOCKSTATUS;
+
+/**
+ * Create a new volume manager.
+ *
+ * @returns IPRT status.
+ * @param phVolMgr Where to store the handle to the volume manager on
+ * success.
+ * @param hVfsFile The disk/container/whatever.
+ * @param cbSector Size of one sector in bytes.
+ * @param fFlags Combination of RTDVM_FLAGS_*
+ */
+RTDECL(int) RTDvmCreate(PRTDVM phVolMgr, RTVFSFILE hVfsFile, uint32_t cbSector, uint32_t fFlags);
+
+/**
+ * Retain a given volume manager.
+ *
+ * @returns New reference count on success, UINT32_MAX on failure.
+ * @param hVolMgr The volume manager to retain.
+ */
+RTDECL(uint32_t) RTDvmRetain(RTDVM hVolMgr);
+
+/**
+ * Releases a given volume manager.
+ *
+ * @returns New reference count on success (0 if closed), UINT32_MAX on failure.
+ * @param hVolMgr The volume manager to release.
+ */
+RTDECL(uint32_t) RTDvmRelease(RTDVM hVolMgr);
+
+/**
+ * Probes the underyling disk for the best volume manager format handler
+ * and opens it.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_NOT_FOUND if no backend can handle the volume map on the disk.
+ * @param hVolMgr The volume manager handle.
+ */
+RTDECL(int) RTDvmMapOpen(RTDVM hVolMgr);
+
+/**
+ * Initializes a new volume map using the given format handler.
+ *
+ * @returns IPRT status code.
+ * @param hVolMgr The volume manager handle.
+ * @param pszFmt The format to use for the new map.
+ */
+RTDECL(int) RTDvmMapInitialize(RTDVM hVolMgr, const char *pszFmt);
+
+/**
+ * Gets the name of the currently used format of the disk map.
+ *
+ * @returns Name of the format.
+ * @param hVolMgr The volume manager handle.
+ */
+RTDECL(const char *) RTDvmMapGetFormatName(RTDVM hVolMgr);
+
+/**
+ * DVM format types.
+ */
+typedef enum RTDVMFORMATTYPE
+{
+ /** Invalid zero value. */
+ RTDVMFORMATTYPE_INVALID = 0,
+ /** Master boot record. */
+ RTDVMFORMATTYPE_MBR,
+ /** GUID partition table. */
+ RTDVMFORMATTYPE_GPT,
+ /** BSD labels. */
+ RTDVMFORMATTYPE_BSD_LABEL,
+ /** End of valid values. */
+ RTDVMFORMATTYPE_END,
+ /** 32-bit type size hack. */
+ RTDVMFORMATTYPE_32BIT_HACK = 0x7fffffff
+} RTDVMFORMATTYPE;
+
+/**
+ * Gets the format type of the current disk map.
+ *
+ * @returns Format type. RTDVMFORMATTYPE_INVALID on invalid input.
+ * @param hVolMgr The volume manager handle.
+ */
+RTDECL(RTDVMFORMATTYPE) RTDvmMapGetFormatType(RTDVM hVolMgr);
+
+/**
+ * Gets the UUID of the disk if applicable.
+ *
+ * Disks using the MBR format may return the 32-bit disk identity in the
+ * u32TimeLow field and set the rest to zero.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_NOT_SUPPORTED if the partition scheme doesn't do UUIDs.
+ * @retval VINF_NOT_SUPPORTED if non-UUID disk ID is returned.
+ * @param hVolMgr The volume manager handle.
+ * @param pUuid Where to return the UUID.
+ *
+ * @todo It's quite possible this should be turned into a map-level edition of
+ * RTDvmVolumeQueryProp...
+ */
+RTDECL(int) RTDvmMapQueryDiskUuid(RTDVM hVolMgr, PRTUUID pUuid);
+
+/**
+ * Gets the number of valid partitions in the map.
+ *
+ * @returns The number of valid volumes in the map or UINT32_MAX on failure.
+ * @param hVolMgr The volume manager handle.
+ */
+RTDECL(uint32_t) RTDvmMapGetValidVolumes(RTDVM hVolMgr);
+
+/**
+ * Gets the maximum number of partitions the map can hold.
+ *
+ * @returns The maximum number of volumes in the map or UINT32_MAX on failure.
+ * @param hVolMgr The volume manager handle.
+ */
+RTDECL(uint32_t) RTDvmMapGetMaxVolumes(RTDVM hVolMgr);
+
+/**
+ * Get the first valid volume from a map.
+ *
+ * @returns IPRT status code.
+ * @param hVolMgr The volume manager handle.
+ * @param phVol Where to store the handle to the first volume on
+ * success. Release with RTDvmVolumeRelease().
+ */
+RTDECL(int) RTDvmMapQueryFirstVolume(RTDVM hVolMgr, PRTDVMVOLUME phVol);
+
+/**
+ * Get the first valid volume from a map.
+ *
+ * @returns IPRT status code.
+ * @param hVolMgr The volume manager handle.
+ * @param hVol Handle of the current volume.
+ * @param phVolNext Where to store the handle to the next volume on
+ * success. Release with RTDvmVolumeRelease().
+ */
+RTDECL(int) RTDvmMapQueryNextVolume(RTDVM hVolMgr, RTDVMVOLUME hVol, PRTDVMVOLUME phVolNext);
+
+/**
+ * Returns whether the given block on the disk is in use.
+ *
+ * @returns IPRT status code.
+ * @param hVolMgr The volume manager handle.
+ * @param off The start offset to check for.
+ * @param cb The range in bytes to check.
+ * @param pfAllocated Where to store the in-use status on success.
+ *
+ * @remark This method will return true even if a part of the range is not in use.
+ */
+RTDECL(int) RTDvmMapQueryBlockStatus(RTDVM hVolMgr, uint64_t off, uint64_t cb, bool *pfAllocated);
+
+/**
+ * Partition/map table location information.
+ * @sa RTDvmMapQueryTableLocations
+ */
+typedef struct RTDVMTABLELOCATION
+{
+ /** The byte offset on the underlying media. */
+ uint64_t off;
+ /** The table size in bytes. */
+ uint64_t cb;
+ /** Number of padding bytes / free space between the actual table and
+ * first partition. */
+ uint64_t cbPadding;
+} RTDVMTABLELOCATION;
+/** Pointer to partition table location info. */
+typedef RTDVMTABLELOCATION *PRTDVMTABLELOCATION;
+/** Pointer to const partition table location info. */
+typedef RTDVMTABLELOCATION const *PCRTDVMTABLELOCATION;
+
+
+/** @name RTDVMMAPQTABLOC_F_XXX - Flags for RTDvmMapQueryTableLocations
+ * @{ */
+/** Make sure GPT includes the protective MBR. */
+#define RTDVMMAPQTABLOC_F_INCLUDE_LEGACY RT_BIT_32(0)
+/** Valid flags. */
+#define RTDVMMAPQTABLOC_F_VALID_MASK UINT32_C(1)
+/** @} */
+
+/**
+ * Query the partition table locations.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_BUFFER_OVERFLOW if the table is too small, @a *pcActual will be
+ * set to the required size.
+ * @retval VERR_BUFFER_UNDERFLOW if the table is too big and @a pcActual is
+ * NULL.
+ * @param hVolMgr The volume manager handle.
+ * @param fFlags Flags, see RTDVMMAPQTABLOC_F_XXX.
+ * @param paLocations Where to return the info. This can be NULL if @a
+ * cLocations is zero and @a pcActual is given.
+ * @param cLocations The size of @a paLocations in items.
+ * @param pcActual Where to return the actual number of locations, or
+ * on VERR_BUFFER_OVERFLOW the necessary table size.
+ * Optional, when not specified the cLocations value
+ * must match exactly or it fails with
+ * VERR_BUFFER_UNDERFLOW.
+ */
+RTDECL(int) RTDvmMapQueryTableLocations(RTDVM hVolMgr, uint32_t fFlags,
+ PRTDVMTABLELOCATION paLocations, size_t cLocations, size_t *pcActual);
+
+/**
+ * Retains a valid volume handle.
+ *
+ * @returns New reference count on success, UINT32_MAX on failure.
+ * @param hVol The volume to retain.
+ */
+RTDECL(uint32_t) RTDvmVolumeRetain(RTDVMVOLUME hVol);
+
+/**
+ * Releases a valid volume handle.
+ *
+ * @returns New reference count on success (0 if closed), UINT32_MAX on failure.
+ * @param hVol The volume to release.
+ */
+RTDECL(uint32_t) RTDvmVolumeRelease(RTDVMVOLUME hVol);
+
+/**
+ * Sets the callback to query the block allocation status for a volume.
+ * This overwrites any other callback set previously.
+ *
+ * @returns nothing.
+ * @param hVol The volume handle.
+ * @param pfnQueryBlockStatus The callback to set. Can be NULL to disable
+ * a previous callback.
+ * @param pvUser Opaque user data passed in the callback.
+ */
+RTDECL(void) RTDvmVolumeSetQueryBlockStatusCallback(RTDVMVOLUME hVol,
+ PFNDVMVOLUMEQUERYBLOCKSTATUS pfnQueryBlockStatus,
+ void *pvUser);
+
+/**
+ * Get the size of a volume in bytes.
+ *
+ * @returns Size of the volume in bytes or 0 on failure.
+ * @param hVol The volume handle.
+ */
+RTDECL(uint64_t) RTDvmVolumeGetSize(RTDVMVOLUME hVol);
+
+/**
+ * Gets the name of the volume if supported.
+ *
+ * @returns IPRT status code.
+ * @param hVol The volume handle.
+ * @param ppszVolName Where to store the name of the volume on success.
+ * The string must be freed with RTStrFree().
+ */
+RTDECL(int) RTDvmVolumeQueryName(RTDVMVOLUME hVol, char **ppszVolName);
+
+/**
+ * Get the volume type of the volume if supported.
+ *
+ * @returns The volume type on success, DVMVOLTYPE_INVALID if hVol is invalid.
+ * @param hVol The volume handle.
+ */
+RTDECL(RTDVMVOLTYPE) RTDvmVolumeGetType(RTDVMVOLUME hVol);
+
+/**
+ * Get the volume flags of the volume if supported.
+ *
+ * @returns The volume flags or UINT64_MAX on failure.
+ * @param hVol The volume handle.
+ */
+RTDECL(uint64_t) RTDvmVolumeGetFlags(RTDVMVOLUME hVol);
+
+/**
+ * Queries the range of the given volume on the underlying medium.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_NOT_SUPPORTED if the DVMVOLUME_F_CONTIGUOUS flag is not returned by RTDvmVolumeGetFlags().
+ * @param hVol The volume handle.
+ * @param poffStart Where to store the start offset in bytes on the underlying medium.
+ * @param poffLast Where to store the last offset in bytes on the underlying medium (inclusive).
+ */
+RTDECL(int) RTDvmVolumeQueryRange(RTDVMVOLUME hVol, uint64_t *poffStart, uint64_t *poffLast);
+
+/**
+ * Returns the partition/whatever table location of the volume.
+ *
+ * For volume format with a single table, like GPT and BSD-labels, it will
+ * return the location of that table. Though for GPT, the fake MBR will not be
+ * included.
+ *
+ * For logical (extended) MBR-style volumes, this will return the location of
+ * the extended partition table. For primary volumes the MBR location is
+ * returned. The special MBR case is why this operation is done on the volume
+ * rather than the volume manager.
+ *
+ * Using RTDvmVolumeGetIndex with RTDVMVOLIDX_IN_PART_TABLE should get you
+ * the index in the table returned by this function.
+ *
+ * @returns IPRT status code.
+ * @param hVol The volume handle.
+ * @param poffTable Where to return the byte offset on the underlying
+ * media of the (partition/volume/whatever) table.
+ * @param pcbTable Where to return the table size in bytes. (This does
+ * not include any alignment padding or such, just
+ * padding up to sector/block size.)
+ */
+RTDECL(int) RTDvmVolumeQueryTableLocation(RTDVMVOLUME hVol, uint64_t *poffTable, uint64_t *pcbTable);
+
+/**
+ * RTDvmVolumeGetIndex indexes.
+ */
+typedef enum RTDVMVOLIDX
+{
+ /** Invalid zero value. */
+ RTDVMVOLIDX_INVALID = 0,
+ /** Index matching the host's volume numbering.
+ * This is a pseudo index, that gets translated to one of the others depending
+ * on which host we're running on. */
+ RTDVMVOLIDX_HOST,
+ /** Only consider user visible ones, i.e. don't count MBR extended partition
+ * entries and such like. */
+ RTDVMVOLIDX_USER_VISIBLE,
+ /** Index when all volumes, user visible, hidden, special, whatever ones are
+ * included.
+ *
+ * For MBR this is 1-based index where all primary entires are included whether
+ * in use or not. Only non-empty entries in extended tables are counted, though
+ * the forward link is included. */
+ RTDVMVOLIDX_ALL,
+ /** The raw index within the partition/volume/whatever table. This have a kind
+ * of special meaning to MBR, where there are multiple tables. */
+ RTDVMVOLIDX_IN_TABLE,
+ /** Follows the linux /dev/sdaX convention as closely as absolutely possible. */
+ RTDVMVOLIDX_LINUX,
+ /** End of valid indexes. */
+ RTDVMVOLIDX_END,
+ /** Make sure the type is 32-bit. */
+ RTDVMVOLIDX_32BIT_HACK = 0x7fffffff
+} RTDVMVOLIDX;
+
+/**
+ * Gets the tiven index for the specified volume.
+ *
+ * @returns The requested index, UINT32_MAX on failure.
+ * @param hVol The volume handle.
+ * @param enmIndex Which kind of index to get for the volume.
+ */
+RTDECL(uint32_t) RTDvmVolumeGetIndex(RTDVMVOLUME hVol, RTDVMVOLIDX enmIndex);
+
+/**
+ * Volume properties queriable via RTDvmVolumeQueryProp.
+ *
+ * @note Integer values can typically be queried in multiple sizes. This is
+ * handled by the frontend code. The format specific backends only
+ * have to handle the smallest allowed size.
+ */
+typedef enum RTDVMVOLPROP
+{
+ /** Customary invalid zero value. */
+ RTDVMVOLPROP_INVALID = 0,
+ /** unsigned[16,32,64]: MBR first cylinder (0-based, CHS). */
+ RTDVMVOLPROP_MBR_FIRST_CYLINDER,
+ /** unsigned[8,16,32,64]: MBR first head (0-based, CHS). */
+ RTDVMVOLPROP_MBR_FIRST_HEAD,
+ /** unsigned[8,16,32,64]: MBR first sector (1-based, CHS). */
+ RTDVMVOLPROP_MBR_FIRST_SECTOR,
+ /** unsigned[16,32,64]: MBR last cylinder (0-based, CHS). */
+ RTDVMVOLPROP_MBR_LAST_CYLINDER,
+ /** unsigned[8,16,32,64]: MBR last head (0-based, CHS). */
+ RTDVMVOLPROP_MBR_LAST_HEAD,
+ /** unsigned[8,16,32,64]: MBR last sector (1-based, CHS). */
+ RTDVMVOLPROP_MBR_LAST_SECTOR,
+ /** unsigned[8,16,32,64]: MBR partition type. */
+ RTDVMVOLPROP_MBR_TYPE,
+ /** RTUUID: GPT volume type. */
+ RTDVMVOLPROP_GPT_TYPE,
+ /** RTUUID: GPT volume UUID. */
+ RTDVMVOLPROP_GPT_UUID,
+ /** End of valid values. */
+ RTDVMVOLPROP_END,
+ /** Make sure the type is 32-bit. */
+ RTDVMVOLPROP_32BIT_HACK = 0x7fffffff
+} RTDVMVOLPROP;
+
+/**
+ * Query a generic volume property.
+ *
+ * This is an extensible interface for retrieving mostly format specific
+ * information, or information that's not commonly used. (It's modeled after
+ * RTLdrQueryPropEx.)
+ *
+ * @returns IPRT status code.
+ * @retval VERR_NOT_SUPPORTED if the property query isn't supported (either all
+ * or that specific property). The caller must handle this result.
+ * @retval VERR_NOT_FOUND is currently not returned, but intended for cases
+ * where it wasn't present in the tables.
+ * @retval VERR_INVALID_FUNCTION if the @a enmProperty value is wrong.
+ * @retval VERR_INVALID_PARAMETER if the fixed buffer size is wrong. Correct
+ * size in @a *pcbBuf.
+ * @retval VERR_BUFFER_OVERFLOW if the property doesn't have a fixed size
+ * buffer and the buffer isn't big enough. Correct size in @a *pcbBuf.
+ * @retval VERR_INVALID_HANDLE if the handle is invalid.
+ * @param hVol Handle to the volume.
+ * @param enmProperty The property to query.
+ * @param pvBuf Pointer to the input / output buffer. In most cases
+ * it's only used for returning data.
+ * @param cbBuf The size of the buffer.
+ * @param pcbBuf Where to return the amount of data returned. On
+ * buffer size errors, this is set to the correct size.
+ * Optional.
+ * @sa RTDvmVolumeGetPropU64
+ */
+RTDECL(int) RTDvmVolumeQueryProp(RTDVMVOLUME hVol, RTDVMVOLPROP enmProperty, void *pvBuf, size_t cbBuf, size_t *pcbBuf);
+
+/**
+ * Wrapper around RTDvmVolumeQueryProp for simplifying getting unimportant
+ * integer properties.
+ *
+ * @returns The property value if supported and found, the default value if not.
+ * Errors other than VERR_NOT_SUPPORTED and VERR_NOT_FOUND are
+ * asserted.
+ * @param hVol Handle to the volume.
+ * @param enmProperty The property to query.
+ * @param uDefault The value to return on error.
+ * @sa RTDvmVolumeQueryProp
+ */
+RTDECL(uint64_t) RTDvmVolumeGetPropU64(RTDVMVOLUME hVol, RTDVMVOLPROP enmProperty, uint64_t uDefault);
+
+/**
+ * Reads data from the given volume.
+ *
+ * @returns IPRT status code.
+ * @param hVol The volume handle.
+ * @param off Where to start reading from - 0 is the beginning of
+ * the volume.
+ * @param pvBuf Where to store the read data.
+ * @param cbRead How many bytes to read.
+ */
+RTDECL(int) RTDvmVolumeRead(RTDVMVOLUME hVol, uint64_t off, void *pvBuf, size_t cbRead);
+
+/**
+ * Writes data to the given volume.
+ *
+ * @returns IPRT status code.
+ * @param hVol The volume handle.
+ * @param off Where to start writing to - 0 is the beginning of
+ * the volume.
+ * @param pvBuf The data to write.
+ * @param cbWrite How many bytes to write.
+ */
+RTDECL(int) RTDvmVolumeWrite(RTDVMVOLUME hVol, uint64_t off, const void *pvBuf, size_t cbWrite);
+
+/**
+ * Returns the description of a given volume type.
+ *
+ * @returns The description of the type.
+ * @param enmVolType The volume type.
+ */
+RTDECL(const char *) RTDvmVolumeTypeGetDescr(RTDVMVOLTYPE enmVolType);
+
+/**
+ * Creates an VFS file from a volume handle.
+ *
+ * @returns IPRT status code.
+ * @param hVol The volume handle.
+ * @param fOpen RTFILE_O_XXX.
+ * @param phVfsFileOut Where to store the VFS file handle on success.
+ */
+RTDECL(int) RTDvmVolumeCreateVfsFile(RTDVMVOLUME hVol, uint64_t fOpen, PRTVFSFILE phVfsFileOut);
+
+RT_C_DECLS_END
+
+/** @} */
+
+#endif /* !IPRT_INCLUDED_dvm_h */
+
diff --git a/include/iprt/efi.h b/include/iprt/efi.h
new file mode 100644
index 00000000..30bb4475
--- /dev/null
+++ b/include/iprt/efi.h
@@ -0,0 +1,299 @@
+/** @file
+ * IPRT - EFI related utilities.
+ */
+
+/*
+ * Copyright (C) 2021-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_efi_h
+#define IPRT_INCLUDED_efi_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+#include <iprt/time.h>
+#include <iprt/vfs.h>
+
+#include <iprt/formats/efi-common.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_efi RTEfi - EFI utilities
+ * @ingroup grp_rt
+ * @{
+ */
+
+
+#ifdef IN_RING3
+
+/**
+ * Converts an EFI time to a time spec (UTC).
+ *
+ * @returns pTimeSpec on success.
+ * @returns NULL if the pEfiTime data is invalid.
+ * @param pTimeSpec Where to store the converted time.
+ * @param pEfiTime Pointer to the EFI time struct.
+ */
+RTDECL(PRTTIMESPEC) RTEfiTimeToTimeSpec(PRTTIMESPEC pTimeSpec, PCEFI_TIME pEfiTime);
+
+
+/**
+ * Converts a time spec (UTC) to an EFI time.
+ *
+ * @returns pEfiTime on success.
+ * @returns NULL if the pTimeSpec data is invalid.
+ * @param pEfiTime Pointer to the EFI time struct.
+ * @param pTimeSpec The time spec to convert.
+ */
+RTDECL(PEFI_TIME) RTEfiTimeFromTimeSpec(PEFI_TIME pEfiTime, PCRTTIMESPEC pTimeSpec);
+
+
+/**
+ * Converts the given EFI GUID to the IPRT UUID representation.
+ *
+ * @returns pUuid.
+ * @param pUuid Where to store the converted GUID.
+ * @param pEfiGuid The EFI GUID to convert.
+ */
+RTDECL(PRTUUID) RTEfiGuidToUuid(PRTUUID pUuid, PCEFI_GUID pEfiGuid);
+
+
+/**
+ * Converts the given EFI GUID to the IPRT UUID representation.
+ *
+ * @returns pEfiGuid.
+ * @param pEfiGuid Where to store the converted UUID.
+ * @param pUuid The UUID to convert.
+ */
+RTDECL(PEFI_GUID) RTEfiGuidFromUuid(PEFI_GUID pEfiGuid, PCRTUUID pUuid);
+
+
+/**
+ * Compares two EFI GUID values.
+ *
+ * @returns 0 if eq, < 0 or > 0.
+ * @param pGuid1 First value to compare.
+ * @param pGuid2 Second value to compare.
+ */
+RTDECL(int) RTEfiGuidCompare(PCEFI_GUID pGuid1, PCEFI_GUID pGuid2);
+
+
+/**
+ * Opens an EFI variable store.
+ *
+ * @returns IPRT status code.
+ * @param hVfsFileIn The file or device backing the store.
+ * @param fMntFlags RTVFSMNT_F_XXX.
+ * @param fVarStoreFlags Reserved, MBZ.
+ * @param phVfs Where to return the virtual file system handle.
+ * @param pErrInfo Where to return additional error information.
+ */
+RTDECL(int) RTEfiVarStoreOpenAsVfs(RTVFSFILE hVfsFileIn, uint32_t fMntFlags, uint32_t fVarStoreFlags, PRTVFS phVfs, PRTERRINFO pErrInfo);
+
+
+/** @name RTEFIVARSTORE_CREATE_F_XXX - RTEfiVarStoreCreate flags
+ * @{ */
+/** Use default options. */
+#define RTEFIVARSTORE_CREATE_F_DEFAULT UINT32_C(0)
+/** Don't create a fault tolerant write working space.
+ * The default is to create one reducing the size of the variable store. */
+#define RTEFIVARSTORE_CREATE_F_NO_FTW_WORKING_SPACE RT_BIT_32(0)
+/** Mask containing all valid flags. */
+#define RTEFIVARSTORE_CREATE_F_VALID_MASK UINT32_C(0x00000001)
+/** @} */
+
+/**
+ * Creates a new EFI variable store.
+ *
+ * @returns IRPT status code.
+ * @param hVfsFile The store file.
+ * @param offStore The offset into @a hVfsFile of the file.
+ * Typically 0.
+ * @param cbStore The size of the variable store. Pass 0 if the rest of
+ * hVfsFile should be used. The remaining space for variables
+ * will be less because of some metadata overhead.
+ * @param fFlags See RTEFIVARSTORE_F_XXX.
+ * @param cbBlock The logical block size.
+ * @param pErrInfo Additional error information, maybe. Optional.
+ */
+RTDECL(int) RTEfiVarStoreCreate(RTVFSFILE hVfsFile, uint64_t offStore, uint64_t cbStore, uint32_t fFlags, uint32_t cbBlock,
+ PRTERRINFO pErrInfo);
+
+
+/**
+ * EFI signature type.
+ */
+typedef enum RTEFISIGTYPE
+{
+ /** Invalid type, do not use. */
+ RTEFISIGTYPE_INVALID = 0,
+ /** First valid signature type. */
+ RTEFISIGTYPE_FIRST_VALID,
+ /** Signature contains a SHA256 hash. */
+ RTEFISIGTYPE_SHA256 = RTEFISIGTYPE_FIRST_VALID,
+ /** Signature contains a RSA2048 key (only the modulus in big endian form,
+ * the exponent is always 65537/0x10001). */
+ RTEFISIGTYPE_RSA2048,
+ /** Signature contains a RSA2048 signature of a SHA256 hash. */
+ RTEFISIGTYPE_RSA2048_SHA256,
+ /** Signature contains a SHA1 hash. */
+ RTEFISIGTYPE_SHA1,
+ /** Signature contains a RSA2048 signature of a SHA1 hash. */
+ RTEFISIGTYPE_RSA2048_SHA1,
+ /** Signature contains a DER encoded X.509 certificate. */
+ RTEFISIGTYPE_X509,
+ /** First invalid type (do not use). */
+ RTEFISIGTYPE_FIRST_INVALID,
+ /** 32bit blowup hack.*/
+ RTEFISIGTYPE_32BIT_HACK = 0x7fffffff
+} RTEFISIGTYPE;
+
+
+/**
+ * EFI signature database enumeration callback.
+ *
+ * @returns IPRT status code, any status code other than VINF_SUCCESS will abort the enumeration.
+ * @param hEfiSigDb Handle to the EFI signature database this callback is called on.
+ * @param enmSigType The signature type.
+ * @param pUuidOwner Signature owner UUID.
+ * @param pvSig The signature data (dependent on the type).
+ * @param cbSig Size of the signature in bytes.
+ * @param pvUser Opaque user data passed in RTEfiSigDbEnum().
+ */
+typedef DECLCALLBACKTYPE(int, FNRTEFISIGDBENUMSIG,(RTEFISIGDB hEfiSigDb, RTEFISIGTYPE enmSigType, PCRTUUID pUuidOwner,
+ const void *pvSig, size_t cbSig, void *pvUser));
+/** Pointer to a EFI signature database enumeration callback. */
+typedef FNRTEFISIGDBENUMSIG *PFNRTEFISIGDBENUMSIG;
+
+
+/**
+ * Creates an empty EFI signature database.
+ *
+ * @returns IPRT status code.
+ * @param phEfiSigDb Where to store the handle to the empty EFI signature database on success.
+ */
+RTDECL(int) RTEfiSigDbCreate(PRTEFISIGDB phEfiSigDb);
+
+
+/**
+ * Destroys the given EFI signature database handle.
+ *
+ * @returns IPRT status code.
+ * @param hEfiSigDb The EFI signature database handle to destroy.
+ */
+RTDECL(int) RTEfiSigDbDestroy(RTEFISIGDB hEfiSigDb);
+
+
+/**
+ * Adds the signatures from an existing signature database contained in the given file.
+ *
+ * @returns IPRT status code.
+ * @param hEfiSigDb The EFI signature database handle.
+ * @param hVfsFileIn The file handle containing the existing signature database.
+ */
+RTDECL(int) RTEfiSigDbAddFromExistingDb(RTEFISIGDB hEfiSigDb, RTVFSFILE hVfsFileIn);
+
+
+/**
+ * Adds a new signature to the given signature database from the given file.
+ *
+ * @returns IPRT status code.
+ * @param hEfiSigDb The EFI signature database handle.
+ * @param enmSigType Type of the signature.
+ * @param pUuidOwner The UUID of the signature owner.
+ * @param hVfsFileIn File handle containing the signature data.
+ */
+RTDECL(int) RTEfiSigDbAddSignatureFromFile(RTEFISIGDB hEfiSigDb, RTEFISIGTYPE enmSigType, PCRTUUID pUuidOwner, RTVFSFILE hVfsFileIn);
+
+
+/**
+ * Adds a new signature to the given signature database from the given buffer.
+ *
+ * @returns IPRT status code.
+ * @param hEfiSigDb The EFI signature database handle.
+ * @param enmSigType Type of the signature.
+ * @param pUuidOwner The UUID of the signature owner.
+ * @param pvBuf Pointer to the signature data.
+ * @param cbBuf Size of the signature data in bytes.
+ */
+RTDECL(int) RTEfiSigDbAddSignatureFromBuf(RTEFISIGDB hEfiSigDb, RTEFISIGTYPE enmSigType, PCRTUUID pUuidOwner,
+ const void *pvBuf, size_t cbBuf);
+
+
+/**
+ * Writes the given EFI signature database to the given file.
+ *
+ * @returns IPRT status code.
+ * @param hEfiSigDb The EFI signature database handle.
+ * @param hVfsFileOut The file handle to write the signature database to.
+ */
+RTDECL(int) RTEfiSigDbWriteToFile(RTEFISIGDB hEfiSigDb, RTVFSFILE hVfsFileOut);
+
+
+/**
+ * Enumerate all signatures in the given EFI signature database.
+ *
+ * @returns IPRT status code.
+ * @param hEfiSigDb The EFI signature database handle.
+ * @param pfnEnumSig The callback to call for each signature.
+ * @param pvUser Opaque user data to pass to the callback.
+ */
+RTDECL(int) RTEfiSigDbEnum(RTEFISIGDB hEfiSigDb, PFNRTEFISIGDBENUMSIG pfnEnumSig, void *pvUser);
+
+
+/**
+ * Returns a human readable string of the given signature type.
+ *
+ * @returns Human readable string.
+ * @param enmSigType The signature type.
+ */
+RTDECL(const char *) RTEfiSigDbTypeStringify(RTEFISIGTYPE enmSigType);
+
+
+/**
+ * Returns a pointer to the EFI GUID identifying the given signature type.
+ *
+ * @returns Pointer to the EFI GUID.
+ * @param enmSigType The signature type.
+ */
+RTDECL(PCEFI_GUID) RTEfiSigDbTypeGetGuid(RTEFISIGTYPE enmSigType);
+
+#endif /* IN_RING3 */
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_efi_h */
+
diff --git a/include/iprt/env.h b/include/iprt/env.h
new file mode 100644
index 00000000..3b3d13b2
--- /dev/null
+++ b/include/iprt/env.h
@@ -0,0 +1,473 @@
+/** @file
+ * IPRT - Process Environment Strings.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_env_h
+#define IPRT_INCLUDED_env_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_env RTEnv - Process Environment Strings
+ * @ingroup grp_rt
+ * @{
+ */
+
+#ifdef IN_RING3
+
+/** Special handle that indicates the default process environment. */
+#define RTENV_DEFAULT ((RTENV)~(uintptr_t)0)
+
+/**
+ * Creates an empty environment block.
+ *
+ * @returns IPRT status code. Typical error is VERR_NO_MEMORY.
+ *
+ * @param pEnv Where to store the handle of the new environment block.
+ */
+RTDECL(int) RTEnvCreate(PRTENV pEnv);
+
+/**
+ * Creates an empty environment block.
+ *
+ * @returns IPRT status code. Typical error is VERR_NO_MEMORY.
+ *
+ * @param phEnv Where to store the handle of the new environment block.
+ * @param fFlags Zero or more RTENV_CREATE_F_XXX flags.
+ */
+RTDECL(int) RTEnvCreateEx(PRTENV phEnv, uint32_t fFlags);
+
+/** @name RTENV_CREATE_F_XXX - Flags for RTEnvCreateEx() and RTEnvCreateChangeRecordEx()
+ * @{ */
+/** Allow equal ('=') as the first character of a variable name.
+ * This is useful for compatibility with Windows' handling of CWD on drives, as
+ * these are stored on the form "=D:=D:\tmp\asdf". It is only really useful
+ * for creating environment blocks for processes and such, since the CRT doesn't
+ * allow us to apply it directly to the process enviornment. */
+#define RTENV_CREATE_F_ALLOW_EQUAL_FIRST_IN_VAR RT_BIT_32(0)
+/** Valid flags. */
+#define RTENV_CREATE_F_VALID_MASK UINT32_C(0x00000001)
+/** @} */
+
+/**
+ * Creates an environment block and fill it with variables from the given
+ * environment array.
+ *
+ * @returns IPRT status code.
+ * @retval VWRN_ENV_NOT_FULLY_TRANSLATED may be returned when passing
+ * RTENV_DEFAULT and one or more of the environment variables have
+ * codeset incompatibilities. The problematic variables will be
+ * ignored and not included in the clone, thus the clone will have
+ * fewer variables.
+ * @retval VERR_NO_MEMORY
+ * @retval VERR_NO_STR_MEMORY
+ * @retval VERR_INVALID_HANDLE
+ *
+ * @param pEnv Where to store the handle of the new environment block.
+ * @param EnvToClone The environment to clone.
+ */
+RTDECL(int) RTEnvClone(PRTENV pEnv, RTENV EnvToClone);
+
+/**
+ * Creates an environment block from an UTF-16 environment raw block.
+ *
+ * This is the reverse of RTEnvQueryUtf16Block.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_NO_MEMORY
+ * @retval VERR_NO_STR_MEMORY
+ *
+ * @param phEnv Where to store the handle of the new environment block.
+ * @param pwszzBlock List of zero terminated string end with a zero length
+ * string (or two zero terminators if you prefer). The
+ * strings are on the RTPutEnv format (VAR=VALUE), except
+ * they are all expected to include an equal sign.
+ * @param fFlags Flags served for the future.
+ */
+RTDECL(int) RTEnvCloneUtf16Block(PRTENV phEnv, PCRTUTF16 pwszzBlock, uint32_t fFlags);
+
+/**
+ * Destroys an environment block.
+ *
+ * @returns IPRT status code.
+ *
+ * @param Env Environment block handle.
+ * Both RTENV_DEFAULT and NIL_RTENV are silently ignored.
+ */
+RTDECL(int) RTEnvDestroy(RTENV Env);
+
+/**
+ * Resets the environment block to contain zero variables.
+ *
+ * @returns IPRT status code.
+ *
+ * @param hEnv Environment block handle. RTENV_DEFAULT is not supported.
+ */
+RTDECL(int) RTEnvReset(RTENV hEnv);
+
+/**
+ * Get the execve/spawnve/main envp.
+ *
+ * All returned strings are in the current process' codepage.
+ * This array is only valid until the next RTEnv call.
+ *
+ * @returns Pointer to the raw array of environment variables.
+ * @returns NULL if Env is NULL or invalid.
+ *
+ * @param Env Environment block handle.
+ *
+ * @note This is NOT available on Windows. It is also not a stable export
+ * and will hopefully be replaced before long (see todo).
+ *
+ * @todo This needs to change to return a copy of the env vars like
+ * RTEnvQueryUtf16Block does!
+ */
+RTDECL(char const * const *) RTEnvGetExecEnvP(RTENV Env);
+
+/**
+ * Get a sorted, UTF-16 environment block for CreateProcess.
+ *
+ * @returns IPRT status code.
+ *
+ * @param hEnv Environment block handle.
+ * @param ppwszzBlock Where to return the environment block. This must be
+ * freed by calling RTEnvFreeUtf16Block.
+ */
+RTDECL(int) RTEnvQueryUtf16Block(RTENV hEnv, PRTUTF16 *ppwszzBlock);
+
+/**
+ * Frees an environment block returned by RTEnvGetUtf16Block().
+ *
+ * @param pwszzBlock What RTEnvGetUtf16Block returned. NULL is ignored.
+ */
+RTDECL(void) RTEnvFreeUtf16Block(PRTUTF16 pwszzBlock);
+
+/**
+ * Get a sorted, UTF-8 environment block.
+ *
+ * The environment block is a sequence of putenv formatted ("NAME=VALUE" or
+ * "NAME") zero terminated strings ending with an empty string (i.e. last string
+ * has two zeros).
+ *
+ * @returns IPRT status code.
+ *
+ * @param hEnv Environment block handle.
+ * @param fSorted Whether to sort it, this will affect @a hEnv.
+ * @param ppszzBlock Where to return the environment block. This must be
+ * freed by calling RTEnvFreeUtf8Block.
+ * @param pcbBlock Where to return the size of the block. Optional.
+ */
+RTDECL(int) RTEnvQueryUtf8Block(RTENV hEnv, bool fSorted, char **ppszzBlock, size_t *pcbBlock);
+
+/**
+ * Frees an environment block returned by RTEnvGetUtf8Block().
+ *
+ * @param pszzBlock What RTEnvGetUtf8Block returned. NULL is ignored.
+ */
+RTDECL(void) RTEnvFreeUtf8Block(char *pszzBlock);
+
+/**
+ * Checks if an environment variable exists in the default environment block.
+ *
+ * @returns IPRT status code. Typical error is VERR_NO_MEMORY.
+ *
+ * @param pszVar The environment variable name.
+ * @remark WARNING! The current implementation does not perform the appropriate
+ * codeset conversion. We'll figure this out when it becomes necessary.
+ */
+RTDECL(bool) RTEnvExist(const char *pszVar);
+RTDECL(bool) RTEnvExistsBad(const char *pszVar);
+RTDECL(bool) RTEnvExistsUtf8(const char *pszVar);
+
+/**
+ * Checks if an environment variable exists in a specific environment block.
+ *
+ * @returns IPRT status code. Typical error is VERR_NO_MEMORY.
+ *
+ * @param Env The environment handle.
+ * @param pszVar The environment variable name.
+ */
+RTDECL(bool) RTEnvExistEx(RTENV Env, const char *pszVar);
+
+/**
+ * Gets an environment variable from the default environment block. (getenv).
+ *
+ * The caller is responsible for ensuring that nobody changes the environment
+ * while it's using the returned string pointer!
+ *
+ * @returns Pointer to read only string on success, NULL if the variable wasn't found.
+ *
+ * @param pszVar The environment variable name.
+ *
+ * @remark WARNING! The current implementation does not perform the appropriate
+ * codeset conversion. We'll figure this out when it becomes necessary.
+ */
+RTDECL(const char *) RTEnvGet(const char *pszVar);
+RTDECL(const char *) RTEnvGetBad(const char *pszVar);
+RTDECL(int) RTEnvGetUtf8(const char *pszVar, char *pszValue, size_t cbValue, size_t *pcchActual);
+
+/**
+ * Gets an environment variable in a specific environment block.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_ENV_VAR_NOT_FOUND if the variable was not found.
+ * @retval VERR_ENV_VAR_UNSET if @a hEnv is an environment change record and
+ * the variable has been recorded as unset.
+ *
+ * @param hEnv The environment handle.
+ * @param pszVar The environment variable name.
+ * @param pszValue Where to put the buffer.
+ * @param cbValue The size of the value buffer.
+ * @param pcchActual Returns the actual value string length. Optional.
+ */
+RTDECL(int) RTEnvGetEx(RTENV hEnv, const char *pszVar, char *pszValue, size_t cbValue, size_t *pcchActual);
+
+/**
+ * Puts an variable=value string into the environment (putenv).
+ *
+ * @returns IPRT status code. Typical error is VERR_NO_MEMORY.
+ *
+ * @param pszVarEqualValue The variable '=' value string. If the value and '=' is
+ * omitted, the variable is removed from the environment.
+ *
+ * @remark Don't assume the value is copied.
+ * @remark WARNING! The current implementation does not perform the appropriate
+ * codeset conversion. We'll figure this out when it becomes necessary.
+ */
+RTDECL(int) RTEnvPut(const char *pszVarEqualValue);
+RTDECL(int) RTEnvPutBad(const char *pszVarEqualValue);
+RTDECL(int) RTEnvPutUtf8(const char *pszVarEqualValue);
+
+/**
+ * Puts a copy of the passed in 'variable=value' string into the environment block.
+ *
+ * @returns IPRT status code. Typical error is VERR_NO_MEMORY.
+ *
+ * @param Env Handle of the environment block.
+ * @param pszVarEqualValue The variable '=' value string. If the value and '=' is
+ * omitted, the variable is removed from the environment.
+ */
+RTDECL(int) RTEnvPutEx(RTENV Env, const char *pszVarEqualValue);
+
+/**
+ * Sets an environment variable (setenv(,,1)).
+ *
+ * @returns IPRT status code. Typical error is VERR_NO_MEMORY.
+ *
+ * @param pszVar The environment variable name.
+ * @param pszValue The environment variable value.
+ *
+ * @remark WARNING! The current implementation does not perform the appropriate
+ * codeset conversion. We'll figure this out when it becomes necessary.
+ */
+RTDECL(int) RTEnvSet(const char *pszVar, const char *pszValue);
+RTDECL(int) RTEnvSetBad(const char *pszVar, const char *pszValue);
+RTDECL(int) RTEnvSetUtf8(const char *pszVar, const char *pszValue);
+
+/**
+ * Sets an environment variable (setenv(,,1)).
+ *
+ * @returns IPRT status code. Typical error is VERR_NO_MEMORY.
+ *
+ * @param Env The environment handle.
+ * @param pszVar The environment variable name.
+ * @param pszValue The environment variable value.
+ */
+RTDECL(int) RTEnvSetEx(RTENV Env, const char *pszVar, const char *pszValue);
+
+/**
+ * Removes an environment variable from the default environment block.
+ *
+ * @returns IPRT status code.
+ * @returns VINF_ENV_VAR_NOT_FOUND if the variable was not found.
+ *
+ * @param pszVar The environment variable name.
+ *
+ * @remark WARNING! The current implementation does not perform the appropriate
+ * codeset conversion. We'll figure this out when it becomes necessary.
+ */
+RTDECL(int) RTEnvUnset(const char *pszVar);
+RTDECL(int) RTEnvUnsetBad(const char *pszVar);
+RTDECL(int) RTEnvUnsetUtf8(const char *pszVar);
+
+/**
+ * Removes an environment variable from the specified environment block.
+ *
+ * @returns IPRT status code.
+ * @returns VINF_ENV_VAR_NOT_FOUND if the variable was not found.
+ *
+ * @param Env The environment handle.
+ * @param pszVar The environment variable name.
+ */
+RTDECL(int) RTEnvUnsetEx(RTENV Env, const char *pszVar);
+
+
+/**
+ * Returns the value of a environment variable from the default
+ * environment block in a heap buffer.
+ *
+ * @returns Pointer to a string containing the value, free it using RTStrFree.
+ * NULL if the variable was not found or we're out of memory.
+ *
+ * @param pszVar The environment variable name (UTF-8).
+ */
+RTDECL(char *) RTEnvDup(const char *pszVar);
+
+/**
+ * Duplicates the value of a environment variable if it exists.
+ *
+ * @returns Pointer to a string containing the value, free it using RTStrFree.
+ * NULL if the variable was not found or we're out of memory.
+ *
+ * @param Env The environment handle.
+ * @param pszVar The environment variable name.
+ */
+RTDECL(char *) RTEnvDupEx(RTENV Env, const char *pszVar);
+
+/**
+ * Counts the variables in the environment.
+ *
+ * @returns Number of variables in the environment. UINT32_MAX on error.
+ * @param hEnv The environment handle.
+ * RTENV_DEFAULT is currently not accepted.
+ */
+RTDECL(uint32_t) RTEnvCountEx(RTENV hEnv);
+
+/**
+ * Queries an environment variable by it's index.
+ *
+ * This can be used together with RTEnvCount to enumerate the environment block.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_ENV_VAR_NOT_FOUND if the index is out of bounds, output buffers
+ * untouched.
+ * @retval VERR_BUFFER_OVERFLOW if one of the buffers are too small. We'll
+ * fill it with as much we can in RTStrCopy fashion.
+ * @retval VINF_ENV_VAR_UNSET if @a hEnv is an environment change record and
+ * the variable at @a iVar is recorded as being unset.
+ *
+ * @param hEnv The environment handle.
+ * RTENV_DEFAULT is currently not accepted.
+ * @param iVar The variable index.
+ * @param pszVar Variable name buffer.
+ * @param cbVar The size of the variable name buffer.
+ * @param pszValue Value buffer.
+ * @param cbValue The size of the value buffer.
+ */
+RTDECL(int) RTEnvGetByIndexEx(RTENV hEnv, uint32_t iVar, char *pszVar, size_t cbVar, char *pszValue, size_t cbValue);
+
+/**
+ * Leaner and meaner version of RTEnvGetByIndexEx.
+ *
+ * This can be used together with RTEnvCount to enumerate the environment block.
+ *
+ * Use with caution as the returned pointer may change by the next call using
+ * the environment handle. Please only use this API in cases where there is no
+ * chance of races.
+ *
+ * @returns Pointer to the internal environment variable=value string on
+ * success. If @a hEnv is an environment change recordthe string may
+ * also be on the "variable" form, representing an unset operation. Do
+ * NOT change this string, it is read only!
+ *
+ * If the index is out of range on the environment handle is invalid,
+ * NULL is returned.
+ *
+ * @param hEnv The environment handle.
+ * RTENV_DEFAULT is currently not accepted.
+ * @param iVar The variable index.
+ */
+RTDECL(const char *) RTEnvGetByIndexRawEx(RTENV hEnv, uint32_t iVar);
+
+
+/**
+ * Creates an empty environment change record.
+ *
+ * This is a special environment for use with RTEnvApplyChanges and similar
+ * purposes. The
+ *
+ * @returns IPRT status code. Typical error is VERR_NO_MEMORY.
+ *
+ * @param phEnv Where to store the handle of the new environment block.
+ */
+RTDECL(int) RTEnvCreateChangeRecord(PRTENV phEnv);
+
+/**
+ * Extended version of RTEnvCreateChangeRecord that takes flags.
+ *
+ * @returns IPRT status code. Typical error is VERR_NO_MEMORY.
+ *
+ * @param phEnv Where to store the handle of the new environment block.
+ * @param fFlags Zero or more RTENV_CREATE_F_XXX flags.
+ */
+RTDECL(int) RTEnvCreateChangeRecordEx(PRTENV phEnv, uint32_t fFlags);
+
+/**
+ * Checks if @a hEnv is an environment change record.
+ *
+ * @returns true if it is, false if it's not or if the handle is invalid.
+ * @param hEnv The environment handle.
+ * @sa RTEnvCreateChangeRecord.
+ */
+RTDECL(bool) RTEnvIsChangeRecord(RTENV hEnv);
+
+/**
+ * Applies changes from one environment onto another.
+ *
+ * If @a hEnvChanges is a normal environment, its content is just added to @a
+ * hEnvDst, where variables in the destination can only be overwritten. However
+ * if @a hEnvChanges is a change record environment, variables in the
+ * destination can also be removed.
+ *
+ * @returns IPRT status code. Typical error is VERR_NO_MEMORY.
+ * @param hEnvDst The destination environment.
+ * @param hEnvChanges Handle to the environment containig the changes to
+ * apply. As said, especially useful if it's a environment
+ * change record. RTENV_DEFAULT is not supported here.
+ */
+RTDECL(int) RTEnvApplyChanges(RTENV hEnvDst, RTENV hEnvChanges);
+
+#endif /* IN_RING3 */
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_env_h */
+
diff --git a/include/iprt/err.h b/include/iprt/err.h
new file mode 100644
index 00000000..cfa1d115
--- /dev/null
+++ b/include/iprt/err.h
@@ -0,0 +1,2823 @@
+/** @file
+ * IPRT - Status Codes.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_err_h
+#define IPRT_INCLUDED_err_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/errcore.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.
+ *
+ * @{
+ */
+
+/** @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 */
+
+/** Success. */
+#define VINF_SUCCESS 0
+
+/** @name Misc. Status Codes
+ * @{
+ */
+/** 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)
+/** The request function is not implemented. */
+#define VINF_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
+/** Already initialized. */
+#define VERR_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)
+/** Wrong type. */
+#define VWRN_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)
+/** Wrong parameter count. */
+#define VERR_WRONG_PARAMETER_COUNT (-22415)
+/** Wrong parameter type. */
+#define VERR_WRONG_PARAMETER_TYPE (-22416)
+/** Invalid client ID. */
+#define VERR_INVALID_CLIENT_ID (-22417)
+/** Invalid session ID. */
+#define VERR_INVALID_SESSION_ID (-22418)
+/** Requires process elevation (UAC). */
+#define VERR_PROC_ELEVATION_REQUIRED (-22419)
+/** Incompatible configuration requested. */
+#define VERR_INCOMPATIBLE_CONFIG (-22420)
+/** String is not terminated within the buffer bounds. */
+#define VERR_NO_STRING_TERMINATOR (-22421)
+/** Empty string. */
+#define VERR_EMPTY_STRING (-22422)
+/** Too many references to an object. */
+#define VERR_TOO_MANY_REFERENCES (-22423)
+/** Returned by RTThreadQueryTerminationStatus to indicate that the thread is
+ * (or should be) terminating. */
+#define VINF_THREAD_IS_TERMINATING (22424)
+/** The thread is terminating. */
+#define VERR_THREAD_IS_TERMINATING (-22424)
+/** Unable to translate one or more of the arguments to the codeset the child
+ * process is expected to use. */
+#define VERR_PROC_NO_ARG_TRANSLATION (-22425)
+/** Floating pointer underflow. */
+#define VERR_FLOAT_UNDERFLOW (-22426)
+/** Floating pointer underflow. */
+#define VWRN_FLOAT_UNDERFLOW (22426)
+/** Floating pointer overflow. */
+#define VERR_FLOAT_OVERFLOW (-22427)
+/** Floating pointer overflow. */
+#define VWRN_FLOAT_OVERFLOW (22427)
+/** @} */
+
+
+/** @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)
+/** The native file handle got stale while it was open. Can occur with
+ * files on network shares when the server is unresponsive. */
+#define VERR_STALE_FILE_HANDLE (-147)
+/** @} */
+
+
+/** @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)
+/** Symbolic link not allowed. */
+#define VERR_SYMLINK_NOT_ALLOWED (-159)
+/** Is a symbolic link. */
+#define VERR_IS_A_SYMLINK (-160)
+/** Is a FIFO. */
+#define VERR_IS_A_FIFO (-161)
+/** Is a socket. */
+#define VERR_IS_A_SOCKET (-162)
+/** Is a block device. */
+#define VERR_IS_A_BLOCK_DEVICE (-163)
+/** Is a character device. */
+#define VERR_IS_A_CHAR_DEVICE (-164)
+/** No media in drive. */
+#define VERR_DRIVE_IS_EMPTY (-165)
+/** @} */
+
+
+/** @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 posted. */
+#define VINF_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)
+/** Winsock init error. */
+#define VERR_NET_INIT_FAILED (-468)
+/** Trying to use too new winsock API. */
+#define VERR_NET_NOT_UNSUPPORTED (-469)
+/** @} */
+
+
+/** @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)
+/** The ELF loader encountered an unterminated string table. */
+#define VERR_LDRELF_UNTERMINATED_STRING_TAB (-641)
+/** 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)
+/** No unwind information was found. */
+#define VERR_DBG_NO_UNWIND_INFO (-694)
+/** No unwind information for the specified location. */
+#define VERR_DBG_UNWIND_INFO_NOT_FOUND (-695)
+/** Malformed unwind information. */
+#define VERR_DBG_MALFORMED_UNWIND_INFO (-696)
+/** @} */
+
+/** @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 Internal Server Error. */
+#define VERR_HTTP_STATUS_SERVER_ERROR (-884)
+/** 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 element separator (| or :). */
+#define VERR_VFS_CHAIN_EXPECTED_SEPARATOR (-22107)
+/** Leading element separator not permitted. */
+#define VERR_VFS_CHAIN_LEADING_SEPARATOR (-22108)
+/** Trailing element separator not permitted. */
+#define VERR_VFS_CHAIN_TRAILING_SEPARATOR (-22109)
+/** The provider is only allowed as the first element. */
+#define VERR_VFS_CHAIN_MUST_BE_FIRST_ELEMENT (-22110)
+/** The provider cannot be the first element. */
+#define VERR_VFS_CHAIN_CANNOT_BE_FIRST_ELEMENT (-22111)
+/** VFS object cast failed. */
+#define VERR_VFS_CHAIN_CAST_FAILED (-22112)
+/** Internal error in the VFS chain code. */
+#define VERR_VFS_CHAIN_IPE (-22113)
+/** VFS chain element provider not found. */
+#define VERR_VFS_CHAIN_PROVIDER_NOT_FOUND (-22114)
+/** VFS chain does not terminate with the desired object type. */
+#define VERR_VFS_CHAIN_FINAL_TYPE_MISMATCH (-22115)
+/** VFS chain element takes no arguments. */
+#define VERR_VFS_CHAIN_NO_ARGS (-22116)
+/** VFS chain element takes exactly one argument. */
+#define VERR_VFS_CHAIN_ONE_ARG (-22117)
+/** VFS chain element expected at most one argument. */
+#define VERR_VFS_CHAIN_AT_MOST_ONE_ARG (-22118)
+/** VFS chain element expected at least one argument. */
+#define VERR_VFS_CHAIN_AT_LEAST_ONE_ARG (-22119)
+/** VFS chain element takes exactly two arguments. */
+#define VERR_VFS_CHAIN_TWO_ARGS (-22120)
+/** VFS chain element expected at least two arguments. */
+#define VERR_VFS_CHAIN_AT_LEAST_TWO_ARGS (-22121)
+/** VFS chain element expected at most two arguments. */
+#define VERR_VFS_CHAIN_AT_MOST_TWO_ARGS (-22122)
+/** VFS chain element takes exactly three arguments. */
+#define VERR_VFS_CHAIN_THREE_ARGS (-22123)
+/** VFS chain element expected at least three arguments. */
+#define VERR_VFS_CHAIN_AT_LEAST_THREE_ARGS (-22124)
+/** VFS chain element expected at most three arguments. */
+#define VERR_VFS_CHAIN_AT_MOST_THREE_ARGS (-22125)
+/** VFS chain element takes exactly four arguments. */
+#define VERR_VFS_CHAIN_FOUR_ARGS (-22126)
+/** VFS chain element expected at least four arguments. */
+#define VERR_VFS_CHAIN_AT_LEAST_FOUR_ARGS (-22127)
+/** VFS chain element expected at most four arguments. */
+#define VERR_VFS_CHAIN_AT_MOST_FOUR_ARGS (-22128)
+/** VFS chain element takes exactly five arguments. */
+#define VERR_VFS_CHAIN_FIVE_ARGS (-22129)
+/** VFS chain element expected at least five arguments. */
+#define VERR_VFS_CHAIN_AT_LEAST_FIVE_ARGS (-22130)
+/** VFS chain element expected at most five arguments. */
+#define VERR_VFS_CHAIN_AT_MOST_FIVE_ARGS (-22131)
+/** VFS chain element takes exactly six arguments. */
+#define VERR_VFS_CHAIN_SIX_ARGS (-22132)
+/** VFS chain element expected at least six arguments. */
+#define VERR_VFS_CHAIN_AT_LEAST_SIX_ARGS (-22133)
+/** VFS chain element expected at most six arguments. */
+#define VERR_VFS_CHAIN_AT_MOST_SIX_ARGS (-22134)
+/** VFS chain element expected at most six arguments. */
+#define VERR_VFS_CHAIN_TOO_FEW_ARGS (-22135)
+/** VFS chain element expected at most six arguments. */
+#define VERR_VFS_CHAIN_TOO_MANY_ARGS (-22136)
+/** VFS chain element expected non-empty argument. */
+#define VERR_VFS_CHAIN_EMPTY_ARG (-22137)
+/** Invalid argument to VFS chain element. */
+#define VERR_VFS_CHAIN_INVALID_ARGUMENT (-22138)
+/** VFS chain element only provides file and I/O stream (ios) objects. */
+#define VERR_VFS_CHAIN_ONLY_FILE_OR_IOS (-22139)
+/** VFS chain element only provides I/O stream (ios) objects. */
+#define VERR_VFS_CHAIN_ONLY_IOS (-22140)
+/** VFS chain element only provides directory (dir) objects. */
+#define VERR_VFS_CHAIN_ONLY_DIR (-22141)
+/** VFS chain element only provides file system stream (fss) objects. */
+#define VERR_VFS_CHAIN_ONLY_FSS (-22142)
+/** VFS chain element only provides file system (vfs) objects. */
+#define VERR_VFS_CHAIN_ONLY_VFS (-22143)
+/** VFS chain element only provides file, I/O stream (ios), or
+ * directory (dir) objects. */
+#define VERR_VFS_CHAIN_ONLY_FILE_OR_IOS_OR_DIR (-22144)
+/** VFS chain element only provides file, I/O stream (ios), or
+ * directory (dir) objects. */
+#define VERR_VFS_CHAIN_ONLY_DIR_OR_VFS (-22145)
+/** VFS chain element takes a file object as input. */
+#define VERR_VFS_CHAIN_TAKES_FILE (-22146)
+/** VFS chain element takes a file or I/O stream (ios) object as input. */
+#define VERR_VFS_CHAIN_TAKES_FILE_OR_IOS (-22147)
+/** VFS chain element takes a directory (dir) object as input. */
+#define VERR_VFS_CHAIN_TAKES_DIR (-22148)
+/** VFS chain element takes a file system stream (fss) object as input. */
+#define VERR_VFS_CHAIN_TAKES_FSS (-22149)
+/** VFS chain element takes a file system (vfs) object as input. */
+#define VERR_VFS_CHAIN_TAKES_VFS (-22150)
+/** VFS chain element takes a directory (dir) or file system (vfs)
+ * object as input. */
+#define VERR_VFS_CHAIN_TAKES_DIR_OR_VFS (-22151)
+/** VFS chain element takes a directory (dir), file system stream (fss),
+ * or file system (vfs) object as input. */
+#define VERR_VFS_CHAIN_TAKES_DIR_OR_FSS_OR_VFS (-22152)
+/** VFS chain element only provides a read-only I/O stream, while the chain
+ * requires write access. */
+#define VERR_VFS_CHAIN_READ_ONLY_IOS (-22153)
+/** VFS chain element only provides a read-only I/O stream, while the chain
+ * read access. */
+#define VERR_VFS_CHAIN_WRITE_ONLY_IOS (-22154)
+/** VFS chain only has a single element and it is just a path, need to be
+ * treated as a normal file system request. */
+#define VERR_VFS_CHAIN_PATH_ONLY (-22155)
+/** VFS chain element preceding the final path needs to be a directory, file
+ * system or file system stream. */
+#define VERR_VFS_CHAIN_TYPE_MISMATCH_PATH_ONLY (-22156)
+/** VFS chain doesn't end with a path only element. */
+#define VERR_VFS_CHAIN_NOT_PATH_ONLY (-22157)
+/** The path only element at the end of the VFS chain is too short to make out
+ * the parent directory. */
+#define VERR_VFS_CHAIN_TOO_SHORT_FOR_PARENT (-22158)
+/** @} */
+
+/** @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)
+/** Logging is disabled or logger instance could not be created. */
+#define VINF_LOG_DISABLED (22301)
+/** No logger instance. */
+#define VINF_LOG_NO_LOGGER (22302)
+/** @} */
+
+/* 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)
+/** Unsupported firmware property. */
+#define VERR_SYS_UNSUPPORTED_FIRMWARE_PROPERTY (-22503)
+/** @} */
+
+/** @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_INDEFINITE_LENGTH (-22832)
+/** Malformed indefinite length encoding. */
+#define VERR_ASN1_CURSOR_BAD_INDEFINITE_LENGTH (-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)
+/** Invalid ASN.1 INTEGER encoding. */
+#define VERR_ASN1_INVALID_INTEGER_ENCODING (-22857)
+
+/** 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)
+/** Malformed code signing structure. */
+#define VERR_LDRVI_BAD_CERT_FORMAT (-22930)
+
+/** 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)
+/** Only native endian Mach-O files are supported. */
+#define VERR_LDRMACHO_OTHER_ENDIAN_NOT_SUPPORTED (-22955)
+/** The Mach-O header is bad or contains new and unsupported features. */
+#define VERR_LDRMACHO_BAD_HEADER (-22956)
+/** The file type isn't supported. */
+#define VERR_LDRMACHO_UNSUPPORTED_FILE_TYPE (-22957)
+/** The machine (cputype / cpusubtype combination) isn't supported. */
+#define VERR_LDRMACHO_UNSUPPORTED_MACHINE (-22958)
+/** Bad load command(s). */
+#define VERR_LDRMACHO_BAD_LOAD_COMMAND (-22959)
+/** Encountered an unknown load command.*/
+#define VERR_LDRMACHO_UNKNOWN_LOAD_COMMAND (-22960)
+/** Encountered a load command that's not implemented.*/
+#define VERR_LDRMACHO_UNSUPPORTED_LOAD_COMMAND (-22961)
+/** Bad section. */
+#define VERR_LDRMACHO_BAD_SECTION (-22962)
+/** Encountered a section type that's not implemented.*/
+#define VERR_LDRMACHO_UNSUPPORTED_SECTION (-22963)
+/** Encountered a init function section. */
+#define VERR_LDRMACHO_UNSUPPORTED_INIT_SECTION (-22964)
+/** Encountered a term function section. */
+#define VERR_LDRMACHO_UNSUPPORTED_TERM_SECTION (-22965)
+/** Encountered a section type that's not known to the loader. (probably invalid) */
+#define VERR_LDRMACHO_UNKNOWN_SECTION (-22966)
+/** The sections aren't ordered by segment as expected by the loader. */
+#define VERR_LDRMACHO_BAD_SECTION_ORDER (-22967)
+/** The image is 32-bit and contains 64-bit load commands or vise versa. */
+#define VERR_LDRMACHO_BIT_MIX (-22968)
+/** Bad MH_OBJECT file. */
+#define VERR_LDRMACHO_BAD_OBJECT_FILE (-22969)
+/** Bad symbol table entry. */
+#define VERR_LDRMACHO_BAD_SYMBOL (-22970)
+/** Unsupported fixup type. */
+#define VERR_LDRMACHO_UNSUPPORTED_FIXUP_TYPE (-22971)
+/** Both debug and non-debug sections in segment. */
+#define VERR_LDRMACHO_MIXED_DEBUG_SECTION_FLAGS (-22972)
+/** The segment bits are non-contiguous in the file. */
+#define VERR_LDRMACHO_NON_CONT_SEG_BITS (-22973)
+/** Hit a todo in the mach-o loader. */
+#define VERR_LDRMACHO_TODO (-22974)
+/** Bad symbol table size in Mach-O image. */
+#define VERR_LDRMACHO_BAD_SYMTAB_SIZE (-22975)
+/** Duplicate segment name. */
+#define VERR_LDR_DUPLICATE_SEGMENT_NAME (-22976)
+/** No image UUID. */
+#define VERR_LDR_NO_IMAGE_UUID (-22977)
+/** Bad image relocation. */
+#define VERR_LDR_BAD_FIXUP (-22978)
+/** Address overflow. */
+#define VERR_LDR_ADDRESS_OVERFLOW (-22979)
+/** validation of LX header failed. */
+#define VERR_LDRLX_BAD_HEADER (-22980)
+/** validation of the loader section (in the LX header) failed. */
+#define VERR_LDRLX_BAD_LOADER_SECTION (-22981)
+/** validation of the fixup section (in the LX header) failed. */
+#define VERR_LDRLX_BAD_FIXUP_SECTION (-22982)
+/** validation of the LX object table failed. */
+#define VERR_LDRLX_BAD_OBJECT_TABLE (-22983)
+/** A bad page map entry was encountered. */
+#define VERR_LDRLX_BAD_PAGE_MAP (-22984)
+/** Bad iterdata (EXEPACK) data. */
+#define VERR_LDRLX_BAD_ITERDATA (-22985)
+/** Bad iterdata2 (EXEPACK2) data. */
+#define VERR_LDRLX_BAD_ITERDATA2 (-22986)
+/** Bad bundle data. */
+#define VERR_LDRLX_BAD_BUNDLE (-22987)
+/** No soname. */
+#define VERR_LDRLX_NO_SONAME (-22988)
+/** Bad soname. */
+#define VERR_LDRLX_BAD_SONAME (-22989)
+/** Bad forwarder entry. */
+#define VERR_LDRLX_BAD_FORWARDER (-22990)
+/** internal fixup chain isn't implemented yet. */
+#define VERR_LDRLX_NRICHAIN_NOT_SUPPORTED (-22991)
+/** Import module ordinal is out of bounds. */
+#define VERR_LDRLX_IMPORT_ORDINAL_OUT_OF_BOUNDS (-22992)
+/** @} */
+
+/** @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)
+/** The PKCS \#7 content is not data. */
+#define VERR_CR_PKCS7_NOT_DATA (-22360)
+/** @} */
+
+/** @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)
+/** OpenSSL failed to decode the public key. */
+#define VERR_CR_PKIX_OSSL_D2I_PRIVATE_KEY_FAILED (-23518)
+/** The EVP_PKEY_CTX_set_rsa_padding API in OpenSSL failed. */
+#define VERR_CR_PKIX_OSSL_EVP_PKEY_RSA_PAD_ERROR (-23519)
+/** Final OpenSSL PKIX signing failed. */
+#define VERR_CR_PKIX_OSSL_SIGN_FINAL_FAILED (-23520)
+/** OpenSSL and IPRT disagree on the signature size. */
+#define VERR_CR_PKIX_OSSL_VS_IPRT_SIGNATURE_SIZE (-23521)
+/** OpenSSL and IPRT disagree on the signature. */
+#define VERR_CR_PKIX_OSSL_VS_IPRT_SIGNATURE (-23522)
+/** Expected RSA private key. */
+#define VERR_CR_PKIX_NOT_RSA_PRIVATE_KEY (-23523)
+/** Expected RSA public key. */
+#define VERR_CR_PKIX_NOT_RSA_PUBLIC_KEY (-23524)
+/** @} */
+
+/** @name RTCrStore status codes.
+ * @{ */
+/** Generic store error. */
+#define VERR_CR_STORE_GENERIC_ERROR (-23700)
+/** @} */
+
+/** @name RTCrKey status codes.
+ * @{ */
+/** Could not recognize the key type. */
+#define VERR_CR_KEY_UNKNOWN_TYPE (-23800)
+/** Unsupported key format. */
+#define VERR_CR_KEY_FORMAT_NOT_SUPPORTED (-23801)
+/** Key encrypted but no password was given. */
+#define VERR_CR_KEY_ENCRYPTED (-23802)
+/** The key was marked as encrypted by no DEK-Info field with the encryption
+ * algortihms was found. */
+#define VERR_CR_KEY_NO_DEK_INFO (-23803)
+/** The algorithms part of the DEK-Info field is too long. */
+#define VERR_CR_KEY_DEK_INFO_TOO_LONG (-23804)
+/** Key decryption is not supported. */
+#define VERR_CR_KEY_DECRYPTION_NOT_SUPPORTED (-23805)
+/** Unsupported key encryption cipher. */
+#define VERR_CR_KEY_UNSUPPORTED_CIPHER (-23806)
+/** Found unexpected cipher parameters for encrypted key. */
+#define VERR_CR_KEY_UNEXPECTED_CIPHER_PARAMS (-23807)
+/** Missing ciper parameters for encrypted key. */
+#define VERR_CR_KEY_MISSING_CIPHER_PARAMS (-23808)
+/** To short initialization vector for encrypted key ciper. */
+#define VERR_CR_KEY_TOO_SHORT_CIPHER_IV (-23809)
+/** Malformed initialization vector for encrypted key ciper. */
+#define VERR_CR_KEY_MALFORMED_CIPHER_IV (-23810)
+/** Error encoding the password for key decryption. */
+#define VERR_CR_KEY_PASSWORD_ENCODING (-23811)
+/** EVP_DecryptInit_ex failed. */
+#define VERR_CR_KEY_OSSL_DECRYPT_INIT_ERROR (-23812)
+/** Key decryption failed, perhaps due to an incorrect password. */
+#define VERR_CR_KEY_DECRYPTION_FAILED (-23813)
+/** The key was decrypted. */
+#define VINF_CR_KEY_WAS_DECRYPTED (23814)
+/** Failed to generate RSA key. */
+#define VERR_CR_KEY_GEN_FAILED_RSA (-23815)
+/** @} */
+
+/** @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)
+/** Deprecated digest. */
+#define VINF_CR_DIGEST_DEPRECATED (24202)
+/** Deprecated digest. */
+#define VERR_CR_DIGEST_DEPRECATED (-24202)
+/** Compromised digest. */
+#define VINF_CR_DIGEST_COMPROMISED (24203)
+/** Compromised digest. */
+#define VERR_CR_DIGEST_COMPROMISED (-24203)
+/** Severely compromised digest. */
+#define VINF_CR_DIGEST_SEVERELY_COMPROMISED (24204)
+/** Severely compromised digest. */
+#define VERR_CR_DIGEST_SEVERELY_COMPROMISED (-24204)
+/** Specified digest not supported in this context. */
+#define VERR_CR_DIGEST_NOT_SUPPORTED (-24205)
+/** @} */
+
+/** @name RTCr misc status codes.
+ * @{ */
+/** Failed to derivate key from password. */
+#define VERR_CR_PASSWORD_2_KEY_DERIVIATION_FAILED (-24396)
+/** Failed getting cryptographically strong random bytes. */
+#define VERR_CR_RANDOM_SETUP_FAILED (-24397)
+/** Failed getting cryptographically strong random bytes. */
+#define VERR_CR_RANDOM_FAILED (-24398)
+/** Malformed or failed to parse PEM formatted data. */
+#define VERR_CR_MALFORMED_PEM_HEADER (-24399)
+/** @} */
+
+/** @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)
+/** Object or array is empty. */
+#define VERR_JSON_IS_EMPTY (-24703)
+/** Invalid UTF-16 escape sequence. */
+#define VERR_JSON_INVALID_UTF16_ESCAPE_SEQUENCE (-24704)
+/** Missing UTF-16 surrogate pair. */
+#define VERR_JSON_MISSING_SURROGATE_PAIR (-24705)
+/** Bad UTF-16 surrogate pair sequence. */
+#define VERR_JSON_BAD_SURROGATE_PAIR_SEQUENCE (-24706)
+/** Invalid codepoint. */
+#define VERR_JSON_INVALID_CODEPOINT (-24707)
+/** @} */
+
+/** @name RTVfs status codes.
+ * @{ */
+/** Unknown file system format. */
+#define VERR_VFS_UNKNOWN_FORMAT (-24800)
+/** Found bogus values in the file system. */
+#define VERR_VFS_BOGUS_FORMAT (-24801)
+/** Found bogus offset in the file system. */
+#define VERR_VFS_BOGUS_OFFSET (-24802)
+/** Unsupported file system format. */
+#define VERR_VFS_UNSUPPORTED_FORMAT (-24803)
+/** Unsupported create type in an RTVfsObjOpen or RTVfsDirOpenObj call. */
+#define VERR_VFS_UNSUPPORTED_CREATE_TYPE (-24804)
+/** @} */
+
+/** @name RTFsIsoMaker status codes.
+ * @{ */
+/** No validation entry in the boot catalog. */
+#define VERR_ISOMK_BOOT_CAT_NO_VALIDATION_ENTRY (-25000)
+/** No default entry in the boot catalog. */
+#define VERR_ISOMK_BOOT_CAT_NO_DEFAULT_ENTRY (-25001)
+/** Expected section header. */
+#define VERR_ISOMK_BOOT_CAT_EXPECTED_SECTION_HEADER (-25002)
+/** Entry in a boot catalog section is empty. */
+#define VERR_ISOMK_BOOT_CAT_EMPTY_ENTRY (-25003)
+/** Entry in a boot catalog section is another section. */
+#define VERR_ISOMK_BOOT_CAT_INVALID_SECTION_SIZE (-25004)
+/** Unsectioned boot catalog entry. */
+#define VERR_ISOMK_BOOT_CAT_ERRATIC_ENTRY (-25005)
+/** The file is too big for the current ISO level (4GB+ sized files
+ * requires ISO level 3). */
+#define VERR_ISOMK_FILE_TOO_BIG_REQ_ISO_LEVEL_3 (-25006)
+/** Cannot add symbolic link to namespace which isn't configured to support it. */
+#define VERR_ISOMK_SYMLINK_REQ_ROCK_RIDGE (-25007)
+/** Cannot add symbolic link to one of the selected namespaces. */
+#define VINF_ISOMK_SYMLINK_REQ_ROCK_RIDGE (25007)
+/** Cannot add symbolic link because no namespace is configured to support it. */
+#define VERR_ISOMK_SYMLINK_SUPPORT_DISABLED (-25008)
+/** No space for rock ridge 'CE' entry in directory record. */
+#define VERR_ISOMK_RR_NO_SPACE_FOR_CE (-25009)
+/** Internal ISO maker error: Rock ridge read problem. */
+#define VERR_ISOMK_IPE_RR_READ (-25010)
+/** Internal ISO maker error: Buggy namespace table. */
+#define VERR_ISOMK_IPE_TABLE (-25011)
+/** Internal ISO maker error: Namespace problem \#1. */
+#define VERR_ISOMK_IPE_NAMESPACE_1 (-25012)
+/** Internal ISO maker error: Namespace problem \#2. */
+#define VERR_ISOMK_IPE_NAMESPACE_2 (-25013)
+/** Internal ISO maker error: Namespace problem \#3. */
+#define VERR_ISOMK_IPE_NAMESPACE_3 (-25014)
+/** Internal ISO maker error: Namespace problem \#4. */
+#define VERR_ISOMK_IPE_NAMESPACE_4 (-25015)
+/** Internal ISO maker error: Namespace problem \#5. */
+#define VERR_ISOMK_IPE_NAMESPACE_5 (-25016)
+/** Internal ISO maker error: Namespace problem \#6. */
+#define VERR_ISOMK_IPE_NAMESPACE_6 (-25017)
+/** Internal ISO maker error: Empty path. */
+#define VERR_ISOMK_IPE_EMPTY_PATH (-25018)
+/** Internal ISO maker error: Unexpected empty component. */
+#define VERR_ISOMK_IPE_EMPTY_COMPONENT (-25019)
+/** Internal ISO maker error: Expected path to start with root slash. */
+#define VERR_ISOMK_IPE_ROOT_SLASH (-25020)
+/** Internal ISO maker error: Descriptor miscounting. */
+#define VERR_ISOMK_IPE_DESC_COUNT (-25021)
+/** Internal ISO maker error: Buffer size. */
+#define VERR_ISOMK_IPE_BUFFER_SIZE (-25022)
+/** Internal ISO maker error: Boot catalog file handle problem. */
+#define VERR_ISOMK_IPE_BOOT_CAT_FILE (-25023)
+/** Internal ISO maker error: Inconsistency produing trans.tbl file. */
+#define VERR_ISOMK_IPE_PRODUCE_TRANS_TBL (-25024)
+/** Internal ISO maker error: Read file data probem \#1. */
+#define VERR_ISOMK_IPE_READ_FILE_DATA_1 (-25025)
+/** Internal ISO maker error: Read file data probem \#2. */
+#define VERR_ISOMK_IPE_READ_FILE_DATA_2 (-25026)
+/** Internal ISO maker error: Read file data probem \#3. */
+#define VERR_ISOMK_IPE_READ_FILE_DATA_3 (-25027)
+/** Internal ISO maker error: Finalization problem \#1. */
+#define VERR_ISOMK_IPE_FINALIZE_1 (-25028)
+/** The spill file grew larger than 4GB. */
+#define VERR_ISOMK_RR_SPILL_FILE_FULL (-25029)
+
+/** Requested to import an unknown ISO format. */
+#define VERR_ISOMK_IMPORT_UNKNOWN_FORMAT (-25100)
+/** Too many volume descriptors in the import ISO. */
+#define VERR_ISOMK_IMPORT_TOO_MANY_VOL_DESCS (-25101)
+/** Import ISO contains a bad volume descriptor header. */
+#define VERR_ISOMK_IMPORT_INVALID_VOL_DESC_HDR (-25102)
+/** Import ISO contains more than one primary volume descriptor. */
+#define VERR_ISOMK_IMPORT_MULTIPLE_PRIMARY_VOL_DESCS (-25103)
+/** Import ISO contains more than one el torito descriptor. */
+#define VERR_ISOMK_IMPORT_MULTIPLE_EL_TORITO_DESCS (-25104)
+/** Import ISO contains more than one joliet volume descriptor. */
+#define VERR_ISOMK_IMPORT_MULTIPLE_JOLIET_VOL_DESCS (-25105)
+/** Import ISO starts with supplementary volume descriptor before any
+ * primary ones. */
+#define VERR_ISOMK_IMPORT_SUPPLEMENTARY_BEFORE_PRIMARY (-25106)
+/** Import ISO contains an unsupported primary volume descriptor version. */
+#define VERR_IOSMK_IMPORT_PRIMARY_VOL_DESC_VER (-25107)
+/** Import ISO contains a bad primary volume descriptor. */
+#define VERR_ISOMK_IMPORT_BAD_PRIMARY_VOL_DESC (-25108)
+/** Import ISO contains an unsupported supplementary volume descriptor
+ * version. */
+#define VERR_IOSMK_IMPORT_SUP_VOL_DESC_VER (-25109)
+/** Import ISO contains a bad supplementary volume descriptor. */
+#define VERR_ISOMK_IMPORT_BAD_SUP_VOL_DESC (-25110)
+/** Import ISO uses a logical block size other than 2KB. */
+#define VERR_ISOMK_IMPORT_LOGICAL_BLOCK_SIZE_NOT_2KB (-25111)
+/** Import ISO contains more than volume. */
+#define VERR_ISOMK_IMPORT_MORE_THAN_ONE_VOLUME_IN_SET (-25112)
+/** Import ISO uses invalid volume sequence number. */
+#define VERR_ISOMK_IMPORT_INVALID_VOLUMNE_SEQ_NO (-25113)
+/** Import ISO has different volume space sizes of primary and supplementary
+ * volume descriptors. */
+#define VERR_ISOMK_IMPORT_VOLUME_SPACE_SIZE_MISMATCH (-25114)
+/** Import ISO has different volume set sizes of primary and supplementary
+ * volume descriptors. */
+#define VERR_ISOMK_IMPORT_VOLUME_IN_SET_MISMATCH (-25115)
+/** Import ISO contains a bad root directory record. */
+#define VERR_ISOMK_IMPORT_BAD_ROOT_DIR_REC (-25116)
+/** Import ISO contains a zero sized root directory. */
+#define VERR_ISOMK_IMPORT_ZERO_SIZED_ROOT_DIR (-25117)
+/** Import ISO contains a root directory with a mismatching volume sequence
+ * number. */
+#define VERR_ISOMK_IMPORT_ROOT_VOLUME_SEQ_NO (-25118)
+/** Import ISO contains a root directory with an out of bounds data extent. */
+#define VERR_ISOMK_IMPORT_ROOT_DIR_EXTENT_OUT_OF_BOUNDS (-25119)
+/** Import ISO contains a root directory with a bad record length. */
+#define VERR_ISOMK_IMPORT_BAD_ROOT_DIR_REC_LENGTH (-25120)
+/** Import ISO contains a root directory without the directory flag set. */
+#define VERR_ISOMK_IMPORT_ROOT_DIR_WITHOUT_DIR_FLAG (-25121)
+/** Import ISO contains a root directory with multiple extents. */
+#define VERR_ISOMK_IMPORT_ROOT_DIR_IS_MULTI_EXTENT (-25122)
+/** Import ISO contains a too deep directory subtree. */
+#define VERR_ISOMK_IMPORT_TOO_DEEP_DIR_TREE (-25123)
+/** Import ISO contains a bad directory record. */
+#define VERR_ISOMK_IMPORT_BAD_DIR_REC (-25124)
+/** Import ISO contains a directory record with a mismatching volume sequence
+ * number. */
+#define VERR_ISOMK_IMPORT_DIR_REC_VOLUME_SEQ_NO (-25125)
+/** Import ISO contains a directory with an extent that is out of bounds. */
+#define VERR_ISOMK_IMPORT_DIR_REC_EXTENT_OUT_OF_BOUNDS (-25126)
+/** Import ISO contains a directory with a bad record length. */
+#define VERR_ISOMK_IMPORT_BAD_DIR_REC_LENGTH (-25127)
+/** Import ISO contains a '.' or '..' directory record with a bad name
+ * length. */
+#define VERR_ISOMK_IMPORT_DOT_DIR_REC_BAD_NAME_LENGTH (-25128)
+/** Import ISO contains a '.' or '..' directory record with a bad name. */
+#define VERR_ISOMK_IMPORT_DOT_DIR_REC_BAD_NAME (-25129)
+/** Import ISO contains a directory with a more than one extent, that's
+ * currently not supported. */
+#define VERR_ISOMK_IMPORT_DIR_WITH_MORE_EXTENTS (-25130)
+/** Import ISO contains a multi-extent directory record that differs
+ * significantly from first record. */
+#define VERR_ISOMK_IMPORT_MISMATCHING_MULTI_EXTENT_REC (-25131)
+/** Import ISO contains a non-final multi-extent directory record with a
+ * size that isn't block aligned. */
+#define VERR_ISOMK_IMPORT_MISALIGNED_MULTI_EXTENT (-25132)
+/** Import ISO contains a non-contigiuous multi-extent data, this is
+ * currently not supported. */
+#define VERR_ISOMK_IMPORT_NON_CONTIGUOUS_MULTI_EXTENT (-25133)
+
+/** The boot catalog block in the import ISO is out of bounds. */
+#define VERR_ISOMK_IMPORT_BOOT_CAT_BAD_OUT_OF_BOUNDS (-25140)
+/** The boot catalog block in the import ISO has an incorrect validation
+ * header ID. */
+#define VERR_ISOMK_IMPORT_BOOT_CAT_BAD_VALIDATION_HEADER_ID (-25141)
+/** The boot catalog validation entry in the import ISO has incorrect keys. */
+#define VERR_ISOMK_IMPORT_BOOT_CAT_BAD_VALIDATION_KEYS (-25142)
+/** The boot catalog validation entry in the import ISO has an incorrect checksum. */
+#define VERR_ISOMK_IMPORT_BOOT_CAT_BAD_VALIDATION_CHECKSUM (-25143)
+/** A boot catalog entry in the import ISO has an unknown type. */
+#define VERR_ISOMK_IMPORT_BOOT_CAT_UNKNOWN_HEADER_ID (-25144)
+/** A boot catalog entry in the import ISO has an invalid boot media type. */
+#define VERR_ISOMK_IMPORT_BOOT_CAT_INVALID_BOOT_MEDIA_TYPE (-25145)
+/** The default boot catalog entry in the import ISO has invalid flags set. */
+#define VERR_ISOMK_IMPORT_BOOT_CAT_DEF_ENTRY_INVALID_FLAGS (-25146)
+/** A boot catalog entry in the import ISO has reserved flag set. */
+#define VERR_ISOMK_IMPORT_BOOT_CAT_ENTRY_RESERVED_FLAG (-25147)
+/** A boot catalog entry in the import ISO is using the unused field. */
+#define VERR_ISOMK_IMPORT_BOOT_CAT_ENTRY_USES_UNUSED_FIELD (-25148)
+/** A boot catalog entry in the import ISO points to a block after the end of
+ * the image input file. */
+#define VERR_ISOMK_IMPORT_BOOT_CAT_ENTRY_IMAGE_OUT_OF_BOUNDS (-25149)
+/** A boot catalog entry in the import ISO has an image with an
+ * indeterminate size. */
+#define VERR_ISOMK_IMPORT_BOOT_CAT_ENTRY_UNKNOWN_IMAGE_SIZE (-25150)
+/** The boot catalog in the import ISO is larger than a sector or it is
+ * missing the final section header entry. */
+#define VERR_ISOMK_IMPORT_BOOT_CAT_MISSING_FINAL_OR_TOO_BIG (-25151)
+/** The default boot catalog entry in the import ISO an invalid boot
+ * indicator value. */
+#define VERR_ISOMK_IMPORT_BOOT_CAT_DEF_ENTRY_INVALID_BOOT_IND (-25152)
+/** A boot catalog extension entry in the import ISO was either flagged
+ * incorrectly in the previous entry or has an invalid header ID. */
+#define VERR_ISOMK_IMPORT_BOOT_CAT_EXT_ENTRY_INVALID_ID (-25153)
+/** A boot catalog extension entry in the import ISO uses undefined flags
+ * which will be lost. */
+#define VERR_ISOMK_IMPORT_BOOT_CAT_EXT_ENTRY_UNDEFINED_FLAGS (-25154)
+/** A boot catalog extension entry in the import ISO indicates more entries when
+ * we reached the end of the boot catalog sector. */
+#define VERR_ISOMK_IMPORT_BOOT_CAT_EXT_ENTRY_END_OF_SECTOR (-25155)
+/** A boot catalog entry in the import ISO sets the continuation flag when using
+ * NONE as the selection criteria type. */
+#define VERR_ISOMK_IMPORT_BOOT_CAT_ENTRY_CONTINUATION_WITH_NONE (-25156)
+/** A boot catalog entry in the import ISO sets the continuation flag when
+ * we reached the ned of the boot catalog secotr. */
+#define VERR_ISOMK_IMPORT_BOOT_CAT_ENTRY_CONTINUATION_EOS (-25157)
+/** @} */
+
+
+/** @name RTFsIsoVol status codes
+ * @{ */
+/** Descriptor tag is all zeros. */
+#define VERR_ISOFS_TAG_IS_ALL_ZEROS (-25300)
+/** Unsupported descriptor tag version. */
+#define VERR_ISOFS_UNSUPPORTED_TAG_VERSION (-25301)
+/** Bad descriptor tag checksum. */
+#define VERR_ISOFS_BAD_TAG_CHECKSUM (-25302)
+/** Descriptor tag sector number mismatch. */
+#define VERR_ISOFS_TAG_SECTOR_MISMATCH (-25303)
+/** Descriptor CRC mismatch. */
+#define VERR_ISOFS_DESC_CRC_MISMATCH (-25304)
+/** Insufficient data to check descriptor CRC. */
+#define VERR_ISOFS_INSUFFICIENT_DATA_FOR_DESC_CRC (-25305)
+/** Unexpected/unknown/bad descriptor in volume descriptor sequence. */
+#define VERR_ISOFS_UNEXPECTED_VDS_DESC (-25306)
+/** Too many primary volume descriptors. */
+#define VERR_ISOFS_TOO_MANY_PVDS (-25307)
+/** Too many logical volume descriptors. */
+#define VERR_ISOFS_TOO_MANY_LVDS (-25308)
+/** Too many partition descriptors. */
+#define VERR_ISOFS_TOO_MANY_PDS (-25309)
+/** The logical volume descriptor has a too big partition map. */
+#define VERR_ISOFS_TOO_BIT_PARTMAP_IN_LVD (-25310)
+/** No primary volume descriptors found. */
+#define VERR_ISOFS_NO_PVD (-25311)
+/** No logical volume descriptors found. */
+#define VERR_ISOFS_NO_LVD (-25312)
+/** No partition descriptors found. */
+#define VERR_ISOFS_NO_PD (-25313)
+/** Multiple primary volume descriptors found, we can only deal with one. */
+#define VERR_ISOFS_MULTIPLE_PVDS (-25314)
+/** Multiple logical volume descriptors found, we can only deal with one. */
+#define VERR_ISOFS_MULTIPLE_LVDS (-25315)
+/** Too many partition maps in the logical volume descriptor. */
+#define VERR_ISOFS_TOO_MANY_PART_MAPS (-25316)
+/** Malformed partition map table in the logical volume descriptor. */
+#define VERR_ISOFS_MALFORMED_PART_MAP_TABLE (-25317)
+/** Unable to find partition descriptor for a partition map table entry. */
+#define VERR_ISOFS_PARTITION_NOT_FOUND (-25318)
+/** Partition mapping table is shorted than described. */
+#define VERR_ISOFS_INCOMPLETE_PART_MAP_TABLE (-25319)
+/** Unknown partition map entry type. */
+#define VERR_ISOFS_UNKNOWN_PART_MAP_ENTRY_TYPE (-25320)
+/** Unkonwn paritition ID found in the partition map table. */
+#define VERR_ISOFS_UNKNOWN_PART_MAP_TYPE_ID (-25321)
+/** Support for virtual partitions as not yet been implemented. */
+#define VERR_ISOFS_VPM_NOT_SUPPORTED (-25322)
+/** Support for sparable partitions as not yet been implemented. */
+#define VERR_ISOFS_SPM_NOT_SUPPORTED (-25323)
+/** Support for metadata partitions as not yet been implemented. */
+#define VERR_ISOFS_MPM_NOT_SUPPORTED (-25324)
+/** Invalid or unsupported logical block size. */
+#define VERR_ISOFS_UNSUPPORTED_LOGICAL_BLOCK_SIZE (-25325)
+/** Unsupported domain ID in logical volume descriptor. */
+#define VERR_ISOFS_BAD_LVD_DOMAIN_ID (-25326)
+/** Malformed or invalid file set descriptor location. */
+#define VERR_ISOFS_BAD_LVD_FILE_SET_DESC_LOCATION (-25327)
+/** Non-standard descriptor character set in the logical volume descriptor. */
+#define VERR_ISOFS_BAD_LVD_DESC_CHAR_SET (-25329)
+/** Invalid partition index in a location. */
+#define VERR_ISOFS_INVALID_PARTITION_INDEX (-25330)
+/** Unsupported file system charset. */
+#define VERR_ISOFS_FSD_UNSUPPORTED_CHAR_SET (-25331)
+/** File set descriptor has an zero length or invalid root dir extent. */
+#define VERR_ISOFS_FSD_ZERO_ROOT_DIR (-25332)
+/** File set descriptor has a next extent member. */
+#define VERR_ISOFS_FSD_NEXT_EXTENT (-25333)
+/** The ICB for is too big. */
+#define VERR_ISOFS_ICB_TOO_BIG (-25334)
+/** The ICB for is too small. */
+#define VERR_ISOFS_ICB_TOO_SMALL (-25335)
+/** No direct ICB entries found. */
+#define VERR_ISOFS_NO_DIRECT_ICB_ENTRIES (-25336)
+/** Too many ICB indirections, possibly a loop. */
+#define VERR_ISOFS_TOO_MANY_ICB_INDIRECTIONS (-25337)
+/** Too deep ICB recursion. */
+#define VERR_ISOFS_TOO_DEEP_ICB_RECURSION (-25338)
+/** ICB is too small to contain anything useful. */
+#define VERR_ISOFS_ICB_ENTRY_TOO_SMALL (-25339)
+/** Unsupported tag encountered in ICB. */
+#define VERR_ISOFS_UNSUPPORTED_ICB (-25340)
+/** Bad file entry (ICB). */
+#define VERR_ISOFS_BAD_FILE_ENTRY (-25341)
+/** Unknown allocation descriptor type. */
+#define VERR_ISO_FS_UNKNOWN_AD_TYPE (-25342)
+/** Malformed extended allocation descriptor. */
+#define VERR_ISOFS_BAD_EXTAD (-25343)
+/** Wrong file type. */
+#define VERR_ISOFS_WRONG_FILE_TYPE (-25344)
+/** Unknow file type. */
+#define VERR_ISOFS_UNKNOWN_FILE_TYPE (-25345)
+
+/** Not implemented for UDF. */
+#define VERR_ISOFS_UDF_NOT_IMPLEMENTED (-25390)
+/** Internal processing error \#1. */
+#define VERR_ISOFS_IPE_1 (-25391)
+/** Internal processing error \#2. */
+#define VERR_ISOFS_IPE_2 (-25392)
+/** Internal processing error \#3. */
+#define VERR_ISOFS_IPE_3 (-25393)
+/** Internal processing error \#4. */
+#define VERR_ISOFS_IPE_4 (-25394)
+/** Internal processing error \#5. */
+#define VERR_ISOFS_IPE_5 (-25395)
+/** @} */
+
+
+/** @name RTSerialPort status codes
+ * @{ */
+/** A break was detected until all requested data could be received. */
+#define VERR_SERIALPORT_BREAK_DETECTED (-25500)
+/** The chosen baudrate is invalid or not supported by the given serial port. */
+#define VERR_SERIALPORT_INVALID_BAUDRATE (-25501)
+/** @} */
+
+
+/** @name RTCRest status codes
+ * @{ */
+/** Do not know how to handle the content type in the server response. */
+#define VERR_REST_RESPONSE_CONTENT_TYPE_NOT_SUPPORTED (-25700)
+/** Invalid UTF-8 encoding in the response. */
+#define VERR_REST_RESPONSE_INVALID_UTF8_ENCODING (-25701)
+/** Server response contains embedded zero character(s). */
+#define VERR_REST_RESPONSE_EMBEDDED_ZERO_CHAR (-25702)
+/** Server response contains unexpected repetitive header field. */
+#define VERR_REST_RESPONSE_REPEAT_HEADER_FIELD (-25703)
+/** Unable to decode date value. */
+#define VWRN_REST_UNABLE_TO_DECODE_DATE (25704)
+/** Unable to decode date value. */
+#define VERR_REST_UNABLE_TO_DECODE_DATE (-25704)
+/** Wrong JSON type for bool value. */
+#define VERR_REST_WRONG_JSON_TYPE_FOR_BOOL (-25705)
+/** Wrong JSON type for integer value. */
+#define VERR_REST_WRONG_JSON_TYPE_FOR_INTEGER (-25706)
+/** Wrong JSON type for double value. */
+#define VERR_REST_WRONG_JSON_TYPE_FOR_DOUBLE (-25707)
+/** Wrong JSON type for string value. */
+#define VERR_REST_WRONG_JSON_TYPE_FOR_STRING (-25708)
+/** Wrong JSON type for date value. */
+#define VERR_REST_WRONG_JSON_TYPE_FOR_DATE (-25709)
+/** Unable to parse string as bool. */
+#define VERR_REST_UNABLE_TO_PARSE_STRING_AS_BOOL (-25710)
+/** A path parameter was not set. */
+#define VERR_REST_PATH_PARAMETER_NOT_SET (-25711)
+/** A required query parameter was not set. */
+#define VERR_REST_REQUIRED_QUERY_PARAMETER_NOT_SET (-25712)
+/** A required header parmaeter was not set. */
+#define VERR_REST_REQUIRED_HEADER_PARAMETER_NOT_SET (-25713)
+
+/** Internal error \#1. */
+#define VERR_REST_INTERNAL_ERROR_1 (-25791)
+/** Internal error \#2. */
+#define VERR_REST_INTERNAL_ERROR_2 (-25792)
+/** Internal error \#3. */
+#define VERR_REST_INTERNAL_ERROR_3 (-25793)
+/** Internal error \#4. */
+#define VERR_REST_INTERNAL_ERROR_4 (-25794)
+/** Internal error \#5. */
+#define VERR_REST_INTERNAL_ERROR_5 (-25795)
+/** Internal error \#6. */
+#define VERR_REST_INTERNAL_ERROR_6 (-25796)
+/** Internal error \#7. */
+#define VERR_REST_INTERNAL_ERROR_7 (-25797)
+/** Internal error \#8. */
+#define VERR_REST_INTERNAL_ERROR_8 (-25798)
+/** Internal error \#9. */
+#define VERR_REST_INTERNAL_ERROR_9 (-25799)
+/** @} */
+
+
+/** @name RTCrCipher status codes
+ * @{ */
+/** Unsupported cipher. */
+#define VERR_CR_CIPHER_NOT_SUPPORTED (-25800)
+/** EVP_EncryptInit failed. */
+#define VERR_CR_CIPHER_OSSL_ENCRYPT_INIT_FAILED (-25801)
+/** EVP_EncryptUpdate failed. */
+#define VERR_CR_CIPHER_OSSL_ENCRYPT_UPDATE_FAILED (-25802)
+/** EVP_EncryptFinal failed. */
+#define VERR_CR_CIPHER_OSSL_ENCRYPT_FINAL_FAILED (-25803)
+/** EVP_DecryptInit failed. */
+#define VERR_CR_CIPHER_OSSL_DECRYPT_INIT_FAILED (-25804)
+/** EVP_DecryptUpdate failed. */
+#define VERR_CR_CIPHER_OSSL_DECRYPT_UPDATE_FAILED (-25805)
+/** EVP_DecryptFinal failed. */
+#define VERR_CR_CIPHER_OSSL_DECRYPT_FINAL_FAILED (-25806)
+/** Invalid key length. */
+#define VERR_CR_CIPHER_INVALID_KEY_LENGTH (-25807)
+/** Invalid initialization vector length. */
+#define VERR_CR_CIPHER_INVALID_INITIALIZATION_VECTOR_LENGTH (-25808)
+/** Invalid tag length. */
+#define VERR_CR_CIPHER_INVALID_TAG_LENGTH (-25809)
+/** EVP_CIPHER_CTX_ctrl EVP_CTRL_AEAD_GET_TAG failed. */
+#define VERR_CR_CIPHER_OSSL_GET_TAG_FAILED (-25810)
+/** EVP_CIPHER_CTX_ctrl EVP_CTRL_AEAD_SET_TAG failed. */
+#define VERR_CR_CIPHER_OSSL_SET_TAG_FAILED (-25811)
+/** @} */
+
+
+/** @name RTShMem status codes
+ * @{ */
+/** Maximum number of mappings reached. */
+#define VERR_SHMEM_MAXIMUM_MAPPINGS_REACHED (-26000)
+/** @} */
+
+
+/** @name RTIoQueue status codes
+ * @{ */
+/** The handle was not registered for use with the I/O queue. */
+#define VERR_IOQUEUE_HANDLE_NOT_REGISTERED (-26200)
+/** The I/O queue is full and can't accept more requests. */
+#define VERR_IOQUEUE_FULL (-26201)
+/** The I/O queue doesn't contain any prepared requests to commit or wait for completion. */
+#define VERR_IOQUEUE_EMPTY (-26202)
+/** The I/O queue has requests pending which need complete first. */
+#define VERR_IOQUEUE_BUSY (-26203)
+/** @} */
+
+
+/** @name FTP status codes
+ * @{ */
+/** FTP Internal Server Error. */
+#define VERR_FTP_STATUS_SERVER_ERROR (-26400)
+/** FTP initialization failed. */
+#define VERR_FTP_INIT_FAILED (-26401)
+/** Data connection not found. */
+#define VERR_FTP_DATA_CONN_INIT_FAILED (-26402)
+/** Data connection not found. */
+#define VERR_FTP_DATA_CONN_NOT_FOUND (-26403)
+/** Data connection limit has been reached. */
+#define VERR_FTP_DATA_CONN_LIMIT_REACHED (-26404)
+/** Client not found. */
+#define VERR_FTP_CLIENT_NOT_FOUND (-26405)
+/** Client limit has been reached. */
+#define VERR_FTP_CLIENT_LIMIT_REACHED (-26406)
+/** @} */
+
+
+/** @name Trace Log status codes.
+ * @{ */
+/** The trace log is malformed. */
+#define VERR_TRACELOG_READER_MALFORMED_LOG (-26600)
+/** The trace log version is not supported. */
+#define VERR_TRACELOG_READER_LOG_UNSUPPORTED (-26601)
+/** The trace log reader iterator reached the end of the event list. */
+#define VERR_TRACELOG_READER_ITERATOR_END (-26602)
+/** @} */
+
+
+/** @name Hardened AVL tree status codes.
+ * @{ */
+/** Node index is out of bounds. */
+#define VERR_HARDAVL_INDEX_OUT_OF_BOUNDS (-26801)
+/** Node pointer is not within the memory allocated for nodes. */
+#define VERR_HARDAVL_POINTER_OUT_OF_BOUNDS (-26802)
+/** Node pointer does not point to the start of a node. */
+#define VERR_HARDAVL_MISALIGNED_POINTER (-26803)
+/** Bogus reference to freed node. */
+#define VERR_HARDAVL_NODE_IS_FREE (-26804)
+/** Stack overflow during AVL tree operation. */
+#define VERR_HARDAVL_STACK_OVERFLOW (-26810)
+/** Attempted to insert mode with invalid key range. */
+#define VERR_HARDAVL_INSERT_INVALID_KEY_RANGE (-26811)
+/** Bad left tree height. */
+#define VERR_HARDAVL_BAD_LEFT_HEIGHT (-26812)
+/** Bad left right height. */
+#define VERR_HARDAVL_BAD_RIGHT_HEIGHT (-26813)
+/** Bad new tree height. */
+#define VERR_HARDAVL_BAD_NEW_HEIGHT (-26814)
+/** Unexpected NULL pointer to left subtree. */
+#define VERR_HARDAVL_UNEXPECTED_NULL_LEFT (-26815)
+/** Unexpected NULL pointer to right subtree. */
+#define VERR_HARDAVL_UNEXPECTED_NULL_RIGHT (-26816)
+/** Tree traversal encountered more nodes than available in the allocator. */
+#define VERR_HARDAVL_TRAVERSED_TOO_MANY_NODES (-26817)
+/** Too deep walk during lookup. */
+#define VERR_HARDAVL_LOOKUP_TOO_DEEP (-26818)
+/** Bad tree height. */
+#define VERR_HARDAVL_BAD_HEIGHT (-26819)
+/** Unbalanced tree. */
+#define VERR_HARDAVL_UNBALANCED (-26820)
+/** @} */
+
+/* SED-END */
+
+/** @} */
+
+#endif /* !IPRT_INCLUDED_err_h */
+
diff --git a/include/iprt/err.mac b/include/iprt/err.mac
new file mode 100644
index 00000000..5bc57b9b
--- /dev/null
+++ b/include/iprt/err.mac
@@ -0,0 +1,1201 @@
+;; @file
+; IPRT - Status Codes.
+;
+; Automatically generated by err.sed. DO NOT EDIT!
+;
+
+;
+; Copyright (C) 2006-2022 Oracle and/or its affiliates.
+;
+; This file is part of VirtualBox base platform packages, as
+; available from https://www.virtualbox.org.
+;
+; This program is free software; you can redistribute it and/or
+; modify it under the terms of the GNU General Public License
+; as published by the Free Software Foundation, in version 3 of the
+; License.
+;
+; This program is distributed in the hope that it will be useful, but
+; WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with this program; if not, see <https://www.gnu.org/licenses>.
+;
+; The contents of this file may alternatively be used under the terms
+; of the Common Development and Distribution License Version 1.0
+; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+; in the VirtualBox 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.
+;
+; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+;
+
+%define VINF_SUCCESS 0
+%define VERR_GENERAL_FAILURE (-1)
+%define VERR_INVALID_PARAMETER (-2)
+%define VWRN_INVALID_PARAMETER 2
+%define VERR_INVALID_MAGIC (-3)
+%define VWRN_INVALID_MAGIC 3
+%define VERR_INVALID_HANDLE (-4)
+%define VWRN_INVALID_HANDLE 4
+%define VERR_LOCK_FAILED (-5)
+%define VERR_INVALID_POINTER (-6)
+%define VERR_IDT_FAILED (-7)
+%define VERR_NO_MEMORY (-8)
+%define VERR_ALREADY_LOADED (-9)
+%define VERR_PERMISSION_DENIED (-10)
+%define VINF_PERMISSION_DENIED 10
+%define VERR_VERSION_MISMATCH (-11)
+%define VERR_NOT_IMPLEMENTED (-12)
+%define VINF_NOT_IMPLEMENTED 12
+%define VERR_INVALID_FLAGS (-13)
+%define VERR_NOT_EQUAL (-18)
+%define VERR_NOT_SYMLINK (-19)
+%define VERR_NO_TMP_MEMORY (-20)
+%define VERR_INVALID_FMODE (-21)
+%define VERR_WRONG_ORDER (-22)
+%define VERR_NO_TLS_FOR_SELF (-23)
+%define VERR_FAILED_TO_SET_SELF_TLS (-24)
+%define VERR_NO_CONT_MEMORY (-26)
+%define VERR_NO_PAGE_MEMORY (-27)
+%define VINF_ALREADY_INITIALIZED 28
+%define VERR_ALREADY_INITIALIZED (-28)
+%define VERR_THREAD_IS_DEAD (-29)
+%define VERR_THREAD_NOT_WAITABLE (-30)
+%define VERR_PAGE_TABLE_NOT_PRESENT (-31)
+%define VERR_INVALID_CONTEXT (-32)
+%define VERR_TIMER_BUSY (-33)
+%define VERR_ADDRESS_CONFLICT (-34)
+%define VERR_UNRESOLVED_ERROR (-35)
+%define VERR_INVALID_FUNCTION (-36)
+%define VERR_NOT_SUPPORTED (-37)
+%define VINF_NOT_SUPPORTED 37
+%define VERR_ACCESS_DENIED (-38)
+%define VERR_INTERRUPTED (-39)
+%define VINF_INTERRUPTED 39
+%define VERR_TIMEOUT (-40)
+%define VINF_TIMEOUT 40
+%define VERR_BUFFER_OVERFLOW (-41)
+%define VINF_BUFFER_OVERFLOW 41
+%define VERR_TOO_MUCH_DATA (-42)
+%define VERR_MAX_THRDS_REACHED (-43)
+%define VERR_MAX_PROCS_REACHED (-44)
+%define VERR_SIGNAL_REFUSED (-45)
+%define VERR_SIGNAL_PENDING (-46)
+%define VERR_SIGNAL_INVALID (-47)
+%define VERR_STATE_CHANGED (-48)
+%define VWRN_STATE_CHANGED 48
+%define VERR_INVALID_UUID_FORMAT (-49)
+%define VERR_PROCESS_NOT_FOUND (-50)
+%define VERR_PROCESS_RUNNING (-51)
+%define VERR_TRY_AGAIN (-52)
+%define VINF_TRY_AGAIN 52
+%define VERR_PARSE_ERROR (-53)
+%define VERR_OUT_OF_RANGE (-54)
+%define VERR_NUMBER_TOO_BIG (-55)
+%define VWRN_NUMBER_TOO_BIG 55
+%define VERR_NO_DIGITS (-56)
+%define VWRN_NO_DIGITS 56
+%define VERR_NEGATIVE_UNSIGNED (-57)
+%define VWRN_NEGATIVE_UNSIGNED 57
+%define VERR_NO_TRANSLATION (-58)
+%define VWRN_NO_TRANSLATION 58
+%define VERR_CODE_POINT_ENDIAN_INDICATOR (-59)
+%define VERR_CODE_POINT_SURROGATE (-60)
+%define VERR_INVALID_UTF8_ENCODING (-61)
+%define VERR_INVALID_UTF16_ENCODING (-62)
+%define VERR_CANT_RECODE_AS_UTF16 (-63)
+%define VERR_NO_STR_MEMORY (-64)
+%define VERR_NO_UTF16_MEMORY (-65)
+%define VERR_NO_CODE_POINT_MEMORY (-66)
+%define VERR_MEMORY_BUSY (-67)
+%define VERR_TIMER_ACTIVE (-68)
+%define VERR_TIMER_SUSPENDED (-69)
+%define VERR_CANCELLED (-70)
+%define VERR_MEMOBJ_INIT_FAILED (-71)
+%define VERR_NO_LOW_MEMORY (-72)
+%define VERR_NO_PHYS_MEMORY (-73)
+%define VERR_ADDRESS_TOO_BIG (-74)
+%define VERR_MAP_FAILED (-75)
+%define VERR_TRAILING_CHARS (-76)
+%define VWRN_TRAILING_CHARS 76
+%define VERR_TRAILING_SPACES (-77)
+%define VWRN_TRAILING_SPACES 77
+%define VERR_NOT_FOUND (-78)
+%define VWRN_NOT_FOUND 78
+%define VERR_INVALID_STATE (-79)
+%define VWRN_INVALID_STATE 79
+%define VERR_OUT_OF_RESOURCES (-80)
+%define VWRN_OUT_OF_RESOURCES 80
+%define VERR_NO_MORE_HANDLES (-81)
+%define VERR_PREEMPT_DISABLED (-82)
+%define VERR_END_OF_STRING (-83)
+%define VINF_END_OF_STRING 83
+%define VERR_PAGE_COUNT_OUT_OF_RANGE (-84)
+%define VERR_OBJECT_DESTROYED (-85)
+%define VINF_OBJECT_DESTROYED 85
+%define VERR_DANGLING_OBJECTS (-86)
+%define VWRN_DANGLING_OBJECTS 86
+%define VERR_INVALID_BASE64_ENCODING (-87)
+%define VERR_CALLBACK_RETURN (-88)
+%define VINF_CALLBACK_RETURN 88
+%define VERR_AUTHENTICATION_FAILURE (-89)
+%define VERR_NOT_POWER_OF_TWO (-90)
+%define VERR_IGNORED (-91)
+%define VERR_CONCURRENT_ACCESS (-92)
+%define VERR_CALLER_NO_REFERENCE (-93)
+%define VERR_NO_CHANGE (-95)
+%define VINF_NO_CHANGE 95
+%define VERR_NO_EXEC_MEMORY (-96)
+%define VERR_UNSUPPORTED_ALIGNMENT (-97)
+%define VINF_UNSUPPORTED_ALIGNMENT 97
+%define VERR_DUPLICATE (-98)
+%define VERR_MISSING (-99)
+%define VERR_UNEXPECTED_EXCEPTION (-22400)
+%define VERR_BUFFER_UNDERFLOW (-22401)
+%define VINF_BUFFER_UNDERFLOW 22401
+%define VERR_UNEVEN_INPUT (-22402)
+%define VERR_NOT_AVAILABLE (-22403)
+%define VERR_PROC_DETACH_NOT_SUPPORTED (-22404)
+%define VERR_ACCOUNT_RESTRICTED (-22405)
+%define VINF_ACCOUNT_RESTRICTED 22405
+%define VERR_UNABLE_TO_SATISFY_REQUIREMENTS (-22406)
+%define VWRN_UNABLE_TO_SATISFY_REQUIREMENTS 22406
+%define VERR_ALLOCATION_TOO_BIG (-22407)
+%define VERR_MISMATCH (-22408)
+%define VERR_WRONG_TYPE (-22409)
+%define VWRN_WRONG_TYPE (22409)
+%define VERR_PRIVILEGE_NOT_HELD (-22410)
+%define VERR_PROC_TCB_PRIV_NOT_HELD (-22411)
+%define VERR_PROC_APT_PRIV_NOT_HELD (-22412)
+%define VERR_PROC_IQ_PRIV_NOT_HELD (-22413)
+%define VERR_MP_TOO_MANY_CPUS (-22414)
+%define VERR_WRONG_PARAMETER_COUNT (-22415)
+%define VERR_WRONG_PARAMETER_TYPE (-22416)
+%define VERR_INVALID_CLIENT_ID (-22417)
+%define VERR_INVALID_SESSION_ID (-22418)
+%define VERR_PROC_ELEVATION_REQUIRED (-22419)
+%define VERR_INCOMPATIBLE_CONFIG (-22420)
+%define VERR_NO_STRING_TERMINATOR (-22421)
+%define VERR_EMPTY_STRING (-22422)
+%define VERR_TOO_MANY_REFERENCES (-22423)
+%define VINF_THREAD_IS_TERMINATING (22424)
+%define VERR_THREAD_IS_TERMINATING (-22424)
+%define VERR_PROC_NO_ARG_TRANSLATION (-22425)
+%define VERR_FLOAT_UNDERFLOW (-22426)
+%define VWRN_FLOAT_UNDERFLOW (22426)
+%define VERR_FLOAT_OVERFLOW (-22427)
+%define VWRN_FLOAT_OVERFLOW (22427)
+%define VERR_FILE_IO_ERROR (-100)
+%define VERR_OPEN_FAILED (-101)
+%define VERR_FILE_NOT_FOUND (-102)
+%define VERR_PATH_NOT_FOUND (-103)
+%define VERR_INVALID_NAME (-104)
+%define VERR_ALREADY_EXISTS (-105)
+%define VWRN_ALREADY_EXISTS 105
+%define VERR_TOO_MANY_OPEN_FILES (-106)
+%define VERR_SEEK (-107)
+%define VERR_NEGATIVE_SEEK (-108)
+%define VERR_SEEK_ON_DEVICE (-109)
+%define VERR_EOF (-110)
+%define VINF_EOF 110
+%define VERR_READ_ERROR (-111)
+%define VERR_WRITE_ERROR (-112)
+%define VERR_WRITE_PROTECT (-113)
+%define VERR_SHARING_VIOLATION (-114)
+%define VERR_FILE_LOCK_FAILED (-115)
+%define VERR_FILE_LOCK_VIOLATION (-116)
+%define VERR_CANT_CREATE (-117)
+%define VERR_CANT_DELETE_DIRECTORY (-118)
+%define VERR_NOT_SAME_DEVICE (-119)
+%define VERR_FILENAME_TOO_LONG (-120)
+%define VERR_MEDIA_NOT_PRESENT (-121)
+%define VERR_MEDIA_NOT_RECOGNIZED (-122)
+%define VERR_FILE_NOT_LOCKED (-123)
+%define VERR_FILE_LOCK_LOST (-124)
+%define VERR_DIR_NOT_EMPTY (-125)
+%define VERR_NOT_A_DIRECTORY (-126)
+%define VERR_IS_A_DIRECTORY (-127)
+%define VERR_FILE_TOO_BIG (-128)
+%define VERR_FILE_AIO_NO_REQUEST (-129)
+%define VERR_FILE_AIO_IN_PROGRESS (-130)
+%define VERR_FILE_AIO_COMPLETED (-131)
+%define VERR_FILE_AIO_BUSY (-132)
+%define VERR_FILE_AIO_LIMIT_EXCEEDED (-133)
+%define VERR_FILE_AIO_CANCELED (-134)
+%define VERR_FILE_AIO_NOT_SUBMITTED (-135)
+%define VERR_FILE_AIO_NOT_PREPARED (-136)
+%define VERR_FILE_AIO_INSUFFICIENT_RESSOURCES (-137)
+%define VERR_RESOURCE_BUSY (-138)
+%define VERR_NOT_A_FILE (-139)
+%define VERR_IS_A_FILE (-140)
+%define VERR_UNEXPECTED_FS_OBJ_TYPE (-141)
+%define VERR_PATH_DOES_NOT_START_WITH_ROOT (-142)
+%define VERR_PATH_IS_RELATIVE (-143)
+%define VERR_PATH_IS_NOT_RELATIVE (-144)
+%define VERR_PATH_ZERO_LENGTH (-145)
+%define VERR_FILE_AIO_INSUFFICIENT_EVENTS (-146)
+%define VERR_STALE_FILE_HANDLE (-147)
+%define VERR_DISK_IO_ERROR (-150)
+%define VERR_INVALID_DRIVE (-151)
+%define VERR_DISK_FULL (-152)
+%define VERR_DISK_CHANGE (-153)
+%define VERR_DRIVE_LOCKED (-154)
+%define VERR_DISK_INVALID_FORMAT (-155)
+%define VERR_TOO_MANY_SYMLINKS (-156)
+%define VERR_NS_SYMLINK_SET_TIME (-157)
+%define VERR_NS_SYMLINK_CHANGE_OWNER (-158)
+%define VERR_SYMLINK_NOT_ALLOWED (-159)
+%define VERR_IS_A_SYMLINK (-160)
+%define VERR_IS_A_FIFO (-161)
+%define VERR_IS_A_SOCKET (-162)
+%define VERR_IS_A_BLOCK_DEVICE (-163)
+%define VERR_IS_A_CHAR_DEVICE (-164)
+%define VERR_DRIVE_IS_EMPTY (-165)
+%define VERR_SEARCH_ERROR (-200)
+%define VERR_NO_MORE_FILES (-201)
+%define VERR_NO_MORE_SEARCH_HANDLES (-202)
+%define VWRN_NO_DIRENT_INFO 203
+%define VERR_INTERNAL_ERROR (-225)
+%define VERR_INTERNAL_ERROR_2 (-226)
+%define VERR_INTERNAL_ERROR_3 (-227)
+%define VERR_INTERNAL_ERROR_4 (-228)
+%define VERR_INTERNAL_ERROR_5 (-229)
+%define VERR_IPE_UNEXPECTED_STATUS (-230)
+%define VERR_IPE_UNEXPECTED_INFO_STATUS (-231)
+%define VERR_IPE_UNEXPECTED_ERROR_STATUS (-232)
+%define VERR_IPE_UNINITIALIZED_STATUS (-233)
+%define VERR_IPE_NOT_REACHED_DEFAULT_CASE (-234)
+%define VERR_DEV_IO_ERROR (-250)
+%define VERR_IO_BAD_UNIT (-251)
+%define VERR_IO_NOT_READY (-252)
+%define VERR_IO_BAD_COMMAND (-253)
+%define VERR_IO_CRC (-254)
+%define VERR_IO_BAD_LENGTH (-255)
+%define VERR_IO_SECTOR_NOT_FOUND (-256)
+%define VERR_IO_GEN_FAILURE (-257)
+%define VERR_PIPE_IO_ERROR (-300)
+%define VERR_BROKEN_PIPE (-301)
+%define VERR_BAD_PIPE (-302)
+%define VERR_PIPE_BUSY (-303)
+%define VERR_NO_DATA (-304)
+%define VERR_PIPE_NOT_CONNECTED (-305)
+%define VERR_MORE_DATA (-306)
+%define VERR_PIPE_NOT_READ (-307)
+%define VERR_PIPE_NOT_WRITE (-308)
+%define VERR_SEM_ERROR (-350)
+%define VERR_TOO_MANY_SEMAPHORES (-351)
+%define VERR_EXCL_SEM_ALREADY_OWNED (-352)
+%define VERR_SEM_IS_SET (-353)
+%define VERR_TOO_MANY_SEM_REQUESTS (-354)
+%define VERR_NOT_OWNER (-355)
+%define VERR_TOO_MANY_OPENS (-356)
+%define VERR_TOO_MANY_POSTS (-357)
+%define VERR_ALREADY_POSTED (-358)
+%define VINF_ALREADY_POSTED (358)
+%define VERR_ALREADY_RESET (-359)
+%define VERR_SEM_BUSY (-360)
+%define VERR_SEM_OWNER_DIED (-361)
+%define VERR_SEM_NOT_FOUND (-362)
+%define VERR_SEM_DESTROYED (-363)
+%define VERR_SEM_NESTED (-364)
+%define VINF_SEM_NESTED (364)
+%define VERR_DEADLOCK (-365)
+%define VERR_SEM_OUT_OF_TURN (-366)
+%define VERR_SEM_BAD_CONTEXT (-367)
+%define VINF_SEM_BAD_CONTEXT (367)
+%define VERR_SEM_LV_WRONG_ORDER (-368)
+%define VERR_SEM_LV_WRONG_RELEASE_ORDER (-369)
+%define VERR_SEM_LV_NESTED (-370)
+%define VERR_SEM_LV_INVALID_PARAMETER (-371)
+%define VERR_SEM_LV_DEADLOCK (-372)
+%define VERR_SEM_LV_EXISTING_DEADLOCK (-373)
+%define VERR_SEM_LV_NOT_OWNER (-374)
+%define VERR_SEM_LV_ILLEGAL_UPGRADE (-375)
+%define VERR_SEM_LV_NOT_SIGNALLER (-376)
+%define VERR_SEM_LV_INTERNAL_ERROR (-377)
+%define VERR_NET_IO_ERROR (-400)
+%define VERR_NET_OUT_OF_RESOURCES (-401)
+%define VERR_NET_HOST_NOT_FOUND (-402)
+%define VERR_NET_PATH_NOT_FOUND (-403)
+%define VERR_NET_PRINT_ERROR (-404)
+%define VERR_NET_NO_NETWORK (-405)
+%define VERR_NET_NOT_UNIQUE_NAME (-406)
+%define VERR_NET_IN_PROGRESS (-436)
+%define VERR_NET_ALREADY_IN_PROGRESS (-437)
+%define VERR_NET_NOT_SOCKET (-438)
+%define VERR_NET_DEST_ADDRESS_REQUIRED (-439)
+%define VERR_NET_MSG_SIZE (-440)
+%define VERR_NET_PROTOCOL_TYPE (-441)
+%define VERR_NET_PROTOCOL_NOT_AVAILABLE (-442)
+%define VERR_NET_PROTOCOL_NOT_SUPPORTED (-443)
+%define VERR_NET_SOCKET_TYPE_NOT_SUPPORTED (-444)
+%define VERR_NET_OPERATION_NOT_SUPPORTED (-445)
+%define VERR_NET_PROTOCOL_FAMILY_NOT_SUPPORTED (-446)
+%define VERR_NET_ADDRESS_FAMILY_NOT_SUPPORTED (-447)
+%define VERR_NET_ADDRESS_IN_USE (-448)
+%define VERR_NET_ADDRESS_NOT_AVAILABLE (-449)
+%define VERR_NET_DOWN (-450)
+%define VERR_NET_UNREACHABLE (-451)
+%define VERR_NET_CONNECTION_RESET (-452)
+%define VERR_NET_CONNECTION_ABORTED (-453)
+%define VERR_NET_CONNECTION_RESET_BY_PEER (-454)
+%define VERR_NET_NO_BUFFER_SPACE (-455)
+%define VERR_NET_ALREADY_CONNECTED (-456)
+%define VERR_NET_NOT_CONNECTED (-457)
+%define VERR_NET_SHUTDOWN (-458)
+%define VERR_NET_TOO_MANY_REFERENCES (-459)
+%define VERR_NET_CONNECTION_TIMED_OUT (-460)
+%define VERR_NET_CONNECTION_REFUSED (-461)
+%define VERR_NET_HOST_DOWN (-464)
+%define VERR_NET_HOST_UNREACHABLE (-465)
+%define VERR_NET_PROTOCOL_ERROR (-466)
+%define VERR_NET_INCOMPLETE_TX_PACKET (-467)
+%define VERR_NET_INIT_FAILED (-468)
+%define VERR_NET_NOT_UNSUPPORTED (-469)
+%define VERR_TCP_SERVER_STOP (-500)
+%define VINF_TCP_SERVER_STOP 500
+%define VERR_TCP_SERVER_SHUTDOWN (-501)
+%define VERR_TCP_SERVER_DESTROYED (-502)
+%define VINF_TCP_SERVER_NO_CLIENT 503
+%define VERR_UDP_SERVER_STOP (-520)
+%define VINF_UDP_SERVER_STOP 520
+%define VERR_UDP_SERVER_SHUTDOWN (-521)
+%define VERR_UDP_SERVER_DESTROYED (-522)
+%define VINF_UDP_SERVER_NO_CLIENT 523
+%define VERR_L4_INVALID_DS_OFFSET (-550)
+%define VERR_IPC (-551)
+%define VERR_RESOURCE_IN_USE (-552)
+%define VERR_IPC_PROCESS_NOT_FOUND (-553)
+%define VERR_IPC_RECEIVE_TIMEOUT (-554)
+%define VERR_IPC_SEND_TIMEOUT (-555)
+%define VERR_IPC_RECEIVE_CANCELLED (-556)
+%define VERR_IPC_SEND_CANCELLED (-557)
+%define VERR_IPC_RECEIVE_ABORTED (-558)
+%define VERR_IPC_SEND_ABORTED (-559)
+%define VERR_IPC_RECEIVE_MAP_FAILED (-560)
+%define VERR_IPC_SEND_MAP_FAILED (-561)
+%define VERR_IPC_RECEIVE_SEND_PF_TIMEOUT (-562)
+%define VERR_IPC_SEND_SEND_PF_TIMEOUT (-563)
+%define VINF_IPC_RECEIVE_MSG_CUT 564
+%define VINF_IPC_SEND_MSG_CUT 565
+%define VERR_L4_DS_MANAGER_NOT_FOUND (-566)
+%define VERR_INVALID_EXE_SIGNATURE (-600)
+%define VERR_ELF_EXE_NOT_SUPPORTED (-601)
+%define VERR_PE_EXE_NOT_SUPPORTED (-602)
+%define VERR_LX_EXE_NOT_SUPPORTED (-603)
+%define VERR_LE_EXE_NOT_SUPPORTED (-604)
+%define VERR_NE_EXE_NOT_SUPPORTED (-605)
+%define VERR_MZ_EXE_NOT_SUPPORTED (-606)
+%define VERR_AOUT_EXE_NOT_SUPPORTED (-607)
+%define VERR_BAD_EXE_FORMAT (-608)
+%define VERR_SYMBOL_NOT_FOUND (-609)
+%define VERR_MODULE_NOT_FOUND (-610)
+%define VERR_SYMBOL_VALUE_TOO_BIG (-611)
+%define VERR_IMAGE_TOO_BIG (-612)
+%define VERR_IMAGE_BASE_TOO_HIGH (-614)
+%define VERR_LDR_ARCH_MISMATCH (-615)
+%define VERR_LDR_MISMATCH_NATIVE (-616)
+%define VERR_LDR_IMPORTED_SYMBOL_NOT_FOUND (-617)
+%define VERR_LDR_GENERAL_FAILURE (-618)
+%define VERR_LDR_IMAGE_HASH (-619)
+%define VERR_LDRPE_DELAY_IMPORT (-620)
+%define VERR_LDRPE_CERT_MALFORMED (-621)
+%define VERR_LDRPE_CERT_UNSUPPORTED (-622)
+%define VERR_LDRPE_GLOBALPTR (-623)
+%define VERR_LDRPE_TLS (-624)
+%define VERR_LDRPE_COM_DESCRIPTOR (-625)
+%define VERR_LDRPE_LOAD_CONFIG_SIZE (-626)
+%define VERR_LDRPE_LOCK_PREFIX_TABLE (-627)
+%define VERR_LDRPE_GUARD_CF_STUFF (-628)
+%define VERR_LDRELF_ODD_ENDIAN (-630)
+%define VERR_LDRELF_DYN (-631)
+%define VERR_LDRELF_EXEC (-632)
+%define VERR_LDRELF_MACHINE (-633)
+%define VERR_LDRELF_VERSION (-634)
+%define VERR_LDRELF_MULTIPLE_SYMTABS (-635)
+%define VERR_LDRELF_RELOCATION_NOT_SUPPORTED (-636)
+%define VERR_LDRELF_INVALID_SYMBOL_INDEX (-637)
+%define VERR_LDRELF_INVALID_SYMBOL_NAME_OFFSET (-638)
+%define VERR_LDRELF_INVALID_RELOCATION_OFFSET (-639)
+%define VERR_LDRELF_NO_SYMBOL_OR_NO_STRING_TABS (-640)
+%define VERR_LDRELF_UNTERMINATED_STRING_TAB (-641)
+%define VERR_LDR_INVALID_LINK_ADDRESS (-647)
+%define VERR_LDR_INVALID_RVA (-648)
+%define VERR_LDR_INVALID_SEG_OFFSET (-649)
+%define VERR_DBG_NO_LINE_NUMBERS (-650)
+%define VERR_DBG_NO_SYMBOLS (-651)
+%define VERR_DBG_INVALID_ADDRESS (-652)
+%define VERR_DBG_INVALID_SEGMENT_INDEX (-653)
+%define VERR_DBG_INVALID_SEGMENT_OFFSET (-654)
+%define VERR_DBG_INVALID_RVA (-655)
+%define VERR_DBG_SPECIAL_SEGMENT (-656)
+%define VERR_DBG_ADDRESS_CONFLICT (-657)
+%define VERR_DBG_DUPLICATE_SYMBOL (-658)
+%define VERR_DBG_SEGMENT_INDEX_CONFLICT (-659)
+%define VERR_DBG_LINE_NOT_FOUND (-660)
+%define VERR_DBG_SYMBOL_NAME_OUT_OF_RANGE (-661)
+%define VERR_DBG_FILE_NAME_OUT_OF_RANGE (-662)
+%define VERR_DBG_SEGMENT_NAME_OUT_OF_RANGE (-663)
+%define VERR_DBG_ADDRESS_WRAP (-664)
+%define VERR_DBG_NOT_NM_MAP_FILE (-665)
+%define VERR_DBG_NOT_LINUX_KALLSYMS (-666)
+%define VERR_DBG_NO_MATCHING_INTERPRETER (-667)
+%define VERR_DWARF_BAD_LINE_NUMBER_HEADER (-668)
+%define VERR_DWARF_UNEXPECTED_END (-669)
+%define VERR_DWARF_LEB_OVERFLOW (-670)
+%define VERR_DWARF_BAD_LNE (-671)
+%define VERR_DWARF_BAD_STRING (-672)
+%define VERR_DWARF_BAD_POS (-673)
+%define VERR_DWARF_BAD_INFO (-674)
+%define VERR_DWARF_BAD_ABBREV (-675)
+%define VERR_DWARF_ABBREV_NOT_FOUND (-676)
+%define VERR_DWARF_UNKNOWN_FORM (-677)
+%define VERR_DWARF_UNEXPECTED_FORM (-678)
+%define VERR_DWARF_TODO (-679)
+%define VERR_DWARF_UNKNOWN_LOC_OPCODE (-680)
+%define VERR_DWARF_STACK_OVERFLOW (-681)
+%define VERR_DWARF_STACK_UNDERFLOW (-682)
+%define VERR_DWARF_IPE (-683)
+%define VERR_DBG_CFG_INVALID_VALUE (-684)
+%define VERR_DBG_CFG_NOT_UINT_PROP (-685)
+%define VERR_DBG_DEFERRED_LOAD_FAILED (-686)
+%define VERR_DBG_TODO (-687)
+%define VERR_DBG_FILE_MISMATCH (-688)
+%define VERR_DBG_MOD_IPE (-689)
+%define VINF_DBG_ADJUSTED_SYM_SIZE 690
+%define VERR_CV_BAD_FORMAT (-691)
+%define VERR_CV_TODO (-692)
+%define VERR_CV_IPE (-693)
+%define VERR_DBG_NO_UNWIND_INFO (-694)
+%define VERR_DBG_UNWIND_INFO_NOT_FOUND (-695)
+%define VERR_DBG_MALFORMED_UNWIND_INFO (-696)
+%define VERR_RT_REQUEST_INVALID_TYPE (-700)
+%define VERR_RT_REQUEST_STATE (-701)
+%define VERR_RT_REQUEST_INVALID_PACKAGE (-702)
+%define VERR_RT_REQUEST_STATUS_STILL_PENDING (-703)
+%define VERR_RT_REQUEST_STATUS_FREED (-704)
+%define VERR_ENV_VAR_NOT_FOUND (-750)
+%define VINF_ENV_VAR_NOT_FOUND (750)
+%define VWRN_ENV_NOT_FULLY_TRANSLATED (751)
+%define VERR_ENV_INVALID_VAR_NAME (-752)
+%define VINF_ENV_VAR_UNSET (753)
+%define VERR_ENV_VAR_UNSET (-753)
+%define VERR_CPU_OFFLINE (-800)
+%define VERR_CPU_NOT_FOUND (-801)
+%define VERR_NOT_ALL_CPUS_SHOWED (-802)
+%define VERR_CPU_IPE_1 (-803)
+%define VERR_GETOPT_UNKNOWN_OPTION (-825)
+%define VERR_GETOPT_REQUIRED_ARGUMENT_MISSING (-826)
+%define VERR_GETOPT_INVALID_ARGUMENT_FORMAT (-827)
+%define VINF_GETOPT_NOT_OPTION 828
+%define VERR_GETOPT_INDEX_MISSING (-829)
+%define VERR_CACHE_FULL (-850)
+%define VERR_CACHE_EMPTY (-851)
+%define VERR_MEM_CACHE_MAX_SIZE (-855)
+%define VERR_S3_ACCESS_DENIED (-875)
+%define VERR_S3_NOT_FOUND (-876)
+%define VERR_S3_BUCKET_ALREADY_EXISTS (-877)
+%define VERR_S3_BUCKET_NOT_EMPTY (-878)
+%define VERR_S3_CANCELED (-879)
+%define VERR_HTTP_STATUS_SERVER_ERROR (-884)
+%define VERR_HTTP_INIT_FAILED (-885)
+%define VERR_HTTP_NOT_FOUND (-886)
+%define VERR_HTTP_ACCESS_DENIED (-887)
+%define VERR_HTTP_BAD_REQUEST (-888)
+%define VERR_HTTP_COULDNT_CONNECT (-889)
+%define VERR_HTTP_SSL_CONNECT_ERROR (-890)
+%define VERR_HTTP_CACERT_WRONG_FORMAT (-891)
+%define VERR_HTTP_CACERT_CANNOT_AUTHENTICATE (-892)
+%define VERR_HTTP_ABORTED (-893)
+%define VERR_HTTP_REDIRECTED (-894)
+%define VERR_HTTP_PROXY_NOT_FOUND (-895)
+%define VERR_HTTP_HOST_NOT_FOUND (-896)
+%define VERR_HTTP_CURL_PROXY_CONFIG (-897)
+%define VERR_HTTP_CURL_ERROR (-899)
+%define VERR_MANIFEST_UNSUPPORTED_DIGEST_TYPE (-900)
+%define VERR_MANIFEST_WRONG_FILE_FORMAT (-901)
+%define VERR_MANIFEST_DIGEST_MISMATCH (-902)
+%define VERR_MANIFEST_FILE_MISMATCH (-903)
+%define VERR_MANIFEST_ATTR_NOT_FOUND (-904)
+%define VERR_MANIFEST_ATTR_TYPE_MISMATCH (-905)
+%define VERR_MANIFEST_ATTR_TYPE_NOT_FOUND (-906)
+%define VERR_TAR_CHKSUM_MISMATCH (-925)
+%define VERR_TAR_END_OF_FILE (-926)
+%define VERR_TAR_UNEXPECTED_EOS (-927)
+%define VERR_TAR_EOS_MORE_INPUT (-928)
+%define VERR_TAR_BAD_NUM_FIELD (-929)
+%define VERR_TAR_BAD_NUM_FIELD_TERM (-930)
+%define VERR_TAR_BASE_256_NOT_SUPPORTED (-931)
+%define VERR_TAR_NUM_VALUE_TOO_LARGE (-932)
+%define VERR_TAR_DEV_VALUE_TOO_LARGE (-933)
+%define VERR_TAR_BAD_MODE_FIELD (-934)
+%define VERR_TAR_MODE_WITH_TYPE (-935)
+%define VERR_TAR_SIZE_NOT_ZERO (-936)
+%define VERR_TAR_UNKNOWN_TYPE_FLAG (-937)
+%define VERR_TAR_ZERO_HEADER (-938)
+%define VERR_TAR_NOT_USTAR_V00 (-939)
+%define VERR_TAR_EMPTY_NAME (-940)
+%define VERR_TAR_NON_DIR_ENDS_WITH_SLASH (-941)
+%define VERR_TAR_UNSUPPORTED_PAX_TYPE (-942)
+%define VERR_TAR_UNSUPPORTED_SOLARIS_HDR_TYPE (-943)
+%define VERR_TAR_UNSUPPORTED_GNU_HDR_TYPE (-944)
+%define VERR_TAR_BAD_CHKSUM_FIELD (-945)
+%define VERR_TAR_MALFORMED_GNU_LONGXXXX (-946)
+%define VERR_TAR_NAME_TOO_LONG (-947)
+%define VINF_TAR_DIR_PATH (948)
+%define VERR_POLL_HANDLE_NOT_POLLABLE (-950)
+%define VERR_POLL_HANDLE_ID_EXISTS (-951)
+%define VERR_POLL_HANDLE_ID_NOT_FOUND (-952)
+%define VERR_POLL_SET_IS_FULL (-953)
+%define VERR_PKZIP_NO_EOCB (-960)
+%define VERR_PKZIP_NAME_TOO_LONG (-961)
+%define VERR_PKZIP_BAD_LF_HEADER (-962)
+%define VERR_PKZIP_BAD_CDF_HEADER (-963)
+%define VERR_PKZIP_UNKNOWN_TYPE_FLAG (-964)
+%define VERR_PKZIP_ZIP64EX_IN_ZIP32 (-965)
+%define VERR_ZIP_ERROR (-22000)
+%define VERR_ZIP_CORRUPTED (-22001)
+%define VERR_ZIP_NO_MEMORY (-22002)
+%define VERR_ZIP_UNSUPPORTED_VERSION (-22003)
+%define VERR_ZIP_UNSUPPORTED_METHOD (-22004)
+%define VERR_ZIP_BAD_HEADER (-22005)
+%define VERR_VFS_CHAIN_NO_PREFIX (-22100)
+%define VERR_VFS_CHAIN_EMPTY (-22101)
+%define VERR_VFS_CHAIN_EXPECTED_ELEMENT (-22102)
+%define VERR_VFS_CHAIN_UNKNOWN_TYPE (-22103)
+%define VERR_VFS_CHAIN_EXPECTED_LEFT_PARENTHESES (-22104)
+%define VERR_VFS_CHAIN_EXPECTED_RIGHT_PARENTHESES (-22105)
+%define VERR_VFS_CHAIN_EXPECTED_PROVIDER_NAME (-22106)
+%define VERR_VFS_CHAIN_EXPECTED_SEPARATOR (-22107)
+%define VERR_VFS_CHAIN_LEADING_SEPARATOR (-22108)
+%define VERR_VFS_CHAIN_TRAILING_SEPARATOR (-22109)
+%define VERR_VFS_CHAIN_MUST_BE_FIRST_ELEMENT (-22110)
+%define VERR_VFS_CHAIN_CANNOT_BE_FIRST_ELEMENT (-22111)
+%define VERR_VFS_CHAIN_CAST_FAILED (-22112)
+%define VERR_VFS_CHAIN_IPE (-22113)
+%define VERR_VFS_CHAIN_PROVIDER_NOT_FOUND (-22114)
+%define VERR_VFS_CHAIN_FINAL_TYPE_MISMATCH (-22115)
+%define VERR_VFS_CHAIN_NO_ARGS (-22116)
+%define VERR_VFS_CHAIN_ONE_ARG (-22117)
+%define VERR_VFS_CHAIN_AT_MOST_ONE_ARG (-22118)
+%define VERR_VFS_CHAIN_AT_LEAST_ONE_ARG (-22119)
+%define VERR_VFS_CHAIN_TWO_ARGS (-22120)
+%define VERR_VFS_CHAIN_AT_LEAST_TWO_ARGS (-22121)
+%define VERR_VFS_CHAIN_AT_MOST_TWO_ARGS (-22122)
+%define VERR_VFS_CHAIN_THREE_ARGS (-22123)
+%define VERR_VFS_CHAIN_AT_LEAST_THREE_ARGS (-22124)
+%define VERR_VFS_CHAIN_AT_MOST_THREE_ARGS (-22125)
+%define VERR_VFS_CHAIN_FOUR_ARGS (-22126)
+%define VERR_VFS_CHAIN_AT_LEAST_FOUR_ARGS (-22127)
+%define VERR_VFS_CHAIN_AT_MOST_FOUR_ARGS (-22128)
+%define VERR_VFS_CHAIN_FIVE_ARGS (-22129)
+%define VERR_VFS_CHAIN_AT_LEAST_FIVE_ARGS (-22130)
+%define VERR_VFS_CHAIN_AT_MOST_FIVE_ARGS (-22131)
+%define VERR_VFS_CHAIN_SIX_ARGS (-22132)
+%define VERR_VFS_CHAIN_AT_LEAST_SIX_ARGS (-22133)
+%define VERR_VFS_CHAIN_AT_MOST_SIX_ARGS (-22134)
+%define VERR_VFS_CHAIN_TOO_FEW_ARGS (-22135)
+%define VERR_VFS_CHAIN_TOO_MANY_ARGS (-22136)
+%define VERR_VFS_CHAIN_EMPTY_ARG (-22137)
+%define VERR_VFS_CHAIN_INVALID_ARGUMENT (-22138)
+%define VERR_VFS_CHAIN_ONLY_FILE_OR_IOS (-22139)
+%define VERR_VFS_CHAIN_ONLY_IOS (-22140)
+%define VERR_VFS_CHAIN_ONLY_DIR (-22141)
+%define VERR_VFS_CHAIN_ONLY_FSS (-22142)
+%define VERR_VFS_CHAIN_ONLY_VFS (-22143)
+%define VERR_VFS_CHAIN_ONLY_FILE_OR_IOS_OR_DIR (-22144)
+%define VERR_VFS_CHAIN_ONLY_DIR_OR_VFS (-22145)
+%define VERR_VFS_CHAIN_TAKES_FILE (-22146)
+%define VERR_VFS_CHAIN_TAKES_FILE_OR_IOS (-22147)
+%define VERR_VFS_CHAIN_TAKES_DIR (-22148)
+%define VERR_VFS_CHAIN_TAKES_FSS (-22149)
+%define VERR_VFS_CHAIN_TAKES_VFS (-22150)
+%define VERR_VFS_CHAIN_TAKES_DIR_OR_VFS (-22151)
+%define VERR_VFS_CHAIN_TAKES_DIR_OR_FSS_OR_VFS (-22152)
+%define VERR_VFS_CHAIN_READ_ONLY_IOS (-22153)
+%define VERR_VFS_CHAIN_WRITE_ONLY_IOS (-22154)
+%define VERR_VFS_CHAIN_PATH_ONLY (-22155)
+%define VERR_VFS_CHAIN_TYPE_MISMATCH_PATH_ONLY (-22156)
+%define VERR_VFS_CHAIN_NOT_PATH_ONLY (-22157)
+%define VERR_VFS_CHAIN_TOO_SHORT_FOR_PARENT (-22158)
+%define VERR_DVM_MAP_EMPTY (-22200)
+%define VERR_DVM_MAP_NO_VOLUME (-22201)
+%define VERR_LOG_REVISION_MISMATCH (-22300)
+%define VINF_LOG_DISABLED (22301)
+%define VINF_LOG_NO_LOGGER (22302)
+%define VERR_SYS_CANNOT_POWER_OFF (-22500)
+%define VINF_SYS_MAY_POWER_OFF (22501)
+%define VERR_SYS_SHUTDOWN_FAILED (-22502)
+%define VERR_SYS_UNSUPPORTED_FIRMWARE_PROPERTY (-22503)
+%define VERR_FILESYSTEM_CORRUPT (-22600)
+%define VERR_XAR_WRONG_MAGIC (-22700)
+%define VERR_XAR_BAD_HDR_SIZE (-22701)
+%define VERR_XAR_UNSUPPORTED_VERSION (-22702)
+%define VERR_XAR_UNSUPPORTED_HASH_FUNCTION (-22703)
+%define VERR_XAR_TOC_TOO_SMALL (-22704)
+%define VERR_XAR_TOC_TOO_BIG (-22705)
+%define VERR_XAR_TOC_TOO_BIG_COMPRESSED (-22706)
+%define VERR_XAR_TOC_UNCOMP_SIZE_MISMATCH (-22707)
+%define VERR_XAR_TOC_STRLEN_MISMATCH (-22708)
+%define VERR_XAR_TOC_UTF8_ENCODING (-22709)
+%define VERR_XAR_TOC_XML_PARSE_ERROR (-22710)
+%define VERR_XML_TOC_ELEMENT_MISSING (-22711)
+%define VERR_XML_TOC_ELEMENT_HAS_SIBLINGS (-22712)
+%define VERR_XAR_TOC_DIGEST_MISMATCH (-22713)
+%define VERR_XAR_BAD_CHECKSUM_ELEMENT (-22714)
+%define VERR_XAR_HASH_FUNCTION_MISMATCH (-22715)
+%define VERR_XAR_BAD_DIGEST_LENGTH (-22716)
+%define VERR_XAR_NOT_STREAMBLE_ELEMENT_ORDER (-22717)
+%define VERR_XAR_MISSING_OFFSET_ELEMENT (-22718)
+%define VERR_XAR_BAD_OFFSET_ELEMENT (-22719)
+%define VERR_XAR_MISSING_SIZE_ELEMENT (-22720)
+%define VERR_XAR_BAD_SIZE_ELEMENT (-22721)
+%define VERR_XAR_MISSING_LENGTH_ELEMENT (-22722)
+%define VERR_XAR_BAD_LENGTH_ELEMENT (-22723)
+%define VERR_XAR_BAD_FILE_ELEMENT (-22724)
+%define VERR_XAR_MISSING_DATA_ELEMENT (-22725)
+%define VERR_XAR_UNKNOWN_FILE_TYPE (-22726)
+%define VERR_XAR_NO_ENCODING (-22727)
+%define VERR_XAR_BAD_FILE_TIMESTAMP (-22728)
+%define VERR_XAR_BAD_FILE_MODE (-22729)
+%define VERR_XAR_BAD_FILE_UID (-22730)
+%define VERR_XAR_BAD_FILE_GID (-22731)
+%define VERR_XAR_BAD_FILE_DEVICE_NO (-22732)
+%define VERR_XAR_BAD_FILE_INODE (-22733)
+%define VERR_XAR_INVALID_FILE_NAME (-22734)
+%define VERR_XAR_EXTRACTED_HASH_MISMATCH (-22735)
+%define VERR_XAR_EXTRACTED_SIZE_EXCEEDED (-22736)
+%define VERR_XAR_ARCHIVED_HASH_MISMATCH (-22737)
+%define VERR_XAR_UNUSED_ARCHIVED_DATA (-22738)
+%define VERR_XAR_ARCHIVED_AND_EXTRACTED_SIZES_MISMATCH (-22739)
+%define VERR_X509_READING_CERT_FROM_BIO (-23100)
+%define VERR_X509_EXTRACT_PUBKEY_FROM_CERT (-23101)
+%define VERR_X509_EXTRACT_RSA_FROM_PUBLIC_KEY (-23102)
+%define VERR_X509_RSA_VERIFICATION_FUILURE (-23103)
+%define VERR_X509_NO_BASIC_CONSTARAINTS (-23104)
+%define VERR_X509_GETTING_EXTENSION_FROM_CERT (-23105)
+%define VERR_X509_GETTING_DATA_FROM_EXTENSION (-23106)
+%define VERR_X509_PRINT_EXTENSION_TO_BIO (-23107)
+%define VERR_X509_CERTIFICATE_VERIFICATION_FAILURE (-23108)
+%define VERR_X509_NOT_SELFSIGNED_CERTIFICATE (-23109)
+%define VINF_X509_NOT_SELFSIGNED_CERTIFICATE 23109
+%define VERR_ASN1_ERROR (-22800)
+%define VERR_ASN1_STRING_TYPE_NOT_IMPLEMENTED (-22801)
+%define VERR_ASN1_INVALID_UTF8_STRING_ENCODING (-22802)
+%define VERR_ASN1_INVALID_NUMERIC_STRING_ENCODING (-22803)
+%define VERR_ASN1_INVALID_PRINTABLE_STRING_ENCODING (-22804)
+%define VERR_ASN1_INVALID_T61_STRING_ENCODING (-22805)
+%define VERR_ASN1_INVALID_VIDEOTEX_STRING_ENCODING (-22806)
+%define VERR_ASN1_INVALID_IA5_STRING_ENCODING (-22807)
+%define VERR_ASN1_INVALID_GRAPHIC_STRING_ENCODING (-22808)
+%define VERR_ASN1_INVALID_VISIBLE_STRING_ENCODING (-22809)
+%define VERR_ASN1_INVALID_GENERAL_STRING_ENCODING (-22810)
+%define VERR_ASN1_INVALID_UNIVERSAL_STRING_ENCODING (-22811)
+%define VERR_ASN1_INVALID_BMP_STRING_ENCODING (-22812)
+%define VERR_ASN1_INVALID_OBJID_ENCODING (-22813)
+%define VERR_ASN1_OBJID_COMPONENT_TOO_BIG (-22814)
+%define VERR_ASN1_OBJID_TOO_MANY_COMPONENTS (-22815)
+%define VERR_ASN1_OBJID_TOO_LONG_STRING_FORM (-22816)
+%define VERR_ASN1_OBJID_INVALID_DOTTED_STRING (-22817)
+%define VERR_ASN1_CONSTRUCTED_STRING_NOT_IMPL (-22818)
+%define VERR_ASN1_STRING_TAG_MISMATCH (-22819)
+%define VERR_ASN1_TIME_TAG_MISMATCH (-22820)
+%define VINF_ASN1_MORE_DATA (22821)
+%define VINF_ASN1_NOT_ENCODED (22822)
+%define VERR_ASN1_TELETEX_UNKNOWN_ESC_SEQ (-22823)
+%define VERR_ASN1_TELETEX_UNSUPPORTED_ESC_SEQ (-22824)
+%define VERR_ASN1_TELETEX_UNSUPPORTED_CHARSET (-22825)
+%define VERR_ASN1_NO_VTABLE (-22826)
+%define VERR_ASN1_NO_CHECK_SANITY_METHOD (-22827)
+%define VERR_ASN1_NOT_PRESENT (-22828)
+%define VERR_ASN1_CURSOR_NOT_AT_END (-22829)
+%define VERR_ASN1_CURSOR_LONG_TAG (-22830)
+%define VERR_ASN1_CURSOR_BAD_LENGTH_ENCODING (-22831)
+%define VERR_ASN1_CURSOR_ILLEGAL_INDEFINITE_LENGTH (-22832)
+%define VERR_ASN1_CURSOR_BAD_INDEFINITE_LENGTH (-22833)
+%define VERR_ASN1_CURSOR_BAD_LENGTH (-22834)
+%define VERR_ASN1_CURSOR_NO_MORE_DATA (-22835)
+%define VERR_ASN1_CURSOR_TOO_LITTLE_DATA_LEFT (-22836)
+%define VERR_ASN1_CURSOR_ILLEGAL_CONSTRUCTED_STRING (-22837)
+%define VERR_ASN1_CURSOR_TAG_MISMATCH (-22838)
+%define VERR_ASN1_CURSOR_TAG_FLAG_CLASS_MISMATCH (-22839)
+%define VERR_ASN1_BITSTRING_OUT_OF_BOUNDS (-22840)
+%define VERR_ASN1_TIME_BAD_NORMALIZE_INPUT (-22841)
+%define VERR_ASN1_TIME_NORMALIZE_ERROR (-22842)
+%define VERR_ASN1_TIME_NORMALIZE_MISMATCH (-22843)
+%define VERR_ASN1_INVALID_UTC_TIME_ENCODING (-22844)
+%define VERR_ASN1_INVALID_GENERALIZED_TIME_ENCODING (-22845)
+%define VERR_ASN1_INVALID_BOOLEAN_ENCODING (-22846)
+%define VERR_ASN1_INVALID_NULL_ENCODING (-22847)
+%define VERR_ASN1_INVALID_BITSTRING_ENCODING (-22848)
+%define VERR_ASN1_DYNTYPE_TAG_NOT_IMPL (-22849)
+%define VERR_ASN1_DYNTYPE_BAD_TAG (-22850)
+%define VERR_ASN1_DUMMY_OBJECT (-22851)
+%define VERR_ASN1_TOO_LONG (-22852)
+%define VERR_ASN1_EXPECTED_PRIMITIVE (-22853)
+%define VERR_ASN1_INVALID_DATA_POINTER (-22854)
+%define VERR_ASN1_TOO_DEEPLY_NESTED (-22855)
+%define VERR_ASN1_UNEXPECTED_OBJ_ID (-22856)
+%define VERR_ASN1_INVALID_INTEGER_ENCODING (-22857)
+%define VERR_ASN1_INTERNAL_ERROR_1 (-22895)
+%define VERR_ASN1_INTERNAL_ERROR_2 (-22896)
+%define VERR_ASN1_INTERNAL_ERROR_3 (-22897)
+%define VERR_ASN1_INTERNAL_ERROR_4 (-22898)
+%define VERR_ASN1_INTERNAL_ERROR_5 (-22899)
+%define VERR_LDRVI_NOT_SIGNED (-22900)
+%define VINF_LDRVI_NOT_SIGNED (22900)
+%define VERR_LDRVI_READ_ERROR_HDR (-22901)
+%define VERR_LDRVI_READ_ERROR_SHDRS (-22902)
+%define VERR_LDRVI_READ_ERROR_SIGNATURE (-22903)
+%define VERR_LDRVI_READ_ERROR_HASH (-22904)
+%define VERR_LDRVI_FILE_LENGTH_ERROR (-22905)
+%define VERR_LDRVI_NO_MEMORY_STATE (-22906)
+%define VERR_LDRVI_NO_MEMORY_SIGNATURE (-22907)
+%define VERR_LDRVI_NO_MEMORY_SHDRS (-22908)
+%define VERR_LDRVI_NO_MEMORY_PARSE_OUTPUT (-22909)
+%define VERR_LDRVI_INVALID_SECURITY_DIR_ENTRY (-22910)
+%define VERR_LDRVI_BAD_CERT_HDR_LENGTH (-22911)
+%define VERR_LDRVI_BAD_CERT_HDR_REVISION (-22912)
+%define VERR_LDRVI_BAD_CERT_HDR_TYPE (-22913)
+%define VERR_LDRVI_BAD_CERT_MULTIPLE (-22914)
+%define VERR_LDRVI_BAD_MZ_OFFSET (-22915)
+%define VERR_LDRVI_INVALID_SECTION_COUNT (-22916)
+%define VERR_LDRVI_SECTION_RAW_DATA_VALUES (-22917)
+%define VERR_LDRVI_MACHINE_OPT_HDR_MAGIC_MISMATCH (-22918)
+%define VERR_LDRVI_UNSUPPORTED_ARCH (-22919)
+%define VERR_LDRVI_PARSE_IPE (-22921)
+%define VERR_LDRVI_PARSE_BER_ERROR (-22922)
+%define VERR_LDRVI_EXPECTED_INDIRECT_DATA_CONTENT_OID (-22923)
+%define VERR_LDRVI_PAGE_HASH_TAB_SIZE_OVERFLOW (-22924)
+%define VERR_LDRVI_PAGE_HASH_TAB_TOO_LONG (-22925)
+%define VERR_LDRVI_PAGE_HASH_TAB_NOT_STRICTLY_SORTED (-22926)
+%define VERR_PAGE_HASH_TAB_HASHES_NON_SECTION_DATA (-22927)
+%define VERR_LDRVI_PAGE_HASH_MISMATCH (-22928)
+%define VERR_LDRVI_IMAGE_HASH_MISMATCH (-22929)
+%define VERR_LDRVI_BAD_CERT_FORMAT (-22930)
+%define VERR_LDR_FORWARDER (-22950)
+%define VERR_LDR_NOT_FORWARDER (-22951)
+%define VERR_LDR_BAD_FORWARDER (-22952)
+%define VERR_LDR_FORWARDER_CHAIN_TOO_LONG (-22953)
+%define VERR_LDR_FORWARDERS_NOT_SUPPORTED (-22954)
+%define VERR_LDRMACHO_OTHER_ENDIAN_NOT_SUPPORTED (-22955)
+%define VERR_LDRMACHO_BAD_HEADER (-22956)
+%define VERR_LDRMACHO_UNSUPPORTED_FILE_TYPE (-22957)
+%define VERR_LDRMACHO_UNSUPPORTED_MACHINE (-22958)
+%define VERR_LDRMACHO_BAD_LOAD_COMMAND (-22959)
+%define VERR_LDRMACHO_UNKNOWN_LOAD_COMMAND (-22960)
+%define VERR_LDRMACHO_UNSUPPORTED_LOAD_COMMAND (-22961)
+%define VERR_LDRMACHO_BAD_SECTION (-22962)
+%define VERR_LDRMACHO_UNSUPPORTED_SECTION (-22963)
+%define VERR_LDRMACHO_UNSUPPORTED_INIT_SECTION (-22964)
+%define VERR_LDRMACHO_UNSUPPORTED_TERM_SECTION (-22965)
+%define VERR_LDRMACHO_UNKNOWN_SECTION (-22966)
+%define VERR_LDRMACHO_BAD_SECTION_ORDER (-22967)
+%define VERR_LDRMACHO_BIT_MIX (-22968)
+%define VERR_LDRMACHO_BAD_OBJECT_FILE (-22969)
+%define VERR_LDRMACHO_BAD_SYMBOL (-22970)
+%define VERR_LDRMACHO_UNSUPPORTED_FIXUP_TYPE (-22971)
+%define VERR_LDRMACHO_MIXED_DEBUG_SECTION_FLAGS (-22972)
+%define VERR_LDRMACHO_NON_CONT_SEG_BITS (-22973)
+%define VERR_LDRMACHO_TODO (-22974)
+%define VERR_LDRMACHO_BAD_SYMTAB_SIZE (-22975)
+%define VERR_LDR_DUPLICATE_SEGMENT_NAME (-22976)
+%define VERR_LDR_NO_IMAGE_UUID (-22977)
+%define VERR_LDR_BAD_FIXUP (-22978)
+%define VERR_LDR_ADDRESS_OVERFLOW (-22979)
+%define VERR_LDRLX_BAD_HEADER (-22980)
+%define VERR_LDRLX_BAD_LOADER_SECTION (-22981)
+%define VERR_LDRLX_BAD_FIXUP_SECTION (-22982)
+%define VERR_LDRLX_BAD_OBJECT_TABLE (-22983)
+%define VERR_LDRLX_BAD_PAGE_MAP (-22984)
+%define VERR_LDRLX_BAD_ITERDATA (-22985)
+%define VERR_LDRLX_BAD_ITERDATA2 (-22986)
+%define VERR_LDRLX_BAD_BUNDLE (-22987)
+%define VERR_LDRLX_NO_SONAME (-22988)
+%define VERR_LDRLX_BAD_SONAME (-22989)
+%define VERR_LDRLX_BAD_FORWARDER (-22990)
+%define VERR_LDRLX_NRICHAIN_NOT_SUPPORTED (-22991)
+%define VERR_LDRLX_IMPORT_ORDINAL_OUT_OF_BOUNDS (-22992)
+%define VERR_CR_X509_GENERIC_ERROR (-23000)
+%define VERR_CR_X509_INTERNAL_ERROR (-23001)
+%define VERR_CR_X509_CERTPATHS_INTERNAL_ERROR (-23002)
+%define VERR_CR_X509_NOT_VERIFIED (-23003)
+%define VERR_CR_X509_NO_TRUST_ANCHOR (-23004)
+%define VERR_CR_X509_UNKNOWN_CERT_SIGN_ALGO (-23005)
+%define VERR_CR_X509_CERT_SIGN_ALGO_MISMATCH (-23006)
+%define VERR_CR_X509_CERT_TBS_SIGN_ALGO_MISMATCH (-23007)
+%define VERR_CR_X509_TBSCERT_EXTS_REQ_V3 (-23008)
+%define VERR_CR_X509_TBSCERT_UNIQUE_IDS_REQ_V2 (-23009)
+%define VERR_CR_X509_TBSCERT_SERIAL_NUMBER_OUT_OF_BOUNDS (-23010)
+%define VERR_CR_X509_TBSCERT_UNSUPPORTED_VERSION (-23011)
+%define VERR_CR_X509_PUBLIC_KEY_TOO_SMALL (-23012)
+%define VERR_CR_X509_INVALID_NAME_STRING_TAG (-23013)
+%define VERR_CR_X509_NAME_EMPTY_STRING (-23014)
+%define VERR_CR_X509_NAME_NOT_STRING (-23015)
+%define VERR_CR_X509_NAME_EMPTY_SET (-23016)
+%define VERR_CR_X509_NAME_EMPTY_SUB_SET (-23017)
+%define VERR_CR_X509_VALIDITY_SWAPPED (-23018)
+%define VERR_CR_X509_TBSCERT_DUPLICATE_EXTENSION (-23019)
+%define VERR_CR_X509_NAME_MISSING_RDN_MAP_ENTRY (-23020)
+%define VERR_CR_X509_CPV_NO_TRUSTED_PATHS (-23021)
+%define VERR_CR_X509_CPV_NO_VALID_POLICY (-23022)
+%define VERR_CR_X509_CPV_UNKNOWN_CRITICAL_EXTENSION (-23023)
+%define VERR_CR_X509_CPV_MISSING_KEY_CERT_SIGN (-23024)
+%define VERR_CR_X509_CPV_MAX_PATH_LENGTH (-23025)
+%define VERR_CR_X509_CPV_NOT_CA_CERT (-23026)
+%define VERR_CR_X509_CPV_NOT_V3_CERT (-23027)
+%define VERR_CR_X509_CPV_INVALID_POLICY_MAPPING (-23028)
+%define VERR_CR_X509_CPV_NO_PERMITTED_NAMES (-23029)
+%define VERR_CR_X509_CPV_NAME_NOT_PERMITTED (-23030)
+%define VERR_CR_X509_CPV_ALT_NAME_NOT_PERMITTED (-23031)
+%define VERR_CR_X509_CPV_ISSUER_MISMATCH (-23032)
+%define VERR_CR_X509_CPV_NOT_VALID_AT_TIME (-23033)
+%define VERR_CR_X509_CPV_UNEXP_GENERAL_SUBTREE_CHOICE (-23034)
+%define VERR_CR_X509_CPV_UNEXP_GENERAL_SUBTREE_MIN (-23035)
+%define VERR_CR_X509_CPV_UNEXP_GENERAL_SUBTREE_MAX (-23036)
+%define VERR_CR_X509_CPB_BAD_CERT_CTX (-23037)
+%define VERR_CR_X509_OSSL_D2I_FAILED (-23090)
+%define VERR_CR_PKCS7_GENERIC_ERROR (-23300)
+%define VERR_CR_PKCS7_NO_SIGNER_INFOS (-23301)
+%define VERR_CR_PKCS7_SIGNED_DATA_CERT_NOT_FOUND (-23302)
+%define VERR_CR_PKCS7_KEY_USAGE_MISMATCH (-23303)
+%define VERR_CR_PKCS7_MISSING_CONTENT_TYPE_ATTRIB (-23304)
+%define VERR_CR_PKCS7_CONTENT_TYPE_ATTRIB_MISMATCH (-23305)
+%define VERR_CR_PKCS7_BAD_CONTENT_TYPE_ATTRIB (-23306)
+%define VERR_CR_PKCS7_MISSING_MESSAGE_DIGEST_ATTRIB (-23307)
+%define VERR_CR_PKCS7_MESSAGE_DIGEST_ATTRIB_MISMATCH (-23308)
+%define VERR_CR_PKCS7_BAD_MESSAGE_DIGEST_ATTRIB (-23309)
+%define VERR_CR_PKCS7_SIGNATURE_VERIFICATION_FAILED (-23310)
+%define VERR_CR_PKCS7_INTERNAL_ERROR (-22311)
+%define VERR_CR_PKCS7_OSSL_D2I_FAILED (-22312)
+%define VERR_CR_PKCS7_OSSL_VERIFY_FAILED (-22313)
+%define VERR_CR_PKCS7_DIGEST_PARAMS_NOT_IMPL (-22314)
+%define VERR_CR_PKCS7_DIGEST_ALGO_NOT_FOUND_IN_LIST (-22315)
+%define VERR_CR_PKCS7_NOT_SIGNED_DATA (-22316)
+%define VERR_CR_PKCS7_NO_DIGEST_ALGORITHMS (-22317)
+%define VERR_CR_PKCS7_TOO_MANY_DIGEST_ALGORITHMS (-22318)
+%define VERR_CR_PKCS7_DIGEST_CREATE_ERROR (-22319)
+%define VERR_CR_PKCS7_DIGEST_CALC_ERROR (-22320)
+%define VERR_CR_PKCS7_SIGNED_DATA_VERSION (-22350)
+%define VERR_CR_PKCS7_SIGNED_DATA_NO_DIGEST_ALGOS (-22351)
+%define VERR_CR_PKCS7_UNKNOWN_DIGEST_ALGORITHM (-22352)
+%define VERR_CR_PKCS7_NO_CERTIFICATES (-22353)
+%define VERR_CR_PKCS7_EXPECTED_NO_CRLS (-22354)
+%define VERR_CR_PKCS7_EXPECTED_ONE_SIGNER_INFO (-22355)
+%define VERR_CR_PKCS7_SIGNER_INFO_VERSION (-22356)
+%define VERR_CR_PKCS7_SIGNER_INFO_NO_ISSUER_SERIAL_NO (-22357)
+%define VERR_CR_PKCS7_SIGNER_CERT_NOT_SHIPPED (-22358)
+%define VERR_CR_PKCS7_SIGNER_INFO_DIGEST_ENCRYPT_MISMATCH (-22359)
+%define VERR_CR_PKCS7_NOT_DATA (-22360)
+%define VERR_CR_SPC_GENERIC_ERROR (-23400)
+%define VERR_CR_SPC_NOT_EXACTLY_ONE_SIGNER_INFOS (-23401)
+%define VERR_CR_SPC_NOT_EXACTLY_ONE_DIGEST_ALGO (-23402)
+%define VERR_CR_SPC_SIGNED_IND_DATA_DIGEST_ALGO_MISMATCH (-23403)
+%define VERR_CR_SPC_IND_DATA_DIGEST_ALGO_NOT_IN_DIGEST_ALGOS (-23404)
+%define VERR_CR_SPC_UNKNOWN_DIGEST_ALGO (-23405)
+%define VERR_CR_SPC_IND_DATA_DIGEST_SIZE_MISMATCH (-23406)
+%define VERR_CR_SPC_EXPECTED_PE_IMAGE_DATA (-23407)
+%define VERR_CR_SPC_PEIMAGE_DATA_NOT_PRESENT (-23408)
+%define VERR_CR_SPC_BAD_MONIKER_UUID (-23409)
+%define VERR_CR_SPC_UNKNOWN_MONIKER_UUID (-23410)
+%define VERR_CR_SPC_BAD_MONIKER_CHOICE (-23411)
+%define VERR_CR_SPC_MONIKER_BAD_DATA (-23412)
+%define VERR_CR_SPC_PEIMAGE_MULTIPLE_HASH_TABS (-23413)
+%define VERR_CR_SPC_PEIMAGE_UNKNOWN_ATTRIBUTE (-23414)
+%define VERR_CR_SPC_PEIMAGE_URL_UNEXPECTED (-23415)
+%define VERR_CR_SPC_PEIMAGE_NO_CONTENT (-23416)
+%define VERR_CR_PKIX_GENERIC_ERROR (-23500)
+%define VERR_CR_PKIX_SIGNATURE_TAKES_NO_PARAMETERS (-23501)
+%define VERR_CR_PKIX_UNKNOWN_DIGEST_TYPE (-23502)
+%define VERR_CR_PKIX_INTERNAL_ERROR (-23503)
+%define VERR_CR_PKIX_HASH_TOO_LONG_FOR_KEY (-23504)
+%define VERR_CR_PKIX_SIGNATURE_TOO_LONG (-23505)
+%define VERR_CR_PKIX_SIGNATURE_GE_KEY (-23506)
+%define VERR_CR_PKIX_SIGNATURE_NEGATIVE (-23507)
+%define VERR_CR_PKIX_INVALID_SIGNATURE_LENGTH (-23508)
+%define VERR_CR_PKIX_SIGNATURE_MISMATCH (-23509)
+%define VERR_CR_PKIX_CIPHER_ALGO_PARAMS_NOT_IMPL (-23510)
+%define VERR_CR_PKIX_CIPHER_ALGO_NOT_KNOWN (-23511)
+%define VERR_CR_PKIX_OSSL_CIPHER_ALGO_NOT_KNOWN (-23512)
+%define VERR_CR_PKIX_OSSL_CIPHER_ALGO_NOT_KNOWN_EVP (-23513)
+%define VERR_CR_PKIX_OSSL_CIPHER_ALOG_INIT_FAILED (-23514)
+%define VERR_CR_PKIX_OSSL_VERIFY_FINAL_FAILED (-23515)
+%define VERR_CR_PKIX_OSSL_D2I_PUBLIC_KEY_FAILED (-23516)
+%define VERR_CR_PKIX_OSSL_EVP_PKEY_TYPE_ERROR (-23517)
+%define VERR_CR_PKIX_OSSL_D2I_PRIVATE_KEY_FAILED (-23518)
+%define VERR_CR_PKIX_OSSL_EVP_PKEY_RSA_PAD_ERROR (-23519)
+%define VERR_CR_PKIX_OSSL_SIGN_FINAL_FAILED (-23520)
+%define VERR_CR_PKIX_OSSL_VS_IPRT_SIGNATURE_SIZE (-23521)
+%define VERR_CR_PKIX_OSSL_VS_IPRT_SIGNATURE (-23522)
+%define VERR_CR_PKIX_NOT_RSA_PRIVATE_KEY (-23523)
+%define VERR_CR_PKIX_NOT_RSA_PUBLIC_KEY (-23524)
+%define VERR_CR_STORE_GENERIC_ERROR (-23700)
+%define VERR_CR_KEY_UNKNOWN_TYPE (-23800)
+%define VERR_CR_KEY_FORMAT_NOT_SUPPORTED (-23801)
+%define VERR_CR_KEY_ENCRYPTED (-23802)
+%define VERR_CR_KEY_NO_DEK_INFO (-23803)
+%define VERR_CR_KEY_DEK_INFO_TOO_LONG (-23804)
+%define VERR_CR_KEY_DECRYPTION_NOT_SUPPORTED (-23805)
+%define VERR_CR_KEY_UNSUPPORTED_CIPHER (-23806)
+%define VERR_CR_KEY_UNEXPECTED_CIPHER_PARAMS (-23807)
+%define VERR_CR_KEY_MISSING_CIPHER_PARAMS (-23808)
+%define VERR_CR_KEY_TOO_SHORT_CIPHER_IV (-23809)
+%define VERR_CR_KEY_MALFORMED_CIPHER_IV (-23810)
+%define VERR_CR_KEY_PASSWORD_ENCODING (-23811)
+%define VERR_CR_KEY_OSSL_DECRYPT_INIT_ERROR (-23812)
+%define VERR_CR_KEY_DECRYPTION_FAILED (-23813)
+%define VINF_CR_KEY_WAS_DECRYPTED (23814)
+%define VERR_CR_KEY_GEN_FAILED_RSA (-23815)
+%define VERR_CR_RSA_GENERIC_ERROR (-23900)
+%define VERR_BIGNUM_SENSITIVE_INPUT (-24000)
+%define VERR_BIGNUM_DIV_BY_ZERO (-24001)
+%define VERR_BIGNUM_NEGATIVE_EXPONENT (-24002)
+%define VERR_CR_DIGEST_OSSL_DIGEST_INIT_ERROR (-24200)
+%define VERR_CR_DIGEST_OSSL_DIGEST_CTX_COPY_ERROR (-24201)
+%define VINF_CR_DIGEST_DEPRECATED (24202)
+%define VERR_CR_DIGEST_DEPRECATED (-24202)
+%define VINF_CR_DIGEST_COMPROMISED (24203)
+%define VERR_CR_DIGEST_COMPROMISED (-24203)
+%define VINF_CR_DIGEST_SEVERELY_COMPROMISED (24204)
+%define VERR_CR_DIGEST_SEVERELY_COMPROMISED (-24204)
+%define VERR_CR_DIGEST_NOT_SUPPORTED (-24205)
+%define VERR_CR_PASSWORD_2_KEY_DERIVIATION_FAILED (-24396)
+%define VERR_CR_RANDOM_SETUP_FAILED (-24397)
+%define VERR_CR_RANDOM_FAILED (-24398)
+%define VERR_CR_MALFORMED_PEM_HEADER (-24399)
+%define VERR_PATH_MATCH_UNKNOWN_VARIABLE (-24400)
+%define VERR_PATH_MATCH_VARIABLE_MUST_BE_FIRST (-24401)
+%define VERR_PATH_MATCH_FEATURE_NOT_IMPLEMENTED (-24402)
+%define VERR_PATH_GLOB_UNKNOWN_CHAR_CLASS (-24403)
+%define VERR_URI_EMPTY (-24600)
+%define VERR_URI_TOO_SHORT (-24601)
+%define VERR_URI_INVALID_SCHEME (-24602)
+%define VERR_URI_INVALID_PORT_NUMBER (-24603)
+%define VERR_URI_INVALID_ESCAPE_SEQ (-24604)
+%define VERR_URI_ESCAPED_ZERO (-24605)
+%define VERR_URI_ESCAPED_CHARS_NOT_VALID_UTF8 (-24606)
+%define VERR_URI_INVALID_ESCAPED_UTF8_LEAD_BYTE (-24607)
+%define VERR_URI_INVALID_ESCAPED_UTF8_CONTINUATION_BYTE (-24608)
+%define VERR_URI_MISSING_UTF8_CONTINUATION_BYTE (-24609)
+%define VERR_URI_NOT_FILE_SCHEME (-24610)
+%define VERR_JSON_VALUE_INVALID_TYPE (-24700)
+%define VERR_JSON_ITERATOR_END (-24701)
+%define VERR_JSON_MALFORMED (-24702)
+%define VERR_JSON_IS_EMPTY (-24703)
+%define VERR_JSON_INVALID_UTF16_ESCAPE_SEQUENCE (-24704)
+%define VERR_JSON_MISSING_SURROGATE_PAIR (-24705)
+%define VERR_JSON_BAD_SURROGATE_PAIR_SEQUENCE (-24706)
+%define VERR_JSON_INVALID_CODEPOINT (-24707)
+%define VERR_VFS_UNKNOWN_FORMAT (-24800)
+%define VERR_VFS_BOGUS_FORMAT (-24801)
+%define VERR_VFS_BOGUS_OFFSET (-24802)
+%define VERR_VFS_UNSUPPORTED_FORMAT (-24803)
+%define VERR_VFS_UNSUPPORTED_CREATE_TYPE (-24804)
+%define VERR_ISOMK_BOOT_CAT_NO_VALIDATION_ENTRY (-25000)
+%define VERR_ISOMK_BOOT_CAT_NO_DEFAULT_ENTRY (-25001)
+%define VERR_ISOMK_BOOT_CAT_EXPECTED_SECTION_HEADER (-25002)
+%define VERR_ISOMK_BOOT_CAT_EMPTY_ENTRY (-25003)
+%define VERR_ISOMK_BOOT_CAT_INVALID_SECTION_SIZE (-25004)
+%define VERR_ISOMK_BOOT_CAT_ERRATIC_ENTRY (-25005)
+%define VERR_ISOMK_FILE_TOO_BIG_REQ_ISO_LEVEL_3 (-25006)
+%define VERR_ISOMK_SYMLINK_REQ_ROCK_RIDGE (-25007)
+%define VINF_ISOMK_SYMLINK_REQ_ROCK_RIDGE (25007)
+%define VERR_ISOMK_SYMLINK_SUPPORT_DISABLED (-25008)
+%define VERR_ISOMK_RR_NO_SPACE_FOR_CE (-25009)
+%define VERR_ISOMK_IPE_RR_READ (-25010)
+%define VERR_ISOMK_IPE_TABLE (-25011)
+%define VERR_ISOMK_IPE_NAMESPACE_1 (-25012)
+%define VERR_ISOMK_IPE_NAMESPACE_2 (-25013)
+%define VERR_ISOMK_IPE_NAMESPACE_3 (-25014)
+%define VERR_ISOMK_IPE_NAMESPACE_4 (-25015)
+%define VERR_ISOMK_IPE_NAMESPACE_5 (-25016)
+%define VERR_ISOMK_IPE_NAMESPACE_6 (-25017)
+%define VERR_ISOMK_IPE_EMPTY_PATH (-25018)
+%define VERR_ISOMK_IPE_EMPTY_COMPONENT (-25019)
+%define VERR_ISOMK_IPE_ROOT_SLASH (-25020)
+%define VERR_ISOMK_IPE_DESC_COUNT (-25021)
+%define VERR_ISOMK_IPE_BUFFER_SIZE (-25022)
+%define VERR_ISOMK_IPE_BOOT_CAT_FILE (-25023)
+%define VERR_ISOMK_IPE_PRODUCE_TRANS_TBL (-25024)
+%define VERR_ISOMK_IPE_READ_FILE_DATA_1 (-25025)
+%define VERR_ISOMK_IPE_READ_FILE_DATA_2 (-25026)
+%define VERR_ISOMK_IPE_READ_FILE_DATA_3 (-25027)
+%define VERR_ISOMK_IPE_FINALIZE_1 (-25028)
+%define VERR_ISOMK_RR_SPILL_FILE_FULL (-25029)
+%define VERR_ISOMK_IMPORT_UNKNOWN_FORMAT (-25100)
+%define VERR_ISOMK_IMPORT_TOO_MANY_VOL_DESCS (-25101)
+%define VERR_ISOMK_IMPORT_INVALID_VOL_DESC_HDR (-25102)
+%define VERR_ISOMK_IMPORT_MULTIPLE_PRIMARY_VOL_DESCS (-25103)
+%define VERR_ISOMK_IMPORT_MULTIPLE_EL_TORITO_DESCS (-25104)
+%define VERR_ISOMK_IMPORT_MULTIPLE_JOLIET_VOL_DESCS (-25105)
+%define VERR_ISOMK_IMPORT_SUPPLEMENTARY_BEFORE_PRIMARY (-25106)
+%define VERR_IOSMK_IMPORT_PRIMARY_VOL_DESC_VER (-25107)
+%define VERR_ISOMK_IMPORT_BAD_PRIMARY_VOL_DESC (-25108)
+%define VERR_IOSMK_IMPORT_SUP_VOL_DESC_VER (-25109)
+%define VERR_ISOMK_IMPORT_BAD_SUP_VOL_DESC (-25110)
+%define VERR_ISOMK_IMPORT_LOGICAL_BLOCK_SIZE_NOT_2KB (-25111)
+%define VERR_ISOMK_IMPORT_MORE_THAN_ONE_VOLUME_IN_SET (-25112)
+%define VERR_ISOMK_IMPORT_INVALID_VOLUMNE_SEQ_NO (-25113)
+%define VERR_ISOMK_IMPORT_VOLUME_SPACE_SIZE_MISMATCH (-25114)
+%define VERR_ISOMK_IMPORT_VOLUME_IN_SET_MISMATCH (-25115)
+%define VERR_ISOMK_IMPORT_BAD_ROOT_DIR_REC (-25116)
+%define VERR_ISOMK_IMPORT_ZERO_SIZED_ROOT_DIR (-25117)
+%define VERR_ISOMK_IMPORT_ROOT_VOLUME_SEQ_NO (-25118)
+%define VERR_ISOMK_IMPORT_ROOT_DIR_EXTENT_OUT_OF_BOUNDS (-25119)
+%define VERR_ISOMK_IMPORT_BAD_ROOT_DIR_REC_LENGTH (-25120)
+%define VERR_ISOMK_IMPORT_ROOT_DIR_WITHOUT_DIR_FLAG (-25121)
+%define VERR_ISOMK_IMPORT_ROOT_DIR_IS_MULTI_EXTENT (-25122)
+%define VERR_ISOMK_IMPORT_TOO_DEEP_DIR_TREE (-25123)
+%define VERR_ISOMK_IMPORT_BAD_DIR_REC (-25124)
+%define VERR_ISOMK_IMPORT_DIR_REC_VOLUME_SEQ_NO (-25125)
+%define VERR_ISOMK_IMPORT_DIR_REC_EXTENT_OUT_OF_BOUNDS (-25126)
+%define VERR_ISOMK_IMPORT_BAD_DIR_REC_LENGTH (-25127)
+%define VERR_ISOMK_IMPORT_DOT_DIR_REC_BAD_NAME_LENGTH (-25128)
+%define VERR_ISOMK_IMPORT_DOT_DIR_REC_BAD_NAME (-25129)
+%define VERR_ISOMK_IMPORT_DIR_WITH_MORE_EXTENTS (-25130)
+%define VERR_ISOMK_IMPORT_MISMATCHING_MULTI_EXTENT_REC (-25131)
+%define VERR_ISOMK_IMPORT_MISALIGNED_MULTI_EXTENT (-25132)
+%define VERR_ISOMK_IMPORT_NON_CONTIGUOUS_MULTI_EXTENT (-25133)
+%define VERR_ISOMK_IMPORT_BOOT_CAT_BAD_OUT_OF_BOUNDS (-25140)
+%define VERR_ISOMK_IMPORT_BOOT_CAT_BAD_VALIDATION_HEADER_ID (-25141)
+%define VERR_ISOMK_IMPORT_BOOT_CAT_BAD_VALIDATION_KEYS (-25142)
+%define VERR_ISOMK_IMPORT_BOOT_CAT_BAD_VALIDATION_CHECKSUM (-25143)
+%define VERR_ISOMK_IMPORT_BOOT_CAT_UNKNOWN_HEADER_ID (-25144)
+%define VERR_ISOMK_IMPORT_BOOT_CAT_INVALID_BOOT_MEDIA_TYPE (-25145)
+%define VERR_ISOMK_IMPORT_BOOT_CAT_DEF_ENTRY_INVALID_FLAGS (-25146)
+%define VERR_ISOMK_IMPORT_BOOT_CAT_ENTRY_RESERVED_FLAG (-25147)
+%define VERR_ISOMK_IMPORT_BOOT_CAT_ENTRY_USES_UNUSED_FIELD (-25148)
+%define VERR_ISOMK_IMPORT_BOOT_CAT_ENTRY_IMAGE_OUT_OF_BOUNDS (-25149)
+%define VERR_ISOMK_IMPORT_BOOT_CAT_ENTRY_UNKNOWN_IMAGE_SIZE (-25150)
+%define VERR_ISOMK_IMPORT_BOOT_CAT_MISSING_FINAL_OR_TOO_BIG (-25151)
+%define VERR_ISOMK_IMPORT_BOOT_CAT_DEF_ENTRY_INVALID_BOOT_IND (-25152)
+%define VERR_ISOMK_IMPORT_BOOT_CAT_EXT_ENTRY_INVALID_ID (-25153)
+%define VERR_ISOMK_IMPORT_BOOT_CAT_EXT_ENTRY_UNDEFINED_FLAGS (-25154)
+%define VERR_ISOMK_IMPORT_BOOT_CAT_EXT_ENTRY_END_OF_SECTOR (-25155)
+%define VERR_ISOMK_IMPORT_BOOT_CAT_ENTRY_CONTINUATION_WITH_NONE (-25156)
+%define VERR_ISOMK_IMPORT_BOOT_CAT_ENTRY_CONTINUATION_EOS (-25157)
+%define VERR_ISOFS_TAG_IS_ALL_ZEROS (-25300)
+%define VERR_ISOFS_UNSUPPORTED_TAG_VERSION (-25301)
+%define VERR_ISOFS_BAD_TAG_CHECKSUM (-25302)
+%define VERR_ISOFS_TAG_SECTOR_MISMATCH (-25303)
+%define VERR_ISOFS_DESC_CRC_MISMATCH (-25304)
+%define VERR_ISOFS_INSUFFICIENT_DATA_FOR_DESC_CRC (-25305)
+%define VERR_ISOFS_UNEXPECTED_VDS_DESC (-25306)
+%define VERR_ISOFS_TOO_MANY_PVDS (-25307)
+%define VERR_ISOFS_TOO_MANY_LVDS (-25308)
+%define VERR_ISOFS_TOO_MANY_PDS (-25309)
+%define VERR_ISOFS_TOO_BIT_PARTMAP_IN_LVD (-25310)
+%define VERR_ISOFS_NO_PVD (-25311)
+%define VERR_ISOFS_NO_LVD (-25312)
+%define VERR_ISOFS_NO_PD (-25313)
+%define VERR_ISOFS_MULTIPLE_PVDS (-25314)
+%define VERR_ISOFS_MULTIPLE_LVDS (-25315)
+%define VERR_ISOFS_TOO_MANY_PART_MAPS (-25316)
+%define VERR_ISOFS_MALFORMED_PART_MAP_TABLE (-25317)
+%define VERR_ISOFS_PARTITION_NOT_FOUND (-25318)
+%define VERR_ISOFS_INCOMPLETE_PART_MAP_TABLE (-25319)
+%define VERR_ISOFS_UNKNOWN_PART_MAP_ENTRY_TYPE (-25320)
+%define VERR_ISOFS_UNKNOWN_PART_MAP_TYPE_ID (-25321)
+%define VERR_ISOFS_VPM_NOT_SUPPORTED (-25322)
+%define VERR_ISOFS_SPM_NOT_SUPPORTED (-25323)
+%define VERR_ISOFS_MPM_NOT_SUPPORTED (-25324)
+%define VERR_ISOFS_UNSUPPORTED_LOGICAL_BLOCK_SIZE (-25325)
+%define VERR_ISOFS_BAD_LVD_DOMAIN_ID (-25326)
+%define VERR_ISOFS_BAD_LVD_FILE_SET_DESC_LOCATION (-25327)
+%define VERR_ISOFS_BAD_LVD_DESC_CHAR_SET (-25329)
+%define VERR_ISOFS_INVALID_PARTITION_INDEX (-25330)
+%define VERR_ISOFS_FSD_UNSUPPORTED_CHAR_SET (-25331)
+%define VERR_ISOFS_FSD_ZERO_ROOT_DIR (-25332)
+%define VERR_ISOFS_FSD_NEXT_EXTENT (-25333)
+%define VERR_ISOFS_ICB_TOO_BIG (-25334)
+%define VERR_ISOFS_ICB_TOO_SMALL (-25335)
+%define VERR_ISOFS_NO_DIRECT_ICB_ENTRIES (-25336)
+%define VERR_ISOFS_TOO_MANY_ICB_INDIRECTIONS (-25337)
+%define VERR_ISOFS_TOO_DEEP_ICB_RECURSION (-25338)
+%define VERR_ISOFS_ICB_ENTRY_TOO_SMALL (-25339)
+%define VERR_ISOFS_UNSUPPORTED_ICB (-25340)
+%define VERR_ISOFS_BAD_FILE_ENTRY (-25341)
+%define VERR_ISO_FS_UNKNOWN_AD_TYPE (-25342)
+%define VERR_ISOFS_BAD_EXTAD (-25343)
+%define VERR_ISOFS_WRONG_FILE_TYPE (-25344)
+%define VERR_ISOFS_UNKNOWN_FILE_TYPE (-25345)
+%define VERR_ISOFS_UDF_NOT_IMPLEMENTED (-25390)
+%define VERR_ISOFS_IPE_1 (-25391)
+%define VERR_ISOFS_IPE_2 (-25392)
+%define VERR_ISOFS_IPE_3 (-25393)
+%define VERR_ISOFS_IPE_4 (-25394)
+%define VERR_ISOFS_IPE_5 (-25395)
+%define VERR_SERIALPORT_BREAK_DETECTED (-25500)
+%define VERR_SERIALPORT_INVALID_BAUDRATE (-25501)
+%define VERR_REST_RESPONSE_CONTENT_TYPE_NOT_SUPPORTED (-25700)
+%define VERR_REST_RESPONSE_INVALID_UTF8_ENCODING (-25701)
+%define VERR_REST_RESPONSE_EMBEDDED_ZERO_CHAR (-25702)
+%define VERR_REST_RESPONSE_REPEAT_HEADER_FIELD (-25703)
+%define VWRN_REST_UNABLE_TO_DECODE_DATE (25704)
+%define VERR_REST_UNABLE_TO_DECODE_DATE (-25704)
+%define VERR_REST_WRONG_JSON_TYPE_FOR_BOOL (-25705)
+%define VERR_REST_WRONG_JSON_TYPE_FOR_INTEGER (-25706)
+%define VERR_REST_WRONG_JSON_TYPE_FOR_DOUBLE (-25707)
+%define VERR_REST_WRONG_JSON_TYPE_FOR_STRING (-25708)
+%define VERR_REST_WRONG_JSON_TYPE_FOR_DATE (-25709)
+%define VERR_REST_UNABLE_TO_PARSE_STRING_AS_BOOL (-25710)
+%define VERR_REST_PATH_PARAMETER_NOT_SET (-25711)
+%define VERR_REST_REQUIRED_QUERY_PARAMETER_NOT_SET (-25712)
+%define VERR_REST_REQUIRED_HEADER_PARAMETER_NOT_SET (-25713)
+%define VERR_REST_INTERNAL_ERROR_1 (-25791)
+%define VERR_REST_INTERNAL_ERROR_2 (-25792)
+%define VERR_REST_INTERNAL_ERROR_3 (-25793)
+%define VERR_REST_INTERNAL_ERROR_4 (-25794)
+%define VERR_REST_INTERNAL_ERROR_5 (-25795)
+%define VERR_REST_INTERNAL_ERROR_6 (-25796)
+%define VERR_REST_INTERNAL_ERROR_7 (-25797)
+%define VERR_REST_INTERNAL_ERROR_8 (-25798)
+%define VERR_REST_INTERNAL_ERROR_9 (-25799)
+%define VERR_CR_CIPHER_NOT_SUPPORTED (-25800)
+%define VERR_CR_CIPHER_OSSL_ENCRYPT_INIT_FAILED (-25801)
+%define VERR_CR_CIPHER_OSSL_ENCRYPT_UPDATE_FAILED (-25802)
+%define VERR_CR_CIPHER_OSSL_ENCRYPT_FINAL_FAILED (-25803)
+%define VERR_CR_CIPHER_OSSL_DECRYPT_INIT_FAILED (-25804)
+%define VERR_CR_CIPHER_OSSL_DECRYPT_UPDATE_FAILED (-25805)
+%define VERR_CR_CIPHER_OSSL_DECRYPT_FINAL_FAILED (-25806)
+%define VERR_CR_CIPHER_INVALID_KEY_LENGTH (-25807)
+%define VERR_CR_CIPHER_INVALID_INITIALIZATION_VECTOR_LENGTH (-25808)
+%define VERR_CR_CIPHER_INVALID_TAG_LENGTH (-25809)
+%define VERR_CR_CIPHER_OSSL_GET_TAG_FAILED (-25810)
+%define VERR_CR_CIPHER_OSSL_SET_TAG_FAILED (-25811)
+%define VERR_SHMEM_MAXIMUM_MAPPINGS_REACHED (-26000)
+%define VERR_IOQUEUE_HANDLE_NOT_REGISTERED (-26200)
+%define VERR_IOQUEUE_FULL (-26201)
+%define VERR_IOQUEUE_EMPTY (-26202)
+%define VERR_IOQUEUE_BUSY (-26203)
+%define VERR_FTP_STATUS_SERVER_ERROR (-26400)
+%define VERR_FTP_INIT_FAILED (-26401)
+%define VERR_FTP_DATA_CONN_INIT_FAILED (-26402)
+%define VERR_FTP_DATA_CONN_NOT_FOUND (-26403)
+%define VERR_FTP_DATA_CONN_LIMIT_REACHED (-26404)
+%define VERR_FTP_CLIENT_NOT_FOUND (-26405)
+%define VERR_FTP_CLIENT_LIMIT_REACHED (-26406)
+%define VERR_TRACELOG_READER_MALFORMED_LOG (-26600)
+%define VERR_TRACELOG_READER_LOG_UNSUPPORTED (-26601)
+%define VERR_TRACELOG_READER_ITERATOR_END (-26602)
+%define VERR_HARDAVL_INDEX_OUT_OF_BOUNDS (-26801)
+%define VERR_HARDAVL_POINTER_OUT_OF_BOUNDS (-26802)
+%define VERR_HARDAVL_MISALIGNED_POINTER (-26803)
+%define VERR_HARDAVL_NODE_IS_FREE (-26804)
+%define VERR_HARDAVL_STACK_OVERFLOW (-26810)
+%define VERR_HARDAVL_INSERT_INVALID_KEY_RANGE (-26811)
+%define VERR_HARDAVL_BAD_LEFT_HEIGHT (-26812)
+%define VERR_HARDAVL_BAD_RIGHT_HEIGHT (-26813)
+%define VERR_HARDAVL_BAD_NEW_HEIGHT (-26814)
+%define VERR_HARDAVL_UNEXPECTED_NULL_LEFT (-26815)
+%define VERR_HARDAVL_UNEXPECTED_NULL_RIGHT (-26816)
+%define VERR_HARDAVL_TRAVERSED_TOO_MANY_NODES (-26817)
+%define VERR_HARDAVL_LOOKUP_TOO_DEEP (-26818)
+%define VERR_HARDAVL_BAD_HEIGHT (-26819)
+%define VERR_HARDAVL_UNBALANCED (-26820)
diff --git a/include/iprt/err.sed b/include/iprt/err.sed
new file mode 100644
index 00000000..e094b083
--- /dev/null
+++ b/include/iprt/err.sed
@@ -0,0 +1,55 @@
+## @file
+# IPRT - SED script for converting VBox/err.h to .mac.
+#
+
+#
+# Copyright (C) 2006-2022 Oracle and/or its affiliates.
+#
+# This file is part of VirtualBox base platform packages, as
+# available from https://www.virtualbox.org.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation, in version 3 of the
+# License.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <https://www.gnu.org/licenses>.
+#
+# The contents of this file may alternatively be used under the terms
+# of the Common Development and Distribution License Version 1.0
+# (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+# in the VirtualBox 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.
+#
+# SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+#
+
+# Handle text inside the markers.
+/SED-START/,/SED-END/{
+
+# if (#define) goto defines
+/^[[:space:]]*#[[:space:]]*define/b defines
+
+}
+
+# Everything else is deleted!
+d
+b end
+
+##
+# Convert the defines
+:defines
+s/^[[:space:]]*#[[:space:]]*define[[:space:]]*\([[:alnum:]_]*\)[[:space:]]*\(.*\)[[:space:]]*$/%define \1 \2/
+b end
+
+# next expression
+:end
diff --git a/include/iprt/errcore.h b/include/iprt/errcore.h
new file mode 100644
index 00000000..12a09c1c
--- /dev/null
+++ b/include/iprt/errcore.h
@@ -0,0 +1,947 @@
+/** @file
+ * IPRT - Status Codes Core.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_errcore_h
+#define IPRT_INCLUDED_errcore_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+#include <iprt/stdarg.h>
+
+
+/** @defgroup grp_rt_err_core Status Codes Core
+ * @ingroup grp_rt_err
+ * @{
+ */
+
+/** @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(RTERR_NO_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) )
+
+
+#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) RT_NO_THROW_DEF
+ : m_rc(rcObj.getValue())
+ {
+ }
+
+ /**
+ * Integer constructor used by RT_SUCCESS_NP.
+ *
+ * @param rc IPRT style status code.
+ */
+ RTErrStrictType(int32_t rc) RT_NO_THROW_DEF
+ : 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 RT_NO_THROW_DEF
+ {
+ return m_rc >= 0;
+ }
+
+private:
+ /** @name Try ban a number of wrong types.
+ * @{ */
+ RTErrStrictType(uint8_t rc) RT_NO_THROW_DEF : m_rc(-999) { NOREF(rc); }
+ RTErrStrictType(uint16_t rc) RT_NO_THROW_DEF : m_rc(-999) { NOREF(rc); }
+ RTErrStrictType(uint32_t rc) RT_NO_THROW_DEF : m_rc(-999) { NOREF(rc); }
+ RTErrStrictType(uint64_t rc) RT_NO_THROW_DEF : m_rc(-999) { NOREF(rc); }
+ RTErrStrictType(int8_t rc) RT_NO_THROW_DEF : m_rc(-999) { NOREF(rc); }
+ RTErrStrictType(int16_t rc) RT_NO_THROW_DEF : m_rc(-999) { NOREF(rc); }
+ RTErrStrictType(int64_t rc) RT_NO_THROW_DEF : m_rc(-999) { NOREF(rc); }
+ /** @todo fight long here - clashes with int32_t/int64_t on some platforms. */
+ /** @} */
+};
+#endif /* __cplusplus */
+
+
+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 iNativeCode errno code.
+ */
+RTDECL(int) RTErrConvertFromErrno(int iNativeCode);
+
+/**
+ * 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);
+
+
+#ifndef DECLARED_FNRTSTROUTPUT /* duplicated in iprt/string.h & 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 DECLCALLBACKTYPE(size_t, FNRTSTROUTPUT,(void *pvArg, const char *pachChars, size_t cbChars));
+/** Pointer to callback function. */
+typedef FNRTSTROUTPUT *PFNRTSTROUTPUT;
+#endif
+
+#ifdef IN_RING3
+
+RTDECL(bool) RTErrIsKnown(int rc);
+RTDECL(ssize_t) RTErrQueryDefine(int rc, char *pszBuf, size_t cbBuf, bool fFailIfUnknown);
+RTDECL(ssize_t) RTErrQueryMsgShort(int rc, char *pszBuf, size_t cbBuf, bool fFailIfUnknown);
+RTDECL(ssize_t) RTErrQueryMsgFull(int rc, char *pszBuf, size_t cbBuf, bool fFailIfUnknown);
+
+/** @name Error formatters used internally by RTStrFormat.
+ * @internal
+ * @{ */
+RTDECL(size_t) RTErrFormatDefine( int rc, PFNRTSTROUTPUT pfnOutput, void *pvArgOutput, char *pszTmp, size_t cbTmp);
+RTDECL(size_t) RTErrFormatMsgShort(int rc, PFNRTSTROUTPUT pfnOutput, void *pvArgOutput, char *pszTmp, size_t cbTmp);
+RTDECL(size_t) RTErrFormatMsgFull( int rc, PFNRTSTROUTPUT pfnOutput, void *pvArgOutput, char *pszTmp, size_t cbTmp);
+RTDECL(size_t) RTErrFormatMsgAll( int rc, PFNRTSTROUTPUT pfnOutput, void *pvArgOutput, char *pszTmp, size_t cbTmp);
+/** @} */
+
+
+# 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;
+
+RTDECL(bool) RTErrWinIsKnown(long rc);
+RTDECL(ssize_t) RTErrWinQueryDefine(long rc, char *pszBuf, size_t cbBuf, bool fFailIfUnknown);
+
+/** @name Error formatters used internally by RTStrFormat.
+ * @internal
+ * @{ */
+RTDECL(size_t) RTErrWinFormatDefine(long rc, PFNRTSTROUTPUT pfnOutput, void *pvArgOutput, char *pszTmp, size_t cbTmp);
+RTDECL(size_t) RTErrWinFormatMsg( long rc, PFNRTSTROUTPUT pfnOutput, void *pvArgOutput, char *pszTmp, size_t cbTmp);
+RTDECL(size_t) RTErrWinFormatMsgAll(long rc, PFNRTSTROUTPUT pfnOutput, void *pvArgOutput, char *pszTmp, size_t cbTmp);
+/** @} */
+
+# 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;
+/** 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 /* !RT_OS_WINDOWS */
+
+#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);
+
+/** @name RTERRINFO_LOG_F_XXX
+ * @{ */
+/** Both debug and release log. */
+#define RTERRINFO_LOG_F_RELEASE RT_BIT_32(0)
+/** @} */
+
+/**
+ * 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 iLogGroup The logging group.
+ * @param fFlags RTERRINFO_LOG_F_XXX.
+ * @param pszMsg The error message string.
+ */
+RTDECL(int) RTErrInfoLogAndSet(PRTERRINFO pErrInfo, int rc, uint32_t iLogGroup, uint32_t fFlags, 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 iLogGroup The logging group.
+ * @param fFlags RTERRINFO_LOG_F_XXX.
+ * @param pszFormat The format string.
+ * @param ... The format arguments.
+ */
+RTDECL(int) RTErrInfoLogAndSetF(PRTERRINFO pErrInfo, int rc, uint32_t iLogGroup, uint32_t fFlags, const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(5, 6);
+
+/**
+ * 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 iLogGroup The logging group.
+ * @param fFlags RTERRINFO_LOG_F_XXX.
+ * @param pszFormat The format string.
+ * @param va The format arguments.
+ */
+RTDECL(int) RTErrInfoLogAndSetV(PRTERRINFO pErrInfo, int rc, uint32_t iLogGroup, uint32_t fFlags, const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(5, 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 iLogGroup The logging group.
+ * @param fFlags RTERRINFO_LOG_F_XXX.
+ * @param pszMsg The error message string to add.
+ */
+RTDECL(int) RTErrInfoLogAndAdd(PRTERRINFO pErrInfo, int rc, uint32_t iLogGroup, uint32_t fFlags, 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 iLogGroup The logging group.
+ * @param fFlags RTERRINFO_LOG_F_XXX.
+ * @param pszFormat The format string to add.
+ * @param ... The format arguments.
+ */
+RTDECL(int) RTErrInfoLogAndAddF(PRTERRINFO pErrInfo, int rc, uint32_t iLogGroup, uint32_t fFlags, const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(5, 6);
+
+/**
+ * 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 iLogGroup The logging group.
+ * @param fFlags RTERRINFO_LOG_F_XXX.
+ * @param pszFormat The format string to add.
+ * @param va The format arguments.
+ */
+RTDECL(int) RTErrInfoLogAndAddV(PRTERRINFO pErrInfo, int rc, uint32_t iLogGroup, uint32_t fFlags, const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(5, 0);
+
+/** @name Macros wrapping the RTErrInfoLog* functions.
+ * @{ */
+#ifndef LOG_DISABLED
+# define RTERRINFO_LOG_SET( a_pErrInfo, a_rc, a_pszMsg) RTErrInfoLogAndSet( a_pErrInfo, a_rc, LOG_GROUP, 0, a_pszMsg)
+# define RTERRINFO_LOG_SET_V(a_pErrInfo, a_rc, a_pszMsg, a_va) RTErrInfoLogAndSetV(a_pErrInfo, a_rc, LOG_GROUP, 0, a_pszMsg, a_va)
+# define RTERRINFO_LOG_ADD( a_pErrInfo, a_rc, a_pszMsg) RTErrInfoLogAndAdd( a_pErrInfo, a_rc, LOG_GROUP, 0, a_pszMsg)
+# define RTERRINFO_LOG_ADD_V(a_pErrInfo, a_rc, a_pszMsg, a_va) RTErrInfoLogAndAddV(a_pErrInfo, a_rc, LOG_GROUP, 0, a_pszMsg, a_va)
+# ifdef RT_COMPILER_SUPPORTS_VA_ARGS
+# define RTERRINFO_LOG_ADD_F(a_pErrInfo, a_rc, ...) RTErrInfoLogAndAddF(a_pErrInfo, a_rc, LOG_GROUP, 0, __VA_ARGS__)
+# define RTERRINFO_LOG_SET_F(a_pErrInfo, a_rc, ...) RTErrInfoLogAndSetF(a_pErrInfo, a_rc, LOG_GROUP, 0, __VA_ARGS__)
+# else
+# define RTERRINFO_LOG_ADD_F RTErrInfoAddF
+# define RTERRINFO_LOG_SET_F RTErrInfoSetF
+# endif
+#else
+# define RTERRINFO_LOG_SET( a_pErrInfo, a_rc, a_pszMsg) RTErrInfoSet( a_pErrInfo, a_rc, a_pszMsg)
+# define RTERRINFO_LOG_SET_V(a_pErrInfo, a_rc, a_pszMsg, a_va) RTErrInfoSetV(a_pErrInfo, a_rc, a_pszMsg, a_va)
+# define RTERRINFO_LOG_ADD( a_pErrInfo, a_rc, a_pszMsg) RTErrInfoAdd( a_pErrInfo, a_rc, a_pszMsg)
+# define RTERRINFO_LOG_ADD_V(a_pErrInfo, a_rc, a_pszMsg, a_va) RTErrInfoAddV(a_pErrInfo, a_rc, a_pszMsg, a_va)
+# define RTERRINFO_LOG_ADD_F RTErrInfoAddF
+# define RTERRINFO_LOG_SET_F RTErrInfoSetF
+#endif
+
+#define RTERRINFO_LOG_REL_SET( a_pErrInfo, a_rc, a_pszMsg) RTErrInfoLogAndSet( a_pErrInfo, a_rc, LOG_GROUP, RTERRINFO_LOG_F_RELEASE, a_pszMsg)
+#define RTERRINFO_LOG_REL_SET_V(a_pErrInfo, a_rc, a_pszMsg, a_va) RTErrInfoLogAndSetV(a_pErrInfo, a_rc, LOG_GROUP, RTERRINFO_LOG_F_RELEASE, a_pszMsg, a_va)
+#define RTERRINFO_LOG_REL_ADD( a_pErrInfo, a_rc, a_pszMsg) RTErrInfoLogAndAdd( a_pErrInfo, a_rc, LOG_GROUP, RTERRINFO_LOG_F_RELEASE, a_pszMsg)
+#define RTERRINFO_LOG_REL_ADD_V(a_pErrInfo, a_rc, a_pszMsg, a_va) RTErrInfoLogAndAddV(a_pErrInfo, a_rc, LOG_GROUP, RTERRINFO_LOG_F_RELEASE, a_pszMsg, a_va)
+#ifdef RT_COMPILER_SUPPORTS_VA_ARGS
+# define RTERRINFO_LOG_REL_ADD_F(a_pErrInfo, a_rc, ...) RTErrInfoLogAndAddF(a_pErrInfo, a_rc, LOG_GROUP, RTERRINFO_LOG_F_RELEASE, __VA_ARGS__)
+# define RTERRINFO_LOG_REL_SET_F(a_pErrInfo, a_rc, ...) RTErrInfoLogAndSetF(a_pErrInfo, a_rc, LOG_GROUP, RTERRINFO_LOG_F_RELEASE, __VA_ARGS__)
+#else
+# define RTERRINFO_LOG_REL_ADD_F RTErrInfoAddF
+# define RTERRINFO_LOG_REL_SET_F RTErrInfoSetF
+#endif
+/** @} */
+
+
+/**
+ * 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
+
+
+/* We duplicate a handful of very commonly used status codes from err.h here.
+ Needless to say, these needs to match the err.h definition exactly: */
+
+/** Success.
+ * @ingroup grp_rt_err */
+#define VINF_SUCCESS 0
+
+/** General failure - DON'T USE THIS!!!
+ * @ingroup grp_rt_err */
+#define VERR_GENERAL_FAILURE (-1)
+/** Invalid parameter.
+ * @ingroup grp_rt_err */
+#define VERR_INVALID_PARAMETER (-2)
+/** Invalid parameter.
+ * @ingroup grp_rt_err */
+#define VWRN_INVALID_PARAMETER 2
+/** Invalid magic or cookie.
+ * @ingroup grp_rt_err */
+#define VERR_INVALID_MAGIC (-3)
+/** Invalid magic or cookie.
+ * @ingroup grp_rt_err */
+#define VWRN_INVALID_MAGIC 3
+/** Invalid loader handle.
+ * @ingroup grp_rt_err */
+#define VERR_INVALID_HANDLE (-4)
+/** Invalid loader handle.
+ * @ingroup grp_rt_err */
+#define VWRN_INVALID_HANDLE 4
+/** Invalid memory pointer. */
+#define VERR_INVALID_POINTER (-6)
+/** Memory allocation failed.
+ * @ingroup grp_rt_err */
+#define VERR_NO_MEMORY (-8)
+/** Permission denied.
+ * @ingroup grp_rt_err */
+#define VERR_PERMISSION_DENIED (-10)
+/** Permission denied.
+ * @ingroup grp_rt_err */
+#define VINF_PERMISSION_DENIED 10
+/** Version mismatch.
+ * @ingroup grp_rt_err */
+#define VERR_VERSION_MISMATCH (-11)
+/** The request function is not implemented.
+ * @ingroup grp_rt_err */
+#define VERR_NOT_IMPLEMENTED (-12)
+/** Invalid flags was given.
+ * @ingroup grp_rt_err */
+#define VERR_INVALID_FLAGS (-13)
+/** Incorrect call order.
+ * @ingroup grp_rt_err */
+#define VERR_WRONG_ORDER (-22)
+/** Invalid function.
+ * @ingroup grp_rt_err */
+#define VERR_INVALID_FUNCTION (-36)
+/** Not supported.
+ * @ingroup grp_rt_err */
+#define VERR_NOT_SUPPORTED (-37)
+/** Not supported.
+ * @ingroup grp_rt_err */
+#define VINF_NOT_SUPPORTED 37
+/** Access denied.
+ * @ingroup grp_rt_err */
+#define VERR_ACCESS_DENIED (-38)
+/** Call interrupted.
+ * @ingroup grp_rt_err */
+#define VERR_INTERRUPTED (-39)
+/** Call interrupted.
+ * @ingroup grp_rt_err */
+#define VINF_INTERRUPTED 39
+/** Timeout.
+ * @ingroup grp_rt_err */
+#define VERR_TIMEOUT (-40)
+/** Timeout.
+ * @ingroup grp_rt_err */
+#define VINF_TIMEOUT 40
+/** Buffer too small to save result.
+ * @ingroup grp_rt_err */
+#define VERR_BUFFER_OVERFLOW (-41)
+/** Buffer too small to save result.
+ * @ingroup grp_rt_err */
+#define VINF_BUFFER_OVERFLOW 41
+/** Data size overflow.
+ * @ingroup grp_rt_err */
+#define VERR_TOO_MUCH_DATA (-42)
+/** Retry the operation.
+ * @ingroup grp_rt_err */
+#define VERR_TRY_AGAIN (-52)
+/** Retry the operation.
+ * @ingroup grp_rt_err */
+#define VINF_TRY_AGAIN 52
+/** Generic parse error.
+ * @ingroup grp_rt_err */
+#define VERR_PARSE_ERROR (-53)
+/** Value out of range.
+ * @ingroup grp_rt_err */
+#define VERR_OUT_OF_RANGE (-54)
+/** A numeric conversion encountered a value which was too big for the target.
+ * @ingroup grp_rt_err */
+#define VERR_NUMBER_TOO_BIG (-55)
+/** A numeric conversion encountered a value which was too big for the target.
+ * @ingroup grp_rt_err */
+#define VWRN_NUMBER_TOO_BIG 55
+/** The operation was cancelled by the user (copy) or another thread (local ipc).
+ * @ingroup grp_rt_err */
+#define VERR_CANCELLED (-70)
+/** Trailing characters.
+ * @ingroup grp_rt_err */
+#define VERR_TRAILING_CHARS (-76)
+/** Trailing characters.
+ * @ingroup grp_rt_err */
+#define VWRN_TRAILING_CHARS 76
+/** Trailing spaces.
+ * @ingroup grp_rt_err */
+#define VERR_TRAILING_SPACES (-77)
+/** Trailing spaces.
+ * @ingroup grp_rt_err */
+#define VWRN_TRAILING_SPACES 77
+/** Generic not found error.
+ * @ingroup grp_rt_err */
+#define VERR_NOT_FOUND (-78)
+/** Generic not found warning.
+ * @ingroup grp_rt_err */
+#define VWRN_NOT_FOUND 78
+/** Generic invalid state error.
+ * @ingroup grp_rt_err */
+#define VERR_INVALID_STATE (-79)
+/** Generic invalid state warning.
+ * @ingroup grp_rt_err */
+#define VWRN_INVALID_STATE 79
+/** Generic out of resources error.
+ * @ingroup grp_rt_err */
+#define VERR_OUT_OF_RESOURCES (-80)
+/** Generic out of resources warning.
+ * @ingroup grp_rt_err */
+#define VWRN_OUT_OF_RESOURCES 80
+/** End of string.
+ * @ingroup grp_rt_err */
+#define VERR_END_OF_STRING (-83)
+/** Return instigated by a callback or similar.
+ * @ingroup grp_rt_err */
+#define VERR_CALLBACK_RETURN (-88)
+/** Return instigated by a callback or similar.
+ * @ingroup grp_rt_err */
+#define VINF_CALLBACK_RETURN 88
+/** Duplicate something.
+ * @ingroup grp_rt_err */
+#define VERR_DUPLICATE (-98)
+/** Something is missing.
+ * @ingroup grp_rt_err */
+#define VERR_MISSING (-99)
+/** Buffer underflow.
+ * @ingroup grp_rt_err */
+#define VERR_BUFFER_UNDERFLOW (-22401)
+/** Buffer underflow.
+ * @ingroup grp_rt_err */
+#define VINF_BUFFER_UNDERFLOW 22401
+/** Something is not available or not working properly.
+ * @ingroup grp_rt_err */
+#define VERR_NOT_AVAILABLE (-22403)
+/** Mismatch.
+ * @ingroup grp_rt_err */
+#define VERR_MISMATCH (-22408)
+/** Wrong type.
+ * @ingroup grp_rt_err */
+#define VERR_WRONG_TYPE (-22409)
+/** Wrong type.
+ * @ingroup grp_rt_err */
+#define VWRN_WRONG_TYPE (22409)
+/** Wrong parameter count.
+ * @ingroup grp_rt_err */
+#define VERR_WRONG_PARAMETER_COUNT (-22415)
+/** Wrong parameter type.
+ * @ingroup grp_rt_err */
+#define VERR_WRONG_PARAMETER_TYPE (-22416)
+/** Invalid client ID.
+ * @ingroup grp_rt_err */
+#define VERR_INVALID_CLIENT_ID (-22417)
+/** Invalid session ID.
+ * @ingroup grp_rt_err */
+#define VERR_INVALID_SESSION_ID (-22418)
+/** Incompatible configuration requested.
+ * @ingroup grp_rt_err */
+#define VERR_INCOMPATIBLE_CONFIG (-22420)
+/** Internal error - this should never happen.
+ * @ingroup grp_rt_err */
+#define VERR_INTERNAL_ERROR (-225)
+/** RTGetOpt: Not an option.
+ * @ingroup grp_rt_err */
+#define VINF_GETOPT_NOT_OPTION 828
+/** RTGetOpt: Command line option not recognized.
+ * @ingroup grp_rt_err */
+#define VERR_GETOPT_UNKNOWN_OPTION (-825)
+
+/** @} */
+
+#endif /* !IPRT_INCLUDED_errcore_h */
+
diff --git a/include/iprt/errno.h b/include/iprt/errno.h
new file mode 100644
index 00000000..f41e677b
--- /dev/null
+++ b/include/iprt/errno.h
@@ -0,0 +1,441 @@
+/** @file
+ * IPRT - errno.h wrapper.
+ */
+
+/*
+ * Copyright (C) 2012-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_errno_h
+#define IPRT_INCLUDED_errno_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#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) /* solaris */
+# 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)
+# elif defined(RT_OS_WINDOWS)
+# define ENOMSG (122)
+# 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 (111)
+# 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)
+# elif defined(RT_OS_WINDOWS)
+# define EINPROGRESS (112)
+# else
+# define EINPROGRESS (150) /* solaris */
+# endif
+#endif
+#ifndef ENAMETOOLONG
+# if defined(RT_ERRNO_OS_BSD)
+# define ENAMETOOLONG (63)
+# elif defined(RT_OS_LINUX)
+# define ENAMETOOLONG (36)
+# elif defined(RT_OS_WINDOWS)
+# define ENAMETOOLONG (38)
+# else
+# define ENAMETOOLONG (78) /* solaris */
+# 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)
+# elif defined(RT_OS_WINDOWS)
+# define ENOLCK (39)
+# 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)
+# elif defined(RT_OS_WINDOWS)
+# define EALREADY (103)
+# else
+# define EALREADY (149)
+# endif
+#endif
+
+/* 38 - Also ENAMETOOLONG on Windows. */
+#ifndef ENOSYS
+# if defined(RT_ERRNO_OS_BSD)
+# define ENOSYS (78)
+# elif defined(RT_OS_LINUX)
+# define ENOSYS (38)
+# elif defined(RT_OS_WINDOWS)
+# define ENOSYS (40)
+# else
+# define ENOSYS (89) /* solaris */
+# endif
+#endif
+#ifndef ENOTSOCK
+# if defined(RT_ERRNO_OS_BSD)
+# define ENOTSOCK (38)
+# elif defined(RT_OS_LINUX)
+# define ENOTSOCK (88)
+# elif defined(RT_OS_WINDOWS)
+# define ENOTSOCK (128)
+# else
+# define ENOTSOCK (95) /* solaris */
+# endif
+#endif
+#ifndef EL2NSYNC
+# if defined(RT_OS_LINUX)
+# define EL2NSYNC (45)
+# elif defined(RT_ERRNO_OS_SYSV_HARDCORE)
+# define EL2NSYNC (38) /* solaris */
+# endif
+#endif
+
+/* 39 - Also ENOLCK on Windows. */
+#ifndef ENOTEMPTY
+# if defined(RT_ERRNO_OS_BSD)
+# define ENOTEMPTY (66)
+# elif defined(RT_OS_LINUX)
+# define ENOTEMPTY (39)
+# elif defined(RT_OS_WINDOWS)
+# define ENOTEMPTY (41)
+# else
+# define ENOTEMPTY (93) /* solaris */
+# endif
+#endif
+#ifndef EDESTADDRREQ
+# if defined(RT_ERRNO_OS_BSD)
+# define EDESTADDRREQ (39)
+# elif defined(RT_OS_LINUX)
+# define EDESTADDRREQ (89)
+# elif defined(RT_OS_WINDOWS)
+# define EDESTADDRREQ (109)
+# else
+# define EDESTADDRREQ (96) /* solaris */
+# endif
+#endif
+#ifndef EL3HLT
+# if defined(RT_OS_LINUX)
+# define EL3HLT (46)
+# elif defined(RT_ERRNO_OS_SYSV_HARDCORE)
+# define EL3HLT (39) /* solaris */
+# endif
+#endif
+
+/* 40 - Also ENOSYS on Windows. */
+#ifndef ELOOP
+# if defined(RT_ERRNO_OS_BSD)
+# define ELOOP (62)
+# elif defined(RT_OS_LINUX)
+# define ELOOP (40)
+# elif defined(RT_OS_WINDOWS)
+# define ELOOP (114)
+# else
+# define ELOOP (90) /* solaris */
+# endif
+#endif
+#ifndef EMSGSIZE
+# if defined(RT_ERRNO_OS_BSD)
+# define EMSGSIZE (40)
+# elif defined(RT_OS_LINUX)
+# define EMSGSIZE (90)
+# elif defined(RT_OS_WINDOWS)
+# define EMSGSIZE (115)
+# else
+# define EMSGSIZE (97) /* solaris */
+# endif
+#endif
+#ifndef EL3RST
+# if defined(RT_OS_LINUX)
+# define EL3RST (47)
+# elif defined(RT_ERRNO_OS_SYSV_HARDCORE)
+# define EL3RST (40) /* solaris */
+# endif
+#endif
+
+/** @todo errno constants {41..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)
+# elif defined(RT_OS_WINDOWS)
+# define ENOTSUP (129)
+# 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
+# elif defined(RT_OS_WINDOWS)
+# define EOPNOTSUPP (130)
+# 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)
+# elif defined(RT_OS_WINDOWS)
+# define EOVERFLOW (132)
+# 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 /* !IPRT_INCLUDED_errno_h */
diff --git a/include/iprt/expreval.h b/include/iprt/expreval.h
new file mode 100644
index 00000000..0ec98a59
--- /dev/null
+++ b/include/iprt/expreval.h
@@ -0,0 +1,159 @@
+/* $Id: expreval.h $ */
+/** @file
+ * IPRT - Expression Evaluator.
+ */
+
+/*
+ * Copyright (C) 2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_expreval_h
+#define IPRT_INCLUDED_expreval_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_expr_eval RTExprEval - Expression Evaluator
+ * @{ */
+
+/** Handle to an expression evaluator. */
+typedef struct RTEXPREVALINT *RTEXPREVAL;
+/** Pointer to an expression evaluator handle. */
+typedef RTEXPREVAL *PRTEXPREVAL;
+/** NIL expression evaluator handle. */
+#define NIL_RTEXPREVAL ((RTEXPREVAL)~(uintptr_t)0)
+
+/**
+ * Variable getter (supplied by user).
+ *
+ * @returns IPRT status code.
+ * @retval VERR_NOT_FOUND if the variable does not exist.
+ */
+typedef DECLCALLBACKTYPE(int, FNRTEXPREVALQUERYVARIABLE,(const char *pchName, size_t cchName, void *pvUser, char **ppszValue));
+/** Pointer to a variable getter. */
+typedef FNRTEXPREVALQUERYVARIABLE *PFNRTEXPREVALQUERYVARIABLE;
+
+/** @name Expression evaluator flags.
+ * @sa RTExprEvalCreate
+ * @{ */
+/** Default to hexadecimal instead of decimal numbers. */
+#define RTEXPREVAL_F_DEFAULT_BASE_16 RT_BIT_64(0)
+/** Enables C-ish octal style, i.e. 0777 be read as 0x1ff (in hex). */
+#define RTEXPREVAL_F_C_OCTAL RT_BIT_64(1)
+/** Enables the 'exists' operator that can be used to check if a path exists.
+ * @sa RTPathExists */
+#define RTEXPREVAL_F_EXISTS_OP RT_BIT_64(2)
+/** Valid mask. */
+#define RTEXPREVAL_F_VALID_MASK UINT64_MAX(3)
+/** @} */
+
+/**
+ * Creates an expression evaluator.
+ *
+ * @returns IPRT status code.
+ * @param phEval Where to return the handle to the evaluator.
+ * @param fFlags RTEXPREVAL_F_XXX.
+ * @param pszName The evaluator name (for logging).
+ * @param pvUser User argument for callbacks.
+ * @param pfnQueryVariable Callback for querying variables. Optional.
+ */
+RTDECL(int) RTExprEvalCreate(PRTEXPREVAL phEval, uint64_t fFlags, const char *pszName,
+ void *pvUser, PFNRTEXPREVALQUERYVARIABLE pfnQueryVariable);
+
+/**
+ * Retains a reference to the evaluator.
+ *
+ * @returns New reference count, UINT32_MAX if @a hEval is not valid.
+ * @param hEval Handle to the evaluator.
+ */
+RTDECL(uint32_t) RTExprEvalRetain(RTEXPREVAL hEval);
+
+/**
+ * Releases a reference to the evaluator.
+ *
+ * @returns New reference count, UINT32_MAX if @a hEval is not valid. (The
+ * evaluator was destroyed when 0 is returned.)
+ * @param hEval Handle to the evaluator.
+ */
+RTDECL(uint32_t) RTExprEvalRelease(RTEXPREVAL hEval);
+
+/**
+ * Evaluates the given if expression to a boolean result.
+ *
+ * @returns IPRT status code
+ * @param hEval Handle to the evaluator.
+ * @param pch The expression string. Does not need to be zero
+ * terminated.
+ * @param cch The length of the expression. Pass RTSTR_MAX if not
+ * known.
+ * @param pfResult Where to return the result.
+ * @param pErrInfo Where to return additional error info.
+ */
+RTDECL(int) RTExprEvalToBool(RTEXPREVAL hEval, const char *pch, size_t cch, bool *pfResult, PRTERRINFO pErrInfo);
+
+/**
+ * Evaluates the given if expression to an integer (signed 64-bit) result.
+ *
+ * @returns IPRT status code
+ * @param hEval Handle to the evaluator.
+ * @param pch The expression string. Does not need to be zero
+ * terminated.
+ * @param cch The length of the expression. Pass RTSTR_MAX if not
+ * known.
+ * @param piResult Where to return the result.
+ * @param pErrInfo Where to return additional error info.
+ */
+RTDECL(int) RTExprEvalToInteger(RTEXPREVAL hEval, const char *pch, size_t cch, int64_t *piResult, PRTERRINFO pErrInfo);
+
+/**
+ * Evaluates the given if expression to a string result.
+ *
+ * @returns IPRT status code
+ * @param hEval Handle to the evaluator.
+ * @param pch The expression string. Does not need to be zero
+ * terminated.
+ * @param cch The length of the expression. Pass RTSTR_MAX if not
+ * known.
+ * @param ppszResult Where to return the result. This must be freed using
+ * RTStrFree.
+ * @param pErrInfo Where to return additional error info.
+ */
+RTDECL(int) RTExprEvalToString(RTEXPREVAL hEval, const char *pch, size_t cch, char **ppszResult, PRTERRINFO pErrInfo);
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_expreval_h */
+
diff --git a/include/iprt/file.h b/include/iprt/file.h
new file mode 100644
index 00000000..6b36bfae
--- /dev/null
+++ b/include/iprt/file.h
@@ -0,0 +1,1826 @@
+/** @file
+ * IPRT - File I/O.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_file_h
+#define IPRT_INCLUDED_file_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+#include <iprt/stdarg.h>
+#include <iprt/fs.h>
+#include <iprt/sg.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_fileio RTFile - File I/O
+ * @ingroup grp_rt
+ * @{
+ */
+
+/** Platform specific text line break.
+ * @deprecated Use text I/O streams and '\\n'. See iprt/stream.h. */
+#if defined(RT_OS_OS2) || defined(RT_OS_WINDOWS)
+# define RTFILE_LINEFEED "\r\n"
+#else
+# define RTFILE_LINEFEED "\n"
+#endif
+
+/** Platform specific native standard input "handle". */
+#ifdef RT_OS_WINDOWS
+# define RTFILE_NATIVE_STDIN ((uint32_t)-10)
+#else
+# define RTFILE_NATIVE_STDIN 0
+#endif
+
+/** Platform specific native standard out "handle". */
+#ifdef RT_OS_WINDOWS
+# define RTFILE_NATIVE_STDOUT ((uint32_t)-11)
+#else
+# define RTFILE_NATIVE_STDOUT 1
+#endif
+
+/** Platform specific native standard error "handle". */
+#ifdef RT_OS_WINDOWS
+# define RTFILE_NATIVE_STDERR ((uint32_t)-12)
+#else
+# define RTFILE_NATIVE_STDERR 2
+#endif
+
+
+/**
+ * Checks if the specified file name exists and is a regular file.
+ *
+ * Symbolic links will be resolved.
+ *
+ * @returns true if it's a regular file, false if it isn't.
+ * @param pszPath The path to the file.
+ *
+ * @sa RTDirExists, RTPathExists, RTSymlinkExists.
+ */
+RTDECL(bool) RTFileExists(const char *pszPath);
+
+/**
+ * Queries the size of a file, given the path to it.
+ *
+ * Symbolic links will be resolved.
+ *
+ * @returns IPRT status code.
+ * @param pszPath The path to the file.
+ * @param pcbFile Where to return the file size (bytes).
+ *
+ * @sa RTFileQuerySize, RTPathQueryInfoEx.
+ */
+RTDECL(int) RTFileQuerySizeByPath(const char *pszPath, uint64_t *pcbFile);
+
+
+/** @name Open flags
+ * @{ */
+/** Attribute access only.
+ * @remarks Only accepted on windows, requires RTFILE_O_ACCESS_ATTR_MASK
+ * to yield a non-zero result. Otherwise, this is invalid. */
+#define RTFILE_O_ATTR_ONLY UINT32_C(0x00000000)
+/** Open the file with read access. */
+#define RTFILE_O_READ UINT32_C(0x00000001)
+/** Open the file with write access. */
+#define RTFILE_O_WRITE UINT32_C(0x00000002)
+/** Open the file with read & write access. */
+#define RTFILE_O_READWRITE UINT32_C(0x00000003)
+/** The file access mask.
+ * @remarks The value 0 is invalid, except for windows special case. */
+#define RTFILE_O_ACCESS_MASK UINT32_C(0x00000003)
+
+/** Open file in APPEND mode, so all writes to the file handle will
+ * append data at the end of the file.
+ * @remarks It is ignored if write access is not requested, that is
+ * RTFILE_O_WRITE is not set.
+ * @note Behaviour of functions differ between hosts: See RTFileWriteAt, as
+ * well as ticketref:19003 (RTFileSetSize). */
+#define RTFILE_O_APPEND UINT32_C(0x00000004)
+ /* UINT32_C(0x00000008) is unused atm. */
+
+/** Sharing mode: deny none. */
+#define RTFILE_O_DENY_NONE UINT32_C(0x00000080)
+/** Sharing mode: deny read. */
+#define RTFILE_O_DENY_READ UINT32_C(0x00000010)
+/** Sharing mode: deny write. */
+#define RTFILE_O_DENY_WRITE UINT32_C(0x00000020)
+/** Sharing mode: deny read and write. */
+#define RTFILE_O_DENY_READWRITE UINT32_C(0x00000030)
+/** Sharing mode: deny all. */
+#define RTFILE_O_DENY_ALL RTFILE_O_DENY_READWRITE
+/** Sharing mode: do NOT deny delete (NT).
+ * @remarks This might not be implemented on all platforms, and will be
+ * defaulted & ignored on those.
+ */
+#define RTFILE_O_DENY_NOT_DELETE UINT32_C(0x00000040)
+/** Sharing mode mask. */
+#define RTFILE_O_DENY_MASK UINT32_C(0x000000f0)
+
+/** Action: Open an existing file. */
+#define RTFILE_O_OPEN UINT32_C(0x00000700)
+/** Action: Create a new file or open an existing one. */
+#define RTFILE_O_OPEN_CREATE UINT32_C(0x00000100)
+/** Action: Create a new a file. */
+#define RTFILE_O_CREATE UINT32_C(0x00000200)
+/** Action: Create a new file or replace an existing one. */
+#define RTFILE_O_CREATE_REPLACE UINT32_C(0x00000300)
+/** Action mask. */
+#define RTFILE_O_ACTION_MASK UINT32_C(0x00000700)
+
+/** Turns off indexing of files on Windows hosts, *CREATE* only.
+ * @remarks Window only. */
+#define RTFILE_O_NOT_CONTENT_INDEXED UINT32_C(0x00000800)
+/** Truncate the file.
+ * @remarks This will not truncate files opened for read-only.
+ * @remarks The truncation doesn't have to be atomically, so anyone else opening
+ * the file may be racing us. The caller is responsible for not causing
+ * this race. */
+#define RTFILE_O_TRUNCATE UINT32_C(0x00001000)
+/** Make the handle inheritable on RTProcessCreate(/exec). */
+#define RTFILE_O_INHERIT UINT32_C(0x00002000)
+/** Open file in non-blocking mode - non-portable.
+ * @remarks This flag may not be supported on all platforms, in which case it's
+ * considered an invalid parameter. */
+#define RTFILE_O_NON_BLOCK UINT32_C(0x00004000)
+/** Write through directly to disk. Workaround to avoid iSCSI
+ * initiator deadlocks on Windows hosts.
+ * @remarks This might not be implemented on all platforms, and will be ignored
+ * on those. */
+#define RTFILE_O_WRITE_THROUGH UINT32_C(0x00008000)
+
+/** Attribute access: Attributes can be read if the file is being opened with
+ * read access, and can be written with write access. */
+#define RTFILE_O_ACCESS_ATTR_DEFAULT UINT32_C(0x00000000)
+/** Attribute access: Attributes can be read.
+ * @remarks Windows only. */
+#define RTFILE_O_ACCESS_ATTR_READ UINT32_C(0x00010000)
+/** Attribute access: Attributes can be written.
+ * @remarks Windows only. */
+#define RTFILE_O_ACCESS_ATTR_WRITE UINT32_C(0x00020000)
+/** Attribute access: Attributes can be both read & written.
+ * @remarks Windows only. */
+#define RTFILE_O_ACCESS_ATTR_READWRITE UINT32_C(0x00030000)
+/** Attribute access: The file attributes access mask.
+ * @remarks Windows only. */
+#define RTFILE_O_ACCESS_ATTR_MASK UINT32_C(0x00030000)
+
+/** Open file for async I/O
+ * @remarks This flag may not be needed on all platforms, and will be ignored on
+ * those. */
+#define RTFILE_O_ASYNC_IO UINT32_C(0x00040000)
+
+/** Disables caching.
+ *
+ * Useful when using very big files which might bring the host I/O scheduler to
+ * its knees during high I/O load.
+ *
+ * @remarks This flag might impose restrictions
+ * on the buffer alignment, start offset and/or transfer size.
+ *
+ * On Linux the buffer needs to be aligned to the 512 sector
+ * boundary.
+ *
+ * On Windows the FILE_FLAG_NO_BUFFERING is used (see
+ * http://msdn.microsoft.com/en-us/library/cc644950(VS.85).aspx ).
+ * The buffer address, the transfer size and offset needs to be aligned
+ * to the sector size of the volume. Furthermore FILE_APPEND_DATA is
+ * disabled. To write beyond the size of file use RTFileSetSize prior
+ * writing the data to the file.
+ *
+ * This flag does not work on Solaris if the target filesystem is ZFS.
+ * RTFileOpen will return an error with that configuration. When used
+ * with UFS the same alginment restrictions apply like Linux and
+ * Windows.
+ *
+ * @remarks This might not be implemented on all platforms, and will be ignored
+ * on those.
+ */
+#define RTFILE_O_NO_CACHE UINT32_C(0x00080000)
+
+/** Don't allow symbolic links as part of the path.
+ * @remarks this flag is currently not implemented and will be ignored. */
+#define RTFILE_O_NO_SYMLINKS UINT32_C(0x20000000)
+
+/** Unix file mode mask for use when creating files. */
+#define RTFILE_O_CREATE_MODE_MASK UINT32_C(0x1ff00000)
+/** The number of bits to shift to get the file mode mask.
+ * To extract it: (fFlags & RTFILE_O_CREATE_MODE_MASK) >> RTFILE_O_CREATE_MODE_SHIFT.
+ */
+#define RTFILE_O_CREATE_MODE_SHIFT 20
+
+/** Temporary file that should be automatically deleted when closed.
+ * If not supported by the OS, the open call will fail with VERR_NOT_SUPPORTED
+ * to prevent leaving undeleted files behind.
+ * @note On unix the file wont be visible and cannot be accessed by it's path.
+ * On Windows it will be visible but only accessible of deletion is
+ * shared. Not implemented on OS/2. */
+#define RTFILE_O_TEMP_AUTO_DELETE UINT32_C(0x40000000)
+
+ /* UINT32_C(0x80000000) is unused atm. */
+
+/** Mask of all valid flags.
+ * @remark This doesn't validate the access mode properly.
+ */
+#define RTFILE_O_VALID_MASK UINT32_C(0x7ffffff7)
+
+/** @} */
+
+
+/** Action taken by RTFileOpenEx. */
+typedef enum RTFILEACTION
+{
+ /** Invalid zero value. */
+ RTFILEACTION_INVALID = 0,
+ /** Existing file was opened (returned by RTFILE_O_OPEN and
+ * RTFILE_O_OPEN_CREATE). */
+ RTFILEACTION_OPENED,
+ /** New file was created (returned by RTFILE_O_CREATE and
+ * RTFILE_O_OPEN_CREATE). */
+ RTFILEACTION_CREATED,
+ /** Existing file was replaced (returned by RTFILE_O_CREATE_REPLACE). */
+ RTFILEACTION_REPLACED,
+ /** Existing file was truncated (returned if RTFILE_O_TRUNCATE take effect). */
+ RTFILEACTION_TRUNCATED,
+ /** The file already exists (returned by RTFILE_O_CREATE on failure). */
+ RTFILEACTION_ALREADY_EXISTS,
+ /** End of valid values. */
+ RTFILEACTION_END,
+ /** Type size hack. */
+ RTFILEACTION_32BIT_HACK = 0x7fffffff
+} RTFILEACTION;
+/** Pointer to action taken value (RTFileOpenEx). */
+typedef RTFILEACTION *PRTFILEACTION;
+
+
+#ifdef IN_RING3
+/**
+ * Force the use of open flags for all files opened after the setting is
+ * changed. The caller is responsible for not causing races with RTFileOpen().
+ *
+ * @returns iprt status code.
+ * @param fOpenForAccess Access mode to which the set/mask settings apply.
+ * @param fSet Open flags to be forced set.
+ * @param fMask Open flags to be masked out.
+ */
+RTR3DECL(int) RTFileSetForceFlags(unsigned fOpenForAccess, unsigned fSet, unsigned fMask);
+#endif /* IN_RING3 */
+
+/**
+ * Open a file.
+ *
+ * @returns iprt status code.
+ * @param pFile Where to store the handle to the opened file.
+ * @param pszFilename Path to the file which is to be opened. (UTF-8)
+ * @param fOpen Open flags, i.e a combination of the RTFILE_O_* defines.
+ * The ACCESS, ACTION and DENY flags are mandatory!
+ */
+RTDECL(int) RTFileOpen(PRTFILE pFile, const char *pszFilename, uint64_t fOpen);
+
+/**
+ * Open a file given as a format string.
+ *
+ * @returns iprt status code.
+ * @param pFile Where to store the handle to the opened file.
+ * @param fOpen Open flags, i.e a combination of the RTFILE_O_* defines.
+ * The ACCESS, ACTION and DENY flags are mandatory!
+ * @param pszFilenameFmt Format string givin the path to the file which is to
+ * be opened. (UTF-8)
+ * @param ... Arguments to the format string.
+ */
+RTDECL(int) RTFileOpenF(PRTFILE pFile, uint64_t fOpen, const char *pszFilenameFmt, ...) RT_IPRT_FORMAT_ATTR(3, 4);
+
+/**
+ * Open a file given as a format string.
+ *
+ * @returns iprt status code.
+ * @param pFile Where to store the handle to the opened file.
+ * @param fOpen Open flags, i.e a combination of the RTFILE_O_* defines.
+ * The ACCESS, ACTION and DENY flags are mandatory!
+ * @param pszFilenameFmt Format string givin the path to the file which is to
+ * be opened. (UTF-8)
+ * @param va Arguments to the format string.
+ */
+RTDECL(int) RTFileOpenV(PRTFILE pFile, uint64_t fOpen, const char *pszFilenameFmt, va_list va) RT_IPRT_FORMAT_ATTR(3, 0);
+
+/**
+ * Open a file, extended version.
+ *
+ * @returns iprt status code.
+ * @param pszFilename Path to the file which is to be opened. (UTF-8)
+ * @param fOpen Open flags, i.e a combination of the RTFILE_O_* defines.
+ * The ACCESS, ACTION and DENY flags are mandatory!
+ * @param phFile Where to store the handle to the opened file.
+ * @param penmActionTaken Where to return an indicator of which action was
+ * taken. This is optional and it is recommended to
+ * pass NULL when not strictly needed as it adds
+ * complexity (slower) on posix systems.
+ */
+RTDECL(int) RTFileOpenEx(const char *pszFilename, uint64_t fOpen, PRTFILE phFile, PRTFILEACTION penmActionTaken);
+
+/**
+ * Open the bit bucket (aka /dev/null or nul).
+ *
+ * @returns IPRT status code.
+ * @param phFile Where to store the handle to the opened file.
+ * @param fAccess The desired access only, i.e. read, write or both.
+ */
+RTDECL(int) RTFileOpenBitBucket(PRTFILE phFile, uint64_t fAccess);
+
+/**
+ * Duplicates a file handle.
+ *
+ * @returns IPRT status code.
+ * @param hFileSrc The handle to duplicate.
+ * @param fFlags RTFILE_O_INHERIT or zero.
+ * @param phFileNew Where to return the new file handle
+ */
+RTDECL(int) RTFileDup(RTFILE hFileSrc, uint64_t fFlags, PRTFILE phFileNew);
+
+/**
+ * Close a file opened by RTFileOpen().
+ *
+ * @returns iprt status code.
+ * @param File The file handle to close.
+ */
+RTDECL(int) RTFileClose(RTFILE File);
+
+/**
+ * Creates an IPRT file handle from a native one.
+ *
+ * @returns IPRT status code.
+ * @param pFile Where to store the IPRT file handle.
+ * @param uNative The native handle.
+ */
+RTDECL(int) RTFileFromNative(PRTFILE pFile, RTHCINTPTR uNative);
+
+/**
+ * Gets the native handle for an IPRT file handle.
+ *
+ * @return The native handle.
+ * @param File The IPRT file handle.
+ */
+RTDECL(RTHCINTPTR) RTFileToNative(RTFILE File);
+
+/**
+ * Delete a file.
+ *
+ * @returns iprt status code.
+ * @param pszFilename Path to the file which is to be deleted. (UTF-8)
+ * @todo This is a RTPath api!
+ */
+RTDECL(int) RTFileDelete(const char *pszFilename);
+
+/** @name Seek flags.
+ * @{ */
+/** Seek from the start of the file. */
+#define RTFILE_SEEK_BEGIN 0x00
+/** Seek from the current file position. */
+#define RTFILE_SEEK_CURRENT 0x01
+/** Seek from the end of the file. */
+#define RTFILE_SEEK_END 0x02
+/** @internal */
+#define RTFILE_SEEK_FIRST RTFILE_SEEK_BEGIN
+/** @internal */
+#define RTFILE_SEEK_LAST RTFILE_SEEK_END
+/** @} */
+
+
+/**
+ * Changes the read & write position in a file.
+ *
+ * @returns iprt status code.
+ * @param File Handle to the file.
+ * @param offSeek Offset to seek.
+ * @param uMethod Seek method, i.e. one of the RTFILE_SEEK_* defines.
+ * @param poffActual Where to store the new file position.
+ * NULL is allowed.
+ */
+RTDECL(int) RTFileSeek(RTFILE File, int64_t offSeek, unsigned uMethod, uint64_t *poffActual);
+
+/**
+ * Read bytes from a file.
+ *
+ * @returns iprt status code.
+ * @param File Handle to the file.
+ * @param pvBuf Where to put the bytes we read.
+ * @param cbToRead How much to read.
+ * @param pcbRead How much we actually read .
+ * If NULL an error will be returned for a partial read.
+ */
+RTDECL(int) RTFileRead(RTFILE File, void *pvBuf, size_t cbToRead, size_t *pcbRead);
+
+/**
+ * Read bytes from a file at a given offset.
+ *
+ * @returns iprt status code.
+ * @param File Handle to the file.
+ * @param off Where to read.
+ * @param pvBuf Where to put the bytes we read.
+ * @param cbToRead How much to read.
+ * @param pcbRead How much we actually read .
+ * If NULL an error will be returned for a partial read.
+ *
+ * @note OS/2 requires separate seek and write calls.
+ *
+ * @note Whether the file position is modified or not is host specific.
+ */
+RTDECL(int) RTFileReadAt(RTFILE File, RTFOFF off, void *pvBuf, size_t cbToRead, size_t *pcbRead);
+
+/**
+ * Read bytes from a file at a given offset into a S/G buffer.
+ *
+ * @returns iprt status code.
+ * @param hFile Handle to the file.
+ * @param pSgBuf Pointer to the S/G buffer to read into.
+ * @param cbToRead How much to read.
+ * @param pcbRead How much we actually read .
+ * If NULL an error will be returned for a partial read.
+ *
+ * @note It is not possible to guarantee atomicity on all platforms, so
+ * caller must take care wrt concurrent access to @a hFile.
+ */
+RTDECL(int) RTFileSgRead(RTFILE hFile, PRTSGBUF pSgBuf, size_t cbToRead, size_t *pcbRead);
+
+/**
+ * Read bytes from a file at a given offset into a S/G buffer.
+ *
+ * @returns iprt status code.
+ * @param hFile Handle to the file.
+ * @param off Where to read.
+ * @param pSgBuf Pointer to the S/G buffer to read into.
+ * @param cbToRead How much to read.
+ * @param pcbRead How much we actually read .
+ * If NULL an error will be returned for a partial read.
+ *
+ * @note Whether the file position is modified or not is host specific.
+ *
+ * @note It is not possible to guarantee atomicity on all platforms, so
+ * caller must take care wrt concurrent access to @a hFile.
+ */
+RTDECL(int) RTFileSgReadAt(RTFILE hFile, RTFOFF off, PRTSGBUF pSgBuf, size_t cbToRead, size_t *pcbRead);
+
+/**
+ * Write bytes to a file.
+ *
+ * @returns iprt status code.
+ * @param File Handle to the file.
+ * @param pvBuf What to write.
+ * @param cbToWrite How much to write.
+ * @param pcbWritten How much we actually wrote.
+ * If NULL an error will be returned for a partial write.
+ */
+RTDECL(int) RTFileWrite(RTFILE File, const void *pvBuf, size_t cbToWrite, size_t *pcbWritten);
+
+/**
+ * Write bytes to a file at a given offset.
+ *
+ * @returns iprt status code.
+ * @param hFile Handle to the file.
+ * @param off Where to write.
+ * @param pvBuf What to write.
+ * @param cbToWrite How much to write.
+ * @param pcbWritten How much we actually wrote.
+ * If NULL an error will be returned for a partial write.
+ *
+ * @note OS/2 requires separate seek and write calls.
+ *
+ * @note Whether the file position is modified or not is host specific.
+ *
+ * @note Whether @a off is used when @a hFile was opened with RTFILE_O_APPEND
+ * is also host specific. Currently Linux is the the only one
+ * documented to ignore @a off.
+ */
+RTDECL(int) RTFileWriteAt(RTFILE hFile, RTFOFF off, const void *pvBuf, size_t cbToWrite, size_t *pcbWritten);
+
+/**
+ * Write bytes from a S/G buffer to a file.
+ *
+ * @returns iprt status code.
+ * @param hFile Handle to the file.
+ * @param pSgBuf What to write.
+ * @param cbToWrite How much to write.
+ * @param pcbWritten How much we actually wrote.
+ * If NULL an error will be returned for a partial write.
+ *
+ * @note It is not possible to guarantee atomicity on all platforms, so
+ * caller must take care wrt concurrent access to @a hFile.
+ */
+RTDECL(int) RTFileSgWrite(RTFILE hFile, PRTSGBUF pSgBuf, size_t cbToWrite, size_t *pcbWritten);
+
+/**
+ * Write bytes from a S/G buffer to a file at a given offset.
+ *
+ * @returns iprt status code.
+ * @param hFile Handle to the file.
+ * @param off Where to write.
+ * @param pSgBuf What to write.
+ * @param cbToWrite How much to write.
+ * @param pcbWritten How much we actually wrote.
+ * If NULL an error will be returned for a partial write.
+ *
+ * @note It is not possible to guarantee atomicity on all platforms, so
+ * caller must take care wrt concurrent access to @a hFile.
+ *
+ * @note Whether the file position is modified or not is host specific.
+ *
+ * @note Whether @a off is used when @a hFile was opened with RTFILE_O_APPEND
+ * is also host specific. Currently Linux is the the only one
+ * documented to ignore @a off.
+ */
+RTDECL(int) RTFileSgWriteAt(RTFILE hFile, RTFOFF off, PRTSGBUF pSgBuf, size_t cbToWrite, size_t *pcbWritten);
+
+/**
+ * Flushes the buffers for the specified file.
+ *
+ * @returns iprt status code.
+ * @retval VINF_NOT_SUPPORTED if it is a special file that does not support
+ * flushing. This is reported as a informational status since in most
+ * cases this is entirely harmless (e.g. tty) and simplifies the usage.
+ * @param File Handle to the file.
+ */
+RTDECL(int) RTFileFlush(RTFILE File);
+
+/**
+ * Set the size of the file.
+ *
+ * @returns iprt status code.
+ * @param File Handle to the file.
+ * @param cbSize The new file size.
+ */
+RTDECL(int) RTFileSetSize(RTFILE File, uint64_t cbSize);
+
+/**
+ * Query the size of the file.
+ *
+ * @returns iprt status code.
+ * @param File Handle to the file.
+ * @param pcbSize Where to store the filesize.
+ */
+RTDECL(int) RTFileQuerySize(RTFILE File, uint64_t *pcbSize);
+
+/**
+ * Determine the maximum file size.
+ *
+ * @returns The max size of the file.
+ * -1 on failure, the file position is undefined.
+ * @param File Handle to the file.
+ * @see RTFileQueryMaxSizeEx.
+ */
+RTDECL(RTFOFF) RTFileGetMaxSize(RTFILE File);
+
+/**
+ * Determine the maximum file size.
+ *
+ * @returns IPRT status code.
+ * @param File Handle to the file.
+ * @param pcbMax Where to store the max file size.
+ * @see RTFileGetMaxSize.
+ */
+RTDECL(int) RTFileQueryMaxSizeEx(RTFILE File, PRTFOFF pcbMax);
+
+/**
+ * Queries the sector size (/ logical block size) for a disk or similar.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_INVALID_FUNCTION if not a disk/similar. Could also be returned
+ * if not really implemented.
+ * @param hFile Handle to the disk. This must typically be a device
+ * rather than a file or directory, though this may vary
+ * from OS to OS.
+ * @param pcbSector Where to store the sector size.
+ */
+RTDECL(int) RTFileQuerySectorSize(RTFILE hFile, uint32_t *pcbSector);
+
+/**
+ * Gets the current file position.
+ *
+ * @returns File offset.
+ * @returns ~0UUL on failure.
+ * @param File Handle to the file.
+ */
+RTDECL(uint64_t) RTFileTell(RTFILE File);
+
+/**
+ * Checks if the supplied handle is valid.
+ *
+ * @returns true if valid.
+ * @returns false if invalid.
+ * @param File The file handle
+ */
+RTDECL(bool) RTFileIsValid(RTFILE File);
+
+/**
+ * Copies a file.
+ *
+ * @returns IPRT status code
+ * @retval VERR_ALREADY_EXISTS if the destination file exists.
+ *
+ * @param pszSrc The path to the source file.
+ * @param pszDst The path to the destination file.
+ * This file will be created.
+ */
+RTDECL(int) RTFileCopy(const char *pszSrc, const char *pszDst);
+
+/**
+ * Copies a file given the handles to both files.
+ *
+ * @returns IPRT status code
+ *
+ * @param FileSrc The source file. The file position is unaltered.
+ * @param FileDst The destination file.
+ * On successful returns the file position is at the end of the file.
+ * On failures the file position and size is undefined.
+ */
+RTDECL(int) RTFileCopyByHandles(RTFILE FileSrc, RTFILE FileDst);
+
+/** Flags for RTFileCopyEx().
+ * @{ */
+/** Do not use RTFILE_O_DENY_WRITE on the source file to allow for copying files opened for writing. */
+#define RTFILECOPY_FLAGS_NO_SRC_DENY_WRITE RT_BIT(0)
+/** Do not use RTFILE_O_DENY_WRITE on the target file. */
+#define RTFILECOPY_FLAGS_NO_DST_DENY_WRITE RT_BIT(1)
+/** Do not use RTFILE_O_DENY_WRITE on either of the two files. */
+#define RTFILECOPY_FLAGS_NO_DENY_WRITE ( RTFILECOPY_FLAGS_NO_SRC_DENY_WRITE | RTFILECOPY_FLAGS_NO_DST_DENY_WRITE )
+/** */
+#define RTFILECOPY_FLAGS_MASK UINT32_C(0x00000003)
+/** @} */
+
+/**
+ * Copies a file.
+ *
+ * @returns IPRT status code
+ * @retval VERR_ALREADY_EXISTS if the destination file exists.
+ *
+ * @param pszSrc The path to the source file.
+ * @param pszDst The path to the destination file.
+ * This file will be created.
+ * @param fFlags Flags (RTFILECOPY_*).
+ * @param pfnProgress Pointer to callback function for reporting progress.
+ * @param pvUser User argument to pass to pfnProgress along with the completion percentage.
+ */
+RTDECL(int) RTFileCopyEx(const char *pszSrc, const char *pszDst, uint32_t fFlags, PFNRTPROGRESS pfnProgress, void *pvUser);
+
+/**
+ * Copies a file given the handles to both files and
+ * provide progress callbacks.
+ *
+ * @returns IPRT status code.
+ *
+ * @param FileSrc The source file. The file position is unaltered.
+ * @param FileDst The destination file.
+ * On successful returns the file position is at the end of the file.
+ * On failures the file position and size is undefined.
+ * @param pfnProgress Pointer to callback function for reporting progress.
+ * @param pvUser User argument to pass to pfnProgress along with the completion percentage.
+ */
+RTDECL(int) RTFileCopyByHandlesEx(RTFILE FileSrc, RTFILE FileDst, PFNRTPROGRESS pfnProgress, void *pvUser);
+
+/**
+ * Copies a part of a file to another one.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_EOF if @a pcbCopied is NULL and the end-of-file is reached
+ * before @a cbToCopy bytes have been copied.
+ *
+ * @param hFileSrc Handle to the source file. Must be readable.
+ * @param offSrc The source file offset.
+ * @param hFileDst Handle to the destination file. Must be writable and
+ * RTFILE_O_APPEND must be be in effect.
+ * @param offDst The destination file offset.
+ * @param cbToCopy How many bytes to copy.
+ * @param fFlags Reserved for the future, must be zero.
+ * @param pcbCopied Where to return the exact number of bytes copied.
+ * Optional.
+ *
+ * @note The file positions of @a hFileSrc and @a hFileDst are undefined
+ * upon return of this function.
+ *
+ * @sa RTFileCopyPartEx.
+ */
+RTDECL(int) RTFileCopyPart(RTFILE hFileSrc, RTFOFF offSrc, RTFILE hFileDst, RTFOFF offDst, uint64_t cbToCopy,
+ uint32_t fFlags, uint64_t *pcbCopied);
+
+
+/** Copy buffer state for RTFileCopyPartEx.
+ * @note The fields are considered internal!
+ */
+typedef struct RTFILECOPYPARTBUFSTATE
+{
+ /** Magic value (RTFILECOPYPARTBUFSTATE_MAGIC).
+ * @internal */
+ uint32_t uMagic;
+ /** Allocation type (internal).
+ * @internal */
+ int32_t iAllocType;
+ /** Buffer pointer.
+ * @internal */
+ uint8_t *pbBuf;
+ /** Buffer size.
+ * @internal */
+ size_t cbBuf;
+ /** Reserved.
+ * @internal */
+ void *papReserved[3];
+} RTFILECOPYPARTBUFSTATE;
+/** Pointer to copy buffer state for RTFileCopyPartEx(). */
+typedef RTFILECOPYPARTBUFSTATE *PRTFILECOPYPARTBUFSTATE;
+/** Magic value for the RTFileCopyPartEx() buffer state structure (Stephen John Fry). */
+#define RTFILECOPYPARTBUFSTATE_MAGIC UINT32_C(0x19570857)
+
+/**
+ * Prepares buffer state for one or more RTFileCopyPartEx() calls.
+ *
+ * Caller must call RTFileCopyPartCleanup() after the final RTFileCopyPartEx()
+ * call.
+ *
+ * @returns IPRT status code.
+ * @param pBufState The buffer state to prepare.
+ * @param cbToCopy The number of bytes we typically to copy in one
+ * RTFileCopyPartEx call.
+ */
+RTDECL(int) RTFileCopyPartPrep(PRTFILECOPYPARTBUFSTATE pBufState, uint64_t cbToCopy);
+
+/**
+ * Cleans up after RTFileCopyPartPrep() once the final RTFileCopyPartEx()
+ * call has been made.
+ *
+ * @param pBufState The buffer state to clean up.
+ */
+RTDECL(void) RTFileCopyPartCleanup(PRTFILECOPYPARTBUFSTATE pBufState);
+
+/**
+ * Copies a part of a file to another one, extended version.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_EOF if @a pcbCopied is NULL and the end-of-file is reached
+ * before @a cbToCopy bytes have been copied.
+ *
+ * @param hFileSrc Handle to the source file. Must be readable.
+ * @param offSrc The source file offset.
+ * @param hFileDst Handle to the destination file. Must be writable and
+ * RTFILE_O_APPEND must be be in effect.
+ * @param offDst The destination file offset.
+ * @param cbToCopy How many bytes to copy.
+ * @param fFlags Reserved for the future, must be zero.
+ * @param pBufState Copy buffer state prepared by RTFileCopyPartPrep().
+ * @param pcbCopied Where to return the exact number of bytes copied.
+ * Optional.
+ *
+ * @note The file positions of @a hFileSrc and @a hFileDst are undefined
+ * upon return of this function.
+ *
+ * @sa RTFileCopyPart.
+ */
+RTDECL(int) RTFileCopyPartEx(RTFILE hFileSrc, RTFOFF offSrc, RTFILE hFileDst, RTFOFF offDst, uint64_t cbToCopy,
+ uint32_t fFlags, PRTFILECOPYPARTBUFSTATE pBufState, uint64_t *pcbCopied);
+
+/**
+ * Copy file attributes from @a hFileSrc to @a hFileDst.
+ *
+ * @returns IPRT status code.
+ * @param hFileSrc Handle to the source file.
+ * @param hFileDst Handle to the destination file.
+ * @param fFlags Reserved, pass zero.
+ */
+RTDECL(int) RTFileCopyAttributes(RTFILE hFileSrc, RTFILE hFileDst, uint32_t fFlags);
+
+/**
+ * Compares two file given the paths to both files.
+ *
+ * @returns IPRT status code.
+ * @retval VINF_SUCCESS if equal.
+ * @retval VERR_NOT_EQUAL if not equal.
+ *
+ * @param pszFile1 The path to the first file.
+ * @param pszFile2 The path to the second file.
+ */
+RTDECL(int) RTFileCompare(const char *pszFile1, const char *pszFile2);
+
+/**
+ * Compares two file given the handles to both files.
+ *
+ * @returns IPRT status code.
+ * @retval VINF_SUCCESS if equal.
+ * @retval VERR_NOT_EQUAL if not equal.
+ *
+ * @param hFile1 The first file. Undefined return position.
+ * @param hFile2 The second file. Undefined return position.
+ */
+RTDECL(int) RTFileCompareByHandles(RTFILE hFile1, RTFILE hFile2);
+
+/** Flags for RTFileCompareEx().
+ * @{ */
+/** Do not use RTFILE_O_DENY_WRITE on the first file. */
+#define RTFILECOMP_FLAGS_NO_DENY_WRITE_FILE1 RT_BIT(0)
+/** Do not use RTFILE_O_DENY_WRITE on the second file. */
+#define RTFILECOMP_FLAGS_NO_DENY_WRITE_FILE2 RT_BIT(1)
+/** Do not use RTFILE_O_DENY_WRITE on either of the two files. */
+#define RTFILECOMP_FLAGS_NO_DENY_WRITE ( RTFILECOMP_FLAGS_NO_DENY_WRITE_FILE1 | RTFILECOMP_FLAGS_NO_DENY_WRITE_FILE2 )
+/** */
+#define RTFILECOMP_FLAGS_MASK UINT32_C(0x00000003)
+/** @} */
+
+/**
+ * Compares two files, extended version with progress callback.
+ *
+ * @returns IPRT status code.
+ * @retval VINF_SUCCESS if equal.
+ * @retval VERR_NOT_EQUAL if not equal.
+ *
+ * @param pszFile1 The path to the source file.
+ * @param pszFile2 The path to the destination file. This file will be
+ * created.
+ * @param fFlags Flags, any of the RTFILECOMP_FLAGS_ \#defines.
+ * @param pfnProgress Pointer to callback function for reporting progress.
+ * @param pvUser User argument to pass to pfnProgress along with the completion percentage.
+ */
+RTDECL(int) RTFileCompareEx(const char *pszFile1, const char *pszFile2, uint32_t fFlags, PFNRTPROGRESS pfnProgress, void *pvUser);
+
+/**
+ * Compares two files given their handles, extended version with progress
+ * callback.
+ *
+ * @returns IPRT status code.
+ * @retval VINF_SUCCESS if equal.
+ * @retval VERR_NOT_EQUAL if not equal.
+ *
+ * @param hFile1 The first file. Undefined return position.
+ * @param hFile2 The second file. Undefined return position.
+ *
+ * @param fFlags Flags, any of the RTFILECOMP_FLAGS_ \#defines, flags
+ * related to opening of the files will be ignored.
+ * @param pfnProgress Pointer to callback function for reporting progress.
+ * @param pvUser User argument to pass to pfnProgress along with the completion percentage.
+ */
+RTDECL(int) RTFileCompareByHandlesEx(RTFILE hFile1, RTFILE hFile2, uint32_t fFlags, PFNRTPROGRESS pfnProgress, void *pvUser);
+
+/**
+ * Renames a file.
+ *
+ * Identical to RTPathRename except that it will ensure that the source is not a directory.
+ *
+ * @returns IPRT status code.
+ * @returns VERR_ALREADY_EXISTS if the destination file exists.
+ *
+ * @param pszSrc The path to the source file.
+ * @param pszDst The path to the destination file.
+ * This file will be created.
+ * @param fRename See RTPathRename.
+ */
+RTDECL(int) RTFileRename(const char *pszSrc, const char *pszDst, unsigned fRename);
+
+
+/** @name RTFileMove flags (bit masks).
+ * @{ */
+/** Replace destination file if present. */
+#define RTFILEMOVE_FLAGS_REPLACE 0x1
+/** Don't allow symbolic links as part of the path.
+ * @remarks this flag is currently not implemented and will be ignored. */
+#define RTFILEMOVE_FLAGS_NO_SYMLINKS 0x2
+/** @} */
+
+/**
+ * Converts file opening modes (used by fopen, for example) to IPRT
+ * compatible flags, which then can be used with RTFileOpen* APIs.
+ *
+ * @note Handling sharing modes is not supported yet, so RTFILE_O_DENY_NONE
+ * will always be used.
+ *
+ * @return IPRT status code.
+ * @param pszMode Mode string to convert.
+ * @param pfMode Where to store the converted mode flags on
+ * success.
+ */
+RTDECL(int) RTFileModeToFlags(const char *pszMode, uint64_t *pfMode);
+
+/**
+ * Converts file opening modes along with a separate disposition command
+ * to IPRT compatible flags, which then can be used with RTFileOpen* APIs.
+ *
+ * Access modes:
+ * - "r": Opens a file for reading.
+ * - "r+": Opens a file for reading and writing.
+ * - "w": Opens a file for writing.
+ * - "w+": Opens a file for writing and reading.
+ *
+ * Disposition modes:
+ * - "oe", "open": Opens an existing file or fail if it does not exist.
+ * - "oc", "open-create": Opens an existing file or create it if it does
+ * not exist.
+ * - "oa", "open-append": Opens an existing file and places the file
+ * pointer at the end of the file, if opened with write access. Create
+ * the file if it does not exist.
+ * - "ot", "open-truncate": Opens and truncate an existing file or fail if
+ * it does not exist.
+ * - "ce", "create": Creates a new file if it does not exist. Fail if
+ * exist.
+ * - "ca", "create-replace": Creates a new file, always. Overwrites an
+ * existing file.
+ *
+ * Sharing mode:
+ * - "nr": Deny read.
+ * - "nw": Deny write.
+ * - "nrw": Deny both read and write.
+ * - "d": Allow delete.
+ * - "", NULL: Deny none, except delete.
+ *
+ * @return IPRT status code.
+ * @param pszAccess Access mode string to convert.
+ * @param pszDisposition Disposition mode string to convert.
+ * @param pszSharing Sharing mode string to convert.
+ * @param pfMode Where to store the converted mode flags on success.
+ */
+RTDECL(int) RTFileModeToFlagsEx(const char *pszAccess, const char *pszDisposition, const char *pszSharing, uint64_t *pfMode);
+
+/**
+ * Moves a file.
+ *
+ * RTFileMove differs from RTFileRename in that it works across volumes.
+ *
+ * @returns IPRT status code.
+ * @returns VERR_ALREADY_EXISTS if the destination file exists.
+ *
+ * @param pszSrc The path to the source file.
+ * @param pszDst The path to the destination file.
+ * This file will be created.
+ * @param fMove A combination of the RTFILEMOVE_* flags.
+ */
+RTDECL(int) RTFileMove(const char *pszSrc, const char *pszDst, unsigned fMove);
+
+
+/**
+ * Creates a new file with a unique name using the given template, returning a
+ * handle to it.
+ *
+ * One or more trailing X'es in the template will be replaced by random alpha
+ * numeric characters until a RTFileOpen with RTFILE_O_CREATE succeeds or we
+ * run out of patience.
+ * For instance:
+ * "/tmp/myprog-XXXXXX"
+ *
+ * As an alternative to trailing X'es, it is possible to put 3 or more X'es
+ * somewhere inside the file name. In the following string only the last
+ * bunch of X'es will be modified:
+ * "/tmp/myprog-XXX-XXX.tmp"
+ *
+ * @returns IPRT status code.
+ * @param phFile Where to return the file handle on success. Set to
+ * NIL on failure.
+ * @param pszTemplate The file name template on input. The actual file
+ * name on success. Empty string on failure.
+ * @param fOpen The RTFILE_O_XXX flags to open the file with.
+ * RTFILE_O_CREATE is mandatory.
+ * @see RTFileCreateTemp
+ */
+RTDECL(int) RTFileCreateUnique(PRTFILE phFile, char *pszTemplate, uint64_t fOpen);
+
+/**
+ * Creates a new file with a unique name using the given template.
+ *
+ * One or more trailing X'es in the template will be replaced by random alpha
+ * numeric characters until a RTFileOpen with RTFILE_O_CREATE succeeds or we
+ * run out of patience.
+ * For instance:
+ * "/tmp/myprog-XXXXXX"
+ *
+ * As an alternative to trailing X'es, it is possible to put 3 or more X'es
+ * somewhere inside the file name. In the following string only the last
+ * bunch of X'es will be modified:
+ * "/tmp/myprog-XXX-XXX.tmp"
+ *
+ * @returns iprt status code.
+ * @param pszTemplate The file name template on input. The actual file
+ * name on success. Empty string on failure.
+ * @param fMode The mode to create the file with. Use 0600 unless
+ * you have reason not to.
+ * @see RTFileCreateUnique
+ */
+RTDECL(int) RTFileCreateTemp(char *pszTemplate, RTFMODE fMode);
+
+/**
+ * Secure version of @a RTFileCreateTemp with a fixed mode of 0600.
+ *
+ * This function behaves in the same way as @a RTFileCreateTemp with two
+ * additional points. Firstly the mode is fixed to 0600. Secondly it will
+ * fail if it is not possible to perform the operation securely. Possible
+ * reasons include that the file could be removed by another unprivileged
+ * user before it is used (e.g. if is created in a non-sticky /tmp directory)
+ * or that the path contains symbolic links which another unprivileged user
+ * could manipulate; however the exact criteria will be specified on a
+ * platform-by-platform basis as platform support is added.
+ * @see RTPathIsSecure for the current list of criteria.
+ *
+ * @returns iprt status code.
+ * @returns VERR_NOT_SUPPORTED if the interface can not be supported on the
+ * current platform at this time.
+ * @returns VERR_INSECURE if the file could not be created securely.
+ * @param pszTemplate The file name template on input. The actual
+ * file name on success. Empty string on failure.
+ * @see RTFileCreateUnique
+ */
+RTDECL(int) RTFileCreateTempSecure(char *pszTemplate);
+
+/**
+ * Opens a new file with a unique name in the temp directory.
+ *
+ * Unlike the other temp file creation APIs, this does not allow you any control
+ * over the name. Nor do you have to figure out where the temporary directory
+ * is.
+ *
+ * @returns iprt status code.
+ * @param phFile Where to return the handle to the file.
+ * @param pszFilename Where to return the name (+path) of the file .
+ * @param cbFilename The size of the buffer @a pszFilename points to.
+ * @param fOpen The RTFILE_O_XXX flags to open the file with.
+ *
+ * @remarks If actual control over the filename or location is required, we'll
+ * create an extended edition of this API.
+ */
+RTDECL(int) RTFileOpenTemp(PRTFILE phFile, char *pszFilename, size_t cbFilename, uint64_t fOpen);
+
+
+/** @page pg_rt_filelock RT File locking API description
+ *
+ * File locking general rules:
+ *
+ * Region to lock or unlock can be located beyond the end of file, this can be used for
+ * growing files.
+ * Read (or Shared) locks can be acquired held by an unlimited number of processes at the
+ * same time, but a Write (or Exclusive) lock can only be acquired by one process, and
+ * cannot coexist with a Shared lock. To acquire a Read lock, a process must wait until
+ * there are no processes holding any Write locks. To acquire a Write lock, a process must
+ * wait until there are no processes holding either kind of lock.
+ * By default, RTFileLock and RTFileChangeLock calls returns error immediately if the lock
+ * can't be acquired due to conflict with other locks, however they can be called in wait mode.
+ *
+ * Differences in implementation:
+ *
+ * Win32, OS/2: Locking is mandatory, since locks are enforced by the operating system.
+ * I.e. when file region is locked in Read mode, any write in it will fail; in case of Write
+ * lock - region can be read and writed only by lock's owner.
+ *
+ * Win32: File size change (RTFileSetSize) is not controlled by locking at all (!) in the
+ * operation system. Also see comments to RTFileChangeLock API call.
+ *
+ * Linux/Posix: By default locks in Unixes are advisory. This means that cooperating processes
+ * may use locks to coordinate access to a file between themselves, but programs are also free
+ * to ignore locks and access the file in any way they choose to.
+ *
+ * Additional reading:
+ * http://en.wikipedia.org/wiki/File_locking
+ * http://unixhelp.ed.ac.uk/CGI/man-cgi?fcntl+2
+ * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/fs/lockfileex.asp
+ */
+
+/** @name Lock flags (bit masks).
+ * @{ */
+/** Read access, can be shared with others. */
+#define RTFILE_LOCK_READ 0x00
+/** Write access, one at a time. */
+#define RTFILE_LOCK_WRITE 0x01
+/** Don't wait for other locks to be released. */
+#define RTFILE_LOCK_IMMEDIATELY 0x00
+/** Wait till conflicting locks have been released. */
+#define RTFILE_LOCK_WAIT 0x02
+/** Valid flags mask */
+#define RTFILE_LOCK_MASK 0x03
+/** @} */
+
+
+/**
+ * Locks a region of file for read (shared) or write (exclusive) access.
+ *
+ * @returns iprt status code.
+ * @returns VERR_FILE_LOCK_VIOLATION if lock can't be acquired.
+ * @param File Handle to the file.
+ * @param fLock Lock method and flags, see RTFILE_LOCK_* defines.
+ * @param offLock Offset of lock start.
+ * @param cbLock Length of region to lock, may overlap the end of file.
+ */
+RTDECL(int) RTFileLock(RTFILE File, unsigned fLock, int64_t offLock, uint64_t cbLock);
+
+/**
+ * Changes a lock type from read to write or from write to read.
+ * The region to type change must correspond exactly to an existing locked region.
+ * If change can't be done due to locking conflict and non-blocking mode is used, error is
+ * returned and lock keeps its state (see next warning).
+ *
+ * WARNING: win32 implementation of this call is not atomic, it transforms to a pair of
+ * calls RTFileUnlock and RTFileLock. Potentially the previously acquired lock can be
+ * lost, i.e. function is called in non-blocking mode, previous lock is freed, new lock can't
+ * be acquired, and old lock (previous state) can't be acquired back too. This situation
+ * may occurs _only_ if the other process is acquiring a _write_ lock in blocking mode or
+ * in race condition with the current call.
+ * In this very bad case special error code VERR_FILE_LOCK_LOST will be returned.
+ *
+ * @returns iprt status code.
+ * @returns VERR_FILE_NOT_LOCKED if region was not locked.
+ * @returns VERR_FILE_LOCK_VIOLATION if lock type can't be changed, lock remains its type.
+ * @returns VERR_FILE_LOCK_LOST if lock was lost, we haven't this lock anymore :(
+ * @param File Handle to the file.
+ * @param fLock Lock method and flags, see RTFILE_LOCK_* defines.
+ * @param offLock Offset of lock start.
+ * @param cbLock Length of region to lock, may overlap the end of file.
+ */
+RTDECL(int) RTFileChangeLock(RTFILE File, unsigned fLock, int64_t offLock, uint64_t cbLock);
+
+/**
+ * Unlocks previously locked region of file.
+ * The region to unlock must correspond exactly to an existing locked region.
+ *
+ * @returns iprt status code.
+ * @returns VERR_FILE_NOT_LOCKED if region was not locked.
+ * @param File Handle to the file.
+ * @param offLock Offset of lock start.
+ * @param cbLock Length of region to unlock, may overlap the end of file.
+ */
+RTDECL(int) RTFileUnlock(RTFILE File, int64_t offLock, uint64_t cbLock);
+
+
+/**
+ * Query information about an open file.
+ *
+ * @returns iprt status code.
+ *
+ * @param File Handle to the file.
+ * @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.
+ */
+RTDECL(int) RTFileQueryInfo(RTFILE File, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAdditionalAttribs);
+
+/**
+ * Changes one or more of the timestamps associated of file system object.
+ *
+ * @returns iprt status code.
+ * @retval VERR_NOT_SUPPORTED is returned if the operation isn't supported by
+ * the OS.
+ *
+ * @param File Handle to the file.
+ * @param pAccessTime Pointer to the new access time. NULL if not to be changed.
+ * @param pModificationTime Pointer to the new modifcation time. NULL if not to be changed.
+ * @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.
+ */
+RTDECL(int) RTFileSetTimes(RTFILE File, PCRTTIMESPEC pAccessTime, PCRTTIMESPEC pModificationTime,
+ PCRTTIMESPEC pChangeTime, PCRTTIMESPEC pBirthTime);
+
+/**
+ * Gets one or more of the timestamps associated of file system object.
+ *
+ * @returns iprt status code.
+ * @param File Handle to the file.
+ * @param pAccessTime Where to store the access time. NULL is ok.
+ * @param pModificationTime Where to store the modifcation time. NULL is ok.
+ * @param pChangeTime Where to store the change time. NULL is ok.
+ * @param pBirthTime Where to store the time of birth. NULL is ok.
+ *
+ * @remark This is wrapper around RTFileQueryInfo() and exists to complement RTFileSetTimes().
+ */
+RTDECL(int) RTFileGetTimes(RTFILE File, PRTTIMESPEC pAccessTime, PRTTIMESPEC pModificationTime,
+ PRTTIMESPEC pChangeTime, PRTTIMESPEC pBirthTime);
+
+/**
+ * Changes the mode flags of an open file.
+ *
+ * The API requires at least one of the mode flag sets (Unix/Dos) to
+ * be set. The type is ignored.
+ *
+ * @returns iprt status code.
+ * @param File Handle to the file.
+ * @param fMode The new file mode, see @ref grp_rt_fs for details.
+ */
+RTDECL(int) RTFileSetMode(RTFILE File, RTFMODE fMode);
+
+/**
+ * Gets the mode flags of an open file.
+ *
+ * @returns iprt status code.
+ * @param File Handle to the file.
+ * @param pfMode Where to store the file mode, see @ref grp_rt_fs for details.
+ *
+ * @remark This is wrapper around RTFileQueryInfo()
+ * and exists to complement RTFileSetMode().
+ */
+RTDECL(int) RTFileGetMode(RTFILE File, uint32_t *pfMode);
+
+/**
+ * Changes the owner and/or group of an open file.
+ *
+ * @returns iprt status code.
+ * @param File Handle to the file.
+ * @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.
+ */
+RTDECL(int) RTFileSetOwner(RTFILE File, uint32_t uid, uint32_t gid);
+
+/**
+ * Gets the owner and/or group of an open file.
+ *
+ * @returns iprt status code.
+ * @param File Handle to the file.
+ * @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 RTFileQueryInfo() and exists to complement RTFileGetOwner().
+ */
+RTDECL(int) RTFileGetOwner(RTFILE File, uint32_t *pUid, uint32_t *pGid);
+
+/**
+ * Executes an IOCTL on a file descriptor.
+ *
+ * This function is currently only available in L4 and posix environments.
+ * Attemps at calling it from code shared with any other platforms will break things!
+ *
+ * The rational for defining this API is to simplify L4 porting of audio drivers,
+ * and to remove some of the assumptions on RTFILE being a file descriptor on
+ * platforms using the posix file implementation.
+ *
+ * @returns iprt status code.
+ * @param File Handle to the file.
+ * @param ulRequest IOCTL request to carry out.
+ * @param pvData IOCTL data.
+ * @param cbData Size of the IOCTL data.
+ * @param piRet Return value of the IOCTL request.
+ */
+RTDECL(int) RTFileIoCtl(RTFILE File, unsigned long ulRequest, void *pvData, unsigned cbData, int *piRet);
+
+/**
+ * Query the sizes of a filesystem.
+ *
+ * @returns iprt status code.
+ * @retval VERR_NOT_SUPPORTED is returned if the operation isn't supported by
+ * the OS.
+ *
+ * @param hFile The file handle.
+ * @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 RTFsQuerySizes
+ */
+RTDECL(int) RTFileQueryFsSizes(RTFILE hFile, PRTFOFF pcbTotal, RTFOFF *pcbFree,
+ uint32_t *pcbBlock, uint32_t *pcbSector);
+
+/**
+ * Reads the file into memory.
+ *
+ * The caller must free the memory using RTFileReadAllFree().
+ *
+ * @returns IPRT status code.
+ * @param pszFilename The name of the file.
+ * @param ppvFile Where to store the pointer to the memory on successful return.
+ * @param pcbFile Where to store the size of the returned memory.
+ *
+ * @remarks Note that this function may be implemented using memory mapping, which means
+ * that the file may remain open until RTFileReadAllFree() is called. It also
+ * means that the return memory may reflect the state of the file when it's
+ * accessed instead of when this call was done. So, in short, don't use this
+ * API for volatile files, then rather use the extended variant with a
+ * yet-to-be-defined flag.
+ */
+RTDECL(int) RTFileReadAll(const char *pszFilename, void **ppvFile, size_t *pcbFile);
+
+/**
+ * Reads the file into memory.
+ *
+ * The caller must free the memory using RTFileReadAllFree().
+ *
+ * @returns IPRT status code.
+ * @param pszFilename The name of the file.
+ * @param off The offset to start reading at.
+ * @param cbMax The maximum number of bytes to read into memory. Specify RTFOFF_MAX
+ * to read to the end of the file.
+ * @param fFlags See RTFILE_RDALL_*.
+ * @param ppvFile Where to store the pointer to the memory on successful return.
+ * @param pcbFile Where to store the size of the returned memory.
+ *
+ * @remarks See the remarks for RTFileReadAll.
+ */
+RTDECL(int) RTFileReadAllEx(const char *pszFilename, RTFOFF off, RTFOFF cbMax, uint32_t fFlags, void **ppvFile, size_t *pcbFile);
+
+/**
+ * Reads the file into memory.
+ *
+ * The caller must free the memory using RTFileReadAllFree().
+ *
+ * @returns IPRT status code.
+ * @param File The handle to the file.
+ * @param ppvFile Where to store the pointer to the memory on successful return.
+ * @param pcbFile Where to store the size of the returned memory.
+ *
+ * @remarks See the remarks for RTFileReadAll.
+ */
+RTDECL(int) RTFileReadAllByHandle(RTFILE File, void **ppvFile, size_t *pcbFile);
+
+/**
+ * Reads the file into memory.
+ *
+ * The caller must free the memory using RTFileReadAllFree().
+ *
+ * @returns IPRT status code.
+ * @param File The handle to the file.
+ * @param off The offset to start reading at.
+ * @param cbMax The maximum number of bytes to read into memory. Specify RTFOFF_MAX
+ * to read to the end of the file.
+ * @param fFlags See RTFILE_RDALL_*.
+ * @param ppvFile Where to store the pointer to the memory on successful return.
+ * @param pcbFile Where to store the size of the returned memory.
+ *
+ * @remarks See the remarks for RTFileReadAll.
+ */
+RTDECL(int) RTFileReadAllByHandleEx(RTFILE File, RTFOFF off, RTFOFF cbMax, uint32_t fFlags, void **ppvFile, size_t *pcbFile);
+
+/**
+ * Frees the memory returned by one of the RTFileReadAll(), RTFileReadAllEx(),
+ * RTFileReadAllByHandle() and RTFileReadAllByHandleEx() functions.
+ *
+ * @param pvFile Pointer to the memory.
+ * @param cbFile The size of the memory.
+ */
+RTDECL(void) RTFileReadAllFree(void *pvFile, size_t cbFile);
+
+/** @name RTFileReadAllEx and RTFileReadAllHandleEx flags
+ * The open flags are ignored by RTFileReadAllHandleEx.
+ * @{ */
+#define RTFILE_RDALL_O_DENY_NONE RTFILE_O_DENY_NONE
+#define RTFILE_RDALL_O_DENY_READ RTFILE_O_DENY_READ
+#define RTFILE_RDALL_O_DENY_WRITE RTFILE_O_DENY_WRITE
+#define RTFILE_RDALL_O_DENY_READWRITE RTFILE_O_DENY_READWRITE
+#define RTFILE_RDALL_O_DENY_ALL RTFILE_O_DENY_ALL
+#define RTFILE_RDALL_O_DENY_NOT_DELETE RTFILE_O_DENY_NOT_DELETE
+#define RTFILE_RDALL_O_DENY_MASK RTFILE_O_DENY_MASK
+/** Fail with VERR_OUT_OF_RANGE if the file size exceeds the specified maximum
+ * size. The default behavior is to cap the size at cbMax. */
+#define RTFILE_RDALL_F_FAIL_ON_MAX_SIZE RT_BIT_32(30)
+/** Add a trailing zero byte to facilitate reading text files. */
+#define RTFILE_RDALL_F_TRAILING_ZERO_BYTE RT_BIT_32(31)
+/** Mask of valid flags. */
+#define RTFILE_RDALL_VALID_MASK (RTFILE_RDALL_O_DENY_MASK | UINT32_C(0xc0000000))
+/** @} */
+
+/**
+ * Sets the current size of the file ensuring that all required blocks
+ * are allocated on the underlying medium.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_NOT_SUPPORTED if either this operation is not supported on the
+ * current host in an efficient manner or the given combination of
+ * flags is not supported.
+ * @param hFile The handle to the file.
+ * @param cbSize The new size of the file to allocate.
+ * @param fFlags Combination of RTFILE_ALLOC_SIZE_F_*
+ */
+RTDECL(int) RTFileSetAllocationSize(RTFILE hFile, uint64_t cbSize, uint32_t fFlags);
+
+/** @name RTFILE_ALLOC_SIZE_F_XXX - RTFileSetAllocationSize flags
+ * @{ */
+/** Default flags. */
+#define RTFILE_ALLOC_SIZE_F_DEFAULT 0
+/** Do not change the size of the file if the given size is bigger than the
+ * current file size.
+ *
+ * Useful to preallocate blocks beyond the current size for appending data in an
+ * efficient manner. Might not be supported on all hosts and will return
+ * VERR_NOT_SUPPORTED in that case. */
+#define RTFILE_ALLOC_SIZE_F_KEEP_SIZE RT_BIT(0)
+/** Mask of valid flags. */
+#define RTFILE_ALLOC_SIZE_F_VALID (RTFILE_ALLOC_SIZE_F_KEEP_SIZE)
+/** @} */
+
+
+#ifdef IN_RING3
+
+/** @page pg_rt_asyncio RT File async I/O API
+ *
+ * File operations are usually blocking the calling thread until
+ * they completed making it impossible to let the thread do anything
+ * else in-between.
+ * The RT File async I/O API provides an easy and efficient way to
+ * access files asynchronously using the native facilities provided
+ * by each operating system.
+ *
+ * @section sec_rt_asyncio_objects Objects
+ *
+ * There are two objects used in this API.
+ * The first object is the request. A request contains every information
+ * needed two complete the file operation successfully like the start offset
+ * and pointer to the source or destination buffer.
+ * Requests are created with RTFileAioReqCreate() and destroyed with
+ * RTFileAioReqDestroy().
+ * Because creating a request may require allocating various operating
+ * system dependent resources and may be quite expensive it is possible
+ * to use a request more than once to save CPU cycles.
+ * A request is constructed with either RTFileAioReqPrepareRead()
+ * which will set up a request to read from the given file or
+ * RTFileAioReqPrepareWrite() which will write to a given file.
+ *
+ * The second object is the context. A file is associated with a context
+ * and requests for this file may complete only on the context the file
+ * was associated with and not on the context given in RTFileAioCtxSubmit()
+ * (see below for further information).
+ * RTFileAioCtxWait() is used to wait for completion of requests which were
+ * associated with the context. While waiting for requests the thread can not
+ * respond to global state changes. That's why the API provides a way to let
+ * RTFileAioCtxWait() return immediately no matter how many requests
+ * have finished through RTFileAioCtxWakeup(). The return code is
+ * VERR_INTERRUPTED to let the thread know that he got interrupted.
+ *
+ * @section sec_rt_asyncio_request_states Request states
+ *
+ * Created:
+ * After a request was created with RTFileAioReqCreate() it is in the same state
+ * like it just completed successfully. RTFileAioReqGetRC() will return VINF_SUCCESS
+ * and a transfer size of 0. RTFileAioReqGetUser() will return NULL. The request can be
+ * destroyed RTFileAioReqDestroy(). It is also allowed to prepare a the request
+ * for a data transfer with the RTFileAioReqPrepare* methods.
+ * Calling any other method like RTFileAioCtxSubmit() will return VERR_FILE_AIO_NOT_PREPARED
+ * and RTFileAioReqCancel() returns VERR_FILE_AIO_NOT_SUBMITTED.
+ *
+ * Prepared:
+ * A request will enter this state if one of the RTFileAioReqPrepare* methods
+ * is called. In this state you can still destroy and retrieve the user data
+ * associated with the request but trying to cancel the request or getting
+ * the result of the operation will return VERR_FILE_AIO_NOT_SUBMITTED.
+ *
+ * Submitted:
+ * A prepared request can be submitted with RTFileAioCtxSubmit(). If the operation
+ * succeeds it is not allowed to touch the request or free any resources until
+ * it completed through RTFileAioCtxWait(). The only allowed method is RTFileAioReqCancel()
+ * which tries to cancel the request. The request will go into the completed state
+ * and RTFileAioReqGetRC() will return VERR_FILE_AIO_CANCELED.
+ * If the request completes not matter if successfully or with an error it will
+ * switch into the completed state. RTFileReqDestroy() fails if the given request
+ * is in this state.
+ *
+ * Completed:
+ * The request will be in this state after it completed and returned through
+ * RTFileAioCtxWait(). RTFileAioReqGetRC() returns the final result code
+ * and the number of bytes transferred.
+ * The request can be used for new data transfers.
+ *
+ * @section sec_rt_asyncio_threading Threading
+ *
+ * The API is a thin wrapper around the specific host OS APIs and therefore
+ * relies on the thread safety of the underlying API.
+ * The interesting functions with regards to thread safety are RTFileAioCtxSubmit()
+ * and RTFileAioCtxWait(). RTFileAioCtxWait() must not be called from different
+ * threads at the same time with the same context handle. The same applies to
+ * RTFileAioCtxSubmit(). However it is possible to submit new requests from a different
+ * thread while waiting for completed requests on another thread with RTFileAioCtxWait().
+ *
+ * @section sec_rt_asyncio_implementations Differences in implementation
+ *
+ * Because the host APIs are quite different on every OS and every API has other limitations
+ * there are some things to consider to make the code as portable as possible.
+ *
+ * The first restriction at the moment is that every buffer has to be aligned to a 512 byte boundary.
+ * This limitation comes from the Linux io_* interface. To use the interface the file
+ * must be opened with O_DIRECT. This flag disables the kernel cache too which may
+ * degrade performance but is unfortunately the only way to make asynchronous
+ * I/O work till today (if O_DIRECT is omitted io_submit will revert to sychronous behavior
+ * and will return when the requests finished and when they are queued).
+ * It is mostly used by DBMS which do theire own caching.
+ * Furthermore there is no filesystem independent way to discover the restrictions at least
+ * for the 2.4 kernel series. Since 2.6 the 512 byte boundary seems to be used by all
+ * file systems. So Linus comment about this flag is comprehensible but Linux
+ * lacks an alternative at the moment.
+ *
+ * The next limitation applies only to Windows. Requests are not associated with the
+ * I/O context they are associated with but with the file the request is for.
+ * The file needs to be associated with exactly one I/O completion port and requests
+ * for this file will only arrive at that context after they completed and not on
+ * the context the request was submitted.
+ * To associate a file with a specific context RTFileAioCtxAssociateWithFile() is
+ * used. It is only implemented on Windows and does nothing on the other platforms.
+ * If the file needs to be associated with different context for some reason
+ * the file must be closed first. After it was opened again the new context
+ * can be associated with the other context.
+ * This can't be done by the API because there is no way to retrieve the flags
+ * the file was opened with.
+ */
+
+/**
+ * Global limits for the AIO API.
+ */
+typedef struct RTFILEAIOLIMITS
+{
+ /** Global number of simultaneous outstanding requests allowed.
+ * RTFILEAIO_UNLIMITED_REQS means no limit. */
+ uint32_t cReqsOutstandingMax;
+ /** The alignment data buffers need to have.
+ * 0 means no alignment restrictions. */
+ uint32_t cbBufferAlignment;
+} RTFILEAIOLIMITS;
+/** A pointer to a AIO limits structure. */
+typedef RTFILEAIOLIMITS *PRTFILEAIOLIMITS;
+
+/**
+ * Returns the global limits for the AIO API.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_NOT_SUPPORTED if the host does not support the async I/O API.
+ *
+ * @param pAioLimits Where to store the global limit information.
+ */
+RTDECL(int) RTFileAioGetLimits(PRTFILEAIOLIMITS pAioLimits);
+
+/**
+ * Creates an async I/O request handle.
+ *
+ * @returns IPRT status code.
+ * @param phReq Where to store the request handle.
+ */
+RTDECL(int) RTFileAioReqCreate(PRTFILEAIOREQ phReq);
+
+/**
+ * Destroys an async I/O request handle.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_FILE_AIO_IN_PROGRESS if the request is still in progress.
+ *
+ * @param hReq The request handle.
+ */
+RTDECL(int) RTFileAioReqDestroy(RTFILEAIOREQ hReq);
+
+/**
+ * Prepares an async read request.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_FILE_AIO_IN_PROGRESS if the request is still in progress.
+ *
+ * @param hReq The request handle.
+ * @param hFile The file to read from.
+ * @param off The offset to start reading at.
+ * @param pvBuf Where to store the read bits.
+ * @param cbRead Number of bytes to read.
+ * @param pvUser Opaque user data associated with this request which
+ * can be retrieved with RTFileAioReqGetUser().
+ */
+RTDECL(int) RTFileAioReqPrepareRead(RTFILEAIOREQ hReq, RTFILE hFile, RTFOFF off,
+ void *pvBuf, size_t cbRead, void *pvUser);
+
+/**
+ * Prepares an async write request.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_FILE_AIO_IN_PROGRESS if the request is still in progress.
+ *
+ * @param hReq The request handle.
+ * @param hFile The file to write to.
+ * @param off The offset to start writing at.
+ * @param pvBuf The bits to write.
+ * @param cbWrite Number of bytes to write.
+ * @param pvUser Opaque user data associated with this request which
+ * can be retrieved with RTFileAioReqGetUser().
+ */
+RTDECL(int) RTFileAioReqPrepareWrite(RTFILEAIOREQ hReq, RTFILE hFile, RTFOFF off,
+ void const *pvBuf, size_t cbWrite, void *pvUser);
+
+/**
+ * Prepares an async flush of all cached data associated with a file handle.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_FILE_AIO_IN_PROGRESS if the request is still in progress.
+ *
+ * @param hReq The request handle.
+ * @param hFile The file to flush.
+ * @param pvUser Opaque user data associated with this request which
+ * can be retrieved with RTFileAioReqGetUser().
+ *
+ * @remarks May also flush other caches on some platforms.
+ */
+RTDECL(int) RTFileAioReqPrepareFlush(RTFILEAIOREQ hReq, RTFILE hFile, void *pvUser);
+
+/**
+ * Gets the opaque user data associated with the given request.
+ *
+ * @returns Opaque user data.
+ * @retval NULL if the request hasn't been prepared yet.
+ *
+ * @param hReq The request handle.
+ */
+RTDECL(void *) RTFileAioReqGetUser(RTFILEAIOREQ hReq);
+
+/**
+ * Cancels a pending request.
+ *
+ * @returns IPRT status code.
+ * @retval VINF_SUCCESS If the request was canceled.
+ * @retval VERR_FILE_AIO_NOT_SUBMITTED If the request wasn't submitted yet.
+ * @retval VERR_FILE_AIO_IN_PROGRESS If the request could not be canceled because it is already processed.
+ * @retval VERR_FILE_AIO_COMPLETED If the request could not be canceled because it already completed.
+ *
+ * @param hReq The request to cancel.
+ */
+RTDECL(int) RTFileAioReqCancel(RTFILEAIOREQ hReq);
+
+/**
+ * Gets the status of a completed request.
+ *
+ * @returns The IPRT status code of the given request.
+ * @retval VERR_FILE_AIO_NOT_SUBMITTED if the request wasn't submitted yet.
+ * @retval VERR_FILE_AIO_CANCELED if the request was canceled.
+ * @retval VERR_FILE_AIO_IN_PROGRESS if the request isn't yet completed.
+ *
+ * @param hReq The request handle.
+ * @param pcbTransferred Where to store the number of bytes transferred.
+ * Optional since it is not relevant for all kinds of
+ * requests.
+ */
+RTDECL(int) RTFileAioReqGetRC(RTFILEAIOREQ hReq, size_t *pcbTransferred);
+
+
+
+/**
+ * Creates an async I/O context.
+ *
+ * @todo briefly explain what an async context is here or in the page
+ * above.
+ *
+ * @returns IPRT status code.
+ * @param phAioCtx Where to store the async I/O context handle.
+ * @param cAioReqsMax How many async I/O requests the context should be capable
+ * to handle. Pass RTFILEAIO_UNLIMITED_REQS if the
+ * context should support an unlimited number of
+ * requests.
+ * @param fFlags Combination of RTFILEAIOCTX_FLAGS_*.
+ */
+RTDECL(int) RTFileAioCtxCreate(PRTFILEAIOCTX phAioCtx, uint32_t cAioReqsMax,
+ uint32_t fFlags);
+
+/** Unlimited number of requests.
+ * Used with RTFileAioCtxCreate and RTFileAioCtxGetMaxReqCount. */
+#define RTFILEAIO_UNLIMITED_REQS UINT32_MAX
+
+/** When set RTFileAioCtxWait() will always wait for completing requests,
+ * even when there is none waiting currently, instead of returning
+ * VERR_FILE_AIO_NO_REQUEST. */
+#define RTFILEAIOCTX_FLAGS_WAIT_WITHOUT_PENDING_REQUESTS RT_BIT_32(0)
+/** mask of valid flags. */
+#define RTFILEAIOCTX_FLAGS_VALID_MASK (RTFILEAIOCTX_FLAGS_WAIT_WITHOUT_PENDING_REQUESTS)
+
+/**
+ * Destroys an async I/O context.
+ *
+ * @returns IPRT status code.
+ * @param hAioCtx The async I/O context handle.
+ */
+RTDECL(int) RTFileAioCtxDestroy(RTFILEAIOCTX hAioCtx);
+
+/**
+ * Get the maximum number of requests one aio context can handle.
+ *
+ * @returns Maximum number of tasks the context can handle.
+ * RTFILEAIO_UNLIMITED_REQS if there is no limit.
+ *
+ * @param hAioCtx The async I/O context handle.
+ * If NIL_RTAIOCONTEXT is passed the maximum value
+ * which can be passed to RTFileAioCtxCreate()
+ * is returned.
+ */
+RTDECL(uint32_t) RTFileAioCtxGetMaxReqCount(RTFILEAIOCTX hAioCtx);
+
+/**
+ * Associates a file with an async I/O context.
+ * Requests for this file will arrive at the completion port
+ * associated with the file.
+ *
+ * @returns IPRT status code.
+ *
+ * @param hAioCtx The async I/O context handle.
+ * @param hFile The file handle.
+ */
+RTDECL(int) RTFileAioCtxAssociateWithFile(RTFILEAIOCTX hAioCtx, RTFILE hFile);
+
+/**
+ * Submits a set of requests to an async I/O context for processing.
+ *
+ * @returns IPRT status code.
+ * @returns VERR_FILE_AIO_INSUFFICIENT_RESSOURCES if the maximum number of
+ * simultaneous outstanding requests would be exceeded.
+ *
+ * @param hAioCtx The async I/O context handle.
+ * @param pahReqs Pointer to an array of request handles.
+ * @param cReqs The number of entries in the array.
+ *
+ * @remarks It is possible that some requests could be submitted successfully
+ * even if the method returns an error code. In that case RTFileAioReqGetRC()
+ * can be used to determine the status of a request.
+ * If it returns VERR_FILE_AIO_IN_PROGRESS it was submitted successfully.
+ * Any other error code may indicate why the request failed.
+ * VERR_FILE_AIO_NOT_SUBMITTED indicates that a request wasn't submitted
+ * probably because the previous request encountered an error.
+ *
+ * @remarks @a cReqs uses the type size_t while it really is a uint32_t, this is
+ * to avoid annoying warnings when using RT_ELEMENTS and similar
+ * macros.
+ */
+RTDECL(int) RTFileAioCtxSubmit(RTFILEAIOCTX hAioCtx, PRTFILEAIOREQ pahReqs, size_t cReqs);
+
+/**
+ * Waits for request completion.
+ *
+ * Only one thread at a time may call this API on a context.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_INVALID_POINTER If pcReqs or/and pahReqs are invalid.
+ * @retval VERR_INVALID_HANDLE If hAioCtx is invalid.
+ * @retval VERR_OUT_OF_RANGE If cMinReqs is larger than cReqs.
+ * @retval VERR_INVALID_PARAMETER If cReqs is 0.
+ * @retval VERR_TIMEOUT If cMinReqs didn't complete before the
+ * timeout expired.
+ * @retval VERR_INTERRUPTED If the completion context was interrupted
+ * by RTFileAioCtxWakeup().
+ * @retval VERR_FILE_AIO_NO_REQUEST If there are no pending request.
+ *
+ * @param hAioCtx The async I/O context handle to wait and get
+ * completed requests from.
+ * @param cMinReqs The minimum number of requests which have to
+ * complete before this function returns.
+ * @param cMillies The number of milliseconds to wait before returning
+ * VERR_TIMEOUT. Use RT_INDEFINITE_WAIT to wait
+ * forever.
+ * @param pahReqs Pointer to an array where the handles of the
+ * completed requests will be stored on success.
+ * @param cReqs The number of entries @a pahReqs can hold.
+ * @param pcReqs Where to store the number of returned (complete)
+ * requests. This will always be set.
+ *
+ * @remarks The wait will be resume if interrupted by a signal. An
+ * RTFileAioCtxWaitNoResume variant can be added later if it becomes
+ * necessary.
+ *
+ * @remarks @a cMinReqs and @a cReqs use the type size_t while they really are
+ * uint32_t's, this is to avoid annoying warnings when using
+ * RT_ELEMENTS and similar macros.
+ */
+RTDECL(int) RTFileAioCtxWait(RTFILEAIOCTX hAioCtx, size_t cMinReqs, RTMSINTERVAL cMillies,
+ PRTFILEAIOREQ pahReqs, size_t cReqs, uint32_t *pcReqs);
+
+/**
+ * Forces any RTFileAioCtxWait() call on another thread to return immediately.
+ *
+ * @returns IPRT status code.
+ *
+ * @param hAioCtx The handle of the async I/O context to wakeup.
+ */
+RTDECL(int) RTFileAioCtxWakeup(RTFILEAIOCTX hAioCtx);
+
+#endif /* IN_RING3 */
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_file_h */
+
diff --git a/include/iprt/formats/Makefile.kup b/include/iprt/formats/Makefile.kup
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/include/iprt/formats/Makefile.kup
diff --git a/include/iprt/formats/apfs.h b/include/iprt/formats/apfs.h
new file mode 100644
index 00000000..f45a37df
--- /dev/null
+++ b/include/iprt/formats/apfs.h
@@ -0,0 +1,244 @@
+/* $Id: apfs.h $ */
+/** @file
+ * IPRT, APFS (Apple File System) format.
+ */
+
+/*
+ * Copyright (C) 2019-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_formats_apfs_h
+#define IPRT_INCLUDED_formats_apfs_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+#include <iprt/assertcompile.h>
+
+
+/** @defgroup grp_rt_formats_apfs Apple File System structures and definitions
+ * @ingroup grp_rt_formats
+ * @{
+ */
+
+/*
+ * The filesystem structures were retrieved from:
+ * https://developer.apple.com/support/downloads/Apple-File-System-Reference.pdf
+ */
+
+/** Physical address of an on-disk block. */
+typedef int64_t APFSPADDR;
+/** Object identifier. */
+typedef uint64_t APFSOID;
+/** Transaction identifier. */
+typedef uint64_t APFSXID;
+
+/** Invalid object ID. */
+#define APFS_OID_INVALID UINT64_C(0)
+/** Number of reserved object IDs for special structures. */
+#define APFS_OID_RSVD_CNT 1024
+/** Object ID of a super block. */
+#define APFS_OID_NX_SUPERBLOCK UINT64_C(1)
+
+
+/**
+ * Range of physical addresses.
+ */
+typedef struct
+{
+ /** Start address of the range. */
+ APFSPADDR PAddrStart;
+ /** Size of the range in blocks.*/
+ uint64_t cBlocks;
+} APFSPRANGE;
+/** Pointer to a APFS range. */
+typedef APFSPRANGE *PAPFSPRANGE;
+/** Pointer to a const APFS range. */
+typedef const APFSPRANGE *PCAPFSPRANGE;
+
+/** APFS UUID (compatible with our UUID definition). */
+typedef RTUUID APFSUUID;
+
+/** Maximum object checksum size. */
+#define APFS_OBJ_MAX_CHKSUM_SZ 8
+
+/**
+ * APFS Object header.
+ */
+typedef struct APFSOBJPHYS
+{
+ /** The stored checksum of the object. */
+ uint8_t abChkSum[APFS_OBJ_MAX_CHKSUM_SZ];
+ /** Object ID. */
+ APFSOID Oid;
+ /** Transaction ID. */
+ APFSXID Xid;
+ /** Object type. */
+ uint32_t u32Type;
+ /** Object sub type. */
+ uint32_t u32SubType;
+} APFSOBJPHYS;
+/** Pointer to an APFS object header. */
+typedef APFSOBJPHYS *PAPFSOBJPHYS;
+/** Pointer to a const APFS object header. */
+typedef const APFSOBJPHYS *PCAPFSOBJPHYS;
+
+#define APFS_OBJECT_TYPE_MASK UINT32_C(0x0000ffff)
+#define APFS_OBJECT_TYPE_FLAGS_MASK UINT32_C(0xffff0000)
+
+/**
+ * APFS EFI jumpstart information.
+ */
+typedef struct APFSEFIJMPSTART
+{
+ /** Object header. */
+ APFSOBJPHYS ObjHdr;
+ /** The magic value. */
+ uint32_t u32Magic;
+ /** The version of the structure. */
+ uint32_t u32Version;
+ /** EFI file length in bytes. */
+ uint32_t cbEfiFile;
+ /** Number of extents describing the on disk blocks the file is stored in. */
+ uint32_t cExtents;
+ /** Reserved. */
+ uint64_t au64Rsvd0[16];
+ /** After this comes a variable size of APFSPRANGE extent structures. */
+} APFSEFIJMPSTART;
+/** Pointer to an APFS EFI jumpstart structure. */
+typedef APFSEFIJMPSTART *PAPFSEFIJMPSTART;
+/** Pointer to a const APFS EFI jumpstart structure. */
+typedef const APFSEFIJMPSTART *PCAPFSEFIJMPSTART;
+
+/** EFI jumpstart magic ('RDSJ'). */
+#define APFS_EFIJMPSTART_MAGIC RT_MAKE_U32_FROM_U8('J', 'S', 'D', 'R')
+/** EFI jumpstart version. */
+#define APFS_EFIJMPSTART_VERSION UINT32_C(1)
+
+/** Maximum number of filesystems supported in a single container. */
+#define APFS_NX_SUPERBLOCK_FS_MAX UINT32_C(100)
+/** Maximum number of counters in the superblock. */
+#define APFS_NX_SUPERBLOCK_COUNTERS_MAX UINT32_C(32)
+/** Number of entries in the ephemeral information array. */
+#define APFS_NX_SUPERBLOCK_EPH_INFO_COUNT UINT32_C(4)
+
+/**
+ * APFS super block.
+ */
+typedef struct
+{
+ /** Object header. */
+ APFSOBJPHYS ObjHdr;
+ /** The magic value. */
+ uint32_t u32Magic;
+ /** Block size in bytes. */
+ uint32_t cbBlock;
+ /** Number of blocks in the volume. */
+ uint64_t cBlocks;
+ /** Feature flags of the volume. */
+ uint64_t fFeatures;
+ /** Readonly compatible features. */
+ uint64_t fRdOnlyCompatFeatures;
+ /** Incompatible features. */
+ uint64_t fIncompatFeatures;
+ /** UUID of the volume. */
+ APFSUUID Uuid;
+ /** Next free object identifier to use for new objects. */
+ APFSOID OidNext;
+ /** Next free transaction identifier to use for new transactions. */
+ APFSOID XidNext;
+ /** Number of blocks used by the checkpoint descriptor area. */
+ uint32_t cXpDescBlocks;
+ /** Number of blocks used by the checkpoint data area. */
+ uint32_t cXpDataBlocks;
+ /** Base address of checkpoint descriptor area. */
+ APFSPADDR PAddrXpDescBase;
+ /** Base address of checkpoint data area. */
+ APFSPADDR PAddrXpDataBase;
+ /** Next index to use in the checkpoint descriptor area. */
+ uint32_t idxXpDescNext;
+ /** Next index to use in the checkpoint data area. */
+ uint32_t idxXpDataNext;
+ /** Number of blocks in the checkpoint descriptor area used by the checkpoint that this superblock belongs to. */
+ uint32_t cXpDescLen;
+ /** Index of the first valid item in the checkpoint data area. */
+ uint32_t idxXpDataFirst;
+ /** Number of blocks in the checkpoint data area used by the checkpoint that this superblock belongs to. */
+ uint32_t cXpDataLen;
+ /** Ephemeral object identifer of the space manager. */
+ APFSOID OidSpaceMgr;
+ /** Physical object identifier for the containers object map. */
+ APFSOID OidOMap;
+ /** Ephemeral object identifer for the reaper. */
+ APFSOID OidReaper;
+ /** Reserved for testing should be always zero on disk. */
+ uint32_t u32TestType;
+ /** Maximum number of filesystems which can be stored in this container. */
+ uint32_t cFsMax;
+ /** Array of filesystem object identifiers. */
+ APFSOID aFsOids[APFS_NX_SUPERBLOCK_FS_MAX];
+ /** Array of counters primarily used during debugging. */
+ uint64_t aCounters[APFS_NX_SUPERBLOCK_COUNTERS_MAX];
+ /** Range of blocks where no space will be allocated, used for shrinking a partition. */
+ APFSPRANGE RangeBlocked;
+ /** Physical object identifier of a tree keeping track of objects needing to be moved out of the block range. */
+ APFSOID OidTreeEvictMapping;
+ /** Container flags. */
+ uint64_t fFlags;
+ /** Address of the EFI jumpstart structure. */
+ APFSPADDR PAddrEfiJmpStart;
+ /** UUID of the containers Fusion set if available. */
+ APFSUUID UuidFusion;
+ /** Address of the containers keybag. */
+ APFSPADDR PAddrKeyLocker;
+ /** Array of fields used in the management of ephemeral data. */
+ uint64_t au64EphemeralInfo[APFS_NX_SUPERBLOCK_EPH_INFO_COUNT];
+ /** Reserved for testing. */
+ APFSOID OidTest;
+ /** Physical object identifier of the Fusion middle tree. */
+ APFSOID OidFusionMt;
+ /** Ephemeral object identifier of the Fusion write-back cache state. */
+ APFSOID OidFusionWbc;
+ /** Blocks used for the Fusion write-back cache area. */
+ APFSPRANGE RangeFusionWbc;
+} APFSNXSUPERBLOCK;
+/** Pointer to a APFS super block structure. */
+typedef APFSNXSUPERBLOCK *PAPFSNXSUPERBLOCK;
+/** Pointer to a const APFS super block structure. */
+typedef const APFSNXSUPERBLOCK *PCAPFSNXSUPERBLOCK;
+
+/** Superblock magic value ('BSXN'). */
+#define APFS_NX_SUPERBLOCK_MAGIC RT_MAKE_U32_FROM_U8('N', 'X', 'S', 'B')
+
+/** @} */
+
+#endif /* !IPRT_INCLUDED_formats_apfs_h */
+
diff --git a/include/iprt/formats/asn1.h b/include/iprt/formats/asn1.h
new file mode 100644
index 00000000..d1ba8f80
--- /dev/null
+++ b/include/iprt/formats/asn1.h
@@ -0,0 +1,107 @@
+/** @file
+ * IPRT - Abstract Syntax Notation One (ASN.1) Definitions.
+ */
+
+/*
+ * Copyright (C) 2014-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_formats_asn1_h
+#define IPRT_INCLUDED_formats_asn1_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cdefs.h>
+
+
+/** @defgroup grp_rt_formats_asn1 ASN.1 definitions
+ * @ingroup grp_rt_formats
+ *
+ * @{ */
+
+/** @name Tag classes.
+ * @{ */
+#define ASN1_TAGCLASS_UNIVERSAL UINT8_C(0x00)
+#define ASN1_TAGCLASS_APPLICATION UINT8_C(0x40)
+#define ASN1_TAGCLASS_CONTEXT UINT8_C(0x80)
+#define ASN1_TAGCLASS_PRIVATE UINT8_C(0xc0)
+#define ASN1_TAGCLASS_MASK UINT8_C(0xc0)
+/** @} */
+
+/** Primitive encoding. */
+#define ASN1_TAGFLAG_PRIMITIVE UINT8_C(0x00)
+/** Constructed encoding, as opposed to primitive. */
+#define ASN1_TAGFLAG_CONSTRUCTED UINT8_C(0x20)
+
+/** The tag value mask. */
+#define ASN1_TAG_MASK UINT8_C(0x1f)
+
+/** @name ASN.1 universal tags.
+ * @{ */
+#define ASN1_TAG_EOC UINT8_C(0x00)
+#define ASN1_TAG_BOOLEAN UINT8_C(0x01)
+#define ASN1_TAG_INTEGER UINT8_C(0x02)
+#define ASN1_TAG_BIT_STRING UINT8_C(0x03)
+#define ASN1_TAG_OCTET_STRING UINT8_C(0x04)
+#define ASN1_TAG_NULL UINT8_C(0x05)
+#define ASN1_TAG_OID UINT8_C(0x06)
+#define ASN1_TAG_OBJECT_DESCRIPTOR UINT8_C(0x07)
+#define ASN1_TAG_EXTERNAL UINT8_C(0x08)
+#define ASN1_TAG_REAL UINT8_C(0x09)
+#define ASN1_TAG_ENUMERATED UINT8_C(0x0a)
+#define ASN1_TAG_EMBEDDED_PDV UINT8_C(0x0b)
+#define ASN1_TAG_UTF8_STRING UINT8_C(0x0c)
+#define ASN1_TAG_RELATIVE_OID UINT8_C(0x0d)
+#define ASN1_TAG_RESERVED_14 UINT8_C(0x0e)
+#define ASN1_TAG_RESERVED_15 UINT8_C(0x0f)
+#define ASN1_TAG_SEQUENCE UINT8_C(0x10)
+#define ASN1_TAG_SET UINT8_C(0x11)
+#define ASN1_TAG_NUMERIC_STRING UINT8_C(0x12)
+#define ASN1_TAG_PRINTABLE_STRING UINT8_C(0x13)
+#define ASN1_TAG_T61_STRING UINT8_C(0x14)
+#define ASN1_TAG_VIDEOTEX_STRING UINT8_C(0x15)
+#define ASN1_TAG_IA5_STRING UINT8_C(0x16)
+#define ASN1_TAG_UTC_TIME UINT8_C(0x17) /**< Century seems to be 1900 if YY < 50, otherwise 2000. Baka ASN.1! */
+#define ASN1_TAG_GENERALIZED_TIME UINT8_C(0x18)
+#define ASN1_TAG_GRAPHIC_STRING UINT8_C(0x19)
+#define ASN1_TAG_VISIBLE_STRING UINT8_C(0x1a)
+#define ASN1_TAG_GENERAL_STRING UINT8_C(0x1b)
+#define ASN1_TAG_UNIVERSAL_STRING UINT8_C(0x1c)
+#define ASN1_TAG_CHARACTER_STRING UINT8_C(0x1d)
+#define ASN1_TAG_BMP_STRING UINT8_C(0x1e)
+#define ASN1_TAG_USE_LONG_FORM UINT8_C(0x1f)
+/** @} */
+
+
+/** @} */
+
+#endif /* !IPRT_INCLUDED_formats_asn1_h */
+
diff --git a/include/iprt/formats/bmp.h b/include/iprt/formats/bmp.h
new file mode 100644
index 00000000..1a1625df
--- /dev/null
+++ b/include/iprt/formats/bmp.h
@@ -0,0 +1,192 @@
+/* $Id: bmp.h $ */
+/** @file
+ * IPRT - Microsoft Bitmap Formats (BMP).
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_formats_bmp_h
+#define IPRT_INCLUDED_formats_bmp_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+#include <iprt/assertcompile.h>
+
+
+/** @defgroup grp_rt_fmt_bmp Microsoft Bitmaps Formats (BMP)
+ * @ingroup grp_rt_formats
+ * @{
+ */
+
+/** @name BMP header sizes (in bytes).
+ * @{ */
+#define BMP_HDR_SIZE_FILE 14
+#define BMP_HDR_SIZE_OS21 12
+#define BMP_HDR_SIZE_OS22 64
+#define BMP_HDR_SIZE_WIN3X 40
+/** @} */
+
+
+/** BMP format file header. */
+#pragma pack(1)
+typedef struct BMPFILEHDR
+{
+ /** File type identifier ("magic"). */
+ uint16_t uType;
+ /** Size of file in bytes. */
+ uint32_t cbFileSize;
+ /** Reserved (should be 0). */
+ uint16_t Reserved1;
+ /** Reserved (should be 0). */
+ uint16_t Reserved2;
+ /** Offset (in bytes) to bitmap data. */
+ uint32_t offBits;
+} BMPFILEHDR;
+#pragma pack()
+AssertCompileSize(BMPFILEHDR, BMP_HDR_SIZE_FILE);
+/** Pointer to a BMP format file header. */
+typedef BMPFILEHDR *PBMPFILEHDR;
+
+/** BMP file magic number for BMP / DIB. */
+#define BMP_HDR_MAGIC (RT_H2LE_U16_C(0x4d42))
+
+/** OS/2 1.x BMP core header,
+ * also known as BITMAPCOREHEADER. */
+typedef struct BMPOS2COREHDR
+{
+ /** Size (in bytes) of remaining header. */
+ uint32_t cbSize;
+ /** Width of bitmap in pixels. */
+ uint16_t uWidth;
+ /** Height of bitmap in pixels. */
+ uint16_t uHeight;
+ /** Number of planes. */
+ uint16_t cPlanes;
+ /** Color bits per pixel. */
+ uint16_t cBits;
+} BMPOS2COREHDR;
+AssertCompileSize(BMPOS2COREHDR, BMP_HDR_SIZE_OS21);
+/** Pointer to a OS/2 1.x BMP core header. */
+typedef BMPOS2COREHDR *PBMPOS2COREHDR;
+
+/** OS/2 2.0 BMP core header, version 2,
+ * also known as BITMAPCOREHEADER2. */
+typedef struct BMPOS2COREHDR2
+{
+ /** Size (in bytes) of remaining header. */
+ uint32_t cbSize;
+ /** Width of bitmap in pixels. */
+ uint32_t uWidth;
+ /** Height of bitmap in pixels. */
+ uint32_t uHeight;
+ /** Number of planes. */
+ uint16_t cPlanes;
+ /** Color bits per pixel. */
+ uint16_t cBits;
+ /** Compression scheme of type BMP_COMPRESSION_TYPE. */
+ uint32_t enmCompression;
+ /** Size of bitmap in bytes. */
+ uint32_t cbSizeImage;
+ /** Horz. resolution in pixels/meter. */
+ uint32_t uXPelsPerMeter;
+ /** Vert. resolution in pixels/meter. */
+ uint32_t uYPelsPerMeter;
+ /** Number of colors in color table. */
+ uint32_t cClrUsed;
+ /** Number of important colors. */
+ uint32_t cClrImportant;
+ /** Resolution measurement Used. */
+ uint16_t uUnits;
+ /** Reserved fields (always 0). */
+ uint16_t Reserved;
+ /** Orientation of bitmap. */
+ uint16_t uRecording;
+ /** Halftone algorithm used on image. */
+ uint16_t enmHalftone;
+ /** Halftone algorithm data. */
+ uint32_t uHalftoneParm1;
+ /** Halftone algorithm data. */
+ uint32_t uHalftoneParm2;
+ /** Color table format (always 0). */
+ uint32_t uColorEncoding;
+ /** Misc. field for application use . */
+ uint32_t uIdentifier;
+} BMPOS2COREHDR2;
+AssertCompileSize(BMPOS2COREHDR2, BMP_HDR_SIZE_OS22);
+/** Pointer to an OS/2 2.0 BMP core header version 2. */
+typedef BMPOS2COREHDR2 *PBMPOS2COREHDR2;
+
+/** Windows 3.x BMP information header Format. */
+typedef struct BMPWIN3XINFOHDR
+{
+ /** Size (in bytes) of remaining header. */
+ uint32_t cbSize;
+ /** Width of bitmap in pixels. */
+ uint32_t uWidth;
+ /** Height of bitmap in pixels. */
+ uint32_t uHeight;
+ /** Number of planes. */
+ uint16_t cPlanes;
+ /** Color bits per pixel. */
+ uint16_t cBits;
+ /** Compression scheme of type BMP_COMPRESSION_TYPE. */
+ uint32_t enmCompression;
+ /** Size of bitmap in bytes. */
+ uint32_t cbSizeImage;
+ /** Horz. resolution in pixels/meter. */
+ uint32_t uXPelsPerMeter;
+ /** Vert. resolution in pixels/meter. */
+ uint32_t uYPelsPerMeter;
+ /** Number of colors in color table. */
+ uint32_t cClrUsed;
+ /** Number of important colors. */
+ uint32_t cClrImportant;
+} BMPWIN3XINFOHDR;
+AssertCompileSize(BMPWIN3XINFOHDR, BMP_HDR_SIZE_WIN3X);
+/** Pointer to a Windows 3.x BMP information header. */
+typedef BMPWIN3XINFOHDR *PBMPWIN3XINFOHDR;
+
+
+
+/** @name BMP compression types.
+ * @{ */
+#define BMP_COMPRESSION_TYPE_NONE 0
+#define BMP_COMPRESSION_TYPE_RLE8 1
+#define BMP_COMPRESSION_TYPE_RLE4 2
+/** @} */
+
+/** @} */
+
+#endif /* !IPRT_INCLUDED_formats_bmp_h */
+
diff --git a/include/iprt/formats/codeview.h b/include/iprt/formats/codeview.h
new file mode 100644
index 00000000..f8cf66ab
--- /dev/null
+++ b/include/iprt/formats/codeview.h
@@ -0,0 +1,870 @@
+/** @file
+ * IPRT - Microsoft CodeView Debug Information.
+ */
+
+/*
+ * Copyright (C) 2009-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_formats_codeview_h
+#define IPRT_INCLUDED_formats_codeview_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+
+#include <iprt/types.h>
+#include <iprt/assertcompile.h>
+
+
+/** @defgroup grp_rt_fmt_codeview Microsoft CodeView Debug Information
+ * @{
+ */
+
+
+/**
+ * CodeView Header. There are two of this, base header at the start of the debug
+ * information and a trailing header at the end.
+ */
+typedef struct RTCVHDR
+{
+ /** The magic ('NBxx'), see RTCVHDR_MAGIC_XXX. */
+ uint32_t u32Magic;
+ /**
+ * Base header: Subsection directory offset relative to this header (start).
+ * Trailing header: Offset of the base header relative to the end of the file.
+ *
+ * Called lfoBase, lfaBase, lfoDirectory, lfoDir and probably other things in
+ * the various specs/docs available. */
+ uint32_t off;
+} RTCVHDR;
+/** Pointer to a CodeView header. */
+typedef RTCVHDR *PRTCVHDR;
+
+/** @name CodeView magic values (RTCVHDR::u32Magic).
+ * @{ */
+/** CodeView from Visual C++ 5.0. Specified in the 2001 MSDN specs.chm file. */
+#define RTCVHDR_MAGIC_NB11 RT_MAKE_U32_FROM_U8('N', 'B', '1', '1')
+/** External PDB reference (often referred to as PDB 2.0). */
+#define RTCVHDR_MAGIC_NB10 RT_MAKE_U32_FROM_U8('N', 'B', '1', '0')
+/** CodeView v4.10, packed. Specified in the TIS document. */
+#define RTCVHDR_MAGIC_NB09 RT_MAKE_U32_FROM_U8('N', 'B', '0', '9')
+/** CodeView v4.00 thru v4.05. Specified in the TIS document? */
+#define RTCVHDR_MAGIC_NB08 RT_MAKE_U32_FROM_U8('N', 'B', '0', '8')
+/** Quick C for Windows 1.0 debug info. */
+#define RTCVHDR_MAGIC_NB07 RT_MAKE_U32_FROM_U8('N', 'B', '0', '7')
+/** Emitted by ILINK indicating incremental link. Comparable to NB05? */
+#define RTCVHDR_MAGIC_NB06 RT_MAKE_U32_FROM_U8('N', 'B', '0', '6')
+/** Emitted by LINK version 5.20 and later before packing. */
+#define RTCVHDR_MAGIC_NB05 RT_MAKE_U32_FROM_U8('N', 'B', '0', '5')
+/** Emitted by IBM ILINK for HLL (similar to NB02 in many ways). */
+#define RTCVHDR_MAGIC_NB04 RT_MAKE_U32_FROM_U8('N', 'B', '0', '4')
+/** Emitted by LINK version 5.10 (or similar OMF linkers), as shipped with
+ * Microsoft C v6.0 for example. More or less entirely 16-bit. */
+#define RTCVHDR_MAGIC_NB02 RT_MAKE_U32_FROM_U8('N', 'B', '0', '2')
+/* No idea what NB03 might have been. */
+/** AIX debugger format according to "IBM OS/2 16/32-bit Object Module Format
+ * (OMF) and Linear eXecutable Module Format (LX)" revision 10 (LXOMF.PDF). */
+#define RTCVHDR_MAGIC_NB01 RT_MAKE_U32_FROM_U8('N', 'B', '0', '1')
+/** Ancient CodeView format according to LXOMF.PDF. */
+#define RTCVHDR_MAGIC_NB00 RT_MAKE_U32_FROM_U8('N', 'B', '0', '0')
+/** @} */
+
+
+/** @name CV directory headers.
+ * @{ */
+
+/**
+ * Really old CV directory header used with NB00 and NB02.
+ *
+ * Uses 16-bit directory entires (RTCVDIRENT16).
+ */
+typedef struct RTCVDIRHDR16
+{
+ /** The number of directory entries. */
+ uint16_t cEntries;
+} RTCVDIRHDR16;
+/** Pointer to a old CV directory header. */
+typedef RTCVDIRHDR16 *PRTCVDIRHDR16;
+
+/**
+ * Simple 32-bit CV directory base header, used by NB04 (aka IBM HLL).
+ */
+typedef struct RTCVDIRHDR32
+{
+ /** The number of bytes of this header structure. */
+ uint16_t cbHdr;
+ /** The number of bytes per entry. */
+ uint16_t cbEntry;
+ /** The number of directory entries. */
+ uint32_t cEntries;
+} RTCVDIRHDR32;
+/** Pointer to a 32-bit CV directory header. */
+typedef RTCVDIRHDR32 *PRTCVDIRHDR32;
+
+/**
+ * Extended 32-bit CV directory header as specified in the TIS doc.
+ * The two extra fields seems to never have been assigned any official purpose.
+ */
+typedef struct RTCVDIRHDR32EX
+{
+ /** This starts the same way as the NB04 header. */
+ RTCVDIRHDR32 Core;
+ /** Tentatively decleared as the offset to the next directory generated by
+ * the incremental linker. Haven't seen this used yet. */
+ uint32_t offNextDir;
+ /** Flags, non defined apparently, so MBZ. */
+ uint32_t fFlags;
+} RTCVDIRHDR32EX;
+/** Pointer to an extended 32-bit CV directory header. */
+typedef RTCVDIRHDR32EX *PRTCVDIRHDR32EX;
+
+/** @} */
+
+
+/**
+ * 16-bit CV directory entry used with NB00 and NB02.
+ */
+typedef struct RTCVDIRENT16
+{
+ /** Subsection type (RTCVSST). */
+ uint16_t uSubSectType;
+ /** Which module (1-based, 0xffff is special). */
+ uint16_t iMod;
+ /** The lowe offset of this subsection relative to the base CV header. */
+ uint16_t offLow;
+ /** The high part of the subsection offset. */
+ uint16_t offHigh;
+ /** The size of the subsection. */
+ uint16_t cb;
+} RTCVDIRENT16;
+AssertCompileSize(RTCVDIRENT16, 10);
+/** Pointer to a 16-bit CV directory entry. */
+typedef RTCVDIRENT16 *PRTCVDIRENT16;
+
+
+/**
+ * 32-bit CV directory entry used starting with NB04.
+ */
+typedef struct RTCVDIRENT32
+{
+ /** Subsection type (RTCVSST). */
+ uint16_t uSubSectType;
+ /** Which module (1-based, 0xffff is special). */
+ uint16_t iMod;
+ /** The offset of this subsection relative to the base CV header. */
+ uint32_t off;
+ /** The size of the subsection. */
+ uint32_t cb;
+} RTCVDIRENT32;
+AssertCompileSize(RTCVDIRENT32, 12);
+/** Pointer to a 32-bit CV directory entry. */
+typedef RTCVDIRENT32 *PRTCVDIRENT32;
+/** Pointer to a const 32-bit CV directory entry. */
+typedef RTCVDIRENT32 const *PCRTCVDIRENT32;
+
+
+/**
+ * CodeView subsection types.
+ */
+typedef enum RTCVSST
+{
+ /** @name NB00, NB02 and NB04 subsection types.
+ * The actual format of each subsection varies between NB04 and the others,
+ * and it may further vary in NB04 depending on the module type.
+ * @{ */
+ kCvSst_OldModule = 0x101,
+ kCvSst_OldPublic,
+ kCvSst_OldTypes,
+ kCvSst_OldSymbols,
+ kCvSst_OldSrcLines,
+ kCvSst_OldLibraries,
+ kCvSst_OldImports,
+ kCvSst_OldCompacted,
+ kCvSst_OldSrcLnSeg = 0x109,
+ kCvSst_OldSrcLines3 = 0x10b,
+ /** @} */
+
+ /** @name NB09, NB11 (and possibly NB05, NB06, NB07, and NB08) subsection types.
+ * @{ */
+ kCvSst_Module = 0x120,
+ kCvSst_Types,
+ kCvSst_Public,
+ kCvSst_PublicSym,
+ kCvSst_Symbols,
+ kCvSst_AlignSym,
+ kCvSst_SrcLnSeg,
+ kCvSst_SrcModule,
+ kCvSst_Libraries,
+ kCvSst_GlobalSym,
+ kCvSst_GlobalPub,
+ kCvSst_GlobalTypes,
+ kCvSst_MPC,
+ kCvSst_SegMap,
+ kCvSst_SegName,
+ kCvSst_PreComp,
+ kCvSst_PreCompMap,
+ kCvSst_OffsetMap16,
+ kCvSst_OffsetMap32,
+ kCvSst_FileIndex = 0x133,
+ kCvSst_StaticSym
+ /** @} */
+} RTCVSST;
+/** Pointer to a CV subsection type value. */
+typedef RTCVSST *PRTCVSST;
+/** Pointer to a const CV subsection type value. */
+typedef RTCVSST const *PCRTCVSST;
+
+
+/**
+ * CV4 module segment info.
+ */
+typedef struct RTCVMODSEGINFO32
+{
+ /** The segment number. */
+ uint16_t iSeg;
+ /** Explicit padding. */
+ uint16_t u16Padding;
+ /** Offset into the segment. */
+ uint32_t off;
+ /** The size of the contribution. */
+ uint32_t cb;
+} RTCVMODSEGINFO32;
+typedef RTCVMODSEGINFO32 *PRTCVMODSEGINFO32;
+typedef RTCVMODSEGINFO32 const *PCRTCVMODSEGINFO32;
+
+
+/**
+ * CV4 segment map header.
+ */
+typedef struct RTCVSEGMAPHDR
+{
+ /** Number of segments descriptors in the table. */
+ uint16_t cSegs;
+ /** Number of logical segment descriptors. */
+ uint16_t cLogSegs;
+} RTCVSEGMAPHDR;
+/** Pointer to a CV4 segment map header. */
+typedef RTCVSEGMAPHDR *PRTCVSEGMAPHDR;
+/** Pointer to a const CV4 segment map header. */
+typedef RTCVSEGMAPHDR const *PCRTCVSEGMAPHDR;
+
+/**
+ * CV4 Segment map descriptor entry.
+ */
+typedef struct RTCVSEGMAPDESC
+{
+ /** Segment flags. */
+ uint16_t fFlags;
+ /** The overlay number. */
+ uint16_t iOverlay;
+ /** Group index into this segment descriptor array. 0 if not relevant.
+ * The group descriptors are found in the second half of the table. */
+ uint16_t iGroup;
+ /** Complicated. */
+ uint16_t iFrame;
+ /** Offset (byte) into the kCvSst_SegName table of the segment name, or
+ * 0xffff. */
+ uint16_t offSegName;
+ /** Offset (byte) into the kCvSst_SegName table of the class name, or 0xffff. */
+ uint16_t offClassName;
+ /** Offset into the physical segment. */
+ uint32_t off;
+ /** Size of segment. */
+ uint32_t cb;
+} RTCVSEGMAPDESC;
+/** Pointer to a segment map descriptor entry. */
+typedef RTCVSEGMAPDESC *PRTCVSEGMAPDESC;
+/** Pointer to a const segment map descriptor entry. */
+typedef RTCVSEGMAPDESC const *PCRTCVSEGMAPDESC;
+
+/** @name RTCVSEGMAPDESC_F_XXX - RTCVSEGMAPDESC::fFlags values.
+ * @{ */
+#define RTCVSEGMAPDESC_F_READ UINT16_C(0x0001)
+#define RTCVSEGMAPDESC_F_WRITE UINT16_C(0x0002)
+#define RTCVSEGMAPDESC_F_EXECUTE UINT16_C(0x0004)
+#define RTCVSEGMAPDESC_F_32BIT UINT16_C(0x0008)
+#define RTCVSEGMAPDESC_F_SEL UINT16_C(0x0100)
+#define RTCVSEGMAPDESC_F_ABS UINT16_C(0x0200)
+#define RTCVSEGMAPDESC_F_GROUP UINT16_C(0x1000)
+#define RTCVSEGMAPDESC_F_RESERVED UINT16_C(0xecf0)
+/** @} */
+
+/**
+ * CV4 segment map subsection.
+ */
+typedef struct RTCVSEGMAP
+{
+ /** The header. */
+ RTCVSEGMAPHDR Hdr;
+ /** Descriptor array. */
+ RTCVSEGMAPDESC aDescs[1];
+} RTCVSEGMAP;
+/** Pointer to a segment map subsection. */
+typedef RTCVSEGMAP *PRTCVSEGMAP;
+/** Pointer to a const segment map subsection. */
+typedef RTCVSEGMAP const *PCRTCVSEGMAP;
+
+
+/**
+ * CV4 line number segment contribution start/end table entry.
+ * Part of RTCVSRCMODULE.
+ */
+typedef struct RTCVSRCRANGE
+{
+ /** Start segment offset. */
+ uint32_t offStart;
+ /** End segment offset (inclusive?). */
+ uint32_t offEnd;
+} RTCVSRCRANGE;
+/** Pointer to a line number segment contributation. */
+typedef RTCVSRCRANGE *PRTCVSRCRANGE;
+/** Pointer to a const line number segment contributation. */
+typedef RTCVSRCRANGE const *PCRTCVSRCRANGE;
+
+/**
+ * CV4 header for a line number subsection, used by kCvSst_SrcModule.
+ *
+ * The aoffSrcFiles member is followed by an array of segment ranges
+ * (RTCVSRCRANGE), cSegs in length. This may contain zero entries if the
+ * information is not known or not possible to express in this manner.
+ *
+ * After the range table, a segment index (uint16_t) mapping table follows, also
+ * cSegs in length.
+ */
+typedef struct RTCVSRCMODULE
+{
+ /** The number of files described in this subsection. */
+ uint16_t cFiles;
+ /** The number of code segments this module contributes to. */
+ uint16_t cSegs;
+ /** Offsets of the RTCVSRCFILE entries in this subsection, length given by
+ * the above cFiles member. */
+ uint32_t aoffSrcFiles[1 /*cFiles*/];
+ /* RTCVSRCRANGE aSegRanges[cSegs]; */
+ /* uint16_t aidxSegs[cSegs]; */
+} RTCVSRCMODULE;
+/** Pointer to a source module subsection header. */
+typedef RTCVSRCMODULE *PRTCVSRCMODULE;
+/** Pointer to a const source module subsection header. */
+typedef RTCVSRCMODULE const *PCRTCVSRCMODULE;
+
+/**
+ * CV4 source file, inside a kCvSst_SrcModule (see RTCVSRCMODULE::aoffSrcFiles)
+ *
+ * The aoffSrcLines member is followed by an array of segment ranges
+ * (RTCVSRCRANGE), cSegs in length. Just like for RTCVSRCMODULE this may
+ * contain zero entries.
+ *
+ * After the range table is the filename, which is preceeded by a 8-bit length
+ * (actually documented to be 16-bit, but seeing 8-bit here with wlink).
+ */
+typedef struct RTCVSRCFILE
+{
+ /** The number segments that this source file contributed to. */
+ uint16_t cSegs;
+ /** Alignment padding. */
+ uint16_t uPadding;
+ /** Offsets of the RTCVSRCLN entries for this source file, length given by
+ * the above cSegs member. Relative to the start of the subsection. */
+ uint32_t aoffSrcLines[1 /*cSegs*/];
+ /* RTCVSRCRANGE aSegRanges[cSegs]; */
+ /* uint8_t/uint16_t cchName; */
+ /* char achName[cchName]; */
+} RTCVSRCFILE;
+/** Pointer to a source file. */
+typedef RTCVSRCFILE *PRTCVSRCFILE;
+/** Pointer to a const source file. */
+typedef RTCVSRCFILE const *PCRTCVSRCFILE;
+
+/**
+ * CV4 line numbers header.
+ *
+ * The aoffLines member is followed by an array of line numbers (uint16_t).
+ */
+typedef struct RTCVSRCLINE
+{
+ /** The index of the segment these line numbers belong to. */
+ uint16_t idxSeg;
+ /** The number of line number pairs the two following tables. */
+ uint16_t cPairs;
+ /** Segment offsets, cPairs long. */
+ uint32_t aoffLines[1 /*cPairs*/];
+ /* uint16_t aiLines[cPairs]; */
+} RTCVSRCLINE;
+/** Pointer to a line numbers header. */
+typedef RTCVSRCLINE *PRTCVSRCLINE;
+/** Pointer to a const line numbers header. */
+typedef RTCVSRCLINE const *PCRTCVSRCLINE;
+
+
+/**
+ * Global symbol table header, used by kCvSst_GlobalSym and kCvSst_GlobalPub.
+ */
+typedef struct RTCVGLOBALSYMTABHDR
+{
+ /** The symbol hash function. */
+ uint16_t uSymHash;
+ /** The address hash function. */
+ uint16_t uAddrHash;
+ /** The amount of symbol information following immediately after the header. */
+ uint32_t cbSymbols;
+ /** The amount of symbol hash tables following the symbols. */
+ uint32_t cbSymHash;
+ /** The amount of address hash tables following the symbol hash tables. */
+ uint32_t cbAddrHash;
+} RTCVGLOBALSYMTABHDR;
+/** Pointer to a global symbol table header. */
+typedef RTCVGLOBALSYMTABHDR *PRTCVGLOBALSYMTABHDR;
+/** Pointer to a const global symbol table header. */
+typedef RTCVGLOBALSYMTABHDR const *PCRTCVGLOBALSYMTABHDR;
+
+
+typedef enum RTCVSYMTYPE
+{
+ /** @name Symbols that doesn't change with compilation model or target machine.
+ * @{ */
+ kCvSymType_Compile = 0x0001,
+ kCvSymType_Register,
+ kCvSymType_Constant,
+ kCvSymType_UDT,
+ kCvSymType_SSearch,
+ kCvSymType_End,
+ kCvSymType_Skip,
+ kCvSymType_CVReserve,
+ kCvSymType_ObjName,
+ kCvSymType_EndArg,
+ kCvSymType_CobolUDT,
+ kCvSymType_ManyReg,
+ kCvSymType_Return,
+ kCvSymType_EntryThis,
+ /** @} */
+
+ /** @name Symbols with 16:16 addresses.
+ * @{ */
+ kCvSymType_BpRel16 = 0x0100,
+ kCvSymType_LData16,
+ kCvSymType_GData16,
+ kCvSymType_Pub16,
+ kCvSymType_LProc16,
+ kCvSymType_GProc16,
+ kCvSymType_Thunk16,
+ kCvSymType_BLock16,
+ kCvSymType_With16,
+ kCvSymType_Label16,
+ kCvSymType_CExModel16,
+ kCvSymType_VftPath16,
+ kCvSymType_RegRel16,
+ /** @} */
+
+ /** @name Symbols with 16:32 addresses.
+ * @{ */
+ kCvSymType_BpRel32 = 0x0200,
+ kCvSymType_LData32,
+ kCvSymType_GData32,
+ kCvSymType_Pub32,
+ kCvSymType_LProc32,
+ kCvSymType_GProc32,
+ kCvSymType_Thunk32,
+ kCvSymType_Block32,
+ kCvSymType_With32,
+ kCvSymType_Label32,
+ kCvSymType_CExModel32,
+ kCvSymType_VftPath32,
+ kCvSymType_RegRel32,
+ kCvSymType_LThread32,
+ kCvSymType_GThread32,
+ /** @} */
+
+ /** @name Symbols for MIPS.
+ * @{ */
+ kCvSymType_LProcMips = 0x0300,
+ kCvSymType_GProcMips,
+ /** @} */
+
+ /** @name Symbols for Microsoft CodeView.
+ * @{ */
+ kCvSymType_ProcRef = 0x0400,
+ kCvSymType_DataRef,
+ kCvSymType_Align,
+ kCvSymType_LProcRef,
+ /** @} */
+
+ /** @name Symbols with 32-bit address (I think) and 32-bit type indices.
+ * @{ */
+ kCvSymType_V2_Register = 0x1001,
+ kCvSymType_V2_Constant,
+ kCvSymType_V2_Udt,
+ kCvSymType_V2_CobolUdt,
+ kCvSymType_V2_ManyReg,
+ kCvSymType_V2_BpRel,
+ kCvSymType_V2_LData,
+ kCvSymType_V2_GData,
+ kCvSymType_V2_Pub,
+ kCvSymType_V2_LProc,
+ kCvSymType_V2_GProc,
+ kCvSymType_V2_VftTable,
+ kCvSymType_V2_RegRel,
+ kCvSymType_V2_LThread,
+ kCvSymType_V2_GThread,
+ kCvSymType_V2_Unknown_1010,
+ kCvSymType_V2_Unknown_1011,
+ kCvSymType_V2_FrameInfo,
+ kCvSymType_V2_Compliand,
+ /** @} */
+
+ /** @name Version 3 symbol types.
+ * @{ */
+ /** Name of the object file, preceded by a 4-byte language type (ASM=0) */
+ kCvSymType_V3_Compliand = 0x1101,
+ kCvSymType_V3_Thunk,
+ kCvSymType_V3_Block,
+ kCvSymType_V3_Unknown_1104,
+ kCvSymType_V3_Label, /**< RTCVSYMV3LABEL */
+ kCvSymType_V3_Register,
+ kCvSymType_V3_Constant,
+ kCvSymType_V3_Udt,
+ kCvSymType_V3_Unknown_1109,
+ kCvSymType_V3_Unknown_110a,
+ kCvSymType_V3_BpRel,
+ kCvSymType_V3_LData, /**< RTCVSYMV3TYPEDNAME */
+ kCvSymType_V3_GData, /**< RTCVSYMV3TYPEDNAME */
+ kCvSymType_V3_Pub,
+ kCvSymType_V3_LProc,
+ kCvSymType_V3_GProc,
+ kCvSymType_V3_RegRel,
+ kCvSymType_V3_LThread,
+ kCvSymType_V3_GThread,
+ kCvSymType_V3_Unknown_1114,
+ kCvSymType_V3_Unknown_1115,
+ kCvSymType_V3_MSTool, /**< RTCVSYMV3MSTOOL */
+
+ kCvSymType_V3_PubFunc1 = 0x1125,
+ kCvSymType_V3_PubFunc2 = 0x1127,
+ kCvSymType_V3_SectInfo = 0x1136,
+ kCvSymType_V3_SubSectInfo,
+ kCvSymType_V3_Entrypoint,
+ kCvSymType_V3_Unknown_1139,
+ kCvSymType_V3_SecuCookie,
+ kCvSymType_V3_Unknown_113b,
+ kCvSymType_V3_MsToolInfo,
+ kCvSymType_V3_MsToolEnv,
+
+ kCvSymType_VS2013_Local,
+ kCvSymType_VS2013_FpOff = 0x1144,
+ kCvSymType_VS2013_LProc32 = 0x1146,
+ kCvSymType_VS2013_GProc32,
+ /** @} */
+
+ kCvSymType_EndOfValues
+} RTCVSYMTYPE;
+AssertCompile(kCvSymType_V3_Udt == 0x1108);
+AssertCompile(kCvSymType_V3_GProc == 0x1110);
+AssertCompile(kCvSymType_V3_MSTool == 0x1116);
+AssertCompile(kCvSymType_VS2013_Local == 0x113E);
+typedef RTCVSYMTYPE *PRTCVSYMTYPE;
+typedef RTCVSYMTYPE const *PCRTCVSYMTYPE;
+
+
+/**
+ * kCvSymType_V3_MSTool format.
+ */
+typedef struct RTCVSYMV3MSTOOL
+{
+ /** Language or tool ID (3 == masm). */
+ uint32_t uLanguage;
+ /** Target CPU (0xd0 == AMD64). */
+ uint32_t uTargetCpu;
+ /** Flags. */
+ uint32_t fFlags;
+ /** Version. */
+ uint32_t uVersion;
+ /** The creator name, zero terminated.
+ *
+ * It is followed by key/value pairs of zero terminated strings giving more
+ * details about the current directory ('cwd'), compiler executable ('cl'),
+ * full command line ('cmd'), source path relative to cwd ('src'), the
+ * full program database path ('pdb'), and possibly others. Terminated by a
+ * pair of empty strings, usually. */
+ char szCreator[1];
+} RTCVSYMV3MSTOOL;
+typedef RTCVSYMV3MSTOOL *PRTCVSYMV3MSTOOL;
+typedef RTCVSYMV3MSTOOL const *PCRTCVSYMV3MSTOOL;
+
+/**
+ * kCvSymType_V3_Label format.
+ */
+typedef struct RTCVSYMV3LABEL
+{
+ /** Offset into iSection of this symbol. */
+ uint32_t offSection;
+ /** The index of the section where the symbol lives. */
+ uint16_t iSection;
+ /** Flags or something. */
+ uint8_t fFlags;
+ /** Zero terminated symbol name (variable length). */
+ char szName[1];
+} RTCVSYMV3LABEL;
+AssertCompileSize(RTCVSYMV3LABEL, 8);
+typedef RTCVSYMV3LABEL *PRTCVSYMV3LABEL;
+typedef RTCVSYMV3LABEL const *PCRTCVSYMV3LABEL;
+
+/**
+ * kCvSymType_V3_LData and kCvSymType_V3_GData format.
+ */
+typedef struct RTCVSYMV3TYPEDNAME
+{
+ /** The type ID. */
+ uint32_t idType;
+ /** Offset into iSection of this symbol. */
+ uint32_t offSection;
+ /** The index of the section where the symbol lives. */
+ uint16_t iSection;
+ /** Zero terminated symbol name (variable length). */
+ char szName[2];
+} RTCVSYMV3TYPEDNAME;
+AssertCompileSize(RTCVSYMV3TYPEDNAME, 12);
+typedef RTCVSYMV3TYPEDNAME *PRTCVSYMV3TYPEDNAME;
+typedef RTCVSYMV3TYPEDNAME const *PCRTCVSYMV3TYPEDNAME;
+
+/**
+ * kCvSymType_V3_LProc and kCvSymType_V3_GProc format.
+ */
+typedef struct RTCVSYMV3PROC
+{
+ /** Lexical scope linking: Parent. */
+ uint32_t uParent;
+ /** Lexical scope linking: End. */
+ uint32_t uEnd;
+ /** Lexical scope linking: Next. */
+ uint32_t uNext;
+ /** The procedure length. */
+ uint32_t cbProc;
+ /** Offset into the procedure where the stack frame has been setup and is an
+ * excellent position for a function breakpoint. */
+ uint32_t offDebugStart;
+ /** Offset into the procedure where the procedure is ready to return and has a
+ * return value (if applicable). */
+ uint32_t offDebugEnd;
+ /** The type ID for the procedure. */
+ uint32_t idType;
+ /** Offset into iSection of this procedure. */
+ uint32_t offSection;
+ /** The index of the section where the procedure lives. */
+ uint16_t iSection;
+ /** Flags. */
+ uint8_t fFlags;
+ /** Zero terminated procedure name (variable length). */
+ char szName[1];
+} RTCVSYMV3PROC;
+AssertCompileSize(RTCVSYMV3PROC, 36);
+typedef RTCVSYMV3PROC *PRTCVSYMV3PROC;
+typedef RTCVSYMV3PROC const *PCRTCVSYMV3PROC;
+
+
+/** @name $$SYMBOLS signatures.
+ * @{ */
+/** The $$SYMBOL table signature for CV4. */
+#define RTCVSYMBOLS_SIGNATURE_CV4 UINT32_C(0x00000001)
+/** The $$SYMBOL table signature for CV8 (MSVC 8/2005).
+ * Also seen with MSVC 2010 using -Z7, so maybe more appropriate to call it
+ * CV7? */
+#define RTCVSYMBOLS_SIGNATURE_CV8 UINT32_C(0x00000004)
+/** @} */
+
+
+/**
+ * CV8 $$SYMBOLS block header.
+ */
+typedef struct RTCV8SYMBOLSBLOCK
+{
+ /** BLock type (RTCV8SYMBLOCK_TYPE_XXX). */
+ uint32_t uType;
+ /** The block length, including this header? */
+ uint32_t cb;
+} RTCV8SYMBOLSBLOCK;
+AssertCompileSize(RTCV8SYMBOLSBLOCK, 8);
+typedef RTCV8SYMBOLSBLOCK *PRTCV8SYMBOLSBLOCK;
+typedef RTCV8SYMBOLSBLOCK const *PCRTCV8SYMBOLSBLOCK;
+
+/** @name RTCV8SYMBLOCK_TYPE_XXX - CV8 (MSVC 8/2005) $$SYMBOL table types.
+ * @{ */
+/** Symbol information.
+ * Sequence of types. Each type entry starts with a 16-bit length followed
+ * by a 16-bit RTCVSYMTYPE value. Just like CV4/5, but with C-strings
+ * instead of pascal. */
+#define RTCV8SYMBLOCK_TYPE_SYMBOLS UINT32_C(0x000000f1)
+/** Line numbers for a section. */
+#define RTCV8SYMBLOCK_TYPE_SECT_LINES UINT32_C(0x000000f2)
+/** Source file string table.
+ * The strings are null terminated. Indexed by RTCV8SYMBLOCK_TYPE_SRC_INFO. */
+#define RTCV8SYMBLOCK_TYPE_SRC_STR UINT32_C(0x000000f3)
+/** Source file information. */
+#define RTCV8SYMBLOCK_TYPE_SRC_INFO UINT32_C(0x000000f4)
+/** @} */
+
+/**
+ * Line number header found in a RTCV8SYMBLOCK_TYPE_SECT_LINES block.
+ *
+ * This is followed by a sequence of RTCV8LINESSRCMAP structures.
+ */
+typedef struct RTCV8LINESHDR
+{
+ /** Offset into the section. */
+ uint32_t offSection;
+ /** The section number. */
+ uint16_t iSection;
+ /** Padding/zero/maybe-previous-member-is-a-32-bit-value. */
+ uint16_t u16Padding;
+ /** Number of bytes covered by this table, starting at offSection. */
+ uint32_t cbSectionCovered;
+} RTCV8LINESHDR;
+AssertCompileSize(RTCV8LINESHDR, 12);
+typedef RTCV8LINESHDR *PRTCV8LINESHDR;
+typedef RTCV8LINESHDR const *PCRTCV8LINESHDR;
+
+/**
+ * CV8 (MSVC 8/2005) line number source map.
+ *
+ * This is followed by an array of RTCV8LINEPAIR.
+ */
+typedef struct RTCV8LINESSRCMAP
+{
+ /** The source file, given as an offset (byte) into the source file
+ * information table (RTCV8SYMBLOCK_TYPE_SRC_INFO). */
+ uint32_t offSourceInfo;
+ /** Number of line numbers following this structure. */
+ uint32_t cLines;
+ /** The size of this source map. */
+ uint32_t cb;
+} RTCV8LINESSRCMAP;
+AssertCompileSize(RTCV8LINESSRCMAP, 12);
+typedef RTCV8LINESSRCMAP *PRTCV8LINESSRCMAP;
+typedef RTCV8LINESSRCMAP const *PCRTCV8LINESSRCMAP;
+
+/**
+ * One line number.
+ */
+typedef struct RTCV8LINEPAIR
+{
+ /** Offset into the section of this line number. */
+ uint32_t offSection;
+ /** The line number. */
+ uint32_t uLineNumber : 30;
+ /** Indicates that it's not possible to set breakpoint? */
+ uint32_t fEndOfStatement : 1;
+} RTCV8LINEPAIR;
+AssertCompileSize(RTCV8LINEPAIR, 8);
+typedef RTCV8LINEPAIR *PRTCV8LINEPAIR;
+typedef RTCV8LINEPAIR const *PCRTCV8LINEPAIR;
+
+/**
+ * Source file information found in a RTCV8SYMBLOCK_TYPE_SRC_INFO block.
+ */
+typedef struct RTCV8SRCINFO
+{
+ /** The source file name, given as an offset into the string table
+ * (RTCV8SYMBLOCK_TYPE_SRC_STR). */
+ uint32_t offSourceName;
+ /** Digest/checksum type. */
+ uint16_t uDigestType;
+ union
+ {
+ /** RTCV8SRCINFO_DIGEST_TYPE_MD5. */
+ struct
+ {
+ /** The digest. */
+ uint8_t ab[16];
+ /** Structur alignment padding. */
+ uint8_t abPadding[2];
+ } md5;
+ /** RTCV8SRCINFO_DIGEST_TYPE_NONE: Padding. */
+ uint8_t abNone[2];
+ } Digest;
+} RTCV8SRCINFO;
+AssertCompileSize(RTCV8SRCINFO, 24);
+typedef RTCV8SRCINFO *PRTCV8SRCINFO;
+typedef RTCV8SRCINFO const *PCRTCV8SRCINFO;
+
+/** @name RTCV8SRCINFO_DIGEST_TYPE_XXX - CV8 source digest types.
+ * Used by RTCV8SRCINFO::uDigestType.
+ * @{ */
+#define RTCV8SRCINFO_DIGEST_TYPE_NONE UINT16_C(0x0000)
+#define RTCV8SRCINFO_DIGEST_TYPE_MD5 UINT16_C(0x0110)
+/** @} */
+
+
+
+/**
+ * PDB v2.0 in image debug info.
+ * The URL is constructed from the timestamp and age?
+ */
+typedef struct CVPDB20INFO
+{
+ uint32_t u32Magic; /**< CVPDB20INFO_SIGNATURE. */
+ int32_t offDbgInfo; /**< Always 0. Used to be the offset to the real debug info. */
+ uint32_t uTimestamp;
+ uint32_t uAge;
+ uint8_t szPdbFilename[4];
+} CVPDB20INFO;
+/** Pointer to in executable image PDB v2.0 info. */
+typedef CVPDB20INFO *PCVPDB20INFO;
+/** Pointer to read only in executable image PDB v2.0 info. */
+typedef CVPDB20INFO const *PCCVPDB20INFO;
+/** The CVPDB20INFO magic value. */
+#define CVPDB20INFO_MAGIC RT_MAKE_U32_FROM_U8('N','B','1','0')
+
+/**
+ * PDB v7.0 in image debug info.
+ * The URL is constructed from the signature and the age.
+ */
+#pragma pack(4)
+typedef struct CVPDB70INFO
+{
+ uint32_t u32Magic; /**< CVPDB70INFO_SIGNATURE. */
+ RTUUID PdbUuid;
+ uint32_t uAge;
+ uint8_t szPdbFilename[4];
+} CVPDB70INFO;
+#pragma pack()
+AssertCompileMemberOffset(CVPDB70INFO, PdbUuid, 4);
+AssertCompileMemberOffset(CVPDB70INFO, uAge, 4 + 16);
+/** Pointer to in executable image PDB v7.0 info. */
+typedef CVPDB70INFO *PCVPDB70INFO;
+/** Pointer to read only in executable image PDB v7.0 info. */
+typedef CVPDB70INFO const *PCCVPDB70INFO;
+/** The CVPDB70INFO magic value. */
+#define CVPDB70INFO_MAGIC RT_MAKE_U32_FROM_U8('R','S','D','S')
+
+
+/** @} */
+
+#endif /* !IPRT_INCLUDED_formats_codeview_h */
+
diff --git a/include/iprt/formats/cpio.h b/include/iprt/formats/cpio.h
new file mode 100644
index 00000000..a202a0a6
--- /dev/null
+++ b/include/iprt/formats/cpio.h
@@ -0,0 +1,210 @@
+/** @file
+ * IPRT - CPIO archive format.
+ */
+
+/*
+ * Copyright (C) 2020-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_formats_cpio_h
+#define IPRT_INCLUDED_formats_cpio_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+#include <iprt/assertcompile.h>
+
+
+/** @defgroup grp_rt_formats_cpio CPIO Archive format
+ * @ingroup grp_rt_formats
+ *
+ * @{ */
+
+/** This denotes the end of the archive (record with this filename, zero size and
+ * a zero mode). */
+#define CPIO_EOS_FILE_NAME "TRAILER!!!"
+
+
+/**
+ * The old binary header.
+ */
+typedef struct CPIOHDRBIN
+{
+ /** 0x00: Magic identifying the old header. */
+ uint16_t u16Magic;
+ /** 0x02: Device number. */
+ uint16_t u16Dev;
+ /** 0x04: Inode number. */
+ uint16_t u16Inode;
+ /** 0x06: Mode. */
+ uint16_t u16Mode;
+ /** 0x08: User ID. */
+ uint16_t u16Uid;
+ /** 0x0a: Group ID. */
+ uint16_t u16Gid;
+ /** 0x0c: Number of links to this file. */
+ uint16_t u16NLinks;
+ /** 0x0e: Associated device number for block and character device entries. */
+ uint16_t u16RDev;
+ /** 0x10: Modification time stored as two independent 16bit integers. */
+ uint16_t au16MTime[2];
+ /** 0x14: Number of bytes in the path name (including zero terminator) following the header. */
+ uint16_t u16NameSize;
+ /** 0x16: Size of the file stored as two independent 16bit integers. */
+ uint16_t au16FileSize[2];
+} CPIOHDRBIN;
+AssertCompileSize(CPIOHDRBIN, 13 * 2);
+typedef CPIOHDRBIN *PCPIOHDRBIN;
+typedef const CPIOHDRBIN *PCCPIOHDRBIN;
+
+
+/** The magic for the binary header. */
+#define CPIO_HDR_BIN_MAGIC UINT16_C(070707)
+
+
+/**
+ * Portable ASCII format header as defined by SUSv2.
+ */
+typedef struct CPIOHDRSUSV2
+{
+ /** 0x00: Magic identifying the header. */
+ char achMagic[6];
+ /** 0x06: Device number. */
+ char achDev[6];
+ /** 0x0c: Inode number. */
+ char achInode[6];
+ /** 0x12: Mode. */
+ char achMode[6];
+ /** 0x18: User ID. */
+ char achUid[6];
+ /** 0x1e: Group ID. */
+ char achGid[6];
+ /** 0x24: Number of links to this file. */
+ char achNLinks[6];
+ /** 0x2a: Associated device number for block and character device entries. */
+ char achRDev[6];
+ /** 0x30: Modification time stored as two independent 16bit integers. */
+ char achMTime[11];
+ /** 0x36: Number of bytes in the path name (including zero terminator) following the header. */
+ char achNameSize[6];
+ /** 0x3c: Size of the file stored as two independent 16bit integers. */
+ char achFileSize[11];
+} CPIOHDRSUSV2;
+AssertCompileSize(CPIOHDRSUSV2, 9 * 6 + 2 * 11);
+typedef CPIOHDRSUSV2 *PCPIOHDRSUSV2;
+typedef const CPIOHDRSUSV2 *PCCPIOHDRSUSV2;
+
+
+/** The magic for the SuSv2 CPIO header. */
+#define CPIO_HDR_SUSV2_MAGIC "070707"
+
+
+/**
+ * New ASCII format header.
+ */
+typedef struct CPIOHDRNEW
+{
+ /** 0x00: Magic identifying the header. */
+ char achMagic[6];
+ /** 0x06: Inode number. */
+ char achInode[8];
+ /** 0x0e: Mode. */
+ char achMode[8];
+ /** 0x16: User ID. */
+ char achUid[8];
+ /** 0x1e: Group ID. */
+ char achGid[8];
+ /** 0x26: Number of links to this file. */
+ char achNLinks[8];
+ /** 0x2e: Modification time. */
+ char achMTime[8];
+ /** 0x36: Size of the file stored as two independent 16bit integers. */
+ char achFileSize[8];
+ /** 0x3e: Device major number. */
+ char achDevMajor[8];
+ /** 0x46: Device minor number. */
+ char achDevMinor[8];
+ /** 0x4e: Assigned device major number for block or character device files. */
+ char achRDevMajor[8];
+ /** 0x56: Assigned device minor number for block or character device files. */
+ char achRDevMinor[8];
+ /** 0x5e: Number of bytes in the path name (including zero terminator) following the header. */
+ char achNameSize[8];
+ /** 0x66: Checksum of the file data if used. */
+ char achCheck[8];
+} CPIOHDRNEW;
+AssertCompileSize(CPIOHDRNEW, 6 + 13 * 8);
+AssertCompileMemberOffset(CPIOHDRNEW, achMagic, 0x00);
+AssertCompileMemberOffset(CPIOHDRNEW, achInode, 0x06);
+AssertCompileMemberOffset(CPIOHDRNEW, achMode, 0x0e);
+AssertCompileMemberOffset(CPIOHDRNEW, achUid, 0x16);
+AssertCompileMemberOffset(CPIOHDRNEW, achGid, 0x1e);
+AssertCompileMemberOffset(CPIOHDRNEW, achNLinks, 0x26);
+AssertCompileMemberOffset(CPIOHDRNEW, achMTime, 0x2e);
+AssertCompileMemberOffset(CPIOHDRNEW, achFileSize, 0x36);
+AssertCompileMemberOffset(CPIOHDRNEW, achDevMajor, 0x3e);
+AssertCompileMemberOffset(CPIOHDRNEW, achDevMinor, 0x46);
+AssertCompileMemberOffset(CPIOHDRNEW, achRDevMajor, 0x4e);
+AssertCompileMemberOffset(CPIOHDRNEW, achRDevMinor, 0x56);
+AssertCompileMemberOffset(CPIOHDRNEW, achNameSize, 0x5e);
+AssertCompileMemberOffset(CPIOHDRNEW, achCheck, 0x66);
+typedef CPIOHDRNEW *PCPIOHDRNEW;
+typedef const CPIOHDRNEW *PCCPIOHDRNEW;
+
+
+/** The magic for the new ASCII CPIO header. */
+#define CPIO_HDR_NEW_MAGIC "070701"
+/** The magic for the new ASCII CPIO header + checksum. */
+#define CPIO_HDR_NEW_CHKSUM_MAGIC "070702"
+
+
+/**
+ * CPIO header union.
+ */
+typedef union CPIOHDR
+{
+ /** byte view. */
+ uint8_t ab[110];
+ /** The ancient binary header. */
+ CPIOHDRBIN AncientBin;
+ /** The SuSv2 ASCII header. */
+ CPIOHDRSUSV2 AsciiSuSv2;
+ /** The new ASCII header format. */
+ CPIOHDRNEW AsciiNew;
+} CPIOHDR;
+typedef CPIOHDR *PCPIOHDR;
+typedef const CPIOHDR *PCCPIOHDR;
+
+
+/** @} */
+
+#endif /* !IPRT_INCLUDED_formats_cpio_h */
+
diff --git a/include/iprt/formats/dwarf.h b/include/iprt/formats/dwarf.h
new file mode 100644
index 00000000..45a58ad9
--- /dev/null
+++ b/include/iprt/formats/dwarf.h
@@ -0,0 +1,542 @@
+/** @file
+ * IPRT - DWARF constants.
+ *
+ * @note dwarf.mac is generated from this file by running 'kmk incs' in the root.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_formats_dwarf_h
+#define IPRT_INCLUDED_formats_dwarf_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+
+/** @name Standard DWARF Line Number Opcodes
+ * @{ */
+#define DW_LNS_extended UINT8_C(0x00)
+#define DW_LNS_copy UINT8_C(0x01)
+#define DW_LNS_advance_pc UINT8_C(0x02)
+#define DW_LNS_advance_line UINT8_C(0x03)
+#define DW_LNS_set_file UINT8_C(0x04)
+#define DW_LNS_set_column UINT8_C(0x05)
+#define DW_LNS_negate_stmt UINT8_C(0x06)
+#define DW_LNS_set_basic_block UINT8_C(0x07)
+#define DW_LNS_const_add_pc UINT8_C(0x08)
+#define DW_LNS_fixed_advance_pc UINT8_C(0x09)
+#define DW_LNS_set_prologue_end UINT8_C(0x0a)
+#define DW_LNS_set_epilogue_begin UINT8_C(0x0b)
+#define DW_LNS_set_isa UINT8_C(0x0c)
+#define DW_LNS_what_question_mark UINT8_C(0x0d)
+/** @} */
+
+
+/** @name Extended DWARF Line Number Opcodes
+ * @{ */
+#define DW_LNE_end_sequence UINT8_C(1)
+#define DW_LNE_set_address UINT8_C(2)
+#define DW_LNE_define_file UINT8_C(3)
+#define DW_LNE_set_descriminator UINT8_C(4)
+/** @} */
+
+
+/** @name DIE Tags.
+ * @{ */
+#define DW_TAG_array_type UINT16_C(0x0001)
+#define DW_TAG_class_type UINT16_C(0x0002)
+#define DW_TAG_entry_point UINT16_C(0x0003)
+#define DW_TAG_enumeration_type UINT16_C(0x0004)
+#define DW_TAG_formal_parameter UINT16_C(0x0005)
+#define DW_TAG_imported_declaration UINT16_C(0x0008)
+#define DW_TAG_label UINT16_C(0x000a)
+#define DW_TAG_lexical_block UINT16_C(0x000b)
+#define DW_TAG_member UINT16_C(0x000d)
+#define DW_TAG_pointer_type UINT16_C(0x000f)
+#define DW_TAG_reference_type UINT16_C(0x0010)
+#define DW_TAG_compile_unit UINT16_C(0x0011)
+#define DW_TAG_string_type UINT16_C(0x0012)
+#define DW_TAG_structure_type UINT16_C(0x0013)
+#define DW_TAG_subroutine_type UINT16_C(0x0015)
+#define DW_TAG_typedef UINT16_C(0x0016)
+#define DW_TAG_union_type UINT16_C(0x0017)
+#define DW_TAG_unspecified_parameters UINT16_C(0x0018)
+#define DW_TAG_variant UINT16_C(0x0019)
+#define DW_TAG_common_block UINT16_C(0x001a)
+#define DW_TAG_common_inclusion UINT16_C(0x001b)
+#define DW_TAG_inheritance UINT16_C(0x001c)
+#define DW_TAG_inlined_subroutine UINT16_C(0x001d)
+#define DW_TAG_module UINT16_C(0x001e)
+#define DW_TAG_ptr_to_member_type UINT16_C(0x001f)
+#define DW_TAG_set_type UINT16_C(0x0020)
+#define DW_TAG_subrange_type UINT16_C(0x0021)
+#define DW_TAG_with_stmt UINT16_C(0x0022)
+#define DW_TAG_access_declaration UINT16_C(0x0023)
+#define DW_TAG_base_type UINT16_C(0x0024)
+#define DW_TAG_catch_block UINT16_C(0x0025)
+#define DW_TAG_const_type UINT16_C(0x0026)
+#define DW_TAG_constant UINT16_C(0x0027)
+#define DW_TAG_enumerator UINT16_C(0x0028)
+#define DW_TAG_file_type UINT16_C(0x0029)
+#define DW_TAG_friend UINT16_C(0x002a)
+#define DW_TAG_namelist UINT16_C(0x002b)
+#define DW_TAG_namelist_item UINT16_C(0x002c)
+#define DW_TAG_packed_type UINT16_C(0x002d)
+#define DW_TAG_subprogram UINT16_C(0x002e)
+#define DW_TAG_template_type_parameter UINT16_C(0x002f)
+#define DW_TAG_template_value_parameter UINT16_C(0x0030)
+#define DW_TAG_thrown_type UINT16_C(0x0031)
+#define DW_TAG_try_block UINT16_C(0x0032)
+#define DW_TAG_variant_part UINT16_C(0x0033)
+#define DW_TAG_variable UINT16_C(0x0034)
+#define DW_TAG_volatile_type UINT16_C(0x0035)
+#define DW_TAG_dwarf_procedure UINT16_C(0x0036)
+#define DW_TAG_restrict_type UINT16_C(0x0037)
+#define DW_TAG_interface_type UINT16_C(0x0038)
+#define DW_TAG_namespace UINT16_C(0x0039)
+#define DW_TAG_imported_module UINT16_C(0x003a)
+#define DW_TAG_unspecified_type UINT16_C(0x003b)
+#define DW_TAG_partial_unit UINT16_C(0x003c)
+#define DW_TAG_imported_unit UINT16_C(0x003d)
+#define DW_TAG_condition UINT16_C(0x003f)
+#define DW_TAG_shared_type UINT16_C(0x0040)
+#define DW_TAG_type_unit UINT16_C(0x0041)
+#define DW_TAG_rvalue_reference_type UINT16_C(0x0042)
+#define DW_TAG_template_alias UINT16_C(0x0043)
+#define DW_TAG_lo_user UINT16_C(0x4080)
+#define DW_TAG_GNU_call_site UINT16_C(0x4109)
+#define DW_TAG_GNU_call_site_parameter UINT16_C(0x410a)
+#define DW_TAG_WATCOM_address_class_type UINT16_C(0x4100) /**< Watcom extension. */
+#define DW_TAG_WATCOM_namespace UINT16_C(0x4101) /**< Watcom extension. */
+#define DW_TAG_hi_user UINT16_C(0xffff)
+/** @} */
+
+
+/** @name Has children or not (follows DW_TAG_xxx in .debug_abbrev).
+ * @{ */
+#define DW_CHILDREN_yes 1
+#define DW_CHILDREN_no 0
+/** @} */
+
+
+/** @name DIE Attributes.
+ * @{ */
+#define DW_AT_sibling UINT16_C(0x0001)
+#define DW_AT_location UINT16_C(0x0002)
+#define DW_AT_name UINT16_C(0x0003)
+#define DW_AT_ordering UINT16_C(0x0009)
+#define DW_AT_byte_size UINT16_C(0x000b)
+#define DW_AT_bit_offset UINT16_C(0x000c)
+#define DW_AT_bit_size UINT16_C(0x000d)
+#define DW_AT_stmt_list UINT16_C(0x0010)
+#define DW_AT_low_pc UINT16_C(0x0011)
+#define DW_AT_high_pc UINT16_C(0x0012)
+#define DW_AT_language UINT16_C(0x0013)
+#define DW_AT_discr UINT16_C(0x0015)
+#define DW_AT_discr_value UINT16_C(0x0016)
+#define DW_AT_visibility UINT16_C(0x0017)
+#define DW_AT_import UINT16_C(0x0018)
+#define DW_AT_string_length UINT16_C(0x0019)
+#define DW_AT_common_reference UINT16_C(0x001a)
+#define DW_AT_comp_dir UINT16_C(0x001b)
+#define DW_AT_const_value UINT16_C(0x001c)
+#define DW_AT_containing_type UINT16_C(0x001d)
+#define DW_AT_default_value UINT16_C(0x001e)
+#define DW_AT_inline UINT16_C(0x0020)
+#define DW_AT_is_optional UINT16_C(0x0021)
+#define DW_AT_lower_bound UINT16_C(0x0022)
+#define DW_AT_producer UINT16_C(0x0025)
+#define DW_AT_prototyped UINT16_C(0x0027)
+#define DW_AT_return_addr UINT16_C(0x002a)
+#define DW_AT_start_scope UINT16_C(0x002c)
+#define DW_AT_bit_stride UINT16_C(0x002e)
+#define DW_AT_upper_bound UINT16_C(0x002f)
+#define DW_AT_abstract_origin UINT16_C(0x0031)
+#define DW_AT_accessibility UINT16_C(0x0032)
+#define DW_AT_address_class UINT16_C(0x0033)
+#define DW_AT_artificial UINT16_C(0x0034)
+#define DW_AT_base_types UINT16_C(0x0035)
+#define DW_AT_calling_convention UINT16_C(0x0036)
+#define DW_AT_count UINT16_C(0x0037)
+#define DW_AT_data_member_location UINT16_C(0x0038)
+#define DW_AT_decl_column UINT16_C(0x0039)
+#define DW_AT_decl_file UINT16_C(0x003a)
+#define DW_AT_decl_line UINT16_C(0x003b)
+#define DW_AT_declaration UINT16_C(0x003c)
+#define DW_AT_discr_list UINT16_C(0x003d)
+#define DW_AT_encoding UINT16_C(0x003e)
+#define DW_AT_external UINT16_C(0x003f)
+#define DW_AT_frame_base UINT16_C(0x0040)
+#define DW_AT_friend UINT16_C(0x0041)
+#define DW_AT_identifier_case UINT16_C(0x0042)
+#define DW_AT_macro_info UINT16_C(0x0043)
+#define DW_AT_namelist_item UINT16_C(0x0044)
+#define DW_AT_priority UINT16_C(0x0045)
+#define DW_AT_segment UINT16_C(0x0046)
+#define DW_AT_specification UINT16_C(0x0047)
+#define DW_AT_static_link UINT16_C(0x0048)
+#define DW_AT_type UINT16_C(0x0049)
+#define DW_AT_use_location UINT16_C(0x004a)
+#define DW_AT_variable_parameter UINT16_C(0x004b)
+#define DW_AT_virtuality UINT16_C(0x004c)
+#define DW_AT_vtable_elem_location UINT16_C(0x004d)
+#define DW_AT_allocated UINT16_C(0x004e)
+#define DW_AT_associated UINT16_C(0x004f)
+#define DW_AT_data_location UINT16_C(0x0050)
+#define DW_AT_byte_stride UINT16_C(0x0051)
+#define DW_AT_entry_pc UINT16_C(0x0052)
+#define DW_AT_use_UTF8 UINT16_C(0x0053)
+#define DW_AT_extension UINT16_C(0x0054)
+#define DW_AT_ranges UINT16_C(0x0055)
+#define DW_AT_trampoline UINT16_C(0x0056)
+#define DW_AT_call_column UINT16_C(0x0057)
+#define DW_AT_call_file UINT16_C(0x0058)
+#define DW_AT_call_line UINT16_C(0x0059)
+#define DW_AT_description UINT16_C(0x005a)
+#define DW_AT_binary_scale UINT16_C(0x005b)
+#define DW_AT_decimal_scale UINT16_C(0x005c)
+#define DW_AT_small UINT16_C(0x005d)
+#define DW_AT_decimal_sign UINT16_C(0x005e)
+#define DW_AT_digit_count UINT16_C(0x005f)
+#define DW_AT_picture_string UINT16_C(0x0060)
+#define DW_AT_mutable UINT16_C(0x0061)
+#define DW_AT_threads_scaled UINT16_C(0x0062)
+#define DW_AT_explicit UINT16_C(0x0063)
+#define DW_AT_object_pointer UINT16_C(0x0064)
+#define DW_AT_endianity UINT16_C(0x0065)
+#define DW_AT_elemental UINT16_C(0x0066)
+#define DW_AT_pure UINT16_C(0x0067)
+#define DW_AT_recursive UINT16_C(0x0068)
+#define DW_AT_signature UINT16_C(0x0069)
+#define DW_AT_main_subprogram UINT16_C(0x006a)
+#define DW_AT_data_bit_offset UINT16_C(0x006b)
+#define DW_AT_const_expr UINT16_C(0x006c)
+#define DW_AT_enum_class UINT16_C(0x006d)
+#define DW_AT_linkage_name UINT16_C(0x006e)
+#define DW_AT_lo_user UINT16_C(0x2000)
+/** Used by GCC and others, same as DW_AT_linkage_name. See http://wiki.dwarfstd.org/index.php?title=DW_AT_linkage_name*/
+#define DW_AT_MIPS_linkage_name UINT16_C(0x2007)
+#define DW_AT_WATCOM_memory_model UINT16_C(0x2082) /**< Watcom extension. */
+#define DW_AT_WATCOM_references_start UINT16_C(0x2083) /**< Watcom extension. */
+#define DW_AT_WATCOM_parm_entry UINT16_C(0x2084) /**< Watcom extension. */
+#define DW_AT_hi_user UINT16_C(0x3fff)
+/** @} */
+
+/** @name DIE Forms.
+ * @{ */
+#define DW_FORM_addr UINT16_C(0x01)
+/* 0x02 was FORM_REF in DWARF v1, obsolete now. */
+#define DW_FORM_block2 UINT16_C(0x03)
+#define DW_FORM_block4 UINT16_C(0x04)
+#define DW_FORM_data2 UINT16_C(0x05)
+#define DW_FORM_data4 UINT16_C(0x06)
+#define DW_FORM_data8 UINT16_C(0x07)
+#define DW_FORM_string UINT16_C(0x08)
+#define DW_FORM_block UINT16_C(0x09)
+#define DW_FORM_block1 UINT16_C(0x0a)
+#define DW_FORM_data1 UINT16_C(0x0b)
+#define DW_FORM_flag UINT16_C(0x0c)
+#define DW_FORM_sdata UINT16_C(0x0d)
+#define DW_FORM_strp UINT16_C(0x0e)
+#define DW_FORM_udata UINT16_C(0x0f)
+#define DW_FORM_ref_addr UINT16_C(0x10)
+#define DW_FORM_ref1 UINT16_C(0x11)
+#define DW_FORM_ref2 UINT16_C(0x12)
+#define DW_FORM_ref4 UINT16_C(0x13)
+#define DW_FORM_ref8 UINT16_C(0x14)
+#define DW_FORM_ref_udata UINT16_C(0x15)
+#define DW_FORM_indirect UINT16_C(0x16)
+#define DW_FORM_sec_offset UINT16_C(0x17)
+#define DW_FORM_exprloc UINT16_C(0x18)
+#define DW_FORM_flag_present UINT16_C(0x19)
+#define DW_FORM_ref_sig8 UINT16_C(0x20)
+/** @} */
+
+/** @name Address classes.
+ * @{ */
+#define DW_ADDR_none UINT8_C(0)
+#define DW_ADDR_i386_near16 UINT8_C(1)
+#define DW_ADDR_i386_far16 UINT8_C(2)
+#define DW_ADDR_i386_huge16 UINT8_C(3)
+#define DW_ADDR_i386_near32 UINT8_C(4)
+#define DW_ADDR_i386_far32 UINT8_C(5)
+/** @} */
+
+
+/** @name Location Expression Opcodes
+ * @{ */
+#define DW_OP_addr UINT8_C(0x03) /**< 1 operand, a constant address (size target specific). */
+#define DW_OP_deref UINT8_C(0x06) /**< 0 operands. */
+#define DW_OP_const1u UINT8_C(0x08) /**< 1 operand, a 1-byte constant. */
+#define DW_OP_const1s UINT8_C(0x09) /**< 1 operand, a 1-byte constant. */
+#define DW_OP_const2u UINT8_C(0x0a) /**< 1 operand, a 2-byte constant. */
+#define DW_OP_const2s UINT8_C(0x0b) /**< 1 operand, a 2-byte constant. */
+#define DW_OP_const4u UINT8_C(0x0c) /**< 1 operand, a 4-byte constant. */
+#define DW_OP_const4s UINT8_C(0x0d) /**< 1 operand, a 4-byte constant. */
+#define DW_OP_const8u UINT8_C(0x0e) /**< 1 operand, a 8-byte constant. */
+#define DW_OP_const8s UINT8_C(0x0f) /**< 1 operand, a 8-byte constant. */
+#define DW_OP_constu UINT8_C(0x10) /**< 1 operand, a ULEB128 constant. */
+#define DW_OP_consts UINT8_C(0x11) /**< 1 operand, a SLEB128 constant. */
+#define DW_OP_dup UINT8_C(0x12) /**< 0 operands. */
+#define DW_OP_drop UINT8_C(0x13) /**< 0 operands. */
+#define DW_OP_over UINT8_C(0x14) /**< 0 operands. */
+#define DW_OP_pick UINT8_C(0x15) /**< 1 operands, a 1-byte stack index. */
+#define DW_OP_swap UINT8_C(0x16) /**< 0 operands. */
+#define DW_OP_rot UINT8_C(0x17) /**< 0 operands. */
+#define DW_OP_xderef UINT8_C(0x18) /**< 0 operands. */
+#define DW_OP_abs UINT8_C(0x19) /**< 0 operands. */
+#define DW_OP_and UINT8_C(0x1a) /**< 0 operands. */
+#define DW_OP_div UINT8_C(0x1b) /**< 0 operands. */
+#define DW_OP_minus UINT8_C(0x1c) /**< 0 operands. */
+#define DW_OP_mod UINT8_C(0x1d) /**< 0 operands. */
+#define DW_OP_mul UINT8_C(0x1e) /**< 0 operands. */
+#define DW_OP_neg UINT8_C(0x1f) /**< 0 operands. */
+#define DW_OP_not UINT8_C(0x20) /**< 0 operands. */
+#define DW_OP_or UINT8_C(0x21) /**< 0 operands. */
+#define DW_OP_plus UINT8_C(0x22) /**< 0 operands. */
+#define DW_OP_plus_uconst UINT8_C(0x23) /**< 1 operands, a ULEB128 addend. */
+#define DW_OP_shl UINT8_C(0x24) /**< 0 operands. */
+#define DW_OP_shr UINT8_C(0x25) /**< 0 operands. */
+#define DW_OP_shra UINT8_C(0x26) /**< 0 operands. */
+#define DW_OP_xor UINT8_C(0x27) /**< 0 operands. */
+#define DW_OP_skip UINT8_C(0x2f) /**< 1 signed 2-byte constant. */
+#define DW_OP_bra UINT8_C(0x28) /**< 1 signed 2-byte constant. */
+#define DW_OP_eq UINT8_C(0x29) /**< 0 operands. */
+#define DW_OP_ge UINT8_C(0x2a) /**< 0 operands. */
+#define DW_OP_gt UINT8_C(0x2b) /**< 0 operands. */
+#define DW_OP_le UINT8_C(0x2c) /**< 0 operands. */
+#define DW_OP_lt UINT8_C(0x2d) /**< 0 operands. */
+#define DW_OP_ne UINT8_C(0x2e) /**< 0 operands. */
+#define DW_OP_lit0 UINT8_C(0x30) /**< 0 operands - literals 0..31 */
+#define DW_OP_lit31 UINT8_C(0x4f) /**< last litteral. */
+#define DW_OP_reg0 UINT8_C(0x50) /**< 0 operands - reg 0..31. */
+#define DW_OP_reg31 UINT8_C(0x6f) /**< last register. */
+#define DW_OP_breg0 UINT8_C(0x70) /**< 1 operand, a SLEB128 offset. */
+#define DW_OP_breg31 UINT8_C(0x8f) /**< last branch register. */
+#define DW_OP_regx UINT8_C(0x90) /**< 1 operand, a ULEB128 register. */
+#define DW_OP_fbreg UINT8_C(0x91) /**< 1 operand, a SLEB128 offset. */
+#define DW_OP_bregx UINT8_C(0x92) /**< 2 operands, a ULEB128 register followed by a SLEB128 offset. */
+#define DW_OP_piece UINT8_C(0x93) /**< 1 operand, a ULEB128 size of piece addressed. */
+#define DW_OP_deref_size UINT8_C(0x94) /**< 1 operand, a 1-byte size of data retrieved. */
+#define DW_OP_xderef_size UINT8_C(0x95) /**< 1 operand, a 1-byte size of data retrieved. */
+#define DW_OP_nop UINT8_C(0x96) /**< 0 operands. */
+#define DW_OP_lo_user UINT8_C(0xe0) /**< First user opcode */
+#define DW_OP_hi_user UINT8_C(0xff) /**< Last user opcode. */
+/** @} */
+
+/** @name Exception Handler Pointer Encodings (GCC/LSB).
+ * @{ */
+#define DW_EH_PE_FORMAT_MASK UINT8_C(0x0f) /**< Format mask. */
+#define DW_EH_PE_APPL_MASK UINT8_C(0x70) /**< Application mask. */
+#define DW_EH_PE_indirect UINT8_C(0x80) /**< Flag: Indirect pointer. */
+#define DW_EH_PE_omit UINT8_C(0xff) /**< Special value: Omitted. */
+#define DW_EH_PE_ptr UINT8_C(0x00) /**< Format: pointer sized, unsigned. */
+#define DW_EH_PE_uleb128 UINT8_C(0x01) /**< Format: unsigned LEB128. */
+#define DW_EH_PE_udata2 UINT8_C(0x02) /**< Format: unsigned 16-bit. */
+#define DW_EH_PE_udata4 UINT8_C(0x03) /**< Format: unsigned 32-bit. */
+#define DW_EH_PE_udata8 UINT8_C(0x04) /**< Format: unsigned 64-bit. */
+#define DW_EH_PE_sleb128 UINT8_C(0x09) /**< Format: signed LEB128. */
+#define DW_EH_PE_sdata2 UINT8_C(0x0a) /**< Format: signed 16-bit. */
+#define DW_EH_PE_sdata4 UINT8_C(0x0b) /**< Format: signed 32-bit. */
+#define DW_EH_PE_sdata8 UINT8_C(0x0c) /**< Format: signed 64-bit. */
+#define DW_EH_PE_absptr UINT8_C(0x00) /**< Application: Absolute */
+#define DW_EH_PE_pcrel UINT8_C(0x10) /**< Application: PC relative, i.e. relative pointer address. */
+#define DW_EH_PE_textrel UINT8_C(0x20) /**< Application: text section relative. */
+#define DW_EH_PE_datarel UINT8_C(0x30) /**< Application: data section relative. */
+#define DW_EH_PE_funcrel UINT8_C(0x40) /**< Application: relative to start of function. */
+#define DW_EH_PE_aligned UINT8_C(0x50) /**< Application: aligned pointer. */
+/** @} */
+
+/** @name Call frame instructions.
+ * @{ */
+/** Mask to use to identify DW_CFA_advance_loc, DW_CFA_offset and DW_CFA_restore. */
+#define DW_CFA_high_bit_mask UINT8_C(0xc0)
+
+#define DW_CFA_nop UINT8_C(0x00) /**< No operands. */
+
+#define DW_CFA_advance_loc UINT8_C(0x40) /**< low 6 bits: delta to advance. */
+#define DW_CFA_set_loc UINT8_C(0x01) /**< op1: address. */
+#define DW_CFA_advance_loc1 UINT8_C(0x02) /**< op1: 1-byte delta. */
+#define DW_CFA_advance_loc2 UINT8_C(0x03) /**< op1: 2-byte delta. */
+#define DW_CFA_advance_loc4 UINT8_C(0x04) /**< op1: 4-byte delta. */
+
+#define DW_CFA_offset UINT8_C(0x80) /**< low 6 bits: register; op1: ULEB128 offset. */
+#define DW_CFA_offset_extended UINT8_C(0x05) /**< op1: ULEB128 register; op2: ULEB128 offset. */
+#define DW_CFA_offset_extended_sf UINT8_C(0x11) /**< op1: ULEB128 register; op2: SLEB128 offset. */
+#define DW_CFA_restore UINT8_C(0xc0) /**< low 6 bits: register. */
+#define DW_CFA_restore_extended UINT8_C(0x06) /**< op1: ULEB128 register. */
+#define DW_CFA_undefined UINT8_C(0x07) /**< op1: ULEB128 register. */
+#define DW_CFA_same_value UINT8_C(0x08) /**< op1: ULEB128 register. */
+#define DW_CFA_register UINT8_C(0x09) /**< op1: ULEB128 destination register; op2: ULEB128 source register. */
+#define DW_CFA_expression UINT8_C(0x10) /**< op1: ULEB128 register; op2: BLOCK. */
+
+#define DW_CFA_val_offset UINT8_C(0x14) /**< op1: ULEB128 register; op2: ULEB128. */
+#define DW_CFA_val_offset_sf UINT8_C(0x15) /**< op1: ULEB128 register; op2: SLEB128. */
+#define DW_CFA_val_expression UINT8_C(0x16) /**< op1: ULEB128 register; op2: BLOCK. */
+
+#define DW_CFA_remember_state UINT8_C(0x0a) /**< No operands. */
+#define DW_CFA_restore_state UINT8_C(0x0b) /**< No operands. */
+
+#define DW_CFA_def_cfa UINT8_C(0x0c) /**< op1: ULEB128 register; op2: ULEB128 offset. */
+#define DW_CFA_def_cfa_register UINT8_C(0x0d) /**< op1: ULEB128 register. */
+#define DW_CFA_def_cfa_offset UINT8_C(0x0e) /**< op1: ULEB128 offset. */
+#define DW_CFA_def_cfa_expression UINT8_C(0x0f) /**< op1: BLOCK. */
+#define DW_CFA_def_cfa_sf UINT8_C(0x12) /**< op1: ULEB128 register; op2: SLEB128 offset. */
+#define DW_CFA_def_cfa_offset_sf UINT8_C(0x13) /**< op1: SLEB128 offset. */
+
+#define DW_CFA_lo_user UINT8_C(0x1c) /**< User defined operands. */
+#define DW_CFA_MIPS_advance_loc8 UINT8_C(0x1d) /**< op1: 8-byte delta? */
+#define DW_CFA_GNU_window_save UINT8_C(0x2d) /**< op1: ??; op2: ?? */
+#define DW_CFA_GNU_args_size UINT8_C(0x2e) /**< op1: ??; op2: ?? */
+#define DW_CFA_GNU_negative_offset_extended UINT8_C(0x2f) /**< op1: ??; op2: ?? */
+#define DW_CFA_hi_user UINT8_C(0x3f) /**< User defined operands. */
+/** @} */
+
+
+/** @name DWREG_X86_XXX - 386+ register number mappings.
+ * @{ */
+#define DWREG_X86_EAX 0
+#define DWREG_X86_ECX 1
+#define DWREG_X86_EDX 2
+#define DWREG_X86_EBX 3
+#define DWREG_X86_ESP 4
+#define DWREG_X86_EBP 5
+#define DWREG_X86_ESI 6
+#define DWREG_X86_EDI 7
+#define DWREG_X86_RA 8 /* return address (=EIP) */
+#define DWREG_X86_EFLAGS 9
+#define DWREG_X86_ST1 11
+#define DWREG_X86_ST2 12
+#define DWREG_X86_ST3 13
+#define DWREG_X86_ST4 14
+#define DWREG_X86_ST5 15
+#define DWREG_X86_ST6 16
+#define DWREG_X86_ST7 17
+#define DWREG_X86_XMM0 21
+#define DWREG_X86_XMM1 22
+#define DWREG_X86_XMM2 23
+#define DWREG_X86_XMM3 24
+#define DWREG_X86_XMM4 25
+#define DWREG_X86_XMM5 26
+#define DWREG_X86_XMM6 27
+#define DWREG_X86_XMM7 28
+#define DWREG_X86_MM0 29
+#define DWREG_X86_MM1 30
+#define DWREG_X86_MM2 31
+#define DWREG_X86_MM3 32
+#define DWREG_X86_MM4 33
+#define DWREG_X86_MM5 34
+#define DWREG_X86_MM6 35
+#define DWREG_X86_MM7 36
+#define DWREG_X86_MXCSR 39
+#define DWREG_X86_ES 40
+#define DWREG_X86_CS 41
+#define DWREG_X86_SS 42
+#define DWREG_X86_DS 43
+#define DWREG_X86_FS 44
+#define DWREG_X86_GS 45
+#define DWREG_X86_TR 48
+#define DWREG_X86_LDTR 49
+/** @} */
+
+
+/** @name DWREG_AMD64_XXX - AMD64 register number mappings.
+ * @note This for some braindead reason the first 8 GPR are in intel encoding
+ * order, unlike the DWREG_X86_XXX variant. Utter stupidity.
+ * @{ */
+#define DWREG_AMD64_RAX 0
+#define DWREG_AMD64_RDX 1
+#define DWREG_AMD64_RCX 2
+#define DWREG_AMD64_RBX 3
+#define DWREG_AMD64_RSI 4
+#define DWREG_AMD64_RDI 5
+#define DWREG_AMD64_RBP 6
+#define DWREG_AMD64_RSP 7
+#define DWREG_AMD64_R8 8
+#define DWREG_AMD64_R9 9
+#define DWREG_AMD64_R10 10
+#define DWREG_AMD64_R11 11
+#define DWREG_AMD64_R12 12
+#define DWREG_AMD64_R13 13
+#define DWREG_AMD64_R14 14
+#define DWREG_AMD64_R15 15
+#define DWREG_AMD64_RA 16 /* return address (=RIP) */
+#define DWREG_AMD64_XMM0 17
+#define DWREG_AMD64_XMM1 18
+#define DWREG_AMD64_XMM2 19
+#define DWREG_AMD64_XMM3 20
+#define DWREG_AMD64_XMM4 21
+#define DWREG_AMD64_XMM5 22
+#define DWREG_AMD64_XMM6 23
+#define DWREG_AMD64_XMM7 24
+#define DWREG_AMD64_XMM8 25
+#define DWREG_AMD64_XMM9 26
+#define DWREG_AMD64_XMM10 27
+#define DWREG_AMD64_XMM11 28
+#define DWREG_AMD64_XMM12 29
+#define DWREG_AMD64_XMM13 30
+#define DWREG_AMD64_XMM14 31
+#define DWREG_AMD64_XMM15 32
+#define DWREG_AMD64_ST0 33
+#define DWREG_AMD64_ST1 34
+#define DWREG_AMD64_ST2 35
+#define DWREG_AMD64_ST3 36
+#define DWREG_AMD64_ST4 37
+#define DWREG_AMD64_ST5 38
+#define DWREG_AMD64_ST6 39
+#define DWREG_AMD64_ST7 40
+#define DWREG_AMD64_MM0 41
+#define DWREG_AMD64_MM1 42
+#define DWREG_AMD64_MM2 43
+#define DWREG_AMD64_MM3 44
+#define DWREG_AMD64_MM4 45
+#define DWREG_AMD64_MM5 46
+#define DWREG_AMD64_MM6 47
+#define DWREG_AMD64_MM7 48
+#define DWREG_AMD64_RFLAGS 49
+#define DWREG_AMD64_ES 50
+#define DWREG_AMD64_CS 51
+#define DWREG_AMD64_SS 52
+#define DWREG_AMD64_DS 53
+#define DWREG_AMD64_FS 54
+#define DWREG_AMD64_GS 55
+#define DWREG_AMD64_FS_BASE 58
+#define DWREG_AMD64_GS_BASE 59
+#define DWREG_AMD64_TR 62
+#define DWREG_AMD64_LDTR 63
+#define DWREG_AMD64_MXCSR 64
+#define DWREG_AMD64_FCW 65
+#define DWREG_AMD64_FSW 66
+/** @} */
+
+#endif /* !IPRT_INCLUDED_formats_dwarf_h */
+
diff --git a/include/iprt/formats/dwarf.mac b/include/iprt/formats/dwarf.mac
new file mode 100644
index 00000000..a54b0965
--- /dev/null
+++ b/include/iprt/formats/dwarf.mac
@@ -0,0 +1,471 @@
+;; @file
+; IPRT - DWARF constants.
+;
+; Automatically generated by various.sed. DO NOT EDIT!
+;
+
+;
+; Copyright (C) 2006-2022 Oracle and/or its affiliates.
+;
+; This file is part of VirtualBox base platform packages, as
+; available from https://www.virtualbox.org.
+;
+; This program is free software; you can redistribute it and/or
+; modify it under the terms of the GNU General Public License
+; as published by the Free Software Foundation, in version 3 of the
+; License.
+;
+; This program is distributed in the hope that it will be useful, but
+; WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with this program; if not, see <https://www.gnu.org/licenses>.
+;
+; The contents of this file may alternatively be used under the terms
+; of the Common Development and Distribution License Version 1.0
+; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+; in the VirtualBox 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.
+;
+; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+;
+
+%ifndef IPRT_INCLUDED_formats_dwarf_h
+%define IPRT_INCLUDED_formats_dwarf_h
+%ifndef RT_WITHOUT_PRAGMA_ONCE
+%endif
+%define DW_LNS_extended 0x00
+%define DW_LNS_copy 0x01
+%define DW_LNS_advance_pc 0x02
+%define DW_LNS_advance_line 0x03
+%define DW_LNS_set_file 0x04
+%define DW_LNS_set_column 0x05
+%define DW_LNS_negate_stmt 0x06
+%define DW_LNS_set_basic_block 0x07
+%define DW_LNS_const_add_pc 0x08
+%define DW_LNS_fixed_advance_pc 0x09
+%define DW_LNS_set_prologue_end 0x0a
+%define DW_LNS_set_epilogue_begin 0x0b
+%define DW_LNS_set_isa 0x0c
+%define DW_LNS_what_question_mark 0x0d
+%define DW_LNE_end_sequence 1
+%define DW_LNE_set_address 2
+%define DW_LNE_define_file 3
+%define DW_LNE_set_descriminator 4
+%define DW_TAG_array_type 0x0001
+%define DW_TAG_class_type 0x0002
+%define DW_TAG_entry_point 0x0003
+%define DW_TAG_enumeration_type 0x0004
+%define DW_TAG_formal_parameter 0x0005
+%define DW_TAG_imported_declaration 0x0008
+%define DW_TAG_label 0x000a
+%define DW_TAG_lexical_block 0x000b
+%define DW_TAG_member 0x000d
+%define DW_TAG_pointer_type 0x000f
+%define DW_TAG_reference_type 0x0010
+%define DW_TAG_compile_unit 0x0011
+%define DW_TAG_string_type 0x0012
+%define DW_TAG_structure_type 0x0013
+%define DW_TAG_subroutine_type 0x0015
+%define DW_TAG_typedef 0x0016
+%define DW_TAG_union_type 0x0017
+%define DW_TAG_unspecified_parameters 0x0018
+%define DW_TAG_variant 0x0019
+%define DW_TAG_common_block 0x001a
+%define DW_TAG_common_inclusion 0x001b
+%define DW_TAG_inheritance 0x001c
+%define DW_TAG_inlined_subroutine 0x001d
+%define DW_TAG_module 0x001e
+%define DW_TAG_ptr_to_member_type 0x001f
+%define DW_TAG_set_type 0x0020
+%define DW_TAG_subrange_type 0x0021
+%define DW_TAG_with_stmt 0x0022
+%define DW_TAG_access_declaration 0x0023
+%define DW_TAG_base_type 0x0024
+%define DW_TAG_catch_block 0x0025
+%define DW_TAG_const_type 0x0026
+%define DW_TAG_constant 0x0027
+%define DW_TAG_enumerator 0x0028
+%define DW_TAG_file_type 0x0029
+%define DW_TAG_friend 0x002a
+%define DW_TAG_namelist 0x002b
+%define DW_TAG_namelist_item 0x002c
+%define DW_TAG_packed_type 0x002d
+%define DW_TAG_subprogram 0x002e
+%define DW_TAG_template_type_parameter 0x002f
+%define DW_TAG_template_value_parameter 0x0030
+%define DW_TAG_thrown_type 0x0031
+%define DW_TAG_try_block 0x0032
+%define DW_TAG_variant_part 0x0033
+%define DW_TAG_variable 0x0034
+%define DW_TAG_volatile_type 0x0035
+%define DW_TAG_dwarf_procedure 0x0036
+%define DW_TAG_restrict_type 0x0037
+%define DW_TAG_interface_type 0x0038
+%define DW_TAG_namespace 0x0039
+%define DW_TAG_imported_module 0x003a
+%define DW_TAG_unspecified_type 0x003b
+%define DW_TAG_partial_unit 0x003c
+%define DW_TAG_imported_unit 0x003d
+%define DW_TAG_condition 0x003f
+%define DW_TAG_shared_type 0x0040
+%define DW_TAG_type_unit 0x0041
+%define DW_TAG_rvalue_reference_type 0x0042
+%define DW_TAG_template_alias 0x0043
+%define DW_TAG_lo_user 0x4080
+%define DW_TAG_GNU_call_site 0x4109
+%define DW_TAG_GNU_call_site_parameter 0x410a
+%define DW_TAG_WATCOM_address_class_type 0x4100
+%define DW_TAG_WATCOM_namespace 0x4101
+%define DW_TAG_hi_user 0xffff
+%define DW_CHILDREN_yes 1
+%define DW_CHILDREN_no 0
+%define DW_AT_sibling 0x0001
+%define DW_AT_location 0x0002
+%define DW_AT_name 0x0003
+%define DW_AT_ordering 0x0009
+%define DW_AT_byte_size 0x000b
+%define DW_AT_bit_offset 0x000c
+%define DW_AT_bit_size 0x000d
+%define DW_AT_stmt_list 0x0010
+%define DW_AT_low_pc 0x0011
+%define DW_AT_high_pc 0x0012
+%define DW_AT_language 0x0013
+%define DW_AT_discr 0x0015
+%define DW_AT_discr_value 0x0016
+%define DW_AT_visibility 0x0017
+%define DW_AT_import 0x0018
+%define DW_AT_string_length 0x0019
+%define DW_AT_common_reference 0x001a
+%define DW_AT_comp_dir 0x001b
+%define DW_AT_const_value 0x001c
+%define DW_AT_containing_type 0x001d
+%define DW_AT_default_value 0x001e
+%define DW_AT_inline 0x0020
+%define DW_AT_is_optional 0x0021
+%define DW_AT_lower_bound 0x0022
+%define DW_AT_producer 0x0025
+%define DW_AT_prototyped 0x0027
+%define DW_AT_return_addr 0x002a
+%define DW_AT_start_scope 0x002c
+%define DW_AT_bit_stride 0x002e
+%define DW_AT_upper_bound 0x002f
+%define DW_AT_abstract_origin 0x0031
+%define DW_AT_accessibility 0x0032
+%define DW_AT_address_class 0x0033
+%define DW_AT_artificial 0x0034
+%define DW_AT_base_types 0x0035
+%define DW_AT_calling_convention 0x0036
+%define DW_AT_count 0x0037
+%define DW_AT_data_member_location 0x0038
+%define DW_AT_decl_column 0x0039
+%define DW_AT_decl_file 0x003a
+%define DW_AT_decl_line 0x003b
+%define DW_AT_declaration 0x003c
+%define DW_AT_discr_list 0x003d
+%define DW_AT_encoding 0x003e
+%define DW_AT_external 0x003f
+%define DW_AT_frame_base 0x0040
+%define DW_AT_friend 0x0041
+%define DW_AT_identifier_case 0x0042
+%define DW_AT_macro_info 0x0043
+%define DW_AT_namelist_item 0x0044
+%define DW_AT_priority 0x0045
+%define DW_AT_segment 0x0046
+%define DW_AT_specification 0x0047
+%define DW_AT_static_link 0x0048
+%define DW_AT_type 0x0049
+%define DW_AT_use_location 0x004a
+%define DW_AT_variable_parameter 0x004b
+%define DW_AT_virtuality 0x004c
+%define DW_AT_vtable_elem_location 0x004d
+%define DW_AT_allocated 0x004e
+%define DW_AT_associated 0x004f
+%define DW_AT_data_location 0x0050
+%define DW_AT_byte_stride 0x0051
+%define DW_AT_entry_pc 0x0052
+%define DW_AT_use_UTF8 0x0053
+%define DW_AT_extension 0x0054
+%define DW_AT_ranges 0x0055
+%define DW_AT_trampoline 0x0056
+%define DW_AT_call_column 0x0057
+%define DW_AT_call_file 0x0058
+%define DW_AT_call_line 0x0059
+%define DW_AT_description 0x005a
+%define DW_AT_binary_scale 0x005b
+%define DW_AT_decimal_scale 0x005c
+%define DW_AT_small 0x005d
+%define DW_AT_decimal_sign 0x005e
+%define DW_AT_digit_count 0x005f
+%define DW_AT_picture_string 0x0060
+%define DW_AT_mutable 0x0061
+%define DW_AT_threads_scaled 0x0062
+%define DW_AT_explicit 0x0063
+%define DW_AT_object_pointer 0x0064
+%define DW_AT_endianity 0x0065
+%define DW_AT_elemental 0x0066
+%define DW_AT_pure 0x0067
+%define DW_AT_recursive 0x0068
+%define DW_AT_signature 0x0069
+%define DW_AT_main_subprogram 0x006a
+%define DW_AT_data_bit_offset 0x006b
+%define DW_AT_const_expr 0x006c
+%define DW_AT_enum_class 0x006d
+%define DW_AT_linkage_name 0x006e
+%define DW_AT_lo_user 0x2000
+%define DW_AT_MIPS_linkage_name 0x2007
+%define DW_AT_WATCOM_memory_model 0x2082
+%define DW_AT_WATCOM_references_start 0x2083
+%define DW_AT_WATCOM_parm_entry 0x2084
+%define DW_AT_hi_user 0x3fff
+%define DW_FORM_addr 0x01
+%define DW_FORM_block2 0x03
+%define DW_FORM_block4 0x04
+%define DW_FORM_data2 0x05
+%define DW_FORM_data4 0x06
+%define DW_FORM_data8 0x07
+%define DW_FORM_string 0x08
+%define DW_FORM_block 0x09
+%define DW_FORM_block1 0x0a
+%define DW_FORM_data1 0x0b
+%define DW_FORM_flag 0x0c
+%define DW_FORM_sdata 0x0d
+%define DW_FORM_strp 0x0e
+%define DW_FORM_udata 0x0f
+%define DW_FORM_ref_addr 0x10
+%define DW_FORM_ref1 0x11
+%define DW_FORM_ref2 0x12
+%define DW_FORM_ref4 0x13
+%define DW_FORM_ref8 0x14
+%define DW_FORM_ref_udata 0x15
+%define DW_FORM_indirect 0x16
+%define DW_FORM_sec_offset 0x17
+%define DW_FORM_exprloc 0x18
+%define DW_FORM_flag_present 0x19
+%define DW_FORM_ref_sig8 0x20
+%define DW_ADDR_none 0
+%define DW_ADDR_i386_near16 1
+%define DW_ADDR_i386_far16 2
+%define DW_ADDR_i386_huge16 3
+%define DW_ADDR_i386_near32 4
+%define DW_ADDR_i386_far32 5
+%define DW_OP_addr 0x03
+%define DW_OP_deref 0x06
+%define DW_OP_const1u 0x08
+%define DW_OP_const1s 0x09
+%define DW_OP_const2u 0x0a
+%define DW_OP_const2s 0x0b
+%define DW_OP_const4u 0x0c
+%define DW_OP_const4s 0x0d
+%define DW_OP_const8u 0x0e
+%define DW_OP_const8s 0x0f
+%define DW_OP_constu 0x10
+%define DW_OP_consts 0x11
+%define DW_OP_dup 0x12
+%define DW_OP_drop 0x13
+%define DW_OP_over 0x14
+%define DW_OP_pick 0x15
+%define DW_OP_swap 0x16
+%define DW_OP_rot 0x17
+%define DW_OP_xderef 0x18
+%define DW_OP_abs 0x19
+%define DW_OP_and 0x1a
+%define DW_OP_div 0x1b
+%define DW_OP_minus 0x1c
+%define DW_OP_mod 0x1d
+%define DW_OP_mul 0x1e
+%define DW_OP_neg 0x1f
+%define DW_OP_not 0x20
+%define DW_OP_or 0x21
+%define DW_OP_plus 0x22
+%define DW_OP_plus_uconst 0x23
+%define DW_OP_shl 0x24
+%define DW_OP_shr 0x25
+%define DW_OP_shra 0x26
+%define DW_OP_xor 0x27
+%define DW_OP_skip 0x2f
+%define DW_OP_bra 0x28
+%define DW_OP_eq 0x29
+%define DW_OP_ge 0x2a
+%define DW_OP_gt 0x2b
+%define DW_OP_le 0x2c
+%define DW_OP_lt 0x2d
+%define DW_OP_ne 0x2e
+%define DW_OP_lit0 0x30
+%define DW_OP_lit31 0x4f
+%define DW_OP_reg0 0x50
+%define DW_OP_reg31 0x6f
+%define DW_OP_breg0 0x70
+%define DW_OP_breg31 0x8f
+%define DW_OP_regx 0x90
+%define DW_OP_fbreg 0x91
+%define DW_OP_bregx 0x92
+%define DW_OP_piece 0x93
+%define DW_OP_deref_size 0x94
+%define DW_OP_xderef_size 0x95
+%define DW_OP_nop 0x96
+%define DW_OP_lo_user 0xe0
+%define DW_OP_hi_user 0xff
+%define DW_EH_PE_FORMAT_MASK 0x0f
+%define DW_EH_PE_APPL_MASK 0x70
+%define DW_EH_PE_indirect 0x80
+%define DW_EH_PE_omit 0xff
+%define DW_EH_PE_ptr 0x00
+%define DW_EH_PE_uleb128 0x01
+%define DW_EH_PE_udata2 0x02
+%define DW_EH_PE_udata4 0x03
+%define DW_EH_PE_udata8 0x04
+%define DW_EH_PE_sleb128 0x09
+%define DW_EH_PE_sdata2 0x0a
+%define DW_EH_PE_sdata4 0x0b
+%define DW_EH_PE_sdata8 0x0c
+%define DW_EH_PE_absptr 0x00
+%define DW_EH_PE_pcrel 0x10
+%define DW_EH_PE_textrel 0x20
+%define DW_EH_PE_datarel 0x30
+%define DW_EH_PE_funcrel 0x40
+%define DW_EH_PE_aligned 0x50
+%define DW_CFA_high_bit_mask 0xc0
+%define DW_CFA_nop 0x00
+%define DW_CFA_advance_loc 0x40
+%define DW_CFA_set_loc 0x01
+%define DW_CFA_advance_loc1 0x02
+%define DW_CFA_advance_loc2 0x03
+%define DW_CFA_advance_loc4 0x04
+%define DW_CFA_offset 0x80
+%define DW_CFA_offset_extended 0x05
+%define DW_CFA_offset_extended_sf 0x11
+%define DW_CFA_restore 0xc0
+%define DW_CFA_restore_extended 0x06
+%define DW_CFA_undefined 0x07
+%define DW_CFA_same_value 0x08
+%define DW_CFA_register 0x09
+%define DW_CFA_expression 0x10
+%define DW_CFA_val_offset 0x14
+%define DW_CFA_val_offset_sf 0x15
+%define DW_CFA_val_expression 0x16
+%define DW_CFA_remember_state 0x0a
+%define DW_CFA_restore_state 0x0b
+%define DW_CFA_def_cfa 0x0c
+%define DW_CFA_def_cfa_register 0x0d
+%define DW_CFA_def_cfa_offset 0x0e
+%define DW_CFA_def_cfa_expression 0x0f
+%define DW_CFA_def_cfa_sf 0x12
+%define DW_CFA_def_cfa_offset_sf 0x13
+%define DW_CFA_lo_user 0x1c
+%define DW_CFA_MIPS_advance_loc8 0x1d
+%define DW_CFA_GNU_window_save 0x2d
+%define DW_CFA_GNU_args_size 0x2e
+%define DW_CFA_GNU_negative_offset_extended 0x2f
+%define DW_CFA_hi_user 0x3f
+%define DWREG_X86_EAX 0
+%define DWREG_X86_ECX 1
+%define DWREG_X86_EDX 2
+%define DWREG_X86_EBX 3
+%define DWREG_X86_ESP 4
+%define DWREG_X86_EBP 5
+%define DWREG_X86_ESI 6
+%define DWREG_X86_EDI 7
+%define DWREG_X86_RA 8
+%define DWREG_X86_EFLAGS 9
+%define DWREG_X86_ST1 11
+%define DWREG_X86_ST2 12
+%define DWREG_X86_ST3 13
+%define DWREG_X86_ST4 14
+%define DWREG_X86_ST5 15
+%define DWREG_X86_ST6 16
+%define DWREG_X86_ST7 17
+%define DWREG_X86_XMM0 21
+%define DWREG_X86_XMM1 22
+%define DWREG_X86_XMM2 23
+%define DWREG_X86_XMM3 24
+%define DWREG_X86_XMM4 25
+%define DWREG_X86_XMM5 26
+%define DWREG_X86_XMM6 27
+%define DWREG_X86_XMM7 28
+%define DWREG_X86_MM0 29
+%define DWREG_X86_MM1 30
+%define DWREG_X86_MM2 31
+%define DWREG_X86_MM3 32
+%define DWREG_X86_MM4 33
+%define DWREG_X86_MM5 34
+%define DWREG_X86_MM6 35
+%define DWREG_X86_MM7 36
+%define DWREG_X86_MXCSR 39
+%define DWREG_X86_ES 40
+%define DWREG_X86_CS 41
+%define DWREG_X86_SS 42
+%define DWREG_X86_DS 43
+%define DWREG_X86_FS 44
+%define DWREG_X86_GS 45
+%define DWREG_X86_TR 48
+%define DWREG_X86_LDTR 49
+%define DWREG_AMD64_RAX 0
+%define DWREG_AMD64_RDX 1
+%define DWREG_AMD64_RCX 2
+%define DWREG_AMD64_RBX 3
+%define DWREG_AMD64_RSI 4
+%define DWREG_AMD64_RDI 5
+%define DWREG_AMD64_RBP 6
+%define DWREG_AMD64_RSP 7
+%define DWREG_AMD64_R8 8
+%define DWREG_AMD64_R9 9
+%define DWREG_AMD64_R10 10
+%define DWREG_AMD64_R11 11
+%define DWREG_AMD64_R12 12
+%define DWREG_AMD64_R13 13
+%define DWREG_AMD64_R14 14
+%define DWREG_AMD64_R15 15
+%define DWREG_AMD64_RA 16
+%define DWREG_AMD64_XMM0 17
+%define DWREG_AMD64_XMM1 18
+%define DWREG_AMD64_XMM2 19
+%define DWREG_AMD64_XMM3 20
+%define DWREG_AMD64_XMM4 21
+%define DWREG_AMD64_XMM5 22
+%define DWREG_AMD64_XMM6 23
+%define DWREG_AMD64_XMM7 24
+%define DWREG_AMD64_XMM8 25
+%define DWREG_AMD64_XMM9 26
+%define DWREG_AMD64_XMM10 27
+%define DWREG_AMD64_XMM11 28
+%define DWREG_AMD64_XMM12 29
+%define DWREG_AMD64_XMM13 30
+%define DWREG_AMD64_XMM14 31
+%define DWREG_AMD64_XMM15 32
+%define DWREG_AMD64_ST0 33
+%define DWREG_AMD64_ST1 34
+%define DWREG_AMD64_ST2 35
+%define DWREG_AMD64_ST3 36
+%define DWREG_AMD64_ST4 37
+%define DWREG_AMD64_ST5 38
+%define DWREG_AMD64_ST6 39
+%define DWREG_AMD64_ST7 40
+%define DWREG_AMD64_MM0 41
+%define DWREG_AMD64_MM1 42
+%define DWREG_AMD64_MM2 43
+%define DWREG_AMD64_MM3 44
+%define DWREG_AMD64_MM4 45
+%define DWREG_AMD64_MM5 46
+%define DWREG_AMD64_MM6 47
+%define DWREG_AMD64_MM7 48
+%define DWREG_AMD64_RFLAGS 49
+%define DWREG_AMD64_ES 50
+%define DWREG_AMD64_CS 51
+%define DWREG_AMD64_SS 52
+%define DWREG_AMD64_DS 53
+%define DWREG_AMD64_FS 54
+%define DWREG_AMD64_GS 55
+%define DWREG_AMD64_FS_BASE 58
+%define DWREG_AMD64_GS_BASE 59
+%define DWREG_AMD64_TR 62
+%define DWREG_AMD64_LDTR 63
+%define DWREG_AMD64_MXCSR 64
+%define DWREG_AMD64_FCW 65
+%define DWREG_AMD64_FSW 66
+%endif
diff --git a/include/iprt/formats/efi-common.h b/include/iprt/formats/efi-common.h
new file mode 100644
index 00000000..eb41ac89
--- /dev/null
+++ b/include/iprt/formats/efi-common.h
@@ -0,0 +1,102 @@
+/* $Id: efi-common.h $ */
+/** @file
+ * IPRT, EFI common definitions.
+ */
+
+/*
+ * Copyright (C) 2021-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_formats_efi_common_h
+#define IPRT_INCLUDED_formats_efi_common_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+#include <iprt/assertcompile.h>
+
+/**
+ * EFI GUID.
+ */
+typedef struct EFI_GUID
+{
+ uint32_t u32Data1;
+ uint16_t u16Data2;
+ uint16_t u16Data3;
+ uint8_t abData4[8];
+} EFI_GUID;
+AssertCompileSize(EFI_GUID, 16);
+/** Pointer to an EFI GUID. */
+typedef EFI_GUID *PEFI_GUID;
+/** Pointer to a const EFI GUID. */
+typedef const EFI_GUID *PCEFI_GUID;
+
+
+/** A Null GUID. */
+#define EFI_NULL_GUID { 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }}
+/** Global variable GUID. */
+#define EFI_GLOBAL_VARIABLE_GUID \
+ { 0x8be4df61, 0x93ca, 0x11d2, { 0xaa, 0x0d, 0x00, 0xe0, 0x98, 0x03, 0x2b, 0x8c }}
+/** SecureBootEnable variable GUID. */
+#define EFI_SECURE_BOOT_ENABLE_DISABLE_GUID \
+ { 0xf0a30bc7, 0xaf08, 0x4556, { 0x99, 0xc4, 0x0, 0x10, 0x9, 0xc9, 0x3a, 0x44 } }
+
+
+/**
+ * EFI time value.
+ */
+typedef struct EFI_TIME
+{
+ uint16_t u16Year;
+ uint8_t u8Month;
+ uint8_t u8Day;
+ uint8_t u8Hour;
+ uint8_t u8Minute;
+ uint8_t u8Second;
+ uint8_t bPad0;
+ uint32_t u32Nanosecond;
+ int16_t iTimezone;
+ uint8_t u8Daylight;
+ uint8_t bPad1;
+} EFI_TIME;
+AssertCompileSize(EFI_TIME, 16);
+/** Pointer to an EFI time abstraction. */
+typedef EFI_TIME *PEFI_TIME;
+/** Pointer to a const EFI time abstraction. */
+typedef const EFI_TIME *PCEFI_TIME;
+
+#define EFI_TIME_TIMEZONE_UNSPECIFIED INT16_C(0x07ff)
+
+#define EFI_TIME_DAYLIGHT_ADJUST RT_BIT(0)
+#define EFI_TIME_DAYLIGHT_INDST RT_BIT(1)
+
+#endif /* !IPRT_INCLUDED_formats_efi_common_h */
+
diff --git a/include/iprt/formats/efi-fat.h b/include/iprt/formats/efi-fat.h
new file mode 100644
index 00000000..975fe317
--- /dev/null
+++ b/include/iprt/formats/efi-fat.h
@@ -0,0 +1,92 @@
+/* $Id: efi-fat.h $ */
+/** @file
+ * IPRT, EFI FAT Binary (used by Apple, contains multiple architectures).
+ */
+
+/*
+ * Copyright (C) 2019-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_formats_efi_fat_h
+#define IPRT_INCLUDED_formats_efi_fat_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+#include <iprt/assertcompile.h>
+
+/*
+ * Definitions come from http://refit.sourceforge.net/info/fat_binary.html
+ */
+
+/**
+ * The header structure.
+ */
+typedef struct EFI_FATHDR
+{
+ /** The magic identifying the header .*/
+ uint32_t u32Magic;
+ /** Number of files (one per architecture) embedded into the file. */
+ uint32_t cFilesEmbedded;
+} EFI_FATHDR;
+AssertCompileSize(EFI_FATHDR, 8);
+typedef EFI_FATHDR *PEFI_FATHDR;
+
+/** The magic identifying a FAT header. */
+#define EFI_FATHDR_MAGIC UINT32_C(0x0ef1fab9)
+
+/**
+ * The direcory entry.
+ */
+typedef struct EFI_FATDIRENTRY
+{
+ /** The CPU type the referenced file is for. */
+ uint32_t u32CpuType;
+ /** The CPU sub-type the referenced file is for. */
+ uint32_t u32CpuSubType;
+ /** Offset in bytes where the file is located. */
+ uint32_t u32OffsetStart;
+ /** Length of the file in bytes. */
+ uint32_t cbFile;
+ /** Alignment used for the file. */
+ uint32_t u32Alignment;
+} EFI_FATDIRENTRY;
+AssertCompileSize(EFI_FATDIRENTRY, 20);
+typedef EFI_FATDIRENTRY *PEFI_FATDIRENTRY;
+
+#define EFI_FATDIRENTRY_CPU_TYPE_X86 UINT32_C(0x7)
+#define EFI_FATDIRENTRY_CPU_TYPE_AMD64 UINT32_C(0x01000007)
+
+#define EFI_FATDIRENTRY_CPU_SUB_TYPE_GENERIC UINT32_C(0x3)
+
+
+#endif /* !IPRT_INCLUDED_formats_efi_fat_h */
+
diff --git a/include/iprt/formats/efi-fv.h b/include/iprt/formats/efi-fv.h
new file mode 100644
index 00000000..aa68189d
--- /dev/null
+++ b/include/iprt/formats/efi-fv.h
@@ -0,0 +1,131 @@
+/* $Id: efi-fv.h $ */
+/** @file
+ * IPRT, EFI firmware volume (FV) definitions.
+ */
+
+/*
+ * Copyright (C) 2021-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_formats_efi_fv_h
+#define IPRT_INCLUDED_formats_efi_fv_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+#include <iprt/assertcompile.h>
+#include <iprt/formats/efi-common.h>
+
+
+/*
+ * Definitions come from the UEFI PI Spec 1.5 Volume 3 Firmware, chapter 3 "Firmware Storage Code Definitions"
+ */
+
+/**
+ * The volume header.
+ */
+typedef struct EFI_FIRMWARE_VOLUME_HEADER
+{
+ /** Reserved data for the reset vector. */
+ uint8_t abZeroVec[16];
+ /** The filesystem GUID. */
+ EFI_GUID GuidFilesystem;
+ /** The firmware volume length in bytes including this header. */
+ uint64_t cbFv;
+ /** The signature of the firmware volume header (set to _FVH). */
+ uint32_t u32Signature;
+ /** Firmware volume attributes. */
+ uint32_t fAttr;
+ /** Size of the header in bytes. */
+ uint16_t cbFvHdr;
+ /** Checksum of the header. */
+ uint16_t u16Chksum;
+ /** Offset of the extended header (0 for no extended header). */
+ uint16_t offExtHdr;
+ /** Reserved MBZ. */
+ uint8_t bRsvd;
+ /** Revision of the header. */
+ uint8_t bRevision;
+} EFI_FIRMWARE_VOLUME_HEADER;
+AssertCompileSize(EFI_FIRMWARE_VOLUME_HEADER, 56);
+/** Pointer to a EFI firmware volume header. */
+typedef EFI_FIRMWARE_VOLUME_HEADER *PEFI_FIRMWARE_VOLUME_HEADER;
+/** Pointer to a const EFI firmware volume header. */
+typedef const EFI_FIRMWARE_VOLUME_HEADER *PCEFI_FIRMWARE_VOLUME_HEADER;
+
+/** The signature for a firmware volume header. */
+#define EFI_FIRMWARE_VOLUME_HEADER_SIGNATURE RT_MAKE_U32_FROM_U8('_', 'F', 'V', 'H')
+/** Revision of the firmware volume header. */
+#define EFI_FIRMWARE_VOLUME_HEADER_REVISION 2
+
+
+/**
+ * Firmware block map entry.
+ */
+typedef struct EFI_FW_BLOCK_MAP
+{
+ /** Number of blocks for this entry. */
+ uint32_t cBlocks;
+ /** Block size in bytes. */
+ uint32_t cbBlock;
+} EFI_FW_BLOCK_MAP;
+AssertCompileSize(EFI_FW_BLOCK_MAP, 8);
+/** Pointer to a firmware volume block map entry. */
+typedef EFI_FW_BLOCK_MAP *PEFI_FW_BLOCK_MAP;
+/** Pointer to a const firmware volume block map entry. */
+typedef const EFI_FW_BLOCK_MAP *PCEFI_FW_BLOCK_MAP;
+
+
+/**
+ * Fault tolerant working block header.
+ */
+typedef struct EFI_FTW_BLOCK_HEADER
+{
+ /** GUID identifying the FTW block header. */
+ EFI_GUID GuidSignature;
+ /** The checksum. */
+ uint32_t u32Chksum;
+ /** Flags marking the working block area as valid/invalid. */
+ uint32_t fWorkingBlockValid;
+ /** Size of the write queue. */
+ uint64_t cbWriteQueue;
+} EFI_FTW_BLOCK_HEADER;
+/** Pointer to a fault tolerant working block header. */
+typedef EFI_FTW_BLOCK_HEADER *PEFI_FTW_BLOCK_HEADER;
+/** Pointer to a const fault tolerant working block header. */
+typedef const EFI_FTW_BLOCK_HEADER *PCEFI_FTW_BLOCK_HEADER;
+
+/** The signature for the working block header. */
+#define EFI_WORKING_BLOCK_SIGNATURE_GUID \
+ { 0x9e58292b, 0x7c68, 0x497d, { 0xa0, 0xce, 0x65, 0x0, 0xfd, 0x9f, 0x1b, 0x95 }}
+
+#endif /* !IPRT_INCLUDED_formats_efi_fv_h */
+
diff --git a/include/iprt/formats/efi-signature.h b/include/iprt/formats/efi-signature.h
new file mode 100644
index 00000000..73b4e524
--- /dev/null
+++ b/include/iprt/formats/efi-signature.h
@@ -0,0 +1,138 @@
+/* $Id: efi-signature.h $ */
+/** @file
+ * IPRT, EFI signature database definitions.
+ */
+
+/*
+ * Copyright (C) 2021-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_formats_efi_signature_h
+#define IPRT_INCLUDED_formats_efi_signature_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+#include <iprt/assertcompile.h>
+#include <iprt/formats/efi-common.h>
+
+
+/*
+ * Definitions come from the UEFI 2.6 specification, chapter 30.4.1
+ */
+
+/** The GUID used for setting and retrieving variables from the variable store. */
+#define EFI_IMAGE_SECURITY_DATABASE_GUID \
+ { 0xd719b2cb, 0x3d3a, 0x4596, { 0xa3, 0xbc, 0xda, 0xd0, 0x0e, 0x67, 0x65, 0x6f }}
+
+
+/**
+ * Signature entry data.
+ */
+typedef struct EFI_SIGNATURE_DATA
+{
+ /** The GUID of the owner of the signature. */
+ EFI_GUID GuidOwner;
+ /** The signature data follows (size varies depending on the signature type). */
+} EFI_SIGNATURE_DATA;
+AssertCompileSize(EFI_SIGNATURE_DATA, 16);
+/** Pointer to a signature entry. */
+typedef EFI_SIGNATURE_DATA *PEFI_SIGNATURE_DATA;
+/** Pointer to a const signature entry. */
+typedef const EFI_SIGNATURE_DATA *PCEFI_SIGNATURE_DATA;
+
+/** Microsoft's GUID for signatures. */
+#define EFI_SIGNATURE_OWNER_GUID_MICROSOFT \
+ { 0x77fa9abd, 0x0359, 0x4d32, { 0xbd, 0x60, 0x28, 0xf4, 0xe7, 0x8f, 0x78, 0x4b }}
+
+/** VirtualBox's GUID for signatures. */
+#define EFI_SIGNATURE_OWNER_GUID_VBOX \
+ { 0x9400896a, 0x146c, 0x4f4c, { 0x96, 0x47, 0x2c, 0x73, 0x62, 0x0c, 0xa8, 0x94 }}
+
+
+/**
+ * Signature list header.
+ */
+typedef struct EFI_SIGNATURE_LIST
+{
+ /** The signature type stored in this list. */
+ EFI_GUID GuidSigType;
+ /** Size of the signature list in bytes. */
+ uint32_t cbSigLst;
+ /** Size of the optional signature header following this header in bytes. */
+ uint32_t cbSigHdr;
+ /** Size of each signature entry in bytes, must be at least the size of EFI_SIGNATURE_DATA. */
+ uint32_t cbSig;
+ // uint8_t abSigHdr[];
+ // EFI_SIGNATURE_DATA aSigs[];
+} EFI_SIGNATURE_LIST;
+AssertCompileSize(EFI_SIGNATURE_LIST, 28);
+/** Pointer to a signature list header. */
+typedef EFI_SIGNATURE_LIST *PEFI_SIGNATURE_LIST;
+/** Pointer to a const signature list header. */
+typedef const EFI_SIGNATURE_LIST *PCEFI_SIGNATURE_LIST;
+
+/** Signature contains a SHA256 hash. */
+#define EFI_SIGNATURE_TYPE_GUID_SHA256 \
+ { 0xc1c41626, 0x504c, 0x4092, { 0xac, 0xa9, 0x41, 0xf9, 0x36, 0x93, 0x43, 0x28 }}
+/** Size of a SHA256 signature entry (GUID + 32 bytes for the hash). */
+#define EFI_SIGNATURE_TYPE_SZ_SHA256 UINT32_C(48)
+
+/** Signature contains a RSA2048 key. */
+#define EFI_SIGNATURE_TYPE_GUID_RSA2048 \
+ { 0x3c5766e8, 0x269c, 0x4e34, { 0xaa, 0x14, 0xed, 0x77, 0x6e, 0x85, 0xb3, 0xb6 }}
+/** Size of a RSA2048 signature entry (GUID + 256 for the key). */
+#define EFI_SIGNATURE_TYPE_SZ_RSA2048 UINT32_C(272)
+
+/** Signature contains a RSA2048 signature of a SHA256 hash. */
+#define EFI_SIGNATURE_TYPE_GUID_RSA2048_SHA256 \
+ { 0xe2b36190, 0x879b, 0x4a3d, { 0xad, 0x8d, 0xf2, 0xe7, 0xbb, 0xa3, 0x27, 0x84 }}
+/** Size of a RSA2048 signature entry (GUID + 256 for the key). */
+#define EFI_SIGNATURE_TYPE_SZ_RSA2048_SHA256 UINT32_C(272)
+
+/** Signature contains a SHA1 hash. */
+#define EFI_SIGNATURE_TYPE_GUID_SHA1 \
+ { 0x826ca512, 0xcf10, 0x4ac9, { 0xb1, 0x87, 0xbe, 0x01, 0x49, 0x66, 0x31, 0xbd }}
+/** Size of a SHA1 signature entry (GUID + 20 bytes for the hash). */
+#define EFI_SIGNATURE_TYPE_SZ_SHA1 UINT32_C(36)
+
+/** Signature contains a RSA2048 signature of a SHA1 hash. */
+#define EFI_SIGNATURE_TYPE_GUID_RSA2048_SHA1 \
+ { 0x67f8444f, 0x8743, 0x48f1, { 0xa3, 0x28, 0x1e, 0xaa, 0xb8, 0x73, 0x60, 0x80 }}
+/** Size of a RSA2048 signature entry (GUID + 256 for the key). */
+#define EFI_SIGNATURE_TYPE_SZ_RSA2048_SHA1 UINT32_C(272)
+
+/** Signature contains a DER encoded X.509 certificate (size varies with each certificate). */
+#define EFI_SIGNATURE_TYPE_GUID_X509 \
+ { 0xa5c059a1, 0x94e4, 0x4aa7, { 0x87, 0xb5, 0xab, 0x15, 0x5c, 0x2b, 0xf0, 0x72 }}
+
+#endif /* !IPRT_INCLUDED_formats_efi_signature_h */
+
diff --git a/include/iprt/formats/efi-varstore.h b/include/iprt/formats/efi-varstore.h
new file mode 100644
index 00000000..9846ef5f
--- /dev/null
+++ b/include/iprt/formats/efi-varstore.h
@@ -0,0 +1,160 @@
+/* $Id: efi-varstore.h $ */
+/** @file
+ * IPRT, EFI variable store (VarStore) definitions.
+ */
+
+/*
+ * Copyright (C) 2021-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_formats_efi_varstore_h
+#define IPRT_INCLUDED_formats_efi_varstore_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+#include <iprt/assertcompile.h>
+#include <iprt/formats/efi-common.h>
+
+
+/*
+ * Definitions come from the EDK2 sources MdeModulePkg/Include/Guid/VariableFormat.h
+ */
+
+/** The filesystem GUID for a variable store stored in a volume header. */
+#define EFI_VARSTORE_FILESYSTEM_GUID \
+ { 0xfff12b8d, 0x7696, 0x4c8b, { 0xa9, 0x85, 0x27, 0x47, 0x07, 0x5b, 0x4f, 0x50 }}
+
+
+/**
+ * The variable store header.
+ */
+typedef struct EFI_VARSTORE_HEADER
+{
+ /** The GUID identifying a variable store. */
+ EFI_GUID GuidVarStore;
+ /** Size of the variable store including the header. */
+ uint32_t cbVarStore;
+ /** The format state. */
+ uint8_t bFmt;
+ /** The region health state. */
+ uint8_t bState;
+ /** Reserved. */
+ uint8_t abRsvd[6];
+} EFI_VARSTORE_HEADER;
+AssertCompileSize(EFI_VARSTORE_HEADER, 28);
+/** Pointer to a variable store header. */
+typedef EFI_VARSTORE_HEADER *PEFI_VARSTORE_HEADER;
+/** Pointer to a const variable store header. */
+typedef const EFI_VARSTORE_HEADER *PCEFI_VARSTORE_HEADER;
+
+/** The GUID for a variable store using the authenticated variable header format. */
+#define EFI_VARSTORE_HEADER_GUID_AUTHENTICATED_VARIABLE \
+ { 0xaaf32c78, 0x947b, 0x439a, { 0xa1, 0x80, 0x2e, 0x14, 0x4e, 0xc3, 0x77, 0x92 } }
+/** The GUID for a variable store using the standard variable header format. */
+#define EFI_VARSTORE_HEADER_GUID_VARIABLE \
+ { 0xddcf3616, 0x3275, 0x4164, { 0x98, 0xb6, 0xfe, 0x85, 0x70, 0x7f, 0xfe, 0x7d } }
+
+/** The EFI_VARSTORE_HEADER::bFmt value when the store region is formatted. */
+#define EFI_VARSTORE_HEADER_FMT_FORMATTED 0x5a
+/** The EFI_VARSTORE_HEADER::bState value when the store region is healthy. */
+#define EFI_VARSTORE_HEADER_STATE_HEALTHY 0xfe
+
+
+/**
+ * Authenticated variable header.
+ */
+#pragma pack(1)
+typedef struct EFI_AUTH_VAR_HEADER
+{
+ /** Contains EFI_AUTH_VAR_HEADER_START to identify the start of a new variable header. */
+ uint16_t u16StartId;
+ /** Variable state. */
+ uint8_t bState;
+ /** Reserved. */
+ uint8_t bRsvd;
+ /** Variable attributes. */
+ uint32_t fAttr;
+ /** Monotonic counter value increased with each change to protect against replay attacks. */
+ uint64_t cMonotonic;
+ /** Timestamp value to protect against replay attacks. */
+ EFI_TIME Timestamp;
+ /** Index of associated public key in database. */
+ uint32_t idPubKey;
+ /** Size of the variable zero terminated unicode name in bytes. */
+ uint32_t cbName;
+ /** Size of the variable data without this header. */
+ uint32_t cbData;
+ /** Producer/Consumer GUID for this variable. */
+ EFI_GUID GuidVendor;
+} EFI_AUTH_VAR_HEADER;
+#pragma pack()
+AssertCompileSize(EFI_AUTH_VAR_HEADER, 60);
+/** Pointer to a authenticated variable header. */
+typedef EFI_AUTH_VAR_HEADER *PEFI_AUTH_VAR_HEADER;
+/** Pointer to a const authenticated variable header. */
+typedef const EFI_AUTH_VAR_HEADER *PCEFI_AUTH_VAR_HEADER;
+
+/** Value in EFI_AUTH_VAR_HEADER::u16StartId for a valid variable header. */
+#define EFI_AUTH_VAR_HEADER_START 0x55aa
+/** @name Possible variable states.
+ * @{ */
+/** Variable is in the process of being deleted. */
+#define EFI_AUTH_VAR_HEADER_STATE_IN_DELETED_TRANSITION 0xfe
+/** Variable was deleted. */
+#define EFI_AUTH_VAR_HEADER_STATE_DELETED 0xfd
+/** Variable has only a valid header right now. */
+#define EFI_AUTH_VAR_HEADER_STATE_HDR_VALID_ONLY 0x7f
+/** Variable header, name and data are all valid. */
+#define EFI_AUTH_VAR_HEADER_STATE_ADDED 0x3f
+/** @} */
+
+
+/** @name Possible variable attributes.
+ * @{ */
+/** The variable is stored in non volatile memory. */
+#define EFI_VAR_HEADER_ATTR_NON_VOLATILE RT_BIT_32(0)
+/** The variable is accessible by the EFI bootservice stage. */
+#define EFI_VAR_HEADER_ATTR_BOOTSERVICE_ACCESS RT_BIT_32(1)
+/** The variable is accessible during runtime. */
+#define EFI_VAR_HEADER_ATTR_RUNTIME_ACCESS RT_BIT_32(2)
+/** The variable contains an hardware error record. */
+#define EFI_VAR_HEADER_ATTR_HW_ERROR_RECORD RT_BIT_32(3)
+/** The variable can be modified only by an authenticated source. */
+#define EFI_AUTH_VAR_HEADER_ATTR_AUTH_WRITE_ACCESS RT_BIT_32(4)
+/** The variable was written with a time based authentication. */
+#define EFI_AUTH_VAR_HEADER_ATTR_TIME_BASED_AUTH_WRITE_ACCESS RT_BIT_32(5)
+/** The variable can be appended. */
+#define EFI_AUTH_VAR_HEADER_ATTR_APPEND_WRITE RT_BIT_32(6)
+/** @} */
+
+#endif /* !IPRT_INCLUDED_formats_efi_varstore_h */
+
diff --git a/include/iprt/formats/elf-amd64.h b/include/iprt/formats/elf-amd64.h
new file mode 100644
index 00000000..c0c7f0c1
--- /dev/null
+++ b/include/iprt/formats/elf-amd64.h
@@ -0,0 +1,131 @@
+/*-
+ * Copyright (c) 1996-1997 John D. Polstra.
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ */
+
+#ifndef IPRT_INCLUDED_formats_elf_amd64_h
+#define IPRT_INCLUDED_formats_elf_amd64_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+/*
+ * ELF definitions for the AMD64 architecture.
+ */
+
+#if 0 /* later */
+/*
+ * Auxiliary vector entries for passing information to the interpreter.
+ *
+ * The i386 supplement to the SVR4 ABI specification names this "auxv_t",
+ * but POSIX lays claim to all symbols ending with "_t".
+ */
+typedef struct { /* Auxiliary vector entry on initial stack */
+ int a_type; /* Entry type. */
+ union {
+ int a_val; /* Integer value. */
+ } a_un;
+} Elf32_Auxinfo;
+
+
+typedef struct { /* Auxiliary vector entry on initial stack */
+ long a_type; /* Entry type. */
+ union {
+ long a_val; /* Integer value. */
+ void *a_ptr; /* Address. */
+ void (*a_fcn)(void); /* Function pointer (not used). */
+ } a_un;
+} Elf64_Auxinfo;
+
+__ElfType(Auxinfo);
+
+/* Values for a_type. */
+#define AT_NULL 0 /* Terminates the vector. */
+#define AT_IGNORE 1 /* Ignored entry. */
+#define AT_EXECFD 2 /* File descriptor of program to load. */
+#define AT_PHDR 3 /* Program header of program already loaded. */
+#define AT_PHENT 4 /* Size of each program header entry. */
+#define AT_PHNUM 5 /* Number of program header entries. */
+#define AT_PAGESZ 6 /* Page size in bytes. */
+#define AT_BASE 7 /* Interpreter's base address. */
+#define AT_FLAGS 8 /* Flags (unused for i386). */
+#define AT_ENTRY 9 /* Where interpreter should transfer control. */
+
+/*
+ * The following non-standard values are used for passing information
+ * from John Polstra's testbed program to the dynamic linker. These
+ * are expected to go away soon.
+ *
+ * Unfortunately, these overlap the Linux non-standard values, so they
+ * must not be used in the same context.
+ */
+#define AT_BRK 10 /* Starting point for sbrk and brk. */
+#define AT_DEBUG 11 /* Debugging level. */
+
+/*
+ * The following non-standard values are used in Linux ELF binaries.
+ */
+#define AT_NOTELF 10 /* Program is not ELF ?? */
+#define AT_UID 11 /* Real uid. */
+#define AT_EUID 12 /* Effective uid. */
+#define AT_GID 13 /* Real gid. */
+#define AT_EGID 14 /* Effective gid. */
+
+#define AT_COUNT 15 /* Count of defined aux entry types. */
+
+#endif /* later */
+
+/*
+ * Relocation types.
+ */
+
+#define R_X86_64_NONE 0 /* No relocation. */
+#define R_X86_64_64 1 /* Add 64 bit symbol value. */
+#define R_X86_64_PC32 2 /* PC-relative 32 bit signed sym value. */
+#define R_X86_64_GOT32 3 /* PC-relative 32 bit GOT offset. */
+#define R_X86_64_PLT32 4 /* PC-relative 32 bit PLT offset. */
+#define R_X86_64_COPY 5 /* Copy data from shared object. */
+#define R_X86_64_GLOB_DAT 6 /* Set GOT entry to data address. */
+#define R_X86_64_JMP_SLOT 7 /* Set GOT entry to code address. */
+#define R_X86_64_RELATIVE 8 /* Add load address of shared object. */
+#define R_X86_64_GOTPCREL 9 /* Add 32 bit signed pcrel offset to GOT. */
+#define R_X86_64_32 10 /* Add 32 bit zero extended symbol value */
+#define R_X86_64_32S 11 /* Add 32 bit sign extended symbol value */
+#define R_X86_64_16 12 /* Add 16 bit zero extended symbol value */
+#define R_X86_64_PC16 13 /* Add 16 bit signed extended pc relative symbol value */
+#define R_X86_64_8 14 /* Add 8 bit zero extended symbol value */
+#define R_X86_64_PC8 15 /* Add 8 bit signed extended pc relative symbol value */
+#define R_X86_64_DTPMOD64 16 /* ID of module containing symbol */
+#define R_X86_64_DTPOFF64 17 /* Offset in TLS block */
+#define R_X86_64_TPOFF64 18 /* Offset in static TLS block */
+#define R_X86_64_TLSGD 19 /* PC relative offset to GD GOT entry */
+#define R_X86_64_TLSLD 20 /* PC relative offset to LD GOT entry */
+#define R_X86_64_DTPOFF32 21 /* Offset in TLS block */
+#define R_X86_64_GOTTPOFF 22 /* PC relative offset to IE GOT entry */
+#define R_X86_64_TPOFF32 23 /* Offset in static TLS block */
+
+#define R_X86_64_COUNT 24 /* Count of defined relocation types. */
+
+#endif /* !IPRT_INCLUDED_formats_elf_amd64_h */
+
diff --git a/include/iprt/formats/elf-common.h b/include/iprt/formats/elf-common.h
new file mode 100644
index 00000000..992ebaed
--- /dev/null
+++ b/include/iprt/formats/elf-common.h
@@ -0,0 +1,348 @@
+/*-
+ * Copyright (c) 1998 John D. Polstra.
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ */
+
+#ifndef IPRT_INCLUDED_formats_elf_common_h
+#define IPRT_INCLUDED_formats_elf_common_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/stdint.h>
+
+/*
+ * ELF definitions that are independent of architecture or word size.
+ */
+
+/*
+ * Note header. The ".note" section contains an array of notes. Each
+ * begins with this header, aligned to a word boundary. Immediately
+ * following the note header is n_namesz bytes of name, padded to the
+ * next word boundary. Then comes n_descsz bytes of descriptor, again
+ * padded to a word boundary. The values of n_namesz and n_descsz do
+ * not include the padding.
+ */
+
+typedef struct {
+ uint32_t n_namesz; /* Length of name. */
+ uint32_t n_descsz; /* Length of descriptor. */
+ uint32_t n_type; /* Type of this note. */
+} Elf_Note;
+
+/* Indexes into the e_ident array. Keep synced with
+ http://www.sco.com/developer/gabi/ch4.eheader.html */
+#define EI_MAG0 0 /* Magic number, byte 0. */
+#define EI_MAG1 1 /* Magic number, byte 1. */
+#define EI_MAG2 2 /* Magic number, byte 2. */
+#define EI_MAG3 3 /* Magic number, byte 3. */
+#define EI_CLASS 4 /* Class of machine. */
+#define EI_DATA 5 /* Data format. */
+#define EI_VERSION 6 /* ELF format version. */
+#define EI_OSABI 7 /* Operating system / ABI identification */
+#define EI_ABIVERSION 8 /* ABI version */
+#define OLD_EI_BRAND 8 /* Start of architecture identification. */
+#define EI_PAD 9 /* Start of padding (per SVR4 ABI). */
+#define EI_NIDENT 16 /* Size of e_ident array. */
+
+/* Values for the magic number bytes. */
+#define ELFMAG0 0x7f
+#define ELFMAG1 'E'
+#define ELFMAG2 'L'
+#define ELFMAG3 'F'
+#define ELFMAG "\177ELF" /* magic string */
+#define SELFMAG 4 /* magic string size */
+
+/* Values for e_ident[EI_VERSION] and e_version. */
+#define EV_NONE 0
+#define EV_CURRENT 1
+
+/* Values for e_ident[EI_CLASS]. */
+#define ELFCLASSNONE 0 /* Unknown class. */
+#define ELFCLASS32 1 /* 32-bit architecture. */
+#define ELFCLASS64 2 /* 64-bit architecture. */
+
+/* Values for e_ident[EI_DATA]. */
+#define ELFDATANONE 0 /* Unknown data format. */
+#define ELFDATA2LSB 1 /* 2's complement little-endian. */
+#define ELFDATA2MSB 2 /* 2's complement big-endian. */
+
+/* Values for e_ident[EI_OSABI]. */
+#define ELFOSABI_SYSV 0 /* UNIX System V ABI */
+#define ELFOSABI_NONE ELFOSABI_SYSV /* symbol used in old spec */
+#define ELFOSABI_HPUX 1 /* HP-UX operating system */
+#define ELFOSABI_NETBSD 2 /* NetBSD */
+#define ELFOSABI_LINUX 3 /* GNU/Linux */
+#define ELFOSABI_HURD 4 /* GNU/Hurd */
+#define ELFOSABI_86OPEN 5 /* 86Open common IA32 ABI */
+#define ELFOSABI_SOLARIS 6 /* Solaris */
+#define ELFOSABI_MONTEREY 7 /* Monterey */
+#define ELFOSABI_IRIX 8 /* IRIX */
+#define ELFOSABI_FREEBSD 9 /* FreeBSD */
+#define ELFOSABI_TRU64 10 /* TRU64 UNIX */
+#define ELFOSABI_MODESTO 11 /* Novell Modesto */
+#define ELFOSABI_OPENBSD 12 /* OpenBSD */
+#define ELFOSABI_ARM 97 /* ARM */
+#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */
+
+/* e_ident */
+#define IS_ELF(ehdr) ((ehdr).e_ident[EI_MAG0] == ELFMAG0 && \
+ (ehdr).e_ident[EI_MAG1] == ELFMAG1 && \
+ (ehdr).e_ident[EI_MAG2] == ELFMAG2 && \
+ (ehdr).e_ident[EI_MAG3] == ELFMAG3)
+
+/* Values for e_type. */
+#define ET_NONE 0 /* Unknown type. */
+#define ET_REL 1 /* Relocatable. */
+#define ET_EXEC 2 /* Executable. */
+#define ET_DYN 3 /* Shared object. */
+#define ET_CORE 4 /* Core file. */
+
+/* Values for e_machine. */
+#define EM_NONE 0 /* Unknown machine. */
+#define EM_M32 1 /* AT&T WE32100. */
+#define EM_SPARC 2 /* Sun SPARC. */
+#define EM_386 3 /* Intel i386. */
+#define EM_68K 4 /* Motorola 68000. */
+#define EM_88K 5 /* Motorola 88000. */
+#define EM_486 6 /* Intel i486. */
+#define EM_860 7 /* Intel i860. */
+#define EM_MIPS 8 /* MIPS R3000 Big-Endian only */
+
+/* Extensions. This list is not complete. */
+#define EM_S370 9 /* IBM System/370 */
+#define EM_MIPS_RS4_BE 10 /* MIPS R4000 Big-Endian */ /* Depreciated */
+#define EM_PARISC 15 /* HPPA */
+#define EM_SPARC32PLUS 18 /* SPARC v8plus */
+#define EM_PPC 20 /* PowerPC 32-bit */
+#define EM_PPC64 21 /* PowerPC 64-bit */
+#define EM_ARM 40 /* ARM */
+#define EM_SPARCV9 43 /* SPARC v9 64-bit */
+#define EM_IA_64 50 /* Intel IA-64 Processor */
+#define EM_X86_64 62 /* Advanced Micro Devices x86-64 */
+#define EM_AMD64 EM_X86_64 /* SunOS compatibility (added by Ramshankar) */
+#define EM_ALPHA 0x9026 /* Alpha (written in the absence of an ABI */
+
+/* Special section indexes. */
+#define SHN_UNDEF 0 /* Undefined, missing, irrelevant. */
+#define SHN_LORESERVE 0xff00 /* First of reserved range. */
+#define SHN_LOPROC 0xff00 /* First processor-specific. */
+#define SHN_HIPROC 0xff1f /* Last processor-specific. */
+#define SHN_ABS 0xfff1 /* Absolute values. */
+#define SHN_COMMON 0xfff2 /* Common data. */
+#define SHN_HIRESERVE 0xffff /* Last of reserved range. */
+
+/* sh_type */
+#define SHT_NULL 0 /* inactive */
+#define SHT_PROGBITS 1 /* program defined information */
+#define SHT_SYMTAB 2 /* symbol table section */
+#define SHT_STRTAB 3 /* string table section */
+#define SHT_RELA 4 /* relocation section with addends */
+#define SHT_HASH 5 /* symbol hash table section */
+#define SHT_DYNAMIC 6 /* dynamic section */
+#define SHT_NOTE 7 /* note section */
+#define SHT_NOBITS 8 /* no space section */
+#define SHT_REL 9 /* relocation section - no addends */
+#define SHT_SHLIB 10 /* reserved - purpose unknown */
+#define SHT_DYNSYM 11 /* dynamic symbol table section */
+#define SHT_NUM 12 /* number of section types */
+#define SHT_LOOS 0x60000000 /* First of OS specific semantics */
+#define SHT_HIOS 0x6fffffff /* Last of OS specific semantics */
+#define SHT_LOPROC 0x70000000 /* reserved range for processor */
+#define SHT_HIPROC 0x7fffffff /* specific section header types */
+#define SHT_LOUSER 0x80000000 /* reserved range for application */
+#define SHT_HIUSER 0xffffffff /* specific indexes */
+
+/* Flags for sh_flags. */
+#define SHF_WRITE 0x1 /* Section contains writable data. */
+#define SHF_ALLOC 0x2 /* Section occupies memory. */
+#define SHF_EXECINSTR 0x4 /* Section contains instructions. */
+#define SHF_TLS 0x400 /* Section contains TLS data. */
+#define SHF_MASKPROC 0xf0000000 /* Reserved for processor-specific. */
+
+/* Values for p_type. */
+#define PT_NULL 0 /* Unused entry. */
+#define PT_LOAD 1 /* Loadable segment. */
+#define PT_DYNAMIC 2 /* Dynamic linking information segment. */
+#define PT_INTERP 3 /* Pathname of interpreter. */
+#define PT_NOTE 4 /* Auxiliary information. */
+#define PT_SHLIB 5 /* Reserved (not used). */
+#define PT_PHDR 6 /* Location of program header itself. */
+#define PT_TLS 7 /* Thread local storage segment */
+
+#define PT_COUNT 8 /* Number of defined p_type values. */
+
+#define PT_LOOS 0x60000000 /* OS-specific */
+#define PT_HIOS 0x6fffffff /* OS-specific */
+#define PT_LOPROC 0x70000000 /* First processor-specific type. */
+#define PT_HIPROC 0x7fffffff /* Last processor-specific type. */
+
+#define PT_GNU_EH_FRAME 0x6474e550 /**< GNU/Linux -> .eh_frame_hdr */
+#define PT_GNU_STACK 0x6474e551 /**< GNU/Linux -> stack prot (RWX or RW) */
+#define PT_GNU_RELRO 0x6474e552 /**< GNU/Linux -> make RO after relocations */
+#define PT_GNU_PROPERTY 0x6474e553 /**< GNU/Linux -> .note.gnu.property */
+
+
+/* Values for p_flags. */
+#define PF_X 0x1 /* Executable. */
+#define PF_W 0x2 /* Writable. */
+#define PF_R 0x4 /* Readable. */
+
+/* Values for d_tag. */
+#define DT_NULL 0 /* Terminating entry. */
+#define DT_NEEDED 1 /* String table offset of a needed shared
+ library. */
+#define DT_PLTRELSZ 2 /* Total size in bytes of PLT relocations. */
+#define DT_PLTGOT 3 /* Processor-dependent address. */
+#define DT_HASH 4 /* Address of symbol hash table. */
+#define DT_STRTAB 5 /* Address of string table. */
+#define DT_SYMTAB 6 /* Address of symbol table. */
+#define DT_RELA 7 /* Address of ElfNN_Rela relocations. */
+#define DT_RELASZ 8 /* Total size of ElfNN_Rela relocations. */
+#define DT_RELAENT 9 /* Size of each ElfNN_Rela relocation entry. */
+#define DT_STRSZ 10 /* Size of string table. */
+#define DT_SYMENT 11 /* Size of each symbol table entry. */
+#define DT_INIT 12 /* Address of initialization function. */
+#define DT_FINI 13 /* Address of finalization function. */
+#define DT_SONAME 14 /* String table offset of shared object
+ name. */
+#define DT_RPATH 15 /* String table offset of library path. [sup] */
+#define DT_SYMBOLIC 16 /* Indicates "symbolic" linking. [sup] */
+#define DT_REL 17 /* Address of ElfNN_Rel relocations. */
+#define DT_RELSZ 18 /* Total size of ElfNN_Rel relocations. */
+#define DT_RELENT 19 /* Size of each ElfNN_Rel relocation. */
+#define DT_PLTREL 20 /* Type of relocation used for PLT. */
+#define DT_DEBUG 21 /* Reserved (not used). */
+#define DT_TEXTREL 22 /* Indicates there may be relocations in
+ non-writable segments. [sup] */
+#define DT_JMPREL 23 /* Address of PLT relocations. */
+#define DT_BIND_NOW 24 /* [sup] */
+#define DT_INIT_ARRAY 25 /* Address of the array of pointers to
+ initialization functions */
+#define DT_FINI_ARRAY 26 /* Address of the array of pointers to
+ termination functions */
+#define DT_INIT_ARRAYSZ 27 /* Size in bytes of the array of
+ initialization functions. */
+#define DT_FINI_ARRAYSZ 28 /* Size in bytes of the array of
+ terminationfunctions. */
+#define DT_RUNPATH 29 /* String table offset of a null-terminated
+ library search path string. */
+#define DT_FLAGS 30 /* Object specific flag values. */
+#define DT_ENCODING 32 /* Values greater than or equal to DT_ENCODING
+ and less than DT_LOOS follow the rules for
+ the interpretation of the d_un union
+ as follows: even == 'd_ptr', even == 'd_val'
+ or none */
+#define DT_PREINIT_ARRAY 32 /* Address of the array of pointers to
+ pre-initialization functions. */
+#define DT_PREINIT_ARRAYSZ 33 /* Size in bytes of the array of
+ pre-initialization functions. */
+
+#define DT_COUNT 33 /* Number of defined d_tag values. */
+
+#define DT_LOOS 0x6000000d /* First OS-specific */
+#define DT_HIOS 0x6fff0000 /* Last OS-specific */
+#define DT_LOPROC 0x70000000 /* First processor-specific type. */
+#define DT_HIPROC 0x7fffffff /* Last processor-specific type. */
+
+/* Values for DT_FLAGS */
+#define DF_ORIGIN 0x0001 /* Indicates that the object being loaded may
+ make reference to the $ORIGIN substitution
+ string */
+#define DF_SYMBOLIC 0x0002 /* Indicates "symbolic" linking. */
+#define DF_TEXTREL 0x0004 /* Indicates there may be relocations in
+ non-writable segments. */
+#define DF_BIND_NOW 0x0008 /* Indicates that the dynamic linker should
+ process all relocations for the object
+ containing this entry before transferring
+ control to the program. */
+#define DF_STATIC_TLS 0x0010 /* Indicates that the shared object or
+ executable contains code using a static
+ thread-local storage scheme. */
+
+/* Values for n_type. Used in core files. */
+#if defined(RT_OS_FREEBSD)
+# define NT_PRSTATUS 1 /* Process status. */
+# define NT_FPREGSET 2 /* Floating point registers. */
+# define NT_PRPSINFO 3 /* Process state info. */
+#elif defined(RT_OS_SOLARIS)
+# define NT_PRSTATUS 1 /* prstatus_t <sys/old_procfs.h> */
+# define NT_PRFPREG 2 /* prfpregset_t <sys/old_procfs.h> */
+# define NT_PRPSINFO 3 /* prpsinfo_t <sys/old_procfs.h> */
+# define NT_PRXREG 4 /* prxregset_t <sys/procfs.h> */
+# define NT_PLATFORM 5 /* string from sysinfo(SI_PLATFORM) */
+# define NT_AUXV 6 /* auxv_t array <sys/auxv.h> */
+# define NT_LDT 9 /* ssd array <sys/sysi86.h> IA32 only */
+# define NT_PSTATUS 10 /* pstatus_t <sys/procfs.h> */
+# define NT_PSINFO 13 /* psinfo_t <sys/procfs.h> */
+# define NT_PRCRED 14 /* prcred_t <sys/procfs.h> */
+# define NT_UTSNAME 15 /* struct utsname <sys/utsname.h> */
+# define NT_LWPSTATUS 16 /* lwpstatus_t <sys/procfs.h> */
+# define NT_LWPSINFO 17 /* lwpsinfo_t <sys/procfs.h> */
+# define NT_PRPRIV 18 /* prpriv_t <sys/procfs.h> */
+# define NT_PRPRIVINFO 19 /* priv_impl_info_t <sys/priv.h> */
+# define NT_CONTENT 20 /* core_content_t <sys/corectl.h> */
+# define NT_ZONENAME 21 /* string from getzonenamebyid(3C) */
+# define PF_SUNW_FAILURE 0x00100000 /* mapping absent due to failure */
+# define PN_XNUM 0xffff /* extended program header index */
+#elif defined(RT_OS_LINUX)
+# define NT_PRSTATUS 1 /* Process status. */
+# define NT_PRFPREG 2 /* Floating point registers. */
+# define NT_PRPSINFO 3 /* Process state info. */
+# define NT_TASKSTRUCT 4 /* Task info. */
+# define NT_AUXV 6 /* Process auxiliary vectors. */
+# define NT_PRXFPREG 0x46e62b7f /* from gdb5.1/include/elf/common.h */
+#endif
+/* GNU Build ID in a dedicated section. */
+#define NT_GNU_BUILD_ID 3
+
+/* VirtualBox specific NOTE sections (added by Ramshankar) */
+#ifdef VBOX
+# define NT_VBOXCORE 0xb00
+# define NT_VBOXCPU 0xb01
+#endif
+
+/* Symbol Binding - ELFNN_ST_BIND - st_info */
+#define STB_LOCAL 0 /* Local symbol */
+#define STB_GLOBAL 1 /* Global symbol */
+#define STB_WEAK 2 /* like global - lower precedence */
+#define STB_LOPROC 13 /* reserved range for processor */
+#define STB_HIPROC 15 /* specific symbol bindings */
+
+/* Symbol type - ELFNN_ST_TYPE - st_info */
+#define STT_NOTYPE 0 /* Unspecified type. */
+#define STT_OBJECT 1 /* Data object. */
+#define STT_FUNC 2 /* Function. */
+#define STT_SECTION 3 /* Section. */
+#define STT_FILE 4 /* Source file. */
+#define STT_TLS 6 /* TLS object. */
+#define STT_NUM 7 /* Number of generic symbol types. */
+#define STT_LOPROC 13 /* reserved range for processor */
+#define STT_HIPROC 15 /* specific symbol types */
+
+/* Special symbol table indexes. */
+#define STN_UNDEF 0 /* Undefined symbol index. */
+
+#endif /* !IPRT_INCLUDED_formats_elf_common_h */
+
diff --git a/include/iprt/formats/elf-i386.h b/include/iprt/formats/elf-i386.h
new file mode 100644
index 00000000..4ebaafc6
--- /dev/null
+++ b/include/iprt/formats/elf-i386.h
@@ -0,0 +1,134 @@
+/*-
+ * Copyright (c) 1996-1997 John D. Polstra.
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ */
+
+#ifndef IPRT_INCLUDED_formats_elf_i386_h
+#define IPRT_INCLUDED_formats_elf_i386_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#if 0 /* later */
+
+/*
+ * Auxiliary vector entries for passing information to the interpreter.
+ *
+ * The i386 supplement to the SVR4 ABI specification names this "auxv_t",
+ * but POSIX lays claim to all symbols ending with "_t".
+ */
+
+typedef struct { /* Auxiliary vector entry on initial stack */
+ int a_type; /* Entry type. */
+ union {
+ long a_val; /* Integer value. */
+ void *a_ptr; /* Address. */
+ void (*a_fcn)(void); /* Function pointer (not used). */
+ } a_un;
+} Elf32_Auxinfo;
+
+#if __ELF_WORD_SIZE == 64
+/* Fake for amd64 loader support */
+typedef struct {
+ int fake;
+} Elf64_Auxinfo;
+#endif
+
+/* Values for a_type. */
+#define AT_NULL 0 /* Terminates the vector. */
+#define AT_IGNORE 1 /* Ignored entry. */
+#define AT_EXECFD 2 /* File descriptor of program to load. */
+#define AT_PHDR 3 /* Program header of program already loaded. */
+#define AT_PHENT 4 /* Size of each program header entry. */
+#define AT_PHNUM 5 /* Number of program header entries. */
+#define AT_PAGESZ 6 /* Page size in bytes. */
+#define AT_BASE 7 /* Interpreter's base address. */
+#define AT_FLAGS 8 /* Flags (unused for i386). */
+#define AT_ENTRY 9 /* Where interpreter should transfer control. */
+
+/*
+ * The following non-standard values are used for passing information
+ * from John Polstra's testbed program to the dynamic linker. These
+ * are expected to go away soon.
+ *
+ * Unfortunately, these overlap the Linux non-standard values, so they
+ * must not be used in the same context.
+ */
+#define AT_BRK 10 /* Starting point for sbrk and brk. */
+#define AT_DEBUG 11 /* Debugging level. */
+
+/*
+ * The following non-standard values are used in Linux ELF binaries.
+ */
+#define AT_NOTELF 10 /* Program is not ELF ?? */
+#define AT_UID 11 /* Real uid. */
+#define AT_EUID 12 /* Effective uid. */
+#define AT_GID 13 /* Real gid. */
+#define AT_EGID 14 /* Effective gid. */
+
+#define AT_COUNT 15 /* Count of defined aux entry types. */
+
+#endif /* later */
+
+
+/*
+ * Relocation types.
+ */
+
+#define R_386_NONE 0 /* No relocation. */
+#define R_386_32 1 /* Add symbol value. */
+#define R_386_PC32 2 /* Add PC-relative symbol value. */
+#define R_386_GOT32 3 /* Add PC-relative GOT offset. */
+#define R_386_PLT32 4 /* Add PC-relative PLT offset. */
+#define R_386_COPY 5 /* Copy data from shared object. */
+#define R_386_GLOB_DAT 6 /* Set GOT entry to data address. */
+#define R_386_JMP_SLOT 7 /* Set GOT entry to code address. */
+#define R_386_RELATIVE 8 /* Add load address of shared object. */
+#define R_386_GOTOFF 9 /* Add GOT-relative symbol address. */
+#define R_386_GOTPC 10 /* Add PC-relative GOT table address. */
+#define R_386_TLS_TPOFF 14 /* Negative offset in static TLS block */
+#define R_386_TLS_IE 15 /* Absolute address of GOT for -ve static TLS */
+#define R_386_TLS_GOTIE 16 /* GOT entry for negative static TLS block */
+#define R_386_TLS_LE 17 /* Negative offset relative to static TLS */
+#define R_386_TLS_GD 18 /* 32 bit offset to GOT (index,off) pair */
+#define R_386_TLS_LDM 19 /* 32 bit offset to GOT (index,zero) pair */
+#define R_386_TLS_GD_32 24 /* 32 bit offset to GOT (index,off) pair */
+#define R_386_TLS_GD_PUSH 25 /* pushl instruction for Sun ABI GD sequence */
+#define R_386_TLS_GD_CALL 26 /* call instruction for Sun ABI GD sequence */
+#define R_386_TLS_GD_POP 27 /* popl instruction for Sun ABI GD sequence */
+#define R_386_TLS_LDM_32 28 /* 32 bit offset to GOT (index,zero) pair */
+#define R_386_TLS_LDM_PUSH 29 /* pushl instruction for Sun ABI LD sequence */
+#define R_386_TLS_LDM_CALL 30 /* call instruction for Sun ABI LD sequence */
+#define R_386_TLS_LDM_POP 31 /* popl instruction for Sun ABI LD sequence */
+#define R_386_TLS_LDO_32 32 /* 32 bit offset from start of TLS block */
+#define R_386_TLS_IE_32 33 /* 32 bit offset to GOT static TLS offset entry */
+#define R_386_TLS_LE_32 34 /* 32 bit offset within static TLS block */
+#define R_386_TLS_DTPMOD32 35 /* GOT entry containing TLS index */
+#define R_386_TLS_DTPOFF32 36 /* GOT entry containing TLS offset */
+#define R_386_TLS_TPOFF32 37 /* GOT entry of -ve static TLS offset */
+
+#define R_386_COUNT 38 /* Count of defined relocation types. */
+
+#endif /* !IPRT_INCLUDED_formats_elf_i386_h */
+
diff --git a/include/iprt/formats/elf.h b/include/iprt/formats/elf.h
new file mode 100644
index 00000000..e7daab46
--- /dev/null
+++ b/include/iprt/formats/elf.h
@@ -0,0 +1,98 @@
+/* $Id: elf.h $ */
+/** @file
+ * ELF types, current architecture.
+ */
+
+/*
+ * Copyright (C) 2010-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_formats_elf_h
+#define IPRT_INCLUDED_formats_elf_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_ARM64)
+# include "elf64.h"
+typedef Elf64_Addr Elf_Addr;
+typedef Elf64_Half Elf_Half;
+typedef Elf64_Off Elf_Off;
+typedef Elf64_Sword Elf_Sword;
+typedef Elf64_Word Elf_Word;
+typedef Elf64_Size Elf_Size;
+typedef Elf64_Hashelt Elf_Hashelt;
+typedef Elf64_Ehdr Elf_Ehdr;
+typedef Elf64_Shdr Elf_Shdr;
+typedef Elf64_Phdr Elf_Phdr;
+typedef Elf64_Nhdr Elf_Nhdr;
+typedef Elf64_Dyn Elf_Dyn;
+typedef Elf64_Rel Elf_Rel;
+typedef Elf64_Rela Elf_Rela;
+typedef Elf64_Sym Elf_Sym;
+
+#define ELF_R_SYM ELF64_R_SYM
+#define ELF_R_TYPE ELF64_R_TYPE
+#define ELF_R_INFO ELF64_R_INFO
+#define ELF_ST_BIND ELF64_ST_BIND
+#define ELF_ST_TYPE ELF64_ST_TYPE
+#define ELF_ST_INFO ELF64_ST_INFO
+
+#elif defined(RT_ARCH_X86)
+# include "elf32.h"
+typedef Elf32_Addr Elf_Addr;
+typedef Elf32_Half Elf_Half;
+typedef Elf32_Off Elf_Off;
+typedef Elf32_Sword Elf_Sword;
+typedef Elf32_Word Elf_Word;
+typedef Elf32_Size Elf_Size;
+typedef Elf32_Hashelt Elf_Hashelt;
+typedef Elf32_Ehdr Elf_Ehdr;
+typedef Elf32_Shdr Elf_Shdr;
+typedef Elf32_Phdr Elf_Phdr;
+typedef Elf32_Nhdr Elf_Nhdr;
+typedef Elf32_Dyn Elf_Dyn;
+typedef Elf32_Rel Elf_Rel;
+typedef Elf32_Rela Elf_Rela;
+typedef Elf32_Sym Elf_Sym;
+
+#define ELF_R_SYM ELF32_R_SYM
+#define ELF_R_TYPE ELF32_R_TYPE
+#define ELF_R_INFO ELF32_R_INFO
+#define ELF_ST_BIND ELF32_ST_BIND
+#define ELF_ST_TYPE ELF32_ST_TYPE
+#define ELF_ST_INFO ELF32_ST_INFO
+
+#else
+# error Unknown arch!
+#endif
+
+#endif /* !IPRT_INCLUDED_formats_elf_h */
+
diff --git a/include/iprt/formats/elf32.h b/include/iprt/formats/elf32.h
new file mode 100644
index 00000000..ae322bb6
--- /dev/null
+++ b/include/iprt/formats/elf32.h
@@ -0,0 +1,200 @@
+/* $Id: elf32.h $ */
+/** @file
+ * IPRT - ELF 32-bit header.
+ */
+
+/*
+ * Copyright (C) 2010-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_formats_elf32_h
+#define IPRT_INCLUDED_formats_elf32_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/assertcompile.h>
+#include "elf-common.h"
+
+/*
+ * ELF 32 standard types.
+ */
+typedef uint32_t Elf32_Addr;
+typedef uint16_t Elf32_Half;
+typedef uint32_t Elf32_Off;
+typedef int32_t Elf32_Sword;
+typedef uint32_t Elf32_Word;
+
+/*
+ * Ensure type size correctness in accordance to .
+ * Portable Format Specification (for ELF), Version 1.1, fig 1-2. .
+ */
+AssertCompileSize(Elf32_Addr, 4);
+AssertCompileSize(Elf32_Half, 2);
+AssertCompileSize(Elf32_Off, 4);
+AssertCompileSize(Elf32_Sword, 4);
+AssertCompileSize(Elf32_Word, 4);
+
+/*
+ * ELF 32 non-standard types for convenience.
+ */
+typedef Elf32_Word Elf32_Size;
+typedef Elf32_Word Elf32_Hashelt;
+
+/*
+ * ELF header.
+ */
+typedef struct
+{
+ unsigned char e_ident[16]; /* ELF identification. */
+ Elf32_Half e_type; /* Object file type. */
+ Elf32_Half e_machine; /* Machine type. */
+ Elf32_Word e_version; /* Object file version. */
+ Elf32_Addr e_entry; /* Entry point address. */
+ Elf32_Off e_phoff; /* Program header offset. */
+ Elf32_Off e_shoff; /* Section header offset. */
+ Elf32_Word e_flags; /* Processor-specific flags. */
+ Elf32_Half e_ehsize; /* ELF header size. */
+ Elf32_Half e_phentsize; /* Size of program header entries. */
+ Elf32_Half e_phnum; /* Number of program headers. */
+ Elf32_Half e_shentsize; /* Size of section header entries. */
+ Elf32_Half e_shnum; /* Number of section headers. */
+ Elf32_Half e_shstrndx; /* Section name string table index. */
+} Elf32_Ehdr;
+
+/*
+ * Section header.
+ */
+typedef struct
+{
+ Elf32_Word sh_name; /* Section name. */
+ Elf32_Word sh_type; /* Section type. */
+ Elf32_Word sh_flags; /* Section attributes. */
+ Elf32_Addr sh_addr; /* Virtual address in memory. */
+ Elf32_Off sh_offset; /* Offset in file. */
+ Elf32_Word sh_size; /* Size of section. */
+ Elf32_Word sh_link; /* Link to other section. */
+ Elf32_Word sh_info; /* Miscellaneous information. */
+ Elf32_Word sh_addralign; /* Address alignment boundary. */
+ Elf32_Word sh_entsize; /* Size of entries, if section has table. */
+} Elf32_Shdr;
+
+
+/*
+ * Program header.
+ */
+typedef struct
+{
+ Elf32_Word p_type; /* Type of segment. */
+ Elf32_Off p_offset; /* Offset in file. */
+ Elf32_Addr p_vaddr; /* Virtual address in memory. */
+ Elf32_Addr p_paddr; /* Physical address (reserved). */
+ Elf32_Word p_filesz; /* Size of segment in file. */
+ Elf32_Word p_memsz; /* Size of segment in memory. */
+ Elf32_Word p_flags; /* Segment attributes. */
+ Elf32_Word p_align; /* Alignment of segment. */
+} Elf32_Phdr;
+
+
+/*
+ * Note header.
+ */
+typedef struct
+{
+ Elf32_Word n_namesz; /* Length of note's name. */
+ Elf32_Word n_descsz; /* Length of note's description. */
+ Elf32_Word n_type; /* Type of note. */
+} Elf32_Nhdr;
+
+
+/*
+ * Symbol table entry.
+ */
+typedef struct
+{
+ Elf32_Word st_name; /* Symbol name. */
+ Elf32_Addr st_value; /* Symbol value. */
+ Elf32_Word st_size; /* Size associated with symbol. */
+ unsigned char st_info; /* Type and binding attributes. */
+ unsigned char st_other; /* Reserved. */
+ Elf32_Half st_shndx; /* Section header table index. */
+} Elf32_Sym;
+
+
+/*
+ * Relocations.
+ */
+typedef struct
+{
+ Elf32_Addr r_offset; /* Location to be relocated. */
+ Elf32_Word r_info; /* Symbol index and type of relocation. */
+} Elf32_Rel;
+
+typedef struct
+{
+ Elf32_Addr r_offset; /* Location to be relocated. */
+ Elf32_Word r_info; /* Symbol index and type of relocation. */
+ Elf32_Sword r_addend; /* Constant part of expression. */
+} Elf32_Rela;
+
+/*
+ * Dynamic section entry.
+ * ".dynamic" section contains an array of this.
+ */
+typedef struct
+{
+ Elf32_Sword d_tag; /* Type of entry. */
+ union
+ {
+ Elf32_Word d_val; /* Integer value. */
+ Elf32_Addr d_ptr; /* Virtual address value. */
+ } d_un;
+} Elf32_Dyn;
+
+/*
+ * Helper macros.
+ */
+/** The symbol's type. */
+#define ELF32_ST_TYPE(info) ((info) & 0xF)
+/** The symbol's binding. */
+#define ELF32_ST_BIND(info) ((info) >> 4)
+/** Make st_info. given binding and type. */
+#define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
+
+/** Relocation type. */
+#define ELF32_R_TYPE(info) ((unsigned char)(info))
+/** Relocation symbol index. */
+#define ELF32_R_SYM(info) ((info) >> 8)
+/** Make r_info given the symbol index and type. */
+#define ELF32_R_INFO(sym, type) (((sym) << 8) + (unsigned char)(type))
+
+
+#endif /* !IPRT_INCLUDED_formats_elf32_h */
+
diff --git a/include/iprt/formats/elf64.h b/include/iprt/formats/elf64.h
new file mode 100644
index 00000000..63d4b1cb
--- /dev/null
+++ b/include/iprt/formats/elf64.h
@@ -0,0 +1,199 @@
+/* $Id: elf64.h $ */
+/** @file
+ * IPRT - ELF 64-bit header.
+ */
+
+/*
+ * Copyright (C) 2010-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_formats_elf64_h
+#define IPRT_INCLUDED_formats_elf64_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/assertcompile.h>
+#include "elf-common.h"
+
+/*
+ * ELF 64 standard types.
+ */
+typedef uint64_t Elf64_Addr;
+typedef uint64_t Elf64_Off;
+typedef uint16_t Elf64_Half;
+typedef uint32_t Elf64_Word;
+typedef int32_t Elf64_Sword;
+typedef uint64_t Elf64_Xword;
+typedef int64_t Elf64_Sxword;
+
+/*
+ * Ensure type size correctness in accordance to ELF-64 Object File Format, Version 1.5 Draft 2, p2.
+ */
+AssertCompileSize(Elf64_Addr, 8);
+AssertCompileSize(Elf64_Off, 8);
+AssertCompileSize(Elf64_Half, 2);
+AssertCompileSize(Elf64_Word, 4);
+AssertCompileSize(Elf64_Sword, 4);
+AssertCompileSize(Elf64_Xword, 8);
+AssertCompileSize(Elf64_Sxword, 8);
+
+/*
+ * ELF 64 non-standard types for convenience.
+ */
+typedef Elf64_Xword Elf64_Size;
+typedef Elf64_Word Elf64_Hashelt;
+
+/*
+ * ELF Header.
+ */
+typedef struct
+{
+ unsigned char e_ident[16]; /* ELF identification. */
+ Elf64_Half e_type; /* Object file type. */
+ Elf64_Half e_machine; /* Machine type. */
+ Elf64_Word e_version; /* Object file version. */
+ Elf64_Addr e_entry; /* Entry point address. */
+ Elf64_Off e_phoff; /* Program header offset. */
+ Elf64_Off e_shoff; /* Section header offset. */
+ Elf64_Word e_flags; /* Processor-specific flags. */
+ Elf64_Half e_ehsize; /* ELF header size. */
+ Elf64_Half e_phentsize; /* Size of program header entry. */
+ Elf64_Half e_phnum; /* Number of program header entries. */
+ Elf64_Half e_shentsize; /* Size of section header entry. */
+ Elf64_Half e_shnum; /* Number of section header entries. */
+ Elf64_Half e_shstrndx; /* Section name string table index. */
+} Elf64_Ehdr;
+
+/*
+ * Section header.
+ */
+typedef struct
+{
+ Elf64_Word sh_name; /* Section name. */
+ Elf64_Word sh_type; /* Section type. */
+ Elf64_Xword sh_flags; /* Section attributes. */
+ Elf64_Addr sh_addr; /* Virtual address in memory. */
+ Elf64_Off sh_offset; /* Offset in file. */
+ Elf64_Xword sh_size; /* Size of section. */
+ Elf64_Word sh_link; /* Link to other section. */
+ Elf64_Word sh_info; /* Miscellaneous information. */
+ Elf64_Xword sh_addralign; /* Address alignment boundary. */
+ Elf64_Xword sh_entsize; /* Size of entries, if section has table. */
+} Elf64_Shdr;
+
+/*
+ * Program header.
+ */
+typedef struct
+{
+ Elf64_Word p_type; /* Type of segment. */
+ Elf64_Word p_flags; /* Segment attributes. */
+ Elf64_Off p_offset; /* Offset in file. */
+ Elf64_Addr p_vaddr; /* Virtual address in memory. */
+ Elf64_Addr p_paddr; /* Physical address (reserved). */
+ Elf64_Xword p_filesz; /* Size of segment in file. */
+ Elf64_Xword p_memsz; /* Size of segment in memory. */
+ Elf64_Xword p_align; /* Alignment of segment. */
+} Elf64_Phdr;
+
+/*
+ * Note header.
+ */
+typedef struct
+{
+ Elf64_Word n_namesz; /* Length of note's name. */
+ Elf64_Word n_descsz; /* Length of note's description. */
+ Elf64_Word n_type; /* Type of note. */
+} Elf64_Nhdr;
+
+/*
+ * Symbol table entry.
+ */
+typedef struct
+{
+ Elf64_Word st_name; /* Symbol name. */
+ unsigned char st_info; /* Type and binding attributes. */
+ unsigned char st_other; /* Reserved. */
+ Elf64_Half st_shndx; /* Section header table index. */
+ Elf64_Addr st_value; /* Symbol value. */
+ Elf64_Xword st_size; /* Size associated with symbol. */
+} Elf64_Sym;
+
+/*
+ * Relocations.
+ */
+typedef struct
+{
+ Elf64_Addr r_offset; /* Location to be relocated. */
+ Elf64_Xword r_info; /* Symbol index and type of relocation. */
+} Elf64_Rel;
+
+typedef struct
+{
+ Elf64_Addr r_offset; /* Location to be relocated. */
+ Elf64_Xword r_info; /* Symbol index and type of relocation. */
+ Elf64_Sxword r_addend; /* Constant part of expression. */
+} Elf64_Rela;
+
+/*
+ * Dynamic section entry.
+ * ".dynamic" section contains an array of this.
+ */
+typedef struct
+{
+ Elf64_Sxword d_tag; /* Type of entry. */
+ union
+ {
+ Elf64_Xword d_val; /* Integer value. */
+ Elf64_Addr d_ptr; /* Virtual address value. */
+ } d_un;
+} Elf64_Dyn;
+
+/*
+ * Helper macros.
+ */
+/** The symbol's type. */
+#define ELF64_ST_TYPE(info) ((info) & 0xF)
+/** The symbol's binding. */
+#define ELF64_ST_BIND(info) ((info) >> 4)
+/** Make st_info. given binding and type. */
+#define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
+
+/** Relocation type. */
+#define ELF64_R_TYPE(info) ((unsigned char)(info))
+/** Relocation symbol index. */
+#define ELF64_R_SYM(info) ((info) >> 32)
+/** Make r_info given the symbol index and type. */
+#define ELF64_R_INFO(sym, type) (((sym) << 32) + (unsigned char)(type))
+
+
+#endif /* !IPRT_INCLUDED_formats_elf64_h */
+
diff --git a/include/iprt/formats/ext.h b/include/iprt/formats/ext.h
new file mode 100644
index 00000000..e9b137a4
--- /dev/null
+++ b/include/iprt/formats/ext.h
@@ -0,0 +1,998 @@
+/* $Id: ext.h $ */
+/** @file
+ * IPRT, Ext2/3/4 format.
+ */
+
+/*
+ * Copyright (C) 2012-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_formats_ext_h
+#define IPRT_INCLUDED_formats_ext_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+#include <iprt/assertcompile.h>
+
+
+/** @defgroup grp_rt_formats_ext Extended Filesystem (EXT2/3/4) structures and definitions
+ * @ingroup grp_rt_formats
+ * @{
+ */
+
+/*
+ * The filesystem structures were retrieved from:
+ * https://www.kernel.org/doc/html/latest/filesystems/ext4/index.html
+ */
+
+/** Offset where to find the first superblock on the disk, this is constant. */
+#define EXT_SB_OFFSET 1024
+
+/** @name EXT_INODE_NR_XXX - Special inode numbers.
+ * @{ */
+#define EXT_INODE_NR_DEF_BLOCKS 1 /**< List of defective blocks. */
+#define EXT_INODE_NR_ROOT_DIR 2 /**< Root directory. */
+#define EXT_INODE_NR_USER_QUOTA 3 /**< User quota. */
+#define EXT_INODE_NR_GROUP_QUOTA 4 /**< Group quota. */
+#define EXT_INODE_NR_BOOT_LOADER 5 /**< Boot loader. */
+#define EXT_INODE_NR_UNDEL_DIR 6 /**< Undelete directory. */
+#define EXT_INODE_NR_RESV_GRP_DESC 7 /**< Reserved group descriptors inode. */
+#define EXT_INODE_NR_JOURNAL 8 /**< Journal. */
+#define EXT_INODE_NR_EXCLUDE 9 /**< Exclude inode. */
+#define EXT_INODE_NR_REPLICA 10 /**< Replica inode. */
+/** @} */
+
+/**
+ * Ext superblock.
+ *
+ * Everything is stored little endian on the disk.
+ */
+typedef struct EXTSUPERBLOCK
+{
+ /** 0x00: Total number of inodes in the filesystem. */
+ uint32_t cInodesTotal;
+ /** 0x04: Total number of blocks in the filesystem (low 32bits). */
+ uint32_t cBlocksTotalLow;
+ /** 0x08: Number of blocks reserved for the super user (low 32bits). */
+ uint32_t cBlocksRsvdForSuperUserLow;
+ /** 0x0c: Total number of free blocks (low 32bits). */
+ uint32_t cBlocksFreeLow;
+ /** 0x10: Total number of free inodes. */
+ uint32_t cInodesFree;
+ /** 0x14: First data block. */
+ uint32_t iBlockOfSuperblock;
+ /** 0x18: Block size (calculated as 2^(10 + cBitsShiftLeftBlockSize)). */
+ uint32_t cLogBlockSize;
+ /** 0x1c: Cluster size (calculated as 2^cLogClusterSize). */
+ uint32_t cLogClusterSize;
+ /** 0x20: Number of blocks in each block group. */
+ uint32_t cBlocksPerGroup;
+ /** 0x24: Number of clusters in each block group. */
+ uint32_t cClustersPerBlockGroup;
+ /** 0x28: Number of inodes for each block group. */
+ uint32_t cInodesPerBlockGroup;
+ /** 0x2c: Last mount time in seconds since epoch. */
+ uint32_t u32LastMountTime;
+ /** 0x30: Last written time in seconds since epoch. */
+ uint32_t u32LastWrittenTime;
+ /** 0x34: Number of times the volume was mounted since the last check. */
+ uint16_t cMountsSinceLastCheck;
+ /** 0x36: Number of mounts allowed before a consistency check. */
+ uint16_t cMaxMountsUntilCheck;
+ /** 0x38: Signature to identify a ext2 volume (EXT_SIGNATURE). */
+ uint16_t u16Signature;
+ /** 0x3a: State of the filesystem (EXT_SB_STATE_XXX) */
+ uint16_t u16FilesystemState;
+ /** 0x3c: What to do on an error. */
+ uint16_t u16ActionOnError;
+ /** 0x3e: Minor revision level. */
+ uint16_t u16RevLvlMinor;
+ /** 0x40: Time of last check in seconds since epoch. */
+ uint32_t u32LastCheckTime;
+ /** 0x44: Interval between consistency checks in seconds. */
+ uint32_t u32CheckInterval;
+ /** 0x48: Operating system ID of the filesystem creator (EXT_SB_OS_ID_CREATOR_XXX). */
+ uint32_t u32OsIdCreator;
+ /** 0x4c: Revision level (EXT_SB_REV_XXX). */
+ uint32_t u32RevLvl;
+ /** 0x50: User ID that is allowed to use reserved blocks. */
+ uint16_t u16UidReservedBlocks;
+ /** 0x52: Group ID that is allowed to use reserved blocks. */
+ uint16_t u16GidReservedBlocks;
+ /** 0x54: First non reserved inode number. */
+ uint32_t iFirstInodeNonRsvd;
+ /** 0x58: Size of the inode structure in bytes. */
+ uint16_t cbInode;
+ /** 0x5a: Block group number of this super block. */
+ uint16_t iBlkGrpSb;
+ /** 0x5c: Compatible feature set flags (EXT_SB_FEAT_COMPAT_XXX). */
+ uint32_t fFeaturesCompat;
+ /** 0x60: Incompatible feature set (EXT_SB_FEAT_INCOMPAT_XXX). */
+ uint32_t fFeaturesIncompat;
+ /** 0x64: Readonly-compatible feature set (EXT_SB_FEAT_COMPAT_RO_XXX). */
+ uint32_t fFeaturesCompatRo;
+ /** 0x68: 128bit UUID for the volume. */
+ uint8_t au8Uuid[16];
+ /** 0x78: Volume name. */
+ char achVolumeName[16];
+ /** 0x88: Directory were the filesystem was mounted last. */
+ char achLastMounted[64];
+ /** 0xc8: Bitmap usage algorithm (used for compression). */
+ uint32_t u32AlgoUsageBitmap;
+ /** 0xcc: Number of blocks to try to preallocate for files(?). */
+ uint8_t cBlocksPrealloc;
+ /** 0xcd: Number of blocks to try to preallocate for directories. */
+ uint8_t cBlocksPreallocDirectory;
+ /** 0xce: Number of reserved group descriptor entries for future filesystem expansion. */
+ uint16_t cGdtEntriesRsvd;
+ /** 0xd0: 128bit UUID for the journal superblock. */
+ uint8_t au8JournalUuid[16];
+ /** 0xe0: Inode number of the journal file. */
+ uint32_t iJournalInode;
+ /** 0xe4: Device number of journal file (if the appropriate feature flag is set). */
+ uint32_t u32JournalDev;
+ /** 0xe8: Start of list of orpaned inodes to delete. */
+ uint32_t u32LastOrphan;
+ /** 0xec: HTREE hash seed. */
+ uint32_t au32HashSeedHtree[4];
+ /** 0xfc: Default hash algorithm to use for hashes (EXT_SB_HASH_VERSION_DEF_XXX). */
+ uint8_t u8HashVersionDef;
+ /** 0xfd: Journal backup type. */
+ uint8_t u8JnlBackupType;
+ /** 0xfe: Group descriptor size in bytes. */
+ uint16_t cbGroupDesc;
+ /** 0x100: Default mount options (EXT_SB_MNT_OPTS_DEF_XXX). */
+ uint32_t fMntOptsDef;
+ /** 0x104: First metablock block group (if feature is enabled). */
+ uint32_t iFirstMetaBg;
+ /** 0x108: Filesystem creation time in seconds since epoch. */
+ uint32_t u32TimeFsCreation;
+ /** 0x10c: Backup copy of journals inodes block array for the first elements. */
+ uint32_t au32JnlBlocks[17];
+ /** 0x150: Total number of blocks in the filesystem (high 32bits). */
+ uint32_t cBlocksTotalHigh;
+ /** 0x154: Number of blocks reserved for the super user (high 32bits). */
+ uint32_t cBlocksRsvdForSuperUserHigh;
+ /** 0x158: Total number of free blocks (high 32bits). */
+ uint32_t cBlocksFreeHigh;
+ /** 0x15c: All inodes have at least this number of bytes. */
+ uint16_t cbInodesExtraMin;
+ /** 0x15e: New inodes should reserve this number of bytes. */
+ uint16_t cbNewInodesRsv;
+ /** 0x160: Miscellaneous flags (EXT_SB_F_XXX). */
+ uint32_t fFlags;
+ /** 0x164: RAID stride, number of logical blocks read from or written to the disk
+ * before moving to the next disk. */
+ uint16_t cRaidStride;
+ /** 0x166: Number of seconds between multi-mount prevention checking. */
+ uint16_t cSecMmpInterval;
+ /** 0x168: Block number for the multi-mount protection data. */
+ uint64_t iMmpBlock;
+ /** 0x170: Raid stride width. */
+ uint32_t cRaidStrideWidth;
+ /** 0x174: Size of a flexible block group (calculated as 2^cLogGroupsPerFlex). */
+ uint8_t cLogGroupsPerFlex;
+ /** 0x175: Metadata checksum algorithm type, only 1 is valid (for CRC32c). */
+ uint8_t u8ChksumType;
+ /** 0x176: Padding. */
+ uint16_t u16Padding;
+ /** 0x178: Number of KiB written to the filesystem so far. */
+ uint64_t cKbWritten;
+ /** 0x180: Inode number of active snapshot. */
+ uint32_t iSnapshotInode;
+ /** 0x184: Sequential ID of active snapshot. */
+ uint32_t iSnapshotId;
+ /** 0x188: Number of blocks reserved for activ snapshot's future use. */
+ uint64_t cSnapshotRsvdBlocks;
+ /** 0x190: Inode number of the head of the on-disk snapshot list. */
+ uint32_t iSnapshotListInode;
+ /** 0x194: Number of errors seen so far. */
+ uint32_t cErrorsSeen;
+ /** 0x198: First time an error happened in seconds since epoch. */
+ uint32_t u32TimeFirstError;
+ /** 0x19c: Inode involved in the first error. */
+ uint32_t iInodeFirstError;
+ /** 0x1a0: Number of block involved of first error. */
+ uint64_t iBlkFirstError;
+ /** 0x1a8: Name of the function where the first error happened. */
+ char achFuncFirstError[32];
+ /** 0x1c8: Line number where the error happened. */
+ uint32_t iLineFirstError;
+ /** 0x1cc: Time of the most receent error in seconds since epoch. */
+ uint32_t u32TimeLastError;
+ /** 0x1d0: Inode involved in the most recent error. */
+ uint32_t iInodeLastError;
+ /** 0x1d4: Line number where the most recent error happened. */
+ uint32_t iLineLastError;
+ /** 0x1d8: Number of block involved of most recent error. */
+ uint64_t iBlkLastError;
+ /** 0x1e0: Name of the function where the most recent error happened. */
+ char achFuncLastError[32];
+ /** 0x200: ASCIIz string of mount options. */
+ char aszMntOpts[64];
+ /** 0x240: Inode number of user quota file. */
+ uint32_t iInodeUsrQuota;
+ /** 0x244: Inode number of group quota file. */
+ uint32_t iInodeGrpQuota;
+ /** 0x248: Overhead blocks/clusters in filesystem. */
+ uint32_t cOverheadBlocks;
+ /** 0x24c: Block groups containing superblock backups. */
+ uint32_t aiBlkGrpSbBackups[2];
+ /** 0x254: Encryption algorithms in use (EXT_SB_ENCRYPT_ALGO_XXX). */
+ uint8_t au8EncryptAlgo[4];
+ /** 0x258: Salt for the string2key algorithm for encryption. */
+ uint8_t abEncryptPwSalt[16];
+ /** 0x268: Inode number of lost+found. */
+ uint32_t iInodeLostFound;
+ /** 0x26c: Inode that tracks project quotas. */
+ uint32_t iInodeProjQuota;
+ /** 0x270: Checksum seed used for the metadata checksum calculations.
+ * Should be crc32c(~0, au8Uuid). */
+ uint32_t u32ChksumSeed;
+ /** 0x274: Upper 8bits of the u32LastWrittenTime field. */
+ uint8_t u32LastWrittenTimeHigh8Bits;
+ /** 0x275: Upper 8bits of the u32LastMountTime field. */
+ uint8_t u32LastMountTimeHigh8Bits;
+ /** 0x276: Upper 8bits of the u32TimeFsCreation field. */
+ uint8_t u32TimeFsCreationHigh8Bits;
+ /** 0x277: Upper 8bits of the u32LastCheckTime field. */
+ uint8_t u32LastCheckTimeHigh8Bits;
+ /** 0x278: Upper 8bits of the u32TimeFirstError field. */
+ uint8_t u32TimeFirstErrorHigh8Bits;
+ /** 0x279: Upper 8bits of the u32TimeLastError field. */
+ uint8_t u32TimeLastErrorHigh8Bits;
+ /** 0x27a: Zero padding. */
+ uint8_t au8Padding[2];
+ /** 0x27c: Padding to the end of the block. */
+ uint32_t au32Rsvd[96];
+ /** 0x3fc: Superblock checksum. */
+ uint32_t u32Chksum;
+} EXTSUPERBLOCK;
+AssertCompileMemberOffset(EXTSUPERBLOCK, u16UidReservedBlocks, 0x50);
+AssertCompileMemberOffset(EXTSUPERBLOCK, u32AlgoUsageBitmap, 0xc8);
+AssertCompileMemberOffset(EXTSUPERBLOCK, iJournalInode, 0xe0);
+AssertCompileMemberOffset(EXTSUPERBLOCK, u8HashVersionDef, 0xfc);
+AssertCompileMemberOffset(EXTSUPERBLOCK, fMntOptsDef, 0x100);
+AssertCompileMemberOffset(EXTSUPERBLOCK, iBlkLastError, 0x1d8);
+AssertCompileMemberOffset(EXTSUPERBLOCK, iInodeLostFound, 0x268);
+AssertCompileSize(EXTSUPERBLOCK, 1024);
+/** Pointer to an ext super block. */
+typedef EXTSUPERBLOCK *PEXTSUPERBLOCK;
+/** Pointer to a const ext super block. */
+typedef EXTSUPERBLOCK const *PCEXTSUPERBLOCK;
+
+/** Ext signature. */
+#define EXT_SB_SIGNATURE UINT16_C(0xef53)
+
+/** @name EXT_SB_STATE_XXX - Filesystem state
+ * @{ */
+/** Clean filesystem state. */
+#define EXT_SB_STATE_CLEAN UINT16_C(0x0001)
+/** Error filesystem state. */
+#define EXT_SB_STATE_ERRORS UINT16_C(0x0002)
+/** Orphans being recovered state. */
+#define EXT_SB_STATE_ORPHANS_RECOVERING UINT16_C(0x0004)
+/** @} */
+
+/** @name EXT_SB_OS_ID_CREATOR_XXX - Filesystem creator
+ * @{ */
+/** Linux. */
+#define EXT_SB_OS_ID_CREATOR_LINUX 0
+/** Hurd. */
+#define EXT_SB_OS_ID_CREATOR_HURD 1
+/** Masix. */
+#define EXT_SB_OS_ID_CREATOR_MASIX 2
+/** FreeBSD. */
+#define EXT_SB_OS_ID_CREATOR_FREEBSD 3
+/** Lites. */
+#define EXT_SB_OS_ID_CREATOR_LITES 4
+/** @} */
+
+/** @name EXT_SB_REV_XXX - Superblock revision
+ * @{ */
+/** Original format (ext2). */
+#define EXT_SB_REV_ORIG 0
+/** Inodes have dynmic sizes. */
+#define EXT_SB_REV_V2_DYN_INODE_SZ 1
+/** @} */
+
+/** @name EXT_SB_FEAT_COMPAT_XXX - Compatible features which can be ignored when set
+ * and not being supported.
+ * @{ */
+/** Directories can be preallocated. */
+#define EXT_SB_FEAT_COMPAT_DIR_PREALLOC RT_BIT_32(0)
+/** Some sort of "imagic" inodes. */
+#define EXT_SB_FEAT_COMPAT_IMAGIC_INODES RT_BIT_32(1)
+/** Filesystem has a journal. */
+#define EXT_SB_FEAT_COMPAT_HAS_JOURNAL RT_BIT_32(2)
+/** Filesystem supports extended attributes. */
+#define EXT_SB_FEAT_COMPAT_EXT_ATTR RT_BIT_32(3)
+/** Filesystem contains reserved group descriptor blocks for filesystem expansion. */
+#define EXT_SB_FEAT_COMPAT_RESIZE_INODE RT_BIT_32(4)
+/** Filesystem contains directory indices. */
+#define EXT_SB_FEAT_COMPAT_DIR_INDEX RT_BIT_32(5)
+/** Lazy block group - not used. */
+#define EXT_SB_FEAT_COMPAT_LAZY_BG RT_BIT_32(6)
+/** Exclude inode - not used. */
+#define EXT_SB_FEAT_COMPAT_EXCLUDE_INODE RT_BIT_32(7)
+/** Exclude bitmap - not used. */
+#define EXT_SB_FEAT_COMPAT_EXCLUDE_BITMAP RT_BIT_32(8)
+/** Sparse super blocks, super block contains pointers to block groups
+ * containing backups of the superblock. */
+#define EXT_SB_FEAT_COMPAT_SPARSE_SUPER2 RT_BIT_32(9)
+/** @} */
+
+/** @name EXT_SB_FEAT_INCOMPAT_XXX - Incompatible features which cause a mounting
+ * error when set and not being supported.
+ * @{ */
+/** Filesystem contains compressed files. */
+#define EXT_SB_FEAT_INCOMPAT_COMPRESSION RT_BIT_32(0)
+/** Directory entries contain a file type. */
+#define EXT_SB_FEAT_INCOMPAT_DIR_FILETYPE RT_BIT_32(1)
+/** Filesystem needs recovery. */
+#define EXT_SB_FEAT_INCOMPAT_RECOVER RT_BIT_32(2)
+/** The journal is recorded on a separate device. */
+#define EXT_SB_FEAT_INCOMPAT_JOURNAL_DEV RT_BIT_32(3)
+/** Filesystem uses meta block groups. */
+#define EXT_SB_FEAT_INCOMPAT_META_BG RT_BIT_32(4)
+/** Files in the filesystem use extents. */
+#define EXT_SB_FEAT_INCOMPAT_EXTENTS RT_BIT_32(6)
+/** Filesystem uses 64bit offsets. */
+#define EXT_SB_FEAT_INCOMPAT_64BIT RT_BIT_32(7)
+/** Filesystem requires multiple mount preotection. */
+#define EXT_SB_FEAT_INCOMPAT_MMP RT_BIT_32(8)
+/** Filesystem uses flexible block groups. */
+#define EXT_SB_FEAT_INCOMPAT_FLEX_BG RT_BIT_32(9)
+/** Inodes can be used to store large extended attribute values. */
+#define EXT_SB_FEAT_INCOMPAT_EXT_ATTR_INODE RT_BIT_32(10)
+/** Data is contained in directory entries. */
+#define EXT_SB_FEAT_INCOMPAT_DIRDATA RT_BIT_32(12)
+/** Metadata checksum seed is stored in the super block. */
+#define EXT_SB_FEAT_INCOMPAT_CSUM_SEED RT_BIT_32(13)
+/** Directories can be larger than 2GiB or contain a 3-level HTree. */
+#define EXT_SB_FEAT_INCOMPAT_LARGE_DIR RT_BIT_32(14)
+/** Data is inlined in the inode. */
+#define EXT_SB_FEAT_INCOMPAT_INLINE_DATA RT_BIT_32(15)
+/** Encrypted inodes are present on the filesystem. */
+#define EXT_SB_FEAT_INCOMPAT_ENCRYPT RT_BIT_32(16)
+/** @} */
+
+/** @name EXT_SB_FEAT_COMPAT_RO_XXX - Backward compatible features when mounted readonly
+ * @{ */
+/** Sparse superblocks. */
+#define EXT_SB_FEAT_COMPAT_RO_SPARSE_SUPER RT_BIT_32(0)
+/** There is at least one large file (> 2GiB). */
+#define EXT_SB_FEAT_COMPAT_RO_LARGE_FILE RT_BIT_32(1)
+/** Actually not used in the Linux kernel and e2fprogs. */
+#define EXT_SB_FEAT_COMPAT_RO_BTREE_DIR RT_BIT_32(2)
+/** Filesystem contains files which sizes are not represented as a multiple of 512 byte sectors
+ * but logical blocks instead. */
+#define EXT_SB_FEAT_COMPAT_RO_HUGE_FILE RT_BIT_32(3)
+/** Group descriptors have checksums embedded */
+#define EXT_SB_FEAT_COMPAT_RO_GDT_CHSKUM RT_BIT_32(4)
+/** Subdirectory limit of 32000 doesn't apply. The link count is set to 1 if beyond 64999. */
+#define EXT_SB_FEAT_COMPAT_RO_DIR_NLINK RT_BIT_32(5)
+/** Inodes can contain extra data. */
+#define EXT_SB_FEAT_COMPAT_RO_EXTRA_INODE_SZ RT_BIT_32(6)
+/** There is at least one snapshot on the filesystem. */
+#define EXT_SB_FEAT_COMPAT_RO_HAS_SNAPSHOTS RT_BIT_32(7)
+/** Quotas are enabled for this filesystem. */
+#define EXT_SB_FEAT_COMPAT_RO_QUOTA RT_BIT_32(8)
+/** The bigalloc feature is enabled, file extents are tracked in units of clusters
+ * instead of blocks. */
+#define EXT_SB_FEAT_COMPAT_RO_BIGALLOC RT_BIT_32(9)
+/** Metadata contains checksums. */
+#define EXT_SB_FEAT_COMPAT_RO_METADATA_CHKSUM RT_BIT_32(10)
+/** Filesystem supports replicas. */
+#define EXT_SB_FEAT_COMPAT_RO_REPLICA RT_BIT_32(11)
+/** Filesystem is readonly. */
+#define EXT_SB_FEAT_COMPAT_RO_READONLY RT_BIT_32(12)
+/** Filesystem tracks project quotas. */
+#define EXT_SB_FEAT_COMPAT_RO_PROJECT RT_BIT_32(13)
+/** @} */
+
+/** @name EXT_SB_HASH_VERSION_DEF_XXX - Default hash algorithm used
+ * @{ */
+/** Legacy. */
+#define EXT_SB_HASH_VERSION_DEF_LEGACY 0
+/** Half MD4. */
+#define EXT_SB_HASH_VERSION_DEF_HALF_MD4 1
+/** Tea. */
+#define EXT_SB_HASH_VERSION_DEF_TEA 2
+/** Unsigned legacy. */
+#define EXT_SB_HASH_VERSION_DEF_LEGACY_UNSIGNED 3
+/** Unsigned half MD4. */
+#define EXT_SB_HASH_VERSION_DEF_HALF_MD4_UNSIGNED 4
+/** Unsigned tea. */
+#define EXT_SB_HASH_VERSION_DEF_TEA_UNSIGNED 5
+/** @} */
+
+/** @name EXT_SB_MNT_OPTS_DEF_XXX - Default mount options
+ * @{ */
+/** Print debugging information on (re)mount. */
+#define EXT_SB_MNT_OPTS_DEF_DEBUG RT_BIT_32(0)
+/** Created files take the group ID ofthe containing directory. */
+#define EXT_SB_MNT_OPTS_DEF_BSDGROUPS RT_BIT_32(1)
+/** Support userspace extended attributes. */
+#define EXT_SB_MNT_OPTS_DEF_XATTR_USER RT_BIT_32(2)
+/** Support POSIX access control lists. */
+#define EXT_SB_MNT_OPTS_DEF_ACL RT_BIT_32(3)
+/** Do not support 32bit UIDs. */
+#define EXT_SB_MNT_OPTS_DEF_UID16 RT_BIT_32(4)
+/** All data and metadata are committed to the journal. */
+#define EXT_SB_MNT_OPTS_DEF_JMODE_DATA RT_BIT_32(5)
+/** All data are flushed to the disk before metadata are committed to the journal. */
+#define EXT_SB_MNT_OPTS_DEF_JMODE_ORDERED RT_BIT_32(6)
+/** Data ordering not preserved, data may be written after metadata has been written. */
+#define EXT_SB_MNT_OPTS_DEF_JMODE_WBACK (EXT_SB_MNT_OPTS_DEF_JMODE_DATA | EXT_SB_MNT_OPTS_DEF_JMODE_ORDERED)
+/** No write flushes. */
+#define EXT_SB_MNT_OPTS_DEF_NOBARRIER RT_BIT_32(8)
+/** Track metadata blocks on the filesystem not being used as data blocks. */
+#define EXT_SB_MNT_OPTS_DEF_BLOCK_VALIDITY RT_BIT_32(9)
+/** Enables TRIM/DISCARD support. */
+#define EXT_SB_MNT_OPTS_DEF_DISCARD RT_BIT_32(10)
+/** Disable delayed allocation. */
+#define EXT_SB_MNT_OPTS_DEF_NODELALLOC RT_BIT_32(11)
+/** @} */
+
+/** @name EXT_SB_F_XXX - Superblock flags
+ * @{ */
+/** Signed directory hash used. */
+#define EXT_SB_F_SIGNED_DIR_HASH RT_BIT_32(0)
+/** Unsigned directory hash used. */
+#define EXT_SB_F_UNSIGNED_DIR_HASH RT_BIT_32(1)
+/** Only used to test development code. */
+#define EXT_SB_F_DEV_CODE RT_BIT_32(3)
+/** @} */
+
+/** @name EXT_SB_ENCRYPT_ALGO_XXX - Group descriptor flags
+ * @{ */
+/** Invalid encryption algorithm. */
+#define EXT_SB_ENCRYPT_ALGO_INVALID 0
+/** 256-bit AES in XTS mode. */
+#define EXT_SB_ENCRYPT_ALGO_256BIT_AES_XTS 1
+/** 256-bit AES in GCM mode. */
+#define EXT_SB_ENCRYPT_ALGO_256BIT_AES_GCM 2
+/** 256-bit AES in CBC mode. */
+#define EXT_SB_ENCRYPT_ALGO_256BIT_AES_CBC 3
+/** @} */
+
+
+/**
+ * Block group descriptor (32byte version).
+ */
+typedef struct EXTBLOCKGROUPDESC32
+{
+ /** 0x00: Block address of the block bitmap (low 32bits). */
+ uint32_t offBlockBitmapLow;
+ /** 0x04: Block address of the inode bitmap (low 32bits). */
+ uint32_t offInodeBitmapLow;
+ /** 0x08: Start block address of the inode table (low 32bits). */
+ uint32_t offInodeTableLow;
+ /** 0x0c: Number of unallocated blocks in group (low 16bits). */
+ uint16_t cBlocksFreeLow;
+ /** 0x0e: Number of unallocated inodes in group (low 16bits). */
+ uint16_t cInodesFreeLow;
+ /** 0x10: Number of directories in the group (low 16bits). */
+ uint16_t cDirectoriesLow;
+ /** 0x12: Flags (EXT_GROUP_DESC_F_XXX). */
+ uint16_t fFlags;
+ /** 0x14: Location of snapshot exclusion bitmap (lower 32bits) */
+ uint32_t offSnapshotExclBitmapLow;
+ /** 0x18: Block bitmap checksum (lower 16bits). */
+ uint16_t u16ChksumBlockBitmapLow;
+ /** 0x1a: Inode bitmap checksum (lower 16bits). */
+ uint16_t u16ChksumInodeBitmapLow;
+ /** 0x1c: Unused inode entry count in the groups inode table (lower 16bits).*/
+ uint16_t cInodeTblUnusedLow;
+ /** 0x1e: Group descriptor checksum. */
+ uint16_t u16Chksum;
+} EXTBLOCKGROUPDESC32;
+AssertCompileSize(EXTBLOCKGROUPDESC32, 32);
+/** Pointer to an ext block group descriptor. */
+typedef EXTBLOCKGROUPDESC32 *PEXTBLOCKGROUPDESC32;
+/** Pointer to a const 32 byte block group descriptor. */
+typedef const EXTBLOCKGROUPDESC32 *PCEXTBLOCKGROUPDESC32;
+
+
+/**
+ * Block group descriptor (64byte version).
+ */
+typedef struct EXTBLOCKGROUPDESC64
+{
+ /** 0x00: Embedded 32 byte descriptor. */
+ EXTBLOCKGROUPDESC32 v32;
+ /** 0x20: Location of block bitmap (upper 32bits). */
+ uint32_t offBlockBitmapHigh;
+ /** 0x24: Location of inode bitmap (upper 32bits). */
+ uint32_t offInodeBitmapHigh;
+ /** 0x28: Location of inode table (upper 32bits). */
+ uint32_t offInodeTableHigh;
+ /** 0x2c: Number of unallocated blocks (upper 16bits). */
+ uint16_t cBlocksFreeHigh;
+ /** 0x2e: Number of unallocated inodes (upper 16bits). */
+ uint16_t cInodesFreeHigh;
+ /** 0x30: Number of directories in the group (upper 16bits). */
+ uint16_t cDirectoriesHigh;
+ /** 0x32: Unused inode entry count in the groups inode table (upper 16bits).*/
+ uint16_t cInodeTblUnusedHigh;
+ /** 0x34: Location of snapshot exclusion bitmap (upper 32bits) */
+ uint32_t offSnapshotExclBitmapHigh;
+ /** 0x38: Block bitmap checksum (upper 16bits). */
+ uint16_t u16ChksumBlockBitmapHigh;
+ /** 0x3a: Inode bitmap checksum (upper 16bits). */
+ uint16_t u16ChksumInodeBitmapHigh;
+ /** 0x3c: Padding to 64 bytes. */
+ uint32_t u64Padding;
+} EXTBLOCKGROUPDESC64;
+AssertCompileSize(EXTBLOCKGROUPDESC64, 64);
+/** Pointer to an ext block group descriptor. */
+typedef EXTBLOCKGROUPDESC64 *PEXTBLOCKGROUPDESC64;
+/** Pointer to a const 64 byte block group descriptor. */
+typedef const EXTBLOCKGROUPDESC64 *PCEXTBLOCKGROUPDESC64;
+
+/** @name EXT_GROUP_DESC_F_XXX - Group descriptor flags
+ * @{ */
+/** Inode table and bitmaps are not initialized. */
+#define EXT_GROUP_DESC_F_INODE_UNINIT RT_BIT(0)
+/** Block bitmap is not initialized. */
+#define EXT_GROUP_DESC_F_BLOCK_UNINIT RT_BIT(1)
+/** Inode table is zeroed. */
+#define EXT_GROUP_DESC_F_INODE_ZEROED RT_BIT(2)
+/** @} */
+
+
+/**
+ * Combiend view of the different block gorup descriptor versions.
+ */
+typedef union EXTBLOCKGROUPDESC
+{
+ /** 32 byte version. */
+ EXTBLOCKGROUPDESC32 v32;
+ /** 64 byte version. */
+ EXTBLOCKGROUPDESC64 v64;
+ /** Byte view. */
+ uint8_t au8[64];
+} EXTBLOCKGROUPDESC;
+/** Poiner to a unified block gorup descriptor view. */
+typedef EXTBLOCKGROUPDESC *PEXTBLOCKGROUPDESC;
+/** Poiner to a const unified block gorup descriptor view. */
+typedef const EXTBLOCKGROUPDESC *PCEXTBLOCKGROUPDESC;
+
+
+/** Number of block entries in the inodes block map. */
+#define EXT_INODE_BLOCK_ENTRIES 15
+
+/**
+ * Inode table entry (standard 128 byte version).
+ */
+typedef struct EXTINODE
+{
+ /** 0x00: File mode (EXT_INODE_FILE_MODE_XXX). */
+ uint16_t fMode;
+ /** 0x02: Owner UID (lower 16bits). */
+ uint16_t uUidLow;
+ /** 0x04: Size in bytes (lower 32bits). */
+ uint32_t cbSizeLow;
+ /** 0x08: Last access time in seconds since epoch. */
+ uint32_t u32TimeLastAccess;
+ /** 0x0c: Last inode change time in seconds since epoch. */
+ uint32_t u32TimeLastChange;
+ /** 0x10: Last data modification time in seconds since epoch. */
+ uint32_t u32TimeLastModification;
+ /** 0x14: Deletion time in seconds since epoch. */
+ uint32_t u32TimeDeletion;
+ /** 0x18: Group ID (lower 16bits). */
+ uint16_t uGidLow;
+ /** 0x1a: Hard link count. */
+ uint16_t cHardLinks;
+ /** 0x1c: Block count (lower 32bits). */
+ uint32_t cBlocksLow;
+ /** 0x20: Inode flags. */
+ uint32_t fFlags;
+ /** 0x24: Operating system dependent data. */
+ union
+ {
+ /** Linux: Inode version. */
+ uint32_t u32LnxVersion;
+ } Osd1;
+ /** 0x28: Block map or extent tree. */
+ uint32_t au32Block[EXT_INODE_BLOCK_ENTRIES];
+ /** 0x64: File version. */
+ uint32_t u32Version;
+ /** 0x68: Extended attribute control block (lower 32bits). */
+ uint32_t offExtAttrLow;
+ /** 0x6c: File/directory size (upper 32bits). */
+ uint32_t cbSizeHigh;
+ /** 0x70: Fragment address (obsolete). */
+ uint32_t u32FragmentAddrObs;
+ /** 0x74: Operating system dependent data 2. */
+ union
+ {
+ /** Linux related data. */
+ struct
+ {
+ /** 0x00: Block count (upper 16bits). */
+ uint16_t cBlocksHigh;
+ /** 0x02: Extended attribute block location (upper 16bits). */
+ uint16_t offExtAttrHigh;
+ /** 0x04: Owner UID (upper 16bits). */
+ uint16_t uUidHigh;
+ /** 0x06: Group ID (upper 16bits). */
+ uint16_t uGidHigh;
+ /** 0x08: Inode checksum (lower 16bits). */
+ uint16_t u16ChksumLow;
+ /** 0x0a: Reserved */
+ uint16_t u16Rsvd;
+ } Lnx;
+ } Osd2;
+} EXTINODE;
+AssertCompileSize(EXTINODE, 128);
+/** Pointer to an inode. */
+typedef EXTINODE *PEXTINODE;
+/** Pointer to a const inode. */
+typedef const EXTINODE *PCEXTINODE;
+
+
+/**
+ * Extra inode data (coming right behind the fixed inode data).
+ */
+typedef struct EXTINODEEXTRA
+{
+ /** 0x80: Size of the extra inode data in bytes. */
+ uint16_t cbInodeExtra;
+ /** 0x82: Inode checksum (upper 16bits.) */
+ uint16_t u16ChksumHigh;
+ /** 0x84: Last inode change time, extra time bits for sub-second precision. */
+ uint32_t u32ExtraTimeLastChange;
+ /** 0x88: Last data modification time, extra time bits for sub-second precision. */
+ uint32_t u32ExtraTimeLastModification;
+ /** 0x8c: Last access time, extra time bits for sub-second precision. */
+ uint32_t u32ExtraTimeLastAccess;
+ /** 0x90: File creation time in seconds since epoch. */
+ uint32_t u32TimeCreation;
+ /** 0x94: File creation time, extra time bits for sub-second precision. */
+ uint32_t u32ExtraTimeCreation;
+ /** 0x98: Version number (upper 32bits). */
+ uint32_t u32VersionHigh;
+ /** 0x9c: Project ID. */
+ uint32_t u32ProjectId;
+} EXTINODEEXTRA;
+/** Pointer to extra inode data. */
+typedef EXTINODEEXTRA *PEXTINODEEXTRA;
+/** Pointer to a const extra inode data. */
+typedef const EXTINODEEXTRA *PCEXTINODEEXTRA;
+
+
+/**
+ * Combined inode data.
+ */
+typedef struct EXTINODECOMB
+{
+ /** Core inode structure. */
+ EXTINODE Core;
+ /** Any extra inode data which might be present. */
+ EXTINODEEXTRA Extra;
+} EXTINODECOMB;
+/** Pointer to combined inode data. */
+typedef EXTINODECOMB *PEXTINODECOMB;
+/** Pointer to a const combined inode data. */
+typedef const EXTINODECOMB *PCEXTINODECOMB;
+
+
+
+/** @name EXT_INODE_MODE_XXX - File mode
+ * @{ */
+/** Others can execute the file. */
+#define EXT_INODE_MODE_EXEC_OTHER RT_BIT(0)
+/** Others can write to the file. */
+#define EXT_INODE_MODE_WRITE_OTHER RT_BIT(1)
+/** Others can read the file. */
+#define EXT_INODE_MODE_READ_OTHER RT_BIT(2)
+/** Members of the same group can execute the file. */
+#define EXT_INODE_MODE_EXEC_GROUP RT_BIT(3)
+/** Members of the same group can write to the file. */
+#define EXT_INODE_MODE_WRITE_GROUP RT_BIT(4)
+/** Members of the same group can read the file. */
+#define EXT_INODE_MODE_READ_GROUP RT_BIT(5)
+/** Owner can execute the file. */
+#define EXT_INODE_MODE_EXEC_OWNER RT_BIT(6)
+/** Owner can write to the file. */
+#define EXT_INODE_MODE_WRITE_OWNER RT_BIT(7)
+/** Owner can read the file. */
+#define EXT_INODE_MODE_READ_OWNER RT_BIT(8)
+/** Sticky file mode. */
+#define EXT_INODE_MODE_STICKY RT_BIT(9)
+/** File is set GID. */
+#define EXT_INODE_MODE_SET_GROUP_ID RT_BIT(10)
+/** File is set UID. */
+#define EXT_INODE_MODE_SET_USER_ID RT_BIT(11)
+/** @} */
+
+/** @name EXT_INODE_MODE_TYPE_XXX - File type
+ * @{ */
+/** Inode represents a FIFO. */
+#define EXT_INODE_MODE_TYPE_FIFO UINT16_C(0x1000)
+/** Inode represents a character device. */
+#define EXT_INODE_MODE_TYPE_CHAR UINT16_C(0x2000)
+/** Inode represents a directory. */
+#define EXT_INODE_MODE_TYPE_DIR UINT16_C(0x4000)
+/** Inode represents a block device. */
+#define EXT_INODE_MODE_TYPE_BLOCK UINT16_C(0x6000)
+/** Inode represents a regular file. */
+#define EXT_INODE_MODE_TYPE_REGULAR UINT16_C(0x8000)
+/** Inode represents a symlink. */
+#define EXT_INODE_MODE_TYPE_SYMLINK UINT16_C(0xa000)
+/** Inode represents a socket. */
+#define EXT_INODE_MODE_TYPE_SOCKET UINT16_C(0xc000)
+/** Returns the inode type from the combined mode field. */
+#define EXT_INODE_MODE_TYPE_GET_TYPE(a_Mode) ((a_Mode) & 0xf000)
+/** @} */
+
+/** @name EXT_INODE_F_XXX - Inode flags
+ * @{ */
+/** Inode requires secure erase on deletion. */
+#define EXT_INODE_F_SECURE_ERASE RT_BIT_32(0)
+/** Inode should be preserved for undeletion during deletion. */
+#define EXT_INODE_F_UNDELETE RT_BIT_32(1)
+/** Inode contains compressed data. */
+#define EXT_INODE_F_COMPRESSED RT_BIT_32(2)
+/** All writes to this inode must be synchronous. */
+#define EXT_INODE_F_SYNCHRONOUS RT_BIT_32(3)
+/** Inode is immutable. */
+#define EXT_INODE_F_IMMUTABLE RT_BIT_32(4)
+/** Inode is append only. */
+#define EXT_INODE_F_APPEND_ONLY RT_BIT_32(5)
+/** Inode should not be dumped via dump(1). */
+#define EXT_INODE_F_NO_DUMP RT_BIT_32(6)
+/** Access time is not updated. */
+#define EXT_INODE_F_NO_ACCESS_TIME RT_BIT_32(7)
+/** Dirty compressed file. */
+#define EXT_INODE_F_DIRTY_COMPRESSED RT_BIT_32(8)
+/** Inode has one or more compressed clusters. */
+#define EXT_INODE_F_COMPRESSED_BLOCK RT_BIT_32(9)
+/** Inode should not be compressed. */
+#define EXT_INODE_F_NO_COMPRESSION RT_BIT_32(10)
+/** Inode is encrypted. */
+#define EXT_INODE_F_ENCRYPTED RT_BIT_32(11)
+/** Directory has hashed indexes. */
+#define EXT_INODE_F_DIR_HASHED_INDEX RT_BIT_32(12)
+/** AFS magic directory. */
+#define EXT_INODE_F_IMAGIC RT_BIT_32(13)
+/** Data must always be written through the journal. */
+#define EXT_INODE_F_JOURNAL_DATA RT_BIT_32(14)
+/** File tail should not be merged. */
+#define EXT_INODE_F_NOTAIL RT_BIT_32(15)
+/** All directory entry data should be written synchronously. */
+#define EXT_INODE_F_DIR_SYNCHRONOUS RT_BIT_32(16)
+/** Top of directory hierarchy. */
+#define EXT_INODE_F_TOP_DIRECTORY RT_BIT_32(17)
+/** Inode is a huge file. */
+#define EXT_INODE_F_HUGE_FILE RT_BIT_32(18)
+/** Inode uses extents. */
+#define EXT_INODE_F_EXTENTS RT_BIT_32(19)
+/** Inode stores a large extended attribute value in its data blocks. */
+#define EXT_INODE_F_EXT_ATTR_INODE RT_BIT_32(20)
+/** File has blocks allocated past end of file. */
+#define EXT_INODE_F_ALLOC_BLOCKS_EOF RT_BIT_32(21)
+/** Inode is a snapshot. */
+#define EXT_INODE_F_SNAPSHOT RT_BIT_32(22)
+/** Snapshot is being deleted. */
+#define EXT_INODE_F_SNAPSHOT_DELETED RT_BIT_32(23)
+/** Snapshot shrink has completed. */
+#define EXT_INODE_F_SNAPSHOT_SHRUNK RT_BIT_32(24)
+/** Inode contains inline data. */
+#define EXT_INODE_F_INLINE_DATA RT_BIT_32(25)
+/** Children are created with the same project ID. */
+#define EXT_INODE_F_PROJECT_ID_INHERIT RT_BIT_32(26)
+/** Reserved for ext4 library. */
+#define EXT_INODE_F_RESERVED_LIBRARY RT_BIT_32(27)
+/** @} */
+
+
+/**
+ * Extent tree header.
+ */
+typedef struct EXTEXTENTHDR
+{
+ /** 0x00: Magic number for identification. */
+ uint16_t u16Magic;
+ /** 0x02: Number of valid entries following. */
+ uint16_t cEntries;
+ /** 0x04: Maxmimum number of entries that could follow. */
+ uint16_t cMax;
+ /** 0x06: Depth of this extent node in the tree. */
+ uint16_t uDepth;
+ /** 0x08: Generation of the tree (not used by standard ext4). */
+ uint32_t cGeneration;
+} EXTEXTENTHDR;
+AssertCompileSize(EXTEXTENTHDR, 12);
+/** Pointer to a extent tree header. */
+typedef EXTEXTENTHDR *PEXTEXTENTHDR;
+/** Pointer to a const extent tree header. */
+typedef const EXTEXTENTHDR *PCEXTEXTENTHDR;
+
+/** Magic number identifying an extent header. */
+#define EXT_EXTENT_HDR_MAGIC UINT16_C(0xf30a)
+/** Maximum depth an extent header can have. */
+#define EXT_EXTENT_HDR_DEPTH_MAX UINT16_C(5)
+
+
+/**
+ * Extent tree index node.
+ */
+typedef struct EXTEXTENTIDX
+{
+ /** 0x00: Start file block this node covers. */
+ uint32_t iBlock;
+ /** 0x04: Block number of child extent node (lower 32bits). */
+ uint32_t offChildLow;
+ /** 0x08: Block number of child extent node (upper 16bits). */
+ uint16_t offChildHigh;
+ /** 0x0a: Reserved. */
+ uint16_t u16Rsvd;
+} EXTEXTENTIDX;
+AssertCompileSize(EXTEXTENTIDX, 12);
+/** Pointer to an extent tree index node. */
+typedef EXTEXTENTIDX *PEXTEXTENTIDX;
+/** Pointer to a const extent tree index node. */
+typedef const EXTEXTENTIDX *PCEXTEXTENTIDX;
+
+
+/**
+ * Extent tree leaf node.
+ */
+typedef struct EXTEXTENT
+{
+ /** 0x00: First file block number this extent covers. */
+ uint32_t iBlock;
+ /** 0x04: Number of blocks covered by this extent. */
+ uint16_t cBlocks;
+ /** 0x06: Block number this extent points to (upper 32bits). */
+ uint16_t offStartHigh;
+ /** 0x08: Block number this extent points to (lower 32bits). */
+ uint32_t offStartLow;
+} EXTEXTENT;
+AssertCompileSize(EXTEXTENT, 12);
+/** Pointer to a leaf node. */
+typedef EXTEXTENT *PEXTEXTENT;
+/** Pointer to a const leaf node. */
+typedef const EXTEXTENT *PCEXTEXTENT;
+
+/** Length field limit for a populated extent, fields greater than that limit indicate a sparse extent. */
+#define EXT_EXTENT_LENGTH_LIMIT UINT16_C(32768)
+
+
+/**
+ * Directory entry.
+ */
+typedef struct EXTDIRENTRY
+{
+ /** 0x00: Inode number being referenced by this entry. */
+ uint32_t iInodeRef;
+ /** 0x04: Record length of this directory entry in bytes (multiple of 4). */
+ uint16_t cbRecord;
+ /** 0x06: Version dependent data. */
+ union
+ {
+ /** Original. */
+ struct
+ {
+ /** Name length in bytes (maximum 255). */
+ uint16_t cbName;
+ } v1;
+ /** Version 2. */
+ struct
+ {
+ /** Name length in bytes (maximum 255). */
+ uint8_t cbName;
+ /** File type (EXT_DIRENTRY_TYPE_XXX). */
+ uint8_t uType;
+ } v2;
+ } u;
+ /** 0x08: File name - variable in size. */
+ char achName[1];
+} EXTDIRENTRY;
+/** Pointer to a directory entry. */
+typedef EXTDIRENTRY *PEXTDIRENTRY;
+/** Poiner to a const directory entry. */
+typedef const EXTDIRENTRY *PCEXTDIRENTRY;
+
+
+/**
+ * Extended directory entry with the maximum size (263 bytes).
+ */
+#pragma pack(1)
+typedef union EXTDIRENTRYEX
+{
+ /** The directory entry. */
+ EXTDIRENTRY Core;
+ /** The byte view. */
+ uint8_t au8[263];
+} EXTDIRENTRYEX;
+#pragma pack()
+AssertCompileSize(EXTDIRENTRYEX, 263);
+/** Pointer to an extended directory entry. */
+typedef EXTDIRENTRYEX *PEXTDIRENTRYEX;
+/** Pointer to a const extended directory entry. */
+typedef const EXTDIRENTRYEX *PCEXTDIRENTRYEX;
+
+
+/** @name EXT_DIRENTRY_TYPE_XXX - file type
+ * @{ */
+/** Entry is of unknown file type. */
+#define EXT_DIRENTRY_TYPE_UNKNOWN 0
+/** Entry is regular file. */
+#define EXT_DIRENTRY_TYPE_REGULAR 1
+/** Entry is another directory. */
+#define EXT_DIRENTRY_TYPE_DIRECTORY 2
+/** Entry is a character device. */
+#define EXT_DIRENTRY_TYPE_CHAR 3
+/** Entry is a block device. */
+#define EXT_DIRENTRY_TYPE_BLOCK 4
+/** Entry is a FIFO. */
+#define EXT_DIRENTRY_TYPE_FIFO 5
+/** Entry is a socket. */
+#define EXT_DIRENTRY_TYPE_SOCKET 6
+/** Entry is a symlink. */
+#define EXT_DIRENTRY_TYPE_SYMLINK 7
+/** Entry is a checksum and uses EXTDIRENTRYCHKSUM. */
+#define EXT_DIRENTRY_TYPE_CHKSUM 0xde
+/** @} */
+
+
+/**
+ * Tail directory entry (for checksumming).
+ */
+typedef struct EXTDIRENTRYCHKSUM
+{
+ /** 0x00: Reserved, must be 0 (overlays with EXTDIRENTRY::iNodeRef). */
+ uint32_t u32Rsvd;
+ /** 0x04: Record length (must be 12). */
+ uint16_t cbRecord;
+ /** 0x06: Reserved (overlays with EXTDIRENTRY::u::v1::cbName). */
+ uint8_t u8Rsvd;
+ /** 0x07: File type (must be 0xde). */
+ uint8_t uType;
+ /** 0x08: Checksum. */
+ uint32_t u32Chksum;
+} EXTDIRENTRYCHKSUM;
+/** Pointer to a tail directory entry. */
+typedef EXTDIRENTRYCHKSUM *PEXTDIRENTRYCHKSUM;
+/** Pointer to const tail directory entry. */
+typedef const EXTDIRENTRYCHKSUM *PCEXTDIRENTRYCHKSUM;
+
+
+/** @} */
+
+#endif /* !IPRT_INCLUDED_formats_ext_h */
+
diff --git a/include/iprt/formats/fat.h b/include/iprt/formats/fat.h
new file mode 100644
index 00000000..d55c0957
--- /dev/null
+++ b/include/iprt/formats/fat.h
@@ -0,0 +1,759 @@
+/* $Id: fat.h $ */
+/** @file
+ * IPRT, File Allocation Table (FAT).
+ */
+
+/*
+ * Copyright (C) 2017-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_formats_fat_h
+#define IPRT_INCLUDED_formats_fat_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+#include <iprt/assertcompile.h>
+
+
+/** @defgroup grp_rt_formats_fat File Allocation Table (FAT) structures and definitions
+ * @ingroup grp_rt_formats
+ * @{
+ */
+
+
+/** @name FAT Media byte values
+ * @remarks This isn't as simple as it's made out to be here!
+ * @{ */
+#define FATBPB_MEDIA_FLOPPY_8 UINT8_C(0xe5)
+#define FATBPB_MEDIA_FLOPPY_5_DOT_25 UINT8_C(0xed)
+#define FATBPB_MEDIA_FLOPPY_3_DOT_5 UINT8_C(0xf0)
+/* incomplete, figure out as needed... */
+
+/** Checks if @a a_bMedia is a valid media byte. */
+#define FATBPB_MEDIA_IS_VALID(a_bMedia) ( (uint8_t)(a_bMedia) >= 0xf8 \
+ || (uint8_t)(a_bMedia) == 0xf0 \
+ || (uint8_t)(a_bMedia) == 0xf4 /* obscure - msdos 2.11 */ \
+ || (uint8_t)(a_bMedia) == 0xf5 /* obscure - msdos 2.11 */ \
+ || (uint8_t)(a_bMedia) == 0xed /* obscure - tandy 2000 */ \
+ || (uint8_t)(a_bMedia) == 0xe5 /* obscure - tandy 2000 */ )
+/** @} */
+
+/** Checks if @a a_bFatId is a valid FAT ID byte.
+ * @todo uncertain whether 0xf4 and 0xf5 should be allowed here too. */
+#define FAT_ID_IS_VALID(a_bFatId) ( (uint8_t)(a_bFatId) >= 0xf8 \
+ || (uint8_t)(a_bFatId) == 0xf0 \
+ || (uint8_t)(a_bFatId) == 0xf4 /* obscure - msdos 2.11 */ \
+ || (uint8_t)(a_bFatId) == 0xf5 /* obscure - msdos 2.11 */ \
+ || (uint8_t)(a_bFatId) == 0xed /* obscure, tandy 2000 */ \
+ || (uint8_t)(a_bFatId) == 0xe5 /* obscure, tandy 2000 */ )
+
+/**
+ * The DOS 2.0 BIOS parameter block (BPB).
+ *
+ * This was the first DOS version with a BPB.
+ */
+#pragma pack(1)
+typedef struct FATBPB20
+{
+ /** 0x0b / 0x00: The sector size in bytes. */
+ uint16_t cbSector;
+ /** 0x0d / 0x02: Number of sectors per cluster. */
+ uint8_t cSectorsPerCluster;
+ /** 0x0e / 0x03: Number of reserved sectors before the first FAT. */
+ uint16_t cReservedSectors;
+ /** 0x10 / 0x05: Number of FATs. */
+ uint8_t cFats;
+ /** 0x11 / 0x06: Max size of the root directory (0 for FAT32). */
+ uint16_t cMaxRootDirEntries;
+ /** 0x13 / 0x08: Total sector count, zero if 32-bit count is used. */
+ uint16_t cTotalSectors16;
+ /** 0x15 / 0x0a: Media ID. */
+ uint8_t bMedia;
+ /** 0x16 / 0x0b: Number of sectors per FAT (0 for FAT32). */
+ uint16_t cSectorsPerFat;
+} FATBPB20;
+#pragma pack()
+AssertCompileSize(FATBPB20, 0xd);
+/** Pointer to a DOS 2.0 BPB. */
+typedef FATBPB20 *PFATBPB20;
+/** Pointer to a const DOS 2.0 BPB. */
+typedef FATBPB20 const *PCFATBPB20;
+
+
+/**
+ * The DOS 3.0 BPB changes that survived.
+ */
+#pragma pack(1)
+typedef struct FATBPB30CMN
+{
+ /** DOS v2.0 BPB. */
+ FATBPB20 Bpb20;
+ /** 0x18 / 0x0d: Sectors per track. Zero means reserved and not used. */
+ uint16_t cSectorsPerTrack;
+ /** 0x1a / 0x0f: Number of heads. Zero means reserved and not used. */
+ uint16_t cTracksPerCylinder;
+} FATBPB30CMN;
+#pragma pack()
+AssertCompileSize(FATBPB30CMN, 0x11);
+
+/**
+ * The DOS 3.0 BPB.
+ */
+#pragma pack(1)
+typedef struct FATBPB30
+{
+ /** DOS v3.0 BPB bits that survived. */
+ FATBPB30CMN Core30;
+ /** 0x1c / 0x11: Number of hidden sectors preceeding the volume. This is zero
+ * on unpartitioned media. */
+ uint16_t cHiddenSectors;
+} FATBPB30;
+#pragma pack()
+AssertCompileSize(FATBPB30, 0x13);
+/** Pointer to a DOS 3.0 BPB. */
+typedef FATBPB30 *PFATBPB30;
+/** Pointer to a const DOS 3.0 BPB. */
+typedef FATBPB30 const *PCFATBPB30;
+
+/**
+ * The DOS 3.0 BPB, flattened structure.
+ */
+#pragma pack(1)
+typedef struct FATBPB30FLAT
+{
+ /** @name New in DOS 2.0
+ * @{ */
+ /** 0x0b / 0x00: The sector size in bytes. */
+ uint16_t cbSector;
+ /** 0x0d / 0x02: Number of sectors per cluster. */
+ uint8_t cSectorsPerCluster;
+ /** 0x0e / 0x03: Number of reserved sectors before the first FAT. */
+ uint16_t cReservedSectors;
+ /** 0x10 / 0x05: Number of FATs. */
+ uint8_t cFats;
+ /** 0x11 / 0x06: Max size of the root directory (0 for FAT32). */
+ uint16_t cMaxRootDirEntries;
+ /** 0x13 / 0x08: Total sector count, zero if 32-bit count is used. */
+ uint16_t cTotalSectors16;
+ /** 0x15 / 0x0a: Media ID. */
+ uint8_t bMedia;
+ /** 0x16 / 0x0b: Number of sectors per FAT (0 for FAT32). */
+ uint16_t cSectorsPerFat;
+ /** @} */
+ /** @name New in DOS 3.0
+ * @{ */
+ /** 0x18 / 0x0d: Sectors per track. Zero means reserved and not used. */
+ uint16_t cSectorsPerTrack;
+ /** 0x1a / 0x0f: Number of heads. Zero means reserved and not used. */
+ uint16_t cTracksPerCylinder;
+ /** 0x1c / 0x11: Number of hidden sectors preceeding the volume. This is zero
+ * on unpartitioned media. */
+ uint16_t cHiddenSectors;
+ /** @} */
+} FATBPB30FLAT;
+#pragma pack()
+AssertCompileSize(FATBPB30FLAT, 0x13);
+/** Pointer to a flattened DOS 3.0 BPB. */
+typedef FATBPB30FLAT *PFATBPB30FLAT;
+/** Pointer to a const flattened DOS 3.0 BPB. */
+typedef FATBPB30FLAT const *PCFATBPB30FLAT;
+
+
+/**
+ * The DOS 3.2 BPB.
+ */
+#pragma pack(1)
+typedef struct FATBPB32
+{
+ /** DOS v3.0 BPB. */
+ FATBPB30 Bpb30;
+ /** 0x1e / 0x13: Number of sectors, including the hidden ones. This is ZERO
+ * in DOS 3.31+. */
+ uint16_t cAnotherTotalSectors;
+} FATBPB32;
+#pragma pack()
+AssertCompileSize(FATBPB32, 0x15);
+/** Pointer to a DOS 3.2 BPB. */
+typedef FATBPB32 *PFATBPB32;
+/** Pointer to const a DOS 3.2 BPB. */
+typedef FATBPB32 const *PCFATBPB32;
+
+/**
+ * The DOS 3.2 BPB, flattened structure.
+ */
+#pragma pack(1)
+typedef struct FATBPB32FLAT
+{
+ /** @name New in DOS 2.0
+ * @{ */
+ /** 0x0b / 0x00: The sector size in bytes. */
+ uint16_t cbSector;
+ /** 0x0d / 0x02: Number of sectors per cluster. */
+ uint8_t cSectorsPerCluster;
+ /** 0x0e / 0x03: Number of reserved sectors before the first FAT. */
+ uint16_t cReservedSectors;
+ /** 0x10 / 0x05: Number of FATs. */
+ uint8_t cFats;
+ /** 0x11 / 0x06: Max size of the root directory (0 for FAT32). */
+ uint16_t cMaxRootDirEntries;
+ /** 0x13 / 0x08: Total sector count, zero if 32-bit count is used. */
+ uint16_t cTotalSectors16;
+ /** 0x15 / 0x0a: Media ID. */
+ uint8_t bMedia;
+ /** 0x16 / 0x0b: Number of sectors per FAT (0 for FAT32). */
+ uint16_t cSectorsPerFat;
+ /** @} */
+ /** @name New in DOS 3.0
+ * @{ */
+ /** 0x18 / 0x0d: Sectors per track. Zero means reserved and not used. */
+ uint16_t cSectorsPerTrack;
+ /** 0x1a / 0x0f: Number of heads. Zero means reserved and not used. */
+ uint16_t cTracksPerCylinder;
+ /** 0x1c / 0x11: Number of hidden sectors preceeding the volume. This is zero
+ * on unpartitioned media. */
+ uint16_t cHiddenSectors;
+ /** @} */
+ /** @name New in DOS 3.2
+ * @{ */
+ /** 0x1e / 0x13: Number of sectors, including the hidden ones. This is ZERO
+ * in DOS 3.31+. */
+ uint16_t cAnotherTotalSectors;
+ /** @} */
+} FATBPB32FLAT;
+#pragma pack()
+AssertCompileSize(FATBPB32FLAT, 0x15);
+/** Pointer to a flattened DOS 3.2 BPB. */
+typedef FATBPB32FLAT *PFATBPB32FLAT;
+/** Pointer to a const flattened DOS 3.2 BPB. */
+typedef FATBPB32FLAT const *PCFATBPB32FLAT;
+
+
+/**
+ * The DOS 3.31 BPB.
+ */
+#pragma pack(1)
+typedef struct FATBPB331
+{
+ /** DOS v3.0 BPB bits that survived. */
+ FATBPB30CMN Core30;
+ /** 0x1c / 0x11: Number of hidden sectors preceeding the volume. This is zero
+ * on unpartitioned media. Values higher than 65535 are complicated due to
+ * the field overlapping FATBPB32::cAnotherTotalSectors */
+ uint32_t cHiddenSectors;
+ /** 0x20 / 0x15: Total logical sectors. Used if count >= 64K, otherwise
+ * FATBPB20::cTotalSectors16 is used. Zero if 64-bit value used with FAT32. */
+ uint32_t cTotalSectors32;
+} FATBPB331;
+#pragma pack()
+AssertCompileSize(FATBPB331, 0x19);
+/** Pointer to a DOS 3.31 BPB. */
+typedef FATBPB331 *PFATBPB331;
+/** Pointer to a const DOS 3.31 BPB. */
+typedef FATBPB331 const *PCFATBPB331;
+
+/**
+ * The DOS 3.31 BPB, flattened structure.
+ */
+#pragma pack(1)
+typedef struct FATBPB331FLAT
+{
+ /** @name New in DOS 2.0
+ * @{ */
+ /** 0x0b / 0x00: The sector size in bytes. */
+ uint16_t cbSector;
+ /** 0x0d / 0x02: Number of sectors per cluster. */
+ uint8_t cSectorsPerCluster;
+ /** 0x0e / 0x03: Number of reserved sectors before the first FAT (0 for
+ * NTFS). */
+ uint16_t cReservedSectors;
+ /** 0x10 / 0x05: Number of FATs (0 for NTFS). */
+ uint8_t cFats;
+ /** 0x11 / 0x06: Max size of the root directory (0 for FAT32 & NTFS). */
+ uint16_t cMaxRootDirEntries;
+ /** 0x13 / 0x08: Total sector count, zero if 32-bit count is used (and for
+ * NTFS). */
+ uint16_t cTotalSectors16;
+ /** 0x15 / 0x0a: Media ID. */
+ uint8_t bMedia;
+ /** 0x16 / 0x0b: Number of sectors per FAT (0 for FAT32 & NTFS). */
+ uint16_t cSectorsPerFat;
+ /** @} */
+ /** @name New in DOS 3.0
+ * @{ */
+ /** 0x18 / 0x0d: Sectors per track. Zero means reserved and not used. */
+ uint16_t cSectorsPerTrack;
+ /** 0x1a / 0x0f: Number of heads. Zero means reserved and not used. */
+ uint16_t cTracksPerCylinder;
+ /** @} */
+ /** @name New in DOS 3.31
+ * @{ */
+ /** 0x1c / 0x11: Number of hidden sectors preceeding the volume. This is zero
+ * on unpartitioned media. Values higher than 65535 are complicated due to
+ * the field overlapping FATBPB32::cAnotherTotalSectors */
+ uint32_t cHiddenSectors;
+ /** 0x20 / 0x15: Total logical sectors. Used if count >= 64K, otherwise
+ * FATBPB20::cTotalSectors16 is used. Zero if 64-bit value used with FAT32.
+ * (Zero for NTFS). */
+ uint32_t cTotalSectors32;
+ /** @} */
+} FATBPB331FLAT;
+#pragma pack()
+AssertCompileSize(FATBPB331FLAT, 0x19);
+/** Pointer to a flattened DOS 3.31 BPB. */
+typedef FATBPB331FLAT *PFATBPB331FLAT;
+/** Pointer to a const flattened DOS 3.31 BPB. */
+typedef FATBPB331FLAT const *PCFATBPB331FLAT;
+
+
+/**
+ * Extended BIOS parameter block (EBPB).
+ */
+#pragma pack(1)
+typedef struct FATEBPB
+{
+ /** The BPB. */
+ FATBPB331FLAT Bpb;
+
+ /** 0x24 / 0x19: BIOS INT13 pysical drive number. */
+ uint8_t bInt13Drive;
+ /** 0x25 / 0x1a: Reserved. NT used bit 0 for indicating dirty FS, and bit 1
+ * for surface scan. */
+ uint8_t bReserved;
+ /** 0x26 / 0x1b: Extended boot signature, FATEBPB_SIGNATURE or
+ * FATEBPB_SIGNATURE_OLD. */
+ uint8_t bExtSignature;
+ /** 0x27 / 0x1c: The volume serial number. */
+ uint32_t uSerialNumber;
+ /** 0x2b / 0x20: The volume label (space padded).
+ * @remarks Not available with FATEBPB_SIGNATURE_OLD */
+ char achLabel[11];
+ /** 0x36 / 0x2b: The file system type (space padded).
+ * @remarks Not available with FATEBPB_SIGNATURE_OLD */
+ char achType[8];
+} FATEBPB;
+#pragma pack()
+AssertCompileSize(FATEBPB, 0x33);
+/** Pointer to an extended BIOS parameter block. */
+typedef FATEBPB *PFATEBPB;
+/** Pointer to a const extended BIOS parameter block. */
+typedef FATEBPB const *PCFATEBPB;
+
+/** FATEBPB::bExtSignature value. */
+#define FATEBPB_SIGNATURE UINT8_C(0x29)
+/** FATEBPB::bExtSignature value used by OS/2 1.0-1.1 and PC DOS 3.4. These
+ * does not have the volume and file system type. */
+#define FATEBPB_SIGNATURE_OLD UINT8_C(0x28)
+
+/**FATEBPB::achType value for FAT12. */
+#define FATEBPB_TYPE_FAT12 "FAT12 "
+/**FATEBPB::achType value for FAT16. */
+#define FATEBPB_TYPE_FAT16 "FAT16 "
+/**FATEBPB::achType value for FAT12/FAT16. */
+#define FATEBPB_TYPE_FAT "FAT32 "
+
+
+/**
+ * FAT32 Extended BIOS parameter block (EBPB).
+ */
+#pragma pack(1)
+typedef struct FAT32EBPB
+{
+ /** The BPB. */
+ FATBPB331FLAT Bpb;
+
+ /** 0x24 / 0x19: Number of sectors per FAT.
+ * @note To avoid confusion with the FATEBPB signature, values which result in
+ * 0x00280000 or 0x00290000 when masked by 0x00ff0000 must not be used. */
+ uint32_t cSectorsPerFat32;
+ /** 0x28 / 0x1d: Flags pertaining to FAT mirroring and other stuff. */
+ uint16_t fFlags;
+ /** 0x2a / 0x1f: FAT32 version number (FAT32EBPB_VERSION_0_0). */
+ uint16_t uVersion;
+ /** 0x2c / 0x21: Cluster number of the root directory. */
+ uint32_t uRootDirCluster;
+ /** 0x30 / 0x25: Logical sector number of the information sector. */
+ uint16_t uInfoSectorNo;
+ /** 0x32 / 0x27: Logical sector number of boot sector copy. */
+ uint16_t uBootSectorCopySectorNo;
+ /** 0x34 / 0x29: Reserved, zero (or 0xf6) filled, preserve. */
+ uint8_t abReserved[12];
+
+ /** 0x40 / 0x35: BIOS INT13 pysical drive number
+ * @remarks Same as FATEBPB::bInt13Drive. */
+ uint8_t bInt13Drive;
+ /** 0x41 / 0x36: Reserved.
+ * @remarks Same as FATEBPB::bReserved. */
+ uint8_t bReserved;
+ /** 0x42 / 0x37: Extended boot signature (FATEBPB_SIGNATURE, or
+ * FATEBPB_SIGNATURE_OLD in some special cases).
+ * @remarks Same as FATEBPB::bExtSignature. */
+ uint8_t bExtSignature;
+ /** 0x43 / 0x38: The volume serial number.
+ * @remarks Same as FATEBPB::uSerialNumber. */
+ uint32_t uSerialNumber;
+ /** 0x47 / 0x3c: The volume label (space padded).
+ * @remarks Not available with FATEBPB_SIGNATURE_OLD
+ * @remarks Same as FATEBPB::achLabel. */
+ char achLabel[11];
+ /** 0x52 / 0x47: The file system type (space padded), or 64-bit logical sector
+ * count if both other count fields are zero. In the latter case, the type is
+ * moved to the OEM name field (FATBOOTSECTOR::achOemName).
+ *
+ * @remarks Not available with FATEBPB_SIGNATURE_OLD
+ * @remarks Same as FATEBPB::achType. */
+ union
+ {
+ /** Type string variant. */
+ char achType[8];
+ /** Total sector count if 4G or higher. */
+ uint64_t cTotalSectors64;
+ } u;
+} FAT32EBPB;
+#pragma pack()
+AssertCompileSize(FAT32EBPB, 0x4f);
+/** Pointer to a FAT32 extended BIOS parameter block. */
+typedef FAT32EBPB *PFAT32EBPB;
+/** Pointer to a const FAT32 extended BIOS parameter block. */
+typedef FAT32EBPB const *PCFAT32EBPB;
+
+/** FAT32 version 0.0 (FAT32EBPB::uVersion). */
+#define FAT32EBPB_VERSION_0_0 UINT16_C(0x0000)
+
+
+/**
+ * NTFS extended BIOS parameter block (NTFSEBPB).
+ */
+#pragma pack(1)
+typedef struct NTFSEBPB
+{
+ /** The BPB. */
+ FATBPB331FLAT Bpb;
+
+ /** 0x24 / 0x19: BIOS INT13 pysical drive number.
+ * @note Same location as FATEBPB::bInt13Drive. */
+ uint8_t bInt13Drive;
+ /** 0x25 / 0x1a: Reserved / flags */
+ uint8_t bReserved;
+ /** 0x26 / 0x1b: Extended boot signature (NTFSEBPB_SIGNATURE).
+ * @note Same location as FATEBPB::bExtSignature. */
+ uint8_t bExtSignature;
+ /** 0x27 / 0x1c: Reserved */
+ uint8_t bReserved2;
+
+ /** 0x28 / 0x1d: Number of sectors. */
+ uint64_t cSectors;
+ /** 0x30 / 0x25: Logical cluster number of the master file table (MFT). */
+ uint64_t uLcnMft;
+ /** 0x38 / 0x2d: Logical cluster number of the MFT mirror. */
+ uint64_t uLcnMftMirror;
+ /** 0x40 / 0x35: Logical clusters per file record segment.
+ * This is a shift count if negative. */
+ int8_t cClustersPerMftRecord;
+ /** 0x41 / 0x36: Reserved. */
+ uint8_t abReserved3[3];
+ /** 0x44 / 0x39: The default logical clusters count per index node.
+ * This is a shift count if negative. */
+ int8_t cClustersPerIndexNode;
+ /** 0x45 / 0x3a: Reserved. */
+ uint8_t abReserved4[3];
+ /** 0x48 / 0x3d: Volume serial number.
+ * @note This is larger than the the FAT serial numbers. */
+ uint64_t uSerialNumber;
+ /** 0x50 / 0x45: Checksum. */
+ uint32_t uChecksum;
+} NTFSEBPB;
+#pragma pack()
+AssertCompileSize(NTFSEBPB, 0x49);
+/** Pointer to a NTFS extended BIOS parameter block. */
+typedef NTFSEBPB *PNTFSEBPB;
+/** Pointer to a const NTFS extended BIOS parameter block. */
+typedef NTFSEBPB const *PCNTFSEBPB;
+
+/** NTFS EBPB signature (NTFSEBPB::bExtSignature). */
+#define NTFSEBPB_SIGNATURE UINT8_C(0x80)
+
+
+/**
+ * FAT boot sector layout.
+ */
+#pragma pack(1)
+typedef struct FATBOOTSECTOR
+{
+ /** 0x000: DOS 2.0+ jump sequence. */
+ uint8_t abJmp[3];
+ /** 0x003: OEM name (who formatted this volume). */
+ char achOemName[8];
+ /** 0x00b: The BIOS parameter block.
+ * This varies a lot in size. */
+ union
+ {
+ FATBPB20 Bpb20;
+ FATBPB30FLAT Bpb30;
+ FATBPB32FLAT Bpb32;
+ FATBPB331FLAT Bpb331;
+ FATEBPB Ebpb;
+ FAT32EBPB Fat32Ebpb;
+ NTFSEBPB Ntfs;
+ } Bpb;
+ /** 0x05a: Bootloader code/data/stuff. */
+ uint8_t abStuff[0x1a3];
+ /** 0x1fd: Old drive number location (DOS 3.2-3.31). */
+ uint8_t bOldInt13Drive;
+ /** 0x1fe: DOS signature (FATBOOTSECTOR_SIGNATURE). */
+ uint16_t uSignature;
+} FATBOOTSECTOR;
+#pragma pack()
+AssertCompileSize(FATBOOTSECTOR, 0x200);
+/** Pointer to a FAT boot sector. */
+typedef FATBOOTSECTOR *PFATBOOTSECTOR;
+/** Pointer to a const FAT boot sector. */
+typedef FATBOOTSECTOR const *PCFATBOOTSECTOR;
+
+/** Boot sector signature (FATBOOTSECTOR::uSignature). */
+#define FATBOOTSECTOR_SIGNATURE UINT16_C(0xaa55)
+
+
+
+/**
+ * FAT32 info sector (follows the boot sector).
+ */
+typedef struct FAT32INFOSECTOR
+{
+ /** 0x000: Signature \#1 (FAT32INFOSECTOR_SIGNATURE_1). */
+ uint32_t uSignature1;
+ /** Reserved, should be zero. */
+ uint8_t abReserved1[0x1E0];
+ /** 0x1e4: Signature \#1 (FAT32INFOSECTOR_SIGNATURE_2). */
+ uint32_t uSignature2;
+ /** 0x1e8: Last known number of free clusters (informational). */
+ uint32_t cFreeClusters;
+ /** 0x1ec: Last allocated cluster number (informational). This could be used as
+ * an allocation hint when searching for a free cluster. */
+ uint32_t cLastAllocatedCluster;
+ /** 0x1f0: Reserved, should be zero, preserve. */
+ uint8_t abReserved2[12];
+ /** 0x1fc: Signature \#3 (FAT32INFOSECTOR_SIGNATURE_3). */
+ uint32_t uSignature3;
+} FAT32INFOSECTOR;
+AssertCompileSize(FAT32INFOSECTOR, 0x200);
+/** Pointer to a FAT32 info sector. */
+typedef FAT32INFOSECTOR *PFAT32INFOSECTOR;
+/** Pointer to a const FAT32 info sector. */
+typedef FAT32INFOSECTOR const *PCFAT32INFOSECTOR;
+
+#define FAT32INFOSECTOR_SIGNATURE_1 UINT32_C(0x41615252)
+#define FAT32INFOSECTOR_SIGNATURE_2 UINT32_C(0x61417272)
+#define FAT32INFOSECTOR_SIGNATURE_3 UINT32_C(0xaa550000)
+
+
+/** @name Special FAT cluster numbers and limits.
+ * @{ */
+#define FAT_FIRST_DATA_CLUSTER 2 /**< The first data cluster. */
+
+#define FAT_MAX_FAT12_TOTAL_CLUSTERS UINT32_C(0x00000ff6) /**< Maximum number of clusters in a 12-bit FAT . */
+#define FAT_MAX_FAT16_TOTAL_CLUSTERS UINT32_C(0x0000fff6) /**< Maximum number of clusters in a 16-bit FAT . */
+#define FAT_MAX_FAT32_TOTAL_CLUSTERS UINT32_C(0x0ffffff6) /**< Maximum number of clusters in a 32-bit FAT . */
+
+#define FAT_LAST_FAT12_DATA_CLUSTER UINT32_C(0x00000ff5) /**< The last possible data cluster for FAT12. */
+#define FAT_LAST_FAT16_DATA_CLUSTER UINT32_C(0x0000fff5) /**< The last possible data cluster for FAT16. */
+#define FAT_LAST_FAT32_DATA_CLUSTER UINT32_C(0x0ffffff5) /**< The last possible data cluster for FAT32. */
+
+#define FAT_MAX_FAT12_DATA_CLUSTERS UINT32_C(0x00000ff4) /**< Maximum number of data clusters for FAT12. */
+#define FAT_MAX_FAT16_DATA_CLUSTERS UINT32_C(0x0000fff4) /**< Maximum number of data clusters for FAT16. */
+#define FAT_MAX_FAT32_DATA_CLUSTERS UINT32_C(0x0ffffff4) /**< Maximum number of data clusters for FAT32. */
+
+#define FAT_MIN_FAT12_DATA_CLUSTERS UINT32_C(0x00000001) /**< Maximum number of data clusters for FAT12. */
+#define FAT_MIN_FAT16_DATA_CLUSTERS UINT32_C(0x00000ff5) /**< Maximum number of data clusters for FAT16. */
+#define FAT_MIN_FAT32_DATA_CLUSTERS UINT32_C(0x0000fff5) /**< Maximum number of data clusters for FAT32. */
+
+#define FAT_FIRST_FAT12_EOC UINT32_C(0x00000ff8) /**< The first end-of-file-cluster number for FAT12. */
+#define FAT_FIRST_FAT16_EOC UINT32_C(0x0000fff8) /**< The first end-of-file-cluster number for FAT16. */
+#define FAT_FIRST_FAT32_EOC UINT32_C(0x0ffffff8) /**< The first end-of-file-cluster number for FAT32. */
+/** @} */
+
+
+/**
+ * FAT directory entry.
+ */
+typedef struct FATDIRENTRY
+{
+ /** 0x00: The directory entry name.
+ * First character serves as a flag to indicate deleted or not. */
+ uint8_t achName[8+3];
+ /** 0x0b: Attributes (FAT_ATTR_XXX). */
+ uint8_t fAttrib;
+ /** 0x0c: NT case flags (FATDIRENTRY_CASE_F_XXX). */
+ uint8_t fCase;
+ /** 0x0d: Birth milliseconds (DOS 7.0+ w/VFAT). */
+ uint8_t uBirthCentiseconds;
+ /** 0x0e: Birth time (DOS 7.0+ w/VFAT). */
+ uint16_t uBirthTime;
+ /** 0x10: Birth date (DOS 7.0+ w/VFAT). */
+ uint16_t uBirthDate;
+ /** 0x12: Access date (DOS 7.0+ w/ACCDATA in Config.sys). */
+ uint16_t uAccessDate;
+ union
+ {
+ /** 0x14: High cluster word for FAT32. */
+ uint16_t idxClusterHigh;
+ /** 0x14: Index of extended attributes (FAT16/FAT12). */
+ uint16_t idxEAs;
+ } u;
+ /** 0x16: Modify time (PC-DOS 1.1+, MS-DOS 1.20+). */
+ uint16_t uModifyTime;
+ /** 0x18: Modify date. */
+ uint16_t uModifyDate;
+ /** 0x1a: The data cluster index. */
+ uint16_t idxCluster;
+ /** 0x1c: The file size. */
+ uint32_t cbFile;
+} FATDIRENTRY;
+AssertCompileSize(FATDIRENTRY, 0x20);
+AssertCompileMemberOffset(FATDIRENTRY, fAttrib, 0x0b);
+AssertCompileMemberOffset(FATDIRENTRY, fCase, 0x0c);
+AssertCompileMemberOffset(FATDIRENTRY, uBirthCentiseconds, 0x0d);
+AssertCompileMemberOffset(FATDIRENTRY, uBirthTime, 0x0e);
+AssertCompileMemberOffset(FATDIRENTRY, uBirthDate, 0x10);
+AssertCompileMemberOffset(FATDIRENTRY, uAccessDate, 0x12);
+AssertCompileMemberOffset(FATDIRENTRY, u, 0x14);
+AssertCompileMemberOffset(FATDIRENTRY, uModifyTime, 0x16);
+AssertCompileMemberOffset(FATDIRENTRY, uModifyDate, 0x18);
+AssertCompileMemberOffset(FATDIRENTRY, idxCluster, 0x1a);
+AssertCompileMemberOffset(FATDIRENTRY, cbFile, 0x1c);
+/** Pointer to a FAT directory entry. */
+typedef FATDIRENTRY *PFATDIRENTRY;
+/** Pointer to a FAT directory entry. */
+typedef FATDIRENTRY const *PCFATDIRENTRY;
+
+
+/** @name FAT_ATTR_XXX - FATDIRENTRY::fAttrib flags.
+ * @{ */
+#define FAT_ATTR_READONLY UINT8_C(0x01)
+#define FAT_ATTR_HIDDEN UINT8_C(0x02)
+#define FAT_ATTR_SYSTEM UINT8_C(0x04)
+#define FAT_ATTR_VOLUME UINT8_C(0x08)
+#define FAT_ATTR_DIRECTORY UINT8_C(0x10)
+#define FAT_ATTR_ARCHIVE UINT8_C(0x20)
+#define FAT_ATTR_DEVICE UINT8_C(0x40)
+#define FAT_ATTR_RESERVED UINT8_C(0x80)
+#define FAT_ATTR_NAME_SLOT UINT8_C(0x0f) /**< Special attribute value for FATDIRNAMESLOT. */
+/** @} */
+
+/** @name FATDIRENTRY_CASE_F_XXX - FATDIRENTRY::fCase flags.
+ * @{ */
+/** Lower cased base name (first 8 chars). */
+#define FATDIRENTRY_CASE_F_LOWER_BASE UINT8_C(0x08)
+/** Lower cased filename extension (last 3 chars). */
+#define FATDIRENTRY_CASE_F_LOWER_EXT UINT8_C(0x10)
+/** @} */
+
+/** @name FATDIRENTRY_CH0_XXX - FATDIRENTRY::achName[0]
+ * @{ */
+/** Deleted entry. */
+#define FATDIRENTRY_CH0_DELETED UINT8_C(0xe5)
+/** End of used directory entries (MS-DOS 1.25+, PC-DOS 2.0+). */
+#define FATDIRENTRY_CH0_END_OF_DIR UINT8_C(0x00)
+/** The special dot or dot-dot dir aliases (MS-DOS 1.40+, PC-DOS 2.0+).
+ * @remarks 0x2e is the ascii table entry of the '.' character. */
+#define FATDIRENTRY_CH0_DOT_ALIAS UINT8_C(0x2e)
+/** Escaped 0xe5 leadcharacter (DOS 3.0+). */
+#define FATDIRENTRY_CH0_ESC_E5 UINT8_C(0x05)
+/** @} */
+
+
+/**
+ * FAT directory alias name slot.
+ *
+ * Each slot holds 13 UTF-16 (/ UCS-2) characters, so it takes 20 slots to cover
+ * a 255 character long name.
+ */
+#pragma pack(1)
+typedef struct FATDIRNAMESLOT
+{
+ /** The slot sequence number. */
+ uint8_t idSlot;
+ /** The first 5 name chars.
+ * @remarks misaligned */
+ RTUTF16 awcName0[5];
+ /** Attributes (FAT_ATTR_XXX). */
+ uint8_t fAttrib;
+ /** Always zero. */
+ uint8_t fZero;
+ /** Alias checksum. */
+ uint8_t bChecksum;
+ /** The next 6 name chars. */
+ RTUTF16 awcName1[6];
+ /** Always zero (usually cluster entry). */
+ uint16_t idxZero;
+ /** The next 2 name chars. */
+ RTUTF16 awcName2[2];
+} FATDIRNAMESLOT;
+#pragma pack()
+AssertCompileSize(FATDIRNAMESLOT, 0x20);
+/** Pointer to a FAT directory entry. */
+typedef FATDIRNAMESLOT *PFATDIRNAMESLOT;
+/** Pointer to a FAT directory entry. */
+typedef FATDIRNAMESLOT const *PCFATDIRNAMESLOT;
+
+/** Slot ID flag indicating that it's the first slot. */
+#define FATDIRNAMESLOT_FIRST_SLOT_FLAG UINT8_C(0x40)
+/** Highest slot ID recognized. This allows for 260 characters, however many
+ * implementation limits it to 255 or 250. */
+#define FATDIRNAMESLOT_HIGHEST_SLOT_ID UINT8_C(0x14)
+/** Max number of slots recognized. (This is the same as the higest slot ID
+ * because the 0 isn't a valid ID.) */
+#define FATDIRNAMESLOT_MAX_SLOTS FATDIRNAMESLOT_HIGHEST_SLOT_ID
+/** Number of UTF-16 units per slot. */
+#define FATDIRNAMESLOT_CHARS_PER_SLOT (5 + 6 + 2)
+
+
+
+/**
+ * FAT directory entry union.
+ */
+typedef union FATDIRENTRYUNION
+{
+ /** Regular entry view. */
+ FATDIRENTRY Entry;
+ /** Name slot view. */
+ FATDIRNAMESLOT Slot;
+} FATDIRENTRYUNION;
+AssertCompileSize(FATDIRENTRYUNION, 0x20);
+/** Pointer to a FAT directory entry union. */
+typedef FATDIRENTRYUNION *PFATDIRENTRYUNION;
+/** Pointer to a const FAT directory entry union. */
+typedef FATDIRENTRYUNION const *PCFATDIRENTRYUNION;
+
+/** @} */
+
+#endif /* !IPRT_INCLUDED_formats_fat_h */
+
diff --git a/include/iprt/formats/hfs.h b/include/iprt/formats/hfs.h
new file mode 100644
index 00000000..bedcb8f1
--- /dev/null
+++ b/include/iprt/formats/hfs.h
@@ -0,0 +1,691 @@
+/** @file
+ * IPRT - Hierarchical File System (HFS).
+ */
+
+/*
+ * Copyright (C) 2009-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_formats_hfs_h
+#define IPRT_INCLUDED_formats_hfs_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+
+#include <iprt/types.h>
+#include <iprt/assertcompile.h>
+
+
+/** @defgroup grp_rt_fmt_hfs HFS - Hierarchical File System.
+ * @{
+ */
+
+
+/** @name HFS signature words (HFSPlusVolumeHeader::signature)
+ * @{ */
+#define kHFSSigWord UINT16_C(0x4244)
+#define kHFSPlusSigWord UINT16_C(0x482b)
+#define kHFSXSigWord UINT16_C(0x4858)
+/** @} */
+
+/** @name HFS version numbers (HFSPlusVolumeHeader::version).
+ * @{ */
+#define kHFSPlusVersion UINT16_C(4)
+#define kHFSXVersion UINT16_C(5)
+/** @} */
+
+/** @name HFS mount version numbers (HFSPlusVolumeHeader::lastMountedVersion).
+ * @{ */
+#define kHFSPlusMountVersion UINT32_C(0x31302e30)
+#define kHFSJMountVersion UINT32_C(0x4846534a)
+#define kFSKMountVersion UINT32_C(0x46534b21)
+/** @} */
+
+/** @name Hard link file creators & types.
+ * @{ */
+#define kHardLinkFileType UINT32_C(0x686c6e6b)
+#define kHFSPlusCreator UINT32_C(0x6866732b)
+/** @} */
+
+/** @name Symlink file creators & types.
+ * @{ */
+#define kSymLinkFileType UINT32_C(0x736c6e6b)
+#define kSymLinkCreator UINT32_C(0x72686170)
+/** @} */
+
+/** @name Name limits.
+ * @{ */
+#define kHFSMaxVolumeNameChars UINT8_C(0x1b)
+#define kHFSMaxFileNameChars UINT8_C(0x1f)
+#define kHFSPlusMaxFileNameChars UINT8_C(0xff)
+#define kHFSMaxAttrNameLen UINT8_C(0x7f)
+/** @} */
+
+/** @name Extent descriptor record densities
+ * @{ */
+#define kHFSExtentDensity UINT8_C(3)
+#define kHFSPlusExtentDensity UINT8_C(8)
+/** @} */
+
+
+/** @name File IDs (various fileID members).
+ * @{ */
+#define kHFSRootParentID UINT32_C(0x00000001)
+#define kHFSRootFolderID UINT32_C(0x00000002)
+#define kHFSExtentsFileID UINT32_C(0x00000003)
+#define kHFSCatalogFileID UINT32_C(0x00000004)
+#define kHFSBadBlockFileID UINT32_C(0x00000005)
+#define kHFSAllocationFileID UINT32_C(0x00000006)
+#define kHFSStartupFileID UINT32_C(0x00000007)
+#define kHFSAttributesFileID UINT32_C(0x00000008)
+#define kHFSAttributeDataFileID UINT32_C(0x0000000c)
+#define kHFSRepairCatalogFileID UINT32_C(0x0000000e)
+#define kHFSBogusExtentFileID UINT32_C(0x0000000f)
+#define kHFSFirstUserCatalogNodeID UINT32_C(0x00000010)
+/** @} */
+
+/** @name Catalog record types.
+ * @{ */
+#define kHFSFolderRecord UINT16_C(0x0100)
+#define kHFSFileRecord UINT16_C(0x0200)
+#define kHFSFolderThreadRecord UINT16_C(0x0300)
+#define kHFSFileThreadRecord UINT16_C(0x0400)
+#define kHFSPlusFolderRecord UINT16_C(0x0001)
+#define kHFSPlusFileRecord UINT16_C(0x0002)
+#define kHFSPlusFolderThreadRecord UINT16_C(0x0003)
+#define kHFSPlusFileThreadRecord UINT16_C(0x0004)
+/** @} */
+
+/** @name File record bits and masks.
+ * @{ */
+#define kHFSFileLockedBit 0
+#define kHFSThreadExistsBit 1
+#define kHFSHasAttributesBit 2
+#define kHFSHasSecurityBit 3
+#define kHFSHasFolderCountBit 4
+#define kHFSHasLinkChainBit 5
+#define kHFSHasChildLinkBit 6
+#define kHFSHasDateAddedBit 7
+
+#define kHFSFileLockedMask RT_BIT(kHFSFileLockedBit)
+#define kHFSThreadExistsMask RT_BIT(kHFSThreadExistsBit)
+#define kHFSHasAttributesMask RT_BIT(kHFSHasAttributesBit)
+#define kHFSHasSecurityMask RT_BIT(kHFSHasSecurityBit)
+#define kHFSHasFolderCountMask RT_BIT(kHFSHasFolderCountBit)
+#define kHFSHasLinkChainMask RT_BIT(kHFSHasLinkChainBit)
+#define kHFSHasChildLinkMask RT_BIT(kHFSHasChildLinkBit)
+#define kHFSHasDateAddedMask RT_BIT(kHFSHasDateAddedBit)
+/** @} */
+
+/** @name Key and node lengths.
+ * @{ */
+#define kHFSPlusAttrKeyMaximumLength ( sizeof(HFSPlusAttrKey) - sizeof(uint16_t) )
+#define kHFSPlusAttrKeyMinimumLength ( kHFSPlusAttrKeyMaximumLength - (kHFSMaxAttrNameLen * sizeof(uint16_t)) )
+#define kHFSPlusExtentKeyMaximumLength ( sizeof(HFSPlusExtentKey) - sizeof(uint16_t),
+#define kHFSExtentKeyMaximumLength ( sizeof(HFSExtentKey) - sizeof(uint8_t) )
+#define kHFSPlusCatalogKeyMaximumLength ( sizeof(HFSPlusCatalogKey) - sizeof(uint16_t) )
+#define kHFSPlusCatalogKeyMinimumLength ( kHFSPlusCatalogKeyMaximumLength - sizeof(HFSUniStr255) + sizeof(uint16_t) )
+#define kHFSCatalogKeyMaximumLength ( sizeof(HFSCatalogKey) - sizeof(uint8_t) )
+#define kHFSCatalogKeyMinimumLength ( kHFSCatalogKeyMaximumLength - kHFSMaxFileNameChars - 1 + sizeof(uint8_t) )
+#define kHFSPlusCatalogMinNodeSize UINT16_C(0x1000)
+#define kHFSPlusExtentMinNodeSize UINT16_C(0x0200)
+#define kHFSPlusAttrMinNodeSize UINT16_C(0x1000)
+/** @} */
+
+/** @name Volume Attribute bits and masks.
+ * @remarks HFS has only 16-bit wide field, HFS+ has 32-bit.
+ * @{ */
+#define kHFSVolumeHardwareLockBit 7
+#define kHFSVolumeUnmountedBit 8
+#define kHFSVolumeSparedBlocksBit 9
+#define kHFSVolumeNoCacheRequiredBit 10
+#define kHFSBootVolumeInconsistentBit 11
+#define kHFSCatalogNodeIDsReusedBit 12
+#define kHFSVolumeJournaledBit 13
+#define kHFSVolumeInconsistentBit 14
+#define kHFSVolumeSoftwareLockBit 15
+#define kHFSUnusedNodeFixBit 31
+#define kHFSContentProtectionBit 30
+
+#define kHFSVolumeHardwareLockMask RT_BIT(kHFSVolumeHardwareLockBit)
+#define kHFSVolumeUnmountedMask RT_BIT(kHFSVolumeUnmountedBit)
+#define kHFSVolumeSparedBlocksMask RT_BIT(kHFSVolumeSparedBlocksBit)
+#define kHFSVolumeNoCacheRequiredMask RT_BIT(kHFSVolumeNoCacheRequiredBit)
+#define kHFSBootVolumeInconsistentMask RT_BIT(kHFSBootVolumeInconsistentBit)
+#define kHFSCatalogNodeIDsReusedMask RT_BIT(kHFSCatalogNodeIDsReusedBit)
+#define kHFSVolumeJournaledMask RT_BIT(kHFSVolumeJournaledBit)
+#define kHFSVolumeInconsistentMask RT_BIT(kHFSVolumeInconsistentBit)
+#define kHFSVolumeSoftwareLockMask RT_BIT(kHFSVolumeSoftwareLockBit)
+#define kHFSUnusedNodeFixMask RT_BIT(kHFSUnusedNodeFixBit)
+#define kHFSContentProtectionMask RT_BIT(kHFSContentProtectionBit)
+
+#define kHFSMDBAttributesMask UINT16_C(0x8380)
+/** @} */
+
+/** @name Misc
+ * @{ */
+#define kHFSUnusedNodesFixDate UINT32_C(0xc5ef2480)
+
+#define HFSPLUSMETADATAFOLDER "\xE2\x90\x80\xE2\x90\x80\xE2\x90\x80\xE2\x90\x80HFS+ Private Data"
+#define HFSPLUS_DIR_METADATA_FOLDER ".HFS+ Private Directory Data\xd"
+#define HFS_INODE_PREFIX "iNode"
+#define HFS_DELETE_PREFIX "temp"
+#define HFS_DIRINODE_PREFIX "dir_"
+#define FIRST_LINK_XATTR_NAME "com.apple.system.hfs.firstlink"
+#define FIRST_LINK_XATTR_REC_SIZE ( sizeof(HFSPlusAttrData) + 10 )
+
+/* {b3e20f39-f292-11d6-97a4-00306543ecac} */
+#define HFS_UUID_NAMESPACE_ID "\xB3\xE2\x0F\x39\xF2\x92\x11\xD6\x97\xA4\x00\x30\x65\x43\xEC\xAC"
+
+#define SET_HFS_TEXT_ENCODING(a_uHint) (UINT32_C(0x656e6300) | (uint8_t)(a_uHint))
+#define GET_HFS_TEXT_ENCODING(a_uHint) ( ((a_uHint) & UINT32_C(0xffffff00)) == UINT32_C(0x656e6300) \
+ ? UINT32_C(0x000000ff)(a_uHint) : UINT32_MAX)
+/** @} */
+
+/** @name B-tree stuff.
+ * @{ */
+#define kMaxKeyLength 520
+
+#define kBTLeafNode (-1)
+#define kBTIndexNode 0
+#define kBTHeaderNode 1
+#define kBTMapNode 2
+
+#define kBTBadCloseMask RT_BIT_32(0)
+#define kBTBigKeysMask RT_BIT_32(1)
+#define kBTVariableIndexKeysMask RT_BIT_32(2)
+
+/** @} */
+
+/** @name B-tree compare types (BTHeaderRec::keyCompareType)
+ * @{ */
+#define kHFSCaseFolding UINT8_C(0xcf)
+#define kHFSBinaryCompare UINT8_C(0xbc)
+/** @} */
+
+/** @name Journal stuff.
+ * @{ */
+#define JIB_RESERVED_SIZE ( sizeof(uint32_t) * 32 - 85 )
+
+#define kJIJournalInFSMask RT_BIT_32(0)
+#define kJIJournalOnOtherDeviceMask RT_BIT_32(1)
+#define kJIJournalNeedInitMask RT_BIT_32(2)
+
+#define EXTJNL_CONTENT_TYPE_UUID "4a6f7572-6e61-11aa-aa11-00306543ecac"
+/** @} */
+
+
+
+typedef struct HFSUniStr255
+{
+ uint16_t length;
+ RTUTF16 unicode[255];
+} HFSUniStr255;
+AssertCompileSize(HFSUniStr255, 0x200);
+typedef const HFSUniStr255 * ConstHFSUniStr255Param;
+
+#pragma pack(1)
+typedef struct HFSExtentKey
+{
+ uint8_t keyLength;
+ uint8_t forkType;
+ uint32_t fileID; /**< Misaligned. */
+ uint16_t startBLock;
+} HFSExtentKey;
+#pragma pack()
+AssertCompileSize(HFSExtentKey, 8);
+
+typedef struct HFSPlusExtentKey
+{
+ uint16_t keyLength;
+ uint8_t forkType;
+ uint8_t pad;
+ uint32_t fileID;
+ uint32_t startBlock;
+} HFSPlusExtentKey;
+AssertCompileSize(HFSPlusExtentKey, 12);
+
+typedef struct HFSExtentDescriptor
+{
+ uint16_t startBlock;
+ uint16_t blockCount;
+} HFSExtentDescriptor;
+AssertCompileSize(HFSExtentDescriptor, 4);
+
+typedef struct HFSPlusExtentDescriptor
+{
+ uint32_t startBlock;
+ uint32_t blockCount;
+} HFSPlusExtentDescriptor;
+AssertCompileSize(HFSPlusExtentDescriptor, 8);
+
+typedef HFSExtentDescriptor HFSExtentRecord[3];
+typedef HFSPlusExtentDescriptor HFSPlusExtentRecord[8];
+
+typedef struct FndrFileInfo
+{
+ uint32_t fdType;
+ uint32_t fdCreator;
+ uint16_t fdFlags;
+ struct
+ {
+ int16_t v;
+ int16_t h;
+ } fdLocation;
+ uint16_t opaque;
+} FndrFileInfo;
+AssertCompileSize(FndrFileInfo, 16);
+
+typedef struct FndrDirInfo
+{
+ struct
+ {
+ int16_t top;
+ int16_t left;
+ int16_t bottom;
+ int16_t right;
+ } frRect;
+ uint16_t frFlags;
+ struct
+ {
+ int16_t v;
+ int16_t h;
+ } fdLocation;
+ uint16_t opaque;
+} FndrDirInfo;
+AssertCompileSize(FndrDirInfo, 16);
+
+typedef struct FndrOpaqueInfo
+{
+ int8_t opaque[16];
+} FndrOpaqueInfo;
+AssertCompileSize(FndrOpaqueInfo, 16);
+
+typedef struct FndrExtendedFileInfo
+{
+ uint32_t reserved1;
+ uint32_t date_added;
+ uint16_t extended_flags;
+ uint16_t reserved2;
+ uint32_t reserved3;
+} FndrExtendedFileInfo;
+AssertCompileSize(FndrExtendedFileInfo, 16);
+
+typedef struct FndrExtendedDirInfo
+{
+ uint32_t point;
+ uint32_t date_added;
+ uint16_t extended_flags;
+ uint16_t reserved3;
+ uint32_t reserved4;
+} FndrExtendedDirInfo;
+AssertCompileSize(FndrExtendedDirInfo, 16);
+
+typedef struct HFSPlusForkData
+{
+ uint64_t logicalSize;
+ uint32_t clumpSize;
+ uint32_t totalBlocks;
+ HFSPlusExtentRecord extents;
+} HFSPlusForkData;
+AssertCompileSize(HFSPlusForkData, 80);
+
+typedef struct HFSPlusBSDInfo
+{
+ uint32_t ownerID;
+ uint32_t groupID;
+ uint8_t adminFlags;
+ uint8_t ownerFlags;
+ uint16_t fileMode;
+ union
+ {
+ uint32_t iNodeNum;
+ uint32_t linkCount;
+ uint32_t rawDevice;
+ } special;
+} HFSPlusBSDInfo;
+AssertCompileSize(HFSPlusBSDInfo, 16);
+
+#pragma pack(1)
+typedef struct HFSCatalogKey
+{
+ uint8_t keyLength;
+ uint8_t reserved;
+ uint32_t parentID; /**< Misaligned. */
+ uint8_t nodeName[kHFSMaxFileNameChars + 1];
+} HFSCatalogKey;
+#pragma pack()
+AssertCompileSize(HFSCatalogKey, 0x26);
+
+#pragma pack(1)
+typedef struct HFSPlusCatalogKey
+{
+ uint16_t keyLength;
+ uint32_t parentID; /**< Misaligned. */
+ HFSUniStr255 nodeName;
+} HFSPlusCatalogKey;
+#pragma pack()
+AssertCompileSize(HFSPlusCatalogKey, 0x206);
+
+#pragma pack(1)
+typedef struct HFSCatalogFolder
+{
+ int16_t recordType;
+ uint16_t flags;
+ uint16_t valence;
+ uint32_t folderID; /**< Misaligned. */
+ uint32_t createDate; /**< Misaligned. */
+ uint32_t modifyDate; /**< Misaligned. */
+ uint32_t backupDate; /**< Misaligned. */
+ FndrDirInfo userInfo;
+ FndrOpaqueInfo finderInfo;
+ uint32_t reserved[4]; /**< Misaligned. */
+} HFSCatalogFolder;
+#pragma pack()
+AssertCompileSize(HFSCatalogFolder, 70);
+
+typedef struct HFSPlusCatalogFolder
+{
+ int16_t recordType;
+ uint16_t flags;
+ uint32_t valence;
+ uint32_t folderID;
+ uint32_t createDate;
+ uint32_t contentModDate;
+ uint32_t attributeModDate;
+ uint32_t accessDate;
+ uint32_t backupDate;
+ HFSPlusBSDInfo bsdInfo;
+ FndrDirInfo userInfo;
+ FndrOpaqueInfo finderInfo;
+ uint32_t textEncoding;
+ uint32_t folderCount;
+} HFSPlusCatalogFolder;
+AssertCompileSize(HFSPlusCatalogFolder, 88);
+
+#pragma pack(1)
+typedef struct HFSCatalogFile
+{
+ int16_t recordType;
+ uint8_t flags;
+ uint8_t fileType;
+ FndrFileInfo userInfo;
+ uint32_t fileID;
+ uint16_t dataStartBlock;
+ int32_t dataLogicalSize; /**< Misaligned. */
+ int32_t dataPhysicalSize; /**< Misaligned. */
+ uint16_t rsrcStartBlock;
+ int32_t rsrcLogicalSize;
+ int32_t rsrcPhysicalSize;
+ uint32_t createDate;
+ uint32_t modifyDate;
+ uint32_t backupDate;
+ FndrOpaqueInfo finderInfo;
+ uint16_t clumpSize;
+ HFSExtentRecord dataExtents; /**< Misaligned. */
+ HFSExtentRecord rsrcExtents; /**< Misaligned. */
+ uint32_t reserved; /**< Misaligned. */
+} HFSCatalogFile;
+#pragma pack()
+AssertCompileSize(HFSCatalogFile, 102);
+
+#pragma pack(1)
+typedef struct HFSPlusCatalogFile
+{
+ int16_t recordType;
+ uint16_t flags;
+ uint32_t reserved1;
+ uint32_t fileID;
+ uint32_t createDate;
+ uint32_t contentModDate;
+ uint32_t attributeModDate;
+ uint32_t accessDate;
+ uint32_t backupDate;
+ HFSPlusBSDInfo bsdInfo;
+ FndrFileInfo userInfo;
+ FndrOpaqueInfo finderInfo;
+ uint32_t textEncoding;
+ uint32_t reserved2;
+ HFSPlusForkData dataFork;
+ HFSPlusForkData resourceFork;
+} HFSPlusCatalogFile;
+#pragma pack()
+AssertCompileMemberAlignment(HFSPlusCatalogFile, dataFork, 8);
+AssertCompileSize(HFSPlusCatalogFile, 248);
+
+#pragma pack(1)
+typedef struct HFSCatalogThread
+{
+ int16_t recordType;
+ int32_t reserved[2];
+ uint32_t parentID;
+ uint8_t nodeName[kHFSMaxFileNameChars + 1];
+} HFSCatalogThread;
+#pragma pack()
+AssertCompileSize(HFSCatalogThread, 46);
+
+typedef struct HFSPlusCatalogThread
+{
+ int16_t recordType;
+ int16_t reserved;
+ uint32_t parentID;
+ HFSUniStr255 nodeName;
+} HFSPlusCatalogThread;
+AssertCompileSize(HFSPlusCatalogThread, 0x208);
+
+typedef struct HFSPlusAttrForkData
+{
+ uint32_t recordType;
+ uint32_t reserved;
+ HFSPlusForkData theFork;
+} HFSPlusAttrForkData;
+AssertCompileSize(HFSPlusAttrForkData, 88);
+
+typedef struct HFSPlusAttrExtents
+{
+ uint32_t recordType;
+ uint32_t reserved;
+ HFSPlusExtentRecord extents;
+} HFSPlusAttrExtents;
+AssertCompileSize(HFSPlusAttrExtents, 72);
+
+#pragma pack(1)
+typedef struct HFSPlusAttrData
+{
+ uint32_t recordType;
+ uint32_t reserved[2];
+ uint32_t attrSize;
+ uint8_t attrData[2]; /**< Causes misaligned struct size. */
+} HFSPlusAttrData;
+#pragma pack()
+AssertCompileSize(HFSPlusAttrData, 18);
+
+#pragma pack(1)
+typedef struct HFSPlusAttrInlineData
+{
+ uint32_t recordType;
+ uint32_t reserved;
+ uint32_t logicalSize;
+ uint8_t userData[2]; /**< Causes misaligned struct size. */
+} HFSPlusAttrInlineData;
+#pragma pack()
+AssertCompileSize(HFSPlusAttrInlineData, 14);
+
+typedef union HFSPlusAttrRecord
+{
+ uint32_t recordType;
+ HFSPlusAttrInlineData inlineData;
+ HFSPlusAttrData attrData;
+ HFSPlusAttrForkData forkData;
+ HFSPlusAttrExtents overflowExtents;
+} HFSPlusAttrRecord;
+AssertCompileSize(HFSPlusAttrRecord, 88);
+
+typedef struct HFSPlusAttrKey
+{
+ uint16_t keyLength;
+ uint16_t pad;
+ uint32_t fileID;
+ uint32_t startBlock;
+ uint16_t attrNameLen;
+ RTUTF16 attrName[kHFSMaxAttrNameLen];
+} HFSPlusAttrKey;
+AssertCompileSize(HFSPlusAttrKey, 268);
+
+#pragma pack(1)
+typedef struct HFSMasterDirectoryBlock
+{
+ uint16_t drSigWord;
+ uint32_t drCrDate; /**< Misaligned. */
+ uint32_t drLsMod; /**< Misaligned. */
+ uint16_t drAtrb;
+ uint16_t drNmFls;
+ uint16_t drVBMSt;
+ uint16_t drAllocPtr;
+ uint16_t drNmAlBlks;
+ uint32_t drAlBlkSiz;
+ uint32_t drClpSiz;
+ uint16_t drAlBlSt;
+ uint32_t drNxCNID; /**< Misaligned. */
+ uint16_t drFreeBks;
+ uint8_t drVN[kHFSMaxVolumeNameChars + 1];
+ uint32_t drVolBkUp;
+ uint16_t drVSeqNum;
+ uint32_t drWrCnt; /**< Misaligned. */
+ uint32_t drXTClpSiz; /**< Misaligned. */
+ uint32_t drCTClpSiz; /**< Misaligned. */
+ uint16_t drNmRtDirs;
+ uint32_t drFilCnt;
+ uint32_t drDirCnt;
+ uint32_t drFndrInfo[8];
+ uint16_t drEmbedSigWord;
+ HFSExtentDescriptor drEmbedExtent;
+ uint32_t drXTFlSize; /**< Misaligned. */
+ HFSExtentRecord drXTExtRec;
+ uint32_t drCTFlSize; /**< Misaligned. */
+ HFSExtentRecord drCTExtRec;
+} HFSMasterDirectoryBlock;
+#pragma pack()
+AssertCompileSize(HFSMasterDirectoryBlock, 162);
+
+typedef struct HFSPlusVolumeHeader
+{
+ uint16_t signature;
+ uint16_t version;
+ uint32_t attributes;
+ uint32_t lastMountedVersion;
+ uint32_t journalInfoBlock;
+ uint32_t createDate;
+ uint32_t modifyDate;
+ uint32_t backupDate;
+ uint32_t checkedDate;
+ uint32_t fileCount;
+ uint32_t folderCount;
+ uint32_t blockSize;
+ uint32_t totalBlocks;
+ uint32_t freeBlocks;
+ uint32_t nextAllocation;
+ uint32_t rsrcClumpSize;
+ uint32_t dataClumpSize;
+ uint32_t nextCatalogID;
+ uint32_t writeCount;
+ uint64_t encodingsBitmap;
+ uint8_t finderInfo[32];
+ HFSPlusForkData allocationFile;
+ HFSPlusForkData extentsFile;
+ HFSPlusForkData catalogFile;
+ HFSPlusForkData attributesFile;
+ HFSPlusForkData startupFile;
+} HFSPlusVolumeHeader;
+AssertCompileMemberAlignment(HFSPlusVolumeHeader, nextCatalogID, 8);
+AssertCompileSize(HFSPlusVolumeHeader, 512);
+
+typedef union BTreeKey
+{
+ uint8_t length8;
+ uint16_t length16;
+ uint8_t rawData[kMaxKeyLength + 2];
+} BTreeKey;
+AssertCompileSize(BTreeKey, 522);
+
+#pragma pack(1)
+typedef struct BTNodeDescriptor
+{
+ uint32_t fLink;
+ uint32_t bLink;
+ int8_t kind;
+ uint8_t height;
+ uint16_t numRecords;
+ uint16_t reserved; /**< Causes struct size misalignment. */
+} BTNodeDescriptor;
+#pragma pack()
+AssertCompileSize(BTNodeDescriptor, 14);
+
+#pragma pack(1)
+typedef struct BTHeaderRec
+{
+ uint16_t treeDepth;
+ uint32_t rootNode; /**< Misaligned. */
+ uint32_t leafRecords; /**< Misaligned. */
+ uint32_t firstLeafNode; /**< Misaligned. */
+ uint32_t lastLeafNode; /**< Misaligned. */
+ uint16_t nodeSize;
+ uint16_t maxKeyLength;
+ uint32_t totalNodes; /**< Misaligned. */
+ uint32_t freeNodes; /**< Misaligned. */
+ uint16_t reserved1;
+ uint32_t clumpSize;
+ uint8_t btreeType;
+ uint8_t keyCompareType;
+ uint32_t attributes; /**< Misaligned. */
+ uint32_t reserved3[16]; /**< Misaligned. */
+} BTHeaderRec;
+#pragma pack()
+AssertCompileSize(BTHeaderRec, 106);
+
+#pragma pack(1)
+typedef struct JournalInfoBlock
+{
+ uint32_t flags;
+ uint32_t devices_signature[8];
+ uint64_t offset; /**< Misaligned (morons). */
+ uint64_t size; /**< Misaligned. */
+ char ext_jnl_uuid[37];
+ char machine_serial_num[48];
+ char reserved[JIB_RESERVED_SIZE];
+} JournalInfoBlock;
+#pragma pack()
+AssertCompileSize(JournalInfoBlock, 180);
+
+/** @} */
+
+#endif /* !IPRT_INCLUDED_formats_hfs_h */
+
diff --git a/include/iprt/formats/iso9660.h b/include/iprt/formats/iso9660.h
new file mode 100644
index 00000000..6b3e7192
--- /dev/null
+++ b/include/iprt/formats/iso9660.h
@@ -0,0 +1,1516 @@
+/* $Id: iso9660.h $ */
+/** @file
+ * IPRT, ISO 9660 File System
+ */
+
+/*
+ * Copyright (C) 2017-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_formats_iso9660_h
+#define IPRT_INCLUDED_formats_iso9660_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+#include <iprt/assertcompile.h>
+
+
+/** @defgroup grp_rt_formats_iso9660 ISO 9660 structures and definitions
+ * @ingroup grp_rt_formats
+ * @{
+ */
+
+
+/** The (default) logical sectors size of ISO 9660. */
+#define ISO9660_SECTOR_SIZE 2048
+/** The (default) sector offset mask of ISO 9660. */
+#define ISO9660_SECTOR_OFFSET_MASK 2047
+/** Maximum filename length (level 2 & 3). */
+#define ISO9660_MAX_NAME_LEN 30
+
+
+/** Accessor for ISO9660U16 and ISO9660U32 that retrievs the member value for
+ * the host endianess. */
+#ifdef RT_BIG_ENDIAN
+# define ISO9660_GET_ENDIAN(a_pInt) ((a_pInt)->be)
+#else
+# define ISO9660_GET_ENDIAN(a_pInt) ((a_pInt)->le)
+#endif
+
+
+/**
+ * ISO 9660 16-bit unsigned integer type.
+ */
+typedef struct ISO9660U16
+{
+ /** Little endian. */
+ uint16_t le;
+ /** Big endian. */
+ uint16_t be;
+} ISO9660U16;
+/** Pointer to an ISO 9660 16-bit unsigned integer type. */
+typedef ISO9660U16 *PISO9660U16;
+/** Pointer to a const ISO 9660 16-bit unsigned integer type. */
+typedef ISO9660U16 const *PCISO9660U16;
+
+/** ISO 9660 big endian 16-bit unsigned integer. */
+typedef uint16_t ISO9660U16BE;
+
+
+/**
+ * ISO 9660 32-bit unsigned integer type.
+ */
+typedef struct ISO9660U32
+{
+ /** Little endian. */
+ uint32_t le;
+ /** Big endian. */
+ uint32_t be;
+} ISO9660U32;
+/** Pointer to an ISO 9660 32-bit unsigned integer type. */
+typedef ISO9660U32 *PISO9660U32;
+/** Pointer to a const ISO 9660 32-bit unsigned integer type. */
+typedef ISO9660U32 const *PCISO9660U32;
+
+/** ISO 9660 little endian 32-bit unsigned integer. */
+typedef uint32_t ISO9660U32LE;
+/** ISO 9660 big endian 32-bit unsigned integer. */
+typedef uint32_t ISO9660U32BE;
+
+/**
+ * ISO 9660 timestamp (date & time).
+ */
+typedef struct ISO9660TIMESTAMP
+{
+ /** 0x00: For digit year (0001-9999). */
+ char achYear[4];
+ /** 0x04: Month of the year (01-12). */
+ char achMonth[2];
+ /** 0x06: Day of month (01-31). */
+ char achDay[2];
+ /** 0x08: Hour of day (00-23). */
+ char achHour[2];
+ /** 0x0a: Minute of hour (00-59). */
+ char achMinute[2];
+ /** 0x0c: Second of minute (00-59). */
+ char achSecond[2];
+ /** 0x0e: Hundreth of second (00-99). */
+ char achCentisecond[2];
+ /** 0x10: The UTC (GMT) offset in 15 min units. */
+ int8_t offUtc;
+} ISO9660TIMESTAMP;
+AssertCompileSize(ISO9660TIMESTAMP, 17);
+/** Pointer to an ISO 9660 timestamp. */
+typedef ISO9660TIMESTAMP *PISO9660TIMESTAMP;
+/** Pointer to a const ISO 9660 timestamp. */
+typedef ISO9660TIMESTAMP const *PCISO9660TIMESTAMP;
+
+/**
+ * ISO 9660 record timestamp (date & time).
+ */
+typedef struct ISO9660RECTIMESTAMP
+{
+ /** 0: Years since 1900. */
+ uint8_t bYear;
+ /** 1: Month of year (1-12). */
+ uint8_t bMonth;
+ /** 2: Day of month (1-31). */
+ uint8_t bDay;
+ /** 3: Hour of day (0-23). */
+ uint8_t bHour;
+ /** 4: Minute of hour (0-59). */
+ uint8_t bMinute;
+ /** 5: Second of minute (0-59). */
+ uint8_t bSecond;
+ /** 6: The UTC (GMT) offset in 15 min units. */
+ int8_t offUtc;
+} ISO9660RECTIMESTAMP;
+AssertCompileSize(ISO9660RECTIMESTAMP, 7);
+/** Pointer to an ISO 9660 record timestamp. */
+typedef ISO9660RECTIMESTAMP *PISO9660RECTIMESTAMP;
+/** Pointer to a const ISO 9660 record timestamp. */
+typedef ISO9660RECTIMESTAMP const *PCISO9660RECTIMESTAMP;
+
+
+/**
+ * ISO 9660 directory record.
+ */
+#pragma pack(1)
+typedef struct ISO9660DIRREC
+{
+ /** 0x00: Length of this record in bytes. */
+ uint8_t cbDirRec;
+ /** 0x01: Extended attribute record length in logical blocks. */
+ uint8_t cExtAttrBlocks;
+ /** 0x02: Location of extent (logical block number).
+ * @note Misaligned. */
+ ISO9660U32 offExtent;
+ /** 0x0a: Size of the data (file section). Does not include EAs.
+ * @note Misaligned. */
+ ISO9660U32 cbData;
+ /** 0x12: Recording time and date. */
+ ISO9660RECTIMESTAMP RecTime;
+ /** 0x19: File flags (ISO9660_FILE_FLAGS_XXX). */
+ uint8_t fFileFlags;
+ /** 0x1a: File unit size for interlaved mode. */
+ uint8_t bFileUnitSize;
+ /** 0x1b: Interlave gap size. */
+ uint8_t bInterleaveGapSize;
+ /** 0x1c: Volume sequence number where the extent resides. */
+ ISO9660U16 VolumeSeqNo;
+ /** 0x20: Length of file identifier field. */
+ uint8_t bFileIdLength;
+ /** 0x21: File identifier (d-characters or d1-characters). */
+ char achFileId[1];
+ /* There are more fields following:
+ * - one byte optional padding so the following field is at an even boundrary.
+ * - system use field until cbDirRec is reached.
+ */
+} ISO9660DIRREC;
+#pragma pack()
+AssertCompileMemberOffset(ISO9660DIRREC, offExtent, 0x02);
+AssertCompileMemberOffset(ISO9660DIRREC, cbData, 0x0a);
+AssertCompileMemberOffset(ISO9660DIRREC, RecTime, 0x12);
+AssertCompileMemberOffset(ISO9660DIRREC, fFileFlags, 0x19);
+AssertCompileMemberOffset(ISO9660DIRREC, bFileIdLength, 0x20);
+AssertCompileMemberOffset(ISO9660DIRREC, achFileId, 0x21);
+/** Pointer to an ISO 9660 directory record. */
+typedef ISO9660DIRREC *PISO9660DIRREC;
+/** Pointer to a const ISO 9660 directory record. */
+typedef ISO9660DIRREC const *PCISO9660DIRREC;
+
+/** @name ISO9660_FILE_FLAGS_XXX
+ * @{ */
+/** Existence - Hide the file from the user. */
+#define ISO9660_FILE_FLAGS_HIDDEN UINT8_C(0x01)
+/** Directory - Indicates a directory as apposed to a regular file (0). */
+#define ISO9660_FILE_FLAGS_DIRECTORY UINT8_C(0x02)
+/** Assocated File - Indicates that the file is an associated file. */
+#define ISO9660_FILE_FLAGS_ASSOCIATED_FILE UINT8_C(0x04)
+/** Record - Indicates specified file content record format (see EAs). */
+#define ISO9660_FILE_FLAGS_RECORD UINT8_C(0x08)
+/** Protection - Indicates owner/group or permission protection in EAs. */
+#define ISO9660_FILE_FLAGS_PROTECTION UINT8_C(0x10)
+/** Reserved bit, MBZ. */
+#define ISO9660_FILE_FLAGS_RESERVED_5 UINT8_C(0x20)
+/** Reserved bit, MBZ. */
+#define ISO9660_FILE_FLAGS_RESERVED_6 UINT8_C(0x40)
+/** Multi-extend - Indicates that this isn't the final record for the file.
+ * @remarks Use for working around 4 GiB file size limitation. */
+#define ISO9660_FILE_FLAGS_MULTI_EXTENT UINT8_C(0x80)
+/** @} */
+
+
+/**
+ * ISO 9660 path table record.
+ */
+#pragma pack(1)
+typedef struct ISO9660PATHREC
+{
+ /** 0x00: Length of the achDirId field in bytes. */
+ uint8_t cbDirId;
+ /** 0x01: Extended attribute record length in bytes? */
+ uint8_t cbExtAttr;
+ /** 0x02: Location of extent (logical block number).
+ * @note Endianess depends on table.
+ * @note Misaligned. */
+ uint32_t offExtent;
+ /** 0x06: Parent directory number.
+ * @note Endianess depends on table. */
+ uint16_t idParentRec;
+ /** 0x08: Directory identifier (d-characters or d1-characters). */
+ RT_FLEXIBLE_ARRAY_EXTENSION
+ char achDirId[RT_FLEXIBLE_ARRAY];
+ /* There will be a zero padding byte following if the directory identifier length is odd. */
+} ISO9660PATHREC;
+#pragma pack()
+AssertCompileMemberOffset(ISO9660PATHREC, cbExtAttr, 0x01);
+AssertCompileMemberOffset(ISO9660PATHREC, offExtent, 0x02);
+AssertCompileMemberOffset(ISO9660PATHREC, idParentRec, 0x06);
+AssertCompileMemberOffset(ISO9660PATHREC, achDirId, 0x08);
+/** Pointer to an ISO 9660 path table record. */
+typedef ISO9660PATHREC *PISO9660PATHREC;
+/** Pointer to a const ISO 9660 path table record. */
+typedef ISO9660PATHREC const *PCISO9660PATHREC;
+
+
+/**
+ * ISO 9660 extended attribute record.
+ */
+typedef struct ISO9660EXATTRREC
+{
+ /** 0x000: The owner ID. */
+ ISO9660U16 idOwner;
+ /** 0x004: The group ID. */
+ ISO9660U16 idGroup;
+ /** 0x008: File permissions (ISO9660_PERM_XXX). */
+ ISO9660U16BE fPermissions;
+ /** 0x00a: File creation timestamp. */
+ ISO9660TIMESTAMP BirthTimestamp;
+ /** 0x01b: File modification timestamp. */
+ ISO9660TIMESTAMP ModifyTimestamp;
+ /** 0x02c: File expiration timestamp. */
+ ISO9660TIMESTAMP ExpireTimestamp;
+ /** 0x03d: File effective timestamp. */
+ ISO9660TIMESTAMP EffectiveTimestamp;
+ /** 0x04e: Record format. */
+ uint8_t bRecordFormat;
+ /** 0x04f: Record attributes. */
+ uint8_t fRecordAttrib;
+ /** 0x050: Record length. */
+ ISO9660U16 RecordLength;
+ /** 0x054: System identifier (a-characters or a1-characters). */
+ char achSystemId[0x20];
+ /** 0x074: System specific bytes. */
+ uint8_t abSystemUse[64];
+ /** 0x0b4: Extended attribute record version (ISO9660EXATTRREC_VERSION). */
+ uint8_t bExtRecVersion;
+ /** 0x0b5: Length of escape sequences. */
+ uint8_t cbEscapeSequences;
+ /** 0x0b6: Reserved for the future, MBZ. */
+ uint8_t abReserved183[64];
+ /** 0x0f6: Length of the application use field. */
+ ISO9660U16 cbAppUse;
+ /** 0x0fa: Variable sized application use field. */
+ RT_FLEXIBLE_ARRAY_EXTENSION
+ uint8_t abAppUse[RT_FLEXIBLE_ARRAY];
+ /* This is followed by escape sequences with length given by cbEscapeSequnces. */
+} ISO9660EXATTRREC;
+AssertCompileMemberOffset(ISO9660EXATTRREC, EffectiveTimestamp, 0x03d);
+AssertCompileMemberOffset(ISO9660EXATTRREC, cbAppUse, 0x0f6);
+
+/** The ISO9660EXATTRREC::bExtRecVersion value. */
+#define ISO9660EXATTRREC_VERSION UINT8_C(0x01)
+
+/** @name ISO9660_PERM_XXX - ISO9660EXATTRREC::fPermissions
+ * @{ */
+/** @todo figure out this weird permission stuff... */
+/** @} */
+
+
+/**
+ * ISO 9660 volume descriptor header.
+ */
+typedef struct ISO9660VOLDESCHDR
+{
+ /** Descriptor type ISO9660VOLDESC_TYPE_XXX. */
+ uint8_t bDescType;
+ /** Standard identifier 'CD001' */
+ uint8_t achStdId[5];
+ /** The descriptor version. */
+ uint8_t bDescVersion;
+ /* (This is followed by the descriptor specific data). */
+} ISO9660VOLDESCHDR;
+AssertCompileSize(ISO9660VOLDESCHDR, 7);
+/** Pointer to a volume descriptor header. */
+typedef ISO9660VOLDESCHDR *PISO9660VOLDESCHDR;
+/** Pointer to a const volume descriptor header. */
+typedef ISO9660VOLDESCHDR const *PCISO9660VOLDESCHDR;
+
+/** @name ISO9660VOLDESC_TYPE_XXX - volume descriptor types
+ * @{ */
+/** See ISO9660BOOTRECORD. */
+#define ISO9660VOLDESC_TYPE_BOOT_RECORD UINT8_C(0x00)
+/** See ISO9660PRIMARYVOLDESC. */
+#define ISO9660VOLDESC_TYPE_PRIMARY UINT8_C(0x01)
+/** See ISO9660SUPVOLDESC. */
+#define ISO9660VOLDESC_TYPE_SUPPLEMENTARY UINT8_C(0x02)
+/** See ISO9660VOLPARTDESC. */
+#define ISO9660VOLDESC_TYPE_PARTITION UINT8_C(0x03)
+/** Terminates the volume descriptor set. Has no data (zeros), version is 1. */
+#define ISO9660VOLDESC_TYPE_TERMINATOR UINT8_C(0xff)
+/** @} */
+
+/** The value of ISO9660VOLDESCHDR::achStdId */
+#define ISO9660VOLDESC_STD_ID "CD001"
+#define ISO9660VOLDESC_STD_ID_0 'C'
+#define ISO9660VOLDESC_STD_ID_1 'D'
+#define ISO9660VOLDESC_STD_ID_2 '0'
+#define ISO9660VOLDESC_STD_ID_3 '0'
+#define ISO9660VOLDESC_STD_ID_4 '1'
+
+
+
+/**
+ * ISO 9660 boot record (volume descriptor).
+ */
+typedef struct ISO9660BOOTRECORD
+{
+ /** The volume descriptor header.
+ * Type is ISO9660VOLDESC_TYPE_BOOT_RECORD and version
+ * ISO9660BOOTRECORD_VERSION. */
+ ISO9660VOLDESCHDR Hdr;
+ /** Boot system identifier string (a-characters). */
+ char achBootSystemId[32];
+ /** Boot identifier (a-characters). */
+ char achBootId[32];
+ /** Boot system specific content. */
+ uint8_t abBootSystemSpecific[1977];
+} ISO9660BOOTRECORD;
+AssertCompileSize(ISO9660BOOTRECORD, ISO9660_SECTOR_SIZE);
+/** Pointer to an ISO 9660 boot record. */
+typedef ISO9660BOOTRECORD *PISO9660BOOTRECORD;
+/** Pointer to a const ISO 9660 boot record. */
+typedef ISO9660BOOTRECORD const *PCISO9660BOOTRECORD;
+
+/** The value of ISO9660BOOTRECORD::Hdr.uDescVersion. */
+#define ISO9660BOOTRECORD_VERSION UINT8_C(1)
+
+
+/**
+ * ISO 9660 boot record (volume descriptor), El Torito variant.
+ */
+#pragma pack(1)
+typedef struct ISO9660BOOTRECORDELTORITO
+{
+ /** 0x000: The volume descriptor header.
+ * Type is ISO9660VOLDESC_TYPE_BOOT_RECORD and version
+ * ISO9660BOOTRECORD_VERSION. */
+ ISO9660VOLDESCHDR Hdr;
+ /** 0x007: Boot system identifier string,
+ * zero padded ISO9660BOOTRECORDELTORITO_BOOT_SYSTEM_ID. */
+ char achBootSystemId[32];
+ /** 0x027: Boot identifier - all zeros. */
+ char achBootId[32];
+ /** 0x047: Boot catalog location (block offset), always (?) little endian.
+ * @note Misaligned. */
+ uint32_t offBootCatalog;
+ /** 0x04b: Unused - all zeros. */
+ uint8_t abBootSystemSpecific[1973];
+} ISO9660BOOTRECORDELTORITO;
+#pragma pack()
+AssertCompileSize(ISO9660BOOTRECORDELTORITO, ISO9660_SECTOR_SIZE);
+/** Pointer to an ISO 9660 El Torito boot record. */
+typedef ISO9660BOOTRECORDELTORITO *PISO9660BOOTRECORDELTORITO;
+/** Pointer to a const ISO 9660 El Torito boot record. */
+typedef ISO9660BOOTRECORDELTORITO const *PCISO9660BOOTRECORDELTORITO;
+
+/** The value of ISO9660BOOTRECORDELTORITO::achBootSystemId (zero padded). */
+#define ISO9660BOOTRECORDELTORITO_BOOT_SYSTEM_ID "EL TORITO SPECIFICATION"
+
+
+/**
+ * ISO 9660 primary volume descriptor.
+ */
+typedef struct ISO9660PRIMARYVOLDESC
+{
+ /** 0x000: The volume descriptor header.
+ * Type is ISO9660VOLDESC_TYPE_PRIMARY and version
+ * ISO9660PRIMARYVOLDESC_VERSION. */
+ ISO9660VOLDESCHDR Hdr;
+ /** 0x007: Explicit alignment zero padding. */
+ uint8_t bPadding8;
+ /** 0x008: System identifier (a-characters). */
+ char achSystemId[32];
+ /** 0x028: Volume identifier (d-characters). */
+ char achVolumeId[32];
+ /** 0x048: Unused field, zero filled. */
+ ISO9660U32 Unused73;
+ /** 0x050: Volume space size in logical blocks (cbLogicalBlock). */
+ ISO9660U32 VolumeSpaceSize;
+ /** 0x058: Unused field(s), zero filled. */
+ uint8_t abUnused89[32];
+ /** 0x078: The number of volumes in the volume set. */
+ ISO9660U16 cVolumesInSet;
+ /** 0x07c: Volume sequence number. */
+ ISO9660U16 VolumeSeqNo;
+ /** 0x080: Logical block size in bytes. */
+ ISO9660U16 cbLogicalBlock;
+ /** 0x084: Path table size. */
+ ISO9660U32 cbPathTable;
+ /** 0x08c: Type L(ittle endian) path table location (block offset). */
+ ISO9660U32LE offTypeLPathTable;
+ /** 0x090: Optional type L(ittle endian) path table location (block offset). */
+ ISO9660U32LE offOptionalTypeLPathTable;
+ /** 0x094: Type M (big endian) path table location (block offset). */
+ ISO9660U32BE offTypeMPathTable;
+ /** 0x098: Optional type M (big endian) path table location (block offset). */
+ ISO9660U32BE offOptionalTypeMPathTable;
+ /** 0x09c: Directory entry for the root directory (union). */
+ union
+ {
+ uint8_t ab[34];
+ ISO9660DIRREC DirRec;
+ } RootDir;
+ /** 0x0be: Volume set identifier (d-characters). */
+ char achVolumeSetId[128];
+ /** 0x13e: Publisher identifier (a-characters). Alternatively, it may refere to
+ * a file in the root dir if it starts with 0x5f and restricts itself to 8
+ * d-characters. */
+ char achPublisherId[128];
+ /** 0x1be: Data preparer identifier (a-characters).
+ * Same file reference alternative as previous field. */
+ char achDataPreparerId[128];
+ /** 0x23e: Application identifier (a-characters).
+ * Same file reference alternative as previous field. */
+ char achApplicationId[128];
+ /** 0x2be: Copyright (root) file identifier (d-characters).
+ * All spaces if none. */
+ char achCopyrightFileId[37];
+ /** 0x2e3: Abstract (root) file identifier (d-characters).
+ * All spaces if none. */
+ char achAbstractFileId[37];
+ /** 0x308: Bibliographic file identifier (d-characters).
+ * All spaces if none. */
+ char achBibliographicFileId[37];
+ /** 0x32d: Volume creation date and time. */
+ ISO9660TIMESTAMP BirthTime;
+ /** 0x33e: Volume modification date and time. */
+ ISO9660TIMESTAMP ModifyTime;
+ /** 0x34f: Volume (data) expiration date and time.
+ * If not specified, don't regard data as obsolete. */
+ ISO9660TIMESTAMP ExpireTime;
+ /** 0x360: Volume (data) effective date and time.
+ * If not specified, info can be used immediately. */
+ ISO9660TIMESTAMP EffectiveTime;
+ /** 0x371: File structure version (ISO9660_FILE_STRUCTURE_VERSION). */
+ uint8_t bFileStructureVersion;
+ /** 0x372: Reserve for future, MBZ. */
+ uint8_t bReserved883;
+ /** 0x373: Reserve for future.
+ * mkisofs & genisoimage & libisofs seems to space pad this most of the time.
+ * Microsoft image (2.56) zero pads it. isomd5sum uses it to store checksum
+ * info for the iso and space pads it. */
+ uint8_t abAppUse[512];
+ /** 0x573: Reserved for future standardization, MBZ. */
+ uint8_t abReserved1396[653];
+} ISO9660PRIMARYVOLDESC;
+AssertCompileSize(ISO9660PRIMARYVOLDESC, ISO9660_SECTOR_SIZE);
+/** Pointer to a ISO 9660 primary volume descriptor. */
+typedef ISO9660PRIMARYVOLDESC *PISO9660PRIMARYVOLDESC;
+/** Pointer to a const ISO 9660 primary volume descriptor. */
+typedef ISO9660PRIMARYVOLDESC const *PCISO9660PRIMARYVOLDESC;
+
+/** The value of ISO9660PRIMARYVOLDESC::Hdr.uDescVersion. */
+#define ISO9660PRIMARYVOLDESC_VERSION UINT8_C(1)
+/** The value of ISO9660PRIMARYVOLDESC::bFileStructureVersion and
+ * ISO9660SUPVOLDESC::bFileStructureVersion. */
+#define ISO9660_FILE_STRUCTURE_VERSION UINT8_C(1)
+
+
+
+/**
+ * ISO 9660 supplementary volume descriptor.
+ *
+ * This is in the large parts identicial to the primary descriptor, except it
+ * have a few more fields where the primary one has reserved spaces.
+ */
+typedef struct ISO9660SUPVOLDESC
+{
+ /** 0x000: The volume descriptor header.
+ * Type is ISO9660VOLDESC_TYPE_SUPPLEMENTARY and version
+ * ISO9660SUPVOLDESC_VERSION. */
+ ISO9660VOLDESCHDR Hdr;
+ /** 0x007: Volume flags (ISO9660SUPVOLDESC_VOL_F_XXX).
+ * @note This is reserved in the primary volume descriptor. */
+ uint8_t fVolumeFlags;
+ /** 0x008: System identifier (a1-characters) of system that can act upon
+ * sectors 0 thru 15.
+ * @note Purpose differs from primary description. */
+ char achSystemId[32];
+ /** 0x028: Volume identifier (d1-characters).
+ * @note Character set differs from primary description. */
+ char achVolumeId[32];
+ /** 0x048: Unused field, zero filled. */
+ ISO9660U32 Unused73;
+ /** 0x050: Volume space size in logical blocks (cbLogicalBlock). */
+ ISO9660U32 VolumeSpaceSize;
+ /** 0x058: Escape sequences.
+ * Complicated stuff, see ISO 2022 and ECMA-35.
+ * @note This is reserved in the primary volume descriptor. */
+ uint8_t abEscapeSequences[32];
+ /** 0x078: The number of volumes in the volume set. */
+ ISO9660U16 cVolumesInSet;
+ /** 0x07c: Volume sequence number. */
+ ISO9660U16 VolumeSeqNo;
+ /** 0x080: Logical block size in bytes. */
+ ISO9660U16 cbLogicalBlock;
+ /** 0x084: Path table size. */
+ ISO9660U32 cbPathTable;
+ /** 0x08c: Type L(ittle endian) path table location (block offset). */
+ ISO9660U32LE offTypeLPathTable;
+ /** 0x090: Optional type L(ittle endian) path table location (block offset). */
+ ISO9660U32LE offOptionalTypeLPathTable;
+ /** 0x094: Type M (big endian) path table location (block offset). */
+ ISO9660U32BE offTypeMPathTable;
+ /** 0x098: Optional type M (big endian) path table location (block offset). */
+ ISO9660U32BE offOptionalTypeMPathTable;
+ /** 0x09c: Directory entry for the root directory (union). */
+ union
+ {
+ uint8_t ab[34];
+ ISO9660DIRREC DirRec;
+ } RootDir;
+ /** 0x0be: Volume set identifier (d1-characters).
+ * @note Character set differs from primary description. */
+ char achVolumeSetId[128];
+ /** 0x13e: Publisher identifier (a1-characters). Alternatively, it may refere
+ * to a file in the root dir if it starts with 0x5f and restricts itself to 8
+ * d1-characters.
+ * @note Character set differs from primary description. */
+ char achPublisherId[128];
+ /** 0x1be: Data preparer identifier (a1-characters).
+ * Same file reference alternative as previous field.
+ * @note Character set differs from primary description. */
+ char achDataPreparerId[128];
+ /** 0x23e: Application identifier (a1-characters).
+ * Same file reference alternative as previous field.
+ * @note Character set differs from primary description. */
+ char achApplicationId[128];
+ /** 0x2be: Copyright (root) file identifier (d1-characters).
+ * All spaces if none.
+ * @note Character set differs from primary description. */
+ char achCopyrightFileId[37];
+ /** 0x2e3: Abstract (root) file identifier (d1-characters).
+ * All spaces if none.
+ * @note Character set differs from primary description. */
+ char achAbstractFileId[37];
+ /** 0x308: Bibliographic file identifier (d1-characters).
+ * All spaces if none.
+ * @note Character set differs from primary description. */
+ char achBibliographicFileId[37];
+ /** 0x32d: Volume creation date and time. */
+ ISO9660TIMESTAMP BirthTime;
+ /** 0x33e: Volume modification date and time. */
+ ISO9660TIMESTAMP ModifyTime;
+ /** 0x34f: Volume (data) expiration date and time.
+ * If not specified, don't regard data as obsolete. */
+ ISO9660TIMESTAMP ExpireTime;
+ /** 0x360: Volume (data) effective date and time.
+ * If not specified, info can be used immediately. */
+ ISO9660TIMESTAMP EffectiveTime;
+ /** 0x371: File structure version (ISO9660_FILE_STRUCTURE_VERSION). */
+ uint8_t bFileStructureVersion;
+ /** 0x372: Reserve for future, MBZ. */
+ uint8_t bReserved883;
+ /** 0x373: Reserve for future, MBZ. */
+ uint8_t abAppUse[512];
+ /** 0x573: Reserved for future standardization, MBZ. */
+ uint8_t abReserved1396[653];
+} ISO9660SUPVOLDESC;
+AssertCompileSize(ISO9660SUPVOLDESC, ISO9660_SECTOR_SIZE);
+/** Pointer to a ISO 9660 supplementary volume descriptor. */
+typedef ISO9660SUPVOLDESC *PISO9660SUPVOLDESC;
+/** Pointer to a const ISO 9660 supplementary volume descriptor. */
+typedef ISO9660SUPVOLDESC const *PCISO9660SUPVOLDESC;
+/** The value of ISO9660SUPVOLDESC::Hdr.uDescVersion. */
+#define ISO9660SUPVOLDESC_VERSION UINT8_C(1)
+
+/** @name ISO9660SUPVOLDESC_VOL_F_XXX - ISO9660SUPVOLDESC::fVolumeFlags
+ * @{ */
+#define ISO9660SUPVOLDESC_VOL_F_ESC_ONLY_REG UINT8_C(0x00)
+#define ISO9660SUPVOLDESC_VOL_F_ESC_NOT_REG UINT8_C(0x01)
+/** @} */
+
+
+
+/**
+ * ISO 9660 volume partition descriptor.
+ */
+typedef struct ISO9660VOLPARTDESC
+{
+ /** 0x000: The volume descriptor header.
+ * Type is ISO9660VOLDESC_TYPE_PARTITION and version
+ * ISO9660VOLPARTDESC_VERSION. */
+ ISO9660VOLDESCHDR Hdr;
+ /** 0x007: Alignment padding. */
+ uint8_t bPadding8;
+ /** 0x008: System identifier (a-characters). */
+ char achSystemId[32];
+ /** 0x028: Volume partition identifier (d-characters). */
+ char achVolumePartitionId[32];
+ /** 0x048: The location of the partition (logical block number). */
+ ISO9660U32 offVolumePartition;
+ /** 0x050: The partition size in logical blocks (cbLogicalBlock). */
+ ISO9660U32 VolumePartitionSize;
+ /** 0x058: System specific data. */
+ uint8_t achSystemUse[1960];
+} ISO9660VOLPARTDESC;
+AssertCompileSize(ISO9660VOLPARTDESC, ISO9660_SECTOR_SIZE);
+/** Pointer to an ISO 9660 volume partition description. */
+typedef ISO9660VOLPARTDESC *PISO9660VOLPARTDESC;
+/** Pointer to a const ISO 9660 volume partition description. */
+typedef ISO9660VOLPARTDESC const *PCISO9660VOLPARTDESC;
+/** The value of ISO9660VOLPARTDESC::Hdr.uDescVersion. */
+#define ISO9660VOLPARTDESC_VERSION UINT8_C(1)
+
+
+
+/** @name Joliet escape sequence identifiers.
+ *
+ * These bytes appears in the supplementary volume descriptor field
+ * abEscapeSequences. The ISO9660SUPVOLDESC_VOL_F_ESC_NOT_REG flags will not
+ * be set.
+ *
+ * @{ */
+#define ISO9660_JOLIET_ESC_SEQ_0 UINT8_C(0x25) /**< First escape sequence byte.*/
+#define ISO9660_JOLIET_ESC_SEQ_1 UINT8_C(0x2f) /**< Second escape sequence byte.*/
+#define ISO9660_JOLIET_ESC_SEQ_2_LEVEL_1 UINT8_C(0x40) /**< Third escape sequence byte: level 1 */
+#define ISO9660_JOLIET_ESC_SEQ_2_LEVEL_2 UINT8_C(0x43) /**< Third escape sequence byte: level 2 */
+#define ISO9660_JOLIET_ESC_SEQ_2_LEVEL_3 UINT8_C(0x45) /**< Third escape sequence byte: level 3 */
+/** @} */
+
+
+/** The size of an El Torito boot catalog entry. */
+#define ISO9660_ELTORITO_ENTRY_SIZE UINT32_C(0x20)
+
+/**
+ * El Torito boot catalog: Validation entry.
+ *
+ * This is the first entry in the boot catalog. It is followed by a
+ * ISO9660ELTORITODEFAULTENTRY, which in turn is followed by a
+ * ISO9660ELTORITOSECTIONHEADER.
+ */
+typedef struct ISO9660ELTORITOVALIDATIONENTRY
+{
+ /** 0x00: The header ID (ISO9660_ELTORITO_HEADER_ID_VALIDATION_ENTRY). */
+ uint8_t bHeaderId;
+ /** 0x01: The platform ID (ISO9660_ELTORITO_PLATFORM_ID_XXX). */
+ uint8_t bPlatformId;
+ /** 0x02: Reserved, MBZ. */
+ uint16_t u16Reserved;
+ /** 0x04: String ID of the developer of the CD/DVD-ROM. */
+ char achId[24];
+ /** 0x1c: The checksum. */
+ uint16_t u16Checksum;
+ /** 0x1e: Key byte 1 (ISO9660_ELTORITO_KEY_BYTE_1). */
+ uint8_t bKey1;
+ /** 0x1f: Key byte 2 (ISO9660_ELTORITO_KEY_BYTE_2). */
+ uint8_t bKey2;
+} ISO9660ELTORITOVALIDATIONENTRY;
+AssertCompileSize(ISO9660ELTORITOVALIDATIONENTRY, ISO9660_ELTORITO_ENTRY_SIZE);
+/** Pointer to an El Torito validation entry. */
+typedef ISO9660ELTORITOVALIDATIONENTRY *PISO9660ELTORITOVALIDATIONENTRY;
+/** Pointer to a const El Torito validation entry. */
+typedef ISO9660ELTORITOVALIDATIONENTRY const *PCISO9660ELTORITOVALIDATIONENTRY;
+
+/** ISO9660ELTORITOVALIDATIONENTRY::bKey1 value. */
+#define ISO9660_ELTORITO_KEY_BYTE_1 UINT8_C(0x55)
+/** ISO9660ELTORITOVALIDATIONENTRY::bKey2 value. */
+#define ISO9660_ELTORITO_KEY_BYTE_2 UINT8_C(0xaa)
+
+
+/** @name ISO9660_ELTORITO_HEADER_ID_XXX - header IDs.
+ * @{ */
+/** Header ID for a ISO9660ELTORITOVALIDATIONENTRY. */
+#define ISO9660_ELTORITO_HEADER_ID_VALIDATION_ENTRY UINT8_C(0x01)
+/** Header ID for a ISO9660ELTORITOSECTIONHEADER. */
+#define ISO9660_ELTORITO_HEADER_ID_SECTION_HEADER UINT8_C(0x90)
+/** Header ID for the final ISO9660ELTORITOSECTIONHEADER. */
+#define ISO9660_ELTORITO_HEADER_ID_FINAL_SECTION_HEADER UINT8_C(0x91)
+/** @} */
+
+
+/** @name ISO9660_ELTORITO_PLATFORM_ID_XXX - El Torito Platform IDs
+ * @{ */
+#define ISO9660_ELTORITO_PLATFORM_ID_X86 UINT8_C(0x00) /**< 80x86 */
+#define ISO9660_ELTORITO_PLATFORM_ID_PPC UINT8_C(0x01) /**< PowerPC */
+#define ISO9660_ELTORITO_PLATFORM_ID_MAC UINT8_C(0x02) /**< Mac */
+#define ISO9660_ELTORITO_PLATFORM_ID_EFI UINT8_C(0xef) /**< UEFI */
+/** @} */
+
+
+/**
+ * El Torito boot catalog: Section header entry.
+ *
+ * A non-final section header entry is followed by
+ * ISO9660ELTORITOSECTIONHEADER::cEntries ISO9660ELTORITOSECTIONTENTRY instances.
+ */
+typedef struct ISO9660ELTORITOSECTIONHEADER
+{
+ /** 0x00: Header ID - ISO9660_ELTORITO_HEADER_ID_SECTION_HEADER or
+ * ISO9660_ELTORITO_HEADER_ID_FINAL_SECTION_HEADER (if final). */
+ uint8_t bHeaderId;
+ /** 0x01: The platform ID (ISO9660_ELTORITO_PLATFORM_ID_XXX). */
+ uint8_t bPlatformId;
+ /** 0x02: Number of entries in this section (i.e. following this header). */
+ uint16_t cEntries;
+ /** 0x04: String ID for the section. */
+ char achSectionId[28];
+} ISO9660ELTORITOSECTIONHEADER;
+AssertCompileSize(ISO9660ELTORITOSECTIONHEADER, ISO9660_ELTORITO_ENTRY_SIZE);
+/** Pointer to an El Torito section header entry. */
+typedef ISO9660ELTORITOSECTIONHEADER *PISO9660ELTORITOSECTIONHEADER;
+/** Pointer to a const El Torito section header entry. */
+typedef ISO9660ELTORITOSECTIONHEADER const *PCISO9660ELTORITOSECTIONHEADER;
+
+
+/**
+ * El Torito boot catalog: Default (initial) entry.
+ *
+ * Followed by ISO9660ELTORITOSECTIONHEADER.
+ *
+ * Differs from ISO9660ELTORITOSECTIONENTRY in that it doesn't have a
+ * selection criteria and no media flags (only type).
+ */
+typedef struct ISO9660ELTORITODEFAULTENTRY
+{
+ /** 0x00: Boot indicator (ISO9660_ELTORITO_BOOT_INDICATOR_XXX). */
+ uint8_t bBootIndicator;
+ /** 0x01: Boot media type. The first four bits are defined by
+ * ISO9660_ELTORITO_BOOT_MEDIA_TYPE_XXX, whereas the top four bits MBZ. */
+ uint8_t bBootMediaType;
+ /** 0x02: Load segment - load address divided by 0x10. */
+ uint16_t uLoadSeg;
+ /** 0x04: System type from image partition table. */
+ uint8_t bSystemType;
+ /** 0x05: Unused, MBZ. */
+ uint8_t bUnused;
+ /** 0x06: Number of emulated 512 byte sectors to load. */
+ uint16_t cEmulatedSectorsToLoad;
+ /** 0x08: Image location in the ISO (block offset), always (?) little endian. */
+ uint32_t offBootImage;
+ /** 0x0c: Reserved, MBZ */
+ uint8_t abReserved[20];
+} ISO9660ELTORITODEFAULTENTRY;
+AssertCompileSize(ISO9660ELTORITODEFAULTENTRY, ISO9660_ELTORITO_ENTRY_SIZE);
+/** Pointer to an El Torito default (initial) entry. */
+typedef ISO9660ELTORITODEFAULTENTRY *PISO9660ELTORITODEFAULTENTRY;
+/** Pointer to a const El Torito default (initial) entry. */
+typedef ISO9660ELTORITODEFAULTENTRY const *PCISO9660ELTORITODEFAULTENTRY;
+
+
+/**
+ * El Torito boot catalg: Section entry.
+ */
+typedef struct ISO9660ELTORITOSECTIONENTRY
+{
+ /** 0x00: Boot indicator (ISO9660_ELTORITO_BOOT_INDICATOR_XXX). */
+ uint8_t bBootIndicator;
+ /** 0x01: Boot media type and flags. The first four bits are defined by
+ * ISO9660_ELTORITO_BOOT_MEDIA_TYPE_XXX and the top four bits by
+ * ISO9660_ELTORITO_BOOT_MEDIA_F_XXX. */
+ uint8_t bBootMediaType;
+ /** 0x02: Load segment - load address divided by 0x10. */
+ uint16_t uLoadSeg;
+ /** 0x04: System type from image partition table. */
+ uint8_t bSystemType;
+ /** 0x05: Unused, MBZ. */
+ uint8_t bUnused;
+ /** 0x06: Number of emulated 512 byte sectors to load. */
+ uint16_t cEmulatedSectorsToLoad;
+ /** 0x08: Image location in the ISO (block offset), always (?) little endian. */
+ uint32_t offBootImage;
+ /** 0x0c: Selection criteria type (ISO9660_ELTORITO_SEL_CRIT_TYPE_XXX). */
+ uint8_t bSelectionCriteriaType;
+ /** 0x0c: Selection criteria specific data. */
+ uint8_t abSelectionCriteria[19];
+} ISO9660ELTORITOSECTIONENTRY;
+AssertCompileSize(ISO9660ELTORITOSECTIONENTRY, ISO9660_ELTORITO_ENTRY_SIZE);
+/** Pointer to an El Torito default (initial) entry. */
+typedef ISO9660ELTORITOSECTIONENTRY *PISO9660ELTORITOSECTIONENTRY;
+/** Pointer to a const El Torito default (initial) entry. */
+typedef ISO9660ELTORITOSECTIONENTRY const *PCISO9660ELTORITOSECTIONENTRY;
+
+
+/** @name ISO9660_ELTORITO_BOOT_INDICATOR_XXX - Boot indicators.
+ * @{ */
+#define ISO9660_ELTORITO_BOOT_INDICATOR_BOOTABLE UINT8_C(0x88)
+#define ISO9660_ELTORITO_BOOT_INDICATOR_NOT_BOOTABLE UINT8_C(0x00)
+/** @} */
+
+/** @name ISO9660_ELTORITO_BOOT_MEDIA_TYPE_XXX - Boot media types.
+ * @{ */
+#define ISO9660_ELTORITO_BOOT_MEDIA_TYPE_NO_EMULATION UINT8_C(0x0)
+#define ISO9660_ELTORITO_BOOT_MEDIA_TYPE_FLOPPY_1_2_MB UINT8_C(0x1)
+#define ISO9660_ELTORITO_BOOT_MEDIA_TYPE_FLOPPY_1_44_MB UINT8_C(0x2)
+#define ISO9660_ELTORITO_BOOT_MEDIA_TYPE_FLOPPY_2_88_MB UINT8_C(0x3)
+#define ISO9660_ELTORITO_BOOT_MEDIA_TYPE_HARD_DISK UINT8_C(0x4)
+#define ISO9660_ELTORITO_BOOT_MEDIA_TYPE_MASK UINT8_C(0xf) /**< The media type mask. */
+/** @} */
+
+/** @name ISO9660_ELTORITO_BOOT_MEDIA_F_XXX - Boot media flags.
+ * These only applies to the section entry, not to the default (initial) entry.
+ * @{ */
+#define ISO9660_ELTORITO_BOOT_MEDIA_F_RESERVED UINT8_C(0x10) /**< Reserved bit, MBZ. */
+#define ISO9660_ELTORITO_BOOT_MEDIA_F_CONTINUATION UINT8_C(0x20) /**< Contiunation entry follows. */
+#define ISO9660_ELTORITO_BOOT_MEDIA_F_ATAPI_DRIVER UINT8_C(0x40) /**< Image contains an ATAPI driver. */
+#define ISO9660_ELTORITO_BOOT_MEDIA_F_SCSI_DRIVERS UINT8_C(0x80) /**< Image contains SCSI drivers. */
+#define ISO9660_ELTORITO_BOOT_MEDIA_F_MASK UINT8_C(0xf0) /**< The media/entry flag mask. */
+/** @} */
+
+/** @name ISO9660_ELTORITO_SEL_CRIT_TYPE_XXX - Selection criteria type.
+ * @{ */
+#define ISO9660_ELTORITO_SEL_CRIT_TYPE_NONE UINT8_C(0x00) /**< No selection criteria */
+#define ISO9660_ELTORITO_SEL_CRIT_TYPE_LANG_AND_VERSION UINT8_C(0x01) /**< Language and version (IBM). */
+/** @} */
+
+
+/**
+ * El Torito boot catalog: Section entry extension.
+ *
+ * This is used for carrying additional selection criteria data. It follows
+ * a ISO9660ELTORITOSECTIONENTRY.
+ */
+typedef struct ISO9660ELTORITOSECTIONENTRYEXT
+{
+ /** 0x00: Extension indicator (ISO9660_ELTORITO_SECTION_ENTRY_EXT_ID). */
+ uint8_t bExtensionId;
+ /** 0x01: Selection criteria extension flags (ISO9660_ELTORITO_SECTION_ENTRY_EXT_F_XXX). */
+ uint8_t fFlags;
+ /** 0x02: Selection critiera data. */
+ uint8_t abSelectionCriteria[30];
+} ISO9660ELTORITOSECTIONENTRYEXT;
+AssertCompileSize(ISO9660ELTORITOSECTIONENTRYEXT, ISO9660_ELTORITO_ENTRY_SIZE);
+/** Pointer to an El Torito default (initial) entry. */
+typedef ISO9660ELTORITOSECTIONENTRYEXT *PISO9660ELTORITOSECTIONENTRYEXT;
+/** Pointer to a const El Torito default (initial) entry. */
+typedef ISO9660ELTORITOSECTIONENTRYEXT const *PCISO9660ELTORITOSECTIONENTRYEXT;
+
+/** Value of ISO9660ELTORITOSECTIONENTRYEXT::bExtensionId. */
+#define ISO9660_ELTORITO_SECTION_ENTRY_EXT_ID UINT8_C(0x44)
+
+/** @name ISO9660_ELTORITO_SECTION_ENTRY_EXT_F_XXX - ISO9660ELTORITOSECTIONENTRYEXT::fFlags
+ * @{ */
+#define ISO9660_ELTORITO_SECTION_ENTRY_EXT_F_MORE UINT8_C(0x20) /**< Further extension entries follows. */
+#define ISO9660_ELTORITO_SECTION_ENTRY_EXT_F_UNUSED_MASK UINT8_C(0xef) /**< Mask of all unused bits. */
+/** @} */
+
+
+/**
+ * Boot information table used by isolinux and GRUB2 El Torito boot files.
+ */
+typedef struct ISO9660SYSLINUXINFOTABLE
+{
+ /** 0x00/0x08: Offset of the primary volume descriptor (block offset). */
+ uint32_t offPrimaryVolDesc;
+ /** 0x04/0x0c: Offset of the boot file (block offset). */
+ uint32_t offBootFile;
+ /** 0x08/0x10: Size of the boot file in bytes. */
+ uint32_t cbBootFile;
+ /** 0x0c/0x14: Boot file checksum.
+ * This is the sum of all the 32-bit words in the image, start at the end of
+ * this structure (i.e. offset 64). */
+ uint32_t uChecksum;
+ /** 0x10/0x18: Reserved for future fun. */
+ uint32_t auReserved[10];
+} ISO9660SYSLINUXINFOTABLE;
+AssertCompileSize(ISO9660SYSLINUXINFOTABLE, 56);
+/** Pointer to a syslinux boot information table. */
+typedef ISO9660SYSLINUXINFOTABLE *PISO9660SYSLINUXINFOTABLE;
+/** Pointer to a const syslinux boot information table. */
+typedef ISO9660SYSLINUXINFOTABLE const *PCISO9660SYSLINUXINFOTABLE;
+
+/** The file offset of the isolinux boot info table. */
+#define ISO9660SYSLINUXINFOTABLE_OFFSET 8
+
+
+
+/**
+ * System Use Sharing Protocol Protocol (SUSP) header.
+ */
+typedef struct ISO9660SUSPHDR
+{
+ /** Signature byte 1. */
+ uint8_t bSig1;
+ /** Signature byte 2. */
+ uint8_t bSig2;
+ /** Length of the entry (including the header). */
+ uint8_t cbEntry;
+ /** Entry version number. */
+ uint8_t bVersion;
+} ISO9660SUSPHDR;
+AssertCompileSize(ISO9660SUSPHDR, 4);
+/** Pointer to a SUSP header. */
+typedef ISO9660SUSPHDR *PISO9660SUSPHDR;
+/** Pointer to a const SUSP header. */
+typedef ISO9660SUSPHDR const *PCISO9660SUSPHDR;
+
+
+/**
+ * SUSP continuation entry (CE).
+ */
+typedef struct ISO9660SUSPCE
+{
+ /** Header (ISO9660SUSPCE_SIG1, ISO9660SUSPCE_SIG2, ISO9660SUSPCE_VER). */
+ ISO9660SUSPHDR Hdr;
+ /** The offset of the continutation data block (block offset). */
+ ISO9660U32 offBlock;
+ /** The byte offset in the block of the contiuation data. */
+ ISO9660U32 offData;
+ /** The size of the continuation data. */
+ ISO9660U32 cbData;
+} ISO9660SUSPCE;
+/** Pointer to a SUSP continuation entry. */
+typedef ISO9660SUSPCE *PISO9660SUSPCE;
+/** Pointer to a const SUSP continuation entry. */
+typedef ISO9660SUSPCE const *PCISO9660SUSPCE;
+#define ISO9660SUSPCE_SIG1 'C' /**< SUSP continutation entry signature byte 1. */
+#define ISO9660SUSPCE_SIG2 'E' /**< SUSP continutation entry signature byte 2. */
+#define ISO9660SUSPCE_LEN 28 /**< SUSP continutation entry length. */
+#define ISO9660SUSPCE_VER 1 /**< SUSP continutation entry version number. */
+AssertCompileSize(ISO9660SUSPCE, ISO9660SUSPCE_LEN);
+
+
+/**
+ * SUSP padding entry (PD).
+ */
+typedef struct ISO9660SUSPPD
+{
+ /** Header (ISO9660SUSPPD_SIG1, ISO9660SUSPPD_SIG2, ISO9660SUSPPD_VER). */
+ ISO9660SUSPHDR Hdr;
+ /* Padding follows. */
+} ISO9660SUSPPD;
+AssertCompileSize(ISO9660SUSPPD, 4);
+/** Pointer to a SUSP padding entry. */
+typedef ISO9660SUSPPD *PISO9660SUSPPD;
+/** Pointer to a const SUSP padding entry. */
+typedef ISO9660SUSPPD const *PCISO9660SUSPPD;
+#define ISO9660SUSPPD_SIG1 'P' /**< SUSP padding entry signature byte 1. */
+#define ISO9660SUSPPD_SIG2 'D' /**< SUSP padding entry signature byte 2. */
+#define ISO9660SUSPPD_VER 1 /**< SUSP padding entry version number. */
+
+
+/**
+ * SUSP system use protocol entry (SP)
+ *
+ * This is only used in the '.' record of the root directory.
+ */
+typedef struct ISO9660SUSPSP
+{
+ /** Header (ISO9660SUSPSP_SIG1, ISO9660SUSPSP_SIG2,
+ * ISO9660SUSPSP_LEN, ISO9660SUSPSP_VER). */
+ ISO9660SUSPHDR Hdr;
+ /** Check byte 1 (ISO9660SUSPSP_CHECK1). */
+ uint8_t bCheck1;
+ /** Check byte 2 (ISO9660SUSPSP_CHECK2). */
+ uint8_t bCheck2;
+ /** Number of bytes to skip within the system use field of each directory
+ * entry (except the '.' entry of the root, since that's where this is). */
+ uint8_t cbSkip;
+} ISO9660SUSPSP;
+/** Pointer to a SUSP entry. */
+typedef ISO9660SUSPSP *PISO9660SUSPSP;
+/** Pointer to a const SUSP entry. */
+typedef ISO9660SUSPSP const *PCISO9660SUSPSP;
+#define ISO9660SUSPSP_SIG1 'S' /**< SUSP system use protocol entry signature byte 1. */
+#define ISO9660SUSPSP_SIG2 'P' /**< SUSP system use protocol entry signature byte 2. */
+#define ISO9660SUSPSP_VER 1 /**< SUSP system use protocol entry version number. */
+#define ISO9660SUSPSP_LEN 7 /**< SUSP system use protocol entry length (fixed). */
+#define ISO9660SUSPSP_CHECK1 UINT8_C(0xbe) /**< SUSP system use protocol entry check byte 1. */
+#define ISO9660SUSPSP_CHECK2 UINT8_C(0xef) /**< SUSP system use protocol entry check byte 2. */
+AssertCompileSize(ISO9660SUSPSP, ISO9660SUSPSP_LEN);
+
+
+/**
+ * SUSP terminator entry (ST)
+ *
+ * Used to terminate system use entries.
+ */
+typedef struct ISO9660SUSPST
+{
+ /** Header (ISO9660SUSPST_SIG1, ISO9660SUSPST_SIG2,
+ * ISO9660SUSPST_LEN, ISO9660SUSPST_VER). */
+ ISO9660SUSPHDR Hdr;
+} ISO9660SUSPST;
+/** Pointer to a SUSP padding entry. */
+typedef ISO9660SUSPST *PISO9660SUSPST;
+/** Pointer to a const SUSP padding entry. */
+typedef ISO9660SUSPST const *PCISO9660SUSPST;
+#define ISO9660SUSPST_SIG1 'S' /**< SUSP system use protocol entry signature byte 1. */
+#define ISO9660SUSPST_SIG2 'T' /**< SUSP system use protocol entry signature byte 2. */
+#define ISO9660SUSPST_VER 1 /**< SUSP system use protocol entry version number. */
+#define ISO9660SUSPST_LEN 4 /**< SUSP system use protocol entry length (fixed). */
+AssertCompileSize(ISO9660SUSPST, ISO9660SUSPST_LEN);
+
+
+/**
+ * SUSP extension record entry (ER)
+ *
+ * This is only used in the '.' record of the root directory. There can be multiple of these.
+ */
+typedef struct ISO9660SUSPER
+{
+ /** Header (ISO9660SUSPER_SIG1, ISO9660SUSPER_SIG2, ISO9660SUSPER_VER). */
+ ISO9660SUSPHDR Hdr;
+ /** The length of the identifier component. */
+ uint8_t cchIdentifier;
+ /** The length of the description component. */
+ uint8_t cchDescription;
+ /** The length of the source component. */
+ uint8_t cchSource;
+ /** The extension version number. */
+ uint8_t bVersion;
+ /** The payload: first @a cchIdentifier chars of identifier string, second
+ * @a cchDescription chars of description string, thrid @a cchSource chars
+ * of source string. Variable length. */
+ char achPayload[RT_FLEXIBLE_ARRAY_IN_NESTED_UNION];
+} ISO9660SUSPER;
+/** Pointer to a SUSP padding entry. */
+typedef ISO9660SUSPER *PISO9660SUSPER;
+/** Pointer to a const SUSP padding entry. */
+typedef ISO9660SUSPER const *PCISO9660SUSPER;
+#define ISO9660SUSPER_SIG1 'E' /**< SUSP extension record entry signature byte 1. */
+#define ISO9660SUSPER_SIG2 'R' /**< SUSP extension record entry signature byte 2. */
+#define ISO9660SUSPER_VER 1 /**< SUSP extension record entry version number. */
+#define ISO9660SUSPER_OFF_PAYLOAD 8 /**< SUSP extension record entry payload member offset. */
+AssertCompileMemberOffset(ISO9660SUSPER, achPayload, ISO9660SUSPER_OFF_PAYLOAD);
+
+/**
+ * SUSP extension sequence entry (ES)
+ *
+ * This is only used in the '.' record of the root directory.
+ */
+typedef struct ISO9660SUSPES
+{
+ /** Header (ISO9660SUSPES_SIG1, ISO9660SUSPES_SIG2, ISO9660SUSPES_VER). */
+ ISO9660SUSPHDR Hdr;
+ /** The ER entry sequence number of the extension comming first. */
+ uint8_t iFirstExtension;
+} ISO9660SUSPES;
+/** Pointer to a SUSP padding entry. */
+typedef ISO9660SUSPES *PISO9660SUSPES;
+/** Pointer to a const SUSP padding entry. */
+typedef ISO9660SUSPES const *PCISO9660SUSPES;
+#define ISO9660SUSPES_SIG1 'E' /**< SUSP extension sequence entry signature byte 1. */
+#define ISO9660SUSPES_SIG2 'S' /**< SUSP extension sequence entry signature byte 2. */
+#define ISO9660SUSPES_VER 1 /**< SUSP extension sequence entry version number. */
+#define ISO9660SUSPES_LEN 5 /**< SUSP extension sequence entry length (fixed). */
+AssertCompileSize(ISO9660SUSPES, ISO9660SUSPES_LEN);
+
+
+/** RRIP ER identifier string from Rock Ridge Interchange Protocol v1.10 specs. */
+#define ISO9660_RRIP_ID "RRIP_1991A"
+/** RRIP ER recommended description string (from RRIP v1.10 specs). */
+#define ISO9660_RRIP_DESC "THE ROCK RIDGE INTERCHANGE PROTOCOL PROVIDES SUPPORT FOR POSIX FILE SYSTEM SEMANTICS"
+/** RRIP ER recommended source string (from RRIP v1.10 specs). */
+#define ISO9660_RRIP_SRC "PLEASE CONTACT DISC PUBLISHER FOR SPECIFICATION SOURCE. SEE PUBLISHER IDENTIFIER IN PRIMARY VOLUME DESCRIPTOR FOR CONTACT INFORMATION."
+/** RRIP ER version field value from the Rock Ridge Interchange Protocol v1.10 specs. */
+#define ISO9660_RRIP_VER 1
+/** The length of a RRIP v1.10 ER record.
+ * The record must be constructed using ISO9660_RRIP_ID, ISO9660_RRIP_DESC
+ * and ISO9660_RRIP_SRC. */
+#define ISO9660_RRIP_ER_LEN ((uint8_t)( ISO9660SUSPER_OFF_PAYLOAD \
+ + sizeof(ISO9660_RRIP_ID) - 1 \
+ + sizeof(ISO9660_RRIP_DESC) - 1 \
+ + sizeof(ISO9660_RRIP_SRC) - 1 ))
+
+/** RRIP ER identifier string from RRIP IEEE P1282 v1.12 draft. */
+#define ISO9660_RRIP_1_12_ID "IEEE_P1282"
+/** RRIP ER recommended description string (RRIP IEEE P1282 v1.12 draft). */
+#define ISO9660_RRIP_1_12_DESC "THE IEEE P1282 PROTOCOL PROVIDES SUPPORT FOR POSIX FILE SYSTEM SEMANTICS."
+/** RRIP ER recommended source string (RRIP IEEE P1282 v1.12 draft). */
+#define ISO9660_RRIP_1_12_SRC "PLEASE CONTACT THE IEEE STANDARDS DEPARTMENT, PISCATAWAY, NJ, USA FOR THE P1282 SPECIFICATION."
+/** RRIP ER version field value from the Rock Ridge Interchange Protocol v1.12 specs. */
+#define ISO9660_RRIP_1_12_VER 1
+/** The length of a RRIP v1.12 ER record.
+ * The record must be constructed using ISO9660_RRIP_1_12_ID,
+ * ISO9660_RRIP_1_12_DESC and ISO9660_RRIP_1_12_SRC. */
+#define ISO9660_RRIP_1_12_ER_LEN ((uint8_t)( ISO9660SUSPER_OFF_PAYLOAD \
+ + sizeof(ISO9660_RRIP_1_12_ID) - 1 \
+ + sizeof(ISO9660_RRIP_1_12_DESC) - 1 \
+ + sizeof(ISO9660_RRIP_1_12_SRC) - 1 ))
+
+
+/**
+ * Rock ridge interchange protocol - RR.
+ */
+typedef struct ISO9660RRIPRR
+{
+ /** Header (ISO9660RRIPRR_SIG1, ISO9660RRIPRR_SIG2,
+ * ISO9660RRIPRR_LEN, ISO9660RRIPRR_VER). */
+ ISO9660SUSPHDR Hdr;
+ /** Flags indicating which RRIP entries are present (). */
+ uint8_t fFlags;
+} ISO9660RRIPRR;
+/** Pointer to a RRIP RR entry. */
+typedef ISO9660RRIPRR *PISO9660RRIPRR;
+/** Pointer to a const RRIP RR entry. */
+typedef ISO9660RRIPRR const *PCISO9660RRIPRR;
+#define ISO9660RRIPRR_SIG1 'R' /**< RRIP RR entry signature byte 1. */
+#define ISO9660RRIPRR_SIG2 'R' /**< RRIP RR entry signature byte 2. */
+#define ISO9660RRIPRR_VER 1 /**< RRIP RR entry version number. */
+#define ISO9660RRIPRR_LEN 5 /**< RRIP RR entry length (fixed). */
+AssertCompileSize(ISO9660RRIPRR, ISO9660RRIPRR_LEN);
+
+/** @name ISO9660RRIP_RR_F_XXX - Indicates which RRIP entries are present.
+ * @{ */
+#define ISO9660RRIP_RR_F_PX UINT8_C(0x01)
+#define ISO9660RRIP_RR_F_PN UINT8_C(0x02)
+#define ISO9660RRIP_RR_F_SL UINT8_C(0x04)
+#define ISO9660RRIP_RR_F_NM UINT8_C(0x08)
+#define ISO9660RRIP_RR_F_CL UINT8_C(0x10)
+#define ISO9660RRIP_RR_F_PL UINT8_C(0x20)
+#define ISO9660RRIP_RR_F_RE UINT8_C(0x40)
+#define ISO9660RRIP_RR_F_TF UINT8_C(0x80)
+/** @} */
+
+/**
+ * Rock ridge interchange protocol - posix attribute entry (PX).
+ */
+typedef struct ISO9660RRIPPX
+{
+ /** Header (ISO9660RRIPPX_SIG1, ISO9660RRIPPX_SIG2,
+ * ISO9660RRIPPX_LEN, ISO9660RRIPPX_VER). */
+ ISO9660SUSPHDR Hdr;
+ /** The file mode (RTFS_UNIX_XXX, RTFS_TYPE_XXX). */
+ ISO9660U32 fMode;
+ /** Number of hardlinks. */
+ ISO9660U32 cHardlinks;
+ /** User ID. */
+ ISO9660U32 uid;
+ /** Group ID. */
+ ISO9660U32 gid;
+ /** Inode number. */
+ ISO9660U32 INode;
+} ISO9660RRIPPX;
+/** Pointer to a RRIP posix attribute entry. */
+typedef ISO9660RRIPPX *PISO9660RRIPPX;
+/** Pointer to a const RRIP posix attribute entry. */
+typedef ISO9660RRIPPX const *PCISO9660RRIPPX;
+#define ISO9660RRIPPX_SIG1 'P' /**< RRIP posix attribute entry signature byte 1. */
+#define ISO9660RRIPPX_SIG2 'X' /**< RRIP posix attribute entry signature byte 2. */
+#define ISO9660RRIPPX_VER 1 /**< RRIP posix attribute entry version number. */
+#define ISO9660RRIPPX_LEN 44 /**< RRIP posix attribute entry length (fixed). */
+AssertCompileSize(ISO9660RRIPPX, ISO9660RRIPPX_LEN);
+#define ISO9660RRIPPX_LEN_NO_INODE 36 /**< RRIP posix attribute entry length without inode (fixed). */
+
+
+/**
+ * Rock ridge interchange protocol - timestamp entry (TF).
+ */
+typedef struct ISO9660RRIPTF
+{
+ /** Header (ISO9660RRIPTF_SIG1, ISO9660RRIPTF_SIG2, ISO9660RRIPTF_VER). */
+ ISO9660SUSPHDR Hdr;
+ /** Flags, ISO9660RRIPTF_F_XXX. */
+ uint8_t fFlags;
+ /** Timestamp payload bytes (variable size and format). */
+ uint8_t abPayload[RT_FLEXIBLE_ARRAY_IN_NESTED_UNION];
+} ISO9660RRIPTF;
+AssertCompileMemberOffset(ISO9660RRIPTF, abPayload, 5);
+/** Pointer to a RRIP timestamp entry. */
+typedef ISO9660RRIPTF *PISO9660RRIPTF;
+/** Pointer to a const RRIP timestamp entry. */
+typedef ISO9660RRIPTF const *PCISO9660RRIPTF;
+#define ISO9660RRIPTF_SIG1 'T' /**< RRIP child link entry signature byte 1. */
+#define ISO9660RRIPTF_SIG2 'F' /**< RRIP child link entry signature byte 2. */
+#define ISO9660RRIPTF_VER 1 /**< RRIP child link entry version number. */
+
+/** @name ISO9660RRIPTF_F_XXX - Timestmap flags.
+ * @{ */
+#define ISO9660RRIPTF_F_BIRTH UINT8_C(0x01) /**< Birth (creation) timestamp is recorded. */
+#define ISO9660RRIPTF_F_MODIFY UINT8_C(0x02) /**< Modification timestamp is recorded. */
+#define ISO9660RRIPTF_F_ACCESS UINT8_C(0x04) /**< Accessed timestamp is recorded. */
+#define ISO9660RRIPTF_F_CHANGE UINT8_C(0x08) /**< Attribute change timestamp is recorded. */
+#define ISO9660RRIPTF_F_BACKUP UINT8_C(0x10) /**< Backup timestamp is recorded. */
+#define ISO9660RRIPTF_F_EXPIRATION UINT8_C(0x20) /**< Expiration timestamp is recorded. */
+#define ISO9660RRIPTF_F_EFFECTIVE UINT8_C(0x40) /**< Effective timestamp is recorded. */
+#define ISO9660RRIPTF_F_LONG_FORM UINT8_C(0x80) /**< If set ISO9660TIMESTAMP is used, otherwise ISO9660RECTIMESTAMP. */
+/** @} */
+
+/**
+ * Calculates the length of a 'TF' entry given the flags.
+ *
+ * @returns Length in bytes.
+ * @param fFlags The flags (ISO9660RRIPTF_F_XXX).
+ */
+DECLINLINE(uint8_t) Iso9660RripTfCalcLength(uint8_t fFlags)
+{
+ unsigned cTimestamps = ((fFlags & ISO9660RRIPTF_F_BIRTH) != 0)
+ + ((fFlags & ISO9660RRIPTF_F_MODIFY) != 0)
+ + ((fFlags & ISO9660RRIPTF_F_ACCESS) != 0)
+ + ((fFlags & ISO9660RRIPTF_F_CHANGE) != 0)
+ + ((fFlags & ISO9660RRIPTF_F_BACKUP) != 0)
+ + ((fFlags & ISO9660RRIPTF_F_EXPIRATION) != 0)
+ + ((fFlags & ISO9660RRIPTF_F_EFFECTIVE) != 0);
+ return (uint8_t)( cTimestamps * (fFlags & ISO9660RRIPTF_F_LONG_FORM ? sizeof(ISO9660TIMESTAMP) : sizeof(ISO9660RECTIMESTAMP))
+ + RT_OFFSETOF(ISO9660RRIPTF, abPayload));
+}
+
+
+/**
+ * Rock ridge interchange protocol - posix device number entry (PN).
+ *
+ * Mandatory for block or character devices.
+ */
+typedef struct ISO9660RRIPPN
+{
+ /** Header (ISO9660RRIPPN_SIG1, ISO9660RRIPPN_SIG2,
+ * ISO9660RRIPPN_LEN, ISO9660RRIPPN_VER). */
+ ISO9660SUSPHDR Hdr;
+ /** The major device number. */
+ ISO9660U32 Major;
+ /** The minor device number. */
+ ISO9660U32 Minor;
+} ISO9660RRIPPN;
+/** Pointer to a RRIP posix attribute entry. */
+typedef ISO9660RRIPPN *PISO9660RRIPPN;
+/** Pointer to a const RRIP posix attribute entry. */
+typedef ISO9660RRIPPN const *PCISO9660RRIPPN;
+#define ISO9660RRIPPN_SIG1 'P' /**< RRIP posix device number entry signature byte 1. */
+#define ISO9660RRIPPN_SIG2 'N' /**< RRIP posix device number entry signature byte 2. */
+#define ISO9660RRIPPN_VER 1 /**< RRIP posix device number entry version number. */
+#define ISO9660RRIPPN_LEN 20 /**< RRIP posix device number entry length (fixed). */
+AssertCompileSize(ISO9660RRIPPN, ISO9660RRIPPN_LEN);
+
+/**
+ * Rock ridge interchange protocol - symlink entry (SL).
+ *
+ * Mandatory for symbolic links.
+ */
+typedef struct ISO9660RRIPSL
+{
+ /** Header (ISO9660RRIPSL_SIG1, ISO9660RRIPSL_SIG2, ISO9660RRIPSL_VER). */
+ ISO9660SUSPHDR Hdr;
+ /** Flags (0 or ISO9660RRIP_SL_F_CONTINUE). */
+ uint8_t fFlags;
+ /** Variable length of components. First byte in each component is a
+ * combination of ISO9660RRIP_SL_C_XXX flag values. The second byte the
+ * length of character data following it. */
+ uint8_t abComponents[RT_FLEXIBLE_ARRAY_IN_NESTED_UNION];
+} ISO9660RRIPSL;
+AssertCompileMemberOffset(ISO9660RRIPSL, abComponents, 5);
+/** Pointer to a RRIP symbolic link entry. */
+typedef ISO9660RRIPSL *PISO9660RRIPSL;
+/** Pointer to a const RRIP symbolic link entry. */
+typedef ISO9660RRIPSL const *PCISO9660RRIPSL;
+#define ISO9660RRIPSL_SIG1 'S' /**< RRIP symbolic link entry signature byte 1. */
+#define ISO9660RRIPSL_SIG2 'L' /**< RRIP symbolic link entry signature byte 2. */
+#define ISO9660RRIPSL_VER 1 /**< RRIP symbolic link entry version number. */
+/** ISO9660RRIPSL.fFlags - When set another symlink entry follows this one. */
+#define ISO9660RRIP_SL_F_CONTINUE UINT8_C(0x01)
+/** @name ISO9660RRIP_SL_C_XXX - Symlink component flags.
+ * @note These matches ISO9660RRIP_NM_F_XXX.
+ * @{ */
+/** Indicates that the component continues in the next entry. */
+#define ISO9660RRIP_SL_C_CONTINUE UINT8_C(0x01)
+/** Refer to '.' (the current dir). */
+#define ISO9660RRIP_SL_C_CURRENT UINT8_C(0x02)
+/** Refer to '..' (the parent dir). */
+#define ISO9660RRIP_SL_C_PARENT UINT8_C(0x04)
+/** Refer to '/' (the root dir). */
+#define ISO9660RRIP_SL_C_ROOT UINT8_C(0x08)
+/** Reserved / historically was mount point reference. */
+#define ISO9660RRIP_SL_C_MOUNT_POINT UINT8_C(0x10)
+/** Reserved / historically was uname network node name. */
+#define ISO9660RRIP_SL_C_UNAME UINT8_C(0x20)
+/** Reserved mask (considers historically bits reserved). */
+#define ISO9660RRIP_SL_C_RESERVED_MASK UINT8_C(0xf0)
+/** @} */
+
+
+/**
+ * Rock ridge interchange protocol - name entry (NM).
+ */
+typedef struct ISO9660RRIPNM
+{
+ /** Header (ISO9660RRIPNM_SIG1, ISO9660RRIPNM_SIG2, ISO9660RRIPNM_VER). */
+ ISO9660SUSPHDR Hdr;
+ /** Flags (ISO9660RRIP_NM_F_XXX). */
+ uint8_t fFlags;
+ /** The name part (if any). */
+ char achName[RT_FLEXIBLE_ARRAY_IN_NESTED_UNION];
+} ISO9660RRIPNM;
+AssertCompileMemberOffset(ISO9660RRIPNM, achName, 5);
+/** Pointer to a RRIP name entry. */
+typedef ISO9660RRIPNM *PISO9660RRIPNM;
+/** Pointer to a const RRIP name entry. */
+typedef ISO9660RRIPNM const *PCISO9660RRIPNM;
+#define ISO9660RRIPNM_SIG1 'N' /**< RRIP name entry signature byte 1. */
+#define ISO9660RRIPNM_SIG2 'M' /**< RRIP name entry signature byte 2. */
+#define ISO9660RRIPNM_VER 1 /**< RRIP name entry version number. */
+/** @name ISO9660RRIP_NM_F_XXX - Name flags.
+ * @note These matches ISO9660RRIP_SL_C_XXX.
+ * @{ */
+/** Indicates there are more 'NM' entries. */
+#define ISO9660RRIP_NM_F_CONTINUE UINT8_C(0x01)
+/** Refer to '.' (the current dir). */
+#define ISO9660RRIP_NM_F_CURRENT UINT8_C(0x02)
+/** Refer to '..' (the parent dir). */
+#define ISO9660RRIP_NM_F_PARENT UINT8_C(0x04)
+/** Reserved / historically was uname network node name. */
+#define ISO9660RRIP_NM_F_UNAME UINT8_C(0x20)
+/** Reserved mask (considers historical bits reserved). */
+#define ISO9660RRIP_NM_F_RESERVED_MASK UINT8_C(0xf8)
+/** @} */
+
+/** Maximum name length in one 'NM' entry. */
+#define ISO9660RRIPNM_MAX_NAME_LEN 250
+
+
+/**
+ * Rock ridge interchange protocol - child link entry (CL).
+ *
+ * This is used for relocated directories. Relocated directries are employed
+ * to bypass the ISO 9660 maximum tree depth of 8.
+ *
+ * The size of the directory and everything else is found in the '.' entry in
+ * the specified location. Only the name (NM or dir rec) and this link record
+ * should be used.
+ */
+typedef struct ISO9660RRIPCL
+{
+ /** Header (ISO9660RRIPCL_SIG1, ISO9660RRIPCL_SIG2,
+ * ISO9660RRIPCL_LEN, ISO9660RRIPCL_VER). */
+ ISO9660SUSPHDR Hdr;
+ /** The offset of the directory data (block offset). */
+ ISO9660U32 offExtend;
+} ISO9660RRIPCL;
+/** Pointer to a RRIP child link entry. */
+typedef ISO9660RRIPCL *PISO9660RRIPCL;
+/** Pointer to a const RRIP child link entry. */
+typedef ISO9660RRIPCL const *PCISO9660RRIPCL;
+#define ISO9660RRIPCL_SIG1 'C' /**< RRIP child link entry signature byte 1. */
+#define ISO9660RRIPCL_SIG2 'L' /**< RRIP child link entry signature byte 2. */
+#define ISO9660RRIPCL_VER 1 /**< RRIP child link entry version number. */
+#define ISO9660RRIPCL_LEN 12 /**< RRIP child link entry length. */
+AssertCompileSize(ISO9660RRIPCL, ISO9660RRIPCL_LEN);
+
+
+/**
+ * Rock ridge interchange protocol - parent link entry (PL).
+ *
+ * This is used in relocated directories. Relocated directries are employed
+ * to bypass the ISO 9660 maximum tree depth of 8.
+ *
+ * The size of the directory and everything else is found in the '.' entry in
+ * the specified location. Only the name (NM or dir rec) and this link record
+ * should be used.
+ */
+typedef struct ISO9660RRIPPL
+{
+ /** Header (ISO9660RRIPPL_SIG1, ISO9660RRIPPL_SIG2,
+ * ISO9660RRIPPL_LEN, ISO9660RRIPPL_VER). */
+ ISO9660SUSPHDR Hdr;
+ /** The offset of the directory data (block offset). */
+ ISO9660U32 offExtend;
+} ISO9660RRIPPL;
+/** Pointer to a RRIP parent link entry. */
+typedef ISO9660RRIPPL *PISO9660RRIPPL;
+/** Pointer to a const RRIP parent link entry. */
+typedef ISO9660RRIPPL const *PCISO9660RRIPPL;
+#define ISO9660RRIPPL_SIG1 'P' /**< RRIP parent link entry signature byte 1. */
+#define ISO9660RRIPPL_SIG2 'L' /**< RRIP parent link entry signature byte 2. */
+#define ISO9660RRIPPL_VER 1 /**< RRIP parent link entry version number. */
+#define ISO9660RRIPPL_LEN 12 /**< RRIP parent link entry length. */
+AssertCompileSize(ISO9660RRIPPL, ISO9660RRIPPL_LEN);
+
+
+/**
+ * Rock ridge interchange protocol - relocated entry (RE).
+ *
+ * This is used in the directory record for a relocated directory in the
+ * holding place high up in the directory hierarchy. The system may choose to
+ * ignore/hide entries with this entry present.
+ */
+typedef struct ISO9660RRIPRE
+{
+ /** Header (ISO9660RRIPRE_SIG1, ISO9660RRIPRE_SIG2,
+ * ISO9660RRIPRE_LEN, ISO9660RRIPRE_VER). */
+ ISO9660SUSPHDR Hdr;
+} ISO9660RRIPRE;
+/** Pointer to a RRIP parent link entry. */
+typedef ISO9660RRIPRE *PISO9660RRIPRE;
+/** Pointer to a const RRIP parent link entry. */
+typedef ISO9660RRIPRE const *PCISO9660RRIPRE;
+#define ISO9660RRIPRE_SIG1 'R' /**< RRIP relocated entry signature byte 1. */
+#define ISO9660RRIPRE_SIG2 'E' /**< RRIP relocated entry signature byte 2. */
+#define ISO9660RRIPRE_VER 1 /**< RRIP relocated entry version number. */
+#define ISO9660RRIPRE_LEN 4 /**< RRIP relocated entry length. */
+AssertCompileSize(ISO9660RRIPRE, ISO9660RRIPRE_LEN);
+
+
+/**
+ * Rock ridge interchange protocol - sparse file entry (SF).
+ */
+#pragma pack(1)
+typedef struct ISO9660RRIPSF
+{
+ /** Header (ISO9660RRIPSF_SIG1, ISO9660RRIPSF_SIG2,
+ * ISO9660RRIPSF_LEN, ISO9660RRIPSF_VER). */
+ ISO9660SUSPHDR Hdr;
+ /** The high 32-bits of the 64-bit sparse file size. */
+ ISO9660U32 cbSparseHi;
+ /** The low 32-bits of the 64-bit sparse file size. */
+ ISO9660U32 cbSparseLo;
+ /** The table depth. */
+ uint8_t cDepth;
+} ISO9660RRIPSF;
+#pragma pack()
+/** Pointer to a RRIP symbolic link entry. */
+typedef ISO9660RRIPSF *PISO9660RRIPSF;
+/** Pointer to a const RRIP symbolic link entry. */
+typedef ISO9660RRIPSF const *PCISO9660RRIPSF;
+#define ISO9660RRIPSF_SIG1 'S' /**< RRIP spare file entry signature byte 1. */
+#define ISO9660RRIPSF_SIG2 'F' /**< RRIP spare file entry signature byte 2. */
+#define ISO9660RRIPSF_VER 1 /**< RRIP spare file entry version number. */
+#define ISO9660RRIPSF_LEN 21 /**< RRIP spare file entry length. */
+AssertCompileSize(ISO9660RRIPSF, ISO9660RRIPSF_LEN);
+
+/** @name ISO9660RRIP_SF_TAB_F_XXX - Sparse table format.
+ * @{ */
+/** The 24-bit logical block number mask.
+ * This is somewhat complicated, see docs. MBZ for EMPTY. */
+#define ISO9660RRIP_SF_TAB_F_BLOCK_MASK UINT32_C(0x00ffffff)
+/** Reserved bits, MBZ. */
+#define ISO9660RRIP_SF_TAB_F_RESERVED RT_BIT_32()
+/** References a sub-table with 256 entries (ISO9660U32). */
+#define ISO9660RRIP_SF_TAB_F_TABLE RT_BIT_32(30)
+/** Zero data region. */
+#define ISO9660RRIP_SF_TAB_F_EMPTY RT_BIT_32(31)
+/** @} */
+
+
+/**
+ * SUSP and RRIP union.
+ */
+typedef union ISO9660SUSPUNION
+{
+ ISO9660SUSPHDR Hdr; /**< SUSP header . */
+ ISO9660SUSPCE CE; /**< SUSP continuation entry. */
+ ISO9660SUSPPD PD; /**< SUSP padding entry. */
+ ISO9660SUSPSP SP; /**< SUSP system use protocol entry. */
+ ISO9660SUSPST ST; /**< SUSP terminator entry. */
+ ISO9660SUSPER ER; /**< SUSP extension record entry. */
+ ISO9660SUSPES ES; /**< SUSP extension sequence entry. */
+ ISO9660RRIPRR RR; /**< RRIP optimization entry. */
+ ISO9660RRIPPX PX; /**< RRIP posix attribute entry. */
+ ISO9660RRIPTF TF; /**< RRIP timestamp entry. */
+ ISO9660RRIPPN PN; /**< RRIP posix device number entry. */
+ ISO9660RRIPSF SF; /**< RRIP sparse file entry. */
+ ISO9660RRIPSL SL; /**< RRIP symbolic link entry. */
+ ISO9660RRIPNM NM; /**< RRIP name entry. */
+ ISO9660RRIPCL CL; /**< RRIP child link entry. */
+ ISO9660RRIPPL PL; /**< RRIP parent link entry. */
+ ISO9660RRIPRE RE; /**< RRIP relocated entry. */
+} ISO9660SUSPUNION;
+/** Pointer to a SUSP and RRIP union. */
+typedef ISO9660SUSPUNION *PISO9660SUSPUNION;
+/** Pointer to a const SUSP and RRIP union. */
+typedef ISO9660SUSPUNION *PCISO9660SUSPUNION;
+
+
+/** @} */
+
+#endif /* !IPRT_INCLUDED_formats_iso9660_h */
+
diff --git a/include/iprt/formats/lx.h b/include/iprt/formats/lx.h
new file mode 100644
index 00000000..b01a5ab8
--- /dev/null
+++ b/include/iprt/formats/lx.h
@@ -0,0 +1,510 @@
+/* $Id: lx.h $ */
+/** @file
+ * LX structures, types and defines.
+ */
+
+/*
+ * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix@anduin.net>
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef IPRT_INCLUDED_formats_lx_h
+#define IPRT_INCLUDED_formats_lx_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+#include <iprt/assertcompile.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_formats_lx LX executable format (OS/2)
+ * @ingroup grp_rt_formats
+ * @{ */
+
+#ifndef IMAGE_OS2_SIGNATURE_LX
+/** LX signature ("LX") */
+# define IMAGE_LX_SIGNATURE K_LE2H_U16('L' | ('X' << 8))
+#endif
+
+/**
+ * Linear eXecutable header.
+ * This structure is exactly 196 bytes long.
+ */
+typedef struct e32_exe
+{
+ uint8_t e32_magic[2];
+ uint8_t e32_border;
+ uint8_t e32_worder;
+ uint32_t e32_level;
+ uint16_t e32_cpu;
+ uint16_t e32_os;
+ uint32_t e32_ver;
+ uint32_t e32_mflags;
+ uint32_t e32_mpages;
+ uint32_t e32_startobj;
+ uint32_t e32_eip;
+ uint32_t e32_stackobj;
+ uint32_t e32_esp;
+ uint32_t e32_pagesize;
+ uint32_t e32_pageshift;
+ /** The size of the fixup section.
+ * The fixup section consists of the fixup page table, the fixup record table,
+ * the import module table, and the import procedure name table.
+ */
+ uint32_t e32_fixupsize;
+ uint32_t e32_fixupsum;
+ /** The size of the resident loader section.
+ * This includes the object table, the object page map table, the resource table, the resident name table,
+ * the entry table, the module format directives table, and the page checksum table (?). */
+ uint32_t e32_ldrsize;
+ /** The checksum of the loader section. 0 if not calculated. */
+ uint32_t e32_ldrsum;
+ /** The offset of the object table relative to this structure. */
+ uint32_t e32_objtab;
+ /** Count of objects. */
+ uint32_t e32_objcnt;
+ /** The offset of the object page map table relative to this structure. */
+ uint32_t e32_objmap;
+ /** The offset of the object iterated pages (whatever this is used for) relative to the start of the file. */
+ uint32_t e32_itermap;
+ /** The offset of the resource table relative to this structure. */
+ uint32_t e32_rsrctab;
+ /** The number of entries in the resource table. */
+ uint32_t e32_rsrccnt;
+ /** The offset of the resident name table relative to this structure. */
+ uint32_t e32_restab;
+ /** The offset of the entry (export) table relative to this structure. */
+ uint32_t e32_enttab;
+ /** The offset of the module format directives table relative to this structure. */
+ uint32_t e32_dirtab;
+ /** The number of entries in the module format directives table. */
+ uint32_t e32_dircnt;
+ /** The offset of the fixup page table relative to this structure. */
+ uint32_t e32_fpagetab;
+ /** The offset of the fixup record table relative to this structure. */
+ uint32_t e32_frectab;
+ /** The offset of the import module name table relative to this structure. */
+ uint32_t e32_impmod;
+ /** The number of entries in the import module name table. */
+ uint32_t e32_impmodcnt;
+ /** The offset of the import procedure name table relative to this structure. */
+ uint32_t e32_impproc;
+ /** The offset of the page checksum table relative to this structure. */
+ uint32_t e32_pagesum;
+ /** The offset of the data pages relative to the start of the file. */
+ uint32_t e32_datapage;
+ /** The number of preload pages (ignored). */
+ uint32_t e32_preload;
+ /** The offset of the non-resident name table relative to the start of the file. */
+ uint32_t e32_nrestab;
+ /** The size of the non-resident name table. */
+ uint32_t e32_cbnrestab;
+ uint32_t e32_nressum;
+ uint32_t e32_autodata;
+ uint32_t e32_debuginfo;
+ uint32_t e32_debuglen;
+ uint32_t e32_instpreload;
+ uint32_t e32_instdemand;
+ uint32_t e32_heapsize;
+ uint32_t e32_stacksize;
+ uint8_t e32_res3[20];
+} e32_exe;
+AssertCompileSize(struct e32_exe, 196);
+
+/** e32_magic[0] */
+#define E32MAGIC1 'L'
+/** e32_magic[1] */
+#define E32MAGIC2 'X'
+/** MAKEWORD(e32_magic[0], e32_magic[1]) */
+#define E32MAGIC 0x584c
+/** e32_border - little endian */
+#define E32LEBO 0
+/** e32_border - big endian */
+#define E32BEBO 1
+/** e32_worder - little endian */
+#define E32LEWO 0
+/** e32_worder - big endian */
+#define E32BEWO 1
+/** e32_level */
+#define E32LEVEL UINT32_C(0)
+/** e32_cpu - 80286 */
+#define E32CPU286 1
+/** e32_cpu - 80386 */
+#define E32CPU386 2
+/** e32_cpu - 80486 */
+#define E32CPU486 3
+/** e32_pagesize */
+#define OBJPAGELEN UINT32_C(0x1000)
+
+
+/** @name e32_mflags
+ * @{ */
+/** App Type: Fullscreen only. */
+#define E32NOPMW UINT32_C(0x00000100)
+/** App Type: PM API. */
+#define E32PMAPI UINT32_C(0x00000300)
+/** App Type: PM VIO compatible. */
+#define E32PMW UINT32_C(0x00000200)
+/** Application type mask. */
+#define E32APPMASK UINT32_C(0x00000300)
+/** Executable module. */
+#define E32MODEXE UINT32_C(0x00000000)
+/** Dynamic link library (DLL / library) module. */
+#define E32MODDLL UINT32_C(0x00008000)
+/** Protected memory DLL. */
+#define E32PROTDLL UINT32_C(0x00010000)
+/** Physical Device Driver. */
+#define E32MODPDEV UINT32_C(0x00020000)
+/** Virtual Device Driver. */
+#define E32MODVDEV UINT32_C(0x00028000)
+/** Device driver */
+#define E32DEVICE E32MODPDEV
+/** Dynamic link library (DLL / library) module. */
+#define E32NOTP E32MODDLL
+/** Protected memory DLL. */
+#define E32MODPROTDLL (E32MODDLL | E32PROTDLL)
+/** Module Type mask. */
+#define E32MODMASK UINT32_C(0x00038000)
+/** Not loadable (linker error). */
+#define E32NOLOAD UINT32_C(0x00002000)
+/** No internal fixups. */
+#define E32NOINTFIX UINT32_C(0x00000010)
+/** No external fixups (i.e. imports). */
+#define E32NOEXTFIX UINT32_C(0x00000020)
+/** System DLL, no internal fixups. */
+#define E32SYSDLL UINT32_C(0x00000008)
+/** Global (set) or per instance (cleared) library initialization. */
+#define E32LIBINIT UINT32_C(0x00000004)
+/** Global (set) or per instance (cleared) library termination. */
+#define E32LIBTERM UINT32_C(0x40000000)
+/** Indicates when set in an executable that the process isn't SMP safe. */
+#define E32NOTMPSAFE UINT32_C(0x00080000)
+/** @} */
+
+
+/** @defgroup grp_rt_formats_lx_relocs Relocations (aka Fixups).
+ * @{ */
+typedef union r32_offset
+{
+ uint16_t offset16;
+ uint32_t offset32;
+} r32_offset;
+AssertCompileSize(r32_offset, 4);
+
+/** A relocation.
+ * @remark this structure isn't very usable since LX relocations comes in too many size variations.
+ */
+#pragma pack(1)
+typedef struct r32_rlc
+{
+ uint8_t nr_stype;
+ uint8_t nr_flags;
+ int16_t r32_soff;
+ uint16_t r32_objmod;
+
+ union targetid
+ {
+ r32_offset intref;
+ union extfixup
+ {
+ r32_offset proc;
+ uint32_t ord;
+ } extref;
+ struct addfixup
+ {
+ uint16_t entry;
+ r32_offset addval;
+ } addfix;
+ } r32_target;
+ uint16_t r32_srccount;
+ uint16_t r32_chain;
+} r32_rlc;
+#pragma pack()
+AssertCompileSize(r32_rlc, 16);
+/** @} */
+
+/** @name Some attempt at size constanstants.
+ * @{
+ */
+#define RINTSIZE16 8
+#define RINTSIZE32 10
+#define RORDSIZE 8
+#define RNAMSIZE16 8
+#define RNAMSIZE32 10
+#define RADDSIZE16 10
+#define RADDSIZE32 12
+/** @} */
+
+/** @name nr_stype (source flags)
+ * @{ */
+#define NRSBYT 0x00
+#define NRSSEG 0x02
+#define NRSPTR 0x03
+#define NRSOFF 0x05
+#define NRPTR48 0x06
+#define NROFF32 0x07
+#define NRSOFF32 0x08
+#define NRSTYP 0x0f
+#define NRSRCMASK 0x0f
+#define NRALIAS 0x10
+#define NRCHAIN 0x20
+/** @} */
+
+/** @name nr_flags (target flags)
+ * @{ */
+#define NRRINT 0x00
+#define NRRORD 0x01
+#define NRRNAM 0x02
+#define NRRENT 0x03
+#define NRRTYP 0x03
+#define NRADD 0x04
+#define NRICHAIN 0x08
+#define NR32BITOFF 0x10
+#define NR32BITADD 0x20
+#define NR16OBJMOD 0x40
+#define NR8BITORD 0x80
+/** @} */
+
+/** @} */
+
+
+/** @defgroup grp_rt_formats_lx_object_tab The Object Table (aka segment table)
+ * @{ */
+
+/** The Object Table Entry. */
+typedef struct o32_obj
+{
+ /** The size of the object. */
+ uint32_t o32_size;
+ /** The base address of the object. */
+ uint32_t o32_base;
+ /** Object flags. */
+ uint32_t o32_flags;
+ /** Page map index. */
+ uint32_t o32_pagemap;
+ /** Page map size. (doesn't need to be o32_size >> page shift). */
+ uint32_t o32_mapsize;
+ /** Reserved */
+ uint32_t o32_reserved;
+} o32_obj;
+AssertCompileSize(o32_obj, 24);
+
+/** @name o32_flags
+ * @{ */
+/** Read access. */
+#define OBJREAD UINT32_C(0x00000001)
+/** Write access. */
+#define OBJWRITE UINT32_C(0x00000002)
+/** Execute access. */
+#define OBJEXEC UINT32_C(0x00000004)
+/** Resource object. */
+#define OBJRSRC UINT32_C(0x00000008)
+/** The object is discarable (i.e. don't swap, just load in pages from the executable).
+ * This overlaps a bit with object type. */
+#define OBJDISCARD UINT32_C(0x00000010)
+/** The object is shared. */
+#define OBJSHARED UINT32_C(0x00000020)
+/** The object has preload pages. */
+#define OBJPRELOAD UINT32_C(0x00000040)
+/** The object has invalid pages. */
+#define OBJINVALID UINT32_C(0x00000080)
+/** Non-permanent, link386 bug. */
+#define LNKNONPERM UINT32_C(0x00000600)
+/** Non-permanent, correct 'value'. */
+#define OBJNONPERM UINT32_C(0x00000000)
+/** Obj Type: The object is permanent and swappable. */
+#define OBJPERM UINT32_C(0x00000100)
+/** Obj Type: The object is permanent and resident (i.e. not swappable). */
+#define OBJRESIDENT UINT32_C(0x00000200)
+/** Obj Type: The object is resident and contigious. */
+#define OBJCONTIG UINT32_C(0x00000300)
+/** Obj Type: The object is permanent and long locable. */
+#define OBJDYNAMIC UINT32_C(0x00000400)
+/** Object type mask. */
+#define OBJTYPEMASK UINT32_C(0x00000700)
+/** x86: The object require an 16:16 alias. */
+#define OBJALIAS16 UINT32_C(0x00001000)
+/** x86: Big/Default selector setting, i.e. toggle 32-bit or 16-bit. */
+#define OBJBIGDEF UINT32_C(0x00002000)
+/** x86: conforming selector setting (weird stuff). */
+#define OBJCONFORM UINT32_C(0x00004000)
+/** x86: IOPL. */
+#define OBJIOPL UINT32_C(0x00008000)
+/** @} */
+
+/** A Object Page Map Entry. */
+typedef struct o32_map
+{
+ /** The file offset of the page. */
+ uint32_t o32_pagedataoffset;
+ /** The number of bytes of raw page data. */
+ uint16_t o32_pagesize;
+ /** Per page flags describing how the page is encoded in the file. */
+ uint16_t o32_pageflags;
+} o32_map;
+AssertCompileSize(o32_map, 8);
+
+/** @name o32 o32_pageflags
+ * @{
+ */
+/** Raw page (uncompressed) in the file. */
+#define VALID UINT16_C(0x0000)
+/** RLE encoded page in file. */
+#define ITERDATA UINT16_C(0x0001)
+/** Invalid page, nothing in the file. */
+#define INVALID UINT16_C(0x0002)
+/** Zero page, nothing in file. */
+#define ZEROED UINT16_C(0x0003)
+/** range of pages (what is this?) */
+#define RANGE UINT16_C(0x0004)
+/** Compressed page in file. */
+#define ITERDATA2 UINT16_C(0x0005)
+/** @} */
+
+
+/** Iteration Record format (RLE compressed page). */
+#pragma pack(1)
+typedef struct LX_Iter
+{
+ /** Number of iterations. */
+ uint16_t LX_nIter;
+ /** The number of bytes that's being iterated. */
+ uint16_t LX_nBytes;
+ /** The bytes. */
+ uint8_t LX_Iterdata;
+} LX_Iter;
+#pragma pack()
+AssertCompileSize(LX_Iter, 5);
+
+/** @} */
+
+
+/** A Resource Table Entry */
+#pragma pack(1)
+typedef struct rsrc32
+{
+ /** Resource Type. */
+ uint16_t type;
+ /** Resource ID. */
+ uint16_t name;
+ /** Resource size in bytes. */
+ uint32_t cb;
+ /** The index of the object containing the resource. */
+ uint16_t obj;
+ /** Offset of the resource that within the object. */
+ uint32_t offset;
+} rsrc32;
+#pragma pack()
+AssertCompileSize(rsrc32, 14);
+
+
+/** @defgroup grp_rt_formats_lx_entry_tab The Entry Table (aka Export Table)
+ * @{ */
+
+/** Entry bundle.
+ * Header descripting up to 255 entries that follows immediatly after this structure. */
+typedef struct b32_bundle
+{
+ /** The number of entries. */
+ uint8_t b32_cnt;
+ /** The type of bundle. */
+ uint8_t b32_type;
+ /** The index of the object containing these entry points. */
+ uint16_t b32_obj;
+} b32_bundle;
+AssertCompileSize(b32_bundle, 4);
+
+/** @name b32_type
+ * @{ */
+/** Empty bundle, filling up unused ranges of ordinals. */
+#define EMPTY 0x00
+/** 16-bit offset entry point. */
+#define ENTRY16 0x01
+/** 16-bit callgate entry point. */
+#define GATE16 0x02
+/** 32-bit offset entry point. */
+#define ENTRY32 0x03
+/** Forwarder entry point. */
+#define ENTRYFWD 0x04
+/** Typing information present indicator. */
+#define TYPEINFO 0x80
+/** @} */
+
+
+/** Entry point. */
+#pragma pack(1)
+typedef struct e32_entry
+{
+ /** Entry point flags */
+ uint8_t e32_flags; /* Entry point flags */
+ union entrykind
+ {
+ /** ENTRY16 or ENTRY32. */
+ r32_offset e32_offset;
+ /** GATE16 */
+ struct scallgate
+ {
+ /** Offset into segment. */
+ uint16_t offset;
+ /** The callgate selector */
+ uint16_t callgate;
+ } e32_callgate;
+ /** ENTRYFWD */
+ struct fwd
+ {
+ /** Module ordinal number (i.e. into the import module table). */
+ uint16_t modord;
+ /** Procedure name or ordinal number. */
+ uint32_t value;
+ } e32_fwd;
+ } e32_variant;
+} e32_entry;
+#pragma pack()
+
+/** @name e32_flags
+ * @{ */
+/** Exported entry (set) or private entry (clear). */
+#define E32EXPORT 0x01
+/** Uses shared data. */
+#define E32SHARED 0x02
+/** Parameter word count mask. */
+#define E32PARAMS 0xf8
+/** ENTRYFWD: Imported by ordinal (set) or by name (clear). */
+#define FWD_ORDINAL 0x01
+/** @} */
+
+/** @name dunno
+ * @{ */
+#define FIXENT16 3
+#define FIXENT32 5
+#define GATEENT16 5
+#define FWDENT 7
+/** @} */
+
+/** @} */
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_formats_lx_h */
+
diff --git a/include/iprt/formats/mach-o.h b/include/iprt/formats/mach-o.h
new file mode 100644
index 00000000..75fe0ed2
--- /dev/null
+++ b/include/iprt/formats/mach-o.h
@@ -0,0 +1,860 @@
+/* $Id: mach-o.h $ */
+/** @file
+ * IPRT - Mach-O Structures and Constants.
+ */
+
+/*
+ * Copyright (C) 2011-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_formats_mach_o_h
+#define IPRT_INCLUDED_formats_mach_o_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+#include <iprt/assertcompile.h>
+
+#ifndef CPU_ARCH_MASK
+
+/* cputype */
+#define CPU_ARCH_MASK INT32_C(0xff000000)
+#define CPU_ARCH_ABI64 INT32_C(0x01000000)
+#define CPU_ARCH_ABI64_32 INT32_C(0x02000000) /**< LP32 on 64-bit hardware */
+
+#define CPU_TYPE_ANY INT32_C(-1)
+#define CPU_TYPE_VAX INT32_C(1)
+#define CPU_TYPE_MC680x0 INT32_C(6)
+#define CPU_TYPE_X86 INT32_C(7)
+#define CPU_TYPE_I386 CPU_TYPE_X86
+#define CPU_TYPE_X86_64 (CPU_TYPE_X86 | CPU_ARCH_ABI64)
+#define CPU_TYPE_MC98000 INT32_C(10)
+#define CPU_TYPE_HPPA INT32_C(11)
+#define CPU_TYPE_ARM INT32_C(12)
+#define CPU_TYPE_ARM32 CPU_TYPE_ARM
+#define CPU_TYPE_ARM64 (CPU_TYPE_ARM | CPU_ARCH_ABI64)
+#define CPU_TYPE_ARM64_32 (CPU_TYPE_ARM | CPU_ARCH_ABI64_32)
+#define CPU_TYPE_MC88000 INT32_C(13)
+#define CPU_TYPE_SPARC INT32_C(14)
+#define CPU_TYPE_I860 INT32_C(15)
+#define CPU_TYPE_POWERPC INT32_C(18)
+#define CPU_TYPE_POWERPC64 (CPU_TYPE_POWERPC | CPU_ARCH_ABI64)
+
+/* cpusubtype */
+#define CPU_SUBTYPE_MULTIPLE INT32_C(-1)
+#define CPU_SUBTYPE_LITTLE_ENDIAN INT32_C(0)
+#define CPU_SUBTYPE_BIG_ENDIAN INT32_C(1)
+
+#define CPU_SUBTYPE_VAX_ALL INT32_C(0)
+#define CPU_SUBTYPE_VAX780 INT32_C(1)
+#define CPU_SUBTYPE_VAX785 INT32_C(2)
+#define CPU_SUBTYPE_VAX750 INT32_C(3)
+#define CPU_SUBTYPE_VAX730 INT32_C(4)
+#define CPU_SUBTYPE_UVAXI INT32_C(5)
+#define CPU_SUBTYPE_UVAXII INT32_C(6)
+#define CPU_SUBTYPE_VAX8200 INT32_C(7)
+#define CPU_SUBTYPE_VAX8500 INT32_C(8)
+#define CPU_SUBTYPE_VAX8600 INT32_C(9)
+#define CPU_SUBTYPE_VAX8650 INT32_C(10)
+#define CPU_SUBTYPE_VAX8800 INT32_C(11)
+#define CPU_SUBTYPE_UVAXIII INT32_C(12)
+
+#define CPU_SUBTYPE_MC680x0_ALL INT32_C(1)
+#define CPU_SUBTYPE_MC68030 INT32_C(1)
+#define CPU_SUBTYPE_MC68040 INT32_C(2)
+#define CPU_SUBTYPE_MC68030_ONLY INT32_C(3)
+
+#define CPU_SUBTYPE_INTEL(fam, model) ( (int32_t )(((model) << 4) | (fam)) )
+#define CPU_SUBTYPE_INTEL_FAMILY(subtype) ( (subtype) & 0xf )
+#define CPU_SUBTYPE_INTEL_MODEL(subtype) ( (subtype) >> 4 )
+#define CPU_SUBTYPE_INTEL_FAMILY_MAX 0xf
+#define CPU_SUBTYPE_INTEL_MODEL_ALL 0
+
+#define CPU_SUBTYPE_I386_ALL CPU_SUBTYPE_INTEL(3, 0)
+#define CPU_SUBTYPE_386 CPU_SUBTYPE_INTEL(3, 0)
+#define CPU_SUBTYPE_486 CPU_SUBTYPE_INTEL(4, 0)
+#define CPU_SUBTYPE_486SX CPU_SUBTYPE_INTEL(4, 8)
+#define CPU_SUBTYPE_586 CPU_SUBTYPE_INTEL(5, 0)
+#define CPU_SUBTYPE_PENT CPU_SUBTYPE_INTEL(5, 0)
+#define CPU_SUBTYPE_PENTPRO CPU_SUBTYPE_INTEL(6, 1)
+#define CPU_SUBTYPE_PENTII_M3 CPU_SUBTYPE_INTEL(6, 3)
+#define CPU_SUBTYPE_PENTII_M5 CPU_SUBTYPE_INTEL(6, 5)
+#define CPU_SUBTYPE_CELERON CPU_SUBTYPE_INTEL(7, 6)
+#define CPU_SUBTYPE_CELERON_MOBILE CPU_SUBTYPE_INTEL(7, 7)
+#define CPU_SUBTYPE_PENTIUM_3 CPU_SUBTYPE_INTEL(8, 0)
+#define CPU_SUBTYPE_PENTIUM_3_M CPU_SUBTYPE_INTEL(8, 1)
+#define CPU_SUBTYPE_PENTIUM_3_XEON CPU_SUBTYPE_INTEL(8, 2)
+#define CPU_SUBTYPE_PENTIUM_M CPU_SUBTYPE_INTEL(9, 0)
+#define CPU_SUBTYPE_PENTIUM_4 CPU_SUBTYPE_INTEL(10, 0)
+#define CPU_SUBTYPE_PENTIUM_4_M CPU_SUBTYPE_INTEL(10, 1)
+#define CPU_SUBTYPE_ITANIUM CPU_SUBTYPE_INTEL(11, 0)
+#define CPU_SUBTYPE_ITANIUM_2 CPU_SUBTYPE_INTEL(11, 1)
+#define CPU_SUBTYPE_XEON CPU_SUBTYPE_INTEL(12, 0)
+#define CPU_SUBTYPE_XEON_MP CPU_SUBTYPE_INTEL(12, 1)
+
+#define CPU_SUBTYPE_X86_ALL INT32_C(3)
+#define CPU_SUBTYPE_X86_64_ALL INT32_C(3)
+#define CPU_SUBTYPE_X86_ARCH1 INT32_C(4)
+
+#define CPU_SUBTYPE_MIPS_ALL INT32_C(0)
+#define CPU_SUBTYPE_MIPS_R2300 INT32_C(1)
+#define CPU_SUBTYPE_MIPS_R2600 INT32_C(2)
+#define CPU_SUBTYPE_MIPS_R2800 INT32_C(3)
+#define CPU_SUBTYPE_MIPS_R2000a INT32_C(4)
+#define CPU_SUBTYPE_MIPS_R2000 INT32_C(5)
+#define CPU_SUBTYPE_MIPS_R3000a INT32_C(6)
+#define CPU_SUBTYPE_MIPS_R3000 INT32_C(7)
+
+#define CPU_SUBTYPE_MC98000_ALL INT32_C(0)
+#define CPU_SUBTYPE_MC98601 INT32_C(1)
+
+#define CPU_SUBTYPE_HPPA_ALL INT32_C(0)
+#define CPU_SUBTYPE_HPPA_7100 INT32_C(0)
+#define CPU_SUBTYPE_HPPA_7100LC INT32_C(1)
+
+#define CPU_SUBTYPE_ARM_ALL INT32_C(0)
+#define CPU_SUBTYPE_ARM_V4T INT32_C(5)
+#define CPU_SUBTYPE_ARM_V6 INT32_C(6)
+#define CPU_SUBTYPE_ARM_V5TEJ INT32_C(7)
+#define CPU_SUBTYPE_ARM_XSCALE INT32_C(8)
+#define CPU_SUBTYPE_ARM_V7 INT32_C(9)
+#define CPU_SUBTYPE_ARM_V7F INT32_C(10)
+#define CPU_SUBTYPE_ARM_V7S INT32_C(11)
+#define CPU_SUBTYPE_ARM_V7K INT32_C(12)
+#define CPU_SUBTYPE_ARM_V8 INT32_C(13)
+#define CPU_SUBTYPE_ARM_V6M INT32_C(14)
+#define CPU_SUBTYPE_ARM_V7M INT32_C(15)
+#define CPU_SUBTYPE_ARM_V7EM INT32_C(16)
+#define CPU_SUBTYPE_ARM_V8M INT32_C(17)
+
+#define CPU_SUBTYPE_ARM64_ALL INT32_C(0)
+#define CPU_SUBTYPE_ARM64_V8 INT32_C(1)
+#define CPU_SUBTYPE_ARM64E INT32_C(2)
+#define CPU_SUBTYPE_ARM64_PTR_AUTH_MASK UINT32_C(0x0f000000)
+#define CPU_SUBTYPE_ARM64_PTR_AUTH_VERSION(a) ( ((a) & CPU_SUBTYPE_ARM64_PTR_AUTH_MASK) >> 24 )
+
+#define CPU_SUBTYPE_ARM64_32_ALL INT32_C(0)
+#define CPU_SUBTYPE_ARM64_32_V8 INT32_C(1)
+
+#define CPU_SUBTYPE_MC88000_ALL INT32_C(0)
+#define CPU_SUBTYPE_MC88100 INT32_C(1)
+#define CPU_SUBTYPE_MC88110 INT32_C(2)
+
+#define CPU_SUBTYPE_SPARC_ALL INT32_C(0)
+
+#define CPU_SUBTYPE_I860_ALL INT32_C(0)
+#define CPU_SUBTYPE_I860_860 INT32_C(1)
+
+#define CPU_SUBTYPE_POWERPC_ALL INT32_C(0)
+#define CPU_SUBTYPE_POWERPC_601 INT32_C(1)
+#define CPU_SUBTYPE_POWERPC_602 INT32_C(2)
+#define CPU_SUBTYPE_POWERPC_603 INT32_C(3)
+#define CPU_SUBTYPE_POWERPC_603e INT32_C(4)
+#define CPU_SUBTYPE_POWERPC_603ev INT32_C(5)
+#define CPU_SUBTYPE_POWERPC_604 INT32_C(6)
+#define CPU_SUBTYPE_POWERPC_604e INT32_C(7)
+#define CPU_SUBTYPE_POWERPC_620 INT32_C(8)
+#define CPU_SUBTYPE_POWERPC_750 INT32_C(9)
+#define CPU_SUBTYPE_POWERPC_7400 INT32_C(10)
+#define CPU_SUBTYPE_POWERPC_7450 INT32_C(11)
+#define CPU_SUBTYPE_POWERPC_Max INT32_C(10)
+#define CPU_SUBTYPE_POWERPC_SCVger INT32_C(11)
+#define CPU_SUBTYPE_POWERPC_970 INT32_C(100)
+
+#define CPU_SUBTYPE_MASK UINT32_C(0xff000000)
+#define CPU_SUBTYPE_LIB64 UINT32_C(0x80000000)
+
+#endif /* !CPU_ARCH_MASK */
+
+
+typedef struct fat_header
+{
+ uint32_t magic;
+ uint32_t nfat_arch;
+} fat_header_t;
+
+#ifndef IMAGE_FAT_SIGNATURE
+# define IMAGE_FAT_SIGNATURE UINT32_C(0xcafebabe)
+#endif
+#ifndef IMAGE_FAT_SIGNATURE_OE
+# define IMAGE_FAT_SIGNATURE_OE UINT32_C(0xbebafeca)
+#endif
+
+typedef struct fat_arch
+{
+ int32_t cputype;
+ int32_t cpusubtype;
+ uint32_t offset;
+ uint32_t size;
+ uint32_t align;
+} fat_arch_t;
+
+typedef struct mach_header_32
+{
+ uint32_t magic;
+ int32_t cputype;
+ int32_t cpusubtype;
+ uint32_t filetype;
+ uint32_t ncmds;
+ uint32_t sizeofcmds;
+ uint32_t flags;
+} mach_header_32_t;
+
+/* magic */
+#ifndef IMAGE_MACHO32_SIGNATURE
+# define IMAGE_MACHO32_SIGNATURE UINT32_C(0xfeedface)
+#endif
+#ifndef IMAGE_MACHO32_SIGNATURE_OE
+# define IMAGE_MACHO32_SIGNATURE_OE UINT32_C(0xcefaedfe)
+#endif
+#define MH_MAGIC IMAGE_MACHO32_SIGNATURE
+#define MH_CIGAM IMAGE_MACHO32_SIGNATURE_OE
+
+typedef struct mach_header_64
+{
+ uint32_t magic; /**< 0x00 */
+ int32_t cputype; /**< 0x04 */
+ int32_t cpusubtype; /**< 0x08 */
+ uint32_t filetype; /**< 0x0c */
+ uint32_t ncmds; /**< 0x10 */
+ uint32_t sizeofcmds; /**< 0x14 */
+ uint32_t flags; /**< 0x18 */
+ uint32_t reserved; /**< 0x1c */
+} mach_header_64_t;
+AssertCompileSize(mach_header_64_t, 0x20);
+
+/* magic */
+#ifndef IMAGE_MACHO64_SIGNATURE
+# define IMAGE_MACHO64_SIGNATURE UINT32_C(0xfeedfacf)
+#endif
+#ifndef IMAGE_MACHO64_SIGNATURE_OE
+# define IMAGE_MACHO64_SIGNATURE_OE UINT32_C(0xfefaedfe)
+#endif
+#define MH_MAGIC_64 IMAGE_MACHO64_SIGNATURE
+#define MH_CIGAM_64 IMAGE_MACHO64_SIGNATURE_OE
+
+/* mach_header_* filetype */
+#define MH_OBJECT UINT32_C(1)
+#define MH_EXECUTE UINT32_C(2)
+#define MH_FVMLIB UINT32_C(3)
+#define MH_CORE UINT32_C(4)
+#define MH_PRELOAD UINT32_C(5)
+#define MH_DYLIB UINT32_C(6)
+#define MH_DYLINKER UINT32_C(7)
+#define MH_BUNDLE UINT32_C(8)
+#define MH_DYLIB_STUB UINT32_C(9)
+#define MH_DSYM UINT32_C(10)
+#define MH_KEXT_BUNDLE UINT32_C(11)
+
+/* mach_header_* flags */
+#define MH_NOUNDEFS UINT32_C(0x00000001)
+#define MH_INCRLINK UINT32_C(0x00000002)
+#define MH_DYLDLINK UINT32_C(0x00000004)
+#define MH_BINDATLOAD UINT32_C(0x00000008)
+#define MH_PREBOUND UINT32_C(0x00000010)
+#define MH_SPLIT_SEGS UINT32_C(0x00000020)
+#define MH_LAZY_INIT UINT32_C(0x00000040)
+#define MH_TWOLEVEL UINT32_C(0x00000080)
+#define MH_FORCE_FLAT UINT32_C(0x00000100)
+#define MH_NOMULTIDEFS UINT32_C(0x00000200)
+#define MH_NOFIXPREBINDING UINT32_C(0x00000400)
+#define MH_PREBINDABLE UINT32_C(0x00000800)
+#define MH_ALLMODSBOUND UINT32_C(0x00001000)
+#define MH_SUBSECTIONS_VIA_SYMBOLS UINT32_C(0x00002000)
+#define MH_CANONICAL UINT32_C(0x00004000)
+#define MH_WEAK_DEFINES UINT32_C(0x00008000)
+#define MH_BINDS_TO_WEAK UINT32_C(0x00010000)
+#define MH_ALLOW_STACK_EXECUTION UINT32_C(0x00020000)
+#define MH_ROOT_SAFE UINT32_C(0x00040000)
+#define MH_SETUID_SAFE UINT32_C(0x00080000)
+#define MH_NO_REEXPORTED_DYLIBS UINT32_C(0x00100000)
+#define MH_PIE UINT32_C(0x00200000)
+#define MH_DEAD_STRIPPABLE_DYLIB UINT32_C(0x00400000)
+#define MH_HAS_TLV_DESCRIPTORS UINT32_C(0x00800000)
+#define MH_NO_HEAP_EXECUTION UINT32_C(0x01000000)
+#define MH_UNKNOWN UINT32_C(0x80000000)
+#define MH_VALID_FLAGS UINT32_C(0x81ffffff)
+
+
+typedef struct load_command
+{
+ uint32_t cmd;
+ uint32_t cmdsize;
+} load_command_t;
+
+/* load cmd */
+#define LC_REQ_DYLD UINT32_C(0x80000000)
+#define LC_SEGMENT_32 UINT32_C(0x01)
+#define LC_SYMTAB UINT32_C(0x02)
+#define LC_SYMSEG UINT32_C(0x03)
+#define LC_THREAD UINT32_C(0x04)
+#define LC_UNIXTHREAD UINT32_C(0x05)
+#define LC_LOADFVMLIB UINT32_C(0x06)
+#define LC_IDFVMLIB UINT32_C(0x07)
+#define LC_IDENT UINT32_C(0x08)
+#define LC_FVMFILE UINT32_C(0x09)
+#define LC_PREPAGE UINT32_C(0x0a)
+#define LC_DYSYMTAB UINT32_C(0x0b)
+#define LC_LOAD_DYLIB UINT32_C(0x0c)
+#define LC_ID_DYLIB UINT32_C(0x0d)
+#define LC_LOAD_DYLINKER UINT32_C(0x0e)
+#define LC_ID_DYLINKER UINT32_C(0x0f)
+#define LC_PREBOUND_DYLIB UINT32_C(0x10)
+#define LC_ROUTINES UINT32_C(0x11)
+#define LC_SUB_FRAMEWORK UINT32_C(0x12)
+#define LC_SUB_UMBRELLA UINT32_C(0x13)
+#define LC_SUB_CLIENT UINT32_C(0x14)
+#define LC_SUB_LIBRARY UINT32_C(0x15)
+#define LC_TWOLEVEL_HINTS UINT32_C(0x16)
+#define LC_PREBIND_CKSUM UINT32_C(0x17)
+#define LC_LOAD_WEAK_DYLIB (UINT32_C(0x18) | LC_REQ_DYLD)
+#define LC_SEGMENT_64 UINT32_C(0x19)
+#define LC_ROUTINES_64 UINT32_C(0x1a)
+#define LC_UUID UINT32_C(0x1b)
+#define LC_RPATH (UINT32_C(0x1c) | LC_REQ_DYLD)
+#define LC_CODE_SIGNATURE UINT32_C(0x1d)
+#define LC_SEGMENT_SPLIT_INFO UINT32_C(0x1e)
+#define LC_REEXPORT_DYLIB (UINT32_C(0x1f) | LC_REQ_DYLD)
+#define LC_LAZY_LOAD_DYLIB UINT32_C(0x20)
+#define LC_ENCRYPTION_INFO UINT32_C(0x21)
+#define LC_DYLD_INFO UINT32_C(0x22)
+#define LC_DYLD_INFO_ONLY (UINT32_C(0x22) | LC_REQ_DYLD)
+#define LC_LOAD_UPWARD_DYLIB (UINT32_C(0x23) | LC_REQ_DYLD)
+#define LC_VERSION_MIN_MACOSX UINT32_C(0x24)
+#define LC_VERSION_MIN_IPHONEOS UINT32_C(0x25)
+#define LC_FUNCTION_STARTS UINT32_C(0x26)
+#define LC_DYLD_ENVIRONMENT UINT32_C(0x27)
+#define LC_MAIN (UINT32_C(0x28) | LC_REQ_DYLD)
+#define LC_DATA_IN_CODE UINT32_C(0x29)
+#define LC_SOURCE_VERSION UINT32_C(0x2a) /**< source_version_command */
+#define LC_DYLIB_CODE_SIGN_DRS UINT32_C(0x2b)
+#define LC_ENCRYPTION_INFO_64 UINT32_C(0x2c)
+#define LC_LINKER_OPTION UINT32_C(0x2d)
+#define LC_LINKER_OPTIMIZATION_HINT UINT32_C(0x2e)
+#define LC_VERSION_MIN_TVOS UINT32_C(0x2f)
+#define LC_VERSION_MIN_WATCHOS UINT32_C(0x30)
+#define LC_NOTE UINT32_C(0x31)
+#define LC_BUILD_VERSION UINT32_C(0x32)
+
+
+typedef struct lc_str
+{
+ uint32_t offset;
+} lc_str_t;
+
+typedef struct segment_command_32
+{
+ uint32_t cmd;
+ uint32_t cmdsize;
+ char segname[16];
+ uint32_t vmaddr;
+ uint32_t vmsize;
+ uint32_t fileoff;
+ uint32_t filesize;
+ uint32_t maxprot;
+ uint32_t initprot;
+ uint32_t nsects;
+ uint32_t flags;
+} segment_command_32_t;
+
+typedef struct segment_command_64
+{
+ uint32_t cmd;
+ uint32_t cmdsize;
+ char segname[16];
+ uint64_t vmaddr;
+ uint64_t vmsize;
+ uint64_t fileoff;
+ uint64_t filesize;
+ uint32_t maxprot;
+ uint32_t initprot;
+ uint32_t nsects;
+ uint32_t flags;
+} segment_command_64_t;
+
+/* segment flags */
+#define SG_HIGHVM UINT32_C(0x00000001)
+#define SG_FVMLIB UINT32_C(0x00000002)
+#define SG_NORELOC UINT32_C(0x00000004)
+#define SG_PROTECTED_VERSION_1 UINT32_C(0x00000008)
+#define SG_READ_ONLY UINT32_C(0x00000010) /**< Make it read-only after applying fixups. @since 10.14 */
+
+/* maxprot/initprot */
+#ifndef VM_PROT_NONE
+# define VM_PROT_NONE UINT32_C(0x00000000)
+# define VM_PROT_READ UINT32_C(0x00000001)
+# define VM_PROT_WRITE UINT32_C(0x00000002)
+# define VM_PROT_EXECUTE UINT32_C(0x00000004)
+# define VM_PROT_ALL UINT32_C(0x00000007)
+#endif
+
+typedef struct section_32
+{
+ char sectname[16];
+ char segname[16];
+ uint32_t addr;
+ uint32_t size;
+ uint32_t offset;
+ uint32_t align;
+ uint32_t reloff;
+ uint32_t nreloc;
+ uint32_t flags;
+ /** For S_LAZY_SYMBOL_POINTERS, S_NON_LAZY_SYMBOL_POINTERS and S_SYMBOL_STUBS
+ * this is the index into the indirect symbol table. */
+ uint32_t reserved1;
+ /** For S_SYMBOL_STUBS this is the entry size. */
+ uint32_t reserved2;
+} section_32_t;
+
+typedef struct section_64
+{
+ char sectname[16];
+ char segname[16];
+ uint64_t addr;
+ uint64_t size;
+ uint32_t offset;
+ uint32_t align;
+ uint32_t reloff;
+ uint32_t nreloc;
+ uint32_t flags;
+ /** For S_LAZY_SYMBOL_POINTERS, S_NON_LAZY_SYMBOL_POINTERS and S_SYMBOL_STUBS
+ * this is the index into the indirect symbol table. */
+ uint32_t reserved1;
+ uint32_t reserved2;
+ uint32_t reserved3;
+} section_64_t;
+
+/* section flags */
+#define SECTION_TYPE UINT32_C(0xff)
+#define S_REGULAR UINT32_C(0x00)
+#define S_ZEROFILL UINT32_C(0x01)
+#define S_CSTRING_LITERALS UINT32_C(0x02)
+#define S_4BYTE_LITERALS UINT32_C(0x03)
+#define S_8BYTE_LITERALS UINT32_C(0x04)
+#define S_LITERAL_POINTERS UINT32_C(0x05)
+#define S_NON_LAZY_SYMBOL_POINTERS UINT32_C(0x06)
+#define S_LAZY_SYMBOL_POINTERS UINT32_C(0x07)
+#define S_SYMBOL_STUBS UINT32_C(0x08)
+#define S_MOD_INIT_FUNC_POINTERS UINT32_C(0x09)
+#define S_MOD_TERM_FUNC_POINTERS UINT32_C(0x0a)
+#define S_COALESCED UINT32_C(0x0b)
+#define S_GB_ZEROFILL UINT32_C(0x0c)
+#define S_INTERPOSING UINT32_C(0x0d)
+#define S_16BYTE_LITERALS UINT32_C(0x0e)
+#define S_DTRACE_DOF UINT32_C(0x0f)
+#define S_LAZY_DYLIB_SYMBOL_POINTERS UINT32_C(0x10)
+#define S_THREAD_LOCAL_REGULAR UINT32_C(0x11)
+#define S_THREAD_LOCAL_ZEROFILL UINT32_C(0x12)
+#define S_THREAD_LOCAL_VARIABLES UINT32_C(0x13)
+#define S_THREAD_LOCAL_VARIABLE_POINTERS UINT32_C(0x14)
+#define S_THREAD_LOCAL_INIT_FUNCTION_POINTERS UINT32_C(0x15)
+
+
+
+
+#define SECTION_ATTRIBUTES UINT32_C(0xffffff00)
+#define SECTION_ATTRIBUTES_USR UINT32_C(0xff000000)
+#define S_ATTR_PURE_INSTRUCTIONS UINT32_C(0x80000000)
+#define S_ATTR_NO_TOC UINT32_C(0x40000000)
+#define S_ATTR_STRIP_STATIC_SYMS UINT32_C(0x20000000)
+#define S_ATTR_NO_DEAD_STRIP UINT32_C(0x10000000)
+#define S_ATTR_LIVE_SUPPORT UINT32_C(0x08000000)
+#define S_ATTR_SELF_MODIFYING_CODE UINT32_C(0x04000000)
+#define S_ATTR_DEBUG UINT32_C(0x02000000)
+#define SECTION_ATTRIBUTES_SYS UINT32_C(0x00ffff00)
+#define S_ATTR_SOME_INSTRUCTIONS UINT32_C(0x00000400)
+#define S_ATTR_EXT_RELOC UINT32_C(0x00000200)
+#define S_ATTR_LOC_RELOC UINT32_C(0x00000100)
+
+/* standard section names */
+#define SEG_PAGEZERO "__PAGEZERO"
+#define SEG_TEXT "__TEXT"
+#define SECT_TEXT "__text"
+#define SECT_FVMLIB_INIT0 "__fvmlib_init0"
+#define SECT_FVMLIB_INIT1 "__fvmlib_init1"
+#define SEG_DATA "__DATA"
+#define SECT_DATA "__data"
+#define SECT_BSS "__bss"
+#define SECT_COMMON "__common"
+#define SEG_OBJC "__OBJC"
+#define SECT_OBJC_SYMBOLS "__symbol_table"
+#define SECT_OBJC_MODULES "__module_info"
+#define SECT_OBJC_STRINGS "__selector_strs"
+#define SECT_OBJC_REFS "__selector_refs"
+#define SEG_ICON "__ICON"
+#define SECT_ICON_HEADER "__header"
+#define SECT_ICON_TIFF "__tiff"
+#define SEG_LINKEDIT "__LINKEDIT"
+#define SEG_UNIXSTACK "__UNIXSTACK"
+#define SEG_IMPORT "__IMPORT"
+
+typedef struct thread_command
+{
+ uint32_t cmd;
+ uint32_t cmdsize;
+} thread_command_t;
+
+typedef struct symtab_command
+{
+ uint32_t cmd;
+ uint32_t cmdsize;
+ uint32_t symoff;
+ uint32_t nsyms;
+ uint32_t stroff;
+ uint32_t strsize;
+} symtab_command_t;
+
+typedef struct dysymtab_command
+{
+ uint32_t cmd;
+ uint32_t cmdsize;
+ /** @name Symbol groupings.
+ * @{ */
+ uint32_t ilocalsym; /**< Index into the symbol table of the first local symbol. */
+ uint32_t nlocalsym; /**< Number of local symbols. */
+ uint32_t iextdefsym; /**< Index into the symbol table of the first externally defined symbol. */
+ uint32_t nextdefsym; /**< Number of externally defined symbols. */
+ uint32_t iundefsym; /**< Index into the symbol table of the first undefined symbol. */
+ uint32_t nundefsym; /**< Number of undefined symbols. */
+ /** @} */
+ uint32_t tocoff; /**< Table of content file offset. (usually empty) */
+ uint32_t ntoc; /**< Number of entries in TOC. */
+ uint32_t modtaboff; /** The module table file offset. (usually empty) */
+ uint32_t nmodtab; /**< Number of entries in the module table. */
+ /** @name Dynamic symbol tables.
+ * @{ */
+ uint32_t extrefsymoff; /**< Externally referenceable symbol table file offset. @sa dylib_reference_t */
+ uint32_t nextrefsym; /**< Number externally referenceable symbols. */
+ uint32_t indirectsymboff; /**< Indirect symbol table (32-bit symtab indexes) for thunks and offset tables. */
+ uint32_t nindirectsymb; /**< Number of indirect symbol table entries. */
+ /** @} */
+ /** @name Relocations.
+ * @{ */
+ uint32_t extreloff; /**< External relocations (r_address is relative to first segment (i.e. RVA)). */
+ uint32_t nextrel; /**< Number of external relocations. */
+ uint32_t locreloff; /**< Local relocations (r_address is relative to first segment (i.e. RVA)). */
+ uint32_t nlocrel; /**< Number of local relocations. */
+ /** @} */
+} dysymtab_command_t;
+AssertCompileSize(dysymtab_command_t, 80);
+
+/** Special indirect symbol table entry value, stripped local symbol. */
+#define INDIRECT_SYMBOL_LOCAL UINT32_C(0x80000000)
+/** Special indirect symbol table entry value, stripped absolute symbol. */
+#define INDIRECT_SYMBOL_ABS UINT32_C(0x40000000)
+
+typedef struct dylib_reference
+{
+ uint32_t isym : 24; /**< Symbol table index. */
+ uint32_t flags : 8; /**< REFERENCE_FLAG_XXX? */
+} dylib_reference_t;
+AssertCompileSize(dylib_reference_t, 4);
+
+
+typedef struct dylib_table_of_contents
+{
+ uint32_t symbol_index; /**< External symbol table entry. */
+ uint32_t module_index; /**< The module table index of the module defining it. */
+} dylib_table_of_contents_t;
+AssertCompileSize(dylib_table_of_contents_t, 8);
+
+
+/** 32-bit module table entry. */
+typedef struct dylib_module
+{
+ uint32_t module_name;
+ uint32_t iextdefsym;
+ uint32_t nextdefsym;
+ uint32_t irefsym;
+ uint32_t nrefsym;
+ uint32_t ilocalsym;
+ uint32_t nlocalsym;
+ uint32_t iextrel;
+ uint32_t nextrel;
+ uint32_t iinit_iterm;
+ uint32_t ninit_nterm;
+ uint32_t objc_module_info_addr;
+ uint32_t objc_module_info_size;
+} dylib_module_32_t;
+AssertCompileSize(dylib_module_32_t, 13*4);
+
+/* a 64-bit module table entry */
+typedef struct dylib_module_64
+{
+ uint32_t module_name;
+ uint32_t iextdefsym;
+ uint32_t nextdefsym;
+ uint32_t irefsym;
+ uint32_t nrefsym;
+ uint32_t ilocalsym;
+ uint32_t nlocalsym;
+ uint32_t iextrel;
+ uint32_t nextrel;
+ uint32_t iinit_iterm;
+ uint32_t ninit_nterm;
+ uint32_t objc_module_info_size;
+ uint64_t objc_module_info_addr;
+} dylib_module_64_t;
+AssertCompileSize(dylib_module_64_t, 12*4+8);
+
+typedef struct uuid_command
+{
+ uint32_t cmd;
+ uint32_t cmdsize;
+ uint8_t uuid[16];
+} uuid_command_t;
+AssertCompileSize(uuid_command_t, 24);
+
+typedef struct linkedit_data_command
+{
+ uint32_t cmd; /**< LC_CODE_SIGNATURE, LC_SEGMENT_SPLIT_INFO, LC_FUNCTION_STARTS */
+ uint32_t cmdsize; /**< Size of this structure (16). */
+ uint32_t dataoff; /**< Offset into the file of the data. */
+ uint32_t datasize; /**< The size of the data. */
+} linkedit_data_command_t;
+AssertCompileSize(linkedit_data_command_t, 16);
+
+typedef struct version_min_command
+{
+ uint32_t cmd; /**< LC_VERSION_MIN_MACOSX, LC_VERSION_MIN_IPHONEOS, LC_VERSION_MIN_TVOS, LC_VERSION_MIN_WATCHOS */
+ uint32_t cmdsize; /**< Size of this structure (16). */
+ uint32_t version; /**< 31..16=major, 15..8=minor, 7..0=patch. */
+ uint32_t reserved; /**< MBZ. */
+} version_min_command_t;
+AssertCompileSize(version_min_command_t, 16);
+
+typedef struct build_tool_version
+{
+ uint32_t tool; /**< TOOL_XXX */
+ uint32_t version; /**< 31..16=major, 15..8=minor, 7..0=patch. */
+} build_tool_version_t;
+AssertCompileSize(build_tool_version_t, 8);
+
+/** @name TOOL_XXX - Values for build_tool_version::tool
+ * @{ */
+#define TOOL_CLANG 1
+#define TOOL_SWIFT 2
+#define TOOL_LD 3
+/** @} */
+
+typedef struct build_version_command
+{
+ uint32_t cmd; /**< LC_BUILD_VERSION */
+ uint32_t cmdsize; /**< Size of this structure (at least 24). */
+ uint32_t platform; /**< PLATFORM_XXX */
+ uint32_t minos; /**< Minimum OS version: 31..16=major, 15..8=minor, 7..0=patch */
+ uint32_t sdk; /**< SDK version: 31..16=major, 15..8=minor, 7..0=patch */
+ uint32_t ntools; /**< Number of build_tool_version entries following in aTools. */
+ RT_FLEXIBLE_ARRAY_EXTENSION
+ build_tool_version_t aTools[RT_FLEXIBLE_ARRAY];
+} build_version_command_t;
+AssertCompileMemberOffset(build_version_command_t, aTools, 24);
+
+/** @name PLATFORM_XXX - Values for build_version_command::platform
+ * @{ */
+#define PLATFORM_MACOS 1
+#define PLATFORM_IOS 2
+#define PLATFORM_TVOS 3
+#define PLATFORM_WATCHOS 4
+/** @} */
+
+typedef struct source_version_command
+{
+ uint32_t cmd; /**< LC_SOURCE_VERSION */
+ uint32_t cmdsize; /**< Size of this structure (16). */
+ uint64_t version; /**< A.B.C.D.E, where A is 24 bits wide and the rest 10 bits each. */
+} source_version_command_t;
+AssertCompileSize(source_version_command_t, 16);
+
+
+typedef struct macho_nlist_32
+{
+ union
+ {
+ int32_t n_strx;
+ } n_un;
+ uint8_t n_type;
+ uint8_t n_sect;
+ int16_t n_desc;
+ uint32_t n_value;
+} macho_nlist_32_t;
+
+
+typedef struct macho_nlist_64
+{
+ union
+ {
+ uint32_t n_strx;
+ } n_un;
+ uint8_t n_type;
+ uint8_t n_sect;
+ int16_t n_desc;
+ uint64_t n_value;
+} macho_nlist_64_t;
+
+#define MACHO_N_EXT UINT8_C(0x01)
+#define MACHO_N_PEXT UINT8_C(0x10)
+
+#define MACHO_N_TYPE UINT8_C(0x0e)
+#define MACHO_N_UNDF UINT8_C(0x00)
+#define MACHO_N_ABS UINT8_C(0x02)
+#define MACHO_N_INDR UINT8_C(0x0a)
+#define MACHO_N_PBUD UINT8_C(0x0c)
+#define MACHO_N_SECT UINT8_C(0x0e)
+
+#define MACHO_N_STAB UINT8_C(0xe0)
+#define MACHO_N_GSYM UINT8_C(0x20)
+#define MACHO_N_FNAME UINT8_C(0x22)
+#define MACHO_N_FUN UINT8_C(0x24)
+#define MACHO_N_STSYM UINT8_C(0x26)
+#define MACHO_N_LCSYM UINT8_C(0x28)
+#define MACHO_N_BNSYM UINT8_C(0x2e)
+#define MACHO_N_PC UINT8_C(0x30)
+#define MACHO_N_OPT UINT8_C(0x3c)
+#define MACHO_N_RSYM UINT8_C(0x40)
+#define MACHO_N_SLINE UINT8_C(0x44)
+#define MACHO_N_ENSYM UINT8_C(0x4e)
+#define MACHO_N_SSYM UINT8_C(0x60)
+#define MACHO_N_SO UINT8_C(0x64)
+#define MACHO_N_OSO UINT8_C(0x66)
+#define MACHO_N_LSYM UINT8_C(0x80)
+#define MACHO_N_BINCL UINT8_C(0x82)
+#define MACHO_N_SOL UINT8_C(0x84)
+#define MACHO_N_PARAMS UINT8_C(0x86)
+#define MACHO_N_VERSION UINT8_C(0x88)
+#define MACHO_N_OLEVEL UINT8_C(0x8A)
+#define MACHO_N_PSYM UINT8_C(0xa0)
+#define MACHO_N_EINCL UINT8_C(0xa2)
+#define MACHO_N_ENTRY UINT8_C(0xa4)
+#define MACHO_N_LBRAC UINT8_C(0xc0)
+#define MACHO_N_EXCL UINT8_C(0xc2)
+#define MACHO_N_RBRAC UINT8_C(0xe0)
+#define MACHO_N_BCOMM UINT8_C(0xe2)
+#define MACHO_N_ECOMM UINT8_C(0xe4)
+#define MACHO_N_ECOML UINT8_C(0xe8)
+#define MACHO_N_LENG UINT8_C(0xfe)
+
+#define MACHO_NO_SECT UINT8_C(0x00)
+#define MACHO_MAX_SECT UINT8_C(0xff)
+
+#define REFERENCE_TYPE UINT16_C(0x000f)
+#define REFERENCE_FLAG_UNDEFINED_NON_LAZY 0
+#define REFERENCE_FLAG_UNDEFINED_LAZY 1
+#define REFERENCE_FLAG_DEFINED 2
+#define REFERENCE_FLAG_PRIVATE_DEFINED 3
+#define REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY 4
+#define REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY 5
+#define REFERENCED_DYNAMICALLY UINT16_C(0x0010)
+
+#define GET_LIBRARY_ORDINAL(a_n_desc) \
+ RT_BYTE2(a_n_desc)
+#define SET_LIBRARY_ORDINAL(a_n_desc, a_ordinal) \
+ do { (a_n_desc) = RT_MAKE_U16(RT_BYTE1(a_n_desc), a_ordinal); } while (0)
+
+#define SELF_LIBRARY_ORDINAL 0x00
+#define MAX_LIBRARY_ORDINAL 0xfd
+#define DYNAMIC_LOOKUP_ORDINAL 0xfe
+#define EXECUTABLE_ORDINAL 0xff
+
+#define N_NO_DEAD_STRIP UINT16_C(0x0020)
+#define N_DESC_DISCARDED UINT16_C(0x0020)
+#define N_WEAK_REF UINT16_C(0x0040)
+#define N_WEAK_DEF UINT16_C(0x0080)
+#define N_REF_TO_WEAK UINT16_C(0x0080)
+#define N_SYMBOL_RESOLVER UINT16_C(0x0100)
+#define N_ALT_ENTRY UINT16_C(0x0200)
+
+typedef struct macho_relocation_info
+{
+ int32_t r_address;
+ uint32_t r_symbolnum : 24;
+ uint32_t r_pcrel : 1;
+ uint32_t r_length : 2;
+ uint32_t r_extern : 1;
+ uint32_t r_type : 4;
+} macho_relocation_info_t;
+AssertCompileSize(macho_relocation_info_t, 8);
+
+#define R_ABS 0
+#define R_SCATTERED UINT32_C(0x80000000)
+
+typedef struct scattered_relocation_info
+{
+#ifdef RT_LITTLE_ENDIAN
+ uint32_t r_address : 24;
+ uint32_t r_type : 4;
+ uint32_t r_length : 2;
+ uint32_t r_pcrel : 1;
+ uint32_t r_scattered : 1;
+#elif defined(RT_BIG_ENDIAN)
+ uint32_t r_scattered : 1;
+ uint32_t r_pcrel : 1;
+ uint32_t r_length : 2;
+ uint32_t r_type : 4;
+ uint32_t r_address : 24;
+#else
+# error "Neither K_ENDIAN isn't LITTLE or BIG!"
+#endif
+ int32_t r_value;
+} scattered_relocation_info_t;
+AssertCompileSize(scattered_relocation_info_t, 8);
+
+typedef union
+{
+ macho_relocation_info_t r;
+ scattered_relocation_info_t s;
+} macho_relocation_union_t;
+AssertCompileSize(macho_relocation_union_t, 8);
+
+typedef enum reloc_type_generic
+{
+ GENERIC_RELOC_VANILLA = 0,
+ GENERIC_RELOC_PAIR,
+ GENERIC_RELOC_SECTDIFF,
+ GENERIC_RELOC_PB_LA_PTR,
+ GENERIC_RELOC_LOCAL_SECTDIFF
+} reloc_type_generic_t;
+
+typedef enum reloc_type_x86_64
+{
+ X86_64_RELOC_UNSIGNED = 0,
+ X86_64_RELOC_SIGNED,
+ X86_64_RELOC_BRANCH,
+ X86_64_RELOC_GOT_LOAD,
+ X86_64_RELOC_GOT,
+ X86_64_RELOC_SUBTRACTOR,
+ X86_64_RELOC_SIGNED_1,
+ X86_64_RELOC_SIGNED_2,
+ X86_64_RELOC_SIGNED_4
+} reloc_type_x86_64_t;
+
+#endif /* !IPRT_INCLUDED_formats_mach_o_h */
+
diff --git a/include/iprt/formats/mz.h b/include/iprt/formats/mz.h
new file mode 100644
index 00000000..4759ad40
--- /dev/null
+++ b/include/iprt/formats/mz.h
@@ -0,0 +1,77 @@
+/* $Id: mz.h $ */
+/** @file
+ * IPRT, MZ Executable Header.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_formats_mz_h
+#define IPRT_INCLUDED_formats_mz_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+#include <iprt/assertcompile.h>
+
+typedef struct _IMAGE_DOS_HEADER
+{
+ uint16_t e_magic;
+ uint16_t e_cblp;
+ uint16_t e_cp;
+ uint16_t e_crlc;
+ uint16_t e_cparhdr;
+ uint16_t e_minalloc;
+ uint16_t e_maxalloc;
+ uint16_t e_ss;
+ uint16_t e_sp;
+ uint16_t e_csum;
+ uint16_t e_ip;
+ uint16_t e_cs;
+ uint16_t e_lfarlc;
+ uint16_t e_ovno;
+ uint16_t e_res[4];
+ uint16_t e_oemid;
+ uint16_t e_oeminfo;
+ uint16_t e_res2[10];
+ uint32_t e_lfanew;
+} IMAGE_DOS_HEADER;
+AssertCompileSize(IMAGE_DOS_HEADER, 0x40);
+typedef IMAGE_DOS_HEADER *PIMAGE_DOS_HEADER;
+
+#ifndef IMAGE_DOS_SIGNATURE
+# define IMAGE_DOS_SIGNATURE ('M' | ('Z' << 8)) /* fix endianness */
+#endif
+
+
+#endif /* !IPRT_INCLUDED_formats_mz_h */
+
diff --git a/include/iprt/formats/mz.mac b/include/iprt/formats/mz.mac
new file mode 100644
index 00000000..97e30cc6
--- /dev/null
+++ b/include/iprt/formats/mz.mac
@@ -0,0 +1,66 @@
+;; @file
+; IPRT - MZ (DOS Executable Header) definitions for YASM/NASM.
+;
+
+;
+; Copyright (C) 2006-2022 Oracle and/or its affiliates.
+;
+; This file is part of VirtualBox base platform packages, as
+; available from https://www.virtualbox.org.
+;
+; This program is free software; you can redistribute it and/or
+; modify it under the terms of the GNU General Public License
+; as published by the Free Software Foundation, in version 3 of the
+; License.
+;
+; This program is distributed in the hope that it will be useful, but
+; WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with this program; if not, see <https://www.gnu.org/licenses>.
+;
+; The contents of this file may alternatively be used under the terms
+; of the Common Development and Distribution License Version 1.0
+; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+; in the VirtualBox 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.
+;
+; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+;
+
+%ifndef ___iprt_formats_mz_mac
+%define ___iprt_formats_mz_mac
+
+struc IMAGE_DOS_HEADER
+ .e_magic resw 1
+ .e_cblp resw 1
+ .e_cp resw 1
+ .e_crlc resw 1
+ .e_cparhdr resw 1
+ .e_minalloc resw 1
+ .e_maxalloc resw 1
+ .e_ss resw 1
+ .e_sp resw 1
+ .e_csum resw 1
+ .e_ip resw 1
+ .e_cs resw 1
+ .e_lfarlc resw 1
+ .e_ovno resw 1
+ .e_res resw 4
+ .e_oemid resw 1
+ .e_oeminfo resw 1
+ .e_res2 resw 10
+ .e_lfanew resd 1
+endstruc
+
+%ifndef IMAGE_DOS_SIGNATURE
+ %define IMAGE_DOS_SIGNATURE 0x5a4d
+%endif
+
+%endif
+
diff --git a/include/iprt/formats/ntfs.h b/include/iprt/formats/ntfs.h
new file mode 100644
index 00000000..36c0b112
--- /dev/null
+++ b/include/iprt/formats/ntfs.h
@@ -0,0 +1,782 @@
+/* $Id: ntfs.h $ */
+/** @file
+ * IPRT, NT File System (NTFS).
+ */
+
+/*
+ * Copyright (C) 2017-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_formats_ntfs_h
+#define IPRT_INCLUDED_formats_ntfs_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/formats/fat.h>
+
+
+/** @defgroup grp_rt_formats_ntfs NT File System (NTFS) structures and definitions
+ * @ingroup grp_rt_formats
+ * @{
+ */
+
+/** Value of the FATBOOTSECTOR::achOemName for an NTFS file system. */
+#define NTFS_OEM_ID_MAGIC "NTFS "
+
+
+/** @name NTFS_MFT_IDX_XXX - Predefined MFT indexes.
+ * @{ */
+#define NTFS_MFT_IDX_MFT 0 /**< The MFT itself. */
+#define NTFS_MFT_IDX_MFT_MIRROR 1 /**< Mirror MFT (partial?). */
+#define NTFS_MFT_IDX_LOG_FILE 2 /**< Journalling log. */
+#define NTFS_MFT_IDX_VOLUME 3 /**< Volume attributes. */
+#define NTFS_MFT_IDX_ATTRIB_DEF 4 /**< Attribute definitions. */
+#define NTFS_MFT_IDX_ROOT 5 /**< The root directory. */
+#define NTFS_MFT_IDX_BITMAP 6 /**< Allocation bitmap. */
+#define NTFS_MFT_IDX_BOOT 7 /**< The boot sector. */
+#define NTFS_MFT_IDX_BAD_CLUSTER 8 /**< Bad cluster table. */
+#define NTFS_MFT_IDX_SECURITY 9 /**< Shared security descriptors (w2k and later). */
+#define NTFS_MFT_IDX_UP_CASE 10 /**< Unicode upper case table. */
+#define NTFS_MFT_IDX_EXTEND 11 /**< Directory containing further system files. */
+#define NTFS_MFT_IDX_FIRST_USER 16 /**< The first user file. */
+/** @} */
+
+/**
+ * NTFS MFT record reference.
+ */
+typedef union NTFSMFTREF
+{
+ /** unsigned 64-bit view. */
+ uint64_t u64;
+ /** unsigned 32-bit view. */
+ uint32_t au32[2];
+ /** unsigned 16-bit view. */
+ uint16_t au16[4];
+
+ /** Structured view. */
+ struct
+ {
+ /** Index of the master file table record. */
+ RT_GCC_EXTENSION uint64_t idxMft : 48;
+ /** MFT record reuse sequence number (for catching dangling references). */
+ RT_GCC_EXTENSION uint64_t uRecReuseSeqNo : 16;
+ } s;
+} NTFSMFTREF;
+AssertCompileSize(NTFSMFTREF, 8);
+/** Pointer to a NTFS MFT record reference. */
+typedef NTFSMFTREF *PNTFSMFTREF;
+/** Pointer to a const NTFS MFT record reference. */
+typedef NTFSMFTREF const *PCNTFSMFTREF;
+
+/** @name NTFSMFTREF_GET_IDX
+ * Gets the MFT index number (host endian) from a MFT reference. */
+/** @name NTFSMFTREF_GET_SEQ
+ * Gets the MFT reuse sequence number (host endian) from a MFT reference. */
+/** @name NTFSMFTREF_SET_IDX
+ * Sets the MFT index number of a MFT reference. */
+/** @name NTFSMFTREF_SET_SEQ
+ * Sets the MFT reuse sequence number of a MFT reference. */
+/** @name NTFSMFTREF_SET
+ * Sets the values of a MFT reference. */
+#ifdef RT_LITTLE_ENDIAN
+# define NTFSMFTREF_GET_IDX(a_pMftRef) ((a_pMftRef)->s.idxMft)
+# define NTFSMFTREF_GET_SEQ(a_pMftRef) ((a_pMftRef)->s.uRecReuseSeqNo)
+# define NTFSMFTREF_SET_SEQ(a_pMftRef, a_uValue) do { (a_pMftRef)->s.uRecReuseSeqNo = (a_uValue); } while (0)
+# define NTFSMFTREF_SET_IDX(a_pMftRef, a_uValue) do { (a_pMftRef)->s.idxMft = (a_uValue); } while (0)
+# define NTFSMFTREF_SET(a_pMftRef, a_idx, a_uSeq) \
+ do { \
+ (a_pMftRef)->s.idxMft = (a_idx); \
+ (a_pMftRef)->s.uRecReuseSeqNo = (a_uSeq); \
+ } while (0)
+#else
+# define NTFSMFTREF_GET_IDX(a_pMftRef) (RT_LE2H_U64((a_pMftRef)->u64) & UINT64_C(0x0000ffffffffffff))
+# define NTFSMFTREF_GET_SEQ(a_pMftRef) RT_LE2H_U16((uint16_t)(a_pMftRef)->u64)
+# define NTFSMFTREF_SET_SEQ(a_pMftRef, a_uValue) do { (a_pMftRef)->au16[3] = RT_H2LE_U16(a_uValue); } while (0)
+# define NTFSMFTREF_SET_IDX(a_pMftRef, a_uValue) \
+ do { \
+ (a_pMftRef)->au32[0] = RT_H2LE_U32((uint32_t)(a_uValue)); \
+ (a_pMftRef)->au16[2] = RT_H2LE_U16((uint16_t)((a_uValue) >> 32)); \
+ } while (0)
+# define NTFSMFTREF_SET(a_pMftRef, a_idx, a_uSeq) \
+ do { \
+ (a_pMftRef)->au32[0] = RT_H2LE_U32((uint32_t)(a_idx)); \
+ (a_pMftRef)->au16[2] = RT_H2LE_U16((uint16_t)((a_idx) >> 32)); \
+ (a_pMftRef)->au16[3] = RT_H2LE_U16((uint16_t)(a_uSeq)); \
+ } while (0)
+#endif
+/** Check that the reference is zero. */
+#define NTFSMFTREF_IS_ZERO(a_pMftRef) ((a_pMftRef)->u64 == 0)
+
+
+/**
+ * NTFS record header.
+ */
+typedef struct NTFSRECHDR
+{
+ /** Magic number (usually ASCII). */
+ uint32_t uMagic;
+ /** Offset of the update sequence array from the start of the record. */
+ uint16_t offUpdateSeqArray;
+ /** Number of entries in the update sequence array. (uint16_t sized entries) */
+ uint16_t cUpdateSeqEntries;
+} NTFSRECHDR;
+AssertCompileSize(NTFSRECHDR, 8);
+/** Pointer to a NTFS record header. */
+typedef NTFSRECHDR *PNTFSRECHDR;
+/** Pointer to a const NTFS record header. */
+typedef NTFSRECHDR const *PCNTFSRECHDR;
+
+/** The multi-sector update sequence stride.
+ * @see https://msdn.microsoft.com/en-us/library/bb470212%28v=vs.85%29.aspx
+ * @see NTFSRECHDR::offUpdateSeqArray, NTFSRECHDR::cUpdateSeqEntries
+ */
+#define NTFS_MULTI_SECTOR_STRIDE 512
+
+
+/**
+ * NTFS file record (in the MFT).
+ */
+typedef struct NTFSRECFILE
+{
+ /** 0x00: Header with NTFSREC_MAGIC_FILE. */
+ NTFSRECHDR Hdr;
+ /** 0x08: Log file sequence number. */
+ uint64_t uLsn;
+ /** 0x10: MFT record reuse sequence number (for dangling MFT references). */
+ uint16_t uRecReuseSeqNo;
+ /** 0x12: Number of hard links. */
+ uint16_t cLinks;
+ /** 0x14: Offset of the first attribute (relative to start of record). */
+ uint16_t offFirstAttrib;
+ /** 0x16: Record flags (NTFSRECFILE_F_XXX). */
+ uint16_t fFlags;
+ /** 0x18: Number of byte in use in this MFT record. */
+ uint32_t cbRecUsed;
+ /** 0x1c: The MFT record size. */
+ uint32_t cbRecSize;
+ /** 0x20: Reference to the base MFT record. */
+ NTFSMFTREF BaseMftRec;
+ /** 0x28: Next attribute instance number. */
+ uint16_t idNextAttrib;
+ /** 0x2a: Padding if NTFS 3.1+, update sequence array if older. */
+ uint16_t uPaddingOrUsa;
+ /** 0x2c: MFT index of this record. */
+ uint32_t idxMftSelf;
+} NTFSRECFILE;
+AssertCompileSize(NTFSRECFILE, 0x30);
+/** Pointer to a NTFS file record. */
+typedef NTFSRECFILE *PNTFSRECFILE;
+/** Pointer to a const NTFS file record. */
+typedef NTFSRECFILE const *PCNTFSRECFILE;
+
+
+/** NTFS 'FILE' record magic value. */
+#define NTFSREC_MAGIC_FILE RT_H2LE_U32_C(UINT32_C(0x454c4946))
+
+/** @name NTFSRECFILE_F_XXX - NTFSRECFILE::fFlags.
+ * @{ */
+/** MFT record is in use. */
+#define NTFSRECFILE_F_IN_USE RT_H2LE_U16_C(UINT16_C(0x0001))
+/** Directory record. */
+#define NTFSRECFILE_F_DIRECTORY RT_H2LE_U16_C(UINT16_C(0x0002))
+/** @} */
+
+
+/** @name NTFS_AT_XXX - Attribute types
+ * @{ */
+#define NTFS_AT_UNUSED RT_H2LE_U32_C(UINT32_C(0x00000000))
+/** NTFSATSTDINFO */
+#define NTFS_AT_STANDARD_INFORMATION RT_H2LE_U32_C(UINT32_C(0x00000010))
+/** NTFSATLISTENTRY */
+#define NTFS_AT_ATTRIBUTE_LIST RT_H2LE_U32_C(UINT32_C(0x00000020))
+/** NTFSATFILENAME */
+#define NTFS_AT_FILENAME RT_H2LE_U32_C(UINT32_C(0x00000030))
+#define NTFS_AT_OBJECT_ID RT_H2LE_U32_C(UINT32_C(0x00000040))
+#define NTFS_AT_SECURITY_DESCRIPTOR RT_H2LE_U32_C(UINT32_C(0x00000050))
+#define NTFS_AT_VOLUME_NAME RT_H2LE_U32_C(UINT32_C(0x00000060))
+/** NTFSATVOLUMEINFO */
+#define NTFS_AT_VOLUME_INFORMATION RT_H2LE_U32_C(UINT32_C(0x00000070))
+#define NTFS_AT_DATA RT_H2LE_U32_C(UINT32_C(0x00000080))
+/** NTFSATINDEXROOT */
+#define NTFS_AT_INDEX_ROOT RT_H2LE_U32_C(UINT32_C(0x00000090))
+#define NTFS_AT_INDEX_ALLOCATION RT_H2LE_U32_C(UINT32_C(0x000000a0))
+#define NTFS_AT_BITMAP RT_H2LE_U32_C(UINT32_C(0x000000b0))
+#define NTFS_AT_REPARSE_POINT RT_H2LE_U32_C(UINT32_C(0x000000c0))
+#define NTFS_AT_EA_INFORMATION RT_H2LE_U32_C(UINT32_C(0x000000d0))
+#define NTFS_AT_EA RT_H2LE_U32_C(UINT32_C(0x000000e0))
+#define NTFS_AT_PROPERTY_SET RT_H2LE_U32_C(UINT32_C(0x000000f0))
+#define NTFS_AT_LOGGED_UTILITY_STREAM RT_H2LE_U32_C(UINT32_C(0x00000100))
+#define NTFS_AT_FIRST_USER_DEFINED RT_H2LE_U32_C(UINT32_C(0x00001000))
+#define NTFS_AT_END RT_H2LE_U32_C(UINT32_C(0xffffffff))
+/** @} */
+
+/** @name NTFS_AF_XXX - Attribute flags.
+ * @{ */
+#define NTFS_AF_COMPR_FMT_NONE RT_H2LE_U16_C(UINT16_C(0x0000))
+/** See RtlCompressBuffer / COMPRESSION_FORMAT_LZNT1. */
+#define NTFS_AF_COMPR_FMT_LZNT1 RT_H2LE_U16_C(UINT16_C(0x0001))
+/** See RtlCompressBuffer / COMPRESSION_FORMAT_XPRESS_HUFF. */
+#define NTFS_AF_COMPR_FMT_XPRESS RT_H2LE_U16_C(UINT16_C(0x0002))
+/** See RtlCompressBuffer / COMPRESSION_FORMAT_XPRESS_HUFF. */
+#define NTFS_AF_COMPR_FMT_XPRESS_HUFF RT_H2LE_U16_C(UINT16_C(0x0003))
+#define NTFS_AF_COMPR_FMT_MASK RT_H2LE_U16_C(UINT16_C(0x00ff))
+#define NTFS_AF_ENCRYPTED RT_H2LE_U16_C(UINT16_C(0x4000))
+#define NTFS_AF_SPARSE RT_H2LE_U16_C(UINT16_C(0x8000))
+/** @} */
+
+/**
+ * NTFS attribute header.
+ *
+ * This has three forms:
+ * - Resident
+ * - Non-resident, no compression
+ * - Non-resident, compressed.
+ *
+ * Each form translates to a different header size.
+ */
+typedef struct NTFSATTRIBHDR
+{
+ /** 0x00: Attribute type (NTFS_AT_XXX). */
+ uint32_t uAttrType;
+ /** 0x04: Length of this attribute (resident part). */
+ uint32_t cbAttrib;
+ /** 0x08: Set (1) if non-resident attribute, 0 if resident. */
+ uint8_t fNonResident;
+ /** 0x09: Attribute name length (can be zero). */
+ uint8_t cwcName;
+ /** 0x0a: Offset of the name string (relative to the start of this header). */
+ uint16_t offName;
+ /** 0x0c: NTFS_AF_XXX. */
+ uint16_t fFlags;
+ /** 0x0e: Attribute instance number. Unique within the MFT record. */
+ uint16_t idAttrib;
+ /** 0x10: Data depending on the fNonResident member value. */
+ union
+ {
+ /** Resident attributes. */
+ struct
+ {
+ /** 0x10: Attribute value length. */
+ uint32_t cbValue;
+ /** 0x14: Offset of the value (relative to the start of this header). */
+ uint16_t offValue;
+ /** 0x16: NTFS_RES_AF_XXX. */
+ uint8_t fFlags;
+ /** 0x17: Reserved. */
+ uint8_t bReserved;
+ } Res;
+
+ /** Non-resident attributes. */
+ struct
+ {
+ /** 0x10: The first virtual cluster containing data.
+ *
+ * This is mainly for internal checking when the run list doesn't fit in one
+ * MFT record. It can also be used to avoid recording a sparse run at the
+ * beginning of the data covered by this attribute record. */
+ int64_t iVcnFirst;
+ /** 0x18: The last virtual cluster containing data (inclusive). */
+ int64_t iVcnLast;
+ /** 0x20: Offset of the mapping pair program. This program gives us a mapping
+ * between VNC and LCN for the attribute value. */
+ uint16_t offMappingPairs;
+ /** 0x22: Power of two compression unit size in clusters (cbCluster << uCompessionUnit).
+ * Zero means uncompressed. */
+ uint8_t uCompressionUnit;
+ /** 0x23: Reserved */
+ uint8_t abReserved[5];
+ /** 0x28: Allocated size (rouneded to cluster).
+ * @note Only set in the first attribute record (iVcnFirst == 0). */
+ int64_t cbAllocated;
+ /** 0x30: The exact length of the data.
+ * @note Only set in the first attribute record (iVcnFirst == 0). */
+ int64_t cbData;
+ /** 0x38: The length of the initialized data. (Not necessarily
+ * rounded up to cluster size.)
+ * @note Only set in the first attribute record (iVcnFirst == 0). */
+ int64_t cbInitialized;
+ /** 0x40: Compressed size if compressed, otherwise absent. */
+ int64_t cbCompressed;
+ } NonRes;
+ } u;
+} NTFSATTRIBHDR;
+AssertCompileSize(NTFSATTRIBHDR, 0x48);
+AssertCompileMemberOffset(NTFSATTRIBHDR, u.Res, 0x10);
+AssertCompileMemberOffset(NTFSATTRIBHDR, u.Res.bReserved, 0x17);
+AssertCompileMemberOffset(NTFSATTRIBHDR, u.NonRes, 0x10);
+AssertCompileMemberOffset(NTFSATTRIBHDR, u.NonRes.cbCompressed, 0x40);
+/** Pointer to a NTFS attribute header. */
+typedef NTFSATTRIBHDR *PNTFSATTRIBHDR;
+/** Pointer to a const NTFS attribute header. */
+typedef NTFSATTRIBHDR const *PCNTFSATTRIBHDR;
+
+/** @name NTFSATTRIBHDR_SIZE_XXX - Attribute header sizes.
+ * @{ */
+/** Attribute header size for resident values. */
+#define NTFSATTRIBHDR_SIZE_RESIDENT (0x18)
+/** Attribute header size for uncompressed non-resident values. */
+#define NTFSATTRIBHDR_SIZE_NONRES_UNCOMPRESSED (0x40)
+/** Attribute header size for compressed non-resident values. */
+#define NTFSATTRIBHDR_SIZE_NONRES_COMPRESSED (0x48)
+/** @} */
+
+/** Get the pointer to the embedded name from an attribute.
+ * @note ASSUMES the caller check that there is a name. */
+#define NTFSATTRIBHDR_GET_NAME(a_pAttrHdr) ( (PRTUTF16)((uintptr_t)(a_pAttrHdr) + (a_pAttrHdr)->offName) )
+
+/** Get the pointer to resident value.
+ * @note ASSUMES the caller checks that it's resident and valid. */
+#define NTFSATTRIBHDR_GET_RES_VALUE_PTR(a_pAttrHdr) ( (uint8_t *)(a_pAttrHdr) + (a_pAttrHdr)->u.Res.offValue )
+
+
+/** @name NTFS_RES_AF_XXX
+ * @{ */
+/** Attribute is referenced in an index. */
+#define NTFS_RES_AF_INDEXED UINT8_C(0x01)
+/** @} */
+
+/**
+ * Attribute list entry (NTFS_AT_ATTRIBUTE_LIST).
+ *
+ * This is used to deal with a file having attributes in more than one MFT
+ * record. A prominent example is an fragment file (unnamed data attribute)
+ * which mapping pairs doesn't fit in a single MFT record.
+ *
+ * This attribute can be non-resident, however it's mapping pair program must
+ * fit in the base MFT record.
+ */
+typedef struct NTFSATLISTENTRY
+{
+ /** 0x00: Attribute type (NTFS_AT_XXX). */
+ uint32_t uAttrType;
+ /** 0x04: Length of this entry. */
+ uint16_t cbEntry;
+ /** 0x06: Attribute name length (zero if none). */
+ uint8_t cwcName;
+ /** 0x07: Name offset. */
+ uint8_t offName;
+ /** 0x08: The first VNC for this part of the attribute value. */
+ int64_t iVcnFirst;
+ /** 0x10: The MFT record holding the actual attribute. */
+ NTFSMFTREF InMftRec;
+ /** 0x18: Attribute instance number. Unique within the MFT record. */
+ uint16_t idAttrib;
+ /** 0x1a: Maybe where the attribute name starts. */
+ RT_FLEXIBLE_ARRAY_EXTENSION
+ RTUTF16 wszName[RT_FLEXIBLE_ARRAY];
+} NTFSATLISTENTRY;
+AssertCompileMemberOffset(NTFSATLISTENTRY, idAttrib, 0x18);
+/** Pointer to a NTFS attribute list entry. */
+typedef NTFSATLISTENTRY *PNTFSATLISTENTRY;
+/** Pointer to a const NTFS attribute list entry. */
+typedef NTFSATLISTENTRY const *PCNTFSATLISTENTRY;
+
+/** Unaligned minimum entry size (no name). */
+#define NTFSATLISTENTRY_SIZE_MINIMAL 0x1a
+
+
+
+/**
+ * NTFS standard file info attribute (NTFS_AT_STANDARD_INFORMATION).
+ */
+typedef struct NTFSATSTDINFO
+{
+ /** 0x00: Creation timestamp. */
+ int64_t iCreationTime;
+ /** 0x08: Last data modification timestamp. */
+ int64_t iLastDataModTime;
+ /** 0x10: Last MFT record modification timestamp. */
+ int64_t iLastMftModTime;
+ /** 0x18: Last access timestamp. */
+ int64_t iLastAccessTime;
+ /** 0x20: File attributes. */
+ uint32_t fFileAttribs;
+ /** 0x24: Maximum number of file versions allowed.
+ * @note NTFS 3.x, padding in 1.2 */
+ uint32_t cMaxFileVersions;
+ /** 0x28: Current file version number.
+ * @note NTFS 3.x, padding in 1.2 */
+ uint32_t uFileVersion;
+ /** 0x2c: Class ID (whatever that is).
+ * @note NTFS 3.x, padding in 1.2 */
+ uint32_t idClass;
+ /** 0x30: Owner ID.
+ * Translated via $Q index in NTFS_MFT_IDX_EXTENDED/$Quota.
+ * @note NTFS 3.x, not present in 1.2 */
+ uint32_t idOwner;
+ /** 0x34: Security ID. Translated via $SII index and $SDS data stream in
+ * NTFS_MFT_IDX_SECURITY.
+ * @note NTFS 3.x, not present in 1.2 */
+ uint32_t idSecurity;
+ /** 0x38: Total quota charged for this file.
+ * @note NTFS 3.x, not present in 1.2 */
+ uint64_t cbQuotaChared;
+ /** 0x40: Last update sequence number, index into $UsnJrnl.
+ * @note NTFS 3.x, not present in 1.2 */
+ uint64_t idxUpdateSequence;
+} NTFSATSTDINFO;
+AssertCompileSize(NTFSATSTDINFO, 0x48);
+/** Pointer to NTFS standard file info. */
+typedef NTFSATSTDINFO *PNTFSATSTDINFO;
+/** Pointer to const NTFS standard file info. */
+typedef NTFSATSTDINFO const *PCNTFSATSTDINFO;
+
+/** The size of NTFSATSTDINFO in NTFS v1.2 and earlier. */
+#define NTFSATSTDINFO_SIZE_NTFS_V12 (0x30)
+
+/** @name NTFS_FA_XXX - NTFS file attributes (host endian).
+ * @{ */
+#define NTFS_FA_READONLY UINT32_C(0x00000001)
+#define NTFS_FA_HIDDEN UINT32_C(0x00000002)
+#define NTFS_FA_SYSTEM UINT32_C(0x00000004)
+#define NTFS_FA_DIRECTORY UINT32_C(0x00000010)
+#define NTFS_FA_ARCHIVE UINT32_C(0x00000020)
+#define NTFS_FA_DEVICE UINT32_C(0x00000040)
+#define NTFS_FA_NORMAL UINT32_C(0x00000080)
+#define NTFS_FA_TEMPORARY UINT32_C(0x00000100)
+#define NTFS_FA_SPARSE_FILE UINT32_C(0x00000200)
+#define NTFS_FA_REPARSE_POINT UINT32_C(0x00000400)
+#define NTFS_FA_COMPRESSED UINT32_C(0x00000800)
+#define NTFS_FA_OFFLINE UINT32_C(0x00001000)
+#define NTFS_FA_NOT_CONTENT_INDEXED UINT32_C(0x00002000)
+#define NTFS_FA_ENCRYPTED UINT32_C(0x00004000)
+#define NTFS_FA_VALID_FLAGS UINT32_C(0x00007fb7)
+#define NTFS_FA_VALID_SET_FLAGS UINT32_C(0x000031a7)
+#define NTFS_FA_DUP_FILE_NAME_INDEX_PRESENT UINT32_C(0x10000000) /**< This means directory apparently. */
+#define NTFS_FA_DUP_VIEW_INDEX_PRESENT UINT32_C(0x20000000) /**< ?? */
+/** @} */
+
+
+
+/**
+ * NTFS filename attribute (NTFS_AT_FILENAME).
+ */
+typedef struct NTFSATFILENAME
+{
+ /** 0x00: The parent directory MFT record. */
+ NTFSMFTREF ParentDirMftRec;
+ /** 0x08: Creation timestamp. */
+ int64_t iCreationTime;
+ /** 0x10: Last data modification timestamp. */
+ int64_t iLastDataModTime;
+ /** 0x18: Last MFT record modification timestamp. */
+ int64_t iLastMftModTime;
+ /** 0x20: Last access timestamp. */
+ int64_t iLastAccessTime;
+ /** 0x28: Allocated disk space for the unnamed data attribute. */
+ int64_t cbAllocated;
+ /** 0x30: Actual size of unnamed data attribute. */
+ int64_t cbData;
+ /** 0x38: File attributes (NTFS_FA_XXX). */
+ uint32_t fFileAttribs;
+ union
+ {
+ /** 0x3c: Packed EA length. */
+ uint16_t cbPackedEas;
+ /** 0x3c: Reparse tag, if no EAs. */
+ uint32_t uReparseTag;
+ } u;
+ /** 0x40: Filename length in unicode chars. */
+ uint8_t cwcFilename;
+ /** 0x41: Filename type (NTFS_FILENAME_T_XXX). */
+ uint8_t fFilenameType;
+ /** 0x42: The filename. */
+ RT_FLEXIBLE_ARRAY_EXTENSION
+ RTUTF16 wszFilename[RT_FLEXIBLE_ARRAY];
+} NTFSATFILENAME;
+AssertCompileMemberOffset(NTFSATFILENAME, cbData, 0x30);
+AssertCompileMemberOffset(NTFSATFILENAME, u.cbPackedEas, 0x3c);
+AssertCompileMemberOffset(NTFSATFILENAME, u.uReparseTag, 0x3c);
+AssertCompileMemberOffset(NTFSATFILENAME, wszFilename, 0x42);
+/** Pointer to a NTFS filename attribute. */
+typedef NTFSATFILENAME *PNTFSATFILENAME;
+/** Pointer to a const NTFS filename attribute. */
+typedef NTFSATFILENAME const *PCNTFSATFILENAME;
+
+/** @name NTFS_FILENAME_T_XXX - filename types
+ * @{ */
+#define NTFS_FILENAME_T_POSIX 0
+#define NTFS_FILENAME_T_WINDOWS 1
+#define NTFS_FILENAME_T_DOS 2
+#define NTFS_FILENAME_T_WINDOWS_AND_DSO 3
+/** @} */
+
+
+/**
+ * NTFS volume information (NTFS_AT_VOLUME_INFORMATION).
+ *
+ * This is found in the special NTFS_MFT_IDX_VOLUME file.
+ */
+typedef struct NTFSATVOLUMEINFO
+{
+ /** 0x00: Reserved bytes. */
+ uint8_t abReserved[8];
+ /** 0x08: Major NTFS version number. */
+ uint8_t uMajorVersion;
+ /** 0x09: Minor NTFS version number. */
+ uint8_t uMinorVersion;
+ /** 0x0a: Volume flags (NTFS_VOLUME_F_XXX) */
+ uint16_t fFlags;
+} NTFSATVOLUMEINFO;
+AssertCompileSize(NTFSATVOLUMEINFO, 12);
+/** Pointer to NTFS volume information. */
+typedef NTFSATVOLUMEINFO *PNTFSATVOLUMEINFO;
+/** Pointer to const NTFS volume information. */
+typedef NTFSATVOLUMEINFO const *PCNTFSATVOLUMEINFO;
+
+/** @name NTFS_VOLUME_F_XXX
+ * @{ */
+#define NTFS_VOLUME_F_DIRTY RT_H2LE_U16_C(0x0001) /**< Volume is dirty. */
+#define NTFS_VOLUME_F_RESIZE_LOG_FILE RT_H2LE_U16_C(0x0002) /**< */
+#define NTFS_VOLUME_F_UPGRADE_ON_MOUNT RT_H2LE_U16_C(0x0004) /**< */
+#define NTFS_VOLUME_F_MOUNTED_ON_NT4 RT_H2LE_U16_C(0x0008) /**< */
+#define NTFS_VOLUME_F_DELETE_USN_UNDERWAY RT_H2LE_U16_C(0x0010) /**< */
+#define NTFS_VOLUME_F_REPAIR_OBJECT_ID RT_H2LE_U16_C(0x0020) /**< */
+#define NTFS_VOLUME_F_CHKDSK_UNDERWAY RT_H2LE_U16_C(0x4000) /**< */
+#define NTFS_VOLUME_F_MODIFIED_BY_CHKDSK RT_H2LE_U16_C(0x8000) /**< */
+
+#define NTFS_VOLUME_F_KNOWN_MASK RT_H2LE_U16_C(0xc03f)
+#define NTFS_VOLUME_F_MOUNT_READONLY_MASK RT_H2LE_U16_C(0xc027)
+/** @} */
+
+
+/** The attribute name used by the index attributes on NTFS directories,
+ * ASCII stirng variant. */
+#define NTFS_DIR_ATTRIBUTE_NAME "$I30"
+
+/**
+ * NTFS index header.
+ *
+ * This is used by NTFSATINDEXROOT and NTFSATINDEXALLOC as a prelude to the
+ * sequence of entries in a node.
+ */
+typedef struct NTFSINDEXHDR
+{
+ /** 0x00: Offset of the first entry relative to this header. */
+ uint32_t offFirstEntry;
+ /** 0x04: Current index size in bytes, including this header. */
+ uint32_t cbUsed;
+ /** 0x08: Number of bytes allocated for the index (including this header). */
+ uint32_t cbAllocated;
+ /** 0x0c: Flags (NTFSINDEXHDR_F_XXX). */
+ uint8_t fFlags;
+ /** 0x0d: Reserved bytes. */
+ uint8_t abReserved[3];
+ /* NTFSIDXENTRYHDR sequence typically follows here */
+} NTFSINDEXHDR;
+AssertCompileSize(NTFSINDEXHDR, 16);
+/** Pointer to a NTFS index header. */
+typedef NTFSINDEXHDR *PNTFSINDEXHDR;
+/** Pointer to a const NTFS index header. */
+typedef NTFSINDEXHDR const *PCNTFSINDEXHDR;
+
+/** @name NTFSINDEXHDR_F_XXX
+ * @{ */
+/** An internal node (as opposed to a leaf node if clear).
+ * This means that the entries will have trailing node references (VCN). */
+#define NTFSINDEXHDR_F_INTERNAL UINT8_C(0x01)
+/** @} */
+
+/** Gets the pointer to the first entry header for an index. */
+#define NTFSINDEXHDR_GET_FIRST_ENTRY(a_pIndexHdr) \
+ ( (PNTFSIDXENTRYHDR)((uint8_t *)(a_pIndexHdr) + RT_LE2H_U32((a_pIndexHdr)->offFirstEntry)) )
+
+
+/**
+ * NTFS index root node (NTFS_AT_INDEX_ROOT).
+ *
+ * This is a generic index structure, but is most prominently used for
+ * implementating directories. The index is structured like B-tree, meaning
+ * each node contains multiple entries, and each entry contains data regardless
+ * of whether it's a leaf node or not.
+ *
+ * The index is sorted in ascending order according to the collation rules
+ * defined by the root node (NTFSATINDEXROOT::uCollationRules, see also (see
+ * NTFS_COLLATION_XXX).
+ *
+ * @note The root directory contains a '.' entry, others don't.
+ */
+typedef struct NTFSATINDEXROOT
+{
+ /** 0x00: The index type (NTFSATINDEXROOT_TYPE_XXX). */
+ uint32_t uType;
+ /** 0x04: The sorting rules to use (NTFS_COLLATION_XXX). */
+ uint32_t uCollationRules;
+ /** 0x08: Number of bytes in
+ * Index node size (in bytes). */
+ uint32_t cbIndexNode;
+ /** 0x0c: Number of node addresses per node.
+ * This sounds weird right? A subnode is generally addressed as a virtual
+ * cluster when cbIndexNode >= cbCluster, but when clusters are large NTFS uses
+ * 512 bytes chunks.
+ *
+ * (You would've thought it would be simpler to just use cbIndexNode as the
+ * addressing unit, maybe storing the log2 here to avoid a ffs call.) */
+ uint8_t cAddressesPerIndexNode;
+ /** 0x0d: Reserved padding or something. */
+ uint8_t abReserved[3];
+ /** 0x10: Index header detailing the entries that follows. */
+ NTFSINDEXHDR Hdr;
+ /* 0x20: NTFSIDXENTRYHDR sequence typically follows here */
+} NTFSATINDEXROOT;
+AssertCompileSize(NTFSATINDEXROOT, 32);
+/** Pointer to a NTFS index root. */
+typedef NTFSATINDEXROOT *PNTFSATINDEXROOT;
+/** Pointer to a const NTFS index root. */
+typedef NTFSATINDEXROOT const *PCNTFSATINDEXROOT;
+
+/** @name NTFSATINDEXROOT_TYPE_XXX
+ * @{ */
+/** View index. */
+#define NTFSATINDEXROOT_TYPE_VIEW RT_H2LE_U32_C(UINT32_C(0x00000000))
+/** Directory index, NTFSATFILENAME follows NTFSINDEXENTRY. */
+#define NTFSATINDEXROOT_TYPE_DIR RT_H2LE_U32_C(UINT32_C(0x00000030))
+/** @} */
+
+/** @name NTFS_COLLATION_XXX - index sorting rules
+ * @{ */
+/** Little endian binary compare (or plain byte compare if you like). */
+#define NTFS_COLLATION_BINARY RT_H2LE_U32_C(UINT32_C(0x00000000))
+/** Same as NTFS_COLLATION_UNICODE_STRING. */
+#define NTFS_COLLATION_FILENAME RT_H2LE_U32_C(UINT32_C(0x00000001))
+/** Compare the uppercased unicode characters. */
+#define NTFS_COLLATION_UNICODE_STRING RT_H2LE_U32_C(UINT32_C(0x00000002))
+
+/** Single little endian 32-bit unsigned integer value as sort key. */
+#define NTFS_COLLATION_UINT32 RT_H2LE_U32_C(UINT32_C(0x00000010))
+/** Little endian SID value as sort key. */
+#define NTFS_COLLATION_SID RT_H2LE_U32_C(UINT32_C(0x00000011))
+/** Two little endian 32-bit unsigned integer values used as sorting key. */
+#define NTFS_COLLATION_UINT32_PAIR RT_H2LE_U32_C(UINT32_C(0x00000012))
+/** Sequence of little endian 32-bit unsigned integer values used as sorting key. */
+#define NTFS_COLLATION_UINT32_SEQ RT_H2LE_U32_C(UINT32_C(0x00000013))
+/** @} */
+
+
+/**
+ * NTFS index non-root node.
+ */
+typedef struct NTFSATINDEXALLOC
+{
+ /** 0x00: Header with NTFSREC_MAGIC_INDEX_ALLOC. */
+ NTFSRECHDR RecHdr;
+ /** 0x08: Log file sequence number. */
+ uint64_t uLsn;
+ /** 0x10: The node address of this node (for consistency checking and
+ * perhaps data reconstruction).
+ * @see NTFSATINDEXROOT::cAddressesPerIndexNode for node addressing. */
+ int64_t iSelfAddress;
+ /** 0x18: Index header detailing the entries that follows. */
+ NTFSINDEXHDR Hdr;
+ /* 0x28: NTFSIDXENTRYHDR sequence typically follows here */
+} NTFSATINDEXALLOC;
+AssertCompileSize(NTFSATINDEXALLOC, 40);
+/** Pointer to a NTFS index non-root node. */
+typedef NTFSATINDEXALLOC *PNTFSATINDEXALLOC;
+/** Pointer to a const NTFS index non-root node. */
+typedef NTFSATINDEXALLOC const *PCNTFSATINDEXALLOC;
+
+/** NTFS 'INDX' attribute magic value (NTFSATINDEXALLOC).
+ * @todo sort out the record / attribute name clash here. */
+#define NTFSREC_MAGIC_INDEX_ALLOC RT_H2LE_U32_C(UINT32_C(0x58444e49))
+
+
+/**
+ * NTFS index entry header.
+ *
+ * Each entry in a node starts with this header. It is immediately followed by
+ * the key data (NTFSIDXENTRYHDR::cbKey). When
+ *
+ */
+typedef struct NTFSIDXENTRYHDR
+{
+ union
+ {
+ /** 0x00: NTFSATINDEXROOT_TYPE_DIR: Reference to the MFT record being indexed here.
+ * @note This is invalid if NTFSIDXENTRYHDR_F_END is set (no key data). */
+ NTFSMFTREF FileMftRec;
+ /** 0x00: NTFSATINDEXROOT_TYPE_VIEW: Go figure later if necessary. */
+ struct
+ {
+ /** 0x00: Offset to the data relative to this header.
+ * @note This is invalid if NTFSIDXENTRYHDR_F_END is set (no key data). */
+ uint16_t offData;
+ /** 0x02: Size of data at offData.
+ * @note This is invalid if NTFSIDXENTRYHDR_F_END is set (no key data). */
+ uint16_t cbData;
+ /** 0x04: Reserved. */
+ uint32_t uReserved;
+ } View;
+ } u;
+
+ /** 0x08: Size of this entry, 8-byte aligned. */
+ uint16_t cbEntry;
+ /** 0x0a: Key length (unaligned). */
+ uint16_t cbKey;
+ /** 0x0c: Entry flags, NTFSIDXENTRYHDR_F_XXX. */
+ uint16_t fFlags;
+ /** 0x0e: Reserved. */
+ uint16_t uReserved;
+} NTFSIDXENTRYHDR;
+AssertCompileSize(NTFSIDXENTRYHDR, 16);
+/** Pointer to a NTFS index entry header. */
+typedef NTFSIDXENTRYHDR *PNTFSIDXENTRYHDR;
+/** Pointer to a const NTFS index entry header. */
+typedef NTFSIDXENTRYHDR const *PCNTFSIDXENTRYHDR;
+
+/** @name NTFSIDXENTRYHDR_F_XXX - NTFSIDXENTRYHDR::fFlags
+ * @{ */
+/** Indicates an internal node (as opposed to a leaf node).
+ * This indicates that there is a 64-bit integer value at the very end of the
+ * entry (NTFSIDXENTRYHDR::cbEntry - 8) giving the virtual cluster number of the
+ * subnode. The subnode and all its decendants contain keys that are lower than
+ * the key in this entry.
+ */
+#define NTFSIDXENTRYHDR_F_INTERNAL RT_H2LE_U16_C(UINT16_C(0x0001))
+/** Set if special end entry in a node.
+ * This does not have any key data, but can point to a subnode with
+ * higher keys. */
+#define NTFSIDXENTRYHDR_F_END RT_H2LE_U16_C(UINT16_C(0x0002))
+/** @} */
+
+/** Gets the pointer to the next index entry header. */
+#define NTFSIDXENTRYHDR_GET_NEXT(a_pEntryHdr) \
+ ( (PNTFSIDXENTRYHDR)((uintptr_t)(a_pEntryHdr) + RT_LE2H_U16((a_pEntryHdr)->cbEntry)) )
+/** Gets the subnode address from an index entry.
+ * @see NTFSATINDEXROOT::cAddressesPerIndexNode for node addressing.
+ * @note Only invoke when NTFSIDXENTRYHDR_F_INTERNAL is set! */
+#define NTFSIDXENTRYHDR_GET_SUBNODE(a_pEntryHdr) \
+ ( *(int64_t *)((uintptr_t)(a_pEntryHdr) + RT_LE2H_U16((a_pEntryHdr)->cbEntry) - sizeof(int64_t)) )
+
+/** @} */
+
+#endif /* !IPRT_INCLUDED_formats_ntfs_h */
+
diff --git a/include/iprt/formats/omf.h b/include/iprt/formats/omf.h
new file mode 100644
index 00000000..b5ffb01d
--- /dev/null
+++ b/include/iprt/formats/omf.h
@@ -0,0 +1,260 @@
+/* $Id: omf.h $ */
+/** @file
+ * IPRT - Relocatable Object Module Format (OMF).
+ *
+ * @remarks For a more details description, see specification from Tools
+ * Interface Standards (TIS), version 1.1 dated May 2015.
+ * Typically named found as OMF_v1.1.pdf.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_formats_omf_h
+#define IPRT_INCLUDED_formats_omf_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/stdint.h>
+#include <iprt/assertcompile.h>
+
+
+/** @defgroup grp_rt_formats_omf Relocatable Object Module Format (OMF) structures and definitions
+ * @ingroup grp_rt_formats
+ * @{
+ */
+
+/**
+ * OMF record header.
+ */
+#pragma pack(1)
+typedef struct OMFRECHDR
+{
+ /** The record type. */
+ uint8_t bType;
+ /** The record length, excluding the this header. */
+ uint16_t cbLen;
+} OMFRECHDR;
+#pragma pack()
+AssertCompileSize(OMFRECHDR, 3);
+/** Pointer to an OMF header. */
+typedef OMFRECHDR *POMFRECHDR;
+/** Pointer to a const OMF header. */
+typedef OMFRECHDR *PCOMFRECHDR;
+
+/** The max OMF record length, including the header. */
+#define OMF_MAX_RECORD_LENGTH UINT16_C(1024)
+
+/** The max OMF record payload, including CRC byte. */
+#define OMF_MAX_RECORD_PAYLOAD UINT16_C(1021)
+
+
+/** @name OMF Record Types (OMFRECHDR::bType).
+ * @{ */
+/** Record type flag indicating 32-bit record. */
+#define OMF_REC32 UINT8_C(0x01)
+/** Object file header record.
+ * Is followed by a length prefixed string */
+#define OMF_THEADR UINT8_C(0x80)
+/** Comment record.
+ * Is followed by a comment type byte and a commen class byte, thereafter comes
+ * type specific byte sequence. */
+#define OMF_COMENT UINT8_C(0x88)
+/** Local name table referenced by segment and group defintions.
+ * Array of length prefixed strings. Multi record. */
+#define OMF_LNAMES UINT8_C(0x96)
+/** 16-bit segment definition.
+ * Complicated, see TIS docs. */
+#define OMF_SEGDEF16 UINT8_C(0x98)
+/** 32-bit segment definition.
+ * Complicated, see TIS docs. */
+#define OMF_SEGDEF32 UINT8_C(0x99)
+/** Segment group definition.
+ * Starts with an LNAMES index (one or two bytes) of the group name. Followed
+ * by an array which entries consists of a 0xff byte and a segment
+ * defintion index (one or two bytes). */
+#define OMF_GRPDEF UINT8_C(0x9a)
+/** External symbol defintions.
+ * Array where each entry is a length prefixed symbol name string followed by a
+ * one or two byte type number. */
+#define OMF_EXTDEF UINT8_C(0x8c)
+/** 16-but public symbol definitions.
+ * Starts with a group index (one or two bytes) and a segment index (ditto)
+ * which indicates which group/segment the symbols belong to.
+ * Is followed by an array with entries consiting of a length prefixed symbol
+ * name string, a two byte segment offset, and a one or two byte type index. */
+#define OMF_PUBDEF16 UINT8_C(0x90)
+/** 32-but public symbol definitions.
+ * Identical to #OMF_PUBDEF16 except that the symbol offset field is four
+ * byte. */
+#define OMF_PUBDEF32 UINT8_C(0x91)
+/** 16-bit local symbol definitions.
+ * Same format as #OMF_PUBDEF16. */
+#define OMF_LPUBDEF16 UINT8_C(0xb6)
+/** 16-bit local symbol definitions.
+ * Same format as #OMF_PUBDEF32. */
+#define OMF_LPUBDEF32 UINT8_C(0xb7)
+/** Logical enumerated data record (a chunk of raw segment bits).
+ * Starts with the index of the segment it contributes to (one or two bytes) and
+ * is followed by the offset into the segment of the bytes (two bytes).
+ * After that comes the raw data bytes. */
+#define OMF_LEDATA16 UINT8_C(0xa0)
+/** Logical enumerated data record (a chunk of raw segment bits).
+ * Identical to #OMF_LEDATA16 except that is has a the segment offset field is
+ * four bytes. */
+#define OMF_LEDATA32 UINT8_C(0xa1)
+/** 16-bit fixup record.
+ * Complicated, see TIS docs. */
+#define OMF_FIXUPP16 UINT8_C(0x9c)
+/** 32-bit fixup record.
+ * Complicated, see TIS docs. */
+#define OMF_FIXUPP32 UINT8_C(0x9d)
+/** 16-bit line numbers record. */
+#define OMF_LINNUM16 UINT8_C(0x94)
+/** 32-bit line numbers record. */
+#define OMF_LINNUM32 UINT8_C(0x95)
+/** 16-bit object file end record.
+ * Duh! wrong bitfield order.
+ *
+ * Starts with a byte bitfield indicating module type: bit 0 is set if this is a
+ * main program module; bit 1 is set if this is a start address is available;
+ * bits 2 thru 6 are reserved and must be zero; bit 7 is set to indicate
+ * a non-absolute start address.
+ *
+ * When bit 1 is set what follow is: A FIXUPP byte, one or two byte frame datum,
+ * one or two byte target datum, and a 2 byte target displacement. */
+#define OMF_MODEND16 UINT8_C(0x8a)
+/** 32-bit object file end record.
+ * Identical to #OMF_MODEND16 except that is has a 4 byte target
+ * displacement field. */
+#define OMF_MODEND32 UINT8_C(0x8b)
+/** @} */
+
+/** @name OMF COMENT Type Flags
+ * @{ */
+/** Comment type: Don't remove comment when object is manipulated. */
+#define OMF_CTYP_NO_PURGE UINT8_C(0x80)
+/** Comment type: Don't include in object listing. */
+#define OMF_CTYP_NO_LIST UINT8_C(0x40)
+/** @} */
+
+/** @name OMF COMENT Classes
+ * @{ */
+/** Comment class: Dependency file.
+ * Is followed by a dword timestamp (1980 based?) and a length prefix
+ * filename string. */
+#define OMF_CCLS_DEP_FILE UINT8_C(0x88)
+/** Comment class: Link pass separator.
+ * Contains a byte with the value 01 to indicate the linker can stop pass 1
+ * processing now. */
+#define OMF_CCLS_LINK_PASS_SEP UINT8_C(0xa2)
+/** Comment class: Borland type information. */
+#define OMF_CCLS_BORLAND_TYPES UINT8_C(0xe3)
+/** Comment class: Borland symbol information. */
+#define OMF_CCLS_BORLAND_SYMBOLS UINT8_C(0xe6)
+/** Comment class: Borland source file (applies to subsequent LINNUMs). */
+#define OMF_CCLS_BORLAND_SRC_FILE UINT8_C(0xe8)
+/** Comment class: Borland dependency files. */
+#define OMF_CCLS_BORLAND_DEP_FILES UINT8_C(0xe9)
+/** @} */
+
+/** @name OMF SEGDEF Attrib.
+ * @{ */
+#define OMF_SEG_ATTR_ALIGN_ABS (UINT8_C(0) << 5) /**< SEGDEF attrib A: absolute - frame and offset fields present. */
+#define OMF_SEG_ATTR_ALIGN_BYTE (UINT8_C(1) << 5) /**< SEGDEF attrib A: 1-byte alignment. */
+#define OMF_SEG_ATTR_ALIGN_WORD (UINT8_C(2) << 5) /**< SEGDEF attrib A: 2-byte alignment. */
+#define OMF_SEG_ATTR_ALIGN_PARA (UINT8_C(3) << 5) /**< SEGDEF attrib A: 16-byte alignment. */
+#define OMF_SEG_ATTR_ALIGN_PAGE (UINT8_C(4) << 5) /**< SEGDEF attrib A: 4096-byte alignment (or 256-byte). */
+#define OMF_SEG_ATTR_ALIGN_DWORD (UINT8_C(5) << 5) /**< SEGDEF attrib A: 4-byte alignment. */
+#define OMF_SEG_ATTR_ALIGN_6 (UINT8_C(6) << 5) /**< SEGDEF attrib A: not supported (load-time locatable, paragraph aligned). */
+#define OMF_SEG_ATTR_ALIGN_7 (UINT8_C(7) << 5) /**< SEGDEF attrib A: undefined. */
+#define OMF_SEG_ATTR_ALIGN_MASK (UINT8_C(7) << 5) /**< SEGDEF attrib A: Mask for the alignment field. */
+#define OMF_SEG_ATTR_ALIGN_SHIFT 5 /**< SEGDEF attrib A: Shift count for the alignment field. */
+
+#define OMF_SEG_ATTR_COMB_PRIVATE (UINT8_C(0) << 2) /**< SEGDEF attrib C: Private - do not combine with anyone. */
+#define OMF_SEG_ATTR_COMB_1 (UINT8_C(1) << 2) /**< SEGDEF attrib C: Reserved */
+#define OMF_SEG_ATTR_COMB_PUBLIC (UINT8_C(2) << 2) /**< SEGDEF attrib C: Public - append at offset meeting alignment. */
+#define OMF_SEG_ATTR_COMB_3 (UINT8_C(3) << 2) /**< SEGDEF attrib C: Reserved */
+#define OMF_SEG_ATTR_COMB_PUBLIC_4 (UINT8_C(4) << 2) /**< SEGDEF attrib C: Public - append at offset meeting alignment. */
+#define OMF_SEG_ATTR_COMB_STACK (UINT8_C(5) << 2) /**< SEGDEF attrib C: Stack - same as public, but forced byte alignment. */
+#define OMF_SEG_ATTR_COMB_COMMON (UINT8_C(6) << 2) /**< SEGDEF attrib C: Common - overlay using maximum size. */
+#define OMF_SEG_ATTR_COMB_PUBLIC_7 (UINT8_C(5) << 2) /**< SEGDEF attrib C: Public - append at offset meeting alignment. */
+#define OMF_SEG_ATTR_COMB_MASK (UINT8_C(7) << 2) /**< SEGDEF attrib C: Mask for the combination field. */
+#define OMF_SEG_ATTR_COMB_SHIFT 2 /**< SEGDEF attrib C: Shift count for the combination field. */
+#define OMF_SEG_ATTR_BIG UINT8_C(2) /**< SEGDEF attrib B: Big segment 64K / 4GB. */
+#define OMF_SEG_ATTR_USE32 UINT8_C(1) /**< SEGDEF attrib P: Indicates 32-bit data or code. */
+#define OMF_SEG_ATTR_USE16 UINT8_C(0) /**< SEGDEF attrib ~P: Just for spelling out !USE32. */
+/** @} */
+
+
+/** @name OMF FIXUPP Locations.
+ * @{ */
+#define OMF_FIX_LOC_8BIT_LOW_BYTE UINT8_C(0) /**< FIXUP location: low byte (offset or displacement). */
+#define OMF_FIX_LOC_16BIT_OFFSET UINT8_C(1) /**< FIXUP location: 16-bit offset. */
+#define OMF_FIX_LOC_16BIT_SEGMENT UINT8_C(2) /**< FIXUP location: 16-bit segment. */
+#define OMF_FIX_LOC_1616FAR UINT8_C(3) /**< FIXUP location: 16:16 far pointer. */
+#define OMF_FIX_LOC_8BIT_HIGH_BYTE UINT8_C(4) /**< FIXUP location: high byte (offset). Not supported by MS/IBM. */
+#define OMF_FIX_LOC_16BIT_OFFSET_LDR UINT8_C(5) /**< FIXUP location: 16-bit loader resolved offset, same a 1 for linker. PharLab conflict. */
+#define OMF_FIX_LOC_RESERVED_FAR1632 UINT8_C(6) /**< FIXUP location: PharLab 16:32 far pointers, not defined by MS/IBM. */
+#define OMF_FIX_LOC_RESERVED_7 UINT8_C(7) /**< FIXUP location: Not defined. */
+#define OMF_FIX_LOC_RESERVED_8 UINT8_C(8) /**< FIXUP location: Not defined. */
+#define OMF_FIX_LOC_32BIT_OFFSET UINT8_C(9) /**< FIXUP location: 32-bit offset. */
+#define OMF_FIX_LOC_RESERVED_10 UINT8_C(10) /**< FIXUP location: Not defined. */
+#define OMF_FIX_LOC_1632FAR UINT8_C(11) /**< FIXUP location: 16:32 far pointer. */
+#define OMF_FIX_LOC_RESERVED_12 UINT8_C(12) /**< FIXUP location: Not defined. */
+#define OMF_FIX_LOC_32BIT_OFFSET_LDR UINT8_C(13) /**< FIXUP location: 32-bit loader resolved offset, same as 9 for linker. */
+/** @} */
+/** @name OMF FIXUPP Targets
+ * @{ */
+#define OMF_FIX_T_SEGDEF UINT8_C(0) /**< FIXUP target: SEGDEF index. */
+#define OMF_FIX_T_GRPDEF UINT8_C(1) /**< FIXUP target: GRPDEF index. */
+#define OMF_FIX_T_EXTDEF UINT8_C(2) /**< FIXUP target: EXTDEF index. */
+#define OMF_FIX_T_FRAME_NO UINT8_C(3) /**< FIXUP target: Explicit frame number, not supported by MS/IBM. */
+#define OMF_FIX_T_SEGDEF_NO_DISP UINT8_C(4) /**< FIXUP target: SEGDEF index only, displacement take as 0. */
+#define OMF_FIX_T_GRPDEF_NO_DISP UINT8_C(5) /**< FIXUP target: GRPDEF index only, displacement take as 0. */
+#define OMF_FIX_T_EXTDEF_NO_DISP UINT8_C(6) /**< FIXUP target: EXTDEF index only, displacement take as 0. */
+/** @} */
+/** @name OMF FIXUPP Frames
+ * @{ */
+#define OMF_FIX_F_SEGDEF UINT8_C(0) /**< FIXUP frame: SEGDEF index. */
+#define OMF_FIX_F_GRPDEF UINT8_C(1) /**< FIXUP frame: GRPDEF index. */
+#define OMF_FIX_F_EXTDEF UINT8_C(2) /**< FIXUP frame: EXTDEF index. */
+#define OMF_FIX_F_FRAME_NO UINT8_C(3) /**< FIXUP frame: Explicit frame number, not supported by any linkers. */
+#define OMF_FIX_F_LXDATA_SEG UINT8_C(4) /**< FIXUP frame: Determined from the data being fixed up. (No index field.) */
+#define OMF_FIX_F_TARGET_SEG UINT8_C(5) /**< FIXUP frame: Determined from the target. (No index field.) */
+#define OMF_FIX_F_RESERVED_6 UINT8_C(6) /**< FIXUP frame: Reserved. */
+/** @} */
+
+
+/** @} */
+#endif /* !IPRT_INCLUDED_formats_omf_h */
+
diff --git a/include/iprt/formats/pe.mac b/include/iprt/formats/pe.mac
new file mode 100644
index 00000000..62bf83b1
--- /dev/null
+++ b/include/iprt/formats/pe.mac
@@ -0,0 +1,732 @@
+;; @file
+; IPRT - Windows PE definitions for YASM/NASM.
+;
+
+;
+; Copyright (C) 2006-2022 Oracle and/or its affiliates.
+;
+; This file is part of VirtualBox base platform packages, as
+; available from https://www.virtualbox.org.
+;
+; This program is free software; you can redistribute it and/or
+; modify it under the terms of the GNU General Public License
+; as published by the Free Software Foundation, in version 3 of the
+; License.
+;
+; This program is distributed in the hope that it will be useful, but
+; WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with this program; if not, see <https://www.gnu.org/licenses>.
+;
+; The contents of this file may alternatively be used under the terms
+; of the Common Development and Distribution License Version 1.0
+; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+; in the VirtualBox 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.
+;
+; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+;
+
+%ifndef ___iprt_format_pe_mac
+%define ___iprt_format_pe_mac
+
+
+;*******************************************************************************
+;* Header Files *
+;*******************************************************************************
+%include "iprt/asmdefs.mac"
+
+
+;*******************************************************************************
+;* Defined Constants And Macros *
+;*******************************************************************************
+%define IMAGE_NT_SIGNATURE 0x00004550
+
+; file header
+%define IMAGE_FILE_MACHINE_I386 0x014c
+%define IMAGE_FILE_MACHINE_AMD64 0x8664
+
+%define IMAGE_FILE_RELOCS_STRIPPED 0x0001
+%define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002
+%define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004
+%define IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008
+%define IMAGE_FILE_AGGRESIVE_WS_TRIM 0x0010
+%define IMAGE_FILE_LARGE_ADDRESS_AWARE 0x0020
+%define IMAGE_FILE_16BIT_MACHINE 0x0040
+%define IMAGE_FILE_BYTES_REVERSED_LO 0x0080
+%define IMAGE_FILE_32BIT_MACHINE 0x0100
+%define IMAGE_FILE_DEBUG_STRIPPED 0x0200
+%define IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP 0x0400
+%define IMAGE_FILE_NET_RUN_FROM_SWAP 0x0800
+%define IMAGE_FILE_SYSTEM 0x1000
+%define IMAGE_FILE_DLL 0x2000
+%define IMAGE_FILE_UP_SYSTEM_ONLY 0x4000
+%define IMAGE_FILE_BYTES_REVERSED_HI 0x8000
+
+
+; optional header
+%define IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10B
+%define IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20B
+
+%define IMAGE_SUBSYSTEM_UNKNOWN 0x0
+%define IMAGE_SUBSYSTEM_NATIVE 0x1
+%define IMAGE_SUBSYSTEM_WINDOWS_GUI 0x2
+%define IMAGE_SUBSYSTEM_WINDOWS_CUI 0x3
+%define IMAGE_SUBSYSTEM_OS2_GUI 0x4
+%define IMAGE_SUBSYSTEM_OS2_CUI 0x5
+%define IMAGE_SUBSYSTEM_POSIX_CUI 0x7
+
+%define IMAGE_LIBRARY_PROCESS_INIT 0x0001
+%define IMAGE_LIBRARY_PROCESS_TERM 0x0002
+%define IMAGE_LIBRARY_THREAD_INIT 0x0004
+%define IMAGE_LIBRARY_THREAD_TERM 0x0008
+%define IMAGE_DLLCHARACTERISTICS_NO_ISOLATION 0x0200
+%define IMAGE_DLLCHARACTERISTICS_NO_SEH 0x0400
+%define IMAGE_DLLCHARACTERISTICS_NO_BIND 0x0800
+%define IMAGE_DLLCHARACTERISTICS_WDM_DRIVER 0x2000
+%define IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE 0x8000
+
+%define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 0x10
+
+%define IMAGE_DIRECTORY_ENTRY_EXPORT 0x0
+%define IMAGE_DIRECTORY_ENTRY_IMPORT 0x1
+%define IMAGE_DIRECTORY_ENTRY_RESOURCE 0x2
+%define IMAGE_DIRECTORY_ENTRY_EXCEPTION 0x3
+%define IMAGE_DIRECTORY_ENTRY_SECURITY 0x4
+%define IMAGE_DIRECTORY_ENTRY_BASERELOC 0x5
+%define IMAGE_DIRECTORY_ENTRY_DEBUG 0x6
+%define IMAGE_DIRECTORY_ENTRY_ARCHITECTURE 0x7
+%define IMAGE_DIRECTORY_ENTRY_COPYRIGHT IMAGE_DIRECTORY_ENTRY_ARCHITECTURE
+%define IMAGE_DIRECTORY_ENTRY_GLOBALPTR 0x8
+%define IMAGE_DIRECTORY_ENTRY_TLS 0x9
+%define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 0xa
+%define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT 0xb
+%define IMAGE_DIRECTORY_ENTRY_IAT 0xc
+%define IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT 0xd
+%define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 0xe
+
+
+; section header
+%define IMAGE_SIZEOF_SHORT_NAME 0x8
+
+%define IMAGE_SCN_TYPE_REG 0x00000000
+%define IMAGE_SCN_TYPE_DSECT 0x00000001
+%define IMAGE_SCN_TYPE_NOLOAD 0x00000002
+%define IMAGE_SCN_TYPE_GROUP 0x00000004
+%define IMAGE_SCN_TYPE_NO_PAD 0x00000008
+%define IMAGE_SCN_TYPE_COPY 0x00000010
+
+%define IMAGE_SCN_CNT_CODE 0x00000020
+%define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040
+%define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080
+
+%define IMAGE_SCN_LNK_OTHER 0x00000100
+%define IMAGE_SCN_LNK_INFO 0x00000200
+%define IMAGE_SCN_TYPE_OVER 0x00000400
+%define IMAGE_SCN_LNK_REMOVE 0x00000800
+%define IMAGE_SCN_LNK_COMDAT 0x00001000
+%define IMAGE_SCN_MEM_PROTECTED 0x00004000
+%define IMAGE_SCN_NO_DEFER_SPEC_EXC 0x00004000
+%define IMAGE_SCN_GPREL 0x00008000
+%define IMAGE_SCN_MEM_FARDATA 0x00008000
+%define IMAGE_SCN_MEM_SYSHEAP 0x00010000
+%define IMAGE_SCN_MEM_PURGEABLE 0x00020000
+%define IMAGE_SCN_MEM_16BIT 0x00020000
+%define IMAGE_SCN_MEM_LOCKED 0x00040000
+%define IMAGE_SCN_MEM_PRELOAD 0x00080000
+
+%define IMAGE_SCN_ALIGN_1BYTES 0x00100000
+%define IMAGE_SCN_ALIGN_2BYTES 0x00200000
+%define IMAGE_SCN_ALIGN_4BYTES 0x00300000
+%define IMAGE_SCN_ALIGN_8BYTES 0x00400000
+%define IMAGE_SCN_ALIGN_16BYTES 0x00500000
+%define IMAGE_SCN_ALIGN_32BYTES 0x00600000
+%define IMAGE_SCN_ALIGN_64BYTES 0x00700000
+%define IMAGE_SCN_ALIGN_128BYTES 0x00800000
+%define IMAGE_SCN_ALIGN_256BYTES 0x00900000
+%define IMAGE_SCN_ALIGN_512BYTES 0x00A00000
+%define IMAGE_SCN_ALIGN_1024BYTES 0x00B00000
+%define IMAGE_SCN_ALIGN_2048BYTES 0x00C00000
+%define IMAGE_SCN_ALIGN_4096BYTES 0x00D00000
+%define IMAGE_SCN_ALIGN_8192BYTES 0x00E00000
+%define IMAGE_SCN_ALIGN_MASK 0x00F00000
+%define IMAGE_SCN_ALIGN_SHIFT 20
+
+%define IMAGE_SCN_LNK_NRELOC_OVFL 0x01000000
+%define IMAGE_SCN_MEM_DISCARDABLE 0x02000000
+%define IMAGE_SCN_MEM_NOT_CACHED 0x04000000
+%define IMAGE_SCN_MEM_NOT_PAGED 0x08000000
+%define IMAGE_SCN_MEM_SHARED 0x10000000
+%define IMAGE_SCN_MEM_EXECUTE 0x20000000
+%define IMAGE_SCN_MEM_READ 0x40000000
+%define IMAGE_SCN_MEM_WRITE 0x80000000
+
+
+; relocations
+%define IMAGE_REL_BASED_ABSOLUTE 0x0
+%define IMAGE_REL_BASED_HIGH 0x1
+%define IMAGE_REL_BASED_LOW 0x2
+%define IMAGE_REL_BASED_HIGHLOW 0x3
+%define IMAGE_REL_BASED_HIGHADJ 0x4
+%define IMAGE_REL_BASED_MIPS_JMPADDR 0x5
+%define IMAGE_REL_BASED_MIPS_JMPADDR16 0x9
+%define IMAGE_REL_BASED_IA64_IMM64 0x9
+%define IMAGE_REL_BASED_DIR64 0xa
+%define IMAGE_REL_BASED_HIGH3ADJ 0xb
+
+
+; imports
+%define IMAGE_ORDINAL_FLAG32 0x80000000
+%define IMAGE_ORDINAL_FLAG64 UINT64_MAX(0x8000000000000000)
+
+
+; debug dir
+%define IMAGE_DEBUG_TYPE_UNKNOWN UINT32_C(0x0)
+%define IMAGE_DEBUG_TYPE_COFF UINT32_C(0x1)
+%define IMAGE_DEBUG_TYPE_CODEVIEW UINT32_C(0x2)
+%define IMAGE_DEBUG_TYPE_FPO UINT32_C(0x3)
+%define IMAGE_DEBUG_TYPE_MISC UINT32_C(0x4)
+%define IMAGE_DEBUG_TYPE_EXCEPTION UINT32_C(0x5)
+%define IMAGE_DEBUG_TYPE_FIXUP UINT32_C(0x6)
+%define IMAGE_DEBUG_TYPE_OMAP_TO_SRC UINT32_C(0x7)
+%define IMAGE_DEBUG_TYPE_OMAP_FROM_SRC UINT32_C(0x8)
+%define IMAGE_DEBUG_TYPE_BORLAND UINT32_C(0x9)
+%define IMAGE_DEBUG_TYPE_RESERVED10 UINT32_C(0x10)
+
+%define IMAGE_DEBUG_MISC_EXENAME UINT32_C(1)
+
+; security directory
+%define WIN_CERT_REVISION_1_0 UINT16_C(0x0100)
+%define WIN_CERT_REVISION_2_0 UINT16_C(0x0200)
+
+%define WIN_CERT_TYPE_X509 UINT16_C(1)
+%define WIN_CERT_TYPE_PKCS_SIGNED_DATA UINT16_C(2)
+%define WIN_CERT_TYPE_RESERVED_1 UINT16_C(3)
+%define WIN_CERT_TYPE_TS_STACK_SIGNED UINT16_C(4)
+%define WIN_CERT_TYPE_EFI_PKCS115 UINT16_C(0x0ef0)
+%define WIN_CERT_TYPE_EFI_GUID UINT16_C(0x0ef1)
+
+
+; For .DBG files.
+%define IMAGE_SEPARATE_DEBUG_SIGNATURE UINT16_C(0x4944)
+
+%define IMAGE_SIZE_OF_SYMBOL 18
+%define IMAGE_SIZE_OF_SYMBOL_EX 20
+
+%define IMAGE_SYM_UNDEFINED INT16_C(0)
+%define IMAGE_SYM_ABSOLUTE INT16_C(-1)
+%define IMAGE_SYM_DEBUG INT16_C(-2)
+
+%define IMAGE_SYM_CLASS_END_OF_FUNCTION UINT8_C(0xff) ; -1
+%define IMAGE_SYM_CLASS_NULL UINT8_C(0)
+%define IMAGE_SYM_CLASS_AUTOMATIC UINT8_C(1)
+%define IMAGE_SYM_CLASS_EXTERNAL UINT8_C(2)
+%define IMAGE_SYM_CLASS_STATIC UINT8_C(3)
+%define IMAGE_SYM_CLASS_REGISTER UINT8_C(4)
+%define IMAGE_SYM_CLASS_EXTERNAL_DEF UINT8_C(5)
+%define IMAGE_SYM_CLASS_LABEL UINT8_C(6)
+%define IMAGE_SYM_CLASS_UNDEFINED_LABEL UINT8_C(7)
+%define IMAGE_SYM_CLASS_MEMBER_OF_STRUCT UINT8_C(8)
+%define IMAGE_SYM_CLASS_ARGUMENT UINT8_C(9)
+%define IMAGE_SYM_CLASS_STRUCT_TAG UINT8_C(10)
+%define IMAGE_SYM_CLASS_MEMBER_OF_UNION UINT8_C(11)
+%define IMAGE_SYM_CLASS_UNION_TAG UINT8_C(12)
+%define IMAGE_SYM_CLASS_TYPE_DEFINITION UINT8_C(13)
+%define IMAGE_SYM_CLASS_UNDEFINED_STATIC UINT8_C(14)
+%define IMAGE_SYM_CLASS_ENUM_TAG UINT8_C(15)
+%define IMAGE_SYM_CLASS_MEMBER_OF_ENUM UINT8_C(16)
+%define IMAGE_SYM_CLASS_REGISTER_PARAM UINT8_C(17)
+%define IMAGE_SYM_CLASS_BIT_FIELD UINT8_C(18)
+%define IMAGE_SYM_CLASS_FAR_EXTERNAL UINT8_C(68)
+%define IMAGE_SYM_CLASS_BLOCK UINT8_C(100)
+%define IMAGE_SYM_CLASS_FUNCTION UINT8_C(101)
+%define IMAGE_SYM_CLASS_END_OF_STRUCT UINT8_C(102)
+%define IMAGE_SYM_CLASS_FILE UINT8_C(103)
+%define IMAGE_SYM_CLASS_SECTION UINT8_C(104)
+%define IMAGE_SYM_CLASS_WEAK_EXTERNAL UINT8_C(105)
+%define IMAGE_SYM_CLASS_CLR_TOKEN UINT8_C(107)
+
+
+%define IMAGE_SYM_TYPE_NULL UINT16_C(0x0000)
+%define IMAGE_SYM_TYPE_VOID UINT16_C(0x0001)
+%define IMAGE_SYM_TYPE_CHAR UINT16_C(0x0002)
+%define IMAGE_SYM_TYPE_SHORT UINT16_C(0x0003)
+%define IMAGE_SYM_TYPE_INT UINT16_C(0x0004)
+%define IMAGE_SYM_TYPE_LONG UINT16_C(0x0005)
+%define IMAGE_SYM_TYPE_FLOAT UINT16_C(0x0006)
+%define IMAGE_SYM_TYPE_DOUBLE UINT16_C(0x0007)
+%define IMAGE_SYM_TYPE_STRUCT UINT16_C(0x0008)
+%define IMAGE_SYM_TYPE_UNION UINT16_C(0x0009)
+%define IMAGE_SYM_TYPE_ENUM UINT16_C(0x000a)
+%define IMAGE_SYM_TYPE_MOE UINT16_C(0x000b)
+%define IMAGE_SYM_TYPE_BYTE UINT16_C(0x000c)
+%define IMAGE_SYM_TYPE_WORD UINT16_C(0x000d)
+%define IMAGE_SYM_TYPE_UINT UINT16_C(0x000e)
+%define IMAGE_SYM_TYPE_DWORD UINT16_C(0x000f)
+%define IMAGE_SYM_TYPE_PCODE UINT16_C(0x8000)
+
+%define IMAGE_SYM_DTYPE_NULL UINT16_C(0x0)
+%define IMAGE_SYM_DTYPE_POINTER UINT16_C(0x1)
+%define IMAGE_SYM_DTYPE_FUNCTION UINT16_C(0x2)
+%define IMAGE_SYM_DTYPE_ARRAY UINT16_C(0x3)
+
+
+%define N_BTMASK UINT16_C(0x000f)
+%define N_TMASK UINT16_C(0x0030)
+%define N_TMASK1 UINT16_C(0x00c0)
+%define N_TMASK2 UINT16_C(0x00f0)
+%define N_BTSHFT 4
+%define N_TSHIFT 2
+
+
+;*******************************************************************************
+;* Structures and Typedefs *
+;*******************************************************************************
+
+struc IMAGE_FILE_HEADER
+ .Machine resw 1 ;;< 0x00
+ .NumberOfSections resw 1 ;;< 0x02
+ .TimeDateStamp resd 1 ;;< 0x04
+ .PointerToSymbolTable resd 1 ;;< 0x08
+ .NumberOfSymbols resd 1 ;;< 0x0c
+ .SizeOfOptionalHeader resw 1 ;;< 0x10
+ .Characteristics resw 1 ;;< 0x12
+endstruc
+AssertCompileSize(IMAGE_FILE_HEADER, 0x14)
+
+struc IMAGE_DATA_DIRECTORY
+ .VirtualAddress resd 1
+ .Size resd 1
+endstruc
+
+
+struc IMAGE_OPTIONAL_HEADER32
+ .Magic resw 1 ;;< 0x00
+ .MajorLinkerVersion resb 1 ;;< 0x02
+ .MinorLinkerVersion resb 1 ;;< 0x03
+ .SizeOfCode resd 1 ;;< 0x04
+ .SizeOfInitializedData resd 1 ;;< 0x08
+ .SizeOfUninitializedData resd 1 ;;< 0x0c
+ .AddressOfEntryPoint resd 1 ;;< 0x10
+ .BaseOfCode resd 1 ;;< 0x14
+ .BaseOfData resd 1 ;;< 0x18
+ .ImageBase resd 1 ;;< 0x1c
+ .SectionAlignment resd 1 ;;< 0x20
+ .FileAlignment resd 1 ;;< 0x24
+ .MajorOperatingSystemVersion resw 1 ;;< 0x28
+ .MinorOperatingSystemVersion resw 1 ;;< 0x2a
+ .MajorImageVersion resw 1 ;;< 0x2c
+ .MinorImageVersion resw 1 ;;< 0x2e
+ .MajorSubsystemVersion resw 1 ;;< 0x30
+ .MinorSubsystemVersion resw 1 ;;< 0x32
+ .Win32VersionValue resd 1 ;;< 0x34
+ .SizeOfImage resd 1 ;;< 0x38
+ .SizeOfHeaders resd 1 ;;< 0x3c
+ .CheckSum resd 1 ;;< 0x40
+ .Subsystem resw 1 ;;< 0x44
+ .DllCharacteristics resw 1 ;;< 0x46
+ .SizeOfStackReserve resd 1 ;;< 0x48
+ .SizeOfStackCommit resd 1 ;;< 0x4c
+ .SizeOfHeapReserve resd 1 ;;< 0x50
+ .SizeOfHeapCommit resd 1 ;;< 0x54
+ .LoaderFlags resd 1 ;;< 0x58
+ .NumberOfRvaAndSizes resd 1 ;;< 0x5c
+ .DataDirectory resb IMAGE_DATA_DIRECTORY_size * IMAGE_NUMBEROF_DIRECTORY_ENTRIES ;;< 0x60; 0x10*8 = 0x80
+endstruc
+AssertCompileSize(IMAGE_OPTIONAL_HEADER32, 0xe0);
+
+struc IMAGE_OPTIONAL_HEADER64
+ .Magic resw 1 ;;< 0x00
+ .MajorLinkerVersion resb 1 ;;< 0x02
+ .MinorLinkerVersion resb 1 ;;< 0x03
+ .SizeOfCode resd 1 ;;< 0x04
+ .SizeOfInitializedData resd 1 ;;< 0x08
+ .SizeOfUninitializedData resd 1 ;;< 0x0c
+ .AddressOfEntryPoint resd 1 ;;< 0x10
+ .BaseOfCode resd 1 ;;< 0x14
+ .ImageBase resq 1 ;;< 0x18
+ .SectionAlignment resd 1 ;;< 0x20
+ .FileAlignment resd 1 ;;< 0x24
+ .MajorOperatingSystemVersion resw 1 ;;< 0x28
+ .MinorOperatingSystemVersion resw 1 ;;< 0x2a
+ .MajorImageVersion resw 1 ;;< 0x2c
+ .MinorImageVersion resw 1 ;;< 0x2e
+ .MajorSubsystemVersion resw 1 ;;< 0x30
+ .MinorSubsystemVersion resw 1 ;;< 0x32
+ .Win32VersionValue resd 1 ;;< 0x34
+ .SizeOfImage resd 1 ;;< 0x38
+ .SizeOfHeaders resd 1 ;;< 0x3c
+ .CheckSum resd 1 ;;< 0x40
+ .Subsystem resw 1 ;;< 0x44
+ .DllCharacteristics resw 1 ;;< 0x46
+ .SizeOfStackReserve resq 1 ;;< 0x48
+ .SizeOfStackCommit resq 1 ;;< 0x50
+ .SizeOfHeapReserve resq 1 ;;< 0x58
+ .SizeOfHeapCommit resq 1 ;;< 0x60
+ .LoaderFlags resd 1 ;;< 0x68
+ .NumberOfRvaAndSizes resd 1 ;;< 0x6c
+ .DataDirectory resb IMAGE_DATA_DIRECTORY_size * IMAGE_NUMBEROF_DIRECTORY_ENTRIES ;;< 0x70; 0x10*8 = 0x80
+endstruc ; size: 0xf0
+AssertCompileSize(IMAGE_OPTIONAL_HEADER64, 0xf0);
+
+
+struc IMAGE_NT_HEADERS32
+ .Signature resd 1 ;;< 0x00
+ .FileHeader resb IMAGE_FILE_HEADER_size ; ;;< 0x04
+ .OptionalHeader resb IMAGE_OPTIONAL_HEADER32_size ;;< 0x18
+endstruc ; size: 0xf8
+AssertCompileSize(IMAGE_NT_HEADERS32, 0xf8);
+AssertCompileMemberOffset(IMAGE_NT_HEADERS32, FileHeader, 4);
+AssertCompileMemberOffset(IMAGE_NT_HEADERS32, OptionalHeader, 24);
+
+struc IMAGE_NT_HEADERS64
+ .Signature resd 1 ;;< 0x00
+ .FileHeader resb IMAGE_FILE_HEADER_size ;;< 0x04
+ .OptionalHeader resb IMAGE_OPTIONAL_HEADER64_size ;;< 0x18
+endstruc ; size: 0x108
+AssertCompileSize(IMAGE_NT_HEADERS64, 0x108);
+AssertCompileMemberOffset(IMAGE_NT_HEADERS64, FileHeader, 4);
+AssertCompileMemberOffset(IMAGE_NT_HEADERS64, OptionalHeader, 24);
+
+
+struc IMAGE_SECTION_HEADER
+ .Name resb IMAGE_SIZEOF_SHORT_NAME
+ .Misc.VirtualSize resd 1
+ .VirtualAddress resd 1
+ .SizeOfRawData resd 1
+ .PointerToRawData resd 1
+ .PointerToRelocations resd 1
+ .PointerToLinenumbers resd 1
+ .NumberOfRelocations resw 1
+ .NumberOfLinenumbers resw 1
+ .Characteristics resd 1
+endstruc
+%define IMAGE_SECTION_HEADER.Misc.PhysicalAddress IMAGE_SECTION_HEADER.Misc.VirtualSize
+
+
+struc IMAGE_BASE_RELOCATION
+ .VirtualAddress resd 1
+ .SizeOfBlock resd 1
+endstruc
+
+
+struc IMAGE_EXPORT_DIRECTORY
+ .Characteristics resd 1
+ .TimeDateStamp resd 1
+ .MajorVersion resw 1
+ .MinorVersion resw 1
+ .Name resd 1
+ .Base resd 1
+ .NumberOfFunctions resd 1
+ .NumberOfNames resd 1
+ .AddressOfFunctions resd 1
+ .AddressOfNames resd 1
+ .AddressOfNameOrdinals resd 1
+endstruc
+
+
+struc IMAGE_IMPORT_DESCRIPTOR
+ .u.Characteristics resd 1
+ .TimeDateStamp resd 1
+ .ForwarderChain resd 1
+ .Name resd 1
+ .FirstThunk resd 1
+endstruc
+%define IMAGE_IMPORT_DESCRIPTOR.u.OriginalFirstThunk IMAGE_IMPORT_DESCRIPTOR.u.Characteristics
+
+struc IMAGE_IMPORT_BY_NAME
+ .Hint resw 1
+ .Name resb 1
+endstruc
+
+
+struc IMAGE_THUNK_DATA64
+ .u1.ForwarderString resq 1
+endstruc
+%define IMAGE_THUNK_DATA64.u1.Function IMAGE_THUNK_DATA64.u1.ForwarderString
+%define IMAGE_THUNK_DATA64.u1.Ordinal IMAGE_THUNK_DATA64.u1.ForwarderString
+%define IMAGE_THUNK_DATA64.u1.AddressOfData IMAGE_THUNK_DATA64.u1.ForwarderString
+
+struc IMAGE_THUNK_DATA32
+ .u1.ForwarderString resd 1
+endstruc
+%define IMAGE_THUNK_DATA32.u1.Function IMAGE_THUNK_DATA32.u1.ForwarderString
+%define IMAGE_THUNK_DATA32.u1.Ordinal IMAGE_THUNK_DATA32.u1.ForwarderString
+%define IMAGE_THUNK_DATA32.u1.AddressOfData IMAGE_THUNK_DATA32.u1.ForwarderString
+
+
+struc IMAGE_LOAD_CONFIG_DIRECTORY32
+ .Size resd 1
+ .TimeDateStamp resd 1
+ .MajorVersion resw 1
+ .MinorVersion resw 1
+ .GlobalFlagsClear resd 1
+ .GlobalFlagsSet resd 1
+ .CriticalSectionDefaultTimeout resd 1
+ .DeCommitFreeBlockThreshold resd 1
+ .DeCommitTotalFreeThreshold resd 1
+ .LockPrefixTable resd 1
+ .MaximumAllocationSize resd 1
+ .VirtualMemoryThreshold resd 1
+ .ProcessHeapFlags resd 1
+ .ProcessAffinityMask resd 1
+ .CSDVersion resw 1
+ .Reserved1 resw 1
+ .EditList resd 1
+ .SecurityCookie resd 1
+ .SEHandlerTable resd 1
+ .SEHandlerCount resd 1
+endstruc
+
+struc IMAGE_LOAD_CONFIG_DIRECTORY64
+ .Size resd 1
+ .TimeDateStamp resd 1
+ .MajorVersion resw 1
+ .MinorVersion resw 1
+ .GlobalFlagsClear resd 1
+ .GlobalFlagsSet resd 1
+ .CriticalSectionDefaultTimeout resd 1
+ .DeCommitFreeBlockThreshold resq 1
+ .DeCommitTotalFreeThreshold resq 1
+ .LockPrefixTable resq 1
+ .MaximumAllocationSize resq 1
+ .VirtualMemoryThreshold resq 1
+ .ProcessAffinityMask resq 1
+ .ProcessHeapFlags resd 1
+ .CSDVersion resw 1
+ .Reserved1 resw 1
+ .EditList resq 1
+ .SecurityCookie resq 1
+ .SEHandlerTable resq 1
+ .SEHandlerCount resq 1
+endstruc
+
+
+struc IMAGE_DEBUG_DIRECTORY
+ .Characteristics resd 1
+ .TimeDateStamp resd 1
+ .MajorVersion resw 1
+ .MinorVersion resw 1
+ .Type resd 1
+ .SizeOfData resd 1
+ .AddressOfRawData resd 1
+ .PointerToRawData resd 1
+endstruc
+
+struc IMAGE_DEBUG_MISC
+ .DataType resd 1
+ .Length resd 1
+ .Unicode resb 1
+ .Reserved resb 3
+ .Data resb 1
+endstruc
+
+
+struc WIN_CERTIFICATE
+ .dwLength resd 1
+ .wRevision resw 1
+ .wCertificateType resw 1
+ .bCertificate resb 8
+endstruc
+
+;; The header of a .DBG file (NT4).
+struc IMAGE_SEPARATE_DEBUG_HEADER
+ .Signature resw 1 ;;< 0x00
+ .Flags resw 1 ;;< 0x02
+ .Machine resw 1 ;;< 0x04
+ .Characteristics resw 1 ;;< 0x06
+ .TimeDateStamp resd 1 ;;< 0x08
+ .CheckSum resd 1 ;;< 0x0c
+ .ImageBase resd 1 ;;< 0x10
+ .SizeOfImage resd 1 ;;< 0x14
+ .NumberOfSections resd 1 ;;< 0x18
+ .ExportedNamesSize resd 1 ;;< 0x1c
+ .DebugDirectorySize resd 1 ;;< 0x20
+ .SectionAlignment resd 1 ;;< 0x24
+ .Reserved resd 2 ;;< 0x28
+endstruc ; size: 0x30
+AssertCompileSize(IMAGE_SEPARATE_DEBUG_HEADER, 0x30);
+
+
+struc IMAGE_COFF_SYMBOLS_HEADER
+ .NumberOfSymbols resd 1
+ .LvaToFirstSymbol resd 1
+ .NumberOfLinenumbers resd 1
+ .LvaToFirstLinenumber resd 1
+ .RvaToFirstByteOfCode resd 1
+ .RvaToLastByteOfCode resd 1
+ .RvaToFirstByteOfData resd 1
+ .RvaToLastByteOfData resd 1
+endstruc
+AssertCompileSize(IMAGE_COFF_SYMBOLS_HEADER, 0x20);
+
+
+struc IMAGE_LINENUMBER
+ .Type.VirtualAddress resd 1
+ .Linenumber resw 1
+endstruc
+AssertCompileSize(IMAGE_LINENUMBER, 6);
+%define IMAGE_LINENUMBER.Type.SymbolTableIndex IMAGE_LINENUMBER.Type.VirtualAddress
+
+
+;;#pragma pack(2)
+;;struc IMAGE_SYMBOL
+;;{
+;; union
+;; {
+;; uint8_t ShortName[8];
+;; struct
+;; {
+;; .Short resd 1
+;; .Long resd 1
+;; } Name;
+;; uint32_t LongName[2];
+;; } N;
+;;
+;; .Value resd 1
+;; int16_t SectionNumber;
+;; .Type resw 1
+;; .StorageClass resb 1
+;; .NumberOfAuxSymbols resb 1
+;;} IMAGE_SYMBOL;
+;;#pragma pack()
+;;AssertCompileSize(IMAGE_SYMBOL, IMAGE_SIZE_OF_SYMBOL);
+;;
+;;
+;;#pragma pack(2)
+;;typedef struct IMAGE_AUX_SYMBOL_TOKEN_DEF
+;;{
+;; .bAuxType resb 1
+;; .bReserved resb 1
+;; .SymbolTableIndex resd 1
+;; uint8_t rgbReserved[12];
+;;} IMAGE_AUX_SYMBOL_TOKEN_DEF;
+;;#pragma pack()
+;;AssertCompileSize(IMAGE_AUX_SYMBOL_TOKEN_DEF, IMAGE_SIZE_OF_SYMBOL);
+;;
+;;
+;;#pragma pack(1)
+;;typedef union _IMAGE_AUX_SYMBOL
+;;{
+;; struct
+;; {
+;; .TagIndex resd 1
+;; union
+;; {
+;; struct
+;; {
+;; .Linenumber resw 1
+;; .Size resw 1
+;; } LnSz;
+;; } Misc;
+;; union
+;; {
+;; struct
+;; {
+;; .PointerToLinenumber resd 1
+;; .PointerToNextFunction resd 1
+;; } Function;
+;; struct
+;; {
+;; uint16_t Dimension[4];
+;; } Array;
+;; } FcnAry;
+;; .TvIndex resw 1
+;; } Sym;
+;;
+;; struct
+;; {
+;; uint8_t Name[IMAGE_SIZE_OF_SYMBOL];
+;; } File;
+;;
+;; struct
+;; {
+;; .Length resd 1
+;; .NumberOfRelocations resw 1
+;; .NumberOfLinenumbers resw 1
+;; .CheckSum resd 1
+;; .Number resw 1
+;; .Selection resb 1
+;; .bReserved resb 1
+;; .HighNumber resw 1
+;; } Section;
+;;
+;; IMAGE_AUX_SYMBOL_TOKEN_DEF TokenDef;
+;; struct
+;; {
+;; .crc resd 1
+;; uint8_t rgbReserved[14];
+;; } CRC;
+;;} IMAGE_AUX_SYMBOL;
+;;#pragma pack()
+;;AssertCompileSize(IMAGE_AUX_SYMBOL, IMAGE_SIZE_OF_SYMBOL);
+;;
+;;
+;;
+;;struc IMAGE_SYMBOL_EX
+;;{
+;; union
+;; {
+;; uint8_t ShortName[8];
+;; struct
+;; {
+;; .Short resd 1
+;; .Long resd 1
+;; } Name;
+;; uint32_t LongName[2];
+;; } N;
+;;
+;; .Value resd 1
+;; int32_t SectionNumber; /* The difference from IMAGE_SYMBOL
+;; .Type resw 1
+;; .StorageClass resb 1
+;; .NumberOfAuxSymbols resb 1
+;;} IMAGE_SYMBOL_EX;
+;;AssertCompileSize(IMAGE_SYMBOL_EX, IMAGE_SIZE_OF_SYMBOL_EX);
+;;
+;;
+;;typedef union _IMAGE_AUX_SYMBOL_EX
+;;{
+;; struct
+;; {
+;; .WeakDefaultSymIndex resd 1
+;; .WeakSearchType resd 1
+;; uint8_t rgbReserved[12];
+;; } Sym;
+;;
+;; struct
+;; {
+;; uint8_t Name[IMAGE_SIZE_OF_SYMBOL_EX];
+;; } File;
+;;
+;; struct
+;; {
+;; .Length resd 1
+;; .NumberOfRelocations resw 1
+;; .NumberOfLinenumbers resw 1
+;; .CheckSum resd 1
+;; .Number resw 1
+;; .Selection resb 1
+;; .bReserved resb 1
+;; .HighNumber resw 1
+;; uint8_t rgbReserved[2];
+;; } Section;
+;;
+;; IMAGE_AUX_SYMBOL_TOKEN_DEF TokenDef;
+;;
+;; struct
+;; {
+;; .crc resd 1
+;; uint8_t rgbReserved[16];
+;; } CRC;
+;;} IMAGE_AUX_SYMBOL_EX;
+;;AssertCompileSize(IMAGE_AUX_SYMBOL_EX, IMAGE_SIZE_OF_SYMBOL_EX);
+
+%endif
+
diff --git a/include/iprt/formats/pecoff.h b/include/iprt/formats/pecoff.h
new file mode 100644
index 00000000..a705d20a
--- /dev/null
+++ b/include/iprt/formats/pecoff.h
@@ -0,0 +1,2610 @@
+/* $Id: pecoff.h $ */
+/** @file
+ * IPRT - Windows NT PE & COFF Structures and Constants.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_formats_pecoff_h
+#define IPRT_INCLUDED_formats_pecoff_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+#include <iprt/assertcompile.h>
+
+
+/** @defgroup grp_rt_formats_pecoff PE & Microsoft COFF structures and definitions
+ * @ingroup grp_rt_formats
+ * @{
+ */
+
+
+/**
+ * PE & COFF file header.
+ *
+ * This starts COFF files, while in PE files it's preceeded by the PE signature
+ * (see IMAGE_NT_HEADERS32, IMAGE_NT_HEADERS64).
+ */
+typedef struct _IMAGE_FILE_HEADER
+{
+ uint16_t Machine; /**< 0x00 */
+ uint16_t NumberOfSections; /**< 0x02 */
+ uint32_t TimeDateStamp; /**< 0x04 */
+ uint32_t PointerToSymbolTable; /**< 0x08 */
+ uint32_t NumberOfSymbols; /**< 0x0c */
+ uint16_t SizeOfOptionalHeader; /**< 0x10 */
+ uint16_t Characteristics; /**< 0x12 */
+} IMAGE_FILE_HEADER; /* size: 0x14 */
+AssertCompileSize(IMAGE_FILE_HEADER, 0x14);
+typedef IMAGE_FILE_HEADER *PIMAGE_FILE_HEADER;
+typedef IMAGE_FILE_HEADER const *PCIMAGE_FILE_HEADER;
+
+
+/** @name PE & COFF machine types.
+ * Used by IMAGE_FILE_HEADER::Machine and IMAGE_SEPARATE_DEBUG_HEADER::Machine.
+ * @{ */
+/** X86 compatible CPU, 32-bit instructions. */
+#define IMAGE_FILE_MACHINE_I386 UINT16_C(0x014c)
+/** AMD64 compatible CPU, 64-bit instructions. */
+#define IMAGE_FILE_MACHINE_AMD64 UINT16_C(0x8664)
+
+/** Unknown target CPU. */
+#define IMAGE_FILE_MACHINE_UNKNOWN UINT16_C(0x0000)
+/** Basic-16 (whatever that is). */
+#define IMAGE_FILE_MACHINE_BASIC_16 UINT16_C(0x0142)
+/** Basic-16 (whatever that is) w/ transfer vector(s?) (TV). */
+#define IMAGE_FILE_MACHINE_BASIC_16_TV UINT16_C(0x0143)
+/** Intel iAPX 16 (8086?). */
+#define IMAGE_FILE_MACHINE_IAPX16 UINT16_C(0x0144)
+/** Intel iAPX 16 (8086?) w/ transfer vector(s?) (TV). */
+#define IMAGE_FILE_MACHINE_IAPX16_TV UINT16_C(0x0145)
+/** Intel iAPX 20 (80286?). */
+#define IMAGE_FILE_MACHINE_IAPX20 UINT16_C(0x0144)
+/** Intel iAPX 20 (80286?) w/ transfer vector(s?) (TV). */
+#define IMAGE_FILE_MACHINE_IAPX20_TV UINT16_C(0x0145)
+/** X86 compatible CPU, 8086. */
+#define IMAGE_FILE_MACHINE_I8086 UINT16_C(0x0148)
+/** X86 compatible CPU, 8086 w/ transfer vector(s?) (TV). */
+#define IMAGE_FILE_MACHINE_I8086_TV UINT16_C(0x0149)
+/** X86 compatible CPU, 80286 small model program. */
+#define IMAGE_FILE_MACHINE_I286_SMALL UINT16_C(0x014a)
+/** Motorola 68000. */
+#define IMAGE_FILE_MACHINE_MC68 UINT16_C(0x0150)
+/** Motorola 68000 w/ writable text sections. */
+#define IMAGE_FILE_MACHINE_MC68_WR UINT16_C(0x0150)
+/** Motorola 68000 w/ transfer vector(s?). */
+#define IMAGE_FILE_MACHINE_MC68_TV UINT16_C(0x0151)
+/** Motorola 68000 w/ demand paged text.
+ * @note shared with 80286 large model program. */
+#define IMAGE_FILE_MACHINE_MC68_PG UINT16_C(0x0152)
+/** X86 compatible CPU, 80286 large model program.
+ * @note shared with MC68000 w/ demand paged text */
+#define IMAGE_FILE_MACHINE_I286_LARGE UINT16_C(0x0152)
+/** IBM 370 (writable text). */
+#define IMAGE_FILE_MACHINE_U370_WR UINT16_C(0x0158)
+/** Amdahl 470/580 (writable text). */
+#define IMAGE_FILE_MACHINE_AMDAHL_470_WR UINT16_C(0x0159)
+/** Amdahl 470/580 (read only text). */
+#define IMAGE_FILE_MACHINE_AMDAHL_470_RO UINT16_C(0x015c)
+/** IBM 370 (read only text). */
+#define IMAGE_FILE_MACHINE_U370_RO UINT16_C(0x015d)
+/** MIPS R4000 CPU, little endian. */
+#define IMAGE_FILE_MACHINE_R4000 UINT16_C(0x0166)
+/** MIPS CPU, little endian, Windows CE (?) v2 designation. */
+#define IMAGE_FILE_MACHINE_WCEMIPSV2 UINT16_C(0x0169)
+/** VAX-11/750 and VAX-11/780 (writable text). */
+#define IMAGE_FILE_MACHINE_VAX_WR UINT16_C(0x0178)
+/** VAX-11/750 and VAX-11/780 (read-only text). */
+#define IMAGE_FILE_MACHINE_VAX_RO UINT16_C(0x017d)
+/** Hitachi SH3 CPU. */
+#define IMAGE_FILE_MACHINE_SH3 UINT16_C(0x01a2)
+/** Hitachi SH3 DSP. */
+#define IMAGE_FILE_MACHINE_SH3DSP UINT16_C(0x01a3)
+/** Hitachi SH4 CPU. */
+#define IMAGE_FILE_MACHINE_SH4 UINT16_C(0x01a6)
+/** Hitachi SH5 CPU. */
+#define IMAGE_FILE_MACHINE_SH5 UINT16_C(0x01a8)
+/** Little endian ARM CPU. */
+#define IMAGE_FILE_MACHINE_ARM UINT16_C(0x01c0)
+/** ARM or Thumb stuff. */
+#define IMAGE_FILE_MACHINE_THUMB UINT16_C(0x01c2)
+/** ARMv7 or higher CPU, Thumb mode. */
+#define IMAGE_FILE_MACHINE_ARMNT UINT16_C(0x01c4)
+/** Matshushita AM33 CPU. */
+#define IMAGE_FILE_MACHINE_AM33 UINT16_C(0x01d3)
+/** Power PC CPU, little endian. */
+#define IMAGE_FILE_MACHINE_POWERPC UINT16_C(0x01f0)
+/** Power PC CPU with FPU, also little endian? */
+#define IMAGE_FILE_MACHINE_POWERPCFP UINT16_C(0x01f1)
+/** "Itanic" CPU. */
+#define IMAGE_FILE_MACHINE_IA64 UINT16_C(0x0200)
+/** MIPS CPU, compact 16-bit instructions only? */
+#define IMAGE_FILE_MACHINE_MIPS16 UINT16_C(0x0266)
+/** MIPS CPU with FPU, full 32-bit instructions only? */
+#define IMAGE_FILE_MACHINE_MIPSFPU UINT16_C(0x0366)
+/** MIPS CPU with FPU, compact 16-bit instructions? */
+#define IMAGE_FILE_MACHINE_MIPSFPU16 UINT16_C(0x0466)
+/** EFI byte code. */
+#define IMAGE_FILE_MACHINE_EBC UINT16_C(0x0ebc)
+/** Mitsubishi M32R CPU, little endian. */
+#define IMAGE_FILE_MACHINE_M32R UINT16_C(0x9041)
+/** ARMv8 CPU, 64-bit mode. */
+#define IMAGE_FILE_MACHINE_ARM64 UINT16_C(0xaa64)
+/** @} */
+
+/** @name File header characteristics (IMAGE_FILE_HEADER::Characteristics)
+ * @{ */
+#define IMAGE_FILE_RELOCS_STRIPPED UINT16_C(0x0001)
+#define IMAGE_FILE_EXECUTABLE_IMAGE UINT16_C(0x0002)
+#define IMAGE_FILE_LINE_NUMS_STRIPPED UINT16_C(0x0004)
+#define IMAGE_FILE_LOCAL_SYMS_STRIPPED UINT16_C(0x0008)
+#define IMAGE_FILE_AGGRESIVE_WS_TRIM UINT16_C(0x0010)
+#define IMAGE_FILE_LARGE_ADDRESS_AWARE UINT16_C(0x0020)
+#define IMAGE_FILE_16BIT_MACHINE UINT16_C(0x0040)
+#define IMAGE_FILE_BYTES_REVERSED_LO UINT16_C(0x0080)
+#define IMAGE_FILE_32BIT_MACHINE UINT16_C(0x0100)
+#define IMAGE_FILE_DEBUG_STRIPPED UINT16_C(0x0200)
+#define IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP UINT16_C(0x0400)
+#define IMAGE_FILE_NET_RUN_FROM_SWAP UINT16_C(0x0800)
+#define IMAGE_FILE_SYSTEM UINT16_C(0x1000) /**< (COFF/IAPX*: Used to indicate 80186 instructions) */
+#define IMAGE_FILE_DLL UINT16_C(0x2000) /**< (COFF/IAPX*: Used to indicate 80286 instructions) */
+#define IMAGE_FILE_UP_SYSTEM_ONLY UINT16_C(0x4000)
+#define IMAGE_FILE_BYTES_REVERSED_HI UINT16_C(0x8000)
+/** @} */
+
+
+/**
+ * PE data directory.
+ *
+ * This is used to locate data in the loaded image so the dynamic linker or
+ * others can make use of it. However, in the case of
+ * IMAGE_DIRECTORY_ENTRY_SECURITY it is referring to raw file offsets.
+ */
+typedef struct _IMAGE_DATA_DIRECTORY
+{
+ uint32_t VirtualAddress;
+ uint32_t Size;
+} IMAGE_DATA_DIRECTORY;
+AssertCompileSize(IMAGE_DATA_DIRECTORY, 0x8);
+typedef IMAGE_DATA_DIRECTORY *PIMAGE_DATA_DIRECTORY;
+typedef IMAGE_DATA_DIRECTORY const *PCIMAGE_DATA_DIRECTORY;
+
+/** The standard number of data directories in the optional header.
+ * I.e. the dimensions of IMAGE_OPTIONAL_HEADER32::DataDirectory and
+ * IMAGE_OPTIONAL_HEADER64::DataDirectory.
+ */
+#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 0x10
+
+
+/**
+ * PE optional header, 32-bit version.
+ */
+typedef struct _IMAGE_OPTIONAL_HEADER32
+{
+ uint16_t Magic; /**< 0x00 */
+ uint8_t MajorLinkerVersion; /**< 0x02 */
+ uint8_t MinorLinkerVersion; /**< 0x03 */
+ uint32_t SizeOfCode; /**< 0x04 */
+ uint32_t SizeOfInitializedData; /**< 0x08 */
+ uint32_t SizeOfUninitializedData; /**< 0x0c */
+ uint32_t AddressOfEntryPoint; /**< 0x10 */
+ uint32_t BaseOfCode; /**< 0x14 */
+ uint32_t BaseOfData; /**< 0x18 */
+ uint32_t ImageBase; /**< 0x1c */
+ uint32_t SectionAlignment; /**< 0x20 */
+ uint32_t FileAlignment; /**< 0x24 */
+ uint16_t MajorOperatingSystemVersion; /**< 0x28 */
+ uint16_t MinorOperatingSystemVersion; /**< 0x2a */
+ uint16_t MajorImageVersion; /**< 0x2c */
+ uint16_t MinorImageVersion; /**< 0x2e */
+ uint16_t MajorSubsystemVersion; /**< 0x30 */
+ uint16_t MinorSubsystemVersion; /**< 0x32 */
+ uint32_t Win32VersionValue; /**< 0x34 */
+ uint32_t SizeOfImage; /**< 0x38 */
+ uint32_t SizeOfHeaders; /**< 0x3c */
+ uint32_t CheckSum; /**< 0x40 */
+ uint16_t Subsystem; /**< 0x44 */
+ uint16_t DllCharacteristics; /**< 0x46 */
+ uint32_t SizeOfStackReserve; /**< 0x48 */
+ uint32_t SizeOfStackCommit; /**< 0x4c */
+ uint32_t SizeOfHeapReserve; /**< 0x50 */
+ uint32_t SizeOfHeapCommit; /**< 0x54 */
+ uint32_t LoaderFlags; /**< 0x58 */
+ uint32_t NumberOfRvaAndSizes; /**< 0x5c */
+ IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; /**< 0x60; 0x10*8 = 0x80 */
+} IMAGE_OPTIONAL_HEADER32; /* size: 0xe0 */
+AssertCompileSize(IMAGE_OPTIONAL_HEADER32, 0xe0);
+typedef IMAGE_OPTIONAL_HEADER32 *PIMAGE_OPTIONAL_HEADER32;
+typedef IMAGE_OPTIONAL_HEADER32 const *PCIMAGE_OPTIONAL_HEADER32;
+
+/**
+ * PE optional header, 64-bit version.
+ */
+typedef struct _IMAGE_OPTIONAL_HEADER64
+{
+ uint16_t Magic; /**< 0x00 */
+ uint8_t MajorLinkerVersion; /**< 0x02 */
+ uint8_t MinorLinkerVersion; /**< 0x03 */
+ uint32_t SizeOfCode; /**< 0x04 */
+ uint32_t SizeOfInitializedData; /**< 0x08 */
+ uint32_t SizeOfUninitializedData; /**< 0x0c */
+ uint32_t AddressOfEntryPoint; /**< 0x10 */
+ uint32_t BaseOfCode; /**< 0x14 */
+ uint64_t ImageBase; /**< 0x18 */
+ uint32_t SectionAlignment; /**< 0x20 */
+ uint32_t FileAlignment; /**< 0x24 */
+ uint16_t MajorOperatingSystemVersion; /**< 0x28 */
+ uint16_t MinorOperatingSystemVersion; /**< 0x2a */
+ uint16_t MajorImageVersion; /**< 0x2c */
+ uint16_t MinorImageVersion; /**< 0x2e */
+ uint16_t MajorSubsystemVersion; /**< 0x30 */
+ uint16_t MinorSubsystemVersion; /**< 0x32 */
+ uint32_t Win32VersionValue; /**< 0x34 */
+ uint32_t SizeOfImage; /**< 0x38 */
+ uint32_t SizeOfHeaders; /**< 0x3c */
+ uint32_t CheckSum; /**< 0x40 */
+ uint16_t Subsystem; /**< 0x44 */
+ uint16_t DllCharacteristics; /**< 0x46 */
+ uint64_t SizeOfStackReserve; /**< 0x48 */
+ uint64_t SizeOfStackCommit; /**< 0x50 */
+ uint64_t SizeOfHeapReserve; /**< 0x58 */
+ uint64_t SizeOfHeapCommit; /**< 0x60 */
+ uint32_t LoaderFlags; /**< 0x68 */
+ uint32_t NumberOfRvaAndSizes; /**< 0x6c */
+ IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; /**< 0x70; 0x10*8 = 0x80 */
+} IMAGE_OPTIONAL_HEADER64; /* size: 0xf0 */
+AssertCompileSize(IMAGE_OPTIONAL_HEADER64, 0xf0);
+typedef IMAGE_OPTIONAL_HEADER64 *PIMAGE_OPTIONAL_HEADER64;
+typedef IMAGE_OPTIONAL_HEADER64 const *PCIMAGE_OPTIONAL_HEADER64;
+
+/** @name Optional header magic values.
+ * @{ */
+#define IMAGE_NT_OPTIONAL_HDR32_MAGIC UINT16_C(0x010b)
+#define IMAGE_NT_OPTIONAL_HDR64_MAGIC UINT16_C(0x020b)
+/** @} */
+
+/** @name IMAGE_SUBSYSTEM_XXX - Optional header subsystems.
+ * IMAGE_OPTIONAL_HEADER32::Subsystem, IMAGE_OPTIONAL_HEADER64::Subsystem
+ * @{ */
+#define IMAGE_SUBSYSTEM_UNKNOWN UINT16_C(0x0000)
+#define IMAGE_SUBSYSTEM_NATIVE UINT16_C(0x0001)
+#define IMAGE_SUBSYSTEM_WINDOWS_GUI UINT16_C(0x0002)
+#define IMAGE_SUBSYSTEM_WINDOWS_CUI UINT16_C(0x0003)
+#define IMAGE_SUBSYSTEM_OS2_GUI UINT16_C(0x0004)
+#define IMAGE_SUBSYSTEM_OS2_CUI UINT16_C(0x0005)
+#define IMAGE_SUBSYSTEM_POSIX_CUI UINT16_C(0x0007)
+/** @} */
+
+/** @name Optional header characteristics.
+ * @{ */
+#define IMAGE_LIBRARY_PROCESS_INIT UINT16_C(0x0001)
+#define IMAGE_LIBRARY_PROCESS_TERM UINT16_C(0x0002)
+#define IMAGE_LIBRARY_THREAD_INIT UINT16_C(0x0004)
+#define IMAGE_LIBRARY_THREAD_TERM UINT16_C(0x0008)
+#define IMAGE_DLLCHARACTERISTICS_RESERVED UINT16_C(0x0010)
+#define IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA UINT16_C(0x0020)
+#define IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE UINT16_C(0x0040)
+#define IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY UINT16_C(0x0080)
+#define IMAGE_DLLCHARACTERISTICS_NX_COMPAT UINT16_C(0x0100)
+#define IMAGE_DLLCHARACTERISTICS_NO_ISOLATION UINT16_C(0x0200)
+#define IMAGE_DLLCHARACTERISTICS_NO_SEH UINT16_C(0x0400)
+#define IMAGE_DLLCHARACTERISTICS_NO_BIND UINT16_C(0x0800)
+#define IMAGE_DLLCHARACTERISTICS_APPCONTAINER UINT16_C(0x1000)
+#define IMAGE_DLLCHARACTERISTICS_WDM_DRIVER UINT16_C(0x2000)
+#define IMAGE_DLLCHARACTERISTICS_GUARD_CF UINT16_C(0x4000)
+#define IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE UINT16_C(0x8000)
+/** @} */
+
+
+/** @name IMAGE_DIRECTORY_ENTRY_XXX - Data directory indexes.
+ * Used to index IMAGE_OPTIONAL_HEADER32::DataDirectory and
+ * IMAGE_OPTIONAL_HEADER64::DataDirectory
+ * @{ */
+#define IMAGE_DIRECTORY_ENTRY_EXPORT 0x0
+#define IMAGE_DIRECTORY_ENTRY_IMPORT 0x1
+#define IMAGE_DIRECTORY_ENTRY_RESOURCE 0x2
+#define IMAGE_DIRECTORY_ENTRY_EXCEPTION 0x3
+#define IMAGE_DIRECTORY_ENTRY_SECURITY 0x4
+#define IMAGE_DIRECTORY_ENTRY_BASERELOC 0x5
+#define IMAGE_DIRECTORY_ENTRY_DEBUG 0x6
+#define IMAGE_DIRECTORY_ENTRY_ARCHITECTURE 0x7
+#define IMAGE_DIRECTORY_ENTRY_COPYRIGHT IMAGE_DIRECTORY_ENTRY_ARCHITECTURE
+#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR 0x8
+#define IMAGE_DIRECTORY_ENTRY_TLS 0x9
+#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 0xa
+#define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT 0xb
+#define IMAGE_DIRECTORY_ENTRY_IAT 0xc
+#define IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT 0xd
+#define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 0xe
+/** @} */
+
+
+/**
+ * PE (NT) headers, 32-bit version.
+ */
+typedef struct _IMAGE_NT_HEADERS32
+{
+ uint32_t Signature; /**< 0x00 */
+ IMAGE_FILE_HEADER FileHeader; /**< 0x04 */
+ IMAGE_OPTIONAL_HEADER32 OptionalHeader; /**< 0x18 */
+} IMAGE_NT_HEADERS32; /* size: 0xf8 */
+AssertCompileSize(IMAGE_NT_HEADERS32, 0xf8);
+AssertCompileMemberOffset(IMAGE_NT_HEADERS32, FileHeader, 4);
+AssertCompileMemberOffset(IMAGE_NT_HEADERS32, OptionalHeader, 24);
+typedef IMAGE_NT_HEADERS32 *PIMAGE_NT_HEADERS32;
+typedef IMAGE_NT_HEADERS32 const *PCIMAGE_NT_HEADERS32;
+
+/**
+ * PE (NT) headers, 64-bit version.
+ */
+typedef struct _IMAGE_NT_HEADERS64
+{
+ uint32_t Signature; /**< 0x00 */
+ IMAGE_FILE_HEADER FileHeader; /**< 0x04 */
+ IMAGE_OPTIONAL_HEADER64 OptionalHeader; /**< 0x18 */
+} IMAGE_NT_HEADERS64; /**< 0x108 */
+AssertCompileSize(IMAGE_NT_HEADERS64, 0x108);
+AssertCompileMemberOffset(IMAGE_NT_HEADERS64, FileHeader, 4);
+AssertCompileMemberOffset(IMAGE_NT_HEADERS64, OptionalHeader, 24);
+typedef IMAGE_NT_HEADERS64 *PIMAGE_NT_HEADERS64;
+typedef IMAGE_NT_HEADERS64 const *PCIMAGE_NT_HEADERS64;
+
+/** The PE signature.
+ * Used by IMAGE_NT_HEADERS32::Signature, IMAGE_NT_HEADERS64::Signature. */
+#define IMAGE_NT_SIGNATURE UINT32_C(0x00004550)
+
+
+/** Section header short name length (IMAGE_SECTION_HEADER::Name). */
+#define IMAGE_SIZEOF_SHORT_NAME 0x8
+
+/**
+ * PE & COFF section header.
+ */
+typedef struct _IMAGE_SECTION_HEADER
+{
+ uint8_t Name[IMAGE_SIZEOF_SHORT_NAME];
+ union
+ {
+ uint32_t PhysicalAddress;
+ uint32_t VirtualSize;
+ } Misc;
+ uint32_t VirtualAddress;
+ uint32_t SizeOfRawData;
+ uint32_t PointerToRawData;
+ uint32_t PointerToRelocations;
+ uint32_t PointerToLinenumbers;
+ uint16_t NumberOfRelocations;
+ uint16_t NumberOfLinenumbers;
+ uint32_t Characteristics;
+} IMAGE_SECTION_HEADER;
+AssertCompileSize(IMAGE_SECTION_HEADER, 40);
+typedef IMAGE_SECTION_HEADER *PIMAGE_SECTION_HEADER;
+typedef IMAGE_SECTION_HEADER const *PCIMAGE_SECTION_HEADER;
+
+/** @name IMAGE_SCN_XXX - Section header characteristics.
+ * Used by IMAGE_SECTION_HEADER::Characteristics.
+ * @{ */
+#define IMAGE_SCN_TYPE_REG UINT32_C(0x00000000)
+#define IMAGE_SCN_TYPE_DSECT UINT32_C(0x00000001)
+#define IMAGE_SCN_TYPE_NOLOAD UINT32_C(0x00000002)
+#define IMAGE_SCN_TYPE_GROUP UINT32_C(0x00000004)
+#define IMAGE_SCN_TYPE_NO_PAD UINT32_C(0x00000008)
+#define IMAGE_SCN_TYPE_COPY UINT32_C(0x00000010)
+
+#define IMAGE_SCN_CNT_CODE UINT32_C(0x00000020)
+#define IMAGE_SCN_CNT_INITIALIZED_DATA UINT32_C(0x00000040)
+#define IMAGE_SCN_CNT_UNINITIALIZED_DATA UINT32_C(0x00000080)
+
+#define IMAGE_SCN_LNK_OTHER UINT32_C(0x00000100)
+#define IMAGE_SCN_LNK_INFO UINT32_C(0x00000200)
+#define IMAGE_SCN_TYPE_OVER UINT32_C(0x00000400)
+#define IMAGE_SCN_LNK_REMOVE UINT32_C(0x00000800)
+#define IMAGE_SCN_LNK_COMDAT UINT32_C(0x00001000)
+#define IMAGE_SCN_MEM_PROTECTED UINT32_C(0x00004000)
+#define IMAGE_SCN_NO_DEFER_SPEC_EXC UINT32_C(0x00004000)
+#define IMAGE_SCN_GPREL UINT32_C(0x00008000)
+#define IMAGE_SCN_MEM_FARDATA UINT32_C(0x00008000)
+#define IMAGE_SCN_MEM_SYSHEAP UINT32_C(0x00010000)
+#define IMAGE_SCN_MEM_PURGEABLE UINT32_C(0x00020000)
+#define IMAGE_SCN_MEM_16BIT UINT32_C(0x00020000)
+#define IMAGE_SCN_MEM_LOCKED UINT32_C(0x00040000)
+#define IMAGE_SCN_MEM_PRELOAD UINT32_C(0x00080000)
+
+#define IMAGE_SCN_ALIGN_1BYTES UINT32_C(0x00100000)
+#define IMAGE_SCN_ALIGN_2BYTES UINT32_C(0x00200000)
+#define IMAGE_SCN_ALIGN_4BYTES UINT32_C(0x00300000)
+#define IMAGE_SCN_ALIGN_8BYTES UINT32_C(0x00400000)
+#define IMAGE_SCN_ALIGN_16BYTES UINT32_C(0x00500000)
+#define IMAGE_SCN_ALIGN_32BYTES UINT32_C(0x00600000)
+#define IMAGE_SCN_ALIGN_64BYTES UINT32_C(0x00700000)
+#define IMAGE_SCN_ALIGN_128BYTES UINT32_C(0x00800000)
+#define IMAGE_SCN_ALIGN_256BYTES UINT32_C(0x00900000)
+#define IMAGE_SCN_ALIGN_512BYTES UINT32_C(0x00A00000)
+#define IMAGE_SCN_ALIGN_1024BYTES UINT32_C(0x00B00000)
+#define IMAGE_SCN_ALIGN_2048BYTES UINT32_C(0x00C00000)
+#define IMAGE_SCN_ALIGN_4096BYTES UINT32_C(0x00D00000)
+#define IMAGE_SCN_ALIGN_8192BYTES UINT32_C(0x00E00000)
+#define IMAGE_SCN_ALIGN_MASK UINT32_C(0x00F00000)
+#define IMAGE_SCN_ALIGN_SHIFT 20
+
+#define IMAGE_SCN_LNK_NRELOC_OVFL UINT32_C(0x01000000)
+#define IMAGE_SCN_MEM_DISCARDABLE UINT32_C(0x02000000)
+#define IMAGE_SCN_MEM_NOT_CACHED UINT32_C(0x04000000)
+#define IMAGE_SCN_MEM_NOT_PAGED UINT32_C(0x08000000)
+#define IMAGE_SCN_MEM_SHARED UINT32_C(0x10000000)
+#define IMAGE_SCN_MEM_EXECUTE UINT32_C(0x20000000)
+#define IMAGE_SCN_MEM_READ UINT32_C(0x40000000)
+#define IMAGE_SCN_MEM_WRITE UINT32_C(0x80000000)
+/** @} */
+
+
+/**
+ * PE image base relocations block header.
+ *
+ * This found in IMAGE_DIRECTORY_ENTRY_BASERELOC. Each entry is follow
+ * immediately by an array of 16-bit words, where the lower 12-bits are used
+ * for the page offset and the upper 4-bits for the base relocation type
+ * (IMAGE_REL_BASE_XXX). The block should be padded with
+ * IMAGE_REL_BASED_ABSOLUTE entries to ensure 32-bit alignment of this header.
+ */
+typedef struct _IMAGE_BASE_RELOCATION
+{
+ /** The RVA of the page/block the following ase relocations applies to. */
+ uint32_t VirtualAddress;
+ /** The size of this relocation block, including this header. */
+ uint32_t SizeOfBlock;
+} IMAGE_BASE_RELOCATION;
+AssertCompileSize(IMAGE_BASE_RELOCATION, 8);
+typedef IMAGE_BASE_RELOCATION *PIMAGE_BASE_RELOCATION;
+typedef IMAGE_BASE_RELOCATION const *PCIMAGE_BASE_RELOCATION;
+
+/** @name IMAGE_REL_BASED_XXX - PE base relocations.
+ * Found in the IMAGE_DIRECTORY_ENTRY_BASERELOC data directory.
+ * @{ */
+#define IMAGE_REL_BASED_ABSOLUTE UINT16_C(0x0)
+#define IMAGE_REL_BASED_HIGH UINT16_C(0x1)
+#define IMAGE_REL_BASED_LOW UINT16_C(0x2)
+#define IMAGE_REL_BASED_HIGHLOW UINT16_C(0x3)
+#define IMAGE_REL_BASED_HIGHADJ UINT16_C(0x4)
+#define IMAGE_REL_BASED_MIPS_JMPADDR UINT16_C(0x5)
+#define IMAGE_REL_BASED_MIPS_JMPADDR16 UINT16_C(0x9)
+#define IMAGE_REL_BASED_IA64_IMM64 UINT16_C(0x9)
+#define IMAGE_REL_BASED_DIR64 UINT16_C(0xa)
+#define IMAGE_REL_BASED_HIGH3ADJ UINT16_C(0xb)
+/** @} */
+
+/**
+ * PE export directory entry.
+ */
+typedef struct _IMAGE_EXPORT_DIRECTORY
+{
+ uint32_t Characteristics;
+ uint32_t TimeDateStamp;
+ uint16_t MajorVersion;
+ uint16_t MinorVersion;
+ uint32_t Name;
+ uint32_t Base;
+ uint32_t NumberOfFunctions;
+ uint32_t NumberOfNames;
+ uint32_t AddressOfFunctions;
+ uint32_t AddressOfNames;
+ uint32_t AddressOfNameOrdinals;
+} IMAGE_EXPORT_DIRECTORY;
+AssertCompileSize(IMAGE_EXPORT_DIRECTORY, 40);
+typedef IMAGE_EXPORT_DIRECTORY *PIMAGE_EXPORT_DIRECTORY;
+typedef IMAGE_EXPORT_DIRECTORY const *PCIMAGE_EXPORT_DIRECTORY;
+
+
+/**
+ * PE import directory entry.
+ */
+typedef struct _IMAGE_IMPORT_DESCRIPTOR
+{
+ union
+ {
+ uint32_t Characteristics;
+ uint32_t OriginalFirstThunk;
+ } u;
+ uint32_t TimeDateStamp;
+ uint32_t ForwarderChain;
+ uint32_t Name;
+ uint32_t FirstThunk;
+} IMAGE_IMPORT_DESCRIPTOR;
+AssertCompileSize(IMAGE_IMPORT_DESCRIPTOR, 20);
+typedef IMAGE_IMPORT_DESCRIPTOR *PIMAGE_IMPORT_DESCRIPTOR;
+typedef IMAGE_IMPORT_DESCRIPTOR const *PCIMAGE_IMPORT_DESCRIPTOR;
+
+/**
+ * Something we currently don't make use of...
+ */
+typedef struct _IMAGE_IMPORT_BY_NAME
+{
+ uint16_t Hint;
+ uint8_t Name[1];
+} IMAGE_IMPORT_BY_NAME;
+AssertCompileSize(IMAGE_IMPORT_BY_NAME, 4);
+typedef IMAGE_IMPORT_BY_NAME *PIMAGE_IMPORT_BY_NAME;
+typedef IMAGE_IMPORT_BY_NAME const *PCIMAGE_IMPORT_BY_NAME;
+
+
+#if 0
+/* The image_thunk_data32/64 structures are not very helpful except for getting RSI.
+ keep them around till all the code has been converted. */
+typedef struct _IMAGE_THUNK_DATA64
+{
+ union
+ {
+ uint64_t ForwarderString;
+ uint64_t Function;
+ uint64_t Ordinal;
+ uint64_t AddressOfData;
+ } u1;
+} IMAGE_THUNK_DATA64;
+typedef IMAGE_THUNK_DATA64 *PIMAGE_THUNK_DATA64;
+typedef IMAGE_THUNK_DATA64 const *PCIMAGE_THUNK_DATA64;
+
+typedef struct _IMAGE_THUNK_DATA32
+{
+ union
+ {
+ uint32_t ForwarderString;
+ uint32_t Function;
+ uint32_t Ordinal;
+ uint32_t AddressOfData;
+ } u1;
+} IMAGE_THUNK_DATA32;
+typedef IMAGE_THUNK_DATA32 *PIMAGE_THUNK_DATA32;
+typedef IMAGE_THUNK_DATA32 const *PCIMAGE_THUNK_DATA32;
+#endif
+
+/** @name PE import directory macros.
+ * @{ */
+#define IMAGE_ORDINAL_FLAG32 UINT32_C(0x80000000)
+#define IMAGE_ORDINAL32(ord) ((ord) & UINT32_C(0xffff))
+#define IMAGE_SNAP_BY_ORDINAL32(ord) (!!((ord) & IMAGE_ORDINAL_FLAG32))
+
+#define IMAGE_ORDINAL_FLAG64 UINT64_C(0x8000000000000000)
+#define IMAGE_ORDINAL64(ord) ((ord) & UINT32_C(0xffff))
+#define IMAGE_SNAP_BY_ORDINAL64(ord) (!!((ord) & IMAGE_ORDINAL_FLAG64))
+/** @} */
+
+/** @name PE Resource directory
+ * @{ */
+typedef struct _IMAGE_RESOURCE_DIRECTORY
+{
+ uint32_t Characteristics;
+ uint32_t TimeDateStamp;
+ uint16_t MajorVersion;
+ uint16_t MinorVersion;
+ uint16_t NumberOfNamedEntries;
+ uint16_t NumberOfIdEntries;
+} IMAGE_RESOURCE_DIRECTORY;
+typedef IMAGE_RESOURCE_DIRECTORY *PIMAGE_RESOURCE_DIRECTORY;
+typedef IMAGE_RESOURCE_DIRECTORY const *PCIMAGE_RESOURCE_DIRECTORY;
+
+typedef struct _IMAGE_RESOURCE_DIRECTORY_ENTRY
+{
+ union
+ {
+ struct
+ {
+ uint32_t NameOffset : 31;
+ uint32_t NameIsString : 1; /**< IMAGE_RESOURCE_NAME_IS_STRING */
+ } s;
+ uint32_t Name;
+ uint16_t Id;
+ } u;
+ union
+ {
+ struct
+ {
+ uint32_t OffsetToDirectory : 31;
+ uint32_t DataIsDirectory : 1; /**< IMAGE_RESOURCE_DATA_IS_DIRECTORY*/
+ } s2;
+ uint32_t OffsetToData;
+ } u2;
+} IMAGE_RESOURCE_DIRECTORY_ENTRY;
+typedef IMAGE_RESOURCE_DIRECTORY_ENTRY *PIMAGE_RESOURCE_DIRECTORY_ENTRY;
+typedef IMAGE_RESOURCE_DIRECTORY_ENTRY const *PCIMAGE_RESOURCE_DIRECTORY_ENTRY;
+
+#define IMAGE_RESOURCE_NAME_IS_STRING UINT32_C(0x80000000)
+#define IMAGE_RESOURCE_DATA_IS_DIRECTORY UINT32_C(0x80000000)
+
+typedef struct _IMAGE_RESOURCE_DIRECTORY_STRING
+{
+ uint16_t Length;
+ char NameString[1];
+} IMAGE_RESOURCE_DIRECTORY_STRING;
+typedef IMAGE_RESOURCE_DIRECTORY_STRING *PIMAGE_RESOURCE_DIRECTORY_STRING;
+typedef IMAGE_RESOURCE_DIRECTORY_STRING const *PCIMAGE_RESOURCE_DIRECTORY_STRING;
+
+
+typedef struct _IMAGE_RESOURCE_DIR_STRING_U
+{
+ uint16_t Length;
+ RTUTF16 NameString[1];
+} IMAGE_RESOURCE_DIR_STRING_U;
+typedef IMAGE_RESOURCE_DIR_STRING_U *PIMAGE_RESOURCE_DIR_STRING_U;
+typedef IMAGE_RESOURCE_DIR_STRING_U const *PCIMAGE_RESOURCE_DIR_STRING_U;
+
+
+typedef struct _IMAGE_RESOURCE_DATA_ENTRY
+{
+ uint32_t OffsetToData;
+ uint32_t Size;
+ uint32_t CodePage;
+ uint32_t Reserved;
+} IMAGE_RESOURCE_DATA_ENTRY;
+typedef IMAGE_RESOURCE_DATA_ENTRY *PIMAGE_RESOURCE_DATA_ENTRY;
+typedef IMAGE_RESOURCE_DATA_ENTRY const *PCIMAGE_RESOURCE_DATA_ENTRY;
+
+/** @} */
+
+/** @name Image exception information
+ * @{ */
+
+/** This structure is used by AMD64 and "Itanic".
+ * MIPS uses a different one. ARM, SH3, SH4 and PPC on WinCE also uses a different one. */
+typedef struct _IMAGE_RUNTIME_FUNCTION_ENTRY
+{
+ uint32_t BeginAddress;
+ uint32_t EndAddress;
+ uint32_t UnwindInfoAddress;
+} IMAGE_RUNTIME_FUNCTION_ENTRY;
+AssertCompileSize(IMAGE_RUNTIME_FUNCTION_ENTRY, 12);
+typedef IMAGE_RUNTIME_FUNCTION_ENTRY *PIMAGE_RUNTIME_FUNCTION_ENTRY;
+typedef IMAGE_RUNTIME_FUNCTION_ENTRY const *PCIMAGE_RUNTIME_FUNCTION_ENTRY;
+
+/**
+ * An unwind code for AMD64 and ARM64.
+ *
+ * @note Also known as UNWIND_CODE or _UNWIND_CODE.
+ */
+typedef union IMAGE_UNWIND_CODE
+{
+ struct
+ {
+ /** The prolog offset where the change takes effect.
+ * This means the instruction following the one being described. */
+ uint8_t CodeOffset;
+ /** Unwind opcode.
+ * For AMD64 see IMAGE_AMD64_UNWIND_OP_CODES. */
+ RT_GCC_EXTENSION uint8_t UnwindOp : 4;
+ /** Opcode specific. */
+ RT_GCC_EXTENSION uint8_t OpInfo : 4;
+ } u;
+ uint16_t FrameOffset;
+} IMAGE_UNWIND_CODE;
+AssertCompileSize(IMAGE_UNWIND_CODE, 2);
+
+/**
+ * Unwind information for AMD64 and ARM64.
+ *
+ * Pointed to by IMAGE_RUNTIME_FUNCTION_ENTRY::UnwindInfoAddress,
+ *
+ * @note Also known as UNWIND_INFO or _UNWIND_INFO.
+ */
+typedef struct IMAGE_UNWIND_INFO
+{
+ /** Version, currently 1 or 2. The latter if IMAGE_AMD64_UWOP_EPILOG is used. */
+ RT_GCC_EXTENSION uint8_t Version : 3;
+ /** IMAGE_UNW_FLAG_XXX */
+ RT_GCC_EXTENSION uint8_t Flags : 5;
+ /** Size of function prolog. */
+ uint8_t SizeOfProlog;
+ /** Number of opcodes in aOpcodes. */
+ uint8_t CountOfCodes;
+ /** Initial frame register. */
+ RT_GCC_EXTENSION uint8_t FrameRegister : 4;
+ /** Scaled frame register offset. */
+ RT_GCC_EXTENSION uint8_t FrameOffset : 4;
+ /** Unwind opcodes. */
+ RT_FLEXIBLE_ARRAY_EXTENSION
+ IMAGE_UNWIND_CODE aOpcodes[RT_FLEXIBLE_ARRAY];
+} IMAGE_UNWIND_INFO;
+AssertCompileMemberOffset(IMAGE_UNWIND_INFO, aOpcodes, 4);
+typedef IMAGE_UNWIND_INFO *PIMAGE_UNWIND_INFO;
+typedef IMAGE_UNWIND_INFO const *PCIMAGE_UNWIND_INFO;
+
+/** IMAGE_UNW_FLAGS_XXX - IMAGE_UNWIND_INFO::Flags.
+ * @{ */
+/** No handler.
+ * @note Also know as UNW_FLAG_NHANDLER. */
+#define IMAGE_UNW_FLAGS_NHANDLER 0
+/** Have exception handler (RVA after codes, dword aligned.)
+ * @note Also know as UNW_FLAG_NHANDLER. */
+#define IMAGE_UNW_FLAGS_EHANDLER 1
+/** Have unwind handler (RVA after codes, dword aligned.)
+ * @note Also know as UNW_FLAG_NHANDLER. */
+#define IMAGE_UNW_FLAGS_UHANDLER 2
+/** Set if not primary unwind info for a function. An
+ * IMAGE_RUNTIME_FUNCTION_ENTRY giving the chained unwind info follows the
+ * aOpcodes array at a dword aligned offset. */
+#define IMAGE_UNW_FLAGS_CHAININFO 4
+/** @} */
+
+/**
+ * AMD64 unwind opcodes.
+ */
+typedef enum IMAGE_AMD64_UNWIND_OP_CODES
+{
+ /** Push non-volatile register (OpInfo).
+ * YASM: [pushreg reg]
+ * MASM: .PUSHREG reg */
+ IMAGE_AMD64_UWOP_PUSH_NONVOL = 0,
+ /** Stack allocation: Size stored in scaled in the next slot if OpInfo == 0,
+ * otherwise stored unscaled in the next two slots.
+ * YASM: [allocstack size]
+ * MASM: .ALLOCSTACK size */
+ IMAGE_AMD64_UWOP_ALLOC_LARGE,
+ /** Stack allocation: OpInfo = size / 8 - 1.
+ * YASM: [allocstack size]
+ * MASM: .ALLOCSTACK size */
+ IMAGE_AMD64_UWOP_ALLOC_SMALL,
+ /** Set frame pointer register: RSP + FrameOffset * 16.
+ * YASM: [setframe reg, offset]
+ * MASM: .SETFRAME reg, offset
+ * @code
+ * LEA RBP, [RSP + 20h]
+ * [setframe RBP, 20h]
+ * @endcode */
+ IMAGE_AMD64_UWOP_SET_FPREG,
+ /** Save non-volatile register (OpInfo) on stack (RSP/FP + next slot).
+ * YASM: [savereg reg, offset]
+ * MASM: .SAVEREG reg, offset */
+ IMAGE_AMD64_UWOP_SAVE_NONVOL,
+ /** Save non-volatile register (OpInfo) on stack (RSP/FP + next two slots).
+ * YASM: [savereg reg, offset]
+ * MASM: .SAVEREG reg, offset */
+ IMAGE_AMD64_UWOP_SAVE_NONVOL_FAR,
+ /** Epilog info, version 2+.
+ *
+ * The first time this opcode is used, the CodeOffset gives the size of the
+ * epilog and bit 0 of the OpInfo field indicates that there is only one
+ * epilog at the very end of the function.
+ *
+ * Subsequent uses of this opcode specifies epilog start offsets relative to
+ * the end of the function, using CodeOffset for the 8 lower bits and OpInfo
+ * for bits 8 thru 11.
+ *
+ * The compiler seems to stack allocations and register saving opcodes and
+ * indicates the location mirroring the first IMAGE_AMD64_UWOP_PUSH_NONVOL. */
+ IMAGE_AMD64_UWOP_EPILOG,
+ /** Undefined. */
+ IMAGE_AMD64_UWOP_RESERVED_7,
+ /** Save 128-bit XMM register (OpInfo) on stack (RSP/FP + next slot).
+ * YASM: [savexmm128 reg, offset]
+ * MASM: .SAVEXMM128 reg, offset */
+ IMAGE_AMD64_UWOP_SAVE_XMM128,
+ /** Save 128-bit XMM register (OpInfo) on stack (RSP/FP + next two slots).
+ * YASM: [savexmm128 reg, offset]
+ * MASM: .SAVEXMM128 reg, offset */
+ IMAGE_AMD64_UWOP_SAVE_XMM128_FAR,
+ /** IRET frame, OpInfo serves as error code indicator.
+ * YASM: [pushframe with-code]
+ * MASM: .pushframe with-code */
+ IMAGE_AMD64_UWOP_PUSH_MACHFRAME
+} IMAGE_AMD64_UNWIND_OP_CODES;
+/** @} */
+
+
+
+/** @name Image load config directories
+ * @{ */
+
+/** @since Windows 10 (preview 9879) */
+typedef struct _IMAGE_LOAD_CONFIG_CODE_INTEGRITY
+{
+ uint16_t Flags;
+ uint16_t Catalog;
+ uint32_t CatalogOffset;
+ uint32_t Reserved;
+} IMAGE_LOAD_CONFIG_CODE_INTEGRITY;
+AssertCompileSize(IMAGE_LOAD_CONFIG_CODE_INTEGRITY, 12);
+typedef IMAGE_LOAD_CONFIG_CODE_INTEGRITY *PIMAGE_LOAD_CONFIG_CODE_INTEGRITY;
+typedef IMAGE_LOAD_CONFIG_CODE_INTEGRITY const *PCIMAGE_LOAD_CONFIG_CODE_INTEGRITY;
+
+typedef struct _IMAGE_LOAD_CONFIG_DIRECTORY32_V1
+{
+ uint32_t Size;
+ uint32_t TimeDateStamp;
+ uint16_t MajorVersion;
+ uint16_t MinorVersion;
+ uint32_t GlobalFlagsClear;
+ uint32_t GlobalFlagsSet;
+ uint32_t CriticalSectionDefaultTimeout;
+ uint32_t DeCommitFreeBlockThreshold;
+ uint32_t DeCommitTotalFreeThreshold;
+ uint32_t LockPrefixTable;
+ uint32_t MaximumAllocationSize;
+ uint32_t VirtualMemoryThreshold;
+ uint32_t ProcessHeapFlags;
+ uint32_t ProcessAffinityMask;
+ uint16_t CSDVersion;
+ uint16_t DependentLoadFlags;
+ uint32_t EditList;
+ uint32_t SecurityCookie;
+} IMAGE_LOAD_CONFIG_DIRECTORY32_V1;
+AssertCompileSize(IMAGE_LOAD_CONFIG_DIRECTORY32_V1, 0x40);
+typedef IMAGE_LOAD_CONFIG_DIRECTORY32_V1 *PIMAGE_LOAD_CONFIG_DIRECTORY32_V1;
+typedef IMAGE_LOAD_CONFIG_DIRECTORY32_V1 const *PCIMAGE_LOAD_CONFIG_DIRECTORY32_V1;
+
+typedef struct _IMAGE_LOAD_CONFIG_DIRECTORY32_V2
+{
+ uint32_t Size;
+ uint32_t TimeDateStamp;
+ uint16_t MajorVersion;
+ uint16_t MinorVersion;
+ uint32_t GlobalFlagsClear;
+ uint32_t GlobalFlagsSet;
+ uint32_t CriticalSectionDefaultTimeout;
+ uint32_t DeCommitFreeBlockThreshold;
+ uint32_t DeCommitTotalFreeThreshold;
+ uint32_t LockPrefixTable;
+ uint32_t MaximumAllocationSize;
+ uint32_t VirtualMemoryThreshold;
+ uint32_t ProcessHeapFlags;
+ uint32_t ProcessAffinityMask;
+ uint16_t CSDVersion;
+ uint16_t DependentLoadFlags;
+ uint32_t EditList;
+ uint32_t SecurityCookie;
+ uint32_t SEHandlerTable;
+ uint32_t SEHandlerCount;
+} IMAGE_LOAD_CONFIG_DIRECTORY32_V2;
+AssertCompileSize(IMAGE_LOAD_CONFIG_DIRECTORY32_V2, 0x48);
+typedef IMAGE_LOAD_CONFIG_DIRECTORY32_V2 *PIMAGE_LOAD_CONFIG_DIRECTORY32_V2;
+typedef IMAGE_LOAD_CONFIG_DIRECTORY32_V2 const *PCIMAGE_LOAD_CONFIG_DIRECTORY32_V2;
+
+typedef struct _IMAGE_LOAD_CONFIG_DIRECTORY32_V3
+{
+ uint32_t Size;
+ uint32_t TimeDateStamp;
+ uint16_t MajorVersion;
+ uint16_t MinorVersion;
+ uint32_t GlobalFlagsClear;
+ uint32_t GlobalFlagsSet;
+ uint32_t CriticalSectionDefaultTimeout;
+ uint32_t DeCommitFreeBlockThreshold;
+ uint32_t DeCommitTotalFreeThreshold;
+ uint32_t LockPrefixTable;
+ uint32_t MaximumAllocationSize;
+ uint32_t VirtualMemoryThreshold;
+ uint32_t ProcessHeapFlags;
+ uint32_t ProcessAffinityMask;
+ uint16_t CSDVersion;
+ uint16_t DependentLoadFlags;
+ uint32_t EditList;
+ uint32_t SecurityCookie;
+ uint32_t SEHandlerTable;
+ uint32_t SEHandlerCount;
+ uint32_t GuardCFCCheckFunctionPointer;
+ uint32_t GuardCFDispatchFunctionPointer;
+ uint32_t GuardCFFunctionTable;
+ uint32_t GuardCFFunctionCount;
+ uint32_t GuardFlags;
+} IMAGE_LOAD_CONFIG_DIRECTORY32_V3;
+AssertCompileSize(IMAGE_LOAD_CONFIG_DIRECTORY32_V3, 0x5c);
+typedef IMAGE_LOAD_CONFIG_DIRECTORY32_V3 *PIMAGE_LOAD_CONFIG_DIRECTORY32_V3;
+typedef IMAGE_LOAD_CONFIG_DIRECTORY32_V3 const *PCIMAGE_LOAD_CONFIG_DIRECTORY32_V3;
+
+/** @since Windows 10 (preview 9879) */
+typedef struct _IMAGE_LOAD_CONFIG_DIRECTORY32_V4
+{
+ uint32_t Size;
+ uint32_t TimeDateStamp;
+ uint16_t MajorVersion;
+ uint16_t MinorVersion;
+ uint32_t GlobalFlagsClear;
+ uint32_t GlobalFlagsSet;
+ uint32_t CriticalSectionDefaultTimeout;
+ uint32_t DeCommitFreeBlockThreshold;
+ uint32_t DeCommitTotalFreeThreshold;
+ uint32_t LockPrefixTable;
+ uint32_t MaximumAllocationSize;
+ uint32_t VirtualMemoryThreshold;
+ uint32_t ProcessHeapFlags;
+ uint32_t ProcessAffinityMask;
+ uint16_t CSDVersion;
+ uint16_t DependentLoadFlags;
+ uint32_t EditList;
+ uint32_t SecurityCookie;
+ uint32_t SEHandlerTable;
+ uint32_t SEHandlerCount;
+ uint32_t GuardCFCCheckFunctionPointer;
+ uint32_t GuardCFDispatchFunctionPointer;
+ uint32_t GuardCFFunctionTable;
+ uint32_t GuardCFFunctionCount;
+ uint32_t GuardFlags;
+ IMAGE_LOAD_CONFIG_CODE_INTEGRITY CodeIntegrity;
+} IMAGE_LOAD_CONFIG_DIRECTORY32_V4;
+AssertCompileSize(IMAGE_LOAD_CONFIG_DIRECTORY32_V4, 0x68);
+typedef IMAGE_LOAD_CONFIG_DIRECTORY32_V4 *PIMAGE_LOAD_CONFIG_DIRECTORY32_V4;
+typedef IMAGE_LOAD_CONFIG_DIRECTORY32_V4 const *PCIMAGE_LOAD_CONFIG_DIRECTORY32_V4;
+
+/** @since Windows 10 build 14286 (or maybe earlier). */
+typedef struct _IMAGE_LOAD_CONFIG_DIRECTORY32_V5
+{
+ uint32_t Size;
+ uint32_t TimeDateStamp;
+ uint16_t MajorVersion;
+ uint16_t MinorVersion;
+ uint32_t GlobalFlagsClear;
+ uint32_t GlobalFlagsSet;
+ uint32_t CriticalSectionDefaultTimeout;
+ uint32_t DeCommitFreeBlockThreshold;
+ uint32_t DeCommitTotalFreeThreshold;
+ uint32_t LockPrefixTable;
+ uint32_t MaximumAllocationSize;
+ uint32_t VirtualMemoryThreshold;
+ uint32_t ProcessHeapFlags;
+ uint32_t ProcessAffinityMask;
+ uint16_t CSDVersion;
+ uint16_t DependentLoadFlags;
+ uint32_t EditList;
+ uint32_t SecurityCookie;
+ uint32_t SEHandlerTable;
+ uint32_t SEHandlerCount;
+ uint32_t GuardCFCCheckFunctionPointer;
+ uint32_t GuardCFDispatchFunctionPointer;
+ uint32_t GuardCFFunctionTable;
+ uint32_t GuardCFFunctionCount;
+ uint32_t GuardFlags;
+ IMAGE_LOAD_CONFIG_CODE_INTEGRITY CodeIntegrity;
+ uint32_t GuardAddressTakenIatEntryTable;
+ uint32_t GuardAddressTakenIatEntryCount;
+ uint32_t GuardLongJumpTargetTable;
+ uint32_t GuardLongJumpTargetCount;
+} IMAGE_LOAD_CONFIG_DIRECTORY32_V5;
+AssertCompileSize(IMAGE_LOAD_CONFIG_DIRECTORY32_V5, 0x78);
+typedef IMAGE_LOAD_CONFIG_DIRECTORY32_V5 *PIMAGE_LOAD_CONFIG_DIRECTORY32_V5;
+typedef IMAGE_LOAD_CONFIG_DIRECTORY32_V5 const *PCIMAGE_LOAD_CONFIG_DIRECTORY32_V5;
+
+/** @since Windows 10 build 14383 (or maybe earlier). */
+typedef struct _IMAGE_LOAD_CONFIG_DIRECTORY32_V6
+{
+ uint32_t Size; /**< 0x00 */
+ uint32_t TimeDateStamp; /**< 0x04 */
+ uint16_t MajorVersion; /**< 0x08 */
+ uint16_t MinorVersion; /**< 0x0a */
+ uint32_t GlobalFlagsClear; /**< 0x0c */
+ uint32_t GlobalFlagsSet; /**< 0x10 */
+ uint32_t CriticalSectionDefaultTimeout; /**< 0x14 */
+ uint32_t DeCommitFreeBlockThreshold; /**< 0x18 */
+ uint32_t DeCommitTotalFreeThreshold; /**< 0x1c */
+ uint32_t LockPrefixTable; /**< 0x20 */
+ uint32_t MaximumAllocationSize; /**< 0x24 */
+ uint32_t VirtualMemoryThreshold; /**< 0x28 */
+ uint32_t ProcessHeapFlags; /**< 0x2c */
+ uint32_t ProcessAffinityMask; /**< 0x30 */
+ uint16_t CSDVersion; /**< 0x34 */
+ uint16_t DependentLoadFlags; /**< 0x36 */
+ uint32_t EditList; /**< 0x38 */
+ uint32_t SecurityCookie; /**< 0x3c */
+ uint32_t SEHandlerTable; /**< 0x40 */
+ uint32_t SEHandlerCount; /**< 0x44 */
+ uint32_t GuardCFCCheckFunctionPointer; /**< 0x48 */
+ uint32_t GuardCFDispatchFunctionPointer; /**< 0x4c */
+ uint32_t GuardCFFunctionTable; /**< 0x50 */
+ uint32_t GuardCFFunctionCount; /**< 0x54 */
+ uint32_t GuardFlags; /**< 0x58 */
+ IMAGE_LOAD_CONFIG_CODE_INTEGRITY CodeIntegrity; /**< 0x5c */
+ uint32_t GuardAddressTakenIatEntryTable; /**< 0x68 */
+ uint32_t GuardAddressTakenIatEntryCount; /**< 0x6c */
+ uint32_t GuardLongJumpTargetTable; /**< 0x70 */
+ uint32_t GuardLongJumpTargetCount; /**< 0x74 */
+ uint32_t DynamicValueRelocTable; /**< 0x78 */
+ uint32_t HybridMetadataPointer; /**< 0x7c */
+} IMAGE_LOAD_CONFIG_DIRECTORY32_V6;
+AssertCompileSize(IMAGE_LOAD_CONFIG_DIRECTORY32_V6, 0x80);
+typedef IMAGE_LOAD_CONFIG_DIRECTORY32_V6 *PIMAGE_LOAD_CONFIG_DIRECTORY32_V6;
+typedef IMAGE_LOAD_CONFIG_DIRECTORY32_V6 const *PCIMAGE_LOAD_CONFIG_DIRECTORY32_V6;
+
+/** @since Windows 10 build 14901 (or maybe earlier). */
+typedef struct _IMAGE_LOAD_CONFIG_DIRECTORY32_V7
+{
+ uint32_t Size; /**< 0x00 */
+ uint32_t TimeDateStamp; /**< 0x04 */
+ uint16_t MajorVersion; /**< 0x08 */
+ uint16_t MinorVersion; /**< 0x0a */
+ uint32_t GlobalFlagsClear; /**< 0x0c */
+ uint32_t GlobalFlagsSet; /**< 0x10 */
+ uint32_t CriticalSectionDefaultTimeout; /**< 0x14 */
+ uint32_t DeCommitFreeBlockThreshold; /**< 0x18 */
+ uint32_t DeCommitTotalFreeThreshold; /**< 0x1c */
+ uint32_t LockPrefixTable; /**< 0x20 */
+ uint32_t MaximumAllocationSize; /**< 0x24 */
+ uint32_t VirtualMemoryThreshold; /**< 0x28 */
+ uint32_t ProcessHeapFlags; /**< 0x2c */
+ uint32_t ProcessAffinityMask; /**< 0x30 */
+ uint16_t CSDVersion; /**< 0x34 */
+ uint16_t DependentLoadFlags; /**< 0x36 */
+ uint32_t EditList; /**< 0x38 */
+ uint32_t SecurityCookie; /**< 0x3c */
+ uint32_t SEHandlerTable; /**< 0x40 */
+ uint32_t SEHandlerCount; /**< 0x44 */
+ uint32_t GuardCFCCheckFunctionPointer; /**< 0x48 */
+ uint32_t GuardCFDispatchFunctionPointer; /**< 0x4c */
+ uint32_t GuardCFFunctionTable; /**< 0x50 */
+ uint32_t GuardCFFunctionCount; /**< 0x54 */
+ uint32_t GuardFlags; /**< 0x58 */
+ IMAGE_LOAD_CONFIG_CODE_INTEGRITY CodeIntegrity; /**< 0x5c */
+ uint32_t GuardAddressTakenIatEntryTable; /**< 0x68 */
+ uint32_t GuardAddressTakenIatEntryCount; /**< 0x6c */
+ uint32_t GuardLongJumpTargetTable; /**< 0x70 */
+ uint32_t GuardLongJumpTargetCount; /**< 0x74 */
+ uint32_t DynamicValueRelocTable; /**< 0x78 */
+ uint32_t CHPEMetadataPointer; /**< 0x7c Not sure when this was renamed from HybridMetadataPointer. */
+ uint32_t GuardRFFailureRoutine; /**< 0x80 */
+ uint32_t GuardRFFailureRoutineFunctionPointer; /**< 0x84 */
+ uint32_t DynamicValueRelocTableOffset; /**< 0x88 */
+ uint16_t DynamicValueRelocTableSection; /**< 0x8c */
+ uint16_t Reserved2; /**< 0x8e */
+} IMAGE_LOAD_CONFIG_DIRECTORY32_V7;
+AssertCompileSize(IMAGE_LOAD_CONFIG_DIRECTORY32_V7, 0x90);
+typedef IMAGE_LOAD_CONFIG_DIRECTORY32_V7 *PIMAGE_LOAD_CONFIG_DIRECTORY32_V7;
+typedef IMAGE_LOAD_CONFIG_DIRECTORY32_V7 const *PCIMAGE_LOAD_CONFIG_DIRECTORY32_V7;
+
+/** @since Windows 10 build 15002 (or maybe earlier). */
+typedef struct _IMAGE_LOAD_CONFIG_DIRECTORY32_V8
+{
+ uint32_t Size; /**< 0x00 */
+ uint32_t TimeDateStamp; /**< 0x04 */
+ uint16_t MajorVersion; /**< 0x08 */
+ uint16_t MinorVersion; /**< 0x0a */
+ uint32_t GlobalFlagsClear; /**< 0x0c */
+ uint32_t GlobalFlagsSet; /**< 0x10 */
+ uint32_t CriticalSectionDefaultTimeout; /**< 0x14 */
+ uint32_t DeCommitFreeBlockThreshold; /**< 0x18 */
+ uint32_t DeCommitTotalFreeThreshold; /**< 0x1c */
+ uint32_t LockPrefixTable; /**< 0x20 */
+ uint32_t MaximumAllocationSize; /**< 0x24 */
+ uint32_t VirtualMemoryThreshold; /**< 0x28 */
+ uint32_t ProcessHeapFlags; /**< 0x2c */
+ uint32_t ProcessAffinityMask; /**< 0x30 */
+ uint16_t CSDVersion; /**< 0x34 */
+ uint16_t DependentLoadFlags; /**< 0x36 */
+ uint32_t EditList; /**< 0x38 */
+ uint32_t SecurityCookie; /**< 0x3c */
+ uint32_t SEHandlerTable; /**< 0x40 */
+ uint32_t SEHandlerCount; /**< 0x44 */
+ uint32_t GuardCFCCheckFunctionPointer; /**< 0x48 */
+ uint32_t GuardCFDispatchFunctionPointer; /**< 0x4c */
+ uint32_t GuardCFFunctionTable; /**< 0x50 */
+ uint32_t GuardCFFunctionCount; /**< 0x54 */
+ uint32_t GuardFlags; /**< 0x58 */
+ IMAGE_LOAD_CONFIG_CODE_INTEGRITY CodeIntegrity; /**< 0x5c */
+ uint32_t GuardAddressTakenIatEntryTable; /**< 0x68 */
+ uint32_t GuardAddressTakenIatEntryCount; /**< 0x6c */
+ uint32_t GuardLongJumpTargetTable; /**< 0x70 */
+ uint32_t GuardLongJumpTargetCount; /**< 0x74 */
+ uint32_t DynamicValueRelocTable; /**< 0x78 */
+ uint32_t CHPEMetadataPointer; /**< 0x7c Not sure when this was renamed from HybridMetadataPointer. */
+ uint32_t GuardRFFailureRoutine; /**< 0x80 */
+ uint32_t GuardRFFailureRoutineFunctionPointer; /**< 0x84 */
+ uint32_t DynamicValueRelocTableOffset; /**< 0x88 */
+ uint16_t DynamicValueRelocTableSection; /**< 0x8c */
+ uint16_t Reserved2; /**< 0x8e */
+ uint32_t GuardRFVerifyStackPointerFunctionPointer; /**< 0x90 */
+ uint32_t HotPatchTableOffset; /**< 0x94 */
+} IMAGE_LOAD_CONFIG_DIRECTORY32_V8;
+AssertCompileSize(IMAGE_LOAD_CONFIG_DIRECTORY32_V8, 0x98);
+typedef IMAGE_LOAD_CONFIG_DIRECTORY32_V8 *PIMAGE_LOAD_CONFIG_DIRECTORY32_V8;
+typedef IMAGE_LOAD_CONFIG_DIRECTORY32_V8 const *PCIMAGE_LOAD_CONFIG_DIRECTORY32_V8;
+
+/** @since Windows 10 build 16237 (or maybe earlier). */
+typedef struct _IMAGE_LOAD_CONFIG_DIRECTORY32_V9
+{
+ uint32_t Size; /**< 0x00 */
+ uint32_t TimeDateStamp; /**< 0x04 */
+ uint16_t MajorVersion; /**< 0x08 */
+ uint16_t MinorVersion; /**< 0x0a */
+ uint32_t GlobalFlagsClear; /**< 0x0c */
+ uint32_t GlobalFlagsSet; /**< 0x10 */
+ uint32_t CriticalSectionDefaultTimeout; /**< 0x14 */
+ uint32_t DeCommitFreeBlockThreshold; /**< 0x18 */
+ uint32_t DeCommitTotalFreeThreshold; /**< 0x1c */
+ uint32_t LockPrefixTable; /**< 0x20 */
+ uint32_t MaximumAllocationSize; /**< 0x24 */
+ uint32_t VirtualMemoryThreshold; /**< 0x28 */
+ uint32_t ProcessHeapFlags; /**< 0x2c */
+ uint32_t ProcessAffinityMask; /**< 0x30 */
+ uint16_t CSDVersion; /**< 0x34 */
+ uint16_t DependentLoadFlags; /**< 0x36 */
+ uint32_t EditList; /**< 0x38 */
+ uint32_t SecurityCookie; /**< 0x3c */
+ uint32_t SEHandlerTable; /**< 0x40 */
+ uint32_t SEHandlerCount; /**< 0x44 */
+ uint32_t GuardCFCCheckFunctionPointer; /**< 0x48 */
+ uint32_t GuardCFDispatchFunctionPointer; /**< 0x4c */
+ uint32_t GuardCFFunctionTable; /**< 0x50 */
+ uint32_t GuardCFFunctionCount; /**< 0x54 */
+ uint32_t GuardFlags; /**< 0x58 */
+ IMAGE_LOAD_CONFIG_CODE_INTEGRITY CodeIntegrity; /**< 0x5c */
+ uint32_t GuardAddressTakenIatEntryTable; /**< 0x68 */
+ uint32_t GuardAddressTakenIatEntryCount; /**< 0x6c */
+ uint32_t GuardLongJumpTargetTable; /**< 0x70 */
+ uint32_t GuardLongJumpTargetCount; /**< 0x74 */
+ uint32_t DynamicValueRelocTable; /**< 0x78 */
+ uint32_t CHPEMetadataPointer; /**< 0x7c Not sure when this was renamed from HybridMetadataPointer. */
+ uint32_t GuardRFFailureRoutine; /**< 0x80 */
+ uint32_t GuardRFFailureRoutineFunctionPointer; /**< 0x84 */
+ uint32_t DynamicValueRelocTableOffset; /**< 0x88 */
+ uint16_t DynamicValueRelocTableSection; /**< 0x8c */
+ uint16_t Reserved2; /**< 0x8e */
+ uint32_t GuardRFVerifyStackPointerFunctionPointer; /**< 0x90 */
+ uint32_t HotPatchTableOffset; /**< 0x94 */
+ uint32_t Reserved3; /**< 0x98 */
+ uint32_t EnclaveConfigurationPointer; /**< 0x9c */
+} IMAGE_LOAD_CONFIG_DIRECTORY32_V9;
+AssertCompileSize(IMAGE_LOAD_CONFIG_DIRECTORY32_V9, 0xa0);
+typedef IMAGE_LOAD_CONFIG_DIRECTORY32_V9 *PIMAGE_LOAD_CONFIG_DIRECTORY32_V9;
+typedef IMAGE_LOAD_CONFIG_DIRECTORY32_V9 const *PCIMAGE_LOAD_CONFIG_DIRECTORY32_V9;
+
+/** @since Windows 10 build 18362 (or maybe earlier). */
+typedef struct _IMAGE_LOAD_CONFIG_DIRECTORY32_V10
+{
+ uint32_t Size; /**< 0x00 */
+ uint32_t TimeDateStamp; /**< 0x04 */
+ uint16_t MajorVersion; /**< 0x08 */
+ uint16_t MinorVersion; /**< 0x0a */
+ uint32_t GlobalFlagsClear; /**< 0x0c */
+ uint32_t GlobalFlagsSet; /**< 0x10 */
+ uint32_t CriticalSectionDefaultTimeout; /**< 0x14 */
+ uint32_t DeCommitFreeBlockThreshold; /**< 0x18 */
+ uint32_t DeCommitTotalFreeThreshold; /**< 0x1c */
+ uint32_t LockPrefixTable; /**< 0x20 */
+ uint32_t MaximumAllocationSize; /**< 0x24 */
+ uint32_t VirtualMemoryThreshold; /**< 0x28 */
+ uint32_t ProcessHeapFlags; /**< 0x2c */
+ uint32_t ProcessAffinityMask; /**< 0x30 */
+ uint16_t CSDVersion; /**< 0x34 */
+ uint16_t DependentLoadFlags; /**< 0x36 */
+ uint32_t EditList; /**< 0x38 */
+ uint32_t SecurityCookie; /**< 0x3c */
+ uint32_t SEHandlerTable; /**< 0x40 */
+ uint32_t SEHandlerCount; /**< 0x44 */
+ uint32_t GuardCFCCheckFunctionPointer; /**< 0x48 */
+ uint32_t GuardCFDispatchFunctionPointer; /**< 0x4c */
+ uint32_t GuardCFFunctionTable; /**< 0x50 */
+ uint32_t GuardCFFunctionCount; /**< 0x54 */
+ uint32_t GuardFlags; /**< 0x58 */
+ IMAGE_LOAD_CONFIG_CODE_INTEGRITY CodeIntegrity; /**< 0x5c */
+ uint32_t GuardAddressTakenIatEntryTable; /**< 0x68 */
+ uint32_t GuardAddressTakenIatEntryCount; /**< 0x6c */
+ uint32_t GuardLongJumpTargetTable; /**< 0x70 */
+ uint32_t GuardLongJumpTargetCount; /**< 0x74 */
+ uint32_t DynamicValueRelocTable; /**< 0x78 */
+ uint32_t CHPEMetadataPointer; /**< 0x7c Not sure when this was renamed from HybridMetadataPointer. */
+ uint32_t GuardRFFailureRoutine; /**< 0x80 */
+ uint32_t GuardRFFailureRoutineFunctionPointer; /**< 0x84 */
+ uint32_t DynamicValueRelocTableOffset; /**< 0x88 */
+ uint16_t DynamicValueRelocTableSection; /**< 0x8c */
+ uint16_t Reserved2; /**< 0x8e */
+ uint32_t GuardRFVerifyStackPointerFunctionPointer; /**< 0x90 */
+ uint32_t HotPatchTableOffset; /**< 0x94 */
+ uint32_t Reserved3; /**< 0x98 */
+ uint32_t EnclaveConfigurationPointer; /**< 0x9c */
+ uint32_t VolatileMetadataPointer; /**< 0xa0 */
+} IMAGE_LOAD_CONFIG_DIRECTORY32_V10;
+AssertCompileSize(IMAGE_LOAD_CONFIG_DIRECTORY32_V10, 0xa4);
+typedef IMAGE_LOAD_CONFIG_DIRECTORY32_V10 *PIMAGE_LOAD_CONFIG_DIRECTORY32_V10;
+typedef IMAGE_LOAD_CONFIG_DIRECTORY32_V10 const *PCIMAGE_LOAD_CONFIG_DIRECTORY32_V10;
+
+/** @since Windows 10 build 19564 (or maybe earlier). */
+typedef struct _IMAGE_LOAD_CONFIG_DIRECTORY32_V11
+{
+ uint32_t Size; /**< 0x00 */
+ uint32_t TimeDateStamp; /**< 0x04 */
+ uint16_t MajorVersion; /**< 0x08 */
+ uint16_t MinorVersion; /**< 0x0a */
+ uint32_t GlobalFlagsClear; /**< 0x0c */
+ uint32_t GlobalFlagsSet; /**< 0x10 */
+ uint32_t CriticalSectionDefaultTimeout; /**< 0x14 */
+ uint32_t DeCommitFreeBlockThreshold; /**< 0x18 */
+ uint32_t DeCommitTotalFreeThreshold; /**< 0x1c */
+ uint32_t LockPrefixTable; /**< 0x20 */
+ uint32_t MaximumAllocationSize; /**< 0x24 */
+ uint32_t VirtualMemoryThreshold; /**< 0x28 */
+ uint32_t ProcessHeapFlags; /**< 0x2c */
+ uint32_t ProcessAffinityMask; /**< 0x30 */
+ uint16_t CSDVersion; /**< 0x34 */
+ uint16_t DependentLoadFlags; /**< 0x36 */
+ uint32_t EditList; /**< 0x38 */
+ uint32_t SecurityCookie; /**< 0x3c */
+ uint32_t SEHandlerTable; /**< 0x40 */
+ uint32_t SEHandlerCount; /**< 0x44 */
+ uint32_t GuardCFCCheckFunctionPointer; /**< 0x48 */
+ uint32_t GuardCFDispatchFunctionPointer; /**< 0x4c */
+ uint32_t GuardCFFunctionTable; /**< 0x50 */
+ uint32_t GuardCFFunctionCount; /**< 0x54 */
+ uint32_t GuardFlags; /**< 0x58 */
+ IMAGE_LOAD_CONFIG_CODE_INTEGRITY CodeIntegrity; /**< 0x5c */
+ uint32_t GuardAddressTakenIatEntryTable; /**< 0x68 */
+ uint32_t GuardAddressTakenIatEntryCount; /**< 0x6c */
+ uint32_t GuardLongJumpTargetTable; /**< 0x70 */
+ uint32_t GuardLongJumpTargetCount; /**< 0x74 */
+ uint32_t DynamicValueRelocTable; /**< 0x78 */
+ uint32_t CHPEMetadataPointer; /**< 0x7c Not sure when this was renamed from HybridMetadataPointer. */
+ uint32_t GuardRFFailureRoutine; /**< 0x80 */
+ uint32_t GuardRFFailureRoutineFunctionPointer; /**< 0x84 */
+ uint32_t DynamicValueRelocTableOffset; /**< 0x88 */
+ uint16_t DynamicValueRelocTableSection; /**< 0x8c */
+ uint16_t Reserved2; /**< 0x8e */
+ uint32_t GuardRFVerifyStackPointerFunctionPointer; /**< 0x90 */
+ uint32_t HotPatchTableOffset; /**< 0x94 */
+ uint32_t Reserved3; /**< 0x98 */
+ uint32_t EnclaveConfigurationPointer; /**< 0x9c - virtual address */
+ uint32_t VolatileMetadataPointer; /**< 0xa0 */
+ uint32_t GuardEHContinuationTable; /**< 0xa4 - virtual address */
+ uint32_t GuardEHContinuationCount; /**< 0xa8 */
+} IMAGE_LOAD_CONFIG_DIRECTORY32_V11;
+AssertCompileSize(IMAGE_LOAD_CONFIG_DIRECTORY32_V11, 0xac);
+typedef IMAGE_LOAD_CONFIG_DIRECTORY32_V11 *PIMAGE_LOAD_CONFIG_DIRECTORY32_V11;
+typedef IMAGE_LOAD_CONFIG_DIRECTORY32_V11 const *PCIMAGE_LOAD_CONFIG_DIRECTORY32_V11;
+
+/** @since Visual C++ 2019 / RS5_IMAGE_LOAD_CONFIG_DIRECTORY32. */
+typedef struct _IMAGE_LOAD_CONFIG_DIRECTORY32_V12
+{
+ uint32_t Size; /**< 0x00 */
+ uint32_t TimeDateStamp; /**< 0x04 */
+ uint16_t MajorVersion; /**< 0x08 */
+ uint16_t MinorVersion; /**< 0x0a */
+ uint32_t GlobalFlagsClear; /**< 0x0c */
+ uint32_t GlobalFlagsSet; /**< 0x10 */
+ uint32_t CriticalSectionDefaultTimeout; /**< 0x14 */
+ uint32_t DeCommitFreeBlockThreshold; /**< 0x18 */
+ uint32_t DeCommitTotalFreeThreshold; /**< 0x1c */
+ uint32_t LockPrefixTable; /**< 0x20 */
+ uint32_t MaximumAllocationSize; /**< 0x24 */
+ uint32_t VirtualMemoryThreshold; /**< 0x28 */
+ uint32_t ProcessHeapFlags; /**< 0x2c */
+ uint32_t ProcessAffinityMask; /**< 0x30 */
+ uint16_t CSDVersion; /**< 0x34 */
+ uint16_t DependentLoadFlags; /**< 0x36 */
+ uint32_t EditList; /**< 0x38 */
+ uint32_t SecurityCookie; /**< 0x3c */
+ uint32_t SEHandlerTable; /**< 0x40 */
+ uint32_t SEHandlerCount; /**< 0x44 */
+ uint32_t GuardCFCCheckFunctionPointer; /**< 0x48 */
+ uint32_t GuardCFDispatchFunctionPointer; /**< 0x4c */
+ uint32_t GuardCFFunctionTable; /**< 0x50 */
+ uint32_t GuardCFFunctionCount; /**< 0x54 */
+ uint32_t GuardFlags; /**< 0x58 */
+ IMAGE_LOAD_CONFIG_CODE_INTEGRITY CodeIntegrity; /**< 0x5c */
+ uint32_t GuardAddressTakenIatEntryTable; /**< 0x68 */
+ uint32_t GuardAddressTakenIatEntryCount; /**< 0x6c */
+ uint32_t GuardLongJumpTargetTable; /**< 0x70 */
+ uint32_t GuardLongJumpTargetCount; /**< 0x74 */
+ uint32_t DynamicValueRelocTable; /**< 0x78 */
+ uint32_t CHPEMetadataPointer; /**< 0x7c Not sure when this was renamed from HybridMetadataPointer. */
+ uint32_t GuardRFFailureRoutine; /**< 0x80 */
+ uint32_t GuardRFFailureRoutineFunctionPointer; /**< 0x84 */
+ uint32_t DynamicValueRelocTableOffset; /**< 0x88 */
+ uint16_t DynamicValueRelocTableSection; /**< 0x8c */
+ uint16_t Reserved2; /**< 0x8e */
+ uint32_t GuardRFVerifyStackPointerFunctionPointer; /**< 0x90 */
+ uint32_t HotPatchTableOffset; /**< 0x94 */
+ uint32_t Reserved3; /**< 0x98 */
+ uint32_t EnclaveConfigurationPointer; /**< 0x9c - virtual address */
+ uint32_t VolatileMetadataPointer; /**< 0xa0 */
+ uint32_t GuardEHContinuationTable; /**< 0xa4 - virtual address */
+ uint32_t GuardEHContinuationCount; /**< 0xa8 */
+ uint32_t GuardXFGCheckFunctionPointer; /**< 0xac */
+ uint32_t GuardXFGDispatchFunctionPointer; /**< 0xb0 */
+ uint32_t GuardXFGTableDispatchFunctionPointer; /**< 0xb4 */
+} IMAGE_LOAD_CONFIG_DIRECTORY32_V12;
+AssertCompileSize(IMAGE_LOAD_CONFIG_DIRECTORY32_V12, 0xb8);
+typedef IMAGE_LOAD_CONFIG_DIRECTORY32_V12 *PIMAGE_LOAD_CONFIG_DIRECTORY32_V12;
+typedef IMAGE_LOAD_CONFIG_DIRECTORY32_V12 const *PCIMAGE_LOAD_CONFIG_DIRECTORY32_V12;
+
+/** @since Visual C++ 2019 16.x (found in 16.11.9) / RS5_IMAGE_LOAD_CONFIG_DIRECTORY32. */
+typedef struct _IMAGE_LOAD_CONFIG_DIRECTORY32_V13
+{
+ uint32_t Size; /**< 0x00 - virtual address */
+ uint32_t TimeDateStamp; /**< 0x04 */
+ uint16_t MajorVersion; /**< 0x08 */
+ uint16_t MinorVersion; /**< 0x0a */
+ uint32_t GlobalFlagsClear; /**< 0x0c */
+ uint32_t GlobalFlagsSet; /**< 0x10 */
+ uint32_t CriticalSectionDefaultTimeout; /**< 0x14 */
+ uint32_t DeCommitFreeBlockThreshold; /**< 0x18 - virtual address */
+ uint32_t DeCommitTotalFreeThreshold; /**< 0x1c - virtual address */
+ uint32_t LockPrefixTable; /**< 0x20 */
+ uint32_t MaximumAllocationSize; /**< 0x24 */
+ uint32_t VirtualMemoryThreshold; /**< 0x28 - virtual address of pointer variable */
+ uint32_t ProcessHeapFlags; /**< 0x2c - virtual address of pointer variable */
+ uint32_t ProcessAffinityMask; /**< 0x30 - virtual address */
+ uint16_t CSDVersion; /**< 0x34 */
+ uint16_t DependentLoadFlags; /**< 0x36 */
+ uint32_t EditList; /**< 0x38 */
+ uint32_t SecurityCookie; /**< 0x3c - virtual address */
+ uint32_t SEHandlerTable; /**< 0x40 */
+ uint32_t SEHandlerCount; /**< 0x44 - virtual address */
+ uint32_t GuardCFCCheckFunctionPointer; /**< 0x48 */
+ uint32_t GuardCFDispatchFunctionPointer; /**< 0x4c - virtual address */
+ uint32_t GuardCFFunctionTable; /**< 0x50 */
+ uint32_t GuardCFFunctionCount; /**< 0x54 - virtual address */
+ uint32_t GuardFlags; /**< 0x58 - virtual address of pointer variable */
+ IMAGE_LOAD_CONFIG_CODE_INTEGRITY CodeIntegrity; /**< 0x5c */
+ uint32_t GuardAddressTakenIatEntryTable; /**< 0x68 - virtual address */
+ uint32_t GuardAddressTakenIatEntryCount; /**< 0x6c */
+ uint32_t GuardLongJumpTargetTable; /**< 0x70 - virtual address */
+ uint32_t GuardLongJumpTargetCount; /**< 0x74 */
+ uint32_t DynamicValueRelocTable; /**< 0x78 - virtual address */
+ uint32_t CHPEMetadataPointer; /**< 0x7c Not sure when this was renamed from HybridMetadataPointer. */
+ uint32_t GuardRFFailureRoutine; /**< 0x80 - virtual address */
+ uint32_t GuardRFFailureRoutineFunctionPointer; /**< 0x84 - virtual address of pointer variable */
+ uint32_t DynamicValueRelocTableOffset; /**< 0x88 */
+ uint16_t DynamicValueRelocTableSection; /**< 0x8c */
+ uint16_t Reserved2; /**< 0x8e */
+ uint32_t GuardRFVerifyStackPointerFunctionPointer; /**< 0x90 - virtual address of pointer variable */
+ uint32_t HotPatchTableOffset; /**< 0x94 */
+ uint32_t Reserved3; /**< 0x98 */
+ uint32_t EnclaveConfigurationPointer; /**< 0x9c - virtual address of pointer variable */
+ uint32_t VolatileMetadataPointer; /**< 0xa0 - virtual address of pointer variable */
+ uint32_t GuardEHContinuationTable; /**< 0xa4 - virtual address */
+ uint32_t GuardEHContinuationCount; /**< 0xa8 */
+ uint32_t GuardXFGCheckFunctionPointer; /**< 0xac - virtual address of pointer variable */
+ uint32_t GuardXFGDispatchFunctionPointer; /**< 0xb0 - virtual address of pointer variable */
+ uint32_t GuardXFGTableDispatchFunctionPointer; /**< 0xb4 - virtual address of pointer variable */
+ uint32_t CastGuardOsDeterminedFailureMode; /**< 0xb8 - virtual address */
+} IMAGE_LOAD_CONFIG_DIRECTORY32_V13;
+AssertCompileSize(IMAGE_LOAD_CONFIG_DIRECTORY32_V13, 0xbc);
+typedef IMAGE_LOAD_CONFIG_DIRECTORY32_V13 *PIMAGE_LOAD_CONFIG_DIRECTORY32_V13;
+typedef IMAGE_LOAD_CONFIG_DIRECTORY32_V13 const *PCIMAGE_LOAD_CONFIG_DIRECTORY32_V13;
+
+typedef IMAGE_LOAD_CONFIG_DIRECTORY32_V13 IMAGE_LOAD_CONFIG_DIRECTORY32;
+typedef PIMAGE_LOAD_CONFIG_DIRECTORY32_V13 PIMAGE_LOAD_CONFIG_DIRECTORY32;
+typedef PCIMAGE_LOAD_CONFIG_DIRECTORY32_V13 PCIMAGE_LOAD_CONFIG_DIRECTORY32;
+
+
+/* No _IMAGE_LOAD_CONFIG_DIRECTORY64_V1 exists. */
+
+typedef struct _IMAGE_LOAD_CONFIG_DIRECTORY64_V2
+{
+ uint32_t Size;
+ uint32_t TimeDateStamp;
+ uint16_t MajorVersion;
+ uint16_t MinorVersion;
+ uint32_t GlobalFlagsClear;
+ uint32_t GlobalFlagsSet;
+ uint32_t CriticalSectionDefaultTimeout;
+ uint64_t DeCommitFreeBlockThreshold;
+ uint64_t DeCommitTotalFreeThreshold;
+ uint64_t LockPrefixTable;
+ uint64_t MaximumAllocationSize;
+ uint64_t VirtualMemoryThreshold;
+ uint64_t ProcessAffinityMask;
+ uint32_t ProcessHeapFlags;
+ uint16_t CSDVersion;
+ uint16_t DependentLoadFlags;
+ uint64_t EditList;
+ uint64_t SecurityCookie;
+ uint64_t SEHandlerTable;
+ uint64_t SEHandlerCount;
+} IMAGE_LOAD_CONFIG_DIRECTORY64_V2;
+AssertCompileSize(IMAGE_LOAD_CONFIG_DIRECTORY64_V2, 0x70);
+typedef IMAGE_LOAD_CONFIG_DIRECTORY64_V2 *PIMAGE_LOAD_CONFIG_DIRECTORY64_V2;
+typedef IMAGE_LOAD_CONFIG_DIRECTORY64_V2 const *PCIMAGE_LOAD_CONFIG_DIRECTORY64_V2;
+
+#pragma pack(4) /* Why not 8 byte alignment, baka microsofties?!? */
+typedef struct _IMAGE_LOAD_CONFIG_DIRECTORY64_V3
+{
+ uint32_t Size;
+ uint32_t TimeDateStamp;
+ uint16_t MajorVersion;
+ uint16_t MinorVersion;
+ uint32_t GlobalFlagsClear;
+ uint32_t GlobalFlagsSet;
+ uint32_t CriticalSectionDefaultTimeout;
+ uint64_t DeCommitFreeBlockThreshold;
+ uint64_t DeCommitTotalFreeThreshold;
+ uint64_t LockPrefixTable;
+ uint64_t MaximumAllocationSize;
+ uint64_t VirtualMemoryThreshold;
+ uint64_t ProcessAffinityMask;
+ uint32_t ProcessHeapFlags;
+ uint16_t CSDVersion;
+ uint16_t DependentLoadFlags;
+ uint64_t EditList;
+ uint64_t SecurityCookie;
+ uint64_t SEHandlerTable;
+ uint64_t SEHandlerCount;
+ uint64_t GuardCFCCheckFunctionPointer;
+ uint64_t GuardCFDispatchFunctionPointer;
+ uint64_t GuardCFFunctionTable;
+ uint64_t GuardCFFunctionCount;
+ uint32_t GuardFlags;
+} IMAGE_LOAD_CONFIG_DIRECTORY64_V3;
+#pragma pack()
+AssertCompileSize(IMAGE_LOAD_CONFIG_DIRECTORY64_V3, 0x94);
+typedef IMAGE_LOAD_CONFIG_DIRECTORY64_V3 *PIMAGE_LOAD_CONFIG_DIRECTORY64_V3;
+typedef IMAGE_LOAD_CONFIG_DIRECTORY64_V3 const *PCIMAGE_LOAD_CONFIG_DIRECTORY64_V3;
+
+/** @since Windows 10 (Preview (9879). */
+typedef struct _IMAGE_LOAD_CONFIG_DIRECTORY64_V4
+{
+ uint32_t Size; /**< 0x00 */
+ uint32_t TimeDateStamp; /**< 0x04 */
+ uint16_t MajorVersion; /**< 0x08 */
+ uint16_t MinorVersion; /**< 0x0a */
+ uint32_t GlobalFlagsClear; /**< 0x0c */
+ uint32_t GlobalFlagsSet; /**< 0x10 */
+ uint32_t CriticalSectionDefaultTimeout; /**< 0x14 */
+ uint64_t DeCommitFreeBlockThreshold; /**< 0x18 */
+ uint64_t DeCommitTotalFreeThreshold; /**< 0x20 */
+ uint64_t LockPrefixTable; /**< 0x28 */
+ uint64_t MaximumAllocationSize; /**< 0x30 */
+ uint64_t VirtualMemoryThreshold; /**< 0x38 */
+ uint64_t ProcessAffinityMask; /**< 0x40 */
+ uint32_t ProcessHeapFlags; /**< 0x48 */
+ uint16_t CSDVersion; /**< 0x4c */
+ uint16_t DependentLoadFlags; /**< 0x4e */
+ uint64_t EditList; /**< 0x50 */
+ uint64_t SecurityCookie; /**< 0x58 */
+ uint64_t SEHandlerTable; /**< 0x60 */
+ uint64_t SEHandlerCount; /**< 0x68 */
+ uint64_t GuardCFCCheckFunctionPointer; /**< 0x70 */
+ uint64_t GuardCFDispatchFunctionPointer; /**< 0x78 */
+ uint64_t GuardCFFunctionTable; /**< 0x80 */
+ uint64_t GuardCFFunctionCount; /**< 0x88 */
+ uint32_t GuardFlags; /**< 0x90 */
+ IMAGE_LOAD_CONFIG_CODE_INTEGRITY CodeIntegrity; /**< 0x94 */
+} IMAGE_LOAD_CONFIG_DIRECTORY64_V4;
+AssertCompileSize(IMAGE_LOAD_CONFIG_DIRECTORY64_V4, 0xa0);
+typedef IMAGE_LOAD_CONFIG_DIRECTORY64_V4 *PIMAGE_LOAD_CONFIG_DIRECTORY64_V4;
+typedef IMAGE_LOAD_CONFIG_DIRECTORY64_V4 const *PCIMAGE_LOAD_CONFIG_DIRECTORY64_V4;
+
+/** @since Windows 10 build 14286 (or maybe earlier). */
+typedef struct _IMAGE_LOAD_CONFIG_DIRECTORY64_V5
+{
+ uint32_t Size; /**< 0x00 */
+ uint32_t TimeDateStamp; /**< 0x04 */
+ uint16_t MajorVersion; /**< 0x08 */
+ uint16_t MinorVersion; /**< 0x0a */
+ uint32_t GlobalFlagsClear; /**< 0x0c */
+ uint32_t GlobalFlagsSet; /**< 0x10 */
+ uint32_t CriticalSectionDefaultTimeout; /**< 0x14 */
+ uint64_t DeCommitFreeBlockThreshold; /**< 0x18 */
+ uint64_t DeCommitTotalFreeThreshold; /**< 0x20 */
+ uint64_t LockPrefixTable; /**< 0x28 */
+ uint64_t MaximumAllocationSize; /**< 0x30 */
+ uint64_t VirtualMemoryThreshold; /**< 0x38 */
+ uint64_t ProcessAffinityMask; /**< 0x40 */
+ uint32_t ProcessHeapFlags; /**< 0x48 */
+ uint16_t CSDVersion; /**< 0x4c */
+ uint16_t DependentLoadFlags; /**< 0x4e */
+ uint64_t EditList; /**< 0x50 */
+ uint64_t SecurityCookie; /**< 0x58 */
+ uint64_t SEHandlerTable; /**< 0x60 */
+ uint64_t SEHandlerCount; /**< 0x68 */
+ uint64_t GuardCFCCheckFunctionPointer; /**< 0x70 */
+ uint64_t GuardCFDispatchFunctionPointer; /**< 0x78 */
+ uint64_t GuardCFFunctionTable; /**< 0x80 */
+ uint64_t GuardCFFunctionCount; /**< 0x88 */
+ uint32_t GuardFlags; /**< 0x90 */
+ IMAGE_LOAD_CONFIG_CODE_INTEGRITY CodeIntegrity; /**< 0x94 */
+ uint64_t GuardAddressTakenIatEntryTable; /**< 0xa0 */
+ uint64_t GuardAddressTakenIatEntryCount; /**< 0xa8 */
+ uint64_t GuardLongJumpTargetTable; /**< 0xb0 */
+ uint64_t GuardLongJumpTargetCount; /**< 0xb8 */
+} IMAGE_LOAD_CONFIG_DIRECTORY64_V5;
+AssertCompileSize(IMAGE_LOAD_CONFIG_DIRECTORY64_V5, 0xc0);
+typedef IMAGE_LOAD_CONFIG_DIRECTORY64_V5 *PIMAGE_LOAD_CONFIG_DIRECTORY64_V5;
+typedef IMAGE_LOAD_CONFIG_DIRECTORY64_V5 const *PCIMAGE_LOAD_CONFIG_DIRECTORY64_V5;
+
+/** @since Windows 10 build 14393 (or maybe earlier). */
+typedef struct _IMAGE_LOAD_CONFIG_DIRECTORY64_V6
+{
+ uint32_t Size; /**< 0x00 */
+ uint32_t TimeDateStamp; /**< 0x04 */
+ uint16_t MajorVersion; /**< 0x08 */
+ uint16_t MinorVersion; /**< 0x0a */
+ uint32_t GlobalFlagsClear; /**< 0x0c */
+ uint32_t GlobalFlagsSet; /**< 0x10 */
+ uint32_t CriticalSectionDefaultTimeout; /**< 0x14 */
+ uint64_t DeCommitFreeBlockThreshold; /**< 0x18 */
+ uint64_t DeCommitTotalFreeThreshold; /**< 0x20 */
+ uint64_t LockPrefixTable; /**< 0x28 */
+ uint64_t MaximumAllocationSize; /**< 0x30 */
+ uint64_t VirtualMemoryThreshold; /**< 0x38 */
+ uint64_t ProcessAffinityMask; /**< 0x40 */
+ uint32_t ProcessHeapFlags; /**< 0x48 */
+ uint16_t CSDVersion; /**< 0x4c */
+ uint16_t DependentLoadFlags; /**< 0x4e */
+ uint64_t EditList; /**< 0x50 */
+ uint64_t SecurityCookie; /**< 0x58 */
+ uint64_t SEHandlerTable; /**< 0x60 */
+ uint64_t SEHandlerCount; /**< 0x68 */
+ uint64_t GuardCFCCheckFunctionPointer; /**< 0x70 */
+ uint64_t GuardCFDispatchFunctionPointer; /**< 0x78 */
+ uint64_t GuardCFFunctionTable; /**< 0x80 */
+ uint64_t GuardCFFunctionCount; /**< 0x88 */
+ uint32_t GuardFlags; /**< 0x90 */
+ IMAGE_LOAD_CONFIG_CODE_INTEGRITY CodeIntegrity; /**< 0x94 */
+ uint64_t GuardAddressTakenIatEntryTable; /**< 0xa0 */
+ uint64_t GuardAddressTakenIatEntryCount; /**< 0xa8 */
+ uint64_t GuardLongJumpTargetTable; /**< 0xb0 */
+ uint64_t GuardLongJumpTargetCount; /**< 0xb8 */
+ uint64_t DynamicValueRelocTable; /**< 0xc0 */
+ uint64_t HybridMetadataPointer; /**< 0xc8 */
+} IMAGE_LOAD_CONFIG_DIRECTORY64_V6;
+AssertCompileSize(IMAGE_LOAD_CONFIG_DIRECTORY64_V6, 0xd0);
+typedef IMAGE_LOAD_CONFIG_DIRECTORY64_V6 *PIMAGE_LOAD_CONFIG_DIRECTORY64_V6;
+typedef IMAGE_LOAD_CONFIG_DIRECTORY64_V6 const *PCIMAGE_LOAD_CONFIG_DIRECTORY64_V6;
+
+/** @since Windows 10 build 14901 (or maybe earlier). */
+typedef struct _IMAGE_LOAD_CONFIG_DIRECTORY64_V7
+{
+ uint32_t Size; /**< 0x00 */
+ uint32_t TimeDateStamp; /**< 0x04 */
+ uint16_t MajorVersion; /**< 0x08 */
+ uint16_t MinorVersion; /**< 0x0a */
+ uint32_t GlobalFlagsClear; /**< 0x0c */
+ uint32_t GlobalFlagsSet; /**< 0x10 */
+ uint32_t CriticalSectionDefaultTimeout; /**< 0x14 */
+ uint64_t DeCommitFreeBlockThreshold; /**< 0x18 */
+ uint64_t DeCommitTotalFreeThreshold; /**< 0x20 */
+ uint64_t LockPrefixTable; /**< 0x28 */
+ uint64_t MaximumAllocationSize; /**< 0x30 */
+ uint64_t VirtualMemoryThreshold; /**< 0x38 */
+ uint64_t ProcessAffinityMask; /**< 0x40 */
+ uint32_t ProcessHeapFlags; /**< 0x48 */
+ uint16_t CSDVersion; /**< 0x4c */
+ uint16_t DependentLoadFlags; /**< 0x4e */
+ uint64_t EditList; /**< 0x50 */
+ uint64_t SecurityCookie; /**< 0x58 */
+ uint64_t SEHandlerTable; /**< 0x60 */
+ uint64_t SEHandlerCount; /**< 0x68 */
+ uint64_t GuardCFCCheckFunctionPointer; /**< 0x70 */
+ uint64_t GuardCFDispatchFunctionPointer; /**< 0x78 */
+ uint64_t GuardCFFunctionTable; /**< 0x80 */
+ uint64_t GuardCFFunctionCount; /**< 0x88 */
+ uint32_t GuardFlags; /**< 0x90 */
+ IMAGE_LOAD_CONFIG_CODE_INTEGRITY CodeIntegrity; /**< 0x94 */
+ uint64_t GuardAddressTakenIatEntryTable; /**< 0xa0 */
+ uint64_t GuardAddressTakenIatEntryCount; /**< 0xa8 */
+ uint64_t GuardLongJumpTargetTable; /**< 0xb0 */
+ uint64_t GuardLongJumpTargetCount; /**< 0xb8 */
+ uint64_t DynamicValueRelocTable; /**< 0xc0 */
+ uint64_t CHPEMetadataPointer; /**< 0xc8 Not sure when this was renamed from HybridMetadataPointer. */
+ uint64_t GuardRFFailureRoutine; /**< 0xd0 */
+ uint64_t GuardRFFailureRoutineFunctionPointer; /**< 0xd8 */
+ uint32_t DynamicValueRelocTableOffset; /**< 0xe0 */
+ uint16_t DynamicValueRelocTableSection; /**< 0xe4 */
+ uint16_t Reserved2; /**< 0xe6 */
+} IMAGE_LOAD_CONFIG_DIRECTORY64_V7;
+AssertCompileSize(IMAGE_LOAD_CONFIG_DIRECTORY64_V7, 0xe8);
+typedef IMAGE_LOAD_CONFIG_DIRECTORY64_V7 *PIMAGE_LOAD_CONFIG_DIRECTORY64_V7;
+typedef IMAGE_LOAD_CONFIG_DIRECTORY64_V7 const *PCIMAGE_LOAD_CONFIG_DIRECTORY64_V7;
+
+/** @since Windows 10 build 15002 (or maybe earlier). */
+#pragma pack(4) /* Stupid, stupid microsofties! */
+typedef struct _IMAGE_LOAD_CONFIG_DIRECTORY64_V8
+{
+ uint32_t Size; /**< 0x00 */
+ uint32_t TimeDateStamp; /**< 0x04 */
+ uint16_t MajorVersion; /**< 0x08 */
+ uint16_t MinorVersion; /**< 0x0a */
+ uint32_t GlobalFlagsClear; /**< 0x0c */
+ uint32_t GlobalFlagsSet; /**< 0x10 */
+ uint32_t CriticalSectionDefaultTimeout; /**< 0x14 */
+ uint64_t DeCommitFreeBlockThreshold; /**< 0x18 */
+ uint64_t DeCommitTotalFreeThreshold; /**< 0x20 */
+ uint64_t LockPrefixTable; /**< 0x28 */
+ uint64_t MaximumAllocationSize; /**< 0x30 */
+ uint64_t VirtualMemoryThreshold; /**< 0x38 */
+ uint64_t ProcessAffinityMask; /**< 0x40 */
+ uint32_t ProcessHeapFlags; /**< 0x48 */
+ uint16_t CSDVersion; /**< 0x4c */
+ uint16_t DependentLoadFlags; /**< 0x4e */
+ uint64_t EditList; /**< 0x50 */
+ uint64_t SecurityCookie; /**< 0x58 */
+ uint64_t SEHandlerTable; /**< 0x60 */
+ uint64_t SEHandlerCount; /**< 0x68 */
+ uint64_t GuardCFCCheckFunctionPointer; /**< 0x70 */
+ uint64_t GuardCFDispatchFunctionPointer; /**< 0x78 */
+ uint64_t GuardCFFunctionTable; /**< 0x80 */
+ uint64_t GuardCFFunctionCount; /**< 0x88 */
+ uint32_t GuardFlags; /**< 0x90 */
+ IMAGE_LOAD_CONFIG_CODE_INTEGRITY CodeIntegrity; /**< 0x94 */
+ uint64_t GuardAddressTakenIatEntryTable; /**< 0xa0 */
+ uint64_t GuardAddressTakenIatEntryCount; /**< 0xa8 */
+ uint64_t GuardLongJumpTargetTable; /**< 0xb0 */
+ uint64_t GuardLongJumpTargetCount; /**< 0xb8 */
+ uint64_t DynamicValueRelocTable; /**< 0xc0 */
+ uint64_t CHPEMetadataPointer; /**< 0xc8 */
+ uint64_t GuardRFFailureRoutine; /**< 0xd0 */
+ uint64_t GuardRFFailureRoutineFunctionPointer; /**< 0xd8 */
+ uint32_t DynamicValueRelocTableOffset; /**< 0xe0 */
+ uint16_t DynamicValueRelocTableSection; /**< 0xe4 */
+ uint16_t Reserved2; /**< 0xe6 */
+ uint64_t GuardRFVerifyStackPointerFunctionPointer; /**< 0xe8 */
+ uint32_t HotPatchTableOffset; /**< 0xf0 */
+} IMAGE_LOAD_CONFIG_DIRECTORY64_V8;
+#pragma pack()
+AssertCompileSize(IMAGE_LOAD_CONFIG_DIRECTORY64_V8, 0xf4);
+typedef IMAGE_LOAD_CONFIG_DIRECTORY64_V8 *PIMAGE_LOAD_CONFIG_DIRECTORY64_V8;
+typedef IMAGE_LOAD_CONFIG_DIRECTORY64_V8 const *PCIMAGE_LOAD_CONFIG_DIRECTORY64_V8;
+
+/** @since Windows 10 build 15002 (or maybe earlier). */
+typedef struct _IMAGE_LOAD_CONFIG_DIRECTORY64_V9
+{
+ uint32_t Size; /**< 0x00 */
+ uint32_t TimeDateStamp; /**< 0x04 */
+ uint16_t MajorVersion; /**< 0x08 */
+ uint16_t MinorVersion; /**< 0x0a */
+ uint32_t GlobalFlagsClear; /**< 0x0c */
+ uint32_t GlobalFlagsSet; /**< 0x10 */
+ uint32_t CriticalSectionDefaultTimeout; /**< 0x14 */
+ uint64_t DeCommitFreeBlockThreshold; /**< 0x18 */
+ uint64_t DeCommitTotalFreeThreshold; /**< 0x20 */
+ uint64_t LockPrefixTable; /**< 0x28 */
+ uint64_t MaximumAllocationSize; /**< 0x30 */
+ uint64_t VirtualMemoryThreshold; /**< 0x38 */
+ uint64_t ProcessAffinityMask; /**< 0x40 */
+ uint32_t ProcessHeapFlags; /**< 0x48 */
+ uint16_t CSDVersion; /**< 0x4c */
+ uint16_t DependentLoadFlags; /**< 0x4e */
+ uint64_t EditList; /**< 0x50 */
+ uint64_t SecurityCookie; /**< 0x58 */
+ uint64_t SEHandlerTable; /**< 0x60 */
+ uint64_t SEHandlerCount; /**< 0x68 */
+ uint64_t GuardCFCCheckFunctionPointer; /**< 0x70 */
+ uint64_t GuardCFDispatchFunctionPointer; /**< 0x78 */
+ uint64_t GuardCFFunctionTable; /**< 0x80 */
+ uint64_t GuardCFFunctionCount; /**< 0x88 */
+ uint32_t GuardFlags; /**< 0x90 */
+ IMAGE_LOAD_CONFIG_CODE_INTEGRITY CodeIntegrity; /**< 0x94 */
+ uint64_t GuardAddressTakenIatEntryTable; /**< 0xa0 */
+ uint64_t GuardAddressTakenIatEntryCount; /**< 0xa8 */
+ uint64_t GuardLongJumpTargetTable; /**< 0xb0 */
+ uint64_t GuardLongJumpTargetCount; /**< 0xb8 */
+ uint64_t DynamicValueRelocTable; /**< 0xc0 */
+ uint64_t CHPEMetadataPointer; /**< 0xc8 */
+ uint64_t GuardRFFailureRoutine; /**< 0xd0 */
+ uint64_t GuardRFFailureRoutineFunctionPointer; /**< 0xd8 */
+ uint32_t DynamicValueRelocTableOffset; /**< 0xe0 */
+ uint16_t DynamicValueRelocTableSection; /**< 0xe4 */
+ uint16_t Reserved2; /**< 0xe6 */
+ uint64_t GuardRFVerifyStackPointerFunctionPointer; /**< 0xe8 */
+ uint32_t HotPatchTableOffset; /**< 0xf0 */
+ uint32_t Reserved3; /**< 0xf4 */
+ uint64_t EnclaveConfigurationPointer; /**< 0xf8 - seen in bcrypt and bcryptprimitives pointing to the string "L". */
+} IMAGE_LOAD_CONFIG_DIRECTORY64_V9;
+AssertCompileSize(IMAGE_LOAD_CONFIG_DIRECTORY64_V9, 0x100);
+typedef IMAGE_LOAD_CONFIG_DIRECTORY64_V9 *PIMAGE_LOAD_CONFIG_DIRECTORY64_V9;
+typedef IMAGE_LOAD_CONFIG_DIRECTORY64_V9 const *PCIMAGE_LOAD_CONFIG_DIRECTORY64_V9;
+
+/** @since Windows 10 build 18362 (or maybe earlier). */
+typedef struct _IMAGE_LOAD_CONFIG_DIRECTORY64_V10
+{
+ uint32_t Size; /**< 0x00 */
+ uint32_t TimeDateStamp; /**< 0x04 */
+ uint16_t MajorVersion; /**< 0x08 */
+ uint16_t MinorVersion; /**< 0x0a */
+ uint32_t GlobalFlagsClear; /**< 0x0c */
+ uint32_t GlobalFlagsSet; /**< 0x10 */
+ uint32_t CriticalSectionDefaultTimeout; /**< 0x14 */
+ uint64_t DeCommitFreeBlockThreshold; /**< 0x18 */
+ uint64_t DeCommitTotalFreeThreshold; /**< 0x20 */
+ uint64_t LockPrefixTable; /**< 0x28 */
+ uint64_t MaximumAllocationSize; /**< 0x30 */
+ uint64_t VirtualMemoryThreshold; /**< 0x38 */
+ uint64_t ProcessAffinityMask; /**< 0x40 */
+ uint32_t ProcessHeapFlags; /**< 0x48 */
+ uint16_t CSDVersion; /**< 0x4c */
+ uint16_t DependentLoadFlags; /**< 0x4e */
+ uint64_t EditList; /**< 0x50 */
+ uint64_t SecurityCookie; /**< 0x58 */
+ uint64_t SEHandlerTable; /**< 0x60 */
+ uint64_t SEHandlerCount; /**< 0x68 */
+ uint64_t GuardCFCCheckFunctionPointer; /**< 0x70 */
+ uint64_t GuardCFDispatchFunctionPointer; /**< 0x78 */
+ uint64_t GuardCFFunctionTable; /**< 0x80 */
+ uint64_t GuardCFFunctionCount; /**< 0x88 */
+ uint32_t GuardFlags; /**< 0x90 */
+ IMAGE_LOAD_CONFIG_CODE_INTEGRITY CodeIntegrity; /**< 0x94 */
+ uint64_t GuardAddressTakenIatEntryTable; /**< 0xa0 */
+ uint64_t GuardAddressTakenIatEntryCount; /**< 0xa8 */
+ uint64_t GuardLongJumpTargetTable; /**< 0xb0 */
+ uint64_t GuardLongJumpTargetCount; /**< 0xb8 */
+ uint64_t DynamicValueRelocTable; /**< 0xc0 */
+ uint64_t CHPEMetadataPointer; /**< 0xc8 */
+ uint64_t GuardRFFailureRoutine; /**< 0xd0 */
+ uint64_t GuardRFFailureRoutineFunctionPointer; /**< 0xd8 */
+ uint32_t DynamicValueRelocTableOffset; /**< 0xe0 */
+ uint16_t DynamicValueRelocTableSection; /**< 0xe4 */
+ uint16_t Reserved2; /**< 0xe6 */
+ uint64_t GuardRFVerifyStackPointerFunctionPointer; /**< 0xe8 */
+ uint32_t HotPatchTableOffset; /**< 0xf0 */
+ uint32_t Reserved3; /**< 0xf4 */
+ uint64_t EnclaveConfigurationPointer; /**< 0xf8 - seen in bcrypt and bcryptprimitives pointing to the string "L". */
+ uint64_t VolatileMetadataPointer; /**< 0x100 */
+} IMAGE_LOAD_CONFIG_DIRECTORY64_V10;
+AssertCompileSize(IMAGE_LOAD_CONFIG_DIRECTORY64_V10, 0x108);
+typedef IMAGE_LOAD_CONFIG_DIRECTORY64_V10 *PIMAGE_LOAD_CONFIG_DIRECTORY64_V10;
+typedef IMAGE_LOAD_CONFIG_DIRECTORY64_V10 const *PCIMAGE_LOAD_CONFIG_DIRECTORY64_V10;
+
+/** @since Windows 10 build 19534 (or maybe earlier). */
+typedef struct _IMAGE_LOAD_CONFIG_DIRECTORY64_V11
+{
+ uint32_t Size; /**< 0x00 */
+ uint32_t TimeDateStamp; /**< 0x04 */
+ uint16_t MajorVersion; /**< 0x08 */
+ uint16_t MinorVersion; /**< 0x0a */
+ uint32_t GlobalFlagsClear; /**< 0x0c */
+ uint32_t GlobalFlagsSet; /**< 0x10 */
+ uint32_t CriticalSectionDefaultTimeout; /**< 0x14 */
+ uint64_t DeCommitFreeBlockThreshold; /**< 0x18 */
+ uint64_t DeCommitTotalFreeThreshold; /**< 0x20 */
+ uint64_t LockPrefixTable; /**< 0x28 */
+ uint64_t MaximumAllocationSize; /**< 0x30 */
+ uint64_t VirtualMemoryThreshold; /**< 0x38 */
+ uint64_t ProcessAffinityMask; /**< 0x40 */
+ uint32_t ProcessHeapFlags; /**< 0x48 */
+ uint16_t CSDVersion; /**< 0x4c */
+ uint16_t DependentLoadFlags; /**< 0x4e */
+ uint64_t EditList; /**< 0x50 */
+ uint64_t SecurityCookie; /**< 0x58 */
+ uint64_t SEHandlerTable; /**< 0x60 */
+ uint64_t SEHandlerCount; /**< 0x68 */
+ uint64_t GuardCFCCheckFunctionPointer; /**< 0x70 */
+ uint64_t GuardCFDispatchFunctionPointer; /**< 0x78 */
+ uint64_t GuardCFFunctionTable; /**< 0x80 */
+ uint64_t GuardCFFunctionCount; /**< 0x88 */
+ uint32_t GuardFlags; /**< 0x90 */
+ IMAGE_LOAD_CONFIG_CODE_INTEGRITY CodeIntegrity; /**< 0x94 */
+ uint64_t GuardAddressTakenIatEntryTable; /**< 0xa0 */
+ uint64_t GuardAddressTakenIatEntryCount; /**< 0xa8 */
+ uint64_t GuardLongJumpTargetTable; /**< 0xb0 */
+ uint64_t GuardLongJumpTargetCount; /**< 0xb8 */
+ uint64_t DynamicValueRelocTable; /**< 0xc0 */
+ uint64_t CHPEMetadataPointer; /**< 0xc8 */
+ uint64_t GuardRFFailureRoutine; /**< 0xd0 */
+ uint64_t GuardRFFailureRoutineFunctionPointer; /**< 0xd8 */
+ uint32_t DynamicValueRelocTableOffset; /**< 0xe0 */
+ uint16_t DynamicValueRelocTableSection; /**< 0xe4 */
+ uint16_t Reserved2; /**< 0xe6 */
+ uint64_t GuardRFVerifyStackPointerFunctionPointer; /**< 0xe8 */
+ uint32_t HotPatchTableOffset; /**< 0xf0 */
+ uint32_t Reserved3; /**< 0xf4 */
+ uint64_t EnclaveConfigurationPointer; /**< 0xf8 - seen in bcrypt and bcryptprimitives pointing to the string "L". */
+ uint64_t VolatileMetadataPointer; /**< 0x100 */
+ uint64_t GuardEHContinuationTable; /**< 0x108 - virtual address */
+ uint64_t GuardEHContinuationCount; /**< 0x110 */
+} IMAGE_LOAD_CONFIG_DIRECTORY64_V11;
+AssertCompileSize(IMAGE_LOAD_CONFIG_DIRECTORY64_V11, 0x118);
+typedef IMAGE_LOAD_CONFIG_DIRECTORY64_V11 *PIMAGE_LOAD_CONFIG_DIRECTORY64_V11;
+typedef IMAGE_LOAD_CONFIG_DIRECTORY64_V11 const *PCIMAGE_LOAD_CONFIG_DIRECTORY64_V11;
+
+/** @since Visual C++ 2019 / RS5_IMAGE_LOAD_CONFIG_DIRECTORY64. */
+typedef struct _IMAGE_LOAD_CONFIG_DIRECTORY64_V12
+{
+ uint32_t Size; /**< 0x00 */
+ uint32_t TimeDateStamp; /**< 0x04 */
+ uint16_t MajorVersion; /**< 0x08 */
+ uint16_t MinorVersion; /**< 0x0a */
+ uint32_t GlobalFlagsClear; /**< 0x0c */
+ uint32_t GlobalFlagsSet; /**< 0x10 */
+ uint32_t CriticalSectionDefaultTimeout; /**< 0x14 */
+ uint64_t DeCommitFreeBlockThreshold; /**< 0x18 */
+ uint64_t DeCommitTotalFreeThreshold; /**< 0x20 */
+ uint64_t LockPrefixTable; /**< 0x28 */
+ uint64_t MaximumAllocationSize; /**< 0x30 */
+ uint64_t VirtualMemoryThreshold; /**< 0x38 */
+ uint64_t ProcessAffinityMask; /**< 0x40 */
+ uint32_t ProcessHeapFlags; /**< 0x48 */
+ uint16_t CSDVersion; /**< 0x4c */
+ uint16_t DependentLoadFlags; /**< 0x4e */
+ uint64_t EditList; /**< 0x50 */
+ uint64_t SecurityCookie; /**< 0x58 */
+ uint64_t SEHandlerTable; /**< 0x60 */
+ uint64_t SEHandlerCount; /**< 0x68 */
+ uint64_t GuardCFCCheckFunctionPointer; /**< 0x70 */
+ uint64_t GuardCFDispatchFunctionPointer; /**< 0x78 */
+ uint64_t GuardCFFunctionTable; /**< 0x80 */
+ uint64_t GuardCFFunctionCount; /**< 0x88 */
+ uint32_t GuardFlags; /**< 0x90 */
+ IMAGE_LOAD_CONFIG_CODE_INTEGRITY CodeIntegrity; /**< 0x94 */
+ uint64_t GuardAddressTakenIatEntryTable; /**< 0xa0 */
+ uint64_t GuardAddressTakenIatEntryCount; /**< 0xa8 */
+ uint64_t GuardLongJumpTargetTable; /**< 0xb0 */
+ uint64_t GuardLongJumpTargetCount; /**< 0xb8 */
+ uint64_t DynamicValueRelocTable; /**< 0xc0 */
+ uint64_t CHPEMetadataPointer; /**< 0xc8 */
+ uint64_t GuardRFFailureRoutine; /**< 0xd0 */
+ uint64_t GuardRFFailureRoutineFunctionPointer; /**< 0xd8 */
+ uint32_t DynamicValueRelocTableOffset; /**< 0xe0 */
+ uint16_t DynamicValueRelocTableSection; /**< 0xe4 */
+ uint16_t Reserved2; /**< 0xe6 */
+ uint64_t GuardRFVerifyStackPointerFunctionPointer; /**< 0xe8 */
+ uint32_t HotPatchTableOffset; /**< 0xf0 */
+ uint32_t Reserved3; /**< 0xf4 */
+ uint64_t EnclaveConfigurationPointer; /**< 0xf8 - seen in bcrypt and bcryptprimitives pointing to the string "L". */
+ uint64_t VolatileMetadataPointer; /**< 0x100 */
+ uint64_t GuardEHContinuationTable; /**< 0x108 - virtual address */
+ uint64_t GuardEHContinuationCount; /**< 0x110 */
+ uint64_t GuardXFGCheckFunctionPointer; /**< 0x118 */
+ uint64_t GuardXFGDispatchFunctionPointer; /**< 0x120 */
+ uint64_t GuardXFGTableDispatchFunctionPointer; /**< 0x128 */
+} IMAGE_LOAD_CONFIG_DIRECTORY64_V12;
+AssertCompileSize(IMAGE_LOAD_CONFIG_DIRECTORY64_V12, 0x130);
+typedef IMAGE_LOAD_CONFIG_DIRECTORY64_V12 *PIMAGE_LOAD_CONFIG_DIRECTORY64_V12;
+typedef IMAGE_LOAD_CONFIG_DIRECTORY64_V12 const *PCIMAGE_LOAD_CONFIG_DIRECTORY64_V12;
+
+/** @since Visual C++ 2019 16.x (found in 16.11.9) / RS5_IMAGE_LOAD_CONFIG_DIRECTORY32. */
+typedef struct _IMAGE_LOAD_CONFIG_DIRECTORY64_V13
+{
+ uint32_t Size; /**< 0x00 */
+ uint32_t TimeDateStamp; /**< 0x04 */
+ uint16_t MajorVersion; /**< 0x08 */
+ uint16_t MinorVersion; /**< 0x0a */
+ uint32_t GlobalFlagsClear; /**< 0x0c */
+ uint32_t GlobalFlagsSet; /**< 0x10 */
+ uint32_t CriticalSectionDefaultTimeout; /**< 0x14 */
+ uint64_t DeCommitFreeBlockThreshold; /**< 0x18 */
+ uint64_t DeCommitTotalFreeThreshold; /**< 0x20 */
+ uint64_t LockPrefixTable; /**< 0x28 - virtual address */
+ uint64_t MaximumAllocationSize; /**< 0x30 */
+ uint64_t VirtualMemoryThreshold; /**< 0x38 */
+ uint64_t ProcessAffinityMask; /**< 0x40 */
+ uint32_t ProcessHeapFlags; /**< 0x48 */
+ uint16_t CSDVersion; /**< 0x4c */
+ uint16_t DependentLoadFlags; /**< 0x4e */
+ uint64_t EditList; /**< 0x50 - virtual address */
+ uint64_t SecurityCookie; /**< 0x58 - virtual address */
+ uint64_t SEHandlerTable; /**< 0x60 */
+ uint64_t SEHandlerCount; /**< 0x68 */
+ uint64_t GuardCFCCheckFunctionPointer; /**< 0x70 - virtual address of pointer variable */
+ uint64_t GuardCFDispatchFunctionPointer; /**< 0x78 - virtual address of pointer variable */
+ uint64_t GuardCFFunctionTable; /**< 0x80 - virtual address */
+ uint64_t GuardCFFunctionCount; /**< 0x88 */
+ uint32_t GuardFlags; /**< 0x90 */
+ IMAGE_LOAD_CONFIG_CODE_INTEGRITY CodeIntegrity; /**< 0x94 */
+ uint64_t GuardAddressTakenIatEntryTable; /**< 0xa0 - virtual address */
+ uint64_t GuardAddressTakenIatEntryCount; /**< 0xa8 */
+ uint64_t GuardLongJumpTargetTable; /**< 0xb0 - virtual address */
+ uint64_t GuardLongJumpTargetCount; /**< 0xb8 */
+ uint64_t DynamicValueRelocTable; /**< 0xc0 - virtual address */
+ uint64_t CHPEMetadataPointer; /**< 0xc8 */
+ uint64_t GuardRFFailureRoutine; /**< 0xd0 - virtual address */
+ uint64_t GuardRFFailureRoutineFunctionPointer; /**< 0xd8 - virtual address of pointer variable */
+ uint32_t DynamicValueRelocTableOffset; /**< 0xe0 */
+ uint16_t DynamicValueRelocTableSection; /**< 0xe4 */
+ uint16_t Reserved2; /**< 0xe6 */
+ uint64_t GuardRFVerifyStackPointerFunctionPointer; /**< 0xe8 - virtual address of pointer variable */
+ uint32_t HotPatchTableOffset; /**< 0xf0 */
+ uint32_t Reserved3; /**< 0xf4 */
+ uint64_t EnclaveConfigurationPointer; /**< 0xf8 - seen in bcrypt and bcryptprimitives pointing to the string "L". */
+ uint64_t VolatileMetadataPointer; /**< 0x100 - virtual address of pointer variable */
+ uint64_t GuardEHContinuationTable; /**< 0x108 - virtual address */
+ uint64_t GuardEHContinuationCount; /**< 0x110 */
+ uint64_t GuardXFGCheckFunctionPointer; /**< 0x118 - virtual address of pointer variable */
+ uint64_t GuardXFGDispatchFunctionPointer; /**< 0x120 - virtual address of pointer variable */
+ uint64_t GuardXFGTableDispatchFunctionPointer; /**< 0x128 - virtual address of pointer variable */
+ uint64_t CastGuardOsDeterminedFailureMode; /**< 0x130 - virtual address */
+} IMAGE_LOAD_CONFIG_DIRECTORY64_V13;
+AssertCompileSize(IMAGE_LOAD_CONFIG_DIRECTORY64_V13, 0x138);
+typedef IMAGE_LOAD_CONFIG_DIRECTORY64_V13 *PIMAGE_LOAD_CONFIG_DIRECTORY64_V13;
+typedef IMAGE_LOAD_CONFIG_DIRECTORY64_V13 const *PCIMAGE_LOAD_CONFIG_DIRECTORY64_V13;
+
+typedef IMAGE_LOAD_CONFIG_DIRECTORY64_V13 IMAGE_LOAD_CONFIG_DIRECTORY64;
+typedef PIMAGE_LOAD_CONFIG_DIRECTORY64_V13 PIMAGE_LOAD_CONFIG_DIRECTORY64;
+typedef PCIMAGE_LOAD_CONFIG_DIRECTORY64_V13 PCIMAGE_LOAD_CONFIG_DIRECTORY64;
+
+/** @} */
+
+
+/**
+ * PE certificate directory.
+ *
+ * Found in IMAGE_DIRECTORY_ENTRY_SECURITY.
+ */
+typedef struct WIN_CERTIFICATE
+{
+ uint32_t dwLength;
+ uint16_t wRevision;
+ uint16_t wCertificateType;
+ uint8_t bCertificate[8];
+} WIN_CERTIFICATE;
+AssertCompileSize(WIN_CERTIFICATE, 16);
+typedef WIN_CERTIFICATE *PWIN_CERTIFICATE;
+typedef WIN_CERTIFICATE const *PCWIN_CERTIFICATE;
+
+/** @name WIN_CERT_REVISION_XXX - Certificate data directory revision.
+ * Used WIN_CERTIFICATE::wRevision found in the IMAGE_DIRECTORY_ENTRY_SECURITY
+ * data directory.
+ * @{ */
+#define WIN_CERT_REVISION_1_0 UINT16_C(0x0100)
+#define WIN_CERT_REVISION_2_0 UINT16_C(0x0200)
+/** @} */
+
+/** @name WIN_CERT_TYPE_XXX - Signature type.
+ * Used by WIN_CERTIFICATE::wCertificateType.
+ * @{ */
+#define WIN_CERT_TYPE_X509 UINT16_C(1)
+#define WIN_CERT_TYPE_PKCS_SIGNED_DATA UINT16_C(2)
+#define WIN_CERT_TYPE_RESERVED_1 UINT16_C(3)
+#define WIN_CERT_TYPE_TS_STACK_SIGNED UINT16_C(4)
+#define WIN_CERT_TYPE_EFI_PKCS115 UINT16_C(0x0ef0)
+#define WIN_CERT_TYPE_EFI_GUID UINT16_C(0x0ef1)
+/** @} */
+
+/** The alignment of the certificate table.
+ * @remarks Found thru signtool experiments.
+ * @note There is a copy of this in RTSignTool.cpp. */
+#define WIN_CERTIFICATE_ALIGNMENT UINT32_C(8)
+
+
+/**
+ * Debug directory.
+ *
+ * Found in IMAGE_DIRECTORY_ENTRY_DEBUG.
+ */
+typedef struct _IMAGE_DEBUG_DIRECTORY
+{
+ uint32_t Characteristics;
+ uint32_t TimeDateStamp;
+ uint16_t MajorVersion;
+ uint16_t MinorVersion;
+ uint32_t Type;
+ uint32_t SizeOfData;
+ uint32_t AddressOfRawData;
+ uint32_t PointerToRawData;
+} IMAGE_DEBUG_DIRECTORY;
+AssertCompileSize(IMAGE_DEBUG_DIRECTORY, 28);
+typedef IMAGE_DEBUG_DIRECTORY *PIMAGE_DEBUG_DIRECTORY;
+typedef IMAGE_DEBUG_DIRECTORY const *PCIMAGE_DEBUG_DIRECTORY;
+
+/** @name IMAGE_DEBUG_TYPE_XXX - Debug format types.
+ * Used by IMAGE_DEBUG_DIRECTORY::Type.
+ * @{ */
+#define IMAGE_DEBUG_TYPE_UNKNOWN UINT32_C(0x00)
+#define IMAGE_DEBUG_TYPE_COFF UINT32_C(0x01)
+#define IMAGE_DEBUG_TYPE_CODEVIEW UINT32_C(0x02)
+#define IMAGE_DEBUG_TYPE_FPO UINT32_C(0x03)
+#define IMAGE_DEBUG_TYPE_MISC UINT32_C(0x04)
+#define IMAGE_DEBUG_TYPE_EXCEPTION UINT32_C(0x05)
+#define IMAGE_DEBUG_TYPE_FIXUP UINT32_C(0x06)
+#define IMAGE_DEBUG_TYPE_OMAP_TO_SRC UINT32_C(0x07)
+#define IMAGE_DEBUG_TYPE_OMAP_FROM_SRC UINT32_C(0x08)
+#define IMAGE_DEBUG_TYPE_BORLAND UINT32_C(0x09)
+#define IMAGE_DEBUG_TYPE_RESERVED10 UINT32_C(0x0a)
+#define IMAGE_DEBUG_TYPE_CLSID UINT32_C(0x0b)
+#define IMAGE_DEBUG_TYPE_VC_FEATURE UINT32_C(0x0c)
+#define IMAGE_DEBUG_TYPE_POGO UINT32_C(0x0d)
+#define IMAGE_DEBUG_TYPE_ILTCG UINT32_C(0x0e)
+#define IMAGE_DEBUG_TYPE_MPX UINT32_C(0x0f)
+#define IMAGE_DEBUG_TYPE_REPRO UINT32_C(0x10)
+/** @} */
+
+/** @name IMAGE_DEBUG_MISC_XXX - Misc debug data type.
+ * Used by IMAGE_DEBUG_MISC::DataType.
+ * @{ */
+#define IMAGE_DEBUG_MISC_EXENAME UINT32_C(1)
+/** @} */
+
+
+/**
+ * The format of IMAGE_DEBUG_TYPE_MISC debug info.
+ */
+typedef struct _IMAGE_DEBUG_MISC
+{
+ uint32_t DataType;
+ uint32_t Length;
+ uint8_t Unicode;
+ uint8_t Reserved[3];
+ uint8_t Data[1];
+} IMAGE_DEBUG_MISC;
+AssertCompileSize(IMAGE_DEBUG_MISC, 16);
+typedef IMAGE_DEBUG_MISC *PIMAGE_DEBUG_MISC;
+typedef IMAGE_DEBUG_MISC const *PCIMAGE_DEBUG_MISC;
+
+
+
+/**
+ * The header of a .DBG file (NT4).
+ */
+typedef struct _IMAGE_SEPARATE_DEBUG_HEADER
+{
+ uint16_t Signature; /**< 0x00 */
+ uint16_t Flags; /**< 0x02 */
+ uint16_t Machine; /**< 0x04 */
+ uint16_t Characteristics; /**< 0x06 */
+ uint32_t TimeDateStamp; /**< 0x08 */
+ uint32_t CheckSum; /**< 0x0c */
+ uint32_t ImageBase; /**< 0x10 */
+ uint32_t SizeOfImage; /**< 0x14 */
+ uint32_t NumberOfSections; /**< 0x18 */
+ uint32_t ExportedNamesSize; /**< 0x1c */
+ uint32_t DebugDirectorySize; /**< 0x20 */
+ uint32_t SectionAlignment; /**< 0x24 */
+ uint32_t Reserved[2]; /**< 0x28 */
+} IMAGE_SEPARATE_DEBUG_HEADER; /* size: 0x30 */
+AssertCompileSize(IMAGE_SEPARATE_DEBUG_HEADER, 0x30);
+typedef IMAGE_SEPARATE_DEBUG_HEADER *PIMAGE_SEPARATE_DEBUG_HEADER;
+typedef IMAGE_SEPARATE_DEBUG_HEADER const *PCIMAGE_SEPARATE_DEBUG_HEADER;
+
+/** The signature of a IMAGE_SEPARATE_DEBUG_HEADER. */
+#define IMAGE_SEPARATE_DEBUG_SIGNATURE UINT16_C(0x4944)
+
+
+/**
+ * The format of IMAGE_DEBUG_TYPE_COFF debug info.
+ */
+typedef struct _IMAGE_COFF_SYMBOLS_HEADER
+{
+ uint32_t NumberOfSymbols;
+ uint32_t LvaToFirstSymbol;
+ uint32_t NumberOfLinenumbers;
+ uint32_t LvaToFirstLinenumber;
+ uint32_t RvaToFirstByteOfCode;
+ uint32_t RvaToLastByteOfCode;
+ uint32_t RvaToFirstByteOfData;
+ uint32_t RvaToLastByteOfData;
+} IMAGE_COFF_SYMBOLS_HEADER;
+AssertCompileSize(IMAGE_COFF_SYMBOLS_HEADER, 0x20);
+typedef IMAGE_COFF_SYMBOLS_HEADER *PIMAGE_COFF_SYMBOLS_HEADER;
+typedef IMAGE_COFF_SYMBOLS_HEADER const *PCIMAGE_COFF_SYMBOLS_HEADER;
+
+
+/**
+ * Line number format of IMAGE_DEBUG_TYPE_COFF debug info.
+ *
+ * @remarks This has misaligned members.
+ */
+#pragma pack(2)
+typedef struct _IMAGE_LINENUMBER
+{
+ union
+ {
+ uint32_t VirtualAddress;
+ uint32_t SymbolTableIndex;
+ } Type;
+ uint16_t Linenumber;
+} IMAGE_LINENUMBER;
+#pragma pack()
+AssertCompileSize(IMAGE_LINENUMBER, 6);
+typedef IMAGE_LINENUMBER *PIMAGE_LINENUMBER;
+typedef IMAGE_LINENUMBER const *PCIMAGE_LINENUMBER;
+
+
+/** The size of a IMAGE_SYMBOL & IMAGE_AUX_SYMBOL structure. */
+#define IMAGE_SIZE_OF_SYMBOL 18
+/** The size of a IMAGE_SYMBOL_EX & IMAGE_AUX_SYMBOL_EX structure. */
+#define IMAGE_SIZE_OF_SYMBOL_EX 20
+
+/**
+ * COFF symbol.
+ */
+#pragma pack(2)
+typedef struct _IMAGE_SYMBOL
+{
+ union
+ {
+ uint8_t ShortName[8];
+ struct
+ {
+ uint32_t Short;
+ uint32_t Long;
+ } Name;
+ uint32_t LongName[2];
+ } N;
+
+ uint32_t Value;
+ int16_t SectionNumber;
+ uint16_t Type;
+ uint8_t StorageClass;
+ uint8_t NumberOfAuxSymbols;
+} IMAGE_SYMBOL;
+#pragma pack()
+AssertCompileSize(IMAGE_SYMBOL, IMAGE_SIZE_OF_SYMBOL);
+typedef IMAGE_SYMBOL *PIMAGE_SYMBOL;
+typedef IMAGE_SYMBOL const *PCIMAGE_SYMBOL;
+
+/**
+ * COFF auxiliary symbol token defintion (whatever that is).
+ */
+#pragma pack(2)
+typedef struct IMAGE_AUX_SYMBOL_TOKEN_DEF
+{
+ uint8_t bAuxType;
+ uint8_t bReserved;
+ uint32_t SymbolTableIndex;
+ uint8_t rgbReserved[12];
+} IMAGE_AUX_SYMBOL_TOKEN_DEF;
+#pragma pack()
+AssertCompileSize(IMAGE_AUX_SYMBOL_TOKEN_DEF, IMAGE_SIZE_OF_SYMBOL);
+typedef IMAGE_AUX_SYMBOL_TOKEN_DEF *PIMAGE_AUX_SYMBOL_TOKEN_DEF;
+typedef IMAGE_AUX_SYMBOL_TOKEN_DEF const *PCIMAGE_AUX_SYMBOL_TOKEN_DEF;
+
+/**
+ * COFF auxiliary symbol.
+ */
+#pragma pack(1)
+typedef union _IMAGE_AUX_SYMBOL
+{
+ struct
+ {
+ uint32_t TagIndex;
+ union
+ {
+ struct
+ {
+ uint16_t Linenumber;
+ uint16_t Size;
+ } LnSz;
+ } Misc;
+ union
+ {
+ struct
+ {
+ uint32_t PointerToLinenumber;
+ uint32_t PointerToNextFunction;
+ } Function;
+ struct
+ {
+ uint16_t Dimension[4];
+ } Array;
+ } FcnAry;
+ uint16_t TvIndex;
+ } Sym;
+
+ struct
+ {
+ uint8_t Name[IMAGE_SIZE_OF_SYMBOL];
+ } File;
+
+ struct
+ {
+ uint32_t Length;
+ uint16_t NumberOfRelocations;
+ uint16_t NumberOfLinenumbers;
+ uint32_t CheckSum;
+ uint16_t Number;
+ uint8_t Selection;
+ uint8_t bReserved;
+ uint16_t HighNumber;
+ } Section;
+
+ IMAGE_AUX_SYMBOL_TOKEN_DEF TokenDef;
+ struct
+ {
+ uint32_t crc;
+ uint8_t rgbReserved[14];
+ } CRC;
+} IMAGE_AUX_SYMBOL;
+#pragma pack()
+AssertCompileSize(IMAGE_AUX_SYMBOL, IMAGE_SIZE_OF_SYMBOL);
+typedef IMAGE_AUX_SYMBOL *PIMAGE_AUX_SYMBOL;
+typedef IMAGE_AUX_SYMBOL const *PCIMAGE_AUX_SYMBOL;
+
+
+/**
+ * Extended COFF symbol.
+ */
+typedef struct _IMAGE_SYMBOL_EX
+{
+ union
+ {
+ uint8_t ShortName[8];
+ struct
+ {
+ uint32_t Short;
+ uint32_t Long;
+ } Name;
+ uint32_t LongName[2];
+ } N;
+
+ uint32_t Value;
+ int32_t SectionNumber; /* The difference from IMAGE_SYMBOL */
+ uint16_t Type;
+ uint8_t StorageClass;
+ uint8_t NumberOfAuxSymbols;
+} IMAGE_SYMBOL_EX;
+AssertCompileSize(IMAGE_SYMBOL_EX, IMAGE_SIZE_OF_SYMBOL_EX);
+typedef IMAGE_SYMBOL_EX *PIMAGE_SYMBOL_EX;
+typedef IMAGE_SYMBOL_EX const *PCIMAGE_SYMBOL_EX;
+
+/**
+ * Extended COFF auxiliary symbol.
+ */
+typedef union _IMAGE_AUX_SYMBOL_EX
+{
+ struct
+ {
+ uint32_t WeakDefaultSymIndex;
+ uint32_t WeakSearchType;
+ uint8_t rgbReserved[12];
+ } Sym;
+
+ struct
+ {
+ uint8_t Name[IMAGE_SIZE_OF_SYMBOL_EX];
+ } File;
+
+ struct
+ {
+ uint32_t Length;
+ uint16_t NumberOfRelocations;
+ uint16_t NumberOfLinenumbers;
+ uint32_t CheckSum;
+ uint16_t Number;
+ uint8_t Selection;
+ uint8_t bReserved;
+ uint16_t HighNumber;
+ uint8_t rgbReserved[2];
+ } Section;
+
+ IMAGE_AUX_SYMBOL_TOKEN_DEF TokenDef;
+
+ struct
+ {
+ uint32_t crc;
+ uint8_t rgbReserved[16];
+ } CRC;
+} IMAGE_AUX_SYMBOL_EX;
+AssertCompileSize(IMAGE_AUX_SYMBOL_EX, IMAGE_SIZE_OF_SYMBOL_EX);
+typedef IMAGE_AUX_SYMBOL_EX *PIMAGE_AUX_SYMBOL_EX;
+typedef IMAGE_AUX_SYMBOL_EX const *PCIMAGE_AUX_SYMBOL_EX;
+
+/** @name Special COFF section numbers.
+ * Used by IMAGE_SYMBOL::SectionNumber and IMAGE_SYMBOL_EX::SectionNumber
+ * @{ */
+#define IMAGE_SYM_UNDEFINED INT16_C(0)
+#define IMAGE_SYM_ABSOLUTE INT16_C(-1)
+#define IMAGE_SYM_DEBUG INT16_C(-2)
+/** @} */
+
+/** @name IMAGE_SYM_CLASS_XXX - COFF symbol storage classes.
+ * @{ */
+#define IMAGE_SYM_CLASS_END_OF_FUNCTION UINT8_C(0xff) /* -1 */
+#define IMAGE_SYM_CLASS_NULL UINT8_C(0)
+#define IMAGE_SYM_CLASS_AUTOMATIC UINT8_C(1)
+#define IMAGE_SYM_CLASS_EXTERNAL UINT8_C(2)
+#define IMAGE_SYM_CLASS_STATIC UINT8_C(3)
+#define IMAGE_SYM_CLASS_REGISTER UINT8_C(4)
+#define IMAGE_SYM_CLASS_EXTERNAL_DEF UINT8_C(5)
+#define IMAGE_SYM_CLASS_LABEL UINT8_C(6)
+#define IMAGE_SYM_CLASS_UNDEFINED_LABEL UINT8_C(7)
+#define IMAGE_SYM_CLASS_MEMBER_OF_STRUCT UINT8_C(8)
+#define IMAGE_SYM_CLASS_ARGUMENT UINT8_C(9)
+#define IMAGE_SYM_CLASS_STRUCT_TAG UINT8_C(10)
+#define IMAGE_SYM_CLASS_MEMBER_OF_UNION UINT8_C(11)
+#define IMAGE_SYM_CLASS_UNION_TAG UINT8_C(12)
+#define IMAGE_SYM_CLASS_TYPE_DEFINITION UINT8_C(13)
+#define IMAGE_SYM_CLASS_UNDEFINED_STATIC UINT8_C(14)
+#define IMAGE_SYM_CLASS_ENUM_TAG UINT8_C(15)
+#define IMAGE_SYM_CLASS_MEMBER_OF_ENUM UINT8_C(16)
+#define IMAGE_SYM_CLASS_REGISTER_PARAM UINT8_C(17)
+#define IMAGE_SYM_CLASS_BIT_FIELD UINT8_C(18)
+#define IMAGE_SYM_CLASS_FAR_EXTERNAL UINT8_C(68)
+#define IMAGE_SYM_CLASS_BLOCK UINT8_C(100)
+#define IMAGE_SYM_CLASS_FUNCTION UINT8_C(101)
+#define IMAGE_SYM_CLASS_END_OF_STRUCT UINT8_C(102)
+#define IMAGE_SYM_CLASS_FILE UINT8_C(103)
+#define IMAGE_SYM_CLASS_SECTION UINT8_C(104)
+#define IMAGE_SYM_CLASS_WEAK_EXTERNAL UINT8_C(105)
+#define IMAGE_SYM_CLASS_CLR_TOKEN UINT8_C(107)
+/** @} */
+
+/** @name IMAGE_SYM_TYPE_XXX - COFF symbol base types
+ * @{ */
+#define IMAGE_SYM_TYPE_NULL UINT16_C(0x0000)
+#define IMAGE_SYM_TYPE_VOID UINT16_C(0x0001)
+#define IMAGE_SYM_TYPE_CHAR UINT16_C(0x0002)
+#define IMAGE_SYM_TYPE_SHORT UINT16_C(0x0003)
+#define IMAGE_SYM_TYPE_INT UINT16_C(0x0004)
+#define IMAGE_SYM_TYPE_LONG UINT16_C(0x0005)
+#define IMAGE_SYM_TYPE_FLOAT UINT16_C(0x0006)
+#define IMAGE_SYM_TYPE_DOUBLE UINT16_C(0x0007)
+#define IMAGE_SYM_TYPE_STRUCT UINT16_C(0x0008)
+#define IMAGE_SYM_TYPE_UNION UINT16_C(0x0009)
+#define IMAGE_SYM_TYPE_ENUM UINT16_C(0x000a)
+#define IMAGE_SYM_TYPE_MOE UINT16_C(0x000b)
+#define IMAGE_SYM_TYPE_BYTE UINT16_C(0x000c)
+#define IMAGE_SYM_TYPE_WORD UINT16_C(0x000d)
+#define IMAGE_SYM_TYPE_UINT UINT16_C(0x000e)
+#define IMAGE_SYM_TYPE_DWORD UINT16_C(0x000f)
+#define IMAGE_SYM_TYPE_PCODE UINT16_C(0x8000)
+/** @} */
+
+/** @name IMAGE_SYM_DTYPE_XXX - COFF symbol complex types
+ * @{ */
+#define IMAGE_SYM_DTYPE_NULL UINT16_C(0x0)
+#define IMAGE_SYM_DTYPE_POINTER UINT16_C(0x1)
+#define IMAGE_SYM_DTYPE_FUNCTION UINT16_C(0x2)
+#define IMAGE_SYM_DTYPE_ARRAY UINT16_C(0x3)
+/** @} */
+
+/** @name COFF Symbol type masks and shift counts.
+ * @{ */
+#define N_BTMASK UINT16_C(0x000f)
+#define N_TMASK UINT16_C(0x0030)
+#define N_TMASK1 UINT16_C(0x00c0)
+#define N_TMASK2 UINT16_C(0x00f0)
+#define N_BTSHFT 4
+#define N_TSHIFT 2
+/** @} */
+
+/** @name COFF Symbol type macros.
+ * @{ */
+#define BTYPE(a_Type) ( (a_Type) & N_BTMASK )
+#define ISPTR(a_Type) ( ((a_Type) & N_TMASK) == (IMAGE_SYM_DTYPE_POINTER << N_BTSHFT) )
+#define ISFCN(a_Type) ( ((a_Type) & N_TMASK) == (IMAGE_SYM_DTYPE_FUNCTION << N_BTSHFT) )
+#define ISARY(a_Type) ( ((a_Type) & N_TMASK) == (IMAGE_SYM_DTYPE_ARRAY << N_BTSHFT) )
+#define ISTAG(a_StorageClass) ( (a_StorageClass) == IMAGE_SYM_CLASS_STRUCT_TAG \
+ || (a_StorageClass) == IMAGE_SYM_CLASS_UNION_TAG \
+ || (a_StorageClass) == IMAGE_SYM_CLASS_ENUM_TAG )
+/** @} */
+
+
+/**
+ * COFF relocation table entry.
+ *
+ * @note The size of the structure is not a multiple of the largest member
+ * (uint32_t), so odd relocation table entry members will have
+ * misaligned uint32_t members.
+ */
+#pragma pack(1)
+typedef struct _IMAGE_RELOCATION
+{
+ union
+ {
+ uint32_t VirtualAddress;
+ uint32_t RelocCount;
+ } u;
+ uint32_t SymbolTableIndex;
+ uint16_t Type;
+} IMAGE_RELOCATION;
+#pragma pack()
+/** The size of a COFF relocation entry. */
+#define IMAGE_SIZEOF_RELOCATION 10
+AssertCompileSize(IMAGE_RELOCATION, IMAGE_SIZEOF_RELOCATION);
+typedef IMAGE_RELOCATION *PIMAGE_RELOCATION;
+typedef IMAGE_RELOCATION const *PCIMAGE_RELOCATION;
+
+
+/** @name IMAGE_REL_AMD64_XXX - COFF relocations for AMD64 CPUs.
+ * Used by IMAGE_RELOCATION::Type.
+ * @{ */
+#define IMAGE_REL_AMD64_ABSOLUTE UINT16_C(0x0000)
+#define IMAGE_REL_AMD64_ADDR64 UINT16_C(0x0001)
+#define IMAGE_REL_AMD64_ADDR32 UINT16_C(0x0002)
+#define IMAGE_REL_AMD64_ADDR32NB UINT16_C(0x0003)
+#define IMAGE_REL_AMD64_REL32 UINT16_C(0x0004)
+#define IMAGE_REL_AMD64_REL32_1 UINT16_C(0x0005)
+#define IMAGE_REL_AMD64_REL32_2 UINT16_C(0x0006)
+#define IMAGE_REL_AMD64_REL32_3 UINT16_C(0x0007)
+#define IMAGE_REL_AMD64_REL32_4 UINT16_C(0x0008)
+#define IMAGE_REL_AMD64_REL32_5 UINT16_C(0x0009)
+#define IMAGE_REL_AMD64_SECTION UINT16_C(0x000a)
+#define IMAGE_REL_AMD64_SECREL UINT16_C(0x000b)
+#define IMAGE_REL_AMD64_SECREL7 UINT16_C(0x000c)
+#define IMAGE_REL_AMD64_TOKEN UINT16_C(0x000d)
+#define IMAGE_REL_AMD64_SREL32 UINT16_C(0x000e)
+#define IMAGE_REL_AMD64_PAIR UINT16_C(0x000f)
+#define IMAGE_REL_AMD64_SSPAN32 UINT16_C(0x0010)
+/** @} */
+
+/** @name ARM IMAGE_REL_ARM_XXX - COFF relocations for ARM CPUs.
+ * Used by IMAGE_RELOCATION::Type.
+ * @{ */
+#define IMAGE_REL_ARM_ABSOLUTE UINT16_C(0x0000)
+#define IMAGE_REL_ARM_ADDR32 UINT16_C(0x0001)
+#define IMAGE_REL_ARM_ADDR32NB UINT16_C(0x0002)
+#define IMAGE_REL_ARM_BRANCH24 UINT16_C(0x0003)
+#define IMAGE_REL_ARM_BRANCH11 UINT16_C(0x0004)
+#define IMAGE_REL_ARM_TOKEN UINT16_C(0x0005)
+#define IMAGE_REL_ARM_BLX24 UINT16_C(0x0008)
+#define IMAGE_REL_ARM_BLX11 UINT16_C(0x0009)
+#define IMAGE_REL_ARM_SECTION UINT16_C(0x000e)
+#define IMAGE_REL_ARM_SECREL UINT16_C(0x000f)
+#define IMAGE_REL_ARM_MOV32A UINT16_C(0x0010)
+#define IMAGE_REL_ARM_MOV32T UINT16_C(0x0011)
+#define IMAGE_REL_ARM_BRANCH20T UINT16_C(0x0012)
+#define IMAGE_REL_ARM_BRANCH24T UINT16_C(0x0014)
+#define IMAGE_REL_ARM_BLX23T UINT16_C(0x0015)
+/** @} */
+
+/** @name IMAGE_REL_ARM64_XXX - COFF relocations for ARMv8 CPUs (64-bit).
+ * Used by IMAGE_RELOCATION::Type.
+ * @{ */
+#define IMAGE_REL_ARM64_ABSOLUTE UINT16_C(0x0000)
+#define IMAGE_REL_ARM64_ADDR32 UINT16_C(0x0001)
+#define IMAGE_REL_ARM64_ADDR32NB UINT16_C(0x0002)
+#define IMAGE_REL_ARM64_BRANCH26 UINT16_C(0x0003)
+#define IMAGE_REL_ARM64_PAGEBASE_REL21 UINT16_C(0x0004)
+#define IMAGE_REL_ARM64_REL21 UINT16_C(0x0005)
+#define IMAGE_REL_ARM64_PAGEOFFSET_12A UINT16_C(0x0006)
+#define IMAGE_REL_ARM64_PAGEOFFSET_12L UINT16_C(0x0007)
+#define IMAGE_REL_ARM64_SECREL UINT16_C(0x0008)
+#define IMAGE_REL_ARM64_SECREL_LOW12A UINT16_C(0x0009)
+#define IMAGE_REL_ARM64_SECREL_HIGH12A UINT16_C(0x000a)
+#define IMAGE_REL_ARM64_SECREL_LOW12L UINT16_C(0x000b)
+#define IMAGE_REL_ARM64_TOKEN UINT16_C(0x000c)
+#define IMAGE_REL_ARM64_SECTION UINT16_C(0x000d)
+#define IMAGE_REL_ARM64_ADDR64 UINT16_C(0x000e)
+/** @} */
+
+/** @name IMAGE_REL_SH3_XXX - COFF relocation for Hitachi SuperH CPUs.
+ * Used by IMAGE_RELOCATION::Type.
+ * @{ */
+#define IMAGE_REL_SH3_ABSOLUTE UINT16_C(0x0000)
+#define IMAGE_REL_SH3_DIRECT16 UINT16_C(0x0001)
+#define IMAGE_REL_SH3_DIRECT32 UINT16_C(0x0002)
+#define IMAGE_REL_SH3_DIRECT8 UINT16_C(0x0003)
+#define IMAGE_REL_SH3_DIRECT8_WORD UINT16_C(0x0004)
+#define IMAGE_REL_SH3_DIRECT8_LONG UINT16_C(0x0005)
+#define IMAGE_REL_SH3_DIRECT4 UINT16_C(0x0006)
+#define IMAGE_REL_SH3_DIRECT4_WORD UINT16_C(0x0007)
+#define IMAGE_REL_SH3_DIRECT4_LONG UINT16_C(0x0008)
+#define IMAGE_REL_SH3_PCREL8_WORD UINT16_C(0x0009)
+#define IMAGE_REL_SH3_PCREL8_LONG UINT16_C(0x000a)
+#define IMAGE_REL_SH3_PCREL12_WORD UINT16_C(0x000b)
+#define IMAGE_REL_SH3_STARTOF_SECTION UINT16_C(0x000c)
+#define IMAGE_REL_SH3_SIZEOF_SECTION UINT16_C(0x000d)
+#define IMAGE_REL_SH3_SECTION UINT16_C(0x000e)
+#define IMAGE_REL_SH3_SECREL UINT16_C(0x000f)
+#define IMAGE_REL_SH3_DIRECT32_NB UINT16_C(0x0010)
+#define IMAGE_REL_SH3_GPREL4_LONG UINT16_C(0x0011)
+#define IMAGE_REL_SH3_TOKEN UINT16_C(0x0012)
+#define IMAGE_REL_SHM_PCRELPT UINT16_C(0x0013)
+#define IMAGE_REL_SHM_REFLO UINT16_C(0x0014)
+#define IMAGE_REL_SHM_REFHALF UINT16_C(0x0015)
+#define IMAGE_REL_SHM_RELLO UINT16_C(0x0016)
+#define IMAGE_REL_SHM_RELHALF UINT16_C(0x0017)
+#define IMAGE_REL_SHM_PAIR UINT16_C(0x0018)
+#define IMAGE_REL_SHM_NOMODE UINT16_C(0x8000)
+/** @} */
+
+/** @name IMAGE_REL_PPC_XXX - COFF relocations for IBM PowerPC CPUs.
+ * Used by IMAGE_RELOCATION::Type.
+ * @{ */
+#define IMAGE_REL_PPC_ABSOLUTE UINT16_C(0x0000)
+#define IMAGE_REL_PPC_ADDR64 UINT16_C(0x0001)
+#define IMAGE_REL_PPC_ADDR32 UINT16_C(0x0002)
+#define IMAGE_REL_PPC_ADDR24 UINT16_C(0x0003)
+#define IMAGE_REL_PPC_ADDR16 UINT16_C(0x0004)
+#define IMAGE_REL_PPC_ADDR14 UINT16_C(0x0005)
+#define IMAGE_REL_PPC_REL24 UINT16_C(0x0006)
+#define IMAGE_REL_PPC_REL14 UINT16_C(0x0007)
+#define IMAGE_REL_PPC_ADDR32NB UINT16_C(0x000a)
+#define IMAGE_REL_PPC_SECREL UINT16_C(0x000b)
+#define IMAGE_REL_PPC_SECTION UINT16_C(0x000c)
+#define IMAGE_REL_PPC_SECREL16 UINT16_C(0x000f)
+#define IMAGE_REL_PPC_REFHI UINT16_C(0x0010)
+#define IMAGE_REL_PPC_REFLO UINT16_C(0x0011)
+#define IMAGE_REL_PPC_PAIR UINT16_C(0x0012)
+#define IMAGE_REL_PPC_SECRELLO UINT16_C(0x0013)
+#define IMAGE_REL_PPC_GPREL UINT16_C(0x0015)
+#define IMAGE_REL_PPC_TOKEN UINT16_C(0x0016)
+/** @} */
+
+/** @name IMAGE_REL_I386_XXX - COFF relocations for x86 CPUs.
+ * Used by IMAGE_RELOCATION::Type.
+ * @{ */
+#define IMAGE_REL_I386_ABSOLUTE UINT16_C(0x0000)
+#define IMAGE_REL_I386_DIR16 UINT16_C(0x0001)
+#define IMAGE_REL_I386_REL16 UINT16_C(0x0002)
+#define IMAGE_REL_I386_DIR32 UINT16_C(0x0006)
+#define IMAGE_REL_I386_DIR32NB UINT16_C(0x0007)
+#define IMAGE_REL_I386_SEG12 UINT16_C(0x0009)
+#define IMAGE_REL_I386_SECTION UINT16_C(0x000A)
+#define IMAGE_REL_I386_SECREL UINT16_C(0x000B)
+#define IMAGE_REL_I386_TOKEN UINT16_C(0x000C)
+#define IMAGE_REL_I386_SECREL7 UINT16_C(0x000D)
+#define IMAGE_REL_I386_REL32 UINT16_C(0x0014)
+/** @} */
+
+/** @name IMAGE_REL_IA64_XXX - COFF relocations for "Itanic" CPUs.
+ * @{ */
+#define IMAGE_REL_IA64_ABSOLUTE UINT16_C(0x0000)
+#define IMAGE_REL_IA64_IMM14 UINT16_C(0x0001)
+#define IMAGE_REL_IA64_IMM22 UINT16_C(0x0002)
+#define IMAGE_REL_IA64_IMM64 UINT16_C(0x0003)
+#define IMAGE_REL_IA64_DIR32 UINT16_C(0x0004)
+#define IMAGE_REL_IA64_DIR64 UINT16_C(0x0005)
+#define IMAGE_REL_IA64_PCREL21B UINT16_C(0x0006)
+#define IMAGE_REL_IA64_PCREL21M UINT16_C(0x0007)
+#define IMAGE_REL_IA64_PCREL21F UINT16_C(0x0008)
+#define IMAGE_REL_IA64_GPREL22 UINT16_C(0x0009)
+#define IMAGE_REL_IA64_LTOFF22 UINT16_C(0x000a)
+#define IMAGE_REL_IA64_SECTION UINT16_C(0x000b)
+#define IMAGE_REL_IA64_SECREL22 UINT16_C(0x000c)
+#define IMAGE_REL_IA64_SECREL64I UINT16_C(0x000d)
+#define IMAGE_REL_IA64_SECREL32 UINT16_C(0x000e)
+#define IMAGE_REL_IA64_DIR32NB UINT16_C(0x0010)
+#define IMAGE_REL_IA64_SREL14 UINT16_C(0x0011)
+#define IMAGE_REL_IA64_SREL22 UINT16_C(0x0012)
+#define IMAGE_REL_IA64_SREL32 UINT16_C(0x0013)
+#define IMAGE_REL_IA64_UREL32 UINT16_C(0x0014)
+#define IMAGE_REL_IA64_PCREL60X UINT16_C(0x0015)
+#define IMAGE_REL_IA64_PCREL60B UINT16_C(0x0016)
+#define IMAGE_REL_IA64_PCREL60F UINT16_C(0x0017)
+#define IMAGE_REL_IA64_PCREL60I UINT16_C(0x0018)
+#define IMAGE_REL_IA64_PCREL60M UINT16_C(0x0019)
+#define IMAGE_REL_IA64_IMMGPREL64 UINT16_C(0x001a)
+#define IMAGE_REL_IA64_TOKEN UINT16_C(0x001b)
+#define IMAGE_REL_IA64_GPREL32 UINT16_C(0x001c)
+#define IMAGE_REL_IA64_ADDEND UINT16_C(0x001f)
+/** @} */
+
+/** @name IMAGE_REL_MIPS_XXX - COFF relocations for MIPS CPUs.
+ * Used by IMAGE_RELOCATION::Type.
+ * @{ */
+#define IMAGE_REL_MIPS_ABSOLUTE UINT16_C(0x0000)
+#define IMAGE_REL_MIPS_REFHALF UINT16_C(0x0001)
+#define IMAGE_REL_MIPS_REFWORD UINT16_C(0x0002)
+#define IMAGE_REL_MIPS_JMPADDR UINT16_C(0x0003)
+#define IMAGE_REL_MIPS_REFHI UINT16_C(0x0004)
+#define IMAGE_REL_MIPS_REFLO UINT16_C(0x0005)
+#define IMAGE_REL_MIPS_GPREL UINT16_C(0x0006)
+#define IMAGE_REL_MIPS_LITERAL UINT16_C(0x0007)
+#define IMAGE_REL_MIPS_SECTION UINT16_C(0x000a)
+#define IMAGE_REL_MIPS_SECREL UINT16_C(0x000b)
+#define IMAGE_REL_MIPS_SECRELLO UINT16_C(0x000c)
+#define IMAGE_REL_MIPS_SECRELHI UINT16_C(0x000d)
+#define IMAGE_REL_MIPS_JMPADDR16 UINT16_C(0x0010)
+#define IMAGE_REL_MIPS_REFWORDNB UINT16_C(0x0022)
+#define IMAGE_REL_MIPS_PAIR UINT16_C(0x0025)
+/** @} */
+
+/** @name IMAGE_REL_M32R_XXX - COFF relocations for Mitsubishi M32R CPUs.
+ * Used by IMAGE_RELOCATION::Type.
+ * @{ */
+#define IMAGE_REL_M32R_ABSOLUTE UINT16_C(0x0000)
+#define IMAGE_REL_M32R_ADDR32 UINT16_C(0x0001)
+#define IMAGE_REL_M32R_ADDR32NB UINT16_C(0x0002)
+#define IMAGE_REL_M32R_ADDR24 UINT16_C(0x0003)
+#define IMAGE_REL_M32R_GPREL16 UINT16_C(0x0004)
+#define IMAGE_REL_M32R_PCREL24 UINT16_C(0x0005)
+#define IMAGE_REL_M32R_PCREL16 UINT16_C(0x0006)
+#define IMAGE_REL_M32R_PCREL8 UINT16_C(0x0007)
+#define IMAGE_REL_M32R_REFHALF UINT16_C(0x0008)
+#define IMAGE_REL_M32R_REFHI UINT16_C(0x0009)
+#define IMAGE_REL_M32R_REFLO UINT16_C(0x000a)
+#define IMAGE_REL_M32R_PAIR UINT16_C(0x000b)
+#define IMAGE_REL_M32R_SECTION UINT16_C(0x000c)
+#define IMAGE_REL_M32R_SECREL UINT16_C(0x000d)
+#define IMAGE_REL_M32R_TOKEN UINT16_C(0x000e)
+/** @} */
+
+
+/** @} */
+
+#endif /* !IPRT_INCLUDED_formats_pecoff_h */
+
diff --git a/include/iprt/formats/riff.h b/include/iprt/formats/riff.h
new file mode 100644
index 00000000..91de3bec
--- /dev/null
+++ b/include/iprt/formats/riff.h
@@ -0,0 +1,247 @@
+/* $Id: riff.h $ */
+/** @file
+ * IPRT - Resource Interchange File Format (RIFF), WAVE, ++.
+ */
+
+/*
+ * Copyright (C) 2021-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_formats_riff_h
+#define IPRT_INCLUDED_formats_riff_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+#include <iprt/assertcompile.h>
+
+
+/** @defgroup grp_rt_formats_riff RIFF & WAVE structures and definitions
+ * @ingroup grp_rt_formats
+ * @{
+ */
+
+/**
+ * Resource interchange file format (RIFF) file header.
+ */
+typedef struct RTRIFFHDR
+{
+ /** The 'RIFF' magic (RTRIFFHDR_MAGIC). */
+ uint32_t uMagic;
+ /** The file size. */
+ uint32_t cbFile;
+ /** The file type. */
+ uint32_t uFileType;
+} RTRIFFHDR;
+AssertCompileSize(RTRIFFHDR, 12);
+/** Pointer to a RIFF file header. */
+typedef RTRIFFHDR *PRTRIFFHDR;
+
+/** Magic value for RTRIFFHDR::uMagic ('RIFF'). */
+#define RTRIFFHDR_MAGIC RT_BE2H_U32_C(0x52494646)
+
+/** @name RIFF file types (RTRIFFHDR::uFileType)
+ * @{ */
+/** RIFF file type: WAVE (audio) */
+#define RTRIFF_FILE_TYPE_WAVE RT_BE2H_U32_C(0x57415645)
+/** RIFF file type: AVI (video) */
+#define RTRIFF_FILE_TYPE_AVI RT_BE2H_U32_C(0x41564920)
+/** @} */
+
+/**
+ * A RIFF chunk.
+ */
+typedef struct RTRIFFCHUNK
+{
+ /** The chunk magic (four character code). */
+ uint32_t uMagic;
+ /** The size of the chunk minus this header. */
+ uint32_t cbChunk;
+} RTRIFFCHUNK;
+AssertCompileSize(RTRIFFCHUNK, 8);
+/** Pointer to a RIFF chunk. */
+typedef RTRIFFCHUNK *PRTRIFFCHUNK;
+
+/**
+ * A RIFF list.
+ */
+typedef struct RTRIFFLIST
+{
+ /** The list indicator (RTRIFFLIST_MAGIC). */
+ uint32_t uMagic;
+ /** The size of the chunk minus this header. */
+ uint32_t cbChunk;
+ /** The list type (four character code). */
+ uint32_t uListType;
+} RTRIFFLIST;
+AssertCompileSize(RTRIFFLIST, 12);
+/** Pointer to a RIFF list. */
+typedef RTRIFFLIST *PRTRIFFLIST;
+/** Magic value for RTRIFFLIST::uMagic ('LIST'). */
+#define RTRIFFLIST_MAGIC RT_BE2H_U32_C(0x4c495354)
+
+/** Generic 'INFO' list type. */
+#define RTRIFFLIST_TYPE_INFO RT_BE2H_U32_C(0x494e464f)
+
+
+/**
+ * Wave file format (WAVEFORMATEX w/o cbSize).
+ * @see RTRIFFWAVEFMTCHUNK.
+ */
+typedef struct RTRIFFWAVEFMT
+{
+ /** Audio format tag. */
+ uint16_t uFormatTag;
+ /** Number of channels. */
+ uint16_t cChannels;
+ /** Sample rate. */
+ uint32_t uHz;
+ /** Byte rate (= uHz * cChannels * cBitsPerSample / 8) */
+ uint32_t cbRate;
+ /** Frame size (aka block alignment). */
+ uint16_t cbFrame;
+ /** Number of bits per sample. */
+ uint16_t cBitsPerSample;
+} RTRIFFWAVEFMT;
+AssertCompileSize(RTRIFFWAVEFMT, 16);
+/** Pointer to a wave file format structure. */
+typedef RTRIFFWAVEFMT *PRTRIFFWAVEFMT;
+
+/**
+ * Extensible wave file format (WAVEFORMATEXTENSIBLE).
+ * @see RTRIFFWAVEFMTEXTCHUNK.
+ */
+#pragma pack(4) /* Override the uint64_t effect from RTUUID, so we can safely put it after RTRIFFHDR in a structure. */
+typedef struct RTRIFFWAVEFMTEXT
+{
+ /** The coreformat structure. */
+ RTRIFFWAVEFMT Core;
+ /** Number of bytes of extra information after the core. */
+ uint16_t cbExtra;
+ /** Number of valid bits per sample. */
+ uint16_t cValidBitsPerSample;
+ /** The channel mask. */
+ uint32_t fChannelMask;
+ /** The GUID of the sub-format. */
+ RTUUID SubFormat;
+} RTRIFFWAVEFMTEXT;
+#pragma pack()
+AssertCompileSize(RTRIFFWAVEFMTEXT, 16+2+22);
+/** Pointer to an extensible wave file format structure. */
+typedef RTRIFFWAVEFMTEXT *PRTRIFFWAVEFMTEXT;
+
+/** RTRIFFWAVEFMT::uFormatTag value for PCM (WDK: WAVE_FORMAT_PCM). */
+#define RTRIFFWAVEFMT_TAG_PCM UINT16_C(0x0001)
+/** RTRIFFWAVEFMT::uFormatTag value for extensible wave files (WDK: WAVE_FORMAT_EXTENSIBLE). */
+#define RTRIFFWAVEFMT_TAG_EXTENSIBLE UINT16_C(0xfffe)
+
+/** Typical RTRIFFWAVEFMTEXT::cbExtra value (min). */
+#define RTRIFFWAVEFMTEXT_EXTRA_SIZE UINT16_C(22)
+
+/** @name Channel IDs for RTRIFFWAVEFMTEXT::fChannelMask.
+ * @{ */
+#define RTRIFFWAVEFMTEXT_CH_ID_FL RT_BIT_32(0) /**< Front left. */
+#define RTRIFFWAVEFMTEXT_CH_ID_FR RT_BIT_32(1) /**< Front right. */
+#define RTRIFFWAVEFMTEXT_CH_ID_FC RT_BIT_32(2) /**< Front center */
+#define RTRIFFWAVEFMTEXT_CH_ID_LFE RT_BIT_32(3) /**< Low frequency */
+#define RTRIFFWAVEFMTEXT_CH_ID_BL RT_BIT_32(4) /**< Back left. */
+#define RTRIFFWAVEFMTEXT_CH_ID_BR RT_BIT_32(5) /**< Back right. */
+#define RTRIFFWAVEFMTEXT_CH_ID_FLC RT_BIT_32(6) /**< Front left of center. */
+#define RTRIFFWAVEFMTEXT_CH_ID_FLR RT_BIT_32(7) /**< Front right of center. */
+#define RTRIFFWAVEFMTEXT_CH_ID_BC RT_BIT_32(8) /**< Back center. */
+#define RTRIFFWAVEFMTEXT_CH_ID_SL RT_BIT_32(9) /**< Side left. */
+#define RTRIFFWAVEFMTEXT_CH_ID_SR RT_BIT_32(10) /**< Side right. */
+#define RTRIFFWAVEFMTEXT_CH_ID_TC RT_BIT_32(11) /**< Top center. */
+#define RTRIFFWAVEFMTEXT_CH_ID_TFL RT_BIT_32(12) /**< Top front left. */
+#define RTRIFFWAVEFMTEXT_CH_ID_TFC RT_BIT_32(13) /**< Top front center. */
+#define RTRIFFWAVEFMTEXT_CH_ID_TFR RT_BIT_32(14) /**< Top front right. */
+#define RTRIFFWAVEFMTEXT_CH_ID_TBL RT_BIT_32(15) /**< Top back left. */
+#define RTRIFFWAVEFMTEXT_CH_ID_TBC RT_BIT_32(16) /**< Top back center. */
+#define RTRIFFWAVEFMTEXT_CH_ID_TBR RT_BIT_32(17) /**< Top back right. */
+/** @} */
+
+/** RTRIFFWAVEFMTEXT::SubFormat UUID string for PCM. */
+#define RTRIFFWAVEFMTEXT_SUBTYPE_PCM "00000001-0000-0010-8000-00aa00389b71"
+
+
+/**
+ * Wave file format chunk.
+ */
+typedef struct RTRIFFWAVEFMTCHUNK
+{
+ /** Chunk header with RTRIFFWAVEFMT_MAGIC as magic. */
+ RTRIFFCHUNK Chunk;
+ /** The wave file format. */
+ RTRIFFWAVEFMT Data;
+} RTRIFFWAVEFMTCHUNK;
+AssertCompileSize(RTRIFFWAVEFMTCHUNK, 8+16);
+/** Pointer to a wave file format chunk. */
+typedef RTRIFFWAVEFMTCHUNK *PRTRIFFWAVEFMTCHUNK;
+/** Magic value for RTRIFFWAVEFMTCHUNK and RTRIFFWAVEFMTEXTCHUNK ('fmt '). */
+#define RTRIFFWAVEFMT_MAGIC RT_BE2H_U32_C(0x666d7420)
+
+/**
+ * Extensible wave file format chunk.
+ */
+typedef struct RTRIFFWAVEFMTEXTCHUNK
+{
+ /** Chunk header with RTRIFFWAVEFMT_MAGIC as magic. */
+ RTRIFFCHUNK Chunk;
+ /** The wave file format. */
+ RTRIFFWAVEFMTEXT Data;
+} RTRIFFWAVEFMTEXTCHUNK;
+AssertCompileSize(RTRIFFWAVEFMTEXTCHUNK, 8+16+2+22);
+/** Pointer to a wave file format chunk. */
+typedef RTRIFFWAVEFMTEXTCHUNK *PRTRIFFWAVEFMTEXTCHUNK;
+
+
+/**
+ * Wave file data chunk.
+ */
+typedef struct RTRIFFWAVEDATACHUNK
+{
+ /** Chunk header with RTRIFFWAVEFMT_MAGIC as magic. */
+ RTRIFFCHUNK Chunk;
+ /** Variable sized sample data. */
+ uint8_t abData[RT_FLEXIBLE_ARRAY_IN_NESTED_UNION];
+} RTRIFFWAVEDATACHUNK;
+
+/** Magic value for RTRIFFWAVEFMT::uMagic ('data'). */
+#define RTRIFFWAVEDATACHUNK_MAGIC RT_BE2H_U32_C(0x64617461)
+
+
+/** Magic value padding chunks ('PAD '). */
+#define RTRIFFPADCHUNK_MAGIC RT_BE2H_U32_C(0x50414420)
+
+/** @} */
+
+#endif /* !IPRT_INCLUDED_formats_riff_h */
+
diff --git a/include/iprt/formats/tpm.h b/include/iprt/formats/tpm.h
new file mode 100644
index 00000000..454a2d4f
--- /dev/null
+++ b/include/iprt/formats/tpm.h
@@ -0,0 +1,313 @@
+/* $Id: tpm.h $ */
+/** @file
+ * IPRT, TPM common definitions (this is actually a protocol and not a format).
+ */
+
+/*
+ * Copyright (C) 2021-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_formats_tpm_h
+#define IPRT_INCLUDED_formats_tpm_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/asm.h>
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+#include <iprt/assertcompile.h>
+#include <iprt/string.h>
+
+
+/**
+ * TPM request header (everything big endian).
+ */
+#pragma pack(1)
+typedef struct TPMREQHDR
+{
+ /** The tag for this request. */
+ uint16_t u16Tag;
+ /** Size of the request in bytes. */
+ uint32_t cbReq;
+ /** The request ordinal to execute. */
+ uint32_t u32Ordinal;
+} TPMREQHDR;
+#pragma pack()
+AssertCompileSize(TPMREQHDR, 2 + 4 + 4);
+/** Pointer to a TPM request header. */
+typedef TPMREQHDR *PTPMREQHDR;
+/** Pointer to a const TPM request header. */
+typedef const TPMREQHDR *PCTPMREQHDR;
+
+
+/** @name TPM 1.2 request tags
+ * @{ */
+/** Command with no authentication. */
+#define TPM_TAG_RQU_COMMAND UINT16_C(0x00c1)
+/** An authenticated command with one authentication handle. */
+#define TPM_TAG_RQU_AUTH1_COMMAND UINT16_C(0x00c2)
+/** An authenticated command with two authentication handles. */
+#define TPM_TAG_RQU_AUTH2_COMMAND UINT16_C(0x00c3)
+/** @} */
+
+
+/** @name TPM 2.0 request/response tags
+ * @{ */
+/** Command with no associated session. */
+#define TPM2_ST_NO_SESSIONS UINT16_C(0x8001)
+/** Command with an associated session. */
+#define TPM2_ST_SESSIONS UINT16_C(0x8002)
+/** @} */
+
+
+/** @name TPM 1.2 request ordinals.
+ * @{ */
+/** Perform a full self test. */
+#define TPM_ORD_SELFTESTFULL UINT32_C(80)
+/** Continue the selftest. */
+#define TPM_ORD_CONTINUESELFTEST UINT32_C(83)
+/** Return the test result. */
+#define TPM_ORD_GETTESTRESULT UINT32_C(84)
+/** Get a capability. */
+#define TPM_ORD_GETCAPABILITY UINT32_C(101)
+/** @} */
+
+
+/** @name TPM 2.0 command codes.
+ * @{ */
+/** Get a capability. */
+#define TPM2_CC_GET_CAPABILITY UINT32_C(378)
+/** @} */
+
+
+/** @name Defines related to TPM_ORD_GETCAPABILITY.
+ * @{ */
+/** Return a TPM related property. */
+#define TPM_CAP_PROPERTY UINT32_C(5)
+
+/** Returns the size of the input buffer. */
+#define TPM_CAP_PROP_INPUT_BUFFER UINT32_C(0x124)
+
+/**
+ * TPM_ORD_GETCAPABILITY request.
+ */
+#pragma pack(1)
+typedef struct TPMREQGETCAPABILITY
+{
+ /** Request header. */
+ TPMREQHDR Hdr;
+ /** The capability group to query. */
+ uint32_t u32Cap;
+ /** Length of the capability. */
+ uint32_t u32Length;
+ /** The sub capability to query. */
+ uint32_t u32SubCap;
+} TPMREQGETCAPABILITY;
+#pragma pack()
+/** Pointer to a TPM_ORD_GETCAPABILITY request. */
+typedef TPMREQGETCAPABILITY *PTPMREQGETCAPABILITY;
+/** Pointer to a const TPM_ORD_GETCAPABILITY request. */
+typedef const TPMREQGETCAPABILITY *PCTPMREQGETCAPABILITY;
+/** @} */
+
+
+/** @name Defines related to TPM2_CC_GET_CAPABILITY.
+ * @{ */
+/** Return a TPM related property. */
+#define TPM2_CAP_TPM_PROPERTIES UINT32_C(6)
+
+/** Returns the size of the input buffer. */
+#define TPM2_PT_INPUT_BUFFER UINT32_C(0x10d)
+
+/**
+ * TPM2_CC_GET_CAPABILITY request.
+ */
+#pragma pack(1)
+typedef struct TPM2REQGETCAPABILITY
+{
+ /** Request header. */
+ TPMREQHDR Hdr;
+ /** The capability group to query. */
+ uint32_t u32Cap;
+ /** Property to query. */
+ uint32_t u32Property;
+ /** Number of values to return. */
+ uint32_t u32Count;
+} TPM2REQGETCAPABILITY;
+#pragma pack()
+/** Pointer to a TPM2_CC_GET_CAPABILITY request. */
+typedef TPM2REQGETCAPABILITY *PTPM2REQGETCAPABILITY;
+/** Pointer to a const TPM2_CC_GET_CAPABILITY request. */
+typedef const TPM2REQGETCAPABILITY *PCTPM2REQGETCAPABILITY;
+/** @} */
+
+
+/**
+ * TPM response header (everything big endian).
+ */
+#pragma pack(1)
+typedef struct TPMRESPHDR
+{
+ /** The tag for this request. */
+ uint16_t u16Tag;
+ /** Size of the response in bytes. */
+ uint32_t cbResp;
+ /** The error code for the response. */
+ uint32_t u32ErrCode;
+} TPMRESPHDR;
+#pragma pack()
+AssertCompileSize(TPMRESPHDR, 2 + 4 + 4);
+/** Pointer to a TPM response header. */
+typedef TPMRESPHDR *PTPMRESPHDR;
+/** Pointer to a const TPM response header. */
+typedef const TPMRESPHDR *PCTPMRESPHDR;
+
+
+/** @name TPM 1.2 response tags
+ * @{ */
+/** A response from a command with no authentication. */
+#define TPM_TAG_RSP_COMMAND UINT16_C(0x00c4)
+/** An authenticated response with one authentication handle. */
+#define TPM_TAG_RSP_AUTH1_COMMAND UINT16_C(0x00c5)
+/** An authenticated response with two authentication handles. */
+#define TPM_TAG_RSP_AUTH2_COMMAND UINT16_C(0x00c6)
+/** @} */
+
+
+/** @name TPM status codes.
+ * @{ */
+#ifndef TPM_SUCCESS
+/** Request executed successfully. */
+# define TPM_SUCCESS UINT32_C(0)
+#endif
+#ifndef TPM_AUTHFAIL
+/** Authentication failed. */
+# define TPM_AUTHFAIL UINT32_C(1)
+#endif
+#ifndef TPM_BADINDEX
+/** An index is malformed. */
+# define TPM_BADINDEX UINT32_C(2)
+#endif
+#ifndef TPM_BAD_PARAMETER
+/** A request parameter is invalid. */
+# define TPM_BAD_PARAMETER UINT32_C(3)
+#endif
+#ifndef TPM_FAIL
+/** The TPM failed to execute the request. */
+# define TPM_FAIL UINT32_C(9)
+#endif
+/** @todo Extend as need arises. */
+/** @} */
+
+
+/* Some inline helpers to account for the unaligned members of the request and response headers. */
+
+/**
+ * Returns the request tag of the given TPM request header.
+ *
+ * @returns TPM request tag in bytes.
+ * @param pTpmReqHdr Pointer to the TPM request header.
+ */
+DECLINLINE(uint16_t) RTTpmReqGetTag(PCTPMREQHDR pTpmReqHdr)
+{
+ return RT_BE2H_U16(pTpmReqHdr->u16Tag);
+}
+
+
+/**
+ * Returns the request size of the given TPM request header.
+ *
+ * @returns TPM request size in bytes.
+ * @param pTpmReqHdr Pointer to the TPM request header.
+ */
+DECLINLINE(size_t) RTTpmReqGetSz(PCTPMREQHDR pTpmReqHdr)
+{
+ uint32_t cbReq;
+ memcpy(&cbReq, &pTpmReqHdr->cbReq, sizeof(pTpmReqHdr->cbReq));
+ return RT_BE2H_U32(cbReq);
+}
+
+
+/**
+ * Returns the request ordinal of the given TPM request header.
+ *
+ * @returns TPM request ordinal in bytes.
+ * @param pTpmReqHdr Pointer to the TPM request header.
+ */
+DECLINLINE(uint32_t) RTTpmReqGetOrdinal(PCTPMREQHDR pTpmReqHdr)
+{
+ uint32_t u32Ordinal;
+ memcpy(&u32Ordinal, &pTpmReqHdr->u32Ordinal, sizeof(pTpmReqHdr->u32Ordinal));
+ return RT_BE2H_U32(u32Ordinal);
+}
+
+
+/**
+ * Returns the response tag of the given TPM response header.
+ *
+ * @returns TPM request tag in bytes.
+ * @param pTpmRespHdr Pointer to the TPM response header.
+ */
+DECLINLINE(uint16_t) RTTpmRespGetTag(PCTPMRESPHDR pTpmRespHdr)
+{
+ return RT_BE2H_U16(pTpmRespHdr->u16Tag);
+}
+
+
+/**
+ * Returns the response size included in the given TPM response header.
+ *
+ * @returns TPM response size in bytes.
+ * @param pTpmRespHdr Pointer to the TPM response header.
+ */
+DECLINLINE(size_t) RTTpmRespGetSz(PCTPMRESPHDR pTpmRespHdr)
+{
+ uint32_t cbResp;
+ memcpy(&cbResp, &pTpmRespHdr->cbResp, sizeof(pTpmRespHdr->cbResp));
+ return RT_BE2H_U32(cbResp);
+}
+
+
+/**
+ * Returns the error code of the given TPM response header.
+ *
+ * @returns TPM response error code.
+ * @param pTpmRespHdr Pointer to the TPM response header.
+ */
+DECLINLINE(uint32_t) RTTpmRespGetErrCode(PCTPMRESPHDR pTpmRespHdr)
+{
+ uint32_t u32ErrCode;
+ memcpy(&u32ErrCode, &pTpmRespHdr->u32ErrCode, sizeof(pTpmRespHdr->u32ErrCode));
+ return RT_BE2H_U32(u32ErrCode);
+}
+
+#endif /* !IPRT_INCLUDED_formats_tpm_h */
+
diff --git a/include/iprt/formats/tracelog.h b/include/iprt/formats/tracelog.h
new file mode 100644
index 00000000..8b20e925
--- /dev/null
+++ b/include/iprt/formats/tracelog.h
@@ -0,0 +1,239 @@
+/* $Id: tracelog.h $ */
+/** @file
+ * IPRT, Binary trace log format.
+ */
+
+/*
+ * Copyright (C) 2018-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_formats_tracelog_h
+#define IPRT_INCLUDED_formats_tracelog_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/assert.h>
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+
+
+/** @defgroup grp_rt_formats_tracelog Binary trace log structures and definitions
+ * @ingroup grp_rt_formats
+ * @{
+ */
+
+/** Size of the record magic in bytes. */
+#define TRACELOG_MAGIC_SZ 8
+
+/**
+ * Trace log identification and options header.
+ */
+typedef struct TRACELOGHDR
+{
+ /** Identifiaction magic. */
+ uint8_t szMagic[8];
+ /** Endianess indicator. */
+ uint32_t u32Endianess;
+ /** File version indicator. */
+ uint32_t u32Version;
+ /** File flags (MBZ for now). */
+ uint32_t fFlags;
+ /** Size of the trace log description in bytes following this header. */
+ uint32_t cbStrDesc;
+ /** Size of a pointer item in bytes. */
+ uint8_t cbTypePtr;
+ /** size of the size_t item in bytes. */
+ uint8_t cbTypeSize;
+ /** Padding to an 4 byte boundary. */
+ uint16_t u16Reserved0;
+ /** Padding to an 8 byte boundary. */
+ uint32_t u32Reserved0;
+ /** Starting timestamp when the log was initialised. */
+ uint64_t u64TsStart;
+ /** Padding to 64byte boundary, reserved for future use. */
+ uint64_t au64Reserved[3];
+} TRACELOGHDR;
+AssertCompileSize(TRACELOGHDR, 64);
+/** Pointer to a trace log header. */
+typedef TRACELOGHDR *PTRACELOGHDR;
+/** Pointer to a const trace log header. */
+typedef const TRACELOGHDR *PCTRACELOGHDR;
+
+/** Magic value for a trace log file (TRACELOG backwards). */
+#define TRACELOG_HDR_MAGIC "GOLECART"
+/** Endianess indicator. */
+#define TRACELOG_HDR_ENDIANESS 0xdeadc0de
+/** The default version (Higher 16bits major, low 16bits minor version). */
+#define TRACELOG_VERSION RT_MAKE_U32(1, 0)
+
+
+/**
+ * Trace log event structure descriptor.
+ */
+typedef struct TRACELOGEVTDESC
+{
+ /** Event descriptor magic. */
+ uint8_t szMagic[8];
+ /** Event structure descriptor ID for identification in events later. */
+ uint32_t u32Id;
+ /** Severity class of the event .*/
+ uint32_t u32Severity;
+ /** Size of the identifier string in bytes without terminator. */
+ uint32_t cbStrId;
+ /** Size of the description string in bytes without terminator. */
+ uint32_t cbStrDesc;
+ /** Number of event items following. */
+ uint32_t cEvtItems;
+ /** Padding to end the descriptor on a 32 byte boundary. */
+ uint32_t au32Padding0;
+} TRACELOGEVTDESC;
+AssertCompileSize(TRACELOGEVTDESC, 32);
+/** Pointer to a trace log event structure descriptor. */
+typedef TRACELOGEVTDESC *PTRACELOGEVTDESC;
+/** Pointer to a const trace log event structure descriptor. */
+typedef const TRACELOGEVTDESC *PCTRACELOGEVTDESC;
+
+/** Event descriptor magic. */
+#define TRACELOG_EVTDESC_MAGIC "\0CSEDTVE"
+
+/** Severity: Informational event*/
+#define TRACELOG_EVTDESC_SEVERITY_INFO UINT32_C(0)
+/** Severity: Warning event*/
+#define TRACELOG_EVTDESC_SEVERITY_WARNING UINT32_C(1)
+/** Severity: Error event*/
+#define TRACELOG_EVTDESC_SEVERITY_ERROR UINT32_C(2)
+/** Severity: Fatal event*/
+#define TRACELOG_EVTDESC_SEVERITY_FATAL UINT32_C(3)
+/** Severity: Debug event*/
+#define TRACELOG_EVTDESC_SEVERITY_DEBUG UINT32_C(4)
+
+
+/**
+ * Trace log event item descriptor.
+ */
+typedef struct TRACELOGEVTITEMDESC
+{
+ /** Event item descriptor magic. */
+ uint8_t szMagic[8];
+ /** Size of the item name string in bytes without terminator. */
+ uint32_t cbStrName;
+ /** Size of the optional description string in bytes without terminator. */
+ uint32_t cbStrDesc;
+ /** Item type */
+ uint32_t u32Type;
+ /** Size of the raw data type if static throughout. */
+ uint32_t cbRawData;
+ /** Padding to end the descriptor on a 32 byte boundary. */
+ uint32_t au32Padding0[2];
+} TRACELOGEVTITEMDESC;
+AssertCompileSize(TRACELOGEVTITEMDESC, 32);
+/** Pointer to a trace log event item descriptor. */
+typedef TRACELOGEVTITEMDESC *PTRACELOGEVTITEMDESC;
+/** Pointer to a const trace log event item descriptor. */
+typedef const TRACELOGEVTITEMDESC *PCTRACELOGEVTITEMDESC;
+
+/** Event item descriptor magic. */
+#define TRACELOG_EVTITEMDESC_MAGIC "CSEDMETI"
+/** Boolean type. */
+#define TRACELOG_EVTITEMDESC_TYPE_BOOL UINT32_C(1)
+/** Unsigned 8bit integer type. */
+#define TRACELOG_EVTITEMDESC_TYPE_UINT8 UINT32_C(2)
+/** Signed 8bit integer type. */
+#define TRACELOG_EVTITEMDESC_TYPE_INT8 UINT32_C(3)
+/** Unsigned 16bit integer type. */
+#define TRACELOG_EVTITEMDESC_TYPE_UINT16 UINT32_C(4)
+/** Signed 16bit integer type. */
+#define TRACELOG_EVTITEMDESC_TYPE_INT16 UINT32_C(5)
+/** Unsigned 32bit integer type. */
+#define TRACELOG_EVTITEMDESC_TYPE_UINT32 UINT32_C(6)
+/** Signed 32bit integer type. */
+#define TRACELOG_EVTITEMDESC_TYPE_INT32 UINT32_C(7)
+/** Unsigned 64bit integer type. */
+#define TRACELOG_EVTITEMDESC_TYPE_UINT64 UINT32_C(8)
+/** Signed 64bit integer type. */
+#define TRACELOG_EVTITEMDESC_TYPE_INT64 UINT32_C(9)
+/** 32bit floating point type. */
+#define TRACELOG_EVTITEMDESC_TYPE_FLOAT32 UINT32_C(10)
+/** 64bit floating point type. */
+#define TRACELOG_EVTITEMDESC_TYPE_FLOAT64 UINT32_C(11)
+/** Raw binary data type. */
+#define TRACELOG_EVTITEMDESC_TYPE_RAWDATA UINT32_C(12)
+/** Pointer data type. */
+#define TRACELOG_EVTITEMDESC_TYPE_POINTER UINT32_C(13)
+/** size_t data type. */
+#define TRACELOG_EVTITEMDESC_TYPE_SIZE UINT32_C(14)
+
+/**
+ * Trace log event marker.
+ */
+typedef struct TRACELOGEVT
+{
+ /** Event marker magic. */
+ uint8_t szMagic[8];
+ /** Trace log sequence number to identify the event uniquely. */
+ uint64_t u64SeqNo;
+ /** Timestamp for the marker (resolution is infered from the header). */
+ uint64_t u64Ts;
+ /** Event group ID for grouping different events together - for no grouped event. */
+ uint64_t u64EvtGrpId;
+ /** Parent group ID this event originated from. */
+ uint64_t u64EvtParentGrpId;
+ /** Overall number of bytes for the event data following including static and possibly variable data. */
+ uint32_t cbEvtData;
+ /** Number of size_t sized raw data size indicators before the raw event data follows. */
+ uint32_t cRawEvtDataSz;
+ /** Event flags. */
+ uint32_t fFlags;
+ /** Event structure descriptor ID to use for structuring the event data. */
+ uint32_t u32EvtDescId;
+ /** Reserved for future use. */
+ uint64_t u64Reserved0;
+} TRACELOGEVT;
+AssertCompileSize(TRACELOGEVT, 64);
+/** Pointer to a trace log event marker. */
+typedef TRACELOGEVT *PTRACELOGEVT;
+/** Pointer to a const trace log event marker. */
+typedef const TRACELOGEVT *PCTRACELOGEVT;
+
+/** Event marker descriptor magic. */
+#define TRACELOG_EVT_MAGIC "\0RKRMTVE"
+/** Flag indicating this is the start of an event group and all subsequent events
+ * with the same group ID belong to the same group. */
+#define TRACELOG_EVT_F_GRP_START RT_BIT_32(0)
+/** Flag indicating this is the end of an event group which was started earlier. */
+#define TRACELOG_EVT_F_GRP_END RT_BIT_32(1)
+/** Combination of valid flags. */
+#define TRACELOG_EVT_F_VALID (TRACELOG_EVT_F_GRP_START | TRACELOG_EVT_F_GRP_END)
+
+/** @} */
+
+#endif /* !IPRT_INCLUDED_formats_tracelog_h */
+
diff --git a/include/iprt/formats/udf.h b/include/iprt/formats/udf.h
new file mode 100644
index 00000000..5081c11e
--- /dev/null
+++ b/include/iprt/formats/udf.h
@@ -0,0 +1,2232 @@
+/* $Id: udf.h $ */
+/** @file
+ * IPRT, Universal Disk Format (UDF).
+ */
+
+/*
+ * Copyright (C) 2017-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_formats_udf_h
+#define IPRT_INCLUDED_formats_udf_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+#include <iprt/assertcompile.h>
+#include <iprt/formats/iso9660.h>
+
+
+/** @defgroup grp_rt_formats_udf Universal Disk Format (UDF) structures and definitions
+ * @ingroup grp_rt_formats
+ *
+ * References:
+ * - https://www.ecma-international.org/publications/files/ECMA-ST/Ecma-167.pdf
+ * - http://www.osta.org/specs/pdf/udf260.pdf
+ * - http://wiki.osdev.org/UDF
+ * - https://sites.google.com/site/udfintro/
+ *
+ * @{
+ */
+
+/**
+ * UDF d-character string (@ecma167{1,7.2.12,25}).
+ *
+ * This is mainly to mark what's d-strings and what's not.
+ */
+typedef char UDFDSTRING;
+/** Pointer to an UDF dstring. */
+typedef UDFDSTRING *PUDFDSTRING;
+/** Pointer to a const UDF dstring. */
+typedef UDFDSTRING const *PCUDFDSTRING;
+
+/**
+ * UDF extent allocation descriptor (AD) (@ecma167{3,7.1,42}).
+ */
+typedef struct UDFEXTENTAD
+{
+ /** Extent length in bytes. */
+ uint32_t cb;
+ /** Extent offset (logical sector number).
+ * If @a cb is zero, this is also zero. */
+ uint32_t off;
+} UDFEXTENTAD;
+AssertCompileSize(UDFEXTENTAD, 8);
+/** Pointer to an UDF extent descriptor. */
+typedef UDFEXTENTAD *PUDFEXTENTAD;
+/** Pointer to a const UDF extent descriptor. */
+typedef UDFEXTENTAD const *PCUDFEXTENTAD;
+
+
+/**
+ * UDF logical block address (@ecma167{4,7.1,73}).
+ */
+#pragma pack(2)
+typedef struct UDFLBADDR
+{
+ /** Logical block number, relative to the start of the given partition. */
+ uint32_t off;
+ /** Partition reference number. */
+ uint16_t uPartitionNo;
+} UDFLBADDR;
+#pragma pack()
+AssertCompileSize(UDFLBADDR, 6);
+/** Pointer to an UDF logical block address. */
+typedef UDFLBADDR *PUDFLBADDR;
+/** Pointer to a const UDF logical block address. */
+typedef UDFLBADDR const *PCUDFLBADDR;
+
+
+/** @name UDF_AD_TYPE_XXX - Allocation descriptor types.
+ *
+ * Used by UDFSHORTAD::uType, UDFLONGAD::uType and UDFEXTAD::uType.
+ *
+ * See @ecma167{4,14.14.1.1,116}.
+ *
+ * @{ */
+/** Recorded and allocated.
+ * Also used for zero length descriptors. */
+#define UDF_AD_TYPE_RECORDED_AND_ALLOCATED 0
+/** Allocated but not recorded. */
+#define UDF_AD_TYPE_ONLY_ALLOCATED 1
+/** Not recorded nor allocated. */
+#define UDF_AD_TYPE_FREE 2
+/** Go figure. */
+#define UDF_AD_TYPE_NEXT 3
+/** @} */
+
+/**
+ * UDF short allocation descriptor (@ecma167{4,14.14.1,116}).
+ */
+typedef struct UDFSHORTAD
+{
+#ifdef RT_BIG_ENDIAN
+ /** Extent type (UDF_AD_TYPE_XXX). */
+ uint32_t uType : 2;
+ /** Extent length in bytes, top 2 bits . */
+ uint32_t cb : 30;
+#else
+ /** Extent length in bytes. */
+ uint32_t cb : 30;
+ /** Extent type (UDF_AD_TYPE_XXX). */
+ uint32_t uType : 2;
+#endif
+ /** Extent offset (logical sector number). */
+ uint32_t off;
+} UDFSHORTAD;
+AssertCompileSize(UDFSHORTAD, 8);
+/** Pointer to an UDF short allocation descriptor. */
+typedef UDFSHORTAD *PUDFSHORTAD;
+/** Pointer to a const UDF short allocation descriptor. */
+typedef UDFSHORTAD const *PCUDFSHORTAD;
+
+/**
+ * UDF long allocation descriptor (@ecma167{4,14.14.2,116}).
+ */
+#pragma pack(2)
+typedef struct UDFLONGAD
+{
+#ifdef RT_BIG_ENDIAN
+ /** Extent type (UDF_AD_TYPE_XXX). */
+ uint32_t uType : 2;
+ /** Extent length in bytes, top 2 bits . */
+ uint32_t cb : 30;
+#else
+ /** Extent length in bytes. */
+ uint32_t cb : 30;
+ /** Extent type (UDF_AD_TYPE_XXX). */
+ uint32_t uType : 2;
+#endif
+ /** Extent location. */
+ UDFLBADDR Location;
+ /** Implementation use area. */
+ union
+ {
+ /** Generic view. */
+ uint8_t ab[6];
+ /** Used in FIDs.
+ * See @udf260{2.3.10.1,66}, @udf260{2.3.4.3,58}.
+ */
+ struct
+ {
+ /** Flags (UDF_AD_IMP_USE_FLAGS_XXX). */
+ uint16_t fFlags;
+ /** Unique ID. */
+ uint32_t idUnique;
+ } Fid;
+ } ImplementationUse;
+} UDFLONGAD;
+#pragma pack()
+AssertCompileSize(UDFLONGAD, 16);
+/** Pointer to an UDF long allocation descriptor. */
+typedef UDFLONGAD *PUDFLONGAD;
+/** Pointer to a const UDF long allocation descriptor. */
+typedef UDFLONGAD const *PCUDFLONGAD;
+
+/** @name UDF_AD_IMP_USE_FLAGS_XXX - UDFLONGAD::ImplementationUse::Fid::fFlags values
+ * See @udf260{2.3.10.1,66}.
+ * @{ */
+/** Set if erased and the extend is of the type UDF_AD_TYPE_ONLY_ALLOCATED. */
+#define UDF_AD_IMP_USE_FLAGS_ERASED UINT16_C(0x0001)
+/** Valid mask. */
+#define UDF_AD_IMP_USE_FLAGS_VALID_MASK UINT16_C(0x0001)
+/** @} */
+
+/**
+ * UDF extended allocation descriptor (@ecma167{4,14.14.3,117}).
+ */
+typedef struct UDFEXTAD
+{
+#ifdef RT_BIG_ENDIAN
+ /** 0x00: Extent type (UDF_AD_TYPE_XXX). */
+ uint32_t uType : 2;
+ /** 0x00: Extent length in bytes, top 2 bits . */
+ uint32_t cb : 30;
+ /** 0x04: Reserved, MBZ. */
+ uint32_t uReserved : 2;
+ /** 0x04: Number of bytes recorded. */
+ uint32_t cbRecorded : 30;
+#else
+ /** 0x00: Extent length in bytes. */
+ uint32_t cb : 30;
+ /** 0x00: Extent type (UDF_AD_TYPE_XXX). */
+ uint32_t uType : 2;
+ /** 0x04: Number of bytes recorded. */
+ uint32_t cbRecorded : 30;
+ /** 0x04: Reserved, MBZ. */
+ uint32_t uReserved : 2;
+#endif
+ /** 0x08: Number of bytes of information (from first byte). */
+ uint32_t cbInformation;
+ /** 0x0c: Extent location. */
+ UDFLBADDR Location;
+ /** 0x12: Implementation use area. */
+ uint8_t abImplementationUse[2];
+} UDFEXTAD;
+AssertCompileSize(UDFEXTAD, 20);
+/** Pointer to an UDF extended allocation descriptor. */
+typedef UDFEXTAD *PUDFEXTAD;
+/** Pointer to a const UDF extended allocation descriptor. */
+typedef UDFEXTAD const *PCUDFEXTAD;
+
+
+/**
+ * UDF timestamp (@ecma167{1,7.3,25}, @udf260{2.1.4,19}).
+ */
+typedef struct UDFTIMESTAMP
+{
+#ifdef RT_BIG_ENDIAN
+ /** 0x00: Type (UDFTIMESTAMP_T_XXX). */
+ RT_GCC_EXTENSION uint16_t fType : 4;
+ /** 0x00: Time zone offset in minutes.
+ * For EST this will be -300, whereas for CET it will be 60. */
+ RT_GCC_EXTENSION int16_t offUtcInMin : 12;
+#else
+ /** 0x00: Time zone offset in minutes.
+ * For EST this will be -300, whereas for CET it will be 60. */
+ RT_GCC_EXTENSION int16_t offUtcInMin : 12;
+ /** 0x00: Type (UDFTIMESTAMP_T_XXX). */
+ RT_GCC_EXTENSION uint16_t fType : 4;
+#endif
+ /** 0x02: The year. */
+ int16_t iYear;
+ /** 0x04: Month of year (1-12). */
+ uint8_t uMonth;
+ /** 0x05: Day of month (1-31). */
+ uint8_t uDay;
+ /** 0x06: Hour of day (0-23). */
+ uint8_t uHour;
+ /** 0x07: Minute of hour (0-59). */
+ uint8_t uMinute;
+ /** 0x08: Second of minute (0-60 if type 2, otherwise 0-59). */
+ uint8_t uSecond;
+ /** 0x09: Number of Centiseconds (0-99). */
+ uint8_t cCentiseconds;
+ /** 0x0a: Number of hundreds of microseconds (0-99). Unit is 100us. */
+ uint8_t cHundredsOfMicroseconds;
+ /** 0x0b: Number of microseconds (0-99). */
+ uint8_t cMicroseconds;
+} UDFTIMESTAMP;
+AssertCompileSize(UDFTIMESTAMP, 12);
+/** Pointer to an UDF timestamp. */
+typedef UDFTIMESTAMP *PUDFTIMESTAMP;
+/** Pointer to a const UDF timestamp. */
+typedef UDFTIMESTAMP const *PCUDFTIMESTAMP;
+
+/** @name UDFTIMESTAMP_T_XXX
+ * @{ */
+/** Local time. */
+#define UDFTIMESTAMP_T_LOCAL 1
+/** @} */
+
+/** No time zone specified. */
+#define UDFTIMESTAMP_NO_TIME_ZONE (-2047)
+
+
+/**
+ * UDF character set specficiation (@ecma167{1,7.2.1,21}, @udf260{2.1.2,18}).
+ */
+typedef struct UDFCHARSPEC
+{
+ /** The character set type (UDF_CHAR_SET_TYPE_XXX) */
+ uint8_t uType;
+ /** Character set information. */
+ uint8_t abInfo[63];
+} UDFCHARSPEC;
+AssertCompileSize(UDFCHARSPEC, 64);
+/** Pointer to UDF character set specification. */
+typedef UDFCHARSPEC *PUDFCHARSPEC;
+/** Pointer to const UDF character set specification. */
+typedef UDFCHARSPEC const *PCUDFCHARSPEC;
+
+/** @name UDF_CHAR_SET_TYPE_XXX - Character set types.
+ * @{ */
+/** CS0: By agreement between the medium producer and consumer.
+ * See UDF_CHAR_SET_OSTA_COMPRESSED_UNICODE. */
+#define UDF_CHAR_SET_TYPE_BY_AGREEMENT UINT8_C(0x00)
+/** CS1: ASCII (ECMA-6) with all or part of the specified graphic characters. */
+#define UDF_CHAR_SET_TYPE_ASCII UINT8_C(0x01)
+/** CS5: Latin-1 (ECMA-94) with all graphical characters. */
+#define UDF_CHAR_SET_TYPE_LATIN_1 UINT8_C(0x05)
+/* there are more defined here, but they are mostly useless, since UDF only uses CS0. */
+
+/** The CS0 definition used by the UDF specification. */
+#define UDF_CHAR_SET_OSTA_COMPRESSED_UNICODE UDF_CHAR_SET_TYPE_BY_AGREEMENT
+/** String to put in the UDFCHARSEPC::abInfo field for UDF CS0. */
+#define UDF_CHAR_SET_OSTA_COMPRESSED_UNICODE_INFO "OSTA Compressed Unicode"
+/** @} */
+
+
+/**
+ * UDF entity identifier (@ecma167{1,7.4,26}, @udf260{2.1.5,20}).
+ */
+typedef struct UDFENTITYID
+{
+ /** 0x00: Flags (UDFENTITYID_FLAGS_XXX). */
+ uint8_t fFlags;
+ /** 0x01: Identifier string (see UDF_ENTITY_ID_XXX). */
+ char achIdentifier[23];
+ /** 0x18: Identifier suffix. */
+ union
+ {
+ /** Domain ID suffix. */
+ struct
+ {
+ uint16_t uUdfRevision;
+ uint8_t fDomain;
+ uint8_t abReserved[5];
+ } Domain;
+
+ /** UDF ID suffix. */
+ struct
+ {
+ uint16_t uUdfRevision;
+ uint8_t bOsClass;
+ uint8_t idOS;
+ uint8_t abReserved[4];
+ } Udf;
+
+
+ /** Implementation ID suffix. */
+ struct
+ {
+ uint8_t bOsClass;
+ uint8_t idOS;
+ uint8_t achImplUse[6];
+ } Implementation;
+
+ /** Application ID suffix / generic. */
+ uint8_t abApplication[8];
+ } Suffix;
+} UDFENTITYID;
+AssertCompileSize(UDFENTITYID, 32);
+/** Pointer to UDF entity identifier. */
+typedef UDFENTITYID *PUDFENTITYID;
+/** Pointer to const UDF entity identifier. */
+typedef UDFENTITYID const *PCUDFENTITYID;
+
+/** @name UDF_ENTITY_ID_XXX - UDF identifier strings
+ *
+ * See @udf260{2.1.5.2,21}.
+ *
+ * @{ */
+/** Implementation use volume descriptor, implementation ID field.
+ * UDF ID suffix. */
+#define UDF_ENTITY_ID_IUVD_IMPLEMENTATION "*UDF LV Info"
+
+/** Partition descriptor, partition contents field, set to indicate UDF
+ * (ECMA-167 3rd edition). Application ID suffix. */
+#define UDF_ENTITY_ID_PD_PARTITION_CONTENTS_UDF "+NSR03"
+/** Partition descriptor, partition contents field, set to indicate ISO-9660
+ * (ECMA-119). Application ID suffix. */
+#define UDF_ENTITY_ID_PD_PARTITION_CONTENTS_ISO9660 "+CD001"
+/** Partition descriptor, partition contents field, set to indicate ECMA-168.
+ * Application ID suffix. */
+#define UDF_ENTITY_ID_PD_PARTITION_CONTENTS_CDW "+CDW02"
+/** Partition descriptor, partition contents field, set to indicate FAT
+ * (ECMA-107). Application ID suffix. */
+#define UDF_ENTITY_ID_PD_PARTITION_CONTENTS_FAT "+FDC01"
+
+/** Logical volume descriptor, domain ID field.
+ * Domain ID suffix. */
+#define UDF_ENTITY_ID_LVD_DOMAIN "*OSTA UDF Compliant"
+
+/** File set descriptor, domain ID field.
+ * Domain ID suffix. */
+#define UDF_ENTITY_FSD_LVD_DOMAIN "*OSTA UDF Compliant"
+
+/** UDF implementation use extended attribute, implementation ID field, set
+ * to free EA space. UDF ID suffix. */
+#define UDF_ENTITY_ID_IUEA_FREE_EA_SPACE "*UDF FreeEASpace"
+/** UDF implementation use extended attribute, implementation ID field, set
+ * to DVD copyright management information. UDF ID suffix. */
+#define UDF_ENTITY_ID_IUEA_DVD_CGMS_INFO "*UDF DVD CGMS Info"
+/** UDF implementation use extended attribute, implementation ID field, set
+ * to OS/2 extended attribute length. UDF ID suffix. */
+#define UDF_ENTITY_ID_IUEA_OS2_EA_LENGTH "*UDF OS/2 EALength"
+/** UDF implementation use extended attribute, implementation ID field, set
+ * to Machintosh OS volume information. UDF ID suffix. */
+#define UDF_ENTITY_ID_IUEA_MAC_VOLUME_INFO "*UDF Mac VolumeInfo"
+/** UDF implementation use extended attribute, implementation ID field, set
+ * to Machintosh Finder Info. UDF ID suffix. */
+#define UDF_ENTITY_ID_IUEA_MAC_FINDER_INFO "*UDF Mac FinderInfo"
+/** UDF implementation use extended attribute, implementation ID field, set
+ * to OS/400 extended directory information. UDF ID suffix. */
+#define UDF_ENTITY_ID_IUEA_OS400_DIR_INFO "*UDF OS/400 DirInfo"
+
+/** UDF application use extended attribute, application ID field, set
+ * to free application use EA space. UDF ID suffix. */
+#define UDF_ENTITY_ID_AUEA_FREE_EA_SPACE "*UDF FreeAppEASpace"
+
+/** Virtual partition map, partition type field.
+ * UDF ID suffix. */
+#define UDF_ENTITY_ID_VPM_PARTITION_TYPE "*UDF Virtual Partition"
+
+/** Sparable partition map, partition type field.
+ * UDF ID suffix. */
+#define UDF_ENTITY_ID_SPM_PARTITION_TYPE "*UDF Sparable Partition"
+
+/** Metadata partition map, partition type field.
+ * UDF ID suffix. */
+#define UDF_ENTITY_ID_MPM_PARTITION_TYPE "*UDF Metadata Partition"
+
+/** Sparing table, sparing identifier field.
+ * UDF ID suffix. */
+#define UDF_ENTITY_ID_ST_SPARING "*UDF Sparting Table"
+
+/** @} */
+
+
+/**
+ * UDF descriptor tag (@ecma167{3,7.2,42}, @udf260{2.2.1,26}).
+ */
+typedef struct UDFTAG
+{
+ /** Tag identifier (UDF_TAG_ID_XXX). */
+ uint16_t idTag;
+ /** Descriptor version. */
+ uint16_t uVersion;
+ /** Tag checksum.
+ * Sum of each byte in the structure with this field as zero. */
+ uint8_t uChecksum;
+ /** Reserved, MBZ. */
+ uint8_t bReserved;
+ /** Tag serial number. */
+ uint16_t uTagSerialNo;
+ /** Descriptor CRC. */
+ uint16_t uDescriptorCrc;
+ /** Descriptor CRC length. */
+ uint16_t cbDescriptorCrc;
+ /** The tag location (logical sector number). */
+ uint32_t offTag;
+} UDFTAG;
+AssertCompileSize(UDFTAG, 16);
+/** Pointer to an UDF descriptor tag. */
+typedef UDFTAG *PUDFTAG;
+/** Pointer to a const UDF descriptor tag. */
+typedef UDFTAG const *PCUDFTAG;
+
+/** @name UDF_TAG_ID_XXX - UDF descriptor tag IDs.
+ * @{ */
+#define UDF_TAG_ID_PRIMARY_VOL_DESC UINT16_C(0x0001) /**< See UDFPRIMARYVOLUMEDESC */
+#define UDF_TAG_ID_ANCHOR_VOLUME_DESC_PTR UINT16_C(0x0002) /**< See UDFANCHORVOLUMEDESCPTR */
+#define UDF_TAG_ID_VOLUME_DESC_PTR UINT16_C(0x0003) /**< See UDFVOLUMEDESCPTR */
+#define UDF_TAG_ID_IMPLEMENTATION_USE_VOLUME_DESC UINT16_C(0x0004) /**< See UDFIMPLEMENTATIONUSEVOLUMEDESC */
+#define UDF_TAG_ID_PARTITION_DESC UINT16_C(0x0005) /**< See UDFPARTITIONDESC */
+#define UDF_TAG_ID_LOGICAL_VOLUME_DESC UINT16_C(0x0006) /**< See UDFLOGICALVOLUMEDESC */
+#define UDF_TAG_ID_UNALLOCATED_SPACE_DESC UINT16_C(0x0007) /**< See UDFUNALLOCATEDSPACEDESC */
+#define UDF_TAG_ID_TERMINATING_DESC UINT16_C(0x0008) /**< See UDFTERMINATINGDESC */
+#define UDF_TAG_ID_LOGICAL_VOLUME_INTEGRITY_DESC UINT16_C(0x0009) /**< See UDFLOGICALVOLINTEGRITYDESC */
+#define UDF_TAG_ID_FILE_SET_DESC UINT16_C(0x0100) /**< See UDFFILESETDESC */
+#define UDF_TAG_ID_FILE_ID_DESC UINT16_C(0x0101) /**< See UDFFILEIDDESC */
+#define UDF_TAG_ID_ALLOCATION_EXTENT_DESC UINT16_C(0x0102) /**< See UDFALLOCATIONEXTENTDESC */
+#define UDF_TAG_ID_INDIRECT_ENTRY UINT16_C(0x0103) /**< See UDFINDIRECTENTRY */
+#define UDF_TAG_ID_TERMINAL_ENTRY UINT16_C(0x0104) /**< See UDFTERMINALENTRY */
+#define UDF_TAG_ID_FILE_ENTRY UINT16_C(0x0105) /**< See UDFFILEENTRY */
+#define UDF_TAG_ID_EXTENDED_ATTRIB_HDR_DESC UINT16_C(0x0106) /**< See UDFEXTATTRIBHDRDESC */
+#define UDF_TAG_ID_UNALLOCATED_SPACE_ENTRY UINT16_C(0x0107) /**< See UDFUNALLOCATEDSPACEENTRY */
+#define UDF_TAG_ID_SPACE_BITMAP_DESC UINT16_C(0x0108) /**< See UDFSPACEBITMAPDESC */
+#define UDF_TAG_ID_PARTITION_INTEGERITY_DESC UINT16_C(0x0109) /**< See UDFPARTITIONINTEGRITYDESC */
+#define UDF_TAG_ID_EXTENDED_FILE_ENTRY UINT16_C(0x010a) /**< See UDFEXFILEENTRY */
+/** @} */
+
+
+/**
+ * UDF primary volume descriptor (PVD) (@ecma167{3,10.1,50},
+ * @udf260{2.2.2,27}).
+ */
+typedef struct UDFPRIMARYVOLUMEDESC
+{
+ /** 0x000: The descriptor tag (UDF_TAG_ID_PRIMARY_VOL_DESC). */
+ UDFTAG Tag;
+ /** 0x010: Volume descriptor sequence number. */
+ uint32_t uVolumeDescSeqNo;
+ /** 0x014: Primary volume descriptor number. */
+ uint32_t uPrimaryVolumeDescNo;
+ /** 0x018: Volume identifier (dstring). */
+ UDFDSTRING achVolumeID[32];
+ /** 0x038: Volume sequence number. */
+ uint16_t uVolumeSeqNo;
+ /** 0x03a: Maximum volume sequence number. */
+ uint16_t uMaxVolumeSeqNo;
+ /** 0x03c: Interchange level. */
+ uint16_t uInterchangeLevel;
+ /** 0x03e: Maximum interchange level. */
+ uint16_t uMaxInterchangeLevel;
+ /** 0x040: Character set bitmask (aka list). Each bit correspond to a
+ * character set number. */
+ uint32_t fCharacterSets;
+ /** 0x044: Maximum character set bitmask (aka list). */
+ uint32_t fMaxCharacterSets;
+ /** 0x048: Volume set identifier (dstring). This starts with 16 unique
+ * characters, the first 8 being the hex representation of a time value. */
+ UDFDSTRING achVolumeSetID[128];
+ /** 0x0c8: Descriptor character set.
+ * For achVolumeSetID and achVolumeID. */
+ UDFCHARSPEC DescCharSet;
+ /** 0x108: Explanatory character set.
+ * For VolumeAbstract and VolumeCopyrightNotice data. */
+ UDFCHARSPEC ExplanatoryCharSet;
+ /** 0x148: Volume abstract. */
+ UDFEXTENTAD VolumeAbstract;
+ /** 0x150: Volume copyright notice. */
+ UDFEXTENTAD VolumeCopyrightNotice;
+ /** 0x158: Application identifier ("*Application ID"). */
+ UDFENTITYID idApplication;
+ /** 0x178: Recording date and time. */
+ UDFTIMESTAMP RecordingTimestamp;
+ /** 0x184: Implementation identifier ("*Developer ID"). */
+ UDFENTITYID idImplementation;
+ /** 0x1a4: Implementation use. */
+ uint8_t abImplementationUse[64];
+ /** 0x1e4: Predecessor volume descriptor sequence location. */
+ uint32_t offPredecessorVolDescSeq;
+ /** 0x1e8: Flags (UDF_PVD_FLAGS_XXX). */
+ uint16_t fFlags;
+ /** 0x1ea: Reserved. */
+ uint8_t abReserved[22];
+} UDFPRIMARYVOLUMEDESC;
+AssertCompileSize(UDFPRIMARYVOLUMEDESC, 512);
+/** Pointer to a UDF primary volume descriptor. */
+typedef UDFPRIMARYVOLUMEDESC *PUDFPRIMARYVOLUMEDESC;
+/** Pointer to a const UDF primary volume descriptor. */
+typedef UDFPRIMARYVOLUMEDESC const *PCUDFPRIMARYVOLUMEDESC;
+
+/** @name UDF_PVD_FLAGS_XXX - Flags for UDFPRIMARYVOLUMEDESC::fFlags.
+ * @{ */
+/** Indicates that the volume set ID is common to all members of the set. */
+#define UDF_PVD_FLAGS_COMMON_VOLUME_SET_ID UINT16_C(0x0001)
+/** @} */
+
+
+/**
+ * UDF anchor volume descriptor pointer (AVDP) (@ecma167{3,10.2,53},
+ * @udf260{2.2.3,29}).
+ *
+ * This is stored at least two of these locations:
+ * - logical sector 256
+ * - logical sector N - 256.
+ * - logical sector N.
+ */
+typedef struct UDFANCHORVOLUMEDESCPTR
+{
+ /** 0x00: The descriptor tag (UDF_TAG_ID_ANCHOR_VOLUME_DESC_PTR). */
+ UDFTAG Tag;
+ /** 0x10: The extent descripting the main volume descriptor sequence. */
+ UDFEXTENTAD MainVolumeDescSeq;
+ /** 0x18: Location of the backup descriptor sequence. */
+ UDFEXTENTAD ReserveVolumeDescSeq;
+ /** 0x20: Reserved, probably must be zeros. */
+ uint8_t abReserved[0x1e0];
+} UDFANCHORVOLUMEDESCPTR;
+AssertCompileSize(UDFANCHORVOLUMEDESCPTR, 512);
+/** Pointer to UDF anchor volume descriptor pointer. */
+typedef UDFANCHORVOLUMEDESCPTR *PUDFANCHORVOLUMEDESCPTR;
+/** Pointer to const UDF anchor volume descriptor pointer. */
+typedef UDFANCHORVOLUMEDESCPTR const *PCUDFANCHORVOLUMEDESCPTR;
+
+
+/**
+ * UDF volume descriptor pointer (VDP) (@ecma167{3,10.3,53}).
+ */
+typedef struct UDFVOLUMEDESCPTR
+{
+ /** 0x00: The descriptor tag (UDF_TAG_ID_VOLUME_DESC_PTR). */
+ UDFTAG Tag;
+ /** 0x10: Volume descriptor sequence number. */
+ uint32_t uVolumeDescSeqNo;
+ /** 0x14: Location of the next volume descriptor sequence. */
+ UDFEXTENTAD NextVolumeDescSeq;
+ /** 0x1c: Reserved, probably must be zeros. */
+ uint8_t abReserved[484];
+} UDFVOLUMEDESCPTR;
+AssertCompileSize(UDFVOLUMEDESCPTR, 512);
+/** Pointer to UDF volume descriptor pointer. */
+typedef UDFVOLUMEDESCPTR *PUDFVOLUMEDESCPTR;
+/** Pointer to const UDF volume descriptor pointer. */
+typedef UDFVOLUMEDESCPTR const *PCUDFVOLUMEDESCPTR;
+
+
+/**
+ * UDF implementation use volume descriptor (IUVD) (@ecma167{3,10.4,55},
+ * @udf260{2.2.7,35}).
+ */
+typedef struct UDFIMPLEMENTATIONUSEVOLUMEDESC
+{
+ /** 0x00: The descriptor tag (UDF_TAG_ID_IMPLEMENTATION_USE_VOLUME_DESC). */
+ UDFTAG Tag;
+ /** 0x10: Volume descriptor sequence number. */
+ uint32_t uVolumeDescSeqNo;
+ /** 0x14: The implementation identifier (UDF_ENTITY_ID_IUVD_IMPLEMENTATION). */
+ UDFENTITYID idImplementation;
+ /** 0x34: The implementation use area. */
+ union
+ {
+ /** Generic view. */
+ uint8_t ab[460];
+ /** Logical volume information (@udf260{2.2.7.2,35}). */
+ struct
+ {
+ /** 0x034: The character set used in this sub-structure. */
+ UDFCHARSPEC Charset;
+ /** 0x074: Logical volume identifier. */
+ UDFDSTRING achVolumeID[128];
+ /** 0x0f4: Info string \#1. */
+ UDFDSTRING achInfo1[36];
+ /** 0x118: Info string \#2. */
+ UDFDSTRING achInfo2[36];
+ /** 0x13c: Info string \#3. */
+ UDFDSTRING achInfo3[36];
+ /** 0x160: The implementation identifier ("*Developer ID"). */
+ UDFENTITYID idImplementation;
+ /** 0x180: Additional use bytes. */
+ uint8_t abUse[128];
+ } Lvi;
+ } ImplementationUse;
+} UDFIMPLEMENTATIONUSEVOLUMEDESC;
+AssertCompileSize(UDFIMPLEMENTATIONUSEVOLUMEDESC, 512);
+AssertCompileMemberOffset(UDFIMPLEMENTATIONUSEVOLUMEDESC, ImplementationUse.Lvi.Charset, 0x034);
+AssertCompileMemberOffset(UDFIMPLEMENTATIONUSEVOLUMEDESC, ImplementationUse.Lvi.achVolumeID, 0x074);
+AssertCompileMemberOffset(UDFIMPLEMENTATIONUSEVOLUMEDESC, ImplementationUse.Lvi.achInfo1, 0x0f4);
+AssertCompileMemberOffset(UDFIMPLEMENTATIONUSEVOLUMEDESC, ImplementationUse.Lvi.achInfo2, 0x118);
+AssertCompileMemberOffset(UDFIMPLEMENTATIONUSEVOLUMEDESC, ImplementationUse.Lvi.achInfo3, 0x13c);
+AssertCompileMemberOffset(UDFIMPLEMENTATIONUSEVOLUMEDESC, ImplementationUse.Lvi.idImplementation, 0x160);
+/** Pointer to an UDF implementation use volume descriptor. */
+typedef UDFIMPLEMENTATIONUSEVOLUMEDESC *PUDFIMPLEMENTATIONUSEVOLUMEDESC;
+/** Pointer to a const UDF implementation use volume descriptor. */
+typedef UDFIMPLEMENTATIONUSEVOLUMEDESC const *PCUDFIMPLEMENTATIONUSEVOLUMEDESC;
+
+
+/**
+ * UDF partition header descriptor (@ecma167{4,14.3,90}, @udf260{2.3.3,56}).
+ *
+ * This is found in UDFPARTITIONDESC::ContentsUse.
+ */
+typedef struct UDFPARTITIONHDRDESC
+{
+ /** 0x00: Unallocated space table location. Zero length means no table. */
+ UDFSHORTAD UnallocatedSpaceTable;
+ /** 0x08: Unallocated space bitmap location. Zero length means no bitmap. */
+ UDFSHORTAD UnallocatedSpaceBitmap;
+ /** 0x10: Partition integrity table location. Zero length means no table. */
+ UDFSHORTAD PartitionIntegrityTable;
+ /** 0x18: Freed space table location. Zero length means no table. */
+ UDFSHORTAD FreedSpaceTable;
+ /** 0x20: Freed space bitmap location. Zero length means no bitmap. */
+ UDFSHORTAD FreedSpaceBitmap;
+ /** 0x28: Reserved, MBZ. */
+ uint8_t abReserved[88];
+} UDFPARTITIONHDRDESC;
+AssertCompileSize(UDFPARTITIONHDRDESC, 128);
+AssertCompileMemberOffset(UDFPARTITIONHDRDESC, PartitionIntegrityTable, 0x10);
+AssertCompileMemberOffset(UDFPARTITIONHDRDESC, abReserved, 0x28);
+/** Pointer to an UDF partition header descriptor. */
+typedef UDFPARTITIONHDRDESC *PUDFPARTITIONHDRDESC;
+/** Pointer to a const UDF partition header descriptor. */
+typedef UDFPARTITIONHDRDESC const *PCUDFPARTITIONHDRDESC;
+
+
+/**
+ * UDF partition descriptor (PD) (@ecma167{3,10.5,55}, @udf260{2.2.14,51}).
+ */
+typedef struct UDFPARTITIONDESC
+{
+ /** 0x000: The descriptor tag (UDF_TAG_ID_PARTITION_DESC). */
+ UDFTAG Tag;
+ /** 0x010: Volume descriptor sequence number. */
+ uint32_t uVolumeDescSeqNo;
+ /** 0x014: The partition flags (UDF_PARTITION_FLAGS_XXX). */
+ uint16_t fFlags;
+ /** 0x016: The partition number. */
+ uint16_t uPartitionNo;
+ /** 0x018: Partition contents (UDF_ENTITY_ID_PD_PARTITION_CONTENTS_XXX). */
+ UDFENTITYID PartitionContents;
+ /** 0x038: partition contents use (depends on the PartitionContents field). */
+ union
+ {
+ /** Generic view. */
+ uint8_t ab[128];
+ /** UDF partition header descriptor (UDF_ENTITY_ID_PD_PARTITION_CONTENTS_UDF). */
+ UDFPARTITIONHDRDESC Hdr;
+ } ContentsUse;
+ /** 0x0b8: Access type (UDF_PART_ACCESS_TYPE_XXX). */
+ uint32_t uAccessType;
+ /** 0x0bc: Partition starting location (logical sector number). */
+ uint32_t offLocation;
+ /** 0x0c0: Partition length in sectors. */
+ uint32_t cSectors;
+ /** 0x0c4: Implementation identifier ("*Developer ID"). */
+ UDFENTITYID idImplementation;
+ /** 0x0e4: Implementation use bytes. */
+ union
+ {
+ /** Generic view. */
+ uint8_t ab[128];
+ } ImplementationUse;
+ /** 0x164: Reserved. */
+ uint8_t abReserved[156];
+} UDFPARTITIONDESC;
+AssertCompileSize(UDFPARTITIONDESC, 512);
+/** Pointer to an UDF partitions descriptor. */
+typedef UDFPARTITIONDESC *PUDFPARTITIONDESC;
+/** Pointer to a const UDF partitions descriptor. */
+typedef const UDFPARTITIONDESC *PCUDFPARTITIONDESC;
+
+/** @name UDF_PART_ACCESS_TYPE_XXX - UDF partition access types
+ *
+ * See @ecma167{3,10.5.7,57}, @udf260{2.2.14.2,51}.
+ *
+ * @{ */
+/** Access not specified by this field. */
+#define UDF_PART_ACCESS_TYPE_NOT_SPECIFIED UINT32_C(0x00000000)
+/** Read only: No writes. */
+#define UDF_PART_ACCESS_TYPE_READ_ONLY UINT32_C(0x00000001)
+/** Write once: Sectors can only be written once. */
+#define UDF_PART_ACCESS_TYPE_WRITE_ONCE UINT32_C(0x00000002)
+/** Rewritable: Logical sectors may require preprocessing before writing. */
+#define UDF_PART_ACCESS_TYPE_REWRITABLE UINT32_C(0x00000003)
+/** Overwritable: No restrictions on writing. */
+#define UDF_PART_ACCESS_TYPE_OVERWRITABLE UINT32_C(0x00000004)
+/** @} */
+
+
+/**
+ * Logical volume descriptor (LVD) (@ecma167{3,10.6,58}, @udf260{2.2.4,30}).
+ *
+ * @note Variable length.
+ */
+typedef struct UDFLOGICALVOLUMEDESC
+{
+ /** 0x000: The descriptor tag (UDF_TAG_ID_LOGICAL_VOLUME_DESC). */
+ UDFTAG Tag;
+ /** 0x010: Volume descriptor sequence number. */
+ uint32_t uVolumeDescSeqNo;
+ /** 0x014: Character set used in the achLogicalVolumeID field. */
+ UDFCHARSPEC DescCharSet;
+ /** 0x054: The logical volume ID (label). */
+ UDFDSTRING achLogicalVolumeID[128];
+ /** 0x0d4: Logical block size (in bytes). */
+ uint32_t cbLogicalBlock;
+ /** 0x0d8: Domain identifier (UDF_ENTITY_ID_LVD_DOMAIN). */
+ UDFENTITYID idDomain;
+ /** 0x0f8: Logical volume contents use. */
+ union
+ {
+ /** Byte view. */
+ uint8_t ab[16];
+ /** The extent containing the file set descriptor. */
+ UDFLONGAD FileSetDescriptor;
+ } ContentsUse;
+ /** 0x108: Map table length (in bytes). */
+ uint32_t cbMapTable;
+ /** 0x10c: Number of partition maps. */
+ uint32_t cPartitionMaps;
+ /** 0x110: Implementation identifier ("*Developer ID"). */
+ UDFENTITYID idImplementation;
+ /** 0x130: Implementation use. */
+ union
+ {
+ /** Byte view. */
+ uint8_t ab[128];
+ } ImplementationUse;
+ /** 0x1b0: Integrity sequence extent. Can be zero if cPartitionMaps is zero. */
+ UDFEXTENTAD IntegritySeqExtent;
+ /** 0x1b8: Partition maps (length given by @a cbMapTable), data format is
+ * defined by UDFPARTMAPHDR, UDFPARTMAPTYPE1 and UDFPARTMAPTYPE2. */
+ RT_FLEXIBLE_ARRAY_EXTENSION
+ uint8_t abPartitionMaps[RT_FLEXIBLE_ARRAY];
+} UDFLOGICALVOLUMEDESC;
+AssertCompileMemberOffset(UDFLOGICALVOLUMEDESC, abPartitionMaps, 0x1b8);
+/** Pointer to an UDF logical volume descriptor. */
+typedef UDFLOGICALVOLUMEDESC *PUDFLOGICALVOLUMEDESC;
+/** Pointer to a const UDF logical volume descriptor. */
+typedef UDFLOGICALVOLUMEDESC const *PCUDFLOGICALVOLUMEDESC;
+
+/**
+ * Partition map header (UDFLOGICALVOLUMEDESC::abPartitionMaps).
+ */
+typedef struct UDFPARTMAPHDR
+{
+ /** 0x00: The partition map type. */
+ uint8_t bType;
+ /** 0x01: The partition map length (header included). */
+ uint8_t cb;
+} UDFPARTMAPHDR;
+AssertCompileSize(UDFPARTMAPHDR, 2);
+/** Pointer to a partition map header. */
+typedef UDFPARTMAPHDR *PUDFPARTMAPHDR;
+/** Pointer to a const partition map header. */
+typedef UDFPARTMAPHDR const *PCUDFPARTMAPHDR;
+
+/**
+ * Partition map type 1 (UDFLOGICALVOLUMEDESC::abPartitionMaps).
+ */
+typedef struct UDFPARTMAPTYPE1
+{
+ /** 0x00: Header (uType=1, cb=6). */
+ UDFPARTMAPHDR Hdr;
+ /** 0x02: Volume sequence number. */
+ uint16_t uVolumeSeqNo;
+ /** 0x04: Partition number. */
+ uint16_t uPartitionNo;
+} UDFPARTMAPTYPE1;
+AssertCompileSize(UDFPARTMAPTYPE1, 6);
+/** Pointer to a type 1 partition map. */
+typedef UDFPARTMAPTYPE1 *PUDFPARTMAPTYPE1;
+/** Pointer to a const type 1 partition map. */
+typedef UDFPARTMAPTYPE1 const *PCUDFPARTMAPTYPE1;
+
+/**
+ * Partition map type 2 (UDFLOGICALVOLUMEDESC::abPartitionMaps).
+ */
+typedef struct UDFPARTMAPTYPE2
+{
+ /** 0x00: Header (uType=2, cb=64). */
+ UDFPARTMAPHDR Hdr;
+ /** 0x02: Reserved \#1. */
+ uint16_t uReserved1;
+ /** 0x04: Partition ID type (UDF_ENTITY_ID_VPM_PARTITION_TYPE,
+ * UDF_ENTITY_ID_SPM_PARTITION_TYPE, or UDF_ENTITY_ID_MPM_PARTITION_TYPE). */
+ UDFENTITYID idPartitionType;
+ /** 0x24: Volume sequence number. */
+ uint16_t uVolumeSeqNo;
+ /** 0x26: Partition number. */
+ uint16_t uPartitionNo;
+ /** 0x28: Data specific to the partition ID type. */
+ union
+ {
+ /** 0x28: Generic view. */
+ uint8_t ab[24];
+
+ /** UDF_ENTITY_ID_VPM_PARTITION_TYPE. */
+ struct
+ {
+ /** 0x28: Reserved. */
+ uint8_t abReserved2[24];
+ } Vpm;
+
+ /** UDF_ENTITY_ID_SPM_PARTITION_TYPE. */
+ struct
+ {
+ /** 0x28: Packet length in blocks. */
+ uint16_t cBlocksPerPacket;
+ /** 0x2a: Number of sparing tables. */
+ uint8_t cSparingTables;
+ /** 0x2b: Reserved padding byte. */
+ uint8_t bReserved2;
+ /** 0x2c: The size of each sparing table. */
+ uint32_t cbSparingTable;
+ /** 0x30: The sparing table locations (logical block). */
+ uint32_t aoffSparingTables[4];
+ } Spm;
+
+ /** UDF_ENTITY_ID_MPM_PARTITION_TYPE. */
+ struct
+ {
+ /** 0x28: Metadata file entry location (logical block). */
+ uint32_t offMetadataFile;
+ /** 0x2c: Metadata mirror file entry location (logical block). */
+ uint32_t offMetadataMirrorFile;
+ /** 0x30: Metadata bitmap file entry location (logical block). */
+ uint32_t offMetadataBitmapFile;
+ /** 0x34: The metadata allocation unit (logical blocks) */
+ uint32_t cBlocksAllocationUnit;
+ /** 0x38: The metadata allocation unit alignment (logical blocks). */
+ uint16_t cBlocksAlignmentUnit;
+ /** 0x3a: Flags, UDFPARTMAPMETADATA_F_XXX. */
+ uint8_t fFlags;
+ /** 0x3b: Reserved. */
+ uint8_t abReserved2[5];
+ } Mpm;
+ } u;
+} UDFPARTMAPTYPE2;
+AssertCompileSize(UDFPARTMAPTYPE2, 64);
+/** Pointer to a type 2 partition map. */
+typedef UDFPARTMAPTYPE2 *PUDFPARTMAPTYPE2;
+/** Pointer to a const type 2 partition map. */
+typedef UDFPARTMAPTYPE2 const *PCUDFPARTMAPTYPE2;
+
+/** @name UDFPARTMAPMETADATA_F_XXX
+ * @{ */
+/** Indicates that the metadata is mirrored too, not just the file entry. */
+#define UDFPARTMAPMETADATA_F_DATA_MIRRORED UINT8_C(1)
+/** @} */
+
+
+/**
+ * UDF unallocated space descriptor (USD) (@ecma167{3,10.8,61}, @udf260{2.2.5,32}).
+ *
+ * @note Variable length.
+ */
+typedef struct UDFUNALLOCATEDSPACEDESC
+{
+ /** 0x00: The descriptor tag (UDF_TAG_ID_UNALLOCATED_SPACE_DESC). */
+ UDFTAG Tag;
+ /** 0x10: Volume descriptor sequence number. */
+ uint32_t uVolumeDescSeqNo;
+ /** 0x14: Number of allocation descriptors in the array below. */
+ uint32_t cAllocationDescriptors;
+ /** 0x18: Allocation descriptors (variable length). */
+ RT_FLEXIBLE_ARRAY_EXTENSION
+ UDFEXTENTAD aAllocationDescriptors[RT_FLEXIBLE_ARRAY];
+} UDFUNALLOCATEDSPACEDESC;
+AssertCompileMemberOffset(UDFUNALLOCATEDSPACEDESC, aAllocationDescriptors, 0x18);
+/** Pointer to an UDF unallocated space descriptor. */
+typedef UDFUNALLOCATEDSPACEDESC *PUDFUNALLOCATEDSPACEDESC;
+/** Pointer to a const UDF unallocated space descriptor. */
+typedef UDFUNALLOCATEDSPACEDESC const *PCUDFUNALLOCATEDSPACEDESC;
+
+
+/**
+ * UDF terminating descriptor (@ecma167{3,10.9,62}, @ecma167{4,14.2,62}).
+ */
+typedef struct UDFTERMINATINGDESC
+{
+ /** 0x00: The descriptor tag (UDF_TAG_ID_TERMINATING_DESC). */
+ UDFTAG Tag;
+ /** 0x10: Reserved, MBZ. */
+ uint8_t abReserved[496];
+} UDFTERMINATINGDESC;
+/** Pointer to an UDF terminating descriptor. */
+typedef UDFTERMINATINGDESC *PUDFTERMINATINGDESC;
+/** Pointer to a const UDF terminating descriptor. */
+typedef UDFTERMINATINGDESC const *PCUDFTERMINATINGDESC;
+
+
+/**
+ * UDF logical volume integrity descriptor (LVID) (@ecma167{3,10.10,62},
+ * @udf260{2.2.6,32}).
+ */
+typedef struct UDFLOGICALVOLINTEGRITYDESC
+{
+ /** 0x00: The descriptor tag (UDF_TAG_ID_TERMINATING_DESC). */
+ UDFTAG Tag;
+ /** 0x10: Recording timestamp. */
+ UDFTIMESTAMP RecordingTimestamp;
+ /** 0x1c: Integrity type (UDF_LVID_TYPE_XXX). */
+ uint32_t uIntegrityType;
+ /** 0x20: The next integrity extent. */
+ UDFEXTENTAD NextIntegrityExtent;
+ /** 0x28: Number of partitions. */
+ uint32_t cPartitions;
+ /** 0x2c: Length of implementation use. */
+ uint32_t cbImplementationUse;
+ /**
+ * There are two tables each @a cPartitions in size. The first is the free
+ * space table. The second the size table.
+ *
+ * Following these tables there are @a cbImplementationUse bytes of space for
+ * the implementation to use.
+ */
+ RT_FLEXIBLE_ARRAY_EXTENSION
+ uint32_t aTables[RT_FLEXIBLE_ARRAY];
+} UDFLOGICALVOLINTEGRITYDESC;
+AssertCompileMemberOffset(UDFLOGICALVOLINTEGRITYDESC, cbImplementationUse, 0x2c);
+AssertCompileMemberOffset(UDFLOGICALVOLINTEGRITYDESC, aTables, 0x30);
+/** Pointer to an UDF logical volume integrity descriptor. */
+typedef UDFLOGICALVOLINTEGRITYDESC *PUDFLOGICALVOLINTEGRITYDESC;
+/** Pointer to a const UDF logical volume integrity descriptor. */
+typedef UDFLOGICALVOLINTEGRITYDESC const *PCUDFLOGICALVOLINTEGRITYDESC;
+
+/** @name UDF_LVID_TYPE_XXX - Integirty types.
+ * @{ */
+#define UDF_LVID_TYPE_OPEN UINT32_C(0x00000000)
+#define UDF_LVID_TYPE_CLOSE UINT32_C(0x00000001)
+/** @} */
+
+/**
+ * UDF file set descriptor (FSD) (@ecma167{4,14.1,86}, @udf260{2.3.2,54}).
+ */
+typedef struct UDFFILESETDESC
+{
+ /** 0x000: The descriptor tag (UDF_TAG_ID_FILE_SET_DESC). */
+ UDFTAG Tag;
+ /** 0x010: Recording timestamp. */
+ UDFTIMESTAMP RecordingTimestamp;
+ /** 0x01c: Interchange level. */
+ uint16_t uInterchangeLevel;
+ /** 0x01e: Maximum interchange level. */
+ uint16_t uMaxInterchangeLevel;
+ /** 0x020: Character set bitmask (aka list). Each bit correspond to a
+ * character set number. */
+ uint32_t fCharacterSets;
+ /** 0x024: Maximum character set bitmask (aka list). */
+ uint32_t fMaxCharacterSets;
+ /** 0x028: File set number. */
+ uint32_t uFileSetNo;
+ /** 0x02c: File set descriptor number. */
+ uint32_t uFileSetDescNo;
+ /** 0x030: Logical volume identifier character set. */
+ UDFCHARSPEC LogicalVolumeIDCharSet;
+ /** 0x070: Logical volume identifier string. */
+ UDFDSTRING achLogicalVolumeID[128];
+ /** 0x0e0: File set character set. */
+ UDFCHARSPEC FileSetCharSet;
+ /** 0x130: Identifier string for this file set. */
+ UDFDSTRING achFileSetID[32];
+ /** 0x150: Names a root file containing copyright info. Optional. */
+ UDFDSTRING achCopyrightFile[32];
+ /** 0x170: Names a root file containing an abstract for the file set. Optional. */
+ UDFDSTRING achAbstractFile[32];
+ /** 0x190: Root directory information control block location (ICB).
+ * An ICB is a sequence made up of UDF_TAG_ID_FILE_ENTRY,
+ * UDF_TAG_ID_INDIRECT_ENTRY, and UDF_TAG_ID_TERMINAL_ENTRY descriptors. */
+ UDFLONGAD RootDirIcb;
+ /** 0x1a0: Domain identifier (UDF_ENTITY_FSD_LVD_DOMAIN). Optional. */
+ UDFENTITYID idDomain;
+ /** 0x1c0: Next location with file set descriptors location, 0 if none. */
+ UDFLONGAD NextExtent;
+ /** 0x1d0: Location of the system stream directory associated with the
+ * file set. Optional. */
+ UDFLONGAD SystemStreamDirIcb;
+ /** 0x1e0: Reserved, MBZ. */
+ uint8_t abReserved[32];
+} UDFFILESETDESC;
+AssertCompileSize(UDFFILESETDESC, 512);
+/** Pointer to an UDF file set descriptor. */
+typedef UDFFILESETDESC *PUDFFILESETDESC;
+/** Pointer to a const UDF file set descriptor. */
+typedef UDFFILESETDESC const *PCUDFFILESETDESC;
+
+
+/**
+ * UDF file identifier descriptor (FID) (@ecma167{4,14.4,91}, @udf260{2.3.4,57}).
+ */
+typedef struct UDFFILEIDDESC
+{
+ /** 0x00: The descriptor tag (UDF_TAG_ID_FILE_ID_DESC). */
+ UDFTAG Tag;
+ /** 0x10: File version number (1..32767). Always set to 1. */
+ uint16_t uVersion;
+ /** 0x12: File characteristics (UDF_FILE_FLAGS_XXX). */
+ uint8_t fFlags;
+ /** 0x13: File identifier (name) length. */
+ uint8_t cbName;
+ /** 0x14: Location of an information control block describing the file.
+ * Can be null if marked deleted. The implementation defined part of
+ * this contains additional flags and a unique ID. */
+ UDFLONGAD Icb;
+ /** 0x24: Length of implementation use field (in bytes). This can be zero.
+ *
+ * It can be used to prevent the following FID from spanning a block
+ * boundrary, in which case it will be 32 bytes or more, and the it will
+ * start with an UDFENTITYID identifying who last wrote it.
+ *
+ * The latter padding fun is a requirement from write-once media. */
+ uint16_t cbImplementationUse;
+ /** 0x26: Two variable sized fields followed by padding to make the
+ * actual structure size 4 byte aligned. The first field in an
+ * implementation use field with length given by @a cbImplementationUse.
+ * After that is a d-string field with the name of the file, length
+ * specified by @a cbName. */
+ RT_FLEXIBLE_ARRAY_EXTENSION
+ uint8_t abImplementationUse[RT_FLEXIBLE_ARRAY];
+} UDFFILEIDDESC;
+AssertCompileMemberOffset(UDFFILEIDDESC, fFlags, 0x12);
+AssertCompileMemberOffset(UDFFILEIDDESC, cbName, 0x13);
+AssertCompileMemberOffset(UDFFILEIDDESC, Icb, 0x14);
+AssertCompileMemberOffset(UDFFILEIDDESC, abImplementationUse, 0x26);
+/** Pointer to an UDF file set descriptor */
+typedef UDFFILEIDDESC *PUDFFILEIDDESC;
+/** Pointer to a const UDF file set descriptor */
+typedef UDFFILEIDDESC const *PCUDFFILEIDDESC;
+
+/** Get the pointer to the name field. */
+#define UDFFILEIDDESC_2_NAME(a_pFid) ((uint8_t const *)(&(a_pFid)->abImplementationUse[(a_pFid)->cbImplementationUse]))
+/** Calculates the total size the size of a record. */
+#define UDFFILEIDDESC_CALC_SIZE_EX(cbImplementationUse, cbName) \
+ RT_ALIGN_32((uint32_t)RT_UOFFSETOF(UDFFILEIDDESC, abImplementationUse) + cbImplementationUse + cbName, 4)
+/** Gets the actual size of a record. */
+#define UDFFILEIDDESC_GET_SIZE(a_pFid) UDFFILEIDDESC_CALC_SIZE_EX((a_pFid)->cbImplementationUse, (a_pFid)->cbName)
+
+/** @name UDF_FILE_FLAGS_XXX
+ * @{ */
+/** Existence - Hide the file from the user. */
+#define UDF_FILE_FLAGS_HIDDEN UINT8_C(0x01)
+/** Directory - Indicates a directory as apposed to some kind of file or symlink or something (0). */
+#define UDF_FILE_FLAGS_DIRECTORY UINT8_C(0x02)
+/** Deleted - Indicate that the file has been deleted. Assoicated descriptors may still be valid, though. */
+#define UDF_FILE_FLAGS_DELETED UINT8_C(0x04)
+/** Parent - Indicate the ICB field refers to the parent directory (or maybe
+ * a file in case of streaming directory). */
+#define UDF_FILE_FLAGS_PARENT UINT8_C(0x08)
+/** Metadata - Zero means user data, one means implementation specific metadata.
+ * Only allowed used in stream directory. */
+#define UDF_FILE_FLAGS_METADATA UINT8_C(0x10)
+/** Reserved bits that should be zer. */
+#define UDF_FILE_FLAGS_RESERVED_MASK UINT8_C(0xe0)
+/** @} */
+
+
+/**
+ * UDF allocation extent descriptor (@ecma167{4,14.5,93}, @udf260{2.3.11,67}).
+ */
+typedef struct UDFALLOCATIONEXTENTDESC
+{
+ /** 0x00: The descriptor tag (UDF_TAG_ID_ALLOCATION_EXTENT_DESC). */
+ UDFTAG Tag;
+ /** 0x10: Previous allocation extent location (logical block in current
+ * partition). */
+ uint32_t offPrevExtent;
+ /** 0x14: Size of the following allocation descriptors (in bytes). */
+ uint32_t cbAllocDescs;
+ /** 0x18: Allocation descriptors. */
+ union
+ {
+ UDFSHORTAD aShortADs[RT_FLEXIBLE_ARRAY_IN_NESTED_UNION];
+ UDFLONGAD aLongADs[RT_FLEXIBLE_ARRAY_IN_NESTED_UNION];
+ UDFEXTAD aExtADs[RT_FLEXIBLE_ARRAY_IN_NESTED_UNION];
+ } u;
+} UDFALLOCATIONEXTENTDESC;
+AssertCompileMemberOffset(UDFALLOCATIONEXTENTDESC, u, 0x18);
+/** Pointer to an UDF allocation extent descriptor. */
+typedef UDFALLOCATIONEXTENTDESC *PUDFALLOCATIONEXTENTDESC;
+/** Pointer to a const UDF allocation extent descriptor. */
+typedef UDFALLOCATIONEXTENTDESC const *PCUDFALLOCATIONEXTENTDESC;
+
+/**
+ * UDF information control block tag (@ecma167{4,14.6,93}, @udf260{2.3.5,60}).
+ */
+typedef struct UDFICBTAG
+{
+ /** 0x00: Number of direct entries in this ICB prior to this one. */
+ uint32_t cEntiresBeforeThis;
+ /** 0x04: ICB hierarchy building strategy type (UDF_ICB_STRATEGY_TYPE_XXX). */
+ uint16_t uStrategyType;
+ /** 0x06: Type specific parameters. */
+ uint8_t abStrategyParams[2];
+ /** 0x08: Max number of direct and indirect entries that MAY be recorded in this ICB. */
+ uint16_t cMaxEntries;
+ /** 0x0a: Reserved, MBZ. */
+ uint8_t bReserved;
+ /** 0x0b: File type (UDF_FILE_TYPE_XXX). */
+ uint8_t bFileType;
+ /** 0x0c: Parent ICB location. */
+ UDFLBADDR ParentIcb;
+ /** 0x12: Parent ICB location (UDF_ICB_FLAGS_XXX). */
+ uint16_t fFlags;
+} UDFICBTAG;
+AssertCompileSize(UDFICBTAG, 20);
+typedef UDFICBTAG *PUDFICBTAG;
+typedef UDFICBTAG const *PCUDFICBTAG;
+
+/** @name UDF_ICB_STRATEGY_TYPE_XXX - ICB hierarchy building strategies
+ *
+ * See @ecma167{4,14.6.2,94}, @udf260{6.6,121}
+ *
+ * @{ */
+/** Strategy not specified. */
+#define UDF_ICB_STRATEGY_TYPE_NOT_SPECIFIED UINT16_C(0x0000)
+/** See @ecma167{4,A.2,129}. */
+#define UDF_ICB_STRATEGY_TYPE_1 UINT16_C(0x0001)
+/** See @ecma167{4,A.3,131}. */
+#define UDF_ICB_STRATEGY_TYPE_2 UINT16_C(0x0002)
+/** See @ecma167{4,A.4,131}. */
+#define UDF_ICB_STRATEGY_TYPE_3 UINT16_C(0x0003)
+/** See @ecma167{4,A.5,131}. */
+#define UDF_ICB_STRATEGY_TYPE_4 UINT16_C(0x0004)
+/** Defined by the UDF spec, see @udf260{6.6,121}. */
+#define UDF_ICB_STRATEGY_TYPE_4096 UINT16_C(0x1000)
+/** @} */
+
+/** @name UDF_ICB_FLAGS_XXX - ICB flags
+ *
+ * See @ecma167{4,14.6.8,95}, @udf260{2.3.5.4,61}
+ *
+ * @{ */
+/** Using UDFSHORTAD. */
+#define UDF_ICB_FLAGS_AD_TYPE_SHORT UINT16_C(0x0000)
+/** Using UDFLONGAD. */
+#define UDF_ICB_FLAGS_AD_TYPE_LONG UINT16_C(0x0001)
+/** Using UDFEXTAD. */
+#define UDF_ICB_FLAGS_AD_TYPE_EXTENDED UINT16_C(0x0002)
+/** File content is embedded in the allocation descriptor area. */
+#define UDF_ICB_FLAGS_AD_TYPE_EMBEDDED UINT16_C(0x0003)
+/** Allocation type mask. */
+#define UDF_ICB_FLAGS_AD_TYPE_MASK UINT16_C(0x0007)
+/** Set on directories that are sorted (according to @ecma167{4,8.6.1,78}).
+ * @note Directories are never sorted in UDF. */
+#define UDF_ICB_FLAGS_SORTED_DIRECTORY UINT16_C(0x0008)
+/** Not relocatable. */
+#define UDF_ICB_FLAGS_NON_RELOCATABLE UINT16_C(0x0010)
+/** Indicate that the file needs backing up (DOS attribute). */
+#define UDF_ICB_FLAGS_ARCHIVE UINT16_C(0x0020)
+/** Set UID bit (UNIX). */
+#define UDF_ICB_FLAGS_SET_UID UINT16_C(0x0040)
+/** Set GID bit (UNIX). */
+#define UDF_ICB_FLAGS_SET_GID UINT16_C(0x0080)
+/** Set sticky bit (UNIX). */
+#define UDF_ICB_FLAGS_STICKY UINT16_C(0x0100)
+/** Extents are contiguous. */
+#define UDF_ICB_FLAGS_CONTIGUOUS UINT16_C(0x0200)
+/** System bit, reserved for implementation use. */
+#define UDF_ICB_FLAGS_SYSTEM UINT16_C(0x0400)
+/** Data has been transformed in some way.
+ * @note UDF shall not set this bit. */
+#define UDF_ICB_FLAGS_TRANSFORMED UINT16_C(0x0800)
+/** Directory may contain multi-versioned files.
+ * @note UDF shall not set this bit. */
+#define UDF_ICB_FLAGS_MULTI_VERSIONS UINT16_C(0x1000)
+/** Is a stream in a stream directory. */
+#define UDF_ICB_FLAGS_STREAM UINT16_C(0x2000)
+/** Reserved mask. */
+#define UDF_ICB_FLAGS_RESERVED_MASK UINT16_C(0xc000)
+/** @} */
+
+/** @name UDF_FILE_TYPE_XXX - File types
+ *
+ * See @ecma167{4,14.6.6,94}, @udf260{2.3.5.2,60}
+ *
+ * @{ */
+#define UDF_FILE_TYPE_NOT_SPECIFIED UINT8_C(0x00) /**< Not specified by this field. */
+#define UDF_FILE_TYPE_UNALLOCATED_SPACE_ENTRY UINT8_C(0x01)
+#define UDF_FILE_TYPE_PARTITION_INTEGRITY_ENTRY UINT8_C(0x02)
+#define UDF_FILE_TYPE_INDIRECT_ENTRY UINT8_C(0x03)
+#define UDF_FILE_TYPE_DIRECTORY UINT8_C(0x04)
+#define UDF_FILE_TYPE_REGULAR_FILE UINT8_C(0x05)
+#define UDF_FILE_TYPE_BLOCK_DEVICE UINT8_C(0x06)
+#define UDF_FILE_TYPE_CHARACTER_DEVICE UINT8_C(0x07)
+#define UDF_FILE_TYPE_EXTENDED_ATTRIBUTES UINT8_C(0x08)
+#define UDF_FILE_TYPE_FIFO UINT8_C(0x09)
+#define UDF_FILE_TYPE_SOCKET UINT8_C(0x0a)
+#define UDF_FILE_TYPE_TERMINAL_ENTRY UINT8_C(0x0b)
+#define UDF_FILE_TYPE_SYMBOLIC_LINK UINT8_C(0x0c)
+#define UDF_FILE_TYPE_STREAM_DIRECTORY UINT8_C(0x0d)
+#define UDF_FILE_TYPE_VAT UINT8_C(0xf8)
+#define UDF_FILE_TYPE_REAL_TIME_FILE UINT8_C(0xf9)
+#define UDF_FILE_TYPE_METADATA_FILE UINT8_C(0xfa)
+#define UDF_FILE_TYPE_METADATA_MIRROR_FILE UINT8_C(0xfb)
+#define UDF_FILE_TYPE_METADATA_BITMAP_FILE UINT8_C(0xfc)
+/** @} */
+
+
+/**
+ * UDF ICB header (derived structure).
+ */
+typedef struct UDFICBHDR
+{
+ /** 0x00: The descriptor tag (UDF_TAG_ID_INDIRECT_ENTRY). */
+ UDFTAG Tag;
+ /** 0x10: ICB Tag. */
+ UDFICBTAG IcbTag;
+} UDFICBHDR;
+AssertCompileSize(UDFICBHDR, 36);
+/** Pointer to an UDF ICB header. */
+typedef UDFICBHDR *PUDFICBHDR;
+/** Pointer to a const UDF ICB header. */
+typedef UDFICBHDR const *PCUDFICBHDR;
+
+
+/**
+ * UDF indirect entry (@ecma167{4,14.7,96}).
+ */
+typedef struct UDFINDIRECTENTRY
+{
+ /** 0x00: The descriptor tag (UDF_TAG_ID_INDIRECT_ENTRY). */
+ UDFTAG Tag;
+ /** 0x10: ICB Tag. */
+ UDFICBTAG IcbTag;
+ /** 0x24: Indirect ICB location. */
+ UDFLONGAD IndirectIcb;
+} UDFINDIRECTENTRY;
+AssertCompileSize(UDFINDIRECTENTRY, 52);
+/** Pointer to an UDF indirect entry. */
+typedef UDFINDIRECTENTRY *PUDFINDIRECTENTRY;
+/** Pointer to a const UDF indirect entry. */
+typedef UDFINDIRECTENTRY const *PCUDFINDIRECTENTRY;
+
+
+/**
+ * UDF terminal entry (@ecma167{4,14.8,97}).
+ */
+typedef struct UDFTERMINALENTRY
+{
+ /** 0x00: The descriptor tag (UDF_TAG_ID_TERMINAL_ENTRY). */
+ UDFTAG Tag;
+ /** 0x10: ICB Tag (UDF_FILE_TYPE_TERMINAL_ENTRY). */
+ UDFICBTAG IcbTag;
+} UDFTERMINALENTRY;
+AssertCompileSize(UDFTERMINALENTRY, 36);
+/** Pointer to an UDF terminal entry. */
+typedef UDFTERMINALENTRY *PUDFTERMINALENTRY;
+/** Pointer to a const UDF terminal entry. */
+typedef UDFTERMINALENTRY const *PCUDFTERMINALENTRY;
+
+
+/**
+ * UDF file entry (FE) (@ecma167{4,14.8,97}, @udf260{2.3.6,62}).
+ *
+ * @note Total length shall not exceed one logical block.
+ */
+typedef struct UDFFILEENTRY
+{
+ /** 0x00: The descriptor tag (UDF_TAG_ID_FILE_ENTRY). */
+ UDFTAG Tag;
+ /** 0x10: ICB Tag. */
+ UDFICBTAG IcbTag;
+ /** 0x24: User ID (UNIX). */
+ uint32_t uid;
+ /** 0x28: Group ID (UNIX). */
+ uint32_t gid;
+ /** 0x2c: Permission (UDF_PERM_XXX). */
+ uint32_t fPermissions;
+ /** 0x30: Number hard links. */
+ uint16_t cHardlinks;
+ /** 0x32: Record format (UDF_REC_FMT_XXX). */
+ uint8_t uRecordFormat;
+ /** 0x33: Record format (UDF_REC_ATTR_XXX). */
+ uint8_t fRecordDisplayAttribs;
+ /** 0x34: Record length (in bytes).
+ * @note Must be zero according to the UDF specification. */
+ uint32_t cbRecord;
+ /** 0x38: Information length in bytes (file size). */
+ uint64_t cbData;
+ /** 0x40: Number of logical blocks allocated (for file data). */
+ uint64_t cLogicalBlocks;
+ /** 0x48: Time of last access (prior to recording the file entry). */
+ UDFTIMESTAMP AccessTime;
+ /** 0x54: Time of last data modification. */
+ UDFTIMESTAMP ModificationTime;
+ /** 0x60: Time of last attribute/status modification. */
+ UDFTIMESTAMP ChangeTime;
+ /** 0x6c: Checkpoint number (defaults to 1). */
+ uint32_t uCheckpoint;
+ /** 0x70: Extended attribute information control block location. */
+ UDFLONGAD ExtAttribIcb;
+ /** 0x80: Implementation identifier ("*Developer ID"). */
+ UDFENTITYID idImplementation;
+ /** 0xa0: Unique ID. */
+ uint64_t INodeId;
+ /** 0xa8: Length of extended attributes in bytes, multiple of four. */
+ uint32_t cbExtAttribs;
+ /** 0xac: Length of allocation descriptors in bytes, multiple of four. */
+ uint32_t cbAllocDescs;
+ /** 0xb0: Two variable sized fields. First @a cbExtAttribs bytes of extended
+ * attributes, then @a cbAllocDescs bytes of allocation descriptors. */
+ RT_FLEXIBLE_ARRAY_EXTENSION
+ uint8_t abExtAttribs[RT_FLEXIBLE_ARRAY];
+} UDFFILEENTRY;
+AssertCompileMemberOffset(UDFFILEENTRY, abExtAttribs, 0xb0);
+/** Pointer to an UDF file entry. */
+typedef UDFFILEENTRY *PUDFFILEENTRY;
+/** Pointer to a const UDF file entry. */
+typedef UDFFILEENTRY const *PCUDFFILEENTRY;
+
+/** @name UDF_PERM_XXX - UDFFILEENTRY::fPermissions
+ * See @ecma167{4,14.9.5,99}.
+ * @{ */
+#define UDF_PERM_OTH_EXEC UINT32_C(0x00000001)
+#define UDF_PERM_OTH_WRITE UINT32_C(0x00000002)
+#define UDF_PERM_OTH_READ UINT32_C(0x00000004)
+#define UDF_PERM_OTH_ATTRIB UINT32_C(0x00000008)
+#define UDF_PERM_OTH_DELETE UINT32_C(0x00000010)
+#define UDF_PERM_OTH_MASK UINT32_C(0x0000001f)
+
+#define UDF_PERM_GRP_EXEC UINT32_C(0x00000020)
+#define UDF_PERM_GRP_WRITE UINT32_C(0x00000040)
+#define UDF_PERM_GRP_READ UINT32_C(0x00000080)
+#define UDF_PERM_GRP_ATTRIB UINT32_C(0x00000100)
+#define UDF_PERM_GRP_DELETE UINT32_C(0x00000200)
+#define UDF_PERM_GRP_MASK UINT32_C(0x000003e0)
+
+#define UDF_PERM_USR_EXEC UINT32_C(0x00000400)
+#define UDF_PERM_USR_WRITE UINT32_C(0x00000800)
+#define UDF_PERM_USR_READ UINT32_C(0x00001000)
+#define UDF_PERM_USR_ATTRIB UINT32_C(0x00002000)
+#define UDF_PERM_USR_DELETE UINT32_C(0x00004000)
+#define UDF_PERM_USR_MASK UINT32_C(0x00007c00)
+
+#define UDF_PERM_USR_RESERVED_MASK UINT32_C(0xffff8000)
+/** @} */
+
+/** @name UDF_REC_FMT_XXX - Record format.
+ * See @ecma167{4,14.9.7,100}.
+ * @{ */
+/** Not record format specified.
+ * @note The only allowed value according to the UDF specification. */
+#define UDF_REC_FMT_NOT_SPECIFIED UINT8_C(0x00)
+/** @} */
+
+/** @name UDF_REC_ATTR_XXX - Record display attributes.
+ * See @ecma167{4,14.9.8,100}.
+ * @{ */
+/** Manner of record display not specified.
+ * @note The only allowed value according to the UDF specification. */
+#define UDF_REC_ATTR_NOT_SPECIFIED UINT8_C(0x00)
+/** @} */
+
+
+/**
+ * UDF extended attribute header descriptor (@ecma167{4,14.10.1,102},
+ * @udf260{3.3.4,79}).
+ */
+typedef struct UDFEXTATTRIBHDRDESC
+{
+ /** 0x00: The descriptor tag (UDF_TAG_ID_EXTENDED_ATTRIB_HDR_DESC). */
+ UDFTAG Tag;
+ /** 0x10: Implementation attributes location (byte offset) into the EA space.
+ * This typically set to UINT32_MAX if not present, though any value larger
+ * than the EA space will do. */
+ uint32_t offImplementationAttribs;
+ /** 0x14: Application attributes location (byte offset) into the EA space.
+ * This typically set to UINT32_MAX if not present, though any value larger
+ * than the EA space will do. */
+ uint32_t offApplicationAttribs;
+} UDFEXTATTRIBHDRDESC;
+AssertCompileSize(UDFEXTATTRIBHDRDESC, 24);
+/** Pointer to an UDF extended attribute header descriptor. */
+typedef UDFEXTATTRIBHDRDESC *PUDFEXTATTRIBHDRDESC;
+/** Pointer to a const UDF extended attribute header descriptor. */
+typedef UDFEXTATTRIBHDRDESC const *PCUDFEXTATTRIBHDRDESC;
+
+/**
+ * UDF character set info EA data (@ecma167{4,14.10.3,104}).
+ *
+ * Not needed by UDF.
+ */
+typedef struct UDFEADATACHARSETINFO
+{
+ /** 0x00/0x0c: The length of the escape sequences (in bytes). */
+ uint32_t cbEscSeqs;
+ /** 0x04/0x10: The character set type (UDF_CHAR_SET_TYPE_XXX). */
+ uint8_t bType;
+ /** 0x05/0x11: Escape sequences. */
+ uint8_t abEscSeqs[RT_FLEXIBLE_ARRAY_IN_NESTED_UNION];
+} UDFEADATACHARSETINFO;
+/** Pointer to UDF character set info EA data. */
+typedef UDFEADATACHARSETINFO *PUDFEADATACHARSETINFO;
+/** Pointer to const UDF character set info EA data. */
+typedef UDFEADATACHARSETINFO const *PCUDFEADATACHARSETINFO;
+/** UDFGEA::uAttribType value for UDFEADATACHARSETINFO.*/
+#define UDFEADATACHARSETINFO_ATTRIB_TYPE UINT32_C(0x00000001)
+/** UDFGEA::uAttribSubtype value for UDFEADATACHARSETINFO. */
+#define UDFEADATACHARSETINFO_ATTRIB_SUBTYPE UINT32_C(0x00000001)
+
+/**
+ * UDF alternate permissions EA data (@ecma167{4,14.10.4,105}, @udf260{3.3.4.2,80}).
+ * @note Not recorded according to the UDF specification.
+ */
+typedef struct UDFEADATAALTPERM
+{
+ /** 0x00/0x0c: Alternative owner ID. */
+ uint16_t idOwner;
+ /** 0x02/0x0e: Alternative group ID. */
+ uint16_t idGroup;
+ /** 0x04/0x10: Alternative permissions. */
+ uint16_t fPermission;
+} UDFEADATAALTPERM;
+/** Pointer to UDF alternative permissions EA data. */
+typedef UDFEADATAALTPERM *PUDFEADATAALTPERM;
+/** Pointer to const UDF alternative permissions EA data. */
+typedef UDFEADATAALTPERM const *PCUDFEADATAALTPERM;
+/** UDFGEA::uAttribType value for UDFEADATAALTPERM. */
+#define UDFEADATAALTPERM_ATTRIB_TYPE UINT32_C(0x00000003)
+/** UDFGEA::uAttribSubtype value for UDFEADATAALTPERM. */
+#define UDFEADATAALTPERM_ATTRIB_SUBTYPE UINT32_C(0x00000001)
+
+/**
+ * UDF file times EA data (@ecma167{4,14.10.5,108}, @udf260{3.3.4.3,80}).
+ * (This is a bit reminiscent of ISO9660RRIPTF.)
+ */
+typedef struct UDFEADATAFILETIMES
+{
+ /** 0x00/0x0c: Timestamp length. */
+ uint32_t cbTimestamps;
+ /** 0x04/0x10: Indicates which timestamps are present
+ * (UDF_FILE_TIMES_EA_F_XXX). */
+ uint32_t fFlags;
+ /** 0x08/0x14: Timestamps. */
+ UDFTIMESTAMP aTimestamps[RT_FLEXIBLE_ARRAY_IN_NESTED_UNION];
+} UDFEADATAFILETIMES;
+/** Pointer to UDF file times EA data. */
+typedef UDFEADATAFILETIMES *PUDFEADATAFILETIMES;
+/** Pointer to const UDF file times EA data. */
+typedef UDFEADATAFILETIMES const *PCUDFEADATAFILETIMES;
+/** UDFGEA::uAttribType value for UDFEADATAFILETIMES. */
+#define UDFEADATAFILETIMES_ATTRIB_TYPE UINT32_C(0x00000005)
+/** UDFGEA::uAttribSubtype value for UDFEADATAFILETIMES. */
+#define UDFEADATAFILETIMES_ATTRIB_SUBTYPE UINT32_C(0x00000001)
+
+/** @name UDF_FILE_TIMES_EA_F_XXX - File times existence flags.
+ * See @ecma167{4,14.10.5.6,109}
+ * @{ */
+#define UDF_FILE_TIMES_EA_F_BIRTH UINT8_C(0x01) /**< Birth (creation) timestamp is recorded. */
+#define UDF_FILE_TIMES_EA_F_DELETE UINT8_C(0x04) /**< Deletion timestamp is recorded. */
+#define UDF_FILE_TIMES_EA_F_EFFECTIVE UINT8_C(0x08) /**< Effective timestamp is recorded. */
+#define UDF_FILE_TIMES_EA_F_BACKUP UINT8_C(0x20) /**< Backup timestamp is recorded. */
+#define UDF_FILE_TIMES_EA_F_RESERVED_MASK UINT8_C(0xd2)
+/** @} */
+
+/**
+ * UDF information times EA data (@ecma167{4,14.10.6,109}).
+ */
+typedef struct UDFEADATAINFOTIMES
+{
+ /** 0x00/0x0c: Timestamp length. */
+ uint32_t cbTimestamps;
+ /** 0x04/0x10: Indicates which timestamps are present
+ * (UDF_INFO_TIMES_EA_F_XXX). */
+ uint32_t fFlags;
+ /** 0x08/0x14: Timestamps. */
+ UDFTIMESTAMP aTimestamps[RT_FLEXIBLE_ARRAY_IN_NESTED_UNION];
+} UDFEADATAINFOTIMES;
+/** Pointer to UDF information times EA data. */
+typedef UDFEADATAINFOTIMES *PUDFEADATAINFOTIMES;
+/** Pointer to const UDF information times EA data. */
+typedef UDFEADATAINFOTIMES const *PCUDFEADATAINFOTIMES;
+/** UDFGEA::uAttribType value for UDFEADATAINFOTIMES. */
+#define UDFEADATAINFOTIMES_ATTRIB_TYPE UINT32_C(0x00000006)
+/** UDFGEA::uAttribSubtype value for UDFEADATAINFOTIMES. */
+#define UDFEADATAINFOTIMES_ATTRIB_SUBTYPE UINT32_C(0x00000001)
+
+/** @name UDF_INFO_TIMES_EA_F_XXX - Information times existence flags.
+ * See @ecma167{4,14.10.6.6,110}
+ * @{ */
+#define UDF_INFO_TIMES_EA_F_BIRTH UINT8_C(0x01) /**< Birth (creation) timestamp is recorded. */
+#define UDF_INFO_TIMES_EA_F_MODIFIED UINT8_C(0x02) /**< Last (data) modified timestamp is recorded. */
+#define UDF_INFO_TIMES_EA_F_EXPIRE UINT8_C(0x04) /**< Expiration (deletion) timestamp is recorded. */
+#define UDF_INFO_TIMES_EA_F_EFFECTIVE UINT8_C(0x08) /**< Effective timestamp is recorded. */
+#define UDF_INFO_TIMES_EA_F_RESERVED_MASK UINT8_C(0xf0)
+/** @} */
+
+/**
+ * UDF device specification EA data (@ecma167{4,14.10.7,110}, @udf260{3.3.4.4,81}).
+ */
+typedef struct UDFEADATADEVICESPEC
+{
+ /** 0x00/0x0c: Length of implementation use field. */
+ uint32_t cbImplementationUse;
+ /** 0x04/0x10: Major device number. */
+ uint32_t uMajorDeviceNo;
+ /** 0x08/0x14: Minor device number. */
+ uint32_t uMinorDeviceNo;
+ /** 0x0c/0x18: Implementation use field (variable length).
+ * UDF specficiation expects UDFENTITYID with a "*Developer ID" as first part
+ * here. */
+ uint8_t abImplementationUse[RT_FLEXIBLE_ARRAY_IN_NESTED_UNION];
+} UDFEADATADEVICESPEC;
+/** Pointer to UDF device specification EA data. */
+typedef UDFEADATADEVICESPEC *PUDFEADATADEVICESPEC;
+/** Pointer to const UDF device specification EA data. */
+typedef UDFEADATADEVICESPEC const *PCUDFEADATADEVICESPEC;
+/** UDFGEA::uAttribType value for UDFEADATADEVICESPEC. */
+#define UDFEADATADEVICESPEC_ATTRIB_TYPE UINT32_C(0x0000000c)
+/** UDFGEA::uAttribSubtype value for UDFEADATADEVICESPEC. */
+#define UDFEADATADEVICESPEC_ATTRIB_SUBTYPE UINT32_C(0x00000001)
+
+/**
+ * UDF free EA space payload for implementation and application use EAs
+ * (@udf260{3.3.4.5.1.1,82}, @udf260{3.3.4.6.1.1,88}).
+ *
+ * UDFEADATAIMPLUSE::idImplementation is UDF_ENTITY_ID_IUEA_FREE_EA_SPACE.
+ * UDFEADATAAPPUSE::idImplementation is UDF_ENTITY_ID_AUEA_FREE_EA_SPACE.
+ */
+typedef struct UDFFREEEASPACE
+{
+ /** 0x00/0x30: Header checksum.
+ * @note 16-bit checksum of UDFGEA up thru u.ImplUse.idImplementation. */
+ uint16_t uChecksum;
+ /** 0x02/0x32: Free space. */
+ uint8_t abFree[RT_FLEXIBLE_ARRAY_IN_NESTED_UNION];
+} UDFFREEEASPACE;
+/** Pointer to UDF free EA space impl/app use payload. */
+typedef UDFFREEEASPACE *PUDFFREEEASPACE;
+/** Pointer to const UDF free EA space impl/app use payload. */
+typedef UDFFREEEASPACE const *PCUDFFREEEASPACE;
+
+/**
+ * UDF DVD copyright management information implementation use EA payload
+ * (@udf260{3.3.4.5.1.2,83}).
+ *
+ * UDFEADATAIMPLUSE::idImplementation is UDF_ENTITY_ID_IUEA_DVD_CGMS_INFO.
+ */
+typedef struct UDFIUEADVDCGMSINFO
+{
+ /** 0x00/0x30: Header checksum.
+ * @note 16-bit checksum of UDFGEA up thru u.ImplUse.idImplementation. */
+ uint16_t uChecksum;
+ /** 0x02/0x32: The CGMS information (whatever that is). */
+ uint8_t bInfo;
+ /** 0x03/0x33: Data structure type (whatever that is). */
+ uint8_t bType;
+ /** 0x04/0x34: Production system information, probably dependend on the
+ * values of previous fields. */
+ uint8_t abProtSysInfo[4];
+} UDFIUEADVDCGMSINFO;
+/** Pointer to UDF DVD copyright management information implementation use EA payload. */
+typedef UDFIUEADVDCGMSINFO *PUDFIUEADVDCGMSINFO;
+/** Pointer to const UDF DVD copyright management information implementation use EA payload. */
+typedef UDFIUEADVDCGMSINFO const *PCUDFIUEADVDCGMSINFO;
+
+/**
+ * UDF OS/2 EA length implementation use EA payload (@udf260{3.3.4.5.3.1,84}).
+ *
+ * UDFEADATAIMPLUSE::idImplementation is UDF_ENTITY_ID_IUEA_OS2_EA_LENGTH.
+ */
+#pragma pack(2)
+typedef struct UDFIUEAOS2EALENGTH
+{
+ /** 0x00/0x30: Header checksum.
+ * @note 16-bit checksum of UDFGEA up thru u.ImplUse.idImplementation. */
+ uint16_t uChecksum;
+ /** 0x02/0x32: The CGMS information (whatever that is). */
+ uint32_t cbEAs;
+} UDFIUEAOS2EALENGTH;
+#pragma pack()
+AssertCompileMemberOffset(UDFIUEAOS2EALENGTH, cbEAs, 2);
+/** Pointer to UDF OS/2 EA length implementation use EA payload. */
+typedef UDFIUEAOS2EALENGTH *PUDFIUEAOS2EALENGTH;
+/** Pointer to const UDF OS/2 EA length implementation use EA payload. */
+typedef UDFIUEAOS2EALENGTH const *PCUDFIUEAOS2EALENGTH;
+
+/**
+ * UDF Mac volume info implementation use EA payload (@udf260{3.3.4.5.4.1,84}).
+ *
+ * UDFEADATAIMPLUSE::idImplementation is UDF_ENTITY_ID_IUEA_MAC_VOLUME_INFO.
+ */
+#pragma pack(2)
+typedef struct UDFIUEAMACVOLINFO
+{
+ /** 0x00/0x30: Header checksum.
+ * @note 16-bit checksum of UDFGEA up thru u.ImplUse.idImplementation. */
+ uint16_t uChecksum;
+ /** 0x02/0x32: Last modification time. */
+ UDFTIMESTAMP LastModificationTime;
+ /** 0x0e/0x3e: Last backup time. */
+ UDFTIMESTAMP LastBackupTime;
+ /** 0x1a/0x4e: Volume finder information. */
+ uint32_t au32FinderInfo[8];
+} UDFIUEAMACVOLINFO;
+#pragma pack()
+AssertCompileMemberOffset(UDFIUEAMACVOLINFO, au32FinderInfo, 0x1a);
+/** Pointer to UDF Mac volume info implementation use EA payload. */
+typedef UDFIUEAMACVOLINFO *PUDFIUEAMACVOLINFO;
+/** Pointer to const UDF Mac volume info implementation use EA payload. */
+typedef UDFIUEAMACVOLINFO const *PCUDFIUEAMACVOLINFO;
+
+/**
+ * UDF point for use in Mac EAs (@udf260{3.3.4.5.4.2,86}).
+ */
+typedef struct UDFMACPOINT
+{
+ /** X coordinate. */
+ int16_t x;
+ /** Y coordinate. */
+ int16_t y;
+} UDFMACPOINT;
+
+/**
+ * UDF rectangle for using Mac EAs (@udf260{3.3.4.5.4.2,86}).
+ */
+typedef struct UDFMACRECT
+{
+ /** top Y coordinate. */
+ int16_t yTop;
+ /** left X coordinate. */
+ int16_t xLeft;
+ /** bottom Y coordinate. (exclusive?) */
+ int16_t yBottom;
+ /** right X coordinate. (exclusive?) */
+ int16_t xRight;
+} UDFMACRECT;
+
+/**
+ * UDF finder directory info for Mac EAs (@udf260{3.3.4.5.4.2,86}).
+ */
+typedef struct UDFMACFDINFO
+{
+ UDFMACRECT FrRect;
+ int16_t FrFlags;
+ UDFMACPOINT FrLocation;
+ int16_t FrView;
+} UDFMACFDINFO;
+AssertCompileSize(UDFMACFDINFO, 16);
+
+/**
+ * UDF finder directory extended info for Mac EAs (@udf260{3.3.4.5.4.2,86}).
+ */
+typedef struct UDFMACFDXINFO
+{
+ UDFMACPOINT FrScroll;
+ int32_t FrOpenChain;
+ uint8_t FrScript;
+ uint8_t FrXFlags;
+ uint16_t FrComment;
+ uint32_t FrPutAway;
+} UDFMACFDXINFO;
+AssertCompileSize(UDFMACFDXINFO, 16);
+
+/**
+ * UDF Mac finder info implementation use EA payload (@udf260{3.3.4.5.4.1,84}),
+ * directory edition.
+ *
+ * UDFEADATAIMPLUSE::idImplementation is UDF_ENTITY_ID_IUEA_MAC_FINDER_INFO.
+ */
+typedef struct UDFIUEAMACFINDERINFODIR
+{
+ /** 0x00/0x30: Header checksum.
+ * @note 16-bit checksum of UDFGEA up thru u.ImplUse.idImplementation. */
+ uint16_t uChecksum;
+ /** 0x02/0x32: Explicit alignment padding, MBZ. */
+ uint16_t uPadding;
+ /** 0x04/0x34: Parent directory ID. */
+ uint32_t idParentDir;
+ /** 0x08/0x38: Dir information. */
+ UDFMACFDINFO DirInfo;
+ /** 0x18/0x48: Dir extended information. */
+ UDFMACFDXINFO DirExInfo;
+} UDFIUEAMACFINDERINFODIR;
+AssertCompileMemberOffset(UDFIUEAMACFINDERINFODIR, DirInfo, 0x08);
+AssertCompileMemberOffset(UDFIUEAMACFINDERINFODIR, DirExInfo, 0x18);
+AssertCompileSize(UDFIUEAMACFINDERINFODIR, 0x28);
+/** Pointer to UDF Mac finder info for dir implementation use EA payload. */
+typedef UDFIUEAMACFINDERINFODIR *PUDFIUEAMACFINDERINFODIR;
+/** Pointer to const UDF Mac finder info for dir implementation use EA payload. */
+typedef UDFIUEAMACFINDERINFODIR const *PCUDFIUEAMACFINDERINFODIR;
+
+/**
+ * UDF finder file info for Mac EAs (@udf260{3.3.4.5.4.2,86}).
+ */
+typedef struct UDFMACFFINFO
+{
+ uint32_t FrType;
+ uint32_t FrCreator;
+ uint16_t FrFlags;
+ UDFMACPOINT FrLocation;
+ int16_t FrFldr;
+} UDFMACFFINFO;
+AssertCompileSize(UDFMACFFINFO, 16);
+
+/**
+ * UDF finder file extended info for Mac EAs (@udf260{3.3.4.5.4.2,86}).
+ */
+typedef struct UDFMACFFXINFO
+{
+ int16_t FrIconID;
+ uint8_t FdUnused[6];
+ uint8_t FrScript;
+ uint8_t FrXFlags;
+ uint16_t FrComment;
+ uint32_t FrPutAway;
+} UDFMACFFXINFO;
+AssertCompileSize(UDFMACFFXINFO, 16);
+
+/**
+ * UDF Mac finder info implementation use EA payload (@udf260{3.3.4.5.4.1,84}),
+ * file edition.
+ *
+ * UDFEADATAIMPLUSE::idImplementation is UDF_ENTITY_ID_IUEA_MAC_FINDER_INFO.
+ */
+typedef struct UDFIUEAMACFINDERINFOFILE
+{
+ /** 0x00/0x30: Header checksum.
+ * @note 16-bit checksum of UDFGEA up thru u.ImplUse.idImplementation. */
+ uint16_t uChecksum;
+ /** 0x02/0x32: Explicit alignment padding, MBZ. */
+ uint16_t uPadding;
+ /** 0x04/0x34: Parent directory ID. */
+ uint32_t idParentDir;
+ /** 0x08/0x38: File information. */
+ UDFMACFFINFO FileInfo;
+ /** 0x18/0x48: File extended information. */
+ UDFMACFFXINFO FileExInfo;
+ /** 0x28/0x58: The size of the fork data (in bytes). */
+ uint32_t cbForkData;
+ /** 0x2c/0x5c: The size of the fork allocation (in bytes). */
+ uint32_t cbForkAlloc;
+} UDFIUEAMACFINDERINFOFILE;
+AssertCompileMemberOffset(UDFIUEAMACFINDERINFOFILE, FileInfo, 0x08);
+AssertCompileMemberOffset(UDFIUEAMACFINDERINFOFILE, FileExInfo, 0x18);
+AssertCompileMemberOffset(UDFIUEAMACFINDERINFOFILE, cbForkData, 0x28);
+AssertCompileSize(UDFIUEAMACFINDERINFOFILE, 0x30);
+/** Pointer to UDF Mac finder info for file implementation use EA payload. */
+typedef UDFIUEAMACFINDERINFOFILE *PUDFIUEAMACFINDERINFOFILE;
+/** Pointer to const UDF Mac finder info for file implementation use EA payload. */
+typedef UDFIUEAMACFINDERINFOFILE const *PCUDFIUEAMACFINDERINFOFILE;
+
+/**
+ * UDF OS/400 directory info implementation use EA payload (@udf260{3.3.4.5.6.1,87})
+ *
+ * UDFEADATAIMPLUSE::idImplementation is UDF_ENTITY_ID_IUEA_OS400_DIR_INFO.
+ */
+typedef struct UDFIUEAOS400DIRINFO
+{
+ /** 0x00/0x30: Header checksum.
+ * @note 16-bit checksum of UDFGEA up thru u.ImplUse.idImplementation. */
+ uint16_t uChecksum;
+ /** 0x02/0x32: Explicit alignment padding, MBZ. */
+ uint16_t uPadding;
+ /** 0x04/0x34: The directory info, format documented elsewhere. */
+ uint8_t abDirInfo[44];
+} UDFIUEAOS400DIRINFO;
+AssertCompileSize(UDFIUEAOS400DIRINFO, 0x30);
+/** Pointer to UDF Mac finder info for file implementation use EA payload. */
+typedef UDFIUEAOS400DIRINFO *PUDFIUEAOS400DIRINFO;
+/** Pointer to const UDF Mac finder info for file implementation use EA payload. */
+typedef UDFIUEAOS400DIRINFO const *PCUDFIUEAOS400DIRINFO;
+
+
+/**
+ * UDF implementation use EA data (@ecma167{4,14.10.8,111}, @udf260{3.3.4.5,82}).
+ */
+typedef struct UDFEADATAIMPLUSE
+{
+ /** 0x00/0x0c: Length uData in bytes. */
+ uint32_t cbData;
+ /** 0x04/0x10: Implementation identifier (UDF_ENTITY_ID_IUEA_XXX). */
+ UDFENTITYID idImplementation;
+ /** 0x24/0x30: Implementation use field (variable length). */
+ union
+ {
+ /** Generic byte view. */
+ uint8_t abData[RT_FLEXIBLE_ARRAY_IN_NESTED_UNION];
+ /** Free EA space (UDF_ENTITY_ID_IUEA_FREE_EA_SPACE). */
+ UDFFREEEASPACE FreeEaSpace;
+ /** DVD copyright management information (UDF_ENTITY_ID_IUEA_DVD_CGMS_INFO). */
+ UDFIUEADVDCGMSINFO DvdCgmsInfo;
+ /** OS/2 EA length (UDF_ENTITY_ID_IUEA_OS2_EA_LENGTH). */
+ UDFIUEAOS2EALENGTH Os2EaLength;
+ /** Mac volume info (UDF_ENTITY_ID_IUEA_MAC_VOLUME_INFO). */
+ UDFIUEAMACVOLINFO MacVolInfo;
+ /** Mac finder info, directory edition (UDF_ENTITY_ID_IUEA_MAC_FINDER_INFO). */
+ UDFIUEAMACFINDERINFODIR MacFinderInfoDir;
+ /** Mac finder info, file edition (UDF_ENTITY_ID_IUEA_MAC_FINDER_INFO). */
+ UDFIUEAMACFINDERINFOFILE MacFinderInfoFile;
+ /** OS/400 directory info (UDF_ENTITY_ID_IUEA_OS400_DIR_INFO). */
+ UDFIUEAOS400DIRINFO Os400DirInfo;
+ } u;
+} UDFEADATAIMPLUSE;
+/** Pointer to UDF implementation use EA data. */
+typedef UDFEADATAIMPLUSE *PUDFEADATAIMPLUSE;
+/** Pointer to const UDF implementation use EA data. */
+typedef UDFEADATAIMPLUSE const *PCUDFEADATAIMPLUSE;
+/** UDFGEA::uAttribType value for UDFEADATAIMPLUSE. */
+#define UDFEADATAIMPLUSE_ATTRIB_TYPE UINT32_C(0x00000800)
+/** UDFGEA::uAttribSubtype value for UDFEADATAIMPLUSE. */
+#define UDFEADATAIMPLUSE_ATTRIB_SUBTYPE UINT32_C(0x00000001)
+
+/**
+ * UDF application use EA data (@ecma167{4,14.10.9,112}, @udf260{3.3.4.6,88}).
+ */
+typedef struct UDFEADATAAPPUSE
+{
+ /** 0x0c: Length uData in bytes. */
+ uint32_t cbData;
+ /** 0x10: Application identifier (UDF_ENTITY_ID_AUEA_FREE_EA_SPACE). */
+ UDFENTITYID idApplication;
+ /** 0x30: Application use field (variable length). */
+ union
+ {
+ /** Generic byte view. */
+ uint8_t ab[RT_FLEXIBLE_ARRAY_IN_NESTED_UNION];
+ /** Free EA space (UDF_ENTITY_ID_AUEA_FREE_EA_SPACE). */
+ UDFFREEEASPACE FreeEaSpace;
+ } uData;
+} UDFEADATAAPPUSE;
+/** Pointer to UDF application use EA data. */
+typedef UDFEADATAAPPUSE *PUDFEADATAAPPUSE;
+/** Pointer to const UDF application use EA data. */
+typedef UDFEADATAAPPUSE const *PCUDFEADATAAPPUSE;
+/** UDFGEA::uAttribType value for UDFEADATAAPPUSE. */
+#define UDFEADATAAPPUSE_ATTRIB_TYPE UINT32_C(0x00010000)
+/** UDFGEA::uAttribSubtype value for UDFEADATAAPPUSE. */
+#define UDFEADATAAPPUSE_ATTRIB_SUBTYPE UINT32_C(0x00000001)
+
+/**
+ * UDF generic extended attribute (@ecma167{4,14.10.2,103}).
+ */
+typedef struct UDFGEA
+{
+ /** 0x00: Attribute type (UDFXXX_ATTRIB_TYPE). */
+ uint32_t uAttribType;
+ /** 0x04: Attribute subtype (UDFXXX_ATTRIB_SUBTYPE). */
+ uint8_t uAttribSubtype;
+ /** 0x05: Reserved padding bytes, MBZ. */
+ uint8_t abReserved[3];
+ /** 0x08: Size of the whole extended attribute.
+ * Multiple of four is recommended. */
+ uint32_t cbAttrib;
+ /** 0x0c: Attribute data union. */
+ union
+ {
+ /** Generic byte view (variable size). */
+ uint8_t abData[RT_FLEXIBLE_ARRAY_IN_NESTED_UNION];
+ /** Character set information (@ecma167{4,14.10.3,104}). */
+ UDFEADATACHARSETINFO CharSetInfo;
+ /** Alternate permissions (@ecma167{4,14.10.4,105}, @udf260{3.3.4.2,80}).
+ * @note Not recorded according to the UDF specification. */
+ UDFEADATAALTPERM AltPerm;
+ /** File times (@ecma167{4,14.10.5,108}, @udf260{3.3.4.3,80}).
+ * (This is a bit reminiscent of ISO9660RRIPTF.) */
+ UDFEADATAFILETIMES FileTimes;
+ /** Information times (@ecma167{4,14.10.6,109}). */
+ UDFEADATAINFOTIMES InfoTimes;
+ /** Device specification (@ecma167{4,14.10.7,110}, @udf260{3.3.4.4,81}). */
+ UDFEADATADEVICESPEC DeviceSpec;
+ /** Implementation use (@ecma167{4,14.10.8,111}, @udf260{3.3.4.5,82}). */
+ UDFEADATAIMPLUSE ImplUse;
+ /** Application use (@ecma167{4,14.10.9,112}, @udf260{3.3.4.6,88}). */
+ UDFEADATAAPPUSE AppUse;
+ } u;
+} UDFGEA;
+AssertCompileMemberOffset(UDFGEA, u, 0x0c);
+/** Pointer to a UDF extended attribute. */
+typedef UDFGEA *PUDFGEA;
+/** Pointer to a const UDF extended attribute. */
+typedef UDFGEA const *PCUDFGEA;
+
+
+/**
+ * UDF unallocated space entry (@ecma167{4,14.11,113}, @udf260{2.3.7,64}).
+ *
+ * @note Total length shall not exceed one logical block.
+ */
+typedef struct UDFUNALLOCATEDSPACEENTRY
+{
+ /** 0x00: The descriptor tag (UDF_TAG_ID_UNALLOCATED_SPACE_ENTRY). */
+ UDFTAG Tag;
+ /** 0x10: ICB Tag. */
+ UDFICBTAG IcbTag;
+ /** 0x24: Size of the allocation desciptors in bytes. */
+ uint32_t cbAllocDescs;
+ /** 0x28: Allocation desciptors, type given by IcbTag::fFlags. */
+ union
+ {
+ UDFSHORTAD aShortADs[RT_FLEXIBLE_ARRAY_IN_NESTED_UNION];
+ UDFLONGAD aLongADs[RT_FLEXIBLE_ARRAY_IN_NESTED_UNION];
+ UDFEXTAD aExtADs[RT_FLEXIBLE_ARRAY_IN_NESTED_UNION];
+ UDFEXTENTAD SingleAD;
+ } u;
+} UDFUNALLOCATEDSPACEENTRY;
+AssertCompileMemberOffset(UDFUNALLOCATEDSPACEENTRY, u, 0x28);
+/** Pointer to an UDF unallocated space entry. */
+typedef UDFUNALLOCATEDSPACEENTRY *PUDFUNALLOCATEDSPACEENTRY;
+/** Pointer to a const UDF unallocated space entry. */
+typedef UDFUNALLOCATEDSPACEENTRY const *PCUDFUNALLOCATEDSPACEENTRY;
+
+
+/**
+ * UDF space bitmap descriptor (SBD) (@ecma167{4,14.12,114}, @udf260{2.3.8,65}).
+ */
+typedef struct UDFSPACEBITMAPDESC
+{
+ /** 0x00: The descriptor tag (UDF_TAG_ID_SPACE_BITMAP_DESC). */
+ UDFTAG Tag;
+ /** 0x10: Number of bits in the bitmap. */
+ uint32_t cBits;
+ /** 0x14: The bitmap size in bytes. */
+ uint32_t cbBitmap;
+ /** 0x18: The bitmap. */
+ RT_FLEXIBLE_ARRAY_EXTENSION
+ uint8_t abBitmap[RT_FLEXIBLE_ARRAY];
+} UDFSPACEBITMAPDESC;
+AssertCompileMemberOffset(UDFSPACEBITMAPDESC, abBitmap, 0x18);
+/** Pointer to an UDF space bitmap descriptor. */
+typedef UDFSPACEBITMAPDESC *PUDFSPACEBITMAPDESC;
+/** Pointer to a const UDF space bitmap descriptor. */
+typedef UDFSPACEBITMAPDESC const *PCUDFSPACEBITMAPDESC;
+
+
+/**
+ * UDF partition integrity descriptor (@ecma167{4,14.3,115}, @udf260{2.3.9,65}).
+ *
+ * @note Not needed by UDF.
+ */
+typedef struct UDFPARTITIONINTEGRITYDESC
+{
+ /** 0x000: The descriptor tag (UDF_TAG_ID_PARTITION_INTEGERITY_DESC). */
+ UDFTAG Tag;
+ /** 0x010: ICB Tag. */
+ UDFICBTAG IcbTag;
+ /** 0x024: Recording timestamp. */
+ UDFTIMESTAMP RecordingTimestamp;
+ /** 0x030: Interity type (UDF_PARTITION_INTEGRITY_TYPE_XXX). */
+ uint8_t bType;
+ /** 0x031: Reserved. */
+ uint8_t abReserved[175];
+ /** 0x0e0: Implementation identifier. */
+ UDFENTITYID idImplementation;
+ /** 0x100: Implementation use data. */
+ RT_FLEXIBLE_ARRAY_EXTENSION
+ uint8_t abImplementationUse[RT_FLEXIBLE_ARRAY];
+} UDFPARTITIONINTEGRITYDESC;
+AssertCompileMemberOffset(UDFPARTITIONINTEGRITYDESC, abImplementationUse, 0x100);
+/** Pointer to an UDF partition integrity descriptor. */
+typedef UDFPARTITIONINTEGRITYDESC *PUDFPARTITIONINTEGRITYDESC;
+/** Pointer to a const UDF partition integrity descriptor. */
+typedef UDFPARTITIONINTEGRITYDESC const *PCUDFPARTITIONINTEGRITYDESC;
+
+
+/**
+ * UDF extended file entry (EFE) (@ecma167{4,14.17,120}, @udf260{3.3.5,83}).
+ *
+ * @note Total length shall not exceed one logical block.
+ */
+typedef struct UDFEXFILEENTRY
+{
+ /** 0x00: The descriptor tag (UDF_TAG_ID_EXTENDED_FILE_ENTRY). */
+ UDFTAG Tag;
+ /** 0x10: ICB Tag. */
+ UDFICBTAG IcbTag;
+ /** 0x24: User ID (UNIX). */
+ uint32_t uid;
+ /** 0x28: Group ID (UNIX). */
+ uint32_t gid;
+ /** 0x2c: Permission (UDF_PERM_XXX). */
+ uint32_t fPermissions;
+ /** 0x30: Number hard links. */
+ uint16_t cHardlinks;
+ /** 0x32: Record format (UDF_REC_FMT_XXX). */
+ uint8_t uRecordFormat;
+ /** 0x33: Record format (UDF_REC_FMT_XXX). */
+ uint8_t fRecordDisplayAttribs;
+ /** 0x34: Record length (in bytes).
+ * @note Must be zero according to the UDF specification. */
+ uint32_t cbRecord;
+ /** 0x38: Information length in bytes (file size). */
+ uint64_t cbData;
+ /** 0x40: The size of all streams. Same as cbData if no additional streams. */
+ uint64_t cbObject;
+ /** 0x48: Number of logical blocks allocated (for file data). */
+ uint64_t cLogicalBlocks;
+ /** 0x50: Time of last access (prior to recording the file entry). */
+ UDFTIMESTAMP AccessTime;
+ /** 0x5c: Time of last data modification. */
+ UDFTIMESTAMP ModificationTime;
+ /** 0x68: Birth (creation) time. */
+ UDFTIMESTAMP BirthTime;
+ /** 0x74: Time of last attribute/status modification. */
+ UDFTIMESTAMP ChangeTime;
+ /** 0x80: Checkpoint number (defaults to 1). */
+ uint32_t uCheckpoint;
+ /** 0x84: Reserved, MBZ. */
+ uint32_t uReserved;
+ /** 0x88: Extended attribute information control block location. */
+ UDFLONGAD ExtAttribIcb;
+ /** 0x98: Stream directory information control block location. */
+ UDFLONGAD StreamDirIcb;
+ /** 0xa8: Implementation identifier (UDF_ENTITY_ID_FE_IMPLEMENTATION). */
+ UDFENTITYID idImplementation;
+ /** 0xc8: Unique ID. */
+ uint64_t INodeId;
+ /** 0xd0: Length of extended attributes in bytes, multiple of four. */
+ uint32_t cbExtAttribs;
+ /** 0xd4: Length of allocation descriptors in bytes, multiple of four. */
+ uint32_t cbAllocDescs;
+ /** 0xd8: Two variable sized fields. First @a cbExtAttribs bytes of extended
+ * attributes, then @a cbAllocDescs bytes of allocation descriptors. */
+ RT_FLEXIBLE_ARRAY_EXTENSION
+ uint8_t abExtAttribs[RT_FLEXIBLE_ARRAY];
+} UDFEXFILEENTRY;
+AssertCompileMemberOffset(UDFEXFILEENTRY, abExtAttribs, 0xd8);
+/** Pointer to an UDF extended file entry. */
+typedef UDFEXFILEENTRY *PUDFEXFILEENTRY;
+/** Pointer to a const UDF extended file entry. */
+typedef UDFEXFILEENTRY const *PCUDFEXFILEENTRY;
+
+
+
+/** @name UDF Volume Recognition Sequence (VRS)
+ *
+ * The recognition sequence usually follows the CD001 descriptor sequence at
+ * sector 16 and is there to indicate that the medium (also) contains a UDF file
+ * system and which standards are involved.
+ *
+ * See @ecma167{2,8,31}, @ecma167{2,9,32}, @udf260{2.1.7,25}.
+ *
+ * @{ */
+
+/** The type value used for all the extended UDF volume descriptors
+ * (ISO9660VOLDESCHDR::bDescType). */
+#define UDF_EXT_VOL_DESC_TYPE 0
+/** The version value used for all the extended UDF volume descriptors
+ * (ISO9660VOLDESCHDR::bDescVersion). */
+#define UDF_EXT_VOL_DESC_VERSION 1
+
+/** Standard ID for UDFEXTVOLDESCBEGIN. */
+#define UDF_EXT_VOL_DESC_STD_ID_BEGIN "BEA01"
+/** Standard ID for UDFEXTVOLDESCTERM. */
+#define UDF_EXT_VOL_DESC_STD_ID_TERM "TEA01"
+/** Standard ID for UDFEXTVOLDESCNSR following ECMA-167 2nd edition. */
+#define UDF_EXT_VOL_DESC_STD_ID_NSR_02 "NSR02"
+/** Standard ID for UDFEXTVOLDESCNSR following ECMA-167 3rd edition. */
+#define UDF_EXT_VOL_DESC_STD_ID_NSR_03 "NSR03"
+/** Standard ID for UDFEXTVOLDESCBOOT. */
+#define UDF_EXT_VOL_DESC_STD_ID_BOOT "BOOT2"
+
+
+/**
+ * Begin UDF extended volume descriptor area (@ecma167{2,9.2,33}).
+ */
+typedef struct UDFEXTVOLDESCBEGIN
+{
+ /** The volume descriptor header.
+ * The standard identifier is UDF_EXT_VOL_DESC_STD_ID_BEGIN. */
+ ISO9660VOLDESCHDR Hdr;
+ /** Zero payload. */
+ uint8_t abZero[2041];
+} UDFEXTVOLDESCBEGIN;
+AssertCompileSize(UDFEXTVOLDESCBEGIN, 2048);
+/** Pointer to an UDF extended volume descriptor indicating the start of the
+ * extended descriptor area. */
+typedef UDFEXTVOLDESCBEGIN *PUDFEXTVOLDESCBEGIN;
+/** Pointer to a const UDF extended volume descriptor indicating the start of
+ * the extended descriptor area. */
+typedef UDFEXTVOLDESCBEGIN const *PCUDFEXTVOLDESCBEGIN;
+
+
+/**
+ * Terminate UDF extended volume descriptor area (@ecma167{2,9.3,33}).
+ */
+typedef struct UDFEXTVOLDESCTERM
+{
+ /** The volume descriptor header.
+ * The standard identifier is UDF_EXT_VOL_DESC_STD_ID_TERM. */
+ ISO9660VOLDESCHDR Hdr;
+ /** Zero payload. */
+ uint8_t abZero[2041];
+} UDFEXTVOLDESCTERM;
+AssertCompileSize(UDFEXTVOLDESCTERM, 2048);
+/** Pointer to an UDF extended volume descriptor indicating the end of the
+ * extended descriptor area. */
+typedef UDFEXTVOLDESCTERM *PUDFEXTVOLDESCTERM;
+/** Pointer to a const UDF extended volume descriptor indicating the end of
+ * the extended descriptor area. */
+typedef UDFEXTVOLDESCTERM const *PCUDFEXTVOLDESCTERM;
+
+
+/**
+ * UDF NSR extended volume descriptor (@ecma167{3,9.1,50}).
+ *
+ * This gives the ECMA standard version.
+ */
+typedef struct UDFEXTVOLDESCNSR
+{
+ /** The volume descriptor header.
+ * The standard identifier is UDF_EXT_VOL_DESC_STD_ID_NSR_02, or
+ * UDF_EXT_VOL_DESC_STD_ID_NSR_03. */
+ ISO9660VOLDESCHDR Hdr;
+ /** Zero payload. */
+ uint8_t abZero[2041];
+} UDFEXTVOLDESCNSR;
+AssertCompileSize(UDFEXTVOLDESCNSR, 2048);
+/** Pointer to an extended volume descriptor giving the UDF standard version. */
+typedef UDFEXTVOLDESCNSR *PUDFEXTVOLDESCNSR;
+/** Pointer to a const extended volume descriptor giving the UDF standard version. */
+typedef UDFEXTVOLDESCNSR const *PCUDFEXTVOLDESCNSR;
+
+
+/**
+ * UDF boot extended volume descriptor (@ecma167{2,9.4,34}).
+ *
+ * @note Probably entirely unused.
+ */
+typedef struct UDFEXTVOLDESCBOOT
+{
+ /** 0x00: The volume descriptor header.
+ * The standard identifier is UDF_EXT_VOL_DESC_STD_ID_BOOT. */
+ ISO9660VOLDESCHDR Hdr;
+ /** 0x07: Reserved/alignment, MBZ. */
+ uint8_t bReserved1;
+ /** 0x08: The architecture type. */
+ UDFENTITYID ArchType;
+ /** 0x28: The boot identifier. */
+ UDFENTITYID idBoot;
+ /** 0x48: Logical sector number of load the boot loader from. */
+ uint32_t offBootExtent;
+ /** 0x4c: Number of bytes to load. */
+ uint32_t cbBootExtent;
+ /** 0x50: The load address (in memory). */
+ uint64_t uLoadAddress;
+ /** 0x58: The start address (in memory). */
+ uint64_t uStartAddress;
+ /** 0x60: The descriptor creation timestamp. */
+ UDFTIMESTAMP CreationTimestamp;
+ /** 0x6c: Flags. */
+ uint16_t fFlags;
+ /** 0x6e: Reserved, MBZ. */
+ uint8_t abReserved2[32];
+ /** 0x8e: Implementation use. */
+ uint8_t abBootUse[1906];
+} UDFEXTVOLDESCBOOT;
+AssertCompileSize(UDFEXTVOLDESCBOOT, 2048);
+/** Pointer to a boot extended volume descriptor. */
+typedef UDFEXTVOLDESCBOOT *PUDFEXTVOLDESCBOOT;
+/** Pointer to a const boot extended volume descriptor. */
+typedef UDFEXTVOLDESCBOOT const *PCUDFEXTVOLDESCBOOT;
+
+/** @} */
+
+
+/** @} */
+
+#endif /* !IPRT_INCLUDED_formats_udf_h */
+
diff --git a/include/iprt/formats/wim.h b/include/iprt/formats/wim.h
new file mode 100644
index 00000000..b0fb7036
--- /dev/null
+++ b/include/iprt/formats/wim.h
@@ -0,0 +1,160 @@
+/** @file
+ * IPRT - Windows Imaging (WIM) format.
+ */
+
+/*
+ * Copyright (C) 2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_formats_wim_h
+#define IPRT_INCLUDED_formats_wim_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+#include <iprt/assertcompile.h>
+#include <iprt/uuid.h>
+
+
+/** @defgroup grp_rt_formats_win Windows Imaging (WIM) format
+ * @ingroup grp_rt_formats
+ *
+ * Specification:
+ * http://download.microsoft.com/download/f/e/f/fefdc36e-392d-4678-9e4e-771ffa2692ab/Windows%20Imaging%20File%20Format.rtf
+ *
+ * @{ */
+
+
+/**
+ * A short WIM resource entry.
+ *
+ * This is a simplified version of the specs.
+ */
+typedef struct RESHDRDISKSHORT
+{
+ /** 0x00 - The compressed size. */
+ RT_GCC_EXTENSION
+ uint64_t cb : 56;
+ /** 0x07 - Flags, RESHDR_FLAGS_XXX. */
+ RT_GCC_EXTENSION
+ uint64_t bFlags : 8;
+ /** 0x08 - Offset.
+ * @note This is signed in the specficiation... */
+ uint64_t off;
+ /** 0x10 - The uncompressed original size.
+ * @note This is signed in the specficiation... */
+ uint64_t cbOriginal;
+} RESHDRDISKSHORT;
+AssertCompileSize(RESHDRDISKSHORT, 0x18);
+/** Pointer to a short WIM resource entry. */
+typedef RESHDRDISKSHORT *PRESHDRDISKSHORT;
+/** Pointer to a const short WIM resource entry. */
+typedef RESHDRDISKSHORT *PCRESHDRDISKSHORT;
+
+/** @name RESHDR_FLAGS_XXX
+ * @{ */
+#define RESHDR_FLAGS_FREE UINT8_C(0x01)
+#define RESHDR_FLAGS_METADATA UINT8_C(0x02)
+#define RESHDR_FLAGS_COMPRESSED UINT8_C(0x04)
+#define RESHDR_FLAGS_SPANNED UINT8_C(0x08)
+/** @} */
+
+/**
+ * WIM file header, version 1.
+ *
+ * The field names have been normalized to our coding style.
+ */
+#pragma pack(4)
+typedef struct WIMHEADERV1
+{
+ /** 0x00 - Magic value WIMHEADER_MAGIC. */
+ char szMagic[8];
+ /** 0x08 - The size of this header structure. */
+ uint32_t cbHeader;
+ /** 0x0c - The header version structure. */
+ uint32_t uVersion;
+ /** 0x10 - Flags. */
+ uint32_t fFlags;
+ /** 0x14 - ??. */
+ uint32_t cbCompression;
+ /** 0x18 - Unique identifier. */
+ RTUUID WIMGuid;
+ /** 0x28 - Part number in spanned (split) wim set. Unsplit use part number 1. */
+ uint16_t idxPartNumber;
+ /** 0x2a - Total number of parts in spanned set. */
+ uint16_t cTotalParts;
+ /** 0x2c - Number of images in the archive. */
+ uint32_t cImages;
+ /** 0x30 - Resource lookup table offset & size. */
+ RESHDRDISKSHORT OffsetTable;
+ /** 0x48 - XML data offset & size. */
+ RESHDRDISKSHORT XmlData;
+ /** 0x60 - Boot metadata offset & size. */
+ RESHDRDISKSHORT BootMetadata;
+ /** 0x78 - Bootable image index, zero if no bootable image. */
+ uint32_t idxBoot;
+ /** 0x7c - Integrity data offset & size.
+ * @note Misaligned! */
+ RESHDRDISKSHORT Integrity;
+ /** 0x94 - Reserved */
+ uint8_t abUnused[60];
+} WIMHEADERV1;
+#pragma pack()
+AssertCompileSize(WIMHEADERV1, 0xd0);
+/** Pointer to a XAR header. */
+typedef WIMHEADERV1 *PWIMHEADERV1;
+/** Pointer to a const XAR header. */
+typedef WIMHEADERV1 const *PCWIMHEADERV1;
+
+/** The WIMHEADERV1::szMagic value. */
+#define WIMHEADER_MAGIC "MSWIM\0\0"
+AssertCompile(sizeof(WIMHEADER_MAGIC) == 8);
+
+/** @name WIMHEADER_FLAGS_XXX - WINHEADERV1::fFlags.
+ * @note Specfication names these FLAG_HEADER_XXX.
+ * @{ */
+#define WIMHEADER_FLAGS_RESERVED RT_BIT_32(0)
+#define WIMHEADER_FLAGS_COMPRESSION RT_BIT_32(1)
+#define WIMHEADER_FLAGS_READONLY RT_BIT_32(2)
+#define WIMHEADER_FLAGS_SPANNED RT_BIT_32(3)
+#define WIMHEADER_FLAGS_RESOURCE_ONLY RT_BIT_32(4)
+#define WIMHEADER_FLAGS_METADATA_ONLY RT_BIT_32(5)
+#define WIMHEADER_FLAGS_WRITE_IN_PROGRESS RT_BIT_32(5)
+#define WIMHEADER_FLAGS_RP_FIX RT_BIT_32(6)
+#define WIMHEADER_FLAGS_COMPRESS_RESERVED RT_BIT_32(16)
+#define WIMHEADER_FLAGS_COMPRESS_XPRESS RT_BIT_32(17)
+#define WIMHEADER_FLAGS_COMPRESS_LZX RT_BIT_32(18)
+/** @} */
+
+/** @} */
+
+#endif /* !IPRT_INCLUDED_formats_wim_h */
+
diff --git a/include/iprt/formats/xar.h b/include/iprt/formats/xar.h
new file mode 100644
index 00000000..9b3b85c4
--- /dev/null
+++ b/include/iprt/formats/xar.h
@@ -0,0 +1,90 @@
+/** @file
+ * IPRT - Extensible Archiver (XAR) format.
+ */
+
+/*
+ * Copyright (C) 2013-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_formats_xar_h
+#define IPRT_INCLUDED_formats_xar_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+#include <iprt/assertcompile.h>
+
+
+/** @defgroup grp_rt_formats_xar Extensible Archive (XAR) format
+ * @ingroup grp_rt_formats
+ *
+ * @{ */
+
+#pragma pack(4) /* Misdesigned header, not 8-byte aligned size. */
+typedef struct XARHEADER
+{
+ /** The magic number 'xar!' (XAR_HEADER_MAGIC). */
+ uint32_t u32Magic;
+ /** The size of this header structure. */
+ uint16_t cbHeader;
+ /** The header version structure. */
+ uint16_t uVersion;
+ /** The size of the compressed table of content (TOC). */
+ uint64_t cbTocCompressed;
+ /** The size of the table of context (TOC) when not compressed. */
+ uint64_t cbTocUncompressed;
+ /** Which cryptographic hash function is used (XAR_HASH_XXX). */
+ uint32_t uHashFunction;
+} XARHEADER;
+#pragma pack()
+AssertCompileSize(XARHEADER, 28);
+/** Pointer to a XAR header. */
+typedef XARHEADER *PXARHEADER;
+/** Pointer to a const XAR header. */
+typedef XARHEADER const *PCXARHEADER;
+
+/** XAR magic value (on disk endian). */
+#define XAR_HEADER_MAGIC RT_H2LE_U32(RT_MAKE_U32_FROM_U8('x', 'a', 'r', '!'))
+/** The current header version value (host endian). */
+#define XAR_HEADER_VERSION 1
+
+/** @name XAR hashing functions.
+ * @{ */
+#define XAR_HASH_NONE 0
+#define XAR_HASH_SHA1 1
+#define XAR_HASH_MD5 2
+#define XAR_HASH_MAX 2
+/** @} */
+
+/** @} */
+
+#endif /* !IPRT_INCLUDED_formats_xar_h */
+
diff --git a/include/iprt/formats/xfs.h b/include/iprt/formats/xfs.h
new file mode 100644
index 00000000..a50d6b9f
--- /dev/null
+++ b/include/iprt/formats/xfs.h
@@ -0,0 +1,721 @@
+/* $Id: xfs.h $ */
+/** @file
+ * IPRT, XFS format.
+ */
+
+/*
+ * Copyright (C) 2018-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_formats_xfs_h
+#define IPRT_INCLUDED_formats_xfs_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+#include <iprt/assertcompile.h>
+
+
+/** @defgroup grp_rt_formats_xfs XFS filesystem structures and definitions
+ * @ingroup grp_rt_formats
+ * @{
+ */
+
+/*
+ * The filesystem structures were retrieved from:
+ * http://xfs.org/docs/xfsdocs-xml-dev/XFS_Filesystem_Structure//tmp/en-US/html/index.html and
+ * https://elixir.bootlin.com/linux/v4.9/source/fs/xfs/libxfs/xfs_format.h and
+ * https://righteousit.wordpress.com/
+ */
+
+/** XFS superblock offset from the beginning of the volume, this is constant. */
+#define XFS_SB_OFFSET UINT64_C(0)
+
+/** @name Common XFS types as defined in the spec.
+ * @{ */
+/** Unsigned 64 bit absolute inode number. */
+typedef uint64_t XFSINO;
+/** Signed 64 bit file offset. */
+typedef int64_t XFSFOFF;
+/** Signed 64 bit disk address. */
+typedef int64_t XFSDADDR;
+/** Unsinged 32 bit allocation group (AG) number. */
+typedef uint32_t XFSAGNUMBER;
+/** Unsigned 32 bit AG relative block number. */
+typedef uint32_t XFSAGBLOCK;
+/** Unsigned 32 bit extent length in blocks. */
+typedef uint32_t XFSEXTLEN;
+/** Signed 32 bit number of extents in a file. */
+typedef int32_t XFSEXTNUM;
+/** Unsigned 32 bit block number for directories and extended attributes. */
+typedef uint32_t XFSDABLK;
+/** Unsigned 32 bit hash of a directory file name or extended attribute name. */
+typedef uint32_t XFSDAHASH;
+/** Unsigned 64 bit filesystem block number combining AG number and block offset into the AG. */
+typedef uint64_t XFSDFSBNO;
+/** Unsigned 64 bit raw filesystem block number. */
+typedef uint64_t XFSDRFSBNO;
+/** Unsigned 64 bit extent number in the real-time device. */
+typedef uint64_t XFSDRTBNO;
+/** Unsigned 64 bit block offset int oa file. */
+typedef uint64_t XFSDFILOFF;
+/** Unsigned 64 bit block count for a file. */
+typedef uint64_t XFSDFILBLKS;
+/** @} */
+
+/**
+ * XFS superblock.
+ */
+#pragma pack(1)
+typedef struct XFSSUPERBLOCK
+{
+ /** 0x00: Magic number to identify the superblock. */
+ uint32_t u32Magic;
+ /** 0x04: Size of smallest allocation unit in bytes. */
+ uint32_t cbBlock;
+ /** 0x04: Number of blocks available for data and metadata. */
+ XFSDRFSBNO cBlocks;
+ /** 0x0c: Number of block in the real-time device. */
+ XFSDRFSBNO cBlocksRtDev;
+ /** 0x14: Number of extents on real-time device. */
+ XFSDRTBNO cExtentsRtDev;
+ /** 0x1c: UUID of the filesystem. */
+ uint8_t abUuid[16];
+ /** 0x2c: First block of the filesystem journal. */
+ XFSDFSBNO uBlockJournal;
+ /** 0x34: Inode number of the root directory. */
+ XFSINO uInodeRoot;
+ /** Inode for the real-time extent bitmap. */
+ XFSINO uInodeBitmapRtExt;
+ /** Inode for the real-time bitmap summary. */
+ XFSINO uInodeBitmapSummary;
+ /** Extent size on the real-time device in blocks. */
+ XFSAGBLOCK cRtExtent;
+ /** Size of an AG in blocks. */
+ XFSAGBLOCK cAgBlocks;
+ /** Number of AGs in hte filesystem. */
+ XFSAGNUMBER cAg;
+ /** Number of real-time bitmap blocks. */
+ XFSEXTLEN cRtBitmapBlocks;
+ /** Number of blocks for the journal. */
+ XFSEXTLEN cJournalBlocks;
+ /** Version number (actually flag bitmaps of features). */
+ uint16_t fVersion;
+ /** Sector size of the underlying medium. */
+ uint16_t cbSector;
+ /** Size of an inode in bytes. */
+ uint16_t cbInode;
+ /** Number of inodes stored in one block. */
+ uint16_t cInodesPerBlock;
+ /** Name of the filesystem. */
+ char achFsName[12];
+ /** Block size as log2 (number of bits to shift left). */
+ uint8_t cBlockSzLog;
+ /** Sector size as log2 (number of bits to shift left). */
+ uint8_t cSectorSzLog;
+ /** Inode size as log2 (number of bits to shift left). */
+ uint8_t cInodeSzLog;
+ /** Number of inodes per block as log2. */
+ uint8_t cInodesPerBlockLog;
+ /** Number of AG blocks as log2 (number of bits to shift left). */
+ uint8_t cAgBlocksLog;
+ /** Number of extent blocks as log2. */
+ uint8_t cExtentsRtDevLog;
+ /** Flag when the filesystem is in the process of being created. */
+ uint8_t fInProgress;
+ /** Maximum percentage of the filesystem usable for inodes. */
+ uint8_t cInodeMaxPct;
+ /** Global number of inodes allocated (only mainted on the first superblock). */
+ uint64_t cInodesGlobal;
+ /** Global number of free inodes (only mainted on the first superblock). */
+ uint64_t cInodesGlobalFree;
+ /** Global count of free data blocks on the filesystem (only mainted on the first superblock). */
+ uint64_t cBlocksFree;
+ /** Global count of free extents on the real-time device (only mainted on the first superblock). */
+ uint64_t cExtentsRtFree;
+ /** Inode containing the user quotas. */
+ XFSINO uInodeQuotaUsr;
+ /** Inode containing the group/project quotas. */
+ XFSINO uInodeQuotaGrp;
+ /** Quota flags. */
+ uint16_t fQuotaFlags;
+ /** Misc flags. */
+ uint8_t fFlagsMisc;
+ /** Reserved MBZ. */
+ uint8_t uSharedVn;
+ /** Number of filesystem blocks for the inode chunk alignment. */
+ XFSEXTLEN cBlocksInodeAlignment;
+ /** Raid stripe size in blocks. */
+ uint32_t cBlocksRaidStripe;
+ /** Raid width in number of blocks. */
+ uint32_t cBlocksRaidWidth;
+ /** Multiplier for determining the allocation size for directory blocks as log2. */
+ uint8_t cDirBlockAllocLog;
+ /** Sub volume sector size as log2 if an external journal device is used. */
+ uint8_t cLogDevSubVolSectorSzLog;
+ /** Sector size of the device an external journal is stored as log2. */
+ uint16_t cLogDevSectorSzLog;
+ /** Log devices stripe size. */
+ uint32_t cLogDevRaidStripe;
+ /** Additional features which may be active. */
+ uint32_t fFeatures2;
+ /** Padding. */
+ uint32_t u32Padding0;
+ /** From here follow data only available from version 5 and later. */
+ /** Read/Write feature flags. */
+ uint32_t fFeaturesRw;
+ /** Read-only feature flags. */
+ uint32_t fFeaturesRo;
+ /** Read/Write incompatible feature flags. */
+ uint32_t fFeaturesIncompatRw;
+ /** Read/Write incompatible feature flags for the journal. */
+ uint32_t fFeaturesJrnlIncompatRw;
+ /** CRC32 checksum for the superblock. */
+ uint32_t u32Chksum;
+ /** Sparse inode alignment. */
+ uint32_t u32SparseInodeAlignment;
+ /** Project quota inode. */
+ XFSINO uInodeProjectQuota;
+ /** Log sequence number of last superblock update. */
+ uint64_t uJrnlSeqSbUpdate;
+ /** UUID used when INCOMPAT_META_UUID is used. */
+ uint8_t abUuidMeta[16];
+ /** Inode if INCOMPATMETA_RMAPBT is used. */
+ XFSINO uInodeRm;
+} XFSSUPERBLOCK;
+#pragma pack()
+AssertCompileSize(XFSSUPERBLOCK, 272);
+/** Pointer to an XFS superblock. */
+typedef XFSSUPERBLOCK *PXFSSUPERBLOCK;
+/** Pointer to a const XFS superblock. */
+typedef const XFSSUPERBLOCK *PCXFSSUPERBLOCK;
+
+/** XFS superblock magic. */
+#define XFS_SB_MAGIC RT_MAKE_U32_FROM_U8('B', 'S', 'F', 'X')
+
+/** @name XFS_SB_VERSION_F_XXX - Version/Feature flags.
+ * @{ */
+/** Retrieves the version part of the field. */
+#define XFS_SB_VERSION_GET(a_fVersion) ((a_fVersion) & 0xf)
+/** Version number for filesystem 5.3, 6.0.1 and 6.1. */
+#define XFS_SB_VERSION_1 1
+/** Version number for filesystem 6.2 - attributes. */
+#define XFS_SB_VERSION_2 2
+/** Version number for filesystem 6.2 - new inode version. */
+#define XFS_SB_VERSION_3 3
+/** Version number for filesystem 6.2+ - new bitmask version. */
+#define XFS_SB_VERSION_4 4
+/** Introduced checksums in the metadata. */
+#define XFS_SB_VERSION_5 5
+/** Extended attributes are used for at least one inode. */
+#define XFS_SB_VERSION_F_ATTR RT_BIT_32(4)
+/** At least one inode use 32-bit nlink values. */
+#define XFS_SB_VERSION_F_NLINK RT_BIT_32(5)
+/** Quotas are enabled on the filesystem. */
+#define XFS_SB_VERSION_F_QUOTA RT_BIT_32(6)
+/** Set if XFSSUPERBLOCK::cBlocksInodeAlignment is used. */
+#define XFS_SB_VERSION_F_ALIGN RT_BIT_32(7)
+/** Set if XFSSUPERBLOCK::cBlocksRaidStripe and XFSSUPERBLOCK::cBlocksRaidWidth are used. */
+#define XFS_SB_VERSION_F_DALIGN RT_BIT_32(8)
+/** Set if XFSSUPERBLOCK::uSharedVn is used. */
+#define XFS_SB_VERSION_F_SHARED RT_BIT_32(9)
+/** Version 2 journaling is used. */
+#define XFS_SB_VERSION_F_LOGV2 RT_BIT_32(10)
+/** Set if sector size is not 512 bytes. */
+#define XFS_SB_VERSION_F_SECTOR RT_BIT_32(11)
+/** Set if unwritten extents are used (always set). */
+#define XFS_SB_VERSION_F_EXTFLG RT_BIT_32(12)
+/** Version 2 directories are used (always set). */
+#define XFS_SB_VERSION_F_DIRV2 RT_BIT_32(13)
+/** Set if XFSSUPERBLOCK::fFeatures2 is used. */
+#define XFS_SB_VERSION_F_FEAT2 RT_BIT_32(14)
+/** @} */
+
+/** @name XFS_SB_QUOTA_F_XXX - Quota flags
+ * @{ */
+/** User quota accounting enabled. */
+#define XFS_SB_QUOTA_F_USR_ACCT RT_BIT(0)
+/** User quotas are enforced. */
+#define XFS_SB_QUOTA_F_USR_ENFD RT_BIT(1)
+/** User quotas have been checked and updated on disk. */
+#define XFS_SB_QUOTA_F_USR_CHKD RT_BIT(2)
+/** Project quota accounting is enabled. */
+#define XFS_SB_QUOTA_F_PROJ_ACCT RT_BIT(3)
+/** Other quotas are enforced. */
+#define XFS_SB_QUOTA_F_OTH_ENFD RT_BIT(4)
+/** Other quotas have been checked and updated on disk. */
+#define XFS_SB_QUOTA_F_OTH_CHKD RT_BIT(5)
+/** Group quota accounting enabled. */
+#define XFS_SB_QUOTA_F_GRP_ACCT RT_BIT(6)
+/** @} */
+
+/** @name XFS_SB_FEATURES2_F_XXX - Additional features
+ * @{ */
+/** Global counters are lazy and are only updated when the filesystem is cleanly unmounted. */
+#define XFS_SB_FEATURES2_F_LAZYSBCOUNT RT_BIT_32(1)
+/** Extended attributes version 2. */
+#define XFS_SB_FEATURES2_F_ATTR2 RT_BIT_32(3)
+/** Parent pointers, inodes must have an extended attribute pointing to the parent inode. */
+#define XFS_SB_FEATURES2_F_PARENT RT_BIT_32(4)
+/** @} */
+
+
+/**
+ * XFS AG free space block.
+ */
+typedef struct XFSAGF
+{
+ /** Magic number. */
+ uint32_t u32Magic;
+ /** Header version number. */
+ uint32_t uVersion;
+ /** AG number for the sector. */
+ uint32_t uSeqNo;
+ /** Length of the AG in filesystem blocks. */
+ uint32_t cLengthBlocks;
+ /** Block numbers for the roots of the free space B+trees. */
+ uint32_t auRoots[3];
+ /** Depths of the free space B+trees. */
+ uint32_t acLvls[3];
+ /** Index of the first free list block. */
+ uint32_t idxFreeListFirst;
+ /** Index of the last free list block. */
+ uint32_t idxFreeListLast;
+ /** Number of blocks in the free list. */
+ uint32_t cFreeListBlocks;
+ /** Current number of free blocks in the AG. */
+ uint32_t cFreeBlocks;
+ /** Longest number of contiguous free blocks in the AG. */
+ uint32_t cFreeBlocksLongest;
+ /** Number of blocks used for the free space B+-trees. */
+ uint32_t cBlocksBTrees;
+ /** UUID of filesystem the AG belongs to. */
+ uint8_t abUuid[16];
+ /** Number of blocks used for the reverse map. */
+ uint32_t cBlocksRevMap;
+ /** Number of blocks used for the refcount B+-tree. */
+ uint32_t cBlocksRefcountBTree;
+ /** Block number for the refcount tree root. */
+ uint32_t uRootRefcount;
+ /** Depth of the refcount B+-tree. */
+ uint32_t cLvlRefcount;
+ /** Reserved contiguous space for future extensions. */
+ uint64_t au64Rsvd[14];
+ /** Last write sequence number. */
+ uint64_t uSeqNoLastWrite;
+ /** CRC of the AGF. */
+ uint32_t uChkSum;
+ /** Padding to 64 bit alignment. */
+ uint32_t uAlignment0;
+} XFSAGF;
+/** Pointer to a AG free space block. */
+typedef XFSAGF *PXFSAGF;
+/** Poiner to a const AG free space block. */
+typedef const XFSAGF *PCXFSAGF;
+
+/** AGF magic. */
+#define XFS_AGF_MAGIC RT_MAKE_U32_FROM_U8('F', 'G', 'A', 'X')
+/** The current valid AGF version. */
+#define XFS_AGF_VERSION 1
+
+
+/**
+ * XFS AG inode information.
+ */
+typedef struct XFSAGI
+{
+ /** Magic number. */
+ uint32_t u32Magic;
+ /** Header version number. */
+ uint32_t uVersion;
+ /** AG number for the sector. */
+ uint32_t uSeqNo;
+ /** Length of the AG in filesystem blocks. */
+ uint32_t cLengthBlocks;
+ /** Count of allocated inodes. */
+ uint32_t cInodesAlloc;
+ /** Block number of the inode tree root. */
+ uint32_t uRootInode;
+ /** Depth of the inode B+-tree. */
+ uint32_t cLvlsInode;
+ /** Newest allocated inode. */
+ uint32_t uInodeNew;
+ /** Last directory inode chunk. */
+ uint32_t uInodeDir;
+ /** Hash table of unlinked but still referenced inodes. */
+ uint32_t au32HashUnlinked[64];
+ /** UUID of filesystem. */
+ uint8_t abUuid[16];
+ /** CRC of the AGI. */
+ uint32_t uChkSum;
+ /** Padding. */
+ uint32_t uAlignment0;
+ /** Last write sequence number. */
+ uint64_t uSeqNoLastWrite;
+ /** Block number of the free inode tree. */
+ uint32_t uRootFreeInode;
+ /** Depth of the free inode B+-tree. */
+ uint32_t cLvlsFreeInode;
+} XFSAGI;
+/** Pointer to a AG inode information. */
+typedef XFSAGI *PXFSAGI;
+/** Pointer to a const AG inode information. */
+typedef const XFSAGI *PCXFSAGI;
+
+/** AGI magic. */
+#define XFS_AGI_MAGIC RT_MAKE_U32_FROM_U8('I', 'G', 'A', 'X')
+/** The current valid AGI version. */
+#define XFS_AGI_VERSION 1
+
+
+/**
+ * XFS timestamp structure.
+ */
+typedef struct XFSTIMESTAMP
+{
+ /** 0x00: The second part of the timestamp since the epoch. */
+ int32_t cSecEpoch;
+ /** 0x04: Nanosecond part of the timestamp. */
+ int32_t cNanoSec;
+} XFSTIMESTAMP;
+/** Pointer to a XFS timestamp. */
+typedef XFSTIMESTAMP *PXFSTIMESTAMP;
+/** Poiner to a const CFS timestamp. */
+typedef const XFSTIMESTAMP *PCXFSTIMESTAMP;
+
+
+/**
+ * The inode core structure.
+ */
+typedef struct XFSINODECORE
+{
+ /** 0x00: Magic value. */
+ uint16_t u16Magic;
+ /** 0x02: File mode and access bits (XFS_INODE_MODE_XXX). */
+ uint16_t fMode;
+ /** 0x04: Inode version. */
+ int8_t iVersion;
+ /** 0x05: The format of the data fork. */
+ int8_t enmFormat;
+ /** 0x06: Number of links to this inode from directories for v1 inodes. */
+ uint16_t cOnLinks;
+ /** 0x08: Owners UID. */
+ uint32_t uUid;
+ /** 0x0c: Owners GID. */
+ uint32_t uGid;
+ /** 0x10: The number of links to this inode for v2 inodes. */
+ uint32_t cLinks;
+ /** 0x14: Project ID for v2 inodes (not used for v1, low 16bits). */
+ uint16_t uProjIdLow;
+ /** 0x16: Project ID for v2 inodes (not used for v1, high 16bits). */
+ uint16_t uProjIdHigh;
+ /** 0x18: Padding. */
+ uint8_t abPad0[6];
+ /** 0x1e: Flush counter. */
+ uint16_t cFlush;
+ /** 0x20: Last accessed timestamp. */
+ XFSTIMESTAMP TsLastAccessed;
+ /** 0x28: Last modified timestamp. */
+ XFSTIMESTAMP TsLastModified;
+ /** 0x30: Inode created/modified timestamp. */
+ XFSTIMESTAMP TsCreatedModified;
+ /** 0x38: Number of bytes in the file. */
+ uint64_t cbInode;
+ /** 0x40: Number of direct and B-Tree blocks used for the forks. */
+ uint64_t cBlocks;
+ /** 0x48: Minimum extent size for the inode. */
+ uint32_t cExtentBlocksMin;
+ /** 0x4c: Number of extents in the data fork. */
+ uint32_t cExtentsData;
+ /** 0x50: Number of extents in the attribute fork. */
+ uint16_t cExtentsAttr;
+ /** 0x52: Offset of the attribute fork from the start of the inode. */
+ uint8_t offAttrFork;
+ /** 0x53: Attribute fork format. */
+ int8_t enmFormatAttr;
+ /** 0x54: DMIG event mask. */
+ uint32_t fEvtMaskDmig;
+ /** 0x58: DMIG state info. */
+ uint16_t uStateDmig;
+ /** 0x5a: Inode flags. */
+ uint16_t fFlags;
+ /** 0x5c: Generation number. */
+ uint32_t cGeneration;
+ /** 0x60: AGI unlinked list pointer. */
+ uint32_t offBlockUnlinkedNext;
+ /** The following fields are for v3 inodes only. */
+ /** 0x64: The CRC of the inode. */
+ uint32_t uChkSum;
+ /** 0x68: Number of attribute changes. */
+ uint64_t cAttrChanges;
+ /** 0x70: Last flush sequence number. */
+ uint64_t uFlushSeqNo;
+ /** 0x78: Additional flags. */
+ uint64_t fFlags2;
+ /** 0x80: Basic COW extent size. */
+ uint32_t cExtentCowMin;
+ /** 0x84: Padding for future expansion. */
+ uint8_t abPad1[12];
+ /** 0x90: Inode creation timestamp. */
+ XFSTIMESTAMP TsCreation;
+ /** 0x98: The inode number. */
+ uint64_t uInode;
+ /** 0x100: Filesystem UUID the inode belongs to. */
+ uint8_t abUuid[16];
+} XFSINODECORE;
+AssertCompileSizeAlignment(XFSINODECORE, 8);
+/** Pointer to a inode core. */
+typedef XFSINODECORE *PXFSINODECORE;
+/** Pointer to a const inode core. */
+typedef const XFSINODECORE *PCXFSINODECORE;
+
+/** Inode magic. */
+#define XFS_INODE_MAGIC RT_MAKE_U16_FROM_U8('N', 'I')
+
+/** @name XFS_INODE_MODE_XXX - File mode
+ * @{ */
+/** Others can execute the file. */
+#define XFS_INODE_MODE_EXEC_OTHER RT_BIT(0)
+/** Others can write to the file. */
+#define XFS_INODE_MODE_WRITE_OTHER RT_BIT(1)
+/** Others can read the file. */
+#define XFS_INODE_MODE_READ_OTHER RT_BIT(2)
+/** Members of the same group can execute the file. */
+#define XFS_INODE_MODE_EXEC_GROUP RT_BIT(3)
+/** Members of the same group can write to the file. */
+#define XFS_INODE_MODE_WRITE_GROUP RT_BIT(4)
+/** Members of the same group can read the file. */
+#define XFS_INODE_MODE_READ_GROUP RT_BIT(5)
+/** Owner can execute the file. */
+#define XFS_INODE_MODE_EXEC_OWNER RT_BIT(6)
+/** Owner can write to the file. */
+#define XFS_INODE_MODE_WRITE_OWNER RT_BIT(7)
+/** Owner can read the file. */
+#define XFS_INODE_MODE_READ_OWNER RT_BIT(8)
+/** Sticky file mode. */
+#define XFS_INODE_MODE_STICKY RT_BIT(9)
+/** File is set GID. */
+#define XFS_INODE_MODE_SET_GROUP_ID RT_BIT(10)
+/** File is set UID. */
+#define XFS_INODE_MODE_SET_USER_ID RT_BIT(11)
+/** @} */
+
+/** @name XFS_INODE_MODE_TYPE_XXX - File type
+ * @{ */
+/** Inode represents a FIFO. */
+#define XFS_INODE_MODE_TYPE_FIFO UINT16_C(0x1000)
+/** Inode represents a character device. */
+#define XFS_INODE_MODE_TYPE_CHAR UINT16_C(0x2000)
+/** Inode represents a directory. */
+#define XFS_INODE_MODE_TYPE_DIR UINT16_C(0x4000)
+/** Inode represents a block device. */
+#define XFS_INODE_MODE_TYPE_BLOCK UINT16_C(0x6000)
+/** Inode represents a regular file. */
+#define XFS_INODE_MODE_TYPE_REGULAR UINT16_C(0x8000)
+/** Inode represents a symlink. */
+#define XFS_INODE_MODE_TYPE_SYMLINK UINT16_C(0xa000)
+/** Inode represents a socket. */
+#define XFS_INODE_MODE_TYPE_SOCKET UINT16_C(0xc000)
+/** Returns the inode type from the combined mode field. */
+#define XFS_INODE_MODE_TYPE_GET_TYPE(a_Mode) ((a_Mode) & 0xf000)
+/** @} */
+
+/** @name XFS_INODE_FORMAT_XXX - Inode data fork format.
+ * @{ */
+/** Device node data. */
+#define XFS_INODE_FORMAT_DEV 0
+/** Inline data. */
+#define XFS_INODE_FORMAT_LOCAL 1
+/** Array of extent descriptors. */
+#define XFS_INODE_FORMAT_EXTENTS 2
+/** Data fork contains root of B-Tree. */
+#define XFS_INODE_FORMAT_BTREE 3
+/** Data fork contains UUID. */
+#define XFS_INODE_FORMAT_UUID 4
+/** @} */
+
+/** @name XFS_INODE_F_XXX - Inode flags.
+ * @{ */
+/** File data blocks are stored in the real-time device area. */
+#define XFS_INODE_F_RTDEV RT_BIT(0)
+/** File space has been pre-allocated. */
+#define XFS_INODE_F_PREALLOC RT_BIT(1)
+/** Use new real-time bitmap format. */
+#define XFS_INODE_F_NEWRTBITMAP RT_BIT(2)
+/** Inode is immutable. */
+#define XFS_INODE_F_IMMUTABLE RT_BIT(3)
+/** Inode is append only. */
+#define XFS_INODE_F_APPEND RT_BIT(4)
+/** Inode is written synchronously. */
+#define XFS_INODE_F_SYNC RT_BIT(5)
+/** The last accessed timestamp is not updated. */
+#define XFS_INODE_F_NOATIME RT_BIT(6)
+/** The inode is not dumpable via dump(1). */
+#define XFS_INODE_F_NODUMP RT_BIT(7)
+/** Create with real-time bit set. */
+#define XFS_INODE_F_RTINHERIT RT_BIT(8)
+/** Create with parents project ID. */
+#define XFS_INODE_F_PROJIDINHERIT RT_BIT(9)
+/** Deny symlink creation. */
+#define XFS_INODE_F_NOSYMLINKS RT_BIT(10)
+/** Inode extent size allocator hint. */
+#define XFS_INODE_F_EXTSIZEHINT RT_BIT(11)
+/** Inode extent size is inherited. */
+#define XFS_INODE_F_EXTSIZEINHERIT RT_BIT(12)
+/** Do not defrag/reorganize the inode. */
+#define XFS_INODE_F_NODEFRAG RT_BIT(13)
+/** Use filestream allocator. */
+#define XFS_INODE_F_FILESTREAM RT_BIT(14)
+/** @} */
+
+/** @name XFS_INODE_F2_XXX - Inode flags number 2 (XFSINODECORE::fFlags2).
+ * @{ */
+/** Use DAX for the inode. */
+#define XFS_INODE_F2_DAX RT_BIT_64(0)
+/** Blocks use reference counting for sharing. */
+#define XFS_INODE_F2_REFLINK RT_BIT_64(1)
+/** Inode COW extent size hint is valid. */
+#define XFS_INODE_F2_COWEXTSIZEHINT RT_BIT_64(2)
+/** @} */
+
+
+/**
+ * Inode B-Tree record.
+ */
+typedef struct XFSINODEBTREEREC
+{
+ /** 0x00: Starting inode number. */
+ uint32_t uInodeStart;
+ /** 0x04: Version dependent data. */
+ union
+ {
+ /** Full (old) version. */
+ struct
+ {
+ /** 0x04: Number of free inodes. */
+ uint32_t cInodesFree;
+ } Full;
+ /** Sparse (new) version. */
+ struct
+ {
+ /** 0x04: Hole mask for sparse chunks. */
+ uint16_t bmHoles;
+ /** 0x06: Total number of inodes. */
+ uint8_t cInodes;
+ /** 0x07: Number of free inodes. */
+ uint8_t cInodesFree;
+ } Sparse;
+ } u;
+ /** 0x08: Free inode mask. */
+ uint64_t bmInodesFree;
+} XFSINODEBTREEREC;
+/** Pointer to an inode B-Tree record. */
+typedef XFSINODEBTREEREC *PXFSINODEBTREEREC;
+/** Pointer to a const inode B-Tree record. */
+typedef const XFSINODEBTREEREC *PCXFSINODEBTREEREC;
+
+
+/**
+ * XFS B+Tree root header.
+ */
+typedef struct XFSBTREEROOTHDR
+{
+ /** 0x00: Tree level. */
+ uint16_t iLvl;
+ /** 0x02: Number of records. */
+ uint16_t cRecs;
+} XFSBTREEROOTHDR;
+/** Pointer to a B+Tree root header */
+typedef XFSBTREEROOTHDR *PXFSBTREEROOTHDR;
+/** Pointer to a const B+Tree root header. */
+typedef const XFSBTREEROOTHDR *PCXFSBTREEROOTHDR;
+
+
+/**
+ * XFS B+Tree intermediate/leave node header.
+ */
+typedef struct XFSBTREENODEHDR
+{
+ /** 0x00: Magic identifying the node. */
+ uint32_t u32Magic;
+ /** 0x04: Tree level. */
+ uint16_t iLvl;
+ /** 0x06: Number of records. */
+ uint16_t cRecs;
+ /** 0x08: Block number of the left sibling. */
+ uint64_t uSibLeft;
+ /** 0x10: Block number of the right sibling. */
+ uint64_t uSibRight;
+} XFSBTREENODEHDR;
+/** Pointer to a B+Tree intermediate/leave node header. */
+typedef XFSBTREENODEHDR *PXFSBTREENODEHDR;
+/** Pointer to a const B+Tree intermediate/leave node header. */
+typedef const XFSBTREENODEHDR *PCXFSBTREENODEHDR;
+
+/** @name XFS_BTREENODEHDR_XXX - B+Tree node related defines.
+ * @{ */
+/** Magic for the tree node header. */
+#define XFS_BTREENODEHDR_MAGIC RT_MAKE_U32_FROM_U8('P', 'A', 'M', 'B')
+/** @} */
+
+
+/**
+ * XFS Extent.
+ */
+typedef struct XFSEXTENT
+{
+ /** 0x00: Low 64 bits. */
+ uint64_t u64Low;
+ /** 0x08: High 64 bits. */
+ uint64_t u64High;
+} XFSEXTENT;
+/** Pointer to an XFS extent. */
+typedef XFSEXTENT *PXFSEXTENT;
+/** Pointer to a const XFS extent. */
+typedef const XFSEXTENT *PCXFSEXTENT;
+
+/** @name XFS_EXTENT_XXX - Extent related getters.
+ * @{ */
+/** Returns whether the extent is allocated but unwritten (true) or a normal extent (false). */
+#define XFS_EXTENT_IS_UNWRITTEN(a_pExtent) (RT_BOOL((a_pExtent)->u64High & RT_BIT_64(63)))
+/** Returns the number of blocks the extent covers. */
+#define XFS_EXTENT_GET_BLOCK_COUNT(a_pExtent) ((a_pExtent)->u64Low & UINT64_C(0x1fffff))
+/** Returns the absolute block number where the data is stored on the disk. */
+#define XFS_EXTENT_GET_DISK_BLOCK(a_pExtent) ( (((a_pExtent)->u64High & UINT64_C(0x1ff)) << 42) \
+ | (((a_pExtent)->u64Low & UINT64_C(0xffffffffffe00000)) >> 21))
+/** Returns the logical inode block offset. */
+#define XFS_EXTENT_GET_LOGICAL_BLOCK(a_pExtent) (((a_pExtent)->u64High & UINT64_C(0x7ffffffffffffe00)) >> 9)
+/** @} */
+
+/** @} */
+
+#endif /* !IPRT_INCLUDED_formats_xfs_h */
+
diff --git a/include/iprt/fs.h b/include/iprt/fs.h
new file mode 100644
index 00000000..03c4f370
--- /dev/null
+++ b/include/iprt/fs.h
@@ -0,0 +1,668 @@
+/** @file
+ * IPRT - Filesystem.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_fs_h
+#define IPRT_INCLUDED_fs_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#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,
+ /** Extended File Allocation Table, main target are flash drives. */
+ RTFSTYPE_EXFAT,
+ /** Resilient File System. */
+ RTFSTYPE_REFS,
+
+ /* 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_APFS,
+ 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_RTUID if not supported. */
+ RTUID uid;
+
+ /** The group the filesystem object is assigned (st_gid).
+ * This field is NIL_RTGID 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.
+ *
+ * @remarks The special '..' dir always shows up with 0 on NTFS/Windows. */
+ 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 compressed.
+ * 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 DECLCALLBACKTYPE(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);
+
+
+/**
+ * A /bin/ls clone.
+ *
+ * @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.)
+ */
+RTR3DECL(RTEXITCODE) RTFsCmdLs(unsigned cArgs, char **papszArgs);
+
+#endif /* IN_RING3 */
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_fs_h */
+
diff --git a/include/iprt/fsisomaker.h b/include/iprt/fsisomaker.h
new file mode 100644
index 00000000..5eb782ba
--- /dev/null
+++ b/include/iprt/fsisomaker.h
@@ -0,0 +1,826 @@
+/** @file
+ * IPRT - ISO Image Maker.
+ */
+
+/*
+ * Copyright (C) 2017-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_fsisomaker_h
+#define IPRT_INCLUDED_fsisomaker_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+#include <iprt/time.h>
+#include <iprt/fs.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_fsisomaker RTFsIsoMaker - ISO Image Maker
+ * @ingroup grp_rt_fs
+ * @{
+ */
+
+
+/** @name RTFSISOMAKER_NAMESPACE_XXX - Namespace selector.
+ * @{
+ */
+#define RTFSISOMAKER_NAMESPACE_ISO_9660 RT_BIT_32(0) /**< The primary ISO-9660 namespace. */
+#define RTFSISOMAKER_NAMESPACE_JOLIET RT_BIT_32(1) /**< The joliet namespace. */
+#define RTFSISOMAKER_NAMESPACE_UDF RT_BIT_32(2) /**< The UDF namespace. */
+#define RTFSISOMAKER_NAMESPACE_HFS RT_BIT_32(3) /**< The HFS namespace */
+#define RTFSISOMAKER_NAMESPACE_ALL UINT32_C(0x0000000f) /**< All namespaces. */
+#define RTFSISOMAKER_NAMESPACE_VALID_MASK UINT32_C(0x0000000f) /**< Valid namespace bits. */
+/** @} */
+
+/** Root directory configuration index. */
+#define RTFSISOMAKER_CFG_IDX_ROOT UINT32_C(0)
+
+
+/**
+ * Creates an ISO maker instance.
+ *
+ * @returns IPRT status code.
+ * @param phIsoMaker Where to return the handle to the new ISO maker.
+ */
+RTDECL(int) RTFsIsoMakerCreate(PRTFSISOMAKER phIsoMaker);
+
+/**
+ * Retains a references to an ISO maker instance.
+ *
+ * @returns New reference count on success, UINT32_MAX if invalid handle.
+ * @param hIsoMaker The ISO maker handle.
+ */
+RTDECL(uint32_t) RTFsIsoMakerRetain(RTFSISOMAKER hIsoMaker);
+
+/**
+ * Releases a references to an ISO maker instance.
+ *
+ * @returns New reference count on success, UINT32_MAX if invalid handle.
+ * @param hIsoMaker The ISO maker handle. NIL is ignored.
+ */
+RTDECL(uint32_t) RTFsIsoMakerRelease(RTFSISOMAKER hIsoMaker);
+
+/**
+ * Sets the ISO-9660 level.
+ *
+ * @returns IPRT status code
+ * @param hIsoMaker The ISO maker handle.
+ * @param uIsoLevel The level, 1-3.
+ */
+RTDECL(int) RTFsIsoMakerSetIso9660Level(RTFSISOMAKER hIsoMaker, uint8_t uIsoLevel);
+
+/**
+ * Gets the ISO-9660 level.
+ *
+ * @returns The level, UINT8_MAX if invalid handle.
+ * @param hIsoMaker The ISO maker handle.
+ */
+RTDECL(uint8_t) RTFsIsoMakerGetIso9660Level(RTFSISOMAKER hIsoMaker);
+
+/**
+ * Sets the joliet level.
+ *
+ * @returns IPRT status code
+ * @param hIsoMaker The ISO maker handle.
+ * @param uJolietLevel The joliet UCS-2 level 1-3, or 0 to disable
+ * joliet.
+ */
+RTDECL(int) RTFsIsoMakerSetJolietUcs2Level(RTFSISOMAKER hIsoMaker, uint8_t uJolietLevel);
+
+/**
+ * Sets the rock ridge support level (on the primary ISO-9660 namespace).
+ *
+ * @returns IPRT status code
+ * @param hIsoMaker The ISO maker handle.
+ * @param uLevel 0 if disabled, 1 to just enable, 2 to enable and
+ * write the ER tag.
+ */
+RTDECL(int) RTFsIsoMakerSetRockRidgeLevel(RTFSISOMAKER hIsoMaker, uint8_t uLevel);
+
+/**
+ * Sets the rock ridge support level on the joliet namespace (experimental).
+ *
+ * @returns IPRT status code
+ * @param hIsoMaker The ISO maker handle.
+ * @param uLevel 0 if disabled, 1 to just enable, 2 to enable and
+ * write the ER tag.
+ */
+RTDECL(int) RTFsIsoMakerSetJolietRockRidgeLevel(RTFSISOMAKER hIsoMaker, uint8_t uLevel);
+
+/**
+ * Gets the rock ridge support level (on the primary ISO-9660 namespace).
+ *
+ * @returns 0 if disabled, 1 just enabled, 2 if enabled with ER tag, and
+ * UINT8_MAX if the handle is invalid.
+ * @param hIsoMaker The ISO maker handle.
+ */
+RTDECL(uint8_t) RTFsIsoMakerGetRockRidgeLevel(RTFSISOMAKER hIsoMaker);
+
+/**
+ * Gets the rock ridge support level on the joliet namespace (experimental).
+ *
+ * @returns 0 if disabled, 1 just enabled, 2 if enabled with ER tag, and
+ * UINT8_MAX if the handle is invalid.
+ * @param hIsoMaker The ISO maker handle.
+ */
+RTDECL(uint8_t) RTFsIsoMakerGetJolietRockRidgeLevel(RTFSISOMAKER hIsoMaker);
+
+/**
+ * Changes the file attribute (mode, owner, group) inherit style (from source).
+ *
+ * The strict style will use the exact attributes from the source, where as the
+ * non-strict (aka rational and default) style will use 0 for the owner and
+ * group IDs and normalize the mode bits along the lines of 'chmod a=rX',
+ * stripping set-uid/gid bitson files but preserving sticky ones on directories.
+ *
+ * When disabling strict style, the default dir and file modes will be restored
+ * to default values.
+ *
+ * @returns IRPT status code.
+ * @param hIsoMaker The ISO maker handle.
+ * @param fStrict Indicates strict (true) or non-strict (false)
+ * style.
+ */
+RTDECL(int) RTFsIsoMakerSetAttribInheritStyle(RTFSISOMAKER hIsoMaker, bool fStrict);
+
+/**
+ * Sets the default file mode settings.
+ *
+ * @returns IRPT status code.
+ * @param hIsoMaker The ISO maker handle.
+ * @param fMode The default file mode.
+ */
+RTDECL(int) RTFsIsoMakerSetDefaultFileMode(RTFSISOMAKER hIsoMaker, RTFMODE fMode);
+
+/**
+ * Sets the default dir mode settings.
+ *
+ * @returns IRPT status code.
+ * @param hIsoMaker The ISO maker handle.
+ * @param fMode The default dir mode.
+ */
+RTDECL(int) RTFsIsoMakerSetDefaultDirMode(RTFSISOMAKER hIsoMaker, RTFMODE fMode);
+
+/**
+ * Sets the forced file mode, if @a fForce is true also the default mode is set.
+ *
+ * @returns IRPT status code.
+ * @param hIsoMaker The ISO maker handle.
+ * @param fMode The file mode.
+ * @param fForce Indicate whether forced mode is active or not.
+ */
+RTDECL(int) RTFsIsoMakerSetForcedFileMode(RTFSISOMAKER hIsoMaker, RTFMODE fMode, bool fForce);
+
+/**
+ * Sets the forced dir mode, if @a fForce is true also the default mode is set.
+ *
+ * @returns IRPT status code.
+ * @param hIsoMaker The ISO maker handle.
+ * @param fMode The dir mode.
+ * @param fForce Indicate whether forced mode is active or not.
+ */
+RTDECL(int) RTFsIsoMakerSetForcedDirMode(RTFSISOMAKER hIsoMaker, RTFMODE fMode, bool fForce);
+
+/**
+ * Sets the content of the system area, i.e. the first 32KB of the image.
+ *
+ * This can be used to put generic boot related stuff.
+ *
+ * @note Other settings may overwrite parts of the content (yet to be
+ * determined which).
+ *
+ * @returns IPRT status code
+ * @param hIsoMaker The ISO maker handle.
+ * @param pvContent The content to put in the system area.
+ * @param cbContent The size of the content.
+ * @param off The offset into the system area.
+ */
+RTDECL(int) RTFsIsoMakerSetSysAreaContent(RTFSISOMAKER hIsoMaker, void const *pvContent, size_t cbContent, uint32_t off);
+
+/**
+ * String properties settable thru RTFsIsoMakerSetStringProp.
+ */
+typedef enum RTFSISOMAKERSTRINGPROP
+{
+ /** The customary invalid zero value. */
+ RTFSISOMAKERSTRINGPROP_INVALID = 0,
+ /** The system identifier. */
+ RTFSISOMAKERSTRINGPROP_SYSTEM_ID,
+ /** The volume identifier(label). */
+ RTFSISOMAKERSTRINGPROP_VOLUME_ID,
+ /** The volume set identifier. */
+ RTFSISOMAKERSTRINGPROP_VOLUME_SET_ID,
+ /** The publisher ID (root file reference if it starts with '_'). */
+ RTFSISOMAKERSTRINGPROP_PUBLISHER_ID,
+ /** The data preparer ID (root file reference if it starts with '_'). */
+ RTFSISOMAKERSTRINGPROP_DATA_PREPARER_ID,
+ /** The application ID (root file reference if it starts with '_'). */
+ RTFSISOMAKERSTRINGPROP_APPLICATION_ID,
+ /** The copyright file ID. */
+ RTFSISOMAKERSTRINGPROP_COPYRIGHT_FILE_ID,
+ /** The abstract file ID. */
+ RTFSISOMAKERSTRINGPROP_ABSTRACT_FILE_ID,
+ /** The bibliographic file ID. */
+ RTFSISOMAKERSTRINGPROP_BIBLIOGRAPHIC_FILE_ID,
+ /** End of valid string property values. */
+ RTFSISOMAKERSTRINGPROP_END,
+ /** Make sure it's a 32-bit type. */
+ RTFSISOMAKERSTRINGPROP_32BIT_HACK = 0x7fffffff
+} RTFSISOMAKERSTRINGPROP;
+
+/**
+ * Sets a string property in one or more namespaces.
+ *
+ * @returns IPRT status code.
+ * @param hIsoMaker The ISO maker handle.
+ * @param enmStringProp The string property to set.
+ * @param fNamespaces The namespaces to set it in.
+ * @param pszValue The value to set it to. NULL is treated like an
+ * empty string. The value will be silently truncated
+ * to fit the available space.
+ */
+RTDECL(int) RTFsIsoMakerSetStringProp(RTFSISOMAKER hIsoMaker, RTFSISOMAKERSTRINGPROP enmStringProp,
+ uint32_t fNamespaces, const char *pszValue);
+
+/**
+ * Specifies image padding.
+ *
+ * @returns IPRT status code.
+ * @param hIsoMaker The ISO maker handle.
+ * @param cSectors Number of sectors to pad the image with.
+ */
+RTDECL(int) RTFsIsoMakerSetImagePadding(RTFSISOMAKER hIsoMaker, uint32_t cSectors);
+
+/**
+ * Gets currently populated namespaces.
+ *
+ * @returns Set of namespaces (RTFSISOMAKER_NAMESPACE_XXX), UINT32_MAX on error.
+ * @param hIsoMaker The ISO maker handle.
+ */
+RTDECL(uint32_t) RTFsIsoMakerGetPopulatedNamespaces(RTFSISOMAKER hIsoMaker);
+
+/**
+ * Resolves a path into a object ID.
+ *
+ * This will be doing the looking up using the specified object names rather
+ * than the version adjusted and mangled according to the namespace setup.
+ *
+ * @returns The object ID corresponding to @a pszPath, or UINT32_MAX if not
+ * found or invalid parameters.
+ * @param hIsoMaker The ISO maker instance.
+ * @param fNamespaces The namespace to resolve @a pszPath in. It's
+ * possible to specify multiple namespaces here, of
+ * course, but that's inefficient.
+ * @param pszPath The path to the object.
+ */
+RTDECL(uint32_t) RTFsIsoMakerGetObjIdxForPath(RTFSISOMAKER hIsoMaker, uint32_t fNamespaces, const char *pszPath);
+
+/**
+ * Queries the configuration index of the boot catalog file object.
+ *
+ * The boot catalog file is created as necessary, thus this have to be a query
+ * rather than a getter since object creation may fail.
+ *
+ * @returns IPRT status code.
+ * @param hIsoMaker The ISO maker handle.
+ * @param pidxObj Where to return the configuration index.
+ */
+RTDECL(int) RTFsIsoMakerQueryObjIdxForBootCatalog(RTFSISOMAKER hIsoMaker, uint32_t *pidxObj);
+
+/**
+ * Removes the specified object from the image.
+ *
+ * @returns IPRT status code.
+ * @param hIsoMaker The ISO maker instance.
+ * @param idxObj The index of the object to remove.
+ */
+RTDECL(int) RTFsIsoMakerObjRemove(RTFSISOMAKER hIsoMaker, uint32_t idxObj);
+
+/**
+ * Sets the path (name) of an object in the selected namespaces.
+ *
+ * The name will be transformed as necessary.
+ *
+ * The initial implementation does not allow this function to be called more
+ * than once on an object.
+ *
+ * @returns IPRT status code.
+ * @param hIsoMaker The ISO maker handle.
+ * @param idxObj The configuration index of to name.
+ * @param fNamespaces The namespaces to apply the path to
+ * (RTFSISOMAKER_NAMESPACE_XXX).
+ * @param pszPath The path.
+ */
+RTDECL(int) RTFsIsoMakerObjSetPath(RTFSISOMAKER hIsoMaker, uint32_t idxObj, uint32_t fNamespaces, const char *pszPath);
+
+/**
+ * Sets the name of an object in the selected namespaces, placing it under the
+ * given directory.
+ *
+ * The name will be transformed as necessary.
+ *
+ * @returns IPRT status code.
+ * @param hIsoMaker The ISO maker handle.
+ * @param idxObj The configuration index of to name.
+ * @param idxParentObj The parent directory object.
+ * @param fNamespaces The namespaces to apply the path to
+ * (RTFSISOMAKER_NAMESPACE_XXX).
+ * @param pszName The name.
+ * @param fNoNormalize Don't normalize the name (imported or such).
+ */
+RTDECL(int) RTFsIsoMakerObjSetNameAndParent(RTFSISOMAKER hIsoMaker, uint32_t idxObj, uint32_t idxParentObj,
+ uint32_t fNamespaces, const char *pszName, bool fNoNormalize);
+
+/**
+ * Changes the rock ridge name for the object in the selected namespaces.
+ *
+ * The object must already be enetered into the namespaces by
+ * RTFsIsoMakerObjSetNameAndParent, RTFsIsoMakerObjSetPath or similar.
+ *
+ * @returns IPRT status code.
+ * @param hIsoMaker The ISO maker handle.
+ * @param idxObj The configuration index of to name.
+ * @param fNamespaces The namespaces to apply the path to
+ * (RTFSISOMAKER_NAMESPACE_XXX).
+ * @param pszRockName The rock ridge name. Passing NULL or an empty
+ * string will restore the specified name.
+ */
+RTDECL(int) RTFsIsoMakerObjSetRockName(RTFSISOMAKER hIsoMaker, uint32_t idxObj, uint32_t fNamespaces, const char *pszRockName);
+
+/**
+ * Enables or disable syslinux boot info table patching of a file.
+ *
+ * @returns IPRT status code.
+ * @param hIsoMaker The ISO maker handle.
+ * @param idxObj The configuration index.
+ * @param fEnable Whether to enable or disable patching.
+ */
+RTDECL(int) RTFsIsoMakerObjEnableBootInfoTablePatching(RTFSISOMAKER hIsoMaker, uint32_t idxObj, bool fEnable);
+
+/**
+ * Gets the data size of an object.
+ *
+ * Currently only supported on file objects.
+ *
+ * @returns IPRT status code.
+ * @param hIsoMaker The ISO maker handle.
+ * @param idxObj The configuration index.
+ * @param pcbData Where to return the size.
+ */
+RTDECL(int) RTFsIsoMakerObjQueryDataSize(RTFSISOMAKER hIsoMaker, uint32_t idxObj, uint64_t *pcbData);
+
+/**
+ * Adds an unnamed directory to the image.
+ *
+ * The directory must explictly be entered into the desired namespaces.
+ *
+ * @returns IPRT status code
+ * @param hIsoMaker The ISO maker handle.
+ * @param pObjInfo Pointer to object attributes, must be set to
+ * UNIX. The size and hardlink counts are ignored.
+ * Optional.
+ * @param pidxObj Where to return the configuration index of the
+ * directory.
+ * @sa RTFsIsoMakerAddDir, RTFsIsoMakerObjSetPath
+ */
+RTDECL(int) RTFsIsoMakerAddUnnamedDir(RTFSISOMAKER hIsoMaker, PCRTFSOBJINFO pObjInfo, uint32_t *pidxObj);
+
+/**
+ * Adds a directory to the image in all namespaces and default attributes.
+ *
+ * @returns IPRT status code
+ * @param hIsoMaker The ISO maker handle.
+ * @param pszDir The path (UTF-8) to the directory in the ISO.
+ *
+ * @param pidxObj Where to return the configuration index of the
+ * directory. Optional.
+ * @sa RTFsIsoMakerAddUnnamedDir, RTFsIsoMakerObjSetPath
+ */
+RTDECL(int) RTFsIsoMakerAddDir(RTFSISOMAKER hIsoMaker, const char *pszDir, uint32_t *pidxObj);
+
+/**
+ * Adds an unnamed file to the image that's backed by a host file.
+ *
+ * The file must explictly be entered into the desired namespaces.
+ *
+ * @returns IPRT status code
+ * @param hIsoMaker The ISO maker handle.
+ * @param pszSrcFile The source file path. VFS chain spec allowed.
+ * @param pidxObj Where to return the configuration index of the
+ * directory.
+ * @sa RTFsIsoMakerAddFile, RTFsIsoMakerObjSetPath
+ */
+RTDECL(int) RTFsIsoMakerAddUnnamedFileWithSrcPath(RTFSISOMAKER hIsoMaker, const char *pszSrcFile, uint32_t *pidxObj);
+
+/**
+ * Adds an unnamed file to the image that's backed by a VFS file.
+ *
+ * The file must explictly be entered into the desired namespaces.
+ *
+ * @returns IPRT status code
+ * @param hIsoMaker The ISO maker handle.
+ * @param hVfsFileSrc The source file handle.
+ * @param pidxObj Where to return the configuration index of the
+ * directory.
+ * @sa RTFsIsoMakerAddUnnamedFileWithSrcPath, RTFsIsoMakerObjSetPath
+ */
+RTDECL(int) RTFsIsoMakerAddUnnamedFileWithVfsFile(RTFSISOMAKER hIsoMaker, RTVFSFILE hVfsFileSrc, uint32_t *pidxObj);
+
+/**
+ * Adds an unnamed file to the image that's backed by a portion of a common
+ * source file.
+ *
+ * The file must explictly be entered into the desired namespaces.
+ *
+ * @returns IPRT status code
+ * @param hIsoMaker The ISO maker handle.
+ * @param idxCommonSrc The common source file index.
+ * @param offData The offset of the data in the source file.
+ * @param cbData The file size.
+ * @param pObjInfo Pointer to file info. Optional.
+ * @param pidxObj Where to return the configuration index of the
+ * directory.
+ * @sa RTFsIsoMakerAddUnnamedFileWithSrcPath, RTFsIsoMakerObjSetPath
+ */
+RTDECL(int) RTFsIsoMakerAddUnnamedFileWithCommonSrc(RTFSISOMAKER hIsoMaker, uint32_t idxCommonSrc,
+ uint64_t offData, uint64_t cbData, PCRTFSOBJINFO pObjInfo, uint32_t *pidxObj);
+
+/**
+ * Adds a common source file.
+ *
+ * Using RTFsIsoMakerAddUnnamedFileWithCommonSrc a sections common source file
+ * can be referenced to make up other files. The typical use case is when
+ * importing data from an existing ISO.
+ *
+ * @returns IPRT status code
+ * @param hIsoMaker The ISO maker handle.
+ * @param hVfsFile VFS handle of the common source. (A reference
+ * is added, none consumed.)
+ * @param pidxCommonSrc Where to return the assigned common source
+ * index. This is used to reference the file.
+ * @sa RTFsIsoMakerAddUnnamedFileWithCommonSrc
+ */
+RTDECL(int) RTFsIsoMakerAddCommonSourceFile(RTFSISOMAKER hIsoMaker, RTVFSFILE hVfsFile, uint32_t *pidxCommonSrc);
+
+/**
+ * Adds a file that's backed by a host file to the image in all namespaces and
+ * with attributes taken from the source file.
+ *
+ * @returns IPRT status code
+ * @param hIsoMaker The ISO maker handle.
+ * @param pszFile The path to the file in the image.
+ * @param pszSrcFile The source file path. VFS chain spec allowed.
+ * @param pidxObj Where to return the configuration index of the file.
+ * Optional
+ * @sa RTFsIsoMakerAddFileWithVfsFile,
+ * RTFsIsoMakerAddUnnamedFileWithSrcPath
+ */
+RTDECL(int) RTFsIsoMakerAddFileWithSrcPath(RTFSISOMAKER hIsoMaker, const char *pszFile, const char *pszSrcFile, uint32_t *pidxObj);
+
+/**
+ * Adds a file that's backed by a VFS file to the image in all namespaces and
+ * with attributes taken from the source file.
+ *
+ * @returns IPRT status code
+ * @param hIsoMaker The ISO maker handle.
+ * @param pszFile The path to the file in the image.
+ * @param hVfsFileSrc The source file handle.
+ * @param pidxObj Where to return the configuration index of the file.
+ * Optional.
+ * @sa RTFsIsoMakerAddUnnamedFileWithVfsFile,
+ * RTFsIsoMakerAddFileWithSrcPath
+ */
+RTDECL(int) RTFsIsoMakerAddFileWithVfsFile(RTFSISOMAKER hIsoMaker, const char *pszFile, RTVFSFILE hVfsFileSrc, uint32_t *pidxObj);
+
+/**
+ * Adds an unnamed symbolic link to the image.
+ *
+ * The symlink must explictly be entered into the desired namespaces. Please
+ * note that it is not possible to enter a symbolic link into an ISO 9660
+ * namespace where rock ridge extensions are disabled, since symbolic links
+ * depend on rock ridge. For HFS and UDF there is no such requirement.
+ *
+ * Will fail if no namespace is configured that supports symlinks.
+ *
+ * @returns IPRT status code
+ * @retval VERR_ISOMK_SYMLINK_SUPPORT_DISABLED if not supported.
+ * @param hIsoMaker The ISO maker handle.
+ * @param pObjInfo Pointer to object attributes, must be set to
+ * UNIX. The size and hardlink counts are ignored.
+ * Optional.
+ * @param pszTarget The symbolic link target (UTF-8).
+ * @param pidxObj Where to return the configuration index of the
+ * directory.
+ * @sa RTFsIsoMakerAddSymlink, RTFsIsoMakerObjSetPath
+ */
+RTDECL(int) RTFsIsoMakerAddUnnamedSymlink(RTFSISOMAKER hIsoMaker, PCRTFSOBJINFO pObjInfo, const char *pszTarget, uint32_t *pidxObj);
+
+/**
+ * Adds a directory to the image in all namespaces and default attributes.
+ *
+ * Will fail if no namespace is configured that supports symlinks.
+ *
+ * @returns IPRT status code
+ * @param hIsoMaker The ISO maker handle.
+ * @param pszSymlink The path (UTF-8) to the symlink in the ISO.
+ * @param pszTarget The symlink target (UTF-8).
+ * @param pidxObj Where to return the configuration index of the
+ * directory. Optional.
+ * @sa RTFsIsoMakerAddUnnamedSymlink, RTFsIsoMakerObjSetPath
+ */
+RTDECL(int) RTFsIsoMakerAddSymlink(RTFSISOMAKER hIsoMaker, const char *pszSymlink, const char *pszTarget, uint32_t *pidxObj);
+
+/**
+ * Modifies the mode mask for a given path in one or more namespaces.
+ *
+ * The mode mask is used by rock ridge, UDF and HFS.
+ *
+ * @returns IPRT status code.
+ * @retval VWRN_NOT_FOUND if the path wasn't found in any of the specified
+ * namespaces.
+ *
+ * @param hIsoMaker The ISO maker handler.
+ * @param pszPath The path which mode mask should be modified.
+ * @param fNamespaces The namespaces to set it in.
+ * @param fSet The mode bits to set.
+ * @param fUnset The mode bits to clear (applied first).
+ * @param fFlags Reserved, MBZ.
+ * @param pcHits Where to return number of paths found. Optional.
+ */
+RTDECL(int) RTFsIsoMakerSetPathMode(RTFSISOMAKER hIsoMaker, const char *pszPath, uint32_t fNamespaces,
+ RTFMODE fSet, RTFMODE fUnset, uint32_t fFlags, uint32_t *pcHits);
+
+/**
+ * Modifies the owner ID for a given path in one or more namespaces.
+ *
+ * The owner ID is used by rock ridge, UDF and HFS.
+ *
+ * @returns IPRT status code.
+ * @retval VWRN_NOT_FOUND if the path wasn't found in any of the specified
+ * namespaces.
+ *
+ * @param hIsoMaker The ISO maker handler.
+ * @param pszPath The path which mode mask should be modified.
+ * @param fNamespaces The namespaces to set it in.
+ * @param idOwner The new owner ID to set.
+ * @param pcHits Where to return number of paths found. Optional.
+ */
+RTDECL(int) RTFsIsoMakerSetPathOwnerId(RTFSISOMAKER hIsoMaker, const char *pszPath, uint32_t fNamespaces,
+ RTUID idOwner, uint32_t *pcHits);
+
+/**
+ * Modifies the group ID for a given path in one or more namespaces.
+ *
+ * The group ID is used by rock ridge, UDF and HFS.
+ *
+ * @returns IPRT status code.
+ * @retval VWRN_NOT_FOUND if the path wasn't found in any of the specified
+ * namespaces.
+ *
+ * @param hIsoMaker The ISO maker handler.
+ * @param pszPath The path which mode mask should be modified.
+ * @param fNamespaces The namespaces to set it in.
+ * @param idGroup The new group ID to set.
+ * @param pcHits Where to return number of paths found. Optional.
+ */
+RTDECL(int) RTFsIsoMakerSetPathGroupId(RTFSISOMAKER hIsoMaker, const char *pszPath, uint32_t fNamespaces,
+ RTGID idGroup, uint32_t *pcHits);
+
+/**
+ * Set the validation entry of the boot catalog (this is the first entry).
+ *
+ * @returns IPRT status code.
+ * @param hIsoMaker The ISO maker handle.
+ * @param idPlatform The platform ID
+ * (ISO9660_ELTORITO_PLATFORM_ID_XXX).
+ * @param pszString CD/DVD-ROM identifier. Optional.
+ */
+RTDECL(int) RTFsIsoMakerBootCatSetValidationEntry(RTFSISOMAKER hIsoMaker, uint8_t idPlatform, const char *pszString);
+
+/**
+ * Set the validation entry of the boot catalog (this is the first entry).
+ *
+ * @returns IPRT status code.
+ * @param hIsoMaker The ISO maker handle.
+ * @param idxBootCat The boot catalog entry. Zero and two are
+ * invalid. Must be less than 63.
+ * @param idxImageObj The configuration index of the boot image.
+ * @param bBootMediaType The media type and flag (not for entry 1)
+ * (ISO9660_ELTORITO_BOOT_MEDIA_TYPE_XXX,
+ * ISO9660_ELTORITO_BOOT_MEDIA_F_XXX).
+ * @param bSystemType The partitiona table system ID.
+ * @param fBootable Whether it's a bootable entry or if we just want
+ * the BIOS to setup the emulation without booting
+ * it.
+ * @param uLoadSeg The load address divided by 0x10 (i.e. the real
+ * mode segment number).
+ * @param cSectorsToLoad Number of emulated sectors to load.
+ * @param bSelCritType The selection criteria type, if none pass
+ * ISO9660_ELTORITO_SEL_CRIT_TYPE_NONE.
+ * @param pvSelCritData Pointer to the selection criteria data.
+ * @param cbSelCritData Size of the selection criteria data.
+ */
+RTDECL(int) RTFsIsoMakerBootCatSetSectionEntry(RTFSISOMAKER hIsoMaker, uint32_t idxBootCat, uint32_t idxImageObj,
+ uint8_t bBootMediaType, uint8_t bSystemType, bool fBootable,
+ uint16_t uLoadSeg, uint16_t cSectorsToLoad,
+ uint8_t bSelCritType, void const *pvSelCritData, size_t cbSelCritData);
+
+/**
+ * Set the validation entry of the boot catalog (this is the first entry).
+ *
+ * @returns IPRT status code.
+ * @param hIsoMaker The ISO maker handle.
+ * @param idxBootCat The boot catalog entry.
+ * @param cEntries Number of entries in the section.
+ * @param idPlatform The platform ID
+ * (ISO9660_ELTORITO_PLATFORM_ID_XXX).
+ * @param pszString Section identifier or something. Optional.
+ */
+RTDECL(int) RTFsIsoMakerBootCatSetSectionHeaderEntry(RTFSISOMAKER hIsoMaker, uint32_t idxBootCat, uint32_t cEntries,
+ uint8_t idPlatform, const char *pszString);
+
+/**
+ * Sets the boot catalog backing file.
+ *
+ * The content of the given file will be discarded and replaced with the boot
+ * catalog, the naming and file attributes (other than size) will be retained.
+ *
+ * This API exists mainly to assist when importing ISOs.
+ *
+ * @returns IPRT status code.
+ * @param hIsoMaker The ISO maker handle.
+ * @param idxObj The configuration index of the file.
+ */
+RTDECL(int) RTFsIsoMakerBootCatSetFile(RTFSISOMAKER hIsoMaker, uint32_t idxObj);
+
+
+/**
+ * ISO maker import results (RTFsIsoMakerImport).
+ */
+typedef struct RTFSISOMAKERIMPORTRESULTS
+{
+ /** Number of names added. */
+ uint32_t cAddedNames;
+ /** Number of directories added. */
+ uint32_t cAddedDirs;
+ /** Amount of added data blocks, files only. */
+ uint64_t cbAddedDataBlocks;
+ /** Number of unique files added (unique in terms of data location). */
+ uint32_t cAddedFiles;
+ /** Number of symbolic links added. */
+ uint32_t cAddedSymlinks;
+ /** Number of imported boot catalog entries. */
+ uint32_t cBootCatEntries;
+ /** Number of system area bytes imported (from offset zero). */
+ uint32_t cbSysArea;
+
+ /** Number of import errors. */
+ uint32_t cErrors;
+} RTFSISOMAKERIMPORTRESULTS;
+/** Pointer to ISO maker import results. */
+typedef RTFSISOMAKERIMPORTRESULTS *PRTFSISOMAKERIMPORTRESULTS;
+
+/**
+ * Imports an existing ISO.
+ *
+ * Just like other source files, the existing image must remain present and
+ * unmodified till the ISO maker is done with it.
+ *
+ * @returns IRPT status code.
+ * @param hIsoMaker The ISO maker handle.
+ * @param hIsoFile VFS file handle to the existing image to import / clone.
+ * @param fFlags Reserved for the future, MBZ.
+ * @param pResults Where to return import results.
+ * @param pErrInfo Where to return additional error information.
+ * Optional.
+ */
+RTDECL(int) RTFsIsoMakerImport(RTFSISOMAKER hIsoMaker, RTVFSFILE hIsoFile, uint32_t fFlags,
+ PRTFSISOMAKERIMPORTRESULTS pResults, PRTERRINFO pErrInfo);
+
+/** @name RTFSISOMK_IMPORT_F_XXX - Flags for RTFsIsoMakerImport.
+ * @{ */
+#define RTFSISOMK_IMPORT_F_NO_PRIMARY_ISO RT_BIT_32(0) /**< Skip the primary ISO-9660 namespace (rock ridge included). */
+#define RTFSISOMK_IMPORT_F_NO_JOLIET RT_BIT_32(1) /**< Skip the joliet namespace. */
+#define RTFSISOMK_IMPORT_F_NO_ROCK_RIDGE RT_BIT_32(2) /**< Skip rock ridge (both primary and joliet). */
+#define RTFSISOMK_IMPORT_F_NO_UDF RT_BIT_32(3) /**< Skip the UDF namespace. */
+#define RTFSISOMK_IMPORT_F_NO_HFS RT_BIT_32(4) /**< Skip the HFS namespace. */
+#define RTFSISOMK_IMPORT_F_NO_BOOT RT_BIT_32(5) /**< Skip importing El Torito boot stuff. */
+#define RTFSISOMK_IMPORT_F_NO_SYS_AREA RT_BIT_32(6) /**< Skip importing the system area (first 32KB). */
+
+#define RTFSISOMK_IMPORT_F_NO_SYSTEM_ID RT_BIT_32(7) /**< Don't import the system ID primary descriptor field. */
+#define RTFSISOMK_IMPORT_F_NO_VOLUME_ID RT_BIT_32(8) /**< Don't import the volume ID primary descriptor field. */
+#define RTFSISOMK_IMPORT_F_NO_VOLUME_SET_ID RT_BIT_32(9) /**< Don't import the volume set ID primary descriptor field. */
+#define RTFSISOMK_IMPORT_F_NO_PUBLISHER_ID RT_BIT_32(10) /**< Don't import the publisher ID primary descriptor field. */
+#define RTFSISOMK_IMPORT_F_DATA_PREPARER_ID RT_BIT_32(11) /**< Do import the data preparer ID primary descriptor field. */
+#define RTFSISOMK_IMPORT_F_APPLICATION_ID RT_BIT_32(12) /**< Do import the application ID primary descriptor field. */
+#define RTFSISOMK_IMPORT_F_NO_COPYRIGHT_FID RT_BIT_32(13) /**< Don't import the copyright file ID primary descriptor field. */
+#define RTFSISOMK_IMPORT_F_NO_ABSTRACT_FID RT_BIT_32(14) /**< Don't import the abstract file ID primary descriptor field. */
+#define RTFSISOMK_IMPORT_F_NO_BIBLIO_FID RT_BIT_32(15) /**< Don't import the bibliographic file ID primary descriptor field. */
+
+#define RTFSISOMK_IMPORT_F_NO_J_SYSTEM_ID RT_BIT_32(16) /**< Don't import the system ID joliet descriptor field. */
+#define RTFSISOMK_IMPORT_F_NO_J_VOLUME_ID RT_BIT_32(17) /**< Don't import the volume ID joliet descriptor field. */
+#define RTFSISOMK_IMPORT_F_NO_J_VOLUME_SET_ID RT_BIT_32(18) /**< Don't import the volume set ID joliet descriptor field. */
+#define RTFSISOMK_IMPORT_F_NO_J_PUBLISHER_ID RT_BIT_32(19) /**< Don't import the publisher ID joliet descriptor field. */
+#define RTFSISOMK_IMPORT_F_J_DATA_PREPARER_ID RT_BIT_32(20) /**< Do import the data preparer ID joliet descriptor field. */
+#define RTFSISOMK_IMPORT_F_J_APPLICATION_ID RT_BIT_32(21) /**< Do import the application ID joliet descriptor field. */
+#define RTFSISOMK_IMPORT_F_NO_J_COPYRIGHT_FID RT_BIT_32(22) /**< Don't import the copyright file ID joliet descriptor field. */
+#define RTFSISOMK_IMPORT_F_NO_J_ABSTRACT_FID RT_BIT_32(23) /**< Don't import the abstract file ID joliet descriptor field. */
+#define RTFSISOMK_IMPORT_F_NO_J_BIBLIO_FID RT_BIT_32(24) /**< Don't import the bibliographic file ID joliet descriptor field. */
+
+#define RTFSISOMK_IMPORT_F_VALID_MASK UINT32_C(0x01ffffff)
+/** @} */
+
+
+/**
+ * Finalizes the image.
+ *
+ * @returns IPRT status code.
+ * @param hIsoMaker The ISO maker handle.
+ */
+RTDECL(int) RTFsIsoMakerFinalize(RTFSISOMAKER hIsoMaker);
+
+/**
+ * Creates a VFS file for a finalized ISO maker instanced.
+ *
+ * The file can be used to access the image. Both sequential and random access
+ * are supported, so that this could in theory be hooked up to a CD/DVD-ROM
+ * drive emulation and used as a virtual ISO image.
+ *
+ * @returns IRPT status code.
+ * @param hIsoMaker The ISO maker handle.
+ * @param phVfsFile Where to return the handle.
+ */
+RTDECL(int) RTFsIsoMakerCreateVfsOutputFile(RTFSISOMAKER hIsoMaker, PRTVFSFILE phVfsFile);
+
+
+
+/**
+ * ISO maker command (creates image file on disk).
+ *
+ * @returns IPRT status code
+ * @param cArgs Number of arguments.
+ * @param papszArgs Pointer to argument array.
+ */
+RTDECL(RTEXITCODE) RTFsIsoMakerCmd(unsigned cArgs, char **papszArgs);
+
+/**
+ * Extended ISO maker command.
+ *
+ * This can be used as a ISO maker command that produces a image file, or
+ * alternatively for setting up a virtual ISO in memory.
+ *
+ * @returns IPRT status code
+ * @param cArgs Number of arguments.
+ * @param papszArgs Pointer to argument array.
+ * @param hVfsCwd The current working directory to assume when processing
+ * relative file/dir references. Pass NIL_RTVFSDIR to use
+ * the current CWD of the process.
+ * @param pszCwd Path to @a hVfsCwdDir. Use for error reporting and
+ * optimizing the open file count if possible.
+ * @param phVfsFile Where to return the virtual ISO. Pass NULL to for
+ * normal operation (creates file on disk).
+ * @param pErrInfo Where to return extended error information in the
+ * virtual ISO mode.
+ */
+RTDECL(int) RTFsIsoMakerCmdEx(unsigned cArgs, char **papszArgs, RTVFSDIR hVfsCwd, const char *pszCwd,
+ PRTVFSFILE phVfsFile, PRTERRINFO pErrInfo);
+
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_fsisomaker_h */
+
diff --git a/include/iprt/fsvfs.h b/include/iprt/fsvfs.h
new file mode 100644
index 00000000..0b9d8d03
--- /dev/null
+++ b/include/iprt/fsvfs.h
@@ -0,0 +1,204 @@
+/** @file
+ * IPRT - Filesystem, VFS implementations.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_fsvfs_h
+#define IPRT_INCLUDED_fsvfs_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_fs_vfs VFS File System Implementations
+ * @ingroup grp_rt_fs
+ * @{
+ */
+
+/**
+ * Opens a FAT file system volume.
+ *
+ * @returns IPRT status code.
+ * @param hVfsFileIn The file or device backing the volume.
+ * @param fReadOnly Whether to mount it read-only.
+ * @param offBootSector The offset of the boot sector relative to the start
+ * of @a hVfsFileIn. Pass 0 for floppies.
+ * @param phVfs Where to return the virtual file system handle.
+ * @param pErrInfo Where to return additional error information.
+ */
+RTDECL(int) RTFsFatVolOpen(RTVFSFILE hVfsFileIn, bool fReadOnly, uint64_t offBootSector, PRTVFS phVfs, PRTERRINFO pErrInfo);
+
+
+/**
+ * FAT type (format).
+ */
+typedef enum RTFSFATTYPE
+{
+ RTFSFATTYPE_INVALID = 0,
+ RTFSFATTYPE_FAT12,
+ RTFSFATTYPE_FAT16,
+ RTFSFATTYPE_FAT32,
+ RTFSFATTYPE_END
+} RTFSFATTYPE;
+
+
+/** @name RTFSFATVOL_FMT_F_XXX - RTFsFatVolFormat flags
+ * @{ */
+/** Perform a full format, filling unused sectors with 0xf6. */
+#define RTFSFATVOL_FMT_F_FULL UINT32_C(0)
+/** Perform a quick format.
+ * I.e. just write the boot sector, FATs and root directory. */
+#define RTFSFATVOL_FMT_F_QUICK RT_BIT_32(0)
+/** Mask containing all valid flags. */
+#define RTFSFATVOL_FMT_F_VALID_MASK UINT32_C(0x00000001)
+/** @} */
+
+/**
+ * Formats a FAT volume.
+ *
+ * @returns IRPT status code.
+ * @param hVfsFile The volume file.
+ * @param offVol The offset into @a hVfsFile of the file.
+ * Typically 0.
+ * @param cbVol The size of the volume. Pass 0 if the rest of
+ * hVfsFile should be used.
+ * @param fFlags See RTFSFATVOL_FMT_F_XXX.
+ * @param cbSector The logical sector size. Must be power of two.
+ * Optional, pass zero to use 512.
+ * @param cSectorsPerCluster Number of sectors per cluster. Power of two.
+ * Optional, pass zero to auto detect.
+ * @param enmFatType The FAT type (12, 16, 32) to use.
+ * Optional, pass RTFSFATTYPE_INVALID for default.
+ * @param cHeads The number of heads to report in the BPB.
+ * Optional, pass zero to auto detect.
+ * @param cSectorsPerTrack The number of sectors per track to put in the
+ * BPB. Optional, pass zero to auto detect.
+ * @param bMedia The media byte value and FAT ID to use.
+ * Optional, pass zero to auto detect.
+ * @param cRootDirEntries Number of root directory entries.
+ * Optional, pass zero to auto detect.
+ * @param cHiddenSectors Number of hidden sectors. Pass 0 for
+ * unpartitioned media.
+ * @param pErrInfo Additional error information, maybe. Optional.
+ */
+RTDECL(int) RTFsFatVolFormat(RTVFSFILE hVfsFile, uint64_t offVol, uint64_t cbVol, uint32_t fFlags, uint16_t cbSector,
+ uint16_t cSectorsPerCluster, RTFSFATTYPE enmFatType, uint32_t cHeads, uint32_t cSectorsPerTrack,
+ uint8_t bMedia, uint16_t cRootDirEntries, uint32_t cHiddenSectors, PRTERRINFO pErrInfo);
+
+/**
+ * Formats a 1.44MB floppy image.
+ *
+ * @returns IPRT status code.
+ * @param hVfsFile The image. Will be grown to 1.44MB if
+ * necessary.
+ * @param fQuick Whether to quick format the floppy or not.
+ */
+RTDECL(int) RTFsFatVolFormat144(RTVFSFILE hVfsFile, bool fQuick);
+
+/**
+ * Formats a 2.88MB floppy image.
+ *
+ * @returns IPRT status code.
+ * @param hVfsFile The image. Will be grown to 1.44MB if
+ * necessary.
+ * @param fQuick Whether to quick format the floppy or not.
+ */
+RTDECL(int) RTFsFatVolFormat288(RTVFSFILE hVfsFile, bool fQuick);
+
+
+/**
+ * Opens an EXT2/3/4 file system volume.
+ *
+ * @returns IPRT status code.
+ * @param hVfsFileIn The file or device backing the volume.
+ * @param fMntFlags RTVFSMNT_F_XXX.
+ * @param fExtFlags Reserved, MBZ.
+ * @param phVfs Where to return the virtual file system handle.
+ * @param pErrInfo Where to return additional error information.
+ */
+RTDECL(int) RTFsExtVolOpen(RTVFSFILE hVfsFileIn, uint32_t fMntFlags, uint32_t fExtFlags, PRTVFS phVfs, PRTERRINFO pErrInfo);
+
+
+
+/** @name RTFSISO9660_F_XXX - ISO 9660 mount flags.
+ * @{ */
+/** Do not use the UDF part if present. */
+#define RTFSISO9660_F_NO_UDF RT_BIT_32(0)
+/** Do not use the joliet part. */
+#define RTFSISO9660_F_NO_JOLIET RT_BIT_32(1)
+/** Do not use the rock ridge extensions if present. */
+#define RTFSISO9660_F_NO_ROCK RT_BIT_32(2)
+/** Valid ISO 9660 mount option mask. */
+#define RTFSISO9660_F_VALID_MASK UINT32_C(0x00000007)
+/** Checks if @a a_fNoType is the only acceptable volume type. */
+#define RTFSISO9660_F_IS_ONLY_TYPE(a_fFlags, a_fNoType) \
+ ( ((a_fFlags) & (RTFSISO9660_F_NO_UDF | RTFSISO9660_F_NO_JOLIET | RTFSISO9660_F_NO_ROCK)) \
+ == (~(a_fNoType) & (RTFSISO9660_F_NO_UDF | RTFSISO9660_F_NO_JOLIET | RTFSISO9660_F_NO_ROCK)) )
+/** @} */
+
+/**
+ * Opens an ISO 9660 file system volume.
+ *
+ * @returns IPRT status code.
+ * @param hVfsFileIn The file or device backing the volume.
+ * @param fFlags RTFSISO9660_F_XXX.
+ * @param phVfs Where to return the virtual file system handle.
+ * @param pErrInfo Where to return additional error information.
+ */
+RTDECL(int) RTFsIso9660VolOpen(RTVFSFILE hVfsFileIn, uint32_t fFlags, PRTVFS phVfs, PRTERRINFO pErrInfo);
+
+
+/**
+ * Opens an NTFS file system volume.
+ *
+ * @returns IPRT status code.
+ * @param hVfsFileIn The file or device backing the volume.
+ * @param fMntFlags RTVFSMNT_F_XXX.
+ * @param fNtfsFlags Reserved, MBZ.
+ * @param phVfs Where to return the virtual file system handle.
+ * @param pErrInfo Where to return additional error information.
+ */
+RTDECL(int) RTFsNtfsVolOpen(RTVFSFILE hVfsFileIn, uint32_t fMntFlags, uint32_t fNtfsFlags, PRTVFS phVfs, PRTERRINFO pErrInfo);
+
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_fsvfs_h */
+
diff --git a/include/iprt/ftp.h b/include/iprt/ftp.h
new file mode 100644
index 00000000..8771d1d2
--- /dev/null
+++ b/include/iprt/ftp.h
@@ -0,0 +1,390 @@
+/* $Id: ftp.h $ */
+/** @file
+ * Header file for FTP client / server implementations.
+ */
+
+/*
+ * Copyright (C) 2020-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_ftp_h
+#define IPRT_INCLUDED_ftp_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+#include <iprt/fs.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_ftp RTFtp - FTP server and client.
+ * @ingroup grp_rt
+ * @{
+ */
+
+/** @defgroup grp_rt_ftpserver RTFtpServer - FTP server implementation.
+ * @{
+ */
+
+/** @todo the following three definitions may move the iprt/types.h later. */
+/** FTP server handle. */
+typedef R3PTRTYPE(struct RTFTPSERVERINTERNAL *) RTFTPSERVER;
+/** Pointer to a FTP server handle. */
+typedef RTFTPSERVER *PRTFTPSERVER;
+/** Nil FTP client handle. */
+#define NIL_RTFTPSERVER ((RTFTPSERVER)0)
+
+/** Maximum length (in characters) a command can have (without parameters). */
+#define RTFTPSERVER_MAX_CMD_LEN 8
+
+/**
+ * Enumeration for defining the current server connection mode.
+ */
+typedef enum RTFTPSERVER_CONNECTION_MODE
+{
+ /** Normal mode, nothing to transfer. */
+ RTFTPSERVER_CONNECTION_MODE_NORMAL = 0,
+ /** Server is in passive mode (is listening). */
+ RTFTPSERVER_CONNECTION_MODE_PASSIVE,
+ /** Server connects via port to the client. */
+ RTFTPSERVER_CONNECTION_MODE_MODE_PORT,
+ /** The usual 32-bit hack. */
+ RTFTPSERVER_CONNECTION_MODE_32BIT_HACK = 0x7fffffff
+} RTFTPSERVER_CONNECTION_MODE;
+
+/**
+ * Enumeration for defining the data transfer mode.
+ */
+typedef enum RTFTPSERVER_TRANSFER_MODE
+{
+ /** Default if nothing else is set. */
+ RTFTPSERVER_TRANSFER_MODE_STREAM = 0,
+ RTFTPSERVER_TRANSFER_MODE_BLOCK,
+ RTFTPSERVER_TRANSFER_MODE_COMPRESSED,
+ /** The usual 32-bit hack. */
+ RTFTPSERVER_DATA_MODE_32BIT_HACK = 0x7fffffff
+} RTFTPSERVER_DATA_MODE;
+
+/**
+ * Enumeration for defining the data type.
+ */
+typedef enum RTFTPSERVER_DATA_TYPE
+{
+ /** Default if nothing else is set. */
+ RTFTPSERVER_DATA_TYPE_ASCII = 0,
+ RTFTPSERVER_DATA_TYPE_EBCDIC,
+ RTFTPSERVER_DATA_TYPE_IMAGE,
+ RTFTPSERVER_DATA_TYPE_LOCAL,
+ /** The usual 32-bit hack. */
+ RTFTPSERVER_DATA_TYPE_32BIT_HACK = 0x7fffffff
+} RTFTPSERVER_DATA_TYPE;
+
+/**
+ * Enumeration for defining the struct type.
+ */
+typedef enum RTFTPSERVER_STRUCT_TYPE
+{
+ /** Default if nothing else is set. */
+ RTFTPSERVER_STRUCT_TYPE_FILE = 0,
+ RTFTPSERVER_STRUCT_TYPE_RECORD,
+ RTFTPSERVER_STRUCT_TYPE_PAGE,
+ /** The usual 32-bit hack. */
+ RTFTPSERVER_STRUCT_TYPE_32BIT_HACK = 0x7fffffff
+} RTFTPSERVER_STRUCT_TYPE;
+
+/**
+ * Enumeration for FTP server reply codes.
+ *
+ ** @todo Might needs more codes, not complete yet.
+ */
+typedef enum RTFTPSERVER_REPLY
+{
+ /** Invalid reply type, do not use. */
+ RTFTPSERVER_REPLY_INVALID = 0,
+ /** Data connection already open. */
+ RTFTPSERVER_REPLY_DATACONN_ALREADY_OPEN = 125,
+ /** Command okay. */
+ RTFTPSERVER_REPLY_FILE_STS_OK_OPENING_DATA_CONN = 150,
+ /** Command okay. */
+ RTFTPSERVER_REPLY_OKAY = 200,
+ /** Command not implemented, superfluous at this site. */
+ RTFTPSERVER_REPLY_ERROR_CMD_NOT_IMPL_SUPERFLUOUS = 202,
+ /** System status report. */
+ RTFTPSERVER_REPLY_SYSTEM_STATUS = 211,
+ /** Service ready for new user. */
+ RTFTPSERVER_REPLY_READY_FOR_NEW_USER = 220,
+ /** Service is closing control connection. */
+ RTFTPSERVER_REPLY_CLOSING_CTRL_CONN = 221,
+ /** Closing data connection. */
+ RTFTPSERVER_REPLY_CLOSING_DATA_CONN = 226,
+ /** Requested file action okay, completed. */
+ RTFTPSERVER_REPLY_FILE_ACTION_OKAY_COMPLETED = 250,
+ /** "PATHNAME" ok (created / exists). */
+ RTFTPSERVER_REPLY_PATHNAME_OK = 257,
+ /** User logged in, proceed. */
+ RTFTPSERVER_REPLY_LOGGED_IN_PROCEED = 230,
+ /** User name okay, need password. */
+ RTFTPSERVER_REPLY_USERNAME_OKAY_NEED_PASSWORD = 331,
+ /** Service not available, closing control connection. */
+ RTFTPSERVER_REPLY_SVC_NOT_AVAIL_CLOSING_CTRL_CONN = 421,
+ /** Can't open data connection. */
+ RTFTPSERVER_REPLY_CANT_OPEN_DATA_CONN = 425,
+ /** Connection closed; transfer aborted. */
+ RTFTPSERVER_REPLY_CONN_CLOSED_TRANSFER_ABORTED = 426,
+ /** Requested file action not taken. */
+ RTFTPSERVER_REPLY_CONN_REQ_FILE_ACTION_NOT_TAKEN = 450,
+ /** Requested action aborted; local error in processing. */
+ RTFTPSERVER_REPLY_ACTION_ABORTED_LOCAL_ERROR = 451,
+ /** Syntax error, command unrecognized. */
+ RTFTPSERVER_REPLY_ERROR_CMD_NOT_RECOGNIZED = 500,
+ /** Syntax error in parameters or arguments. */
+ RTFTPSERVER_REPLY_ERROR_INVALID_PARAMETERS = 501,
+ /** Command not implemented. */
+ RTFTPSERVER_REPLY_ERROR_CMD_NOT_IMPL = 502,
+ /** Bad sequence of commands. */
+ RTFTPSERVER_REPLY_ERROR_BAD_SEQUENCE = 503,
+ /** Command not implemented for that parameter. */
+ RTFTPSERVER_REPLY_ERROR_CMD_NOT_IMPL_PARAM = 504,
+ /** Not logged in. */
+ RTFTPSERVER_REPLY_NOT_LOGGED_IN = 530,
+ /** Requested action not taken. */
+ RTFTPSERVER_REPLY_REQ_ACTION_NOT_TAKEN = 550,
+ /** The usual 32-bit hack. */
+ RTFTPSERVER_REPLY_32BIT_HACK = 0x7fffffff
+} RTFTPSERVER_REPLY;
+
+/**
+ * Structure for maintaining a FTP server client state.
+ */
+typedef struct RTFTPSERVERCLIENTSTATE
+{
+ /** Authenticated user (name). If NULL, no user has been logged in (yet). */
+ char *pszUser;
+ /** Current working directory.
+ * *Always* relative to the server's root directory (which is only is known to the actual implemenation). */
+ char *pszCWD;
+ /** Number of failed login attempts. */
+ uint8_t cFailedLoginAttempts;
+ /** Timestamp (in ms) of last command issued by the client. */
+ uint64_t tsLastCmdMs;
+ /** Current set data type. */
+ RTFTPSERVER_DATA_TYPE enmDataType;
+ /** Current set struct type. */
+ RTFTPSERVER_STRUCT_TYPE enmStructType;
+} RTFTPSERVERCLIENTSTATE;
+/** Pointer to a FTP server client state. */
+typedef RTFTPSERVERCLIENTSTATE *PRTFTPSERVERCLIENTSTATE;
+
+/**
+ * Structure for storing FTP server callback data.
+ */
+typedef struct RTFTPCALLBACKDATA
+{
+ /** Pointer to the client state. */
+ PRTFTPSERVERCLIENTSTATE pClient;
+ /** Saved user pointer. */
+ void *pvUser;
+ /** Size (in bytes) of data at user pointer. */
+ size_t cbUser;
+} RTFTPCALLBACKDATA;
+/** Pointer to FTP server callback data. */
+typedef RTFTPCALLBACKDATA *PRTFTPCALLBACKDATA;
+
+/**
+ * Function callback table for the FTP server implementation.
+ *
+ * All callbacks are optional and therefore can be NULL.
+ */
+typedef struct RTFTPSERVERCALLBACKS
+{
+ /**
+ * Callback which gets invoked when a user connected.
+ *
+ * @returns VBox status code.
+ * @param pData Pointer to generic callback data.
+ * @param pcszUser User name.
+ */
+ DECLCALLBACKMEMBER(int, pfnOnUserConnect,(PRTFTPCALLBACKDATA pData, const char *pcszUser));
+ /**
+ * Callback which gets invoked when a user tries to authenticate with a password.
+ *
+ * @returns VBox status code.
+ * @param pData Pointer to generic callback data.
+ * @param pcszUser User name to authenticate.
+ * @param pcszPassword Password to authenticate with.
+ */
+ DECLCALLBACKMEMBER(int, pfnOnUserAuthenticate,(PRTFTPCALLBACKDATA pData, const char *pcszUser, const char *pcszPassword));
+ /**
+ * Callback which gets invoked when a user disconnected.
+ *
+ * @returns VBox status code.
+ * @param pData Pointer to generic callback data.
+ * @param pcszUser User name which disconnected.
+ */
+ DECLCALLBACKMEMBER(int, pfnOnUserDisconnect,(PRTFTPCALLBACKDATA pData, const char *pcszUser));
+ /**
+ * Callback which gets invoked when the client wants to start reading or writing a file.
+ *
+ * @returns VBox status code.
+ * @param pData Pointer to generic callback data.
+ * @param pcsszPath Relative path (to root directory) of file to open.
+ * @param fMode File mode to use (IPRT stlye).
+ * @param ppvHandle Opaque file handle only known to the callback implementation.
+ */
+ DECLCALLBACKMEMBER(int, pfnOnFileOpen,(PRTFTPCALLBACKDATA pData, const char *pcszPath, uint32_t fMode, void **ppvHandle));
+ /**
+ * Callback which gets invoked when the client wants to read from a file.
+ *
+ * @returns VBox status code.
+ * @param pData Pointer to generic callback data.
+ * @param pvHandle Opaque file handle only known to the callback implementation.
+ * @param pvBuf Where to store the read file data.
+ * @param cbToRead How much (in bytes) to read. Must at least supply the size of pvBuf.
+ * @param pcbRead How much (in bytes) was read. Optional.
+ */
+ DECLCALLBACKMEMBER(int, pfnOnFileRead,(PRTFTPCALLBACKDATA pData, void *pvHandle, void *pvBuf, size_t cbToRead, size_t *pcbRead));
+ /**
+ * Callback which gets invoked when the client is done reading from or writing to a file.
+ *
+ * @returns VBox status code.
+ * @param pData Pointer to generic callback data.
+ * @param ppvHandle Opaque file handle only known to the callback implementation.
+ */
+ DECLCALLBACKMEMBER(int, pfnOnFileClose,(PRTFTPCALLBACKDATA pData, void *pvHandle));
+ /**
+ * Callback which gets invoked when the client wants to retrieve the size of a specific file.
+ *
+ * @returns VBox status code.
+ * @param pData Pointer to generic callback data.
+ * @param pcszPath Relative path (to root directory) of file to retrieve size for.
+ * @param puSize Where to store the file size on success.
+ */
+ DECLCALLBACKMEMBER(int, pfnOnFileGetSize,(PRTFTPCALLBACKDATA pData, const char *pcszPath, uint64_t *puSize));
+ /**
+ * Callback which gets invoked when the client wants to retrieve information about a file.
+ *
+ * @param pData Pointer to generic callback data.
+ * @param pcszPath Relative path (to root directory) of file / directory to "stat". Optional.
+ * If NULL, the current directory will be used.
+ * @param pFsObjInfo Where to return the RTFSOBJINFO data on success. Optional.
+ * @returns VBox status code.
+ */
+ DECLCALLBACKMEMBER(int, pfnOnFileStat,(PRTFTPCALLBACKDATA pData, const char *pcszPath, PRTFSOBJINFO pFsObjInfo));
+ /**
+ * Callback which gets invoked when setting the current working directory.
+ *
+ * @returns VBox status code.
+ * @param pData Pointer to generic callback data.
+ * @param pcszCWD Current working directory to set.
+ */
+ DECLCALLBACKMEMBER(int, pfnOnPathSetCurrent,(PRTFTPCALLBACKDATA pData, const char *pcszCWD));
+ /**
+ * Callback which gets invoked when a client wants to retrieve the current working directory.
+ *
+ * @returns VBox status code.
+ * @param pData Pointer to generic callback data.
+ * @param pszPWD Where to store the current working directory.
+ * @param cbPWD Size of buffer in bytes.
+ */
+ DECLCALLBACKMEMBER(int, pfnOnPathGetCurrent,(PRTFTPCALLBACKDATA pData, char *pszPWD, size_t cbPWD));
+ /**
+ * Callback which gets invoked when the client wants to move up a directory (relative to the current working directory).
+ *
+ * @returns VBox status code.
+ * @param pData Pointer to generic callback data.
+ */
+ DECLCALLBACKMEMBER(int, pfnOnPathUp,(PRTFTPCALLBACKDATA pData));
+ /**
+ * Callback which gets invoked when the server wants to open a directory for reading.
+ *
+ * @returns VBox status code. VERR_NO_MORE_FILES if listing is complete.
+ * @param pData Pointer to generic callback data.
+ * @param pcszPath Relative path (to root directory) of file / directory to list. Optional.
+ * If NULL, the current directory will be listed.
+ * @param ppvHandle Where to return the opaque directory handle.
+ */
+ DECLCALLBACKMEMBER(int, pfnOnDirOpen,(PRTFTPCALLBACKDATA pData, const char *pcszPath, void **ppvHandle));
+ /**
+ * Callback which gets invoked when the server wants to close a directory handle.
+ *
+ * @returns VBox status code. VERR_NO_MORE_FILES if listing is complete.
+ * @param pData Pointer to generic callback data.
+ * @param pvHandle Directory handle to close.
+ */
+ DECLCALLBACKMEMBER(int, pfnOnDirClose,(PRTFTPCALLBACKDATA pData, void *pvHandle));
+ /**
+ * Callback which gets invoked when the server wants to read the next directory entry.
+ *
+ * @returns VBox status code. VERR_NO_MORE_FILES if listing is complete.
+ * @param pData Pointer to generic callback data.
+ * @param pvHandle Directory handle to use for reading.
+ * @param pInfo Where to store the FS object information.
+ * @param ppszEntry Where to return the allocated string of the entry name.
+ * @param ppszOwner Where to return the allocated string of the owner.
+ * @param ppszGroup Where to return the allocated string of the group.
+ * @param ppszTarget Where to return the allocated string of the target (if a link). Currently unused.
+ */
+ DECLCALLBACKMEMBER(int, pfnOnDirRead,(PRTFTPCALLBACKDATA pData, void *pvHandle, char **ppszEntry,
+ PRTFSOBJINFO pInfo, char **ppszOwner, char **ppszGroup, char **ppszTarget));
+} RTFTPSERVERCALLBACKS;
+/** Pointer to a FTP server callback data table. */
+typedef RTFTPSERVERCALLBACKS *PRTFTPSERVERCALLBACKS;
+
+/**
+ * Creates a FTP server instance.
+ *
+ * @returns IPRT status code.
+ * @param phFTPServer Where to store the FTP server handle.
+ * @param pcszAddress The address for creating a listening socket.
+ * If NULL or empty string the server is bound to all interfaces.
+ * @param uPort The port for creating a listening socket.
+ * @param pCallbacks Callback table to use.
+ * @param pvUser Pointer to user-specific data. Optional.
+ * @param cbUser Size of user-specific data. Optional.
+ */
+RTR3DECL(int) RTFtpServerCreate(PRTFTPSERVER phFTPServer, const char *pcszAddress, uint16_t uPort,
+ PRTFTPSERVERCALLBACKS pCallbacks, void *pvUser, size_t cbUser);
+
+/**
+ * Destroys a FTP server instance.
+ *
+ * @returns IPRT status code.
+ * @param hFTPServer Handle to the FTP server handle.
+ */
+RTR3DECL(int) RTFtpServerDestroy(RTFTPSERVER hFTPServer);
+
+/** @} */
+
+/** @} */
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_ftp_h */
+
diff --git a/include/iprt/fuzz.h b/include/iprt/fuzz.h
new file mode 100644
index 00000000..5ad6f397
--- /dev/null
+++ b/include/iprt/fuzz.h
@@ -0,0 +1,971 @@
+/** @file
+ * IPRT - Fuzzing framework
+ */
+
+/*
+ * Copyright (C) 2018-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_fuzz_h
+#define IPRT_INCLUDED_fuzz_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cdefs.h>
+#include <iprt/process.h>
+#include <iprt/types.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_fuzz RTFuzz - Data fuzzing framework
+ * @ingroup grp_rt
+ * @sa grp_rt_test
+ * @{
+ */
+
+/** A fuzzer context handle. */
+typedef struct RTFUZZCTXINT *RTFUZZCTX;
+/** Pointer to a fuzzer context handle. */
+typedef RTFUZZCTX *PRTFUZZCTX;
+/** NIL fuzzer context handle. */
+#define NIL_RTFUZZCTX ((RTFUZZCTX)~(uintptr_t)0)
+/** A fuzzer input handle. */
+typedef struct RTFUZZINPUTINT *RTFUZZINPUT;
+/** Pointer to a fuzzer input handle. */
+typedef RTFUZZINPUT *PRTFUZZINPUT;
+/** NIL fuzzer input handle. */
+#define NIL_RTFUZZINPUT ((RTFUZZINPUT)~(uintptr_t)0)
+
+
+/** A fuzzer config handle. */
+typedef struct RTFUZZCFGINT *RTFUZZCFG;
+/** Pointer to a fuzzer config handle. */
+typedef RTFUZZCFG *PRTFUZZCFG;
+/** NIL fuzzer config handle. */
+#define NIL_RTFUZZCFG ((RTFUZZCFG)~(uintptr_t)0)
+
+
+/** A fuzzer target recorder handler. */
+typedef struct RTFUZZTGTRECINT *RTFUZZTGTREC;
+/** Pointer to a fuzzer target recorder handle. */
+typedef RTFUZZTGTREC *PRTFUZZTGTREC;
+/** NIL fuzzer target recorder handle. */
+#define NIL_RTFUZZTGTREC ((RTFUZZTGTREC)~(uintptr_t)0)
+/** A fuzzed target state handle. */
+typedef struct RTFUZZTGTSTATEINT *RTFUZZTGTSTATE;
+/** Pointer to a fuzzed target state handle. */
+typedef RTFUZZTGTSTATE *PRTFUZZTGTSTATE;
+/** NIL fuzzed target state handle. */
+#define NIL_RTFUZZTGTSTATE ((RTFUZZTGTSTATE)~(uintptr_t)0)
+
+
+/** Fuzzing observer handle. */
+typedef struct RTFUZZOBSINT *RTFUZZOBS;
+/** Pointer to a fuzzing observer handle. */
+typedef RTFUZZOBS *PRTFUZZOBS;
+/** NIL fuzzing observer handle. */
+#define NIL_RTFUZZOBS ((RTFUZZOBS)~(uintptr_t)0)
+
+
+/**
+ * Fuzzing context type.
+ */
+typedef enum RTFUZZCTXTYPE
+{
+ /** Invalid type. */
+ RTFUZZCTXTYPE_INVALID = 0,
+ /** Original input data is a single binary large object (BLOB), from a file or similar. */
+ RTFUZZCTXTYPE_BLOB,
+ /** Original input data is from a data stream like a network connection. */
+ RTFUZZCTXTYPE_STREAM,
+ /** 32bit hack. */
+ RTFUZZCTXTYPE_32BIT_HACK = 0x7fffffff
+} RTFUZZCTXTYPE;
+
+
+/**
+ * Fuzzing context statistics.
+ */
+typedef struct RTFUZZCTXSTATS
+{
+ /** Amount of memory currently allocated. */
+ size_t cbMemory;
+ /** Number of mutations accumulated in the corpus. */
+ uint64_t cMutations;
+} RTFUZZCTXSTATS;
+/** Pointer to fuzzing context statistics. */
+typedef RTFUZZCTXSTATS *PRTFUZZCTXSTATS;
+
+
+/** @name RTFUZZCTX_F_XXX - Flags for RTFuzzCtxCfgSetBehavioralFlags
+ * @{ */
+/** Adds all generated inputs automatically to the input corpus for the owning context. */
+#define RTFUZZCTX_F_BEHAVIORAL_ADD_INPUT_AUTOMATICALLY_TO_CORPUS RT_BIT_32(0)
+/** All valid behavioral modification flags. */
+#define RTFUZZCTX_F_BEHAVIORAL_VALID (RTFUZZCTX_F_BEHAVIORAL_ADD_INPUT_AUTOMATICALLY_TO_CORPUS)
+/** @} */
+
+
+/** @name RTFUZZOBS_SANITIZER_F_XXX - Flags for RTFuzzObsSetTestBinarySanitizers().
+ * @{ */
+/** ASAN is compiled and enabled (observer needs to configure to abort on error to catch memory errors). */
+#define RTFUZZOBS_SANITIZER_F_ASAN UINT32_C(0x00000001)
+/** A converage sanitizer is compiled in which can be used to produce coverage reports aiding in the
+ * fuzzing process. */
+#define RTFUZZOBS_SANITIZER_F_SANCOV UINT32_C(0x00000002)
+/** @} */
+
+
+/** @name RTFUZZTGT_REC_STATE_F_XXX - Flags for RTFuzzTgtRecorderCreate().
+ * @{ */
+/** The output from stdout is used to compare states. */
+#define RTFUZZTGT_REC_STATE_F_STDOUT RT_BIT_32(0)
+/** The output from stderr is used to compare states. */
+#define RTFUZZTGT_REC_STATE_F_STDERR RT_BIT_32(1)
+/** The process status is used to compare states. */
+#define RTFUZZTGT_REC_STATE_F_PROCSTATUS RT_BIT_32(2)
+/** The coverage report is used to compare states. */
+#define RTFUZZTGT_REC_STATE_F_SANCOV RT_BIT_32(3)
+/** Mask of all valid flags. */
+#define RTFUZZTGT_REC_STATE_F_VALID UINT32_C(0x0000000f)
+/** @} */
+
+
+/** @name RTFUZZCFG_IMPORT_F_XXX - Flags for RTFuzzCfgImport().
+ * @{ */
+/** Default flags. */
+#define RTFUZZCFG_IMPORT_F_DEFAULT 0
+/** Adds only the inputs and doesn't set any glboal configuration flags of the fuzzing context. */
+#define RTFUZZCFG_IMPORT_F_ONLY_INPUT RT_BIT_32(0)
+/** Mask of all valid flags. */
+#define RTFUZZCFG_IMPORT_F_VALID UINT32_C(0x00000001)
+/** @} */
+
+
+/**
+ * Fuzzing context state export callback.
+ *
+ * @returns IPRT status code.
+ * @param hFuzzCtx Handle of the fuzzing context.
+ * @param pvBuf The data to write.
+ * @param cbWrite Number of bytes to write.
+ * @param pvUser Opaque user data passed in RTFuzzCtxStateExport().
+ */
+typedef DECLCALLBACKTYPE(int, FNRTFUZZCTXEXPORT,(RTFUZZCTX hFuzzCtx, const void *pvBuf, size_t cbWrite, void *pvUser));
+/** Pointer to a fuzzing context state export callback. */
+typedef FNRTFUZZCTXEXPORT *PFNRTFUZZCTXEXPORT;
+
+/**
+ * Fuzzing context state import callback.
+ *
+ * @returns IPRT status code.
+ * @param hFuzzCtx Handle of the fuzzing context.
+ * @param pvBuf Where to store the read data.
+ * @param cbRead Number of bytes to read.
+ * @param pcbRead Where to store the amount of data written, optional.
+ * @param pvUser Opaque user data passed in RTFuzzCtxCreateFromState().
+ */
+typedef DECLCALLBACKTYPE(int, FNRTFUZZCTXIMPORT,(RTFUZZCTX hFuzzCtx, void *pvBuf, size_t cbRead, size_t *pcbRead, void *pvUser));
+/** Pointer to a fuzzing context state export callback. */
+typedef FNRTFUZZCTXIMPORT *PFNRTFUZZCTXIMPORT;
+
+
+/**
+ * Creates a new fuzzing context.
+ *
+ * @returns IPRT status code.
+ * @param phFuzzCtx Where to store the handle to the fuzzing context on success.
+ * @param enmType Fuzzing context data type.
+ */
+RTDECL(int) RTFuzzCtxCreate(PRTFUZZCTX phFuzzCtx, RTFUZZCTXTYPE enmType);
+
+/**
+ * Creates a new fuzzing context from the given state.
+ *
+ * @returns IPRT status code.
+ * @param phFuzzCtx Where to store the handle to the fuzzing context on success.
+ * @param pfnImport State import callback.
+ * @param pvUser Opaque user data to pass to the callback.
+ */
+RTDECL(int) RTFuzzCtxCreateFromState(PRTFUZZCTX phFuzzCtx, PFNRTFUZZCTXIMPORT pfnImport, void *pvUser);
+
+/**
+ * Creates a new fuzzing context loading the state from the given memory buffer.
+ *
+ * @returns IPRT status code.
+ * @param phFuzzCtx Where to store the handle to the fuzzing context on success.
+ * @param pvState Pointer to the memory containing the state.
+ * @param cbState Size of the state buffer.
+ */
+RTDECL(int) RTFuzzCtxCreateFromStateMem(PRTFUZZCTX phFuzzCtx, const void *pvState, size_t cbState);
+
+/**
+ * Creates a new fuzzing context loading the state from the given file.
+ *
+ * @returns IPRT status code.
+ * @param phFuzzCtx Where to store the handle to the fuzzing context on success.
+ * @param pszFilename File to load the fuzzing context from.
+ */
+RTDECL(int) RTFuzzCtxCreateFromStateFile(PRTFUZZCTX phFuzzCtx, const char *pszFilename);
+
+/**
+ * Retains a reference to the given fuzzing context.
+ *
+ * @returns New reference count on success.
+ * @param hFuzzCtx Handle of the fuzzing context.
+ */
+RTDECL(uint32_t) RTFuzzCtxRetain(RTFUZZCTX hFuzzCtx);
+
+/**
+ * Releases a reference from the given fuzzing context, destroying it when reaching 0.
+ *
+ * @returns New reference count on success, 0 if the fuzzing context got destroyed.
+ * @param hFuzzCtx Handle of the fuzzing context.
+ */
+RTDECL(uint32_t) RTFuzzCtxRelease(RTFUZZCTX hFuzzCtx);
+
+/**
+ * Queries statistics about the given fuzzing context.
+ *
+ * @returns IPRT status code.
+ * @param hFuzzCtx Handle of the fuzzing context.
+ * @param pStats Where to store the stats on success.
+ */
+RTDECL(int) RTFuzzCtxQueryStats(RTFUZZCTX hFuzzCtx, PRTFUZZCTXSTATS pStats);
+
+/**
+ * Exports the given fuzzing context state.
+ *
+ * @returns IPRT statuse code
+ * @param hFuzzCtx The fuzzing context to export.
+ * @param pfnExport Export callback.
+ * @param pvUser Opaque user data to pass to the callback.
+ */
+RTDECL(int) RTFuzzCtxStateExport(RTFUZZCTX hFuzzCtx, PFNRTFUZZCTXEXPORT pfnExport, void *pvUser);
+
+/**
+ * Exports the given fuzzing context state to memory allocating the buffer.
+ *
+ * @returns IPRT status code.
+ * @param hFuzzCtx The fuzzing context to export.
+ * @param ppvState Where to store the pointer to the memory containing state on success.
+ * Free with RTMemFree().
+ * @param pcbState Where to store the size of the state in bytes.
+ */
+RTDECL(int) RTFuzzCtxStateExportToMem(RTFUZZCTX hFuzzCtx, void **ppvState, size_t *pcbState);
+
+/**
+ * Exports the given fuzzing context state to the given file.
+ *
+ * @returns IPRT status code.
+ * @param hFuzzCtx The fuzzing context to export.
+ * @param pszFilename The file to save the state to.
+ */
+RTDECL(int) RTFuzzCtxStateExportToFile(RTFUZZCTX hFuzzCtx, const char *pszFilename);
+
+/**
+ * Adds a new seed to the input corpus of the given fuzzing context.
+ *
+ * @returns IPRT status code.
+ * @param hFuzzCtx The fuzzing context handle.
+ * @param pvInput The pointer to the input buffer.
+ * @param cbInput Size of the input buffer.
+ */
+RTDECL(int) RTFuzzCtxCorpusInputAdd(RTFUZZCTX hFuzzCtx, const void *pvInput, size_t cbInput);
+
+/**
+ * Adds a new seed to the input corpus of the given fuzzing context - extended version.
+ *
+ * @returns IPRT status code.
+ * @param hFuzzCtx The fuzzing context handle.
+ * @param pvInput The pointer to the input buffer.
+ * @param cbInput Size of the input buffer.
+ * @param offMutStart Start offset at which a mutation can happen.
+ * @param cbMutRange Size of the range in bytes where a mutation can happen,
+ * use UINT64_MAX to allow mutations till the end of the input.
+ */
+RTDECL(int) RTFuzzCtxCorpusInputAddEx(RTFUZZCTX hFuzzCtx, const void *pvInput, size_t cbInput,
+ uint64_t offMutStart, uint64_t cbMutRange);
+
+/**
+ * Adds a new seed to the input corpus of the given fuzzing context from the given file.
+ *
+ * @returns IPRT status code.
+ * @param hFuzzCtx The fuzzing context handle.
+ * @param pszFilename The filename to load the seed from.
+ */
+RTDECL(int) RTFuzzCtxCorpusInputAddFromFile(RTFUZZCTX hFuzzCtx, const char *pszFilename);
+
+/**
+ * Adds a new seed to the input corpus of the given fuzzing context from the given file - extended version.
+ *
+ * @returns IPRT status code.
+ * @param hFuzzCtx The fuzzing context handle.
+ * @param pszFilename The filename to load the seed from.
+ * @param offMutStart Start offset at which a mutation can happen.
+ * @param cbMutRange Size of the range in bytes where a mutation can happen,
+ * use UINT64_MAX to allow mutations till the end of the input.
+ */
+RTDECL(int) RTFuzzCtxCorpusInputAddFromFileEx(RTFUZZCTX hFuzzCtx, const char *pszFilename,
+ uint64_t offMutStart, uint64_t cbMutRange);
+
+/**
+ * Adds a new seed to the input corpus of the given fuzzing context from the given VFS file.
+ *
+ * @returns IPRT status code.
+ * @param hFuzzCtx The fuzzing context handle.
+ * @param hVfsFile The VFS file handle to load the seed from.
+ */
+RTDECL(int) RTFuzzCtxCorpusInputAddFromVfsFile(RTFUZZCTX hFuzzCtx, RTVFSFILE hVfsFile);
+
+/**
+ * Adds a new seed to the input corpus of the given fuzzing context from the given VFS file - extended version.
+ *
+ * @returns IPRT status code.
+ * @param hFuzzCtx The fuzzing context handle.
+ * @param hVfsFile The VFS file handle to load the seed from.
+ * @param offMutStart Start offset at which a mutation can happen.
+ * @param cbMutRange Size of the range in bytes where a mutation can happen,
+ * use UINT64_MAX to allow mutations till the end of the input.
+ */
+RTDECL(int) RTFuzzCtxCorpusInputAddFromVfsFileEx(RTFUZZCTX hFuzzCtx, RTVFSFILE hVfsFile,
+ uint64_t offMutStart, uint64_t cbMutRange);
+
+/**
+ * Adds a new seed to the input corpus of the given fuzzing context from the given VFS I/O stream.
+ *
+ * @returns IPRT status code.
+ * @param hFuzzCtx The fuzzing context handle.
+ * @param hVfsIos The VFS I/O stream handle to load the seed from.
+ */
+RTDECL(int) RTFuzzCtxCorpusInputAddFromVfsIoStrm(RTFUZZCTX hFuzzCtx, RTVFSIOSTREAM hVfsIos);
+
+/**
+ * Adds a new seed to the input corpus of the given fuzzing context from the given VFS I/O stream - extended version.
+ *
+ * @returns IPRT status code.
+ * @param hFuzzCtx The fuzzing context handle.
+ * @param hVfsIos The VFS I/O stream handle to load the seed from.
+ * @param offMutStart Start offset at which a mutation can happen.
+ * @param cbMutRange Size of the range in bytes where a mutation can happen,
+ * use UINT64_MAX to allow mutations till the end of the input.
+ */
+RTDECL(int) RTFuzzCtxCorpusInputAddFromVfsIoStrmEx(RTFUZZCTX hFuzzCtx, RTVFSIOSTREAM hVfsIos,
+ uint64_t offMutStart, uint64_t cbMutRange);
+
+/**
+ * Adds new seeds to the input corpus of the given fuzzing context from the given directory.
+ *
+ * Will only process regular files, i.e. ignores directories, symbolic links, devices, fifos
+ * and such.
+ *
+ * @returns IPRT status code.
+ * @param hFuzzCtx The fuzzing context handle.
+ * @param pszDirPath The directory to load seeds from.
+ */
+RTDECL(int) RTFuzzCtxCorpusInputAddFromDirPath(RTFUZZCTX hFuzzCtx, const char *pszDirPath);
+
+/**
+ * Restricts the maximum input size to generate by the fuzzing context.
+ *
+ * @returns IPRT status code
+ * @param hFuzzCtx The fuzzing context handle.
+ * @param cbMax Maximum input size in bytes.
+ */
+RTDECL(int) RTFuzzCtxCfgSetInputSeedMaximum(RTFUZZCTX hFuzzCtx, size_t cbMax);
+
+/**
+ * Returns the maximum input size of the given fuzzing context.
+ *
+ * @returns Maximum input size generated in bytes.
+ * @param hFuzzCtx The fuzzing context handle.
+ */
+RTDECL(size_t) RTFuzzCtxCfgGetInputSeedMaximum(RTFUZZCTX hFuzzCtx);
+
+/**
+ * Sets flags controlling the behavior of the fuzzing context.
+ *
+ * @returns IPRT status code.
+ * @param hFuzzCtx The fuzzing context handle.
+ * @param fFlags Flags controlling the fuzzing context, RTFUZZCTX_F_XXX.
+ */
+RTDECL(int) RTFuzzCtxCfgSetBehavioralFlags(RTFUZZCTX hFuzzCtx, uint32_t fFlags);
+
+/**
+ * Returns the current set behavioral flags for the given fuzzing context.
+ *
+ * @returns Behavioral flags of the given fuzzing context.
+ * @param hFuzzCtx The fuzzing context handle.
+ */
+RTDECL(uint32_t) RTFuzzCfgGetBehavioralFlags(RTFUZZCTX hFuzzCtx);
+
+/**
+ * Sets the temporary directory used by the fuzzing context.
+ *
+ * @returns IPRT status code.
+ * @param hFuzzCtx The fuzzing context handle.
+ * @param pszPathTmp The directory for the temporary state.
+ */
+RTDECL(int) RTFuzzCtxCfgSetTmpDirectory(RTFUZZCTX hFuzzCtx, const char *pszPathTmp);
+
+/**
+ * Returns the current temporary directory.
+ *
+ * @returns Current temporary directory.
+ * @param hFuzzCtx The fuzzing context handle.
+ */
+RTDECL(const char *) RTFuzzCtxCfgGetTmpDirectory(RTFUZZCTX hFuzzCtx);
+
+/**
+ * Sets the range in which a particular input can get mutated.
+ *
+ * @returns IPRT status code.
+ * @param hFuzzCtx The fuzzing context handle.
+ * @param offStart Start offset at which a mutation can happen.
+ * @param cbRange Size of the range in bytes where a mutation can happen,
+ * use UINT64_MAX to allow mutations till the end of the input.
+ */
+RTDECL(int) RTFuzzCtxCfgSetMutationRange(RTFUZZCTX hFuzzCtx, uint64_t offStart, uint64_t cbRange);
+
+/**
+ * Reseeds the PRNG of the given fuzzing context.
+ *
+ * @returns IPRT status code.
+ * @param hFuzzCtx The fuzzing context handle.
+ * @param uSeed The new seed.
+ */
+RTDECL(int) RTFuzzCtxReseed(RTFUZZCTX hFuzzCtx, uint64_t uSeed);
+
+/**
+ * Generates a new input from the given fuzzing context and returns it.
+ *
+ * @returns IPRT status code.
+ * @param hFuzzCtx The fuzzing context handle.
+ * @param phFuzzInput Where to store the handle to the fuzzed input on success.
+ */
+RTDECL(int) RTFuzzCtxInputGenerate(RTFUZZCTX hFuzzCtx, PRTFUZZINPUT phFuzzInput);
+
+
+/**
+ * Retains a reference to the given fuzzing input handle.
+ *
+ * @returns New reference count on success.
+ * @param hFuzzInput The fuzzing input handle.
+ */
+RTDECL(uint32_t) RTFuzzInputRetain(RTFUZZINPUT hFuzzInput);
+
+/**
+ * Releases a reference from the given fuzzing input handle, destroying it when reaching 0.
+ *
+ * @returns New reference count on success, 0 if the fuzzing input got destroyed.
+ * @param hFuzzInput The fuzzing input handle.
+ */
+RTDECL(uint32_t) RTFuzzInputRelease(RTFUZZINPUT hFuzzInput);
+
+/**
+ * Queries the data pointer and size of the given fuzzed input blob.
+ *
+ * @returns IPRT status code
+ * @param hFuzzInput The fuzzing input handle.
+ * @param ppv Where to store the pointer to the input data on success.
+ * @param pcb Where to store the size of the input data on success.
+ */
+RTDECL(int) RTFuzzInputQueryBlobData(RTFUZZINPUT hFuzzInput, void **ppv, size_t *pcb);
+
+/**
+ * Processes the given data stream for a streamed fuzzing context.
+ *
+ * @returns IPRT status code.
+ * @param hFuzzInput The fuzzing input handle.
+ * @param pvBuf The data buffer.
+ * @param cbBuf Size of the buffer.
+ */
+RTDECL(int) RTFuzzInputMutateStreamData(RTFUZZINPUT hFuzzInput, void *pvBuf, size_t cbBuf);
+
+/**
+ * Queries the string of the MD5 digest for the given fuzzed input.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_BUFFER_OVERFLOW if the size of the string buffer is not sufficient.
+ * @param hFuzzInput The fuzzing input handle.
+ * @param pszDigest Where to store the digest string and a closing terminator.
+ * @param cchDigest Size of the string buffer in characters (including the zero terminator).
+ */
+RTDECL(int) RTFuzzInputQueryDigestString(RTFUZZINPUT hFuzzInput, char *pszDigest, size_t cchDigest);
+
+/**
+ * Writes the given fuzzing input to the given file.
+ *
+ * @returns IPRT status code.
+ * @param hFuzzInput The fuzzing input handle.
+ * @param pszFilename The filename to store the input to.
+ */
+RTDECL(int) RTFuzzInputWriteToFile(RTFUZZINPUT hFuzzInput, const char *pszFilename);
+
+/**
+ * Adds the given fuzzed input to the input corpus of the owning context.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_ALREADY_EXISTS if the input exists already.
+ * @param hFuzzInput The fuzzing input handle.
+ */
+RTDECL(int) RTFuzzInputAddToCtxCorpus(RTFUZZINPUT hFuzzInput);
+
+/**
+ * Removes the given fuzzed input from the input corpus of the owning context.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_NOT_FOUND if the input is not part of the corpus.
+ * @param hFuzzInput The fuzzing input handle.
+ */
+RTDECL(int) RTFuzzInputRemoveFromCtxCorpus(RTFUZZINPUT hFuzzInput);
+
+
+/**
+ * Creates a fuzzing config from the given VFS file handle.
+ *
+ * @returns IPRT status code.
+ * @param phFuzzCfg Where to store the handle to the fuzzing config on success.
+ * @param hVfsFile The VFS file to use (retained).
+ * @param pErrInfo Where to store extended error info. Optional.
+ */
+RTDECL(int) RTFuzzCfgCreateFromVfsFile(PRTFUZZCFG phFuzzCfg, RTVFSFILE hVfsFile, PRTERRINFO pErrInfo);
+
+/**
+ * Creates a fuzzing config from the given file path.
+ *
+ * @returns IPRT status code.
+ * @param phFuzzCfg Where to store the handle to the fuzzing config on success.
+ * @param pszFilename Filename to load the config from.
+ * @param pErrInfo Where to store extended error info. Optional.
+ */
+RTDECL(int) RTFuzzCfgCreateFromFile(PRTFUZZCFG phFuzzCfg, const char *pszFilename, PRTERRINFO pErrInfo);
+
+/**
+ * Retains a reference to the given fuzzing config.
+ *
+ * @returns New reference count on success.
+ * @param hFuzzCfg Handle of the fuzzing config.
+ */
+RTDECL(uint32_t) RTFuzzCfgRetain(RTFUZZCFG hFuzzCfg);
+
+/**
+ * Releases a reference from the given fuzzing config, destroying it when reaching 0.
+ *
+ * @returns New reference count on success, 0 if the fuzzing config got destroyed.
+ * @param hFuzzCfg Handle of the fuzzing config.
+ */
+RTDECL(uint32_t) RTFuzzCfgRelease(RTFUZZCFG hFuzzCfg);
+
+/**
+ * Imports the given fuzzing config into a previously created fuzzing context.
+ *
+ * @returns IPRT status code.
+ * @param hFuzzCfg Handle of the fuzzing config.
+ * @param hFuzzCtx Handle of the fuzzing context.
+ * @param fFlags Flags controlling what to import exactly, combination of RTFUZZCFG_IMPORT_F_XXX.
+ */
+RTDECL(int) RTFuzzCfgImport(RTFUZZCFG hFuzzCfg, RTFUZZCTX hFuzzCtx, uint32_t fFlags);
+
+/**
+ * Queries the custom config for the controller of the fuzzing process.
+ *
+ * @returns IPRT status code.
+ * @param hFuzzCfg Handle of the fuzzing config.
+ * @param phVfsFile Where to store the handle of the VFS file containing the custom config.
+ */
+RTDECL(int) RTFuzzCfgQueryCustomCfg(RTFUZZCFG hFuzzCfg, PRTVFSFILE phVfsFile);
+
+
+/**
+ * Creates a new fuzzed target recorder.
+ *
+ * @returns IPRT status code.
+ * @param phFuzzTgtRec Where to store the handle to the fuzzed target recorder on success.
+ * @param fRecFlags What to take into account when checking for equal states.
+ * Combination of RTFUZZTGT_REC_STATE_F_*
+ */
+RTDECL(int) RTFuzzTgtRecorderCreate(PRTFUZZTGTREC phFuzzTgtRec, uint32_t fRecFlags);
+
+/**
+ * Retains a reference to the given fuzzed target recorder handle.
+ *
+ * @returns New reference count on success.
+ * @param hFuzzTgtRec The fuzzed target recorder handle.
+ */
+RTDECL(uint32_t) RTFuzzTgtRecorderRetain(RTFUZZTGTREC hFuzzTgtRec);
+
+/**
+ * Releases a reference from the given fuzzed target recorder handle, destroying it when reaching 0.
+ *
+ * @returns New reference count on success, 0 if the fuzzed target recorder got destroyed.
+ * @param hFuzzTgtRec The fuzzed target recorder handle.
+ */
+RTDECL(uint32_t) RTFuzzTgtRecorderRelease(RTFUZZTGTREC hFuzzTgtRec);
+
+/**
+ * Creates a new empty fuzzed target state.
+ *
+ * @returns IPRT status code.
+ * @param hFuzzTgtRec The fuzzed target recorder handle.
+ * @param phFuzzTgtState Where to store the handle to the fuzzed target state on success.
+ */
+RTDECL(int) RTFuzzTgtRecorderCreateNewState(RTFUZZTGTREC hFuzzTgtRec, PRTFUZZTGTSTATE phFuzzTgtState);
+
+/**
+ * Retains a reference to the given fuzzed target state handle.
+ *
+ * @returns New reference count on success.
+ * @param hFuzzTgtState The fuzzed target state handle.
+ */
+RTDECL(uint32_t) RTFuzzTgtStateRetain(RTFUZZTGTSTATE hFuzzTgtState);
+
+/**
+ * Releases a reference from the given fuzzed target state handle, destroying it when reaching 0.
+ *
+ * @returns New reference count on success, 0 if the fuzzed target recorder got destroyed.
+ * @param hFuzzTgtState The fuzzed target state handle.
+ */
+RTDECL(uint32_t) RTFuzzTgtStateRelease(RTFUZZTGTSTATE hFuzzTgtState);
+
+/**
+ * Resets the given fuzzed target state to an empty state (keeping allocated memory).
+ *
+ * @returns IPRT status code.
+ * @param hFuzzTgtState The fuzzed target state handle.
+ *
+ * @note Useful when the state is not added to the recorded set to avoid allocating memory.
+ */
+RTDECL(int) RTFuzzTgtStateReset(RTFUZZTGTSTATE hFuzzTgtState);
+
+/**
+ * Finalizes the given fuzzed target state, making it readonly.
+ *
+ * @returns IPRT status code.
+ * @param hFuzzTgtState The fuzzed target state handle.
+ */
+RTDECL(int) RTFuzzTgtStateFinalize(RTFUZZTGTSTATE hFuzzTgtState);
+
+/**
+ * Adds the given state to the set for the owning target recorder.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_ALREADY_EXISTS if the state is already existing in the recorder set.
+ * @param hFuzzTgtState The fuzzed target state handle.
+ *
+ * @note This also finalizes the target state if not already done.
+ */
+RTDECL(int) RTFuzzTgtStateAddToRecorder(RTFUZZTGTSTATE hFuzzTgtState);
+
+/**
+ * Appends the given stdout output to the given target state.
+ *
+ * @returns IPRT status code.
+ * @param hFuzzTgtState The fuzzed target state handle.
+ * @param pvStdOut Pointer to the stdout data buffer.
+ * @param cbStdOut Size of the stdout data buffer in bytes.
+ */
+RTDECL(int) RTFuzzTgtStateAppendStdoutFromBuf(RTFUZZTGTSTATE hFuzzTgtState, const void *pvStdOut, size_t cbStdOut);
+
+/**
+ * Appends the given stderr output to the given target state.
+ *
+ * @returns IPRT status code.
+ * @param hFuzzTgtState The fuzzed target state handle.
+ * @param pvStdErr Pointer to the stderr data buffer.
+ * @param cbStdErr Size of the stderr data buffer in bytes.
+ */
+RTDECL(int) RTFuzzTgtStateAppendStderrFromBuf(RTFUZZTGTSTATE hFuzzTgtState, const void *pvStdErr, size_t cbStdErr);
+
+/**
+ * Appends the given stdout output to the given target state, reading from the given pipe.
+ *
+ * @returns IPRT status code.
+ * @param hFuzzTgtState The fuzzed target state handle.
+ * @param hPipe The stdout pipe to read the data from.
+ */
+RTDECL(int) RTFuzzTgtStateAppendStdoutFromPipe(RTFUZZTGTSTATE hFuzzTgtState, RTPIPE hPipe);
+
+/**
+ * Appends the given stderr output to the given target state, reading from the given pipe.
+ *
+ * @returns IPRT status code.
+ * @param hFuzzTgtState The fuzzed target state handle.
+ * @param hPipe The stdout pipe to read the data from.
+ */
+RTDECL(int) RTFuzzTgtStateAppendStderrFromPipe(RTFUZZTGTSTATE hFuzzTgtState, RTPIPE hPipe);
+
+/**
+ * Adds the SanCov coverage information from the given file to the given target state.
+ *
+ * @returns IPRT status code.
+ * @param hFuzzTgtState The fuzzed target state handle.
+ * @param pszFilename Filename of the coverage report.
+ */
+RTDECL(int) RTFuzzTgtStateAddSanCovReportFromFile(RTFUZZTGTSTATE hFuzzTgtState, const char *pszFilename);
+
+/**
+ * Adds the given process status to the target state.
+ *
+ * @returns IPRT status code.
+ * @param hFuzzTgtState The fuzzed target state handle.
+ * @param pProcSts The process status to add.
+ */
+RTDECL(int) RTFuzzTgtStateAddProcSts(RTFUZZTGTSTATE hFuzzTgtState, PCRTPROCSTATUS pProcSts);
+
+/**
+ * Dumps the given target state to the given directory.
+ *
+ * @returns IPRT status code.
+ * @param hFuzzTgtState The fuzzed target state handle.
+ * @param pszDirPath The directory to dump to.
+ */
+RTDECL(int) RTFuzzTgtStateDumpToDir(RTFUZZTGTSTATE hFuzzTgtState, const char *pszDirPath);
+
+
+/**
+ * Fuzzed binary input channel.
+ */
+typedef enum RTFUZZOBSINPUTCHAN
+{
+ /** Invalid. */
+ RTFUZZOBSINPUTCHAN_INVALID = 0,
+ /** File input. */
+ RTFUZZOBSINPUTCHAN_FILE,
+ /** Input over stdin. */
+ RTFUZZOBSINPUTCHAN_STDIN,
+ /** The binary is a fuzzing aware client using the
+ * specified protocol over stdin/stdout. */
+ RTFUZZOBSINPUTCHAN_FUZZING_AWARE_CLIENT,
+ /** TCP server. */
+ RTFUZZOBSINPUTCHAN_TCP_SERVER,
+ /** TCP client. */
+ RTFUZZOBSINPUTCHAN_TCP_CLIENT,
+ /** UDP server. */
+ RTFUZZOBSINPUTCHAN_UDP_SERVER,
+ /** UDP client. */
+ RTFUZZOBSINPUTCHAN_UDP_CLIENT,
+ /** 32bit hack. */
+ RTFUZZOBSINPUTCHAN_32BIT_HACK = 0x7fffffff
+} RTFUZZOBSINPUTCHAN;
+
+/**
+ * Fuzzing observer statistics.
+ */
+typedef struct RTFUZZOBSSTATS
+{
+ /** Number of fuzzed inputs per second. */
+ uint32_t cFuzzedInputsPerSec;
+ /** Number of overall fuzzed inputs. */
+ uint32_t cFuzzedInputs;
+ /** Number of observed hangs. */
+ uint32_t cFuzzedInputsHang;
+ /** Number of observed crashes. */
+ uint32_t cFuzzedInputsCrash;
+} RTFUZZOBSSTATS;
+/** Pointer to a fuzzing observer statistics record. */
+typedef RTFUZZOBSSTATS *PRTFUZZOBSSTATS;
+
+/**
+ * Creates a new fuzzing observer.
+ *
+ * @returns IPRT status code.
+ * @param phFuzzObs Where to store the fuzzing observer handle on success.
+ * @param enmType Fuzzing context data type.
+ * @param fTgtRecFlags Flags to pass to the target state recorder, see RTFuzzTgtRecorderCreate().
+ */
+RTDECL(int) RTFuzzObsCreate(PRTFUZZOBS phFuzzObs, RTFUZZCTXTYPE enmType, uint32_t fTgtRecFlags);
+
+/**
+ * Destroys a previously created fuzzing observer.
+ *
+ * @returns IPRT status code.
+ * @param hFuzzObs The fuzzing observer handle.
+ */
+RTDECL(int) RTFuzzObsDestroy(RTFUZZOBS hFuzzObs);
+
+/**
+ * Queries the internal fuzzing context of the given observer.
+ *
+ * @returns IPRT status code.
+ * @param hFuzzObs The fuzzing observer handle.
+ * @param phFuzzCtx Where to store the handle to the fuzzing context on success.
+ *
+ * @note The fuzzing context handle should be released with RTFuzzCtxRelease() when not used anymore.
+ */
+RTDECL(int) RTFuzzObsQueryCtx(RTFUZZOBS hFuzzObs, PRTFUZZCTX phFuzzCtx);
+
+/**
+ * Queries the current statistics for the given fuzzing observer.
+ *
+ * @returns IPRT status code.
+ * @param hFuzzObs The fuzzing observer handle.
+ * @param pStats Where to store the statistics to.
+ */
+RTDECL(int) RTFuzzObsQueryStats(RTFUZZOBS hFuzzObs, PRTFUZZOBSSTATS pStats);
+
+/**
+ * Sets the temp directory for the given fuzzing observer.
+ *
+ * @returns IPRT status code.
+ * @param hFuzzObs The fuzzing observer handle.
+ * @param pszTmp The temp directory path.
+ */
+RTDECL(int) RTFuzzObsSetTmpDirectory(RTFUZZOBS hFuzzObs, const char *pszTmp);
+
+/**
+ * Sets the directory to store results to.
+ *
+ * @returns IPRT status code.
+ * @param hFuzzObs The fuzzing observer handle.
+ * @param pszResults The path to store the results.
+ */
+RTDECL(int) RTFuzzObsSetResultDirectory(RTFUZZOBS hFuzzObs, const char *pszResults);
+
+/**
+ * Sets the binary to run for each fuzzed input.
+ *
+ * @returns IPRT status code.
+ * @param hFuzzObs The fuzzing observer handle.
+ * @param pszBinary The binary path.
+ * @param enmInputChan The input channel to use.
+ */
+RTDECL(int) RTFuzzObsSetTestBinary(RTFUZZOBS hFuzzObs, const char *pszBinary, RTFUZZOBSINPUTCHAN enmInputChan);
+
+/**
+ * Sets additional arguments to run the binary with.
+ *
+ * @returns IPRT status code.
+ * @param hFuzzObs The fuzzing observer handle.
+ * @param papszArgs Pointer to the array of arguments.
+ * @param cArgs Number of arguments.
+ */
+RTDECL(int) RTFuzzObsSetTestBinaryArgs(RTFUZZOBS hFuzzObs, const char * const *papszArgs, unsigned cArgs);
+
+/**
+ * Sets an environment block to run the binary in.
+ *
+ * @returns IPRT status code.
+ * @param hFuzzObs The fuzzing observer handle.
+ * @param hEnv The environment block to set for the test binary.
+ * Use RTENV_DEFAULT for the default process environment or
+ * NULL for an empty environment.
+ *
+ * @note Upon successful return of this function the observer has taken ownership over the
+ * environment block and can alter it in unexpected ways. It also destroys the environment
+ * block when the observer gets destroyed. So don't touch the environment block after
+ * calling this function.
+ */
+RTDECL(int) RTFuzzObsSetTestBinaryEnv(RTFUZZOBS hFuzzObs, RTENV hEnv);
+
+/**
+ * Makes the observer aware of any configured sanitizers for the test binary.
+ *
+ * @returns IPRT status code.
+ * @param hFuzzObs The fuzzing observer handle.
+ * @param fSanitizers Bitmask of compiled and enabled sanitiziers in the
+ * target binary.
+ */
+RTDECL(int) RTFuzzObsSetTestBinarySanitizers(RTFUZZOBS hFuzzObs, uint32_t fSanitizers);
+
+/**
+ * Sets maximum timeout until a process is considered hung and killed.
+ *
+ * @returns IPRT status code.
+ * @param hFuzzObs The fuzzing observer handle.
+ * @param msTimeoutMax The maximum number of milliseconds to wait until the process
+ * is considered hung.
+ */
+RTDECL(int) RTFuzzObsSetTestBinaryTimeout(RTFUZZOBS hFuzzObs, RTMSINTERVAL msTimeoutMax);
+
+/**
+ * Starts fuzzing the set binary.
+ *
+ * @returns IPRT status code.
+ * @param hFuzzObs The fuzzing observer handle.
+ * @param cProcs Number of processes to run simulteanously,
+ * 0 will create as many processes as there are CPUs available.
+ */
+RTDECL(int) RTFuzzObsExecStart(RTFUZZOBS hFuzzObs, uint32_t cProcs);
+
+/**
+ * Stops the fuzzing process.
+ *
+ * @returns IPRT status code.
+ * @param hFuzzObs The fuzzing observer handle.
+ */
+RTDECL(int) RTFuzzObsExecStop(RTFUZZOBS hFuzzObs);
+
+
+/**
+ * A fuzzing master program.
+ *
+ * @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.)
+ */
+RTR3DECL(RTEXITCODE) RTFuzzCmdMaster(unsigned cArgs, char **papszArgs);
+
+
+/**
+ * Client input consumption callback.
+ *
+ * @returns IPRT status code.
+ * @retval VINF_SUCCESS the fuzzed code accepted the input.
+ * @retval VERR_* the client rejected the input while parsing it.
+ * @param pvBuf The buffer containing the input data.
+ * @param cbBuf Size of the buffer in bytes.
+ * @param pvUser Opaque user data.
+ */
+typedef DECLCALLBACKTYPE(int, FNFUZZCLIENTCONSUME,(const void *pvBuf, size_t cbBuf, void *pvUser));
+/** Pointer to a client consumption callback. */
+typedef FNFUZZCLIENTCONSUME *PFNFUZZCLIENTCONSUME;
+
+/**
+ * A fuzzing client program for more efficient fuzzing.
+ *
+ * @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.)
+ * @param pfnConsume Input data consumption callback.
+ * @param pvUser Opaque user data to pass to the callback.
+ */
+RTR3DECL(RTEXITCODE) RTFuzzCmdFuzzingClient(unsigned cArgs, char **papszArgs, PFNFUZZCLIENTCONSUME pfnConsume, void *pvUser);
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_fuzz_h */
+
diff --git a/include/iprt/getopt.h b/include/iprt/getopt.h
new file mode 100644
index 00000000..57a2bbcf
--- /dev/null
+++ b/include/iprt/getopt.h
@@ -0,0 +1,564 @@
+/** @file
+ * IPRT - Command Line Parsing.
+ */
+
+/*
+ * Copyright (C) 2007-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_getopt_h
+#define IPRT_INCLUDED_getopt_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+#include <iprt/errcore.h> /* for VINF_GETOPT_NOT_OPTION */
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_getopt RTGetOpt - Command Line Parsing
+ * @ingroup grp_rt
+ * @{
+ */
+
+/** @name Values for RTGETOPTDEF::fFlags and the fFlags parameter of
+ * RTGetOptFetchValue.
+ *
+ * @remarks When neither of the RTGETOPT_FLAG_HEX, RTGETOPT_FLAG_OCT and RTGETOPT_FLAG_DEC
+ * flags are specified with a integer value format, RTGetOpt will default to
+ * decimal but recognize the 0x prefix when present. RTGetOpt will not look for
+ * for the octal prefix (0).
+ * @{ */
+/** Requires no extra argument.
+ * (Can be assumed to be 0 for ever.) */
+#define RTGETOPT_REQ_NOTHING 0
+/** A value is required or error will be returned. */
+#define RTGETOPT_REQ_STRING 1
+/** The value must be a valid signed 8-bit integer or an error will be returned. */
+#define RTGETOPT_REQ_INT8 2
+/** The value must be a valid unsigned 8-bit integer or an error will be returned. */
+#define RTGETOPT_REQ_UINT8 3
+/** The value must be a valid signed 16-bit integer or an error will be returned. */
+#define RTGETOPT_REQ_INT16 4
+/** The value must be a valid unsigned 16-bit integer or an error will be returned. */
+#define RTGETOPT_REQ_UINT16 5
+/** The value must be a valid signed 32-bit integer or an error will be returned. */
+#define RTGETOPT_REQ_INT32 6
+/** The value must be a valid unsigned 32-bit integer or an error will be returned. */
+#define RTGETOPT_REQ_UINT32 7
+/** The value must be a valid signed 64-bit integer or an error will be returned. */
+#define RTGETOPT_REQ_INT64 8
+/** The value must be a valid unsigned 64-bit integer or an error will be returned. */
+#define RTGETOPT_REQ_UINT64 9
+/** The value must be a valid IPv4 address.
+ * (Not a name, but 4 values in the 0..255 range with dots separating them). */
+#define RTGETOPT_REQ_IPV4ADDR 10
+/** The value must be a valid IPv4 CIDR.
+ * As with RTGETOPT_REQ_IPV4ADDR, no name.
+ */
+#define RTGETOPT_REQ_IPV4CIDR 11
+#if 0
+/* take placers */
+/** The value must be a valid IPv6 addr
+ * @todo: Add types and parsing routines in (iprt/net.h)
+ */
+#define RTGETOPT_REQ_IPV6ADDR 12
+/** The value must be a valid IPv6 CIDR
+ * @todo: Add types and parsing routines in (iprt/net.h)
+ */
+#define RTGETOPT_REQ_IPV6CIDR 13
+#endif
+/** The value must be a valid ethernet MAC address. */
+#define RTGETOPT_REQ_MACADDR 14
+/** The value must be a valid UUID. */
+#define RTGETOPT_REQ_UUID 15
+/** The value must be a string with value as "on" or "off". */
+#define RTGETOPT_REQ_BOOL_ONOFF 16
+/** Boolean option accepting a wide range of typical ways of
+ * expression true and false. */
+#define RTGETOPT_REQ_BOOL 17
+/** The value must two unsigned 32-bit integer values separated by a colon,
+ * slash, pipe or space(s). */
+#define RTGETOPT_REQ_UINT32_PAIR 18
+/** The value must two unsigned 64-bit integer values separated by a colon,
+ * slash, pipe or space(s). */
+#define RTGETOPT_REQ_UINT64_PAIR 19
+/** The value must at least unsigned 32-bit integer value, optionally
+ * followed by a second separated by a colon, slash, pipe or space(s). */
+#define RTGETOPT_REQ_UINT32_OPTIONAL_PAIR 20
+/** The value must at least unsigned 64-bit integer value, optionally
+ * followed by a second separated by a colon, slash, pipe or space(s). */
+#define RTGETOPT_REQ_UINT64_OPTIONAL_PAIR 21
+/** The mask of the valid required types. */
+#define RTGETOPT_REQ_MASK 31
+/** Treat the value as hexadecimal - only applicable with the RTGETOPT_REQ_*INT*. */
+#define RTGETOPT_FLAG_HEX RT_BIT(16)
+/** Treat the value as octal - only applicable with the RTGETOPT_REQ_*INT*. */
+#define RTGETOPT_FLAG_OCT RT_BIT(17)
+/** Treat the value as decimal - only applicable with the RTGETOPT_REQ_*INT*. */
+#define RTGETOPT_FLAG_DEC RT_BIT(18)
+/** The index value is attached to the argument - only valid for long arguments. */
+#define RTGETOPT_FLAG_INDEX RT_BIT(19)
+/** Used with RTGETOPT_FLAG_INDEX, setting index to zero if none given.
+ * (The default is to fail with VERR_GETOPT_INDEX_MISSING.) */
+#define RTGETOPT_FLAG_INDEX_DEF_0 RT_BIT(20)
+/** Used with RTGETOPT_FLAG_INDEX, setting index to one if none given.
+ * (The default is to fail with VERR_GETOPT_INDEX_MISSING.) */
+#define RTGETOPT_FLAG_INDEX_DEF_1 RT_BIT(21)
+/** For simplicity. */
+#define RTGETOPT_FLAG_INDEX_DEF_MASK (RT_BIT(20) | RT_BIT(21))
+/** For simple conversion. */
+#define RTGETOPT_FLAG_INDEX_DEF_SHIFT 20
+/** For use with RTGETOPT_FLAG_INDEX_DEF_0 or RTGETOPT_FLAG_INDEX_DEF_1 to
+ * imply a dash before the index when a digit is specified.
+ * This is for transitioning from options without index to optionally allow
+ * index options, i.e. "--long" defaults to either index 1 or 1 using the above
+ * flags, while "--long-1" explicitly gives the index ("--long-" is not valid).
+ * This flag matches an "-" separating the "--long" string
+ * (RTGETOPTDEFS::pszLong) from the index value. */
+#define RTGETOPT_FLAG_INDEX_DEF_DASH RT_BIT(22)
+/** Treat the long option as case insensitive. */
+#define RTGETOPT_FLAG_ICASE RT_BIT(23)
+/** Mask of valid bits - for validation. */
+#define RTGETOPT_VALID_MASK ( RTGETOPT_REQ_MASK \
+ | RTGETOPT_FLAG_HEX \
+ | RTGETOPT_FLAG_OCT \
+ | RTGETOPT_FLAG_DEC \
+ | RTGETOPT_FLAG_INDEX \
+ | RTGETOPT_FLAG_INDEX_DEF_0 \
+ | RTGETOPT_FLAG_INDEX_DEF_1 \
+ | RTGETOPT_FLAG_INDEX_DEF_DASH \
+ | RTGETOPT_FLAG_ICASE )
+/** @} */
+
+/**
+ * An option definition.
+ */
+typedef struct RTGETOPTDEF
+{
+ /** The long option.
+ * This is optional */
+ const char *pszLong;
+ /** The short option character.
+ * This doesn't have to be a character, it may also be a \#define or enum value if
+ * there isn't any short version of this option. Must be greater than 0. */
+ int iShort;
+ /** The flags (RTGETOPT_*). */
+ unsigned fFlags;
+} RTGETOPTDEF;
+/** Pointer to an option definition. */
+typedef RTGETOPTDEF *PRTGETOPTDEF;
+/** Pointer to an const option definition. */
+typedef const RTGETOPTDEF *PCRTGETOPTDEF;
+
+/**
+ * Option argument union.
+ *
+ * What ends up here depends on argument format in the option definition.
+ */
+typedef union RTGETOPTUNION
+{
+ /** Pointer to the definition on failure or when the option doesn't take an argument.
+ * This can be NULL for some errors. */
+ PCRTGETOPTDEF pDef;
+ /** A RTGETOPT_REQ_STRING option argument. */
+ const char *psz;
+
+ /** A RTGETOPT_REQ_INT8 option argument. */
+ int8_t i8;
+ /** A RTGETOPT_REQ_UINT8 option argument . */
+ uint8_t u8;
+ /** A RTGETOPT_REQ_INT16 option argument. */
+ int16_t i16;
+ /** A RTGETOPT_REQ_UINT16 option argument . */
+ uint16_t u16;
+ /** A RTGETOPT_REQ_INT16 option argument. */
+ int32_t i32;
+ /** A RTGETOPT_REQ_UINT32 option argument . */
+ uint32_t u32;
+ /** A RTGETOPT_REQ_INT64 option argument. */
+ int64_t i64;
+ /** A RTGETOPT_REQ_UINT64 option argument. */
+ uint64_t u64;
+#ifdef IPRT_INCLUDED_net_h
+ /** A RTGETOPT_REQ_IPV4ADDR option argument. */
+ RTNETADDRIPV4 IPv4Addr;
+ /** A RTGETOPT_REQ_IPV4CIDR option argument. */
+ struct
+ {
+ RTNETADDRIPV4 IPv4Network;
+ RTNETADDRIPV4 IPv4Netmask;
+ } CidrIPv4;
+#endif
+ /** A RTGETOPT_REQ_MACADDR option argument. */
+ RTMAC MacAddr;
+ /** A RTGETOPT_REQ_UUID option argument. */
+ RTUUID Uuid;
+ /** A boolean flag. */
+ bool f;
+ /** A RTGETOPT_REQ_UINT32_PAIR or RTGETOPT_REQ_UINT32_OPTIONAL_PAIR option
+ * argument. */
+ struct
+ {
+ uint32_t uFirst;
+ uint32_t uSecond; /**< Set to UINT32_MAX if optional and not present. */
+ } PairU32;
+ /** A RTGETOPT_REQ_UINT64_COLON_PAIR option argument. */
+ struct
+ {
+ uint64_t uFirst;
+ uint64_t uSecond; /**< Set to UINT64_MAX if optional and not present. */
+ } PairU64;
+} RTGETOPTUNION;
+/** Pointer to an option argument union. */
+typedef RTGETOPTUNION *PRTGETOPTUNION;
+/** Pointer to a const option argument union. */
+typedef RTGETOPTUNION const *PCRTGETOPTUNION;
+
+
+/**
+ * RTGetOpt state.
+ */
+typedef struct RTGETOPTSTATE
+{
+ /** The next argument. */
+ int iNext;
+ /** Argument array. */
+ char **argv;
+ /** Number of items in argv. */
+ int argc;
+ /** Option definition array. */
+ PCRTGETOPTDEF paOptions;
+ /** Number of items in paOptions. */
+ size_t cOptions;
+ /** The next short option.
+ * (For parsing ls -latrT4 kind of option lists.) */
+ const char *pszNextShort;
+ /** The option definition which matched. NULL otherwise. */
+ PCRTGETOPTDEF pDef;
+ /** The index of an index option, otherwise UINT32_MAX. */
+ uint32_t uIndex;
+ /** The flags passed to RTGetOptInit. */
+ uint32_t fFlags;
+ /** Number of non-options that we're skipping during a sorted get. The value
+ * INT32_MAX is used to indicate that there are no more options. This is used
+ * to implement '--'. */
+ int32_t cNonOptions;
+
+ /* More members may be added later for dealing with new features. */
+} RTGETOPTSTATE;
+/** Pointer to RTGetOpt state. */
+typedef RTGETOPTSTATE *PRTGETOPTSTATE;
+
+
+/**
+ * Initialize the RTGetOpt state.
+ *
+ * The passed in argument vector may be sorted if fFlags indicates that this is
+ * desired (to be implemented).
+ *
+ * @returns VINF_SUCCESS, VERR_INVALID_PARAMETER or VERR_INVALID_POINTER.
+ * @param pState The state.
+ *
+ * @param argc Argument count, to be copied from what comes in with
+ * main().
+ * @param argv Argument array, to be copied from what comes in with
+ * main(). This may end up being modified by the
+ * option/argument sorting.
+ * @param paOptions Array of RTGETOPTDEF structures, which must specify what
+ * options are understood by the program.
+ * @param cOptions Number of array items passed in with paOptions.
+ * @param iFirst The argument to start with (in argv).
+ * @param fFlags The flags, see RTGETOPTINIT_FLAGS_XXX.
+ */
+RTDECL(int) RTGetOptInit(PRTGETOPTSTATE pState, int argc, char **argv,
+ PCRTGETOPTDEF paOptions, size_t cOptions,
+ int iFirst, uint32_t fFlags);
+
+/** @name RTGetOptInit flags.
+ * @{ */
+/** Sort the arguments so that options comes first, then non-options. */
+#define RTGETOPTINIT_FLAGS_OPTS_FIRST RT_BIT_32(0)
+/** Prevent add the standard version and help options:
+ * - "--help", "-h" and "-?" returns 'h'.
+ * - "--version" and "-V" return 'V'.
+ */
+#define RTGETOPTINIT_FLAGS_NO_STD_OPTS RT_BIT_32(1)
+/** @} */
+
+/**
+ * Command line argument parser, handling both long and short options and checking
+ * argument formats, if desired.
+ *
+ * This is to be called in a loop until it returns 0 (meaning that all options
+ * were parsed) or a negative value (meaning that an error occurred). How non-option
+ * arguments are dealt with depends on the flags passed to RTGetOptInit. The default
+ * (fFlags = 0) is to return VINF_GETOPT_NOT_OPTION with pValueUnion->psz pointing to
+ * the argument string.
+ *
+ * For example, for a program which takes the following options:
+ *
+ * --optwithstring (or -s) and a string argument;
+ * --optwithint (or -i) and a 32-bit signed integer argument;
+ * --verbose (or -v) with no arguments,
+ *
+ * code would look something like this:
+ *
+ * @code
+int main(int argc, char **argv)
+{
+ int rc = RTR3Init();
+ if (RT_FAILURE(rc))
+ return RTMsgInitFailure(rc);
+
+ static const RTGETOPTDEF s_aOptions[] =
+ {
+ { "--optwithstring", 's', RTGETOPT_REQ_STRING },
+ { "--optwithint", 'i', RTGETOPT_REQ_INT32 },
+ { "--verbose", 'v', 0 },
+ };
+
+ int ch;
+ RTGETOPTUNION ValueUnion;
+ RTGETOPTSTATE GetState;
+ RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, 0);
+ while ((ch = RTGetOpt(&GetState, &ValueUnion)))
+ {
+ // for options that require an argument, ValueUnion has received the value
+ switch (ch)
+ {
+ case 's': // --optwithstring or -s
+ // string argument, copy ValueUnion.psz
+ break;
+
+ case 'i': // --optwithint or -i
+ // integer argument, copy ValueUnion.i32
+ break;
+
+ case 'v': // --verbose or -v
+ g_fOptVerbose = true;
+ break;
+
+ case VINF_GETOPT_NOT_OPTION:
+ // handle non-option argument in ValueUnion.psz.
+ break;
+
+ default:
+ return RTGetOptPrintError(ch, &ValueUnion);
+ }
+ }
+
+ return RTEXITCODE_SUCCESS;
+}
+ @endcode
+ *
+ * @returns 0 when done parsing.
+ * @returns the iShort value of the option. pState->pDef points to the option
+ * definition which matched.
+ * @returns IPRT error status on parse error.
+ * @returns VINF_GETOPT_NOT_OPTION when encountering a non-option argument and
+ * RTGETOPTINIT_FLAGS_OPTS_FIRST was not specified. pValueUnion->psz
+ * points to the argument string.
+ * @returns VERR_GETOPT_UNKNOWN_OPTION when encountering an unknown option.
+ * pValueUnion->psz points to the option string.
+ * @returns VERR_GETOPT_REQUIRED_ARGUMENT_MISSING and pValueUnion->pDef if
+ * a required argument (aka value) was missing for an option.
+ * @returns VERR_GETOPT_INVALID_ARGUMENT_FORMAT and pValueUnion->pDef if
+ * argument (aka value) conversion failed.
+ *
+ * @param pState The state previously initialized with RTGetOptInit.
+ * @param pValueUnion Union with value; in the event of an error, psz member
+ * points to erroneous parameter; otherwise, for options
+ * that require an argument, this contains the value of
+ * that argument, depending on the type that is required.
+ */
+RTDECL(int) RTGetOpt(PRTGETOPTSTATE pState, PRTGETOPTUNION pValueUnion);
+
+/**
+ * Fetch a value.
+ *
+ * Used to retrive a value argument in a manner similar to what RTGetOpt does
+ * (@a fFlags -> @a pValueUnion). This can be used when handling
+ * VINF_GETOPT_NOT_OPTION, but is equally useful for decoding options that
+ * takes more than one value.
+ *
+ * @returns VINF_SUCCESS on success.
+ * @returns IPRT error status on parse error.
+ * @returns VERR_INVALID_PARAMETER if the flags are wrong.
+ * @returns VERR_GETOPT_UNKNOWN_OPTION when pState->pDef is null.
+ * @returns VERR_GETOPT_REQUIRED_ARGUMENT_MISSING if there are no more
+ * available arguments. pValueUnion->pDef is NULL.
+ * @returns VERR_GETOPT_INVALID_ARGUMENT_FORMAT and pValueUnion->pDef is
+ * unchanged if value conversion failed.
+ *
+ * @param pState The state previously initialized with RTGetOptInit.
+ * @param pValueUnion Union with value; in the event of an error, psz member
+ * points to erroneous parameter; otherwise, for options
+ * that require an argument, this contains the value of
+ * that argument, depending on the type that is required.
+ * @param fFlags What to get, that is RTGETOPT_REQ_XXX.
+ */
+RTDECL(int) RTGetOptFetchValue(PRTGETOPTSTATE pState, PRTGETOPTUNION pValueUnion, uint32_t fFlags);
+
+/**
+ * Gets the pointer to the argv entry of the current non-option argument.
+ *
+ * This function ASSUMES the previous RTGetOpt() call returned
+ * VINF_GETOPT_NOT_OPTION and require RTGETOPTINIT_FLAGS_OPTS_FIRST to be
+ * specified to RTGetOptInit().
+ *
+ * @returns Pointer to the argv entry of the current non-option. NULL if
+ * (detectable) precondition isn't fullfilled (asserted)
+ * @param pState The state previously initialized with RTGetOptInit.
+ */
+RTDECL(char **) RTGetOptNonOptionArrayPtr(PRTGETOPTSTATE pState);
+
+/**
+ * Print error messages for a RTGetOpt default case.
+ *
+ * Uses RTMsgError.
+ *
+ * @returns Suitable exit code.
+ *
+ * @param ch The RTGetOpt return value.
+ * @param pValueUnion The value union returned by RTGetOpt.
+ */
+RTDECL(RTEXITCODE) RTGetOptPrintError(int ch, PCRTGETOPTUNION pValueUnion);
+
+/**
+ * Formats error messages for a RTGetOpt default case.
+ *
+ * @returns On success, positive count of formatted character excluding the
+ * terminator. On buffer overflow, negative number giving the required
+ * buffer size (including terminator char). (RTStrPrintf2 style.)
+ *
+ * @param pszBuf The buffer to format into.
+ * @param cbBuf The size of the buffer @a pszBuf points to.
+ * @param ch The RTGetOpt return value.
+ * @param pValueUnion The value union returned by RTGetOpt.
+ */
+RTDECL(ssize_t) RTGetOptFormatError(char *pszBuf, size_t cbBuf, int ch, PCRTGETOPTUNION pValueUnion);
+
+/**
+ * Parses the @a pszCmdLine string into an argv array.
+ *
+ * This is useful for converting a response file or similar to an argument
+ * vector that can be used with RTGetOptInit().
+ *
+ * This function aims at following the bourne shell string quoting rules.
+ *
+ * @returns IPRT status code.
+ *
+ * @param ppapszArgv Where to return the argument vector. This must be
+ * freed by calling RTGetOptArgvFreeEx or
+ * RTGetOptArgvFree.
+ * @param pcArgs Where to return the argument count.
+ * @param pszCmdLine The string to parse.
+ * @param fFlags A combination of the RTGETOPTARGV_CNV_XXX flags,
+ * except RTGETOPTARGV_CNV_UNQUOTED is not supported.
+ * @param pszSeparators String containing the argument separators. If NULL,
+ * then space, tab, line feed (\\n) and return (\\r)
+ * are used.
+ */
+RTDECL(int) RTGetOptArgvFromString(char ***ppapszArgv, int *pcArgs, const char *pszCmdLine, uint32_t fFlags,
+ const char *pszSeparators);
+
+/**
+ * Frees and argument vector returned by RTGetOptStringToArgv.
+ *
+ * @param papszArgv Argument vector. NULL is fine.
+ */
+RTDECL(void) RTGetOptArgvFree(char **papszArgv);
+
+/**
+ * Frees and argument vector returned by RTGetOptStringToArgv, taking
+ * RTGETOPTARGV_CNV_MODIFY_INPUT into account.
+ *
+ * @param papszArgv Argument vector. NULL is fine.
+ * @param fFlags The flags passed to RTGetOptStringToArgv.
+ */
+RTDECL(void) RTGetOptArgvFreeEx(char **papszArgv, uint32_t fFlags);
+
+/**
+ * Turns an argv array into a command line string.
+ *
+ * This is useful for calling CreateProcess on Windows, but can also be used for
+ * displaying an argv array.
+ *
+ * This function aims at following the bourn shell string quoting rules.
+ *
+ * @returns IPRT status code.
+ *
+ * @param ppszCmdLine Where to return the command line string. This must
+ * be freed by calling RTStrFree.
+ * @param papszArgv The argument vector to convert.
+ * @param fFlags A combination of the RTGETOPTARGV_CNV_XXX flags.
+ */
+RTDECL(int) RTGetOptArgvToString(char **ppszCmdLine, const char * const *papszArgv, uint32_t fFlags);
+
+/** @name RTGetOptArgvToString, RTGetOptArgvToUtf16String and
+ * RTGetOptArgvFromString flags
+ * @{ */
+/** Quote strings according to the Microsoft CRT rules. */
+#define RTGETOPTARGV_CNV_QUOTE_MS_CRT UINT32_C(0x00000000)
+/** Quote strings according to the Unix Bourne Shell. */
+#define RTGETOPTARGV_CNV_QUOTE_BOURNE_SH UINT32_C(0x00000001)
+/** Don't quote any strings at all. */
+#define RTGETOPTARGV_CNV_UNQUOTED UINT32_C(0x00000002)
+/** Mask for the quoting style. */
+#define RTGETOPTARGV_CNV_QUOTE_MASK UINT32_C(0x00000003)
+/** Allow RTGetOptArgvFromString to modifying the command line input string.
+ * @note Must use RTGetOptArgvFreeEx to free. */
+#define RTGETOPTARGV_CNV_MODIFY_INPUT UINT32_C(0x00000004)
+/** Valid bits. */
+#define RTGETOPTARGV_CNV_VALID_MASK UINT32_C(0x00000007)
+/** @} */
+
+/**
+ * Convenience wrapper around RTGetOpArgvToString and RTStrToUtf16.
+ *
+ * @returns IPRT status code.
+ *
+ * @param ppwszCmdLine Where to return the command line string. This must
+ * be freed by calling RTUtf16Free.
+ * @param papszArgv The argument vector to convert.
+ * @param fFlags A combination of the RTGETOPTARGV_CNV_XXX flags.
+ */
+RTDECL(int) RTGetOptArgvToUtf16String(PRTUTF16 *ppwszCmdLine, const char * const *papszArgv, uint32_t fFlags);
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_getopt_h */
+
diff --git a/include/iprt/handle.h b/include/iprt/handle.h
new file mode 100644
index 00000000..9f4ad5bd
--- /dev/null
+++ b/include/iprt/handle.h
@@ -0,0 +1,81 @@
+/** @file
+ * IPRT - Generic Handle Operations.
+ */
+
+/*
+ * Copyright (C) 2010-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_handle_h
+#define IPRT_INCLUDED_handle_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_handle RTHandle - Generic Handle Operations
+ * @ingroup grp_rt
+ * @{
+ */
+
+/**
+ * Closes or destroy a generic handle.
+ *
+ * @returns IPRT status code.
+ * @param ph Pointer to the generic handle. The structure handle
+ * will be set to NIL. A NULL pointer or a NIL handle
+ * will be quietly ignore (VINF_SUCCESS).
+ */
+RTDECL(int) RTHandleClose(PRTHANDLE ph);
+
+/**
+ * Gets one of the standard handles.
+ *
+ * @returns IPRT status code.
+ * @param enmStdHandle The standard handle.
+ * @param fLeaveOpen Whether closing the returned handle should leave the
+ * native standard handle open or not.
+ * Note! This currently only works with pipes and
+ * sockets!
+ * @param ph Pointer to the generic handle. This will contain
+ * the most appropriate IPRT handle on success.
+ */
+RTDECL(int) RTHandleGetStandard(RTHANDLESTD enmStdHandle, bool fLeaveOpen, PRTHANDLE ph);
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_handle_h */
+
diff --git a/include/iprt/handletable.h b/include/iprt/handletable.h
new file mode 100644
index 00000000..98d243af
--- /dev/null
+++ b/include/iprt/handletable.h
@@ -0,0 +1,259 @@
+/** @file
+ * IPRT - Handle Tables.
+ */
+
+/*
+ * Copyright (C) 2008-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_handletable_h
+#define IPRT_INCLUDED_handletable_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_handletable RTHandleTable - Handle Tables
+ * @ingroup grp_rt
+ * @{
+ */
+
+/**
+ * Callback for retaining an object during the lookup and free calls.
+ *
+ * This callback is executed when a handle is being looked up in one
+ * way or another from behind the handle table lock. This allows you
+ * to increase the reference (or some equivalent thing) during the
+ * handle lookup and thereby eliminate any race with anyone trying
+ * to free the handle.
+ *
+ * Note that there is no counterpart to this callback, so if you make
+ * use of this you'll have to release the object manually of course.
+ *
+ * Another use of this callback is to do some extra access checking.
+ * Use the return code to indicate whether the lookup should fail
+ * or not (no object is returned on faliure, naturally).
+ *
+ * @returns IPRT status code for the lookup (the caller won't see this).
+ *
+ * @param hHandleTable The handle table handle.
+ * @param pvObj The object which has been looked up.
+ * @param pvCtx The context argument if the handle table was created with the
+ * RTHANDLETABLE_FLAGS_CONTEXT set. Otherwise NULL.
+ * @param pvUser The user context argument specified when creating the table.
+ */
+typedef DECLCALLBACKTYPE(int, FNRTHANDLETABLERETAIN,(RTHANDLETABLE hHandleTable, void *pvObj, void *pvCtx, void *pvUser));
+/** Pointer to a FNHANDLETABLERETAIN. */
+typedef FNRTHANDLETABLERETAIN *PFNRTHANDLETABLERETAIN;
+
+/**
+ * Callback for deleting a left over object during RTHandleTableDestroy.
+ *
+ * @param hHandleTable The handle table handle.
+ * @param h The handle.
+ * @param pvObj The object.
+ * @param pvCtx The context argument if the handle table was created with the
+ * RTHANDLETABLE_FLAGS_CONTEXT set. Otherwise NULL.
+ * @param pvUser The user context argument specified when creating the table.
+ *
+ */
+typedef DECLCALLBACKTYPE(void, FNRTHANDLETABLEDELETE,(RTHANDLETABLE hHandleTable, uint32_t h, void *pvObj, void *pvCtx, void *pvUser));
+/** Pointer to a FNRTHANDLETABLEDELETE. */
+typedef FNRTHANDLETABLEDELETE *PFNRTHANDLETABLEDELETE;
+
+
+/** @name RTHandleTableCreateEx flags
+ * @{ */
+/** Whether the handle table entries takes a context or not.
+ *
+ * This can be useful for associating a handle with for instance a process or
+ * similar in order to prevent anyone but the owner from using the handle.
+ *
+ * Setting this means you will have to use the WithCtx functions to do the
+ * handle management. */
+#define RTHANDLETABLE_FLAGS_CONTEXT RT_BIT_32(0)
+/** Whether the handle table should take care of the serialization (IRQ unsafe).
+ * If not specified the caller will have to take care of that. */
+#define RTHANDLETABLE_FLAGS_LOCKED RT_BIT_32(1)
+/** Like RTHANDLETABLE_FLAGS_LOCKED, except it's IRQ safe.
+ * A side-effect is that callbacks may be called with IRQs disabled. */
+#define RTHANDLETABLE_FLAGS_LOCKED_IRQ_SAFE RT_BIT_32(2)
+/** The mask of valid flags. */
+#define RTHANDLETABLE_FLAGS_MASK UINT32_C(0x00000007)
+/** @} */
+
+
+/**
+ * Creates a handle table.
+ *
+ * The handle table translates a 32-bit handle into an object pointer,
+ * optionally calling you back so you can retain the object without
+ * racing RTHandleTableFree.
+ *
+ * @returns IPRT status code and on success a handle table handle will be stored at the
+ * location phHandleTable points at.
+ *
+ * @param phHandleTable Where to store the handle table handle on success.
+ * @param fFlags Flags, see RTHANDLETABLE_FLAGS_*.
+ * @param uBase The handle base value. This is the value of the
+ * first handle to be returned.
+ * @param cMax The max number of handles. When exceeded the RTHandleTableAlloc
+ * or RTHandleTableAllocWithCtx calls will fail. Note that this
+ * number will be rounded up to a multiple of the sub-table size,
+ * or if it's too close to UINT32_MAX it will be rounded down.
+ * @param pfnRetain Optional retain callback that will be called from behind the
+ * lock (if any) during lookup.
+ * @param pvUser The user argument to the retain callback.
+ */
+RTDECL(int) RTHandleTableCreateEx(PRTHANDLETABLE phHandleTable, uint32_t fFlags, uint32_t uBase, uint32_t cMax,
+ PFNRTHANDLETABLERETAIN pfnRetain, void *pvUser);
+
+/**
+ * A simplified version of the RTHandleTableCreateEx API.
+ *
+ * It assumes a max of about 64K handles with 1 being the base. The table
+ * access will serialized (RTHANDLETABLE_FLAGS_LOCKED).
+ *
+ * @returns IPRT status code and *phHandleTable.
+ *
+ * @param phHandleTable Where to store the handle table handle on success.
+ */
+RTDECL(int) RTHandleTableCreate(PRTHANDLETABLE phHandleTable);
+
+/**
+ * Destroys a handle table.
+ *
+ * If any entries are still in used the pfnDelete callback will be invoked
+ * on each of them (if specfied) to allow to you clean things up.
+ *
+ * @returns IPRT status code
+ *
+ * @param hHandleTable The handle to the handle table.
+ * @param pfnDelete Function to be called back on each handle still in use. Optional.
+ * @param pvUser The user argument to pfnDelete.
+ */
+RTDECL(int) RTHandleTableDestroy(RTHANDLETABLE hHandleTable, PFNRTHANDLETABLEDELETE pfnDelete, void *pvUser);
+
+/**
+ * Allocates a handle from the handle table.
+ *
+ * @returns IPRT status code, almost any.
+ * @retval VINF_SUCCESS on success.
+ * @retval VERR_NO_MEMORY if we failed to extend the handle table.
+ * @retval VERR_NO_MORE_HANDLES if we're out of handles.
+ *
+ * @param hHandleTable The handle to the handle table.
+ * @param pvObj The object to associate with the new handle.
+ * This must be aligned on a 4 byte boundary.
+ * @param ph Where to return the handle on success.
+ *
+ * @remarks Do not call this if RTHANDLETABLE_FLAGS_CONTEXT was used during creation.
+ */
+RTDECL(int) RTHandleTableAlloc(RTHANDLETABLE hHandleTable, void *pvObj, uint32_t *ph);
+
+/**
+ * Looks up a handle.
+ *
+ * @returns The object pointer on success. NULL on failure.
+ *
+ * @param hHandleTable The handle to the handle table.
+ * @param h The handle to lookup.
+ *
+ * @remarks Do not call this if RTHANDLETABLE_FLAGS_CONTEXT was used during creation.
+ */
+RTDECL(void *) RTHandleTableLookup(RTHANDLETABLE hHandleTable, uint32_t h);
+
+/**
+ * Looks up and frees a handle.
+ *
+ * @returns The object pointer on success. NULL on failure.
+ *
+ * @param hHandleTable The handle to the handle table.
+ * @param h The handle to lookup.
+ *
+ * @remarks Do not call this if RTHANDLETABLE_FLAGS_CONTEXT was used during creation.
+ */
+RTDECL(void *) RTHandleTableFree(RTHANDLETABLE hHandleTable, uint32_t h);
+
+/**
+ * Allocates a handle from the handle table.
+ *
+ * @returns IPRT status code, almost any.
+ * @retval VINF_SUCCESS on success.
+ * @retval VERR_NO_MEMORY if we failed to extend the handle table.
+ * @retval VERR_NO_MORE_HANDLES if we're out of handles.
+ *
+ * @param hHandleTable The handle to the handle table.
+ * @param pvObj The object to associate with the new handle.
+ * This must be aligned on a 4 byte boundary.
+ * @param pvCtx The context to associate with the new handle.
+ * @param ph Where to return the handle on success.
+ *
+ * @remarks Call this if RTHANDLETABLE_FLAGS_CONTEXT was used during creation.
+ */
+RTDECL(int) RTHandleTableAllocWithCtx(RTHANDLETABLE hHandleTable, void *pvObj, void *pvCtx, uint32_t *ph);
+
+/**
+ * Looks up a handle.
+ *
+ * @returns The object pointer on success. NULL on failure.
+ *
+ * @param hHandleTable The handle to the handle table.
+ * @param h The handle to lookup.
+ * @param pvCtx The handle context, this must match what was given on allocation.
+ *
+ * @remarks Call this if RTHANDLETABLE_FLAGS_CONTEXT was used during creation.
+ */
+RTDECL(void *) RTHandleTableLookupWithCtx(RTHANDLETABLE hHandleTable, uint32_t h, void *pvCtx);
+
+/**
+ * Looks up and frees a handle.
+ *
+ * @returns The object pointer on success. NULL on failure.
+ *
+ * @param hHandleTable The handle to the handle table.
+ * @param h The handle to lookup.
+ * @param pvCtx The handle context, this must match what was given on allocation.
+ *
+ * @remarks Call this if RTHANDLETABLE_FLAGS_CONTEXT was used during creation.
+ */
+RTDECL(void *) RTHandleTableFreeWithCtx(RTHANDLETABLE hHandleTable, uint32_t h, void *pvCtx);
+
+/** @} */
+
+RT_C_DECLS_END
+
+
+#endif /* !IPRT_INCLUDED_handletable_h */
+
diff --git a/include/iprt/heap.h b/include/iprt/heap.h
new file mode 100644
index 00000000..bf2b3853
--- /dev/null
+++ b/include/iprt/heap.h
@@ -0,0 +1,369 @@
+/** @file
+ * IPRT - Heap Implementations
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_heap_h
+#define IPRT_INCLUDED_heap_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#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 DECLCALLBACKTYPE(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 DECLCALLBACKTYPE(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 /* !IPRT_INCLUDED_heap_h */
+
diff --git a/include/iprt/http-common.h b/include/iprt/http-common.h
new file mode 100644
index 00000000..d9cc746f
--- /dev/null
+++ b/include/iprt/http-common.h
@@ -0,0 +1,286 @@
+/* $Id: http-common.h $ */
+/** @file
+ * IPRT - Common (client / server) HTTP API.
+ */
+
+/*
+ * Copyright (C) 2012-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_http_common_h
+#define IPRT_INCLUDED_http_common_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/list.h>
+#include <iprt/types.h>
+
+RT_C_DECLS_BEGIN
+
+/** HTTP methods. */
+typedef enum RTHTTPMETHOD
+{
+ RTHTTPMETHOD_INVALID = 0,
+ RTHTTPMETHOD_GET,
+ RTHTTPMETHOD_PUT,
+ RTHTTPMETHOD_POST,
+ RTHTTPMETHOD_PATCH,
+ RTHTTPMETHOD_DELETE,
+ RTHTTPMETHOD_HEAD,
+ RTHTTPMETHOD_OPTIONS,
+ RTHTTPMETHOD_TRACE,
+#ifdef IPRT_HTTP_WITH_WEBDAV
+ RTHTTPMETHOD_PROPFIND,
+#endif
+ RTHTTPMETHOD_END,
+ RTHTTPMETHOD_32BIT_HACK = 0x7fffffff
+} RTHTTPMETHOD;
+
+/** HTTP status codes. */
+typedef enum RTHTTPSTATUS
+{
+ RTHTTPSTATUS_INTERNAL_NOT_SET = 0,
+ /**
+ * 2xx - Success / information codes.
+ */
+ RTHTTPSTATUS_OK = 200,
+ RTHTTPSTATUS_CREATED = 201,
+ RTHTTPSTATUS_ACCEPTED = 202,
+ RTHTTPSTATUS_NONAUTHORITATIVEINFORMATION = 203,
+ RTHTTPSTATUS_NOCONTENT = 204,
+ RTHTTPSTATUS_RESETCONTENT = 205,
+ RTHTTPSTATUS_PARTIALCONTENT = 206,
+ RTHTTPSTATUS_MULTISTATUS = 207,
+ RTHTTPSTATUS_ALREADYREPORTED = 208,
+ RTHTTPSTATUS_IMUSED = 226,
+ /**
+ * 4xx - Client error codes.
+ */
+ RTHTTPSTATUS_BADREQUEST = 400,
+ RTHTTPSTATUS_UNAUTHORIZED = 401,
+ RTHTTPSTATUS_PAYMENTREQUIRED = 402,
+ RTHTTPSTATUS_FORBIDDEN = 403,
+ RTHTTPSTATUS_NOTFOUND = 404,
+ RTHTTPSTATUS_METHODNOTALLOWED = 405,
+ RTHTTPSTATUS_NOTACCEPTABLE = 406,
+ RTHTTPSTATUS_PROXYAUTHENTICATIONREQUIRED = 407,
+ RTHTTPSTATUS_REQUESTTIMEOUT = 408,
+ RTHTTPSTATUS_CONFLICT = 409,
+ RTHTTPSTATUS_GONE = 410,
+ RTHTTPSTATUS_LENGTHREQUIRED = 411,
+ RTHTTPSTATUS_PRECONDITIONFAILED = 412,
+ RTHTTPSTATUS_PAYLOADTOOLARGE = 413,
+ RTHTTPSTATUS_URITOOLONG = 414,
+ RTHTTPSTATUS_UNSUPPORTEDMEDIATYPE = 415,
+ RTHTTPSTATUS_RANGENOTSATISFIABLE = 416,
+ RTHTTPSTATUS_EXPECTATIONFAILED = 417,
+ RTHTTPSTATUS_IMATEAPOT = 418,
+ RTHTTPSTATUS_UNPROCESSABLEENTITY = 422,
+ RTHTTPSTATUS_LOCKED = 423,
+ RTHTTPSTATUS_FAILEDDEPENDENCY = 424,
+ RTHTTPSTATUS_UPGRADEREQUIRED = 426,
+ RTHTTPSTATUS_PRECONDITIONREQUIRED = 428,
+ RTHTTPSTATUS_TOOMANYREQUESTS = 429,
+ RTHTTPSTATUS_REQUESTHEADERFIELDSTOOLARGE = 431,
+ RTHTTPSTATUS_UNAVAILABLEFORLEGALREASONS = 451,
+ /**
+ * 5xx - Server error codes.
+ */
+ RTHTTPSTATUS_INTERNALSERVERERROR = 500,
+ RTHTTPSTATUS_NOTIMPLEMENTED = 501,
+ RTHTTPSTATUS_BADGATEWAY = 502,
+ RTHTTPSTATUS_SERVICEUNAVAILABLE = 503,
+ RTHTTPSTATUS_GATEWAYTIMEOUT = 504,
+ RTHTTPSTATUS_HTTPVERSIONNOTSUPPORTED = 505,
+ RTHTTPSTATUS_VARIANTALSONEGOTIATES = 506,
+ RTHTTPSTATUS_INSUFFICIENTSTORAGE = 507,
+ RTHTTPSTATUS_LOOPDETECTED = 508,
+ RTHTTPSTATUS_NOTEXTENDED = 510,
+ RTHTTPSTATUS_NETWORKAUTHENTICATIONREQUIRED = 511,
+
+ RTHTTPSTATUS_32BIT_HACK = 0x7fffffff
+} RTHTTPSTATUS;
+
+/** Checks whether a HTTP status is of type "informational" or not. */
+#define RTHTTPSTATUS_IS_INFO(a_Code) (a_Code >= 100 && a_Code < 200)
+/** Checks whether a HTTP status indicates success or not. */
+#define RTHTTPSTATUS_IS_OK(a_Code) (a_Code >= 200 && a_Code < 300)
+/** Checks whether a HTTP status indicates a redirection or not. */
+#define RTHTTPSTATUS_IS_REDIRECT(a_Code) (a_Code >= 300 && a_Code < 400)
+/** Checks whether a HTTP status indicates a client error or not. */
+#define RTHTTPSTATUS_IS_CLIENTERROR(a_Code) (a_Code >= 400 && a_Code < 500)
+/** Checks whether a HTTP status indicates a server error or not. */
+#define RTHTTPSTATUS_IS_SERVERERROR(a_Code) (a_Code >= 500 && a_Code < 600)
+/** Checks whether a HTTP status indicates an error or not. */
+#define RTHTTPSTATUS_IS_ERROR(a_Code) (a_Code >= 400)
+
+/** Specifies a HTTP MIME type. */
+typedef uint32_t RTHTTPMIMETYPE;
+
+#define RTHTTPMIMETYPE_TEXT_PLAIN "text/plain"
+#define RTHTTPMIMETYPE_APPLICATION_OCTET_STREAM "application/octet-stream"
+
+/** Specifies HTTP version 1.1 as a string. */
+#define RTHTTPVER_1_1_STR "HTTP/1.1"
+
+/** @todo the following three definitions may move the iprt/types.h later. */
+/** HTTP header list handle. */
+typedef R3PTRTYPE(struct RTHTTPHEADERLISTINTERNAL *) RTHTTPHEADERLIST;
+/** Pointer to a HTTP header list handle. */
+typedef RTHTTPHEADERLIST *PRTHTTPHEADERLIST;
+/** Nil HTTP HTTP header list handle. */
+#define NIL_RTHTTPHEADERLIST ((RTHTTPHEADERLIST)0)
+
+/**
+ * HTTP header list entry.
+ */
+typedef struct RTHTTPHEADERENTRY
+{
+ /** The list node. */
+ RTLISTNODE Node;
+ /** The field name length. */
+ uint32_t cchName;
+ /** The value offset. */
+ uint32_t offValue;
+ /** The full header field. */
+ RT_FLEXIBLE_ARRAY_EXTENSION
+ RT_GCC_EXTENSION char szData[RT_FLEXIBLE_ARRAY];
+} RTHTTPHEADERENTRY;
+/** Pointer to a HTTP header. */
+typedef RTHTTPHEADERENTRY *PRTHTTPHEADERENTRY;
+
+/**
+ * Structure for maintaining a HTTP body.
+ */
+typedef struct RTHTTPBODY
+{
+ /** Body to send, if any. Can be NULL. */
+ void *pvBody;
+ /** Body allocation size (in bytes). */
+ size_t cbBodyAlloc;
+ /** How much body data is being used (in bytes). */
+ size_t cbBodyUsed;
+ /** Current body data read/write offset (in bytes). */
+ size_t offBody;
+} RTHTTPBODY;
+/** Pointer to a HTTP body. */
+typedef RTHTTPBODY *PRTHTTPBODY;
+
+/**
+ * Returns the name of the HTTP method.
+ * @returns Read only string.
+ * @param enmMethod The HTTP method to name.
+ */
+RTR3DECL(const char *) RTHttpMethodToStr(RTHTTPMETHOD enmMethod);
+
+RTR3DECL(const char *) RTHttpStatusToStr(RTHTTPSTATUS enmSts);
+
+RTR3DECL(int) RTHttpHeaderListInit(PRTHTTPHEADERLIST hHdrList);
+
+RTR3DECL(void) RTHttpHeaderListDestroy(RTHTTPHEADERLIST hHdrList);
+
+/**
+ * Set custom raw headers.
+ *
+ * @returns IPRT status code.
+ * @param hHdrLst The HTTP header list handle.
+ * @param cHeaders Number of custom headers.
+ * @param papszHeaders Array of headers in form "foo: bar".
+ */
+RTR3DECL(int) RTHttpHeaderListSet(RTHTTPHEADERLIST hHdrLst, size_t cHeaders, const char * const *papszHeaders);
+
+/** @name RTHTTPHEADERLISTADD_F_XXX - Flags for RTHttpHeaderListAddRaw and RTHttpHeaderListAdd
+ * @{ */
+#define RTHTTPHEADERLISTADD_F_BACK UINT32_C(0) /**< Append the header. */
+#define RTHTTPHEADERLISTADD_F_FRONT UINT32_C(1) /**< Prepend the header. */
+/** @} */
+
+/**
+ * Adds a raw header.
+ *
+ * @returns IPRT status code.
+ * @param hHdrLst The HTTP header list handle.
+ * @param pszHeader Header string on the form "foo: bar".
+ * @param fFlags RTHTTPADDHDR_F_FRONT or RTHTTPADDHDR_F_BACK.
+ */
+RTR3DECL(int) RTHttpHeaderListAddRaw(RTHTTPHEADERLIST hHdrLst, const char *pszHeader, uint32_t fFlags);
+
+/**
+ * Adds a header field and value.
+ *
+ * @returns IPRT status code.
+ * @param hHdrLst The HTTP header list handle.
+ * @param pszField The header field name.
+ * @param pszValue The header field value.
+ * @param cchValue The value length or RTSTR_MAX.
+ * @param fFlags Only RTHTTPADDHDR_F_FRONT or RTHTTPADDHDR_F_BACK,
+ * may be extended with encoding controlling flags if
+ * needed later.
+ */
+RTR3DECL(int) RTHttpHeaderListAdd(RTHTTPHEADERLIST hHdrLst, const char *pszField, const char *pszValue, size_t cchValue, uint32_t fFlags);
+
+/**
+ * Gets a header previously added using RTHttpSetHeaders, RTHttpAppendRawHeader
+ * or RTHttpAppendHeader.
+ *
+ * @returns Pointer to the header value on if found, otherwise NULL.
+ * @param hHdrLst The HTTP header list handle.
+ * @param pszField The field name (no colon).
+ * @param cchField The length of the field name or RTSTR_MAX.
+ */
+RTR3DECL(const char *) RTHttpHeaderListGet(RTHTTPHEADERLIST hHdrLst, const char *pszField, size_t cchField);
+
+/**
+ * Gets the number of headers specified by RTHttpAddHeader, RTHttpAddRawHeader or RTHttpSetHeaders.
+ *
+ * @returns Number of headers.
+ * @param hHdrLst The HTTP header list handle.
+ * @note This can be slow and is only really intended for test cases and debugging!
+ */
+RTR3DECL(size_t) RTHttpHeaderListGetCount(RTHTTPHEADERLIST hHdrLst);
+
+/**
+ * Gets a header by ordinal.
+ *
+ * Can be used together with RTHttpGetHeaderCount by test case and debug code to
+ * iterate headers specified by RTHttpAddHeader, RTHttpAddRawHeader or RTHttpSetHeaders.
+ *
+ * @returns The header string ("field: value").
+ * @param hHdrLst The HTTP header list handle.
+ * @param iOrdinal The number of the header to get.
+ * @note This can be slow and is only really intended for test cases and debugging!
+ */
+RTR3DECL(const char *) RTHttpHeaderListGetByOrdinal(RTHTTPHEADERLIST hHdrLst, size_t iOrdinal);
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_http_common_h */
+
diff --git a/include/iprt/http-server.h b/include/iprt/http-server.h
new file mode 100644
index 00000000..eab06a37
--- /dev/null
+++ b/include/iprt/http-server.h
@@ -0,0 +1,244 @@
+/* $Id: http-server.h $ */
+/** @file
+ * Header file for HTTP server implementation.
+ */
+
+/*
+ * Copyright (C) 2020-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_http_server_h
+#define IPRT_INCLUDED_http_server_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/http-common.h>
+#include <iprt/types.h>
+#include <iprt/fs.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_httpserver RTHttpServer - HTTP server implementation.
+ * @ingroup grp_rt
+ * @{
+ */
+
+/** @todo the following three definitions may move the iprt/types.h later. */
+/** HTTP server handle. */
+typedef R3PTRTYPE(struct RTHTTPSERVERINTERNAL *) RTHTTPSERVER;
+/** Pointer to a HTTP server handle. */
+typedef RTHTTPSERVER *PRTHTTPSERVER;
+/** Nil HTTP client handle. */
+#define NIL_RTHTTPSERVER ((RTHTTPSERVER)0)
+
+/**
+ * Structure for maintaining a HTTP client request.
+ */
+typedef struct RTHTTPSERVERREQ
+{
+ /** Request URL. */
+ char *pszUrl;
+ /** Request method. */
+ RTHTTPMETHOD enmMethod;
+ /** Request header list. */
+ RTHTTPHEADERLIST hHdrLst;
+ /** Request body data. */
+ RTHTTPBODY Body;
+} RTHTTPSERVERREQ;
+/** Pointer to a HTTP client request. */
+typedef RTHTTPSERVERREQ *PRTHTTPSERVERREQ;
+
+/**
+ * Structure for maintaining a HTTP server response.
+ */
+typedef struct RTHTTPSERVERRESP
+{
+ /** HTTP status to send. */
+ RTHTTPSTATUS enmSts;
+ /** List of headers to send. */
+ RTHTTPHEADERLIST hHdrLst;
+ /** Body data to send. */
+ RTHTTPBODY Body;
+} RTHTTPSERVERRESP;
+/** Pointer to a HTTP server response. */
+typedef RTHTTPSERVERRESP *PRTHTTPSERVERRESP;
+
+RTR3DECL(int) RTHttpServerResponseInitEx(PRTHTTPSERVERRESP pResp, size_t cbBody);
+RTR3DECL(int) RTHttpServerResponseInit(PRTHTTPSERVERRESP pResp);
+RTR3DECL(void) RTHttpServerResponseDestroy(PRTHTTPSERVERRESP pResp);
+
+/**
+ * Structure for maintaining a HTTP server client state.
+ *
+ * Note: The HTTP protocol itself is stateless, but we want to have to possibility to store
+ * some state stuff here nevertheless.
+ */
+typedef struct RTHTTPSERVERCLIENTSTATE
+{
+ /** If non-zero, the time (in ms) to keep a client connection alive.
+ * Requested via client header, but set and controlled by the server in the end. */
+ RTMSINTERVAL msKeepAlive;
+} RTHTTPSERVERCLIENTSTATE;
+/** Pointer to a FTP server client state. */
+typedef RTHTTPSERVERCLIENTSTATE *PRTHTTPSERVERCLIENTSTATE;
+
+/**
+ * Structure for storing HTTP server callback data.
+ */
+typedef struct RTHTTPCALLBACKDATA
+{
+ /** Pointer to the client state. */
+ PRTHTTPSERVERCLIENTSTATE pClient;
+ /** Saved user pointer. */
+ void *pvUser;
+ /** Size (in bytes) of data at user pointer. */
+ size_t cbUser;
+} RTHTTPCALLBACKDATA;
+/** Pointer to HTTP server callback data. */
+typedef RTHTTPCALLBACKDATA *PRTHTTPCALLBACKDATA;
+
+/**
+ * Function callback table for the HTTP server implementation.
+ *
+ * All callbacks are optional and therefore can be NULL.
+ */
+typedef struct RTHTTPSERVERCALLBACKS
+{
+ /**
+ * Called before a given URL will be retrieved by the GET method.
+ *
+ * Note: High level function, not being called when pfnOnGetRequest is implemented.
+ *
+ * @returns VBox status code.
+ * @param pData Pointer to HTTP callback data.
+ * @param pReq Pointer to request to handle.
+ * @param ppvHandle Where to return the pointer to the opaque handle used for object identification.
+ */
+ DECLCALLBACKMEMBER(int, pfnOpen,(PRTHTTPCALLBACKDATA pData, PRTHTTPSERVERREQ pReq, void **ppvHandle));
+ /**
+ * Called when a given URL will be retrieved by the GET method.
+ *
+ * Note: High level function, not being called when pfnOnGetRequest is implemented.
+ * Note2: Can be called multiple times, based on the body size to send.
+ *
+ * @returns VBox status code.
+ * @param pData Pointer to HTTP callback data.
+ * @param pvHandle Opaque handle for object identification.
+ * @param pvBuf Pointer to buffer where to store the read data.
+ * @param cbBuf Size (in bytes) of the buffer where to store the read data.
+ * @param pcbRead Where to return the amount (in bytes) of read data. Optional and can be NULL.
+ */
+ DECLCALLBACKMEMBER(int, pfnRead,(PRTHTTPCALLBACKDATA pData, void *pvHandle, void *pvBuf, size_t cbBuf, size_t *pcbRead));
+ /**
+ * Called when a given URL is done retrieving by the GET method.
+ *
+ * Note: High level function, not being called when pfnOnGetRequest is implemented.
+ *
+ * @returns VBox status code.
+ * @param pData Pointer to HTTP callback data.
+ * @param pszUrl URL to handle.
+ * @param pvHandle Opaque handle for object identification.
+ */
+ DECLCALLBACKMEMBER(int, pfnClose,(PRTHTTPCALLBACKDATA pData, void *pvHandle));
+ /**
+ * Queries information about a given URL.
+ *
+ * Will be called with GET or HEAD request.
+ *
+ * @returns VBox status code.
+ * @param pData Pointer to HTTP callback data.
+ * @param pReq Pointer to request to handle.
+ * @param pObjInfo Where to store the queried file information on success.
+ * @param ppszMIMEHint Where to return an allocated MIME type hint on success.
+ * Must be free'd by the caller using RTStrFree().
+ */
+ DECLCALLBACKMEMBER(int, pfnQueryInfo,(PRTHTTPCALLBACKDATA pData, PRTHTTPSERVERREQ pReq, PRTFSOBJINFO pObjInfo, char **ppszMIMEHint));
+ /**
+ * Low-level handler for a GET method request.
+ *
+ * @returns VBox status code.
+ * @param pData Pointer to HTTP callback data.
+ * @param pReq Pointer to request to handle.
+ */
+ DECLCALLBACKMEMBER(int, pfnOnGetRequest,(PRTHTTPCALLBACKDATA pData, PRTHTTPSERVERREQ pReq));
+ /**
+ * Low-level handler for a HEAD method request.
+ *
+ * @returns VBox status code.
+ * @param pData Pointer to HTTP callback data.
+ * @param pReq Pointer to request to handle.
+ */
+ DECLCALLBACKMEMBER(int, pfnOnHeadRequest,(PRTHTTPCALLBACKDATA pData, PRTHTTPSERVERREQ pReq));
+ /**
+ * Called before the HTTP server will be destroyed.
+ *
+ * @returns VBox status code.
+ * @param pData Pointer to HTTP callback data.
+ */
+ DECLCALLBACKMEMBER(int, pfnDestroy,(PRTHTTPCALLBACKDATA pData));
+} RTHTTPSERVERCALLBACKS;
+/** Pointer to a HTTP server callback data table. */
+typedef RTHTTPSERVERCALLBACKS *PRTHTTPSERVERCALLBACKS;
+
+/** Maximum length (in bytes) a single client request can have. */
+#define RTHTTPSERVER_MAX_REQ_LEN _8K
+/** EOL string according to the HTTP 1.1 specs.
+ * See https://tools.ietf.org/html/rfc2616#section-2.2 */
+#define RTHTTPSERVER_HTTP11_EOL_STR "\r\n"
+
+/**
+ * Creates a HTTP server instance.
+ *
+ * @returns IPRT status code.
+ * @param phHttpServer Where to store the HTTP server handle.
+ * @param pcszAddress The address for creating a listening socket.
+ * If NULL or empty string the server is bound to all interfaces.
+ * @param uPort The port for creating a listening socket.
+ * @param pCallbacks Callback table to use.
+ * @param pvUser Pointer to user-specific data. Optional.
+ * @param cbUser Size of user-specific data. Optional.
+ */
+RTR3DECL(int) RTHttpServerCreate(PRTHTTPSERVER phHttpServer, const char *pcszAddress, uint16_t uPort,
+ PRTHTTPSERVERCALLBACKS pCallbacks, void *pvUser, size_t cbUser);
+
+/**
+ * Destroys a HTTP server instance.
+ *
+ * @returns IPRT status code.
+ * @param hHttpServer Handle to the HTTP server handle.
+ */
+RTR3DECL(int) RTHttpServerDestroy(RTHTTPSERVER hHttpServer);
+
+/** @} */
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_http_server_h */
+
diff --git a/include/iprt/http.h b/include/iprt/http.h
new file mode 100644
index 00000000..5ab966fd
--- /dev/null
+++ b/include/iprt/http.h
@@ -0,0 +1,746 @@
+/* $Id: http.h $ */
+/** @file
+ * IPRT - Simple HTTP/HTTPS Client API.
+ */
+
+/*
+ * Copyright (C) 2012-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_http_h
+#define IPRT_INCLUDED_http_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+#include <iprt/http-common.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_http RTHttp - Simple HTTP/HTTPS Client API
+ * @ingroup grp_rt
+ * @{
+ */
+
+/** @todo the following three definitions may move the iprt/types.h later. */
+/** HTTP/HTTPS client handle. */
+typedef R3PTRTYPE(struct RTHTTPINTERNAL *) RTHTTP;
+/** Pointer to a HTTP/HTTPS client handle. */
+typedef RTHTTP *PRTHTTP;
+/** Nil HTTP/HTTPS client handle. */
+#define NIL_RTHTTP ((RTHTTP)0)
+
+
+/**
+ * Creates a HTTP client instance.
+ *
+ * @returns IPRT status code.
+ * @param phHttp Where to store the HTTP handle.
+ */
+RTR3DECL(int) RTHttpCreate(PRTHTTP phHttp);
+
+/**
+ * Resets a HTTP client instance.
+ *
+ * @returns IPRT status code.
+ * @param hHttp Handle to the HTTP interface.
+ * @param fFlags Flags, RTHTTP_RESET_F_XXX.
+ */
+RTR3DECL(int) RTHttpReset(RTHTTP hHttp, uint32_t fFlags);
+
+/** @name RTHTTP_RESET_F_XXX - Flags for RTHttpReset.
+ * @{ */
+/** Keep the headers. */
+#define RTHTTP_RESET_F_KEEP_HEADERS RT_BIT_32(0)
+/** Mask containing the valid flags. */
+#define RTHTTP_RESET_F_VALID_MASK UINT32_C(0x00000001)
+/** @} */
+
+
+/**
+ * Destroys a HTTP client instance.
+ *
+ * @returns IPRT status code.
+ * @param hHttp Handle to the HTTP interface.
+ */
+RTR3DECL(int) RTHttpDestroy(RTHTTP hHttp);
+
+
+/**
+ * Retrieve the redir location for 301 responses.
+ *
+ * @param hHttp Handle to the HTTP interface.
+ * @param ppszRedirLocation Where to store the string. To be freed with
+ * RTStrFree().
+ */
+RTR3DECL(int) RTHttpGetRedirLocation(RTHTTP hHttp, char **ppszRedirLocation);
+
+/**
+ * Perform a simple blocking HTTP GET request.
+ *
+ * This is a just a convenient wrapper around RTHttpGetBinary that returns a
+ * different type and sheds a parameter.
+ *
+ * @returns iprt status code.
+ *
+ * @param hHttp The HTTP client handle.
+ * @param pszUrl URL.
+ * @param ppszNotUtf8 Where to return the pointer to the HTTP response.
+ * The string is of course zero terminated. Use
+ * RTHttpFreeReponseText to free.
+ *
+ * @remarks BIG FAT WARNING!
+ *
+ * This function does not guarantee the that returned string is valid UTF-8 or
+ * any other kind of text encoding!
+ *
+ * The caller must determine and validate the string encoding _before_
+ * passing it along to functions that expect UTF-8!
+ *
+ * Also, this function does not guarantee that the returned string
+ * doesn't have embedded zeros and provides the caller no way of
+ * finding out! If you are worried about the response from the HTTPD
+ * containing embedded zero's, use RTHttpGetBinary instead.
+ */
+RTR3DECL(int) RTHttpGetText(RTHTTP hHttp, const char *pszUrl, char **ppszNotUtf8);
+
+/**
+ * Perform a simple blocking HTTP HEAD request.
+ *
+ * This is a just a convenient wrapper around RTHttpGetBinary that returns a
+ * different type and sheds a parameter.
+ *
+ * @returns iprt status code.
+ *
+ * @param hHttp The HTTP client handle.
+ * @param pszUrl URL.
+ * @param ppszNotUtf8 Where to return the pointer to the HTTP response.
+ * The string is of course zero terminated. Use
+ * RTHttpFreeReponseText to free.
+ *
+ * @remarks BIG FAT WARNING!
+ *
+ * This function does not guarantee the that returned string is valid UTF-8 or
+ * any other kind of text encoding!
+ *
+ * The caller must determine and validate the string encoding _before_
+ * passing it along to functions that expect UTF-8!
+ *
+ * Also, this function does not guarantee that the returned string
+ * doesn't have embedded zeros and provides the caller no way of
+ * finding out! If you are worried about the response from the HTTPD
+ * containing embedded zero's, use RTHttpGetHeaderBinary instead.
+ */
+RTR3DECL(int) RTHttpGetHeaderText(RTHTTP hHttp, const char *pszUrl, char **ppszNotUtf8);
+
+/**
+ * Frees memory returned by RTHttpGetText.
+ *
+ * @param pszNotUtf8 What RTHttpGetText returned.
+ */
+RTR3DECL(void) RTHttpFreeResponseText(char *pszNotUtf8);
+
+/**
+ * Perform a simple blocking HTTP GET request.
+ *
+ * @returns iprt status code.
+ *
+ * @param hHttp The HTTP client handle.
+ * @param pszUrl The URL.
+ * @param ppvResponse Where to store the HTTP response data. Use
+ * RTHttpFreeResponse to free.
+ * @param pcb Size of the returned buffer.
+ *
+ * @note There is a limit on how much this function allows to be downloaded,
+ * given that the return requires a single heap allocation and all
+ * that. Currently 32 MB on 32-bit hosts and 64 MB on 64-bit hosts.
+ * Use RTHttpGetFile or RTHttpSetDownloadCallback for larger transfers.
+ */
+RTR3DECL(int) RTHttpGetBinary(RTHTTP hHttp, const char *pszUrl, void **ppvResponse, size_t *pcb);
+
+/**
+ * Perform a simple blocking HTTP HEAD request.
+ *
+ * @returns iprt status code.
+ *
+ * @param hHttp The HTTP client handle.
+ * @param pszUrl The URL.
+ * @param ppvResponse Where to store the HTTP response data. Use
+ * RTHttpFreeResponse to free.
+ * @param pcb Size of the returned buffer.
+ */
+RTR3DECL(int) RTHttpGetHeaderBinary(RTHTTP hHttp, const char *pszUrl, void **ppvResponse, size_t *pcb);
+
+/**
+ * Frees memory returned by RTHttpGetBinary.
+ *
+ * @param pvResponse What RTHttpGetBinary returned.
+ */
+RTR3DECL(void) RTHttpFreeResponse(void *pvResponse);
+
+/**
+ * Perform a simple blocking HTTP request, writing the output to a file.
+ *
+ * @returns iprt status code.
+ *
+ * @param hHttp The HTTP client handle.
+ * @param pszUrl The URL.
+ * @param pszDstFile The destination file name.
+ */
+RTR3DECL(int) RTHttpGetFile(RTHTTP hHttp, const char *pszUrl, const char *pszDstFile);
+
+/**
+ * Performs generic blocking HTTP request, optionally returning the body and headers.
+ *
+ * @returns IPRT status code.
+ * @param hHttp The HTTP client handle.
+ * @param pszUrl The URL.
+ * @param enmMethod The HTTP method for the request.
+ * @param pvReqBody Pointer to the request body. NULL if none.
+ * @param cbReqBody Size of the request body. Zero if none.
+ * @param puHttpStatus Where to return the HTTP status code. Optional.
+ * @param ppvHeaders Where to return the headers. Optional.
+ * @param pcbHeaders Where to return the header size.
+ * @param ppvBody Where to return the body. Optional.
+ * @param pcbBody Where to return the body size.
+ */
+RTR3DECL(int) RTHttpPerform(RTHTTP hHttp, const char *pszUrl, RTHTTPMETHOD enmMethod, void const *pvReqBody, size_t cbReqBody,
+ uint32_t *puHttpStatus, void **ppvHeaders, size_t *pcbHeaders, void **ppvBody, size_t *pcbBody);
+
+
+/**
+ * Abort a pending HTTP request. A blocking RTHttpGet() call will return with
+ * VERR_HTTP_ABORTED. It may take some time (current cURL implementation needs
+ * up to 1 second) before the request is aborted.
+ *
+ * @returns iprt status code.
+ *
+ * @param hHttp The HTTP client handle.
+ */
+RTR3DECL(int) RTHttpAbort(RTHTTP hHttp);
+
+/**
+ * Tells the HTTP interface to use the system proxy configuration.
+ *
+ * @returns iprt status code.
+ * @param hHttp The HTTP client handle.
+ */
+RTR3DECL(int) RTHttpUseSystemProxySettings(RTHTTP hHttp);
+
+/**
+ * Sets up the proxy according to the specified URL.
+ *
+ * @returns IPRT status code.
+ * @retval VWRN_WRONG_TYPE if the type isn't known/supported and we defaulted to 'http'.
+ *
+ * @param hHttp The HTTP client handle.
+ * @param pszUrl The proxy URL (libproxy style):
+ *
+ * [{type}"://"][{userid}[\@{password}]:]{server}[":"{port}]
+ *
+ * Valid proxy types are: http (default), https, socks4, socks4a,
+ * socks5, socks5h and direct. Support for the socks and https
+ * ones depends on the HTTP library we use.
+ *
+ * The port number defaults to 80 for http, 443 for https and 1080
+ * for the socks ones.
+ *
+ * If this starts with "direct://", then no proxy will be used.
+ * An empty or NULL string is equivalent to calling
+ * RTHttpUseSystemProxySettings().
+ */
+RTR3DECL(int) RTHttpSetProxyByUrl(RTHTTP hHttp, const char *pszUrl);
+
+/**
+ * Specify proxy settings.
+ *
+ * @returns iprt status code.
+ *
+ * @param hHttp The HTTP client handle.
+ * @param pszProxyUrl URL of the proxy server.
+ * @param uPort port number of the proxy, use 0 for not specifying a port.
+ * @param pszProxyUser Username, pass NULL for no authentication.
+ * @param pszProxyPwd Password, pass NULL for no authentication.
+ *
+ * @todo This API does not allow specifying the type of proxy server... We're
+ * currently assuming it's a HTTP proxy.
+ *
+ * @deprecated Use RTHttpSetProxyByUrl.
+ */
+RTR3DECL(int) RTHttpSetProxy(RTHTTP hHttp, const char *pszProxyUrl, uint32_t uPort,
+ const char *pszProxyUser, const char *pszProxyPwd);
+
+/**
+ * Set follow redirects (3xx)
+ *
+ * @returns iprt status code.
+ *
+ * @param hHttp The HTTP client handle.
+ * @param cMaxRedirects Max number of redirects to follow. Zero if no
+ * redirects should be followed but instead returned
+ * to caller.
+ */
+RTR3DECL(int) RTHttpSetFollowRedirects(RTHTTP hHttp, uint32_t cMaxRedirects);
+
+/**
+ * Gets the follow redirect setting.
+ *
+ * @returns cMaxRedirects value, 0 means not to follow.
+ * @param hHttp The HTTP client handle.
+ */
+RTR3DECL(uint32_t) RTHttpGetFollowRedirects(RTHTTP hHttp);
+
+/**
+ * Set custom raw headers.
+ *
+ * @returns iprt status code.
+ *
+ * @param hHttp The HTTP client handle.
+ * @param cHeaders Number of custom headers.
+ * @param papszHeaders Array of headers in form "foo: bar".
+ */
+RTR3DECL(int) RTHttpSetHeaders(RTHTTP hHttp, size_t cHeaders, const char * const *papszHeaders);
+
+/** @name RTHTTPADDHDR_F_XXX - Flags for RTHttpAddRawHeader and RTHttpAddHeader
+ * @{ */
+#define RTHTTPADDHDR_F_BACK UINT32_C(0) /**< Append the header. */
+#define RTHTTPADDHDR_F_FRONT UINT32_C(1) /**< Prepend the header. */
+/** @} */
+
+/**
+ * Adds a raw header.
+ *
+ * @returns IPRT status code.
+ * @param hHttp The HTTP client handle.
+ * @param pszHeader Header string on the form "foo: bar".
+ * @param fFlags RTHTTPADDHDR_F_FRONT or RTHTTPADDHDR_F_BACK.
+ */
+RTR3DECL(int) RTHttpAddRawHeader(RTHTTP hHttp, const char *pszHeader, uint32_t fFlags);
+
+/**
+ * Adds a header field and value.
+ *
+ * @returns IPRT status code.
+ * @param hHttp The HTTP client handle.
+ * @param pszField The header field name.
+ * @param pszValue The header field value.
+ * @param cchValue The value length or RTSTR_MAX.
+ * @param fFlags Only RTHTTPADDHDR_F_FRONT or RTHTTPADDHDR_F_BACK,
+ * may be extended with encoding controlling flags if
+ * needed later.
+ */
+RTR3DECL(int) RTHttpAddHeader(RTHTTP hHttp, const char *pszField, const char *pszValue, size_t cchValue, uint32_t fFlags);
+
+/**
+ * Gets a header previously added using RTHttpSetHeaders, RTHttpAppendRawHeader
+ * or RTHttpAppendHeader.
+ *
+ * @returns Pointer to the header value on if found, otherwise NULL.
+ * @param hHttp The HTTP client handle.
+ * @param pszField The field name (no colon).
+ * @param cchField The length of the field name or RTSTR_MAX.
+ */
+RTR3DECL(const char *) RTHttpGetHeader(RTHTTP hHttp, const char *pszField, size_t cchField);
+
+/**
+ * Gets the number of headers specified by RTHttpAddHeader, RTHttpAddRawHeader or RTHttpSetHeaders.
+ *
+ * @returns Number of headers.
+ * @param hHttp The HTTP client handle.
+ * @note This can be slow and is only really intended for test cases and debugging!
+ */
+RTR3DECL(size_t) RTHttpGetHeaderCount(RTHTTP hHttp);
+
+/**
+ * Gets a header by ordinal.
+ *
+ * Can be used together with RTHttpGetHeaderCount by test case and debug code to
+ * iterate headers specified by RTHttpAddHeader, RTHttpAddRawHeader or RTHttpSetHeaders.
+ *
+ * @returns The header string ("field: value").
+ * @param hHttp The HTTP client handle.
+ * @param iOrdinal The number of the header to get.
+ * @note This can be slow and is only really intended for test cases and debugging!
+ */
+RTR3DECL(const char *) RTHttpGetByOrdinal(RTHTTP hHttp, size_t iOrdinal);
+
+/**
+ * Sign all headers present according to pending "Signing HTTP Messages" RFC.
+ *
+ * Currently hardcoded RSA-SHA-256 algorithm choice.
+ *
+ * @returns IPRT status code.
+ * @param hHttp The HTTP client handle.
+ * @param enmMethod The HTTP method that will be used for the request.
+ * @param pszUrl The target URL for the request.
+ * @param hKey The RSA key to use when signing.
+ * @param pszKeyId The key ID string corresponding to @a hKey.
+ * @param fFlags Reserved for future, MBZ.
+ *
+ * @note Caller is responsible for making all desired fields are present before
+ * making the call.
+ *
+ * @remarks Latest RFC draft at the time of writing:
+ * https://tools.ietf.org/html/draft-cavage-http-signatures-10
+ */
+RTR3DECL(int) RTHttpSignHeaders(RTHTTP hHttp, RTHTTPMETHOD enmMethod, const char *pszUrl,
+ RTCRKEY hKey, const char *pszKeyId, uint32_t fFlags);
+
+/**
+ * Tells the HTTP client instance to gather system CA certificates into a
+ * temporary file and use it for HTTPS connections.
+ *
+ * This will be called automatically if a 'https' URL is presented and
+ * RTHttpSetCaFile hasn't been called yet.
+ *
+ * @returns IPRT status code.
+ * @param hHttp The HTTP client handle.
+ * @param pErrInfo Where to store additional error/warning information.
+ * Optional.
+ */
+RTR3DECL(int) RTHttpUseTemporaryCaFile(RTHTTP hHttp, PRTERRINFO pErrInfo);
+
+/**
+ * Set a custom certification authority file, containing root certificates.
+ *
+ * @returns iprt status code.
+ *
+ * @param hHttp The HTTP client handle.
+ * @param pszCAFile File name containing root certificates.
+ *
+ * @remarks For portable HTTPS support, use RTHttpGatherCaCertsInFile and pass
+ */
+RTR3DECL(int) RTHttpSetCAFile(RTHTTP hHttp, const char *pszCAFile);
+
+/**
+ * Gathers certificates into a cryptographic (certificate) store
+ *
+ * This is a just a combination of RTHttpGatherCaCertsInStore and
+ * RTCrStoreCertExportAsPem.
+ *
+ * @returns IPRT status code.
+ * @param hStore The certificate store to gather the certificates
+ * in.
+ * @param fFlags RTHTTPGATHERCACERT_F_XXX.
+ * @param pErrInfo Where to store additional error/warning information.
+ * Optional.
+ */
+RTR3DECL(int) RTHttpGatherCaCertsInStore(RTCRSTORE hStore, uint32_t fFlags, PRTERRINFO pErrInfo);
+
+/**
+ * Gathers certificates into a file that can be used with RTHttpSetCAFile.
+ *
+ * This is a just a combination of RTHttpGatherCaCertsInStore and
+ * RTCrStoreCertExportAsPem.
+ *
+ * @returns IPRT status code.
+ * @param pszCaFile The output file.
+ * @param fFlags RTHTTPGATHERCACERT_F_XXX.
+ * @param pErrInfo Where to store additional error/warning information.
+ * Optional.
+ */
+RTR3DECL(int) RTHttpGatherCaCertsInFile(const char *pszCaFile, uint32_t fFlags, PRTERRINFO pErrInfo);
+
+/**
+ * Set whether to verify the peer's SSL certificate.
+ *
+ * The default is to verify it. It can however sometimes be useful or even
+ * necessary to skip this.
+ *
+ * @returns iprt status code.
+ *
+ * @param hHttp The HTTP client handle.
+ * @param fVerify Verify the certificate if @a true.
+ */
+RTR3DECL(int) RTHttpSetVerifyPeer(RTHTTP hHttp, bool fVerify);
+
+/**
+ * Get the state of the peer's SSL certificate setting.
+ *
+ * @returns true if we verify the SSL certificate, false if not.
+ * @param hHttp The HTTP client handle.
+ */
+RTR3DECL(bool) RTHttpGetVerifyPeer(RTHTTP hHttp);
+
+/**
+ * Callback function to be called during RTHttpGet*().
+ *
+ * Register it using RTHttpSetDownloadProgressCallback().
+ *
+ * @param hHttp The HTTP client handle.
+ * @param pvUser The user parameter specified when registering the callback.
+ * @param cbDownloadTotal The content-length value, if available.
+ * Warning! Not entirely clear what it will be if
+ * unavailable, probably 0.
+ * @param cbDownloaded How much was downloaded thus far.
+ */
+typedef DECLCALLBACKTYPE(void, FNRTHTTPDOWNLDPROGRCALLBACK,(RTHTTP hHttp, void *pvUser, uint64_t cbDownloadTotal,
+ uint64_t cbDownloaded));
+/** Pointer to a download progress callback. */
+typedef FNRTHTTPDOWNLDPROGRCALLBACK *PFNRTHTTPDOWNLDPROGRCALLBACK;
+
+/**
+ * Set the callback function which is called during (GET)
+ *
+ * @returns IPRT status code.
+ * @param hHttp The HTTP client handle.
+ * @param pfnCallback Progress function to be called. Set it to
+ * NULL to disable the callback.
+ * @param pvUser Convenience pointer for the callback function.
+ */
+RTR3DECL(int) RTHttpSetDownloadProgressCallback(RTHTTP hHttp, PFNRTHTTPDOWNLDPROGRCALLBACK pfnCallback, void *pvUser);
+
+/**
+ * Callback function for receiving body data.
+ *
+ * @returns IPRT status code.
+ * @param hHttp The HTTP client handle.
+ * @param pvBuf Pointer to buffer with body bytes.
+ * @param cbBuf Number of bytes in the buffer.
+ * @param uHttpStatus The HTTP status code.
+ * @param offContent The byte offset corresponding to the start of @a pvBuf.
+ * @param cbContent The content length field value, UINT64_MAX if not available.
+ * @param pvUser The user parameter.
+ *
+ * @note The @a offContent parameter does not imply random access or anthing
+ * like that, it is just a convenience provided by the caller. The
+ * value is the sum of the previous @a cbBuf values.
+ */
+typedef DECLCALLBACKTYPE(int, FNRTHTTPDOWNLOADCALLBACK,(RTHTTP hHttp, void const *pvBuf, size_t cbBuf, uint32_t uHttpStatus,
+ uint64_t offContent, uint64_t cbContent, void *pvUser));
+/** Pointer to a download data receiver callback. */
+typedef FNRTHTTPDOWNLOADCALLBACK *PFNRTHTTPDOWNLOADCALLBACK;
+
+/**
+ * Set the callback function for downloading data (HTTP GET).
+ *
+ * @returns IPRT status code.
+ * @param hHttp The HTTP client handle.
+ * @param fFlags RTHTTPDOWNLOAD_F_XXX.
+ * @param pfnCallback The callback function. Pass NULL to reset the callback.
+ * @param pvUser Convenience pointer for the callback function.
+ *
+ * @remarks There can only be one download callback, so it is not possible to
+ * call this method for different status codes. Only the last one
+ * with be honored.
+ *
+ * @note This only works reliably with RTHttpPerform at the moment.
+ */
+RTR3DECL(int) RTHttpSetDownloadCallback(RTHTTP hHttp, uint32_t fFlags, PFNRTHTTPDOWNLOADCALLBACK pfnCallback, void *pvUser);
+
+/** @name RTHTTPDOWNLOAD_F_XXX
+ * @{ */
+/** The lower 10 bits gives the HTTP status required by the callback.
+ * For all other status codes, any body data will be returned via the
+ * RTHttpPerform ppvBody/pcbBody return parameters. */
+#define RTHTTPDOWNLOAD_F_ONLY_STATUS_MASK UINT32_C(0x000003ff)
+/** Callback requires no special HTTP status. */
+#define RTHTTPDOWNLOAD_F_ANY_STATUS UINT32_C(0x000003ff)
+/** @} */
+
+
+/**
+ * Callback function for producing body data for uploading.
+ *
+ * @returns IPRT status code.
+ * @param hHttp The HTTP client handle.
+ * @param pvBuf Where to put the data to upload
+ * @param cbBuf Max number of bytes to provide.
+ * @param offContent The byte offset corresponding to the start of @a pvBuf.
+ * @param pcbActual Actual number of bytes provided.
+ * @param pvUser The user parameter.
+ *
+ * @note The @a offContent parameter does not imply random access or anthing
+ * like that, it is just a convenience provided by the caller. The
+ * value is the sum of the previously returned @a *pcbActual values.
+ */
+typedef DECLCALLBACKTYPE(int, FNRTHTTPUPLOADCALLBACK,(RTHTTP hHttp, void *pvBuf, size_t cbBuf, uint64_t offContent,
+ size_t *pcbActual, void *pvUser));
+/** Pointer to an upload data producer callback. */
+typedef FNRTHTTPUPLOADCALLBACK *PFNRTHTTPUPLOADCALLBACK;
+
+/**
+ * Set the callback function for providing upload data (HTTP PUT / POST).
+ *
+ * @returns IPRT status code.
+ * @param hHttp The HTTP client handle.
+ * @param cbContent The content length, UINT64_MAX if not know or specified separately.
+ * @param pfnCallback The callback function. Pass NULL to reset the callback.
+ * @param pvUser Convenience pointer for the callback function.
+ *
+ * @note This only works reliably with RTHttpPerform at the moment.
+ */
+RTR3DECL(int) RTHttpSetUploadCallback(RTHTTP hHttp, uint64_t cbContent, PFNRTHTTPUPLOADCALLBACK pfnCallback, void *pvUser);
+
+
+/**
+ * Callback for consuming header fields.
+ *
+ * @returns IPRT status code.
+ * @param hHttp The HTTP client handle.
+ * @param uMatchWord Match word constructed by RTHTTP_MAKE_HDR_MATCH_WORD
+ * @param pchField The field name (not zero terminated).
+ * Not necessarily valid UTF-8!
+ * @param cchField The length of the field.
+ * @param pchValue The field value (not zero terminated).
+ * Not necessarily valid UTF-8!
+ * @param cchValue The length of the value.
+ * @param pvUser The user parameter.
+ *
+ * @remarks This is called with two fictitious header fields too:
+ * - ':http-status-line' -- the HTTP/{version} {status-code} stuff.
+ * - ':end-of-headers' -- marks the end of header callbacks.
+ */
+typedef DECLCALLBACKTYPE(int, FNRTHTTPHEADERCALLBACK,(RTHTTP hHttp, uint32_t uMatchWord, const char *pchField, size_t cchField,
+ const char *pchValue, size_t cchValue, void *pvUser));
+/** Pointer to a header field consumer callback. */
+typedef FNRTHTTPHEADERCALLBACK *PFNRTHTTPHEADERCALLBACK;
+
+/**
+ * Forms a fast header match word.
+ *
+ * @returns Fast header match word.
+ * @param a_cchField The length of the header field name.
+ * @param a_chLower1 The first character in the name, lowercased.
+ * @param a_chLower2 The second character in the name, lowercased.
+ * @param a_chLower3 The third character in the name, lowercased.
+ */
+#define RTHTTP_MAKE_HDR_MATCH_WORD(a_cchField, a_chLower1, a_chLower2, a_chLower3) \
+ RT_MAKE_U32_FROM_U8(a_cchField, a_chLower1, a_chLower2, a_chLower3)
+
+/**
+ * Set the callback function for processing header fields in the response.
+ *
+ * @returns IPRT status code.
+ * @param hHttp The HTTP client handle.
+ * @param pfnCallback The callback function. Pass NULL to reset the callback.
+ * @param pvUser Convenience pointer for the callback function.
+ *
+ * @note This only works reliably with RTHttpPerform at the moment.
+ */
+RTR3DECL(int) RTHttpSetHeaderCallback(RTHTTP hHttp, PFNRTHTTPHEADERCALLBACK pfnCallback, void *pvUser);
+
+
+/**
+ * Supported proxy types.
+ */
+typedef enum RTHTTPPROXYTYPE
+{
+ RTHTTPPROXYTYPE_INVALID = 0,
+ RTHTTPPROXYTYPE_NOPROXY,
+ RTHTTPPROXYTYPE_HTTP,
+ RTHTTPPROXYTYPE_HTTPS,
+ RTHTTPPROXYTYPE_SOCKS4,
+ RTHTTPPROXYTYPE_SOCKS5,
+ RTHTTPPROXYTYPE_UNKNOWN,
+ RTHTTPPROXYTYPE_END,
+ RTHTTPPROXYTYPE_32BIT_HACK = 0x7fffffff
+} RTHTTPPROXYTYPE;
+
+/**
+ * Proxy information returned by RTHttpQueryProxyInfoForUrl.
+ */
+typedef struct RTHTTPPROXYINFO
+{
+ /** Proxy host name. */
+ char *pszProxyHost;
+ /** Proxy port number (UINT32_MAX if not specified). */
+ uint32_t uProxyPort;
+ /** The proxy type (RTHTTPPROXYTYPE_HTTP, RTHTTPPROXYTYPE_SOCKS5, ++). */
+ RTHTTPPROXYTYPE enmProxyType;
+ /** Proxy username. */
+ char *pszProxyUsername;
+ /** Proxy password. */
+ char *pszProxyPassword;
+} RTHTTPPROXYINFO;
+/** A pointer to proxy information structure. */
+typedef RTHTTPPROXYINFO *PRTHTTPPROXYINFO;
+
+/**
+ * Retrieve system proxy information for the specified URL.
+ *
+ * @returns IPRT status code.
+ * @param hHttp The HTTP client handle.
+ * @param pszUrl The URL that needs to be accessed via proxy.
+ * @param pProxyInfo Where to return the proxy information. This must be
+ * freed up by calling RTHttpFreeProxyInfo() when done.
+ */
+RTR3DECL(int) RTHttpQueryProxyInfoForUrl(RTHTTP hHttp, const char *pszUrl, PRTHTTPPROXYINFO pProxyInfo);
+
+/**
+ * Counter part to RTHttpQueryProxyInfoForUrl that releases any memory returned
+ * in the proxy info structure.
+ *
+ * @returns IPRT status code.
+ * @param pProxyInfo Pointer to proxy info returned by a successful
+ * RTHttpQueryProxyInfoForUrl() call.
+ */
+RTR3DECL(int) RTHttpFreeProxyInfo(PRTHTTPPROXYINFO pProxyInfo);
+
+/** @name thin wrappers for setting one or a few related curl options
+ * @remarks Temporary. Will not be included in the 7.0 release!
+ * @{ */
+typedef DECLCALLBACKTYPE_EX(size_t, RT_NOTHING, FNRTHTTPREADCALLBACKRAW,(void *pbDst, size_t cbItem, size_t cItems, void *pvUser));
+typedef FNRTHTTPREADCALLBACKRAW *PFNRTHTTPREADCALLBACKRAW;
+#define RT_HTTP_READCALLBACK_ABORT 0x10000000 /* CURL_READFUNC_ABORT */
+RTR3DECL(int) RTHttpRawSetReadCallback(RTHTTP hHttp, PFNRTHTTPREADCALLBACKRAW pfnRead, void *pvUser);
+
+typedef DECLCALLBACKTYPE_EX(size_t, RT_NOTHING, FNRTHTTPWRITECALLBACKRAW,(char *pbSrc, size_t cbItem, size_t cItems, void *pvUser));
+typedef FNRTHTTPWRITECALLBACKRAW *PFNRTHTTPWRITECALLBACKRAW;
+RTR3DECL(int) RTHttpRawSetWriteCallback(RTHTTP hHttp, PFNRTHTTPWRITECALLBACKRAW pfnWrite, void *pvUser);
+RTR3DECL(int) RTHttpRawSetWriteHeaderCallback(RTHTTP hHttp, PFNRTHTTPWRITECALLBACKRAW pfnWrite, void *pvUser);
+
+RTR3DECL(int) RTHttpRawSetUrl(RTHTTP hHttp, const char *pszUrl);
+
+RTR3DECL(int) RTHttpRawSetGet(RTHTTP hHttp);
+RTR3DECL(int) RTHttpRawSetHead(RTHTTP hHttp);
+RTR3DECL(int) RTHttpRawSetPost(RTHTTP hHttp);
+RTR3DECL(int) RTHttpRawSetPut(RTHTTP hHttp);
+RTR3DECL(int) RTHttpRawSetDelete(RTHTTP hHttp);
+RTR3DECL(int) RTHttpRawSetCustomRequest(RTHTTP hHttp, const char *pszVerb);
+
+RTR3DECL(int) RTHttpRawSetPostFields(RTHTTP hHttp, const void *pv, size_t cb);
+RTR3DECL(int) RTHttpRawSetInfileSize(RTHTTP hHttp, RTFOFF cb);
+
+RTR3DECL(int) RTHttpRawSetVerbose(RTHTTP hHttp, bool fValue);
+RTR3DECL(int) RTHttpRawSetTimeout(RTHTTP hHttp, long sec);
+
+RTR3DECL(int) RTHttpRawPerform(RTHTTP hHttp);
+
+RTR3DECL(int) RTHttpRawGetResponseCode(RTHTTP hHttp, long *plCode);
+/** @} */
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_http_h */
+
diff --git a/include/iprt/inifile.h b/include/iprt/inifile.h
new file mode 100644
index 00000000..bc784bc5
--- /dev/null
+++ b/include/iprt/inifile.h
@@ -0,0 +1,150 @@
+/* $Id: inifile.h $ */
+/** @file
+ * IPRT - INI-file parser.
+ */
+
+/*
+ * Copyright (C) 2017-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_inifile_h
+#define IPRT_INCLUDED_inifile_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+
+#include <iprt/types.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_inifile RTIniFile - INI-file parser
+ * @ingroup grp_rt
+ * @{
+ */
+
+/** @name RTINIFILE_F_XXX - INI-file open flags.
+ * @{ */
+/** Readonly. */
+#define RTINIFILE_F_READONLY RT_BIT(0)
+/** Valid mask. */
+#define RTINIFILE_F_VALID_MASK UINT32_C(0x00000001)
+/** @} */
+
+
+
+/**
+ * Creates a INI-file instance from a VFS file handle.
+ *
+ * @returns IPRT status code
+ * @param phIniFile Where to return the INI-file handle.
+ * @param hVfsFile The VFS file handle (not consumed, additional
+ * reference is retained).
+ * @param fFlags Flags, RTINIFILE_F_XXX.
+ */
+RTDECL(int) RTIniFileCreateFromVfsFile(PRTINIFILE phIniFile, RTVFSFILE hVfsFile, uint32_t fFlags);
+
+/**
+ * Retains a reference to an INI-file instance.
+ *
+ * @returns New reference count, UINT32_MAX on failure.
+ * @param hIniFile The INI-file handle.
+ */
+RTDECL(uint32_t) RTIniFileRetain(RTINIFILE hIniFile);
+
+/**
+ * Releases a reference to an INI-file instance, destroying it if the count
+ * reaches zero.
+ *
+ * @returns New reference count, UINT32_MAX on failure.
+ * @param hIniFile The INI-file handle. NIL is ignored.
+ */
+RTDECL(uint32_t) RTIniFileRelease(RTINIFILE hIniFile);
+
+/**
+ * Queries a named value in a section.
+ *
+ * The first matching value is returned. The matching is by default case
+ * insensitive.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_NOT_FOUND if section or key not found.
+ *
+ * @param hIniFile The INI-file handle.
+ * @param pszSection The section name. Pass NULL to refer to the
+ * unsectioned key space at the top of the file.
+ * @param pszKey The key name.
+ * @param pszValue Where to return the value.
+ * @param cbValue Size of the buffer @a pszValue points to.
+ * @param pcbActual Where to return the actual value size excluding
+ * terminator on success. On VERR_BUFFER_OVERFLOW this
+ * will be set to the buffer size needed to hold the
+ * value, terminator included. Optional.
+ */
+RTDECL(int) RTIniFileQueryValue(RTINIFILE hIniFile, const char *pszSection, const char *pszKey,
+ char *pszValue, size_t cbValue, size_t *pcbActual);
+
+/**
+ * Queries a key-value pair in a section by ordinal.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_NOT_FOUND if the section wasn't found or if it contains no pair
+ * with the given ordinal value.
+ *
+ * @param hIniFile The INI-file handle.
+ * @param pszSection The section name. Pass NULL to refer to the
+ * unsectioned key space at the top of the file.
+ * @param idxPair The pair to fetch (counting from 0).
+ *
+ * @param pszKey Where to return the key name.
+ * @param cbKey Size of the buffer @a pszKey points to.
+ * @param pcbKeyActual Where to return the actual key size excluding
+ * terminator on success. On VERR_BUFFER_OVERFLOW this
+ * will be set to the buffer size needed to hold the
+ * value, terminator included. Optional.
+ *
+ * @param pszValue Where to return the value.
+ * @param cbValue Size of the buffer @a pszValue points to.
+ * @param pcbValueActual Where to return the actual value size excluding
+ * terminator on success. On VERR_BUFFER_OVERFLOW this
+ * will be set to the buffer size needed to hold the
+ * value, terminator included. Optional.
+ */
+RTDECL(int) RTIniFileQueryPair(RTINIFILE hIniFile, const char *pszSection, uint32_t idxPair,
+ char *pszKey, size_t cbKey, size_t *pcbKeyActual,
+ char *pszValue, size_t cbValue, size_t *pcbValueActual);
+
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_inifile_h */
+
diff --git a/include/iprt/initterm.h b/include/iprt/initterm.h
new file mode 100644
index 00000000..8083d559
--- /dev/null
+++ b/include/iprt/initterm.h
@@ -0,0 +1,291 @@
+/** @file
+ * IPRT - Runtime Init/Term.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_initterm_h
+#define IPRT_INCLUDED_initterm_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#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_XXX - RTR3Init* flags.
+ * @see RTR3InitExeNoArguments, RTR3InitExe, RTR3InitDll, RTR3InitEx
+ * @{ */
+/** Initializing IPRT from a DLL. */
+# define RTR3INIT_FLAGS_DLL RT_BIT(0)
+/** The caller ensures that the argument vector is UTF-8. */
+# define RTR3INIT_FLAGS_UTF8_ARGV RT_BIT(1)
+/** 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(2)
+/** We are sharing a process space, so we need to behave. */
+# define RTR3INIT_FLAGS_UNOBTRUSIVE RT_BIT(3)
+
+/** Initialize SUPLib (must not fail). */
+# define RTR3INIT_FLAGS_SUPLIB RT_BIT(16)
+/** Try initialize SUPLib and ignore failures. */
+# define RTR3INIT_FLAGS_TRY_SUPLIB RT_BIT(17)
+/** Shift count for passing thru SUPR3INIT_F_XXX flags. */
+# define RTR3INIT_FLAGS_SUPLIB_SHIFT 18
+/** The mask covering the passthru SUPR3INIT_F_XXX flags. */
+# define RTR3INIT_FLAGS_SUPLIB_MASK UINT32_C(0xfffc0000)
+
+/** Valid flag mask. */
+# define RTR3INIT_FLAGS_VALID_MASK UINT32_C(0xffff000f)
+/** @} */
+
+/** @name RTR3InitEx version
+ * @{ */
+/** Version 1. */
+# define RTR3INIT_VER_1 UINT32_C(1)
+/** Version 2 - new flags, rearranged a bit. */
+# define RTR3INIT_VER_2 UINT32_C(2)
+/** The current version. */
+# define RTR3INIT_VER_CUR RTR3INIT_VER_2
+/** @} */
+
+/**
+ * Initializes the runtime library.
+ *
+ * @returns iprt status code.
+ * @param fFlags Flags, see RTR3INIT_FLAGS_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_FLAGS_XXX.
+ */
+RTR3DECL(int) RTR3InitExe(int cArgs, char ***ppapszArgs, uint32_t fFlags);
+
+/**
+ * Initializes the runtime library.
+ *
+ * @returns iprt status code.
+ * @param fFlags Flags, see RTR3INIT_FLAGS_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_FLAGS_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 DECLCALLBACKTYPE(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 /* !IPRT_INCLUDED_initterm_h */
+
diff --git a/include/iprt/ioqueue.h b/include/iprt/ioqueue.h
new file mode 100644
index 00000000..92f1e2f1
--- /dev/null
+++ b/include/iprt/ioqueue.h
@@ -0,0 +1,405 @@
+/** @file
+ * IPRT Generic I/O queue API.
+ */
+
+/*
+ * Copyright (C) 2019-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_ioqueue_h
+#define IPRT_INCLUDED_ioqueue_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+#include <iprt/sg.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_ioqueue IPRT generic I/O queue API
+ * @ingroup grp_rt
+ *
+ * This API models a generic I/O queue which can be attached to different providers
+ * for different types of handles.
+ *
+ * @{
+ */
+
+
+/**
+ * I/O queue request operations.
+ */
+typedef enum RTIOQUEUEOP
+{
+ /** The usual invalid option. */
+ RTIOQUEUEOP_INVALID = 0,
+ /** Read request. */
+ RTIOQUEUEOP_READ,
+ /** Write request. */
+ RTIOQUEUEOP_WRITE,
+ /** Synchronize (i.e. flush) request. */
+ RTIOQUEUEOP_SYNC,
+ /** Usual 32bit hack. */
+ RTIOQUEUEOP_32BIT_HACK = 0x7fffffff
+} RTIOQUEUEOP;
+/** Pointer to a I/O queue operation code. */
+typedef RTIOQUEUEOP *PRTIOQUEUEOP;
+
+/** I/O queue provider (processes requests put into the I/O queue) handle. */
+typedef struct RTIOQUEUEPROVINT *RTIOQUEUEPROV;
+/** I/O queue handle. */
+typedef struct RTIOQUEUEINT *RTIOQUEUE;
+/** Pointer to an I/O queue handle. */
+typedef RTIOQUEUE *PRTIOQUEUE;
+/** NIL I/O queue handle value. */
+#define NIL_RTIOQUEUE ((RTIOQUEUE)0)
+
+
+/**
+ * I/O queue completion event.
+ */
+typedef struct RTIOQUEUECEVT
+{
+ /** The user data passed when preparing the request. */
+ void *pvUser;
+ /** The IPRT status code for this request. */
+ int rcReq;
+ /** Transferred data size if applicaple by the request. */
+ size_t cbXfered;
+} RTIOQUEUECEVT;
+/** Pointer to a I/O queue completion event. */
+typedef RTIOQUEUECEVT *PRTIOQUEUECEVT;
+/** Pointer to a const I/O queue completion event. */
+typedef const RTIOQUEUECEVT *PCRTIOQUEUECEVT;
+
+
+/**
+ * I/O queue provider virtual method table.
+ */
+typedef struct RTIOQUEUEPROVVTABLE
+{
+ /** The structure version (RTIOQUEUEPROVVTABLE_VERSION). */
+ uint32_t uVersion;
+ /** Provider ID. */
+ const char *pszId;
+ /** Size of provider specific data for an I/O queue instance. */
+ size_t cbIoQueueProv;
+ /** The handle type the provider is able to process. */
+ RTHANDLETYPE enmHnd;
+ /** Additional flags for exposing supported features or quirks to the user. */
+ uint32_t fFlags;
+
+ /**
+ * Returns whether the provider is supported on the calling host system.
+ *
+ * @returns Flag whether the provider is supported.
+ */
+ DECLCALLBACKMEMBER(bool, pfnIsSupported,(void));
+
+ /**
+ * Initializes the provider specific parts of the given I/O queue.
+ *
+ * @returns IPRT status code.
+ * @param hIoQueueProv The I/O queue provider instance to initialize.
+ * @param fFlags Flags for the queue.
+ * @param cSqEntries Number of entries for the submission queue.
+ * @param cCqEntries Number of entries for the completion queue.
+ */
+ DECLCALLBACKMEMBER(int, pfnQueueInit,(RTIOQUEUEPROV hIoQueueProv, uint32_t fFlags, uint32_t cSqEntries, uint32_t cCqEntries));
+
+ /**
+ * Destroys the provider specific parts of the I/O queue and frees all
+ * associated resources.
+ *
+ * @returns nothing.
+ * @param hIoQueueProv The I/O queue provider instance to destroy.
+ */
+ DECLCALLBACKMEMBER(void, pfnQueueDestroy,(RTIOQUEUEPROV hIoQueueProv));
+
+ /**
+ * Registers the given handle for use with the I/O queue instance.
+ * The generic code already checked for the correct handle type and that the
+ * handle wasn't registered already by tracking all registered handles.
+ *
+ * @returns IPRT status code.
+ * @param hIoQueueProv The I/O queue provider instance.
+ * @param pHandle The handle to register.
+ */
+ DECLCALLBACKMEMBER(int, pfnHandleRegister,(RTIOQUEUEPROV hIoQueueProv, PCRTHANDLE pHandle));
+
+ /**
+ * Deregisters the given handle for use with the I/O queue instance.
+ * The generic code already checked for the correct handle type and that the
+ * handle was registered previously.
+ *
+ * @returns IPRT status code.
+ * @param hIoQueueProv The I/O queue provider instance.
+ * @param pHandle The handle to deregister.
+ */
+ DECLCALLBACKMEMBER(int, pfnHandleDeregister,(RTIOQUEUEPROV hIoQueueProv, PCRTHANDLE pHandle));
+
+ /**
+ * Prepares a request for the given I/O queue.
+ *
+ * @returns IPRT status code.
+ * @param hIoQueueProv The I/O queue provider instance.
+ * @param pHandle The handle the request is for.
+ * @param enmOp The operation to perform.
+ * @param off Start offset (if applicable, not all handles support/require it and will ignore it).
+ * @param pvBuf Buffer to use for read/write operations (sync ignores this).
+ * @param cbBuf Size of the buffer in bytes.
+ * @param fReqFlags Additional flags for the request.
+ * @param pvUser Opaque user data which is passed back in the completion event.
+ */
+ DECLCALLBACKMEMBER(int, pfnReqPrepare,(RTIOQUEUEPROV hIoQueueProv, PCRTHANDLE pHandle, RTIOQUEUEOP enmOp,
+ uint64_t off, void *pvBuf, size_t cbBuf, uint32_t fReqFlags, void *pvUser));
+
+ /**
+ * Prepares a request for the given I/O queue.
+ *
+ * @returns IPRT status code.
+ * @param hIoQueueProv The I/O queue provider instance.
+ * @param pHandle The handle the request is for.
+ * @param enmOp The operation to perform.
+ * @param off Start offset (if applicable, not all handles support/require it and will ignore it).
+ * @param pSgBuf The S/G buufer to use for read/write operations (sync ignores this).
+ * @param cbSg Number of bytes to transfer from the S/G buffer.
+ * @param fReqFlags Additional flags for the request.
+ * @param pvUser Opaque user data which is passed back in the completion event.
+ */
+ DECLCALLBACKMEMBER(int, pfnReqPrepareSg,(RTIOQUEUEPROV hIoQueueProv, PCRTHANDLE pHandle, RTIOQUEUEOP enmOp,
+ uint64_t off, PCRTSGBUF pSgBuf, size_t cbSg, uint32_t fReqFlags, void *pvUser));
+
+ /**
+ * Commits all prepared requests to the consumer for processing.
+ *
+ * @returns IPRT status code.
+ * @param hIoQueueProv The I/O queue provider instance.
+ * @param pcReqsCommitted Where to store the number of requests actually committed.
+ */
+ DECLCALLBACKMEMBER(int, pfnCommit,(RTIOQUEUEPROV hIoQueueProv, uint32_t *pcReqsCommitted));
+
+ /**
+ * Waits for completion events from the given I/O queue.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_IOQUEUE_EMPTY if there is nothing to wait for.
+ * @param hIoQueueProv The I/O queue provider instance.
+ * @param paCEvt Pointer to the array of completion event entries to fill.
+ * @param cCEvt Size of the completion event entry array.
+ * @param cMinWait Minimum number of completion events to wait for before returning.
+ * @param pcCEvt Where to store the number of completion events on success.
+ * @param fFlags Additional flags controlling the wait behavior.
+ */
+ DECLCALLBACKMEMBER(int, pfnEvtWait,(RTIOQUEUEPROV hIoQueueProv, PRTIOQUEUECEVT paCEvt, uint32_t cCEvt,
+ uint32_t cMinWait, uint32_t *pcCEvt, uint32_t fFlags));
+
+ /**
+ * Wakes up the thread waiting in RTIOQUEUEPROVVTABLE::pfnEvtWait().
+ *
+ * @returns IPRT status code.
+ * @param hIoQueueProv The I/O queue provider instance.
+ */
+ DECLCALLBACKMEMBER(int, pfnEvtWaitWakeup,(RTIOQUEUEPROV hIoQueueProv));
+
+ /** Marks the end of the structure (RTIOQUEUEPROVVTABLE_VERSION). */
+ uintptr_t uEndMarker;
+} RTIOQUEUEPROVVTABLE;
+/** Pointer to an I/O queue provider vtable. */
+typedef RTIOQUEUEPROVVTABLE *PRTIOQUEUEPROVVTABLE;
+/** Pointer to a const I/O queue provider vtable. */
+typedef RTIOQUEUEPROVVTABLE const *PCRTIOQUEUEPROVVTABLE;
+
+/** The RTIOQUEUEPROVVTABLE structure version. */
+#define RTIOQUEUEPROVVTABLE_VERSION RT_MAKE_U32_FROM_U8(0xff,0xf,1,0)
+
+/** @name RTIOQUEUEPROVVTABLE::fFlags
+ * @{ */
+/** Provider supports S/G lists. */
+#define RTIOQUEUEPROVVTABLE_F_SG RT_BIT_32(0)
+/** Mask of the valid I/O stream feature flags. */
+#define RTIOQUEUEPROVVTABLE_F_VALID_MASK UINT32_C(0x00000001)
+/** @} */
+
+
+/**
+ * Tries to return the best I/O queue provider for the given handle type on the called
+ * host system.
+ *
+ * @returns Pointer to the I/O queue provider handle table or NULL if no suitable
+ * provider was found for the given handle type.
+ * @param enmHnd The handle type to look for a provider.
+ */
+RTDECL(PCRTIOQUEUEPROVVTABLE) RTIoQueueProviderGetBestForHndType(RTHANDLETYPE enmHnd);
+
+
+/**
+ * Returns the I/O queue provider with the given ID.
+ *
+ * @returns Pointer to the I/O queue provider handle table or NULL if no provider with
+ * the given ID was found.
+ * @param pszId The ID to look for.
+ */
+RTDECL(PCRTIOQUEUEPROVVTABLE) RTIoQueueProviderGetById(const char *pszId);
+
+
+/**
+ * Creates a new I/O queue with the given consumer.
+ *
+ * @returns IPRT status code.
+ * @param phIoQueue Where to store the handle to the I/O queue on success.
+ * @param pProvVTable The I/O queue provider vtable which will process the requests.
+ * @param fFlags Flags for the queue (MBZ for now).
+ * @param cSqEntries Number of entries for the submission queue.
+ * @param cCqEntries Number of entries for the completion queue.
+ *
+ * @note The number of submission and completion queue entries serve only as a hint to the
+ * provider implementation. It may decide to align the number to a smaller or greater
+ * size.
+ */
+RTDECL(int) RTIoQueueCreate(PRTIOQUEUE phIoQueue, PCRTIOQUEUEPROVVTABLE pProvVTable,
+ uint32_t fFlags, uint32_t cSqEntries, uint32_t cCqEntries);
+
+
+/**
+ * Destroys the given I/O queue.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_IOQUEUE_BUSY if the I/O queue is still processing requests.
+ * @param hIoQueue The I/O queue handle to destroy.
+ */
+RTDECL(int) RTIoQueueDestroy(RTIOQUEUE hIoQueue);
+
+
+/**
+ * Registers the given handle for use with the I/O queue.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_ALREADY_EXISTS if the handle was already registered.
+ * @retval VERR_NOT_SUPPORTED if the handle type is not supported by the consumer
+ * for the given I/O queue.
+ * @param hIoQueue The I/O queue handle.
+ * @param pHandle The handle to register.
+ */
+RTDECL(int) RTIoQueueHandleRegister(RTIOQUEUE hIoQueue, PCRTHANDLE pHandle);
+
+
+/**
+ * Deregisters the given handle from the given I/O queue.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_IOQUEUE_HANDLE_NOT_REGISTERED if the handle wasn't registered by a call to RTIoQueueHandleRegister().
+ * @param hIoQueue The I/O queue handle.
+ * @param pHandle The handle to deregister.
+ */
+RTDECL(int) RTIoQueueHandleDeregister(RTIOQUEUE hIoQueue, PCRTHANDLE pHandle);
+
+
+/**
+ * Prepares a request for the given I/O queue.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_IOQUEUE_FULL if the I/O queue can't accept the new request because the submission queue is full.
+ * @retval VERR_IOQUEUE_HANDLE_NOT_REGISTERED if the handle wasn't registered for use with RTIoQueueHandleRegister() yet.
+ * @param hIoQueue The I/O queue handle.
+ * @param pHandle The handle the request is for.
+ * @param enmOp The operation to perform.
+ * @param off Start offset (if applicable, not all handles support/require it and will ignore it).
+ * @param pvBuf Buffer to use for read/write operations (sync ignores this).
+ * @param cbBuf Size of the buffer in bytes.
+ * @param fReqFlags Additional flags for the request.
+ * @param pvUser Opaque user data which is passed back in the completion event.
+ */
+RTDECL(int) RTIoQueueRequestPrepare(RTIOQUEUE hIoQueue, PCRTHANDLE pHandle, RTIOQUEUEOP enmOp,
+ uint64_t off, void *pvBuf, size_t cbBuf, uint32_t fReqFlags,
+ void *pvUser);
+
+
+/**
+ * Prepares a request for the given I/O queue - S/G buffer variant.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_IOQUEUE_FULL if the I/O queue can't accept the new request because the submission queue is full.
+ * @retval VERR_IOQUEUE_HANDLE_NOT_REGISTERED if the handle wasn't registered for use with RTIoQueueHandleRegister() yet.
+ * @param hIoQueue The I/O queue handle.
+ * @param pHandle The handle the request is for.
+ * @param enmOp The operation to perform.
+ * @param off Start offset (if applicable, not all handles support/require it and will ignore it).
+ * @param pSgBuf The S/G buufer to use for read/write operations (sync ignores this).
+ * @param cbSg Number of bytes to transfer from the S/G buffer.
+ * @param fReqFlags Additional flags for the request.
+ * @param pvUser Opaque user data which is passed back in the completion event.
+ */
+RTDECL(int) RTIoQueueRequestPrepareSg(RTIOQUEUE hIoQueue, PCRTHANDLE pHandle, RTIOQUEUEOP enmOp,
+ uint64_t off, PCRTSGBUF pSgBuf, size_t cbSg, uint32_t fReqFlags,
+ void *pvUser);
+
+
+/**
+ * Commits all prepared requests to the consumer for processing.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_IOQUEUE_EMPTY if there is nothing to commit.
+ * @param hIoQueue The I/O queue handle.
+ */
+RTDECL(int) RTIoQueueCommit(RTIOQUEUE hIoQueue);
+
+
+/**
+ * Waits for completion events from the given I/O queue.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_IOQUEUE_EMPTY if there is nothing to wait for.
+ * @param hIoQueue The I/O queue handle.
+ * @param paCEvt Pointer to the array of completion event entries to fill.
+ * @param cCEvt Size of the completion event entry array.
+ * @param cMinWait Minimum number of completion events to wait for before returning.
+ * @param pcCEvt Where to store the number of completion events on success.
+ * @param fFlags Additional flags controlling the wait behavior.
+ */
+RTDECL(int) RTIoQueueEvtWait(RTIOQUEUE hIoQueue, PRTIOQUEUECEVT paCEvt, uint32_t cCEvt, uint32_t cMinWait,
+ uint32_t *pcCEvt, uint32_t fFlags);
+
+
+/**
+ * Wakes up the thread waiting in RTIoQueueEvtWait().
+ *
+ * @returns IPRT status code.
+ * @param hIoQueue The I/O queue handle to wake up.
+ */
+RTDECL(int) RTIoQueueEvtWaitWakeup(RTIOQUEUE hIoQueue);
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_ioqueue_h */
+
diff --git a/include/iprt/json.h b/include/iprt/json.h
new file mode 100644
index 00000000..df588736
--- /dev/null
+++ b/include/iprt/json.h
@@ -0,0 +1,384 @@
+/** @file
+ * IPRT - JavaScript Object Notation (JSON) Parser.
+ */
+
+/*
+ * Copyright (C) 2016-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_json_h
+#define IPRT_INCLUDED_json_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+
+RT_C_DECLS_BEGIN
+
+
+/** @defgroup grp_json RTJson - JavaScript Object Notation (JSON) Parser
+ * @ingroup grp_rt
+ * @{
+ */
+
+/**
+ * JSON value types.
+ */
+typedef enum RTJSONVALTYPE
+{
+ /** Invalid first value. */
+ RTJSONVALTYPE_INVALID = 0,
+ /** Value containing an object. */
+ RTJSONVALTYPE_OBJECT,
+ /** Value containing an array. */
+ RTJSONVALTYPE_ARRAY,
+ /** Value containing a string. */
+ RTJSONVALTYPE_STRING,
+ /** Value containg an integer number. */
+ RTJSONVALTYPE_INTEGER,
+ /** Value containg an floating point number. */
+ RTJSONVALTYPE_NUMBER,
+ /** Value containg the special null value. */
+ RTJSONVALTYPE_NULL,
+ /** Value containing true. */
+ RTJSONVALTYPE_TRUE,
+ /** Value containing false. */
+ RTJSONVALTYPE_FALSE,
+ /** 32-bit hack. */
+ RTJSONVALTYPE_32BIT_HACK = 0x7fffffff
+} RTJSONVALTYPE;
+/** Pointer to a JSON value type. */
+typedef RTJSONVALTYPE *PRTJSONVALTYPE;
+
+/** JSON value handle. */
+typedef struct RTJSONVALINT *RTJSONVAL;
+/** Pointer to a JSON value handle. */
+typedef RTJSONVAL *PRTJSONVAL;
+/** NIL JSON value handle. */
+#define NIL_RTJSONVAL ((RTJSONVAL)~(uintptr_t)0)
+
+/** JSON iterator handle. */
+typedef struct RTJSONITINT *RTJSONIT;
+/** Pointer to a JSON iterator handle. */
+typedef RTJSONIT *PRTJSONIT;
+/** NIL JSON iterator handle. */
+#define NIL_RTJSONIT ((RTJSONIT)~(uintptr_t)0)
+
+/**
+ * Parses a JSON document in the provided buffer returning the root JSON value.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_JSON_MALFORMED if the document does not conform to the spec.
+ * @param phJsonVal Where to store the handle to the JSON value on success.
+ * @param pbBuf The byte buffer containing the JSON document.
+ * @param cbBuf Size of the buffer.
+ * @param pErrInfo Where to store extended error info. Optional.
+ *
+ * @todo r=bird: The use of uint8_t makes no sense here since the parser
+ * expects ASCII / UTF-8. What's more, if this is a real buffer the
+ * type should be 'const void *' rather than 'const uint8_t *'.
+ * This function should be modified to reflect that it's really for
+ * handling unterminated strings.
+ */
+RTDECL(int) RTJsonParseFromBuf(PRTJSONVAL phJsonVal, const uint8_t *pbBuf, size_t cbBuf, PRTERRINFO pErrInfo);
+
+/**
+ * Parses a JSON document from the provided string returning the root JSON value.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_JSON_MALFORMED if the document does not conform to the spec.
+ * @param phJsonVal Where to store the handle to the JSON value on success.
+ * @param pszStr The string containing the JSON document.
+ * @param pErrInfo Where to store extended error info. Optional.
+ */
+RTDECL(int) RTJsonParseFromString(PRTJSONVAL phJsonVal, const char *pszStr, PRTERRINFO pErrInfo);
+
+/**
+ * Parses a JSON document from the file pointed to by the given filename
+ * returning the root JSON value.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_JSON_MALFORMED if the document does not conform to the spec.
+ * @param phJsonVal Where to store the handle to the JSON value on success.
+ * @param pszFilename The name of the file containing the JSON document.
+ * @param pErrInfo Where to store extended error info. Optional.
+ */
+RTDECL(int) RTJsonParseFromFile(PRTJSONVAL phJsonVal, const char *pszFilename, PRTERRINFO pErrInfo);
+
+/**
+ * Parses a JSON document from the given VFS file
+ * returning the root JSON value.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_JSON_MALFORMED if the document does not conform to the spec.
+ * @param phJsonVal Where to store the handle to the JSON value on success.
+ * @param hVfsFile The VFS file to parse.
+ * @param pErrInfo Where to store extended error info. Optional.
+ */
+RTDECL(int) RTJsonParseFromVfsFile(PRTJSONVAL phJsonVal, RTVFSFILE hVfsFile, PRTERRINFO pErrInfo);
+
+/**
+ * Retain a given JSON value.
+ *
+ * @returns New reference count.
+ * @param hJsonVal The JSON value handle.
+ */
+RTDECL(uint32_t) RTJsonValueRetain(RTJSONVAL hJsonVal);
+
+/**
+ * Release a given JSON value.
+ *
+ * @returns New reference count, if this drops to 0 the value is freed.
+ * @param hJsonVal The JSON value handle.
+ */
+RTDECL(uint32_t) RTJsonValueRelease(RTJSONVAL hJsonVal);
+
+/**
+ * Return the type of a given JSON value.
+ *
+ * @returns Type of the given JSON value.
+ * @param hJsonVal The JSON value handle.
+ */
+RTDECL(RTJSONVALTYPE) RTJsonValueGetType(RTJSONVAL hJsonVal);
+
+/**
+ * Translates value type to a name.
+ *
+ * @returns Readonly name string
+ * @param enmType The JSON value type to name.
+ */
+RTDECL(const char *) RTJsonValueTypeName(RTJSONVALTYPE enmType);
+
+/**
+ * Returns the string from a given JSON string value.
+ *
+ * @returns Pointer to the string of the JSON value, NULL if the value type
+ * doesn't indicate a string.
+ * @param hJsonVal The JSON value handle.
+ */
+RTDECL(const char *) RTJsonValueGetString(RTJSONVAL hJsonVal);
+
+/**
+ * Returns the string from a given JSON string value, extended.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_JSON_VALUE_INVALID_TYPE if the JSON value is not a string.
+ * @param hJsonVal The JSON value handle.
+ * @param ppszStr Where to store the pointer to the string on success.
+ */
+RTDECL(int) RTJsonValueQueryString(RTJSONVAL hJsonVal, const char **ppszStr);
+
+/**
+ * Returns the integer from a given JSON integer value.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_JSON_VALUE_INVALID_TYPE if the JSON value is not a number.
+ * @param hJsonVal The JSON value handle.
+ * @param pi64Num WHere to store the number on success.
+ * @sa RTJsonValueQueryNumber
+ */
+RTDECL(int) RTJsonValueQueryInteger(RTJSONVAL hJsonVal, int64_t *pi64Num);
+
+/**
+ * Returns the floating point value from a given JSON number value.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_JSON_VALUE_INVALID_TYPE if the JSON value is not a number.
+ * @param hJsonVal The JSON value handle.
+ * @param prdNum WHere to store the floating point number on success.
+ * @sa RTJsonValueQueryInteger
+ */
+RTDECL(int) RTJsonValueQueryNumber(RTJSONVAL hJsonVal, double *prdNum);
+
+/**
+ * Returns the value associated with a given name for the given JSON object value.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_JSON_VALUE_INVALID_TYPE if the JSON value is not an object.
+ * @retval VERR_NOT_FOUND if the name is not known for this JSON object.
+ * @param hJsonVal The JSON value handle.
+ * @param pszName The member name of the object.
+ * @param phJsonVal Where to store the handle to the JSON value on success.
+ */
+RTDECL(int) RTJsonValueQueryByName(RTJSONVAL hJsonVal, const char *pszName, PRTJSONVAL phJsonVal);
+
+/**
+ * Returns the number of a number value associated with a given name for the given JSON object value.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_JSON_VALUE_INVALID_TYPE if the JSON value is not an object or
+ * the name does not point to an integer value.
+ * @retval VERR_NOT_FOUND if the name is not known for this JSON object.
+ * @param hJsonVal The JSON value handle.
+ * @param pszName The member name of the object.
+ * @param pi64Num Where to store the number on success.
+ */
+RTDECL(int) RTJsonValueQueryIntegerByName(RTJSONVAL hJsonVal, const char *pszName, int64_t *pi64Num);
+
+/**
+ * Returns the number of a number value associated with a given name for the given JSON object value.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_JSON_VALUE_INVALID_TYPE if the JSON value is not an object or
+ * the name does not point to a number value.
+ * @retval VERR_NOT_FOUND if the name is not known for this JSON object.
+ * @param hJsonVal The JSON value handle.
+ * @param pszName The member name of the object.
+ * @param prdNum WHere to store the floating point number on success.
+ */
+RTDECL(int) RTJsonValueQueryNumberByName(RTJSONVAL hJsonVal, const char *pszName, double *prdNum);
+
+/**
+ * Returns the string of a string value associated with a given name for the given JSON object value.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_JSON_VALUE_INVALID_TYPE if the JSON value is not an object or
+ * the name does not point to a string value.
+ * @retval VERR_NOT_FOUND if the name is not known for this JSON object.
+ * @param hJsonVal The JSON value handle.
+ * @param pszName The member name of the object.
+ * @param ppszStr Where to store the pointer to the string on success.
+ * Must be freed with RTStrFree().
+ */
+RTDECL(int) RTJsonValueQueryStringByName(RTJSONVAL hJsonVal, const char *pszName, char **ppszStr);
+
+/**
+ * Returns the boolean of a true/false value associated with a given name for the given JSON object value.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_JSON_VALUE_INVALID_TYPE if the JSON value is not an object or
+ * the name does not point to a true/false value.
+ * @retval VERR_NOT_FOUND if the name is not known for this JSON object.
+ * @param hJsonVal The JSON value handle.
+ * @param pszName The member name of the object.
+ * @param pfBoolean Where to store the boolean value on success.
+ */
+RTDECL(int) RTJsonValueQueryBooleanByName(RTJSONVAL hJsonVal, const char *pszName, bool *pfBoolean);
+
+/**
+ * Returns the size of a given JSON array value.
+ *
+ * @returns Size of the JSON array value.
+ * @retval 0 if the array is empty or the JSON value is not an array.
+ * @param hJsonVal The JSON value handle.
+ */
+RTDECL(unsigned) RTJsonValueGetArraySize(RTJSONVAL hJsonVal);
+
+/**
+ * Returns the size of a given JSON array value - extended version.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_JSON_VALUE_INVALID_TYPE if the JSON value is not an array.
+ * @param hJsonVal The JSON value handle.
+ * @param pcItems Where to store the size of the JSON array value on success.
+ */
+RTDECL(int) RTJsonValueQueryArraySize(RTJSONVAL hJsonVal, unsigned *pcItems);
+
+/**
+ * Returns the value for the given index of a given JSON array value.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_JSON_VALUE_INVALID_TYPE if the JSON value is not an array.
+ * @retval VERR_OUT_OF_RANGE if @a idx is out of bounds.
+ *
+ * @param hJsonVal The JSON value handle.
+ * @param idx The index to get the value from.
+ * @param phJsonVal Where to store the handle to the JSON value on success.
+ */
+RTDECL(int) RTJsonValueQueryByIndex(RTJSONVAL hJsonVal, unsigned idx, PRTJSONVAL phJsonVal);
+
+/**
+ * Creates an iterator for a given JSON array or object value.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_JSON_VALUE_INVALID_TYPE if the JSON value is not an array or
+ * object.
+ * @param hJsonVal The JSON value handle.
+ * @param phJsonIt Where to store the JSON iterator handle on success.
+ * @todo Make return VERR_JSON_IS_EMPTY (or remove it).
+ */
+RTDECL(int) RTJsonIteratorBegin(RTJSONVAL hJsonVal, PRTJSONIT phJsonIt);
+
+/**
+ * Creates an iterator for a given JSON array value.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_JSON_VALUE_INVALID_TYPE if the JSON value is not an array.
+ * @retval VERR_JSON_IS_EMPTY if no members.
+ * @param hJsonVal The JSON value handle.
+ * @param phJsonIt Where to store the JSON iterator handle on success.
+ */
+RTDECL(int) RTJsonIteratorBeginArray(RTJSONVAL hJsonVal, PRTJSONIT phJsonIt);
+
+/**
+ * Creates an iterator for a given JSON object value.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_JSON_VALUE_INVALID_TYPE if the JSON value is not an object.
+ * @retval VERR_JSON_IS_EMPTY if no members.
+ * @param hJsonVal The JSON value handle.
+ * @param phJsonIt Where to store the JSON iterator handle on success.
+ */
+RTDECL(int) RTJsonIteratorBeginObject(RTJSONVAL hJsonVal, PRTJSONIT phJsonIt);
+
+/**
+ * Gets the value and optional name for the current iterator position.
+ *
+ * @returns IPRT status code.
+ * @param hJsonIt The JSON iterator handle.
+ * @param phJsonVal Where to store the handle to the JSON value on success.
+ * @param ppszName Where to store the object member name for an object.
+ * NULL is returned for arrays.
+ */
+RTDECL(int) RTJsonIteratorQueryValue(RTJSONIT hJsonIt, PRTJSONVAL phJsonVal, const char **ppszName);
+
+/**
+ * Advances to the next element in the referenced JSON value.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_JSON_ITERATOR_END if the end for this iterator was reached.
+ * @param hJsonIt The JSON iterator handle.
+ */
+RTDECL(int) RTJsonIteratorNext(RTJSONIT hJsonIt);
+
+/**
+ * Frees a given JSON iterator.
+ *
+ * @param hJsonIt The JSON iterator to free.
+ */
+RTDECL(void) RTJsonIteratorFree(RTJSONIT hJsonIt);
+
+RT_C_DECLS_END
+
+/** @} */
+
+#endif /* !IPRT_INCLUDED_json_h */
+
diff --git a/include/iprt/krnlmod.h b/include/iprt/krnlmod.h
new file mode 100644
index 00000000..9b1eb12c
--- /dev/null
+++ b/include/iprt/krnlmod.h
@@ -0,0 +1,202 @@
+/** @file
+ * IPRT - Kernel module.
+ */
+
+/*
+ * Copyright (C) 2017-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_krnlmod_h
+#define IPRT_INCLUDED_krnlmod_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_kmod RTKrnlMod - Kernel module/driver userspace side API.
+ * @ingroup grp_rt
+ * @{
+ */
+
+/**
+ * Checks whether the given kernel module was loaded.
+ *
+ * @returns IPRT status code.
+ * @param pszName The driver name to check.
+ * @param pfLoaded Where to store the flag whether the module is loaded on success.
+ */
+RTDECL(int) RTKrnlModQueryLoaded(const char *pszName, bool *pfLoaded);
+
+/**
+ * Returns the kernel module information handle for the given loaded kernel module.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_NOT_FOUND if the kernel driver is not loaded.
+ * @param pszName The driver name.
+ * @param phKrnlModInfo Where to store the handle to the kernel module information record.
+ */
+RTDECL(int) RTKrnlModLoadedQueryInfo(const char *pszName, PRTKRNLMODINFO phKrnlModInfo);
+
+/**
+ * Returns the number of kernel modules loaded on the host system.
+ *
+ * @returns Number of kernel modules loaded.
+ */
+RTDECL(uint32_t) RTKrnlModLoadedGetCount(void);
+
+/**
+ * Returns all loaded kernel modules on the host.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_BUFFER_OVERFLOW if there are not enough entries in the passed handle array.
+ * The required number of entries will be returned in pcEntries.
+ * @param pahKrnlModInfo Where to store the handles to the kernel module information records
+ * on success.
+ * @param cEntriesMax Maximum number of entries fitting in the given array.
+ * @param pcEntries Where to store the number of entries used/required.
+ */
+RTDECL(int) RTKrnlModLoadedQueryInfoAll(PRTKRNLMODINFO pahKrnlModInfo, uint32_t cEntriesMax,
+ uint32_t *pcEntries);
+
+/**
+ * Retains the given kernel module information record handle.
+ *
+ * @returns New reference count.
+ * @param hKrnlModInfo The kernel module information record handle.
+ */
+RTDECL(uint32_t) RTKrnlModInfoRetain(RTKRNLMODINFO hKrnlModInfo);
+
+/**
+ * Releases the given kernel module information record handle.
+ *
+ * @returns New reference count, on 0 the handle is destroyed.
+ * @param hKrnlModInfo The kernel module information record handle.
+ */
+RTDECL(uint32_t) RTKrnlModInfoRelease(RTKRNLMODINFO hKrnlModInfo);
+
+/**
+ * Returns the number of references held onto the kernel module by other
+ * drivers or userspace clients.
+ *
+ * @returns Number of references held on the kernel module.
+ * @param hKrnlModInfo The kernel module information record handle.
+ */
+RTDECL(uint32_t) RTKrnlModInfoGetRefCnt(RTKRNLMODINFO hKrnlModInfo);
+
+/**
+ * Returns the name of the kernel module.
+ *
+ * @returns Pointer to the kernel module name.
+ * @param hKrnlModInfo The kernel module information record handle.
+ */
+RTDECL(const char *) RTKrnlModInfoGetName(RTKRNLMODINFO hKrnlModInfo);
+
+/**
+ * Returns the filepath of the kernel module.
+ *
+ * @returns Pointer to the kernel module path.
+ * @param hKrnlModInfo The kernel module information record handle.
+ */
+RTDECL(const char *) RTKrnlModInfoGetFilePath(RTKRNLMODINFO hKrnlModInfo);
+
+/**
+ * Returns the size of the kernel module.
+ *
+ * @returns Size of the kernel module in bytes.
+ * @param hKrnlModInfo The kernel module information record handle.
+ */
+RTDECL(size_t) RTKrnlModInfoGetSize(RTKRNLMODINFO hKrnlModInfo);
+
+/**
+ * Returns the load address of the kernel module.
+ *
+ * @returns Load address of the kernel module.
+ * @param hKrnlModInfo The kernel module information record handle.
+ */
+RTDECL(RTR0UINTPTR) RTKrnlModInfoGetLoadAddr(RTKRNLMODINFO hKrnlModInfo);
+
+/**
+ * Query the kernel information record for a referencing kernel module of the
+ * given record.
+ *
+ * @returns IPRT status code.
+ * @param hKrnlModInfo The kernel module information record handle.
+ * @param idx Referencing kernel module index (< reference count
+ * as retrieved by RTKrnlModInfoGetRefCnt() ).
+ * @param phKrnlModInfoRef Where to store the handle to the referencing kernel module
+ * information record.
+ */
+RTDECL(int) RTKrnlModInfoQueryRefModInfo(RTKRNLMODINFO hKrnlModInfo, uint32_t idx,
+ PRTKRNLMODINFO phKrnlModInfoRef);
+
+/**
+ * Tries to load a kernel module by the given name.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_NOT_SUPPORTED if not supported by or implemented for the platform.
+ * @param pszName The name of the kernel module. This is highly platform
+ * dependent.
+ *
+ * @note On macOS for example the name is the bundle ID.
+ */
+RTDECL(int) RTKrnlModLoadByName(const char *pszName);
+
+/**
+ * Tries to load a kernel module by the given file path.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_NOT_SUPPORTED if not supported by or implemented for the platform.
+ * @param pszPath The path of the kernel module.
+ */
+RTDECL(int) RTKrnlModLoadByPath(const char *pszPath);
+
+/**
+ * Tries to unload a kernel module by the given name.
+ *
+ * @returns IPRT status code.
+ * @param pszName The name of the kernel module. This is highly platform
+ * dependent and should be queried with RTKrnlModInfoGetName()
+ * when checking whether the module was actually loaded.
+ *
+ * @note On macOS for example the name is the bundle ID.
+ */
+RTDECL(int) RTKrnlModUnloadByName(const char *pszName);
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_krnlmod_h */
+
diff --git a/include/iprt/latin1.h b/include/iprt/latin1.h
new file mode 100644
index 00000000..074c1e65
--- /dev/null
+++ b/include/iprt/latin1.h
@@ -0,0 +1,404 @@
+/** @file
+ * IPRT - String Manipulation, Latin-1 (ISO-8859-1) encoding.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_latin1_h
+#define IPRT_INCLUDED_latin1_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/assert.h>
+#include <iprt/errcore.h> /* VERR_END_OF_STRING */
+
+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 /* !IPRT_INCLUDED_latin1_h */
+
diff --git a/include/iprt/ldr.h b/include/iprt/ldr.h
new file mode 100644
index 00000000..aa67646e
--- /dev/null
+++ b/include/iprt/ldr.h
@@ -0,0 +1,1340 @@
+/** @file
+ * IPRT - Loader.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_ldr_h
+#define IPRT_INCLUDED_ldr_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+
+
+/** @defgroup grp_ldr RTLdr - Loader
+ * @ingroup grp_rt
+ * @{
+ */
+
+
+RT_C_DECLS_BEGIN
+
+/** Loader address (unsigned integer). */
+typedef RTUINTPTR RTLDRADDR;
+/** Pointer to a loader address. */
+typedef RTLDRADDR *PRTLDRADDR;
+/** Pointer to a const loader address. */
+typedef RTLDRADDR const *PCRTLDRADDR;
+/** The max loader address value. */
+#define RTLDRADDR_MAX RTUINTPTR_MAX
+/** NIL loader address value. */
+#define NIL_RTLDRADDR RTLDRADDR_MAX
+
+
+/**
+ * Loader module format.
+ */
+typedef enum RTLDRFMT
+{
+ /** The usual invalid 0 format. */
+ RTLDRFMT_INVALID = 0,
+ /** The native OS loader. */
+ RTLDRFMT_NATIVE,
+ /** The AOUT loader. */
+ RTLDRFMT_AOUT,
+ /** The ELF loader. */
+ RTLDRFMT_ELF,
+ /** The LX loader. */
+ RTLDRFMT_LX,
+ /** The Mach-O loader. */
+ RTLDRFMT_MACHO,
+ /** The PE loader. */
+ RTLDRFMT_PE,
+ /** The end of the valid format values (exclusive). */
+ RTLDRFMT_END,
+ /** Hack to blow the type up to 32-bit. */
+ RTLDRFMT_32BIT_HACK = 0x7fffffff
+} RTLDRFMT;
+
+
+/**
+ * Loader module type.
+ */
+typedef enum RTLDRTYPE
+{
+ /** The usual invalid 0 type. */
+ RTLDRTYPE_INVALID = 0,
+ /** Object file. */
+ RTLDRTYPE_OBJECT,
+ /** Executable module, fixed load address. */
+ RTLDRTYPE_EXECUTABLE_FIXED,
+ /** Executable module, relocatable, non-fixed load address. */
+ RTLDRTYPE_EXECUTABLE_RELOCATABLE,
+ /** Executable module, position independent code, non-fixed load address. */
+ RTLDRTYPE_EXECUTABLE_PIC,
+ /** Shared library, fixed load address.
+ * Typically a system library. */
+ RTLDRTYPE_SHARED_LIBRARY_FIXED,
+ /** Shared library, relocatable, non-fixed load address. */
+ RTLDRTYPE_SHARED_LIBRARY_RELOCATABLE,
+ /** Shared library, position independent code, non-fixed load address. */
+ RTLDRTYPE_SHARED_LIBRARY_PIC,
+ /** DLL that contains no code or data only imports and exports. (Chiefly OS/2.) */
+ RTLDRTYPE_FORWARDER_DLL,
+ /** Core or dump. */
+ RTLDRTYPE_CORE,
+ /** Debug module (debug info with empty code & data segments). */
+ RTLDRTYPE_DEBUG_INFO,
+ /** The end of the valid types values (exclusive). */
+ RTLDRTYPE_END,
+ /** Hack to blow the type up to 32-bit. */
+ RTLDRTYPE_32BIT_HACK = 0x7fffffff
+} RTLDRTYPE;
+
+
+/**
+ * Loader endian indicator.
+ */
+typedef enum RTLDRENDIAN
+{
+ /** The usual invalid endian. */
+ RTLDRENDIAN_INVALID,
+ /** Little endian. */
+ RTLDRENDIAN_LITTLE,
+ /** Bit endian. */
+ RTLDRENDIAN_BIG,
+ /** Endianness doesn't have a meaning in the context. */
+ RTLDRENDIAN_NA,
+ /** The end of the valid endian values (exclusive). */
+ RTLDRENDIAN_END,
+ /** Hack to blow the type up to 32-bit. */
+ RTLDRENDIAN_32BIT_HACK = 0x7fffffff
+} RTLDRENDIAN;
+
+
+/** Pointer to a loader reader instance. */
+typedef struct RTLDRREADER *PRTLDRREADER;
+/**
+ * Loader image reader instance.
+ *
+ * @remarks The reader will typically have a larger structure wrapping this one
+ * for storing necessary instance variables.
+ *
+ * The loader ASSUMES the caller serializes all access to the
+ * individual loader module handlers, thus no serialization is required
+ * when implementing this interface.
+ */
+typedef struct RTLDRREADER
+{
+ /** Magic value (RTLDRREADER_MAGIC). */
+ uintptr_t uMagic;
+
+ /**
+ * Reads bytes at a give place in the raw image.
+ *
+ * @returns iprt status code.
+ * @param pReader Pointer to the reader instance.
+ * @param pvBuf Where to store the bits.
+ * @param cb Number of bytes to read.
+ * @param off Where to start reading relative to the start of the raw image.
+ */
+ DECLCALLBACKMEMBER(int, pfnRead,(PRTLDRREADER pReader, void *pvBuf, size_t cb, RTFOFF off));
+
+ /**
+ * Tells end position of last read.
+ *
+ * @returns position relative to start of the raw image.
+ * @param pReader Pointer to the reader instance.
+ */
+ DECLCALLBACKMEMBER(RTFOFF, pfnTell,(PRTLDRREADER pReader));
+
+ /**
+ * Gets the size of the raw image bits.
+ *
+ * @returns size of raw image bits in bytes.
+ * @param pReader Pointer to the reader instance.
+ */
+ DECLCALLBACKMEMBER(uint64_t, pfnSize,(PRTLDRREADER pReader));
+
+ /**
+ * Map the bits into memory.
+ *
+ * The mapping will be freed upon calling pfnDestroy() if not pfnUnmap()
+ * is called before that. The mapping is read only.
+ *
+ * @returns iprt status code.
+ * @param pReader Pointer to the reader instance.
+ * @param ppvBits Where to store the address of the memory mapping on success.
+ * The size of the mapping can be obtained by calling pfnSize().
+ */
+ DECLCALLBACKMEMBER(int, pfnMap,(PRTLDRREADER pReader, const void **ppvBits));
+
+ /**
+ * Unmap bits.
+ *
+ * @returns iprt status code.
+ * @param pReader Pointer to the reader instance.
+ * @param pvBits Memory pointer returned by pfnMap().
+ */
+ DECLCALLBACKMEMBER(int, pfnUnmap,(PRTLDRREADER pReader, const void *pvBits));
+
+ /**
+ * Gets the most appropriate log name.
+ *
+ * @returns Pointer to readonly log name.
+ * @param pReader Pointer to the reader instance.
+ */
+ DECLCALLBACKMEMBER(const char *, pfnLogName,(PRTLDRREADER pReader));
+
+ /**
+ * Releases all resources associated with the reader instance.
+ * The instance is invalid after this call returns.
+ *
+ * @returns iprt status code.
+ * @param pReader Pointer to the reader instance.
+ */
+ DECLCALLBACKMEMBER(int, pfnDestroy,(PRTLDRREADER pReader));
+} RTLDRREADER;
+
+/** Magic value for RTLDRREADER (Gordon Matthew Thomas Sumner / Sting). */
+#define RTLDRREADER_MAGIC UINT32_C(0x19511002)
+
+
+/**
+ * Gets the default file suffix for DLL/SO/DYLIB/whatever.
+ *
+ * @returns The stuff (readonly).
+ */
+RTDECL(const char *) RTLdrGetSuff(void);
+
+/**
+ * Checks if a library is loadable or not.
+ *
+ * This may attempt load and unload the library.
+ *
+ * @returns true/false accordingly.
+ * @param pszFilename Image filename.
+ */
+RTDECL(bool) RTLdrIsLoadable(const char *pszFilename);
+
+/**
+ * Loads a dynamic load library (/shared object) image file using native
+ * OS facilities.
+ *
+ * The filename will be appended the default DLL/SO extension of
+ * the platform if it have been omitted. This means that it's not
+ * possible to load DLLs/SOs with no extension using this interface,
+ * but that's not a bad tradeoff.
+ *
+ * If no path is specified in the filename, the OS will usually search it's library
+ * path to find the image file.
+ *
+ * @returns iprt status code.
+ * @param pszFilename Image filename.
+ * @param phLdrMod Where to store the handle to the loader module.
+ */
+RTDECL(int) RTLdrLoad(const char *pszFilename, PRTLDRMOD phLdrMod);
+
+/**
+ * Loads a dynamic load library (/shared object) image file using native
+ * OS facilities.
+ *
+ * The filename will be appended the default DLL/SO extension of
+ * the platform if it have been omitted. This means that it's not
+ * possible to load DLLs/SOs with no extension using this interface,
+ * but that's not a bad tradeoff.
+ *
+ * If no path is specified in the filename, the OS will usually search it's library
+ * path to find the image file.
+ *
+ * @returns iprt status code.
+ * @param pszFilename Image filename.
+ * @param phLdrMod Where to store the handle to the loader module.
+ * @param fFlags See RTLDRLOAD_FLAGS_XXX.
+ * @param pErrInfo Where to return extended error information. Optional.
+ */
+RTDECL(int) RTLdrLoadEx(const char *pszFilename, PRTLDRMOD phLdrMod, uint32_t fFlags, PRTERRINFO pErrInfo);
+
+/** @defgroup RTLDRLOAD_FLAGS_XXX Flags for RTLdrLoadEx, RTLdrLoadSystemEx and RTLdrGetSystemSymbolEx
+ * @{ */
+/** Symbols defined in this library are not made available to resolve
+ * references in subsequently loaded libraries (default). */
+#define RTLDRLOAD_FLAGS_LOCAL UINT32_C(0)
+/** Symbols defined in this library will be made available for symbol
+ * resolution of subsequently loaded libraries. */
+#define RTLDRLOAD_FLAGS_GLOBAL RT_BIT_32(0)
+/** Do not unload the library upon RTLdrClose. (For system libs.) */
+#define RTLDRLOAD_FLAGS_NO_UNLOAD RT_BIT_32(1)
+/** Windows/NT: Search the DLL load directory for imported DLLs - W7,
+ * Vista, and W2K8 requires KB2533623 to be installed to support this; not
+ * supported on XP, W2K3 or earlier. Ignored on other platforms. */
+#define RTLDRLOAD_FLAGS_NT_SEARCH_DLL_LOAD_DIR RT_BIT_32(2)
+/** Do not append default suffix. */
+#define RTLDRLOAD_FLAGS_NO_SUFFIX RT_BIT_32(3)
+/** Shift for the first .so.MAJOR version number to try.
+ * Only applicable to RTLdrLoadSystemEx() and RTLdrGetSystemSymbolEx(). */
+#define RTLDRLOAD_FLAGS_SO_VER_BEGIN_SHIFT 12
+/** Mask for the first .so.MAJOR version number to try.
+ * Only applicable to RTLdrLoadSystemEx() and RTLdrGetSystemSymbolEx(). */
+#define RTLDRLOAD_FLAGS_SO_VER_BEGIN_MASK UINT32_C(0x003ff000)
+/** Shift for the end .so.MAJOR version number (exclusive).
+ * Only applicable to RTLdrLoadSystemEx() and RTLdrGetSystemSymbolEx(). */
+#define RTLDRLOAD_FLAGS_SO_VER_END_SHIFT 22
+/** Mask for the end .so.MAJOR version number (exclusive).
+ * Only applicable to RTLdrLoadSystemEx() and RTLdrGetSystemSymbolEx(). */
+#define RTLDRLOAD_FLAGS_SO_VER_END_MASK UINT32_C(0xffc00000)
+/** Specifies the range for the .so.MAJOR version number.
+ * Only applicable to RTLdrLoadSystemEx() and RTLdrGetSystemSymbolEx().
+ * Ignored on systems not using .so.
+ * @param a_uBegin The first version to try.
+ * @param a_uEnd The version number to stop at (exclusive).
+ */
+#define RTLDRLOAD_FLAGS_SO_VER_RANGE(a_uBegin, a_uEnd) \
+ ( ((a_uBegin) << RTLDRLOAD_FLAGS_SO_VER_BEGIN_SHIFT) | ((a_uEnd) << RTLDRLOAD_FLAGS_SO_VER_END_SHIFT) )
+/** The mask of valid flag bits.
+ * The shared object major version range is excluded. */
+#define RTLDRLOAD_FLAGS_VALID_MASK UINT32_C(0x0000000f)
+/** @} */
+
+/**
+ * Loads a dynamic load library (/shared object) image file residing in one of
+ * the default system library locations.
+ *
+ * Only the system library locations are searched. No suffix is required.
+ *
+ * @returns iprt status code.
+ * @param pszFilename Image filename. No path.
+ * @param fNoUnload Do not unload the library when RTLdrClose is called.
+ * @param phLdrMod Where to store the handle to the loaded module.
+ */
+RTDECL(int) RTLdrLoadSystem(const char *pszFilename, bool fNoUnload, PRTLDRMOD phLdrMod);
+
+/**
+ * Loads a dynamic load library (/shared object) image file residing in one of
+ * the default system library locations, extended version.
+ *
+ * Only the system library locations are searched. No suffix is required.
+ *
+ * @returns iprt status code.
+ * @param pszFilename Image filename. No path.
+ * @param fFlags RTLDRLOAD_FLAGS_XXX, including RTLDRLOAD_FLAGS_SO_VER_XXX.
+ * @param phLdrMod Where to store the handle to the loaded module.
+ */
+RTDECL(int) RTLdrLoadSystemEx(const char *pszFilename, uint32_t fFlags, PRTLDRMOD phLdrMod);
+
+/**
+ * Combines RTLdrLoadSystem and RTLdrGetSymbol, with fNoUnload set to true.
+ *
+ * @returns The symbol value, NULL on failure. (If you care for a less boolean
+ * status, go thru the necessary API calls yourself.)
+ * @param pszFilename Image filename. No path.
+ * @param pszSymbol Symbol name.
+ */
+RTDECL(void *) RTLdrGetSystemSymbol(const char *pszFilename, const char *pszSymbol);
+
+/**
+ * Combines RTLdrLoadSystemEx and RTLdrGetSymbol.
+ *
+ * @returns The symbol value, NULL on failure. (If you care for a less boolean
+ * status, go thru the necessary API calls yourself.)
+ * @param pszFilename Image filename. No path.
+ * @param pszSymbol Symbol name.
+ * @param fFlags RTLDRLOAD_FLAGS_XXX, including RTLDRLOAD_FLAGS_SO_VER_XXX.
+ */
+RTDECL(void *) RTLdrGetSystemSymbolEx(const char *pszFilename, const char *pszSymbol, uint32_t fFlags);
+
+/**
+ * Loads a dynamic load library (/shared object) image file residing in the
+ * RTPathAppPrivateArch() directory.
+ *
+ * Suffix is not required.
+ *
+ * @returns iprt status code.
+ * @param pszFilename Image filename. No path.
+ * @param phLdrMod Where to store the handle to the loaded module.
+ */
+RTDECL(int) RTLdrLoadAppPriv(const char *pszFilename, PRTLDRMOD phLdrMod);
+
+/**
+ * Gets the native module handle for a module loaded by RTLdrLoad, RTLdrLoadEx,
+ * RTLdrLoadSystem, or RTLdrLoadAppPriv.
+ *
+ * @returns Native handle on success, ~(uintptr_t)0 on failure.
+ * @param hLdrMod The loader module handle.
+ */
+RTDECL(uintptr_t) RTLdrGetNativeHandle(RTLDRMOD hLdrMod);
+
+
+/**
+ * Image architecuture specifier for RTLdrOpenEx.
+ */
+typedef enum RTLDRARCH
+{
+ RTLDRARCH_INVALID = 0,
+ /** Whatever. */
+ RTLDRARCH_WHATEVER,
+ /** The host architecture. */
+ RTLDRARCH_HOST,
+ /** 16-bit x86. */
+ RTLDRARCH_X86_16,
+ /** 32-bit x86. */
+ RTLDRARCH_X86_32,
+ /** AMD64 (64-bit x86 if you like). */
+ RTLDRARCH_AMD64,
+ /** 32-bit ARM. */
+ RTLDRARCH_ARM32,
+ /** 64-bit ARM. */
+ RTLDRARCH_ARM64,
+ /** End of the valid values. */
+ RTLDRARCH_END,
+ /** Make sure the type is a full 32-bit. */
+ RTLDRARCH_32BIT_HACK = 0x7fffffff
+} RTLDRARCH;
+/** Pointer to a RTLDRARCH. */
+typedef RTLDRARCH *PRTLDRARCH;
+
+/**
+ * Translates a RTLDRARCH value to a string.
+ *
+ * @returns Name corresponding to @a enmArch
+ * @param enmArch The value to name.
+ */
+RTDECL(const char *) RTLdrArchName(RTLDRARCH enmArch);
+
+/**
+ * Returns the host architecture.
+ *
+ * @returns Host architecture or RTLDRARCH_WHATEVER if no match.
+ */
+RTDECL(RTLDRARCH) RTLdrGetHostArch(void);
+
+
+/** @name RTLDR_O_XXX - RTLdrOpen flags.
+ * @{ */
+/** Open for debugging or introspection reasons.
+ * This will skip a few of the stricter validations when loading images. */
+#define RTLDR_O_FOR_DEBUG RT_BIT_32(0)
+/** Open for signature validation. */
+#define RTLDR_O_FOR_VALIDATION RT_BIT_32(1)
+/** The arch specification is just a guideline for FAT binaries. */
+#define RTLDR_O_WHATEVER_ARCH RT_BIT_32(2)
+/** Ignore the architecture specification if there is no code. */
+#define RTLDR_O_IGNORE_ARCH_IF_NO_CODE RT_BIT_32(3)
+/** Mach-O: Include the __LINKEDIT segment (ignored by the others). */
+#define RTLDR_O_MACHO_LOAD_LINKEDIT RT_BIT_32(4)
+/** Mask of valid flags. */
+#define RTLDR_O_VALID_MASK UINT32_C(0x0000001f)
+/** @} */
+
+/**
+ * Open a binary image file.
+ *
+ * @returns iprt status code.
+ * @param pszFilename Image filename.
+ * @param fFlags Valid RTLDR_O_XXX combination.
+ * @param enmArch CPU architecture specifier for the image to be loaded.
+ * @param phLdrMod Where to store the handle to the loader module.
+ */
+RTDECL(int) RTLdrOpen(const char *pszFilename, uint32_t fFlags, RTLDRARCH enmArch, PRTLDRMOD phLdrMod);
+
+/**
+ * Open a binary image file, extended version.
+ *
+ * @returns iprt status code.
+ * @param pszFilename Image filename.
+ * @param fFlags Valid RTLDR_O_XXX combination.
+ * @param enmArch CPU architecture specifier for the image to be loaded.
+ * @param phLdrMod Where to store the handle to the loader module.
+ * @param pErrInfo Where to return extended error information. Optional.
+ */
+RTDECL(int) RTLdrOpenEx(const char *pszFilename, uint32_t fFlags, RTLDRARCH enmArch, PRTLDRMOD phLdrMod, PRTERRINFO pErrInfo);
+
+/**
+ * Open a binary image file allowing VFS chains in the filename.
+ *
+ * @returns iprt status code.
+ * @param pszFilename Image filename, VFS chain specifiers allowed.
+ * @param fFlags Valid RTLDR_O_XXX combination.
+ * @param enmArch CPU architecture specifier for the image to be loaded.
+ * @param phLdrMod Where to store the handle to the loader module.
+ * @param poffError Where to return the offset into @a pszFilename of an VFS
+ * chain element causing trouble. Optional.
+ * @param pErrInfo Where to return extended error information. Optional.
+ */
+RTDECL(int) RTLdrOpenVfsChain(const char *pszFilename, uint32_t fFlags, RTLDRARCH enmArch,
+ PRTLDRMOD phLdrMod, uint32_t *poffError, PRTERRINFO pErrInfo);
+
+/**
+ * Open part with reader.
+ *
+ * @returns iprt status code.
+ * @param pReader The loader reader instance which will provide the raw
+ * image bits. The reader instance will be consumed on
+ * success. On failure, the caller has to do the cleaning
+ * up.
+ * @param fFlags Valid RTLDR_O_XXX combination.
+ * @param enmArch Architecture specifier.
+ * @param phMod Where to store the handle.
+ * @param pErrInfo Where to return extended error information. Optional.
+ */
+RTDECL(int) RTLdrOpenWithReader(PRTLDRREADER pReader, uint32_t fFlags, RTLDRARCH enmArch, PRTLDRMOD phMod, PRTERRINFO pErrInfo);
+
+/**
+ * Called to read @a cb bytes at @a off into @a pvBuf.
+ *
+ * @returns IPRT status code
+ * @param pvBuf The output buffer.
+ * @param cb The number of bytes to read.
+ * @param off Where to start reading.
+ * @param pvUser The user parameter.
+ */
+typedef DECLCALLBACKTYPE(int, FNRTLDRRDRMEMREAD,(void *pvBuf, size_t cb, size_t off, void *pvUser));
+/** Pointer to a RTLdrOpenInMemory reader callback. */
+typedef FNRTLDRRDRMEMREAD *PFNRTLDRRDRMEMREAD;
+
+/**
+ * Called to when the module is unloaded (or done loading) to release resources
+ * associated with it (@a pvUser).
+ *
+ * @returns IPRT status code
+ * @param pvUser The user parameter.
+ * @param cbImage The image size.
+ */
+typedef DECLCALLBACKTYPE(void, FNRTLDRRDRMEMDTOR,(void *pvUser, size_t cbImage));
+/** Pointer to a RTLdrOpenInMemory destructor callback. */
+typedef FNRTLDRRDRMEMDTOR *PFNRTLDRRDRMEMDTOR;
+
+/**
+ * Open a in-memory image or an image with a custom reader callback.
+ *
+ * @returns IPRT status code.
+ * @param pszName The image name.
+ * @param fFlags Valid RTLDR_O_XXX combination.
+ * @param enmArch CPU architecture specifier for the image to be loaded.
+ * @param cbImage The size of the image (fake file).
+ * @param pfnRead The read function. If NULL is passed in, a default
+ * reader function is provided that assumes @a pvUser
+ * points to the raw image bits, at least @a cbImage of
+ * valid memory.
+ * @param pfnDtor The destructor function. If NULL is passed, a default
+ * destructor will be provided that passes @a pvUser to
+ * RTMemFree.
+ * @param pvUser The user argument or, if any of the callbacks are NULL,
+ * a pointer to a memory block.
+ * @param phLdrMod Where to return the module handle.
+ * @param pErrInfo Pointer to an error info buffer, optional.
+ *
+ * @remarks With the exception of invalid @a pfnDtor and/or @a pvUser
+ * parameters, the pfnDtor methods (or the default one if NULL) will
+ * always be invoked. The destruction of pvUser is entirely in the
+ * hands of this method once it's called.
+ */
+RTDECL(int) RTLdrOpenInMemory(const char *pszName, uint32_t fFlags, RTLDRARCH enmArch, size_t cbImage,
+ PFNRTLDRRDRMEMREAD pfnRead, PFNRTLDRRDRMEMDTOR pfnDtor, void *pvUser,
+ PRTLDRMOD phLdrMod, PRTERRINFO pErrInfo);
+
+/**
+ * Closes a loader module handle.
+ *
+ * The handle can be obtained using any of the RTLdrLoad(), RTLdrOpen()
+ * and RTLdrOpenInMemory() functions.
+ *
+ * @returns iprt status code.
+ * @param hLdrMod The loader module handle.
+ */
+RTDECL(int) RTLdrClose(RTLDRMOD hLdrMod);
+
+/**
+ * Gets the address of a named exported symbol.
+ *
+ * @returns iprt status code.
+ * @retval VERR_LDR_FORWARDER forwarder, use pfnQueryForwarderInfo. Buffer size
+ * hint in @a ppvValue.
+ * @param hLdrMod The loader module handle.
+ * @param pszSymbol Symbol name.
+ * @param ppvValue Where to store the symbol value. Note that this is restricted to the
+ * pointer size used on the host!
+ */
+RTDECL(int) RTLdrGetSymbol(RTLDRMOD hLdrMod, const char *pszSymbol, void **ppvValue);
+
+/**
+ * Gets the address of a named exported symbol.
+ *
+ * This function differs from the plain one in that it can deal with
+ * both GC and HC address sizes, and that it can calculate the symbol
+ * value relative to any given base address.
+ *
+ * @returns iprt status code.
+ * @retval VERR_LDR_FORWARDER forwarder, use pfnQueryForwarderInfo. Buffer size
+ * hint in @a pValue.
+ * @param hLdrMod The loader module handle.
+ * @param pvBits Optional pointer to the loaded image.
+ * Set this to NULL if no RTLdrGetBits() processed image bits are available.
+ * Not supported for RTLdrLoad() images.
+ * @param BaseAddress Image load address.
+ * Not supported for RTLdrLoad() images.
+ * @param iOrdinal Symbol ordinal number, pass UINT32_MAX if pszSymbol
+ * should be used instead.
+ * @param pszSymbol Symbol name.
+ * @param pValue Where to store the symbol value.
+ */
+RTDECL(int) RTLdrGetSymbolEx(RTLDRMOD hLdrMod, const void *pvBits, RTLDRADDR BaseAddress,
+ uint32_t iOrdinal, const char *pszSymbol, PRTLDRADDR pValue);
+
+/**
+ * Gets the address of a named exported function.
+ *
+ * Same as RTLdrGetSymbol, but skips the status code and pointer to return
+ * variable stuff.
+ *
+ * @returns Pointer to the function if found, NULL if not.
+ * @param hLdrMod The loader module handle.
+ * @param pszSymbol Function name.
+ */
+RTDECL(PFNRT) RTLdrGetFunction(RTLDRMOD hLdrMod, const char *pszSymbol);
+
+/**
+ * Information about an imported symbol.
+ */
+typedef struct RTLDRIMPORTINFO
+{
+ /** Symbol table entry number, UINT32_MAX if not available. */
+ uint32_t iSelfOrdinal;
+ /** The ordinal of the imported symbol in szModule, UINT32_MAX if not used. */
+ uint32_t iOrdinal;
+ /** The symbol name, NULL if not used. This points to the char immediately
+ * following szModule when returned by RTLdrQueryForwarderInfo. */
+ const char *pszSymbol;
+ /** The name of the module being imported from. */
+ char szModule[1];
+} RTLDRIMPORTINFO;
+/** Pointer to information about an imported symbol. */
+typedef RTLDRIMPORTINFO *PRTLDRIMPORTINFO;
+/** Pointer to const information about an imported symbol. */
+typedef RTLDRIMPORTINFO const *PCRTLDRIMPORTINFO;
+
+/**
+ * Query information about a forwarded symbol.
+ *
+ * @returns IPRT status code.
+ * @param hLdrMod The loader module handle.
+ * @param pvBits Optional pointer to the loaded image.
+ * Set this to NULL if no RTLdrGetBits() processed image bits are available.
+ * Not supported for RTLdrLoad() images.
+ * @param iOrdinal Symbol ordinal number, pass UINT32_MAX if pszSymbol
+ * should be used instead.
+ * @param pszSymbol Symbol name.
+ * @param pInfo Where to return the forwarder info.
+ * @param cbInfo Size of the buffer @a pInfo points to. For a size
+ * hint, see @a pValue when RTLdrGetSymbolEx returns
+ * VERR_LDR_FORWARDER.
+ */
+RTDECL(int) RTLdrQueryForwarderInfo(RTLDRMOD hLdrMod, const void *pvBits, uint32_t iOrdinal, const char *pszSymbol,
+ PRTLDRIMPORTINFO pInfo, size_t cbInfo);
+
+
+/**
+ * Gets the size of the loaded image.
+ *
+ * This is not necessarily available for images that has been loaded using
+ * RTLdrLoad().
+ *
+ * @returns image size (in bytes).
+ * @returns ~(size_t)0 on if not available.
+ * @param hLdrMod Handle to the loader module.
+ */
+RTDECL(size_t) RTLdrSize(RTLDRMOD hLdrMod);
+
+/**
+ * Resolve an external symbol during RTLdrGetBits().
+ *
+ * @returns iprt status code.
+ * @param hLdrMod The loader module handle.
+ * @param pszModule Module name.
+ * @param pszSymbol Symbol name, NULL if uSymbol should be used.
+ * @param uSymbol Symbol ordinal, ~0 if pszSymbol should be used.
+ * @param pValue Where to store the symbol value (address).
+ * @param pvUser User argument.
+ */
+typedef DECLCALLBACKTYPE(int, FNRTLDRIMPORT,(RTLDRMOD hLdrMod, const char *pszModule, const char *pszSymbol, unsigned uSymbol,
+ PRTLDRADDR pValue, void *pvUser));
+/** Pointer to a FNRTLDRIMPORT() callback function. */
+typedef FNRTLDRIMPORT *PFNRTLDRIMPORT;
+
+/**
+ * Loads the image into a buffer provided by the user and applies fixups
+ * for the given base address.
+ *
+ * @returns iprt status code.
+ * @param hLdrMod The load module handle.
+ * @param pvBits Where to put the bits.
+ * Must be as large as RTLdrSize() suggests.
+ * @param BaseAddress The base address.
+ * @param pfnGetImport Callback function for resolving imports one by one.
+ * @param pvUser User argument for the callback.
+ * @remark Not supported for RTLdrLoad() images.
+ */
+RTDECL(int) RTLdrGetBits(RTLDRMOD hLdrMod, void *pvBits, RTLDRADDR BaseAddress, PFNRTLDRIMPORT pfnGetImport, void *pvUser);
+
+/**
+ * Relocates bits after getting them.
+ * Useful for code which moves around a bit.
+ *
+ * @returns iprt status code.
+ * @param hLdrMod The loader module handle.
+ * @param pvBits Where the image bits are.
+ * Must have been passed to RTLdrGetBits().
+ * @param NewBaseAddress The new base address.
+ * @param OldBaseAddress The old base address.
+ * @param pfnGetImport Callback function for resolving imports one by one.
+ * @param pvUser User argument for the callback.
+ * @remark Not supported for RTLdrLoad() images.
+ */
+RTDECL(int) RTLdrRelocate(RTLDRMOD hLdrMod, void *pvBits, RTLDRADDR NewBaseAddress, RTLDRADDR OldBaseAddress,
+ PFNRTLDRIMPORT pfnGetImport, void *pvUser);
+
+/**
+ * Enumeration callback function used by RTLdrEnumSymbols().
+ *
+ * @returns iprt status code. Failure will stop the enumeration.
+ * @param hLdrMod The loader module handle.
+ * @param pszSymbol Symbol name. NULL if ordinal only.
+ * @param uSymbol Symbol ordinal, ~0 if not used.
+ * @param Value Symbol value.
+ * @param pvUser The user argument specified to RTLdrEnumSymbols().
+ */
+typedef DECLCALLBACKTYPE(int, FNRTLDRENUMSYMS,(RTLDRMOD hLdrMod, const char *pszSymbol, unsigned uSymbol, RTLDRADDR Value, void *pvUser));
+/** Pointer to a FNRTLDRENUMSYMS() callback function. */
+typedef FNRTLDRENUMSYMS *PFNRTLDRENUMSYMS;
+
+/**
+ * Enumerates all symbols in a module.
+ *
+ * @returns iprt status code.
+ * @param hLdrMod The loader module handle.
+ * @param fFlags Flags indicating what to return and such.
+ * @param pvBits Optional pointer to the loaded image. (RTLDR_ENUM_SYMBOL_FLAGS_*)
+ * Set this to NULL if no RTLdrGetBits() processed image bits are available.
+ * @param BaseAddress Image load address.
+ * @param pfnCallback Callback function.
+ * @param pvUser User argument for the callback.
+ * @remark Not supported for RTLdrLoad() images.
+ */
+RTDECL(int) RTLdrEnumSymbols(RTLDRMOD hLdrMod, unsigned fFlags, const void *pvBits, RTLDRADDR BaseAddress, PFNRTLDRENUMSYMS pfnCallback, void *pvUser);
+
+/** @name RTLdrEnumSymbols flags.
+ * @{ */
+/** Returns ALL kinds of symbols. The default is to only return public/exported symbols. */
+#define RTLDR_ENUM_SYMBOL_FLAGS_ALL RT_BIT(1)
+/** Ignore forwarders rather than reporting them with RTLDR_ENUM_SYMBOL_FWD_ADDRESS as value. */
+#define RTLDR_ENUM_SYMBOL_FLAGS_NO_FWD RT_BIT(2)
+/** @} */
+
+/** Special symbol for forwarder symbols, since they cannot be resolved with
+ * the current API. */
+#if (HC_ARCH_BITS == 64 || GC_ARCH_BITS == 64)
+# define RTLDR_ENUM_SYMBOL_FWD_ADDRESS UINT64_C(0xff4242fffd4242fd)
+#else
+# define RTLDR_ENUM_SYMBOL_FWD_ADDRESS UINT32_C(0xff4242fd)
+#endif
+
+
+/**
+ * Debug info type (as far the loader can tell).
+ */
+typedef enum RTLDRDBGINFOTYPE
+{
+ /** The invalid 0 value. */
+ RTLDRDBGINFOTYPE_INVALID = 0,
+ /** Unknown debug info format. */
+ RTLDRDBGINFOTYPE_UNKNOWN,
+ /** Stabs. */
+ RTLDRDBGINFOTYPE_STABS,
+ /** Debug With Arbitrary Record Format (DWARF). */
+ RTLDRDBGINFOTYPE_DWARF,
+ /** Debug With Arbitrary Record Format (DWARF), in external file (DWO). */
+ RTLDRDBGINFOTYPE_DWARF_DWO,
+ /** Microsoft Codeview debug info. */
+ RTLDRDBGINFOTYPE_CODEVIEW,
+ /** Microsoft Codeview debug info, in external v2.0+ program database (PDB). */
+ RTLDRDBGINFOTYPE_CODEVIEW_PDB20,
+ /** Microsoft Codeview debug info, in external v7.0+ program database (PDB). */
+ RTLDRDBGINFOTYPE_CODEVIEW_PDB70,
+ /** Microsoft Codeview debug info, in external file (DBG). */
+ RTLDRDBGINFOTYPE_CODEVIEW_DBG,
+ /** Microsoft COFF debug info. */
+ RTLDRDBGINFOTYPE_COFF,
+ /** Watcom debug info. */
+ RTLDRDBGINFOTYPE_WATCOM,
+ /** IBM High Level Language debug info. */
+ RTLDRDBGINFOTYPE_HLL,
+ /** The end of the valid debug info values (exclusive). */
+ RTLDRDBGINFOTYPE_END,
+ /** Blow the type up to 32-bits. */
+ RTLDRDBGINFOTYPE_32BIT_HACK = 0x7fffffff
+} RTLDRDBGINFOTYPE;
+
+
+/**
+ * Debug info details for the enumeration callback.
+ */
+typedef struct RTLDRDBGINFO
+{
+ /** The kind of debug info. */
+ RTLDRDBGINFOTYPE enmType;
+ /** The debug info ordinal number / id. */
+ uint32_t iDbgInfo;
+ /** The file offset *if* this type has one specific location in the executable
+ * image file. This is -1 if there isn't any specific file location. */
+ RTFOFF offFile;
+ /** The link address of the debug info if it's loadable. NIL_RTLDRADDR if not
+ * loadable*/
+ RTLDRADDR LinkAddress;
+ /** The size of the debug information. -1 is used if this isn't applicable.*/
+ RTLDRADDR cb;
+ /** This is set if the debug information is found in an external file. NULL
+ * if no external file involved.
+ * @note Putting it outside the union to allow lazy callback implementation. */
+ const char *pszExtFile;
+ /** Type (enmType) specific information. */
+ union
+ {
+ /** RTLDRDBGINFOTYPE_DWARF */
+ struct
+ {
+ /** The section name. */
+ const char *pszSection;
+ } Dwarf;
+
+ /** RTLDRDBGINFOTYPE_DWARF_DWO */
+ struct
+ {
+ /** The CRC32 of the external file. */
+ uint32_t uCrc32;
+ } Dwo;
+
+ /** RTLDRDBGINFOTYPE_CODEVIEW, RTLDRDBGINFOTYPE_COFF */
+ struct
+ {
+ /** The PE image size. */
+ uint32_t cbImage;
+ /** The timestamp. */
+ uint32_t uTimestamp;
+ /** The major version from the entry. */
+ uint32_t uMajorVer;
+ /** The minor version from the entry. */
+ uint32_t uMinorVer;
+ } Cv, Coff;
+
+ /** RTLDRDBGINFOTYPE_CODEVIEW_DBG */
+ struct
+ {
+ /** The PE image size. */
+ uint32_t cbImage;
+ /** The timestamp. */
+ uint32_t uTimestamp;
+ } Dbg;
+
+ /** RTLDRDBGINFOTYPE_CODEVIEW_PDB20*/
+ struct
+ {
+ /** The PE image size. */
+ uint32_t cbImage;
+ /** The timestamp. */
+ uint32_t uTimestamp;
+ /** The PDB age. */
+ uint32_t uAge;
+ } Pdb20;
+
+ /** RTLDRDBGINFOTYPE_CODEVIEW_PDB70 */
+ struct
+ {
+ /** The PE image size. */
+ uint32_t cbImage;
+ /** The PDB age. */
+ uint32_t uAge;
+ /** The UUID. */
+ RTUUID Uuid;
+ } Pdb70;
+ } u;
+} RTLDRDBGINFO;
+/** Pointer to debug info details. */
+typedef RTLDRDBGINFO *PRTLDRDBGINFO;
+/** Pointer to read only debug info details. */
+typedef RTLDRDBGINFO const *PCRTLDRDBGINFO;
+
+
+/**
+ * Debug info enumerator callback.
+ *
+ * @returns VINF_SUCCESS to continue the enumeration. Any other status code
+ * will cause RTLdrEnumDbgInfo to immediately return with that status.
+ *
+ * @param hLdrMod The module handle.
+ * @param pDbgInfo Pointer to a read only structure with the details.
+ * @param pvUser The user parameter specified to RTLdrEnumDbgInfo.
+ */
+typedef DECLCALLBACKTYPE(int, FNRTLDRENUMDBG,(RTLDRMOD hLdrMod, PCRTLDRDBGINFO pDbgInfo, void *pvUser));
+/** Pointer to a debug info enumerator callback. */
+typedef FNRTLDRENUMDBG *PFNRTLDRENUMDBG;
+
+/**
+ * Enumerate the debug info contained in the executable image.
+ *
+ * @returns IPRT status code or whatever pfnCallback returns.
+ *
+ * @param hLdrMod The module handle.
+ * @param pvBits Optional pointer to bits returned by
+ * RTLdrGetBits(). This can be used by some module
+ * interpreters to reduce memory consumption.
+ * @param pfnCallback The callback function.
+ * @param pvUser The user argument.
+ */
+RTDECL(int) RTLdrEnumDbgInfo(RTLDRMOD hLdrMod, const void *pvBits, PFNRTLDRENUMDBG pfnCallback, void *pvUser);
+
+
+/**
+ * Loader segment.
+ */
+typedef struct RTLDRSEG
+{
+ /** The segment name. Always set to something. */
+ const char *pszName;
+ /** The length of the segment name. */
+ uint32_t cchName;
+ /** The flat selector to use for the segment (i.e. data/code).
+ * Primarily a way for the user to specify selectors for the LX/LE and NE interpreters. */
+ uint16_t SelFlat;
+ /** The 16-bit selector to use for the segment.
+ * Primarily a way for the user to specify selectors for the LX/LE and NE interpreters. */
+ uint16_t Sel16bit;
+ /** Segment flags. */
+ uint32_t fFlags;
+ /** The segment protection (RTMEM_PROT_XXX). */
+ uint32_t fProt;
+ /** The size of the segment. */
+ RTLDRADDR cb;
+ /** The required segment alignment.
+ * The to 0 if the segment isn't supposed to be mapped. */
+ RTLDRADDR Alignment;
+ /** The link address.
+ * Set to NIL_RTLDRADDR if the segment isn't supposed to be mapped or if
+ * the image doesn't have link addresses. */
+ RTLDRADDR LinkAddress;
+ /** File offset of the segment.
+ * Set to -1 if no file backing (like BSS). */
+ RTFOFF offFile;
+ /** Size of the file bits of the segment.
+ * Set to -1 if no file backing (like BSS). */
+ RTFOFF cbFile;
+ /** The relative virtual address when mapped.
+ * Set to NIL_RTLDRADDR if the segment isn't supposed to be mapped. */
+ RTLDRADDR RVA;
+ /** The size of the segment including the alignment gap up to the next segment when mapped.
+ * This is set to NIL_RTLDRADDR if not implemented. */
+ RTLDRADDR cbMapped;
+} RTLDRSEG;
+/** Pointer to a loader segment. */
+typedef RTLDRSEG *PRTLDRSEG;
+/** Pointer to a read only loader segment. */
+typedef RTLDRSEG const *PCRTLDRSEG;
+
+
+/** @name Segment flags
+ * @{ */
+/** The segment is 16-bit. When not set the default of the target architecture is assumed. */
+#define RTLDRSEG_FLAG_16BIT UINT32_C(1)
+/** The segment requires a 16-bit selector alias. (OS/2) */
+#define RTLDRSEG_FLAG_OS2_ALIAS16 UINT32_C(2)
+/** Conforming segment (x86 weirdness). (OS/2) */
+#define RTLDRSEG_FLAG_OS2_CONFORM UINT32_C(4)
+/** IOPL (ring-2) segment. (OS/2) */
+#define RTLDRSEG_FLAG_OS2_IOPL UINT32_C(8)
+/** @} */
+
+/**
+ * Segment enumerator callback.
+ *
+ * @returns VINF_SUCCESS to continue the enumeration. Any other status code
+ * will cause RTLdrEnumSegments to immediately return with that
+ * status.
+ *
+ * @param hLdrMod The module handle.
+ * @param pSeg The segment information.
+ * @param pvUser The user parameter specified to RTLdrEnumSegments.
+ */
+typedef DECLCALLBACKTYPE(int, FNRTLDRENUMSEGS,(RTLDRMOD hLdrMod, PCRTLDRSEG pSeg, void *pvUser));
+/** Pointer to a segment enumerator callback. */
+typedef FNRTLDRENUMSEGS *PFNRTLDRENUMSEGS;
+
+/**
+ * Enumerate the debug info contained in the executable image.
+ *
+ * @returns IPRT status code or whatever pfnCallback returns.
+ *
+ * @param hLdrMod The module handle.
+ * @param pfnCallback The callback function.
+ * @param pvUser The user argument.
+ */
+RTDECL(int) RTLdrEnumSegments(RTLDRMOD hLdrMod, PFNRTLDRENUMSEGS pfnCallback, void *pvUser);
+
+/**
+ * Converts a link address to a segment:offset address.
+ *
+ * @returns IPRT status code.
+ *
+ * @param hLdrMod The module handle.
+ * @param LinkAddress The link address to convert.
+ * @param piSeg Where to return the segment index.
+ * @param poffSeg Where to return the segment offset.
+ */
+RTDECL(int) RTLdrLinkAddressToSegOffset(RTLDRMOD hLdrMod, RTLDRADDR LinkAddress, uint32_t *piSeg, PRTLDRADDR poffSeg);
+
+/**
+ * Converts a link address to an image relative virtual address (RVA).
+ *
+ * @returns IPRT status code.
+ *
+ * @param hLdrMod The module handle.
+ * @param LinkAddress The link address to convert.
+ * @param pRva Where to return the RVA.
+ */
+RTDECL(int) RTLdrLinkAddressToRva(RTLDRMOD hLdrMod, RTLDRADDR LinkAddress, PRTLDRADDR pRva);
+
+/**
+ * Converts an image relative virtual address (RVA) to a segment:offset.
+ *
+ * @returns IPRT status code.
+ *
+ * @param hLdrMod The module handle.
+ * @param iSeg The segment index.
+ * @param offSeg The segment offset.
+ * @param pRva Where to return the RVA.
+ */
+RTDECL(int) RTLdrSegOffsetToRva(RTLDRMOD hLdrMod, uint32_t iSeg, RTLDRADDR offSeg, PRTLDRADDR pRva);
+
+/**
+ * Converts a segment:offset into an image relative virtual address (RVA).
+ *
+ * @returns IPRT status code.
+ *
+ * @param hLdrMod The module handle.
+ * @param Rva The link address to convert.
+ * @param piSeg Where to return the segment index.
+ * @param poffSeg Where to return the segment offset.
+ */
+RTDECL(int) RTLdrRvaToSegOffset(RTLDRMOD hLdrMod, RTLDRADDR Rva, uint32_t *piSeg, PRTLDRADDR poffSeg);
+
+/**
+ * Gets the image format.
+ *
+ * @returns Valid image format on success. RTLDRFMT_INVALID on invalid handle or
+ * other errors.
+ * @param hLdrMod The module handle.
+ */
+RTDECL(RTLDRFMT) RTLdrGetFormat(RTLDRMOD hLdrMod);
+
+/**
+ * Gets the image type.
+ *
+ * @returns Valid image type value on success. RTLDRTYPE_INVALID on
+ * invalid handle or other errors.
+ * @param hLdrMod The module handle.
+ */
+RTDECL(RTLDRTYPE) RTLdrGetType(RTLDRMOD hLdrMod);
+
+/**
+ * Gets the image endian-ness.
+ *
+ * @returns Valid image endian value on success. RTLDRENDIAN_INVALID on invalid
+ * handle or other errors.
+ * @param hLdrMod The module handle.
+ */
+RTDECL(RTLDRENDIAN) RTLdrGetEndian(RTLDRMOD hLdrMod);
+
+/**
+ * Gets the image endian-ness.
+ *
+ * @returns Valid image architecture value on success.
+ * RTLDRARCH_INVALID on invalid handle or other errors.
+ * @param hLdrMod The module handle.
+ */
+RTDECL(RTLDRARCH) RTLdrGetArch(RTLDRMOD hLdrMod);
+
+/**
+ * Loader properties that can be queried thru RTLdrQueryProp.
+ */
+typedef enum RTLDRPROP
+{
+ RTLDRPROP_INVALID = 0,
+ /** The image UUID (Mach-O).
+ * Returns a RTUUID in the buffer. */
+ RTLDRPROP_UUID,
+ /** The image timestamp in seconds, genrally since unix epoc.
+ * Returns a 32-bit or 64-bit signed integer value in the buffer. */
+ RTLDRPROP_TIMESTAMP_SECONDS,
+ /** Checks if the image is signed.
+ * Returns a bool. */
+ RTLDRPROP_IS_SIGNED,
+ /** Retrives the PKCS \#7 SignedData blob that signs the image.
+ * Returns variable sized buffer containing the ASN.1 BER encoding.
+ *
+ * @remarks This generally starts with a PKCS \#7 Content structure, the
+ * SignedData bit is found a few levels down into this as per RFC. */
+ RTLDRPROP_PKCS7_SIGNED_DATA,
+ /** Query the number of pages that needs hashing.
+ * This is for RTLDRPROP_SHA1_PAGE_HASHES and RTLDRPROP_SHA256_PAGE_HASHES
+ * buffer size calculations. */
+ RTLDRPROP_HASHABLE_PAGES,
+ /** Query the SHA-1 page hashes.
+ * Returns an array with entries made of a 32-bit file offset and a SHA-1
+ * digest. Use RTLDRPROP_HASHABLE_PAGES to calculate the buffer size. */
+ RTLDRPROP_SHA1_PAGE_HASHES,
+ /** Query the SHA-256 page hashes.
+ * Returns an array with entries made of a 32-bit file offset and a SHA-256
+ * digest. Use RTLDRPROP_HASHABLE_PAGES to calculate the buffer size. */
+ RTLDRPROP_SHA256_PAGE_HASHES,
+
+ /** Query whether code signature checks are enabled. */
+ RTLDRPROP_SIGNATURE_CHECKS_ENFORCED,
+
+ /** Number of import or needed modules. */
+ RTLDRPROP_IMPORT_COUNT,
+ /** Import module by index (32-bit) stored in the buffer. */
+ RTLDRPROP_IMPORT_MODULE,
+ /** The file offset of the main executable header.
+ * This is mainly for PE, NE and LX headers, but also Mach-O FAT. */
+ RTLDRPROP_FILE_OFF_HEADER,
+ /** The internal module name.
+ * This is the SONAME for ELF, export table name for PE, and zero'th resident
+ * name table entry for LX.
+ * Returns zero terminated string. */
+ RTLDRPROP_INTERNAL_NAME,
+ /** The raw unwind table if available.
+ * For PE this means IMAGE_DIRECTORY_ENTRY_EXCEPTION content, for AMD64 this
+ * is the lookup table (IMAGE_RUNTIME_FUNCTION_ENTRY).
+ * Not implemented any others yet. */
+ RTLDRPROP_UNWIND_TABLE,
+ /** Read unwind info at given RVA and up to buffer size. The RVA is stored
+ * as uint32_t in the buffer when making the call.
+ * This is only implemented for PE. */
+ RTLDRPROP_UNWIND_INFO,
+ /** The image build-id (ELF/GNU).
+ * Returns usually a SHA1 checksum in the buffer. */
+ RTLDRPROP_BUILDID,
+
+ /** End of valid properties. */
+ RTLDRPROP_END,
+ /** Blow the type up to 32 bits. */
+ RTLDRPROP_32BIT_HACK = 0x7fffffff
+} RTLDRPROP;
+
+/**
+ * Generic method for querying image properties.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_NOT_SUPPORTED if the property query isn't supported (either all
+ * or that specific property). The caller must handle this result.
+ * @retval VERR_NOT_FOUND the property was not found in the module. The caller
+ * must also normally deal with this.
+ * @retval VERR_INVALID_FUNCTION if the function value is wrong.
+ * @retval VERR_INVALID_PARAMETER if the buffer size is wrong.
+ * @retval VERR_BUFFER_OVERFLOW if the function doesn't have a fixed size
+ * buffer and the buffer isn't big enough. Use RTLdrQueryPropEx.
+ * @retval VERR_INVALID_HANDLE if the handle is invalid.
+ *
+ * @param hLdrMod The module handle.
+ * @param enmProp The property to query.
+ * @param pvBuf Pointer to the input / output buffer. In most cases
+ * it's only used for returning data.
+ * @param cbBuf The size of the buffer.
+ */
+RTDECL(int) RTLdrQueryProp(RTLDRMOD hLdrMod, RTLDRPROP enmProp, void *pvBuf, size_t cbBuf);
+
+/**
+ * Generic method for querying image properties, extended version.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_NOT_SUPPORTED if the property query isn't supported (either all
+ * or that specific property). The caller must handle this result.
+ * @retval VERR_NOT_FOUND the property was not found in the module. The caller
+ * must also normally deal with this.
+ * @retval VERR_INVALID_FUNCTION if the function value is wrong.
+ * @retval VERR_INVALID_PARAMETER if the fixed buffer size is wrong. Correct
+ * size in @a *pcbRet.
+ * @retval VERR_BUFFER_OVERFLOW if the function doesn't have a fixed size
+ * buffer and the buffer isn't big enough. Correct size in @a *pcbRet.
+ * @retval VERR_INVALID_HANDLE if the handle is invalid.
+ *
+ * @param hLdrMod The module handle.
+ * @param enmProp The property to query.
+ * @param pvBits Optional pointer to bits returned by
+ * RTLdrGetBits(). This can be utilized by some module
+ * interpreters to reduce memory consumption and file
+ * access.
+ * @param pvBuf Pointer to the input / output buffer. In most cases
+ * it's only used for returning data.
+ * @param cbBuf The size of the buffer.
+ * @param pcbRet Where to return the amount of data returned. On
+ * buffer size errors, this is set to the correct size.
+ * Optional.
+ */
+RTDECL(int) RTLdrQueryPropEx(RTLDRMOD hLdrMod, RTLDRPROP enmProp, void *pvBits, void *pvBuf, size_t cbBuf, size_t *pcbRet);
+
+
+/**
+ * Signature type, see FNRTLDRVALIDATESIGNEDDATA.
+ */
+typedef enum RTLDRSIGNATURETYPE
+{
+ /** Invalid value. */
+ RTLDRSIGNATURETYPE_INVALID = 0,
+ /** A RTPKCS7CONTENTINFO structure w/ RTPKCS7SIGNEDDATA inside.
+ * It's parsed, so the whole binary ASN.1 representation can be found by
+ * using RTASN1CORE_GET_RAW_ASN1_PTR() and RTASN1CORE_GET_RAW_ASN1_SIZE(). */
+ RTLDRSIGNATURETYPE_PKCS7_SIGNED_DATA,
+ /** End of valid values. */
+ RTLDRSIGNATURETYPE_END,
+ /** Make sure the size is 32-bit. */
+ RTLDRSIGNATURETYPE_32BIT_HACK = 0x7fffffff
+} RTLDRSIGNATURETYPE;
+
+/**
+ * Signature information provided by FNRTLDRVALIDATESIGNEDDATA.
+ */
+typedef struct RTLDRSIGNATUREINFO
+{
+ /** The signature number (0-based). */
+ uint16_t iSignature;
+ /** The total number of signatures. */
+ uint16_t cSignatures;
+ /** Sginature format type. */
+ RTLDRSIGNATURETYPE enmType;
+ /** The signature data (formatted according to enmType). */
+ void const *pvSignature;
+ /** The size of the buffer pvSignature points to. */
+ size_t cbSignature;
+ /** Pointer to the signed data, if external.
+ * NULL if the data is internal to the signature structure. */
+ void const *pvExternalData;
+ /** Size of the signed data, if external.
+ * 0 if internal to the signature structure. */
+ size_t cbExternalData;
+} RTLDRSIGNATUREINFO;
+/** Pointer to a signature structure. */
+typedef RTLDRSIGNATUREINFO *PRTLDRSIGNATUREINFO;
+/** Pointer to a const signature structure. */
+typedef RTLDRSIGNATUREINFO const *PCRTLDRSIGNATUREINFO;
+
+/**
+ * Callback used by RTLdrVerifySignature to verify the signature and associated
+ * certificates.
+ *
+ * This is called multiple times when the executable contains more than one
+ * signature (PE only at the moment). The RTLDRSIGNATUREINFO::cSignatures gives
+ * the total number of signatures (and thereby callbacks) and
+ * RTLDRSIGNATUREINFO::iSignature indicates the current one.
+ *
+ * @returns IPRT status code. A status code other than VINF_SUCCESS will
+ * prevent callbacks the remaining signatures (if any).
+ * @param hLdrMod The module handle.
+ * @param pInfo Signature information.
+ * @param pErrInfo Pointer to an error info buffer, optional.
+ * @param pvUser User argument.
+ */
+typedef DECLCALLBACKTYPE(int, FNRTLDRVALIDATESIGNEDDATA,(RTLDRMOD hLdrMod, PCRTLDRSIGNATUREINFO pInfo,
+ PRTERRINFO pErrInfo, void *pvUser));
+/** Pointer to a signature verification callback. */
+typedef FNRTLDRVALIDATESIGNEDDATA *PFNRTLDRVALIDATESIGNEDDATA;
+
+/**
+ * Verify the image signature.
+ *
+ * This may permform additional integrity checks on the image structures that
+ * was not done when opening the image.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_LDRVI_NOT_SIGNED if not signed.
+ *
+ * @param hLdrMod The module handle.
+ * @param pfnCallback Callback that does the signature and certificate
+ * verficiation.
+ * @param pvUser User argument for the callback.
+ * @param pErrInfo Pointer to an error info buffer. Optional.
+ */
+RTDECL(int) RTLdrVerifySignature(RTLDRMOD hLdrMod, PFNRTLDRVALIDATESIGNEDDATA pfnCallback, void *pvUser, PRTERRINFO pErrInfo);
+
+/**
+ * Calculate the image hash according the image signing rules.
+ *
+ * @returns IPRT status code.
+ * @param hLdrMod The module handle.
+ * @param enmDigest Which kind of digest.
+ * @param pabHash Where to store the image hash.
+ * @param cbHash Size of the buffer @a pabHash points at. The
+ * required and returned size can be derived from the
+ * digest type (@a enmDigest).
+ */
+RTDECL(int) RTLdrHashImage(RTLDRMOD hLdrMod, RTDIGESTTYPE enmDigest, uint8_t *pabHash, size_t cbHash);
+
+/**
+ * Try use unwind information to unwind one frame.
+ *
+ * @returns IPRT status code. Last informational status from stack reader callback.
+ * @retval VERR_DBG_NO_UNWIND_INFO if the module contains no unwind information.
+ * @retval VERR_DBG_UNWIND_INFO_NOT_FOUND if no unwind information was found
+ * for the location given by iSeg:off.
+ *
+ * @param hLdrMod The module handle.
+ * @param pvBits Optional pointer to bits returned by
+ * RTLdrGetBits(). This can be utilized by some module
+ * interpreters to reduce memory consumption and file
+ * access.
+ * @param iSeg The segment number of the program counter. UINT32_MAX if RVA.
+ * @param off The offset into @a iSeg. Together with @a iSeg
+ * this corresponds to the RTDBGUNWINDSTATE::uPc
+ * value pointed to by @a pState.
+ * @param pState The unwind state to work.
+ *
+ * @sa RTDbgModUnwindFrame
+ */
+RTDECL(int) RTLdrUnwindFrame(RTLDRMOD hLdrMod, void const *pvBits, uint32_t iSeg, RTLDRADDR off, PRTDBGUNWINDSTATE pState);
+
+RT_C_DECLS_END
+
+/** @} */
+
+#endif /* !IPRT_INCLUDED_ldr_h */
+
diff --git a/include/iprt/ldrlazy.h b/include/iprt/ldrlazy.h
new file mode 100644
index 00000000..0fa788da
--- /dev/null
+++ b/include/iprt/ldrlazy.h
@@ -0,0 +1,122 @@
+/** @file
+ * IPRT - Lazy share library linking (2nd try).
+ */
+
+/*
+ * Copyright (C) 2013-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_ldrlazy_h
+#define IPRT_INCLUDED_ldrlazy_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/ldr.h>
+
+/** @defgroup grp_rt_ldrlazy RTLdrLazy - Lazy shared library linking.
+ * @ingroup grp_rt
+ *
+ * This is a set of macros which will produce code for dynamically loading and
+ * resolving symbols in shared libraries (DLLs).
+ *
+ * There is an assembly language alternative to this that only requires writing
+ * a list of symbols in a format similar to what the microsoft linkers take as
+ * input when producing DLLs and import libraries. That is probably preferable
+ * over this code. See src/bldprog/VBoxDef2LazyLoad.cpp.
+ *
+ * @{
+ */
+
+
+/**
+ * Defines a module for use in lazy resolving.
+ *
+ * @param a_Mod The module name (C name).
+ * @param a_pszFile The file to tell RTLdrLoad to load.
+ */
+#define RTLDRLAZY_MODULE(a_Mod, a_pszFile) \
+ RTLDRLAZY_MODULE_EX(a_Mod, a_pszFile, RTLdrLoad)
+
+/**
+ * Defines a module for use in lazy resolving.
+ *
+ * @param a_Mod The module name (C name).
+ * @param a_pszFile The file to tell RTLdrLoad to load.
+ * @param a_pfnLoadIt Function to call for loading the DLL, replacing
+ * RTLdrLoad.
+ */
+#define RTLDRLAZY_MODULE_EX(a_Mod, a_pszFile, a_pfnLoadIt) \
+ static bool rtLdrLazy_##a_Mod##_Resolve(const char *pszName, void **ppvSymbol) \
+ { \
+ static RTLDRMOD volatile s_hMod = NIL_RTLDRMOD; \
+ static bool volatile s_fLoaded = false; \
+ RTLDRMOD hMod; \
+ int rc; \
+ if (!s_fLoaded) \
+ { \
+ rc = a_pfnLoadIt(a_pszFile, &hMod); \
+ s_hMod = RT_SUCCESS(rc) ? hMod : NIL_RTLDRMOD; \
+ s_fLoaded = true; \
+ if (RT_FAILURE(rc)) \
+ return false; \
+ } \
+ hMod = s_hMod; \
+ if (hMod == NIL_RTLDRMOD) \
+ return false; \
+ rc = RTLdrGetSymbol(hMod, pszName, ppvSymbol); \
+ return RT_SUCCESS(rc); \
+ }
+
+
+
+/** Function name mangler for preventing collision with system prototypes. */
+#define RTLDRLAZY_FUNC_NAME(a_Mod, a_Name) a_Mod##__##a_Name
+
+/**
+ * Defines a function that should be lazily resolved.
+ */
+#define RTLDRLAZY_FUNC(a_Mod, a_RetType, a_CallConv, a_Name, a_ParamDecl, a_ParamNames, a_ErrRet) \
+ DECLINLINE(a_RetType) RTLDRLAZY_FUNC_NAME(a_Mod, a_Name) a_ParamDecl \
+ { \
+ static a_RetType (a_CallConv * s_pfn) a_ParamDecl; \
+ if (!s_pfn) \
+ { \
+ if (!rtLdrLazy_##a_Mod##_Resolve(#a_Name, (void **)&s_pfn)) \
+ return a_ErrRet; \
+ } \
+ return s_pfn a_ParamNames; \
+ }
+
+
+/** @} */
+
+#endif /* !IPRT_INCLUDED_ldrlazy_h */
+
diff --git a/include/iprt/linux/Makefile.kup b/include/iprt/linux/Makefile.kup
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/include/iprt/linux/Makefile.kup
diff --git a/include/iprt/linux/symvers.h b/include/iprt/linux/symvers.h
new file mode 100644
index 00000000..0a8ef1b7
--- /dev/null
+++ b/include/iprt/linux/symvers.h
@@ -0,0 +1,89 @@
+/** @file
+ * IPRT - Linux symver and compatibility definitions.
+ */
+
+/*
+ * Copyright (C) 2008-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+/* Various tricks to produce binaries which can be run on old Linux
+ * distributions. This will almost certainly need updating as time
+ * goes by. */
+
+#ifndef IPRT_INCLUDED_linux_symvers_h
+#define IPRT_INCLUDED_linux_symvers_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+/* Please use -fno-stack-protector on the command line to avoid stack check
+ * functions which are not available in EL3 for 32-bit builds. */
+
+/* Use versions of glibc symbols which are available in 32-bit EL3 or
+ * 64-bit EL4. Currently only those symbols needed by the Additions,
+ * though this could probably be extended to work for host builds too. */
+#if defined(RT_ARCH_AMD64)
+__asm__(".symver memcpy,memcpy@GLIBC_2.2.5");
+__asm__(".symver posix_spawn,posix_spawn@GLIBC_2.2.5");
+#else /* RT_ARCH_X86 */
+__asm__(".symver posix_spawn,posix_spawn@GLIBC_2.2");
+#endif
+
+/* Do not use *_chk functions */
+#undef _FORTIFY_SOURCE
+
+/* Do not use __isoc99_* functions */
+#undef __USE_GNU
+#define __USE_GNU 1
+
+/* And EL5 wants this too with __USE_GNU */
+#undef _GNU_SOURCE
+#define _GNU_SOURCE 1
+
+/* Tell IPRT not to use newer functions */
+#include <features.h>
+#undef __GLIBC_MINOR__
+#define __GLIBC_MINOR__ 3
+
+/* Do not use fcntl64 */
+#include <fcntl.h>
+#ifdef fnctl
+# undef fcntl
+#endif
+#if defined(RT_ARCH_AMD64)
+__asm__(".symver fcntl64,fcntl@GLIBC_2.2.5");
+#else
+__asm__(".symver fcntl64,fcntl@GLIBC_2.0");
+#endif
+
+/* Do not use ISO C99 scanf which has a glibc 2.7 dependency. */
+#undef __GLIBC_USE_DEPRECATED_SCANF
+#define __GLIBC_USE_DEPRECATED_SCANF 1
+#endif /* !IPRT_INCLUDED_linux_symvers_h */
diff --git a/include/iprt/linux/sysfs.h b/include/iprt/linux/sysfs.h
new file mode 100644
index 00000000..02c3af39
--- /dev/null
+++ b/include/iprt/linux/sysfs.h
@@ -0,0 +1,487 @@
+/* $Id: sysfs.h $ */
+/** @file
+ * IPRT - Linux sysfs access.
+ */
+
+/*
+ * Copyright (C) 2008-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_linux_sysfs_h
+#define IPRT_INCLUDED_linux_sysfs_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+#include <iprt/stdarg.h>
+
+#include <sys/types.h> /* for dev_t */
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_linux_sysfs RTLinuxSysfs - Linux sysfs
+ * @ingroup grp_rt
+ * @{
+ */
+
+/**
+ * Checks if a sysfs file (or directory, device, symlink, whatever) exists.
+ *
+ * @returns true if the sysfs object exists.
+ * false otherwise or if an error occurred.
+ * @param pszFormat The name format, either absolute or relative to "/sys/".
+ * @param va The format args.
+ */
+RTDECL(bool) RTLinuxSysFsExistsV(const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(1, 0);
+
+/**
+ * Checks if a sysfs object (directory, device, symlink, whatever) exists.
+ *
+ * @returns IPRT status code.
+ * @retval VINF_SUCCESS if the sysfs object exists.
+ * @retval VERR_FILE_NOT_FOUND if the sysfs object does not exist.
+ * @param pszFormat The name format, either absolute or relative to "/sys/".
+ * @param va The format args.
+ */
+RTDECL(int) RTLinuxSysFsExistsExV(const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(1, 0);
+
+/**
+ * Checks if a sysfs file (or directory, device, symlink, whatever) exists.
+ *
+ * @returns true if the sysfs object exists.
+ * false otherwise or if an error occurred.
+ * @param pszFormat The name format, either absolute or relative to "/sys/".
+ * @param ... The format args.
+ */
+RTDECL(bool) RTLinuxSysFsExists(const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(1, 2);
+
+/**
+ * Checks if a sysfs object (directory, device, symlink, whatever) exists.
+ *
+ * @returns IPRT status code.
+ * @retval VINF_SUCCESS if the sysfs object exists.
+ * @retval VERR_FILE_NOT_FOUND if the sysfs object does not exist.
+ * @param pszFormat The name format, either absolute or relative to "/sys/".
+ * @param ... The format args.
+ */
+RTDECL(int) RTLinuxSysFsExistsEx(const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(1, 2);
+
+/**
+ * Opens a sysfs file for reading.
+ *
+ * @returns IPRT status code.
+ * @param phFile Where to store the file handle on success.
+ * @param pszFormat The name format, either absolute or relative to "/sys/".
+ * @param va The format args.
+ *
+ * @note Close the file using RTFileClose().
+ */
+RTDECL(int) RTLinuxSysFsOpenV(PRTFILE phFile, const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(2, 0);
+
+/**
+ * Opens a sysfs file - extended version.
+ *
+ * @returns IPRT status code.
+ * @param phFile Where to store the file handle on success.
+ * @param fOpen Open flags, see RTFileOpen().
+ * @param pszFormat The name format, either absolute or relative to "/sys/".
+ * @param va The format args.
+ */
+RTDECL(int) RTLinuxSysFsOpenExV(PRTFILE phFile, uint64_t fOpen, const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(3, 0);
+
+/**
+ * Opens a sysfs file.
+ *
+ * @returns IPRT status code.
+ * @param phFile Where to store the file handle on success.
+ * @param pszFormat The name format, either absolute or relative to "/sys/".
+ * @param ... The format args.
+ *
+ * @note Close the file using RTFileClose().
+ */
+RTDECL(int) RTLinuxSysFsOpen(PRTFILE phFile, const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(2, 3);
+
+/**
+ * Opens a sysfs file - extended version.
+ *
+ * @returns IPRT status code.
+ * @param phFile Where to store the file handle on success.
+ * @param fOpen Open flags, see RTFileOpen().
+ * @param pszFormat The name format, either absolute or relative to "/sys/".
+ * @param ... The format args.
+ */
+RTDECL(int) RTLinuxSysFsOpenEx(PRTFILE phFile, uint64_t fOpen, const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(3, 4);
+
+/**
+ * Reads a string from a file opened with RTLinuxSysFsOpen or RTLinuxSysFsOpenV.
+ *
+ * Expects to read the whole file, mind, and will return VERR_BUFFER_OVERFLOW if
+ * that is not possible with the given buffer size.
+ *
+ * @returns IPRT status code.
+ * @param hFile The file descriptor returned by RTLinuxSysFsOpen or RTLinuxSysFsOpenV.
+ * @param pszBuf Where to store the string.
+ * @param cchBuf The size of the buffer. Must be at least 2 bytes.
+ * @param pcchRead Where to store the amount of characters read on success - optional.
+ */
+RTDECL(int) RTLinuxSysFsReadStr(RTFILE hFile, char *pszBuf, size_t cchBuf, size_t *pcchRead);
+
+/**
+ * Writes a string to a file opened with RTLinuxSysFsOpenEx or RTLinuxSysFsOpenExV for writing.
+ *
+ * @returns IPRT status code.
+ * @param hFile The file descriptor returned by RTLinuxSysFsOpenEx or RTLinuxSysFsOpenExV.
+ * @param pszBuf The string to write.
+ * @param cchBuf The length of the string to write - if 0 is given
+ * the string length is determined before writing it including the zero terminator.
+ * @param pcchWritten Where to store the amount of characters written on success - optional.
+ */
+RTDECL(int) RTLinuxSysFsWriteStr(RTFILE hFile, const char *pszBuf, size_t cchBuf, size_t *pcchWritten);
+
+/**
+ * Reads the remainder of a file opened with RTLinuxSysFsOpen or
+ * RTLinuxSysFsOpenV.
+ *
+ * @returns IPRT status code.
+ * @param hFile The file descriptor returned by RTLinuxSysFsOpen or RTLinuxSysFsOpenV.
+ * @param pvBuf Where to store the bits from the file.
+ * @param cbBuf The size of the buffer.
+ * @param pcbRead Where to return the number of bytes read. Optional.
+ */
+RTDECL(int) RTLinuxSysFsReadFile(RTFILE hFile, void *pvBuf, size_t cbBuf, size_t *pcbRead);
+
+/**
+ * Writes the given buffer to a file opened with RTLinuxSysFsOpenEx or
+ * RTLinuxSysFsOpenExV.
+ *
+ * @returns IPRT status code.
+ * @param hFile The file descriptor returned by RTLinuxSysFsOpenEx or RTLinuxSysFsOpenExV.
+ * @param pvBuf The data to write.
+ * @param cbBuf The size of the buffer.
+ * @param pcbWritten Where to return the number of bytes read. Optional.
+ */
+RTDECL(int) RTLinuxSysFsWriteFile(RTFILE hFile, void *pvBuf, size_t cbBuf, size_t *pcbWritten);
+
+/**
+ * Reads a number from a sysfs file.
+ *
+ * @returns IPRT status code.
+ * @param uBase The number base, 0 for autodetect.
+ * @param pi64 Where to store the 64-bit signed on success.
+ * @param pszFormat The filename format, either absolute or relative to "/sys/".
+ * @param va Format args.
+ */
+RTDECL(int) RTLinuxSysFsReadIntFileV(unsigned uBase, int64_t *pi64, const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(3, 0);
+
+/**
+ * Reads a number from a sysfs file.
+ *
+ * @returns IPRT status code.
+ * @param uBase The number base, 0 for autodetect.
+ * @param pi64 Where to store the 64-bit signed on success.
+ * @param pszFormat The filename format, either absolute or relative to "/sys/".
+ * @param ... Format args.
+ */
+RTDECL(int) RTLinuxSysFsReadIntFile(unsigned uBase, int64_t *pi64, const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(3, 4);
+
+/**
+ * Writes an unsigned 8-bit number to a sysfs file.
+ *
+ * @returns IPRT status code.
+ * @param uBase The base format to write the number. Passing 16 here for
+ * example writes the number as a hexadecimal string with 0x prepended.
+ * @param u8 The number to write.
+ * @param pszFormat The filename format, either absolute or relative to "/sys/".
+ * @param va Format args.
+ */
+RTDECL(int) RTLinuxSysFsWriteU8FileV(unsigned uBase, uint8_t u8, const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(3, 0);
+
+/**
+ * Writes an unsigned 8-bit number to a sysfs file.
+ *
+ * @returns IPRT status code.
+ * @param uBase The base format to write the number. Passing 16 here for
+ * example writes the number as a hexadecimal string with 0x prepended.
+ * @param u8 The number to write.
+ * @param pszFormat The filename format, either absolute or relative to "/sys/".
+ * @param ... Format args.
+ */
+RTDECL(int) RTLinuxSysFsWriteU8File(unsigned uBase, uint8_t u8, const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(3, 4);
+
+/**
+ * Writes an unsigned 16-bit number to a sysfs file.
+ *
+ * @returns IPRT status code.
+ * @param uBase The base format to write the number. Passing 16 here for
+ * example writes the number as a hexadecimal string with 0x prepended.
+ * @param u16 The number to write.
+ * @param pszFormat The filename format, either absolute or relative to "/sys/".
+ * @param va Format args.
+ */
+RTDECL(int) RTLinuxSysFsWriteU16FileV(unsigned uBase, uint16_t u16, const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(3, 0);
+
+/**
+ * Writes an unsigned 16-bit number to a sysfs file.
+ *
+ * @returns IPRT status code.
+ * @param uBase The base format to write the number. Passing 16 here for
+ * example writes the number as a hexadecimal string with 0x prepended.
+ * @param u16 The number to write.
+ * @param pszFormat The filename format, either absolute or relative to "/sys/".
+ * @param ... Format args.
+ */
+RTDECL(int) RTLinuxSysFsWriteU16File(unsigned uBase, uint16_t u16, const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(3, 4);
+
+/**
+ * Writes an unsigned 32-bit number to a sysfs file.
+ *
+ * @returns IPRT status code.
+ * @param uBase The base format to write the number. Passing 16 here for
+ * example writes the number as a hexadecimal string with 0x prepended.
+ * @param u32 The number to write.
+ * @param pszFormat The filename format, either absolute or relative to "/sys/".
+ * @param va Format args.
+ */
+RTDECL(int) RTLinuxSysFsWriteU32FileV(unsigned uBase, uint32_t u32, const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(3, 0);
+
+/**
+ * Writes an unsigned 8-bit number to a sysfs file.
+ *
+ * @returns IPRT status code.
+ * @param uBase The base format to write the number. Passing 16 here for
+ * example writes the number as a hexadecimal string with 0x prepended.
+ * @param u32 The number to write.
+ * @param pszFormat The filename format, either absolute or relative to "/sys/".
+ * @param ... Format args.
+ */
+RTDECL(int) RTLinuxSysFsWriteU32File(unsigned uBase, uint32_t u32, const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(3, 4);
+
+/**
+ * Writes an unsigned 64-bit number to a sysfs file.
+ *
+ * @returns IPRT status code.
+ * @param uBase The base format to write the number. Passing 16 here for
+ * example writes the number as a hexadecimal string with 0x prepended.
+ * @param u64 The number to write.
+ * @param pszFormat The filename format, either absolute or relative to "/sys/".
+ * @param va Format args.
+ */
+RTDECL(int) RTLinuxSysFsWriteU64FileV(unsigned uBase, uint64_t u64, const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(3, 0);
+
+/**
+ * Writes an unsigned 8-bit number to a sysfs file.
+ *
+ * @returns IPRT status code.
+ * @param uBase The base format to write the number. Passing 16 here for
+ * example writes the number as a hexadecimal string with 0x prepended.
+ * @param u64 The number to write.
+ * @param pszFormat The filename format, either absolute or relative to "/sys/".
+ * @param ... Format args.
+ */
+RTDECL(int) RTLinuxSysFsWriteU64File(unsigned uBase, uint32_t u64, const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(3, 4);
+
+/**
+ * Reads a device number from a sysfs file.
+ *
+ * @returns IPRT status code.
+ * @param pDevNum Where to store the device number on success.
+ * @param pszFormat The filename format, either absolute or relative to "/sys/".
+ * @param va Format args.
+ */
+RTDECL(int) RTLinuxSysFsReadDevNumFileV(dev_t *pDevNum, const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(2, 0);
+
+/**
+ * Reads a device number from a sysfs file.
+ *
+ * @returns IPRT status code.
+ * @param pDevNum Where to store the device number on success.
+ * @param pszFormat The filename format, either absolute or relative to "/sys/".
+ * @param ... Format args.
+ */
+RTDECL(int) RTLinuxSysFsReadDevNumFile(dev_t *pDevNum, const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(2, 3);
+
+/**
+ * Reads a string from a sysfs file.
+ *
+ * If the file contains a newline, we only return the text up until there. This
+ * differs from the RTLinuxSysFsReadStr() behaviour.
+ *
+ * @returns IPRT status code.
+ * @param pszBuf Where to store the path element. Must be at least two
+ * characters, but a longer buffer would be advisable.
+ * @param cchBuf The size of the buffer pointed to by @a pszBuf.
+ * @param pcchRead Where to store the amount of characters read on success - optional.
+ * @param pszFormat The filename format, either absolute or relative to "/sys/".
+ * @param va Format args.
+ */
+RTDECL(int) RTLinuxSysFsReadStrFileV(char *pszBuf, size_t cchBuf, size_t *pcchRead, const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(4, 0);
+
+/**
+ * Reads a string from a sysfs file. If the file contains a newline, we only
+ * return the text up until there.
+ *
+ * @returns IPRT status code.
+ * @param pszBuf Where to store the path element. Must be at least two
+ * characters, but a longer buffer would be advisable.
+ * @param cchBuf The size of the buffer pointed to by @a pszBuf.
+ * @param pcchRead Where to store the amount of characters read on success - optional.
+ * @param pszFormat The filename format, either absolute or relative to "/sys/".
+ * @param ... Format args.
+ */
+RTDECL(int) RTLinuxSysFsReadStrFile(char *pszBuf, size_t cchBuf, size_t *pcchRead, const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(4, 5);
+
+/**
+ * Writes a string to a sysfs file.
+ *
+ * @returns IPRT status code.
+ * @param pszBuf The string to write.
+ * @param cchBuf The size of the buffer pointed to by @a pszBuf.
+ * @param pcchWritten Where to store the amount of characters written on success - optional.
+ * @param pszFormat The filename format, either absolute or relative to "/sys/".
+ * @param va Format args.
+ */
+RTDECL(int) RTLinuxSysFsWriteStrFileV(const char *pszBuf, size_t cchBuf, size_t *pcchWritten, const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(4, 0);
+
+/**
+ * Writes a string to a sysfs file.
+ *
+ * @returns IPRT status code.
+ * @param pszBuf The string to write.
+ * @param cchBuf The size of the buffer pointed to by @a pszBuf.
+ * @param pcchWritten Where to store the amount of characters written on success - optional.
+ * @param pszFormat The filename format, either absolute or relative to "/sys/".
+ * @param ... Format args.
+ */
+RTDECL(int) RTLinuxSysFsWriteStrFile(const char *pszBuf, size_t cchBuf, size_t *pcchWritten, const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(4, 5);
+
+/**
+ * Reads the last element of the path of the file pointed to by the symbolic
+ * link specified.
+ *
+ * This is needed at least to get the name of the driver associated with a
+ * device, where pszFormat should be the "driver" link in the devices sysfs
+ * directory.
+ *
+ * @returns IPRT status code.
+ * @param pszBuf Where to store the path element. Must be at least two
+ * characters, but a longer buffer would be advisable.
+ * @param cchBuf The size of the buffer pointed to by @a pszBuf.
+ * @param pchBuf Where to store the length of the returned string on success - optional.
+ * @param pszFormat The filename format, either absolute or relative to "/sys/".
+ * @param va Format args.
+ */
+RTDECL(int) RTLinuxSysFsGetLinkDestV(char *pszBuf, size_t cchBuf, size_t *pchBuf, const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(4, 0);
+
+/**
+ * Reads the last element of the path of the file pointed to by the symbolic
+ * link specified.
+ *
+ * This is needed at least to get the name of the driver associated with a
+ * device, where pszFormat should be the "driver" link in the devices sysfs
+ * directory.
+ *
+ * @returns IPRT status code.
+ * @param pszBuf Where to store the path element. Must be at least two
+ * characters, but a longer buffer would be advisable.
+ * @param cchBuf The size of the buffer pointed to by @a pszBuf.
+ * @param pchBuf Where to store the length of the returned string on success - optional.
+ * @param pszFormat The filename format, either absolute or relative to "/sys/".
+ * @param ... Format args.
+ */
+RTDECL(int) RTLinuxSysFsGetLinkDest(char *pszBuf, size_t cchBuf, size_t *pchBuf, const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(4, 5);
+
+/**
+ * Check the path of a device node under /dev, given the device number and a
+ * pattern and store the path into @a pszBuf.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_FILE_NOT_FOUND if no matching device node could be found.
+ * @param DevNum The device number to search for.
+ * @param fMode The type of device - only RTFS_TYPE_DEV_CHAR and
+ * RTFS_TYPE_DEV_BLOCK are valid values.
+ * @param pszBuf Where to store the path.
+ * @param cchBuf The size of the buffer.
+ * @param pszPattern The expected path format of the device node, either
+ * absolute or relative to "/dev".
+ * @param va Format args.
+ */
+RTDECL(int) RTLinuxCheckDevicePathV(dev_t DevNum, RTFMODE fMode, char *pszBuf, size_t cchBuf,
+ const char *pszPattern, va_list va) RT_IPRT_FORMAT_ATTR(5, 0);
+
+/**
+ * Check the path of a device node under /dev, given the device number and a
+ * pattern and store the path into @a pszBuf.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_FILE_NOT_FOUND if no matching device node could be found.
+ * @param DevNum The device number to search for
+ * @param fMode The type of device - only RTFS_TYPE_DEV_CHAR and
+ * RTFS_TYPE_DEV_BLOCK are valid values
+ * @param pszBuf Where to store the path.
+ * @param cchBuf The size of the buffer.
+ * @param pszPattern The expected path format of the device node, either
+ * absolute or relative to "/dev".
+ * @param ... Format args.
+ */
+RTDECL(int) RTLinuxCheckDevicePath(dev_t DevNum, RTFMODE fMode, char *pszBuf, size_t cchBuf,
+ const char *pszPattern, ...) RT_IPRT_FORMAT_ATTR(5, 6);
+
+/**
+ * Constructs the path of a sysfs file from the format parameters passed,
+ * prepending "/sys/" if the path is relative.
+ *
+ * @returns IPRT status code.
+ * @param pszPath Where to write the path.
+ * @param cbPath The size of the buffer pointed to by @a pszPath.
+ * @param pszFormat The name format, either absolute or relative to "/sys/".
+ * @param va The format args.
+ */
+RTDECL(int) RTLinuxConstructPathV(char *pszPath, size_t cbPath, const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(3, 0);
+
+/**
+ * Constructs the path of a sysfs file from the format parameters passed,
+ * prepending "/sys/" if the path is relative.
+ *
+ * @returns IPRT status code.
+ * @param pszPath Where to write the path.
+ * @param cbPath The size of the buffer pointed to by @a pszPath.
+ * @param pszFormat The name format, either absolute or relative to "/sys/".
+ * @param ... The format args.
+ */
+RTDECL(int) RTLinuxConstructPath(char *pszPath, size_t cbPath, const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(3, 4);
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_linux_sysfs_h */
+
diff --git a/include/iprt/linux/version.h b/include/iprt/linux/version.h
new file mode 100644
index 00000000..6badeab0
--- /dev/null
+++ b/include/iprt/linux/version.h
@@ -0,0 +1,205 @@
+/* $Id: version.h $ */
+/** @file
+ * IPRT - Linux kernel version.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_linux_version_h
+#define IPRT_INCLUDED_linux_version_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <linux/version.h>
+
+/* We need utsrelease.h in order to detect Ubuntu kernel,
+ * i.e. check if UTS_UBUNTU_RELEASE_ABI is defined. Support kernels
+ * starting from Ubuntu 14.04 Trusty which is based on upstream
+ * kernel 3.13.x. */
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,13,0))
+# include <generated/utsrelease.h>
+# include <iprt/cdefs.h>
+#endif
+
+/** @def RTLNX_VER_MIN
+ * Evaluates to true if the linux kernel version is equal or higher to the
+ * one specfied. */
+#define RTLNX_VER_MIN(a_Major, a_Minor, a_Patch) \
+ (LINUX_VERSION_CODE >= KERNEL_VERSION(a_Major, a_Minor, a_Patch))
+
+/** @def RTLNX_VER_MAX
+ * Evaluates to true if the linux kernel version is less to the one specfied
+ * (exclusive). */
+#define RTLNX_VER_MAX(a_Major, a_Minor, a_Patch) \
+ (LINUX_VERSION_CODE < KERNEL_VERSION(a_Major, a_Minor, a_Patch))
+
+/** @def RTLNX_VER_RANGE
+ * Evaluates to true if the linux kernel version is equal or higher to the given
+ * minimum version and less (but not equal) to the maximum version (exclusive). */
+#define RTLNX_VER_RANGE(a_MajorMin, a_MinorMin, a_PatchMin, a_MajorMax, a_MinorMax, a_PatchMax) \
+ ( LINUX_VERSION_CODE >= KERNEL_VERSION(a_MajorMin, a_MinorMin, a_PatchMin) \
+ && LINUX_VERSION_CODE < KERNEL_VERSION(a_MajorMax, a_MinorMax, a_PatchMax) )
+
+
+/** @def RTLNX_RHEL_MIN
+ * Require a minium RedHat release.
+ * @param a_iMajor The major release number (RHEL_MAJOR).
+ * @param a_iMinor The minor release number (RHEL_MINOR).
+ * @sa RTLNX_RHEL_MAX, RTLNX_RHEL_RANGE, RTLNX_RHEL_MAJ_PREREQ
+ */
+#if defined(RHEL_MAJOR) && defined(RHEL_MINOR)
+# define RTLNX_RHEL_MIN(a_iMajor, a_iMinor) \
+ ((RHEL_MAJOR) > (a_iMajor) || ((RHEL_MAJOR) == (a_iMajor) && (RHEL_MINOR) >= (a_iMinor)))
+#else
+# define RTLNX_RHEL_MIN(a_iMajor, a_iMinor) (0)
+#endif
+
+/** @def RTLNX_RHEL_MAX
+ * Require a maximum RedHat release, true for all RHEL versions below it.
+ * @param a_iMajor The major release number (RHEL_MAJOR).
+ * @param a_iMinor The minor release number (RHEL_MINOR).
+ * @sa RTLNX_RHEL_MIN, RTLNX_RHEL_RANGE, RTLNX_RHEL_MAJ_PREREQ
+ */
+#if defined(RHEL_MAJOR) && defined(RHEL_MINOR)
+# define RTLNX_RHEL_MAX(a_iMajor, a_iMinor) \
+ ((RHEL_MAJOR) < (a_iMajor) || ((RHEL_MAJOR) == (a_iMajor) && (RHEL_MINOR) < (a_iMinor)))
+#else
+# define RTLNX_RHEL_MAX(a_iMajor, a_iMinor) (0)
+#endif
+
+/** @def RTLNX_RHEL_RANGE
+ * Check that it's a RedHat kernel in the given version range.
+ * The max version is exclusive, the minimum inclusive.
+ * @sa RTLNX_RHEL_MIN, RTLNX_RHEL_MAX, RTLNX_RHEL_MAJ_PREREQ
+ */
+#if defined(RHEL_MAJOR) && defined(RHEL_MINOR)
+# define RTLNX_RHEL_RANGE(a_iMajorMin, a_iMinorMin, a_iMajorMax, a_iMinorMax) \
+ (RTLNX_RHEL_MIN(a_iMajorMin, a_iMinorMin) && RTLNX_RHEL_MAX(a_iMajorMax, a_iMinorMax))
+#else
+# define RTLNX_RHEL_RANGE(a_iMajorMin, a_iMinorMin, a_iMajorMax, a_iMinorMax) (0)
+#endif
+
+/** @def RTLNX_RHEL_MAJ_PREREQ
+ * Require a minimum minor release number for the given RedHat release.
+ * @param a_iMajor RHEL_MAJOR must _equal_ this.
+ * @param a_iMinor RHEL_MINOR must be greater or equal to this.
+ * @sa RTLNX_RHEL_MIN, RTLNX_RHEL_MAX
+ */
+#if defined(RHEL_MAJOR) && defined(RHEL_MINOR)
+# define RTLNX_RHEL_MAJ_PREREQ(a_iMajor, a_iMinor) ((RHEL_MAJOR) == (a_iMajor) && (RHEL_MINOR) >= (a_iMinor))
+#else
+# define RTLNX_RHEL_MAJ_PREREQ(a_iMajor, a_iMinor) (0)
+#endif
+
+
+/** @def RTLNX_SUSE_MAJ_PREREQ
+ * Require a minimum minor release number for the given SUSE release.
+ * @param a_iMajor CONFIG_SUSE_VERSION must _equal_ this.
+ * @param a_iMinor CONFIG_SUSE_PATCHLEVEL must be greater or equal to this.
+ */
+#if defined(CONFIG_SUSE_VERSION) && defined(CONFIG_SUSE_PATCHLEVEL)
+# define RTLNX_SUSE_MAJ_PREREQ(a_iMajor, a_iMinor) ((CONFIG_SUSE_VERSION) == (a_iMajor) && (CONFIG_SUSE_PATCHLEVEL) >= (a_iMinor))
+#else
+# define RTLNX_SUSE_MAJ_PREREQ(a_iMajor, a_iMinor) (0)
+#endif
+
+
+#if defined(UTS_UBUNTU_RELEASE_ABI) || defined(DOXYGEN_RUNNING)
+
+/** Hack to make the UTS_UBUNTU_RELEASE_ABI palatable by the C preprocesor.
+ *
+ * While the Ubuntu kernel ABI version looks like a decimal number, some
+ * kernels has a leading zero (e.g. 050818) that makes the preprocessor think
+ * it's an octal number. To work around that, we turn it into an hexadecimal
+ * number by prefixing it with '0x'. */
+# define RTLNX_UBUNTU_ABI(a_iAbi) (RT_CONCAT(0x,a_iAbi))
+
+/** @def RTLNX_UBUNTU_ABI_MIN
+ * Require Ubuntu release ABI to be equal or newer than specified version.
+ *
+ * The kernel version should exactly match the specified @a a_iMajor, @a
+ * a_iMinor and @a a_iPatch. The @a a_iAbi number should be equal to or greater
+ * than the current ABI version.
+ *
+ * @param a_iMajor The major kernel version number.
+ * @param a_iMinor The minor kernel version number.
+ * @param a_iPatch The kernel patch level.
+ * @param a_iAbi Ubuntu kernel ABI version number (inclusive).
+ */
+# define RTLNX_UBUNTU_ABI_MIN(a_iMajor, a_iMinor, a_iPatch, a_iAbi) \
+ ( KERNEL_VERSION(a_iMajor, a_iMinor, a_iPatch) == LINUX_VERSION_CODE \
+ && RTLNX_UBUNTU_ABI(UTS_UBUNTU_RELEASE_ABI) >= RTLNX_UBUNTU_ABI(a_iAbi))
+
+/** @def RTLNX_UBUNTU_ABI_MAX
+ * Require Ubuntu release ABI to be older than specified version.
+ *
+ * The kernel version should exactly match the specified @a a_iMajor, @a
+ * a_iMinor and @a a_iPatch. The @a a_iAbi number should be less than the
+ * current ABI version.
+ *
+ * @param a_iMajor The major kernel version number.
+ * @param a_iMinor The minor kernel version number.
+ * @param a_iPatch The kernel patch level.
+ * @param a_iAbi Ubuntu kernel ABI version number (exclusive).
+ */
+# define RTLNX_UBUNTU_ABI_MAX(a_iMajor, a_iMinor, a_iPatch, a_iAbi) \
+ ( KERNEL_VERSION(a_iMajor, a_iMinor, a_iPatch) == LINUX_VERSION_CODE \
+ && RTLNX_UBUNTU_ABI(UTS_UBUNTU_RELEASE_ABI) < RTLNX_UBUNTU_ABI(a_iAbi))
+
+/** @def RTLNX_UBUNTU_ABI_RANGE
+ * Require Ubuntu release ABI to be in specified range.
+ *
+ * The kernel version should exactly match the specified @a a_iMajor, @a
+ * a_iMinor and @a a_iPatch. The numbers @a a_iAbiMin and @a a_iAbiMax specify
+ * ABI versions range. The max ABI version is exclusive, the minimum inclusive.
+ *
+ * @param a_iMajor The major kernel version number.
+ * @param a_iMinor The minor kernel version number.
+ * @param a_iPatch The kernel patch level.
+ * @param a_iAbiMin The minimum Ubuntu kernel ABI version number (inclusive).
+ * @param a_iAbiMax The maximum Ubuntu kernel ABI version number (exclusive).
+ */
+# define RTLNX_UBUNTU_ABI_RANGE(a_iMajor, a_iMinor, a_iPatch, a_iAbiMin, a_iAbiMax) \
+ ( RTLNX_UBUNTU_ABI_MIN(a_iMajor, a_iMinor, a_iPatch, a_iAbiMin) \
+ && RTLNX_UBUNTU_ABI_MAX(a_iMajor, a_iMinor, a_iPatch, a_iAbiMax))
+
+#else /* !UTS_UBUNTU_RELEASE_ABI */
+
+# define RTLNX_UBUNTU_ABI_MIN(a_iMajor, a_iMinor, a_iPatch, a_iAbi) (0)
+# define RTLNX_UBUNTU_ABI_MAX(a_iMajor, a_iMinor, a_iPatch, a_iAbi) (0)
+# define RTLNX_UBUNTU_ABI_RANGE(a_iMajorMin, a_iMinorMin, a_iPatchMin, a_iAbiMin, a_iAbiMax) (0)
+
+#endif /* !UTS_UBUNTU_RELEASE_ABI */
+
+#endif /* !IPRT_INCLUDED_linux_version_h */
+
diff --git a/include/iprt/list-off32.h b/include/iprt/list-off32.h
new file mode 100644
index 00000000..69a4efcf
--- /dev/null
+++ b/include/iprt/list-off32.h
@@ -0,0 +1,514 @@
+/** @file
+ * IPRT - Generic Doubly Linked List, using 32-bit offset instead of pointers.
+ */
+
+/*
+ * Copyright (C) 2010-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_list_off32_h
+#define IPRT_INCLUDED_list_off32_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+
+/** @defgroup grp_rt_list_off32 RTListOff32 - Generic Doubly Linked List based on 32-bit offset.
+ * @ingroup grp_rt
+ *
+ * This is the same as @ref grp_rt_list , except that instead of pointers we use
+ * 32-bit offsets. The list implementation is circular, with a dummy node as
+ * anchor. Be careful with the dummy node when walking the list.
+ *
+ * @{
+ */
+
+RT_C_DECLS_BEGIN
+
+/**
+ * A list node of a doubly linked list.
+ */
+typedef struct RTLISTOFF32NODE
+{
+ /** Offset to the next list node, relative to this structure. */
+ int32_t offNext;
+ /** Offset to the previous list node, relative to this structure. */
+ int32_t offPrev;
+} RTLISTOFF32NODE;
+/** Pointer to a list node. */
+typedef RTLISTOFF32NODE *PRTLISTOFF32NODE;
+/** Pointer to a const list node. */
+typedef RTLISTOFF32NODE const *PCRTLISTOFF32NODE;
+/** Pointer to a list node pointer. */
+typedef PRTLISTOFF32NODE *PPRTLISTOFF32NODE;
+
+/** The anchor (head/tail) of a doubly linked list.
+ *
+ * @remarks Please always use this instead of RTLISTOFF32NODE 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.
+ * @remarks Must be allocated in a similar manner as the nodes, so as to
+ * keep it within a 32-bit distance from them.
+ */
+typedef RTLISTOFF32NODE RTLISTOFF32ANCHOR;
+/** Pointer to a doubly linked list anchor. */
+typedef RTLISTOFF32ANCHOR *PRTLISTOFF32ANCHOR;
+/** Pointer to a const doubly linked list anchor. */
+typedef RTLISTOFF32ANCHOR const *PCRTLISTOFF32ANCHOR;
+
+
+/**
+ * Initialize a list.
+ *
+ * @param pList Pointer to an unitialised list.
+ */
+DECLINLINE(void) RTListOff32Init(PRTLISTOFF32NODE pList)
+{
+ pList->offNext = 0;
+ pList->offPrev = 0;
+}
+
+/**
+ * Internal macro for converting an offset to a pointer.
+ * @returns PRTLISTOFF32NODE
+ * @param a_pNode The node the offset is relative to.
+ * @param a_off The offset.
+ */
+#define RTLISTOFF32_TO_PTR(a_pNode, a_off) ((PRTLISTOFF32NODE)((intptr_t)(a_pNode) + (a_off)))
+
+/**
+ * Internal macro for getting the pointer to the next node.
+ * @returns PRTLISTOFF32NODE
+ * @param a_pNode The node the offset is relative to.
+ */
+#define RTLISTOFF32_NEXT_PTR(a_pNode) RTLISTOFF32_TO_PTR(a_pNode, (a_pNode)->offNext)
+
+/**
+ * Internal macro for getting the pointer to the previous node.
+ * @returns PRTLISTOFF32NODE
+ * @param a_pNode The node the offset is relative to.
+ */
+#define RTLISTOFF32_PREV_PTR(a_pNode) RTLISTOFF32_TO_PTR(a_pNode, (a_pNode)->offPrev)
+
+/**
+ * Internal macro for converting an a pointer to an offset.
+ * @returns offset
+ * @param a_pNode The node the offset is relative to.
+ * @param a_pOtherNode The pointer to convert.
+ */
+#define RTLISTOFF32_TO_OFF(a_pNode, a_pOtherNode) ((int32_t)((intptr_t)(a_pOtherNode) - (intptr_t)(a_pNode)))
+
+/**
+ * Internal macro for getting the pointer to the next node.
+ * @returns PRTLISTOFF32NODE
+ * @param a_pNode The node which offNext member should be set.
+ * @param a_pNewNext Pointer to the new next node.
+ */
+#define RTLISTOFF32_SET_NEXT_PTR(a_pNode, a_pNewNext) \
+ do { (a_pNode)->offNext = RTLISTOFF32_TO_OFF(a_pNode, a_pNewNext); } while (0)
+
+/**
+ * Internal macro for getting the pointer to the previous node.
+ * @returns PRTLISTOFF32NODE
+ * @param a_pNode The node which offPrev member should be set.
+ * @param a_pNewPrev Pointer to the new previous node.
+ */
+#define RTLISTOFF32_SET_PREV_PTR(a_pNode, a_pNewPrev) \
+ do { (a_pNode)->offPrev = RTLISTOFF32_TO_OFF(a_pNode, a_pNewPrev); } while (0)
+
+
+
+/**
+ * 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) RTListOff32Append(PRTLISTOFF32NODE pList, PRTLISTOFF32NODE pNode)
+{
+ PRTLISTOFF32NODE pLast = RTLISTOFF32_PREV_PTR(pList);
+ RTLISTOFF32_SET_NEXT_PTR(pLast, pNode);
+ RTLISTOFF32_SET_PREV_PTR(pNode, pLast);
+ RTLISTOFF32_SET_NEXT_PTR(pNode, pList);
+ RTLISTOFF32_SET_PREV_PTR(pList, 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) RTListOff32Prepend(PRTLISTOFF32NODE pList, PRTLISTOFF32NODE pNode)
+{
+ PRTLISTOFF32NODE pFirst = RTLISTOFF32_NEXT_PTR(pList);
+ RTLISTOFF32_SET_PREV_PTR(pFirst, pNode);
+ RTLISTOFF32_SET_NEXT_PTR(pNode, pFirst);
+ RTLISTOFF32_SET_PREV_PTR(pNode, pList);
+ RTLISTOFF32_SET_NEXT_PTR(pList, pNode);
+}
+
+/**
+ * Inserts a node after the specified one.
+ *
+ * @param pCurNode The current node.
+ * @param pNewNode The node to insert.
+ */
+DECLINLINE(void) RTListOff32NodeInsertAfter(PRTLISTOFF32NODE pCurNode, PRTLISTOFF32NODE pNewNode)
+{
+ RTListOff32Prepend(pCurNode, pNewNode);
+}
+
+/**
+ * Inserts a node before the specified one.
+ *
+ * @param pCurNode The current node.
+ * @param pNewNode The node to insert.
+ */
+DECLINLINE(void) RTListOff32NodeInsertBefore(PRTLISTOFF32NODE pCurNode, PRTLISTOFF32NODE pNewNode)
+{
+ RTListOff32Append(pCurNode, pNewNode);
+}
+
+/**
+ * Remove a node from a list.
+ *
+ * @param pNode The node to remove.
+ */
+DECLINLINE(void) RTListOff32NodeRemove(PRTLISTOFF32NODE pNode)
+{
+ PRTLISTOFF32NODE pPrev = RTLISTOFF32_PREV_PTR(pNode);
+ PRTLISTOFF32NODE pNext = RTLISTOFF32_NEXT_PTR(pNode);
+
+ RTLISTOFF32_SET_NEXT_PTR(pPrev, pNext);
+ RTLISTOFF32_SET_PREV_PTR(pNext, pPrev);
+
+ /* poison */
+ pNode->offNext = INT32_MAX / 2;
+ pNode->offPrev = INT32_MAX / 2;
+}
+
+/**
+ * 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 RTListOff32NodeIsLast(pList, pNode) (RTLISTOFF32_NEXT_PTR(pNode) == (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 RTListOff32NodeIsFirst(pList, pNode) (RTLISTOFF32_PREV_PTR(pNode) == (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 RTListOff32NodeGetNext()
+ * or RTListOff32NodeGetPrev(). This is NOT a
+ * PRTLISTOFF32NODE but something that contains a
+ * RTLISTOFF32NODE member!
+ * @param Type Structure the list node is a member of.
+ * @param Member The list node member.
+ */
+#define RTListOff32NodeIsDummy(pList, pNode, Type, Member) \
+ ( (pNode) == RT_FROM_MEMBER((pList), Type, Member) )
+/** @copydoc RTListOff32NodeIsDummy */
+#define RTListOff32NodeIsDummyCpp(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 RTListOff32IsEmpty(pList) ((pList)->offNext == 0)
+
+/**
+ * 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 RTListOff32NodeGetNext(pCurNode, Type, Member) \
+ RT_FROM_MEMBER(RTLISTOFF32_NEXT_PTR(pCurNode), Type, Member)
+/** @copydoc RTListOff32NodeGetNext */
+#define RTListOff32NodeGetNextCpp(pCurNode, Type, Member) \
+ RT_FROM_CPP_MEMBER(RTLISTOFF32_NEXT_PTR(pCurNode), 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 RTListOff32NodeGetPrev(pCurNode, Type, Member) \
+ RT_FROM_MEMBER(RTLISTOFF32_PREV_PTR(pCurNode), Type, Member)
+/** @copydoc RTListOff32NodeGetPrev */
+#define RTListOff32NodeGetPrevCpp(pCurNode, Type, Member) \
+ RT_FROM_CPP_MEMBER(RTLISTOFF32_PREV_PTR(pCurNode), Type, Member)
+
+/**
+ * Returns the first element in the list (checks for empty list).
+ *
+ * @retval Pointer to the first list element.
+ * @retval NULL if the list is empty.
+ *
+ * @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 RTListOff32GetFirst(pList, Type, Member) \
+ ((pList)->offNext != 0 ? RTListOff32NodeGetNext(pList, Type, Member) : NULL)
+/** @copydoc RTListOff32GetFirst */
+#define RTListOff32GetFirstCpp(pList, Type, Member) \
+ ((pList)->offNext != 0 ? RTListOff32NodeGetNextCpp(pList, Type, Member) : NULL)
+
+/**
+ * Returns the last element in the list (checks for empty list).
+ *
+ * @retval Pointer to the last list element.
+ * @retval NULL if the list is empty.
+ *
+ * @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 RTListOff32GetLast(pList, Type, Member) \
+ ((pList)->offPrev != 0 ? RTListOff32NodeGetPrev(pList, Type, Member) : NULL)
+/** @copydoc RTListOff32GetLast */
+#define RTListOff32GetLastCpp(pList, Type, Member) \
+ ((pList)->offPrev != 0 ? RTListOff32NodeGetPrevCpp(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.
+ *
+ * @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 RTListOff32GetNext(pList, pCurNode, Type, Member) \
+ ( RTLISTOFF32_NEXT_PTR(&(pCurNode)->Member) != (pList) \
+ ? RT_FROM_MEMBER(RTLISTOFF32_NEXT_PTR(&(pCurNode)->Member), Type, Member) : NULL )
+/** @copydoc RTListOff32GetNext */
+#define RTListOff32GetNextCpp(pList, pCurNode, Type, Member) \
+ ( RTLISTOFF32_NEXT_PTR(&(pCurNode)->Member) != (pList) \
+ ? RT_FROM_CPP_MEMBER(RTLISTOFF32_NEXT_PTR(&(pCurNode)->Member), Type, Member) : NULL )
+
+/**
+ * Returns the previous node in the list or NULL if the start has been reached.
+ *
+ * @returns The previous node or NULL.
+ *
+ * @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 RTListOff32GetPrev(pList, pCurNode, Type, Member) \
+ ( RTLISTOFF32_PREV_PTR(&(pCurNode)->Member) != (pList) \
+ ? RT_FROM_MEMBER(RTLISTOFF32_PREV_PTR(&(pCurNode)->Member), Type, Member) : NULL )
+/** @copydoc RTListOff32GetPrev */
+#define RTListOff32GetPrevCpp(pList, pCurNode, Type, Member) \
+ ( RTLISTOFF32_PREV_PTR(&(pCurNode)->Member) != (pList) \
+ ? RT_FROM_CPP_MEMBER(RTLISTOFF32_PREV_PTR(&(pCurNode)->Member), 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 RTListOff32ForEach(pList, pIterator, Type, Member) \
+ for (pIterator = RTListOff32NodeGetNext(pList, Type, Member); \
+ !RTListOff32NodeIsDummy(pList, pIterator, Type, Member); \
+ pIterator = RT_FROM_MEMBER(RTLISTOFF32_NEXT_PTR(&(pIterator)->Member), Type, Member) )
+/** @copydoc RTListOff32ForEach */
+#define RTListOff32ForEachCpp(pList, pIterator, Type, Member) \
+ for (pIterator = RTListOff32NodeGetNextCpp(pList, Type, Member); \
+ !RTListOff32NodeIsDummyCpp(pList, pIterator, Type, Member); \
+ pIterator = RT_FROM_CPP_MEMBER(RTLISTOFF32_NEXT_PTR(&(pIterator)->Member), 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 RTListOff32ForEachSafe(pList, pIterator, pIterNext, Type, Member) \
+ for (pIterator = RTListOff32NodeGetNext(pList, Type, Member), \
+ pIterNext = RT_FROM_MEMBER(RTLISTOFF32_NEXT_PTR(&(pIterator)->Member), Type, Member); \
+ !RTListOff32NodeIsDummy(pList, pIterator, Type, Member); \
+ pIterator = pIterNext, \
+ pIterNext = RT_FROM_MEMBER(RTLISTOFF32_NEXT_PTR(&(pIterator)->Member), Type, Member) )
+/** @copydoc RTListOff32ForEachSafe */
+#define RTListOff32ForEachSafeCpp(pList, pIterator, pIterNext, Type, Member) \
+ for (pIterator = RTListOff32NodeGetNextCpp(pList, Type, Member), \
+ pIterNext = RT_FROM_CPP_MEMBER(RTLISTOFF32_NEXT_PTR(&(pIterator)->Member), Type, Member); \
+ !RTListOff32NodeIsDummyCpp(pList, pIterator, Type, Member); \
+ pIterator = pIterNext, \
+ pIterNext = RT_FROM_CPP_MEMBER(RTLISTOFF32_NEXT_PTR(&(pIterator)->Member), 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 RTListOff32ForEachReverse(pList, pIterator, Type, Member) \
+ for (pIterator = RTListOff32NodeGetPrev(pList, Type, Member); \
+ !RTListOff32NodeIsDummy(pList, pIterator, Type, Member); \
+ pIterator = RT_FROM_MEMBER(RTLISTOFF32_NEXT_PTR(&(pIterator)->Member), Type, Member) )
+/** @copydoc RTListOff32ForEachReverse */
+#define RTListOff32ForEachReverseCpp(pList, pIterator, Type, Member) \
+ for (pIterator = RTListOff32NodeGetPrevCpp(pList, Type, Member); \
+ !RTListOff32NodeIsDummyCpp(pList, pIterator, Type, Member); \
+ pIterator = RT_FROM_CPP_MEMBER(RTLISTOFF32_PREV_PTR(&(pIterator)->Member), 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 RTListOff32ForEachReverseSafe(pList, pIterator, pIterPrev, Type, Member) \
+ for (pIterator = RTListOff32NodeGetPrev(pList, Type, Member), \
+ pIterPrev = RT_FROM_MEMBER(RTLISTOFF32_NEXT_PTR(&(pIterator)->Member), Type, Member); \
+ !RTListOff32NodeIsDummy(pList, pIterator, Type, Member); \
+ pIterator = pIterPrev, \
+ pIterPrev = RT_FROM_MEMBER(RTLISTOFF32_NEXT_PTR(&(pIterator)->Member), Type, Member) )
+/** @copydoc RTListOff32ForEachReverseSafe */
+#define RTListOff32ForEachReverseSafeCpp(pList, pIterator, pIterPrev, Type, Member) \
+ for (pIterator = RTListOff32NodeGetPrevCpp(pList, Type, Member), \
+ pIterPrev = RT_FROM_CPP_MEMBER(RTLISTOFF32_NEXT_PTR(&(pIterator)->Member), Type, Member); \
+ !RTListOff32NodeIsDummyCpp(pList, pIterator, Type, Member); \
+ pIterator = pIterPrev, \
+ pIterPrev = RT_FROM_CPP_MEMBER(RTLISTOFF32_NEXT_PTR(&(pIterator)->Member), Type, Member) )
+
+
+/**
+ * Move the given list to a new list header.
+ *
+ * @param pListDst The new list.
+ * @param pListSrc The list to move.
+ */
+DECLINLINE(void) RTListOff32Move(PRTLISTOFF32NODE pListDst, PRTLISTOFF32NODE pListSrc)
+{
+ if (!RTListOff32IsEmpty(pListSrc))
+ {
+ PRTLISTOFF32NODE pFirst = RTLISTOFF32_NEXT_PTR(pListSrc);
+ PRTLISTOFF32NODE pLast = RTLISTOFF32_PREV_PTR(pListSrc);
+
+ RTLISTOFF32_SET_NEXT_PTR(pListDst, pFirst);
+ RTLISTOFF32_SET_PREV_PTR(pListDst, pLast);
+
+ /* Adjust the first and last element links */
+ RTLISTOFF32_SET_NEXT_PTR(pLast, pListDst);
+ RTLISTOFF32_SET_PREV_PTR(pFirst, pListDst);
+
+ /* Finally remove the elements from the source list */
+ RTListOff32Init(pListSrc);
+ }
+}
+
+/**
+ * List concatenation.
+ *
+ * @returns nothing.
+ * @param pListDst The destination list.
+ * @param pListSrc The source list to concatenate.
+ */
+DECLINLINE(void) RTListOff32Concatenate(PRTLISTOFF32ANCHOR pListDst, PRTLISTOFF32ANCHOR pListSrc)
+{
+ if (!RTListOff32IsEmpty(pListSrc))
+ {
+ PRTLISTOFF32NODE pFirstSrc = RTLISTOFF32_NEXT_PTR(pListSrc);
+ PRTLISTOFF32NODE pLastSrc = RTLISTOFF32_PREV_PTR(pListSrc);
+ PRTLISTOFF32NODE pLastDst = RTLISTOFF32_PREV_PTR(pListDst);
+
+ RTLISTOFF32_SET_NEXT_PTR(pLastDst, pFirstSrc);
+ RTLISTOFF32_SET_PREV_PTR(pFirstSrc, pLastDst);
+
+ RTLISTOFF32_SET_NEXT_PTR(pLastSrc, pListDst);
+ RTLISTOFF32_SET_PREV_PTR(pListDst, pLastSrc);
+
+ /* Finally remove the elements from the source list */
+ RTListOff32Init(pListSrc);
+ }
+}
+
+/** @} */
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_list_off32_h */
+
diff --git a/include/iprt/list.h b/include/iprt/list.h
new file mode 100644
index 00000000..dbc1946f
--- /dev/null
+++ b/include/iprt/list.h
@@ -0,0 +1,560 @@
+/** @file
+ * IPRT - Generic Doubly Linked List.
+ */
+
+/*
+ * Copyright (C) 2010-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_list_h
+#define IPRT_INCLUDED_list_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#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. */
+#ifdef 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;
+
+/** Version of RTLISTNODE for holding a ring-0 only list in data which gets
+ * shared between multiple contexts. */
+#ifdef IN_RING0
+typedef RTLISTNODE RTLISTNODER0;
+#else
+typedef struct { RTR0PTR aOffLimits[2]; } RTLISTNODER0;
+#endif
+/** Version of RTLISTANCHOR for holding a ring-0 only list in data which gets
+ * shared between multiple contexts. */
+typedef RTLISTNODER0 RTLISTANCHORR0;
+
+
+/**
+ * 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);
+ }
+ else
+ RTListInit(pListDst);
+}
+
+/**
+ * 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 /* !IPRT_INCLUDED_list_h */
diff --git a/include/iprt/locale.h b/include/iprt/locale.h
new file mode 100644
index 00000000..3a83a5f5
--- /dev/null
+++ b/include/iprt/locale.h
@@ -0,0 +1,113 @@
+/** @file
+ * IPRT - Locale and Related Info.
+ */
+
+/*
+ * Copyright (C) 2017-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_locale_h
+#define IPRT_INCLUDED_locale_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_locale RTLocale - Locale and Related Info
+ * @ingroup grp_rt
+ * @{
+ */
+
+/**
+ * Returns the setlocale(LC_ALL,NULL) return value.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_NOT_SUPPORTED if not supported.
+ * @param pszName Where to return the name.
+ * @param cbName The size of the name buffer.
+ */
+RTDECL(int) RTLocaleQueryLocaleName(char *pszName, size_t cbName);
+
+/**
+ * Returns a normalized base locale name ('{ll}_{CC}' or 'C').
+ *
+ * @returns IPRT status code.
+ * @retval VERR_NOT_SUPPORTED if not supported.
+ * @param pszName Where to return the name.
+ * @param cbName The size of the name buffer.
+ *
+ * @sa RTLOCALE_IS_LANGUAGE2_UNDERSCORE_COUNTRY2
+ */
+RTDECL(int) RTLocaleQueryNormalizedBaseLocaleName(char *pszName, size_t cbName);
+
+/**
+ * Gets the two letter country code (ISO 3166-1 alpha-2) for the current user.
+ *
+ * This is not necessarily the country from the locale name, when possible the
+ * source is a different setting (host specific).
+ *
+ * @returns IPRT status code.
+ * @retval VERR_NOT_SUPPORTED if not supported.
+ * @param pszCountryCode Pointer buffer that's at least three bytes in size.
+ * The country code will be returned here on success.
+ */
+RTDECL(int) RTLocaleQueryUserCountryCode(char pszCountryCode[3]);
+
+
+/**
+ * Checks whether @a a_psz seems to start with a
+ * language-code-underscore-country-code sequence.
+ *
+ * We perform a check for a likely ISO 639-1 language code, followed by an
+ * underscore, followed by a likely ISO 3166-1 alpha-2 country code.
+ *
+ * @return true if probable '{ll}_{CC}' sequence, false if surely not.
+ * @param a_psz The string to test the start of.
+ *
+ * @note User must include iprt/ctype.h separately.
+ */
+#define RTLOCALE_IS_LANGUAGE2_UNDERSCORE_COUNTRY2(a_psz) \
+ ( RT_C_IS_LOWER((a_psz)[0]) \
+ && RT_C_IS_LOWER((a_psz)[1]) \
+ && (a_psz)[2] == '_' \
+ && RT_C_IS_UPPER((a_psz)[3]) \
+ && RT_C_IS_UPPER((a_psz)[4]) )
+
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_locale_h */
+
diff --git a/include/iprt/localipc.h b/include/iprt/localipc.h
new file mode 100644
index 00000000..e5baa5ab
--- /dev/null
+++ b/include/iprt/localipc.h
@@ -0,0 +1,354 @@
+/** @file
+ * IPRT - Local IPC Server & Client.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_localipc_h
+#define IPRT_INCLUDED_localipc_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+#include <iprt/thread.h>
+
+#ifdef IN_RING0
+# error "There are no RTLocalIpc APIs available Ring-0 Host Context!"
+#endif
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_localipc RTLocalIpc - Local IPC
+ * @ingroup grp_rt
+ * @{
+ */
+
+/** Handle to a local IPC server instance. */
+typedef struct RTLOCALIPCSERVERINT *RTLOCALIPCSERVER;
+/** Pointer to a local IPC server handle. */
+typedef RTLOCALIPCSERVER *PRTLOCALIPCSERVER;
+/** Local IPC server handle nil value. */
+#define NIL_RTLOCALIPCSERVER ((RTLOCALIPCSERVER)0)
+
+/** Handle to a local ICP session instance. */
+typedef struct RTLOCALIPCSESSIONINT *RTLOCALIPCSESSION;
+/** Pointer to a local ICP session handle. */
+typedef RTLOCALIPCSESSION *PRTLOCALIPCSESSION;
+/** Local ICP session handle nil value. */
+#define NIL_RTLOCALIPCSESSION ((RTLOCALIPCSESSION)0)
+
+
+
+/**
+ * Create a local IPC server.
+ *
+ * @returns IPRT status code.
+ * @retval VINF_SUCCESS on success and *phServer containing the instance handle.
+ *
+ * @param phServer Where to put the server instance handle.
+ * @param pszName The server name. This must be unique and not include
+ * any special chars or slashes. It will be morphed into a
+ * unique platform specific identifier.
+ * @param fFlags Flags, see RTLOCALIPC_FLAGS_*.
+ */
+RTDECL(int) RTLocalIpcServerCreate(PRTLOCALIPCSERVER phServer, const char *pszName, uint32_t fFlags);
+
+/** @name RTLocalIpcServerCreate flags
+ * @{ */
+/** Native name, as apposed to a portable one. */
+#define RTLOCALIPC_FLAGS_NATIVE_NAME RT_BIT_32(0)
+/** The mask of valid flags. */
+#define RTLOCALIPC_FLAGS_VALID_MASK UINT32_C(0x00000001)
+/** @} */
+
+/**
+ * Destroys a local IPC server.
+ *
+ * @returns IPRT status code.
+ * @retval VINF_SUCCESS if still other references or NIL.
+ * @retval VINF_OBJECT_DESTROYED if actually destroyed.
+ *
+ * @param hServer The server handle. The nil value is quietly ignored (VINF_SUCCESS).
+ */
+RTDECL(int) RTLocalIpcServerDestroy(RTLOCALIPCSERVER hServer);
+
+/**
+ * Grant the specified group access to the local IPC server socket.
+ *
+ * @returns IPRT status code.
+ * @param hServer The server handle.
+ * @param gid Group ID.
+ */
+RTDECL(int) RTLocalIpcServerGrantGroupAccess(RTLOCALIPCSERVER hServer, RTGID gid);
+
+/**
+ * Set access mode for IPC server socket.
+ *
+ * @returns IPRT status code.
+ * @param hServer The server handle.
+ * @param fMode Access mode.
+ */
+RTDECL(int) RTLocalIpcServerSetAccessMode(RTLOCALIPCSERVER hServer, RTFMODE fMode);
+
+/**
+ * Listen for clients.
+ *
+ * @returns IPRT status code.
+ * @retval VINF_SUCCESS on success and *phClientSession containing the session handle.
+ * @retval VERR_CANCELLED if the listening was interrupted by RTLocalIpcServerCancel().
+ *
+ * @param hServer The server handle.
+ * @param phClientSession Where to store the client session handle on success.
+ *
+ */
+RTDECL(int) RTLocalIpcServerListen(RTLOCALIPCSERVER hServer, PRTLOCALIPCSESSION phClientSession);
+
+/**
+ * Cancel the current or subsequent RTLocalIpcServerListen call.
+ *
+ * @returns IPRT status code.
+ * @param hServer The server handle. The nil value is quietly ignored (VINF_SUCCESS).
+ */
+RTDECL(int) RTLocalIpcServerCancel(RTLOCALIPCSERVER hServer);
+
+
+/**
+ * Connects to a local IPC server.
+ *
+ * This is used a client process (or thread).
+ *
+ * @returns IPRT status code.
+ * @retval VINF_SUCCESS on success and *phSession holding the session handle.
+ *
+ * @param phSession Where to store the sesson handle on success.
+ * @param pszName The server name (see RTLocalIpcServerCreate for details).
+ * @param fFlags Flags, RTLOCALIPC_C_FLAGS_XXX.
+ */
+RTDECL(int) RTLocalIpcSessionConnect(PRTLOCALIPCSESSION phSession, const char *pszName, uint32_t fFlags);
+
+/** @name RTLOCALIPC_C_FLAGS_XXX - RTLocalIpcSessionConnect flags
+ * @{ */
+/** Native name, as apposed to a portable one. */
+#define RTLOCALIPC_C_FLAGS_NATIVE_NAME RT_BIT_32(0)
+/** The mask of valid flags. */
+#define RTLOCALIPC_C_FLAGS_VALID_MASK UINT32_C(0x00000001)
+/** @} */
+
+/**
+ * Closes the local IPC session.
+ *
+ * This can be used with sessions created by both RTLocalIpcSessionConnect
+ * and RTLocalIpcServerListen. It will release one cancel pending I/O and
+ * relase one reference (typically the implict reference from the create API).
+ *
+ * @returns IPRT status code.
+ * @retval VINF_SUCCESS if still other references or NIL.
+ * @retval VINF_OBJECT_DESTROYED if session destroyed.
+ *
+ * @param hSession The session handle. The nil value is quietly ignored (VINF_SUCCESS).
+ */
+RTDECL(int) RTLocalIpcSessionClose(RTLOCALIPCSESSION hSession);
+
+/**
+ * Retain a refence to the given session.
+ *
+ * @returns New reference count, UINT32_MAX if the handle is invalid.
+ * @param hSession The session handle.
+ */
+RTDECL(uint32_t) RTLocalIpcSessionRetain(RTLOCALIPCSESSION hSession);
+
+/**
+ * Releases a refence to the given session.
+ *
+ * This differs from RTLocalIpcSessionClose in that it won't cancel any pending
+ * I/O. So, better call RTLocalIpcSessionClose if you want to terminate the
+ * session.
+ *
+ * @returns New reference count, 0 if NIL handle, UINT32_MAX if the handle is
+ * invalid.
+ * @param hSession The session handle.
+ */
+RTDECL(uint32_t) RTLocalIpcSessionRelease(RTLOCALIPCSESSION hSession);
+
+
+/**
+ * Receive data from the other end of an local IPC session.
+ *
+ * This will block if there isn't any data.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_CANCELLED if the operation was cancelled by RTLocalIpcSessionCancel.
+ *
+ * @param hSession The session handle.
+ * @param pvBuf Where to store the data.
+ * @param cbToRead How much to read. This is exact request if
+ * pcbRead is NULL, otherwise it's an upper limit.
+ * @param pcbRead Optional argument for indicating a partial read
+ * and returning the number of bytes actually read.
+ */
+RTDECL(int) RTLocalIpcSessionRead(RTLOCALIPCSESSION hSession, void *pvBuf, size_t cbToRead, size_t *pcbRead);
+
+/**
+ * Receive pending data from the other end of an local IPC session.
+ *
+ * This will not block to wait for data.
+ *
+ * @returns IPRT status code.
+ * @retval VINF_TRY_AGAIN if no pending data (*pcbRead is set to 0).
+ * @retval VERR_CANCELLED if a previous operation was cancelled by
+ * RTLocalIpcSessionCancel (this operation isn't cancellable).
+ *
+ * @param hSession The session handle.
+ * @param pvBuf Where to store the data.
+ * @param cbToRead How much to read (upper limit).
+ * @param pcbRead Where to return exactly how much was read.
+ */
+RTDECL(int) RTLocalIpcSessionReadNB(RTLOCALIPCSESSION hSession, void *pvBuf, size_t cbToRead, size_t *pcbRead);
+
+/**
+ * Send data to the other end of an local IPC session.
+ *
+ * This may or may not block until the data is received by the other party,
+ * this is an implementation detail. If you want to make sure that the data
+ * has been received you should always call RTLocalIpcSessionFlush().
+ *
+ * @returns IPRT status code.
+ * @retval VERR_CANCELLED if the operation was cancelled by RTLocalIpcSessionCancel.
+ *
+ * @param hSession The session handle.
+ * @param pvBuf The data to write.
+ * @param cbToWrite How much to write.
+ */
+RTDECL(int) RTLocalIpcSessionWrite(RTLOCALIPCSESSION hSession, const void *pvBuf, size_t cbToWrite);
+
+/**
+ * Flush any buffered data and (perhaps) wait for the other party to receive it.
+ *
+ * The waiting for the other party to receive the data is
+ * implementation dependent.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_CANCELLED if the operation was cancelled by RTLocalIpcSessionCancel.
+ *
+ * @param hSession The session handle.
+ */
+RTDECL(int) RTLocalIpcSessionFlush(RTLOCALIPCSESSION hSession);
+
+/**
+ * Wait for data to become ready for reading or for the session to be
+ * disconnected.
+ *
+ * @returns IPRT status code.
+ * @retval VINF_SUCCESS when there is data to read.
+ * @retval VERR_TIMEOUT if no data became available within the specified period (@a cMillies)
+ * @retval VERR_BROKEN_PIPE if the session was disconnected.
+ * @retval VERR_CANCELLED if the operation was cancelled by RTLocalIpcSessionCancel.
+ *
+ * @param hSession The session handle.
+ * @param cMillies The number of milliseconds to wait. Use RT_INDEFINITE_WAIT
+ * to wait forever.
+ *
+ * @remark VERR_INTERRUPTED will not be returned. If this is desired at some later point
+ * add a RTLocalIpcSessionWaitForDataNoResume() variant like we're using elsewhere.
+ */
+RTDECL(int) RTLocalIpcSessionWaitForData(RTLOCALIPCSESSION hSession, uint32_t cMillies);
+
+/**
+ * Cancells a pending or subsequent operation.
+ *
+ * Not all methods are cancellable, only those which are specfied
+ * returning VERR_CANCELLED. The others are assumed to not be blocking
+ * for ever and ever. However, the cancel is sticky, so the session must
+ * basically be trashed (closed) after calling this method.
+ *
+ * @returns IPRT status code.
+ *
+ * @param hSession The session handle.
+ */
+RTDECL(int) RTLocalIpcSessionCancel(RTLOCALIPCSESSION hSession);
+
+/**
+ * Query the process ID of the other party.
+ *
+ * This is an optional feature which may not be implemented, so don't
+ * depend on it and check for VERR_NOT_SUPPORTED.
+ *
+ * @returns IPRT status code.
+ * @retval VINF_SUCCESS and *pProcess on success.
+ * @retval VERR_CANCELLED if the operation was cancelled by RTLocalIpcSessionCancel.
+ * @retval VERR_NOT_SUPPORTED and *pProcess = NIL_RTPROCESS if not supported.
+ *
+ * @param hSession The session handle.
+ * @param pProcess Where to store the process ID.
+ */
+RTDECL(int) RTLocalIpcSessionQueryProcess(RTLOCALIPCSESSION hSession, PRTPROCESS pProcess);
+
+/**
+ * Query the user ID of the other party.
+ *
+ * This is an optional feature which may not be implemented, so don't
+ * depend on it and check for VERR_NOT_SUPPORTED.
+ *
+ * @returns IPRT status code.
+ * @retval VINF_SUCCESS and *pUid on success.
+ * @retval VERR_CANCELLED if the operation was cancelled by RTLocalIpcSessionCancel.
+ * @retval VERR_NOT_SUPPORTED and *pUid = NIL_RTUID if not supported.
+ *
+ * @param hSession The session handle.
+ * @param pUid Where to store the user ID on success.
+ */
+RTDECL(int) RTLocalIpcSessionQueryUserId(RTLOCALIPCSESSION hSession, PRTUID pUid);
+
+/**
+ * Query the group ID of the other party.
+ *
+ * This is an optional feature which may not be implemented, so don't
+ * depend on it and check for VERR_NOT_SUPPORTED.
+ *
+ * @returns IPRT status code.
+ * @retval VINF_SUCCESS and *pUid on success.
+ * @retval VERR_CANCELLED if the operation was cancelled by RTLocalIpcSessionCancel.
+ * @retval VERR_NOT_SUPPORTED and *pGid = NIL_RTUID if not supported.
+ *
+ * @param hSession The session handle.
+ * @param pGid Where to store the group ID on success.
+ */
+RTDECL(int) RTLocalIpcSessionQueryGroupId(RTLOCALIPCSESSION hSession, PRTGID pGid);
+
+/** @} */
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_localipc_h */
+
diff --git a/include/iprt/lockvalidator.h b/include/iprt/lockvalidator.h
new file mode 100644
index 00000000..829ed9f2
--- /dev/null
+++ b/include/iprt/lockvalidator.h
@@ -0,0 +1,1143 @@
+/** @file
+ * IPRT - Lock Validator.
+ */
+
+/*
+ * Copyright (C) 2009-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_lockvalidator_h
+#define IPRT_INCLUDED_lockvalidator_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#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 /* !IPRT_INCLUDED_lockvalidator_h */
+
diff --git a/include/iprt/log.h b/include/iprt/log.h
new file mode 100644
index 00000000..fd677b71
--- /dev/null
+++ b/include/iprt/log.h
@@ -0,0 +1,2869 @@
+/** @file
+ * IPRT - Logging.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_log_h
+#define IPRT_INCLUDED_log_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#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_FTP,
+ RTLOGGROUP_HTTP,
+ RTLOGGROUP_IOQUEUE,
+ RTLOGGROUP_LDR,
+ RTLOGGROUP_LOCALIPC,
+ RTLOGGROUP_PATH,
+ RTLOGGROUP_PROCESS,
+ RTLOGGROUP_REST,
+ RTLOGGROUP_SYMLINK,
+ RTLOGGROUP_THREAD,
+ RTLOGGROUP_TIME,
+ RTLOGGROUP_TIMER,
+ 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
+ *
+ * The RT_XX log group names are placeholders for new modules being added,
+ * to make sure that there always is a total of 32 log group entries.
+ */
+#define RT_LOGGROUP_NAMES \
+ "DEFAULT", \
+ "RT_CRYPTO", \
+ "RT_DBG", \
+ "RT_DBG_DWARF", \
+ "RT_DIR", \
+ "RT_FILE", \
+ "RT_FS", \
+ "RT_FTP", \
+ "RT_HTTP", \
+ "RT_IOQUEUE", \
+ "RT_LDR", \
+ "RT_LOCALIPC", \
+ "RT_PATH", \
+ "RT_PROCESS", \
+ "RT_REST", \
+ "RT_SYMLINK", \
+ "RT_THREAD", \
+ "RT_TIME", \
+ "RT_TIMER", \
+ "RT_VFS", \
+ "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 your 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. */
+typedef struct RTLOGGER RTLOGGER;
+/** Pointer to logger structure. */
+typedef RTLOGGER *PRTLOGGER;
+/** Pointer to const logger structure. */
+typedef const RTLOGGER *PCRTLOGGER;
+
+
+/** Pointer to a log buffer descriptor. */
+typedef struct RTLOGBUFFERDESC *PRTLOGBUFFERDESC;
+
+
+/**
+ * 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;
+
+
+#if 0 /* retired */
+/**
+ * Logger function.
+ *
+ * @param pszFormat Format string.
+ * @param ... Optional arguments as specified in the format string.
+ */
+typedef DECLCALLBACKTYPE(void, FNRTLOGGER,(const char *pszFormat, ...)) RT_IPRT_FORMAT_ATTR(1, 2);
+/** Pointer to logger function. */
+typedef FNRTLOGGER *PFNRTLOGGER;
+#endif
+
+/**
+ * Custom buffer flushing function.
+ *
+ * @retval true if flushed and the buffer can be reused.
+ * @retval false for switching to the next buffer because an async flush of
+ * @a pBufDesc is still pending. The implementation is responsible for
+ * only returning when the next buffer is ready for reuse, the generic
+ * logger code has no facility to make sure of this.
+ *
+ * @param pLogger Pointer to the logger instance which is to be flushed.
+ * @param pBufDesc The descriptor of the buffer to be flushed.
+ */
+typedef DECLCALLBACKTYPE(bool, FNRTLOGFLUSH,(PRTLOGGER pLogger, PRTLOGBUFFERDESC pBufDesc));
+/** Pointer to flush function. */
+typedef FNRTLOGFLUSH *PFNRTLOGFLUSH;
+
+/**
+ * Header/footer message callback.
+ *
+ * @param pLogger Pointer to the logger instance.
+ * @param pszFormat Format string.
+ * @param ... Optional arguments specified in the format string.
+ */
+typedef DECLCALLBACKTYPE(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 DECLCALLBACKTYPE(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 DECLCALLBACKTYPE(size_t, FNRTLOGPREFIX,(PRTLOGGER pLogger, char *pchBuf, size_t cchBuf, void *pvUser));
+/** Pointer to prefix callback function. */
+typedef FNRTLOGPREFIX *PFNRTLOGPREFIX;
+
+
+/** Pointer to a constant log output interface. */
+typedef const struct RTLOGOUTPUTIF *PCRTLOGOUTPUTIF;
+
+/**
+ * Logging output interface.
+ */
+typedef struct RTLOGOUTPUTIF
+{
+ /**
+ * Opens a new log file with the given name.
+ *
+ * @returns IPRT status code.
+ * @param pIf Pointer to this interface.
+ * @param pvUser Opaque user data passed when setting the callbacks.
+ * @param pszFilename The filename to open.
+ * @param fFlags Open flags, combination of RTFILE_O_XXX.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnOpen, (PCRTLOGOUTPUTIF pIf, void *pvUser, const char *pszFilename, uint32_t fFlags));
+
+ /**
+ * Closes the currently open file.
+ *
+ * @returns IPRT status code.
+ * @param pIf Pointer to this interface.
+ * @param pvUser Opaque user data passed when setting the callbacks.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnClose, (PCRTLOGOUTPUTIF pIf, void *pvUser));
+
+ /**
+ * Deletes the given file.
+ *
+ * @returns IPRT status code.
+ * @param pIf Pointer to this interface.
+ * @param pvUser Opaque user data passed when setting the callbacks.
+ * @param pszFilename The filename to delete.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnDelete, (PCRTLOGOUTPUTIF pIf, void *pvUser, const char *pszFilename));
+
+ /**
+ * Renames the given file.
+ *
+ * @returns IPRT status code.
+ * @param pIf Pointer to this interface.
+ * @param pvUser Opaque user data passed when setting the callbacks.
+ * @param pszFilenameOld The old filename to rename.
+ * @param pszFilenameNew The new filename.
+ * @param fFlags Flags for the operation, combination of RTFILEMOVE_FLAGS_XXX.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnRename, (PCRTLOGOUTPUTIF pIf, void *pvUser, const char *pszFilenameOld,
+ const char *pszFilenameNew, uint32_t fFlags));
+
+ /**
+ * Queries the size of the log file.
+ *
+ * @returns IPRT status code.
+ * @param pIf Pointer to this interface.
+ * @param pvUser Opaque user data passed when setting the callbacks.
+ * @param pcbFile Where to store the file size in bytes on success.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnQuerySize, (PCRTLOGOUTPUTIF pIf, void *pvUser, uint64_t *pcbSize));
+
+ /**
+ * Writes data to the log file.
+ *
+ * @returns IPRT status code.
+ * @param pIf Pointer to this interface.
+ * @param pvUser Opaque user data passed when setting the callbacks.
+ * @param pvBuf The data to write.
+ * @param cbWrite Number of bytes to write.
+ * @param pcbWritten Where to store the actual number of bytes written on success.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnWrite, (PCRTLOGOUTPUTIF pIf, void *pvUser, const void *pvBuf,
+ size_t cbWrite, size_t *pcbWritten));
+
+ /**
+ * Flushes data to the underlying storage medium.
+ *
+ * @returns IPRT status code.
+ * @param pIf Pointer to this interface.
+ * @param pvUser Opaque user data passed when setting the callbacks.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnFlush, (PCRTLOGOUTPUTIF pIf, void *pvUser));
+} RTLOGOUTPUTIF;
+/** Pointer to a logging output interface. */
+typedef struct RTLOGOUTPUTIF *PRTLOGOUTPUTIF;
+
+
+/**
+ * Auxiliary buffer descriptor.
+ *
+ * This is what we share we ring-3 and use for flushing ring-0 EMT loggers when
+ * we return to ring-3.
+ */
+typedef struct RTLOGBUFFERAUXDESC
+{
+ /** Flush indicator.
+ * Ring-3 sets this if it flushed the buffer, ring-0 clears it again after
+ * writing. */
+ bool volatile fFlushedIndicator;
+ bool afPadding[3];
+ /** Copy of RTLOGBUFFERDESC::offBuf. */
+ uint32_t offBuf;
+} RTLOGBUFFERAUXDESC;
+/** Pointer to auxiliary buffer descriptor. */
+typedef RTLOGBUFFERAUXDESC *PRTLOGBUFFERAUXDESC;
+
+/**
+ * Log buffer desciptor.
+ */
+typedef struct RTLOGBUFFERDESC
+{
+ /** Magic value / eye catcher (RTLOGBUFFERDESC_MAGIC). */
+ uint32_t u32Magic;
+ /** Padding. */
+ uint32_t uReserved;
+ /** The buffer size. */
+ uint32_t cbBuf;
+ /** The current buffer offset. */
+ uint32_t offBuf;
+ /** Pointer to the buffer. */
+ char *pchBuf;
+ /** Pointer to auxiliary desciptor, NULL if not used. */
+ PRTLOGBUFFERAUXDESC pAux;
+} RTLOGBUFFERDESC;
+
+/** RTLOGBUFFERDESC::u32Magic value. (Avram Noam Chomsky) */
+#define RTLOGBUFFERDESC_MAGIC UINT32_C(0x19281207)
+
+/**
+ * The public logger instance part.
+ *
+ * The logger instance is mostly abstract and kept as RTLOGGERINTERNAL within
+ * log.cpp. This public part is at the start of RTLOGGERINTERNAL.
+ */
+struct RTLOGGER
+{
+ /** Magic number (RTLOGGER_MAGIC). */
+ uint32_t u32Magic;
+ /** User value \#1, initialized to zero. */
+ uint32_t u32UserValue1;
+ /** User value \#2, initialized to zero. */
+ uint64_t u64UserValue2;
+ /** User value \#3, initialized to zero. */
+ uint64_t u64UserValue3;
+#if 0
+ /** Pointer to the logger function (used in non-C99 mode only).
+ *
+ * This is actually pointer to a wrapper/stub function 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;
+#else
+ /** Unused. */
+ uintptr_t uUsedToBeNonC99Logger;
+#endif
+#if ARCH_BITS == 32
+ /** Explicit padding. */
+ uint32_t uReserved1;
+#endif
+};
+
+/** RTLOGGER::u32Magic value. (John Rogers Searle) */
+#define RTLOGGER_MAGIC UINT32_C(0x19320731)
+
+/**
+ * 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;
+/** Don't use locking. */
+#define RTLOG_F_NO_LOCKING RT_BIT_64(63)
+/** Mask with all valid log flags (for validation). */
+#define RTLOG_F_VALID_MASK UINT64_C(0x800000007fff87f3)
+
+/**
+ * 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 types and flags.
+ */
+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,
+ /** The parent VMM debug log. */
+ RTLOGDEST_VMM = 0x00000040,
+ /** The parent VMM release log. */
+ RTLOGDEST_VMM_REL = 0x00000080,
+ /** Open files with no deny (share read, write, delete) on Windows. */
+ RTLOGDEST_F_NO_DENY = 0x00010000,
+ /** Delay opening the log file, logging to the buffer untill
+ * RTLogClearFileDelayFlag is called. */
+ RTLOGDEST_F_DELAY_FILE = 0x00020000,
+ /** Don't allow changes to the filename or mode of opening it. */
+ RTLOGDEST_FIXED_FILE = 0x01000000,
+ /** Don't allow changing the directory. */
+ RTLOGDEST_FIXED_DIR = 0x02000000,
+ /** 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;
+/** Valid log destinations. */
+#define RTLOG_DST_VALID_MASK UINT32_C(0x630300ff)
+/** Log destinations that can be changed via RTLogChangeDestinations. */
+#define RTLOG_DST_CHANGE_MASK UINT32_C(0x400000de)
+
+
+#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 enable 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
+# define LOG_USE_C99
+#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 \
+ { \
+ 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 \
+ { \
+ 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 \
+ { \
+ 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", RT_GCC_EXTENSION __PRETTY_FUNCTION__, _LogRemoveParentheseis a )
+#else
+# define LogWarnFunc(a) \
+ do { LogFlow((LOG_FN_FMT ": ", RT_GCC_EXTENSION __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, RT_GCC_EXTENSION __PRETTY_FUNCTION__, _LogRemoveParentheseis a )
+#else
+# define LogThisFunc(a) do { Log(("{%p} " LOG_FN_FMT ": ", this, RT_GCC_EXTENSION __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, RT_GCC_EXTENSION __PRETTY_FUNCTION__, _LogRemoveParentheseis a )
+#else
+# define Log2ThisFunc(a) do { Log2(("{%p} " LOG_FN_FMT ": ", this, RT_GCC_EXTENSION __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, RT_GCC_EXTENSION __PRETTY_FUNCTION__, _LogRemoveParentheseis a )
+#else
+# define Log3ThisFunc(a) do { Log3(("{%p} " LOG_FN_FMT ": ", this, RT_GCC_EXTENSION __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, RT_GCC_EXTENSION __PRETTY_FUNCTION__, _LogRemoveParentheseis a )
+#else
+# define Log4ThisFunc(a) do { Log4(("{%p} " LOG_FN_FMT ": ", this, RT_GCC_EXTENSION __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, RT_GCC_EXTENSION __PRETTY_FUNCTION__, _LogRemoveParentheseis a )
+#else
+# define Log5ThisFunc(a) do { Log5(("{%p} " LOG_FN_FMT ": ", this, RT_GCC_EXTENSION __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, RT_GCC_EXTENSION __PRETTY_FUNCTION__, _LogRemoveParentheseis a )
+#else
+# define Log6ThisFunc(a) do { Log6(("{%p} " LOG_FN_FMT ": ", this, RT_GCC_EXTENSION __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, RT_GCC_EXTENSION __PRETTY_FUNCTION__, _LogRemoveParentheseis a )
+#else
+# define Log7ThisFunc(a) do { Log7(("{%p} " LOG_FN_FMT ": ", this, RT_GCC_EXTENSION __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, RT_GCC_EXTENSION __PRETTY_FUNCTION__, _LogRemoveParentheseis a )
+#else
+# define Log8ThisFunc(a) do { Log8(("{%p} " LOG_FN_FMT ": ", this, RT_GCC_EXTENSION __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, RT_GCC_EXTENSION __PRETTY_FUNCTION__, _LogRemoveParentheseis a )
+#else
+# define Log9ThisFunc(a) do { Log9(("{%p} " LOG_FN_FMT ": ", this, RT_GCC_EXTENSION __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, RT_GCC_EXTENSION __PRETTY_FUNCTION__, _LogRemoveParentheseis a )
+#else
+# define Log10ThisFunc(a) do { Log10(("{%p} " LOG_FN_FMT ": ", this, RT_GCC_EXTENSION __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, RT_GCC_EXTENSION __PRETTY_FUNCTION__, _LogRemoveParentheseis a )
+#else
+# define Log11ThisFunc(a) do { Log11(("{%p} " LOG_FN_FMT ": ", this, RT_GCC_EXTENSION __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, RT_GCC_EXTENSION __PRETTY_FUNCTION__, _LogRemoveParentheseis a )
+#else
+# define Log12ThisFunc(a) do { Log12(("{%p} " LOG_FN_FMT ": ", this, RT_GCC_EXTENSION __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, RT_GCC_EXTENSION __PRETTY_FUNCTION__, _LogRemoveParentheseis a )
+#else
+# define LogFlowThisFunc(a) do { LogFlow(("{%p} " LOG_FN_FMT ": ", this, RT_GCC_EXTENSION __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, RT_GCC_EXTENSION __PRETTY_FUNCTION__, _LogRemoveParentheseis a )
+#else
+# define LogWarnThisFunc(a) do { LogWarn(("{%p} " LOG_FN_FMT ": ", this, RT_GCC_EXTENSION __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", RT_GCC_EXTENSION __PRETTY_FUNCTION__, _LogRemoveParentheseis a )
+#else
+# define Log1WarningFunc(a) \
+ do { Log((LOG_FN_FMT ": WARNING! ", RT_GCC_EXTENSION __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, RT_GCC_EXTENSION __PRETTY_FUNCTION__, _LogRemoveParentheseis a )
+#else
+# define Log1WarningThisFunc(a) \
+ do { Log(("{%p} " LOG_FN_FMT ": WARNING! ", this, RT_GCC_EXTENSION __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__, RT_GCC_EXTENSION __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
+/** @} */
+
+
+
+/** @defgroup grp_rt_log_rel 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) ( RTLogRelGetDefaultInstanceExWeak(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 = RTLogRelGetDefaultInstanceExWeak(RT_MAKE_U32(a_fFlags, a_iGroup)); \
+ if (RT_LIKELY(!LogRelIt_pLogger)) \
+ { /* likely */ } \
+ else \
+ RTLogLoggerExWeak(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 = RTLogRelGetDefaultInstanceExWeak(RT_MAKE_U32(a_fFlags, a_iGroup)); \
+ if (LogRelIt_pLogger) \
+ RTLogLoggerExWeak(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 = RTLogRelGetDefaultInstanceExWeak(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++; \
+ RTLogLoggerExWeak(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 = RTLogRelGetDefaultInstanceExWeak(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 = RTLogRelGetDefaultInstanceExWeak(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 = RTLogRelGetDefaultInstanceExWeak(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", RT_GCC_EXTENSION __PRETTY_FUNCTION__, _LogRemoveParentheseis a )
+#else
+# define LogRelFlowFunc(a) do { LogRelFlow((LOG_FN_FMT ": ", RT_GCC_EXTENSION __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", RT_GCC_EXTENSION __PRETTY_FUNCTION__, _LogRemoveParentheseis a )
+#else
+# define LogRelMaxFunc(a_cMax, a) \
+ do { LogRelMax(a_cMax, (LOG_FN_FMT ": ", RT_GCC_EXTENSION __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", RT_GCC_EXTENSION __PRETTY_FUNCTION__, _LogRemoveParentheseis a )
+#else
+# define LogRelMaxFlowFunc(a_cMax, a) \
+ do { LogRelMaxFlow(a_cMax, (LOG_FN_FMT ": ", RT_GCC_EXTENSION __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, RT_GCC_EXTENSION __PRETTY_FUNCTION__, _LogRemoveParentheseis a )
+#else
+# define LogRelThisFunc(a) \
+ do { LogRel(("{%p} " LOG_FN_FMT ": ", this, RT_GCC_EXTENSION __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, RT_GCC_EXTENSION __PRETTY_FUNCTION__, _LogRemoveParentheseis a )
+#else
+# define LogRelMaxThisFunc(a_cMax, a) \
+ do { LogRelMax(a_cMax, ("{%p} " LOG_FN_FMT ": ", this, RT_GCC_EXTENSION __PRETTY_FUNCTION__)); LogRelMax(a_cMax, a); } while (0)
+#endif
+
+/** @def LogRelFlowThisFunc
+ * The same as LogRelFlowFunc but for class functions (methods): the resulting
+ * log line is additionally prepended with a hex value of |this| pointer.
+ */
+#ifdef LOG_USE_C99
+# define LogRelFlowThisFunc(a) \
+ _LogRelIt(RTLOGGRPFLAGS_FLOW, LOG_GROUP, "{%p} " LOG_FN_FMT ": %M", this, RT_GCC_EXTENSION __PRETTY_FUNCTION__, _LogRemoveParentheseis a )
+#else
+# define LogRelFlowThisFunc(a) do { LogRelFlow(("{%p} " LOG_FN_FMT ": ", this, RT_GCC_EXTENSION __PRETTY_FUNCTION__)); LogRelFlow(a); } while (0)
+#endif
+
+
+/** Shortcut to |LogRelFlowFunc ("ENTER\n")|, marks the beginnig of the function. */
+#define LogRelFlowFuncEnter() LogRelFlowFunc(("ENTER\n"))
+
+/** Shortcut to |LogRelFlowFunc ("LEAVE\n")|, marks the end of the function. */
+#define LogRelFlowFuncLeave() LogRelFlowFunc(("LEAVE\n"))
+
+/** Shortcut to |LogRelFlowFunc ("LEAVE: %Rrc\n")|, marks the end of the function. */
+#define LogRelFlowFuncLeaveRC(rc) LogRelFlowFunc(("LEAVE: %Rrc\n", (rc)))
+
+/** Shortcut to |LogRelFlowThisFunc ("ENTER\n")|, marks the beginnig of the function. */
+#define LogRelFlowThisFuncEnter() LogRelFlowThisFunc(("ENTER\n"))
+
+/** Shortcut to |LogRelFlowThisFunc ("LEAVE\n")|, marks the end of the function. */
+#define LogRelFlowThisFuncLeave() LogRelFlowThisFunc(("LEAVE\n"))
+
+/** @} */
+
+
+/**
+ * Sets the default release logger instance.
+ *
+ * @returns The old default instance.
+ * @param pLogger The new default release logger instance.
+ */
+RTDECL(PRTLOGGER) RTLogRelSetDefaultInstance(PRTLOGGER pLogger);
+
+/**
+ * Gets the default release logger instance.
+ *
+ * @returns Pointer to default release logger instance if availble, otherwise NULL.
+ */
+RTDECL(PRTLOGGER) RTLogRelGetDefaultInstance(void);
+
+/** @copydoc RTLogRelGetDefaultInstance */
+typedef DECLCALLBACKTYPE(PRTLOGGER, FNLOGRELGETDEFAULTINSTANCE,(void));
+/** Pointer to RTLogRelGetDefaultInstance. */
+typedef FNLOGRELGETDEFAULTINSTANCE *PFNLOGRELGETDEFAULTINSTANCE;
+
+/** "Weak symbol" emulation for RTLogRelGetDefaultInstance.
+ * @note This is first set when RTLogRelSetDefaultInstance is called. */
+extern RTDATADECL(PFNLOGRELGETDEFAULTINSTANCE) g_pfnRTLogRelGetDefaultInstance;
+
+/** "Weak symbol" wrapper for RTLogRelGetDefaultInstance. */
+DECL_FORCE_INLINE(PRTLOGGER) RTLogRelGetDefaultInstanceWeak(void)
+{
+#if defined(IN_RING3) && (defined(IN_RT_STATIC) || defined(IPRT_NO_CRT))
+ if (g_pfnRTLogRelGetDefaultInstance)
+ return g_pfnRTLogRelGetDefaultInstance();
+ return NULL;
+#else
+ return RTLogRelGetDefaultInstance();
+#endif
+}
+
+/**
+ * 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);
+
+/** @copydoc RTLogRelGetDefaultInstanceEx */
+typedef DECLCALLBACKTYPE(PRTLOGGER, FNLOGRELGETDEFAULTINSTANCEEX,(uint32_t fFlagsAndGroup));
+/** Pointer to RTLogRelGetDefaultInstanceEx. */
+typedef FNLOGRELGETDEFAULTINSTANCEEX *PFNLOGRELGETDEFAULTINSTANCEEX;
+
+/** "Weak symbol" emulation for RTLogRelGetDefaultInstanceEx.
+ * @note This is first set when RTLogRelSetDefaultInstance is called. */
+extern RTDATADECL(PFNLOGRELGETDEFAULTINSTANCEEX) g_pfnRTLogRelGetDefaultInstanceEx;
+
+/** "Weak symbol" wrapper for RTLogRelGetDefaultInstanceEx. */
+DECL_FORCE_INLINE(PRTLOGGER) RTLogRelGetDefaultInstanceExWeak(uint32_t fFlagsAndGroup)
+{
+#if defined(IN_RING3) && (defined(IN_RT_STATIC) || defined(IPRT_NO_CRT))
+ if (g_pfnRTLogRelGetDefaultInstanceEx)
+ return g_pfnRTLogRelGetDefaultInstanceEx(fFlagsAndGroup);
+ return NULL;
+#else
+ return RTLogRelGetDefaultInstanceEx(fFlagsAndGroup);
+#endif
+}
+
+
+/**
+ * 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 (does not create one).
+ *
+ * @returns Pointer to default logger instance if availble, otherwise NULL.
+ */
+RTDECL(PRTLOGGER) RTLogGetDefaultInstance(void);
+
+/** @copydoc RTLogGetDefaultInstance */
+typedef DECLCALLBACKTYPE(PRTLOGGER, FNLOGGETDEFAULTINSTANCE,(void));
+/** Pointer to RTLogGetDefaultInstance. */
+typedef FNLOGGETDEFAULTINSTANCE *PFNLOGGETDEFAULTINSTANCE;
+
+/** "Weak symbol" emulation for RTLogGetDefaultInstance.
+ * @note This is first set when RTLogSetDefaultInstance is called. */
+extern RTDATADECL(PFNLOGGETDEFAULTINSTANCE) g_pfnRTLogGetDefaultInstance;
+
+/** "Weak symbol" wrapper for RTLogGetDefaultInstance. */
+DECL_FORCE_INLINE(PRTLOGGER) RTLogGetDefaultInstanceWeak(void)
+{
+#if defined(IN_RING3) && (defined(IN_RT_STATIC) || defined(IPRT_NO_CRT))
+ if (g_pfnRTLogGetDefaultInstance)
+ return g_pfnRTLogGetDefaultInstance();
+ return NULL;
+#else
+ return RTLogGetDefaultInstance();
+#endif
+}
+
+/**
+ * Gets the default logger instance if enabled (does not create one).
+ *
+ * @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);
+
+/** @copydoc RTLogGetDefaultInstanceEx */
+typedef DECLCALLBACKTYPE(PRTLOGGER, FNLOGGETDEFAULTINSTANCEEX,(uint32_t fFlagsAndGroup));
+/** Pointer to RTLogGetDefaultInstanceEx. */
+typedef FNLOGGETDEFAULTINSTANCEEX *PFNLOGGETDEFAULTINSTANCEEX;
+
+/** "Weak symbol" emulation for RTLogGetDefaultInstanceEx.
+ * @note This is first set when RTLogSetDefaultInstance is called. */
+extern RTDATADECL(PFNLOGGETDEFAULTINSTANCEEX) g_pfnRTLogGetDefaultInstanceEx;
+
+/** "Weak symbol" wrapper for RTLogGetDefaultInstanceEx. */
+DECL_FORCE_INLINE(PRTLOGGER) RTLogGetDefaultInstanceExWeak(uint32_t fFlagsAndGroup)
+{
+#if defined(IN_RING3) && (defined(IN_RT_STATIC) || defined(IPRT_NO_CRT))
+ if (g_pfnRTLogGetDefaultInstanceEx)
+ return g_pfnRTLogGetDefaultInstanceEx(fFlagsAndGroup);
+ return NULL;
+#else
+ return RTLogGetDefaultInstanceEx(fFlagsAndGroup);
+#endif
+}
+
+/**
+ * Sets the default logger instance.
+ *
+ * @returns The old default instance.
+ * @param pLogger The new default logger instance.
+ */
+RTDECL(PRTLOGGER) RTLogSetDefaultInstance(PRTLOGGER pLogger);
+
+#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.
+ */
+RTR0DECL(int) RTLogSetDefaultInstanceThread(PRTLOGGER pLogger, uintptr_t uKey);
+#endif /* IN_RING0 */
+
+/**
+ * Creates the default logger instance for 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);
+
+/**
+ * This is the 2nd half of what RTLogGetDefaultInstanceEx() and
+ * RTLogRelGetDefaultInstanceEx() does.
+ *
+ * @returns If the group has the specified flags enabled @a pLogger will be
+ * returned returned. Otherwise NULL is returned.
+ * @param pLogger The logger. NULL is NULL.
+ * @param fFlagsAndGroup The flags in the lower 16 bits, the group number in
+ * the high 16 bits.
+ */
+RTDECL(PRTLOGGER) RTLogCheckGroupFlags(PRTLOGGER pLogger, uint32_t fFlagsAndGroup);
+
+/**
+ * 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, uint64_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 pszEnvVarBase Base name for the environment variables for
+ * this instance (ring-3 only).
+ * @param fFlags Logger instance flags, a combination of the
+ * RTLOGFLAGS_* values.
+ * @param pszGroupSettings The initial group settings.
+ * @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 cMaxEntriesPerGroup The max number of entries per group. UINT32_MAX
+ * or zero for unlimited.
+ * @param cBufDescs Number of buffer descriptors that @a paBufDescs
+ * points to. Zero for defaults.
+ * @param paBufDescs Buffer descriptors, optional.
+ * @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 pOutputIf The optional file output interface, can be NULL which will
+ * make use of the default one.
+ * @param pvOutputIfUser The opaque user data to pass to the callbacks in the output interface.
+ * @param pErrInfo Where to return extended error information.
+ * Optional.
+ * @param pszFilenameFmt Log filename format string. Standard RTStrFormat().
+ * @param ... Format arguments.
+ */
+RTDECL(int) RTLogCreateEx(PRTLOGGER *ppLogger, const char *pszEnvVarBase, uint64_t fFlags, const char *pszGroupSettings,
+ unsigned cGroups, const char * const *papszGroups, uint32_t cMaxEntriesPerGroup,
+ uint32_t cBufDescs, PRTLOGBUFFERDESC paBufDescs, uint32_t fDestFlags,
+ PFNRTLOGPHASE pfnPhase, uint32_t cHistory, uint64_t cbHistoryFileMax, uint32_t cSecsHistoryTimeSlot,
+ PCRTLOGOUTPUTIF pOutputIf, void *pvOutputIfUser,
+ PRTERRINFO pErrInfo, const char *pszFilenameFmt, ...) RT_IPRT_FORMAT_ATTR_MAYBE_NULL(18, 19);
+
+/**
+ * Create a logger instance.
+ *
+ * @returns iprt status code.
+ *
+ * @param ppLogger Where to store the logger instance.
+ * @param pszEnvVarBase Base name for the environment variables for
+ * this instance (ring-3 only).
+ * @param fFlags Logger instance flags, a combination of the
+ * RTLOGFLAGS_* values.
+ * @param pszGroupSettings The initial group settings.
+ * @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 cMaxEntriesPerGroup The max number of entries per group. UINT32_MAX
+ * or zero for unlimited.
+ * @param cBufDescs Number of buffer descriptors that @a paBufDescs
+ * points to. Zero for defaults.
+ * @param paBufDescs Buffer descriptors, optional.
+ * @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 pOutputIf The optional file output interface, can be NULL which will
+ * make use of the default one.
+ * @param pvOutputIfUser The opaque user data to pass to the callbacks in the output interface.
+ * @param pErrInfo Where to return extended error information.
+ * Optional.
+ * @param pszFilenameFmt Log filename format string. Standard
+ * RTStrFormat().
+ * @param va Format arguments.
+ */
+RTDECL(int) RTLogCreateExV(PRTLOGGER *ppLogger, const char *pszEnvVarBase, uint64_t fFlags, const char *pszGroupSettings,
+ uint32_t cGroups, const char * const *papszGroups, uint32_t cMaxEntriesPerGroup,
+ uint32_t cBufDescs, PRTLOGBUFFERDESC paBufDescs, uint32_t fDestFlags,
+ PFNRTLOGPHASE pfnPhase, uint32_t cHistory, uint64_t cbHistoryFileMax, uint32_t cSecsHistoryTimeSlot,
+ PCRTLOGOUTPUTIF pOutputIf, void *pvOutputIfUser,
+ PRTERRINFO pErrInfo, const char *pszFilenameFmt, va_list va) RT_IPRT_FORMAT_ATTR_MAYBE_NULL(18, 0);
+
+/**
+ * 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);
+
+/**
+ * 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);
+
+/**
+ * Sets the custom flush callback.
+ *
+ * This can be handy for special loggers like the per-EMT ones in ring-0,
+ * but also for implementing a log viewer in the debugger GUI.
+ *
+ * @returns IPRT status code.
+ * @retval VWRN_ALREADY_EXISTS if it was set to a different flusher.
+ * @param pLogger The logger instance.
+ * @param pfnFlush The flush callback.
+ */
+RTDECL(int) RTLogSetFlushCallback(PRTLOGGER pLogger, PFNRTLOGFLUSH pfnFlush);
+
+/**
+ * Sets the thread name for a thread specific ring-0 logger.
+ *
+ * @returns IPRT status code.
+ * @param pLogger The logger. NULL is not allowed.
+ * @param pszNameFmt The format string for the thread name.
+ * @param ... Format arguments.
+ */
+RTR0DECL(int) RTLogSetR0ThreadNameF(PRTLOGGER pLogger, const char *pszNameFmt, ...) RT_IPRT_FORMAT_ATTR(2, 3);
+
+/**
+ * Sets the thread name for a thread specific ring-0 logger.
+ *
+ * @returns IPRT status code.
+ * @param pLogger The logger. NULL is not allowed.
+ * @param pszNameFmt The format string for the thread name.
+ * @param va Format arguments.
+ */
+RTR0DECL(int) RTLogSetR0ThreadNameV(PRTLOGGER pLogger, const char *pszNameFmt, va_list va) RT_IPRT_FORMAT_ATTR(2, 0);
+
+/**
+ * Sets the program start time for a thread specific ring-0 logger.
+ *
+ * @returns IPRT status code.
+ * @param pLogger The logger. NULL is not allowed.
+ * @param nsStart The RTTimeNanoTS() value at program start.
+ */
+RTR0DECL(int) RTLogSetR0ProgramStart(PRTLOGGER pLogger, uint64_t nsStart);
+
+/**
+ * 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) RTLogQueryGroupSettings(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);
+
+/**
+ * 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);
+
+/**
+ * Gets the current flag settings for the given logger.
+ *
+ * @returns Logger flags, UINT64_MAX if no logger.
+ * @param pLogger Logger instance (NULL for default logger).
+ */
+RTDECL(uint64_t) RTLogGetFlags(PRTLOGGER pLogger);
+
+/**
+ * Modifies the flag settings for the given logger.
+ *
+ * @returns IPRT status code. Returns VINF_LOG_NO_LOGGER if no default logger
+ * and @a pLogger is NULL.
+ * @param pLogger Logger instance (NULL for default logger).
+ * @param fSet Mask of flags to set (OR).
+ * @param fClear Mask of flags to clear (NAND). This is allowed to
+ * include invalid flags - e.g. UINT64_MAX is okay.
+ */
+RTDECL(int) RTLogChangeFlags(PRTLOGGER pLogger, uint64_t fSet, uint64_t fClear);
+
+/**
+ * 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);
+
+/**
+ * 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) RTLogQueryFlags(PRTLOGGER pLogger, char *pszBuf, size_t cchBuf);
+
+/**
+ * Gets the current destinations flags for the given logger.
+ *
+ * @returns Logger destination flags, UINT32_MAX if no logger.
+ * @param pLogger Logger instance (NULL for default logger).
+ */
+RTDECL(uint32_t) RTLogGetDestinations(PRTLOGGER pLogger);
+
+/**
+ * Modifies the log destinations settings for the given logger.
+ *
+ * This is only suitable for simple destination settings that doesn't take
+ * additional arguments, like RTLOGDEST_FILE.
+ *
+ * @returns IPRT status code. Returns VINF_LOG_NO_LOGGER if no default logger
+ * and @a pLogger is NULL.
+ * @param pLogger Logger instance (NULL for default logger).
+ * @param fSet Mask of destinations to set (OR).
+ * @param fClear Mask of destinations to clear (NAND).
+ */
+RTDECL(int) RTLogChangeDestinations(PRTLOGGER pLogger, uint32_t fSet, uint32_t fClear);
+
+/**
+ * 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);
+
+/**
+ * Clear the file delay flag if set, opening the destination and flushing.
+ *
+ * @returns IPRT status code.
+ * @param pLogger Logger instance (NULL for default logger).
+ * @param pErrInfo Where to return extended error info. Optional.
+ */
+RTDECL(int) RTLogClearFileDelayFlag(PRTLOGGER pLogger, PRTERRINFO pErrInfo);
+
+/**
+ * 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) RTLogQueryDestinations(PRTLOGGER pLogger, char *pszBuf, size_t cchBuf);
+
+/**
+ * Performs a bulk update of logger flags and group flags.
+ *
+ * This is for instanced used for copying settings from ring-3 to ring-0
+ * loggers.
+ *
+ * @returns IPRT status code.
+ * @param pLogger The logger instance (NULL for default logger).
+ * @param fFlags The new logger flags.
+ * @param uGroupCrc32 The CRC32 of the group name strings.
+ * @param cGroups Number of groups.
+ * @param pafGroups Array of group flags.
+ * @sa RTLogQueryBulk
+ */
+RTDECL(int) RTLogBulkUpdate(PRTLOGGER pLogger, uint64_t fFlags, uint32_t uGroupCrc32, uint32_t cGroups, uint32_t const *pafGroups);
+
+/**
+ * Queries data for a bulk update of logger flags and group flags.
+ *
+ * This is for instanced used for copying settings from ring-3 to ring-0
+ * loggers.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_BUFFER_OVERFLOW if pafGroups is too small, @a pcGroups will be
+ * set to the actual number of groups.
+ * @param pLogger The logger instance (NULL for default logger).
+ * @param pfFlags Where to return the logger flags.
+ * @param puGroupCrc32 Where to return the CRC32 of the group names.
+ * @param pcGroups Input: Size of the @a pafGroups allocation.
+ * Output: Actual number of groups returned.
+ * @param pafGroups Where to return the flags for each group.
+ * @sa RTLogBulkUpdate
+ */
+RTDECL(int) RTLogQueryBulk(PRTLOGGER pLogger, uint64_t *pfFlags, uint32_t *puGroupCrc32, uint32_t *pcGroups, uint32_t *pafGroups);
+
+/**
+ * Write/copy bulk log data from another logger.
+ *
+ * This is used for transferring stuff from the ring-0 loggers and into the
+ * ring-3 one. The text goes in as-is w/o any processing (i.e. prefixing or
+ * newline fun).
+ *
+ * @returns IRPT status code.
+ * @param pLogger The logger instance (NULL for default logger).
+ * @param pszBefore Text to log before the bulk text. Optional.
+ * @param pch Pointer to the block of bulk log text to write.
+ * @param cch Size of the block of bulk log text to write.
+ * @param pszAfter Text to log after the bulk text. Optional.
+ */
+RTDECL(int) RTLogBulkWrite(PRTLOGGER pLogger, const char *pszBefore, const char *pch, size_t cch, const char *pszAfter);
+
+/**
+ * Write/copy bulk log data from a nested VM logger.
+ *
+ * This is used for
+ *
+ * @returns IRPT status code.
+ * @param pLogger The logger instance (NULL for default logger).
+ * @param pch Pointer to the block of bulk log text to write.
+ * @param cch Size of the block of bulk log text to write.
+ * @param pszInfix String to put after the line prefixes and the
+ * line content.
+ */
+RTDECL(int) RTLogBulkNestedWrite(PRTLOGGER pLogger, const char *pch, size_t cch, const char *pszInfix);
+
+/**
+ * Flushes the specified logger.
+ *
+ * @returns IRPT status code.
+ * @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(int) 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, weak version.
+ *
+ * @param pLogger Pointer to logger instance.
+ * @param pvCallerRet Ignored.
+ * @param pszFormat Format string.
+ * @param ... Format arguments.
+ */
+#if defined(IN_RING3) && (defined(IN_RT_STATIC) || defined(IPRT_NO_CRT))
+RTDECL(void) RTLogLoggerWeak(PRTLOGGER pLogger, void *pvCallerRet, const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(3, 4);
+#else /* Cannot use a DECL_FORCE_INLINE because older GCC versions doesn't support inlining va_start. */
+# undef RTLogLoggerWeak /* in case of mangling */
+# define RTLogLoggerWeak RTLogLogger
+#endif
+
+/**
+ * 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(2, 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, weak version.
+ *
+ * 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.
+ */
+#if defined(IN_RING3) && (defined(IN_RT_STATIC) || defined(IPRT_NO_CRT))
+RTDECL(void) RTLogLoggerExWeak(PRTLOGGER pLogger, unsigned fFlags, unsigned iGroup,
+ const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(4, 5);
+#else /* Cannot use a DECL_FORCE_INLINE because older GCC versions doesn't support inlining va_start. */
+# undef RTLogLoggerExWeak /* in case of mangling */
+# define RTLogLoggerExWeak RTLogLoggerEx
+#endif
+
+/**
+ * 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.
+ *
+ * @returns VINF_SUCCESS, VINF_LOG_NO_LOGGER, VINF_LOG_DISABLED, or IPRT error
+ * status.
+ * @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(int) RTLogLoggerExV(PRTLOGGER pLogger, unsigned fFlags, unsigned iGroup,
+ const char *pszFormat, va_list args) RT_IPRT_FORMAT_ATTR(4, 0);
+
+/** @copydoc RTLogLoggerExV */
+typedef DECLCALLBACKTYPE(int, FNRTLOGLOGGEREXV,(PRTLOGGER pLogger, unsigned fFlags, unsigned iGroup,
+ const char *pszFormat, va_list args)) RT_IPRT_FORMAT_ATTR(4, 0);
+/** Pointer to RTLogLoggerExV. */
+typedef FNRTLOGLOGGEREXV *PFNRTLOGLOGGEREXV;
+/** "Weak symbol" emulation for RTLogLoggerExV.
+ * @note This is first set when RTLogCreateEx or RTLogCreate is called. */
+extern RTDATADECL(PFNRTLOGLOGGEREXV) g_pfnRTLogLoggerExV;
+
+/** "Weak symbol" wrapper for RTLogLoggerExV. */
+DECL_FORCE_INLINE(int) RTLogLoggerExVWeak(PRTLOGGER pLogger, unsigned fFlags, unsigned iGroup,
+ const char *pszFormat, va_list args) /* RT_IPRT_FORMAT_ATTR(4, 0) */
+{
+#if defined(IN_RING3) && (defined(IN_RT_STATIC) || defined(IPRT_NO_CRT))
+ if (g_pfnRTLogLoggerExV)
+ return g_pfnRTLogLoggerExV(pLogger, fFlags, iGroup, pszFormat, args);
+ return 22301; /* VINF_LOG_DISABLED, don't want err.h dependency here. */
+#else
+ return RTLogLoggerExV(pLogger, fFlags, iGroup, pszFormat, args);
+#endif
+}
+
+/**
+ * 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);
+
+/**
+ * Used for logging assertions, debug and release log as appropriate.
+ *
+ * Implies flushing.
+ *
+ * @param pszFormat Format string.
+ * @param ... Format arguments.
+ */
+typedef DECLCALLBACKTYPE(void, FNRTLOGASSERTION,(const char *pszFormat, ...)) RT_IPRT_FORMAT_ATTR(1, 2);
+/** Pointer to an assertion logger, ellipsis variant. */
+typedef FNRTLOGASSERTION *PFNRTLOGASSERTION;
+
+/**
+ * Used for logging assertions, debug and release log as appropriate.
+ *
+ * Implies flushing.
+ *
+ * @param pszFormat Format string.
+ * @param va Format arguments.
+ */
+typedef DECLCALLBACKTYPE(void, FNRTLOGASSERTIONV,(const char *pszFormat, va_list va)) RT_IPRT_FORMAT_ATTR(1, 0);
+/** Pointer to an assertion logger, va_list variant. */
+typedef FNRTLOGASSERTIONV *PFNRTLOGASSERTIONV;
+
+/** @copydoc FNRTLOGASSERTION */
+RTDECL(void) RTLogAssert(const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(1, 2);
+/** @copydoc FNRTLOGASSERTIONV */
+RTDECL(void) RTLogAssertV(const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(1, 0);
+
+/** "Weak symbol" emulation for RTLogAssert. */
+extern RTDATADECL(PFNRTLOGASSERTION) g_pfnRTLogAssert;
+/** "Weak symbol" emulation for RTLogAssertV. */
+extern RTDATADECL(PFNRTLOGASSERTIONV) g_pfnRTLogAssertV;
+
+
+#ifndef DECLARED_FNRTSTROUTPUT /* duplicated in iprt/string.h & iprt/errcore.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 DECLCALLBACKTYPE(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);
+
+/**
+ * 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 a parent VMM (hypervisor).
+ *
+ * @param pach What to write.
+ * @param cb How much to write.
+ * @param fRelease Set if targeting the release log, clear if debug log.
+ *
+ * @note Currently only available on AMD64 and x86.
+ */
+RTDECL(void) RTLogWriteVmm(const char *pach, size_t cb, bool fRelease);
+
+/**
+ * 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 /* !IPRT_INCLUDED_log_h */
+
diff --git a/include/iprt/mangling.h b/include/iprt/mangling.h
new file mode 100644
index 00000000..eef92f51
--- /dev/null
+++ b/include/iprt/mangling.h
@@ -0,0 +1,4320 @@
+/** @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-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_mangling_h
+#define IPRT_INCLUDED_mangling_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#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 ASMAtomicUoXorU32 RT_MANGLER(ASMAtomicUoXorU32)
+# 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 ASMMultU64ByU32DivByU32 RT_MANGLER(ASMMultU64ByU32DivByU32)
+# define ASMMultU64ByU32DivByU32_EndProc RT_MANGLER(ASMMultU64ByU32DivByU32_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 RTAvlU64Destroy RT_MANGLER(RTAvlU64Destroy)
+# define RTAvlU64DoWithAll RT_MANGLER(RTAvlU64DoWithAll)
+# define RTAvlU64Get RT_MANGLER(RTAvlU64Get)
+# define RTAvlU64GetBestFit RT_MANGLER(RTAvlU64GetBestFit)
+# define RTAvlU64Insert RT_MANGLER(RTAvlU64Insert)
+# define RTAvlU64Remove RT_MANGLER(RTAvlU64Remove)
+# define RTAvlU64RemoveBestFit RT_MANGLER(RTAvlU64RemoveBestFit)
+# 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 RTBase64DecodeUtf16 RT_MANGLER(RTBase64DecodeUtf16)
+# define RTBase64DecodeUtf16Ex RT_MANGLER(RTBase64DecodeUtf16Ex)
+# define RTBase64DecodedUtf16Size RT_MANGLER(RTBase64DecodedUtf16Size)
+# define RTBase64DecodedUtf16SizeEx RT_MANGLER(RTBase64DecodedUtf16SizeEx)
+# define RTBase64Encode RT_MANGLER(RTBase64Encode)
+# define RTBase64EncodeEx RT_MANGLER(RTBase64EncodeEx)
+# define RTBase64EncodedLength RT_MANGLER(RTBase64EncodedLength)
+# define RTBase64EncodedLengthEx RT_MANGLER(RTBase64EncodedLengthEx)
+# define RTBase64EncodeUtf16 RT_MANGLER(RTBase64EncodeUtf16)
+# define RTBase64EncodeUtf16Ex RT_MANGLER(RTBase64EncodeUtf16Ex)
+# define RTBase64EncodedUtf16Length RT_MANGLER(RTBase64EncodedUtf16Length)
+# define RTBase64EncodedUtf16LengthEx RT_MANGLER(RTBase64EncodedUtf16LengthEx)
+# 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 RTCrc16Ccitt RT_MANGLER(RTCrc16Ccitt)
+# define RTCrc16CcittProcess RT_MANGLER(RTCrc16CcittProcess)
+# define RTCrc16CcittFinish RT_MANGLER(RTCrc16CcittFinish)
+# define RTCrc16CcittStart RT_MANGLER(RTCrc16CcittStart)
+# 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 RTDbgCfgOpenEx RT_MANGLER(RTDbgCfgOpenEx)
+# define RTDbgCfgOpenDbg RT_MANGLER(RTDbgCfgOpenDbg)
+# define RTDbgCfgOpenDsymBundle RT_MANGLER(RTDbgCfgOpenDsymBundle)
+# define RTDbgCfgOpenMachOImage RT_MANGLER(RTDbgCfgOpenMachOImage)
+# define RTDbgCfgOpenDwo RT_MANGLER(RTDbgCfgOpenDwo)
+# define RTDbgCfgOpenDwoBuildId RT_MANGLER(RTDbgCfgOpenDwoBuildId)
+# 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 RTDbgModImageGetArch RT_MANGLER(RTDbgModImageGetArch)
+# define RTDbgModImageGetFormat RT_MANGLER(RTDbgModImageGetFormat)
+# define RTDbgModImageSize RT_MANGLER(RTDbgModImageSize)
+# define RTDbgModImageQueryProp RT_MANGLER(RTDbgModImageQueryProp)
+# 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 RTDbgModUnwindFrame RT_MANGLER(RTDbgModUnwindFrame)
+# define RTDbgStackDumpSelf RT_MANGLER(RTDbgStackDumpSelf)
+# define RTDbgStackDumpSelf_EndProc RT_MANGLER(RTDbgStackDumpSelf_EndProc)
+# 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 RTDirCreateFullPathEx RT_MANGLER(RTDirCreateFullPathEx)
+# 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 RTDirIsValid RT_MANGLER(RTDirIsValid)
+# 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 RTDirReadExA RT_MANGLER(RTDirReadExA)
+# define RTDirReadExAFree RT_MANGLER(RTDirReadExAFree)
+# define RTDirRemove RT_MANGLER(RTDirRemove)
+# define RTDirRemoveRecursive RT_MANGLER(RTDirRemoveRecursive)
+# define RTDirRename RT_MANGLER(RTDirRename)
+# define RTDirRewind RT_MANGLER(RTDirRewind)
+# define RTDirSetMode RT_MANGLER(RTDirSetMode)
+# define RTDirSetTimes RT_MANGLER(RTDirSetTimes)
+# define RTDirRelFileOpen RT_MANGLER(RTDirRelFileOpen)
+# define RTDirRelDirOpen RT_MANGLER(RTDirRelDirOpen)
+# define RTDirRelDirOpenFiltered RT_MANGLER(RTDirRelDirOpenFiltered)
+# define RTDirRelDirCreate RT_MANGLER(RTDirRelDirCreate)
+# define RTDirRelDirRemove RT_MANGLER(RTDirRelDirRemove)
+# define RTDirRelPathQueryInfo RT_MANGLER(RTDirRelPathQueryInfo)
+# define RTDirRelPathSetMode RT_MANGLER(RTDirRelPathSetMode)
+# define RTDirRelPathSetTimes RT_MANGLER(RTDirRelPathSetTimes)
+# define RTDirRelPathSetOwner RT_MANGLER(RTDirRelPathSetOwner)
+# define RTDirRelPathRename RT_MANGLER(RTDirRelPathRename)
+# define RTDirRelPathUnlink RT_MANGLER(RTDirRelPathUnlink)
+# define RTDirRelSymlinkCreate RT_MANGLER(RTDirRelSymlinkCreate)
+# define RTDirRelSymlinkRead RT_MANGLER(RTDirRelSymlinkRead)
+# define RTVfsDirOpenDir RT_MANGLER(RTVfsDirOpenDir)
+# define RTVfsDirFromRTDir RT_MANGLER(RTVfsDirFromRTDir)
+# define RTVfsDirOpenNormal RT_MANGLER(RTVfsDirOpenNormal)
+# define RTVfsDirIsStdDir RT_MANGLER(RTVfsDirIsStdDir)
+# define RTDvmCreate RT_MANGLER(RTDvmCreate)
+# define RTDvmCreateFromVfsFile RT_MANGLER(RTDvmCreateFromVfsFile)
+# define RTDvmRetain RT_MANGLER(RTDvmRetain)
+# define RTDvmRelease RT_MANGLER(RTDvmRelease)
+# define RTDvmMapOpen RT_MANGLER(RTDvmMapOpen)
+# define RTDvmMapInitialize RT_MANGLER(RTDvmMapInitialize)
+# define RTDvmMapGetFormatName RT_MANGLER(RTDvmMapGetFormatName)
+# define RTDvmMapGetFormatType RT_MANGLER(RTDvmMapGetFormatType)
+# 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 RTDvmMapQueryDiskUuid RT_MANGLER(RTDvmMapQueryDiskUuid)
+# define RTDvmMapQueryTableLocations RT_MANGLER(RTDvmMapQueryTableLocations)
+# define RTDvmVolumeRetain RT_MANGLER(RTDvmVolumeRetain)
+# define RTDvmVolumeRelease RT_MANGLER(RTDvmVolumeRelease)
+# define RTDvmVolumeGetIndex RT_MANGLER(RTDvmVolumeGetIndex)
+# define RTDvmVolumeGetPropU64 RT_MANGLER(RTDvmVolumeGetPropU64)
+# define RTDvmVolumeGetSize RT_MANGLER(RTDvmVolumeGetSize)
+# define RTDvmVolumeQueryName RT_MANGLER(RTDvmVolumeQueryName)
+# define RTDvmVolumeQueryProp RT_MANGLER(RTDvmVolumeQueryProp)
+# define RTDvmVolumeQueryTableLocation RT_MANGLER(RTDvmVolumeQueryTableLocation)
+# define RTDvmVolumeGetType RT_MANGLER(RTDvmVolumeGetType)
+# define RTDvmVolumeGetFlags RT_MANGLER(RTDvmVolumeGetFlags)
+# define RTDvmVolumeQueryRange RT_MANGLER(RTDvmVolumeQueryRange)
+# 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 RTEfiGuidCompare RT_MANGLER(RTEfiGuidCompare)
+# define RTEfiGuidFromUuid RT_MANGLER(RTEfiGuidFromUuid)
+# define RTEfiGuidToUuid RT_MANGLER(RTEfiGuidToUuid)
+# define RTEfiSigDbAddFromExistingDb RT_MANGLER(RTEfiSigDbAddFromExistingDb)
+# define RTEfiSigDbAddSignatureFromFile RT_MANGLER(RTEfiSigDbAddSignatureFromFile)
+# define RTEfiSigDbAddSignatureFromBuf RT_MANGLER(RTEfiSigDbAddSignatureFromBuf)
+# define RTEfiSigDbCreate RT_MANGLER(RTEfiSigDbCreate)
+# define RTEfiSigDbDestroy RT_MANGLER(RTEfiSigDbDestroy)
+# define RTEfiSigDbEnum RT_MANGLER(RTEfiSigDbEnum)
+# define RTEfiSigDbTypeGetGuid RT_MANGLER(RTEfiSigDbTypeGetGuid)
+# define RTEfiSigDbTypeStringify RT_MANGLER(RTEfiSigDbTypeStringify)
+# define RTEfiSigDbWriteToFile RT_MANGLER(RTEfiSigDbWriteToFile)
+# define RTEfiTimeFromTimeSpec RT_MANGLER(RTEfiTimeFromTimeSpec)
+# define RTEfiTimeToTimeSpec RT_MANGLER(RTEfiTimeToTimeSpec)
+# define RTEfiVarStoreCreate RT_MANGLER(RTEfiVarStoreCreate)
+# define RTEfiVarStoreOpenAsVfs RT_MANGLER(RTEfiVarStoreOpenAsVfs)
+# 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 RTEnvCreateEx RT_MANGLER(RTEnvCreateEx)
+# define RTEnvCreateChangeRecord RT_MANGLER(RTEnvCreateChangeRecord)
+# define RTEnvCreateChangeRecordEx RT_MANGLER(RTEnvCreateChangeRecordEx)
+# define RTEnvDestroy RT_MANGLER(RTEnvDestroy)
+# define RTEnvDup RT_MANGLER(RTEnvDup)
+# 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 RTErrIsKnown RT_MANGLER(RTErrIsKnown)
+# define RTErrQueryDefine RT_MANGLER(RTErrQueryDefine)
+# define RTErrQueryMsgShort RT_MANGLER(RTErrQueryMsgShort)
+# define RTErrQueryMsgFull RT_MANGLER(RTErrQueryMsgFull)
+# define RTErrFormatDefine RT_MANGLER(RTErrFormatDefine)
+# define RTErrFormatMsgShort RT_MANGLER(RTErrFormatMsgShort)
+# define RTErrFormatMsgFull RT_MANGLER(RTErrFormatMsgFull)
+# define RTErrFormatMsgAll RT_MANGLER(RTErrFormatMsgAll)
+# 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 RTErrInfoLogAndSet RT_MANGLER(RTErrInfoLogAndSet)
+# define RTErrInfoLogAndSetF RT_MANGLER(RTErrInfoLogAndSetF)
+# define RTErrInfoLogAndSetV RT_MANGLER(RTErrInfoLogAndSetV)
+# define RTErrInfoLogAndAdd RT_MANGLER(RTErrInfoLogAndAdd)
+# define RTErrInfoLogAndAddF RT_MANGLER(RTErrInfoLogAndAddF)
+# define RTErrInfoLogAndAddV RT_MANGLER(RTErrInfoLogAndAddV)
+# 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 RTFileCopyAttributes RT_MANGLER(RTFileCopyAttributes)
+# define RTFileCopyByHandles RT_MANGLER(RTFileCopyByHandles)
+# define RTFileCopyByHandlesEx RT_MANGLER(RTFileCopyByHandlesEx)
+# define RTFileCopyEx RT_MANGLER(RTFileCopyEx)
+# define RTFileCopyPart RT_MANGLER(RTFileCopyPart)
+# define RTFileCopyPartCleanup RT_MANGLER(RTFileCopyPartCleanup)
+# define RTFileCopyPartEx RT_MANGLER(RTFileCopyPartEx)
+# define RTFileCopyPartPrep RT_MANGLER(RTFileCopyPartPrep)
+# define RTFileCreateUnique RT_MANGLER(RTFileCreateUnique)
+# define RTFileCreateTemp RT_MANGLER(RTFileCreateTemp)
+# define RTFileCreateTempSecure RT_MANGLER(RTFileCreateTempSecure)
+# define RTFileDelete RT_MANGLER(RTFileDelete)
+# define RTFileDup RT_MANGLER(RTFileDup)
+# define RTFileExists RT_MANGLER(RTFileExists)
+# define RTFileFlush RT_MANGLER(RTFileFlush)
+# define RTFileFromNative RT_MANGLER(RTFileFromNative)
+# define RTFileGetMaxSize RT_MANGLER(RTFileGetMaxSize)
+# define RTFileQueryMaxSizeEx RT_MANGLER(RTFileQueryMaxSizeEx)
+# define RTFileQuerySizeByPath RT_MANGLER(RTFileQuerySizeByPath)
+# 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 RTFileOpenEx RT_MANGLER(RTFileOpenEx)
+# 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 RTFileQuerySectorSize RT_MANGLER(RTFileQuerySectorSize)
+# 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 RTFileSgRead RT_MANGLER(RTFileSgRead)
+# define RTFileSgReadAt RT_MANGLER(RTFileSgReadAt)
+# define RTFileSgWrite RT_MANGLER(RTFileSgWrite)
+# 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 RTFsExtVolOpen RT_MANGLER(RTFsExtVolOpen)
+# define RTFsFatVolOpen RT_MANGLER(RTFsFatVolOpen)
+# define RTFsFatVolFormat RT_MANGLER(RTFsFatVolFormat)
+# define RTFsFatVolFormat144 RT_MANGLER(RTFsFatVolFormat144)
+# define RTFsFatVolFormat288 RT_MANGLER(RTFsFatVolFormat288)
+# define RTFsCmdLs RT_MANGLER(RTFsCmdLs)
+# define RTFsIso9660VolOpen RT_MANGLER(RTFsIso9660VolOpen)
+# define RTFsIsoMakerCreate RT_MANGLER(RTFsIsoMakerCreate)
+# define RTFsIsoMakerRetain RT_MANGLER(RTFsIsoMakerRetain)
+# define RTFsIsoMakerRelease RT_MANGLER(RTFsIsoMakerRelease)
+# define RTFsIsoMakerBootCatSetFile RT_MANGLER(RTFsIsoMakerBootCatSetFile)
+# define RTFsIsoMakerBootCatSetValidationEntry RT_MANGLER(RTFsIsoMakerBootCatSetValidationEntry)
+# define RTFsIsoMakerBootCatSetSectionEntry RT_MANGLER(RTFsIsoMakerBootCatSetSectionEntry)
+# define RTFsIsoMakerBootCatSetSectionHeaderEntry RT_MANGLER(RTFsIsoMakerBootCatSetSectionHeaderEntry)
+# define RTFsIsoMakerQueryObjIdxForBootCatalog RT_MANGLER(RTFsIsoMakerQueryObjIdxForBootCatalog)
+# define RTFsIsoMakerGetPopulatedNamespaces RT_MANGLER(RTFsIsoMakerGetPopulatedNamespaces)
+# define RTFsIsoMakerGetIso9660Level RT_MANGLER(RTFsIsoMakerGetIso9660Level)
+# define RTFsIsoMakerGetRockRidgeLevel RT_MANGLER(RTFsIsoMakerGetRockRidgeLevel)
+# define RTFsIsoMakerGetJolietRockRidgeLevel RT_MANGLER(RTFsIsoMakerGetJolietRockRidgeLevel)
+# define RTFsIsoMakerSetImagePadding RT_MANGLER(RTFsIsoMakerSetImagePadding)
+# define RTFsIsoMakerSetIso9660Level RT_MANGLER(RTFsIsoMakerSetIso9660Level)
+# define RTFsIsoMakerSetJolietUcs2Level RT_MANGLER(RTFsIsoMakerSetJolietUcs2Level)
+# define RTFsIsoMakerSetRockRidgeLevel RT_MANGLER(RTFsIsoMakerSetRockRidgeLevel)
+# define RTFsIsoMakerSetJolietRockRidgeLevel RT_MANGLER(RTFsIsoMakerSetJolietRockRidgeLevel)
+# define RTFsIsoMakerSetAttribInheritStyle RT_MANGLER(RTFsIsoMakerSetAttribInheritStyle)
+# define RTFsIsoMakerSetDefaultDirMode RT_MANGLER(RTFsIsoMakerSetDefaultDirMode)
+# define RTFsIsoMakerSetDefaultFileMode RT_MANGLER(RTFsIsoMakerSetDefaultFileMode)
+# define RTFsIsoMakerSetForcedDirMode RT_MANGLER(RTFsIsoMakerSetForcedDirMode)
+# define RTFsIsoMakerSetForcedFileMode RT_MANGLER(RTFsIsoMakerSetForcedFileMode)
+# define RTFsIsoMakerSetPathGroupId RT_MANGLER(RTFsIsoMakerSetPathGroupId)
+# define RTFsIsoMakerSetPathMode RT_MANGLER(RTFsIsoMakerSetPathMode)
+# define RTFsIsoMakerSetPathOwnerId RT_MANGLER(RTFsIsoMakerSetPathOwnerId)
+# define RTFsIsoMakerSetSysAreaContent RT_MANGLER(RTFsIsoMakerSetSysAreaContent)
+# define RTFsIsoMakerSetStringProp RT_MANGLER(RTFsIsoMakerSetStringProp)
+# define RTFsIsoMakerGetObjIdxForPath RT_MANGLER(RTFsIsoMakerGetObjIdxForPath)
+# define RTFsIsoMakerObjEnableBootInfoTablePatching RT_MANGLER(RTFsIsoMakerObjEnableBootInfoTablePatching)
+# define RTFsIsoMakerObjQueryDataSize RT_MANGLER(RTFsIsoMakerObjQueryDataSize)
+# define RTFsIsoMakerObjRemove RT_MANGLER(RTFsIsoMakerObjRemove)
+# define RTFsIsoMakerObjSetPath RT_MANGLER(RTFsIsoMakerObjSetPath)
+# define RTFsIsoMakerObjSetNameAndParent RT_MANGLER(RTFsIsoMakerObjSetNameAndParent)
+# define RTFsIsoMakerObjSetRockName RT_MANGLER(RTFsIsoMakerObjSetRockName)
+# define RTFsIsoMakerAddUnnamedDir RT_MANGLER(RTFsIsoMakerAddUnnamedDir)
+# define RTFsIsoMakerAddDir RT_MANGLER(RTFsIsoMakerAddDir)
+# define RTFsIsoMakerAddFileWithSrcPath RT_MANGLER(RTFsIsoMakerAddFileWithSrcPath)
+# define RTFsIsoMakerAddFileWithVfsFile RT_MANGLER(RTFsIsoMakerAddFileWithVfsFile)
+# define RTFsIsoMakerAddUnnamedFileWithSrcPath RT_MANGLER(RTFsIsoMakerAddUnnamedFileWithSrcPath)
+# define RTFsIsoMakerAddUnnamedFileWithVfsFile RT_MANGLER(RTFsIsoMakerAddUnnamedFileWithVfsFile)
+# define RTFsIsoMakerAddUnnamedFileWithCommonSrc RT_MANGLER(RTFsIsoMakerAddUnnamedFileWithCommonSrc)
+# define RTFsIsoMakerAddSymlink RT_MANGLER(RTFsIsoMakerAddSymlink)
+# define RTFsIsoMakerAddUnnamedSymlink RT_MANGLER(RTFsIsoMakerAddUnnamedSymlink)
+# define RTFsIsoMakerAddCommonSourceFile RT_MANGLER(RTFsIsoMakerAddCommonSourceFile)
+# define RTFsIsoMakerImport RT_MANGLER(RTFsIsoMakerImport)
+# define RTFsIsoMakerFinalize RT_MANGLER(RTFsIsoMakerFinalize)
+# define RTFsIsoMakerCreateVfsOutputFile RT_MANGLER(RTFsIsoMakerCreateVfsOutputFile)
+# define RTFsIsoMakerCmd RT_MANGLER(RTFsIsoMakerCmd)
+# define RTFsIsoMakerCmdEx RT_MANGLER(RTFsIsoMakerCmdEx)
+# define RTFsNtfsVolOpen RT_MANGLER(RTFsNtfsVolOpen)
+# define RTFtpServerCreate RT_MANGLER(RTFtpServerCreate)
+# define RTFtpServerDestroy RT_MANGLER(RTFtpServerDestroy)
+# define RTFuzzCmdMaster RT_MANGLER(RTFuzzCmdMaster)
+# define RTFuzzCfgCreateFromFile RT_MANGLER(RTFuzzCfgCreateFromFile)
+# define RTFuzzCfgCreateFromVfsFile RT_MANGLER(RTFuzzCfgCreateFromVfsFile)
+# define RTFuzzCfgRetain RT_MANGLER(RTFuzzCfgRetain)
+# define RTFuzzCfgRelease RT_MANGLER(RTFuzzCfgRelease)
+# define RTFuzzCfgImport RT_MANGLER(RTFuzzCfgImport)
+# define RTFuzzCfgQueryCustomCfg RT_MANGLER(RTFuzzCfgQueryCustomCfg)
+# define RTFuzzCtxCfgGetBehavioralFlags RT_MANGLER(RTFuzzCtxCfgGetBehavioralFlags)
+# define RTFuzzCtxCfgGetInputSeedMaximum RT_MANGLER(RTFuzzCtxCfgGetInputSeedMaximum)
+# define RTFuzzCtxCfgGetTmpDirectory RT_MANGLER(RTFuzzCtxCfgGetTmpDirectory)
+# define RTFuzzCtxCfgSetBehavioralFlags RT_MANGLER(RTFuzzCtxCfgSetBehavioralFlags)
+# define RTFuzzCtxCfgSetInputSeedMaximum RT_MANGLER(RTFuzzCtxCfgSetInputSeedMaximum)
+# define RTFuzzCtxCfgSetMutationRange RT_MANGLER(RTFuzzCtxCfgSetMutationRange)
+# define RTFuzzCtxCfgSetTmpDirectory RT_MANGLER(RTFuzzCtxCfgSetTmpDirectory)
+# define RTFuzzCtxCorpusInputAdd RT_MANGLER(RTFuzzCtxCorpusInputAdd)
+# define RTFuzzCtxCorpusInputAddEx RT_MANGLER(RTFuzzCtxCorpusInputAddEx)
+# define RTFuzzCtxCorpusInputAddFromDirPath RT_MANGLER(RTFuzzCtxCorpusInputAddFromDirPath)
+# define RTFuzzCtxCorpusInputAddFromFile RT_MANGLER(RTFuzzCtxCorpusInputAddFromFile)
+# define RTFuzzCtxCorpusInputAddFromFileEx RT_MANGLER(RTFuzzCtxCorpusInputAddFromFileEx)
+# define RTFuzzCtxCorpusInputAddFromVfsFile RT_MANGLER(RTFuzzCtxCorpusInputAddFromVfsFile)
+# define RTFuzzCtxCorpusInputAddFromVfsFileEx RT_MANGLER(RTFuzzCtxCorpusInputAddFromVfsFileEx)
+# define RTFuzzCtxCorpusInputAddFromVfsIoStrm RT_MANGLER(RTFuzzCtxCorpusInputAddFromVfsIoStrm)
+# define RTFuzzCtxCorpusInputAddFromVfsIoStrmEx RT_MANGLER(RTFuzzCtxCorpusInputAddFromVfsIoStrmEx)
+# define RTFuzzCtxCreate RT_MANGLER(RTFuzzCtxCreate)
+# define RTFuzzCtxCreateFromState RT_MANGLER(RTFuzzCtxCreateFromState)
+# define RTFuzzCtxCreateFromStateFile RT_MANGLER(RTFuzzCtxCreateFromStateFile)
+# define RTFuzzCtxCreateFromStateMem RT_MANGLER(RTFuzzCtxCreateFromStateMem)
+# define RTFuzzCtxInputGenerate RT_MANGLER(RTFuzzCtxInputGenerate)
+# define RTFuzzCtxQueryStats RT_MANGLER(RTFuzzCtxQueryStats)
+# define RTFuzzCtxRelease RT_MANGLER(RTFuzzCtxRelease)
+# define RTFuzzCtxReseed RT_MANGLER(RTFuzzCtxReseed)
+# define RTFuzzCtxRetain RT_MANGLER(RTFuzzCtxRetain)
+# define RTFuzzCtxStateExport RT_MANGLER(RTFuzzCtxStateExport)
+# define RTFuzzCtxStateExportToFile RT_MANGLER(RTFuzzCtxStateExportToFile)
+# define RTFuzzCtxStateExportToMem RT_MANGLER(RTFuzzCtxStateExportToMem)
+# define RTFuzzInputAddToCtxCorpus RT_MANGLER(RTFuzzInputAddToCtxCorpus)
+# define RTFuzzInputMutateStreamData RT_MANGLER(RTFuzzInputMutateStreamData)
+# define RTFuzzInputQueryBlobData RT_MANGLER(RTFuzzInputQueryBlobData)
+# define RTFuzzInputQueryDigestString RT_MANGLER(RTFuzzInputQueryDigestString)
+# define RTFuzzInputRelease RT_MANGLER(RTFuzzInputRelease)
+# define RTFuzzInputRemoveFromCtxCorpus RT_MANGLER(RTFuzzInputRemoveFromCtxCorpus)
+# define RTFuzzInputRetain RT_MANGLER(RTFuzzInputRetain)
+# define RTFuzzInputWriteToFile RT_MANGLER(RTFuzzInputWriteToFile)
+# define RTFuzzObsCreate RT_MANGLER(RTFuzzObsCreate)
+# define RTFuzzObsDestroy RT_MANGLER(RTFuzzObsDestroy)
+# define RTFuzzObsExecStart RT_MANGLER(RTFuzzObsExecStart)
+# define RTFuzzObsExecStop RT_MANGLER(RTFuzzObsExecStop)
+# define RTFuzzObsQueryCtx RT_MANGLER(RTFuzzObsQueryCtx)
+# define RTFuzzObsQueryStats RT_MANGLER(RTFuzzObsQueryStats)
+# define RTFuzzObsSetResultDirectory RT_MANGLER(RTFuzzObsSetResultDirectory)
+# define RTFuzzObsSetTestBinary RT_MANGLER(RTFuzzObsSetTestBinary)
+# define RTFuzzObsSetTestBinaryArgs RT_MANGLER(RTFuzzObsSetTestBinaryArgs)
+# define RTFuzzObsSetTestBinaryEnv RT_MANGLER(RTFuzzObsSetTestBinaryEnv)
+# define RTFuzzObsSetTestBinarySanitizers RT_MANGLER(RTFuzzObsSetTestBinarySanitizers)
+# define RTFuzzObsSetTestBinaryTimeout RT_MANGLER(RTFuzzObsSetTestBinaryTimeout)
+# define RTFuzzObsSetTmpDirectory RT_MANGLER(RTFuzzObsSetTmpDirectory)
+# define RTFuzzTgtRecorderCreate RT_MANGLER(RTFuzzTgtRecorderCreate)
+# define RTFuzzTgtRecorderCreateNewState RT_MANGLER(RTFuzzTgtRecorderCreateNewState)
+# define RTFuzzTgtRecorderRelease RT_MANGLER(RTFuzzTgtRecorderRelease)
+# define RTFuzzTgtRecorderRetain RT_MANGLER(RTFuzzTgtRecorderRetain)
+# define RTFuzzTgtStateAddProcSts RT_MANGLER(RTFuzzTgtStateAddProcSts)
+# define RTFuzzTgtStateAddSanCovReportFromFile RT_MANGLER(RTFuzzTgtStateAddSanCovReportFromFile)
+# define RTFuzzTgtStateAddToRecorder RT_MANGLER(RTFuzzTgtStateAddToRecorder)
+# define RTFuzzTgtStateAppendStderrFromBuf RT_MANGLER(RTFuzzTgtStateAppendStderrFromBuf)
+# define RTFuzzTgtStateAppendStderrFromPipe RT_MANGLER(RTFuzzTgtStateAppendStderrFromPipe)
+# define RTFuzzTgtStateAppendStdoutFromBuf RT_MANGLER(RTFuzzTgtStateAppendStdoutFromBuf)
+# define RTFuzzTgtStateAppendStdoutFromPipe RT_MANGLER(RTFuzzTgtStateAppendStdoutFromPipe)
+# define RTFuzzTgtStateDumpToDir RT_MANGLER(RTFuzzTgtStateDumpToDir)
+# define RTFuzzTgtStateFinalize RT_MANGLER(RTFuzzTgtStateFinalize)
+# define RTFuzzTgtStateRelease RT_MANGLER(RTFuzzTgtStateRelease)
+# define RTFuzzTgtStateReset RT_MANGLER(RTFuzzTgtStateReset)
+# define RTFuzzTgtStateRetain RT_MANGLER(RTFuzzTgtStateRetain)
+# define RTGetOpt RT_MANGLER(RTGetOpt)
+# define RTGetOptArgvFree RT_MANGLER(RTGetOptArgvFree)
+# define RTGetOptArgvFreeEx RT_MANGLER(RTGetOptArgvFreeEx)
+# 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 RTGetOptNonOptionArrayPtr RT_MANGLER(RTGetOptNonOptionArrayPtr)
+# define RTGetOptFormatError RT_MANGLER(RTGetOptFormatError)
+# 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 RTHttpGetFollowRedirects RT_MANGLER(RTHttpGetFollowRedirects)
+# define RTHttpSetFollowRedirects RT_MANGLER(RTHttpSetFollowRedirects)
+# define RTHttpGetVerifyPeer RT_MANGLER(RTHttpGetVerifyPeer)
+# define RTHttpHeaderListInit RT_MANGLER(RTHttpHeaderListInit)
+# define RTHttpHeaderListDestroy RT_MANGLER(RTHttpHeaderListDestroy)
+# define RTHttpHeaderListSet RT_MANGLER(RTHttpHeaderListSet)
+# define RTHttpHeaderListAddRaw RT_MANGLER(RTHttpHeaderListAddRaw)
+# define RTHttpHeaderListAdd RT_MANGLER(RTHttpHeaderListAdd)
+# define RTHttpHeaderListGet RT_MANGLER(RTHttpHeaderListGet)
+# define RTHttpHeaderListGetCount RT_MANGLER(RTHttpHeaderListGetCount)
+# define RTHttpHeaderListGetByOrdinal RT_MANGLER(RTHttpHeaderListGetByOrdinal)
+# define RTHttpMethodToStr RT_MANGLER(RTHttpMethodToStr)
+# define RTHttpSetVerifyPeer RT_MANGLER(RTHttpSetVerifyPeer)
+# define RTHttpUseSystemProxySettings RT_MANGLER(RTHttpUseSystemProxySettings)
+# define RTHttpServerCreate RT_MANGLER(RTHttpServerCreate)
+# define RTHttpServerDestroy RT_MANGLER(RTHttpServerDestroy)
+# define RTHttpServerResponseInitEx RT_MANGLER(RTHttpServerResponseInitEx)
+# define RTHttpServerResponseInit RT_MANGLER(RTHttpServerResponseInit)
+# define RTHttpServerResponseDestroy RT_MANGLER(RTHttpServerResponseDestroy)
+# define RTHttpStatusToStr RT_MANGLER(RTHttpStatusToStr)
+# define RTIniFileCreateFromVfsFile RT_MANGLER(RTIniFileCreateFromVfsFile)
+# define RTIniFileRetain RT_MANGLER(RTIniFileRetain)
+# define RTIniFileRelease RT_MANGLER(RTIniFileRelease)
+# define RTIniFileQueryPair RT_MANGLER(RTIniFileQueryPair)
+# define RTIniFileQueryValue RT_MANGLER(RTIniFileQueryValue)
+# define RTIoQueueCommit RT_MANGLER(RTIoQueueCommit)
+# define RTIoQueueCreate RT_MANGLER(RTIoQueueCreate)
+# define RTIoQueueDestroy RT_MANGLER(RTIoQueueDestroy)
+# define RTIoQueueEvtWait RT_MANGLER(RTIoQueueEvtWait)
+# define RTIoQueueEvtWaitWakeup RT_MANGLER(RTIoQueueEvtWaitWakeup)
+# define RTIoQueueHandleDeregister RT_MANGLER(RTIoQueueHandleDeregister)
+# define RTIoQueueHandleRegister RT_MANGLER(RTIoQueueHandleRegister)
+# define RTIoQueueProviderGetBestForHndType RT_MANGLER(RTIoQueueProviderGetBestForHndType)
+# define RTIoQueueProviderGetById RT_MANGLER(RTIoQueueProviderGetById)
+# define RTIoQueueRequestPrepare RT_MANGLER(RTIoQueueRequestPrepare)
+# define RTIoQueueRequestPrepareSg RT_MANGLER(RTIoQueueRequestPrepareSg)
+# define RTJsonIteratorBegin RT_MANGLER(RTJsonIteratorBegin)
+# define RTJsonIteratorBeginArray RT_MANGLER(RTJsonIteratorBeginArray)
+# define RTJsonIteratorBeginObject RT_MANGLER(RTJsonIteratorBeginObject)
+# 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 RTJsonParseFromVfsFile RT_MANGLER(RTJsonParseFromVfsFile)
+# 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 RTJsonValueQueryNumber RT_MANGLER(RTJsonValueQueryNumber)
+# define RTJsonValueQueryNumberByName RT_MANGLER(RTJsonValueQueryNumberByName)
+# define RTJsonValueQueryString RT_MANGLER(RTJsonValueQueryString)
+# define RTJsonValueQueryStringByName RT_MANGLER(RTJsonValueQueryStringByName)
+# define RTJsonValueRelease RT_MANGLER(RTJsonValueRelease)
+# define RTJsonValueRetain RT_MANGLER(RTJsonValueRetain)
+# define RTJsonValueTypeName RT_MANGLER(RTJsonValueTypeName)
+# define RTKrnlModInfoGetFilePath RT_MANGLER(RTKrnlModInfoGetFilePath)
+# define RTKrnlModInfoGetLoadAddr RT_MANGLER(RTKrnlModInfoGetLoadAddr)
+# define RTKrnlModInfoGetName RT_MANGLER(RTKrnlModInfoGetName)
+# define RTKrnlModInfoGetRefCnt RT_MANGLER(RTKrnlModInfoGetRefCnt)
+# define RTKrnlModInfoGetSize RT_MANGLER(RTKrnlModInfoGetSize)
+# define RTKrnlModInfoQueryRefModInfo RT_MANGLER(RTKrnlModInfoQueryRefModInfo)
+# define RTKrnlModInfoRetain RT_MANGLER(RTKrnlModInfoRetain)
+# define RTKrnlModInfoRelease RT_MANGLER(RTKrnlModInfoRelease)
+# define RTKrnlModLoadByName RT_MANGLER(RTKrnlModLoadByName)
+# define RTKrnlModLoadByPath RT_MANGLER(RTKrnlModLoadByPath)
+# define RTKrnlModLoadedGetCount RT_MANGLER(RTKrnlModLoadedGetCount)
+# define RTKrnlModLoadedQueryInfo RT_MANGLER(RTKrnlModLoadedQueryInfo)
+# define RTKrnlModLoadedQueryInfoAll RT_MANGLER(RTKrnlModLoadedQueryInfoAll)
+# define RTKrnlModQueryLoaded RT_MANGLER(RTKrnlModQueryLoaded)
+# define RTKrnlModUnloadByName RT_MANGLER(RTKrnlModUnloadByName)
+# 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 RTLdrArchName RT_MANGLER(RTLdrArchName)
+# 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 RTLdrGetHostArch RT_MANGLER(RTLdrGetHostArch)
+# 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 RTLdrGetSystemSymbolEx RT_MANGLER(RTLdrGetSystemSymbolEx)
+# 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 RTLdrLoadSystemEx RT_MANGLER(RTLdrLoadSystemEx)
+# define RTLdrOpen RT_MANGLER(RTLdrOpen)
+# define RTLdrOpenEx RT_MANGLER(RTLdrOpenEx)
+# define RTLdrOpenInMemory RT_MANGLER(RTLdrOpenInMemory)
+# define RTLdrOpenVfsChain RT_MANGLER(RTLdrOpenVfsChain)
+# 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 RTLdrUnwindFrame RT_MANGLER(RTLdrUnwindFrame)
+# define RTLinuxCheckDevicePath RT_MANGLER(RTLinuxCheckDevicePath)
+# define RTLinuxCheckDevicePathV RT_MANGLER(RTLinuxCheckDevicePathV)
+# define RTLinuxConstructPath RT_MANGLER(RTLinuxConstructPath)
+# define RTLinuxConstructPathV RT_MANGLER(RTLinuxConstructPathV)
+# 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 RTLocalIpcServerGrantGroupAccess RT_MANGLER(RTLocalIpcServerGrantGroupAccess)
+# define RTLocalIpcServerSetAccessMode RT_MANGLER(RTLocalIpcServerSetAccessMode);
+# 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 RTLocaleQueryLocaleName RT_MANGLER(RTLocaleQueryLocaleName)
+# define RTLocaleQueryNormalizedBaseLocaleName RT_MANGLER(RTLocaleQueryNormalizedBaseLocaleName)
+# define RTLocaleQueryUserCountryCode RT_MANGLER(RTLocaleQueryUserCountryCode)
+# 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 RTLogAssert RT_MANGLER(RTLogAssert)
+# define RTLogAssertV RT_MANGLER(RTLogAssertV)
+# define RTLogBackdoorPrintf RT_MANGLER(RTLogBackdoorPrintf) /* r0drv-guest */
+# define RTLogBackdoorPrintfV RT_MANGLER(RTLogBackdoorPrintfV) /* r0drv-guest */
+# define RTLogBulkUpdate RT_MANGLER(RTLogBulkUpdate)
+# define RTLogBulkWrite RT_MANGLER(RTLogBulkWrite)
+# define RTLogBulkNestedWrite RT_MANGLER(RTLogBulkNestedWrite)
+# define RTLogChangeDestinations RT_MANGLER(RTLogChangeDestinations)
+# define RTLogChangeFlags RT_MANGLER(RTLogChangeFlags)
+# define RTLogCheckGroupFlags RT_MANGLER(RTLogCheckGroupFlags)
+# define RTLogClearFileDelayFlag RT_MANGLER(RTLogClearFileDelayFlag)
+# define RTLogCloneRC RT_MANGLER(RTLogCloneRC)
+# define RTLogComPrintf RT_MANGLER(RTLogComPrintf)
+# define RTLogComPrintfV RT_MANGLER(RTLogComPrintfV)
+# define RTLogCreate RT_MANGLER(RTLogCreate)
+# define RTLogCreateEx RT_MANGLER(RTLogCreateEx)
+# define RTLogCreateExV RT_MANGLER(RTLogCreateExV)
+# 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 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 RTLogGroupSettings RT_MANGLER(RTLogGroupSettings)
+# define RTLogLogger RT_MANGLER(RTLogLogger)
+# define RTLogLoggerWeak RT_MANGLER(RTLogLoggerWeak)
+# define RTLogLoggerEx RT_MANGLER(RTLogLoggerEx)
+# define RTLogLoggerExWeak RT_MANGLER(RTLogLoggerExWeak)
+# 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 RTLogQueryBulk RT_MANGLER(RTLogQueryBulk)
+# define RTLogQueryDestinations RT_MANGLER(RTLogQueryDestinations)
+# define RTLogQueryFlags RT_MANGLER(RTLogQueryFlags)
+# define RTLogQueryGroupSettings RT_MANGLER(RTLogQueryGroupSettings)
+# 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 RTLogSetFlushCallback RT_MANGLER(RTLogSetFlushCallback)
+# define RTLogSetDefaultInstance RT_MANGLER(RTLogSetDefaultInstance)
+# define RTLogSetDefaultInstanceThread RT_MANGLER(RTLogSetDefaultInstanceThread) /* r0drv */
+# define RTLogSetGroupLimit RT_MANGLER(RTLogSetGroupLimit)
+# define RTLogSetR0ProgramStart RT_MANGLER(RTLogSetR0ProgramStart) /* r0drv */
+# define RTLogSetR0ThreadNameF RT_MANGLER(RTLogSetR0ThreadNameF) /* r0drv */
+# define RTLogSetR0ThreadNameV RT_MANGLER(RTLogSetR0ThreadNameV) /* r0drv */
+# 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 RTLogWriteVmm RT_MANGLER(RTLogWriteVmm)
+# define RTLogWriteVmm_EndProc RT_MANGLER(RTLogWriteVmm_EndProc)
+# 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 RTMd4 RT_MANGLER(RTMd4)
+# define RTMd4Final RT_MANGLER(RTMd4Final)
+# define RTMd4FromString RT_MANGLER(RTMd4FromString)
+# define RTMd4Init RT_MANGLER(RTMd4Init)
+# define RTMd4ToString RT_MANGLER(RTMd4ToString)
+# define RTMd4Update RT_MANGLER(RTMd4Update)
+# 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 RTMemDumpFreed RT_MANGLER(RTMemDumpFreed)
+# 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 RTMemEfFreeZ RT_MANGLER(RTMemEfFreeZ)
+# define RTMemEfFreeZNP RT_MANGLER(RTMemEfFreeZNP)
+# define RTMemEfRealloc RT_MANGLER(RTMemEfRealloc)
+# define RTMemEfReallocNP RT_MANGLER(RTMemEfReallocNP)
+# define RTMemEfReallocZ RT_MANGLER(RTMemEfReallocZ)
+# define RTMemEfReallocZNP RT_MANGLER(RTMemEfReallocZNP)
+# 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 RTMemEfTmpFreeZ RT_MANGLER(RTMemEfTmpFreeZ)
+# define RTMemEfTmpFreeZNP RT_MANGLER(RTMemEfTmpFreeZNP)
+# define RTMemFree RT_MANGLER(RTMemFree)
+# define RTMemFreeZ RT_MANGLER(RTMemFreeZ)
+# define RTMemFreeEx RT_MANGLER(RTMemFreeEx)
+# define RTMemPageAllocTag RT_MANGLER(RTMemPageAllocTag)
+# define RTMemPageAllocExTag RT_MANGLER(RTMemPageAllocExTag)
+# 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 RTMemReallocZTag RT_MANGLER(RTMemReallocZTag)
+# define RTMemTmpAllocTag RT_MANGLER(RTMemTmpAllocTag)
+# define RTMemTmpAllocZTag RT_MANGLER(RTMemTmpAllocZTag)
+# define RTMemTmpFree RT_MANGLER(RTMemTmpFree)
+# define RTMemTmpFreeZ RT_MANGLER(RTMemTmpFreeZ)
+# 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 RTMsgErrorExitFailure RT_MANGLER(RTMsgErrorExitFailure)
+# define RTMsgErrorExitFailureV RT_MANGLER(RTMsgErrorExitFailureV)
+# 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 RTMsgSyntax RT_MANGLER(RTMsgSyntax)
+# define RTMsgSyntaxV RT_MANGLER(RTMsgSyntaxV)
+# define RTMsgWarning RT_MANGLER(RTMsgWarning)
+# define RTMsgWarningV RT_MANGLER(RTMsgWarningV)
+# define RTMsgRefEntryPrintStringTable RT_MANGLER(RTMsgRefEntryPrintStringTable)
+# define RTMsgRefEntrySynopsisEx RT_MANGLER(RTMsgRefEntrySynopsisEx)
+# define RTMsgRefEntrySynopsis RT_MANGLER(RTMsgRefEntrySynopsis)
+# define RTMsgRefEntryHelpEx RT_MANGLER(RTMsgRefEntryHelpEx)
+# define RTMsgRefEntryHelp RT_MANGLER(RTMsgRefEntryHelp)
+# 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 RTNetIsIPv4AddrStr RT_MANGLER(RTNetIsIPv4AddrStr)
+# define RTNetIsIPv6AddrStr RT_MANGLER(RTNetIsIPv6AddrStr)
+# define RTNetMaskToPrefixIPv4 RT_MANGLER(RTNetMaskToPrefixIPv4)
+# define RTNetMaskToPrefixIPv6 RT_MANGLER(RTNetMaskToPrefixIPv6)
+# define RTNetPrefixToMaskIPv4 RT_MANGLER(RTNetPrefixToMaskIPv4)
+# define RTNetPrefixToMaskIPv6 RT_MANGLER(RTNetPrefixToMaskIPv6)
+# define RTNetStrIsIPv4AddrAny RT_MANGLER(RTNetStrIsIPv4AddrAny)
+# define RTNetStrIsIPv6AddrAny RT_MANGLER(RTNetStrIsIPv6AddrAny)
+# define RTNetStrToIPv4Addr RT_MANGLER(RTNetStrToIPv4Addr)
+# define RTNetStrToIPv4AddrEx RT_MANGLER(RTNetStrToIPv4AddrEx)
+# define RTNetStrToIPv4Cidr RT_MANGLER(RTNetStrToIPv4Cidr)
+# define RTNetStrToIPv6Addr RT_MANGLER(RTNetStrToIPv6Addr)
+# define RTNetStrToIPv6AddrEx RT_MANGLER(RTNetStrToIPv6AddrEx)
+# define RTNetStrToIPv6Cidr RT_MANGLER(RTNetStrToIPv6Cidr)
+# define RTNetStrToMacAddr RT_MANGLER(RTNetStrToMacAddr)
+# define RTNetTCPChecksum RT_MANGLER(RTNetTCPChecksum)
+# define RTNetUDPChecksum RT_MANGLER(RTNetUDPChecksum)
+# 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 RTPathEnsureTrailingSeparatorEx RT_MANGLER(RTPathEnsureTrailingSeparatorEx)
+# 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 RTPathFilenameUtf16 RT_MANGLER(RTPathFilenameUtf16)
+# define RTPathFilenameEx RT_MANGLER(RTPathFilenameEx)
+# define RTPathFilenameExUtf16 RT_MANGLER(RTPathFilenameExUtf16)
+# define RTPathFindCommon RT_MANGLER(RTPathFindCommon)
+# define RTPathFindCommonEx RT_MANGLER(RTPathFindCommonEx)
+# 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 RTPathParentLength RT_MANGLER(RTPathParentLength)
+# define RTPathParentLengthEx RT_MANGLER(RTPathParentLengthEx)
+# define RTPathParse RT_MANGLER(RTPathParse)
+# define RTPathParsedReassemble RT_MANGLER(RTPathParsedReassemble)
+# define RTPathParseSimple RT_MANGLER(RTPathParseSimple)
+# define RTPathPurgeFilename RT_MANGLER(RTPathPurgeFilename)
+# 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 RTPathSkipRootSpec RT_MANGLER(RTPathSkipRootSpec)
+# 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 RTPipeCloseEx RT_MANGLER(RTPipeCloseEx)
+# 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 RTProcExecutablePath RT_MANGLER(RTProcExecutablePath)
+# 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 RTProcSignalName RT_MANGLER(RTProcSignalName)
+# 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 RTR0DbgKrnlInfoGetSymbol RT_MANGLER(RTR0DbgKrnlInfoGetSymbol) /* 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 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 RTR0MemObjAllocLargeTag RT_MANGLER(RTR0MemObjAllocLargeTag) /* 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 RTR0MemObjMapUserExTag RT_MANGLER(RTR0MemObjMapUserExTag) /* 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 RTR0MemObjWasZeroInitialized RT_MANGLER(RTR0MemObjWasZeroInitialized)/* r0drv */
+# define RTR0MemUserCopyFrom RT_MANGLER(RTR0MemUserCopyFrom) /* r0drv */
+# define RTR0MemUserCopyTo RT_MANGLER(RTR0MemUserCopyTo) /* r0drv */
+# define RTR0MemUserIsValidAddr RT_MANGLER(RTR0MemUserIsValidAddr) /* r0drv */
+# define rtR0MemObjLinuxVirtToPage RT_MANGLER(rtR0MemObjLinuxVirtToPage) /* r0drv linux-only */
+# 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 RTReqCancel RT_MANGLER(RTReqCancel)
+# define RTReqRelease RT_MANGLER(RTReqRelease)
+# define RTReqRetain RT_MANGLER(RTReqRetain)
+# define RTReqSubmit RT_MANGLER(RTReqSubmit)
+# 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 RTSemEventIsSignalSafe RT_MANGLER(RTSemEventIsSignalSafe) /* 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 RTSemEventMultiIsSignalSafe RT_MANGLER(RTSemEventMultiIsSignalSafe) /* 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 RTSerialPortOpen RT_MANGLER(RTSerialPortOpen)
+# define RTSerialPortClose RT_MANGLER(RTSerialPortClose)
+# define RTSerialPortToNative RT_MANGLER(RTSerialPortToNative)
+# define RTSerialPortRead RT_MANGLER(RTSerialPortRead)
+# define RTSerialPortReadNB RT_MANGLER(RTSerialPortReadNB)
+# define RTSerialPortWrite RT_MANGLER(RTSerialPortWrite)
+# define RTSerialPortWriteNB RT_MANGLER(RTSerialPortWriteNB)
+# define RTSerialPortCfgQueryCurrent RT_MANGLER(RTSerialPortCfgQueryCurrent)
+# define RTSerialPortCfgSet RT_MANGLER(RTSerialPortCfgSet)
+# define RTSerialPortEvtPoll RT_MANGLER(RTSerialPortEvtPoll)
+# define RTSerialPortEvtPollInterrupt RT_MANGLER(RTSerialPortEvtPollInterrupt)
+# define RTSerialPortChgBreakCondition RT_MANGLER(RTSerialPortChgBreakCondition)
+# define RTSerialPortChgStatusLines RT_MANGLER(RTSerialPortChgStatusLines)
+# define RTSerialPortQueryStatusLines RT_MANGLER(RTSerialPortQueryStatusLines)
+# 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 RTSgBufCopyFromFn RT_MANGLER(RTSgBufCopyFromFn)
+# define RTSgBufCopyToBuf RT_MANGLER(RTSgBufCopyToBuf)
+# define RTSgBufCopyToFn RT_MANGLER(RTSgBufCopyToFn)
+# 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 RTSha3t224 RT_MANGLER(RTSha3t224)
+# define RTSha3t224Check RT_MANGLER(RTSha3t224Check)
+# define RTSha3t224Cleanup RT_MANGLER(RTSha3t224Cleanup)
+# define RTSha3t224Clone RT_MANGLER(RTSha3t224Clone)
+# define RTSha3t224Init RT_MANGLER(RTSha3t224Init)
+# define RTSha3t224Final RT_MANGLER(RTSha3t224Final)
+# define RTSha3t224FromString RT_MANGLER(RTSha3t224FromString)
+# define RTSha3t224ToString RT_MANGLER(RTSha3t224ToString)
+# define RTSha3t224Update RT_MANGLER(RTSha3t224Update)
+# define RTSha3t256 RT_MANGLER(RTSha3t256)
+# define RTSha3t256Check RT_MANGLER(RTSha3t256Check)
+# define RTSha3t256Cleanup RT_MANGLER(RTSha3t256Cleanup)
+# define RTSha3t256Clone RT_MANGLER(RTSha3t256Clone)
+# define RTSha3t256Init RT_MANGLER(RTSha3t256Init)
+# define RTSha3t256Final RT_MANGLER(RTSha3t256Final)
+# define RTSha3t256FromString RT_MANGLER(RTSha3t256FromString)
+# define RTSha3t256ToString RT_MANGLER(RTSha3t256ToString)
+# define RTSha3t256Update RT_MANGLER(RTSha3t256Update)
+# define RTSha3t384 RT_MANGLER(RTSha3t384)
+# define RTSha3t384Check RT_MANGLER(RTSha3t384Check)
+# define RTSha3t384Cleanup RT_MANGLER(RTSha3t384Cleanup)
+# define RTSha3t384Clone RT_MANGLER(RTSha3t384Clone)
+# define RTSha3t384Init RT_MANGLER(RTSha3t384Init)
+# define RTSha3t384Final RT_MANGLER(RTSha3t384Final)
+# define RTSha3t384FromString RT_MANGLER(RTSha3t384FromString)
+# define RTSha3t384ToString RT_MANGLER(RTSha3t384ToString)
+# define RTSha3t384Update RT_MANGLER(RTSha3t384Update)
+# define RTSha3t512 RT_MANGLER(RTSha3t512)
+# define RTSha3t512Check RT_MANGLER(RTSha3t512Check)
+# define RTSha3t512Cleanup RT_MANGLER(RTSha3t512Cleanup)
+# define RTSha3t512Clone RT_MANGLER(RTSha3t512Clone)
+# define RTSha3t512Init RT_MANGLER(RTSha3t512Init)
+# define RTSha3t512Final RT_MANGLER(RTSha3t512Final)
+# define RTSha3t512FromString RT_MANGLER(RTSha3t512FromString)
+# define RTSha3t512ToString RT_MANGLER(RTSha3t512ToString)
+# define RTSha3t512Update RT_MANGLER(RTSha3t512Update)
+# define RTShMemClose RT_MANGLER(RTShMemClose)
+# define RTShMemDelete RT_MANGLER(RTShMemDelete)
+# define RTShMemMapRegion RT_MANGLER(RTShMemMapRegion)
+# define RTShMemOpen RT_MANGLER(RTShMemOpen)
+# define RTShMemQuerySize RT_MANGLER(RTShMemQuerySize)
+# define RTShMemRefCount RT_MANGLER(RTShMemRefCount)
+# define RTShMemSetSize RT_MANGLER(RTShMemSetSize)
+# define RTShMemUnmapRegion RT_MANGLER(RTShMemUnmapRegion)
+# 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 RTStrConvertHexBytesEx RT_MANGLER(RTStrConvertHexBytesEx)
+# 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 RTStrConsoleCPToUtf8Tag RT_MANGLER(RTStrConsoleCPToUtf8Tag)
+# define RTStrDupExTag RT_MANGLER(RTStrDupExTag)
+# define RTStrDupNTag RT_MANGLER(RTStrDupNTag)
+# define RTStrDupNExTag RT_MANGLER(RTStrDupNExTag)
+# define RTStrDupTag RT_MANGLER(RTStrDupTag)
+# define RTStrEnd RT_MANGLER(RTStrEnd)
+# define RTStrEnd_EndProc RT_MANGLER(RTStrEnd_EndProc)
+# define RTStrFormat RT_MANGLER(RTStrFormat)
+# define RTStrFormatNumber RT_MANGLER(RTStrFormatNumber)
+# define RTStrFormatR32 RT_MANGLER(RTStrFormatR32)
+# define RTStrFormatR64 RT_MANGLER(RTStrFormatR64)
+# 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 RTStrMemFind16 RT_MANGLER(RTStrMemFind16)
+# define RTStrMemFind16_EndProc RT_MANGLER(RTStrMemFind16_EndProc)
+# define RTStrMemFind32 RT_MANGLER(RTStrMemFind32)
+# define RTStrMemFind32_EndProc RT_MANGLER(RTStrMemFind32_EndProc)
+# define RTStrMemFind64 RT_MANGLER(RTStrMemFind64)
+# define RTStrMemFind64_EndProc RT_MANGLER(RTStrMemFind64_EndProc)
+# define RTStrSplit RT_MANGLER(RTStrSplit)
+# 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 RTStrmGetLine RT_MANGLER(RTStrmGetLine)
+# define RTStrmOpen RT_MANGLER(RTStrmOpen)
+# define RTStrmOpenF RT_MANGLER(RTStrmOpenF)
+# define RTStrmOpenFV RT_MANGLER(RTStrmOpenFV)
+# define RTStrmOpenFileHandle RT_MANGLER(RTStrmOpenFileHandle)
+# define RTStrmQueryFileHandle RT_MANGLER(RTStrmQueryFileHandle)
+# define RTStrmPrintf RT_MANGLER(RTStrmPrintf)
+# define RTStrmPrintfV RT_MANGLER(RTStrmPrintfV)
+# define RTStrmWrappedPrintf RT_MANGLER(RTStrmWrappedPrintf)
+# define RTStrmWrappedPrintfV RT_MANGLER(RTStrmWrappedPrintfV)
+# 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 RTStrmSetBufferingMode RT_MANGLER(RTStrmSetBufferingMode)
+# define RTStrmSetMode RT_MANGLER(RTStrmSetMode)
+# define RTStrmSeek RT_MANGLER(RTStrmSeek)
+# define RTStrmTell RT_MANGLER(RTStrmTell)
+# define RTStrmWriteEx RT_MANGLER(RTStrmWriteEx)
+# define RTStrmIsTerminal RT_MANGLER(RTStrmIsTerminal)
+# define RTStrmInputGetEchoChars RT_MANGLER(RTStrmInputGetEchoChars)
+# define RTStrmInputSetEchoChars RT_MANGLER(RTStrmInputSetEchoChars)
+# define RTStrmQueryTerminalWidth RT_MANGLER(RTStrmQueryTerminalWidth)
+# define RTStrNanLongDouble RT_MANGLER(RTStrNanLongDouble)
+# define RTStrNanDouble RT_MANGLER(RTStrNanDouble)
+# define RTStrNanFloat RT_MANGLER(RTStrNanFloat)
+# define RTStrNCmp RT_MANGLER(RTStrNCmp)
+# define RTStrNICmp RT_MANGLER(RTStrNICmp)
+# define RTStrNICmpAscii RT_MANGLER(RTStrNICmpAscii)
+# 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 RTStrPrintf2 RT_MANGLER(RTStrPrintf2)
+# define RTStrPrintf2Ex RT_MANGLER(RTStrPrintf2Ex)
+# define RTStrPrintf2ExV RT_MANGLER(RTStrPrintf2ExV)
+# define RTStrPrintf2V RT_MANGLER(RTStrPrintf2V)
+# 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 RTStrToFloatEx RT_MANGLER(RTStrToFloatEx)
+# define RTStrToDoubleEx RT_MANGLER(RTStrToDoubleEx)
+# define RTStrToLongDoubleEx RT_MANGLER(RTStrToLongDoubleEx)
+# define RTStrToUni RT_MANGLER(RTStrToUni)
+# define RTStrToUniEx RT_MANGLER(RTStrToUniEx)
+# define RTStrToUpper RT_MANGLER(RTStrToUpper)
+# define RTStrToUtf16BigExTag RT_MANGLER(RTStrToUtf16BigExTag)
+# define RTStrToUtf16BigTag RT_MANGLER(RTStrToUtf16BigTag)
+# 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 RTStrUtf8ToCurrentCPExTag RT_MANGLER(RTStrUtf8ToCurrentCPExTag)
+# 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 RTSystemQueryFirmwareType RT_MANGLER(RTSystemQueryFirmwareType)
+# define RTSystemQueryFirmwareBoolean RT_MANGLER(RTSystemQueryFirmwareBoolean)
+# define RTSystemFirmwareTypeName RT_MANGLER(RTSystemFirmwareTypeName)
+# 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 RTTcpCreatePair RT_MANGLER(RTTcpCreatePair)
+# 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 RTTcpSetBufferSize RT_MANGLER(RTTcpSetBufferSize)
+# 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 RTTestErrContext RT_MANGLER(RTTestErrContext)
+# define RTTestErrContextV RT_MANGLER(RTTestErrContextV)
+# 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 RTTestIErrContext RT_MANGLER(RTTestIErrContext)
+# define RTTestIErrContextV RT_MANGLER(RTTestIErrContextV)
+# 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 RTThreadGetNativeHandle RT_MANGLER(RTThreadGetNativeHandle)
+# 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 RTThreadControlPokeSignal RT_MANGLER(RTThreadControlPokeSignal) /* not-win not-os2 */
+# 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 RTThreadQueryTerminationStatus RT_MANGLER(RTThreadQueryTerminationStatus) /* 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 RTTimeCompare RT_MANGLER(RTTimeCompare)
+# define RTTimeConvertToZulu RT_MANGLER(RTTimeConvertToZulu)
+# define RTTimeDbgBad RT_MANGLER(RTTimeDbgBad)
+# define RTTimeDbgExpired RT_MANGLER(RTTimeDbgExpired)
+# define RTTimeDbgRaces RT_MANGLER(RTTimeDbgRaces)
+# define RTTimeDbgSteps RT_MANGLER(RTTimeDbgSteps)
+# define RTTimeFormatDuration RT_MANGLER(RTTimeFormatDuration)
+# define RTTimeFormatDurationEx RT_MANGLER(RTTimeFormatDurationEx)
+# define RTTimeExplode RT_MANGLER(RTTimeExplode)
+# define RTTimeImplode RT_MANGLER(RTTimeImplode)
+# define RTTimeIsLeapYear RT_MANGLER(RTTimeIsLeapYear)
+# define RTTimeLocalDeltaNano RT_MANGLER(RTTimeLocalDeltaNano)
+# define RTTimeLocalDeltaNanoFor RT_MANGLER(RTTimeLocalDeltaNanoFor)
+# define RTTimeLocalExplode RT_MANGLER(RTTimeLocalExplode)
+# define RTTimeLocalNormalize RT_MANGLER(RTTimeLocalNormalize)
+# 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 RTTimeNanoTSLegacyAsyncUseApicIdExt0B RT_MANGLER(RTTimeNanoTSLegacyAsyncUseApicIdExt0B)
+# define RTTimeNanoTSLegacyAsyncUseApicIdExt0B_EndProc RT_MANGLER(RTTimeNanoTSLegacyAsyncUseApicIdExt0B_EndProc)
+# define RTTimeNanoTSLegacyAsyncUseApicIdExt8000001E RT_MANGLER(RTTimeNanoTSLegacyAsyncUseApicIdExt8000001E)
+# define RTTimeNanoTSLegacyAsyncUseApicIdExt8000001E_EndProc RT_MANGLER(RTTimeNanoTSLegacyAsyncUseApicIdExt8000001E_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 RTTimeNanoTSLegacySyncInvarWithDeltaUseApicIdExt0B RT_MANGLER(RTTimeNanoTSLegacySyncInvarWithDeltaUseApicIdExt0B)
+# define RTTimeNanoTSLegacySyncInvarWithDeltaUseApicIdExt0B_EndProc RT_MANGLER(RTTimeNanoTSLegacySyncInvarWithDeltaUseApicIdExt0B_EndProc)
+# define RTTimeNanoTSLegacySyncInvarWithDeltaUseApicIdExt8000001E RT_MANGLER(RTTimeNanoTSLegacySyncInvarWithDeltaUseApicIdExt8000001E)
+# define RTTimeNanoTSLegacySyncInvarWithDeltaUseApicIdExt8000001E_EndProc RT_MANGLER(RTTimeNanoTSLegacySyncInvarWithDeltaUseApicIdExt8000001E_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 RTTimeNanoTSLFenceAsyncUseApicIdExt0B RT_MANGLER(RTTimeNanoTSLFenceAsyncUseApicIdExt0B)
+# define RTTimeNanoTSLFenceAsyncUseApicIdExt0B_EndProc RT_MANGLER(RTTimeNanoTSLFenceAsyncUseApicIdExt0B_EndProc)
+# define RTTimeNanoTSLFenceAsyncUseApicIdExt8000001E RT_MANGLER(RTTimeNanoTSLFenceAsyncUseApicIdExt8000001E)
+# define RTTimeNanoTSLFenceAsyncUseApicIdExt8000001E_EndProc RT_MANGLER(RTTimeNanoTSLFenceAsyncUseApicIdExt8000001E_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 RTTimeNanoTSLFenceSyncInvarWithDeltaUseApicIdExt0B RT_MANGLER(RTTimeNanoTSLFenceSyncInvarWithDeltaUseApicIdExt0B)
+# define RTTimeNanoTSLFenceSyncInvarWithDeltaUseApicIdExt0B_EndProc RT_MANGLER(RTTimeNanoTSLFenceSyncInvarWithDeltaUseApicIdExt0B_EndProc)
+# define RTTimeNanoTSLFenceSyncInvarWithDeltaUseApicIdExt8000001E RT_MANGLER(RTTimeNanoTSLFenceSyncInvarWithDeltaUseApicIdExt8000001E)
+# define RTTimeNanoTSLFenceSyncInvarWithDeltaUseApicIdExt8000001E_EndProc RT_MANGLER(RTTimeNanoTSLFenceSyncInvarWithDeltaUseApicIdExt8000001E_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 RTTimeNanoTSWorkerName RT_MANGLER(RTTimeNanoTSWorkerName)
+# 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 RTTimeFromRfc2822 RT_MANGLER(RTTimeFromRfc2822)
+# define RTTimeToString RT_MANGLER(RTTimeToString)
+# define RTTimeToStringEx RT_MANGLER(RTTimeToStringEx)
+# define RTTimeToRfc2822 RT_MANGLER(RTTimeToRfc2822)
+# define RTTimeZoneGetInfoByUnixName RT_MANGLER(RTTimeZoneGetInfoByUnixName)
+# define RTTimeZoneGetInfoByWindowsName RT_MANGLER(RTTimeZoneGetInfoByWindowsName)
+# define RTTimeZoneGetInfoByWindowsIndex RT_MANGLER(RTTimeZoneGetInfoByWindowsIndex)
+# define RTTimeZoneGetCurrent RT_MANGLER(RTTimeZoneGetCurrent)
+# 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 RTTpmOpen RT_MANGLER(RTTpmOpen)
+# define RTTpmClose RT_MANGLER(RTTpmClose)
+# define RTTpmGetLocalityMax RT_MANGLER(RTTpmGetLocalityMax)
+# define RTTpmGetVersion RT_MANGLER(RTTpmGetVersion)
+# define RTTpmReqCancel RT_MANGLER(RTTpmReqCancel)
+# define RTTpmReqExec RT_MANGLER(RTTpmReqExec)
+# 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 RTTraceLogRdrCreate RT_MANGLER(RTTraceLogRdrCreate)
+# define RTTraceLogRdrCreateFromFile RT_MANGLER(RTTraceLogRdrCreateFromFile)
+# define RTTraceLogRdrDestroy RT_MANGLER(RTTraceLogRdrDestroy)
+# define RTTraceLogRdrEvtFillVals RT_MANGLER(RTTraceLogRdrEvtFillVals)
+# define RTTraceLogRdrEvtGetDesc RT_MANGLER(RTTraceLogRdrEvtGetDesc)
+# define RTTraceLogRdrEvtGetSeqNo RT_MANGLER(RTTraceLogRdrEvtGetSeqNo)
+# define RTTraceLogRdrEvtGetTs RT_MANGLER(RTTraceLogRdrEvtGetTs)
+# define RTTraceLogRdrEvtIsGrouped RT_MANGLER(RTTraceLogRdrEvtIsGrouped)
+# define RTTraceLogRdrEvtMapToStruct RT_MANGLER(RTTraceLogRdrEvtMapToStruct)
+# define RTTraceLogRdrEvtMapFree RT_MANGLER(RTTraceLogRdrEvtMapFree)
+# define RTTraceLogRdrEvtPoll RT_MANGLER(RTTraceLogRdrEvtPoll)
+# define RTTraceLogRdrEvtQueryVal RT_MANGLER(RTTraceLogRdrEvtQueryVal)
+# define RTTraceLogRdrIteratorFree RT_MANGLER(RTTraceLogRdrIteratorFree)
+# define RTTraceLogRdrIteratorNext RT_MANGLER(RTTraceLogRdrIteratorNext)
+# define RTTraceLogRdrIteratorQueryEvent RT_MANGLER(RTTraceLogRdrIteratorQueryEvent)
+# define RTTraceLogRdrQueryIterator RT_MANGLER(RTTraceLogRdrQueryIterator)
+# define RTTraceLogRdrQueryLastEvt RT_MANGLER(RTTraceLogRdrQueryLastEvt)
+# define RTTraceLogWrAddEvtDesc RT_MANGLER(RTTraceLogWrAddEvtDesc)
+# define RTTraceLogWrCreate RT_MANGLER(RTTraceLogWrCreate)
+# define RTTraceLogWrCreateFile RT_MANGLER(RTTraceLogWrCreateFile)
+# define RTTraceLogWrCreateTcpClient RT_MANGLER(RTTraceLogWrCreateTcpClient)
+# define RTTraceLogWrCreateTcpServer RT_MANGLER(RTTraceLogWrCreateTcpServer)
+# define RTTraceLogWrDestroy RT_MANGLER(RTTraceLogWrDestroy)
+# define RTTraceLogWrEvtAdd RT_MANGLER(RTTraceLogWrEvtAdd)
+# define RTTraceLogWrEvtAddL RT_MANGLER(RTTraceLogWrEvtAddL)
+# define RTTraceLogWrEvtAddLV RT_MANGLER(RTTraceLogWrEvtAddLV)
+# define RTTraceLogWrEvtAddSg RT_MANGLER(RTTraceLogWrEvtAddSg)
+# define RTTraceSetDefaultBuf RT_MANGLER(RTTraceSetDefaultBuf)
+# define RTUdpCreateClientSocket RT_MANGLER(RTUdpCreateClientSocket)
+# define RTUdpCreateServerSocket RT_MANGLER(RTUdpCreateServerSocket)
+# 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 RTUtf16BigCalcUtf8Len RT_MANGLER(RTUtf16BigCalcUtf8Len)
+# define RTUtf16BigCalcUtf8LenEx RT_MANGLER(RTUtf16BigCalcUtf8LenEx)
+# define RTUtf16LittleCalcUtf8Len RT_MANGLER(RTUtf16LittleCalcUtf8Len)
+# define RTUtf16LittleCalcUtf8LenEx RT_MANGLER(RTUtf16LittleCalcUtf8LenEx)
+# 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 RTUtf16GetCpNExInternal RT_MANGLER(RTUtf16GetCpNExInternal)
+# define RTUtf16BigGetCpExInternal RT_MANGLER(RTUtf16BigGetCpExInternal)
+# define RTUtf16GetCpInternal RT_MANGLER(RTUtf16GetCpInternal)
+# define RTUtf16BigGetCpInternal RT_MANGLER(RTUtf16BigGetCpInternal)
+# define RTUtf16NCmp RT_MANGLER(RTUtf16NCmp)
+# define RTUtf16NCmpAscii RT_MANGLER(RTUtf16NCmpAscii)
+# define RTUtf16NCmpUtf8 RT_MANGLER(RTUtf16NCmpUtf8)
+# define RTUtf16ICmp RT_MANGLER(RTUtf16ICmp)
+# define RTUtf16BigICmp RT_MANGLER(RTUtf16BigICmp)
+# define RTUtf16ICmpUtf8 RT_MANGLER(RTUtf16ICmpUtf8)
+# define RTUtf16NICmp RT_MANGLER(RTUtf16NICmp)
+# define RTUtf16BigNICmp RT_MANGLER(RTUtf16BigNICmp)
+# define RTUtf16FindAscii RT_MANGLER(RTUtf16FindAscii)
+# define RTUtf16IsValidEncoding RT_MANGLER(RTUtf16IsValidEncoding)
+# define RTUtf16Len RT_MANGLER(RTUtf16Len)
+# define RTUtf16LocaleICmp RT_MANGLER(RTUtf16LocaleICmp)
+# define RTUtf16PutCpInternal RT_MANGLER(RTUtf16PutCpInternal)
+# define RTUtf16BigPutCpInternal RT_MANGLER(RTUtf16BigPutCpInternal)
+# 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 RTUtf16BigToUtf8ExTag RT_MANGLER(RTUtf16BigToUtf8ExTag)
+# define RTUtf16LittleToUtf8ExTag RT_MANGLER(RTUtf16LittleToUtf8ExTag)
+# define RTUtf16ToUtf8Tag RT_MANGLER(RTUtf16ToUtf8Tag)
+# define RTUtf16BigToUtf8Tag RT_MANGLER(RTUtf16BigToUtf8Tag)
+# define RTUtf16LittleToUtf8Tag RT_MANGLER(RTUtf16LittleToUtf8Tag)
+# define RTUtf16ValidateEncoding RT_MANGLER(RTUtf16ValidateEncoding)
+# define RTUtf16ValidateEncodingEx RT_MANGLER(RTUtf16ValidateEncodingEx)
+# define RTUtf16Printf RT_MANGLER(RTUtf16Printf)
+# define RTUtf16PrintfV RT_MANGLER(RTUtf16PrintfV)
+# define RTUtf16PrintfEx RT_MANGLER(RTUtf16PrintfEx)
+# define RTUtf16PrintfExV RT_MANGLER(RTUtf16PrintfExV)
+# 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 RTVfsChainMsgError RT_MANGLER(RTVfsChainMsgError)
+# define RTVfsChainMsgErrorExitFailure RT_MANGLER(RTVfsChainMsgErrorExitFailure)
+# define RTVfsChainOpenObj RT_MANGLER(RTVfsChainOpenObj)
+# define RTVfsChainOpenDir RT_MANGLER(RTVfsChainOpenDir)
+# define RTVfsChainOpenParentDir RT_MANGLER(RTVfsChainOpenParentDir)
+# define RTVfsChainOpenFile RT_MANGLER(RTVfsChainOpenFile)
+# define RTVfsChainOpenIoStream RT_MANGLER(RTVfsChainOpenIoStream)
+# define RTVfsChainQueryFinalPath RT_MANGLER(RTVfsChainQueryFinalPath)
+# define RTVfsChainQueryInfo RT_MANGLER(RTVfsChainQueryInfo)
+# define RTVfsChainSpecCheckAndSetup RT_MANGLER(RTVfsChainSpecCheckAndSetup)
+# define RTVfsChainSpecFree RT_MANGLER(RTVfsChainSpecFree)
+# define RTVfsChainSpecParse RT_MANGLER(RTVfsChainSpecParse)
+# define RTVfsChainSplitOffFinalPath RT_MANGLER(RTVfsChainSplitOffFinalPath)
+# define RTVfsChainValidateOpenFileOrIoStream RT_MANGLER(RTVfsChainValidateOpenFileOrIoStream)
+# define RTVfsDirRelease RT_MANGLER(RTVfsDirRelease)
+# define RTVfsDirRetain RT_MANGLER(RTVfsDirRetain)
+# define RTVfsDirRetainDebug RT_MANGLER(RTVfsDirRetainDebug)
+# define RTVfsDirOpen RT_MANGLER(RTVfsDirOpen)
+# define RTVfsDirOpenDir RT_MANGLER(RTVfsDirOpenDir)
+# define RTVfsDirCreateDir RT_MANGLER(RTVfsDirCreateDir)
+# define RTVfsDirOpenFile RT_MANGLER(RTVfsDirOpenFile)
+# define RTVfsDirOpenFileAsIoStream RT_MANGLER(RTVfsDirOpenFileAsIoStream)
+# define RTVfsDirOpenObj RT_MANGLER(RTVfsDirOpenObj)
+# define RTVfsDirQueryPathInfo RT_MANGLER(RTVfsDirQueryPathInfo)
+# define RTVfsDirReadEx RT_MANGLER(RTVfsDirReadEx)
+# define RTVfsDirRemoveDir RT_MANGLER(RTVfsDirRemoveDir)
+# define RTVfsDirRewind RT_MANGLER(RTVfsDirRewind)
+# define RTVfsDirSetPathMode RT_MANGLER(RTVfsDirSetPathMode)
+# define RTVfsDirToPrivate RT_MANGLER(RTVfsDirToPrivate)
+# define RTVfsFileFlush RT_MANGLER(RTVfsFileFlush)
+# define RTVfsFileFromBuffer RT_MANGLER(RTVfsFileFromBuffer)
+# define RTVfsFileFromRTFile RT_MANGLER(RTVfsFileFromRTFile)
+# define RTVfsFileGetOpenFlags RT_MANGLER(RTVfsFileGetOpenFlags)
+# define RTVfsFileQuerySize RT_MANGLER(RTVfsFileQuerySize)
+# define RTVfsFileGetMaxSize RT_MANGLER(RTVfsFileGetMaxSize)
+# define RTVfsFileOpen RT_MANGLER(RTVfsFileOpen)
+# define RTVfsFileOpenNormal RT_MANGLER(RTVfsFileOpenNormal)
+# define RTVfsFilePoll RT_MANGLER(RTVfsFilePoll)
+# define RTVfsFilePrintf RT_MANGLER(RTVfsFilePrintf)
+# define RTVfsFilePrintfV RT_MANGLER(RTVfsFilePrintfV)
+# define RTVfsFileQueryInfo RT_MANGLER(RTVfsFileQueryInfo)
+# define RTVfsFileQueryMaxSize RT_MANGLER(RTVfsFileQueryMaxSize)
+# define RTVfsFileRead RT_MANGLER(RTVfsFileRead)
+# define RTVfsFileReadAt RT_MANGLER(RTVfsFileReadAt)
+# define RTVfsFileRelease RT_MANGLER(RTVfsFileRelease)
+# define RTVfsFileRetain RT_MANGLER(RTVfsFileRetain)
+# define RTVfsFileRetainDebug RT_MANGLER(RTVfsFileRetainDebug)
+# define RTVfsFileSeek RT_MANGLER(RTVfsFileSeek)
+# define RTVfsFileSetSize RT_MANGLER(RTVfsFileSetSize)
+# define RTVfsFileSgRead RT_MANGLER(RTVfsFileSgRead)
+# define RTVfsFileSgWrite RT_MANGLER(RTVfsFileSgWrite)
+# define RTVfsFileTell RT_MANGLER(RTVfsFileTell)
+# define RTVfsFileToIoStream RT_MANGLER(RTVfsFileToIoStream)
+# define RTVfsFileWrite RT_MANGLER(RTVfsFileWrite)
+# define RTVfsFileWriteAt RT_MANGLER(RTVfsFileWriteAt)
+# define RTVfsFsStreamToPrivate RT_MANGLER(RTVfsFsStreamToPrivate)
+# define RTVfsFsStrmAdd RT_MANGLER(RTVfsFsStrmAdd)
+# define RTVfsFsStrmEnd RT_MANGLER(RTVfsFsStrmEnd)
+# define RTVfsFsStrmNext RT_MANGLER(RTVfsFsStrmNext)
+# define RTVfsFsStrmPushFile RT_MANGLER(RTVfsFsStrmPushFile)
+# define RTVfsFsStrmQueryInfo RT_MANGLER(RTVfsFsStrmQueryInfo)
+# define RTVfsFsStrmRelease RT_MANGLER(RTVfsFsStrmRelease)
+# define RTVfsFsStrmRetain RT_MANGLER(RTVfsFsStrmRetain)
+# define RTVfsFsStrmRetainDebug RT_MANGLER(RTVfsFsStrmRetainDebug)
+# define RTVfsFsStrmToDir RT_MANGLER(RTVfsFsStrmToDir)
+# define RTVfsFsStrmToNormalDir RT_MANGLER(RTVfsFsStrmToNormalDir)
+# define RTVfsFsStrmToDirUndo RT_MANGLER(RTVfsFsStrmToDirUndo)
+# 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 RTVfsIoStrmGetOpenFlags RT_MANGLER(RTVfsIoStrmGetOpenFlags)
+# define RTVfsIoStrmIsAtEnd RT_MANGLER(RTVfsIoStrmIsAtEnd)
+# define RTVfsIoStrmOpenNormal RT_MANGLER(RTVfsIoStrmOpenNormal)
+# define RTVfsIoStrmPoll RT_MANGLER(RTVfsIoStrmPoll)
+# define RTVfsIoStrmPrintf RT_MANGLER(RTVfsIoStrmPrintf)
+# define RTVfsIoStrmPrintfV RT_MANGLER(RTVfsIoStrmPrintfV)
+# 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 RTVfsIoStrmRetainDebug RT_MANGLER(RTVfsIoStrmRetainDebug)
+# define RTVfsIoStrmSgRead RT_MANGLER(RTVfsIoStrmSgRead)
+# define RTVfsIoStrmSgWrite RT_MANGLER(RTVfsIoStrmSgWrite)
+# define RTVfsIoStrmSkip RT_MANGLER(RTVfsIoStrmSkip)
+# define RTVfsIoStrmStrOutputCallback RT_MANGLER(RTVfsIoStrmStrOutputCallback)
+# 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 RTVfsQueryLabel RT_MANGLER(RTVfsQueryLabel)
+# define RTVfsQueryRangeState RT_MANGLER(RTVfsQueryRangeState)
+# 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 RTVfsLockRetainDebug RT_MANGLER(RTVfsLockRetainDebug)
+# define RTVfsMemFileCreate RT_MANGLER(RTVfsMemFileCreate)
+# define RTVfsMemIoStrmCreate RT_MANGLER(RTVfsMemIoStrmCreate)
+# define RTVfsMemorizeIoStreamAsFile RT_MANGLER(RTVfsMemorizeIoStreamAsFile)
+# define RTVfsNew RT_MANGLER(RTVfsNew)
+# define RTVfsNewBaseObj RT_MANGLER(RTVfsNewBaseObj)
+# define RTVfsNewDir RT_MANGLER(RTVfsNewDir)
+# 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 RTVfsObjGetType RT_MANGLER(RTVfsObjGetType)
+# define RTVfsObjOpen RT_MANGLER(RTVfsObjOpen)
+# define RTVfsObjQueryInfo RT_MANGLER(RTVfsObjQueryInfo)
+# define RTVfsObjRelease RT_MANGLER(RTVfsObjRelease)
+# define RTVfsObjRetain RT_MANGLER(RTVfsObjRetain)
+# define RTVfsObjRetainDebug RT_MANGLER(RTVfsObjRetainDebug)
+# define RTVfsObjSetMode RT_MANGLER(RTVfsObjSetMode)
+# define RTVfsObjSetOwner RT_MANGLER(RTVfsObjSetOwner)
+# define RTVfsObjSetTimes RT_MANGLER(RTVfsObjSetTimes)
+# define RTVfsObjToDir RT_MANGLER(RTVfsObjToDir)
+# define RTVfsObjToFile RT_MANGLER(RTVfsObjToFile)
+# define RTVfsObjToFsStream RT_MANGLER(RTVfsObjToFsStream)
+# define RTVfsObjToIoStream RT_MANGLER(RTVfsObjToIoStream)
+# define RTVfsObjToPrivate RT_MANGLER(RTVfsObjToPrivate)
+# 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 RTVfsOpenRoot RT_MANGLER(RTVfsOpenRoot)
+# define RTVfsQuerPathInfo RT_MANGLER(RTVfsQueryPathInfo)
+# define RTVfsMountVol RT_MANGLER(RTVfsMountVol)
+# define RTVfsRetain RT_MANGLER(RTVfsRetain)
+# define RTVfsRetainDebug RT_MANGLER(RTVfsRetainDebug)
+# define RTVfsSymlinkQueryInfo RT_MANGLER(RTVfsSymlinkQueryInfo)
+# define RTVfsSymlinkRead RT_MANGLER(RTVfsSymlinkRead)
+# define RTVfsSymlinkRelease RT_MANGLER(RTVfsSymlinkRelease)
+# define RTVfsSymlinkRetain RT_MANGLER(RTVfsSymlinkRetain)
+# define RTVfsSymlinkRetainDebug RT_MANGLER(RTVfsSymlinkRetainDebug)
+# define RTVfsSymlinkSetMode RT_MANGLER(RTVfsSymlinkSetMode)
+# define RTVfsSymlinkSetOwner RT_MANGLER(RTVfsSymlinkSetOwner)
+# define RTVfsSymlinkSetTimes RT_MANGLER(RTVfsSymlinkSetTimes)
+# define RTVfsSymlinkToPrivate RT_MANGLER(RTVfsSymlinkToPrivate)
+# define RTVfsTypeName RT_MANGLER(RTVfsTypeName)
+# define RTVfsUtilDummyPollOne RT_MANGLER(RTVfsUtilDummyPollOne)
+# define RTVfsUtilPumpIoStreams RT_MANGLER(RTVfsUtilPumpIoStreams)
+# define RTVfsCreateProgressForFile RT_MANGLER(RTVfsCreateProgressForFile)
+# define RTVfsCreateProgressForIoStream RT_MANGLER(RTVfsCreateProgressForIoStream)
+# 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 RTZipGzipCmd RT_MANGLER(RTZipGzipCmd)
+# 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 RTZipTarFsStreamToIoStream RT_MANGLER(RTZipTarFsStreamToIoStream)
+# define RTZipTarFsStreamSetOwner RT_MANGLER(RTZipTarFsStreamSetOwner)
+# define RTZipTarFsStreamSetGroup RT_MANGLER(RTZipTarFsStreamSetGroup)
+# define RTZipTarFsStreamSetPrefix RT_MANGLER(RTZipTarFsStreamSetPrefix)
+# define RTZipTarFsStreamSetFileMode RT_MANGLER(RTZipTarFsStreamSetFileMode)
+# define RTZipTarFsStreamSetDirMode RT_MANGLER(RTZipTarFsStreamSetDirMode)
+# define RTZipTarFsStreamSetModTime RT_MANGLER(RTZipTarFsStreamSetModTime)
+# define RTZipTarFsStreamTruncate RT_MANGLER(RTZipTarFsStreamTruncate)
+# define RTZipXarFsStreamFromIoStream RT_MANGLER(RTZipXarFsStreamFromIoStream)
+# define RTZipTarFsStreamForFile RT_MANGLER(RTZipTarFsStreamForFile)
+# define RTZipCpioFsStreamFromIoStream RT_MANGLER(RTZipCpioFsStreamFromIoStream)
+
+/* 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 RTAsn1CursorCheckOctStrEnd RT_MANGLER(RTAsn1CursorCheckOctStrEnd)
+# define RTAsn1CursorCheckSeqEnd RT_MANGLER(RTAsn1CursorCheckSeqEnd)
+# define RTAsn1CursorCheckSetEnd RT_MANGLER(RTAsn1CursorCheckSetEnd)
+# 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 RTAsn1CursorInitSub RT_MANGLER(RTAsn1CursorInitSub)
+# define RTAsn1CursorInitSubFromCore RT_MANGLER(RTAsn1CursorInitSubFromCore)
+# define RTAsn1CursorIsNextEx RT_MANGLER(RTAsn1CursorIsNextEx)
+# define RTAsn1CursorIsEnd RT_MANGLER(RTAsn1CursorIsEnd)
+# 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 RTAsn1EncodeQueryRawBits RT_MANGLER(RTAsn1EncodeQueryRawBits)
+# 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 RTAsn1BitString_InitWithData RT_MANGLER(RTAsn1BitString_InitWithData)
+# define RTAsn1BitString_AreContentBitsValid RT_MANGLER(RTAsn1BitString_AreContentBitsValid)
+# define RTAsn1BitString_RefreshContent RT_MANGLER(RTAsn1BitString_RefreshContent)
+# 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_SetToNull RT_MANGLER(RTAsn1DynType_SetToNull)
+# 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_SetFromString RT_MANGLER(RTAsn1ObjId_SetFromString)
+# 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_AllocContent RT_MANGLER(RTAsn1OctetString_AllocContent)
+# define RTAsn1OctetString_SetContent RT_MANGLER(RTAsn1OctetString_SetContent)
+# 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 RTAsn1OctetString_AreContentBytesValid RT_MANGLER(RTAsn1OctetString_AreContentBytesValid)
+# define RTAsn1OctetString_RefreshContent RT_MANGLER(RTAsn1OctetString_RefreshContent)
+# 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_CompareValues RT_MANGLER(RTAsn1String_CompareValues)
+# 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 RTAsn1Time_InitEx RT_MANGLER(RTAsn1Time_InitEx)
+# define RTAsn1Time_InitWithTime RT_MANGLER(RTAsn1Time_InitWithTime)
+# define RTAsn1Time_SetTime RT_MANGLER(RTAsn1Time_SetTime)
+# define RTAsn1Time_SetTimeSpec RT_MANGLER(RTAsn1Time_SetTimeSpec)
+# 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 RTCrCipherDecrypt RT_MANGLER(RTCrCipherDecrypt)
+# define RTCrCipherEncrypt RT_MANGLER(RTCrCipherEncrypt)
+# define RTCrCipherGetBlockSize RT_MANGLER(RTCrCipherGetBlockSize)
+# define RTCrCipherGetInitializationVectorLength RT_MANGLER(RTCrCipherGetInitializationVectorLength)
+# define RTCrCipherGetKeyLength RT_MANGLER(RTCrCipherGetKeyLength)
+# define RTCrCipherOpenByType RT_MANGLER(RTCrCipherOpenByType)
+# define RTCrCipherRetain RT_MANGLER(RTCrCipherRetain)
+# define RTCrCipherRelease RT_MANGLER(RTCrCipherRelease)
+# define RTCrCipherCtxFree RT_MANGLER(RTCrCipherCtxFree)
+# define RTCrCipherCtxDecryptInit RT_MANGLER(RTCrCipherCtxDecryptInit)
+# define RTCrCipherCtxDecryptFinish RT_MANGLER(RTCrCipherCtxDecryptFinish)
+# define RTCrCipherCtxDecryptProcess RT_MANGLER(RTCrCipherCtxDecryptProcess)
+# define RTCrCipherCtxEncryptInit RT_MANLGER(RTCrCipherCtxEncryptInit)
+# define RTCrCipherCtxEncryptFinish RT_MANGLER(RTCrCipherCtxEncryptFinish)
+# define RTCrCipherCtxEncryptProcess RT_MANGLER(RTCrCipherCtxEncryptProcess)
+# define RTCrCipherDecrypt RT_MANGLER(RTCrCipherDecrypt)
+# define RTCrCipherDecryptEx RT_MANGLER(RTCrCipherDecryptEx)
+# define RTCrCipherEncrypt RT_MANGLER(RTCrCipherEncrypt)
+# define RTCrCipherEncryptEx RT_MANGLER(RTCrCipherEncryptEx)
+# define RTCrDigestClone RT_MANGLER(RTCrDigestClone)
+# define RTCrDigestCreate RT_MANGLER(RTCrDigestCreate)
+# define RTCrDigestFinal RT_MANGLER(RTCrDigestFinal)
+# define RTCrDigestGetConsumedSize RT_MANGLER(RTCrDigestGetConsumedSize)
+# define RTCrDigestGetFlags RT_MANGLER(RTCrDigestGetFlags)
+# 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 RTCrKeyCreateFromBuffer RT_MANGLER(RTCrKeyCreateFromBuffer)
+# define RTCrKeyCreateFromFile RT_MANGLER(RTCrKeyCreateFromFile)
+# define RTCrKeyCreateFromPemSection RT_MANGLER(RTCrKeyCreateFromPemSection)
+# define RTCrKeyCreateFromPublicAlgorithmAndBits RT_MANGLER(RTCrKeyCreateFromPublicAlgorithmAndBits)
+# define RTCrKeyCreateFromSubjectPublicKeyInfo RT_MANGLER(RTCrKeyCreateFromSubjectPublicKeyInfo)
+# define RTCrKeyCreateNewRsa RT_MANGLER(RTCrKeyCreateNewRsa)
+# define RTCrKeyGetBitCount RT_MANGLER(RTCrKeyGetBitCount)
+# define RTCrKeyGetType RT_MANGLER(RTCrKeyGetType)
+# define RTCrKeyHasPrivatePart RT_MANGLER(RTCrKeyHasPrivatePart)
+# define RTCrKeyHasPublicPart RT_MANGLER(RTCrKeyHasPublicPart)
+# define RTCrKeyRelease RT_MANGLER(RTCrKeyRelease)
+# define RTCrKeyRetain RT_MANGLER(RTCrKeyRetain)
+# define RTCrKeyQueryRsaModulus RT_MANGLER(RTCrKeyQueryRsaModulus)
+# define RTCrKeyQueryRsaPrivateExponent RT_MANGLER(RTCrKeyQueryRsaPrivateExponent)
+# define RTCrRc4 RT_MANGLER(RTCrRc4)
+# define RTCrRc4SetKey RT_MANGLER(RTCrRc4SetKey)
+# 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 RTCrRsaPrivateKey_CanHandleDigestType RT_MANGLER(RTCrRsaPrivateKey_CanHandleDigestType)
+# define RTCrRsaPublicKey_CheckSanity RT_MANGLER(RTCrRsaPublicKey_CheckSanity)
+# define RTCrRsaPublicKey_CanHandleDigestType RT_MANGLER(RTCrRsaPublicKey_CanHandleDigestType)
+# define RTCrPemFindFirstSectionInContent RT_MANGLER(RTCrPemFindFirstSectionInContent)
+# define RTCrPemFreeSections RT_MANGLER(RTCrPemFreeSections)
+# define RTCrPemParseContent RT_MANGLER(RTCrPemParseContent)
+# define RTCrPemReadFile RT_MANGLER(RTCrPemReadFile)
+# define RTCrPemWriteBlob RT_MANGLER(RTCrPemWriteBlob)
+# define RTCrPemWriteBlobToVfsIoStrm RT_MANGLER(RTCrPemWriteBlobToVfsIoStrm)
+# define RTCrPemWriteBlobToVfsFile RT_MANGLER(RTCrPemWriteBlobToVfsFile)
+# define RTCrPemWriteAsn1 RT_MANGLER(RTCrPemWriteAsn1)
+# define RTCrPemWriteAsn1ToVfsIoStrm RT_MANGLER(RTCrPemWriteAsn1ToVfsIoStrm)
+# define RTCrPemWriteAsn1ToVfsFile RT_MANGLER(RTCrPemWriteAsn1ToVfsFile)
+# define RTCrPkcs5Pbkdf2Hmac RT_MANGLER(RTCrPkcs5Pbkdf2Hmac)
+# define RTCrPkcs7_ReadFromBuffer RT_MANGLER(RTCrPkcs7_ReadFromBuffer)
+# define RTCrPkcs7Attribute_SetAppleMultiCdPlist RT_MANGLER(RTCrPkcs7Attribute_SetAppleMultiCdPlist)
+# define RTCrPkcs7Attribute_SetContentType RT_MANGLER(RTCrPkcs7Attribute_SetContentType)
+# define RTCrPkcs7Attribute_SetCounterSignatures RT_MANGLER(RTCrPkcs7Attribute_SetCounterSignatures)
+# define RTCrPkcs7Attribute_SetMessageDigest RT_MANGLER(RTCrPkcs7Attribute_SetMessageDigest)
+# define RTCrPkcs7Attribute_SetMsStatementType RT_MANGLER(RTCrPkcs7Attribute_SetMsStatementType)
+# define RTCrPkcs7Attribute_SetMsNestedSignature RT_MANGLER(RTCrPkcs7Attribute_SetMsNestedSignature)
+# define RTCrPkcs7Attribute_SetMsTimestamp RT_MANGLER(RTCrPkcs7Attribute_SetMsTimestamp)
+# define RTCrPkcs7Attribute_SetSigningTime RT_MANGLER(RTCrPkcs7Attribute_SetSigningTime)
+# define RTCrPkcs7Attributes_HashAttributes RT_MANGLER(RTCrPkcs7Attributes_HashAttributes)
+# 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_SetCertificates RT_MANGLER(RTCrPkcs7SignedData_SetCertificates)
+# define RTCrPkcs7SignedData_SetCrls RT_MANGLER(RTCrPkcs7SignedData_SetCrls)
+# define RTCrPkcs7SignedData_DecodeAsn1 RT_MANGLER(RTCrPkcs7SignedData_DecodeAsn1)
+# define RTCrPkcs7SignerInfo_SetAuthenticatedAttributes RT_MANGLER(RTCrPkcs7SignerInfo_SetAuthenticatedAttributes)
+# define RTCrPkcs7SignerInfo_SetUnauthenticatedAttributes RT_MANGLER(RTCrPkcs7SignerInfo_SetUnauthenticatedAttributes)
+# 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 RTCrPkcs7SimpleSignSignedData RT_MANGLER(RTCrPkcs7SimpleSignSignedData)
+# define RTCrPkcs7VerifyCertCallbackCodeSigning RT_MANGLER(RTCrPkcs7VerifyCertCallbackCodeSigning)
+# define RTCrPkcs7VerifyCertCallbackDefault RT_MANGLER(RTCrPkcs7VerifyCertCallbackDefault)
+# define RTCrPkcs7VerifySignedData RT_MANGLER(RTCrPkcs7VerifySignedData)
+# define RTCrPkcs7VerifySignedDataWithExternalData RT_MANGLER(RTCrPkcs7VerifySignedDataWithExternalData)
+# define RTCrPkcs7Cert_SetX509Cert RT_MANGLER(RTCrPkcs7Cert_SetX509Cert)
+# define RTCrPkcs7Cert_SetExtendedCert RT_MANGLER(RTCrPkcs7Cert_SetExtendedCert)
+# define RTCrPkcs7Cert_SetAcV1 RT_MANGLER(RTCrPkcs7Cert_SetAcV1)
+# define RTCrPkcs7Cert_SetAcV2 RT_MANGLER(RTCrPkcs7Cert_SetAcV2)
+# define RTCrPkcs7Cert_SetOtherCert RT_MANGLER(RTCrPkcs7Cert_SetOtherCert)
+# 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 RTCrPkixSignatureFindByObjId RT_MANGLER(RTCrPkixSignatureFindByObjId)
+# define RTCrPkixSignatureFindByObjIdString RT_MANGLER(RTCrPkixSignatureFindByObjIdString)
+# 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 RTCrPkixPubKeySignDigest RT_MANGLER(RTCrPkixPubKeySignDigest)
+# define RTCrPkixPubKeyVerifySignature RT_MANGLER(RTCrPkixPubKeyVerifySignature)
+# define RTCrPkixPubKeyVerifySignedDigest RT_MANGLER(RTCrPkixPubKeyVerifySignedDigest)
+# define RTCrPkixPubKeyVerifySignedDigestByCertPubKeyInfo RT_MANGLER(RTCrPkixPubKeyVerifySignedDigestByCertPubKeyInfo)
+# define RTCrPkixPubKeyCanHandleDigestType RT_MANGLER(RTCrPkixPubKeyCanHandleDigestType)
+# define RTCrPkixCanCertHandleDigestType RT_MANGLER(RTCrPkixCanCertHandleDigestType)
+# define RTCrRandBytes RT_MANGLER(RTCrRandBytes)
+# define RTCrSpcAttributeTypeAndOptionalValue_SetPeImage RT_MANGLER(RTCrSpcAttributeTypeAndOptionalValue_SetPeImage)
+# define RTCrSpcAttributeTypeAndOptionalValue_DecodeAsn1 RT_MANGLER(RTCrSpcAttributeTypeAndOptionalValue_DecodeAsn1)
+# define RTCrSpcIndirectDataContent_DecodeAsn1 RT_MANGLER(RTCrSpcIndirectDataContent_DecodeAsn1)
+# define RTCrSpcLink_DecodeAsn1 RT_MANGLER(RTCrSpcLink_DecodeAsn1)
+# define RTCrSpcPeImageData_SetFile RT_MANGLER(RTCrSpcPeImageData_SetFile)
+# define RTCrSpcPeImageData_SetFlags RT_MANGLER(RTCrSpcPeImageData_SetFlags)
+# define RTCrSpcPeImageData_DecodeAsn1 RT_MANGLER(RTCrSpcPeImageData_DecodeAsn1)
+# define RTCrSpcSerializedObjectAttribute_SetV1Hashes RT_MANGLER(RTCrSpcSerializedObjectAttribute_SetV1Hashes)
+# define RTCrSpcSerializedObjectAttribute_SetV2Hashes RT_MANGLER(RTCrSpcSerializedObjectAttribute_SetV2Hashes)
+# 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_SetFile RT_MANGLER(RTCrSpcLink_SetFile)
+# define RTCrSpcLink_SetMoniker RT_MANGLER(RTCrSpcLink_SetMoniker)
+# define RTCrSpcLink_SetUrl RT_MANGLER(RTCrSpcLink_SetUrl)
+# 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 RTCrSpcString_SetAscii RT_MANGLER(RTCrSpcString_SetAscii)
+# define RTCrSpcString_SetUcs2 RT_MANGLER(RTCrSpcString_SetUcs2)
+# 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 RTCrSslCreate RT_MANGLER(RTCrSslCreate)
+# define RTCrSslCreateSessionForNativeSocket RT_MANGLER(RTCrSslCreateSessionForNativeSocket)
+# define RTCrSslLoadTrustedRootCerts RT_MANGLER(RTCrSslLoadTrustedRootCerts)
+# define RTCrSslRelease RT_MANGLER(RTCrSslRelease)
+# define RTCrSslRetain RT_MANGLER(RTCrSslRetain)
+# define RTCrSslSessionAccept RT_MANGLER(RTCrSslSessionAccept)
+# define RTCrSslSessionConnect RT_MANGLER(RTCrSslSessionConnect)
+# define RTCrSslSessionGetCertIssuerNameAsString RT_MANGLER(RTCrSslSessionGetCertIssuerNameAsString)
+# define RTCrSslSessionGetVersion RT_MANGLER(RTCrSslSessionGetVersion)
+# define RTCrSslSessionPending RT_MANGLER(RTCrSslSessionPending)
+# define RTCrSslSessionRead RT_MANGLER(RTCrSslSessionRead)
+# define RTCrSslSessionRelease RT_MANGLER(RTCrSslSessionRelease)
+# define RTCrSslSessionRetain RT_MANGLER(RTCrSslSessionRetain)
+# define RTCrSslSessionWrite RT_MANGLER(RTCrSslSessionWrite)
+# define RTCrSslSetCertificateFile RT_MANGLER(RTCrSslSetCertificateFile)
+# define RTCrSslSetNoPeerVerify RT_MANGLER(RTCrSslSetNoPeerVerify)
+# define RTCrSslSetPrivateKeyFile RT_MANGLER(RTCrSslSetPrivateKeyFile)
+# 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 RTCrX509CertPathsSetTrustAnchorChecks RT_MANGLER(RTCrX509CertPathsSetTrustAnchorChecks)
+# 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 RTCrRsaPrivateKey_ReadFromFile RT_MANGLER(RTCrRsaPrivateKey_ReadFromFile)
+# define RTCrRsaPrivateKey_ReadFromBuffer RT_MANGLER(RTCrRsaPrivateKey_ReadFromBuffer)
+# define RTCrRsaPublicKey_ReadFromFile RT_MANGLER(RTCrRsaPublicKey_ReadFromFile)
+# define RTCrRsaPublicKey_ReadFromBuffer RT_MANGLER(RTCrRsaPublicKey_ReadFromBuffer)
+# 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 RTCrStoreCertAddX509 RT_MANGLER(RTCrStoreCertAddX509)
+# 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 RTCrStoreCreateInMemEx RT_MANGLER(RTCrStoreCreateInMemEx)
+# 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 RTExprEvalCreate RT_MANGLER(RTExprEvalCreate)
+# define RTExprEvalRelease RT_MANGLER(RTExprEvalRelease)
+# define RTExprEvalRetain RT_MANGLER(RTExprEvalRetain)
+# define RTExprEvalToBool RT_MANGLER(RTExprEvalToBool)
+# define RTExprEvalToInteger RT_MANGLER(RTExprEvalToInteger)
+# define RTExprEvalToString RT_MANGLER(RTExprEvalToString)
+# 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 RTUInt128MulByU64Ex RT_MANGLER(RTUInt128MulByU64Ex)
+# define RTUInt128MulByU64Ex_EndProc RT_MANGLER(RTUInt128MulByU64Ex_EndProc)
+# define RTUtf16Copy RT_MANGLER(RTUtf16Copy)
+# define RTUtf16CopyAscii RT_MANGLER(RTUtf16CopyAscii)
+# define RTUtf16CopyEx RT_MANGLER(RTUtf16CopyEx)
+# define RTUtf16Cat RT_MANGLER(RTUtf16Cat)
+# define RTUtf16CatAscii RT_MANGLER(RTUtf16CatAscii)
+# define RTUtf16Chr RT_MANGLER(RTUtf16Chr)
+# 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 RTMemSaferGetSize RT_MANGLER(RTMemSaferGetSize)
+# 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_pfnRTLogAssert RT_MANGLER(g_pfnRTLogAssert)
+# define g_pfnRTLogAssertV RT_MANGLER(g_pfnRTLogAssertV)
+# define g_pfnRTLogGetDefaultInstance RT_MANGLER(g_pfnRTLogGetDefaultInstance)
+# define g_pfnRTLogGetDefaultInstanceEx RT_MANGLER(g_pfnRTLogGetDefaultInstanceEx)
+# define g_pfnRTLogLoggerExV RT_MANGLER(g_pfnRTLogLoggerExV)
+# define g_pfnRTLogRelGetDefaultInstance RT_MANGLER(g_pfnRTLogRelGetDefaultInstance)
+# define g_pfnRTLogRelGetDefaultInstanceEx RT_MANGLER(g_pfnRTLogRelGetDefaultInstanceEx)
+# 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_RTAsn1SaferAllocator RT_MANGLER(g_RTAsn1SaferAllocator)
+# define g_aRTCrPkcs7Markers RT_MANGLER(g_aRTCrPkcs7Markers)
+# define g_cRTCrPkcs7Markers RT_MANGLER(g_cRTCrPkcs7Markers)
+# define g_aRTCrX509CertificateMarkers RT_MANGLER(g_aRTCrX509CertificateMarkers)
+# define g_cRTCrX509CertificateMarkers RT_MANGLER(g_cRTCrX509CertificateMarkers)
+# define g_aRTCrKeyPublicMarkers RT_MANGLER(g_aRTCrKeyPublicMarkers)
+# define g_cRTCrKeyPublicMarkers RT_MANGLER(g_cRTCrKeyPublicMarkers)
+# define g_aRTCrKeyPrivateMarkers RT_MANGLER(g_aRTCrKeyPrivateMarkers)
+# define g_cRTCrKeyPrivateMarkers RT_MANGLER(g_cRTCrKeyPrivateMarkers)
+# define g_aRTCrKeyAllMarkers RT_MANGLER(g_aRTCrKeyAllMarkers)
+# define g_cRTCrKeyAllMarkers RT_MANGLER(g_cRTCrKeyAllMarkers)
+# define g_acRTThreadTypeStats RT_MANGLER(g_acRTThreadTypeStats) /* internal */
+# define g_RTIoQueueStdFileProv RT_MANGLER(g_RTIoQueueStdFileProv) /* internal */
+# define g_RTIoQueueAioFileProv RT_MANGLER(g_RTIoQueueAioFileProv) /* internal */
+# define g_RTIoQueueLnxIoURingProv RT_MANGLER(g_RTIoQueueLnxIoURingProv) /* internal */
+
+#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 /* !IPRT_INCLUDED_mangling_h */
+
diff --git a/include/iprt/manifest.h b/include/iprt/manifest.h
new file mode 100644
index 00000000..ececd07f
--- /dev/null
+++ b/include/iprt/manifest.h
@@ -0,0 +1,560 @@
+/** @file
+ * IPRT - Manifest file handling.
+ */
+
+/*
+ * Copyright (C) 2009-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_manifest_h
+#define IPRT_INCLUDED_manifest_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_manifest RTManifest - Manifest file creation and checking
+ * @ingroup grp_rt
+ * @{
+ */
+
+/** @name Manifest attribute types.
+ * The types can be ORed together to form a set.
+ * @{ */
+/** For use with other attributes. Representation unknown. */
+#define RTMANIFEST_ATTR_UNKNOWN 0
+/** The size of the content. Represented as a decimal number. */
+#define RTMANIFEST_ATTR_SIZE RT_BIT_32(0)
+/** The MD5 of the content. Represented as a hex string. */
+#define RTMANIFEST_ATTR_MD5 RT_BIT_32(1)
+/** The SHA-1 of the content. Represented as a hex string. */
+#define RTMANIFEST_ATTR_SHA1 RT_BIT_32(2)
+/** The SHA-256 of the content. Represented as a hex string. */
+#define RTMANIFEST_ATTR_SHA256 RT_BIT_32(3)
+/** The SHA-512 of the content. Represented as a hex string. */
+#define RTMANIFEST_ATTR_SHA512 RT_BIT_32(4)
+/** The end of the valid values. */
+#define RTMANIFEST_ATTR_END RT_BIT_32(5)
+/** Wildcard for use in queries. */
+#define RTMANIFEST_ATTR_ANY UINT32_C(0xffffffff)
+/** @} */
+
+
+/**
+ * Creates an empty manifest.
+ *
+ * @returns IPRT status code.
+ * @param fFlags Flags, MBZ.
+ * @param phManifest Where to return the handle to the manifest.
+ */
+RTDECL(int) RTManifestCreate(uint32_t fFlags, PRTMANIFEST phManifest);
+
+/**
+ * Retains a reference to the manifest handle.
+ *
+ * @returns The new reference count, UINT32_MAX if the handle is invalid.
+ * @param hManifest The handle to retain.
+ */
+RTDECL(uint32_t) RTManifestRetain(RTMANIFEST hManifest);
+
+/**
+ * Releases a reference to the manifest handle.
+ *
+ * @returns The new reference count, 0 if free. UINT32_MAX is returned if the
+ * handle is invalid.
+ * @param hManifest The handle to release.
+ * NIL is quietly ignored (returns 0).
+ */
+RTDECL(uint32_t) RTManifestRelease(RTMANIFEST hManifest);
+
+/**
+ * Creates a duplicate of the specified manifest.
+ *
+ * @returns IPRT status code
+ * @param hManifestSrc The manifest to clone.
+ * @param phManifestDst Where to store the handle to the duplicate.
+ */
+RTDECL(int) RTManifestDup(RTMANIFEST hManifestSrc, PRTMANIFEST phManifestDst);
+
+/**
+ * Compares two manifests for equality.
+ *
+ * @returns IPRT status code.
+ * @retval VINF_SUCCESS if equal.
+ * @retval VERR_NOT_EQUAL if not equal.
+ *
+ * @param hManifest1 The first manifest.
+ * @param hManifest2 The second manifest.
+ * @param papszIgnoreEntries Entries to ignore. Ends with a NULL entry.
+ * @param papszIgnoreAttrs Attributes to ignore. Ends with a NULL entry.
+ * @param fFlags A combination of RTMANIFEST_EQUALS_XXX values.
+ * @param pszError Where to store the name of the mismatching
+ * entry, or as much of the name as there is room
+ * for. This is always set. Optional.
+ * @param cbError The size of the buffer pointed to by @a
+ * pszError.
+ */
+RTDECL(int) RTManifestEqualsEx(RTMANIFEST hManifest1, RTMANIFEST hManifest2, const char * const *papszIgnoreEntries,
+ const char * const *papszIgnoreAttrs, uint32_t fFlags, char *pszError, size_t cbError);
+
+/** @defgroup RTMANIFEST_EQUALS_XXX RTManifestEqualsEx flags
+ * @{ */
+/** Ignore missing attributes if there is one or more to compare. */
+#define RTMANIFEST_EQUALS_IGN_MISSING_ATTRS RT_BIT_32(0)
+/** Ignore attributes missing in the 1st manifest.
+ * @todo implement this */
+#define RTMANIFEST_EQUALS_IGN_MISSING_ATTRS_1ST RT_BIT_32(1)
+/** Ignore missing entries in the 2nd manifest. */
+#define RTMANIFEST_EQUALS_IGN_MISSING_ENTRIES_2ND RT_BIT_32(2)
+/** Mask of valid flags. */
+#define RTMANIFEST_EQUALS_VALID_MASK UINT32_C(0x00000005)
+/** @} */
+
+/**
+ * Compares two manifests for equality.
+ *
+ * @returns IPRT status code.
+ * @retval VINF_SUCCESS if equal.
+ * @retval VERR_NOT_EQUAL if not equal.
+ *
+ * @param hManifest1 The first manifest.
+ * @param hManifest2 The second manifest.
+ */
+RTDECL(int) RTManifestEquals(RTMANIFEST hManifest1, RTMANIFEST hManifest2);
+
+/**
+ *
+ * @returns IPRT status code.
+ * @param hManifest Handle to the manifest.
+ * @param fEntriesOnly Whether to only gather attribute types from the
+ * entries (@c true), or also include the manifest
+ * attributes (@c false).
+ * @param pfTypes Where to return the attributes.
+ */
+RTDECL(int) RTManifestQueryAllAttrTypes(RTMANIFEST hManifest, bool fEntriesOnly, uint32_t *pfTypes);
+
+/**
+ * Sets a manifest attribute.
+ *
+ * @returns IPRT status code.
+ * @param hManifest The manifest handle.
+ * @param pszAttr The attribute name, if NULL it will be termined from @a
+ * fType gives it. If this already exists, its value will
+ * be replaced.
+ * @param pszValue The value string.
+ * @param fType The attribute type. If not know, pass
+ * RTMANIFEST_ATTR_UNKNOWN with a valid attribute
+ * name string (@a pszAttr).
+ */
+RTDECL(int) RTManifestSetAttr(RTMANIFEST hManifest, const char *pszAttr, const char *pszValue, uint32_t fType);
+
+/**
+ * Unsets (removes) a manifest attribute if it exists.
+ *
+ * @returns IPRT status code.
+ * @retval VWRN_NOT_FOUND if not found.
+ *
+ * @param hManifest The manifest handle.
+ * @param pszAttr The attribute name.
+ */
+RTDECL(int) RTManifestUnsetAttr(RTMANIFEST hManifest, const char *pszAttr);
+
+/**
+ * Query a manifest attribute.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_BUFFER_OVERFLOW if the value buffer is too small. The @a
+ * pszValue buffer will not be modified.
+ * @retval VERR_MANIFEST_ATTR_NOT_FOUND
+ * @retval VERR_MANIFEST_ATTR_TYPE_NOT_FOUND
+ * @retval VERR_MANIFEST_ATTR_TYPE_MISMATCH
+ *
+ * @param hManifest The manifest handle.
+ * @param pszAttr The attribute name. If NULL, it will be
+ * selected by @a fType alone.
+ * @param fType The attribute types the entry should match. Pass
+ * Pass RTMANIFEST_ATTR_ANY match any. If more
+ * than one is given, the first matching one is
+ * returned.
+ * @param pszValue Where to return value.
+ * @param cbValue The size of the buffer @a pszValue points to.
+ * @param pfType Where to return the attribute type value.
+ */
+RTDECL(int) RTManifestQueryAttr(RTMANIFEST hManifest, const char *pszAttr, uint32_t fType,
+ char *pszValue, size_t cbValue, uint32_t *pfType);
+
+/**
+ * Sets an attribute of a manifest entry.
+ *
+ * @returns IPRT status code.
+ * @param hManifest The manifest handle.
+ * @param pszEntry The entry name. This will automatically be
+ * added if there was no previous call to
+ * RTManifestEntryAdd for this name. See
+ * RTManifestEntryAdd for the entry name rules.
+ * @param pszAttr The attribute name, if NULL it will be termined from @a
+ * fType gives it. If this already exists, its value will
+ * be replaced.
+ * @param pszValue The value string.
+ * @param fType The attribute type. If not know, pass
+ * RTMANIFEST_ATTR_UNKNOWN with a valid attribute
+ * name string (@a pszAttr).
+ */
+RTDECL(int) RTManifestEntrySetAttr(RTMANIFEST hManifest, const char *pszEntry, const char *pszAttr,
+ const char *pszValue, uint32_t fType);
+
+/**
+ * Unsets (removes) an attribute of a manifest entry if they both exist.
+ *
+ * @returns IPRT status code.
+ * @retval VWRN_NOT_FOUND if not found.
+ *
+ * @param hManifest The manifest handle.
+ * @param pszEntry The entry name.
+ * @param pszAttr The attribute name.
+ */
+RTDECL(int) RTManifestEntryUnsetAttr(RTMANIFEST hManifest, const char *pszEntry, const char *pszAttr);
+
+/**
+ * Query a manifest entry attribute.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_BUFFER_OVERFLOW if the value buffer is too small. The @a
+ * pszValue buffer will not be modified.
+ * @retval VERR_NOT_FOUND if the entry was not found.
+ * @retval VERR_MANIFEST_ATTR_NOT_FOUND
+ * @retval VERR_MANIFEST_ATTR_TYPE_NOT_FOUND
+ * @retval VERR_MANIFEST_ATTR_TYPE_MISMATCH
+ *
+ * @param hManifest The manifest handle.
+ * @param pszEntry The entry name.
+ * @param pszAttr The attribute name. If NULL, it will be
+ * selected by @a fType alone.
+ * @param fType The attribute types the entry should match. Pass
+ * Pass RTMANIFEST_ATTR_ANY match any. If more
+ * than one is given, the first matching one is
+ * returned.
+ * @param pszValue Where to return value.
+ * @param cbValue The size of the buffer @a pszValue points to.
+ * @param pfType Where to return the attribute type value.
+ */
+RTDECL(int) RTManifestEntryQueryAttr(RTMANIFEST hManifest, const char *pszEntry, const char *pszAttr, uint32_t fType,
+ char *pszValue, size_t cbValue, uint32_t *pfType);
+
+/**
+ * Adds a new entry to a manifest.
+ *
+ * The entry name rules:
+ * - The entry name can contain any character defined by unicode, except
+ * control characters, ':', '(' and ')'. The exceptions are mainly there
+ * because of uncertainty around how various formats handles these.
+ * - It is considered case sensitive.
+ * - Forward (unix) and backward (dos) slashes are considered path
+ * separators and converted to forward slashes.
+ *
+ * @returns IPRT status code.
+ * @retval VWRN_ALREADY_EXISTS if the entry already exists.
+ *
+ * @param hManifest The manifest handle.
+ * @param pszEntry The entry name (UTF-8).
+ *
+ * @remarks Some manifest formats will not be able to store an entry without
+ * any attributes. So, this is just here in case it comes in handy
+ * when dealing with formats which can.
+ */
+RTDECL(int) RTManifestEntryAdd(RTMANIFEST hManifest, const char *pszEntry);
+
+/**
+ * Removes an entry.
+ *
+ * @returns IPRT status code.
+ * @param hManifest The manifest handle.
+ * @param pszEntry The entry name.
+ */
+RTDECL(int) RTManifestEntryRemove(RTMANIFEST hManifest, const char *pszEntry);
+
+/**
+ * Add an entry for an I/O stream using a passthru stream.
+ *
+ * The passthru I/O stream will hash all the data read from or written to the
+ * stream and automatically add an entry to the manifest with the desired
+ * attributes when it is released. Alternatively one can call
+ * RTManifestPtIosAddEntryNow() to have more control over exactly when this
+ * action is performed and which status it yields.
+ *
+ * @returns IPRT status code.
+ * @param hManifest The manifest to add the entry to.
+ * @param hVfsIos The I/O stream to pass thru to/from.
+ * @param pszEntry The entry name.
+ * @param fAttrs The attributes to create for this stream.
+ * @param fReadOrWrite Whether it's a read or write I/O stream.
+ * @param phVfsIosPassthru Where to return the new handle.
+ */
+RTDECL(int) RTManifestEntryAddPassthruIoStream(RTMANIFEST hManifest, RTVFSIOSTREAM hVfsIos, const char *pszEntry,
+ uint32_t fAttrs, bool fReadOrWrite, PRTVFSIOSTREAM phVfsIosPassthru);
+
+/**
+ * Adds the entry to the manifest right now.
+ *
+ * @returns IPRT status code.
+ * @param hVfsPtIos The manifest passthru I/O stream returned by
+ * RTManifestEntryAddPassthruIoStream().
+ */
+RTDECL(int) RTManifestPtIosAddEntryNow(RTVFSIOSTREAM hVfsPtIos);
+
+/**
+ * Checks if the give I/O stream is a manifest passthru instance or not.
+ *
+ * @returns true if it's a manifest passthru I/O stream, false if not.
+ * @param hVfsPtIos Possible the manifest passthru I/O stream handle.
+ */
+RTDECL(bool) RTManifestPtIosIsInstanceOf(RTVFSIOSTREAM hVfsPtIos);
+
+/**
+ * Adds an entry for a file with the specified set of attributes.
+ *
+ * @returns IPRT status code.
+ *
+ * @param hManifest The manifest handle.
+ * @param hVfsIos The I/O stream handle of the entry. This will
+ * be processed to its end on successful return.
+ * (Must be positioned at the start to get
+ * the expected results.)
+ * @param pszEntry The entry name.
+ * @param fAttrs The attributes to create for this stream. See
+ * RTMANIFEST_ATTR_XXX.
+ */
+RTDECL(int) RTManifestEntryAddIoStream(RTMANIFEST hManifest, RTVFSIOSTREAM hVfsIos, const char *pszEntry, uint32_t fAttrs);
+
+/**
+ * Checks if there is a manifest entry by the given name.
+ *
+ * @returns true if there is, false if not or if the handle is invalid.
+ * @param hManifest The manifest handle.
+ * @param pszEntry The entry name.
+ */
+RTDECL(bool) RTManifestEntryExists(RTMANIFEST hManifest, const char *pszEntry);
+
+/**
+ * Reads in a "standard" manifest.
+ *
+ * This reads the format used by OVF, the distinfo in FreeBSD ports, and
+ * others.
+ *
+ * @returns IPRT status code.
+ * @param hManifest The handle to the manifest where to add the
+ * manifest that's read in.
+ * @param hVfsIos The I/O stream to read the manifest from.
+ */
+RTDECL(int) RTManifestReadStandard(RTMANIFEST hManifest, RTVFSIOSTREAM hVfsIos);
+
+/**
+ * Reads in a "standard" manifest.
+ *
+ * This reads the format used by OVF, the distinfo in FreeBSD ports, and
+ * others.
+ *
+ * @returns IPRT status code.
+ * @param hManifest The handle to the manifest where to add the
+ * manifest that's read in.
+ * @param hVfsIos The I/O stream to read the manifest from.
+ * @param pszErr Where to return extended error info on failure.
+ * Optional.
+ * @param cbErr The size of the buffer @a pszErr points to.
+ */
+RTDECL(int) RTManifestReadStandardEx(RTMANIFEST hManifest, RTVFSIOSTREAM hVfsIos, char *pszErr, size_t cbErr);
+
+/**
+ * Reads in a "standard" manifest from the specified file.
+ *
+ * This reads the format used by OVF, the distinfo in FreeBSD ports, and
+ * others.
+ *
+ * @returns IPRT status code.
+ * @param hManifest The handle to the manifest where to add the
+ * manifest that's read in.
+ * @param pszFilename The name of the file to read in.
+ */
+RTDECL(int) RTManifestReadStandardFromFile(RTMANIFEST hManifest, const char *pszFilename);
+
+/**
+ * Writes a "standard" manifest.
+ *
+ * This writes the format used by OVF, the distinfo in FreeBSD ports, and
+ * others.
+ *
+ * @returns IPRT status code.
+ * @param hManifest The handle to the manifest to write.
+ * @param hVfsIos The I/O stream to read the manifest from.
+ */
+RTDECL(int) RTManifestWriteStandard(RTMANIFEST hManifest, RTVFSIOSTREAM hVfsIos);
+
+/**
+ * Writes a "standard" manifest to the specified file.
+ *
+ * @returns IPRT status code.
+ * @param hManifest The handle to the manifest to write.
+ * @param pszFilename The name of the file.
+ */
+RTDECL(int) RTManifestWriteStandardToFile(RTMANIFEST hManifest, const char *pszFilename);
+
+
+
+
+
+/**
+ * Input structure for RTManifestVerify() which contains the filename & the
+ * SHA1/SHA256 digest.
+ */
+typedef struct RTMANIFESTTEST
+{
+ /** The filename. */
+ const char *pszTestFile;
+ /** The SHA1/SHA256 digest of the file. */
+ const char *pszTestDigest;
+} RTMANIFESTTEST;
+/** Pointer to the input structure. */
+typedef RTMANIFESTTEST* PRTMANIFESTTEST;
+
+
+/**
+ * Verify the given SHA1 digests against the entries in the manifest file.
+ *
+ * Please note that not only the various digest have to match, but the
+ * filenames as well. If there are more or even less files listed in the
+ * manifest file than provided by paTests, VERR_MANIFEST_FILE_MISMATCH will be
+ * returned.
+ *
+ * @returns iprt status code.
+ *
+ * @param pszManifestFile Filename of the manifest file to verify.
+ * @param paTests Array of files & SHA1 sums.
+ * @param cTests Number of entries in paTests.
+ * @param piFailed A index to paTests in the
+ * VERR_MANIFEST_DIGEST_MISMATCH error case
+ * (optional).
+ * @deprecated Use the RTMANIFEST based API instead.
+ */
+RTR3DECL(int) RTManifestVerify(const char *pszManifestFile, PRTMANIFESTTEST paTests, size_t cTests, size_t *piFailed);
+
+/**
+ * This is analogous to function RTManifestVerify(), but calculates the SHA1
+ * sums of the given files itself.
+ *
+ * @returns iprt status code.
+ *
+ * @param pszManifestFile Filename of the manifest file to verify.
+ * @param papszFiles Array of files to check SHA1 sums.
+ * @param cFiles Number of entries in papszFiles.
+ * @param piFailed A index to papszFiles in the
+ * VERR_MANIFEST_DIGEST_MISMATCH error case
+ * (optional).
+ * @param pfnProgressCallback optional callback for the progress indication
+ * @param pvUser user defined pointer for the callback
+ * @deprecated Use the RTMANIFEST based API instead.
+ */
+RTR3DECL(int) RTManifestVerifyFiles(const char *pszManifestFile, const char * const *papszFiles, size_t cFiles, size_t *piFailed,
+ PFNRTPROGRESS pfnProgressCallback, void *pvUser);
+
+/**
+ * Creates a manifest file for a set of files. The manifest file contains SHA1
+ * sums of every provided file and could be used to verify the data integrity
+ * of them.
+ *
+ * @returns iprt status code.
+ *
+ * @param pszManifestFile Filename of the manifest file to create.
+ * @param enmDigestType The digest type (RTDIGESTTYPE_*)
+ * @param papszFiles Array of files to create SHA1 sums for.
+ * @param cFiles Number of entries in papszFiles.
+ * @param pfnProgressCallback optional callback for the progress indication
+ * @param pvUser user defined pointer for the callback
+ * @deprecated Use the RTMANIFEST based API instead.
+ */
+RTR3DECL(int) RTManifestWriteFiles(const char *pszManifestFile, RTDIGESTTYPE enmDigestType,
+ const char * const *papszFiles, size_t cFiles,
+ PFNRTPROGRESS pfnProgressCallback, void *pvUser);
+
+/**
+ * Queries the first digest type found in the given manifest.
+ *
+ * @returns iprt status code.
+ *
+ * @param pvBuf Pointer to memory buffer of the manifest file.
+ * @param cbSize Size of the memory buffer.
+ * @param penmDigestType Where to return the first digest type found in
+ * the manifest.
+ * @deprecated Use the RTMANIFEST based API instead.
+ */
+RTR3DECL(int) RTManifestVerifyDigestType(void const *pvBuf, size_t cbSize, RTDIGESTTYPE *penmDigestType);
+
+/**
+ * Verify the given SHA1 digests against the entries in the manifest file in
+ * memory.
+ *
+ * @returns iprt status code.
+ *
+ * @param pvBuf Pointer to memory buffer of the manifest file.
+ * @param cbSize Size of the memory buffer.
+ * @param paTests Array of file names and digests.
+ * @param cTests Number of entries in paTests.
+ * @param piFailed A index to paTests in the
+ * VERR_MANIFEST_DIGEST_MISMATCH error case
+ * (optional).
+ * @deprecated Use the RTMANIFEST based API instead.
+ */
+RTR3DECL(int) RTManifestVerifyFilesBuf(void *pvBuf, size_t cbSize, PRTMANIFESTTEST paTests, size_t cTests, size_t *piFailed);
+
+/**
+ * Creates a manifest file in memory for a set of files. The manifest file
+ * contains SHA1 sums of every provided file and could be used to verify the
+ * data integrity of them.
+ *
+ * @returns iprt status code.
+ *
+ * @param ppvBuf Pointer to resulting memory buffer.
+ * @param pcbSize Pointer for the size of the memory buffer.
+ * @param enmDigestType Which type of digest ("SHA1", "SHA256", ...)
+ * @param paFiles Array of file names and digests.
+ * @param cFiles Number of entries in paFiles.
+ * @deprecated Use the RTMANIFEST based API instead.
+ */
+RTR3DECL(int) RTManifestWriteFilesBuf(void **ppvBuf, size_t *pcbSize, RTDIGESTTYPE enmDigestType, PRTMANIFESTTEST paFiles, size_t cFiles);
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_manifest_h */
+
diff --git a/include/iprt/md2.h b/include/iprt/md2.h
new file mode 100644
index 00000000..0b408424
--- /dev/null
+++ b/include/iprt/md2.h
@@ -0,0 +1,139 @@
+/** @file
+ * IPRT - Message-Digest Algorithm 2.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_md2_h
+#define IPRT_INCLUDED_md2_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_md2 RTMd2 - Message-Digest algorithm 2
+ * @ingroup grp_rt
+ * @{
+ */
+
+/** Size of a MD2 hash. */
+#define RTMD2_HASH_SIZE 16
+/** The length of a MD2 digest string. The terminator is not included. */
+#define RTMD2_DIGEST_LEN 32
+
+/**
+ * MD2 hash algorithm context.
+ */
+typedef union RTMD2CONTEXT
+{
+ uint64_t u64BetterAlignment;
+ uint8_t abPadding[4 + 16 + 16*4 + 16*4];
+#ifdef RT_MD2_PRIVATE_CONTEXT
+ MD2_CTX Private;
+#endif
+#ifdef RT_MD2_PRIVATE_ALT_CONTEXT
+ RTMD2ALTPRIVATECTX AltPrivate;
+#endif
+} RTMD2CONTEXT;
+
+/** Pointer to MD2 hash algorithm context. */
+typedef RTMD2CONTEXT *PRTMD2CONTEXT;
+
+
+/**
+ * Compute the MD2 hash of the data.
+ *
+ * @param pvBuf Pointer to data.
+ * @param cbBuf Length of data (in bytes).
+ * @param pabDigest Where to store the hash.
+ * (What's passed is a pointer to the caller's buffer.)
+ */
+RTDECL(void) RTMd2(const void *pvBuf, size_t cbBuf, uint8_t pabDigest[RTMD2_HASH_SIZE]);
+
+/**
+ * Initialize MD2 context.
+ *
+ * @param pCtx Pointer to the MD2 context to initialize.
+ */
+RTDECL(void) RTMd2Init(PRTMD2CONTEXT pCtx);
+
+/**
+ * Feed data into the MD2 computation.
+ *
+ * @param pCtx Pointer to the MD2 context.
+ * @param pvBuf Pointer to data.
+ * @param cbBuf Length of data (in bytes).
+ */
+RTDECL(void) RTMd2Update(PRTMD2CONTEXT pCtx, const void *pvBuf, size_t cbBuf);
+
+/**
+ * Compute the MD2 hash of the data.
+ *
+ * @param pCtx Pointer to the MD2 context.
+ * @param pabDigest Where to store the hash. (What's passed is a pointer to
+ * the caller's buffer.)
+ */
+RTDECL(void) RTMd2Final(PRTMD2CONTEXT pCtx, uint8_t pabDigest[RTMD2_HASH_SIZE]);
+
+/**
+ * Converts a MD2 hash to a digest string.
+ *
+ * @returns IPRT status code.
+ *
+ * @param pabDigest The binary digest returned by RTMd2Final or RTMd2.
+ * @param pszDigest Where to return the stringified digest.
+ * @param cchDigest The size of the output buffer. Should be at least
+ * RTMD2_STRING_LEN + 1 bytes.
+ */
+RTDECL(int) RTMd2ToString(uint8_t const pabDigest[RTMD2_HASH_SIZE], char *pszDigest, size_t cchDigest);
+
+/**
+ * Converts a MD2 hash to a digest string.
+ *
+ * @returns IPRT status code.
+ *
+ * @param pszDigest The stringified digest. Leading and trailing spaces are
+ * ignored.
+ * @param pabDigest Where to store the hash. (What is passed is a pointer to
+ * the caller's buffer.)
+ */
+RTDECL(int) RTMd2FromString(char const *pszDigest, uint8_t pabDigest[RTMD2_HASH_SIZE]);
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_md2_h */
+
diff --git a/include/iprt/md4.h b/include/iprt/md4.h
new file mode 100644
index 00000000..a95d2e25
--- /dev/null
+++ b/include/iprt/md4.h
@@ -0,0 +1,142 @@
+/** @file
+ * IPRT - Message-Digest Algorithm 4.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_md4_h
+#define IPRT_INCLUDED_md4_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_md4 RTMd4 - Message-Digest algorithm 4
+ * @ingroup grp_rt
+ *
+ * @note This is just for backwards compatibility and completeness.
+ *
+ * @{
+ */
+
+/** Size of a MD4 hash. */
+#define RTMD4_HASH_SIZE 16
+/** The length of a MD4 digest string. The terminator is not included. */
+#define RTMD4_DIGEST_LEN 32
+
+/**
+ * MD4 hash algorithm context.
+ */
+typedef union RTMD4CONTEXT
+{
+ uint64_t u64BetterAlignment;
+ uint8_t abPadding[22*4 + 64 + 8];
+#ifdef RT_MD4_PRIVATE_CONTEXT
+ MD4_CTX Private;
+#endif
+#ifdef RT_MD4_PRIVATE_ALT_CONTEXT
+ RTMD4ALTPRIVATECTX AltPrivate;
+#endif
+} RTMD4CONTEXT;
+
+/** Pointer to MD4 hash algorithm context. */
+typedef RTMD4CONTEXT *PRTMD4CONTEXT;
+
+
+/**
+ * Compute the MD4 hash of the data.
+ *
+ * @param pvBuf Pointer to data.
+ * @param cbBuf Length of data (in bytes).
+ * @param pabDigest Where to store the hash.
+ * (What's passed is a pointer to the caller's buffer.)
+ */
+RTDECL(void) RTMd4(const void *pvBuf, size_t cbBuf, uint8_t pabDigest[RTMD4_HASH_SIZE]);
+
+/**
+ * Initialize MD4 context.
+ *
+ * @param pCtx Pointer to the MD4 context to initialize.
+ */
+RTDECL(void) RTMd4Init(PRTMD4CONTEXT pCtx);
+
+/**
+ * Feed data into the MD4 computation.
+ *
+ * @param pCtx Pointer to the MD4 context.
+ * @param pvBuf Pointer to data.
+ * @param cbBuf Length of data (in bytes).
+ */
+RTDECL(void) RTMd4Update(PRTMD4CONTEXT pCtx, const void *pvBuf, size_t cbBuf);
+
+/**
+ * Compute the MD4 hash of the data.
+ *
+ * @param pCtx Pointer to the MD4 context.
+ * @param pabDigest Where to store the hash. (What's passed is a pointer to
+ * the caller's buffer.)
+ */
+RTDECL(void) RTMd4Final(PRTMD4CONTEXT pCtx, uint8_t pabDigest[RTMD4_HASH_SIZE]);
+
+/**
+ * Converts a MD4 hash to a digest string.
+ *
+ * @returns IPRT status code.
+ *
+ * @param pabDigest The binary digest returned by RTMd4Final or RTMd4.
+ * @param pszDigest Where to return the stringified digest.
+ * @param cchDigest The size of the output buffer. Should be at least
+ * RTMD4_STRING_LEN + 1 bytes.
+ */
+RTDECL(int) RTMd4ToString(uint8_t const pabDigest[RTMD4_HASH_SIZE], char *pszDigest, size_t cchDigest);
+
+/**
+ * Converts a MD4 hash to a digest string.
+ *
+ * @returns IPRT status code.
+ *
+ * @param pszDigest The stringified digest. Leading and trailing spaces are
+ * ignored.
+ * @param pabDigest Where to store the hash. (What is passed is a pointer to
+ * the caller's buffer.)
+ */
+RTDECL(int) RTMd4FromString(char const *pszDigest, uint8_t pabDigest[RTMD4_HASH_SIZE]);
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_md4_h */
+
diff --git a/include/iprt/md5.h b/include/iprt/md5.h
new file mode 100644
index 00000000..a89ab8ac
--- /dev/null
+++ b/include/iprt/md5.h
@@ -0,0 +1,148 @@
+/** @file
+ * IPRT - Message-Digest algorithm 5.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_md5_h
+#define IPRT_INCLUDED_md5_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+
+/** @defgroup grp_rt_md5 RTMd5 - Message-Digest algorithm 5
+ * @ingroup grp_rt
+ * @{
+ */
+
+/** Size of a MD5 hash. */
+#define RTMD5_HASH_SIZE 16
+/** @deprecated Use RTMD5_HASH_SIZE. */
+#define RTMD5HASHSIZE RTMD5_HASH_SIZE
+/** The length of a MD5 digest string. The terminator is not included. */
+#define RTMD5_DIGEST_LEN 32
+/** Size of a MD5 hash.
+ * @deprecated Use RTMD5_DIGEST_LEN */
+#define RTMD5_STRING_LEN RTMD5_DIGEST_LEN
+
+/**
+ * MD5 hash algorithm context.
+ */
+typedef union RTMD5CONTEXT
+{
+ uint64_t u64BetterAlignment;
+ uint8_t abPadding[(4 + 6 + 16 + 1) * sizeof(uint32_t)];
+ /** Context used by md5-alt.cpp. */
+ struct
+ {
+ uint32_t in[16];
+ uint32_t buf[4];
+ uint32_t bits[2];
+ } AltPrivate;
+#ifdef RT_MD5_OPENSSL_PRIVATE_CONTEXT
+ /** Context used by md5-openssl.cpp. */
+ MD5_CTX OsslPrivate;
+#endif
+} RTMD5CONTEXT;
+/** Pointer to MD5 hash algorithm context. */
+typedef RTMD5CONTEXT *PRTMD5CONTEXT;
+
+RT_C_DECLS_BEGIN
+
+/**
+ * Compute the MD5 hash of the data.
+ *
+ * @param pvBuf Pointer to data.
+ * @param cbBuf Length of data (in bytes).
+ * @param pabDigest Where to store the hash.
+ * (What's passed is a pointer to the caller's buffer.)
+ */
+RTDECL(void) RTMd5(const void *pvBuf, size_t cbBuf, uint8_t pabDigest[RTMD5HASHSIZE]);
+
+/**
+ * Initialize MD5 context.
+ *
+ * @param pCtx Pointer to the MD5 context to initialize.
+ */
+RTDECL(void) RTMd5Init(PRTMD5CONTEXT pCtx);
+
+/**
+ * Feed data into the MD5 computation.
+ *
+ * @param pCtx Pointer to the MD5 context.
+ * @param pvBuf Pointer to data.
+ * @param cbBuf Length of data (in bytes).
+ */
+RTDECL(void) RTMd5Update(PRTMD5CONTEXT pCtx, const void *pvBuf, size_t cbBuf);
+
+/**
+ * Compute the MD5 hash of the data.
+ *
+ * @param pabDigest Where to store the hash.
+ * (What's passed is a pointer to the caller's buffer.)
+ * @param pCtx Pointer to the MD5 context.
+ */
+RTDECL(void) RTMd5Final(uint8_t pabDigest[RTMD5HASHSIZE], PRTMD5CONTEXT pCtx);
+
+/**
+ * Converts a MD5 hash to a digest string.
+ *
+ * @returns IPRT status code.
+ *
+ * @param pabDigest The binary digest returned by RTMd5Final or RTMd5.
+ * @param pszDigest Where to return the stringified digest.
+ * @param cchDigest The size of the output buffer. Should be at least
+ * RTMD5_STRING_LEN + 1 bytes.
+ */
+RTDECL(int) RTMd5ToString(uint8_t const pabDigest[RTMD5_HASH_SIZE], char *pszDigest, size_t cchDigest);
+
+/**
+ * Converts a MD5 hash to a digest string.
+ *
+ * @returns IPRT status code.
+ *
+ * @param pszDigest The stringified digest. Leading and trailing spaces are
+ * ignored.
+ * @param pabDigest Where to store the hash. (What is passed is a pointer to
+ * the caller's buffer.)
+ */
+RTDECL(int) RTMd5FromString(char const *pszDigest, uint8_t pabDigest[RTMD5_HASH_SIZE]);
+
+
+RT_C_DECLS_END
+
+/** @} */
+
+#endif /* !IPRT_INCLUDED_md5_h */
+
diff --git a/include/iprt/mem.h b/include/iprt/mem.h
new file mode 100644
index 00000000..9cfbbc20
--- /dev/null
+++ b/include/iprt/mem.h
@@ -0,0 +1,1239 @@
+/** @file
+ * IPRT - Memory Management and Manipulation.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_mem_h
+#define IPRT_INCLUDED_mem_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+
+#ifdef IPRT_WITH_GCC_SANITIZER
+# include <sanitizer/lsan_interface.h>
+#endif
+
+#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;
+
+/**
+ * Clear and free temporary memory.
+ *
+ * This is strongly recommended when the memory being freed holds untrusted data
+ * to help counter heap spraying.
+ *
+ * @param pv Pointer to memory block.
+ * @param cb Size of the memory block.
+ *
+ * @note The memory isn't always filled with zeros, it can be set to a
+ * different value in some configurations.
+ */
+RTDECL(void) RTMemTmpFreeZ(void *pv, size_t cb) 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;
+
+/**
+ * Reallocates memory with default tag, initializing any new space to zero.
+ *
+ * @returns Pointer to the allocated memory.
+ * @returns NULL on failure.
+ * @param pvOld The memory block to reallocate.
+ * @param cbOld The old block size (in bytes).
+ * @param cbNew The new block size (in bytes).
+ */
+#define RTMemReallocZ(pvOld, cbOld, cbNew) RTMemReallocZTag((pvOld), (cbOld), (cbNew), RTMEM_TAG)
+
+/**
+ * Reallocates memory with custom tag, initializing any new space to zero.
+ *
+ * @returns Pointer to the allocated memory.
+ * @returns NULL on failure.
+ * @param pvOld The memory block to reallocate.
+ * @param cbOld The old block size (in bytes).
+ * @param cbNew The new block size (in bytes).
+ * @param pszTag Allocation tag used for statistics and such.
+ */
+RTDECL(void *) RTMemReallocZTag(void *pvOld, size_t cbOld, 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;
+
+/**
+ * Clears and frees memory.
+ *
+ * This is strongly recommended when the memory being freed holds untrusted data
+ * to help counter heap spraying.
+ *
+ * @param pv Pointer to memory block.
+ * @param cb The size of the allocation.
+ *
+ * @note The memory isn't always filled with zeros, it can be set to a
+ * different value in some configurations.
+ */
+RTDECL(void) RTMemFreeZ(void *pv, size_t cb) RT_NO_THROW_PROTO;
+
+
+
+/** @name RTR0MemAllocEx and RTR0MemAllocExTag flags.
+ * @{ */
+/** The returned memory should be zeroed. */
+#define RTMEMALLOCEX_FLAGS_ZEROED RT_BIT(0)
+/** Allocate memory that can be executed.
+ * @note Only supported in ring-3 for now, use RTR0MemObjAllocPage w/ @a
+ * fExecutable = @c true for ring-0. */
+#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;
+
+/**
+ * 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;
+
+/**
+ * Allocate page aligned memory with default tag, extended version.
+ *
+ * @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 fFlags RTMEMPAGEALLOC_F_XXX.
+ */
+#define RTMemPageAllocEx(cb, fFlags) RTMemPageAllocExTag((cb), (fFlags), RTMEM_TAG)
+
+/**
+ * Allocate page aligned memory with custom tag, extended version.
+ *
+ * @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 fFlags RTMEMPAGEALLOC_F_XXX.
+ * @param pszTag Allocation tag used for statistics and such.
+ */
+RTDECL(void *) RTMemPageAllocExTag(size_t cb, uint32_t fFlags, const char *pszTag) RT_NO_THROW_PROTO;
+
+/** @name RTMEMPAGEALLOC_F_XXX - flags for RTMemPageAllocEx() and RTMemPageAllocExTag()
+ * @{ */
+/** Zero the allocation. */
+#define RTMEMPAGEALLOC_F_ZERO RT_BIT_32(0)
+/** Try lock the allocation (failure ignored). */
+#define RTMEMPAGEALLOC_F_ADVISE_LOCKED RT_BIT_32(1)
+/** Try prevent the memory from ending up in a dump/core. */
+#define RTMEMPAGEALLOC_F_ADVISE_NO_DUMP RT_BIT_32(2)
+/** Valid bit mask. */
+#define RTMEMPAGEALLOC_F_VALID_MASK UINT32_C(0x00000007)
+/** @} */
+
+/**
+ * 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;
+
+
+/** @def RTMEM_WILL_LEAK
+ * Macro for hinting that a memory allocation @a a_pv will leak.
+ *
+ * @note This shall only be used in code that doesn't allocate the object.
+ * Code allocating memory knowing it will leak shall start the allocation
+ * tag string with 'will-leak:'.
+ */
+/** @def RTMEM_MAY_LEAK
+ * Macro for hinting that a memory allocation @a a_pv may leak.
+ *
+ * @note This shall only be used in code that doesn't allocate the object.
+ * Code allocating memory knowing it may leak shall start the allocation
+ * tag string with 'may-leak:'.
+ */
+#ifdef IPRT_WITH_GCC_SANITIZER
+# define RTMEM_WILL_LEAK(a_pv) __lsan_ignore_object(a_pv)
+# define RTMEM_MAY_LEAK(a_pv) __lsan_ignore_object(a_pv)
+#else
+# define RTMEM_WILL_LEAK(a_pv) do { } while (0)
+# define RTMEM_MAY_LEAK(a_pv) do { } while (0)
+#endif
+
+
+/** @def RTMEM_IMPLEMENT_NEW_AND_DELETE
+ * Provides a new and delete implementation to a class using IPRT's RTMem
+ * allocator.
+ */
+#if !defined(RTMEM_WRAP_SOME_NEW_AND_DELETE_TO_EF) || defined(RTMEM_NO_WRAP_SOME_NEW_AND_DELETE_TO_EF)
+# ifdef RT_EXCEPTIONS_ENABLED
+# define RTMEM_IMPLEMENT_NEW_AND_DELETE() \
+ void *operator new(size_t cb) RT_THROW(std::bad_alloc) \
+ { \
+ void *pv = RTMemAlloc(cb); \
+ 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 RTMemAlloc(cb); \
+ } \
+ void *operator new(size_t cb, void *pvBuf) RT_NO_THROW_DEF \
+ { \
+ NOREF(cb); \
+ return pvBuf; \
+ } \
+ void *operator new[](size_t cb) RT_THROW(std::bad_alloc) \
+ { \
+ void *pv = RTMemAlloc(cb); \
+ 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 RTMemAlloc(cb); \
+ } \
+ \
+ void operator delete(void *pv) RT_NO_THROW_DEF \
+ { \
+ RTMemFree(pv); \
+ } \
+ void operator delete(void *pv, const std::nothrow_t &nothrow_constant) RT_NO_THROW_DEF \
+ { \
+ NOREF(nothrow_constant); \
+ RTMemFree(pv); \
+ } \
+ void operator delete[](void *pv) RT_NO_THROW_DEF \
+ { \
+ RTMemFree(pv); \
+ } \
+ void operator delete[](void *pv, const std::nothrow_t &nothrow_constant) RT_NO_THROW_DEF \
+ { \
+ NOREF(nothrow_constant); \
+ RTMemFree(pv); \
+ } \
+ \
+ typedef int UsingIprtNewAndDeleteOperators
+# else /* !RT_EXCEPTIONS_ENABLED */
+# define RTMEM_IMPLEMENT_NEW_AND_DELETE() \
+ void *operator new(size_t cb) \
+ { \
+ return RTMemAlloc(cb); \
+ } \
+ void *operator new(size_t cb, const std::nothrow_t &nothrow_constant) \
+ { \
+ NOREF(nothrow_constant); \
+ return RTMemAlloc(cb); \
+ } \
+ void *operator new(size_t cb, void *pvBuf) RT_NO_THROW_DEF \
+ { \
+ NOREF(cb); \
+ return pvBuf; \
+ } \
+ void *operator new[](size_t cb) \
+ { \
+ return RTMemAlloc(cb); \
+ } \
+ void *operator new[](size_t cb, const std::nothrow_t &nothrow_constant) \
+ { \
+ NOREF(nothrow_constant); \
+ return RTMemAlloc(cb); \
+ } \
+ \
+ void operator delete(void *pv) \
+ { \
+ RTMemFree(pv); \
+ } \
+ void operator delete(void *pv, const std::nothrow_t &nothrow_constant) \
+ { \
+ NOREF(nothrow_constant); \
+ RTMemFree(pv); \
+ } \
+ void operator delete[](void *pv) \
+ { \
+ RTMemFree(pv); \
+ } \
+ void operator delete[](void *pv, const std::nothrow_t &nothrow_constant) \
+ { \
+ NOREF(nothrow_constant); \
+ RTMemFree(pv); \
+ } \
+ \
+ typedef int UsingIprtNewAndDeleteOperators
+# endif /* !RT_EXCEPTIONS_ENABLED */
+#else /* defined(RTMEM_WRAP_SOME_NEW_AND_DELETE_TO_EF) && !defined(RTMEM_NO_WRAP_SOME_NEW_AND_DELETE_TO_EF) */
+# define RTMEM_IMPLEMENT_NEW_AND_DELETE() RTMEMEF_NEW_AND_DELETE_OPERATORS()
+#endif /* defined(RTMEM_WRAP_SOME_NEW_AND_DELETE_TO_EF) && !defined(RTMEM_NO_WRAP_SOME_NEW_AND_DELETE_TO_EF) */
+
+
+#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 RTMemTmpFreeZ() except that it's for fenced memory.
+ *
+ * @param pv Pointer to memory block.
+ * @param cb Size of the memory block.
+ * @param SRC_POS The source position where call is being made from. Use
+ * RT_SRC_POS when possible. Optional.
+ */
+RTDECL(void) RTMemEfTmpFreeZ(void *pv, size_t cb, 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;
+
+/**
+ * Same as RTMemReallocZTag() except that it's fenced.
+ *
+ * @returns Pointer to the allocated memory.
+ * @returns NULL on failure.
+ * @param pvOld The memory block to reallocate.
+ * @param cbOld The old block size (in bytes).
+ * @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 *) RTMemEfReallocZ(void *pvOld, size_t cbOld, 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;
+
+/**
+ * Clear and free memory allocated by any of the RTMemEf* allocators.
+ *
+ * @param pv Pointer to memory block.
+ * @param cb Size of the allocation.
+ * @param SRC_POS The source position where call is being made from. Use
+ * RT_SRC_POS when possible. Optional.
+ */
+RTDECL(void) RTMemEfFreeZ(void *pv, size_t cb, 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, void *pvBuf) RT_NO_THROW_DEF \
+ { \
+ NOREF(cb); \
+ return pvBuf; \
+ } \
+ 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, void *pvBuf) RT_NO_THROW_DEF \
+ { \
+ NOREF(cb); \
+ return pvBuf; \
+ } \
+ 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 RTMemTmpFreeZ(pv, cb) RTMemEfTmpFreeZ((pv), (cb), 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 RTMemReallocZTag(pvOld, cbOld, cbNew, pszTag) RTMemEfReallocZ((pvOld), (cbOld), (cbNew), (pszTag), RT_SRC_POS)
+# define RTMemFree(pv) RTMemEfFree((pv), RT_SRC_POS)
+# define RTMemFreeZ(pv, cb) RTMemEfFreeZ((pv), (cb), 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 RTMemTmpFree.
+ * @copydoc RTMemTmpFree
+ */
+RTDECL(void) RTMemEfTmpFreeNP(void *pv) RT_NO_THROW_PROTO;
+
+/**
+ * Fenced drop-in replacement for RTMemTmpFreeZ.
+ * @copydoc RTMemTmpFreeZ
+ */
+RTDECL(void) RTMemEfTmpFreeZNP(void *pv, size_t cb) 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 RTMemReallocZTag.
+ * @copydoc RTMemReallocZTag
+ */
+RTDECL(void *) RTMemEfReallocZNP(void *pvOld, size_t cbOld, 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 RTMemFreeZ.
+ * @copydoc RTMemFreeZ
+ */
+RTDECL(void) RTMemEfFreeZNP(void *pv, size_t cb) 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 /* !IPRT_INCLUDED_mem_h */
+
diff --git a/include/iprt/memcache.h b/include/iprt/memcache.h
new file mode 100644
index 00000000..365ff61e
--- /dev/null
+++ b/include/iprt/memcache.h
@@ -0,0 +1,170 @@
+/** @file
+ * IPRT - Memory Object Allocation Cache.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_memcache_h
+#define IPRT_INCLUDED_memcache_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+
+RT_C_DECLS_BEGIN
+
+
+/** @defgroup grp_rt_memcache RTMemCache - Memory Object Allocation Cache
+ * @ingroup grp_rt
+ *
+ * Optimized allocation, initialization, freeing and destruction of memory
+ * objects of the same kind and size. Objects are constructed once, then
+ * allocated and freed one or more times, until finally destructed together with
+ * the cache (RTMemCacheDestroy). It's expected behavior, even when pfnCtor is
+ * NULL, that the user will be store information that should be persistent
+ * across RTMemCacheFree calls.
+ *
+ * The objects are zeroed prior to calling pfnCtor. For obvious reasons, the
+ * objects are not touched by the cache after that, so that RTMemCacheAlloc will
+ * return the object in the same state as when it as handed to RTMemCacheFree.
+ *
+ * @todo A callback for the reuse (at alloc time) might be of interest.
+ *
+ * @{
+ */
+
+/** A memory cache handle. */
+typedef R3R0PTRTYPE(struct RTMEMCACHEINT *) RTMEMCACHE;
+/** Pointer to a memory cache handle. */
+typedef RTMEMCACHE *PRTMEMCACHE;
+/** Nil memory cache handle. */
+#define NIL_RTMEMCACHE ((RTMEMCACHE)0)
+
+
+/**
+ * Object constructor.
+ *
+ * This is called for when an element is allocated for the first time.
+ *
+ * @returns IPRT status code.
+ * @param hMemCache The cache handle.
+ * @param pvObj The memory object that should be initialized.
+ * @param pvUser The user argument.
+ *
+ * @remarks No serialization is performed.
+ */
+typedef DECLCALLBACKTYPE(int, FNMEMCACHECTOR,(RTMEMCACHE hMemCache, void *pvObj, void *pvUser));
+/** Pointer to an object constructor for the memory cache. */
+typedef FNMEMCACHECTOR *PFNMEMCACHECTOR;
+
+/**
+ * Object destructor.
+ *
+ * This is called when we're shrinking or destroying the cache.
+ *
+ * @param hMemCache The cache handle.
+ * @param pvObj The memory object that should be initialized.
+ * @param pvUser The user argument.
+ *
+ * @remarks No serialization is performed.
+ */
+typedef DECLCALLBACKTYPE(void, FNMEMCACHEDTOR,(RTMEMCACHE hMemCache, void *pvObj, void *pvUser));
+/** Pointer to an object destructor for the memory cache. */
+typedef FNMEMCACHEDTOR *PFNMEMCACHEDTOR;
+
+
+/**
+ * Create an allocation cache for fixed size memory objects.
+ *
+ * @returns IPRT status code.
+ * @param phMemCache Where to return the cache handle.
+ * @param cbObject The size of one memory object.
+ * @param cbAlignment The object alignment. This must be a power of
+ * two. The higest alignment is 64. If set to 0,
+ * a sensible alignment value will be derived from
+ * the object size.
+ * @param cMaxObjects The maximum cache size. Pass UINT32_MAX if unsure.
+ * @param pfnCtor Object constructor callback. Optional.
+ * @param pfnDtor Object destructor callback. Optional.
+ * @param pvUser User argument for the two callbacks.
+ * @param fFlags Flags reserved for future use. Must be zero.
+ */
+RTDECL(int) RTMemCacheCreate(PRTMEMCACHE phMemCache, size_t cbObject, size_t cbAlignment, uint32_t cMaxObjects,
+ PFNMEMCACHECTOR pfnCtor, PFNMEMCACHEDTOR pfnDtor, void *pvUser, uint32_t fFlags);
+
+/**
+ * Destroy a cache destroying and freeing allocated memory.
+ *
+ * @returns IPRT status code.
+ * @param hMemCache The cache handle. NIL is quietly (VINF_SUCCESS)
+ * ignored.
+ */
+RTDECL(int) RTMemCacheDestroy(RTMEMCACHE hMemCache);
+
+/**
+ * Allocate an object.
+ *
+ * @returns Pointer to the allocated cache object.
+ * @param hMemCache The cache handle.
+ */
+RTDECL(void *) RTMemCacheAlloc(RTMEMCACHE hMemCache);
+
+/**
+ * Allocate an object and return a proper status code.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_MEM_CACHE_MAX_SIZE if we've reached maximum size (see
+ * RTMemCacheCreate).
+ * @retval VERR_NO_MEMORY if we failed to allocate more memory for the cache.
+ *
+ * @param hMemCache The cache handle.
+ * @param ppvObj Where to return the object.
+ */
+RTDECL(int) RTMemCacheAllocEx(RTMEMCACHE hMemCache, void **ppvObj);
+
+/**
+ * Free an object previously returned by RTMemCacheAlloc or RTMemCacheAllocEx.
+ *
+ * @param hMemCache The cache handle.
+ * @param pvObj The object to free. NULL is fine.
+ */
+RTDECL(void) RTMemCacheFree(RTMEMCACHE hMemCache, void *pvObj);
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_memcache_h */
+
diff --git a/include/iprt/memobj.h b/include/iprt/memobj.h
new file mode 100644
index 00000000..e68ea046
--- /dev/null
+++ b/include/iprt/memobj.h
@@ -0,0 +1,795 @@
+/** @file
+ * IPRT - Memory Objects (Ring-0).
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_memobj_h
+#define IPRT_INCLUDED_memobj_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#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);
+
+/**
+ * Checks whether the allocation was zero initialized or not.
+ *
+ * This only works on allocations. It is not meaningful for mappings, reserved
+ * memory and entered physical address, and will return false for these.
+ *
+ * @returns true if the allocation was initialized to zero at allocation time,
+ * false if not or query not meaningful to the object type.
+ * @param hMemObj The ring-0 memory object to be freed.
+ *
+ * @remarks It can be expected that memory allocated in the same fashion will
+ * have the same initialization state. So, if this returns true for
+ * one allocation it will return true for all other similarly made
+ * allocations.
+ */
+RTR0DECL(bool) RTR0MemObjWasZeroInitialized(RTR0MEMOBJ hMemObj);
+
+/**
+ * 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. The user must
+ * use RTR0MemObjProtect after initialization the
+ * allocation to actually make it executable.
+ */
+#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. The user must
+ * use RTR0MemObjProtect after initialization the
+ * allocation to actually make it executable.
+ * @param pszTag Allocation tag used for statistics and such.
+ */
+RTR0DECL(int) RTR0MemObjAllocPageTag(PRTR0MEMOBJ pMemObj, size_t cb, bool fExecutable, const char *pszTag);
+
+/**
+ * Allocates large page aligned virtual kernel memory (default tag).
+ *
+ * Each large page in the allocation is backed by a contiguous chunk of physical
+ * memory aligned to the page size. The memory is taken from a non paged (=
+ * fixed physical memory backing) pool.
+ *
+ * On some hosts we only support allocating a single large page at a time, they
+ * will return VERR_NOT_SUPPORTED if @a cb is larger than @a cbLargePage.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_TRY_AGAIN instead of VERR_NO_MEMORY when
+ * RTMEMOBJ_ALLOC_LARGE_F_FAST is set and supported.
+ * @param pMemObj Where to store the ring-0 memory object handle.
+ * @param cb Number of bytes to allocate. This is rounded up to
+ * nearest large page.
+ * @param cbLargePage The large page size. The allowed values varies from
+ * architecture to architecture and the paging mode
+ * used by the OS.
+ * @param fFlags Flags, RTMEMOBJ_ALLOC_LARGE_F_XXX.
+ *
+ * @note The implicit kernel mapping of this allocation does not necessarily
+ * have to be aligned on a @a cbLargePage boundrary.
+ */
+#define RTR0MemObjAllocLarge(pMemObj, cb, cbLargePage, fFlags) \
+ RTR0MemObjAllocLargeTag((pMemObj), (cb), (cbLargePage), (fFlags), RTMEM_TAG)
+
+/**
+ * Allocates large page aligned virtual kernel memory (custom tag).
+ *
+ * Each large page in the allocation is backed by a contiguous chunk of physical
+ * memory aligned to the page size. The memory is taken from a non paged (=
+ * fixed physical memory backing) pool.
+ *
+ * On some hosts we only support allocating a single large page at a time, they
+ * will return VERR_NOT_SUPPORTED if @a cb is larger than @a cbLargePage.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_TRY_AGAIN instead of VERR_NO_MEMORY when
+ * RTMEMOBJ_ALLOC_LARGE_F_FAST is set and supported.
+ * @param pMemObj Where to store the ring-0 memory object handle.
+ * @param cb Number of bytes to allocate. This is rounded up to
+ * nearest large page.
+ * @param cbLargePage The large page size. The allowed values varies from
+ * architecture to architecture and the paging mode
+ * used by the OS.
+ * @param fFlags Flags, RTMEMOBJ_ALLOC_LARGE_F_XXX.
+ * @param pszTag Allocation tag used for statistics and such.
+ *
+ * @note The implicit kernel mapping of this allocation does not necessarily
+ * have to be aligned on a @a cbLargePage boundrary.
+ */
+RTR0DECL(int) RTR0MemObjAllocLargeTag(PRTR0MEMOBJ pMemObj, size_t cb, size_t cbLargePage, uint32_t fFlags, const char *pszTag);
+
+/** @name RTMEMOBJ_ALLOC_LARGE_F_XXX
+ * @{ */
+/** Indicates that it is okay to fail if there aren't enough large pages handy,
+ * cancelling any expensive search and reshuffling of memory (when supported).
+ * @note This flag can't be realized on all OSes. (Those who do support it
+ * will return VERR_TRY_AGAIN instead of VERR_NO_MEMORY if they
+ * cannot satisfy the request.) */
+#define RTMEMOBJ_ALLOC_LARGE_F_FAST RT_BIT_32(0)
+/** Mask with valid bits. */
+#define RTMEMOBJ_ALLOC_LARGE_F_VALID_MASK UINT32_C(0x00000001)
+/** @} */
+
+/**
+ * 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. The user must
+ * use RTR0MemObjProtect after initialization the
+ * allocation to actually make it executable.
+ */
+#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. The user must
+ * use RTR0MemObjProtect after initialization the
+ * allocation to actually make it executable.
+ * @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. The user must
+ * use RTR0MemObjProtect after initialization the
+ * allocation to actually make it executable.
+ */
+#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. The user must
+ * use RTR0MemObjProtect after initialization the
+ * allocation to actually make it executable.
+ * @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_RTR0PROCESS 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_RTR0PROCESS 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_RTR0PROCESS 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_RTR0PROCESS 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_RTR0PROCESS
+ * 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_RTR0PROCESS
+ * 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);
+
+/**
+ * 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_RTR0PROCESS
+ * is an alias for the current one.
+ * @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 RTR0MemObjMapUserEx(pMemObj, MemObjToMap, R3PtrFixed, uAlignment, fProt, R0Process, offSub, cbSub) \
+ RTR0MemObjMapUserExTag((pMemObj), (MemObjToMap), (R3PtrFixed), (uAlignment), (fProt), (R0Process), \
+ (offSub), (cbSub), 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_RTR0PROCESS
+ * is an alias for the current one.
+ * @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) RTR0MemObjMapUserExTag(PRTR0MEMOBJ pMemObj, RTR0MEMOBJ MemObjToMap, RTR3PTR R3PtrFixed, size_t uAlignment,
+ unsigned fProt, RTR0PROCESS R0Process, size_t offSub, size_t cbSub, 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 /* !IPRT_INCLUDED_memobj_h */
+
diff --git a/include/iprt/mempool.h b/include/iprt/mempool.h
new file mode 100644
index 00000000..2073a6dd
--- /dev/null
+++ b/include/iprt/mempool.h
@@ -0,0 +1,178 @@
+/** @file
+ * IPRT - Memory Allocation Pool.
+ */
+
+/*
+ * Copyright (C) 2009-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_mempool_h
+#define IPRT_INCLUDED_mempool_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+
+RT_C_DECLS_BEGIN
+
+/**
+ * Creates a new memory pool.
+ *
+ * @returns IPRT status code.
+ *
+ * @param phMemPool Where to return the handle to the new memory
+ * pool.
+ * @param pszName The name of the pool (for debug purposes).
+ */
+RTDECL(int) RTMemPoolCreate(PRTMEMPOOL phMemPool, const char *pszName);
+
+/**
+ * Destroys the specified pool, freeing all the memory it contains.
+ *
+ * @returns IPRT status code.
+ *
+ * @param hMemPool The handle to the pool. The nil handle and
+ * RTMEMPOOL_DEFAULT are quietly ignored (retval
+ * VINF_SUCCESS).
+ */
+RTDECL(int) RTMemPoolDestroy(RTMEMPOOL hMemPool);
+
+/**
+ * Allocates memory.
+ *
+ * @returns Pointer to the allocated memory.
+ * @returns NULL on failure.
+ *
+ * @param hMemPool Handle to the pool to allocate the memory from.
+ * @param cb Size in bytes of the memory block to allocated.
+ */
+RTDECL(void *) RTMemPoolAlloc(RTMEMPOOL hMemPool, size_t cb) RT_NO_THROW_PROTO;
+
+/**
+ * Allocates zero'd memory.
+ *
+ * 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 hMemPool Handle to the pool to allocate the memory from.
+ * @param cb Size in bytes of the memory block to allocated.
+ */
+RTDECL(void *) RTMemPoolAllocZ(RTMEMPOOL hMemPool, size_t cb) RT_NO_THROW_PROTO;
+
+/**
+ * Duplicates a chunk of memory into a new heap block.
+ *
+ * @returns New heap block with the duplicate data.
+ * @returns NULL if we're out of memory.
+ *
+ * @param hMemPool Handle to the pool to allocate the memory from.
+ * @param pvSrc The memory to duplicate.
+ * @param cb The amount of memory to duplicate.
+ */
+RTDECL(void *) RTMemPoolDup(RTMEMPOOL hMemPool, const void *pvSrc, size_t cb) RT_NO_THROW_PROTO;
+
+/**
+ * Duplicates a chunk of memory into a new heap block with some
+ * additional zeroed memory.
+ *
+ * @returns New heap block with the duplicate data.
+ * @returns NULL if we're out of memory.
+ *
+ * @param hMemPool Handle to the pool to allocate the memory from.
+ * @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.
+ */
+RTDECL(void *) RTMemPoolDupEx(RTMEMPOOL hMemPool, const void *pvSrc, size_t cbSrc, size_t cbExtra) RT_NO_THROW_PROTO;
+
+/**
+ * Reallocates memory.
+ *
+ * @returns Pointer to the allocated memory.
+ * @returns NULL on failure.
+ *
+ * @param hMemPool Handle to the pool containing the old memory.
+ * @param pvOld The memory block to reallocate.
+ * @param cbNew The new block size (in bytes).
+ */
+RTDECL(void *) RTMemPoolRealloc(RTMEMPOOL hMemPool, void *pvOld, size_t cbNew) RT_NO_THROW_PROTO;
+
+/**
+ * Frees memory allocated from a pool.
+ *
+ * @param hMemPool Handle to the pool containing the memory. Passing
+ * NIL here is fine, but it may come at a slight
+ * performance cost.
+ * @param pv Pointer to memory block.
+ *
+ * @remarks This is the same a RTMemPoolRelease but included here as a separate
+ * function to simplify code migration.
+ */
+RTDECL(void) RTMemPoolFree(RTMEMPOOL hMemPool, void *pv) RT_NO_THROW_PROTO;
+
+/**
+ * Retains a reference to a memory block in a pool.
+ *
+ * @returns New reference count, UINT32_MAX on error (asserted).
+ *
+ * @param pv Pointer to memory block.
+ */
+RTDECL(uint32_t) RTMemPoolRetain(void *pv) RT_NO_THROW_PROTO;
+
+/**
+ * Releases a reference to a memory block in a pool.
+ *
+ * @returns New reference count, UINT32_MAX on error (asserted).
+ *
+ * @param hMemPool Handle to the pool containing the memory. Passing
+ * NIL here is fine, but it may come at a slight
+ * performance cost.
+ * @param pv Pointer to memory block.
+ */
+RTDECL(uint32_t) RTMemPoolRelease(RTMEMPOOL hMemPool, void *pv) RT_NO_THROW_PROTO;
+
+/**
+ * Get the current reference count.
+ *
+ * @returns The reference count, UINT32_MAX on error (asserted).
+ * @param pv Pointer to memory block.
+ */
+RTDECL(uint32_t) RTMemPoolRefCount(void *pv) RT_NO_THROW_PROTO;
+
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_mempool_h */
+
diff --git a/include/iprt/memsafer.h b/include/iprt/memsafer.h
new file mode 100644
index 00000000..cc9545bf
--- /dev/null
+++ b/include/iprt/memsafer.h
@@ -0,0 +1,270 @@
+/** @file
+ * IPRT - Memory Allocate for Sensitive Data.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_memsafer_h
+#define IPRT_INCLUDED_memsafer_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/mem.h> /* RTMEM_TAG */
+
+RT_C_DECLS_BEGIN
+
+
+/** @defgroup grp_rt_memsafer RTMemSafer - Memory Allocator for Sensitive Data
+ * @ingroup grp_rt
+ *
+ * This API doesn't provide 100% secure storage, it only provider more secure
+ * and safer storage. Thus the API isn't called RTMemSafe because you cannot
+ * assume the data is safe against all kinds of extraction methods.
+ *
+ * The API guarantee that the memory won't be returned to the system containing
+ * any of the information you put there. It will be repeatedly wiped after use.
+ *
+ * The API tries to isolate your data from other information stored in the
+ * process/system. How well this is done depends on the implementation. The
+ * more complicated implementations will provide protection against heartbleed
+ * like bugs where pieces of the heap is copied onto the wire.
+ *
+ * The more hardened implementations of the API will also do their best to
+ * prevent the memory from ending up in process dumps or being readable by
+ * debuggers.
+ *
+ * Finally, two functions are provided for scrambling the sensitive memory while
+ * it's not in use.
+ *
+ * @{
+ */
+
+/** @name RTMEMSAFER_F_XXX
+ * @{ */
+/** Require the memory to not hit the page file.
+ * @remarks Makes not guarantees with regards to hibernation /
+ * suspend-to-disk. */
+#define RTMEMSAFER_F_REQUIRE_NOT_PAGABLE RT_BIT_32(0)
+/** Mask of valid bits. */
+#define RTMEMSAFER_F_VALID_MASK UINT32_C(0x00000001)
+/** @} */
+
+/**
+ * Scrambles memory allocated by RTMemSaferAllocZEx and associates after use.
+ *
+ * Call this when the sensitive data isn't actively being used. It will at a
+ * minimum make sure the data is slightly scrambled, how hard it is to unbutton
+ * is dependent on which implementation is used and available host support.
+ *
+ * The user must synchronize calls to RTMemSaferScramble and
+ * RTMemSaferUnscramble, this memory allocator provides no help and keeps no
+ * state information around.
+ *
+ * @returns IPRT status code.
+ * @param pv The pointer returned by the allocation function.
+ * @param cb The exact size given to the allocation function.
+ */
+RTDECL(int) RTMemSaferScramble(void *pv, size_t cb);
+
+/**
+ * Unscrambles memory allocated by RTMemSaferAllocZEx and associates before use.
+ *
+ * This undoes the effect of RTMemSaferScramble.
+ *
+ * @returns IPRT status code.
+ * @param pv The pointer returned by the allocation function.
+ * @param cb The exact size given to the allocation function.
+ */
+RTDECL(int) RTMemSaferUnscramble(void *pv, size_t cb);
+
+/**
+ * Allocates memory for sensitive data.
+ *
+ * Some effort will be taken to isolate the data from other memory allocation.
+ * Memory is always zeroed.
+ *
+ * @returns IPRT status code.
+ * @param ppvNew Where to return the pointer to the memory.
+ * @param cb Number of bytes to allocate.
+ * @param fFlags Flags for controlling the allocation, see
+ * RTMEMSAFER_F_XXX.
+ * @param pszTag Allocation tag used for statistics and such.
+ */
+RTDECL(int) RTMemSaferAllocZExTag(void **ppvNew, size_t cb, uint32_t fFlags, const char *pszTag) RT_NO_THROW_PROTO;
+
+/**
+ * Allocates memory for sensitive data.
+ *
+ * Some effort will be taken to isolate the data from other memory allocation.
+ * Memory is always zeroed.
+ *
+ * @returns IPRT status code.
+ * @param a_ppvNew Where to return the pointer to the memory.
+ * @param a_cb Number of bytes to allocate.
+ * @param a_fFlags Flags for controlling the allocation, see
+ * RTMEMSAFER_F_XXX.
+ */
+#define RTMemSaferAllocZEx(a_ppvNew, a_cb, a_fFlags) RTMemSaferAllocZExTag(a_ppvNew, a_cb, a_fFlags, RTMEM_TAG)
+
+/**
+ * Allocates memory for sensitive data.
+ *
+ * Some effort will be taken to isolate the data from other memory allocation.
+ * Memory is always zeroed.
+ *
+ * @returns Pointer to the allocated memory.
+ * @param cb Number of bytes to allocate.
+ * @param pszTag Allocation tag used for statistics and such.
+ */
+RTDECL(void *) RTMemSaferAllocZTag(size_t cb, const char *pszTag) RT_NO_THROW_PROTO;
+
+/**
+ * Allocates memory for sensitive data.
+ *
+ * Some effort will be taken to isolate the data from other memory allocation.
+ * Memory is always zeroed.
+ *
+ * @returns Pointer to the allocated memory.
+ * @param a_cb Number of bytes to allocate.
+ */
+#define RTMemSaferAllocZ(a_cb) RTMemSaferAllocZTag(a_cb, RTMEM_TAG)
+
+
+/**
+ * Reallocates memory allocated by RTMemSaferAllocZEx, RTMemSaferAllocZ,
+ * RTMemSaferAllocZExTag, or RTMemSaferAllocZTag.
+ *
+ * When extending the allocation, the new memory will be zeroed. When shrinking
+ * the allocation the left over memory will be wiped clean using
+ * RTMemWipeThorougly.
+ *
+ * The function follows the standard realloc behavior.
+ *
+ * @returns IPRT status code.
+ * @param cbOld The current allocation size.
+ * @param pvOld The current allocation.
+ * @param cbNew The size of the new allocation.
+ * @param ppvNew Where to return the pointer to the new memory.
+ * @param fFlags Flags for controlling the allocation, see
+ * RTMEMSAFER_F_XXX. It is not permitted to drop saftely
+ * requirments after the initial allocation.
+ * @param pszTag Allocation tag used for statistics and such.
+ */
+RTDECL(int) RTMemSaferReallocZExTag(size_t cbOld, void *pvOld, size_t cbNew, void **ppvNew, uint32_t fFlags, const char *pszTag) RT_NO_THROW_PROTO;
+
+/**
+ * Reallocates memory allocated by RTMemSaferAllocZEx, RTMemSaferAllocZ,
+ * RTMemSaferAllocZExTag, or RTMemSaferAllocZTag.
+ *
+ * When extending the allocation, the new memory will be zeroed. When shrinking
+ * the allocation the left over memory will be wiped clean using
+ * RTMemWipeThorougly.
+ *
+ * The function follows the standard realloc behavior.
+ *
+ * @returns IPRT status code.
+ * @param a_cbOld The current allocation size.
+ * @param a_pvOld The current allocation.
+ * @param a_cbNew The size of the new allocation.
+ * @param a_ppvNew Where to return the pointer to the new memory.
+ * @param a_fFlags Flags for controlling the allocation. See RTMEMSAFER_ALLOC_EX_FLAGS_* defines,
+ * this takes only effect when allocating completely new memory, for extending or
+ * shrinking existing allocations the flags of the allocation take precedence.
+ */
+#define RTMemSaferReallocZEx(a_cbOld, a_pvOld, a_cbNew, a_ppvNew, a_fFlags) \
+ RTMemSaferReallocZExTag(a_cbOld, a_pvOld, a_cbNew, a_ppvNew, a_fFlags, RTMEM_TAG)
+
+/**
+ * Reallocates memory allocated by RTMemSaferAllocZ or RTMemSaferAllocZTag.
+ *
+ * When extending the allocation, the new memory will be zeroed. When shrinking
+ * the allocation the left over memory will be wiped clean using
+ * RTMemWipeThorougly.
+ *
+ * The function follows the standard realloc behavior.
+ *
+ * @returns Pointer to the allocated memory.
+ * @param cbOld The current allocation size.
+ * @param pvOld The current allocation.
+ * @param cbNew The size of the new allocation.
+ * @param pszTag Allocation tag used for statistics and such.
+ */
+RTDECL(void *) RTMemSaferReallocZTag(size_t cbOld, void *pvOld, size_t cbNew, const char *pszTag) RT_NO_THROW_PROTO;
+
+/**
+ * Reallocates memory allocated by RTMemSaferAllocZ or RTMemSaferAllocZTag.
+ *
+ * When extending the allocation, the new memory will be zeroed. When shrinking
+ * the allocation the left over memory will be wiped clean using
+ * RTMemWipeThorougly.
+ *
+ * The function follows the standard realloc behavior.
+ *
+ * @returns Pointer to the allocated memory.
+ * @param a_cbOld The current allocation size.
+ * @param a_pvOld The current allocation.
+ * @param a_cbNew The size of the new allocation.
+ */
+#define RTMemSaferReallocZ(a_cbOld, a_pvOld, a_cbNew) RTMemSaferReallocZTag(a_cbOld, a_pvOld, a_cbNew, RTMEM_TAG)
+
+
+/**
+ * Frees memory allocated by RTMemSaferAllocZ* or RTMemSaferReallocZ*.
+ *
+ * Before freeing the allocated memory, it will be wiped clean using
+ * RTMemWipeThorougly.
+ *
+ * @returns Pointer to the allocated memory.
+ * @param pv The allocation.
+ * @param cb The allocation size.
+ */
+RTDECL(void) RTMemSaferFree(void *pv, size_t cb) RT_NO_THROW_PROTO;
+
+/**
+ * Gets the amount of memory allocated at @a pv.
+ *
+ * This can be used to check if the allocation was made using an RTMemSafer API.
+ *
+ * @returns Allocation size in bytes, 0 if not a RTMemSafer allocation.
+ * @param pv The alleged RTMemSafer allocation.
+ *
+ * @note Not supported in all contexts and implementations of the API.
+ */
+RTDECL(size_t) RTMemSaferGetSize(void *pv) RT_NO_THROW_PROTO;
+
+
+/** @} */
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_memsafer_h */
+
diff --git a/include/iprt/memtracker.h b/include/iprt/memtracker.h
new file mode 100644
index 00000000..cd3eff0b
--- /dev/null
+++ b/include/iprt/memtracker.h
@@ -0,0 +1,257 @@
+/** @file
+ * IPRT - Memory Tracker.
+ */
+
+/*
+ * Copyright (C) 2010-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_memtracker_h
+#define IPRT_INCLUDED_memtracker_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+#include <iprt/list.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_memtracker RTMemTracker - Memory Allocation Tracker.
+ * @ingroup grp_rt
+ * @{
+ */
+
+/**
+ * The allocation/free method.
+ */
+typedef enum RTMEMTRACKERMETHOD
+{
+ RTMEMTRACKERMETHOD_INVALID = 0,
+ RTMEMTRACKERMETHOD_ALLOC,
+ RTMEMTRACKERMETHOD_ALLOCZ,
+ RTMEMTRACKERMETHOD_REALLOC_PREP, /**< Internal, don't use. */
+ RTMEMTRACKERMETHOD_REALLOC_DONE, /**< Internal, don't use. */
+ RTMEMTRACKERMETHOD_REALLOC_FAILED, /**< Internal, don't use. */
+ RTMEMTRACKERMETHOD_FREE,
+
+ RTMEMTRACKERMETHOD_NEW,
+ RTMEMTRACKERMETHOD_NEW_ARRAY,
+ RTMEMTRACKERMETHOD_DELETE,
+ RTMEMTRACKERMETHOD_DELETE_ARRAY,
+ RTMEMTRACKERMETHOD_END,
+ RTMEMTRACKERMETHOD_32BIT_HACK = 0x7fffffff
+} RTMEMTRACKERMETHOD;
+
+/** Pointer to a tag structure. */
+typedef struct RTMEMTRACKERTAG *PRTMEMTRACKERTAG;
+
+/** Pointer to a user structure. */
+typedef struct RTMEMTRACKERUSER *PRTMEMTRACKERUSER;
+
+/**
+ * Memory Tracking Header for use with RTMemTrackerHdrAlloc,
+ * RTMemTrackerHdrReallocPrep, RTMemTrackerHdrReallocDone and
+ * RTMemTrackerHdrFree.
+ */
+typedef struct RTMEMTRACKERHDR
+{
+ /** Magic value / eye catcher (RTMEMTRACKERHDR_MAGIC). */
+ size_t uMagic;
+ /** The allocation size, user data only. */
+ size_t cbUser;
+ /** The list entry. */
+ RTLISTNODE ListEntry;
+ /** Pointer to the user structure where this header is linked. */
+ PRTMEMTRACKERUSER pUser;
+ /** Pointer to the per-tag structure. */
+ PRTMEMTRACKERTAG pTag;
+ /** The tag string. */
+ const char *pszTag;
+ /** The caller address. */
+ void *pvCaller;
+ /** Pointer to the user data we're tracking. */
+ void *pvUser;
+ /** Alignment padding. */
+ size_t uReserved;
+} RTMEMTRACKERHDR;
+/** Pointer to a memory tracker header. */
+typedef RTMEMTRACKERHDR *PRTMEMTRACKERHDR;
+/** Pointer to a const memory tracker header. */
+typedef RTMEMTRACKERHDR *PPRTMEMTRACKERHDR;
+
+/** Magic value for RTMEMTRACKERHDR::uMagic (Kelly Link). */
+#if ARCH_BITS == 64
+# define RTMEMTRACKERHDR_MAGIC UINT64_C(0x1907691919690719)
+#else
+# define RTMEMTRACKERHDR_MAGIC UINT32_C(0x19690719)
+#endif
+/** Magic number used when reallocated. */
+#if ARCH_BITS == 64
+# define RTMEMTRACKERHDR_MAGIC_REALLOC UINT64_C(0x0000691919690000)
+#else
+# define RTMEMTRACKERHDR_MAGIC_REALLOC UINT32_C(0x19690000)
+#endif
+/** Magic number used when freed. */
+#define RTMEMTRACKERHDR_MAGIC_FREE (~RTMEMTRACKERHDR_MAGIC)
+
+
+/**
+ * Initializes the allocation header and links it to the relevant tag.
+ *
+ * @returns Pointer to the user data part.
+ * @param pv The header + user data block. This must be at
+ * least @a cb + sizeof(RTMEMTRACKERHDR).
+ * @param cbUser The user data size (bytes).
+ * @param pszTag The tag string.
+ * @param pvCaller The return address.
+ * @param enmMethod The method that the user called.
+ */
+RTDECL(void *) RTMemTrackerHdrAlloc(void *pv, size_t cbUser, const char *pszTag, void *pvCaller, RTMEMTRACKERMETHOD enmMethod);
+
+/**
+ * Prepares for a realloc, i.e. invalidates the header.
+ *
+ * @returns Pointer to the user data part.
+ * @param pvOldUser Pointer to the old user data.
+ * @param cbOldUser The size of the old user data, 0 if not
+ * known.
+ * @param pszTag The tag string.
+ * @param pvCaller The return address.
+ */
+RTDECL(void *) RTMemTrackerHdrReallocPrep(void *pvOldUser, size_t cbOldUser, const char *pszTag, void *pvCaller);
+
+/**
+ * Initializes the allocation header and links it to the relevant tag.
+ *
+ * @returns Pointer to the user data part.
+ * @param pvNew The new header + user data block. This must be
+ * at least @a cb + sizeof(RTMEMTRACKERHDR). If
+ * this is NULL, we assume the realloc() call
+ * failed.
+ * @param cbNewUser The user data size (bytes).
+ * @param pvOldUser Pointer to the old user data. This is only
+ * valid on failure of course and used to bail out
+ * in that case. Should not be NULL.
+ * @param pszTag The tag string.
+ * @param pvCaller The return address.
+ */
+RTDECL(void *) RTMemTrackerHdrReallocDone(void *pvNew, size_t cbNewUser, void *pvOldUser, const char *pszTag, void *pvCaller);
+
+
+/**
+ * Do the accounting on free.
+ *
+ * @returns @a pv.
+ * @param pvUser Pointer to the user data.
+ * @param cbUser The size of the user data, 0 if not known.
+ * @param pszTag The tag string.
+ * @param pvCaller The return address.
+ * @param enmMethod The method that the user called.
+ */
+RTDECL(void *) RTMemTrackerHdrFree(void *pvUser, size_t cbUser, const char *pszTag, void *pvCaller, RTMEMTRACKERMETHOD enmMethod);
+
+
+/**
+ * Dumps all the allocations and tag statistics to the log.
+ */
+RTDECL(void) RTMemTrackerDumpAllToLog(void);
+
+/**
+ * Dumps all the allocations and tag statistics to the release log.
+ */
+RTDECL(void) RTMemTrackerDumpAllToLogRel(void);
+
+/**
+ * Dumps all the allocations and tag statistics to standard out.
+ */
+RTDECL(void) RTMemTrackerDumpAllToStdOut(void);
+
+/**
+ * Dumps all the allocations and tag statistics to standard err.
+ */
+RTDECL(void) RTMemTrackerDumpAllToStdErr(void);
+
+/**
+ * Dumps all the allocations and tag statistics to the specified filename.
+ */
+RTDECL(void) RTMemTrackerDumpAllToFile(const char *pszFilename);
+
+
+/**
+ * Dumps all the tag statistics to the log.
+ *
+ * @param fVerbose Whether to print all the stats or just the ones
+ * relevant to hunting leaks.
+ */
+RTDECL(void) RTMemTrackerDumpStatsToLog(bool fVerbose);
+
+/**
+ * Dumps all the tag statistics to the release log.
+ *
+ * @param fVerbose Whether to print all the stats or just the ones
+ * relevant to hunting leaks.
+ */
+RTDECL(void) RTMemTrackerDumpStatsToLogRel(bool fVerbose);
+
+/**
+ * Dumps all the tag statistics to standard out.
+ *
+ * @param fVerbose Whether to print all the stats or just the ones
+ * relevant to hunting leaks.
+ */
+RTDECL(void) RTMemTrackerDumpStatsToStdOut(bool fVerbose);
+
+/**
+ * Dumps all the tag statistics to standard err.
+ *
+ * @param fVerbose Whether to print all the stats or just the ones
+ * relevant to hunting leaks.
+ */
+RTDECL(void) RTMemTrackerDumpStatsToStdErr(bool fVerbose);
+
+/**
+ * Dumps all the tag statistics to the specified filename.
+ *
+ * @param fVerbose Whether to print all the stats or just the ones
+ * relevant to hunting leaks.
+ * @param pszFilename The name of the file to dump to.
+ */
+RTDECL(void) RTMemTrackerDumpStatsToFile(bool fVerbose, const char *pszFilename);
+
+
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_memtracker_h */
+
diff --git a/include/iprt/message.h b/include/iprt/message.h
new file mode 100644
index 00000000..b5a912c7
--- /dev/null
+++ b/include/iprt/message.h
@@ -0,0 +1,394 @@
+/** @file
+ * IPRT - Message Formatting.
+ */
+
+/*
+ * Copyright (C) 2009-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_message_h
+#define IPRT_INCLUDED_message_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+#include <iprt/stdarg.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_msg RTMsg - Message Formatting
+ * @ingroup grp_rt
+ * @{
+ */
+
+/**
+ * Sets the program name to use.
+ *
+ * @returns IPRT status code.
+ * @param pszFormat The program name format string.
+ * @param ... Format arguments.
+ */
+RTDECL(int) RTMsgSetProgName(const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(1, 2);
+
+/**
+ * Print error message to standard error.
+ *
+ * The message will be prefixed with the file name part of process image name
+ * (i.e. no path) and "error: ". If the message doesn't end with a new line,
+ * one will be added. The caller should call this with an empty string if
+ * unsure whether the cursor is currently position at the start of a new line.
+ *
+ * @returns IPRT status code.
+ * @param pszFormat The message format string.
+ * @param ... Format arguments.
+ */
+RTDECL(int) RTMsgError(const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(1, 2);
+
+/**
+ * Print error message to standard error.
+ *
+ * The message will be prefixed with the file name part of process image name
+ * (i.e. no path) and "error: ". If the message doesn't end with a new line,
+ * one will be added. The caller should call this with an empty string if
+ * unsure whether the cursor is currently position at the start of a new line.
+ *
+ * @returns IPRT status code.
+ * @param pszFormat The message format string.
+ * @param va Format arguments.
+ */
+RTDECL(int) RTMsgErrorV(const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(1, 0);
+
+/**
+ * Same as RTMsgError() except for the return value.
+ *
+ * @returns @a enmExitCode
+ * @param enmExitCode What to exit code to return. This is mainly for
+ * saving some vertical space in the source file.
+ * @param pszFormat The message format string.
+ * @param ... Format arguments.
+ */
+RTDECL(RTEXITCODE) RTMsgErrorExit(RTEXITCODE enmExitCode, const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(2, 3);
+
+/**
+ * Same as RTMsgErrorV() except for the return value.
+ *
+ * @returns @a enmExitCode
+ * @param enmExitCode What to exit code to return. This is mainly for
+ * saving some vertical space in the source file.
+ * @param pszFormat The message format string.
+ * @param va Format arguments.
+ */
+RTDECL(RTEXITCODE) RTMsgErrorExitV(RTEXITCODE enmExitCode, const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(2, 0);
+
+/**
+ * Same as RTMsgError() except for always returning RTEXITCODE_FAILURE.
+ *
+ * @returns RTEXITCODE_FAILURE
+ * @param pszFormat The message format string.
+ * @param ... Format arguments.
+ */
+RTDECL(RTEXITCODE) RTMsgErrorExitFailure(const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(1, 2);
+
+/**
+ * Same as RTMsgErrorV() except for always returning RTEXITCODE_FAILURE.
+ *
+ * @returns RTEXITCODE_FAILURE
+ * @param pszFormat The message format string.
+ * @param va Format arguments.
+ */
+RTDECL(RTEXITCODE) RTMsgErrorExitFailureV(const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(1, 0);
+
+/**
+ * Same as RTMsgError() except for the return value.
+ *
+ * @returns @a rcRet
+ * @param rcRet What IPRT status to return. This is mainly for
+ * saving some vertical space in the source file.
+ * @param pszFormat The message format string.
+ * @param ... Format arguments.
+ */
+RTDECL(int) RTMsgErrorRc(int rcRet, const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(2, 3);
+
+/**
+ * Same as RTMsgErrorV() except for the return value.
+ *
+ * @returns @a rcRet
+ * @param rcRet What IPRT status to return. This is mainly for
+ * saving some vertical space in the source file.
+ * @param pszFormat The message format string.
+ * @param va Format arguments.
+ */
+RTDECL(int) RTMsgErrorRcV(int rcRet, const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(2, 0);
+
+/**
+ * For reporting syntax errors.
+ *
+ * @returns RTEXITCODE_SYNTAX
+ * @param pszFormat The message format string. Newline not needed.
+ * @param ... Format arguments.
+ */
+RTDECL(RTEXITCODE) RTMsgSyntax(const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(1, 2);
+
+/**
+ * For reporting syntax errors.
+ *
+ * @returns RTEXITCODE_SYNTAX
+ * @param pszFormat The message format string. Newline not needed.
+ * @param va Format arguments.
+ */
+RTDECL(RTEXITCODE) RTMsgSyntaxV(const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(1, 0);
+
+/**
+ * Print an error message for a RTR3Init failure and suggest an exit code.
+ *
+ * @code
+ *
+ * int rc = RTR3Init();
+ * if (RT_FAILURE(rc))
+ * return RTMsgInitFailure(rc);
+ *
+ * @endcode
+ *
+ * @returns Appropriate exit code.
+ * @param rcRTR3Init The status code returned by RTR3Init.
+ */
+RTDECL(RTEXITCODE) RTMsgInitFailure(int rcRTR3Init);
+
+/**
+ * Print informational message to standard error.
+ *
+ * The message will be prefixed with the file name part of process image name
+ * (i.e. no path) and "warning: ". If the message doesn't end with a new line,
+ * one will be added. The caller should call this with an empty string if
+ * unsure whether the cursor is currently position at the start of a new line.
+ *
+ * @returns IPRT status code.
+ * @param pszFormat The message format string.
+ * @param ... Format arguments.
+ */
+RTDECL(int) RTMsgWarning(const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(1, 2);
+
+/**
+ * Print informational message to standard error.
+ *
+ * The message will be prefixed with the file name part of process image name
+ * (i.e. no path) and "warning: ". If the message doesn't end with a new line,
+ * one will be added. The caller should call this with an empty string if
+ * unsure whether the cursor is currently position at the start of a new line.
+ *
+ * @returns IPRT status code.
+ * @param pszFormat The message format string.
+ * @param va Format arguments.
+ */
+RTDECL(int) RTMsgWarningV(const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(1, 0);
+
+/**
+ * Print informational message to standard output.
+ *
+ * The message will be prefixed with the file name part of process image name
+ * (i.e. no path) and "info: ". If the message doesn't end with a new line,
+ * one will be added. The caller should call this with an empty string if
+ * unsure whether the cursor is currently position at the start of a new line.
+ *
+ * @returns IPRT status code.
+ * @param pszFormat The message format string.
+ * @param ... Format arguments.
+ */
+RTDECL(int) RTMsgInfo(const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(1, 2);
+
+/**
+ * Print informational message to standard output.
+ *
+ * The message will be prefixed with the file name part of process image name
+ * (i.e. no path) and "info: ". If the message doesn't end with a new line,
+ * one will be added. The caller should call this with an empty string if
+ * unsure whether the cursor is currently position at the start of a new line.
+ *
+ * @returns IPRT status code.
+ * @param pszFormat The message format string.
+ * @param va Format arguments.
+ */
+RTDECL(int) RTMsgInfoV(const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(1, 0);
+
+
+
+/** @defgroup grp_rt_msg_refentry Help generated from refentry/manpage.
+ *
+ * The refentry/manpage docbook source in doc/manual/en_US/man_* is processed by
+ * doc/manual/docbook-refentry-to-C-help.xsl and turned a set of the structures
+ * defined here.
+ *
+ * @{
+ */
+
+/** The non-breaking space character.
+ * @remarks We could've used U+00A0, but it is easier both to encode and to
+ * search and replace a single ASCII character. */
+#define RTMSGREFENTRY_NBSP '\b'
+
+/** @name REFENTRYSTR_SCOPE_XXX - Common string scoping and flags.
+ * @{ */
+/** Same scope as previous string table entry, flags are reset and can be
+ * ORed in. */
+#define RTMSGREFENTRYSTR_SCOPE_SAME UINT64_C(0)
+/** Global scope. */
+#define RTMSGREFENTRYSTR_SCOPE_GLOBAL UINT64_C(0x0fffffffffffffff)
+/** Scope mask. */
+#define RTMSGREFENTRYSTR_SCOPE_MASK UINT64_C(0x0fffffffffffffff)
+/** Flags mask. */
+#define RTMSGREFENTRYSTR_FLAGS_MASK UINT64_C(0xf000000000000000)
+/** Command synopsis, special hanging indent rules applies. */
+#define RTMSGREFENTRYSTR_FLAGS_SYNOPSIS RT_BIT_64(63)
+/** @} */
+
+/** String table entry for a refentry. */
+typedef struct RTMSGREFENTRYSTR
+{
+ /** The scope of the string. There are two predefined scopes,
+ * REFENTRYSTR_SCOPE_SAME and REFENTRYSTR_SCOPE_GLOBAL. The rest are
+ * reference entry specific. */
+ uint64_t fScope;
+ /** The string. Non-breaking space is represented by the char
+ * REFENTRY_NBSP defines, just in case the string needs wrapping. There is
+ * no trailing newline, that's implicit. */
+ const char *psz;
+} RTMSGREFENTRYSTR;
+/** Pointer to a read-only string table entry. */
+typedef const RTMSGREFENTRYSTR *PCRTMSGREFENTRYSTR;
+
+/** Refentry string table. */
+typedef struct RTMSGREFENTRYSTRTAB
+{
+ /** Number of strings. */
+ uint16_t cStrings;
+ /** Reserved for future use. */
+ uint16_t fReserved;
+ /** Pointer to the string table. */
+ PCRTMSGREFENTRYSTR paStrings;
+} RTMSGREFENTRYSTRTAB;
+/** Pointer to a read-only string table. */
+typedef RTMSGREFENTRYSTRTAB const *PCRTMSGREFENTRYSTRTAB;
+
+/**
+ * Help extracted from a docbook refentry document.
+ */
+typedef struct RTMSGREFENTRY
+{
+ /** Internal reference entry identifier. */
+ int64_t idInternal;
+ /** Usage synopsis. */
+ RTMSGREFENTRYSTRTAB Synopsis;
+ /** Full help. */
+ RTMSGREFENTRYSTRTAB Help;
+ /** Brief command description. */
+ const char *pszBrief;
+} RTMSGREFENTRY;
+/** Pointer to a read-only refentry help extract structure. */
+typedef RTMSGREFENTRY const *PCRTMSGREFENTRY;
+
+
+#ifndef IPRT_INCLUDED_stream_h
+typedef struct RTSTREAM *PRTSTREAM;
+#endif
+
+
+/**
+ * Print the synopsis to the given stream.
+ *
+ * @returns Current number of pending blank lines.
+ * @param pStrm The output stream.
+ * @param pEntry The refentry to print the help for.
+ */
+RTDECL(int) RTMsgRefEntrySynopsis(PRTSTREAM pStrm, PCRTMSGREFENTRY pEntry);
+
+
+/**
+ * Print the synopsis to the given stream.
+ *
+ * @returns Current number of pending blank lines.
+ * @param pStrm The output stream.
+ * @param pEntry The refentry to print the help for.
+ * @param fScope The scope inclusion mask.
+ * @param fFlags RTMSGREFENTRY_SYNOPSIS_F_XXX.
+ */
+RTDECL(int) RTMsgRefEntrySynopsisEx(PRTSTREAM pStrm, PCRTMSGREFENTRY pEntry, uint64_t fScope, uint32_t fFlags);
+/** @name RTMSGREFENTRY_SYNOPSIS_F_XXX - Flags for RTMsgRefEntrySynopsisEx.
+ * @{ */
+/** Prefix the output with 'Usage:'. */
+#define RTMSGREFENTRY_SYNOPSIS_F_USAGE RT_BIT_32(0)
+/** @} */
+
+
+/**
+ * Print the help text to the given stream.
+ *
+ * @returns Current number of pending blank lines.
+ * @param pStrm The output stream.
+ * @param pEntry The refentry to print the help for.
+ */
+RTDECL(int) RTMsgRefEntryHelp(PRTSTREAM pStrm, PCRTMSGREFENTRY pEntry);
+
+/**
+ * Print the help text to the given stream, extended version.
+ *
+ * @returns Current number of pending blank lines.
+ * @param pStrm The output stream.
+ * @param pEntry The refentry to print the help for.
+ * @param fScope The scope inclusion mask.
+ * @param fFlags Reserved, MBZ.
+ */
+RTDECL(int) RTMsgRefEntryHelpEx(PRTSTREAM pStrm, PCRTMSGREFENTRY pEntry, uint64_t fScope, uint32_t fFlags);
+
+/**
+ * Prints a string table.
+ *
+ * @returns Current number of pending blank lines.
+ * @param pStrm The output stream.
+ * @param pStrTab The string table.
+ * @param fScope The selection scope.
+ * @param pcPendingBlankLines In: Pending blank lines from previous string
+ * table. Out: Pending blank lines.
+ * @param pcLinesWritten Pointer to variable that should be incremented
+ * by the number of lines written. Optional.
+ */
+RTDECL(int) RTMsgRefEntryPrintStringTable(PRTSTREAM pStrm, PCRTMSGREFENTRYSTRTAB pStrTab, uint64_t fScope,
+ uint32_t *pcPendingBlankLines, uint32_t *pcLinesWritten);
+
+/** @} */
+
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_message_h */
+
diff --git a/include/iprt/mp.h b/include/iprt/mp.h
new file mode 100644
index 00000000..e418bceb
--- /dev/null
+++ b/include/iprt/mp.h
@@ -0,0 +1,521 @@
+/** @file
+ * IPRT - Multiprocessor.
+ */
+
+/*
+ * Copyright (C) 2008-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_mp_h
+#define IPRT_INCLUDED_mp_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#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 DECLCALLBACKTYPE(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 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 DECLCALLBACKTYPE(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 /* !IPRT_INCLUDED_mp_h */
+
diff --git a/include/iprt/net.h b/include/iprt/net.h
new file mode 100644
index 00000000..647c15c3
--- /dev/null
+++ b/include/iprt/net.h
@@ -0,0 +1,1064 @@
+/** @file
+ * IPRT - Network Protocols.
+ */
+
+/*
+ * Copyright (C) 2008-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_net_h
+#define IPRT_INCLUDED_net_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#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);
+
+/**
+ * Parses dotted-decimal IPv4 CIDR notation into RTNETADDRIPV4
+ * representation and prefix length. Missing prefix specification is
+ * treated as exact address specification (prefix length 32). 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 address.
+ * @param piPrefix Where to store the prefix length;
+ */
+RTDECL(int) RTNetStrToIPv4Cidr(const char *pcszAddr, PRTNETADDRIPV4 pAddr, int *piPrefix);
+
+/**
+ * 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);
+
+/**
+ * Parses IPv6 prefix notation into RTNETADDRIPV6 representation and
+ * prefix length. Missing prefix specification is treated as exact
+ * address specification (prefix length 128). Leading and trailing
+ * whitespace is ignored.
+ *
+ * "CIDR" in the name is a misnomer as IPv6 doesn't have network
+ * classes, but is parallel to the IPv4 name (and naming things is
+ * hard).
+ *
+ * @returns VINF_SUCCESS on success, VERR_INVALID_PARAMETER on
+ * failure.
+ *
+ * @param pcszAddr The value to convert.
+ * @param pAddr Where to store the address.
+ * @param piPrefix Where to store the prefix length;
+ */
+RTDECL(int) RTNetStrToIPv6Cidr(const char *pcszAddr, PRTNETADDRIPV6 pAddr, int *piPrefix);
+
+
+/**
+ * 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 Option overload flags (option 52)
+ * @{ */
+#define RTNET_DHCP_OPTION_OVERLOAD_FILE 1
+#define RTNET_DHCP_OPTION_OVERLOAD_SNAME 2
+#define RTNET_DHCP_OPTION_OVERLOAD_MASK 3
+/** @} */
+
+/** @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 /* !IPRT_INCLUDED_net_h */
+
diff --git a/include/iprt/nocrt/Makefile.kup b/include/iprt/nocrt/Makefile.kup
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/include/iprt/nocrt/Makefile.kup
diff --git a/include/iprt/nocrt/algorithm b/include/iprt/nocrt/algorithm
new file mode 100644
index 00000000..bf6102f8
--- /dev/null
+++ b/include/iprt/nocrt/algorithm
@@ -0,0 +1,164 @@
+/** @file
+ * IPRT / No-CRT - Minimal C++ algorithm header.
+ */
+
+/*
+ * Copyright (C) 2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_SRC_nocrt_algorithm
+#define VBOX_INCLUDED_SRC_nocrt_algorithm
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#ifdef _MSC_VER
+# pragma warning(push)
+# pragma warning(disable: 4643) /* warning C4643: Forward declaring 'ios_base' in namespace std is not permitted by the C++ Standard */
+#endif
+
+namespace std
+{
+ /**
+ * Swap the values pointed to by the two references.
+ */
+ template<typename a_Type>
+ void swap(a_Type &a_rObj1, a_Type &a_rObj2)
+ {
+ a_Type Tmp(a_rObj1);
+ a_rObj1 = a_rObj2;
+ a_rObj2 = Tmp;
+ }
+
+ /**
+ * Swap the values pointed to by two forward iterators.
+ */
+ template<typename a_ForwardIt1, typename a_ForwardIt2>
+ void iter_swap(a_ForwardIt1 a_It1, a_ForwardIt2 a_It2)
+ {
+ swap(*a_It1, *a_It2);
+ }
+
+ template<typename a_RandomIt>
+ void sort(a_RandomIt a_ItBegin, a_RandomIt a_ItEnd)
+ {
+ /* Note! Using shell sort here because it's tiny and we've got code for it. */
+ /** @todo replace with faster code. */
+
+ /* Anything worth sorting? */
+ std::size_t const cElements = a_ItEnd - a_ItBegin;
+ if (cElements >= 1)
+ {
+ /* Loop on decreasing gap, ending with 1: */
+ std::size_t cGap = (cElements + 1) / 2;
+ while (cGap > 0)
+ {
+ /* Iterate from cGap till the end: */
+ for (std::size_t i = cGap; i < cElements; i++)
+ {
+ /* Find the best suitable location for the item at 'i' comparing
+ backwards in steps of 'cGap', swapping the item at 'i' with the
+ one at '-cGap*j' if it's smaller, stopping if it's larger.
+
+ Note! Original algorithm would make a copy of the item, this version
+ avoids extra copies of sorted items at the cost of extra copies
+ when dealing with unsorted ones a small cGaps values. */
+ a_RandomIt ItCur = a_ItBegin + i;
+ size_t j = i;
+ do
+ {
+ j -= cGap;
+ a_RandomIt ItAtGap = a_ItBegin + j;
+ if (*ItAtGap < *ItCur)
+ break;
+ std::iter_swap(ItAtGap, ItCur);
+ ItCur = ItAtGap;
+ } while (j >= cGap);
+ }
+
+ /* This does not generate the most optimal gap sequence, but it has the
+ advantage of being simple and avoid floating point. */
+ cGap /= 2;
+ }
+ }
+ }
+
+ template<typename a_RandomIt, typename a_FnCompareType>
+ void sort(a_RandomIt a_ItBegin, a_RandomIt a_ItEnd, a_FnCompareType a_fnComp)
+ {
+ /* Note! Using shell sort here because it's tiny and we've got code for it. */
+ /** @todo replace with faster code. */
+
+ /* Anything worth sorting? */
+ std::size_t const cElements = a_ItEnd - a_ItBegin;
+ if (cElements >= 1)
+ {
+ /* Loop on decreasing gap, ending with 1: */
+ std::size_t cGap = (cElements + 1) / 2;
+ while (cGap > 0)
+ {
+ /* Iterate from cGap till the end: */
+ for (std::size_t i = cGap; i < cElements; i++)
+ {
+ /* Find the best suitable location for the item at 'i' comparing
+ backwards in steps of 'cGap', swapping the item at 'i' with the
+ one at '-cGap*j' if it's smaller, stopping if it's larger.
+
+ Note! Original algorithm would make a copy of the item, this version
+ avoids extra copies of sorted items at the cost of extra copies
+ when dealing with unsorted ones a small cGaps values. */
+ a_RandomIt ItCur = a_ItBegin + i;
+ size_t j = i;
+ do
+ {
+ j -= cGap;
+ a_RandomIt ItAtGap = a_ItBegin + j;
+ if (a_fnComp(*ItAtGap, *ItCur))
+ break;
+ std::iter_swap(ItAtGap, ItCur);
+ ItCur = ItAtGap;
+ } while (j >= cGap);
+ }
+
+ /* This does not generate the most optimal gap sequence, but it has the
+ advantage of being simple and avoid floating point. */
+ cGap /= 2;
+ }
+ }
+ }
+
+}
+
+#ifdef _MSC_VER
+# pragma warning(pop)
+#endif
+
+#endif /* !VBOX_INCLUDED_SRC_nocrt_algorithm */
+
diff --git a/include/iprt/nocrt/amd64/Makefile.kup b/include/iprt/nocrt/amd64/Makefile.kup
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/include/iprt/nocrt/amd64/Makefile.kup
diff --git a/include/iprt/nocrt/amd64/math.h b/include/iprt/nocrt/amd64/math.h
new file mode 100644
index 00000000..19bdea78
--- /dev/null
+++ b/include/iprt/nocrt/amd64/math.h
@@ -0,0 +1,115 @@
+/** @file
+ * IPRT / No-CRT - math.h, AMD inlined functions.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_nocrt_amd64_math_h
+#define IPRT_INCLUDED_nocrt_amd64_math_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/asm.h>
+
+
+#if RT_INLINE_ASM_GNU_STYLE && defined(__SSE__)
+
+DECLINLINE(long double) inline_atan2l(long double lrd1, long double lrd2)
+{
+ long double lrdResult;
+ __asm__ __volatile__("fpatan"
+ : "=t" (lrdResult)
+ : "u" (lrd1),
+ "0" (lrd2)
+ : "st(1)");
+ return lrdResult;
+}
+
+DECLINLINE(long double) inline_rintl(long double lrd)
+{
+ long double lrdResult;
+ __asm__ __volatile__("frndint"
+ : "=t" (lrdResult)
+ : "0" (lrd));
+ return lrdResult;
+}
+
+DECLINLINE(float) inline_rintf(float rf)
+{
+ return (float)inline_rintl(rf);
+}
+
+DECLINLINE(double) inline_rint(double rd)
+{
+ return (double)inline_rintl(rd);
+}
+
+DECLINLINE(long double) inline_sqrtl(long double lrd)
+{
+ long double lrdResult;
+ __asm__ __volatile__("fsqrt"
+ : "=t" (lrdResult)
+ : "0" (lrd));
+ return lrdResult;
+}
+
+DECLINLINE(float) inline_sqrtf(float rf)
+{
+ return (float)inline_sqrtl(rf);
+}
+
+DECLINLINE(double) inline_sqrt(double rd)
+{
+ return (double)inline_sqrtl(rd);
+}
+
+
+# undef atan2l
+# define atan2l(lrd1, lrd2) inline_atan2l(lrd1, lrd2)
+# undef rint
+# define rint(rd) inline_rint(rd)
+# undef rintf
+# define rintf(rf) inline_rintf(rf)
+# undef rintl
+# define rintl(lrd) inline_rintl(lrd)
+# undef sqrt
+# define sqrt(rd) inline_sqrt(rd)
+# undef sqrtf
+# define sqrtf(rf) inline_sqrtf(rf)
+# undef sqrtl
+# define sqrtl(lrd) inline_sqrtl(lrd)
+
+#endif /* RT_INLINE_ASM_GNU_STYLE */
+
+#endif /* !IPRT_INCLUDED_nocrt_amd64_math_h */
+
diff --git a/include/iprt/nocrt/assert.h b/include/iprt/nocrt/assert.h
new file mode 100644
index 00000000..987db7df
--- /dev/null
+++ b/include/iprt/nocrt/assert.h
@@ -0,0 +1,57 @@
+/** @file
+ * IPRT / No-CRT - Our own assert.h header.
+ */
+
+/*
+ * Copyright (C) 2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_nocrt_assert_h
+#define IPRT_INCLUDED_nocrt_assert_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/assert.h>
+
+DECL_FORCE_INLINE(void) rtCrtAssertPanic(void)
+{
+ RTAssertPanic();
+}
+
+/* Mesa uses assert() in such a way that we must not have any 'do {} while'
+ wrappers in the expansion, so we partially cook our own assert here but
+ using the standard iprt/assert.h building blocks. */
+#define assert(a_Expr) (RT_LIKELY(!!(a_Expr)) ? (void)0 \
+ : RTAssertMsg1Weak((const char *)0, __LINE__, __FILE__, RT_GCC_EXTENSION __PRETTY_FUNCTION__), \
+ rtCrtAssertPanic(), (void)0 )
+
+#endif /* !IPRT_INCLUDED_nocrt_assert_h */
+
diff --git a/include/iprt/nocrt/cassert b/include/iprt/nocrt/cassert
new file mode 100644
index 00000000..3315a4bd
--- /dev/null
+++ b/include/iprt/nocrt/cassert
@@ -0,0 +1,49 @@
+/** @file
+ * IPRT / No-CRT - Minimal C++ cassert header.
+ */
+
+/*
+ * Copyright (C) 2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_SRC_nocrt_cassert
+#define VBOX_INCLUDED_SRC_nocrt_cassert
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/nocrt/assert.h>
+
+namespace std
+{
+}
+
+#endif /* !VBOX_INCLUDED_SRC_nocrt_cassert */
+
diff --git a/include/iprt/nocrt/compiler/compiler.h b/include/iprt/nocrt/compiler/compiler.h
new file mode 100644
index 00000000..c2ca1d80
--- /dev/null
+++ b/include/iprt/nocrt/compiler/compiler.h
@@ -0,0 +1,52 @@
+/** @file
+ * IPRT / No-CRT - compiler specifics.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_nocrt_compiler_compiler_h
+#define IPRT_INCLUDED_nocrt_compiler_compiler_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#ifdef __GNUC__
+# include <iprt/nocrt/compiler/gcc.h>
+#elif defined(_MSC_VER)
+# include <iprt/nocrt/compiler/msc.h>
+#elif defined(__WATCOMC__)
+# include <iprt/nocrt/compiler/watcom.h>
+#else
+# error "Unsupported compiler."
+#endif
+
+#endif /* !IPRT_INCLUDED_nocrt_compiler_compiler_h */
diff --git a/include/iprt/nocrt/compiler/gcc.h b/include/iprt/nocrt/compiler/gcc.h
new file mode 100644
index 00000000..91c1d5a8
--- /dev/null
+++ b/include/iprt/nocrt/compiler/gcc.h
@@ -0,0 +1,134 @@
+/** @file
+ * IPRT / No-CRT - GCC specifics.
+ *
+ * A quick hack for freebsd where there are no separate location
+ * for compiler specific headers like on linux, mingw, os2, ++.
+ * This file will be cleaned up later...
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_nocrt_compiler_gcc_h
+#define IPRT_INCLUDED_nocrt_compiler_gcc_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+
+/* stddef.h */
+#ifdef __PTRDIFF_TYPE__
+typedef __PTRDIFF_TYPE__ ptrdiff_t;
+#elif ARCH_BITS == 32
+typedef int32_t ptrdiff_t;
+#elif ARCH_BITS == 64
+typedef int64_t ptrdiff_t;
+#else
+# error "ARCH_BITS is undefined or incorrect."
+#endif
+#define _PTRDIFF_T_DECLARED
+
+#ifdef __SIZE_TYPE__
+typedef __SIZE_TYPE__ size_t;
+#elif ARCH_BITS == 32
+typedef uint32_t size_t;
+#elif ARCH_BITS == 64
+typedef uint64_t size_t;
+#else
+# error "ARCH_BITS is undefined or incorrect."
+#endif
+#define _SIZE_T_DECLARED
+
+#ifndef __cplusplus
+# ifdef __WCHAR_TYPE__
+typedef __WCHAR_TYPE__ wchar_t;
+# elif defined(RT_OS_OS2) || defined(RT_OS_WINDOWS)
+typedef uint16_t wchar_t;
+# else
+typedef int wchar_t;
+# endif
+# define _WCHAR_T_DECLARED
+#endif
+
+#ifdef __WINT_TYPE__
+typedef __WINT_TYPE__ wint_t;
+#else
+typedef unsigned int wint_t;
+#endif
+#define _WINT_T_DECLARED
+
+#ifndef NULL
+# ifdef __cplusplus
+# define NULL 0
+# else
+# define NULL ((void *)0)
+# endif
+#endif
+
+
+#ifndef offsetof
+# if defined(__cplusplus) && defined(__offsetof__)
+# define offsetof(type, memb)
+ (__offsetof__ (reinterpret_cast<size_t>(&reinterpret_cast<const volatile char &>(static_cast<type *>(0)->memb))) )
+# else
+# define offsetof(type, memb) ((size_t)&((type *)0)->memb)
+# endif
+#endif
+
+
+/* sys/types.h */
+#ifdef __SSIZE_TYPE__
+typedef __SSIZE_TYPE__ ssize_t;
+#elif ARCH_BITS == 32
+typedef int32_t ssize_t;
+#elif ARCH_BITS == 64
+typedef int64_t ssize_t;
+#else
+# define ARCH_BITS 123123
+# error "ARCH_BITS is undefined or incorrect."
+#endif
+#define _SSIZE_T_DECLARED
+
+
+/* stdarg.h */
+typedef __builtin_va_list va_list;
+#if __GNUC__ == 3 \
+ && __GNUC_MINOR__ == 2
+# define va_start(va, arg) __builtin_stdarg_start(va, arg)
+#else
+# define va_start(va, arg) __builtin_va_start(va, arg)
+#endif
+#define va_end(va) __builtin_va_end(va)
+#define va_arg(va, type) __builtin_va_arg(va, type)
+#define va_copy(dst, src) __builtin_va_copy(dst, src)
+
+
+#endif /* !IPRT_INCLUDED_nocrt_compiler_gcc_h */
diff --git a/include/iprt/nocrt/compiler/msc.h b/include/iprt/nocrt/compiler/msc.h
new file mode 100644
index 00000000..be81fffc
--- /dev/null
+++ b/include/iprt/nocrt/compiler/msc.h
@@ -0,0 +1,62 @@
+/** @file
+ * IPRT / No-CRT - MSC specifics.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_nocrt_compiler_msc_h
+#define IPRT_INCLUDED_nocrt_compiler_msc_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+
+/* stddef.h */
+#if !defined(_MT) && !defined(_DLL) && _MSC_VER < 1400
+# define errno msvcrt_errno
+#endif
+#if _MSC_VER >= 1900
+# include <vcruntime.h>
+#else
+# include <../include/stddef.h>
+#endif
+#undef errno
+
+#undef ssize_t
+typedef intptr_t ssize_t;
+
+
+/* stdarg.h */
+#include <../include/stdarg.h>
+
+#endif /* !IPRT_INCLUDED_nocrt_compiler_msc_h */
+
diff --git a/include/iprt/nocrt/compiler/watcom.h b/include/iprt/nocrt/compiler/watcom.h
new file mode 100644
index 00000000..507b66dc
--- /dev/null
+++ b/include/iprt/nocrt/compiler/watcom.h
@@ -0,0 +1,108 @@
+/** @file
+ * IPRT / No-CRT - Open Watcom specifics.
+ */
+
+/*
+ * Copyright (C) 2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_nocrt_compiler_watcom_h
+#define IPRT_INCLUDED_nocrt_compiler_watcom_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cdefs.h>
+
+/* stddef.h for size_t and such */
+#if 0
+# include <../h/stddef.h>
+
+# ifndef _SSIZE_T_DEFINED_
+# define _SSIZE_T_DEFINED_
+typedef signed int ssize_t;
+# endif
+
+#else
+
+# define _SIZE_T_DEFINED_
+# define __size_t
+typedef unsigned size_t;
+typedef size_t _w_size_t;
+
+# define _SSIZE_T_DEFINED_
+# define __ssize_t
+typedef signed int ssize_t;
+
+# define _RSIZE_T_DEFINED
+typedef size_t rsize_t;
+
+# define _PTRDIFF_T_DEFINED_
+# ifdef __HUGE__
+typedef long ptrdiff_t;
+# else
+typedef int ptrdiff_t;
+# endif
+
+# ifndef _WCHAR_T_DEFINED /* predefined in C++ mode? */
+# define _WCHAR_T_DEFINED
+typedef unsigned short wchar_t;
+# endif
+
+# ifndef NULL
+# ifndef __cplusplus
+# define NULL ((void *)0)
+# elif defined(__SMALL__) || defined(__MEDIUM__) || !defined(_M_I86)
+# define NULL (0)
+# else
+# define NULL (0L)
+# endif
+# endif
+
+# define offsetof(a_Type, a_Member) RT_OFFSETOF(a_Type, a_Member)
+
+# if defined(_M_I86) && (defined(__SMALL__) || defined(__MEDIUM__))
+typedef int intptr_t;
+typedef unsigned int uintptr_t;
+# elif defined(_M_I86) || (!defined(__COMPACT__) && !defined(__LARGE__))
+typedef long intptr_t;
+typedef unsigned long uintptr_t;
+# else /* 32-bit compile using far data pointers (16:32) */
+typedef long long intptr_t;
+typedef unsigned long long uintptr_t;
+# endif
+
+#endif
+
+/* stdarg.h */
+#include <../h/stdarg.h>
+
+#endif /* !IPRT_INCLUDED_nocrt_compiler_watcom_h */
+
diff --git a/include/iprt/nocrt/cstddef b/include/iprt/nocrt/cstddef
new file mode 100644
index 00000000..2b3c29e9
--- /dev/null
+++ b/include/iprt/nocrt/cstddef
@@ -0,0 +1,52 @@
+/** @file
+ * IPRT / No-CRT - Dummy cstddef.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_SRC_nocrt_cstddef
+#define VBOX_INCLUDED_SRC_nocrt_cstddef
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/nocrt/sys/types.h>
+
+namespace std
+{
+ using size_t = ::size_t;
+ using ptrdiff_t = ::ptrdiff_t;
+}
+
+
+#endif /* !VBOX_INCLUDED_SRC_nocrt_cstddef */
+
diff --git a/include/iprt/nocrt/cstdlib b/include/iprt/nocrt/cstdlib
new file mode 100644
index 00000000..2a11d98f
--- /dev/null
+++ b/include/iprt/nocrt/cstdlib
@@ -0,0 +1,47 @@
+/** @file
+ * IPRT / No-CRT - Dummy cstdlib.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_SRC_nocrt_cstdlib
+#define VBOX_INCLUDED_SRC_nocrt_cstdlib
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/nocrt/stdlib.h>
+#include <iprt/nocrt/cstddef>
+
+
+#endif /* !VBOX_INCLUDED_SRC_nocrt_cstdlib */
+
diff --git a/include/iprt/nocrt/ctype.h b/include/iprt/nocrt/ctype.h
new file mode 100644
index 00000000..466a9283
--- /dev/null
+++ b/include/iprt/nocrt/ctype.h
@@ -0,0 +1,61 @@
+/** @file
+ * IPRT / No-CRT - Our own minimal ctype.h header (needed by ntdefs.h).
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_nocrt_ctype_h
+#define IPRT_INCLUDED_nocrt_ctype_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/ctype.h>
+
+#define isspace(a_ch) RT_C_IS_SPACE(a_ch)
+#define isblank(a_ch) RT_C_IS_BLANK(a_ch)
+#define isdigit(a_ch) RT_C_IS_DIGIT(a_ch)
+#define isxdigit(a_ch) RT_C_IS_XDIGIT(a_ch)
+#define isalpha(a_ch) RT_C_IS_ALPHA(a_ch)
+#define isalnum(a_ch) RT_C_IS_ALNUM(a_ch)
+#define iscntrl(a_ch) RT_C_IS_CNTRL(a_ch)
+#define isgraph(a_ch) RT_C_IS_GRAPH(a_ch)
+#define ispunct(a_ch) RT_C_IS_PUNCT(a_ch)
+#define isprint(a_ch) RT_C_IS_PRINT(a_ch)
+#define isupper(a_ch) RT_C_IS_UPPER(a_ch)
+#define islower(a_ch) RT_C_IS_LOWER(a_ch)
+
+#define tolower(a_ch) RT_C_TO_LOWER(a_ch)
+#define toupper(a_ch) RT_C_TO_UPPER(a_ch)
+
+#endif /* !IPRT_INCLUDED_nocrt_ctype_h */
+
diff --git a/include/iprt/nocrt/direct.h b/include/iprt/nocrt/direct.h
new file mode 100644
index 00000000..72f23a17
--- /dev/null
+++ b/include/iprt/nocrt/direct.h
@@ -0,0 +1,43 @@
+/** @file
+ * IPRT / No-CRT - Stub direct.h header (for MSC compatibility).
+ */
+
+/*
+ * Copyright (C) 2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_nocrt_direct_h
+#define IPRT_INCLUDED_nocrt_direct_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#endif /* !IPRT_INCLUDED_nocrt_direct_h */
+
diff --git a/include/iprt/nocrt/errno.h b/include/iprt/nocrt/errno.h
new file mode 100644
index 00000000..1217a531
--- /dev/null
+++ b/include/iprt/nocrt/errno.h
@@ -0,0 +1,56 @@
+/** @file
+ * IPRT / No-CRT - Dummy errno.h.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_nocrt_errno_h
+#define IPRT_INCLUDED_nocrt_errno_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+#ifdef IPRT_NO_CRT_FOR_3RD_PARTY
+# include <iprt/errno.h>
+
+RT_C_DECLS_BEGIN
+
+RTDECL(int *) rtNoCrtGetErrnoPtr(void);
+# define errno (*rtNoCrtGetErrnoPtr())
+
+RT_C_DECLS_END
+
+#endif /* IPRT_NO_CRT_FOR_3RD_PARTY */
+
+#endif /* !IPRT_INCLUDED_nocrt_errno_h */
+
diff --git a/include/iprt/nocrt/exception b/include/iprt/nocrt/exception
new file mode 100644
index 00000000..6e6ee777
--- /dev/null
+++ b/include/iprt/nocrt/exception
@@ -0,0 +1,90 @@
+/** @file
+ * IPRT / No-CRT - Our own exception header.
+ */
+
+/*
+ * Copyright (C) 2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_SRC_nocrt_exception
+#define VBOX_INCLUDED_SRC_nocrt_exception
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+
+namespace std {
+
+/** Exception base class. */
+class exception
+{
+public:
+ exception() RT_NOEXCEPT
+#ifdef _MSC_VER
+ : m_pszWhat(NULL)
+#endif
+ { }
+
+ exception(const exception &a_rThat) RT_NOEXCEPT
+#ifdef _MSC_VER
+ : m_pszWhat(a_rThat.m_pszWhat)
+#endif
+ {
+ RT_NOREF(a_rThat);
+ }
+
+#ifdef _MSC_VER
+ exception(const char *a_pszWhat, int a_iIgnored = 0) RT_NOEXCEPT
+ : m_pszWhat(a_pszWhat)
+ { RT_NOREF(a_iIgnored); }
+#endif
+
+ virtual ~exception() RT_NOEXCEPT
+ {}
+
+ virtual const char *what() const RT_NOEXCEPT
+ {
+#ifdef _MSC_VER
+ if (m_pszWhat)
+ return m_pszWhat;
+#endif
+ return "unknown exception";
+ }
+#ifdef _MSC_VER
+protected:
+ const char *m_pszWhat;
+#endif
+};
+
+}
+
+#endif /* !VBOX_INCLUDED_SRC_nocrt_exception */
+
diff --git a/include/iprt/nocrt/fcntl.h b/include/iprt/nocrt/fcntl.h
new file mode 100644
index 00000000..49cf6f4b
--- /dev/null
+++ b/include/iprt/nocrt/fcntl.h
@@ -0,0 +1,90 @@
+/** @file
+ * IPRT / No-CRT - fcntl.h
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_nocrt_fcntl_h
+#define IPRT_INCLUDED_nocrt_fcntl_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/nocrt/time.h> /* to establish the timespec and timeval types before iprt/file.h includes iprt/time.h */
+#include <iprt/file.h>
+
+#ifdef IPRT_NO_CRT_FOR_3RD_PARTY
+
+/* Open flags:*/
+AssertCompile(RT_IS_POWER_OF_TWO(RTFILE_O_OPEN_CREATE));
+AssertCompile(RT_IS_POWER_OF_TWO(RTFILE_O_CREATE));
+# define _O_CREAT RTFILE_O_OPEN_CREATE
+# define _O_EXCL RTFILE_O_CREATE /**< Will remove RTFILE_O_OPEN_CREATE when processing it. */
+# define _O_TRUNC RTFILE_O_TRUNCATE
+# define _O_APPEND RTFILE_O_APPEND
+# define _O_RDONLY RTFILE_O_READ
+# define _O_WRONLY RTFILE_O_WRITE
+# define _O_RDWR (RTFILE_O_READ | RTFILE_O_WRITE)
+# define _O_CLOEXEC RTFILE_O_INHERIT /**< Invert meaning when processing it. */
+# define _O_NOINHERIT O_CLOEXEC
+# define _O_LARGEFILE 0
+# define _O_BINARY 0
+
+# define O_CREAT _O_CREAT
+# define O_EXCL _O_EXCL
+# define O_TRUNC _O_TRUNC
+# define O_APPEND _O_APPEND
+# define O_RDONLY _O_RDONLY
+# define O_WRONLY _O_WRONLY
+# define O_RDWR _O_RDWR
+# define O_CLOEXEC _O_CLOEXEC
+# define O_NOINHERIT _O_NOINHERIT
+# define O_BINARY _O_BINARY
+
+RT_C_DECLS_BEGIN
+
+int RT_NOCRT(open)(const char *pszFilename, uint64_t fFlags, ... /*RTFMODE fMode*/);
+int RT_NOCRT(_open)(const char *pszFilename, uint64_t fFlags, ... /*RTFMODE fMode*/);
+
+# if !defined(RT_WITHOUT_NOCRT_WRAPPERS) && !defined(RT_WITHOUT_NOCRT_WRAPPER_ALIASES)
+# define open RT_NOCRT(open)
+# define _open RT_NOCRT(_open)
+# endif
+
+RT_C_DECLS_END
+
+#endif /* IPRT_NO_CRT_FOR_3RD_PARTY */
+
+
+
+#endif /* !IPRT_INCLUDED_nocrt_fcntl_h */
+
diff --git a/include/iprt/nocrt/fenv.h b/include/iprt/nocrt/fenv.h
new file mode 100644
index 00000000..7af59d13
--- /dev/null
+++ b/include/iprt/nocrt/fenv.h
@@ -0,0 +1,49 @@
+/** @file
+ * IPRT / No-CRT - fenv.h wrapper.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_nocrt_fenv_h
+#define IPRT_INCLUDED_nocrt_fenv_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cdefs.h>
+#if defined(RT_ARCH_X86) || defined(RT_ARCH_AMD64)
+# include <iprt/nocrt/x86/fenv-x86-amd64.h>
+#else
+# error "IPRT: no fenv.h available for this platform, or the platform define is missing!"
+#endif
+
+#endif /* !IPRT_INCLUDED_nocrt_fenv_h */
diff --git a/include/iprt/nocrt/float.h b/include/iprt/nocrt/float.h
new file mode 100644
index 00000000..f0e8081d
--- /dev/null
+++ b/include/iprt/nocrt/float.h
@@ -0,0 +1,131 @@
+/** @file
+ * IPRT / No-CRT - Our minimal float.h.
+ */
+
+/*
+ * Copyright (C) 2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_nocrt_float_h
+#define IPRT_INCLUDED_nocrt_float_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+
+/*
+ * Common.
+ */
+#define FLT_RADIX 2
+
+
+/*
+ * float
+ */
+#if defined(RT_ARCH_X86) || defined(RT_ARCH_AMD64) || defined(RT_ARCH_ARM64)
+
+# define FLT_MAX (3.40282347E+38F)
+# define FLT_MIN (1.17549435E-38F)
+# define FLT_TRUE_MIN (1.40129846E-45F)
+# define FLT_MAX_EXP (128)
+# define FLT_MIN_EXP (-125)
+# define FLT_MAX_10_EXP (38)
+# define FLT_MIN_10_EXP (-37)
+# define FLT_EPSILON (1.192092896E-07F)
+# define FLT_DIG (6)
+# define FLT_DECIMAL_DIG (9)
+# define FLT_MANT_DIG (24)
+# define FLT_HAS_SUBNORM (1)
+
+#endif
+
+/*
+ * double
+ */
+#if defined(RT_ARCH_X86) || defined(RT_ARCH_AMD64) || defined(RT_ARCH_ARM64)
+
+# ifdef _MSC_VER
+# define DBL_MAX (1.7976931348623158E+308)
+# else
+# define DBL_MAX (1.7976931348623157E+308)
+# endif
+# define DBL_MIN (2.2250738585072014E-308)
+# define DBL_TRUE_MIN (4.9406564584124654E-324)
+# define DBL_MAX_EXP (1024)
+# define DBL_MIN_EXP (-1021)
+# define DBL_MAX_10_EXP (308)
+# define DBL_MIN_10_EXP (-307)
+# define DBL_EPSILON (2.2204460492503131E-16)
+# define DBL_DIG (15)
+# define DBL_DECIMAL_DIG (17)
+# define DBL_MANT_DIG (53)
+# define DBL_HAS_SUBNORM (1)
+
+#endif
+
+/*
+ * long double
+ */
+#if ((defined(RT_ARCH_X86) || defined(RT_ARCH_AMD64)) && defined(RT_OS_WINDOWS)) || defined(RT_ARCH_ARM64) /*?*/
+
+# define LDBL_MAX DBL_MAX
+# define LDBL_MIN DBL_MIN
+# define LDBL_TRUE_MIN DBL_TRUE_MIN
+# define LDBL_MAX_EXP DBL_MAX_EXP
+# define LDBL_MIN_EXP DBL_MIN_EXP
+# define LDBL_MAX_10_EXP DBL_MAX_10_EXP
+# define LDBL_MIN_10_EXP DBL_MIN_10_EXP
+# define LDBL_EPSILON DBL_EPSILON
+# define LDBL_DIG DBL_DIG
+# define LDBL_DECIMAL_DIG DBL_DECIMAL_DIG
+# define LDBL_MANT_DIG DBL_MANT_DIG
+# define LDBL_HAS_SUBNORM DBL_HAS_SUBNORM
+
+#elif defined(RT_ARCH_X86) || defined(RT_ARCH_AMD64)
+
+# define LDBL_MAX (1.1897314953572317650E+4932L)
+# define LDBL_MIN (3.3621031431120935063E-4932L)
+# define LDBL_TRUE_MIN (3.6451995318824746025E-4951L)
+# define LDBL_MAX_EXP (-16381)
+# define LDBL_MIN_EXP (16384)
+# define LDBL_MAX_10_EXP (4932)
+# define LDBL_MIN_10_EXP (-4931)
+# define LDBL_EPSILON (1.0842021724855044340E-19L)
+# define LDBL_DIG (18)
+# define LDBL_DECIMAL_DIG (21)
+# define LDBL_MANT_DIG (64)
+# define LDBL_HAS_SUBNORM (1)
+
+#endif
+
+
+#endif /* !IPRT_INCLUDED_nocrt_float_h */
+
diff --git a/include/iprt/nocrt/fstream b/include/iprt/nocrt/fstream
new file mode 100644
index 00000000..1abd06eb
--- /dev/null
+++ b/include/iprt/nocrt/fstream
@@ -0,0 +1,206 @@
+/** @file
+ * IPRT / No-CRT - Minimal C++ fstream header.
+ */
+
+/*
+ * Copyright (C) 2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_SRC_nocrt_fstream
+#define VBOX_INCLUDED_SRC_nocrt_fstream
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/nocrt/ostream>
+#include <iprt/stream.h>
+
+
+namespace std
+{
+ template<typename a_CharType, typename a_CharTraits /*= std::char_traits<a_CharType>*/ >
+ class basic_filebuf : public basic_streambuf<a_CharType, a_CharTraits>
+ {
+ protected:
+ PRTSTREAM m_pStrm;
+ bool m_fStdStream;
+ ios_base::openmode m_fMode;
+
+ public:
+ basic_filebuf(PRTSTREAM a_pStrm = NULL, bool a_fStdStream = false)
+ : basic_streambuf()
+ , m_pStrm(a_pStrm)
+ , m_fStdStream(a_fStdStream)
+ , m_fMode(ios_base::openmode(0))
+ {
+ }
+
+ virtual ~basic_filebuf()
+ {
+ if (m_pStrm)
+ {
+ if (m_fStdStream)
+ RTStrmClose(m_pStrm);
+ m_pStrm = NULL;
+ }
+ }
+
+ bool is_open() const RT_NOEXCEPT
+ {
+ return m_pStrm != NULL;
+ }
+
+ basic_filebuf *open(const char *a_pszFilename, ios_base::openmode a_fMode)
+ {
+ /*
+ * Sanitize the a_fMode first.
+ */
+ AssertReturn(!is_open(), NULL);
+ AssertReturn(a_fMode & (ios_base::out | ios_base::in), NULL); /* Neither write nor read mode? */
+ AssertStmt((a_fMode & (ios_base::out | ios_base::app)) != ios_base::app, a_fMode &= ~ios_base::app);
+ AssertReturn((a_fMode & (ios_base::out | ios_base::trunc)) != ios_base::trunc, NULL);
+ AssertReturn(!(a_fMode & ios_base::trunc) || !(a_fMode & ios_base::app), NULL);
+
+ /*
+ * Translate a_fMode into a stream mode string and try open the file.
+ */
+ char szMode[8];
+ szMode[0] = a_fMode & ios_base::trunc ? 'w' : a_fMode & ios_base::app ? 'a' : 'r';
+ size_t offMode = 1;
+ if ((a_fMode & (ios_base::in | ios_base::out)) == (ios_base::in | ios_base::out))
+ szMode[offMode++] = '+';
+ if (a_fMode & ios_base::binary)
+ szMode[offMode++] = 'b';
+ szMode[offMode] = '\0';
+
+ int rc = RTStrmOpen(a_pszFilename, szMode, &m_pStrm);
+ if (RT_SUCCESS(rc))
+ {
+ /** @todo if (a_fMode & ios_base::ate)? */
+
+ /*
+ * Set up the buffer?
+ */
+ if (true)
+ {
+ return this;
+ }
+
+ RTStrmClose(m_pStrm);
+ m_pStrm = NULL;
+ }
+ return NULL;
+ }
+
+ protected:
+ bool flushBuffered()
+ {
+ /** @todo buffering. */
+ return true;
+ }
+
+ //virtual int_type overflow(int_type a_iChar) RT_OVERRIDE
+ //{
+ // if (a_iChar != traits_type::eof())
+ // {
+ // if (flushBuffered())
+ // {
+ // char_type ch = traits_type::to_char_type(a_iChar);
+ // int rc = RTStrmWrite(m_pStrm, &ch, sizeof(ch));
+ // if (RT_SUCCESS(rc))
+ // return a_iChar;
+ // }
+ // }
+ // return traits_type::eof();
+ //}
+
+ std::streamsize xsputn(char_type const *a_pchSrc, std::streamsize a_cchSrc) //RT_OVERRIDE
+ {
+ if (flushBuffered())
+ {
+ size_t cbWritten = 0;
+ int rc = RTStrmWriteEx(m_pStrm, &a_pchSrc, sizeof(a_pchSrc[0]) * a_cchSrc, &cbWritten);
+ if (RT_SUCCESS(rc))
+ return cbWritten / sizeof(a_pchSrc[0]);
+ }
+ return 0;
+ }
+ };
+
+
+ /**
+ * Basic I/O stream.
+ */
+ template<typename a_CharType, typename a_CharTraits /*= std::char_traits<a_CharType>*/ >
+ class basic_ofstream : public basic_ostream<a_CharType, a_CharTraits>
+ {
+ protected:
+ basic_filebuf<a_CharType, a_CharTraits> m_FileBuf;
+
+ public:
+ basic_ofstream()
+ : basic_ostream(&m_FileBuf) /** @todo m_FileBuf isn't initialized yet... */
+ , m_FileBuf()
+ {
+ }
+
+ explicit basic_ofstream(const char *a_pszFilename, ios_base::openmode a_fMode = ios_base::out)
+ : basic_ostream(&m_FileBuf) /** @todo m_FileBuf isn't initialized yet... */
+ , m_FileBuf()
+ {
+ m_FileBuf.open(a_pszFilename, a_fMode);
+ }
+ private:
+ basic_ofstream(basic_ofstream const &a_rSrc); /* no copying */
+ basic_ofstream &operator=(basic_ofstream const &a_rSrc); /* no copying */
+
+ public:
+ virtual ~basic_ofstream()
+ {
+ }
+
+ public:
+
+ bool is_open() const RT_NOEXCEPT
+ {
+ return m_FileBuf.is_open();
+ }
+
+ basic_filebuf<a_CharType, a_CharTraits> *open(const char *a_pszFilename, ios_base::openmode a_fMode)
+ {
+ return m_FileBuf.open(a_pszFilename, a_fMode);
+ }
+
+
+ };
+}
+
+#endif /* !VBOX_INCLUDED_SRC_nocrt_fstream */
+
diff --git a/include/iprt/nocrt/inttypes.h b/include/iprt/nocrt/inttypes.h
new file mode 100644
index 00000000..cb2265c8
--- /dev/null
+++ b/include/iprt/nocrt/inttypes.h
@@ -0,0 +1,75 @@
+/** @file
+ * IPRT / No-CRT - Our minimal inttypes.h.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_nocrt_inttypes_h
+#define IPRT_INCLUDED_nocrt_inttypes_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+
+#define PRId8 "RI8"
+#define PRIi8 "RI8"
+#define PRIx8 "RX8"
+#define PRIu8 "RU8"
+#define PRIo8 huh? anyone using this? great!
+
+#define PRId16 "RI16"
+#define PRIi16 "RI16"
+#define PRIx16 "RX16"
+#define PRIu16 "RU16"
+#define PRIo16 huh? anyone using this? great!
+
+#define PRId32 "RI32"
+#define PRIi32 "RI32"
+#define PRIx32 "RX32"
+#define PRIu32 "RU32"
+#define PRIo32 huh? anyone using this? great!
+
+#define PRId64 "RI64"
+#define PRIi64 "RI64"
+#define PRIx64 "RX64"
+#define PRIu64 "RU64"
+#define PRIo64 huh? anyone using this? great!
+
+#define PRIdMAX "RI64"
+#define PRIiMAX "RI64"
+#define PRIxMAX "RX64"
+#define PRIuMAX "RU64"
+#define PRIoMAX huh? anyone using this? great!
+
+#endif /* !IPRT_INCLUDED_nocrt_inttypes_h */
+
diff --git a/include/iprt/nocrt/io.h b/include/iprt/nocrt/io.h
new file mode 100644
index 00000000..f8d42941
--- /dev/null
+++ b/include/iprt/nocrt/io.h
@@ -0,0 +1,48 @@
+/** @file
+ * IPRT / No-CRT - io.h (DOS, OS/2, Windows compilers).
+ */
+
+/*
+ * Copyright (C) 2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_nocrt_io_h
+#define IPRT_INCLUDED_nocrt_io_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/nocrt/fcntl.h>
+#include <iprt/nocrt/sys/stat.h>
+#include <iprt/nocrt/unistd.h>
+
+
+#endif /* !IPRT_INCLUDED_nocrt_io_h */
+
diff --git a/include/iprt/nocrt/iomanip b/include/iprt/nocrt/iomanip
new file mode 100644
index 00000000..29c651e9
--- /dev/null
+++ b/include/iprt/nocrt/iomanip
@@ -0,0 +1,166 @@
+/** @file
+ * IPRT / No-CRT - Minimal C++ iomanip header.
+ */
+
+/*
+ * Copyright (C) 2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_SRC_nocrt_iomanip
+#define VBOX_INCLUDED_SRC_nocrt_iomanip
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/nocrt/ios>
+
+
+namespace std
+{
+ /**
+ * Used by all flag manipulators.
+ */
+ struct rtNoCrtIosSetFlagsEx
+ {
+ ios_base::fmtflags m_fSet;
+ ios_base::fmtflags m_fMask;
+ };
+
+ template<typename a_CharType, typename a_CharTraits>
+ inline basic_istream<a_CharType, a_CharTraits> &operator>>(basic_istream<a_CharType, a_CharTraits> &a_rSrc,
+ struct rtNoCrtIosSetFlagsEx a_Change)
+ {
+ a_rSrc.setf(a_Change.m_fSet, a_Change.m_fMask);
+ return a_rSrc;
+ }
+
+ template<typename a_CharType, typename a_CharTraits>
+ inline basic_ostream<a_CharType, a_CharTraits> &operator<<(basic_ostream<a_CharType, a_CharTraits> &a_rDst,
+ struct rtNoCrtIosSetFlagsEx a_Change)
+ {
+ a_rDst.setf(a_Change.m_fSet, a_Change.m_fMask);
+ return a_rDst;
+ }
+
+
+ /*
+ * Flag modification functions.
+ */
+
+ inline struct rtNoCrtIosSetFlagsEx setiosflags(ios_base::fmtflags a_fFlags)
+ {
+ struct rtNoCrtIosSetFlagsEx Ret = { a_fFlags, a_fFlags };
+ return Ret;
+ }
+
+ inline struct rtNoCrtIosSetFlagsEx resetiosflags(ios_base::fmtflags a_fFlags)
+ {
+ struct rtNoCrtIosSetFlagsEx Ret = { ios_base::fmtflags(0), a_fFlags };
+ return Ret;
+ }
+
+ inline struct rtNoCrtIosSetFlagsEx setbase(int a_iBase)
+ {
+ struct rtNoCrtIosSetFlagsEx Ret =
+ {
+ a_iBase == 10 ? ios_base::dec
+ : a_iBase == 16 ? ios_base::hex
+ : a_iBase == 8 ? ios_base::oct
+ : ios_base::fmtflags(0),
+ ios_base::basefield
+ };
+ return Ret;
+ }
+
+ /*
+ * Modify precision.
+ */
+ struct rtNoCrtIosSetPrecision
+ {
+ int m_cchPrecision;
+ };
+
+ template<typename a_CharType, typename a_CharTraits>
+ inline basic_istream<a_CharType, a_CharTraits> &operator>>(basic_istream<a_CharType, a_CharTraits> &a_rSrc,
+ struct rtNoCrtIosSetPrecision a_Change)
+ {
+ a_rSrc.precision(a_Change.m_cchPrecision);
+ return a_rSrc;
+ }
+
+ template<typename a_CharType, typename a_CharTraits>
+ inline basic_ostream<a_CharType, a_CharTraits> &operator<<(basic_ostream<a_CharType, a_CharTraits> &a_rDst,
+ struct rtNoCrtIosSetPrecision a_Change)
+ {
+ a_rDst.precision(a_Change.m_cchPrecision);
+ return a_rDst;
+ }
+
+ inline struct rtNoCrtIosSetPrecision setprecision(int a_cchPrecision)
+ {
+ struct rtNoCrtIosSetPrecision Ret = { a_cchPrecision };
+ return Ret;
+ }
+
+ /*
+ * Modify width.
+ */
+ struct rtNoCrtIosSetWidth
+ {
+ int m_cchWidth;
+ };
+
+ template<typename a_CharType, typename a_CharTraits>
+ inline basic_istream<a_CharType, a_CharTraits> &operator>>(basic_istream<a_CharType, a_CharTraits> &a_rSrc,
+ struct rtNoCrtIosSetWidth a_Change)
+ {
+ a_rSrc.width(a_Change.m_cchWidth);
+ return a_rSrc;
+ }
+
+ template<typename a_CharType, typename a_CharTraits>
+ inline basic_ostream<a_CharType, a_CharTraits> &operator<<(basic_ostream<a_CharType, a_CharTraits> &a_rDst,
+ struct rtNoCrtIosSetWidth a_Change)
+ {
+ a_rDst.width(a_Change.m_cchWidth);
+ return a_rDst;
+ }
+
+ inline struct rtNoCrtIosSetWidth setw(int a_cchWidth)
+ {
+ struct rtNoCrtIosSetWidth Ret = { a_cchWidth };
+ return Ret;
+ }
+
+ /** @todo setfil, get_money, set_money, get_time, set_time */
+}
+
+#endif /* !VBOX_INCLUDED_SRC_nocrt_iomanip */
+
diff --git a/include/iprt/nocrt/ios b/include/iprt/nocrt/ios
new file mode 100644
index 00000000..9e49eaa9
--- /dev/null
+++ b/include/iprt/nocrt/ios
@@ -0,0 +1,525 @@
+/** @file
+ * IPRT / No-CRT - Minimal C++ ios header.
+ */
+
+/*
+ * Copyright (C) 2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_SRC_nocrt_ios
+#define VBOX_INCLUDED_SRC_nocrt_ios
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/nocrt/iosfwd>
+#include <iprt/nocrt/string>
+
+/** @todo something for cdecl.h */
+#define RTNOCRT_IOS_ENUM_BIT_OPS(a_EnumType, a_IntType) \
+ inline a_EnumType operator~(a_EnumType a_fLeft) RT_NOEXCEPT \
+ { return a_EnumType(~static_cast<a_IntType>(a_fLeft)); } \
+ \
+ inline a_EnumType operator&(a_EnumType a_fLeft, a_EnumType a_fRight) RT_NOEXCEPT \
+ { return a_EnumType(static_cast<a_IntType>(a_fLeft) & static_cast<a_IntType>(a_fRight)); } \
+ inline a_EnumType operator|(a_EnumType a_fLeft, a_EnumType a_fRight) RT_NOEXCEPT \
+ { return a_EnumType(static_cast<a_IntType>(a_fLeft) | static_cast<a_IntType>(a_fRight)); } \
+ inline a_EnumType operator^(a_EnumType a_fLeft, a_EnumType a_fRight) RT_NOEXCEPT \
+ { return a_EnumType(static_cast<a_IntType>(a_fLeft) ^ static_cast<a_IntType>(a_fRight)); } \
+ \
+ inline const a_EnumType &operator&=(a_EnumType &a_rfLeft, a_EnumType a_fRight) RT_NOEXCEPT \
+ { return a_rfLeft = a_rfLeft & a_fRight; } \
+ inline const a_EnumType &operator|=(a_EnumType &a_rfLeft, a_EnumType a_fRight) RT_NOEXCEPT \
+ { return a_rfLeft = a_rfLeft | a_fRight; } \
+ inline const a_EnumType &operator^=(a_EnumType &a_rfLeft, a_EnumType a_fRight) RT_NOEXCEPT \
+ { return a_rfLeft = a_rfLeft ^ a_fRight; } \
+
+namespace std
+{
+ typedef ptrdiff_t streamsize;
+
+ /**
+ * I/O stream format flags.
+ */
+ class rtNoCrtIosEnums
+ {
+ public:
+ enum fmtflags
+ {
+ /* int: */
+ dec = 0x00000001,
+ oct = 0x00000002,
+ hex = 0x00000004,
+ basefield = 0x00000007,
+ /* float: */
+ scientific = 0x00000010,
+ fixed = 0x00000020,
+ floatfield = 0x00000030,
+ /* int and float output tweaks: */
+ showbase = 0x00000100,
+ showpoint = 0x00000200,
+ showpos = 0x00000400,
+ /* bool: */
+ boolalpha = 0x00000800,
+ /* adjustment: */
+ left = 0x00001000,
+ right = 0x00002000,
+ internal = 0x00004000,
+ adjustfield = 0x00007000,
+ /* misc: */
+ skipws = 0x00010000,
+ unitbuf = 0x00020000,
+ uppercase = 0x00040000,
+ };
+
+ enum seekdir
+ {
+ beg = 1,
+ end,
+ cur,
+ };
+
+ enum openmode
+ {
+ app = 1,
+ binary,
+ in,
+ out,
+ trunc,
+ ate
+ };
+
+ enum iostate
+ {
+ goodbit = 0,
+ badbit = 1,
+ failbit = 2,
+ eofbit = 4
+ };
+ };
+ RTNOCRT_IOS_ENUM_BIT_OPS(rtNoCrtIosEnums::fmtflags, int)
+ RTNOCRT_IOS_ENUM_BIT_OPS(rtNoCrtIosEnums::seekdir, int)
+ RTNOCRT_IOS_ENUM_BIT_OPS(rtNoCrtIosEnums::openmode, int)
+ RTNOCRT_IOS_ENUM_BIT_OPS(rtNoCrtIosEnums::iostate, int)
+
+
+ /**
+ * I/O stream base class.
+ */
+ class ios_base : public rtNoCrtIosEnums
+ {
+ public:
+ //typedef rtNoCrtIosFmtFlags fmtflags;
+ //typedef rtNoCrtIosSeekDir seekdir;
+ //typedef rtNoCrtIosOpenMode openmode;
+ //typedef rtNoCrtIosState iostate;
+
+ protected:
+ streamsize m_cWidth;
+ streamsize m_cPrecision;
+ fmtflags m_fFlags;
+ iostate m_fState;
+
+ protected:
+ ios_base()
+ : m_cWidth(0)
+ , m_cPrecision(0)
+ , m_fFlags(dec | skipws)
+ , m_fState(goodbit)
+ {
+ }
+ private:
+ ios_base(const ios_base &); /* not copyable */
+ ios_base &operator=(const ios_base &); /* not copyable */
+
+ public:
+ virtual ~ios_base()
+ {
+ }
+
+ streamsize width() const RT_NOEXCEPT
+ {
+ return m_cWidth;
+ }
+
+ streamsize width(streamsize a_cWidth) RT_NOEXCEPT
+ {
+ streamsize cOldWidth = m_cWidth;
+ m_cWidth = a_cWidth;
+ return cOldWidth;
+ }
+
+ streamsize precision() const RT_NOEXCEPT
+ {
+ return m_cPrecision;
+ }
+
+ streamsize precision(streamsize a_cPrecision) RT_NOEXCEPT
+ {
+ streamsize cOldPrecision = m_cPrecision;
+ m_cPrecision = a_cPrecision;
+ return cOldPrecision;
+ }
+
+ fmtflags flags() const RT_NOEXCEPT
+ {
+ return m_fFlags;
+ }
+
+ fmtflags flags(fmtflags a_fNew) RT_NOEXCEPT
+ {
+ fmtflags const fOld = m_fFlags;
+ m_fFlags = a_fNew;
+ return fOld;
+ }
+
+ fmtflags setf(fmtflags a_fAdd) RT_NOEXCEPT
+ {
+ fmtflags const fOld = m_fFlags;
+ m_fFlags = static_cast<fmtflags>(fOld | a_fAdd);
+ return fOld;
+ }
+
+ fmtflags setf(fmtflags a_fAdd, fmtflags a_fMask) RT_NOEXCEPT
+ {
+ fmtflags const fOld = m_fFlags;
+ m_fFlags = static_cast<fmtflags>((fOld & ~a_fMask) | (a_fAdd & a_fMask));
+ return fOld;
+ }
+
+ void unsetf(fmtflags a_fClear) RT_NOEXCEPT
+ {
+ m_fFlags = static_cast<fmtflags>(m_fFlags & ~a_fClear);
+ }
+ };
+
+
+ /**
+ * Stream buffer.
+ */
+ template<typename a_CharType, typename a_CharTraits /*= std::char_traits<a_CharType>*/ >
+ class basic_streambuf
+ {
+ public:
+ typedef a_CharType char_type;
+ typedef a_CharTraits traits_type;
+ typedef typename a_CharTraits::int_type int_type;
+ typedef typename a_CharTraits::pos_type pos_type;
+ typedef typename a_CharTraits::off_type off_type;
+
+ protected:
+ /** @name Put buffering
+ * @{ */
+ char_type *m_pachPut; /**< The put buffer pointer. */
+ std::size_t m_cchPut; /**< Put buffer size. */
+ std::size_t m_offPutNext; /**< The current put buffer position (where to write next). */
+ std::size_t m_offPutStart; /**< Where the buffered put sequence starts. */
+
+ void setp(char_type *a_pachNewBuf, char_type *a_pachNewBufEnd)
+ {
+ Assert((uintptr_t)a_pachNewBuf <= (uintptr_t)a_pachNewBufEnd);
+ m_pachPut = a_pachNewBuf;
+ m_cchPut = static_cast<std::size_t>(a_pachNewBufEnd - a_pachNewBuf);
+ m_offPutNext = 0;
+ m_offPutStart = 0;
+ }
+
+ char_type *pbbase() const RT_NOEXCEPT
+ {
+ Assert(m_offPutNext >= m_offPutStart); Assert(m_offPutNext <= m_cchPut); Assert(m_offPutStart <= m_cchPut);
+ return &m_pachPut[m_offPutStart];
+ }
+
+ char_type *pptr() const RT_NOEXCEPT
+ {
+ Assert(m_offPutNext <= m_cchPut);
+ return &m_pachPut[m_offPutNext];
+ }
+
+ char_type *epptr() const RT_NOEXCEPT
+ {
+ return &m_pachBuf[m_cchPut];
+ }
+
+ void pbump(int a_cchAdvance) const RT_NOEXCEPT
+ {
+ Assert(m_offPutNext <= m_cchPut);
+ m_offPutNext += a_cchAdvance;
+ Assert(m_offPutNext <= m_cchPut);
+ }
+ /** @} */
+
+ protected:
+ basic_streambuf() RT_NOEXCEPT
+ : m_pachPut(NULL)
+ , m_cchPut(0)
+ , m_offPutNext(0)
+ , m_offPutStart(0)
+ {
+ }
+
+ basic_streambuf(const basic_streambuf &a_rSrc) RT_NOEXCEPT
+ : m_pachPut(a_rSrc.m_pachPut)
+ , m_cchPut(a_rSrc.m_cchPut)
+ , m_offPutNext(a_rSrc.m_offPutNext)
+ , m_offPutStart(a_rSrc.m_offPutStart)
+ {
+ }
+
+ public:
+ virtual ~basic_streambuf()
+ {
+ }
+
+ /** @name Positioning
+ * @{ */
+ protected:
+ virtual basic_streambuf *setbuf(char_type *a_pchBuf, std::streamsize a_cchBuf)
+ {
+ RT_NOREF(a_pchBuf, a_cchBuf);
+ return this;
+ }
+ public:
+ basic_streambuf *pubsetbuf(char_type *a_pchBuf, std::streamsize a_cchBuf)
+ {
+ return setbuf(a_pchBuf, a_cchBuf);
+ }
+
+ protected:
+ virtual pos_type seekoff(off_type a_off, std::ios_base::seekdir a_enmDir,
+ std::ios_base::openmode a_enmTarget = ios_base::in | ios_base::out)
+ {
+ RT_NOREF(a_off, a_enmDir, a_enmTarget);
+ return pos_type(off_type(-1));
+ }
+ public:
+ pos_type pubseekoff(off_type a_off, std::ios_base::seekdir a_enmDir,
+ std::ios_base::openmode a_enmTarget = ios_base::in | ios_base::out)
+ {
+ return seekoff(a_off, a_enmDir, a_enmTarget);
+ }
+
+ protected:
+ virtual pos_type seekpos(pos_type a_pos, std::ios_base::openmode a_enmTarget = ios_base::in | ios_base::out)
+ {
+ RT_NOREF(a_pos, a_enmTarget);
+ return pos_type(off_type(-1));
+ }
+ public:
+ pos_type pubseekpos(pos_type a_pos, std::ios_base::openmode a_enmTarget = ios_base::in | ios_base::out)
+ {
+ return seekpos(a_pos, a_enmTarget);
+ }
+
+ protected:
+ virtual int sync()
+ {
+ return 0;
+ }
+ public:
+ pos_type pubsync()
+ {
+ return sync();
+ }
+ /** @} */
+
+ /** @name Output
+ * @{ */
+ protected:
+ virtual int_type overflow(int_type a_iChar)
+ {
+ RT_NOREF(a_iChar);
+ return traits_type::eof();
+ }
+
+ virtual std::streamsize xsputn(char_type const *a_pchSrc, std::streamsize a_cchSrc)
+ {
+ std::streamsize cchWritten = 0;
+ while (a_cchSrc > 0)
+ {
+ std::size_t cchCopied = m_cchPut - m_offPutNext;
+ if (cchCopied > 0)
+ {
+ cchCopied = RT_MIN(cchCopied, static_cast<std::size_t>(a_cchSrc));
+ traits_type::copy(&m_pachPut[m_offPutNext], a_pchSrc, cchCopied);
+ m_cchPut += cchCopied;
+ }
+ else
+ {
+ if (overflow(traits_type::to_int_type(m_pachPut[m_offPutNext])) != traits_type::eof())
+ cchCopied = 1;
+ else
+ break;
+ }
+ a_pchSrc += cchCopied;
+ a_cchSrc -= cchCopied;
+ }
+ return cchWritten;
+ }
+
+ public:
+ int_type sputc(char_type a_ch)
+ {
+ if (m_offPutNext < m_cchPut)
+ {
+ m_pachPut[m_offPutNext++] = a_ch;
+ return traits_type::to_int_type(a_ch);
+ }
+ return overflow(traits_type::to_int_type(a_ch));
+ }
+
+ std::streamsize sputn(char_type const *a_pchSrc, std::streamsize a_cchSrc)
+ {
+ AssertReturn(a_cchSrc >= 0, 0);
+ return xsputn(a_pchSrc, a_cchSrc);
+ }
+
+ /** @} */
+
+ /** @todo add the remaining members... */
+ };
+
+
+ /**
+ * Basic I/O stream.
+ */
+ template<typename a_CharType, typename a_CharTraits /*= std::char_traits<a_CharType>*/ >
+ class basic_ios : public ios_base
+ {
+ public:
+ typedef a_CharType char_type;
+ typedef a_CharTraits traits_type;
+ typedef typename a_CharTraits::int_type int_type;
+ typedef typename a_CharTraits::pos_type pos_type;
+ typedef typename a_CharTraits::off_type off_type;
+
+ protected:
+ basic_streambuf<a_CharType, a_CharTraits> *m_pBuf;
+ basic_ostream<a_CharType, a_CharTraits> *m_pTiedStream;
+
+ protected:
+ void init(std::basic_streambuf<a_CharType, a_CharTraits> *a_pBuf)
+ {
+ m_pBuf = a_pBuf;
+ m_cWidth = 0;
+ m_cPrecision = 6;
+ m_fFlags = ios_base::dec | ios_base::skipws;
+ m_fState = ios_base::goodbit;
+ }
+
+ public:
+ basic_ios()
+ : ios_base()
+ , m_pBuf(NULL)
+ , m_pTiedStream(NULL)
+ {
+ }
+
+ basic_ios(std::basic_streambuf<a_CharType, a_CharTraits> *a_pBuf)
+ : ios_base()
+ , m_pBuf(NULL)
+ , m_pTiedStream(NULL)
+ {
+ init(a_pBuf);
+ }
+ private:
+ basic_ios(const basic_ios &a_rSrc); /* not copyable */
+ basic_ios &operator=(const basic_ios &a_rSrc); /* not copyable */
+
+ public:
+ virtual ~basic_ios()
+ {
+ }
+
+ /** @name State methods
+ * @{ */
+ bool good() const RT_NOEXCEPT { return m_fState == ios_base::goodbit; }
+ bool fail() const RT_NOEXCEPT { return (m_fState & (ios_base::failbit | ios_base::badbit)) != ios_base::goodbit; }
+ bool bad() const RT_NOEXCEPT { return (m_fState & ios_base::badbit) == ios_base::badbit; }
+ bool eof() const RT_NOEXCEPT { return (m_fState & ios_base::eofbit) != ios_base::eofbit; }
+#if RT_CPLUSPLUS_PREREQ(201100)
+ operator bool() const RT_NOEXCEPT { return good(); }
+#else
+ operator void*() const RT_NOEXCEPT { return good() ? NULL : this; }
+#endif
+ bool operator!() const RT_NOEXCEPT { return fail(); }
+
+ iostate rdstate() const RT_NOEXCEPT
+ {
+ return m_fState;
+ }
+
+ void clear(iostate a_fNewState = goodbit)
+ {
+ m_fState = a_fNewState;
+ if (!m_pBuf)
+ m_fState |= badbit;
+ /** @todo failure exception */
+ }
+
+ void setstate(iostate a_fNewState)
+ {
+ clear(m_fState | a_fNewState);
+ }
+ /** @} */
+
+ /** @name Misc
+ * @{ */
+ std::basic_streambuf<a_CharType, a_CharTraits> *rdbuf() const RT_NOEXCEPT
+ {
+ return m_pBuf;
+ }
+
+ std::basic_streambuf<a_CharType, a_CharTraits> *rdbuf(std::basic_streambuf<a_CharType, a_CharTraits> *a_pNewbuf) RT_NOEXCEPT
+ {
+ std::basic_streambuf<a_CharType, a_CharTraits> *pOldBuf = m_pBuf;
+ m_pBuf = a_pNewBuf;
+ return pOldBuf;
+ }
+
+ std::basic_ostream<a_CharType, a_CharTraits> *tie() const
+ {
+ return m_pTiedStream;
+ }
+
+ std::basic_ostream<a_CharType, a_CharTraits> tie(std::basic_ostream<a_CharType, a_CharTraits> *a_pNew) const RT_NOEXCEPT
+ {
+ std::basic_ostream<a_CharType, a_CharTraits> * const pOld = m_pTiedStream;
+ m_pTiedStream = a_pNew;
+ return pOld;
+ }
+ /** @} */
+
+ /** @todo implement the rest... */
+ };
+}
+
+#endif /* !VBOX_INCLUDED_SRC_nocrt_ios */
+
diff --git a/include/iprt/nocrt/iosfwd b/include/iprt/nocrt/iosfwd
new file mode 100644
index 00000000..835f4a5e
--- /dev/null
+++ b/include/iprt/nocrt/iosfwd
@@ -0,0 +1,81 @@
+/** @file
+ * IPRT / No-CRT - Minimal C++ iosfwd header.
+ */
+
+/*
+ * Copyright (C) 2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_SRC_nocrt_iosfwd
+#define VBOX_INCLUDED_SRC_nocrt_iosfwd
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/nocrt/memory>
+#include <iprt/nocrt/string>
+
+#ifdef _MSC_VER
+# pragma warning(push)
+# pragma warning(disable: 4643) /* warning C4643: Forward declaring 'ios_base' in namespace std is not permitted by the C++ Standard */
+#endif
+
+namespace std
+{
+ using streamoff = RTFOFF;
+
+ class ios_base;
+
+ template<typename a_CharType, typename a_CharTraits = std::char_traits<a_CharType> > class basic_ios;
+ template<typename a_CharType, typename a_CharTraits = std::char_traits<a_CharType> > class basic_streambuf;
+ template<typename a_CharType, typename a_CharTraits = std::char_traits<a_CharType> > class basic_istream;
+ template<typename a_CharType, typename a_CharTraits = std::char_traits<a_CharType> > class basic_ostream;
+ template<typename a_CharType, typename a_CharTraits = std::char_traits<a_CharType> > class basic_iostream;
+ template<typename a_CharType, typename a_CharTraits = std::char_traits<a_CharType> > class basic_ifstream;
+ template<typename a_CharType, typename a_CharTraits = std::char_traits<a_CharType> > class basic_ofstream;
+ template<typename a_CharType, typename a_CharTraits = std::char_traits<a_CharType> > class basic_fstream;
+
+
+ typedef basic_ios<char> ios;
+ typedef basic_streambuf<char> streambuf;
+ typedef basic_istream<char> istream;
+ typedef basic_ostream<char> ostream;
+ typedef basic_iostream<char> iostream;
+ typedef basic_ifstream<char> ifstream;
+ typedef basic_ofstream<char> ofstream;
+ typedef basic_fstream<char> fstream;
+}
+
+#ifdef _MSC_VER
+# pragma warning(pop)
+#endif
+
+#endif /* !VBOX_INCLUDED_SRC_nocrt_iosfwd */
+
diff --git a/include/iprt/nocrt/iostream b/include/iprt/nocrt/iostream
new file mode 100644
index 00000000..d4997a99
--- /dev/null
+++ b/include/iprt/nocrt/iostream
@@ -0,0 +1,53 @@
+/** @file
+ * IPRT / No-CRT - Minimal C++ iostream header.
+ */
+
+/*
+ * Copyright (C) 2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_SRC_nocrt_iostream
+#define VBOX_INCLUDED_SRC_nocrt_iostream
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/nocrt/iosfwd>
+
+namespace std
+{
+ extern istream cin;
+ extern ostream cout;
+ extern ostream cerr;
+ extern ostream clog; /**< buffered cerr */
+}
+
+#endif /* !VBOX_INCLUDED_SRC_nocrt_iostream */
+
diff --git a/include/iprt/nocrt/limits b/include/iprt/nocrt/limits
new file mode 100644
index 00000000..0d414536
--- /dev/null
+++ b/include/iprt/nocrt/limits
@@ -0,0 +1,494 @@
+/** @file
+ * IPRT / No-CRT - C++ limits header.
+ */
+
+/*
+ * Copyright (C) 2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_SRC_nocrt_limits
+#define VBOX_INCLUDED_SRC_nocrt_limits
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/nocrt/limits.h>
+#include <iprt/nocrt/float.h>
+
+namespace std
+{
+ enum float_denorm_style
+ {
+ denorm_indeterminate = -1,
+ denorm_absent,
+ denorm_present,
+ };
+
+ enum float_round_style
+ {
+ round_indeterminate = -1,
+ round_toward_zero,
+ round_to_nearest,
+ round_toward_infinity,
+ round_toward_neg_infinity,
+ };
+
+ struct rtNoCrtLimitNumericBase
+ {
+ static const bool is_specialized = false;
+ static const bool is_integer = false;
+ static const bool is_signed = false;
+ static const bool is_exact = false;
+ static const bool is_bounded = false;
+
+ static const bool has_infinity = false;
+ static const bool has_quiet_NaN = false;
+ static const bool has_signaling_NaN = false;
+ static const bool has_denorm_loss = false;
+ static const bool is_iec559 = false;
+ static const bool is_modulo = false;
+ static const bool traps = false;
+ static const bool tinyness_before = false;
+
+ static const int digits = 0;
+ static const int digits10 = 0;
+ static const int max_digits10 = 0;
+ static const int radix = 0;
+ static const int min_exponent = 0;
+ static const int min_exponent10 = 0;
+ static const int max_exponent = 0;
+ static const int max_exponent10 = 0;
+
+ static const float_denorm_style has_denorm = denorm_absent;
+ static const float_round_style round_style = round_toward_zero;
+ };
+
+ struct rtNoCrtLimitNumericIntBase : public rtNoCrtLimitNumericBase
+ {
+ static const bool is_specialized = true;
+ static const bool is_integer = true;
+ static const bool is_exact = true;
+ static const bool is_bounded = true;
+ static const int radix = 2;
+ };
+
+ struct rtNoCrtLimitNumericFloatBase : public rtNoCrtLimitNumericBase
+ {
+ static const bool is_specialized = true;
+ static const bool is_signed = true;
+ static const bool is_bounded = true;
+ static const bool has_infinity = false;
+ static const bool has_quiet_NaN = false;
+ static const bool has_signaling_NaN = false;
+ static const bool is_iec559 = false;
+ static const int radix = FLT_RADIX;
+ static const float_denorm_style has_denorm = denorm_present;
+ static const float_round_style round_style = round_to_nearest;
+ };
+
+ /*
+ * Generic template.
+ */
+ template<typename a_Type>
+ struct numeric_limits : public rtNoCrtLimitNumericBase
+ {
+ /** @todo need a RT_CONSTEXPR_FN etc */
+ static constexpr a_Type(min)() RT_NOEXCEPT { return a_Type(); }
+ static constexpr a_Type(max)() RT_NOEXCEPT { return a_Type(); }
+ static constexpr a_Type lowest() RT_NOEXCEPT { return a_Type(); }
+ static constexpr a_Type epsilon() RT_NOEXCEPT { return a_Type(); }
+ static constexpr a_Type round_error() RT_NOEXCEPT { return a_Type(); }
+ static constexpr a_Type infinity() RT_NOEXCEPT { return a_Type(); }
+ static constexpr a_Type quiet_NaN() RT_NOEXCEPT { return a_Type(); }
+ static constexpr a_Type signaling_NaN() RT_NOEXCEPT { return a_Type(); }
+ static constexpr a_Type denorm_min() RT_NOEXCEPT { return a_Type(); }
+ };
+
+ /* const and volatile trickery: */
+ template<typename a_Type> struct numeric_limits<const a_Type> : public numeric_limits<a_Type> {};
+ template<typename a_Type> struct numeric_limits<volatile a_Type> : public numeric_limits<a_Type> {};
+ template<typename a_Type> struct numeric_limits<const volatile a_Type> : public numeric_limits<a_Type> {};
+
+ /*
+ * Integer specializations.
+ */
+ template<>
+ struct numeric_limits<bool> : public rtNoCrtLimitNumericIntBase
+ {
+ static constexpr bool(min)() RT_NOEXCEPT { return false; }
+ static constexpr bool(max)() RT_NOEXCEPT { return true; }
+ static constexpr bool lowest() RT_NOEXCEPT { return false; }
+ static constexpr bool epsilon() RT_NOEXCEPT { return false; }
+ static constexpr bool round_error() RT_NOEXCEPT { return false; }
+ static constexpr bool infinity() RT_NOEXCEPT { return false; }
+ static constexpr bool quiet_NaN() RT_NOEXCEPT { return false; }
+ static constexpr bool signaling_NaN() RT_NOEXCEPT { return false; }
+ static constexpr bool denorm_min() RT_NOEXCEPT { return false; }
+ static const int digits = 1;
+ };
+
+ template<>
+ struct numeric_limits<char> : public rtNoCrtLimitNumericIntBase
+ {
+ static constexpr char(min)() RT_NOEXCEPT { return CHAR_MIN; }
+ static constexpr char(max)() RT_NOEXCEPT { return CHAR_MAX; }
+ static constexpr char lowest() RT_NOEXCEPT { return CHAR_MIN; }
+ static constexpr char epsilon() RT_NOEXCEPT { return 0; }
+ static constexpr char round_error() RT_NOEXCEPT { return 0; }
+ static constexpr char infinity() RT_NOEXCEPT { return 0; }
+ static constexpr char quiet_NaN() RT_NOEXCEPT { return 0; }
+ static constexpr char signaling_NaN() RT_NOEXCEPT { return 0; }
+ static constexpr char denorm_min() RT_NOEXCEPT { return 0; }
+
+ static const bool is_signed = (char)(-1) < 0;
+ static const bool is_modulo = (char)(-1) > 0;
+ static const int digits = (char)(-1) < 0 ? CHAR_BIT - 1 : CHAR_BIT;
+ static const int digits10 = 2;
+ };
+
+ template<>
+ struct numeric_limits<signed char> : public rtNoCrtLimitNumericIntBase
+ {
+ static constexpr signed char(min)() RT_NOEXCEPT { return SCHAR_MIN; }
+ static constexpr signed char(max)() RT_NOEXCEPT { return SCHAR_MAX; }
+ static constexpr signed char lowest() RT_NOEXCEPT { return SCHAR_MIN; }
+ static constexpr signed char epsilon() RT_NOEXCEPT { return 0; }
+ static constexpr signed char round_error() RT_NOEXCEPT { return 0; }
+ static constexpr signed char infinity() RT_NOEXCEPT { return 0; }
+ static constexpr signed char quiet_NaN() RT_NOEXCEPT { return 0; }
+ static constexpr signed char signaling_NaN() RT_NOEXCEPT { return 0; }
+ static constexpr signed char denorm_min() RT_NOEXCEPT { return 0; }
+
+ static const bool is_signed = true;
+ static const int digits = CHAR_BIT - 1;
+ static const int digits10 = 2;
+ };
+
+ template<>
+ struct numeric_limits<unsigned char> : public rtNoCrtLimitNumericIntBase
+ {
+ static constexpr unsigned char(min)() RT_NOEXCEPT { return 0; }
+ static constexpr unsigned char(max)() RT_NOEXCEPT { return UCHAR_MAX; }
+ static constexpr unsigned char lowest() RT_NOEXCEPT { return 0; }
+ static constexpr unsigned char epsilon() RT_NOEXCEPT { return 0; }
+ static constexpr unsigned char round_error() RT_NOEXCEPT { return 0; }
+ static constexpr unsigned char infinity() RT_NOEXCEPT { return 0; }
+ static constexpr unsigned char quiet_NaN() RT_NOEXCEPT { return 0; }
+ static constexpr unsigned char signaling_NaN() RT_NOEXCEPT { return 0; }
+ static constexpr unsigned char denorm_min() RT_NOEXCEPT { return 0; }
+
+ static const bool is_modulo = true;
+ static const int digits = CHAR_BIT;
+ static const int digits10 = 2;
+ };
+
+ /** @todo wchar_t, char8_t, char16_t, char32_t */
+
+ template<>
+ struct numeric_limits<short> : public rtNoCrtLimitNumericIntBase
+ {
+ static constexpr short(min)() RT_NOEXCEPT { return SHRT_MIN; }
+ static constexpr short(max)() RT_NOEXCEPT { return SHRT_MAX; }
+ static constexpr short lowest() RT_NOEXCEPT { return SHRT_MIN; }
+ static constexpr short epsilon() RT_NOEXCEPT { return 0; }
+ static constexpr short round_error() RT_NOEXCEPT { return 0; }
+ static constexpr short infinity() RT_NOEXCEPT { return 0; }
+ static constexpr short quiet_NaN() RT_NOEXCEPT { return 0; }
+ static constexpr short signaling_NaN() RT_NOEXCEPT { return 0; }
+ static constexpr short denorm_min() RT_NOEXCEPT { return 0; }
+
+ static const bool is_signed = true;
+ static const int digits = CHAR_BIT * sizeof(short) - 1;
+ static const int digits10 = 4;
+ };
+
+ template<>
+ struct numeric_limits<unsigned short> : public rtNoCrtLimitNumericIntBase
+ {
+ static constexpr unsigned short(min)() RT_NOEXCEPT { return 0; }
+ static constexpr unsigned short(max)() RT_NOEXCEPT { return USHRT_MAX; }
+ static constexpr unsigned short lowest() RT_NOEXCEPT { return 0; }
+ static constexpr unsigned short epsilon() RT_NOEXCEPT { return 0; }
+ static constexpr unsigned short round_error() RT_NOEXCEPT { return 0; }
+ static constexpr unsigned short infinity() RT_NOEXCEPT { return 0; }
+ static constexpr unsigned short quiet_NaN() RT_NOEXCEPT { return 0; }
+ static constexpr unsigned short signaling_NaN() RT_NOEXCEPT { return 0; }
+ static constexpr unsigned short denorm_min() RT_NOEXCEPT { return 0; }
+
+ static const bool is_modulo = true;
+ static const int digits = CHAR_BIT * sizeof(unsigned short);
+ static const int digits10 = 4;
+ };
+
+# if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
+ template<>
+ struct numeric_limits<wchar_t> : public rtNoCrtLimitNumericIntBase
+ {
+ static constexpr wchar_t(min)() RT_NOEXCEPT { return WCHAR_MIN; }
+ static constexpr wchar_t(max)() RT_NOEXCEPT { return WCHAR_MAX; }
+ static constexpr wchar_t lowest() RT_NOEXCEPT { return WCHAR_MIN; }
+ static constexpr wchar_t epsilon() RT_NOEXCEPT { return 0; }
+ static constexpr wchar_t round_error() RT_NOEXCEPT { return 0; }
+ static constexpr wchar_t infinity() RT_NOEXCEPT { return 0; }
+ static constexpr wchar_t quiet_NaN() RT_NOEXCEPT { return 0; }
+ static constexpr wchar_t signaling_NaN() RT_NOEXCEPT { return 0; }
+ static constexpr wchar_t denorm_min() RT_NOEXCEPT { return 0; }
+
+ static const bool is_modulo = true;
+ static const int digits = CHAR_BIT * sizeof(wchar_t);
+ static const int digits10 = sizeof(wchar_t) == 2 ? 4 : 9; /** @todo ASSUMES wchar_t is either 16 or 32 bits */
+ };
+# endif
+
+ template<>
+ struct numeric_limits<char16_t> : public rtNoCrtLimitNumericIntBase
+ {
+ static constexpr char16_t(min)() RT_NOEXCEPT { return 0; }
+ static constexpr char16_t(max)() RT_NOEXCEPT { return USHRT_MAX; }
+ static constexpr char16_t lowest() RT_NOEXCEPT { return 0; }
+ static constexpr char16_t epsilon() RT_NOEXCEPT { return 0; }
+ static constexpr char16_t round_error() RT_NOEXCEPT { return 0; }
+ static constexpr char16_t infinity() RT_NOEXCEPT { return 0; }
+ static constexpr char16_t quiet_NaN() RT_NOEXCEPT { return 0; }
+ static constexpr char16_t signaling_NaN() RT_NOEXCEPT { return 0; }
+ static constexpr char16_t denorm_min() RT_NOEXCEPT { return 0; }
+
+ static const bool is_modulo = true;
+ static const int digits = CHAR_BIT * sizeof(char16_t);
+ static const int digits10 = 4;
+ };
+
+ template<>
+ struct numeric_limits<int> : public rtNoCrtLimitNumericIntBase
+ {
+ static constexpr int(min)() RT_NOEXCEPT { return INT_MIN; }
+ static constexpr int(max)() RT_NOEXCEPT { return INT_MAX; }
+ static constexpr int lowest() RT_NOEXCEPT { return INT_MIN; }
+ static constexpr int epsilon() RT_NOEXCEPT { return 0; }
+ static constexpr int round_error() RT_NOEXCEPT { return 0; }
+ static constexpr int infinity() RT_NOEXCEPT { return 0; }
+ static constexpr int quiet_NaN() RT_NOEXCEPT { return 0; }
+ static constexpr int signaling_NaN() RT_NOEXCEPT { return 0; }
+ static constexpr int denorm_min() RT_NOEXCEPT { return 0; }
+
+ static const bool is_signed = true;
+ static const int digits = CHAR_BIT * sizeof(int) - 1;
+ static const int digits10 = 9;
+ };
+
+ template<>
+ struct numeric_limits<unsigned int> : public rtNoCrtLimitNumericIntBase
+ {
+ static constexpr unsigned int(min)() RT_NOEXCEPT { return 0; }
+ static constexpr unsigned int(max)() RT_NOEXCEPT { return UINT_MAX; }
+ static constexpr unsigned int lowest() RT_NOEXCEPT { return 0; }
+ static constexpr unsigned int epsilon() RT_NOEXCEPT { return 0; }
+ static constexpr unsigned int round_error() RT_NOEXCEPT { return 0; }
+ static constexpr unsigned int infinity() RT_NOEXCEPT { return 0; }
+ static constexpr unsigned int quiet_NaN() RT_NOEXCEPT { return 0; }
+ static constexpr unsigned int signaling_NaN() RT_NOEXCEPT { return 0; }
+ static constexpr unsigned int denorm_min() RT_NOEXCEPT { return 0; }
+
+ static const bool is_modulo = true;
+ static const int digits = CHAR_BIT * sizeof(unsigned int);
+ static const int digits10 = 9;
+ };
+
+ template<>
+ struct numeric_limits<char32_t> : public rtNoCrtLimitNumericIntBase
+ {
+ static constexpr char32_t(min)() RT_NOEXCEPT { return 0; }
+ static constexpr char32_t(max)() RT_NOEXCEPT { return UINT_MAX; }
+ static constexpr char32_t lowest() RT_NOEXCEPT { return 0; }
+ static constexpr char32_t epsilon() RT_NOEXCEPT { return 0; }
+ static constexpr char32_t round_error() RT_NOEXCEPT { return 0; }
+ static constexpr char32_t infinity() RT_NOEXCEPT { return 0; }
+ static constexpr char32_t quiet_NaN() RT_NOEXCEPT { return 0; }
+ static constexpr char32_t signaling_NaN() RT_NOEXCEPT { return 0; }
+ static constexpr char32_t denorm_min() RT_NOEXCEPT { return 0; }
+
+ static const bool is_modulo = true;
+ static const int digits = CHAR_BIT * sizeof(char32_t);
+ static const int digits10 = 9;
+ };
+
+ template<>
+ struct numeric_limits<long> : public rtNoCrtLimitNumericIntBase
+ {
+ static constexpr long(min)() RT_NOEXCEPT { return LONG_MIN; }
+ static constexpr long(max)() RT_NOEXCEPT { return LONG_MAX; }
+ static constexpr long lowest() RT_NOEXCEPT { return LONG_MIN; }
+ static constexpr long epsilon() RT_NOEXCEPT { return 0; }
+ static constexpr long round_error() RT_NOEXCEPT { return 0; }
+ static constexpr long infinity() RT_NOEXCEPT { return 0; }
+ static constexpr long quiet_NaN() RT_NOEXCEPT { return 0; }
+ static constexpr long signaling_NaN() RT_NOEXCEPT { return 0; }
+ static constexpr long denorm_min() RT_NOEXCEPT { return 0; }
+
+ static const bool is_signed = true;
+ static const int digits = CHAR_BIT * sizeof(long) - 1;
+ static const int digits10 = sizeof(long) == sizeof(int) ? 9 : 18;
+ };
+
+ template<>
+ struct numeric_limits<unsigned long> : public rtNoCrtLimitNumericIntBase
+ {
+ static constexpr unsigned long(min)() RT_NOEXCEPT { return 0; }
+ static constexpr unsigned long(max)() RT_NOEXCEPT { return ULONG_MAX; }
+ static constexpr unsigned long lowest() RT_NOEXCEPT { return 0; }
+ static constexpr unsigned long epsilon() RT_NOEXCEPT { return 0; }
+ static constexpr unsigned long round_error() RT_NOEXCEPT { return 0; }
+ static constexpr unsigned long infinity() RT_NOEXCEPT { return 0; }
+ static constexpr unsigned long quiet_NaN() RT_NOEXCEPT { return 0; }
+ static constexpr unsigned long signaling_NaN() RT_NOEXCEPT { return 0; }
+ static constexpr unsigned long denorm_min() RT_NOEXCEPT { return 0; }
+
+ static const bool is_modulo = true;
+ static const int digits = CHAR_BIT * sizeof(unsigned long);
+ static const int digits10 = sizeof(unsigned long) == sizeof(unsigned int) ? 9 : 19;
+ };
+
+ template<>
+ struct numeric_limits<long long> : public rtNoCrtLimitNumericIntBase
+ {
+ static constexpr long long(min)() RT_NOEXCEPT { return LLONG_MIN; }
+ static constexpr long long(max)() RT_NOEXCEPT { return LLONG_MAX; }
+ static constexpr long long lowest() RT_NOEXCEPT { return LLONG_MIN; }
+ static constexpr long long epsilon() RT_NOEXCEPT { return 0; }
+ static constexpr long long round_error() RT_NOEXCEPT { return 0; }
+ static constexpr long long infinity() RT_NOEXCEPT { return 0; }
+ static constexpr long long quiet_NaN() RT_NOEXCEPT { return 0; }
+ static constexpr long long signaling_NaN() RT_NOEXCEPT { return 0; }
+ static constexpr long long denorm_min() RT_NOEXCEPT { return 0; }
+
+ static const bool is_signed = true;
+ static const int digits = CHAR_BIT * sizeof(long long) - 1;
+ static const int digits10 = 18;
+ };
+
+ template<>
+ struct numeric_limits<unsigned long long> : public rtNoCrtLimitNumericIntBase
+ {
+ static constexpr unsigned long long(min)() RT_NOEXCEPT { return 0; }
+ static constexpr unsigned long long(max)() RT_NOEXCEPT { return ULLONG_MAX; }
+ static constexpr unsigned long long lowest() RT_NOEXCEPT { return 0; }
+ static constexpr unsigned long long epsilon() RT_NOEXCEPT { return 0; }
+ static constexpr unsigned long long round_error() RT_NOEXCEPT { return 0; }
+ static constexpr unsigned long long infinity() RT_NOEXCEPT { return 0; }
+ static constexpr unsigned long long quiet_NaN() RT_NOEXCEPT { return 0; }
+ static constexpr unsigned long long signaling_NaN() RT_NOEXCEPT { return 0; }
+ static constexpr unsigned long long denorm_min() RT_NOEXCEPT { return 0; }
+
+ static const bool is_modulo = true;
+ static const int digits = CHAR_BIT * sizeof(unsigned long long);
+ static const int digits10 = 19;
+ };
+
+
+ /*
+ * Floating point.
+ */
+ template<>
+ struct numeric_limits<float> : public rtNoCrtLimitNumericFloatBase
+ {
+ static constexpr float(min)() RT_NOEXCEPT { return FLT_MIN; }
+ static constexpr float(max)() RT_NOEXCEPT { return FLT_MAX; }
+ static constexpr float lowest() RT_NOEXCEPT { return -(FLT_MAX); }
+ static constexpr float epsilon() RT_NOEXCEPT { return FLT_EPSILON; }
+ static constexpr float round_error() RT_NOEXCEPT { return 0.5F; }
+ static constexpr float infinity() RT_NOEXCEPT { return __builtin_huge_valf(); }
+ static constexpr float quiet_NaN() RT_NOEXCEPT { return __builtin_nanf("0"); }
+ static constexpr float signaling_NaN() RT_NOEXCEPT { return __builtin_nansf("1"); }
+ static constexpr float denorm_min() RT_NOEXCEPT { return FLT_TRUE_MIN; }
+
+ static const int digits = FLT_MANT_DIG;
+ static const int digits10 = FLT_DIG;
+ static const int max_digits10 = FLT_DECIMAL_DIG;
+ static const int max_exponent = FLT_MAX_EXP;
+ static const int max_exponent10 = FLT_MAX_10_EXP;
+ static const int min_exponent = FLT_MIN_EXP;
+ static const int min_exponent10 = FLT_MIN_10_EXP;
+ };
+
+ template<>
+ struct numeric_limits<double> : public rtNoCrtLimitNumericFloatBase
+ {
+ static constexpr double(min)() RT_NOEXCEPT { return DBL_MIN; }
+ static constexpr double(max)() RT_NOEXCEPT { return DBL_MAX; }
+ static constexpr double lowest() RT_NOEXCEPT { return -(DBL_MAX); }
+ static constexpr double epsilon() RT_NOEXCEPT { return DBL_EPSILON; }
+ static constexpr double round_error() RT_NOEXCEPT { return 0.5; }
+ static constexpr double infinity() RT_NOEXCEPT { return __builtin_huge_val(); }
+ static constexpr double quiet_NaN() RT_NOEXCEPT { return __builtin_nan("0"); }
+ static constexpr double signaling_NaN() RT_NOEXCEPT { return __builtin_nans("1"); }
+ static constexpr double denorm_min() RT_NOEXCEPT { return DBL_TRUE_MIN; }
+
+ static const int digits = DBL_MANT_DIG;
+ static const int digits10 = DBL_DIG;
+ static const int max_digits10 = DBL_DECIMAL_DIG;
+ static const int max_exponent = DBL_MAX_EXP;
+ static const int max_exponent10 = DBL_MAX_10_EXP;
+ static const int min_exponent = DBL_MIN_EXP;
+ static const int min_exponent10 = DBL_MIN_10_EXP;
+ };
+
+ template<>
+ struct numeric_limits<long double> : public rtNoCrtLimitNumericFloatBase
+ {
+ static constexpr long double(min)() RT_NOEXCEPT { return LDBL_MIN; }
+ static constexpr long double(max)() RT_NOEXCEPT { return LDBL_MAX; }
+ static constexpr long double lowest() RT_NOEXCEPT { return -(LDBL_MAX); }
+ static constexpr long double epsilon() RT_NOEXCEPT { return LDBL_EPSILON; }
+ static constexpr long double round_error() RT_NOEXCEPT { return 0.5L; }
+#if LDBL_DIG == DBL_DIG
+ static constexpr long double infinity() RT_NOEXCEPT { return __builtin_huge_val(); }
+ static constexpr long double quiet_NaN() RT_NOEXCEPT { return __builtin_nan("0"); }
+ static constexpr long double signaling_NaN() RT_NOEXCEPT { return __builtin_nans("1"); }
+#else
+ static constexpr long double infinity() RT_NOEXCEPT { return __builtin_huge_vall(); }
+ static constexpr long double quiet_NaN() RT_NOEXCEPT { return __builtin_nanl("0"); }
+ static constexpr long double signaling_NaN() RT_NOEXCEPT { return __builtin_nansl("1"); }
+#endif
+ static constexpr long double denorm_min() RT_NOEXCEPT { return LDBL_TRUE_MIN; }
+
+ static const int digits = LDBL_MANT_DIG;
+ static const int digits10 = LDBL_DIG;
+ static const int max_digits10 = LDBL_DECIMAL_DIG;
+ static const int max_exponent = LDBL_MAX_EXP;
+ static const int max_exponent10 = LDBL_MAX_10_EXP;
+ static const int min_exponent = LDBL_MIN_EXP;
+ static const int min_exponent10 = LDBL_MIN_10_EXP;
+ };
+
+ /** @todo more types */
+}
+
+#endif /* !VBOX_INCLUDED_SRC_nocrt_limits */
+
diff --git a/include/iprt/nocrt/limits.h b/include/iprt/nocrt/limits.h
new file mode 100644
index 00000000..7b2e060b
--- /dev/null
+++ b/include/iprt/nocrt/limits.h
@@ -0,0 +1,109 @@
+/** @file
+ * IPRT / No-CRT - Our own limits header.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_nocrt_limits_h
+#define IPRT_INCLUDED_nocrt_limits_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#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) || defined(RT_ARCH_ARM32)
+# 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) || defined(RT_ARCH_ARM64)
+# 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)
+
+#undef SIZE_MAX
+#undef SIZE_T_MAX
+#undef SSIZE_MAX
+#undef INTPTR_MAX
+#undef UINTPTR_MAX
+#if ARCH_BITS == 32
+# define SIZE_T_MAX 0xffffffffU
+# define SSIZE_MAX 0x7fffffff
+# define INTPTR_MAX 0x7fffffff
+# define UINTPTR_MAX 0xffffffffU
+#elif ARCH_BITS == 64
+# define SIZE_T_MAX UINT64_C(0xffffffffffffffff)
+# define SSIZE_MAX INT64_C(0x7fffffffffffffff)
+# define INTPTR_MAX INT64_C(0x7fffffffffffffff)
+# define UINTPTR_MAX UINT64_C(0xffffffffffffffff)
+#else
+# error "huh?"
+#endif
+#define SIZE_MAX SIZE_T_MAX
+
+/*#define OFF_MAX __OFF_MAX
+#define OFF_MIN __OFF_MIN*/
+
+#endif /* !IPRT_INCLUDED_nocrt_limits_h */
+
diff --git a/include/iprt/nocrt/malloc.h b/include/iprt/nocrt/malloc.h
new file mode 100644
index 00000000..57c5aa4f
--- /dev/null
+++ b/include/iprt/nocrt/malloc.h
@@ -0,0 +1,49 @@
+/** @file
+ * IPRT / No-CRT - Our own minimal malloc.h header (needed by xmmintrin.h).
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_nocrt_malloc_h
+#define IPRT_INCLUDED_nocrt_malloc_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+/* Just map it onto stdlib.h and alloca.h for now. */
+#include <stdlib.h>
+#ifdef IN_RING3
+# include <iprt/alloca.h>
+#endif
+
+#endif /* !IPRT_INCLUDED_nocrt_malloc_h */
+
diff --git a/include/iprt/nocrt/math.h b/include/iprt/nocrt/math.h
new file mode 100644
index 00000000..4ae2c48c
--- /dev/null
+++ b/include/iprt/nocrt/math.h
@@ -0,0 +1,859 @@
+/** @file
+ * IPRT / No-CRT - math.h.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ * --------------------------------------------------------------------
+ *
+ * This code is based on:
+ *
+ * from: @(#)fdlibm.h 5.1 93/09/24
+ * $FreeBSD: src/lib/msun/src/math.h,v 1.61 2005/04/16 21:12:47 das Exp $
+ * FreeBSD HEAD 2005-06-xx
+ *
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#ifndef IPRT_INCLUDED_nocrt_math_h
+#define IPRT_INCLUDED_nocrt_math_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+/*#include <machine/_limits.h>*/
+
+/* from sys/cdefs.h */
+#if defined(__GNUC__) && !defined(__INTEL_COMPILER)
+#define __GNUC_PREREQ__(ma, mi) \
+ (__GNUC__ > (ma) || __GNUC__ == (ma) && __GNUC_MINOR__ >= (mi))
+#else
+#define __GNUC_PREREQ__(ma, mi) 0
+#endif
+#undef __pure2 /* darwin: avoid conflict with system headers when doing syntax checking of the headers */
+#define __pure2
+
+
+/*
+ * ANSI/POSIX
+ */
+extern const union __infinity_un {
+ RTFLOAT64U __uu;
+ double __ud;
+} RT_NOCRT(__infinity);
+
+extern const union __nanf_un {
+ RTFLOAT32U __uu;
+ float __uf;
+} RT_NOCRT(__nanf);
+
+#if __GNUC_PREREQ__(3, 3) || (defined(__INTEL_COMPILER) && __INTEL_COMPILER >= 800)
+#define __MATH_BUILTIN_CONSTANTS
+#endif
+
+#if __GNUC_PREREQ__(3, 0) && !defined(__INTEL_COMPILER)
+#define __MATH_BUILTIN_RELOPS
+#endif
+
+#ifndef IPRT_NOCRT_WITHOUT_CONFLICTING_CONSTANTS
+
+# if defined(__MATH_BUILTIN_CONSTANTS) \
+ || (RT_MSC_PREREQ(RT_MSC_VER_VC140) && defined(__cplusplus)) /** @todo when was this added exactly? 2015, 2017 & 2019 has it for C++. */
+# define HUGE_VAL __builtin_huge_val()
+# else
+# define HUGE_VAL (RT_NOCRT(__infinity).__ud)
+# endif
+
+/*
+ * XOPEN/SVID
+ */
+# if 1/* __BSD_VISIBLE || __XSI_VISIBLE*/
+# define M_E 2.7182818284590452354 /* e */
+# define M_LOG2E 1.4426950408889634074 /* log 2e */
+# define M_LOG10E 0.43429448190325182765 /* log 10e */
+# define M_LN2 0.69314718055994530942 /* log e2 */
+# define M_LN10 2.30258509299404568402 /* log e10 */
+# define M_PI 3.14159265358979323846 /* pi */
+# define M_PI_2 1.57079632679489661923 /* pi/2 */
+# define M_PI_4 0.78539816339744830962 /* pi/4 */
+# define M_1_PI 0.31830988618379067154 /* 1/pi */
+# define M_2_PI 0.63661977236758134308 /* 2/pi */
+# define M_2_SQRTPI 1.12837916709551257390 /* 2/sqrt(pi) */
+# define M_SQRT2 1.41421356237309504880 /* sqrt(2) */
+# define M_SQRT1_2 0.70710678118654752440 /* 1/sqrt(2) */
+
+# define MAXFLOAT ((float)3.40282346638528860e+38)
+extern int RT_NOCRT(signgam);
+# endif /* __BSD_VISIBLE || __XSI_VISIBLE */
+
+# if 1/* __BSD_VISIBLE*/
+# if 0
+/* Old value from 4.4BSD-Lite math.h; this is probably better. */
+# define HUGE HUGE_VAL
+# else
+# define HUGE MAXFLOAT
+# endif
+# endif /* __BSD_VISIBLE */
+
+#endif /* !IPRT_NOCRT_WITHOUT_MATH_CONSTANTS */
+
+/*
+ * Most of these functions depend on the rounding mode and have the side
+ * effect of raising floating-point exceptions, so they are not declared
+ * as __pure2. In C99, FENV_ACCESS affects the purity of these functions.
+ */
+RT_C_DECLS_BEGIN
+/*
+ * ANSI/POSIX
+ */
+int RT_NOCRT(__fpclassifyd)(double) __pure2;
+int RT_NOCRT(__fpclassifyf)(float) __pure2;
+int RT_NOCRT(__fpclassifyl)(long double) __pure2;
+int RT_NOCRT(__isfinitef)(float) __pure2;
+int RT_NOCRT(__isfinite)(double) __pure2;
+int RT_NOCRT(__isfinitel)(long double) __pure2;
+int RT_NOCRT(__isinff)(float) __pure2;
+int RT_NOCRT(__isinfl)(long double) __pure2;
+int RT_NOCRT(__isnanl)(long double) __pure2;
+int RT_NOCRT(__isnormalf)(float) __pure2;
+int RT_NOCRT(__isnormal)(double) __pure2;
+int RT_NOCRT(__isnormall)(long double) __pure2;
+int RT_NOCRT(__signbit)(double) __pure2;
+int RT_NOCRT(__signbitf)(float) __pure2;
+int RT_NOCRT(__signbitl)(long double) __pure2;
+
+double RT_NOCRT(acos)(double);
+double RT_NOCRT(asin)(double);
+double RT_NOCRT(atan)(double);
+double RT_NOCRT(atan2)(double, double);
+double RT_NOCRT(cos)(double);
+double RT_NOCRT(sin)(double);
+double RT_NOCRT(tan)(double);
+
+double RT_NOCRT(cosh)(double);
+double RT_NOCRT(sinh)(double);
+double RT_NOCRT(tanh)(double);
+
+double RT_NOCRT(exp)(double);
+double RT_NOCRT(frexp)(double, int *); /* fundamentally !__pure2 */
+double RT_NOCRT(ldexp)(double, int);
+double RT_NOCRT(log)(double);
+double RT_NOCRT(log10)(double);
+double RT_NOCRT(modf)(double, double *); /* fundamentally !__pure2 */
+
+double RT_NOCRT(pow)(double, double);
+double RT_NOCRT(sqrt)(double);
+
+double RT_NOCRT(ceil)(double);
+double RT_NOCRT(fabs)(double) __pure2;
+double RT_NOCRT(floor)(double);
+double RT_NOCRT(fmod)(double, double);
+
+/*
+ * These functions are not in C90.
+ */
+#if 1 /*__BSD_VISIBLE || __ISO_C_VISIBLE >= 1999 || __XSI_VISIBLE*/
+double RT_NOCRT(acosh)(double);
+double RT_NOCRT(asinh)(double);
+double RT_NOCRT(atanh)(double);
+double RT_NOCRT(cbrt)(double);
+double RT_NOCRT(erf)(double);
+double RT_NOCRT(erfc)(double);
+double RT_NOCRT(exp2)(double);
+double RT_NOCRT(expm1)(double);
+double RT_NOCRT(fma)(double, double, double);
+double RT_NOCRT(hypot)(double, double);
+int RT_NOCRT(ilogb)(double) __pure2;
+int RT_NOCRT(isinf)(double) __pure2;
+int RT_NOCRT(isnan)(double) __pure2;
+double RT_NOCRT(lgamma)(double);
+long long RT_NOCRT(llrint)(double);
+long long RT_NOCRT(llround)(double);
+double RT_NOCRT(log1p)(double);
+double RT_NOCRT(logb)(double);
+long RT_NOCRT(lrint)(double);
+long RT_NOCRT(lround)(double);
+double RT_NOCRT(nextafter)(double, double);
+double RT_NOCRT(remainder)(double, double);
+double RT_NOCRT(remquo)(double, double, int *);
+double RT_NOCRT(rint)(double);
+#endif /* __BSD_VISIBLE || __ISO_C_VISIBLE >= 1999 || __XSI_VISIBLE */
+
+#if 1/* __BSD_VISIBLE || __XSI_VISIBLE*/
+double RT_NOCRT(j0)(double);
+double RT_NOCRT(j1)(double);
+double RT_NOCRT(jn)(int, double);
+double RT_NOCRT(scalb)(double, double);
+double RT_NOCRT(y0)(double);
+double RT_NOCRT(y1)(double);
+double RT_NOCRT(yn)(int, double);
+
+#if 1/* __XSI_VISIBLE <= 500 || __BSD_VISIBLE*/
+double RT_NOCRT(gamma)(double);
+#endif
+#endif /* __BSD_VISIBLE || __XSI_VISIBLE */
+
+#if 1/* __BSD_VISIBLE || __ISO_C_VISIBLE >= 1999*/
+double RT_NOCRT(copysign)(double, double) __pure2;
+double RT_NOCRT(fdim)(double, double);
+double RT_NOCRT(fmax)(double, double) __pure2;
+double RT_NOCRT(fmin)(double, double) __pure2;
+double RT_NOCRT(nearbyint)(double);
+double RT_NOCRT(round)(double);
+double RT_NOCRT(scalbln)(double, long);
+double RT_NOCRT(scalbn)(double, int);
+double RT_NOCRT(tgamma)(double);
+double RT_NOCRT(trunc)(double);
+#endif
+
+/*
+ * BSD math library entry points
+ */
+#if 1/* __BSD_VISIBLE*/
+double RT_NOCRT(drem)(double, double);
+int RT_NOCRT(finite)(double) __pure2;
+int RT_NOCRT(isnanf)(float) __pure2;
+
+/*
+ * Reentrant version of gamma & lgamma; passes signgam back by reference
+ * as the second argument; user must allocate space for signgam.
+ */
+double RT_NOCRT(gamma_r)(double, int *);
+double RT_NOCRT(lgamma_r)(double, int *);
+
+/*
+ * IEEE Test Vector
+ */
+double RT_NOCRT(significand)(double);
+#endif /* __BSD_VISIBLE */
+
+/* float versions of ANSI/POSIX functions */
+#if 1/* __ISO_C_VISIBLE >= 1999*/
+float RT_NOCRT(acosf)(float);
+float RT_NOCRT(asinf)(float);
+float RT_NOCRT(atanf)(float);
+float RT_NOCRT(atan2f)(float, float);
+float RT_NOCRT(cosf)(float);
+float RT_NOCRT(sinf)(float);
+float RT_NOCRT(tanf)(float);
+
+float RT_NOCRT(coshf)(float);
+float RT_NOCRT(sinhf)(float);
+float RT_NOCRT(tanhf)(float);
+
+float RT_NOCRT(exp2f)(float);
+float RT_NOCRT(expf)(float);
+float RT_NOCRT(expm1f)(float);
+float RT_NOCRT(frexpf)(float, int *); /* fundamentally !__pure2 */
+int RT_NOCRT(ilogbf)(float) __pure2;
+float RT_NOCRT(ldexpf)(float, int);
+float RT_NOCRT(log10f)(float);
+float RT_NOCRT(log1pf)(float);
+float RT_NOCRT(logf)(float);
+float RT_NOCRT(modff)(float, float *); /* fundamentally !__pure2 */
+
+float RT_NOCRT(powf)(float, float);
+float RT_NOCRT(sqrtf)(float);
+
+float RT_NOCRT(ceilf)(float);
+float RT_NOCRT(fabsf)(float) __pure2;
+float RT_NOCRT(floorf)(float);
+float RT_NOCRT(fmodf)(float, float);
+float RT_NOCRT(roundf)(float);
+
+float RT_NOCRT(erff)(float);
+float RT_NOCRT(erfcf)(float);
+float RT_NOCRT(hypotf)(float, float);
+float RT_NOCRT(lgammaf)(float);
+
+float RT_NOCRT(acoshf)(float);
+float RT_NOCRT(asinhf)(float);
+float RT_NOCRT(atanhf)(float);
+float RT_NOCRT(cbrtf)(float);
+float RT_NOCRT(logbf)(float);
+float RT_NOCRT(copysignf)(float, float) __pure2;
+long long RT_NOCRT(llrintf)(float);
+long long RT_NOCRT(llroundf)(float);
+long RT_NOCRT(lrintf)(float);
+long RT_NOCRT(lroundf)(float);
+float RT_NOCRT(nearbyintf)(float);
+float RT_NOCRT(nextafterf)(float, float);
+float RT_NOCRT(remainderf)(float, float);
+float RT_NOCRT(remquof)(float, float, int *);
+float RT_NOCRT(rintf)(float);
+float RT_NOCRT(scalblnf)(float, long);
+float RT_NOCRT(scalbnf)(float, int);
+float RT_NOCRT(truncf)(float);
+
+float RT_NOCRT(fdimf)(float, float);
+float RT_NOCRT(fmaf)(float, float, float);
+float RT_NOCRT(fmaxf)(float, float) __pure2;
+float RT_NOCRT(fminf)(float, float) __pure2;
+#endif
+
+/*
+ * float versions of BSD math library entry points
+ */
+#if 1/* __BSD_VISIBLE*/
+float RT_NOCRT(dremf)(float, float);
+int RT_NOCRT(finitef)(float) __pure2;
+float RT_NOCRT(gammaf)(float);
+float RT_NOCRT(j0f)(float);
+float RT_NOCRT(j1f)(float);
+float RT_NOCRT(jnf)(int, float);
+float RT_NOCRT(scalbf)(float, float);
+float RT_NOCRT(y0f)(float);
+float RT_NOCRT(y1f)(float);
+float RT_NOCRT(ynf)(int, float);
+
+/*
+ * Float versions of reentrant version of gamma & lgamma; passes
+ * signgam back by reference as the second argument; user must
+ * allocate space for signgam.
+ */
+float RT_NOCRT(gammaf_r)(float, int *);
+float RT_NOCRT(lgammaf_r)(float, int *);
+
+/*
+ * float version of IEEE Test Vector
+ */
+float RT_NOCRT(significandf)(float);
+#endif /* __BSD_VISIBLE */
+
+/*
+ * long double versions of ISO/POSIX math functions
+ */
+#if 1/* __ISO_C_VISIBLE >= 1999*/
+#if 1 /* bird: we've got these */
+long double RT_NOCRT(acoshl)(long double);
+long double RT_NOCRT(acosl)(long double);
+long double RT_NOCRT(asinhl)(long double);
+long double RT_NOCRT(asinl)(long double);
+long double RT_NOCRT(atan2l)(long double, long double);
+long double RT_NOCRT(atanhl)(long double);
+long double RT_NOCRT(atanl)(long double);
+long double RT_NOCRT(cbrtl)(long double);
+#endif
+long double RT_NOCRT(ceill)(long double);
+long double RT_NOCRT(copysignl)(long double, long double) __pure2;
+#if 1 /* bird */
+long double RT_NOCRT(coshl)(long double);
+long double RT_NOCRT(cosl)(long double);
+long double RT_NOCRT(erfcl)(long double);
+long double RT_NOCRT(erfl)(long double);
+long double RT_NOCRT(exp2l)(long double);
+long double RT_NOCRT(expl)(long double);
+long double RT_NOCRT(expm1l)(long double);
+#endif
+long double RT_NOCRT(fabsl)(long double) __pure2;
+long double RT_NOCRT(fdiml)(long double, long double);
+long double RT_NOCRT(floorl)(long double);
+long double RT_NOCRT(fmal)(long double, long double, long double);
+long double RT_NOCRT(fmaxl)(long double, long double) __pure2;
+long double RT_NOCRT(fminl)(long double, long double) __pure2;
+#if 1 /* bird */
+long double RT_NOCRT(fmodl)(long double, long double);
+#endif
+long double RT_NOCRT(frexpl)(long double value, int *); /* fundamentally !__pure2 */
+#if 1 /* bird */
+long double RT_NOCRT(hypotl)(long double, long double);
+#endif
+int RT_NOCRT(ilogbl)(long double) __pure2;
+long double RT_NOCRT(ldexpl)(long double, int);
+#if 1 /* bird */
+long double RT_NOCRT(lgammal)(long double);
+long long RT_NOCRT(llrintl)(long double);
+#endif
+long long RT_NOCRT(llroundl)(long double);
+#if 1 /* bird */
+long double RT_NOCRT(log10l)(long double);
+long double RT_NOCRT(log1pl)(long double);
+long double RT_NOCRT(log2l)(long double);
+long double RT_NOCRT(logbl)(long double);
+long double RT_NOCRT(logl)(long double);
+long RT_NOCRT(lrintl)(long double);
+#endif
+long RT_NOCRT(lroundl)(long double);
+#if 1 /* bird */
+long double RT_NOCRT(modfl)(long double, long double *); /* fundamentally !__pure2 */
+long double RT_NOCRT(nanl)(const char *) __pure2;
+long double RT_NOCRT(nearbyintl)(long double);
+#endif
+long double RT_NOCRT(nextafterl)(long double, long double);
+double RT_NOCRT(nexttoward)(double, long double);
+float RT_NOCRT(nexttowardf)(float, long double);
+long double RT_NOCRT(nexttowardl)(long double, long double);
+#if 1 /* bird */
+long double RT_NOCRT(powl)(long double, long double);
+long double RT_NOCRT(remainderl)(long double, long double);
+long double RT_NOCRT(remquol)(long double, long double, int *);
+long double RT_NOCRT(rintl)(long double);
+#endif
+long double RT_NOCRT(roundl)(long double);
+long double RT_NOCRT(scalblnl)(long double, long);
+long double RT_NOCRT(scalbnl)(long double, int);
+#if 1 /* bird: we 've got most of these. */
+long double RT_NOCRT(sinhl)(long double);
+long double RT_NOCRT(sinl)(long double);
+long double RT_NOCRT(sqrtl)(long double);
+long double RT_NOCRT(tanhl)(long double);
+long double RT_NOCRT(tanl)(long double);
+long double RT_NOCRT(tgammal)(long double);
+#endif
+long double RT_NOCRT(truncl)(long double);
+
+/* bird: these were missing, gcc apparently inlines them. */
+double RT_NOCRT(nan)(const char *);
+float RT_NOCRT(nanf)(const char *);
+
+#endif /* __ISO_C_VISIBLE >= 1999 */
+
+#ifndef IPRT_NOCRT_WITHOUT_CONFLICTING_CONSTANTS /*def __USE_GNU*/
+/*
+ * In GLIBC there are long variants of the XOPEN/SVID constant
+ * block some pages ago. We need this to get the math tests going.
+ */
+# define M_El 2.7182818284590452353602874713526625L
+# define M_LOG2El 1.4426950408889634073599246810018921L
+# define M_LOG10El 0.4342944819032518276511289189166051L
+# define M_LN2l 0.6931471805599453094172321214581766L
+# define M_LN10l 2.3025850929940456840179914546843642L
+# define M_PIl 3.1415926535897932384626433832795029L
+# define M_PI_2l 1.5707963267948966192313216916397514L
+# define M_PI_4l 0.7853981633974483096156608458198757L
+# define M_1_PIl 0.3183098861837906715377675267450287L
+# define M_2_PIl 0.6366197723675813430755350534900574L
+# define M_2_SQRTPIl 1.1283791670955125738961589031215452L
+# define M_SQRT2l 1.4142135623730950488016887242096981L
+# define M_SQRT1_2l 0.7071067811865475244008443621048490L
+#endif /* !IPRT_NOCRT_WITHOUT_MATH_CONSTANTS */
+
+#if 1/*def __USE_GNU*/
+
+void RT_NOCRT(sincos)(double, double *, double *);
+void RT_NOCRT(sincosf)(float, float *, float *);
+void RT_NOCRT(sincosl)(long double, long double *, long double *);
+float RT_NOCRT(exp10f)(float);
+double RT_NOCRT(exp10)(double);
+long double RT_NOCRT(exp10l)(long double);
+float RT_NOCRT(log2f)(float);
+double RT_NOCRT(log2)(double);
+long double RT_NOCRT(log2l)(long double);
+float RT_NOCRT(tgammaf)(float);
+long double RT_NOCRT(significandl)(long double);
+long double RT_NOCRT(j0l)(long double);
+long double RT_NOCRT(j1l)(long double);
+long double RT_NOCRT(jnl)(int, long double);
+long double RT_NOCRT(scalbl)(long double, long double);
+long double RT_NOCRT(y0l)(long double);
+long double RT_NOCRT(y1l)(long double);
+long double RT_NOCRT(ynl)(int, long double);
+long double RT_NOCRT(lgammal_r)(long double,int *);
+long double RT_NOCRT(gammal)(long double);
+#endif
+
+
+RT_C_DECLS_END
+
+
+/** @name fpclassify return values
+ * @{ */
+#define RT_NOCRT_FP_INFINITE 0x01
+#define RT_NOCRT_FP_NAN 0x02
+#define RT_NOCRT_FP_NORMAL 0x04
+#define RT_NOCRT_FP_SUBNORMAL 0x08
+#define RT_NOCRT_FP_ZERO 0x10
+/** @} */
+
+/* bird 2022-08-03: moved this block down so we can prototype isnan & isinf without runnning into the macro forms. */
+#ifndef IPRT_NOCRT_WITHOUT_CONFLICTING_CONSTANTS /* __ISO_C_VISIBLE >= 1999*/
+# define FP_ILOGB0 (-__INT_MAX)
+# define FP_ILOGBNAN __INT_MAX
+
+# ifdef __MATH_BUILTIN_CONSTANTS
+# define HUGE_VALF __builtin_huge_valf()
+# define HUGE_VALL __builtin_huge_vall()
+# define INFINITY __builtin_inf()
+# define NAN __builtin_nan("")
+# elif RT_MSC_PREREQ(RT_MSC_VER_VC140) && defined(__cplusplus)
+/** @todo When were these introduced exactly? 2015, 2017 & 2019 has them.
+ * However, they only work in C++ even if the c1.dll includes the strings. Oh, well. */
+# define HUGE_VALF __builtin_huge_valf()
+# define HUGE_VALL __builtin_huge_val()
+# define INFINITY __builtin_huge_val()
+# define NAN __builtin_nan("0") /* same as we use in climits */
+# else
+# define HUGE_VALF (float)HUGE_VAL
+# define HUGE_VALL (long double)HUGE_VAL
+# define INFINITY HUGE_VALF
+# define NAN (__nanf.__uf)
+# endif /* __MATH_BUILTIN_CONSTANTS */
+
+# ifndef IPRT_NO_CRT
+# define MATH_ERRNO 1
+# endif
+# define MATH_ERREXCEPT 2
+# define math_errhandling MATH_ERREXCEPT
+
+/* XXX We need a <machine/math.h>. */
+# if defined(__ia64__) || defined(__sparc64__)
+# define FP_FAST_FMA
+# endif
+# ifdef __ia64__
+# define FP_FAST_FMAL
+# endif
+# define FP_FAST_FMAF
+
+/* Symbolic constants to classify floating point numbers. */
+# define FP_INFINITE RT_NOCRT_FP_INFINITE
+# define FP_NAN RT_NOCRT_FP_NAN
+# define FP_NORMAL RT_NOCRT_FP_NORMAL
+# define FP_SUBNORMAL RT_NOCRT_FP_SUBNORMAL
+# define FP_ZERO RT_NOCRT_FP_ZERO
+# define fpclassify(x) \
+ ((sizeof (x) == sizeof (float)) ? RT_NOCRT(__fpclassifyf)(x) \
+ : (sizeof (x) == sizeof (double)) ? RT_NOCRT(__fpclassifyd)(x) \
+ : RT_NOCRT(__fpclassifyl)(x))
+
+# define isfinite(x) \
+ ((sizeof (x) == sizeof (float)) ? RT_NOCRT(__isfinitef)(x) \
+ : (sizeof (x) == sizeof (double)) ? RT_NOCRT(__isfinite)(x) \
+ : RT_NOCRT(__isfinitel)(x))
+# define isinf(x) \
+ ((sizeof (x) == sizeof (float)) ? RT_NOCRT(__isinff)(x) \
+ : (sizeof (x) == sizeof (double)) ? RT_NOCRT(isinf)(x) \
+ : RT_NOCRT(__isinfl)(x))
+# define isnan(x) \
+ ((sizeof (x) == sizeof (float)) ? RT_NOCRT(isnanf)(x) \
+ : (sizeof (x) == sizeof (double)) ? RT_NOCRT(isnan)(x) \
+ : RT_NOCRT(__isnanl)(x))
+# define isnormal(x) \
+ ((sizeof (x) == sizeof (float)) ? RT_NOCRT(__isnormalf)(x) \
+ : (sizeof (x) == sizeof (double)) ? RT_NOCRT(__isnormal)(x) \
+ : RT_NOCRT(__isnormall)(x))
+
+# ifdef __MATH_BUILTIN_RELOPS
+# define isgreater(x, y) __builtin_isgreater((x), (y))
+# define isgreaterequal(x, y) __builtin_isgreaterequal((x), (y))
+# define isless(x, y) __builtin_isless((x), (y))
+# define islessequal(x, y) __builtin_islessequal((x), (y))
+# define islessgreater(x, y) __builtin_islessgreater((x), (y))
+# define isunordered(x, y) __builtin_isunordered((x), (y))
+# else
+# define isgreater(x, y) (!isunordered((x), (y)) && (x) > (y))
+# define isgreaterequal(x, y) (!isunordered((x), (y)) && (x) >= (y))
+# define isless(x, y) (!isunordered((x), (y)) && (x) < (y))
+# define islessequal(x, y) (!isunordered((x), (y)) && (x) <= (y))
+# define islessgreater(x, y) (!isunordered((x), (y)) && \
+ ((x) > (y) || (y) > (x)))
+# define isunordered(x, y) (isnan(x) || isnan(y))
+# endif /* __MATH_BUILTIN_RELOPS */
+
+# define signbit(x) \
+ ((sizeof (x) == sizeof (float)) ? RT_NOCRT(__signbitf)(x) \
+ : (sizeof (x) == sizeof (double)) ? RT_NOCRT(__signbit)(x) \
+ : RT_NOCRT(__signbitl)(x))
+
+typedef double double_t;
+typedef float float_t;
+#endif /* !IPRT_NOCRT_WITHOUT_MATH_CONSTANTS */ /* __ISO_C_VISIBLE >= 1999 */
+
+
+#if !defined(RT_WITHOUT_NOCRT_WRAPPERS) && !defined(RT_WITHOUT_NOCRT_WRAPPER_ALIASES)
+/* sed -e "/#/d" -e "/RT_NOCRT/!d" -e "s/^.*RT_NOCRT(\([a-z0-9_]*\)).*$/# define \1 RT_NOCRT(\1)/" */
+# define __fpclassifyf RT_NOCRT(__fpclassifyf)
+# define __fpclassifyd RT_NOCRT(__fpclassifyd)
+# define __fpclassifyl RT_NOCRT(__fpclassifyl)
+# define __isfinitef RT_NOCRT(__isfinitef)
+# define __isfinite RT_NOCRT(__isfinite)
+# define __isfinitel RT_NOCRT(__isfinitel)
+# define __isinff RT_NOCRT(__isinff)
+# define __isinfl RT_NOCRT(__isinfl)
+# define __isnanl RT_NOCRT(__isnanl)
+# define __isnormalf RT_NOCRT(__isnormalf)
+# define __isnormal RT_NOCRT(__isnormal)
+# define __isnormall RT_NOCRT(__isnormall)
+# define __signbitf RT_NOCRT(__signbitf)
+# define __signbit RT_NOCRT(__signbit)
+# define __signbitl RT_NOCRT(__signbitl)
+# define signgam RT_NOCRT(signgam)
+# define __fpclassifyd RT_NOCRT(__fpclassifyd)
+# define __fpclassifyf RT_NOCRT(__fpclassifyf)
+# define __fpclassifyl RT_NOCRT(__fpclassifyl)
+# define __isfinitef RT_NOCRT(__isfinitef)
+# define __isfinite RT_NOCRT(__isfinite)
+# define __isfinitel RT_NOCRT(__isfinitel)
+# define __isinff RT_NOCRT(__isinff)
+# define __isinfl RT_NOCRT(__isinfl)
+# define __isnanl RT_NOCRT(__isnanl)
+# define __isnormalf RT_NOCRT(__isnormalf)
+# define __isnormal RT_NOCRT(__isnormal)
+# define __isnormall RT_NOCRT(__isnormall)
+# define __signbit RT_NOCRT(__signbit)
+# define __signbitf RT_NOCRT(__signbitf)
+# define __signbitl RT_NOCRT(__signbitl)
+# define acos RT_NOCRT(acos)
+# define asin RT_NOCRT(asin)
+# define atan RT_NOCRT(atan)
+# define atan2 RT_NOCRT(atan2)
+# define cos RT_NOCRT(cos)
+# define sin RT_NOCRT(sin)
+# define tan RT_NOCRT(tan)
+# define cosh RT_NOCRT(cosh)
+# define sinh RT_NOCRT(sinh)
+# define tanh RT_NOCRT(tanh)
+# define exp RT_NOCRT(exp)
+# define frexp RT_NOCRT(frexp)
+# define ldexp RT_NOCRT(ldexp)
+# define log RT_NOCRT(log)
+# define log10 RT_NOCRT(log10)
+# define modf RT_NOCRT(modf)
+# define pow RT_NOCRT(pow)
+# define sqrt RT_NOCRT(sqrt)
+# define ceil RT_NOCRT(ceil)
+# define fabs RT_NOCRT(fabs)
+# define floor RT_NOCRT(floor)
+# define fmod RT_NOCRT(fmod)
+# define acosh RT_NOCRT(acosh)
+# define asinh RT_NOCRT(asinh)
+# define atanh RT_NOCRT(atanh)
+# define cbrt RT_NOCRT(cbrt)
+# define erf RT_NOCRT(erf)
+# define erfc RT_NOCRT(erfc)
+# define exp2 RT_NOCRT(exp2)
+# define expm1 RT_NOCRT(expm1)
+# define fma RT_NOCRT(fma)
+# define hypot RT_NOCRT(hypot)
+# define ilogb RT_NOCRT(ilogb)
+# define lgamma RT_NOCRT(lgamma)
+# define llrint RT_NOCRT(llrint)
+# define llround RT_NOCRT(llround)
+# define log1p RT_NOCRT(log1p)
+# define logb RT_NOCRT(logb)
+# define lrint RT_NOCRT(lrint)
+# define lround RT_NOCRT(lround)
+# define nextafter RT_NOCRT(nextafter)
+# define remainder RT_NOCRT(remainder)
+# define remquo RT_NOCRT(remquo)
+# define rint RT_NOCRT(rint)
+# define j0 RT_NOCRT(j0)
+# define j1 RT_NOCRT(j1)
+# define jn RT_NOCRT(jn)
+# define scalb RT_NOCRT(scalb)
+# define y0 RT_NOCRT(y0)
+# define y1 RT_NOCRT(y1)
+# define yn RT_NOCRT(yn)
+# define gamma RT_NOCRT(gamma)
+# define copysign RT_NOCRT(copysign)
+# define fdim RT_NOCRT(fdim)
+# define fmax RT_NOCRT(fmax)
+# define fmin RT_NOCRT(fmin)
+# define nearbyint RT_NOCRT(nearbyint)
+# define round RT_NOCRT(round)
+# define scalbln RT_NOCRT(scalbln)
+# define scalbn RT_NOCRT(scalbn)
+# define tgamma RT_NOCRT(tgamma)
+# define trunc RT_NOCRT(trunc)
+# define drem RT_NOCRT(drem)
+# define finite RT_NOCRT(finite)
+/*# define isinf RT_NOCRT(isinf) - already a macro */
+/*# define isnan RT_NOCRT(isnan) - already a macro */
+# define isnanf RT_NOCRT(isnanf)
+# define gamma_r RT_NOCRT(gamma_r)
+# define lgamma_r RT_NOCRT(lgamma_r)
+# define significand RT_NOCRT(significand)
+# define acosf RT_NOCRT(acosf)
+# define asinf RT_NOCRT(asinf)
+# define atanf RT_NOCRT(atanf)
+# define atan2f RT_NOCRT(atan2f)
+# define cosf RT_NOCRT(cosf)
+# define sinf RT_NOCRT(sinf)
+# define tanf RT_NOCRT(tanf)
+# define coshf RT_NOCRT(coshf)
+# define sinhf RT_NOCRT(sinhf)
+# define tanhf RT_NOCRT(tanhf)
+# define exp2f RT_NOCRT(exp2f)
+# define expf RT_NOCRT(expf)
+# define expm1f RT_NOCRT(expm1f)
+# define frexpf RT_NOCRT(frexpf)
+# define ilogbf RT_NOCRT(ilogbf)
+# define ldexpf RT_NOCRT(ldexpf)
+# define log10f RT_NOCRT(log10f)
+# define log1pf RT_NOCRT(log1pf)
+# define logf RT_NOCRT(logf)
+# define modff RT_NOCRT(modff)
+# define powf RT_NOCRT(powf)
+# define sqrtf RT_NOCRT(sqrtf)
+# define ceilf RT_NOCRT(ceilf)
+# define fabsf RT_NOCRT(fabsf)
+# define floorf RT_NOCRT(floorf)
+# define fmodf RT_NOCRT(fmodf)
+# define roundf RT_NOCRT(roundf)
+# define erff RT_NOCRT(erff)
+# define erfcf RT_NOCRT(erfcf)
+# define hypotf RT_NOCRT(hypotf)
+# define lgammaf RT_NOCRT(lgammaf)
+# define acoshf RT_NOCRT(acoshf)
+# define asinhf RT_NOCRT(asinhf)
+# define atanhf RT_NOCRT(atanhf)
+# define cbrtf RT_NOCRT(cbrtf)
+# define logbf RT_NOCRT(logbf)
+# define copysignf RT_NOCRT(copysignf)
+# define llrintf RT_NOCRT(llrintf)
+# define llroundf RT_NOCRT(llroundf)
+# define lrintf RT_NOCRT(lrintf)
+# define lroundf RT_NOCRT(lroundf)
+# define nearbyintf RT_NOCRT(nearbyintf)
+# define nextafterf RT_NOCRT(nextafterf)
+# define remainderf RT_NOCRT(remainderf)
+# define remquof RT_NOCRT(remquof)
+# define rintf RT_NOCRT(rintf)
+# define scalblnf RT_NOCRT(scalblnf)
+# define scalbnf RT_NOCRT(scalbnf)
+# define truncf RT_NOCRT(truncf)
+# define fdimf RT_NOCRT(fdimf)
+# define fmaf RT_NOCRT(fmaf)
+# define fmaxf RT_NOCRT(fmaxf)
+# define fminf RT_NOCRT(fminf)
+# define dremf RT_NOCRT(dremf)
+# define finitef RT_NOCRT(finitef)
+# define gammaf RT_NOCRT(gammaf)
+# define j0f RT_NOCRT(j0f)
+# define j1f RT_NOCRT(j1f)
+# define jnf RT_NOCRT(jnf)
+# define scalbf RT_NOCRT(scalbf)
+# define y0f RT_NOCRT(y0f)
+# define y1f RT_NOCRT(y1f)
+# define ynf RT_NOCRT(ynf)
+# define gammaf_r RT_NOCRT(gammaf_r)
+# define lgammaf_r RT_NOCRT(lgammaf_r)
+# define significandf RT_NOCRT(significandf)
+# define acoshl RT_NOCRT(acoshl)
+# define acosl RT_NOCRT(acosl)
+# define asinhl RT_NOCRT(asinhl)
+# define asinl RT_NOCRT(asinl)
+# define atan2l RT_NOCRT(atan2l)
+# define atanhl RT_NOCRT(atanhl)
+# define atanl RT_NOCRT(atanl)
+# define cbrtl RT_NOCRT(cbrtl)
+# define ceill RT_NOCRT(ceill)
+# define copysignl RT_NOCRT(copysignl)
+# define coshl RT_NOCRT(coshl)
+# define cosl RT_NOCRT(cosl)
+# define erfcl RT_NOCRT(erfcl)
+# define erfl RT_NOCRT(erfl)
+# define exp2l RT_NOCRT(exp2l)
+# define expl RT_NOCRT(expl)
+# define expm1l RT_NOCRT(expm1l)
+# define fabsl RT_NOCRT(fabsl)
+# define fdiml RT_NOCRT(fdiml)
+# define floorl RT_NOCRT(floorl)
+# define fmal RT_NOCRT(fmal)
+# define fmaxl RT_NOCRT(fmaxl)
+# define fminl RT_NOCRT(fminl)
+# define fmodl RT_NOCRT(fmodl)
+# define frexpl RT_NOCRT(frexpl)
+# define hypotl RT_NOCRT(hypotl)
+# define ilogbl RT_NOCRT(ilogbl)
+# define ldexpl RT_NOCRT(ldexpl)
+# define lgammal RT_NOCRT(lgammal)
+# define llrintl RT_NOCRT(llrintl)
+# define llroundl RT_NOCRT(llroundl)
+# define log10l RT_NOCRT(log10l)
+# define log1pl RT_NOCRT(log1pl)
+# define log2l RT_NOCRT(log2l)
+# define logbl RT_NOCRT(logbl)
+# define logl RT_NOCRT(logl)
+# define lrintl RT_NOCRT(lrintl)
+# define lroundl RT_NOCRT(lroundl)
+# define modfl RT_NOCRT(modfl)
+# define nanl RT_NOCRT(nanl)
+# define nearbyintl RT_NOCRT(nearbyintl)
+# define nextafterl RT_NOCRT(nextafterl)
+# define nexttoward RT_NOCRT(nexttoward)
+# define nexttowardf RT_NOCRT(nexttowardf)
+# define nexttowardl RT_NOCRT(nexttowardl)
+# define powl RT_NOCRT(powl)
+# define remainderl RT_NOCRT(remainderl)
+# define remquol RT_NOCRT(remquol)
+# define rintl RT_NOCRT(rintl)
+# define roundl RT_NOCRT(roundl)
+# define scalblnl RT_NOCRT(scalblnl)
+# define scalbnl RT_NOCRT(scalbnl)
+# define sinhl RT_NOCRT(sinhl)
+# define sinl RT_NOCRT(sinl)
+# define sqrtl RT_NOCRT(sqrtl)
+# define tanhl RT_NOCRT(tanhl)
+# define tanl RT_NOCRT(tanl)
+# define tgammal RT_NOCRT(tgammal)
+# define truncl RT_NOCRT(truncl)
+# define nan RT_NOCRT(nan)
+# define nanf RT_NOCRT(nanf)
+# define sincos RT_NOCRT(sincos)
+# define sincosf RT_NOCRT(sincosf)
+# define sincosl RT_NOCRT(sincosl)
+# define exp10f RT_NOCRT(exp10f)
+# define exp10 RT_NOCRT(exp10)
+# define exp10l RT_NOCRT(exp10l)
+# define log2f RT_NOCRT(log2f)
+# define log2 RT_NOCRT(log2)
+# define log2l RT_NOCRT(log2l)
+# define tgammaf RT_NOCRT(tgammaf)
+# define significandl RT_NOCRT(significandl)
+# define j0l RT_NOCRT(j0l)
+# define j1l RT_NOCRT(j1l)
+# define jnl RT_NOCRT(jnl)
+# define scalbl RT_NOCRT(scalbl)
+# define y0l RT_NOCRT(y0l)
+# define y1l RT_NOCRT(y1l)
+# define ynl RT_NOCRT(ynl)
+# define lgammal_r RT_NOCRT(lgammal_r)
+# define gammal RT_NOCRT(gammal)
+#endif
+
+/*
+ * Include inlined implementations.
+ */
+#ifdef RT_ARCH_AMD64
+# include <iprt/nocrt/amd64/math.h>
+#elif defined(RT_ARCH_X86)
+# include <iprt/nocrt/x86/math.h>
+#endif
+
+#endif /* !IPRT_INCLUDED_nocrt_math_h */
+
diff --git a/include/iprt/nocrt/memory b/include/iprt/nocrt/memory
new file mode 100644
index 00000000..6399c414
--- /dev/null
+++ b/include/iprt/nocrt/memory
@@ -0,0 +1,108 @@
+/** @file
+ * IPRT / No-CRT - Minimal C++ std::memory.
+ */
+
+/*
+ * Copyright (C) 2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_SRC_nocrt_memory
+#define VBOX_INCLUDED_SRC_nocrt_memory
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/nocrt/cstddef>
+#include <iprt/nocrt/new>
+
+namespace std
+{
+ /**
+ * Simple allocator - not C++11 compliant.
+ */
+ template<class a_Type> class allocator
+ {
+ public:
+ typedef a_Type value_type;
+ typedef a_Type const &const_reference;
+ typedef a_Type *pointer;
+ typedef a_Type const *const_pointer;
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
+
+ public:
+ allocator() RT_NOEXCEPT
+ { }
+
+ allocator(allocator const &a_rThat) RT_NOEXCEPT
+ { RT_NOREF(a_rThat); }
+
+ ~allocator()
+ { }
+
+ a_Type *allocate(size_type a_cItems, const void *a_pvHint = NULL)
+ {
+ RT_NOREF(a_pvHint);
+ Assert(a_cItems <= max_size()); /** @todo throw stuff */
+ return static_cast<pointer>(::operator new(sizeof(value_type) * a_cItems));
+ }
+
+ void deallocate(a_Type *a_paItems, size_type a_cItems)
+ {
+ if (a_paItems && a_cItems > 0)
+ ::operator delete(a_paItems);
+ }
+
+ size_type max_size() const
+ {
+ /* whatever */
+#if ARCH_BITS >= 64
+ return _4G / sizeof(value_type);
+#else
+ return _512M / sizeof(value_type);
+#endif
+ }
+
+ void construct(pointer a_pDst, const_reference a_rSrc)
+ {
+ ::new (static_cast<void *>(a_pDst)) a_Type(a_rSrc);
+ }
+
+ void destroy(pointer a_pDst)
+ {
+ a_pDst->~value_type();
+ }
+ };
+
+ /** @todo make_unique and unique */
+}
+
+#endif /* !VBOX_INCLUDED_SRC_nocrt_memory */
+
diff --git a/include/iprt/nocrt/new b/include/iprt/nocrt/new
new file mode 100644
index 00000000..ce8929c4
--- /dev/null
+++ b/include/iprt/nocrt/new
@@ -0,0 +1,118 @@
+/** @file
+ * IPRT / No-CRT - Our own new header.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_SRC_nocrt_new
+#define VBOX_INCLUDED_SRC_nocrt_new
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+
+
+/** MSC declares the operators as cdecl it seems. */
+#ifdef _MSC_VER
+# define RT_NEW_DELETE_CDECL __cdecl
+#else
+# define RT_NEW_DELETE_CDECL
+#endif
+
+/** MSC doesn't use the standard namespace. */
+#ifdef _MSC_VER
+# define RT_NEW_DELETE_SIZE_T size_t
+#else
+# define RT_NEW_DELETE_SIZE_T std::size_t
+#endif
+
+/** The hint that we're throwing std::bad_alloc is not apprecitated by MSC. */
+#ifdef RT_EXCEPTIONS_ENABLED
+# ifdef _MSC_VER
+# define RT_NEW_DELETE_THROWS_BAD_ALLOC
+# define RT_NEW_DELETE_NOTHROW RT_NO_THROW_DEF
+# else
+# ifdef _GLIBCXX_THROW
+# define RT_NEW_DELETE_THROWS_BAD_ALLOC _GLIBCXX_THROW(std::bad_alloc)
+# elif defined(__cplusplus) && (__cplusplus + 0) < 201700
+# define RT_NEW_DELETE_THROWS_BAD_ALLOC throw(std::bad_alloc)
+# else
+# define RT_NEW_DELETE_THROWS_BAD_ALLOC noexcept(false)
+# endif
+# define RT_NEW_DELETE_NOTHROW throw()
+# endif
+#else /* !RT_EXCEPTIONS_ENABLED */
+# define RT_NEW_DELETE_THROWS_BAD_ALLOC
+# define RT_NEW_DELETE_NOTHROW
+#endif /* !RT_EXCEPTIONS_ENABLED */
+
+
+#ifdef IPRT_NO_CRT
+
+namespace std
+{
+ struct nothrow_t
+ {
+ explicit nothrow_t()
+ {}
+ };
+ extern __declspec(selectany) nothrow_t const nothrow;
+}
+
+
+void *RT_NEW_DELETE_CDECL operator new(RT_NEW_DELETE_SIZE_T cb) RT_NEW_DELETE_THROWS_BAD_ALLOC;
+void *RT_NEW_DELETE_CDECL operator new(RT_NEW_DELETE_SIZE_T cb, const std::nothrow_t &) RT_NEW_DELETE_NOTHROW;
+void *RT_NEW_DELETE_CDECL operator new(RT_NEW_DELETE_SIZE_T cb, void *pvPlacement) RT_NEW_DELETE_NOTHROW;
+void RT_NEW_DELETE_CDECL operator delete(void *pv) RT_NEW_DELETE_NOTHROW;
+#ifdef __cpp_sized_deallocation
+void RT_NEW_DELETE_CDECL operator delete(void *pv, RT_NEW_DELETE_SIZE_T cb) RT_NEW_DELETE_NOTHROW;
+#endif
+void RT_NEW_DELETE_CDECL operator delete(void *pv, const std::nothrow_t &) RT_NEW_DELETE_NOTHROW;
+
+
+void *RT_NEW_DELETE_CDECL operator new[](RT_NEW_DELETE_SIZE_T cb) RT_NEW_DELETE_THROWS_BAD_ALLOC;
+void *RT_NEW_DELETE_CDECL operator new[](RT_NEW_DELETE_SIZE_T cb, const std::nothrow_t &) RT_NEW_DELETE_NOTHROW;
+void *RT_NEW_DELETE_CDECL operator new[](RT_NEW_DELETE_SIZE_T cb, void *pvPlacement) RT_NEW_DELETE_NOTHROW;
+void RT_NEW_DELETE_CDECL operator delete[](void * pv) RT_NEW_DELETE_NOTHROW;
+#ifdef __cpp_sized_deallocation
+void RT_NEW_DELETE_CDECL operator delete[](void * pv, RT_NEW_DELETE_SIZE_T cb) RT_NEW_DELETE_NOTHROW;
+#endif
+void RT_NEW_DELETE_CDECL operator delete[](void *pv, const std::nothrow_t &) RT_NEW_DELETE_NOTHROW;
+
+
+#else /* IPRT_NO_CRT */
+# include <new>
+#endif /* IPRT_NO_CRT */
+
+#endif /* !VBOX_INCLUDED_SRC_nocrt_new */
+
diff --git a/include/iprt/nocrt/ostream b/include/iprt/nocrt/ostream
new file mode 100644
index 00000000..98820e27
--- /dev/null
+++ b/include/iprt/nocrt/ostream
@@ -0,0 +1,280 @@
+/** @file
+ * IPRT / No-CRT - Minimal C++ ostream header.
+ */
+
+/*
+ * Copyright (C) 2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_SRC_nocrt_ostream
+#define VBOX_INCLUDED_SRC_nocrt_ostream
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+/* Currently all in the ios header. */
+#include <iprt/nocrt/ios>
+
+namespace std
+{
+ /**
+ * Basic output stream.
+ */
+ template<typename a_CharType, typename a_CharTraits /*= std::char_traits<a_CharType>*/ >
+ class basic_ostream : public basic_ios<a_CharType, a_CharTraits>
+ {
+ protected:
+ /** Sentry class that performs pre and post output work. */
+ class sentry
+ {
+ private:
+ basic_ostream &m_rParent;
+
+ public:
+ explicit sentry(basic_ostream &a_rParent)
+ : m_rParent(a_rParent)
+ {
+ if (a_rParent.good())
+ {
+ basic_ostream *pTiedStream = a_rParent.tie();
+ if (!pTiedStream)
+ { /* likely? */ }
+ else
+ {
+ pTiedStream->flush();
+ if (!pTiedStream->good())
+ a_rParent.setstate(failbit);
+ }
+ }
+ }
+
+ explicit operator bool() const
+ {
+ return m_rParent.good();
+ }
+
+ ~sentry()
+ {
+ if ( (m_rParent.flags() & std::ios_base::unitbuf)
+ && m_rParent.good())
+ m_rParent.rdbuf()->pubsync();
+ }
+ };
+
+ public:
+ explicit basic_ostream(std::basic_streambuf<a_CharType,a_CharTraits> *a_pBuf)
+ : basic_ios(a_pBuf)
+ { }
+
+ /** For cerr initialization.
+ * @internal */
+ explicit basic_ostream(std::basic_streambuf<a_CharType,a_CharTraits> *a_pBuf,
+ std::basic_ostream<a_CharType, a_CharTraits> *a_pTiedStream,
+ bool a_fUnbuffered)
+ : basic_ios(a_pBuf)
+ {
+ m_pTiedStream = a_pTiedStream;
+ if (!a_fUnbuffered)
+ setf(std::ios_base::unitbuf);
+ }
+
+ private:
+ basic_ostream(basic_ostream const &a_rSrc); /* not copyable */
+ basic_ostream &operator=(basic_ostream const &a_rSrc); /* not copyable */
+
+ public:
+ virtual ~basic_ostream()
+ {
+ }
+
+ public:
+ basic_ostream &put(char_type a_ch)
+ {
+ sentry PrePost(*this);
+ if (PrePost)
+ {
+ if (m_pBuf->sputc(a_ch) == traits_type::eof())
+ m_fState |= badbit;
+ }
+ return *this;
+ }
+
+ basic_ostream &write(const char_type *a_pchSrc, std::streamsize a_cchToWrite)
+ {
+ sentry PrePost(*this);
+ if (PrePost)
+ {
+ std::streamsize cchWritten = m_pBuf->sputn(a_pchSrc, a_cchToWrite);
+ if (cchWritten != a_cchToWrite)
+ m_fState |= badbit;
+ }
+ return *this;
+ }
+
+ basic_ostream &flush()
+ {
+ if (m_pBuf)
+ m_pBuf->pubsync();
+ return *this;
+ }
+
+ pos_type tellp() RT_NOEXCEPT;
+ basic_ostream &seekp(pos_type a_off) RT_NOEXCEPT;
+ basic_ostream &seekp(off_type a_off, seekdir enmDir) RT_NOEXCEPT;
+
+ /** @name Internal support methods
+ * @{ */
+ inline basic_ostream &intWrite(const char *a_pchSrc, std::streamsize a_cchToWrite); /**< Internal method outputting char buffers. */
+
+ /** @returns 8, 10 or 16. */
+ inline unsigned intGetIntegerBase() const RT_NOEXCEPT
+ {
+ switch (m_fFlags & basefield)
+ {
+ default:
+ case dec: return 10;
+ case hex: return 16;
+ case oct: return 8;
+ }
+ }
+
+ /** @returns RTSTR_F_XXX . */
+ inline unsigned intGetIntegerFlags() const RT_NOEXCEPT
+ {
+ unsigned fFlags = 0;
+ if (m_fFlags & uppercase)
+ fFlags |= RTSTR_F_CAPITAL;
+ if (m_fFlags & showbase)
+ fFlags |= RTSTR_F_SPECIAL;
+ if (m_fFlags & showpos)
+ fFlags |= RTSTR_F_PLUS;
+ return fFlags;
+ }
+
+ basic_ostream &formatInteger(uint64_t a_uValue, uint32_t a_fFlags, unsigned a_uBase = 0)
+ {
+ a_fFlags |= intGetIntegerFlags();
+ char szTmp[72];
+ int cchTmp = RTStrFormatNumber(szTmp, a_uValue, !a_uBase ? intGetIntegerBase() : a_uBase, 0, 0, a_fFlags);
+
+ /** @todo apply cchWidth and padding. */
+
+ return intWrite(szTmp, cchTmp);
+ }
+
+ /** @} */
+ };
+
+ /** @name Character and string output.
+ * @{ */
+ /** @todo not sure if this really works... */
+ template<typename a_CharType, typename a_CharTraits = std::char_traits<a_CharType> >
+ basic_ostream<a_CharType, a_CharTraits> &operator<<(basic_ostream<a_CharType, a_CharTraits> &a_rDst, char a_ch)
+ {
+ return a_rDst.put(a_ch);
+ }
+
+ template<typename a_CharType, typename a_CharTraits = std::char_traits<a_CharType> >
+ basic_ostream<a_CharType, a_CharTraits> &operator<<(basic_ostream<a_CharType, a_CharTraits> &a_rDst, const char *a_psz)
+ {
+ return a_rDst.intWrite(a_psz, strlen(a_psz));
+ }
+ /** @} */
+
+ /** @name Integer formatting.
+ * @{ */
+ template<typename a_CharType, typename a_CharTraits = std::char_traits<a_CharType> >
+ basic_ostream<a_CharType, a_CharTraits> &operator<<(basic_ostream<a_CharType, a_CharTraits> &a_rDst, signed char a_iValue)
+ {
+ return a_rDst.formatInteger(a_iValue, RTSTR_F_8BIT | RTSTR_F_VALSIGNED);
+ }
+
+ template<typename a_CharType, typename a_CharTraits = std::char_traits<a_CharType> >
+ basic_ostream<a_CharType, a_CharTraits> &operator<<(basic_ostream<a_CharType, a_CharTraits> &a_rDst, unsigned char a_uValue)
+ {
+ return a_rDst.formatInteger(a_uValue, RTSTR_F_8BIT);
+ }
+
+ template<typename a_CharType, typename a_CharTraits = std::char_traits<a_CharType> >
+ basic_ostream<a_CharType, a_CharTraits> &operator<<(basic_ostream<a_CharType, a_CharTraits> &a_rDst, short a_iValue)
+ {
+ return a_rDst.formatInteger(a_iValue, RTSTR_F_16BIT | RTSTR_F_VALSIGNED);
+ }
+
+ template<typename a_CharType, typename a_CharTraits = std::char_traits<a_CharType> >
+ basic_ostream<a_CharType, a_CharTraits> &operator<<(basic_ostream<a_CharType, a_CharTraits> &a_rDst, unsigned short a_uValue)
+ {
+ return a_rDst.formatInteger(a_uValue, RTSTR_F_16BIT);
+ }
+
+ template<typename a_CharType, typename a_CharTraits = std::char_traits<a_CharType> >
+ basic_ostream<a_CharType, a_CharTraits> &operator<<(basic_ostream<a_CharType, a_CharTraits> &a_rDst, int a_iValue)
+ {
+ return a_rDst.formatInteger(a_iValue, RTSTR_F_32BIT | RTSTR_F_VALSIGNED);
+ }
+
+ template<typename a_CharType, typename a_CharTraits = std::char_traits<a_CharType> >
+ basic_ostream<a_CharType, a_CharTraits> &operator<<(basic_ostream<a_CharType, a_CharTraits> &a_rDst, unsigned int a_uValue)
+ {
+ return a_rDst.formatInteger(a_uValue, RTSTR_F_32BIT | RTSTR_F_VALSIGNED);
+ }
+
+ template<typename a_CharType, typename a_CharTraits = std::char_traits<a_CharType> >
+ basic_ostream<a_CharType, a_CharTraits> &operator<<(basic_ostream<a_CharType, a_CharTraits> &a_rDst, long a_iValue)
+ {
+ return a_rDst.formatInteger(a_iValue, (sizeof(a_iValue) > sizeof(int32_t) ? RTSTR_F_64BIT : RTSTR_F_32BIT));
+ }
+
+ template<typename a_CharType, typename a_CharTraits = std::char_traits<a_CharType> >
+ basic_ostream<a_CharType, a_CharTraits> &operator<<(basic_ostream<a_CharType, a_CharTraits> &a_rDst, unsigned long a_uValue)
+ {
+ return a_rDst.formatInteger(a_uValue,
+ RTSTR_F_VALSIGNED | (sizeof(a_uValue) > sizeof(uint32_t) ? RTSTR_F_64BIT : RTSTR_F_32BIT));
+ }
+
+ template<typename a_CharType, typename a_CharTraits = std::char_traits<a_CharType> >
+ basic_ostream<a_CharType, a_CharTraits> &operator<<(basic_ostream<a_CharType, a_CharTraits> &a_rDst, void const *a_pvValue)
+ {
+ return a_rDst.formatInteger((uintptr_t)a_pvValue,
+ (sizeof(a_pvValue) > sizeof(uint32_t) ? RTSTR_F_64BIT : RTSTR_F_32BIT), 16);
+ }
+ /** @} */
+
+ template<>
+ inline basic_ostream<char> &basic_ostream<char>::intWrite(const char *a_pchSrc, std::streamsize a_cchToWrite)
+ {
+ return write(a_pchSrc, a_cchToWrite);
+ }
+
+
+}
+
+#endif /* !VBOX_INCLUDED_SRC_nocrt_ostream */
+
diff --git a/include/iprt/nocrt/process.h b/include/iprt/nocrt/process.h
new file mode 100644
index 00000000..f965813c
--- /dev/null
+++ b/include/iprt/nocrt/process.h
@@ -0,0 +1,43 @@
+/** @file
+ * IPRT / No-CRT - Stub process.h header for MSC compatibility.
+ */
+
+/*
+ * Copyright (C) 2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_nocrt_process_h
+#define IPRT_INCLUDED_nocrt_process_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#endif /* !IPRT_INCLUDED_nocrt_process_h */
+
diff --git a/include/iprt/nocrt/setjmp.h b/include/iprt/nocrt/setjmp.h
new file mode 100644
index 00000000..6b2e15af
--- /dev/null
+++ b/include/iprt/nocrt/setjmp.h
@@ -0,0 +1,68 @@
+/** @file
+ * IPRT / No-CRT - Our own setjmp header.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_nocrt_setjmp_h
+#define IPRT_INCLUDED_nocrt_setjmp_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+
+RT_C_DECLS_BEGIN
+
+#ifdef RT_ARCH_AMD64
+# ifdef RT_OS_WINDOWS /* Also saves rsi, rdi and xmm6-xmm15. */
+typedef uint64_t RT_NOCRT(jmp_buf)[10 + (2*10)];
+# else
+typedef uint64_t RT_NOCRT(jmp_buf)[8];
+# endif
+#else
+typedef uint32_t RT_NOCRT(jmp_buf)[6+2];
+#endif
+
+extern DECL_RETURNS_TWICE(int) RT_NOCRT(setjmp)(RT_NOCRT(jmp_buf));
+extern DECL_NO_RETURN(int) RT_NOCRT(longjmp)(RT_NOCRT(jmp_buf), int);
+
+#if !defined(RT_WITHOUT_NOCRT_WRAPPERS) && !defined(RT_WITHOUT_NOCRT_WRAPPER_ALIASES)
+# define jmp_buf RT_NOCRT(jmp_buf)
+# define setjmp RT_NOCRT(setjmp)
+# define longjmp RT_NOCRT(longjmp)
+#endif
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_nocrt_setjmp_h */
+
diff --git a/include/iprt/nocrt/signal.h b/include/iprt/nocrt/signal.h
new file mode 100644
index 00000000..36ca57b5
--- /dev/null
+++ b/include/iprt/nocrt/signal.h
@@ -0,0 +1,43 @@
+/** @file
+ * IPRT / No-CRT - Stub signal.h header.
+ */
+
+/*
+ * Copyright (C) 2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_nocrt_signal_h
+#define IPRT_INCLUDED_nocrt_signal_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#endif /* !IPRT_INCLUDED_nocrt_signal_h */
+
diff --git a/include/iprt/nocrt/stdarg.h b/include/iprt/nocrt/stdarg.h
new file mode 100644
index 00000000..3a5b039d
--- /dev/null
+++ b/include/iprt/nocrt/stdarg.h
@@ -0,0 +1,45 @@
+/** @file
+ * IPRT / No-CRT - stdarg.h (-> iprt/stdarg.h).
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_nocrt_stdarg_h
+#define IPRT_INCLUDED_nocrt_stdarg_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/stdarg.h>
+
+#endif /* !IPRT_INCLUDED_nocrt_stdarg_h */
+
diff --git a/include/iprt/nocrt/stdbool.h b/include/iprt/nocrt/stdbool.h
new file mode 100644
index 00000000..d288ce2c
--- /dev/null
+++ b/include/iprt/nocrt/stdbool.h
@@ -0,0 +1,58 @@
+/** @file
+ * IPRT / No-CRT - Our own minimal stdbool.h header (needed by softfloat.h).
+ */
+
+/*
+ * Copyright (C) 2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_nocrt_stdbool_h
+#define IPRT_INCLUDED_nocrt_stdbool_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+/* The iprt/types.h header should take care of the basics. */
+#include <iprt/types.h>
+
+#ifndef __cplusplus
+# ifndef bool
+# define bool _Bool
+# endif
+# ifndef true
+# define true (1)
+# endif
+# ifndef false
+# define false (0)
+# endif
+#endif
+
+#endif /* !IPRT_INCLUDED_nocrt_stdbool_h */
+
diff --git a/include/iprt/nocrt/stddef.h b/include/iprt/nocrt/stddef.h
new file mode 100644
index 00000000..df56a617
--- /dev/null
+++ b/include/iprt/nocrt/stddef.h
@@ -0,0 +1,48 @@
+/** @file
+ * IPRT / No-CRT - stddef.h (-> iprt/types.h).
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_nocrt_stddef_h
+#define IPRT_INCLUDED_nocrt_stddef_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+
+#ifndef offsetof
+# define offsetof(a_Type, a_Member) RT_OFFSETOF(a_Type, a_Member)
+#endif
+
+#endif /* !IPRT_INCLUDED_nocrt_stddef_h */
diff --git a/include/iprt/nocrt/stdint.h b/include/iprt/nocrt/stdint.h
new file mode 100644
index 00000000..2b481159
--- /dev/null
+++ b/include/iprt/nocrt/stdint.h
@@ -0,0 +1,46 @@
+/** @file
+ * IPRT / No-CRT - Our own minimal stdint.h header (needed by softfloat.h).
+ */
+
+/*
+ * Copyright (C) 2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_nocrt_stdint_h
+#define IPRT_INCLUDED_nocrt_stdint_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+/* The iprt/stdint.h header should take care of the basics. */
+#include <iprt/stdint.h>
+
+#endif /* !IPRT_INCLUDED_nocrt_stdint_h */
+
diff --git a/include/iprt/nocrt/stdio.h b/include/iprt/nocrt/stdio.h
new file mode 100644
index 00000000..a63b3e49
--- /dev/null
+++ b/include/iprt/nocrt/stdio.h
@@ -0,0 +1,226 @@
+/** @file
+ * IPRT / No-CRT - Mostly empty stdio.h.
+ */
+
+/*
+ * Copyright (C) 2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_nocrt_stdio_h
+#define IPRT_INCLUDED_nocrt_stdio_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/stream.h>
+#include <iprt/nocrt/sys/types.h> /* errno_t, off_t */
+#ifdef IPRT_NO_CRT_FOR_3RD_PARTY
+# include <iprt/nocrt/time.h> /* file.h includes fs.h which includes time.h */
+# include <iprt/file.h> /* for RTFILE_SEEK_XXX */
+# include <iprt/assertcompile.h>
+#endif
+
+typedef RTFOFF fpos_t;
+
+
+#ifdef IPRT_NO_CRT_FOR_3RD_PARTY
+/*
+ * Only for external libraries and such, but even then it would be best to
+ * check each printf and fprintf call as IPRT isn't 100% compatible...
+ */
+
+/* These are also in unistd.h: */
+# undef SEEK_SET
+# define SEEK_SET RTFILE_SEEK_BEGIN
+# undef SEEK_CUR
+# define SEEK_CUR RTFILE_SEEK_CURRENT
+# undef SEEK_END
+# define SEEK_END RTFILE_SEEK_END
+AssertCompile(SEEK_SET == 0); AssertCompile(SEEK_CUR == 1); AssertCompile(SEEK_END == 2); /* Also in WDK header mmiscapi.h. */
+
+# define RT_NOCRT_BUFSIZ 4096
+# define BUFSIZ RT_NOCRT_BUFSIZ
+
+RT_C_DECLS_BEGIN
+
+typedef struct RTSTREAM FILE;
+# define stdin g_pStdIn
+# define stdout g_pStdOut
+# define stderr g_pStdErr
+
+# define printf RTPrintf
+# define vprintf RTPrintfV
+# define fprintf RTStrmPrintf
+# define vfprintf RTStrmPrintfV
+int RT_NOCRT(snprintf)(char *, size_t, const char *, ...);
+int RT_NOCRT(vsnprintf)(char *, size_t, const char *, va_list);
+int RT_NOCRT(scprintf)(const char *, ...);
+int RT_NOCRT(vscprintf)(const char *, va_list);
+
+FILE *RT_NOCRT(fopen)(const char *pszFilename, const char *pszMode);
+FILE *RT_NOCRT(fdopen)(int fd, const char *pszMode);
+FILE *RT_NOCRT(tmpfile)(void);
+errno_t RT_NOCRT(tmpfile_s)(FILE **ppFile);
+int RT_NOCRT(fileno)(FILE *pFile);
+int RT_NOCRT(fclose)(FILE *pFile);
+int RT_NOCRT(fflush)(FILE *pFile);
+int RT_NOCRT(setvbuf)(FILE *pFile, char *pchBuf, int iBufferingType, size_t cbBuf);
+int RT_NOCRT(fseek)(FILE *pFile, long, int);
+int RT_NOCRT(fseeko)(FILE *pFile, off_t, int);
+long RT_NOCRT(ftell)(FILE *pFile);
+off_t RT_NOCRT(ftello)(FILE *pFile);
+size_t RT_NOCRT(fwrite)(void const *pvBuf, size_t cbItem, size_t cItems, FILE *pFile);
+int RT_NOCRT(fputs)(const char *psz, FILE *pFile);
+int RT_NOCRT(puts)(const char *psz);
+int RT_NOCRT(fputc)(int, FILE *pFile);
+int RT_NOCRT(putc)(int, FILE *pFile);
+size_t RT_NOCRT(fread)(void *pvBuf, size_t cbItem, size_t cItems, FILE *pFile);
+int RT_NOCRT(fgetc)(FILE *pFile);
+int RT_NOCRT(getc)(FILE *pFile);
+int RT_NOCRT(ferror)(FILE *pFile);
+void RT_NOCRT(clearerr)(FILE *pFile);
+int RT_NOCRT(remove)(const char *pszFilename);
+int RT_NOCRT(sscanf)(const char *pszString, const char *pszFormat, ...);
+int RT_NOCRT(vsscanf)(const char *pszString, const char *pszFormat, va_list);
+
+# ifndef RT_NOCRT_EOF /* also in string */
+# define RT_NOCRT_EOF (-1)
+# endif
+# define EOF RT_NOCRT_EOF
+
+/* Underscored variants: */
+# define _printf RTPrintf
+# define _vprintf RTPrintfV
+# define _fprintf RTStrmPrintf
+# define _vfprintf RTStrmPrintfV
+int RT_NOCRT(_snprintf)(char *, size_t, const char *, ...);
+int RT_NOCRT(_vsnprintf)(char *, size_t, const char *, va_list);
+int RT_NOCRT(_scprintf)(const char *, ...);
+int RT_NOCRT(_vscprintf)(const char *, va_list);
+
+FILE *RT_NOCRT(_fopen)(const char *pszFilename, const char *pszMode);
+FILE *RT_NOCRT(_fdopen)(int fd, const char *pszMode);
+FILE *RT_NOCRT(_tmpfile)(void);
+errno_t RT_NOCRT(_tmpfile_s)(FILE **ppFile);
+int RT_NOCRT(_fileno)(FILE *pFile);
+int RT_NOCRT(_fclose)(FILE *pFile);
+int RT_NOCRT(_fflush)(FILE *pFile);
+int RT_NOCRT(_setvbuf)(FILE *pFile, char *pchBuf, int iBufferingType, size_t cbBuf);
+int RT_NOCRT(_fseek)(FILE *pFile, long, int);
+int RT_NOCRT(_fseeko)(FILE *pFile, off_t, int);
+long RT_NOCRT(_ftell)(FILE *pFile);
+off_t RT_NOCRT(_ftello)(FILE *pFile);
+size_t RT_NOCRT(_fwrite)(void const *pvBuf, size_t cbItem, size_t cItems, FILE *pFile);
+int RT_NOCRT(_fputs)(const char *psz, FILE *pFile);
+int RT_NOCRT(_fputc)(int, FILE *pFile);
+size_t RT_NOCRT(_fread)(void *pvBuf, size_t cbItem, size_t cItems, FILE *pFile);
+int RT_NOCRT(_fgetc)(FILE *pFile);
+int RT_NOCRT(_getc)(FILE *pFile);
+int RT_NOCRT(_ferror)(FILE *pFile);
+void RT_NOCRT(_clearerr)(FILE *pFile);
+int RT_NOCRT(_remove)(const char *pszFilename);
+int RT_NOCRT(_sscanf)(const char *pszString, const char *pszFormat, ...);
+int RT_NOCRT(_vsscanf)(const char *pszString, const char *pszFormat, va_list);
+
+# define _IONBF (1) /**< No buffering. */
+# define _IOLBF (2) /**< Line buffered. */
+# define _IOFBF (3) /**< Fully buffered. */
+
+/* Aliases: */
+# if !defined(RT_WITHOUT_NOCRT_WRAPPERS) && !defined(RT_WITHOUT_NOCRT_WRAPPER_ALIASES)
+# define snprintf RT_NOCRT(snprintf)
+# define vsnprintf RT_NOCRT(vsnprintf)
+# define scprintf RT_NOCRT(scprintf)
+# define vscprintf RT_NOCRT(vscprintf)
+
+# define fopen RT_NOCRT(fopen)
+# define fdopen RT_NOCRT(fdopen)
+# define tmpfile RT_NOCRT(tmpfile)
+# define tmpfile_s RT_NOCRT(tmpfile_s)
+# define fileno RT_NOCRT(fileno)
+# define fclose RT_NOCRT(fclose)
+# define fflush RT_NOCRT(fflush)
+# define setvbuf RT_NOCRT(setvbuf)
+# define fseek RT_NOCRT(fseek)
+# define fseeko RT_NOCRT(fseeko)
+# define ftell RT_NOCRT(ftell)
+# define ftello RT_NOCRT(ftello)
+# define fwrite RT_NOCRT(fwrite)
+# define fputs RT_NOCRT(fputs)
+# define puts RT_NOCRT(puts)
+# define fputc RT_NOCRT(fputc)
+# define fread RT_NOCRT(fread)
+# define fgetc RT_NOCRT(fgetc)
+# define getc RT_NOCRT(getc)
+# define ferror RT_NOCRT(ferror)
+# define clearerr RT_NOCRT(clearerr)
+# define remove RT_NOCRT(remove)
+# define sscanf RT_NOCRT(sscanf)
+# define vsscanf RT_NOCRT(vsscanf)
+
+
+/* Underscored variants: */
+# define _snprintf RT_NOCRT(snprintf)
+# define _vsnprintf RT_NOCRT(vsnprintf)
+# define _scprintf RT_NOCRT(scprintf)
+# define _vscprintf RT_NOCRT(vscprintf)
+
+# define _fopen RT_NOCRT(fopen)
+# define _fdopen RT_NOCRT(fdopen)
+# define _tmpfile RT_NOCRT(tmpfile)
+# define _tmpfile_s RT_NOCRT(tmpfile_s)
+# define _fileno RT_NOCRT(fileno)
+# define _fclose RT_NOCRT(fclose)
+# define _flush RT_NOCRT(fflush)
+# define _setvbuf RT_NOCRT(setvbuf)
+# define _fseek RT_NOCRT(fseek)
+# define _fseeko RT_NOCRT(fseeko)
+# define _ftell RT_NOCRT(ftell)
+# define _ftello RT_NOCRT(ftello)
+# define _fwrite RT_NOCRT(fwrite)
+# define _fputs RT_NOCRT(fputs)
+# define _puts RT_NOCRT(puts)
+# define _fputc RT_NOCRT(fputc)
+# define _fread RT_NOCRT(fread)
+# define _fgetc RT_NOCRT(fgetc)
+# define _getc RT_NOCRT(getc)
+# define _ferror RT_NOCRT(ferror)
+# define _clearerr RT_NOCRT(clearerr)
+# define _remove RT_NOCRT(remove)
+# define _sscanf RT_NOCRT(_sscanf)
+# define _vsscanf RT_NOCRT(_vsscanf)
+# endif
+
+RT_C_DECLS_END
+
+#endif
+
+#endif /* !IPRT_INCLUDED_nocrt_stdio_h */
+
diff --git a/include/iprt/nocrt/stdlib.h b/include/iprt/nocrt/stdlib.h
new file mode 100644
index 00000000..49868cbe
--- /dev/null
+++ b/include/iprt/nocrt/stdlib.h
@@ -0,0 +1,227 @@
+/** @file
+ * IPRT / No-CRT - Our minimal stdlib.h.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_nocrt_stdlib_h
+#define IPRT_INCLUDED_nocrt_stdlib_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/assert.h>
+#include <iprt/env.h>
+#include <iprt/mem.h>
+#include <iprt/nocrt/limits.h>
+
+RT_C_DECLS_BEGIN
+
+#define EXIT_SUCCESS RTEXITCODE_SUCCESS
+#define EXIT_FAILURE RTEXITCODE_FAILURE
+
+
+typedef void FNRTNOCRTATEXITCALLBACK(void) /*RT_NOEXCEPT*/;
+typedef FNRTNOCRTATEXITCALLBACK *PFNRTNOCRTATEXITCALLBACK;
+#if defined(_MSC_VER) && defined(RT_WITHOUT_NOCRT_WRAPPERS) /* Clashes with compiler internal prototype or smth. */
+int nocrt_atexit(PFNRTNOCRTATEXITCALLBACK) RT_NOEXCEPT;
+# define atexit nocrt_atexit
+#else
+int RT_NOCRT(atexit)(PFNRTNOCRTATEXITCALLBACK) RT_NOEXCEPT;
+#endif
+
+#if !defined(RT_WITHOUT_NOCRT_WRAPPERS) && !defined(RT_WITHOUT_NOCRT_WRAPPER_ALIASES)
+# define atexit RT_NOCRT(atexit)
+#endif
+
+
+#ifdef IPRT_NO_CRT_FOR_3RD_PARTY
+/*
+ * Only for external libraries and such.
+ */
+
+DECLINLINE(void *) RT_NOCRT(malloc)(size_t cb)
+{
+ return RTMemAlloc(cb);
+}
+
+DECLINLINE(void *) RT_NOCRT(calloc)(size_t cItems, size_t cbItem)
+{
+ return RTMemAllocZ(cItems * cbItem); /* caller responsible for overflow issues. */
+}
+
+DECLINLINE(void *) RT_NOCRT(realloc)(void *pvOld, size_t cbNew)
+{
+ return RTMemRealloc(pvOld, cbNew);
+}
+
+DECLINLINE(void) RT_NOCRT(free)(void *pv)
+{
+ RTMemFree(pv);
+}
+
+DECLINLINE(const char *) RT_NOCRT(getenv)(const char *pszVar)
+{
+ return RTEnvGet(pszVar);
+}
+
+int RT_NOCRT(abs)(int) RT_NOEXCEPT;
+long RT_NOCRT(labs)(long) RT_NOEXCEPT;
+long long RT_NOCRT(llabs)(long long) RT_NOEXCEPT;
+int RT_NOCRT(rand)(void) RT_NOEXCEPT;
+void RT_NOCRT(srand)(unsigned) RT_NOEXCEPT;
+long RT_NOCRT(strtol)(const char *psz, char **ppszNext, int iBase) RT_NOEXCEPT;
+long long RT_NOCRT(strtoll)(const char *psz, char **ppszNext, int iBase) RT_NOEXCEPT;
+unsigned long RT_NOCRT(strtoul)(const char *psz, char **ppszNext, int iBase) RT_NOEXCEPT;
+unsigned long long RT_NOCRT(strtoull)(const char *psz, char **ppszNext, int iBase) RT_NOEXCEPT;
+int RT_NOCRT(atoi)(const char *psz) RT_NOEXCEPT;
+double RT_NOCRT(strtod)(const char *psz, char **ppszNext) RT_NOEXCEPT;
+double RT_NOCRT(atof)(const char *psz) RT_NOEXCEPT;
+void *RT_NOCRT(bsearch)(const void *pvKey, const void *pvBase, size_t cEntries, size_t cbEntry,
+ int (*pfnCompare)(const void *pvKey, const void *pvEntry));
+void RT_NOCRT(qsort)(void *pvBase, size_t cEntries, size_t cbEntry,
+ int (*pfnCompare)(const void *pv1, const void *pv2));
+void RT_NOCRT(qsort_r)(void *pvBase, size_t cEntries, size_t cbEntry,
+ int (*pfnCompare)(const void *pv1, const void *pv2, void *pvUser), void *pvUser);
+
+/* Map exit & abort onto fatal assert. */
+DECL_NO_RETURN(DECLINLINE(void)) RT_NOCRT(exit)(int iExitCode) { AssertFatalMsgFailed(("exit: iExitCode=%d\n", iExitCode)); }
+DECL_NO_RETURN(DECLINLINE(void)) RT_NOCRT(abort)(void) { AssertFatalMsgFailed(("abort\n")); }
+
+/*
+ * Underscored versions:
+ */
+DECLINLINE(void *) RT_NOCRT(_malloc)(size_t cb)
+{
+ return RTMemAlloc(cb);
+}
+
+DECLINLINE(void *) RT_NOCRT(_calloc)(size_t cItems, size_t cbItem)
+{
+ return RTMemAllocZ(cItems * cbItem); /* caller responsible for overflow issues. */
+}
+
+DECLINLINE(void *) RT_NOCRT(_realloc)(void *pvOld, size_t cbNew)
+{
+ return RTMemRealloc(pvOld, cbNew);
+}
+
+DECLINLINE(void) RT_NOCRT(_free)(void *pv)
+{
+ RTMemFree(pv);
+}
+
+DECLINLINE(const char *) RT_NOCRT(_getenv)(const char *pszVar)
+{
+ return RTEnvGet(pszVar);
+}
+
+int RT_NOCRT(_abs)(int);
+long RT_NOCRT(_labs)(long);
+long long RT_NOCRT(_llabs)(long long);
+int RT_NOCRT(_rand)(void);
+void RT_NOCRT(_srand)(unsigned);
+long RT_NOCRT(_strtol)(const char *psz, char **ppszNext, int iBase);
+long long RT_NOCRT(_strtoll)(const char *psz, char **ppszNext, int iBase);
+unsigned long RT_NOCRT(_strtoul)(const char *psz, char **ppszNext, int iBase);
+unsigned long long RT_NOCRT(_strtoull)(const char *psz, char **ppszNext, int iBase);
+int RT_NOCRT(_atoi)(const char *psz);
+double RT_NOCRT(_strtod)(const char *psz, char **ppszNext);
+double RT_NOCRT(_atof)(const char *psz);
+void *RT_NOCRT(_bsearch)(const void *pvKey, const void *pvBase, size_t cEntries, size_t cbEntry,
+ int (*pfnCompare)(const void *pv1, const void *pv2));
+void RT_NOCRT(_qsort)(void *pvBase, size_t cEntries, size_t cbEntry,
+ int (*pfnCompare)(const void *pv1, const void *pv2));
+void RT_NOCRT(_qsort_r)(void *pvBase, size_t cEntries, size_t cbEntry,
+ int (*pfnCompare)(const void *pv1, const void *pv2, void *pvUser), void *pvUser);
+
+/* Map exit & abort onto fatal assert. */
+DECL_NO_RETURN(DECLINLINE(void)) RT_NOCRT(_exit)(int iExitCode) { AssertFatalMsgFailed(("_exit: iExitCode=%d\n", iExitCode)); }
+DECL_NO_RETURN(DECLINLINE(void)) RT_NOCRT(_abort)(void) { AssertFatalMsgFailed(("_abort\n")); }
+
+/* Some windows CRT error control functions we totally ignore (only underscored): */
+# define _set_error_mode(a_Mode) (0)
+# define _set_abort_behavior(a_fFlags, a_fMask) (0)
+
+/*
+ * No-CRT aliases.
+ */
+# if !defined(RT_WITHOUT_NOCRT_WRAPPERS) && !defined(RT_WITHOUT_NOCRT_WRAPPER_ALIASES)
+# define malloc RT_NOCRT(malloc)
+# define calloc RT_NOCRT(calloc)
+# define realloc RT_NOCRT(realloc)
+# define free RT_NOCRT(free)
+# define getenv RT_NOCRT(getenv)
+# define bsearch RT_NOCRT(bsearch)
+# define exit RT_NOCRT(exit)
+# define abort RT_NOCRT(abort)
+# define abs RT_NOCRT(abs)
+# define labs RT_NOCRT(labs)
+# define llabs RT_NOCRT(llabs)
+# define rand RT_NOCRT(rand)
+# define srand RT_NOCRT(srand)
+# define strtol RT_NOCRT(strtol)
+# define strtoll RT_NOCRT(strtoll)
+# define strtoul RT_NOCRT(strtoul)
+# define strtoull RT_NOCRT(strtoull)
+# define atoi RT_NOCRT(atoi)
+# define strtod RT_NOCRT(strtod)
+# define atof RT_NOCRT(atof)
+
+# define _malloc RT_NOCRT(malloc)
+# define _calloc RT_NOCRT(calloc)
+# define _realloc RT_NOCRT(realloc)
+# define _free RT_NOCRT(free)
+# define _getenv RT_NOCRT(getenv)
+# define _bsearch RT_NOCRT(bsearch)
+# define _exit RT_NOCRT(exit)
+# define _abort RT_NOCRT(abort)
+# define _abs RT_NOCRT(abs)
+# define _labs RT_NOCRT(labs)
+# define _llabs RT_NOCRT(llabs)
+# define _rand RT_NOCRT(rand)
+# define _srand RT_NOCRT(srand)
+# define _strtol RT_NOCRT(strtol)
+# define _strtoll RT_NOCRT(strtoll)
+# define _strtoul RT_NOCRT(strtoul)
+# define _strtoull RT_NOCRT(strtoull)
+# define _atoi RT_NOCRT(atoi)
+# define _strtod RT_NOCRT(strtod)
+# define _atof RT_NOCRT(atof)
+# endif
+
+#endif /* IPRT_NO_CRT_FOR_3RD_PARTY */
+
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_nocrt_stdlib_h */
diff --git a/include/iprt/nocrt/string b/include/iprt/nocrt/string
new file mode 100644
index 00000000..31897dd1
--- /dev/null
+++ b/include/iprt/nocrt/string
@@ -0,0 +1,322 @@
+/** @file
+ * IPRT / No-CRT - Minimal C++ string header.
+ */
+
+/*
+ * Copyright (C) 2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_SRC_nocrt_string
+#define VBOX_INCLUDED_SRC_nocrt_string
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/nocrt/string.h>
+#include <iprt/nocrt/cstddef> /* for std::size_t */
+#include <iprt/cpp/ministring.h>
+
+#ifndef RT_NOCRT_EOF /* also in stdio.h */
+# define RT_NOCRT_EOF (-1)
+#endif
+
+namespace std
+{
+ using streamoff = ::RTFOFF;
+
+ /**
+ * @note This should be in iosfwd, not string.
+ */
+ template<typename a_MbStateType>
+ class fpos
+ {
+ protected:
+ std::streamoff m_off;
+ a_MbStateType m_MbState;
+
+ public:
+ fpos()
+ : m_off(0)
+ , m_MbState()
+ { }
+
+ fpos(std::streamoff a_off)
+ : m_off(a_off)
+ , m_MbState()
+ { }
+
+ a_MbStateType state() const RT_NOEXCEPT
+ {
+ return m_MbState;
+ }
+
+ void state(a_MbStateType a_NewMbState) const RT_NOEXCEPT
+ {
+ m_MbState = a_NewMbState;
+ }
+ };
+ using mbstate_t = ::RT_NOCRT(mbstate_t);
+ using streampos = fpos<std::mbstate_t>;
+
+ /* Use RTCString as std::string, it should be a reasonable match. */
+ typedef ::RTCString string;
+
+ /**
+ * Character traits.
+ */
+ template<typename a_CharType>
+ struct char_traits
+ {
+ /** @name Types
+ * @{ */
+ typedef a_CharType char_type;
+ typedef unsigned long int_type;
+ typedef std::streamoff off_type;
+ typedef std::streampos pos_type;
+ typedef std::mbstate_t state_type;
+ /** @} */
+
+ static void assign(char_type &a_rchDst, const char_type &a_rchSrc) RT_NOEXCEPT
+ {
+ a_rchDst = a_rchSrc;
+ }
+
+ static bool eq(const char_type &a_rchLeft, const char_type &a_rchRight) RT_NOEXCEPT
+ {
+ return a_rchLeft == a_rchRight;
+ }
+
+ static bool lt(const char_type &a_rchLeft, const char_type &a_rchRight) RT_NOEXCEPT
+ {
+ return a_rchLeft < a_rchRight;
+ }
+
+ static std::size_t length(const char_type *a_psz) RT_NOEXCEPT;
+ static int compare(const char_type *a_pchLeft, const char_type *a_pchRight, std::size_t a_cch) RT_NOEXCEPT;
+ static const char_type *find(const char_type *a_pchHaystack, std::size_t a_cchHaystack, const char_type &a_rchNeedle) RT_NOEXCEPT;
+ static char_type *assign(char_type *a_pchDst, std::size_t a_cchDst, char_type a_chFill) RT_NOEXCEPT;
+ static char_type *copy(char_type *a_pchDst, const char_type *a_pchSrc, std::size_t a_cch) RT_NOEXCEPT;
+ static char_type *move(char_type *a_pchDst, const char_type *a_pchSrc, std::size_t a_cch) RT_NOEXCEPT;
+
+ static char_type to_char_type(const int_type &a_riChar)
+ {
+ return static_cast<char_type>(a_riChar);
+ }
+
+ static int_type to_int_type(const char_type &a_rch)
+ {
+ return static_cast<int_type>(a_rch);
+ }
+
+ static bool eq_int_type(const int_type &a_riLeft, const int_type &a_riRight) RT_NOEXCEPT
+ {
+ return a_riLeft == a_riRight;
+ }
+
+ static int_type eof() RT_NOEXCEPT
+ {
+ return static_cast<int_type>(RT_NOCRT_EOF);
+ }
+
+ static int_type not_eof(const int_type &a_riChar) RT_NOEXCEPT
+ {
+ if (!eq_int_type(a_riChar, eof()))
+ return a_riChar;
+ return to_int_type(char_type());
+ }
+ };
+
+ template<typename a_CharType>
+ /*static*/ std::size_t char_traits<a_CharType>::length(const char_type *a_psz) RT_NOEXCEPT
+ {
+ const char_type * const pszStart = a_psz;
+ while (!eq(*a_pszLeft, char_type()))
+ a_psz++;
+ return static_cast<std::size_t>(a_psz - pszStart);
+ }
+
+ template<typename a_CharType>
+ /*static*/ int char_traits<a_CharType>::compare(const char_type *a_pchLeft, const char_type *a_pchRight,
+ std::size_t a_cch) RT_NOEXCEPT
+ {
+ for (std::size_t off = 0; off < a_cch; off++)
+ if (eq(a_pchLeft[off], a_pchRight[off]))
+ { /* likely? */ }
+ else
+ return lt(a_pchLeft[off], a_pchRight[off]) ? -1 : 1;
+ return 0;
+ }
+
+ template<typename a_CharType>
+ /*static*/ const typename char_traits<a_CharType>::char_type *
+ char_traits<a_CharType>::find(const char_type *a_pchHaystack, std::size_t a_cchHaystack,
+ const char_type &a_rchNeedle) RT_NOEXCEPT
+ {
+ while (a_cchHaystack-- > 0)
+ {
+ if (eq(*a_pchHaystack, a_rchNeedle))
+ return a_pchHaystack;
+ a_pchHaystack++;
+ }
+ return NULL;
+ }
+
+ template<typename a_CharType>
+ /*static*/ typename char_traits<a_CharType>::char_type *
+ char_traits<a_CharType>::assign(char_type *a_pchDst, std::size_t a_cchDst, char_type a_chFill) RT_NOEXCEPT
+ {
+ char_type * const pchRet = a_pchDst;
+ while (a_cchDst-- > 0)
+ *a_pchDst++ = a_chFill;
+ return pchRet;
+ }
+
+ template<typename a_CharType>
+ /*static*/ typename char_traits<a_CharType>::char_type *
+ char_traits<a_CharType>::copy(char_type *a_pchDst, const char_type *a_pchSrc, std::size_t a_cch) RT_NOEXCEPT
+ {
+ char_type * const pchRet = a_pchDst;
+ while (a_cch-- > 0)
+ *a_pchDst++ = *a_pchSrc++;
+ return pchRet;
+ }
+
+ template<typename a_CharType>
+ /*static*/ typename char_traits<a_CharType>::char_type *
+ char_traits<a_CharType>::move(char_type *a_pchDst, const char_type *a_pchSrc, std::size_t a_cch) RT_NOEXCEPT
+ {
+ char_type * const pchRet = a_pchDst;
+ char_type volatile *pchDstV = static_cast<char_type const volatile *>(a_pchDst);
+ char_type const volatile *pchSrcV = static_cast<char_type const volatile *>(a_pchSrc);
+ if ((uintptr_t)a_pchDst < (uintptr_t)a_pchSrc)
+ {
+ /* forward copy */
+ while (a_cch-- > 0)
+ *a_pchDstV++ = *a_pchSrcV++;
+ }
+ else
+ {
+ /* reverse copy */
+ a_pchSrcV += a_cch;
+ a_pchDstV += a_cch;
+ while (a_cchDst-- > 0)
+ *a_pchDstV-- = *a_pchSrcV--;
+ }
+ return pchRet;
+ }
+
+ /*
+ * Character train specializations.
+ */
+ template <>
+ struct char_traits<char>
+ {
+ typedef char char_type;
+ typedef int int_type;
+ typedef std::streamoff off_type;
+ typedef std::streampos pos_type;
+ typedef std::mbstate_t state_type;
+
+ static void assign(char_type &a_rchDst, const char_type &a_rchSrc) RT_NOEXCEPT
+ {
+ a_rchDst = a_rchSrc;
+ }
+
+ static bool eq(const char_type &a_rchLeft, const char_type &a_rchRight) RT_NOEXCEPT
+ {
+ return a_rchLeft == a_rchRight;
+ }
+
+ static bool lt(const char_type &a_rchLeft, const char_type &a_rchRight) RT_NOEXCEPT
+ {
+ return a_rchLeft < a_rchRight;
+ }
+
+ static std::size_t length(const char_type *a_psz) RT_NOEXCEPT
+ {
+ return ::RT_NOCRT(strlen)(a_psz);
+ }
+
+ static int compare(const char_type *a_pchLeft, const char_type *a_pchRight, std::size_t a_cch) RT_NOEXCEPT
+ {
+ return ::RT_NOCRT(memcmp)(a_pchLeft, a_pchRight, a_cch);
+ }
+
+ static const char_type *find(const char_type *a_pchHaystack, std::size_t a_cchHaystack, const char_type &a_rchNeedle) RT_NOEXCEPT
+ {
+ return static_cast<const char_type *>(::RT_NOCRT(memchr)(a_pchHaystack, a_rchNeedle, a_cchHaystack));
+ }
+
+ static char_type *assign(char_type *a_pchDst, std::size_t a_cchDst, char_type a_chFill) RT_NOEXCEPT
+ {
+ return static_cast<char_type *>(::RT_NOCRT(memset)(a_pchDst, a_chFill, a_cchDst));
+ }
+
+ static char_type *copy(char_type *a_pchDst, const char_type *a_pchSrc, std::size_t a_cch) RT_NOEXCEPT
+ {
+ return static_cast<char_type *>(::RT_NOCRT(memcpy)(a_pchDst, a_pchSrc, a_cch));
+ }
+
+ static char_type *move(char_type *a_pchDst, const char_type *a_pchSrc, std::size_t a_cch) RT_NOEXCEPT
+ {
+ return static_cast<char_type *>(::RT_NOCRT(memmove)(a_pchDst, a_pchSrc, a_cch));
+ }
+
+ static char_type to_char_type(const int_type &a_riChar)
+ {
+ return static_cast<char_type>(a_riChar);
+ }
+
+ static int_type to_int_type(const char_type &a_rch)
+ {
+ return static_cast<int_type>(a_rch);
+ }
+
+ static bool eq_int_type(const int_type &a_riLeft, const int_type &a_riRight) RT_NOEXCEPT
+ {
+ return a_riLeft == a_riRight;
+ }
+
+ static int_type eof() RT_NOEXCEPT
+ {
+ return static_cast<int_type>(RT_NOCRT_EOF);
+ }
+
+ static int_type not_eof(const int_type &a_riChar) RT_NOEXCEPT
+ {
+ if (!eq_int_type(a_riChar, eof()))
+ return a_riChar;
+ return 0;
+ }
+ };
+}
+
+
+#endif /* !VBOX_INCLUDED_SRC_nocrt_string */
diff --git a/include/iprt/nocrt/string.h b/include/iprt/nocrt/string.h
new file mode 100644
index 00000000..b83d0036
--- /dev/null
+++ b/include/iprt/nocrt/string.h
@@ -0,0 +1,254 @@
+/** @file
+ * IPRT / No-CRT - string.h.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_nocrt_string_h
+#define IPRT_INCLUDED_nocrt_string_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+
+/* Dummy for now, fix when/if needed. */
+typedef struct RT_NOCRT(mbstate_t)
+{
+ unsigned long whatever;
+} RT_NOCRT(mbstate_t);
+
+
+RT_C_DECLS_BEGIN
+
+void *RT_NOCRT(memchr)(const void *pv, int ch, size_t cb);
+int RT_NOCRT(memcmp)(const void *pv1, const void *pv2, size_t cb);
+void *RT_NOCRT(memcpy)(void *pvDst, const void *pvSrc, size_t cb);
+void *RT_NOCRT(mempcpy)(void *pvDst, const void *pvSrc, size_t cb);
+void *RT_NOCRT(memrchr)(const void *pv, int ch, size_t cb);
+void *RT_NOCRT(memmove)(void *pvDst, const void *pvSrc, size_t cb);
+void *RT_NOCRT(memset)(void *pvDst, int ch, size_t cb);
+
+char *RT_NOCRT(strcat)(char *pszDst, const char *pszSrc);
+char *RT_NOCRT(strncat)(char *pszDst, const char *pszSrc, size_t cch);
+char *RT_NOCRT(strchr)(const char *psz, int ch);
+char *RT_NOCRT(strrchr)(const char *psz, int ch);
+int RT_NOCRT(strcmp)(const char *psz1, const char *psz2);
+int RT_NOCRT(strncmp)(const char *psz1, const char *psz2, size_t cch);
+int RT_NOCRT(stricmp)(const char *psz1, const char *psz2);
+int RT_NOCRT(strnicmp)(const char *psz1, const char *psz2, size_t cch);
+int RT_NOCRT(strcmpcase)(const char *psz1, const char *psz2, size_t cch);
+int RT_NOCRT(strcoll)(const char *psz1, const char *psz2);
+char *RT_NOCRT(strcpy)(char *pszDst, const char *pszSrc);
+char *RT_NOCRT(strncpy)(char *pszDst, const char *pszSrc, size_t cch);
+char *RT_NOCRT(strcat)(char *pszDst, const char *pszSrc);
+char *RT_NOCRT(strncat)(char *pszDst, const char *pszSrc, size_t cch);
+size_t RT_NOCRT(strlen)(const char *psz);
+size_t RT_NOCRT(strnlen)(const char *psz, size_t cch);
+size_t RT_NOCRT(strspn)(const char *psz, const char *pszBreakChars);
+size_t RT_NOCRT(strcspn)(const char *psz, const char *pszBreakChars);
+char *RT_NOCRT(strpbrk)(const char *psz, const char *pszBreakChars);
+char *RT_NOCRT(strstr)(const char *psz, const char *pszSub);
+char *RT_NOCRT(strtok)(char *psz, const char *pszDelim);
+char *RT_NOCRT(strtok_r)(char *psz, const char *pszDelim, char **ppszSave);
+#if 0 /* C++11: */
+char *RT_NOCRT(strtok_s)(char *psz, /*rsize_t*/ size_t cchMax, const char *pszDelim, char **ppszSave);
+#else /* Microsoft: */
+char *RT_NOCRT(strtok_s)(char *psz, const char *pszDelim, char **ppszSave);
+#endif
+size_t RT_NOCRT(strxfrm)(char *pszDst, const char *pszSrc, size_t cch);
+
+size_t RT_NOCRT(wcslen)(const wchar_t *pwsz);
+wchar_t *RT_NOCRT(wcscat)(wchar_t *pwszDst, const wchar_t *pwszSrc);
+wchar_t *RT_NOCRT(wcschr)(const wchar_t *pwsz, wchar_t wc);
+wchar_t *RT_NOCRT(wcscpy)(wchar_t *pwszDst, const wchar_t *pwszSrc);
+int RT_NOCRT(wcsicmp)(const wchar_t *pwsz1, const wchar_t *pwsz2);
+size_t RT_NOCRT(wcstombs)(char *pszDst, const wchar_t *pszSrc, size_t cbDst);
+
+
+/* Underscored versions for MSC compatibility (mesa #defines regular to _regular
+ a lot, which is why we really need these prototypes). */
+void *RT_NOCRT(_memchr)(const void *pv, int ch, size_t cb);
+int RT_NOCRT(_memcmp)(const void *pv1, const void *pv2, size_t cb);
+void *RT_NOCRT(_memcpy)(void *pvDst, const void *pvSrc, size_t cb);
+void *RT_NOCRT(_mempcpy)(void *pvDst, const void *pvSrc, size_t cb);
+void *RT_NOCRT(_memrchr)(const void *pv, int ch, size_t cb);
+void *RT_NOCRT(_memmove)(void *pvDst, const void *pvSrc, size_t cb);
+void *RT_NOCRT(_memset)(void *pvDst, int ch, size_t cb);
+
+char *RT_NOCRT(_strcat)(char *pszDst, const char *pszSrc);
+char *RT_NOCRT(_strncat)(char *pszDst, const char *pszSrc, size_t cch);
+char *RT_NOCRT(_strchr)(const char *psz, int ch);
+char *RT_NOCRT(_strrchr)(const char *psz, int ch);
+int RT_NOCRT(_strcmp)(const char *psz1, const char *psz2);
+int RT_NOCRT(_strncmp)(const char *psz1, const char *psz2, size_t cch);
+int RT_NOCRT(_stricmp)(const char *psz1, const char *psz2);
+int RT_NOCRT(_strnicmp)(const char *psz1, const char *psz2, size_t cch);
+int RT_NOCRT(_strcmpcase)(const char *psz1, const char *psz2, size_t cch);
+int RT_NOCRT(_strcoll)(const char *psz1, const char *psz2);
+char *RT_NOCRT(_strcpy)(char *pszDst, const char *pszSrc);
+char *RT_NOCRT(_strncpy)(char *pszDst, const char *pszSrc, size_t cch);
+char *RT_NOCRT(_strcat)(char *pszDst, const char *pszSrc);
+char *RT_NOCRT(_strncat)(char *pszDst, const char *pszSrc, size_t cch);
+size_t RT_NOCRT(_strlen)(const char *psz);
+size_t RT_NOCRT(_strnlen)(const char *psz, size_t cch);
+size_t RT_NOCRT(_strspn)(const char *psz, const char *pszBreakChars);
+size_t RT_NOCRT(_strcspn)(const char *psz, const char *pszBreakChars);
+char *RT_NOCRT(_strpbrk)(const char *psz, const char *pszBreakChars);
+char *RT_NOCRT(_strstr)(const char *psz, const char *pszSub);
+char *RT_NOCRT(_strtok)(char *psz, const char *pszDelim);
+char *RT_NOCRT(_strtok_r)(char *psz, const char *pszDelim, char **ppszSave);
+#if 0 /* C++11: */
+char *RT_NOCRT(_strtok_s)(char *psz, /*rsize_t*/ size_t cchMax, const char *pszDelim, char **ppszSave);
+#else /* Microsoft: */
+char *RT_NOCRT(_strtok_s)(char *psz, const char *pszDelim, char **ppszSave);
+#endif
+size_t RT_NOCRT(_strxfrm)(char *pszDst, const char *pszSrc, size_t cch);
+
+size_t RT_NOCRT(_wcslen)(const wchar_t *pwsz);
+wchar_t *RT_NOCRT(_wcscat)(wchar_t *pwszDst, const wchar_t *pwszSrc);
+wchar_t *RT_NOCRT(_wcschr)(const wchar_t *pwsz, wchar_t wc);
+wchar_t *RT_NOCRT(_wcscpy)(wchar_t *pwszDst, const wchar_t *pwszSrc);
+int RT_NOCRT(_wcsicmp)(const wchar_t *pwsz1, const wchar_t *pwsz2);
+size_t RT_NOCRT(_wcstombs)(char *pszDst, const wchar_t *pszSrc, size_t cbDst);
+
+
+#if !defined(RT_WITHOUT_NOCRT_WRAPPERS) && !defined(RT_WITHOUT_NOCRT_WRAPPER_ALIASES)
+# define memchr RT_NOCRT(memchr)
+# define memcmp RT_NOCRT(memcmp)
+# define memcpy RT_NOCRT(memcpy)
+# define mempcpy RT_NOCRT(mempcpy)
+# define memrchr RT_NOCRT(memrchr)
+# define memmove RT_NOCRT(memmove)
+# define memset RT_NOCRT(memset)
+
+# define strcat RT_NOCRT(strcat)
+# define strncat RT_NOCRT(strncat)
+# define strchr RT_NOCRT(strchr)
+# define strrchr RT_NOCRT(strrchr)
+# define strcmp RT_NOCRT(strcmp)
+# define strncmp RT_NOCRT(strncmp)
+# define stricmp RT_NOCRT(stricmp)
+# define strnicmp RT_NOCRT(strnicmp)
+# define strcmpcase RT_NOCRT(strcmpcase)
+# define strcoll RT_NOCRT(strcoll)
+# define strcpy RT_NOCRT(strcpy)
+# define strncpy RT_NOCRT(strncpy)
+# define strcat RT_NOCRT(strcat)
+# define strncat RT_NOCRT(strncat)
+# define strlen RT_NOCRT(strlen)
+# define strnlen RT_NOCRT(strnlen)
+# define strspn RT_NOCRT(strspn)
+# define strcspn RT_NOCRT(strcspn)
+# define strpbrk RT_NOCRT(strpbrk)
+# define strstr RT_NOCRT(strstr)
+# define strtok RT_NOCRT(strtok)
+# define strtok_r RT_NOCRT(strtok_r)
+# define strtok_s RT_NOCRT(strtok_s)
+# define strxfrm RT_NOCRT(strxfrm)
+
+# define wcslen RT_NOCRT(wcslen)
+# define wcscat RT_NOCRT(wcscat)
+# define wcschr RT_NOCRT(wcschr)
+# define wcscpy RT_NOCRT(wcscpy)
+# define wcsicmp RT_NOCRT(wcsicmp)
+# define wcstombs RT_NOCRT(wcstombs)
+
+/* Underscored: */
+# define _memchr RT_NOCRT(memchr)
+# define _memcmp RT_NOCRT(memcmp)
+# define _memcpy RT_NOCRT(memcpy)
+# define _mempcpy RT_NOCRT(mempcpy)
+# define _memrchr RT_NOCRT(memrchr)
+# define _memmove RT_NOCRT(memmove)
+# define _memset RT_NOCRT(memset)
+
+# define _strcat RT_NOCRT(strcat)
+# define _strncat RT_NOCRT(strncat)
+# define _strchr RT_NOCRT(strchr)
+# define _strrchr RT_NOCRT(strrchr)
+# define _strcmp RT_NOCRT(strcmp)
+# define _strncmp RT_NOCRT(strncmp)
+# define _stricmp RT_NOCRT(stricmp)
+# define _strnicmp RT_NOCRT(strnicmp)
+# define _strcmpcase RT_NOCRT(strcmpcase)
+# define _strcoll RT_NOCRT(strcoll)
+# define _strcpy RT_NOCRT(strcpy)
+# define _strncpy RT_NOCRT(strncpy)
+# define _strcat RT_NOCRT(strcat)
+# define _strncat RT_NOCRT(strncat)
+# define _strlen RT_NOCRT(strlen)
+# define _strnlen RT_NOCRT(strnlen)
+# define _strspn RT_NOCRT(strspn)
+# define _strcspn RT_NOCRT(strcspn)
+# define _strpbrk RT_NOCRT(strpbrk)
+# define _strstr RT_NOCRT(strstr)
+# define _strtok RT_NOCRT(strtok)
+# define _strtok_r RT_NOCRT(strtok_r)
+# define _strtok_s RT_NOCRT(strtok_s)
+# define _strxfrm RT_NOCRT(strxfrm)
+
+# define _wcslen RT_NOCRT(wcslen)
+# define _wcscat RT_NOCRT(wcscat)
+# define _wcschr RT_NOCRT(wcschr)
+# define _wcscpy RT_NOCRT(wcscpy)
+# define _wcsicmp RT_NOCRT(wcsicmp)
+# define _wcstombs RT_NOCRT(wcstombs)
+#endif
+
+
+#ifdef IPRT_NO_CRT_FOR_3RD_PARTY
+/*
+ * Only for external libraries and such.
+ */
+
+const char *RT_NOCRT(strerror)(int iErrNo);
+char *RT_NOCRT(strdup)(const char *pszSrc);
+
+/* Underscored: */
+const char *RT_NOCRT(_strerror)(int iErrNo);
+char *RT_NOCRT(_strdup)(const char *pszSrc);
+
+# if !defined(RT_WITHOUT_NOCRT_WRAPPERS) && !defined(RT_WITHOUT_NOCRT_WRAPPER_ALIASES)
+# define strerror RT_NOCRT(strerror)
+# define strdup RT_NOCRT(strdup)
+
+/* Underscored: */
+# define _strerror RT_NOCRT(strerror)
+# define _strdup RT_NOCRT(strdup)
+# endif
+
+#endif /* IPRT_NO_CRT_FOR_3RD_PARTY */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_nocrt_string_h */
diff --git a/include/iprt/nocrt/sys/stat.h b/include/iprt/nocrt/sys/stat.h
new file mode 100644
index 00000000..0ed81c59
--- /dev/null
+++ b/include/iprt/nocrt/sys/stat.h
@@ -0,0 +1,138 @@
+/** @file
+ * IPRT / No-CRT - sys/stat.h
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_nocrt_sys_stat_h
+#define IPRT_INCLUDED_nocrt_sys_stat_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/nocrt/time.h> /* Establish timespec and timeval before iprt/fs.h includes iprt/time.h. */
+#include <iprt/fs.h>
+#include <iprt/nocrt/sys/types.h>
+#include <iprt/nocrt/limits.h>
+
+#ifdef IPRT_NO_CRT_FOR_3RD_PARTY
+
+struct RT_NOCRT(stat)
+{
+ RTINODE st_ino;
+ RTDEV st_dev;
+ RTDEV st_rdev;
+ RTFMODE st_mode;
+ uint32_t st_link;
+ RTUID st_uid;
+ RTGID st_gid;
+ RTFOFF st_size;
+ RTFOFF st_blocks;
+ uint32_t st_blksize; /**< Not related to st_blocks! */
+ time_t st_birthtime;
+ time_t st_ctime;
+ time_t st_mtime;
+ time_t st_atime;
+};
+
+# define _S_IFIFO RTFS_TYPE_FIFO
+# define _S_IFCHR RTFS_TYPE_DEV_CHAR
+# define _S_IFDIR RTFS_TYPE_DIRECTORY
+# define _S_IFBLK RTFS_TYPE_DEV_BLOCK
+# define _S_IFREG RTFS_TYPE_FILE
+# define _S_IFLNK RTFS_TYPE_SYMLINK
+# define _S_IFSOCK RTFS_TYPE_SOCKET
+# define _S_IFWHT RTFS_TYPE_WHITEOUT
+# define _S_IFMT RTFS_TYPE_MASK
+
+# define S_IFIFO _S_IFIFO
+# define S_IFCHR _S_IFCHR
+# define S_IFDIR _S_IFDIR
+# define S_IFBLK _S_IFBLK
+# define S_IFREG _S_IFREG
+# define S_IFLNK _S_IFLNK
+# define S_IFSOCK _S_IFSOCK
+# define S_IFWHT _S_IFWHT
+# define S_IFMT _S_IFMT
+
+# define S_ISFIFO(a_fMode) RTFS_IS_FIFO(a_fMode)
+# define S_ISCHR(a_fMode) RTFS_IS_DEV_CHAR(a_fMode)
+# define S_ISDIR(a_fMode) RTFS_IS_DIRECTORY(a_fMode)
+# define S_ISBLK(a_fMode) RTFS_IS_DEV_BLOCK(a_fMode)
+# define S_ISREG(a_fMode) RTFS_IS_FILE(a_fMode)
+# define S_ISLNK(a_fMode) RTFS_IS_SYMLINK(a_fMode)
+# define S_ISSOCK(a_fMode) RTFS_IS_SOCKET(a_fMode)
+# define S_ISWHT(a_fMode) RTFS_IS_WHITEOUT(a_fMode)
+
+
+RT_C_DECLS_BEGIN
+
+int RT_NOCRT(chmod)(const char *pszPath, RTFMODE fMode);
+int RT_NOCRT(fchmod)(int fd, RTFMODE fMode);
+int RT_NOCRT(fstat)(int fd, struct RT_NOCRT(stat) *pStat);
+int RT_NOCRT(lstat)(const char *pszPath, struct RT_NOCRT(stat) *pStat);
+int RT_NOCRT(stat)(const char *pszPath, struct RT_NOCRT(stat) *pStat);
+RTFMODE RT_NOCRT(umask)(RTFMODE fMode);
+int RT_NOCRT(mkdir)(const char *, RTFMODE fMode);
+
+int RT_NOCRT(_chmod)(const char *pszPath, RTFMODE fMode);
+int RT_NOCRT(_fchmod)(int fd, RTFMODE fMode);
+int RT_NOCRT(_fstat)(int fd, struct RT_NOCRT(stat) *pStat);
+int RT_NOCRT(_lstat)(const char *pszPath, struct RT_NOCRT(stat) *pStat);
+int RT_NOCRT(_stat)(const char *pszPath, struct RT_NOCRT(stat) *pStat);
+RTFMODE RT_NOCRT(_umask)(RTFMODE fMode);
+int RT_NOCRT(_mkdir)(const char *, RTFMODE fMode);
+
+# if !defined(RT_WITHOUT_NOCRT_WRAPPERS) && !defined(RT_WITHOUT_NOCRT_WRAPPER_ALIASES)
+# define chmod RT_NOCRT(chmod)
+# define fchmod RT_NOCRT(fchmod)
+# define fstat RT_NOCRT(fstat)
+# define lstat RT_NOCRT(lstat)
+# define stat RT_NOCRT(stat)
+# define umask RT_NOCRT(umask)
+# define mkdir RT_NOCRT(mkdir)
+
+# define _chmod RT_NOCRT(chmod)
+# define _fchmod RT_NOCRT(fchmod)
+# define _fstat RT_NOCRT(fstat)
+# define _lstat RT_NOCRT(lstat)
+# define _stat RT_NOCRT(stat)
+# define _umask RT_NOCRT(umask)
+# define _mkdir RT_NOCRT(mkdir)
+# endif
+
+RT_C_DECLS_END
+
+#endif /* IPRT_NO_CRT_FOR_3RD_PARTY */
+
+#endif /* !IPRT_INCLUDED_nocrt_sys_stat_h */
+
diff --git a/include/iprt/nocrt/sys/types.h b/include/iprt/nocrt/sys/types.h
new file mode 100644
index 00000000..3320200a
--- /dev/null
+++ b/include/iprt/nocrt/sys/types.h
@@ -0,0 +1,66 @@
+/** @file
+ * IPRT / No-CRT - Our own sys/types header.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_nocrt_sys_types_h
+#define IPRT_INCLUDED_nocrt_sys_types_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#if defined(IPRT_INCLUDED_types_h) && !defined(IPRT_COMPLETED_types_h)
+# error "Can't include nocrt/sys/types.h from iprt/types.h"
+#endif
+
+#include <iprt/types.h>
+
+/* #if !defined(MSC-define) && !defined(GNU/LINUX-define) */
+#if !defined(_DEV_T_DEFINED) && !defined(__dev_t_defined)
+typedef RTDEV dev_t;
+#endif
+#if !defined(_UCRT_RESTORE_CLANG_WARNINGS) /* MSC specific type */
+typedef int errno_t;
+#endif
+#if !defined(_INO_T_DEFINED) && !defined(__ino_t_defined)
+typedef RTINODE ino_t;
+#endif
+#if !defined(_OFF_T_DEFINED) && !defined(__off_t_defined)
+typedef RTFOFF off_t;
+#endif
+#if !defined(_PID_T_DEFINED) && !defined(__pid_t_defined)
+typedef RTPROCESS pid_t;
+#endif
+
+#endif /* !IPRT_INCLUDED_nocrt_sys_types_h */
+
diff --git a/include/iprt/nocrt/time.h b/include/iprt/nocrt/time.h
new file mode 100644
index 00000000..ab2a8649
--- /dev/null
+++ b/include/iprt/nocrt/time.h
@@ -0,0 +1,107 @@
+/** @file
+ * IPRT / No-CRT - Our minimal time.h.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_nocrt_time_h
+#define IPRT_INCLUDED_nocrt_time_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#define RTTIME_INCL_TIMESPEC
+/*#define RTTIME_INCL_TIMEVAL*/
+#include <iprt/types.h>
+#include <iprt/nocrt/sys/types.h>
+
+/* #if !defined(MSC-define) && !defined(GNU/LINUX-define) */
+#if !defined(_TIME_T_DEFINED) && !defined(__time_t_defined)
+# if defined(RT_OS_WINDOWS) && defined(_USE_32BIT_TIME_T) && ARCH_BITS == 32
+typedef long time_t;
+# else
+typedef int64_t time_t;
+# endif
+# ifdef _MSC_VER
+typedef int64_t __time64_t;
+# endif
+#endif /* !_TIME_T_DEFINED */
+
+#if !defined(_INC_TIME) /* MSC/UCRT guard */
+
+# if !defined(_STRUCT_TIMESPEC) && !defined(__struct_timespec_defined) && !defined(_TIMESPEC_DEFINED) && !defined(__timespec_defined) /* << linux variations, new to old. */
+struct timespec
+{
+ time_t tv_sec;
+ long tv_nsec;
+};
+# endif
+
+#if !defined(__struct_tm_defined)
+struct tm
+{
+ int tm_sec, tm_min, tm_hour, tm_mday, tm_mon, tm_year;
+ int tm_wday, tm_yday, tm_isdst, tm_gmtoff;
+ const char *tm_zone;
+};
+# endif
+
+#endif /* !_INC_TIME */
+
+RT_C_DECLS_BEGIN
+
+time_t RT_NOCRT(time)(time_t *);
+errno_t RT_NOCRT(localtime_s)(struct tm *, const time_t *); /* The Microsoft version, not the C11 one. */
+struct tm *RT_NOCRT(localtime_r)(const time_t *, struct tm *);
+
+time_t RT_NOCRT(_time)(time_t *);
+errno_t RT_NOCRT(_localtime_s)(struct tm *, const time_t *);
+struct tm *RT_NOCRT(_localtime_r)(const time_t *, struct tm *);
+
+# if !defined(RT_WITHOUT_NOCRT_WRAPPERS) && !defined(RT_WITHOUT_NOCRT_WRAPPER_ALIASES)
+# define time RT_NOCRT(time)
+# define localtime_s RT_NOCRT(localtime_s)
+# define localtime_r RT_NOCRT(localtime_r)
+
+# define _time RT_NOCRT(time)
+# define _localtime_s RT_NOCRT(localtime_s)
+# define _localtime_r RT_NOCRT(localtime_r)
+# endif
+
+RT_C_DECLS_END
+
+#ifdef IPRT_INCLUDED_time_h
+# error nocrt/time.h after time.h
+#endif
+
+#endif /* !IPRT_INCLUDED_nocrt_time_h */
+
diff --git a/include/iprt/nocrt/type_traits b/include/iprt/nocrt/type_traits
new file mode 100644
index 00000000..c8c35b2f
--- /dev/null
+++ b/include/iprt/nocrt/type_traits
@@ -0,0 +1,88 @@
+/** @file
+ * IPRT / No-CRT - Minimal type_traits C++ header.
+ */
+
+/*
+ * Copyright (C) 2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_SRC_nocrt_type_traits
+#define VBOX_INCLUDED_SRC_nocrt_type_traits
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cdefs.h>
+
+namespace std
+{
+ /*
+ * std::integral_constant
+ */
+ template<typename a_Type, a_Type a_Value>
+ struct integral_constant
+ {
+ static constexpr a_Type value = a_Value;
+ typedef a_Type value_type;
+ typedef integral_constant<a_Type, a_Value> type;
+ constexpr operator value_type() const RT_NOEXCEPT { return value; }
+ /** @todo operator()() for 2014+ */
+ };
+ template<typename a_Type, a_Type a_Value> constexpr a_Type integral_constant<a_Type, a_Value>::value;
+
+ /* Helper: */
+ template<bool a_Value> using bool_constant = integral_constant<bool, a_Value>;
+
+ /* Specializations: */
+ typedef integral_constant<bool, true> true_type;
+ typedef integral_constant<bool, false> false_type;
+
+
+ /*
+ * std::is_enum
+ */
+ template<typename a_Type> struct is_enum
+ : integral_constant<bool, __is_enum(a_Type) /* compiler (clan, gcc, msc) builtin */ >
+ { };
+
+ /*
+ * std::underlying_type
+ */
+ template<typename a_Type> struct underlying_type
+ {
+ using type = __underlying_type(a_Type); /* compiler (clan, gcc, msc) builtin */
+ };
+
+ template<typename a_Type> using underlying_type_t = typename underlying_type<a_Type>::type;
+
+}
+
+#endif /* !VBOX_INCLUDED_SRC_nocrt_type_traits */
+
diff --git a/include/iprt/nocrt/unistd.h b/include/iprt/nocrt/unistd.h
new file mode 100644
index 00000000..270a0739
--- /dev/null
+++ b/include/iprt/nocrt/unistd.h
@@ -0,0 +1,125 @@
+/** @file
+ * IPRT / No-CRT - Minimal unistd.h header.
+ */
+
+/*
+ * Copyright (C) 2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_nocrt_unistd_h
+#define IPRT_INCLUDED_nocrt_unistd_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/nocrt/sys/types.h>
+#ifdef IPRT_NO_CRT_FOR_3RD_PARTY
+# include <iprt/nocrt/time.h> /* file.h includes fs.h which includes time.h */
+# include <iprt/file.h> /* for RTFILE_SEEK_XXX */
+# include <iprt/assertcompile.h>
+#endif
+
+
+#ifdef IPRT_NO_CRT_FOR_3RD_PARTY
+
+/* Flags for access: */
+# define F_OK 0
+# define X_OK 1
+# define W_OK 2
+# define R_OK 4
+
+/* These are also in stdio.h: */
+# undef SEEK_SET
+# define SEEK_SET RTFILE_SEEK_BEGIN
+# undef SEEK_CUR
+# define SEEK_CUR RTFILE_SEEK_CURRENT
+# undef SEEK_END
+# define SEEK_END RTFILE_SEEK_END
+AssertCompile(SEEK_SET == 0); AssertCompile(SEEK_CUR == 1); AssertCompile(SEEK_END == 2); /* Also in WDK header mmiscapi.h. */
+
+RT_C_DECLS_BEGIN
+
+int RT_NOCRT(access)(const char *, int) RT_NOEXCEPT;
+int RT_NOCRT(dup)(int) RT_NOEXCEPT;
+int RT_NOCRT(dup2)(int, int) RT_NOEXCEPT;
+ssize_t RT_NOCRT(read)(int, void *, size_t) RT_NOEXCEPT;
+ssize_t RT_NOCRT(write)(int, const void *, size_t) RT_NOEXCEPT;
+int RT_NOCRT(close)(int) RT_NOEXCEPT;
+int RT_NOCRT(isatty)(int) RT_NOEXCEPT;
+char *RT_NOCRT(getcwd)(char *, size_t) RT_NOEXCEPT;
+RTPROCESS RT_NOCRT(getpid)(void) RT_NOEXCEPT;
+RTPROCESS RT_NOCRT(getppid)(void) RT_NOEXCEPT;
+int RT_NOCRT(unlink)(const char *) RT_NOEXCEPT;
+
+int RT_NOCRT(_access)(const char *, int) RT_NOEXCEPT;
+int RT_NOCRT(_dup)(int) RT_NOEXCEPT;
+int RT_NOCRT(_dup2)(int, int) RT_NOEXCEPT;
+ssize_t RT_NOCRT(_read)(int, void *, size_t) RT_NOEXCEPT;
+ssize_t RT_NOCRT(_write)(int, const void *, size_t) RT_NOEXCEPT;
+int RT_NOCRT(_close)(int) RT_NOEXCEPT;
+int RT_NOCRT(_isatty)(int) RT_NOEXCEPT;
+char *RT_NOCRT(_getcwd)(char *, size_t) RT_NOEXCEPT;
+RTPROCESS RT_NOCRT(_getpid)(void) RT_NOEXCEPT;
+RTPROCESS RT_NOCRT(_getppid)(void) RT_NOEXCEPT;
+int RT_NOCRT(_unlink)(const char *) RT_NOEXCEPT;
+
+# if !defined(RT_WITHOUT_NOCRT_WRAPPERS) && !defined(RT_WITHOUT_NOCRT_WRAPPER_ALIASES)
+# define access RT_NOCRT(access)
+# define dup RT_NOCRT(dup)
+# define dup2 RT_NOCRT(dup2)
+# define read RT_NOCRT(read)
+# define write RT_NOCRT(write)
+# define close RT_NOCRT(close)
+# define isatty RT_NOCRT(isatty)
+# define getcwd RT_NOCRT(getcwd)
+# define getpid RT_NOCRT(getpid)
+# define getppid RT_NOCRT(getppid)
+# define unlink RT_NOCRT(unlink)
+
+# define _access RT_NOCRT(access)
+# define _dup RT_NOCRT(dup)
+# define _dup2 RT_NOCRT(dup2)
+# define _read RT_NOCRT(read)
+# define _write RT_NOCRT(write)
+# define _close RT_NOCRT(close)
+# define _isatty RT_NOCRT(isatty)
+# define _getcwd RT_NOCRT(getcwd)
+# define _getpid RT_NOCRT(getpid)
+# define _getppid RT_NOCRT(getppid)
+# define _unlink RT_NOCRT(unlink)
+# endif
+
+RT_C_DECLS_END
+
+#endif /* IPRT_NO_CRT_FOR_3RD_PARTY */
+
+
+#endif /* !IPRT_INCLUDED_nocrt_unistd_h */
+
diff --git a/include/iprt/nocrt/vector b/include/iprt/nocrt/vector
new file mode 100644
index 00000000..bee4b734
--- /dev/null
+++ b/include/iprt/nocrt/vector
@@ -0,0 +1,398 @@
+/** @file
+ * IPRT / No-CRT - Minimal C++ std::vector.
+ */
+
+/*
+ * Copyright (C) 2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef VBOX_INCLUDED_SRC_nocrt_vector
+#define VBOX_INCLUDED_SRC_nocrt_vector
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/nocrt/memory>
+
+namespace std
+{
+ template<typename a_Type, class a_Container>
+ class RTCNoCrtVectorIterator
+ {
+ public:
+ typedef a_Type &reference;
+ typedef a_Type *pointer;
+ typedef typename a_Container::difference_type difference_type;
+
+ protected:
+ a_Type *m_pItem;
+
+ public:
+ RTCNoCrtVectorIterator() RT_NOEXCEPT
+ : m_pItem(NULL)
+ { }
+
+ RTCNoCrtVectorIterator(a_Type *a_pItem) RT_NOEXCEPT
+ : m_pItem(a_pItem)
+ { }
+
+ ~RTCNoCrtVectorIterator()
+ {
+ m_pItem = NULL;
+ }
+
+ /** @name Moving the iterator.
+ * @{ */
+
+ RTCNoCrtVectorIterator &operator++() RT_NOEXCEPT
+ {
+ ++m_pItem;
+ return *this;
+ }
+
+ RTCNoCrtVectorIterator &operator--() RT_NOEXCEPT
+ {
+ --m_pItem;
+ return *this;
+ }
+
+ RTCNoCrtVectorIterator operator++(int) RT_NOEXCEPT
+ {
+ return RTCNoCrtVectorIterator(m_pItem++);
+ }
+
+ RTCNoCrtVectorIterator operator--(int) RT_NOEXCEPT
+ {
+ return RTCNoCrtVectorIterator(m_pItem--);
+ }
+
+ RTCNoCrtVectorIterator &operator+=(difference_type cItems) RT_NOEXCEPT
+ {
+ m_pItem += cItems;
+ return *this;
+ }
+
+ RTCNoCrtVectorIterator &operator-=(difference_type cItems) RT_NOEXCEPT
+ {
+ m_pItem -= cItems;
+ return *this;
+ }
+
+ RTCNoCrtVectorIterator operator+(difference_type cItems) const RT_NOEXCEPT
+ {
+ return RTCNoCrtVectorIterator(m_pItem + cItems);
+ }
+
+ RTCNoCrtVectorIterator operator-(difference_type cItems) const RT_NOEXCEPT
+ {
+ return RTCNoCrtVectorIterator(m_pItem - cItems);
+ }
+
+ /** @} */
+
+ /** @name Item access
+ * @{ */
+ reference operator*() const RT_NOEXCEPT
+ {
+ return *m_pItem;
+ }
+
+ pointer operator->() const RT_NOEXCEPT
+ {
+ return m_pItem;
+ }
+
+ reference operator[](difference_type iItem) const RT_NOEXCEPT
+ {
+ return m_pItem[iItem];
+ }
+
+ /** @} */
+
+ /** Helper for const/non-const iterator comparisons: */
+ inline typename a_Container::const_pointer getConst() const RT_NOEXCEPT
+ {
+ return m_pItem;
+ }
+ };
+
+ template<typename a_TypeLeft, typename a_TypeRight, class a_Container>
+ inline bool operator==(const RTCNoCrtVectorIterator<a_TypeLeft, a_Container> &a_rLeft,
+ const RTCNoCrtVectorIterator<a_TypeRight, a_Container> &a_rRight) RT_NOEXCEPT
+ {
+ return a_rLeft.getConst() == a_rRight.getConst();
+ }
+
+ template<typename a_TypeLeft, typename a_TypeRight, class a_Container>
+ inline bool operator!=(const RTCNoCrtVectorIterator<a_TypeLeft, a_Container> &a_rLeft,
+ const RTCNoCrtVectorIterator<a_TypeRight, a_Container> &a_rRight) RT_NOEXCEPT
+ {
+ return a_rLeft.getConst() != a_rRight.getConst();
+ }
+
+ template<typename a_TypeLeft, typename a_TypeRight, class a_Container>
+ inline bool operator<(const RTCNoCrtVectorIterator<a_TypeLeft, a_Container> &a_rLeft,
+ const RTCNoCrtVectorIterator<a_TypeRight, a_Container> &a_rRight) RT_NOEXCEPT
+ {
+ return (uintptr_t)a_rLeft.getConst() < (uintptr_t)a_rRight.getConst();
+ }
+
+ template<typename a_TypeLeft, typename a_TypeRight, class a_Container>
+ inline bool operator<=(const RTCNoCrtVectorIterator<a_TypeLeft, a_Container> &a_rLeft,
+ const RTCNoCrtVectorIterator<a_TypeRight, a_Container> &a_rRight) RT_NOEXCEPT
+ {
+ return (uintptr_t)a_rLeft.getConst() <= (uintptr_t)a_rRight.getConst();
+ }
+
+ template<typename a_TypeLeft, typename a_TypeRight, class a_Container>
+ inline bool operator>(const RTCNoCrtVectorIterator<a_TypeLeft, a_Container> &a_rLeft,
+ const RTCNoCrtVectorIterator<a_TypeRight, a_Container> &a_rRight) RT_NOEXCEPT
+ {
+ return (uintptr_t)a_rLeft.getConst() > (uintptr_t)a_rRight.getConst();
+ }
+
+ template<typename a_TypeLeft, typename a_TypeRight, class a_Container>
+ inline bool operator>=(const RTCNoCrtVectorIterator<a_TypeLeft, a_Container> &a_rLeft,
+ const RTCNoCrtVectorIterator<a_TypeRight, a_Container> &a_rRight) RT_NOEXCEPT
+ {
+ return (uintptr_t)a_rLeft.getConst() >= (uintptr_t)a_rRight.getConst();
+ }
+
+
+
+ template<class a_Type, class a_Allocator = std::allocator<a_Type> >
+ class vector
+ {
+ public:
+ typedef a_Type value_type;
+ typedef a_Type &reference;
+ typedef a_Type const &const_reference;
+ typedef a_Allocator allocator_type;
+ typedef typename a_Allocator::size_type size_type;
+ typedef typename a_Allocator::difference_type difference_type;
+ typedef typename a_Allocator::pointer pointer;
+ typedef typename a_Allocator::const_pointer const_pointer;
+
+ typedef RTCNoCrtVectorIterator<a_Type, vector> iterator;
+ typedef RTCNoCrtVectorIterator<const a_Type, vector> const_iterator;
+
+ protected:
+ pointer m_paItems;
+ size_t m_cItems;
+ size_t m_cAllocated;
+ allocator_type m_Allocator;
+
+ public:
+ vector() RT_NOEXCEPT
+ : m_paItems(NULL)
+ , m_cItems(0)
+ , m_cAllocated(0)
+ { }
+
+ vector(size_type a_cAllocate)
+ : m_paItems(NULL)
+ , m_cItems(0)
+ , m_cAllocated(0)
+ {
+ m_paItems = m_Allocator.allocate(a_cAllocate);
+ if (m_paItems)
+ m_cAllocated = a_cAllocate;
+ }
+
+ ~vector()
+ {
+ clear();
+ }
+
+ /** @name Iterators
+ * @{ */
+ iterator begin() RT_NOEXCEPT
+ {
+ return iterator(m_paItems);
+ }
+
+ const_iterator begin() const RT_NOEXCEPT
+ {
+ return const_iterator(m_paItems);
+ }
+
+ const_iterator cbegin() const RT_NOEXCEPT
+ {
+ return const_iterator(m_paItems);
+ }
+
+ iterator end() RT_NOEXCEPT
+ {
+ return iterator(m_paItems + m_cItems);
+ }
+
+ const_iterator end() const RT_NOEXCEPT
+ {
+ return const_iterator(m_paItems + m_cItems);
+ }
+
+ const_iterator cend() const RT_NOEXCEPT
+ {
+ return const_iterator(m_paItems + m_cItems);
+ }
+ /** @} */
+
+ /** @name Element access
+ * @{ */
+ reference operator[](size_type iItem) RT_NOEXCEPT
+ {
+ Assert(iItem < m_cAllocated);
+ return m_paItems[iItem];
+ }
+
+ const_reference operator[](size_type iItem) const RT_NOEXCEPT
+ {
+ Assert(iItem < m_cAllocated);
+ return m_paItems[iItem];
+ }
+
+ reference front() RT_NOEXCEPT
+ {
+ return m_paItems[0];
+ }
+
+ const_reference front() const RT_NOEXCEPT
+ {
+ return m_paItems[0];
+ }
+
+ reference back() RT_NOEXCEPT
+ {
+ return m_paItems[m_cItems - 1];
+ }
+
+ const_reference back() const RT_NOEXCEPT
+ {
+ return m_paItems[m_cItems - 1];
+ }
+
+ pointer data() RT_NOEXCEPT
+ {
+ return m_paItems;
+ }
+
+ const_pointer data() const RT_NOEXCEPT
+ {
+ return m_paItems;
+ }
+
+ /** @} */
+
+ /** @name Capacity
+ * @{ */
+ bool empty() const RT_NOEXCEPT
+ {
+ return m_cItems == 0;
+ }
+
+ size_type size() const RT_NOEXCEPT
+ {
+ return m_cItems;
+ }
+
+ size_type max_size() const RT_NOEXCEPT
+ {
+ return m_Allocator.max_size();
+ }
+
+ void reserve(size_type a_cNewAllocated)
+ {
+ Assert(a_cNewAllocated <= max_size());
+
+ if (a_cNewAllocated > m_cAllocated)
+ {
+ vector Temp(a_cNewAllocated);
+ if (Temp.m_paItems)
+ {
+ /* Copy over the data: */
+ size_type const cItems = m_cItems;
+ const_pointer paSrc = m_paItems;
+ pointer paDst = Temp.m_paItems;
+ for (size_type i = 0; i < cItems; Temp.m_cItems = ++i)
+ m_Allocator.construct(&paDst[i], paSrc[i]);
+
+ /* Swap the data. */
+ size_type const cOldAllocated = m_cAllocated;
+ Temp.m_paItems = m_paItems;
+ m_paItems = paDst;
+ m_cAllocated = Temp.m_cAllocated;
+ Temp.m_cAllocated = cOldAllocated;
+ }
+ }
+ }
+
+ /** @} */
+
+ /** @name Modifiers
+ * @{ */
+ void push_back(const_reference a_rValue)
+ {
+ if (m_cItems < m_cAllocated)
+ { }
+ else
+ {
+ Assert(m_cItems * 2 >= m_cItems);
+ reserve(m_cItems < 8 ? 8 : m_cItems * 2); /* This might be non-standard. */
+ AssertReturnVoid(m_cItems < m_cAllocated);
+ }
+ m_paItems[m_cItems] = a_rValue;
+ m_cItems++;
+ }
+
+ void pop_back() RT_NOEXCEPT
+ {
+ if (m_cItems > 0)
+ m_cItems -= 1;
+ }
+
+ void clear() RT_NOEXCEPT
+ {
+ size_type i = m_cItems;
+ while (i-- > 0)
+ {
+ m_Allocator.destroy(&m_paItems[i]);
+ m_cItems = i;
+ }
+ m_Allocator.deallocate(m_paItems, m_cAllocated);
+ m_paItems = NULL;
+ m_cAllocated = 0;
+ }
+ /** @} */
+ };
+
+}
+
+#endif /* !VBOX_INCLUDED_SRC_nocrt_vector */
+
diff --git a/include/iprt/nocrt/x86/Makefile.kup b/include/iprt/nocrt/x86/Makefile.kup
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/include/iprt/nocrt/x86/Makefile.kup
diff --git a/include/iprt/nocrt/x86/fenv-x86-amd64.h b/include/iprt/nocrt/x86/fenv-x86-amd64.h
new file mode 100644
index 00000000..55199ab8
--- /dev/null
+++ b/include/iprt/nocrt/x86/fenv-x86-amd64.h
@@ -0,0 +1,219 @@
+/** @file
+ * IPRT / No-CRT - x86 & AMD64 fenv.h.
+ */
+
+/*
+ * Copyright (C) 2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_nocrt_x86_fenv_x86_amd64_h
+#define IPRT_INCLUDED_nocrt_x86_fenv_x86_amd64_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+
+typedef struct RTNOCRTFENV
+{
+ /** The FPU environment. */
+ union
+ {
+ uint32_t au32[28/4];
+#ifdef IPRT_INCLUDED_x86_h
+ X86FSTENV32P Env;
+#endif
+ } fpu;
+ /** The SSE control & status register. */
+ uint32_t fMxCsr;
+} RTNOCRTFENV;
+
+/** Exception flags/mask. */
+typedef uint16_t RTNOCRTFEXCEPT;
+
+#ifndef IPRT_NOCRT_WITHOUT_CONFLICTING_TYPES
+typedef RTNOCRTFENV fenv_t;
+typedef RTNOCRTFEXCEPT fexcept_t;
+#endif
+
+/** @name Exception flags (same as X86_FCW_xM, X86_FSW_xE, X86_MXCSR_xE)
+ * @note The X86_FSW_SF is not covered here as it is more of a sub-type of
+ * invalid operand exception, and it is not part of MXCSR.
+ * @{ */
+#define RT_NOCRT_FE_INVALID 0x0001
+#define RT_NOCRT_FE_DENORMAL 0x0002
+#define RT_NOCRT_FE_DIVBYZERO 0x0004
+#define RT_NOCRT_FE_OVERFLOW 0x0008
+#define RT_NOCRT_FE_UNDERFLOW 0x0010
+#define RT_NOCRT_FE_INEXACT 0x0020
+#define RT_NOCRT_FE_ALL_EXCEPT 0x003f
+#ifndef IPRT_NOCRT_WITHOUT_MATH_CONSTANTS
+# define FE_INVALID RT_NOCRT_FE_INVALID
+# define FE_DENORMAL RT_NOCRT_FE_DENORMAL
+# define FE_DIVBYZERO RT_NOCRT_FE_DIVBYZERO
+# define FE_OVERFLOW RT_NOCRT_FE_OVERFLOW
+# define FE_UNDERFLOW RT_NOCRT_FE_UNDERFLOW
+# define FE_INEXACT RT_NOCRT_FE_INEXACT
+# define FE_ALL_EXCEPT RT_NOCRT_FE_ALL_EXCEPT
+#endif
+/** @} */
+
+/** @name Rounding Modes (same X86_FCW_RC_XXX)
+ * @{ */
+#define RT_NOCRT_FE_TONEAREST 0x0000
+#define RT_NOCRT_FE_DOWNWARD 0x0400
+#define RT_NOCRT_FE_UPWARD 0x0800
+#define RT_NOCRT_FE_TOWARDZERO 0x0c00
+#define RT_NOCRT_FE_ROUND_MASK 0x0c00
+#ifndef IPRT_NOCRT_WITHOUT_MATH_CONSTANTS
+# define FE_TONEAREST RT_NOCRT_FE_TONEAREST
+# define FE_DOWNWARD RT_NOCRT_FE_DOWNWARD
+# define FE_UPWARD RT_NOCRT_FE_UPWARD
+# define FE_TOWARDZERO RT_NOCRT_FE_TOWARDZERO
+#endif
+/** @} */
+
+
+/** @name x87 Precision (same X86_FCW_PC_XXX)
+ * @{ */
+#define RT_NOCRT_PC_FLOAT 0x0000
+#define RT_NOCRT_PC_RSVD 0x0100
+#define RT_NOCRT_PC_DOUBLE 0x0200
+#define RT_NOCRT_PC_EXTENDED 0x0300
+#define RT_NOCRT_PC_MASK 0x0300
+/** @} */
+
+
+/** @name Special environment pointer values.
+ * @note Only valid with fesetenv and feupdateenv.
+ * @note Defined as constants in fesetenv.asm.
+ * @{ */
+/** The default FPU+SSE environment set, all exceptions disabled (masked). */
+#define RT_NOCRT_FE_DFL_ENV ((RTNOCRTFENV const *)(intptr_t)1)
+/** The default FPU+SSE environment set, but all exceptions enabled (unmasked)
+ * except for RT_NOCRT_FE_DENORMAL. */
+#define RT_NOCRT_FE_NOMASK_ENV ((RTNOCRTFENV const *)(intptr_t)2)
+/** The default FPU+SSE environment set, all exceptions disabled (masked),
+ * double precision (53 bit mantissa). */
+#define RT_NOCRT_FE_PC53_ENV ((RTNOCRTFENV const *)(intptr_t)3)
+/** The default FPU+SSE environment set, all exceptions disabled (masked),
+ * extended double precision (64 bit mantissa). */
+#define RT_NOCRT_FE_PC64_ENV ((RTNOCRTFENV const *)(intptr_t)4)
+#ifndef IPRT_NOCRT_WITHOUT_MATH_CONSTANTS
+# define FE_DFL_ENV RT_NOCRT_FE_DFL_ENV
+# define FE_NOMASK_ENV RT_NOCRT_FE_NOMASK_ENV
+# define FE_PC53_ENV RT_NOCRT_FE_PC53_ENV
+# define FE_PC64_ENV RT_NOCRT_FE_PC64_ENV
+#endif
+/** @} */
+
+RT_C_DECLS_BEGIN
+
+int RT_NOCRT(fegetenv)(RTNOCRTFENV *);
+int RT_NOCRT(fesetenv)(RTNOCRTFENV const *);
+int RT_NOCRT(feholdexcept)(RTNOCRTFENV *);
+int RT_NOCRT(feupdateenv)(RTNOCRTFENV const *);
+
+int RT_NOCRT(fegetround)(void);
+int RT_NOCRT(fesetround)(int);
+
+int RT_NOCRT(fegetexcept)(void);
+int RT_NOCRT(feenableexcept)(int);
+int RT_NOCRT(fedisableexcept)(int);
+
+int RT_NOCRT(feclearexcept)(int);
+int RT_NOCRT(fetestexcept)(int);
+int RT_NOCRT(fegetexceptflag)(RTNOCRTFEXCEPT *, int);
+int RT_NOCRT(fesetexceptflag)(RTNOCRTFEXCEPT const *, int);
+
+int RT_NOCRT(feraiseexcept)(int);
+
+/* IPRT addition: */
+int RT_NOCRT(fegetx87precision)(void);
+int RT_NOCRT(fesetx87precision)(int);
+
+/* Underscored variants: */
+int RT_NOCRT(_fegetenv)(RTNOCRTFENV *);
+int RT_NOCRT(_fesetenv)(RTNOCRTFENV const *);
+int RT_NOCRT(_feholdexcept)(RTNOCRTFENV *);
+int RT_NOCRT(_feupdateenv)(RTNOCRTFENV const *);
+
+int RT_NOCRT(_fegetround)(void);
+int RT_NOCRT(_fesetround)(int);
+
+int RT_NOCRT(_fegetexcept)(void);
+int RT_NOCRT(_feenableexcept)(int);
+int RT_NOCRT(_fedisableexcept)(int);
+
+int RT_NOCRT(_feclearexcept)(int);
+int RT_NOCRT(_fetestexcept)(int);
+int RT_NOCRT(_fegetexceptflag)(RTNOCRTFEXCEPT *, int);
+int RT_NOCRT(_fesetexceptflag)(RTNOCRTFEXCEPT const *, int);
+
+int RT_NOCRT(_feraiseexcept)(int);
+
+/* Aliases: */
+#if !defined(RT_WITHOUT_NOCRT_WRAPPERS) && !defined(RT_WITHOUT_NOCRT_WRAPPER_ALIASES)
+# define fegetenv RT_NOCRT(fegetenv)
+# define fesetenv RT_NOCRT(fesetenv)
+# define feholdexcept RT_NOCRT(feholdexcept)
+# define feupdateenv RT_NOCRT(feupdateenv)
+# define fegetround RT_NOCRT(fegetround)
+# define fesetround RT_NOCRT(fesetround)
+# define fegetexcept RT_NOCRT(fegetexcept)
+# define feenableexcept RT_NOCRT(feenableexcept)
+# define fedisableexcept RT_NOCRT(fedisableexcept)
+# define feclearexcept RT_NOCRT(feclearexcept)
+# define fetestexcept RT_NOCRT(fetestexcept)
+# define fegetexceptflag RT_NOCRT(fegetexceptflag)
+# define fesetexceptflag RT_NOCRT(fesetexceptflag)
+# define feraiseexcept RT_NOCRT(feraiseexcept)
+
+/* Underscored variants: */
+# define _fegetenv RT_NOCRT(fegetenv)
+# define _fesetenv RT_NOCRT(fesetenv)
+# define _feholdexcept RT_NOCRT(feholdexcept)
+# define _feupdateenv RT_NOCRT(feupdateenv)
+# define _fegetround RT_NOCRT(fegetround)
+# define _fesetround RT_NOCRT(fesetround)
+# define _fegetexcept RT_NOCRT(fegetexcept)
+# define _feenableexcept RT_NOCRT(feenableexcept)
+# define _fedisableexcept RT_NOCRT(fedisableexcept)
+# define _feclearexcept RT_NOCRT(feclearexcept)
+# define _fetestexcept RT_NOCRT(fetestexcept)
+# define _fegetexceptflag RT_NOCRT(fegetexceptflag)
+# define _fesetexceptflag RT_NOCRT(fesetexceptflag)
+# define _feraiseexcept RT_NOCRT(feraiseexcept)
+#endif
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_nocrt_x86_fenv_x86_amd64_h */
+
diff --git a/include/iprt/nocrt/x86/math.h b/include/iprt/nocrt/x86/math.h
new file mode 100644
index 00000000..1aa223a3
--- /dev/null
+++ b/include/iprt/nocrt/x86/math.h
@@ -0,0 +1,114 @@
+/** @file
+ * IPRT / No-CRT - math.h, x86 inlined functions.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_nocrt_x86_math_h
+#define IPRT_INCLUDED_nocrt_x86_math_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/asm.h>
+
+#if RT_INLINE_ASM_GNU_STYLE
+
+DECLINLINE(long double) inline_atan2l(long double lrd1, long double lrd2)
+{
+ long double lrdResult;
+ __asm__ __volatile__("fpatan"
+ : "=t" (lrdResult)
+ : "u" (lrd1),
+ "0" (lrd2)
+ : "st(1)");
+ return lrdResult;
+}
+
+DECLINLINE(long double) inline_rintl(long double lrd)
+{
+ long double lrdResult;
+ __asm__ __volatile__("frndint"
+ : "=t" (lrdResult)
+ : "0" (lrd));
+ return lrdResult;
+}
+
+DECLINLINE(float) inline_rintf(float rf)
+{
+ return (float)inline_rintl(rf);
+}
+
+DECLINLINE(double) inline_rint(double rd)
+{
+ return (double)inline_rintl(rd);
+}
+
+DECLINLINE(long double) inline_sqrtl(long double lrd)
+{
+ long double lrdResult;
+ __asm__ __volatile__("fsqrt"
+ : "=t" (lrdResult)
+ : "0" (lrd));
+ return lrdResult;
+}
+
+DECLINLINE(float) inline_sqrtf(float rf)
+{
+ return (float)inline_sqrtl(rf);
+}
+
+DECLINLINE(double) inline_sqrt(double rd)
+{
+ return (double)inline_sqrtl(rd);
+}
+
+
+# undef atan2l
+# define atan2l(lrd1, lrd2) inline_atan2l(lrd1, lrd2)
+# undef rint
+# define rint(rd) inline_rint(rd)
+# undef rintf
+# define rintf(rf) inline_rintf(rf)
+# undef rintl
+# define rintl(lrd) inline_rintl(lrd)
+# undef sqrt
+# define sqrt(rd) inline_sqrt(rd)
+# undef sqrtf
+# define sqrtf(rf) inline_sqrtf(rf)
+# undef sqrtl
+# define sqrtl(lrd) inline_sqrtl(lrd)
+
+#endif /* RT_INLINE_ASM_GNU_STYLE */
+
+#endif /* !IPRT_INCLUDED_nocrt_x86_math_h */
+
diff --git a/include/iprt/nt/Makefile.kup b/include/iprt/nt/Makefile.kup
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/include/iprt/nt/Makefile.kup
diff --git a/include/iprt/nt/dispmprt.h b/include/iprt/nt/dispmprt.h
new file mode 100644
index 00000000..055648d9
--- /dev/null
+++ b/include/iprt/nt/dispmprt.h
@@ -0,0 +1,61 @@
+/** @file
+ * Safe way to include dispmprt.h (DDK).
+ */
+
+/*
+ * Copyright (C) 2016-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_nt_dispmprt_h
+#define IPRT_INCLUDED_nt_dispmprt_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cdefs.h>
+
+#ifdef _MSC_VER
+# pragma warning(push)
+# pragma warning(disable:4668) /* warning C4668: 'DBG' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif' */
+# ifndef __cplusplus
+# pragma warning(disable:4255) /* video.h(1776) : warning C4255: 'VideoPortGetCurrentIrql' : no function prototype given: converting '()' to '(void)' */
+# endif
+#endif
+
+RT_C_DECLS_BEGIN
+#include <dispmprt.h>
+RT_C_DECLS_END
+
+#ifdef _MSC_VER
+# pragma warning(pop)
+#endif
+
+#endif /* !IPRT_INCLUDED_nt_dispmprt_h */
+
diff --git a/include/iprt/nt/hyperv.h b/include/iprt/nt/hyperv.h
new file mode 100644
index 00000000..aa461a35
--- /dev/null
+++ b/include/iprt/nt/hyperv.h
@@ -0,0 +1,1768 @@
+/** @file
+ * Hyper-V related types and definitions.
+ */
+
+/*
+ * Copyright (C) 2018-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_nt_hyperv_h
+#define IPRT_INCLUDED_nt_hyperv_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+
+#ifndef IN_IDA_PRO
+# include <iprt/types.h>
+# include <iprt/assertcompile.h>
+#else
+# define RT_FLEXIBLE_ARRAY
+# define RT_FLEXIBLE_ARRAY_EXTENSION
+# define AssertCompile(expr)
+# define AssertCompileSize(type, size)
+# define AssertCompileMemberOffset(type, member, off)
+typedef unsigned char uint8_t;
+typedef unsigned __int32 uint32_t;
+typedef unsigned __int64 uint64_t;
+#endif
+
+
+/** Hyper-V partition ID. */
+typedef uint64_t HV_PARTITION_ID;
+/** Invalid Hyper-V partition ID. */
+#define HV_PARTITION_ID_INVALID UINT64_C(0)
+/** Hyper-V virtual processor index (== VMCPUID). */
+typedef uint32_t HV_VP_INDEX;
+/** Guest physical address (== RTGCPHYS). */
+typedef uint64_t HV_GPA;
+/** Guest physical page number. */
+typedef uint64_t HV_GPA_PAGE_NUMBER;
+/** System(/parent) physical page number. */
+typedef uint64_t HV_SPA_PAGE_NUMBER;
+/** Hyper-V unsigned 128-bit integer type. */
+typedef struct { uint64_t Low64, High64; } HV_UINT128;
+/** Hyper-V port ID. */
+typedef union
+{
+ uint32_t AsUINT32;
+ struct
+ {
+ uint32_t Id : 24;
+ uint32_t Reserved : 8;
+ };
+} HV_PORT_ID;
+/** Pointer to a Hyper-V port ID. */
+typedef HV_PORT_ID *PHV_PORT_ID;
+
+
+/**
+ * Hypercall IDs.
+ */
+typedef enum
+{
+ HvCallReserved0000 = 0,
+
+ HvCallSwitchVirtualAddressSpace,
+ HvCallFlushVirtualAddressSpace,
+ HvCallFlushVirtualAddressList,
+ HvCallGetLogicalProcessorRunTime,
+ /* 5, 6 & 7 are deprecated / reserved. */
+ HvCallNotifyLongSpinWait = 8,
+ HvCallParkLogicalProcessors, /**< @since v2 */
+ HvCallInvokeHypervisorDebugger, /**< @since v2 - not mentioned in TLFS v5.0b */
+ HvCallSendSyntheticClusterIpi, /**< @since v? */
+ HvCallModifyVtlProtectionMask, /**< @since v? */
+ HvCallEnablePartitionVtl, /**< @since v? */
+ HvCallDisablePartitionVtl, /**< @since v? */
+ HvCallEnableVpVtl, /**< @since v? */
+ HvCallDisableVpVtl, /**< @since v? */
+ HvCallVtlCall, /**< @since v? */
+ HvCallVtlReturn, /**< @since v? */
+ HvCallFlushVirtualAddressSpaceEx, /**< @since v? */
+ HvCallFlushVirtualAddressListEx, /**< @since v? */
+ HvCallSendSyntheticClusterIpiEx, /**< @since v? */
+ /* Reserved: 0x16..0x3f */
+
+ HvCallCreatePartition = 0x40,
+ HvCallInitializePartition,
+ HvCallFinalizePartition,
+ HvCallDeletePartition,
+ HvCallGetPartitionProperty,
+ HvCallSetPartitionProperty,
+ HvCallGetPartitionId,
+ HvCallGetNextChildPartition,
+ HvCallDepositMemory, /**< 0x48 - Repeat call. */
+ HvCallWithdrawMemory, /**< 0x49 - Repeat call. */
+ HvCallGetMemoryBalance,
+ HvCallMapGpaPages, /**< 0X4b - Repeat call. */
+ HvCallUnmapGpaPages, /**< 0X4c - Repeat call. */
+ HvCallInstallIntercept,
+ HvCallCreateVp,
+ HvCallDeleteVp, /**< 0x4f - Fast call. */
+ HvCallGetVpRegisters, /**< 0x50 - Repeat call. */
+ HvCallSetVpRegisters, /**< 0x51 - Repeat call. */
+ HvCallTranslateVirtualAddress,
+ HvCallReadGpa,
+ HvCallWriteGpa,
+ HvCallAssertVirtualInterruptV1,
+ HvCallClearVirtualInterrupt, /**< 0x56 - Fast call. */
+ HvCallCreatePortV1,
+ HvCallDeletePort, /**< 0x58 - Fast call. */
+ HvCallConnectPortV1,
+ HvCallGetPortProperty,
+ HvCallDisconnectPort,
+ HvCallPostMessage,
+ HvCallSignalEvent,
+ HvCallSavePartitionState,
+ HvCallRestorePartitionState,
+ HvCallInitializeEventLogBufferGroup,
+ HvCallFinalizeEventLogBufferGroup,
+ HvCallCreateEventLogBuffer,
+ HvCallDeleteEventLogBuffer,
+ HvCallMapEventLogBuffer,
+ HvCallUnmapEventLogBuffer,
+ HvCallSetEventLogGroupSources,
+ HvCallReleaseEventLogBuffer,
+ HvCallFlushEventLogBuffer,
+ HvCallPostDebugData,
+ HvCallRetrieveDebugData,
+ HvCallResetDebugSession,
+ HvCallMapStatsPage,
+ HvCallUnmapStatsPage,
+ HvCallMapSparseGpaPages, /**< @since v2 */
+ HvCallSetSystemProperty, /**< @since v2 */
+ HvCallSetPortProperty, /**< @since v2 */
+ /* 0x71..0x75 reserved/deprecated (was v2 test IDs). */
+ HvCallAddLogicalProcessor = 0x76,
+ HvCallRemoveLogicalProcessor,
+ HvCallQueryNumaDistance,
+ HvCallSetLogicalProcessorProperty,
+ HvCallGetLogicalProcessorProperty,
+ HvCallGetSystemProperty,
+ HvCallMapDeviceInterrupt,
+ HvCallUnmapDeviceInterrupt,
+ HvCallRetargetDeviceInterrupt,
+ /* 0x7f is reserved. */
+ HvCallMapDevicePages = 0x80,
+ HvCallUnmapDevicePages,
+ HvCallAttachDevice,
+ HvCallDetachDevice,
+ HvCallNotifyStandbyTransition,
+ HvCallPrepareForSleep,
+ HvCallPrepareForHibernate,
+ HvCallNotifyPartitionEvent,
+ HvCallGetLogicalProcessorRegisters,
+ HvCallSetLogicalProcessorRegisters,
+ HvCallQueryAssociatedLpsforMca,
+ HvCallNotifyRingEmpty,
+ HvCallInjectSyntheticMachineCheck,
+ HvCallScrubPartition,
+ HvCallCollectLivedump,
+ HvCallDisableHypervisor,
+ HvCallModifySparseGpaPages,
+ HvCallRegisterInterceptResult,
+ HvCallUnregisterInterceptResult,
+ /* 0x93 is reserved/undocumented. */
+ HvCallAssertVirtualInterrupt = 0x94,
+ HvCallCreatePort,
+ HvCallConnectPort,
+ HvCallGetSpaPageList,
+ /* 0x98 is reserved. */
+ HvCallStartVirtualProcessor = 0x99,
+ HvCallGetVpIndexFromApicId,
+ /* 0x9b..0xae are reserved/undocumented.
+ 0xad: New version of HvCallGetVpRegisters? Perhaps on logical CPU or smth. */
+ HvCallFlushGuestPhysicalAddressSpace = 0xaf,
+ HvCallFlushGuestPhysicalAddressList,
+ /* 0xb1..0xb4 are unknown */
+ HvCallCreateCpuGroup = 0xb5,
+ HvCallDeleteCpuGroup,
+ HvCallGetCpuGroupProperty,
+ HvCallSetCpuGroupProperty,
+ HvCallGetCpuGroupAffinit,
+ HvCallGetNextCpuGroup = 0xba,
+ HvCallGetNextCpuGroupPartition,
+ HvCallPrecommitGpaPages = 0xbe,
+ HvCallUncommitGpaPages, /**< Happens when VidDestroyGpaRangeCheckSecure/WHvUnmapGpaRange is called. */
+ /* 0xc0 is unknown */
+ HvCallVpRunloopRelated = 0xc2, /**< Fast */
+ /* 0xc3..0xcb are unknown */
+ HvCallQueryVtlProtectionMaskRange = 0xcc,
+ HvCallModifyVtlProtectionMaskRange,
+ /* 0xce..0xd1 are unknown */
+ HvCallAcquireSparseGpaPageHostAccess = 0xd2,
+ HvCallReleaseSparseGpaPageHostAccess,
+ HvCallCheckSparseGpaPageVtlAccess,
+ HvCallAcquireSparseSpaPageHostAccess = 0xd7,
+ HvCallReleaseSparseSpaPageHostAccess,
+ HvCallAcceptGpaPages, /**< 0x18 byte input, zero rep, no output. */
+ /* 0xda..0xe0 are unknown (not dug out yet) */
+ HvCallMapVpRegisterPage = 0xe1, /**< Takes partition id + VP index (16 bytes). Returns a physical address (8 bytes). */
+ HvCallUnmapVpRegisterPage, /**< Takes partition id + VP index. */
+ HvCallUnknownE3,
+ HvCallUnknownE4,
+ HvCallUnknownE5,
+ HvCallUnknownE6,
+ /** Number of defined hypercalls (varies with version). */
+ HvCallCount
+} HV_CALL_CODE;
+AssertCompile(HvCallSendSyntheticClusterIpiEx == 0x15);
+AssertCompile(HvCallMapGpaPages == 0x4b);
+AssertCompile(HvCallSetPortProperty == 0x70);
+AssertCompile(HvCallRetargetDeviceInterrupt == 0x7e);
+AssertCompile(HvCallUnregisterInterceptResult == 0x92);
+AssertCompile(HvCallGetSpaPageList == 0x97);
+AssertCompile(HvCallFlushGuestPhysicalAddressList == 0xb0);
+AssertCompile(HvCallUncommitGpaPages == 0xbf);
+AssertCompile(HvCallCount == 0xe7);
+
+/** Makes the first parameter to a hypercall (rcx). */
+#define HV_MAKE_CALL_INFO(a_enmCallCode, a_cReps) ( (uint64_t)(a_enmCallCode) | ((uint64_t)(a_cReps) << 32) )
+/** Makes the return value (success) for a rep hypercall. */
+#define HV_MAKE_CALL_REP_RET(a_cReps) ((uint64_t)(a_cReps) << 32)
+
+/** Hypercall status code. */
+typedef uint16_t HV_STATUS;
+
+/** @name Hyper-V Hypercall status codes
+ * @{ */
+#define HV_STATUS_SUCCESS (0x0000)
+#define HV_STATUS_RESERVED_1 (0x0001)
+#define HV_STATUS_INVALID_HYPERCALL_CODE (0x0002)
+#define HV_STATUS_INVALID_HYPERCALL_INPUT (0x0003)
+#define HV_STATUS_INVALID_ALIGNMENT (0x0004)
+#define HV_STATUS_INVALID_PARAMETER (0x0005)
+#define HV_STATUS_ACCESS_DENIED (0x0006)
+#define HV_STATUS_INVALID_PARTITION_STATE (0x0007)
+#define HV_STATUS_OPERATION_DENIED (0x0008)
+#define HV_STATUS_UNKNOWN_PROPERTY (0x0009)
+#define HV_STATUS_PROPERTY_VALUE_OUT_OF_RANGE (0x000a)
+#define HV_STATUS_INSUFFICIENT_MEMORY (0x000b)
+#define HV_STATUS_PARTITION_TOO_DEEP (0x000c)
+#define HV_STATUS_INVALID_PARTITION_ID (0x000d)
+#define HV_STATUS_INVALID_VP_INDEX (0x000e)
+#define HV_STATUS_RESERVED_F (0x000f)
+#define HV_STATUS_NOT_FOUND (0x0010)
+#define HV_STATUS_INVALID_PORT_ID (0x0011)
+#define HV_STATUS_INVALID_CONNECTION_ID (0x0012)
+#define HV_STATUS_INSUFFICIENT_BUFFERS (0x0013)
+#define HV_STATUS_NOT_ACKNOWLEDGED (0x0014)
+#define HV_STATUS_INVALID_VP_STATE (0x0015)
+#define HV_STATUS_ACKNOWLEDGED (0x0016)
+#define HV_STATUS_INVALID_SAVE_RESTORE_STATE (0x0017)
+#define HV_STATUS_INVALID_SYNIC_STATE (0x0018)
+#define HV_STATUS_OBJECT_IN_USE (0x0019)
+#define HV_STATUS_INVALID_PROXIMITY_DOMAIN_INFO (0x001a)
+#define HV_STATUS_NO_DATA (0x001b)
+#define HV_STATUS_INACTIVE (0x001c)
+#define HV_STATUS_NO_RESOURCES (0x001d)
+#define HV_STATUS_FEATURE_UNAVAILABLE (0x001e)
+#define HV_STATUS_PARTIAL_PACKET (0x001f)
+#define HV_STATUS_PROCESSOR_FEATURE_SSE3_NOT_SUPPORTED (0x0020)
+#define HV_STATUS_PROCESSOR_FEATURE_LAHFSAHF_NOT_SUPPORTED (0x0021)
+#define HV_STATUS_PROCESSOR_FEATURE_SSSE3_NOT_SUPPORTED (0x0022)
+#define HV_STATUS_PROCESSOR_FEATURE_SSE4_1_NOT_SUPPORTED (0x0023)
+#define HV_STATUS_PROCESSOR_FEATURE_SSE4_2_NOT_SUPPORTED (0x0024)
+#define HV_STATUS_PROCESSOR_FEATURE_SSE4A_NOT_SUPPORTED (0x0025)
+#define HV_STATUS_PROCESSOR_FEATURE_XOP_NOT_SUPPORTED (0x0026)
+#define HV_STATUS_PROCESSOR_FEATURE_POPCNT_NOT_SUPPORTED (0x0027)
+#define HV_STATUS_PROCESSOR_FEATURE_CMPXCHG16B_NOT_SUPPORTED (0x0028)
+#define HV_STATUS_PROCESSOR_FEATURE_ALTMOVCR8_NOT_SUPPORTED (0x0029)
+#define HV_STATUS_PROCESSOR_FEATURE_LZCNT_NOT_SUPPORTED (0x002a)
+#define HV_STATUS_PROCESSOR_FEATURE_MISALIGNED_SSE_NOT_SUPPORTED (0x002b)
+#define HV_STATUS_PROCESSOR_FEATURE_MMX_EXT_NOT_SUPPORTED (0x002c)
+#define HV_STATUS_PROCESSOR_FEATURE_3DNOW_NOT_SUPPORTED (0x002d)
+#define HV_STATUS_PROCESSOR_FEATURE_EXTENDED_3DNOW_NOT_SUPPORTED (0x002e)
+#define HV_STATUS_PROCESSOR_FEATURE_PAGE_1GB_NOT_SUPPORTED (0x002f)
+#define HV_STATUS_PROCESSOR_CACHE_LINE_FLUSH_SIZE_INCOMPATIBLE (0x0030)
+#define HV_STATUS_PROCESSOR_FEATURE_XSAVE_NOT_SUPPORTED (0x0031)
+#define HV_STATUS_PROCESSOR_FEATURE_XSAVEOPT_NOT_SUPPORTED (0x0032)
+#define HV_STATUS_INSUFFICIENT_BUFFER (0x0033)
+#define HV_STATUS_PROCESSOR_FEATURE_XSAVE_AVX_NOT_SUPPORTED (0x0034)
+#define HV_STATUS_PROCESSOR_FEATURE_XSAVE_ FEATURE_NOT_SUPPORTED (0x0035)
+#define HV_STATUS_PROCESSOR_XSAVE_SAVE_AREA_INCOMPATIBLE (0x0036)
+#define HV_STATUS_INCOMPATIBLE_PROCESSOR (0x0037)
+#define HV_STATUS_INSUFFICIENT_DEVICE_DOMAINS (0x0038)
+#define HV_STATUS_PROCESSOR_FEATURE_AES_NOT_SUPPORTED (0x0039)
+#define HV_STATUS_PROCESSOR_FEATURE_PCLMULQDQ_NOT_SUPPORTED (0x003a)
+#define HV_STATUS_PROCESSOR_FEATURE_INCOMPATIBLE_XSAVE_FEATURES (0x003b)
+#define HV_STATUS_CPUID_FEATURE_VALIDATION_ERROR (0x003c)
+#define HV_STATUS_CPUID_XSAVE_FEATURE_VALIDATION_ERROR (0x003d)
+#define HV_STATUS_PROCESSOR_STARTUP_TIMEOUT (0x003e)
+#define HV_STATUS_SMX_ENABLED (0x003f)
+#define HV_STATUS_PROCESSOR_FEATURE_PCID_NOT_SUPPORTED (0x0040)
+#define HV_STATUS_INVALID_LP_INDEX (0x0041)
+#define HV_STATUS_FEATURE_FMA4_NOT_SUPPORTED (0x0042)
+#define HV_STATUS_FEATURE_F16C_NOT_SUPPORTED (0x0043)
+#define HV_STATUS_PROCESSOR_FEATURE_RDRAND_NOT_SUPPORTED (0x0044)
+#define HV_STATUS_PROCESSOR_FEATURE_RDWRFSGS_NOT_SUPPORTED (0x0045)
+#define HV_STATUS_PROCESSOR_FEATURE_SMEP_NOT_SUPPORTED (0x0046)
+#define HV_STATUS_PROCESSOR_FEATURE_ENHANCED_FAST_STRING_NOT_SUPPORTED (0x0047)
+#define HV_STATUS_PROCESSOR_FEATURE_MOVBE_NOT_SUPPORTED (0x0048)
+#define HV_STATUS_PROCESSOR_FEATURE_BMI1_NOT_SUPPORTED (0x0049)
+#define HV_STATUS_PROCESSOR_FEATURE_BMI2_NOT_SUPPORTED (0x004a)
+#define HV_STATUS_PROCESSOR_FEATURE_HLE_NOT_SUPPORTED (0x004b)
+#define HV_STATUS_PROCESSOR_FEATURE_RTM_NOT_SUPPORTED (0x004c)
+#define HV_STATUS_PROCESSOR_FEATURE_XSAVE_FMA_NOT_SUPPORTED (0x004d)
+#define HV_STATUS_PROCESSOR_FEATURE_XSAVE_AVX2_NOT_SUPPORTED (0x004e)
+#define HV_STATUS_PROCESSOR_FEATURE_NPIEP1_NOT_SUPPORTED (0x004f)
+#define HV_STATUS_INVALID_REGISTER_VALUE (0x0050)
+#define HV_STATUS_PROCESSOR_FEATURE_RDSEED_NOT_SUPPORTED (0x0052)
+#define HV_STATUS_PROCESSOR_FEATURE_ADX_NOT_SUPPORTED (0x0053)
+#define HV_STATUS_PROCESSOR_FEATURE_SMAP_NOT_SUPPORTED (0x0054)
+#define HV_STATUS_NX_NOT_DETECTED (0x0055)
+#define HV_STATUS_PROCESSOR_FEATURE_INTEL_PREFETCH_NOT_SUPPORTED (0x0056)
+#define HV_STATUS_INVALID_DEVICE_ID (0x0057)
+#define HV_STATUS_INVALID_DEVICE_STATE (0x0058)
+#define HV_STATUS_PENDING_PAGE_REQUESTS (0x0059)
+#define HV_STATUS_PAGE_REQUEST_INVALID (0x0060)
+#define HV_STATUS_OPERATION_FAILED (0x0071)
+#define HV_STATUS_NOT_ALLOWED_WITH_NESTED_VIRT_ACTIVE (0x0072)
+/** @} */
+
+
+/** Hyper-V partition property value. */
+typedef uint64_t HV_PARTITION_PROPERTY;
+/** Pointer to a partition property value. */
+typedef HV_PARTITION_PROPERTY *PHV_PARTITION_PROPERTY;
+/**
+ * Hyper-V partition property code.
+ * This is documented in TLFS, except version 5.x.
+ */
+typedef enum
+{
+ HvPartitionPropertyPrivilegeFlags = 0x00010000,
+ HvPartitionPropertySyntheticProcessorFeaturesBanks, /**< Read by WHvApi::Capabilities::GetSyntheticProcessorFeaturesBanks (build 22000) */
+
+ HvPartitionPropertyCpuReserve = 0x00020001,
+ HvPartitionPropertyCpuCap,
+ HvPartitionPropertyCpuWeight,
+ HvPartitionPropertyUnknown20004, /**< On exo partition (build 17134), initial value zero. */
+
+ HvPartitionPropertyEmulatedTimerPeriod = 0x00030000, /**< @note Fails on exo partition (build 17134). */
+ HvPartitionPropertyEmulatedTimerControl, /**< @note Fails on exo partition (build 17134). */
+ HvPartitionPropertyPmTimerAssist, /**< @note Fails on exo partition (build 17134). */
+ HvPartitionPropertyUnknown30003, /**< @note WHvSetupPartition writes this (build 22000). */
+ HvPartitionPropertyUnknown30004, /**< ? */
+ HvPartitionPropertyUnknown30005, /**< WHvPartitionPropertyCodeReferenceTime maps to this (build 22000) */
+
+ HvPartitionPropertyDebugChannelId = 0x00040000, /**< @note Hangs system on exo partition hangs (build 17134). */
+
+ HvPartitionPropertyVirtualTlbPageCount = 0x00050000,
+ HvPartitionPropertyUnknown50001, /**< On exo partition (build 17134), initial value zero. */
+ HvPartitionPropertyUnknown50002, /**< On exo partition (build 17134), initial value zero. */
+ HvPartitionPropertyUnknown50003, /**< On exo partition (build 17134), initial value zero. */
+ HvPartitionPropertyUnknown50004, /**< On exo partition (build 17134), initial value zero. */
+ HvPartitionPropertyUnknown50005, /**< On exo partition (build 17134), initial value one. */
+ HvPartitionPropertyUnknown50006, /**< On exo partition (build 17134), initial value zero.
+ * @note build 22000/w11-ga fends this off in VID.SYS. */
+ HvPartitionPropertyUnknown50007,
+ HvPartitionPropertyUnknown50008,
+ HvPartitionPropertyUnknown50009,
+ HvPartitionPropertyUnknown5000a,
+ HvPartitionPropertyUnknown5000b,
+ HvPartitionPropertyUnknown5000c,
+ HvPartitionPropertyUnknown5000d,
+ HvPartitionPropertyUnknown5000e,
+ HvPartitionPropertyUnknown5000f,
+ HvPartitionPropertyUnknown50010,
+ HvPartitionPropertyUnknown50012,
+ HvPartitionPropertyUnknown50013, /**< Set by WHvSetupPartition (build 22000) */
+ HvPartitionPropertyUnknown50014,
+ HvPartitionPropertyUnknown50015,
+ HvPartitionPropertyUnknown50016,
+ HvPartitionPropertyUnknown50017, /**< Set by WHvSetupPartition (build 22000) */
+
+ HvPartitionPropertyProcessorVendor = 0x00060000,
+ HvPartitionPropertyProcessorFeatures, /**< On exo/17134/threadripper: 0x6cb26f39fbf */
+ HvPartitionPropertyProcessorXsaveFeatures,
+ HvPartitionPropertyProcessorCLFlushSize, /**< On exo/17134/threadripper: 8 */
+ HvPartitionPropertyUnknown60004, /**< On exo partition (build 17134), initial value zero. */
+ HvPartitionPropertyUnknown60005, /**< On exo partition (build 17134), initial value 0x603. */
+ HvPartitionPropertyUnknown60006, /**< On exo partition (build 17134), initial value 0x2c. */
+ HvPartitionPropertyUnknown60007, /**< WHvSetupPartition reads this (build 22000). */
+ HvPartitionPropertyUnknown60008, /**< WHvSetupPartition reads this (build 22000). */
+ HvPartitionPropertyProcessorClockFrequency, /**< Read by WHvApi::Capabilities::GetProcessorClockFrequency (build 22000). */
+ HvPartitionPropertyProcessorFeaturesBank0, /**< Read by WHvApi::Capabilities::GetProcessorFeaturesBanks (build 22000). */
+ HvPartitionPropertyProcessorFeaturesBank1, /**< Read by WHvApi::Capabilities::GetProcessorFeaturesBanks (build 22000). */
+
+ HvPartitionPropertyGuestOsId = 0x00070000, /**< @since v4 */
+
+ HvPartitionPropertyUnknown800000 = 0x00080000 /**< On exo partition (build 17134), initial value zero. */
+} HV_PARTITION_PROPERTY_CODE;
+AssertCompileSize(HV_PARTITION_PROPERTY_CODE, 4);
+/** Pointer to a partition property code. */
+typedef HV_PARTITION_PROPERTY_CODE *PHV_PARTITION_PROPERTY_CODE;
+
+
+/** Input for HvCallGetPartitionProperty. */
+typedef struct
+{
+ HV_PARTITION_ID PartitionId;
+ HV_PARTITION_PROPERTY_CODE PropertyCode;
+ uint32_t uPadding;
+} HV_INPUT_GET_PARTITION_PROPERTY;
+AssertCompileSize(HV_INPUT_GET_PARTITION_PROPERTY, 16);
+/** Pointer to input for HvCallGetPartitionProperty. */
+typedef HV_INPUT_GET_PARTITION_PROPERTY *PHV_INPUT_GET_PARTITION_PROPERTY;
+
+/** Output for HvCallGetPartitionProperty. */
+typedef struct
+{
+ HV_PARTITION_PROPERTY PropertyValue;
+} HV_OUTPUT_GET_PARTITION_PROPERTY;
+/** Pointer to output for HvCallGetPartitionProperty. */
+typedef HV_OUTPUT_GET_PARTITION_PROPERTY *PHV_OUTPUT_GET_PARTITION_PROPERTY;
+
+
+/** Input for HvCallSetPartitionProperty. */
+typedef struct
+{
+ HV_PARTITION_ID PartitionId;
+ HV_PARTITION_PROPERTY_CODE PropertyCode;
+ uint32_t uPadding;
+ HV_PARTITION_PROPERTY PropertyValue;
+} HV_INPUT_SET_PARTITION_PROPERTY;
+AssertCompileSize(HV_INPUT_SET_PARTITION_PROPERTY, 24);
+/** Pointer to input for HvCallSetPartitionProperty. */
+typedef HV_INPUT_SET_PARTITION_PROPERTY *PHV_INPUT_SET_PARTITION_PROPERTY;
+
+
+/** Hyper-V NUMA node ID.
+ * On systems without NUMA, i.e. a single node, it uses 0 as identifier. */
+typedef uint32_t HV_PROXIMITY_DOMAIN_ID;
+/** Pointer to NUMA node ID. */
+typedef HV_PROXIMITY_DOMAIN_ID *PHV_PROXIMITY_DOMAIN_ID;
+
+/** Hyper-V NUMA flags. */
+typedef struct
+{
+ uint32_t ProximityPreferred : 1; /**< When set, allocations may come from other NUMA nodes. */
+ uint32_t Reserved : 30; /**< Reserved for future (as of circa v2). */
+ uint32_t ProxyimityInfoValid : 1; /**< Set if the NUMA information is valid. */
+} HV_PROXIMITY_DOMAIN_FLAGS;
+/** Pointer to Hyper-V NUMA flags. */
+typedef HV_PROXIMITY_DOMAIN_FLAGS *PHV_PROXIMITY_DOMAIN_FLAGS;
+
+/** Hyper-V NUMA information. */
+typedef struct
+{
+ HV_PROXIMITY_DOMAIN_ID Id; /**< NUMA node identifier. */
+ HV_PROXIMITY_DOMAIN_FLAGS Flags; /**< NUMA flags. */
+} HV_PROXIMITY_DOMAIN_INFO;
+/** Pointer to Hyper-V NUMA information. */
+typedef HV_PROXIMITY_DOMAIN_INFO *PHV_PROXIMITY_DOMAIN_INFO;
+
+/** Input for HvCallGetMemoryBalance. */
+typedef struct
+{
+ HV_PARTITION_ID TargetPartitionId;
+ HV_PROXIMITY_DOMAIN_INFO ProximityDomainInfo;
+} HV_INPUT_GET_MEMORY_BALANCE;
+AssertCompileSize(HV_INPUT_GET_MEMORY_BALANCE, 16);
+/** Pointer to the input for HvCallGetMemoryBalance. */
+typedef HV_INPUT_GET_MEMORY_BALANCE *PHV_INPUT_GET_MEMORY_BALANCE;
+
+/** Output for HvCallGetMemoryBalance. */
+typedef struct
+{
+ uint64_t PagesAvailable;
+ uint64_t PagesInUse;
+} HV_OUTPUT_GET_MEMORY_BALANCE;
+/** Pointer to the output for HvCallGetMemoryBalance. */
+typedef HV_OUTPUT_GET_MEMORY_BALANCE *PHV_OUTPUT_GET_MEMORY_BALANCE;
+
+
+/** @name Flags used with HvCallMapGpaPages and HvCallMapSparseGpaPages.
+ * @note There seems to be a more flags defined after v2.
+ * @{ */
+typedef uint32_t HV_MAP_GPA_FLAGS;
+#define HV_MAP_GPA_READABLE UINT32_C(0x0001)
+#define HV_MAP_GPA_WRITABLE UINT32_C(0x0002)
+#define HV_MAP_GPA_EXECUTABLE UINT32_C(0x0004)
+/** Seems this have to be set when HV_MAP_GPA_EXECUTABLE is (17101). */
+#define HV_MAP_GPA_EXECUTABLE_AGAIN UINT32_C(0x0008)
+/** Dunno what this is yet, but it requires HV_MAP_GPA_DUNNO_1000.
+ * The readable bit gets put here when both HV_MAP_GPA_DUNNO_1000 and
+ * HV_MAP_GPA_DUNNO_MASK_0700 are clear. */
+#define HV_MAP_GPA_DUNNO_ACCESS UINT32_C(0x0010)
+/** Guess work. */
+#define HV_MAP_GPA_MAYBE_ACCESS_MASK UINT32_C(0x001f)
+/** Some kind of mask. */
+#define HV_MAP_GPA_DUNNO_MASK_0700 UINT32_C(0x0700)
+/** Dunno what this is, but required for HV_MAP_GPA_DUNNO_ACCESS. */
+#define HV_MAP_GPA_DUNNO_1000 UINT32_C(0x1000)
+/** Working with large 2MB pages. */
+#define HV_MAP_GPA_LARGE UINT32_C(0x2000)
+/** Valid mask as per build 17101. */
+#define HV_MAP_GPA_VALID_MASK UINT32_C(0x7f1f)
+/** @} */
+
+/** Input for HvCallMapGpaPages. */
+typedef struct
+{
+ HV_PARTITION_ID TargetPartitionId;
+ HV_GPA_PAGE_NUMBER TargetGpaBase;
+ HV_MAP_GPA_FLAGS MapFlags;
+ uint32_t u32ExplicitPadding;
+ /* The repeating part: */
+ RT_FLEXIBLE_ARRAY_EXTENSION
+ HV_SPA_PAGE_NUMBER PageList[RT_FLEXIBLE_ARRAY];
+} HV_INPUT_MAP_GPA_PAGES;
+AssertCompileMemberOffset(HV_INPUT_MAP_GPA_PAGES, PageList, 24);
+/** Pointer to the input for HvCallMapGpaPages. */
+typedef HV_INPUT_MAP_GPA_PAGES *PHV_INPUT_MAP_GPA_PAGES;
+
+
+/** A parent to guest mapping pair for HvCallMapSparseGpaPages. */
+typedef struct
+{
+ HV_GPA_PAGE_NUMBER TargetGpaPageNumber;
+ HV_SPA_PAGE_NUMBER SourceSpaPageNumber;
+} HV_GPA_MAPPING;
+/** Pointer to a parent->guest mapping pair for HvCallMapSparseGpaPages. */
+typedef HV_GPA_MAPPING *PHV_GPA_MAPPING;
+
+/** Input for HvCallMapSparseGpaPages. */
+typedef struct
+{
+ HV_PARTITION_ID TargetPartitionId;
+ HV_MAP_GPA_FLAGS MapFlags;
+ uint32_t u32ExplicitPadding;
+ /* The repeating part: */
+ RT_FLEXIBLE_ARRAY_EXTENSION
+ HV_GPA_MAPPING PageList[RT_FLEXIBLE_ARRAY];
+} HV_INPUT_MAP_SPARSE_GPA_PAGES;
+AssertCompileMemberOffset(HV_INPUT_MAP_SPARSE_GPA_PAGES, PageList, 16);
+/** Pointer to the input for HvCallMapSparseGpaPages. */
+typedef HV_INPUT_MAP_SPARSE_GPA_PAGES *PHV_INPUT_MAP_SPARSE_GPA_PAGES;
+
+
+/** Input for HvCallUnmapGpaPages. */
+typedef struct
+{
+ HV_PARTITION_ID TargetPartitionId;
+ HV_GPA_PAGE_NUMBER TargetGpaBase;
+ /** This field is either an omission in the 7600 WDK or a later additions.
+ * Anyway, not quite sure what it does. Bit 2 seems to indicate 2MB pages. */
+ uint64_t fFlags;
+} HV_INPUT_UNMAP_GPA_PAGES;
+AssertCompileSize(HV_INPUT_UNMAP_GPA_PAGES, 24);
+/** Pointer to the input for HvCallUnmapGpaPages. */
+typedef HV_INPUT_UNMAP_GPA_PAGES *PHV_INPUT_UNMAP_GPA_PAGES;
+
+
+
+/** Cache types used by HvCallReadGpa and HvCallWriteGpa. */
+typedef enum
+{
+ HvCacheTypeX64Uncached = 0,
+ HvCacheTypeX64WriteCombining,
+ /* 2 & 3 are undefined. */
+ HvCacheTypeX64WriteThrough = 4,
+ HvCacheTypeX64WriteProtected,
+ HvCacheTypeX64WriteBack
+} HV_CACHE_TYPE;
+
+/** Control flags for HvCallReadGpa and HvCallWriteGpa. */
+typedef union
+{
+ uint64_t AsUINT64;
+ struct
+ {
+ uint64_t CacheType : 8; /**< HV_CACHE_TYPE */
+#ifndef IN_IDA_PRO
+ uint64_t Reserved : 56;
+#endif
+ };
+} HV_ACCESS_GPA_CONTROL_FLAGS;
+
+/** Results codes for HvCallReadGpa and HvCallWriteGpa. */
+typedef enum
+{
+ HvAccessGpaSuccess = 0,
+ HvAccessGpaUnmapped,
+ HvAccessGpaReadIntercept,
+ HvAccessGpaWriteIntercept,
+ HvAccessGpaIllegalOverlayAccess
+} HV_ACCESS_GPA_RESULT_CODE;
+
+/** The result of HvCallReadGpa and HvCallWriteGpa. */
+typedef union
+{
+ uint64_t AsUINT64;
+ struct
+ {
+ HV_ACCESS_GPA_RESULT_CODE ResultCode;
+ uint32_t Reserved;
+ };
+} HV_ACCESS_GPA_RESULT;
+
+
+/** Input for HvCallReadGpa. */
+typedef struct
+{
+ HV_PARTITION_ID PartitionId;
+ HV_VP_INDEX VpIndex;
+ uint32_t ByteCount;
+ HV_GPA BaseGpa;
+ HV_ACCESS_GPA_CONTROL_FLAGS ControlFlags;
+} HV_INPUT_READ_GPA;
+AssertCompileSize(HV_INPUT_READ_GPA, 32);
+/** Pointer to the input for HvCallReadGpa. */
+typedef HV_INPUT_READ_GPA *PHV_INPUT_READ_GPA;
+
+/** Output for HvCallReadGpa. */
+typedef struct
+{
+ HV_ACCESS_GPA_RESULT AccessResult;
+ uint8_t Data[16];
+} HV_OUTPUT_READ_GPA;
+AssertCompileSize(HV_OUTPUT_READ_GPA, 24);
+/** Pointer to the output for HvCallReadGpa. */
+typedef HV_OUTPUT_READ_GPA *PHV_OUTPUT_READ_GPA;
+
+
+/** Input for HvCallWriteGpa. */
+typedef struct
+{
+ HV_PARTITION_ID PartitionId;
+ HV_VP_INDEX VpIndex;
+ uint32_t ByteCount;
+ HV_GPA BaseGpa;
+ HV_ACCESS_GPA_CONTROL_FLAGS ControlFlags;
+ uint8_t Data[16];
+} HV_INPUT_WRITE_GPA;
+AssertCompileSize(HV_INPUT_READ_GPA, 32);
+/** Pointer to the input for HvCallWriteGpa. */
+typedef HV_INPUT_READ_GPA *PHV_INPUT_READ_GPA;
+
+/** Output for HvCallWriteGpa. */
+typedef struct
+{
+ HV_ACCESS_GPA_RESULT AccessResult;
+} HV_OUTPUT_WRITE_GPA;
+AssertCompileSize(HV_OUTPUT_WRITE_GPA, 8);
+/** Pointer to the output for HvCallWriteGpa. */
+typedef HV_OUTPUT_WRITE_GPA *PHV_OUTPUT_WRITE_GPA;
+
+
+/**
+ * Register names used by HvCallGetVpRegisters and HvCallSetVpRegisters.
+ */
+typedef enum _HV_REGISTER_NAME
+{
+ HvRegisterExplicitSuspend = 0x00000000,
+ HvRegisterInterceptSuspend,
+ HvRegisterUnknown02, /**< Reads as 0 initially on exo part. */
+ HvRegisterUnknown03, /**< Reads as 0 initially on exo part. */
+ HvRegisterInternalActivityState, /**< @since about build 17758 */
+
+ HvRegisterHypervisorVersion = 0x00000100, /**< @since v5 @note Not readable on exo part. */
+
+ HvRegisterPrivilegesAndFeaturesInfo = 0x00000200, /**< @since v5 @note Not readable on exo part. */
+ HvRegisterFeaturesInfo, /**< @since v5 @note Not readable on exo part. */
+ HvRegisterImplementationLimitsInfo, /**< @since v5 @note Not readable on exo part. */
+ HvRegisterHardwareFeaturesInfo, /**< @since v5 @note Not readable on exo part. */
+
+ HvRegisterGuestCrashP0 = 0x00000210, /**< @since v5 @note Not readable on exo part. */
+ HvRegisterGuestCrashP1, /**< @since v5 @note Not readable on exo part. */
+ HvRegisterGuestCrashP2, /**< @since v5 @note Not readable on exo part. */
+ HvRegisterGuestCrashP3, /**< @since v5 @note Not readable on exo part. */
+ HvRegisterGuestCrashP4, /**< @since v5 @note Not readable on exo part. */
+ HvRegisterGuestCrashCtl, /**< @since v5 @note Not readable on exo part. */
+
+ HvRegisterPowerStateConfigC1 = 0x00000220, /**< @since v5 @note Not readable on exo part. */
+ HvRegisterPowerStateTriggerC1, /**< @since v5 @note Not readable on exo part. */
+ HvRegisterPowerStateConfigC2, /**< @since v5 @note Not readable on exo part. */
+ HvRegisterPowerStateTriggerC2, /**< @since v5 @note Not readable on exo part. */
+ HvRegisterPowerStateConfigC3, /**< @since v5 @note Not readable on exo part. */
+ HvRegisterPowerStateTriggerC3, /**< @since v5 @note Not readable on exo part. */
+
+ HvRegisterSystemReset = 0x00000230, /**< @since v5 @note Not readable on exo part. */
+
+ HvRegisterProcessorClockFrequency = 0x00000240, /**< @since v5 @note Not readable on exo part. */
+ HvRegisterInterruptClockFrequency, /**< @since v5 @note Not readable on exo part. */
+
+ HvRegisterGuestIdle = 0x00000250, /**< @since v5 @note Not readable on exo part. */
+
+ HvRegisterDebugDeviceOptions = 0x00000260, /**< @since v5 @note Not readable on exo part. */
+
+ HvRegisterPendingInterruption = 0x00010002,
+ HvRegisterInterruptState,
+ HvRegisterPendingEvent0, /**< @since v5 */
+ HvRegisterPendingEvent1, /**< @since v5 */
+ HvX64RegisterDeliverabilityNotifications, /**< @since v5c? Late 2017? */
+
+ HvX64RegisterRax = 0x00020000,
+ HvX64RegisterRcx,
+ HvX64RegisterRdx,
+ HvX64RegisterRbx,
+ HvX64RegisterRsp,
+ HvX64RegisterRbp,
+ HvX64RegisterRsi,
+ HvX64RegisterRdi,
+ HvX64RegisterR8,
+ HvX64RegisterR9,
+ HvX64RegisterR10,
+ HvX64RegisterR11,
+ HvX64RegisterR12,
+ HvX64RegisterR13,
+ HvX64RegisterR14,
+ HvX64RegisterR15,
+ HvX64RegisterRip,
+ HvX64RegisterRflags,
+
+ HvX64RegisterXmm0 = 0x00030000,
+ HvX64RegisterXmm1,
+ HvX64RegisterXmm2,
+ HvX64RegisterXmm3,
+ HvX64RegisterXmm4,
+ HvX64RegisterXmm5,
+ HvX64RegisterXmm6,
+ HvX64RegisterXmm7,
+ HvX64RegisterXmm8,
+ HvX64RegisterXmm9,
+ HvX64RegisterXmm10,
+ HvX64RegisterXmm11,
+ HvX64RegisterXmm12,
+ HvX64RegisterXmm13,
+ HvX64RegisterXmm14,
+ HvX64RegisterXmm15,
+ HvX64RegisterFpMmx0,
+ HvX64RegisterFpMmx1,
+ HvX64RegisterFpMmx2,
+ HvX64RegisterFpMmx3,
+ HvX64RegisterFpMmx4,
+ HvX64RegisterFpMmx5,
+ HvX64RegisterFpMmx6,
+ HvX64RegisterFpMmx7,
+ HvX64RegisterFpControlStatus,
+ HvX64RegisterXmmControlStatus,
+
+ HvX64RegisterCr0 = 0x00040000,
+ HvX64RegisterCr2,
+ HvX64RegisterCr3,
+ HvX64RegisterCr4,
+ HvX64RegisterCr8,
+ HvX64RegisterXfem,
+
+ HvX64RegisterIntermediateCr0 = 0x00041000, /**< @since v5 */
+ HvX64RegisterIntermediateCr4 = 0x00041003, /**< @since v5 */
+ HvX64RegisterIntermediateCr8, /**< @since v5 */
+
+ HvX64RegisterDr0 = 0x00050000,
+ HvX64RegisterDr1,
+ HvX64RegisterDr2,
+ HvX64RegisterDr3,
+ HvX64RegisterDr6,
+ HvX64RegisterDr7,
+
+ HvX64RegisterEs = 0x00060000,
+ HvX64RegisterCs,
+ HvX64RegisterSs,
+ HvX64RegisterDs,
+ HvX64RegisterFs,
+ HvX64RegisterGs,
+ HvX64RegisterLdtr,
+ HvX64RegisterTr,
+
+ HvX64RegisterIdtr = 0x00070000,
+ HvX64RegisterGdtr,
+
+ HvX64RegisterTsc = 0x00080000,
+ HvX64RegisterEfer,
+ HvX64RegisterKernelGsBase,
+ HvX64RegisterApicBase,
+ HvX64RegisterPat,
+ HvX64RegisterSysenterCs,
+ HvX64RegisterSysenterEip,
+ HvX64RegisterSysenterEsp,
+ HvX64RegisterStar,
+ HvX64RegisterLstar,
+ HvX64RegisterCstar,
+ HvX64RegisterSfmask,
+ HvX64RegisterInitialApicId,
+
+ HvX64RegisterMtrrCap, /**< Not readable in exo partitions? */
+ HvX64RegisterMtrrDefType,
+
+ HvX64RegisterMtrrPhysBase0 = 0x00080010,
+ HvX64RegisterMtrrPhysBase1,
+ HvX64RegisterMtrrPhysBase2,
+ HvX64RegisterMtrrPhysBase3,
+ HvX64RegisterMtrrPhysBase4,
+ HvX64RegisterMtrrPhysBase5,
+ HvX64RegisterMtrrPhysBase6,
+ HvX64RegisterMtrrPhysBase7,
+ HvX64RegisterMtrrPhysBase8, /**< @since v4 @note Appears not to be readable on exo partition (Threadripper). */
+ HvX64RegisterMtrrPhysBase9, /**< @since v4 @note Appears not to be readable on exo partition (Threadripper). */
+ HvX64RegisterMtrrPhysBaseA, /**< @since v4 @note Appears not to be readable on exo partition (Threadripper). */
+ HvX64RegisterMtrrPhysBaseB, /**< @since v4 @note Appears not to be readable on exo partition (Threadripper). */
+ HvX64RegisterMtrrPhysBaseC, /**< @since v4 @note Appears not to be readable on exo partition (Threadripper). */
+ HvX64RegisterMtrrPhysBaseD, /**< @since v4 @note Appears not to be readable on exo partition (Threadripper). */
+ HvX64RegisterMtrrPhysBaseE, /**< @since v4 @note Appears not to be readable on exo partition (Threadripper). */
+ HvX64RegisterMtrrPhysBaseF, /**< @since v4 @note Appears not to be readable on exo partition (Threadripper). */
+
+ HvX64RegisterMtrrPhysMask0 = 0x00080040,
+ HvX64RegisterMtrrPhysMask1,
+ HvX64RegisterMtrrPhysMask2,
+ HvX64RegisterMtrrPhysMask3,
+ HvX64RegisterMtrrPhysMask4,
+ HvX64RegisterMtrrPhysMask5,
+ HvX64RegisterMtrrPhysMask6,
+ HvX64RegisterMtrrPhysMask7,
+ HvX64RegisterMtrrPhysMask8, /**< @since v4 @note Appears not to be readable on exo partition (Threadripper). */
+ HvX64RegisterMtrrPhysMask9, /**< @since v4 @note Appears not to be readable on exo partition (Threadripper). */
+ HvX64RegisterMtrrPhysMaskA, /**< @since v4 @note Appears not to be readable on exo partition (Threadripper). */
+ HvX64RegisterMtrrPhysMaskB, /**< @since v4 @note Appears not to be readable on exo partition (Threadripper). */
+ HvX64RegisterMtrrPhysMaskC, /**< @since v4 @note Appears not to be readable on exo partition (Threadripper). */
+ HvX64RegisterMtrrPhysMaskD, /**< @since v4 @note Appears not to be readable on exo partition (Threadripper). */
+ HvX64RegisterMtrrPhysMaskE, /**< @since v4 @note Appears not to be readable on exo partition (Threadripper). */
+ HvX64RegisterMtrrPhysMaskF, /**< @since v4 @note Appears not to be readable on exo partition (Threadripper). */
+
+ HvX64RegisterMtrrFix64k00000 = 0x00080070,
+ HvX64RegisterMtrrFix16k80000,
+ HvX64RegisterMtrrFix16kA0000,
+ HvX64RegisterMtrrFix4kC0000,
+ HvX64RegisterMtrrFix4kC8000,
+ HvX64RegisterMtrrFix4kD0000,
+ HvX64RegisterMtrrFix4kD8000,
+ HvX64RegisterMtrrFix4kE0000,
+ HvX64RegisterMtrrFix4kE8000,
+ HvX64RegisterMtrrFix4kF0000,
+ HvX64RegisterMtrrFix4kF8000,
+ HvX64RegisterTscAux, /**< @since v5c? late 2017? */
+
+ HvX64RegisterUnknown8007d = 0x0008007d, /**< Readable on exo partition (17134), initial value is zero. */
+
+ HvX64RegisterSpecCtrl = 0x00080084, /**< @since build about 17758 */
+ HvX64RegisterPredCmd, /**< @since build about 17758 */
+
+ HvX64RegisterIa32MiscEnable = 0x000800a0, /**< @since v5 @note Appears not to be readable on exo partition (Threadripper). */
+ HvX64RegisterIa32FeatureControl, /**< @since v5 @note Appears not to be readable on exo partition (Threadripper). */
+
+ HvX64RegisterApicId = 0x00084802, /**< @since build 17758 */
+ HvX64RegisterApicVersion, /**< @since build 17758 */
+
+ /** Uptime counter or some such thing. Unit is different than HvRegisterTimeRefCount or the accounting is different. */
+ HvX64RegisterVpRuntime = 0x00090000,
+ HvX64RegisterHypercall,
+ HvRegisterGuestOsId,
+ HvRegisterVpIndex,
+ HvRegisterTimeRefCount, /**< Time counter since partition creation, 100ns units. */
+
+ HvRegisterCpuManagementVersion = 0x00090007, /**< @since v5 @note Appears not to be readable on exo partition. */
+
+ HvX64RegisterEoi = 0x00090010, /**< @note Appears not to be readable on exo partition. */
+ HvX64RegisterIcr, /**< @note Appears not to be readable on exo partition. */
+ HvX64RegisterTpr, /**< @note Appears not to be readable on exo partition. */
+ HvRegisterVpAssistPage,
+ /** Readable on exo partition (17134). Some kind of counter. */
+ HvRegisterUnknown90014,
+
+ HvRegisterStatsPartitionRetail = 0x00090020,
+ HvRegisterStatsPartitionInternal,
+ HvRegisterStatsVpRetail,
+ HvRegisterStatsVpInternal,
+
+ HvRegisterSint0 = 0x000a0000,
+ HvRegisterSint1,
+ HvRegisterSint2,
+ HvRegisterSint3,
+ HvRegisterSint4,
+ HvRegisterSint5,
+ HvRegisterSint6,
+ HvRegisterSint7,
+ HvRegisterSint8,
+ HvRegisterSint9,
+ HvRegisterSint10,
+ HvRegisterSint11,
+ HvRegisterSint12,
+ HvRegisterSint13,
+ HvRegisterSint14,
+ HvRegisterSint15,
+ HvRegisterScontrol,
+ HvRegisterSversion,
+ HvRegisterSifp,
+ HvRegisterSipp,
+ HvRegisterEom,
+ HvRegisterSirbp, /**< @since v4 */
+
+ HvRegisterStimer0Config = 0x000b0000,
+ HvRegisterStimer0Count,
+ HvRegisterStimer1Config,
+ HvRegisterStimer1Count,
+ HvRegisterStimer2Config,
+ HvRegisterStimer2Count,
+ HvRegisterStimer3Config,
+ HvRegisterStimer3Count,
+
+ HvRegisterUnknown0b0100 = 0x000b0100, /**< Readable on exo partition (17134), initial value is zero. */
+ HvRegisterUnknown0b0101, /**< Readable on exo partition (17134), initial value is zero. */
+
+ HvX64RegisterYmm0Low = 0x000c0000, /**< @note Not readable on exo partition. Need something enabled? */
+ HvX64RegisterYmm1Low,
+ HvX64RegisterYmm2Low,
+ HvX64RegisterYmm3Low,
+ HvX64RegisterYmm4Low,
+ HvX64RegisterYmm5Low,
+ HvX64RegisterYmm6Low,
+ HvX64RegisterYmm7Low,
+ HvX64RegisterYmm8Low,
+ HvX64RegisterYmm9Low,
+ HvX64RegisterYmm10Low,
+ HvX64RegisterYmm11Low,
+ HvX64RegisterYmm12Low,
+ HvX64RegisterYmm13Low,
+ HvX64RegisterYmm14Low,
+ HvX64RegisterYmm15Low,
+ HvX64RegisterYmm0High,
+ HvX64RegisterYmm1High,
+ HvX64RegisterYmm2High,
+ HvX64RegisterYmm3High,
+ HvX64RegisterYmm4High,
+ HvX64RegisterYmm5High,
+ HvX64RegisterYmm6High,
+ HvX64RegisterYmm7High,
+ HvX64RegisterYmm8High,
+ HvX64RegisterYmm9High,
+ HvX64RegisterYmm10High,
+ HvX64RegisterYmm11High,
+ HvX64RegisterYmm12High,
+ HvX64RegisterYmm13High,
+ HvX64RegisterYmm14High,
+ HvX64RegisterYmm15High,
+
+ HvRegisterVsmVpVtlControl = 0x000d0000, /**< @note Not readable on exo partition. */
+
+ HvRegisterVsmCodePageOffsets = 0x000d0002,
+ HvRegisterVsmVpStatus,
+ HvRegisterVsmPartitionStatus,
+ HvRegisterVsmVina, /**< @note Not readable on exo partition. */
+ HvRegisterVsmCapabilities,
+ HvRegisterVsmPartitionConfig, /**< @note Not readable on exo partition. */
+
+ HvRegisterVsmVpSecureConfigVtl0 = 0x000d0010, /**< @since v5 */
+ HvRegisterVsmVpSecureConfigVtl1, /**< @since v5 */
+ HvRegisterVsmVpSecureConfigVtl2, /**< @since v5 */
+ HvRegisterVsmVpSecureConfigVtl3, /**< @since v5 */
+ HvRegisterVsmVpSecureConfigVtl4, /**< @since v5 */
+ HvRegisterVsmVpSecureConfigVtl5, /**< @since v5 */
+ HvRegisterVsmVpSecureConfigVtl6, /**< @since v5 */
+ HvRegisterVsmVpSecureConfigVtl7, /**< @since v5 */
+ HvRegisterVsmVpSecureConfigVtl8, /**< @since v5 */
+ HvRegisterVsmVpSecureConfigVtl9, /**< @since v5 */
+ HvRegisterVsmVpSecureConfigVtl10, /**< @since v5 */
+ HvRegisterVsmVpSecureConfigVtl11, /**< @since v5 */
+ HvRegisterVsmVpSecureConfigVtl12, /**< @since v5 */
+ HvRegisterVsmVpSecureConfigVtl13, /**< @since v5 */
+ HvRegisterVsmVpSecureConfigVtl14, /**< @since v5 */
+
+ HvRegisterUnknown0e0000 = 0x000e0000, /**< Readable on exo partition (17134), initial value zero. */
+ HvRegisterUnknown0e0001, /**< Readable on exo partition (17134), initial value zero. */
+ HvRegisterUnknown0e0002, /**< Readable on exo partition (17134), initial value zero. */
+ HvRegisterUnknown0e0003 /**< Readable on exo partition (17134), initial value zero. */
+} HV_REGISTER_NAME;
+AssertCompile(HvRegisterInterceptSuspend == 0x00000001);
+AssertCompile(HvRegisterPendingEvent1 == 0x00010005);
+AssertCompile(HvX64RegisterDeliverabilityNotifications == 0x00010006);
+AssertCompile(HvX64RegisterRflags == 0x00020011);
+AssertCompile(HvX64RegisterXmmControlStatus == 0x00030019);
+AssertCompile(HvX64RegisterXfem == 0x00040005);
+AssertCompile(HvX64RegisterIntermediateCr0 == 0x00041000);
+AssertCompile(HvX64RegisterIntermediateCr4 == 0x00041003);
+AssertCompile(HvX64RegisterDr7 == 0x00050005);
+AssertCompile(HvX64RegisterTr == 0x00060007);
+AssertCompile(HvX64RegisterGdtr == 0x00070001);
+AssertCompile(HvX64RegisterInitialApicId == 0x0008000c);
+AssertCompile(HvX64RegisterMtrrCap == 0x0008000d);
+AssertCompile(HvX64RegisterMtrrDefType == 0x0008000e);
+AssertCompile(HvX64RegisterMtrrPhysBaseF == 0x0008001f);
+AssertCompile(HvX64RegisterMtrrPhysMaskF == 0x0008004f);
+AssertCompile(HvX64RegisterMtrrFix4kF8000 == 0x0008007a);
+AssertCompile(HvRegisterTimeRefCount == 0x00090004);
+AssertCompile(HvRegisterCpuManagementVersion == 0x00090007);
+AssertCompile(HvRegisterVpAssistPage == 0x00090013);
+AssertCompile(HvRegisterStatsVpInternal == 0x00090023);
+AssertCompile(HvRegisterSirbp == 0x000a0015);
+AssertCompile(HvRegisterStimer3Count == 0x000b0007);
+AssertCompile(HvX64RegisterYmm15High == 0x000c001f);
+AssertCompile(HvRegisterVsmVpSecureConfigVtl14 == 0x000d001e);
+AssertCompileSize(HV_REGISTER_NAME, 4);
+
+
+/** Value format for HvRegisterExplicitSuspend. */
+typedef union
+{
+ uint64_t AsUINT64;
+ struct
+ {
+ uint64_t Suspended : 1;
+#ifndef IN_IDA_PRO
+ uint64_t Reserved : 63;
+#endif
+ };
+} HV_EXPLICIT_SUSPEND_REGISTER;
+/** Pointer to a value of HvRegisterExplicitSuspend. */
+typedef HV_EXPLICIT_SUSPEND_REGISTER *PHV_EXPLICIT_SUSPEND_REGISTER;
+
+/** Value format for HvRegisterInterceptSuspend. */
+typedef union
+{
+ uint64_t AsUINT64;
+ struct
+ {
+ uint64_t Suspended : 1;
+ uint64_t TlbLocked : 1;
+#ifndef IN_IDA_PRO
+ uint64_t Reserved : 62;
+#endif
+ };
+} HV_INTERCEPT_SUSPEND_REGISTER;
+/** Pointer to a value of HvRegisterInterceptSuspend. */
+typedef HV_INTERCEPT_SUSPEND_REGISTER *PHV_INTERCEPT_SUSPEND_REGISTER;
+
+/** Value format for HvRegisterInterruptState.
+ * @sa WHV_X64_INTERRUPT_STATE_REGISTER */
+typedef union
+{
+ uint64_t AsUINT64;
+ struct
+ {
+ uint64_t InterruptShadow : 1;
+ uint64_t NmiMasked : 1;
+#ifndef IN_IDA_PRO
+ uint64_t Reserved : 62;
+#endif
+ };
+} HV_X64_INTERRUPT_STATE_REGISTER;
+/** Pointer to a value of HvRegisterInterruptState. */
+typedef HV_X64_INTERRUPT_STATE_REGISTER *PHV_X64_INTERRUPT_STATE_REGISTER;
+
+/** Pending exception type for HvRegisterPendingInterruption.
+ * @sa WHV_X64_PENDING_INTERRUPTION_TYPE */
+typedef enum
+{
+ HvX64PendingInterrupt = 0,
+ /* what is/was 1? */
+ HvX64PendingNmi = 2,
+ HvX64PendingException
+ /* any more? */
+} HV_X64_PENDING_INTERRUPTION_TYPE;
+
+/** Value format for HvRegisterPendingInterruption.
+ * @sa WHV_X64_PENDING_INTERRUPTION_REGISTER */
+typedef union
+{
+ uint64_t AsUINT64;
+ struct
+ {
+ uint32_t InterruptionPending : 1;
+ uint32_t InterruptionType : 3; /**< HV_X64_PENDING_INTERRUPTION_TYPE */
+ uint32_t DeliverErrorCode : 1;
+ uint32_t InstructionLength : 4; /**< @since v5? Wasn't in 7600 WDK */
+ uint32_t NestedEvent : 1; /**< @since v5? Wasn't in 7600 WDK */
+ uint32_t Reserved : 6;
+ uint32_t InterruptionVector : 16;
+ uint32_t ErrorCode;
+ };
+} HV_X64_PENDING_INTERRUPTION_REGISTER;
+/** Pointer to a value of HvRegisterPendingInterruption. */
+typedef HV_X64_PENDING_INTERRUPTION_REGISTER *PHV_X64_PENDING_INTERRUPTION_REGISTER;
+
+/** Value format for HvX64RegisterDeliverabilityNotifications.
+ * Value format for HvRegisterPendingEvent0/1.
+ * @sa WHV_X64_DELIVERABILITY_NOTIFICATIONS_REGISTER */
+typedef union
+{
+ uint64_t AsUINT64;
+ struct
+ {
+ uint64_t NmiNotification : 1;
+ uint64_t InterruptNotification : 1;
+ uint64_t InterruptPriority : 4;
+#ifndef IN_IDA_PRO
+ uint64_t Reserved : 58;
+#endif
+ };
+} HV_X64_DELIVERABILITY_NOTIFICATIONS_REGISTER;
+/** Pointer to a value of HvRegisterPendingEvent0/1. */
+typedef HV_X64_DELIVERABILITY_NOTIFICATIONS_REGISTER *PHV_X64_DELIVERABILITY_NOTIFICATIONS_REGISTER;
+
+
+/** Value format for HvX64RegisterEs..Tr.
+ * @sa WHV_X64_SEGMENT_REGISTER */
+typedef struct _HV_X64_SEGMENT_REGISTER
+{
+ uint64_t Base;
+ uint32_t Limit;
+ uint16_t Selector;
+ union
+ {
+ struct
+ {
+ uint16_t SegmentType : 4;
+ uint16_t NonSystemSegment : 1;
+ uint16_t DescriptorPrivilegeLevel : 2;
+ uint16_t Present : 1;
+ uint16_t Reserved : 4;
+ uint16_t Available : 1;
+ uint16_t Long : 1;
+ uint16_t Default : 1;
+ uint16_t Granularity : 1;
+ };
+ uint16_t Attributes;
+ };
+} HV_X64_SEGMENT_REGISTER;
+AssertCompileSize(HV_X64_SEGMENT_REGISTER, 16);
+/** Pointer to a value of HvX64RegisterEs..Tr. */
+typedef HV_X64_SEGMENT_REGISTER *PHV_X64_SEGMENT_REGISTER;
+
+/** Value format for HvX64RegisterIdtr/Gdtr.
+ * @sa WHV_X64_TABLE_REGISTER */
+typedef struct
+{
+ uint16_t Pad[3];
+ uint16_t Limit;
+ uint64_t Base;
+} HV_X64_TABLE_REGISTER;
+AssertCompileSize(HV_X64_TABLE_REGISTER, 16);
+/** Pointer to a value of HvX64RegisterIdtr/Gdtrr. */
+typedef HV_X64_TABLE_REGISTER *PHV_X64_TABLE_REGISTER;
+
+/** Value format for HvX64RegisterFpMmx0..7 in floating pointer mode.
+ * @sa WHV_X64_FP_REGISTER, RTFLOAT80U2 */
+typedef union
+{
+ HV_UINT128 AsUINT128;
+ struct
+ {
+ uint64_t Mantissa;
+ uint64_t BiasedExponent : 15;
+ uint64_t Sign : 1;
+#ifndef IN_IDA_PRO
+ uint64_t Reserved : 48;
+#endif
+ };
+} HV_X64_FP_REGISTER;
+/** Pointer to a value of HvX64RegisterFpMmx0..7 in floating point mode. */
+typedef HV_X64_FP_REGISTER *PHV_X64_FP_REGISTER;
+
+/** Value union for HvX64RegisterFpMmx0..7. */
+typedef union
+{
+ HV_UINT128 AsUINT128;
+ HV_X64_FP_REGISTER Fp;
+ uint64_t Mmx;
+} HV_X64_FP_MMX_REGISTER;
+/** Pointer to a value of HvX64RegisterFpMmx0..7. */
+typedef HV_X64_FP_MMX_REGISTER *PHV_X64_FP_MMX_REGISTER;
+
+/** Value format for HvX64RegisterFpControlStatus.
+ * @sa WHV_X64_FP_CONTROL_STATUS_REGISTER */
+typedef union
+{
+ HV_UINT128 AsUINT128;
+ struct
+ {
+ uint16_t FpControl;
+ uint16_t FpStatus;
+ uint8_t FpTag;
+ uint8_t IgnNe : 1;
+ uint8_t Reserved : 7;
+ uint16_t LastFpOp;
+ union
+ {
+ uint64_t LastFpRip;
+ struct
+ {
+ uint32_t LastFpEip;
+ uint16_t LastFpCs;
+ };
+ };
+ };
+} HV_X64_FP_CONTROL_STATUS_REGISTER;
+/** Pointer to a value of HvX64RegisterFpControlStatus. */
+typedef HV_X64_FP_CONTROL_STATUS_REGISTER *PHV_X64_FP_CONTROL_STATUS_REGISTER;
+
+/** Value format for HvX64RegisterXmmControlStatus.
+ * @sa WHV_X64_XMM_CONTROL_STATUS_REGISTER */
+typedef union
+{
+ HV_UINT128 AsUINT128;
+ struct
+ {
+ union
+ {
+ uint64_t LastFpRdp;
+ struct
+ {
+ uint32_t LastFpDp;
+ uint16_t LastFpDs;
+ };
+ };
+ uint32_t XmmStatusControl;
+ uint32_t XmmStatusControlMask;
+ };
+} HV_X64_XMM_CONTROL_STATUS_REGISTER;
+/** Pointer to a value of HvX64RegisterXmmControlStatus. */
+typedef HV_X64_XMM_CONTROL_STATUS_REGISTER *PHV_X64_XMM_CONTROL_STATUS_REGISTER;
+
+/** Register value union.
+ * @sa WHV_REGISTER_VALUE */
+typedef union
+{
+ HV_UINT128 Reg128;
+ uint64_t Reg64;
+ uint32_t Reg32;
+ uint16_t Reg16;
+ uint8_t Reg8;
+ HV_EXPLICIT_SUSPEND_REGISTER ExplicitSuspend;
+ HV_INTERCEPT_SUSPEND_REGISTER InterceptSuspend;
+ HV_X64_INTERRUPT_STATE_REGISTER InterruptState;
+ HV_X64_PENDING_INTERRUPTION_REGISTER PendingInterruption;
+ HV_X64_DELIVERABILITY_NOTIFICATIONS_REGISTER DeliverabilityNotifications;
+ HV_X64_TABLE_REGISTER Table;
+ HV_X64_SEGMENT_REGISTER Segment;
+ HV_X64_FP_REGISTER Fp;
+ HV_X64_FP_CONTROL_STATUS_REGISTER FpControlStatus;
+ HV_X64_XMM_CONTROL_STATUS_REGISTER XmmControlStatus;
+} HV_REGISTER_VALUE;
+AssertCompileSize(HV_REGISTER_VALUE, 16);
+/** Pointer to a Hyper-V register value union. */
+typedef HV_REGISTER_VALUE *PHV_REGISTER_VALUE;
+/** Pointer to a const Hyper-V register value union. */
+typedef HV_REGISTER_VALUE const *PCHV_REGISTER_VALUE;
+
+
+/** Input for HvCallGetVpRegisters. */
+typedef struct
+{
+ HV_PARTITION_ID PartitionId;
+ HV_VP_INDEX VpIndex;
+ /** Was this introduced after v2? Dunno what it it really is. */
+ uint32_t fFlags;
+ /* The repeating part: */
+ RT_FLEXIBLE_ARRAY_EXTENSION
+ HV_REGISTER_NAME Names[RT_FLEXIBLE_ARRAY];
+} HV_INPUT_GET_VP_REGISTERS;
+AssertCompileMemberOffset(HV_INPUT_GET_VP_REGISTERS, Names, 16);
+/** Pointer to input for HvCallGetVpRegisters. */
+typedef HV_INPUT_GET_VP_REGISTERS *PHV_INPUT_GET_VP_REGISTERS;
+/* Output for HvCallGetVpRegisters is an array of HV_REGISTER_VALUE parallel to HV_INPUT_GET_VP_REGISTERS::Names. */
+
+
+/** Register and value pair for HvCallSetVpRegisters. */
+typedef struct
+{
+ HV_REGISTER_NAME Name;
+ uint32_t Pad0;
+ uint64_t Pad1;
+ HV_REGISTER_VALUE Value;
+} HV_REGISTER_ASSOC;
+AssertCompileSize(HV_REGISTER_ASSOC, 32);
+AssertCompileMemberOffset(HV_REGISTER_ASSOC, Value, 16);
+/** Pointer to a register and value pair for HvCallSetVpRegisters. */
+typedef HV_REGISTER_ASSOC *PHV_REGISTER_ASSOC;
+/** Helper for clearing the alignment padding members. */
+#define HV_REGISTER_ASSOC_ZERO_PADDING(a_pRegAssoc) do { (a_pRegAssoc)->Pad0 = 0; (a_pRegAssoc)->Pad1 = 0; } while (0)
+/** Helper for clearing the alignment padding members and the high 64-bit
+ * part of the value. */
+#define HV_REGISTER_ASSOC_ZERO_PADDING_AND_HI64(a_pRegAssoc) \
+ do { (a_pRegAssoc)->Pad0 = 0; (a_pRegAssoc)->Pad1 = 0; (a_pRegAssoc)->Value.Reg128.High64 = 0; } while (0)
+
+/** Input for HvCallSetVpRegisters. */
+typedef struct
+{
+ HV_PARTITION_ID PartitionId;
+ HV_VP_INDEX VpIndex;
+ uint32_t RsvdZ;
+ /* The repeating part: */
+ RT_FLEXIBLE_ARRAY_EXTENSION
+ HV_REGISTER_ASSOC Elements[RT_FLEXIBLE_ARRAY];
+} HV_INPUT_SET_VP_REGISTERS;
+AssertCompileMemberOffset(HV_INPUT_SET_VP_REGISTERS, Elements, 16);
+/** Pointer to input for HvCallSetVpRegisters. */
+typedef HV_INPUT_SET_VP_REGISTERS *PHV_INPUT_SET_VP_REGISTERS;
+
+
+
+/**
+ * Hyper-V SyncIC message types.
+ */
+typedef enum
+{
+ HvMessageTypeNone = 0x00000000,
+
+ HvMessageTypeUnmappedGpa = 0x80000000,
+ HvMessageTypeGpaIntercept,
+
+ HvMessageTimerExpired = 0x80000010,
+
+ HvMessageTypeInvalidVpRegisterValue = 0x80000020,
+ HvMessageTypeUnrecoverableException,
+ HvMessageTypeUnsupportedFeature,
+ HvMessageTypeTlbPageSizeMismatch, /**< @since v5 */
+
+ /** @note Same as HvMessageTypeX64ApicEoi? Gone in 5.0. Missing from 7600 WDK
+ * headers even if it's in the 2.0 docs. */
+ HvMessageTypeApicEoi = 0x80000030,
+ /** @note Same as HvMessageTypeX64LegacyFpError? Gone in 5.0, whereas 4.0b
+ * calls it HvMessageTypeX64LegacyFpError. Missing from 7600 WDK
+ * headers even if it's in the 2.0 docs. */
+ HvMessageTypeFerrAsserted,
+
+ HvMessageTypeEventLogBufferComplete = 0x80000040,
+
+ HvMessageTypeX64IoPortIntercept = 0x80010000,
+ HvMessageTypeX64MsrIntercept,
+ HvMessageTypeX64CpuidIntercept,
+ HvMessageTypeX64ExceptionIntercept,
+ /** @note Appeared in 5.0 docs, but were here in 7600 WDK headers already. */
+ HvMessageTypeX64ApicEoi,
+ /** @note Appeared in 5.0 docs, but were here in 7600 WDK headers already. */
+ HvMessageTypeX64LegacyFpError,
+ /** @since v5 */
+ HvMessageTypeX64RegisterIntercept,
+ /** @since WinHvPlatform? */
+ HvMessageTypeX64Halt,
+ /** @since WinHvPlatform? */
+ HvMessageTypeX64InterruptWindow
+
+} HV_MESSAGE_TYPE;
+AssertCompileSize(HV_MESSAGE_TYPE, 4);
+AssertCompile(HvMessageTypeX64RegisterIntercept == 0x80010006);
+AssertCompile(HvMessageTypeX64Halt == 0x80010007);
+AssertCompile(HvMessageTypeX64InterruptWindow == 0x80010008);
+/** Pointer to a Hyper-V SyncIC message type. */
+typedef HV_MESSAGE_TYPE *PHV_MESSAGE_TYPE;
+
+/** Flag set for hypervisor messages, guest cannot send messages with this
+ * flag set. */
+#define HV_MESSAGE_TYPE_HYPERVISOR_MASK UINT32_C(0x80000000)
+
+/** Hyper-V SynIC message size (they are fixed sized). */
+#define HV_MESSAGE_SIZE 256
+/** Maximum Hyper-V SynIC message payload size in bytes. */
+#define HV_MESSAGE_MAX_PAYLOAD_BYTE_COUNT (HV_MESSAGE_SIZE - 16)
+/** Maximum Hyper-V SynIC message payload size in QWORDs (uint64_t). */
+#define HV_MESSAGE_MAX_PAYLOAD_QWORD_COUNT (HV_MESSAGE_MAX_PAYLOAD_BYTE_COUNT / 8)
+
+/** SynIC message flags. */
+typedef union
+{
+ uint8_t AsUINT8;
+ struct
+ {
+ /** Messages are pending in the queue. */
+ uint8_t MessagePending : 1;
+ uint8_t Reserved : 7;
+ };
+} HV_MESSAGE_FLAGS;
+AssertCompileSize(HV_MESSAGE_FLAGS, 1);
+
+/** SynIC message header. */
+typedef struct
+{
+ HV_MESSAGE_TYPE MessageType;
+ /** The 2.0-5.0b docs all have this incorrectly switched with 'Reserved', WDK 7600 got it right. */
+ uint8_t PayloadSize;
+ HV_MESSAGE_FLAGS MessageFlags;
+ uint16_t Reserved;
+ union
+ {
+ uint64_t OriginationId;
+ HV_PARTITION_ID Sender;
+ HV_PORT_ID Port;
+ };
+} HV_MESSAGE_HEADER;
+AssertCompileSize(HV_MESSAGE_HEADER, 16);
+/** Pointer to a Hyper-V message header. */
+typedef HV_MESSAGE_HEADER *PHV_MESSAGE_HEADER;
+/** Pointer to a const Hyper-V message header. */
+typedef HV_MESSAGE_HEADER const *PCHV_MESSAGE_HEADER;
+
+
+
+/** @name Intercept access type.
+ * @{ */
+typedef uint8_t HV_INTERCEPT_ACCESS_TYPE;
+#define HV_INTERCEPT_ACCESS_READ 0
+#define HV_INTERCEPT_ACCESS_WRITE 1
+#define HV_INTERCEPT_ACCESS_EXECUTE 2
+/** @} */
+
+/** @name Intercept access type mask.
+ * @{ */
+typedef uint32_t HV_INTERCEPT_ACCESS_TYPE_MASK;
+#define HV_INTERCEPT_ACCESS_MASK_NONE 0
+#define HV_INTERCEPT_ACCESS_MASK_READ 1
+#define HV_INTERCEPT_ACCESS_MASK_WRITE 2
+#define HV_INTERCEPT_ACCESS_MASK_EXECUTE 4
+/** @} */
+
+/** X64 intercept execution state.
+ * @sa WHV_X64_VP_EXECUTION_STATE */
+typedef union
+{
+ uint16_t AsUINT16;
+ struct
+ {
+ uint16_t Cpl : 2;
+ uint16_t Cr0Pe : 1;
+ uint16_t Cr0Am : 1;
+ uint16_t EferLma : 1;
+ uint16_t DebugActive : 1;
+ uint16_t InterruptionPending : 1;
+ uint16_t Reserved0 : 5;
+ uint16_t InterruptShadow : 1;
+ uint16_t Reserved1 : 3;
+ };
+} HV_X64_VP_EXECUTION_STATE;
+AssertCompileSize(HV_X64_VP_EXECUTION_STATE, 2);
+/** Pointer to X86 intercept execution state. */
+typedef HV_X64_VP_EXECUTION_STATE *PHV_X64_VP_EXECUTION_STATE;
+/** Pointer to const X86 intercept execution state. */
+typedef HV_X64_VP_EXECUTION_STATE const *PCHV_X64_VP_EXECUTION_STATE;
+
+/** X64 intercept message header. */
+typedef struct
+{
+ HV_VP_INDEX VpIndex; /**< 0x00 */
+ uint8_t InstructionLength : 4; /**< 0x04[3:0]: Zero if not available, instruction fetch exit, ... */
+ uint8_t Cr8 : 4; /**< 0x04[7:4]: Not sure since when, but after v2. */
+ HV_INTERCEPT_ACCESS_TYPE InterceptAccessType; /**< 0x05 */
+ HV_X64_VP_EXECUTION_STATE ExecutionState; /**< 0x06 */
+ HV_X64_SEGMENT_REGISTER CsSegment; /**< 0x08 */
+ uint64_t Rip; /**< 0x18 */
+ uint64_t Rflags; /**< 0x20 */
+} HV_X64_INTERCEPT_MESSAGE_HEADER;
+AssertCompileSize(HV_X64_INTERCEPT_MESSAGE_HEADER, 40);
+/** Pointer to a x86 intercept message header. */
+typedef HV_X64_INTERCEPT_MESSAGE_HEADER *PHV_X64_INTERCEPT_MESSAGE_HEADER;
+
+
+/** X64 memory access flags (HvMessageTypeGpaIntercept, HvMessageTypeUnmappedGpa).
+ * @sa WHV_MEMORY_ACCESS_INFO */
+typedef union
+{
+ uint8_t AsUINT8;
+ struct
+ {
+ uint8_t GvaValid : 1;
+ uint8_t Reserved : 7;
+ };
+} HV_X64_MEMORY_ACCESS_INFO;
+AssertCompileSize(HV_X64_MEMORY_ACCESS_INFO, 1);
+
+/** The payload format for HvMessageTypeGpaIntercept and HvMessageTypeUnmappedGpa.
+ * @sa WHV_MEMORY_ACCESS_CONTEXT
+ * @note max message size. */
+typedef struct
+{
+ HV_X64_INTERCEPT_MESSAGE_HEADER Header; /**< 0x00 */
+ HV_CACHE_TYPE CacheType; /**< 0x28 */
+ uint8_t InstructionByteCount; /**< 0x2c */
+ HV_X64_MEMORY_ACCESS_INFO MemoryAccessInfo; /**< 0x2d */
+ uint16_t Reserved1; /**< 0x2e */
+ uint64_t GuestVirtualAddress; /**< 0x30 */
+ uint64_t GuestPhysicalAddress; /**< 0x38 */
+ uint8_t InstructionBytes[16]; /**< 0x40 */
+ /* We don't the following (v5 / WinHvPlatform): */
+ HV_X64_SEGMENT_REGISTER DsSegment; /**< 0x50 */
+ HV_X64_SEGMENT_REGISTER SsSegment; /**< 0x60 */
+ uint64_t Rax; /**< 0x70 */
+ uint64_t Rcx; /**< 0x78 */
+ uint64_t Rdx; /**< 0x80 */
+ uint64_t Rbx; /**< 0x88 */
+ uint64_t Rsp; /**< 0x90 */
+ uint64_t Rbp; /**< 0x98 */
+ uint64_t Rsi; /**< 0xa0 */
+ uint64_t Rdi; /**< 0xa8 */
+ uint64_t R8; /**< 0xb0 */
+ uint64_t R9; /**< 0xb8 */
+ uint64_t R10; /**< 0xc0 */
+ uint64_t R11; /**< 0xc8 */
+ uint64_t R12; /**< 0xd0 */
+ uint64_t R13; /**< 0xd8 */
+ uint64_t R14; /**< 0xe0 */
+ uint64_t R15; /**< 0xe8 */
+} HV_X64_MEMORY_INTERCEPT_MESSAGE;
+AssertCompileSize(HV_X64_MEMORY_INTERCEPT_MESSAGE, 0xf0);
+AssertCompileMemberOffset(HV_X64_MEMORY_INTERCEPT_MESSAGE, DsSegment, 0x50);
+/** Pointer to a HvMessageTypeGpaIntercept or HvMessageTypeUnmappedGpa payload. */
+typedef HV_X64_MEMORY_INTERCEPT_MESSAGE *PHV_X64_MEMORY_INTERCEPT_MESSAGE;
+/** Pointer to a const HvMessageTypeGpaIntercept or HvMessageTypeUnmappedGpa payload. */
+typedef HV_X64_MEMORY_INTERCEPT_MESSAGE const *PCHV_X64_MEMORY_INTERCEPT_MESSAGE;
+
+
+/** The payload format for HvMessageTypeX64MsrIntercept. */
+typedef struct _HV_X64_MSR_INTERCEPT_MESSAGE
+{
+ HV_X64_INTERCEPT_MESSAGE_HEADER Header; /**< 0x00 */
+ uint32_t MsrNumber; /**< 0x28 (ecx) */
+ uint32_t Reserved; /**< 0x2c */
+ uint64_t Rdx; /**< 0x30 */
+ uint64_t Rax; /**< 0x38 */
+} HV_X64_MSR_INTERCEPT_MESSAGE;
+AssertCompileSize(HV_X64_MSR_INTERCEPT_MESSAGE, 0x40);
+/** Pointer to a HvMessageTypeX64MsrIntercept payload. */
+typedef HV_X64_MSR_INTERCEPT_MESSAGE *PHV_X64_MSR_INTERCEPT_MESSAGE;
+/** Pointer to a const HvMessageTypeX64MsrIntercept payload. */
+typedef HV_X64_MSR_INTERCEPT_MESSAGE const *PCHV_X64_MSR_INTERCEPT_MESSAGE;
+
+/** Full MSR message. */
+typedef struct
+{
+ HV_MESSAGE_HEADER MsgHdr;
+ HV_X64_MSR_INTERCEPT_MESSAGE Payload;
+} HV_X64_MSR_INTERCEPT_MESSAGE_FULL;
+
+
+/** X64 I/O port access information (HvMessageTypeX64IoPortIntercept). */
+typedef union HV_X64_IO_PORT_ACCESS_INFO
+{
+ uint8_t AsUINT8;
+ struct
+ {
+ uint8_t AccessSize : 3;
+ uint8_t StringOp : 1;
+ uint8_t RepPrefix : 1;
+ uint8_t Reserved : 3;
+ };
+} HV_X64_IO_PORT_ACCESS_INFO;
+AssertCompileSize(HV_X64_IO_PORT_ACCESS_INFO, 1);
+
+/** The payload format for HvMessageTypeX64IoPortIntercept. */
+typedef struct _HV_X64_IO_PORT_INTERCEPT_MESSAGE
+{
+ HV_X64_INTERCEPT_MESSAGE_HEADER Header; /**< 0x00 */
+ uint16_t PortNumber; /**< 0x28 */
+ HV_X64_IO_PORT_ACCESS_INFO AccessInfo; /**< 0x2a */
+ uint8_t InstructionByteCount; /**< 0x2b */
+ uint32_t Reserved; /**< 0x2c */
+ uint64_t Rax; /**< 0x30 */
+ uint8_t InstructionBytes[16]; /**< 0x38 */
+ HV_X64_SEGMENT_REGISTER DsSegment; /**< 0x48 */
+ HV_X64_SEGMENT_REGISTER EsSegment; /**< 0x58 */
+ uint64_t Rcx; /**< 0x68 */
+ uint64_t Rsi; /**< 0x70 */
+ uint64_t Rdi; /**< 0x78 */
+} HV_X64_IO_PORT_INTERCEPT_MESSAGE;
+AssertCompileSize(HV_X64_IO_PORT_INTERCEPT_MESSAGE, 128);
+/** Pointer to a HvMessageTypeX64IoPortIntercept payload. */
+typedef HV_X64_IO_PORT_INTERCEPT_MESSAGE *PHV_X64_IO_PORT_INTERCEPT_MESSAGE;
+/** Pointer to a const HvMessageTypeX64IoPortIntercept payload. */
+typedef HV_X64_IO_PORT_INTERCEPT_MESSAGE const *PCHV_X64_IO_PORT_INTERCEPT_MESSAGE;
+
+/** Full I/O port message. */
+typedef struct
+{
+ HV_MESSAGE_HEADER MsgHdr;
+ HV_X64_IO_PORT_INTERCEPT_MESSAGE Payload;
+} HV_X64_IO_PORT_INTERCEPT_MESSAGE_FULL;
+
+
+/**
+ * The payload format for HvMessageTypeX64CpuidIntercept,
+ *
+ * @note This message does not include HV_X64_INTERCEPT_MESSAGE_HEADER!
+ */
+typedef struct
+{
+ HV_X64_INTERCEPT_MESSAGE_HEADER Header; /**< 0x00: The usual intercept header. */
+ uint64_t Rax; /**< 0x28: Input RAX. */
+ uint64_t Rcx; /**< 0x30: Input RCX. */
+ uint64_t Rdx; /**< 0x38: Input RDX. */
+ uint64_t Rbx; /**< 0x40: Input RBX. */
+ uint64_t DefaultResultRax; /**< 0x48: Default result RAX. */
+ uint64_t DefaultResultRcx; /**< 0x50: Default result RCX. */
+ uint64_t DefaultResultRdx; /**< 0x58: Default result RDX. */
+ uint64_t DefaultResultRbx; /**< 0x60: Default result RBX. */
+} HV_X64_CPUID_INTERCEPT_MESSAGE;
+AssertCompileSize(HV_X64_CPUID_INTERCEPT_MESSAGE, 0x68);
+/** Pointer to a HvMessageTypeX64CpuidIntercept payload. */
+typedef HV_X64_CPUID_INTERCEPT_MESSAGE *PHV_X64_CPUID_INTERCEPT_MESSAGE;
+/** Pointer to a const HvMessageTypeX64CpuidIntercept payload. */
+typedef HV_X64_CPUID_INTERCEPT_MESSAGE const *PCHV_X64_CPUID_INTERCEPT_MESSAGE;
+
+/** Full HvMessageTypeX64CpuidIntercept message. */
+typedef struct
+{
+ HV_MESSAGE_HEADER MsgHdr;
+ HV_X64_CPUID_INTERCEPT_MESSAGE Payload;
+} HV_X64_CPUID_INTERCEPT_MESSAGE_FULL;
+
+
+/** X64 exception information (HvMessageTypeX64ExceptionIntercept).
+ * @sa WHV_VP_EXCEPTION_INFO */
+typedef union
+{
+ uint8_t AsUINT8;
+ struct
+ {
+ uint8_t ErrorCodeValid : 1;
+ /** @todo WHV_VP_EXCEPTION_INFO::SoftwareException */
+ uint8_t Reserved : 7;
+ };
+} HV_X64_EXCEPTION_INFO;
+AssertCompileSize(HV_X64_EXCEPTION_INFO, 1);
+
+/** The payload format for HvMessageTypeX64ExceptionIntercept.
+ * @sa WHV_VP_EXCEPTION_CONTEXT
+ * @note max message size. */
+typedef struct
+{
+ HV_X64_INTERCEPT_MESSAGE_HEADER Header; /**< 0x00 */
+ uint16_t ExceptionVector; /**< 0x28 */
+ HV_X64_EXCEPTION_INFO ExceptionInfo; /**< 0x2a */
+ uint8_t InstructionByteCount; /**< 0x2b */
+ uint32_t ErrorCode; /**< 0x2c */
+ uint64_t ExceptionParameter; /**< 0x30 */
+ uint64_t Reserved; /**< 0x38 */
+ uint8_t InstructionBytes[16]; /**< 0x40 */
+ HV_X64_SEGMENT_REGISTER DsSegment; /**< 0x50 */
+ HV_X64_SEGMENT_REGISTER SsSegment; /**< 0x60 */
+ uint64_t Rax; /**< 0x70 */
+ uint64_t Rcx; /**< 0x78 */
+ uint64_t Rdx; /**< 0x80 */
+ uint64_t Rbx; /**< 0x88 */
+ uint64_t Rsp; /**< 0x90 */
+ uint64_t Rbp; /**< 0x98 */
+ uint64_t Rsi; /**< 0xa0 */
+ uint64_t Rdi; /**< 0xa8 */
+ uint64_t R8; /**< 0xb0 */
+ uint64_t R9; /**< 0xb8 */
+ uint64_t R10; /**< 0xc0 */
+ uint64_t R11; /**< 0xc8 */
+ uint64_t R12; /**< 0xd0 */
+ uint64_t R13; /**< 0xd8 */
+ uint64_t R14; /**< 0xe0 */
+ uint64_t R15; /**< 0xe8 */
+} HV_X64_EXCEPTION_INTERCEPT_MESSAGE;
+AssertCompileSize(HV_X64_EXCEPTION_INTERCEPT_MESSAGE, 0xf0);
+/** Pointer to a HvMessageTypeX64ExceptionIntercept payload. */
+typedef HV_X64_EXCEPTION_INTERCEPT_MESSAGE *PHV_X64_EXCEPTION_INTERCEPT_MESSAGE;
+/** Pointer to a ocnst HvMessageTypeX64ExceptionIntercept payload. */
+typedef HV_X64_EXCEPTION_INTERCEPT_MESSAGE const *PCHV_X64_EXCEPTION_INTERCEPT_MESSAGE;
+
+
+/**
+ * The payload format for HvMessageTypeX64Halt,
+ *
+ * @note This message does not include HV_X64_INTERCEPT_MESSAGE_HEADER!
+ */
+typedef struct
+{
+ /** Seems to be a zero 64-bit field here. */
+ uint64_t u64Reserved;
+} HV_X64_HALT_MESSAGE;
+/** Pointer to a HvMessageTypeX64Halt payload. */
+typedef HV_X64_HALT_MESSAGE *PHV_X64_HALT_MESSAGE;
+/** Pointer to a const HvMessageTypeX64Halt payload. */
+typedef HV_X64_HALT_MESSAGE const *PCHV_X64_HALT_MESSAGE;
+
+/** Full HvMessageTypeX64Halt message. */
+typedef struct
+{
+ HV_MESSAGE_HEADER MsgHdr;
+ HV_X64_HALT_MESSAGE Payload;
+} HV_X64_HALT_MESSAGE_FULL;
+
+
+/**
+ * The payload format for HvMessageTypeX64InterruptWindow,
+ *
+ * @note This message does not include HV_X64_INTERCEPT_MESSAGE_HEADER!
+ */
+typedef struct
+{
+ /** 0x00: The usual intercept header. */
+ HV_X64_INTERCEPT_MESSAGE_HEADER Header;
+ /** 0x28: What's pending. */
+ HV_X64_PENDING_INTERRUPTION_TYPE Type;
+ /** 0x2c: Explicit structure alignment padding. */
+ uint32_t u32ExplicitPadding;
+} HV_X64_INTERRUPT_WINDOW_MESSAGE;
+AssertCompileSize(HV_X64_INTERRUPT_WINDOW_MESSAGE, 0x30);
+/** Pointer to a HvMessageTypeX64InterruptWindow payload. */
+typedef HV_X64_INTERRUPT_WINDOW_MESSAGE *PHV_X64_INTERRUPT_WINDOW_MESSAGE;
+/** Pointer to a const HvMessageTypeX64InterruptWindow payload. */
+typedef HV_X64_INTERRUPT_WINDOW_MESSAGE const *PCHV_X64_INTERRUPT_WINDOW_MESSAGE;
+
+/** Full HvMessageTypeX64InterruptWindow message. */
+typedef struct
+{
+ /** Payload size is 0x30. */
+ HV_MESSAGE_HEADER MsgHdr;
+ HV_X64_INTERRUPT_WINDOW_MESSAGE Payload;
+} HV_X64_INTERRUPT_WINDOW_MESSAGE_FULL;
+
+
+
+/** Hyper-V SynIC message. */
+typedef struct
+{
+ HV_MESSAGE_HEADER Header;
+ /** 0x10 */
+ union
+ {
+ uint64_t Payload[HV_MESSAGE_MAX_PAYLOAD_QWORD_COUNT];
+
+ /** Common header for X64 intercept messages.
+ * The HvMessageTypeUnrecoverableException message only has this. */
+ HV_X64_INTERCEPT_MESSAGE_HEADER X64InterceptHeader;
+ /** HvMessageTypeGpaIntercept, HvMessageTypeUnmappedGpa. */
+ HV_X64_MEMORY_INTERCEPT_MESSAGE X64MemoryIntercept;
+ /** HvMessageTypeX64IoPortIntercept */
+ HV_X64_IO_PORT_INTERCEPT_MESSAGE X64IoPortIntercept;
+ /** HvMessageTypeX64MsrIntercept */
+ HV_X64_MSR_INTERCEPT_MESSAGE X64MsrIntercept;
+ /** HvMessageTypeX64CpuidIntercept */
+ HV_X64_CPUID_INTERCEPT_MESSAGE X64CpuIdIntercept;
+ /** HvMessageTypeX64ExceptionIntercept */
+ HV_X64_EXCEPTION_INTERCEPT_MESSAGE X64ExceptionIntercept;
+ /** HvMessageTypeX64Halt.
+ * @note No intercept header? */
+ HV_X64_HALT_MESSAGE X64Halt;
+ /** HvMessageTypeX64InterruptWindow. */
+ HV_X64_INTERRUPT_WINDOW_MESSAGE X64InterruptWindow;
+ };
+} HV_MESSAGE;
+AssertCompileSize(HV_MESSAGE, HV_MESSAGE_SIZE);
+/** Pointer to a Hyper-V SynIC message. */
+typedef HV_MESSAGE *PHV_MESSAGE;
+/** Pointer to const a Hyper-V SynIC message. */
+typedef HV_MESSAGE const *PCHV_MESSAGE;
+
+#endif /* !IPRT_INCLUDED_nt_hyperv_h */
+
diff --git a/include/iprt/nt/miniport.h b/include/iprt/nt/miniport.h
new file mode 100644
index 00000000..0525e306
--- /dev/null
+++ b/include/iprt/nt/miniport.h
@@ -0,0 +1,61 @@
+/** @file
+ * Safe way to include miniport.h.
+ */
+
+/*
+ * Copyright (C) 2016-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_nt_miniport_h
+#define IPRT_INCLUDED_nt_miniport_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cdefs.h>
+
+#ifdef _MSC_VER
+# pragma warning(push)
+# pragma warning(disable:4668) /* basetsd.h(114) : warning C4668: '__midl' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif' */
+# if _MSC_VER >= 1800 /*RT_MSC_VER_VC120*/
+# pragma warning(disable:4005) /* sdk/v7.1/include/sal_supp.h(57) : warning C4005: '__useHeader' : macro redefinition */
+# endif
+#endif
+
+RT_C_DECLS_BEGIN
+#include <miniport.h>
+RT_C_DECLS_END
+
+#ifdef _MSC_VER
+# pragma warning(pop)
+#endif
+
+#endif /* !IPRT_INCLUDED_nt_miniport_h */
+
diff --git a/include/iprt/nt/ndis.h b/include/iprt/nt/ndis.h
new file mode 100644
index 00000000..e8263edb
--- /dev/null
+++ b/include/iprt/nt/ndis.h
@@ -0,0 +1,61 @@
+/** @file
+ * Safe way to include ndis.h.
+ */
+
+/*
+ * Copyright (C) 2016-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_nt_ndis_h
+#define IPRT_INCLUDED_nt_ndis_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cdefs.h>
+
+#ifdef _MSC_VER
+# pragma warning(push)
+# pragma warning(disable:4668) /* warning C4668: 'NDIS_WRAPPER' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif' */
+# if _MSC_VER >= 1800 /*RT_MSC_VER_VC120*/
+# pragma warning(disable:4005) /* sdk/v7.1/include/sal_supp.h(57) : warning C4005: '__useHeader' : macro redefinition */
+# endif
+#endif
+
+RT_C_DECLS_BEGIN
+#include <ndis.h>
+RT_C_DECLS_END
+
+#ifdef _MSC_VER
+# pragma warning(pop)
+#endif
+
+#endif /* !IPRT_INCLUDED_nt_ndis_h */
+
diff --git a/include/iprt/nt/nt-and-windows.h b/include/iprt/nt/nt-and-windows.h
new file mode 100644
index 00000000..e5bbbaff
--- /dev/null
+++ b/include/iprt/nt/nt-and-windows.h
@@ -0,0 +1,68 @@
+/* $Id: nt-and-windows.h $ */
+/** @file
+ * IPRT - Header for code using both NT native and Windows APIs.
+ */
+
+/*
+ * Copyright (C) 2013-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_nt_nt_and_windows_h
+#define IPRT_INCLUDED_nt_nt_and_windows_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#define _PEB IncompleteWindows__PEB
+#define PEB IncompleteWindows_PEB
+#define PPEB IncompleteWindows_PPEB
+
+#define _TEB IncompleteWindows__TEB
+#define TEB IncompleteWindows_TEB
+#define PTEB IncompleteWindows_PTEB
+
+#define IPRT_NT_USE_WINTERNL
+#define IPRT_NT_HAVE_CURRENT_TEB_MACRO
+#define WIN32_NO_STATUS
+#include <iprt/win/windows.h>
+#undef WIN32_NO_STATUS
+
+#undef _PEB
+#undef PEB
+#undef PPEB
+
+#undef _TEB
+#undef TEB
+#undef PTEB
+
+#include <iprt/nt/nt.h>
+
+#endif /* !IPRT_INCLUDED_nt_nt_and_windows_h */
+
diff --git a/include/iprt/nt/nt-structures.h b/include/iprt/nt/nt-structures.h
new file mode 100644
index 00000000..fbf83f0a
--- /dev/null
+++ b/include/iprt/nt/nt-structures.h
@@ -0,0 +1,146 @@
+/* $Id: nt-structures.h $ */
+/** @file
+ * IPRT - Header for NT structures.
+ */
+
+/*
+ * Copyright (C) 2010-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_nt_nt_structures_h
+#define IPRT_INCLUDED_nt_nt_structures_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+
+#include <iprt/types.h>
+
+
+/** @name NT Kernel Structures
+ * @{ */
+typedef struct KTRAP_FRAME_AMD64
+{
+ uint64_t P1Home; /**< 0x00 */
+ uint64_t P2Home; /**< 0x08 */
+ uint64_t P3Home; /**< 0x10 */
+ uint64_t P4Home; /**< 0x18 */
+ uint64_t P5; /**< 0x20 */
+ uint8_t PreviousMode; /**< 0x28: KPROCESSOR_MODE / MODE - unused? */
+ uint8_t PreviousIrql; /**< 0x29: KIRQL - Interrupts? */
+ uint8_t FaultIndicator; /**< 0x2a: Holds (ErrCd >> 1) & 9) for \#PF. */
+ uint8_t ExceptionActive; /**< 0x2b: 0 if interrupt, 1 if exception, 2 if service call, */
+ uint32_t MxCsr; /**< 0x2c */
+ /** @name Volatile general register state. Only saved on interrupts and exceptions.
+ * @{ */
+ uint64_t Rax; /**< 0x30 */
+ uint64_t Rcx; /**< 0x38 */
+ uint64_t Rdx; /**< 0x40 */
+ uint64_t R8; /**< 0x48 */
+ uint64_t R9; /**< 0x50 */
+ uint64_t R10; /**< 0x58 */
+ uint64_t R11; /**< 0x60 */
+ /** @} */
+ uint64_t GsBaseOrSwap; /**< 0x68: GsBase if previous mode is kernel, GsSwap if pervious mode was user. */
+ /** @name Volatile SSE state. Only saved on interrupts and exceptions.
+ * @{ */
+ RTUINT128U Xmm0; /**< 0x70 */
+ RTUINT128U Xmm1; /**< 0x80: RBP points here. */
+ RTUINT128U Xmm2; /**< 0x90 */
+ RTUINT128U Xmm3; /**< 0xa0 */
+ RTUINT128U Xmm4; /**< 0xb0 */
+ RTUINT128U Xmm5; /**< 0xc0 */
+ /** @} */
+ uint64_t FaultAddrOrCtxRecOrTS; /**< 0xd0: Used to save CR2 in \#PF and NMI handlers. */
+ /** @name Usermode debug state.
+ * @{ */
+ uint64_t Dr0; /**< 0xd8: Only if DR7 indicates active. */
+ uint64_t Dr1; /**< 0xe0: Only if DR7 indicates active. */
+ uint64_t Dr2; /**< 0xe8: Only if DR7 indicates active. */
+ uint64_t Dr3; /**< 0xf0: Only if DR7 indicates active. */
+ uint64_t Dr6; /**< 0xf8: Only if DR7 indicates active. */
+ uint64_t Dr7; /**< 0x100: Considered active any of these bits are set:
+ X86_DR7_LE_ALL | X86_DR7_LE | X86_DR7_GE. */
+ union
+ {
+ struct
+ {
+ uint64_t LastBranchControl; /**< 0x108 */
+ uint32_t LastBranchMSR; /**< 0x110 */
+ } amd;
+ struct
+ {
+ uint64_t DebugControl; /**< 0x108 */
+ uint64_t LastBranchToRip; /**< 0x110 */
+ uint64_t LastBranchFromRip; /**< 0x118 */
+ uint64_t LastExceptionToRip; /**< 0x120 */
+ uint64_t LastExceptionFromRip; /**< 0x128 */
+ } intel;
+ } u;
+ /** @} */
+ /** @name Segment registers. Not sure when these would actually be used.
+ * @{ */
+ uint16_t SegDs; /**< 0x130 */
+ uint16_t SegEs; /**< 0x132 */
+ uint16_t SegFs; /**< 0x134 */
+ uint16_t SegGs; /**< 0x136 */
+ /** @} */
+ uint64_t TrapFrame; /**< 0x138 */
+ /** @name Some non-volatile registers only saved in service calls.
+ * @{ */
+ uint64_t Rbx; /**< 0x140 */
+ uint64_t Rdi; /**< 0x148 */
+ uint64_t Rsi; /**< 0x150 */
+ /** @} */
+ uint64_t Rbp; /**< 0x158: Typically restored by: MOV RBP, [RBP + 0xd8] */
+ uint64_t ErrCdOrXcptFrameOrS; /**< 0x160 */
+ uint64_t Rip; /**< 0x168 - IRET RIP */
+ uint16_t SegCs; /**< 0x170 - IRET CS */
+ uint8_t Fill0; /**< 0x172 */
+ uint8_t Logging; /**< 0x173 */
+ uint16_t Fill1[2]; /**< 0x174 */
+ uint32_t EFlags; /**< 0x178 - IRET EFLAGS - Uninitialized for stack switching/growth code path. */
+ uint32_t Fill2; /**< 0x17c */
+ uint64_t Rsp; /**< 0x180 - IRET RSP */
+ uint16_t SegSs; /**< 0x188 - IRET SS */
+ uint16_t Fill3; /**< 0x18a */
+ uint32_t Fill4; /**< 0x18c */
+} KTRAP_FRAME_AMD64;
+AssertCompileSize(KTRAP_FRAME_AMD64, 0x190);
+/** Pointer to an AMD64 NT trap frame. */
+typedef KTRAP_FRAME_AMD64 *PKTRAP_FRAME_AMD64;
+/** Pointer to a const AMD64 NT trap frame. */
+typedef KTRAP_FRAME_AMD64 const *PCKTRAP_FRAME_AMD64;
+
+/** @} */
+
+
+#endif /* !IPRT_INCLUDED_nt_nt_structures_h */
+
diff --git a/include/iprt/nt/nt.h b/include/iprt/nt/nt.h
new file mode 100644
index 00000000..c23cd9f0
--- /dev/null
+++ b/include/iprt/nt/nt.h
@@ -0,0 +1,3824 @@
+/* $Id: nt.h $ */
+/** @file
+ * IPRT - Header for code using the Native NT API.
+ */
+
+/*
+ * Copyright (C) 2010-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_nt_nt_h
+#define IPRT_INCLUDED_nt_nt_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+/** @def IPRT_NT_MAP_TO_ZW
+ * Map Nt calls to Zw calls. In ring-0 the Zw calls let you pass kernel memory
+ * to the APIs (takes care of the previous context checks).
+ */
+#ifdef DOXYGEN_RUNNING
+# define IPRT_NT_MAP_TO_ZW
+#endif
+
+#ifdef IPRT_NT_MAP_TO_ZW
+# define NtQueryDirectoryFile ZwQueryDirectoryFile
+# define NtQueryInformationFile ZwQueryInformationFile
+# define NtQueryInformationProcess ZwQueryInformationProcess
+# define NtQueryInformationThread ZwQueryInformationThread
+# define NtQueryFullAttributesFile ZwQueryFullAttributesFile
+# define NtQuerySystemInformation ZwQuerySystemInformation
+# define NtQuerySecurityObject ZwQuerySecurityObject
+# define NtSetInformationFile ZwSetInformationFile
+# define NtClose ZwClose
+# define NtCreateFile ZwCreateFile
+# define NtReadFile ZwReadFile
+# define NtWriteFile ZwWriteFile
+# define NtFlushBuffersFile ZwFlushBuffersFile
+/** @todo this is very incomplete! */
+#endif
+
+#include <ntstatus.h>
+
+/*
+ * Hacks common to both base header sets.
+ */
+#define RtlFreeUnicodeString WrongLinkage_RtlFreeUnicodeString
+#define NtQueryObject Incomplete_NtQueryObject
+#define ZwQueryObject Incomplete_ZwQueryObject
+#define NtSetInformationObject Incomplete_NtSetInformationObject
+#define _OBJECT_INFORMATION_CLASS Incomplete_OBJECT_INFORMATION_CLASS
+#define OBJECT_INFORMATION_CLASS Incomplete_OBJECT_INFORMATION_CLASS
+#define ObjectBasicInformation Incomplete_ObjectBasicInformation
+#define ObjectTypeInformation Incomplete_ObjectTypeInformation
+#define _PEB Incomplete__PEB
+#define PEB Incomplete_PEB
+#define PPEB Incomplete_PPEB
+#define _TEB Incomplete__TEB
+#define TEB Incomplete_TEB
+#define PTEB Incomplete_PTEB
+#define _PEB_LDR_DATA Incomplete__PEB_LDR_DATA
+#define PEB_LDR_DATA Incomplete_PEB_LDR_DATA
+#define PPEB_LDR_DATA Incomplete_PPEB_LDR_DATA
+#define _KUSER_SHARED_DATA Incomplete__KUSER_SHARED_DATA
+#define KUSER_SHARED_DATA Incomplete_KUSER_SHARED_DATA
+#define PKUSER_SHARED_DATA Incomplete_PKUSER_SHARED_DATA
+
+
+
+#ifdef IPRT_NT_USE_WINTERNL
+/*
+ * Use Winternl.h.
+ */
+# define _FILE_INFORMATION_CLASS IncompleteWinternl_FILE_INFORMATION_CLASS
+# define FILE_INFORMATION_CLASS IncompleteWinternl_FILE_INFORMATION_CLASS
+# define FileDirectoryInformation IncompleteWinternl_FileDirectoryInformation
+
+# define NtQueryInformationProcess IncompleteWinternl_NtQueryInformationProcess
+# define NtSetInformationProcess IncompleteWinternl_NtSetInformationProcess
+# define PROCESSINFOCLASS IncompleteWinternl_PROCESSINFOCLASS
+# define _PROCESSINFOCLASS IncompleteWinternl_PROCESSINFOCLASS
+# define PROCESS_BASIC_INFORMATION IncompleteWinternl_PROCESS_BASIC_INFORMATION
+# define PPROCESS_BASIC_INFORMATION IncompleteWinternl_PPROCESS_BASIC_INFORMATION
+# define _PROCESS_BASIC_INFORMATION IncompleteWinternl_PROCESS_BASIC_INFORMATION
+# define ProcessBasicInformation IncompleteWinternl_ProcessBasicInformation
+# define ProcessDebugPort IncompleteWinternl_ProcessDebugPort
+# define ProcessWow64Information IncompleteWinternl_ProcessWow64Information
+# define ProcessImageFileName IncompleteWinternl_ProcessImageFileName
+# define ProcessBreakOnTermination IncompleteWinternl_ProcessBreakOnTermination
+
+# define RTL_USER_PROCESS_PARAMETERS IncompleteWinternl_RTL_USER_PROCESS_PARAMETERS
+# define PRTL_USER_PROCESS_PARAMETERS IncompleteWinternl_PRTL_USER_PROCESS_PARAMETERS
+# define _RTL_USER_PROCESS_PARAMETERS IncompleteWinternl__RTL_USER_PROCESS_PARAMETERS
+
+# define NtQueryInformationThread IncompleteWinternl_NtQueryInformationThread
+# define NtSetInformationThread IncompleteWinternl_NtSetInformationThread
+# define THREADINFOCLASS IncompleteWinternl_THREADINFOCLASS
+# define _THREADINFOCLASS IncompleteWinternl_THREADINFOCLASS
+# define ThreadIsIoPending IncompleteWinternl_ThreadIsIoPending
+
+# define NtQuerySystemInformation IncompleteWinternl_NtQuerySystemInformation
+# define NtSetSystemInformation IncompleteWinternl_NtSetSystemInformation
+# define NtQueryTimerResolution AddedRecentlyUseOwnPrototype_NtQueryTimerResolution
+# define SYSTEM_INFORMATION_CLASS IncompleteWinternl_SYSTEM_INFORMATION_CLASS
+# define _SYSTEM_INFORMATION_CLASS IncompleteWinternl_SYSTEM_INFORMATION_CLASS
+# define SystemBasicInformation IncompleteWinternl_SystemBasicInformation
+# define SystemPerformanceInformation IncompleteWinternl_SystemPerformanceInformation
+# define SystemTimeOfDayInformation IncompleteWinternl_SystemTimeOfDayInformation
+# define SystemProcessInformation IncompleteWinternl_SystemProcessInformation
+# define SystemProcessorPerformanceInformation IncompleteWinternl_SystemProcessorPerformanceInformation
+# define SystemInterruptInformation IncompleteWinternl_SystemInterruptInformation
+# define SystemExceptionInformation IncompleteWinternl_SystemExceptionInformation
+# define SystemRegistryQuotaInformation IncompleteWinternl_SystemRegistryQuotaInformation
+# define SystemLookasideInformation IncompleteWinternl_SystemLookasideInformation
+# define SystemPolicyInformation IncompleteWinternl_SystemPolicyInformation
+
+
+# pragma warning(push)
+# pragma warning(disable: 4668)
+# define WIN32_NO_STATUS
+# include <windef.h>
+# include <winnt.h>
+# include <winternl.h>
+# undef WIN32_NO_STATUS
+# include <ntstatus.h>
+# pragma warning(pop)
+
+# ifndef OBJ_DONT_REPARSE
+# define RTNT_NEED_CLIENT_ID
+# endif
+
+# undef _FILE_INFORMATION_CLASS
+# undef FILE_INFORMATION_CLASS
+# undef FileDirectoryInformation
+
+# undef NtQueryInformationProcess
+# undef NtSetInformationProcess
+# undef PROCESSINFOCLASS
+# undef _PROCESSINFOCLASS
+# undef PROCESS_BASIC_INFORMATION
+# undef PPROCESS_BASIC_INFORMATION
+# undef _PROCESS_BASIC_INFORMATION
+# undef ProcessBasicInformation
+# undef ProcessDebugPort
+# undef ProcessWow64Information
+# undef ProcessImageFileName
+# undef ProcessBreakOnTermination
+
+# undef RTL_USER_PROCESS_PARAMETERS
+# undef PRTL_USER_PROCESS_PARAMETERS
+# undef _RTL_USER_PROCESS_PARAMETERS
+
+# undef NtQueryInformationThread
+# undef NtSetInformationThread
+# undef THREADINFOCLASS
+# undef _THREADINFOCLASS
+# undef ThreadIsIoPending
+
+# undef NtQuerySystemInformation
+# undef NtSetSystemInformation
+# undef NtQueryTimerResolution
+# undef SYSTEM_INFORMATION_CLASS
+# undef _SYSTEM_INFORMATION_CLASS
+# undef SystemBasicInformation
+# undef SystemPerformanceInformation
+# undef SystemTimeOfDayInformation
+# undef SystemProcessInformation
+# undef SystemProcessorPerformanceInformation
+# undef SystemInterruptInformation
+# undef SystemExceptionInformation
+# undef SystemRegistryQuotaInformation
+# undef SystemLookasideInformation
+# undef SystemPolicyInformation
+
+# define RTNT_NEED_NT_GET_PRODUCT_TYPE
+
+#else
+/*
+ * Use ntifs.h and wdm.h.
+ */
+# if _MSC_VER >= 1200 /* Fix/workaround for KeInitializeSpinLock visibility issue on AMD64. */
+# define FORCEINLINE static __forceinline
+# else
+# define FORCEINLINE static __inline
+# endif
+
+# define _FSINFOCLASS OutdatedWdm_FSINFOCLASS
+# define FS_INFORMATION_CLASS OutdatedWdm_FS_INFORMATION_CLASS
+# define PFS_INFORMATION_CLASS OutdatedWdm_PFS_INFORMATION_CLASS
+# define FileFsVolumeInformation OutdatedWdm_FileFsVolumeInformation
+# define FileFsLabelInformation OutdatedWdm_FileFsLabelInformation
+# define FileFsSizeInformation OutdatedWdm_FileFsSizeInformation
+# define FileFsDeviceInformation OutdatedWdm_FileFsDeviceInformation
+# define FileFsAttributeInformation OutdatedWdm_FileFsAttributeInformation
+# define FileFsControlInformation OutdatedWdm_FileFsControlInformation
+# define FileFsFullSizeInformation OutdatedWdm_FileFsFullSizeInformation
+# define FileFsObjectIdInformation OutdatedWdm_FileFsObjectIdInformation
+# define FileFsDriverPathInformation OutdatedWdm_FileFsDriverPathInformation
+# define FileFsVolumeFlagsInformation OutdatedWdm_FileFsVolumeFlagsInformation
+# define FileFsSectorSizeInformation OutdatedWdm_FileFsSectorSizeInformation
+# define FileFsDataCopyInformation OutdatedWdm_FileFsDataCopyInformation
+# define FileFsMetadataSizeInformation OutdatedWdm_FileFsMetadataSizeInformation
+# define FileFsFullSizeInformationEx OutdatedWdm_FileFsFullSizeInformationEx
+# define FileFsMaximumInformation OutdatedWdm_FileFsMaximumInformation
+# define NtQueryVolumeInformationFile OutdatedWdm_NtQueryVolumeInformationFile
+# define NtSetVolumeInformationFile OutdatedWdm_NtSetVolumeInformationFile
+# define _MEMORY_INFORMATION_CLASS OutdatedWdm__MEMORY_INFORMATION_CLASS
+# define MEMORY_INFORMATION_CLASS OutdatedWdm_MEMORY_INFORMATION_CLASS
+# define MemoryBasicInformation OutdatedWdm_MemoryBasicInformation
+# define NtQueryVirtualMemory OutdatedWdm_NtQueryVirtualMemory
+
+# pragma warning(push)
+# ifdef RT_ARCH_X86
+# define _InterlockedAddLargeStatistic _InterlockedAddLargeStatistic_StupidDDKVsCompilerCrap
+# pragma warning(disable: 4163)
+# endif
+# pragma warning(disable: 4668)
+# pragma warning(disable: 4255) /* warning C4255: 'ObGetFilterVersion' : no function prototype given: converting '()' to '(void)' */
+# if _MSC_VER >= 1800 /*RT_MSC_VER_VC120*/
+# pragma warning(disable:4005) /* sdk/v7.1/include/sal_supp.h(57) : warning C4005: '__useHeader' : macro redefinition */
+# pragma warning(disable:4471) /* wdm.h(11057) : warning C4471: '_POOL_TYPE' : a forward declaration of an unscoped enumeration must have an underlying type (int assumed) */
+# endif
+# if _MSC_VER >= 1900 /*RT_MSC_VER_VC140*/
+# ifdef __cplusplus
+# pragma warning(disable:5039) /* warning C5039: 'KeInitializeDpc': pointer or reference to potentially throwing function passed to 'extern "C"' function under -EHc. Undefined behavior may occur if this function throws an exception. */
+# endif
+# endif
+
+# include <ntifs.h>
+# include <wdm.h>
+
+# ifdef RT_ARCH_X86
+# undef _InterlockedAddLargeStatistic
+# endif
+# pragma warning(pop)
+
+# undef _FSINFOCLASS
+# undef FS_INFORMATION_CLASS
+# undef PFS_INFORMATION_CLASS
+# undef FileFsVolumeInformation
+# undef FileFsLabelInformation
+# undef FileFsSizeInformation
+# undef FileFsDeviceInformation
+# undef FileFsAttributeInformation
+# undef FileFsControlInformation
+# undef FileFsFullSizeInformation
+# undef FileFsObjectIdInformation
+# undef FileFsDriverPathInformation
+# undef FileFsVolumeFlagsInformation
+# undef FileFsSectorSizeInformation
+# undef FileFsDataCopyInformation
+# undef FileFsMetadataSizeInformation
+# undef FileFsFullSizeInformationEx
+# undef FileFsMaximumInformation
+# undef NtQueryVolumeInformationFile
+# undef NtSetVolumeInformationFile
+# undef _MEMORY_INFORMATION_CLASS
+# undef MEMORY_INFORMATION_CLASS
+# undef MemoryBasicInformation
+# undef NtQueryVirtualMemory
+
+# define IPRT_NT_NEED_API_GROUP_NTIFS
+# ifndef NTDDI_WIN10_RS1
+# define RTNT_NEED_NT_GET_PRODUCT_TYPE
+# elif NTDDI_VERSION < NTDDI_WIN10_RS1
+# define RTNT_NEED_NT_GET_PRODUCT_TYPE
+# endif
+
+#endif
+
+#undef RtlFreeUnicodeString
+#undef NtQueryObject
+#undef ZwQueryObject
+#undef NtSetInformationObject
+#undef _OBJECT_INFORMATION_CLASS
+#undef OBJECT_INFORMATION_CLASS
+#undef ObjectBasicInformation
+#undef ObjectTypeInformation
+#undef _PEB
+#undef PEB
+#undef PPEB
+#undef _TEB
+#undef TEB
+#undef PTEB
+#undef _PEB_LDR_DATA
+#undef PEB_LDR_DATA
+#undef PPEB_LDR_DATA
+#undef _KUSER_SHARED_DATA
+#undef KUSER_SHARED_DATA
+#undef PKUSER_SHARED_DATA
+
+
+#include <iprt/types.h>
+#include <iprt/assert.h>
+
+
+/** @name Useful macros
+ * @{ */
+/** Indicates that we're targeting native NT in the current source. */
+#define RTNT_USE_NATIVE_NT 1
+/** Initializes a IO_STATUS_BLOCK. */
+#define RTNT_IO_STATUS_BLOCK_INITIALIZER { STATUS_FAILED_DRIVER_ENTRY, ~(uintptr_t)42 }
+/** Reinitializes a IO_STATUS_BLOCK. */
+#define RTNT_IO_STATUS_BLOCK_REINIT(a_pIos) \
+ do { (a_pIos)->Status = STATUS_FAILED_DRIVER_ENTRY; (a_pIos)->Information = ~(uintptr_t)42; } while (0)
+/** Similar to INVALID_HANDLE_VALUE in the Windows environment. */
+#define RTNT_INVALID_HANDLE_VALUE ( (HANDLE)~(uintptr_t)0 )
+/** Constant UNICODE_STRING initializer. */
+#define RTNT_CONSTANT_UNISTR(a_String) { sizeof(a_String) - sizeof(WCHAR), sizeof(a_String), (WCHAR *)a_String }
+/** Null UNICODE_STRING initializer. */
+#define RTNT_NULL_UNISTR() { 0, 0, NULL }
+
+/** Declaration wrapper for NT apis.
+ * Adds nothrow. Don't use with callbacks. */
+#define RT_DECL_NTAPI(type) DECL_NOTHROW(NTSYSAPI type NTAPI)
+/** @} */
+
+
+/** @name IPRT helper functions for NT
+ * @{ */
+RT_C_DECLS_BEGIN
+
+RTDECL(int) RTNtPathOpen(const char *pszPath, ACCESS_MASK fDesiredAccess, ULONG fFileAttribs, ULONG fShareAccess,
+ ULONG fCreateDisposition, ULONG fCreateOptions, ULONG fObjAttribs,
+ PHANDLE phHandle, PULONG_PTR puDisposition);
+RTDECL(int) RTNtPathOpenDir(const char *pszPath, ACCESS_MASK fDesiredAccess, ULONG fShareAccess, ULONG fCreateOptions,
+ ULONG fObjAttribs, PHANDLE phHandle, bool *pfObjDir);
+RTDECL(int) RTNtPathOpenDirEx(HANDLE hRootDir, struct _UNICODE_STRING *pNtName, ACCESS_MASK fDesiredAccess,
+ ULONG fShareAccess, ULONG fCreateOptions, ULONG fObjAttribs, PHANDLE phHandle, bool *pfObjDir);
+RTDECL(int) RTNtPathClose(HANDLE hHandle);
+
+/**
+ * Converts a windows-style path to NT format and encoding.
+ *
+ * @returns IPRT status code.
+ * @param pNtName Where to return the NT name. Free using
+ * RTNtPathFree.
+ * @param phRootDir Where to return the root handle, if applicable.
+ * @param pszPath The UTF-8 path.
+ */
+RTDECL(int) RTNtPathFromWinUtf8(struct _UNICODE_STRING *pNtName, PHANDLE phRootDir, const char *pszPath);
+
+/**
+ * Converts a UTF-16 windows-style path to NT format.
+ *
+ * @returns IPRT status code.
+ * @param pNtName Where to return the NT name. Free using
+ * RTNtPathFree.
+ * @param phRootDir Where to return the root handle, if applicable.
+ * @param pwszPath The UTF-16 windows-style path.
+ * @param cwcPath The max length of the windows-style path in
+ * RTUTF16 units. Use RTSTR_MAX if unknown and @a
+ * pwszPath is correctly terminated.
+ */
+RTDECL(int) RTNtPathFromWinUtf16Ex(struct _UNICODE_STRING *pNtName, HANDLE *phRootDir, PCRTUTF16 pwszPath, size_t cwcPath);
+
+/**
+ * How to handle ascent ('..' relative to a root handle).
+ */
+typedef enum RTNTPATHRELATIVEASCENT
+{
+ kRTNtPathRelativeAscent_Invalid = 0,
+ kRTNtPathRelativeAscent_Allow,
+ kRTNtPathRelativeAscent_Fail,
+ kRTNtPathRelativeAscent_Ignore,
+ kRTNtPathRelativeAscent_End,
+ kRTNtPathRelativeAscent_32BitHack = 0x7fffffff
+} RTNTPATHRELATIVEASCENT;
+
+/**
+ * Converts a relative windows-style path to relative NT format and encoding.
+ *
+ * @returns IPRT status code.
+ * @param pNtName Where to return the NT name. Free using
+ * rtTNtPathToNative with phRootDir set to NULL.
+ * @param phRootDir On input, the handle to the directory the path
+ * is relative to. On output, the handle to
+ * specify as root directory in the object
+ * attributes when accessing the path. If
+ * enmAscent is kRTNtPathRelativeAscent_Allow, it
+ * may have been set to NULL.
+ * @param pszPath The relative UTF-8 path.
+ * @param enmAscent How to handle ascent.
+ * @param fMustReturnAbsolute Must convert to an absolute path. This
+ * is necessary if the root dir is a NT directory
+ * object (e.g. /Devices) since they cannot parse
+ * relative paths it seems.
+ */
+RTDECL(int) RTNtPathRelativeFromUtf8(struct _UNICODE_STRING *pNtName, PHANDLE phRootDir, const char *pszPath,
+ RTNTPATHRELATIVEASCENT enmAscent, bool fMustReturnAbsolute);
+
+/**
+ * Ensures that the NT string has sufficient storage to hold @a cwcMin RTUTF16
+ * chars plus a terminator.
+ *
+ * The NT string must have been returned by RTNtPathFromWinUtf8 or
+ * RTNtPathFromWinUtf16Ex.
+ *
+ * @returns IPRT status code.
+ * @param pNtName The NT path string.
+ * @param cwcMin The minimum number of RTUTF16 chars. Max 32767.
+ * @sa RTNtPathFree
+ */
+RTDECL(int) RTNtPathEnsureSpace(struct _UNICODE_STRING *pNtName, size_t cwcMin);
+
+/**
+ * Gets the NT path to the object represented by the given handle.
+ *
+ * @returns IPRT status code.
+ * @param pNtName Where to return the NT path. Free using
+ * RTNtPathFree.
+ * @param hHandle The handle.
+ * @param cwcExtra How much extra space is needed.
+ */
+RTDECL(int) RTNtPathFromHandle(struct _UNICODE_STRING *pNtName, HANDLE hHandle, size_t cwcExtra);
+
+/**
+ * Frees the native path and root handle.
+ *
+ * @param pNtName The NT path after a successful rtNtPathToNative
+ * call or RTNtPathRelativeFromUtf8.
+ * @param phRootDir The root handle variable from rtNtPathToNative,
+ */
+RTDECL(void) RTNtPathFree(struct _UNICODE_STRING *pNtName, HANDLE *phRootDir);
+
+
+/**
+ * Checks whether the path could be containing alternative 8.3 names generated
+ * by NTFS, FAT, or other similar file systems.
+ *
+ * @returns Pointer to the first component that might be an 8.3 name, NULL if
+ * not 8.3 path.
+ * @param pwszPath The path to check.
+ *
+ * @remarks This is making bad ASSUMPTION wrt to the naming scheme of 8.3 names,
+ * however, non-tilde 8.3 aliases are probably rare enough to not be
+ * worth all the extra code necessary to open each path component and
+ * check if we've got the short name or not.
+ */
+RTDECL(PRTUTF16) RTNtPathFindPossible8dot3Name(PCRTUTF16 pwszPath);
+
+/**
+ * Fixes up a path possibly containing one or more alternative 8-dot-3 style
+ * components.
+ *
+ * The path is fixed up in place. Errors are ignored.
+ *
+ * @returns VINF_SUCCESS if it all went smoothly, informational status codes
+ * indicating the nature of last problem we ran into.
+ *
+ * @param pUniStr The path to fix up. MaximumLength is the max buffer
+ * length.
+ * @param fPathOnly Whether to only process the path and leave the filename
+ * as passed in.
+ */
+RTDECL(int) RTNtPathExpand8dot3Path(struct _UNICODE_STRING *pUniStr, bool fPathOnly);
+
+/**
+ * Wrapper around RTNtPathExpand8dot3Path that allocates a buffer instead of
+ * working on the input buffer.
+ *
+ * @returns IPRT status code, see RTNtPathExpand8dot3Path().
+ * @param pUniStrSrc The path to fix up. MaximumLength is the max buffer
+ * length.
+ * @param fPathOnly Whether to only process the path and leave the filename
+ * as passed in.
+ * @param pUniStrDst Output string. On success, the caller must use
+ * RTUtf16Free to free what the Buffer member points to.
+ * This is all zeros and NULL on failure.
+ */
+RTDECL(int) RTNtPathExpand8dot3PathA(struct _UNICODE_STRING const *pUniStrSrc, bool fPathOnly, struct _UNICODE_STRING *pUniStrDst);
+
+
+RT_C_DECLS_END
+/** @} */
+
+
+/** @name NT API delcarations.
+ * @{ */
+RT_C_DECLS_BEGIN
+
+/** @name Process access rights missing in ntddk headers
+ * @{ */
+#ifndef PROCESS_TERMINATE
+# define PROCESS_TERMINATE UINT32_C(0x00000001)
+#endif
+#ifndef PROCESS_CREATE_THREAD
+# define PROCESS_CREATE_THREAD UINT32_C(0x00000002)
+#endif
+#ifndef PROCESS_SET_SESSIONID
+# define PROCESS_SET_SESSIONID UINT32_C(0x00000004)
+#endif
+#ifndef PROCESS_VM_OPERATION
+# define PROCESS_VM_OPERATION UINT32_C(0x00000008)
+#endif
+#ifndef PROCESS_VM_READ
+# define PROCESS_VM_READ UINT32_C(0x00000010)
+#endif
+#ifndef PROCESS_VM_WRITE
+# define PROCESS_VM_WRITE UINT32_C(0x00000020)
+#endif
+#ifndef PROCESS_DUP_HANDLE
+# define PROCESS_DUP_HANDLE UINT32_C(0x00000040)
+#endif
+#ifndef PROCESS_CREATE_PROCESS
+# define PROCESS_CREATE_PROCESS UINT32_C(0x00000080)
+#endif
+#ifndef PROCESS_SET_QUOTA
+# define PROCESS_SET_QUOTA UINT32_C(0x00000100)
+#endif
+#ifndef PROCESS_SET_INFORMATION
+# define PROCESS_SET_INFORMATION UINT32_C(0x00000200)
+#endif
+#ifndef PROCESS_QUERY_INFORMATION
+# define PROCESS_QUERY_INFORMATION UINT32_C(0x00000400)
+#endif
+#ifndef PROCESS_SUSPEND_RESUME
+# define PROCESS_SUSPEND_RESUME UINT32_C(0x00000800)
+#endif
+#ifndef PROCESS_QUERY_LIMITED_INFORMATION
+# define PROCESS_QUERY_LIMITED_INFORMATION UINT32_C(0x00001000)
+#endif
+#ifndef PROCESS_SET_LIMITED_INFORMATION
+# define PROCESS_SET_LIMITED_INFORMATION UINT32_C(0x00002000)
+#endif
+#define PROCESS_UNKNOWN_4000 UINT32_C(0x00004000)
+#define PROCESS_UNKNOWN_6000 UINT32_C(0x00008000)
+#ifndef PROCESS_ALL_ACCESS
+# define PROCESS_ALL_ACCESS ( STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | UINT32_C(0x0000ffff) )
+#endif
+/** @} */
+
+/** @name Thread access rights missing in ntddk headers
+ * @{ */
+#ifndef THREAD_QUERY_INFORMATION
+# define THREAD_QUERY_INFORMATION UINT32_C(0x00000040)
+#endif
+#ifndef THREAD_SET_THREAD_TOKEN
+# define THREAD_SET_THREAD_TOKEN UINT32_C(0x00000080)
+#endif
+#ifndef THREAD_IMPERSONATE
+# define THREAD_IMPERSONATE UINT32_C(0x00000100)
+#endif
+#ifndef THREAD_DIRECT_IMPERSONATION
+# define THREAD_DIRECT_IMPERSONATION UINT32_C(0x00000200)
+#endif
+#ifndef THREAD_RESUME
+# define THREAD_RESUME UINT32_C(0x00001000)
+#endif
+#define THREAD_UNKNOWN_2000 UINT32_C(0x00002000)
+#define THREAD_UNKNOWN_4000 UINT32_C(0x00004000)
+#define THREAD_UNKNOWN_8000 UINT32_C(0x00008000)
+/** @} */
+
+/** @name Special handle values.
+ * @{ */
+#ifndef NtCurrentProcess
+# define NtCurrentProcess() ( (HANDLE)-(intptr_t)1 )
+#endif
+#ifndef NtCurrentThread
+# define NtCurrentThread() ( (HANDLE)-(intptr_t)2 )
+#endif
+#ifndef ZwCurrentProcess
+# define ZwCurrentProcess() NtCurrentProcess()
+#endif
+#ifndef ZwCurrentThread
+# define ZwCurrentThread() NtCurrentThread()
+#endif
+/** @} */
+
+
+/** @name Directory object access rights.
+ * @{ */
+#ifndef DIRECTORY_QUERY
+# define DIRECTORY_QUERY UINT32_C(0x00000001)
+#endif
+#ifndef DIRECTORY_TRAVERSE
+# define DIRECTORY_TRAVERSE UINT32_C(0x00000002)
+#endif
+#ifndef DIRECTORY_CREATE_OBJECT
+# define DIRECTORY_CREATE_OBJECT UINT32_C(0x00000004)
+#endif
+#ifndef DIRECTORY_CREATE_SUBDIRECTORY
+# define DIRECTORY_CREATE_SUBDIRECTORY UINT32_C(0x00000008)
+#endif
+#ifndef DIRECTORY_ALL_ACCESS
+# define DIRECTORY_ALL_ACCESS ( STANDARD_RIGHTS_REQUIRED | UINT32_C(0x0000000f) )
+#endif
+/** @} */
+
+
+
+#ifdef RTNT_NEED_CLIENT_ID
+typedef struct _CLIENT_ID
+{
+ HANDLE UniqueProcess;
+ HANDLE UniqueThread;
+} CLIENT_ID;
+#endif
+#ifdef IPRT_NT_USE_WINTERNL
+typedef CLIENT_ID *PCLIENT_ID;
+#endif
+
+/** Extended affinity type, introduced in Windows 7 (?). */
+typedef struct _KAFFINITY_EX
+{
+ /** Count of valid bitmap entries. */
+ uint16_t Count;
+ /** Count of allocated bitmap entries. */
+ uint16_t Size;
+ /** Reserved / aligmment padding. */
+ uint32_t Reserved;
+ /** Bitmap where one bit corresponds to a CPU.
+ * @note Started at 20 entries. W10 20H2 increased it to 32. Must be
+ * probed by passing a big buffer to KeInitializeAffinityEx and check
+ * the Size afterwards. */
+ uintptr_t Bitmap[RT_FLEXIBLE_ARRAY_IN_NESTED_UNION];
+} KAFFINITY_EX;
+typedef KAFFINITY_EX *PKAFFINITY_EX;
+typedef KAFFINITY_EX const *PCKAFFINITY_EX;
+
+/** @name User Shared Data
+ * @{ */
+
+#ifdef IPRT_NT_USE_WINTERNL
+typedef struct _KSYSTEM_TIME
+{
+ ULONG LowPart;
+ LONG High1Time;
+ LONG High2Time;
+} KSYSTEM_TIME;
+typedef KSYSTEM_TIME *PKSYSTEM_TIME;
+
+typedef enum _NT_PRODUCT_TYPE
+{
+ NtProductWinNt = 1,
+ NtProductLanManNt,
+ NtProductServer
+} NT_PRODUCT_TYPE;
+
+#define PROCESSOR_FEATURE_MAX 64
+
+typedef enum _ALTERNATIVE_ARCHITECTURE_TYPE
+{
+ StandardDesign = 0,
+ NEC98x86,
+ EndAlternatives
+} ALTERNATIVE_ARCHITECTURE_TYPE;
+
+# if 0
+typedef struct _XSTATE_FEATURE
+{
+ ULONG Offset;
+ ULONG Size;
+} XSTATE_FEATURE;
+typedef XSTATE_FEATURE *PXSTATE_FEATURE;
+
+#define MAXIMUM_XSTATE_FEATURES 64
+
+typedef struct _XSTATE_CONFIGURATION
+{
+ ULONG64 EnabledFeatures;
+ ULONG Size;
+ ULONG OptimizedSave : 1;
+ XSTATE_FEATURE Features[MAXIMUM_XSTATE_FEATURES];
+} XSTATE_CONFIGURATION;
+typedef XSTATE_CONFIGURATION *PXSTATE_CONFIGURATION;
+# endif
+#endif /* IPRT_NT_USE_WINTERNL */
+
+typedef struct _KUSER_SHARED_DATA
+{
+ ULONG TickCountLowDeprecated; /**< 0x000 */
+ ULONG TickCountMultiplier; /**< 0x004 */
+ KSYSTEM_TIME volatile InterruptTime; /**< 0x008 */
+ KSYSTEM_TIME volatile SystemTime; /**< 0x014 */
+ KSYSTEM_TIME volatile TimeZoneBias; /**< 0x020 */
+ USHORT ImageNumberLow; /**< 0x02c */
+ USHORT ImageNumberHigh; /**< 0x02e */
+ WCHAR NtSystemRoot[260]; /**< 0x030 - Seems to be last member in NT 3.51. */
+ ULONG MaxStackTraceDepth; /**< 0x238 */
+ ULONG CryptoExponent; /**< 0x23c */
+ ULONG TimeZoneId; /**< 0x240 */
+ ULONG LargePageMinimum; /**< 0x244 */
+ ULONG AitSamplingValue; /**< 0x248 */
+ ULONG AppCompatFlag; /**< 0x24c */
+ ULONGLONG RNGSeedVersion; /**< 0x250 */
+ ULONG GlobalValidationRunlevel; /**< 0x258 */
+ LONG volatile TimeZoneBiasStamp; /**< 0x25c*/
+ ULONG Reserved2; /**< 0x260 */
+ NT_PRODUCT_TYPE NtProductType; /**< 0x264 */
+ BOOLEAN ProductTypeIsValid; /**< 0x268 */
+ BOOLEAN Reserved0[1]; /**< 0x269 */
+ USHORT NativeProcessorArchitecture; /**< 0x26a */
+ ULONG NtMajorVersion; /**< 0x26c */
+ ULONG NtMinorVersion; /**< 0x270 */
+ BOOLEAN ProcessorFeatures[PROCESSOR_FEATURE_MAX]; /**< 0x274 */
+ ULONG Reserved1; /**< 0x2b4 */
+ ULONG Reserved3; /**< 0x2b8 */
+ ULONG volatile TimeSlip; /**< 0x2bc */
+ ALTERNATIVE_ARCHITECTURE_TYPE AlternativeArchitecture; /**< 0x2c0 */
+ ULONG AltArchitecturePad[1]; /**< 0x2c4 */
+ LARGE_INTEGER SystemExpirationDate; /**< 0x2c8 */
+ ULONG SuiteMask; /**< 0x2d0 */
+ BOOLEAN KdDebuggerEnabled; /**< 0x2d4 */
+ union /**< 0x2d5 */
+ {
+ UCHAR MitigationPolicies; /**< 0x2d5 */
+ struct
+ {
+ UCHAR NXSupportPolicy : 2;
+ UCHAR SEHValidationPolicy : 2;
+ UCHAR CurDirDevicesSkippedForDlls : 2;
+ UCHAR Reserved : 2;
+ };
+ };
+ UCHAR Reserved6[2]; /**< 0x2d6 */
+ ULONG volatile ActiveConsoleId; /**< 0x2d8 */
+ ULONG volatile DismountCount; /**< 0x2dc */
+ ULONG ComPlusPackage; /**< 0x2e0 */
+ ULONG LastSystemRITEventTickCount; /**< 0x2e4 */
+ ULONG NumberOfPhysicalPages; /**< 0x2e8 */
+ BOOLEAN SafeBootMode; /**< 0x2ec */
+ UCHAR Reserved12[3]; /**< 0x2ed */
+ union /**< 0x2f0 */
+ {
+ ULONG SharedDataFlags; /**< 0x2f0 */
+ struct
+ {
+ ULONG DbgErrorPortPresent : 1;
+ ULONG DbgElevationEnabled : 1;
+ ULONG DbgVirtEnabled : 1;
+ ULONG DbgInstallerDetectEnabled : 1;
+ ULONG DbgLkgEnabled : 1;
+ ULONG DbgDynProcessorEnabled : 1;
+ ULONG DbgConsoleBrokerEnabled : 1;
+ ULONG DbgSecureBootEnabled : 1;
+ ULONG SpareBits : 24;
+ };
+ };
+ ULONG DataFlagsPad[1]; /**< 0x2f4 */
+ ULONGLONG TestRetInstruction; /**< 0x2f8 */
+ LONGLONG QpcFrequency; /**< 0x300 */
+ ULONGLONG SystemCallPad[3]; /**< 0x308 */
+ union /**< 0x320 */
+ {
+ ULONG64 volatile TickCountQuad; /**< 0x320 */
+ KSYSTEM_TIME volatile TickCount; /**< 0x320 */
+ struct /**< 0x320 */
+ {
+ ULONG ReservedTickCountOverlay[3]; /**< 0x320 */
+ ULONG TickCountPad[1]; /**< 0x32c */
+ };
+ };
+ ULONG Cookie; /**< 0x330 */
+ ULONG CookiePad[1]; /**< 0x334 */
+ LONGLONG ConsoleSessionForegroundProcessId; /**< 0x338 */
+ ULONGLONG TimeUpdateLock; /**< 0x340 */
+ ULONGLONG BaselineSystemTimeQpc; /**< 0x348 */
+ ULONGLONG BaselineInterruptTimeQpc; /**< 0x350 */
+ ULONGLONG QpcSystemTimeIncrement; /**< 0x358 */
+ ULONGLONG QpcInterruptTimeIncrement; /**< 0x360 */
+ ULONG QpcSystemTimeIncrement32; /**< 0x368 */
+ ULONG QpcInterruptTimeIncrement32; /**< 0x36c */
+ UCHAR QpcSystemTimeIncrementShift; /**< 0x370 */
+ UCHAR QpcInterruptTimeIncrementShift; /**< 0x371 */
+ UCHAR Reserved8[14]; /**< 0x372 */
+ USHORT UserModeGlobalLogger[16]; /**< 0x380 */
+ ULONG ImageFileExecutionOptions; /**< 0x3a0 */
+ ULONG LangGenerationCount; /**< 0x3a4 */
+ ULONGLONG Reserved4; /**< 0x3a8 */
+ ULONGLONG volatile InterruptTimeBias; /**< 0x3b0 - What QueryUnbiasedInterruptTimePrecise
+ * subtracts from interrupt time. */
+ ULONGLONG volatile QpcBias; /**< 0x3b8 */
+ ULONG volatile ActiveProcessorCount; /**< 0x3c0 */
+ UCHAR volatile ActiveGroupCount; /**< 0x3c4 */
+ UCHAR Reserved9; /**< 0x3c5 */
+ union /**< 0x3c6 */
+ {
+ USHORT QpcData; /**< 0x3c6 */
+ struct /**< 0x3c6 */
+ {
+ BOOLEAN volatile QpcBypassEnabled; /**< 0x3c6 */
+ UCHAR QpcShift; /**< 0x3c7 */
+ };
+ };
+ LARGE_INTEGER TimeZoneBiasEffectiveStart; /**< 0x3c8 */
+ LARGE_INTEGER TimeZoneBiasEffectiveEnd; /**< 0x3d0 */
+ XSTATE_CONFIGURATION XState; /**< 0x3d8 */
+} KUSER_SHARED_DATA;
+typedef KUSER_SHARED_DATA *PKUSER_SHARED_DATA;
+AssertCompileMemberOffset(KUSER_SHARED_DATA, InterruptTime, 0x008);
+AssertCompileMemberOffset(KUSER_SHARED_DATA, SystemTime, 0x014);
+AssertCompileMemberOffset(KUSER_SHARED_DATA, NtSystemRoot, 0x030);
+AssertCompileMemberOffset(KUSER_SHARED_DATA, LargePageMinimum, 0x244);
+AssertCompileMemberOffset(KUSER_SHARED_DATA, Reserved1, 0x2b4);
+AssertCompileMemberOffset(KUSER_SHARED_DATA, TestRetInstruction, 0x2f8);
+AssertCompileMemberOffset(KUSER_SHARED_DATA, Cookie, 0x330);
+AssertCompileMemberOffset(KUSER_SHARED_DATA, ImageFileExecutionOptions, 0x3a0);
+AssertCompileMemberOffset(KUSER_SHARED_DATA, XState, 0x3d8);
+/** @def MM_SHARED_USER_DATA_VA
+ * Read only userland mapping of KUSER_SHARED_DATA. */
+#ifndef MM_SHARED_USER_DATA_VA
+# if ARCH_BITS == 32
+# define MM_SHARED_USER_DATA_VA UINT32_C(0x7ffe0000)
+# elif ARCH_BITS == 64
+# define MM_SHARED_USER_DATA_VA UINT64_C(0x7ffe0000)
+# else
+# error "Unsupported/undefined ARCH_BITS value."
+# endif
+#endif
+/** @def KI_USER_SHARED_DATA
+ * Read write kernel mapping of KUSER_SHARED_DATA. */
+#ifndef KI_USER_SHARED_DATA
+# ifdef RT_ARCH_X86
+# define KI_USER_SHARED_DATA UINT32_C(0xffdf0000)
+# elif defined(RT_ARCH_AMD64)
+# define KI_USER_SHARED_DATA UINT64_C(0xfffff78000000000)
+# else
+# error "PORT ME - KI_USER_SHARED_DATA"
+# endif
+#endif
+/** @} */
+
+
+/** @name Process And Thread Environment Blocks
+ * @{ */
+
+typedef struct _PEB_LDR_DATA
+{
+ uint32_t Length;
+ BOOLEAN Initialized;
+ BOOLEAN Padding[3];
+ HANDLE SsHandle;
+ LIST_ENTRY InLoadOrderModuleList;
+ LIST_ENTRY InMemoryOrderModuleList;
+ LIST_ENTRY InInitializationOrderModuleList;
+ /* End NT4 */
+ LIST_ENTRY *EntryInProgress;
+ BOOLEAN ShutdownInProgress;
+ HANDLE ShutdownThreadId;
+} PEB_LDR_DATA;
+typedef PEB_LDR_DATA *PPEB_LDR_DATA;
+
+typedef struct _PEB_COMMON
+{
+ BOOLEAN InheritedAddressSpace; /**< 0x000 / 0x000 */
+ BOOLEAN ReadImageFileExecOptions; /**< 0x001 / 0x001 */
+ BOOLEAN BeingDebugged; /**< 0x002 / 0x002 */
+ union
+ {
+ uint8_t BitField; /**< 0x003 / 0x003 */
+ struct
+ {
+ uint8_t ImageUsesLargePages : 1; /**< 0x003 / 0x003 : Pos 0, 1 Bit */
+ } Common;
+ struct
+ {
+ uint8_t ImageUsesLargePages : 1; /**< 0x003 / 0x003 : Pos 0, 1 Bit */
+ uint8_t IsProtectedProcess : 1; /**< 0x003 / 0x003 : Pos 1, 1 Bit */
+ uint8_t IsImageDynamicallyRelocated : 1; /**< 0x003 / 0x003 : Pos 2, 1 Bit - Differs from W80 */
+ uint8_t SkipPatchingUser32Forwarders : 1; /**< 0x003 / 0x003 : Pos 3, 1 Bit - Differs from W80 */
+ uint8_t IsPackagedProcess : 1; /**< 0x003 / 0x003 : Pos 4, 1 Bit - Differs from W80 */
+ uint8_t IsAppContainer : 1; /**< 0x003 / 0x003 : Pos 5, 1 Bit - Differs from W80 */
+ uint8_t IsProtectedProcessLight : 1; /**< 0x003 / 0x003 : Pos 6, 1 Bit - Differs from W80 */
+ uint8_t SpareBits : 1; /**< 0x003 / 0x003 : Pos 7, 1 Bit */
+ } W81;
+ struct
+ {
+ uint8_t ImageUsesLargePages : 1; /**< 0x003 / 0x003 : Pos 0, 1 Bit */
+ uint8_t IsProtectedProcess : 1; /**< 0x003 / 0x003 : Pos 1, 1 Bit */
+ uint8_t IsLegacyProcess : 1; /**< 0x003 / 0x003 : Pos 2, 1 Bit - Differs from W81 */
+ uint8_t IsImageDynamicallyRelocated : 1; /**< 0x003 / 0x003 : Pos 3, 1 Bit - Differs from W81 */
+ uint8_t SkipPatchingUser32Forwarders : 1; /**< 0x003 / 0x003 : Pos 4, 1 Bit - Differs from W81 */
+ uint8_t IsPackagedProcess : 1; /**< 0x003 / 0x003 : Pos 5, 1 Bit - Differs from W81 */
+ uint8_t IsAppContainer : 1; /**< 0x003 / 0x003 : Pos 6, 1 Bit - Differs from W81 */
+ uint8_t SpareBits : 1; /**< 0x003 / 0x003 : Pos 7, 1 Bit */
+ } W80;
+ struct
+ {
+ uint8_t ImageUsesLargePages : 1; /**< 0x003 / 0x003 : Pos 0, 1 Bit */
+ uint8_t IsProtectedProcess : 1; /**< 0x003 / 0x003 : Pos 1, 1 Bit */
+ uint8_t IsLegacyProcess : 1; /**< 0x003 / 0x003 : Pos 2, 1 Bit - Differs from W81, same as W80 & W6. */
+ uint8_t IsImageDynamicallyRelocated : 1; /**< 0x003 / 0x003 : Pos 3, 1 Bit - Differs from W81, same as W80 & W6. */
+ uint8_t SkipPatchingUser32Forwarders : 1; /**< 0x003 / 0x003 : Pos 4, 1 Bit - Added in W7; Differs from W81, same as W80. */
+ uint8_t SpareBits : 3; /**< 0x003 / 0x003 : Pos 5, 3 Bit - Differs from W81 & W80, more spare bits. */
+ } W7;
+ struct
+ {
+ uint8_t ImageUsesLargePages : 1; /**< 0x003 / 0x003 : Pos 0, 1 Bit */
+ uint8_t IsProtectedProcess : 1; /**< 0x003 / 0x003 : Pos 1, 1 Bit */
+ uint8_t IsLegacyProcess : 1; /**< 0x003 / 0x003 : Pos 2, 1 Bit - Differs from W81, same as W80 & W7. */
+ uint8_t IsImageDynamicallyRelocated : 1; /**< 0x003 / 0x003 : Pos 3, 1 Bit - Differs from W81, same as W80 & W7. */
+ uint8_t SpareBits : 4; /**< 0x003 / 0x003 : Pos 4, 4 Bit - Differs from W81, W80, & W7, more spare bits. */
+ } W6;
+ struct
+ {
+ uint8_t ImageUsesLargePages : 1; /**< 0x003 / 0x003 : Pos 0, 1 Bit */
+ uint8_t SpareBits : 7; /**< 0x003 / 0x003 : Pos 1, 7 Bit - Differs from W81, W80, & W7, more spare bits. */
+ } W52;
+ struct
+ {
+ BOOLEAN SpareBool;
+ } W51;
+ } Diff0;
+#if ARCH_BITS == 64
+ uint32_t Padding0; /**< 0x004 / NA */
+#endif
+ HANDLE Mutant; /**< 0x008 / 0x004 */
+ PVOID ImageBaseAddress; /**< 0x010 / 0x008 */
+ PPEB_LDR_DATA Ldr; /**< 0x018 / 0x00c */
+ struct _RTL_USER_PROCESS_PARAMETERS *ProcessParameters; /**< 0x020 / 0x010 */
+ PVOID SubSystemData; /**< 0x028 / 0x014 */
+ HANDLE ProcessHeap; /**< 0x030 / 0x018 */
+ struct _RTL_CRITICAL_SECTION *FastPebLock; /**< 0x038 / 0x01c */
+ union
+ {
+ struct
+ {
+ PVOID AtlThunkSListPtr; /**< 0x040 / 0x020 */
+ PVOID IFEOKey; /**< 0x048 / 0x024 */
+ union
+ {
+ ULONG CrossProcessFlags; /**< 0x050 / 0x028 */
+ struct
+ {
+ uint32_t ProcessInJob : 1; /**< 0x050 / 0x028: Pos 0, 1 Bit */
+ uint32_t ProcessInitializing : 1; /**< 0x050 / 0x028: Pos 1, 1 Bit */
+ uint32_t ProcessUsingVEH : 1; /**< 0x050 / 0x028: Pos 2, 1 Bit */
+ uint32_t ProcessUsingVCH : 1; /**< 0x050 / 0x028: Pos 3, 1 Bit */
+ uint32_t ProcessUsingFTH : 1; /**< 0x050 / 0x028: Pos 4, 1 Bit */
+ uint32_t ReservedBits0 : 1; /**< 0x050 / 0x028: Pos 5, 27 Bits */
+ } W7, W8, W80, W81;
+ struct
+ {
+ uint32_t ProcessInJob : 1; /**< 0x050 / 0x028: Pos 0, 1 Bit */
+ uint32_t ProcessInitializing : 1; /**< 0x050 / 0x028: Pos 1, 1 Bit */
+ uint32_t ReservedBits0 : 30; /**< 0x050 / 0x028: Pos 2, 30 Bits */
+ } W6;
+ };
+#if ARCH_BITS == 64
+ uint32_t Padding1; /**< 0x054 / */
+#endif
+ } W6, W7, W8, W80, W81;
+ struct
+ {
+ PVOID AtlThunkSListPtr; /**< 0x040 / 0x020 */
+ PVOID SparePtr2; /**< 0x048 / 0x024 */
+ uint32_t EnvironmentUpdateCount; /**< 0x050 / 0x028 */
+#if ARCH_BITS == 64
+ uint32_t Padding1; /**< 0x054 / */
+#endif
+ } W52;
+ struct
+ {
+ PVOID FastPebLockRoutine; /**< NA / 0x020 */
+ PVOID FastPebUnlockRoutine; /**< NA / 0x024 */
+ uint32_t EnvironmentUpdateCount; /**< NA / 0x028 */
+ } W51;
+ } Diff1;
+ union
+ {
+ PVOID KernelCallbackTable; /**< 0x058 / 0x02c */
+ PVOID UserSharedInfoPtr; /**< 0x058 / 0x02c - Alternative use in W6.*/
+ };
+ uint32_t SystemReserved; /**< 0x060 / 0x030 */
+ union
+ {
+ struct
+ {
+ uint32_t AtlThunkSListPtr32; /**< 0x064 / 0x034 */
+ } W7, W8, W80, W81;
+ struct
+ {
+ uint32_t SpareUlong; /**< 0x064 / 0x034 */
+ } W52, W6;
+ struct
+ {
+ uint32_t ExecuteOptions : 2; /**< NA / 0x034: Pos 0, 2 Bits */
+ uint32_t SpareBits : 30; /**< NA / 0x034: Pos 2, 30 Bits */
+ } W51;
+ } Diff2;
+ union
+ {
+ struct
+ {
+ PVOID ApiSetMap; /**< 0x068 / 0x038 */
+ } W7, W8, W80, W81;
+ struct
+ {
+ struct _PEB_FREE_BLOCK *FreeList; /**< 0x068 / 0x038 */
+ } W52, W6;
+ struct
+ {
+ struct _PEB_FREE_BLOCK *FreeList; /**< NA / 0x038 */
+ } W51;
+ } Diff3;
+ uint32_t TlsExpansionCounter; /**< 0x070 / 0x03c */
+#if ARCH_BITS == 64
+ uint32_t Padding2; /**< 0x074 / NA */
+#endif
+ struct _RTL_BITMAP *TlsBitmap; /**< 0x078 / 0x040 */
+ uint32_t TlsBitmapBits[2]; /**< 0x080 / 0x044 */
+ PVOID ReadOnlySharedMemoryBase; /**< 0x088 / 0x04c */
+ union
+ {
+ struct
+ {
+ PVOID SparePvoid0; /**< 0x090 / 0x050 - HotpatchInformation before W81. */
+ } W81;
+ struct
+ {
+ PVOID HotpatchInformation; /**< 0x090 / 0x050 - Retired in W81. */
+ } W6, W7, W80;
+ struct
+ {
+ PVOID ReadOnlySharedMemoryHeap;
+ } W52;
+ } Diff4;
+ PVOID *ReadOnlyStaticServerData; /**< 0x098 / 0x054 */
+ PVOID AnsiCodePageData; /**< 0x0a0 / 0x058 */
+ PVOID OemCodePageData; /**< 0x0a8 / 0x05c */
+ PVOID UnicodeCaseTableData; /**< 0x0b0 / 0x060 */
+ uint32_t NumberOfProcessors; /**< 0x0b8 / 0x064 */
+ uint32_t NtGlobalFlag; /**< 0x0bc / 0x068 */
+#if ARCH_BITS == 32
+ uint32_t Padding2b;
+#endif
+ LARGE_INTEGER CriticalSectionTimeout; /**< 0x0c0 / 0x070 */
+ SIZE_T HeapSegmentReserve; /**< 0x0c8 / 0x078 */
+ SIZE_T HeapSegmentCommit; /**< 0x0d0 / 0x07c */
+ SIZE_T HeapDeCommitTotalFreeThreshold; /**< 0x0d8 / 0x080 */
+ SIZE_T HeapDeCommitFreeBlockThreshold; /**< 0x0e0 / 0x084 */
+ uint32_t NumberOfHeaps; /**< 0x0e8 / 0x088 */
+ uint32_t MaximumNumberOfHeaps; /**< 0x0ec / 0x08c */
+ PVOID *ProcessHeaps; /**< 0x0f0 / 0x090 - Last NT 3.51 member. */
+ PVOID GdiSharedHandleTable; /**< 0x0f8 / 0x094 */
+ PVOID ProcessStarterHelper; /**< 0x100 / 0x098 */
+ uint32_t GdiDCAttributeList; /**< 0x108 / 0x09c */
+#if ARCH_BITS == 64
+ uint32_t Padding3; /**< 0x10c / NA */
+#endif
+ struct _RTL_CRITICAL_SECTION *LoaderLock; /**< 0x110 / 0x0a0 */
+ uint32_t OSMajorVersion; /**< 0x118 / 0x0a4 */
+ uint32_t OSMinorVersion; /**< 0x11c / 0x0a8 */
+ uint16_t OSBuildNumber; /**< 0x120 / 0x0ac */
+ uint16_t OSCSDVersion; /**< 0x122 / 0x0ae */
+ uint32_t OSPlatformId; /**< 0x124 / 0x0b0 */
+ uint32_t ImageSubsystem; /**< 0x128 / 0x0b4 */
+ uint32_t ImageSubsystemMajorVersion; /**< 0x12c / 0x0b8 */
+ uint32_t ImageSubsystemMinorVersion; /**< 0x130 / 0x0bc */
+#if ARCH_BITS == 64
+ uint32_t Padding4; /**< 0x134 / NA */
+#endif
+ union
+ {
+ struct
+ {
+ SIZE_T ActiveProcessAffinityMask; /**< 0x138 / 0x0c0 */
+ } W7, W8, W80, W81;
+ struct
+ {
+ SIZE_T ImageProcessAffinityMask; /**< 0x138 / 0x0c0 */
+ } W52, W6;
+ } Diff5;
+ uint32_t GdiHandleBuffer[ARCH_BITS == 64 ? 60 : 34]; /**< 0x140 / 0x0c4 */
+ PVOID PostProcessInitRoutine; /**< 0x230 / 0x14c */
+ PVOID TlsExpansionBitmap; /**< 0x238 / 0x150 */
+ uint32_t TlsExpansionBitmapBits[32]; /**< 0x240 / 0x154 */
+ uint32_t SessionId; /**< 0x2c0 / 0x1d4 */
+#if ARCH_BITS == 64
+ uint32_t Padding5; /**< 0x2c4 / NA */
+#endif
+ ULARGE_INTEGER AppCompatFlags; /**< 0x2c8 / 0x1d8 */
+ ULARGE_INTEGER AppCompatFlagsUser; /**< 0x2d0 / 0x1e0 */
+ PVOID pShimData; /**< 0x2d8 / 0x1e8 */
+ PVOID AppCompatInfo; /**< 0x2e0 / 0x1ec */
+ UNICODE_STRING CSDVersion; /**< 0x2e8 / 0x1f0 */
+ struct _ACTIVATION_CONTEXT_DATA *ActivationContextData; /**< 0x2f8 / 0x1f8 */
+ struct _ASSEMBLY_STORAGE_MAP *ProcessAssemblyStorageMap; /**< 0x300 / 0x1fc */
+ struct _ACTIVATION_CONTEXT_DATA *SystemDefaultActivationContextData; /**< 0x308 / 0x200 */
+ struct _ASSEMBLY_STORAGE_MAP *SystemAssemblyStorageMap; /**< 0x310 / 0x204 */
+ SIZE_T MinimumStackCommit; /**< 0x318 / 0x208 */
+ /* End of PEB in W52 (Windows XP (RTM))! */
+ struct _FLS_CALLBACK_INFO *FlsCallback; /**< 0x320 / 0x20c */
+ LIST_ENTRY FlsListHead; /**< 0x328 / 0x210 */
+ PVOID FlsBitmap; /**< 0x338 / 0x218 */
+ uint32_t FlsBitmapBits[4]; /**< 0x340 / 0x21c */
+ uint32_t FlsHighIndex; /**< 0x350 / 0x22c */
+ /* End of PEB in W52 (Windows Server 2003)! */
+ PVOID WerRegistrationData; /**< 0x358 / 0x230 */
+ PVOID WerShipAssertPtr; /**< 0x360 / 0x234 */
+ /* End of PEB in W6 (windows Vista)! */
+ union
+ {
+ struct
+ {
+ PVOID pUnused; /**< 0x368 / 0x238 - Was pContextData in W7. */
+ } W8, W80, W81;
+ struct
+ {
+ PVOID pContextData; /**< 0x368 / 0x238 - Retired in W80. */
+ } W7;
+ } Diff6;
+ PVOID pImageHeaderHash; /**< 0x370 / 0x23c */
+ union
+ {
+ uint32_t TracingFlags; /**< 0x378 / 0x240 */
+ struct
+ {
+ uint32_t HeapTracingEnabled : 1; /**< 0x378 / 0x240 : Pos 0, 1 Bit */
+ uint32_t CritSecTracingEnabled : 1; /**< 0x378 / 0x240 : Pos 1, 1 Bit */
+ uint32_t LibLoaderTracingEnabled : 1; /**< 0x378 / 0x240 : Pos 2, 1 Bit */
+ uint32_t SpareTracingBits : 29; /**< 0x378 / 0x240 : Pos 3, 29 Bits */
+ } W8, W80, W81;
+ struct
+ {
+ uint32_t HeapTracingEnabled : 1; /**< 0x378 / 0x240 : Pos 0, 1 Bit */
+ uint32_t CritSecTracingEnabled : 1; /**< 0x378 / 0x240 : Pos 1, 1 Bit */
+ uint32_t SpareTracingBits : 30; /**< 0x378 / 0x240 : Pos 3, 30 Bits - One bit more than W80 */
+ } W7;
+ } Diff7;
+#if ARCH_BITS == 64
+ uint32_t Padding6; /**< 0x37c / NA */
+#endif
+ uint64_t CsrServerReadOnlySharedMemoryBase; /**< 0x380 / 0x248 */
+ /* End of PEB in W8, W81. */
+ uintptr_t TppWorkerpListLock; /**< 0x388 / 0x250 */
+ LIST_ENTRY TppWorkerpList; /**< 0x390 / 0x254 */
+ PVOID WaitOnAddressHashTable[128]; /**< 0x3a0 / 0x25c */
+#if ARCH_BITS == 32
+ uint32_t ExplicitPadding7; /**< NA NA / 0x45c */
+#endif
+} PEB_COMMON;
+typedef PEB_COMMON *PPEB_COMMON;
+
+AssertCompileMemberOffset(PEB_COMMON, ProcessHeap, ARCH_BITS == 64 ? 0x30 : 0x18);
+AssertCompileMemberOffset(PEB_COMMON, SystemReserved, ARCH_BITS == 64 ? 0x60 : 0x30);
+AssertCompileMemberOffset(PEB_COMMON, TlsExpansionCounter, ARCH_BITS == 64 ? 0x70 : 0x3c);
+AssertCompileMemberOffset(PEB_COMMON, NtGlobalFlag, ARCH_BITS == 64 ? 0xbc : 0x68);
+AssertCompileMemberOffset(PEB_COMMON, LoaderLock, ARCH_BITS == 64 ? 0x110 : 0xa0);
+AssertCompileMemberOffset(PEB_COMMON, Diff5.W52.ImageProcessAffinityMask, ARCH_BITS == 64 ? 0x138 : 0xc0);
+AssertCompileMemberOffset(PEB_COMMON, PostProcessInitRoutine, ARCH_BITS == 64 ? 0x230 : 0x14c);
+AssertCompileMemberOffset(PEB_COMMON, AppCompatFlags, ARCH_BITS == 64 ? 0x2c8 : 0x1d8);
+AssertCompileSize(PEB_COMMON, ARCH_BITS == 64 ? 0x7a0 : 0x460);
+
+/** The size of the windows 10 (build 14393) PEB structure. */
+#define PEB_SIZE_W10 sizeof(PEB_COMMON)
+/** The size of the windows 8.1 PEB structure. */
+#define PEB_SIZE_W81 RT_UOFFSETOF(PEB_COMMON, TppWorkerpListLock)
+/** The size of the windows 8.0 PEB structure. */
+#define PEB_SIZE_W80 RT_UOFFSETOF(PEB_COMMON, TppWorkerpListLock)
+/** The size of the windows 7 PEB structure. */
+#define PEB_SIZE_W7 RT_UOFFSETOF(PEB_COMMON, CsrServerReadOnlySharedMemoryBase)
+/** The size of the windows vista PEB structure. */
+#define PEB_SIZE_W6 RT_UOFFSETOF(PEB_COMMON, Diff3)
+/** The size of the windows server 2003 PEB structure. */
+#define PEB_SIZE_W52 RT_UOFFSETOF(PEB_COMMON, WerRegistrationData)
+/** The size of the windows XP PEB structure. */
+#define PEB_SIZE_W51 RT_UOFFSETOF(PEB_COMMON, FlsCallback)
+
+#if 0
+typedef struct _NT_TIB
+{
+ struct _EXCEPTION_REGISTRATION_RECORD *ExceptionList;
+ PVOID StackBase;
+ PVOID StackLimit;
+ PVOID SubSystemTib;
+ union
+ {
+ PVOID FiberData;
+ ULONG Version;
+ };
+ PVOID ArbitraryUserPointer;
+ struct _NT_TIB *Self;
+} NT_TIB;
+typedef NT_TIB *PNT_TIB;
+#endif
+
+typedef struct _ACTIVATION_CONTEXT_STACK
+{
+ uint32_t Flags;
+ uint32_t NextCookieSequenceNumber;
+ PVOID ActiveFrame;
+ LIST_ENTRY FrameListCache;
+} ACTIVATION_CONTEXT_STACK;
+
+/* Common TEB. */
+typedef struct _TEB_COMMON
+{
+ NT_TIB NtTib; /**< 0x000 / 0x000 */
+ PVOID EnvironmentPointer; /**< 0x038 / 0x01c */
+ CLIENT_ID ClientId; /**< 0x040 / 0x020 */
+ PVOID ActiveRpcHandle; /**< 0x050 / 0x028 */
+ PVOID ThreadLocalStoragePointer; /**< 0x058 / 0x02c */
+ PPEB_COMMON ProcessEnvironmentBlock; /**< 0x060 / 0x030 */
+ uint32_t LastErrorValue; /**< 0x068 / 0x034 */
+ uint32_t CountOfOwnedCriticalSections; /**< 0x06c / 0x038 */
+ PVOID CsrClientThread; /**< 0x070 / 0x03c */
+ PVOID Win32ThreadInfo; /**< 0x078 / 0x040 */
+ uint32_t User32Reserved[26]; /**< 0x080 / 0x044 */
+ uint32_t UserReserved[5]; /**< 0x0e8 / 0x0ac */
+ PVOID WOW32Reserved; /**< 0x100 / 0x0c0 */
+ uint32_t CurrentLocale; /**< 0x108 / 0x0c4 */
+ uint32_t FpSoftwareStatusRegister; /**< 0x10c / 0x0c8 */
+ PVOID SystemReserved1[54]; /**< 0x110 / 0x0cc */
+ uint32_t ExceptionCode; /**< 0x2c0 / 0x1a4 */
+#if ARCH_BITS == 64
+ uint32_t Padding0; /**< 0x2c4 / NA */
+#endif
+ union
+ {
+ struct
+ {
+ struct _ACTIVATION_CONTEXT_STACK *ActivationContextStackPointer;/**< 0x2c8 / 0x1a8 */
+ uint8_t SpareBytes[ARCH_BITS == 64 ? 24 : 36]; /**< 0x2d0 / 0x1ac */
+ } W52, W6, W7, W8, W80, W81;
+#if ARCH_BITS == 32
+ struct
+ {
+ ACTIVATION_CONTEXT_STACK ActivationContextStack; /**< NA / 0x1a8 */
+ uint8_t SpareBytes[20]; /**< NA / 0x1bc */
+ } W51;
+#endif
+ } Diff0;
+ union
+ {
+ struct
+ {
+ uint32_t TxFsContext; /**< 0x2e8 / 0x1d0 */
+ } W6, W7, W8, W80, W81;
+ struct
+ {
+ uint32_t SpareBytesContinues; /**< 0x2e8 / 0x1d0 */
+ } W52;
+ } Diff1;
+#if ARCH_BITS == 64
+ uint32_t Padding1; /**< 0x2ec / NA */
+#endif
+ /*_GDI_TEB_BATCH*/ uint8_t GdiTebBatch[ARCH_BITS == 64 ? 0x4e8 :0x4e0]; /**< 0x2f0 / 0x1d4 */
+ CLIENT_ID RealClientId; /**< 0x7d8 / 0x6b4 */
+ HANDLE GdiCachedProcessHandle; /**< 0x7e8 / 0x6bc */
+ uint32_t GdiClientPID; /**< 0x7f0 / 0x6c0 */
+ uint32_t GdiClientTID; /**< 0x7f4 / 0x6c4 */
+ PVOID GdiThreadLocalInfo; /**< 0x7f8 / 0x6c8 */
+ SIZE_T Win32ClientInfo[62]; /**< 0x800 / 0x6cc */
+ PVOID glDispatchTable[233]; /**< 0x9f0 / 0x7c4 */
+ SIZE_T glReserved1[29]; /**< 0x1138 / 0xb68 */
+ PVOID glReserved2; /**< 0x1220 / 0xbdc */
+ PVOID glSectionInfo; /**< 0x1228 / 0xbe0 */
+ PVOID glSection; /**< 0x1230 / 0xbe4 */
+ PVOID glTable; /**< 0x1238 / 0xbe8 */
+ PVOID glCurrentRC; /**< 0x1240 / 0xbec */
+ PVOID glContext; /**< 0x1248 / 0xbf0 */
+ NTSTATUS LastStatusValue; /**< 0x1250 / 0xbf4 */
+#if ARCH_BITS == 64
+ uint32_t Padding2; /**< 0x1254 / NA */
+#endif
+ UNICODE_STRING StaticUnicodeString; /**< 0x1258 / 0xbf8 */
+ WCHAR StaticUnicodeBuffer[261]; /**< 0x1268 / 0xc00 */
+#if ARCH_BITS == 64
+ WCHAR Padding3[3]; /**< 0x1472 / NA */
+#endif
+ PVOID DeallocationStack; /**< 0x1478 / 0xe0c */
+ PVOID TlsSlots[64]; /**< 0x1480 / 0xe10 */
+ LIST_ENTRY TlsLinks; /**< 0x1680 / 0xf10 */
+ PVOID Vdm; /**< 0x1690 / 0xf18 */
+ PVOID ReservedForNtRpc; /**< 0x1698 / 0xf1c */
+ PVOID DbgSsReserved[2]; /**< 0x16a0 / 0xf20 */
+ uint32_t HardErrorMode; /**< 0x16b0 / 0xf28 - Called HardErrorsAreDisabled in W51. */
+#if ARCH_BITS == 64
+ uint32_t Padding4; /**< 0x16b4 / NA */
+#endif
+ PVOID Instrumentation[ARCH_BITS == 64 ? 11 : 9]; /**< 0x16b8 / 0xf2c */
+ union
+ {
+ struct
+ {
+ GUID ActivityId; /**< 0x1710 / 0xf50 */
+ PVOID SubProcessTag; /**< 0x1720 / 0xf60 */
+ } W6, W7, W8, W80, W81;
+ struct
+ {
+ PVOID InstrumentationContinues[ARCH_BITS == 64 ? 3 : 5]; /**< 0x1710 / 0xf50 */
+ } W52;
+ } Diff2;
+ union /**< 0x1728 / 0xf64 */
+ {
+ struct
+ {
+ PVOID PerflibData; /**< 0x1728 / 0xf64 */
+ } W8, W80, W81;
+ struct
+ {
+ PVOID EtwLocalData; /**< 0x1728 / 0xf64 */
+ } W7, W6;
+ struct
+ {
+ PVOID SubProcessTag; /**< 0x1728 / 0xf64 */
+ } W52;
+ struct
+ {
+ PVOID InstrumentationContinues[1]; /**< 0x1728 / 0xf64 */
+ } W51;
+ } Diff3;
+ union
+ {
+ struct
+ {
+ PVOID EtwTraceData; /**< 0x1730 / 0xf68 */
+ } W52, W6, W7, W8, W80, W81;
+ struct
+ {
+ PVOID InstrumentationContinues[1]; /**< 0x1730 / 0xf68 */
+ } W51;
+ } Diff4;
+ PVOID WinSockData; /**< 0x1738 / 0xf6c */
+ uint32_t GdiBatchCount; /**< 0x1740 / 0xf70 */
+ union
+ {
+ union
+ {
+ PROCESSOR_NUMBER CurrentIdealProcessor; /**< 0x1744 / 0xf74 - W7+ */
+ uint32_t IdealProcessorValue; /**< 0x1744 / 0xf74 - W7+ */
+ struct
+ {
+ uint8_t ReservedPad1; /**< 0x1744 / 0xf74 - Called SpareBool0 in W6 */
+ uint8_t ReservedPad2; /**< 0x1745 / 0xf75 - Called SpareBool0 in W6 */
+ uint8_t ReservedPad3; /**< 0x1746 / 0xf76 - Called SpareBool0 in W6 */
+ uint8_t IdealProcessor; /**< 0x1747 / 0xf77 */
+ };
+ } W6, W7, W8, W80, W81;
+ struct
+ {
+ BOOLEAN InDbgPrint; /**< 0x1744 / 0xf74 */
+ BOOLEAN FreeStackOnTermination; /**< 0x1745 / 0xf75 */
+ BOOLEAN HasFiberData; /**< 0x1746 / 0xf76 */
+ uint8_t IdealProcessor; /**< 0x1747 / 0xf77 */
+ } W51, W52;
+ } Diff5;
+ uint32_t GuaranteedStackBytes; /**< 0x1748 / 0xf78 */
+#if ARCH_BITS == 64
+ uint32_t Padding5; /**< 0x174c / NA */
+#endif
+ PVOID ReservedForPerf; /**< 0x1750 / 0xf7c */
+ PVOID ReservedForOle; /**< 0x1758 / 0xf80 */
+ uint32_t WaitingOnLoaderLock; /**< 0x1760 / 0xf84 */
+#if ARCH_BITS == 64
+ uint32_t Padding6; /**< 0x1764 / NA */
+#endif
+ union /**< 0x1770 / 0xf8c */
+ {
+ struct
+ {
+ PVOID SavedPriorityState; /**< 0x1768 / 0xf88 */
+ SIZE_T ReservedForCodeCoverage; /**< 0x1770 / 0xf8c */
+ PVOID ThreadPoolData; /**< 0x1778 / 0xf90 */
+ } W8, W80, W81;
+ struct
+ {
+ PVOID SavedPriorityState; /**< 0x1768 / 0xf88 */
+ SIZE_T SoftPatchPtr1; /**< 0x1770 / 0xf8c */
+ PVOID ThreadPoolData; /**< 0x1778 / 0xf90 */
+ } W6, W7;
+ struct
+ {
+ PVOID SparePointer1; /**< 0x1768 / 0xf88 */
+ SIZE_T SoftPatchPtr1; /**< 0x1770 / 0xf8c */
+ PVOID SoftPatchPtr2; /**< 0x1778 / 0xf90 */
+ } W52;
+#if ARCH_BITS == 32
+ struct _Wx86ThreadState
+ {
+ PVOID CallBx86Eip; /**< NA / 0xf88 */
+ PVOID DeallocationCpu; /**< NA / 0xf8c */
+ BOOLEAN UseKnownWx86Dll; /**< NA / 0xf90 */
+ int8_t OleStubInvoked; /**< NA / 0xf91 */
+ } W51;
+#endif
+ } Diff6;
+ PVOID TlsExpansionSlots; /**< 0x1780 / 0xf94 */
+#if ARCH_BITS == 64
+ PVOID DallocationBStore; /**< 0x1788 / NA */
+ PVOID BStoreLimit; /**< 0x1790 / NA */
+#endif
+ union
+ {
+ struct
+ {
+ uint32_t MuiGeneration; /**< 0x1798 / 0xf98 */
+ } W7, W8, W80, W81;
+ struct
+ {
+ uint32_t ImpersonationLocale;
+ } W6;
+ } Diff7;
+ uint32_t IsImpersonating; /**< 0x179c / 0xf9c */
+ PVOID NlsCache; /**< 0x17a0 / 0xfa0 */
+ PVOID pShimData; /**< 0x17a8 / 0xfa4 */
+ union /**< 0x17b0 / 0xfa8 */
+ {
+ struct
+ {
+ uint16_t HeapVirtualAffinity; /**< 0x17b0 / 0xfa8 */
+ uint16_t LowFragHeapDataSlot; /**< 0x17b2 / 0xfaa */
+ } W8, W80, W81;
+ struct
+ {
+ uint32_t HeapVirtualAffinity; /**< 0x17b0 / 0xfa8 */
+ } W7;
+ } Diff8;
+#if ARCH_BITS == 64
+ uint32_t Padding7; /**< 0x17b4 / NA */
+#endif
+ HANDLE CurrentTransactionHandle; /**< 0x17b8 / 0xfac */
+ struct _TEB_ACTIVE_FRAME *ActiveFrame; /**< 0x17c0 / 0xfb0 */
+ /* End of TEB in W51 (Windows XP)! */
+ PVOID FlsData; /**< 0x17c8 / 0xfb4 */
+ union
+ {
+ struct
+ {
+ PVOID PreferredLanguages; /**< 0x17d0 / 0xfb8 */
+ } W6, W7, W8, W80, W81;
+ struct
+ {
+ BOOLEAN SafeThunkCall; /**< 0x17d0 / 0xfb8 */
+ uint8_t BooleanSpare[3]; /**< 0x17d1 / 0xfb9 */
+ /* End of TEB in W52 (Windows server 2003)! */
+ } W52;
+ } Diff9;
+ PVOID UserPrefLanguages; /**< 0x17d8 / 0xfbc */
+ PVOID MergedPrefLanguages; /**< 0x17e0 / 0xfc0 */
+ uint32_t MuiImpersonation; /**< 0x17e8 / 0xfc4 */
+ union
+ {
+ uint16_t CrossTebFlags; /**< 0x17ec / 0xfc8 */
+ struct
+ {
+ uint16_t SpareCrossTebBits : 16; /**< 0x17ec / 0xfc8 : Pos 0, 16 Bits */
+ };
+ };
+ union
+ {
+ uint16_t SameTebFlags; /**< 0x17ee / 0xfca */
+ struct
+ {
+ uint16_t SafeThunkCall : 1; /**< 0x17ee / 0xfca : Pos 0, 1 Bit */
+ uint16_t InDebugPrint : 1; /**< 0x17ee / 0xfca : Pos 1, 1 Bit */
+ uint16_t HasFiberData : 1; /**< 0x17ee / 0xfca : Pos 2, 1 Bit */
+ uint16_t SkipThreadAttach : 1; /**< 0x17ee / 0xfca : Pos 3, 1 Bit */
+ uint16_t WerInShipAssertCode : 1; /**< 0x17ee / 0xfca : Pos 4, 1 Bit */
+ uint16_t RanProcessInit : 1; /**< 0x17ee / 0xfca : Pos 5, 1 Bit */
+ uint16_t ClonedThread : 1; /**< 0x17ee / 0xfca : Pos 6, 1 Bit */
+ uint16_t SuppressDebugMsg : 1; /**< 0x17ee / 0xfca : Pos 7, 1 Bit */
+ } Common;
+ struct
+ {
+ uint16_t SafeThunkCall : 1; /**< 0x17ee / 0xfca : Pos 0, 1 Bit */
+ uint16_t InDebugPrint : 1; /**< 0x17ee / 0xfca : Pos 1, 1 Bit */
+ uint16_t HasFiberData : 1; /**< 0x17ee / 0xfca : Pos 2, 1 Bit */
+ uint16_t SkipThreadAttach : 1; /**< 0x17ee / 0xfca : Pos 3, 1 Bit */
+ uint16_t WerInShipAssertCode : 1; /**< 0x17ee / 0xfca : Pos 4, 1 Bit */
+ uint16_t RanProcessInit : 1; /**< 0x17ee / 0xfca : Pos 5, 1 Bit */
+ uint16_t ClonedThread : 1; /**< 0x17ee / 0xfca : Pos 6, 1 Bit */
+ uint16_t SuppressDebugMsg : 1; /**< 0x17ee / 0xfca : Pos 7, 1 Bit */
+ uint16_t DisableUserStackWalk : 1; /**< 0x17ee / 0xfca : Pos 8, 1 Bit */
+ uint16_t RtlExceptionAttached : 1; /**< 0x17ee / 0xfca : Pos 9, 1 Bit */
+ uint16_t InitialThread : 1; /**< 0x17ee / 0xfca : Pos 10, 1 Bit */
+ uint16_t SessionAware : 1; /**< 0x17ee / 0xfca : Pos 11, 1 Bit - New Since W7. */
+ uint16_t SpareSameTebBits : 4; /**< 0x17ee / 0xfca : Pos 12, 4 Bits */
+ } W8, W80, W81;
+ struct
+ {
+ uint16_t SafeThunkCall : 1; /**< 0x17ee / 0xfca : Pos 0, 1 Bit */
+ uint16_t InDebugPrint : 1; /**< 0x17ee / 0xfca : Pos 1, 1 Bit */
+ uint16_t HasFiberData : 1; /**< 0x17ee / 0xfca : Pos 2, 1 Bit */
+ uint16_t SkipThreadAttach : 1; /**< 0x17ee / 0xfca : Pos 3, 1 Bit */
+ uint16_t WerInShipAssertCode : 1; /**< 0x17ee / 0xfca : Pos 4, 1 Bit */
+ uint16_t RanProcessInit : 1; /**< 0x17ee / 0xfca : Pos 5, 1 Bit */
+ uint16_t ClonedThread : 1; /**< 0x17ee / 0xfca : Pos 6, 1 Bit */
+ uint16_t SuppressDebugMsg : 1; /**< 0x17ee / 0xfca : Pos 7, 1 Bit */
+ uint16_t DisableUserStackWalk : 1; /**< 0x17ee / 0xfca : Pos 8, 1 Bit */
+ uint16_t RtlExceptionAttached : 1; /**< 0x17ee / 0xfca : Pos 9, 1 Bit */
+ uint16_t InitialThread : 1; /**< 0x17ee / 0xfca : Pos 10, 1 Bit */
+ uint16_t SpareSameTebBits : 5; /**< 0x17ee / 0xfca : Pos 12, 4 Bits */
+ } W7;
+ struct
+ {
+ uint16_t DbgSafeThunkCall : 1; /**< 0x17ee / 0xfca : Pos 0, 1 Bit */
+ uint16_t DbgInDebugPrint : 1; /**< 0x17ee / 0xfca : Pos 1, 1 Bit */
+ uint16_t DbgHasFiberData : 1; /**< 0x17ee / 0xfca : Pos 2, 1 Bit */
+ uint16_t DbgSkipThreadAttach : 1; /**< 0x17ee / 0xfca : Pos 3, 1 Bit */
+ uint16_t DbgWerInShipAssertCode : 1; /**< 0x17ee / 0xfca : Pos 4, 1 Bit */
+ uint16_t DbgRanProcessInit : 1; /**< 0x17ee / 0xfca : Pos 5, 1 Bit */
+ uint16_t DbgClonedThread : 1; /**< 0x17ee / 0xfca : Pos 6, 1 Bit */
+ uint16_t DbgSuppressDebugMsg : 1; /**< 0x17ee / 0xfca : Pos 7, 1 Bit */
+ uint16_t SpareSameTebBits : 8; /**< 0x17ee / 0xfca : Pos 8, 8 Bits */
+ } W6;
+ } Diff10;
+ PVOID TxnScopeEnterCallback; /**< 0x17f0 / 0xfcc */
+ PVOID TxnScopeExitCallback; /**< 0x17f8 / 0xfd0 */
+ PVOID TxnScopeContext; /**< 0x1800 / 0xfd4 */
+ uint32_t LockCount; /**< 0x1808 / 0xfd8 */
+ union
+ {
+ struct
+ {
+ uint32_t SpareUlong0; /**< 0x180c / 0xfdc */
+ } W7, W8, W80, W81;
+ struct
+ {
+ uint32_t ProcessRundown;
+ } W6;
+ } Diff11;
+ union
+ {
+ struct
+ {
+ PVOID ResourceRetValue; /**< 0x1810 / 0xfe0 */
+ /* End of TEB in W7 (windows 7)! */
+ PVOID ReservedForWdf; /**< 0x1818 / 0xfe4 - New Since W7. */
+ /* End of TEB in W8 (windows 8.0 & 8.1)! */
+ PVOID ReservedForCrt; /**< 0x1820 / 0xfe8 - New Since W10. */
+ RTUUID EffectiveContainerId; /**< 0x1828 / 0xfec - New Since W10. */
+ /* End of TEB in W10 14393! */
+ } W8, W80, W81, W10;
+ struct
+ {
+ PVOID ResourceRetValue; /**< 0x1810 / 0xfe0 */
+ } W7;
+ struct
+ {
+ uint64_t LastSwitchTime; /**< 0x1810 / 0xfe0 */
+ uint64_t TotalSwitchOutTime; /**< 0x1818 / 0xfe8 */
+ LARGE_INTEGER WaitReasonBitMap; /**< 0x1820 / 0xff0 */
+ /* End of TEB in W6 (windows Vista)! */
+ } W6;
+ } Diff12;
+} TEB_COMMON;
+typedef TEB_COMMON *PTEB_COMMON;
+AssertCompileMemberOffset(TEB_COMMON, ExceptionCode, ARCH_BITS == 64 ? 0x2c0 : 0x1a4);
+AssertCompileMemberOffset(TEB_COMMON, LastStatusValue, ARCH_BITS == 64 ? 0x1250 : 0xbf4);
+AssertCompileMemberOffset(TEB_COMMON, DeallocationStack, ARCH_BITS == 64 ? 0x1478 : 0xe0c);
+AssertCompileMemberOffset(TEB_COMMON, ReservedForNtRpc, ARCH_BITS == 64 ? 0x1698 : 0xf1c);
+AssertCompileMemberOffset(TEB_COMMON, Instrumentation, ARCH_BITS == 64 ? 0x16b8 : 0xf2c);
+AssertCompileMemberOffset(TEB_COMMON, Diff2, ARCH_BITS == 64 ? 0x1710 : 0xf50);
+AssertCompileMemberOffset(TEB_COMMON, Diff3, ARCH_BITS == 64 ? 0x1728 : 0xf64);
+AssertCompileMemberOffset(TEB_COMMON, Diff4, ARCH_BITS == 64 ? 0x1730 : 0xf68);
+AssertCompileMemberOffset(TEB_COMMON, WinSockData, ARCH_BITS == 64 ? 0x1738 : 0xf6c);
+AssertCompileMemberOffset(TEB_COMMON, GuaranteedStackBytes, ARCH_BITS == 64 ? 0x1748 : 0xf78);
+AssertCompileMemberOffset(TEB_COMMON, MuiImpersonation, ARCH_BITS == 64 ? 0x17e8 : 0xfc4);
+AssertCompileMemberOffset(TEB_COMMON, LockCount, ARCH_BITS == 64 ? 0x1808 : 0xfd8);
+AssertCompileSize(TEB_COMMON, ARCH_BITS == 64 ? 0x1838 : 0x1000);
+
+
+/** The size of the windows 8.1 PEB structure. */
+#define TEB_SIZE_W10 ( RT_UOFFSETOF(TEB_COMMON, Diff12.W10.EffectiveContainerId) + sizeof(RTUUID) )
+/** The size of the windows 8.1 PEB structure. */
+#define TEB_SIZE_W81 ( RT_UOFFSETOF(TEB_COMMON, Diff12.W8.ReservedForWdf) + sizeof(PVOID) )
+/** The size of the windows 8.0 PEB structure. */
+#define TEB_SIZE_W80 ( RT_UOFFSETOF(TEB_COMMON, Diff12.W8.ReservedForWdf) + sizeof(PVOID) )
+/** The size of the windows 7 PEB structure. */
+#define TEB_SIZE_W7 RT_UOFFSETOF(TEB_COMMON, Diff12.W8.ReservedForWdf)
+/** The size of the windows vista PEB structure. */
+#define TEB_SIZE_W6 ( RT_UOFFSETOF(TEB_COMMON, Diff12.W6.WaitReasonBitMap) + sizeof(LARGE_INTEGER) )
+/** The size of the windows server 2003 PEB structure. */
+#define TEB_SIZE_W52 RT_ALIGN_Z(RT_UOFFSETOF(TEB_COMMON, Diff9.W52.BooleanSpare), sizeof(PVOID))
+/** The size of the windows XP PEB structure. */
+#define TEB_SIZE_W51 RT_UOFFSETOF(TEB_COMMON, FlsData)
+
+
+
+#define _PEB _PEB_COMMON
+typedef PEB_COMMON PEB;
+typedef PPEB_COMMON PPEB;
+
+#define _TEB _TEB_COMMON
+typedef TEB_COMMON TEB;
+typedef PTEB_COMMON PTEB;
+
+#if !defined(NtCurrentTeb) && !defined(IPRT_NT_HAVE_CURRENT_TEB_MACRO)
+# ifdef RT_ARCH_X86
+DECL_FORCE_INLINE(PTEB) RTNtCurrentTeb(void) { return (PTEB)__readfsdword(RT_UOFFSETOF(TEB_COMMON, NtTib.Self)); }
+DECL_FORCE_INLINE(PPEB) RTNtCurrentPeb(void) { return (PPEB)__readfsdword(RT_UOFFSETOF(TEB_COMMON, ProcessEnvironmentBlock)); }
+DECL_FORCE_INLINE(uint32_t) RTNtCurrentThreadId(void) { return __readfsdword(RT_UOFFSETOF(TEB_COMMON, ClientId.UniqueThread)); }
+DECL_FORCE_INLINE(NTSTATUS) RTNtLastStatusValue(void) { return (NTSTATUS)__readfsdword(RT_UOFFSETOF(TEB_COMMON, LastStatusValue)); }
+DECL_FORCE_INLINE(uint32_t) RTNtLastErrorValue(void) { return __readfsdword(RT_UOFFSETOF(TEB_COMMON, LastErrorValue)); }
+# elif defined(RT_ARCH_AMD64)
+DECL_FORCE_INLINE(PTEB) RTNtCurrentTeb(void) { return (PTEB)__readgsqword(RT_UOFFSETOF(TEB_COMMON, NtTib.Self)); }
+DECL_FORCE_INLINE(PPEB) RTNtCurrentPeb(void) { return (PPEB)__readgsqword(RT_UOFFSETOF(TEB_COMMON, ProcessEnvironmentBlock)); }
+DECL_FORCE_INLINE(uint32_t) RTNtCurrentThreadId(void) { return __readgsdword(RT_UOFFSETOF(TEB_COMMON, ClientId.UniqueThread)); }
+DECL_FORCE_INLINE(NTSTATUS) RTNtLastStatusValue(void) { return (NTSTATUS)__readgsdword(RT_UOFFSETOF(TEB_COMMON, LastStatusValue)); }
+DECL_FORCE_INLINE(uint32_t) RTNtLastErrorValue(void) { return __readgsdword(RT_UOFFSETOF(TEB_COMMON, LastErrorValue)); }
+# else
+# error "Port me"
+# endif
+#else
+# define RTNtCurrentTeb() ((PTEB)NtCurrentTeb())
+# define RTNtCurrentPeb() (RTNtCurrentTeb()->ProcessEnvironmentBlock)
+# define RTNtCurrentThreadId() ((uint32_t)(uintptr_t)RTNtCurrentTeb()->ClientId.UniqueThread)
+# define RTNtLastStatusValue() (RTNtCurrentTeb()->LastStatusValue)
+# define RTNtLastErrorValue() (RTNtCurrentTeb()->LastErrorValue)
+#endif
+#define NtCurrentPeb() RTNtCurrentPeb()
+
+#ifdef IN_RING3
+RT_DECL_NTAPI(void) RtlAcquirePebLock(void);
+RT_DECL_NTAPI(void) RtlReleasePebLock(void);
+#endif
+
+/** @} */
+
+
+#ifdef IPRT_NT_USE_WINTERNL
+RT_DECL_NTAPI(NTSTATUS) NtCreateSection(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, PLARGE_INTEGER, ULONG, ULONG, HANDLE);
+typedef enum _SECTION_INHERIT
+{
+ ViewShare = 1,
+ ViewUnmap
+} SECTION_INHERIT;
+#endif
+RT_DECL_NTAPI(NTSTATUS) NtMapViewOfSection(HANDLE, HANDLE, PVOID *, ULONG, SIZE_T, PLARGE_INTEGER, PSIZE_T, SECTION_INHERIT,
+ ULONG, ULONG);
+RT_DECL_NTAPI(NTSTATUS) NtFlushVirtualMemory(HANDLE, PVOID *, PSIZE_T, PIO_STATUS_BLOCK);
+RT_DECL_NTAPI(NTSTATUS) NtUnmapViewOfSection(HANDLE, PVOID);
+
+#ifdef IPRT_NT_USE_WINTERNL
+RT_DECL_NTAPI(NTSTATUS) NtOpenProcess(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, PCLIENT_ID);
+RT_DECL_NTAPI(NTSTATUS) ZwOpenProcess(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, PCLIENT_ID);
+#endif
+RT_DECL_NTAPI(NTSTATUS) NtOpenThread(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, PCLIENT_ID);
+RT_DECL_NTAPI(NTSTATUS) ZwOpenThread(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, PCLIENT_ID);
+RT_DECL_NTAPI(NTSTATUS) NtAlertThread(HANDLE hThread);
+#ifdef IPRT_NT_USE_WINTERNL
+RT_DECL_NTAPI(NTSTATUS) ZwAlertThread(HANDLE hThread);
+#endif
+RT_DECL_NTAPI(NTSTATUS) NtTestAlert(void);
+
+#ifdef IPRT_NT_USE_WINTERNL
+RT_DECL_NTAPI(NTSTATUS) NtOpenProcessToken(HANDLE, ACCESS_MASK, PHANDLE);
+RT_DECL_NTAPI(NTSTATUS) NtOpenThreadToken(HANDLE, ACCESS_MASK, BOOLEAN, PHANDLE);
+#endif
+RT_DECL_NTAPI(NTSTATUS) ZwOpenProcessToken(HANDLE, ACCESS_MASK, PHANDLE);
+RT_DECL_NTAPI(NTSTATUS) ZwOpenThreadToken(HANDLE, ACCESS_MASK, BOOLEAN, PHANDLE);
+
+#ifdef IPRT_NT_USE_WINTERNL
+typedef struct _FILE_FS_VOLUME_INFORMATION
+{
+ LARGE_INTEGER VolumeCreationTime;
+ ULONG VolumeSerialNumber;
+ ULONG VolumeLabelLength;
+ BOOLEAN SupportsObjects;
+ WCHAR VolumeLabel[1];
+} FILE_FS_VOLUME_INFORMATION;
+typedef FILE_FS_VOLUME_INFORMATION *PFILE_FS_VOLUME_INFORMATION;
+typedef struct _FILE_FS_LABEL_INFORMATION
+{
+ ULONG VolumeLabelLength;
+ WCHAR VolumeLabel[1];
+} FILE_FS_LABEL_INFORMATION;
+typedef FILE_FS_LABEL_INFORMATION *PFILE_FS_LABEL_INFORMATION;
+typedef struct _FILE_FS_SIZE_INFORMATION
+{
+ LARGE_INTEGER TotalAllocationUnits;
+ LARGE_INTEGER AvailableAllocationUnits;
+ ULONG SectorsPerAllocationUnit;
+ ULONG BytesPerSector;
+} FILE_FS_SIZE_INFORMATION;
+typedef FILE_FS_SIZE_INFORMATION *PFILE_FS_SIZE_INFORMATION;
+typedef struct _FILE_FS_DEVICE_INFORMATION
+{
+ DEVICE_TYPE DeviceType;
+ ULONG Characteristics;
+} FILE_FS_DEVICE_INFORMATION;
+typedef FILE_FS_DEVICE_INFORMATION *PFILE_FS_DEVICE_INFORMATION;
+typedef struct _FILE_FS_ATTRIBUTE_INFORMATION
+{
+ ULONG FileSystemAttributes;
+ LONG MaximumComponentNameLength;
+ ULONG FileSystemNameLength;
+ WCHAR FileSystemName[1];
+} FILE_FS_ATTRIBUTE_INFORMATION;
+typedef FILE_FS_ATTRIBUTE_INFORMATION *PFILE_FS_ATTRIBUTE_INFORMATION;
+typedef struct _FILE_FS_CONTROL_INFORMATION
+{
+ LARGE_INTEGER FreeSpaceStartFiltering;
+ LARGE_INTEGER FreeSpaceThreshold;
+ LARGE_INTEGER FreeSpaceStopFiltering;
+ LARGE_INTEGER DefaultQuotaThreshold;
+ LARGE_INTEGER DefaultQuotaLimit;
+ ULONG FileSystemControlFlags;
+} FILE_FS_CONTROL_INFORMATION;
+typedef FILE_FS_CONTROL_INFORMATION *PFILE_FS_CONTROL_INFORMATION;
+typedef struct _FILE_FS_FULL_SIZE_INFORMATION
+{
+ LARGE_INTEGER TotalAllocationUnits;
+ LARGE_INTEGER CallerAvailableAllocationUnits;
+ LARGE_INTEGER ActualAvailableAllocationUnits;
+ ULONG SectorsPerAllocationUnit;
+ ULONG BytesPerSector;
+} FILE_FS_FULL_SIZE_INFORMATION;
+typedef FILE_FS_FULL_SIZE_INFORMATION *PFILE_FS_FULL_SIZE_INFORMATION;
+typedef struct _FILE_FS_OBJECTID_INFORMATION
+{
+ UCHAR ObjectId[16];
+ UCHAR ExtendedInfo[48];
+} FILE_FS_OBJECTID_INFORMATION;
+typedef FILE_FS_OBJECTID_INFORMATION *PFILE_FS_OBJECTID_INFORMATION;
+typedef struct _FILE_FS_DRIVER_PATH_INFORMATION
+{
+ BOOLEAN DriverInPath;
+ ULONG DriverNameLength;
+ WCHAR DriverName[1];
+} FILE_FS_DRIVER_PATH_INFORMATION;
+typedef FILE_FS_DRIVER_PATH_INFORMATION *PFILE_FS_DRIVER_PATH_INFORMATION;
+typedef struct _FILE_FS_VOLUME_FLAGS_INFORMATION
+{
+ ULONG Flags;
+} FILE_FS_VOLUME_FLAGS_INFORMATION;
+typedef FILE_FS_VOLUME_FLAGS_INFORMATION *PFILE_FS_VOLUME_FLAGS_INFORMATION;
+#endif
+#if !defined(SSINFO_OFFSET_UNKNOWN) || defined(IPRT_NT_USE_WINTERNL)
+typedef struct _FILE_FS_SECTOR_SIZE_INFORMATION
+{
+ ULONG LogicalBytesPerSector;
+ ULONG PhysicalBytesPerSectorForAtomicity;
+ ULONG PhysicalBytesPerSectorForPerformance;
+ ULONG FileSystemEffectivePhysicalBytesPerSectorForAtomicity;
+ ULONG Flags;
+ ULONG ByteOffsetForSectorAlignment;
+ ULONG ByteOffsetForPartitionAlignment;
+} FILE_FS_SECTOR_SIZE_INFORMATION;
+typedef FILE_FS_SECTOR_SIZE_INFORMATION *PFILE_FS_SECTOR_SIZE_INFORMATION;
+# ifndef SSINFO_OFFSET_UNKNOWN
+# define SSINFO_OFFSET_UNKNOWN 0xffffffffUL
+# define SSINFO_FLAGS_ALIGNED_DEVICE 1UL
+# define SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE 2UL
+# define SSINFO_FLAGS_NO_SEEK_PENALTY 4UL
+# define SSINFO_FLAGS_TRIM_ENABLED 8UL
+# define SSINFO_FLAGS_BYTE_ADDRESSABLE 16UL
+# endif
+#endif
+#ifdef IPRT_NT_USE_WINTERNL
+typedef struct _FILE_FS_DATA_COPY_INFORMATION
+{
+ ULONG NumberOfCopies;
+} FILE_FS_DATA_COPY_INFORMATION;
+typedef FILE_FS_DATA_COPY_INFORMATION *PFILE_FS_DATA_COPY_INFORMATION;
+typedef struct _FILE_FS_METADATA_SIZE_INFORMATION
+{
+ LARGE_INTEGER TotalMetadataAllocationUnits;
+ ULONG SectorsPerAllocationUnit;
+ ULONG BytesPerSector;
+} FILE_FS_METADATA_SIZE_INFORMATION;
+typedef FILE_FS_METADATA_SIZE_INFORMATION *PFILE_FS_METADATA_SIZE_INFORMATION;
+typedef struct _FILE_FS_FULL_SIZE_INFORMATION_EX
+{
+ ULONGLONG ActualTotalAllocationUnits;
+ ULONGLONG ActualAvailableAllocationUnits;
+ ULONGLONG ActualPoolUnavailableAllocationUnits;
+ ULONGLONG CallerTotalAllocationUnits;
+ ULONGLONG CallerAvailableAllocationUnits;
+ ULONGLONG CallerPoolUnavailableAllocationUnits;
+ ULONGLONG UsedAllocationUnits;
+ ULONGLONG TotalReservedAllocationUnits;
+ ULONGLONG VolumeStorageReserveAllocationUnits;
+ ULONGLONG AvailableCommittedAllocationUnits;
+ ULONGLONG PoolAvailableAllocationUnits;
+ ULONG SectorsPerAllocationUnit;
+ ULONG BytesPerSector;
+} FILE_FS_FULL_SIZE_INFORMATION_EX;
+typedef FILE_FS_FULL_SIZE_INFORMATION_EX *PFILE_FS_FULL_SIZE_INFORMATION_EX;
+#endif /* IPRT_NT_USE_WINTERNL */
+
+typedef enum _FSINFOCLASS
+{
+ FileFsVolumeInformation = 1,
+ FileFsLabelInformation,
+ FileFsSizeInformation, /**< FILE_FS_SIZE_INFORMATION */
+ FileFsDeviceInformation,
+ FileFsAttributeInformation,
+ FileFsControlInformation,
+ FileFsFullSizeInformation,
+ FileFsObjectIdInformation,
+ FileFsDriverPathInformation,
+ FileFsVolumeFlagsInformation,
+ FileFsSectorSizeInformation,
+ FileFsDataCopyInformation,
+ FileFsMetadataSizeInformation,
+ FileFsFullSizeInformationEx,
+ FileFsMaximumInformation
+} FS_INFORMATION_CLASS;
+typedef FS_INFORMATION_CLASS *PFS_INFORMATION_CLASS;
+RT_DECL_NTAPI(NTSTATUS) NtQueryVolumeInformationFile(HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG, FS_INFORMATION_CLASS);
+RT_DECL_NTAPI(NTSTATUS) NtSetVolumeInformationFile(HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG, FS_INFORMATION_CLASS);
+
+#ifdef IPRT_NT_USE_WINTERNL
+typedef struct _FILE_DIRECTORY_INFORMATION
+{
+ ULONG NextEntryOffset;
+ ULONG FileIndex;
+ LARGE_INTEGER CreationTime;
+ LARGE_INTEGER LastAccessTime;
+ LARGE_INTEGER LastWriteTime;
+ LARGE_INTEGER ChangeTime;
+ LARGE_INTEGER EndOfFile;
+ LARGE_INTEGER AllocationSize;
+ ULONG FileAttributes;
+ ULONG FileNameLength;
+ WCHAR FileName[1];
+} FILE_DIRECTORY_INFORMATION;
+typedef FILE_DIRECTORY_INFORMATION *PFILE_DIRECTORY_INFORMATION;
+typedef struct _FILE_FULL_DIR_INFORMATION
+{
+ ULONG NextEntryOffset;
+ ULONG FileIndex;
+ LARGE_INTEGER CreationTime;
+ LARGE_INTEGER LastAccessTime;
+ LARGE_INTEGER LastWriteTime;
+ LARGE_INTEGER ChangeTime;
+ LARGE_INTEGER EndOfFile;
+ LARGE_INTEGER AllocationSize;
+ ULONG FileAttributes;
+ ULONG FileNameLength;
+ ULONG EaSize;
+ WCHAR FileName[1];
+} FILE_FULL_DIR_INFORMATION;
+typedef FILE_FULL_DIR_INFORMATION *PFILE_FULL_DIR_INFORMATION;
+typedef struct _FILE_BOTH_DIR_INFORMATION
+{
+ ULONG NextEntryOffset; /**< 0x00: */
+ ULONG FileIndex; /**< 0x04: */
+ LARGE_INTEGER CreationTime; /**< 0x08: */
+ LARGE_INTEGER LastAccessTime; /**< 0x10: */
+ LARGE_INTEGER LastWriteTime; /**< 0x18: */
+ LARGE_INTEGER ChangeTime; /**< 0x20: */
+ LARGE_INTEGER EndOfFile; /**< 0x28: */
+ LARGE_INTEGER AllocationSize; /**< 0x30: */
+ ULONG FileAttributes; /**< 0x38: */
+ ULONG FileNameLength; /**< 0x3c: */
+ ULONG EaSize; /**< 0x40: */
+ CCHAR ShortNameLength; /**< 0x44: */
+ WCHAR ShortName[12]; /**< 0x46: */
+ WCHAR FileName[1]; /**< 0x5e: */
+} FILE_BOTH_DIR_INFORMATION;
+typedef FILE_BOTH_DIR_INFORMATION *PFILE_BOTH_DIR_INFORMATION;
+typedef struct _FILE_BASIC_INFORMATION
+{
+ LARGE_INTEGER CreationTime;
+ LARGE_INTEGER LastAccessTime;
+ LARGE_INTEGER LastWriteTime;
+ LARGE_INTEGER ChangeTime;
+ ULONG FileAttributes;
+} FILE_BASIC_INFORMATION;
+typedef FILE_BASIC_INFORMATION *PFILE_BASIC_INFORMATION;
+typedef struct _FILE_STANDARD_INFORMATION
+{
+ LARGE_INTEGER AllocationSize;
+ LARGE_INTEGER EndOfFile;
+ ULONG NumberOfLinks;
+ BOOLEAN DeletePending;
+ BOOLEAN Directory;
+} FILE_STANDARD_INFORMATION;
+typedef FILE_STANDARD_INFORMATION *PFILE_STANDARD_INFORMATION;
+typedef struct _FILE_NAME_INFORMATION
+{
+ ULONG FileNameLength;
+ WCHAR FileName[1];
+} FILE_NAME_INFORMATION;
+typedef FILE_NAME_INFORMATION *PFILE_NAME_INFORMATION;
+typedef FILE_NAME_INFORMATION FILE_NETWORK_PHYSICAL_NAME_INFORMATION;
+typedef FILE_NETWORK_PHYSICAL_NAME_INFORMATION *PFILE_NETWORK_PHYSICAL_NAME_INFORMATION;
+typedef struct _FILE_INTERNAL_INFORMATION
+{
+ LARGE_INTEGER IndexNumber;
+} FILE_INTERNAL_INFORMATION;
+typedef FILE_INTERNAL_INFORMATION *PFILE_INTERNAL_INFORMATION;
+typedef struct _FILE_EA_INFORMATION
+{
+ ULONG EaSize;
+} FILE_EA_INFORMATION;
+typedef FILE_EA_INFORMATION *PFILE_EA_INFORMATION;
+typedef struct _FILE_ACCESS_INFORMATION
+{
+ ACCESS_MASK AccessFlags;
+} FILE_ACCESS_INFORMATION;
+typedef FILE_ACCESS_INFORMATION *PFILE_ACCESS_INFORMATION;
+typedef struct _FILE_RENAME_INFORMATION
+{
+ union
+ {
+ BOOLEAN ReplaceIfExists;
+ ULONG Flags;
+ };
+ HANDLE RootDirectory;
+ ULONG FileNameLength;
+ WCHAR FileName[1];
+} FILE_RENAME_INFORMATION;
+typedef FILE_RENAME_INFORMATION *PFILE_RENAME_INFORMATION;
+typedef struct _FILE_LINK_INFORMATION
+{
+ union
+ {
+ BOOLEAN ReplaceIfExists;
+ ULONG Flags;
+ };
+ HANDLE RootDirectory;
+ ULONG FileNameLength;
+ WCHAR FileName[1];
+} FILE_LINK_INFORMATION;
+typedef FILE_LINK_INFORMATION *PFILE_LINK_INFORMATION;
+typedef struct _FILE_NAMES_INFORMATION
+{
+ ULONG NextEntryOffset;
+ ULONG FileIndex;
+ ULONG FileNameLength;
+ WCHAR FileName[1];
+} FILE_NAMES_INFORMATION;
+typedef FILE_NAMES_INFORMATION *PFILE_NAMES_INFORMATION;
+typedef struct _FILE_DISPOSITION_INFORMATION
+{
+ BOOLEAN DeleteFile;
+} FILE_DISPOSITION_INFORMATION;
+typedef FILE_DISPOSITION_INFORMATION *PFILE_DISPOSITION_INFORMATION;
+typedef struct _FILE_POSITION_INFORMATION
+{
+ LARGE_INTEGER CurrentByteOffset;
+} FILE_POSITION_INFORMATION;
+typedef FILE_POSITION_INFORMATION *PFILE_POSITION_INFORMATION;
+typedef struct _FILE_FULL_EA_INFORMATION
+{
+ ULONG NextEntryOffset;
+ UCHAR Flags;
+ UCHAR EaNameLength;
+ USHORT EaValueLength;
+ CHAR EaName[1];
+} FILE_FULL_EA_INFORMATION;
+typedef FILE_FULL_EA_INFORMATION *PFILE_FULL_EA_INFORMATION;
+typedef struct _FILE_MODE_INFORMATION
+{
+ ULONG Mode;
+} FILE_MODE_INFORMATION;
+typedef FILE_MODE_INFORMATION *PFILE_MODE_INFORMATION;
+typedef struct _FILE_ALIGNMENT_INFORMATION
+{
+ ULONG AlignmentRequirement;
+} FILE_ALIGNMENT_INFORMATION;
+typedef FILE_ALIGNMENT_INFORMATION *PFILE_ALIGNMENT_INFORMATION;
+typedef struct _FILE_ALL_INFORMATION
+{
+ FILE_BASIC_INFORMATION BasicInformation;
+ FILE_STANDARD_INFORMATION StandardInformation;
+ FILE_INTERNAL_INFORMATION InternalInformation;
+ FILE_EA_INFORMATION EaInformation;
+ FILE_ACCESS_INFORMATION AccessInformation;
+ FILE_POSITION_INFORMATION PositionInformation;
+ FILE_MODE_INFORMATION ModeInformation;
+ FILE_ALIGNMENT_INFORMATION AlignmentInformation;
+ FILE_NAME_INFORMATION NameInformation;
+} FILE_ALL_INFORMATION;
+typedef FILE_ALL_INFORMATION *PFILE_ALL_INFORMATION;
+typedef struct _FILE_ALLOCATION_INFORMATION
+{
+ LARGE_INTEGER AllocationSize;
+} FILE_ALLOCATION_INFORMATION;
+typedef FILE_ALLOCATION_INFORMATION *PFILE_ALLOCATION_INFORMATION;
+typedef struct _FILE_END_OF_FILE_INFORMATION
+{
+ LARGE_INTEGER EndOfFile;
+} FILE_END_OF_FILE_INFORMATION;
+typedef FILE_END_OF_FILE_INFORMATION *PFILE_END_OF_FILE_INFORMATION;
+typedef struct _FILE_STREAM_INFORMATION
+{
+ ULONG NextEntryOffset;
+ ULONG StreamNameLength;
+ LARGE_INTEGER StreamSize;
+ LARGE_INTEGER StreamAllocationSize;
+ WCHAR StreamName[1];
+} FILE_STREAM_INFORMATION;
+typedef FILE_STREAM_INFORMATION *PFILE_STREAM_INFORMATION;
+
+typedef struct _FILE_PIPE_INFORMATION
+{
+ ULONG ReadMode;
+ ULONG CompletionMode;
+} FILE_PIPE_INFORMATION;
+typedef FILE_PIPE_INFORMATION *PFILE_PIPE_INFORMATION;
+
+typedef struct _FILE_PIPE_LOCAL_INFORMATION
+{
+ ULONG NamedPipeType;
+ ULONG NamedPipeConfiguration;
+ ULONG MaximumInstances;
+ ULONG CurrentInstances;
+ ULONG InboundQuota;
+ ULONG ReadDataAvailable;
+ ULONG OutboundQuota;
+ ULONG WriteQuotaAvailable;
+ ULONG NamedPipeState;
+ ULONG NamedPipeEnd;
+} FILE_PIPE_LOCAL_INFORMATION;
+typedef FILE_PIPE_LOCAL_INFORMATION *PFILE_PIPE_LOCAL_INFORMATION;
+
+/** @name Pipe state (FILE_PIPE_LOCAL_INFORMATION::NamedPipeState)
+ * @{ */
+#if !defined(FILE_PIPE_DISCONNECTED_STATE) || defined(DOXYGEN_RUNNING)
+# define FILE_PIPE_DISCONNECTED_STATE 0x00000001U
+# define FILE_PIPE_LISTENING_STATE 0x00000002U
+# define FILE_PIPE_CONNECTED_STATE 0x00000003U
+# define FILE_PIPE_CLOSING_STATE 0x00000004U
+#endif
+/** @} */
+
+/** @name Pipe config (FILE_PIPE_LOCAL_INFORMATION::NamedPipeConfiguration)
+ * @{ */
+#if !defined(FILE_PIPE_INBOUND) || defined(DOXYGEN_RUNNING)
+# define FILE_PIPE_INBOUND 0x00000000U
+# define FILE_PIPE_OUTBOUND 0x00000001U
+# define FILE_PIPE_FULL_DUPLEX 0x00000002U
+#endif
+/** @} */
+
+/** @name Pipe end (FILE_PIPE_LOCAL_INFORMATION::NamedPipeEnd)
+ * @{ */
+#if !defined(FILE_PIPE_CLIENT_END) || defined(DOXYGEN_RUNNING)
+# define FILE_PIPE_CLIENT_END 0x00000000U
+# define FILE_PIPE_SERVER_END 0x00000001U
+#endif
+/** @} */
+
+typedef struct _FILE_PIPE_REMOTE_INFORMATION
+{
+ LARGE_INTEGER CollectDataTime;
+ ULONG MaximumCollectionCount;
+} FILE_PIPE_REMOTE_INFORMATION;
+typedef FILE_PIPE_REMOTE_INFORMATION *PFILE_PIPE_REMOTE_INFORMATION;
+typedef struct _FILE_MAILSLOT_QUERY_INFORMATION
+{
+ ULONG MaximumMessageSize;
+ ULONG MailslotQuota;
+ ULONG NextMessageSize;
+ ULONG MessagesAvailable;
+ LARGE_INTEGER ReadTimeout;
+} FILE_MAILSLOT_QUERY_INFORMATION;
+typedef FILE_MAILSLOT_QUERY_INFORMATION *PFILE_MAILSLOT_QUERY_INFORMATION;
+typedef struct _FILE_MAILSLOT_SET_INFORMATION
+{
+ PLARGE_INTEGER ReadTimeout;
+} FILE_MAILSLOT_SET_INFORMATION;
+typedef FILE_MAILSLOT_SET_INFORMATION *PFILE_MAILSLOT_SET_INFORMATION;
+typedef struct _FILE_COMPRESSION_INFORMATION
+{
+ LARGE_INTEGER CompressedFileSize;
+ USHORT CompressionFormat;
+ UCHAR CompressionUnitShift;
+ UCHAR ChunkShift;
+ UCHAR ClusterShift;
+ UCHAR Reserved[3];
+} FILE_COMPRESSION_INFORMATION;
+typedef FILE_COMPRESSION_INFORMATION *PFILE_COMPRESSION_INFORMATION;
+typedef struct _FILE_OBJECTID_INFORMATION
+{
+ LONGLONG FileReference;
+ UCHAR ObjectId[16];
+ union
+ {
+ struct
+ {
+ UCHAR BirthVolumeId[16];
+ UCHAR BirthObjectId[16];
+ UCHAR DomainId[16];
+ };
+ UCHAR ExtendedInfo[48];
+ };
+} FILE_OBJECTID_INFORMATION;
+typedef FILE_OBJECTID_INFORMATION *PFILE_OBJECTID_INFORMATION;
+typedef struct _FILE_COMPLETION_INFORMATION
+{
+ HANDLE Port;
+ PVOID Key;
+} FILE_COMPLETION_INFORMATION;
+typedef FILE_COMPLETION_INFORMATION *PFILE_COMPLETION_INFORMATION;
+typedef struct _FILE_MOVE_CLUSTER_INFORMATION
+{
+ ULONG ClusterCount;
+ HANDLE RootDirectory;
+ ULONG FileNameLength;
+ WCHAR FileName[1];
+} FILE_MOVE_CLUSTER_INFORMATION;
+typedef FILE_MOVE_CLUSTER_INFORMATION *PFILE_MOVE_CLUSTER_INFORMATION;
+typedef struct _FILE_QUOTA_INFORMATION
+{
+ ULONG NextEntryOffset;
+ ULONG SidLength;
+ LARGE_INTEGER ChangeTime;
+ LARGE_INTEGER QuotaUsed;
+ LARGE_INTEGER QuotaThreshold;
+ LARGE_INTEGER QuotaLimit;
+ SID Sid;
+} FILE_QUOTA_INFORMATION;
+typedef FILE_QUOTA_INFORMATION *PFILE_QUOTA_INFORMATION;
+typedef struct _FILE_REPARSE_POINT_INFORMATION
+{
+ LONGLONG FileReference;
+ ULONG Tag;
+} FILE_REPARSE_POINT_INFORMATION;
+typedef FILE_REPARSE_POINT_INFORMATION *PFILE_REPARSE_POINT_INFORMATION;
+typedef struct _FILE_NETWORK_OPEN_INFORMATION
+{
+ LARGE_INTEGER CreationTime;
+ LARGE_INTEGER LastAccessTime;
+ LARGE_INTEGER LastWriteTime;
+ LARGE_INTEGER ChangeTime;
+ LARGE_INTEGER AllocationSize;
+ LARGE_INTEGER EndOfFile;
+ ULONG FileAttributes;
+} FILE_NETWORK_OPEN_INFORMATION;
+typedef FILE_NETWORK_OPEN_INFORMATION *PFILE_NETWORK_OPEN_INFORMATION;
+typedef struct _FILE_ATTRIBUTE_TAG_INFORMATION
+{
+ ULONG FileAttributes;
+ ULONG ReparseTag;
+} FILE_ATTRIBUTE_TAG_INFORMATION;
+typedef FILE_ATTRIBUTE_TAG_INFORMATION *PFILE_ATTRIBUTE_TAG_INFORMATION;
+typedef struct _FILE_TRACKING_INFORMATION
+{
+ HANDLE DestinationFile;
+ ULONG ObjectInformationLength;
+ CHAR ObjectInformation[1];
+} FILE_TRACKING_INFORMATION;
+typedef FILE_TRACKING_INFORMATION *PFILE_TRACKING_INFORMATION;
+typedef struct _FILE_ID_BOTH_DIR_INFORMATION
+{
+ ULONG NextEntryOffset;
+ ULONG FileIndex;
+ LARGE_INTEGER CreationTime;
+ LARGE_INTEGER LastAccessTime;
+ LARGE_INTEGER LastWriteTime;
+ LARGE_INTEGER ChangeTime;
+ LARGE_INTEGER EndOfFile;
+ LARGE_INTEGER AllocationSize;
+ ULONG FileAttributes;
+ ULONG FileNameLength;
+ ULONG EaSize;
+ CCHAR ShortNameLength;
+ WCHAR ShortName[12];
+ LARGE_INTEGER FileId;
+ WCHAR FileName[1];
+} FILE_ID_BOTH_DIR_INFORMATION;
+typedef FILE_ID_BOTH_DIR_INFORMATION *PFILE_ID_BOTH_DIR_INFORMATION;
+typedef struct _FILE_ID_FULL_DIR_INFORMATION
+{
+ ULONG NextEntryOffset;
+ ULONG FileIndex;
+ LARGE_INTEGER CreationTime;
+ LARGE_INTEGER LastAccessTime;
+ LARGE_INTEGER LastWriteTime;
+ LARGE_INTEGER ChangeTime;
+ LARGE_INTEGER EndOfFile;
+ LARGE_INTEGER AllocationSize;
+ ULONG FileAttributes;
+ ULONG FileNameLength;
+ ULONG EaSize;
+ LARGE_INTEGER FileId;
+ WCHAR FileName[1];
+} FILE_ID_FULL_DIR_INFORMATION;
+typedef FILE_ID_FULL_DIR_INFORMATION *PFILE_ID_FULL_DIR_INFORMATION;
+typedef struct _FILE_VALID_DATA_LENGTH_INFORMATION
+{
+ LARGE_INTEGER ValidDataLength;
+} FILE_VALID_DATA_LENGTH_INFORMATION;
+typedef FILE_VALID_DATA_LENGTH_INFORMATION *PFILE_VALID_DATA_LENGTH_INFORMATION;
+typedef struct _FILE_IO_COMPLETION_NOTIFICATION_INFORMATION
+{
+ ULONG Flags;
+} FILE_IO_COMPLETION_NOTIFICATION_INFORMATION;
+typedef FILE_IO_COMPLETION_NOTIFICATION_INFORMATION *PFILE_IO_COMPLETION_NOTIFICATION_INFORMATION;
+typedef enum _IO_PRIORITY_HINT
+{
+ IoPriorityVeryLow = 0,
+ IoPriorityLow,
+ IoPriorityNormal,
+ IoPriorityHigh,
+ IoPriorityCritical,
+ MaxIoPriorityTypes
+} IO_PRIORITY_HINT;
+AssertCompileSize(IO_PRIORITY_HINT, sizeof(int));
+typedef struct _FILE_IO_PRIORITY_HINT_INFORMATION
+{
+ IO_PRIORITY_HINT PriorityHint;
+} FILE_IO_PRIORITY_HINT_INFORMATION;
+typedef FILE_IO_PRIORITY_HINT_INFORMATION *PFILE_IO_PRIORITY_HINT_INFORMATION;
+typedef struct _FILE_SFIO_RESERVE_INFORMATION
+{
+ ULONG RequestsPerPeriod;
+ ULONG Period;
+ BOOLEAN RetryFailures;
+ BOOLEAN Discardable;
+ ULONG RequestSize;
+ ULONG NumOutstandingRequests;
+} FILE_SFIO_RESERVE_INFORMATION;
+typedef FILE_SFIO_RESERVE_INFORMATION *PFILE_SFIO_RESERVE_INFORMATION;
+typedef struct _FILE_SFIO_VOLUME_INFORMATION
+{
+ ULONG MaximumRequestsPerPeriod;
+ ULONG MinimumPeriod;
+ ULONG MinimumTransferSize;
+} FILE_SFIO_VOLUME_INFORMATION;
+typedef FILE_SFIO_VOLUME_INFORMATION *PFILE_SFIO_VOLUME_INFORMATION;
+typedef struct _FILE_LINK_ENTRY_INFORMATION
+{
+ ULONG NextEntryOffset;
+ LONGLONG ParentFileId;
+ ULONG FileNameLength;
+ WCHAR FileName[1];
+} FILE_LINK_ENTRY_INFORMATION;
+typedef FILE_LINK_ENTRY_INFORMATION *PFILE_LINK_ENTRY_INFORMATION;
+typedef struct _FILE_LINKS_INFORMATION
+{
+ ULONG BytesNeeded;
+ ULONG EntriesReturned;
+ FILE_LINK_ENTRY_INFORMATION Entry;
+} FILE_LINKS_INFORMATION;
+typedef FILE_LINKS_INFORMATION *PFILE_LINKS_INFORMATION;
+typedef struct _FILE_PROCESS_IDS_USING_FILE_INFORMATION
+{
+ ULONG NumberOfProcessIdsInList;
+ ULONG_PTR ProcessIdList[1];
+} FILE_PROCESS_IDS_USING_FILE_INFORMATION;
+typedef FILE_PROCESS_IDS_USING_FILE_INFORMATION *PFILE_PROCESS_IDS_USING_FILE_INFORMATION;
+typedef struct _FILE_ID_GLOBAL_TX_DIR_INFORMATION
+{
+ ULONG NextEntryOffset;
+ ULONG FileIndex;
+ LARGE_INTEGER CreationTime;
+ LARGE_INTEGER LastAccessTime;
+ LARGE_INTEGER LastWriteTime;
+ LARGE_INTEGER ChangeTime;
+ LARGE_INTEGER EndOfFile;
+ LARGE_INTEGER AllocationSize;
+ ULONG FileAttributes;
+ ULONG FileNameLength;
+ LARGE_INTEGER FileId;
+ GUID LockingTransactionId;
+ ULONG TxInfoFlags;
+ WCHAR FileName[1];
+} FILE_ID_GLOBAL_TX_DIR_INFORMATION;
+typedef FILE_ID_GLOBAL_TX_DIR_INFORMATION *PFILE_ID_GLOBAL_TX_DIR_INFORMATION;
+typedef struct _FILE_IS_REMOTE_DEVICE_INFORMATION
+{
+ BOOLEAN IsRemote;
+} FILE_IS_REMOTE_DEVICE_INFORMATION;
+typedef FILE_IS_REMOTE_DEVICE_INFORMATION *PFILE_IS_REMOTE_DEVICE_INFORMATION;
+typedef struct _FILE_NUMA_NODE_INFORMATION
+{
+ USHORT NodeNumber;
+} FILE_NUMA_NODE_INFORMATION;
+typedef FILE_NUMA_NODE_INFORMATION *PFILE_NUMA_NODE_INFORMATION;
+typedef struct _FILE_STANDARD_LINK_INFORMATION
+{
+ ULONG NumberOfAccessibleLinks;
+ ULONG TotalNumberOfLinks;
+ BOOLEAN DeletePending;
+ BOOLEAN Directory;
+} FILE_STANDARD_LINK_INFORMATION;
+typedef FILE_STANDARD_LINK_INFORMATION *PFILE_STANDARD_LINK_INFORMATION;
+typedef struct _FILE_REMOTE_PROTOCOL_INFORMATION
+{
+ USHORT StructureVersion;
+ USHORT StructureSize;
+ ULONG Protocol;
+ USHORT ProtocolMajorVersion;
+ USHORT ProtocolMinorVersion;
+ USHORT ProtocolRevision;
+ USHORT Reserved;
+ ULONG Flags;
+ struct
+ {
+ ULONG Reserved[8];
+ } GenericReserved;
+ struct
+ {
+ ULONG Reserved[16];
+ } ProtocolSpecificReserved;
+} FILE_REMOTE_PROTOCOL_INFORMATION;
+typedef FILE_REMOTE_PROTOCOL_INFORMATION *PFILE_REMOTE_PROTOCOL_INFORMATION;
+typedef struct _FILE_VOLUME_NAME_INFORMATION
+{
+ ULONG DeviceNameLength;
+ WCHAR DeviceName[1];
+} FILE_VOLUME_NAME_INFORMATION;
+typedef FILE_VOLUME_NAME_INFORMATION *PFILE_VOLUME_NAME_INFORMATION;
+# ifndef FILE_INVALID_FILE_ID
+typedef struct _FILE_ID_128
+{
+ BYTE Identifier[16];
+} FILE_ID_128;
+typedef FILE_ID_128 *PFILE_ID_128;
+# endif
+typedef struct _FILE_ID_EXTD_DIR_INFORMATION
+{
+ ULONG NextEntryOffset;
+ ULONG FileIndex;
+ LARGE_INTEGER CreationTime;
+ LARGE_INTEGER LastAccessTime;
+ LARGE_INTEGER LastWriteTime;
+ LARGE_INTEGER ChangeTime;
+ LARGE_INTEGER EndOfFile;
+ LARGE_INTEGER AllocationSize;
+ ULONG FileAttributes;
+ ULONG FileNameLength;
+ ULONG EaSize;
+ ULONG ReparsePointTag;
+ FILE_ID_128 FileId;
+ WCHAR FileName[1];
+} FILE_ID_EXTD_DIR_INFORMATION;
+typedef FILE_ID_EXTD_DIR_INFORMATION *PFILE_ID_EXTD_DIR_INFORMATION;
+typedef struct _FILE_ID_EXTD_BOTH_DIR_INFORMATION
+{
+ ULONG NextEntryOffset;
+ ULONG FileIndex;
+ LARGE_INTEGER CreationTime;
+ LARGE_INTEGER LastAccessTime;
+ LARGE_INTEGER LastWriteTime;
+ LARGE_INTEGER ChangeTime;
+ LARGE_INTEGER EndOfFile;
+ LARGE_INTEGER AllocationSize;
+ ULONG FileAttributes;
+ ULONG FileNameLength;
+ ULONG EaSize;
+ ULONG ReparsePointTag;
+ FILE_ID_128 FileId;
+ CCHAR ShortNameLength;
+ WCHAR ShortName[12];
+ WCHAR FileName[1];
+} FILE_ID_EXTD_BOTH_DIR_INFORMATION;
+typedef FILE_ID_EXTD_BOTH_DIR_INFORMATION *PFILE_ID_EXTD_BOTH_DIR_INFORMATION;
+typedef struct _FILE_ID_INFORMATION
+{
+ ULONGLONG VolumeSerialNumber;
+ FILE_ID_128 FileId;
+} FILE_ID_INFORMATION;
+typedef FILE_ID_INFORMATION *PFILE_ID_INFORMATION;
+typedef struct _FILE_LINK_ENTRY_FULL_ID_INFORMATION
+{
+ ULONG NextEntryOffset;
+ FILE_ID_128 ParentFileId;
+ ULONG FileNameLength;
+ WCHAR FileName[1];
+} FILE_LINK_ENTRY_FULL_ID_INFORMATION;
+typedef FILE_LINK_ENTRY_FULL_ID_INFORMATION *PFILE_LINK_ENTRY_FULL_ID_INFORMATION;
+typedef struct _FILE_LINKS_FULL_ID_INFORMATION {
+ ULONG BytesNeeded;
+ ULONG EntriesReturned;
+ FILE_LINK_ENTRY_FULL_ID_INFORMATION Entry;
+} FILE_LINKS_FULL_ID_INFORMATION;
+typedef FILE_LINKS_FULL_ID_INFORMATION *PFILE_LINKS_FULL_ID_INFORMATION;
+typedef struct _FILE_DISPOSITION_INFORMATION_EX
+{
+ ULONG Flags;
+} FILE_DISPOSITION_INFORMATION_EX;
+typedef FILE_DISPOSITION_INFORMATION_EX *PFILE_DISPOSITION_INFORMATION_EX;
+# ifndef QUERY_STORAGE_CLASSES_FLAGS_MEASURE_WRITE
+typedef struct _FILE_DESIRED_STORAGE_CLASS_INFORMATION
+{
+ /*FILE_STORAGE_TIER_CLASS*/ ULONG Class;
+ ULONG Flags;
+} FILE_DESIRED_STORAGE_CLASS_INFORMATION;
+typedef FILE_DESIRED_STORAGE_CLASS_INFORMATION *PFILE_DESIRED_STORAGE_CLASS_INFORMATION;
+# endif
+typedef struct _FILE_STAT_INFORMATION
+{
+ LARGE_INTEGER FileId;
+ LARGE_INTEGER CreationTime;
+ LARGE_INTEGER LastAccessTime;
+ LARGE_INTEGER LastWriteTime;
+ LARGE_INTEGER ChangeTime;
+ LARGE_INTEGER AllocationSize;
+ LARGE_INTEGER EndOfFile;
+ ULONG FileAttributes;
+ ULONG ReparseTag;
+ ULONG NumberOfLinks;
+ ACCESS_MASK EffectiveAccess;
+} FILE_STAT_INFORMATION;
+typedef FILE_STAT_INFORMATION *PFILE_STAT_INFORMATION;
+typedef struct _FILE_STAT_LX_INFORMATION
+{
+ LARGE_INTEGER FileId;
+ LARGE_INTEGER CreationTime;
+ LARGE_INTEGER LastAccessTime;
+ LARGE_INTEGER LastWriteTime;
+ LARGE_INTEGER ChangeTime;
+ LARGE_INTEGER AllocationSize;
+ LARGE_INTEGER EndOfFile;
+ ULONG FileAttributes;
+ ULONG ReparseTag;
+ ULONG NumberOfLinks;
+ ACCESS_MASK EffectiveAccess;
+ ULONG LxFlags;
+ ULONG LxUid;
+ ULONG LxGid;
+ ULONG LxMode;
+ ULONG LxDeviceIdMajor;
+ ULONG LxDeviceIdMinor;
+} FILE_STAT_LX_INFORMATION;
+typedef FILE_STAT_LX_INFORMATION *PFILE_STAT_LX_INFORMATION;
+typedef struct _FILE_CASE_SENSITIVE_INFORMATION
+{
+ ULONG Flags;
+} FILE_CASE_SENSITIVE_INFORMATION;
+typedef FILE_CASE_SENSITIVE_INFORMATION *PFILE_CASE_SENSITIVE_INFORMATION;
+
+typedef enum _FILE_INFORMATION_CLASS
+{
+ FileDirectoryInformation = 1,
+ FileFullDirectoryInformation,
+ FileBothDirectoryInformation,
+ FileBasicInformation,
+ FileStandardInformation,
+ FileInternalInformation,
+ FileEaInformation,
+ FileAccessInformation,
+ FileNameInformation,
+ FileRenameInformation,
+ FileLinkInformation,
+ FileNamesInformation,
+ FileDispositionInformation,
+ FilePositionInformation,
+ FileFullEaInformation,
+ FileModeInformation,
+ FileAlignmentInformation,
+ FileAllInformation,
+ FileAllocationInformation,
+ FileEndOfFileInformation,
+ FileAlternateNameInformation,
+ FileStreamInformation,
+ FilePipeInformation,
+ FilePipeLocalInformation,
+ FilePipeRemoteInformation,
+ FileMailslotQueryInformation,
+ FileMailslotSetInformation,
+ FileCompressionInformation,
+ FileObjectIdInformation,
+ FileCompletionInformation,
+ FileMoveClusterInformation,
+ FileQuotaInformation,
+ FileReparsePointInformation,
+ FileNetworkOpenInformation,
+ FileAttributeTagInformation,
+ FileTrackingInformation,
+ FileIdBothDirectoryInformation,
+ FileIdFullDirectoryInformation,
+ FileValidDataLengthInformation,
+ FileShortNameInformation,
+ FileIoCompletionNotificationInformation,
+ FileIoStatusBlockRangeInformation,
+ FileIoPriorityHintInformation,
+ FileSfioReserveInformation,
+ FileSfioVolumeInformation,
+ FileHardLinkInformation,
+ FileProcessIdsUsingFileInformation,
+ FileNormalizedNameInformation,
+ FileNetworkPhysicalNameInformation,
+ FileIdGlobalTxDirectoryInformation,
+ FileIsRemoteDeviceInformation,
+ FileUnusedInformation,
+ FileNumaNodeInformation,
+ FileStandardLinkInformation,
+ FileRemoteProtocolInformation,
+ /* Defined with Windows 10: */
+ FileRenameInformationBypassAccessCheck,
+ FileLinkInformationBypassAccessCheck,
+ FileVolumeNameInformation,
+ FileIdInformation,
+ FileIdExtdDirectoryInformation,
+ FileReplaceCompletionInformation,
+ FileHardLinkFullIdInformation,
+ FileIdExtdBothDirectoryInformation,
+ FileDispositionInformationEx,
+ FileRenameInformationEx,
+ FileRenameInformationExBypassAccessCheck,
+ FileDesiredStorageClassInformation,
+ FileStatInformation,
+ FileMemoryPartitionInformation,
+ FileStatLxInformation,
+ FileCaseSensitiveInformation,
+ FileLinkInformationEx,
+ FileLinkInformationExBypassAccessCheck,
+ FileStorageReserveIdInformation,
+ FileCaseSensitiveInformationForceAccessCheck,
+ FileMaximumInformation
+} FILE_INFORMATION_CLASS;
+typedef FILE_INFORMATION_CLASS *PFILE_INFORMATION_CLASS;
+RT_DECL_NTAPI(NTSTATUS) NtQueryInformationFile(HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG, FILE_INFORMATION_CLASS);
+RT_DECL_NTAPI(NTSTATUS) NtQueryDirectoryFile(HANDLE, HANDLE, PIO_APC_ROUTINE, PVOID, PIO_STATUS_BLOCK, PVOID, ULONG,
+ FILE_INFORMATION_CLASS, BOOLEAN, PUNICODE_STRING, BOOLEAN);
+RT_DECL_NTAPI(NTSTATUS) NtSetInformationFile(HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG, FILE_INFORMATION_CLASS);
+#endif /* IPRT_NT_USE_WINTERNL */
+RT_DECL_NTAPI(NTSTATUS) NtQueryAttributesFile(POBJECT_ATTRIBUTES, PFILE_BASIC_INFORMATION);
+RT_DECL_NTAPI(NTSTATUS) NtQueryFullAttributesFile(POBJECT_ATTRIBUTES, PFILE_NETWORK_OPEN_INFORMATION);
+
+
+/** @name SE_GROUP_XXX - Attributes returned with TokenGroup and others.
+ * @{ */
+#ifndef SE_GROUP_MANDATORY
+# define SE_GROUP_MANDATORY UINT32_C(0x01)
+#endif
+#ifndef SE_GROUP_ENABLED_BY_DEFAULT
+# define SE_GROUP_ENABLED_BY_DEFAULT UINT32_C(0x02)
+#endif
+#ifndef SE_GROUP_ENABLED
+# define SE_GROUP_ENABLED UINT32_C(0x04)
+#endif
+#ifndef SE_GROUP_OWNER
+# define SE_GROUP_OWNER UINT32_C(0x08)
+#endif
+#ifndef SE_GROUP_USE_FOR_DENY_ONLY
+# define SE_GROUP_USE_FOR_DENY_ONLY UINT32_C(0x10)
+#endif
+#ifndef SE_GROUP_INTEGRITY
+# define SE_GROUP_INTEGRITY UINT32_C(0x20)
+#endif
+#ifndef SE_GROUP_INTEGRITY_ENABLED
+# define SE_GROUP_INTEGRITY_ENABLED UINT32_C(0x40)
+#endif
+#ifndef SE_GROUP_RESOURCE
+# define SE_GROUP_RESOURCE UINT32_C(0x20000000)
+#endif
+#ifndef SE_GROUP_LOGON_ID
+# define SE_GROUP_LOGON_ID UINT32_C(0xc0000000)
+#endif
+/** @} */
+
+
+#ifdef IPRT_NT_USE_WINTERNL
+
+/** For use with KeyBasicInformation. */
+typedef struct _KEY_BASIC_INFORMATION
+{
+ LARGE_INTEGER LastWriteTime;
+ ULONG TitleIndex;
+ ULONG NameLength;
+ WCHAR Name[1];
+} KEY_BASIC_INFORMATION;
+typedef KEY_BASIC_INFORMATION *PKEY_BASIC_INFORMATION;
+
+/** For use with KeyNodeInformation. */
+typedef struct _KEY_NODE_INFORMATION
+{
+ LARGE_INTEGER LastWriteTime;
+ ULONG TitleIndex;
+ ULONG ClassOffset; /**< Offset from the start of the structure. */
+ ULONG ClassLength;
+ ULONG NameLength;
+ WCHAR Name[1];
+} KEY_NODE_INFORMATION;
+typedef KEY_NODE_INFORMATION *PKEY_NODE_INFORMATION;
+
+/** For use with KeyFullInformation. */
+typedef struct _KEY_FULL_INFORMATION
+{
+ LARGE_INTEGER LastWriteTime;
+ ULONG TitleIndex;
+ ULONG ClassOffset; /**< Offset of the Class member. */
+ ULONG ClassLength;
+ ULONG SubKeys;
+ ULONG MaxNameLen;
+ ULONG MaxClassLen;
+ ULONG Values;
+ ULONG MaxValueNameLen;
+ ULONG MaxValueDataLen;
+ WCHAR Class[1];
+} KEY_FULL_INFORMATION;
+typedef KEY_FULL_INFORMATION *PKEY_FULL_INFORMATION;
+
+/** For use with KeyNameInformation. */
+typedef struct _KEY_NAME_INFORMATION
+{
+ ULONG NameLength;
+ WCHAR Name[1];
+} KEY_NAME_INFORMATION;
+typedef KEY_NAME_INFORMATION *PKEY_NAME_INFORMATION;
+
+/** For use with KeyCachedInformation. */
+typedef struct _KEY_CACHED_INFORMATION
+{
+ LARGE_INTEGER LastWriteTime;
+ ULONG TitleIndex;
+ ULONG SubKeys;
+ ULONG MaxNameLen;
+ ULONG Values;
+ ULONG MaxValueNameLen;
+ ULONG MaxValueDataLen;
+ ULONG NameLength;
+} KEY_CACHED_INFORMATION;
+typedef KEY_CACHED_INFORMATION *PKEY_CACHED_INFORMATION;
+
+/** For use with KeyVirtualizationInformation. */
+typedef struct _KEY_VIRTUALIZATION_INFORMATION
+{
+ ULONG VirtualizationCandidate : 1;
+ ULONG VirtualizationEnabled : 1;
+ ULONG VirtualTarget : 1;
+ ULONG VirtualStore : 1;
+ ULONG VirtualSource : 1;
+ ULONG Reserved : 27;
+} KEY_VIRTUALIZATION_INFORMATION;
+typedef KEY_VIRTUALIZATION_INFORMATION *PKEY_VIRTUALIZATION_INFORMATION;
+
+typedef enum _KEY_INFORMATION_CLASS
+{
+ KeyBasicInformation = 0,
+ KeyNodeInformation,
+ KeyFullInformation,
+ KeyNameInformation,
+ KeyCachedInformation,
+ KeyFlagsInformation,
+ KeyVirtualizationInformation,
+ KeyHandleTagsInformation,
+ MaxKeyInfoClass
+} KEY_INFORMATION_CLASS;
+RT_DECL_NTAPI(NTSTATUS) NtQueryKey(HANDLE, KEY_INFORMATION_CLASS, PVOID, ULONG, PULONG);
+RT_DECL_NTAPI(NTSTATUS) NtEnumerateKey(HANDLE, ULONG, KEY_INFORMATION_CLASS, PVOID, ULONG, PULONG);
+
+typedef struct _MEMORY_SECTION_NAME
+{
+ UNICODE_STRING SectionFileName;
+ WCHAR NameBuffer[1];
+} MEMORY_SECTION_NAME;
+
+#ifdef IPRT_NT_USE_WINTERNL
+typedef struct _PROCESS_BASIC_INFORMATION
+{
+ NTSTATUS ExitStatus;
+ PPEB PebBaseAddress;
+ ULONG_PTR AffinityMask;
+ int32_t BasePriority;
+ ULONG_PTR UniqueProcessId;
+ ULONG_PTR InheritedFromUniqueProcessId;
+} PROCESS_BASIC_INFORMATION;
+typedef PROCESS_BASIC_INFORMATION *PPROCESS_BASIC_INFORMATION;
+#endif
+
+typedef enum _PROCESSINFOCLASS
+{
+ ProcessBasicInformation = 0, /**< 0 / 0x00 */
+ ProcessQuotaLimits, /**< 1 / 0x01 */
+ ProcessIoCounters, /**< 2 / 0x02 */
+ ProcessVmCounters, /**< 3 / 0x03 */
+ ProcessTimes, /**< 4 / 0x04 */
+ ProcessBasePriority, /**< 5 / 0x05 */
+ ProcessRaisePriority, /**< 6 / 0x06 */
+ ProcessDebugPort, /**< 7 / 0x07 */
+ ProcessExceptionPort, /**< 8 / 0x08 */
+ ProcessAccessToken, /**< 9 / 0x09 */
+ ProcessLdtInformation, /**< 10 / 0x0a */
+ ProcessLdtSize, /**< 11 / 0x0b */
+ ProcessDefaultHardErrorMode, /**< 12 / 0x0c */
+ ProcessIoPortHandlers, /**< 13 / 0x0d */
+ ProcessPooledUsageAndLimits, /**< 14 / 0x0e */
+ ProcessWorkingSetWatch, /**< 15 / 0x0f */
+ ProcessUserModeIOPL, /**< 16 / 0x10 */
+ ProcessEnableAlignmentFaultFixup, /**< 17 / 0x11 */
+ ProcessPriorityClass, /**< 18 / 0x12 */
+ ProcessWx86Information, /**< 19 / 0x13 */
+ ProcessHandleCount, /**< 20 / 0x14 */
+ ProcessAffinityMask, /**< 21 / 0x15 */
+ ProcessPriorityBoost, /**< 22 / 0x16 */
+ ProcessDeviceMap, /**< 23 / 0x17 */
+ ProcessSessionInformation, /**< 24 / 0x18 */
+ ProcessForegroundInformation, /**< 25 / 0x19 */
+ ProcessWow64Information, /**< 26 / 0x1a */
+ ProcessImageFileName, /**< 27 / 0x1b */
+ ProcessLUIDDeviceMapsEnabled, /**< 28 / 0x1c */
+ ProcessBreakOnTermination, /**< 29 / 0x1d */
+ ProcessDebugObjectHandle, /**< 30 / 0x1e */
+ ProcessDebugFlags, /**< 31 / 0x1f */
+ ProcessHandleTracing, /**< 32 / 0x20 */
+ ProcessIoPriority, /**< 33 / 0x21 */
+ ProcessExecuteFlags, /**< 34 / 0x22 */
+ ProcessTlsInformation, /**< 35 / 0x23 */
+ ProcessCookie, /**< 36 / 0x24 */
+ ProcessImageInformation, /**< 37 / 0x25 */
+ ProcessCycleTime, /**< 38 / 0x26 */
+ ProcessPagePriority, /**< 39 / 0x27 */
+ ProcessInstrumentationCallbak, /**< 40 / 0x28 */
+ ProcessThreadStackAllocation, /**< 41 / 0x29 */
+ ProcessWorkingSetWatchEx, /**< 42 / 0x2a */
+ ProcessImageFileNameWin32, /**< 43 / 0x2b */
+ ProcessImageFileMapping, /**< 44 / 0x2c */
+ ProcessAffinityUpdateMode, /**< 45 / 0x2d */
+ ProcessMemoryAllocationMode, /**< 46 / 0x2e */
+ ProcessGroupInformation, /**< 47 / 0x2f */
+ ProcessTokenVirtualizationEnabled, /**< 48 / 0x30 */
+ ProcessOwnerInformation, /**< 49 / 0x31 */
+ ProcessWindowInformation, /**< 50 / 0x32 */
+ ProcessHandleInformation, /**< 51 / 0x33 */
+ ProcessMitigationPolicy, /**< 52 / 0x34 */
+ ProcessDynamicFunctionTableInformation, /**< 53 / 0x35 */
+ ProcessHandleCheckingMode, /**< 54 / 0x36 */
+ ProcessKeepAliveCount, /**< 55 / 0x37 */
+ ProcessRevokeFileHandles, /**< 56 / 0x38 */
+ ProcessWorkingSetControl, /**< 57 / 0x39 */
+ ProcessHandleTable, /**< 58 / 0x3a */
+ ProcessCheckStackExtentsMode, /**< 59 / 0x3b */
+ ProcessCommandLineInformation, /**< 60 / 0x3c */
+ ProcessProtectionInformation, /**< 61 / 0x3d */
+ ProcessMemoryExhaustion, /**< 62 / 0x3e */
+ ProcessFaultInformation, /**< 63 / 0x3f */
+ ProcessTelemetryIdInformation, /**< 64 / 0x40 */
+ ProcessCommitReleaseInformation, /**< 65 / 0x41 */
+ ProcessDefaultCpuSetsInformation, /**< 66 / 0x42 - aka ProcessReserved1Information */
+ ProcessAllowedCpuSetsInformation, /**< 67 / 0x43 - aka ProcessReserved2Information; PROCESS_SET_LIMITED_INFORMATION & audiog.exe; W10 */
+ ProcessSubsystemProcess, /**< 68 / 0x44 */
+ ProcessJobMemoryInformation, /**< 69 / 0x45 */
+ ProcessInPrivate, /**< 70 / 0x46 */
+ ProcessRaiseUMExceptionOnInvalidHandleClose,/**< 71 / 0x47 */
+ ProcessIumChallengeResponse, /**< 72 / 0x48 */
+ ProcessChildProcessInformation, /**< 73 / 0x49 */
+ ProcessHighGraphicsPriorityInformation, /**< 74 / 0x4a */
+ ProcessSubsystemInformation, /**< 75 / 0x4b */
+ ProcessEnergyValues, /**< 76 / 0x4c */
+ ProcessPowerThrottlingState, /**< 77 / 0x4d */
+ ProcessReserved3Information, /**< 78 / 0x4e */
+ ProcessWin32kSyscallFilterInformation, /**< 79 / 0x4f */
+ ProcessDisableSystemAllowedCpuSets, /**< 80 / 0x50 */
+ ProcessWakeInformation, /**< 81 / 0x51 */
+ ProcessEnergyTrackingState, /**< 82 / 0x52 */
+ ProcessManageWritesToExecutableMemory, /**< 83 / 0x53 */
+ ProcessCaptureTrustletLiveDump, /**< 84 / 0x54 */
+ ProcessTelemetryCoverage, /**< 85 / 0x55 */
+ ProcessEnclaveInformation, /**< 86 / 0x56 */
+ ProcessEnableReadWriteVmLogging, /**< 87 / 0x57 */
+ ProcessUptimeInformation, /**< 88 / 0x58 */
+ ProcessImageSection, /**< 89 / 0x59 */
+ ProcessDebugAuthInformation, /**< 90 / 0x5a */
+ ProcessSystemResourceManagement, /**< 92 / 0x5b */
+ ProcessSequenceNumber, /**< 93 / 0x5c */
+ MaxProcessInfoClass
+} PROCESSINFOCLASS;
+AssertCompile(ProcessSequenceNumber == 0x5c);
+#endif
+#if defined(IPRT_NT_USE_WINTERNL) || defined(WDK_NTDDI_VERSION) /* Present in ntddk.h from 7600.16385.1, but not in W10. */
+RT_DECL_NTAPI(NTSTATUS) NtQueryInformationProcess(HANDLE, PROCESSINFOCLASS, PVOID, ULONG, PULONG);
+#endif
+#ifdef IPRT_NT_USE_WINTERNL
+#if ARCH_BITS == 32
+/** 64-bit API pass thru to WOW64 processes. */
+RT_DECL_NTAPI(NTSTATUS) NtWow64QueryInformationProcess64(HANDLE, PROCESSINFOCLASS, PVOID, ULONG, PULONG);
+#endif
+
+typedef enum _THREADINFOCLASS
+{
+ ThreadBasicInformation = 0,
+ ThreadTimes,
+ ThreadPriority,
+ ThreadBasePriority,
+ ThreadAffinityMask,
+ ThreadImpersonationToken,
+ ThreadDescriptorTableEntry,
+ ThreadEnableAlignmentFaultFixup,
+ ThreadEventPair_Reusable,
+ ThreadQuerySetWin32StartAddress,
+ ThreadZeroTlsCell,
+ ThreadPerformanceCount,
+ ThreadAmILastThread,
+ ThreadIdealProcessor,
+ ThreadPriorityBoost,
+ ThreadSetTlsArrayAddress,
+ ThreadIsIoPending,
+ ThreadHideFromDebugger,
+ ThreadBreakOnTermination,
+ ThreadSwitchLegacyState,
+ ThreadIsTerminated,
+ ThreadLastSystemCall,
+ ThreadIoPriority,
+ ThreadCycleTime,
+ ThreadPagePriority,
+ ThreadActualBasePriority,
+ ThreadTebInformation,
+ ThreadCSwitchMon,
+ ThreadCSwitchPmu,
+ ThreadWow64Context,
+ ThreadGroupInformation,
+ ThreadUmsInformation,
+ ThreadCounterProfiling,
+ ThreadIdealProcessorEx,
+ ThreadCpuAccountingInformation,
+ MaxThreadInfoClass
+} THREADINFOCLASS;
+RT_DECL_NTAPI(NTSTATUS) NtSetInformationThread(HANDLE, THREADINFOCLASS, LPCVOID, ULONG);
+
+RT_DECL_NTAPI(NTSTATUS) NtQueryInformationToken(HANDLE, TOKEN_INFORMATION_CLASS, PVOID, ULONG, PULONG);
+RT_DECL_NTAPI(NTSTATUS) ZwQueryInformationToken(HANDLE, TOKEN_INFORMATION_CLASS, PVOID, ULONG, PULONG);
+
+RT_DECL_NTAPI(NTSTATUS) NtReadFile(HANDLE, HANDLE, PIO_APC_ROUTINE, PVOID, PIO_STATUS_BLOCK, PVOID, ULONG, PLARGE_INTEGER, PULONG);
+RT_DECL_NTAPI(NTSTATUS) NtWriteFile(HANDLE, HANDLE, PIO_APC_ROUTINE, void const *, PIO_STATUS_BLOCK, PVOID, ULONG, PLARGE_INTEGER, PULONG);
+RT_DECL_NTAPI(NTSTATUS) NtFlushBuffersFile(HANDLE, PIO_STATUS_BLOCK);
+RT_DECL_NTAPI(NTSTATUS) NtCancelIoFile(HANDLE, PIO_STATUS_BLOCK);
+
+RT_DECL_NTAPI(NTSTATUS) NtReadVirtualMemory(HANDLE, PVOID, PVOID, SIZE_T, PSIZE_T);
+RT_DECL_NTAPI(NTSTATUS) NtWriteVirtualMemory(HANDLE, PVOID, void const *, SIZE_T, PSIZE_T);
+
+RT_DECL_NTAPI(NTSTATUS) RtlAddAccessAllowedAce(PACL, ULONG, ULONG, PSID);
+RT_DECL_NTAPI(NTSTATUS) RtlCopySid(ULONG, PSID, PSID);
+RT_DECL_NTAPI(NTSTATUS) RtlCreateAcl(PACL, ULONG, ULONG);
+RT_DECL_NTAPI(NTSTATUS) RtlCreateSecurityDescriptor(PSECURITY_DESCRIPTOR, ULONG);
+RT_DECL_NTAPI(BOOLEAN) RtlEqualSid(PSID, PSID);
+RT_DECL_NTAPI(NTSTATUS) RtlGetVersion(PRTL_OSVERSIONINFOW);
+RT_DECL_NTAPI(NTSTATUS) RtlInitializeSid(PSID, PSID_IDENTIFIER_AUTHORITY, UCHAR);
+RT_DECL_NTAPI(NTSTATUS) RtlSetDaclSecurityDescriptor(PSECURITY_DESCRIPTOR, BOOLEAN, PACL, BOOLEAN);
+RT_DECL_NTAPI(PULONG) RtlSubAuthoritySid(PSID, ULONG);
+
+#endif /* IPRT_NT_USE_WINTERNL */
+
+#ifdef RTNT_NEED_NT_GET_PRODUCT_TYPE
+RT_DECL_NTAPI(BOOLEAN) RtlGetNtProductType(enum _NT_PRODUCT_TYPE *); /**< @since NT 3.1 */
+#endif
+
+/** For use with ObjectBasicInformation.
+ * A watered down version of this struct appears under the name
+ * PUBLIC_OBJECT_BASIC_INFORMATION in ntifs.h. It only defines
+ * the first four members, so don't trust the rest. */
+typedef struct _OBJECT_BASIC_INFORMATION
+{
+ ULONG Attributes;
+ ACCESS_MASK GrantedAccess;
+ ULONG HandleCount;
+ ULONG PointerCount;
+ /* Not in ntifs.h: */
+ ULONG PagedPoolCharge;
+ ULONG NonPagedPoolCharge;
+ ULONG Reserved[3];
+ ULONG NameInfoSize;
+ ULONG TypeInfoSize;
+ ULONG SecurityDescriptorSize;
+ LARGE_INTEGER CreationTime;
+} OBJECT_BASIC_INFORMATION;
+typedef OBJECT_BASIC_INFORMATION *POBJECT_BASIC_INFORMATION;
+
+/** For use with ObjectHandleFlagInformation. */
+typedef struct _OBJECT_HANDLE_FLAG_INFORMATION
+{
+ BOOLEAN Inherit;
+ BOOLEAN ProtectFromClose;
+} OBJECT_HANDLE_FLAG_INFORMATION;
+typedef OBJECT_HANDLE_FLAG_INFORMATION *POBJECT_HANDLE_FLAG_INFORMATION;
+
+/**
+ * Returned via ObjectTypesInformation, see also OBJECT_TYPES_INFORMATION.
+ * The next structure address is calculate:
+ * (uintptr_t)Name.Buffer + RT_ALIGN_32(Name.MaximumLength, sizeof(uintptr_t))
+ */
+typedef struct _OBJECT_TYPE_INFORMATION
+{ /* 64-bit offset */
+ UNICODE_STRING TypeName; /**< 0x00 */
+ ULONG TotalNumberOfObjects; /**< 0x10 */
+ ULONG TotalNumberOfHandles; /**< 0x14 */
+ ULONG TotalPagedPoolUsage; /**< 0x18 - not set by W10 19044 */
+ ULONG TotalNonPagedPoolUsage; /**< 0x1c - not set by W10 19044 */
+ ULONG TotalNamePoolUsage; /**< 0x20 - not set by W10 19044 */
+ ULONG TotalHandleTableUsage; /**< 0x24 - not set by W10 19044 */
+ ULONG HighWaterNumberOfObjects; /**< 0x28 */
+ ULONG HighWaterNumberOfHandles; /**< 0x2c */
+ ULONG HighWaterPagedPoolUsage; /**< 0x30 - not set by W10 19044 */
+ ULONG HighWaterNonPagedPoolUsage; /**< 0x34 - not set by W10 19044 */
+ ULONG HighWaterNamePoolUsage; /**< 0x38 - not set by W10 19044 */
+ ULONG HighWaterHandleTableUsage; /**< 0x3c - not set by W10 19044 */
+ ULONG InvalidAttributes; /**< 0x40 */
+ GENERIC_MAPPING GenericMapping; /**< 0x44 */
+ ULONG ValidAccessMask; /**< 0x54 */
+ BOOLEAN SecurityRequired; /**< 0x58 */
+ BOOLEAN MaintainHandleCount; /**< 0x59 */
+ UCHAR TypeIndex; /**< 0x5a */
+ UCHAR ReservedZero; /**< 0x5b */
+ ULONG PoolType; /**< 0x5c */
+ ULONG DefaultPagedPoolCharge; /**< 0x60 - not set by W10 19044 */
+ ULONG DefaultNonPagedPoolCharge; /**< 0x64 - not set by W10 19044 */
+ /* The name string follows after the structure. */
+} OBJECT_TYPE_INFORMATION;
+AssertCompileSize(OBJECT_TYPE_INFORMATION, sizeof(UNICODE_STRING) + 0x58);
+typedef OBJECT_TYPE_INFORMATION *POBJECT_TYPE_INFORMATION;
+
+/** Returned via ObjectTypesInformation. */
+typedef struct _OBJECT_TYPES_INFORMATION
+{
+ ULONG NumberOfTypes;
+ OBJECT_TYPE_INFORMATION FirstType;
+} OBJECT_TYPES_INFORMATION;
+typedef OBJECT_TYPES_INFORMATION *POBJECT_TYPES_INFORMATION;
+
+typedef enum _OBJECT_INFORMATION_CLASS
+{
+ ObjectBasicInformation = 0,
+ ObjectNameInformation,
+ ObjectTypeInformation,
+ ObjectTypesInformation,
+ ObjectHandleFlagInformation,
+ ObjectSessionInformation,
+ MaxObjectInfoClass
+} OBJECT_INFORMATION_CLASS;
+typedef OBJECT_INFORMATION_CLASS *POBJECT_INFORMATION_CLASS;
+#ifdef IN_RING0
+# define NtQueryObject ZwQueryObject
+#endif
+RT_DECL_NTAPI(NTSTATUS) NtQueryObject(HANDLE, OBJECT_INFORMATION_CLASS, PVOID, ULONG, PULONG);
+RT_DECL_NTAPI(NTSTATUS) NtSetInformationObject(HANDLE, OBJECT_INFORMATION_CLASS, PVOID, ULONG);
+RT_DECL_NTAPI(NTSTATUS) NtDuplicateObject(HANDLE, HANDLE, HANDLE, PHANDLE, ACCESS_MASK, ULONG, ULONG);
+
+RT_DECL_NTAPI(NTSTATUS) NtOpenDirectoryObject(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES);
+
+typedef struct _OBJECT_DIRECTORY_INFORMATION
+{
+ UNICODE_STRING Name;
+ UNICODE_STRING TypeName;
+} OBJECT_DIRECTORY_INFORMATION;
+typedef OBJECT_DIRECTORY_INFORMATION *POBJECT_DIRECTORY_INFORMATION;
+RT_DECL_NTAPI(NTSTATUS) NtQueryDirectoryObject(HANDLE, PVOID, ULONG, BOOLEAN, BOOLEAN, PULONG, PULONG);
+
+RT_DECL_NTAPI(NTSTATUS) NtSuspendProcess(HANDLE);
+RT_DECL_NTAPI(NTSTATUS) NtResumeProcess(HANDLE);
+/** @name ProcessDefaultHardErrorMode bit definitions.
+ * @{ */
+#define PROCESS_HARDERR_CRITICAL_ERROR UINT32_C(0x00000001) /**< Inverted from the win32 define. */
+#define PROCESS_HARDERR_NO_GP_FAULT_ERROR UINT32_C(0x00000002)
+#define PROCESS_HARDERR_NO_ALIGNMENT_FAULT_ERROR UINT32_C(0x00000004)
+#define PROCESS_HARDERR_NO_OPEN_FILE_ERROR UINT32_C(0x00008000)
+/** @} */
+RT_DECL_NTAPI(NTSTATUS) NtSetInformationProcess(HANDLE, PROCESSINFOCLASS, PVOID, ULONG);
+RT_DECL_NTAPI(NTSTATUS) NtTerminateProcess(HANDLE, LONG);
+
+/** Returned by NtQUerySection with SectionBasicInformation. */
+typedef struct _SECTION_BASIC_INFORMATION
+{
+ PVOID BaseAddress;
+ ULONG AllocationAttributes;
+ LARGE_INTEGER MaximumSize;
+} SECTION_BASIC_INFORMATION;
+typedef SECTION_BASIC_INFORMATION *PSECTION_BASIC_INFORMATION;
+
+/** Retured by ProcessImageInformation as well as NtQuerySection. */
+typedef struct _SECTION_IMAGE_INFORMATION
+{
+ PVOID TransferAddress;
+ ULONG ZeroBits;
+ SIZE_T MaximumStackSize;
+ SIZE_T CommittedStackSize;
+ ULONG SubSystemType;
+ union
+ {
+ struct
+ {
+ USHORT SubSystemMinorVersion;
+ USHORT SubSystemMajorVersion;
+ };
+ ULONG SubSystemVersion;
+ };
+ ULONG GpValue;
+ USHORT ImageCharacteristics;
+ USHORT DllCharacteristics;
+ USHORT Machine;
+ BOOLEAN ImageContainsCode;
+ union /**< Since Vista, used to be a spare BOOLEAN. */
+ {
+ struct
+ {
+ UCHAR ComPlusNativeRead : 1;
+ UCHAR ComPlusILOnly : 1;
+ UCHAR ImageDynamicallyRelocated : 1;
+ UCHAR ImageMAppedFlat : 1;
+ UCHAR Reserved : 4;
+ };
+ UCHAR ImageFlags;
+ };
+ ULONG LoaderFlags;
+ ULONG ImageFileSize; /**< Since XP? */
+ ULONG CheckSum; /**< Since Vista, Used to be a reserved/spare ULONG. */
+} SECTION_IMAGE_INFORMATION;
+typedef SECTION_IMAGE_INFORMATION *PSECTION_IMAGE_INFORMATION;
+
+typedef enum _SECTION_INFORMATION_CLASS
+{
+ SectionBasicInformation = 0,
+ SectionImageInformation,
+ MaxSectionInfoClass
+} SECTION_INFORMATION_CLASS;
+RT_DECL_NTAPI(NTSTATUS) NtQuerySection(HANDLE, SECTION_INFORMATION_CLASS, PVOID, SIZE_T, PSIZE_T);
+
+RT_DECL_NTAPI(NTSTATUS) NtCreateSymbolicLinkObject(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, PUNICODE_STRING pTarget);
+RT_DECL_NTAPI(NTSTATUS) NtOpenSymbolicLinkObject(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES);
+RT_DECL_NTAPI(NTSTATUS) NtQuerySymbolicLinkObject(HANDLE, PUNICODE_STRING, PULONG);
+#ifndef SYMBOLIC_LINK_QUERY
+# define SYMBOLIC_LINK_QUERY UINT32_C(0x00000001)
+#endif
+#ifndef SYMBOLIC_LINK_ALL_ACCESS
+# define SYMBOLIC_LINK_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | SYMBOLIC_LINK_QUERY)
+#endif
+
+RT_DECL_NTAPI(NTSTATUS) NtQueryInformationThread(HANDLE, THREADINFOCLASS, PVOID, ULONG, PULONG);
+RT_DECL_NTAPI(NTSTATUS) NtResumeThread(HANDLE, PULONG);
+RT_DECL_NTAPI(NTSTATUS) NtSuspendThread(HANDLE, PULONG);
+RT_DECL_NTAPI(NTSTATUS) NtTerminateThread(HANDLE, LONG);
+RT_DECL_NTAPI(NTSTATUS) NtGetContextThread(HANDLE, PCONTEXT);
+RT_DECL_NTAPI(NTSTATUS) NtSetContextThread(HANDLE, PCONTEXT);
+RT_DECL_NTAPI(NTSTATUS) ZwYieldExecution(void);
+
+
+#ifndef SEC_FILE
+# define SEC_FILE UINT32_C(0x00800000)
+#endif
+#ifndef SEC_IMAGE
+# define SEC_IMAGE UINT32_C(0x01000000)
+#endif
+#ifndef SEC_PROTECTED_IMAGE
+# define SEC_PROTECTED_IMAGE UINT32_C(0x02000000)
+#endif
+#ifndef SEC_NOCACHE
+# define SEC_NOCACHE UINT32_C(0x10000000)
+#endif
+#ifndef MEM_ROTATE
+# define MEM_ROTATE UINT32_C(0x00800000)
+#endif
+typedef enum _MEMORY_INFORMATION_CLASS
+{
+ MemoryBasicInformation = 0,
+ MemoryWorkingSetList,
+ MemorySectionName,
+ MemoryBasicVlmInformation
+} MEMORY_INFORMATION_CLASS;
+#ifndef IPRT_NT_USE_WINTERNL
+# ifndef WDK_NTDDI_VERSION /* W10 ntifs.h has it, 7600.16385.1 didn't. */
+typedef struct _MEMORY_BASIC_INFORMATION
+{
+ PVOID BaseAddress;
+ PVOID AllocationBase;
+ ULONG AllocationProtect;
+# if ARCH_BITS == 64
+ USHORT PartitionId;
+# endif
+ SIZE_T RegionSize;
+ ULONG State;
+ ULONG Protect;
+ ULONG Type;
+} MEMORY_BASIC_INFORMATION;
+typedef MEMORY_BASIC_INFORMATION *PMEMORY_BASIC_INFORMATION;
+# endif
+# define NtQueryVirtualMemory ZwQueryVirtualMemory
+#endif
+#if defined(IPRT_NT_USE_WINTERNL) || !defined(WDK_NTDDI_VERSION) /* W10 ntifs.h has it, 7600.16385.1 didn't. */
+RT_DECL_NTAPI(NTSTATUS) NtQueryVirtualMemory(HANDLE, void const *, MEMORY_INFORMATION_CLASS, PVOID, SIZE_T, PSIZE_T);
+#endif
+#ifdef IPRT_NT_USE_WINTERNL
+RT_DECL_NTAPI(NTSTATUS) NtAllocateVirtualMemory(HANDLE, PVOID *, ULONG, PSIZE_T, ULONG, ULONG);
+RT_DECL_NTAPI(NTSTATUS) NtFreeVirtualMemory(HANDLE, PVOID *, PSIZE_T, ULONG);
+#endif
+RT_DECL_NTAPI(NTSTATUS) NtProtectVirtualMemory(HANDLE, PVOID *, PSIZE_T, ULONG, PULONG);
+
+typedef enum _SYSTEM_INFORMATION_CLASS
+{
+ SystemBasicInformation = 0,
+ SystemCpuInformation,
+ SystemPerformanceInformation,
+ SystemTimeOfDayInformation,
+ SystemInformation_Unknown_4,
+ SystemProcessInformation,
+ SystemInformation_Unknown_6,
+ SystemInformation_Unknown_7,
+ SystemProcessorPerformanceInformation,
+ SystemInformation_Unknown_9,
+ SystemInformation_Unknown_10,
+ SystemModuleInformation,
+ SystemInformation_Unknown_12,
+ SystemInformation_Unknown_13,
+ SystemInformation_Unknown_14,
+ SystemInformation_Unknown_15,
+ SystemHandleInformation,
+ SystemInformation_Unknown_17,
+ SystemPageFileInformation,
+ SystemInformation_Unknown_19,
+ SystemInformation_Unknown_20,
+ SystemCacheInformation,
+ SystemInformation_Unknown_22,
+ SystemInterruptInformation,
+ SystemDpcBehaviourInformation,
+ SystemFullMemoryInformation,
+ SystemLoadGdiDriverInformation, /* 26 */
+ SystemUnloadGdiDriverInformation, /* 27 */
+ SystemTimeAdjustmentInformation,
+ SystemSummaryMemoryInformation,
+ SystemInformation_Unknown_30,
+ SystemInformation_Unknown_31,
+ SystemInformation_Unknown_32,
+ SystemExceptionInformation,
+ SystemCrashDumpStateInformation,
+ SystemKernelDebuggerInformation,
+ SystemContextSwitchInformation,
+ SystemRegistryQuotaInformation,
+ SystemInformation_Unknown_38,
+ SystemInformation_Unknown_39,
+ SystemInformation_Unknown_40,
+ SystemInformation_Unknown_41,
+ SystemInformation_Unknown_42,
+ SystemInformation_Unknown_43,
+ SystemCurrentTimeZoneInformation,
+ SystemLookasideInformation,
+ SystemSetTimeSlipEvent,
+ SystemCreateSession,
+ SystemDeleteSession,
+ SystemInformation_Unknown_49,
+ SystemRangeStartInformation,
+ SystemVerifierInformation,
+ SystemInformation_Unknown_52,
+ SystemSessionProcessInformation,
+ SystemLoadGdiDriverInSystemSpaceInformation, /* 54 */
+ SystemInformation_Unknown_55,
+ SystemInformation_Unknown_56,
+ SystemExtendedProcessInformation,
+ SystemInformation_Unknown_58,
+ SystemInformation_Unknown_59,
+ SystemInformation_Unknown_60,
+ SystemInformation_Unknown_61,
+ SystemInformation_Unknown_62,
+ SystemInformation_Unknown_63,
+ SystemExtendedHandleInformation, /* 64 */
+ SystemInformation_Unknown_65,
+ SystemInformation_Unknown_66,
+ SystemInformation_Unknown_67, /**< See https://www.geoffchappell.com/studies/windows/km/ntoskrnl/api/ex/sysinfo/codeintegrity.htm */
+ SystemInformation_Unknown_68,
+ SystemInformation_HotPatchInfo, /* 69 */
+ SystemInformation_Unknown_70,
+ SystemInformation_Unknown_71,
+ SystemInformation_Unknown_72,
+ SystemInformation_Unknown_73,
+ SystemInformation_Unknown_74,
+ SystemInformation_Unknown_75,
+ SystemInformation_Unknown_76,
+ SystemInformation_Unknown_77,
+ SystemInformation_Unknown_78,
+ SystemInformation_Unknown_79,
+ SystemInformation_Unknown_80,
+ SystemInformation_Unknown_81,
+ SystemInformation_Unknown_82,
+ SystemInformation_Unknown_83,
+ SystemInformation_Unknown_84,
+ SystemInformation_Unknown_85,
+ SystemInformation_Unknown_86,
+ SystemInformation_Unknown_87,
+ SystemInformation_Unknown_88,
+ SystemInformation_Unknown_89,
+ SystemInformation_Unknown_90,
+ SystemInformation_Unknown_91,
+ SystemInformation_Unknown_92,
+ SystemInformation_Unknown_93,
+ SystemInformation_Unknown_94,
+ SystemInformation_Unknown_95,
+ SystemInformation_KiOpPrefetchPatchCount, /* 96 */
+ SystemInformation_Unknown_97,
+ SystemInformation_Unknown_98,
+ SystemInformation_Unknown_99,
+ SystemInformation_Unknown_100,
+ SystemInformation_Unknown_101,
+ SystemInformation_Unknown_102,
+ SystemInformation_Unknown_103,
+ SystemInformation_Unknown_104,
+ SystemInformation_Unknown_105,
+ SystemInformation_Unknown_107,
+ SystemInformation_GetLogicalProcessorInformationEx, /* 107 */
+
+ /** @todo fill gap. they've added a whole bunch of things */
+ SystemPolicyInformation = 134,
+ SystemInformationClassMax
+} SYSTEM_INFORMATION_CLASS;
+
+#ifdef IPRT_NT_USE_WINTERNL
+typedef struct _VM_COUNTERS
+{
+ SIZE_T PeakVirtualSize;
+ SIZE_T VirtualSize;
+ ULONG PageFaultCount;
+ SIZE_T PeakWorkingSetSize;
+ SIZE_T WorkingSetSize;
+ SIZE_T QuotaPeakPagedPoolUsage;
+ SIZE_T QuotaPagedPoolUsage;
+ SIZE_T QuotaPeakNonPagedPoolUsage;
+ SIZE_T QuotaNonPagedPoolUsage;
+ SIZE_T PagefileUsage;
+ SIZE_T PeakPagefileUsage;
+} VM_COUNTERS;
+typedef VM_COUNTERS *PVM_COUNTERS;
+#endif
+
+#if 0
+typedef struct _IO_COUNTERS
+{
+ ULONGLONG ReadOperationCount;
+ ULONGLONG WriteOperationCount;
+ ULONGLONG OtherOperationCount;
+ ULONGLONG ReadTransferCount;
+ ULONGLONG WriteTransferCount;
+ ULONGLONG OtherTransferCount;
+} IO_COUNTERS;
+typedef IO_COUNTERS *PIO_COUNTERS;
+#endif
+
+typedef struct _RTNT_SYSTEM_PROCESS_INFORMATION
+{
+ ULONG NextEntryOffset; /**< 0x00 / 0x00 */
+ ULONG NumberOfThreads; /**< 0x04 / 0x04 */
+ LARGE_INTEGER Reserved1[3]; /**< 0x08 / 0x08 */
+ LARGE_INTEGER CreationTime; /**< 0x20 / 0x20 */
+ LARGE_INTEGER UserTime; /**< 0x28 / 0x28 */
+ LARGE_INTEGER KernelTime; /**< 0x30 / 0x30 */
+ UNICODE_STRING ProcessName; /**< 0x38 / 0x38 Clean unicode encoding? */
+ int32_t BasePriority; /**< 0x40 / 0x48 */
+ HANDLE UniqueProcessId; /**< 0x44 / 0x50 */
+ HANDLE ParentProcessId; /**< 0x48 / 0x58 */
+ ULONG HandleCount; /**< 0x4c / 0x60 */
+ ULONG Reserved2; /**< 0x50 / 0x64 Session ID? */
+ ULONG_PTR Reserved3; /**< 0x54 / 0x68 */
+ VM_COUNTERS VmCounters; /**< 0x58 / 0x70 */
+ IO_COUNTERS IoCounters; /**< 0x88 / 0xd0 Might not be present in earlier windows versions. */
+ /* After this follows the threads, then the ProcessName.Buffer. */
+} RTNT_SYSTEM_PROCESS_INFORMATION;
+typedef RTNT_SYSTEM_PROCESS_INFORMATION *PRTNT_SYSTEM_PROCESS_INFORMATION;
+#ifndef IPRT_NT_USE_WINTERNL
+typedef RTNT_SYSTEM_PROCESS_INFORMATION SYSTEM_PROCESS_INFORMATION;
+typedef SYSTEM_PROCESS_INFORMATION *PSYSTEM_PROCESS_INFORMATION;
+#endif
+
+typedef struct _SYSTEM_HANDLE_ENTRY_INFO
+{
+ USHORT UniqueProcessId;
+ USHORT CreatorBackTraceIndex;
+ UCHAR ObjectTypeIndex;
+ UCHAR HandleAttributes;
+ USHORT HandleValue;
+ PVOID Object;
+ ULONG GrantedAccess;
+} SYSTEM_HANDLE_ENTRY_INFO;
+typedef SYSTEM_HANDLE_ENTRY_INFO *PSYSTEM_HANDLE_ENTRY_INFO;
+
+/** Returned by SystemHandleInformation */
+typedef struct _SYSTEM_HANDLE_INFORMATION
+{
+ ULONG NumberOfHandles;
+ SYSTEM_HANDLE_ENTRY_INFO Handles[1];
+} SYSTEM_HANDLE_INFORMATION;
+typedef SYSTEM_HANDLE_INFORMATION *PSYSTEM_HANDLE_INFORMATION;
+
+/** Extended handle information entry.
+ * @remarks 3 x PVOID + 4 x ULONG = 28 bytes on 32-bit / 40 bytes on 64-bit */
+typedef struct _SYSTEM_HANDLE_ENTRY_INFO_EX
+{
+ PVOID Object;
+ HANDLE UniqueProcessId;
+ HANDLE HandleValue;
+ ACCESS_MASK GrantedAccess;
+ USHORT CreatorBackTraceIndex;
+ USHORT ObjectTypeIndex;
+ ULONG HandleAttributes;
+ ULONG Reserved;
+} SYSTEM_HANDLE_ENTRY_INFO_EX;
+typedef SYSTEM_HANDLE_ENTRY_INFO_EX *PSYSTEM_HANDLE_ENTRY_INFO_EX;
+
+/** Returned by SystemExtendedHandleInformation. */
+typedef struct _SYSTEM_HANDLE_INFORMATION_EX
+{
+ ULONG_PTR NumberOfHandles;
+ ULONG_PTR Reserved;
+ SYSTEM_HANDLE_ENTRY_INFO_EX Handles[1];
+} SYSTEM_HANDLE_INFORMATION_EX;
+typedef SYSTEM_HANDLE_INFORMATION_EX *PSYSTEM_HANDLE_INFORMATION_EX;
+
+/** Returned by SystemSessionProcessInformation. */
+typedef struct _SYSTEM_SESSION_PROCESS_INFORMATION
+{
+ ULONG SessionId;
+ ULONG BufferLength;
+ /** Return buffer, SYSTEM_PROCESS_INFORMATION entries. */
+ PVOID Buffer;
+} SYSTEM_SESSION_PROCESS_INFORMATION;
+typedef SYSTEM_SESSION_PROCESS_INFORMATION *PSYSTEM_SESSION_PROCESS_INFORMATION;
+
+typedef struct _RTL_PROCESS_MODULE_INFORMATION
+{
+ HANDLE Section; /**< 0x00 / 0x00 */
+ PVOID MappedBase; /**< 0x04 / 0x08 */
+ PVOID ImageBase; /**< 0x08 / 0x10 */
+ ULONG ImageSize; /**< 0x0c / 0x18 */
+ ULONG Flags; /**< 0x10 / 0x1c */
+ USHORT LoadOrderIndex; /**< 0x14 / 0x20 */
+ USHORT InitOrderIndex; /**< 0x16 / 0x22 */
+ USHORT LoadCount; /**< 0x18 / 0x24 */
+ USHORT OffsetToFileName; /**< 0x1a / 0x26 */
+ UCHAR FullPathName[256]; /**< 0x1c / 0x28 */
+} RTL_PROCESS_MODULE_INFORMATION;
+typedef RTL_PROCESS_MODULE_INFORMATION *PRTL_PROCESS_MODULE_INFORMATION;
+
+/** Returned by SystemModuleInformation. */
+typedef struct _RTL_PROCESS_MODULES
+{
+ ULONG NumberOfModules;
+ RTL_PROCESS_MODULE_INFORMATION Modules[1]; /**< 0x04 / 0x08 */
+} RTL_PROCESS_MODULES;
+typedef RTL_PROCESS_MODULES *PRTL_PROCESS_MODULES;
+
+RT_DECL_NTAPI(NTSTATUS) NtQuerySystemInformation(SYSTEM_INFORMATION_CLASS, PVOID, ULONG, PULONG);
+#ifndef IPRT_NT_MAP_TO_ZW
+RT_DECL_NTAPI(NTSTATUS) ZwQuerySystemInformation(SYSTEM_INFORMATION_CLASS, PVOID, ULONG, PULONG);
+#endif
+
+RT_DECL_NTAPI(NTSTATUS) NtSetTimerResolution(ULONG cNtTicksWanted, BOOLEAN fSetResolution, PULONG pcNtTicksCur);
+RT_DECL_NTAPI(NTSTATUS) NtQueryTimerResolution(PULONG pcNtTicksMin, PULONG pcNtTicksMax, PULONG pcNtTicksCur);
+
+RT_DECL_NTAPI(NTSTATUS) NtDelayExecution(BOOLEAN, PLARGE_INTEGER);
+RT_DECL_NTAPI(NTSTATUS) NtYieldExecution(void);
+#ifndef IPRT_NT_USE_WINTERNL
+RT_DECL_NTAPI(NTSTATUS) NtWaitForSingleObject(HANDLE, BOOLEAN, PLARGE_INTEGER);
+#endif
+typedef NTSYSAPI NTSTATUS (NTAPI *PFNNTWAITFORSINGLEOBJECT)(HANDLE, BOOLEAN, PLARGE_INTEGER);
+typedef enum _OBJECT_WAIT_TYPE { WaitAllObjects = 0, WaitAnyObject = 1, ObjectWaitTypeHack = 0x7fffffff } OBJECT_WAIT_TYPE;
+RT_DECL_NTAPI(NTSTATUS) NtWaitForMultipleObjects(ULONG, PHANDLE, OBJECT_WAIT_TYPE, BOOLEAN, PLARGE_INTEGER);
+
+#ifdef IPRT_NT_USE_WINTERNL
+RT_DECL_NTAPI(NTSTATUS) NtQuerySecurityObject(HANDLE, ULONG, PSECURITY_DESCRIPTOR, ULONG, PULONG);
+#endif
+
+#ifdef IPRT_NT_USE_WINTERNL
+typedef enum _EVENT_TYPE
+{
+ /* Manual reset event. */
+ NotificationEvent = 0,
+ /* Automaitc reset event. */
+ SynchronizationEvent
+} EVENT_TYPE;
+#endif
+RT_DECL_NTAPI(NTSTATUS) NtCreateEvent(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, EVENT_TYPE, BOOLEAN);
+RT_DECL_NTAPI(NTSTATUS) NtOpenEvent(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES);
+typedef NTSYSAPI NTSTATUS (NTAPI *PFNNTCLEAREVENT)(HANDLE);
+RT_DECL_NTAPI(NTSTATUS) NtClearEvent(HANDLE);
+RT_DECL_NTAPI(NTSTATUS) NtResetEvent(HANDLE, PULONG);
+RT_DECL_NTAPI(NTSTATUS) NtSetEvent(HANDLE, PULONG);
+typedef NTSYSAPI NTSTATUS (NTAPI *PFNNTSETEVENT)(HANDLE, PULONG);
+typedef enum _EVENT_INFORMATION_CLASS
+{
+ EventBasicInformation = 0
+} EVENT_INFORMATION_CLASS;
+/** Data returned by NtQueryEvent + EventBasicInformation. */
+typedef struct EVENT_BASIC_INFORMATION
+{
+ EVENT_TYPE EventType;
+ ULONG EventState;
+} EVENT_BASIC_INFORMATION;
+typedef EVENT_BASIC_INFORMATION *PEVENT_BASIC_INFORMATION;
+RT_DECL_NTAPI(NTSTATUS) NtQueryEvent(HANDLE, EVENT_INFORMATION_CLASS, PVOID, ULONG, PULONG);
+
+#ifdef IPRT_NT_USE_WINTERNL
+/** For NtQueryValueKey. */
+typedef enum _KEY_VALUE_INFORMATION_CLASS
+{
+ KeyValueBasicInformation = 0,
+ KeyValueFullInformation,
+ KeyValuePartialInformation,
+ KeyValueFullInformationAlign64,
+ KeyValuePartialInformationAlign64
+} KEY_VALUE_INFORMATION_CLASS;
+
+/** KeyValuePartialInformation and KeyValuePartialInformationAlign64 struct. */
+typedef struct _KEY_VALUE_PARTIAL_INFORMATION
+{
+ ULONG TitleIndex;
+ ULONG Type;
+ ULONG DataLength;
+ UCHAR Data[1];
+} KEY_VALUE_PARTIAL_INFORMATION;
+typedef KEY_VALUE_PARTIAL_INFORMATION *PKEY_VALUE_PARTIAL_INFORMATION;
+#endif
+RT_DECL_NTAPI(NTSTATUS) NtOpenKey(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES);
+RT_DECL_NTAPI(NTSTATUS) NtQueryValueKey(HANDLE, PUNICODE_STRING, KEY_VALUE_INFORMATION_CLASS, PVOID, ULONG, PULONG);
+
+
+RT_DECL_NTAPI(NTSTATUS) RtlAddAccessDeniedAce(PACL, ULONG, ULONG, PSID);
+
+
+typedef struct _CURDIR
+{
+ UNICODE_STRING DosPath;
+ HANDLE Handle; /**< 0x10 / 0x08 */
+} CURDIR;
+AssertCompileSize(CURDIR, ARCH_BITS == 32 ? 0x0c : 0x18);
+typedef CURDIR *PCURDIR;
+
+typedef struct _RTL_DRIVE_LETTER_CURDIR
+{
+ USHORT Flags;
+ USHORT Length;
+ ULONG TimeStamp;
+ STRING DosPath; /**< Yeah, it's STRING according to dt ntdll!_RTL_DRIVE_LETTER_CURDIR. */
+} RTL_DRIVE_LETTER_CURDIR;
+typedef RTL_DRIVE_LETTER_CURDIR *PRTL_DRIVE_LETTER_CURDIR;
+
+typedef struct _RTL_USER_PROCESS_PARAMETERS
+{
+ ULONG MaximumLength; /**< 0x000 / 0x000 */
+ ULONG Length; /**< 0x004 / 0x004 */
+ ULONG Flags; /**< 0x008 / 0x008 */
+ ULONG DebugFlags; /**< 0x00c / 0x00c */
+ HANDLE ConsoleHandle; /**< 0x010 / 0x010 */
+ ULONG ConsoleFlags; /**< 0x018 / 0x014 */
+ HANDLE StandardInput; /**< 0x020 / 0x018 */
+ HANDLE StandardOutput; /**< 0x028 / 0x01c */
+ HANDLE StandardError; /**< 0x030 / 0x020 */
+ CURDIR CurrentDirectory; /**< 0x038 / 0x024 */
+ UNICODE_STRING DllPath; /**< 0x050 / 0x030 */
+ UNICODE_STRING ImagePathName; /**< 0x060 / 0x038 */
+ UNICODE_STRING CommandLine; /**< 0x070 / 0x040 */
+ PWSTR Environment; /**< 0x080 / 0x048 */
+ ULONG StartingX; /**< 0x088 / 0x04c */
+ ULONG StartingY; /**< 0x090 / 0x050 */
+ ULONG CountX; /**< 0x094 / 0x054 */
+ ULONG CountY; /**< 0x098 / 0x058 */
+ ULONG CountCharsX; /**< 0x09c / 0x05c */
+ ULONG CountCharsY; /**< 0x0a0 / 0x060 */
+ ULONG FillAttribute; /**< 0x0a4 / 0x064 */
+ ULONG WindowFlags; /**< 0x0a8 / 0x068 */
+ ULONG ShowWindowFlags; /**< 0x0ac / 0x06c */
+ UNICODE_STRING WindowTitle; /**< 0x0b0 / 0x070 */
+ UNICODE_STRING DesktopInfo; /**< 0x0c0 / 0x078 */
+ UNICODE_STRING ShellInfo; /**< 0x0d0 / 0x080 */
+ UNICODE_STRING RuntimeInfo; /**< 0x0e0 / 0x088 */
+ RTL_DRIVE_LETTER_CURDIR CurrentDirectories[0x20]; /**< 0x0f0 / 0x090 */
+ SIZE_T EnvironmentSize; /**< 0x3f0 / 0x - Added in Vista */
+ SIZE_T EnvironmentVersion; /**< 0x3f8 / 0x - Added in Windows 7. */
+ PVOID PackageDependencyData; /**< 0x400 / 0x - Added Windows 8? */
+ ULONG ProcessGroupId; /**< 0x408 / 0x - Added Windows 8? */
+ ULONG LoaderThreads; /**< 0x40c / 0x - Added Windows 10? */
+} RTL_USER_PROCESS_PARAMETERS;
+typedef RTL_USER_PROCESS_PARAMETERS *PRTL_USER_PROCESS_PARAMETERS;
+#define RTL_USER_PROCESS_PARAMS_FLAG_NORMALIZED 1
+
+typedef struct _RTL_USER_PROCESS_INFORMATION
+{
+ ULONG Size;
+ HANDLE ProcessHandle;
+ HANDLE ThreadHandle;
+ CLIENT_ID ClientId;
+ SECTION_IMAGE_INFORMATION ImageInformation;
+} RTL_USER_PROCESS_INFORMATION;
+typedef RTL_USER_PROCESS_INFORMATION *PRTL_USER_PROCESS_INFORMATION;
+
+
+RT_DECL_NTAPI(NTSTATUS) RtlCreateUserProcess(PUNICODE_STRING, ULONG, PRTL_USER_PROCESS_PARAMETERS, PSECURITY_DESCRIPTOR,
+ PSECURITY_DESCRIPTOR, HANDLE, BOOLEAN, HANDLE, HANDLE, PRTL_USER_PROCESS_INFORMATION);
+RT_DECL_NTAPI(NTSTATUS) RtlCreateProcessParameters(PRTL_USER_PROCESS_PARAMETERS *, PUNICODE_STRING ImagePathName,
+ PUNICODE_STRING DllPath, PUNICODE_STRING CurrentDirectory,
+ PUNICODE_STRING CommandLine, PUNICODE_STRING Environment,
+ PUNICODE_STRING WindowTitle, PUNICODE_STRING DesktopInfo,
+ PUNICODE_STRING ShellInfo, PUNICODE_STRING RuntimeInfo);
+RT_DECL_NTAPI(VOID) RtlDestroyProcessParameters(PRTL_USER_PROCESS_PARAMETERS);
+RT_DECL_NTAPI(NTSTATUS) RtlCreateUserThread(HANDLE, PSECURITY_DESCRIPTOR, BOOLEAN, ULONG, SIZE_T, SIZE_T,
+ PFNRT, PVOID, PHANDLE, PCLIENT_ID);
+
+#ifndef RTL_CRITICAL_SECTION_FLAG_NO_DEBUG_INFO
+typedef struct _RTL_CRITICAL_SECTION
+{
+ struct _RTL_CRITICAL_SECTION_DEBUG *DebugInfo;
+ LONG LockCount;
+ LONG Recursioncount;
+ HANDLE OwningThread;
+ HANDLE LockSemaphore;
+ ULONG_PTR SpinCount;
+} RTL_CRITICAL_SECTION;
+typedef RTL_CRITICAL_SECTION *PRTL_CRITICAL_SECTION;
+#endif
+
+/*RT_DECL_NTAPI(ULONG) RtlNtStatusToDosError(NTSTATUS rcNt);*/
+
+/** @def RTL_QUERY_REGISTRY_TYPECHECK
+ * WDK 8.1+, backported in updates, ignored in older. */
+#if !defined(RTL_QUERY_REGISTRY_TYPECHECK) || defined(DOXYGEN_RUNNING)
+# define RTL_QUERY_REGISTRY_TYPECHECK UINT32_C(0x00000100)
+#endif
+/** @def RTL_QUERY_REGISTRY_TYPECHECK_SHIFT
+ * WDK 8.1+, backported in updates, ignored in older. */
+#if !defined(RTL_QUERY_REGISTRY_TYPECHECK_SHIFT) || defined(DOXYGEN_RUNNING)
+# define RTL_QUERY_REGISTRY_TYPECHECK_SHIFT 24
+#endif
+
+RT_DECL_NTAPI(VOID) RtlFreeUnicodeString(PUNICODE_STRING);
+
+RT_C_DECLS_END
+/** @} */
+
+
+#if defined(IN_RING0) || defined(DOXYGEN_RUNNING)
+/** @name NT Kernel APIs
+ * @{ */
+RT_C_DECLS_BEGIN
+
+typedef ULONG KEPROCESSORINDEX; /**< Bitmap indexes != process numbers, apparently. */
+
+RT_DECL_NTAPI(VOID) KeInitializeAffinityEx(PKAFFINITY_EX pAffinity);
+typedef VOID (NTAPI *PFNKEINITIALIZEAFFINITYEX)(PKAFFINITY_EX pAffinity);
+RT_DECL_NTAPI(VOID) KeAddProcessorAffinityEx(PKAFFINITY_EX pAffinity, KEPROCESSORINDEX idxProcessor);
+typedef VOID (NTAPI *PFNKEADDPROCESSORAFFINITYEX)(PKAFFINITY_EX pAffinity, KEPROCESSORINDEX idxProcessor);
+RT_DECL_NTAPI(VOID) KeRemoveProcessorAffinityEx(PKAFFINITY_EX pAffinity, KEPROCESSORINDEX idxProcessor);
+typedef VOID (NTAPI *PFNKEREMOVEPROCESSORAFFINITYEX)(PKAFFINITY_EX pAffinity, KEPROCESSORINDEX idxProcessor);
+RT_DECL_NTAPI(BOOLEAN) KeInterlockedSetProcessorAffinityEx(PKAFFINITY_EX pAffinity, KEPROCESSORINDEX idxProcessor);
+typedef BOOLEAN (NTAPI *PFNKEINTERLOCKEDSETPROCESSORAFFINITYEX)(PKAFFINITY_EX pAffinity, KEPROCESSORINDEX idxProcessor);
+RT_DECL_NTAPI(BOOLEAN) KeInterlockedClearProcessorAffinityEx(PKAFFINITY_EX pAffinity, KEPROCESSORINDEX idxProcessor);
+typedef BOOLEAN (NTAPI *PFNKEINTERLOCKEDCLEARPROCESSORAFFINITYEX)(PKAFFINITY_EX pAffinity, KEPROCESSORINDEX idxProcessor);
+RT_DECL_NTAPI(BOOLEAN) KeCheckProcessorAffinityEx(PCKAFFINITY_EX pAffinity, KEPROCESSORINDEX idxProcessor);
+typedef BOOLEAN (NTAPI *PFNKECHECKPROCESSORAFFINITYEX)(PCKAFFINITY_EX pAffinity, KEPROCESSORINDEX idxProcessor);
+RT_DECL_NTAPI(VOID) KeCopyAffinityEx(PKAFFINITY_EX pDst, PCKAFFINITY_EX pSrc);
+typedef VOID (NTAPI *PFNKECOPYAFFINITYEX)(PKAFFINITY_EX pDst, PCKAFFINITY_EX pSrc);
+RT_DECL_NTAPI(VOID) KeComplementAffinityEx(PKAFFINITY_EX pResult, PCKAFFINITY_EX pIn);
+typedef VOID (NTAPI *PFNKECOMPLEMENTAFFINITYEX)(PKAFFINITY_EX pResult, PCKAFFINITY_EX pIn);
+RT_DECL_NTAPI(BOOLEAN) KeAndAffinityEx(PCKAFFINITY_EX pIn1, PCKAFFINITY_EX pIn2, PKAFFINITY_EX pResult OPTIONAL);
+typedef BOOLEAN (NTAPI *PFNKEANDAFFINITYEX)(PCKAFFINITY_EX pIn1, PCKAFFINITY_EX pIn2, PKAFFINITY_EX pResult OPTIONAL);
+RT_DECL_NTAPI(BOOLEAN) KeOrAffinityEx(PCKAFFINITY_EX pIn1, PCKAFFINITY_EX pIn2, PKAFFINITY_EX pResult OPTIONAL);
+typedef BOOLEAN (NTAPI *PFNKEORAFFINITYEX)(PCKAFFINITY_EX pIn1, PCKAFFINITY_EX pIn2, PKAFFINITY_EX pResult OPTIONAL);
+/** Works like anding the complemented subtrahend with the minuend. */
+RT_DECL_NTAPI(BOOLEAN) KeSubtractAffinityEx(PCKAFFINITY_EX pMinuend, PCKAFFINITY_EX pSubtrahend, PKAFFINITY_EX pResult OPTIONAL);
+typedef BOOLEAN (NTAPI *PFNKESUBTRACTAFFINITYEX)(PCKAFFINITY_EX pMinuend, PCKAFFINITY_EX pSubtrahend, PKAFFINITY_EX pResult OPTIONAL);
+RT_DECL_NTAPI(BOOLEAN) KeIsEqualAffinityEx(PCKAFFINITY_EX pLeft, PCKAFFINITY_EX pRight);
+typedef BOOLEAN (NTAPI *PFNKEISEQUALAFFINITYEX)(PCKAFFINITY_EX pLeft, PCKAFFINITY_EX pRight);
+RT_DECL_NTAPI(BOOLEAN) KeIsEmptyAffinityEx(PCKAFFINITY_EX pAffinity);
+typedef BOOLEAN (NTAPI *PFNKEISEMPTYAFFINITYEX)(PCKAFFINITY_EX pAffinity);
+RT_DECL_NTAPI(BOOLEAN) KeIsSubsetAffinityEx(PCKAFFINITY_EX pSubset, PCKAFFINITY_EX pSuperSet);
+typedef BOOLEAN (NTAPI *PFNKEISSUBSETAFFINITYEX)(PCKAFFINITY_EX pSubset, PCKAFFINITY_EX pSuperSet);
+RT_DECL_NTAPI(ULONG) KeCountSetBitsAffinityEx(PCKAFFINITY_EX pAffinity);
+typedef ULONG (NTAPI *PFNKECOUNTSETAFFINITYEX)(PCKAFFINITY_EX pAffinity);
+RT_DECL_NTAPI(KEPROCESSORINDEX) KeFindFirstSetLeftAffinityEx(PCKAFFINITY_EX pAffinity);
+typedef KEPROCESSORINDEX (NTAPI *PFNKEFINDFIRSTSETLEFTAFFINITYEX)(PCKAFFINITY_EX pAffinity);
+typedef NTSTATUS (NTAPI *PFNKEGETPROCESSORNUMBERFROMINDEX)(KEPROCESSORINDEX idxProcessor, PPROCESSOR_NUMBER pProcNumber);
+typedef KEPROCESSORINDEX (NTAPI *PFNKEGETPROCESSORINDEXFROMNUMBER)(const PROCESSOR_NUMBER *pProcNumber);
+typedef NTSTATUS (NTAPI *PFNKEGETPROCESSORNUMBERFROMINDEX)(KEPROCESSORINDEX ProcIndex, PROCESSOR_NUMBER *pProcNumber);
+typedef KEPROCESSORINDEX (NTAPI *PFNKEGETCURRENTPROCESSORNUMBEREX)(const PROCESSOR_NUMBER *pProcNumber);
+typedef KAFFINITY (NTAPI *PFNKEQUERYACTIVEPROCESSORS)(VOID);
+typedef ULONG (NTAPI *PFNKEQUERYMAXIMUMPROCESSORCOUNT)(VOID);
+typedef ULONG (NTAPI *PFNKEQUERYMAXIMUMPROCESSORCOUNTEX)(USHORT GroupNumber);
+typedef USHORT (NTAPI *PFNKEQUERYMAXIMUMGROUPCOUNT)(VOID);
+typedef ULONG (NTAPI *PFNKEQUERYACTIVEPROCESSORCOUNT)(KAFFINITY *pfActiveProcessors);
+typedef ULONG (NTAPI *PFNKEQUERYACTIVEPROCESSORCOUNTEX)(USHORT GroupNumber);
+typedef NTSTATUS (NTAPI *PFNKEQUERYLOGICALPROCESSORRELATIONSHIP)(PROCESSOR_NUMBER *pProcNumber,
+ LOGICAL_PROCESSOR_RELATIONSHIP RelationShipType,
+ SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *pInfo, PULONG pcbInfo);
+typedef PVOID (NTAPI *PFNKEREGISTERPROCESSORCHANGECALLBACK)(PPROCESSOR_CALLBACK_FUNCTION pfnCallback, void *pvUser, ULONG fFlags);
+typedef VOID (NTAPI *PFNKEDEREGISTERPROCESSORCHANGECALLBACK)(PVOID pvCallback);
+typedef NTSTATUS (NTAPI *PFNKESETTARGETPROCESSORDPCEX)(KDPC *pDpc, PROCESSOR_NUMBER *pProcNumber);
+typedef LOGICAL (NTAPI *PFNKESHOULDYIELDPROCESSOR)(void);
+
+RT_DECL_NTAPI(BOOLEAN) ObFindHandleForObject(PEPROCESS pProcess, PVOID pvObject, POBJECT_TYPE pObjectType,
+ PVOID pvOptionalConditions, PHANDLE phFound);
+RT_DECL_NTAPI(NTSTATUS) ObReferenceObjectByName(PUNICODE_STRING pObjectPath, ULONG fAttributes, PACCESS_STATE pAccessState,
+ ACCESS_MASK fDesiredAccess, POBJECT_TYPE pObjectType,
+ KPROCESSOR_MODE enmAccessMode, PVOID pvParseContext, PVOID *ppvObject);
+RT_DECL_NTAPI(HANDLE) PsGetProcessInheritedFromUniqueProcessId(PEPROCESS);
+RT_DECL_NTAPI(UCHAR *) PsGetProcessImageFileName(PEPROCESS);
+RT_DECL_NTAPI(BOOLEAN) PsIsProcessBeingDebugged(PEPROCESS);
+RT_DECL_NTAPI(ULONG) PsGetProcessSessionId(PEPROCESS);
+extern DECLIMPORT(POBJECT_TYPE *) LpcPortObjectType; /**< In vista+ this is the ALPC port object type. */
+extern DECLIMPORT(POBJECT_TYPE *) LpcWaitablePortObjectType; /**< In vista+ this is the ALPC port object type. */
+
+typedef VOID (NTAPI *PFNHALREQUESTIPI_PRE_W7)(KAFFINITY TargetSet);
+typedef VOID (NTAPI *PFNHALREQUESTIPI_W7PLUS)(ULONG uUsuallyZero, PCKAFFINITY_EX pTargetSet);
+
+RT_C_DECLS_END
+/** @ */
+#endif /* IN_RING0 */
+
+
+#if defined(IN_RING3) || defined(DOXYGEN_RUNNING)
+/** @name NT Userland APIs
+ * @{ */
+RT_C_DECLS_BEGIN
+
+#if 0 /** @todo figure this out some time... */
+typedef struct CSR_MSG_DATA_CREATED_PROCESS
+{
+ HANDLE hProcess;
+ HANDLE hThread;
+ CLIENT_ID
+ DWORD idProcess;
+ DWORD idThread;
+ DWORD fCreate;
+
+} CSR_MSG_DATA_CREATED_PROCESS;
+
+#define CSR_MSG_NO_CREATED_PROCESS UINT32_C(0x10000)
+#define CSR_MSG_NO_CREATED_THREAD UINT32_C(0x10001)
+RT_DECL_NTAPI(NTSTATUS) CsrClientCallServer(PVOID, PVOID, ULONG, SIZE_T);
+#endif
+
+RT_DECL_NTAPI(VOID) LdrInitializeThunk(PVOID, PVOID, PVOID);
+
+typedef struct _LDR_DLL_LOADED_NOTIFICATION_DATA
+{
+ ULONG Flags;
+ PCUNICODE_STRING FullDllName;
+ PCUNICODE_STRING BaseDllName;
+ PVOID DllBase;
+ ULONG SizeOfImage;
+} LDR_DLL_LOADED_NOTIFICATION_DATA, LDR_DLL_UNLOADED_NOTIFICATION_DATA;
+typedef LDR_DLL_LOADED_NOTIFICATION_DATA *PLDR_DLL_LOADED_NOTIFICATION_DATA, *PLDR_DLL_UNLOADED_NOTIFICATION_DATA;
+typedef LDR_DLL_LOADED_NOTIFICATION_DATA const *PCLDR_DLL_LOADED_NOTIFICATION_DATA, *PCLDR_DLL_UNLOADED_NOTIFICATION_DATA;
+
+typedef union _LDR_DLL_NOTIFICATION_DATA
+{
+ LDR_DLL_LOADED_NOTIFICATION_DATA Loaded;
+ LDR_DLL_UNLOADED_NOTIFICATION_DATA Unloaded;
+} LDR_DLL_NOTIFICATION_DATA;
+typedef LDR_DLL_NOTIFICATION_DATA *PLDR_DLL_NOTIFICATION_DATA;
+typedef LDR_DLL_NOTIFICATION_DATA const *PCLDR_DLL_NOTIFICATION_DATA;
+
+typedef VOID (NTAPI *PLDR_DLL_NOTIFICATION_FUNCTION)(ULONG ulReason, PCLDR_DLL_NOTIFICATION_DATA pData, PVOID pvUser);
+
+#define LDR_DLL_NOTIFICATION_REASON_LOADED UINT32_C(1)
+#define LDR_DLL_NOTIFICATION_REASON_UNLOADED UINT32_C(2)
+RT_DECL_NTAPI(NTSTATUS) LdrRegisterDllNotification(ULONG fFlags, PLDR_DLL_NOTIFICATION_FUNCTION pfnCallback, PVOID pvUser,
+ PVOID *pvCookie);
+typedef NTSTATUS (NTAPI *PFNLDRREGISTERDLLNOTIFICATION)(ULONG, PLDR_DLL_NOTIFICATION_FUNCTION, PVOID, PVOID *);
+RT_DECL_NTAPI(NTSTATUS) LdrUnregisterDllNotification(PVOID pvCookie);
+typedef NTSTATUS (NTAPI *PFNLDRUNREGISTERDLLNOTIFICATION)(PVOID);
+
+RT_DECL_NTAPI(NTSTATUS) LdrLoadDll(IN PWSTR pwszSearchPathOrFlags OPTIONAL, IN PULONG pfFlags OPTIONAL,
+ IN PCUNICODE_STRING pName, OUT PHANDLE phMod);
+typedef NTSTATUS (NTAPI *PFNLDRLOADDLL)(IN PWSTR pwszSearchPathOrFlags OPTIONAL, IN PULONG pfFlags OPTIONAL,
+ IN PCUNICODE_STRING pName, OUT PHANDLE phMod);
+RT_DECL_NTAPI(NTSTATUS) LdrUnloadDll(IN HANDLE hMod);
+typedef NTSTATUS (NTAPI *PFNLDRUNLOADDLL)(IN HANDLE hMod);
+RT_DECL_NTAPI(NTSTATUS) LdrGetDllHandle(IN PCWSTR pwszDllPath OPTIONAL, IN PULONG pfFlags OPTIONAL,
+ IN PCUNICODE_STRING pName, OUT PHANDLE phDll);
+typedef NTSTATUS (NTAPI *PFNLDRGETDLLHANDLE)(IN PCWSTR pwszDllPath OPTIONAL, IN PULONG pfFlags OPTIONAL,
+ IN PCUNICODE_STRING pName, OUT PHANDLE phDll);
+#define LDRGETDLLHANDLEEX_F_UNCHANGED_REFCOUNT RT_BIT_32(0)
+#define LDRGETDLLHANDLEEX_F_PIN RT_BIT_32(1)
+/** @since Windows XP. */
+RT_DECL_NTAPI(NTSTATUS) LdrGetDllHandleEx(IN ULONG fFlags, IN PCWSTR pwszDllPath OPTIONAL, IN PULONG pfFlags OPTIONAL,
+ IN PCUNICODE_STRING pName, OUT PHANDLE phDll);
+/** @since Windows XP. */
+typedef NTSTATUS (NTAPI *PFNLDRGETDLLHANDLEEX)(IN ULONG fFlags, IN PCWSTR pwszDllPath OPTIONAL, IN PULONG pfFlags OPTIONAL,
+ IN PCUNICODE_STRING pName, OUT PHANDLE phDll);
+/** @since Windows 7. */
+RT_DECL_NTAPI(NTSTATUS) LdrGetDllHandleByMapping(IN PVOID pvBase, OUT PHANDLE phDll);
+/** @since Windows 7. */
+typedef NTSTATUS (NTAPI *PFNLDRGETDLLHANDLEBYMAPPING)(IN PVOID pvBase, OUT PHANDLE phDll);
+/** @since Windows 7. */
+RT_DECL_NTAPI(NTSTATUS) LdrGetDllHandleByName(IN PCUNICODE_STRING pName OPTIONAL, IN PCUNICODE_STRING pFullName OPTIONAL,
+ OUT PHANDLE phDll);
+/** @since Windows 7. */
+typedef NTSTATUS (NTAPI *PFNLDRGETDLLHANDLEBYNAME)(IN PCUNICODE_STRING pName OPTIONAL, IN PCUNICODE_STRING pFullName OPTIONAL,
+ OUT PHANDLE phDll);
+#define LDRADDREFDLL_F_PIN RT_BIT_32(0)
+RT_DECL_NTAPI(NTSTATUS) LdrAddRefDll(IN ULONG fFlags, IN HANDLE hDll);
+typedef NTSTATUS (NTAPI *PFNLDRADDREFDLL)(IN ULONG fFlags, IN HANDLE hDll);
+RT_DECL_NTAPI(NTSTATUS) LdrGetProcedureAddress(IN HANDLE hDll, IN ANSI_STRING const *pSymbol OPTIONAL,
+ IN ULONG uOrdinal OPTIONAL, OUT PVOID *ppvSymbol);
+typedef NTSTATUS (NTAPI *PFNLDRGETPROCEDUREADDRESS)(IN HANDLE hDll, IN PCANSI_STRING pSymbol OPTIONAL,
+ IN ULONG uOrdinal OPTIONAL, OUT PVOID *ppvSymbol);
+#define LDRGETPROCEDUREADDRESSEX_F_DONT_RECORD_FORWARDER RT_BIT_32(0)
+/** @since Windows Vista. */
+RT_DECL_NTAPI(NTSTATUS) LdrGetProcedureAddressEx(IN HANDLE hDll, IN ANSI_STRING const *pSymbol OPTIONAL,
+ IN ULONG uOrdinal OPTIONAL, OUT PVOID *ppvSymbol, ULONG fFlags);
+/** @since Windows Vista. */
+typedef NTSTATUS (NTAPI *PFNLDRGETPROCEDUREADDRESSEX)(IN HANDLE hDll, IN ANSI_STRING const *pSymbol OPTIONAL,
+ IN ULONG uOrdinal OPTIONAL, OUT PVOID *ppvSymbol, ULONG fFlags);
+#define LDRLOCKLOADERLOCK_F_RAISE_ERRORS RT_BIT_32(0)
+#define LDRLOCKLOADERLOCK_F_NO_WAIT RT_BIT_32(1)
+#define LDRLOCKLOADERLOCK_DISP_INVALID UINT32_C(0)
+#define LDRLOCKLOADERLOCK_DISP_ACQUIRED UINT32_C(1)
+#define LDRLOCKLOADERLOCK_DISP_NOT_ACQUIRED UINT32_C(2)
+/** @since Windows XP. */
+RT_DECL_NTAPI(NTSTATUS) LdrLockLoaderLock(IN ULONG fFlags, OUT PULONG puDisposition OPTIONAL, OUT PVOID *ppvCookie);
+/** @since Windows XP. */
+typedef NTSTATUS (NTAPI *PFNLDRLOCKLOADERLOCK)(IN ULONG fFlags, OUT PULONG puDisposition OPTIONAL, OUT PVOID *ppvCookie);
+#define LDRUNLOCKLOADERLOCK_F_RAISE_ERRORS RT_BIT_32(0)
+/** @since Windows XP. */
+RT_DECL_NTAPI(NTSTATUS) LdrUnlockLoaderLock(IN ULONG fFlags, OUT PVOID pvCookie);
+/** @since Windows XP. */
+typedef NTSTATUS (NTAPI *PFNLDRUNLOCKLOADERLOCK)(IN ULONG fFlags, OUT PVOID pvCookie);
+
+RT_DECL_NTAPI(NTSTATUS) RtlExpandEnvironmentStrings_U(PVOID, PUNICODE_STRING, PUNICODE_STRING, PULONG);
+RT_DECL_NTAPI(VOID) RtlExitUserProcess(NTSTATUS rcExitCode); /**< Vista and later. */
+RT_DECL_NTAPI(VOID) RtlExitUserThread(NTSTATUS rcExitCode);
+RT_DECL_NTAPI(NTSTATUS) RtlDosApplyFileIsolationRedirection_Ustr(IN ULONG fFlags,
+ IN PCUNICODE_STRING pOrgName,
+ IN PUNICODE_STRING pDefaultSuffix,
+ IN OUT PUNICODE_STRING pStaticString,
+ IN OUT PUNICODE_STRING pDynamicString,
+ IN OUT PUNICODE_STRING *ppResultString,
+ IN PULONG pfNewFlags OPTIONAL,
+ IN PSIZE_T pcbFilename OPTIONAL,
+ IN PSIZE_T pcbNeeded OPTIONAL);
+/** @since Windows 8.
+ * @note Status code is always zero in windows 10 build 14393. */
+RT_DECL_NTAPI(NTSTATUS) ApiSetQueryApiSetPresence(IN PCUNICODE_STRING pAllegedApiSetDll, OUT PBOOLEAN pfPresent);
+/** @copydoc ApiSetQueryApiSetPresence */
+typedef NTSTATUS (NTAPI *PFNAPISETQUERYAPISETPRESENCE)(IN PCUNICODE_STRING pAllegedApiSetDll, OUT PBOOLEAN pfPresent);
+
+
+# ifdef IPRT_NT_USE_WINTERNL
+typedef NTSTATUS NTAPI RTL_HEAP_COMMIT_ROUTINE(PVOID, PVOID *, PSIZE_T);
+typedef RTL_HEAP_COMMIT_ROUTINE *PRTL_HEAP_COMMIT_ROUTINE;
+typedef struct _RTL_HEAP_PARAMETERS
+{
+ ULONG Length;
+ SIZE_T SegmentReserve;
+ SIZE_T SegmentCommit;
+ SIZE_T DeCommitFreeBlockThreshold;
+ SIZE_T DeCommitTotalFreeThreshold;
+ SIZE_T MaximumAllocationSize;
+ SIZE_T VirtualMemoryThreshold;
+ SIZE_T InitialCommit;
+ SIZE_T InitialReserve;
+ PRTL_HEAP_COMMIT_ROUTINE CommitRoutine;
+ SIZE_T Reserved[2];
+} RTL_HEAP_PARAMETERS;
+typedef RTL_HEAP_PARAMETERS *PRTL_HEAP_PARAMETERS;
+RT_DECL_NTAPI(PVOID) RtlCreateHeap(ULONG fFlags, PVOID pvHeapBase, SIZE_T cbReserve, SIZE_T cbCommit, PVOID pvLock,
+ PRTL_HEAP_PARAMETERS pParameters);
+/** @name Heap flags (for RtlCreateHeap).
+ * @{ */
+/*# define HEAP_NO_SERIALIZE UINT32_C(0x00000001)
+# define HEAP_GROWABLE UINT32_C(0x00000002)
+# define HEAP_GENERATE_EXCEPTIONS UINT32_C(0x00000004)
+# define HEAP_ZERO_MEMORY UINT32_C(0x00000008)
+# define HEAP_REALLOC_IN_PLACE_ONLY UINT32_C(0x00000010)
+# define HEAP_TAIL_CHECKING_ENABLED UINT32_C(0x00000020)
+# define HEAP_FREE_CHECKING_ENABLED UINT32_C(0x00000040)
+# define HEAP_DISABLE_COALESCE_ON_FREE UINT32_C(0x00000080)*/
+# define HEAP_SETTABLE_USER_VALUE UINT32_C(0x00000100)
+# define HEAP_SETTABLE_USER_FLAG1 UINT32_C(0x00000200)
+# define HEAP_SETTABLE_USER_FLAG2 UINT32_C(0x00000400)
+# define HEAP_SETTABLE_USER_FLAG3 UINT32_C(0x00000800)
+# define HEAP_SETTABLE_USER_FLAGS UINT32_C(0x00000e00)
+# define HEAP_CLASS_0 UINT32_C(0x00000000)
+# define HEAP_CLASS_1 UINT32_C(0x00001000)
+# define HEAP_CLASS_2 UINT32_C(0x00002000)
+# define HEAP_CLASS_3 UINT32_C(0x00003000)
+# define HEAP_CLASS_4 UINT32_C(0x00004000)
+# define HEAP_CLASS_5 UINT32_C(0x00005000)
+# define HEAP_CLASS_6 UINT32_C(0x00006000)
+# define HEAP_CLASS_7 UINT32_C(0x00007000)
+# define HEAP_CLASS_8 UINT32_C(0x00008000)
+# define HEAP_CLASS_MASK UINT32_C(0x0000f000)
+# endif
+# define HEAP_CLASS_PROCESS HEAP_CLASS_0
+# define HEAP_CLASS_PRIVATE HEAP_CLASS_1
+# define HEAP_CLASS_KERNEL HEAP_CLASS_2
+# define HEAP_CLASS_GDI HEAP_CLASS_3
+# define HEAP_CLASS_USER HEAP_CLASS_4
+# define HEAP_CLASS_CONSOLE HEAP_CLASS_5
+# define HEAP_CLASS_USER_DESKTOP HEAP_CLASS_6
+# define HEAP_CLASS_CSRSS_SHARED HEAP_CLASS_7
+# define HEAP_CLASS_CSRSS_PORT HEAP_CLASS_8
+# ifdef IPRT_NT_USE_WINTERNL
+/*# define HEAP_CREATE_ALIGN_16 UINT32_C(0x00010000)
+# define HEAP_CREATE_ENABLE_TRACING UINT32_C(0x00020000)
+# define HEAP_CREATE_ENABLE_EXECUTE UINT32_C(0x00040000)*/
+# define HEAP_CREATE_VALID_MASK UINT32_C(0x0007f0ff)
+# endif /* IPRT_NT_USE_WINTERNL */
+/** @} */
+# ifdef IPRT_NT_USE_WINTERNL
+/** @name Heap tagging constants
+ * @{ */
+# define HEAP_GLOBAL_TAG UINT32_C(0x00000800)
+/*# define HEAP_MAXIMUM_TAG UINT32_C(0x00000fff)
+# define HEAP_PSEUDO_TAG_FLAG UINT32_C(0x00008000)
+# define HEAP_TAG_SHIFT 18 */
+# define HEAP_TAG_MASK (HEAP_MAXIMUM_TAG << HEAP_TAG_SHIFT)
+/** @} */
+RT_DECL_NTAPI(PVOID) RtlAllocateHeap(HANDLE hHeap, ULONG fFlags, SIZE_T cb);
+RT_DECL_NTAPI(PVOID) RtlReAllocateHeap(HANDLE hHeap, ULONG fFlags, PVOID pvOld, SIZE_T cbNew);
+RT_DECL_NTAPI(BOOLEAN) RtlFreeHeap(HANDLE hHeap, ULONG fFlags, PVOID pvMem);
+# endif /* IPRT_NT_USE_WINTERNL */
+RT_DECL_NTAPI(SIZE_T) RtlCompactHeap(HANDLE hHeap, ULONG fFlags);
+RT_DECL_NTAPI(SIZE_T) RtlSizeHeap(HANDLE hHeap, ULONG fFlags, PVOID pvMem);
+RT_DECL_NTAPI(NTSTATUS) RtlGetLastNtStatus(VOID);
+RT_DECL_NTAPI(ULONG) RtlGetLastWin32Error(VOID);
+RT_DECL_NTAPI(VOID) RtlSetLastWin32Error(ULONG uError);
+RT_DECL_NTAPI(VOID) RtlSetLastWin32ErrorAndNtStatusFromNtStatus(NTSTATUS rcNt);
+RT_DECL_NTAPI(VOID) RtlRestoreLastWin32Error(ULONG uError);
+RT_DECL_NTAPI(BOOLEAN) RtlQueryPerformanceCounter(PLARGE_INTEGER);
+RT_DECL_NTAPI(uint64_t) RtlGetSystemTimePrecise(VOID);
+typedef uint64_t (NTAPI * PFNRTLGETSYSTEMTIMEPRECISE)(VOID);
+RT_DECL_NTAPI(uint64_t) RtlGetInterruptTimePrecise(uint64_t *puPerfTime);
+typedef uint64_t (NTAPI * PFNRTLGETINTERRUPTTIMEPRECISE)(uint64_t *);
+RT_DECL_NTAPI(BOOLEAN) RtlQueryUnbiasedInterruptTime(uint64_t *puInterruptTime);
+typedef BOOLEAN (NTAPI * PFNRTLQUERYUNBIASEDINTERRUPTTIME)(uint64_t *);
+
+RT_C_DECLS_END
+/** @} */
+#endif /* IN_RING3 */
+
+#endif /* !IPRT_INCLUDED_nt_nt_h */
+
diff --git a/include/iprt/nt/ntddk.h b/include/iprt/nt/ntddk.h
new file mode 100644
index 00000000..51313368
--- /dev/null
+++ b/include/iprt/nt/ntddk.h
@@ -0,0 +1,83 @@
+/** @file
+ * Safe way to include ntddk.h.
+ */
+
+/*
+ * Copyright (C) 2016-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_nt_ntddk_h
+#define IPRT_INCLUDED_nt_ntddk_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+/* Make sure we get the right prototypes. */
+#include <iprt/sanitized/intrin.h>
+
+#define _InterlockedExchange _InterlockedExchange_StupidDDKVsCompilerCrap
+#define _InterlockedExchangeAdd _InterlockedExchangeAdd_StupidDDKVsCompilerCrap
+#define _InterlockedCompareExchange _InterlockedCompareExchange_StupidDDKVsCompilerCrap
+#define _InterlockedAddLargeStatistic _InterlockedAddLargeStatistic_StupidDDKVsCompilerCrap
+#define _interlockedbittestandset _interlockedbittestandset_StupidDDKVsCompilerCrap
+#define _interlockedbittestandreset _interlockedbittestandreset_StupidDDKVsCompilerCrap
+#define _interlockedbittestandset64 _interlockedbittestandset64_StupidDDKVsCompilerCrap
+#define _interlockedbittestandreset64 _interlockedbittestandreset64_StupidDDKVsCompilerCrap
+
+#pragma warning(push)
+#pragma warning(disable:4163)
+#pragma warning(disable:4668) /* warning C4668: 'WHEA_DOWNLEVEL_TYPE_NAMES' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif' */
+#pragma warning(disable:4255) /* warning C4255: 'ObGetFilterVersion' : no function prototype given: converting '()' to '(void)' */
+#if _MSC_VER >= 1800 /*RT_MSC_VER_VC120*/
+# pragma warning(disable:4005) /* sdk/v7.1/include/sal_supp.h(57) : warning C4005: '__useHeader' : macro redefinition */
+# pragma warning(disable:4471) /* wdm.h(11057) : warning C4471: '_POOL_TYPE' : a forward declaration of an unscoped enumeration must have an underlying type (int assumed) */
+#endif
+
+/* Include the sdk/ddk version header so _WIN32_VER and the rest gets defined before ntdef.h is included,
+ otherwise we'll miss out on DECLARE_GLOBAL_CONST_UNICODE_STRING and friends in the W10 SDKs. */
+#define DECLSPEC_DEPRECATED_DDK
+#include <sdkddkver.h>
+
+/*RT_C_DECLS_BEGIN - no longer necessary it seems */
+#include <ntddk.h>
+/*RT_C_DECLS_END - no longer necessary it seems */
+#pragma warning(pop)
+
+#undef _InterlockedExchange
+#undef _InterlockedExchangeAdd
+#undef _InterlockedCompareExchange
+#undef _InterlockedAddLargeStatistic
+#undef _interlockedbittestandset
+#undef _interlockedbittestandreset
+#undef _interlockedbittestandset64
+#undef _interlockedbittestandreset64
+
+#endif /* !IPRT_INCLUDED_nt_ntddk_h */
+
diff --git a/include/iprt/nt/rx.h b/include/iprt/nt/rx.h
new file mode 100644
index 00000000..99c40d4a
--- /dev/null
+++ b/include/iprt/nt/rx.h
@@ -0,0 +1,65 @@
+/** @file
+ * Safe way to include rx.h (DDK/IFS).
+ */
+
+/*
+ * Copyright (C) 2016-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_nt_rx_h
+#define IPRT_INCLUDED_nt_rx_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cdefs.h>
+
+#ifdef _MSC_VER
+# pragma warning(push)
+# pragma warning(disable: 4668) /* rxovride.h(38) : warning C4668: 'DBG' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif' */
+# pragma warning(disable: 4100) /* Fcb.h(1558) : warning C4100: 'SrvOpen' : unreferenced formal parameter */
+# pragma warning(disable: 4115) /* rxce.h(106) : warning C4115: '_ADAPTER_STATUS' : named type definition in parentheses */
+# ifndef __cplusplus
+# pragma warning(disable: 4255) /* rxworkq.h(235) : warning C4255: 'RxInitializeDispatcher' : no function prototype given: converting '()' to '(void)' */
+# endif
+#endif
+
+RT_C_DECLS_BEGIN
+
+#include <rx.h>
+
+RT_C_DECLS_END
+
+#ifdef _MSC_VER
+# pragma warning(pop)
+#endif
+
+#endif /* !IPRT_INCLUDED_nt_rx_h */
+
diff --git a/include/iprt/nt/tdikrnl.h b/include/iprt/nt/tdikrnl.h
new file mode 100644
index 00000000..94446f72
--- /dev/null
+++ b/include/iprt/nt/tdikrnl.h
@@ -0,0 +1,50 @@
+/** @file
+ * Safe way to include tdikrnl.h.
+ */
+
+/*
+ * Copyright (C) 2016-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_nt_tdikrnl_h
+#define IPRT_INCLUDED_nt_tdikrnl_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#pragma warning(push)
+#pragma warning(disable:4668) /* warning C4668: 'NTDDI_WINS03' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif' */
+RT_C_DECLS_BEGIN
+#include <tdikrnl.h>
+RT_C_DECLS_END
+#pragma warning(pop)
+
+#endif /* !IPRT_INCLUDED_nt_tdikrnl_h */
+
diff --git a/include/iprt/nt/vid.h b/include/iprt/nt/vid.h
new file mode 100644
index 00000000..a319af67
--- /dev/null
+++ b/include/iprt/nt/vid.h
@@ -0,0 +1,313 @@
+/** @file
+ * Virtualization Infrastructure Driver (VID) API.
+ */
+
+/*
+ * Copyright (C) 2018-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_nt_vid_h
+#define IPRT_INCLUDED_nt_vid_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include "hyperv.h"
+
+
+/**
+ * Output from VidMessageSlotMap.
+ */
+typedef struct VID_MAPPED_MESSAGE_SLOT
+{
+ /** The message block mapping. */
+ struct _HV_MESSAGE *pMsgBlock;
+ /** Copy of input iCpu. */
+ uint32_t iCpu;
+ /** Explicit padding. */
+ uint32_t uParentAdvisory;
+} VID_MAPPED_MESSAGE_SLOT;
+/** Pointer to VidMessageSlotMap output structure. */
+typedef VID_MAPPED_MESSAGE_SLOT *PVID_MAPPED_MESSAGE_SLOT;
+
+
+/** @name VID_MESSAGE_MAPPING_HEADER::enmVidMsgType values (wild guess).
+ * @{ */
+/** Type mask, strips flags. */
+#define VID_MESSAGE_TYPE_MASK UINT32_C(0x00ffffff)
+/** No return message necessary. */
+#define VID_MESSAGE_TYPE_FLAG_NO_RETURN UINT32_C(0x01000000)
+/** Observed message values. */
+typedef enum
+{
+ /** Invalid zero value. */
+ VidMessageInvalid = 0,
+ /** Guessing this means a message from the hypervisor. */
+ VidMessageHypervisorMessage = 0x00000c | VID_MESSAGE_TYPE_FLAG_NO_RETURN,
+ /** Guessing this means stop request completed. Message length is 1 byte. */
+ VidMessageStopRequestComplete = 0x00000d | VID_MESSAGE_TYPE_FLAG_NO_RETURN,
+} VID_MESSAGE_TYPE;
+AssertCompileSize(VID_MESSAGE_TYPE, 4);
+/** @} */
+
+/**
+ * Header of the message mapping returned by VidMessageSlotMap.
+ */
+typedef struct VID_MESSAGE_MAPPING_HEADER
+{
+ /** Current guess is that this is VID_MESSAGE_TYPE. */
+ VID_MESSAGE_TYPE enmVidMsgType;
+ /** The message size or so it seems (0x100). */
+ uint32_t cbMessage;
+ /** So far these have been zero. */
+ uint32_t aZeroPPadding[2+4];
+} VID_MESSAGE_MAPPING_HEADER;
+AssertCompileSize(VID_MESSAGE_MAPPING_HEADER, 32);
+
+/**
+ * VID processor status (VidGetVirtualProcessorRunningStatus).
+ *
+ * @note This is used internally in VID.SYS, in 17101 it's at offset 8 in their
+ * 'pVCpu' structure.
+ */
+typedef enum
+{
+ VidProcessorStatusStopped = 0,
+ VidProcessorStatusRunning,
+ VidProcessorStatusSuspended,
+ VidProcessorStatusUndefined = 0xffff
+} VID_PROCESSOR_STATUS;
+AssertCompileSize(VID_PROCESSOR_STATUS, 4);
+
+
+/** I/O control input for VidMessageSlotHandleAndGetNext. */
+typedef struct VID_IOCTL_INPUT_MESSAGE_SLOT_HANDLE_AND_GET_NEXT
+{
+ HV_VP_INDEX iCpu;
+ uint32_t fFlags; /**< VID_MSHAGN_F_GET_XXX*/
+ uint32_t cMillies; /**< Not present in build 17758 as the API changed to always to infinite waits. */
+} VID_IOCTL_INPUT_MESSAGE_SLOT_HANDLE_AND_GET_NEXT;
+/** Pointer to input for VidMessageSlotHandleAndGetNext. */
+typedef VID_IOCTL_INPUT_MESSAGE_SLOT_HANDLE_AND_GET_NEXT *PVID_IOCTL_INPUT_MESSAGE_SLOT_HANDLE_AND_GET_NEXT;
+/** Pointer to const input for VidMessageSlotHandleAndGetNext. */
+typedef VID_IOCTL_INPUT_MESSAGE_SLOT_HANDLE_AND_GET_NEXT const *PCVID_IOCTL_INPUT_MESSAGE_SLOT_HANDLE_AND_GET_NEXT;
+
+/** @name VID_MSHAGN_F_GET_XXX - Flags for VidMessageSlotHandleAndGetNext
+ * @{ */
+/** This will try get the next message, waiting if necessary.
+ * It is subject to NtAlertThread processing when it starts waiting. */
+#define VID_MSHAGN_F_GET_NEXT_MESSAGE RT_BIT_32(0)
+/** ACK the message as handled and resume execution/whatever.
+ * This is executed before VID_MSHAGN_F_GET_NEXT_MESSAGE and should not be
+ * subject to NtAlertThread side effects. */
+#define VID_MSHAGN_F_HANDLE_MESSAGE RT_BIT_32(1)
+/** Cancel VP execution (no other bit set).
+ * @since about build 17758. */
+#define VID_MSHAGN_F_CANCEL RT_BIT_32(2)
+/** @} */
+
+/** A 64-bit version of HV_PARTITION_PROPERTY_CODE. */
+typedef int64_t VID_PARTITION_PROPERTY_CODE;
+
+
+#ifdef IN_RING3
+RT_C_DECLS_BEGIN
+
+/** Calling convention. */
+#ifndef WINAPI
+# define VIDAPI __stdcall
+#else
+# define VIDAPI WINAPI
+#endif
+
+/** Partition handle. */
+#ifndef WINAPI
+typedef void *VID_PARTITION_HANDLE;
+#else
+typedef HANDLE VID_PARTITION_HANDLE;
+#endif
+
+/**
+ * Gets the partition ID.
+ *
+ * The partition ID is the numeric identifier used when making hypercalls to the
+ * hypervisor.
+ *
+ * @note Starting with Windows 11 (or possibly earlier), this does not work on
+ * Exo partition as created by WHvCreatePartition. It returns a
+ * STATUS_NOT_IMPLEMENTED as the I/O control code is not allowed through.
+ * All partitions has an ID though, so just pure annoying blockheadedness
+ * sprung upon us w/o any chance of doing a memory managment rewrite in
+ * time.
+ */
+DECLIMPORT(BOOL) VIDAPI VidGetHvPartitionId(VID_PARTITION_HANDLE hPartition, HV_PARTITION_ID *pidPartition);
+
+/**
+ * Get a partition property.
+ *
+ * @returns Success indicator (details in LastErrorValue).
+ * @param hPartition The partition handle.
+ * @param enmProperty The property to get. Is a HV_PARTITION_PROPERTY_CODE
+ * type, but seems to be passed around as a 64-bit integer
+ * for some reason.
+ * @param puValue Where to return the property value.
+ */
+DECLIMPORT(BOOL) VIDAPI VidGetPartitionProperty(VID_PARTITION_HANDLE hPartition, VID_PARTITION_PROPERTY_CODE enmProperty,
+ PHV_PARTITION_PROPERTY puValue);
+
+/**
+ * @copydoc VidGetPartitionProperty
+ * @note Currently (Windows 11 GA) identical to VidGetPartitionProperty.
+ */
+DECLIMPORT(BOOL) VIDAPI VidGetExoPartitionProperty(VID_PARTITION_HANDLE hPartition, VID_PARTITION_PROPERTY_CODE enmProperty,
+ PHV_PARTITION_PROPERTY puValue);
+
+/**
+ * Starts asynchronous execution of a virtual CPU.
+ */
+DECLIMPORT(BOOL) VIDAPI VidStartVirtualProcessor(VID_PARTITION_HANDLE hPartition, HV_VP_INDEX iCpu);
+
+/**
+ * Stops the asynchronous execution of a virtual CPU.
+ *
+ * @retval ERROR_VID_STOP_PENDING if busy with intercept, check messages.
+ */
+DECLIMPORT(BOOL) VIDAPI VidStopVirtualProcessor(VID_PARTITION_HANDLE hPartition, HV_VP_INDEX iCpu);
+
+/**
+ * WHvCreateVirtualProcessor boils down to a call to VidMessageSlotMap and
+ * some internal WinHvPlatform state fiddling.
+ *
+ * Looks like it maps memory and returns the pointer to it.
+ * VidMessageSlotHandleAndGetNext is later used to wait for the next message and
+ * put (??) it into that memory mapping.
+ *
+ * @returns Success indicator (details in LastErrorValue).
+ *
+ * @param hPartition The partition handle.
+ * @param pOutput Where to return the pointer to the message memory
+ * mapping. The CPU index is also returned here.
+ * @param iCpu The CPU to wait-and-get messages for.
+ */
+DECLIMPORT(BOOL) VIDAPI VidMessageSlotMap(VID_PARTITION_HANDLE hPartition, PVID_MAPPED_MESSAGE_SLOT pOutput, HV_VP_INDEX iCpu);
+
+/**
+ * This is used by WHvRunVirtualProcessor to wait for the next exit msg.
+ *
+ * The message appears in the memory mapping returned by VidMessageSlotMap.
+ *
+ * @returns Success indicator (details only in LastErrorValue - LastStatusValue
+ * is not set).
+ * @retval STATUS_TIMEOUT for STATUS_TIMEOUT as well as STATUS_USER_APC and
+ * STATUS_ALERTED.
+ *
+ * @param hPartition The partition handle.
+ * @param iCpu The CPU to wait-and-get messages for.
+ * @param fFlags Flags, VID_MSHAGN_F_XXX.
+ *
+ * When starting or resuming execution, at least one of
+ * VID_MSHAGN_F_GET_NEXT_MESSAGE (bit 0) and
+ * VID_MSHAGN_F_HANDLE_MESSAGE (bit 1) must be set.
+ *
+ * When cancelling execution only VID_MSHAGN_F_CANCEL (big 2)
+ * must be set.
+ *
+ * @param cMillies The timeout, presumably in milliseconds. This parameter
+ * was dropped about build 17758.
+ *
+ * @todo Would be awfully nice if someone at Microsoft could hit at the
+ * flags here.
+ */
+DECLIMPORT(BOOL) VIDAPI VidMessageSlotHandleAndGetNext(VID_PARTITION_HANDLE hPartition, HV_VP_INDEX iCpu,
+ uint32_t fFlags, uint32_t cMillies);
+/**
+ * Gets the processor running status.
+ *
+ * This is probably only available in special builds, as one of the early I/O
+ * control dispatching routines will not let it thru. Lower down routines does
+ * implement it, so it's possible to patch it into working. This works for
+ * build 17101: eb vid+12180 0f 84 98 00 00 00
+ *
+ * @retval ERROR_NOT_IMPLEMENTED
+ *
+ * @remarks VidExoFastIoControlPartition probably disapproves of this too. It
+ * could be very handy for debugging upon occation.
+ */
+DECLIMPORT(BOOL) VIDAPI VidGetVirtualProcessorRunningStatus(VID_PARTITION_HANDLE hPartition, HV_VP_INDEX iCpu,
+ VID_PROCESSOR_STATUS *penmStatus);
+
+/**
+ * For query virtual processor registers and other state information.
+ *
+ * @returns Success indicator (details in LastErrorValue).
+ */
+DECLIMPORT(BOOL) VIDAPI VidGetVirtualProcessorState(VID_PARTITION_HANDLE hPartition, HV_VP_INDEX iCpu,
+ HV_REGISTER_NAME const *paRegNames, uint32_t cRegisters,
+ HV_REGISTER_VALUE *paRegValues);
+
+/**
+ * For setting virtual processor registers and other state information.
+ *
+ * @returns Success indicator (details in LastErrorValue).
+ */
+DECLIMPORT(BOOL) VIDAPI VidSetVirtualProcessorState(VID_PARTITION_HANDLE hPartition, HV_VP_INDEX iCpu,
+ HV_REGISTER_NAME const *paRegNames, uint32_t cRegisters,
+ HV_REGISTER_VALUE const *paRegValues);
+
+/**
+ * Wrapper around the HvCallGetMemoryBalance hypercall.
+ *
+ * When VID.SYS processes the request, it will also query
+ * HvPartitionPropertyVirtualTlbPageCount, so we're passing a 3rd return
+ * parameter in case the API is ever extended to match the I/O control.
+ *
+ * @returns Success indicator (details in LastErrorValue).
+ * @retval ERROR_NOT_IMPLEMENTED for exo partitions.
+ *
+ * @param hPartition The partition handle.
+ * @param pcPagesAvailable Where to return the number of unused pages
+ * still available to the partition.
+ * @param pcPagesInUse Where to return the number of pages currently
+ * in use by the partition.
+ * @param pReserved Pointer to dummy value, just in case they
+ * modify the API to include the nested TLB size.
+ *
+ * @note Not available for exo partitions, unfortunately. The
+ * VidExoFastIoControlPartition function deflects it, failing it with
+ * STATUS_NOT_IMPLEMENTED / ERROR_NOT_IMPLEMENTED.
+ */
+DECLIMPORT(BOOL) VIDAPI VidGetHvMemoryBalance(VID_PARTITION_HANDLE hPartition, uint64_t *pcPagesAvailable,
+ uint64_t *pcPagesInUse, uint64_t *pReserved);
+
+RT_C_DECLS_END
+#endif /* IN_RING3 */
+
+#endif /* !IPRT_INCLUDED_nt_vid_h */
+
diff --git a/include/iprt/nt/video.h b/include/iprt/nt/video.h
new file mode 100644
index 00000000..f48ab5ab
--- /dev/null
+++ b/include/iprt/nt/video.h
@@ -0,0 +1,59 @@
+/** @file
+ * Safe way to include video.h (DDK).
+ */
+
+/*
+ * Copyright (C) 2016-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_nt_video_h
+#define IPRT_INCLUDED_nt_video_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cdefs.h>
+
+#ifdef _MSC_VER
+# pragma warning(push)
+# pragma warning(disable:4668) /* warning C4668: 'DBG' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif' */
+# ifndef __cplusplus
+# pragma warning(disable:4255) /* warning C4255: 'VideoPortGetCurrentIrql' : no function prototype given: converting '()' to '(void)'*/
+# endif
+#endif
+
+#include <video.h>
+
+#ifdef _MSC_VER
+# pragma warning(pop)
+#endif
+
+#endif /* !IPRT_INCLUDED_nt_video_h */
+
diff --git a/include/iprt/nt/wdm.h b/include/iprt/nt/wdm.h
new file mode 100644
index 00000000..06560e90
--- /dev/null
+++ b/include/iprt/nt/wdm.h
@@ -0,0 +1,81 @@
+/** @file
+ * Safe way to include wdm.h.
+ */
+
+/*
+ * Copyright (C) 2016-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_nt_wdm_h
+#define IPRT_INCLUDED_nt_wdm_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+/* Make sure we get the right prototypes. */
+#include <iprt/sanitized/intrin.h>
+
+#define _InterlockedExchange _InterlockedExchange_StupidDDKVsCompilerCrap
+#define _InterlockedExchangeAdd _InterlockedExchangeAdd_StupidDDKVsCompilerCrap
+#define _InterlockedCompareExchange _InterlockedCompareExchange_StupidDDKVsCompilerCrap
+#define _InterlockedAddLargeStatistic _InterlockedAddLargeStatistic_StupidDDKVsCompilerCrap
+#define _interlockedbittestandset _interlockedbittestandset_StupidDDKVsCompilerCrap
+#define _interlockedbittestandreset _interlockedbittestandreset_StupidDDKVsCompilerCrap
+#define _interlockedbittestandset64 _interlockedbittestandset64_StupidDDKVsCompilerCrap
+#define _interlockedbittestandreset64 _interlockedbittestandreset64_StupidDDKVsCompilerCrap
+
+#pragma warning(push)
+#pragma warning(disable:4163)
+#pragma warning(disable:4668) /* warning C4668: 'WHEA_DOWNLEVEL_TYPE_NAMES' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif' */
+#pragma warning(disable:4255) /* warning C4255: 'ObGetFilterVersion' : no function prototype given: converting '()' to '(void)' */
+#pragma warning(disable:4005) /* wdm.h(29) : warning C4005: 'NO_INTERLOCKED_INTRINSICS' : macro redefinition */
+#if _MSC_VER >= 1800 /*RT_MSC_VER_VC120*/
+# pragma warning(disable:4005) /* sdk/v7.1/include/sal_supp.h(57) : warning C4005: '__useHeader' : macro redefinition */
+# pragma warning(disable:4471) /* wdm.h(11057) : warning C4471: '_POOL_TYPE' : a forward declaration of an unscoped enumeration must have an underlying type (int assumed) */
+#endif
+# if _MSC_VER >= 1900 /*RT_MSC_VER_VC140*/
+# ifdef __cplusplus
+# pragma warning(disable:5039) /* warning C5039: 'KeInitializeDpc': pointer or reference to potentially throwing function passed to 'extern "C"' function under -EHc. Undefined behavior may occur if this function throws an exception. */
+# endif
+# endif
+#include <wdm.h>
+#pragma warning(pop)
+
+#undef _InterlockedExchange
+#undef _InterlockedExchangeAdd
+#undef _InterlockedCompareExchange
+#undef _InterlockedAddLargeStatistic
+#undef _interlockedbittestandset
+#undef _interlockedbittestandreset
+#undef _interlockedbittestandset64
+#undef _interlockedbittestandreset64
+
+#endif /* !IPRT_INCLUDED_nt_wdm_h */
+
diff --git a/include/iprt/once.h b/include/iprt/once.h
new file mode 100644
index 00000000..eb734e79
--- /dev/null
+++ b/include/iprt/once.h
@@ -0,0 +1,231 @@
+/** @file
+ * IPRT - Execute Once.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_once_h
+#define IPRT_INCLUDED_once_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+#include <iprt/asm.h>
+#include <iprt/errcore.h>
+#include <iprt/list.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_once RTOnce - Execute Once
+ * @ingroup grp_rt
+ * @{
+ */
+
+/**
+ * Callback that gets executed once.
+ *
+ * @returns IPRT style status code, RTOnce returns this.
+ *
+ * @param pvUser The user parameter.
+ */
+typedef DECLCALLBACKTYPE(int32_t, FNRTONCE,(void *pvUser));
+/** Pointer to a FNRTONCE. */
+typedef FNRTONCE *PFNRTONCE;
+
+/**
+ * Callback that gets executed on IPRT/process termination.
+ *
+ * @param pvUser The user parameter.
+ * @param fLazyCleanUpOk Indicates whether lazy clean-up is OK (see
+ * initterm.h).
+ */
+typedef DECLCALLBACKTYPE(void, FNRTONCECLEANUP,(void *pvUser, bool fLazyCleanUpOk));
+/** Pointer to a FNRTONCE. */
+typedef FNRTONCECLEANUP *PFNRTONCECLEANUP;
+
+/**
+ * Execute once structure.
+ *
+ * This is typically a global variable that is statically initialized
+ * by RTONCE_INITIALIZER.
+ */
+typedef struct RTONCE
+{
+ /** Event semaphore that the other guys are blocking on. */
+ RTSEMEVENTMULTI volatile hEventMulti;
+ /** Reference counter for hEventMulti. */
+ int32_t volatile cEventRefs;
+ /** See RTONCESTATE. */
+ int32_t volatile iState;
+ /** The return code of pfnOnce. */
+ int32_t volatile rc;
+
+ /** Pointer to the clean-up function. */
+ PFNRTONCECLEANUP pfnCleanUp;
+ /** Argument to hand to the clean-up function. */
+ void *pvUser;
+ /** Clean-up list entry. */
+ RTLISTNODE CleanUpNode;
+} RTONCE;
+/** Pointer to a execute once struct. */
+typedef RTONCE *PRTONCE;
+
+/**
+ * The execute once statemachine.
+ */
+typedef enum RTONCESTATE
+{
+ /** RTOnce() has not been called.
+ * Next: NO_SEM */
+ RTONCESTATE_UNINITIALIZED = 1,
+ /** RTOnce() is busy, no race.
+ * Next: CREATING_SEM, DONE */
+ RTONCESTATE_BUSY_NO_SEM,
+ /** More than one RTOnce() caller is busy.
+ * Next: BUSY_HAVE_SEM, BUSY_SPIN, DONE_CREATING_SEM, DONE */
+ RTONCESTATE_BUSY_CREATING_SEM,
+ /** More than one RTOnce() caller, the first is busy, the others are
+ * waiting.
+ * Next: DONE */
+ RTONCESTATE_BUSY_HAVE_SEM,
+ /** More than one RTOnce() caller, the first is busy, the others failed to
+ * create a semaphore and are spinning.
+ * Next: DONE */
+ RTONCESTATE_BUSY_SPIN,
+ /** More than one RTOnce() caller, the first has completed, the others
+ * are busy creating the semaphore.
+ * Next: DONE_HAVE_SEM */
+ RTONCESTATE_DONE_CREATING_SEM,
+ /** More than one RTOnce() caller, the first is busy grabbing the
+ * semaphore, while the others are waiting.
+ * Next: DONE */
+ RTONCESTATE_DONE_HAVE_SEM,
+ /** The execute once stuff has completed. */
+ RTONCESTATE_DONE = 16
+} RTONCESTATE;
+
+/** Static initializer for RTONCE variables. */
+#define RTONCE_INITIALIZER \
+ { NIL_RTSEMEVENTMULTI, 0, RTONCESTATE_UNINITIALIZED, VERR_INTERNAL_ERROR, NULL, NULL, { NULL, NULL } }
+
+
+/**
+ * Serializes execution of the pfnOnce function, making sure it's
+ * executed exactly once and that nobody returns from RTOnce before
+ * it has executed successfully.
+ *
+ * @returns IPRT like status code returned by pfnOnce.
+ *
+ * @param pOnce Pointer to the execute once variable.
+ * @param pfnOnce The function to executed once.
+ * @param pfnCleanUp The function that will be doing the cleaning up.
+ * Optional.
+ * @param pvUser The user parameter for pfnOnce.
+ */
+RTDECL(int) RTOnceSlow(PRTONCE pOnce, PFNRTONCE pfnOnce, FNRTONCECLEANUP pfnCleanUp, void *pvUser);
+
+/**
+ * Serializes execution of the pfnOnce function, making sure it's
+ * executed exactly once and that nobody returns from RTOnce before
+ * it has executed successfully.
+ *
+ * @returns IPRT like status code returned by pfnOnce.
+ *
+ * @param pOnce Pointer to the execute once variable.
+ * @param pfnOnce The function to executed once.
+ * @param pvUser The user parameter for pfnOnce.
+ */
+DECLINLINE(int) RTOnce(PRTONCE pOnce, PFNRTONCE pfnOnce, void *pvUser)
+{
+ int32_t iState = ASMAtomicUoReadS32(&pOnce->iState);
+ if (RT_LIKELY( iState == RTONCESTATE_DONE
+ || iState == RTONCESTATE_DONE_CREATING_SEM
+ || iState == RTONCESTATE_DONE_HAVE_SEM ))
+ return ASMAtomicUoReadS32(&pOnce->rc);
+ return RTOnceSlow(pOnce, pfnOnce, NULL, pvUser);
+}
+
+/**
+ * Execute pfnOnce once and register a termination clean-up callback.
+ *
+ * Serializes execution of the pfnOnce function, making sure it's
+ * executed exactly once and that nobody returns from RTOnce before
+ * it has executed successfully.
+ *
+ * @returns IPRT like status code returned by pfnOnce.
+ *
+ * @param pOnce Pointer to the execute once variable.
+ * @param pfnOnce The function to executed once.
+ * @param pfnCleanUp The function that will be doing the cleaning up.
+ * @param pvUser The user parameter for pfnOnce.
+ */
+DECLINLINE(int) RTOnceEx(PRTONCE pOnce, PFNRTONCE pfnOnce, PFNRTONCECLEANUP pfnCleanUp, void *pvUser)
+{
+ int32_t iState = ASMAtomicUoReadS32(&pOnce->iState);
+ if (RT_LIKELY( iState == RTONCESTATE_DONE
+ || iState == RTONCESTATE_DONE_CREATING_SEM
+ || iState == RTONCESTATE_DONE_HAVE_SEM ))
+ return ASMAtomicUoReadS32(&pOnce->rc);
+ return RTOnceSlow(pOnce, pfnOnce, pfnCleanUp, pvUser);
+}
+
+/**
+ * Resets an execute once variable.
+ *
+ * The caller is responsible for making sure there are no concurrent accesses to
+ * the execute once variable.
+ *
+ * @param pOnce Pointer to the execute once variable.
+ */
+RTDECL(void) RTOnceReset(PRTONCE pOnce);
+
+/**
+ * Check whether the execute once variable was successfullly initialized.
+ */
+DECLINLINE(bool) RTOnceWasInitialized(PRTONCE pOnce)
+{
+ int32_t const iState = ASMAtomicUoReadS32(&pOnce->iState);
+ int32_t const rc = ASMAtomicUoReadS32(&pOnce->rc);
+ return RT_SUCCESS(rc)
+ && ( iState == RTONCESTATE_DONE
+ || iState == RTONCESTATE_DONE_CREATING_SEM
+ || iState == RTONCESTATE_DONE_HAVE_SEM);
+}
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_once_h */
+
diff --git a/include/iprt/param.h b/include/iprt/param.h
new file mode 100644
index 00000000..224064b6
--- /dev/null
+++ b/include/iprt/param.h
@@ -0,0 +1,137 @@
+/** @file
+ * IPRT - Parameter Definitions.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_param_h
+#define IPRT_INCLUDED_param_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cdefs.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
+#elif defined(RT_ARCH_ARM64)
+# define PAGE_SIZE 16384
+#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
+#elif defined(RT_ARCH_ARM64)
+# define PAGE_SHIFT 14
+#else
+# define PAGE_SHIFT 12
+#endif
+
+/**
+ * i386 Page offset mask.
+ *
+ * @note If you do one-complement this, always insert a target type case after
+ * the operator! Otherwise you may end up with weird results.
+ */
+#if defined(RT_ARCH_SPARC64)
+# define PAGE_OFFSET_MASK 0x1fff
+#elif defined(RT_ARCH_ARM64)
+# define PAGE_OFFSET_MASK 0x3fff
+#else
+# define PAGE_OFFSET_MASK 0xfff
+#endif
+
+/**
+ * Page address mask for the uintptr_t sized 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 (~(uintptr_t)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_INCLUDED_path_h) || defined(DOXYGEN_RUNNING)
+# define RTPATH_MAX (4096 + 4) /* (PATH_MAX + 1) on linux w/ some alignment */
+#endif
+
+/** @} */
+
+#endif /* !IPRT_INCLUDED_param_h */
+
diff --git a/include/iprt/path.h b/include/iprt/path.h
new file mode 100644
index 00000000..285d9f19
--- /dev/null
+++ b/include/iprt/path.h
@@ -0,0 +1,1674 @@
+/** @file
+ * IPRT - Path Manipulation.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_path_h
+#define IPRT_INCLUDED_path_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#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_INCLUDED_param_h) || defined(DOXYGEN_RUNNING)
+# define RTPATH_MAX (4096 + 4) /* (PATH_MAX + 1) on linux w/ some alignment */
+#endif
+
+/**
+ * The absolute max host path length we are willing to support.
+ * @note Not really suitable for stack buffers.
+ */
+#define RTPATH_BIG_MAX (_64K)
+
+/** @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)
+/** Current RTPATH_F_XXX flag mask. */
+#define RTPATH_F_MASK UINT32_C(0x00000007)
+/** @} */
+
+/** 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) )
+
+#if defined(RT_OS_WINDOWS) || defined(DOXYGEN_RUNNING)
+/** @def RTPATH_NT_PASSTHRU_PREFIX
+ * Prefix used to access the NT namespace directly.
+ * This forms an invalid UNC name. */
+# define RTPATH_NT_PASSTHRU_PREFIX "\\\\:iprtnt:\\"
+#endif
+
+/**
+ * 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 cbAbsPath Size of the buffer.
+ *
+ * @note Current implementation is buggy and will remove trailing slashes
+ * that would normally specify a directory. Don't depend on this.
+ */
+RTDECL(int) RTPathAbs(const char *pszPath, char *pszAbsPath, size_t cbAbsPath);
+
+/**
+ * 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.
+ *
+ * @note Current implementation is buggy and will remove trailing slashes
+ * that would normally specify a directory. Don't depend on this.
+ */
+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 fFlags One of the RTPATH_STR_F_STYLE_XXX flags combined
+ * with any of the RTPATHABS_F_XXX ones. Most
+ * users will pass RTPATH_STR_F_STYLE_HOST (0).
+ * @param pszAbsPath Where to store the absolute path.
+ * @param pcbAbsPath Hold the size of the buffer when called. The return
+ * value is the string length on success, and the
+ * required (or slightly more in some case) buffer
+ * size, including terminator, on VERR_BUFFER_OVERFLOW
+ * failures.
+ */
+RTDECL(int) RTPathAbsEx(const char *pszBase, const char *pszPath, uint32_t fFlags, char *pszAbsPath, size_t *pcbAbsPath);
+
+/** @name RTPATHABS_F_XXX - Flags for RTPathAbsEx.
+ * @note The RTPATH_F_STR_XXX style flags also applies.
+ * @{ */
+/** Treat specified base directory as a root that cannot be ascended beyond. */
+#define RTPATHABS_F_STOP_AT_BASE RT_BIT_32(16)
+/** Treat CWD as a root that cannot be ascended beyond. */
+#define RTPATHABS_F_STOP_AT_CWD RT_BIT_32(17)
+/** Ensure trailing slash in the result. */
+#define RTPATHABS_F_ENSURE_TRAILING_SLASH RT_BIT_32(18)
+/** @} */
+
+/**
+ * Same as RTPathAbsEx only the result is RTStrDup()'ed.
+ *
+ * @returns Pointer to the absolute path. Use RTStrFree() to free this string.
+ * @retval 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.
+ * @param fFlags One of the RTPATH_STR_F_STYLE_XXX flags combined
+ * with any of the RTPATHABS_F_XXX ones. Most
+ * users will pass RTPATH_STR_F_STYLE_HOST (0).
+ */
+RTDECL(char *) RTPathAbsExDup(const char *pszBase, const char *pszPath, uint32_t fFlags);
+
+/**
+ * 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);
+
+/**
+ * Skips the root specification, if present.
+ *
+ * @return Pointer to the first char after the root specification. This can be
+ * pointing to the terminator, if the path is only a root
+ * specification.
+ * @param pszPath The path to skip ahead in.
+ */
+RTDECL(char *) RTPathSkipRootSpec(const 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);
+
+/**
+ * Same as RTPathEnsureTrailingSeparator but with selectable path style.
+ *
+ * @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.
+ * @param fFlags The path style, RTPATH_STR_F_STYLE_XXX.
+ * @sa RTPathEnsureTrailingSeparator
+ */
+RTDECL(size_t) RTPathEnsureTrailingSeparatorEx(char *pszPath, size_t cbPath, uint32_t fFlags);
+
+/**
+ * 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);
+
+/**
+ * Purges a string so it can be used as a file according to fFlags.
+ *
+ * Illegal filename characters are replaced by '_'.
+ *
+ * @returns pszString
+ * @param pszString The string to purge.
+ * @param fFlags One of the RTPATH_STR_F_STYLE_XXX flags. Most users
+ * will pass RTPATH_STR_F_STYLE_HOST (0).
+ */
+RTDECL(char *) RTPathPurgeFilename(char *pszString, uint32_t fFlags);
+
+/**
+ * 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);
+RTDECL(PRTUTF16) RTPathFilenameUtf16(PCRTUTF16 pwszPath);
+
+/**
+ * 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);
+RTDECL(PRTUTF16) RTPathFilenameExUtf16(PCRTUTF16 pwszPath, uint32_t fFlags);
+
+/**
+ * Finds the common path in a given set of paths.
+ *
+ * The paths are not made absolute or real, they are taken as given.
+ *
+ * @returns The common path length as represented by \a papszPaths[0], 0 if not
+ * found or invalid input.
+ * @param cPaths Number of paths in \a papszPaths.
+ * @param papszPaths Array of paths to find common path for. The paths must
+ * not contains ".." sequences, as that's too complicated
+ * to handle.
+ */
+RTDECL(size_t) RTPathFindCommon(size_t cPaths, const char * const *papszPaths);
+
+/**
+ * Finds the common path in a given set of paths, extended version.
+ *
+ * The paths are not made absolute or real, they are taken as given.
+ *
+ * @returns The common path length as represented by \a papszPaths[0], 0 if not
+ * found or invalid input.
+ * @param cPaths Number of paths in \a papszPaths.
+ * @param papszPaths Array of paths to find common path for. The paths must
+ * not contains ".." sequences, as that's too complicated
+ * to handle.
+ * @param fFlags RTPATH_STR_F_STYLE_XXX, RTPATH_STR_F_NO_START, and
+ * RTPATHFINDCOMMON_F_IGNORE_DOTDOT as desired. Other
+ * RTPATH_STR_F_XXX flags will be ignored.
+ */
+RTDECL(size_t) RTPathFindCommonEx(size_t cPaths, const char * const *papszPaths, uint32_t fFlags);
+
+/** @name RTPATHFINDCOMMON_F_XXX - Flags for RTPathFindCommonEx.
+ * @{ */
+/** Ignore the dangers of '..' components. */
+#define RTPATHFINDCOMMON_F_IGNORE_DOTDOT RT_BIT_32(16)
+/** @} */
+
+/**
+ * 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);
+
+/**
+ * Determins the length of the parent part of the given path.
+ *
+ * @returns The length of the parent section of the path, including the final
+ * path separator. Returns 0 if only filename or empty path.
+ * @param pszPath The path to evaluate.
+ *
+ * @note Will stop at the server for UNC paths, so given "//server/share/"
+ * the parent length will be 9.
+ */
+RTDECL(size_t) RTPathParentLength(const char *pszPath);
+
+/**
+ * Determins the length of the parent part of the given path, extended variant.
+ *
+ * @returns The length of the parent section of the path, including the final
+ * path separator. Returns 0 if only filename or empty path.
+ * @param pszPath The path to evaluate.
+ * @param fFlags RTPATH_STR_F_STYLE_XXX and RTPATH_STR_F_NO_START.
+ * Asserts and ignores RTPATH_STR_F_NO_END.
+ *
+ * @note Will stop at the server for UNC paths, so given "//server/share/"
+ * the parent length will be 9.
+ */
+RTDECL(size_t) RTPathParentLengthEx(const char *pszPath, uint32_t fFlags);
+
+/**
+ * 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)
+/** Special UNC root.
+ * The share name is not sacred when this is set. */
+#define RTPATH_PROP_SPECIAL_UNC UINT16_C(0x2000)
+
+
+/** 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 length 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! */
+ RT_FLEXIBLE_ARRAY_EXTENSION
+ struct
+ {
+ /** The offset of the component. */
+ uint16_t off;
+ /** The length of the component. */
+ uint16_t cch;
+ } aComps[RT_FLEXIBLE_ARRAY];
+} RTPATHPARSED;
+/** Pointer to to a parsed path result. */
+typedef RTPATHPARSED *PRTPATHPARSED;
+/** Pointer to to a const parsed path result. */
+typedef RTPATHPARSED *PCRTPATHPARSED;
+
+/** Stupid hack for MSC and flexible arrays. */
+#define RTPATHPARSED_MIN_SIZE (sizeof(uint16_t) * (6 + 4))
+
+
+/**
+ * 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 the destination buffer is too small.
+ * The necessary length is @a pParsed->cchPath + 1 (updated).
+ *
+ * @param pszSrcPath The source path.
+ * @param pParsed The parser output for @a pszSrcPath. Caller may
+ * eliminate elements by setting their length to
+ * zero. The cchPath member is updated.
+ * @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). */
+ RT_FLEXIBLE_ARRAY_EXTENSION
+ char *apszComps[RT_FLEXIBLE_ARRAY];
+} 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.
+ * @param fFlags Combination of RTPATH_STR_F_STYLE_XXX.
+ * Most users will pass 0 / RTPATH_STR_F_STYLE_HOST.
+ *
+ * @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, uint32_t fFlags);
+
+/**
+ * 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.
+ * @param fFlags Combination of RTPATH_STR_F_STYLE_XXX.
+ * Most users will pass 0 / RTPATH_STR_F_STYLE_HOST.
+ *
+ */
+RTDECL(int) RTPathJoinEx(char *pszPathDst, size_t cbPathDst,
+ const char *pszPathSrc, size_t cchPathSrcMax,
+ const char *pszAppend, size_t cchAppendMax, uint32_t fFlags);
+
+/**
+ * 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 DECLCALLBACKTYPE(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 fFromFile Whether @a pszPathFrom is a file and we should work
+ * relative to it's parent directory (@c true), or if
+ * we should assume @a pszPathFrom is a directory and
+ * work relative to it.
+ * @param pszPathTo The path to reach with the created relative path.
+ */
+RTDECL(int) RTPathCalcRelative(char *pszPathDst, size_t cbPathDst, const char *pszPathFrom, bool fFromFile, 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);
+
+# ifdef RT_OS_WINDOWS
+
+/**
+ * Converts the given UTF-8 path into a native windows path.
+ *
+ * @returns IPRT status code.
+ * @param ppwszPath Where to return the path. This will always be
+ * set to NULL on failure. Use RTPathWinFree to
+ * free it when done.
+ * @param pszPath The UTF-8 path to convert.
+ * @param fFlags MBZ, reserved for future hacks.
+ * @sa RTPathWinFree, RTNtPathFromWinUtf8, RTNtPathRelativeFromUtf8.
+ */
+RTDECL(int) RTPathWinFromUtf8(PRTUTF16 *ppwszPath, const char *pszPath, uint32_t fFlags);
+
+/**
+ * Frees a native windows path returned by RTPathWinFromUtf8
+ *
+ * @param pwszPath The path to free. NULL is ignored.
+ */
+RTDECL(void) RTPathWinFree(PRTUTF16 pwszPath);
+
+# endif /* RT_OS_WINDOWS */
+
+#endif /* IN_RING3 */
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_path_h */
+
diff --git a/include/iprt/pipe.h b/include/iprt/pipe.h
new file mode 100644
index 00000000..a47f2d58
--- /dev/null
+++ b/include/iprt/pipe.h
@@ -0,0 +1,293 @@
+/** @file
+ * IPRT - Anonymous Pipes.
+ */
+
+/*
+ * Copyright (C) 2010-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_pipe_h
+#define IPRT_INCLUDED_pipe_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+#include <iprt/fs.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_pipe RTPipe - Anonymous Pipes
+ * @ingroup grp_rt
+ *
+ * @note The current Windows implementation has some peculiarities,
+ * especially with respect to the write side where the it is possible
+ * to write one extra pipe buffer sized block of data when the pipe
+ * buffer is full.
+ *
+ * @{
+ */
+
+/**
+ * Create an anonymous pipe.
+ *
+ * @returns IPRT status code.
+ * @param phPipeRead Where to return the read end of the pipe.
+ * @param phPipeWrite Where to return the write end of the pipe.
+ * @param fFlags A combination of RTPIPE_C_XXX defines.
+ */
+RTDECL(int) RTPipeCreate(PRTPIPE phPipeRead, PRTPIPE phPipeWrite, uint32_t fFlags);
+
+/** @name RTPipeCreate flags.
+ * @{ */
+/** Mark the read end as inheritable. */
+#define RTPIPE_C_INHERIT_READ RT_BIT(0)
+/** Mark the write end as inheritable. */
+#define RTPIPE_C_INHERIT_WRITE RT_BIT(1)
+/** Mask of valid flags. */
+#define RTPIPE_C_VALID_MASK UINT32_C(0x00000003)
+/** @} */
+
+/**
+ * Closes one end of a pipe created by RTPipeCreate.
+ *
+ * @returns IPRT status code.
+ * @param hPipe The pipe end to close.
+ */
+RTDECL(int) RTPipeClose(RTPIPE hPipe);
+
+/**
+ * Closes one end of a pipe created by RTPipeCreate, extended version.
+ *
+ * @returns IPRT status code.
+ * @param hPipe The pipe end to close.
+ * @param fLeaveOpen Wheter to leave the underlying native handle open
+ * (for RTPipeClose() this is @c false).
+ */
+RTDECL(int) RTPipeCloseEx(RTPIPE hPipe, bool fLeaveOpen);
+
+/**
+ * Creates an IPRT pipe handle from a native one.
+ *
+ * Do NOT use the native handle after passing it to this function, IPRT owns it
+ * and might even have closed in some cases (in order to gain some query
+ * information access on Windows).
+ *
+ * @returns IPRT status code.
+ * @param phPipe Where to return the pipe handle.
+ * @param hNativePipe The native pipe handle.
+ * @param fFlags Pipe flags, RTPIPE_N_XXX.
+ */
+RTDECL(int) RTPipeFromNative(PRTPIPE phPipe, RTHCINTPTR hNativePipe, uint32_t fFlags);
+
+/** @name RTPipeFromNative flags.
+ * @{ */
+/** The read end. */
+#define RTPIPE_N_READ RT_BIT(0)
+/** The write end. */
+#define RTPIPE_N_WRITE RT_BIT(1)
+/** Make sure the pipe is inheritable if set and not inheritable when clear. */
+#define RTPIPE_N_INHERIT RT_BIT(2)
+/** Mask of valid flags for . */
+#define RTPIPE_N_VALID_MASK UINT32_C(0x00000007)
+/** RTPipeFromNative: Leave the native pipe handle open on close. */
+#define RTPIPE_N_LEAVE_OPEN RT_BIT(3)
+/** Mask of valid flags for RTPipeFromNative(). */
+#define RTPIPE_N_VALID_MASK_FN UINT32_C(0x0000000f)
+/** @} */
+
+/**
+ * Gets the native handle for an IPRT pipe handle.
+ *
+ * This is mainly for passing a pipe to a child and then closing the parent
+ * handle. IPRT also uses it internally to implement RTProcCreatEx and
+ * RTPollSetAdd on some platforms. Do NOT expect sane API behavior if used
+ * for any other purpose.
+ *
+ * @returns The native handle. -1 on failure.
+ * @param hPipe The IPRT pipe handle.
+ */
+RTDECL(RTHCINTPTR) RTPipeToNative(RTPIPE hPipe);
+
+/**
+ * Get the creation inheritability of the pipe.
+ *
+ * @returns true if inherited by children (when pipe was created), false if not.
+ * @param hPipe The IPRT pipe handle.
+ */
+RTDECL(int) RTPipeGetCreationInheritability(RTPIPE hPipe);
+
+/**
+ * Read bytes from a pipe, non-blocking.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_WRONG_ORDER if racing a call to RTPipeReadBlocking.
+ * @retval VERR_BROKEN_PIPE if the remote party has disconnected and we've read
+ * all the buffered data.
+ * @retval VINF_TRY_AGAIN if no data was available. @a *pcbRead will be set to
+ * 0.
+ * @retval VERR_ACCESS_DENIED if it's a write pipe.
+ *
+ * @param hPipe The IPRT pipe handle to read from.
+ * @param pvBuf Where to put the bytes we read.
+ * @param cbToRead How much to read. Must be greater than 0.
+ * @param pcbRead Where to return the number of bytes that has been
+ * read (mandatory). This is 0 if there is no more
+ * bytes to read.
+ * @sa RTPipeReadBlocking.
+ */
+RTDECL(int) RTPipeRead(RTPIPE hPipe, void *pvBuf, size_t cbToRead, size_t *pcbRead);
+
+/**
+ * Read bytes from a pipe, blocking.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_WRONG_ORDER if racing a call to RTPipeRead.
+ * @retval VERR_BROKEN_PIPE if the remote party has disconnected and we've read
+ * all the buffered data.
+ * @retval VERR_ACCESS_DENIED if it's a write pipe.
+ *
+ * @param hPipe The IPRT pipe handle to read from.
+ * @param pvBuf Where to put the bytes we read.
+ * @param cbToRead How much to read.
+ * @param pcbRead Where to return the number of bytes that has been
+ * read. Optional.
+ */
+RTDECL(int) RTPipeReadBlocking(RTPIPE hPipe, void *pvBuf, size_t cbToRead, size_t *pcbRead);
+
+/**
+ * Write bytes to a pipe, non-blocking.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_WRONG_ORDER if racing a call to RTPipeWriteBlocking.
+ * @retval VERR_BROKEN_PIPE if the remote party has disconnected. Does not
+ * trigger when @a cbToWrite is 0.
+ * @retval VINF_TRY_AGAIN if no data was written. @a *pcbWritten will be set
+ * to 0.
+ * @retval VERR_ACCESS_DENIED if it's a read pipe.
+ *
+ * @param hPipe The IPRT pipe handle to write to.
+ * @param pvBuf What to write.
+ * @param cbToWrite How much to write.
+ * @param pcbWritten How many bytes we wrote, mandatory. The return can
+ * be 0.
+ */
+RTDECL(int) RTPipeWrite(RTPIPE hPipe, const void *pvBuf, size_t cbToWrite, size_t *pcbWritten);
+
+/**
+ * Write bytes to a pipe, blocking.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_WRONG_ORDER if racing a call to RTPipeWrite.
+ * @retval VERR_BROKEN_PIPE if the remote party has disconnected. Does not
+ * trigger when @a cbToWrite is 0.
+ * @retval VERR_ACCESS_DENIED if it's a read pipe.
+ *
+ * @param hPipe The IPRT pipe handle to write to.
+ * @param pvBuf What to write.
+ * @param cbToWrite How much to write.
+ * @param pcbWritten How many bytes we wrote, optional. If NULL then all
+ * bytes will be written.
+ */
+RTDECL(int) RTPipeWriteBlocking(RTPIPE hPipe, const void *pvBuf, size_t cbToWrite, size_t *pcbWritten);
+
+/**
+ * Flushes the buffers for the specified pipe and making sure the other party
+ * reads them.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_NOT_SUPPORTED if not supported by the OS.
+ * @retval VERR_BROKEN_PIPE if the remote party has disconnected.
+ * @retval VERR_ACCESS_DENIED if it's a read pipe.
+ *
+ * @param hPipe The IPRT pipe handle to flush.
+ */
+RTDECL(int) RTPipeFlush(RTPIPE hPipe);
+
+/**
+ * Checks if the pipe is ready for reading or writing (depending on the pipe
+ * end).
+ *
+ * @returns IPRT status code.
+ * @retval VERR_TIMEOUT if the timeout was reached before the pipe was ready
+ * for reading/writing.
+ * @retval VERR_NOT_SUPPORTED if not supported by the OS?
+ *
+ * @param hPipe The IPRT pipe handle to select on.
+ * @param cMillies Number of milliseconds to wait. Use
+ * RT_INDEFINITE_WAIT to wait for ever.
+ */
+RTDECL(int) RTPipeSelectOne(RTPIPE hPipe, RTMSINTERVAL cMillies);
+
+/**
+ * Queries the number of bytes immediately available for reading.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_NOT_SUPPORTED if not supported by the OS. The caller shall
+ * handle this case.
+ *
+ * @param hPipe The IPRT read pipe handle.
+ * @param pcbReadable Where to return the number of bytes that is ready
+ * to be read.
+ */
+RTDECL(int) RTPipeQueryReadable(RTPIPE hPipe, size_t *pcbReadable);
+
+/**
+ * Query information about a pipe (mainly a VFS I/O stream formality).
+ *
+ * The only thing we guarentee to be returned is RTFSOBJINFO::Attr.fMode being
+ * set to FIFO and will reflect the read/write end in the RTFS_DOS_READONLY,
+ * RTFS_UNIX_IRUSR and RTFS_UNIX_IWUSR bits.
+ *
+ * Some implementations sometimes provide the pipe buffer size via
+ * RTFSOBJINFO::cbAllocated.
+ *
+ * Some implementations sometimes provide the available read data or available
+ * write space via RTFSOBJINFO::cbObject.
+ *
+ * Some implementations sometimes provide valid device and/or inode numbers.
+ *
+ * @returns iprt status code.
+ *
+ * @param hPipe The IPRT read pipe handle.
+ * @param pObjInfo Object information structure to be filled on successful
+ * return.
+ * @param enmAddAttr Which set of additional attributes to request. Use
+ * RTFSOBJATTRADD_NOTHING if this doesn't matter.
+ */
+RTDECL(int) RTPipeQueryInfo(RTPIPE hPipe, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr);
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_pipe_h */
+
diff --git a/include/iprt/poll.h b/include/iprt/poll.h
new file mode 100644
index 00000000..be2b3b6d
--- /dev/null
+++ b/include/iprt/poll.h
@@ -0,0 +1,265 @@
+/** @file
+ * IPRT - Polling I/O Handles.
+ */
+
+/*
+ * Copyright (C) 2010-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_poll_h
+#define IPRT_INCLUDED_poll_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_poll RTPoll - Polling I/O Handles
+ * @ingroup grp_rt
+ * @{
+ */
+
+/** @name Poll events
+ * @{ */
+/** Readable without blocking. */
+#define RTPOLL_EVT_READ RT_BIT_32(0)
+/** Writable without blocking. */
+#define RTPOLL_EVT_WRITE RT_BIT_32(1)
+/** Error condition, hangup, exception or similar. */
+#define RTPOLL_EVT_ERROR RT_BIT_32(2)
+/** Mask of the valid bits. */
+#define RTPOLL_EVT_VALID_MASK UINT32_C(0x00000007)
+/** @} */
+
+/**
+ * Polls on the specified poll set until an event occurs on one of the handles
+ * or the timeout expires.
+ *
+ * @returns IPRT status code.
+ * @retval VINF_SUCCESS if an event occurred on a handle. Note that these
+ * @retval VERR_INVALID_HANDLE if @a hPollSet is invalid.
+ * @retval VERR_CONCURRENT_ACCESS if another thread is already accessing the set. The
+ * user is responsible for ensuring single threaded access.
+ * @retval VERR_TIMEOUT if @a cMillies ellapsed without any events.
+ * @retval VERR_DEADLOCK if @a cMillies is set to RT_INDEFINITE_WAIT and there
+ * are no valid handles in the set.
+ *
+ * @param hPollSet The set to poll on.
+ * @param cMillies Number of milliseconds to wait. Use
+ * RT_INDEFINITE_WAIT to wait for ever.
+ * @param pfEvents Where to return details about the events that
+ * occurred. Optional.
+ * @param pid Where to return the ID associated with the
+ * handle when calling RTPollSetAdd. Optional.
+ *
+ * @sa RTPollNoResume
+ *
+ * @remarks The caller is responsible for ensuring
+ */
+RTDECL(int) RTPoll(RTPOLLSET hPollSet, RTMSINTERVAL cMillies, uint32_t *pfEvents, uint32_t *pid);
+
+/**
+ * Same as RTPoll except that it will return when interrupted.
+ *
+ * @returns IPRT status code.
+ * @retval VINF_SUCCESS if an event occurred on a handle. Note that these
+ * @retval VERR_INVALID_HANDLE if @a hPollSet is invalid.
+ * @retval VERR_CONCURRENT_ACCESS if another thread is already accessing the set. The
+ * user is responsible for ensuring single threaded access.
+ * @retval VERR_TIMEOUT if @a cMillies ellapsed without any events.
+ * @retval VERR_DEADLOCK if @a cMillies is set to RT_INDEFINITE_WAIT and there
+ * are no valid handles in the set.
+ * @retval VERR_INTERRUPTED if a signal or other asynchronous event interrupted
+ * the polling.
+ *
+ * @param hPollSet The set to poll on.
+ * @param cMillies Number of milliseconds to wait. Use
+ * RT_INDEFINITE_WAIT to wait for ever.
+ * @param pfEvents Where to return details about the events that
+ * occurred. Optional.
+ * @param pid Where to return the ID associated with the
+ * handle when calling RTPollSetAdd. Optional.
+ */
+RTDECL(int) RTPollNoResume(RTPOLLSET hPollSet, RTMSINTERVAL cMillies, uint32_t *pfEvents, uint32_t *pid);
+
+/**
+ * Creates a poll set with no members.
+ *
+ * @returns IPRT status code.
+ * @param phPollSet Where to return the poll set handle.
+ */
+RTDECL(int) RTPollSetCreate(PRTPOLLSET phPollSet);
+
+/**
+ * Destroys a poll set.
+ *
+ * @returns IPRT status code.
+ * @param hPollSet The poll set to destroy. NIL_POLLSET is quietly
+ * ignored (VINF_SUCCESS).
+ */
+RTDECL(int) RTPollSetDestroy(RTPOLLSET hPollSet);
+
+/**
+ * Adds a generic handle to the poll set.
+ *
+ * If a handle is entered more than once, it is recommended to add the one with
+ * RTPOLL_EVT_ERROR first to ensure that you get the right ID back when an error
+ * actually occurs. On some hosts it is possible that polling for
+ * RTPOLL_EVT_READ on a socket may cause it to return error conditions because
+ * the two cannot so easily be distinguished.
+ *
+ * Also note that RTPOLL_EVT_ERROR may be returned by RTPoll even if not asked
+ * for.
+ *
+ * @returns IPRT status code
+ * @retval VERR_CONCURRENT_ACCESS if another thread is already accessing the set. The
+ * user is responsible for ensuring single threaded access.
+ * @retval VERR_POLL_HANDLE_NOT_POLLABLE if the specified handle is not
+ * pollable.
+ * @retval VERR_POLL_HANDLE_ID_EXISTS if the handle ID is already in use in the
+ * set.
+ *
+ * @param hPollSet The poll set to modify.
+ * @param pHandle The handle to add. NIL handles are quietly
+ * ignored.
+ * @param fEvents Which events to poll for.
+ * @param id The handle ID.
+ */
+RTDECL(int) RTPollSetAdd(RTPOLLSET hPollSet, PCRTHANDLE pHandle, uint32_t fEvents, uint32_t id);
+
+/**
+ * Removes a generic handle from the poll set.
+ *
+ * @returns IPRT status code
+ * @retval VERR_INVALID_HANDLE if @a hPollSet not valid.
+ * @retval VERR_CONCURRENT_ACCESS if another thread is already accessing the set. The
+ * user is responsible for ensuring single threaded access.
+ * @retval VERR_POLL_HANDLE_ID_NOT_FOUND if @a id doesn't resolve to a valid
+ * handle.
+ *
+ * @param hPollSet The poll set to modify.
+ * @param id The handle ID of the handle that should be
+ * removed.
+ */
+RTDECL(int) RTPollSetRemove(RTPOLLSET hPollSet, uint32_t id);
+
+
+/**
+ * Query a handle in the poll set by it's ID.
+ *
+ * @returns IPRT status code
+ * @retval VINF_SUCCESS if the handle was found. @a *pHandle is set.
+ * @retval VERR_INVALID_HANDLE if @a hPollSet is invalid.
+ * @retval VERR_CONCURRENT_ACCESS if another thread is already accessing the set. The
+ * user is responsible for ensuring single threaded access.
+ * @retval VERR_POLL_HANDLE_ID_NOT_FOUND if there is no handle with that ID.
+ *
+ * @param hPollSet The poll set to query.
+ * @param id The ID of the handle.
+ * @param pHandle Where to return the handle details. Optional.
+ */
+RTDECL(int) RTPollSetQueryHandle(RTPOLLSET hPollSet, uint32_t id, PRTHANDLE pHandle);
+
+/**
+ * Gets the number of handles in the set.
+ *
+ * @retval The handle count.
+ * @retval UINT32_MAX if @a hPollSet is invalid or there is concurrent access.
+ *
+ * @param hPollSet The poll set.
+ */
+RTDECL(uint32_t) RTPollSetGetCount(RTPOLLSET hPollSet);
+
+/**
+ * Modifies the events to poll for for the given id.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_INVALID_HANDLE if @a hPollSet not valid.
+ * @retval VERR_CONCURRENT_ACCESS if another thread is already accessing the set. The
+ * user is responsible for ensuring single threaded access.
+ * @retval VERR_POLL_HANDLE_ID_NOT_FOUND if @a id doesn't resolve to a valid
+ * handle.
+ *
+ * @param hPollSet The poll set to modify.
+ * @param id The handle ID to change the events for.
+ * @param fEvents Which events to poll for.
+ */
+RTDECL(int) RTPollSetEventsChange(RTPOLLSET hPollSet, uint32_t id, uint32_t fEvents);
+
+/**
+ * Adds a pipe handle to the set.
+ *
+ * @returns See RTPollSetAdd.
+ *
+ * @param hPollSet The poll set.
+ * @param hPipe The pipe handle.
+ * @param fEvents Which events to poll for.
+ * @param id The handle ID.
+ *
+ * @todo Maybe we could figure out what to poll for depending on the kind of
+ * pipe we're dealing with.
+ */
+DECLINLINE(int) RTPollSetAddPipe(RTPOLLSET hPollSet, RTPIPE hPipe, uint32_t fEvents, uint32_t id)
+{
+ RTHANDLE Handle;
+ Handle.enmType = RTHANDLETYPE_PIPE;
+ Handle.u.uInt = 0;
+ Handle.u.hPipe = hPipe;
+ return RTPollSetAdd(hPollSet, &Handle, fEvents, id);
+}
+
+/**
+ * Adds a socket handle to the set.
+ *
+ * @returns See RTPollSetAdd.
+ *
+ * @param hPollSet The poll set.
+ * @param hSocket The socket handle.
+ * @param fEvents Which events to poll for.
+ * @param id The handle ID.
+ */
+DECLINLINE(int) RTPollSetAddSocket(RTPOLLSET hPollSet, RTSOCKET hSocket, uint32_t fEvents, uint32_t id)
+{
+ RTHANDLE Handle;
+ Handle.enmType = RTHANDLETYPE_SOCKET;
+ Handle.u.uInt = 0;
+ Handle.u.hSocket = hSocket;
+ return RTPollSetAdd(hPollSet, &Handle, fEvents, id);
+}
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_poll_h */
+
diff --git a/include/iprt/power.h b/include/iprt/power.h
new file mode 100644
index 00000000..d36e840d
--- /dev/null
+++ b/include/iprt/power.h
@@ -0,0 +1,125 @@
+/** @file
+ * IPRT - Power management.
+ */
+
+/*
+ * Copyright (C) 2008-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_power_h
+#define IPRT_INCLUDED_power_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#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 DECLCALLBACKTYPE(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 /* !IPRT_INCLUDED_power_h */
+
diff --git a/include/iprt/process.h b/include/iprt/process.h
new file mode 100644
index 00000000..de3590e8
--- /dev/null
+++ b/include/iprt/process.h
@@ -0,0 +1,479 @@
+/** @file
+ * IPRT - Process Management.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_process_h
+#define IPRT_INCLUDED_process_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#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
+
+
+/**
+ * Translate a signal number to a short name on the form SIGXXXX.
+ *
+ * If the signal is not known, it will be formatted as a number into one of
+ * several static buffers. This means that there could be concurrency issues if
+ * this suddenly happens on multiple threads, though that is unlikely.
+ *
+ * @returns Readonly string naming the signal.
+ * @param iSignal The signal to name.
+ */
+RTDECL(const char *) RTProcSignalName(int iSignal);
+
+#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 pvExtraData Points to additional data as per @a fFlags:
+ * - RTPROC_FLAGS_DESIRED_SESSION_ID: Pointing to a
+ * uint32_t variable with the desired session ID.
+ * @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, void *pvExtraData, 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. See
+ * also RTPROC_FLAGS_ONLY_BASIC_PROFILE */
+#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)
+/** Create process using the current impersonated thread token.
+ * Caller should also specify RTPROC_FLAGS_SERVICE and RTPROC_FLAGS_PROFILE.
+ * Windows only flag, ignored everywhere else. */
+#define RTPROC_FLAGS_AS_IMPERSONATED_TOKEN RT_BIT(9)
+/** Hint that we don't expect to ever want to wait on the process. */
+#define RTPROC_FLAGS_NO_WAIT RT_BIT(10)
+/** For use with RTPROC_FLAGS_SERVICE to specify a desired session ID
+ * (Windows only, ignored elsewhere). The @a pvExtraData argument points to
+ * a uint32_t containing the session ID, UINT32_MAX means any session.
+ * Can not be set with RTPROC_FLAGS_TOKEN_SUPPLIED */
+#define RTPROC_FLAGS_DESIRED_SESSION_ID RT_BIT(11)
+/** This is a modifier to RTPROC_FLAGS_PROFILE on unix systems that makes it
+ * skip trying to dump the environment of a login shell. */
+#define RTPROC_FLAGS_ONLY_BASIC_PROFILE RT_BIT(12)
+/** Don't translate arguments to the (guessed) child process codeset.
+ * This is ignored on Windows as it is using UTF-16. */
+#define RTPROC_FLAGS_UTF8_ARGV RT_BIT_32(13)
+/** Create process using supplied token. The @a pvExtraData argument points to
+ * a HANDLE containing the token used as user credentials for process creation.
+ * Can not be set with RTPROC_FLAGS_DESIRED_SESSION_ID.
+ * Windows only flag, ignored everywhere else. */
+#define RTPROC_FLAGS_TOKEN_SUPPLIED RT_BIT(14)
+
+/** Valid flag mask. */
+#define RTPROC_FLAGS_VALID_MASK UINT32_C(0x7fff)
+/** @} */
+
+
+/**
+ * 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.
+ * @note IPRT must've been initialized or the string will be empty.
+ */
+RTR3DECL(const char *) RTProcShortName(void);
+
+/**
+ * Gets the path to the executable image of the current process.
+ *
+ * @returns Pointer to read-only path string.
+ * @note IPRT must've been initialized or the string will be empty.
+ */
+RTR3DECL(const char *) RTProcExecutablePath(void);
+
+/**
+ * Gets a copy of 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.
+ * @note IPRT must've been initialized or the string will be empty.
+ */
+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 /* !IPRT_INCLUDED_process_h */
+
diff --git a/include/iprt/queueatomic.h b/include/iprt/queueatomic.h
new file mode 100644
index 00000000..72b188e1
--- /dev/null
+++ b/include/iprt/queueatomic.h
@@ -0,0 +1,137 @@
+/** @file
+ * IPRT - Generic Work Queue with concurrent atomic access.
+ */
+
+/*
+ * Copyright (C) 2013-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_queueatomic_h
+#define IPRT_INCLUDED_queueatomic_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+#include <iprt/asm.h>
+
+/** @defgroup grp_rt_queueatomic RTQueueAtomic - Generic Work Queue
+ * @ingroup grp_rt
+ *
+ * Implementation of a lockless work queue for threaded environments.
+ * @{
+ */
+
+RT_C_DECLS_BEGIN
+
+/**
+ * A work item
+ */
+typedef struct RTQUEUEATOMICITEM
+{
+ /** Pointer to the next work item in the list. */
+ struct RTQUEUEATOMICITEM * volatile pNext;
+} RTQUEUEATOMICITEM;
+/** Pointer to a work item. */
+typedef RTQUEUEATOMICITEM *PRTQUEUEATOMICITEM;
+/** Pointer to a work item pointer. */
+typedef PRTQUEUEATOMICITEM *PPRTQUEUEATOMICITEM;
+
+/**
+ * Work queue.
+ */
+typedef struct RTQUEUEATOMIC
+{
+ /* Head of the work queue. */
+ volatile PRTQUEUEATOMICITEM pHead;
+} RTQUEUEATOMIC;
+/** Pointer to a work queue. */
+typedef RTQUEUEATOMIC *PRTQUEUEATOMIC;
+
+/**
+ * Initialize a work queue.
+ *
+ * @param pWorkQueue Pointer to an unitialised work queue.
+ */
+DECLINLINE(void) RTQueueAtomicInit(PRTQUEUEATOMIC pWorkQueue)
+{
+ ASMAtomicWriteNullPtr(&pWorkQueue->pHead);
+}
+
+/**
+ * Insert a new item into the work queue.
+ *
+ * @param pWorkQueue The work queue to insert into.
+ * @param pItem The item to insert.
+ */
+DECLINLINE(void) RTQueueAtomicInsert(PRTQUEUEATOMIC pWorkQueue, PRTQUEUEATOMICITEM pItem)
+{
+ PRTQUEUEATOMICITEM pNext = ASMAtomicUoReadPtrT(&pWorkQueue->pHead, PRTQUEUEATOMICITEM);
+ PRTQUEUEATOMICITEM pHeadOld;
+ pItem->pNext = pNext;
+ while (!ASMAtomicCmpXchgExPtr(&pWorkQueue->pHead, pItem, pNext, &pHeadOld))
+ {
+ pNext = pHeadOld;
+ Assert(pNext != pItem);
+ pItem->pNext = pNext;
+ ASMNopPause();
+ }
+}
+
+/**
+ * Remove all items from the given work queue and return them in the inserted order.
+ *
+ * @returns Pointer to the first item.
+ * @param pWorkQueue The work queue.
+ */
+DECLINLINE(PRTQUEUEATOMICITEM) RTQueueAtomicRemoveAll(PRTQUEUEATOMIC pWorkQueue)
+{
+ PRTQUEUEATOMICITEM pHead = ASMAtomicXchgPtrT(&pWorkQueue->pHead, NULL, PRTQUEUEATOMICITEM);
+
+ /* Reverse it. */
+ PRTQUEUEATOMICITEM pCur = pHead;
+ pHead = NULL;
+ while (pCur)
+ {
+ PRTQUEUEATOMICITEM pInsert = pCur;
+ pCur = pCur->pNext;
+ pInsert->pNext = pHead;
+ pHead = pInsert;
+ }
+
+ return pHead;
+}
+
+RT_C_DECLS_END
+
+/** @} */
+
+#endif /* !IPRT_INCLUDED_queueatomic_h */
+
diff --git a/include/iprt/rand.h b/include/iprt/rand.h
new file mode 100644
index 00000000..149e0fb5
--- /dev/null
+++ b/include/iprt/rand.h
@@ -0,0 +1,330 @@
+/** @file
+ * IPRT - Random Numbers and Byte Streams.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_rand_h
+#define IPRT_INCLUDED_rand_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_rand RTRand - Random Numbers and Byte Streams
+ * @ingroup grp_rt
+ * @{
+ */
+
+/**
+ * Fills a buffer with random bytes.
+ *
+ * @param pv Where to store the random bytes.
+ * @param cb Number of bytes to generate.
+ */
+RTDECL(void) RTRandBytes(void *pv, size_t cb) RT_NO_THROW_PROTO;
+
+/**
+ * Generate a 32-bit signed random number in the set [i32First..i32Last].
+ *
+ * @returns The random number.
+ * @param i32First First number in the set.
+ * @param i32Last Last number in the set.
+ */
+RTDECL(int32_t) RTRandS32Ex(int32_t i32First, int32_t i32Last) RT_NO_THROW_PROTO;
+
+/**
+ * Generate a 32-bit signed random number.
+ *
+ * @returns The random number.
+ */
+RTDECL(int32_t) RTRandS32(void) RT_NO_THROW_PROTO;
+
+/**
+ * Generate a 32-bit unsigned random number in the set [u32First..u32Last].
+ *
+ * @returns The random number.
+ * @param u32First First number in the set.
+ * @param u32Last Last number in the set.
+ */
+RTDECL(uint32_t) RTRandU32Ex(uint32_t u32First, uint32_t u32Last) RT_NO_THROW_PROTO;
+
+/**
+ * Generate a 32-bit unsigned random number.
+ *
+ * @returns The random number.
+ */
+RTDECL(uint32_t) RTRandU32(void) RT_NO_THROW_PROTO;
+
+/**
+ * Generate a 64-bit signed random number in the set [i64First..i64Last].
+ *
+ * @returns The random number.
+ * @param i64First First number in the set.
+ * @param i64Last Last number in the set.
+ */
+RTDECL(int64_t) RTRandS64Ex(int64_t i64First, int64_t i64Last) RT_NO_THROW_PROTO;
+
+/**
+ * Generate a 64-bit signed random number.
+ *
+ * @returns The random number.
+ */
+RTDECL(int64_t) RTRandS64(void) RT_NO_THROW_PROTO;
+
+/**
+ * Generate a 64-bit unsigned random number in the set [u64First..u64Last].
+ *
+ * @returns The random number.
+ * @param u64First First number in the set.
+ * @param u64Last Last number in the set.
+ */
+RTDECL(uint64_t) RTRandU64Ex(uint64_t u64First, uint64_t u64Last) RT_NO_THROW_PROTO;
+
+/**
+ * Generate a 64-bit unsigned random number.
+ *
+ * @returns The random number.
+ */
+RTDECL(uint64_t) RTRandU64(void) RT_NO_THROW_PROTO;
+
+
+/**
+ * Create an instance of the default random number generator.
+ *
+ * @returns IPRT status code.
+ * @param phRand Where to return the handle to the new random number
+ * generator.
+ */
+RTDECL(int) RTRandAdvCreate(PRTRAND phRand) RT_NO_THROW_PROTO;
+
+/**
+ * Create an instance of the default pseudo random number generator.
+ *
+ * @returns IPRT status code.
+ * @param phRand Where to store the handle to the generator.
+ */
+RTDECL(int) RTRandAdvCreatePseudo(PRTRAND phRand) RT_NO_THROW_PROTO;
+
+/**
+ * Create an instance of the Park-Miller pseudo random number generator.
+ *
+ * @returns IPRT status code.
+ * @param phRand Where to store the handle to the generator.
+ */
+RTDECL(int) RTRandAdvCreateParkMiller(PRTRAND phRand) RT_NO_THROW_PROTO;
+
+/**
+ * Create an instance of the faster random number generator for the OS.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_NOT_SUPPORTED on platforms which doesn't have this feature.
+ * @retval VERR_FILE_NOT_FOUND on system where the random generator hasn't
+ * been installed or configured correctly.
+ * @retval VERR_PATH_NOT_FOUND for the same reasons as VERR_FILE_NOT_FOUND.
+ *
+ * @param phRand Where to store the handle to the generator.
+ *
+ * @remarks Think /dev/urandom.
+ */
+RTDECL(int) RTRandAdvCreateSystemFaster(PRTRAND phRand) RT_NO_THROW_PROTO;
+
+/**
+ * Create an instance of the truer random number generator for the OS.
+ *
+ * Don't use this unless you seriously need good random numbers because most
+ * systems will have will have problems producing sufficient entropy for this
+ * and you'll end up blocking while it accumulates.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_NOT_SUPPORTED on platforms which doesn't have this feature.
+ * @retval VERR_FILE_NOT_FOUND on system where the random generator hasn't
+ * been installed or configured correctly.
+ * @retval VERR_PATH_NOT_FOUND for the same reasons as VERR_FILE_NOT_FOUND.
+ *
+ * @param phRand Where to store the handle to the generator.
+ *
+ * @remarks Think /dev/random.
+ */
+RTDECL(int) RTRandAdvCreateSystemTruer(PRTRAND phRand) RT_NO_THROW_PROTO;
+
+/**
+ * Destroys a random number generator.
+ *
+ * @returns IPRT status code.
+ * @param hRand Handle to the random number generator.
+ */
+RTDECL(int) RTRandAdvDestroy(RTRAND hRand) RT_NO_THROW_PROTO;
+
+/**
+ * Generic method for seeding of a random number generator.
+ *
+ * The different generators may have specialized methods for
+ * seeding, use one of those if you desire better control
+ * over the result.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_NOT_SUPPORTED if it isn't a pseudo generator.
+ *
+ * @param hRand Handle to the random number generator.
+ * @param u64Seed Seed.
+ */
+RTDECL(int) RTRandAdvSeed(RTRAND hRand, uint64_t u64Seed) RT_NO_THROW_PROTO;
+
+/**
+ * Save the current state of a pseudo generator.
+ *
+ * This can be use to save the state so it can later be resumed at the same
+ * position.
+ *
+ * @returns IPRT status code.
+ * @retval VINF_SUCCESS on success. *pcbState contains the length of the
+ * returned string and pszState contains the state string.
+ * @retval VERR_BUFFER_OVERFLOW if the supplied buffer is too small. *pcbState
+ * will contain the necessary buffer size.
+ * @retval VERR_NOT_SUPPORTED by non-psuedo generators.
+ *
+ * @param hRand Handle to the random number generator.
+ * @param pszState Where to store the state. The returned string will be
+ * null terminated and printable.
+ * @param pcbState The size of the buffer pszState points to on input, the
+ * size required / used on return (including the
+ * terminator, thus the 'cb' instead of 'cch').
+ */
+RTDECL(int) RTRandAdvSaveState(RTRAND hRand, char *pszState, size_t *pcbState) RT_NO_THROW_PROTO;
+
+/**
+ * Restores the state of a pseudo generator.
+ *
+ * The state must have been obtained using RTRandAdvGetState.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_PARSE_ERROR if the state string is malformed.
+ * @retval VERR_NOT_SUPPORTED by non-psuedo generators.
+ *
+ * @param hRand Handle to the random number generator.
+ * @param pszState The state to load.
+ */
+RTDECL(int) RTRandAdvRestoreState(RTRAND hRand, char const *pszState) RT_NO_THROW_PROTO;
+
+/**
+ * Fills a buffer with random bytes.
+ *
+ * @param hRand Handle to the random number generator.
+ * @param pv Where to store the random bytes.
+ * @param cb Number of bytes to generate.
+ */
+RTDECL(void) RTRandAdvBytes(RTRAND hRand, void *pv, size_t cb) RT_NO_THROW_PROTO;
+
+/**
+ * Generate a 32-bit signed random number in the set [i32First..i32Last].
+ *
+ * @returns The random number.
+ * @param hRand Handle to the random number generator.
+ * @param i32First First number in the set.
+ * @param i32Last Last number in the set.
+ */
+RTDECL(int32_t) RTRandAdvS32Ex(RTRAND hRand, int32_t i32First, int32_t i32Last) RT_NO_THROW_PROTO;
+
+/**
+ * Generate a 32-bit signed random number.
+ *
+ * @returns The random number.
+ * @param hRand Handle to the random number generator.
+ */
+RTDECL(int32_t) RTRandAdvS32(RTRAND hRand) RT_NO_THROW_PROTO;
+
+/**
+ * Generate a 32-bit unsigned random number in the set [u32First..u32Last].
+ *
+ * @returns The random number.
+ * @param hRand Handle to the random number generator.
+ * @param u32First First number in the set.
+ * @param u32Last Last number in the set.
+ */
+RTDECL(uint32_t) RTRandAdvU32Ex(RTRAND hRand, uint32_t u32First, uint32_t u32Last) RT_NO_THROW_PROTO;
+
+/**
+ * Generate a 32-bit unsigned random number.
+ *
+ * @returns The random number.
+ * @param hRand Handle to the random number generator.
+ */
+RTDECL(uint32_t) RTRandAdvU32(RTRAND hRand) RT_NO_THROW_PROTO;
+
+/**
+ * Generate a 64-bit signed random number in the set [i64First..i64Last].
+ *
+ * @returns The random number.
+ * @param hRand Handle to the random number generator.
+ * @param i64First First number in the set.
+ * @param i64Last Last number in the set.
+ */
+RTDECL(int64_t) RTRandAdvS64Ex(RTRAND hRand, int64_t i64First, int64_t i64Last) RT_NO_THROW_PROTO;
+
+/**
+ * Generate a 64-bit signed random number.
+ *
+ * @returns The random number.
+ */
+RTDECL(int64_t) RTRandAdvS64(RTRAND hRand) RT_NO_THROW_PROTO;
+
+/**
+ * Generate a 64-bit unsigned random number in the set [u64First..u64Last].
+ *
+ * @returns The random number.
+ * @param hRand Handle to the random number generator.
+ * @param u64First First number in the set.
+ * @param u64Last Last number in the set.
+ */
+RTDECL(uint64_t) RTRandAdvU64Ex(RTRAND hRand, uint64_t u64First, uint64_t u64Last) RT_NO_THROW_PROTO;
+
+/**
+ * Generate a 64-bit unsigned random number.
+ *
+ * @returns The random number.
+ * @param hRand Handle to the random number generator.
+ */
+RTDECL(uint64_t) RTRandAdvU64(RTRAND hRand) RT_NO_THROW_PROTO;
+
+
+/** @} */
+
+RT_C_DECLS_END
+
+
+#endif /* !IPRT_INCLUDED_rand_h */
+
diff --git a/include/iprt/req.h b/include/iprt/req.h
new file mode 100644
index 00000000..a017e9e1
--- /dev/null
+++ b/include/iprt/req.h
@@ -0,0 +1,643 @@
+/** @file
+ * IPRT - Request Queue & Pool.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_req_h
+#define IPRT_INCLUDED_req_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+
+#include <iprt/stdarg.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_req RTReq - Request Queue & Pool.
+ * @ingroup grp_rt
+ * @{
+ */
+
+/** Request queue handle. */
+typedef struct RTREQQUEUEINT *RTREQQUEUE;
+/** Pointer to a request queue handle. */
+typedef RTREQQUEUE *PRTREQQUEUE;
+/** NIL request queue handle. */
+#define NIL_RTREQQUEUE ((RTREQQUEUE)0)
+
+/** Request thread pool handle. */
+typedef struct RTREQPOOLINT *RTREQPOOL;
+/** Poiner to a request thread pool handle. */
+typedef RTREQPOOL *PRTREQPOOL;
+/** NIL request pool handle. */
+#define NIL_RTREQPOOL ((RTREQPOOL)0)
+
+
+/**
+ * Request type.
+ */
+typedef enum RTREQTYPE
+{
+ /** Invalid request. */
+ RTREQTYPE_INVALID = 0,
+ /** RT: Internal. */
+ RTREQTYPE_INTERNAL,
+ /** Maximum request type (exclusive). Used for validation. */
+ RTREQTYPE_MAX
+} RTREQTYPE;
+
+/**
+ * Request flags.
+ */
+typedef enum RTREQFLAGS
+{
+ /** The request returns a IPRT status code. */
+ RTREQFLAGS_IPRT_STATUS = 0,
+ /** The request is a void request and have no status code. */
+ RTREQFLAGS_VOID = 1,
+ /** Return type mask. */
+ RTREQFLAGS_RETURN_MASK = 1,
+ /** Caller does not wait on the packet. */
+ RTREQFLAGS_NO_WAIT = 2
+} RTREQFLAGS;
+
+
+/** A request packet. */
+typedef struct RTREQ RTREQ;
+/** Pointer to an RT request packet. */
+typedef RTREQ *PRTREQ;
+/** Nil request handle. */
+#define NIL_RTREQ ((PRTREQ)0)
+
+
+#ifdef IN_RING3
+
+/**
+ * Create a request packet queue
+ *
+ * @returns IPRT status code.
+ * @param phQueue Where to store the request queue handle.
+ */
+RTDECL(int) RTReqQueueCreate(PRTREQQUEUE phQueue);
+
+/**
+ * Destroy a request packet queue
+ *
+ * @returns IPRT status code.
+ * @param hQueue The request queue.
+ */
+RTDECL(int) RTReqQueueDestroy(RTREQQUEUE hQueue);
+
+/**
+ * Process one or more request packets
+ *
+ * @returns IPRT status code. Any non-VINF_SUCCESS returns from request
+ * processing is immediately propagated to the caller.
+ * @retval VERR_TIMEOUT if @a cMillies was reached without the packet being
+ * added.
+ * @retval VERR_INVALID_HANDLE if @a hQueue not a valid queue handle.
+ *
+ * @param hQueue The request queue.
+ * @param cMillies Max number of milliseconds to wait for a pending
+ * request. This is not adjusted down before another
+ * wait, so the function may end up waiting for much
+ * longer than the given amount if there are requests
+ * trickling in at a rate slightly higher than the
+ * timeout.
+ *
+ * Use RT_INDEFINITE_WAIT to process requests until a
+ * non-VINF_SUCCESS return code is encountered.
+ *
+ * @remarks The function may repeatedly try wait for @a cMillies on new
+ * requests if requests arrive before it times out.
+ */
+RTDECL(int) RTReqQueueProcess(RTREQQUEUE hQueue, RTMSINTERVAL cMillies);
+
+/**
+ * Allocate and queue a call request.
+ *
+ * If it's desired to poll on the completion of the request set cMillies
+ * to 0 and use RTReqWait() to check for completion. In the other case
+ * use RT_INDEFINITE_WAIT.
+ * The returned request packet must be freed using RTReqRelease().
+ *
+ * @returns iprt statuscode.
+ * Will not return VERR_INTERRUPTED.
+ * @returns VERR_TIMEOUT if cMillies was reached without the packet being completed.
+ *
+ * @param hQueue The request queue.
+ * @param ppReq Where to store the pointer to the request.
+ * This will be NULL or a valid request pointer no matter what happens.
+ * @param cMillies Number of milliseconds to wait for the request to
+ * be completed. Use RT_INDEFINITE_WAIT to only
+ * wait till it's completed.
+ * @param pfnFunction Pointer to the function to call.
+ * @param cArgs Number of arguments following in the ellipsis.
+ * @param ... Function arguments.
+ *
+ * @remarks See remarks on RTReqQueueCallV.
+ */
+RTDECL(int) RTReqQueueCall(RTREQQUEUE hQueue, PRTREQ *ppReq, RTMSINTERVAL cMillies, PFNRT pfnFunction, unsigned cArgs, ...);
+
+/**
+ * Allocate and queue a call request to a void function.
+ *
+ * If it's desired to poll on the completion of the request set cMillies
+ * to 0 and use RTReqWait() to check for completion. In the other case
+ * use RT_INDEFINITE_WAIT.
+ * The returned request packet must be freed using RTReqRelease().
+ *
+ * @returns IPRT status code.
+ * Will not return VERR_INTERRUPTED.
+ * @returns VERR_TIMEOUT if cMillies was reached without the packet being completed.
+ *
+ * @param hQueue The request queue.
+ * @param ppReq Where to store the pointer to the request.
+ * This will be NULL or a valid request pointer no matter what happens.
+ * @param cMillies Number of milliseconds to wait for the request to
+ * be completed. Use RT_INDEFINITE_WAIT to only
+ * wait till it's completed.
+ * @param pfnFunction Pointer to the function to call.
+ * @param cArgs Number of arguments following in the ellipsis.
+ * @param ... Function arguments.
+ *
+ * @remarks See remarks on RTReqQueueCallV.
+ */
+RTDECL(int) RTReqQueueCallVoid(RTREQQUEUE hQueue, PRTREQ *ppReq, RTMSINTERVAL cMillies, PFNRT pfnFunction, unsigned cArgs, ...);
+
+/**
+ * Allocate and queue a call request to a void function.
+ *
+ * If it's desired to poll on the completion of the request set cMillies
+ * to 0 and use RTReqWait() to check for completion. In the other case
+ * use RT_INDEFINITE_WAIT.
+ * The returned request packet must be freed using RTReqRelease().
+ *
+ * @returns IPRT status code.
+ * Will not return VERR_INTERRUPTED.
+ * @returns VERR_TIMEOUT if cMillies was reached without the packet being completed.
+ *
+ * @param hQueue The request queue.
+ * @param ppReq Where to store the pointer to the request. Optional
+ * when RTREQFLAGS_NO_WAIT is used.
+ * This variable will be set to NIL or a valid request
+ * handle no matter what happens.
+ * @param cMillies Number of milliseconds to wait for the request to
+ * be completed. Use RT_INDEFINITE_WAIT to only
+ * wait till it's completed.
+ * @param fFlags A combination of the RTREQFLAGS values.
+ * @param pfnFunction Pointer to the function to call.
+ * @param cArgs Number of arguments following in the ellipsis.
+ * @param ... Function arguments.
+ *
+ * @remarks See remarks on RTReqQueueCallV.
+ */
+RTDECL(int) RTReqQueueCallEx(RTREQQUEUE hQueue, PRTREQ *ppReq, RTMSINTERVAL cMillies, unsigned fFlags, PFNRT pfnFunction, unsigned cArgs, ...);
+
+/**
+ * Allocate and queue a call request.
+ *
+ * If it's desired to poll on the completion of the request set cMillies
+ * to 0 and use RTReqWait() to check for completion. In the other case
+ * use RT_INDEFINITE_WAIT.
+ * The returned request packet must be freed using RTReqRelease().
+ *
+ * @returns IPRT status code.
+ * Will not return VERR_INTERRUPTED.
+ * @returns VERR_TIMEOUT if cMillies was reached without the packet being completed.
+ *
+ * @param hQueue The request queue.
+ * @param ppReq Where to store the pointer to the request. Optional
+ * when RTREQFLAGS_NO_WAIT is used.
+ * This variable will be set to NIL or a valid request
+ * handle no matter what happens.
+ * @param cMillies Number of milliseconds to wait for the request to
+ * be completed. Use RT_INDEFINITE_WAIT to only
+ * wait till it's completed.
+ * @param fFlags A combination of the RTREQFLAGS values.
+ * @param pfnFunction Pointer to the function to call.
+ * @param cArgs Number of arguments following in the ellipsis.
+ * @param Args Variable argument vector.
+ *
+ * @remarks Caveats:
+ * - Do not pass anything which is larger than an uintptr_t.
+ * - 64-bit integers are larger than uintptr_t on 32-bit hosts.
+ * Pass integers > 32-bit by reference (pointers).
+ * - Don't use NULL since it should be the integer 0 in C++ and may
+ * therefore end up with garbage in the bits 63:32 on 64-bit
+ * hosts because 'int' is 32-bit.
+ * Use (void *)NULL or (uintptr_t)0 instead of NULL.
+ */
+RTDECL(int) RTReqQueueCallV(RTREQQUEUE hQueue, PRTREQ *ppReq, RTMSINTERVAL cMillies, unsigned fFlags, PFNRT pfnFunction, unsigned cArgs, va_list Args);
+
+/**
+ * Checks if the queue is busy or not.
+ *
+ * The caller is responsible for dealing with any concurrent submitts.
+ *
+ * @returns true if busy, false if idle.
+ * @param hQueue The queue.
+ */
+RTDECL(bool) RTReqQueueIsBusy(RTREQQUEUE hQueue);
+
+/**
+ * Allocates a request packet.
+ *
+ * The caller allocates a request packet, fills in the request data
+ * union and queues the request.
+ *
+ * @returns IPRT status code.
+ *
+ * @param hQueue The request queue.
+ * @param enmType Package type.
+ * @param phReq Where to store the handle to the new request.
+ */
+RTDECL(int) RTReqQueueAlloc(RTREQQUEUE hQueue, RTREQTYPE enmType, PRTREQ *phReq);
+
+
+/**
+ * Creates a request thread pool.
+ *
+ * The core configuration is given as parameters, finer pool tuning can be
+ * achieved via RTReqPoolSetCfgVar.
+ *
+ * @returns IPRT status code.
+ * @param cMaxThreads The maximum number of worker threads.
+ * UINT32_MAX is an alias for the highest
+ * allowed thread count.
+ * @param cMsMinIdle The number of milliseconds a worker
+ * thread needs to be idle before it is
+ * considered for shutdown. The value
+ * RT_INDEFINITE_WAIT disables automatic
+ * idle thread shutdown.
+ * @param cThreadsPushBackThreshold At which worker thread count the push
+ * back should kick in.
+ * @param cMsMaxPushBack The max number of milliseconds to push
+ * back a submitter. UINT32_MAX is an
+ * alias for the highest allowed push back.
+ * @param pszName The pool name. Keep it short as it is
+ * used for naming worker threads.
+ * @param phPool Where to return the pool handle.
+ */
+RTDECL(int) RTReqPoolCreate(uint32_t cMaxThreads, RTMSINTERVAL cMsMinIdle,
+ uint32_t cThreadsPushBackThreshold, uint32_t cMsMaxPushBack,
+ const char *pszName, PRTREQPOOL phPool);
+
+/**
+ * Retains a reference to a request thread pool.
+ *
+ * @returns The new reference count, UINT32_MAX on invalid handle (asserted).
+ * @param hPool The request thread pool handle.
+ */
+RTDECL(uint32_t) RTReqPoolRetain(RTREQPOOL hPool);
+
+/**
+ * Releases a reference to the request thread pool.
+ *
+ * When the reference count reaches zero, the request will be pooled for reuse.
+ *
+ * @returns The new reference count, UINT32_MAX on invalid handle (asserted).
+ * @param hPool The request thread pool handle.
+ */
+RTDECL(uint32_t) RTReqPoolRelease(RTREQPOOL hPool);
+
+/**
+ * Request thread pool configuration variable.
+ */
+typedef enum RTREQPOOLCFGVAR
+{
+ /** Invalid zero value. */
+ RTREQPOOLCFGVAR_INVALID = 0,
+ /** The desired RTTHREADTYPE of the worker threads. */
+ RTREQPOOLCFGVAR_THREAD_TYPE,
+ /** The RTTHREADFLAGS mask for the worker threads (not waitable). */
+ RTREQPOOLCFGVAR_THREAD_FLAGS,
+ /** The minimum number of threads to keep handy once spawned. */
+ RTREQPOOLCFGVAR_MIN_THREADS,
+ /** The maximum number of thread to start. */
+ RTREQPOOLCFGVAR_MAX_THREADS,
+ /** The minimum number of milliseconds a worker thread needs to be idle
+ * before we consider shutting it down. The other shutdown criteria
+ * being set by RTREQPOOLCFGVAR_MIN_THREADS. The value
+ * RT_INDEFINITE_WAIT can be used to disable shutting down idle threads. */
+ RTREQPOOLCFGVAR_MS_MIN_IDLE,
+ /** The sleep period, in milliseoncds, to employ when idling. The value
+ * RT_INDEFINITE_WAIT can be used to disable shutting down idle threads. */
+ RTREQPOOLCFGVAR_MS_IDLE_SLEEP,
+ /** The number of threads at which to start pushing back. The value
+ * UINT64_MAX is an alias for the current upper thread count limit, i.e.
+ * disabling push back. The value 0 (zero) is an alias for the current
+ * lower thread count, a good value to start pushing back at. The value
+ * must otherwise be within */
+ RTREQPOOLCFGVAR_PUSH_BACK_THRESHOLD,
+ /** The minimum push back time in milliseconds. */
+ RTREQPOOLCFGVAR_PUSH_BACK_MIN_MS,
+ /** The maximum push back time in milliseconds. */
+ RTREQPOOLCFGVAR_PUSH_BACK_MAX_MS,
+ /** The maximum number of free requests to keep handy for recycling. */
+ RTREQPOOLCFGVAR_MAX_FREE_REQUESTS,
+ /** The end of the range of valid config variables. */
+ RTREQPOOLCFGVAR_END,
+ /** Blow the type up to 32-bits. */
+ RTREQPOOLCFGVAR_32BIT_HACK = 0x7fffffff
+} RTREQPOOLCFGVAR;
+
+
+/**
+ * Sets a config variable for a request thread pool.
+ *
+ * @returns IPRT status code.
+ * @param hPool The pool handle.
+ * @param enmVar The variable to set.
+ * @param uValue The new value.
+ */
+RTDECL(int) RTReqPoolSetCfgVar(RTREQPOOL hPool, RTREQPOOLCFGVAR enmVar, uint64_t uValue);
+
+/**
+ * Gets a config variable for a request thread pool.
+ *
+ * @returns The value, UINT64_MAX on invalid parameters.
+ * @param hPool The pool handle.
+ * @param enmVar The variable to query.
+ */
+RTDECL(uint64_t) RTReqPoolGetCfgVar(RTREQPOOL hPool, RTREQPOOLCFGVAR enmVar);
+
+/**
+ * Request thread pool statistics value names.
+ */
+typedef enum RTREQPOOLSTAT
+{
+ /** The invalid zero value, as per tradition. */
+ RTREQPOOLSTAT_INVALID = 0,
+ /** The current number of worker threads. */
+ RTREQPOOLSTAT_THREADS,
+ /** The number of threads that have been created. */
+ RTREQPOOLSTAT_THREADS_CREATED,
+ /** The total number of requests that have been processed. */
+ RTREQPOOLSTAT_REQUESTS_PROCESSED,
+ /** The total number of requests that have been submitted. */
+ RTREQPOOLSTAT_REQUESTS_SUBMITTED,
+ /** The total number of requests that have been cancelled. */
+ RTREQPOOLSTAT_REQUESTS_CANCELLED,
+ /** the current number of pending (waiting) requests. */
+ RTREQPOOLSTAT_REQUESTS_PENDING,
+ /** The current number of active (executing) requests. */
+ RTREQPOOLSTAT_REQUESTS_ACTIVE,
+ /** The current number of free (recycled) requests. */
+ RTREQPOOLSTAT_REQUESTS_FREE,
+ /** Total time the requests took to process. */
+ RTREQPOOLSTAT_NS_TOTAL_REQ_PROCESSING,
+ /** Total time the requests had to wait in the queue before being
+ * scheduled. */
+ RTREQPOOLSTAT_NS_TOTAL_REQ_QUEUED,
+ /** Average time the requests took to process. */
+ RTREQPOOLSTAT_NS_AVERAGE_REQ_PROCESSING,
+ /** Average time the requests had to wait in the queue before being
+ * scheduled. */
+ RTREQPOOLSTAT_NS_AVERAGE_REQ_QUEUED,
+ /** The end of the valid statistics value names. */
+ RTREQPOOLSTAT_END,
+ /** Blow the type up to 32-bit. */
+ RTREQPOOLSTAT_32BIT_HACK = 0x7fffffff
+} RTREQPOOLSTAT;
+
+/**
+ * Reads a statistics value from the request thread pool.
+ *
+ * @returns The value, UINT64_MAX if an invalid parameter was given.
+ * @param hPool The request thread pool handle.
+ * @param enmStat The statistics value to get.
+ */
+RTDECL(uint64_t) RTReqPoolGetStat(RTREQPOOL hPool, RTREQPOOLSTAT enmStat);
+
+/**
+ * Allocates a request packet.
+ *
+ * This is mostly for internal use, please use the convenience methods.
+ *
+ * @returns IPRT status code.
+ *
+ * @param hPool The request thread pool handle.
+ * @param enmType Package type.
+ * @param phReq Where to store the handle to the new request.
+ */
+RTDECL(int) RTReqPoolAlloc(RTREQPOOL hPool, RTREQTYPE enmType, PRTREQ *phReq);
+
+/**
+ * Calls a function on a worker thread.
+ *
+ * @returns IPRT status code.
+ * @param hPool The request thread pool handle.
+ * @param cMillies The number of milliseconds to wait for the request
+ * to be processed.
+ * @param phReq Where to store the pointer to the request. Optional
+ * when RTREQFLAGS_NO_WAIT is used.
+ * This variable will be set to NIL or a valid request
+ * handle no matter what happens.
+ * @param fFlags A combination of RTREQFLAGS values.
+ * @param pfnFunction The function to be called. Must be declared by a
+ * DECL macro because of calling conventions.
+ * @param cArgs The number of arguments in the ellipsis.
+ * @param ... Arguments.
+ *
+ * @remarks The function better avoid taking uint64_t and structs as part of the
+ * arguments (use pointers to these instead). In general anything
+ * that's larger than an uintptr_t is problematic.
+ */
+RTDECL(int) RTReqPoolCallEx(RTREQPOOL hPool, RTMSINTERVAL cMillies, PRTREQ *phReq, uint32_t fFlags, PFNRT pfnFunction, unsigned cArgs, ...);
+
+
+/**
+ * Calls a function on a worker thread.
+ *
+ * @returns IPRT status code.
+ * @param hPool The request thread pool handle.
+ * @param cMillies The number of milliseconds to wait for the request
+ * to be processed.
+ * @param phReq Where to store the pointer to the request. Optional
+ * when RTREQFLAGS_NO_WAIT is used.
+ * This variable will be set to NIL or a valid request
+ * handle no matter what happens.
+ * @param fFlags A combination of RTREQFLAGS values.
+ * @param pfnFunction The function to be called. Must be declared by a
+ * DECL macro because of calling conventions.
+ * @param cArgs The number of arguments in the variable argument
+ * list.
+ * @param va Arguments.
+ * @remarks See remarks on RTReqPoolCallEx.
+ */
+RTDECL(int) RTReqPoolCallExV(RTREQPOOL hPool, RTMSINTERVAL cMillies, PRTREQ *phReq, uint32_t fFlags, PFNRT pfnFunction, unsigned cArgs, va_list va);
+
+/**
+ * Calls a function on a worker thread, wait for it to return.
+ *
+ * @returns IPRT status code returned by @a pfnFunction or request pool error.
+ * @param hPool The request thread pool handle.
+ * @param pfnFunction The function to be called. Must be declared by a
+ * DECL macro because of calling conventions. The
+ * function must return an int value compatible with
+ * the IPRT status code convention.
+ * @param cArgs The number of arguments in the elipsis.
+ * @param ... Arguments.
+ * @remarks See remarks on RTReqPoolCallEx.
+ */
+RTDECL(int) RTReqPoolCallWait(RTREQPOOL hPool, PFNRT pfnFunction, unsigned cArgs, ...);
+
+/**
+ * Calls a function on a worker thread, don't wait for it to return.
+ *
+ * @returns IPRT status code.
+ * @param hPool The request thread pool handle.
+ * @param pfnFunction The function to be called. Must be declared by a
+ * DECL macro because of calling conventions. The
+ * function should return an int value compatible with
+ * the IPRT status code convention, thought it's not
+ * all that important as it's thrown away.
+ * @param cArgs The number of arguments in the elipsis.
+ * @param ... Arguments.
+ * @remarks See remarks on RTReqPoolCallEx.
+ */
+RTDECL(int) RTReqPoolCallNoWait(RTREQPOOL hPool, PFNRT pfnFunction, unsigned cArgs, ...);
+
+/**
+ * Calls a void function on a worker thread.
+ *
+ * @returns IPRT status code.
+ * @param hPool The request thread pool handle.
+ * @param pfnFunction The function to be called. Must be declared by a
+ * DECL macro because of calling conventions. The
+ * function is taken to return void.
+ * @param cArgs The number of arguments in the elipsis.
+ * @param ... Arguments.
+ * @remarks See remarks on RTReqPoolCallEx.
+ */
+RTDECL(int) RTReqPoolCallVoidWait(RTREQPOOL hPool, PFNRT pfnFunction, unsigned cArgs, ...);
+
+/**
+ * Call a void function on a worker thread, don't wait for it to return.
+ *
+ * @returns IPRT status code.
+ * @param hPool The request thread pool handle.
+ * @param pfnFunction The function to be called. Must be declared by a
+ * DECL macro because of calling conventions. The
+ * function is taken to return void.
+ * @param cArgs The number of arguments in the elipsis.
+ * @param ... Arguments.
+ * @remarks See remarks on RTReqPoolCallEx.
+ */
+RTDECL(int) RTReqPoolCallVoidNoWait(RTREQPOOL hPool, PFNRT pfnFunction, unsigned cArgs, ...);
+
+
+/**
+ * Retains a reference to a request.
+ *
+ * @returns The new reference count, UINT32_MAX on invalid handle (asserted).
+ * @param hReq The request handle.
+ */
+RTDECL(uint32_t) RTReqRetain(PRTREQ hReq);
+
+/**
+ * Releases a reference to the request.
+ *
+ * When the reference count reaches zero, the request will be pooled for reuse.
+ *
+ * @returns The new reference count, UINT32_MAX on invalid handle (asserted).
+ * @param hReq Package to release.
+ */
+RTDECL(uint32_t) RTReqRelease(PRTREQ hReq);
+
+/**
+ * Queues a request.
+ *
+ * The request must be allocated using RTReqQueueAlloc() or RTReqPoolAlloc() and
+ * contain all the required data.
+ *
+ * If it's desired to poll on the completion of the request set cMillies
+ * to 0 and use RTReqWait() to check for completion. In the other case
+ * use RT_INDEFINITE_WAIT.
+ *
+ * @returns IPRT status code.
+ * Will not return VERR_INTERRUPTED.
+ * @returns VERR_TIMEOUT if cMillies was reached without the packet being completed.
+ *
+ * @param pReq The request to queue.
+ * @param cMillies Number of milliseconds to wait for the request to
+ * be completed. Use RT_INDEFINITE_WAIT to only
+ * wait till it's completed.
+ */
+RTDECL(int) RTReqSubmit(PRTREQ pReq, RTMSINTERVAL cMillies);
+
+/**
+ * Cancels a pending request.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_RT_REQUEST_STATE if the request is not cancellable.
+ *
+ * @param hReq The request to cancel.
+ */
+RTDECL(int) RTReqCancel(PRTREQ hReq);
+
+/**
+ * Waits for a request to be completed.
+ *
+ * @returns IPRT status code.
+ * Will not return VERR_INTERRUPTED.
+ * @returns VERR_TIMEOUT if cMillies was reached without the packet being completed.
+ *
+ * @param pReq The request to wait for.
+ * @param cMillies Number of milliseconds to wait.
+ * Use RT_INDEFINITE_WAIT to only wait till it's completed.
+ */
+RTDECL(int) RTReqWait(PRTREQ pReq, RTMSINTERVAL cMillies);
+
+/**
+ * Gets the status of the request.
+ *
+ * @returns IPRT status code.
+ *
+ * @param pReq The request to get the status for.
+ */
+RTDECL(int) RTReqGetStatus(PRTREQ pReq);
+
+#endif /* IN_RING3 */
+
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_req_h */
+
diff --git a/include/iprt/runtime-loader.h b/include/iprt/runtime-loader.h
new file mode 100644
index 00000000..3892ffcf
--- /dev/null
+++ b/include/iprt/runtime-loader.h
@@ -0,0 +1,189 @@
+/** @file
+ * IPRT - Runtime Loader Generation.
+ */
+
+/*
+ * Copyright (C) 2008-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#include <iprt/types.h>
+#ifdef RT_RUNTIME_LOADER_GENERATE_BODY_STUBS
+# include <iprt/ldr.h>
+# include <iprt/log.h>
+# include <iprt/once.h>
+#endif
+
+/** @defgroup grp_rt_runtime_loader Runtime Loader Generation
+ * @ingroup grp_rt
+ *
+ * How to use this loader generator
+ *
+ * This loader generator can be used to generate stub code for loading a shared
+ * library and its functions at runtime, or for generating a header file with
+ * the declaration of the loader function and optionally declarations for the
+ * functions loaded. It should be included in a header file or a C source
+ * file, after defining certain macros which it makes use of.
+ *
+ * To generate the C source code for function proxy stubs and the library
+ * loader function, you should define the following macros in your source file
+ * before including this header:
+ *
+ * RT_RUNTIME_LOADER_LIB_NAME - the file name of the library to load
+ * RT_RUNTIME_LOADER_FUNCTION - the name of the loader function
+ * RT_RUNTIME_LOADER_INSERT_SYMBOLS - a macro containing the names of the
+ * functions to be loaded, defined in the
+ * following pattern:
+ * @code
+ * #define RT_RUNTIME_LOADER_INSERT_SYMBOLS \
+ * RT_PROXY_STUB(func_name, ret_type, (long_param_list), (short_param_list)) \
+ * RT_PROXY_STUB(func_name2, ret_type2, (long_param_list2), (short_param_list2)) \
+ * ...
+ * @endcode
+ *
+ * where long_param_list is a parameter list for declaring the function of the
+ * form (type1 arg1, type2 arg2, ...) and short_param_list for calling it, of
+ * the form (arg1, arg2, ...).
+ *
+ * To generate the header file, you should define RT_RUNTIME_LOADER_FUNCTION
+ * and if you wish to generate declarations for the functions you should
+ * additionally define RT_RUNTIME_LOADER_INSERT_SYMBOLS as above and
+ * RT_RUNTIME_LOADER_GENERATE_DECLS (without a value) before including this
+ * file.
+ *
+ * @{
+ */
+/** @todo this is far too complicated. A script for generating the files would
+ * probably be preferable.
+ *
+ * bird> An alternative is to generate assembly jump wrappers, this only
+ * requires the symbol names and prefix. I've done this ages ago when we forked
+ * the EMX/GCC toolchain on OS/2... It's a wee bit more annoying in x86 PIC/PIE
+ * mode, but nothing that cannot be dealt with.
+ */
+/** @todo r=bird: The use of RTR3DECL here is an unresolved issue. */
+/** @todo r=bird: The lack of RT_C_DECLS_BEGIN/END is an unresolved issue. Here
+ * we'll get into trouble if we use the same symbol names as the
+ * original! */
+/** @todo r=bird: The prefix usage here is very confused: RT_RUNTIME_LOADER_XXX,
+ * RT_PROXY_STUB, etc. */
+
+#ifdef RT_RUNTIME_LOADER_GENERATE_BODY_STUBS
+
+/* The following are the symbols which we need from the library. */
+# define RT_PROXY_STUB(function, rettype, signature, shortsig) \
+ void (*function ## _fn)(void); \
+ RTR3DECL(rettype) function signature \
+ { return ( (rettype (*) signature) function ## _fn ) shortsig; }
+
+RT_RUNTIME_LOADER_INSERT_SYMBOLS
+
+# undef RT_PROXY_STUB
+
+/* Now comes a table of functions to be loaded from the library. */
+typedef struct
+{
+ const char *pszName;
+ void (**ppfn)(void);
+} RTLDRSHAREDFUNC;
+
+# define RT_PROXY_STUB(s, dummy1, dummy2, dummy3 ) { #s , & s ## _fn } ,
+static RTLDRSHAREDFUNC g_aSharedFuncs[] =
+{
+ RT_RUNTIME_LOADER_INSERT_SYMBOLS
+ { NULL, NULL }
+};
+# undef RT_PROXY_STUB
+
+/**
+ * The function which does the actual work for RT_RUNTIME_LOADER_FUNCTION,
+ * serialised for thread safety.
+ */
+static DECLCALLBACK(int) rtldrLoadOnce(void *)
+{
+ RTLDRMOD hLib;
+ int rc;
+
+ LogFlowFunc(("\n"));
+ rc = RTLdrLoadEx(RT_RUNTIME_LOADER_LIB_NAME, &hLib, RTLDRLOAD_FLAGS_LOCAL | RTLDRLOAD_FLAGS_NO_UNLOAD, NULL);
+ for (unsigned i = 0; RT_SUCCESS(rc) && g_aSharedFuncs[i].pszName != NULL; ++i)
+ rc = RTLdrGetSymbol(hLib, g_aSharedFuncs[i].pszName, (void **)g_aSharedFuncs[i].ppfn);
+ LogFlowFunc(("rc = %Rrc\n", rc));
+
+ return rc;
+}
+
+/**
+ * Load the shared library RT_RUNTIME_LOADER_LIB_NAME and resolve the symbols
+ * pointed to by RT_RUNTIME_LOADER_INSERT_SYMBOLS.
+ *
+ * May safely be called from multiple threads and will not return until the
+ * library is loaded or has failed to load.
+ *
+ * @returns IPRT status code.
+ */
+RTR3DECL(int) RT_RUNTIME_LOADER_FUNCTION(void)
+{
+ static RTONCE s_Once = RTONCE_INITIALIZER;
+ int rc;
+
+ LogFlowFunc(("\n"));
+ rc = RTOnce(&s_Once, rtldrLoadOnce, NULL);
+ LogFlowFunc(("rc = %Rrc\n", rc));
+
+ return rc;
+}
+
+#elif defined(RT_RUNTIME_LOADER_GENERATE_HEADER)
+# ifdef RT_RUNTIME_LOADER_GENERATE_DECLS
+/* Declarations of the functions that we need from
+ * RT_RUNTIME_LOADER_LIB_NAME */
+# define RT_PROXY_STUB(function, rettype, signature, shortsig) \
+ RTR3DECL(rettype) function signature ;
+
+RT_RUNTIME_LOADER_INSERT_SYMBOLS
+
+# undef RT_PROXY_STUB
+# endif /* RT_RUNTIME_LOADER_GENERATE_DECLS */
+
+/**
+ * Try to dynamically load the library. This function should be called before
+ * attempting to use any of the library functions. It is safe to call this
+ * function multiple times.
+ *
+ * @returns iprt status code
+ */
+RTR3DECL(int) RT_RUNTIME_LOADER_FUNCTION(void);
+
+#else
+# error "One of RT_RUNTIME_LOADER_GENERATE_HEADER or RT_RUNTIME_LOADER_GENERATE_BODY_STUBS must be defined when including this file"
+#endif
+
+/** @} */
+
diff --git a/include/iprt/runtime.h b/include/iprt/runtime.h
new file mode 100644
index 00000000..5d2ddc5d
--- /dev/null
+++ b/include/iprt/runtime.h
@@ -0,0 +1,99 @@
+/** @file
+ * IPRT - Include Everything.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_runtime_h
+#define IPRT_INCLUDED_runtime_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+#include <iprt/param.h>
+#include <iprt/initterm.h>
+
+#if !defined(IN_RC) && !defined(IN_RING0_AGNOSTIC)
+# include <iprt/alloca.h>
+#endif
+#include <iprt/asm.h>
+#include <iprt/assert.h>
+#include <iprt/avl.h>
+#include <iprt/crc.h>
+#include <iprt/critsect.h>
+#include <iprt/dir.h>
+#include <iprt/err.h>
+#ifndef IN_RC
+# include <iprt/file.h>
+# include <iprt/fs.h>
+#endif
+#include <iprt/getopt.h>
+#include <iprt/ldr.h>
+#include <iprt/log.h>
+#include <iprt/md5.h>
+#ifndef IN_RC
+# include <iprt/mem.h>
+# include <iprt/mp.h>
+#endif
+#include <iprt/path.h>
+#include <iprt/semaphore.h>
+#include <iprt/spinlock.h>
+#include <iprt/stdarg.h>
+#include <iprt/string.h>
+#include <iprt/system.h>
+#include <iprt/table.h>
+#ifndef IN_RC
+# include <iprt/thread.h>
+#endif
+#include <iprt/time.h>
+#include <iprt/timer.h>
+#include <iprt/uni.h>
+#include <iprt/uuid.h>
+#include <iprt/zip.h>
+
+#ifdef IN_RING3
+# include <iprt/stream.h>
+# include <iprt/tcp.h>
+# include <iprt/ctype.h>
+# include <iprt/alloca.h> /** @todo iprt/alloca.h should be made available in R0 and GC too! */
+# include <iprt/process.h> /** @todo iprt/process.h should be made available in R0 too (partly). */
+#endif
+
+#ifdef IN_RING0
+# include <iprt/memobj.h>
+#endif
+
+
+#endif /* !IPRT_INCLUDED_runtime_h */
+
diff --git a/include/iprt/s3.h b/include/iprt/s3.h
new file mode 100644
index 00000000..93c33454
--- /dev/null
+++ b/include/iprt/s3.h
@@ -0,0 +1,283 @@
+/* $Id: s3.h $ */
+/** @file
+ * IPRT - Simple Storage Service (S3) Communication API.
+ */
+
+/*
+ * Copyright (C) 2009-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_s3_h
+#define IPRT_INCLUDED_s3_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_s3 RTS3 - Simple Storage Service (S3) Communication API
+ * @ingroup grp_rt
+ * @{
+ */
+
+/** @todo the following three definitions may move the iprt/types.h later. */
+/** RTS3 interface handle. */
+typedef R3PTRTYPE(struct RTS3INTERNAL *) RTS3;
+/** Pointer to a RTS3 interface handle. */
+typedef RTS3 *PRTS3;
+/** Nil RTS3 interface handle. */
+#define NIL_RTS3 ((RTS3)0)
+
+
+/**
+ * S3 progress callback.
+ *
+ * @returns Reserved, must be 0.
+ *
+ * @param uPercent The process completion percentage.
+ * @param pvUser The user parameter given to RTS3SetProgressCallback.
+ */
+typedef DECLCALLBACKTYPE(int, FNRTS3PROGRESS,(unsigned uPercent, void *pvUser));
+/** Pointer to a S3 progress callback. */
+typedef FNRTS3PROGRESS *PFNRTS3PROGRESS;
+
+
+/** Pointer to an S3 bucket entry. */
+typedef struct RTS3BUCKETENTRY *PRTS3BUCKETENTRY;
+/** Pointer to a const S3 bucket entry. */
+typedef struct RTS3BUCKETENTRY const *PCRTS3BUCKETENTRY;
+/**
+ * RTS3 bucket entry.
+ *
+ * Represent a bucket of the S3 storage server. Bucket entries are chained as a
+ * doubly linked list using the pPrev & pNext member.
+ *
+ * @todo Consider making the entire list const unless there are plans for
+ * more APIs using this structure which requires the caller to create
+ * or modify it.
+ */
+typedef struct RTS3BUCKETENTRY
+{
+ /** The previous element. */
+ PRTS3BUCKETENTRY pPrev;
+ /** The next element. */
+ PRTS3BUCKETENTRY pNext;
+
+ /** The name of the bucket. */
+ char const *pszName;
+ /** The creation date of the bucket as string. */
+ char const *pszCreationDate;
+} RTS3BUCKETENTRY;
+
+
+/** Pointer to an S3 key entry. */
+typedef struct RTS3KEYENTRY *PRTS3KEYENTRY;
+/** Pointer to a const S3 key entry. */
+typedef struct RTS3KEYENTRY const *PCRTS3KEYENTRY;
+/**
+ * RTS3 key entry.
+ *
+ * Represent a key of the S3 storage server. Key entries are chained as a doubly
+ * linked list using the pPrev & pNext member.
+ *
+ * @todo Consider making the entire list const unless there are plans for
+ * more APIs using this structure which requires the caller to create
+ * or modify it.
+ */
+typedef struct RTS3KEYENTRY
+{
+ /** The previous element. */
+ PRTS3KEYENTRY pPrev;
+ /** The next element. */
+ PRTS3KEYENTRY pNext;
+
+ /** The name of the key. */
+ char const *pszName;
+ /** The date this key was last modified as string. */
+ char const *pszLastModified;
+ /** The size of the file behind this key in bytes. */
+ uint64_t cbFile;
+} RTS3KEYENTRY;
+
+
+/**
+ * Creates a RTS3 interface handle.
+ *
+ * @returns iprt status code.
+ *
+ * @param phS3 Where to store the RTS3 handle.
+ * @param pszAccessKey The access key for the S3 storage server.
+ * @param pszSecretKey The secret access key for the S3 storage server.
+ * @param pszBaseUrl The base URL of the S3 storage server.
+ * @param pszUserAgent An optional user agent string used in the HTTP
+ * communication.
+ */
+RTR3DECL(int) RTS3Create(PRTS3 phS3, const char *pszAccessKey, const char *pszSecretKey, const char *pszBaseUrl, const char *pszUserAgent);
+
+/**
+ * Destroys a RTS3 interface handle.
+ *
+ * @returns iprt status code.
+ *
+ * @param hS3 Handle to the RTS3 interface.
+ */
+RTR3DECL(void) RTS3Destroy(RTS3 hS3);
+
+/**
+ * Sets an optional progress callback.
+ *
+ * This callback function will be called when the completion percentage of an S3
+ * operation changes.
+ *
+ * @returns iprt status code.
+ *
+ * @param hS3 Handle to the RTS3 interface.
+ * @param pfnProgressCB The pointer to the progress function.
+ * @param pvUser The pvUser arg of FNRTS3PROGRESS.
+ */
+RTR3DECL(void) RTS3SetProgressCallback(RTS3 hS3, PFNRTS3PROGRESS pfnProgressCB, void *pvUser);
+
+/**
+ * Gets a list of all available buckets on the S3 storage server.
+ *
+ * You have to delete ppBuckets after usage with RTS3BucketsDestroy.
+ *
+ * @returns iprt status code.
+ *
+ * @param hS3 Handle to the RTS3 interface.
+ * @param ppBuckets Where to store the pointer to the head of the
+ * returned bucket list. Consider the entire list
+ * read-only.
+ */
+RTR3DECL(int) RTS3GetBuckets(RTS3 hS3, PCRTS3BUCKETENTRY *ppBuckets);
+
+/**
+ * Destroys the bucket list returned by RTS3GetBuckets.
+ *
+ * @returns iprt status code.
+ *
+ * @param pBuckets Pointer to the first bucket entry.
+ */
+RTR3DECL(int) RTS3BucketsDestroy(PCRTS3BUCKETENTRY pBuckets);
+
+/**
+ * Creates a new bucket on the S3 storage server.
+ *
+ * This name have to be unique over all accounts on the S3 storage server.
+ *
+ * @returns iprt status code.
+ *
+ * @param hS3 Handle to the RTS3 interface.
+ * @param pszBucketName Name of the new bucket.
+ */
+RTR3DECL(int) RTS3CreateBucket(RTS3 hS3, const char *pszBucketName);
+
+/**
+ * Deletes a bucket on the S3 storage server.
+ *
+ * The bucket must be empty.
+ *
+ * @returns iprt status code.
+ *
+ * @param hS3 Handle to the RTS3 interface.
+ * @param pszBucketName Name of the bucket to delete.
+ */
+RTR3DECL(int) RTS3DeleteBucket(RTS3 hS3, const char *pszBucketName);
+
+/**
+ * Gets a list of all available keys in a bucket on the S3 storage server.
+ *
+ * You have to delete ppKeys after usage with RTS3KeysDestroy.
+ *
+ * @returns iprt status code.
+ *
+ * @param hS3 Handle to the RTS3 interface.
+ * @param pszBucketName Name of the bucket to delete.
+ * @param ppKeys Where to store the pointer to the head of the
+ * returned key list. Consider the entire list
+ * read-only.
+ */
+RTR3DECL(int) RTS3GetBucketKeys(RTS3 hS3, const char *pszBucketName, PCRTS3KEYENTRY *ppKeys);
+
+/**
+ * Delete the key list returned by RTS3GetBucketKeys.
+ *
+ * @returns iprt status code.
+ *
+ * @param pKeys Pointer to the first key entry.
+ */
+RTR3DECL(int) RTS3KeysDestroy(PCRTS3KEYENTRY pKeys);
+
+/**
+ * Deletes a key in a bucket on the S3 storage server.
+ *
+ * @returns iprt status code.
+ *
+ * @param hS3 Handle to the RTS3 interface.
+ * @param pszBucketName Name of the bucket contains pszKeyName.
+ * @param pszKeyName Name of the key to delete.
+ */
+RTR3DECL(int) RTS3DeleteKey(RTS3 hS3, const char *pszBucketName, const char *pszKeyName);
+
+/**
+ * Downloads a key from a bucket into a file.
+ *
+ * The file must not exists.
+ *
+ * @returns iprt status code.
+ *
+ * @param hS3 Handle to the RTS3 interface.
+ * @param pszBucketName Name of the bucket that contains pszKeyName.
+ * @param pszKeyName Name of the key to download.
+ * @param pszFilename Name of the file to store the downloaded key as.
+ */
+RTR3DECL(int) RTS3GetKey(RTS3 hS3, const char *pszBucketName, const char *pszKeyName, const char *pszFilename);
+
+/**
+ * Uploads the content of a file into a key in the specified bucked.
+ *
+ * @returns iprt status code.
+ *
+ * @param hS3 Handle to the RTS3 interface.
+ * @param pszBucketName Name of the bucket where the new key should be
+ * created.
+ * @param pszKeyName Name of the new key.
+ * @param pszFilename Name of the file to upload the content of.
+ */
+RTR3DECL(int) RTS3PutKey(RTS3 hS3, const char *pszBucketName, const char *pszKeyName, const char *pszFilename);
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_s3_h */
+
diff --git a/include/iprt/sanitized/intrin.h b/include/iprt/sanitized/intrin.h
new file mode 100644
index 00000000..39b5ad32
--- /dev/null
+++ b/include/iprt/sanitized/intrin.h
@@ -0,0 +1,62 @@
+/** @file
+ * Safe way to include intrin.h from VC++.
+ */
+
+/*
+ * Copyright (C) 2020-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_sanitized_intrin_h
+#define IPRT_INCLUDED_sanitized_intrin_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#ifdef _MSC_VER
+# pragma warning(push)
+# pragma warning(disable:4668) /* Several incorrect __cplusplus uses. */
+# pragma warning(disable:4255) /* Incorrect __slwpcb prototype. */
+#endif
+
+/* This is a hack to avoid dragging in malloc.h from UCRT. */
+#if (defined(IPRT_NO_CRT) || defined(RT_OS_AGNOSTIC)) && !defined(_INC_MALLOC)
+# define _INC_MALLOC 1
+# include <intrin.h>
+# undef _INC_MALLOC
+#else
+# include <intrin.h>
+#endif
+
+#ifdef _MSC_VER
+# pragma warning(pop)
+#endif
+
+#endif /* !IPRT_INCLUDED_sanitized_intrin_h */
+
diff --git a/include/iprt/sanitized/iterator b/include/iprt/sanitized/iterator
new file mode 100644
index 00000000..b3c78e0c
--- /dev/null
+++ b/include/iprt/sanitized/iterator
@@ -0,0 +1,60 @@
+/** @file
+ * Safe way to include the 'iterator' header from the C++ library.
+ */
+
+/*
+ * Copyright (C) 2020-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_sanitized_iterator
+#define IPRT_INCLUDED_sanitized_iterator
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#ifdef _MSC_VER
+/*
+ * Unfortunately, the 'iterator' file of VCC141 has trouble with C4091 in -Wall mode (via ios):
+ * xlocnum(1616): warning C4774: 'sprintf_s' : format string expected in argument 3 is not a string literal
+ */
+# pragma warning(push)
+# if _MSC_VER >= 1910 /*RT_MSC_VER_VC141*/
+# pragma warning(disable:4774)
+# endif
+#endif
+
+#include <iterator>
+
+#ifdef _MSC_VER
+# pragma warning(pop)
+#endif
+
+#endif /* !IPRT_INCLUDED_sanitized_iterator */
+
diff --git a/include/iprt/sanitized/sstream b/include/iprt/sanitized/sstream
new file mode 100644
index 00000000..46da7af5
--- /dev/null
+++ b/include/iprt/sanitized/sstream
@@ -0,0 +1,62 @@
+/** @file
+ * Safe way to include the 'sstream' header from the C++ library.
+ */
+
+/*
+ * Copyright (C) 2020-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_sanitized_sstream
+#define IPRT_INCLUDED_sanitized_sstream
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#ifdef _MSC_VER
+/*
+ * Unfortunately, the 'sstream' file of VCC141 has trouble with C4091 in -Wall mode
+ * because it drags in string.h which causes stuff like:
+ * xlocnum(1616): warning C4774: 'sprintf_s' : format sstream expected in argument 3 is not a sstream literal
+ * sstream(530): warning C4774: '_scprintf' : format sstream expected in argument 1 is not a sstream literal
+ */
+# pragma warning(push)
+# if _MSC_VER >= 1910 /*RT_MSC_VER_VC141*/
+# pragma warning(disable:4774)
+# endif
+#endif
+
+#include <sstream>
+
+#ifdef _MSC_VER
+# pragma warning(pop)
+#endif
+
+#endif /* !IPRT_INCLUDED_sanitized_sstream */
+
diff --git a/include/iprt/sanitized/string b/include/iprt/sanitized/string
new file mode 100644
index 00000000..515d2a13
--- /dev/null
+++ b/include/iprt/sanitized/string
@@ -0,0 +1,61 @@
+/** @file
+ * Safe way to include the 'string' header from the C++ library.
+ */
+
+/*
+ * Copyright (C) 2020-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_sanitized_string
+#define IPRT_INCLUDED_sanitized_string
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#ifdef _MSC_VER
+/*
+ * Unfortunately, the 'string' file of VCC141 has trouble with C4091 in -Wall mode:
+ * string(530): warning C4774: '_scprintf' : format string expected in argument 1 is not a string literal
+ * xlocnum(1616): warning C4774: 'sprintf_s' : format string expected in argument 3 is not a string literal
+ */
+# pragma warning(push)
+# if _MSC_VER >= 1910 /*RT_MSC_VER_VC141*/
+# pragma warning(disable:4774)
+# endif
+#endif
+
+#include <string>
+
+#ifdef _MSC_VER
+# pragma warning(pop)
+#endif
+
+#endif /* !IPRT_INCLUDED_sanitized_string */
+
diff --git a/include/iprt/semaphore.h b/include/iprt/semaphore.h
new file mode 100644
index 00000000..6d3e5f6a
--- /dev/null
+++ b/include/iprt/semaphore.h
@@ -0,0 +1,1450 @@
+/** @file
+ * IPRT - Semaphore.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_semaphore_h
+#define IPRT_INCLUDED_semaphore_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#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.
+ *
+ * ring-0/Darwin: This works when interrupts are disabled and thereby
+ * in interrupt context, except it cannot race semaphore destruction as
+ * the allocator does not work under these circumstances.
+ */
+RTDECL(int) RTSemEventSignal(RTSEMEVENT hEventSem);
+
+/**
+ * Whether RTSemEventSignal can be safely called w/o risk of preemption.
+ *
+ * Checks whether the caller can safely signal a single release semaphore
+ * without any risk of getting preempted on locks or similar while doing so.
+ * This also checks whether the context is suitable in general.
+ *
+ * @returns true if safe, false if not.
+ * @remarks Only ring-0.
+ */
+RTR0DECL(bool) RTSemEventIsSignalSafe(void);
+
+/**
+ * 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.
+ *
+ * ring-0/Darwin: This works when interrupts are disabled and thereby
+ * in interrupt context, except it cannot race semaphore destruction as
+ * the allocator does not work under these circumstances.
+ */
+RTDECL(int) RTSemEventMultiSignal(RTSEMEVENTMULTI hEventMultiSem);
+
+/**
+ * Whether RTSemEventMultiSignal can be safely called w/o risk of preemption.
+ *
+ * Checks whether the caller can safely signal a multiple release semaphore
+ * without any risk of getting preempted on locks or similar while doing so.
+ * This also checks whether the context is suitable in general.
+ *
+ * @returns true if safe, false if not.
+ * @remarks Only ring-0.
+ */
+RTR0DECL(bool) RTSemEventMultiIsSignalSafe(void);
+
+/**
+ * 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_INCLUDED_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 the driver verifier enabled.
+ *
+ * @{ */
+
+/**
+ * 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.
+ *
+ * @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_INCLUDED_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 /* !IPRT_INCLUDED_semaphore_h */
+
diff --git a/include/iprt/serialport.h b/include/iprt/serialport.h
new file mode 100644
index 00000000..25f5fbe5
--- /dev/null
+++ b/include/iprt/serialport.h
@@ -0,0 +1,377 @@
+/** @file
+ * IPRT Serial Port API.
+ */
+
+/*
+ * Copyright (C) 2017-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_serialport_h
+#define IPRT_INCLUDED_serialport_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_serial IPRT Serial Port API
+ * @ingroup grp_rt
+ *
+ * The IPRT serial port API provides a platform independent API to control a
+ * serial port of the host. It supports receiving/transmitting data as well as
+ * controlling and monitoring the status lines of a standard serial port.
+ *
+ * The user of the API is currently resposible for serializing calls to it.
+ * The only exception is RTSerialPortEvtPollInterrupt() which can be called on
+ * any thread to interrupt another thread waiting in RTSerialPortEvtPoll().
+ *
+ * @{
+ */
+
+/** Serial Port handle. */
+typedef struct RTSERIALPORTINTERNAL *RTSERIALPORT;
+/** Pointer to a Serial Port handle. */
+typedef RTSERIALPORT *PRTSERIALPORT;
+/** NIL Serial Port handle value. */
+#define NIL_RTSERIALPORT ((RTSERIALPORT)0)
+
+
+/**
+ * Supported parity settings.
+ */
+typedef enum RTSERIALPORTPARITY
+{
+ /** Invalid parity setting. */
+ RTSERIALPORTPARITY_INVALID = 0,
+ /** No parity used. */
+ RTSERIALPORTPARITY_NONE,
+ /** Even parity used. */
+ RTSERIALPORTPARITY_EVEN,
+ /** Odd parity used. */
+ RTSERIALPORTPARITY_ODD,
+ /** Mark parity (parity bit always 1) used. */
+ RTSERIALPORTPARITY_MARK,
+ /** Space parity (parity bit always 0) used. */
+ RTSERIALPORTPARITY_SPACE,
+ /** 32bit hack. */
+ RTSERIALPORTPARITY_32BIT_HACK = 0x7fffffff
+} RTSERIALPORTPARITY;
+
+
+/**
+ * Supported data bit count setting.
+ */
+typedef enum RTSERIALPORTDATABITS
+{
+ /** Invalid bitcount setting. */
+ RTSERIALPORTDATABITS_INVALID = 0,
+ /** 5 data bits. */
+ RTSERIALPORTDATABITS_5BITS,
+ /** 6 data bits. */
+ RTSERIALPORTDATABITS_6BITS,
+ /** 7 data bits. */
+ RTSERIALPORTDATABITS_7BITS,
+ /** 8 data bits. */
+ RTSERIALPORTDATABITS_8BITS,
+ /** 32bit hack. */
+ RTSERIALPORTDATABITS_32BIT_HACK = 0x7fffffff
+} RTSERIALPORTDATABITS;
+
+
+/**
+ * Supported stop bit setting.
+ */
+typedef enum RTSERIALPORTSTOPBITS
+{
+ /** Invalid stop bit setting. */
+ RTSERIALPORTSTOPBITS_INVALID = 0,
+ /** One stop bit is used. */
+ RTSERIALPORTSTOPBITS_ONE,
+ /** 1.5 stop bits are used. */
+ RTSERIALPORTSTOPBITS_ONEPOINTFIVE,
+ /** 2 stop bits are used. */
+ RTSERIALPORTSTOPBITS_TWO,
+ /** 32bit hack. */
+ RTSERIALPORTSTOPBITS_32BIT_HACK = 0x7fffffff
+} RTSERIALPORTSTOPBITS;
+
+
+/**
+ * Serial port config structure.
+ */
+typedef struct RTSERIALPORTCFG
+{
+ /** Baud rate. */
+ uint32_t uBaudRate;
+ /** Used parity. */
+ RTSERIALPORTPARITY enmParity;
+ /** Number of data bits. */
+ RTSERIALPORTDATABITS enmDataBitCount;
+ /** Number of stop bits. */
+ RTSERIALPORTSTOPBITS enmStopBitCount;
+} RTSERIALPORTCFG;
+/** Pointer to a serial port config. */
+typedef RTSERIALPORTCFG *PRTSERIALPORTCFG;
+/** Pointer to a const serial port config. */
+typedef const RTSERIALPORTCFG *PCRTSERIALPORTCFG;
+
+
+/** @name RTSerialPortOpen flags
+ * @{ */
+/** Open the serial port with the receiver enabled to receive data. */
+#define RTSERIALPORT_OPEN_F_READ RT_BIT(0)
+/** Open the serial port with the transmitter enabled to transmit data. */
+#define RTSERIALPORT_OPEN_F_WRITE RT_BIT(1)
+/** Open the serial port with status line monitoring enabled to get notified about status line changes. */
+#define RTSERIALPORT_OPEN_F_SUPPORT_STATUS_LINE_MONITORING RT_BIT(2)
+/** Open the serial port with BREAK condition detection enabled (Requires extra work on some hosts). */
+#define RTSERIALPORT_OPEN_F_DETECT_BREAK_CONDITION RT_BIT(3)
+/** Open the serial port with loopback mode enabled. */
+#define RTSERIALPORT_OPEN_F_ENABLE_LOOPBACK RT_BIT(4)
+/** Bitmask of valid flags. */
+#define RTSERIALPORT_OPEN_F_VALID_MASK UINT32_C(0x0000001f)
+/** @} */
+
+
+/** @name RTSerialPortChgModemLines flags
+ * @{ */
+/** Change the RTS (Ready To Send) line signal. */
+#define RTSERIALPORT_CHG_STS_LINES_F_RTS RT_BIT(0)
+/** Change the DTR (Data Terminal Ready) line signal. */
+#define RTSERIALPORT_CHG_STS_LINES_F_DTR RT_BIT(1)
+/** Bitmask of valid flags. */
+#define RTSERIALPORT_CHG_STS_LINES_F_VALID_MASK UINT32_C(0x00000003)
+/** @} */
+
+
+/** @name RTSerialPortQueryStatusLines flags
+ * @{ */
+/** The DCD (Data Carrier Detect) signal is active. */
+#define RTSERIALPORT_STS_LINE_DCD RT_BIT(0)
+/** The RI (Ring Indicator) signal is active. */
+#define RTSERIALPORT_STS_LINE_RI RT_BIT(1)
+/** The DSR (Data Set Ready) signal is active. */
+#define RTSERIALPORT_STS_LINE_DSR RT_BIT(2)
+/** The CTS (Clear To Send) signal is active. */
+#define RTSERIALPORT_STS_LINE_CTS RT_BIT(3)
+/** @} */
+
+
+/** @name RTSerialPortEvtPoll flags
+ * @{ */
+/** Data was received and can be read. */
+#define RTSERIALPORT_EVT_F_DATA_RX RT_BIT(0)
+/** All data was transmitted and there is room again in the transmit buffer. */
+#define RTSERIALPORT_EVT_F_DATA_TX RT_BIT(1)
+/** A BREAK condition was detected on the communication channel.
+ * Only available when BREAK condition detection was enabled when opening the serial port .*/
+#define RTSERIALPORT_EVT_F_BREAK_DETECTED RT_BIT(2)
+/** One of the monitored status lines changed, check with RTSerialPortQueryStatusLines().
+ * Only available if status line monitoring was enabled when opening the serial port. */
+#define RTSERIALPORT_EVT_F_STATUS_LINE_CHANGED RT_BIT(3)
+/** Status line monitor failed with an error and status line monitoring is disabled,
+ * this cannot be given in the event mask but will be set if status line
+ * monitoring is enabled and the monitor failed. */
+#define RTSERIALPORT_EVT_F_STATUS_LINE_MONITOR_FAILED RT_BIT(4)
+/** Bitmask of valid flags. */
+#define RTSERIALPORT_EVT_F_VALID_MASK UINT32_C(0x0000001f)
+/** @} */
+
+
+/**
+ * Opens a serial port with the specified flags.
+ *
+ * @returns IPRT status code.
+ * @param phSerialPort Where to store the IPRT serial port handle on success.
+ * @param pszPortAddress The address of the serial port (host dependent).
+ * @param fFlags Flags to open the serial port with, see RTSERIALPORT_OPEN_F_*.
+ */
+RTDECL(int) RTSerialPortOpen(PRTSERIALPORT phSerialPort, const char *pszPortAddress, uint32_t fFlags);
+
+
+/**
+ * Closes the given serial port handle.
+ *
+ * @returns IPRT status code.
+ * @param hSerialPort The IPRT serial port handle.
+ */
+RTDECL(int) RTSerialPortClose(RTSERIALPORT hSerialPort);
+
+
+/**
+ * Gets the native handle for an IPRT serial port handle.
+ *
+ * @returns The native handle. -1 on failure.
+ * @param hSerialPort The IPRT serial port handle.
+ */
+RTDECL(RTHCINTPTR) RTSerialPortToNative(RTSERIALPORT hSerialPort);
+
+
+/**
+ * Tries to read the given number of bytes from the serial port, blocking version.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_SERIALPORT_BREAK_DETECTED if a break was detected before the requested number of bytes was received.
+ * @param hSerialPort The IPRT serial port handle.
+ * @param pvBuf Where to store the read data.
+ * @param cbToRead How much to read from the serial port.
+ * @param pcbRead Where to store the number of bytes received until an error condition occurred, optional.
+ */
+RTDECL(int) RTSerialPortRead(RTSERIALPORT hSerialPort, void *pvBuf, size_t cbToRead, size_t *pcbRead);
+
+
+/**
+ * Tries to read the given number of bytes from the serial port, non-blocking version.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_SERIALPORT_BREAK_DETECTED if a break was detected before anything could be received.
+ * @retval VINF_TRY_AGAIN if nothing could be read.
+ * @param hSerialPort The IPRT serial port handle.
+ * @param pvBuf Where to store the read data.
+ * @param cbToRead How much to read from the serial port.
+ * @param pcbRead Where to store the number of bytes received.
+ */
+RTDECL(int) RTSerialPortReadNB(RTSERIALPORT hSerialPort, void *pvBuf, size_t cbToRead, size_t *pcbRead);
+
+
+/**
+ * Writes the given data to the serial port, blocking version.
+ *
+ * @returns IPRT status code.
+ * @param hSerialPort The IPRT serial port handle.
+ * @param pvBuf The data to write.
+ * @param cbToWrite How much to write.
+ * @param pcbWritten Where to store the number of bytes written until an error condition occurred, optional.
+ */
+RTDECL(int) RTSerialPortWrite(RTSERIALPORT hSerialPort, const void *pvBuf, size_t cbToWrite, size_t *pcbWritten);
+
+
+/**
+ * Writes the given data to the serial port, non-blocking version.
+ *
+ * @returns IPRT status code.
+ * @retval VINF_TRY_AGAIN if nothing could be written.
+ * @param hSerialPort The IPRT serial port handle.
+ * @param pvBuf The data to write.
+ * @param cbToWrite How much to write.
+ * @param pcbWritten Where to store the number of bytes written.
+ */
+RTDECL(int) RTSerialPortWriteNB(RTSERIALPORT hSerialPort, const void *pvBuf, size_t cbToWrite, size_t *pcbWritten);
+
+
+/**
+ * Queries the current active serial port config.
+ *
+ * @returns IPRT status code.
+ * @param hSerialPort The IPRT serial port handle.
+ * @param pCfg Where to store the current active config.
+ */
+RTDECL(int) RTSerialPortCfgQueryCurrent(RTSERIALPORT hSerialPort, PRTSERIALPORTCFG pCfg);
+
+
+/**
+ * Change the serial port to the given config.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_SERIALPORT_INVALID_BAUDRATE if the baud rate is not supported on the serial port.
+ * @param hSerialPort The IPRT serial port handle.
+ * @param pCfg The config to write.
+ * @param pErrInfo Where to store additional information on error, optional.
+ */
+RTDECL(int) RTSerialPortCfgSet(RTSERIALPORT hSerialPort, PCRTSERIALPORTCFG pCfg, PRTERRINFO pErrInfo);
+
+
+/**
+ * Poll for an event on the given serial port.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_TIMEOUT if the timeout was reached before an event happened.
+ * @retval VERR_INTERRUPTED if another thread interrupted the polling through RTSerialPortEvtPollInterrupt().
+ * @param hSerialPort The IPRT serial port handle.
+ * @param fEvtMask The mask of events to receive, see RTSERIALPORT_EVT_F_*
+ * @param pfEvtsRecv Where to store the bitmask of events received.
+ * @param msTimeout Number of milliseconds to wait for an event.
+ */
+RTDECL(int) RTSerialPortEvtPoll(RTSERIALPORT hSerialPort, uint32_t fEvtMask, uint32_t *pfEvtsRecv,
+ RTMSINTERVAL msTimeout);
+
+
+/**
+ * Interrupt another thread currently polling for an event.
+ *
+ * @returns IPRT status code.
+ * @param hSerialPort The IPRT serial port handle.
+ *
+ * @note Any thread.
+ */
+RTDECL(int) RTSerialPortEvtPollInterrupt(RTSERIALPORT hSerialPort);
+
+
+/**
+ * Sets or clears a BREAK condition on the given serial port.
+ *
+ * @returns IPRT status code.
+ * @param hSerialPort The IPRT serial port handle.
+ * @param fSet Flag whether to set the BREAK condition or clear it.
+ */
+RTDECL(int) RTSerialPortChgBreakCondition(RTSERIALPORT hSerialPort, bool fSet);
+
+
+/**
+ * Modify the status lines of the given serial port.
+ *
+ * @returns IPRT status code.
+ * @param hSerialPort The IPRT serial port handle.
+ * @param fClear Combination of status lines to clear, see RTSERIALPORT_CHG_STS_LINES_F_*.
+ * @param fSet Combination of status lines to set, see RTSERIALPORT_CHG_STS_LINES_F_*.
+ *
+ * @note fClear takes precedence over fSet in case the same status line bit is set in both arguments.
+ */
+RTDECL(int) RTSerialPortChgStatusLines(RTSERIALPORT hSerialPort, uint32_t fClear, uint32_t fSet);
+
+
+/**
+ * Query the status of the status lines on the given serial port.
+ *
+ * @returns IPRT status code.
+ * @param hSerialPort The IPRT serial port handle.
+ * @param pfStsLines Where to store the bitmask of active status lines on success,
+ * see RTSERIALPORT_STS_LINE_*.
+ */
+RTDECL(int) RTSerialPortQueryStatusLines(RTSERIALPORT hSerialPort, uint32_t *pfStsLines);
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_serialport_h */
+
diff --git a/include/iprt/setjmp-without-sigmask.h b/include/iprt/setjmp-without-sigmask.h
new file mode 100644
index 00000000..b73bce4c
--- /dev/null
+++ b/include/iprt/setjmp-without-sigmask.h
@@ -0,0 +1,64 @@
+/** @file
+ * IPRT - setjmp/long without signal mask saving and restoring.
+ */
+
+/*
+ * Copyright (C) 2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_setjmp_without_sigmask_h
+#define IPRT_INCLUDED_setjmp_without_sigmask_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+
+#include <iprt/cdefs.h>
+#include <setjmp.h>
+
+/*
+ * System V and ANSI-C setups does not by default map setjmp/longjmp to the
+ * signal mask saving/restoring variants (Linux included). This is mainly
+ * an issue on BSD derivatives.
+ */
+#if defined(IN_RING3) \
+ && ( defined(RT_OS_DARWIN) \
+ || defined(RT_OS_DRAGONFLY) \
+ || defined(RT_OS_FREEBSD) \
+ || defined(RT_OS_NETBSD) \
+ || defined(RT_OS_OPENBSD) )
+# undef setjmp /* /Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/setjmp.h defines it on macOS. */
+# define setjmp _setjmp
+# define longjmp _longjmp
+#endif
+
+
+#endif /* !IPRT_INCLUDED_setjmp_without_sigmask_h */
+
diff --git a/include/iprt/sg.h b/include/iprt/sg.h
new file mode 100644
index 00000000..b0831d95
--- /dev/null
+++ b/include/iprt/sg.h
@@ -0,0 +1,460 @@
+/** @file
+ * IPRT - S/G buffer handling.
+ */
+
+/*
+ * Copyright (C) 2010-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_sg_h
+#define IPRT_INCLUDED_sg_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_sgbuf RTSgBuf - Scatter / Gather Buffers
+ * @ingroup grp_rt
+ * @{
+ */
+
+/** Pointer to a const S/G entry. */
+typedef const struct RTSGBUF *PCRTSGBUF;
+
+/**
+ * Callback for RTSgBufCopyToFn() called on every segment of the given S/G buffer.
+ *
+ * @returns Number of bytes copied for this segment, a value smaller than cbSrc will stop the copy operation.
+ * @param pSgBuf The S/G buffer for reference.
+ * @param pvSrc Where to copy from.
+ * @param cbSrc The number of bytes in the source buffer.
+ * @param pvUser Opaque user data passed in RTSgBufCopyToFn().
+ */
+typedef DECLCALLBACKTYPE(size_t, FNRTSGBUFCOPYTO, (PCRTSGBUF pSgBuf, const void *pvSrc, size_t cbSrc, void *pvUser));
+/** Pointer to a FNRTSGBUFCOPYTO. */
+typedef FNRTSGBUFCOPYTO *PFNRTSGBUFCOPYTO;
+
+/**
+ * Callback for RTSgBufCopyFromFn() called on every segment of the given S/G buffer.
+ *
+ * @returns Number of bytes copied for this segment, a value smaller than cbDst will stop the copy operation.
+ * @param pSgBuf The S/G buffer for reference.
+ * @param pvDst Where to copy to.
+ * @param cbDst The number of bytes in the destination buffer.
+ * @param pvUser Opaque user data passed in RTSgBufCopyFromFn().
+ */
+typedef DECLCALLBACKTYPE(size_t, FNRTSGBUFCOPYFROM, (PCRTSGBUF pSgBuf, void *pvDst, size_t cbDst, void *pvUser));
+/** Pointer to a FNRTSGBUFCOPYFROM. */
+typedef FNRTSGBUFCOPYFROM *PFNRTSGBUFCOPYFROM;
+
+/**
+ * A S/G entry.
+ */
+typedef struct RTSGSEG
+{
+ /** Pointer to the segment buffer. */
+ void *pvSeg;
+ /** Size of the segment buffer. */
+ size_t cbSeg;
+} RTSGSEG;
+/** Pointer to a S/G entry. */
+typedef RTSGSEG *PRTSGSEG;
+/** Pointer to a const S/G entry. */
+typedef const RTSGSEG *PCRTSGSEG;
+/** Pointer to a S/G entry pointer. */
+typedef PRTSGSEG *PPRTSGSEG;
+
+/**
+ * A S/G buffer.
+ *
+ * The members should be treated as private.
+ *
+ * @warning There is a lot of code, especially in the VFS area of IPRT, that
+ * totally ignores the idxSeg, pvSegCur and cbSegLeft members! So,
+ * it is not recommended to pass buffers that aren't fully reset or
+ * where cbSegLeft is shorter than what paSegs describes.
+ */
+typedef struct RTSGBUF
+{
+ /** Pointer to the scatter/gather array. */
+ PCRTSGSEG paSegs;
+ /** Number of segments. */
+ unsigned cSegs;
+
+ /** Current segment we are in. */
+ unsigned idxSeg;
+ /** Pointer to current byte within the current segment. */
+ void *pvSegCur;
+ /** Number of bytes left in the current segment. */
+ size_t cbSegLeft;
+} RTSGBUF;
+/** Pointer to a S/G entry. */
+typedef RTSGBUF *PRTSGBUF;
+/** Pointer to a S/G entry pointer. */
+typedef PRTSGBUF *PPRTSGBUF;
+
+
+/**
+ * Sums up the length of all the segments.
+ *
+ * @returns The complete segment length.
+ * @param pSgBuf The S/G buffer to check out.
+ */
+DECLINLINE(size_t) RTSgBufCalcTotalLength(PCRTSGBUF pSgBuf)
+{
+ size_t cb = 0;
+ unsigned i = pSgBuf->cSegs;
+ while (i-- > 0)
+ cb += pSgBuf->paSegs[i].cbSeg;
+ return cb;
+}
+
+/**
+ * Sums up the number of bytes left from the current position.
+ *
+ * @returns Number of bytes left.
+ * @param pSgBuf The S/G buffer to check out.
+ */
+DECLINLINE(size_t) RTSgBufCalcLengthLeft(PCRTSGBUF pSgBuf)
+{
+ size_t cb = pSgBuf->cbSegLeft;
+ unsigned i = pSgBuf->cSegs;
+ while (i-- > pSgBuf->idxSeg + 1)
+ cb += pSgBuf->paSegs[i].cbSeg;
+ return cb;
+}
+
+/**
+ * Checks if the current buffer position is at the start of the first segment.
+ *
+ * @returns true / false.
+ * @param pSgBuf The S/G buffer to check out.
+ */
+DECLINLINE(bool) RTSgBufIsAtStart(PCRTSGBUF pSgBuf)
+{
+ return pSgBuf->idxSeg == 0
+ && ( pSgBuf->cSegs == 0
+ || pSgBuf->pvSegCur == pSgBuf->paSegs[0].pvSeg);
+}
+
+/**
+ * Checks if the current buffer position is at the end of all the segments.
+ *
+ * @returns true / false.
+ * @param pSgBuf The S/G buffer to check out.
+ */
+DECLINLINE(bool) RTSgBufIsAtEnd(PCRTSGBUF pSgBuf)
+{
+ return pSgBuf->idxSeg > pSgBuf->cSegs
+ || ( pSgBuf->idxSeg == pSgBuf->cSegs
+ && pSgBuf->cbSegLeft == 0);
+}
+
+/**
+ * Checks if the current buffer position is at the start of the current segment.
+ *
+ * @returns true / false.
+ * @param pSgBuf The S/G buffer to check out.
+ */
+DECLINLINE(bool) RTSgBufIsAtStartOfSegment(PCRTSGBUF pSgBuf)
+{
+ return pSgBuf->idxSeg < pSgBuf->cSegs
+ && pSgBuf->paSegs[pSgBuf->idxSeg].pvSeg == pSgBuf->pvSegCur;
+}
+
+/**
+ * Initialize a S/G buffer structure.
+ *
+ * @returns nothing.
+ * @param pSgBuf Pointer to the S/G buffer to initialize.
+ * @param paSegs Pointer to the start of the segment array.
+ * @param cSegs Number of segments in the array.
+ *
+ * @note paSegs and cSegs can be NULL and 0 respectively to indicate an empty
+ * S/G buffer. Operations on the S/G buffer will not do anything in this
+ * case.
+ */
+RTDECL(void) RTSgBufInit(PRTSGBUF pSgBuf, PCRTSGSEG paSegs, size_t cSegs);
+
+/**
+ * Resets the internal buffer position of the S/G buffer to the beginning.
+ *
+ * @returns nothing.
+ * @param pSgBuf The S/G buffer to reset.
+ */
+RTDECL(void) RTSgBufReset(PRTSGBUF pSgBuf);
+
+/**
+ * Clones a given S/G buffer.
+ *
+ * @returns nothing.
+ * @param pSgBufNew The new S/G buffer to clone to.
+ * @param pSgBufOld The source S/G buffer to clone from.
+ *
+ * @note This is only a shallow copy. Both S/G buffers will point to the
+ * same segment array.
+ */
+RTDECL(void) RTSgBufClone(PRTSGBUF pSgBufNew, PCRTSGBUF pSgBufOld);
+
+/**
+ * Returns the next segment in the S/G buffer or NULL if no segments left.
+ *
+ * @returns Pointer to the next segment in the S/G buffer.
+ * @param pSgBuf The S/G buffer.
+ * @param cbDesired The max number of bytes to get.
+ * @param pcbSeg Where to store the size of the returned segment, this is
+ * equal or smaller than @a cbDesired.
+ *
+ * @note Use RTSgBufAdvance() to advance after read/writing into the buffer.
+ */
+DECLINLINE(void *) RTSgBufGetCurrentSegment(PRTSGBUF pSgBuf, size_t cbDesired, size_t *pcbSeg)
+{
+ if (!RTSgBufIsAtEnd(pSgBuf))
+ {
+ *pcbSeg = RT_MIN(cbDesired, pSgBuf->cbSegLeft);
+ return pSgBuf->pvSegCur;
+ }
+ *pcbSeg = 0;
+ return NULL;
+}
+
+/**
+ * Returns the next segment in the S/G buffer or NULL if no segment is left.
+ *
+ * @returns Pointer to the next segment in the S/G buffer.
+ * @param pSgBuf The S/G buffer.
+ * @param pcbSeg Where to store the size of the returned segment.
+ * Holds the number of bytes requested initially or 0 to
+ * indicate that the size doesn't matter.
+ * This may contain fewer bytes on success if the current segment
+ * is smaller than the amount of bytes requested.
+ *
+ * @note This operation advances the internal buffer pointer of both S/G buffers.
+ */
+RTDECL(void *) RTSgBufGetNextSegment(PRTSGBUF pSgBuf, size_t *pcbSeg);
+
+/**
+ * Copy data between two S/G buffers.
+ *
+ * @returns The number of bytes copied.
+ * @param pSgBufDst The destination S/G buffer.
+ * @param pSgBufSrc The source S/G buffer.
+ * @param cbCopy Number of bytes to copy.
+ *
+ * @note This operation advances the internal buffer pointer of both S/G buffers.
+ */
+RTDECL(size_t) RTSgBufCopy(PRTSGBUF pSgBufDst, PRTSGBUF pSgBufSrc, size_t cbCopy);
+
+/**
+ * Compares the content of two S/G buffers.
+ *
+ * @returns Whatever memcmp returns.
+ * @param pSgBuf1 First S/G buffer.
+ * @param pSgBuf2 Second S/G buffer.
+ * @param cbCmp How many bytes to compare.
+ *
+ * @note This operation doesn't change the internal position of the S/G buffers.
+ */
+RTDECL(int) RTSgBufCmp(PCRTSGBUF pSgBuf1, PCRTSGBUF pSgBuf2, size_t cbCmp);
+
+/**
+ * Compares the content of two S/G buffers - advanced version.
+ *
+ * @returns Whatever memcmp returns.
+ * @param pSgBuf1 First S/G buffer.
+ * @param pSgBuf2 Second S/G buffer.
+ * @param cbCmp How many bytes to compare.
+ * @param poffDiff Where to store the offset of the first different byte
+ * in the buffer starting from the position of the S/G
+ * buffer before this call.
+ * @param fAdvance Flag whether the internal buffer position should be advanced.
+ *
+ */
+RTDECL(int) RTSgBufCmpEx(PRTSGBUF pSgBuf1, PRTSGBUF pSgBuf2, size_t cbCmp, size_t *poffDiff, bool fAdvance);
+
+/**
+ * Fills an S/G buf with a constant byte.
+ *
+ * @returns The number of actually filled bytes.
+ * Can be less than than cbSet if the end of the S/G buffer was reached.
+ * @param pSgBuf The S/G buffer.
+ * @param ubFill The byte to fill the buffer with.
+ * @param cbSet How many bytes to set.
+ *
+ * @note This operation advances the internal buffer pointer of the S/G buffer.
+ */
+RTDECL(size_t) RTSgBufSet(PRTSGBUF pSgBuf, uint8_t ubFill, size_t cbSet);
+
+/**
+ * Copies data from an S/G buffer into a given non scattered buffer.
+ *
+ * @returns Number of bytes copied.
+ * @param pSgBuf The S/G buffer to copy from.
+ * @param pvBuf Buffer to copy the data into.
+ * @param cbCopy How many bytes to copy.
+ *
+ * @note This operation advances the internal buffer pointer of the S/G buffer.
+ */
+RTDECL(size_t) RTSgBufCopyToBuf(PRTSGBUF pSgBuf, void *pvBuf, size_t cbCopy);
+
+/**
+ * Copies data from a non scattered buffer into an S/G buffer.
+ *
+ * @returns Number of bytes copied.
+ * @param pSgBuf The S/G buffer to copy to.
+ * @param pvBuf Buffer to copy the data from.
+ * @param cbCopy How many bytes to copy.
+ *
+ * @note This operation advances the internal buffer pointer of the S/G buffer.
+ */
+RTDECL(size_t) RTSgBufCopyFromBuf(PRTSGBUF pSgBuf, const void *pvBuf, size_t cbCopy);
+
+/**
+ * Copies data from the given S/G buffer to a destination handled by the given callback.
+ *
+ * @returns Number of bytes copied.
+ * @param pSgBuf The S/G buffer to copy from.
+ * @param cbCopy How many bytes to copy.
+ * @param pfnCopyTo The callback to call on every S/G buffer segment until the operation finished.
+ * @param pvUser Opaque user data to pass in the given callback.
+ *
+ * @note This operation advances the internal buffer pointer of the S/G buffer.
+ */
+RTDECL(size_t) RTSgBufCopyToFn(PRTSGBUF pSgBuf, size_t cbCopy, PFNRTSGBUFCOPYTO pfnCopyTo, void *pvUser);
+
+/**
+ * Copies data to the given S/G buffer from a destination handled by the given callback.
+ *
+ * @returns Number of bytes copied.
+ * @param pSgBuf The S/G buffer to copy to.
+ * @param cbCopy How many bytes to copy.
+ * @param pfnCopyFrom The callback to call on every S/G buffer segment until the operation finished.
+ * @param pvUser Opaque user data to pass in the given callback.
+ *
+ * @note This operation advances the internal buffer pointer of the S/G buffer.
+ */
+RTDECL(size_t) RTSgBufCopyFromFn(PRTSGBUF pSgBuf, size_t cbCopy, PFNRTSGBUFCOPYFROM pfnCopyFrom, void *pvUser);
+
+/**
+ * Advances the internal buffer pointer.
+ *
+ * @returns Number of bytes the pointer was moved forward.
+ * @param pSgBuf The S/G buffer.
+ * @param cbAdvance Number of bytes to move forward.
+ */
+RTDECL(size_t) RTSgBufAdvance(PRTSGBUF pSgBuf, size_t cbAdvance);
+
+/**
+ * Constructs a new segment array starting from the current position
+ * and describing the given number of bytes.
+ *
+ * @returns Number of bytes the array describes.
+ * @param pSgBuf The S/G buffer.
+ * @param paSeg The uninitialized segment array.
+ * If NULL pcSeg will contain the number of segments needed
+ * to describe the requested amount of data.
+ * @param pcSeg The number of segments the given array has.
+ * This will hold the actual number of entries needed upon return.
+ * @param cbData Number of bytes the new array should describe.
+ *
+ * @note This operation advances the internal buffer pointer of the S/G buffer if paSeg is not NULL.
+ */
+RTDECL(size_t) RTSgBufSegArrayCreate(PRTSGBUF pSgBuf, PRTSGSEG paSeg, unsigned *pcSeg, size_t cbData);
+
+/**
+ * Returns whether the given S/G buffer is zeroed out from the current position
+ * upto the number of bytes to check.
+ *
+ * @returns true if the buffer has only zeros
+ * false otherwise.
+ * @param pSgBuf The S/G buffer.
+ * @param cbCheck Number of bytes to check.
+ */
+RTDECL(bool) RTSgBufIsZero(PRTSGBUF pSgBuf, size_t cbCheck);
+
+/**
+ * Maps the given S/G buffer to a segment array of another type (for example to
+ * iovec on POSIX or WSABUF on Windows).
+ *
+ * @param paMapped Where to store the pointer to the start of the native
+ * array or NULL. The memory needs to be freed with
+ * RTMemTmpFree().
+ * @param pSgBuf The S/G buffer to map.
+ * @param Struct Struct used as the destination.
+ * @param pvBufField Name of the field holding the pointer to a buffer.
+ * @param TypeBufPtr Type of the buffer pointer.
+ * @param cbBufField Name of the field holding the size of the buffer.
+ * @param TypeBufSize Type of the field for the buffer size.
+ * @param cSegsMapped Where to store the number of segments the native array
+ * has.
+ *
+ * @note This operation maps the whole S/G buffer starting at the current
+ * internal position. The internal buffer position is unchanged by
+ * this operation.
+ *
+ * @remark Usage is a bit ugly but saves a few lines of duplicated code
+ * somewhere else and makes it possible to keep the S/G buffer members
+ * private without going through RTSgBufSegArrayCreate() first.
+ */
+#define RTSgBufMapToNative(paMapped, pSgBuf, Struct, pvBufField, TypeBufPtr, cbBufField, TypeBufSize, cSegsMapped) \
+ do \
+ { \
+ AssertCompileMemberSize(Struct, pvBufField, RT_SIZEOFMEMB(RTSGSEG, pvSeg)); \
+ /*AssertCompile(RT_SIZEOFMEMB(Struct, cbBufField) >= RT_SIZEOFMEMB(RTSGSEG, cbSeg));*/ \
+ (cSegsMapped) = (pSgBuf)->cSegs - (pSgBuf)->idxSeg; \
+ \
+ /* We need room for at least one segment. */ \
+ if ((pSgBuf)->cSegs == (pSgBuf)->idxSeg) \
+ (cSegsMapped)++; \
+ \
+ (paMapped) = (Struct *)RTMemTmpAllocZ((cSegsMapped) * sizeof(Struct)); \
+ if ((paMapped)) \
+ { \
+ /* The first buffer is special because we could be in the middle of a segment. */ \
+ (paMapped)[0].pvBufField = (TypeBufPtr)(pSgBuf)->pvSegCur; \
+ (paMapped)[0].cbBufField = (TypeBufSize)(pSgBuf)->cbSegLeft; \
+ \
+ for (unsigned i = 1; i < (cSegsMapped); i++) \
+ { \
+ (paMapped)[i].pvBufField = (TypeBufPtr)(pSgBuf)->paSegs[(pSgBuf)->idxSeg + i].pvSeg; \
+ (paMapped)[i].cbBufField = (TypeBufSize)(pSgBuf)->paSegs[(pSgBuf)->idxSeg + i].cbSeg; \
+ } \
+ } \
+ } while (0)
+
+RT_C_DECLS_END
+
+/** @} */
+
+#endif /* !IPRT_INCLUDED_sg_h */
+
diff --git a/include/iprt/sha.h b/include/iprt/sha.h
new file mode 100644
index 00000000..d39e0ca7
--- /dev/null
+++ b/include/iprt/sha.h
@@ -0,0 +1,593 @@
+/** @file
+ * IPRT - SHA1 digest creation
+ */
+
+/*
+ * Copyright (C) 2009-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_sha_h
+#define IPRT_INCLUDED_sha_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_sha RTSha - SHA Family of Hash Functions
+ * @ingroup grp_rt
+ * @{
+ */
+
+/** The size of a SHA-1 hash. */
+#define RTSHA1_HASH_SIZE 20
+/** The length of a SHA-1 digest string. The terminator is not included. */
+#define RTSHA1_DIGEST_LEN 40
+
+/**
+ * SHA-1 context.
+ */
+typedef union RTSHA1CONTEXT
+{
+ uint64_t u64BetterAlignment;
+ uint8_t abPadding[8 + (5 + 80) * 4 + 4];
+#ifdef RT_SHA1_PRIVATE_CONTEXT
+ SHA_CTX Private;
+#endif
+#ifdef RT_SHA1_PRIVATE_ALT_CONTEXT
+ RTSHA1ALTPRIVATECTX AltPrivate;
+#endif
+} RTSHA1CONTEXT;
+/** Pointer to an SHA-1 context. */
+typedef RTSHA1CONTEXT *PRTSHA1CONTEXT;
+
+/**
+ * Compute the SHA-1 hash of the data.
+ *
+ * @param pvBuf Pointer to the data.
+ * @param cbBuf The amount of data (in bytes).
+ * @param pabHash Where to store the hash. (What is passed is a pointer to
+ * the caller's buffer.)
+ */
+RTDECL(void) RTSha1(const void *pvBuf, size_t cbBuf, uint8_t pabHash[RTSHA1_HASH_SIZE]);
+
+/**
+ * Computes the SHA-1 hash for the given data comparing it with the one given.
+ *
+ * @returns true on match, false on mismatch.
+ * @param pvBuf Pointer to the data.
+ * @param cbBuf The amount of data (in bytes).
+ * @param pabHash The hash to verify. (What is passed is a pointer to the
+ * caller's buffer.)
+ */
+RTDECL(bool) RTSha1Check(const void *pvBuf, size_t cbBuf, uint8_t const pabHash[RTSHA1_HASH_SIZE]);
+
+/**
+ * Initializes the SHA-1 context.
+ *
+ * @param pCtx Pointer to the SHA-1 context.
+ */
+RTDECL(void) RTSha1Init(PRTSHA1CONTEXT pCtx);
+
+/**
+ * Feed data into the SHA-1 computation.
+ *
+ * @param pCtx Pointer to the SHA-1 context.
+ * @param pvBuf Pointer to the data.
+ * @param cbBuf The length of the data (in bytes).
+ */
+RTDECL(void) RTSha1Update(PRTSHA1CONTEXT pCtx, const void *pvBuf, size_t cbBuf);
+
+/**
+ * Compute the SHA-1 hash of the data.
+ *
+ * @param pCtx Pointer to the SHA-1 context.
+ * @param pabHash Where to store the hash. (What is passed is a pointer to
+ * the caller's buffer.)
+ */
+RTDECL(void) RTSha1Final(PRTSHA1CONTEXT pCtx, uint8_t pabHash[RTSHA1_HASH_SIZE]);
+
+/**
+ * Converts a SHA-1 hash to a digest string.
+ *
+ * @returns IPRT status code.
+ *
+ * @param pabHash The binary digest returned by RTSha1Final or RTSha1.
+ * @param pszDigest Where to return the stringified digest.
+ * @param cchDigest The size of the output buffer. Should be at least
+ * RTSHA1_DIGEST_LEN + 1 bytes.
+ */
+RTDECL(int) RTSha1ToString(uint8_t const pabHash[RTSHA1_HASH_SIZE], char *pszDigest, size_t cchDigest);
+
+/**
+ * Converts a SHA-1 hash to a digest string.
+ *
+ * @returns IPRT status code.
+ *
+ * @param pszDigest The stringified digest. Leading and trailing spaces are
+ * ignored.
+ * @param pabHash Where to store the hash. (What is passed is a pointer to
+ * the caller's buffer.)
+ */
+RTDECL(int) RTSha1FromString(char const *pszDigest, uint8_t pabHash[RTSHA1_HASH_SIZE]);
+
+/**
+ * Creates a SHA1 digest for the given memory buffer.
+ *
+ * @returns iprt status code.
+ *
+ * @param pvBuf Memory buffer to create a SHA1 digest for.
+ * @param cbBuf The amount of data (in bytes).
+ * @param ppszDigest On success the SHA1 digest.
+ * @param pfnProgressCallback optional callback for the progress indication
+ * @param pvUser user defined pointer for the callback
+ */
+RTR3DECL(int) RTSha1Digest(void* pvBuf, size_t cbBuf, char **ppszDigest, PFNRTPROGRESS pfnProgressCallback, void *pvUser);
+
+/**
+ * Creates a SHA1 digest for the given file.
+ *
+ * @returns iprt status code.
+ *
+ * @param pszFile Filename to create a SHA1 digest for.
+ * @param ppszDigest On success the SHA1 digest.
+ * @param pfnProgressCallback optional callback for the progress indication
+ * @param pvUser user defined pointer for the callback
+ */
+RTR3DECL(int) RTSha1DigestFromFile(const char *pszFile, char **ppszDigest, PFNRTPROGRESS pfnProgressCallback, void *pvUser);
+
+
+
+/** The size of a SHA-256 hash. */
+#define RTSHA256_HASH_SIZE 32
+/** The length of a SHA-256 digest string. The terminator is not included. */
+#define RTSHA256_DIGEST_LEN 64
+
+/**
+ * SHA-256 context.
+ */
+typedef union RTSHA256CONTEXT
+{
+ uint64_t u64BetterAlignment;
+ uint8_t abPadding[8 + (8 + 80) * 4];
+#ifdef RT_SHA256_PRIVATE_CONTEXT
+ SHA256_CTX Private;
+#endif
+#ifdef RT_SHA256_PRIVATE_ALT_CONTEXT
+ RTSHA256ALTPRIVATECTX AltPrivate;
+#endif
+} RTSHA256CONTEXT;
+/** Pointer to an SHA-256 context. */
+typedef RTSHA256CONTEXT *PRTSHA256CONTEXT;
+
+/**
+ * Compute the SHA-256 hash of the data.
+ *
+ * @param pvBuf Pointer to the data.
+ * @param cbBuf The amount of data (in bytes).
+ * @param pabHash Where to store the hash. (What is passed is a pointer to
+ * the caller's buffer.)
+ */
+RTDECL(void) RTSha256(const void *pvBuf, size_t cbBuf, uint8_t pabHash[RTSHA256_HASH_SIZE]);
+
+/**
+ * Computes the SHA-256 hash for the given data comparing it with the one given.
+ *
+ * @returns true on match, false on mismatch.
+ * @param pvBuf Pointer to the data.
+ * @param cbBuf The amount of data (in bytes).
+ * @param pabHash The hash to verify. (What is passed is a pointer to the
+ * caller's buffer.)
+ */
+RTDECL(bool) RTSha256Check(const void *pvBuf, size_t cbBuf, uint8_t const pabHash[RTSHA256_HASH_SIZE]);
+
+/**
+ * Initializes the SHA-256 context.
+ *
+ * @param pCtx Pointer to the SHA-256 context.
+ */
+RTDECL(void) RTSha256Init(PRTSHA256CONTEXT pCtx);
+
+/**
+ * Feed data into the SHA-256 computation.
+ *
+ * @param pCtx Pointer to the SHA-256 context.
+ * @param pvBuf Pointer to the data.
+ * @param cbBuf The length of the data (in bytes).
+ */
+RTDECL(void) RTSha256Update(PRTSHA256CONTEXT pCtx, const void *pvBuf, size_t cbBuf);
+
+/**
+ * Compute the SHA-256 hash of the data.
+ *
+ * @param pCtx Pointer to the SHA-256 context.
+ * @param pabHash Where to store the hash. (What is passed is a pointer to
+ * the caller's buffer.)
+ */
+RTDECL(void) RTSha256Final(PRTSHA256CONTEXT pCtx, uint8_t pabHash[RTSHA256_HASH_SIZE]);
+
+/**
+ * Converts a SHA-256 hash to a digest string.
+ *
+ * @returns IPRT status code.
+ *
+ * @param pabHash The binary digest returned by RTSha256Final or RTSha256.
+ * @param pszDigest Where to return the stringified digest.
+ * @param cchDigest The size of the output buffer. Should be at least
+ * RTSHA256_DIGEST_LEN + 1 bytes.
+ */
+RTDECL(int) RTSha256ToString(uint8_t const pabHash[RTSHA256_HASH_SIZE], char *pszDigest, size_t cchDigest);
+
+/**
+ * Converts a SHA-256 hash to a digest string.
+ *
+ * @returns IPRT status code.
+ *
+ * @param pszDigest The stringified digest. Leading and trailing spaces are
+ * ignored.
+ * @param pabHash Where to store the hash. (What is passed is a pointer to
+ * the caller's buffer.)
+ */
+RTDECL(int) RTSha256FromString(char const *pszDigest, uint8_t pabHash[RTSHA256_HASH_SIZE]);
+
+/**
+ * Creates a SHA256 digest for the given memory buffer.
+ *
+ * @returns iprt status code.
+ *
+ * @param pvBuf Memory buffer to create a
+ * SHA256 digest for.
+ * @param cbBuf The amount of data (in bytes).
+ * @param ppszDigest On success the SHA256 digest.
+ * @param pfnProgressCallback optional callback for the progress indication
+ * @param pvUser user defined pointer for the callback
+ */
+RTR3DECL(int) RTSha256Digest(void* pvBuf, size_t cbBuf, char **ppszDigest, PFNRTPROGRESS pfnProgressCallback, void *pvUser);
+
+/**
+ * Creates a SHA256 digest for the given file.
+ *
+ * @returns iprt status code.
+ *
+ * @param pszFile Filename to create a SHA256
+ * digest for.
+ * @param ppszDigest On success the SHA256 digest.
+ * @param pfnProgressCallback optional callback for the progress indication
+ * @param pvUser user defined pointer for the callback
+ */
+RTR3DECL(int) RTSha256DigestFromFile(const char *pszFile, char **ppszDigest, PFNRTPROGRESS pfnProgressCallback, void *pvUser);
+
+
+
+/** The size of a SHA-224 hash. */
+#define RTSHA224_HASH_SIZE 28
+/** The length of a SHA-224 digest string. The terminator is not included. */
+#define RTSHA224_DIGEST_LEN 56
+
+/** SHA-224 context (same as for SHA-256). */
+typedef RTSHA256CONTEXT RTSHA224CONTEXT;
+/** Pointer to an SHA-224 context. */
+typedef RTSHA256CONTEXT *PRTSHA224CONTEXT;
+
+/**
+ * Compute the SHA-224 hash of the data.
+ *
+ * @param pvBuf Pointer to the data.
+ * @param cbBuf The amount of data (in bytes).
+ * @param pabHash Where to store the hash. (What is passed is a pointer to
+ * the caller's buffer.)
+ */
+RTDECL(void) RTSha224(const void *pvBuf, size_t cbBuf, uint8_t pabHash[RTSHA224_HASH_SIZE]);
+
+/**
+ * Computes the SHA-224 hash for the given data comparing it with the one given.
+ *
+ * @returns true on match, false on mismatch.
+ * @param pvBuf Pointer to the data.
+ * @param cbBuf The amount of data (in bytes).
+ * @param pabHash The hash to verify. (What is passed is a pointer to the
+ * caller's buffer.)
+ */
+RTDECL(bool) RTSha224Check(const void *pvBuf, size_t cbBuf, uint8_t const pabHash[RTSHA224_HASH_SIZE]);
+
+/**
+ * Initializes the SHA-224 context.
+ *
+ * @param pCtx Pointer to the SHA-224 context.
+ */
+RTDECL(void) RTSha224Init(PRTSHA224CONTEXT pCtx);
+
+/**
+ * Feed data into the SHA-224 computation.
+ *
+ * @param pCtx Pointer to the SHA-224 context.
+ * @param pvBuf Pointer to the data.
+ * @param cbBuf The length of the data (in bytes).
+ */
+RTDECL(void) RTSha224Update(PRTSHA224CONTEXT pCtx, const void *pvBuf, size_t cbBuf);
+
+/**
+ * Compute the SHA-224 hash of the data.
+ *
+ * @param pCtx Pointer to the SHA-224 context.
+ * @param pabHash Where to store the hash. (What is passed is a pointer to
+ * the caller's buffer.)
+ */
+RTDECL(void) RTSha224Final(PRTSHA224CONTEXT pCtx, uint8_t pabHash[RTSHA224_HASH_SIZE]);
+
+/**
+ * Converts a SHA-224 hash to a digest string.
+ *
+ * @returns IPRT status code.
+ *
+ * @param pabHash The binary digest returned by RTSha224Final or RTSha224.
+ * @param pszDigest Where to return the stringified digest.
+ * @param cchDigest The size of the output buffer. Should be at least
+ * RTSHA224_DIGEST_LEN + 1 bytes.
+ */
+RTDECL(int) RTSha224ToString(uint8_t const pabHash[RTSHA224_HASH_SIZE], char *pszDigest, size_t cchDigest);
+
+/**
+ * Converts a SHA-224 hash to a digest string.
+ *
+ * @returns IPRT status code.
+ *
+ * @param pszDigest The stringified digest. Leading and trailing spaces are
+ * ignored.
+ * @param pabHash Where to store the hash. (What is passed is a pointer to
+ * the caller's buffer.)
+ */
+RTDECL(int) RTSha224FromString(char const *pszDigest, uint8_t pabHash[RTSHA224_HASH_SIZE]);
+
+/**
+ * Creates a SHA224 digest for the given memory buffer.
+ *
+ * @returns iprt status code.
+ *
+ * @param pvBuf Memory buffer to create a SHA224 digest for.
+ * @param cbBuf The amount of data (in bytes).
+ * @param ppszDigest On success the SHA224 digest.
+ * @param pfnProgressCallback optional callback for the progress indication
+ * @param pvUser user defined pointer for the callback
+ */
+RTR3DECL(int) RTSha224Digest(void* pvBuf, size_t cbBuf, char **ppszDigest, PFNRTPROGRESS pfnProgressCallback, void *pvUser);
+
+/**
+ * Creates a SHA224 digest for the given file.
+ *
+ * @returns iprt status code.
+ *
+ * @param pszFile Filename to create a SHA224 digest for.
+ * @param ppszDigest On success the SHA224 digest.
+ * @param pfnProgressCallback optional callback for the progress indication
+ * @param pvUser user defined pointer for the callback
+ */
+RTR3DECL(int) RTSha224DigestFromFile(const char *pszFile, char **ppszDigest, PFNRTPROGRESS pfnProgressCallback, void *pvUser);
+
+
+
+/** The size of a SHA-512 hash. */
+#define RTSHA512_HASH_SIZE 64
+/** The length of a SHA-512 digest string. The terminator is not included. */
+#define RTSHA512_DIGEST_LEN 128
+
+/**
+ * SHA-512 context.
+ */
+typedef union RTSHA512CONTEXT
+{
+ uint64_t u64BetterAlignment;
+ uint8_t abPadding[16 + (80 + 8) * 8];
+#ifdef RT_SHA512_PRIVATE_CONTEXT
+ SHA512_CTX Private;
+#endif
+#ifdef RT_SHA512_PRIVATE_ALT_CONTEXT
+ RTSHA512ALTPRIVATECTX AltPrivate;
+#endif
+} RTSHA512CONTEXT;
+/** Pointer to an SHA-512 context. */
+typedef RTSHA512CONTEXT *PRTSHA512CONTEXT;
+
+/**
+ * Compute the SHA-512 hash of the data.
+ *
+ * @param pvBuf Pointer to the data.
+ * @param cbBuf The amount of data (in bytes).
+ * @param pabHash Where to store the hash. (What is passed is a pointer to
+ * the caller's buffer.)
+ */
+RTDECL(void) RTSha512(const void *pvBuf, size_t cbBuf, uint8_t pabHash[RTSHA512_HASH_SIZE]);
+
+/**
+ * Computes the SHA-512 hash for the given data comparing it with the one given.
+ *
+ * @returns true on match, false on mismatch.
+ * @param pvBuf Pointer to the data.
+ * @param cbBuf The amount of data (in bytes).
+ * @param pabHash The hash to verify. (What is passed is a pointer to the
+ * caller's buffer.)
+ */
+RTDECL(bool) RTSha512Check(const void *pvBuf, size_t cbBuf, uint8_t const pabHash[RTSHA512_HASH_SIZE]);
+
+/**
+ * Initializes the SHA-512 context.
+ *
+ * @param pCtx Pointer to the SHA-512 context.
+ */
+RTDECL(void) RTSha512Init(PRTSHA512CONTEXT pCtx);
+
+/**
+ * Feed data into the SHA-512 computation.
+ *
+ * @param pCtx Pointer to the SHA-512 context.
+ * @param pvBuf Pointer to the data.
+ * @param cbBuf The length of the data (in bytes).
+ */
+RTDECL(void) RTSha512Update(PRTSHA512CONTEXT pCtx, const void *pvBuf, size_t cbBuf);
+
+/**
+ * Compute the SHA-512 hash of the data.
+ *
+ * @param pCtx Pointer to the SHA-512 context.
+ * @param pabHash Where to store the hash. (What is passed is a pointer to
+ * the caller's buffer.)
+ */
+RTDECL(void) RTSha512Final(PRTSHA512CONTEXT pCtx, uint8_t pabHash[RTSHA512_HASH_SIZE]);
+
+/**
+ * Converts a SHA-512 hash to a digest string.
+ *
+ * @returns IPRT status code.
+ *
+ * @param pabHash The binary digest returned by RTSha512Final or RTSha512.
+ * @param pszDigest Where to return the stringified digest.
+ * @param cchDigest The size of the output buffer. Should be at least
+ * RTSHA512_DIGEST_LEN + 1 bytes.
+ */
+RTDECL(int) RTSha512ToString(uint8_t const pabHash[RTSHA512_HASH_SIZE], char *pszDigest, size_t cchDigest);
+
+/**
+ * Converts a SHA-512 hash to a digest string.
+ *
+ * @returns IPRT status code.
+ *
+ * @param pszDigest The stringified digest. Leading and trailing spaces are
+ * ignored.
+ * @param pabHash Where to store the hash. (What is passed is a pointer to
+ * the caller's buffer.)
+ */
+RTDECL(int) RTSha512FromString(char const *pszDigest, uint8_t pabHash[RTSHA512_HASH_SIZE]);
+
+
+/** Macro for declaring the interface for a SHA-512 variation.
+ * @internal */
+#define RTSHA512_DECLARE_VARIANT(a_Name, a_UName) \
+ typedef RTSHA512CONTEXT RT_CONCAT3(RTSHA,a_UName,CONTEXT); \
+ typedef RTSHA512CONTEXT *RT_CONCAT3(PRTSHA,a_UName,CONTEXT); \
+ RTDECL(void) RT_CONCAT(RTSha,a_Name)(const void *pvBuf, size_t cbBuf, uint8_t pabHash[RT_CONCAT3(RTSHA,a_UName,_HASH_SIZE)]); \
+ RTDECL(bool) RT_CONCAT3(RTSha,a_Name,Check)(const void *pvBuf, size_t cbBuf, uint8_t const pabHash[RT_CONCAT3(RTSHA,a_UName,_HASH_SIZE)]); \
+ RTDECL(void) RT_CONCAT3(RTSha,a_Name,Init)(RT_CONCAT3(PRTSHA,a_UName,CONTEXT) pCtx); \
+ RTDECL(void) RT_CONCAT3(RTSha,a_Name,Update)(RT_CONCAT3(PRTSHA,a_UName,CONTEXT) pCtx, const void *pvBuf, size_t cbBuf); \
+ RTDECL(void) RT_CONCAT3(RTSha,a_Name,Final)(RT_CONCAT3(PRTSHA,a_UName,CONTEXT) pCtx, uint8_t pabHash[RT_CONCAT3(RTSHA,a_UName,_HASH_SIZE)]); \
+ RTDECL(int) RT_CONCAT3(RTSha,a_Name,ToString)(uint8_t const pabHash[RT_CONCAT3(RTSHA,a_UName,_HASH_SIZE)], char *pszDigest, size_t cchDigest); \
+ RTDECL(int) RT_CONCAT3(RTSha,a_Name,FromString)(char const *pszDigest, uint8_t pabHash[RT_CONCAT3(RTSHA,a_UName,_HASH_SIZE)])
+
+
+/** The size of a SHA-384 hash. */
+#define RTSHA384_HASH_SIZE 48
+/** The length of a SHA-384 digest string. The terminator is not included. */
+#define RTSHA384_DIGEST_LEN 96
+RTSHA512_DECLARE_VARIANT(384,384);
+
+/** The size of a SHA-512/224 hash. */
+#define RTSHA512T224_HASH_SIZE 28
+/** The length of a SHA-512/224 digest string. The terminator is not
+ * included. */
+#define RTSHA512T224_DIGEST_LEN 56
+RTSHA512_DECLARE_VARIANT(512t224,512T224);
+
+/** The size of a SHA-512/256 hash. */
+#define RTSHA512T256_HASH_SIZE 32
+/** The length of a SHA-512/256 digest string. The terminator is not
+ * included. */
+#define RTSHA512T256_DIGEST_LEN 64
+RTSHA512_DECLARE_VARIANT(512t256,512T256);
+
+
+/**
+ * SHA3 context.
+ */
+typedef union RTSHA3CONTEXT
+{
+ uint64_t a64Padding[26];
+ uint8_t abPadding[208];
+#ifdef RT_SHA3_PRIVATE_CONTEXT
+ RTSHA3PRIVATECTX Private;
+#endif
+#ifdef RT_SHA3_PRIVATE_ALT_CONTEXT
+ RTSHA3ALTPRIVATECTX AltPrivate;
+#endif
+} RTSHA3CONTEXT;
+/** Pointer to an SHA3 context. */
+typedef RTSHA3CONTEXT *PRTSHA3CONTEXT;
+
+/** Macro for declaring the interface for a SHA3 variation.
+ *
+ * @note The interface differes slightly from the older checksums:
+ * - Must call Final and/or Cleanup method.
+ * - Must use Clone instead of memcpy'ing the context.
+ * - Status codes are returned, Init may really fail.
+ *
+ * @internal */
+#define RTSHA3_DECLARE_VARIANT(a_Bits) \
+ typedef struct RT_CONCAT3(RTSHA3T,a_Bits,CONTEXT) { RTSHA3CONTEXT Sha3; } RT_CONCAT3(RTSHA3T,a_Bits,CONTEXT); \
+ typedef RT_CONCAT3(RTSHA3T,a_Bits,CONTEXT) *RT_CONCAT3(PRTSHA3T,a_Bits,CONTEXT); \
+ RTDECL(int) RT_CONCAT(RTSha3t,a_Bits)(const void *pvBuf, size_t cbBuf, uint8_t pabHash[RT_CONCAT3(RTSHA3_,a_Bits,_HASH_SIZE)]); \
+ RTDECL(bool) RT_CONCAT3(RTSha3t,a_Bits,Check)(const void *pvBuf, size_t cbBuf, uint8_t const pabHash[RT_CONCAT3(RTSHA3_,a_Bits,_HASH_SIZE)]); \
+ RTDECL(int) RT_CONCAT3(RTSha3t,a_Bits,Init)(RT_CONCAT3(PRTSHA3T,a_Bits,CONTEXT) pCtx); \
+ RTDECL(int) RT_CONCAT3(RTSha3t,a_Bits,Update)(RT_CONCAT3(PRTSHA3T,a_Bits,CONTEXT) pCtx, const void *pvBuf, size_t cbBuf); \
+ RTDECL(int) RT_CONCAT3(RTSha3t,a_Bits,Final)(RT_CONCAT3(PRTSHA3T,a_Bits,CONTEXT) pCtx, uint8_t pabHash[RT_CONCAT3(RTSHA3_,a_Bits,_HASH_SIZE)]); \
+ RTDECL(int) RT_CONCAT3(RTSha3t,a_Bits,Cleanup)(RT_CONCAT3(PRTSHA3T,a_Bits,CONTEXT) pCtx); \
+ RTDECL(int) RT_CONCAT3(RTSha3t,a_Bits,Clone)(RT_CONCAT3(PRTSHA3T,a_Bits,CONTEXT) pCtx, RT_CONCAT3(RTSHA3T,a_Bits,CONTEXT) const *pCtxSrc); \
+ RTDECL(int) RT_CONCAT3(RTSha3t,a_Bits,ToString)(uint8_t const pabHash[RT_CONCAT3(RTSHA3_,a_Bits,_HASH_SIZE)], char *pszDigest, size_t cchDigest); \
+ RTDECL(int) RT_CONCAT3(RTSha3t,a_Bits,FromString)(char const *pszDigest, uint8_t pabHash[RT_CONCAT3(RTSHA3_,a_Bits,_HASH_SIZE)])
+
+/** The size of a SHA-224 hash. */
+#define RTSHA3_224_HASH_SIZE 28
+/** The length of a SHA-224 digest string. The terminator is not included. */
+#define RTSHA3_224_DIGEST_LEN 56
+RTSHA3_DECLARE_VARIANT(224);
+
+/** The size of a SHA-256 hash. */
+#define RTSHA3_256_HASH_SIZE 32
+/** The length of a SHA-256 digest string. The terminator is not included. */
+#define RTSHA3_256_DIGEST_LEN 64
+RTSHA3_DECLARE_VARIANT(256);
+
+/** The size of a SHA-384 hash. */
+#define RTSHA3_384_HASH_SIZE 48
+/** The length of a SHA-384 digest string. The terminator is not included. */
+#define RTSHA3_384_DIGEST_LEN 96
+RTSHA3_DECLARE_VARIANT(384);
+
+/** The size of a SHA-512 hash. */
+#define RTSHA3_512_HASH_SIZE 64
+/** The length of a SHA-512 digest string. The terminator is not included. */
+#define RTSHA3_512_DIGEST_LEN 128
+RTSHA3_DECLARE_VARIANT(512);
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_sha_h */
+
diff --git a/include/iprt/shmem.h b/include/iprt/shmem.h
new file mode 100644
index 00000000..7ea65f17
--- /dev/null
+++ b/include/iprt/shmem.h
@@ -0,0 +1,180 @@
+/** @file
+ * IPRT - Named shared memory.
+ */
+
+/*
+ * Copyright (C) 2018-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_shmem_h
+#define IPRT_INCLUDED_shmem_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_shmem RTShMem - Shared memory.
+ * @ingroup grp_rt
+ * @{
+ */
+
+/** @name Open flags for RTShMemOpen().
+ * @{
+ */
+/** Creates a new shared memory object or opens an already existing one. */
+#define RTSHMEM_O_F_CREATE RT_BIT_32(0)
+/** Creates a new shared memory object failing if one with the same name exists already. */
+#define RTSHMEM_O_F_CREATE_EXCL (RTSHMEM_O_F_CREATE | RT_BIT_32(1))
+/** Opens the shared memory object for read access. */
+#define RTSHMEM_O_F_READ RT_BIT_32(2)
+/** Opens the shared memory object for write access. */
+#define RTSHMEM_O_F_WRITE RT_BIT_32(3)
+/** Opens the shared memory object for read and write access. */
+#define RTSHMEM_O_F_READWRITE (RTSHMEM_O_F_READ | RTSHMEM_O_F_WRITE)
+/** Truncates the shared memory object to 0 bytes on open. */
+#define RTSHMEM_O_F_TRUNCATE RT_BIT_32(4)
+/** Mappings may be created with executable access right (required to be known on Windows beforehand). */
+#define RTSHMEM_O_F_MAYBE_EXEC RT_BIT_32(5)
+/** Mask of all valid flags. */
+#define RTSHMEM_O_F_VALID_MASK UINT32_C(0x0000003f)
+/** @} */
+
+/**
+ * Creates or opens a new shared memory object with the given name.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_OUT_OF_RANGE if the mapping hint count is too big.
+ * @param phShMem Where to store the handle to the shared memory object on success.
+ * @param pszName Name of the shared memory object to open or create.
+ * @param fFlags Combination of RTSHMEM_O_F_* flags.
+ * @param cbMax Maximum number of bytes to reserve for the shared memory object.
+ * On some platforms this can be 0 and set to another value using RTShMemSetSize() afterwards.
+ * Giving 0 on Windows results in an error as shared memory objects there do not support
+ * changing the size afterwards.
+ * @param cMappingsHint Hint about the possible number of mappings created later on, set to 0 for a default value.
+ */
+RTDECL(int) RTShMemOpen(PRTSHMEM phShMem, const char *pszName, uint32_t fFlags, size_t cbMax, uint32_t cMappingsHint);
+
+/**
+ * Closes the given shared memory object.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_INVALID_STATE if there is still a mapping active for the given shared memory object.
+ * @param hShMem The shared memory object handle.
+ *
+ * @note The shared memory object will be deleted if the creator closes it.
+ */
+RTDECL(int) RTShMemClose(RTSHMEM hShMem);
+
+/**
+ * Tries to delete a shared memory object with the given name.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_NOT_SUPPORTED if the platform does not support deleting the shared memory object by name.
+ * @param pszName Name of the shared memory object to delete.
+ */
+RTDECL(int) RTShMemDelete(const char *pszName);
+
+/**
+ * Returns the number of references (i.e. mappings) held for the given shared memory object.
+ *
+ * @returns Reference count or 0 on invalid handle.
+ * @param hShMem The shared memory object handle.
+ */
+RTDECL(uint32_t) RTShMemRefCount(RTSHMEM hShMem);
+
+/**
+ * Sets the size of the given shared memory object.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_INVALID_STATE if there are mappings active for the given shared memory object.
+ * @retval VERR_NOT_SUPPORTED on some hosts which do not support changing the size after creation.
+ * @param hShMem The shared memory object handle.
+ * @param cbMem Size of the memory object handle in bytes.
+ */
+RTDECL(int) RTShMemSetSize(RTSHMEM hShMem, size_t cbMem);
+
+/**
+ * Queries the current size of the shared memory object.
+ *
+ * @returns IPRT status code.
+ * @param hShMem The shared memory object handle.
+ * @param pcbMem Where to store the size of the shared memory object on success.
+ */
+RTDECL(int) RTShMemQuerySize(RTSHMEM hShMem, size_t *pcbMem);
+
+/** @name Region mapping flags for RTShMemMapRegion().
+ * @{
+ */
+/** Read access. */
+#define RTSHMEM_MAP_F_READ RT_BIT_32(0)
+/** Write access. */
+#define RTSHMEM_MAP_F_WRITE RT_BIT_32(1)
+/** Execute access. */
+#define RTSHMEM_MAP_F_EXEC RT_BIT_32(2)
+/** Copy on write, any write creates a new page private to the callers address space and changes
+ * in that area are not shared with other processes using the hsared memory object. */
+#define RTSHMEM_MAP_F_COW RT_BIT_32(3)
+/** Mask of all valid flags. */
+#define RTSHMEM_MAP_F_VALID_MASK UINT32_C(0x0000000f)
+/** @} */
+
+/**
+ * Maps a region of the given shared memory object into the callers address space.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_SHMEM_MAXIMUM_MAPPINGS_REACHED if the maximum number of mappings was reached (host dependent).
+ * @retval VERR_ACCESS_DENIED if the requested memory access rights do not line up with the flags given when opening
+ * the memory object (requesting write access for a readonly shared memory object for example).
+ * @param hShMem The shared memory object handle.
+ * @param offRegion Offset into the shared memory object to start mapping at.
+ * @param cbRegion Size of the region to map.
+ * @param fFlags Desired properties of the mapped region, combination of RTSHMEM_MAP_F_* defines.
+ * @param ppv Where to store the start address of the mapped region on success.
+ */
+RTDECL(int) RTShMemMapRegion(RTSHMEM hShMem, size_t offRegion, size_t cbRegion, uint32_t fFlags, void **ppv);
+
+/**
+ * Unmaps the given region of the shared memory object.
+ *
+ * @returns IPRT status code.
+ * @param hShMem The shared memory object handle.
+ * @param pv Pointer to the mapped region obtained with RTShMemMapRegion() earlier on.
+ */
+RTDECL(int) RTShMemUnmapRegion(RTSHMEM hShMem, void *pv);
+
+/** @} */
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_shmem_h */
+
diff --git a/include/iprt/socket.h b/include/iprt/socket.h
new file mode 100644
index 00000000..c7a572e7
--- /dev/null
+++ b/include/iprt/socket.h
@@ -0,0 +1,430 @@
+/** @file
+ * IPRT - Network Sockets.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_socket_h
+#define IPRT_INCLUDED_socket_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+#include <iprt/thread.h>
+#include <iprt/net.h>
+#include <iprt/sg.h>
+
+#ifdef IN_RING0
+# error "There are no RTSocket APIs available Ring-0 Host Context!"
+#endif
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_socket RTSocket - Network Sockets
+ * @ingroup grp_rt
+ * @{
+ */
+
+/** Use the system default timeout for the connet attempt. */
+#define RT_SOCKETCONNECT_DEFAULT_WAIT (RT_INDEFINITE_WAIT - 1)
+
+/**
+ * Retains a reference to the socket handle.
+ *
+ * @returns New reference count, UINT32_MAX on invalid handle (asserted).
+ *
+ * @param hSocket The socket handle.
+ */
+RTDECL(uint32_t) RTSocketRetain(RTSOCKET hSocket);
+
+/**
+ * Release a reference to the socket handle.
+ *
+ * When the reference count reaches zero, the socket handle is shut down and
+ * destroyed. This will not be graceful shutdown, use the protocol specific
+ * close method if this is desired.
+ *
+ * @returns New reference count, UINT32_MAX on invalid handle (asserted).
+ *
+ * @param hSocket The socket handle. The NIL handle is quietly
+ * ignored and 0 is returned.
+ */
+RTDECL(uint32_t) RTSocketRelease(RTSOCKET hSocket);
+
+/**
+ * Shuts down the socket, close it and then release one handle reference.
+ *
+ * This is slightly different from RTSocketRelease which will first do the
+ * shutting down and closing when the reference count reaches zero.
+ *
+ * @returns IPRT status code.
+ * @param hSocket The socket handle. NIL is ignored.
+ *
+ * @remarks This will not perform a graceful shutdown of the socket, it will
+ * just destroy it. Use the protocol specific close method if this is
+ * desired.
+ */
+RTDECL(int) RTSocketClose(RTSOCKET hSocket);
+
+/**
+ * Creates an IPRT socket handle from a native one.
+ *
+ * Do NOT use the native handle after passing it to this function, IPRT owns it
+ * and might even have closed upon a successful return.
+ *
+ * @returns IPRT status code.
+ * @param phSocket Where to store the IPRT socket handle.
+ * @param uNative The native handle.
+ */
+RTDECL(int) RTSocketFromNative(PRTSOCKET phSocket, RTHCINTPTR uNative);
+
+/**
+ * Gets the native socket handle.
+ *
+ * @returns The native socket handle or RTHCUINTPTR_MAX if not invalid.
+ * @param hSocket The socket handle.
+ */
+RTDECL(RTHCUINTPTR) RTSocketToNative(RTSOCKET hSocket);
+
+/**
+ * Helper that ensures the correct inheritability of a socket.
+ *
+ * We're currently ignoring failures.
+ *
+ * @returns IPRT status code
+ * @param hSocket The socket handle.
+ * @param fInheritable The desired inheritability state.
+ */
+RTDECL(int) RTSocketSetInheritance(RTSOCKET hSocket, bool fInheritable);
+
+/**
+ * Parse Internet style addresses, getting a generic IPRT network address.
+ *
+ * @returns IPRT status code
+ * @param pszAddress Name or IP address. NULL or empty string (no
+ * spaces) is taken to mean INADDR_ANY, which is
+ * meaningful when binding a server socket for
+ * instance.
+ * @param uPort Port number (host byte order).
+ * @param pAddr Where to return the generic IPRT network address.
+ */
+RTDECL(int) RTSocketParseInetAddress(const char *pszAddress, unsigned uPort, PRTNETADDR pAddr);
+
+/**
+ * Try resolve a host name, returning the first matching address.
+ *
+ * @returns IPRT status code.
+ * @param pszHost Name or IP address to look up.
+ * @param pszAddress Where to return the stringified address.
+ * @param pcbAddress Input: The size of the @a pszResult buffer.
+ * Output: size of the returned string. This is set on
+ * VERR_BUFFER_OVERFLOW and most other error statuses.
+ * @param penmAddrType Input: Which kind of address to return. Valid values
+ * are:
+ * - RTNETADDRTYPE_IPV4 -> lookup AF_INET.
+ * - RTNETADDRTYPE_IPV6 -> lookup AF_INET6.
+ * - RTNETADDRTYPE_INVALID/NULL -> lookup anything.
+ * Output: The type of address that is being returned.
+ * Not modified on failure.
+ */
+RTDECL(int) RTSocketQueryAddressStr(const char *pszHost, char *pszAddress, size_t *pcbAddress, PRTNETADDRTYPE penmAddrType);
+
+/**
+ * Receive data from a socket.
+ *
+ * @returns IPRT status code.
+ * @param hSocket The socket handle.
+ * @param pvBuffer Where to put the data we read.
+ * @param cbBuffer Read buffer size.
+ * @param pcbRead Number of bytes read. If NULL the entire buffer
+ * will be filled upon successful return. If not NULL a
+ * partial read can be done successfully.
+ */
+RTDECL(int) RTSocketRead(RTSOCKET hSocket, void *pvBuffer, size_t cbBuffer, size_t *pcbRead);
+
+/**
+ * Receive data from a socket, including sender address. Mainly useful
+ * for datagram sockets.
+ *
+ * @returns IPRT status code.
+ * @param hSocket The socket handle.
+ * @param pvBuffer Where to put the data we read.
+ * @param cbBuffer Read buffer size.
+ * @param pcbRead Number of bytes read. Must be non-NULL.
+ * @param pSrcAddr Pointer to sender address buffer. May be NULL.
+ */
+RTDECL(int) RTSocketReadFrom(RTSOCKET hSocket, void *pvBuffer, size_t cbBuffer, size_t *pcbRead, PRTNETADDR pSrcAddr);
+
+/**
+ * Send data to a socket.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_INTERRUPTED if interrupted before anything was written.
+ *
+ * @param hSocket The socket handle.
+ * @param pvBuffer Buffer to write data to socket.
+ * @param cbBuffer How much to write.
+ */
+RTDECL(int) RTSocketWrite(RTSOCKET hSocket, const void *pvBuffer, size_t cbBuffer);
+
+/**
+ * Send data to a socket, including destination address. Mainly useful
+ * for datagram sockets.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_INTERRUPTED if interrupted before anything was written.
+ *
+ * @param hSocket The socket handle.
+ * @param pvBuffer Buffer to write data to socket.
+ * @param cbBuffer How much to write.
+ * @param pDstAddr Pointer to destination address. May be NULL.
+ */
+RTDECL(int) RTSocketWriteTo(RTSOCKET hSocket, const void *pvBuffer, size_t cbBuffer, PCRTNETADDR pDstAddr);
+
+/**
+ * Checks if the socket is ready for reading (for I/O multiplexing).
+ *
+ * @returns IPRT status code.
+ * @param hSocket The socket handle.
+ * @param cMillies Number of milliseconds to wait for the socket. Use
+ * RT_INDEFINITE_WAIT to wait for ever.
+ */
+RTDECL(int) RTSocketSelectOne(RTSOCKET hSocket, RTMSINTERVAL cMillies);
+
+/** @name Select events
+ * @{ */
+/** Readable without blocking. */
+#define RTSOCKET_EVT_READ RT_BIT_32(0)
+/** Writable without blocking. */
+#define RTSOCKET_EVT_WRITE RT_BIT_32(1)
+/** Error condition, hangup, exception or similar. */
+#define RTSOCKET_EVT_ERROR RT_BIT_32(2)
+/** Mask of the valid bits. */
+#define RTSOCKET_EVT_VALID_MASK UINT32_C(0x00000007)
+/** @} */
+
+/**
+ * Socket I/O multiplexing
+ * Checks if the socket is ready for one of the given events.
+ *
+ * @returns iprt status code.
+ * @param hSocket The Socket handle.
+ * @param fEvents Event mask to wait for.
+ * @param pfEvents Where to store the event mask on return.
+ * @param cMillies Number of milliseconds to wait for the socket. Use
+ * RT_INDEFINITE_WAIT to wait for ever.
+ */
+RTR3DECL(int) RTSocketSelectOneEx(RTSOCKET hSocket, uint32_t fEvents, uint32_t *pfEvents, RTMSINTERVAL cMillies);
+
+/**
+ * Shuts down one or both directions of communciation.
+ *
+ * @returns IPRT status code.
+ * @param hSocket The socket handle.
+ * @param fRead Whether to shutdown our read direction.
+ * @param fWrite Whether to shutdown our write direction.
+ */
+RTDECL(int) RTSocketShutdown(RTSOCKET hSocket, bool fRead, bool fWrite);
+
+/**
+ * Gets the address of the local side.
+ *
+ * @returns IPRT status code.
+ * @param hSocket The Socket handle.
+ * @param pAddr Where to store the local address on success.
+ */
+RTDECL(int) RTSocketGetLocalAddress(RTSOCKET hSocket, PRTNETADDR pAddr);
+
+/**
+ * Gets the address of the other party.
+ *
+ * @returns IPRT status code.
+ * @param hSocket The Socket handle.
+ * @param pAddr Where to store the peer address on success.
+ */
+RTDECL(int) RTSocketGetPeerAddress(RTSOCKET hSocket, PRTNETADDR pAddr);
+
+/**
+ * Send data from a scatter/gather buffer to a socket.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_INTERRUPTED if interrupted before anything was written.
+ *
+ * @param hSocket The socket handle.
+ * @param pSgBuf Scatter/gather buffer to write data to socket.
+ */
+RTDECL(int) RTSocketSgWrite(RTSOCKET hSocket, PCRTSGBUF pSgBuf);
+
+/**
+ * Send data from multiple buffers to a socket.
+ *
+ * This is convenience wrapper around the RTSocketSgWrite and RTSgBufInit calls
+ * for lazy coders. The "L" in the function name is short for "list" just like
+ * in the execl libc API.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_INTERRUPTED if interrupted before anything was written.
+ *
+ * @param hSocket The socket handle.
+ * @param cSegs The number of data segments in the following
+ * ellipsis.
+ * @param ... Pairs of buffer pointers (void const *) and buffer
+ * sizes (size_t). Make 101% sure the pointer is
+ * really size_t.
+ */
+RTDECL(int) RTSocketSgWriteL(RTSOCKET hSocket, size_t cSegs, ...);
+
+/**
+ * Send data from multiple buffers to a socket.
+ *
+ * This is convenience wrapper around the RTSocketSgWrite and RTSgBufInit calls
+ * for lazy coders. The "L" in the function name is short for "list" just like
+ * in the execl libc API.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_INTERRUPTED if interrupted before anything was written.
+ *
+ * @param hSocket The socket handle.
+ * @param cSegs The number of data segments in the following
+ * argument list.
+ * @param va Pairs of buffer pointers (void const *) and buffer
+ * sizes (size_t). Make 101% sure the pointer is
+ * really size_t.
+ */
+RTDECL(int) RTSocketSgWriteLV(RTSOCKET hSocket, size_t cSegs, va_list va);
+
+/**
+ * Receive data from a socket.
+ *
+ * This version doesn't block if there is no data on the socket.
+ *
+ * @returns IPRT status code.
+ *
+ * @param hSocket The socket handle.
+ * @param pvBuffer Where to put the data we read.
+ * @param cbBuffer Read buffer size.
+ * @param pcbRead Number of bytes read.
+ */
+RTDECL(int) RTSocketReadNB(RTSOCKET hSocket, void *pvBuffer, size_t cbBuffer, size_t *pcbRead);
+
+/**
+ * Send data to a socket.
+ *
+ * This version doesn't block if there is not enough room for the message.
+ *
+ * @returns IPRT status code.
+ *
+ * @param hSocket The socket handle.
+ * @param pvBuffer Buffer to write data to socket.
+ * @param cbBuffer How much to write.
+ * @param pcbWritten Number of bytes written.
+ */
+RTDECL(int) RTSocketWriteNB(RTSOCKET hSocket, const void *pvBuffer, size_t cbBuffer, size_t *pcbWritten);
+
+/**
+ * Send data to a socket, including destination address. Mainly useful
+ * for datagram sockets.
+ *
+ * This version doesn't block if there is not enough room for the message.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_INTERRUPTED if interrupted before anything was written.
+ *
+ * @param hSocket The socket handle.
+ * @param pvBuffer Buffer to write data to socket.
+ * @param cbBuffer How much to write.
+ * @param pDstAddr Pointer to destination address. May be NULL.
+ */
+RTDECL(int) RTSocketWriteToNB(RTSOCKET hSocket, const void *pvBuffer, size_t cbBuffer, PCRTNETADDR pDstAddr);
+
+/**
+ * Send data from a scatter/gather buffer to a socket.
+ *
+ * This version doesn't block if there is not enough room for the message.
+ *
+ * @returns iprt status code.
+ *
+ * @param hSocket The Socket handle.
+ * @param pSgBuf Scatter/gather buffer to write data to socket.
+ * @param pcbWritten Number of bytes written.
+ */
+RTR3DECL(int) RTSocketSgWriteNB(RTSOCKET hSocket, PCRTSGBUF pSgBuf, size_t *pcbWritten);
+
+
+/**
+ * Send data from multiple buffers to a socket.
+ *
+ * This version doesn't block if there is not enough room for the message.
+ * This is convenience wrapper around the RTSocketSgWrite and RTSgBufInit calls
+ * for lazy coders. The "L" in the function name is short for "list" just like
+ * in the execl libc API.
+ *
+ * @returns IPRT status code.
+ *
+ * @param hSocket The socket handle.
+ * @param cSegs The number of data segments in the following
+ * ellipsis.
+ * @param pcbWritten Number of bytes written.
+ * @param ... Pairs of buffer pointers (void const *) and buffer
+ * sizes (size_t). Make 101% sure the pointer is
+ * really size_t.
+ */
+RTR3DECL(int) RTSocketSgWriteLNB(RTSOCKET hSocket, size_t cSegs, size_t *pcbWritten, ...);
+
+/**
+ * Send data from multiple buffers to a socket.
+ *
+ * This version doesn't block if there is not enough room for the message.
+ * This is convenience wrapper around the RTSocketSgWrite and RTSgBufInit calls
+ * for lazy coders. The "L" in the function name is short for "list" just like
+ * in the execl libc API.
+ *
+ * @returns IPRT status code.
+ *
+ * @param hSocket The socket handle.
+ * @param cSegs The number of data segments in the following
+ * argument list.
+ * @param pcbWritten Number of bytes written.
+ * @param va Pairs of buffer pointers (void const *) and buffer
+ * sizes (size_t). Make 101% sure the pointer is
+ * really size_t.
+ */
+RTR3DECL(int) RTSocketSgWriteLVNB(RTSOCKET hSocket, size_t cSegs, size_t *pcbWritten, va_list va);
+
+/** @} */
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_socket_h */
+
diff --git a/include/iprt/solaris/kmoddeps.mac b/include/iprt/solaris/kmoddeps.mac
new file mode 100644
index 00000000..c9ec53e0
--- /dev/null
+++ b/include/iprt/solaris/kmoddeps.mac
@@ -0,0 +1,193 @@
+; $Id: kmoddeps.mac $
+;; @file
+; Assembly macros for generating Solaris kernel module dependencies
+;
+
+;
+; Copyright (C) 2012-2022 Oracle and/or its affiliates.
+;
+; This file is part of VirtualBox base platform packages, as
+; available from https://www.virtualbox.org.
+;
+; This program is free software; you can redistribute it and/or
+; modify it under the terms of the GNU General Public License
+; as published by the Free Software Foundation, in version 3 of the
+; License.
+;
+; This program is distributed in the hope that it will be useful, but
+; WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with this program; if not, see <https://www.gnu.org/licenses>.
+;
+; The contents of this file may alternatively be used under the terms
+; of the Common Development and Distribution License Version 1.0
+; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+; in the VirtualBox 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.
+;
+; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+;
+
+; Solaris kernel modules use non-standard ELF constructions to express inter-
+; module dependencies, namely a DT_NEEDED tag inside a relocatable ELF file.
+; The Solaris linker can generate these automatically; since yasm can't
+; produce an ELF file which quite fits Solaris's requirements we create one
+; manually using flat binary output format. In order to save unnecessary
+; repetition, this file defines macros for the repetitive bits which can be
+; reused by the actual dependency objects. Certainly not the nicest way to
+; get the effect we want, but probably a reasonable compromise between
+; cleanness and required effort.
+;
+
+%ifdef RT_ARCH_AMD64
+
+BITS 64
+;;
+; Native word size
+%define DNAT dq
+
+;;
+; ELF machine number for the current architecture.
+%define EM_CUR 62 ; EM_X86_64
+
+;;
+; ELF header class for the current architecture.
+%define CLASS 2
+
+%else
+
+BITS 32
+%define DNAT dd
+%define EM_CUR 3 ; EM_386
+%define CLASS 1
+
+%endif
+
+;;
+; ELF file header, section tables and shared string table for the dependency
+; object.
+%macro kmoddeps_header 0
+elf_hdr: ; elfxx_hdr structure
+ db 7fh, "ELF" ; e_ident
+ db CLASS, 1, 1 ; e_ident
+ times 9 db 0 ; padding
+ dw 1 ; e_type ET_REL
+ dw EM_CUR ; e_machine
+ dd 1 ; e_version EV_CURRENT
+ DNAT 0 ; e_entry
+ DNAT 0 ; e_phoff
+ DNAT sect_hdr - $$ ; e_shoff
+ dd 0 ; e_flags
+ dw elf_hsize ; e_ehsize
+ dw 0 ; e_phentsize
+ dw 0 ; e_phnum
+ dw sect_hsize ; e_shentsize
+ dw 4 ; e_shnum
+ dw 1 ; e_shstrndx section .shstrtab
+elf_hsize equ $ - elf_hdr
+
+sect_hdr: ; elfxx_shdr structure
+ times sect_hsize db 0 ; undefined section
+
+sect_hdr1:
+ dd str_shstrtab ; sh_name .shstrtab
+ dd 3 ; sh_type SHT_STRTAB
+ DNAT 20h ; sh_flags SHF_STRINGS
+ DNAT 0 ; sh_addr
+ DNAT shstrtab - $$ ; sh_offset
+ DNAT shstrtab_size ; sh_size
+ dd 0 ; sh_link
+ dd 0 ; sh_info
+ DNAT 1 ; sh_addralign
+ DNAT 0 ; sh_entsize
+sect_hsize equ $ - sect_hdr1
+
+ dd str_dynstr ; sh_name .dynstr
+ dd 3 ; sh_type SHT_STRTAB
+ DNAT 20h ; sh_flags SHF_STRINGS
+ DNAT 0 ; sh_addr
+ DNAT dynstr - $$ ; sh_offset
+ DNAT dynstr_size ; sh_size
+ dd 0 ; sh_link
+ dd 0 ; sh_info
+ DNAT 1 ; sh_addralign
+ DNAT 0 ; sh_entsize
+
+ dd str_dynamic ; sh_name .dynamic
+ dd 6 ; sh_type SHT_DYNAMIC
+ DNAT 1 ; sh_flags SHF_WRITE
+ DNAT 0 ; sh_addr
+ DNAT dynamic - $$ ; sh_offset
+ DNAT dynamic_size ; sh_size
+ dd 2 ; sh_link .dynstr
+ dd 0 ; sh_info
+ DNAT 8 ; sh_addralign
+ DNAT 0 ; sh_entsize
+
+shstrtab:
+str_shstrtab equ $ - shstrtab
+ db ".shstrtab", 0
+str_dynstr equ $ - shstrtab
+ db ".dynstr", 0
+str_dynamic equ $ - shstrtab
+ db ".dynamic", 0
+shstrtab_size equ $ - shstrtab
+%endmacro ; kmoddeps_header
+
+;;
+; Start of the .dynstr section for the dependency object.
+%macro kmoddeps_dynstr_start 0
+dynstr:
+ db 0
+%endmacro
+
+;;
+; A .dynstr string entry for the dependency object.
+; The parameters are a symbolic name for the string and the string itself.
+%macro kmoddeps_dynstr_string 2
+dynstr_name_%1 equ $ - dynstr
+ db %2, 0
+%endmacro
+
+;;
+; End of the .dynstr section for the dependency object.
+%macro kmoddeps_dynstr_end 0
+dynstr_size equ $ - dynstr
+%endmacro
+
+;;
+; Start of the .dynamic section for the dependency object.
+%macro kmoddeps_dynamic_start 0
+dynamic:
+%endmacro
+
+;;
+; A .dynamic DT_NEEDED entry for the dependency object.
+; The parameter is a symbolic string name previously defined using
+; @a kmoddeps_dynstr_string.
+%macro kmoddeps_dynamic_needed 1
+ DNAT 1 ; DT_NEEDED
+ DNAT dynstr_name_%1
+%endmacro
+
+;;
+; End of the .dynamic section for the dependency object.
+%macro kmoddeps_dynamic_end 0
+ DNAT 1ah ; DT_FLAGS
+ DNAT 4 ; TEXTREL
+ DNAT 6ffffffbh ; DT_FLAGS1
+ DNAT 0
+ DNAT 601900h ; SUNW_STRPAD
+ DNAT 200h
+ DNAT 601b00h ; SUNW_LDMACH
+ DNAT 62 ; EM_X86_64
+ times 22 DNAT 0 ; padding
+dynamic_size equ $ - dynamic
+%endmacro ; kmoddeps_dynamic_end
+
diff --git a/include/iprt/sort.h b/include/iprt/sort.h
new file mode 100644
index 00000000..4e5d47de
--- /dev/null
+++ b/include/iprt/sort.h
@@ -0,0 +1,141 @@
+/** @file
+ * IPRT - Sorting.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_sort_h
+#define IPRT_INCLUDED_sort_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+
+/** @defgroup grp_rt_sort RTSort - Sorting Algorithms
+ * @ingroup grp_rt
+ * @{ */
+
+RT_C_DECLS_BEGIN
+
+/**
+ * Callback for comparing two array elements.
+ *
+ * @retval 0 if equal.
+ * @retval -1 if @a pvElement1 comes before @a pvElement2.
+ * @retval 1 if @a pvElement1 comes after @a pvElement2.
+ *
+ * @param pvElement1 The 1st element.
+ * @param pvElement2 The 2nd element.
+ * @param pvUser The user argument passed to the sorting function.
+ */
+typedef DECLCALLBACKTYPE(int, FNRTSORTCMP,(void const *pvElement1, void const *pvElement2, void *pvUser));
+/** Pointer to a compare function. */
+typedef FNRTSORTCMP *PFNRTSORTCMP;
+
+/**
+ * Sorter function for an array of variable sized elementes.
+ *
+ * @param pvArray The array to sort.
+ * @param cElements The number of elements in the array.
+ * @param cbElement The size of an array element.
+ * @param pfnCmp Callback function comparing two elements.
+ * @param pvUser User argument for the callback.
+ */
+typedef DECLCALLBACKTYPE(void, FNRTSORT,(void *pvArray, size_t cElements, size_t cbElement, PFNRTSORTCMP pfnCmp, void *pvUser));
+/** Pointer to a sorter function for an array of variable sized elements. */
+typedef FNRTSORT *PFNRTSORT;
+
+/**
+ * Pointer array sorter function.
+ *
+ * @param papvArray The array to sort.
+ * @param cElements The number of elements in the array.
+ * @param pfnCmp Callback function comparing two elements.
+ * @param pvUser User argument for the callback.
+ */
+typedef DECLCALLBACKTYPE(void, FNRTSORTAPV,(void **papvArray, size_t cElements, PFNRTSORTCMP pfnCmp, void *pvUser));
+/** Pointer to a pointer array sorter function. */
+typedef FNRTSORTAPV *PFNRTSORTAPV;
+
+/**
+ * Shell sort an array of variable sized elementes.
+ *
+ * @param pvArray The array to sort.
+ * @param cElements The number of elements in the array.
+ * @param cbElement The size of an array element.
+ * @param pfnCmp Callback function comparing two elements.
+ * @param pvUser User argument for the callback.
+ */
+RTDECL(void) RTSortShell(void *pvArray, size_t cElements, size_t cbElement, PFNRTSORTCMP pfnCmp, void *pvUser);
+
+/**
+ * Same as RTSortShell but speciallized for an array containing element
+ * pointers.
+ *
+ * @param papvArray The array to sort.
+ * @param cElements The number of elements in the array.
+ * @param pfnCmp Callback function comparing two elements.
+ * @param pvUser User argument for the callback.
+ */
+RTDECL(void) RTSortApvShell(void **papvArray, size_t cElements, PFNRTSORTCMP pfnCmp, void *pvUser);
+
+/**
+ * Checks if an array of variable sized elementes is sorted.
+ *
+ * @returns true if it is sorted, false if it isn't.
+ * @param pvArray The array to check.
+ * @param cElements The number of elements in the array.
+ * @param cbElement The size of an array element.
+ * @param pfnCmp Callback function comparing two elements.
+ * @param pvUser User argument for the callback.
+ */
+RTDECL(bool) RTSortIsSorted(void const *pvArray, size_t cElements, size_t cbElement, PFNRTSORTCMP pfnCmp, void *pvUser);
+
+/**
+ * Same as RTSortShell but speciallized for an array containing element
+ * pointers.
+ *
+ * @returns true if it is sorted, false if it isn't.
+ * @param papvArray The array to check.
+ * @param cElements The number of elements in the array.
+ * @param pfnCmp Callback function comparing two elements.
+ * @param pvUser User argument for the callback.
+ */
+RTDECL(bool) RTSortApvIsSorted(void const * const *papvArray, size_t cElements, PFNRTSORTCMP pfnCmp, void *pvUser);
+
+RT_C_DECLS_END
+
+/** @} */
+
+#endif /* !IPRT_INCLUDED_sort_h */
+
diff --git a/include/iprt/spinlock.h b/include/iprt/spinlock.h
new file mode 100644
index 00000000..683be325
--- /dev/null
+++ b/include/iprt/spinlock.h
@@ -0,0 +1,105 @@
+/** @file
+ * IPRT - Spinlocks.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_spinlock_h
+#define IPRT_INCLUDED_spinlock_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#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 /* !IPRT_INCLUDED_spinlock_h */
+
diff --git a/include/iprt/stdarg.h b/include/iprt/stdarg.h
new file mode 100644
index 00000000..9d12cd8b
--- /dev/null
+++ b/include/iprt/stdarg.h
@@ -0,0 +1,79 @@
+/** @file
+ * IPRT - stdarg.h wrapper.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_stdarg_h
+#define IPRT_INCLUDED_stdarg_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#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
+# elif defined(RT_OS_LINUX) && defined(IN_RING0)
+# include "linux/version.h"
+# if RTLNX_VER_MIN(5,15,0) || RTLNX_RHEL_MAJ_PREREQ(9,1)
+# include <linux/stdarg.h>
+# else
+# include <stdarg.h>
+# endif
+# else
+# include <stdarg.h>
+# endif
+#endif
+
+/*
+ * Older MSC versions doesn't implement va_copy. Newer (12.0+?) ones does
+ * implement it like below, but for now it's easier to continue like for the
+ * older ones so we can more easily handle R0, RC and other weird contexts.
+ */
+#if !defined(va_copy) || defined(_MSC_VER)
+# undef va_copy
+# define va_copy(dst, src) do { (dst) = (src); } while (0) /** @todo check AMD64 */
+#endif
+
+#endif /* !IPRT_INCLUDED_stdarg_h */
+
diff --git a/include/iprt/stdint.h b/include/iprt/stdint.h
new file mode 100644
index 00000000..c76e5c6f
--- /dev/null
+++ b/include/iprt/stdint.h
@@ -0,0 +1,349 @@
+/** @file
+ * IPRT - stdint.h wrapper (for backlevel compilers like MSC).
+ */
+
+/*
+ * Copyright (C) 2009-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_stdint_h
+#define IPRT_INCLUDED_stdint_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#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_ARM32) || defined(RT_ARCH_ARM64) \
+ || 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
+
+ /* smallest minimum-width integer types - assumes to be the same as above! */
+typedef int8_t int_least8_t;
+typedef uint8_t uint_least8_t;
+# define INT_LEAST8_MIN INT8_MIN
+# define INT_LEAST8_MAX INT8_MAX
+# define UINT_LEAST8_MAX UINT8_MAX
+typedef int16_t int_least16_t;
+typedef uint16_t uint_least16_t;
+# define INT_LEAST16_MIN INT16_MIN
+# define INT_LEAST16_MAX INT16_MAX
+# define UINT_LEAST16_MAX UINT16_MAX
+typedef int32_t int_least32_t;
+typedef uint32_t uint_least32_t;
+# define INT_LEAST32_MIN INT32_MIN
+# define INT_LEAST32_MAX INT32_MAX
+# define UINT_LEAST32_MAX UINT32_MAX
+typedef int64_t int_least64_t;
+typedef uint64_t uint_least64_t;
+# define INT_LEAST64_MIN INT64_MIN
+# define INT_LEAST64_MAX INT64_MAX
+# define UINT_LEAST64_MAX UINT64_MAX
+
+ /* fastest minimum-width integer types */
+typedef signed char int_fast8_t;
+typedef unsigned char uint_fast8_t;
+# define INT_FAST8_MIN INT8_MIN
+# define INT_FAST8_MAX INT8_MAX
+# define UINT_FAST8_MAX UINT8_MAX
+typedef signed int int_fast16_t;
+typedef unsigned int uint_fast16_t;
+# if ARCH_BITS == 16
+# define INT_FAST16_MIN INT16_MIN
+# define INT_FAST16_MAX INT16_MAX
+# define UINT_FAST16_MAX UINT16_MAX
+# else
+# define INT_FAST16_MIN INT32_MIN
+# define INT_FAST16_MAX INT32_MAX
+# define UINT_FAST16_MAX UINT32_MAX
+# endif
+typedef int32_t int_fast32_t;
+typedef uint32_t uint_fast32_t;
+# define INT_FAST32_MIN INT32_MIN
+# define INT_FAST32_MAX INT32_MAX
+# define UINT_FAST32_MAX UINT32_MAX
+typedef int64_t int_fast64_t;
+typedef uint64_t uint_fast64_t;
+# define INT_FAST64_MIN INT64_MIN
+# define INT_FAST64_MAX INT64_MAX
+# define UINT_FAST64_MAX UINT64_MAX
+
+# 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(__WATCOMC__)) || defined(DOXYGEN_RUNNING)
+# if ARCH_BITS == 32 \
+ || defined(RT_OS_LINUX) \
+ || defined(RT_OS_FREEBSD)
+# if !defined(_INTPTR_T_DECLARED) && !defined(_INTPTR_T) && !defined(_INTPTR_T_DEFINED)
+typedef signed long intptr_t;
+# endif
+# if !defined(_UINTPTR_T_DECLARED) && !defined(_UINTPTR_T) && !defined(_UINTPTR_T_DEFINED)
+typedef unsigned long uintptr_t;
+# endif
+# else
+# if !defined(_INTPTR_T_DECLARED) && !defined(_INTPTR_T) && !defined(_INTPTR_T_DEFINED)
+typedef int64_t intptr_t;
+# endif
+# if !defined(_UINTPTR_T_DECLARED) && !defined(_UINTPTR_T) && !defined(_UINTPTR_T_DEFINED)
+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 /* !IPRT_INCLUDED_stdint_h */
+
diff --git a/include/iprt/strcache.h b/include/iprt/strcache.h
new file mode 100644
index 00000000..a94fa616
--- /dev/null
+++ b/include/iprt/strcache.h
@@ -0,0 +1,201 @@
+/* $Id: strcache.h $ */
+/** @file
+ * IPRT - String Cache, stub implementation.
+ */
+
+/*
+ * Copyright (C) 2009-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_strcache_h
+#define IPRT_INCLUDED_strcache_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+
+RT_C_DECLS_BEGIN
+
+
+/**
+ * Create a new string cache.
+ *
+ * @returns IPRT status code
+ *
+ * @param phStrCache Where to return the string cache handle.
+ * @param pszName The name of the cache (for debug purposes).
+ */
+RTDECL(int) RTStrCacheCreate(PRTSTRCACHE phStrCache, const char *pszName);
+
+
+/**
+ * Destroys a string cache.
+ *
+ * This will cause all strings in the cache to be released and thus become
+ * invalid.
+ *
+ * @returns IPRT status.
+ *
+ * @param hStrCache Handle to the string cache. The nil and default
+ * handles are ignored quietly (VINF_SUCCESS).
+ */
+RTDECL(int) RTStrCacheDestroy(RTSTRCACHE hStrCache);
+
+
+/**
+ * Enters a string into the cache.
+ *
+ * @returns Pointer to a read-only copy of the string.
+ *
+ * @param hStrCache Handle to the string cache.
+ * @param pchString Pointer to a string. This does not need to be
+ * zero terminated, but must not contain any zero
+ * characters.
+ * @param cchString The number of characters (bytes) to enter.
+ *
+ * @remarks It is implementation dependent whether the returned string pointer
+ * differs when entering the same string twice.
+ */
+RTDECL(const char *) RTStrCacheEnterN(RTSTRCACHE hStrCache, const char *pchString, size_t cchString);
+
+/**
+ * Enters a string into the cache.
+ *
+ * @returns Pointer to a read-only copy of the string.
+ *
+ * @param hStrCache Handle to the string cache.
+ * @param psz Pointer to a zero terminated string.
+ *
+ * @remarks See RTStrCacheEnterN.
+ */
+RTDECL(const char *) RTStrCacheEnter(RTSTRCACHE hStrCache, const char *psz);
+
+
+/**
+ * Enters a string into the cache in lower cased form.
+ *
+ * @returns Pointer to a read-only lower cased copy of the string.
+ *
+ * @param hStrCache Handle to the string cache.
+ * @param pchString Pointer to a string. This does not need to be
+ * zero terminated, but must not contain any zero
+ * characters.
+ * @param cchString The number of characters (bytes) to enter.
+ *
+ * @remarks It is implementation dependent whether the returned string pointer
+ * differs when entering the same string twice.
+ */
+RTDECL(const char *) RTStrCacheEnterLowerN(RTSTRCACHE hStrCache, const char *pchString, size_t cchString);
+
+/**
+ * Enters a string into the cache in lower cased form.
+ *
+ * @returns Pointer to a read-only lower cased copy of the string.
+ *
+ * @param hStrCache Handle to the string cache.
+ * @param psz Pointer to a zero terminated string.
+ *
+ * @remarks See RTStrCacheEnterN.
+ */
+RTDECL(const char *) RTStrCacheEnterLower(RTSTRCACHE hStrCache, const char *psz);
+
+
+/**
+ * Retains a reference to a string.
+ *
+ * @returns The new reference count. UINT32_MAX is returned if the string
+ * pointer is invalid.
+ */
+RTDECL(uint32_t) RTStrCacheRetain(const char *psz);
+
+/**
+ * Releases a reference to a string.
+ *
+ * @returns The new reference count.
+ * UINT32_MAX is returned if the string pointer is invalid.
+ *
+ * @param hStrCache Handle to the string cache. NIL is NOT allowed.
+ * @param psz Pointer to a cached string.
+ */
+RTDECL(uint32_t) RTStrCacheRelease(RTSTRCACHE hStrCache, const char *psz);
+
+/**
+ * Gets the string length of a cache entry.
+ *
+ * @returns The string length. 0 if the string is invalid (asserted).
+ *
+ * @param psz Pointer to a cached string.
+ */
+RTDECL(size_t) RTStrCacheLength(const char *psz);
+
+
+/**
+ * Gets cache statistics.
+ *
+ * All parameters, except @a hStrCache, are optional and can be NULL.
+ *
+ * @returns Number of strings, UINT32_MAX on failure (or not supported).
+ * @param hStrCache Handle to the string cache.
+ * @param pcbStrings The number of string bytes (including
+ * terminators) .
+ * @param pcbChunks Amount of memory we've allocated for the
+ * internal allocator.
+ * @param pcbBigEntries Amount of memory we've allocated off the heap
+ * for really long strings that doesn't fit in the
+ * internal allocator.
+ * @param pcHashCollisions Number of hash table insert collisions.
+ * @param pcHashCollisions2 Number of hash table secondary insert
+ * collisions.
+ * @param pcHashInserts Number of hash table inserts.
+ * @param pcRehashes The number of rehashes.
+ *
+ * @remarks This is not a stable interface as it needs to reflect the cache
+ * implementation.
+ */
+RTDECL(uint32_t) RTStrCacheGetStats(RTSTRCACHE hStrCache, size_t *pcbStrings, size_t *pcbChunks, size_t *pcbBigEntries,
+ uint32_t *pcHashCollisions, uint32_t *pcHashCollisions2, uint32_t *pcHashInserts,
+ uint32_t *pcRehashes);
+
+/**
+ * Indicates whether this a real string cache or a cheap place holder.
+ *
+ * A real string cache will return the same address when a string is added
+ * multiple times.
+ *
+ * @returns true / false.
+ */
+RTDECL(bool) RTStrCacheIsRealImpl(void);
+
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_strcache_h */
+
diff --git a/include/iprt/stream.h b/include/iprt/stream.h
new file mode 100644
index 00000000..927fd63a
--- /dev/null
+++ b/include/iprt/stream.h
@@ -0,0 +1,542 @@
+/** @file
+ * IPRT - I/O Stream.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_stream_h
+#define IPRT_INCLUDED_stream_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+#include <iprt/stdarg.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_stream RTStrm - File Streams
+ * @ingroup grp_rt
+ * @{
+ */
+
+#ifndef IPRT_INCLUDED_message_h
+/** Pointer to a stream. */
+typedef struct RTSTREAM *PRTSTREAM;
+#endif
+
+/** Pointer to the standard input stream. */
+extern RTDATADECL(PRTSTREAM) g_pStdIn;
+
+/** Pointer to the standard error stream. */
+extern RTDATADECL(PRTSTREAM) g_pStdErr;
+
+/** Pointer to the standard output stream. */
+extern RTDATADECL(PRTSTREAM) g_pStdOut;
+
+
+/**
+ * Opens a file stream.
+ *
+ * @returns iprt status code.
+ * @param pszFilename Path to the file to open.
+ * @param pszMode The open mode. See fopen() standard.
+ * Format: <a|r|w>[+][b|t][x][e|N|E]
+ * - 'a': Open or create file and writes
+ * append tos it.
+ * - 'r': Open existing file and read from it.
+ * - 'w': Open or truncate existing file and write
+ * to it.
+ * - '+': Open for both read and write access.
+ * - 'b' / 't': binary / text
+ * - 'x': exclusively create, no open. Only
+ * possible with 'w'.
+ * - 'e' / 'N': No inherit on exec. (The 'e' is
+ * how Linux and FreeBSD expresses this, the
+ * latter is Visual C++).
+ * @param ppStream Where to store the opened stream.
+ */
+RTR3DECL(int) RTStrmOpen(const char *pszFilename, const char *pszMode, PRTSTREAM *ppStream);
+
+/**
+ * Opens a file stream.
+ *
+ * @returns iprt status code.
+ * @param pszMode The open mode. See fopen() standard.
+ * Format: <a|r|w>[+][b|t][x][e|N|E]
+ * - 'a': Open or create file and writes
+ * append tos it.
+ * - 'r': Open existing file and read from it.
+ * - 'w': Open or truncate existing file and write
+ * to it.
+ * - '+': Open for both read and write access.
+ * - 'b' / 't': binary / text
+ * - 'x': exclusively create, no open. Only
+ * possible with 'w'.
+ * - 'e' / 'N': No inherit on exec. (The 'e' is
+ * how Linux and FreeBSD expresses this, the
+ * latter is Visual C++).
+ * @param ppStream Where to store the opened stream.
+ * @param pszFilenameFmt Filename path format string.
+ * @param args Arguments to the format string.
+ */
+RTR3DECL(int) RTStrmOpenFV(const char *pszMode, PRTSTREAM *ppStream, const char *pszFilenameFmt,
+ va_list args) RT_IPRT_FORMAT_ATTR(3, 0);
+
+/**
+ * Opens a file stream.
+ *
+ * @returns iprt status code.
+ * @param pszMode The open mode. See fopen() standard.
+ * Format: <a|r|w>[+][b|t][x][e|N|E]
+ * - 'a': Open or create file and writes
+ * append tos it.
+ * - 'r': Open existing file and read from it.
+ * - 'w': Open or truncate existing file and write
+ * to it.
+ * - '+': Open for both read and write access.
+ * - 'b' / 't': binary / text
+ * - 'x': exclusively create, no open. Only
+ * possible with 'w'.
+ * - 'e' / 'N': No inherit on exec. (The 'e' is
+ * how Linux and FreeBSD expresses this, the
+ * latter is Visual C++).
+ * @param ppStream Where to store the opened stream.
+ * @param pszFilenameFmt Filename path format string.
+ * @param ... Arguments to the format string.
+ */
+RTR3DECL(int) RTStrmOpenF(const char *pszMode, PRTSTREAM *ppStream, const char *pszFilenameFmt, ...) RT_IPRT_FORMAT_ATTR(3, 4);
+
+/**
+ * Opens a file stream for a RTFILE handle, taking ownership of the handle.
+ *
+ * @returns iprt status code.
+ * @param hFile The file handle to use. On success, handle
+ * ownership is transfered to the stream and it will be
+ * closed when the stream closes.
+ * @param pszMode The open mode, accept the same as RTStrOpen and
+ * friends however it is only used to figure out what
+ * we can do with the handle.
+ * @param fFlags Reserved, must be zero.
+ * @param ppStream Where to store the opened stream.
+ */
+RTR3DECL(int) RTStrmOpenFileHandle(RTFILE hFile, const char *pszMode, uint32_t fFlags, PRTSTREAM *ppStream);
+
+/**
+ * Queries the file handle backing the stream.
+ *
+ * @returns iprt status code.
+ * @retval VERR_NOT_AVAILABLE if the stream has no valid handle associated with
+ * it.
+ *
+ * @param pStream The stream.
+ * @param phFile Where to return the file handle. This should not be
+ * closed!
+ */
+RTR3DECL(int) RTStrmQueryFileHandle(PRTSTREAM pStream, PRTFILE phFile);
+
+/**
+ * Closes the specified stream.
+ *
+ * @returns iprt status code.
+ * @param pStream The stream to close.
+ *
+ * @note The stream will be closed and freed even when failure is returned.
+ * It cannot be used again after this call. The error status is only
+ * to indicate that the flushing of buffers or the closing of the
+ * underlying file handle failed.
+ */
+RTR3DECL(int) RTStrmClose(PRTSTREAM pStream);
+
+/**
+ * Get the pending error of the stream.
+ *
+ * @returns iprt status code. of the stream.
+ * @param pStream The stream.
+ */
+RTR3DECL(int) RTStrmError(PRTSTREAM pStream);
+
+/**
+ * Clears stream error condition.
+ *
+ * All stream operations save RTStrmClose and this will fail
+ * while an error is asserted on the stream
+ *
+ * @returns iprt status code.
+ * @param pStream The stream.
+ */
+RTR3DECL(int) RTStrmClearError(PRTSTREAM pStream);
+
+/**
+ * Changes the stream mode.
+ *
+ * @returns iprt status code.
+ * @param pStream The stream.
+ * @param fBinary The desired binary (@c true) / text mode (@c false).
+ * Pass -1 to leave it unchanged.
+ * @param fCurrentCodeSet Whether converting the stream from UTF-8 to the
+ * current code set is desired (@c true) or not (@c
+ * false). Pass -1 to leave this property unchanged.
+ */
+RTR3DECL(int) RTStrmSetMode(PRTSTREAM pStream, int fBinary, int fCurrentCodeSet);
+
+/** Stream buffering modes. */
+typedef enum RTSTRMBUFMODE
+{
+ RTSTRMBUFMODE_INVALID = 0,
+ RTSTRMBUFMODE_FULL, /**< Full buffering. */
+ RTSTRMBUFMODE_LINE, /**< Line buffering. On Windows this could be the same as RTSTRMBUFMODE_FULL. */
+ RTSTRMBUFMODE_UNBUFFERED, /**< No buffering. */
+ RTSTRMBUFMODE_END,
+ RTSTRMBUFMODE_32BIT_HACK = 0x7fffffff
+} RTSTRMBUFMODE;
+
+/**
+ * Changes the stream buffering mode.
+ *
+ * @returns iprt status code.
+ * @param pStream The stream.
+ * @param enmBufMode The new buffering mode.
+ */
+RTR3DECL(int) RTStrmSetBufferingMode(PRTSTREAM pStream, RTSTRMBUFMODE enmBufMode);
+
+/**
+ * Returns the current echo mode.
+ *
+ * This works only for standard input streams.
+ *
+ * @returns iprt status code.
+ * @retval VERR_INVALID_FUNCTION if not a TTY.
+ * @param pStream The stream.
+ * @param pfEchoChars Where to store the flag whether typed characters are echoed.
+ */
+RTR3DECL(int) RTStrmInputGetEchoChars(PRTSTREAM pStream, bool *pfEchoChars);
+
+/**
+ * Changes the behavior for echoing inpit characters on the command line.
+ *
+ * This works only for standard input streams.
+ *
+ * @returns iprt status code.
+ * @retval VERR_INVALID_FUNCTION if not a TTY.
+ * @param pStream The stream.
+ * @param fEchoChars Flag whether echoing typed characters is wanted.
+ */
+RTR3DECL(int) RTStrmInputSetEchoChars(PRTSTREAM pStream, bool fEchoChars);
+
+/**
+ * Checks if this is a terminal (TTY) or not.
+ *
+ * @returns true if it is, false if it isn't or the stream isn't valid.
+ * @param pStream The stream.
+ */
+RTR3DECL(bool) RTStrmIsTerminal(PRTSTREAM pStream);
+
+/**
+ * Gets the width of the terminal the stream is associated with.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_INVALID_FUNCTION if not connected to a terminal.
+ * @param pStream The stream.
+ * @param pcchWidth Where to return the width. This will never be zero
+ * and always be set, even on error.
+ */
+RTR3DECL(int) RTStrmQueryTerminalWidth(PRTSTREAM pStream, uint32_t *pcchWidth);
+
+/**
+ * Rewinds the stream.
+ *
+ * Stream errors will be reset on success.
+ *
+ * @returns IPRT status code.
+ *
+ * @param pStream The stream.
+ *
+ * @remarks Not all streams are rewindable and that behavior is currently
+ * undefined for those.
+ */
+RTR3DECL(int) RTStrmRewind(PRTSTREAM pStream);
+
+/**
+ * Changes the file position.
+ *
+ * @returns IPRT status code.
+ *
+ * @param pStream The stream.
+ * @param off The seek offset.
+ * @param uMethod Seek method, i.e. one of the RTFILE_SEEK_* defines.
+ *
+ * @remarks Not all streams are seekable and that behavior is currently
+ * undefined for those.
+ */
+RTR3DECL(int) RTStrmSeek(PRTSTREAM pStream, RTFOFF off, uint32_t uMethod);
+
+/**
+ * Tells the stream position.
+ *
+ * @returns Stream position or IPRT error status. Non-negative numbers are
+ * stream positions, while negative numbers are IPRT error stauses.
+ *
+ * @param pStream The stream.
+ *
+ * @remarks Not all streams have a position and that behavior is currently
+ * undefined for those.
+ */
+RTR3DECL(RTFOFF) RTStrmTell(PRTSTREAM pStream);
+
+/**
+ * Reads from a file stream.
+ *
+ * @returns iprt status code.
+ * @param pStream The stream.
+ * @param pvBuf Where to put the read bits.
+ * Must be cbRead bytes or more.
+ * @param cbToRead Number of bytes to read.
+ * @param pcbRead Where to store the number of bytes actually read.
+ * If NULL cbRead bytes are read or an error is returned.
+ */
+RTR3DECL(int) RTStrmReadEx(PRTSTREAM pStream, void *pvBuf, size_t cbToRead, size_t *pcbRead);
+
+/**
+ * Writes to a file stream.
+ *
+ * @returns iprt status code.
+ * @param pStream The stream.
+ * @param pvBuf Where to get the bits to write from.
+ * @param cbToWrite Number of bytes to write.
+ * @param pcbWritten Where to store the number of bytes actually written.
+ * If NULL cbWrite bytes are written or an error is returned.
+ */
+RTR3DECL(int) RTStrmWriteEx(PRTSTREAM pStream, const void *pvBuf, size_t cbToWrite, size_t *pcbWritten);
+
+/**
+ * Reads from a file stream.
+ *
+ * @returns iprt status code.
+ * @param pStream The stream.
+ * @param pvBuf Where to put the read bits.
+ * Must be cbRead bytes or more.
+ * @param cbToRead Number of bytes to read.
+ */
+DECLINLINE(int) RTStrmRead(PRTSTREAM pStream, void *pvBuf, size_t cbToRead)
+{
+ return RTStrmReadEx(pStream, pvBuf, cbToRead, NULL);
+}
+
+/**
+ * Writes to a file stream.
+ *
+ * @returns iprt status code.
+ * @param pStream The stream.
+ * @param pvBuf Where to get the bits to write from.
+ * @param cbToWrite Number of bytes to write.
+ */
+DECLINLINE(int) RTStrmWrite(PRTSTREAM pStream, const void *pvBuf, size_t cbToWrite)
+{
+ return RTStrmWriteEx(pStream, pvBuf, cbToWrite, NULL);
+}
+
+/**
+ * Reads a character from a file stream.
+ *
+ * @returns The char as an unsigned char cast to int.
+ * @returns -1 on failure.
+ * @param pStream The stream.
+ */
+RTR3DECL(int) RTStrmGetCh(PRTSTREAM pStream);
+
+/**
+ * Writes a character to a file stream.
+ *
+ * @returns iprt status code.
+ * @param pStream The stream.
+ * @param ch The char to write.
+ */
+RTR3DECL(int) RTStrmPutCh(PRTSTREAM pStream, int ch);
+
+/**
+ * Writes a string to a file stream.
+ *
+ * @returns iprt status code.
+ * @param pStream The stream.
+ * @param pszString The string to write.
+ * No newlines or anything are appended or prepended.
+ * The terminating '\\0' is not written, of course.
+ */
+RTR3DECL(int) RTStrmPutStr(PRTSTREAM pStream, const char *pszString);
+
+/**
+ * Reads a line from a file stream.
+ *
+ * A line ends with a '\\n', '\\r\\n', '\\0' or the end of the file.
+ *
+ * @returns iprt status code.
+ * @retval VINF_BUFFER_OVERFLOW if the buffer wasn't big enough to read an
+ * entire line.
+ * @retval VERR_BUFFER_OVERFLOW if a lone '\\r' was encountered at the end of
+ * the buffer and we ended up dropping the following character.
+ *
+ * @param pStream The stream.
+ * @param pszString Where to store the line.
+ * The line will *NOT* contain any '\\n'.
+ * @param cbString The size of the string buffer.
+ */
+RTR3DECL(int) RTStrmGetLine(PRTSTREAM pStream, char *pszString, size_t cbString);
+
+/**
+ * Flushes a stream.
+ *
+ * @returns iprt status code.
+ * @param pStream The stream to flush.
+ */
+RTR3DECL(int) RTStrmFlush(PRTSTREAM pStream);
+
+/**
+ * Prints a formatted string to the specified stream.
+ *
+ * @returns Number of bytes printed.
+ * @param pStream The stream to print to.
+ * @param pszFormat Runtime format string.
+ * @param ... Arguments specified by pszFormat.
+ */
+RTR3DECL(int) RTStrmPrintf(PRTSTREAM pStream, const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(2, 3);
+
+/**
+ * Prints a formatted string to the specified stream.
+ *
+ * @returns Number of bytes printed.
+ * @param pStream The stream to print to.
+ * @param pszFormat Runtime format string.
+ * @param args Arguments specified by pszFormat.
+ */
+RTR3DECL(int) RTStrmPrintfV(PRTSTREAM pStream, const char *pszFormat, va_list args) RT_IPRT_FORMAT_ATTR(2, 0);
+
+/**
+ * Prints a formatted string to the specified stream, performing wrapping of
+ * lines considered too long.
+ *
+ * If the stream is to a terminal, the terminal width is used as the max line
+ * width. Otherwise, the width is taken from @a fFlags
+ * (RTSTRMWRAPPED_F_NON_TERMINAL_WIDTH_MASK /
+ * RTSTRMWRAPPED_F_NON_TERMINAL_WIDTH_SHIFT), defaulting to 80 if zero.
+ *
+ * @returns Low 16 bits is the line offset, high 16 bits the number of lines
+ * outputted. Apply RTSTRMWRAPPED_F_LINE_OFFSET_MASK to the value and
+ * it can be passed via @a fFlags to the next invocation (not necessary
+ * if all format strings ends with a newline).
+ * Negative values are IPRT error status codes.
+ * @param pStream The stream to print to.
+ * @param fFlags RTSTRMWRAPPED_F_XXX - flags, configuration and state.
+ * @param pszFormat Runtime format string.
+ * @param ... Arguments specified by pszFormat.
+ * @sa RTStrmWrappedPrintfV, RTStrmPrintf, RTStrmPrintfV
+ */
+RTDECL(int32_t) RTStrmWrappedPrintf(PRTSTREAM pStream, uint32_t fFlags, const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(3, 4);
+
+/**
+ * Prints a formatted string to the specified stream, performing wrapping of
+ * lines considered too long.
+ *
+ * If the stream is to a terminal, the terminal width is used as the max line
+ * width. Otherwise, the width is taken from @a fFlags
+ * (RTSTRMWRAPPED_F_NON_TERMINAL_WIDTH_MASK /
+ * RTSTRMWRAPPED_F_NON_TERMINAL_WIDTH_SHIFT), defaulting to 80 if zero.
+ *
+ * @returns Low 16 bits is the line offset, high 16 bits the number of lines
+ * outputted. Apply RTSTRMWRAPPED_F_LINE_OFFSET_MASK to the value and
+ * it can be passed via @a fFlags to the next invocation (not necessary
+ * if all format strings ends with a newline).
+ * Negative values are IPRT error status codes.
+ * @param pStream The stream to print to.
+ * @param fFlags RTSTRMWRAPPED_F_XXX - flags, configuration and state.
+ * @param pszFormat Runtime format string.
+ * @param va Arguments specified by pszFormat.
+ * @sa RTStrmWrappedPrintf, RTStrmPrintf, RTStrmPrintfV
+ */
+RTDECL(int32_t) RTStrmWrappedPrintfV(PRTSTREAM pStream, uint32_t fFlags, const char *pszFormat,
+ va_list va) RT_IPRT_FORMAT_ATTR(3, 0);
+
+/** @name RTSTRMWRAPPED_F_XXX - Flags for RTStrmWrappedPrintf &
+ * RTStrmWrappedPrintfV.
+ * @{ */
+/** The current line offset mask.
+ * This should be used to passed the line off state from one call to the next
+ * when printing incomplete lines. If all format strings ends with a newline,
+ * this is not necessary. */
+#define RTSTRMWRAPPED_F_LINE_OFFSET_MASK UINT32_C(0x00000fff)
+/** The non-terminal width mask. Defaults to 80 if not specified (zero). */
+#define RTSTRMWRAPPED_F_NON_TERMINAL_WIDTH_MASK UINT32_C(0x000ff000)
+/** The non-terminal width shift. */
+#define RTSTRMWRAPPED_F_NON_TERMINAL_WIDTH_SHIFT 12
+/** The hanging indent level mask - defaults to 4 if zero.
+ * Used when RTSTRMWRAPPED_F_HANGING_INDENT is set. */
+#define RTSTRMWRAPPED_F_HANGING_INDENT_MASK UINT32_C(0x01f00000)
+/** The hanging indent level shift. */
+#define RTSTRMWRAPPED_F_HANGING_INDENT_SHIFT 20
+/** Hanging indent. Used for command synopsis and such. */
+#define RTSTRMWRAPPED_F_HANGING_INDENT UINT32_C(0x80000000)
+/** @} */
+
+/**
+ * Dumper vprintf-like function outputting to a stream.
+ *
+ * @param pvUser The stream to print to. NULL means standard output.
+ * @param pszFormat Runtime format string.
+ * @param va Arguments specified by pszFormat.
+ */
+RTR3DECL(void) RTStrmDumpPrintfV(void *pvUser, const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(2, 0);
+
+/**
+ * Prints a formatted string to the standard output stream (g_pStdOut).
+ *
+ * @returns Number of bytes printed.
+ * @param pszFormat Runtime format string.
+ * @param ... Arguments specified by pszFormat.
+ */
+RTR3DECL(int) RTPrintf(const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(1, 2);
+
+/**
+ * Prints a formatted string to the standard output stream (g_pStdOut).
+ *
+ * @returns Number of bytes printed.
+ * @param pszFormat Runtime format string.
+ * @param args Arguments specified by pszFormat.
+ */
+RTR3DECL(int) RTPrintfV(const char *pszFormat, va_list args) RT_IPRT_FORMAT_ATTR(1, 0);
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_stream_h */
+
diff --git a/include/iprt/string.h b/include/iprt/string.h
new file mode 100644
index 00000000..d7b78bf3
--- /dev/null
+++ b/include/iprt/string.h
@@ -0,0 +1,3725 @@
+/** @file
+ * IPRT - String Manipulation.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_string_h
+#define IPRT_INCLUDED_string_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+#include <iprt/assert.h>
+#include <iprt/stdarg.h>
+#include <iprt/errcore.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
+# define fls fls_string_h
+# include <string.h>
+# undef fls
+# undef ffs
+# undef strpbrk
+
+#else
+# include <string.h>
+#endif
+
+/*
+ * 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_DARWIN) || defined(RT_OS_SOLARIS) || defined(RT_OS_WINDOWS)) && !defined(IPRT_NO_CRT)
+RT_C_DECLS_BEGIN
+# if !defined(RT_OS_DARWIN) || RT_CLANG_PREREQ(7 /* whatever post gcc-4.2 */, 0)
+RTDECL(void *) mempcpy(void *pvDst, const void *pvSrc, size_t cb);
+# else
+void *mempcpy(void *pvDst, const void *pvSrc, size_t cb);
+# endif
+RT_C_DECLS_END
+#endif
+
+#if (!defined(RT_OS_LINUX) || !defined(_GNU_SOURCE)) \
+ && (!defined(RT_OS_OS2) || !defined(_GNU_SOURCE)) \
+ && !defined(RT_OS_FREEBSD) \
+ && !defined(RT_OS_NETBSD)
+RT_C_DECLS_BEGIN
+void *memrchr(const void *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)
+
+
+/**
+ * For copying a volatile variable to a non-volatile one.
+ * @param a_Dst The non-volatile destination variable.
+ * @param a_VolatileSrc The volatile source variable / dereferenced pointer.
+ */
+#define RT_COPY_VOLATILE(a_Dst, a_VolatileSrc) \
+ do { \
+ void const volatile *a_pvVolatileSrc_BCopy_Volatile = &(a_VolatileSrc); \
+ AssertCompile(sizeof(a_Dst) == sizeof(a_VolatileSrc)); \
+ memcpy(&(a_Dst), (void const *)a_pvVolatileSrc_BCopy_Volatile, sizeof(a_Dst)); \
+ } while (0)
+
+/**
+ * For copy a number of bytes from a volatile buffer to a non-volatile one.
+ *
+ * @param a_pDst Pointer to the destination buffer.
+ * @param a_pVolatileSrc Pointer to the volatile source buffer.
+ * @param a_cbToCopy Number of bytes to copy.
+ */
+#define RT_BCOPY_VOLATILE(a_pDst, a_pVolatileSrc, a_cbToCopy) \
+ do { \
+ void const volatile *a_pvVolatileSrc_BCopy_Volatile = (a_pVolatileSrc); \
+ memcpy((a_pDst), (void const *)a_pvVolatileSrc_BCopy_Volatile, (a_cbToCopy)); \
+ } 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 UTF-8 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 with default tag, translates pszString from UTF-8 to
+ * current codepage, extended version.
+ *
+ * @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.
+ * @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.
+ */
+#define RTStrUtf8ToCurrentCPEx(ppszString, pszString, cchString) \
+ RTStrUtf8ToCurrentCPExTag((ppszString), (pszString), (cchString), 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 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 pszTag Allocation tag used for statistics and such.
+ */
+RTR3DECL(int) RTStrUtf8ToCurrentCPExTag(char **ppszString, const char *pszString, size_t cchString, 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);
+
+/**
+ * Allocates tmp buffer, translates pszString from console 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 RTStrConsoleCPToUtf8(ppszString, pszString) RTStrConsoleCPToUtf8Tag((ppszString), (pszString), RTSTR_TAG)
+
+/**
+ * Allocates tmp buffer, translates pszString from console 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) RTStrConsoleCPToUtf8Tag(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 ppszCopy 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(ppszCopy, pszString) RTStrDupExTag((ppszCopy), (pszString), RTSTR_TAG)
+
+/**
+ * Allocates a new copy of the given UTF-8 string (custom tag).
+ *
+ * @returns iprt status code.
+ * @param ppszCopy 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 **ppszCopy, 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);
+
+/**
+ * Allocates a new copy of the given UTF-8 substring (default tag).
+ *
+ * @returns iprt status code (VINF_SUCCESS or VERR_NO_STR_MEMORY).
+ * @param ppszCopy Receives pointer of the allocated UTF-8 substring.
+ * The returned pointer must be freed using RTStrFree().
+ * @param pszString UTF-8 string to duplicate.
+ * @param cchMax The max number of chars to duplicate, not counting
+ * the terminator.
+ */
+#define RTStrDupNEx(ppszCopy, pszString, cchMax) RTStrDupNExTag((ppszCopy), (pszString), (cchMax), RTSTR_TAG)
+
+/**
+ * Allocates a new copy of the given UTF-8 substring (custom tag).
+ *
+ * @returns iprt status code (VINF_SUCCESS or VERR_NO_STR_MEMORY).
+ * @param ppszCopy Receives pointer of the allocated UTF-8 substring.
+ * The returned pointer must be freed using RTStrFree().
+ * @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(int) RTStrDupNExTag(char **ppszCopy, 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 replacedment 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).
+ *
+ * This differs from RTStrToUtf16 in that it always produces a
+ * big-endian string.
+ *
+ * @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);
+
+/**
+ * Translate a UTF-8 string into a UTF-16BE allocating the result buffer
+ * (default tag).
+ *
+ * This differs from RTStrToUtf16Tag in that it always produces a
+ * big-endian string.
+ *
+ * @returns iprt status code.
+ * @param pszString UTF-8 string to convert.
+ * @param ppwszString Receives pointer to the allocated UTF-16BE string.
+ * The returned string must be freed using RTUtf16Free().
+ */
+#define RTStrToUtf16Big(pszString, ppwszString) RTStrToUtf16BigTag((pszString), (ppwszString), RTSTR_TAG)
+
+/**
+ * Translate a UTF-8 string into a UTF-16BE 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-16BE string.
+ * The returned string must be freed using RTUtf16Free().
+ * @param pszTag Allocation tag used for statistics and such.
+ */
+RTDECL(int) RTStrToUtf16BigTag(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);
+
+
+/**
+ * Translates pszString from UTF-8 to UTF-16BE, allocating the result buffer if requested.
+ *
+ * This differs from RTStrToUtf16Ex in that it always produces a
+ * big-endian string.
+ *
+ * @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 RTStrToUtf16BigEx(pszString, cchString, ppwsz, cwc, pcwc) \
+ RTStrToUtf16BigExTag((pszString), (cchString), (ppwsz), (cwc), (pcwc), RTSTR_TAG)
+
+/**
+ * Translates pszString from UTF-8 to UTF-16BE, allocating the result buffer if
+ * requested (custom tag).
+ *
+ * This differs from RTStrToUtf16ExTag in that it always produces a
+ * big-endian string.
+ *
+ * @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) RTStrToUtf16BigExTag(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++ = (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!'.
+ * - \%RTeic - Takes a #PCRTERRINFO value outputting 'rc: msg',
+ * or 'rc - msg' with the \# flag.
+ * - \%RTeim - Takes a #PCRTERRINFO value outputting ': msg', or
+ * ' - msg' with the \# flag.
+ * - \%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.
+ * - \%RhxD - Same as \%Rhxd, except that it skips duplicate lines.
+ * - \%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.
+ * The space separtor can get change to a colon by
+ * using the ' flag, and removed entirely using \#.
+ * - \%RhXd - Same as \%Rhxd, but takes an additional uint64_t
+ * value with the memory start address/offset after
+ * the memory pointer.
+ * - \%RhXD - Same as \%RhxD, but takes an additional uint64_t
+ * value with the memory start address/offset after
+ * the memory pointer.
+ * - \%RhXs - Same as \%Rhxs, but takes an additional uint64_t
+ * value with the memory start address/offset after
+ * the memory pointer.
+ *
+ * - \%Rhcb - Human readable byte size formatting, using
+ * binary unit prefixes (GiB, MiB and such). Takes a
+ * 64-bit unsigned integer as input. Does one
+ * decimal point by default, can do 0-3 via precision
+ * field. No rounding when calculating fraction.
+ * The space flag add a space between the value and
+ * unit.
+ * - \%RhcB - Same a \%Rhcb only the 'i' is skipped in the unit.
+ * - \%Rhci - SI variant of \%Rhcb, fraction is rounded.
+ * - \%Rhub - Human readable number formatting, using
+ * binary unit prefixes. Takes a 64-bit unsigned
+ * integer as input. Does one decimal point by
+ * default, can do 0-3 via precision field. No
+ * rounding when calculating fraction. The space
+ * flag add a space between the value and unit.
+ * - \%RhuB - Same a \%Rhub only the 'i' is skipped in the unit.
+ * - \%Rhui - SI variant of \%Rhub, fraction is rounded.
+ *
+ * - \%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.
+ * Note! Works like \%Rrs when IN_RT_STATIC is defined (so please avoid).
+ * - \%Rra - Takes an integer iprt status code as argument. Will insert the
+ * status code define + full description.
+ * Note! Reduced output when IN_RT_STATIC is defined (so please avoid).
+ * - \%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.
+ * Note! Works like \%Rwc when IN_RT_STATIC is defined.
+ * - \%Rwa - Takes a long Windows error code as argument. Will insert the
+ * error code define + full description.
+ * Note! Reduced output when IN_RT_STATIC is defined (so please avoid).
+ *
+ * - \%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.
+ * Note! Works like \%Rhrc when IN_RT_STATIC is
+ * defined on Windows (so please avoid).
+ * - \%Rhra - Takes a COM/XPCOM error code as argument. Will insert the
+ * error code define + full description.
+ * Note! Reduced output when IN_RT_STATIC is defined on Windows (so please avoid).
+ *
+ * - \%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.
+ *
+ * - \%lRbs - Same as \%ls except inlut is big endian UTF-16.
+ *
+ * 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, JSON and URI 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.
+ *
+ * - \%RMjs - Takes a string pointer (const char *) and outputs
+ * it in quotes with proper JSON escaping.
+ *
+ * - \%RMpa - Takes a string pointer (const char *) and outputs
+ * it percent-encoded (RFC-3986). All reserved characters
+ * are encoded.
+ *
+ * - \%RMpf - Takes a string pointer (const char *) and outputs
+ * it percent-encoded (RFC-3986), form style. This
+ * means '+' is used to escape space (' ') and '%2B'
+ * is used to escape '+'.
+ *
+ * - \%RMpp - Takes a string pointer (const char *) and outputs
+ * it percent-encoded (RFC-3986), path style. This
+ * means '/' will not be escaped.
+ *
+ * - \%RMpq - Takes a string pointer (const char *) and outputs
+ * it percent-encoded (RFC-3986), query style. This
+ * means '+' will not be escaped.
+ *
+ *
+ * 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 & errcore.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 DECLCALLBACKTYPE(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 DECLCALLBACKTYPE(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 32-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 pr32Value The value to format.
+ * @param cchWidth Width.
+ * @param cchPrecision Precision.
+ * @param fFlags Flags, RTSTR_F_XXX.
+ */
+RTDECL(ssize_t) RTStrFormatR32(char *pszBuf, size_t cbBuf, PCRTFLOAT32U pr32Value, signed int cchWidth,
+ signed int cchPrecision, uint32_t fFlags);
+
+/**
+ * Formats an 64-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 pr64Value The value to format.
+ * @param cchWidth Width.
+ * @param cchPrecision Precision.
+ * @param fFlags Flags, RTSTR_F_XXX.
+ */
+RTDECL(ssize_t) RTStrFormatR64(char *pszBuf, size_t cbBuf, PCRTFLOAT64U pr64Value, signed int cchWidth,
+ signed int cchPrecision, uint32_t fFlags);
+
+#if !defined(__IBMCPP__) && !defined(__IBMC__)
+
+/**
+ * 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);
+
+#endif /* uint16_t bitfields doesn't work */
+
+
+/**
+ * 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 DECLCALLBACKTYPE(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.
+ *
+ * @deprecated Use RTStrPrintf2V! Problematic return value on overflow.
+ */
+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.
+ *
+ * @deprecated Use RTStrPrintf2! Problematic return value on overflow.
+ */
+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.
+ *
+ * @deprecated Use RTStrPrintf2ExV! Problematic return value on overflow.
+ */
+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.
+ *
+ * @deprecated Use RTStrPrintf2Ex! Problematic return value on overflow.
+ */
+RTDECL(size_t) RTStrPrintfEx(PFNSTRFORMAT pfnFormat, void *pvArg, char *pszBuffer, size_t cchBuffer,
+ const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(5, 6);
+
+/**
+ * String printf, version 2.
+ *
+ * @returns On success, positive count of formatted character excluding the
+ * terminator. On buffer overflow, negative number giving the required
+ * buffer size (including terminator char).
+ *
+ * @param pszBuffer Output buffer.
+ * @param cbBuffer Size of the output buffer.
+ * @param pszFormat Pointer to the format string, @see pg_rt_str_format.
+ * @param args The format argument.
+ */
+RTDECL(ssize_t) RTStrPrintf2V(char *pszBuffer, size_t cbBuffer, const char *pszFormat, va_list args) RT_IPRT_FORMAT_ATTR(3, 0);
+
+/**
+ * String printf, version 2.
+ *
+ * @returns On success, positive count of formatted character excluding the
+ * terminator. On buffer overflow, negative number giving the required
+ * buffer size (including terminator char).
+ *
+ * @param pszBuffer Output buffer.
+ * @param cbBuffer Size of the output buffer.
+ * @param pszFormat Pointer to the format string, @see pg_rt_str_format.
+ * @param ... The format argument.
+ */
+RTDECL(ssize_t) RTStrPrintf2(char *pszBuffer, size_t cbBuffer, const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(3, 4);
+
+/**
+ * String printf with custom formatting, version 2.
+ *
+ * @returns On success, positive count of formatted character excluding the
+ * terminator. On buffer overflow, negative number giving the required
+ * buffer size (including terminator char).
+ *
+ * @param pfnFormat Pointer to handler function for the custom formats.
+ * @param pvArg Argument to the pfnFormat function.
+ * @param pszBuffer Output buffer.
+ * @param cbBuffer Size of the output buffer.
+ * @param pszFormat Pointer to the format string, @see pg_rt_str_format.
+ * @param args The format argument.
+ */
+RTDECL(ssize_t) RTStrPrintf2ExV(PFNSTRFORMAT pfnFormat, void *pvArg, char *pszBuffer, size_t cbBuffer,
+ const char *pszFormat, va_list args) RT_IPRT_FORMAT_ATTR(5, 0);
+
+/**
+ * String printf with custom formatting, version 2.
+ *
+ * @returns On success, positive count of formatted character excluding the
+ * terminator. On buffer overflow, negative number giving the required
+ * buffer size (including terminator char).
+ *
+ * @param pfnFormat Pointer to handler function for the custom formats.
+ * @param pvArg Argument to the pfnFormat function.
+ * @param pszBuffer Output buffer.
+ * @param cbBuffer Size of the output buffer.
+ * @param pszFormat Pointer to the format string, @see pg_rt_str_format.
+ * @param ... The format argument.
+ */
+RTDECL(ssize_t) RTStrPrintf2Ex(PFNSTRFORMAT pfnFormat, void *pvArg, char *pszBuffer, size_t cbBuffer,
+ 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 RTStrNCmp 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 RTStrICmp, RTUtf16ICmpAscii
+ */
+RTDECL(int) RTStrICmpAscii(const char *psz1, const char *psz2);
+
+/**
+ * Performs a case insensitive string compare between a UTF-8 string and a 7-bit
+ * ASCII string, given a maximum string length.
+ *
+ * This is potentially faster than RTStrNICmp 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 RTStrNCmp 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.
+ * @param cchMax Maximum string length
+ * @sa RTStrNICmp, RTUtf16NICmpAscii
+ */
+RTDECL(int) RTStrNICmpAscii(const char *psz1, const char *psz2, size_t cchMax);
+
+/**
+ * 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(bool) 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(bool) RTStrIStartsWith(const char *pszString, const char *pszStart);
+
+/**
+ * Splits a string buffer with a given separator into separate strings.
+ * If no separators are found, no strings are returned. Consequtive separators will be skipped.
+ *
+ * @returns iprt status code.
+ * @param pcszStrings String buffer to split.
+ * @param cbStrings Size (in bytes) of string buffer to split, including terminator.
+ * @param pcszSeparator Separator to use / find for splitting strings.
+ * @param ppapszStrings Where to return the allocated string array on success. Needs to be free'd by the caller.
+ * @param pcStrings Where to return the number of split strings in \a ppapszStrings.
+ */
+RTDECL(int) RTStrSplit(const char *pcszStrings, size_t cbStrings,
+ const char *pcszSeparator, char ***ppapszStrings, size_t *pcStrings);
+
+/**
+ * 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);
+
+/** 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.
+ */
+RTDECL(char *) RTStrEnd(char const *pszString, size_t cchMax);
+
+/**
+ * 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 (size_t)(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 uBaseAndMaxLen The low byte is the base of the representation, the
+ * upper 24 bits are the max length to parse. If the base
+ * is zero the function will look for known prefixes before
+ * defaulting to 10. A max length of zero means no length
+ * restriction.
+ * @param pu64 Where to store the converted number. (optional)
+ */
+RTDECL(int) RTStrToUInt64Ex(const char *pszValue, char **ppszNext, unsigned uBaseAndMaxLen, 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 uBaseAndMaxLen The low byte is the base of the representation, the
+ * upper 24 bits are the max length to parse. If the base
+ * is zero the function will look for known prefixes before
+ * defaulting to 10. A max length of zero means no length
+ * restriction.
+ * @param pu64 Where to store the converted number. (optional)
+ */
+RTDECL(int) RTStrToUInt64Full(const char *pszValue, unsigned uBaseAndMaxLen, 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 uBaseAndMaxLen The low byte is the base of the representation, the
+ * upper 24 bits are the max length to parse. If the base
+ * is zero the function will look for known prefixes before
+ * defaulting to 10. A max length of zero means no length
+ * restriction.
+ * @param pu32 Where to store the converted number. (optional)
+ */
+RTDECL(int) RTStrToUInt32Ex(const char *pszValue, char **ppszNext, unsigned uBaseAndMaxLen, 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 uBaseAndMaxLen The low byte is the base of the representation, the
+ * upper 24 bits are the max length to parse. If the base
+ * is zero the function will look for known prefixes before
+ * defaulting to 10. A max length of zero means no length
+ * restriction.
+ * @param pu32 Where to store the converted number. (optional)
+ */
+RTDECL(int) RTStrToUInt32Full(const char *pszValue, unsigned uBaseAndMaxLen, uint32_t *pu32);
+
+/**
+ * Converts a string representation of a number to a 32-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 uBaseAndMaxLen The low byte is the base of the representation, the
+ * upper 24 bits are the max length to parse. If the base
+ * is zero the function will look for known prefixes before
+ * defaulting to 10. A max length of zero means no length
+ * restriction.
+ * @param pu16 Where to store the converted number. (optional)
+ */
+RTDECL(int) RTStrToUInt16Ex(const char *pszValue, char **ppszNext, unsigned uBaseAndMaxLen, 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 uBaseAndMaxLen The low byte is the base of the representation, the
+ * upper 24 bits are the max length to parse. If the base
+ * is zero the function will look for known prefixes before
+ * defaulting to 10. A max length of zero means no length
+ * restriction.
+ * @param pu16 Where to store the converted number. (optional)
+ */
+RTDECL(int) RTStrToUInt16Full(const char *pszValue, unsigned uBaseAndMaxLen, 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 uBaseAndMaxLen The low byte is the base of the representation, the
+ * upper 24 bits are the max length to parse. If the base
+ * is zero the function will look for known prefixes before
+ * defaulting to 10. A max length of zero means no length
+ * restriction.
+ * @param pu8 Where to store the converted number. (optional)
+ */
+RTDECL(int) RTStrToUInt8Ex(const char *pszValue, char **ppszNext, unsigned uBaseAndMaxLen, 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 uBaseAndMaxLen The low byte is the base of the representation, the
+ * upper 24 bits are the max length to parse. If the base
+ * is zero the function will look for known prefixes before
+ * defaulting to 10. A max length of zero means no length
+ * restriction.
+ * @param pu8 Where to store the converted number. (optional)
+ */
+RTDECL(int) RTStrToUInt8Full(const char *pszValue, unsigned uBaseAndMaxLen, 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 uBaseAndMaxLen The low byte is the base of the representation, the
+ * upper 24 bits are the max length to parse. If the base
+ * is zero the function will look for known prefixes before
+ * defaulting to 10. A max length of zero means no length
+ * restriction.
+ * @param pi64 Where to store the converted number. (optional)
+ */
+RTDECL(int) RTStrToInt64Ex(const char *pszValue, char **ppszNext, unsigned uBaseAndMaxLen, 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 uBaseAndMaxLen The low byte is the base of the representation, the
+ * upper 24 bits are the max length to parse. If the base
+ * is zero the function will look for known prefixes before
+ * defaulting to 10. A max length of zero means no length
+ * restriction.
+ * @param pi64 Where to store the converted number. (optional)
+ */
+RTDECL(int) RTStrToInt64Full(const char *pszValue, unsigned uBaseAndMaxLen, 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 uBaseAndMaxLen The low byte is the base of the representation, the
+ * upper 24 bits are the max length to parse. If the base
+ * is zero the function will look for known prefixes before
+ * defaulting to 10. A max length of zero means no length
+ * restriction.
+ * @param pi32 Where to store the converted number. (optional)
+ */
+RTDECL(int) RTStrToInt32Ex(const char *pszValue, char **ppszNext, unsigned uBaseAndMaxLen, 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 uBaseAndMaxLen The low byte is the base of the representation, the
+ * upper 24 bits are the max length to parse. If the base
+ * is zero the function will look for known prefixes before
+ * defaulting to 10. A max length of zero means no length
+ * restriction.
+ * @param pi32 Where to store the converted number. (optional)
+ */
+RTDECL(int) RTStrToInt32Full(const char *pszValue, unsigned uBaseAndMaxLen, 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 uBaseAndMaxLen The low byte is the base of the representation, the
+ * upper 24 bits are the max length to parse. If the base
+ * is zero the function will look for known prefixes before
+ * defaulting to 10. A max length of zero means no length
+ * restriction.
+ * @param pi16 Where to store the converted number. (optional)
+ */
+RTDECL(int) RTStrToInt16Ex(const char *pszValue, char **ppszNext, unsigned uBaseAndMaxLen, 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 uBaseAndMaxLen The low byte is the base of the representation, the
+ * upper 24 bits are the max length to parse. If the base
+ * is zero the function will look for known prefixes before
+ * defaulting to 10. A max length of zero means no length
+ * restriction.
+ * @param pi16 Where to store the converted number. (optional)
+ */
+RTDECL(int) RTStrToInt16Full(const char *pszValue, unsigned uBaseAndMaxLen, 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 uBaseAndMaxLen The low byte is the base of the representation, the
+ * upper 24 bits are the max length to parse. If the base
+ * is zero the function will look for known prefixes before
+ * defaulting to 10. A max length of zero means no length
+ * restriction.
+ * @param pi8 Where to store the converted number. (optional)
+ */
+RTDECL(int) RTStrToInt8Ex(const char *pszValue, char **ppszNext, unsigned uBaseAndMaxLen, 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 uBaseAndMaxLen The low byte is the base of the representation, the
+ * upper 24 bits are the max length to parse. If the base
+ * is zero the function will look for known prefixes before
+ * defaulting to 10. A max length of zero means no length
+ * restriction.
+ * @param pi8 Where to store the converted number. (optional)
+ */
+RTDECL(int) RTStrToInt8Full(const char *pszValue, unsigned uBaseAndMaxLen, 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);
+
+
+/**
+ * Converts a string to long double floating point, extended edition.
+ *
+ * Please note that long double can be double precision, extended precision, or
+ * quad precision floating point depending on the platform and architecture. See
+ * RT_COMPILER_WITH_128BIT_LONG_DOUBLE and RT_COMPILER_WITH_80BIT_LONG_DOUBLE.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_NO_DIGITS if no valid digits found.
+ * @retval VWRN_FLOAT_UNDERFLOW on underflow with denormal/subnormal return
+ * value
+ * @retval VERR_FLOAT_UNDERFLOW on underflow, value set to +/- zero.
+ * @retval VERR_FLOAT_OVERFLOW on overflow, value set to +/- infinity.
+ * @retval VWRN_TRAILING_CHARS
+ * @retval VWRN_TRAILING_SPACES
+ *
+ * @param pszValue The string to parse.
+ * @param ppszNext Where to store the pointer to the first char following
+ * the number. Optional.
+ * @param cchMax Max number of character to parse. Zero means unlimited.
+ * @param plrd Where to return the number. Optional.
+ *
+ * @note This code isn't entirely perfect yet. It could exhibit rounding
+ * differences compared to strtold & the compiler, and extreme value
+ * may overflow/underflow prematurely depending on the build config.
+ */
+RTDECL(int) RTStrToLongDoubleEx(const char *pszValue, char **ppszNext, size_t cchMax, long double *plrd);
+
+/**
+ * Converts a string to double precision floating point, extended edition.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_NO_DIGITS if no valid digits found.
+ * @retval VWRN_FLOAT_UNDERFLOW on underflow with denormal/subnormal return
+ * value
+ * @retval VERR_FLOAT_UNDERFLOW on underflow, value set to +/- zero.
+ * @retval VERR_FLOAT_OVERFLOW on overflow, value set to +/- infinity.
+ * @retval VWRN_TRAILING_CHARS
+ * @retval VWRN_TRAILING_SPACES
+ *
+ * @param pszValue The string to parse.
+ * @param ppszNext Where to store the pointer to the first char following
+ * the number. Optional.
+ * @param cchMax Max number of character to parse. Zero means unlimited.
+ * @param prd Where to return the number. Optional.
+ *
+ * @note This code isn't entirely perfect yet. It could exhibit rounding
+ * differences compared to strtold & the compiler, and extreme value
+ * may overflow/underflow prematurely depending on the build config.
+ */
+RTDECL(int) RTStrToDoubleEx(const char *pszValue, char **ppszNext, size_t cchMax, double *prd);
+
+/**
+ * Converts a string to single precision floating point, extended edition.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_NO_DIGITS if no valid digits found.
+ * @retval VWRN_FLOAT_UNDERFLOW on underflow with denormal/subnormal return
+ * value
+ * @retval VERR_FLOAT_UNDERFLOW on underflow, value set to +/- zero.
+ * @retval VERR_FLOAT_OVERFLOW on overflow, value set to +/- infinity.
+ * @retval VWRN_TRAILING_CHARS
+ * @retval VWRN_TRAILING_SPACES
+ *
+ * @param pszValue The string to parse.
+ * @param ppszNext Where to store the pointer to the first char following
+ * the number. Optional.
+ * @param cchMax Max number of character to parse. Zero means unlimited.
+ * @param pr Where to return the number. Optional.
+ *
+ * @note This code isn't entirely perfect yet. It could exhibit rounding
+ * differences compared to strtold & the compiler, and extreme value
+ * may overflow/underflow prematurely depending on the build config.
+ */
+RTDECL(int) RTStrToFloatEx(const char *pszValue, char **ppszNext, size_t cchMax, float *pr);
+
+
+/**
+ * Gets a long double NaN.
+ *
+ * @returns NaN value.
+ * @param pszTag Optional NaN tag for modifying the NaN value. We
+ * recognizes a string of hex digits for inserting into the
+ * fraction part. This may be followed 'quiet' or
+ * 'signaling', ignoring case and requiring at only the
+ * first character. The two components may be separated by
+ * zero or more '_' characters. Any other stuff in the tag
+ * will be ignored.
+ *
+ * If the tag is empty or we cannot grok any of it, we'll
+ * return a default quiet NaN.
+ * @param fPositive Whether the NaN value should be positive or negative
+ * (for what that's worth).
+ */
+RTDECL(long double) RTStrNanLongDouble(const char *pszTag, bool fPositive);
+
+/**
+ * Gets a double NaN.
+ *
+ * @returns NaN value.
+ * @param pszTag Optional NaN tag for modifying the NaN value. We
+ * recognizes a string of hex digits for inserting into the
+ * fraction part. This may be followed 'quiet' or
+ * 'signaling', ignoring case and requiring at only the
+ * first character. The two components may be separated by
+ * zero or more '_' characters. Any other stuff in the tag
+ * will be ignored.
+ *
+ * If the tag is empty or we cannot grok any of it, we'll
+ * return a default quiet NaN.
+ * @param fPositive Whether the NaN value should be positive or negative
+ * (for what that's worth).
+ */
+RTDECL(double) RTStrNanDouble(const char *pszTag, bool fPositive);
+
+/**
+ * Gets a float NaN.
+ *
+ * @returns NaN value.
+ * @param pszTag Optional NaN tag for modifying the NaN value. We
+ * recognizes a string of hex digits for inserting into the
+ * fraction part. This may be followed 'quiet' or
+ * 'signaling', ignoring case and requiring at only the
+ * first character. The two components may be separated by
+ * zero or more '_' characters. Any other stuff in the tag
+ * will be ignored.
+ *
+ * If the tag is empty or we cannot grok any of it, we'll
+ * return a default quiet NaN.
+ * @param fPositive Whether the NaN value should be positive or negative
+ * (for what that's worth).
+ */
+RTDECL(float) RTStrNanFloat(const char *pszTag, bool fPositive);
+
+/**
+ * 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 RTSTRCONVERTHEXBYTES_F_XXX.
+ */
+RTDECL(int) RTStrConvertHexBytes(char const *pszHex, void *pv, size_t cb, uint32_t fFlags);
+
+/** @name RTSTRCONVERTHEXBYTES_F_XXX - Flags for RTStrConvertHexBytes() and RTStrConvertHexBytesEx().
+ * @{ */
+/** Accept colon as a byte separator. */
+#define RTSTRCONVERTHEXBYTES_F_SEP_COLON RT_BIT(0)
+/** @} */
+
+/**
+ * Converts a string of hex bytes back into binary data, extended version.
+ *
+ * @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 and *pcbReturned is NULL.
+ * @retval VINF_BUFFER_UNDERFLOW if there aren't enough hex bytes to fill up
+ * the output buffer and *pcbReturned is not NULL, *pcbReturned holds
+ * the actual number of bytes.
+ * @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 RTSTRCONVERTHEXBYTES_F_XXX.
+ * @param ppszNext Set to point at where we stopped decoding hex bytes.
+ * Optional.
+ * @param pcbReturned Where to return the number of bytes found. Optional.
+ */
+RTDECL(int) RTStrConvertHexBytesEx(char const *pszHex, void *pv, size_t cb, uint32_t fFlags,
+ const char **ppszNext, size_t *pcbReturned);
+
+/** @} */
+
+
+/** @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
+{
+ /** 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 hash key value. Don't touch. */
+ PRTSTRSPACECORE pList;
+ /** Hash key. Don't touch. */
+ uint32_t Key;
+ /** 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 DECLCALLBACKTYPE(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);
+
+/** @} */
+
+
+/** @defgroup rt_str_mem Raw memory operations.
+ *
+ * @note Following the memchr/memcpy/memcmp/memset tradition and putting these
+ * in the string.h header rather than in the mem.h one.
+ *
+ * @{ */
+
+/**
+ * Searches @a pvHaystack for a 16-bit sized and aligned @a uNeedle.
+ *
+ * @returns Pointer to the first hit if found, NULL if not found.
+ * @param pvHaystack The memory to search.
+ * @param uNeedle The 16-bit value to find.
+ * @param cbHaystack Size of the memory to search.
+ * @sa memchr, RTStrMemFind32, RTStrMemFind64
+ */
+RTDECL(uint16_t *) RTStrMemFind16(const void *pvHaystack, uint16_t uNeedle, size_t cbHaystack);
+
+/**
+ * Searches @a pvHaystack for a 32-bit sized and aligned @a uNeedle.
+ *
+ * @returns Pointer to the first hit if found, NULL if not found.
+ * @param pvHaystack The memory to search.
+ * @param uNeedle The 32-bit value to find.
+ * @param cbHaystack Size of the memory to search.
+ * @sa memchr, RTStrMemFind16, RTStrMemFind64
+ */
+RTDECL(uint32_t *) RTStrMemFind32(const void *pvHaystack, uint32_t uNeedle, size_t cbHaystack);
+
+/**
+ * Searches @a pvHaystack for a 64-bit sized and aligned @a uNeedle.
+ *
+ * @returns Pointer to the first hit if found, NULL if not found.
+ * @param pvHaystack The memory to search.
+ * @param uNeedle The 64-bit value to find.
+ * @param cbHaystack Size of the memory to search.
+ * @sa memchr, RTStrMemFind16, RTStrMemFind32
+ */
+RTDECL(uint64_t *) RTStrMemFind64(const void *pvHaystack, uint64_t uNeedle, size_t cbHaystack);
+
+/** @} */
+
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_string_h */
diff --git a/include/iprt/symlink.h b/include/iprt/symlink.h
new file mode 100644
index 00000000..8b5e60f0
--- /dev/null
+++ b/include/iprt/symlink.h
@@ -0,0 +1,189 @@
+/** @file
+ * IPRT - Symbolic Link Manipulation.
+ */
+
+/*
+ * Copyright (C) 2010-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_symlink_h
+#define IPRT_INCLUDED_symlink_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_symlink RTSymlink - Symbolic Link Manipulation
+ * @ingroup grp_rt
+ *
+ * For querying and changing symlink info (mode, ownership, etc) please refer
+ * to the @ref grp_rt_path "RTPath" API: RTPathQueryInfoEx, RTPathSetOwnerEx,
+ * RTPathSetModeEx and RTPathSetTimesEx.
+ *
+ * @{
+ */
+
+/**
+ * Checks if the specified path exists and is a symlink.
+ *
+ * @returns true if it's a symlink, false if it isn't.
+ * @param pszSymlink The path to the symlink.
+ *
+ * @sa RTDirExists, RTPathExists, RTSymlinkExists.
+ */
+RTDECL(bool) RTSymlinkExists(const char *pszSymlink);
+
+/**
+ * Checks if this is a dangling link or not.
+ *
+ * If the target of @a pszSymlink is a symbolic link, this may return false if
+ * that or any subsequent links are dangling.
+ *
+ * @returns true if it's dangling, false if it isn't.
+ * @param pszSymlink The path to the symlink.
+ */
+RTDECL(bool) RTSymlinkIsDangling(const char *pszSymlink);
+
+/**
+ * RTSymlinkCreate link type argument.
+ */
+typedef enum RTSYMLINKTYPE
+{
+ /** Invalid value. */
+ RTSYMLINKTYPE_INVALID = 0,
+ /** The link targets a directory. */
+ RTSYMLINKTYPE_DIR,
+ /** The link targets a file (or whatever else). */
+ RTSYMLINKTYPE_FILE,
+ /** It is not known what is being targeted.
+ * @remarks The RTSymlinkCreate API may probe the target to try figure
+ * out what is being targeted. */
+ RTSYMLINKTYPE_UNKNOWN,
+ /** The end of the valid type values. */
+ RTSYMLINKTYPE_END,
+ /** Blow the type up to 32-bit. */
+ RTSYMLINKTYPE_32BIT_HACK = 0x7fffffff
+} RTSYMLINKTYPE;
+
+/** @name RTSymlinkCreate flags.
+ * @{ */
+/** Don't allow symbolic links as part of the path.
+ * @remarks this flag is currently not implemented and will be ignored. */
+#define RTSYMLINKCREATE_FLAGS_NO_SYMLINKS RT_BIT(0)
+/** @} */
+
+/**
+ * Creates a symbolic link (@a pszSymlink) targeting @a pszTarget.
+ *
+ * @returns IPRT status code.
+ *
+ * @param pszSymlink The name of the symbolic link.
+ * @param pszTarget The path to the symbolic link target. This is
+ * relative to @a pszSymlink or an absolute path.
+ * @param enmType The symbolic link type. For Windows compatability
+ * it is very important to set this correctly. When
+ * RTSYMLINKTYPE_UNKNOWN is used, the API will try
+ * make a guess and may attempt query information
+ * about @a pszTarget in the process.
+ * @param fCreate Create flags, RTSYMLINKCREATE_FLAGS_*.
+ */
+RTDECL(int) RTSymlinkCreate(const char *pszSymlink, const char *pszTarget,
+ RTSYMLINKTYPE enmType, uint32_t fCreate);
+
+/** @name RTSymlinkDelete flags.
+ * @{ */
+/** Don't allow symbolic links as part of the path.
+ * @remarks this flag is currently not implemented and will be ignored. */
+#define RTSYMLINKDELETE_FLAGS_NO_SYMLINKS RT_BIT(0)
+/** @} */
+
+/**
+ * Deletes the specified symbolic link.
+ *
+ * This will try to refuse deleting non-symlinks, however there are usually
+ * races in the implementation of this check so no guarantees can be are made.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_NOT_SYMLINK if @a pszSymlink does not specify a symbolic link.
+ *
+ * @param pszSymlink The symbolic link that should be removed.
+ * @param fDelete Delete flags, RTSYMLINKDELETE_FLAGS_*.
+ */
+RTDECL(int) RTSymlinkDelete(const char *pszSymlink, uint32_t fDelete);
+
+/** @name RTSymlinkRead flags.
+ * @{ */
+/** Don't allow symbolic links as part of the path.
+ * @remarks this flag is currently not implemented and will be ignored. */
+#define RTSYMLINKREAD_FLAGS_NO_SYMLINKS RT_BIT(0)
+/** @} */
+
+/**
+ * Read the symlink target.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_NOT_SYMLINK if @a pszSymlink does not specify a symbolic link.
+ * @retval VERR_BUFFER_OVERFLOW if the link is larger than @a cbTarget. The
+ * buffer will contain what all we managed to read, fully terminated
+ * if @a cbTarget > 0.
+ *
+ * @param pszSymlink The symbolic link that should be read.
+ * @param pszTarget The target buffer.
+ * @param cbTarget The size of the target buffer.
+ * @param fRead Read flags, RTSYMLINKREAD_FLAGS_*.
+ */
+RTDECL(int) RTSymlinkRead(const char *pszSymlink, char *pszTarget, size_t cbTarget, uint32_t fRead);
+
+/**
+ * Read the symlink target into an API allocated buffer.
+ *
+ * This API eliminates the race involved in determining the right buffer size.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_NOT_SYMLINK if @a pszSymlink does not specify a symbolic link.
+ *
+ * @param pszSymlink The symbolic link that should be read.
+ * @param ppszTarget Where to return the target string. Free the string
+ * by calling RTStrFree.
+ */
+RTDECL(int) RTSymlinkReadA(const char *pszSymlink, char **ppszTarget);
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_symlink_h */
+
diff --git a/include/iprt/system.h b/include/iprt/system.h
new file mode 100644
index 00000000..a4bef54d
--- /dev/null
+++ b/include/iprt/system.h
@@ -0,0 +1,379 @@
+/** @file
+ * IPRT - System Information.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_system_h
+#define IPRT_INCLUDED_system_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_system RTSystem - System Information
+ * @ingroup grp_rt
+ * @{
+ */
+
+/**
+ * Info level for RTSystemGetOSInfo().
+ */
+typedef enum RTSYSOSINFO
+{
+ RTSYSOSINFO_INVALID = 0, /**< The usual invalid entry. */
+ RTSYSOSINFO_PRODUCT, /**< OS product name. (uname -o) */
+ RTSYSOSINFO_RELEASE, /**< OS release. (uname -r) */
+ RTSYSOSINFO_VERSION, /**< OS version, optional. (uname -v) */
+ RTSYSOSINFO_SERVICE_PACK, /**< Service/fix pack level, optional. */
+ RTSYSOSINFO_END /**< End of the valid info levels. */
+} RTSYSOSINFO;
+
+
+/**
+ * Queries information about the OS.
+ *
+ * @returns IPRT status code.
+ * @retval VINF_SUCCESS on success.
+ * @retval VERR_INVALID_PARAMETER if enmInfo is invalid.
+ * @retval VERR_INVALID_POINTER if pszInfoStr is invalid.
+ * @retval VERR_BUFFER_OVERFLOW if the buffer is too small. The buffer will
+ * contain the chopped off result in this case, provided cchInfo isn't 0.
+ * @retval VERR_NOT_SUPPORTED if the info level isn't implemented. The buffer will
+ * contain an empty string.
+ *
+ * @param enmInfo The OS info level.
+ * @param pszInfo Where to store the result.
+ * @param cchInfo The size of the output buffer.
+ */
+RTDECL(int) RTSystemQueryOSInfo(RTSYSOSINFO enmInfo, char *pszInfo, size_t cchInfo);
+
+/**
+ * Queries the total amount of RAM in the system.
+ *
+ * This figure does not given any information about how much memory is
+ * currently available. Use RTSystemQueryAvailableRam instead.
+ *
+ * @returns IPRT status code.
+ * @retval VINF_SUCCESS and *pcb on sucess.
+ * @retval VERR_ACCESS_DENIED if the information isn't accessible to the
+ * caller.
+ *
+ * @param pcb Where to store the result (in bytes).
+ */
+RTDECL(int) RTSystemQueryTotalRam(uint64_t *pcb);
+
+/**
+ * Queries the total amount of RAM accessible to the system.
+ *
+ * This figure should not include memory that is installed but not used,
+ * nor memory that will be slow to bring online. The definition of 'slow'
+ * here is slower than swapping out a MB of pages to disk.
+ *
+ * @returns IPRT status code.
+ * @retval VINF_SUCCESS and *pcb on success.
+ * @retval VERR_ACCESS_DENIED if the information isn't accessible to the
+ * caller.
+ *
+ * @param pcb Where to store the result (in bytes).
+ */
+RTDECL(int) RTSystemQueryAvailableRam(uint64_t *pcb);
+
+/**
+ * Queries the amount of RAM that is currently locked down or in some other
+ * way made impossible to virtualize within reasonably short time.
+ *
+ * The purposes of this API is, when combined with RTSystemQueryTotalRam, to
+ * be able to determine an absolute max limit for how much fixed memory it is
+ * (theoretically) possible to allocate (or lock down).
+ *
+ * The kind memory covered by this function includes:
+ * - locked (wired) memory - like for instance RTR0MemObjLockUser
+ * and RTR0MemObjLockKernel makes,
+ * - kernel pools and heaps - like for instance the ring-0 variant
+ * of RTMemAlloc taps into,
+ * - fixed (not pageable) kernel allocations - like for instance
+ * all the RTR0MemObjAlloc* functions makes,
+ * - any similar memory that isn't easily swapped out, discarded,
+ * or flushed to disk.
+ *
+ * This works against the value returned by RTSystemQueryTotalRam, and
+ * the value reported by this function can never be larger than what a
+ * call to RTSystemQueryTotalRam returns.
+ *
+ * The short time term here is relative to swapping to disk like in
+ * RTSystemQueryTotalRam. This could mean that (part of) the dirty buffers
+ * in the dynamic I/O cache could be included in the total. If the dynamic
+ * I/O cache isn't likely to either flush buffers when the load increases
+ * and put them back into normal circulation, they should be included in
+ * the memory accounted for here.
+ *
+ * @retval VINF_SUCCESS and *pcb on success.
+ * @retval VERR_NOT_SUPPORTED if the information isn't available on the
+ * system in general. The caller must handle this scenario.
+ * @retval VERR_ACCESS_DENIED if the information isn't accessible to the
+ * caller.
+ *
+ * @param pcb Where to store the result (in bytes).
+ *
+ * @remarks This function could've been inverted and called
+ * RTSystemQueryAvailableRam, but that might give impression that
+ * it would be possible to allocate the amount of memory it
+ * indicates for a single purpose, something which would be very
+ * improbable on most systems.
+ *
+ * @remarks We might have to add another output parameter to this function
+ * that indicates if some of the memory kinds listed above cannot
+ * be accounted for on the system and therefore is not include in
+ * the returned amount.
+ */
+RTDECL(int) RTSystemQueryUnavailableRam(uint64_t *pcb);
+
+
+/**
+ * The DMI strings.
+ */
+typedef enum RTSYSDMISTR
+{
+ /** Invalid zero entry. */
+ RTSYSDMISTR_INVALID = 0,
+ /** The product name. */
+ RTSYSDMISTR_PRODUCT_NAME,
+ /** The product version. */
+ RTSYSDMISTR_PRODUCT_VERSION,
+ /** The product UUID. */
+ RTSYSDMISTR_PRODUCT_UUID,
+ /** The product serial. */
+ RTSYSDMISTR_PRODUCT_SERIAL,
+ /** The system manufacturer. */
+ RTSYSDMISTR_MANUFACTURER,
+ /** The end of the valid strings. */
+ RTSYSDMISTR_END,
+ /** The usual 32-bit hack. */
+ RTSYSDMISTR_32_BIT_HACK = 0x7fffffff
+} RTSYSDMISTR;
+
+/**
+ * Queries a DMI string.
+ *
+ * @returns IPRT status code.
+ * @retval VINF_SUCCESS on success.
+ * @retval VERR_BUFFER_OVERFLOW if the buffer is too small. The buffer will
+ * contain the chopped off result in this case, provided cbBuf isn't 0.
+ * @retval VERR_ACCESS_DENIED if the information isn't accessible to the
+ * caller.
+ * @retval VERR_NOT_SUPPORTED if the information isn't available on the system
+ * in general. The caller must expect this status code and deal with
+ * it.
+ *
+ * @param enmString Which string to query.
+ * @param pszBuf Where to store the string. This is always
+ * terminated, even on error.
+ * @param cbBuf The buffer size.
+ */
+RTDECL(int) RTSystemQueryDmiString(RTSYSDMISTR enmString, char *pszBuf, size_t cbBuf);
+
+/** @name Flags for RTSystemReboot and RTSystemShutdown.
+ * @{ */
+/** Reboot the system after shutdown. */
+#define RTSYSTEM_SHUTDOWN_REBOOT UINT32_C(0)
+/** Reboot the system after shutdown.
+ * The call may return VINF_SYS_MAY_POWER_OFF if the OS /
+ * hardware combination may power off instead of halting. */
+#define RTSYSTEM_SHUTDOWN_HALT UINT32_C(1)
+/** Power off the system after shutdown.
+ * This may be equvivalent to a RTSYSTEM_SHUTDOWN_HALT on systems where we
+ * cannot figure out whether the hardware/OS implements the actual powering
+ * off. If we can figure out that it's not supported, an
+ * VERR_SYS_CANNOT_POWER_OFF error is raised. */
+#define RTSYSTEM_SHUTDOWN_POWER_OFF UINT32_C(2)
+/** Power off the system after shutdown, or halt it if that's not possible. */
+#define RTSYSTEM_SHUTDOWN_POWER_OFF_HALT UINT32_C(3)
+/** The shutdown action mask. */
+#define RTSYSTEM_SHUTDOWN_ACTION_MASK UINT32_C(3)
+/** Unplanned shutdown/reboot. */
+#define RTSYSTEM_SHUTDOWN_UNPLANNED UINT32_C(0)
+/** Planned shutdown/reboot. */
+#define RTSYSTEM_SHUTDOWN_PLANNED RT_BIT_32(2)
+/** Force the system to shutdown/reboot regardless of objecting application
+ * or other stuff. This flag might not be realized on all systems. */
+#define RTSYSTEM_SHUTDOWN_FORCE RT_BIT_32(3)
+/** Parameter validation mask. */
+#define RTSYSTEM_SHUTDOWN_VALID_MASK UINT32_C(0x0000000f)
+/** @} */
+
+/**
+ * Shuts down the system.
+ *
+ * @returns IPRT status code on failure, on success it may or may not return
+ * depending on the OS.
+ * @retval VINF_SUCCESS
+ * @retval VINF_SYS_MAY_POWER_OFF
+ * @retval VERR_SYS_SHUTDOWN_FAILED
+ * @retval VERR_SYS_CANNOT_POWER_OFF
+ *
+ * @param cMsDelay The delay before the actual reboot. If this is
+ * not supported by the OS, an immediate reboot
+ * will be performed.
+ * @param fFlags Shutdown flags, see RTSYSTEM_SHUTDOWN_XXX.
+ * @param pszLogMsg Message for the log and users about why we're
+ * shutting down.
+ */
+RTDECL(int) RTSystemShutdown(RTMSINTERVAL cMsDelay, uint32_t fFlags, const char *pszLogMsg);
+
+/**
+ * Checks if we're executing inside a virtual machine (VM).
+ *
+ * The current implemention is very simplistic and won't try to detect the
+ * presence of a virtual machine monitor (VMM) unless it openly tells us it is
+ * there.
+ *
+ * @returns true if inside a VM, false if on real hardware.
+ *
+ * @todo If more information is needed, like which VMM it is and which
+ * version and such, add one or two new APIs.
+ */
+RTDECL(bool) RTSystemIsInsideVM(void);
+
+/**
+ * System firmware types.
+ */
+typedef enum RTSYSFWTYPE
+{
+ /** Invalid zero value. */
+ RTSYSFWTYPE_INVALID = 0,
+ /** Unknown firmware. */
+ RTSYSFWTYPE_UNKNOWN,
+ /** Firmware is BIOS. */
+ RTSYSFWTYPE_BIOS,
+ /** Firmware is UEFI. */
+ RTSYSFWTYPE_UEFI,
+ /** End valid firmware values (exclusive). */
+ RTSYSFWTYPE_END,
+ /** The usual 32-bit hack. */
+ RTSYSFWTYPE_32_BIT_HACK = 0x7fffffff
+} RTSYSFWTYPE;
+/** Pointer to a system firmware type. */
+typedef RTSYSFWTYPE *PRTSYSFWTYPE;
+
+/**
+ * Queries the system's firmware type.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_NOT_SUPPORTED if not supported or implemented.
+ * @param penmType Where to return the firmware type on success.
+ */
+RTDECL(int) RTSystemQueryFirmwareType(PRTSYSFWTYPE penmType);
+
+/**
+ * Translates the @a enmType value to a string.
+ *
+ * @returns Read-only name.
+ * @param enmType The firmware type to convert to string.
+ */
+RTDECL(const char *) RTSystemFirmwareTypeName(RTSYSFWTYPE enmType);
+
+/**
+ * Boolean firmware values queriable via RTSystemQueryFirmwareBoolean().
+ */
+typedef enum RTSYSFWBOOL
+{
+ /** Invalid property, do not use. */
+ RTSYSFWBOOL_INVALID = 0,
+ /** Whether Secure Boot is enabled or not (type: boolean). */
+ RTSYSFWBOOL_SECURE_BOOT,
+ /** End of valid */
+ RTSYSFWBOOL_END,
+ /** The usual 32-bit hack. */
+ RTSYSFWBOOL_32_BIT_HACK = 0x7fffffff
+} RTSYSFWBOOL;
+
+/**
+ * Queries the value of a firmware property.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_NOT_SUPPORTED if we cannot query firmware properties on the host.
+ * @retval VERR_SYS_UNSUPPORTED_FIRMWARE_PROPERTY if @a enmBoolean isn't
+ * supported.
+ * @param enmBoolean The value to query.
+ * @param pfValue Where to return the value.
+ */
+RTDECL(int) RTSystemQueryFirmwareBoolean(RTSYSFWBOOL enmBoolean, bool *pfValue);
+
+#ifdef RT_OS_WINDOWS
+
+/**
+ * Get the Windows NT build number.
+ *
+ * @returns NT build number.
+ *
+ * @remarks Windows NT only. Requires IPRT to be initialized.
+ */
+RTDECL(uint32_t) RTSystemGetNtBuildNo(void);
+
+/** Makes an NT version for comparison with RTSystemGetNtVersion(). */
+# define RTSYSTEM_MAKE_NT_VERSION(a_uMajor, a_uMinor, a_uBuild) \
+ ( ((uint64_t)(a_uMajor) << 52) | ((uint64_t)((a_uMinor) & 0xfffU) << 40) | ((uint32_t)(a_uBuild)) )
+/** Extracts the major version number from a RTSYSTEM_MAKE_NT_VERSION value. */
+# define RTSYSTEM_NT_VERSION_GET_MAJOR(a_uNtVersion) ((uint32_t)((a_uNtVersion) >> 52))
+/** Extracts the minor version number from a RTSYSTEM_MAKE_NT_VERSION value. */
+# define RTSYSTEM_NT_VERSION_GET_MINOR(a_uNtVersion) ((uint32_t)((a_uNtVersion) >> 40) & UINT32_C(0xfff))
+/** Extracts the build number from a RTSYSTEM_MAKE_NT_VERSION value. */
+# define RTSYSTEM_NT_VERSION_GET_BUILD(a_uNtVersion) ((uint32_t)(a_uNtVersion))
+
+/**
+ * Get the Windows NT version number.
+ *
+ * @returns Version formatted using RTSYSTEM_MAKE_NT_VERSION().
+ *
+ * @remarks Windows NT only. Requires IPRT to be initialized.
+ */
+RTDECL(uint64_t) RTSystemGetNtVersion(void);
+
+/**
+ * Get the Windows NT product type (OSVERSIONINFOW::wProductType).
+ */
+RTDECL(uint8_t) RTSystemGetNtProductType(void);
+
+#endif /* RT_OS_WINDOWS */
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_system_h */
+
diff --git a/include/iprt/table.h b/include/iprt/table.h
new file mode 100644
index 00000000..d8bd8f88
--- /dev/null
+++ b/include/iprt/table.h
@@ -0,0 +1,726 @@
+/** @file
+ * IPRT - Abstract Table/Trees.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_table_h
+#define IPRT_INCLUDED_table_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+
+/** @defgroup grp_rt_tab RTTab - Generic Tree and Table Interface.
+ * @ingroup grp_rt
+ * @{
+ */
+
+RT_C_DECLS_BEGIN
+
+/** Pointer to an allocator. */
+typedef struct RTTABALLOCATOR *PRTTABALLOCATOR;
+
+/**
+ * Allocates memory.
+ *
+ * @returns Pointer to the allocated memory.
+ * @returns NULL on failure. (don't throw!)
+ * @param pAllocator The allocator structure.
+ * @param cb The number of bytes to allocate. (Never 0.)
+ */
+typedef DECLCALLBACKTYPE(void *, FNRTTABALLOC,(PRTTABALLOCATOR pAllocator, size_t cb));
+/** Pointer to a FNRTTABALLOC() function. */
+typedef FNRTTABALLOC *PFNRTTABALLOC;
+
+/**
+ * Frees memory.
+ *
+ * @param pAllocator The allocator structure.
+ * @param pv The memory to free. (can be NULL)
+ */
+typedef DECLCALLBACKTYPE(void *, FNRTTABFREE,(PRTTABALLOCATOR pAllocator, void *pv));
+/** Pointer to a FNRTTABFREE() function. */
+typedef FNRTTABFREE *PFNRTTABFREE;
+
+/**
+ * The allocator structure.
+ * (Hint: use this as like 'base class' for your custom allocators.)
+ */
+typedef struct RTTABALLOCATOR
+{
+ /** The allocation function. */
+ PFNRTTABALLOC pfnAlloc;
+ /** The free function. */
+ PFNRTTABFREE pfnFree;
+} RTTABALLOCATOR;
+
+/**
+ * Gets the default allocator.
+ *
+ * @returns Pointer to the default allocator.
+ */
+RTDECL(RTTABALLOCATOR) RTTabDefaultAllocator(void);
+
+
+/**
+ * Compares two table items.
+ *
+ * @returns 0 if equal
+ * @returns <0 if pvItem1 is less than pvItem2 (pvItem2 is then greater than pvItem1).
+ * @returns >0 if pvItem1 is less than pvItem2 (pvItem1 is then greater than pvItem2).
+ *
+ * @param pvItem1 The first item.
+ * @param pvItem2 The second item.
+ * @param pvUser The user argument.
+ */
+typedef DECLCALLBACKTYPE(int, FNRTTABCOMP,(const void *pvItem1, const void *pvItem2, void *pvUser));
+/** Pointer to a FNRTTABCOMP() function. */
+typedef FNRTTABCOMP *PFNRTTABCOMP;
+
+/**
+ * Duplicates a table item.
+ * This is used when duplicating or copying a table.
+ *
+ * @returns Pointer to the copy.
+ * @returns NULL on failure.
+ *
+ * @param pvItem The item to copy.
+ * @param pvUser The user argument.
+ */
+typedef DECLCALLBACKTYPE(void *, FNRTTABDUPLICATE,(const void *pvItem, void *pvUser));
+/** Pointer to a FNRTTABDUPLICATE() function. */
+typedef FNRTTABDUPLICATE *PFNRTTABDUPLICATE;
+
+/**
+ * Callback function for doing something with an item.
+ *
+ * What exactly we're doing is specific to the context of the call.
+ *
+ * @param pvItem The item.
+ * @param pvUser The user argument.
+ */
+typedef DECLCALLBACKTYPE(void, FNRTTABCALLBACK,(const void *pvItem, void *pvUser));
+/** Pointer to a FNRTTABCALLBACK() function. */
+typedef FNRTTABCALLBACK *PFNRTTABCALLBACK;
+
+
+/** Pointer to const table operations. */
+typedef const struct RTTABOPS *PCRTTABOPS;
+/** Pointer to a table. */
+typedef struct RTTAB *PRTTAB;
+/** Pointer to a const table. */
+typedef const struct RTTAB *PCRTTAB;
+/** Pointer to a traverser. */
+typedef struct RTTABTRAVERSER *PRTTABTRAVERSER;
+/** Pointer to a const traverser. */
+typedef const struct RTTABTRAVERSER *PCRTTABTRAVERSER;
+/** Pointer to a traverser core. */
+typedef struct RTTABTRAVERSERCORE *PRTTABTRAVERSERCORE;
+/** Pointer to a const traverser core. */
+typedef const struct RTTABTRAVERSERCORE *PCRTTABTRAVERSERCORE;
+
+
+/**
+ * Table operations.
+ */
+typedef struct RTTABOPS
+{
+ /**
+ * Create a table.
+ *
+ * @returns Pointer to the new table.
+ * @returns NULL if we're out of memory or some other resource.
+ * @param pOps The table operations.
+ * @param fCreateFlags The table type specific creation flags.
+ * @param pAllocator Custom allocator. Pass NULL for the default allocator.
+ * @param pfnComp The comparision function.
+ */
+ DECLCALLBACKMEMBER(PRTTAB, pfnCreate,(PCRTTABOPS pOps, unsigned fCreateFlags, PRTTABALLOCATOR pAllocator, PFNRTTABCOMP pfnComp));
+
+ /**
+ * Duplicates a table to a table of the same type.
+ *
+ * @returns Pointer to the new table.
+ * @returns NULL if we're out of memory or some other resource.
+ * @param pTab The table to duplicate.
+ * @param pfnDuplicate Pointer to the item duplication function. If NULL the new table will
+ * be referencing the same data as the old one.
+ * @param pfnNewCB Callback which is called for all the items in the new table. Optional.
+ * @param pAllocator Custom allocator. Pass NULL to use the same allocator as pTab.
+ */
+ DECLCALLBACKMEMBER(PRTTAB, pfnDuplicate,(PCRTTAB pTab, PFNRTTABDUPLICATE pfnDuplicate, PFNRTTABCALLBACK pfnNewCB, PRTTABALLOCATOR pAllocator));
+
+ /**
+ * Destroys a table.
+ *
+ * @param pTab The table to destroy.
+ */
+ DECLCALLBACKMEMBER(void, pfnDestroy,(PRTTAB pTab));
+
+ /**
+ * Inserts an item into the table, if a matching item is encountered
+ * the pointer to the pointer to it will be returned.
+ *
+ * @returns Pointer to the item pointer in the table.
+ * This can be used to replace existing items (don't break anything, dude).
+ * @returns NULL if we failed to allocate memory for the new node.
+ * @param pTab The table.
+ * @param pvItem The item which will be inserted if an matching item was not found in the table.
+ */
+ DECLCALLBACKMEMBER(void **, pfnProbe,(PRTTAB pTab, void *pvItem));
+
+ /**
+ * Inserts an item into the table, fail if a matching item exists.
+ *
+ * @returns NULL on success and allocation failure.
+ * @returns Pointer to the matching item.
+ * @param pTab The table.
+ * @param pvItem The item which is to be inserted.
+ */
+ DECLCALLBACKMEMBER(void *, pfnInsert,(PRTTAB pTab, void *pvItem));
+
+ /**
+ * Inserts an item into the table, if a matching item is encountered
+ * it will be replaced and returned.
+ *
+ * @returns NULL if inserted and allocation failure.
+ * @returns Pointer to the replaced item.
+ * @param pTab The table.
+ * @param pvItem The item which is to be inserted.
+ */
+ DECLCALLBACKMEMBER(void *, pfnReplace,(PRTTAB pTab, void *pvItem));
+
+ /**
+ * Removes an item from the table if found.
+ *
+ * @returns Pointer to the removed item.
+ * @returns NULL if no item matched pvItem.
+ * @param pTab The table.
+ * @param pvItem The item which is to be inserted.
+ */
+ DECLCALLBACKMEMBER(void *, pfnRemove,(PRTTAB pTab, const void *pvItem));
+
+ /**
+ * Finds an item in the table.
+ *
+ * @returns Pointer to the item it found.
+ * @returns NULL if no item matched pvItem.
+ * @param pTab The table.
+ * @param pvItem The item which is to be inserted.
+ */
+ DECLCALLBACKMEMBER(void *, pfnFind,(PRTTAB pTab, const void *pvItem));
+
+ /**
+ * Initializes a traverser to the NULL item.
+ *
+ * The NULL item is an imaginary table item before the first and after
+ * the last items in the table.
+ *
+ * @returns Pointer to the traverser positioned at the NULL item.
+ * @returns NULL on failure to allocate the traverser.
+ *
+ * @param pTab The table.
+ * @param pTravNew Pointer to a preallocated structure. Optional.
+ */
+ DECLCALLBACKMEMBER(PRTTABTRAVERSERCORE, pfnTravInit,(PRTTAB pTab, PRTTABTRAVERSER pTravNew));
+
+ /**
+ * Initializes a traverser to the first item in the table.
+ *
+ * If the table is empty, the traverser will be positioned at the NULL item
+ * like with RTTabTravInit().
+ *
+ * @returns Pointer to the traverser positioned at the first item or NULL item.
+ * @returns NULL on failure to allocate the traverser.
+ *
+ * @param pTab The table.
+ * @param pTravNew Pointer to a preallocated structure. Optional.
+ */
+ DECLCALLBACKMEMBER(PRTTABTRAVERSERCORE, pfnTravFirst,(PRTTAB pTab, PRTTABTRAVERSER pTravNew));
+
+ /**
+ * Initializes a traverser to the last item in the table.
+ *
+ * If the table is empty, the traverser will be positioned at the NULL item
+ * like with RTTabTravInit().
+ *
+ * @returns Pointer to the traverser positioned at the last item or NULL item.
+ * @returns NULL on failure to allocate the traverser.
+ *
+ * @param pTab The table.
+ * @param pTravNew Pointer to a preallocated structure. Optional.
+ */
+ DECLCALLBACKMEMBER(PRTTABTRAVERSERCORE, pfnTravLast,(PRTTAB pTab, PRTTABTRAVERSER pTravNew));
+
+ /**
+ * Initializes a traverser to an item matching the given one.
+ *
+ * If the item isn't found, the traverser will be positioned at the NULL item
+ * like with RTTabTravInit().
+ *
+ * @returns Pointer to the traverser positioned at the matching item or NULL item.
+ * @returns NULL on failure to allocate the traverser.
+ *
+ * @param pTab The table.
+ * @param pTravNew Pointer to a preallocated structure. Optional.
+ * @param pvItem The item to find the match to.
+ */
+ DECLCALLBACKMEMBER(PRTTABTRAVERSERCORE, pfnTravFind,(PRTTAB pTab, PRTTABTRAVERSER pTravNew, const void *pvItem));
+
+ /**
+ * Initializes a traverser to the inserted item.
+ *
+ * If there already exists an item in the tree matching pvItem, the traverser
+ * is positioned at that item like with RTTabTravFind().
+ *
+ * If the insert operation failes because of an out of memory condition, the
+ * traverser will be positioned at the NULL item like with RTTabTravInit().
+ *
+ * @returns Pointer to the traverser positioned at the inserted, existing or NULL item.
+ * @returns NULL on failure to allocate the traverser.
+ *
+ * @param pTab The table.
+ * @param pTravNew Pointer to a preallocated structure. Optional.
+ * @param pvItem The item to be inserted.
+ */
+ DECLCALLBACKMEMBER(PRTTABTRAVERSERCORE, pfnTravInsert,(PRTTAB pTab, PRTTABTRAVERSER pTravNew, void *pvItem));
+
+ /**
+ * Duplicates a traverser.
+ *
+ * @returns The pointer to the duplicate.
+ * @returns NULL on allocation failure.
+ *
+ * @param pTrav The traverser to duplicate.
+ * @param pTravNew Pointer to a preallocated structure. Optional.
+ */
+ DECLCALLBACKMEMBER(PRTTABTRAVERSERCORE, pfnTravDuplicate,(PRTTABTRAVERSERCORE pTrav, PCRTTABTRAVERSER pTravNew));
+
+ /**
+ * Frees a traverser.
+ *
+ * This can safely be called even if the traverser structure
+ * wasn't dynamically allocated or the constructor failed.
+ *
+ * @param pTrav The traverser which is to be free.
+ */
+ DECLCALLBACKMEMBER(void, pfnTravFree,(PRTTABTRAVERSERCORE pTrav));
+
+ /**
+ * Gets the current item.
+ *
+ * @returns The current item. (NULL indicates the imaginary NULL item.)
+ * @param pTrav The traverser.
+ */
+ DECLCALLBACKMEMBER(void *, pfnTravCur,(PCRTTABTRAVERSERCORE pTrav));
+
+ /**
+ * Advances to the next item.
+ *
+ * @returns The new current item. (NULL indicates the imaginary NULL item.)
+ * @param pTrav The traverser.
+ */
+ DECLCALLBACKMEMBER(void *, pfnTravNext,(PRTTABTRAVERSERCORE pTrav));
+
+ /**
+ * Advances to the previous item.
+ *
+ * @returns The new current item. (NULL indicates the imaginary NULL item.)
+ * @param pTrav The traverser.
+ */
+ DECLCALLBACKMEMBER(void *, pfnTravPrev,(PRTTABTRAVERSERCORE pTrav));
+
+ /**
+ * Replaces the current item.
+ *
+ * This has the same restrictions as RTTabProbe(), e.g. it's not permitted to
+ * break the order of the table.
+ *
+ * @returns The replaced item.
+ * @returns NULL if the current item is the NULL item. The traverser
+ * and table remains unchanged.
+ * @param pTrav The traverser.
+ * @param pvItem The item to be inserted.
+ */
+ DECLCALLBACKMEMBER(void *, pfnTravReplace,(PRTTABTRAVERSERCORE pTrav, void *pvItem));
+
+ /** The type of table type. */
+ const char *pszType;
+} RTTABOPS;
+
+/**
+ * A table.
+ */
+typedef struct RTTAB
+{
+ /** The table operations. */
+ PCRTTABOPS pOps;
+ /** The function for comparing table items. */
+ PFNRTTABCOMP pfnComp;
+ /** The number of items in the table. */
+ RTUINT cItems;
+ /** The table generation number.
+ * This must be updated whenever the table changes. */
+ RTUINT idGeneration;
+} RTTAB;
+
+
+/**
+ * Create a table.
+ *
+ * @returns Pointer to the new table.
+ * @returns NULL if we're out of memory or some other resource.
+ * @param pOps The table operations.
+ * @param fCreateFlags The table type specific creation flags.
+ * @param pAllocator Custom allocator. Pass NULL for the default allocator.
+ * @param pfnComp The comparision function.
+ */
+DECLINLINE(PRTTAB) RTTabCreate(PCRTTABOPS pOps, unsigned fCreateFlags, PRTTABALLOCATOR pAllocator, PFNRTTABCOMP pfnComp)
+{
+ return pOps->pfnCreate(pOps, fCreateFlags, pAllocator, pfnComp);
+}
+
+/**
+ * Duplicates a table to a table of the same type.
+ *
+ * @returns Pointer to the new table.
+ * @returns NULL if we're out of memory or some other resource.
+ * @param pTab The table to duplicate.
+ * @param pfnDuplicate Pointer to the item duplication function. If NULL the new table will
+ * be referencing the same data as the old one.
+ * @param pfnNewCB Callback which is called for all the items in the new table. Optional.
+ * @param pAllocator Custom allocator. Pass NULL to use the same allocator as pTab.
+ */
+DECLINLINE(PRTTAB) RTTabDuplicate(PCRTTAB pTab, PFNRTTABDUPLICATE pfnDuplicate, PFNRTTABCALLBACK pfnNewCB, PRTTABALLOCATOR pAllocator)
+{
+ return pTab->pOps->pfnDuplicate(pTab, pfnDuplicate, pfnNewCB, pAllocator);
+}
+
+/**
+ * Destroys a table.
+ *
+ * @param pTab The table to destroy.
+ */
+DECLINLINE(void) RTTabDestroy(PRTTAB pTab)
+{
+ pTab->pOps->pfnDestroy(pTab);
+}
+
+/**
+ * Count the item in the table.
+ *
+ * @returns Number of items in the table.
+ * @param pTab The table to count.
+ */
+DECLINLINE(RTUINT) RTTabCount(PRTTAB pTab)
+{
+ return pTab->cItems;
+}
+
+/**
+ * Inserts an item into the table, if a matching item is encountered
+ * the pointer to the pointer to it will be returned.
+ *
+ * @returns Pointer to the item pointer in the table.
+ * This can be used to replace existing items (don't break anything, dude).
+ * @returns NULL if we failed to allocate memory for the new node.
+ * @param pTab The table.
+ * @param pvItem The item which will be inserted if an matching item was not found in the table.
+ */
+DECLINLINE(void **) RTTabProbe(PRTTAB pTab, void *pvItem)
+{
+ return pTab->pOps->pfnProbe(pTab, pvItem);
+}
+
+/**
+ * Inserts an item into the table, fail if a matching item exists.
+ *
+ * @returns NULL on success and allocation failure.
+ * @returns Pointer to the matching item.
+ * @param pTab The table.
+ * @param pvItem The item which is to be inserted.
+ */
+DECLINLINE(void *) RTTabInsert(PRTTAB pTab, void *pvItem)
+{
+ return pTab->pOps->pfnInsert(pTab, pvItem);
+}
+
+/**
+ * Inserts an item into the table, if a matching item is encountered
+ * it will be replaced and returned.
+ *
+ * @returns NULL if inserted and allocation failure.
+ * @returns Pointer to the replaced item.
+ * @param pTab The table.
+ * @param pvItem The item which is to be inserted.
+ */
+DECLINLINE(void *) RTTabReplace(PRTTAB pTab, void *pvItem)
+{
+ return pTab->pOps->pfnReplace(pTab, pvItem);
+}
+
+/**
+ * Removes an item from the table if found.
+ *
+ * @returns Pointer to the removed item.
+ * @returns NULL if no item matched pvItem.
+ * @param pTab The table.
+ * @param pvItem The item which is to be inserted.
+ */
+DECLINLINE(void *) RTTabRemove(PRTTAB pTab, const void *pvItem)
+{
+ return pTab->pOps->pfnRemove(pTab, pvItem);
+}
+
+/**
+ * Finds an item in the table.
+ *
+ * @returns Pointer to the item it found.
+ * @returns NULL if no item matched pvItem.
+ * @param pTab The table.
+ * @param pvItem The item to find the match to.
+ */
+DECLINLINE(void *) RTTabFind(PRTTAB pTab, const void *pvItem)
+{
+ return pTab->pOps->pfnFind(pTab, pvItem);
+}
+
+
+/**
+ * Common traverser core.
+ */
+typedef struct RTTABTRAVERSERCORE
+{
+ /** The table being traversed. */
+ PRTTAB pTab;
+ /** Indicates that this traverser was allocated. */
+ bool fAllocated;
+ /** The table generation id this traverser was last updated for.
+ * This is used to catch up with table changes. */
+ RTUINT idGeneration;
+} RTTABTRAVERSERCORE;
+
+/**
+ * Generic traverser structure.
+ *
+ * Tree implementations will use the tree specific part by mapping
+ * this structure onto their own internal traverser structure.
+ *
+ * @remark It would be better to use alloca() for allocating the structure,
+ * OTOH this is simpler for the user.
+ */
+typedef struct RTTABTRAVERSER
+{
+ /** The common core of the traverser data. */
+ RTTABTRAVERSERCORE Core;
+ /** The tree specific data. */
+ void *apvTreeSpecific[32];
+} RTTABTRAVERSER;
+
+
+/**
+ * Initializes a traverser to the NULL item.
+ *
+ * The NULL item is an imaginary table item before the first and after
+ * the last items in the table.
+ *
+ * @returns Pointer to the traverser positioned at the NULL item.
+ * @returns NULL on failure to allocate the traverser.
+ *
+ * @param pTab The table.
+ * @param pTravNew Pointer to a preallocated structure. Optional.
+ */
+DECLINLINE(PRTTABTRAVERSERCORE) RTTabTravInit(PRTTAB pTab, PRTTABTRAVERSER pTravNew)
+{
+ return pTab->pOps->pfnTravInit(pTab, pTravNew);
+}
+
+/**
+ * Initializes a traverser to the first item in the table.
+ *
+ * If the table is empty, the traverser will be positioned at the NULL item
+ * like with RTTabTravInit().
+ *
+ * @returns Pointer to the traverser positioned at the first item or NULL item.
+ * @returns NULL on failure to allocate the traverser.
+ *
+ * @param pTab The table.
+ * @param pTravNew Pointer to a preallocated structure. Optional.
+ */
+DECLINLINE(PRTTABTRAVERSERCORE) RTTabTravFirst(PRTTAB pTab, PRTTABTRAVERSER pTravNew)
+{
+ return pTab->pOps->pfnTravFirst(pTab, pTravNew);
+}
+
+/**
+ * Initializes a traverser to the last item in the table.
+ *
+ * If the table is empty, the traverser will be positioned at the NULL item
+ * like with RTTabTravInit().
+ *
+ * @returns Pointer to the traverser positioned at the last item or NULL item.
+ * @returns NULL on failure to allocate the traverser.
+ *
+ * @param pTab The table.
+ * @param pTravNew Pointer to a preallocated structure. Optional.
+ */
+DECLINLINE(PRTTABTRAVERSERCORE) RTTabTravLast(PRTTAB pTab, PRTTABTRAVERSER pTravNew)
+{
+ return pTab->pOps->pfnTravLast(pTab, pTravNew);
+}
+
+/**
+ * Initializes a traverser to an item matching the given one.
+ *
+ * If the item isn't found, the traverser will be positioned at the NULL item
+ * like with RTTabTravInit().
+ *
+ * @returns Pointer to the traverser positioned at the matching item or NULL item.
+ * @returns NULL on failure to allocate the traverser.
+ *
+ * @param pTab The table.
+ * @param pTravNew Pointer to a preallocated structure. Optional.
+ * @param pvItem The item to find the match to.
+ */
+DECLINLINE(PRTTABTRAVERSERCORE) RTTabTravFind(PRTTAB pTab, PRTTABTRAVERSER pTravNew, const void *pvItem)
+{
+ return pTab->pOps->pfnTravFind(pTab, pTravNew, pvItem);
+}
+
+/**
+ * Initializes a traverser to the inserted item.
+ *
+ * If there already exists an item in the tree matching pvItem, the traverser
+ * is positioned at that item like with RTTabTravFind().
+ *
+ * If the insert operation failes because of an out of memory condition, the
+ * traverser will be positioned at the NULL item like with RTTabTravInit().
+ *
+ * @returns Pointer to the traverser positioned at the inserted, existing or NULL item.
+ * @returns NULL on failure to allocate the traverser.
+ *
+ * @param pTab The table.
+ * @param pTravNew Pointer to a preallocated structure. Optional.
+ * @param pvItem The item to be inserted.
+ */
+DECLINLINE(PRTTABTRAVERSERCORE) RTTabTravInsert(PRTTAB pTab, PRTTABTRAVERSER pTravNew, void *pvItem)
+{
+ return pTab->pOps->pfnTravInsert(pTab, pTravNew, pvItem);
+}
+
+/**
+ * Duplicates a traverser.
+ *
+ * @returns The pointer to the duplicate.
+ * @returns NULL on allocation failure.
+ *
+ * @param pTrav The traverser to duplicate.
+ * @param pTravNew Pointer to a preallocated structure. Optional.
+ */
+DECLINLINE(PRTTABTRAVERSERCORE) RTTabTravDuplicate(PRTTABTRAVERSERCORE pTrav, PCRTTABTRAVERSER pTravNew)
+{
+ if (pTrav)
+ return pTrav->pTab->pOps->pfnTravDuplicate(pTrav, pTravNew);
+ return NULL;
+}
+
+/**
+ * Frees a traverser.
+ *
+ * This can safely be called even if the traverser structure
+ * wasn't dynamically allocated or the constructor failed.
+ *
+ * @param pTrav The traverser which is to be free.
+ */
+DECLINLINE(void) RTTabTravFree(PRTTABTRAVERSERCORE pTrav)
+{
+ if (pTrav && pTrav->fAllocated)
+ pTrav->pTab->pOps->pfnTravFree(pTrav);
+}
+
+/**
+ * Gets the current item.
+ *
+ * @returns The current item. (NULL indicates the imaginary NULL item.)
+ * @param pTrav The traverser.
+ */
+DECLINLINE(void *) RTTabTravCur(PCRTTABTRAVERSERCORE pTrav)
+{
+ return pTrav->pTab->pOps->pfnTravCur(pTrav);
+}
+
+/**
+ * Advances to the next item.
+ *
+ * @returns The new current item. (NULL indicates the imaginary NULL item.)
+ * @param pTrav The traverser.
+ */
+DECLINLINE(void *) RTTabTravNext(PRTTABTRAVERSERCORE pTrav)
+{
+ return pTrav->pTab->pOps->pfnTravNext(pTrav);
+}
+
+/**
+ * Advances to the previous item.
+ *
+ * @returns The new current item. (NULL indicates the imaginary NULL item.)
+ * @param pTrav The traverser.
+ */
+DECLINLINE(void *) RTTabTravPrev(PRTTABTRAVERSERCORE pTrav)
+{
+ return pTrav->pTab->pOps->pfnTravPrev(pTrav);
+}
+
+/**
+ * Replaces the current item.
+ *
+ * This has the same restrictions as RTTabProbe(), e.g. it's not permitted to
+ * break the order of the table.
+ *
+ * @returns The replaced item.
+ * @returns NULL if the current item is the NULL item. The traverser
+ * and table remains unchanged.
+ * @param pTrav The traverser.
+ * @param pvItem The item to be inserted.
+ */
+DECLINLINE(void *) RTTabTravReplace(PRTTABTRAVERSERCORE pTrav, void *pvItem)
+{
+ return pTrav->pTab->pOps->pfnTravReplace(pTrav, pvItem);
+}
+
+RT_C_DECLS_END
+
+/** @} */
+
+#endif /* !IPRT_INCLUDED_table_h */
diff --git a/include/iprt/tar.h b/include/iprt/tar.h
new file mode 100644
index 00000000..9acc0d40
--- /dev/null
+++ b/include/iprt/tar.h
@@ -0,0 +1,184 @@
+/** @file
+ * IPRT - Tar archive I/O.
+ */
+
+/*
+ * Copyright (C) 2009-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_tar_h
+#define IPRT_INCLUDED_tar_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+#include <iprt/time.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_tar RTTar - Tar archive I/O
+ * @ingroup grp_rt
+ *
+ * @deprecated Only used for legacy code and writing. Migrate new code to the
+ * VFS interface, add the write part when needed.
+ *
+ * @{
+ */
+
+/** A tar handle */
+typedef R3PTRTYPE(struct RTTARINTERNAL *) RTTAR;
+/** Pointer to a RTTAR interface handle. */
+typedef RTTAR *PRTTAR;
+/** Nil RTTAR interface handle. */
+#define NIL_RTTAR ((RTTAR)0)
+
+/** A tar file handle */
+typedef R3PTRTYPE(struct RTTARFILEINTERNAL *) RTTARFILE;
+/** Pointer to a RTTARFILE interface handle. */
+typedef RTTARFILE *PRTTARFILE;
+/** Nil RTTARFILE interface handle. */
+#define NIL_RTTARFILE ((RTTARFILE)0)
+
+/** Maximum length of a tar filename, excluding the terminating '\0'. More
+ * does not fit into a tar record. */
+#define RTTAR_NAME_MAX 99
+
+/**
+ * Creates a Tar archive.
+ *
+ * Use the mask to specify the access type.
+ *
+ * @returns IPRT status code.
+ *
+ * @param phTar Where to store the RTTAR handle.
+ * @param pszTarname The file name of the tar archive to create. Should
+ * not exist.
+ * @param fMode Open flags, i.e a combination of the RTFILE_O_* defines.
+ * The ACCESS, ACTION and DENY flags are mandatory!
+ */
+RTR3DECL(int) RTTarOpen(PRTTAR phTar, const char *pszTarname, uint32_t fMode);
+
+/**
+ * Close the Tar archive.
+ *
+ * @returns IPRT status code.
+ *
+ * @param hTar Handle to the RTTAR interface.
+ */
+RTR3DECL(int) RTTarClose(RTTAR hTar);
+
+/**
+ * Open a file in the Tar archive.
+ *
+ * @returns IPRT status code.
+ *
+ * @param hTar The handle of the tar archive.
+ * @param phFile Where to store the handle to the opened file.
+ * @param pszFilename Path to the file which is to be opened. (UTF-8)
+ * @param fOpen Open flags, i.e a combination of the RTFILE_O_* defines.
+ * The ACCESS, ACTION flags are mandatory! DENY flags
+ * are currently not supported.
+ *
+ * @remarks Write mode means append mode only. It is not possible to make
+ * changes to existing files.
+ *
+ * @remarks Currently it is not possible to open more than one file in write
+ * mode. Although open more than one file in read only mode (even when
+ * one file is opened in write mode) is always possible.
+ */
+RTR3DECL(int) RTTarFileOpen(RTTAR hTar, PRTTARFILE phFile, const char *pszFilename, uint32_t fOpen);
+
+/**
+ * Close the file opened by RTTarFileOpen.
+ *
+ * @returns IPRT status code.
+ *
+ * @param hFile The file handle to close.
+ */
+RTR3DECL(int) RTTarFileClose(RTTARFILE hFile);
+
+/**
+ * Read bytes from a file at a given offset.
+ * This function may modify the file position.
+ *
+ * @returns IPRT status code.
+ *
+ * @param hFile Handle to the file.
+ * @param off Where to read.
+ * @param pvBuf Where to put the bytes we read.
+ * @param cbToRead How much to read.
+ * @param pcbRead Where to return how much we actually read. If NULL
+ * an error will be returned for a partial read.
+ */
+RTR3DECL(int) RTTarFileReadAt(RTTARFILE hFile, uint64_t off, void *pvBuf, size_t cbToRead, size_t *pcbRead);
+
+/**
+ * Write bytes to a file at a given offset.
+ * This function may modify the file position.
+ *
+ * @returns IPRT status code.
+ *
+ * @param hFile Handle to the file.
+ * @param off Where to write.
+ * @param pvBuf What to write.
+ * @param cbToWrite How much to write.
+ * @param pcbWritten Where to return how much we actually wrote. If NULL
+ * an error will be returned for a partial write.
+ */
+RTR3DECL(int) RTTarFileWriteAt(RTTARFILE hFile, uint64_t off, const void *pvBuf, size_t cbToWrite, size_t *pcbWritten);
+
+/**
+ * Query the size of the file.
+ *
+ * @returns IPRT status code.
+ *
+ * @param hFile Handle to the file.
+ * @param pcbSize Where to store the filesize.
+ */
+RTR3DECL(int) RTTarFileGetSize(RTTARFILE hFile, uint64_t *pcbSize);
+
+/**
+ * Set the size of the file.
+ *
+ * @returns IPRT status code.
+ *
+ * @param hFile Handle to the file.
+ * @param cbSize The new file size.
+ */
+RTR3DECL(int) RTTarFileSetSize(RTTARFILE hFile, uint64_t cbSize);
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_tar_h */
+
diff --git a/include/iprt/tcp.h b/include/iprt/tcp.h
new file mode 100644
index 00000000..c637915e
--- /dev/null
+++ b/include/iprt/tcp.h
@@ -0,0 +1,514 @@
+/** @file
+ * IPRT - TCP/IP.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_tcp_h
+#define IPRT_INCLUDED_tcp_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+#include <iprt/thread.h>
+#include <iprt/net.h>
+#include <iprt/sg.h>
+#include <iprt/socket.h>
+
+#ifdef IN_RING0
+# error "There are no RTFile APIs available Ring-0 Host Context!"
+#endif
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_tcp RTTcp - TCP/IP
+ * @ingroup grp_rt
+ * @{
+ */
+
+
+/**
+ * Serve a TCP Server connection.
+ *
+ * @returns iprt status code.
+ * @returns VERR_TCP_SERVER_STOP to terminate the server loop forcing
+ * the RTTcpCreateServer() call to return.
+ * @param hSocket The socket which the client is connected to. The call
+ * will close this socket.
+ * @param pvUser User argument.
+ */
+typedef DECLCALLBACKTYPE(int, FNRTTCPSERVE,(RTSOCKET hSocket, void *pvUser));
+/** Pointer to a RTTCPSERVE(). */
+typedef FNRTTCPSERVE *PFNRTTCPSERVE;
+
+/**
+ * Create single connection at a time TCP Server in a separate thread.
+ *
+ * The thread will loop accepting connections and call pfnServe for
+ * each of the incoming connections in turn. The pfnServe function can
+ * return VERR_TCP_SERVER_STOP too terminate this loop. RTTcpServerDestroy()
+ * should be used to terminate the server.
+ *
+ * @returns iprt status code.
+ * @param pszAddress The address for creating a listening socket.
+ * If NULL or empty string the server is bound to all interfaces.
+ * @param uPort The port for creating a listening socket.
+ * @param enmType The thread type.
+ * @param pszThrdName The name of the worker thread.
+ * @param pfnServe The function which will serve a new client connection.
+ * @param pvUser User argument passed to pfnServe.
+ * @param ppServer Where to store the serverhandle.
+ */
+RTR3DECL(int) RTTcpServerCreate(const char *pszAddress, unsigned uPort, RTTHREADTYPE enmType, const char *pszThrdName,
+ PFNRTTCPSERVE pfnServe, void *pvUser, PPRTTCPSERVER ppServer);
+
+/**
+ * Create single connection at a time TCP Server.
+ * The caller must call RTTcpServerListen() to actually start the server.
+ *
+ * @returns iprt status code.
+ * @param pszAddress The address for creating a listening socket.
+ * If NULL the server is bound to all interfaces.
+ * @param uPort The port for creating a listening socket.
+ * @param ppServer Where to store the serverhandle.
+ */
+RTR3DECL(int) RTTcpServerCreateEx(const char *pszAddress, uint32_t uPort, PPRTTCPSERVER ppServer);
+
+/**
+ * Closes down and frees a TCP Server.
+ * This will also terminate any open connections to the server.
+ *
+ * @returns iprt status code.
+ * @param pServer Handle to the server.
+ */
+RTR3DECL(int) RTTcpServerDestroy(PRTTCPSERVER pServer);
+
+/**
+ * Listen for incoming connections.
+ *
+ * The function will loop accepting connections and call pfnServe for
+ * each of the incoming connections in turn. The pfnServe function can
+ * return VERR_TCP_SERVER_STOP too terminate this loop. A stopped server
+ * can only be destroyed.
+ *
+ * @returns iprt status code.
+ * @param pServer The server handle as returned from RTTcpServerCreateEx().
+ * @param pfnServe The function which will serve a new client connection.
+ * @param pvUser User argument passed to pfnServe.
+ */
+RTR3DECL(int) RTTcpServerListen(PRTTCPSERVER pServer, PFNRTTCPSERVE pfnServe, void *pvUser);
+
+/**
+ * Listen and accept one incoming connection.
+ *
+ * This is an alternative to RTTcpServerListen for the use the callbacks are not
+ * possible.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_TCP_SERVER_SHUTDOWN if shut down by RTTcpServerShutdown.
+ * @retval VERR_INTERRUPTED if the listening was interrupted.
+ *
+ * @param pServer The server handle as returned from RTTcpServerCreateEx().
+ * @param phClientSocket Where to return the socket handle to the client
+ * connection (on success only). This must be closed
+ * by calling RTTcpServerDisconnectClient2().
+ */
+RTR3DECL(int) RTTcpServerListen2(PRTTCPSERVER pServer, PRTSOCKET phClientSocket);
+
+/**
+ * Terminate the open connection to the server.
+ *
+ * @returns iprt status code.
+ * @param pServer Handle to the server.
+ */
+RTR3DECL(int) RTTcpServerDisconnectClient(PRTTCPSERVER pServer);
+
+/**
+ * Terminates an open client connect when using RTTcpListen2
+ *
+ * @returns IPRT status code.
+ * @param hClientSocket The client socket handle. This will be invalid upon
+ * return, whether successful or not. NIL is quietly
+ * ignored (VINF_SUCCESS).
+ */
+RTR3DECL(int) RTTcpServerDisconnectClient2(RTSOCKET hClientSocket);
+
+/**
+ * Shuts down the server, leaving client connections open.
+ *
+ * @returns IPRT status code.
+ * @param pServer Handle to the server.
+ */
+RTR3DECL(int) RTTcpServerShutdown(PRTTCPSERVER pServer);
+
+/**
+ * Connect (as a client) to a TCP Server.
+ *
+ * @returns iprt status code.
+ * @param pszAddress The address to connect to.
+ * @param uPort The port to connect to.
+ * @param pSock Where to store the handle to the established connection.
+ */
+RTR3DECL(int) RTTcpClientConnect(const char *pszAddress, uint32_t uPort, PRTSOCKET pSock);
+
+/** Opaque pointer used by RTTcpClientConnectEx and RTTcpClientCancelConnect. */
+typedef struct RTTCPCLIENTCONNECTCANCEL *PRTTCPCLIENTCONNECTCANCEL;
+
+/**
+ * Connect (as a client) to a TCP Server, extended version.
+ *
+ * @returns iprt status code.
+ * @param pszAddress The address to connect to.
+ * @param uPort The port to connect to.
+ * @param pSock Where to store the handle to the established connection.
+ * @param cMillies Number of milliseconds to wait for the connect attempt to complete.
+ * Use RT_INDEFINITE_WAIT to wait for ever.
+ * Use RT_SOCKETCONNECT_DEFAULT_WAIT to wait for the default time
+ * configured on the running system.
+ * @param ppCancelCookie Where to store information for canceling the
+ * operation (from a different thread). Optional.
+ *
+ * The pointer _must_ be initialized to NULL before a
+ * series of connection attempts begins, i.e. at a time
+ * where there will be no RTTcpClientCancelConnect
+ * calls racing access. RTTcpClientCancelConnect will
+ * set it to a special non-NULL value that causes the
+ * current or/and next connect call to fail.
+ *
+ * @sa RTTcpClientCancelConnect
+ */
+RTR3DECL(int) RTTcpClientConnectEx(const char *pszAddress, uint32_t uPort, PRTSOCKET pSock,
+ RTMSINTERVAL cMillies, PRTTCPCLIENTCONNECTCANCEL volatile *ppCancelCookie);
+
+/**
+ * Cancels a RTTcpClientConnectEx call on a different thread.
+ *
+ * @returns iprt status code.
+ * @param ppCancelCookie The address of the cookie pointer shared with the
+ * connect call.
+ */
+RTR3DECL(int) RTTcpClientCancelConnect(PRTTCPCLIENTCONNECTCANCEL volatile *ppCancelCookie);
+
+/**
+ * Close a socket returned by RTTcpClientConnect().
+ *
+ * @returns iprt status code.
+ * @param hSocket Socket descriptor.
+ */
+RTR3DECL(int) RTTcpClientClose(RTSOCKET hSocket);
+
+/**
+ * Close a socket returned by RTTcpClientConnect().
+ *
+ * @returns iprt status code.
+ * @param hSocket The socket handle.
+ * @param fGracefulShutdown If true, try do a graceful shutdown of the
+ * outgoing pipe and draining any lingering input.
+ * This is sometimes better for the server side.
+ * If false, just close the connection without
+ * further ado.
+ */
+RTR3DECL(int) RTTcpClientCloseEx(RTSOCKET hSocket, bool fGracefulShutdown);
+
+/**
+ * Creates connected pair of TCP sockets.
+ *
+ * @returns IPRT status code.
+ * @param phServer Where to return the "server" side of the pair.
+ * @param phClient Where to return the "client" side of the pair.
+ * @param fFlags Reserved, must be zero.
+ *
+ * @note There is no server or client side, but we gotta call it something.
+ */
+RTR3DECL(int) RTTcpCreatePair(PRTSOCKET phServer, PRTSOCKET phClient, uint32_t fFlags);
+
+/**
+ * Receive data from a socket.
+ *
+ * @returns iprt status code.
+ * @param hSocket Socket descriptor.
+ * @param pvBuffer Where to put the data we read.
+ * @param cbBuffer Read buffer size.
+ * @param pcbRead Number of bytes read.
+ * If NULL the entire buffer will be filled upon successful return.
+ * If not NULL a partial read can be done successfully.
+ */
+RTR3DECL(int) RTTcpRead(RTSOCKET hSocket, void *pvBuffer, size_t cbBuffer, size_t *pcbRead);
+
+/**
+ * Send data to a socket.
+ *
+ * @returns iprt status code.
+ * @retval VERR_INTERRUPTED if interrupted before anything was written.
+ *
+ * @param hSocket Socket descriptor.
+ * @param pvBuffer Buffer to write data to socket.
+ * @param cbBuffer How much to write.
+ */
+RTR3DECL(int) RTTcpWrite(RTSOCKET hSocket, const void *pvBuffer, size_t cbBuffer);
+
+/**
+ * Flush socket write buffers.
+ *
+ * @returns iprt status code.
+ * @param hSocket Socket descriptor.
+ */
+RTR3DECL(int) RTTcpFlush(RTSOCKET hSocket);
+
+/**
+ * Enables or disables delaying sends to coalesce packets.
+ *
+ * The TCP/IP stack usually uses the Nagle algorithm (RFC 896) to implement the
+ * coalescing.
+ *
+ * @returns iprt status code.
+ * @param hSocket Socket descriptor.
+ * @param fEnable When set to true enables coalescing.
+ */
+RTR3DECL(int) RTTcpSetSendCoalescing(RTSOCKET hSocket, bool fEnable);
+
+/**
+ * Sets send and receive buffer sizes.
+ *
+ * @returns iprt status code.
+ * @param hSocket Socket descriptor.
+ * @param cbSize Buffer size in bytes.
+ */
+RTR3DECL(int) RTTcpSetBufferSize(RTSOCKET hSocket, uint32_t cbSize);
+
+/**
+ * Socket I/O multiplexing.
+ * Checks if the socket is ready for reading.
+ *
+ * @returns iprt status code.
+ * @param hSocket Socket descriptor.
+ * @param cMillies Number of milliseconds to wait for the socket.
+ * Use RT_INDEFINITE_WAIT to wait for ever.
+ */
+RTR3DECL(int) RTTcpSelectOne(RTSOCKET hSocket, RTMSINTERVAL cMillies);
+
+/**
+ * Socket I/O multiplexing
+ * Checks if the socket is ready for one of the given events.
+ *
+ * @returns iprt status code.
+ * @param hSocket Socket descriptor.
+ * @param fEvents Event mask to wait for.
+ * Use the RTSOCKET_EVT_* defines.
+ * @param pfEvents Where to store the event mask on return.
+ * @param cMillies Number of milliseconds to wait for the socket.
+ * Use RT_INDEFINITE_WAIT to wait for ever.
+ */
+RTR3DECL(int) RTTcpSelectOneEx(RTSOCKET hSocket, uint32_t fEvents, uint32_t *pfEvents, RTMSINTERVAL cMillies);
+
+#if 0 /* skipping these for now - RTTcpServer* handles this. */
+/**
+ * Listen for connection on a socket.
+ *
+ * @returns iprt status code.
+ * @param hSocket Socket descriptor.
+ * @param cBackLog The maximum length the queue of pending connections
+ * may grow to.
+ */
+RTR3DECL(int) RTTcpListen(RTSOCKET hSocket, int cBackLog);
+
+/**
+ * Accept a connection on a socket.
+ *
+ * @returns iprt status code.
+ * @param hSocket Socket descriptor.
+ * @param uPort The port for accepting connection.
+ * @param pSockAccepted Where to store the handle to the accepted connection.
+ */
+RTR3DECL(int) RTTcpAccept(RTSOCKET hSocket, unsigned uPort, PRTSOCKET pSockAccepted);
+
+#endif
+
+/**
+ * Gets the address of the local side.
+ *
+ * @returns IPRT status code.
+ * @param hSocket Socket descriptor.
+ * @param pAddr Where to store the local address on success.
+ */
+RTR3DECL(int) RTTcpGetLocalAddress(RTSOCKET hSocket, PRTNETADDR pAddr);
+
+/**
+ * Gets the address of the other party.
+ *
+ * @returns IPRT status code.
+ * @param hSocket Socket descriptor.
+ * @param pAddr Where to store the peer address on success.
+ */
+RTR3DECL(int) RTTcpGetPeerAddress(RTSOCKET hSocket, PRTNETADDR pAddr);
+
+/**
+ * Send data from a scatter/gather buffer to a socket.
+ *
+ * @returns iprt status code.
+ * @retval VERR_INTERRUPTED if interrupted before anything was written.
+ *
+ * @param hSocket Socket descriptor.
+ * @param pSgBuf Scatter/gather buffer to write data to socket.
+ */
+RTR3DECL(int) RTTcpSgWrite(RTSOCKET hSocket, PCRTSGBUF pSgBuf);
+
+
+/**
+ * Send data from multiple buffers to a socket.
+ *
+ * This is convenience wrapper around the RTSocketSgWrite and RTSgBufInit calls
+ * for lazy coders. The "L" in the function name is short for "list" just like
+ * in the execl libc API.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_INTERRUPTED if interrupted before anything was written.
+ *
+ * @param hSocket The socket handle.
+ * @param cSegs The number of data segments in the following
+ * ellipsis.
+ * @param ... Pairs of buffer pointers (void const *) and buffer
+ * sizes (size_t). Make 101% sure the pointer is
+ * really size_t.
+ */
+RTR3DECL(int) RTTcpSgWriteL(RTSOCKET hSocket, size_t cSegs, ...);
+
+/**
+ * Send data from multiple buffers to a socket.
+ *
+ * This is convenience wrapper around the RTSocketSgWrite and RTSgBufInit calls
+ * for lazy coders. The "L" in the function name is short for "list" just like
+ * in the execl libc API.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_INTERRUPTED if interrupted before anything was written.
+ *
+ * @param hSocket The socket handle.
+ * @param cSegs The number of data segments in the following
+ * argument list.
+ * @param va Pairs of buffer pointers (void const *) and buffer
+ * sizes (size_t). Make 101% sure the pointer is
+ * really size_t.
+ */
+RTR3DECL(int) RTTcpSgWriteLV(RTSOCKET hSocket, size_t cSegs, va_list va);
+
+/**
+ * Receive data from a socket.
+ *
+ * This version doesn't block if there is no data on the socket.
+ *
+ * @returns IPRT status code.
+ *
+ * @param hSocket Socket descriptor.
+ * @param pvBuffer Where to put the data we read.
+ * @param cbBuffer Read buffer size.
+ * @param pcbRead Number of bytes read.
+ */
+RTR3DECL(int) RTTcpReadNB(RTSOCKET hSocket, void *pvBuffer, size_t cbBuffer, size_t *pcbRead);
+
+/**
+ * Send data to a socket.
+ *
+ * This version doesn't block if there is not enough room for the message.
+ *
+ * @returns IPRT status code.
+ *
+ * @param hSocket Socket descriptor.
+ * @param pvBuffer Buffer to write data to socket.
+ * @param cbBuffer How much to write.
+ * @param pcbWritten Number of bytes written.
+ */
+RTR3DECL(int) RTTcpWriteNB(RTSOCKET hSocket, const void *pvBuffer, size_t cbBuffer, size_t *pcbWritten);
+
+/**
+ * Send data from a scatter/gather buffer to a socket.
+ *
+ * This version doesn't block if there is not enough room for the message.
+ *
+ * @returns iprt status code.
+ * @retval VERR_INTERRUPTED if interrupted before anything was written.
+ *
+ * @param hSocket Socket descriptor.
+ * @param pSgBuf Scatter/gather buffer to write data to socket.
+ * @param pcbWritten Number of bytes written.
+ */
+RTR3DECL(int) RTTcpSgWriteNB(RTSOCKET hSocket, PCRTSGBUF pSgBuf, size_t *pcbWritten);
+
+
+/**
+ * Send data from multiple buffers to a socket.
+ *
+ * This version doesn't block if there is not enough room for the message.
+ * This is convenience wrapper around the RTSocketSgWrite and RTSgBufInit calls
+ * for lazy coders. The "L" in the function name is short for "list" just like
+ * in the execl libc API.
+ *
+ * @returns IPRT status code.
+ *
+ * @param hSocket The socket handle.
+ * @param cSegs The number of data segments in the following
+ * ellipsis.
+ * @param pcbWritten Number of bytes written.
+ * @param ... Pairs of buffer pointers (void const *) and buffer
+ * sizes (size_t). Make 101% sure the pointer is
+ * really size_t.
+ */
+RTR3DECL(int) RTTcpSgWriteLNB(RTSOCKET hSocket, size_t cSegs, size_t *pcbWritten, ...);
+
+/**
+ * Send data from multiple buffers to a socket.
+ *
+ * This version doesn't block if there is not enough room for the message.
+ * This is convenience wrapper around the RTSocketSgWrite and RTSgBufInit calls
+ * for lazy coders. The "L" in the function name is short for "list" just like
+ * in the execl libc API.
+ *
+ * @returns IPRT status code.
+ *
+ * @param hSocket The socket handle.
+ * @param cSegs The number of data segments in the following
+ * argument list.
+ * @param pcbWritten Number of bytes written.
+ * @param va Pairs of buffer pointers (void const *) and buffer
+ * sizes (size_t). Make 101% sure the pointer is
+ * really size_t.
+ */
+RTR3DECL(int) RTTcpSgWriteLVNB(RTSOCKET hSocket, size_t cSegs, size_t *pcbWritten, va_list va);
+
+/** @} */
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_tcp_h */
+
diff --git a/include/iprt/test.h b/include/iprt/test.h
new file mode 100644
index 00000000..9cd5ddbe
--- /dev/null
+++ b/include/iprt/test.h
@@ -0,0 +1,1485 @@
+/** @file
+ * IPRT - Testcase Framework.
+ */
+
+/*
+ * Copyright (C) 2009-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_test_h
+#define IPRT_INCLUDED_test_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+#include <iprt/stdarg.h>
+#include <iprt/assert.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_test RTTest - Testcase Framework.
+ * @ingroup grp_rt
+ * @{
+ */
+
+/** A test handle. */
+typedef R3PTRTYPE(struct RTTESTINT *) RTTEST;
+/** A pointer to a test handle. */
+typedef RTTEST *PRTTEST;
+/** A const pointer to a test handle. */
+typedef RTTEST const *PCRTTEST;
+
+/** A NIL Test handle. */
+#define NIL_RTTEST ((RTTEST)0)
+
+/**
+ * Test message importance level.
+ */
+typedef enum RTTESTLVL
+{
+ /** Invalid 0. */
+ RTTESTLVL_INVALID = 0,
+ /** Message should always be printed. */
+ RTTESTLVL_ALWAYS,
+ /** Failure message. */
+ RTTESTLVL_FAILURE,
+ /** Sub-test banner. */
+ RTTESTLVL_SUB_TEST,
+ /** Info message. */
+ RTTESTLVL_INFO,
+ /** Debug message. */
+ RTTESTLVL_DEBUG,
+ /** The last (invalid). */
+ RTTESTLVL_END
+} RTTESTLVL;
+
+
+/**
+ * Creates a test instance.
+ *
+ * @returns IPRT status code.
+ * @param pszTest The test name.
+ * @param phTest Where to store the test instance handle.
+ */
+RTR3DECL(int) RTTestCreate(const char *pszTest, PRTTEST phTest);
+
+/**
+ * Creates a test instance for a child process.
+ *
+ * This differs from RTTestCreate in that it disabled result reporting to file
+ * and pipe in order to avoid producing invalid XML.
+ *
+ * @returns IPRT status code.
+ * @param pszTest The test name.
+ * @param phTest Where to store the test instance handle.
+ */
+RTR3DECL(int) RTTestCreateChild(const char *pszTest, PRTTEST phTest);
+
+/** @name RTTEST_C_XXX - Flags for RTTestCreateEx.
+ * @{ */
+/** Whether to check the IPRT_TEST_XXX variables when constructing the
+ * instance. The following environment variables get checks:
+ *
+ * - IPRT_TEST_MAX_LEVEL: String value indicating which level.
+ * The env. var. is applied if the program specified the default level
+ * (by passing RTTESTLVL_INVALID).
+ *
+ * - IPRT_TEST_PIPE: The native pipe/fifo handle to write XML
+ * results to.
+ * The env. var. is applied if iNativeTestPipe is -1.
+ *
+ * - IPRT_TEST_FILE: Path to file/named-pipe/fifo/whatever to
+ * write XML results to.
+ * The env. var. is applied if the program specified a NULL path, it is
+ * not applied if the program hands us an empty string.
+ *
+ * - IPRT_TEST_OMIT_TOP_TEST: If present, this makes the XML output omit
+ * the top level test element.
+ * The env. var is applied when present.
+ *
+ */
+#define RTTEST_C_USE_ENV RT_BIT(0)
+/** Whether to omit the top test in the XML. */
+#define RTTEST_C_XML_OMIT_TOP_TEST RT_BIT(1)
+/** Whether to delay the top test XML element until testing commences. */
+#define RTTEST_C_XML_DELAY_TOP_TEST RT_BIT(2)
+/** Whether to try install the test instance in the test TLS slot. Setting
+ * this flag is incompatible with using the RTTestIXxxx variant of the API. */
+#define RTTEST_C_NO_TLS RT_BIT(3)
+/** Don't report to the pipe (IPRT_TEST_PIPE or other). */
+#define RTTEST_C_NO_XML_REPORTING_PIPE RT_BIT(4)
+/** Don't report to the results file (IPRT_TEST_FILE or other). */
+#define RTTEST_C_NO_XML_REPORTING_FILE RT_BIT(4)
+/** No XML reporting to pipes, file or anything.
+ * Child processes may want to use this so they don't garble the output of
+ * the main test process. */
+#define RTTEST_C_NO_XML_REPORTING (RTTEST_C_NO_XML_REPORTING_PIPE | RTTEST_C_NO_XML_REPORTING_FILE)
+/** Mask containing the valid bits. */
+#define RTTEST_C_VALID_MASK UINT32_C(0x0000003f)
+/** @} */
+
+
+/**
+ * Creates a test instance.
+ *
+ * @returns IPRT status code.
+ * @param pszTest The test name.
+ * @param fFlags Flags, see RTTEST_C_XXX.
+ * @param enmMaxLevel The max message level. Use RTTESTLVL_INVALID for
+ * the default output level or one from the
+ * environment. If specified, the environment variable
+ * will not be able to override it.
+ * @param iNativeTestPipe Native handle to a test pipe. -1 if not interested.
+ * @param pszXmlFile The XML output file name. If NULL the environment
+ * may be used. To selectively avoid that, pass an
+ * empty string.
+ * @param phTest Where to store the test instance handle.
+ *
+ * @note At the moment, we don't fail if @a pszXmlFile or @a iNativeTestPipe
+ * fails to open. This may change later.
+ */
+RTR3DECL(int) RTTestCreateEx(const char *pszTest, uint32_t fFlags, RTTESTLVL enmMaxLevel,
+ RTHCINTPTR iNativeTestPipe, const char *pszXmlFile, PRTTEST phTest);
+
+/**
+ * Initializes IPRT and creates a test instance.
+ *
+ * Typical usage is:
+ * @code
+ int main(int argc, char **argv)
+ {
+ RTTEST hTest;
+ int rc = RTTestInitAndCreate("tstSomething", &hTest);
+ if (rc)
+ return rc;
+ ...
+ }
+ @endcode
+ *
+ * @returns RTEXITCODE_SUCCESS on success. On failure an error message is
+ * printed and a suitable exit code is return.
+ *
+ * @param pszTest The test name.
+ * @param phTest Where to store the test instance handle.
+ */
+RTR3DECL(RTEXITCODE) RTTestInitAndCreate(const char *pszTest, PRTTEST phTest);
+
+/**
+ * Variant of RTTestInitAndCreate that includes IPRT init flags and argument
+ * vectors.
+ *
+ * @returns RTEXITCODE_SUCCESS on success. On failure an error message is
+ * printed and a suitable exit code is return.
+ *
+ * @param cArgs Pointer to the argument count.
+ * @param ppapszArgs Pointer to the argument vector pointer.
+ * @param fRtInit Flags, see RTR3INIT_XXX.
+ * @param pszTest The test name.
+ * @param phTest Where to store the test instance handle.
+ */
+RTR3DECL(RTEXITCODE) RTTestInitExAndCreate(int cArgs, char ***ppapszArgs, uint32_t fRtInit, const char *pszTest, PRTTEST phTest);
+
+/**
+ * Destroys a test instance previously created by RTTestCreate.
+ *
+ * @returns IPRT status code.
+ * @param hTest The test handle. NIL_RTTEST is ignored.
+ */
+RTR3DECL(int) RTTestDestroy(RTTEST hTest);
+
+/**
+ * Changes the default test instance for the calling thread.
+ *
+ * @returns IPRT status code.
+ *
+ * @param hNewDefaultTest The new default test. NIL_RTTEST is fine.
+ * @param phOldTest Where to store the old test handle. Optional.
+ */
+RTR3DECL(int) RTTestSetDefault(RTTEST hNewDefaultTest, PRTTEST phOldTest);
+
+/**
+ * Changes the test case name.
+ *
+ * @returns IRPT status code.
+ * @param hTest The test handle. If NIL_RTTEST we'll use the one
+ * associated with the calling thread.
+ * @param pszName The new test case name. Empty string is not accepted,
+ * nor are strings longer than 127 chars. Keep it short
+ * but descriptive.
+ */
+RTR3DECL(int) RTTestChangeName(RTTEST hTest, const char *pszName);
+
+/**
+ * Allocate a block of guarded memory.
+ *
+ * @returns IPRT status code.
+ * @param hTest The test handle. If NIL_RTTEST we'll use the one
+ * associated with the calling thread.
+ * @param cb The amount of memory to allocate.
+ * @param cbAlign The alignment of the returned block.
+ * @param fHead Head or tail optimized guard.
+ * @param ppvUser Where to return the pointer to the block.
+ */
+RTR3DECL(int) RTTestGuardedAlloc(RTTEST hTest, size_t cb, uint32_t cbAlign, bool fHead, void **ppvUser);
+
+/**
+ * Allocates a block of guarded memory where the guarded is immediately after
+ * the user memory.
+ *
+ * @returns Pointer to the allocated memory. NULL on failure.
+ * @param hTest The test handle. If NIL_RTTEST we'll use the one
+ * associated with the calling thread.
+ * @param cb The amount of memory to allocate.
+ */
+RTR3DECL(void *) RTTestGuardedAllocTail(RTTEST hTest, size_t cb);
+
+/**
+ * Allocates a block of guarded memory where the guarded is right in front of
+ * the user memory.
+ *
+ * @returns Pointer to the allocated memory. NULL on failure.
+ * @param hTest The test handle. If NIL_RTTEST we'll use the one
+ * associated with the calling thread.
+ * @param cb The amount of memory to allocate.
+ */
+RTR3DECL(void *) RTTestGuardedAllocHead(RTTEST hTest, size_t cb);
+
+/**
+ * Frees a block of guarded memory.
+ *
+ * @returns IPRT status code.
+ * @param hTest The test handle. If NIL_RTTEST we'll use the one
+ * associated with the calling thread.
+ * @param pv The memory. NULL is ignored.
+ */
+RTR3DECL(int) RTTestGuardedFree(RTTEST hTest, void *pv);
+
+/**
+ * Test vprintf making sure the output starts on a new line.
+ *
+ * @returns Number of chars printed.
+ * @param hTest The test handle. If NIL_RTTEST we'll use the one
+ * associated with the calling thread.
+ * @param enmLevel Message importance level.
+ * @param pszFormat The message.
+ * @param va Arguments.
+ */
+RTR3DECL(int) RTTestPrintfNlV(RTTEST hTest, RTTESTLVL enmLevel, const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(3, 0);
+
+/**
+ * Test printf making sure the output starts on a new line.
+ *
+ * @returns Number of chars printed.
+ * @param hTest The test handle. If NIL_RTTEST we'll use the one
+ * associated with the calling thread.
+ * @param enmLevel Message importance level.
+ * @param pszFormat The message.
+ * @param ... Arguments.
+ */
+RTR3DECL(int) RTTestPrintfNl(RTTEST hTest, RTTESTLVL enmLevel, const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(3, 4);
+
+/**
+ * Test vprintf, makes sure lines are prefixed and so forth.
+ *
+ * @returns Number of chars printed.
+ * @param hTest The test handle. If NIL_RTTEST we'll use the one
+ * associated with the calling thread.
+ * @param enmLevel Message importance level.
+ * @param pszFormat The message.
+ * @param va Arguments.
+ */
+RTR3DECL(int) RTTestPrintfV(RTTEST hTest, RTTESTLVL enmLevel, const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(3, 0);
+
+/**
+ * Test printf, makes sure lines are prefixed and so forth.
+ *
+ * @returns Number of chars printed.
+ * @param hTest The test handle. If NIL_RTTEST we'll use the one
+ * associated with the calling thread.
+ * @param enmLevel Message importance level.
+ * @param pszFormat The message.
+ * @param ... Arguments.
+ */
+RTR3DECL(int) RTTestPrintf(RTTEST hTest, RTTESTLVL enmLevel, const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(3, 4);
+
+/**
+ * Prints the test banner.
+ *
+ * @returns Number of chars printed.
+ * @param hTest The test handle. If NIL_RTTEST we'll use the one
+ * associated with the calling thread.
+ */
+RTR3DECL(int) RTTestBanner(RTTEST hTest);
+
+/**
+ * Summaries the test, destroys the test instance and return an exit code.
+ *
+ * @returns Test program exit code.
+ * @param hTest The test handle. If NIL_RTTEST we'll use the one
+ * associated with the calling thread.
+ */
+RTR3DECL(RTEXITCODE) RTTestSummaryAndDestroy(RTTEST hTest);
+
+/**
+ * Skips the test, destroys the test instance and return an exit code.
+ *
+ * @returns Test program exit code.
+ * @param hTest The test handle. If NIL_RTTEST we'll use the one
+ * associated with the calling thread.
+ * @param pszReasonFmt Text explaining why, optional (NULL).
+ * @param va Arguments for the reason format string.
+ */
+RTR3DECL(RTEXITCODE) RTTestSkipAndDestroyV(RTTEST hTest, const char *pszReasonFmt, va_list va) RT_IPRT_FORMAT_ATTR(2, 0);
+
+/**
+ * Skips the test, destroys the test instance and return an exit code.
+ *
+ * @returns Test program exit code.
+ * @param hTest The test handle. If NIL_RTTEST we'll use the one
+ * associated with the calling thread.
+ * @param pszReasonFmt Text explaining why, optional (NULL).
+ * @param ... Arguments for the reason format string.
+ */
+RTR3DECL(RTEXITCODE) RTTestSkipAndDestroy(RTTEST hTest, const char *pszReasonFmt, ...) RT_IPRT_FORMAT_ATTR(2, 3);
+
+/**
+ * Starts a sub-test.
+ *
+ * This will perform an implicit RTTestSubDone() call if that has not been done
+ * since the last RTTestSub call.
+ *
+ * @returns Number of chars printed.
+ * @param hTest The test handle. If NIL_RTTEST we'll use the one
+ * associated with the calling thread.
+ * @param pszSubTest The sub-test name.
+ */
+RTR3DECL(int) RTTestSub(RTTEST hTest, const char *pszSubTest);
+
+/**
+ * Format string version of RTTestSub.
+ *
+ * See RTTestSub for details.
+ *
+ * @returns Number of chars printed.
+ * @param hTest The test handle. If NIL_RTTEST we'll use the one
+ * associated with the calling thread.
+ * @param pszSubTestFmt The sub-test name format string.
+ * @param ... Arguments.
+ */
+RTR3DECL(int) RTTestSubF(RTTEST hTest, const char *pszSubTestFmt, ...) RT_IPRT_FORMAT_ATTR(2, 3);
+
+/**
+ * Format string version of RTTestSub.
+ *
+ * See RTTestSub for details.
+ *
+ * @returns Number of chars printed.
+ * @param hTest The test handle. If NIL_RTTEST we'll use the one
+ * associated with the calling thread.
+ * @param pszSubTestFmt The sub-test name format string.
+ * @param va Arguments.
+ */
+RTR3DECL(int) RTTestSubV(RTTEST hTest, const char *pszSubTestFmt, va_list va) RT_IPRT_FORMAT_ATTR(2, 0);
+
+/**
+ * Completes a sub-test.
+ *
+ * @returns Number of chars printed, negative numbers are IPRT error codes.
+ * @param hTest The test handle. If NIL_RTTEST we'll use the one
+ * associated with the calling thread.
+ */
+RTR3DECL(int) RTTestSubDone(RTTEST hTest);
+
+/**
+ * Prints an extended PASSED message, optional.
+ *
+ * This does not conclude the sub-test, it could be used to report the passing
+ * of a sub-sub-to-the-power-of-N-test.
+ *
+ * @returns Number of chars printed, negative numbers are IPRT error codes.
+ * @param hTest The test handle. If NIL_RTTEST we'll use the one
+ * associated with the calling thread.
+ * @param pszFormat The message. No trailing newline.
+ * @param va The arguments.
+ */
+RTR3DECL(int) RTTestPassedV(RTTEST hTest, const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(2, 0);
+
+/**
+ * Prints an extended PASSED message, optional.
+ *
+ * This does not conclude the sub-test, it could be used to report the passing
+ * of a sub-sub-to-the-power-of-N-test.
+ *
+ * @returns Number of chars printed, negative numbers are IPRT error codes.
+ * @param hTest The test handle. If NIL_RTTEST we'll use the one
+ * associated with the calling thread.
+ * @param pszFormat The message. No trailing newline.
+ * @param ... The arguments.
+ */
+RTR3DECL(int) RTTestPassed(RTTEST hTest, const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(2, 3);
+
+/**
+ * Marks the current test as 'SKIPPED' and optionally displays a message
+ * explaining why.
+ *
+ * @returns Number of chars printed, negative numbers are IPRT error codes.
+ * @param hTest The test handle. If NIL_RTTEST we'll use the one
+ * associated with the calling thread.
+ * @param pszFormat The message. No trailing newline. Can be NULL or empty.
+ * @param ... The arguments.
+ */
+RTR3DECL(int) RTTestSkipped(RTTEST hTest, const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR_MAYBE_NULL(2, 3);
+
+/**
+ * Marks the current test as 'SKIPPED' and optionally displays a message
+ * explaining why.
+ *
+ * @returns Number of chars printed, negative numbers are IPRT error codes.
+ * @param hTest The test handle. If NIL_RTTEST we'll use the one
+ * associated with the calling thread.
+ * @param pszFormat The message. No trailing newline. Can be NULL or empty.
+ * @param va The arguments.
+ */
+RTR3DECL(int) RTTestSkippedV(RTTEST hTest, const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR_MAYBE_NULL(2, 0);
+
+
+/**
+ * Value units.
+ *
+ * @remarks This is an interface where we have to be binary compatible with both
+ * older versions of this header and other components using the same
+ * contant values.
+ * @remarks When adding a new item:
+ * - Always add at the end of the list.
+ * - Add it to rtTestUnitName in r3/test.cpp.
+ * - Add it as VMMDEV_TESTING_UNIT_ in include/VBox/VMMDevTesting.h.
+ * - Add it to g_aszBs2TestUnitNames in
+ * ValidationKit/bootsectors/bootsector2-common-routines.mac.
+ * - Add it to g_aszBs3TestUnitNames in bs3kit/bs3-cmn-TestData.c.
+ * - Add it to ValidationKit/common/constants/valueunit.py both as
+ * a constant (strip RTTESTUNIT_) and as a name (same as what
+ * rtTestUnitName returns) for mapping. Testmanager must be
+ * updated.
+ * - Add it to Value.kdBestByUnit in ValidationKit/analysis/reader.py.
+ */
+typedef enum RTTESTUNIT
+{
+ /** The customary invalid zero value. */
+ RTTESTUNIT_INVALID = 0,
+
+ RTTESTUNIT_PCT, /**< Percentage (10^-2). */
+ RTTESTUNIT_BYTES, /**< Bytes. */
+ RTTESTUNIT_BYTES_PER_SEC, /**< Bytes per second. */
+ RTTESTUNIT_KILOBYTES, /**< Kilobytes. */
+ RTTESTUNIT_KILOBYTES_PER_SEC, /**< Kilobytes per second. */
+ RTTESTUNIT_MEGABYTES, /**< Megabytes. */
+ RTTESTUNIT_MEGABYTES_PER_SEC, /**< Megabytes per second. */
+ RTTESTUNIT_PACKETS, /**< Packets. */
+ RTTESTUNIT_PACKETS_PER_SEC, /**< Packets per second. */
+ RTTESTUNIT_FRAMES, /**< Frames. */
+ RTTESTUNIT_FRAMES_PER_SEC, /**< Frames per second. */
+ RTTESTUNIT_OCCURRENCES, /**< Occurrences. */
+ RTTESTUNIT_OCCURRENCES_PER_SEC, /**< Occurrences per second. */
+ RTTESTUNIT_CALLS, /**< Calls. */
+ RTTESTUNIT_CALLS_PER_SEC, /**< Calls per second. */
+ RTTESTUNIT_ROUND_TRIP, /**< Round trips. */
+ RTTESTUNIT_SECS, /**< Seconds. */
+ RTTESTUNIT_MS, /**< Milliseconds. */
+ RTTESTUNIT_NS, /**< Nanoseconds. */
+ RTTESTUNIT_NS_PER_CALL, /**< Nanoseconds per call. */
+ RTTESTUNIT_NS_PER_FRAME, /**< Nanoseconds per frame. */
+ RTTESTUNIT_NS_PER_OCCURRENCE, /**< Nanoseconds per occurrence. */
+ RTTESTUNIT_NS_PER_PACKET, /**< Nanoseconds per frame. */
+ RTTESTUNIT_NS_PER_ROUND_TRIP, /**< Nanoseconds per round trip. */
+ RTTESTUNIT_INSTRS, /**< Instructions. */
+ RTTESTUNIT_INSTRS_PER_SEC, /**< Instructions per second. */
+ RTTESTUNIT_NONE, /**< No unit. */
+ RTTESTUNIT_PP1K, /**< Parts per thousand (10^-3). */
+ RTTESTUNIT_PP10K, /**< Parts per ten thousand (10^-4). */
+ RTTESTUNIT_PPM, /**< Parts per million (10^-6). */
+ RTTESTUNIT_PPB, /**< Parts per billion (10^-9). */
+ RTTESTUNIT_TICKS, /**< CPU ticks. */
+ RTTESTUNIT_TICKS_PER_CALL, /**< CPU ticks per call. */
+ RTTESTUNIT_TICKS_PER_OCCURENCE, /**< CPU ticks per occurence. */
+ RTTESTUNIT_PAGES, /**< Page count. */
+ RTTESTUNIT_PAGES_PER_SEC, /**< Pages per second. */
+ RTTESTUNIT_TICKS_PER_PAGE, /**< CPU ticks per page. */
+ RTTESTUNIT_NS_PER_PAGE, /**< Nanoseconds per page. */
+ RTTESTUNIT_PS, /**< Picoseconds. */
+ RTTESTUNIT_PS_PER_CALL, /**< Picoseconds per call. */
+ RTTESTUNIT_PS_PER_FRAME, /**< Picoseconds per frame. */
+ RTTESTUNIT_PS_PER_OCCURRENCE, /**< Picoseconds per occurrence. */
+ RTTESTUNIT_PS_PER_PACKET, /**< Picoseconds per frame. */
+ RTTESTUNIT_PS_PER_ROUND_TRIP, /**< Picoseconds per round trip. */
+ RTTESTUNIT_PS_PER_PAGE, /**< Picoseconds per page. */
+
+ /** The end of valid units. */
+ RTTESTUNIT_END
+} RTTESTUNIT;
+AssertCompile(RTTESTUNIT_INSTRS == 0x19);
+AssertCompile(RTTESTUNIT_NONE == 0x1b);
+AssertCompile(RTTESTUNIT_NS_PER_PAGE == 0x26);
+AssertCompile(RTTESTUNIT_PS_PER_PAGE == 0x2d);
+
+/**
+ * Report a named test result value.
+ *
+ * This is typically used for benchmarking but can be used for other purposes
+ * like reporting limits of some implementation. The value gets associated with
+ * the current sub test, the name must be unique within the sub test.
+ *
+ * @returns IPRT status code.
+ *
+ * @param hTest The test handle. If NIL_RTTEST we'll use the one
+ * associated with the calling thread.
+ * @param pszName The value name.
+ * @param u64Value The value.
+ * @param enmUnit The value unit.
+ */
+RTR3DECL(int) RTTestValue(RTTEST hTest, const char *pszName, uint64_t u64Value, RTTESTUNIT enmUnit);
+
+/**
+ * Same as RTTestValue, except that the name is now a format string.
+ *
+ * @returns IPRT status code.
+ *
+ * @param hTest The test handle. If NIL_RTTEST we'll use the one
+ * associated with the calling thread.
+ * @param u64Value The value.
+ * @param enmUnit The value unit.
+ * @param pszNameFmt The value name format string.
+ * @param ... String arguments.
+ */
+RTR3DECL(int) RTTestValueF(RTTEST hTest, uint64_t u64Value, RTTESTUNIT enmUnit,
+ const char *pszNameFmt, ...) RT_IPRT_FORMAT_ATTR(4, 5);
+
+/**
+ * Same as RTTestValue, except that the name is now a format string.
+ *
+ * @returns IPRT status code.
+ *
+ * @param hTest The test handle. If NIL_RTTEST we'll use the one
+ * associated with the calling thread.
+ * @param u64Value The value.
+ * @param enmUnit The value unit.
+ * @param pszNameFmt The value name format string.
+ * @param va String arguments.
+ */
+RTR3DECL(int) RTTestValueV(RTTEST hTest, uint64_t u64Value, RTTESTUNIT enmUnit,
+ const char *pszNameFmt, va_list va) RT_IPRT_FORMAT_ATTR(4, 0);
+
+/**
+ * Increments the error counter.
+ *
+ * @returns IPRT status code.
+ * @param hTest The test handle. If NIL_RTTEST we'll use the one
+ * associated with the calling thread.
+ */
+RTR3DECL(int) RTTestErrorInc(RTTEST hTest);
+
+/**
+ * Get the current error count.
+ *
+ * @returns The error counter, UINT32_MAX if no valid test handle.
+ * @param hTest The test handle. If NIL_RTTEST we'll use the one
+ * associated with the calling thread.
+ */
+RTR3DECL(uint32_t) RTTestErrorCount(RTTEST hTest);
+
+/**
+ * Get the error count of the current sub test.
+ *
+ * @returns The error counter, UINT32_MAX if no valid test handle.
+ * @param hTest The test handle. If NIL_RTTEST we'll use the one
+ * associated with the calling thread.
+ */
+RTR3DECL(uint32_t) RTTestSubErrorCount(RTTEST hTest);
+
+/**
+ * Increments the error counter and prints a failure message.
+ *
+ * @returns IPRT status code.
+ * @param hTest The test handle. If NIL_RTTEST we'll use the one
+ * associated with the calling thread.
+ * @param pszFormat The message. No trailing newline.
+ * @param va The arguments.
+ */
+RTR3DECL(int) RTTestFailedV(RTTEST hTest, const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(2, 0);
+
+/**
+ * Increments the error counter and prints a failure message.
+ *
+ * @returns IPRT status code.
+ * @param hTest The test handle. If NIL_RTTEST we'll use the one
+ * associated with the calling thread.
+ * @param pszFormat The message. No trailing newline.
+ * @param ... The arguments.
+ */
+RTR3DECL(int) RTTestFailed(RTTEST hTest, const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(2, 3);
+
+/**
+ * Same as RTTestPrintfV with RTTESTLVL_FAILURE.
+ *
+ * @returns Number of chars printed.
+ * @param hTest The test handle. If NIL_RTTEST we'll use the one
+ * associated with the calling thread.
+ * @param pszFormat The message.
+ * @param va Arguments.
+ */
+RTR3DECL(int) RTTestFailureDetailsV(RTTEST hTest, const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(2, 0);
+
+/**
+ * Same as RTTestPrintf with RTTESTLVL_FAILURE.
+ *
+ * @returns Number of chars printed.
+ * @param hTest The test handle. If NIL_RTTEST we'll use the one
+ * associated with the calling thread.
+ * @param pszFormat The message.
+ * @param ... Arguments.
+ */
+RTR3DECL(int) RTTestFailureDetails(RTTEST hTest, const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(2, 3);
+
+/**
+ * Sets error context info to be printed with the first failure.
+ *
+ * @returns IPRT status code.
+ * @param hTest The test handle. If NIL_RTTEST we'll use the one
+ * associated with the calling thread.
+ * @param pszFormat The message, no trailing newline. NULL to clear the
+ * context message.
+ * @param va The arguments.
+ */
+RTR3DECL(int) RTTestErrContextV(RTTEST hTest, const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(2, 0);
+
+/**
+ * Sets error context info to be printed with the first failure.
+ *
+ * @returns IPRT status code.
+ * @param hTest The test handle. If NIL_RTTEST we'll use the one
+ * associated with the calling thread.
+ * @param pszFormat The message, no trailing newline. NULL to clear the
+ * context message.
+ * @param ... The arguments.
+ */
+RTR3DECL(int) RTTestErrContext(RTTEST hTest, const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(2, 3);
+
+/**
+ * Disables and shuts up assertions.
+ *
+ * Max 8 nestings.
+ *
+ * @returns IPRT status code.
+ * @param hTest The test handle. If NIL_RTTEST we'll use the one
+ * associated with the calling thread.
+ * @sa RTAssertSetMayPanic, RTAssertSetQuiet.
+ */
+RTR3DECL(int) RTTestDisableAssertions(RTTEST hTest);
+
+/**
+ * Restores the previous call to RTTestDisableAssertions.
+ *
+ * @returns IPRT status code.
+ * @param hTest The test handle. If NIL_RTTEST we'll use the one
+ * associated with the calling thread.
+ */
+RTR3DECL(int) RTTestRestoreAssertions(RTTEST hTest);
+
+
+/** @def RTTEST_CHECK
+ * Check whether a boolean expression holds true.
+ *
+ * If the expression is false, call RTTestFailed giving the line number and expression.
+ *
+ * @param hTest The test handle.
+ * @param expr The expression to evaluate.
+ */
+#define RTTEST_CHECK(hTest, expr) \
+ do { if (!(expr)) { \
+ RTTestFailed((hTest), "line %u: %s", __LINE__, #expr); \
+ } \
+ } while (0)
+/** @def RTTEST_CHECK_RET
+ * Check whether a boolean expression holds true, returns on false.
+ *
+ * If the expression is false, call RTTestFailed giving the line number and
+ * expression, then return @a rcRet.
+ *
+ * @param hTest The test handle.
+ * @param expr The expression to evaluate.
+ * @param rcRet What to return on failure.
+ */
+#define RTTEST_CHECK_RET(hTest, expr, rcRet) \
+ do { if (!(expr)) { \
+ RTTestFailed((hTest), "line %u: %s", __LINE__, #expr); \
+ return (rcRet); \
+ } \
+ } while (0)
+/** @def RTTEST_CHECK_RETV
+ * Check whether a boolean expression holds true, returns void on false.
+ *
+ * If the expression is false, call RTTestFailed giving the line number and
+ * expression, then return void.
+ *
+ * @param hTest The test handle.
+ * @param expr The expression to evaluate.
+ */
+#define RTTEST_CHECK_RETV(hTest, expr) \
+ do { if (!(expr)) { \
+ RTTestFailed((hTest), "line %u: %s", __LINE__, #expr); \
+ return; \
+ } \
+ } while (0)
+/** @def RTTEST_CHECK_BREAK
+ * Check whether a boolean expression holds true.
+ *
+ * If the expression is false, call RTTestFailed giving the line number and
+ * expression, then break.
+ *
+ * @param hTest The test handle.
+ * @param expr The expression to evaluate.
+ */
+#define RTTEST_CHECK_BREAK(hTest, expr) \
+ if (!(expr)) { \
+ RTTestFailed((hTest), "line %u: %s", __LINE__, #expr); \
+ break; \
+ } else do {} while (0)
+
+
+/** @def RTTEST_CHECK_MSG
+ * Check whether a boolean expression holds true.
+ *
+ * If the expression is false, call RTTestFailed giving the line number and expression.
+ *
+ * @param hTest The test handle.
+ * @param expr The expression to evaluate.
+ * @param DetailsArgs Argument list for RTTestFailureDetails, including
+ * parenthesis.
+ */
+#define RTTEST_CHECK_MSG(hTest, expr, DetailsArgs) \
+ do { if (!(expr)) { \
+ RTTestFailed((hTest), "line %u: %s", __LINE__, #expr); \
+ RTTestFailureDetails DetailsArgs; \
+ } \
+ } while (0)
+/** @def RTTEST_CHECK_MSG_RET
+ * Check whether a boolean expression holds true, returns on false.
+ *
+ * If the expression is false, call RTTestFailed giving the line number and expression.
+ *
+ * @param hTest The test handle.
+ * @param expr The expression to evaluate.
+ * @param DetailsArgs Argument list for RTTestFailureDetails, including
+ * parenthesis.
+ * @param rcRet What to return on failure.
+ */
+#define RTTEST_CHECK_MSG_RET(hTest, expr, DetailsArgs, rcRet) \
+ do { if (!(expr)) { \
+ RTTestFailed((hTest), "line %u: %s", __LINE__, #expr); \
+ RTTestFailureDetails DetailsArgs; \
+ return (rcRet); \
+ } \
+ } while (0)
+/** @def RTTEST_CHECK_MSG_RETV
+ * Check whether a boolean expression holds true, returns void on false.
+ *
+ * If the expression is false, call RTTestFailed giving the line number and expression.
+ *
+ * @param hTest The test handle.
+ * @param expr The expression to evaluate.
+ * @param DetailsArgs Argument list for RTTestFailureDetails, including
+ * parenthesis.
+ */
+#define RTTEST_CHECK_MSG_RETV(hTest, expr, DetailsArgs) \
+ do { if (!(expr)) { \
+ RTTestFailed((hTest), "line %u: %s", __LINE__, #expr); \
+ RTTestFailureDetails DetailsArgs; \
+ return; \
+ } \
+ } while (0)
+
+
+/** @def RTTEST_CHECK_RC
+ * Check whether an expression returns a specific IPRT style status code.
+ *
+ * If a different status code is return, call RTTestFailed giving the line
+ * number, expression, actual and expected status codes.
+ *
+ * @param hTest The test handle.
+ * @param rcExpr The expression resulting in an IPRT status code.
+ * @param rcExpect The expected return code. This may be referenced
+ * more than once by the macro.
+ */
+#define RTTEST_CHECK_RC(hTest, rcExpr, rcExpect) \
+ do { \
+ int rcCheck = (rcExpr); \
+ if (rcCheck != (rcExpect)) { \
+ RTTestFailed((hTest), "line %u: %s: expected %Rrc, got %Rrc", __LINE__, #rcExpr, (rcExpect), rcCheck); \
+ } \
+ } while (0)
+/** @def RTTEST_CHECK_RC_RET
+ * Check whether an expression returns a specific IPRT style status code.
+ *
+ * If a different status code is return, call RTTestFailed giving the line
+ * number, expression, actual and expected status codes, then return.
+ *
+ * @param hTest The test handle.
+ * @param rcExpr The expression resulting in an IPRT status code.
+ * This will be assigned to a local rcCheck variable
+ * that can be used as return value.
+ * @param rcExpect The expected return code. This may be referenced
+ * more than once by the macro.
+ * @param rcRet The return code.
+ */
+#define RTTEST_CHECK_RC_RET(hTest, rcExpr, rcExpect, rcRet) \
+ do { \
+ int rcCheck = (rcExpr); \
+ if (rcCheck != (rcExpect)) { \
+ RTTestFailed((hTest), "line %u: %s: expected %Rrc, got %Rrc", __LINE__, #rcExpr, (rcExpect), rcCheck); \
+ return (rcRet); \
+ } \
+ } while (0)
+/** @def RTTEST_CHECK_RC_RETV
+ * Check whether an expression returns a specific IPRT style status code.
+ *
+ * If a different status code is return, call RTTestFailed giving the line
+ * number, expression, actual and expected status codes, then return.
+ *
+ * @param hTest The test handle.
+ * @param rcExpr The expression resulting in an IPRT status code.
+ * @param rcExpect The expected return code. This may be referenced
+ * more than once by the macro.
+ */
+#define RTTEST_CHECK_RC_RETV(hTest, rcExpr, rcExpect) \
+ do { \
+ int rcCheck = (rcExpr); \
+ if (rcCheck != (rcExpect)) { \
+ RTTestFailed((hTest), "line %u: %s: expected %Rrc, got %Rrc", __LINE__, #rcExpr, (rcExpect), rcCheck); \
+ return; \
+ } \
+ } while (0)
+/** @def RTTEST_CHECK_RC_BREAK
+ * Check whether an expression returns a specific IPRT style status code.
+ *
+ * If a different status code is return, call RTTestFailed giving the line
+ * number, expression, actual and expected status codes, then break.
+ *
+ * @param hTest The test handle.
+ * @param rcExpr The expression resulting in an IPRT status code.
+ * @param rcExpect The expected return code. This may be referenced
+ * more than once by the macro.
+ */
+#define RTTEST_CHECK_RC_BREAK(hTest, rcExpr, rcExpect) \
+ if (1) { \
+ int rcCheck = (rcExpr); \
+ if (rcCheck != (rcExpect)) { \
+ RTTestFailed((hTest), "line %u: %s: expected %Rrc, got %Rrc", __LINE__, #rcExpr, (rcExpect), rcCheck); \
+ break; \
+ } \
+ } else do {} while (0)
+
+
+/** @def RTTEST_CHECK_RC_OK
+ * Check whether a IPRT style status code indicates success.
+ *
+ * If the status indicates failure, call RTTestFailed giving the line number,
+ * expression and status code.
+ *
+ * @param hTest The test handle.
+ * @param rcExpr The expression resulting in an IPRT status code.
+ */
+#define RTTEST_CHECK_RC_OK(hTest, rcExpr) \
+ do { \
+ int rcCheck = (rcExpr); \
+ if (RT_FAILURE(rcCheck)) { \
+ RTTestFailed((hTest), "line %u: %s: %Rrc", __LINE__, #rcExpr, rcCheck); \
+ } \
+ } while (0)
+/** @def RTTEST_CHECK_RC_OK_RET
+ * Check whether a IPRT style status code indicates success.
+ *
+ * If the status indicates failure, call RTTestFailed giving the line number,
+ * expression and status code, then return with the specified value.
+ *
+ * @param hTest The test handle.
+ * @param rcExpr The expression resulting in an IPRT status code.
+ * This will be assigned to a local rcCheck variable
+ * that can be used as return value.
+ * @param rcRet The return code.
+ */
+#define RTTEST_CHECK_RC_OK_RET(hTest, rcExpr, rcRet) \
+ do { \
+ int rcCheck = (rcExpr); \
+ if (RT_FAILURE(rcCheck)) { \
+ RTTestFailed((hTest), "line %u: %s: %Rrc", __LINE__, #rcExpr, rcCheck); \
+ return (rcRet); \
+ } \
+ } while (0)
+/** @def RTTEST_CHECK_RC_OK_RETV
+ * Check whether a IPRT style status code indicates success.
+ *
+ * If the status indicates failure, call RTTestFailed giving the line number,
+ * expression and status code, then return.
+ *
+ * @param hTest The test handle.
+ * @param rcExpr The expression resulting in an IPRT status code.
+ */
+#define RTTEST_CHECK_RC_OK_RETV(hTest, rcExpr) \
+ do { \
+ int rcCheck = (rcExpr); \
+ if (RT_FAILURE(rcCheck)) { \
+ RTTestFailed((hTest), "line %u: %s: %Rrc", __LINE__, #rcExpr, rcCheck); \
+ return; \
+ } \
+ } while (0)
+
+
+
+
+/** @name Implicit Test Handle API Variation
+ * The test handle is retrieved from the test TLS entry of the calling thread.
+ * @{
+ */
+
+/**
+ * Test vprintf, makes sure lines are prefixed and so forth.
+ *
+ * @returns Number of chars printed.
+ * @param enmLevel Message importance level.
+ * @param pszFormat The message.
+ * @param va Arguments.
+ */
+RTR3DECL(int) RTTestIPrintfV(RTTESTLVL enmLevel, const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(2, 0);
+
+/**
+ * Test printf, makes sure lines are prefixed and so forth.
+ *
+ * @returns Number of chars printed.
+ * @param enmLevel Message importance level.
+ * @param pszFormat The message.
+ * @param ... Arguments.
+ */
+RTR3DECL(int) RTTestIPrintf(RTTESTLVL enmLevel, const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(2, 3);
+
+/**
+ * Starts a sub-test.
+ *
+ * This will perform an implicit RTTestSubDone() call if that has not been done
+ * since the last RTTestSub call.
+ *
+ * @returns Number of chars printed.
+ * @param pszSubTest The sub-test name.
+ */
+RTR3DECL(int) RTTestISub(const char *pszSubTest);
+
+/**
+ * Format string version of RTTestSub.
+ *
+ * See RTTestSub for details.
+ *
+ * @returns Number of chars printed.
+ * @param pszSubTestFmt The sub-test name format string.
+ * @param ... Arguments.
+ */
+RTR3DECL(int) RTTestISubF(const char *pszSubTestFmt, ...) RT_IPRT_FORMAT_ATTR(1, 2);
+
+/**
+ * Format string version of RTTestSub.
+ *
+ * See RTTestSub for details.
+ *
+ * @returns Number of chars printed.
+ * @param pszSubTestFmt The sub-test name format string.
+ * @param va Arguments.
+ */
+RTR3DECL(int) RTTestISubV(const char *pszSubTestFmt, va_list va) RT_IPRT_FORMAT_ATTR(1, 0);
+
+/**
+ * Completes a sub-test.
+ *
+ * @returns Number of chars printed.
+ */
+RTR3DECL(int) RTTestISubDone(void);
+
+/**
+ * Prints an extended PASSED message, optional.
+ *
+ * This does not conclude the sub-test, it could be used to report the passing
+ * of a sub-sub-to-the-power-of-N-test.
+ *
+ * @returns IPRT status code.
+ * @param pszFormat The message. No trailing newline.
+ * @param va The arguments.
+ */
+RTR3DECL(int) RTTestIPassedV(const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(1, 0);
+
+/**
+ * Prints an extended PASSED message, optional.
+ *
+ * This does not conclude the sub-test, it could be used to report the passing
+ * of a sub-sub-to-the-power-of-N-test.
+ *
+ * @returns IPRT status code.
+ * @param pszFormat The message. No trailing newline.
+ * @param ... The arguments.
+ */
+RTR3DECL(int) RTTestIPassed(const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(1, 2);
+
+/**
+ * Report a named test result value.
+ *
+ * This is typically used for benchmarking but can be used for other purposes
+ * like reporting limits of some implementation. The value gets associated with
+ * the current sub test, the name must be unique within the sub test.
+ *
+ * @returns IPRT status code.
+ *
+ * @param pszName The value name.
+ * @param u64Value The value.
+ * @param enmUnit The value unit.
+ */
+RTR3DECL(int) RTTestIValue(const char *pszName, uint64_t u64Value, RTTESTUNIT enmUnit);
+
+/**
+ * Same as RTTestValue, except that the name is now a format string.
+ *
+ * @returns IPRT status code.
+ *
+ * @param u64Value The value.
+ * @param enmUnit The value unit.
+ * @param pszNameFmt The value name format string.
+ * @param ... String arguments.
+ */
+RTR3DECL(int) RTTestIValueF(uint64_t u64Value, RTTESTUNIT enmUnit, const char *pszNameFmt, ...) RT_IPRT_FORMAT_ATTR(3, 4);
+
+/**
+ * Same as RTTestValue, except that the name is now a format string.
+ *
+ * @returns IPRT status code.
+ *
+ * @param u64Value The value.
+ * @param enmUnit The value unit.
+ * @param pszNameFmt The value name format string.
+ * @param va String arguments.
+ */
+RTR3DECL(int) RTTestIValueV(uint64_t u64Value, RTTESTUNIT enmUnit, const char *pszNameFmt, va_list va) RT_IPRT_FORMAT_ATTR(3, 0);
+
+/**
+ * Increments the error counter.
+ *
+ * @returns IPRT status code.
+ */
+RTR3DECL(int) RTTestIErrorInc(void);
+
+/**
+ * Get the current error count.
+ *
+ * @returns The error counter, UINT32_MAX if no valid test handle.
+ */
+RTR3DECL(uint32_t) RTTestIErrorCount(void);
+
+/**
+ * Increments the error counter and prints a failure message.
+ *
+ * @returns IPRT status code.
+ * @param pszFormat The message. No trailing newline.
+ * @param va The arguments.
+ */
+RTR3DECL(int) RTTestIFailedV(const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(1, 0);
+
+/**
+ * Increments the error counter and prints a failure message.
+ *
+ * @returns IPRT status code.
+ * @param pszFormat The message. No trailing newline.
+ * @param ... The arguments.
+ */
+RTR3DECL(int) RTTestIFailed(const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(1, 2);
+
+/**
+ * Increments the error counter, prints a failure message and returns the
+ * specified status code.
+ *
+ * This is mainly a convenience method for saving vertical space in the source
+ * code.
+ *
+ * @returns @a rcRet
+ * @param rcRet The IPRT status code to return.
+ * @param pszFormat The message. No trailing newline.
+ * @param va The arguments.
+ */
+RTR3DECL(int) RTTestIFailedRcV(int rcRet, const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(2, 0);
+
+/**
+ * Increments the error counter, prints a failure message and returns the
+ * specified status code.
+ *
+ * This is mainly a convenience method for saving vertical space in the source
+ * code.
+ *
+ * @returns @a rcRet
+ * @param rcRet The IPRT status code to return.
+ * @param pszFormat The message. No trailing newline.
+ * @param ... The arguments.
+ */
+RTR3DECL(int) RTTestIFailedRc(int rcRet, const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(2, 3);
+
+/**
+ * Same as RTTestIPrintfV with RTTESTLVL_FAILURE.
+ *
+ * @returns Number of chars printed.
+ * @param pszFormat The message.
+ * @param va Arguments.
+ */
+RTR3DECL(int) RTTestIFailureDetailsV(const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(1, 0);
+
+/**
+ * Same as RTTestIPrintf with RTTESTLVL_FAILURE.
+ *
+ * @returns Number of chars printed.
+ * @param pszFormat The message.
+ * @param ... Arguments.
+ */
+RTR3DECL(int) RTTestIFailureDetails(const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(1, 2);
+
+/**
+ * Sets error context info to be printed with the first failure.
+ *
+ * @returns IPRT status code.
+ * @param pszFormat The message, no trailing newline. NULL to clear the
+ * context message.
+ * @param va The arguments.
+ */
+RTR3DECL(int) RTTestIErrContextV(const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(1, 0);
+
+/**
+ * Sets error context info to be printed with the first failure.
+ *
+ * @returns IPRT status code.
+ * @param pszFormat The message, no trailing newline. NULL to clear the
+ * context message.
+ * @param ... The arguments.
+ */
+RTR3DECL(int) RTTestIErrContext(const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(1, 2);
+
+/**
+ * Disables and shuts up assertions.
+ *
+ * Max 8 nestings.
+ *
+ * @returns IPRT status code.
+ * @sa RTAssertSetMayPanic, RTAssertSetQuiet.
+ */
+RTR3DECL(int) RTTestIDisableAssertions(void);
+
+/**
+ * Restores the previous call to RTTestDisableAssertions.
+ *
+ * @returns IPRT status code.
+ */
+RTR3DECL(int) RTTestIRestoreAssertions(void);
+
+
+/** @def RTTESTI_CHECK
+ * Check whether a boolean expression holds true.
+ *
+ * If the expression is false, call RTTestIFailed giving the line number and
+ * expression.
+ *
+ * @param expr The expression to evaluate.
+ */
+#define RTTESTI_CHECK(expr) \
+ do { if (!(expr)) { \
+ RTTestIFailed("line %u: %s", __LINE__, #expr); \
+ } \
+ } while (0)
+/** @def RTTESTI_CHECK_RET
+ * Check whether a boolean expression holds true, returns on false.
+ *
+ * If the expression is false, call RTTestIFailed giving the line number and
+ * expression, then return @a rcRet.
+ *
+ * @param expr The expression to evaluate.
+ * @param rcRet What to return on failure.
+ */
+#define RTTESTI_CHECK_RET(expr, rcRet) \
+ do { if (!(expr)) { \
+ RTTestIFailed("line %u: %s", __LINE__, #expr); \
+ return (rcRet); \
+ } \
+ } while (0)
+/** @def RTTESTI_CHECK_RETV
+ * Check whether a boolean expression holds true, returns void on false.
+ *
+ * If the expression is false, call RTTestIFailed giving the line number and
+ * expression, then return void.
+ *
+ * @param expr The expression to evaluate.
+ */
+#define RTTESTI_CHECK_RETV(expr) \
+ do { if (!(expr)) { \
+ RTTestIFailed("line %u: %s", __LINE__, #expr); \
+ return; \
+ } \
+ } while (0)
+/** @def RTTESTI_CHECK_BREAK
+ * Check whether a boolean expression holds true, returns void on false.
+ *
+ * If the expression is false, call RTTestIFailed giving the line number and
+ * expression, then break.
+ *
+ * @param expr The expression to evaluate.
+ */
+#define RTTESTI_CHECK_BREAK(expr) \
+ if (!(expr)) { \
+ RTTestIFailed("line %u: %s", __LINE__, #expr); \
+ break; \
+ } else do {} while (0)
+
+
+/** @def RTTESTI_CHECK_MSG
+ * Check whether a boolean expression holds true.
+ *
+ * If the expression is false, call RTTestIFailed giving the line number and
+ * expression.
+ *
+ * @param expr The expression to evaluate.
+ * @param DetailsArgs Argument list for RTTestIFailureDetails, including
+ * parenthesis.
+ */
+#define RTTESTI_CHECK_MSG(expr, DetailsArgs) \
+ do { if (!(expr)) { \
+ RTTestIFailed("line %u: %s", __LINE__, #expr); \
+ RTTestIFailureDetails DetailsArgs; \
+ } \
+ } while (0)
+/** @def RTTESTI_CHECK_MSG_BREAK
+ * Check whether a boolean expression holds true, returns on false.
+ *
+ * If the expression is false, call RTTestIFailed giving the line number and
+ * expression.
+ *
+ * @param expr The expression to evaluate.
+ * @param DetailsArgs Argument list for RTTestIFailureDetails, including
+ * parenthesis.
+ */
+#define RTTESTI_CHECK_MSG_BREAK(expr, DetailsArgs) \
+ if (!(expr)) { \
+ RTTestIFailed("line %u: %s", __LINE__, #expr); \
+ RTTestIFailureDetails DetailsArgs; \
+ break; \
+ } else do {} while (0)
+/** @def RTTESTI_CHECK_MSG_RET
+ * Check whether a boolean expression holds true, returns on false.
+ *
+ * If the expression is false, call RTTestIFailed giving the line number and
+ * expression.
+ *
+ * @param expr The expression to evaluate.
+ * @param DetailsArgs Argument list for RTTestIFailureDetails, including
+ * parenthesis.
+ * @param rcRet What to return on failure.
+ */
+#define RTTESTI_CHECK_MSG_RET(expr, DetailsArgs, rcRet) \
+ do { if (!(expr)) { \
+ RTTestIFailed("line %u: %s", __LINE__, #expr); \
+ RTTestIFailureDetails DetailsArgs; \
+ return (rcRet); \
+ } \
+ } while (0)
+/** @def RTTESTI_CHECK_MSG_RETV
+ * Check whether a boolean expression holds true, returns void on false.
+ *
+ * If the expression is false, call RTTestIFailed giving the line number and
+ * expression.
+ *
+ * @param expr The expression to evaluate.
+ * @param DetailsArgs Argument list for RTTestIFailureDetails, including
+ * parenthesis.
+ */
+#define RTTESTI_CHECK_MSG_RETV(expr, DetailsArgs) \
+ do { if (!(expr)) { \
+ RTTestIFailed("line %u: %s", __LINE__, #expr); \
+ RTTestIFailureDetails DetailsArgs; \
+ return; \
+ } \
+ } while (0)
+
+/** @def RTTESTI_CHECK_RC
+ * Check whether an expression returns a specific IPRT style status code.
+ *
+ * If a different status code is return, call RTTestIFailed giving the line
+ * number, expression, actual and expected status codes.
+ *
+ * @param rcExpr The expression resulting in an IPRT status code.
+ * @param rcExpect The expected return code. This may be referenced
+ * more than once by the macro.
+ */
+#define RTTESTI_CHECK_RC(rcExpr, rcExpect) \
+ do { \
+ int rcCheck = (rcExpr); \
+ if (rcCheck != (rcExpect)) { \
+ RTTestIFailed("line %u: %s: expected %Rrc, got %Rrc", __LINE__, #rcExpr, (rcExpect), rcCheck); \
+ } \
+ } while (0)
+/** @def RTTESTI_CHECK_RC_RET
+ * Check whether an expression returns a specific IPRT style status code.
+ *
+ * If a different status code is return, call RTTestIFailed giving the line
+ * number, expression, actual and expected status codes, then return.
+ *
+ * @param rcExpr The expression resulting in an IPRT status code.
+ * This will be assigned to a local rcCheck variable
+ * that can be used as return value.
+ * @param rcExpect The expected return code. This may be referenced
+ * more than once by the macro.
+ * @param rcRet The return code.
+ */
+#define RTTESTI_CHECK_RC_RET(rcExpr, rcExpect, rcRet) \
+ do { \
+ int rcCheck = (rcExpr); \
+ if (rcCheck != (rcExpect)) { \
+ RTTestIFailed("line %u: %s: expected %Rrc, got %Rrc", __LINE__, #rcExpr, (rcExpect), rcCheck); \
+ return (rcRet); \
+ } \
+ } while (0)
+/** @def RTTESTI_CHECK_RC_RETV
+ * Check whether an expression returns a specific IPRT style status code.
+ *
+ * If a different status code is return, call RTTestIFailed giving the line
+ * number, expression, actual and expected status codes, then return.
+ *
+ * @param rcExpr The expression resulting in an IPRT status code.
+ * @param rcExpect The expected return code. This may be referenced
+ * more than once by the macro.
+ */
+#define RTTESTI_CHECK_RC_RETV(rcExpr, rcExpect) \
+ do { \
+ int rcCheck = (rcExpr); \
+ if (rcCheck != (rcExpect)) { \
+ RTTestIFailed("line %u: %s: expected %Rrc, got %Rrc", __LINE__, #rcExpr, (rcExpect), rcCheck); \
+ return; \
+ } \
+ } while (0)
+/** @def RTTESTI_CHECK_RC_BREAK
+ * Check whether an expression returns a specific IPRT style status code.
+ *
+ * If a different status code is return, call RTTestIFailed giving the line
+ * number, expression, actual and expected status codes, then break.
+ *
+ * @param rcExpr The expression resulting in an IPRT status code.
+ * @param rcExpect The expected return code. This may be referenced
+ * more than once by the macro.
+ */
+#define RTTESTI_CHECK_RC_BREAK(rcExpr, rcExpect) \
+ if (1) { \
+ int rcCheck = (rcExpr); \
+ if (rcCheck != (rcExpect)) { \
+ RTTestIFailed("line %u: %s: expected %Rrc, got %Rrc", __LINE__, #rcExpr, (rcExpect), rcCheck); \
+ break; \
+ } \
+ } else do {} while (0)
+/** @def RTTESTI_CHECK_RC_OK
+ * Check whether a IPRT style status code indicates success.
+ *
+ * If the status indicates failure, call RTTestIFailed giving the line number,
+ * expression and status code.
+ *
+ * @param rcExpr The expression resulting in an IPRT status code.
+ */
+#define RTTESTI_CHECK_RC_OK(rcExpr) \
+ do { \
+ int rcCheck = (rcExpr); \
+ if (RT_FAILURE(rcCheck)) { \
+ RTTestIFailed("line %u: %s: %Rrc", __LINE__, #rcExpr, rcCheck); \
+ } \
+ } while (0)
+/** @def RTTESTI_CHECK_RC_OK_BREAK
+ * Check whether a IPRT style status code indicates success.
+ *
+ * If a different status code is return, call RTTestIFailed giving the line
+ * number, expression, actual and expected status codes, then break.
+ *
+ * @param rcExpr The expression resulting in an IPRT status code.
+ */
+#define RTTESTI_CHECK_RC_OK_BREAK(rcExpr) \
+ do { \
+ int rcCheck = (rcExpr); \
+ if (RT_FAILURE(rcCheck)) { \
+ RTTestIFailed("line %u: %s: %Rrc", __LINE__, #rcExpr, rcCheck); \
+ break; \
+ } \
+ } while (0)
+/** @def RTTESTI_CHECK_RC_OK_RET
+ * Check whether a IPRT style status code indicates success.
+ *
+ * If the status indicates failure, call RTTestIFailed giving the line number,
+ * expression and status code, then return with the specified value.
+ *
+ * @param rcExpr The expression resulting in an IPRT status code.
+ * This will be assigned to a local rcCheck variable
+ * that can be used as return value.
+ * @param rcRet The return code.
+ */
+#define RTTESTI_CHECK_RC_OK_RET(rcExpr, rcRet) \
+ do { \
+ int rcCheck = (rcExpr); \
+ if (RT_FAILURE(rcCheck)) { \
+ RTTestIFailed("line %u: %s: %Rrc", __LINE__, #rcExpr, rcCheck); \
+ return (rcRet); \
+ } \
+ } while (0)
+/** @def RTTESTI_CHECK_RC_OK_RETV
+ * Check whether a IPRT style status code indicates success.
+ *
+ * If the status indicates failure, call RTTestIFailed giving the line number,
+ * expression and status code, then return.
+ *
+ * @param rcExpr The expression resulting in an IPRT status code.
+ */
+#define RTTESTI_CHECK_RC_OK_RETV(rcExpr) \
+ do { \
+ int rcCheck = (rcExpr); \
+ if (RT_FAILURE(rcCheck)) { \
+ RTTestIFailed("line %u: %s: %Rrc", __LINE__, #rcExpr, rcCheck); \
+ return; \
+ } \
+ } while (0)
+
+/** @} */
+
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_test_h */
+
diff --git a/include/iprt/thread.h b/include/iprt/thread.h
new file mode 100644
index 00000000..551c8bcc
--- /dev/null
+++ b/include/iprt/thread.h
@@ -0,0 +1,1023 @@
+/** @file
+ * IPRT - Threads.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_thread_h
+#define IPRT_INCLUDED_thread_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#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;
+
+
+#if !defined(IN_RC) || defined(DOXYGEN_RUNNING)
+
+/**
+ * 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 DECLCALLBACKTYPE(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,
+
+ /** Call CoInitializeEx w/ COINIT_MULTITHREADED, COINIT_DISABLE_OLE1DDE and
+ * COINIT_SPEED_OVER_MEMORY. Ignored on non-windows platforms. */
+ RTTHREADFLAGS_COM_MTA = RT_BIT(1),
+ /** Call CoInitializeEx w/ COINIT_APARTMENTTHREADED and
+ * COINIT_SPEED_OVER_MEMORY. Ignored on non-windows platforms. */
+ RTTHREADFLAGS_COM_STA = RT_BIT(2),
+
+ /** Mask all signals that we can mask. Ignored on most non-posix platforms.
+ * @note RTThreadPoke() will not necessarily work for a thread create with
+ * this flag. */
+ RTTHREADFLAGS_NO_SIGNALS = RT_BIT(3),
+
+ /** Mask of valid flags, use for validation. */
+ RTTHREADFLAGS_MASK = UINT32_C(0xf)
+} RTTHREADFLAGS;
+
+/** Max thread name length (including zero terminator). */
+#define RTTHREAD_NAME_LEN 16
+
+/**
+ * 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 */
+/** Pointer to a RTThreadCreate function. */
+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 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) 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 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, ...) 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 native thread handle for a IPRT thread.
+ *
+ * @returns The thread handle. INVALID_HANDLE_VALUE on failure.
+ * @param hThread The IPRT thread handle.
+ *
+ * @note Windows only.
+ * @note Only valid after parent returns from the thread creation call.
+ */
+RTDECL(uintptr_t) RTThreadGetNativeHandle(RTTHREAD hThread);
+
+/**
+ * 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);
+
+#ifdef IN_RING0
+/**
+ * Checks whether the specified thread is terminating.
+ *
+ * @retval VINF_SUCCESS if not terminating.
+ * @retval VINF_THREAD_IS_TERMINATING if terminating.
+ * @retval VERR_INVALID_HANDLE if hThread is not NIL_RTTHREAD.
+ * @retval VERR_NOT_SUPPORTED if the OS doesn't provide ways to check.
+ *
+ * @param hThread The thread to query about, NIL_RTTHREAD is an alias for
+ * the calling thread. Must be NIL_RTTHREAD for now.
+ *
+ * @note Not suppored on all OSes, so check for VERR_NOT_SUPPORTED.
+ */
+RTDECL(int) RTThreadQueryTerminationStatus(RTTHREAD hThread);
+#endif
+
+/**
+ * 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 wake up or/and signal the thread, attempting to interrupt whatever
+ * it's currently doing.
+ *
+ * The posixy version of this will send a signal to the thread, quite likely
+ * waking it up from normal sleeps, waits, and I/O. When IPRT is in
+ * non-obtrusive mode, the posixy version will definitely return
+ * VERR_NOT_IMPLEMENTED, and it may also do so if no usable signal was found.
+ *
+ * On Windows the thread will be alerted, waking it up from most sleeps and
+ * waits, but not probably very little in the I/O area (needs testing). On NT
+ * 3.50 and 3.1 VERR_NOT_IMPLEMENTED will be returned.
+ *
+ * @returns IPRT status code.
+ *
+ * @param hThread The thread to poke. This must not be the
+ * calling thread.
+ *
+ * @note This is *NOT* implemented on all platforms and may cause unresolved
+ * symbols during linking or VERR_NOT_IMPLEMENTED at runtime.
+ *
+ */
+RTDECL(int) RTThreadPoke(RTTHREAD hThread);
+
+/**
+ * Controls the masking of the signal used by RTThreadPoke on posix systems.
+ *
+ * This function is not available on non-posix systems.
+ *
+ * @returns IPRT status code.
+ *
+ * @param hThread The current thread.
+ * @param fEnable Whether to enable poking (unblock) or to disable it
+ * (block the signal).
+ */
+RTDECL(int) RTThreadControlPokeSignal(RTTHREAD hThread, bool fEnable);
+
+
+# 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.
+ *
+ * @note If called with interrupts disabled, the NT kernel may temporarily
+ * re-enable them while checking.
+ */
+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 DECLCALLBACKTYPE(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 DECLCALLBACKTYPE(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.
+ * @note In static builds on windows, the destructor will only be invoked for
+ * IPRT threads.
+ * @note There are probably OS specific restrictions on what operations you
+ * are allowed to perform from a TLS destructor, so keep it simple.
+ */
+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 || defined(DOXYGEN_RUNNING) */
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_thread_h */
+
diff --git a/include/iprt/time.h b/include/iprt/time.h
new file mode 100644
index 00000000..178f1e33
--- /dev/null
+++ b/include/iprt/time.h
@@ -0,0 +1,1352 @@
+/** @file
+ * IPRT - Time.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_time_h
+#define IPRT_INCLUDED_time_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+#include <iprt/assertcompile.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;
+}
+
+/** @def RTTIME_LINUX_KERNEL_PREREQ
+ * Prerequisite minimum linux kernel version.
+ * @note Cannot really be moved to iprt/cdefs.h, see the-linux-kernel.h */
+/** @def RTTIME_LINUX_KERNEL_PREREQ_LT
+ * Prerequisite maxium linux kernel version (LT=less-than).
+ * @note Cannot really be moved to iprt/cdefs.h, see the-linux-kernel.h */
+#if defined(RT_OS_LINUX) && defined(LINUX_VERSION_CODE) && defined(KERNEL_VERSION)
+# define RTTIME_LINUX_KERNEL_PREREQ(a, b, c) (LINUX_VERSION_CODE >= KERNEL_VERSION(a, b, c))
+# define RTTIME_LINUX_KERNEL_PREREQ_LT(a, b, c) (!RTTIME_LINUX_KERNEL_PREREQ(a, b, c))
+#else
+# define RTTIME_LINUX_KERNEL_PREREQ(a, b, c) 0
+# define RTTIME_LINUX_KERNEL_PREREQ_LT(a, b, c) 0
+#endif
+
+/* PORTME: Add struct timeval guard macro here. */
+#if defined(RTTIME_INCL_TIMEVAL) \
+ || defined(_SYS__TIMEVAL_H_) \
+ || defined(_SYS_TIME_H) \
+ || defined(_TIMEVAL) \
+ || defined(_STRUCT_TIMEVAL) \
+ || ( defined(RT_OS_LINUX) \
+ && defined(_LINUX_TIME_H) \
+ && ( !defined(__KERNEL__) \
+ || RTTIME_LINUX_KERNEL_PREREQ_LT(5,6,0) /* @bugref{9757} */ ) ) \
+ || (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(_SYS__TIMESPEC_H_) \
+ || defined(TIMEVAL_TO_TIMESPEC) \
+ || defined(_TIMESPEC) \
+ || ( defined(_STRUCT_TIMESPEC) \
+ && ( !defined(RT_OS_LINUX) \
+ || !defined(__KERNEL__) \
+ || RTTIME_LINUX_KERNEL_PREREQ_LT(5,6,0) /* @bugref{9757} */ ) ) \
+ || (defined(RT_OS_NETBSD) && defined(_SYS_TIME_H_))
+
+/**
+ * Gets the time as POSIX timespec.
+ *
+ * @returns pTimespec.
+ * @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 */
+
+
+#if defined(RT_OS_LINUX) && defined(_LINUX_TIME64_H) /* since linux 3.17 */
+
+/**
+ * Gets the time a linux 64-bit timespec structure.
+ * @returns pTimespec.
+ * @param pTime The time spec to modify.
+ * @param pTimespec Where to store the time as linux 64-bit timespec.
+ */
+DECLINLINE(struct timespec64 *) RTTimeSpecGetTimespec64(PCRTTIMESPEC pTime, struct timespec64 *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 = i64;
+ pTimespec->tv_nsec = i32Nano;
+ return pTimespec;
+}
+
+/**
+ * Sets the time from a linux 64-bit timespec structure.
+ * @returns pTime.
+ * @param pTime The time spec to modify.
+ * @param pTimespec Pointer to the linux 64-bit timespec struct with the new time.
+ */
+DECLINLINE(PRTTIMESPEC) RTTimeSpecSetTimespec64(PRTTIMESPEC pTime, const struct timespec64 *pTimespec)
+{
+ return RTTimeSpecAddNano(RTTimeSpecSetSeconds(pTime, pTimespec->tv_sec), pTimespec->tv_nsec);
+}
+
+#endif /* RT_OS_LINUX && _LINUX_TIME64_H */
+
+
+/** 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(int64_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 /* _FILETIME_ */
+
+
+/** 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);
+
+/**
+ * Formats duration as best we can according to ISO-8601, with no fraction.
+ *
+ * See RTTimeFormatDurationEx for details.
+ *
+ * @returns Number of characters in the output on success. VERR_BUFFER_OVEFLOW
+ * on failure.
+ * @param pszDst Pointer to the output buffer. In case of overflow,
+ * the max number of characters will be written and
+ * zero terminated, provided @a cbDst isn't zero.
+ * @param cbDst The size of the output buffer.
+ * @param pDuration The duration to format.
+ */
+RTDECL(int) RTTimeFormatDuration(char *pszDst, size_t cbDst, PCRTTIMESPEC pDuration);
+
+/**
+ * Formats duration as best we can according to ISO-8601.
+ *
+ * The returned value is on the form "[-]PnnnnnWnDTnnHnnMnn.fffffffffS", where a
+ * sequence of 'n' can be between 1 and the given lenght, and all but the
+ * "nn.fffffffffS" part is optional and will only be outputted when the duration
+ * is sufficiently large. The code currently does not omit any inbetween
+ * elements other than the day count (D), so an exactly 7 day duration is
+ * formatted as "P1WT0H0M0.000000000S" when @a cFractionDigits is 9.
+ *
+ * @returns Number of characters in the output on success. VERR_BUFFER_OVEFLOW
+ * on failure.
+ * @retval VERR_OUT_OF_RANGE if @a cFractionDigits is too large.
+ * @param pszDst Pointer to the output buffer. In case of overflow,
+ * the max number of characters will be written and
+ * zero terminated, provided @a cbDst isn't zero.
+ * @param cbDst The size of the output buffer.
+ * @param pDuration The duration to format.
+ * @param cFractionDigits Number of digits in the second fraction part. Zero
+ * for whole no fraction. Max is 9 (nano seconds).
+ */
+RTDECL(ssize_t) RTTimeFormatDurationEx(char *pszDst, size_t cbDst, PCRTTIMESPEC pDuration, uint32_t cFractionDigits);
+
+/** Max length of a RTTimeFormatDurationEx output string. */
+#define RTTIME_DURATION_STR_LEN (sizeof("-P99999W7D23H59M59.123456789S") + 2)
+
+/** @} */
+
+
+/**
+ * Exploded time.
+ */
+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;
+ /** UTC time offset in minutes (-840-840). Positive for timezones east of
+ * UTC, negative for zones to the west. Same as what RTTimeLocalDeltaNano
+ * & RTTimeLocalDeltaNanoFor returns, just different unit. */
+ int32_t offUTC;
+} RTTIME;
+AssertCompileSize(RTTIME, 24);
+/** 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 current 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);
+
+/**
+ * Gets the delta between UTC and local time at the given time.
+ *
+ * @code
+ * RTTIMESPEC LocalTime;
+ * RTTimeNow(&LocalTime);
+ * RTTimeSpecAddNano(&LocalTime, RTTimeLocalDeltaNanoFor(&LocalTime));
+ * @endcode
+ *
+ * @param pTimeSpec The time spec giving the time to get the delta for.
+ * @returns Returns the nanosecond delta between UTC and local time.
+ */
+RTDECL(int64_t) RTTimeLocalDeltaNanoFor(PCRTTIMESPEC pTimeSpec);
+
+/**
+ * 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 structure to UTC, relying on UTC offset information
+ * if it contains local time.
+ *
+ * @returns pTime on success.
+ * @returns NULL if the data is invalid.
+ * @param pTime The time structure to convert.
+ */
+RTDECL(PRTTIME) RTTimeConvertToZulu(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);
+
+/**
+ * Converts a time spec to a ISO date string, extended version.
+ *
+ * @returns Output string length on success (positive), VERR_BUFFER_OVERFLOW
+ * (negative) or VERR_OUT_OF_RANGE (negative) on failure.
+ * @param pTime The time. Caller should've normalized this.
+ * @param psz Where to store the string.
+ * @param cb The size of the buffer.
+ * @param cFractionDigits Number of digits in the fraction. Max is 9.
+ */
+RTDECL(ssize_t) RTTimeToStringEx(PCRTTIME pTime, char *psz, size_t cb, unsigned cFractionDigits);
+
+/** Suggested buffer length for RTTimeToString and RTTimeToStringEx output, including terminator. */
+#define RTTIME_STR_LEN 40
+
+/**
+ * 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);
+
+/**
+ * Formats the given time on a RTC-2822 compliant format.
+ *
+ * @returns Output string length on success (positive), VERR_BUFFER_OVERFLOW
+ * (negative) on failure.
+ * @param pTime The time. Caller should've normalized this.
+ * @param psz Where to store the string.
+ * @param cb The size of the buffer.
+ * @param fFlags RTTIME_RFC2822_F_XXX
+ * @sa RTTIME_RFC2822_LEN
+ */
+RTDECL(ssize_t) RTTimeToRfc2822(PRTTIME pTime, char *psz, size_t cb, uint32_t fFlags);
+
+/** Suggested buffer length for RTTimeToRfc2822 output, including terminator. */
+#define RTTIME_RFC2822_LEN 40
+/** @name RTTIME_RFC2822_F_XXX
+ * @{ */
+/** Use the deprecated GMT timezone instead of +/-0000.
+ * This is required by the HTTP RFC-7231 7.1.1.1. */
+#define RTTIME_RFC2822_F_GMT RT_BIT_32(0)
+/** @} */
+
+/**
+ * Attempts to convert an RFC-2822 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) RTTimeFromRfc2822(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);
+
+/**
+ * Compares two normalized time structures.
+ *
+ * @retval 0 if equal.
+ * @retval -1 if @a pLeft is earlier than @a pRight.
+ * @retval 1 if @a pRight is earlier than @a pLeft.
+ *
+ * @param pLeft The left side time. NULL is accepted.
+ * @param pRight The right side time. NULL is accepted.
+ *
+ * @note A NULL time is considered smaller than anything else. If both are
+ * NULL, they are considered equal.
+ */
+RTDECL(int) RTTimeCompare(PCRTTIME pLeft, PCRTTIME pRight);
+
+/**
+ * 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);
+
+
+RTDECL(const char *) RTTimeNanoTSWorkerName(void);
+
+
+/** @name RTTimeNanoTS GIP worker functions, for TM.
+ * @{ */
+
+/** Extra info optionally returned by the RTTimeNanoTS GIP workers. */
+typedef struct RTITMENANOTSEXTRA
+{
+ /** The TSC value used (delta adjusted). */
+ uint64_t uTSCValue;
+} RTITMENANOTSEXTRA;
+/** Pointer to extra info optionally returned by the RTTimeNanoTS GIP workers. */
+typedef RTITMENANOTSEXTRA *PRTITMENANOTSEXTRA;
+
+/** 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.
+ * @param pExtra Where to return extra time info. Optional.
+ */
+ DECLCALLBACKMEMBER(uint64_t, pfnRediscover,(PRTTIMENANOTSDATA pData, PRTITMENANOTSEXTRA pExtra));
+
+ /**
+ * Callback for when some CPU index related stuff goes wrong.
+ *
+ * @returns Nanosecond timestamp.
+ * @param pData Pointer to this structure.
+ * @param pExtra Where to return extra time info. Optional.
+ * @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, PRTITMENANOTSEXTRA pExtra,
+ 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, PRTITMENANOTSEXTRA pExtra));
+ DECLR3CALLBACKMEMBER(uint64_t, pfnBadCpuIndex,(PRTTIMENANOTSDATA pData, PRTITMENANOTSEXTRA pExtra,
+ 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, PRTITMENANOTSEXTRA pExtra));
+ DECLR0CALLBACKMEMBER(uint64_t, pfnBadCpuIndex,(PRTTIMENANOTSDATA pData, PRTITMENANOTSEXTRA pExtra,
+ 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, PRTITMENANOTSEXTRA pExtra));
+ DECLRCCALLBACKMEMBER(uint64_t, pfnBadCpuIndex,(PRTTIMENANOTSDATA pData, PRTITMENANOTSEXTRA pExtra,
+ 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 DECLCALLBACKTYPE(uint64_t, FNTIMENANOTSINTERNAL,(PRTTIMENANOTSDATA pData, PRTITMENANOTSEXTRA pExtra));
+/** Pointer to an internal RTTimeNanoTS worker (assembly). */
+typedef FNTIMENANOTSINTERNAL *PFNTIMENANOTSINTERNAL;
+RTDECL(uint64_t) RTTimeNanoTSLegacySyncInvarNoDelta(PRTTIMENANOTSDATA pData, PRTITMENANOTSEXTRA pExtra);
+RTDECL(uint64_t) RTTimeNanoTSLFenceSyncInvarNoDelta(PRTTIMENANOTSDATA pData, PRTITMENANOTSEXTRA pExtra);
+#ifdef IN_RING3
+RTDECL(uint64_t) RTTimeNanoTSLegacyAsyncUseApicId(PRTTIMENANOTSDATA pData, PRTITMENANOTSEXTRA pExtra);
+RTDECL(uint64_t) RTTimeNanoTSLegacyAsyncUseApicIdExt0B(PRTTIMENANOTSDATA pData, PRTITMENANOTSEXTRA pExtra);
+RTDECL(uint64_t) RTTimeNanoTSLegacyAsyncUseApicIdExt8000001E(PRTTIMENANOTSDATA pData, PRTITMENANOTSEXTRA pExtra);
+RTDECL(uint64_t) RTTimeNanoTSLegacyAsyncUseRdtscp(PRTTIMENANOTSDATA pData, PRTITMENANOTSEXTRA pExtra);
+RTDECL(uint64_t) RTTimeNanoTSLegacyAsyncUseRdtscpGroupChNumCl(PRTTIMENANOTSDATA pData, PRTITMENANOTSEXTRA pExtra);
+RTDECL(uint64_t) RTTimeNanoTSLegacyAsyncUseIdtrLim(PRTTIMENANOTSDATA pData, PRTITMENANOTSEXTRA pExtra);
+RTDECL(uint64_t) RTTimeNanoTSLegacySyncInvarWithDeltaUseApicId(PRTTIMENANOTSDATA pData, PRTITMENANOTSEXTRA pExtra);
+RTDECL(uint64_t) RTTimeNanoTSLegacySyncInvarWithDeltaUseApicIdExt0B(PRTTIMENANOTSDATA pData, PRTITMENANOTSEXTRA pExtra);
+RTDECL(uint64_t) RTTimeNanoTSLegacySyncInvarWithDeltaUseApicIdExt8000001E(PRTTIMENANOTSDATA pData, PRTITMENANOTSEXTRA pExtra);
+RTDECL(uint64_t) RTTimeNanoTSLegacySyncInvarWithDeltaUseRdtscp(PRTTIMENANOTSDATA pData, PRTITMENANOTSEXTRA pExtra);
+RTDECL(uint64_t) RTTimeNanoTSLegacySyncInvarWithDeltaUseIdtrLim(PRTTIMENANOTSDATA pData, PRTITMENANOTSEXTRA pExtra);
+RTDECL(uint64_t) RTTimeNanoTSLFenceAsyncUseApicId(PRTTIMENANOTSDATA pData, PRTITMENANOTSEXTRA pExtra);
+RTDECL(uint64_t) RTTimeNanoTSLFenceAsyncUseApicIdExt0B(PRTTIMENANOTSDATA pData, PRTITMENANOTSEXTRA pExtra);
+RTDECL(uint64_t) RTTimeNanoTSLFenceAsyncUseApicIdExt8000001E(PRTTIMENANOTSDATA pData, PRTITMENANOTSEXTRA pExtra);
+RTDECL(uint64_t) RTTimeNanoTSLFenceAsyncUseRdtscp(PRTTIMENANOTSDATA pData, PRTITMENANOTSEXTRA pExtra);
+RTDECL(uint64_t) RTTimeNanoTSLFenceAsyncUseRdtscpGroupChNumCl(PRTTIMENANOTSDATA pData, PRTITMENANOTSEXTRA pExtra);
+RTDECL(uint64_t) RTTimeNanoTSLFenceAsyncUseIdtrLim(PRTTIMENANOTSDATA pData, PRTITMENANOTSEXTRA pExtra);
+RTDECL(uint64_t) RTTimeNanoTSLFenceSyncInvarWithDeltaUseApicId(PRTTIMENANOTSDATA pData, PRTITMENANOTSEXTRA pExtra);
+RTDECL(uint64_t) RTTimeNanoTSLFenceSyncInvarWithDeltaUseApicIdExt0B(PRTTIMENANOTSDATA pData, PRTITMENANOTSEXTRA pExtra);
+RTDECL(uint64_t) RTTimeNanoTSLFenceSyncInvarWithDeltaUseApicIdExt8000001E(PRTTIMENANOTSDATA pData, PRTITMENANOTSEXTRA pExtra);
+RTDECL(uint64_t) RTTimeNanoTSLFenceSyncInvarWithDeltaUseRdtscp(PRTTIMENANOTSDATA pData, PRTITMENANOTSEXTRA pExtra);
+RTDECL(uint64_t) RTTimeNanoTSLFenceSyncInvarWithDeltaUseIdtrLim(PRTTIMENANOTSDATA pData, PRTITMENANOTSEXTRA pExtra);
+#else
+RTDECL(uint64_t) RTTimeNanoTSLegacyAsync(PRTTIMENANOTSDATA pData, PRTITMENANOTSEXTRA pExtra);
+RTDECL(uint64_t) RTTimeNanoTSLegacySyncInvarWithDelta(PRTTIMENANOTSDATA pData, PRTITMENANOTSEXTRA pExtra);
+RTDECL(uint64_t) RTTimeNanoTSLFenceAsync(PRTTIMENANOTSDATA pData, PRTITMENANOTSEXTRA pExtra);
+RTDECL(uint64_t) RTTimeNanoTSLFenceSyncInvarWithDelta(PRTTIMENANOTSDATA pData, PRTITMENANOTSEXTRA pExtra);
+#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);
+
+
+/**
+ * Time zone information.
+ */
+typedef struct RTTIMEZONEINFO
+{
+ /** Unix time zone name (continent/country[/city]|). */
+ const char *pszUnixName;
+ /** Windows time zone name. */
+ const char *pszWindowsName;
+ /** The length of the unix time zone name. */
+ uint8_t cchUnixName;
+ /** The length of the windows time zone name. */
+ uint8_t cchWindowsName;
+ /** Two letter country/territory code if applicable, otherwise 'ZZ'. */
+ char szCountry[3];
+ /** Two letter windows country/territory code if applicable.
+ * Empty string if no windows mapping. */
+ char szWindowsCountry[3];
+#if 0 /* Add when needed and it's been extracted. */
+ /** The standard delta in minutes (add to UTC). */
+ int16_t cMinStdDelta;
+ /** The daylight saving time delta in minutes (add to UTC). */
+ int16_t cMinDstDelta;
+#endif
+ /** closest matching windows time zone index. */
+ uint32_t idxWindows;
+ /** Flags, RTTIMEZONEINFO_F_XXX. */
+ uint32_t fFlags;
+} RTTIMEZONEINFO;
+/** Pointer to time zone info. */
+typedef RTTIMEZONEINFO const *PCRTTIMEZONEINFO;
+
+/** @name RTTIMEZONEINFO_F_XXX - time zone info flags.
+ * @{ */
+/** Indicates golden mapping entry for a windows time zone name. */
+#define RTTIMEZONEINFO_F_GOLDEN RT_BIT_32(0)
+/** @} */
+
+/**
+ * Looks up static time zone information by unix name.
+ *
+ * @returns Pointer to info entry if found, NULL if not.
+ * @param pszName The unix zone name (TZ).
+ */
+RTDECL(PCRTTIMEZONEINFO) RTTimeZoneGetInfoByUnixName(const char *pszName);
+
+/**
+ * Looks up static time zone information by window name.
+ *
+ * @returns Pointer to info entry if found, NULL if not.
+ * @param pszName The windows zone name (reg key).
+ */
+RTDECL(PCRTTIMEZONEINFO) RTTimeZoneGetInfoByWindowsName(const char *pszName);
+
+/**
+ * Looks up static time zone information by windows index.
+ *
+ * @returns Pointer to info entry if found, NULL if not.
+ * @param idxZone The windows timezone index.
+ */
+RTDECL(PCRTTIMEZONEINFO) RTTimeZoneGetInfoByWindowsIndex(uint32_t idxZone);
+
+/**
+ * Get the current time zone (TZ).
+ *
+ * @returns IPRT status code.
+ * @param pszName Where to return the time zone name.
+ * @param cbName The size of the name buffer.
+ */
+RTDECL(int) RTTimeZoneGetCurrent(char *pszName, size_t cbName);
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_time_h */
+
diff --git a/include/iprt/timer.h b/include/iprt/timer.h
new file mode 100644
index 00000000..8cb34987
--- /dev/null
+++ b/include/iprt/timer.h
@@ -0,0 +1,400 @@
+/** @file
+ * IPRT - Timer.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_timer_h
+#define IPRT_INCLUDED_timer_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+
+#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 DECLCALLBACKTYPE(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 DECLCALLBACKTYPE(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 /* !IPRT_INCLUDED_timer_h */
diff --git a/include/iprt/tpm.h b/include/iprt/tpm.h
new file mode 100644
index 00000000..04cd475e
--- /dev/null
+++ b/include/iprt/tpm.h
@@ -0,0 +1,156 @@
+/** @file
+ * IPRT Trusted Platform Module API abstracting host specific APIs.
+ */
+
+/*
+ * Copyright (C) 2021-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_tpm_h
+#define IPRT_INCLUDED_tpm_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+
+#include <iprt/formats/tpm.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_tpm IPRT Trusted Platform Module API
+ * @ingroup grp_rt
+ *
+ * This API provides a uniform way to access a Trusted Platform Module across all
+ * supported hosts.
+ *
+ * @{
+ */
+
+
+/**
+ * TPM version.
+ */
+typedef enum RTTPMVERSION
+{
+ /** The usual invalid option. */
+ RTTPMVERSION_INVALID = 0,
+ /** TPM conforms to version 1.2 of the TCG specification. */
+ RTTPMVERSION_1_2,
+ /** TPM conforms to version 2.0 of the TCG specification. */
+ RTTPMVERSION_2_0,
+ /** TPM version couldn't be acquired. */
+ RTTPMVERSION_UNKNOWN,
+ /** Usual 32bit hack. */
+ RTTPMVERSION_32BIT_HACK = 0x7fffffff
+} RTTPMVERSION;
+/** Pointer to a TPM version. */
+typedef RTTPMVERSION *PRTTPMVERSION;
+
+/** TPM handle. */
+typedef struct RTTPMINT *RTTPM;
+/** Pointer to a TPM handle. */
+typedef RTTPM *PRTTPM;
+/** NIL TPM handle value. */
+#define NIL_RTTPM ((RTTPM)0)
+
+
+/** Default TPM of the host. */
+#define RTTPM_ID_DEFAULT UINT32_C(0xffffffff)
+
+/**
+ * Tries to open the given TPM returning a handle.
+ *
+ * @returns IPRT status code.
+ * @param phTpm Where to store the handle to the TPM module on success.
+ * @param idTpm The TPM to open, use RTTPM_ID_DEFAULT for the default TPM of the system.
+ */
+RTDECL(int) RTTpmOpen(PRTTPM phTpm, uint32_t idTpm);
+
+
+/**
+ * Closes the given TPM handle freeing all allocated resources.
+ *
+ * @returns IPRT status code.
+ * @param hTpm Handle of the TPM to close.
+ */
+RTDECL(int) RTTpmClose(RTTPM hTpm);
+
+
+/**
+ * Returns the version of the TPM for the given handle.
+ *
+ * @returns Version implemented by the TPM.
+ * @param hTpm Handle of the TPM.
+ */
+RTDECL(RTTPMVERSION) RTTpmGetVersion(RTTPM hTpm);
+
+
+/**
+ * Returns the maximum locality supported by the given TPM.
+ *
+ * @returns Maximum locality supported (0-4).
+ * @param hTpm Handle of the TPM.
+ */
+RTDECL(uint32_t) RTTpmGetLocalityMax(RTTPM hTpm);
+
+
+/**
+ * Cancels a currently executed request for the given TPM handle.
+ *
+ * @returns IPRT status code.
+ * @param hTpm Handle of the TPM.
+ */
+RTDECL(int) RTTpmReqCancel(RTTPM hTpm);
+
+
+/**
+ * Executes the given request on the given TPM handle.
+ *
+ * @returns IPRT status code.
+ * @param hTpm Handle of the TPM.
+ * @param bLoc The locality to use (only 0 might be supported on some hosts).
+ * @param pvReq The request data.
+ * @param cbReq Size of the request in bytes.
+ * @param pvResp Where to store the response data.
+ * @param cbRespMax Size of the response buffer.
+ * @param pcbResp Where to store the actual size of the response, optional.
+ */
+RTDECL(int) RTTpmReqExec(RTTPM hTpm, uint8_t bLoc, const void *pvReq, size_t cbReq,
+ void *pvResp, size_t cbRespMax, size_t *pcbResp);
+
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_tpm_h */
+
diff --git a/include/iprt/trace.h b/include/iprt/trace.h
new file mode 100644
index 00000000..32341d15
--- /dev/null
+++ b/include/iprt/trace.h
@@ -0,0 +1,228 @@
+/** @file
+ * IPRT - Tracing.
+ */
+
+/*
+ * Copyright (C) 2011-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_trace_h
+#define IPRT_INCLUDED_trace_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+#include <iprt/stdarg.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_trace RTTrace - Tracing
+ * @ingroup grp_rt
+ *
+ * The tracing facility is somewhat similar to a stripped down logger that
+ * outputs to a circular buffer. Part of the idea here is that it can the
+ * overhead is much smaller and that it can be done without involving any
+ * locking or other thing that could throw off timing.
+ *
+ * @{
+ */
+
+
+#ifdef DOXYGEN_RUNNING
+# define RTTRACE_DISABLED
+# define RTTRACE_ENABLED
+#endif
+
+/** @def RTTRACE_DISABLED
+ * Use this compile time define to disable all tracing macros. This trumps
+ * RTTRACE_ENABLED.
+ */
+
+/** @def RTTRACE_ENABLED
+ * Use this compile time define to enable tracing when not in debug mode
+ */
+
+/*
+ * Determine whether tracing is enabled and forcefully normalize the indicators.
+ */
+#if (defined(DEBUG) || defined(RTTRACE_ENABLED)) && !defined(RTTRACE_DISABLED)
+# undef RTTRACE_DISABLED
+# undef RTTRACE_ENABLED
+# define RTTRACE_ENABLED
+#else
+# undef RTTRACE_DISABLED
+# undef RTTRACE_ENABLED
+# define RTTRACE_DISABLED
+#endif
+
+
+/** @name RTTRACEBUF_FLAGS_XXX - RTTraceBufCarve and RTTraceBufCreate flags.
+ * @{ */
+/** Free the memory block on release using RTMemFree(). */
+#define RTTRACEBUF_FLAGS_FREE_ME RT_BIT_32(0)
+/** Whether the trace buffer is disabled or enabled. */
+#define RTTRACEBUF_FLAGS_DISABLED RT_BIT_32(RTTRACEBUF_FLAGS_DISABLED_BIT)
+/** The bit number corresponding to the RTTRACEBUF_FLAGS_DISABLED mask. */
+#define RTTRACEBUF_FLAGS_DISABLED_BIT 1
+/** Mask of the valid flags. */
+#define RTTRACEBUF_FLAGS_MASK UINT32_C(0x00000003)
+/** @} */
+
+
+RTDECL(int) RTTraceBufCreate(PRTTRACEBUF hTraceBuf, uint32_t cEntries, uint32_t cbEntry, uint32_t fFlags);
+RTDECL(int) RTTraceBufCarve(PRTTRACEBUF hTraceBuf, uint32_t cEntries, uint32_t cbEntry, uint32_t fFlags,
+ void *pvBlock, size_t *pcbBlock);
+RTDECL(uint32_t) RTTraceBufRetain(RTTRACEBUF hTraceBuf);
+RTDECL(uint32_t) RTTraceBufRelease(RTTRACEBUF hTraceBuf);
+RTDECL(int) RTTraceBufDumpToLog(RTTRACEBUF hTraceBuf);
+RTDECL(int) RTTraceBufDumpToAssert(RTTRACEBUF hTraceBuf);
+
+/**
+ * Trace buffer callback for processing one entry.
+ *
+ * Used by RTTraceBufEnumEntries.
+ *
+ * @returns IPRT status code. Any status code but VINF_SUCCESS will abort the
+ * enumeration and be returned by RTTraceBufEnumEntries.
+ * @param hTraceBuf The trace buffer handle.
+ * @param iEntry The entry number.
+ * @param NanoTS The timestamp of the entry.
+ * @param idCpu The ID of the CPU which added the entry.
+ * @param pszMsg The message text.
+ * @param pvUser The user argument.
+ */
+typedef DECLCALLBACKTYPE(int, FNRTTRACEBUFCALLBACK,(RTTRACEBUF hTraceBuf, uint32_t iEntry, uint64_t NanoTS,
+ RTCPUID idCpu, const char *pszMsg, void *pvUser));
+/** Pointer to trace buffer enumeration callback function. */
+typedef FNRTTRACEBUFCALLBACK *PFNRTTRACEBUFCALLBACK;
+
+/**
+ * Enumerates the used trace buffer entries, calling @a pfnCallback for each.
+ *
+ * @returns IPRT status code. Should the callback (@a pfnCallback) return
+ * anything other than VINF_SUCCESS, then the enumeration will be
+ * aborted and the status code will be returned by this function.
+ * @retval VINF_SUCCESS
+ * @retval VERR_INVALID_HANDLE
+ * @retval VERR_INVALID_PARAMETER
+ * @retval VERR_INVALID_POINTER
+ *
+ * @param hTraceBuf The trace buffer handle. Special handles are
+ * accepted.
+ * @param pfnCallback The callback to call for each entry.
+ * @param pvUser The user argument for the callback.
+ */
+RTDECL(int) RTTraceBufEnumEntries(RTTRACEBUF hTraceBuf, PFNRTTRACEBUFCALLBACK pfnCallback, void *pvUser);
+
+/**
+ * Gets the entry size used by the specified trace buffer.
+ *
+ * @returns The size on success, 0 if the handle is invalid.
+ *
+ * @param hTraceBuf The trace buffer handle. Special handles are
+ * accepted.
+ */
+RTDECL(uint32_t) RTTraceBufGetEntrySize(RTTRACEBUF hTraceBuf);
+
+/**
+ * Gets the number of entries in the specified trace buffer.
+ *
+ * @returns The entry count on success, 0 if the handle is invalid.
+ *
+ * @param hTraceBuf The trace buffer handle. Special handles are
+ * accepted.
+ */
+RTDECL(uint32_t) RTTraceBufGetEntryCount(RTTRACEBUF hTraceBuf);
+
+
+/**
+ * Disables tracing.
+ *
+ * @returns @c true if tracing was enabled prior to this call, @c false if
+ * disabled already.
+ *
+ * @param hTraceBuf The trace buffer handle. Special handles are
+ * accepted.
+ */
+RTDECL(bool) RTTraceBufDisable(RTTRACEBUF hTraceBuf);
+
+/**
+ * Enables tracing.
+ *
+ * @returns @c true if tracing was enabled prior to this call, @c false if
+ * disabled already.
+ *
+ * @param hTraceBuf The trace buffer handle. Special handles are
+ * accepted.
+ */
+RTDECL(bool) RTTraceBufEnable(RTTRACEBUF hTraceBuf);
+
+
+RTDECL(int) RTTraceBufAddMsg( RTTRACEBUF hTraceBuf, const char *pszMsg);
+RTDECL(int) RTTraceBufAddMsgF( RTTRACEBUF hTraceBuf, const char *pszMsgFmt, ...) RT_IPRT_FORMAT_ATTR(2, 3);
+RTDECL(int) RTTraceBufAddMsgV( RTTRACEBUF hTraceBuf, const char *pszMsgFmt, va_list va) RT_IPRT_FORMAT_ATTR(2, 0);
+RTDECL(int) RTTraceBufAddMsgEx( RTTRACEBUF hTraceBuf, const char *pszMsg, size_t cbMaxMsg);
+
+RTDECL(int) RTTraceBufAddPos( RTTRACEBUF hTraceBuf, RT_SRC_POS_DECL);
+RTDECL(int) RTTraceBufAddPosMsg( RTTRACEBUF hTraceBuf, RT_SRC_POS_DECL, const char *pszMsg);
+RTDECL(int) RTTraceBufAddPosMsgEx( RTTRACEBUF hTraceBuf, RT_SRC_POS_DECL, const char *pszMsg, size_t cbMaxMsg);
+RTDECL(int) RTTraceBufAddPosMsgF( RTTRACEBUF hTraceBuf, RT_SRC_POS_DECL, const char *pszMsgFmt, ...) RT_IPRT_FORMAT_ATTR(5, 6);
+RTDECL(int) RTTraceBufAddPosMsgV( RTTRACEBUF hTraceBuf, RT_SRC_POS_DECL, const char *pszMsgFmt, va_list va) RT_IPRT_FORMAT_ATTR(5, 0);
+
+
+RTDECL(int) RTTraceSetDefaultBuf(RTTRACEBUF hTraceBuf);
+RTDECL(RTTRACEBUF) RTTraceGetDefaultBuf(void);
+
+
+/** @def RTTRACE_BUF
+ * The trace buffer used by the macros.
+ */
+#ifndef RTTRACE_BUF
+# define RTTRACE_BUF NULL
+#endif
+
+/**
+ * Record the current source position.
+ */
+#ifdef RTTRACE_ENABLED
+# define RTTRACE_POS() do { RTTraceBufAddPos(RTTRACE_BUF, RT_SRC_POS); } while (0)
+#else
+# define RTTRACE_POS() do { } while (0)
+#endif
+
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_trace_h */
+
diff --git a/include/iprt/tracelog.h b/include/iprt/tracelog.h
new file mode 100644
index 00000000..61ae41c0
--- /dev/null
+++ b/include/iprt/tracelog.h
@@ -0,0 +1,706 @@
+/** @file
+ * IPRT - Binary trace log API.
+ */
+
+/*
+ * Copyright (C) 2018-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_tracelog_h
+#define IPRT_INCLUDED_tracelog_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/sg.h>
+#include <iprt/types.h>
+
+RT_C_DECLS_BEGIN
+
+
+/** @defgroup grp_tracelog RTTraceLog - Binary trace log API
+ * @ingroup grp_rt
+ * @{
+ */
+
+/**
+ * Trace log item type.
+ */
+typedef enum RTTRACELOGTYPE
+{
+ /** Invalid first value. */
+ RTTRACELOGTYPE_INVALID = 0,
+ /** Boolean item type. */
+ RTTRACELOGTYPE_BOOL,
+ /** Unsigned 8bit integer type. */
+ RTTRACELOGTYPE_UINT8,
+ /** Signed 8bit integer type. */
+ RTTRACELOGTYPE_INT8,
+ /** Unsigned 16bit integer type. */
+ RTTRACELOGTYPE_UINT16,
+ /** Signed 16bit integer type. */
+ RTTRACELOGTYPE_INT16,
+ /** Unsigned 32bit integer type. */
+ RTTRACELOGTYPE_UINT32,
+ /** Signed 32bit integer type. */
+ RTTRACELOGTYPE_INT32,
+ /** Unsigned 64bit integer type. */
+ RTTRACELOGTYPE_UINT64,
+ /** Signed 64bit integer type. */
+ RTTRACELOGTYPE_INT64,
+ /** 32bit floating point type. */
+ RTTRACELOGTYPE_FLOAT32,
+ /** 64bit floating point type. */
+ RTTRACELOGTYPE_FLOAT64,
+ /** Raw binary data type. */
+ RTTRACELOGTYPE_RAWDATA,
+ /** Pointer data type. */
+ RTTRACELOGTYPE_POINTER,
+ /** size_t data type. */
+ RTTRACELOGTYPE_SIZE,
+ /** 32-bit hack. */
+ RTTRACELOGTYPE_32BIT_HACK = 0x7fffffff
+} RTTRACELOGTYPE;
+/** Pointer to a trace log item type. */
+typedef RTTRACELOGTYPE *PRTTRACELOGTYPE;
+/** Pointer to a const trace log item type. */
+typedef const RTTRACELOGTYPE *PCRTTRACELOGTYPE;
+
+
+/**
+ * Trace log event severity.
+ */
+typedef enum RTTRACELOGEVTSEVERITY
+{
+ /** Invalid severity. */
+ RTTRACELOGEVTSEVERITY_INVALID = 0,
+ /** Informational event. */
+ RTTRACELOGEVTSEVERITY_INFO,
+ /** Warning event. */
+ RTTRACELOGEVTSEVERITY_WARNING,
+ /** Error event. */
+ RTTRACELOGEVTSEVERITY_ERROR,
+ /** Fatal event. */
+ RTTRACELOGEVTSEVERITY_FATAL,
+ /** Debug event. */
+ RTTRACELOGEVTSEVERITY_DEBUG,
+ /** 32bit hack.*/
+ RTTRACELOGEVTSEVERITY_32BIT_HACK = 0x7fffffff
+} RTTRACELOGEVTSEVERITY;
+/** Pointer to a event severity class. */
+typedef RTTRACELOGEVTSEVERITY *PRTTRACELOGEVTSEVERITY;
+/** Pointer to a const event severiy class. */
+typedef RTTRACELOGEVTSEVERITY *PCRTTRACELOGEVTSEVERITY;
+
+
+/**
+ * Trace log reader event.
+ */
+typedef enum RTTRACELOGRDRPOLLEVT
+{
+ /** Invalid event. */
+ RTTRACELOGRDRPOLLEVT_INVALID = 0,
+ /** The header was received and valid. */
+ RTTRACELOGRDRPOLLEVT_HDR_RECVD,
+ /** Event data was fetched. */
+ RTTRACELOGRDRPOLLEVT_TRACE_EVENT_RECVD,
+ /** 32bit hack. */
+ RTTRACELOGRDRPOLLEVT_32BIT_HACK = 0x7fffffff
+} RTTRACELOGRDRPOLLEVT;
+/** Pointer to a trace log reader event. */
+typedef RTTRACELOGRDRPOLLEVT *PRTTRACELOGRDRPOLLEVT;
+
+
+/**
+ * Trace log event item descriptor.
+ */
+typedef struct RTTRACELOGEVTITEMDESC
+{
+ /** Event item name. */
+ const char *pszName;
+ /** Event item description. */
+ const char *pszDesc;
+ /** Event item type. */
+ RTTRACELOGTYPE enmType;
+ /** The size of the raw data if static for the item,
+ * 0 otherwise (and given when the event is logged).
+ * Only valid for the RTTRACELOGTYPE_RAWDATA type,
+ * ignored otherwise. */
+ size_t cbRawData;
+} RTTRACELOGEVTITEMDESC;
+/** Pointer to an trace log event item descriptor. */
+typedef RTTRACELOGEVTITEMDESC *PRTTRACELOGEVTITEMDESC;
+/** Pointer to a const trace log event item descriptor. */
+typedef const RTTRACELOGEVTITEMDESC *PCRTTRACELOGEVTITEMDESC;
+/** Pointer to a trace log event item descriptor pointer. */
+typedef PRTTRACELOGEVTITEMDESC *PPRTTRACELOGEVTITEMDESC;
+/** Pointer to a const trace log event item descriptor pointer. */
+typedef PCRTTRACELOGEVTITEMDESC *PPCRTTRACELOGEVTITEMDESC;
+
+
+/**
+ * Trace log event descriptor.
+ */
+typedef struct RTTRACELOGEVTDESC
+{
+ /** Event identifier. */
+ const char *pszId;
+ /** Event description. */
+ const char *pszDesc;
+ /** Severity class of the event. */
+ RTTRACELOGEVTSEVERITY enmSeverity;
+ /** Number of items recorded for an event. */
+ uint32_t cEvtItems;
+ /** Pointer to array of event item descriptors. */
+ PCRTTRACELOGEVTITEMDESC paEvtItemDesc;
+} RTTRACELOGEVTDESC;
+/** Pointer to a trace log event descriptor. */
+typedef RTTRACELOGEVTDESC *PRTTRACELOGEVTDESC;
+/** Pointer to a const trace log event descriptor. */
+typedef const RTTRACELOGEVTDESC *PCRTTRACELOGEVTDESC;
+
+
+/**
+ * Trace log event item value.
+ */
+typedef struct RTTRACELOGEVTVAL
+{
+ /** Pointer to the corresponding event item descriptor. */
+ PCRTTRACELOGEVTITEMDESC pItemDesc;
+ /** Value union. */
+ union
+ {
+ bool f;
+ uint8_t u8;
+ int8_t i8;
+ uint16_t u16;
+ int16_t i16;
+ uint32_t u32;
+ int32_t i32;
+ uint64_t u64;
+ int64_t i64;
+ uint64_t sz;
+ uint64_t uPtr;
+ float f32;
+ double f64;
+ struct
+ {
+ size_t cb;
+ const uint8_t *pb;
+ } RawData;
+ } u;
+} RTTRACELOGEVTVAL;
+/** Pointer to trace log event item value. */
+typedef RTTRACELOGEVTVAL *PRTTRACELOGEVTVAL;
+/** Pointer to a const trace log event item value. */
+typedef const RTTRACELOGEVTVAL *PCRTTRACELOGEVTVAL;
+
+
+/**
+ * Item mapping descriptor.
+ */
+typedef struct RTTRACELOGRDRMAPITEM
+{
+ /** The item name. */
+ const char *pszName;
+ /** The value type to map the item to. */
+ RTTRACELOGTYPE enmType;
+} RTTRACELOGRDRMAPITEM;
+/** Pointer to a mapping item descriptor. */
+typedef RTTRACELOGRDRMAPITEM *PRTTRACELOGRDRMAPITEM;
+/** Pointer to a const mapping item descriptor. */
+typedef const RTTRACELOGRDRMAPITEM *PCRTTRACELOGRDRMAPITEM;
+
+
+/**
+ * Event item to value mapping descriptor for RTTraceLogRdrEvtMapToStruct().
+ */
+typedef struct RTTRACELOGRDRMAPDESC
+{
+ /** The event ID this mapping describes. */
+ const char *pszEvtId;
+ /** Number of event items to extract. */
+ uint32_t cEvtItems;
+ /** Pointer to the event items to extract (in the given order). */
+ PCRTTRACELOGRDRMAPITEM paMapItems;
+} RTTRACELOGRDRMAPDESC;
+/** Pointer to a event mapping descriptor. */
+typedef RTTRACELOGRDRMAPDESC *PRTTRACELOGRDRMAPDESC;
+/** Pointer to a const event mapping descriptor. */
+typedef const RTTRACELOGRDRMAPDESC *PCRTTRACELOGRDRMAPDESC;
+
+
+/**
+ * Header for an event mapped to a binary.
+ */
+typedef struct RTTRACELOGRDREVTHDR
+{
+ /** The mapping descriptor this event was mapped to. */
+ PCRTTRACELOGRDRMAPDESC pEvtMapDesc;
+ /** The event descriptor as extracted from the event log. */
+ PCRTTRACELOGEVTDESC pEvtDesc;
+ /** Sequence number of the descriptor. */
+ uint64_t idSeqNo;
+ /** The timestamp of the event. */
+ uint64_t tsEvt;
+ /** Pointer to the event data items. */
+ PCRTTRACELOGEVTVAL paEvtItems;
+} RTTRACELOGRDREVTHDR;
+/** Pointer to an event header. */
+typedef RTTRACELOGRDREVTHDR *PRTTRACELOGRDREVTHDR;
+/** Pointer to a const event header. */
+typedef const RTTRACELOGRDREVTHDR *PCRTTRACELOGRDREVTHDR;
+
+
+/** Event group ID. */
+typedef uint64_t RTTRACELOGEVTGRPID;
+/** Pointer to the event group ID. */
+typedef RTTRACELOGEVTGRPID *PRTTRACELOGEVTGRPID;
+/** Trace log event handle. */
+typedef uint64_t RTRACELOGEVT;
+/** Pointer to a trace log event handle. */
+typedef RTRACELOGEVT *PRTRACELOGEVT;
+/** Trace log writer handle. */
+typedef struct RTTRACELOGWRINT *RTTRACELOGWR;
+/** Pointer to a trace log writer handle. */
+typedef RTTRACELOGWR *PRTTRACELOGWR;
+/** NIL trace log writer handle value. */
+#define NIL_RTTRACELOGWR ((RTTRACELOGWR)0)
+/** Trace log reader handle. */
+typedef struct RTTRACELOGRDRINT *RTTRACELOGRDR;
+/** Pointer to a trace log reader handle. */
+typedef RTTRACELOGRDR *PRTTRACELOGRDR;
+/** NIL trace log reader handle value. */
+#define NIL_RTTRACELOGRDR ((RTTRACELOGRDR)0)
+/** Trace log reader iterator handle. */
+typedef struct RTTRACELOGRDRITINT *RTTRACELOGRDRIT;
+/** Pointer to a trace log reader iterator handle. */
+typedef RTTRACELOGRDRIT *PRTTRACELOGRDRIT;
+/** NIL trace log reader iterator handle. */
+#define NIL_RTTRACELOGRDRIT ((RTTRACELOGRDRIT)0)
+/** Trace log reader event handle. */
+typedef struct RTTRACELOGRDREVTINT *RTTRACELOGRDREVT;
+/** Pointer to a trace log reader event handle. */
+typedef RTTRACELOGRDREVT *PRTTRACELOGRDREVT;
+/** NIL trace log reader event handle. */
+#define NIL_RTTRACELOGRDREVT ((RTTRACELOGRDREVT)0)
+
+/** A new grouped event is started. */
+#define RTTRACELOG_WR_ADD_EVT_F_GRP_START RT_BIT_32(0)
+/** A grouped event is finished. */
+#define RTTRACELOG_WR_ADD_EVT_F_GRP_FINISH RT_BIT_32(1)
+
+/**
+ * Callback to stream out data from the trace log writer.
+ *
+ * @returns IPRT status code.
+ * @param pvUser Opaque user data passed on trace log writer creation.
+ * @param pvBuf Pointer to the buffer to stream out.
+ * @param cbBuf Number of bytes to stream.
+ * @param pcbWritten Where to store the number of bytes written on success, optional.
+ */
+typedef DECLCALLBACKTYPE(int, FNRTTRACELOGWRSTREAM,(void *pvUser, const void *pvBuf, size_t cbBuf, size_t *pcbWritten));
+/** Pointer to a writer stream callback. */
+typedef FNRTTRACELOGWRSTREAM *PFNRTTRACELOGWRSTREAM;
+
+
+/**
+ * Callback to stream int data to the trace log reader.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_EOF if the stream reached the end.
+ * @retval VERR_INTERRUPTED if waiting for something to arrive was interrupted.
+ * @retval VERR_TIMEOUT if the timeout was reached.
+ * @param pvUser Opaque user data passed on trace log reader creation.
+ * @param pvBuf Where to store the read data.
+ * @param cbBuf Number of bytes the buffer can hold.
+ * @param pcbRead Where to store the number of bytes read on success.
+ * @param cMsTimeout How long to wait for something to arrive
+ */
+typedef DECLCALLBACKTYPE(int, FNRTTRACELOGRDRSTREAM,(void *pvUser, void *pvBuf, size_t cbBuf, size_t *pcbRead,
+ RTMSINTERVAL cMsTimeout));
+/** Pointer to a writer stream callback. */
+typedef FNRTTRACELOGRDRSTREAM *PFNRTTRACELOGRDRSTREAM;
+
+
+/**
+ * Callback to close the stream.
+ *
+ * @returns IPRT status code.
+ * @param pvUser Opaque user data passed on trace log writer creation.
+ */
+typedef DECLCALLBACKTYPE(int, FNRTTRACELOGSTREAMCLOSE,(void *pvUser));
+/** Pointer to a stream close callback. */
+typedef FNRTTRACELOGSTREAMCLOSE *PFNRTTRACELOGSTREAMCLOSE;
+
+
+/**
+ * Creates a new trace log writer.
+ *
+ * @returns IPRT status code.
+ * @param phTraceLogWr Where to store the handle to the trace log writer on success.
+ * @param pszDesc Optional description to store in the header.
+ * @param pfnStreamOut The callback to use for streaming the trace log data.
+ * @param pfnStreamClose The callback to use for closing the stream.
+ * @param pvUser Opaque user data to pass to the streaming callback.
+ */
+RTDECL(int) RTTraceLogWrCreate(PRTTRACELOGWR phTraceLogWr, const char *pszDesc,
+ PFNRTTRACELOGWRSTREAM pfnStreamOut,
+ PFNRTTRACELOGSTREAMCLOSE pfnStreamClose, void *pvUser);
+
+
+/**
+ * Creates a new trace log writer streaming data to the given file.
+ *
+ * @returns IPRT status code.
+ * @param phTraceLogWr Where to store the handle to the trace log writer on success.
+ * @param pszDesc Optional description to store in the header.
+ * @param pszFilename The filename to stream the data to.
+ */
+RTDECL(int) RTTraceLogWrCreateFile(PRTTRACELOGWR phTraceLogWr, const char *pszDesc,
+ const char *pszFilename);
+
+
+/**
+ * Creates a new TCP server style trace log writer waiting for the other end to connect to it.
+ *
+ * @returns IPRT status code.
+ * @param phTraceLogWr Where to store the handle to the trace log writer on success.
+ * @param pszDesc Optional description to store in the header.
+ * @param pszListen The address to listen on, NULL to listen on all interfaces.
+ * @param uPort The port to listen on.
+ *
+ * @note The writer will block here until a client has connected.
+ */
+RTDECL(int) RTTraceLogWrCreateTcpServer(PRTTRACELOGWR phTraceLogWr, const char *pszDesc,
+ const char *pszListen, unsigned uPort);
+
+
+/**
+ * Creates a new TCP client style trace log writer connecting to the other end.
+ *
+ * @returns IPRT status code.
+ * @param phTraceLogWr Where to store the handle to the trace log writer on success.
+ * @param pszDesc Optional description to store in the header.
+ * @param pszAddress The address to connect to.
+ * @param uPort The port to connect to.
+ *
+ * @note An error is returned if no connection can be established.
+ */
+RTDECL(int) RTTraceLogWrCreateTcpClient(PRTTRACELOGWR phTraceLogWr, const char *pszDesc,
+ const char *pszAddress, unsigned uPort);
+
+
+/**
+ * Destroys the given trace log writer instance.
+ *
+ * @returns IPRT status code.
+ * @param hTraceLogWr The trace log writer instance handle.
+ */
+RTDECL(int) RTTraceLogWrDestroy(RTTRACELOGWR hTraceLogWr);
+
+
+/**
+ * Adds a given event structure descriptor to the given trace log writer instance
+ * (for prepopulation).
+ *
+ * @returns IPRT status code.
+ * @param hTraceLogWr The trace log writer instance handle.
+ * @param pEvtDesc The event structure descriptor to add.
+ *
+ * @note The event descriptor is keyed by the pointer for faster lookup in subsequent calls,
+ * so don't free after this method finishes.
+ */
+RTDECL(int) RTTraceLogWrAddEvtDesc(RTTRACELOGWR hTraceLogWr, PCRTTRACELOGEVTDESC pEvtDesc);
+
+
+/**
+ * Adds a new event to the trace log.
+ *
+ * @returns IPRT status code.
+ * @param hTraceLogWr The trace log writer instance handle.
+ * @param pEvtDesc The event descriptor to use for formatting.
+ * @param fFlags Flags to use for this event.y
+ * @param uGrpId A unique group ID for grouped events.
+ * @param uParentGrpId A parent group ID this event originated from.
+ * @param pvEvtData Pointer to the raw event data.
+ * @param pacbRawData Pointer to the array of size indicators for non static raw data in the event data stream.
+ *
+ * @note The event descriptor is keyed by the pointer for faster lookup in subsequent calls,
+ * so don't free after this method finishes.
+ */
+RTDECL(int) RTTraceLogWrEvtAdd(RTTRACELOGWR hTraceLogWr, PCRTTRACELOGEVTDESC pEvtDesc, uint32_t fFlags,
+ RTTRACELOGEVTGRPID uGrpId, RTTRACELOGEVTGRPID uParentGrpId,
+ const void *pvEvtData, size_t *pacbRawData);
+
+
+/**
+ * Adds a new event to the trace log.
+ *
+ * @returns IPRT status code.
+ * @param hTraceLogWr The trace log writer instance handle.
+ * @param pEvtDesc The event descriptor used for formatting the data.
+ * @param fFlags Flags to use for this event.
+ * @param uGrpId A unique group ID for grouped events.
+ * @param uParentGrpId A parent group ID this event originated from.
+ * @param pSgBufEvtData S/G buffer holding the raw event data.
+ * @param pacbRawData Pointer to the array of size indicators for non static raw data in the event data stream.
+ *
+ * @note The event descriptor is keyed by the pointer for faster lookup in subsequent calls,
+ * so don't free after this method finishes.
+ */
+RTDECL(int) RTTraceLogWrEvtAddSg(RTTRACELOGWR hTraceLogWr, PCRTTRACELOGEVTDESC pEvtDesc, uint32_t fFlags,
+ RTTRACELOGEVTGRPID uGrpId, RTTRACELOGEVTGRPID uParentGrpId,
+ PRTSGBUF *pSgBufEvtData, size_t *pacbRawData);
+
+
+/**
+ * Adds a new event to the trace log - list variant.
+ *
+ * @returns IPRT status code.
+ * @param hTraceLogWr The trace log writer instance handle.
+ * @param pEvtDesc The event descriptor used for formatting the data.
+ * @param fFlags Flags to use for this event.
+ * @param uGrpId A unique group ID for grouped events.
+ * @param uParentGrpId A parent group ID this event originated from.
+ * @param va The event data as single items as described by the descriptor.
+ *
+ * @note The event descriptor is keyed by the pointer for faster lookup in subsequent calls,
+ * so don't free after this method finishes.
+ */
+RTDECL(int) RTTraceLogWrEvtAddLV(RTTRACELOGWR hTraceLogWr, PCRTTRACELOGEVTDESC pEvtDesc, uint32_t fFlags,
+ RTTRACELOGEVTGRPID uGrpId, RTTRACELOGEVTGRPID uParentGrpId, va_list va);
+
+
+/**
+ * Adds a new event to the trace log - list variant.
+ *
+ * @returns IPRT status code.
+ * @param hTraceLogWr The trace log writer instance handle.
+ * @param pEvtDesc The event descriptor used for formatting the data.
+ * @param fFlags Flags to use for this event.
+ * @param uGrpId A unique group ID for grouped events.
+ * @param uParentGrpId A parent group ID this event originated from.
+ * @param ... The event data as single items as described by the descriptor.
+ *
+ * @note The event descriptor is keyed by the pointer for faster lookup in subsequent calls,
+ * so don't free after this method finishes.
+ */
+RTDECL(int) RTTraceLogWrEvtAddL(RTTRACELOGWR hTraceLogWr, PCRTTRACELOGEVTDESC pEvtDesc, uint32_t fFlags,
+ RTTRACELOGEVTGRPID uGrpId, RTTRACELOGEVTGRPID uParentGrpId, ...);
+
+
+/**
+ * Creates a new trace log reader instance.
+ *
+ * @returns IPRT status code.
+ * @param phTraceLogRdr Where to store the handle to the trace log reader instance on success.
+ * @param pfnStreamIn Callback to stream the data into the reader.
+ * @param pfnStreamClose The callback to use for closing the stream.
+ * @param pvUser Opaque user data passed to the stream callback.
+ */
+RTDECL(int) RTTraceLogRdrCreate(PRTTRACELOGRDR phTraceLogRdr, PFNRTTRACELOGRDRSTREAM pfnStreamIn,
+ PFNRTTRACELOGSTREAMCLOSE pfnStreamClose, void *pvUser);
+
+
+/**
+ * Creates a new trace log reader for the given file.
+ *
+ * @returns IPRT status code.
+ * @param phTraceLogRdr Where to store the handle to the trace log reader instance on success.
+ * @param pszFilename The file to read the trace log data from.
+ */
+RTDECL(int) RTTraceLogRdrCreateFromFile(PRTTRACELOGRDR phTraceLogRdr, const char *pszFilename);
+
+
+/**
+ * Destroys the given trace log reader instance.
+ *
+ * @returns IPRT status code.
+ * @param hTraceLogRdr The trace log reader instance handle.
+ */
+RTDECL(int) RTTraceLogRdrDestroy(RTTRACELOGRDR hTraceLogRdr);
+
+
+/**
+ * Polls for an event on the trace log reader instance.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_TIMEOUT if the timeout was reached.
+ * @retval VERR_INTERRUPTED if the poll was interrupted.
+ * @param hTraceLogRdr The trace log reader instance handle.
+ * @param penmEvt Where to store the event identifier.
+ * @param cMsTimeout How long to poll for an event.
+ */
+RTDECL(int) RTTraceLogRdrEvtPoll(RTTRACELOGRDR hTraceLogRdr, RTTRACELOGRDRPOLLEVT *penmEvt, RTMSINTERVAL cMsTimeout);
+
+/**
+ * Queries the last received event from the trace log read instance.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_NOT_FOUND if no event was received so far.
+ * @param hTraceLogRdr The trace log reader instance handle.
+ * @param phRdrEvt Where to store the event handle on success.
+ */
+RTDECL(int) RTTraceLogRdrQueryLastEvt(RTTRACELOGRDR hTraceLogRdr, PRTTRACELOGRDREVT phRdrEvt);
+
+/**
+ * Queries a new iterator for walking received events.
+ *
+ * @returns IPRT status code
+ * @param hTraceLogRdr The trace log reader instance handle.
+ * @param phIt Where to store the handle to iterator on success.
+ */
+RTDECL(int) RTTraceLogRdrQueryIterator(RTTRACELOGRDR hTraceLogRdr, PRTTRACELOGRDRIT phIt);
+
+
+/**
+ * Extracts the given number of events from the given trace log reader instance returning
+ * and array of events with the values filled in from the mapping descriptor.
+ *
+ * @returns IPRT status code.
+ * @param hTraceLogRdr The trace log reader instance handle.
+ * @param fFlags Flags controlling the behavior, MBZ.
+ * @param cEvts Number of events to extract, UINT32_MAX to map all immediately available events.
+ * @param paMapDesc Pointer to an array of mapping descriptors describing how to map events.
+ * @param ppaEvtHdr Where to return the pointer to the allocated array of event headers on success.
+ * @param pcEvts Where to store the returned number of events on success.
+ */
+RTDECL(int) RTTraceLogRdrEvtMapToStruct(RTTRACELOGRDR hTraceLogRdr, uint32_t fFlags, uint32_t cEvts,
+ PCRTTRACELOGRDRMAPDESC paMapDesc, PCRTTRACELOGRDREVTHDR *ppaEvtHdr,
+ uint32_t *pcEvts);
+
+
+/**
+ * Frees all resources of the given array of event headers as allocated by RTTraceLogRdrEvtMapToStruct().
+ *
+ * @returns nothing.
+ * @param paEvtHdr Pointer to the array of events as returned by RTTraceLogRdrEvtMapToStruct().
+ * @param cEvts Number of events as returned by RTTraceLogRdrEvtMapToStruct().
+ */
+RTDECL(void) RTTraceLogRdrEvtMapFree(PCRTTRACELOGRDREVTHDR paEvtHdr, uint32_t cEvts);
+
+
+/**
+ * Frees a previously created iterator.
+ *
+ * @returns nothing.
+ * @param hIt The iterator handle to free.
+ */
+RTDECL(void) RTTraceLogRdrIteratorFree(RTTRACELOGRDRIT hIt);
+
+
+/**
+ * Advances to the next event.
+ *
+ * @returns IPRT status code
+ * @retval VERR_TRACELOG_READER_ITERATOR_END if the iterator reached the end.
+ * @param hIt The iterator handle.
+ */
+RTDECL(int) RTTraceLogRdrIteratorNext(RTTRACELOGRDRIT hIt);
+
+
+/**
+ * Queries the event at the current iterator position.
+ *
+ * @returns IPRT status code.
+ * @param hIt The iterator handle.
+ * @param phRdrEvt Where to store the event handle on success.
+ */
+RTDECL(int) RTTraceLogRdrIteratorQueryEvent(RTTRACELOGRDRIT hIt, PRTTRACELOGRDREVT phRdrEvt);
+
+
+/**
+ * Returns the sequence number of the given event.
+ *
+ * @returns Sequence number of the given event.
+ * @param hRdrEvt The reader event handle.
+ */
+RTDECL(uint64_t) RTTraceLogRdrEvtGetSeqNo(RTTRACELOGRDREVT hRdrEvt);
+
+
+/**
+ * Gets the timestamp of the given event.
+ *
+ * @returns Timestamp of the given event.
+ * @param hRdrEvt The reader event handle.
+ */
+RTDECL(uint64_t) RTTraceLogRdrEvtGetTs(RTTRACELOGRDREVT hRdrEvt);
+
+
+/**
+ * Returns whether the given event is part of an event group.
+ *
+ * @returns Flag whether the event is part of a group.
+ * @param hRdrEvt The reader event handle.
+ */
+RTDECL(bool) RTTraceLogRdrEvtIsGrouped(RTTRACELOGRDREVT hRdrEvt);
+
+
+/**
+ * Returns the event descriptor associated with the given event.
+ *
+ * @returns The trace log event descriptor associated with this event.
+ * @param hRdrEvt The reader event handle.
+ */
+RTDECL(PCRTTRACELOGEVTDESC) RTTraceLogRdrEvtGetDesc(RTTRACELOGRDREVT hRdrEvt);
+
+
+/**
+ * Queries an event item by its name returning the value in the supplied buffer.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_NOT_FOUND if the item name was not found for the given event.
+ * @param hRdrEvt The reader event handle.
+ * @param pszName The item name to query.
+ * @param pVal The item value buffer to initialise.
+ */
+RTDECL(int) RTTraceLogRdrEvtQueryVal(RTTRACELOGRDREVT hRdrEvt, const char *pszName, PRTTRACELOGEVTVAL pVal);
+
+
+/**
+ * Fills the given value array using the values from the given event.
+ *
+ * @returns IPRT status code
+ * @param hRdrEvt The reader event handle.
+ * @param idxItemStart The index of the item to start filling the value in.
+ * @param paVals Array of values to fill.
+ * @param cVals Number of values the array is able to hold.
+ * @param pcVals Where to store the number of values filled on success.
+ */
+RTDECL(int) RTTraceLogRdrEvtFillVals(RTTRACELOGRDREVT hRdrEvt, unsigned idxItemStart, PRTTRACELOGEVTVAL paVals,
+ unsigned cVals, unsigned *pcVals);
+
+RT_C_DECLS_END
+
+/** @} */
+
+#endif /* !IPRT_INCLUDED_tracelog_h */
+
diff --git a/include/iprt/types.h b/include/iprt/types.h
new file mode 100644
index 00000000..366c19a6
--- /dev/null
+++ b/include/iprt/types.h
@@ -0,0 +1,3890 @@
+/** @file
+ * IPRT - Types.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_types_h
+#define IPRT_INCLUDED_types_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cdefs.h>
+#include <iprt/stdint.h>
+#include <iprt/stdarg.h>
+
+/*
+ * Include standard C types.
+ */
+#if !defined(IPRT_NO_CRT) && !defined(DOXYGEN_RUNNING)
+
+# 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)
+# include <sys/param.h>
+# undef PVM
+# if __FreeBSD_version < 1200000
+ /*
+ * 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
+# else
+# include <sys/stddef.h>
+# include <sys/types.h>
+# 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.
+ */
+# 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
+
+# elif !defined(DOXYGEN_RUNNING) && RT_MSC_PREREQ(RT_MSC_VER_VC140) && defined(RT_OS_AGNOSTIC)
+ /* Try avoid needing the UCRT just for stddef.h and sys/types.h. */
+ /** @todo refine the RT_OS_AGNOSTIC test? */
+# include <vcruntime.h>
+
+# else
+# include <stddef.h>
+# include <sys/types.h>
+# endif
+
+
+/* Define any types missing from sys/types.h on Windows and OS/2. */
+# ifdef _MSC_VER
+# undef ssize_t
+typedef intptr_t ssize_t;
+# endif
+# if defined(RT_OS_OS2) && (defined(__IBMC__) || defined(__IBMCPP__))
+typedef signed long 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
+# undef bool /* see above netbsd explanation */
+typedef _Bool bool;
+# endif
+# else
+# if RT_MSC_PREREQ(RT_MSC_VER_VC120)
+# include <stdbool.h>
+# else
+typedef unsigned char bool;
+# endif
+# endif
+# ifndef true
+# define true (1)
+# endif
+# ifndef false
+# define false (0)
+# endif
+#endif
+
+
+/**
+ * 128-bit unsigned integer.
+ */
+#ifdef RT_COMPILER_WITH_128BIT_INT_TYPES
+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.
+ */
+#ifdef RT_COMPILER_WITH_128BIT_INT_TYPES
+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 hi/lo view. */
+ struct
+ {
+#ifdef RT_BIG_ENDIAN
+ uint8_t Hi;
+ uint8_t Lo;
+#else
+ uint8_t Lo;
+ uint8_t Hi;
+#endif
+ } s;
+
+ /** Unsigned 16-bit view. */
+ uint16_t au16[1];
+ /** Unsigned 8-bit view. */
+ uint8_t au8[2];
+
+ /** Signed 16-bit view. */
+ int16_t ai16[1];
+ /** Signed 8-bit view. */
+ int8_t ai8[2];
+} RTUINT16U;
+/** Pointer to a 16-bit unsigned integer union. */
+typedef RTUINT16U RT_FAR *PRTUINT16U;
+/** Pointer to a const 32-bit unsigned integer union. */
+typedef const RTUINT16U RT_FAR *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;
+
+ /** Unsigned 32-bit view. */
+ uint32_t au32[1];
+ /** Unsigned 16-bit view. */
+ uint16_t au16[2];
+ /** Unsigned 8-bit view. */
+ uint8_t au8[4];
+
+ /** Signed 32-bit view. */
+ int32_t ai32[1];
+ /** Signed 16-bit view. */
+ int16_t ai16[2];
+ /** Signed 8-bit view. */
+ int8_t ai8[4];
+} RTUINT32U;
+/** Pointer to a 32-bit unsigned integer union. */
+typedef RTUINT32U RT_FAR *PRTUINT32U;
+/** Pointer to a const 32-bit unsigned integer union. */
+typedef const RTUINT32U RT_FAR *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;
+
+ /** Unsigned 64-bit view. */
+ uint64_t au64[1];
+ /** Unsigned 32-bit view. */
+ uint32_t au32[2];
+ /** Unsigned 16-bit view. */
+ uint16_t au16[4];
+ /** Unsigned 8-bit view. */
+ uint8_t au8[8];
+
+ /** Signed 64-bit view. */
+ int64_t ai64[1];
+ /** Signed 32-bit view. */
+ int32_t ai32[2];
+ /** Signed 16-bit view. */
+ int16_t ai16[4];
+ /** Signed 8-bit view. */
+ int8_t ai8[8];
+} RTUINT64U;
+/** Pointer to a 64-bit unsigned integer union. */
+typedef RTUINT64U RT_FAR *PRTUINT64U;
+/** Pointer to a const 64-bit unsigned integer union. */
+typedef const RTUINT64U RT_FAR *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;
+
+ /** Unsigned 64-bit view. */
+ uint64_t au64[2];
+ /** Unsigned 32-bit view. */
+ uint32_t au32[4];
+ /** Unsigned 16-bit view. */
+ uint16_t au16[8];
+ /** Unsigned 8-bit view. */
+ uint8_t au8[16];
+
+ /** Signed 64-bit view. */
+ int64_t ai64[2];
+ /** Signed 32-bit view. */
+ int32_t ai32[4];
+ /** Signed 16-bit view. */
+ int16_t ai16[8];
+ /** Signed 8-bit view. */
+ int8_t ai8[16];
+} RTUINT128U;
+#pragma pack()
+/** Pointer to a 128-bit unsigned integer union. */
+typedef RTUINT128U RT_FAR *PRTUINT128U;
+/** Pointer to a const 128-bit unsigned integer union. */
+typedef const RTUINT128U RT_FAR *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;
+
+ /** Unsigned 128-bit view. */
+ RTUINT128U au128[2];
+ /** Unsigned 64-bit view. */
+ uint64_t au64[4];
+ /** Unsigned 32-bit view. */
+ uint32_t au32[8];
+ /** Unsigned 16-bit view. */
+ uint16_t au16[16];
+ /** Unsigned 8-bit view. */
+ uint8_t au8[32];
+
+ /** Signed 64-bit view. */
+ int64_t ai64[4];
+ /** Signed 32-bit view. */
+ int32_t ai32[8];
+ /** Signed 16-bit view. */
+ int16_t ai16[16];
+ /** Signed 8-bit view. */
+ int8_t ai8[32];
+} RTUINT256U;
+#pragma pack()
+/** Pointer to a 256-bit unsigned integer union. */
+typedef RTUINT256U RT_FAR *PRTUINT256U;
+/** Pointer to a const 256-bit unsigned integer union. */
+typedef const RTUINT256U RT_FAR *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 RT_FAR *PRTUINT512U;
+/** Pointer to a const 512-bit unsigned integer union. */
+typedef const RTUINT512U RT_FAR *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))
+
+
+/**
+ * Single precision floating point format (32-bit).
+ */
+typedef union RTFLOAT32U
+{
+ /** Format using regular bitfields. */
+ struct
+ {
+# ifdef RT_BIG_ENDIAN
+ /** The sign indicator. */
+ uint32_t fSign : 1;
+ /** The exponent (offsetted by 127). */
+ uint32_t uExponent : 8;
+ /** The fraction. */
+ uint32_t uFraction : 23;
+# else
+ /** The fraction. */
+ uint32_t uFraction : 23;
+ /** The exponent (offsetted by 127). */
+ uint32_t uExponent : 8;
+ /** The sign indicator. */
+ uint32_t fSign : 1;
+# endif
+ } s;
+
+#if 1 /** @todo exclude targets which doesn't have a 64-bit double type. (currently none) */
+ /** Double view. */
+ float r;
+#endif
+ /** Unsigned integer view. */
+ uint32_t u;
+ /** 32-bit view. */
+ uint32_t au32[1];
+ /** 16-bit view. */
+ uint16_t au16[2];
+ /** 8-bit view. */
+ uint8_t au8[4];
+} RTFLOAT32U;
+/** Pointer to a single precision floating point format union. */
+typedef RTFLOAT32U RT_FAR *PRTFLOAT32U;
+/** Pointer to a const single precision floating point format union. */
+typedef const RTFLOAT32U RT_FAR *PCRTFLOAT32U;
+/** RTFLOAT32U initializer. */
+#ifdef RT_BIG_ENDIAN
+# define RTFLOAT32U_INIT(a_fSign, a_uFraction, a_uExponent) { { (a_fSign), (a_uExponent), (a_uFraction) } }
+#else
+# define RTFLOAT32U_INIT(a_fSign, a_uFraction, a_uExponent) { { (a_uFraction), (a_uExponent), (a_fSign) } }
+#endif
+#define RTFLOAT32U_INIT_C(a_fSign, a_uFraction, a_uExponent) RTFLOAT32U_INIT((a_fSign), UINT32_C(a_uFraction), (a_uExponent))
+#define RTFLOAT32U_INIT_ZERO(a_fSign) RTFLOAT32U_INIT((a_fSign), 0, 0)
+#define RTFLOAT32U_INIT_INF(a_fSign) RTFLOAT32U_INIT((a_fSign), 0, RTFLOAT32U_EXP_MAX)
+#define RTFLOAT32U_INIT_SNAN(a_fSign) RTFLOAT32U_INIT((a_fSign), 1, RTFLOAT32U_EXP_MAX)
+#define RTFLOAT32U_INIT_SNAN_EX(a_fSign, a_uVal) RTFLOAT32U_INIT((a_fSign), (a_uVal) ? (a_uVal) : 1, RTFLOAT32U_EXP_MAX)
+#define RTFLOAT32U_INIT_SIGNALLING_NAN(a_fSign) RTFLOAT32U_INIT_SNAN(a_fSign)
+#define RTFLOAT32U_INIT_QNAN(a_fSign) RTFLOAT32U_INIT((a_fSign), RT_BIT_32(RTFLOAT32U_FRACTION_BITS - 1), RTFLOAT32U_EXP_MAX)
+#define RTFLOAT32U_INIT_QNAN_EX(a_fSign, a_uVal) RTFLOAT32U_INIT((a_fSign), RT_BIT_32(RTFLOAT32U_FRACTION_BITS - 1) | (a_uVal), RTFLOAT32U_EXP_MAX)
+#define RTFLOAT32U_INIT_QUIET_NAN(a_fSign) RTFLOAT32U_INIT_QNAN(a_fSign)
+#define RTFLOAT32U_INIT_NAN_EX(a_fQuiet, a_fSign, a_uVal) \
+ RTFLOAT32U_INIT((a_fSign), \
+ ((a_uVal) || (a_fQuiet) ? (a_uVal) : 1) | ((a_fQuiet) ? RT_BIT_32(RTFLOAT32U_FRACTION_BITS - 1) : 0), \
+ RTFLOAT32U_EXP_MAX)
+
+/** The exponent bias for the RTFLOAT32U format. */
+#define RTFLOAT32U_EXP_BIAS (127)
+/** The max exponent value for the RTFLOAT32U format. */
+#define RTFLOAT32U_EXP_MAX (255)
+/** The exponent bias overflow/underflow adjust for the RTFLOAT32U format.
+ * @note 754-1985 sec 7.3 & 7.4, not mentioned in later standard versions. */
+#define RTFLOAT32U_EXP_BIAS_ADJUST (192)
+/** Fraction width (in bits) for the RTFLOAT32U format. */
+#define RTFLOAT32U_FRACTION_BITS (23)
+/** Check if two 32-bit floating values are identical (memcmp, not
+ * numerically). */
+#define RTFLOAT32U_ARE_IDENTICAL(a_pLeft, a_pRight) ((a_pLeft)->u == (a_pRight)->u)
+/** @name RTFLOAT32U classification macros
+ * @{ */
+#define RTFLOAT32U_IS_ZERO(a_pr32) (((a_pr32)->u & (RT_BIT_32(31) - 1)) == 0)
+#define RTFLOAT32U_IS_SUBNORMAL(a_pr32) ((a_pr32)->s.uExponent == 0 && (a_pr32)->s.uFraction != 0)
+#define RTFLOAT32U_IS_INF(a_pr32) ((a_pr32)->s.uExponent == 0xff && (a_pr32)->s.uFraction == 0)
+#define RTFLOAT32U_IS_SIGNALLING_NAN(a_pr32) ((a_pr32)->s.uExponent == 0xff && !((a_pr32)->s.uFraction & RT_BIT_32(22)) \
+ && (a_pr32)->s.uFraction != 0)
+#define RTFLOAT32U_IS_QUIET_NAN(a_pr32) ((a_pr32)->s.uExponent == 0xff && ((a_pr32)->s.uFraction & RT_BIT_32(22)))
+#define RTFLOAT32U_IS_NAN(a_pr32) ((a_pr32)->s.uExponent == 0xff && (a_pr32)->s.uFraction != 0)
+#define RTFLOAT32U_IS_NORMAL(a_pr32) ((a_pr32)->s.uExponent > 0 && (a_pr32)->s.uExponent < 0xff)
+/** @} */
+
+
+/**
+ * Double precision floating point format (64-bit).
+ */
+typedef union RTFLOAT64U
+{
+ /** Format using regular bitfields. */
+ struct
+ {
+# ifdef RT_BIG_ENDIAN
+ /** The sign indicator. */
+ uint32_t fSign : 1;
+ /** The exponent (offsetted by 1023). */
+ uint32_t uExponent : 11;
+ /** The fraction, bits 32 thru 51. */
+ uint32_t uFractionHigh : 20;
+ /** The fraction, bits 0 thru 31. */
+ uint32_t uFractionLow;
+# else
+ /** The fraction, bits 0 thru 31. */
+ uint32_t uFractionLow;
+ /** The fraction, bits 32 thru 51. */
+ uint32_t uFractionHigh : 20;
+ /** The exponent (offsetted 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 (offsetted 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 (offsetted by 1023). */
+ RT_GCC_EXTENSION uint64_t uExponent : 11;
+ /** The sign indicator. */
+ RT_GCC_EXTENSION uint64_t fSign : 1;
+# endif
+ } s64;
+#endif
+
+#if 1 /** @todo exclude targets which doesn't have a 64-bit double type. (currently none) */
+ /** Double view. */
+ double rd, r;
+#endif
+#ifdef RT_COMPILER_WITH_64BIT_LONG_DOUBLE
+ /** Long double view. */
+ long double lrd;
+#endif
+ /** Unsigned integer view. */
+ uint64_t u;
+ /** 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 RT_FAR *PRTFLOAT64U;
+/** Pointer to a const double precision floating point format union. */
+typedef const RTFLOAT64U RT_FAR *PCRTFLOAT64U;
+/** RTFLOAT64U initializer. */
+#ifdef RT_BIG_ENDIAN
+# define RTFLOAT64U_INIT(a_fSign, a_uFraction, a_uExponent) \
+ { { (a_fSign), (a_uExponent), (uint32_t)((a_uFraction) >> 32), (uint32_t)((a_uFraction) & UINT32_MAX) } }
+#else
+# define RTFLOAT64U_INIT(a_fSign, a_uFraction, a_uExponent) \
+ { { (uint32_t)((a_uFraction) & UINT32_MAX), (uint32_t)((a_uFraction) >> 32), (a_uExponent), (a_fSign) } }
+#endif
+#define RTFLOAT64U_INIT_C(a_fSign, a_uFraction, a_uExponent) RTFLOAT64U_INIT((a_fSign), UINT64_C(a_uFraction), (a_uExponent))
+#define RTFLOAT64U_INIT_ZERO(a_fSign) RTFLOAT64U_INIT((a_fSign), UINT64_C(0), 0)
+#define RTFLOAT64U_INIT_INF(a_fSign) RTFLOAT64U_INIT((a_fSign), UINT64_C(0), RTFLOAT64U_EXP_MAX)
+#define RTFLOAT64U_INIT_SNAN(a_fSign) RTFLOAT64U_INIT((a_fSign), UINT64_C(1), RTFLOAT64U_EXP_MAX)
+#define RTFLOAT64U_INIT_SNAN_EX(a_fSign, a_uVal) RTFLOAT64U_INIT((a_fSign), (a_uVal) ? (a_uVal) : UINT64_C(1), RTFLOAT64U_EXP_MAX)
+#define RTFLOAT64U_INIT_SIGNALLING_NAN(a_fSign) RTFLOAT64U_INIT_SNAN(a_fSign)
+#define RTFLOAT64U_INIT_QNAN(a_fSign) RTFLOAT64U_INIT((a_fSign), RT_BIT_64(RTFLOAT64U_FRACTION_BITS - 1), RTFLOAT64U_EXP_MAX)
+#define RTFLOAT64U_INIT_QNAN_EX(a_fSign, a_uVal) RTFLOAT64U_INIT((a_fSign), RT_BIT_64(RTFLOAT64U_FRACTION_BITS - 1) | (a_uVal), RTFLOAT64U_EXP_MAX)
+#define RTFLOAT64U_INIT_QUIET_NAN(a_fSign) RTFLOAT64U_INIT_QNAN(a_fSign)
+#define RTFLOAT64U_INIT_NAN_EX(a_fQuiet, a_fSign, a_uVal) \
+ RTFLOAT64U_INIT((a_fSign), \
+ ((a_uVal) || (a_fQuiet) ? (a_uVal) : UINT64_C(1)) | ((a_fQuiet) ? RT_BIT_64(RTFLOAT64U_FRACTION_BITS - 1) : UINT64_C(0)), \
+ RTFLOAT64U_EXP_MAX)
+
+/** The exponent bias for the RTFLOAT64U format. */
+#define RTFLOAT64U_EXP_BIAS (1023)
+/** The max exponent value for the RTFLOAT64U format. */
+#define RTFLOAT64U_EXP_MAX (2047)
+/** The exponent bias overflow/underflow adjust for the RTFLOAT64U format.
+ * @note 754-1985 sec 7.3 & 7.4, not mentioned in later standard versions. */
+#define RTFLOAT64U_EXP_BIAS_ADJUST (1536)
+/** Fraction width (in bits) for the RTFLOAT64U format. */
+#define RTFLOAT64U_FRACTION_BITS (52)
+/** Check if two 64-bit floating values are identical (memcmp, not
+ * numerically). */
+#define RTFLOAT64U_ARE_IDENTICAL(a_pLeft, a_pRight) ((a_pLeft)->u == (a_pRight)->u)
+/** @name RTFLOAT64U classification macros
+ * @{ */
+#define RTFLOAT64U_IS_ZERO(a_pr64) (((a_pr64)->u & (RT_BIT_64(63) - 1)) == 0)
+#define RTFLOAT64U_IS_SUBNORMAL(a_pr64) ( (a_pr64)->s.uExponent == 0 \
+ && ((a_pr64)->s.uFractionLow != 0 || (a_pr64)->s.uFractionHigh != 0) )
+#define RTFLOAT64U_IS_INF(a_pr64) ( (a_pr64)->s.uExponent == 0x7ff \
+ && (a_pr64)->s.uFractionLow == 0 && (a_pr64)->s.uFractionHigh == 0)
+#define RTFLOAT64U_IS_SIGNALLING_NAN(a_pr64) ( (a_pr64)->s.uExponent == 0x7ff \
+ && !((a_pr64)->s.uFractionHigh & RT_BIT_32(19)) \
+ && ((a_pr64)->s.uFractionHigh != 0 || (a_pr64)->s.uFractionLow != 0) )
+#define RTFLOAT64U_IS_QUIET_NAN(a_pr64) ((a_pr64)->s.uExponent == 0x7ff && ((a_pr64)->s.uFractionHigh & RT_BIT_32(19)))
+#define RTFLOAT64U_IS_NAN(a_pr64) ( (a_pr64)->s.uExponent == 0x7ff \
+ && ((a_pr64)->s.uFractionHigh != 0 || (a_pr64)->s.uFractionLow != 0) )
+#define RTFLOAT64U_IS_NORMAL(a_pr64) ((a_pr64)->s.uExponent > 0 && (a_pr64)->s.uExponent < 0x7ff)
+/** @} */
+
+
+
+#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 /** @todo big endian mapping is wrong. */
+ /** The sign indicator. */
+ RT_GCC_EXTENSION uint16_t fSign : 1;
+ /** The exponent (offsetted by 16383). */
+ RT_GCC_EXTENSION uint16_t uExponent : 15;
+ /** The mantissa. */
+ uint64_t uMantissa;
+# else
+ /** The mantissa. */
+ uint64_t uMantissa;
+ /** The exponent (offsetted by 16383). */
+ RT_GCC_EXTENSION uint16_t uExponent : 15;
+ /** The sign indicator. */
+ RT_GCC_EXTENSION uint16_t fSign : 1;
+# endif
+ } s;
+
+ /** Format for accessing it as two separate components. */
+ RT_GCC_EXTENSION struct
+ {
+# ifdef RT_BIG_ENDIAN /** @todo big endian mapping is wrong. */
+ /** The sign bit and exponent. */
+ uint16_t uSignAndExponent;
+ /** The mantissa. */
+ uint64_t uMantissa;
+# else
+ /** The mantissa. */
+ uint64_t uMantissa;
+ /** The sign bit and exponent. */
+ uint16_t uSignAndExponent;
+# endif
+ } s2;
+
+# ifdef RT_COMPILER_GROKS_64BIT_BITFIELDS
+ /** 64-bit bitfields exposing the J bit and the fraction. */
+ RT_GCC_EXTENSION struct
+ {
+# ifdef RT_BIG_ENDIAN /** @todo big endian mapping is wrong. */
+ /** The sign indicator. */
+ RT_GCC_EXTENSION uint16_t fSign : 1;
+ /** The exponent (offsetted 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 uFraction : 63;
+# else
+ /** The fraction. */
+ RT_GCC_EXTENSION uint64_t uFraction : 63;
+ /** The J bit, aka the integer bit. */
+ RT_GCC_EXTENSION uint64_t fInteger : 1;
+ /** The exponent (offsetted 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];
+} RTFLOAT80U;
+# pragma pack()
+/** Pointer to a extended precision floating point format union. */
+typedef RTFLOAT80U RT_FAR *PRTFLOAT80U;
+/** Pointer to a const extended precision floating point format union. */
+typedef const RTFLOAT80U RT_FAR *PCRTFLOAT80U;
+/** RTFLOAT80U initializer. */
+# ifdef RT_BIG_ENDIAN
+# define RTFLOAT80U_INIT(a_fSign, a_uMantissa, a_uExponent) { { (a_fSign), (a_uExponent), (a_uMantissa) } }
+# else
+# define RTFLOAT80U_INIT(a_fSign, a_uMantissa, a_uExponent) { { (a_uMantissa), (a_uExponent), (a_fSign) } }
+# endif
+# define RTFLOAT80U_INIT_C(a_fSign, a_uMantissa, a_uExponent) RTFLOAT80U_INIT((a_fSign), UINT64_C(a_uMantissa), (a_uExponent))
+# define RTFLOAT80U_INIT_ZERO(a_fSign) RTFLOAT80U_INIT((a_fSign), 0, 0)
+# define RTFLOAT80U_INIT_INF(a_fSign) RTFLOAT80U_INIT((a_fSign), RT_BIT_64(63), RTFLOAT80U_EXP_MAX)
+# define RTFLOAT80U_INIT_SIGNALLING_NAN(a_fSign) RTFLOAT80U_INIT_SNAN((a_fSign))
+# define RTFLOAT80U_INIT_SNAN(a_fSign) RTFLOAT80U_INIT((a_fSign), RT_BIT_64(63) | 1, RTFLOAT80U_EXP_MAX)
+# define RTFLOAT80U_INIT_SNAN_EX(a_fSign, a_uVal) RTFLOAT80U_INIT((a_fSign), RT_BIT_64(63) | (a_uVal), RTFLOAT80U_EXP_MAX)
+# define RTFLOAT80U_INIT_QUIET_NAN(a_fSign) RTFLOAT80U_INIT_QNAN((a_fSign))
+# define RTFLOAT80U_INIT_QNAN(a_fSign) RTFLOAT80U_INIT((a_fSign), RT_BIT_64(63) | RT_BIT_64(62), RTFLOAT80U_EXP_MAX)
+# define RTFLOAT80U_INIT_QNAN_EX(a_fSign, a_uVal) RTFLOAT80U_INIT((a_fSign), RT_BIT_64(63) | RT_BIT_64(62) | (a_uVal), RTFLOAT80U_EXP_MAX)
+#define RTFLOAT80U_INIT_NAN_EX(a_fQuiet, a_fSign, a_uVal) \
+ RTFLOAT80U_INIT((a_fSign), \
+ ((a_uVal) || (a_fQuiet) ? (a_uVal) : UINT64_C(1)) | ((a_fQuiet) ? RT_BIT_64(63) | RT_BIT_64(62) : RT_BIT_64(63)), \
+ RTFLOAT80U_EXP_MAX)
+# define RTFLOAT80U_INIT_INDEFINITE(a_fSign) RTFLOAT80U_INIT((a_fSign), RT_BIT_64(63) | RT_BIT_64(62), RTFLOAT80U_EXP_MAX)
+# define RTFLOAT80U_INIT_IND(a_fSign) RTFLOAT80U_INIT_INDEFINITE(a_fSign)
+/** The exponent bias for the RTFLOAT80U format. */
+# define RTFLOAT80U_EXP_BIAS (16383)
+/** The max exponent value for the RTFLOAT80U format. */
+# define RTFLOAT80U_EXP_MAX (32767)
+/** The exponent bias overflow/underflow adjust for the RTFLOAT80U format.
+ * @note 754-1985 sec 7.3 & 7.4, not mentioned in later standard versions. */
+# define RTFLOAT80U_EXP_BIAS_ADJUST (24576)
+/** Fraction width (in bits) for the RTFLOAT80U format. */
+# define RTFLOAT80U_FRACTION_BITS (63)
+/** Check if two 80-bit floating values are identical (memcmp, not
+ * numberically). */
+# define RTFLOAT80U_ARE_IDENTICAL(a_pLeft, a_pRight) \
+ ( (a_pLeft)->au64[0] == (a_pRight)->au64[0] \
+ && (a_pLeft)->au16[4] == (a_pRight)->au16[4] )
+/** @name RTFLOAT80U classification macros
+ * @{ */
+/** Is @a a_pr80 +0 or -0. */
+# define RTFLOAT80U_IS_ZERO(a_pr80) RTFLOAT80U_IS_ZERO_EX((a_pr80)->s.uMantissa, (a_pr80)->s.uExponent)
+# define RTFLOAT80U_IS_ZERO_EX(a_uMantissa, a_uExponent) \
+ ((a_uExponent) == 0 && (a_uMantissa) == 0)
+/** Is @a a_pr80 a denormal (does not match psuedo-denormal). */
+# define RTFLOAT80U_IS_DENORMAL(a_pr80) RTFLOAT80U_IS_DENORMAL_EX((a_pr80)->s.uMantissa, (a_pr80)->s.uExponent)
+# define RTFLOAT80U_IS_DENORMAL_EX(a_uMantissa, a_uExponent) \
+ ((a_uExponent) == 0 && (a_uMantissa) < RT_BIT_64(63) && (a_uMantissa) != 0)
+/** Is @a a_pr80 a pseudo-denormal. */
+# define RTFLOAT80U_IS_PSEUDO_DENORMAL(a_pr80) RTFLOAT80U_IS_PSEUDO_DENORMAL_EX((a_pr80)->s.uMantissa, (a_pr80)->s.uExponent)
+# define RTFLOAT80U_IS_PSEUDO_DENORMAL_EX(a_uMantissa, a_uExponent) \
+ ((a_uExponent) == 0 && (a_uMantissa) >= RT_BIT_64(63))
+/** Is @a a_pr80 denormal or pseudo-denormal. */
+# define RTFLOAT80U_IS_DENORMAL_OR_PSEUDO_DENORMAL(a_pr80) \
+ RTFLOAT80U_IS_DENORMAL_OR_PSEUDO_DENORMAL_EX((a_pr80)->s.uMantissa, (a_pr80)->s.uExponent)
+# define RTFLOAT80U_IS_DENORMAL_OR_PSEUDO_DENORMAL_EX(a_uMantissa, a_uExponent) ((a_uExponent) == 0 && (a_uMantissa) != 0)
+/** Is @a a_pr80 +/-pseudo-infinity. */
+# define RTFLOAT80U_IS_PSEUDO_INF(a_pr80) RTFLOAT80U_IS_PSEUDO_INF_EX((a_pr80)->s.uMantissa, (a_pr80)->s.uExponent)
+# define RTFLOAT80U_IS_PSEUDO_INF_EX(a_uMantissa, a_uExponent) ((a_uExponent) == 0x7fff && (a_uMantissa) == 0)
+/** Is @a a_pr80 pseudo-not-a-number. */
+# define RTFLOAT80U_IS_PSEUDO_NAN(a_pr80) RTFLOAT80U_IS_PSEUDO_NAN_EX((a_pr80)->s.uMantissa, (a_pr80)->s.uExponent)
+# define RTFLOAT80U_IS_PSEUDO_NAN_EX(a_uMantissa, a_uExponent) ((a_uExponent) == 0x7fff && !((a_uMantissa) & RT_BIT_64(63)))
+/** Is @a a_pr80 infinity (does not match pseudo-infinity). */
+# define RTFLOAT80U_IS_INF(a_pr80) RTFLOAT80U_IS_INF_EX((a_pr80)->s.uMantissa, (a_pr80)->s.uExponent)
+# define RTFLOAT80U_IS_INF_EX(a_uMantissa, a_uExponent) ((a_uExponent) == 0x7fff && (a_uMantissa) == RT_BIT_64(63))
+/** Is @a a_pr80 a signalling not-a-number value. */
+# define RTFLOAT80U_IS_SIGNALLING_NAN(a_pr80) RTFLOAT80U_IS_SIGNALLING_NAN_EX((a_pr80)->s.uMantissa, (a_pr80)->s.uExponent)
+# define RTFLOAT80U_IS_SIGNALLING_NAN_EX(a_uMantissa, a_uExponent) \
+ ( (a_uExponent) == 0x7fff \
+ && ((a_uMantissa) & (RT_BIT_64(63) | RT_BIT_64(62))) == RT_BIT_64(63) \
+ && ((a_uMantissa) & (RT_BIT_64(62) - 1)) != 0)
+/** Is @a a_pr80 a quiet not-a-number value. */
+# define RTFLOAT80U_IS_QUIET_NAN(a_pr80) RTFLOAT80U_IS_QUIET_NAN_EX((a_pr80)->s.uMantissa, (a_pr80)->s.uExponent)
+# define RTFLOAT80U_IS_QUIET_NAN_EX(a_uMantissa, a_uExponent) \
+ ( (a_uExponent) == 0x7fff \
+ && ((a_uMantissa) & (RT_BIT_64(63) | RT_BIT_64(62))) == (RT_BIT_64(63) | RT_BIT_64(62)) \
+ && ((a_uMantissa) & (RT_BIT_64(62) - 1)) != 0)
+/** Is @a a_pr80 Signalling-, Quiet- or Pseudo-NaN. */
+# define RTFLOAT80U_IS_NAN(a_pr80) RTFLOAT80U_IS_NAN_EX((a_pr80)->s.uMantissa, (a_pr80)->s.uExponent)
+# define RTFLOAT80U_IS_NAN_EX(a_uMantissa, a_uExponent) ((a_uExponent) == 0x7fff && ((a_uMantissa) & (RT_BIT_64(63) - 1)) != 0)
+/** Is @a a_pr80 Signalling- or Quiet-Nan, but not Pseudo-NaN. */
+# define RTFLOAT80U_IS_QUIET_OR_SIGNALLING_NAN(a_pr80) \
+ RTFLOAT80U_IS_QUIET_OR_SIGNALLING_NAN_EX((a_pr80)->s.uMantissa, (a_pr80)->s.uExponent)
+# define RTFLOAT80U_IS_QUIET_OR_SIGNALLING_NAN_EX(a_uMantissa, a_uExponent) \
+ ((a_uExponent) == 0x7fff && ((a_uMantissa) > RT_BIT_64(63)))
+/** Is @a a_pr80 indefinite (ignoring sign). */
+# define RTFLOAT80U_IS_INDEFINITE(a_pr80) RTFLOAT80U_IS_INDEFINITE_EX((a_pr80)->s.uMantissa, (a_pr80)->s.uExponent)
+# define RTFLOAT80U_IS_INDEFINITE_EX(a_uMantissa, a_uExponent) \
+ ((a_uExponent) == 0x7fff && (a_uMantissa) == (RT_BIT_64(63) | RT_BIT_64(62)))
+/** Is @a a_pr80 Indefinite, Signalling- or Quiet-Nan, but not Pseudo-NaN (nor Infinity). */
+# define RTFLOAT80U_IS_INDEFINITE_OR_QUIET_OR_SIGNALLING_NAN(a_pr80) \
+ RTFLOAT80U_IS_INDEFINITE_OR_QUIET_OR_SIGNALLING_NAN_EX((a_pr80)->s.uMantissa, (a_pr80)->s.uExponent)
+# define RTFLOAT80U_IS_INDEFINITE_OR_QUIET_OR_SIGNALLING_NAN_EX(a_uMantissa, a_uExponent) \
+ ((a_uExponent) == 0x7fff && (a_uMantissa) > RT_BIT_64(63))
+/** Is @a a_pr80 an unnormal value (invalid operand on 387+). */
+# define RTFLOAT80U_IS_UNNORMAL(a_pr80) RTFLOAT80U_IS_UNNORMAL_EX((a_pr80)->s.uMantissa, (a_pr80)->s.uExponent)
+# define RTFLOAT80U_IS_UNNORMAL_EX(a_uMantissa, a_uExponent) \
+ (!((a_uMantissa) & RT_BIT_64(63)) && (a_uExponent) > 0 && (a_uExponent) < 0x7fff) /* a_uExponent can be signed and up to 64-bit wide */
+/** Is @a a_pr80 a normal value (excludes zero). */
+# define RTFLOAT80U_IS_NORMAL(a_pr80) RTFLOAT80U_IS_NORMAL_EX((a_pr80)->s.uMantissa, (a_pr80)->s.uExponent)
+# define RTFLOAT80U_IS_NORMAL_EX(a_uMantissa, a_uExponent) \
+ (((a_uMantissa) & RT_BIT_64(63)) && (a_uExponent) > 0 && (a_uExponent) < 0x7fff) /* a_uExponent can be signed and up to 64-bit wide */
+/** Invalid 387 (and later) operands: Pseudo-Infinity, Psuedo-NaN, Unnormals. */
+#define RTFLOAT80U_IS_387_INVALID(a_pr80) RTFLOAT80U_IS_387_INVALID_EX((a_pr80)->s.uMantissa, (a_pr80)->s.uExponent)
+#define RTFLOAT80U_IS_387_INVALID_EX(a_uMantissa, a_uExponent) \
+ (!((a_uMantissa) & RT_BIT_64(63)) && (a_uExponent) > 0)
+/** @} */
+
+
+/**
+ * A variant of RTFLOAT80U that may be larger than 80-bits depending on how the
+ * compiler implements long double.
+ *
+ * @note On AMD64 systems implementing the System V ABI, this will be 16 bytes!
+ * The last 6 bytes are unused padding taken up by the long double view.
+ */
+# pragma pack(1)
+typedef union RTFLOAT80U2
+{
+ /** Format using bitfields. */
+ RT_GCC_EXTENSION struct
+ {
+# ifdef RT_BIG_ENDIAN /** @todo big endian mapping is wrong. */
+ /** The sign indicator. */
+ RT_GCC_EXTENSION uint16_t fSign : 1;
+ /** The exponent (offsetted by 16383). */
+ RT_GCC_EXTENSION uint16_t uExponent : 15;
+ /** The mantissa. */
+ uint64_t uMantissa;
+# else
+ /** The mantissa. */
+ uint64_t uMantissa;
+ /** The exponent (offsetted by 16383). */
+ RT_GCC_EXTENSION uint16_t uExponent : 15;
+ /** The sign indicator. */
+ RT_GCC_EXTENSION uint16_t fSign : 1;
+# endif
+ } s;
+
+ /** Format for accessing it as two separate components. */
+ RT_GCC_EXTENSION struct
+ {
+# ifdef RT_BIG_ENDIAN /** @todo big endian mapping is wrong. */
+ /** The sign bit and exponent. */
+ uint16_t uSignAndExponent;
+ /** The mantissa. */
+ uint64_t uMantissa;
+# else
+ /** The mantissa. */
+ uint64_t uMantissa;
+ /** The sign bit and exponent. */
+ uint16_t uSignAndExponent;
+# endif
+ } s2;
+
+ /** Bitfield exposing the J bit and the fraction. */
+ RT_GCC_EXTENSION struct
+ {
+# ifdef RT_BIG_ENDIAN /** @todo big endian mapping is wrong. */
+ /** The sign indicator. */
+ RT_GCC_EXTENSION uint16_t fSign : 1;
+ /** The exponent (offsetted by 16383). */
+ RT_GCC_EXTENSION uint16_t uExponent : 15;
+ /** The J bit, aka the integer bit. */
+ uint32_t fInteger : 1;
+ /** The fraction, bits 32 thru 62. */
+ uint32_t uFractionHigh : 31;
+ /** The fraction, bits 0 thru 31. */
+ uint32_t uFractionLow : 32;
+# else
+ /** The fraction, bits 0 thru 31. */
+ uint32_t uFractionLow : 32;
+ /** The fraction, bits 32 thru 62. */
+ uint32_t uFractionHigh : 31;
+ /** The J bit, aka the integer bit. */
+ uint32_t fInteger : 1;
+ /** The exponent (offsetted 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 /** @todo big endian mapping is wrong. */
+ /** The sign indicator. */
+ RT_GCC_EXTENSION uint16_t fSign : 1;
+ /** The exponent (offsetted 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 uFraction : 63;
+# else
+ /** The fraction. */
+ RT_GCC_EXTENSION uint64_t uFraction : 63;
+ /** The J bit, aka the integer bit. */
+ RT_GCC_EXTENSION uint64_t fInteger : 1;
+ /** The exponent (offsetted by 16383). */
+ RT_GCC_EXTENSION uint16_t uExponent : 15;
+ /** The sign indicator. */
+ RT_GCC_EXTENSION uint16_t fSign : 1;
+# endif
+ } sj64;
+# endif
+
+# ifdef RT_COMPILER_WITH_80BIT_LONG_DOUBLE
+ /** Long double view. */
+ long double lrd, r;
+# 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 RT_FAR *PRTFLOAT80U2;
+/** Pointer to a const extended precision floating point format union, 2nd
+ * variant. */
+typedef const RTFLOAT80U2 RT_FAR *PCRTFLOAT80U2;
+
+#endif /* uint16_t bitfields doesn't work */
+
+
+/**
+ * Quadruple precision floating point format (128-bit).
+ */
+typedef union RTFLOAT128U
+{
+ /** Format using regular bitfields. */
+ struct
+ {
+# ifdef RT_BIG_ENDIAN
+ /** The sign indicator. */
+ uint32_t fSign : 1;
+ /** The exponent (offsetted by 16383). */
+ uint32_t uExponent : 15;
+ /** The fraction, bits 96 thru 111. */
+ uint32_t uFractionHigh : 16;
+ /** The fraction, bits 64 thru 95. */
+ uint32_t uFractionMid;
+ /** The fraction, bits 0 thru 63. */
+ uint64_t uFractionLow;
+# else
+ /** The fraction, bits 0 thru 63. */
+ uint64_t uFractionLow;
+ /** The fraction, bits 64 thru 95. */
+ uint32_t uFractionMid;
+ /** The fraction, bits 96 thru 111. */
+ uint32_t uFractionHigh : 16;
+ /** The exponent (offsetted by 16383). */
+ uint32_t uExponent : 15;
+ /** The sign indicator. */
+ uint32_t fSign : 1;
+# endif
+ } s;
+
+ /** Format for accessing it as two separate components. */
+ struct
+ {
+# ifdef RT_BIG_ENDIAN
+ /** The sign bit and exponent. */
+ uint16_t uSignAndExponent;
+ /** The fraction, bits 96 thru 111. */
+ uint16_t uFractionHigh;
+ /** The fraction, bits 64 thru 95. */
+ uint32_t uFractionMid;
+ /** The fraction, bits 0 thru 63. */
+ uint64_t uFractionLow;
+# else
+ /** The fraction, bits 0 thru 63. */
+ uint64_t uFractionLow;
+ /** The fraction, bits 64 thru 95. */
+ uint32_t uFractionMid;
+ /** The fraction, bits 96 thru 111. */
+ uint16_t uFractionHigh;
+ /** The sign bit and exponent. */
+ uint16_t uSignAndExponent;
+# endif
+ } s2;
+
+#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 (offsetted by 16383). */
+ RT_GCC_EXTENSION uint64_t uExponent : 15;
+ /** The fraction, bits 64 thru 111. */
+ RT_GCC_EXTENSION uint64_t uFractionHi : 48;
+ /** The fraction, bits 0 thru 63. */
+ uint64_t uFractionLo;
+# else
+ /** The fraction, bits 0 thru 63. */
+ uint64_t uFractionLo;
+ /** The fraction, bits 64 thru 111. */
+ RT_GCC_EXTENSION uint64_t uFractionHi : 48;
+ /** The exponent (offsetted by 16383). */
+ RT_GCC_EXTENSION uint64_t uExponent : 15;
+ /** The sign indicator. */
+ RT_GCC_EXTENSION uint64_t fSign : 1;
+# endif
+ } s64;
+#endif
+
+#ifdef RT_COMPILER_WITH_128BIT_LONG_DOUBLE
+ /** Long double view. */
+ long double lrd, r;
+#endif
+ /** 128-bit view. */
+ RTUINT128U u128;
+ /** 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];
+} RTFLOAT128U;
+/** Pointer to a quadruple precision floating point format union. */
+typedef RTFLOAT128U RT_FAR *PRTFLOAT128U;
+/** Pointer to a const quadruple precision floating point format union. */
+typedef const RTFLOAT128U RT_FAR *PCRTFLOAT128U;
+/** RTFLOAT128U initializer. */
+#ifdef RT_BIG_ENDIAN
+# define RTFLOAT128U_INIT(a_fSign, a_uFractionHi, a_uFractionLo, a_uExponent) \
+ { { (a_fSign), (a_uExponent), (uint32_t)((a_uFractionHi) >> 32), (uint32_t)((a_uFractionHi) & UINT32_MAX), (a_uFractionLo) } }
+#else
+# define RTFLOAT128U_INIT(a_fSign, a_uFractionHi, a_uFractionLo, a_uExponent) \
+ { { (a_uFractionLo), (uint32_t)((a_uFractionHi) & UINT32_MAX), (uint32_t)((a_uFractionHi) >> 32), (a_uExponent), (a_fSign) } }
+#endif
+#define RTFLOAT128U_INIT_C(a_fSign, a_uFractionHi, a_uFractionLo, a_uExponent) \
+ RTFLOAT128U_INIT((a_fSign), UINT64_C(a_uFractionHi), UINT64_C(a_uFractionLo), (a_uExponent))
+
+#define RTFLOAT128U_INIT_ZERO(a_fSign) RTFLOAT128U_INIT((a_fSign), UINT64_C(0), UINT64_C(0), 0)
+#define RTFLOAT128U_INIT_INF(a_fSign) RTFLOAT128U_INIT((a_fSign), UINT64_C(0), UINT64_C(0), RTFLOAT128U_EXP_MAX)
+#define RTFLOAT128U_INIT_SNAN(a_fSign) RTFLOAT128U_INIT((a_fSign), UINT64_C(0), UINT64_C(1), RTFLOAT128U_EXP_MAX)
+#define RTFLOAT128U_INIT_SNAN_EX(a_fSign, a_uValHi, a_uValLo) \
+ RTFLOAT128U_INIT((a_fSign), (a_uValHi), (a_uValHi) || (a_uValLo) ? (a_uValLo) : UINT64_C(1), RTFLOAT128U_EXP_MAX)
+#define RTFLOAT128U_INIT_SIGNALLING_NAN(a_fSign) RTFLOAT128U_INIT_SNAN(a_fSign)
+#define RTFLOAT128U_INIT_QNAN(a_fSign) \
+ RTFLOAT128U_INIT((a_fSign), RT_BIT_64(RTFLOAT128U_FRACTION_BITS - 1 - 64), UINT64_C(0), RTFLOAT128U_EXP_MAX)
+#define RTFLOAT128U_INIT_QNAN_EX(a_fSign, a_uValHi, a_uValLo) \
+ RTFLOAT128U_INIT((a_fSign), RT_BIT_64(RTFLOAT128U_FRACTION_BITS - 1 - 64) | (a_uValHi), (a_uValLo), RTFLOAT128U_EXP_MAX)
+#define RTFLOAT128U_INIT_QUIET_NAN(a_fSign) RTFLOAT128U_INIT_QNAN(a_fSign)
+#define RTFLOAT128U_INIT_NAN_EX(a_fQuiet, a_fSign, a_uValHi, a_uValLo) \
+ RTFLOAT128U_INIT((a_fSign), \
+ ((a_fQuiet) ? RT_BIT_64(RTFLOAT128U_FRACTION_BITS - 1 - 64) : 0) | (a_uValHi), \
+ (a_uValLo) || (a_uValHi) || (a_fQuiet) ? (a_uValLo) : UINT64_C(1), \
+ RTFLOAT128U_EXP_MAX)
+
+/** The exponent bias for the RTFLOAT128U format. */
+#define RTFLOAT128U_EXP_BIAS (16383)
+/** The max exponent value for the RTFLOAT128U format. */
+#define RTFLOAT128U_EXP_MAX (32767)
+/** The exponent bias overflow/underflow adjust for the RTFLOAT128U format.
+ * @note This is stipulated based on RTFLOAT80U, it doesn't appear in any
+ * standard text as far as we know. */
+#define RTFLOAT128U_EXP_BIAS_ADJUST (24576)
+/** Fraction width (in bits) for the RTFLOAT128U format. */
+#define RTFLOAT128U_FRACTION_BITS (112)
+/** Check if two 128-bit floating values are identical (memcmp, not
+ * numerically). */
+#define RTFLOAT128U_ARE_IDENTICAL(a_pLeft, a_pRight) \
+ ( (a_pLeft)->au64[0] == (a_pRight)->au64[0] && (a_pLeft)->au64[1] == (a_pRight)->au64[1] )
+/** @name RTFLOAT128U classification macros
+ * @{ */
+#define RTFLOAT128U_IS_ZERO(a_pr128) ( (a_pr128)->u128.s.Lo == 0 \
+ && ((a_pr128)->u128.s.Hi & (RT_BIT_64(63) - 1)) == 0)
+#define RTFLOAT128U_IS_SUBNORMAL(a_pr128) ( (a_pr128)->s.uExponent == 0 \
+ && ( (a_pr128)->s.uFractionLow != 0 \
+ || (a_pr128)->s.uFractionMid != 0 \
+ || (a_pr128)->s.uFractionHigh != 0 ) )
+#define RTFLOAT128U_IS_INF(a_pr128) ( (a_pr128)->s.uExponent == RTFLOAT128U_EXP_MAX \
+ && (a_pr128)->s.uFractionHigh == 0 \
+ && (a_pr128)->s.uFractionMid == 0 \
+ && (a_pr128)->s.uFractionLow == 0 )
+#define RTFLOAT128U_IS_SIGNALLING_NAN(a_pr128) ( (a_pr128)->s.uExponent == RTFLOAT128U_EXP_MAX \
+ && !((a_pr128)->s.uFractionHigh & RT_BIT_32(15)) \
+ && ( (a_pr128)->s.uFractionHigh != 0 \
+ || (a_pr128)->s.uFractionMid != 0 \
+ || (a_pr128)->s.uFractionLow != 0) )
+#define RTFLOAT128U_IS_QUIET_NAN(a_pr128) ( (a_pr128)->s.uExponent == RTFLOAT128U_EXP_MAX \
+ && ((a_pr128)->s.uFractionHigh & RT_BIT_32(15)))
+#define RTFLOAT128U_IS_NAN(a_pr128) ( (a_pr128)->s.uExponent == RTFLOAT128U_EXP_MAX \
+ && ( (a_pr128)->s.uFractionLow != 0 \
+ || (a_pr128)->s.uFractionMid != 0 \
+ || (a_pr128)->s.uFractionHigh != 0) )
+#define RTFLOAT128U_IS_NORMAL(a_pr128) ((a_pr128)->s.uExponent > 0 && (a_pr128)->s.uExponent < RTFLOAT128U_EXP_MAX)
+/** @} */
+
+
+/**
+ * Packed BCD 18-digit signed integer format (80-bit).
+ */
+#pragma pack(1)
+typedef union RTPBCD80U
+{
+ /** Format using bitfields. */
+ RT_GCC_EXTENSION struct
+ {
+ /** 18 packed BCD digits, two to a byte. */
+ uint8_t abPairs[9];
+ /** Padding, non-zero if indefinite. */
+ RT_GCC_EXTENSION uint8_t uPad : 7;
+ /** The sign indicator. */
+ RT_GCC_EXTENSION uint8_t fSign : 1;
+ } 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];
+} RTPBCD80U;
+#pragma pack()
+/** Pointer to a packed BCD integer format union. */
+typedef RTPBCD80U RT_FAR *PRTPBCD80U;
+/** Pointer to a const packed BCD integer format union. */
+typedef const RTPBCD80U RT_FAR *PCRTPBCD80U;
+/** RTPBCD80U initializer. */
+#define RTPBCD80U_INIT_C(a_fSign, a_D17, a_D16, a_D15, a_D14, a_D13, a_D12, a_D11, a_D10, \
+ a_D9, a_D8, a_D7, a_D6, a_D5, a_D4, a_D3, a_D2, a_D1, a_D0) \
+ RTPBCD80U_INIT_EX_C(0, a_fSign, a_D17, a_D16, a_D15, a_D14, a_D13, a_D12, a_D11, a_D10, \
+ a_D9, a_D8, a_D7, a_D6, a_D5, a_D4, a_D3, a_D2, a_D1, a_D0)
+/** Extended RTPBCD80U initializer. */
+#define RTPBCD80U_INIT_EX_C(a_uPad, a_fSign, a_D17, a_D16, a_D15, a_D14, a_D13, a_D12, a_D11, a_D10, \
+ a_D9, a_D8, a_D7, a_D6, a_D5, a_D4, a_D3, a_D2, a_D1, a_D0) \
+ { { { RTPBCD80U_MAKE_PAIR(a_D1, a_D0), \
+ RTPBCD80U_MAKE_PAIR(a_D3, a_D2), \
+ RTPBCD80U_MAKE_PAIR(a_D5, a_D4), \
+ RTPBCD80U_MAKE_PAIR(a_D7, a_D6), \
+ RTPBCD80U_MAKE_PAIR(a_D9, a_D8), \
+ RTPBCD80U_MAKE_PAIR(a_D11, a_D10), \
+ RTPBCD80U_MAKE_PAIR(a_D13, a_D12), \
+ RTPBCD80U_MAKE_PAIR(a_D15, a_D14), \
+ RTPBCD80U_MAKE_PAIR(a_D17, a_D16), }, (a_uPad), (a_fSign) } }
+/** RTPBCD80U initializer for the zero value. */
+#define RTPBCD80U_INIT_ZERO(a_fSign) RTPBCD80U_INIT_C(a_fSign, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0)
+/** RTPBCD80U initializer for the indefinite value. */
+#define RTPBCD80U_INIT_INDEFINITE() RTPBCD80U_INIT_EX_C(0x7f,1, 0xf,0xf, 0xc,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0)
+/** RTPBCD80U initializer for the minimum value. */
+#define RTPBCD80U_INIT_MIN() RTPBCD80U_INIT_C(1, 9,9, 9,9, 9,9, 9,9, 9,9, 9,9, 9,9, 9,9, 9,9)
+/** RTPBCD80U initializer for the maximum value. */
+#define RTPBCD80U_INIT_MAX() RTPBCD80U_INIT_C(0, 9,9, 9,9, 9,9, 9,9, 9,9, 9,9, 9,9, 9,9, 9,9)
+/** RTPBCD80U minimum value. */
+#define RTPBCD80U_MIN INT64_C(-999999999999999999)
+/** RTPBCD80U maximum value. */
+#define RTPBCD80U_MAX INT64_C(999999999999999999)
+/** Makes a packs a pair of BCD digits. */
+#define RTPBCD80U_MAKE_PAIR(a_D1, a_D0) ((a_D0) | ((a_D1) << 4))
+/** Retrieves the lower digit of a BCD digit pair. */
+#define RTPBCD80U_LO_DIGIT(a_bPair) ((a_bPair) & 0xf)
+/** Retrieves the higher digit of a BCD digit pair. */
+#define RTPBCD80U_HI_DIGIT(a_bPair) ((a_bPair) >> 4)
+/** Checks if the packaged BCD number is representing indefinite. */
+#define RTPBCD80U_IS_INDEFINITE(a_pd80) \
+ ( (a_pd80)->s.uPad == 0x7f \
+ && (a_pd80)->s.fSign == 1 \
+ && (a_pd80)->s.abPairs[8] == 0xff \
+ && (a_pd80)->s.abPairs[7] == RTPBCD80U_MAKE_PAIR(0xc, 0) \
+ && (a_pd80)->s.abPairs[6] == 0 \
+ && (a_pd80)->s.abPairs[5] == 0 \
+ && (a_pd80)->s.abPairs[4] == 0 \
+ && (a_pd80)->s.abPairs[3] == 0 \
+ && (a_pd80)->s.abPairs[2] == 0 \
+ && (a_pd80)->s.abPairs[1] == 0 \
+ && (a_pd80)->s.abPairs[0] == 0)
+/** Check if @a a_pd80Left and @a a_pd80Right are exactly the same. */
+#define RTPBCD80U_ARE_IDENTICAL(a_pd80Left, a_pd80Right) \
+ ( (a_pd80Left)->au64[0] == (a_pd80Right)->au64[0] && (a_pd80Left)->au16[4] == (a_pd80Right)->au16[4] )
+
+
+/** Generic function type.
+ * @see PFNRT
+ */
+typedef DECLCALLBACKTYPE(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;
+
+/** Variant on PFNRT that takes one pointer argument. */
+typedef DECLCALLBACKTYPE(void, FNRT1,(void *pvArg));
+/** Pointer to FNRT1. */
+typedef FNRT1 *PFNRT1;
+
+/** Millisecond interval. */
+typedef uint32_t RTMSINTERVAL;
+/** Pointer to a millisecond interval. */
+typedef RTMSINTERVAL RT_FAR *PRTMSINTERVAL;
+/** Pointer to a const millisecond interval. */
+typedef const RTMSINTERVAL RT_FAR *PCRTMSINTERVAL;
+
+/** Pointer to a time spec structure. */
+typedef struct RTTIMESPEC RT_FAR *PRTTIMESPEC;
+/** Pointer to a const time spec structure. */
+typedef const struct RTTIMESPEC RT_FAR *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 RT_FAR *PRTINTPTR;
+/** Pointer const to signed integer which can contain both GC and HC pointers. */
+typedef const RTINTPTR RT_FAR *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 RT_FAR *PRTUINTPTR;
+/** Pointer const to unsigned integer which can contain both GC and HC pointers. */
+typedef const RTUINTPTR RT_FAR *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 RT_FAR *PRTINT;
+/** Pointer to const signed integer. */
+typedef const RTINT RT_FAR *PCRTINT;
+
+/** Unsigned integer. */
+typedef uint32_t RTUINT;
+/** Pointer to unsigned integer. */
+typedef RTUINT RT_FAR *PRTUINT;
+/** Pointer to const unsigned integer. */
+typedef const RTUINT RT_FAR *PCRTUINT;
+
+/** A file offset / size (off_t). */
+typedef int64_t RTFOFF;
+/** Pointer to a file offset / size. */
+typedef RTFOFF RT_FAR *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 RT_FAR *PRTFMODE;
+
+/** Device unix number. */
+typedef uint32_t RTDEV;
+/** Pointer to a device unix number. */
+typedef RTDEV RT_FAR *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 RT_FAR *PRTINODE;
+
+/** User id. */
+typedef uint32_t RTUID;
+/** Pointer to a user id. */
+typedef RTUID RT_FAR *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 RT_FAR *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 RT_FAR *PRTIOPORT;
+/** Pointer to const I/O Port. */
+typedef const RTIOPORT RT_FAR *PCRTIOPORT;
+
+/** Selector. */
+typedef uint16_t RTSEL;
+/** Pointer to selector. */
+typedef RTSEL RT_FAR *PRTSEL;
+/** Pointer to const selector. */
+typedef const RTSEL RT_FAR *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 RT_FAR *PRTFAR16;
+/** Pointer to const Far 16-bit pointer. */
+typedef const RTFAR16 RT_FAR *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 RT_FAR *PRTFAR32;
+/** Pointer to const Far 32-bit pointer. */
+typedef const RTFAR32 RT_FAR *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 RT_FAR *PRTFAR64;
+/** Pointer to const Far 64-bit pointer. */
+typedef const RTFAR64 RT_FAR *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 RT_FAR *PRTHCINT;
+/** Pointer to const HC Natural signed integer.
+ * @deprecated silly type. */
+typedef const RTHCINT RT_FAR *PCRTHCINT;
+
+/** HC Natural unsigned integer.
+ * @deprecated silly type. */
+typedef uint32_t RTHCUINT;
+/** Pointer to HC Natural unsigned integer.
+ * @deprecated silly type. */
+typedef RTHCUINT RT_FAR *PRTHCUINT;
+/** Pointer to const HC Natural unsigned integer.
+ * @deprecated silly type. */
+typedef const RTHCUINT RT_FAR *PCRTHCUINT;
+
+
+/** Signed integer which can contain a HC pointer. */
+#if HC_ARCH_BITS == 32 || HC_ARCH_BITS == 16
+typedef int32_t RTHCINTPTR;
+#elif HC_ARCH_BITS == 64
+typedef int64_t RTHCINTPTR;
+#else
+# error Unsupported HC_ARCH_BITS value.
+#endif
+/** Pointer to signed integer which can contain a HC pointer. */
+typedef RTHCINTPTR RT_FAR *PRTHCINTPTR;
+/** Pointer to const signed integer which can contain a HC pointer. */
+typedef const RTHCINTPTR RT_FAR *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 || R3_ARCH_BITS == 16
+typedef int32_t RTR3INTPTR;
+#elif R3_ARCH_BITS == 64
+typedef int64_t RTR3INTPTR;
+#else
+# error Unsupported R3_ARCH_BITS value.
+#endif
+/** Pointer to signed integer which can contain a HC ring-3 pointer. */
+typedef RTR3INTPTR RT_FAR *PRTR3INTPTR;
+/** Pointer to const signed integer which can contain a HC ring-3 pointer. */
+typedef const RTR3INTPTR RT_FAR *PCRTR3INTPTR;
+/** Max RTR3INTPTR value. */
+#if R3_ARCH_BITS == 32 || R3_ARCH_BITS == 16
+# define RTR3INTPTR_MAX INT32_MAX
+#else
+# define RTR3INTPTR_MAX INT64_MAX
+#endif
+/** Min RTR3INTPTR value. */
+#if R3_ARCH_BITS == 32 || R3_ARCH_BITS == 16
+# define RTR3INTPTR_MIN INT32_MIN
+#else
+# define RTR3INTPTR_MIN INT64_MIN
+#endif
+
+/** Signed integer which can contain a HC ring-0 pointer. */
+#if R0_ARCH_BITS == 32 || R0_ARCH_BITS == 16
+typedef int32_t RTR0INTPTR;
+#elif R0_ARCH_BITS == 64
+typedef int64_t RTR0INTPTR;
+#else
+# error Unsupported R0_ARCH_BITS value.
+#endif
+/** Pointer to signed integer which can contain a HC ring-0 pointer. */
+typedef RTR0INTPTR RT_FAR *PRTR0INTPTR;
+/** Pointer to const signed integer which can contain a HC ring-0 pointer. */
+typedef const RTR0INTPTR RT_FAR *PCRTR0INTPTR;
+/** Max RTR0INTPTR value. */
+#if R0_ARCH_BITS == 32 || R0_ARCH_BITS == 16
+# define RTR0INTPTR_MAX INT32_MAX
+#else
+# define RTR0INTPTR_MAX INT64_MAX
+#endif
+/** Min RTHCINTPTR value. */
+#if R0_ARCH_BITS == 32 || R0_ARCH_BITS == 16
+# define RTR0INTPTR_MIN INT32_MIN
+#else
+# define RTR0INTPTR_MIN INT64_MIN
+#endif
+
+
+/** Unsigned integer which can contain a HC pointer. */
+#if HC_ARCH_BITS == 32 || HC_ARCH_BITS == 16
+typedef uint32_t RTHCUINTPTR;
+#elif HC_ARCH_BITS == 64
+typedef uint64_t RTHCUINTPTR;
+#else
+# error Unsupported HC_ARCH_BITS value.
+#endif
+/** Pointer to unsigned integer which can contain a HC pointer. */
+typedef RTHCUINTPTR RT_FAR *PRTHCUINTPTR;
+/** Pointer to unsigned integer which can contain a HC pointer. */
+typedef const RTHCUINTPTR RT_FAR *PCRTHCUINTPTR;
+/** Max RTHCUINTTPR value. */
+#if HC_ARCH_BITS == 32 || HC_ARCH_BITS == 16
+# define RTHCUINTPTR_MAX UINT32_MAX
+#else
+# define RTHCUINTPTR_MAX UINT64_MAX
+#endif
+
+/** Unsigned integer which can contain a HC ring-3 pointer. */
+#if R3_ARCH_BITS == 32 || R3_ARCH_BITS == 16
+typedef uint32_t RTR3UINTPTR;
+#elif R3_ARCH_BITS == 64
+typedef uint64_t RTR3UINTPTR;
+#else
+# error Unsupported R3_ARCH_BITS value.
+#endif
+/** Pointer to unsigned integer which can contain a HC ring-3 pointer. */
+typedef RTR3UINTPTR RT_FAR *PRTR3UINTPTR;
+/** Pointer to unsigned integer which can contain a HC ring-3 pointer. */
+typedef const RTR3UINTPTR RT_FAR *PCRTR3UINTPTR;
+/** Max RTHCUINTTPR value. */
+#if R3_ARCH_BITS == 32 || R3_ARCH_BITS == 16
+# define RTR3UINTPTR_MAX UINT32_MAX
+#else
+# define RTR3UINTPTR_MAX UINT64_MAX
+#endif
+
+/** Unsigned integer which can contain a HC ring-0 pointer. */
+#if R0_ARCH_BITS == 32 || R0_ARCH_BITS == 16
+typedef uint32_t RTR0UINTPTR;
+#elif R0_ARCH_BITS == 64
+typedef uint64_t RTR0UINTPTR;
+#else
+# error Unsupported R0_ARCH_BITS value.
+#endif
+/** Pointer to unsigned integer which can contain a HC ring-0 pointer. */
+typedef RTR0UINTPTR RT_FAR *PRTR0UINTPTR;
+/** Pointer to unsigned integer which can contain a HC ring-0 pointer. */
+typedef const RTR0UINTPTR RT_FAR *PCRTR0UINTPTR;
+/** Max RTR0UINTTPR value. */
+#if R0_ARCH_BITS == 32 || R0_ARCH_BITS == 16
+# define RTR0UINTPTR_MAX UINT32_MAX
+#else
+# define RTR0UINTPTR_MAX UINT64_MAX
+#endif
+
+
+/** Host Physical Memory Address. */
+typedef uint64_t RTHCPHYS;
+/** Pointer to Host Physical Memory Address. */
+typedef RTHCPHYS RT_FAR *PRTHCPHYS;
+/** Pointer to const Host Physical Memory Address. */
+typedef const RTHCPHYS RT_FAR *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. */
+#if !defined(IN_RC) || defined(DOXYGEN_RUNNING)
+typedef void RT_FAR *RTHCPTR;
+#else
+typedef RTHCUINTPTR RTHCPTR;
+#endif
+/** Pointer to HC pointer. */
+typedef RTHCPTR RT_FAR *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 RT_FAR *RTR3PTR;
+#else
+typedef RTR3UINTPTR RTR3PTR;
+#endif
+/** Pointer to HC ring-3 pointer. */
+typedef RTR3PTR RT_FAR *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 RT_FAR *RTR0PTR;
+#else
+typedef RTR0UINTPTR RTR0PTR;
+#endif
+/** Pointer to HC ring-0 pointer. */
+typedef RTR0PTR RT_FAR *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 RT_FAR *PRTHCUINTREG;
+/** Pointer to a const unsigned integer register in the host context. */
+typedef const RTHCUINTREG RT_FAR *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 RT_FAR *PRTR3UINTREG;
+/** Pointer to a const unsigned integer register in the host ring-3 context. */
+typedef const RTR3UINTREG RT_FAR *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 RT_FAR *PRTR0UINTREG;
+/** Pointer to a const unsigned integer register in the host ring-3 context. */
+typedef const RTR0UINTREG RT_FAR *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 RT_FAR *PRTGCINT;
+/** Pointer to const natural signed integer in GC.
+ * @deprecated silly type. */
+typedef const RTGCINT RT_FAR *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 RT_FAR *PRTGCUINT;
+/** Pointer to const natural unsigned integer in GC.
+ * @deprecated silly type. */
+typedef const RTGCUINT RT_FAR *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 RT_FAR *PRTGCINTPTR;
+/** Pointer to const signed integer which can contain a GC pointer. */
+typedef const RTGCINTPTR RT_FAR *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 RT_FAR *PRTGCUINTPTR;
+/** Pointer to unsigned integer which can contain a GC pointer. */
+typedef const RTGCUINTPTR RT_FAR *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 RT_FAR *PRTGCUINTPTR32;
+/** Pointer to unsigned integer which can contain a 32 bits GC pointer. */
+typedef const RTGCUINTPTR32 RT_FAR *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 RT_FAR *PRTGCUINTPTR64;
+/** Pointer to unsigned integer which can contain a 32 bits GC pointer. */
+typedef const RTGCUINTPTR64 RT_FAR *PCRTGCUINTPTR64;
+
+/** Guest Physical Memory Address.*/
+typedef uint64_t RTGCPHYS;
+/** Pointer to Guest Physical Memory Address. */
+typedef RTGCPHYS RT_FAR *PRTGCPHYS;
+/** Pointer to const Guest Physical Memory Address. */
+typedef const RTGCPHYS RT_FAR *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 RT_FAR *PRTGCPHYS32;
+/** Pointer to const Guest Physical Memory Address. */
+typedef const RTGCPHYS32 RT_FAR *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 RT_FAR *PRTGCPHYS64;
+/** Pointer to const Guest Physical Memory Address. */
+typedef const RTGCPHYS64 RT_FAR *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 RT_FAR *PRTGCPTR32;
+/** Pointer to a const guest context pointer. */
+typedef const RTGCPTR32 RT_FAR *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 RT_FAR *PRTGCPTR64;
+/** Pointer to a const guest context pointer. */
+typedef const RTGCPTR64 RT_FAR *PCRTGCPTR64;
+/** @def NIL_RTGCPTR64
+ * NIL GC pointer.
+ */
+#define NIL_RTGCPTR64 ((RTGCPTR64)0)
+
+/** @typedef RTGCPTR
+ * Guest context pointer.
+ * Keep in mind that this type is an unsigned integer in HC and void pointer in GC. */
+/** @typedef PRTGCPTR
+ * Pointer to a guest context pointer. */
+/** @typedef PCRTGCPTR
+ * Pointer to a const guest context pointer. */
+/** @def NIL_RTGCPTR
+ * NIL GC pointer. */
+/** @def RTGCPTR_MAX
+ * Max RTGCPTR value. */
+#if GC_ARCH_BITS == 64 || defined(DOXYGEN_RUNNING)
+typedef RTGCPTR64 RTGCPTR;
+typedef PRTGCPTR64 PRTGCPTR;
+typedef PCRTGCPTR64 PCRTGCPTR;
+# define NIL_RTGCPTR NIL_RTGCPTR64
+# define RTGCPTR_MAX UINT64_MAX
+#elif GC_ARCH_BITS == 32
+typedef RTGCPTR32 RTGCPTR;
+typedef PRTGCPTR32 PRTGCPTR;
+typedef PCRTGCPTR32 PCRTGCPTR;
+# define NIL_RTGCPTR NIL_RTGCPTR32
+# 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 RT_FAR *PRTGCUINTREG32;
+/** Pointer to a const unsigned integer register in the guest context. */
+typedef const RTGCUINTREG32 RT_FAR *PCRTGCUINTREG32;
+
+typedef uint64_t RTGCUINTREG64;
+/** Pointer to an unsigned integer register in the guest context. */
+typedef RTGCUINTREG64 RT_FAR *PRTGCUINTREG64;
+/** Pointer to a const unsigned integer register in the guest context. */
+typedef const RTGCUINTREG64 RT_FAR *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 RT_FAR *PRTGCUINTREG;
+/** Pointer to a const unsigned integer register in the guest context. */
+typedef const RTGCUINTREG RT_FAR *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 RT_FAR *RTRCPTR;
+#else
+typedef uint32_t RTRCPTR;
+#endif
+/** Pointer to a raw mode context pointer. */
+typedef RTRCPTR RT_FAR *PRTRCPTR;
+/** Pointer to a const raw mode context pointer. */
+typedef const RTRCPTR RT_FAR *PCRTRCPTR;
+/** @def NIL_RTRCPTR
+ * NIL RC pointer. */
+#ifdef IN_RC
+# define NIL_RTRCPTR (NULL)
+#else
+# define NIL_RTRCPTR ((RTRCPTR)0)
+#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)
+
+/* The following are only temporarily while we clean up RTRCPTR usage: */
+#ifdef IN_RC
+typedef void RT_FAR *RTRGPTR;
+#else
+typedef uint64_t RTRGPTR;
+#endif
+typedef RTRGPTR RT_FAR *PRTRGPTR;
+typedef const RTRGPTR RT_FAR *PCRTRGPTR;
+#ifdef IN_RC
+# define NIL_RTRGPTR (NULL)
+#else
+# define NIL_RTRGPTR ((RTRGPTR)0)
+#endif
+
+/** @} */
+
+
+/** @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 RT_FAR *PRTCCPHYS;
+/** Pointer to const Current Context Physical Memory Address. */
+typedef const RTCCPHYS RT_FAR *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 RT_FAR *PRTCCUINTREG;
+/** Pointer to a const unsigned integer register in the current context. */
+typedef RTCCUINTREG const RT_FAR *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 RT_FAR *PRTCCINTREG;
+/** Pointer to a const signed integer register in the current context. */
+typedef RTCCINTREG const RT_FAR *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 RT_FAR *PRTCCUINTXREG;
+/** Pointer to a const unsigned integer register in the current context. */
+typedef RTCCUINTREG const RT_FAR *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 RT_FAR *PRTCCINTXREG;
+/** Pointer to a const signed integer extended register in the current
+ * context. */
+typedef RTCCINTXREG const RT_FAR *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. */
+/** @def RTCCINTXREG_BITS
+ * The width of RTCCINTXREG in bits (32 or 64). */
+#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"
+# define RTCCINTXREG_BITS 32
+#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
+# define RTCCINTXREG_BITS ARCH_BITS
+#endif
+/** @} */
+
+
+
+/** Pointer to a big integer number. */
+typedef struct RTBIGNUM RT_FAR *PRTBIGNUM;
+/** Pointer to a const big integer number. */
+typedef struct RTBIGNUM const RT_FAR *PCRTBIGNUM;
+
+
+/** Pointer to a critical section. */
+typedef struct RTCRITSECT RT_FAR *PRTCRITSECT;
+/** Pointer to a const critical section. */
+typedef const struct RTCRITSECT RT_FAR *PCRTCRITSECT;
+
+/** Pointer to a read/write critical section. */
+typedef struct RTCRITSECTRW RT_FAR *PRTCRITSECTRW;
+/** Pointer to a const read/write critical section. */
+typedef const struct RTCRITSECTRW RT_FAR *PCRTCRITSECTRW;
+
+
+/** Condition variable handle. */
+typedef R3PTRTYPE(struct RTCONDVARINTERNAL RT_FAR *) RTCONDVAR;
+/** Pointer to a condition variable handle. */
+typedef RTCONDVAR RT_FAR *PRTCONDVAR;
+/** Nil condition variable handle. */
+#define NIL_RTCONDVAR 0
+
+/** Cryptographic (certificate) store handle. */
+typedef R3R0PTRTYPE(struct RTCRSTOREINT RT_FAR *) RTCRSTORE;
+/** Pointer to a Cryptographic (certificate) store handle. */
+typedef RTCRSTORE RT_FAR *PRTCRSTORE;
+/** Nil Cryptographic (certificate) store handle. */
+#define NIL_RTCRSTORE 0
+
+/** Pointer to a const (store) certificate context. */
+typedef struct RTCRCERTCTX const RT_FAR *PCRTCRCERTCTX;
+
+/** Cryptographic message digest handle. */
+typedef R3R0PTRTYPE(struct RTCRDIGESTINT RT_FAR *) RTCRDIGEST;
+/** Pointer to a cryptographic message digest handle. */
+typedef RTCRDIGEST RT_FAR *PRTCRDIGEST;
+/** NIL cryptographic message digest handle. */
+#define NIL_RTCRDIGEST (0)
+
+/** Cryptographic key handle. */
+typedef R3R0PTRTYPE(struct RTCRKEYINT RT_FAR *) RTCRKEY;
+/** Pointer to a cryptographic key handle. */
+typedef RTCRKEY RT_FAR *PRTCRKEY;
+/** Cryptographic key handle nil value. */
+#define NIL_RTCRKEY (0)
+
+/** Public key encryption schema handle. */
+typedef R3R0PTRTYPE(struct RTCRPKIXENCRYPTIONINT RT_FAR *) RTCRPKIXENCRYPTION;
+/** Pointer to a public key encryption schema handle. */
+typedef RTCRPKIXENCRYPTION RT_FAR *PRTCRPKIXENCRYPTION;
+/** NIL public key encryption schema handle */
+#define NIL_RTCRPKIXENCRYPTION (0)
+
+/** Public key signature schema handle. */
+typedef R3R0PTRTYPE(struct RTCRPKIXSIGNATUREINT RT_FAR *) RTCRPKIXSIGNATURE;
+/** Pointer to a public key signature schema handle. */
+typedef RTCRPKIXSIGNATURE RT_FAR *PRTCRPKIXSIGNATURE;
+/** NIL public key signature schema handle */
+#define NIL_RTCRPKIXSIGNATURE (0)
+
+/** X.509 certificate paths builder & validator handle. */
+typedef R3R0PTRTYPE(struct RTCRX509CERTPATHSINT RT_FAR *) RTCRX509CERTPATHS;
+/** Pointer to a certificate paths builder & validator handle. */
+typedef RTCRX509CERTPATHS RT_FAR *PRTCRX509CERTPATHS;
+/** Nil certificate paths builder & validator handle. */
+#define NIL_RTCRX509CERTPATHS 0
+
+/** Directory handle. */
+typedef struct RTDIRINTERNAL *RTDIR;
+/** Pointer to directory handle. */
+typedef RTDIR *PRTDIR;
+/** NIL directory handle. */
+#define NIL_RTDIR ((RTDIR)0)
+
+/** File handle. */
+typedef R3R0PTRTYPE(struct RTFILEINT RT_FAR *) RTFILE;
+/** Pointer to file handle. */
+typedef RTFILE RT_FAR *PRTFILE;
+/** Nil file handle. */
+#define NIL_RTFILE ((RTFILE)~(RTHCINTPTR)0)
+
+/** Async I/O request handle. */
+typedef R3PTRTYPE(struct RTFILEAIOREQINTERNAL RT_FAR *) RTFILEAIOREQ;
+/** Pointer to an async I/O request handle. */
+typedef RTFILEAIOREQ RT_FAR *PRTFILEAIOREQ;
+/** Nil request handle. */
+#define NIL_RTFILEAIOREQ 0
+
+/** Async I/O completion context handle. */
+typedef R3PTRTYPE(struct RTFILEAIOCTXINTERNAL RT_FAR *) RTFILEAIOCTX;
+/** Pointer to an async I/O completion context handle. */
+typedef RTFILEAIOCTX RT_FAR *PRTFILEAIOCTX;
+/** Nil context handle. */
+#define NIL_RTFILEAIOCTX 0
+
+/** ISO image maker handle. */
+typedef struct RTFSISOMAKERINT RT_FAR *RTFSISOMAKER;
+/** Pointer to an ISO image maker handle. */
+typedef RTFSISOMAKER RT_FAR *PRTFSISOMAKER;
+/** NIL ISO maker handle. */
+#define NIL_RTFSISOMAKER ((RTFSISOMAKER)0)
+
+/** INI-file handle. */
+typedef struct RTINIFILEINT RT_FAR *RTINIFILE;
+/** Pointer to an INI-file handle. */
+typedef RTINIFILE RT_FAR *PRTINIFILE;
+/** NIL INI-file handle. */
+#define NIL_RTINIFILE ((RTINIFILE)0)
+
+/** Loader module handle. */
+typedef R3R0PTRTYPE(struct RTLDRMODINTERNAL RT_FAR *) RTLDRMOD;
+/** Pointer to a loader module handle. */
+typedef RTLDRMOD RT_FAR *PRTLDRMOD;
+/** Nil loader module handle. */
+#define NIL_RTLDRMOD 0
+
+/** Lock validator class handle. */
+typedef R3R0PTRTYPE(struct RTLOCKVALCLASSINT RT_FAR *) RTLOCKVALCLASS;
+/** Pointer to a lock validator class handle. */
+typedef RTLOCKVALCLASS RT_FAR *PRTLOCKVALCLASS;
+/** Nil lock validator class handle. */
+#define NIL_RTLOCKVALCLASS ((RTLOCKVALCLASS)0)
+
+/** Ring-0 memory object handle. */
+typedef R0PTRTYPE(struct RTR0MEMOBJINTERNAL RT_FAR *) RTR0MEMOBJ;
+/** Pointer to a Ring-0 memory object handle. */
+typedef RTR0MEMOBJ RT_FAR *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 RT_FAR *PRTNATIVETHREAD;
+/** Nil native thread handle. */
+#define NIL_RTNATIVETHREAD (~(RTNATIVETHREAD)0)
+
+/** Pipe handle. */
+typedef R3R0PTRTYPE(struct RTPIPEINTERNAL RT_FAR *) RTPIPE;
+/** Pointer to a pipe handle. */
+typedef RTPIPE RT_FAR *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 RT_FAR *) RTPOLLSET;
+/** Pointer to a poll set handle. */
+typedef RTPOLLSET RT_FAR *PRTPOLLSET;
+/** Nil poll set handle handle. */
+#define NIL_RTPOLLSET ((RTPOLLSET)0)
+
+/** Process identifier. */
+typedef uint32_t RTPROCESS;
+/** Pointer to a process identifier. */
+typedef RTPROCESS RT_FAR *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 RT_FAR *PRTR0PROCESS;
+/** Nil ring-0 process handle. */
+#define NIL_RTR0PROCESS (~(RTR0PROCESS)0)
+
+/** @typedef RTSEMEVENT
+ * Event Semaphore handle. */
+typedef R3R0PTRTYPE(struct RTSEMEVENTINTERNAL RT_FAR *) RTSEMEVENT;
+/** Pointer to an event semaphore handle. */
+typedef RTSEMEVENT RT_FAR *PRTSEMEVENT;
+/** Nil event semaphore handle. */
+#define NIL_RTSEMEVENT 0
+
+/** @typedef RTSEMEVENTMULTI
+ * Event Multiple Release Semaphore handle. */
+typedef R3R0PTRTYPE(struct RTSEMEVENTMULTIINTERNAL RT_FAR *) RTSEMEVENTMULTI;
+/** Pointer to an event multiple release semaphore handle. */
+typedef RTSEMEVENTMULTI RT_FAR *PRTSEMEVENTMULTI;
+/** Nil multiple release event semaphore handle. */
+#define NIL_RTSEMEVENTMULTI 0
+
+/** @typedef RTSEMFASTMUTEX
+ * Fast mutex Semaphore handle. */
+typedef R3R0PTRTYPE(struct RTSEMFASTMUTEXINTERNAL RT_FAR *) RTSEMFASTMUTEX;
+/** Pointer to a fast mutex semaphore handle. */
+typedef RTSEMFASTMUTEX RT_FAR *PRTSEMFASTMUTEX;
+/** Nil fast mutex semaphore handle. */
+#define NIL_RTSEMFASTMUTEX 0
+
+/** @typedef RTSEMMUTEX
+ * Mutex Semaphore handle. */
+typedef R3R0PTRTYPE(struct RTSEMMUTEXINTERNAL RT_FAR *) RTSEMMUTEX;
+/** Pointer to a mutex semaphore handle. */
+typedef RTSEMMUTEX RT_FAR *PRTSEMMUTEX;
+/** Nil mutex semaphore handle. */
+#define NIL_RTSEMMUTEX 0
+
+/** @typedef RTSEMSPINMUTEX
+ * Spinning mutex Semaphore handle. */
+typedef R3R0PTRTYPE(struct RTSEMSPINMUTEXINTERNAL RT_FAR *) RTSEMSPINMUTEX;
+/** Pointer to a spinning mutex semaphore handle. */
+typedef RTSEMSPINMUTEX RT_FAR *PRTSEMSPINMUTEX;
+/** Nil spinning mutex semaphore handle. */
+#define NIL_RTSEMSPINMUTEX 0
+
+/** @typedef RTSEMRW
+ * Read/Write Semaphore handle. */
+typedef R3R0PTRTYPE(struct RTSEMRWINTERNAL RT_FAR *) RTSEMRW;
+/** Pointer to a read/write semaphore handle. */
+typedef RTSEMRW RT_FAR *PRTSEMRW;
+/** Nil read/write semaphore handle. */
+#define NIL_RTSEMRW 0
+
+/** @typedef RTSEMXROADS
+ * Crossroads semaphore handle. */
+typedef R3R0PTRTYPE(struct RTSEMXROADSINTERNAL RT_FAR *) RTSEMXROADS;
+/** Pointer to a crossroads semaphore handle. */
+typedef RTSEMXROADS RT_FAR *PRTSEMXROADS;
+/** Nil crossroads semaphore handle. */
+#define NIL_RTSEMXROADS ((RTSEMXROADS)0)
+
+/** Spinlock handle. */
+typedef R3R0PTRTYPE(struct RTSPINLOCKINTERNAL RT_FAR *) RTSPINLOCK;
+/** Pointer to a spinlock handle. */
+typedef RTSPINLOCK RT_FAR *PRTSPINLOCK;
+/** Nil spinlock handle. */
+#define NIL_RTSPINLOCK 0
+
+/** Socket handle. */
+typedef R3R0PTRTYPE(struct RTSOCKETINT RT_FAR *) RTSOCKET;
+/** Pointer to socket handle. */
+typedef RTSOCKET RT_FAR *PRTSOCKET;
+/** Nil socket handle. */
+#define NIL_RTSOCKET ((RTSOCKET)0)
+
+/** Pointer to a RTTCPSERVER handle. */
+typedef struct RTTCPSERVER RT_FAR *PRTTCPSERVER;
+/** Pointer to a RTTCPSERVER handle. */
+typedef PRTTCPSERVER RT_FAR *PPRTTCPSERVER;
+/** Nil RTTCPSERVER handle. */
+#define NIL_RTTCPSERVER ((PRTTCPSERVER)0)
+
+/** Pointer to a RTUDPSERVER handle. */
+typedef struct RTUDPSERVER RT_FAR *PRTUDPSERVER;
+/** Pointer to a RTUDPSERVER handle. */
+typedef PRTUDPSERVER RT_FAR *PPRTUDPSERVER;
+/** Nil RTUDPSERVER handle. */
+#define NIL_RTUDPSERVER ((PRTUDPSERVER)0)
+
+/** Thread handle.*/
+typedef R3R0PTRTYPE(struct RTTHREADINT RT_FAR *) RTTHREAD;
+/** Pointer to thread handle. */
+typedef RTTHREAD RT_FAR *PRTTHREAD;
+/** Nil thread handle. */
+#define NIL_RTTHREAD 0
+
+/** Thread context switching hook handle. */
+typedef R0PTRTYPE(struct RTTHREADCTXHOOKINT RT_FAR *) RTTHREADCTXHOOK;
+/** Pointer to Thread context switching hook handle. */
+typedef RTTHREADCTXHOOK RT_FAR *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 RT_FAR *PRTTLS;
+/** Pointer to a const TLS index. */
+typedef RTTLS const RT_FAR *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 RT_FAR *RTTRACEBUF;
+/** Pointer to a trace buffer handle. */
+typedef RTTRACEBUF RT_FAR *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 RT_FAR *) RTHEAPSIMPLE;
+/** Pointer to a handle to a simple heap. */
+typedef RTHEAPSIMPLE RT_FAR *PRTHEAPSIMPLE;
+/** NIL simple heap handle. */
+#define NIL_RTHEAPSIMPLE ((RTHEAPSIMPLE)0)
+
+/** Handle to an offset based heap. */
+typedef R3R0PTRTYPE(struct RTHEAPOFFSETINTERNAL RT_FAR *) RTHEAPOFFSET;
+/** Pointer to a handle to an offset based heap. */
+typedef RTHEAPOFFSET RT_FAR *PRTHEAPOFFSET;
+/** NIL offset based heap handle. */
+#define NIL_RTHEAPOFFSET ((RTHEAPOFFSET)0)
+
+/** Handle to an environment block. */
+typedef R3PTRTYPE(struct RTENVINTERNAL RT_FAR *) RTENV;
+/** Pointer to a handle to an environment block. */
+typedef RTENV RT_FAR *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 RT_FAR *PRTCPUID;
+/** Pointer to a const CPU identifier. */
+typedef RTCPUID const RT_FAR *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 power of two and multiple of 64 (see RTCPUSET). */
+#if defined(RT_ARCH_X86) || defined(RT_ARCH_AMD64)
+# if defined(RT_OS_OS2)
+# define RTCPUSET_MAX_CPUS 64
+# elif defined(RT_OS_DARWIN) || defined(RT_ARCH_X86)
+# define RTCPUSET_MAX_CPUS 256
+# else
+# define RTCPUSET_MAX_CPUS 1024
+# endif
+#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 RT_FAR *PRTCPUSET;
+/** Pointer to a const CPU set. */
+typedef RTCPUSET const RT_FAR *PCRTCPUSET;
+
+/** A handle table handle. */
+typedef R3R0PTRTYPE(struct RTHANDLETABLEINT RT_FAR *) RTHANDLETABLE;
+/** A pointer to a handle table handle. */
+typedef RTHANDLETABLE RT_FAR *PRTHANDLETABLE;
+/** @def NIL_RTHANDLETABLE
+ * NIL handle table handle. */
+#define NIL_RTHANDLETABLE ((RTHANDLETABLE)0)
+
+/** A handle to a low resolution timer. */
+typedef R3R0PTRTYPE(struct RTTIMERLRINT RT_FAR *) RTTIMERLR;
+/** A pointer to a low resolution timer handle. */
+typedef RTTIMERLR RT_FAR *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 RT_FAR *) RTRAND;
+/** Pointer to a random number generator handle. */
+typedef RTRAND RT_FAR *PRTRAND;
+/** NIL random number generator handle value. */
+#define NIL_RTRAND ((RTRAND)0)
+
+/** Debug address space handle. */
+typedef R3R0PTRTYPE(struct RTDBGASINT RT_FAR *) RTDBGAS;
+/** Pointer to a debug address space handle. */
+typedef RTDBGAS RT_FAR *PRTDBGAS;
+/** NIL debug address space handle. */
+#define NIL_RTDBGAS ((RTDBGAS)0)
+
+/** Debug module handle. */
+typedef R3R0PTRTYPE(struct RTDBGMODINT RT_FAR *) RTDBGMOD;
+/** Pointer to a debug module handle. */
+typedef RTDBGMOD RT_FAR *PRTDBGMOD;
+/** NIL debug module handle. */
+#define NIL_RTDBGMOD ((RTDBGMOD)0)
+
+/** Pointer to an unwind machine state. */
+typedef struct RTDBGUNWINDSTATE RT_FAR *PRTDBGUNWINDSTATE;
+/** Pointer to a const unwind machine state. */
+typedef struct RTDBGUNWINDSTATE const RT_FAR *PCRTDBGUNWINDSTATE;
+
+/** Manifest handle. */
+typedef struct RTMANIFESTINT RT_FAR *RTMANIFEST;
+/** Pointer to a manifest handle. */
+typedef RTMANIFEST RT_FAR *PRTMANIFEST;
+/** NIL manifest handle. */
+#define NIL_RTMANIFEST ((RTMANIFEST)~(uintptr_t)0)
+
+/** Memory pool handle. */
+typedef R3R0PTRTYPE(struct RTMEMPOOLINT RT_FAR *) RTMEMPOOL;
+/** Pointer to a memory pool handle. */
+typedef RTMEMPOOL RT_FAR *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 RT_FAR *) RTSTRCACHE;
+/** Pointer to a string cache handle. */
+typedef RTSTRCACHE RT_FAR *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 RT_FAR *RTVFS;
+/** Pointer to a VFS handle. */
+typedef RTVFS RT_FAR *PRTVFS;
+/** A NIL VFS handle. */
+#define NIL_RTVFS ((RTVFS)~(uintptr_t)0)
+
+/** Virtual Filesystem base object handle. */
+typedef struct RTVFSOBJINTERNAL RT_FAR *RTVFSOBJ;
+/** Pointer to a VFS base object handle. */
+typedef RTVFSOBJ RT_FAR *PRTVFSOBJ;
+/** A NIL VFS base object handle. */
+#define NIL_RTVFSOBJ ((RTVFSOBJ)~(uintptr_t)0)
+
+/** Virtual Filesystem directory handle. */
+typedef struct RTVFSDIRINTERNAL RT_FAR *RTVFSDIR;
+/** Pointer to a VFS directory handle. */
+typedef RTVFSDIR RT_FAR *PRTVFSDIR;
+/** A NIL VFS directory handle. */
+#define NIL_RTVFSDIR ((RTVFSDIR)~(uintptr_t)0)
+
+/** Virtual Filesystem filesystem stream handle. */
+typedef struct RTVFSFSSTREAMINTERNAL RT_FAR *RTVFSFSSTREAM;
+/** Pointer to a VFS filesystem stream handle. */
+typedef RTVFSFSSTREAM RT_FAR *PRTVFSFSSTREAM;
+/** A NIL VFS filesystem stream handle. */
+#define NIL_RTVFSFSSTREAM ((RTVFSFSSTREAM)~(uintptr_t)0)
+
+/** Virtual Filesystem I/O stream handle. */
+typedef struct RTVFSIOSTREAMINTERNAL RT_FAR *RTVFSIOSTREAM;
+/** Pointer to a VFS I/O stream handle. */
+typedef RTVFSIOSTREAM RT_FAR *PRTVFSIOSTREAM;
+/** A NIL VFS I/O stream handle. */
+#define NIL_RTVFSIOSTREAM ((RTVFSIOSTREAM)~(uintptr_t)0)
+
+/** Virtual Filesystem file handle. */
+typedef struct RTVFSFILEINTERNAL RT_FAR *RTVFSFILE;
+/** Pointer to a VFS file handle. */
+typedef RTVFSFILE RT_FAR *PRTVFSFILE;
+/** A NIL VFS file handle. */
+#define NIL_RTVFSFILE ((RTVFSFILE)~(uintptr_t)0)
+
+/** Virtual Filesystem symbolic link handle. */
+typedef struct RTVFSSYMLINKINTERNAL RT_FAR *RTVFSSYMLINK;
+/** Pointer to a VFS symbolic link handle. */
+typedef RTVFSSYMLINK RT_FAR *PRTVFSSYMLINK;
+/** A NIL VFS symbolic link handle. */
+#define NIL_RTVFSSYMLINK ((RTVFSSYMLINK)~(uintptr_t)0)
+
+/** Async I/O manager handle. */
+typedef struct RTAIOMGRINT RT_FAR *RTAIOMGR;
+/** Pointer to a async I/O manager handle. */
+typedef RTAIOMGR RT_FAR *PRTAIOMGR;
+/** A NIL async I/O manager handle. */
+#define NIL_RTAIOMGR ((RTAIOMGR)~(uintptr_t)0)
+
+/** Async I/O manager file handle. */
+typedef struct RTAIOMGRFILEINT RT_FAR *RTAIOMGRFILE;
+/** Pointer to a async I/O manager file handle. */
+typedef RTAIOMGRFILE RT_FAR *PRTAIOMGRFILE;
+/** A NIL async I/O manager file handle. */
+#define NIL_RTAIOMGRFILE ((RTAIOMGRFILE)~(uintptr_t)0)
+
+/** Kernel module information record handle. */
+typedef struct RTKRNLMODINFOINT RT_FAR *RTKRNLMODINFO;
+/** Pointer to a kernel information record handle. */
+typedef RTKRNLMODINFO RT_FAR *PRTKRNLMODINFO;
+/** A NIL kernel module information record handle. */
+#define NIL_RTKRNLMODINFO ((RTKRNLMODINFO)~(uintptr_t)0);
+
+/** Shared memory object handle. */
+typedef struct RTSHMEMINT RT_FAR *RTSHMEM;
+/** Pointer to a shared memory object handle. */
+typedef RTSHMEM RT_FAR *PRTSHMEM;
+/** A NIL shared memory object handle. */
+#define NIL_RTSHMEM ((RTSHMEM)~(uintptr_t)0)
+
+/** EFI signature database handle. */
+typedef struct RTEFISIGDBINT RT_FAR *RTEFISIGDB;
+/** Pointer to a EFI signature database handle. */
+typedef RTEFISIGDB RT_FAR *PRTEFISIGDB;
+/** A NIL EFI signature database handle. */
+#define NIL_RTEFISIGDB ((RTEFISIGDB)~(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 RT_FAR *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 RT_FAR *PRTHANDLEUNION;
+/** Pointer to a const handle union. */
+typedef RTHANDLEUNION const RT_FAR *PCRTHANDLEUNION;
+
+/**
+ * Generic handle.
+ */
+typedef struct RTHANDLE
+{
+ /** The handle type. */
+ RTHANDLETYPE enmType;
+ /** The handle value. */
+ RTHANDLEUNION u;
+} RTHANDLE;
+/** Pointer to a generic handle. */
+typedef RTHANDLE RT_FAR *PRTHANDLE;
+/** Pointer to a const generic handle. */
+typedef RTHANDLE const RT_FAR *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 RT_FAR *PRTERRINFO;
+/** Pointer to a const error info structure. */
+typedef RTERRINFO const RT_FAR *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 RT_FAR *PRTERRINFOSTATIC;
+/** Pointer to a const static error info buffer. */
+typedef RTERRINFOSTATIC const RT_FAR *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 RT_FAR *PRTUUID;
+/** Pointer to readonly UUID data. */
+typedef const RTUUID RT_FAR *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 RT_FAR *PRTZIPCOMP;
+/** Decompressor handle. */
+typedef struct RTZIPDECOMP RT_FAR *PRTZIPDECOMP;
+
+
+/**
+ * Unicode Code Point.
+ */
+typedef uint32_t RTUNICP;
+/** Pointer to an Unicode Code Point. */
+typedef RTUNICP RT_FAR *PRTUNICP;
+/** Pointer to an Unicode Code Point. */
+typedef const RTUNICP RT_FAR *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 RT_FAR *PRTUTF16;
+/** Pointer to a const UTF-16 character. */
+typedef const RTUTF16 RT_FAR *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 RT_FAR *PRTSTRTUPLE;
+/** Pointer to a const string tuple. */
+typedef RTSTRTUPLE const RT_FAR *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 DECLCALLBACKTYPE(int, FNRTPROGRESS,(unsigned uPercentage, 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 DECLCALLBACKTYPE(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 RT_FAR *PRTPOINT;
+/** Pointer to a const point. */
+typedef const RTPOINT RT_FAR *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 RT_FAR *PRTRECT;
+/** Pointer to a const double point rectangle. */
+typedef const RTRECT RT_FAR *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 RT_FAR *PRTRECT2;
+/** Pointer to a const point + size rectangle. */
+typedef const RTRECT2 RT_FAR *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 RT_FAR *PRTRECTSIZE;
+/** Pointer to a const rectangle size. */
+typedef const RTRECTSIZE RT_FAR *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 RT_FAR *PRTMAC;
+/** Pointer to a readonly MAC address. */
+typedef const RTMAC RT_FAR *PCRTMAC;
+
+
+/** Pointer to a lock validator record.
+ * The structure definition is found in iprt/lockvalidator.h. */
+typedef struct RTLOCKVALRECEXCL RT_FAR *PRTLOCKVALRECEXCL;
+/** Pointer to a record of one ownership share.
+ * The structure definition is found in iprt/lockvalidator.h. */
+typedef struct RTLOCKVALRECSHRD RT_FAR *PRTLOCKVALRECSHRD;
+/** Pointer to a lock validator source position.
+ * The structure definition is found in iprt/lockvalidator.h. */
+typedef struct RTLOCKVALSRCPOS RT_FAR *PRTLOCKVALSRCPOS;
+/** Pointer to a const lock validator source position.
+ * The structure definition is found in iprt/lockvalidator.h. */
+typedef struct RTLOCKVALSRCPOS const RT_FAR *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,
+ /** SHA3-224 checksum. */
+ RTDIGESTTYPE_SHA3_224,
+ /** SHA3-256 checksum. */
+ RTDIGESTTYPE_SHA3_256,
+ /** SHA3-384 checksum. */
+ RTDIGESTTYPE_SHA3_384,
+ /** SHA3-512 checksum. */
+ RTDIGESTTYPE_SHA3_512,
+#if 0
+ /** SHAKE128 checksum. */
+ RTDIGESTTYPE_SHAKE128,
+ /** SHAKE256 checksum. */
+ RTDIGESTTYPE_SHAKE256,
+#endif
+ /** 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 RT_FAR *PRTRANGE;
+/** Pointer to a readonly range descriptor. */
+typedef const RTRANGE RT_FAR *PCRTRANGE;
+
+
+/**
+ * Generic pointer union.
+ */
+typedef union RTPTRUNION
+{
+ /** Pointer into the void. */
+ void RT_FAR *pv;
+ /** As a signed integer. */
+ intptr_t i;
+ /** As an unsigned integer. */
+ uintptr_t u;
+ /** Pointer to char value. */
+ char RT_FAR *pch;
+ /** Pointer to char value. */
+ unsigned char RT_FAR *puch;
+ /** Pointer to a int value. */
+ int RT_FAR *pi;
+ /** Pointer to a unsigned int value. */
+ unsigned int RT_FAR *pu;
+ /** Pointer to a long value. */
+ long RT_FAR *pl;
+ /** Pointer to a long value. */
+ unsigned long RT_FAR *pul;
+ /** Pointer to a 8-bit unsigned value. */
+ uint8_t RT_FAR *pu8;
+ /** Pointer to a 16-bit unsigned value. */
+ uint16_t RT_FAR *pu16;
+ /** Pointer to a 32-bit unsigned value. */
+ uint32_t RT_FAR *pu32;
+ /** Pointer to a 64-bit unsigned value. */
+ uint64_t RT_FAR *pu64;
+ /** Pointer to a 8-bit signed value. */
+ int8_t RT_FAR *pi8;
+ /** Pointer to a 16-bit signed value. */
+ int16_t RT_FAR *pi16;
+ /** Pointer to a 32-bit signed value. */
+ int32_t RT_FAR *pi32;
+ /** Pointer to a 64-bit signed value. */
+ int64_t RT_FAR *pi64;
+ /** Pointer to a UTF-16 character. */
+ PRTUTF16 pwc;
+ /** Pointer to a UUID character. */
+ PRTUUID pUuid;
+} RTPTRUNION;
+/** Pointer to a pointer union. */
+typedef RTPTRUNION RT_FAR *PRTPTRUNION;
+
+/**
+ * Generic const pointer union.
+ */
+typedef union RTCPTRUNION
+{
+ /** Pointer into the void. */
+ void const RT_FAR *pv;
+ /** As a signed integer. */
+ intptr_t i;
+ /** As an unsigned integer. */
+ uintptr_t u;
+ /** Pointer to char value. */
+ char const RT_FAR *pch;
+ /** Pointer to char value. */
+ unsigned char const RT_FAR *puch;
+ /** Pointer to a int value. */
+ int const RT_FAR *pi;
+ /** Pointer to a unsigned int value. */
+ unsigned int const RT_FAR *pu;
+ /** Pointer to a long value. */
+ long const RT_FAR *pl;
+ /** Pointer to a long value. */
+ unsigned long const RT_FAR *pul;
+ /** Pointer to a 8-bit unsigned value. */
+ uint8_t const RT_FAR *pu8;
+ /** Pointer to a 16-bit unsigned value. */
+ uint16_t const RT_FAR *pu16;
+ /** Pointer to a 32-bit unsigned value. */
+ uint32_t const RT_FAR *pu32;
+ /** Pointer to a 64-bit unsigned value. */
+ uint64_t const RT_FAR *pu64;
+ /** Pointer to a 8-bit signed value. */
+ int8_t const RT_FAR *pi8;
+ /** Pointer to a 16-bit signed value. */
+ int16_t const RT_FAR *pi16;
+ /** Pointer to a 32-bit signed value. */
+ int32_t const RT_FAR *pi32;
+ /** Pointer to a 64-bit signed value. */
+ int64_t const RT_FAR *pi64;
+ /** Pointer to a UTF-16 character. */
+ PCRTUTF16 pwc;
+ /** Pointer to a UUID character. */
+ PCRTUUID pUuid;
+} RTCPTRUNION;
+/** Pointer to a const pointer union. */
+typedef RTCPTRUNION RT_FAR *PRTCPTRUNION;
+
+/**
+ * Generic volatile pointer union.
+ */
+typedef union RTVPTRUNION
+{
+ /** Pointer into the void. */
+ void volatile RT_FAR *pv;
+ /** As a signed integer. */
+ intptr_t i;
+ /** As an unsigned integer. */
+ uintptr_t u;
+ /** Pointer to char value. */
+ char volatile RT_FAR *pch;
+ /** Pointer to char value. */
+ unsigned char volatile RT_FAR *puch;
+ /** Pointer to a int value. */
+ int volatile RT_FAR *pi;
+ /** Pointer to a unsigned int value. */
+ unsigned int volatile RT_FAR *pu;
+ /** Pointer to a long value. */
+ long volatile RT_FAR *pl;
+ /** Pointer to a long value. */
+ unsigned long volatile RT_FAR *pul;
+ /** Pointer to a 8-bit unsigned value. */
+ uint8_t volatile RT_FAR *pu8;
+ /** Pointer to a 16-bit unsigned value. */
+ uint16_t volatile RT_FAR *pu16;
+ /** Pointer to a 32-bit unsigned value. */
+ uint32_t volatile RT_FAR *pu32;
+ /** Pointer to a 64-bit unsigned value. */
+ uint64_t volatile RT_FAR *pu64;
+ /** Pointer to a 8-bit signed value. */
+ int8_t volatile RT_FAR *pi8;
+ /** Pointer to a 16-bit signed value. */
+ int16_t volatile RT_FAR *pi16;
+ /** Pointer to a 32-bit signed value. */
+ int32_t volatile RT_FAR *pi32;
+ /** Pointer to a 64-bit signed value. */
+ int64_t volatile RT_FAR *pi64;
+ /** Pointer to a UTF-16 character. */
+ RTUTF16 volatile RT_FAR *pwc;
+ /** Pointer to a UUID character. */
+ RTUUID volatile RT_FAR *pUuid;
+} RTVPTRUNION;
+/** Pointer to a const pointer union. */
+typedef RTVPTRUNION RT_FAR *PRTVPTRUNION;
+
+/**
+ * Generic const volatile pointer union.
+ */
+typedef union RTCVPTRUNION
+{
+ /** Pointer into the void. */
+ void const volatile RT_FAR *pv;
+ /** As a signed integer. */
+ intptr_t i;
+ /** As an unsigned integer. */
+ uintptr_t u;
+ /** Pointer to char value. */
+ char const volatile RT_FAR *pch;
+ /** Pointer to char value. */
+ unsigned char const volatile RT_FAR *puch;
+ /** Pointer to a int value. */
+ int const volatile RT_FAR *pi;
+ /** Pointer to a unsigned int value. */
+ unsigned int const volatile RT_FAR *pu;
+ /** Pointer to a long value. */
+ long const volatile RT_FAR *pl;
+ /** Pointer to a long value. */
+ unsigned long const volatile RT_FAR *pul;
+ /** Pointer to a 8-bit unsigned value. */
+ uint8_t const volatile RT_FAR *pu8;
+ /** Pointer to a 16-bit unsigned value. */
+ uint16_t const volatile RT_FAR *pu16;
+ /** Pointer to a 32-bit unsigned value. */
+ uint32_t const volatile RT_FAR *pu32;
+ /** Pointer to a 64-bit unsigned value. */
+ uint64_t const volatile RT_FAR *pu64;
+ /** Pointer to a 8-bit signed value. */
+ int8_t const volatile RT_FAR *pi8;
+ /** Pointer to a 16-bit signed value. */
+ int16_t const volatile RT_FAR *pi16;
+ /** Pointer to a 32-bit signed value. */
+ int32_t const volatile RT_FAR *pi32;
+ /** Pointer to a 64-bit signed value. */
+ int64_t const volatile RT_FAR *pi64;
+ /** Pointer to a UTF-16 character. */
+ RTUTF16 const volatile RT_FAR *pwc;
+ /** Pointer to a UUID character. */
+ RTUUID const volatile RT_FAR *pUuid;
+} RTCVPTRUNION;
+/** Pointer to a const pointer union. */
+typedef RTCVPTRUNION RT_FAR *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 */
+/** @} */
+
+#define IPRT_COMPLETED_types_h /* hack for watcom and nocrt headers depending on this one. */
+#endif /* !IPRT_INCLUDED_types_h */
+
diff --git a/include/iprt/udp.h b/include/iprt/udp.h
new file mode 100644
index 00000000..d06a2388
--- /dev/null
+++ b/include/iprt/udp.h
@@ -0,0 +1,191 @@
+/** @file
+ * IPRT - UDP/IP.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_udp_h
+#define IPRT_INCLUDED_udp_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+#include <iprt/thread.h>
+#include <iprt/net.h>
+#include <iprt/sg.h>
+#include <iprt/socket.h>
+
+#ifdef IN_RING0
+# error "There are no RTFile APIs available Ring-0 Host Context!"
+#endif
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_udp RTUdp - UDP/IP
+ * @ingroup grp_rt
+ * @{
+ */
+
+
+/**
+ * Handle incoming UDP datagrams.
+ *
+ * @returns iprt status code.
+ * @returns VERR_UDP_SERVER_STOP to terminate the server loop forcing
+ * the RTUdpCreateServer() call to return.
+ * @param Sock The socket on which the datagram needs to be received.
+ * @param pvUser User argument.
+ */
+typedef DECLCALLBACKTYPE(int, FNRTUDPSERVE,(RTSOCKET Sock, void *pvUser));
+/** Pointer to a RTUDPSERVE(). */
+typedef FNRTUDPSERVE *PFNRTUDPSERVE;
+
+/**
+ * Create single datagram at a time UDP Server in a separate thread.
+ *
+ * The thread will loop accepting datagrams and call pfnServe for
+ * each of the incoming datagrams in turn. The pfnServe function can
+ * return VERR_UDP_SERVER_STOP too terminate this loop. RTUdpServerDestroy()
+ * should be used to terminate the server.
+ *
+ * @returns iprt status code.
+ * @param pszAddress The address for creating a datagram socket.
+ * If NULL or empty string the server is bound to all interfaces.
+ * @param uPort The port for creating a datagram socket.
+ * @param enmType The thread type.
+ * @param pszThrdName The name of the worker thread.
+ * @param pfnServe The function which will handle incoming datagrams.
+ * @param pvUser User argument passed to pfnServe.
+ * @param ppServer Where to store the serverhandle.
+ */
+RTR3DECL(int) RTUdpServerCreate(const char *pszAddress, unsigned uPort, RTTHREADTYPE enmType, const char *pszThrdName,
+ PFNRTUDPSERVE pfnServe, void *pvUser, PPRTUDPSERVER ppServer);
+
+/**
+ * Create single datagram at a time UDP Server.
+ * The caller must call RTUdpServerReceive() to actually start the server.
+ *
+ * @returns iprt status code.
+ * @param pszAddress The address for creating a datagram socket.
+ * If NULL the server is bound to all interfaces.
+ * @param uPort The port for creating a datagram socket.
+ * @param ppServer Where to store the serverhandle.
+ */
+RTR3DECL(int) RTUdpServerCreateEx(const char *pszAddress, uint32_t uPort, PPRTUDPSERVER ppServer);
+
+/**
+ * Shuts down the server.
+ *
+ * @returns IPRT status code.
+ * @param pServer Handle to the server.
+ */
+RTR3DECL(int) RTUdpServerShutdown(PRTUDPSERVER pServer);
+
+/**
+ * Closes down and frees a UDP Server.
+ *
+ * @returns iprt status code.
+ * @param pServer Handle to the server.
+ */
+RTR3DECL(int) RTUdpServerDestroy(PRTUDPSERVER pServer);
+
+/**
+ * Listen for incoming datagrams.
+ *
+ * The function will loop waiting for datagrams and call pfnServe for
+ * each of the incoming datagrams in turn. The pfnServe function can
+ * return VERR_UDP_SERVER_STOP too terminate this loop. A stopped server
+ * can only be destroyed.
+ *
+ * @returns iprt status code.
+ * @param pServer The server handle as returned from RTUdpServerCreateEx().
+ * @param pfnServe The function which will handle incoming datagrams.
+ * @param pvUser User argument passed to pfnServe.
+ */
+RTR3DECL(int) RTUdpServerListen(PRTUDPSERVER pServer, PFNRTUDPSERVE pfnServe, void *pvUser);
+
+/**
+ * Receive data from a socket.
+ *
+ * @returns iprt status code.
+ * @param Sock Socket descriptor.
+ * @param pvBuffer Where to put the data we read.
+ * @param cbBuffer Read buffer size.
+ * @param pcbRead Number of bytes read. Must be non-NULL.
+ * @param pSrcAddr The network address to read from.
+ */
+RTR3DECL(int) RTUdpRead(RTSOCKET Sock, void *pvBuffer, size_t cbBuffer, size_t *pcbRead, PRTNETADDR pSrcAddr);
+
+/**
+ * Send data to a socket.
+ *
+ * @returns iprt status code.
+ * @retval VERR_INTERRUPTED if interrupted before anything was written.
+ *
+ * @param pServer Handle to the server.
+ * @param pvBuffer Buffer to write data to socket.
+ * @param cbBuffer How much to write.
+ * @param pDstAddr Destination address.
+ */
+RTR3DECL(int) RTUdpWrite(PRTUDPSERVER pServer, const void *pvBuffer,
+ size_t cbBuffer, PCRTNETADDR pDstAddr);
+
+/**
+ * Create and connect a data socket.
+ *
+ * @returns iprt status code.
+ * @param pszAddress The address to connect to.
+ * @param uPort The port to connect to.
+ * @param pLocalAddr The local address to bind this socket to, can be
+ * NULL.
+ * @param pSock Where to store the handle to the established connection.
+ */
+RTR3DECL(int) RTUdpCreateClientSocket(const char *pszAddress, uint32_t uPort, PRTNETADDR pLocalAddr, PRTSOCKET pSock);
+
+/**
+ * Create a data socket acting as a server.
+ *
+ * @returns iprt status code.
+ * @param pszAddress The address to connect to.
+ * @param uPort The port to connect to.
+ * @param pSock Where to store the handle to the established connection.
+ */
+RTR3DECL(int) RTUdpCreateServerSocket(const char *pszAddress, uint32_t uPort, PRTSOCKET pSock);
+
+/** @} */
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_udp_h */
+
diff --git a/include/iprt/uint128.h b/include/iprt/uint128.h
new file mode 100644
index 00000000..50b19055
--- /dev/null
+++ b/include/iprt/uint128.h
@@ -0,0 +1,1479 @@
+/** @file
+ * IPRT - RTUINT128U & uint128_t methods.
+ */
+
+/*
+ * Copyright (C) 2011-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_uint128_h
+#define IPRT_INCLUDED_uint128_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+#include <iprt/asm.h>
+#include <iprt/asm-math.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_uint128 RTUInt128 - 128-bit Unsigned Integer Methods
+ * @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) RTUInt128IsZero(PCRTUINT128U pValue)
+{
+#if ARCH_BITS >= 64
+ return pValue->s.Hi == 0
+ && pValue->s.Lo == 0;
+#else
+ return pValue->DWords.dw0 == 0
+ && pValue->DWords.dw1 == 0
+ && pValue->DWords.dw2 == 0
+ && pValue->DWords.dw3 == 0;
+#endif
+}
+
+
+/**
+ * Set a 128-bit unsigned integer value to zero.
+ *
+ * @returns pResult
+ * @param pResult The result variable.
+ */
+DECLINLINE(PRTUINT128U) RTUInt128SetZero(PRTUINT128U pResult)
+{
+#if ARCH_BITS >= 64
+ pResult->s.Hi = 0;
+ pResult->s.Lo = 0;
+#else
+ pResult->DWords.dw0 = 0;
+ pResult->DWords.dw1 = 0;
+ pResult->DWords.dw2 = 0;
+ pResult->DWords.dw3 = 0;
+#endif
+ return pResult;
+}
+
+
+/**
+ * Set a 128-bit unsigned integer value to the maximum value.
+ *
+ * @returns pResult
+ * @param pResult The result variable.
+ */
+DECLINLINE(PRTUINT128U) RTUInt128SetMax(PRTUINT128U pResult)
+{
+#if ARCH_BITS >= 64
+ pResult->s.Hi = UINT64_MAX;
+ pResult->s.Lo = UINT64_MAX;
+#else
+ pResult->DWords.dw0 = UINT32_MAX;
+ pResult->DWords.dw1 = UINT32_MAX;
+ pResult->DWords.dw2 = UINT32_MAX;
+ pResult->DWords.dw3 = UINT32_MAX;
+#endif
+ return pResult;
+}
+
+
+
+
+/**
+ * Adds two 128-bit unsigned integer values.
+ *
+ * @returns pResult
+ * @param pResult The result variable.
+ * @param pValue1 The first value.
+ * @param pValue2 The second value.
+ */
+DECLINLINE(PRTUINT128U) RTUInt128Add(PRTUINT128U pResult, PCRTUINT128U pValue1, PCRTUINT128U 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 128-bit and a 64-bit unsigned integer values.
+ *
+ * @returns pResult
+ * @param pResult The result variable.
+ * @param pValue1 The first value.
+ * @param uValue2 The second value, 64-bit.
+ */
+DECLINLINE(PRTUINT128U) RTUInt128AddU64(PRTUINT128U pResult, PCRTUINT128U pValue1, uint64_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 128-bit unsigned integer value from another.
+ *
+ * @returns pResult
+ * @param pResult The result variable.
+ * @param pValue1 The minuend value.
+ * @param pValue2 The subtrahend value.
+ */
+DECLINLINE(PRTUINT128U) RTUInt128Sub(PRTUINT128U pResult, PCRTUINT128U pValue1, PCRTUINT128U 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 128-bit unsigned integer values.
+ *
+ * @returns pResult
+ * @param pResult The result variable.
+ * @param pValue1 The first value.
+ * @param pValue2 The second value.
+ */
+DECLINLINE(PRTUINT128U) RTUInt128Mul(PRTUINT128U pResult, PCRTUINT128U pValue1, PCRTUINT128U pValue2)
+{
+ RTUINT64U uTmp;
+
+ /* multiply all dwords in v1 by v2.dw0. */
+ pResult->s.Lo = (uint64_t)pValue1->DWords.dw0 * pValue2->DWords.dw0;
+
+ uTmp.u = (uint64_t)pValue1->DWords.dw1 * pValue2->DWords.dw0;
+ pResult->DWords.dw3 = 0;
+ pResult->DWords.dw2 = uTmp.DWords.dw1;
+ pResult->DWords.dw1 += uTmp.DWords.dw0;
+ if (pResult->DWords.dw1 < uTmp.DWords.dw0)
+ if (pResult->DWords.dw2++ == UINT32_MAX)
+ pResult->DWords.dw3++;
+
+ pResult->s.Hi += (uint64_t)pValue1->DWords.dw2 * pValue2->DWords.dw0;
+ pResult->DWords.dw3 += pValue1->DWords.dw3 * pValue2->DWords.dw0;
+
+ /* multiply dw0, dw1 & dw2 in v1 by v2.dw1. */
+ uTmp.u = (uint64_t)pValue1->DWords.dw0 * pValue2->DWords.dw1;
+ pResult->DWords.dw1 += uTmp.DWords.dw0;
+ if (pResult->DWords.dw1 < uTmp.DWords.dw0)
+ if (pResult->DWords.dw2++ == UINT32_MAX)
+ pResult->DWords.dw3++;
+
+ pResult->DWords.dw2 += uTmp.DWords.dw1;
+ if (pResult->DWords.dw2 < uTmp.DWords.dw1)
+ pResult->DWords.dw3++;
+
+ pResult->s.Hi += (uint64_t)pValue1->DWords.dw1 * pValue2->DWords.dw1;
+ pResult->DWords.dw3 += pValue1->DWords.dw2 * pValue2->DWords.dw1;
+
+ /* multiply dw0 & dw1 in v1 by v2.dw2. */
+ pResult->s.Hi += (uint64_t)pValue1->DWords.dw0 * pValue2->DWords.dw2;
+ pResult->DWords.dw3 += pValue1->DWords.dw1 * pValue2->DWords.dw2;
+
+ /* multiply dw0 in v1 by v2.dw3. */
+ pResult->DWords.dw3 += pValue1->DWords.dw0 * pValue2->DWords.dw3;
+
+ return pResult;
+}
+
+
+/**
+ * Multiplies an 128-bit unsigned integer by a 64-bit unsigned integer value.
+ *
+ * @returns pResult
+ * @param pResult The result variable.
+ * @param pValue1 The first value.
+ * @param uValue2 The second value, 64-bit.
+ */
+#if defined(RT_ARCH_AMD64)
+RTDECL(PRTUINT128U) RTUInt128MulByU64(PRTUINT128U pResult, PCRTUINT128U pValue1, uint64_t uValue2);
+#else
+DECLINLINE(PRTUINT128U) RTUInt128MulByU64(PRTUINT128U pResult, PCRTUINT128U pValue1, uint64_t uValue2)
+{
+ uint32_t const uLoValue2 = (uint32_t)uValue2;
+ uint32_t const uHiValue2 = (uint32_t)(uValue2 >> 32);
+ RTUINT64U uTmp;
+
+ /* multiply all dwords in v1 by uLoValue1. */
+ pResult->s.Lo = (uint64_t)pValue1->DWords.dw0 * uLoValue2;
+
+ uTmp.u = (uint64_t)pValue1->DWords.dw1 * uLoValue2;
+ pResult->DWords.dw3 = 0;
+ pResult->DWords.dw2 = uTmp.DWords.dw1;
+ pResult->DWords.dw1 += uTmp.DWords.dw0;
+ if (pResult->DWords.dw1 < uTmp.DWords.dw0)
+ if (pResult->DWords.dw2++ == UINT32_MAX)
+ pResult->DWords.dw3++;
+
+ pResult->s.Hi += (uint64_t)pValue1->DWords.dw2 * uLoValue2;
+ pResult->DWords.dw3 += pValue1->DWords.dw3 * uLoValue2;
+
+ /* multiply dw0, dw1 & dw2 in v1 by uHiValue2. */
+ uTmp.u = (uint64_t)pValue1->DWords.dw0 * uHiValue2;
+ pResult->DWords.dw1 += uTmp.DWords.dw0;
+ if (pResult->DWords.dw1 < uTmp.DWords.dw0)
+ if (pResult->DWords.dw2++ == UINT32_MAX)
+ pResult->DWords.dw3++;
+
+ pResult->DWords.dw2 += uTmp.DWords.dw1;
+ if (pResult->DWords.dw2 < uTmp.DWords.dw1)
+ pResult->DWords.dw3++;
+
+ pResult->s.Hi += (uint64_t)pValue1->DWords.dw1 * uHiValue2;
+ pResult->DWords.dw3 += pValue1->DWords.dw2 * uHiValue2;
+
+ return pResult;
+}
+#endif
+
+
+/**
+ * Multiplies two 64-bit unsigned integer values with 128-bit precision.
+ *
+ * @returns pResult
+ * @param pResult The result variable.
+ * @param uValue1 The first value. 64-bit.
+ * @param uValue2 The second value, 64-bit.
+ */
+DECLINLINE(PRTUINT128U) RTUInt128MulU64ByU64(PRTUINT128U pResult, uint64_t uValue1, uint64_t uValue2)
+{
+#ifdef RT_ARCH_AMD64
+ pResult->s.Lo = ASMMult2xU64Ret2xU64(uValue1, uValue2, &pResult->s.Hi);
+#else
+ uint32_t const uLoValue1 = (uint32_t)uValue1;
+ uint32_t const uHiValue1 = (uint32_t)(uValue1 >> 32);
+ uint32_t const uLoValue2 = (uint32_t)uValue2;
+ uint32_t const uHiValue2 = (uint32_t)(uValue2 >> 32);
+ RTUINT64U uTmp;
+
+ /* Multiply uLoValue1 and uHiValue1 by uLoValue1. */
+ pResult->s.Lo = (uint64_t)uLoValue1 * uLoValue2;
+
+ uTmp.u = (uint64_t)uHiValue1 * uLoValue2;
+ pResult->DWords.dw3 = 0;
+ pResult->DWords.dw2 = uTmp.DWords.dw1;
+ pResult->DWords.dw1 += uTmp.DWords.dw0;
+ if (pResult->DWords.dw1 < uTmp.DWords.dw0)
+ if (pResult->DWords.dw2++ == UINT32_MAX)
+ pResult->DWords.dw3++;
+
+ /* Multiply uLoValue1 and uHiValue1 by uHiValue2. */
+ uTmp.u = (uint64_t)uLoValue1 * uHiValue2;
+ pResult->DWords.dw1 += uTmp.DWords.dw0;
+ if (pResult->DWords.dw1 < uTmp.DWords.dw0)
+ if (pResult->DWords.dw2++ == UINT32_MAX)
+ pResult->DWords.dw3++;
+
+ pResult->DWords.dw2 += uTmp.DWords.dw1;
+ if (pResult->DWords.dw2 < uTmp.DWords.dw1)
+ pResult->DWords.dw3++;
+
+ pResult->s.Hi += (uint64_t)uHiValue1 * uHiValue2;
+#endif
+ return pResult;
+}
+
+
+/**
+ * Multiplies an 128-bit unsigned integer by a 64-bit unsigned integer value,
+ * returning a 256-bit result (top 64 bits are zero).
+ *
+ * @returns pResult
+ * @param pResult The result variable.
+ * @param pValue1 The first value.
+ * @param uValue2 The second value, 64-bit.
+ */
+#if defined(RT_ARCH_AMD64)
+RTDECL(PRTUINT256U) RTUInt128MulByU64Ex(PRTUINT256U pResult, PCRTUINT128U pValue1, uint64_t uValue2);
+#else
+DECLINLINE(PRTUINT256U) RTUInt128MulByU64Ex(PRTUINT256U pResult, PCRTUINT128U pValue1, uint64_t uValue2)
+{
+ /* multiply the two qwords in pValue1 by uValue2. */
+ uint64_t uTmp = 0;
+ pResult->QWords.qw0 = ASMMult2xU64Ret2xU64(pValue1->s.Lo, uValue2, &uTmp);
+ pResult->QWords.qw1 = ASMMult2xU64Ret2xU64(pValue1->s.Hi, uValue2, &pResult->QWords.qw2);
+ pResult->QWords.qw3 = 0;
+ pResult->QWords.qw1 += uTmp;
+ if (pResult->QWords.qw1 < uTmp)
+ pResult->QWords.qw2++; /* This cannot overflow AFAIK: 0xffff*0xffff = 0xFFFE0001 */
+
+ return pResult;
+}
+#endif
+
+
+/**
+ * Multiplies two 128-bit unsigned integer values, returning a 256-bit result.
+ *
+ * @returns pResult
+ * @param pResult The result variable.
+ * @param pValue1 The first value.
+ * @param pValue2 The second value.
+ */
+DECLINLINE(PRTUINT256U) RTUInt128MulEx(PRTUINT256U pResult, PCRTUINT128U pValue1, PCRTUINT128U pValue2)
+{
+ RTUInt128MulByU64Ex(pResult, pValue1, pValue2->s.Lo);
+ if (pValue2->s.Hi)
+ {
+ /* Multiply the two qwords in pValue1 by the high part of uValue2. */
+ uint64_t uTmpHi = 0;
+ uint64_t uTmpLo = ASMMult2xU64Ret2xU64(pValue1->s.Lo, pValue2->s.Hi, &uTmpHi);
+ pResult->QWords.qw1 += uTmpLo;
+ if (pResult->QWords.qw1 < uTmpLo)
+ if (++pResult->QWords.qw2 == 0)
+ pResult->QWords.qw3++; /* (cannot overflow, was == 0) */
+ pResult->QWords.qw2 += uTmpHi;
+ if (pResult->QWords.qw2 < uTmpHi)
+ pResult->QWords.qw3++; /* (cannot overflow, was <= 1) */
+
+ uTmpLo = ASMMult2xU64Ret2xU64(pValue1->s.Hi, pValue2->s.Hi, &uTmpHi);
+ pResult->QWords.qw2 += uTmpLo;
+ if (pResult->QWords.qw2 < uTmpLo)
+ pResult->QWords.qw3++; /* (cannot overflow, was <= 2) */
+ pResult->QWords.qw3 += uTmpHi;
+ }
+
+ return pResult;
+}
+
+
+DECLINLINE(PRTUINT128U) RTUInt128DivRem(PRTUINT128U pQuotient, PRTUINT128U pRemainder, PCRTUINT128U pValue1, PCRTUINT128U pValue2);
+
+/**
+ * Divides a 128-bit unsigned integer value by another.
+ *
+ * @returns pResult
+ * @param pResult The result variable.
+ * @param pValue1 The dividend value.
+ * @param pValue2 The divisor value.
+ */
+DECLINLINE(PRTUINT128U) RTUInt128Div(PRTUINT128U pResult, PCRTUINT128U pValue1, PCRTUINT128U pValue2)
+{
+ RTUINT128U Ignored;
+ return RTUInt128DivRem(pResult, &Ignored, pValue1, pValue2);
+}
+
+
+/**
+ * Divides a 128-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(PRTUINT128U) RTUInt128Mod(PRTUINT128U pResult, PCRTUINT128U pValue1, PCRTUINT128U pValue2)
+{
+ RTUINT128U Ignored;
+ RTUInt128DivRem(&Ignored, pResult, pValue1, pValue2);
+ return pResult;
+}
+
+
+/**
+ * Bitwise AND of two 128-bit unsigned integer values.
+ *
+ * @returns pResult
+ * @param pResult The result variable.
+ * @param pValue1 The first value.
+ * @param pValue2 The second value.
+ */
+DECLINLINE(PRTUINT128U) RTUInt128And(PRTUINT128U pResult, PCRTUINT128U pValue1, PCRTUINT128U 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 128-bit unsigned integer values.
+ *
+ * @returns pResult
+ * @param pResult The result variable.
+ * @param pValue1 The first value.
+ * @param pValue2 The second value.
+ */
+DECLINLINE(PRTUINT128U) RTUInt128Or( PRTUINT128U pResult, PCRTUINT128U pValue1, PCRTUINT128U 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 128-bit unsigned integer values.
+ *
+ * @returns pResult
+ * @param pResult The result variable.
+ * @param pValue1 The first value.
+ * @param pValue2 The second value.
+ */
+DECLINLINE(PRTUINT128U) RTUInt128Xor(PRTUINT128U pResult, PCRTUINT128U pValue1, PCRTUINT128U pValue2)
+{
+ pResult->s.Hi = pValue1->s.Hi ^ pValue2->s.Hi;
+ pResult->s.Lo = pValue1->s.Lo ^ pValue2->s.Lo;
+ return pResult;
+}
+
+
+/**
+ * Shifts a 128-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(PRTUINT128U) RTUInt128ShiftLeft(PRTUINT128U pResult, PCRTUINT128U pValue, int cBits)
+{
+ cBits &= 127;
+ if (cBits < 64)
+ {
+ pResult->s.Lo = pValue->s.Lo << cBits;
+ pResult->s.Hi = (pValue->s.Hi << cBits) | (pValue->s.Lo >> (64 - cBits));
+ }
+ else
+ {
+ pResult->s.Lo = 0;
+ pResult->s.Hi = pValue->s.Lo << (cBits - 64);
+ }
+ return pResult;
+}
+
+
+/**
+ * Shifts a 128-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(PRTUINT128U) RTUInt128ShiftRight(PRTUINT128U pResult, PCRTUINT128U pValue, int cBits)
+{
+ cBits &= 127;
+ if (cBits < 64)
+ {
+ pResult->s.Hi = pValue->s.Hi >> cBits;
+ pResult->s.Lo = (pValue->s.Lo >> cBits) | (pValue->s.Hi << (64 - cBits));
+ }
+ else
+ {
+ pResult->s.Hi = 0;
+ pResult->s.Lo = pValue->s.Hi >> (cBits - 64);
+ }
+ return pResult;
+}
+
+
+/**
+ * Boolean not (result 0 or 1).
+ *
+ * @returns pResult.
+ * @param pResult The result variable.
+ * @param pValue The value.
+ */
+DECLINLINE(PRTUINT128U) RTUInt128BooleanNot(PRTUINT128U pResult, PCRTUINT128U 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 128 bits).
+ *
+ * @returns pResult.
+ * @param pResult The result variable.
+ * @param pValue The value.
+ */
+DECLINLINE(PRTUINT128U) RTUInt128BitwiseNot(PRTUINT128U pResult, PCRTUINT128U pValue)
+{
+ pResult->s.Hi = ~pValue->s.Hi;
+ pResult->s.Lo = ~pValue->s.Lo;
+ return pResult;
+}
+
+
+/**
+ * Assigns one 128-bit unsigned integer value to another.
+ *
+ * @returns pResult
+ * @param pResult The result variable.
+ * @param pValue The value to assign.
+ */
+DECLINLINE(PRTUINT128U) RTUInt128Assign(PRTUINT128U pResult, PCRTUINT128U pValue)
+{
+#if ARCH_BITS >= 64
+ pResult->s.Hi = pValue->s.Hi;
+ pResult->s.Lo = pValue->s.Lo;
+#else
+ pResult->DWords.dw0 = pValue->DWords.dw0;
+ pResult->DWords.dw1 = pValue->DWords.dw1;
+ pResult->DWords.dw2 = pValue->DWords.dw2;
+ pResult->DWords.dw3 = pValue->DWords.dw3;
+#endif
+ return pResult;
+}
+
+
+/**
+ * Assigns a boolean value to 128-bit unsigned integer.
+ *
+ * @returns pValueResult
+ * @param pValueResult The result variable.
+ * @param fValue The boolean value.
+ */
+DECLINLINE(PRTUINT128U) RTUInt128AssignBoolean(PRTUINT128U pValueResult, bool fValue)
+{
+#if ARCH_BITS >= 64
+ pValueResult->s.Lo = fValue;
+ pValueResult->s.Hi = 0;
+#else
+ pValueResult->DWords.dw0 = fValue;
+ pValueResult->DWords.dw1 = 0;
+ pValueResult->DWords.dw2 = 0;
+ pValueResult->DWords.dw3 = 0;
+#endif
+ return pValueResult;
+}
+
+
+/**
+ * Assigns a 8-bit unsigned integer value to 128-bit unsigned integer.
+ *
+ * @returns pValueResult
+ * @param pValueResult The result variable.
+ * @param u8Value The 8-bit unsigned integer value.
+ */
+DECLINLINE(PRTUINT128U) RTUInt128AssignU8(PRTUINT128U pValueResult, uint8_t u8Value)
+{
+#if ARCH_BITS >= 64
+ pValueResult->s.Lo = u8Value;
+ pValueResult->s.Hi = 0;
+#else
+ pValueResult->DWords.dw0 = u8Value;
+ pValueResult->DWords.dw1 = 0;
+ pValueResult->DWords.dw2 = 0;
+ pValueResult->DWords.dw3 = 0;
+#endif
+ return pValueResult;
+}
+
+
+/**
+ * Assigns a 16-bit unsigned integer value to 128-bit unsigned integer.
+ *
+ * @returns pValueResult
+ * @param pValueResult The result variable.
+ * @param u16Value The 16-bit unsigned integer value.
+ */
+DECLINLINE(PRTUINT128U) RTUInt128AssignU16(PRTUINT128U pValueResult, uint16_t u16Value)
+{
+#if ARCH_BITS >= 64
+ pValueResult->s.Lo = u16Value;
+ pValueResult->s.Hi = 0;
+#else
+ pValueResult->DWords.dw0 = u16Value;
+ pValueResult->DWords.dw1 = 0;
+ pValueResult->DWords.dw2 = 0;
+ pValueResult->DWords.dw3 = 0;
+#endif
+ return pValueResult;
+}
+
+
+/**
+ * Assigns a 32-bit unsigned integer value to 128-bit unsigned integer.
+ *
+ * @returns pValueResult
+ * @param pValueResult The result variable.
+ * @param u32Value The 32-bit unsigned integer value.
+ */
+DECLINLINE(PRTUINT128U) RTUInt128AssignU32(PRTUINT128U pValueResult, uint32_t u32Value)
+{
+#if ARCH_BITS >= 64
+ pValueResult->s.Lo = u32Value;
+ pValueResult->s.Hi = 0;
+#else
+ pValueResult->DWords.dw0 = u32Value;
+ pValueResult->DWords.dw1 = 0;
+ pValueResult->DWords.dw2 = 0;
+ pValueResult->DWords.dw3 = 0;
+#endif
+ return pValueResult;
+}
+
+
+/**
+ * Assigns a 64-bit unsigned integer value to 128-bit unsigned integer.
+ *
+ * @returns pValueResult
+ * @param pValueResult The result variable.
+ * @param u64Value The 64-bit unsigned integer value.
+ */
+DECLINLINE(PRTUINT128U) RTUInt128AssignU64(PRTUINT128U pValueResult, uint64_t u64Value)
+{
+ pValueResult->s.Lo = u64Value;
+ pValueResult->s.Hi = 0;
+ return pValueResult;
+}
+
+
+/**
+ * Adds two 128-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(PRTUINT128U) RTUInt128AssignAdd(PRTUINT128U pValue1Result, PCRTUINT128U pValue2)
+{
+ uint64_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;
+}
+
+
+/**
+ * Adds a 64-bit unsigned integer value to a 128-bit unsigned integer values,
+ * storing the result in the 128-bit one.
+ *
+ * @returns pValue1Result.
+ * @param pValue1Result The first value and result.
+ * @param uValue2 The second value, 64-bit.
+ */
+DECLINLINE(PRTUINT128U) RTUInt128AssignAddU64(PRTUINT128U pValue1Result, uint64_t uValue2)
+{
+ pValue1Result->s.Lo += uValue2;
+ if (pValue1Result->s.Lo < uValue2)
+ pValue1Result->s.Hi++;
+ return pValue1Result;
+}
+
+
+/**
+ * Subtracts two 128-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(PRTUINT128U) RTUInt128AssignSub(PRTUINT128U pValue1Result, PCRTUINT128U pValue2)
+{
+ uint64_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;
+}
+
+
+/**
+ * Negates a 128 number, storing the result in the input.
+ *
+ * @returns pValueResult.
+ * @param pValueResult The value to negate.
+ */
+DECLINLINE(PRTUINT128U) RTUInt128AssignNeg(PRTUINT128U pValueResult)
+{
+ /* result = 0 - value */
+ if (pValueResult->s.Lo != 0)
+ {
+ pValueResult->s.Lo = UINT64_C(0) - pValueResult->s.Lo;
+ pValueResult->s.Hi = UINT64_MAX - pValueResult->s.Hi;
+ }
+ else
+ pValueResult->s.Hi = UINT64_C(0) - pValueResult->s.Hi;
+ return pValueResult;
+}
+
+
+/**
+ * Multiplies two 128-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(PRTUINT128U) RTUInt128AssignMul(PRTUINT128U pValue1Result, PCRTUINT128U pValue2)
+{
+ RTUINT128U Result;
+ RTUInt128Mul(&Result, pValue1Result, pValue2);
+ *pValue1Result = Result;
+ return pValue1Result;
+}
+
+
+/**
+ * Divides a 128-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(PRTUINT128U) RTUInt128AssignDiv(PRTUINT128U pValue1Result, PCRTUINT128U pValue2)
+{
+ RTUINT128U Result;
+ RTUINT128U Ignored;
+ RTUInt128DivRem(&Result, &Ignored, pValue1Result, pValue2);
+ *pValue1Result = Result;
+ return pValue1Result;
+}
+
+
+/**
+ * Divides a 128-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(PRTUINT128U) RTUInt128AssignMod(PRTUINT128U pValue1Result, PCRTUINT128U pValue2)
+{
+ RTUINT128U Ignored;
+ RTUINT128U Result;
+ RTUInt128DivRem(&Ignored, &Result, pValue1Result, pValue2);
+ *pValue1Result = Result;
+ return pValue1Result;
+}
+
+
+/**
+ * Performs a bitwise AND of two 128-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(PRTUINT128U) RTUInt128AssignAnd(PRTUINT128U pValue1Result, PCRTUINT128U pValue2)
+{
+#if ARCH_BITS >= 64
+ pValue1Result->s.Hi &= pValue2->s.Hi;
+ pValue1Result->s.Lo &= pValue2->s.Lo;
+#else
+ pValue1Result->DWords.dw0 &= pValue2->DWords.dw0;
+ pValue1Result->DWords.dw1 &= pValue2->DWords.dw1;
+ pValue1Result->DWords.dw2 &= pValue2->DWords.dw2;
+ pValue1Result->DWords.dw3 &= pValue2->DWords.dw3;
+#endif
+ return pValue1Result;
+}
+
+
+/**
+ * Performs a bitwise AND of a 128-bit unsigned integer value and a mask made
+ * up of the first N bits, assigning the result to the the 128-bit value.
+ *
+ * @returns pValueResult.
+ * @param pValueResult The value and result.
+ * @param cBits The number of bits to AND (counting from the first
+ * bit).
+ */
+DECLINLINE(PRTUINT128U) RTUInt128AssignAndNFirstBits(PRTUINT128U pValueResult, unsigned cBits)
+{
+ if (cBits <= 64)
+ {
+ if (cBits != 64)
+ pValueResult->s.Lo &= (RT_BIT_64(cBits) - 1);
+ pValueResult->s.Hi = 0;
+ }
+ else if (cBits < 128)
+ pValueResult->s.Hi &= (RT_BIT_64(cBits - 64) - 1);
+/** @todo \#if ARCH_BITS >= 64 */
+ return pValueResult;
+}
+
+
+/**
+ * Performs a bitwise OR of two 128-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(PRTUINT128U) RTUInt128AssignOr(PRTUINT128U pValue1Result, PCRTUINT128U pValue2)
+{
+#if ARCH_BITS >= 64
+ pValue1Result->s.Hi |= pValue2->s.Hi;
+ pValue1Result->s.Lo |= pValue2->s.Lo;
+#else
+ pValue1Result->DWords.dw0 |= pValue2->DWords.dw0;
+ pValue1Result->DWords.dw1 |= pValue2->DWords.dw1;
+ pValue1Result->DWords.dw2 |= pValue2->DWords.dw2;
+ pValue1Result->DWords.dw3 |= pValue2->DWords.dw3;
+#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(PRTUINT128U) RTUInt128AssignOrBit(PRTUINT128U pValue1Result, uint32_t iBit)
+{
+#if ARCH_BITS >= 64
+ if (iBit >= 64)
+ pValue1Result->s.Hi |= RT_BIT_64(iBit - 64);
+ else
+ pValue1Result->s.Lo |= RT_BIT_64(iBit);
+#else
+ if (iBit >= 64)
+ {
+ if (iBit >= 96)
+ pValue1Result->DWords.dw3 |= RT_BIT_32(iBit - 96);
+ else
+ pValue1Result->DWords.dw2 |= RT_BIT_32(iBit - 64);
+ }
+ else
+ {
+ if (iBit >= 32)
+ pValue1Result->DWords.dw1 |= RT_BIT_32(iBit - 32);
+ else
+ pValue1Result->DWords.dw0 |= RT_BIT_32(iBit);
+ }
+#endif
+ return pValue1Result;
+}
+
+
+
+/**
+ * Performs a bitwise XOR of two 128-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(PRTUINT128U) RTUInt128AssignXor(PRTUINT128U pValue1Result, PCRTUINT128U pValue2)
+{
+#if ARCH_BITS >= 64
+ pValue1Result->s.Hi ^= pValue2->s.Hi;
+ pValue1Result->s.Lo ^= pValue2->s.Lo;
+#else
+ pValue1Result->DWords.dw0 ^= pValue2->DWords.dw0;
+ pValue1Result->DWords.dw1 ^= pValue2->DWords.dw1;
+ pValue1Result->DWords.dw2 ^= pValue2->DWords.dw2;
+ pValue1Result->DWords.dw3 ^= pValue2->DWords.dw3;
+#endif
+ return pValue1Result;
+}
+
+
+/**
+ * Performs a bitwise left shift on a 128-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(PRTUINT128U) RTUInt128AssignShiftLeft(PRTUINT128U pValueResult, int cBits)
+{
+ RTUINT128U const InVal = *pValueResult;
+/** @todo \#if ARCH_BITS >= 64 */
+ if (cBits > 0)
+ {
+ /* (left shift) */
+ if (cBits >= 128)
+ RTUInt128SetZero(pValueResult);
+ else if (cBits >= 64)
+ {
+ pValueResult->s.Lo = 0;
+ pValueResult->s.Hi = InVal.s.Lo << (cBits - 64);
+ }
+ else
+ {
+ pValueResult->s.Hi = InVal.s.Hi << cBits;
+ pValueResult->s.Hi |= InVal.s.Lo >> (64 - cBits);
+ pValueResult->s.Lo = InVal.s.Lo << cBits;
+ }
+ }
+ else if (cBits < 0)
+ {
+ /* (right shift) */
+ cBits = -cBits;
+ if (cBits >= 128)
+ RTUInt128SetZero(pValueResult);
+ else if (cBits >= 64)
+ {
+ pValueResult->s.Hi = 0;
+ pValueResult->s.Lo = InVal.s.Hi >> (cBits - 64);
+ }
+ else
+ {
+ pValueResult->s.Lo = InVal.s.Lo >> cBits;
+ pValueResult->s.Lo |= InVal.s.Hi << (64 - cBits);
+ pValueResult->s.Hi = InVal.s.Hi >> cBits;
+ }
+ }
+ return pValueResult;
+}
+
+
+/**
+ * Performs a bitwise left shift on a 128-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(PRTUINT128U) RTUInt128AssignShiftRight(PRTUINT128U pValueResult, int cBits)
+{
+ return RTUInt128AssignShiftLeft(pValueResult, -cBits);
+}
+
+
+/**
+ * Performs a bitwise NOT on a 128-bit unsigned integer value, assigning the
+ * result to it.
+ *
+ * @returns pValueResult
+ * @param pValueResult The value and result.
+ */
+DECLINLINE(PRTUINT128U) RTUInt128AssignBitwiseNot(PRTUINT128U pValueResult)
+{
+#if ARCH_BITS >= 64
+ pValueResult->s.Hi = ~pValueResult->s.Hi;
+ pValueResult->s.Lo = ~pValueResult->s.Lo;
+#else
+ pValueResult->DWords.dw0 = ~pValueResult->DWords.dw0;
+ pValueResult->DWords.dw1 = ~pValueResult->DWords.dw1;
+ pValueResult->DWords.dw2 = ~pValueResult->DWords.dw2;
+ pValueResult->DWords.dw3 = ~pValueResult->DWords.dw3;
+#endif
+ return pValueResult;
+}
+
+
+/**
+ * Performs a boolean NOT on a 128-bit unsigned integer value, assigning the
+ * result to it.
+ *
+ * @returns pValueResult
+ * @param pValueResult The value and result.
+ */
+DECLINLINE(PRTUINT128U) RTUInt128AssignBooleanNot(PRTUINT128U pValueResult)
+{
+ return RTUInt128AssignBoolean(pValueResult, RTUInt128IsZero(pValueResult));
+}
+
+
+/**
+ * Compares two 128-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) RTUInt128Compare(PCRTUINT128U pValue1, PCRTUINT128U pValue2)
+{
+#if ARCH_BITS >= 64
+ 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->DWords.dw3 != pValue2->DWords.dw3)
+ return pValue1->DWords.dw3 > pValue2->DWords.dw3 ? 1 : -1;
+ if (pValue1->DWords.dw2 != pValue2->DWords.dw2)
+ return pValue1->DWords.dw2 > pValue2->DWords.dw2 ? 1 : -1;
+ if (pValue1->DWords.dw1 != pValue2->DWords.dw1)
+ return pValue1->DWords.dw1 > pValue2->DWords.dw1 ? 1 : -1;
+ if (pValue1->DWords.dw0 != pValue2->DWords.dw0)
+ return pValue1->DWords.dw0 > pValue2->DWords.dw0 ? 1 : -1;
+ return 0;
+#endif
+}
+
+
+/**
+ * Tests if a 128-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) RTUInt128IsSmaller(PCRTUINT128U pValue1, PCRTUINT128U pValue2)
+{
+#if ARCH_BITS >= 64
+ return pValue1->s.Hi < pValue2->s.Hi
+ || ( pValue1->s.Hi == pValue2->s.Hi
+ && pValue1->s.Lo < pValue2->s.Lo);
+#else
+ return pValue1->DWords.dw3 < pValue2->DWords.dw3
+ || ( pValue1->DWords.dw3 == pValue2->DWords.dw3
+ && ( pValue1->DWords.dw2 < pValue2->DWords.dw2
+ || ( pValue1->DWords.dw2 == pValue2->DWords.dw2
+ && ( pValue1->DWords.dw1 < pValue2->DWords.dw1
+ || ( pValue1->DWords.dw1 == pValue2->DWords.dw1
+ && pValue1->DWords.dw0 < pValue2->DWords.dw0)))));
+#endif
+}
+
+
+/**
+ * Tests if a 128-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) RTUInt128IsLarger(PCRTUINT128U pValue1, PCRTUINT128U pValue2)
+{
+#if ARCH_BITS >= 64
+ return pValue1->s.Hi > pValue2->s.Hi
+ || ( pValue1->s.Hi == pValue2->s.Hi
+ && pValue1->s.Lo > pValue2->s.Lo);
+#else
+ return pValue1->DWords.dw3 > pValue2->DWords.dw3
+ || ( pValue1->DWords.dw3 == pValue2->DWords.dw3
+ && ( pValue1->DWords.dw2 > pValue2->DWords.dw2
+ || ( pValue1->DWords.dw2 == pValue2->DWords.dw2
+ && ( pValue1->DWords.dw1 > pValue2->DWords.dw1
+ || ( pValue1->DWords.dw1 == pValue2->DWords.dw1
+ && pValue1->DWords.dw0 > pValue2->DWords.dw0)))));
+#endif
+}
+
+
+/**
+ * Tests if a 128-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) RTUInt128IsLargerOrEqual(PCRTUINT128U pValue1, PCRTUINT128U pValue2)
+{
+#if ARCH_BITS >= 64
+ return pValue1->s.Hi > pValue2->s.Hi
+ || ( pValue1->s.Hi == pValue2->s.Hi
+ && pValue1->s.Lo >= pValue2->s.Lo);
+#else
+ return pValue1->DWords.dw3 > pValue2->DWords.dw3
+ || ( pValue1->DWords.dw3 == pValue2->DWords.dw3
+ && ( pValue1->DWords.dw2 > pValue2->DWords.dw2
+ || ( pValue1->DWords.dw2 == pValue2->DWords.dw2
+ && ( pValue1->DWords.dw1 > pValue2->DWords.dw1
+ || ( pValue1->DWords.dw1 == pValue2->DWords.dw1
+ && pValue1->DWords.dw0 >= pValue2->DWords.dw0)))));
+#endif
+}
+
+
+/**
+ * Tests if two 128-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) RTUInt128IsEqual(PCRTUINT128U pValue1, PCRTUINT128U pValue2)
+{
+#if ARCH_BITS >= 64
+ return pValue1->s.Hi == pValue2->s.Hi
+ && pValue1->s.Lo == pValue2->s.Lo;
+#else
+ return pValue1->DWords.dw0 == pValue2->DWords.dw0
+ && pValue1->DWords.dw1 == pValue2->DWords.dw1
+ && pValue1->DWords.dw2 == pValue2->DWords.dw2
+ && pValue1->DWords.dw3 == pValue2->DWords.dw3;
+#endif
+}
+
+
+/**
+ * Tests if two 128-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) RTUInt128IsNotEqual(PCRTUINT128U pValue1, PCRTUINT128U pValue2)
+{
+ return !RTUInt128IsEqual(pValue1, pValue2);
+}
+
+
+/**
+ * Sets a bit in a 128-bit unsigned integer type.
+ *
+ * @returns pValueResult.
+ * @param pValueResult The input and output value.
+ * @param iBit The bit to set.
+ */
+DECLINLINE(PRTUINT128U) RTUInt128BitSet(PRTUINT128U pValueResult, unsigned iBit)
+{
+ if (iBit < 64)
+ {
+#if ARCH_BITS >= 64
+ pValueResult->s.Lo |= RT_BIT_64(iBit);
+#else
+ if (iBit < 32)
+ pValueResult->DWords.dw0 |= RT_BIT_32(iBit);
+ else
+ pValueResult->DWords.dw1 |= RT_BIT_32(iBit - 32);
+#endif
+ }
+ else if (iBit < 128)
+ {
+#if ARCH_BITS >= 64
+ pValueResult->s.Hi |= RT_BIT_64(iBit - 64);
+#else
+ if (iBit < 96)
+ pValueResult->DWords.dw2 |= RT_BIT_32(iBit - 64);
+ else
+ pValueResult->DWords.dw3 |= RT_BIT_32(iBit - 96);
+#endif
+ }
+ return pValueResult;
+}
+
+
+/**
+ * Sets a bit in a 128-bit unsigned integer type.
+ *
+ * @returns pValueResult.
+ * @param pValueResult The input and output value.
+ * @param iBit The bit to set.
+ */
+DECLINLINE(PRTUINT128U) RTUInt128BitClear(PRTUINT128U pValueResult, unsigned iBit)
+{
+ if (iBit < 64)
+ {
+#if ARCH_BITS >= 64
+ pValueResult->s.Lo &= ~RT_BIT_64(iBit);
+#else
+ if (iBit < 32)
+ pValueResult->DWords.dw0 &= ~RT_BIT_32(iBit);
+ else
+ pValueResult->DWords.dw1 &= ~RT_BIT_32(iBit - 32);
+#endif
+ }
+ else if (iBit < 128)
+ {
+#if ARCH_BITS >= 64
+ pValueResult->s.Hi &= ~RT_BIT_64(iBit - 64);
+#else
+ if (iBit < 96)
+ pValueResult->DWords.dw2 &= ~RT_BIT_32(iBit - 64);
+ else
+ pValueResult->DWords.dw3 &= ~RT_BIT_32(iBit - 96);
+#endif
+ }
+ return pValueResult;
+}
+
+
+/**
+ * Tests if a bit in a 128-bit unsigned integer value is set.
+ *
+ * @returns pValueResult.
+ * @param pValueResult The input and output value.
+ * @param iBit The bit to test.
+ */
+DECLINLINE(bool) RTUInt128BitTest(PRTUINT128U pValueResult, unsigned iBit)
+{
+ bool fRc;
+ if (iBit < 64)
+ {
+#if ARCH_BITS >= 64
+ fRc = RT_BOOL(pValueResult->s.Lo & RT_BIT_64(iBit));
+#else
+ if (iBit < 32)
+ fRc = RT_BOOL(pValueResult->DWords.dw0 & RT_BIT_32(iBit));
+ else
+ fRc = RT_BOOL(pValueResult->DWords.dw1 & RT_BIT_32(iBit - 32));
+#endif
+ }
+ else if (iBit < 128)
+ {
+#if ARCH_BITS >= 64
+ fRc = RT_BOOL(pValueResult->s.Hi & RT_BIT_64(iBit - 64));
+#else
+ if (iBit < 96)
+ fRc = RT_BOOL(pValueResult->DWords.dw2 & RT_BIT_32(iBit - 64));
+ else
+ fRc = RT_BOOL(pValueResult->DWords.dw3 & RT_BIT_32(iBit - 96));
+#endif
+ }
+ else
+ fRc = false;
+ return fRc;
+}
+
+
+/**
+ * Set a range of bits a 128-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(PRTUINT128U) RTUInt128BitSetRange(PRTUINT128U pValueResult, unsigned iFirstBit, unsigned cBits)
+{
+ /* bounds check & fix. */
+ if (iFirstBit < 128)
+ {
+ if (iFirstBit + cBits > 128)
+ cBits = 128 - iFirstBit;
+
+#if ARCH_BITS >= 64
+ if (iFirstBit + cBits < 64)
+ pValueResult->s.Lo |= (RT_BIT_64(cBits) - 1) << iFirstBit;
+ else if (iFirstBit + cBits < 128 && iFirstBit >= 64)
+ pValueResult->s.Hi |= (RT_BIT_64(cBits) - 1) << (iFirstBit - 64);
+ else
+#else
+ if (iFirstBit + cBits < 32)
+ pValueResult->DWords.dw0 |= (RT_BIT_32(cBits) - 1) << iFirstBit;
+ else if (iFirstBit + cBits < 64 && iFirstBit >= 32)
+ pValueResult->DWords.dw1 |= (RT_BIT_32(cBits) - 1) << (iFirstBit - 32);
+ else if (iFirstBit + cBits < 96 && iFirstBit >= 64)
+ pValueResult->DWords.dw2 |= (RT_BIT_32(cBits) - 1) << (iFirstBit - 64);
+ else if (iFirstBit + cBits < 128 && iFirstBit >= 96)
+ pValueResult->DWords.dw3 |= (RT_BIT_32(cBits) - 1) << (iFirstBit - 96);
+ else
+#endif
+ while (cBits-- > 0)
+ RTUInt128BitSet(pValueResult, iFirstBit++);
+ }
+ return pValueResult;
+}
+
+
+/**
+ * Test if all the bits of a 128-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) RTUInt128BitAreAllSet(PRTUINT128U pValue)
+{
+#if ARCH_BITS >= 64
+ return pValue->s.Hi == UINT64_MAX
+ && pValue->s.Lo == UINT64_MAX;
+#else
+ return pValue->DWords.dw0 == UINT32_MAX
+ && pValue->DWords.dw1 == UINT32_MAX
+ && pValue->DWords.dw2 == UINT32_MAX
+ && pValue->DWords.dw3 == UINT32_MAX;
+#endif
+}
+
+
+/**
+ * Test if all the bits of a 128-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) RTUInt128BitAreAllClear(PRTUINT128U pValue)
+{
+#if ARCH_BITS >= 64
+ return pValue->s.Hi == 0
+ && pValue->s.Lo == 0;
+#else
+ return pValue->DWords.dw0 == 0
+ && pValue->DWords.dw1 == 0
+ && pValue->DWords.dw2 == 0
+ && pValue->DWords.dw3 == 0;
+#endif
+}
+
+
+/**
+ * Number of significant bits in the value.
+ *
+ * This is the same a ASMBitLastSetU64 and ASMBitLastSetU32.
+ *
+ * @returns 0 if zero, 1-base index of the last bit set.
+ * @param pValue The value to examine.
+ */
+DECLINLINE(uint32_t) RTUInt128BitCount(PCRTUINT128U pValue)
+{
+ uint32_t cBits;
+ if (pValue->s.Hi != 0)
+ {
+ if (pValue->DWords.dw3)
+ cBits = 96 + ASMBitLastSetU32(pValue->DWords.dw3);
+ else
+ cBits = 64 + ASMBitLastSetU32(pValue->DWords.dw2);
+ }
+ else
+ {
+ if (pValue->DWords.dw1)
+ cBits = 32 + ASMBitLastSetU32(pValue->DWords.dw1);
+ else
+ cBits = 0 + ASMBitLastSetU32(pValue->DWords.dw0);
+ }
+ return cBits;
+}
+
+
+/**
+ * Divides a 128-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(PRTUINT128U) RTUInt128DivRem(PRTUINT128U pQuotient, PRTUINT128U pRemainder, PCRTUINT128U pValue1, PCRTUINT128U 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)
+ {
+ RTUInt128SetZero(pRemainder);
+ *pQuotient = *pValue1;
+ return pQuotient;
+ }
+ /** @todo RTUint128DivModBy64 */
+ }
+
+ /* Dividend is smaller? */
+ iDiff = RTUInt128Compare(pValue1, pValue2);
+ if (iDiff < 0)
+ {
+ *pRemainder = *pValue1;
+ RTUInt128SetZero(pQuotient);
+ }
+
+ /* The values are equal? */
+ else if (iDiff == 0)
+ {
+ RTUInt128SetZero(pRemainder);
+ RTUInt128AssignU64(pQuotient, 1);
+ }
+ else
+ {
+ /*
+ * Prepare.
+ */
+ uint32_t iBitAdder = RTUInt128BitCount(pValue1) - RTUInt128BitCount(pValue2);
+ RTUINT128U NormDivisor = *pValue2;
+ if (iBitAdder)
+ {
+ RTUInt128ShiftLeft(&NormDivisor, pValue2, iBitAdder);
+ if (RTUInt128IsLarger(&NormDivisor, pValue1))
+ {
+ RTUInt128AssignShiftRight(&NormDivisor, 1);
+ iBitAdder--;
+ }
+ }
+ else
+ NormDivisor = *pValue2;
+
+ RTUInt128SetZero(pQuotient);
+ *pRemainder = *pValue1;
+
+ /*
+ * Do the division.
+ */
+ if (RTUInt128IsLargerOrEqual(pRemainder, pValue2))
+ {
+ for (;;)
+ {
+ if (RTUInt128IsLargerOrEqual(pRemainder, &NormDivisor))
+ {
+ RTUInt128AssignSub(pRemainder, &NormDivisor);
+ RTUInt128AssignOrBit(pQuotient, iBitAdder);
+ }
+ if (RTUInt128IsSmaller(pRemainder, pValue2))
+ break;
+ RTUInt128AssignShiftRight(&NormDivisor, 1);
+ iBitAdder--;
+ }
+ }
+ }
+ return pQuotient;
+}
+
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_uint128_h */
+
diff --git a/include/iprt/uint256.h b/include/iprt/uint256.h
new file mode 100644
index 00000000..351f7f4e
--- /dev/null
+++ b/include/iprt/uint256.h
@@ -0,0 +1,1241 @@
+/** @file
+ * IPRT - RTUINT256U methods.
+ */
+
+/*
+ * Copyright (C) 2011-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_uint256_h
+#define IPRT_INCLUDED_uint256_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+#include <iprt/asm.h>
+#include <iprt/asm-math.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_uint256 RTUInt256 - 256-bit Unsigned Integer Methods
+ * @ingroup grp_rt
+ * @{
+ */
+
+
+/**
+ * Test if a 256-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) RTUInt256IsZero(PCRTUINT256U pValue)
+{
+#if ARCH_BITS >= 64
+ return pValue->QWords.qw0 == 0
+ && pValue->QWords.qw1 == 0
+ && pValue->QWords.qw2 == 0
+ && pValue->QWords.qw3 == 0;
+#else
+ return pValue->DWords.dw0 == 0
+ && pValue->DWords.dw1 == 0
+ && pValue->DWords.dw2 == 0
+ && pValue->DWords.dw3 == 0
+ && pValue->DWords.dw4 == 0
+ && pValue->DWords.dw5 == 0
+ && pValue->DWords.dw6 == 0
+ && pValue->DWords.dw7 == 0;
+#endif
+}
+
+
+/**
+ * Set a 256-bit unsigned integer value to zero.
+ *
+ * @returns pResult
+ * @param pResult The result variable.
+ */
+DECLINLINE(PRTUINT256U) RTUInt256SetZero(PRTUINT256U pResult)
+{
+#if ARCH_BITS >= 64
+ pResult->QWords.qw0 = 0;
+ pResult->QWords.qw1 = 0;
+ pResult->QWords.qw2 = 0;
+ pResult->QWords.qw3 = 0;
+#else
+ pResult->DWords.dw0 = 0;
+ pResult->DWords.dw1 = 0;
+ pResult->DWords.dw2 = 0;
+ pResult->DWords.dw3 = 0;
+ pResult->DWords.dw4 = 0;
+ pResult->DWords.dw5 = 0;
+ pResult->DWords.dw6 = 0;
+ pResult->DWords.dw7 = 0;
+#endif
+ return pResult;
+}
+
+
+/**
+ * Set a 256-bit unsigned integer value to the maximum value.
+ *
+ * @returns pResult
+ * @param pResult The result variable.
+ */
+DECLINLINE(PRTUINT256U) RTUInt256SetMax(PRTUINT256U pResult)
+{
+#if ARCH_BITS >= 64
+ pResult->QWords.qw0 = UINT64_MAX;
+ pResult->QWords.qw1 = UINT64_MAX;
+ pResult->QWords.qw2 = UINT64_MAX;
+ pResult->QWords.qw3 = UINT64_MAX;
+#else
+ pResult->DWords.dw0 = UINT32_MAX;
+ pResult->DWords.dw1 = UINT32_MAX;
+ pResult->DWords.dw2 = UINT32_MAX;
+ pResult->DWords.dw3 = UINT32_MAX;
+ pResult->DWords.dw4 = UINT32_MAX;
+ pResult->DWords.dw5 = UINT32_MAX;
+ pResult->DWords.dw6 = UINT32_MAX;
+ pResult->DWords.dw7 = UINT32_MAX;
+#endif
+ return pResult;
+}
+
+
+
+
+/**
+ * Adds two 256-bit unsigned integer values.
+ *
+ * @returns pResult
+ * @param pResult The result variable.
+ * @param pValue1 The first value.
+ * @param pValue2 The second value.
+ */
+DECLINLINE(PRTUINT256U) RTUInt256Add(PRTUINT256U pResult, PCRTUINT256U pValue1, PCRTUINT256U pValue2)
+{
+ unsigned uCarry;
+ pResult->QWords.qw0 = pValue1->QWords.qw0 + pValue2->QWords.qw0;
+ uCarry = pResult->QWords.qw0 < pValue1->QWords.qw0;
+
+ pResult->QWords.qw1 = pValue1->QWords.qw1 + pValue2->QWords.qw1 + uCarry;
+ uCarry = uCarry ? pResult->QWords.qw1 <= pValue1->QWords.qw1 : pResult->QWords.qw1 < pValue1->QWords.qw1;
+
+ pResult->QWords.qw2 = pValue1->QWords.qw2 + pValue2->QWords.qw2 + uCarry;
+ uCarry = uCarry ? pResult->QWords.qw2 <= pValue1->QWords.qw2 : pResult->QWords.qw2 < pValue1->QWords.qw2;
+
+ pResult->QWords.qw3 = pValue1->QWords.qw3 + pValue2->QWords.qw3 + uCarry;
+ return pResult;
+}
+
+
+/**
+ * Adds a 256-bit and a 64-bit unsigned integer values.
+ *
+ * @returns pResult
+ * @param pResult The result variable.
+ * @param pValue1 The first value.
+ * @param uValue2 The second value, 64-bit.
+ */
+DECLINLINE(PRTUINT256U) RTUInt256AddU64(PRTUINT256U pResult, PCRTUINT256U pValue1, uint64_t uValue2)
+{
+ pResult->QWords.qw3 = pValue1->QWords.qw3;
+ pResult->QWords.qw2 = pValue1->QWords.qw2;
+ pResult->QWords.qw1 = pValue1->QWords.qw1;
+ pResult->QWords.qw0 = pValue1->QWords.qw0 + uValue2;
+ if (pResult->QWords.qw0 < uValue2)
+ if (pResult->QWords.qw1++ == UINT64_MAX)
+ if (pResult->QWords.qw2++ == UINT64_MAX)
+ pResult->QWords.qw3++;
+ return pResult;
+}
+
+
+/**
+ * Subtracts a 256-bit unsigned integer value from another.
+ *
+ * @returns pResult
+ * @param pResult The result variable.
+ * @param pValue1 The minuend value.
+ * @param pValue2 The subtrahend value.
+ */
+DECLINLINE(PRTUINT256U) RTUInt256Sub(PRTUINT256U pResult, PCRTUINT256U pValue1, PCRTUINT256U pValue2)
+{
+ unsigned uBorrow;
+ pResult->QWords.qw0 = pValue1->QWords.qw0 - pValue2->QWords.qw0;
+ uBorrow = pResult->QWords.qw0 > pValue1->QWords.qw0;
+
+ pResult->QWords.qw1 = pValue1->QWords.qw1 - pValue2->QWords.qw1 - uBorrow;
+ uBorrow = uBorrow ? pResult->QWords.qw1 >= pValue1->QWords.qw1 : pResult->QWords.qw1 > pValue1->QWords.qw1;
+
+ pResult->QWords.qw2 = pValue1->QWords.qw2 - pValue2->QWords.qw2 - uBorrow;
+ uBorrow = uBorrow ? pResult->QWords.qw2 >= pValue1->QWords.qw2 : pResult->QWords.qw2 > pValue1->QWords.qw2;
+
+ pResult->QWords.qw3 = pValue1->QWords.qw3 - pValue2->QWords.qw3 - uBorrow;
+ return pResult;
+}
+
+
+/**
+ * Multiplies two 256-bit unsigned integer values.
+ *
+ * @returns pResult
+ * @param pResult The result variable.
+ * @param pValue1 The first value.
+ * @param pValue2 The second value.
+ */
+RTDECL(PRTUINT256U) RTUInt256Mul(PRTUINT256U pResult, PCRTUINT256U pValue1, PCRTUINT256U pValue2);
+
+/**
+ * Multiplies an 256-bit unsigned integer by a 64-bit unsigned integer value.
+ *
+ * @returns pResult
+ * @param pResult The result variable.
+ * @param pValue1 The first value.
+ * @param uValue2 The second value, 64-bit.
+ */
+RTDECL(PRTUINT256U) RTUInt256MulByU64(PRTUINT256U pResult, PCRTUINT256U pValue1, uint64_t uValue2);
+
+/**
+ * Divides a 256-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.
+ */
+RTDECL(PRTUINT256U) RTUInt256DivRem(PRTUINT256U pQuotient, PRTUINT256U pRemainder, PCRTUINT256U pValue1, PCRTUINT256U pValue2);
+
+/**
+ * Divides a 256-bit unsigned integer value by another.
+ *
+ * @returns pResult
+ * @param pResult The result variable.
+ * @param pValue1 The dividend value.
+ * @param pValue2 The divisor value.
+ */
+DECLINLINE(PRTUINT256U) RTUInt256Div(PRTUINT256U pResult, PCRTUINT256U pValue1, PCRTUINT256U pValue2)
+{
+ RTUINT256U Ignored;
+ return RTUInt256DivRem(pResult, &Ignored, pValue1, pValue2);
+}
+
+
+/**
+ * Divides a 256-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(PRTUINT256U) RTUInt256Mod(PRTUINT256U pResult, PCRTUINT256U pValue1, PCRTUINT256U pValue2)
+{
+ RTUINT256U Ignored;
+ RTUInt256DivRem(&Ignored, pResult, pValue1, pValue2);
+ return pResult;
+}
+
+
+/**
+ * Bitwise AND of two 256-bit unsigned integer values.
+ *
+ * @returns pResult
+ * @param pResult The result variable.
+ * @param pValue1 The first value.
+ * @param pValue2 The second value.
+ */
+DECLINLINE(PRTUINT256U) RTUInt256And(PRTUINT256U pResult, PCRTUINT256U pValue1, PCRTUINT256U pValue2)
+{
+ pResult->QWords.qw0 = pValue1->QWords.qw0 & pValue2->QWords.qw0;
+ pResult->QWords.qw1 = pValue1->QWords.qw1 & pValue2->QWords.qw1;
+ pResult->QWords.qw2 = pValue1->QWords.qw2 & pValue2->QWords.qw2;
+ pResult->QWords.qw3 = pValue1->QWords.qw3 & pValue2->QWords.qw3;
+ return pResult;
+}
+
+
+/**
+ * Bitwise OR of two 256-bit unsigned integer values.
+ *
+ * @returns pResult
+ * @param pResult The result variable.
+ * @param pValue1 The first value.
+ * @param pValue2 The second value.
+ */
+DECLINLINE(PRTUINT256U) RTUInt256Or( PRTUINT256U pResult, PCRTUINT256U pValue1, PCRTUINT256U pValue2)
+{
+ pResult->QWords.qw0 = pValue1->QWords.qw0 | pValue2->QWords.qw0;
+ pResult->QWords.qw1 = pValue1->QWords.qw1 | pValue2->QWords.qw1;
+ pResult->QWords.qw2 = pValue1->QWords.qw2 | pValue2->QWords.qw2;
+ pResult->QWords.qw3 = pValue1->QWords.qw3 | pValue2->QWords.qw3;
+ return pResult;
+}
+
+
+/**
+ * Bitwise XOR of two 256-bit unsigned integer values.
+ *
+ * @returns pResult
+ * @param pResult The result variable.
+ * @param pValue1 The first value.
+ * @param pValue2 The second value.
+ */
+DECLINLINE(PRTUINT256U) RTUInt256Xor(PRTUINT256U pResult, PCRTUINT256U pValue1, PCRTUINT256U pValue2)
+{
+ pResult->QWords.qw0 = pValue1->QWords.qw0 ^ pValue2->QWords.qw0;
+ pResult->QWords.qw1 = pValue1->QWords.qw1 ^ pValue2->QWords.qw1;
+ pResult->QWords.qw2 = pValue1->QWords.qw2 ^ pValue2->QWords.qw2;
+ pResult->QWords.qw3 = pValue1->QWords.qw3 ^ pValue2->QWords.qw3;
+ return pResult;
+}
+
+
+/**
+ * Shifts a 256-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. This is masked
+ * by 255 before shifting.
+ */
+DECLINLINE(PRTUINT256U) RTUInt256ShiftLeft(PRTUINT256U pResult, PCRTUINT256U pValue, unsigned cBits)
+{
+ /* This is a bit bulky & impractical since we cannot access the data using
+ an array because it is organized according to host endianness. Sigh. */
+ cBits &= 255;
+ if (!(cBits & 0x3f))
+ {
+ if (cBits == 0)
+ *pResult = *pValue;
+ else
+ {
+ pResult->QWords.qw0 = 0;
+ if (cBits == 64)
+ {
+ pResult->QWords.qw1 = pValue->QWords.qw0;
+ pResult->QWords.qw2 = pValue->QWords.qw1;
+ pResult->QWords.qw3 = pValue->QWords.qw2;
+ }
+ else
+ {
+ pResult->QWords.qw1 = 0;
+ if (cBits == 128)
+ {
+ pResult->QWords.qw2 = pValue->QWords.qw0;
+ pResult->QWords.qw3 = pValue->QWords.qw1;
+ }
+ else
+ {
+ pResult->QWords.qw2 = 0;
+ pResult->QWords.qw3 = pValue->QWords.qw0;
+ }
+ }
+ }
+ }
+ else if (cBits < 128)
+ {
+ if (cBits < 64)
+ {
+ pResult->QWords.qw0 = pValue->QWords.qw0 << cBits;
+ pResult->QWords.qw1 = pValue->QWords.qw0 >> (64 - cBits);
+ pResult->QWords.qw1 |= pValue->QWords.qw1 << cBits;
+ pResult->QWords.qw2 = pValue->QWords.qw1 >> (64 - cBits);
+ pResult->QWords.qw2 |= pValue->QWords.qw2 << cBits;
+ pResult->QWords.qw3 = pValue->QWords.qw2 >> (64 - cBits);
+ pResult->QWords.qw3 |= pValue->QWords.qw3 << cBits;
+ }
+ else
+ {
+ cBits -= 64;
+ pResult->QWords.qw0 = 0;
+ pResult->QWords.qw1 = pValue->QWords.qw0 << cBits;
+ pResult->QWords.qw2 = pValue->QWords.qw0 >> (64 - cBits);
+ pResult->QWords.qw2 |= pValue->QWords.qw1 << cBits;
+ pResult->QWords.qw3 = pValue->QWords.qw1 >> (64 - cBits);
+ pResult->QWords.qw3 |= pValue->QWords.qw2 << cBits;
+ }
+ }
+ else
+ {
+ if (cBits < 192)
+ {
+ cBits -= 128;
+ pResult->QWords.qw0 = 0;
+ pResult->QWords.qw1 = 0;
+ pResult->QWords.qw2 = pValue->QWords.qw0 << cBits;
+ pResult->QWords.qw3 = pValue->QWords.qw0 >> (64 - cBits);
+ pResult->QWords.qw3 |= pValue->QWords.qw1 << cBits;
+ }
+ else
+ {
+ cBits -= 192;
+ pResult->QWords.qw0 = 0;
+ pResult->QWords.qw1 = 0;
+ pResult->QWords.qw2 = 0;
+ pResult->QWords.qw3 = pValue->QWords.qw0 << cBits;
+ }
+ }
+ return pResult;
+}
+
+
+/**
+ * Shifts a 256-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. This is masked
+ * by 255 before shifting.
+ */
+DECLINLINE(PRTUINT256U) RTUInt256ShiftRight(PRTUINT256U pResult, PCRTUINT256U pValue, unsigned cBits)
+{
+ /* This is a bit bulky & impractical since we cannot access the data using
+ an array because it is organized according to host endianness. Sigh. */
+ cBits &= 255;
+ if (!(cBits & 0x3f))
+ {
+ if (cBits == 0)
+ *pResult = *pValue;
+ else
+ {
+ if (cBits == 64)
+ {
+ pResult->QWords.qw0 = pValue->QWords.qw1;
+ pResult->QWords.qw1 = pValue->QWords.qw2;
+ pResult->QWords.qw2 = pValue->QWords.qw3;
+ }
+ else
+ {
+ if (cBits == 128)
+ {
+ pResult->QWords.qw0 = pValue->QWords.qw2;
+ pResult->QWords.qw1 = pValue->QWords.qw3;
+ }
+ else
+ {
+ pResult->QWords.qw0 = pValue->QWords.qw3;
+ pResult->QWords.qw1 = 0;
+ }
+ pResult->QWords.qw2 = 0;
+ }
+ pResult->QWords.qw3 = 0;
+ }
+ }
+ else if (cBits < 128)
+ {
+ if (cBits < 64)
+ {
+ pResult->QWords.qw0 = pValue->QWords.qw0 >> cBits;
+ pResult->QWords.qw0 |= pValue->QWords.qw1 << (64 - cBits);
+ pResult->QWords.qw1 = pValue->QWords.qw1 >> cBits;
+ pResult->QWords.qw1 |= pValue->QWords.qw2 << (64 - cBits);
+ pResult->QWords.qw2 = pValue->QWords.qw2 >> cBits;
+ pResult->QWords.qw2 |= pValue->QWords.qw3 << (64 - cBits);
+ pResult->QWords.qw3 = pValue->QWords.qw3 >> cBits;
+ }
+ else
+ {
+ cBits -= 64;
+ pResult->QWords.qw0 = pValue->QWords.qw1 >> cBits;
+ pResult->QWords.qw0 |= pValue->QWords.qw2 << (64 - cBits);
+ pResult->QWords.qw1 = pValue->QWords.qw2 >> cBits;
+ pResult->QWords.qw1 |= pValue->QWords.qw3 << (64 - cBits);
+ pResult->QWords.qw2 = pValue->QWords.qw3 >> cBits;
+ pResult->QWords.qw3 = 0;
+ }
+ }
+ else
+ {
+ if (cBits < 192)
+ {
+ cBits -= 128;
+ pResult->QWords.qw0 = pValue->QWords.qw2 >> cBits;
+ pResult->QWords.qw0 |= pValue->QWords.qw3 << (64 - cBits);
+ pResult->QWords.qw1 = pValue->QWords.qw3 >> cBits;
+ pResult->QWords.qw2 = 0;
+ pResult->QWords.qw3 = 0;
+ }
+ else
+ {
+ cBits -= 192;
+ pResult->QWords.qw0 = pValue->QWords.qw3 >> cBits;
+ pResult->QWords.qw1 = 0;
+ pResult->QWords.qw2 = 0;
+ pResult->QWords.qw3 = 0;
+ }
+ }
+ return pResult;
+}
+
+
+/**
+ * Boolean not (result 0 or 1).
+ *
+ * @returns pResult.
+ * @param pResult The result variable.
+ * @param pValue The value.
+ */
+DECLINLINE(PRTUINT256U) RTUInt256BooleanNot(PRTUINT256U pResult, PCRTUINT256U pValue)
+{
+ pResult->QWords.qw0 = RTUInt256IsZero(pValue);
+ pResult->QWords.qw1 = 0;
+ pResult->QWords.qw2 = 0;
+ pResult->QWords.qw3 = 0;
+ return pResult;
+}
+
+
+/**
+ * Bitwise not (flips each bit of the 256 bits).
+ *
+ * @returns pResult.
+ * @param pResult The result variable.
+ * @param pValue The value.
+ */
+DECLINLINE(PRTUINT256U) RTUInt256BitwiseNot(PRTUINT256U pResult, PCRTUINT256U pValue)
+{
+ pResult->QWords.qw0 = ~pValue->QWords.qw0;
+ pResult->QWords.qw1 = ~pValue->QWords.qw1;
+ pResult->QWords.qw2 = ~pValue->QWords.qw2;
+ pResult->QWords.qw3 = ~pValue->QWords.qw3;
+ return pResult;
+}
+
+
+/**
+ * Assigns one 256-bit unsigned integer value to another.
+ *
+ * @returns pResult
+ * @param pResult The result variable.
+ * @param pValue The value to assign.
+ */
+DECLINLINE(PRTUINT256U) RTUInt256Assign(PRTUINT256U pResult, PCRTUINT256U pValue)
+{
+ pResult->QWords.qw0 = pValue->QWords.qw0;
+ pResult->QWords.qw1 = pValue->QWords.qw1;
+ pResult->QWords.qw2 = pValue->QWords.qw2;
+ pResult->QWords.qw3 = pValue->QWords.qw3;
+ return pResult;
+}
+
+
+/**
+ * Assigns a boolean value to 256-bit unsigned integer.
+ *
+ * @returns pValueResult
+ * @param pValueResult The result variable.
+ * @param fValue The boolean value.
+ */
+DECLINLINE(PRTUINT256U) RTUInt256AssignBoolean(PRTUINT256U pValueResult, bool fValue)
+{
+ pValueResult->QWords.qw0 = fValue;
+ pValueResult->QWords.qw1 = 0;
+ pValueResult->QWords.qw2 = 0;
+ pValueResult->QWords.qw3 = 0;
+ return pValueResult;
+}
+
+
+/**
+ * Assigns a 8-bit unsigned integer value to 256-bit unsigned integer.
+ *
+ * @returns pValueResult
+ * @param pValueResult The result variable.
+ * @param u8Value The 8-bit unsigned integer value.
+ */
+DECLINLINE(PRTUINT256U) RTUInt256AssignU8(PRTUINT256U pValueResult, uint8_t u8Value)
+{
+ pValueResult->QWords.qw0 = u8Value;
+ pValueResult->QWords.qw1 = 0;
+ pValueResult->QWords.qw2 = 0;
+ pValueResult->QWords.qw3 = 0;
+ return pValueResult;
+}
+
+
+/**
+ * Assigns a 16-bit unsigned integer value to 256-bit unsigned integer.
+ *
+ * @returns pValueResult
+ * @param pValueResult The result variable.
+ * @param u16Value The 16-bit unsigned integer value.
+ */
+DECLINLINE(PRTUINT256U) RTUInt256AssignU16(PRTUINT256U pValueResult, uint16_t u16Value)
+{
+ pValueResult->QWords.qw0 = u16Value;
+ pValueResult->QWords.qw1 = 0;
+ pValueResult->QWords.qw2 = 0;
+ pValueResult->QWords.qw3 = 0;
+ return pValueResult;
+}
+
+
+/**
+ * Assigns a 32-bit unsigned integer value to 256-bit unsigned integer.
+ *
+ * @returns pValueResult
+ * @param pValueResult The result variable.
+ * @param u32Value The 32-bit unsigned integer value.
+ */
+DECLINLINE(PRTUINT256U) RTUInt256AssignU32(PRTUINT256U pValueResult, uint32_t u32Value)
+{
+ pValueResult->QWords.qw0 = u32Value;
+ pValueResult->QWords.qw1 = 0;
+ pValueResult->QWords.qw2 = 0;
+ pValueResult->QWords.qw3 = 0;
+ return pValueResult;
+}
+
+
+/**
+ * Assigns a 64-bit unsigned integer value to 256-bit unsigned integer.
+ *
+ * @returns pValueResult
+ * @param pValueResult The result variable.
+ * @param u64Value The 64-bit unsigned integer value.
+ */
+DECLINLINE(PRTUINT256U) RTUInt256AssignU64(PRTUINT256U pValueResult, uint64_t u64Value)
+{
+ pValueResult->QWords.qw0 = u64Value;
+ pValueResult->QWords.qw1 = 0;
+ pValueResult->QWords.qw2 = 0;
+ pValueResult->QWords.qw3 = 0;
+ return pValueResult;
+}
+
+
+/**
+ * Adds two 256-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(PRTUINT256U) RTUInt256AssignAdd(PRTUINT256U pValue1Result, PCRTUINT256U pValue2)
+{
+ RTUINT256U const uTmpValue1 = *pValue1Result; /* lazy bird */
+ return RTUInt256Add(pValue1Result, &uTmpValue1, pValue2);
+}
+
+
+/**
+ * Adds a 64-bit unsigned integer value to a 256-bit unsigned integer values,
+ * storing the result in the 256-bit one.
+ *
+ * @returns pValue1Result.
+ * @param pValue1Result The first value and result.
+ * @param uValue2 The second value, 64-bit.
+ */
+DECLINLINE(PRTUINT256U) RTUInt256AssignAddU64(PRTUINT256U pValue1Result, uint64_t uValue2)
+{
+ RTUINT256U const uTmpValue1 = *pValue1Result; /* lazy bird */
+ return RTUInt256AddU64(pValue1Result, &uTmpValue1, uValue2);
+}
+
+
+/**
+ * Subtracts two 256-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(PRTUINT256U) RTUInt256AssignSub(PRTUINT256U pValue1Result, PCRTUINT256U pValue2)
+{
+ RTUINT256U const uTmpValue1 = *pValue1Result; /* lazy bird */
+ return RTUInt256Sub(pValue1Result, &uTmpValue1, pValue2);
+}
+
+
+#if 0
+/**
+ * Negates a 256 number, storing the result in the input.
+ *
+ * @returns pValueResult.
+ * @param pValueResult The value to negate.
+ */
+DECLINLINE(PRTUINT256U) RTUInt256AssignNeg(PRTUINT256U pValueResult)
+{
+ /* result = 0 - value */
+ if (pValueResult->s.Lo != 0)
+ {
+ pValueResult->s.Lo = UINT64_C(0) - pValueResult->s.Lo;
+ pValueResult->s.Hi = UINT64_MAX - pValueResult->s.Hi;
+ }
+ else
+ pValueResult->s.Hi = UINT64_C(0) - pValueResult->s.Hi;
+ return pValueResult;
+}
+#endif
+
+
+/**
+ * Multiplies two 256-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(PRTUINT256U) RTUInt256AssignMul(PRTUINT256U pValue1Result, PCRTUINT256U pValue2)
+{
+ RTUINT256U Result;
+ RTUInt256Mul(&Result, pValue1Result, pValue2);
+ *pValue1Result = Result;
+ return pValue1Result;
+}
+
+
+/**
+ * Divides a 256-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(PRTUINT256U) RTUInt256AssignDiv(PRTUINT256U pValue1Result, PCRTUINT256U pValue2)
+{
+ RTUINT256U Result;
+ RTUINT256U Ignored;
+ RTUInt256DivRem(&Result, &Ignored, pValue1Result, pValue2);
+ *pValue1Result = Result;
+ return pValue1Result;
+}
+
+
+/**
+ * Divides a 256-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(PRTUINT256U) RTUInt256AssignMod(PRTUINT256U pValue1Result, PCRTUINT256U pValue2)
+{
+ RTUINT256U Ignored;
+ RTUINT256U Result;
+ RTUInt256DivRem(&Ignored, &Result, pValue1Result, pValue2);
+ *pValue1Result = Result;
+ return pValue1Result;
+}
+
+
+/**
+ * Performs a bitwise AND of two 256-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(PRTUINT256U) RTUInt256AssignAnd(PRTUINT256U pValue1Result, PCRTUINT256U pValue2)
+{
+ pValue1Result->QWords.qw0 &= pValue2->QWords.qw0;
+ pValue1Result->QWords.qw1 &= pValue2->QWords.qw1;
+ pValue1Result->QWords.qw2 &= pValue2->QWords.qw2;
+ pValue1Result->QWords.qw3 &= pValue2->QWords.qw3;
+ return pValue1Result;
+}
+
+
+#if 0
+/**
+ * Performs a bitwise AND of a 256-bit unsigned integer value and a mask made
+ * up of the first N bits, assigning the result to the the 256-bit value.
+ *
+ * @returns pValueResult.
+ * @param pValueResult The value and result.
+ * @param cBits The number of bits to AND (counting from the first
+ * bit).
+ */
+DECLINLINE(PRTUINT256U) RTUInt256AssignAndNFirstBits(PRTUINT256U pValueResult, unsigned cBits)
+{
+ if (cBits <= 64)
+ {
+ if (cBits != 64)
+ pValueResult->s.Lo &= (RT_BIT_64(cBits) - 1);
+ pValueResult->s.Hi = 0;
+ }
+ else if (cBits < 256)
+ pValueResult->s.Hi &= (RT_BIT_64(cBits - 64) - 1);
+/** @todo \#if ARCH_BITS >= 64 */
+ return pValueResult;
+}
+#endif
+
+
+/**
+ * Performs a bitwise OR of two 256-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(PRTUINT256U) RTUInt256AssignOr(PRTUINT256U pValue1Result, PCRTUINT256U pValue2)
+{
+ pValue1Result->QWords.qw0 |= pValue2->QWords.qw0;
+ pValue1Result->QWords.qw1 |= pValue2->QWords.qw1;
+ pValue1Result->QWords.qw2 |= pValue2->QWords.qw2;
+ pValue1Result->QWords.qw3 |= pValue2->QWords.qw3;
+ return pValue1Result;
+}
+
+
+DECLINLINE(PRTUINT256U) RTUInt256BitSet(PRTUINT256U pValueResult, unsigned iBit);
+
+/**
+ * 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(PRTUINT256U) RTUInt256AssignOrBit(PRTUINT256U pValue1Result, uint32_t iBit)
+{
+ return RTUInt256BitSet(pValue1Result, (unsigned)iBit);
+}
+
+
+/**
+ * Performs a bitwise XOR of two 256-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(PRTUINT256U) RTUInt256AssignXor(PRTUINT256U pValue1Result, PCRTUINT256U pValue2)
+{
+ pValue1Result->QWords.qw0 ^= pValue2->QWords.qw0;
+ pValue1Result->QWords.qw1 ^= pValue2->QWords.qw1;
+ pValue1Result->QWords.qw2 ^= pValue2->QWords.qw2;
+ pValue1Result->QWords.qw3 ^= pValue2->QWords.qw3;
+ return pValue1Result;
+}
+
+
+/**
+ * Performs a bitwise left shift on a 256-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 - signed. Negative
+ * values are translated to right shifts. If the
+ * absolute value is 256 or higher, the value is set to
+ * zero.
+ *
+ * @note This works differently from RTUInt256ShiftLeft and
+ * RTUInt256ShiftRight in that the shift count is signed and not masked
+ * by 255.
+ */
+DECLINLINE(PRTUINT256U) RTUInt256AssignShiftLeft(PRTUINT256U pValueResult, int cBits)
+{
+ if (cBits == 0)
+ return pValueResult;
+ if (cBits > 0)
+ {
+ /* (left shift) */
+ if (cBits < 256)
+ {
+ RTUINT256U const InVal = *pValueResult;
+ return RTUInt256ShiftLeft(pValueResult, &InVal, cBits);
+ }
+ }
+ else if (cBits > -256)
+ {
+ /* (right shift) */
+ cBits = -cBits;
+ RTUINT256U const InVal = *pValueResult;
+ return RTUInt256ShiftRight(pValueResult, &InVal, cBits);
+ }
+ return RTUInt256SetZero(pValueResult);
+}
+
+
+/**
+ * Performs a bitwise left shift on a 256-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 - signed. Negative
+ * values are translated to left shifts. If the
+ * absolute value is 256 or higher, the value is set to
+ * zero.
+ *
+ * @note This works differently from RTUInt256ShiftRight and
+ * RTUInt256ShiftLeft in that the shift count is signed and not masked
+ * by 255.
+ */
+DECLINLINE(PRTUINT256U) RTUInt256AssignShiftRight(PRTUINT256U pValueResult, int cBits)
+{
+ if (cBits == 0)
+ return pValueResult;
+ if (cBits > 0)
+ {
+ /* (right shift) */
+ if (cBits < 256)
+ {
+ RTUINT256U const InVal = *pValueResult;
+ return RTUInt256ShiftRight(pValueResult, &InVal, cBits);
+ }
+ }
+ else if (cBits > -256)
+ {
+ /* (left shift) */
+ cBits = -cBits;
+ RTUINT256U const InVal = *pValueResult;
+ return RTUInt256ShiftLeft(pValueResult, &InVal, cBits);
+ }
+ return RTUInt256SetZero(pValueResult);
+}
+
+
+/**
+ * Performs a bitwise NOT on a 256-bit unsigned integer value, assigning the
+ * result to it.
+ *
+ * @returns pValueResult
+ * @param pValueResult The value and result.
+ */
+DECLINLINE(PRTUINT256U) RTUInt256AssignBitwiseNot(PRTUINT256U pValueResult)
+{
+ pValueResult->QWords.qw0 = ~pValueResult->QWords.qw0;
+ pValueResult->QWords.qw1 = ~pValueResult->QWords.qw1;
+ pValueResult->QWords.qw2 = ~pValueResult->QWords.qw2;
+ pValueResult->QWords.qw3 = ~pValueResult->QWords.qw3;
+ return pValueResult;
+}
+
+
+/**
+ * Performs a boolean NOT on a 256-bit unsigned integer value, assigning the
+ * result to it.
+ *
+ * @returns pValueResult
+ * @param pValueResult The value and result.
+ */
+DECLINLINE(PRTUINT256U) RTUInt256AssignBooleanNot(PRTUINT256U pValueResult)
+{
+ return RTUInt256AssignBoolean(pValueResult, RTUInt256IsZero(pValueResult));
+}
+
+
+/**
+ * Compares two 256-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) RTUInt256Compare(PCRTUINT256U pValue1, PCRTUINT256U pValue2)
+{
+ if (pValue1->QWords.qw3 != pValue2->QWords.qw3)
+ return pValue1->QWords.qw3 > pValue2->QWords.qw3 ? 1 : -1;
+ if (pValue1->QWords.qw2 != pValue2->QWords.qw2)
+ return pValue1->QWords.qw2 > pValue2->QWords.qw2 ? 1 : -1;
+ if (pValue1->QWords.qw1 != pValue2->QWords.qw1)
+ return pValue1->QWords.qw1 > pValue2->QWords.qw1 ? 1 : -1;
+ if (pValue1->QWords.qw0 != pValue2->QWords.qw0)
+ return pValue1->QWords.qw3 > pValue2->QWords.qw3 ? 1 : -1;
+ return 0;
+}
+
+
+/**
+ * Tests if a 256-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) RTUInt256IsSmaller(PCRTUINT256U pValue1, PCRTUINT256U pValue2)
+{
+ return pValue1->QWords.qw3 < pValue2->QWords.qw3
+ || ( pValue1->QWords.qw3 == pValue2->QWords.qw3
+ && ( pValue1->QWords.qw2 < pValue2->QWords.qw2
+ || ( pValue1->QWords.qw2 == pValue2->QWords.qw2
+ && ( pValue1->QWords.qw1 < pValue2->QWords.qw1
+ || ( pValue1->QWords.qw1 == pValue2->QWords.qw1
+ && pValue1->QWords.qw0 < pValue2->QWords.qw0)))));
+}
+
+
+/**
+ * Tests if a 256-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) RTUInt256IsLarger(PCRTUINT256U pValue1, PCRTUINT256U pValue2)
+{
+ return pValue1->QWords.qw3 > pValue2->QWords.qw3
+ || ( pValue1->QWords.qw3 == pValue2->QWords.qw3
+ && ( pValue1->QWords.qw2 > pValue2->QWords.qw2
+ || ( pValue1->QWords.qw2 == pValue2->QWords.qw2
+ && ( pValue1->QWords.qw1 > pValue2->QWords.qw1
+ || ( pValue1->QWords.qw1 == pValue2->QWords.qw1
+ && pValue1->QWords.qw0 > pValue2->QWords.qw0)))));
+}
+
+
+/**
+ * Tests if a 256-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) RTUInt256IsLargerOrEqual(PCRTUINT256U pValue1, PCRTUINT256U pValue2)
+{
+ return pValue1->QWords.qw3 > pValue2->QWords.qw3
+ || ( pValue1->QWords.qw3 == pValue2->QWords.qw3
+ && ( pValue1->QWords.qw2 > pValue2->QWords.qw2
+ || ( pValue1->QWords.qw2 == pValue2->QWords.qw2
+ && ( pValue1->QWords.qw1 > pValue2->QWords.qw1
+ || ( pValue1->QWords.qw1 == pValue2->QWords.qw1
+ && pValue1->QWords.qw0 >= pValue2->DWords.dw0)))));
+}
+
+
+/**
+ * Tests if two 256-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) RTUInt256IsEqual(PCRTUINT256U pValue1, PCRTUINT256U pValue2)
+{
+ return pValue1->QWords.qw0 == pValue2->QWords.qw0
+ && pValue1->QWords.qw1 == pValue2->QWords.qw1
+ && pValue1->QWords.qw2 == pValue2->QWords.qw2
+ && pValue1->QWords.qw3 == pValue2->QWords.qw3;
+}
+
+
+/**
+ * Tests if two 256-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) RTUInt256IsNotEqual(PCRTUINT256U pValue1, PCRTUINT256U pValue2)
+{
+ return !RTUInt256IsEqual(pValue1, pValue2);
+}
+
+
+/**
+ * Sets a bit in a 256-bit unsigned integer type.
+ *
+ * @returns pValueResult.
+ * @param pValueResult The input and output value.
+ * @param iBit The bit to set.
+ */
+DECLINLINE(PRTUINT256U) RTUInt256BitSet(PRTUINT256U pValueResult, unsigned iBit)
+{
+ if (iBit < 256)
+ {
+ unsigned idxQWord = iBit >> 6;
+#ifdef RT_BIG_ENDIAN
+ idxQWord = RT_ELEMENTS(pValueResult->au64) - idxQWord;
+#endif
+ iBit &= 0x3f;
+ pValueResult->au64[idxQWord] |= RT_BIT_64(iBit);
+ }
+ return pValueResult;
+}
+
+
+/**
+ * Sets a bit in a 256-bit unsigned integer type.
+ *
+ * @returns pValueResult.
+ * @param pValueResult The input and output value.
+ * @param iBit The bit to set.
+ */
+DECLINLINE(PRTUINT256U) RTUInt256BitClear(PRTUINT256U pValueResult, unsigned iBit)
+{
+ if (iBit < 256)
+ {
+ unsigned idxQWord = iBit >> 6;
+#ifdef RT_BIG_ENDIAN
+ idxQWord = RT_ELEMENTS(pValueResult->au64) - idxQWord;
+#endif
+ iBit &= 0x3f;
+ pValueResult->au64[idxQWord] &= ~RT_BIT_64(iBit);
+ }
+ return pValueResult;
+}
+
+
+/**
+ * Tests if a bit in a 256-bit unsigned integer value is set.
+ *
+ * @returns pValueResult.
+ * @param pValueResult The input and output value.
+ * @param iBit The bit to test.
+ */
+DECLINLINE(bool) RTUInt256BitTest(PRTUINT256U pValueResult, unsigned iBit)
+{
+ bool fRc;
+ if (iBit < 256)
+ {
+ unsigned idxQWord = iBit >> 6;
+#ifdef RT_BIG_ENDIAN
+ idxQWord = RT_ELEMENTS(pValueResult->au64) - idxQWord;
+#endif
+ iBit &= 0x3f;
+ fRc = RT_BOOL(pValueResult->au64[idxQWord] & RT_BIT_64(iBit));
+ }
+ else
+ fRc = false;
+ return fRc;
+}
+
+
+/**
+ * Set a range of bits a 256-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(PRTUINT256U) RTUInt256BitSetRange(PRTUINT256U pValueResult, unsigned iFirstBit, unsigned cBits)
+{
+ /* bounds check & fix. */
+ if (iFirstBit < 256)
+ {
+ if (iFirstBit + cBits > 256)
+ cBits = 256 - iFirstBit;
+
+ /* Work the au64 array: */
+#ifdef RT_BIG_ENDIAN
+ int idxQWord = RT_ELEMENTS(pValueResult->au64) - (iFirstBit >> 6);
+ int const idxInc = -1;
+#else
+ int idxQWord = iFirstBit >> 6;
+ int const idxInc = 1;
+#endif
+ while (cBits > 0)
+ {
+ unsigned iQWordFirstBit = iFirstBit & 0x3f;
+ unsigned cQWordBits = cBits + iQWordFirstBit >= 64 ? 64 - iQWordFirstBit : cBits;
+ pValueResult->au64[idxQWord] |= cQWordBits < 64 ? (RT_BIT_64(cQWordBits) - 1) << iQWordFirstBit : UINT64_MAX;
+
+ idxQWord += idxInc;
+ iFirstBit += cQWordBits;
+ cBits -= cQWordBits;
+ }
+ }
+ return pValueResult;
+}
+
+
+/**
+ * Test if all the bits of a 256-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) RTUInt256BitAreAllSet(PRTUINT256U pValue)
+{
+ return pValue->QWords.qw0 == UINT64_MAX
+ && pValue->QWords.qw1 == UINT64_MAX
+ && pValue->QWords.qw2 == UINT64_MAX
+ && pValue->QWords.qw3 == UINT64_MAX;
+}
+
+
+/**
+ * Test if all the bits of a 256-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) RTUInt256BitAreAllClear(PRTUINT256U pValue)
+{
+ return RTUInt256IsZero(pValue);
+}
+
+
+/**
+ * Number of significant bits in the value.
+ *
+ * This is the same a ASMBitLastSetU64 and ASMBitLastSetU32.
+ *
+ * @returns 0 if zero, 1-base index of the last bit set.
+ * @param pValue The value to examine.
+ */
+DECLINLINE(uint32_t) RTUInt256BitCount(PCRTUINT256U pValue)
+{
+ uint64_t u64;
+ uint32_t cBits;
+ if ((u64 = pValue->QWords.qw3) != 0)
+ cBits = 192;
+ else if ((u64 = pValue->QWords.qw2) != 0)
+ cBits = 128;
+ else if ((u64 = pValue->QWords.qw1) != 0)
+ cBits = 64;
+ else
+ {
+ u64 = pValue->QWords.qw0;
+ cBits = 0;
+ }
+ return cBits + ASMBitLastSetU64(u64);
+}
+
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_uint256_h */
+
diff --git a/include/iprt/uint32.h b/include/iprt/uint32.h
new file mode 100644
index 00000000..46140142
--- /dev/null
+++ b/include/iprt/uint32.h
@@ -0,0 +1,1068 @@
+/** @file
+ * IPRT - RTUINT32U methods for old 16-bit compilers (mainly for division).
+ */
+
+/*
+ * Copyright (C) 2011-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_uint32_h
+#define IPRT_INCLUDED_uint32_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+#include <iprt/asm.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_uint32 RTUInt32 - 32-bit Unsigned Integer Methods for 16-bit compilers.
+ * @ingroup grp_rt
+ * @{
+ */
+
+#define RTUINT32_HAVE_32BIT_BASICS
+
+
+/**
+ * Test if a 32-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) RTUInt32IsZero(PRTUINT32U pValue)
+{
+ return pValue->s.Lo == 0
+ && pValue->s.Hi == 0;
+}
+
+
+/**
+ * Set a 32-bit unsigned integer value to zero.
+ *
+ * @returns pResult
+ * @param pResult The result variable.
+ */
+DECLINLINE(PRTUINT32U) RTUInt32SetZero(PRTUINT32U pResult)
+{
+ pResult->s.Hi = 0;
+ pResult->s.Lo = 0;
+ return pResult;
+}
+
+
+/**
+ * Set a 32-bit unsigned integer value to the maximum value.
+ *
+ * @returns pResult
+ * @param pResult The result variable.
+ */
+DECLINLINE(PRTUINT32U) RTUInt32SetMax(PRTUINT32U pResult)
+{
+ pResult->s.Hi = UINT16_MAX;
+ pResult->s.Lo = UINT16_MAX;
+ return pResult;
+}
+
+
+
+
+/**
+ * Adds two 32-bit unsigned integer values.
+ *
+ * @returns pResult
+ * @param pResult The result variable.
+ * @param pValue1 The first value.
+ * @param pValue2 The second value.
+ */
+DECLINLINE(PRTUINT32U) RTUInt32Add(PRTUINT32U pResult, PCRTUINT32U pValue1, PCRTUINT32U pValue2)
+{
+#ifdef RTUINT32_HAVE_32BIT_BASICS
+ pResult->u = pValue1->u + pValue2->u;
+#else
+ 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++;
+#endif
+ return pResult;
+}
+
+
+/**
+ * Adds a 32-bit and a 16-bit unsigned integer values.
+ *
+ * @returns pResult
+ * @param pResult The result variable.
+ * @param pValue1 The first value.
+ * @param uValue2 The second value, 16-bit.
+ */
+DECLINLINE(PRTUINT32U) RTUInt32AddU16(PRTUINT32U pResult, PCRTUINT32U pValue1, uint16_t uValue2)
+{
+#ifdef RTUINT32_HAVE_32BIT_BASICS
+ pResult->u = pValue1->u + uValue2;
+#else
+ pResult->s.Hi = pValue1->s.Hi;
+ pResult->s.Lo = pValue1->s.Lo + uValue2;
+ if (pResult->s.Lo < pValue1->s.Lo)
+ pResult->s.Hi++;
+#endif
+ return pResult;
+}
+
+
+/**
+ * Subtracts a 32-bit unsigned integer value from another.
+ *
+ * @returns pResult
+ * @param pResult The result variable.
+ * @param pValue1 The minuend value.
+ * @param pValue2 The subtrahend value.
+ */
+DECLINLINE(PRTUINT32U) RTUInt32Sub(PRTUINT32U pResult, PCRTUINT32U pValue1, PCRTUINT32U pValue2)
+{
+#ifdef RTUINT32_HAVE_32BIT_BASICS
+ pResult->u = pValue1->u - pValue2->u;
+#else
+ 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--;
+#endif
+ return pResult;
+}
+
+
+/**
+ * Multiplies two 32-bit unsigned integer values.
+ *
+ * @returns pResult
+ * @param pResult The result variable.
+ * @param pValue1 The first value.
+ * @param pValue2 The second value.
+ */
+DECLINLINE(PRTUINT32U) RTUInt32Mul(PRTUINT32U pResult, PCRTUINT32U pValue1, PCRTUINT32U pValue2)
+{
+ pResult->u = (uint32_t)pValue1->s.Lo * pValue2->s.Lo;
+ pResult->s.Hi += pValue1->s.Hi * pValue2->s.Lo;
+ pResult->s.Hi += pValue1->s.Lo * pValue2->s.Hi;
+
+ return pResult;
+}
+
+
+/**
+ * Multiplies an 32-bit unsigned integer by a 16-bit unsigned integer value.
+ *
+ * @returns pResult
+ * @param pResult The result variable.
+ * @param pValue1 The first value.
+ * @param uValue2 The second value, 16-bit.
+ */
+DECLINLINE(PRTUINT32U) RTUInt32MulByU16(PRTUINT32U pResult, PCRTUINT32U pValue1, uint16_t uValue2)
+{
+ pResult->u = (uint32_t)pValue1->s.Lo * uValue2;
+ pResult->s.Hi += pValue1->s.Hi * uValue2;
+ return pResult;
+}
+
+
+DECLINLINE(PRTUINT32U) RTUInt32DivRem(PRTUINT32U pQuotient, PRTUINT32U pRemainder, PCRTUINT32U pValue1, PCRTUINT32U pValue2);
+
+/**
+ * Divides a 32-bit unsigned integer value by another.
+ *
+ * @returns pResult
+ * @param pResult The result variable.
+ * @param pValue1 The dividend value.
+ * @param pValue2 The divisor value.
+ */
+DECLINLINE(PRTUINT32U) RTUInt32Div(PRTUINT32U pResult, PCRTUINT32U pValue1, PCRTUINT32U pValue2)
+{
+ RTUINT32U Ignored;
+ return RTUInt32DivRem(pResult, &Ignored, pValue1, pValue2);
+}
+
+
+/**
+ * Divides a 32-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(PRTUINT32U) RTUInt32Mod(PRTUINT32U pResult, PCRTUINT32U pValue1, PCRTUINT32U pValue2)
+{
+ RTUINT32U Ignored;
+ RTUInt32DivRem(&Ignored, pResult, pValue1, pValue2);
+ return pResult;
+}
+
+
+/**
+ * Bitwise AND of two 32-bit unsigned integer values.
+ *
+ * @returns pResult
+ * @param pResult The result variable.
+ * @param pValue1 The first value.
+ * @param pValue2 The second value.
+ */
+DECLINLINE(PRTUINT32U) RTUInt32And(PRTUINT32U pResult, PCRTUINT32U pValue1, PCRTUINT32U 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 32-bit unsigned integer values.
+ *
+ * @returns pResult
+ * @param pResult The result variable.
+ * @param pValue1 The first value.
+ * @param pValue2 The second value.
+ */
+DECLINLINE(PRTUINT32U) RTUInt32Or( PRTUINT32U pResult, PCRTUINT32U pValue1, PCRTUINT32U 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 32-bit unsigned integer values.
+ *
+ * @returns pResult
+ * @param pResult The result variable.
+ * @param pValue1 The first value.
+ * @param pValue2 The second value.
+ */
+DECLINLINE(PRTUINT32U) RTUInt32Xor(PRTUINT32U pResult, PCRTUINT32U pValue1, PCRTUINT32U pValue2)
+{
+ pResult->s.Hi = pValue1->s.Hi ^ pValue2->s.Hi;
+ pResult->s.Lo = pValue1->s.Lo ^ pValue2->s.Lo;
+ return pResult;
+}
+
+
+/**
+ * Shifts a 32-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(PRTUINT32U) RTUInt32ShiftLeft(PRTUINT32U pResult, PCRTUINT32U pValue, int cBits)
+{
+ cBits &= 31;
+#ifdef RTUINT32_HAVE_32BIT_BASICS
+ pResult->u = pValue->u << cBits;
+#else
+ if (cBits < 16)
+ {
+ pResult->s.Lo = pValue->s.Lo << cBits;
+ pResult->s.Hi = (pValue->s.Hi << cBits) | (pValue->s.Lo >> (16 - cBits));
+ }
+ else
+ {
+ pResult->s.Lo = 0;
+ pResult->s.Hi = pValue->s.Lo << (cBits - 16);
+ }
+#endif
+ return pResult;
+}
+
+
+/**
+ * Shifts a 32-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(PRTUINT32U) RTUInt32ShiftRight(PRTUINT32U pResult, PCRTUINT32U pValue, int cBits)
+{
+ cBits &= 31;
+#ifdef RTUINT32_HAVE_32BIT_BASICS
+ pResult->u = pValue->u >> cBits;
+#else
+ if (cBits < 16)
+ {
+ pResult->s.Hi = pValue->s.Hi >> cBits;
+ pResult->s.Lo = (pValue->s.Lo >> cBits) | (pValue->s.Hi << (16 - cBits));
+ }
+ else
+ {
+ pResult->s.Hi = 0;
+ pResult->s.Lo = pValue->s.Hi >> (cBits - 16);
+ }
+#endif
+ return pResult;
+}
+
+
+/**
+ * Boolean not (result 0 or 1).
+ *
+ * @returns pResult.
+ * @param pResult The result variable.
+ * @param pValue The value.
+ */
+DECLINLINE(PRTUINT32U) RTUInt32BooleanNot(PRTUINT32U pResult, PCRTUINT32U 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 32 bits).
+ *
+ * @returns pResult.
+ * @param pResult The result variable.
+ * @param pValue The value.
+ */
+DECLINLINE(PRTUINT32U) RTUInt32BitwiseNot(PRTUINT32U pResult, PCRTUINT32U pValue)
+{
+ pResult->s.Hi = ~pValue->s.Hi;
+ pResult->s.Lo = ~pValue->s.Lo;
+ return pResult;
+}
+
+
+/**
+ * Assigns one 32-bit unsigned integer value to another.
+ *
+ * @returns pResult
+ * @param pResult The result variable.
+ * @param pValue The value to assign.
+ */
+DECLINLINE(PRTUINT32U) RTUInt32Assign(PRTUINT32U pResult, PCRTUINT32U pValue)
+{
+ pResult->s.Hi = pValue->s.Hi;
+ pResult->s.Lo = pValue->s.Lo;
+ return pResult;
+}
+
+
+/**
+ * Assigns a boolean value to 32-bit unsigned integer.
+ *
+ * @returns pValueResult
+ * @param pValueResult The result variable.
+ * @param fValue The boolean value.
+ */
+DECLINLINE(PRTUINT32U) RTUInt32AssignBoolean(PRTUINT32U pValueResult, bool fValue)
+{
+ pValueResult->s.Lo = fValue;
+ pValueResult->s.Hi = 0;
+ return pValueResult;
+}
+
+
+/**
+ * Assigns a 8-bit unsigned integer value to 32-bit unsigned integer.
+ *
+ * @returns pValueResult
+ * @param pValueResult The result variable.
+ * @param u8Value The 8-bit unsigned integer value.
+ */
+DECLINLINE(PRTUINT32U) RTUInt32AssignU8(PRTUINT32U pValueResult, uint8_t u8Value)
+{
+ pValueResult->s.Lo = u8Value;
+ pValueResult->s.Hi = 0;
+ return pValueResult;
+}
+
+
+/**
+ * Assigns a 16-bit unsigned integer value to 32-bit unsigned integer.
+ *
+ * @returns pValueResult
+ * @param pValueResult The result variable.
+ * @param u16Value The 16-bit unsigned integer value.
+ */
+DECLINLINE(PRTUINT32U) RTUInt32AssignU16(PRTUINT32U pValueResult, uint16_t u16Value)
+{
+ pValueResult->s.Lo = u16Value;
+ pValueResult->s.Hi = 0;
+ return pValueResult;
+}
+
+
+/**
+ * Adds two 32-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(PRTUINT32U) RTUInt32AssignAdd(PRTUINT32U pValue1Result, PCRTUINT32U pValue2)
+{
+#ifdef RTUINT32_HAVE_32BIT_BASICS
+ pValue1Result->u += pValue2->u;
+#else
+ uint16_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;
+#endif
+ return pValue1Result;
+}
+
+
+/**
+ * Subtracts two 32-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(PRTUINT32U) RTUInt32AssignSub(PRTUINT32U pValue1Result, PCRTUINT32U pValue2)
+{
+#ifdef RTUINT32_HAVE_32BIT_BASICS
+ pValue1Result->u -= pValue2->u;
+#else
+ 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;
+#endif
+ return pValue1Result;
+}
+
+
+/**
+ * Multiplies two 32-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(PRTUINT32U) RTUInt32AssignMul(PRTUINT32U pValue1Result, PCRTUINT32U pValue2)
+{
+ RTUINT32U Result;
+ RTUInt32Mul(&Result, pValue1Result, pValue2);
+ *pValue1Result = Result;
+ return pValue1Result;
+}
+
+
+/**
+ * Divides a 32-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(PRTUINT32U) RTUInt32AssignDiv(PRTUINT32U pValue1Result, PCRTUINT32U pValue2)
+{
+ RTUINT32U Result;
+ RTUINT32U Ignored;
+ RTUInt32DivRem(&Result, &Ignored, pValue1Result, pValue2);
+ *pValue1Result = Result;
+ return pValue1Result;
+}
+
+
+/**
+ * Divides a 32-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(PRTUINT32U) RTUInt32AssignMod(PRTUINT32U pValue1Result, PCRTUINT32U pValue2)
+{
+ RTUINT32U Ignored;
+ RTUINT32U Result;
+ RTUInt32DivRem(&Ignored, &Result, pValue1Result, pValue2);
+ *pValue1Result = Result;
+ return pValue1Result;
+}
+
+
+/**
+ * Performs a bitwise AND of two 32-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(PRTUINT32U) RTUInt32AssignAnd(PRTUINT32U pValue1Result, PCRTUINT32U pValue2)
+{
+ pValue1Result->s.Hi &= pValue2->s.Hi;
+ pValue1Result->s.Lo &= pValue2->s.Lo;
+ return pValue1Result;
+}
+
+
+/**
+ * Performs a bitwise AND of a 32-bit unsigned integer value and a mask made up
+ * of the first N bits, assigning the result to the the 32-bit value.
+ *
+ * @returns pValueResult.
+ * @param pValueResult The value and result.
+ * @param cBits The number of bits to AND (counting from the first
+ * bit).
+ */
+DECLINLINE(PRTUINT32U) RTUInt32AssignAndNFirstBits(PRTUINT32U pValueResult, unsigned cBits)
+{
+#ifdef RTUINT32_HAVE_32BIT_BASICS
+ if (cBits < 32)
+ pValueResult->u &= RT_BIT_32(cBits) - 1;
+#else
+ if (cBits <= 16)
+ {
+ if (cBits != 16)
+ pValueResult->s.Lo &= (UINT16_C(1) << cBits) - 1;
+ pValueResult->s.Hi = 0;
+ }
+ else if (cBits < 16)
+ pValueResult->s.Hi &= (UINT16_C(1) << (cBits - 16)) - 1;
+#endif
+ return pValueResult;
+}
+
+
+/**
+ * Performs a bitwise OR of two 32-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(PRTUINT32U) RTUInt32AssignOr(PRTUINT32U pValue1Result, PCRTUINT32U pValue2)
+{
+ pValue1Result->s.Hi |= pValue2->s.Hi;
+ pValue1Result->s.Lo |= pValue2->s.Lo;
+ 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(PRTUINT32U) RTUInt32AssignOrBit(PRTUINT32U pValue1Result, unsigned iBit)
+{
+#ifdef RTUINT32_HAVE_32BIT_BASICS
+ pValue1Result->u |= RT_BIT_32(iBit);
+#else
+ if (iBit >= 32)
+ pValue1Result->s.Hi |= UINT16_C(1) << (iBit - 32);
+ else
+ pValue1Result->s.Lo |= UINT16_C(1) << iBit;
+#endif
+ return pValue1Result;
+}
+
+
+
+/**
+ * Performs a bitwise XOR of two 32-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(PRTUINT32U) RTUInt32AssignXor(PRTUINT32U pValue1Result, PCRTUINT32U pValue2)
+{
+ pValue1Result->s.Hi ^= pValue2->s.Hi;
+ pValue1Result->s.Lo ^= pValue2->s.Lo;
+ return pValue1Result;
+}
+
+
+/**
+ * Performs a bitwise left shift on a 32-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(PRTUINT32U) RTUInt32AssignShiftLeft(PRTUINT32U pValueResult, int cBits)
+{
+#ifndef RTUINT32_HAVE_32BIT_BASICS
+ RTUINT32U const InVal = *pValueResult;
+#endif
+ if (cBits > 0)
+ {
+ /* (left shift) */
+ cBits &= 31;
+#ifdef RTUINT32_HAVE_32BIT_BASICS
+ pValueResult->u <<= cBits;
+#else
+ if (cBits >= 16)
+ {
+ pValueResult->s.Lo = 0;
+ pValueResult->s.Hi = InVal.s.Lo << (cBits - 16);
+ }
+ else
+ {
+ pValueResult->s.Hi = InVal.s.Hi << cBits;
+ pValueResult->s.Hi |= InVal.s.Lo >> (16 - cBits);
+ pValueResult->s.Lo = InVal.s.Lo << cBits;
+ }
+#endif
+ }
+ else if (cBits < 0)
+ {
+ /* (right shift) */
+ cBits = -cBits;
+ cBits &= 31;
+#ifdef RTUINT32_HAVE_32BIT_BASICS
+ pValueResult->u >>= cBits;
+#else
+ if (cBits >= 16)
+ {
+ pValueResult->s.Hi = 0;
+ pValueResult->s.Lo = InVal.s.Hi >> (cBits - 16);
+ }
+ else
+ {
+ pValueResult->s.Lo = InVal.s.Lo >> cBits;
+ pValueResult->s.Lo |= InVal.s.Hi << (16 - cBits);
+ pValueResult->s.Hi = InVal.s.Hi >> cBits;
+ }
+#endif
+ }
+ return pValueResult;
+}
+
+
+/**
+ * Performs a bitwise left shift on a 32-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(PRTUINT32U) RTUInt32AssignShiftRight(PRTUINT32U pValueResult, int cBits)
+{
+ return RTUInt32AssignShiftLeft(pValueResult, -cBits);
+}
+
+
+/**
+ * Performs a bitwise NOT on a 32-bit unsigned integer value, assigning the
+ * result to it.
+ *
+ * @returns pValueResult
+ * @param pValueResult The value and result.
+ */
+DECLINLINE(PRTUINT32U) RTUInt32AssignBitwiseNot(PRTUINT32U pValueResult)
+{
+ pValueResult->s.Hi = ~pValueResult->s.Hi;
+ pValueResult->s.Lo = ~pValueResult->s.Lo;
+ return pValueResult;
+}
+
+
+/**
+ * Performs a boolean NOT on a 32-bit unsigned integer value, assigning the
+ * result to it.
+ *
+ * @returns pValueResult
+ * @param pValueResult The value and result.
+ */
+DECLINLINE(PRTUINT32U) RTUInt32AssignBooleanNot(PRTUINT32U pValueResult)
+{
+ return RTUInt32AssignBoolean(pValueResult, RTUInt32IsZero(pValueResult));
+}
+
+
+/**
+ * Compares two 32-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) RTUInt32Compare(PCRTUINT32U pValue1, PCRTUINT32U pValue2)
+{
+ 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;
+}
+
+
+/**
+ * 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) RTUInt32IsSmaller(PCRTUINT32U pValue1, PCRTUINT32U pValue2)
+{
+#ifdef RTUINT32_HAVE_32BIT_BASICS
+ return pValue1->u < pValue2->u;
+#else
+ return pValue1->s.Hi < pValue2->s.Hi
+ || ( pValue1->s.Hi == pValue2->s.Hi
+ && pValue1->s.Lo < pValue2->s.Lo);
+#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) RTUInt32IsLarger(PCRTUINT32U pValue1, PCRTUINT32U pValue2)
+{
+#ifdef RTUINT32_HAVE_32BIT_BASICS
+ return pValue1->u > pValue2->u;
+#else
+ return pValue1->s.Hi > pValue2->s.Hi
+ || ( pValue1->s.Hi == pValue2->s.Hi
+ && pValue1->s.Lo > pValue2->s.Lo);
+#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) RTUInt32IsLargerOrEqual(PCRTUINT32U pValue1, PCRTUINT32U pValue2)
+{
+#ifdef RTUINT32_HAVE_32BIT_BASICS
+ return pValue1->u >= pValue2->u;
+#else
+ return pValue1->s.Hi > pValue2->s.Hi
+ || ( pValue1->s.Hi == pValue2->s.Hi
+ && pValue1->s.Lo >= pValue2->s.Lo);
+#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) RTUInt32IsEqual(PCRTUINT32U pValue1, PCRTUINT32U pValue2)
+{
+#ifdef RTUINT32_HAVE_32BIT_BASICS
+ return pValue1->u == pValue2->u;
+#else
+ return pValue1->s.Hi == pValue2->s.Hi
+ && pValue1->s.Lo == pValue2->s.Lo;
+#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) RTUInt32IsNotEqual(PCRTUINT32U pValue1, PCRTUINT32U pValue2)
+{
+ return !RTUInt32IsEqual(pValue1, pValue2);
+}
+
+
+/**
+ * Sets a bit in a 32-bit unsigned integer type.
+ *
+ * @returns pValueResult.
+ * @param pValueResult The input and output value.
+ * @param iBit The bit to set.
+ */
+DECLINLINE(PRTUINT32U) RTUInt32BitSet(PRTUINT32U pValueResult, unsigned iBit)
+{
+#ifdef RTUINT32_HAVE_32BIT_BASICS
+ if (iBit < 32)
+ pValueResult->u |= RT_BIT_32(iBit);
+#else
+ if (iBit < 16)
+ pValueResult->s.Lo |= UINT16_C(1) << iBit;
+ else if (iBit < 32)
+ pValueResult->s.Hi |= UINT16_C(1) << (iBit - 32);
+#endif
+ return pValueResult;
+}
+
+
+/**
+ * Sets a bit in a 32-bit unsigned integer type.
+ *
+ * @returns pValueResult.
+ * @param pValueResult The input and output value.
+ * @param iBit The bit to set.
+ */
+DECLINLINE(PRTUINT32U) RTUInt32BitClear(PRTUINT32U pValueResult, unsigned iBit)
+{
+#ifdef RTUINT32_HAVE_32BIT_BASICS
+ if (iBit < 32)
+ pValueResult->u &= ~RT_BIT_32(iBit);
+
+#else
+ if (iBit < 16)
+ pValueResult->s.Lo &= ~RT_BIT_32(iBit);
+ else if (iBit < 32)
+ pValueResult->s.Hi &= ~RT_BIT_32(iBit - 32);
+#endif
+ return pValueResult;
+}
+
+
+/**
+ * Tests if a bit in a 32-bit unsigned integer value is set.
+ *
+ * @returns pValueResult.
+ * @param pValueResult The input and output value.
+ * @param iBit The bit to test.
+ */
+DECLINLINE(bool) RTUInt32BitTest(PRTUINT32U pValueResult, unsigned iBit)
+{
+ bool fRc;
+#ifdef RTUINT32_HAVE_32BIT_BASICS
+ if (iBit < 32)
+ fRc = RT_BOOL(pValueResult->u & RT_BIT_32(iBit));
+#else
+ if (iBit < 16)
+ fRc = RT_BOOL(pValueResult->s.Lo & (UINT16_C(1) << iBit));
+ else if (iBit < 32)
+ fRc = RT_BOOL(pValueResult->s.Hi & (UINT16_C(1) << (iBit - 64)));
+#endif
+ else
+ fRc = false;
+ return fRc;
+}
+
+
+/**
+ * Set a range of bits a 32-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(PRTUINT32U) RTUInt32BitSetRange(PRTUINT32U pValueResult, unsigned iFirstBit, unsigned cBits)
+{
+ /* bounds check & fix. */
+ if (iFirstBit < 32)
+ {
+#ifdef RTUINT32_HAVE_32BIT_BASICS
+ if (iFirstBit + cBits < 32)
+ pValueResult->u |= (RT_BIT_32(cBits) - 1) << iFirstBit;
+ else
+ pValueResult->u = UINT32_MAX << iFirstBit;
+#else
+ if (iFirstBit + cBits > 32)
+ cBits = 32 - iFirstBit;
+ if (iFirstBit + cBits < 16)
+ pValueResult->s.Lo |= ((UINT16_C(1) << cBits) - 1) << iFirstBit;
+ else if (iFirstBit + cBits < 32 && iFirstBit >= 16)
+ pValueResult->s.Hi |= ((UINT16_C(1) << cBits) - 1) << (iFirstBit - 16);
+ else
+ while (cBits-- > 0)
+ RTUInt32BitSet(pValueResult, iFirstBit++);
+#endif
+ }
+ return pValueResult;
+}
+
+
+/**
+ * Test if all the bits of a 32-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) RTUInt32BitAreAllSet(PRTUINT32U pValue)
+{
+ return pValue->s.Hi == UINT16_MAX
+ && pValue->s.Lo == UINT16_MAX;
+}
+
+
+/**
+ * Test if all the bits of a 32-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) RTUInt32BitAreAllClear(PRTUINT32U pValue)
+{
+ return RTUInt32IsZero(pValue);
+}
+
+
+DECLINLINE(unsigned) RTUInt32BitCount(PCRTUINT32U pValue)
+{
+ unsigned cBits;
+ if (pValue->s.Hi != 0)
+ cBits = 16 + ASMBitLastSetU16(pValue->s.Hi);
+ else
+ cBits = ASMBitLastSetU16(pValue->s.Lo);
+ return cBits;
+}
+
+
+/**
+ * Divides a 32-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(PRTUINT32U) RTUInt32DivRem(PRTUINT32U pQuotient, PRTUINT32U pRemainder, PCRTUINT32U pValue1, PCRTUINT32U 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)
+ {
+ RTUInt32SetZero(pRemainder);
+ *pQuotient = *pValue1;
+ return pQuotient;
+ }
+ /** @todo RTUInt32DivModByU32 */
+ }
+
+ /* Dividend is smaller? */
+ iDiff = RTUInt32Compare(pValue1, pValue2);
+ if (iDiff < 0)
+ {
+ *pRemainder = *pValue1;
+ RTUInt32SetZero(pQuotient);
+ }
+
+ /* The values are equal? */
+ else if (iDiff == 0)
+ {
+ RTUInt32SetZero(pRemainder);
+ RTUInt32AssignU8(pQuotient, 1);
+ }
+ else
+ {
+ /*
+ * Prepare.
+ */
+ unsigned iBitAdder = RTUInt32BitCount(pValue1) - RTUInt32BitCount(pValue2);
+ RTUINT32U NormDivisor = *pValue2;
+ if (iBitAdder)
+ {
+ RTUInt32ShiftLeft(&NormDivisor, pValue2, iBitAdder);
+ if (RTUInt32IsLarger(&NormDivisor, pValue1))
+ {
+ RTUInt32AssignShiftRight(&NormDivisor, 1);
+ iBitAdder--;
+ }
+ }
+ else
+ NormDivisor = *pValue2;
+
+ RTUInt32SetZero(pQuotient);
+ *pRemainder = *pValue1;
+
+ /*
+ * Do the division.
+ */
+ if (RTUInt32IsLargerOrEqual(pRemainder, pValue2))
+ {
+ for (;;)
+ {
+ if (RTUInt32IsLargerOrEqual(pRemainder, &NormDivisor))
+ {
+ RTUInt32AssignSub(pRemainder, &NormDivisor);
+ RTUInt32AssignOrBit(pQuotient, iBitAdder);
+ }
+ if (RTUInt32IsSmaller(pRemainder, pValue2))
+ break;
+ RTUInt32AssignShiftRight(&NormDivisor, 1);
+ iBitAdder--;
+ }
+ }
+ }
+ return pQuotient;
+}
+
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_uint32_h */
+
diff --git a/include/iprt/uint64.h b/include/iprt/uint64.h
new file mode 100644
index 00000000..8e9cf0e5
--- /dev/null
+++ b/include/iprt/uint64.h
@@ -0,0 +1,1343 @@
+/** @file
+ * IPRT - RTUINT64U methods for old 32-bit and 16-bit compilers.
+ */
+
+/*
+ * Copyright (C) 2011-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_uint64_h
+#define IPRT_INCLUDED_uint64_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#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 /* !IPRT_INCLUDED_uint64_h */
+
diff --git a/include/iprt/uni.h b/include/iprt/uni.h
new file mode 100644
index 00000000..ad804dcb
--- /dev/null
+++ b/include/iprt/uni.h
@@ -0,0 +1,491 @@
+/** @file
+ * IPRT - Unicode Code Points.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_uni_h
+#define IPRT_INCLUDED_uni_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+/** @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 /* !IPRT_INCLUDED_uni_h */
+
diff --git a/include/iprt/uri.h b/include/iprt/uri.h
new file mode 100644
index 00000000..75787cd4
--- /dev/null
+++ b/include/iprt/uri.h
@@ -0,0 +1,380 @@
+/** @file
+ * IPRT - Uniform Resource Identifier handling.
+ */
+
+/*
+ * Copyright (C) 2011-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_uri_h
+#define IPRT_INCLUDED_uri_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_uri RTUri - Uri parsing and creation
+ *
+ * URI parsing and creation based on RFC-3986.
+ *
+ * @remarks The whole specification isn't implemented and we only provide scheme
+ * specific special APIs for "file://".
+ *
+ * @ingroup grp_rt
+ * @{
+ */
+
+
+/**
+ * Parsed URI.
+ *
+ * @remarks This structure is subject to change.
+ */
+typedef struct RTURIPARSED
+{
+ /** Magic value (for internal use only). */
+ uint32_t u32Magic;
+ /** RTURIPARSED_F_XXX. */
+ uint32_t fFlags;
+
+ /** The length of the scheme. */
+ size_t cchScheme;
+
+ /** The offset into the string of the authority. */
+ size_t offAuthority;
+ /** The authority length.
+ * @remarks The authority component can be zero length, so to check whether
+ * it's there or not consult RTURIPARSED_F_HAVE_AUTHORITY. */
+ size_t cchAuthority;
+
+ /** The offset into the string of the path. */
+ size_t offPath;
+ /** The length of the path. */
+ size_t cchPath;
+
+ /** The offset into the string of the query. */
+ size_t offQuery;
+ /** The length of the query. */
+ size_t cchQuery;
+
+ /** The offset into the string of the fragment. */
+ size_t offFragment;
+ /** The length of the fragment. */
+ size_t cchFragment;
+
+ /** @name Authority subdivisions
+ * @{ */
+ /** If there is a userinfo part, this is the start of it. Otherwise it's the
+ * same as offAuthorityHost. */
+ size_t offAuthorityUsername;
+ /** The length of the username (zero if not present). */
+ size_t cchAuthorityUsername;
+ /** If there is a userinfo part containing a password, this is the start of it.
+ * Otherwise it's the same as offAuthorityHost. */
+ size_t offAuthorityPassword;
+ /** The length of the password (zero if not present). */
+ size_t cchAuthorityPassword;
+ /** The offset of the host part of the authority. */
+ size_t offAuthorityHost;
+ /** The length of the host part of the authority. */
+ size_t cchAuthorityHost;
+ /** The authority port number, UINT32_MAX if not present or empty. */
+ uint32_t uAuthorityPort;
+ /** @} */
+} RTURIPARSED;
+/** Pointer to a parsed URI. */
+typedef RTURIPARSED *PRTURIPARSED;
+/** Pointer to a const parsed URI. */
+typedef RTURIPARSED const *PCRTURIPARSED;
+
+/** @name RTURIPARSED_F_XXX - RTURIPARSED::fFlags
+ * @{ */
+/** Set if the URI contains escaped characters. */
+#define RTURIPARSED_F_CONTAINS_ESCAPED_CHARS UINT32_C(0x00000001)
+/** Set if the URI has an authority component. Necessary since the authority
+ * component can have a zero length. */
+#define RTURIPARSED_F_HAS_AUTHORITY UINT32_C(0x00000002)
+/** Set if there is a port component. */
+#define RTURIPARSED_F_HAS_PORT UINT32_C(0x00000004)
+/** @} */
+
+/**
+ * Parses a URI.
+ *
+ * @returns IPRT status code.
+ * @param pszUri The URI to parse.
+ * @param pParsed Where to return the details. This can be handed
+ * to the RTUriParsed* APIs for retriving
+ * information.
+ */
+RTDECL(int) RTUriParse(const char *pszUri, PRTURIPARSED pParsed);
+
+/**
+ * Extract the scheme out of a parsed URI.
+ *
+ * @returns the scheme if the URI is valid, NULL otherwise.
+ * @param pszUri The URI passed to RTUriParse when producing the
+ * info in @a pParsed.
+ * @param pParsed Pointer to the RTUriParse output.
+ */
+RTDECL(char *) RTUriParsedScheme(const char *pszUri, PCRTURIPARSED pParsed);
+
+/**
+ * Extract the authority out of a parsed URI.
+ *
+ * @returns the authority if the URI contains one, NULL otherwise.
+ * @param pszUri The URI passed to RTUriParse when producing the
+ * info in @a pParsed.
+ * @param pParsed Pointer to the RTUriParse output.
+ * @remarks The authority can have a zero length.
+ */
+RTDECL(char *) RTUriParsedAuthority(const char *pszUri, PCRTURIPARSED pParsed);
+
+/**
+ * Extract the username out of the authority component in a parsed URI.
+ *
+ * @returns The username if the URI contains one, otherwise NULL.
+ * @param pszUri The URI passed to RTUriParse when producing the
+ * info in @a pParsed.
+ * @param pParsed Pointer to the RTUriParse output.
+ *
+ * @todo This may currently be returning NULL when it maybe would be more
+ * appropriate to return an empty string...
+ */
+RTDECL(char *) RTUriParsedAuthorityUsername(const char *pszUri, PCRTURIPARSED pParsed);
+
+/**
+ * Extract the password out of the authority component in a parsed URI.
+ *
+ * @returns The password if the URI contains one, otherwise NULL.
+ * @param pszUri The URI passed to RTUriParse when producing the
+ * info in @a pParsed.
+ * @param pParsed Pointer to the RTUriParse output.
+ *
+ * @todo This may currently be returning NULL when it maybe would be more
+ * appropriate to return an empty string...
+ */
+RTDECL(char *) RTUriParsedAuthorityPassword(const char *pszUri, PCRTURIPARSED pParsed);
+
+/**
+ * Extract the host out of the authority component in a parsed URI.
+ *
+ * @returns The host if the URI contains one, otherwise NULL.
+ * @param pszUri The URI passed to RTUriParse when producing the
+ * info in @a pParsed.
+ * @param pParsed Pointer to the RTUriParse output.
+ *
+ * @todo This may currently be returning NULL when it maybe would be more
+ * appropriate to return an empty string...
+ */
+RTDECL(char *) RTUriParsedAuthorityHost(const char *pszUri, PCRTURIPARSED pParsed);
+
+/**
+ * Extract the port number out of the authority component in a parsed URI.
+ *
+ * @returns The port number if the URI contains one, otherwise UINT32_MAX.
+ * @param pszUri The URI passed to RTUriParse when producing the
+ * info in @a pParsed.
+ * @param pParsed Pointer to the RTUriParse output.
+ */
+RTDECL(uint32_t) RTUriParsedAuthorityPort(const char *pszUri, PCRTURIPARSED pParsed);
+
+/**
+ * Extract the path out of a parsed URI.
+ *
+ * @returns the path if the URI contains one, NULL otherwise.
+ * @param pszUri The URI passed to RTUriParse when producing the
+ * info in @a pParsed.
+ * @param pParsed Pointer to the RTUriParse output.
+ */
+RTDECL(char *) RTUriParsedPath(const char *pszUri, PCRTURIPARSED pParsed);
+
+/**
+ * Extract the query out of a parsed URI.
+ *
+ * @returns the query if the URI contains one, NULL otherwise.
+ * @param pszUri The URI passed to RTUriParse when producing the
+ * info in @a pParsed.
+ * @param pParsed Pointer to the RTUriParse output.
+ */
+RTDECL(char *) RTUriParsedQuery(const char *pszUri, PCRTURIPARSED pParsed);
+
+/**
+ * Extract the fragment out of a parsed URI.
+ *
+ * @returns the fragment if the URI contains one, NULL otherwise.
+ * @param pszUri The URI passed to RTUriParse when producing the
+ * info in @a pParsed.
+ * @param pParsed Pointer to the RTUriParse output.
+ */
+RTDECL(char *) RTUriParsedFragment(const char *pszUri, PCRTURIPARSED pParsed);
+
+
+
+/**
+ * Creates a generic URI.
+ *
+ * The returned pointer must be freed using RTStrFree().
+ *
+ * @returns the new URI on success, NULL otherwise.
+ * @param pszScheme The URI scheme.
+ * @param pszAuthority The authority part of the URI (optional).
+ * @param pszPath The path part of the URI (optional).
+ * @param pszQuery The query part of the URI (optional).
+ * @param pszFragment The fragment part of the URI (optional).
+ */
+RTDECL(char *) RTUriCreate(const char *pszScheme, const char *pszAuthority, const char *pszPath, const char *pszQuery,
+ const char *pszFragment);
+
+/**
+ * Check whether the given scheme matches that of the URI.
+ *
+ * This does not validate the URI, it just compares the scheme, no more, no
+ * less. Thus it's much faster than using RTUriParsedScheme.
+ *
+ * @returns true if the scheme match, false if not.
+ * @param pszUri The URI to check.
+ * @param pszScheme The scheme to compare with.
+ */
+RTDECL(bool) RTUriIsSchemeMatch(const char *pszUri, const char *pszScheme);
+
+/** @defgroup grp_rt_uri_file RTUriFile - Uri file parsing and creation
+ *
+ * Implements basic "file:" scheme support to the generic RTUri interface. This
+ * is partly documented in RFC-1738.
+ *
+ * @{
+ */
+
+/**
+ * Creates a file URI.
+ *
+ * The returned pointer must be freed using RTStrFree().
+ *
+ * @returns The new URI on success, NULL otherwise. Free With RTStrFree.
+ * @param pszPath The path to create an 'file://' URI for. This is
+ * assumed to be using the default path style of the
+ * system.
+ *
+ * @sa RTUriFileCreateEx, RTUriCreate
+ */
+RTDECL(char *) RTUriFileCreate(const char *pszPath);
+
+/**
+ * Creates an file URL for the given path.
+ *
+ * This API works like RTStrToUtf16Ex with regard to result allocation or
+ * buffering (i.e. it's a bit complicated but very flexible).
+ *
+ * @returns iprt status code.
+ * @param pszPath The path to convert to a file:// URL.
+ * @param fPathStyle The input path style, exactly one of
+ * RTPATH_STR_F_STYLE_HOST, RTPATH_STR_F_STYLE_DOS and
+ * RTPATH_STR_F_STYLE_UNIX. Must include iprt/path.h.
+ * @param ppszUri If cbUri is non-zero, this must either be pointing
+ * to pointer to a buffer of the specified size, or
+ * pointer to a NULL pointer. If *ppszUri is NULL or
+ * cbUri is zero a buffer of at least cbUri chars will
+ * be allocated to hold the URI. If a buffer was
+ * requested it must be freed using RTStrFree().
+ * @param cbUri The buffer size in bytes (includes terminator).
+ * @param pcchUri Where to store the length of the URI 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.
+ * @sa RTUriCreate, RTUriFileCreate
+ */
+RTDECL(int) RTUriFileCreateEx(const char *pszPath, uint32_t fPathStyle, char **ppszUri, size_t cbUri, size_t *pcchUri);
+
+/**
+ * Returns the file path encoded in the file URI.
+ *
+ * This differs a quite a bit from RTUriParsedPath in that it tries to be
+ * compatible with URL produced by older windows version. This API is basically
+ * producing the same results as the PathCreateFromUrl API on Windows.
+ *
+ * @returns The path if the URI contains one, system default path style,
+ * otherwise NULL.
+ * @param pszUri The alleged 'file://' URI to extract the path from.
+ *
+ * @sa RTUriParsedPath, RTUriFilePathEx
+ */
+RTDECL(char *) RTUriFilePath(const char *pszUri);
+
+/**
+ * Queries the file path for the given file URI.
+ *
+ * This API works like RTStrToUtf16Ex with regard to result allocation or
+ * buffering (i.e. it's a bit complicated but very flexible).
+ *
+ * This differs a quite a bit from RTUriParsedPath in that it tries to be
+ * compatible with URL produced by older windows version. This API is basically
+ * producing the same results as the PathCreateFromUrl API on Windows.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_URI_NOT_FILE_SCHEME if not file scheme.
+ *
+ * @param pszUri The alleged file:// URI to extract the path from.
+ * @param fPathStyle The output path style, exactly one of
+ * RTPATH_STR_F_STYLE_HOST, RTPATH_STR_F_STYLE_DOS and
+ * RTPATH_STR_F_STYLE_UNIX. Must include iprt/path.h.
+ * @param ppszPath If cbPath is non-zero, this must either be pointing
+ * to pointer to a buffer of the specified size, or
+ * pointer to a NULL pointer. If *ppszPath is NULL or
+ * cbPath is zero a buffer of at least cbPath chars
+ * will be allocated to hold the path. If a buffer was
+ * requested it must be freed using RTStrFree().
+ * @param cbPath The buffer size in bytes (includes terminator).
+ * @param pcchPath Where to store the length of the path 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.
+ * @sa RTUriParsedPath, RTUriFilePath
+ */
+RTDECL(int) RTUriFilePathEx(const char *pszUri, uint32_t fPathStyle, char **ppszPath, size_t cbPath, size_t *pcchPath);
+
+/** @} */
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_uri_h */
+
diff --git a/include/iprt/utf16.h b/include/iprt/utf16.h
new file mode 100644
index 00000000..ed193b1e
--- /dev/null
+++ b/include/iprt/utf16.h
@@ -0,0 +1,1527 @@
+/** @file
+ * IPRT - String Manipulation, UTF-16 encoding.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_utf16_h
+#define IPRT_INCLUDED_utf16_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#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);
+
+/**
+ * Finds a give UTF-16 character in a UTF-16 string.
+ *
+ * @returns Pointer to the first occurence of @a wc.
+ * @returns NULL if @a wc was not found.
+ *
+ * @param pwszString The string to search.
+ * @param wc The UTF-16 character to search for.
+ */
+RTDECL(PRTUTF16) RTUtf16Chr(PCRTUTF16 pwszString, RTUTF16 wc);
+
+/**
+ * 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.
+ * @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.
+ * @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.
+ * @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 sensitive and length limited string compare between two UTF-16 strings.
+ *
+ * @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.
+ * @param cwcMax Maximum number of characters (RTUTF16) from the first
+ * @remark This function will not make any attempt to validate the encoding.
+ */
+RTDECL(int) RTUtf16NCmp(PCRTUTF16 pwsz1, PCRTUTF16 pwsz2, size_t cwcMax);
+
+/**
+ * Performs a case sensitive and length limited string compare between an UTF-16
+ * string and a pure ASCII 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 pwsz1 First UTF-16 string. Null is allowed.
+ * @param psz2 Second string, pure ASCII. Null is allowed.
+ * @param cwcMax Maximum number of characters (RTUTF16) to compare.
+ * @remark This function will not make any attempt to validate the encoding.
+ */
+RTDECL(int) RTUtf16NCmpAscii(PCRTUTF16 pwsz1, const char *psz2, size_t cwcMax);
+
+/**
+ * Performs a case sensitive and length limited string compare between an UTF-16
+ * string and a UTF-8 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 pwsz1 First UTF-16 string. Null is allowed.
+ * @param psz2 Second string, UTF-8. Null is allowed.
+ * @param cwcMax1 Maximum number of UTF-16 characters (RTUTF16) from the
+ * first string to compare.
+ * @param cchMax2 Maximum number of UTF-8 characters (char) from the
+ * second string to compare.
+ * @remarks NULL and empty strings are treated equally.
+ */
+RTDECL(int) RTUtf16NCmpUtf8(PCRTUTF16 pwsz1, const char *psz2, size_t cwcMax1, size_t cchMax2);
+
+
+/**
+ * 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 two big endian 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 big endian UTF-16 string. Null is allowed.
+ * @param pwsz2 Second big endian UTF-16 string. Null is allowed.
+ */
+RTDECL(int) RTUtf16BigICmp(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 two UTF-16 strings,
+ * stopping after N characters.
+ *
+ * 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.
+ * @param cwcMax Maximum number of characters to compare.
+ */
+RTDECL(int) RTUtf16NICmp(PCRTUTF16 pwsz1, PCRTUTF16 pwsz2, size_t cwcMax);
+
+/**
+ * Performs a case insensitive string compare between two big endian UTF-16
+ * strings, stopping after N characters.
+ *
+ * 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 big endian UTF-16 string. Null is allowed.
+ * @param pwsz2 Second big endian UTF-16 string. Null is allowed.
+ * @param cwcMax Maximum number of characters to compare.
+ */
+RTDECL(int) RTUtf16BigNICmp(PCRTUTF16 pwsz1, PCRTUTF16 pwsz2, size_t cwcMax);
+
+/**
+ * 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);
+
+
+/**
+ * Locates a substring, ascii version.
+ *
+ * @returns Offset into @a pwszString of the substring if found, -1 if not.
+ * @param pwszString The UTF-16 to search. NULL is allowed (no match).
+ * @param pszSubStr The pure ASCII substring to locate. NULL is allowed (not
+ * matching anything, just like an empty string).
+ */
+RTDECL(ssize_t) RTUtf16FindAscii(PCRTUTF16 pwszString, const char *pszSubStr);
+
+
+/**
+ * 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);
+
+/**
+ * Translate a UTF-16BE string into a UTF-8 allocating the result buffer
+ * (default tag).
+ *
+ * This differs from RTUtf16ToUtf8 in that the input is always a
+ * big-endian string.
+ *
+ * @returns iprt status code.
+ * @param pwszString UTF-16BE 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 RTUtf16BigToUtf8(pwszString, ppszString) RTUtf16BigToUtf8Tag((pwszString), (ppszString), RTSTR_TAG)
+
+/**
+ * Translate a UTF-16BE string into a UTF-8 allocating the result buffer.
+ *
+ * This differs from RTUtf16ToUtf8Tag in that the input is always a
+ * big-endian string.
+ *
+ * @returns iprt status code.
+ * @param pwszString UTF-16BE 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) RTUtf16BigToUtf8Tag(PCRTUTF16 pwszString, char **ppszString, const char *pszTag);
+
+/**
+ * Translate a UTF-16LE string into a UTF-8 allocating the result buffer
+ * (default tag).
+ *
+ * This differs from RTUtf16ToUtf8 in that the input is always a
+ * little-endian string.
+ *
+ * @returns iprt status code.
+ * @param pwszString UTF-16LE 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 RTUtf16LittleToUtf8(pwszString, ppszString) RTUtf16LittleToUtf8Tag((pwszString), (ppszString), RTSTR_TAG)
+
+/**
+ * Translate a UTF-16LE string into a UTF-8 allocating the result buffer.
+ *
+ * This differs from RTUtf16ToUtf8Tag in that the input is always a
+ * little-endian string.
+ *
+ * @returns iprt status code.
+ * @param pwszString UTF-16LE 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) RTUtf16LittleToUtf8Tag(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);
+
+/**
+ * Translates UTF-16BE to UTF-8 using buffer provided by the caller or a
+ * fittingly sized buffer allocated by the function (default tag).
+ *
+ * This differs from RTUtf16ToUtf8Ex in that the input is always a
+ * big-endian string.
+ *
+ * @returns iprt status code.
+ * @param pwszString The UTF-16BE 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 RTUtf16BigToUtf8Ex(pwszString, cwcString, ppsz, cch, pcch) \
+ RTUtf16BigToUtf8ExTag((pwszString), (cwcString), (ppsz), (cch), (pcch), RTSTR_TAG)
+
+/**
+ * Translates UTF-16BE to UTF-8 using buffer provided by the caller or a
+ * fittingly sized buffer allocated by the function (custom tag).
+ *
+ * This differs from RTUtf16ToUtf8ExTag in that the input is always a
+ * big-endian string.
+ *
+ * @returns iprt status code.
+ * @param pwszString The UTF-16BE 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) RTUtf16BigToUtf8ExTag(PCRTUTF16 pwszString, size_t cwcString, char **ppsz, size_t cch, size_t *pcch, const char *pszTag);
+
+/**
+ * Translates UTF-16LE to UTF-8 using buffer provided by the caller or a
+ * fittingly sized buffer allocated by the function (default tag).
+ *
+ * This differs from RTUtf16ToUtf8Ex in that the input is always a
+ * little-endian string.
+ *
+ * @returns iprt status code.
+ * @param pwszString The UTF-16LE 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 RTUtf16LittleToUtf8Ex(pwszString, cwcString, ppsz, cch, pcch) \
+ RTUtf16LittleToUtf8ExTag((pwszString), (cwcString), (ppsz), (cch), (pcch), RTSTR_TAG)
+
+/**
+ * Translates UTF-16LE to UTF-8 using buffer provided by the caller or a
+ * fittingly sized buffer allocated by the function (custom tag).
+ *
+ * This differs from RTUtf16ToUtf8ExTag in that the input is always a
+ * little-endian string.
+ *
+ * @returns iprt status code.
+ * @param pwszString The UTF-16LE 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) RTUtf16LittleToUtf8ExTag(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-16BE string in UTF-8 chars (bytes).
+ *
+ * This function will validate the string, and incorrectly encoded UTF-16BE
+ * strings will be rejected. The primary purpose of this function is to
+ * help allocate buffers for RTUtf16BigToUtf8() of the correct size. For most
+ * other purposes RTUtf16BigToUtf8Ex() should be used.
+ *
+ * @returns Number of char (bytes).
+ * @returns 0 if the string was incorrectly encoded.
+ * @param pwsz The UTF-16BE string.
+ */
+RTDECL(size_t) RTUtf16BigCalcUtf8Len(PCRTUTF16 pwsz);
+
+/**
+ * Calculates the length of the UTF-16LE string in UTF-8 chars (bytes).
+ *
+ * This function will validate the string, and incorrectly encoded UTF-16LE
+ * strings will be rejected. The primary purpose of this function is to
+ * help allocate buffers for RTUtf16LittleToUtf8() of the correct size. For
+ * most other purposes RTUtf16LittleToUtf8Ex() should be used.
+ *
+ * @returns Number of char (bytes).
+ * @returns 0 if the string was incorrectly encoded.
+ * @param pwsz The UTF-16LE string.
+ */
+RTDECL(size_t) RTUtf16LittleCalcUtf8Len(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);
+
+/**
+ * Calculates the length of the UTF-16BE string in UTF-8 chars (bytes).
+ *
+ * This function will validate the string, and incorrectly encoded UTF-16BE
+ * 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) RTUtf16BigCalcUtf8LenEx(PCRTUTF16 pwsz, size_t cwc, size_t *pcch);
+
+/**
+ * Calculates the length of the UTF-16LE string in UTF-8 chars (bytes).
+ *
+ * This function will validate the string, and incorrectly encoded UTF-16LE
+ * 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) RTUtf16LittleCalcUtf8LenEx(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);
+
+/**
+ * Get the unicode code point at the given string position with length
+ * restriction.
+ *
+ * @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 pcwc Pointer to the max string length. This will be
+ * decremented corrsponding to the advancement of @a ppwsz.
+ * @param pCp Where to store the code point.
+ * RTUNICP_INVALID is stored here on failure.
+ *
+ * @remark This is an internal worker for RTUtf16GetCpNEx().
+ */
+RTDECL(int) RTUtf16GetCpNExInternal(PCRTUTF16 *ppwsz, size_t *pcwc, PRTUNICP pCp);
+
+/**
+ * Get the unicode code point at the given string position, big endian.
+ *
+ * @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 RTUtf16BigGetCpEx().
+ */
+RTDECL(int) RTUtf16BigGetCpExInternal(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);
+}
+
+/**
+ * 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 pcwc Pointer to the max string length. This will be
+ * decremented corrsponding to the advancement of @a ppwsz.
+ * @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) RTUtf16GetCpNEx(PCRTUTF16 *ppwsz, size_t *pcwc, PRTUNICP pCp)
+{
+ const size_t cwc = *pcwc;
+ if (cwc > 0)
+ {
+ const PCRTUTF16 pwsz = *ppwsz;
+ const RTUTF16 wc = *pwsz;
+ if (wc < 0xd800 || (wc > 0xdfff && wc < 0xfffe))
+ {
+ *pCp = wc;
+ *pcwc = cwc - 1;
+ *ppwsz = pwsz + 1;
+ return VINF_SUCCESS;
+ }
+ }
+ return RTUtf16GetCpNExInternal(ppwsz, pcwc, pCp);
+}
+
+/**
+ * Get the unicode code point at the given string position, big endian version.
+ *
+ * @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) RTUtf16BigGetCpEx(PCRTUTF16 *ppwsz, PRTUNICP pCp)
+{
+#ifdef RT_BIG_ENDIAN
+ return RTUtf16GetCpEx(ppwsz, pCp);
+#else
+# ifdef IPRT_INCLUDED_asm_h
+ const RTUTF16 wc = RT_BE2H_U16(**ppwsz);
+ if (wc < 0xd800 || (wc > 0xdfff && wc < 0xfffe))
+ {
+ (*ppwsz)++;
+ *pCp = wc;
+ return VINF_SUCCESS;
+ }
+# endif
+ return RTUtf16BigGetCpExInternal(ppwsz, pCp);
+#endif
+}
+
+/**
+ * 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);
+
+/**
+ * String printf producing UTF-16 output.
+ *
+ * @returns On success, positive count of formatted RTUTF16 units excluding the
+ * terminator. On buffer overflow, negative number giving the required
+ * buffer size (including terminator) in RTUTF16 units.
+ *
+ * @param pwszBuffer Output buffer.
+ * @param cwcBuffer Size of the output buffer in RTUTF16 units.
+ * @param pszFormat Pointer to the format string, @see pg_rt_str_format.
+ * @param args The format argument.
+ *
+ * @note This is similar to RTStrPrintf2V (not RTStrPrintfV)!
+ */
+RTDECL(ssize_t) RTUtf16PrintfV(PRTUTF16 pwszBuffer, size_t cwcBuffer, const char *pszFormat, va_list args) RT_IPRT_FORMAT_ATTR(3, 0);
+
+/**
+ * String printf producing UTF-16 output.
+ *
+ * @returns On success, positive count of formatted RTUTF16 units excluding the
+ * terminator. On buffer overflow, negative number giving the required
+ * buffer size (including terminator) in RTUTF16 units.
+ *
+ * @param pwszBuffer Output buffer.
+ * @param cwcBuffer Size of the output buffer in RTUTF16 units.
+ * @param pszFormat Pointer to the format string, @see pg_rt_str_format.
+ * @param ... The format argument.
+ *
+ * @note This is similar to RTStrPrintf2 (not RTStrPrintf)!
+ */
+RTDECL(ssize_t) RTUtf16Printf(PRTUTF16 pwszBuffer, size_t cwcBuffer, const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(3, 4);
+
+/**
+ * String printf producing UTF-16 output with custom formatting.
+ *
+ * @returns On success, positive count of formatted RTUTF16 units excluding the
+ * terminator. On buffer overflow, negative number giving the required
+ * buffer size (including terminator) in RTUTF16 units.
+ *
+ * @param pfnFormat Pointer to handler function for the custom formats.
+ * @param pvArg Argument to the pfnFormat function.
+ * @param pwszBuffer Output buffer.
+ * @param cwcBuffer Size of the output buffer in RTUTF16 units.
+ * @param pszFormat Pointer to the format string, @see pg_rt_str_format.
+ * @param args The format argument.
+ *
+ * @note This is similar to RTStrPrintf2ExV (not RTStrPrintfExV)!
+ */
+RTDECL(ssize_t) RTUtf16PrintfExV(PFNSTRFORMAT pfnFormat, void *pvArg, PRTUTF16 pwszBuffer, size_t cwcBuffer,
+ const char *pszFormat, va_list args) RT_IPRT_FORMAT_ATTR(5, 0);
+
+/**
+ * String printf producing UTF-16 output with custom formatting.
+ *
+ * @returns On success, positive count of formatted RTUTF16 units excluding the
+ * terminator. On buffer overflow, negative number giving the required
+ * buffer size (including terminator) in RTUTF16 units.
+ *
+ * @param pfnFormat Pointer to handler function for the custom formats.
+ * @param pvArg Argument to the pfnFormat function.
+ * @param pwszBuffer Output buffer.
+ * @param cwcBuffer Size of the output buffer in RTUTF16 units.
+ * @param pszFormat Pointer to the format string, @see pg_rt_str_format.
+ * @param ... The format argument.
+ *
+ * @note This is similar to RTStrPrintf2Ex (not RTStrPrintfEx)!
+ */
+RTDECL(ssize_t) RTUtf16PrintfEx(PFNSTRFORMAT pfnFormat, void *pvArg, PRTUTF16 pwszBuffer, size_t cwcBuffer,
+ const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(5, 6);
+
+/** @} */
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_utf16_h */
+
diff --git a/include/iprt/uuid.h b/include/iprt/uuid.h
new file mode 100644
index 00000000..3c95a641
--- /dev/null
+++ b/include/iprt/uuid.h
@@ -0,0 +1,198 @@
+/** @file
+ * IPRT - Universal Unique Identifiers (UUID).
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_uuid_h
+#define IPRT_INCLUDED_uuid_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_uuid RTUuid - Universally Unique Identifiers
+ * @ingroup grp_rt
+ * @{
+ */
+
+/**
+ * Generates new UUID value.
+ *
+ * @note IPRT uses little endian byte ordering in the UUID integer fields. If
+ * you want to pass IPRT UUIDs in binary representation to other UUID libraries
+ * and expect to get exactly the same string representation as in IPRT, you
+ * need to convert the first three integer fields (one 32 bit value, two 16 bit
+ * values) separately to big endian (also called network byte order).
+ *
+ * @sa RTUUID::Gen
+ *
+ * @returns iprt status code.
+ * @param pUuid Where to store generated uuid.
+ */
+RTDECL(int) RTUuidCreate(PRTUUID pUuid);
+
+/**
+ * Makes null UUID value.
+ *
+ * @returns iprt status code.
+ * @param pUuid Where to store generated null uuid.
+ */
+RTDECL(int) RTUuidClear(PRTUUID pUuid);
+
+/**
+ * Checks if UUID is null.
+ *
+ * @returns true if UUID is null.
+ * @param pUuid uuid to check.
+ */
+RTDECL(bool) RTUuidIsNull(PCRTUUID pUuid);
+
+/**
+ * Compares two UUID values.
+ *
+ * @returns 0 if eq, < 0 or > 0.
+ * @param pUuid1 First value to compare. NULL is treated like if
+ * RTUuidIsNull() return true.
+ * @param pUuid2 Second value to compare. NULL is treated like if
+ * RTUuidIsNull() return true.
+ */
+RTDECL(int) RTUuidCompare(PCRTUUID pUuid1, PCRTUUID pUuid2);
+
+/**
+ * Compares a UUID value with a UUID string.
+ *
+ * @note IPRT uses little endian byte ordering in the UUID integer fields. If
+ * you want to pass IPRT UUIDs in binary representation to other UUID libraries
+ * and expect to get exactly the same string representation as in IPRT, you need
+ * to convert the first three integer fields (one 32 bit value, two 16 bit
+ * values) separately to big endian (also called network byte order).
+ * Correspondingly, if you want to get the right result with UUIDs which are in
+ * big endian format, you need to convert them before using this function.
+ *
+ * @sa RTUUID::Gen
+ *
+ * @returns 0 if eq, < 0 or > 0.
+ * @param pUuid1 First value to compare. NULL is not allowed.
+ * @param pszString2 The 2nd UUID in string form. NULL or malformed
+ * string is not permitted.
+ */
+RTDECL(int) RTUuidCompareStr(PCRTUUID pUuid1, const char *pszString2);
+
+/**
+ * Compares two UUID strings.
+ *
+ * @returns 0 if eq, < 0 or > 0.
+ * @param pszString1 The 1st UUID in string from. NULL or malformed
+ * string is not permitted.
+ * @param pszString2 The 2nd UUID in string form. NULL or malformed
+ * string is not permitted.
+ */
+RTDECL(int) RTUuidCompare2Strs(const char *pszString1, const char *pszString2);
+
+/**
+ * Converts binary UUID to its string representation.
+ *
+ * @note IPRT uses little endian byte ordering in the UUID integer fields. If
+ * you want to pass IPRT UUIDs in binary representation to other UUID libraries
+ * and expect to get exactly the same string representation as in IPRT, you
+ * need to convert the first three integer fields (one 32 bit value, two 16 bit
+ * values) separately to big endian (also called network byte order).
+ * Correspondingly, if you want to get the right result with UUIDs which are in
+ * big endian format, you need to convert them before using this function.
+ *
+ * @sa RTUUID::Gen
+ *
+ * @returns iprt status code.
+ * @param pUuid Uuid to convert.
+ * @param pszString Where to store result string.
+ * @param cchString pszString buffer length, must be >= RTUUID_STR_LENGTH.
+ */
+RTDECL(int) RTUuidToStr(PCRTUUID pUuid, char *pszString, size_t cchString);
+
+/**
+ * Converts UUID from its string representation to binary format.
+ *
+ * @note IPRT uses little endian byte ordering in the UUID integer fields. If
+ * you want to pass IPRT UUIDs in binary representation to other UUID libraries
+ * and expect to get exactly the same string representation as in IPRT, you
+ * need to convert the first three integer fields (one 32 bit value, two 16 bit
+ * values) separately to big endian (also called network byte order).
+ * Correspondingly, if you want to get the right result with UUIDs which are in
+ * big endian format, you need to convert them before using this function.
+ *
+ * @sa RTUUID::Gen
+ *
+ * @returns iprt status code.
+ * @param pUuid Where to store result Uuid.
+ * @param pszString String with UUID text data.
+ */
+RTDECL(int) RTUuidFromStr(PRTUUID pUuid, const char *pszString);
+
+/**
+ * Converts binary UUID to its UTF-16 string representation.
+ *
+ * @note See note in RTUuidToStr.
+ *
+ * @sa RTUUID::Gen
+ *
+ * @returns iprt status code.
+ * @param pUuid Uuid to convert.
+ * @param pwszString Where to store result string.
+ * @param cwcString pszString buffer length, must be >=
+ * RTUUID_STR_LENGTH.
+ */
+RTDECL(int) RTUuidToUtf16(PCRTUUID pUuid, PRTUTF16 pwszString, size_t cwcString);
+
+/**
+ * Converts UUID from its UTF-16 string representation to binary format.
+ *
+ * @note See note in RTUuidFromStr.
+ *
+ * @sa RTUUID::Gen
+ *
+ * @returns iprt status code.
+ * @param pUuid Where to store result Uuid.
+ * @param pwszString String with UUID text data.
+ */
+RTDECL(int) RTUuidFromUtf16(PRTUUID pUuid, PCRTUTF16 pwszString);
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_uuid_h */
+
diff --git a/include/iprt/vector.h b/include/iprt/vector.h
new file mode 100644
index 00000000..0e3f6a8a
--- /dev/null
+++ b/include/iprt/vector.h
@@ -0,0 +1,389 @@
+/** @file
+ * IPRT - Vector - STL-inspired vector implementation in C.
+ */
+
+/*
+ * Copyright (C) 2011-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+/**
+ * @todo the right Doxygen tag here
+ * This file defines a set of macros which provide a functionality and an
+ * interface roughly similar to the C++ STL vector container. To create a
+ * vector of a particular type one must first explicitly instantiate such a
+ * vector in the source file, e.g.
+ * RTVEC_DECL(TopLevels, Window *)
+ * without a semi-colon. This macro will define a structure (struct TopLevels)
+ * which contains a dynamically resizeable array of Window * elements. It
+ * will also define a number of inline methods for manipulating the structure,
+ * such as
+ * Window *TopLevelsPushBack(struct TopLevels *)
+ * which adds a new element to the end of the array and returns it, optionally
+ * reallocating the array if there is not enough space for the new element.
+ * (This particular method prototype differs from the STL equivalent -
+ * push_back - more than most of the other methods).
+ *
+ * To create a vector, one simply needs to declare the structure, in this case
+ * struct TopLevels = RTVEC_INITIALIZER;
+ *
+ * There are various other macros for declaring vectors with different
+ * allocators (e.g. RTVEC_DECL_ALLOCATOR) or with clean-up functions
+ * (e.g. RTVEC_DECL_DELETE). See the descriptions of the generic methods and
+ * the declarator macros below.
+ *
+ * One particular use of vectors is to assemble an array of a particular type
+ * in heap memory without knowing - or counting - the number of elements in
+ * advance. To do this, add the elements onto the array using PushBack, then
+ * extract the array from the vector using the (non-STL) Detach method.
+ *
+ * @note functions in this file are inline to prevent warnings about
+ * unused static functions. I assume that in this day and age a
+ * compiler makes its own decisions about whether to actually
+ * inline a function.
+ * @note since vector structures must be explicitly instanciated unlike the
+ * C++ vector template, care must be taken not to instanciate a
+ * particular type twice, e.g. once in a header and once in a code file.
+ * Only using vectors in code files and keeping them out of interfaces
+ * (or passing them as anonymously) makes it easier to take care of this.
+ */
+
+#ifndef IPRT_INCLUDED_vector_h
+#define IPRT_INCLUDED_vector_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+/*******************************************************************************
+* Header Files *
+*******************************************************************************/
+
+#include <iprt/assert.h>
+#include <iprt/cdefs.h>
+#include <iprt/errcore.h>
+#include <iprt/mem.h> /** @todo Should the caller include this if they need
+ * it? */
+
+
+/**
+ * Generic vector structure
+ */
+/** @todo perhaps we should include an additional member for a parameter to
+ * three-argument reallocators, so that we can support e.g. mempools? */
+#define RTVEC_DECL_STRUCT(name, type) \
+struct name \
+{ \
+ /** The number of elements in the vector */ \
+ size_t mcElements; \
+ /** The current capacity of the vector */ \
+ size_t mcCapacity; \
+ /** The elements themselves */ \
+ type *mpElements; \
+};
+
+/** Initialiser for an empty vector structure */
+#define RTVEC_INITIALIZER { 0, 0, NULL }
+
+/** The unit by which the vector capacity is increased */
+#define RTVECIMPL_ALLOC_UNIT 16
+
+/**
+ * Generic method - get the size of a vector
+ */
+/** @todo What is the correct way to do doxygen for this sort of macro? */
+#define RTVEC_DECLFN_SIZE(name, type) \
+DECLINLINE(size_t) name ## Size(struct name *pVec) \
+{ \
+ return(pVec->mcElements); \
+}
+
+/**
+ * Generic method - expand a vector
+ */
+#define RTVEC_DECLFN_RESERVE(name, type, pfnRealloc) \
+DECLINLINE(int) name ## Reserve(struct name *pVec, size_t cNewCapacity) \
+{ \
+ void *pvNew; \
+ \
+ if (cNewCapacity <= pVec->mcCapacity) \
+ return VINF_SUCCESS; \
+ pvNew = pfnRealloc(pVec->mpElements, cNewCapacity * sizeof(type)); \
+ if (!pvNew) \
+ return VERR_NO_MEMORY; \
+ pVec->mcCapacity = cNewCapacity; \
+ pVec->mpElements = (type *)pvNew; \
+ return VINF_SUCCESS; \
+}
+
+/**
+ * Generic method - return a pointer to the first element in the vector.
+ */
+#define RTVEC_DECLFN_BEGIN(name, type) \
+DECLINLINE(type *) name ## Begin(struct name *pVec) \
+{ \
+ return(pVec->mpElements); \
+}
+
+/**
+ * Generic method - return a pointer to one past the last element in the
+ * vector.
+ */
+#define RTVEC_DECLFN_END(name, type) \
+DECLINLINE(type *) name ## End(struct name *pVec) \
+{ \
+ return(&pVec->mpElements[pVec->mcElements]); \
+}
+
+/**
+ * Generic method - add a new, uninitialised element onto a vector and return
+ * it.
+ * @note this method differs from the STL equivalent by letting the caller
+ * post-initialise the new element rather than copying it from its
+ * argument.
+ */
+#define RTVEC_DECLFN_PUSHBACK(name, type) \
+DECLINLINE(type *) name ## PushBack(struct name *pVec) \
+{ \
+ Assert(pVec->mcElements <= pVec->mcCapacity); \
+ if ( pVec->mcElements == pVec->mcCapacity \
+ && RT_FAILURE(name ## Reserve(pVec, pVec->mcCapacity \
+ + RTVECIMPL_ALLOC_UNIT))) \
+ return NULL; \
+ ++pVec->mcElements; \
+ return &pVec->mpElements[pVec->mcElements - 1]; \
+}
+
+/**
+ * Generic method - drop the last element from the vector.
+ */
+#define RTVEC_DECLFN_POPBACK(name) \
+DECLINLINE(void) name ## PopBack(struct name *pVec) \
+{ \
+ Assert(pVec->mcElements <= pVec->mcCapacity); \
+ --pVec->mcElements; \
+}
+
+/**
+ * Generic method - drop the last element from the vector, calling a clean-up
+ * method first.
+ *
+ * By taking an adapter function for the element to be dropped as an
+ * additional macro parameter we can support clean-up by pointer
+ * (pfnAdapter maps T* -> T*) or by value (maps T* -> T). pfnAdapter takes
+ * one argument of type @a type * and must return whatever type pfnDelete
+ * expects.
+ */
+/** @todo find a better name for pfnAdapter? */
+#define RTVEC_DECLFN_POPBACK_DELETE(name, type, pfnDelete, pfnAdapter) \
+DECLINLINE(void) name ## PopBack(struct name *pVec) \
+{ \
+ Assert(pVec->mcElements <= pVec->mcCapacity); \
+ --pVec->mcElements; \
+ pfnDelete(pfnAdapter(&pVec->mpElements[pVec->mcElements])); \
+}
+
+/**
+ * Generic method - reset a vector to empty.
+ * @note This function does not free any memory
+ */
+#define RTVEC_DECLFN_CLEAR(name) \
+DECLINLINE(void) name ## Clear(struct name *pVec) \
+{ \
+ Assert(pVec->mcElements <= pVec->mcCapacity); \
+ pVec->mcElements = 0; \
+}
+
+/**
+ * Generic method - reset a vector to empty, calling a clean-up method on each
+ * element first.
+ * @note See @a RTVEC_DECLFN_POPBACK_DELETE for an explanation of pfnAdapter
+ * @note This function does not free any memory
+ * @note The cleanup function is currently called on the elements from first
+ * to last. The testcase expects this.
+ */
+#define RTVEC_DECLFN_CLEAR_DELETE(name, pfnDelete, pfnAdapter) \
+DECLINLINE(void) name ## Clear(struct name *pVec) \
+{ \
+ size_t i; \
+ \
+ Assert(pVec->mcElements <= pVec->mcCapacity); \
+ for (i = 0; i < pVec->mcElements; ++i) \
+ pfnDelete(pfnAdapter(&pVec->mpElements[i])); \
+ pVec->mcElements = 0; \
+}
+
+/**
+ * Generic method - detach the array contained inside a vector and reset the
+ * vector to empty.
+ * @note This function does not free any memory
+ */
+#define RTVEC_DECLFN_DETACH(name, type) \
+DECLINLINE(type *) name ## Detach(struct name *pVec) \
+{ \
+ type *pArray = pVec->mpElements; \
+ \
+ Assert(pVec->mcElements <= pVec->mcCapacity); \
+ pVec->mcElements = 0; \
+ pVec->mpElements = NULL; \
+ pVec->mcCapacity = 0; \
+ return pArray; \
+}
+
+/** Common declarations for all vector types */
+#define RTVEC_DECL_COMMON(name, type, pfnRealloc) \
+ RTVEC_DECL_STRUCT(name, type) \
+ RTVEC_DECLFN_SIZE(name, type) \
+ RTVEC_DECLFN_RESERVE(name, type, pfnRealloc) \
+ RTVEC_DECLFN_BEGIN(name, type) \
+ RTVEC_DECLFN_END(name, type) \
+ RTVEC_DECLFN_PUSHBACK(name, type) \
+ RTVEC_DECLFN_DETACH(name, type)
+
+/**
+ * Declarator macro - declare a vector type
+ * @param name the name of the C struct type describing the vector as
+ * well as the prefix of the functions for manipulating it
+ * @param type the type of the objects contained in the vector
+ * @param pfnRealloc the memory reallocation function used for expanding the
+ * vector
+ */
+#define RTVEC_DECL_ALLOCATOR(name, type, pfnRealloc) \
+ RTVEC_DECL_COMMON(name, type, pfnRealloc) \
+ RTVEC_DECLFN_POPBACK(name) \
+ RTVEC_DECLFN_CLEAR(name)
+
+/**
+ * Generic method - inline id mapping delete adapter function - see the
+ * explanation of pfnAdapter in @a RTVEC_DECLFN_POPBACK_DELETE.
+ */
+#define RTVEC_DECLFN_DELETE_ADAPTER_ID(name, type) \
+DECLINLINE(type *) name ## DeleteAdapterId(type *arg) \
+{ \
+ return arg; \
+}
+
+/**
+ * Generic method - inline pointer-to-value mapping delete adapter function -
+ * see the explanation of pfnAdapter in @a RTVEC_DECLFN_POPBACK_DELETE.
+ */
+#define RTVEC_DECLFN_DELETE_ADAPTER_TO_VALUE(name, type) \
+DECLINLINE(type) name ## DeleteAdapterToValue(type *arg) \
+{ \
+ return *arg; \
+}
+
+/**
+ * Declarator macro - declare a vector type with a cleanup callback to be used
+ * when elements are dropped from the vector. The callback takes a pointer to
+ * @a type,
+ * NOT a value of type @a type.
+ * @param name the name of the C struct type describing the vector as
+ * well as the prefix of the functions for manipulating it
+ * @param type the type of the objects contained in the vector
+ * @param pfnRealloc the memory reallocation function used for expanding the
+ * vector
+ * @param pfnDelete the cleanup callback function - signature
+ * void pfnDelete(type *)
+ */
+#define RTVEC_DECL_ALLOCATOR_DELETE(name, type, pfnRealloc, pfnDelete) \
+ RTVEC_DECL_COMMON(name, type, pfnRealloc) \
+ RTVEC_DECLFN_DELETE_ADAPTER_ID(name, type) \
+ RTVEC_DECLFN_POPBACK_DELETE(name, type, pfnDelete, \
+ name ## DeleteAdapterId) \
+ RTVEC_DECLFN_CLEAR_DELETE(name, pfnDelete, name ## DeleteAdapterId)
+
+/**
+ * Declarator macro - declare a vector type with a cleanup callback to be used
+ * when elements are dropped from the vector. The callback takes a parameter
+ * of type @a type, NOT a pointer to @a type.
+ * @param name the name of the C struct type describing the vector as
+ * well as the prefix of the functions for manipulating it
+ * @param type the type of the objects contained in the vector
+ * @param pfnRealloc the memory reallocation function used for expanding the
+ * vector
+ * @param pfnDelete the cleanup callback function - signature
+ * void pfnDelete(type)
+ */
+#define RTVEC_DECL_ALLOCATOR_DELETE_BY_VALUE(name, type, pfnRealloc, \
+ pfnDelete) \
+ RTVEC_DECL_COMMON(name, type, pfnRealloc) \
+ RTVEC_DECLFN_DELETE_ADAPTER_TO_VALUE(name, type) \
+ RTVEC_DECLFN_POPBACK_DELETE(name, type, pfnDelete, \
+ name ## DeleteAdapterToValue) \
+ RTVEC_DECLFN_CLEAR_DELETE(name, pfnDelete, \
+ name ## DeleteAdapterToValue)
+
+/**
+ * Inline wrapper around RTMemRealloc macro to get a function usable as a
+ * callback.
+ */
+DECLINLINE(void *) rtvecReallocDefTag(void *pv, size_t cbNew)
+{
+ return RTMemRealloc(pv, cbNew);
+}
+
+/**
+ * Declarator macro - declare a vector type (see @a RTVEC_DECL_ALLOCATOR)
+ * using RTMemRealloc as a memory allocator
+ * @param name the name of the C struct type describing the vector as
+ * well as the prefix of the functions for manipulating it
+ * @param type the type of the objects contained in the vector
+ */
+#define RTVEC_DECL(name, type) \
+ RTVEC_DECL_ALLOCATOR(name, type, rtvecReallocDefTag)
+
+/**
+ * Declarator macro - declare a vector type with a cleanup by pointer callback
+ * (see @a RTVEC_DECL_ALLOCATOR_DELETE) using RTMemRealloc as a memory
+ * allocator
+ * @param name the name of the C struct type describing the vector as
+ * well as the prefix of the functions for manipulating it
+ * @param type the type of the objects contained in the vector
+ * @param pfnDelete the cleanup callback function - signature
+ * void pfnDelete(type *)
+ */
+#define RTVEC_DECL_DELETE(name, type, pfnDelete) \
+ RTVEC_DECL_ALLOCATOR_DELETE(name, type, rtvecReallocDefTag, pfnDelete)
+
+/**
+ * Declarator macro - declare a vector type with a cleanup by value callback
+ * (see @a RTVEC_DECL_ALLOCATOR_DELETE_BY_VALUE) using RTMemRealloc as a memory
+ * allocator
+ * @param name the name of the C struct type describing the vector as
+ * well as the prefix of the functions for manipulating it
+ * @param type the type of the objects contained in the vector
+ * @param pfnDelete the cleanup callback function - signature
+ * void pfnDelete(type)
+ */
+#define RTVEC_DECL_DELETE_BY_VALUE(name, type, pfnDelete) \
+ RTVEC_DECL_ALLOCATOR_DELETE_BY_VALUE(name, type, rtvecReallocDefTag, \
+ pfnDelete)
+
+#endif /* !IPRT_INCLUDED_vector_h */
+
diff --git a/include/iprt/vfs.h b/include/iprt/vfs.h
new file mode 100644
index 00000000..21fccdf6
--- /dev/null
+++ b/include/iprt/vfs.h
@@ -0,0 +1,2021 @@
+/** @file
+ * IPRT - Virtual Filesystem.
+ */
+
+/*
+ * Copyright (C) 2010-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_vfs_h
+#define IPRT_INCLUDED_vfs_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+#include <iprt/dir.h>
+#include <iprt/fs.h>
+#include <iprt/handle.h>
+#include <iprt/symlink.h>
+#include <iprt/sg.h>
+#include <iprt/time.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_vfs RTVfs - Virtual Filesystem
+ * @ingroup grp_rt
+ *
+ * The virtual filesystem APIs are intended to make it possible to work on
+ * container files, file system sub-trees, file system overlays and other custom
+ * filesystem configurations. It also makes it possible to create filters, like
+ * automatically gunzipping a tar.gz file before feeding it to the RTTar API for
+ * unpacking - or vice versa.
+ *
+ * The virtual filesystem APIs are intended to mirror the RTDir, RTFile, RTPath
+ * and RTFs APIs pretty closely so that rewriting a piece of code to work with
+ * it should be easy. However there are some differences to the way the APIs
+ * works and the user should heed the documentation. The differences are
+ * usually motivated by simplification and in some case to make the VFS more
+ * flexible.
+ *
+ * @{
+ */
+
+/**
+ * The object type.
+ */
+typedef enum RTVFSOBJTYPE
+{
+ /** Invalid type. */
+ RTVFSOBJTYPE_INVALID = 0,
+ /** Pure base object.
+ * This is returned by the filesystem stream to represent directories,
+ * devices, fifos and similar that needs to be created. */
+ RTVFSOBJTYPE_BASE,
+ /** Virtual filesystem. */
+ RTVFSOBJTYPE_VFS,
+ /** Filesystem stream. */
+ RTVFSOBJTYPE_FS_STREAM,
+ /** Pure I/O stream. */
+ RTVFSOBJTYPE_IO_STREAM,
+ /** Directory. */
+ RTVFSOBJTYPE_DIR,
+ /** File. */
+ RTVFSOBJTYPE_FILE,
+ /** Symbolic link. */
+ RTVFSOBJTYPE_SYMLINK,
+ /** End of valid object types. */
+ RTVFSOBJTYPE_END,
+ /** Pure I/O stream. */
+ RTVFSOBJTYPE_32BIT_HACK = 0x7fffffff
+} RTVFSOBJTYPE;
+/** Pointer to a VFS object type. */
+typedef RTVFSOBJTYPE *PRTVFSOBJTYPE;
+
+/**
+ * Translates a RTVFSOBJTYPE value into a string.
+ *
+ * @returns Pointer to readonly name.
+ * @param enmType The object type to name.
+ */
+RTDECL(const char *) RTVfsTypeName(RTVFSOBJTYPE enmType);
+
+
+
+/** @name RTVfsCreate flags
+ * @{ */
+/** Whether the file system is read-only. */
+#define RTVFS_C_READONLY RT_BIT(0)
+/** Whether we the VFS should be thread safe (i.e. automaticaly employ
+ * locks). */
+#define RTVFS_C_THREAD_SAFE RT_BIT(1)
+/** @} */
+
+/**
+ * Creates an empty virtual filesystem.
+ *
+ * @returns IPRT status code.
+ * @param pszName Name, for logging and such.
+ * @param fFlags Flags, MBZ.
+ * @param phVfs Where to return the VFS handle. Release the returned
+ * reference by calling RTVfsRelease.
+ */
+RTDECL(int) RTVfsCreate(const char *pszName, uint32_t fFlags, PRTVFS phVfs);
+RTDECL(uint32_t) RTVfsRetain(RTVFS hVfs);
+RTDECL(uint32_t) RTVfsRetainDebug(RTVFS hVfs, RT_SRC_POS_DECL);
+RTDECL(uint32_t) RTVfsRelease(RTVFS hVfs);
+
+/** @name RTVFSMNT_F_XXX - Flags for RTVfsMount
+ * @{ */
+/** Mount read-only. */
+#define RTVFSMNT_F_READ_ONLY RT_BIT_32(0)
+/** Purpose is . */
+#define RTVFSMNT_F_FOR_RANGE_IN_USE RT_BIT_32(1)
+/** Valid mask. */
+#define RTVFSMNT_F_VALID_MASK UINT32_C(0x00000003)
+/** @} */
+
+/**
+ * Does the file system detection and mounting.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_VFS_UNSUPPORTED_FORMAT if not recognized as a support file
+ * system.
+ * @param hVfsFileIn The file handle of the volume.
+ * @param fFlags RTVFSMTN_F_XXX.
+ * @param phVfs Where to return the VFS handle on success.
+ * @param pErrInfo Where to return additional error information.
+ * Optional.
+ */
+RTDECL(int) RTVfsMountVol(RTVFSFILE hVfsFileIn, uint32_t fFlags, PRTVFS phVfs, PRTERRINFO pErrInfo);
+
+RTDECL(int) RTVfsAttach(RTVFS hVfs, const char *pszMountPoint, uint32_t fFlags, RTVFS hVfsAttach);
+RTDECL(int) RTVfsDetach(RTVFS hVfs, const char *pszMountPoint, RTVFS hVfsToDetach, PRTVFS *phVfsDetached);
+RTDECL(uint32_t) RTVfsGetAttachmentCount(RTVFS hVfs);
+RTDECL(int) RTVfsGetAttachment(RTVFS hVfs, uint32_t iOrdinal, PRTVFS *phVfsAttached, uint32_t *pfFlags,
+ char *pszMountPoint, size_t cbMountPoint);
+
+/**
+ * Opens the root director of the given VFS.
+ *
+ * @returns IPRT status code.
+ * @param hVfs VFS handle.
+ * @param phDir Where to return the root directory handle.
+ */
+RTDECL(int) RTVfsOpenRoot(RTVFS hVfs, PRTVFSDIR phDir);
+
+/**
+ * Queries information about a object in the virtual filesystem.
+ *
+ * @returns IPRT Status code.
+ * @param hVfs VFS handle.
+ * @param pszPath Path to the object, relative to the VFS root.
+ * @param pObjInfo Where to return info.
+ * @param enmAddAttr What to return.
+ * @param fFlags RTPATH_F_XXX.
+ * @sa RTPathQueryInfoEx, RTVfsDirQueryPathInfo, RTVfsObjQueryInfo
+ */
+RTDECL(int) RTVfsQueryPathInfo(RTVFS hVfs, const char *pszPath, PRTFSOBJINFO pObjInfo,
+ RTFSOBJATTRADD enmAddAttr, uint32_t fFlags);
+
+/**
+ * Checks whether a given range is in use by the virtual filesystem.
+ *
+ * @returns IPRT status code.
+ * @param hVfs VFS handle.
+ * @param off Start offset to check.
+ * @param cb Number of bytes to check.
+ * @param pfUsed Where to store the result.
+ */
+RTDECL(int) RTVfsQueryRangeState(RTVFS hVfs, uint64_t off, size_t cb, bool *pfUsed);
+
+/**
+ * Queries the volume label.
+ *
+ * @returns IPRT status code.
+ * @param hVfs VFS handle.
+ * @param fAlternative For use with ISO files to retrieve the primary lable
+ * rather than the joliet / UDF one that the mount
+ * options would indicate. For other file systems, as
+ * well for ISO not mounted in joliet / UDF mode, the
+ * flag is ignored.
+ * @param pszLabel Where to store the lable.
+ * @param cbLabel Size of the buffer @a pszLable points at.
+ * @param pcbActual Where to return the label length, including the
+ * terminator. In case of VERR_BUFFER_OVERFLOW
+ * returns, this will be set to the required buffer
+ * size. Optional.
+ */
+RTDECL(int) RTVfsQueryLabel(RTVFS hVfs, bool fAlternative, char *pszLabel, size_t cbLabel, size_t *pcbActual);
+
+
+/** @defgroup grp_rt_vfs_obj VFS Base Object API
+ * @{
+ */
+
+/**
+ * Retains a reference to the VFS base object handle.
+ *
+ * @returns New reference count on success, UINT32_MAX on failure.
+ * @param hVfsObj The VFS base object handle.
+ */
+RTDECL(uint32_t) RTVfsObjRetain(RTVFSOBJ hVfsObj);
+RTDECL(uint32_t) RTVfsObjRetainDebug(RTVFSOBJ hVfsObj, RT_SRC_POS_DECL);
+
+/**
+ * Releases a reference to the VFS base handle.
+ *
+ * @returns New reference count on success (0 if closed), UINT32_MAX on failure.
+ * @param hVfsObj The VFS base object handle.
+ */
+RTDECL(uint32_t) RTVfsObjRelease(RTVFSOBJ hVfsObj);
+
+/** @name RTVFSOBJ_F_XXX - Flags or RTVfsObjOpen and RTVfsDirOpenObj.
+ * @note Must leave space for RTPATH_F_XXX.
+ * @{ */
+/** Directory (RTFS_TYPE_DIRECTORY). */
+#define RTVFSOBJ_F_OPEN_DIRECTORY RT_BIT_32(8)
+/** Symbolic link (RTFS_TYPE_SYMLINK). */
+#define RTVFSOBJ_F_OPEN_SYMLINK RT_BIT_32(9)
+/** Regular file (RTFS_TYPE_FILE). */
+#define RTVFSOBJ_F_OPEN_FILE RT_BIT_32(10)
+/** Character device (RTFS_TYPE_DEV_CHAR). */
+#define RTVFSOBJ_F_OPEN_DEV_CHAR RT_BIT_32(11)
+/** Block device (RTFS_TYPE_DEV_BLOCK). */
+#define RTVFSOBJ_F_OPEN_DEV_BLOCK RT_BIT_32(12)
+/** Named pipe (fifo) (RTFS_TYPE_FIFO). */
+#define RTVFSOBJ_F_OPEN_FIFO RT_BIT_32(13)
+/** Socket (RTFS_TYPE_SOCKET). */
+#define RTVFSOBJ_F_OPEN_SOCKET RT_BIT_32(14)
+/** Mounted VFS. */
+#define RTVFSOBJ_F_OPEN_MOUNT RT_BIT_32(15)
+/** Mask object types we wish to open. */
+#define RTVFSOBJ_F_OPEN_MASK UINT32_C(0x0000ff00)
+/** Any kind of object that translates to RTVFSOBJTYPE_FILE. */
+#define RTVFSOBJ_F_OPEN_ANY_FILE (RTVFSOBJ_F_OPEN_FILE | RTVFSOBJ_F_OPEN_DEV_BLOCK)
+/** Any kind of object that translates to RTVFSOBJTYPE_IOS or
+ * RTVFSOBJTYPE_FILE. */
+#define RTVFSOBJ_F_OPEN_ANY_IO_STREAM ( RTVFSOBJ_F_ANY_OPEN_FILE | RTVFSOBJ_F_DEV_OPEN_BLOCK \
+ | RTVFSOBJ_F_OPEN_FIFO | RTVFSOBJ_F_OPEN_SOCKET)
+/** Any kind of object. */
+#define RTVFSOBJ_F_OPEN_ANY RTVFSOBJ_F_OPEN_MASK
+
+/** Do't create anything, return file not found. */
+#define RTVFSOBJ_F_CREATE_NOTHING UINT32_C(0x00000000)
+/** Create a file if the if the object was not found and the RTFILE_O_XXX
+ * flags allows it. */
+#define RTVFSOBJ_F_CREATE_FILE UINT32_C(0x00010000)
+/** Create a directory if the object was not found and the RTFILE_O_XXX
+ * flags allows it. */
+#define RTVFSOBJ_F_CREATE_DIRECTORY UINT32_C(0x00020000)
+/** The creation type mask. */
+#define RTVFSOBJ_F_CREATE_MASK UINT32_C(0x00070000)
+
+/** Indicate that this call is for traversal.
+ * @internal only */
+#define RTVFSOBJ_F_TRAVERSAL RT_BIT_32(31)
+/** Valid mask for external callers. */
+#define RTVFSOBJ_F_VALID_MASK UINT32_C(0x0007ff00)
+/** @} */
+
+/**
+ * Opens any file system object in the given VFS.
+ *
+ * @returns IPRT status code.
+ * @param hVfs The VFS to open the object within.
+ * @param pszPath Path to the file.
+ * @param fFileOpen RTFILE_O_XXX flags.
+ * @param fObjFlags More flags: RTVFSOBJ_F_XXX, RTPATH_F_XXX.
+ * @param phVfsObj Where to return the object handle.
+ * @sa RTVfsDirOpenObj, RTVfsDirOpenDir, RTVfsDirOpenFile
+ */
+RTDECL(int) RTVfsObjOpen(RTVFS hVfs, const char *pszPath, uint64_t fFileOpen, uint32_t fObjFlags, PRTVFSOBJ phVfsObj);
+
+/**
+ * Query information about the object.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_NOT_SUPPORTED if the @a enmAddAttr value is not handled by the
+ * implementation.
+ *
+ * @param hVfsObj The VFS object handle.
+ * @param pObjInfo Where to return the info.
+ * @param enmAddAttr Which additional attributes should be retrieved.
+ * @sa RTVfsIoStrmQueryInfo, RTVfsFileQueryInfo, RTFileQueryInfo,
+ * RTPathQueryInfo
+ */
+RTDECL(int) RTVfsObjQueryInfo(RTVFSOBJ hVfsObj, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr);
+
+/**
+ * Sets the file mode for the given VFS object.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_INVALID_FUNCTION if the object type has no file mode to set.
+ * Only directories, files and symbolic links support this operation.
+ *
+ * @param hVfsObj The VFS object handle.
+ * @param fMode The mode mask.
+ * @param fMask The bits in the mode mask which should be changed.
+ */
+RTDECL(int) RTVfsObjSetMode(RTVFSOBJ hVfsObj, RTFMODE fMode, RTFMODE fMask);
+
+/**
+ * Sets one or more timestamps for the given VFS object.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_INVALID_FUNCTION if the object type has no file mode to set.
+ * Only directories, files and symbolic links support this operation.
+ *
+ * @param hVfsObj The VFS object handle.
+ * @param pAccessTime Pointer to the new access time. NULL if not to
+ * be changed.
+ * @param pModificationTime Pointer to the new modifcation time. NULL if not
+ * to be changed.
+ * @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.
+ *
+ * @remarks See RTFileSetTimes for restrictions and behavior imposed by the
+ * host OS or underlying VFS provider.
+ * @sa RTFileSetTimes, RTPathSetTimes
+ */
+RTDECL(int) RTVfsObjSetTimes(RTVFSOBJ hVfsObj, PCRTTIMESPEC pAccessTime, PCRTTIMESPEC pModificationTime,
+ PCRTTIMESPEC pChangeTime, PCRTTIMESPEC pBirthTime);
+
+/**
+ * Set the unix style owner and group on the given VFS object.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_INVALID_FUNCTION if the object type has no file mode to set.
+ * Only directories, files and symbolic links support this operation.
+ *
+ * @param hVfsObj The VFS object handle.
+ * @param uid The user ID of the new owner. NIL_RTUID if
+ * unchanged.
+ * @param gid The group ID of the new owner group. NIL_RTGID if
+ * unchanged.
+ *
+ * @sa RTFileSetOwner, RTPathSetOwner.
+ */
+RTDECL(int) RTVfsObjSetOwner(RTVFSOBJ hVfsObj, RTUID uid, RTGID gid);
+
+
+/**
+ * Gets the type of a VFS object.
+ *
+ * @returns The VFS object type on success, RTVFSOBJTYPE_INVALID on failure.
+ * @param hVfsObj The VFS base object handle.
+ */
+RTDECL(RTVFSOBJTYPE) RTVfsObjGetType(RTVFSOBJ hVfsObj);
+
+/**
+ * Converts a VFS base object handle to a VFS handle.
+ *
+ * @returns Referenced handle on success, NIL on failure.
+ * @param hVfsObj The VFS base object handle.
+ */
+RTDECL(RTVFS) RTVfsObjToVfs(RTVFSOBJ hVfsObj);
+
+/**
+ * Converts a VFS base object handle to a VFS filesystem stream handle.
+ *
+ * @returns Referenced handle on success, NIL on failure.
+ * @param hVfsObj The VFS base object handle.
+ */
+RTDECL(RTVFSFSSTREAM) RTVfsObjToFsStream(RTVFSOBJ hVfsObj);
+
+/**
+ * Converts a VFS base object handle to a VFS directory handle.
+ *
+ * @returns Referenced handle on success, NIL on failure.
+ * @param hVfsObj The VFS base object handle.
+ */
+RTDECL(RTVFSDIR) RTVfsObjToDir(RTVFSOBJ hVfsObj);
+
+/**
+ * Converts a VFS base object handle to a VFS I/O stream handle.
+ *
+ * @returns Referenced handle on success, NIL on failure.
+ * @param hVfsObj The VFS base object handle.
+ */
+RTDECL(RTVFSIOSTREAM) RTVfsObjToIoStream(RTVFSOBJ hVfsObj);
+
+/**
+ * Converts a VFS base object handle to a VFS file handle.
+ *
+ * @returns Referenced handle on success, NIL on failure.
+ * @param hVfsObj The VFS base object handle.
+ */
+RTDECL(RTVFSFILE) RTVfsObjToFile(RTVFSOBJ hVfsObj);
+
+/**
+ * Converts a VFS base object handle to a VFS symbolic link handle.
+ *
+ * @returns Referenced handle on success, NIL on failure.
+ * @param hVfsObj The VFS base object handle.
+ */
+RTDECL(RTVFSSYMLINK) RTVfsObjToSymlink(RTVFSOBJ hVfsObj);
+
+
+/**
+ * Converts a VFS handle to a VFS base object handle.
+ *
+ * @returns Referenced handle on success, NIL if the input handle was invalid.
+ * @param hVfs The VFS handle.
+ */
+RTDECL(RTVFSOBJ) RTVfsObjFromVfs(RTVFS hVfs);
+
+/**
+ * Converts a VFS filesystem stream handle to a VFS base object handle.
+ *
+ * @returns Referenced handle on success, NIL if the input handle was invalid.
+ * @param hVfsFss The VFS filesystem stream handle.
+ */
+RTDECL(RTVFSOBJ) RTVfsObjFromFsStream(RTVFSFSSTREAM hVfsFss);
+
+/**
+ * Converts a VFS directory handle to a VFS base object handle.
+ *
+ * @returns Referenced handle on success, NIL if the input handle was invalid.
+ * @param hVfsDir The VFS directory handle.
+ */
+RTDECL(RTVFSOBJ) RTVfsObjFromDir(RTVFSDIR hVfsDir);
+
+/**
+ * Converts a VFS I/O stream handle to a VFS base object handle.
+ *
+ * @returns Referenced handle on success, NIL if the input handle was invalid.
+ * @param hVfsIos The VFS I/O stream handle.
+ */
+RTDECL(RTVFSOBJ) RTVfsObjFromIoStream(RTVFSIOSTREAM hVfsIos);
+
+/**
+ * Converts a VFS file handle to a VFS base object handle.
+ *
+ * @returns Referenced handle on success, NIL if the input handle was invalid.
+ * @param hVfsFile The VFS file handle.
+ */
+RTDECL(RTVFSOBJ) RTVfsObjFromFile(RTVFSFILE hVfsFile);
+
+/**
+ * Converts a VFS symbolic link handle to a VFS base object handle.
+ *
+ * @returns Referenced handle on success, NIL if the input handle was invalid.
+ * @param hVfsSym The VFS symbolic link handle.
+ */
+RTDECL(RTVFSOBJ) RTVfsObjFromSymlink(RTVFSSYMLINK hVfsSym);
+
+/** @} */
+
+
+/** @defgroup grp_rt_vfs_fsstream VFS Filesystem Stream API
+ *
+ * Filesystem streams are for tar, cpio and similar. Any virtual filesystem can
+ * be turned into a filesystem stream using RTVfsFsStrmFromVfs.
+ *
+ * @{
+ */
+
+RTDECL(uint32_t) RTVfsFsStrmRetain(RTVFSFSSTREAM hVfsFss);
+RTDECL(uint32_t) RTVfsFsStrmRetainDebug(RTVFSFSSTREAM hVfsFss, RT_SRC_POS_DECL);
+RTDECL(uint32_t) RTVfsFsStrmRelease(RTVFSFSSTREAM hVfsFss);
+RTDECL(int) RTVfsFsStrmQueryInfo(RTVFSFSSTREAM hVfsFss, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr);
+
+/**
+ * Gets the next object in the stream.
+ *
+ * This call may affect the stream posision of a previously returned object.
+ *
+ * The type of object returned here typically boils down to three types:
+ * - I/O streams (representing files),
+ * - symbolic links
+ * - base object
+ * The base objects represent anything not convered by the two other, i.e.
+ * directories, device nodes, fifos, sockets and whatnot. The details can be
+ * queried using RTVfsObjQueryInfo.
+ *
+ * That said, absolutely any object except for filesystem stream objects can be
+ * returned by this call. Any generic code is adviced to just deal with it all.
+ *
+ * @returns IPRT status code.
+ * @retval VINF_SUCCESS if a new object was retrieved.
+ * @retval VERR_EOF when there are no more objects.
+ * @retval VERR_INVALID_FUNCTION if called on a non-readable stream.
+ *
+ * @param hVfsFss The file system stream handle.
+ * @param ppszName Where to return the object name. Must be freed by
+ * calling RTStrFree.
+ * @param penmType Where to return the object type.
+ * @param phVfsObj Where to return the object handle (referenced). This
+ * must be cast to the desired type before use.
+ */
+RTDECL(int) RTVfsFsStrmNext(RTVFSFSSTREAM hVfsFss, char **ppszName, RTVFSOBJTYPE *penmType, PRTVFSOBJ phVfsObj);
+
+/**
+ * Appends a VFS object to the stream.
+ *
+ * The stream must be writable.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_INVALID_FUNCTION if called on a non-writable stream.
+ * @param hVfsFss The file system stream handle.
+ * @param pszPath The path.
+ * @param hVfsObj The VFS object to add.
+ * @param fFlags RTVFSFSSTRM_ADD_F_XXX.
+ */
+RTDECL(int) RTVfsFsStrmAdd(RTVFSFSSTREAM hVfsFss, const char *pszPath, RTVFSOBJ hVfsObj, uint32_t fFlags);
+
+/** @name RTVFSFSSTRM_ADD_F_XXX - Flags for RTVfsFsStrmAdd.
+ * @{ */
+/** Input is an I/O stream of indeterminate length, read to the end and then
+ * update the file header.
+ * @note This is *only* possible if the output stream is actually a file. */
+#define RTVFSFSSTRM_ADD_F_STREAM RT_BIT_32(0)
+/** Mask of flags specific to the target stream. */
+#define RTVFSFSSTRM_ADD_F_SPECIFIC_MASK UINT32_C(0xff000000)
+/** Valid bits. */
+#define RTVFSFSSTRM_ADD_F_VALID_MASK UINT32_C(0xff000001)
+/** @} */
+
+/**
+ * Pushes an byte stream onto the stream.
+ *
+ * The stream must be writable.
+ *
+ * This differs from RTVfsFsStrmAdd() in that it will create a regular file in
+ * the output file system stream and provide the actual content bytes via the
+ * returned I/O stream object.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_INVALID_FUNCTION if called on a non-writable stream.
+ * @param hVfsFss The file system stream handle.
+ * @param pszPath The path to the file.
+ * @param cbFile The file size. This can also be set to UINT64_MAX if
+ * the file system stream is backed by a file.
+ * @param paObjInfo Array of zero or more RTFSOBJINFO structures containing
+ * different pieces of information about the file. If any
+ * provided, the first one should be a RTFSOBJATTRADD_UNIX
+ * one, additional can be supplied if wanted. What exactly
+ * is needed depends on the underlying FS stream
+ * implementation.
+ * @param cObjInfo Number of items in the array @a paObjInfo points at.
+ * @param fFlags RTVFSFSSTRM_PUSH_F_XXX.
+ * @param phVfsIos Where to return the I/O stream to feed the file content
+ * to. If the FS stream is backed by a file, the returned
+ * handle can be cast to a file if necessary.
+ */
+RTDECL(int) RTVfsFsStrmPushFile(RTVFSFSSTREAM hVfsFss, const char *pszPath, uint64_t cbFile,
+ PCRTFSOBJINFO paObjInfo, uint32_t cObjInfo, uint32_t fFlags, PRTVFSIOSTREAM phVfsIos);
+
+/** @name RTVFSFSSTRM_PUSH_F_XXX - Flags for RTVfsFsStrmPushFile.
+ * @{ */
+/** Input is an I/O stream of indeterminate length, read to the end and then
+ * update the file header.
+ * @note This is *only* possible if the output stream is actually a file. */
+#define RTVFSFSSTRM_PUSH_F_STREAM RT_BIT_32(0)
+/** Mask of flags specific to the target stream. */
+#define RTVFSFSSTRM_PUSH_F_SPECIFIC_MASK UINT32_C(0xff000000)
+/** Valid bits. */
+#define RTVFSFSSTRM_PUSH_F_VALID_MASK UINT32_C(0xff000001)
+/** @} */
+
+/**
+ * Marks the end of the stream.
+ *
+ * The stream must be writable.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_INVALID_FUNCTION if called on a non-writable stream.
+ * @param hVfsFss The file system stream handle.
+ */
+RTDECL(int) RTVfsFsStrmEnd(RTVFSFSSTREAM hVfsFss);
+
+/** @} */
+
+
+/** @defgroup grp_rt_vfs_dir VFS Directory API
+ * @{
+ */
+
+/**
+ * Retains a reference to the VFS directory handle.
+ *
+ * @returns New reference count on success, UINT32_MAX on failure.
+ * @param hVfsDir The VFS directory handle.
+ */
+RTDECL(uint32_t) RTVfsDirRetain(RTVFSDIR hVfsDir);
+RTDECL(uint32_t) RTVfsDirRetainDebug(RTVFSDIR hVfsDir, RT_SRC_POS_DECL);
+
+/**
+ * Releases a reference to the VFS directory handle.
+ *
+ * @returns New reference count on success (0 if closed), UINT32_MAX on failure.
+ * @param hVfsDir The VFS directory handle.
+ */
+RTDECL(uint32_t) RTVfsDirRelease(RTVFSDIR hVfsDir);
+
+/**
+ * Opens a directory in the specified file system.
+ *
+ * @returns IPRT status code.
+ * @param hVfs The VFS to open the directory within.
+ * @param pszPath Path to the directory, relative to the root.
+ * @param fFlags Reserved, MBZ.
+ * @param phVfsDir Where to return the directory.
+ */
+RTDECL(int) RTVfsDirOpen(RTVFS hVfs, const char *pszPath, uint32_t fFlags, PRTVFSDIR phVfsDir);
+
+/**
+ * Opens any file system object in or under the given directory.
+ *
+ * @returns IPRT status code.
+ * @param hVfsDir The VFS directory start walking the @a pszPath
+ * relative to.
+ * @param pszPath Path to the file.
+ * @param fFileOpen RTFILE_O_XXX flags.
+ * @param fObjFlags More flags: RTVFSOBJ_F_XXX, RTPATH_F_XXX.
+ * @param phVfsObj Where to return the object handle.
+ * @sa RTVfsObjOpen, RTVfsDirOpenDir, RTVfsDirOpenFile
+ */
+RTDECL(int) RTVfsDirOpenObj(RTVFSDIR hVfsDir, const char *pszPath, uint64_t fFileOpen, uint32_t fObjFlags, PRTVFSOBJ phVfsObj);
+
+/**
+ * Opens a file in or under the given directory.
+ *
+ * @returns IPRT status code.
+ * @param hVfsDir The VFS directory start walking the @a pszPath
+ * relative to.
+ * @param pszPath Path to the file.
+ * @param fOpen RTFILE_O_XXX flags.
+ * @param phVfsFile Where to return the file.
+ * @sa RTVfsDirOpenFileAsIoStream
+ */
+RTDECL(int) RTVfsDirOpenFile(RTVFSDIR hVfsDir, const char *pszPath, uint64_t fOpen, PRTVFSFILE phVfsFile);
+
+/**
+ * Convenience wrapper around RTVfsDirOpenFile that returns an I/O stream.
+ *
+ * @returns IPRT status code.
+ * @param hVfsDir The VFS directory start walking the @a pszPath
+ * relative to.
+ * @param pszPath Path to the file.
+ * @param fOpen RTFILE_O_XXX flags.
+ * @param phVfsIos Where to return the I/O stream handle of the file.
+ * @sa RTVfsDirOpenFile
+ */
+RTDECL(int) RTVfsDirOpenFileAsIoStream(RTVFSDIR hVfsDir, const char *pszPath, uint64_t fOpen, PRTVFSIOSTREAM phVfsIos);
+
+/**
+ * Opens a directory in or under the given directory.
+ *
+ * @returns IPRT status code.
+ * @param hVfsDir The VFS directory start walking the @a pszPath
+ * relative to.
+ * @param pszPath Path to the file.
+ * @param fFlags Reserved, MBZ.
+ * @param phVfsDir Where to return the directory.
+ */
+RTDECL(int) RTVfsDirOpenDir(RTVFSDIR hVfsDir, const char *pszPath, uint32_t fFlags, PRTVFSDIR phVfsDir);
+
+/**
+ * Creates a directory relative to @a hVfsDir.
+ *
+ * @returns IPRT status code
+ * @param hVfsDir The directory the path is relative to.
+ * @param pszRelPath The relative path to the new directory.
+ * @param fMode The file mode for the new directory.
+ * @param fFlags Directory creation flags, RTDIRCREATE_FLAGS_XXX.
+ * @param phVfsDir Where to return the handle to the newly created
+ * directory. Optional.
+ * @sa RTDirCreate, RTDirRelDirCreate
+ */
+RTDECL(int) RTVfsDirCreateDir(RTVFSDIR hVfsDir, const char *pszRelPath, RTFMODE fMode, uint32_t fFlags, PRTVFSDIR phVfsDir);
+
+/**
+ * Create a VFS directory handle from a standard IPRT directory handle (RTDIR).
+ *
+ * @returns IPRT status code.
+ * @param hDir The standard IPRT directory handle.
+ * @param fLeaveOpen Whether to leave the handle open when the VFS
+ * directory is released, or to close it (@c false).
+ * @param phVfsDir Where to return the VFS directory handle.
+ */
+RTDECL(int) RTVfsDirFromRTDir(RTDIR hDir, bool fLeaveOpen, PRTVFSDIR phVfsDir);
+
+/**
+ * RTDirOpen + RTVfsDirFromRTDir.
+ *
+ * @returns IPRT status code.
+ * @param pszPath The path to the directory.
+ * @param fFlags RTDIR_F_XXX.
+ * @param phVfsDir Where to return the VFS directory handle.
+ */
+RTDECL(int) RTVfsDirOpenNormal(const char *pszPath, uint32_t fFlags, PRTVFSDIR phVfsDir);
+
+/** Checks if @a hVfsDir was opened using RTVfsDirOpenNormal() or
+ * RTVfsDirFromRTDir(), either directly or indirectly. */
+RTDECL(bool) RTVfsDirIsStdDir(RTVFSDIR hVfsDir);
+
+/**
+ * Queries information about a object in or under the given directory.
+ *
+ * @returns IPRT Status code.
+ * @param hVfsDir The VFS directory start walking the @a pszPath
+ * relative to.
+ * @param pszPath Path to the object.
+ * @param pObjInfo Where to return info.
+ * @param enmAddAttr What to return.
+ * @param fFlags RTPATH_F_XXX.
+ * @sa RTPathQueryInfoEx, RTVfsQueryPathInfo, RTVfsObjQueryInfo
+ */
+RTDECL(int) RTVfsDirQueryPathInfo(RTVFSDIR hVfsDir, const char *pszPath, PRTFSOBJINFO pObjInfo,
+ RTFSOBJATTRADD enmAddAttr, uint32_t fFlags);
+
+/**
+ * Removes a directory relative to @a hVfsDir.
+ *
+ * @returns IPRT status code.
+ * @param hVfsDir The VFS directory to start walking the @a pszRelPath
+ * relative to.
+ * @param pszRelPath The path to the directory that should be removed.
+ * @param fFlags Reserved, MBZ.
+ */
+RTDECL(int) RTVfsDirRemoveDir(RTVFSDIR hVfsDir, const char *pszRelPath, uint32_t fFlags);
+
+/**
+ * Reads the next entry in the directory returning extended information.
+ *
+ * @returns VINF_SUCCESS and data in pDirEntry on success.
+ * @returns VERR_NO_MORE_FILES when the end of the directory has been reached.
+ * @returns VERR_BUFFER_OVERFLOW if the buffer is too small to contain the filename. If
+ * pcbDirEntry is specified it will be updated with the required buffer size.
+ * @returns suitable iprt status code on other errors.
+ *
+ * @param hVfsDir The VFS directory.
+ * @param pDirEntry Where to store the information about the next
+ * directory entry on success.
+ * @param pcbDirEntry Optional parameter used for variable buffer size.
+ *
+ * On input the variable pointed to contains the size of the pDirEntry
+ * structure. This must be at least OFFSET(RTDIRENTRYEX, szName[2]) bytes.
+ *
+ * On successful output the field is updated to
+ * OFFSET(RTDIRENTRYEX, szName[pDirEntry->cbName + 1]).
+ *
+ * When the data doesn't fit in the buffer and VERR_BUFFER_OVERFLOW is
+ * returned, this field contains the required buffer size.
+ *
+ * The value is unchanged in all other cases.
+ * @param enmAddAttr Which set of additional attributes to request.
+ * Use RTFSOBJATTRADD_NOTHING if this doesn't matter.
+ *
+ * @sa RTDirReadEx
+ */
+RTDECL(int) RTVfsDirReadEx(RTVFSDIR hVfsDir, PRTDIRENTRYEX pDirEntry, size_t *pcbDirEntry, RTFSOBJATTRADD enmAddAttr);
+
+/**
+ * Rewind and restart the directory reading.
+ *
+ * @returns IRPT status code.
+ * @param hVfsDir The VFS directory.
+ */
+RTDECL(int) RTVfsDirRewind(RTVFSDIR hVfsDir);
+
+/** @} */
+
+
+/** @defgroup grp_rt_vfs_symlink VFS Symbolic Link API
+ *
+ * @remarks The TAR VFS and filesystem stream uses symbolic links for
+ * describing hard links as well. The users must use RTFS_IS_SYMLINK
+ * to check if it is a real symlink in those cases.
+ *
+ * @remarks Any VFS which is backed by a real file system may be subject to
+ * races with other processes or threads, so the user may get
+ * unexpected errors when this happends. This is a bit host specific,
+ * i.e. it might be prevent on windows if we care.
+ *
+ * @{
+ */
+
+
+/**
+ * Retains a reference to the VFS symbolic link handle.
+ *
+ * @returns New reference count on success, UINT32_MAX on failure.
+ * @param hVfsSym The VFS symbolic link handle.
+ */
+RTDECL(uint32_t) RTVfsSymlinkRetain(RTVFSSYMLINK hVfsSym);
+RTDECL(uint32_t) RTVfsSymlinkRetainDebug(RTVFSSYMLINK hVfsSym, RT_SRC_POS_DECL);
+
+/**
+ * Releases a reference to the VFS symbolic link handle.
+ *
+ * @returns New reference count on success (0 if closed), UINT32_MAX on failure.
+ * @param hVfsSym The VFS symbolic link handle.
+ */
+RTDECL(uint32_t) RTVfsSymlinkRelease(RTVFSSYMLINK hVfsSym);
+
+/**
+ * Query information about the symbolic link.
+ *
+ * @returns IPRT status code.
+ * @param hVfsSym The VFS symbolic link handle.
+ * @param pObjInfo Where to return the info.
+ * @param enmAddAttr Which additional attributes should be retrieved.
+ *
+ * @sa RTFileQueryInfo, RTPathQueryInfo, RTPathQueryInfoEx
+ */
+RTDECL(int) RTVfsSymlinkQueryInfo(RTVFSSYMLINK hVfsSym, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr);
+
+/**
+ * Set the unix style owner and group.
+ *
+ * @returns IPRT status code.
+ * @param hVfsSym The VFS symbolic link handle.
+ * @param fMode The new mode bits.
+ * @param fMask The mask indicating which bits we are changing.
+ * @sa RTFileSetMode, RTPathSetMode
+ */
+RTDECL(int) RTVfsSymlinkSetMode(RTVFSSYMLINK hVfsSym, RTFMODE fMode, RTFMODE fMask);
+
+/**
+ * Set the timestamps associated with the object.
+ *
+ * @returns IPRT status code.
+ * @param hVfsSym The VFS symbolic link handle.
+ * @param pAccessTime Pointer to the new access time. NULL if not
+ * to be changed.
+ * @param pModificationTime Pointer to the new modifcation time. NULL if
+ * not to be changed.
+ * @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.
+ * @remarks See RTFileSetTimes for restrictions and behavior imposed by the
+ * host OS or underlying VFS provider.
+ * @sa RTFileSetTimes, RTPathSetTimes
+ */
+RTDECL(int) RTVfsSymlinkSetTimes(RTVFSSYMLINK hVfsSym, PCRTTIMESPEC pAccessTime, PCRTTIMESPEC pModificationTime,
+ PCRTTIMESPEC pChangeTime, PCRTTIMESPEC pBirthTime);
+
+/**
+ * Set the unix style owner and group.
+ *
+ * @returns IPRT status code.
+ * @param hVfsSym The VFS symbolic link handle.
+ * @param uid The user ID of the new owner. NIL_RTUID if
+ * unchanged.
+ * @param gid The group ID of the new owner group. NIL_RTGID if
+ * unchanged.
+ * @sa RTFileSetOwner, RTPathSetOwner.
+ */
+RTDECL(int) RTVfsSymlinkSetOwner(RTVFSSYMLINK hVfsSym, RTUID uid, RTGID gid);
+
+/**
+ * Read the symbolic link target.
+ *
+ * @returns IPRT status code.
+ * @param hVfsSym The VFS symbolic link handle.
+ * @param pszTarget The target buffer.
+ * @param cbTarget The size of the target buffer.
+ * @sa RTSymlinkRead
+ */
+RTDECL(int) RTVfsSymlinkRead(RTVFSSYMLINK hVfsSym, char *pszTarget, size_t cbTarget);
+
+/** @} */
+
+
+
+/** @defgroup grp_rt_vfs_iostream VFS I/O Stream API
+ * @{
+ */
+
+/**
+ * Creates a VFS file from a memory buffer.
+ *
+ * @returns IPRT status code.
+ *
+ * @param fFlags A combination of RTFILE_O_READ and RTFILE_O_WRITE.
+ * @param pvBuf The buffer. This will be copied and not referenced
+ * after this function returns.
+ * @param cbBuf The buffer size.
+ * @param phVfsIos Where to return the VFS I/O stream handle.
+ */
+RTDECL(int) RTVfsIoStrmFromBuffer(uint32_t fFlags, void const *pvBuf, size_t cbBuf, PRTVFSIOSTREAM phVfsIos);
+
+/**
+ * Creates a VFS I/O stream handle from a standard IPRT file handle (RTFILE).
+ *
+ * @returns IPRT status code.
+ * @param hFile The standard IPRT file handle.
+ * @param fOpen The flags the handle was opened with. Pass 0 to
+ * have these detected.
+ * @param fLeaveOpen Whether to leave the handle open when the VFS file
+ * is released, or to close it (@c false).
+ * @param phVfsIos Where to return the VFS I/O stream handle.
+ */
+RTDECL(int) RTVfsIoStrmFromRTFile(RTFILE hFile, uint64_t fOpen, bool fLeaveOpen, PRTVFSIOSTREAM phVfsIos);
+
+/**
+ * Creates a VFS I/O stream handle from a standard IPRT pipe handle (RTPIPE).
+ *
+ * @returns IPRT status code.
+ * @param hPipe The standard IPRT pipe handle.
+ * @param fLeaveOpen Whether to leave the handle open when the VFS file
+ * is released, or to close it (@c false).
+ * @param phVfsIos Where to return the VFS I/O stream handle.
+ */
+RTDECL(int) RTVfsIoStrmFromRTPipe(RTPIPE hPipe, bool fLeaveOpen, PRTVFSIOSTREAM phVfsIos);
+
+/**
+ * Convenience function combining RTFileOpen with RTVfsIoStrmFromRTFile.
+ *
+ * @returns IPRT status code.
+ * @param pszFilename The path to the file in the normal file system.
+ * @param fOpen The flags to pass to RTFileOpen when opening the
+ * file, i.e. RTFILE_O_XXX.
+ * @param phVfsIos Where to return the VFS I/O stream handle.
+ */
+RTDECL(int) RTVfsIoStrmOpenNormal(const char *pszFilename, uint64_t fOpen, PRTVFSIOSTREAM phVfsIos);
+
+/**
+ * Create a VFS I/O stream handle from one of the standard handles.
+ *
+ * @returns IPRT status code.
+ * @param enmStdHandle The standard IPRT file handle.
+ * @param fOpen The flags the handle was opened with. Pass 0 to
+ * have these detected.
+ * @param fLeaveOpen Whether to leave the handle open when the VFS file
+ * is released, or to close it (@c false).
+ * @param phVfsIos Where to return the VFS I/O stream handle.
+ */
+RTDECL(int) RTVfsIoStrmFromStdHandle(RTHANDLESTD enmStdHandle, uint64_t fOpen, bool fLeaveOpen,
+ PRTVFSIOSTREAM phVfsIos);
+
+/**
+ * Retains a reference to the VFS I/O stream handle.
+ *
+ * @returns New reference count on success, UINT32_MAX on failure.
+ * @param hVfsIos The VFS I/O stream handle.
+ */
+RTDECL(uint32_t) RTVfsIoStrmRetain(RTVFSIOSTREAM hVfsIos);
+RTDECL(uint32_t) RTVfsIoStrmRetainDebug(RTVFSIOSTREAM hVfsIos, RT_SRC_POS_DECL);
+
+/**
+ * Releases a reference to the VFS I/O stream handle.
+ *
+ * @returns New reference count on success (0 if closed), UINT32_MAX on failure.
+ * @param hVfsIos The VFS I/O stream handle.
+ */
+RTDECL(uint32_t) RTVfsIoStrmRelease(RTVFSIOSTREAM hVfsIos);
+
+/**
+ * Convert the VFS I/O stream handle to a VFS file handle.
+ *
+ * @returns The VFS file handle on success, this must be released.
+ * NIL_RTVFSFILE if the I/O stream handle is invalid.
+ * @param hVfsIos The VFS I/O stream handle.
+ * @sa RTVfsFileToIoStream
+ */
+RTDECL(RTVFSFILE) RTVfsIoStrmToFile(RTVFSIOSTREAM hVfsIos);
+
+/**
+ * Query information about the I/O stream.
+ *
+ * @returns IPRT status code.
+ * @param hVfsIos The VFS I/O stream handle.
+ * @param pObjInfo Where to return the info.
+ * @param enmAddAttr Which additional attributes should be retrieved.
+ * @sa RTFileQueryInfo
+ */
+RTDECL(int) RTVfsIoStrmQueryInfo(RTVFSIOSTREAM hVfsIos, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr);
+
+/**
+ * Read bytes from the I/O stream.
+ *
+ * @returns IPRT status code.
+ * @retval VINF_SUCCESS and the number of bytes read written to @a pcbRead.
+ * @retval VINF_TRY_AGAIN if @a fBlocking is @c false, @a pcbRead is not NULL,
+ * and no data was available. @a *pcbRead will be set to 0.
+ * @retval VINF_EOF when trying to read __beyond__ the end of the stream and
+ * @a pcbRead is not NULL (it will be set to the number of bytes read,
+ * or 0 if the end of the stream was reached before this call).
+ * When the last byte of the read request is the last byte in the
+ * stream, this status code will not be used. However, VINF_EOF is
+ * returned when attempting to read 0 bytes while standing at the end
+ * of the stream.
+ * @retval VERR_EOF when trying to read __beyond__ the end of the stream and
+ * @a pcbRead is NULL.
+ * @retval VERR_ACCESS_DENIED if the stream is not readable.
+ *
+ * @param hVfsIos The VFS I/O stream handle.
+ * @param pvBuf Where to store the read bytes.
+ * @param cbToRead The number of bytes to read.
+ * @param fBlocking Whether the call is blocking (@c true) or not. If
+ * not, the @a pcbRead parameter must not be NULL.
+ * @param pcbRead Where to always store the number of bytes actually
+ * read. This can be NULL if @a fBlocking is true.
+ * @sa RTVfsFileRead, RTFileRead, RTPipeRead, RTPipeReadBlocking,
+ * RTSocketRead
+ */
+RTDECL(int) RTVfsIoStrmRead(RTVFSIOSTREAM hVfsIos, void *pvBuf, size_t cbToRead, bool fBlocking, size_t *pcbRead);
+
+/**
+ * Read bytes from the I/O stream, optionally with offset.
+ *
+ * @returns IPRT status code.
+ * @retval VINF_SUCCESS and the number of bytes read written to @a pcbRead.
+ * @retval VINF_TRY_AGAIN if @a fBlocking is @c false, @a pcbRead is not NULL,
+ * and no data was available. @a *pcbRead will be set to 0.
+ * @retval VINF_EOF when trying to read __beyond__ the end of the stream and
+ * @a pcbRead is not NULL (it will be set to the number of bytes read,
+ * or 0 if the end of the stream was reached before this call).
+ * When the last byte of the read request is the last byte in the
+ * stream, this status code will not be used. However, VINF_EOF is
+ * returned when attempting to read 0 bytes while standing at the end
+ * of the stream.
+ * @retval VERR_EOF when trying to read __beyond__ the end of the stream and
+ * @a pcbRead is NULL.
+ * @retval VERR_ACCESS_DENIED if the stream is not readable.
+ *
+ * @param hVfsIos The VFS I/O stream handle.
+ * @param off Where to read at, -1 for the current position.
+ * @param pvBuf Where to store the read bytes.
+ * @param cbToRead The number of bytes to read.
+ * @param fBlocking Whether the call is blocking (@c true) or not. If
+ * not, the @a pcbRead parameter must not be NULL.
+ * @param pcbRead Where to always store the number of bytes actually
+ * read. This can be NULL if @a fBlocking is true.
+ * @sa RTVfsFileRead, RTFileRead, RTPipeRead, RTPipeReadBlocking,
+ * RTSocketRead
+ */
+RTDECL(int) RTVfsIoStrmReadAt(RTVFSIOSTREAM hVfsIos, RTFOFF off, void *pvBuf, size_t cbToRead, bool fBlocking, size_t *pcbRead);
+
+/**
+ * Reads the remainder of the stream into a memory buffer.
+ *
+ * For simplifying string-style processing, the is a zero byte after the
+ * returned buffer, making sure it can be used as a zero terminated string.
+ *
+ * @returns IPRT status code.
+ * @param hVfsIos The VFS I/O stream handle.
+ * @param ppvBuf Where to return the buffer. Must pass to
+ * RTVfsIoStrmReadAllFree for freeing, not RTMemFree!
+ * @param pcbBuf Where to return the buffer size.
+ */
+RTDECL(int) RTVfsIoStrmReadAll(RTVFSIOSTREAM hVfsIos, void **ppvBuf, size_t *pcbBuf);
+
+/**
+ * Free memory buffer returned by RTVfsIoStrmReadAll.
+ *
+ * @param pvBuf What RTVfsIoStrmReadAll returned.
+ * @param cbBuf What RTVfsIoStrmReadAll returned.
+ */
+RTDECL(void) RTVfsIoStrmReadAllFree(void *pvBuf, size_t cbBuf);
+
+/**
+ * Write bytes to the I/O stream.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_ACCESS_DENIED if the stream is not writable.
+ *
+ * @param hVfsIos The VFS I/O stream handle.
+ * @param pvBuf The bytes to write.
+ * @param cbToWrite The number of bytes to write.
+ * @param fBlocking Whether the call is blocking (@c true) or not. If
+ * not, the @a pcbWritten parameter must not be NULL.
+ * @param pcbWritten Where to always store the number of bytes actually
+ * written. This can be NULL if @a fBlocking is true.
+ * @sa RTVfsFileWrite, RTFileWrite, RTPipeWrite, RTPipeWriteBlocking,
+ * RTSocketWrite
+ */
+RTDECL(int) RTVfsIoStrmWrite(RTVFSIOSTREAM hVfsIos, const void *pvBuf, size_t cbToWrite, bool fBlocking, size_t *pcbWritten);
+RTDECL(int) RTVfsIoStrmWriteAt(RTVFSIOSTREAM hVfsIos, RTFOFF off, const void *pvBuf, size_t cbToWrite, bool fBlocking, size_t *pcbWritten);
+
+/**
+ * Reads bytes from the I/O stream into a scatter buffer.
+ *
+ * @returns IPRT status code.
+ * @retval VINF_SUCCESS and the number of bytes read written to @a pcbRead.
+ * @retval VINF_TRY_AGAIN if @a fBlocking is @c false, @a pcbRead is not NULL,
+ * and no data was available. @a *pcbRead will be set to 0.
+ * @retval VINF_EOF when trying to read __beyond__ the end of the stream and
+ * @a pcbRead is not NULL (it will be set to the number of bytes read,
+ * or 0 if the end of the stream was reached before this call).
+ * When the last byte of the read request is the last byte in the
+ * stream, this status code will not be used. However, VINF_EOF is
+ * returned when attempting to read 0 bytes while standing at the end
+ * of the stream.
+ * @retval VERR_EOF when trying to read __beyond__ the end of the stream and
+ * @a pcbRead is NULL.
+ * @retval VERR_ACCESS_DENIED if the stream is not readable.
+ *
+ * @param hVfsIos The VFS I/O stream handle.
+ * @param off Where to read at, -1 for the current position.
+ * @param pSgBuf Pointer to a scatter buffer descriptor. The number
+ * of bytes described by the segments is what will be
+ * attemted read.
+ * @param fBlocking Whether the call is blocking (@c true) or not. If
+ * not, the @a pcbRead parameter must not be NULL.
+ * @param pcbRead Where to always store the number of bytes actually
+ * read. This can be NULL if @a fBlocking is true.
+ * @sa RTFileSgRead, RTSocketSgRead, RTPipeRead, RTPipeReadBlocking
+ */
+RTDECL(int) RTVfsIoStrmSgRead(RTVFSIOSTREAM hVfsIos, RTFOFF off, PCRTSGBUF pSgBuf, bool fBlocking, size_t *pcbRead);
+
+/**
+ * Write bytes to the I/O stream from a gather buffer.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_ACCESS_DENIED if the stream is not writable.
+ *
+ * @param hVfsIos The VFS I/O stream handle.
+ * @param off Where to write at, -1 for the current position.
+ * @param pSgBuf Pointer to a gather buffer descriptor. The number
+ * of bytes described by the segments is what will be
+ * attemted written.
+ * @param fBlocking Whether the call is blocking (@c true) or not. If
+ * not, the @a pcbWritten parameter must not be NULL.
+ * @param pcbWritten Where to always store the number of bytes actually
+ * written. This can be NULL if @a fBlocking is true.
+ * @sa RTFileSgWrite, RTSocketSgWrite
+ */
+RTDECL(int) RTVfsIoStrmSgWrite(RTVFSIOSTREAM hVfsIos, RTFOFF off, PCRTSGBUF pSgBuf, bool fBlocking, size_t *pcbWritten);
+
+/**
+ * Flush any buffered data to the I/O stream.
+ *
+ * @returns IPRT status code.
+ * @param hVfsIos The VFS I/O stream handle.
+ * @sa RTVfsFileFlush, RTFileFlush, RTPipeFlush
+ */
+RTDECL(int) RTVfsIoStrmFlush(RTVFSIOSTREAM hVfsIos);
+
+/**
+ * Poll for events.
+ *
+ * @returns IPRT status code.
+ * @param hVfsIos The VFS I/O stream handle.
+ * @param fEvents The events to poll for (RTPOLL_EVT_XXX).
+ * @param cMillies How long to wait for event to eventuate.
+ * @param fIntr Whether the wait is interruptible and can return
+ * VERR_INTERRUPTED (@c true) or if this condition
+ * should be hidden from the caller (@c false).
+ * @param pfRetEvents Where to return the event mask.
+ * @sa RTVfsFilePoll, RTPollSetAdd, RTPoll, RTPollNoResume.
+ */
+RTDECL(int) RTVfsIoStrmPoll(RTVFSIOSTREAM hVfsIos, uint32_t fEvents, RTMSINTERVAL cMillies, bool fIntr,
+ uint32_t *pfRetEvents);
+/**
+ * Tells the current I/O stream position.
+ *
+ * @returns Zero or higher - where to return the I/O stream offset. Values
+ * below zero are IPRT status codes (VERR_XXX).
+ * @param hVfsIos The VFS I/O stream handle.
+ * @sa RTFileTell
+ */
+RTDECL(RTFOFF) RTVfsIoStrmTell(RTVFSIOSTREAM hVfsIos);
+
+/**
+ * Skips @a cb ahead in the stream.
+ *
+ * @returns IPRT status code.
+ * @param hVfsIos The VFS I/O stream handle.
+ * @param cb The number bytes to skip.
+ */
+RTDECL(int) RTVfsIoStrmSkip(RTVFSIOSTREAM hVfsIos, RTFOFF cb);
+
+/**
+ * Fills the stream with @a cb zeros.
+ *
+ * @returns IPRT status code.
+ * @param hVfsIos The VFS I/O stream handle.
+ * @param cb The number of zero bytes to insert.
+ */
+RTDECL(int) RTVfsIoStrmZeroFill(RTVFSIOSTREAM hVfsIos, RTFOFF cb);
+
+/**
+ * Checks if we're at the end of the I/O stream.
+ *
+ * @returns true if at EOS, otherwise false.
+ * @param hVfsIos The VFS I/O stream handle.
+ */
+RTDECL(bool) RTVfsIoStrmIsAtEnd(RTVFSIOSTREAM hVfsIos);
+
+/**
+ * Get the RTFILE_O_XXX flags for the I/O stream.
+ *
+ * @returns RTFILE_O_XXX, 0 on failure.
+ * @param hVfsIos The VFS I/O stream handle.
+ */
+RTDECL(uint64_t) RTVfsIoStrmGetOpenFlags(RTVFSIOSTREAM hVfsIos);
+
+/**
+ * Process the rest of the stream, checking if it's all valid UTF-8 encoding.
+ *
+ * @returns IPRT status code.
+ *
+ * @param hVfsIos The VFS I/O stream handle.
+ * @param fFlags Flags governing the validation, see
+ * RTVFS_VALIDATE_UTF8_XXX.
+ * @param poffError Where to return the error offset. Optional.
+ */
+RTDECL(int) RTVfsIoStrmValidateUtf8Encoding(RTVFSIOSTREAM hVfsIos, uint32_t fFlags, PRTFOFF poffError);
+
+/** @defgroup RTVFS_VALIDATE_UTF8_XXX RTVfsIoStrmValidateUtf8Encoding flags.
+ * @{ */
+/** The text must not contain any null terminator codepoints. */
+#define RTVFS_VALIDATE_UTF8_NO_NULL RT_BIT_32(0)
+/** The codepoints must be in the range covered by RTC-3629. */
+#define RTVFS_VALIDATE_UTF8_BY_RTC_3629 RT_BIT_32(1)
+/** Mask of valid flags. */
+#define RTVFS_VALIDATE_UTF8_VALID_MASK UINT32_C(0x00000003)
+/** @} */
+
+/**
+ * Printf-like write function.
+ *
+ * @returns Number of characters written on success, negative error status on
+ * failure.
+ * @param hVfsIos The VFS I/O stream handle to write to.
+ * @param pszFormat The format string.
+ * @param ... Format arguments.
+ */
+RTDECL(ssize_t) RTVfsIoStrmPrintf(RTVFSIOSTREAM hVfsIos, const char *pszFormat, ...);
+
+/**
+ * Printf-like write function.
+ *
+ * @returns Number of characters written on success, negative error status on
+ * failure.
+ * @param hVfsIos The VFS I/O stream handle to write to.
+ * @param pszFormat The format string.
+ * @param va Format arguments.
+ */
+RTDECL(ssize_t) RTVfsIoStrmPrintfV(RTVFSIOSTREAM hVfsIos, const char *pszFormat, va_list va);
+
+/**
+ * VFS I/O stream output buffer structure to use with
+ * RTVfsIoStrmStrOutputCallback().
+ */
+typedef struct VFSIOSTRMOUTBUF
+{
+ /** The I/O stream handle. */
+ RTVFSIOSTREAM hVfsIos;
+ /** Size of this structure (for sanity). */
+ size_t cbSelf;
+ /** Status code of the operation. */
+ int rc;
+ /** Current offset into szBuf (number of output bytes pending). */
+ size_t offBuf;
+ /** Modest output buffer. */
+ char szBuf[256];
+} VFSIOSTRMOUTBUF;
+/** Pointer to an VFS I/O stream output buffer for use with
+ * RTVfsIoStrmStrOutputCallback() */
+typedef VFSIOSTRMOUTBUF *PVFSIOSTRMOUTBUF;
+
+/** Initializer for a VFS I/O stream output buffer. */
+#define VFSIOSTRMOUTBUF_INIT(a_pOutBuf, a_hVfsIos) \
+ do { \
+ (a_pOutBuf)->hVfsIos = a_hVfsIos; \
+ (a_pOutBuf)->cbSelf = sizeof(*(a_pOutBuf)); \
+ (a_pOutBuf)->rc = VINF_SUCCESS; \
+ (a_pOutBuf)->offBuf = 0; \
+ (a_pOutBuf)->szBuf[0] = '\0'; \
+ } while (0)
+
+/**
+ * @callback_method_impl{FNRTSTROUTPUT,
+ * For use with VFSIOSTRMOUTBUF.
+ *
+ * Users must use VFSIOSTRMOUTBUF_INIT to initialize a VFSIOSTRMOUTBUF and pass
+ * that as the outputter argument to the function this callback is handed to.}
+ */
+RTDECL(size_t) RTVfsIoStrmStrOutputCallback(void *pvArg, const char *pachChars, size_t cbChars);
+
+/** @} */
+
+
+/** @defgroup grp_rt_vfs_file VFS File API
+ * @{
+ */
+RTDECL(int) RTVfsFileOpen(RTVFS hVfs, const char *pszFilename, uint64_t fOpen, PRTVFSFILE phVfsFile);
+
+/**
+ * Create a VFS file handle from a standard IPRT file handle (RTFILE).
+ *
+ * @returns IPRT status code.
+ * @param hFile The standard IPRT file handle.
+ * @param fOpen The flags the handle was opened with. Pass 0 to
+ * have these detected.
+ * @param fLeaveOpen Whether to leave the handle open when the VFS file
+ * is released, or to close it (@c false).
+ * @param phVfsFile Where to return the VFS file handle.
+ */
+RTDECL(int) RTVfsFileFromRTFile(RTFILE hFile, uint64_t fOpen, bool fLeaveOpen, PRTVFSFILE phVfsFile);
+RTDECL(RTHCUINTPTR) RTVfsFileToNative(RTFILE hVfsFile);
+
+/**
+ * Convenience function combining RTFileOpen with RTVfsFileFromRTFile.
+ *
+ * @returns IPRT status code.
+ * @param pszFilename The path to the file in the normal file system.
+ * @param fOpen The flags to pass to RTFileOpen when opening the
+ * file, i.e. RTFILE_O_XXX.
+ * @param phVfsFile Where to return the VFS file handle.
+ */
+RTDECL(int) RTVfsFileOpenNormal(const char *pszFilename, uint64_t fOpen, PRTVFSFILE phVfsFile);
+
+/**
+ * Convert the VFS file handle to a VFS I/O stream handle.
+ *
+ * @returns The VFS I/O stream handle on success, this must be released.
+ * NIL_RTVFSIOSTREAM if the file handle is invalid.
+ * @param hVfsFile The VFS file handle.
+ * @sa RTVfsIoStrmToFile
+ */
+RTDECL(RTVFSIOSTREAM) RTVfsFileToIoStream(RTVFSFILE hVfsFile);
+
+/**
+ * Retains a reference to the VFS file handle.
+ *
+ * @returns New reference count on success, UINT32_MAX on failure.
+ * @param hVfsFile The VFS file handle.
+ */
+RTDECL(uint32_t) RTVfsFileRetain(RTVFSFILE hVfsFile);
+RTDECL(uint32_t) RTVfsFileRetainDebug(RTVFSFILE hVfsFile, RT_SRC_POS_DECL);
+
+/**
+ * Releases a reference to the VFS file handle.
+ *
+ * @returns New reference count on success (0 if closed), UINT32_MAX on failure.
+ * @param hVfsFile The VFS file handle.
+ */
+RTDECL(uint32_t) RTVfsFileRelease(RTVFSFILE hVfsFile);
+
+/**
+ * Query information about the object.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_NOT_SUPPORTED if the @a enmAddAttr value is not handled by the
+ * implementation.
+ *
+ * @param hVfsFile The VFS file handle.
+ * @param pObjInfo Where to return the info.
+ * @param enmAddAttr Which additional attributes should be retrieved.
+ * @sa RTVfsObjQueryInfo, RTVfsFsStrmQueryInfo, RTVfsDirQueryInfo,
+ * RTVfsIoStrmQueryInfo, RTVfsFileQueryInfo, RTFileQueryInfo,
+ * RTPathQueryInfo.
+ */
+RTDECL(int) RTVfsFileQueryInfo(RTVFSFILE hVfsFile, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr);
+
+/**
+ * Read bytes from the file at the current position.
+ *
+ * @returns IPRT status code.
+ * @retval VINF_SUCCESS and the number of bytes read written to @a pcbRead.
+ * @retval VINF_EOF when trying to read __beyond__ the end of the file and
+ * @a pcbRead is not NULL (it will be set to the number of bytes read,
+ * or 0 if the end of the file was reached before this call).
+ * When the last byte of the read request is the last byte in the
+ * file, this status code will not be used. However, VINF_EOF is
+ * returned when attempting to read 0 bytes while standing at the end
+ * of the file.
+ * @retval VERR_EOF when trying to read __beyond__ the end of the file and
+ * @a pcbRead is NULL.
+ * @retval VERR_ACCESS_DENIED if the file is not readable.
+ *
+ * @param hVfsFile The VFS file handle.
+ * @param pvBuf Where to store the read bytes.
+ * @param cbToRead The number of bytes to read.
+ * @param pcbRead Where to always store the number of bytes actually
+ * read. Optional.
+ * @sa RTVfsIoStrmRead, RTFileRead, RTPipeRead, RTPipeReadBlocking,
+ * RTSocketRead
+ */
+RTDECL(int) RTVfsFileRead(RTVFSFILE hVfsFile, void *pvBuf, size_t cbToRead, size_t *pcbRead);
+RTDECL(int) RTVfsFileReadAt(RTVFSFILE hVfsFile, RTFOFF off, void *pvBuf, size_t cbToRead, size_t *pcbRead);
+
+/**
+ * Write bytes to the file at the current position.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_ACCESS_DENIED if the file is not writable.
+ *
+ * @param hVfsFile The VFS file handle.
+ * @param pvBuf The bytes to write.
+ * @param cbToWrite The number of bytes to write.
+ * @param pcbWritten Where to always store the number of bytes actually
+ * written. This can be NULL.
+ * @sa RTVfsIoStrmRead, RTFileWrite, RTPipeWrite, RTPipeWriteBlocking,
+ * RTSocketWrite
+ */
+RTDECL(int) RTVfsFileWrite(RTVFSFILE hVfsFile, const void *pvBuf, size_t cbToWrite, size_t *pcbWritten);
+RTDECL(int) RTVfsFileWriteAt(RTVFSFILE hVfsFile, RTFOFF off, const void *pvBuf, size_t cbToWrite, size_t *pcbWritten);
+
+
+/**
+ * Reads bytes from the file into a scatter buffer.
+ *
+ * @returns IPRT status code.
+ * @retval VINF_SUCCESS and the number of bytes read written to @a pcbRead.
+ * @retval VINF_TRY_AGAIN if @a fBlocking is @c false, @a pcbRead is not NULL,
+ * and no data was available. @a *pcbRead will be set to 0.
+ * @retval VINF_EOF when trying to read __beyond__ the end of the stream and
+ * @a pcbRead is not NULL (it will be set to the number of bytes read,
+ * or 0 if the end of the stream was reached before this call).
+ * When the last byte of the read request is the last byte in the
+ * stream, this status code will not be used. However, VINF_EOF is
+ * returned when attempting to read 0 bytes while standing at the end
+ * of the stream.
+ * @retval VERR_EOF when trying to read __beyond__ the end of the stream and
+ * @a pcbRead is NULL.
+ * @retval VERR_ACCESS_DENIED if the stream is not readable.
+ *
+ * @param hVfsFile The VFS file handle.
+ * @param off Where to read at, -1 for the current position.
+ * @param pSgBuf Pointer to a scatter buffer descriptor. The number
+ * of bytes described by the segments is what will be
+ * attemted read.
+ * @param fBlocking Whether the call is blocking (@c true) or not. If
+ * not, the @a pcbRead parameter must not be NULL.
+ * @param pcbRead Where to always store the number of bytes actually
+ * read. This can be NULL if @a fBlocking is true.
+ * @sa RTFileSgRead, RTSocketSgRead, RTPipeRead, RTPipeReadBlocking
+ */
+RTDECL(int) RTVfsFileSgRead(RTVFSFILE hVfsFile, RTFOFF off, PCRTSGBUF pSgBuf, bool fBlocking, size_t *pcbRead);
+
+/**
+ * Write bytes to the file from a gather buffer.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_ACCESS_DENIED if the stream is not writable.
+ *
+ * @param hVfsFile The VFS file handle.
+ * @param off Where to write at, -1 for the current position.
+ * @param pSgBuf Pointer to a gather buffer descriptor. The number
+ * of bytes described by the segments is what will be
+ * attemted written.
+ * @param fBlocking Whether the call is blocking (@c true) or not. If
+ * not, the @a pcbWritten parameter must not be NULL.
+ * @param pcbWritten Where to always store the number of bytes actually
+ * written. This can be NULL if @a fBlocking is true.
+ * @sa RTFileSgWrite, RTSocketSgWrite
+ */
+RTDECL(int) RTVfsFileSgWrite(RTVFSFILE hVfsFile, RTFOFF off, PCRTSGBUF pSgBuf, bool fBlocking, size_t *pcbWritten);
+
+/**
+ * Flush any buffered data to the file.
+ *
+ * @returns IPRT status code.
+ * @param hVfsFile The VFS file handle.
+ * @sa RTVfsIoStrmFlush, RTFileFlush, RTPipeFlush
+ */
+RTDECL(int) RTVfsFileFlush(RTVFSFILE hVfsFile);
+
+/**
+ * Poll for events.
+ *
+ * @returns IPRT status code.
+ * @param hVfsFile The VFS file handle.
+ * @param fEvents The events to poll for (RTPOLL_EVT_XXX).
+ * @param cMillies How long to wait for event to eventuate.
+ * @param fIntr Whether the wait is interruptible and can return
+ * VERR_INTERRUPTED (@c true) or if this condition
+ * should be hidden from the caller (@c false).
+ * @param pfRetEvents Where to return the event mask.
+ * @sa RTVfsIoStrmPoll, RTPollSetAdd, RTPoll, RTPollNoResume.
+ */
+RTDECL(RTFOFF) RTVfsFilePoll(RTVFSFILE hVfsFile, uint32_t fEvents, RTMSINTERVAL cMillies, bool fIntr,
+ uint32_t *pfRetEvents);
+
+/**
+ * Tells the current file position.
+ *
+ * @returns Zero or higher - where to return the file offset. Values
+ * below zero are IPRT status codes (VERR_XXX).
+ * @param hVfsFile The VFS file handle.
+ * @sa RTFileTell, RTVfsIoStrmTell.
+ */
+RTDECL(RTFOFF) RTVfsFileTell(RTVFSFILE hVfsFile);
+
+/**
+ * Changes the current read/write position of a file.
+ *
+ * @returns IPRT status code.
+ *
+ * @param hVfsFile The VFS file handle.
+ * @param offSeek The seek offset.
+ * @param uMethod The seek method.
+ * @param poffActual Where to optionally return the new file offset.
+ *
+ * @sa RTFileSeek
+ */
+RTDECL(int) RTVfsFileSeek(RTVFSFILE hVfsFile, RTFOFF offSeek, uint32_t uMethod, uint64_t *poffActual);
+
+/**
+ * Sets the size of a file.
+ *
+ * This may also be used for preallocating space
+ * (RTVFSFILE_SIZE_F_PREALLOC_KEEP_SIZE).
+ *
+ * @returns IPRT status code.
+ * @retval VERR_ACCESS_DENIED if handle isn't writable.
+ * @retval VERR_WRITE_PROTECT if read-only file system.
+ * @retval VERR_FILE_TOO_BIG if cbSize is larger than what the file system can
+ * theoretically deal with.
+ * @retval VERR_DISK_FULL if the file system if full.
+ * @retval VERR_NOT_SUPPORTED if fFlags indicates some operation that's not
+ * supported by the file system / host operating system.
+ *
+ * @param hVfsFile The VFS file handle.
+ * @param cbSize The new file size.
+ * @param fFlags RTVFSFILE_SIZE_F_NORMAL, RTVFSFILE_SIZE_F_GROW, or
+ * RTVFSFILE_SIZE_F_GROW_KEEP_SIZE.
+ *
+ * @sa RTFileSetSize, RTFileSetAllocationSize
+ */
+RTDECL(int) RTVfsFileSetSize(RTVFSFILE hVfsFile, uint64_t cbSize, uint32_t fFlags);
+
+/** @name RTVFSFILE_SIZE_F_XXX - RTVfsFileSetSize flags.
+ * @{ */
+/** Normal truncate or grow (zero'ed) like RTFileSetSize . */
+#define RTVFSFILE_SIZE_F_NORMAL UINT32_C(0x00000001)
+/** Only grow the file, ignore call if cbSize would truncate the file.
+ * This is what RTFileSetAllocationSize does by default. */
+#define RTVFSFILE_SIZE_F_GROW UINT32_C(0x00000002)
+/** Only grow the file, ignore call if cbSize would truncate the file.
+ * This is what RTFileSetAllocationSize does by default. */
+#define RTVFSFILE_SIZE_F_GROW_KEEP_SIZE UINT32_C(0x00000003)
+/** Action mask. */
+#define RTVFSFILE_SIZE_F_ACTION_MASK UINT32_C(0x00000003)
+/** Validate the flags.
+ * Will reference @a a_fFlags more than once. */
+#define RTVFSFILE_SIZE_F_IS_VALID(a_fFlags) \
+ ( !((a_fFlags) & ~RTVFSFILE_SIZE_F_ACTION_MASK) && ((a_fFlags) & RTVFSFILE_SIZE_F_ACTION_MASK) != 0 )
+/** Mask of valid flags. */
+#define RTFILE_ALLOC_SIZE_F_VALID (RTFILE_ALLOC_SIZE_F_KEEP_SIZE)
+/** @} */
+
+
+RTDECL(int) RTVfsFileQuerySize(RTVFSFILE hVfsFile, uint64_t *pcbSize);
+RTDECL(RTFOFF) RTVfsFileGetMaxSize(RTVFSFILE hVfsFile);
+RTDECL(int) RTVfsFileQueryMaxSize(RTVFSFILE hVfsFile, uint64_t *pcbMax);
+
+/**
+ * Get the RTFILE_O_XXX flags for the I/O stream.
+ *
+ * @returns RTFILE_O_XXX, 0 on failure.
+ * @param hVfsFile The VFS file handle.
+ */
+RTDECL(uint64_t) RTVfsFileGetOpenFlags(RTVFSFILE hVfsFile);
+
+/**
+ * Printf-like write function.
+ *
+ * @returns Number of characters written on success, negative error status on
+ * failure.
+ * @param hVfsFile The VFS file handle to write to.
+ * @param pszFormat The format string.
+ * @param ... Format arguments.
+ */
+RTDECL(ssize_t) RTVfsFilePrintf(RTVFSFILE hVfsFile, const char *pszFormat, ...);
+
+/**
+ * Printf-like write function.
+ *
+ * @returns Number of characters written on success, negative error status on
+ * failure.
+ * @param hVfsFile The VFS file handle to write to.
+ * @param pszFormat The format string.
+ * @param va Format arguments.
+ */
+RTDECL(ssize_t) RTVfsFilePrintfV(RTVFSFILE hVfsFile, const char *pszFormat, va_list va);
+
+/** @} */
+
+
+#ifdef DEBUG
+# undef RTVfsRetain
+# define RTVfsRetain(hVfs) RTVfsRetainDebug(hVfs, RT_SRC_POS)
+# undef RTVfsObjRetain
+# define RTVfsObjRetain(hVfsObj) RTVfsObjRetainDebug(hVfsObj, RT_SRC_POS)
+# undef RTVfsDirRetain
+# define RTVfsDirRetain(hVfsDir) RTVfsDirRetainDebug(hVfsDir, RT_SRC_POS)
+# undef RTVfsFileRetain
+# define RTVfsFileRetain(hVfsFile) RTVfsFileRetainDebug(hVfsFile, RT_SRC_POS)
+# undef RTVfsIoStrmRetain
+# define RTVfsIoStrmRetain(hVfsIos) RTVfsIoStrmRetainDebug(hVfsIos, RT_SRC_POS)
+# undef RTVfsFsStrmRetain
+# define RTVfsFsStrmRetain(hVfsFss) RTVfsFsStrmRetainDebug(hVfsFss, RT_SRC_POS)
+#endif
+
+
+
+/** @defgroup grp_rt_vfs_misc VFS Miscellaneous
+ * @{
+ */
+
+/**
+ * Memorizes the I/O stream as a file backed by memory.
+ *
+ * @returns IPRT status code.
+ *
+ * @param hVfsIos The VFS I/O stream to memorize. This will be read
+ * to the end on success, on failure its position is
+ * undefined.
+ * @param fFlags A combination of RTFILE_O_READ and RTFILE_O_WRITE.
+ * @param phVfsFile Where to return the handle to the memory file on
+ * success.
+ */
+RTDECL(int) RTVfsMemorizeIoStreamAsFile(RTVFSIOSTREAM hVfsIos, uint32_t fFlags, PRTVFSFILE phVfsFile);
+
+/**
+ * Creates a VFS file from a memory buffer.
+ *
+ * @returns IPRT status code.
+ *
+ * @param fFlags A combination of RTFILE_O_READ and RTFILE_O_WRITE.
+ * @param pvBuf The buffer. This will be copied and not referenced
+ * after this function returns.
+ * @param cbBuf The buffer size.
+ * @param phVfsFile Where to return the handle to the memory file on
+ * success.
+ */
+RTDECL(int) RTVfsFileFromBuffer(uint32_t fFlags, void const *pvBuf, size_t cbBuf, PRTVFSFILE phVfsFile);
+
+/**
+ * Creates a memory backed VFS file object for read and write.
+ *
+ * @returns IPRT status code.
+ *
+ * @param hVfsIos The VFS I/O stream to memorize. This will be read
+ * to the end on success, on failure its position is
+ * undefined.
+ * @param cbEstimate The estimated file size.
+ * @param phVfsFile Where to return the handle to the memory file on
+ * success.
+ * @sa RTVfsMemIoStrmCreate
+ */
+RTDECL(int) RTVfsMemFileCreate(RTVFSIOSTREAM hVfsIos, size_t cbEstimate, PRTVFSFILE phVfsFile);
+
+/**
+ * Creates a memory backed VFS file object for read and write.
+ *
+ * @returns IPRT status code.
+ *
+ * @param hVfsIos The VFS I/O stream to memorize. This will be read
+ * to the end on success, on failure its position is
+ * undefined.
+ * @param cbEstimate The estimated file size.
+ * @param phVfsIos Where to return the handle to the memory I/O stream
+ * on success.
+ * @sa RTVfsMemFileCreate
+ */
+RTDECL(int) RTVfsMemIoStrmCreate(RTVFSIOSTREAM hVfsIos, size_t cbEstimate, PRTVFSIOSTREAM phVfsIos);
+
+/**
+ * Pumps data from one I/O stream to another.
+ *
+ * The data is read in chunks from @a hVfsIosSrc and written to @a hVfsIosDst
+ * until @a hVfsIosSrc indicates end of stream.
+ *
+ * @returns IPRT status code
+ *
+ * @param hVfsIosSrc The input stream.
+ * @param hVfsIosDst The output stream.
+ * @param cbBufHint Hints at a good temporary buffer size, pass 0 if
+ * clueless.
+ */
+RTDECL(int) RTVfsUtilPumpIoStreams(RTVFSIOSTREAM hVfsIosSrc, RTVFSIOSTREAM hVfsIosDst, size_t cbBufHint);
+
+
+/**
+ * Creates a progress wrapper for an I/O stream.
+ *
+ * @returns IRPT status code.
+ * @param hVfsIos The I/O stream to wrap.
+ * @param pfnProgress The progress callback. The return code is
+ * ignored by default, see
+ * RTVFSPROGRESS_F_CANCELABLE.
+ * @param pvUser The user argument to @a pfnProgress.
+ * @param fFlags RTVFSPROGRESS_F_XXX
+ * @param cbExpectedRead The expected number of bytes read.
+ * @param cbExpectedWritten The execpted number of bytes written.
+ * @param phVfsIos Where to return the I/O stream handle.
+ */
+RTDECL(int) RTVfsCreateProgressForIoStream(RTVFSIOSTREAM hVfsIos, PFNRTPROGRESS pfnProgress, void *pvUser, uint32_t fFlags,
+ uint64_t cbExpectedRead, uint64_t cbExpectedWritten, PRTVFSIOSTREAM phVfsIos);
+
+/**
+ * Creates a progress wrapper for a file stream.
+ *
+ * @returns IRPT status code.
+ * @param hVfsFile The file to wrap.
+ * @param pfnProgress The progress callback. The return code is
+ * ignored by default, see
+ * RTVFSPROGRESS_F_CANCELABLE.
+ * @param pvUser The user argument to @a pfnProgress.
+ * @param fFlags RTVFSPROGRESS_F_XXX
+ * @param cbExpectedRead The expected number of bytes read.
+ * @param cbExpectedWritten The execpted number of bytes written.
+ * @param phVfsFile Where to return the file handle.
+ */
+RTDECL(int) RTVfsCreateProgressForFile(RTVFSFILE hVfsFile, PFNRTPROGRESS pfnProgress, void *pvUser, uint32_t fFlags,
+ uint64_t cbExpectedRead, uint64_t cbExpectedWritten, PRTVFSFILE phVfsFile);
+
+/** @name RTVFSPROGRESS_F_XXX - Flags for RTVfsCreateProcessForIoStream and
+ * RTVfsCreateProcessForFile.
+ * @{ */
+/** Cancel if the callback returns a failure status code.
+ * This isn't default behavior because the cancelation is delayed one I/O
+ * operation in most cases and it's uncertain how the VFS user will handle the
+ * cancellation status code. */
+#define RTVFSPROGRESS_F_CANCELABLE RT_BIT_32(0)
+/** Account forward seeks as reads. */
+#define RTVFSPROGRESS_F_FORWARD_SEEK_AS_READ RT_BIT_32(1)
+/** Account fprward seeks as writes. */
+#define RTVFSPROGRESS_F_FORWARD_SEEK_AS_WRITE RT_BIT_32(2)
+/** Valid bits. */
+#define RTVFSPROGRESS_F_VALID_MASK UINT32_C(0x00000007)
+/** @} */
+
+
+/**
+ * Create an I/O stream instance performing simple sequential read-ahead.
+ *
+ * @returns IPRT status code.
+ * @param hVfsIos The input stream to perform read ahead on. If this is
+ * actually for a file object, the returned I/O stream
+ * handle can also be cast to a file handle.
+ * @param fFlags Flags reserved for future use, MBZ.
+ * @param cBuffers How many read ahead buffers to use. Specify 0 for
+ * default value.
+ * @param cbBuffer The size of each read ahead buffer. Specify 0 for
+ * default value.
+ * @param phVfsIos Where to return the read ahead I/O stream handle.
+ *
+ * @remarks Careful using this on a message pipe or socket. The reads are
+ * performed in blocked mode and it may be host and/or implementation
+ * dependent whether they will return ready data immediate or wait
+ * until there's a whole @a cbBuffer (or default) worth ready.
+ *
+ * @sa RTVfsCreateReadAheadForFile
+ */
+RTDECL(int) RTVfsCreateReadAheadForIoStream(RTVFSIOSTREAM hVfsIos, uint32_t fFlags, uint32_t cBuffers, uint32_t cbBuffer,
+ PRTVFSIOSTREAM phVfsIos);
+
+/**
+ * Create an I/O stream instance performing simple sequential read-ahead.
+ *
+ * @returns IPRT status code.
+ * @param hVfsFile The input file to perform read ahead on.
+ * @param fFlags Flags reserved for future use, MBZ.
+ * @param cBuffers How many read ahead buffers to use. Specify 0 for
+ * default value.
+ * @param cbBuffer The size of each read ahead buffer. Specify 0 for
+ * default value.
+ * @param phVfsFile Where to return the read ahead file handle.
+ * @sa RTVfsCreateReadAheadForIoStream
+ */
+RTDECL(int) RTVfsCreateReadAheadForFile(RTVFSFILE hVfsFile, uint32_t fFlags, uint32_t cBuffers, uint32_t cbBuffer,
+ PRTVFSFILE phVfsFile);
+
+
+/**
+ * Create a file system stream for writing to a directory.
+ *
+ * This is just supposed to be a drop in replacement for the TAR creator stream
+ * that instead puts the files and stuff in a directory instead of a TAR
+ * archive. In addition, it has an undo feature for simplying cleaning up after
+ * a botched run
+ *
+ * @returns IPRT status code.
+ * @param hVfsBaseDir The base directory.
+ * @param fFlags RTVFSFSS2DIR_F_XXX
+ * @param phVfsFss Where to return the FSS handle.
+ * @sa RTVfsFsStrmToNormalDir, RTVfsFsStrmToDirUndo
+ */
+RTDECL(int) RTVfsFsStrmToDir(RTVFSDIR hVfsBaseDir, uint32_t fFlags, PRTVFSFSSTREAM phVfsFss);
+
+/**
+ * Create a file system stream for writing to a normal directory.
+ *
+ * This is just supposed to be a drop in replacement for the TAR creator stream
+ * that instead puts the files and stuff in a directory instead of a TAR
+ * archive. In addition, it has an undo feature for simplying cleaning up after
+ * a botched run
+ *
+ * @returns IPRT status code.
+ * @param pszBaseDir The base directory. Must exist.
+ * @param fFlags RTVFSFSS2DIR_F_XXX
+ * @param phVfsFss Where to return the FSS handle.
+ * @sa RTVfsFsStrmToDir, RTVfsFsStrmToDirUndo
+ */
+RTDECL(int) RTVfsFsStrmToNormalDir(const char *pszBaseDir, uint32_t fFlags, PRTVFSFSSTREAM phVfsFss);
+
+/** @name RTVFSFSS2DIR_F_XXX - Flags for RTVfsFsStrmToNormalDir
+ * @{ */
+/** Overwrite existing files (default is to not overwrite anything). */
+#define RTVFSFSS2DIR_F_OVERWRITE_FILES RT_BIT_32(0)
+/** Valid bits. */
+#define RTVFSFSS2DIR_F_VALID_MASK UINT32_C(0x00000001)
+/** @} */
+
+/**
+ * Deletes files, directories, symlinks and stuff created by a FSS returned by
+ * RTVfsFsStrmToNormalDir or RTVfsFsStrmToDir.
+ *
+ * @returns IPRT status code.
+ * @param hVfsFss The write-to-directory FSS handle.
+ */
+RTDECL(int) RTVfsFsStrmToDirUndo(RTVFSFSSTREAM hVfsFss);
+
+
+
+/** @} */
+
+
+/** @defgroup grp_rt_vfs_chain VFS Chains
+ *
+ * VFS chains is for doing pipe like things with VFS objects from the command
+ * line. Imagine you want to cat the readme.gz of an ISO you could do
+ * something like:
+ * RTCat :iprtvfs:file(stdfile,live.iso)|vfs(isofs)|iso(open,readme.gz)|ios(gunzip)
+ * or
+ * RTCat :iprtvfs:file(stdfile,live.iso)|ios(isofs,readme.gz)|ios(gunzip)
+ *
+ * Or say you want to read the README.TXT on a floppy image:
+ * RTCat :iprtvfs:file(stdfile,floppy.img,r)|vfs(fat)|ios(open,README.TXT)
+ * or
+ * RTCat :iprtvfs:file(stdfile,floppy.img,r)|vfs(fat)|README.TXT
+ *
+ * Or in the other direction, you want to write a STUFF.TGZ file to the above
+ * floppy image, using a lazy writer thread for compressing the data:
+ * RTTar cf :iprtvfs:file(stdfile,floppy.img,rw)|ios(fat,STUFF.TGZ)|ios(gzip)|ios(push) .
+ *
+ *
+ * A bit more formally:
+ * :iprtvfs:{type}({provider}[,provider-args])[{separator}{type}...][{separator}{path}]
+ *
+ * The @c type refers to VFS object that should be created by the @c provider.
+ * Valid types:
+ * - vfs: A virtual file system (volume).
+ * - fss: A file system stream (e.g. tar).
+ * - ios: An I/O stream.
+ * - file: A file.
+ * - dir: A directory.
+ * - sym: A symbolic link (not sure how useful this is).
+ *
+ * The @c provider refers to registered chain element providers (see
+ * RTVFSCHAINELEMENTREG for how that works internally). These are asked to
+ * create a VFS object of the specified type using the given arguments (if any).
+ * Default providers:
+ * - std: Standard file, directory and file system.
+ * - open: Opens a file, I/O stream or directory in a vfs or directory object.
+ * - pull: Read-ahead buffering thread on file or I/O stream.
+ * - push: Lazy-writer buffering thread on file or I/O stream.
+ * - gzip: Compresses an I/O stream.
+ * - gunzip: Decompresses an I/O stream.
+ * - fat: FAT file system accessor.
+ * - isofs: ISOFS file system accessor.
+ *
+ * As element @c separator we allow both colon (':') and the pipe character
+ * ('|'). The latter the conventional one, but since it's inconvenient on the
+ * command line, colon is provided as an alternative.
+ *
+ * In the final element we allow a simple @a path to be specified instead of the
+ * type-provider-arguments stuff. The previous object must be a directory, file
+ * system or file system stream. The application will determin exactly which
+ * operation or operations which will be performed.
+ *
+ * @{
+ */
+
+/** The path prefix used to identify an VFS chain specification. */
+#define RTVFSCHAIN_SPEC_PREFIX ":iprtvfs:"
+
+RTDECL(int) RTVfsChainOpenVfs(const char *pszSpec, PRTVFS phVfs, uint32_t *poffError, PRTERRINFO pErrInfo);
+RTDECL(int) RTVfsChainOpenFsStream(const char *pszSpec, PRTVFSFSSTREAM phVfsFss, uint32_t *poffError, PRTERRINFO pErrInfo);
+
+/**
+ * Opens any kind of file system object.
+ *
+ * @returns IPRT status code.
+ * @param pszSpec The VFS chain specification or plain path.
+ * @param fFileOpen RTFILE_O_XXX flags.
+ * @param fObjFlags More flags: RTVFSOBJ_F_XXX, RTPATH_F_XXX.
+ * @param phVfsObj Where to return the handle to the opened object.
+ * @param poffError Where to on error return an offset into @a pszSpec
+ * of what cause the error. Optional.
+ * @param pErrInfo Where to return additional error information.
+ * Optional.
+ */
+RTDECL(int) RTVfsChainOpenObj(const char *pszSpec, uint64_t fFileOpen, uint32_t fObjFlags,
+ PRTVFSOBJ phVfsObj, uint32_t *poffError, PRTERRINFO pErrInfo);
+
+RTDECL(int) RTVfsChainOpenDir(const char *pszSpec, uint32_t fOpen, PRTVFSDIR phVfsDir, uint32_t *poffError, PRTERRINFO pErrInfo);
+RTDECL(int) RTVfsChainOpenParentDir(const char *pszSpec, uint32_t fOpen, PRTVFSDIR phVfsDir, const char **ppszChild,
+ uint32_t *poffError, PRTERRINFO pErrInfo);
+RTDECL(int) RTVfsChainOpenFile(const char *pszSpec, uint64_t fOpen, PRTVFSFILE phVfsFile, uint32_t *poffError, PRTERRINFO pErrInfo);
+RTDECL(int) RTVfsChainOpenIoStream(const char *pszSpec, uint64_t fOpen, PRTVFSIOSTREAM phVfsIos, uint32_t *poffError, PRTERRINFO pErrInfo);
+RTDECL(int) RTVfsChainOpenSymlink(const char *pszSpec, PRTVFSSYMLINK phVfsSym, uint32_t *poffError, PRTERRINFO pErrInfo);
+
+RTDECL(int) RTVfsChainQueryInfo(const char *pszSpec, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAdditionalAttribs,
+ uint32_t fFlags, uint32_t *poffError, PRTERRINFO pErrInfo);
+
+/**
+ * Tests if the given string is a chain specification or not.
+ *
+ * @returns true if it is, false if it isn't.
+ * @param pszSpec The alleged chain spec.
+ */
+RTDECL(bool) RTVfsChainIsSpec(const char *pszSpec);
+
+/**
+ * Queries the path from the final element.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_VFS_CHAIN_NOT_PATH_ONLY if the final element isn't just a
+ * simple path.
+ * @param pszSpec The chain spec.
+ * @param ppszFinalPath Where to return a copy of the final path on success.
+ * Call RTStrFree when done.
+ * @param poffError Where to on error return an offset into @a pszSpec
+ * of what cause the error. Optional.
+ *
+ */
+RTDECL(int) RTVfsChainQueryFinalPath(const char *pszSpec, char **ppszFinalPath, uint32_t *poffError);
+
+/**
+ * Splits the given chain spec into a final path and the preceeding spec.
+ *
+ * This works on plain paths too.
+ *
+ * @returns IPRT status code.
+ * @param pszSpec The chain spec to split. This will be modified!
+ * @param ppszSpec Where to return the pointer to the chain spec part.
+ * This is set to NULL if it's a plain path or a chain
+ * spec with only a final-path element.
+ * @param ppszFinalPath Where to return the pointer to the final path. This
+ * is set to NULL if no final path.
+ * @param poffError Where to on error return an offset into @a pszSpec
+ * of what cause the error. Optional.
+ */
+RTDECL(int) RTVfsChainSplitOffFinalPath(char *pszSpec, char **ppszSpec, char **ppszFinalPath, uint32_t *poffError);
+
+/**
+ * Common code for reporting errors of a RTVfsChainOpen* API.
+ *
+ * @param pszFunction The API called.
+ * @param pszSpec The VFS chain specification or file path passed to the.
+ * @param rc The return code.
+ * @param offError The error offset value returned (0 if not captured).
+ * @param pErrInfo Additional error information. Optional.
+ *
+ * @sa RTVfsChainMsgErrorExitFailure
+ * @sa RTVfsChainOpenVfs, RTVfsChainOpenFsStream, RTVfsChainOpenDir,
+ * RTVfsChainOpenFile, RTVfsChainOpenIoStream, RTVfsChainOpenSymlink
+ */
+RTDECL(void) RTVfsChainMsgError(const char *pszFunction, const char *pszSpec, int rc, uint32_t offError, PRTERRINFO pErrInfo);
+
+/**
+ * Common code for reporting errors of a RTVfsChainOpen* API.
+ *
+ * @returns RTEXITCODE_FAILURE
+ *
+ * @param pszFunction The API called.
+ * @param pszSpec The VFS chain specification or file path passed to the.
+ * @param rc The return code.
+ * @param offError The error offset value returned (0 if not captured).
+ * @param pErrInfo Additional error information. Optional.
+ *
+ * @sa RTVfsChainMsgError
+ * @sa RTVfsChainOpenVfs, RTVfsChainOpenFsStream, RTVfsChainOpenDir,
+ * RTVfsChainOpenFile, RTVfsChainOpenIoStream, RTVfsChainOpenSymlink
+ */
+RTDECL(RTEXITCODE) RTVfsChainMsgErrorExitFailure(const char *pszFunction, const char *pszSpec,
+ int rc, uint32_t offError, PRTERRINFO pErrInfo);
+
+
+/** @} */
+
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_vfs_h */
+
diff --git a/include/iprt/vfslowlevel.h b/include/iprt/vfslowlevel.h
new file mode 100644
index 00000000..aba442ca
--- /dev/null
+++ b/include/iprt/vfslowlevel.h
@@ -0,0 +1,1588 @@
+/** @file
+ * IPRT - Virtual Filesystem.
+ */
+
+/*
+ * Copyright (C) 2010-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_vfslowlevel_h
+#define IPRT_INCLUDED_vfslowlevel_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/vfs.h>
+#include <iprt/errcore.h>
+#include <iprt/list.h>
+#include <iprt/param.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_vfs_lowlevel RTVfs - Low-level Interface.
+ * @ingroup grp_rt_vfs
+ * @{
+ */
+
+
+/** @name VFS Lock Abstraction
+ * @todo This should be moved somewhere else as it is of general use.
+ * @{ */
+
+/**
+ * VFS lock types.
+ */
+typedef enum RTVFSLOCKTYPE
+{
+ /** Invalid lock type. */
+ RTVFSLOCKTYPE_INVALID = 0,
+ /** Read write semaphore. */
+ RTVFSLOCKTYPE_RW,
+ /** Fast mutex semaphore (critical section in ring-3). */
+ RTVFSLOCKTYPE_FASTMUTEX,
+ /** Full fledged mutex semaphore. */
+ RTVFSLOCKTYPE_MUTEX,
+ /** The end of valid lock types. */
+ RTVFSLOCKTYPE_END,
+ /** The customary 32-bit type hack. */
+ RTVFSLOCKTYPE_32BIT_HACK = 0x7fffffff
+} RTVFSLOCKTYPE;
+
+/** VFS lock handle. */
+typedef struct RTVFSLOCKINTERNAL *RTVFSLOCK;
+/** Pointer to a VFS lock handle. */
+typedef RTVFSLOCK *PRTVFSLOCK;
+/** Nil VFS lock handle. */
+#define NIL_RTVFSLOCK ((RTVFSLOCK)~(uintptr_t)0)
+
+/** Special handle value for creating a new read/write semaphore based lock. */
+#define RTVFSLOCK_CREATE_RW ((RTVFSLOCK)~(uintptr_t)1)
+/** Special handle value for creating a new fast mutex semaphore based lock. */
+#define RTVFSLOCK_CREATE_FASTMUTEX ((RTVFSLOCK)~(uintptr_t)2)
+/** Special handle value for creating a new mutex semaphore based lock. */
+#define RTVFSLOCK_CREATE_MUTEX ((RTVFSLOCK)~(uintptr_t)3)
+
+/**
+ * Retains a reference to the VFS lock handle.
+ *
+ * @returns New reference count on success, UINT32_MAX on failure.
+ * @param hLock The VFS lock handle.
+ */
+RTDECL(uint32_t) RTVfsLockRetain(RTVFSLOCK hLock);
+
+/**
+ * Releases a reference to the VFS lock handle.
+ *
+ * @returns New reference count on success (0 if closed), UINT32_MAX on failure.
+ * @param hLock The VFS lock handle.
+ */
+RTDECL(uint32_t) RTVfsLockRelease(RTVFSLOCK hLock);
+
+/**
+ * Gets the lock type.
+ *
+ * @returns The lock type on success, RTVFSLOCKTYPE_INVALID if the handle is
+ * not valid.
+ * @param hLock The lock handle.
+ */
+RTDECL(RTVFSLOCKTYPE) RTVfsLockGetType(RTVFSLOCK hLock);
+
+
+
+RTDECL(void) RTVfsLockAcquireReadSlow(RTVFSLOCK hLock);
+RTDECL(void) RTVfsLockReleaseReadSlow(RTVFSLOCK hLock);
+RTDECL(void) RTVfsLockAcquireWriteSlow(RTVFSLOCK hLock);
+RTDECL(void) RTVfsLockReleaseWriteSlow(RTVFSLOCK hLock);
+
+/**
+ * Acquire a read lock.
+ *
+ * @param hLock The lock handle, can be NIL.
+ */
+DECLINLINE(void) RTVfsLockAcquireRead(RTVFSLOCK hLock)
+{
+ if (hLock != NIL_RTVFSLOCK)
+ RTVfsLockAcquireReadSlow(hLock);
+}
+
+
+/**
+ * Release a read lock.
+ *
+ * @param hLock The lock handle, can be NIL.
+ */
+DECLINLINE(void) RTVfsLockReleaseRead(RTVFSLOCK hLock)
+{
+ if (hLock != NIL_RTVFSLOCK)
+ RTVfsLockReleaseReadSlow(hLock);
+}
+
+
+/**
+ * Acquire a write lock.
+ *
+ * @param hLock The lock handle, can be NIL.
+ */
+DECLINLINE(void) RTVfsLockAcquireWrite(RTVFSLOCK hLock)
+{
+ if (hLock != NIL_RTVFSLOCK)
+ RTVfsLockAcquireWriteSlow(hLock);
+}
+
+
+/**
+ * Release a write lock.
+ *
+ * @param hLock The lock handle, can be NIL.
+ */
+DECLINLINE(void) RTVfsLockReleaseWrite(RTVFSLOCK hLock)
+{
+ if (hLock != NIL_RTVFSLOCK)
+ RTVfsLockReleaseWriteSlow(hLock);
+}
+
+/** @} */
+
+/**
+ * Info queried via RTVFSOBJOPS::pfnQueryInfoEx, ++.
+ */
+typedef enum RTVFSQIEX
+{
+ /** Invalid zero value. */
+ RTVFSQIEX_INVALID = 0,
+ /** Volume label.
+ * Returns a UTF-8 string. */
+ RTVFSQIEX_VOL_LABEL,
+ /** Alternative volume label, the primary one for ISOs, otherwise treated same
+ * as RTVFSQIEX_VOL_LABEL. */
+ RTVFSQIEX_VOL_LABEL_ALT,
+ /** Volume serial number.
+ * Returns a uint32_t, uint64_t or RTUUID. */
+ RTVFSQIEX_VOL_SERIAL,
+ /** End of valid queries. */
+ RTVFSQIEX_END,
+
+ /** The usual 32-bit hack. */
+ RTVFSQIEX_32BIT_SIZE_HACK = 0x7fffffff
+} RTVFSQIEX;
+
+
+/**
+ * The basis for all virtual file system objects.
+ */
+typedef struct RTVFSOBJOPS
+{
+ /** The structure version (RTVFSOBJOPS_VERSION). */
+ uint32_t uVersion;
+ /** The object type for type introspection. */
+ RTVFSOBJTYPE enmType;
+ /** The name of the operations. */
+ const char *pszName;
+
+ /**
+ * Close the object.
+ *
+ * @returns IPRT status code.
+ * @param pvThis The implementation specific file data.
+ */
+ DECLCALLBACKMEMBER(int, pfnClose,(void *pvThis));
+
+ /**
+ * Get information about the file.
+ *
+ * @returns IPRT status code. See RTVfsObjQueryInfo.
+ * @retval VERR_WRONG_TYPE if file system or file system stream.
+ *
+ * @param pvThis The implementation specific file data.
+ * @param pObjInfo Where to return the object info on success.
+ * @param enmAddAttr Which set of additional attributes to request.
+ * @sa RTVfsObjQueryInfo, RTFileQueryInfo, RTPathQueryInfo
+ */
+ DECLCALLBACKMEMBER(int, pfnQueryInfo,(void *pvThis, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr));
+
+ /**
+ * Query arbritray information about the file, volume, or whatever.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_BUFFER_OVERFLOW sets pcbRet.
+ *
+ * @param pvThis The implementation specific file data.
+ * @param enmInfo The information being queried.
+ * @param pvInfo Where to return the info.
+ * @param cbInfo The size of the @a pvInfo buffer.
+ * @param pcbRet The size of the returned data. In case of
+ * VERR_BUFFER_OVERFLOW this will be set to the required
+ * buffer size.
+ */
+ DECLCALLBACKMEMBER(int, pfnQueryInfoEx,(void *pvThis, RTVFSQIEX enmInfo, void *pvInfo, size_t cbInfo, size_t *pcbRet));
+
+ /** Marks the end of the structure (RTVFSOBJOPS_VERSION). */
+ uintptr_t uEndMarker;
+} RTVFSOBJOPS;
+/** Pointer to constant VFS object operations. */
+typedef RTVFSOBJOPS const *PCRTVFSOBJOPS;
+
+/** The RTVFSOBJOPS structure version. */
+#define RTVFSOBJOPS_VERSION RT_MAKE_U32_FROM_U8(0xff,0x1f,2,0)
+
+
+/**
+ * The VFS operations.
+ */
+typedef struct RTVFSOPS
+{
+ /** The basic object operation. */
+ RTVFSOBJOPS Obj;
+ /** The structure version (RTVFSOPS_VERSION). */
+ uint32_t uVersion;
+ /** The virtual file system feature mask. */
+ uint32_t fFeatures;
+
+ /**
+ * Opens the root directory.
+ *
+ * @returns IPRT status code.
+ * @param pvThis The implementation specific data.
+ * @param phVfsDir Where to return the handle to the root directory.
+ */
+ DECLCALLBACKMEMBER(int, pfnOpenRoot,(void *pvThis, PRTVFSDIR phVfsDir));
+
+ /**
+ * Query the status of the given storage range (optional).
+ *
+ * This can be used by the image compaction utilites to evict non-zero blocks
+ * that aren't currently being used by the file system.
+ *
+ * @returns IPRT status code.
+ * @param pvThis The implementation specific data.
+ * @param off Start offset to check.
+ * @param cb Number of bytes to check.
+ * @param pfUsed Where to store whether the given range is in use.
+ */
+ DECLCALLBACKMEMBER(int, pfnQueryRangeState,(void *pvThis, uint64_t off, size_t cb, bool *pfUsed));
+
+ /** @todo There will be more methods here to optimize opening and
+ * querying. */
+
+#if 0
+ /**
+ * Optional entry point for optimizing path traversal within the file system.
+ *
+ * @returns IPRT status code.
+ * @param pvThis The implementation specific data.
+ * @param pszPath The path to resolve.
+ * @param poffPath The current path offset on input, what we've
+ * traversed to on successful return.
+ * @param phVfs??? Return handle to what we've traversed.
+ * @param p??? Return other stuff...
+ */
+ DECLCALLBACKMEMBER(int, pfnTraverse,(void *pvThis, const char *pszPath, size_t *poffPath, PRTVFS??? phVfs?, ???* p???));
+#endif
+
+ /** @todo need rename API */
+
+ /** Marks the end of the structure (RTVFSOPS_VERSION). */
+ uintptr_t uEndMarker;
+} RTVFSOPS;
+/** Pointer to constant VFS operations. */
+typedef RTVFSOPS const *PCRTVFSOPS;
+
+/** The RTVFSOPS structure version. */
+#define RTVFSOPS_VERSION RT_MAKE_U32_FROM_U8(0xff,0x0f,1,0)
+
+/** @name RTVFSOPS::fFeatures
+ * @{ */
+/** The VFS supports attaching other systems. */
+#define RTVFSOPS_FEAT_ATTACH RT_BIT_32(0)
+/** @} */
+
+/**
+ * Creates a new VFS handle.
+ *
+ * @returns IPRT status code
+ * @param pVfsOps The VFS operations.
+ * @param cbInstance The size of the instance data.
+ * @param hVfs The VFS handle to associate this VFS with.
+ * NIL_VFS is ok.
+ * @param hLock Handle to a custom lock to be used with the new
+ * object. The reference is consumed. NIL and
+ * special lock handles are fine.
+ * @param phVfs Where to return the new handle.
+ * @param ppvInstance Where to return the pointer to the instance data
+ * (size is @a cbInstance).
+ */
+RTDECL(int) RTVfsNew(PCRTVFSOPS pVfsOps, size_t cbInstance, RTVFS hVfs, RTVFSLOCK hLock,
+ PRTVFS phVfs, void **ppvInstance);
+
+
+/**
+ * Creates a new VFS base object handle.
+ *
+ * @returns IPRT status code
+ * @param pObjOps The base object operations.
+ * @param cbInstance The size of the instance data.
+ * @param hVfs The VFS handle to associate this base object
+ * with. NIL_VFS is ok.
+ * @param hLock Handle to a custom lock to be used with the new
+ * object. The reference is consumed. NIL and
+ * special lock handles are fine.
+ * @param phVfsObj Where to return the new handle.
+ * @param ppvInstance Where to return the pointer to the instance data
+ * (size is @a cbInstance).
+ */
+RTDECL(int) RTVfsNewBaseObj(PCRTVFSOBJOPS pObjOps, size_t cbInstance, RTVFS hVfs, RTVFSLOCK hLock,
+ PRTVFSOBJ phVfsObj, void **ppvInstance);
+
+
+/**
+ * Gets the private data of a base object.
+ *
+ * @returns Pointer to the private data. NULL if the handle is invalid in some
+ * way.
+ * @param hVfsObj The I/O base object handle.
+ * @param pObjOps The base object operations. This servers as a
+ * sort of password.
+ */
+RTDECL(void *) RTVfsObjToPrivate(RTVFSOBJ hVfsObj, PCRTVFSOBJOPS pObjOps);
+
+/**
+ * Additional operations for setting object attributes.
+ */
+typedef struct RTVFSOBJSETOPS
+{
+ /** The structure version (RTVFSOBJSETOPS_VERSION). */
+ uint32_t uVersion;
+ /** The offset back to the RTVFSOBJOPS structure. */
+ uint32_t offObjOps;
+
+ /**
+ * Set the unix style owner and group.
+ *
+ * @returns IPRT status code.
+ * @param pvThis The implementation specific file data.
+ * @param fMode The new mode bits.
+ * @param fMask The mask indicating which bits we are
+ * changing.
+ * @note Optional, failing with VERR_WRITE_PROTECT if NULL.
+ * @sa RTFileSetMode
+ */
+ DECLCALLBACKMEMBER(int, pfnSetMode,(void *pvThis, RTFMODE fMode, RTFMODE fMask));
+
+ /**
+ * Set the timestamps associated with the object.
+ *
+ * @returns IPRT status code.
+ * @param pvThis The implementation specific file data.
+ * @param pAccessTime Pointer to the new access time. NULL if not
+ * to be changed.
+ * @param pModificationTime Pointer to the new modifcation time. NULL if
+ * not to be changed.
+ * @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.
+ * @remarks See RTFileSetTimes for restrictions and behavior imposed by the
+ * host OS or underlying VFS provider.
+ * @note Optional, failing with VERR_WRITE_PROTECT if NULL.
+ * @sa RTFileSetTimes
+ */
+ DECLCALLBACKMEMBER(int, pfnSetTimes,(void *pvThis, PCRTTIMESPEC pAccessTime, PCRTTIMESPEC pModificationTime,
+ PCRTTIMESPEC pChangeTime, PCRTTIMESPEC pBirthTime));
+
+ /**
+ * Set the unix style owner and group.
+ *
+ * @returns IPRT status code.
+ * @param pvThis The implementation specific file data.
+ * @param uid The user ID of the new owner. NIL_RTUID if
+ * unchanged.
+ * @param gid The group ID of the new owner group. NIL_RTGID if
+ * unchanged.
+ * @note Optional, failing with VERR_WRITE_PROTECT if NULL.
+ * @sa RTFileSetOwner
+ */
+ DECLCALLBACKMEMBER(int, pfnSetOwner,(void *pvThis, RTUID uid, RTGID gid));
+
+ /** Marks the end of the structure (RTVFSOBJSETOPS_VERSION). */
+ uintptr_t uEndMarker;
+} RTVFSOBJSETOPS;
+/** Pointer to const object attribute setter operations. */
+typedef RTVFSOBJSETOPS const *PCRTVFSOBJSETOPS;
+
+/** The RTVFSOBJSETOPS structure version. */
+#define RTVFSOBJSETOPS_VERSION RT_MAKE_U32_FROM_U8(0xff,0x2f,1,0)
+
+
+/**
+ * The filesystem stream operations.
+ *
+ * @extends RTVFSOBJOPS
+ */
+typedef struct RTVFSFSSTREAMOPS
+{
+ /** The basic object operation. */
+ RTVFSOBJOPS Obj;
+ /** The structure version (RTVFSFSSTREAMOPS_VERSION). */
+ uint32_t uVersion;
+ /** Reserved field, MBZ. */
+ uint32_t fReserved;
+
+ /**
+ * Gets the next object in the stream.
+ *
+ * Readable streams only.
+ *
+ * @returns IPRT status code.
+ * @retval VINF_SUCCESS if a new object was retrieved.
+ * @retval VERR_EOF when there are no more objects.
+ * @param pvThis The implementation specific directory data.
+ * @param ppszName Where to return the object name. Must be freed by
+ * calling RTStrFree.
+ * @param penmType Where to return the object type.
+ * @param phVfsObj Where to return the object handle (referenced). This
+ * must be cast to the desired type before use.
+ * @sa RTVfsFsStrmNext
+ *
+ * @note Setting this member to NULL is okay for write-only streams.
+ */
+ DECLCALLBACKMEMBER(int, pfnNext,(void *pvThis, char **ppszName, RTVFSOBJTYPE *penmType, PRTVFSOBJ phVfsObj));
+
+ /**
+ * Adds another object into the stream.
+ *
+ * Writable streams only.
+ *
+ * @returns IPRT status code.
+ * @param pvThis The implementation specific directory data.
+ * @param pszPath The path to the object.
+ * @param hVfsObj The object to add.
+ * @param fFlags Reserved for the future, MBZ.
+ * @sa RTVfsFsStrmAdd
+ *
+ * @note Setting this member to NULL is okay for read-only streams.
+ */
+ DECLCALLBACKMEMBER(int, pfnAdd,(void *pvThis, const char *pszPath, RTVFSOBJ hVfsObj, uint32_t fFlags));
+
+ /**
+ * Pushes an byte stream onto the stream (optional).
+ *
+ * Writable streams only.
+ *
+ * This differs from RTVFSFSSTREAMOPS::pfnAdd() in that it will create a regular
+ * file in the output file system stream and provide the actual content bytes
+ * via the returned I/O stream object.
+ *
+ * @returns IPRT status code.
+ * @param pvThis The implementation specific directory data.
+ * @param pszPath The path to the file.
+ * @param cbFile The file size. This can also be set to UINT64_MAX if
+ * the file system stream is backed by a file.
+ * @param paObjInfo Array of zero or more RTFSOBJINFO structures containing
+ * different pieces of information about the file. If any
+ * provided, the first one should be a RTFSOBJATTRADD_UNIX
+ * one, additional can be supplied if wanted. What exactly
+ * is needed depends on the underlying FS stream
+ * implementation.
+ * @param cObjInfo Number of items in the array @a paObjInfo points at.
+ * @param fFlags RTVFSFSSTRM_PUSH_F_XXX.
+ * @param phVfsIos Where to return the I/O stream to feed the file content
+ * to. If the FS stream is backed by a file, the returned
+ * handle can be cast to a file if necessary.
+ */
+ DECLCALLBACKMEMBER(int, pfnPushFile,(void *pvThis, const char *pszPath, uint64_t cbFile,
+ PCRTFSOBJINFO paObjInfo, uint32_t cObjInfo, uint32_t fFlags, PRTVFSIOSTREAM phVfsIos));
+
+ /**
+ * Marks the end of the stream.
+ *
+ * Writable streams only.
+ *
+ * @returns IPRT status code.
+ * @param pvThis The implementation specific directory data.
+ * @sa RTVfsFsStrmEnd
+ *
+ * @note Setting this member to NULL is okay for read-only streams.
+ */
+ DECLCALLBACKMEMBER(int, pfnEnd,(void *pvThis));
+
+ /** Marks the end of the structure (RTVFSFSSTREAMOPS_VERSION). */
+ uintptr_t uEndMarker;
+} RTVFSFSSTREAMOPS;
+/** Pointer to const object attribute setter operations. */
+typedef RTVFSFSSTREAMOPS const *PCRTVFSFSSTREAMOPS;
+
+/** The RTVFSFSSTREAMOPS structure version. */
+#define RTVFSFSSTREAMOPS_VERSION RT_MAKE_U32_FROM_U8(0xff,0x3f,2,0)
+
+
+/**
+ * Creates a new VFS filesystem stream handle.
+ *
+ * @returns IPRT status code
+ * @param pFsStreamOps The filesystem stream operations.
+ * @param cbInstance The size of the instance data.
+ * @param hVfs The VFS handle to associate this filesystem
+ * stream with. NIL_VFS is ok.
+ * @param hLock Handle to a custom lock to be used with the new
+ * object. The reference is consumed. NIL and
+ * special lock handles are fine.
+ * @param fAccess RTFILE_O_READ and/or RTFILE_O_WRITE.
+ * @param phVfsFss Where to return the new handle.
+ * @param ppvInstance Where to return the pointer to the instance data
+ * (size is @a cbInstance).
+ */
+RTDECL(int) RTVfsNewFsStream(PCRTVFSFSSTREAMOPS pFsStreamOps, size_t cbInstance, RTVFS hVfs, RTVFSLOCK hLock, uint32_t fAccess,
+ PRTVFSFSSTREAM phVfsFss, void **ppvInstance);
+
+/**
+ * Gets the private data of an filesystem stream.
+ *
+ * @returns Pointer to the private data. NULL if the handle is invalid in some
+ * way.
+ * @param hVfsFss The FS stream handle.
+ * @param pFsStreamOps The FS stream operations. This servers as a
+ * sort of password.
+ */
+RTDECL(void *) RTVfsFsStreamToPrivate(RTVFSFSSTREAM hVfsFss, PCRTVFSFSSTREAMOPS pFsStreamOps);
+
+
+/**
+ * The directory operations.
+ *
+ * @extends RTVFSOBJOPS
+ * @extends RTVFSOBJSETOPS
+ */
+typedef struct RTVFSDIROPS
+{
+ /** The basic object operation. */
+ RTVFSOBJOPS Obj;
+ /** The structure version (RTVFSDIROPS_VERSION). */
+ uint32_t uVersion;
+ /** Reserved field, MBZ. */
+ uint32_t fReserved;
+ /** The object setter operations. */
+ RTVFSOBJSETOPS ObjSet;
+
+ /**
+ * Generic method for opening any kind of file system object.
+ *
+ * Can also create files and directories. Symbolic links, devices and such
+ * needs to be created using special methods or this would end up being way more
+ * complicated than it already is.
+ *
+ * There are optional specializations available.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_PATH_NOT_FOUND or VERR_FILE_NOT_FOUND if @a pszEntry was not
+ * found.
+ * @retval VERR_IS_A_FILE if @a pszEntry is a file or similar but @a fFlags
+ * indicates that the type of object should not be opened.
+ * @retval VERR_IS_A_DIRECTORY if @a pszEntry is a directory but @a fFlags
+ * indicates that directories should not be opened.
+ * @retval VERR_IS_A_SYMLINK if @a pszEntry is a symbolic link but @a fFlags
+ * indicates that symbolic links should not be opened (or followed).
+ * @retval VERR_IS_A_FIFO if @a pszEntry is a FIFO but @a fFlags indicates that
+ * FIFOs should not be opened.
+ * @retval VERR_IS_A_SOCKET if @a pszEntry is a socket but @a fFlags indicates
+ * that sockets should not be opened.
+ * @retval VERR_IS_A_BLOCK_DEVICE if @a pszEntry is a block device but
+ * @a fFlags indicates that block devices should not be opened, or vice
+ * versa.
+ *
+ * @param pvThis The implementation specific directory data.
+ * @param pszEntry The name of the immediate file to open or create.
+ * @param fOpenFile RTFILE_O_XXX combination.
+ * @param fObjFlags More flags: RTVFSOBJ_F_XXX, RTPATH_F_XXX.
+ * The meaning of RTPATH_F_FOLLOW_LINK differs here, if
+ * @a pszEntry is a symlink it should be opened for
+ * traversal rather than according to @a fOpenFile.
+ * @param phVfsObj Where to return the handle to the opened object.
+ * @sa RTFileOpen, RTDirOpen
+ */
+ DECLCALLBACKMEMBER(int, pfnOpen,(void *pvThis, const char *pszEntry, uint64_t fOpenFile,
+ uint32_t fObjFlags, PRTVFSOBJ phVfsObj));
+
+ /**
+ * Optional method for symbolic link handling in the vfsstddir.cpp.
+ *
+ * This is really just a hack to make symbolic link handling work when working
+ * with directory objects that doesn't have an associated VFS. It also helps
+ * deal with drive letters in symbolic links on Windows and OS/2.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_PATH_IS_RELATIVE if @a pszPath isn't absolute and should be
+ * handled using pfnOpen().
+ *
+ * @param pvThis The implementation specific directory data.
+ * @param pszRoot Path to the alleged root.
+ * @param phVfsDir Where to return the handle to the specified root
+ * directory (or may current dir on a drive letter).
+ */
+ DECLCALLBACKMEMBER(int, pfnFollowAbsoluteSymlink,(void *pvThis, const char *pszRoot, PRTVFSDIR phVfsDir));
+
+ /**
+ * Open or create a file.
+ *
+ * @returns IPRT status code.
+ * @param pvThis The implementation specific directory data.
+ * @param pszFilename The name of the immediate file to open or create.
+ * @param fOpen The open flags (RTFILE_O_XXX).
+ * @param phVfsFile Where to return the handle to the opened file.
+ * @note Optional. RTVFSDIROPS::pfnOpenObj will be used if NULL.
+ * @sa RTFileOpen.
+ */
+ DECLCALLBACKMEMBER(int, pfnOpenFile,(void *pvThis, const char *pszFilename, uint64_t fOpen, PRTVFSFILE phVfsFile));
+
+ /**
+ * Open an existing subdirectory.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_IS_A_SYMLINK if @a pszSubDir is a symbolic link.
+ * @retval VERR_NOT_A_DIRECTORY is okay for symbolic links too.
+ *
+ * @param pvThis The implementation specific directory data.
+ * @param pszSubDir The name of the immediate subdirectory to open.
+ * @param fFlags RTDIR_F_XXX.
+ * @param phVfsDir Where to return the handle to the opened directory.
+ * Optional.
+ * @note Optional. RTVFSDIROPS::pfnOpenObj will be used if NULL.
+ * @sa RTDirOpen.
+ */
+ DECLCALLBACKMEMBER(int, pfnOpenDir,(void *pvThis, const char *pszSubDir, uint32_t fFlags, PRTVFSDIR phVfsDir));
+
+ /**
+ * Creates a new subdirectory.
+ *
+ * @returns IPRT status code.
+ * @param pvThis The implementation specific directory data.
+ * @param pszSubDir The name of the immediate subdirectory to create.
+ * @param fMode The mode mask of the new directory.
+ * @param phVfsDir Where to optionally return the handle to the newly
+ * create directory.
+ * @note Optional. RTVFSDIROPS::pfnOpenObj will be used if NULL.
+ * @sa RTDirCreate.
+ */
+ DECLCALLBACKMEMBER(int, pfnCreateDir,(void *pvThis, const char *pszSubDir, RTFMODE fMode, PRTVFSDIR phVfsDir));
+
+ /**
+ * Opens an existing symbolic link.
+ *
+ * @returns IPRT status code.
+ * @param pvThis The implementation specific directory data.
+ * @param pszSymlink The name of the immediate symbolic link to open.
+ * @param phVfsSymlink Where to optionally return the handle to the
+ * newly create symbolic link.
+ * @note Optional. RTVFSDIROPS::pfnOpenObj will be used if NULL.
+ * @sa RTSymlinkCreate.
+ */
+ DECLCALLBACKMEMBER(int, pfnOpenSymlink,(void *pvThis, const char *pszSymlink, PRTVFSSYMLINK phVfsSymlink));
+
+ /**
+ * Creates a new symbolic link.
+ *
+ * @returns IPRT status code.
+ * @param pvThis The implementation specific directory data.
+ * @param pszSymlink The name of the immediate symbolic link to create.
+ * @param pszTarget The symbolic link target.
+ * @param enmType The symbolic link type.
+ * @param phVfsSymlink Where to optionally return the handle to the
+ * newly create symbolic link.
+ * @sa RTSymlinkCreate.
+ */
+ DECLCALLBACKMEMBER(int, pfnCreateSymlink,(void *pvThis, const char *pszSymlink, const char *pszTarget,
+ RTSYMLINKTYPE enmType, PRTVFSSYMLINK phVfsSymlink));
+
+ /**
+ * Query information about an entry.
+ *
+ * @returns IPRT status code.
+ * @param pvThis The implementation specific directory data.
+ * @param pszEntry The name of the directory entry to remove.
+ * @param pObjInfo Where to return the info on success.
+ * @param enmAddAttr Which set of additional attributes to request.
+ * @note Optional. RTVFSDIROPS::pfnOpenObj and RTVFSOBJOPS::pfnQueryInfo
+ * will be used if NULL.
+ * @sa RTPathQueryInfo, RTVFSOBJOPS::pfnQueryInfo
+ */
+ DECLCALLBACKMEMBER(int, pfnQueryEntryInfo,(void *pvThis, const char *pszEntry,
+ PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr));
+
+ /**
+ * Removes a directory entry.
+ *
+ * @returns IPRT status code.
+ * @param pvThis The implementation specific directory data.
+ * @param pszEntry The name of the directory entry to remove.
+ * @param fType If non-zero, this restricts the type of the entry to
+ * the object type indicated by the mask
+ * (RTFS_TYPE_XXX).
+ * @sa RTFileRemove, RTDirRemove, RTSymlinkRemove.
+ */
+ DECLCALLBACKMEMBER(int, pfnUnlinkEntry,(void *pvThis, const char *pszEntry, RTFMODE fType));
+
+ /**
+ * Renames a directory entry.
+ *
+ * @returns IPRT status code.
+ * @param pvThis The implementation specific directory data.
+ * @param pszEntry The name of the directory entry to rename.
+ * @param fType If non-zero, this restricts the type of the entry to
+ * the object type indicated by the mask
+ * (RTFS_TYPE_XXX).
+ * @param pszNewName The new entry name.
+ * @sa RTPathRename
+ *
+ * @todo This API is not flexible enough, must be able to rename between
+ * directories within a file system.
+ */
+ DECLCALLBACKMEMBER(int, pfnRenameEntry,(void *pvThis, const char *pszEntry, RTFMODE fType, const char *pszNewName));
+
+ /**
+ * Rewind the directory stream so that the next read returns the first
+ * entry.
+ *
+ * @returns IPRT status code.
+ * @param pvThis The implementation specific directory data.
+ */
+ DECLCALLBACKMEMBER(int, pfnRewindDir,(void *pvThis));
+
+ /**
+ * Rewind the directory stream so that the next read returns the first
+ * entry.
+ *
+ * @returns IPRT status code.
+ * @param pvThis The implementation specific directory data.
+ * @param pDirEntry Output buffer.
+ * @param pcbDirEntry Complicated, see RTDirReadEx.
+ * @param enmAddAttr Which set of additional attributes to request.
+ * @sa RTDirReadEx
+ */
+ DECLCALLBACKMEMBER(int, pfnReadDir,(void *pvThis, PRTDIRENTRYEX pDirEntry, size_t *pcbDirEntry, RTFSOBJATTRADD enmAddAttr));
+
+ /** Marks the end of the structure (RTVFSDIROPS_VERSION). */
+ uintptr_t uEndMarker;
+} RTVFSDIROPS;
+/** Pointer to const directory operations. */
+typedef RTVFSDIROPS const *PCRTVFSDIROPS;
+/** The RTVFSDIROPS structure version. */
+#define RTVFSDIROPS_VERSION RT_MAKE_U32_FROM_U8(0xff,0x4f,1,0)
+
+
+/**
+ * Creates a new VFS directory handle.
+ *
+ * @returns IPRT status code
+ * @param pDirOps The directory operations.
+ * @param cbInstance The size of the instance data.
+ * @param fFlags RTVFSDIR_F_XXX
+ * @param hVfs The VFS handle to associate this directory with.
+ * NIL_VFS is ok.
+ * @param hLock Handle to a custom lock to be used with the new
+ * object. The reference is consumed. NIL and
+ * special lock handles are fine.
+ * @param phVfsDir Where to return the new handle.
+ * @param ppvInstance Where to return the pointer to the instance data
+ * (size is @a cbInstance).
+ */
+RTDECL(int) RTVfsNewDir(PCRTVFSDIROPS pDirOps, size_t cbInstance, uint32_t fFlags, RTVFS hVfs, RTVFSLOCK hLock,
+ PRTVFSDIR phVfsDir, void **ppvInstance);
+
+/** @name RTVFSDIR_F_XXX
+ * @{ */
+/** Don't reference the @a hVfs parameter passed to RTVfsNewDir.
+ * This is a permanent root directory hack. */
+#define RTVFSDIR_F_NO_VFS_REF RT_BIT_32(0)
+/** @} */
+
+/**
+ * Gets the private data of a directory.
+ *
+ * @returns Pointer to the private data. NULL if the handle is invalid in some
+ * way.
+ * @param hVfsDir The directory handle.
+ * @param pDirOps The directory operations. This servers as a
+ * sort of password.
+ */
+RTDECL(void *) RTVfsDirToPrivate(RTVFSDIR hVfsDir, PCRTVFSDIROPS pDirOps);
+
+
+/**
+ * The symbolic link operations.
+ *
+ * @extends RTVFSOBJOPS
+ * @extends RTVFSOBJSETOPS
+ */
+typedef struct RTVFSSYMLINKOPS
+{
+ /** The basic object operation. */
+ RTVFSOBJOPS Obj;
+ /** The structure version (RTVFSSYMLINKOPS_VERSION). */
+ uint32_t uVersion;
+ /** Reserved field, MBZ. */
+ uint32_t fReserved;
+ /** The object setter operations. */
+ RTVFSOBJSETOPS ObjSet;
+
+ /**
+ * Read the symbolic link target.
+ *
+ * @returns IPRT status code.
+ * @param pvThis The implementation specific symbolic link data.
+ * @param pszTarget The target buffer.
+ * @param cbTarget The size of the target buffer.
+ * @sa RTSymlinkRead
+ */
+ DECLCALLBACKMEMBER(int, pfnRead,(void *pvThis, char *pszTarget, size_t cbTarget));
+
+ /** Marks the end of the structure (RTVFSSYMLINKOPS_VERSION). */
+ uintptr_t uEndMarker;
+} RTVFSSYMLINKOPS;
+/** Pointer to const symbolic link operations. */
+typedef RTVFSSYMLINKOPS const *PCRTVFSSYMLINKOPS;
+/** The RTVFSSYMLINKOPS structure version. */
+#define RTVFSSYMLINKOPS_VERSION RT_MAKE_U32_FROM_U8(0xff,0x5f,1,0)
+
+
+/**
+ * Creates a new VFS symlink handle.
+ *
+ * @returns IPRT status code
+ * @param pSymlinkOps The symlink operations.
+ * @param cbInstance The size of the instance data.
+ * @param hVfs The VFS handle to associate this symlink object
+ * with. NIL_VFS is ok.
+ * @param hLock Handle to a custom lock to be used with the new
+ * object. The reference is consumed. NIL and
+ * special lock handles are fine.
+ * @param phVfsSym Where to return the new handle.
+ * @param ppvInstance Where to return the pointer to the instance data
+ * (size is @a cbInstance).
+ */
+RTDECL(int) RTVfsNewSymlink(PCRTVFSSYMLINKOPS pSymlinkOps, size_t cbInstance, RTVFS hVfs, RTVFSLOCK hLock,
+ PRTVFSSYMLINK phVfsSym, void **ppvInstance);
+
+
+/**
+ * Gets the private data of a symbolic link.
+ *
+ * @returns Pointer to the private data. NULL if the handle is invalid in some
+ * way.
+ * @param hVfsSym The symlink handle.
+ * @param pSymlinkOps The symlink operations. This servers as a sort
+ * of password.
+ */
+RTDECL(void *) RTVfsSymlinkToPrivate(RTVFSSYMLINK hVfsSym, PCRTVFSSYMLINKOPS pSymlinkOps);
+
+/**
+ * The basis for all I/O objects (files, pipes, sockets, devices, ++).
+ *
+ * @extends RTVFSOBJOPS
+ */
+typedef struct RTVFSIOSTREAMOPS
+{
+ /** The basic object operation. */
+ RTVFSOBJOPS Obj;
+ /** The structure version (RTVFSIOSTREAMOPS_VERSION). */
+ uint32_t uVersion;
+ /** Feature field. */
+ uint32_t fFeatures;
+
+ /**
+ * Reads from the file/stream.
+ *
+ * @returns IPRT status code. See RTVfsIoStrmRead.
+ * @param pvThis The implementation specific file data.
+ * @param off Where to read at, -1 for the current position.
+ * @param pSgBuf Gather buffer describing the bytes that are to be
+ * written.
+ * @param fBlocking If @c true, the call is blocking, if @c false it
+ * should not block.
+ * @param pcbRead Where return the number of bytes actually read.
+ * This is set it 0 by the caller. If NULL, try read
+ * all and fail if incomplete.
+ * @sa RTVfsIoStrmRead, RTVfsIoStrmSgRead, RTVfsFileRead,
+ * RTVfsFileReadAt, RTFileRead, RTFileReadAt.
+ */
+ DECLCALLBACKMEMBER(int, pfnRead,(void *pvThis, RTFOFF off, PCRTSGBUF pSgBuf, bool fBlocking, size_t *pcbRead));
+
+ /**
+ * Writes to the file/stream.
+ *
+ * @returns IPRT status code.
+ * @param pvThis The implementation specific file data.
+ * @param off Where to start wrinting, -1 for the current
+ * position.
+ * @param pSgBuf Gather buffers describing the bytes that are to be
+ * written.
+ * @param fBlocking If @c true, the call is blocking, if @c false it
+ * should not block.
+ * @param pcbWritten Where to return the number of bytes actually
+ * written. This is set it 0 by the caller. If
+ * NULL, try write it all and fail if incomplete.
+ * @note Optional, failing with VERR_WRITE_PROTECT if NULL.
+ * @sa RTFileWrite, RTFileWriteAt.
+ */
+ DECLCALLBACKMEMBER(int, pfnWrite,(void *pvThis, RTFOFF off, PCRTSGBUF pSgBuf, bool fBlocking, size_t *pcbWritten));
+
+ /**
+ * Flushes any pending data writes to the stream.
+ *
+ * @returns IPRT status code.
+ * @param pvThis The implementation specific file data.
+ * @sa RTFileFlush.
+ */
+ DECLCALLBACKMEMBER(int, pfnFlush,(void *pvThis));
+
+ /**
+ * Poll for events.
+ *
+ * @returns IPRT status code.
+ * @param pvThis The implementation specific file data.
+ * @param fEvents The events to poll for (RTPOLL_EVT_XXX).
+ * @param cMillies How long to wait for event to eventuate.
+ * @param fIntr Whether the wait is interruptible and can return
+ * VERR_INTERRUPTED (@c true) or if this condition
+ * should be hidden from the caller (@c false).
+ * @param pfRetEvents Where to return the event mask.
+ * @note Optional. If NULL, immediately return all requested non-error
+ * events, waiting for errors works like sleep.
+ * @sa RTPollSetAdd, RTPoll, RTPollNoResume.
+ */
+ DECLCALLBACKMEMBER(int, pfnPollOne,(void *pvThis, uint32_t fEvents, RTMSINTERVAL cMillies, bool fIntr,
+ uint32_t *pfRetEvents));
+
+ /**
+ * Tells the current file/stream position.
+ *
+ * @returns IPRT status code.
+ * @param pvThis The implementation specific file data.
+ * @param poffActual Where to return the actual offset.
+ * @sa RTFileTell
+ */
+ DECLCALLBACKMEMBER(int, pfnTell,(void *pvThis, PRTFOFF poffActual));
+
+ /**
+ * Skips @a cb ahead in the stream.
+ *
+ * @returns IPRT status code.
+ * @param pvThis The implementation specific file data.
+ * @param cb The number bytes to skip.
+ * @remarks This is optional and can be NULL.
+ */
+ DECLCALLBACKMEMBER(int, pfnSkip,(void *pvThis, RTFOFF cb));
+
+ /**
+ * Fills the stream with @a cb zeros.
+ *
+ * @returns IPRT status code.
+ * @param pvThis The implementation specific file data.
+ * @param cb The number of zero bytes to insert.
+ * @remarks This is optional and can be NULL.
+ */
+ DECLCALLBACKMEMBER(int, pfnZeroFill,(void *pvThis, RTFOFF cb));
+
+ /** Marks the end of the structure (RTVFSIOSTREAMOPS_VERSION). */
+ uintptr_t uEndMarker;
+} RTVFSIOSTREAMOPS;
+/** Pointer to const I/O stream operations. */
+typedef RTVFSIOSTREAMOPS const *PCRTVFSIOSTREAMOPS;
+
+/** The RTVFSIOSTREAMOPS structure version. */
+#define RTVFSIOSTREAMOPS_VERSION RT_MAKE_U32_FROM_U8(0xff,0x6f,1,0)
+
+/** @name RTVFSIOSTREAMOPS::fFeatures
+ * @{ */
+/** No scatter gather lists, thank you. */
+#define RTVFSIOSTREAMOPS_FEAT_NO_SG RT_BIT_32(0)
+/** Mask of the valid I/O stream feature flags. */
+#define RTVFSIOSTREAMOPS_FEAT_VALID_MASK UINT32_C(0x00000001)
+/** @} */
+
+
+/**
+ * Creates a new VFS I/O stream handle.
+ *
+ * @returns IPRT status code
+ * @param pIoStreamOps The I/O stream operations.
+ * @param cbInstance The size of the instance data.
+ * @param fOpen The open flags. The minimum is the access mask.
+ * @param hVfs The VFS handle to associate this I/O stream
+ * with. NIL_VFS is ok.
+ * @param hLock Handle to a custom lock to be used with the new
+ * object. The reference is consumed. NIL and
+ * special lock handles are fine.
+ * @param phVfsIos Where to return the new handle.
+ * @param ppvInstance Where to return the pointer to the instance data
+ * (size is @a cbInstance).
+ */
+RTDECL(int) RTVfsNewIoStream(PCRTVFSIOSTREAMOPS pIoStreamOps, size_t cbInstance, uint32_t fOpen, RTVFS hVfs, RTVFSLOCK hLock,
+ PRTVFSIOSTREAM phVfsIos, void **ppvInstance);
+
+
+/**
+ * Gets the private data of an I/O stream.
+ *
+ * @returns Pointer to the private data. NULL if the handle is invalid in some
+ * way.
+ * @param hVfsIos The I/O stream handle.
+ * @param pIoStreamOps The I/O stream operations. This servers as a
+ * sort of password.
+ */
+RTDECL(void *) RTVfsIoStreamToPrivate(RTVFSIOSTREAM hVfsIos, PCRTVFSIOSTREAMOPS pIoStreamOps);
+
+
+/**
+ * The file operations.
+ *
+ * @extends RTVFSIOSTREAMOPS
+ * @extends RTVFSOBJSETOPS
+ */
+typedef struct RTVFSFILEOPS
+{
+ /** The I/O stream and basis object operations. */
+ RTVFSIOSTREAMOPS Stream;
+ /** The structure version (RTVFSFILEOPS_VERSION). */
+ uint32_t uVersion;
+ /** Reserved field, MBZ. */
+ uint32_t fReserved;
+ /** The object setter operations. */
+ RTVFSOBJSETOPS ObjSet;
+
+ /**
+ * Changes the current file position.
+ *
+ * @returns IPRT status code.
+ * @param pvThis The implementation specific file data.
+ * @param offSeek The offset to seek.
+ * @param uMethod The seek method, i.e. what the seek is relative to.
+ * @param poffActual Where to return the actual offset.
+ * @sa RTFileSeek
+ */
+ DECLCALLBACKMEMBER(int, pfnSeek,(void *pvThis, RTFOFF offSeek, unsigned uMethod, PRTFOFF poffActual));
+
+ /**
+ * Get the current file size.
+ *
+ * @returns IPRT status code.
+ * @param pvThis The implementation specific file data.
+ * @param pcbFile Where to store the current file size.
+ * @sa RTFileQuerySize
+ */
+ DECLCALLBACKMEMBER(int, pfnQuerySize,(void *pvThis, uint64_t *pcbFile));
+
+ /**
+ * Change the file size.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_ACCESS_DENIED if handle isn't writable.
+ * @retval VERR_WRITE_PROTECT if read-only file system.
+ * @retval VERR_FILE_TOO_BIG if cbSize is larger than what the file system can
+ * theoretically deal with.
+ * @retval VERR_DISK_FULL if the file system if full.
+ * @retval VERR_NOT_SUPPORTED if fFlags indicates some operation that's not
+ * supported by the file system / host operating system.
+ *
+ * @param pvThis The implementation specific file data.
+ * @param pcbFile Where to store the current file size.
+ * @param fFlags RTVFSFILE_SET_SIZE_F_XXX.
+ * @note Optional. If NULL, VERR_WRITE_PROTECT will be returned.
+ * @sa RTFileSetSize, RTFileSetAllocationSize
+ */
+ DECLCALLBACKMEMBER(int, pfnSetSize,(void *pvThis, uint64_t cbFile, uint32_t fFlags));
+
+ /**
+ * Determine the maximum file size.
+ *
+ * This won't take amount of freespace into account, just the limitations of the
+ * underlying file system / host operating system.
+ *
+ * @returns IPRT status code.
+ * @param pvThis The implementation specific file data.
+ * @param pcbMax Where to return the max file size.
+ * @note Optional. If NULL, VERR_NOT_IMPLEMENTED will be returned.
+ * @sa RTFileQueryMaxSizeEx
+ */
+ DECLCALLBACKMEMBER(int, pfnQueryMaxSize,(void *pvThis, uint64_t *pcbMax));
+
+ /** @todo There will be more methods here. */
+
+ /** Marks the end of the structure (RTVFSFILEOPS_VERSION). */
+ uintptr_t uEndMarker;
+} RTVFSFILEOPS;
+/** Pointer to const file operations. */
+typedef RTVFSFILEOPS const *PCRTVFSFILEOPS;
+
+/** The RTVFSFILEOPS structure version. */
+#define RTVFSFILEOPS_VERSION RT_MAKE_U32_FROM_U8(0xff,0x7f,2,0)
+
+/**
+ * Creates a new VFS file handle.
+ *
+ * @returns IPRT status code
+ * @param pFileOps The file operations.
+ * @param cbInstance The size of the instance data.
+ * @param fOpen The open flags. The minimum is the access mask.
+ * @param hVfs The VFS handle to associate this file with.
+ * NIL_VFS is ok.
+ * @param hLock Handle to a custom lock to be used with the new
+ * object. The reference is consumed. NIL and
+ * special lock handles are fine.
+ * @param phVfsFile Where to return the new handle.
+ * @param ppvInstance Where to return the pointer to the instance data
+ * (size is @a cbInstance).
+ */
+RTDECL(int) RTVfsNewFile(PCRTVFSFILEOPS pFileOps, size_t cbInstance, uint32_t fOpen, RTVFS hVfs, RTVFSLOCK hLock,
+ PRTVFSFILE phVfsFile, void **ppvInstance);
+
+
+/** @defgroup grp_rt_vfs_ll_util VFS Utility APIs
+ * @{ */
+
+/**
+ * Parsed path.
+ */
+typedef struct RTVFSPARSEDPATH
+{
+ /** The length of the path in szCopy. */
+ uint16_t cch;
+ /** The number of path components. */
+ uint16_t cComponents;
+ /** Set if the path ends with slash, indicating that it's a directory
+ * reference and not a file reference. The slash has been removed from
+ * the copy. */
+ bool fDirSlash;
+ /** Set if absolute. */
+ bool fAbsolute;
+ /** The offset where each path component starts, i.e. the char after the
+ * slash. The array has cComponents + 1 entries, where the final one is
+ * cch + 1 so that one can always terminate the current component by
+ * szPath[aoffComponent[i] - 1] = '\0'. */
+ uint16_t aoffComponents[RTPATH_MAX / 2 + 1];
+ /** A normalized copy of the path.
+ * Reserve some extra space so we can be more relaxed about overflow
+ * checks and terminator paddings, especially when recursing. */
+ char szPath[RTPATH_MAX];
+} RTVFSPARSEDPATH;
+/** Pointer to a parsed path. */
+typedef RTVFSPARSEDPATH *PRTVFSPARSEDPATH;
+
+/** The max accepted path length.
+ * This must be a few chars shorter than RTVFSPARSEDPATH::szPath because we
+ * use two terminators and wish be a little bit lazy with checking. */
+#define RTVFSPARSEDPATH_MAX (RTPATH_MAX - 4)
+
+/**
+ * Appends @a pszPath (relative) to the already parsed path @a pPath.
+ *
+ * @retval VINF_SUCCESS
+ * @retval VERR_FILENAME_TOO_LONG
+ * @retval VERR_INTERNAL_ERROR_4
+ * @param pPath The parsed path to append @a pszPath onto.
+ * This is both input and output.
+ * @param pszPath The path to append. This must be relative.
+ * @param piRestartComp The component to restart parsing at. This is
+ * input/output. The input does not have to be
+ * within the valid range. Optional.
+ */
+RTDECL(int) RTVfsParsePathAppend(PRTVFSPARSEDPATH pPath, const char *pszPath, uint16_t *piRestartComp);
+
+/**
+ * Parses a path.
+ *
+ * @retval VINF_SUCCESS
+ * @retval VERR_FILENAME_TOO_LONG
+ * @param pPath Where to store the parsed path.
+ * @param pszPath The path to parse. Absolute or relative to @a
+ * pszCwd.
+ * @param pszCwd The current working directory. Must be
+ * absolute.
+ */
+RTDECL(int) RTVfsParsePath(PRTVFSPARSEDPATH pPath, const char *pszPath, const char *pszCwd);
+
+/**
+ * Same as RTVfsParsePath except that it allocates a temporary buffer.
+ *
+ * @retval VINF_SUCCESS
+ * @retval VERR_NO_TMP_MEMORY
+ * @retval VERR_FILENAME_TOO_LONG
+ * @param pszPath The path to parse. Absolute or relative to @a
+ * pszCwd.
+ * @param pszCwd The current working directory. Must be
+ * absolute.
+ * @param ppPath Where to store the pointer to the allocated
+ * buffer containing the parsed path. This must
+ * be freed by calling RTVfsParsePathFree. NULL
+ * will be stored on failured.
+ */
+RTDECL(int) RTVfsParsePathA(const char *pszPath, const char *pszCwd, PRTVFSPARSEDPATH *ppPath);
+
+/**
+ * Frees a buffer returned by RTVfsParsePathA.
+ *
+ * @param pPath The parsed path buffer to free. NULL is fine.
+ */
+RTDECL(void) RTVfsParsePathFree(PRTVFSPARSEDPATH pPath);
+
+/**
+ * Dummy implementation of RTVFSIOSTREAMOPS::pfnPollOne.
+ *
+ * This handles the case where there is no chance any events my be raised and
+ * all that is required is to wait according to the parameters.
+ *
+ * @returns IPRT status code.
+ * @param fEvents The events to poll for (RTPOLL_EVT_XXX).
+ * @param cMillies How long to wait for event to eventuate.
+ * @param fIntr Whether the wait is interruptible and can return
+ * VERR_INTERRUPTED (@c true) or if this condition
+ * should be hidden from the caller (@c false).
+ * @param pfRetEvents Where to return the event mask.
+ * @sa RTVFSIOSTREAMOPS::pfnPollOne, RTPollSetAdd, RTPoll, RTPollNoResume.
+ */
+RTDECL(int) RTVfsUtilDummyPollOne(uint32_t fEvents, RTMSINTERVAL cMillies, bool fIntr, uint32_t *pfRetEvents);
+
+/** @} */
+
+
+/** @defgroup grp_rt_vfs_lowlevel_chain VFS Chains (Low Level)
+ * @ref grp_rt_vfs_chain
+ * @{
+ */
+
+/** Pointer to a VFS chain element registration record. */
+typedef struct RTVFSCHAINELEMENTREG *PRTVFSCHAINELEMENTREG;
+/** Pointer to a const VFS chain element registration record. */
+typedef struct RTVFSCHAINELEMENTREG const *PCRTVFSCHAINELEMENTREG;
+
+/**
+ * VFS chain element argument.
+ */
+typedef struct RTVFSCHAINELEMENTARG
+{
+ /** The string argument value. */
+ char *psz;
+ /** The specification offset of this argument. */
+ uint16_t offSpec;
+ /** Provider specific value. */
+ uint64_t uProvider;
+} RTVFSCHAINELEMENTARG;
+/** Pointer to a VFS chain element argument. */
+typedef RTVFSCHAINELEMENTARG *PRTVFSCHAINELEMENTARG;
+
+
+/**
+ * VFS chain element specification.
+ */
+typedef struct RTVFSCHAINELEMSPEC
+{
+ /** The provider name.
+ * This can be NULL if this is the final component and it's just a path. */
+ char *pszProvider;
+ /** The input type, RTVFSOBJTYPE_INVALID if first. */
+ RTVFSOBJTYPE enmTypeIn;
+ /** The element type.
+ * RTVFSOBJTYPE_END if this is the final component and it's just a path. */
+ RTVFSOBJTYPE enmType;
+ /** The input spec offset of this element. */
+ uint16_t offSpec;
+ /** The length of the input spec. */
+ uint16_t cchSpec;
+ /** The number of arguments. */
+ uint32_t cArgs;
+ /** Arguments. */
+ PRTVFSCHAINELEMENTARG paArgs;
+
+ /** The provider. */
+ PCRTVFSCHAINELEMENTREG pProvider;
+ /** Provider specific value. */
+ uint64_t uProvider;
+ /** The object (with reference). */
+ RTVFSOBJ hVfsObj;
+} RTVFSCHAINELEMSPEC;
+/** Pointer to a chain element specification. */
+typedef RTVFSCHAINELEMSPEC *PRTVFSCHAINELEMSPEC;
+/** Pointer to a const chain element specification. */
+typedef RTVFSCHAINELEMSPEC const *PCRTVFSCHAINELEMSPEC;
+
+
+/**
+ * Parsed VFS chain specification.
+ */
+typedef struct RTVFSCHAINSPEC
+{
+ /** Open directory flags (RTFILE_O_XXX). */
+ uint64_t fOpenFile;
+ /** To be defined. */
+ uint32_t fOpenDir;
+ /** The type desired by the caller. */
+ RTVFSOBJTYPE enmDesiredType;
+ /** The number of elements. */
+ uint32_t cElements;
+ /** The elements. */
+ PRTVFSCHAINELEMSPEC paElements;
+} RTVFSCHAINSPEC;
+/** Pointer to a parsed VFS chain specification. */
+typedef RTVFSCHAINSPEC *PRTVFSCHAINSPEC;
+/** Pointer to a const, parsed VFS chain specification. */
+typedef RTVFSCHAINSPEC const *PCRTVFSCHAINSPEC;
+
+
+/**
+ * A chain element provider registration record.
+ */
+typedef struct RTVFSCHAINELEMENTREG
+{
+ /** The version (RTVFSCHAINELEMENTREG_VERSION). */
+ uint32_t uVersion;
+ /** Reserved, MBZ. */
+ uint32_t fReserved;
+ /** The provider name (unique). */
+ const char *pszName;
+ /** For chaining the providers. */
+ RTLISTNODE ListEntry;
+ /** Help text. */
+ const char *pszHelp;
+
+ /**
+ * Checks the element specification.
+ *
+ * This is allowed to parse arguments and use pSpec->uProvider and
+ * pElement->paArgs[].uProvider to store information that pfnInstantiate and
+ * pfnCanReuseElement may use later on, thus avoiding duplicating work/code.
+ *
+ * @returns IPRT status code.
+ * @param pProviderReg Pointer to the element provider registration.
+ * @param pSpec The chain specification.
+ * @param pElement The chain element specification to validate.
+ * @param poffError Where to return error offset on failure. This is
+ * set to the pElement->offSpec on input, so it only
+ * needs to be adjusted if an argument is at fault.
+ * @param pErrInfo Where to return additional error information, if
+ * available. Optional.
+ */
+ DECLCALLBACKMEMBER(int, pfnValidate,(PCRTVFSCHAINELEMENTREG pProviderReg, PRTVFSCHAINSPEC pSpec,
+ PRTVFSCHAINELEMSPEC pElement, uint32_t *poffError, PRTERRINFO pErrInfo));
+
+ /**
+ * Create a VFS object according to the element specification.
+ *
+ * @returns IPRT status code.
+ * @param pProviderReg Pointer to the element provider registration.
+ * @param pSpec The chain specification.
+ * @param pElement The chain element specification to instantiate.
+ * @param hPrevVfsObj Handle to the previous VFS object, NIL_RTVFSOBJ if
+ * first.
+ * @param phVfsObj Where to return the VFS object handle.
+ * @param poffError Where to return error offset on failure. This is
+ * set to the pElement->offSpec on input, so it only
+ * needs to be adjusted if an argument is at fault.
+ * @param pErrInfo Where to return additional error information, if
+ * available. Optional.
+ */
+ DECLCALLBACKMEMBER(int, pfnInstantiate,(PCRTVFSCHAINELEMENTREG pProviderReg, PCRTVFSCHAINSPEC pSpec,
+ PCRTVFSCHAINELEMSPEC pElement, RTVFSOBJ hPrevVfsObj,
+ PRTVFSOBJ phVfsObj, uint32_t *poffError, PRTERRINFO pErrInfo));
+
+ /**
+ * Determins whether the element can be reused.
+ *
+ * This is for handling situations accessing the same file system twice, like
+ * for both the source and destiation of a copy operation. This allows not only
+ * sharing resources and avoid doing things twice, but also helps avoid file
+ * sharing violations and inconsistencies araising from the image being updated
+ * and read independently.
+ *
+ * @returns true if the element from @a pReuseSpec an be reused, false if not.
+ * @param pProviderReg Pointer to the element provider registration.
+ * @param pSpec The chain specification.
+ * @param pElement The chain element specification.
+ * @param pReuseSpec The chain specification of the existing chain.
+ * @param pReuseElement The chain element specification of the existing
+ * element that is being considered for reuse.
+ */
+ DECLCALLBACKMEMBER(bool, pfnCanReuseElement,(PCRTVFSCHAINELEMENTREG pProviderReg,
+ PCRTVFSCHAINSPEC pSpec, PCRTVFSCHAINELEMSPEC pElement,
+ PCRTVFSCHAINSPEC pReuseSpec, PCRTVFSCHAINELEMSPEC pReuseElement));
+
+ /** End marker (RTVFSCHAINELEMENTREG_VERSION). */
+ uintptr_t uEndMarker;
+} RTVFSCHAINELEMENTREG;
+
+/** The VFS chain element registration record version number. */
+#define RTVFSCHAINELEMENTREG_VERSION RT_MAKE_U32_FROM_U8(0xff, 0x7f, 1, 0)
+
+
+/**
+ * Parses the specification.
+ *
+ * @returns IPRT status code.
+ * @param pszSpec The specification string to parse.
+ * @param fFlags Flags, see RTVFSCHAIN_PF_XXX.
+ * @param enmDesiredType The object type the caller wants to interface with.
+ * @param ppSpec Where to return the pointer to the parsed
+ * specification. This must be freed by calling
+ * RTVfsChainSpecFree. Will always be set (unless
+ * invalid parameters.)
+ * @param poffError Where to return the offset into the input
+ * specification of what's causing trouble. Always
+ * set, unless this argument causes an invalid pointer
+ * error.
+ */
+RTDECL(int) RTVfsChainSpecParse(const char *pszSpec, uint32_t fFlags, RTVFSOBJTYPE enmDesiredType,
+ PRTVFSCHAINSPEC *ppSpec, uint32_t *poffError);
+
+/** @name RTVfsChainSpecParse
+ * @{ */
+/** Mask of valid flags. */
+#define RTVFSCHAIN_PF_VALID_MASK UINT32_C(0x00000000)
+/** @} */
+
+/**
+ * Checks and setups the chain.
+ *
+ * @returns IPRT status code.
+ * @param pSpec The parsed specification.
+ * @param pReuseSpec Spec to reuse if applicable. Optional.
+ * @param phVfsObj Where to return the VFS object.
+ * @param ppszFinalPath Where to return the pointer to the final path if
+ * applicable. The caller needs to check whether this
+ * is NULL or a path, in the former case nothing more
+ * needs doing, whereas in the latter the caller must
+ * perform the desired operation(s) on *phVfsObj using
+ * the final path.
+ * @param poffError Where to return the offset into the input
+ * specification of what's causing trouble. Always
+ * set, unless this argument causes an invalid pointer
+ * error.
+ * @param pErrInfo Where to return additional error information, if
+ * available. Optional.
+ */
+RTDECL(int) RTVfsChainSpecCheckAndSetup(PRTVFSCHAINSPEC pSpec, PCRTVFSCHAINSPEC pReuseSpec,
+ PRTVFSOBJ phVfsObj, const char **ppszFinalPath, uint32_t *poffError, PRTERRINFO pErrInfo);
+
+/**
+ * Frees a parsed chain specification.
+ *
+ * @param pSpec What RTVfsChainSpecParse returned. NULL is
+ * quietly ignored.
+ */
+RTDECL(void) RTVfsChainSpecFree(PRTVFSCHAINSPEC pSpec);
+
+/**
+ * Registers a chain element provider.
+ *
+ * @returns IPRT status code
+ * @param pRegRec The registration record.
+ * @param fFromCtor Indicates where we're called from.
+ */
+RTDECL(int) RTVfsChainElementRegisterProvider(PRTVFSCHAINELEMENTREG pRegRec, bool fFromCtor);
+
+/**
+ * Deregisters a chain element provider.
+ *
+ * @returns IPRT status code
+ * @param pRegRec The registration record.
+ * @param fFromDtor Indicates where we're called from.
+ */
+RTDECL(int) RTVfsChainElementDeregisterProvider(PRTVFSCHAINELEMENTREG pRegRec, bool fFromDtor);
+
+
+/** @def RTVFSCHAIN_AUTO_REGISTER_ELEMENT_PROVIDER
+ * Automatically registers a chain element provider using a global constructor
+ * and destructor hack.
+ *
+ * @param pRegRec Pointer to the registration record.
+ * @param name Some unique variable name prefix.
+ */
+
+#ifdef __cplusplus
+/**
+ * Class used for registering a VFS chain element provider.
+ */
+class RTVfsChainElementAutoRegisterHack
+{
+private:
+ /** The registration record, NULL if registration failed. */
+ PRTVFSCHAINELEMENTREG m_pRegRec;
+
+public:
+ RTVfsChainElementAutoRegisterHack(PRTVFSCHAINELEMENTREG a_pRegRec)
+ : m_pRegRec(a_pRegRec)
+ {
+ int rc = RTVfsChainElementRegisterProvider(m_pRegRec, true);
+ if (RT_FAILURE(rc))
+ m_pRegRec = NULL;
+ }
+
+ ~RTVfsChainElementAutoRegisterHack()
+ {
+ RTVfsChainElementDeregisterProvider(m_pRegRec, true);
+ m_pRegRec = NULL;
+ }
+};
+
+# define RTVFSCHAIN_AUTO_REGISTER_ELEMENT_PROVIDER(pRegRec, name) \
+ static RTVfsChainElementAutoRegisterHack name ## AutoRegistrationHack(pRegRec)
+
+#else
+# define RTVFSCHAIN_AUTO_REGISTER_ELEMENT_PROVIDER(pRegRec, name) \
+ extern void *name ## AutoRegistrationHack = \
+ &Sorry_but_RTVFSCHAIN_AUTO_REGISTER_ELEMENT_PROVIDER_does_not_work_in_c_source_files
+#endif
+
+
+/**
+ * Common worker for the 'stdfile' and 'open' providers for implementing
+ * RTVFSCHAINELEMENTREG::pfnValidate.
+ *
+ * Stores the RTFILE_O_XXX flags in pSpec->uProvider.
+ *
+ * @returns IPRT status code.
+ * @param pSpec The chain specification.
+ * @param pElement The chain element specification to validate.
+ * @param poffError Where to return error offset on failure. This is set to
+ * the pElement->offSpec on input, so it only needs to be
+ * adjusted if an argument is at fault.
+ * @param pErrInfo Where to return additional error information, if
+ * available. Optional.
+ */
+RTDECL(int) RTVfsChainValidateOpenFileOrIoStream(PRTVFSCHAINSPEC pSpec, PRTVFSCHAINELEMSPEC pElement,
+ uint32_t *poffError, PRTERRINFO pErrInfo);
+
+
+/** @} */
+
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_vfslowlevel_h */
+
diff --git a/include/iprt/win/Makefile.kup b/include/iprt/win/Makefile.kup
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/include/iprt/win/Makefile.kup
diff --git a/include/iprt/win/audioclient.h b/include/iprt/win/audioclient.h
new file mode 100644
index 00000000..4fb3fed1
--- /dev/null
+++ b/include/iprt/win/audioclient.h
@@ -0,0 +1,59 @@
+/** @file
+ * Safe way to include audioclient.h.
+ */
+
+/*
+ * Copyright (C) 2021-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_win_audioclient_h
+#define IPRT_INCLUDED_win_audioclient_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#ifdef _MSC_VER
+# pragma warning(push)
+# pragma warning(disable:4668) /* ks.h(1978): warning C4668: '_WIN64' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif' [SDK 7.1] */
+# if _MSC_VER >= 1900 /*RT_MSC_VER_VC140*/
+# ifdef __cplusplus
+# pragma warning(disable:4091) /* ksmedia.h(4356): warning C4091: 'typedef ': ignored on left of '<unnamed-enum-KSEVENT_DYNAMIC_FORMAT_CHANGE>' when no variable is declared [SDK 7.1] */
+# endif
+# endif
+#endif
+
+#include <audioclient.h>
+
+#ifdef _MSC_VER
+# pragma warning(pop)
+#endif
+
+#endif /* !IPRT_INCLUDED_win_audioclient_h */
+
diff --git a/include/iprt/win/commctrl.h b/include/iprt/win/commctrl.h
new file mode 100644
index 00000000..349bac97
--- /dev/null
+++ b/include/iprt/win/commctrl.h
@@ -0,0 +1,61 @@
+/** @file
+ * Safe way to include commctrl.h.
+ */
+
+/*
+ * Copyright (C) 2016-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_win_commctrl_h
+#define IPRT_INCLUDED_win_commctrl_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#ifdef _MSC_VER
+# pragma warning(push)
+# if _MSC_VER >= 1900 /*RT_MSC_VER_VC140*/
+# ifdef __cplusplus
+# pragma warning(disable:5039) /* commctrl.h(8323): warning C5039: 'DSA_DestroyCallback': pointer or reference to potentially throwing function passed to 'extern "C"' function under -EHc. Undefined behavior may occur if this function throws an exception. */
+# endif
+# ifdef __cplusplus
+# pragma warning(disable:4668) /* um\prsht.h(130): warning C4668: 'ISOLATION_AWARE_ENABLED' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif' */
+# endif
+# endif
+#endif
+
+#include <commctrl.h>
+
+#ifdef _MSC_VER
+# pragma warning(pop)
+#endif
+
+#endif /* !IPRT_INCLUDED_win_commctrl_h */
+
diff --git a/include/iprt/win/context-amd64.mac b/include/iprt/win/context-amd64.mac
new file mode 100644
index 00000000..5a1ec649
--- /dev/null
+++ b/include/iprt/win/context-amd64.mac
@@ -0,0 +1,118 @@
+;; @file
+; IPRT - Windows - AMD64 CPU Context Record for NASM/YASM.
+;
+
+;
+; Copyright (C) 2022 Oracle and/or its affiliates.
+;
+; This file is part of VirtualBox base platform packages, as
+; available from https://www.virtualbox.org.
+;
+; This program is free software; you can redistribute it and/or
+; modify it under the terms of the GNU General Public License
+; as published by the Free Software Foundation, in version 3 of the
+; License.
+;
+; This program is distributed in the hope that it will be useful, but
+; WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with this program; if not, see <https://www.gnu.org/licenses>.
+;
+; The contents of this file may alternatively be used under the terms
+; of the Common Development and Distribution License Version 1.0
+; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+; in the VirtualBox 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.
+;
+; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+;
+
+%ifndef ___iprt_win_context_amd64_mac
+%define ___iprt_win_context_amd64_mac
+
+%include "iprt/asmdefs.mac"
+
+struc CONTEXT
+ .P1Home resq 1
+ .P2Home resq 1
+ .P3Home resq 1
+ .P4Home resq 1
+ .P5Home resq 1
+ .P6Home resq 1
+
+ .ContextFlags resd 1
+ .MxCsr resd 1
+
+ .SegCs resw 1 ; CONTEXT_CONTROL
+ .SegDs resw 1
+ .SegEs resw 1
+ .SegFs resw 1
+ .SegGs resw 1
+ .SegSs resw 1 ; CONTEXT_CONTROL
+ .EFlags resd 1 ; CONTEXT_CONTROL
+
+ .Dr0 resq 1 ; CONTEXT_DEBUG_REGISTERS
+ .Dr1 resq 1 ; CONTEXT_DEBUG_REGISTERS
+ .Dr2 resq 1 ; CONTEXT_DEBUG_REGISTERS
+ .Dr3 resq 1 ; CONTEXT_DEBUG_REGISTERS
+ .Dr6 resq 1 ; CONTEXT_DEBUG_REGISTERS
+ .Dr7 resq 1 ; CONTEXT_DEBUG_REGISTERS
+
+ .Rax resq 1 ; CONTEXT_INTEGER
+ .Rcx resq 1 ; CONTEXT_INTEGER
+ .Rdx resq 1 ; CONTEXT_INTEGER
+ .Rbx resq 1 ; CONTEXT_INTEGER
+ .Rsp resq 1 ; CONTEXT_CONTROL
+ .Rbp resq 1 ; CONTEXT_INTEGER
+ .Rsi resq 1 ; CONTEXT_INTEGER
+ .Rdi resq 1 ; CONTEXT_INTEGER
+ .R8 resq 1 ; CONTEXT_INTEGER
+ .R9 resq 1 ; CONTEXT_INTEGER
+ .R10 resq 1 ; CONTEXT_INTEGER
+ .R11 resq 1 ; CONTEXT_INTEGER
+ .R12 resq 1 ; CONTEXT_INTEGER
+ .R13 resq 1 ; CONTEXT_INTEGER
+ .R14 resq 1 ; CONTEXT_INTEGER
+ .R15 resq 1 ; CONTEXT_INTEGER
+
+ .Rip resq 1 ; CONTEXT_CONTROL
+
+ .FltSave resb 512 ; X86FXSTATE - CONTEXT_FLOATING_POINT = Xmm0-Xmm15
+
+ .VectorRegisters resb (26 * 16)
+ .VectorControl resq 1
+
+ .DebugControl resq 1
+ .LastBranchToRip resq 1
+ .LastBranchFromRip resq 1
+ .LastExceptionToRip resq 1
+ .LastExceptionFromRip resq 1
+endstruc
+%define CONTEXT_SIZE (0x4d0)
+AssertCompileSize(CONTEXT, CONTEXT_SIZE)
+
+%define CONTEXT_AMD64 (0x00100000)
+%define CONTEXT_CONTROL (0x00000001 | CONTEXT_AMD64)
+%define CONTEXT_INTEGER (0x00000002 | CONTEXT_AMD64)
+%define CONTEXT_SEGMENTS (0x00000004 | CONTEXT_AMD64)
+%define CONTEXT_FLOATING_POINT (0x00000008 | CONTEXT_AMD64)
+%define CONTEXT_DEBUG_REGISTERS (0x00000010 | CONTEXT_AMD64)
+%define CONTEXT_FULL (0x0000000b | CONTEXT_AMD64)
+%define CONTEXT_ALL (0x0000001f | CONTEXT_AMD64)
+
+%define CONTEXT_XSTATE (0x00000040 | CONTEXT_AMD64)
+%define CONTEXT_KERNEL_CET (0x00000080 | CONTEXT_AMD64)
+%define CONTEXT_EXCEPTION_ACTIVE (0x08000000)
+%define CONTEXT_SERVICE_ACTIVE (0x10000000)
+%define CONTEXT_UNWOUND_TO_CALL (0x20000000)
+%define CONTEXT_EXCEPTION_REQUEST (0x40000000)
+%define CONTEXT_EXCEPTION_REPORTING (0x80000000)
+
+%endif
+
diff --git a/include/iprt/win/context-x86.mac b/include/iprt/win/context-x86.mac
new file mode 100644
index 00000000..1f126295
--- /dev/null
+++ b/include/iprt/win/context-x86.mac
@@ -0,0 +1,101 @@
+;; @file
+; IPRT - Windows - X86 CPU Context Record for NASM/YASM.
+;
+
+;
+; Copyright (C) 2022 Oracle and/or its affiliates.
+;
+; This file is part of VirtualBox base platform packages, as
+; available from https://www.virtualbox.org.
+;
+; This program is free software; you can redistribute it and/or
+; modify it under the terms of the GNU General Public License
+; as published by the Free Software Foundation, in version 3 of the
+; License.
+;
+; This program is distributed in the hope that it will be useful, but
+; WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with this program; if not, see <https://www.gnu.org/licenses>.
+;
+; The contents of this file may alternatively be used under the terms
+; of the Common Development and Distribution License Version 1.0
+; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+; in the VirtualBox 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.
+;
+; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+;
+
+%ifndef ___iprt_win_context_x86_mac
+%define ___iprt_win_context_x86_mac
+
+%include "iprt/asmdefs.mac"
+
+struc CONTEXT
+ .ContextFlags resd 1
+
+ ; CONTEXT_DEBUG_REGISTERS:
+ .Dr0 resd 1
+ .Dr1 resd 1
+ .Dr2 resd 1
+ .Dr3 resd 1
+ .Dr6 resd 1
+ .Dr7 resd 1
+
+ ; CONTEXT_FLOATING_POINT:
+ .FloatSave resb 112 ; X86FPUSTATE + 4 bytes
+
+ ; CONTEXT_SEGMENTS:
+ .SegGs resd 1
+ .SegFs resd 1
+ .SegEs resd 1
+ .SegDs resd 1
+
+ ; CONTEXT_INTEGER:
+ .Edi resd 1
+ .Esi resd 1
+ .Ebx resd 1
+ .Edx resd 1
+ .Ecx resd 1
+ .Eax resd 1
+
+ ; CONTEXT_CONTROL:
+ .Ebp resd 1
+ .Eip resd 1
+ .SegCs resd 1
+ .EFlags resd 1
+ .Esp resd 1
+ .SegSs resd 1
+
+ ; CONTEXT_EXTENDED_REGISTERS:
+ .ExtendedRegisters resb 512
+endstruc
+%define CONTEXT_SIZE (0x2cc)
+AssertCompileSize(CONTEXT, CONTEXT_SIZE)
+
+%define CONTEXT_i386 (0x00010000)
+%define CONTEXT_CONTROL (0x00000001 | CONTEXT_i386)
+%define CONTEXT_INTEGER (0x00000002 | CONTEXT_i386)
+%define CONTEXT_SEGMENTS (0x00000004 | CONTEXT_i386)
+%define CONTEXT_FLOATING_POINT (0x00000008 | CONTEXT_i386)
+%define CONTEXT_DEBUG_REGISTERS (0x00000010 | CONTEXT_i386)
+%define CONTEXT_EXTENDED_REGISTERS (0x00000020 | CONTEXT_i386)
+%define CONTEXT_FULL (0x00000007 | CONTEXT_i386)
+%define CONTEXT_ALL (0x0000003f | CONTEXT_i386)
+
+%define CONTEXT_XSTATE (0x00000040 | CONTEXT_i386)
+%define CONTEXT_EXCEPTION_ACTIVE (0x08000000)
+%define CONTEXT_SERVICE_ACTIVE (0x10000000)
+; 0x20000000 = CONTEXT_UNWOUND_TO_CALL ?
+%define CONTEXT_EXCEPTION_REQUEST (0x40000000)
+%define CONTEXT_EXCEPTION_REPORTING (0x80000000)
+
+%endif
+
diff --git a/include/iprt/win/credentialprovider.h b/include/iprt/win/credentialprovider.h
new file mode 100644
index 00000000..2d71cb6f
--- /dev/null
+++ b/include/iprt/win/credentialprovider.h
@@ -0,0 +1,58 @@
+/** @file
+ * Safe way to include credentialprovider.h.
+ */
+
+/*
+ * Copyright (C) 2016-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_win_credentialprovider_h
+#define IPRT_INCLUDED_win_credentialprovider_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#ifdef _MSC_VER
+# pragma warning(push)
+# if _MSC_VER >= 1900 /*RT_MSC_VER_VC140*/
+# ifdef __cplusplus
+# pragma warning(disable:5039) /* commctrl.h(8323): warning C5039: 'DSA_DestroyCallback': pointer or reference to potentially throwing function passed to 'extern "C"' function under -EHc. Undefined behavior may occur if this function throws an exception. */
+# endif
+# endif
+#endif
+
+#include <credentialprovider.h>
+
+#ifdef _MSC_VER
+# pragma warning(pop)
+#endif
+
+#endif /* !IPRT_INCLUDED_win_credentialprovider_h */
+
diff --git a/include/iprt/win/d3d8.h b/include/iprt/win/d3d8.h
new file mode 100644
index 00000000..14f1c4ed
--- /dev/null
+++ b/include/iprt/win/d3d8.h
@@ -0,0 +1,60 @@
+/** @file
+ * Safe way to include d3d8.h.
+ */
+
+/*
+ * Copyright (C) 2016-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_win_d3d8_h
+#define IPRT_INCLUDED_win_d3d8_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#ifdef _MSC_VER
+# pragma warning(push)
+/*# pragma warning(disable:4163)*/
+# pragma warning(disable:4668) /* warning C4668: 'WHEA_DOWNLEVEL_TYPE_NAMES' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif' */
+# pragma warning(disable:4255) /* warning C4255: 'ObGetFilterVersion' : no function prototype given: converting '()' to '(void)' */
+# if _MSC_VER >= 1800 /*RT_MSC_VER_VC120*/
+# pragma warning(disable:4005) /* sdk/v7.1/include/sal_supp.h(57) : warning C4005: '__useHeader' : macro redefinition */
+# endif
+#endif
+
+#include <d3d8.h>
+
+#ifdef _MSC_VER
+# pragma warning(pop)
+#endif
+
+
+#endif /* !IPRT_INCLUDED_win_d3d8_h */
+
diff --git a/include/iprt/win/d3d9.h b/include/iprt/win/d3d9.h
new file mode 100644
index 00000000..52c02c53
--- /dev/null
+++ b/include/iprt/win/d3d9.h
@@ -0,0 +1,68 @@
+/** @file
+ * Safe way to include d3d9.h.
+ */
+
+/*
+ * Copyright (C) 2016-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_win_d3d9_h
+#define IPRT_INCLUDED_win_d3d9_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+/* d3d9.h includes windows.h (via objbase.h -> rpc.h), so do it up front using
+ our wrappers to avoid needing to duplicate warning workarounds for it. */
+#include <iprt/win/windows.h>
+
+#ifdef _MSC_VER
+# pragma warning(push)
+/*# pragma warning(disable:4163)*/
+# pragma warning(disable:4668) /* warning C4668: 'WHEA_DOWNLEVEL_TYPE_NAMES' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif' */
+# pragma warning(disable:4255) /* warning C4255: 'ObGetFilterVersion' : no function prototype given: converting '()' to '(void)' */
+# if _MSC_VER >= 1800 /*RT_MSC_VER_VC120*/
+# pragma warning(disable:4005) /* sdk/v7.1/include/sal_supp.h(57) : warning C4005: '__useHeader' : macro redefinition */
+# endif
+# ifdef __cplusplus
+# if _MSC_VER >= 1900 /*RT_MSC_VER_VC140*/
+# pragma warning(disable:5039) /* winbase.h(13179): warning C5039: 'TpSetCallbackCleanupGroup': pointer or reference to potentially throwing function passed to 'extern "C"' function under -EHc. Undefined behavior may occur if this function throws an exception. */
+# endif
+# endif
+#endif
+
+#include <d3d9.h>
+
+#ifdef _MSC_VER
+# pragma warning(pop)
+#endif
+
+#endif /* !IPRT_INCLUDED_win_d3d9_h */
+
diff --git a/include/iprt/win/d3dkmthk.h b/include/iprt/win/d3dkmthk.h
new file mode 100644
index 00000000..af8fa34f
--- /dev/null
+++ b/include/iprt/win/d3dkmthk.h
@@ -0,0 +1,61 @@
+/** @file
+ * Safe way to include d3dkmthk.h.
+ */
+
+/*
+ * Copyright (C) 2016-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_win_d3dkmthk_h
+#define IPRT_INCLUDED_win_d3dkmthk_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#ifdef _MSC_VER
+# pragma warning(push)
+# if _MSC_VER >= 1900 /*RT_MSC_VER_VC140*/
+# pragma warning(disable:4255) /* d3dkmthk.h(2061): warning C4255: 'PFND3DKMT_CHECKEXCLUSIVEOWNERSHIP': no function prototype given: converting '()' to '(void)' */
+# endif
+#endif
+
+/* 10.0.22000.0 SDK: */
+#define DXGKDDI_INTERFACE_VERSION_WDDM_1_3 DXGKDDI_INTERFACE_VERSION_WDDM1_3
+#define DXGKDDI_INTERFACE_VERSION_WDDM_2_0 DXGKDDI_INTERFACE_VERSION_WDDM2_0
+#define DXGKDDI_INTERFACE_VERSION_WDDM1_3_M1 DXGKDDI_INTERFACE_VERSION_WDDM1_3
+
+#include <d3dkmthk.h>
+
+#ifdef _MSC_VER
+# pragma warning(pop)
+#endif
+
+#endif /* !IPRT_INCLUDED_win_d3dkmthk_h */
+
diff --git a/include/iprt/win/dbghelp.h b/include/iprt/win/dbghelp.h
new file mode 100644
index 00000000..00d50b32
--- /dev/null
+++ b/include/iprt/win/dbghelp.h
@@ -0,0 +1,61 @@
+/** @file
+ * Safe way to include Dbghelp.h.
+ */
+
+/*
+ * Copyright (C) 2020-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_win_dbghelp_h
+#define IPRT_INCLUDED_win_dbghelp_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#ifdef _MSC_VER
+/*
+ * Unfortunately, the Windows.h file in SDK 7.1 is not clean wrt warning C4091 with VCC140+:
+ * Dbghelp.h(1540): warning C4091: 'typedef ': ignored on left of '<unnamed-enum-hdBase>' when no variable is declared
+ * Dbghelp.h(3056): warning C4091: 'typedef ': ignored on left of '<unnamed-enum-sfImage>' when no variable is declared
+ */
+# pragma warning(push)
+# if _MSC_VER >= 1900 /*RT_MSC_VER_VC140*/
+# pragma warning(disable:4091)
+# endif
+#endif
+
+#include <Dbghelp.h>
+
+#ifdef _MSC_VER
+# pragma warning(pop)
+#endif
+
+#endif /* !IPRT_INCLUDED_win_dbghelp_h */
+
diff --git a/include/iprt/win/dshow.h b/include/iprt/win/dshow.h
new file mode 100644
index 00000000..eab1fdce
--- /dev/null
+++ b/include/iprt/win/dshow.h
@@ -0,0 +1,56 @@
+/** @file
+ * Safe way to include dshow.h.
+ */
+
+/*
+ * Copyright (C) 2016-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_win_dshow_h
+#define IPRT_INCLUDED_win_dshow_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#ifdef _MSC_VER
+# pragma warning(push)
+# if _MSC_VER >= 1920 /*RT_MSC_VER_VC142*/
+# pragma warning(disable:5204) /* strmif.h(16270): warning C5204: 'IAMFilterGraphCallback': class has virtual functions, but its trivial destructor is not virtual; instances of objects derived from this class may not be destructed correctly */
+# endif
+#endif
+
+#include <dshow.h>
+
+#ifdef _MSC_VER
+# pragma warning(pop)
+#endif
+
+#endif /* !IPRT_INCLUDED_win_dshow_h */
+
diff --git a/include/iprt/win/endpointvolume.h b/include/iprt/win/endpointvolume.h
new file mode 100644
index 00000000..ec9cced5
--- /dev/null
+++ b/include/iprt/win/endpointvolume.h
@@ -0,0 +1,58 @@
+/** @file
+ * Safe way to include endpointvolume.h.
+ */
+
+/*
+ * Copyright (C) 2016-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_win_endpointvolume_h
+#define IPRT_INCLUDED_win_endpointvolume_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#ifdef _MSC_VER
+# pragma warning(push)
+# pragma warning(disable:4201)
+# pragma warning(disable:4668) /* ks.h(1978): warning C4668: '_WIN64' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif' [SDK 7.1] */
+# if _MSC_VER >= 1900 /*RT_MSC_VER_VC140*/
+# pragma warning(disable: 4091) /* v7.1\include\ksmedia.h(4356): warning C4091: 'typedef ': ignored on left of '<unnamed-enum-KSEVENT_DYNAMIC_FORMAT_CHANGE>' when no variable is declared */
+# endif
+#endif
+
+#include <endpointvolume.h>
+
+#ifdef _MSC_VER
+# pragma warning(pop)
+#endif
+
+#endif /* !IPRT_INCLUDED_win_endpointvolume_h */
+
diff --git a/include/iprt/win/imagehlp.h b/include/iprt/win/imagehlp.h
new file mode 100644
index 00000000..138bdd3b
--- /dev/null
+++ b/include/iprt/win/imagehlp.h
@@ -0,0 +1,61 @@
+/** @file
+ * Safe way to include ImageHlp.h.
+ */
+
+/*
+ * Copyright (C) 2020-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_win_imagehlp_h
+#define IPRT_INCLUDED_win_imagehlp_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#ifdef _MSC_VER
+/*
+ * Unfortunately, the ImageHlp.h file in SDK 7.1 is not clean wrt warning C4091 with VCC141:
+ * ImageHlp.h(1869): warning C4091: 'typedef ': ignored on left of '<unnamed-enum-hdBase>' when no variable is declared
+ * ImageHlp.h(3385): warning C4091: 'typedef ': ignored on left of '<unnamed-enum-sfImage>' when no variable is declared
+ */
+# pragma warning(push)
+# if _MSC_VER >= 1900 /*RT_MSC_VER_VC140*/
+# pragma warning(disable:4091)
+# endif
+#endif
+
+#include <ImageHlp.h>
+
+#ifdef _MSC_VER
+# pragma warning(pop)
+#endif
+
+#endif /* !IPRT_INCLUDED_win_imagehlp_h */
+
diff --git a/include/iprt/win/intsafe.h b/include/iprt/win/intsafe.h
new file mode 100644
index 00000000..182b93de
--- /dev/null
+++ b/include/iprt/win/intsafe.h
@@ -0,0 +1,77 @@
+/** @file
+ * Safe way to include intsafe.h.
+ */
+
+/*
+ * Copyright (C) 2016-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_win_intsafe_h
+#define IPRT_INCLUDED_win_intsafe_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+/* There's a conflict between the Visual C++ 2010 stdint.h and wDK 7.1 intsafe.h
+ that we must to mediate here. Current approach is to use the stuff from
+ intsafe.h rather than the other. */
+#ifndef _INTSAFE_H_INCLUDED_
+# include <iprt/stdint.h>
+# undef INT8_MIN
+# undef INT16_MIN
+# undef INT32_MIN
+# undef INT8_MAX
+# undef INT16_MAX
+# undef INT32_MAX
+# undef UINT8_MAX
+# undef UINT16_MAX
+# undef UINT32_MAX
+# undef INT64_MIN
+# undef INT64_MAX
+# undef UINT64_MAX
+
+# ifdef _MSC_VER
+# pragma warning(push)
+# pragma warning(disable:4668) /* intsafe.h(55) : warning C4668: '__midl' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif' */
+# if _MSC_VER >= 1800 /*RT_MSC_VER_VC120*/
+# pragma warning(disable:4005) /* sdk/v7.1/include/sal_supp.h(57) : warning C4005: '__useHeader' : macro redefinition */
+# endif
+# endif
+
+# include <intsafe.h>
+
+# ifdef _MSC_VER
+# pragma warning(pop)
+# endif
+
+#endif /* !_INTSAFE_H_INCLUDED_ */
+
+#endif /* !IPRT_INCLUDED_win_intsafe_h */
+
diff --git a/include/iprt/win/iphlpapi.h b/include/iprt/win/iphlpapi.h
new file mode 100644
index 00000000..d823e1ac
--- /dev/null
+++ b/include/iprt/win/iphlpapi.h
@@ -0,0 +1,50 @@
+/** @file
+ * Safe way to include iphlpapi.h.
+ */
+
+/*
+ * Copyright (C) 2016-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_win_iphlpapi_h
+#define IPRT_INCLUDED_win_iphlpapi_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#pragma warning(push)
+#pragma warning(disable:4668) /* 'NDIS_SUPPORT_NDIS6' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif' */
+
+#include <iphlpapi.h>
+
+#pragma warning(pop)
+
+#endif /* !IPRT_INCLUDED_win_iphlpapi_h */
+
diff --git a/include/iprt/win/ks.h b/include/iprt/win/ks.h
new file mode 100644
index 00000000..6febf26c
--- /dev/null
+++ b/include/iprt/win/ks.h
@@ -0,0 +1,54 @@
+/** @file
+ * Safe way to include ks.h.
+ */
+
+/*
+ * Copyright (C) 2016-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_win_ks_h
+#define IPRT_INCLUDED_win_ks_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#ifdef _MSC_VER
+# pragma warning(push)
+# pragma warning(disable:4668) /* C4668: '_WIN64' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif' */
+#endif
+
+#include <ks.h>
+
+#ifdef _MSC_VER
+# pragma warning(pop)
+#endif
+
+#endif /* !IPRT_INCLUDED_win_ks_h */
+
diff --git a/include/iprt/win/lazy-dbghelp.h b/include/iprt/win/lazy-dbghelp.h
new file mode 100644
index 00000000..a6924bb1
--- /dev/null
+++ b/include/iprt/win/lazy-dbghelp.h
@@ -0,0 +1,151 @@
+/** @file
+ * Symbols from dbghelp.dll, allowing us to select which one to load.
+ */
+
+/*
+ * Copyright (C) 2013-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_win_lazy_dbghelp_h
+#define IPRT_INCLUDED_win_lazy_dbghelp_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/ldrlazy.h>
+#include <iprt/path.h>
+#include <iprt/env.h>
+#include <iprt/errcore.h>
+
+
+/**
+ * Custom loader callback.
+ * @returns Module handle or NIL_RTLDRMOD.
+ */
+static int rtLdrLazyLoadDbgHelp(const char *pszFile, PRTLDRMOD phMod)
+{
+ static const struct
+ {
+ const char *pszEnv;
+ const char *pszSubDir;
+ } s_aLocations[] =
+ {
+#ifdef RT_ARCH_AMD64
+ { "ProgramFiles(x86)", "Windows Kits\\8.1\\Debuggers\\x64\\dbghelp.dll" },
+ { "ProgramFiles(x86)", "Windows Kits\\8.0\\Debuggers\\x64\\dbghelp.dll" },
+ { "ProgramFiles", "Debugging Tools for Windows (x64)\\dbghelp.dll" },
+#else
+ { "ProgramFiles", "Windows Kits\\8.1\\Debuggers\\x86\\dbghelp.dll" },
+ { "ProgramFiles", "Windows Kits\\8.0\\Debuggers\\x86\\dbghelp.dll" },
+ { "ProgramFiles", "Debugging Tools for Windows (x86)\\dbghelp.dll" },
+#endif /** @todo More places we should look? */
+ };
+ uint32_t i;
+ for (i = 0; i < RT_ELEMENTS(s_aLocations); i++)
+ {
+ char szPath[RTPATH_MAX];
+ size_t cchPath;
+ int rc = RTEnvGetEx(RTENV_DEFAULT, s_aLocations[i].pszEnv, szPath, sizeof(szPath), &cchPath);
+ if (RT_SUCCESS(rc))
+ {
+ rc = RTPathAppend(szPath, sizeof(szPath), s_aLocations[i].pszSubDir);
+ if (RT_SUCCESS(rc))
+ {
+ rc = RTLdrLoad(szPath, phMod);
+ if (RT_SUCCESS(rc))
+ return rc;
+ }
+ }
+ }
+
+ /* Fall back on the system one, if present. */
+ return RTLdrLoadSystem(pszFile, true /*fNoUnload*/, phMod);
+}
+
+RTLDRLAZY_MODULE_EX(dbghelp, "dbghelp.dll", rtLdrLazyLoadDbgHelp);
+
+RTLDRLAZY_FUNC(dbghelp, BOOL, WINAPI, SymInitialize, (HANDLE a1, PCWSTR a2, BOOL a3), (a1, a2, a3), FALSE);
+#undef SymInitialize
+#define SymInitialize RTLDRLAZY_FUNC_NAME(dbghelp, SymInitialize)
+
+RTLDRLAZY_FUNC(dbghelp, BOOL, WINAPI, SymCleanup, (HANDLE a1), (a1), FALSE);
+#undef SymCleanup
+#define SymCleanup RTLDRLAZY_FUNC_NAME(dbghelp, SymCleanup)
+
+RTLDRLAZY_FUNC(dbghelp, DWORD, WINAPI, SymGetOptions, (VOID), (), 0);
+#undef SymGetOptions
+#define SymGetOptions RTLDRLAZY_FUNC_NAME(dbghelp, SymGetOptions)
+
+RTLDRLAZY_FUNC(dbghelp, DWORD, WINAPI, SymSetOptions, (DWORD a1), (a1), 0);
+#undef SymSetOptions
+#define SymSetOptions RTLDRLAZY_FUNC_NAME(dbghelp, SymSetOptions)
+
+RTLDRLAZY_FUNC(dbghelp, BOOL, WINAPI, SymRegisterCallback64, (HANDLE a1, PSYMBOL_REGISTERED_CALLBACK64 a2, ULONG64 a3),
+ (a1, a2, a3), FALSE);
+#undef SymRegisterCallback64
+#define SymRegisterCallback64 RTLDRLAZY_FUNC_NAME(dbghelp, SymRegisterCallback64)
+
+RTLDRLAZY_FUNC(dbghelp, DWORD64, WINAPI, SymLoadModuleEx,
+ (HANDLE a1, HANDLE a2, PCSTR a3, PCSTR a4, DWORD64 a5, DWORD a6, PMODLOAD_DATA a7, DWORD a8),
+ (a1, a2, a3, a4, a5, a6, a7, a8), 0);
+#undef SymLoadModuleEx
+#define SymLoadModuleEx RTLDRLAZY_FUNC_NAME(dbghelp, SymLoadModuleEx)
+
+RTLDRLAZY_FUNC(dbghelp, DWORD64, WINAPI, SymLoadModuleExW,
+ (HANDLE a1, HANDLE a2, PCWSTR a3, PCWSTR a4, DWORD64 a5, DWORD a6, PMODLOAD_DATA a7, DWORD a8),
+ (a1, a2, a3, a4, a5, a6, a7, a8), 0);
+#undef SymLoadModuleExW
+#define SymLoadModuleExW RTLDRLAZY_FUNC_NAME(dbghelp, SymLoadModuleExW)
+
+RTLDRLAZY_FUNC(dbghelp, DWORD64, WINAPI, SymUnloadModule64, (HANDLE a1, DWORD64 a2), (a1, a2), 0);
+#undef SymUnloadModule64
+#define SymUnloadModule64 RTLDRLAZY_FUNC_NAME(dbghelp, SymUnloadModule64)
+
+RTLDRLAZY_FUNC(dbghelp, BOOL, WINAPI, SymEnumSymbols,
+ (HANDLE a1, ULONG64 a2, PCSTR a3, PSYM_ENUMERATESYMBOLS_CALLBACK a4, PVOID a5),
+ (a1, a2, a3, a4, a5), FALSE);
+#undef SymEnumSymbols
+#define SymEnumSymbols RTLDRLAZY_FUNC_NAME(dbghelp, SymEnumSymbols)
+
+RTLDRLAZY_FUNC(dbghelp, BOOL, WINAPI, SymEnumLinesW,
+ (HANDLE a1, ULONG64 a2, PCWSTR a3, PCWSTR a4, PSYM_ENUMLINES_CALLBACKW a5, PVOID a6),
+ (a1, a2, a3, a4, a5, a6), FALSE);
+#undef SymEnumLinesW
+#define SymEnumLinesW RTLDRLAZY_FUNC_NAME(dbghelp, SymEnumLinesW)
+
+RTLDRLAZY_FUNC(dbghelp, BOOL, WINAPI, SymGetModuleInfo64, (HANDLE a1, DWORD64 a2, PIMAGEHLP_MODULE64 a3), (a1, a2, a3), FALSE);
+#undef SymGetModuleInfo64
+#define SymGetModuleInfo64 RTLDRLAZY_FUNC_NAME(dbghelp, SymGetModuleInfo64)
+
+
+
+
+#endif /* !IPRT_INCLUDED_win_lazy_dbghelp_h */
+
diff --git a/include/iprt/win/mmreg.h b/include/iprt/win/mmreg.h
new file mode 100644
index 00000000..8be69c7c
--- /dev/null
+++ b/include/iprt/win/mmreg.h
@@ -0,0 +1,53 @@
+/** @file
+ * Safe way to include mmreg.h.
+ */
+
+/*
+ * Copyright (C) 2016-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_win_mmreg_h
+#define IPRT_INCLUDED_win_mmreg_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#ifdef _MSC_VER
+# pragma warning(push) /* Looks like this header messes with warning config, at least in the 7.1 SDK. */
+#endif
+
+#include <mmreg.h>
+
+#ifdef _MSC_VER
+# pragma warning(pop)
+#endif
+
+#endif /* !IPRT_INCLUDED_win_mmreg_h */
+
diff --git a/include/iprt/win/netioapi.h b/include/iprt/win/netioapi.h
new file mode 100644
index 00000000..5abf1bac
--- /dev/null
+++ b/include/iprt/win/netioapi.h
@@ -0,0 +1,46 @@
+/** @file
+ * Safe way to include netioapi.h.
+ */
+
+/*
+ * Copyright (C) 2016-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_win_netioapi_h
+#define IPRT_INCLUDED_win_netioapi_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/win/ntddndis.h> /* this one has problems with -Wall */
+#include <netioapi.h>
+
+#endif /* !IPRT_INCLUDED_win_netioapi_h */
+
diff --git a/include/iprt/win/ntdddisk.h b/include/iprt/win/ntdddisk.h
new file mode 100644
index 00000000..452a5ac5
--- /dev/null
+++ b/include/iprt/win/ntdddisk.h
@@ -0,0 +1,50 @@
+/** @file
+ * Safe way to include ntdddisk.h.
+ */
+
+/*
+ * Copyright (C) 2016-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_win_ntdddisk_h
+#define IPRT_INCLUDED_win_ntdddisk_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#pragma warning(push)
+#pragma warning(disable:4668) /* ntdddisk.h(137) : warning C4668: 'NTDDI_WIN2003' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif' */
+
+#include <ntdddisk.h>
+
+#pragma warning(pop)
+
+#endif /* !IPRT_INCLUDED_win_ntdddisk_h */
+
diff --git a/include/iprt/win/ntddndis.h b/include/iprt/win/ntddndis.h
new file mode 100644
index 00000000..fc9b8520
--- /dev/null
+++ b/include/iprt/win/ntddndis.h
@@ -0,0 +1,50 @@
+/** @file
+ * Safe way to include ntddndis.h.
+ */
+
+/*
+ * Copyright (C) 2016-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_win_ntddndis_h
+#define IPRT_INCLUDED_win_ntddndis_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#pragma warning(push)
+#pragma warning(disable:4668) /* 'NDIS_SUPPORT_NDIS6' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif' */
+
+#include <ntddndis.h>
+
+#pragma warning(pop)
+
+#endif /* !IPRT_INCLUDED_win_ntddndis_h */
+
diff --git a/include/iprt/win/ntverp.h b/include/iprt/win/ntverp.h
new file mode 100644
index 00000000..484d8152
--- /dev/null
+++ b/include/iprt/win/ntverp.h
@@ -0,0 +1,50 @@
+/** @file
+ * Safe way to include ntverp.h.
+ */
+
+/*
+ * Copyright (C) 2016-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_win_ntverp_h
+#define IPRT_INCLUDED_win_ntverp_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#pragma warning(push)
+#pragma warning(disable:4668) /*ntverp.h(126) : warning C4668: 'OFFICIAL_BUILD' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif' */
+
+#include <ntverp.h>
+
+#pragma warning(pop)
+
+#endif /* !IPRT_INCLUDED_win_ntverp_h */
+
diff --git a/include/iprt/win/objbase.h b/include/iprt/win/objbase.h
new file mode 100644
index 00000000..8bcb5c00
--- /dev/null
+++ b/include/iprt/win/objbase.h
@@ -0,0 +1,69 @@
+/** @file
+ * Safe way to include objbase.h.
+ */
+
+/*
+ * Copyright (C) 2016-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_win_objbase_h
+#define IPRT_INCLUDED_win_objbase_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+/* objbase.h includes windows.h via rpc.h, so get ahead of it and include
+ it here via our cleanup wrapper. */
+#include <iprt/win/windows.h>
+
+#ifdef _MSC_VER
+# pragma warning(push)
+# pragma warning(disable:4668) /* '__midl' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif' */
+# if !defined(__cplusplus)
+# pragma warning(disable:4255) /* 'FARPROC' : no function prototype given: converting '()' to '(void)' */
+# endif
+# if _MSC_VER >= 1800 /*RT_MSC_VER_VC120*/
+# pragma warning(disable:4005) /* sdk/v7.1/include/sal_supp.h(57) : warning C4005: '__useHeader' : macro redefinition */
+# endif
+# ifdef __cplusplus
+# if _MSC_VER >= 1900 /*RT_MSC_VER_VC140*/
+# pragma warning(disable:5039) /* winbase.h(13179): warning C5039: 'TpSetCallbackCleanupGroup': pointer or reference to potentially throwing function passed to 'extern "C"' function under -EHc. Undefined behavior may occur if this function throws an exception. */
+# endif
+# endif
+#endif
+
+#include <objbase.h>
+
+#ifdef _MSC_VER
+# pragma warning(pop)
+#endif
+
+#endif /* !IPRT_INCLUDED_win_objbase_h */
+
diff --git a/include/iprt/win/objidl.h b/include/iprt/win/objidl.h
new file mode 100644
index 00000000..d12e8bd7
--- /dev/null
+++ b/include/iprt/win/objidl.h
@@ -0,0 +1,63 @@
+/** @file
+ * Safe way to include objidl.h.
+ */
+
+/*
+ * Copyright (C) 2016-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_win_objidl_h
+#define IPRT_INCLUDED_win_objidl_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#ifdef _MSC_VER
+# pragma warning(push)
+# pragma warning(disable:4668) /* '__midl' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif' */
+# if _MSC_VER >= 1800 /*RT_MSC_VER_VC120*/
+# pragma warning(disable:4005) /* sdk/v7.1/include/sal_supp.h(57) : warning C4005: '__useHeader' : macro redefinition */
+# pragma warning(disable:4255) /* windef.h(227) : warning C4255: 'NEARPROC' : no function prototype given: converting '()' to '(void)' */
+# endif
+# ifdef __cplusplus
+# if _MSC_VER >= 1900 /*RT_MSC_VER_VC140*/
+# pragma warning(disable:5039) /* winbase.h(13179): warning C5039: 'TpSetCallbackCleanupGroup': pointer or reference to potentially throwing function passed to 'extern "C"' function under -EHc. Undefined behavior may occur if this function throws an exception. */
+# endif
+# endif
+#endif
+
+#include <objidl.h>
+
+#ifdef _MSC_VER
+# pragma warning(pop)
+#endif
+
+#endif /* !IPRT_INCLUDED_win_objidl_h */
+
diff --git a/include/iprt/win/rpcproxy.h b/include/iprt/win/rpcproxy.h
new file mode 100644
index 00000000..8d355bb2
--- /dev/null
+++ b/include/iprt/win/rpcproxy.h
@@ -0,0 +1,75 @@
+/** @file
+ * Safe way to include rpcproxy.h (not C++ clean).
+ */
+
+/*
+ * Copyright (C) 2016-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_win_rpcproxy_h
+#define IPRT_INCLUDED_win_rpcproxy_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <objbase.h>
+
+#ifdef __cplusplus
+
+typedef struct IRpcStubBufferVtbl
+{
+ BEGIN_INTERFACE
+ HRESULT (STDMETHODCALLTYPE *QueryInterface)(IRpcStubBuffer *, REFIID, void **);
+ ULONG (STDMETHODCALLTYPE *AddRef)(IRpcStubBuffer *);
+ ULONG (STDMETHODCALLTYPE *Release)(IRpcStubBuffer *);
+ HRESULT (STDMETHODCALLTYPE *Connect)(IRpcStubBuffer *, IUnknown *);
+ void (STDMETHODCALLTYPE *Disconnect)(IRpcStubBuffer *);
+ HRESULT (STDMETHODCALLTYPE *Invoke)(IRpcStubBuffer *, RPCOLEMESSAGE *, IRpcChannelBuffer *);
+ IRpcStubBuffer * (STDMETHODCALLTYPE *IsIIDSupported)(IRpcStubBuffer *, REFIID);
+ ULONG (STDMETHODCALLTYPE *CountRefs)(IRpcStubBuffer *);
+ HRESULT (STDMETHODCALLTYPE *DebugServerQueryInterface)(IRpcStubBuffer *, void **);
+ void (STDMETHODCALLTYPE *DebugServerRelease)(IRpcStubBuffer *, void *);
+} IRpcStubBufferVtbl;
+
+typedef struct IPSFactoryBufferVtbl
+{
+ HRESULT (STDMETHODCALLTYPE *QueryInterface)(IPSFactoryBuffer *, REFIID, void **);
+ ULONG (STDMETHODCALLTYPE *AddRef)(IPSFactoryBuffer *);
+ ULONG (STDMETHODCALLTYPE *Release)(IPSFactoryBuffer *);
+ HRESULT (STDMETHODCALLTYPE *CreateProxy)(IPSFactoryBuffer *, IUnknown *, REFIID riid, IRpcProxyBuffer **, void **);
+ HRESULT (STDMETHODCALLTYPE *CreateStub)(IPSFactoryBuffer *, REFIID, IUnknown *, IRpcStubBuffer **);
+} IPSFactoryBufferVtbl;
+
+#endif /* __cplusplus */
+
+#include <rpcproxy.h>
+
+#endif /* !IPRT_INCLUDED_win_rpcproxy_h */
+
diff --git a/include/iprt/win/setupapi.h b/include/iprt/win/setupapi.h
new file mode 100644
index 00000000..704cedaf
--- /dev/null
+++ b/include/iprt/win/setupapi.h
@@ -0,0 +1,59 @@
+/** @file
+ * Safe way to include setupapi.h.
+ */
+
+/*
+ * Copyright (C) 2016-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_win_setupapi_h
+#define IPRT_INCLUDED_win_setupapi_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#ifdef _MSC_VER
+# pragma warning(push)
+# pragma warning(disable:4668) /* warning C4668: 'USE_SP_ALTPLATFORM_INFO_V1' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif' */
+# ifdef __cplusplus
+# if _MSC_VER >= 1900 /*RT_MSC_VER_VC140*/
+# pragma warning(disable:5039) /* winbase.h(13179): warning C5039: 'TpSetCallbackCleanupGroup': pointer or reference to potentially throwing function passed to 'extern "C"' function under -EHc. Undefined behavior may occur if this function throws an exception. */
+# endif
+# endif
+#endif
+
+#include <setupapi.h>
+
+#ifdef _MSC_VER
+# pragma warning(pop)
+#endif
+
+#endif /* !IPRT_INCLUDED_win_setupapi_h */
+
diff --git a/include/iprt/win/shlobj.h b/include/iprt/win/shlobj.h
new file mode 100644
index 00000000..bcbfd343
--- /dev/null
+++ b/include/iprt/win/shlobj.h
@@ -0,0 +1,67 @@
+/** @file
+ * Safe way to include shlobj.h.
+ */
+
+/*
+ * Copyright (C) 2016-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_win_shlobj_h
+#define IPRT_INCLUDED_win_shlobj_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#ifdef _MSC_VER
+# pragma warning(push)
+# pragma warning(disable:4668) /* warning C4668: 'USE_SP_ALTPLATFORM_INFO_V1' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif' */
+# if _MSC_VER >= 1800 /*RT_MSC_VER_VC120*/
+# pragma warning(disable:4005) /* sdk/v7.1/include/sal_supp.h(57) : warning C4005: '__useHeader' : macro redefinition */
+# pragma warning(disable:4255) /* windef.h(227) : warning C4255: 'NEARPROC' : no function prototype given: converting '()' to '(void)' */
+# endif
+# if _MSC_VER >= 1900 /*RT_MSC_VER_VC140*/
+# pragma warning(disable:4091) /* sdk/v7.1/include/shlobj.h(1151): warning C4091: 'typedef ': ignored on left of 'tagGPFIDL_FLAGS' when no variable is declared */
+# ifdef __cplusplus
+# pragma warning(disable:5039) /* commctrl.h(8323): warning C5039: 'DSA_DestroyCallback': pointer or reference to potentially throwing function passed to 'extern "C"' function under -EHc. Undefined behavior may occur if this function throws an exception. */
+# endif
+# endif
+# if _MSC_VER >= 1910 /*RT_MSC_VER_VC141*/
+# pragma warning(disable:4768) /* sdk/v7.1/include/shlobj.h(1065): warning C4768: __declspec attributes before linkage specification are ignored */
+# endif
+#endif
+
+#include <shlobj.h>
+
+#ifdef _MSC_VER
+# pragma warning(pop)
+#endif
+
+#endif /* !IPRT_INCLUDED_win_shlobj_h */
+
diff --git a/include/iprt/win/shlwapi.h b/include/iprt/win/shlwapi.h
new file mode 100644
index 00000000..f1b037d1
--- /dev/null
+++ b/include/iprt/win/shlwapi.h
@@ -0,0 +1,53 @@
+/** @file
+ * Safe way to include shlwapi.h.
+ */
+
+/*
+ * Copyright (C) 2016-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_win_shlwapi_h
+#define IPRT_INCLUDED_win_shlwapi_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#pragma warning(push)
+#pragma warning(disable:4668) /* warning C4668: 'USE_SP_ALTPLATFORM_INFO_V1' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif' */
+#pragma warning(disable:4255) /* warning C4255: 'I_RpcMgmtEnableDedicatedThreadPool' : no function prototype given: converting '()' to '(void)' */
+#if _MSC_VER >= 1800 /*RT_MSC_VER_VC120*/
+# pragma warning(disable:4005) /* sdk/v7.1/include/sal_supp.h(57) : warning C4005: '__useHeader' : macro redefinition */
+#endif
+#include <shlwapi.h>
+
+#pragma warning(pop)
+
+#endif /* !IPRT_INCLUDED_win_shlwapi_h */
+
diff --git a/include/iprt/win/windef.h b/include/iprt/win/windef.h
new file mode 100644
index 00000000..44c6a6ee
--- /dev/null
+++ b/include/iprt/win/windef.h
@@ -0,0 +1,65 @@
+/** @file
+ * Safe way to include windef.h.
+ */
+
+/*
+ * Copyright (C) 2016-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_win_windef_h
+#define IPRT_INCLUDED_win_windef_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#ifdef _MSC_VER
+/*
+ * Unfortunately, the windef.h file in SDK 7.1 is not clean wrt warning C4668:
+ * basetsd.h(114) : warning C4668: '__midl' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif'
+ * winnt.h(13017) : warning C4668: '_DBG_MEMCPY_INLINE_' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif'
+ */
+# pragma warning(push)
+# pragma warning(disable:4668)
+# ifndef __cplusplus
+# pragma warning(disable:4255) /* warning C4255: 'FARPROC' : no function prototype given: converting '()' to '(void)' */
+# endif
+# if _MSC_VER >= 1800 /*RT_MSC_VER_VC120*/
+# pragma warning(disable:4005) /* sdk/v7.1/include/sal_supp.h(57) : warning C4005: '__useHeader' : macro redefinition */
+# endif
+#endif
+
+#include <windef.h>
+
+#ifdef _MSC_VER
+# pragma warning(pop)
+#endif
+
+#endif /* !IPRT_INCLUDED_win_windef_h */
+
diff --git a/include/iprt/win/windows.h b/include/iprt/win/windows.h
new file mode 100644
index 00000000..b1612713
--- /dev/null
+++ b/include/iprt/win/windows.h
@@ -0,0 +1,110 @@
+/** @file
+ * Safe way to include Windows.h.
+ */
+
+/*
+ * Copyright (C) 2016-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_win_windows_h
+#define IPRT_INCLUDED_win_windows_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+
+/* winioctl.h in windows 10 SDKs up to 22000(?) has a warning(push/pop) bug in the
+ portion taken from ntddscm.h causing trouble when using _WIN32_WINNT or NTDDI_VERSION
+ older than NTDDI_WIN10_RS5. In 18362 winioctl.h also tests against _WIN32_WINNT_WIN10_TH2
+ and other sdkddkver.h defines which only exist in NTDDI variants, not in _WIN32_WINNT_XXX,
+ so we fake up those too to keep the precompiler warning free.
+
+ Work around this by blocking out the buggy section on winioctl.h for now if the
+ NTDDI_VERSION target is too small.
+
+ WDK_NTDDI_VERSION is not present in the W7 SDK, not sure when exactly it was added.
+ NTDDI_WIN10_RS5 is W10 1809. NTDDI_WIN10_CO is Windows 11? */
+#include <sdkddkver.h>
+#ifdef _WIN32_WINNT_WIN10
+# ifndef _WIN32_WINNT_WIN10_TH2
+# define _WIN32_WINNT_WIN10_TH2 _WIN32_WINNT_WIN10
+# endif
+# ifndef _WIN32_WINNT_WIN10_RS1
+# define _WIN32_WINNT_WIN10_RS1 _WIN32_WINNT_WIN10
+# endif
+# ifndef _WIN32_WINNT_WIN10_RS2
+# define _WIN32_WINNT_WIN10_RS2 _WIN32_WINNT_WIN10
+# endif
+# ifndef _WIN32_WINNT_WIN10_RS3
+# define _WIN32_WINNT_WIN10_RS3 _WIN32_WINNT_WIN10
+# endif
+# ifndef _WIN32_WINNT_WIN10_RS4
+# define _WIN32_WINNT_WIN10_RS4 _WIN32_WINNT_WIN10
+# endif
+# ifndef _WIN32_WINNT_WIN10_RS5
+# define _WIN32_WINNT_WIN10_RS5 _WIN32_WINNT_WIN10
+# endif
+#endif
+#if defined(NTDDI_WIN10_RS5) && !defined(NTDDI_WIN10_CO) && defined(WDK_NTDDI_VERSION)
+# if NTDDI_VERSION < NTDDI_WIN10_RS5
+# define _NTDDSCM_H_ buggy, hope nobody needs it.
+# endif
+#endif
+
+#ifdef _MSC_VER
+/*
+ * Unfortunately, the Windows.h file in SDK 7.1 is not clean wrt warning C4668:
+ * wincrypt.h(1848) : warning C4668: 'NTDDI_WINLH' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif'
+ */
+# pragma warning(push)
+# pragma warning(disable:4668)
+# pragma warning(disable:4480) /* W10/wincrypt.h(9193) : warning C4480: nonstandard extension used: specifying underlying type for enum 'CertKeyType' */
+# if _MSC_VER >= 1800 /*RT_MSC_VER_VC120*/
+# pragma warning(disable:4005) /* sdk/v7.1/include/sal_supp.h(57) : warning C4005: '__useHeader' : macro redefinition */
+# endif
+# ifdef __cplusplus
+# if _MSC_VER >= 1900 /*RT_MSC_VER_VC140*/
+# pragma warning(disable:5039) /* winbase.h(13179): warning C5039: 'TpSetCallbackCleanupGroup': pointer or reference to potentially throwing function passed to 'extern "C"' function under -EHc. Undefined behavior may occur if this function throws an exception. */
+# endif
+# else
+# pragma warning(disable:4255) /* warning C4255: 'FARPROC' : no function prototype given: converting '()' to '(void)' */
+# endif
+#endif
+
+#include <Windows.h>
+
+#ifdef _MSC_VER
+# pragma warning(pop)
+/* VS2010: Something causes this to be re-enabled above and triggering errors using RT_FLEXIBLE_ARRAY. */
+# pragma warning(disable:4200)
+#endif
+
+#endif /* !IPRT_INCLUDED_win_windows_h */
+
diff --git a/include/iprt/win/winsock.h b/include/iprt/win/winsock.h
new file mode 100644
index 00000000..aabc3372
--- /dev/null
+++ b/include/iprt/win/winsock.h
@@ -0,0 +1,64 @@
+/** @file
+ * Safe way to include winsock2.h.
+ */
+
+/*
+ * Copyright (C) 2016-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_win_winsock_h
+#define IPRT_INCLUDED_win_winsock_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#ifdef _MSC_VER
+/*
+ * Unfortunately, the Windows.h file in SDK 7.1 is not clean wrt warning C4668:
+ * wincrypt.h(1848) : warning C4668: 'NTDDI_WINLH' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif'
+ */
+# pragma warning(push)
+# pragma warning(disable:4668)
+# ifndef __cplusplus
+# pragma warning(disable:4255) /* warning C4255: 'FARPROC' : no function prototype given: converting '()' to '(void)' */
+# endif
+# if _MSC_VER >= 1800 /*RT_MSC_VER_VC120*/
+# pragma warning(disable:4005) /* sdk/v7.1/include/sal_supp.h(57) : warning C4005: '__useHeader' : macro redefinition */
+# endif
+#endif
+
+#include <winsock.h>
+
+#ifdef _MSC_VER
+# pragma warning(pop)
+#endif
+
+#endif /* !IPRT_INCLUDED_win_winsock_h */
+
diff --git a/include/iprt/win/winsock2.h b/include/iprt/win/winsock2.h
new file mode 100644
index 00000000..4c834b9a
--- /dev/null
+++ b/include/iprt/win/winsock2.h
@@ -0,0 +1,74 @@
+/** @file
+ * Safe way to include winsock2.h.
+ */
+
+/*
+ * Copyright (C) 2016-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_win_winsock2_h
+#define IPRT_INCLUDED_win_winsock2_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+/* winsock2.h includes windows.h, but without winsock.h, so we need to do it
+ up front using our wrapper header to avoid repeating tricks here. */
+#define _WINSOCKAPI_ /* do not include winsock.h via windows.h */
+#include <iprt/win/windows.h>
+
+#ifdef _MSC_VER
+/*
+ * Unfortunately, the Windows.h file in SDK 7.1 is not clean wrt warning C4668:
+ * wincrypt.h(1848) : warning C4668: 'NTDDI_WINLH' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif'
+ */
+# pragma warning(push)
+# pragma warning(disable:4668)
+# ifndef __cplusplus
+# pragma warning(disable:4255) /* warning C4255: 'FARPROC' : no function prototype given: converting '()' to '(void)' */
+# endif
+# if _MSC_VER >= 1800 /*RT_MSC_VER_VC120*/
+# pragma warning(disable:4005) /* sdk/v7.1/include/sal_supp.h(57) : warning C4005: '__useHeader' : macro redefinition */
+# endif
+# if _MSC_VER >= 1900 /*RT_MSC_VER_VC140*/
+# ifdef __cplusplus
+# pragma warning(disable:5039) /* winbase.h(13179): warning C5039: 'TpSetCallbackCleanupGroup': pointer or reference to potentially throwing function passed to 'extern "C"' function under -EHc. Undefined behavior may occur if this function throws an exception. */
+# endif
+# endif
+#endif
+
+#include <winsock2.h>
+
+#ifdef _MSC_VER
+# pragma warning(pop)
+#endif
+
+#endif /* !IPRT_INCLUDED_win_winsock2_h */
+
diff --git a/include/iprt/win/ws2tcpip.h b/include/iprt/win/ws2tcpip.h
new file mode 100644
index 00000000..ea5e7f2a
--- /dev/null
+++ b/include/iprt/win/ws2tcpip.h
@@ -0,0 +1,67 @@
+/** @file
+ * Safe way to include ws2tcpip.h.
+ */
+
+/*
+ * Copyright (C) 2016-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_win_ws2tcpip_h
+#define IPRT_INCLUDED_win_ws2tcpip_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+/* ws2tcpip.h includes winsock2.h, so get ahead of it and include our cleanly
+ wrapped version first to avoid duplicating stuff here. */
+#include <iprt/win/winsock2.h>
+
+#ifdef _MSC_VER
+# pragma warning(push)
+# pragma warning(disable:4668) /* 'NDIS_SUPPORT_NDIS6' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif' */
+# if _MSC_VER >= 1800 /*RT_MSC_VER_VC120*/
+# pragma warning(disable:4005) /* sdk/v7.1/include/sal_supp.h(57) : warning C4005: '__useHeader' : macro redefinition */
+# pragma warning(disable:4255) /* windef.h(227) : warning C4255: 'NEARPROC' : no function prototype given: converting '()' to '(void)' */
+# endif
+# if _MSC_VER >= 1900 /*RT_MSC_VER_VC140*/
+# ifdef __cplusplus
+# pragma warning(disable:5039) /* ws2tcpip.h(874): warning C5039: 'WSAIoctl': pointer or reference to potentially throwing function passed to 'extern "C"' function under -EHc. Undefined behavior may occur if this function throws an exception. */
+# endif
+# endif
+#endif
+
+#include <ws2tcpip.h>
+
+#ifdef _MSC_VER
+# pragma warning(pop)
+#endif
+
+#endif /* !IPRT_INCLUDED_win_ws2tcpip_h */
+
diff --git a/include/iprt/x86-helpers.h b/include/iprt/x86-helpers.h
new file mode 100644
index 00000000..78f88762
--- /dev/null
+++ b/include/iprt/x86-helpers.h
@@ -0,0 +1,261 @@
+/** @file
+ * IPRT - X86 and AMD64 Helpers.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_x86_helpers_h
+#define IPRT_INCLUDED_x86_helpers_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+
+
+/** @defgroup grp_rt_x86_helpers x86 Helper Functions
+ * @ingroup grp_rt_x86
+ * @{
+ */
+
+
+/**
+ * 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) RTX86IsIntelCpu(uint32_t uEBX, uint32_t uECX, uint32_t uEDX)
+{
+ /* 'GenuineIntel' */
+ return uEBX == UINT32_C(0x756e6547) /* 'Genu' */
+ && uEDX == UINT32_C(0x49656e69) /* 'ineI' */
+ && uECX == UINT32_C(0x6c65746e); /* 'ntel' */
+}
+
+
+/**
+ * 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) RTX86IsAmdCpu(uint32_t uEBX, uint32_t uECX, uint32_t uEDX)
+{
+ /* 'AuthenticAMD' */
+ return uEBX == UINT32_C(0x68747541) /* 'Auth' */
+ && uEDX == UINT32_C(0x69746e65) /* 'enti' */
+ && uECX == UINT32_C(0x444d4163); /* 'dAMD' */
+}
+
+
+/**
+ * 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) RTX86IsViaCentaurCpu(uint32_t uEBX, uint32_t uECX, uint32_t uEDX)
+{
+ /* 'CentaurHauls' */
+ return uEBX == UINT32_C(0x746e6543) /* 'Cent' */
+ && uEDX == UINT32_C(0x48727561) /* 'aurH' */
+ && uECX == UINT32_C(0x736c7561); /* 'auls' */
+}
+
+
+/**
+ * Tests if it a Shanghai 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) RTX86IsShanghaiCpu(uint32_t uEBX, uint32_t uECX, uint32_t uEDX)
+{
+ /* ' Shanghai ' */
+ return uEBX == UINT32_C(0x68532020) /* ' Sh' */
+ && uEDX == UINT32_C(0x68676e61) /* 'angh' */
+ && uECX == UINT32_C(0x20206961); /* 'ai ' */
+}
+
+
+/**
+ * Tests if it a genuine Hygon 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) RTX86IsHygonCpu(uint32_t uEBX, uint32_t uECX, uint32_t uEDX)
+{
+ /* 'HygonGenuine' */
+ return uEBX == UINT32_C(0x6f677948) /* Hygo */
+ && uECX == UINT32_C(0x656e6975) /* uine */
+ && uEDX == UINT32_C(0x6e65476e); /* nGen */
+}
+
+
+/**
+ * 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) RTX86IsValidStdRange(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) RTX86IsValidExtRange(uint32_t uEAX)
+{
+ return uEAX >= UINT32_C(0x80000001) && uEAX <= UINT32_C(0x800fffff);
+}
+
+
+/**
+ * Checks whether ASMCpuId_EAX(0x40000000) 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 0x40000000.
+ *
+ * @note Unlike RTX86IsValidStdRange() and RTX86IsValidExtRange(), a single
+ * leaf is okay here. So, you always need to check the range.
+ * @remarks The upper range limit is take from the intel docs.
+ */
+DECLINLINE(bool) RTX86IsValidHypervisorRange(uint32_t uEAX)
+{
+ return uEAX >= UINT32_C(0x40000000) && uEAX <= UINT32_C(0x4fffffff);
+}
+
+
+/**
+ * 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) RTX86GetCpuFamily(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) RTX86GetCpuModelIntel(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) RTX86GetCpuModelAMD(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 RTX86IsIntelCpu() or
+ * RTX86IsIntelCpu().
+ */
+DECLINLINE(uint32_t) RTX86GetCpuModel(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) RTX86GetCpuStepping(uint32_t uEAX)
+{
+ return uEAX & 0xf;
+}
+
+
+/** @} */
+#endif /* !IPRT_INCLUDED_x86_helpers_h */
+
diff --git a/include/iprt/x86.h b/include/iprt/x86.h
new file mode 100644
index 00000000..fe4e8ddf
--- /dev/null
+++ b/include/iprt/x86.h
@@ -0,0 +1,4860 @@
+/** @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-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_x86_h
+#define IPRT_INCLUDED_x86_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#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 and sys/controlregs.h
+ * defining MSR_IA32_FLUSH_CMD */
+#ifdef RT_OS_SOLARIS
+# undef CS
+# undef DS
+# undef MSR_IA32_FLUSH_CMD
+#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)
+#define X86_EFL_PF_BIT 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)
+#define X86_EFL_TF_BIT 8
+/** Bit 9 - IF - Interrupt flag - System flag. */
+#define X86_EFL_IF RT_BIT_32(9)
+#define X86_EFL_IF_BIT 9
+/** Bit 10 - DF - Direction flag - Control flag. */
+#define X86_EFL_DF RT_BIT_32(10)
+#define X86_EFL_DF_BIT 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)
+#define X86_EFL_NT_BIT 14
+/** Bit 16 - RF - Resume flag - System flag. */
+#define X86_EFL_RF RT_BIT_32(16)
+#define X86_EFL_RF_BIT 16
+/** Bit 17 - VM - Virtual 8086 mode - System flag. */
+#define X86_EFL_VM RT_BIT_32(17)
+#define X86_EFL_VM_BIT 17
+/** Bit 18 - AC - Alignment check flag - System flag. Works with CR0.AM. */
+#define X86_EFL_AC RT_BIT_32(18)
+#define X86_EFL_AC_BIT 18
+/** Bit 19 - VIF - Virtual interrupt flag - System flag. */
+#define X86_EFL_VIF RT_BIT_32(19)
+#define X86_EFL_VIF_BIT 19
+/** Bit 20 - VIP - Virtual interrupt pending flag - System flag. */
+#define X86_EFL_VIP RT_BIT_32(20)
+#define X86_EFL_VIP_BIT 20
+/** Bit 21 - ID - CPUID flag - System flag. If this responds to flipping CPUID is supported. */
+#define X86_EFL_ID RT_BIT_32(21)
+#define X86_EFL_ID_BIT 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)
+/** Read as 0 bits, excluding bits 31:22.
+ * Bits 3, 5, 15, and 22 thru 31. */
+#define X86_EFL_RAZ_MASK UINT32_C(0xffc08028)
+/** Read as 0 bits, excluding bits 31:22.
+ * Bits 3, 5 and 15. */
+#define X86_EFL_RAZ_LO_MASK UINT32_C(0x00008028)
+/** 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 */
+
+#define X86_CPUID_VENDOR_SHANGHAI_EBX 0x68532020 /* Sh */
+#define X86_CPUID_VENDOR_SHANGHAI_ECX 0x20206961 /* ai */
+#define X86_CPUID_VENDOR_SHANGHAI_EDX 0x68676e61 /* angh */
+
+#define X86_CPUID_VENDOR_HYGON_EBX 0x6f677948 /* Hygo */
+#define X86_CPUID_VENDOR_HYGON_ECX 0x656e6975 /* uine */
+#define X86_CPUID_VENDOR_HYGON_EDX 0x6e65476e /* nGen */
+/** @} */
+
+
+/** @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)
+/** ECX Bit 2 - UIMP - Supports user mode instruction prevention. */
+#define X86_CPUID_STEXT_FEATURE_ECX_UMIP RT_BIT_32(2)
+/** ECX Bit 3 - PKU - Supports protection keys for user-mode pages. */
+#define X86_CPUID_STEXT_FEATURE_ECX_PKU RT_BIT_32(3)
+/** ECX Bit 4 - OSPKE - Protection keys for user mode pages enabled. */
+#define X86_CPUID_STEXT_FEATURE_ECX_OSPKE RT_BIT_32(4)
+/** ECX Bits 17-21 - MAWAU - Value used by BNDLDX and BNDSTX. */
+#define X86_CPUID_STEXT_FEATURE_ECX_MAWAU UINT32_C(0x003e0000)
+/** ECX Bit 22 - RDPID - Support pread process ID. */
+#define X86_CPUID_STEXT_FEATURE_ECX_RDPID RT_BIT_32(2)
+/** ECX Bit 30 - SGX_LC - Supports SGX launch configuration. */
+#define X86_CPUID_STEXT_FEATURE_ECX_SGX_LC RT_BIT_32(30)
+
+/** EDX Bit 10 - MD_CLEAR - Supports flushing MDS related buffers. */
+#define X86_CPUID_STEXT_FEATURE_EDX_MD_CLEAR RT_BIT_32(10)
+/** EDX Bit 26 - IBRS & IBPB - Supports the IBRS flag in IA32_SPEC_CTRL and
+ * IBPB command in IA32_PRED_CMD. */
+#define X86_CPUID_STEXT_FEATURE_EDX_IBRS_IBPB RT_BIT_32(26)
+/** EDX Bit 27 - IBRS & IBPB - Supports the STIBP flag in IA32_SPEC_CTRL. */
+#define X86_CPUID_STEXT_FEATURE_EDX_STIBP RT_BIT_32(27)
+/** EDX Bit 28 - FLUSH_CMD - Supports IA32_FLUSH_CMD MSR. */
+#define X86_CPUID_STEXT_FEATURE_EDX_FLUSH_CMD RT_BIT_32(28)
+/** EDX Bit 29 - ARCHCAP - Supports the IA32_ARCH_CAPABILITIES MSR. */
+#define X86_CPUID_STEXT_FEATURE_EDX_ARCHCAP RT_BIT_32(29)
+/** EDX Bit 31 - SSBD - Supports the SSBD flag in IA32_SPEC_CTRL. */
+#define X86_CPUID_STEXT_FEATURE_EDX_SSBD RT_BIT_32(31)
+
+/** @} */
+
+
+/** @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 extended feature extensions ID (EBX).
+ * CPUID query with EAX=0x80000008.
+ * @{
+ */
+/** Bit 0 - CLZERO - Clear zero instruction. */
+#define X86_CPUID_AMD_EFEID_EBX_CLZERO RT_BIT_32(0)
+/** Bit 1 - IRPerf - Instructions retired count support. */
+#define X86_CPUID_AMD_EFEID_EBX_IRPERF RT_BIT_32(1)
+/** Bit 2 - XSaveErPtr - Always XSAVE* and XRSTR* error pointers. */
+#define X86_CPUID_AMD_EFEID_EBX_XSAVE_ER_PTR RT_BIT_32(2)
+/** Bit 4 - RDPRU - Supports the RDPRU instruction. */
+#define X86_CPUID_AMD_EFEID_EBX_RDPRU RT_BIT_32(4)
+/** Bit 8 - MCOMMIT - Supports the MCOMMIT instruction. */
+#define X86_CPUID_AMD_EFEID_EBX_MCOMMIT RT_BIT_32(8)
+/* AMD pipeline length: 9 feature bits ;-) */
+/** Bit 12 - IBPB - Supports the IBPB command in IA32_PRED_CMD. */
+#define X86_CPUID_AMD_EFEID_EBX_IBPB RT_BIT_32(12)
+/** Bit 14 - IBRS - Supports the IBRS bit in IA32_SPEC_CTRL. */
+#define X86_CPUID_AMD_EFEID_EBX_IBRS RT_BIT_32(14)
+/** Bit 15 - STIBP - Supports the STIBP bit in IA32_SPEC_CTRL. */
+#define X86_CPUID_AMD_EFEID_EBX_STIBP RT_BIT_32(15)
+/** Bit 16 - IBRS always on mode - IBRS should be set once during boot only. */
+#define X86_CPUID_AMD_EFEID_EBX_IBRS_ALWAYS_ON RT_BIT_32(16)
+/** Bit 17 - STIBP always on mode - STIBP should be set once during boot only. */
+#define X86_CPUID_AMD_EFEID_EBX_STIBP_ALWAYS_ON RT_BIT_32(17)
+/** Bit 18 - IBRS preferred - IBRS is preferred over software mitigations. */
+#define X86_CPUID_AMD_EFEID_EBX_IBRS_PREFERRED RT_BIT_32(18)
+/** Bit 24 - Speculative Store Bypass Disable supported in SPEC_CTL. */
+#define X86_CPUID_AMD_EFEID_EBX_SPEC_CTRL_SSBD RT_BIT_32(24)
+/** Bit 25 - Speculative Store Bypass Disable supported in VIRT_SPEC_CTL. */
+#define X86_CPUID_AMD_EFEID_EBX_VIRT_SPEC_CTRL_SSBD RT_BIT_32(25)
+/** Bit 26 - Speculative Store Bypass Disable not required. */
+#define X86_CPUID_AMD_EFEID_EBX_NO_SSBD_REQUIRED RT_BIT_32(26)
+/** @} */
+
+
+/** @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 - DecodeAssists - Indicate decode assists is supported. */
+#define X86_CPUID_SVM_FEATURE_EDX_DECODE_ASSISTS 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)
+/** Bit 15 - VMSAVEvirt - Supports virtualized VMSAVE/VMLOAD. */
+#define X86_CPUID_SVM_FEATURE_EDX_VIRT_VMSAVE_VMLOAD RT_BIT(15)
+/** Bit 16 - VGIF - Supports virtualized GIF. */
+#define X86_CPUID_SVM_FEATURE_EDX_VGIF RT_BIT(16)
+/** Bit 17 - GMET - Supports Guest Mode Execute Trap Extensions. */
+#define X86_CPUID_SVM_FEATURE_EDX_GMET RT_BIT(17)
+/** Bit 19 - SSSCheck - SVM supervisor shadow stack restrictions. */
+#define X86_CPUID_SVM_FEATURE_EDX_SSSCHECK RT_BIT(19)
+/** Bit 20 - SpecCtrl - Supports SPEC_CTRL Virtualization. */
+#define X86_CPUID_SVM_FEATURE_EDX_SPEC_CTRL RT_BIT(20)
+/** Bit 23 - HOST_MCE_OVERRIDE - Supports host \#MC exception override. */
+#define X86_CPUID_SVM_FEATURE_EDX_HOST_MCE_OVERRIDE RT_BIT(23)
+/** Bit 24 - TlbiCtl - Supports INVLPGB/TLBSYNC in VMCB and TLBSYNC intercept. */
+#define X86_CPUID_SVM_FEATURE_EDX_TLBICTL RT_BIT(24)
+/** @} */
+
+
+/** @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)
+#define X86_CR0_BIT_PG 31 /**< Bit number of X86_CR0_PG */
+/** @} */
+
+
+/** @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 PML4 page number.
+ * @note This is a maxed out mask, the actual acceptable CR3 value can
+ * be lower depending on the PhysAddrSize from CPUID Fn8000_0008. */
+#define X86_CR3_AMD64_PAGE_MASK UINT64_C(0x000ffffffffff000)
+/** Bits 12-51 - - Intel EPT PML4 page number (EPTP).
+ * @note This is a maxed out mask, the actual acceptable CR3/EPTP value can
+ * be lower depending on the PhysAddrSize from CPUID Fn8000_0008. */
+#define X86_CR3_EPT_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 11 - UMIP - User-Mode Instruction Prevention. */
+#define X86_CR4_UMIP RT_BIT_32(11)
+/** 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 16 - FSGSBASE - Read/write FSGSBASE instructions Enable. */
+#define X86_CR4_FSGSBASE RT_BIT_32(16)
+/** 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)
+/** Bit 23 - CET - Control-flow Enhancement Technology enabled. */
+#define X86_CR4_CET RT_BIT_32(23)
+/** @} */
+
+
+/** @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)
+/** Bit 16 - RTM - Cleared if debug exception inside RTM (@sa X86_DR7_RTM). */
+#define X86_DR6_RTM RT_BIT_32(16)
+/** 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 1s in DR6, when RTM is supported. */
+#define X86_DR6_RA1_MASK_RTM UINT64_C(0xfffe0ff0)
+/** 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 - Global 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 11 - RTM - Enable advanced debugging of RTM transactions.
+ * Requires IA32_DEBUGCTL.RTM=1 too, and RTM HW support of course. */
+#define X86_DR7_RTM RT_BIT_32(11)
+/** 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 UINT32_C(0)
+/** Break on write only. */
+#define X86_DR7_RW_WO UINT32_C(1)
+/** Break on I/O read/write. This is only defined if CR4.DE is set. */
+#define X86_DR7_RW_IO UINT32_C(2)
+/** Break on read or write (but not instruction fetches). */
+#define X86_DR7_RW_RW UINT32_C(3)
+/** @} */
+
+/** 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 the RW and LEN fields are set up for an instruction breakpoint.
+ * @note This does not check if it's enabled. */
+# define X86_DR7_IS_EO_CFG(a_uDR7, a_iBp) ( ((a_uDR7) & (UINT32_C(0x000f0000) << ((a_iBp) * 4))) == 0 )
+/** Checks if an instruction breakpoint is enabled and configured correctly.
+ * @sa X86_DR7_IS_EO_CFG, X86_DR7_ANY_EO_ENABLED */
+# define X86_DR7_IS_EO_ENABLED(a_uDR7, a_iBp) \
+ ( ((a_uDR7) & (UINT32_C(0x03) << ((a_iBp) * 2))) != 0 && X86_DR7_IS_EO_CFG(a_uDR7, a_iBp) )
+/** Checks if there are any instruction fetch breakpoint types configured in the
+ * RW and LEN registers.
+ * @sa X86_DR7_IS_EO_CFG, X86_DR7_IS_EO_ENABLED */
+# define X86_DR7_ANY_EO_ENABLED(a_uDR7) \
+ ( (((a_uDR7) & UINT32_C(0x03)) != 0 && ((a_uDR7) & UINT32_C(0x000f0000)) == 0) \
+ || (((a_uDR7) & UINT32_C(0x0c)) != 0 && ((a_uDR7) & UINT32_C(0x00f00000)) == 0) \
+ || (((a_uDR7) & UINT32_C(0x30)) != 0 && ((a_uDR7) & UINT32_C(0x0f000000)) == 0) \
+ || (((a_uDR7) & UINT32_C(0xc0)) != 0 && ((a_uDR7) & UINT32_C(0xf0000000)) == 0) )
+
+/** 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 UINT32_C(0)
+#define X86_DR7_LEN_WORD UINT32_C(1)
+#define X86_DR7_LEN_QWORD UINT32_C(2) /**< AMD64 long mode only. */
+#define X86_DR7_LEN_DWORD UINT32_C(3)
+/** @} */
+
+/** 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
+/** Feature control - Lock MSR from writes (R/W0). */
+#define MSR_IA32_FEATURE_CONTROL_LOCK RT_BIT_64(0)
+/** Feature control - Enable VMX inside SMX operation (R/WL). */
+#define MSR_IA32_FEATURE_CONTROL_SMX_VMXON RT_BIT_64(1)
+/** Feature control - Enable VMX outside SMX operation (R/WL). */
+#define MSR_IA32_FEATURE_CONTROL_VMXON RT_BIT_64(2)
+/** Feature control - SENTER local functions enable (R/WL). */
+#define MSR_IA32_FEATURE_CONTROL_SENTER_LOCAL_FN_0 RT_BIT_64(8)
+#define MSR_IA32_FEATURE_CONTROL_SENTER_LOCAL_FN_1 RT_BIT_64(9)
+#define MSR_IA32_FEATURE_CONTROL_SENTER_LOCAL_FN_2 RT_BIT_64(10)
+#define MSR_IA32_FEATURE_CONTROL_SENTER_LOCAL_FN_3 RT_BIT_64(11)
+#define MSR_IA32_FEATURE_CONTROL_SENTER_LOCAL_FN_4 RT_BIT_64(12)
+#define MSR_IA32_FEATURE_CONTROL_SENTER_LOCAL_FN_5 RT_BIT_64(13)
+#define MSR_IA32_FEATURE_CONTROL_SENTER_LOCAL_FN_6 RT_BIT_64(14)
+/** Feature control - SENTER global enable (R/WL). */
+#define MSR_IA32_FEATURE_CONTROL_SENTER_GLOBAL_EN RT_BIT_64(15)
+/** Feature control - SGX launch control enable (R/WL). */
+#define MSR_IA32_FEATURE_CONTROL_SGX_LAUNCH_EN RT_BIT_64(17)
+/** Feature control - SGX global enable (R/WL). */
+#define MSR_IA32_FEATURE_CONTROL_SGX_GLOBAL_EN RT_BIT_64(18)
+/** Feature control - LMCE on (R/WL). */
+#define MSR_IA32_FEATURE_CONTROL_LMCE RT_BIT_64(20)
+
+/** Per-processor TSC adjust MSR. */
+#define MSR_IA32_TSC_ADJUST 0x3B
+
+/** Spectre control register.
+ * Logical processor scope. Reset value 0, unaffected by SIPI & INIT. */
+#define MSR_IA32_SPEC_CTRL 0x48
+/** IBRS - Indirect branch restricted speculation. */
+#define MSR_IA32_SPEC_CTRL_F_IBRS RT_BIT_32(0)
+/** STIBP - Single thread indirect branch predictors. */
+#define MSR_IA32_SPEC_CTRL_F_STIBP RT_BIT_32(1)
+/** SSBD - Speculative Store Bypass Disable. */
+#define MSR_IA32_SPEC_CTRL_F_SSBD RT_BIT_32(2)
+
+/** Prediction command register.
+ * Write only, logical processor scope, no state since write only. */
+#define MSR_IA32_PRED_CMD 0x49
+/** IBPB - Indirect branch prediction barrie when written as 1. */
+#define MSR_IA32_PRED_CMD_F_IBPB RT_BIT_32(0)
+
+/** 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
+/** SMM control - Valid. */
+#define MSR_IA32_SMM_MONITOR_VALID RT_BIT_64(0)
+/** SMM control - VMXOFF unblocks SMI. */
+#define MSR_IA32_SMM_MONITOR_VMXOFF_UNBLOCK_SMI RT_BIT_64(2)
+/** SMM control - MSEG base physical address. */
+#define MSR_IA32_SMM_MONITOR_MSGEG_PHYSADDR(a) (((a) >> 12) & UINT64_C(0xfffff))
+
+/** SMBASE - Base address of SMRANGE image (Read-only, SMM only). */
+#define MSR_IA32_SMBASE 0x9E
+
+/** 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
+/** General performance counter no. 4. */
+#define MSR_IA32_PMC4 0xC5
+/** General performance counter no. 5. */
+#define MSR_IA32_PMC5 0xC6
+/** General performance counter no. 6. */
+#define MSR_IA32_PMC6 0xC7
+/** General performance counter no. 7. */
+#define MSR_IA32_PMC7 0xC8
+
+/** 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
+
+/** Architecture capabilities (bugfixes). */
+#define MSR_IA32_ARCH_CAPABILITIES UINT32_C(0x10a)
+/** CPU is no subject to meltdown problems. */
+#define MSR_IA32_ARCH_CAP_F_RDCL_NO RT_BIT_32(0)
+/** CPU has better IBRS and you can leave it on all the time. */
+#define MSR_IA32_ARCH_CAP_F_IBRS_ALL RT_BIT_32(1)
+/** CPU has return stack buffer (RSB) override. */
+#define MSR_IA32_ARCH_CAP_F_RSBO RT_BIT_32(2)
+/** Virtual machine monitors need not flush the level 1 data cache on VM entry.
+ * This is also the case when MSR_IA32_ARCH_CAP_F_RDCL_NO is set. */
+#define MSR_IA32_ARCH_CAP_F_VMM_NEED_NOT_FLUSH_L1D RT_BIT_32(3)
+/** CPU does not suffer from MDS issues. */
+#define MSR_IA32_ARCH_CAP_F_MDS_NO RT_BIT_32(4)
+
+/** Flush command register. */
+#define MSR_IA32_FLUSH_CMD UINT32_C(0x10b)
+/** Flush the level 1 data cache when this bit is written. */
+#define MSR_IA32_FLUSH_CMD_F_L1D RT_BIT_32(0)
+
+/** 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
+/** Default PAT MSR value on processor powerup / reset (see Intel spec. 11.12.4
+ * "Programming the PAT", AMD spec. 7.8.2 "PAT Indexing") */
+#define MSR_IA32_CR_PAT_INIT_VAL UINT64_C(0x0007040600070406)
+
+/** Performance event select MSRs. (Intel only) */
+#define MSR_IA32_PERFEVTSEL0 0x186
+#define MSR_IA32_PERFEVTSEL1 0x187
+#define MSR_IA32_PERFEVTSEL2 0x188
+#define MSR_IA32_PERFEVTSEL3 0x189
+
+/** 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
+
+/** Offcore response event select registers. */
+#define MSR_OFFCORE_RSP_0 0x1a6
+#define MSR_OFFCORE_RSP_1 0x1a7
+
+/** 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)
+/** Last branch record. */
+#define MSR_IA32_DEBUGCTL_LBR RT_BIT_64(0)
+/** Branch trace flag (single step on branches). */
+#define MSR_IA32_DEBUGCTL_BTF RT_BIT_64(1)
+/** Performance monitoring pin control (AMD only). */
+#define MSR_IA32_DEBUGCTL_PB0 RT_BIT_64(2)
+#define MSR_IA32_DEBUGCTL_PB1 RT_BIT_64(3)
+#define MSR_IA32_DEBUGCTL_PB2 RT_BIT_64(4)
+#define MSR_IA32_DEBUGCTL_PB3 RT_BIT_64(5)
+/** Trace message enable (Intel only). */
+#define MSR_IA32_DEBUGCTL_TR RT_BIT_64(6)
+/** Branch trace store (Intel only). */
+#define MSR_IA32_DEBUGCTL_BTS RT_BIT_64(7)
+/** Branch trace interrupt (Intel only). */
+#define MSR_IA32_DEBUGCTL_BTINT RT_BIT_64(8)
+/** Branch trace off in privileged code (Intel only). */
+#define MSR_IA32_DEBUGCTL_BTS_OFF_OS RT_BIT_64(9)
+/** Branch trace off in user code (Intel only). */
+#define MSR_IA32_DEBUGCTL_BTS_OFF_USER RT_BIT_64(10)
+/** Freeze LBR on PMI flag (Intel only). */
+#define MSR_IA32_DEBUGCTL_FREEZE_LBR_ON_PMI RT_BIT_64(11)
+/** Freeze PERFMON on PMI flag (Intel only). */
+#define MSR_IA32_DEBUGCTL_FREEZE_PERFMON_ON_PMI RT_BIT_64(12)
+/** Freeze while SMM enabled (Intel only). */
+#define MSR_IA32_DEBUGCTL_FREEZE_WHILE_SMM_EM RT_BIT_64(14)
+/** Advanced debugging of RTM regions (Intel only). */
+#define MSR_IA32_DEBUGCTL_RTM RT_BIT_64(15)
+/** Debug control MSR valid bits (Intel only). */
+#define MSR_IA32_DEBUGCTL_VALID_MASK_INTEL ( MSR_IA32_DEBUGCTL_LBR | MSR_IA32_DEBUGCTL_BTF | MSR_IA32_DEBUGCTL_TR \
+ | MSR_IA32_DEBUGCTL_BTS | MSR_IA32_DEBUGCTL_BTINT | MSR_IA32_DEBUGCTL_BTS_OFF_OS \
+ | MSR_IA32_DEBUGCTL_BTS_OFF_USER | MSR_IA32_DEBUGCTL_FREEZE_LBR_ON_PMI \
+ | MSR_IA32_DEBUGCTL_FREEZE_PERFMON_ON_PMI | MSR_IA32_DEBUGCTL_FREEZE_WHILE_SMM_EM \
+ | MSR_IA32_DEBUGCTL_RTM)
+
+/** @name Last branch registers for P4 and Xeon, models 0 thru 2.
+ * @{ */
+#define MSR_P4_LASTBRANCH_0 0x1db
+#define MSR_P4_LASTBRANCH_1 0x1dc
+#define MSR_P4_LASTBRANCH_2 0x1dd
+#define MSR_P4_LASTBRANCH_3 0x1de
+
+/** LBR Top-of-stack MSR (index to most recent record). */
+#define MSR_P4_LASTBRANCH_TOS 0x1da
+/** @} */
+
+/** @name Last branch registers for Core 2 and related Xeons.
+ * @{ */
+#define MSR_CORE2_LASTBRANCH_0_FROM_IP 0x40
+#define MSR_CORE2_LASTBRANCH_1_FROM_IP 0x41
+#define MSR_CORE2_LASTBRANCH_2_FROM_IP 0x42
+#define MSR_CORE2_LASTBRANCH_3_FROM_IP 0x43
+
+#define MSR_CORE2_LASTBRANCH_0_TO_IP 0x60
+#define MSR_CORE2_LASTBRANCH_1_TO_IP 0x61
+#define MSR_CORE2_LASTBRANCH_2_TO_IP 0x62
+#define MSR_CORE2_LASTBRANCH_3_TO_IP 0x63
+
+/** LBR Top-of-stack MSR (index to most recent record). */
+#define MSR_CORE2_LASTBRANCH_TOS 0x1c9
+/** @} */
+
+/** @name Last branch registers.
+ * @{ */
+#define MSR_LASTBRANCH_0_FROM_IP 0x680
+#define MSR_LASTBRANCH_1_FROM_IP 0x681
+#define MSR_LASTBRANCH_2_FROM_IP 0x682
+#define MSR_LASTBRANCH_3_FROM_IP 0x683
+#define MSR_LASTBRANCH_4_FROM_IP 0x684
+#define MSR_LASTBRANCH_5_FROM_IP 0x685
+#define MSR_LASTBRANCH_6_FROM_IP 0x686
+#define MSR_LASTBRANCH_7_FROM_IP 0x687
+#define MSR_LASTBRANCH_8_FROM_IP 0x688
+#define MSR_LASTBRANCH_9_FROM_IP 0x689
+#define MSR_LASTBRANCH_10_FROM_IP 0x68a
+#define MSR_LASTBRANCH_11_FROM_IP 0x68b
+#define MSR_LASTBRANCH_12_FROM_IP 0x68c
+#define MSR_LASTBRANCH_13_FROM_IP 0x68d
+#define MSR_LASTBRANCH_14_FROM_IP 0x68e
+#define MSR_LASTBRANCH_15_FROM_IP 0x68f
+#define MSR_LASTBRANCH_16_FROM_IP 0x690
+#define MSR_LASTBRANCH_17_FROM_IP 0x691
+#define MSR_LASTBRANCH_18_FROM_IP 0x692
+#define MSR_LASTBRANCH_19_FROM_IP 0x693
+#define MSR_LASTBRANCH_20_FROM_IP 0x694
+#define MSR_LASTBRANCH_21_FROM_IP 0x695
+#define MSR_LASTBRANCH_22_FROM_IP 0x696
+#define MSR_LASTBRANCH_23_FROM_IP 0x697
+#define MSR_LASTBRANCH_24_FROM_IP 0x698
+#define MSR_LASTBRANCH_25_FROM_IP 0x699
+#define MSR_LASTBRANCH_26_FROM_IP 0x69a
+#define MSR_LASTBRANCH_27_FROM_IP 0x69b
+#define MSR_LASTBRANCH_28_FROM_IP 0x69c
+#define MSR_LASTBRANCH_29_FROM_IP 0x69d
+#define MSR_LASTBRANCH_30_FROM_IP 0x69e
+#define MSR_LASTBRANCH_31_FROM_IP 0x69f
+
+#define MSR_LASTBRANCH_0_TO_IP 0x6c0
+#define MSR_LASTBRANCH_1_TO_IP 0x6c1
+#define MSR_LASTBRANCH_2_TO_IP 0x6c2
+#define MSR_LASTBRANCH_3_TO_IP 0x6c3
+#define MSR_LASTBRANCH_4_TO_IP 0x6c4
+#define MSR_LASTBRANCH_5_TO_IP 0x6c5
+#define MSR_LASTBRANCH_6_TO_IP 0x6c6
+#define MSR_LASTBRANCH_7_TO_IP 0x6c7
+#define MSR_LASTBRANCH_8_TO_IP 0x6c8
+#define MSR_LASTBRANCH_9_TO_IP 0x6c9
+#define MSR_LASTBRANCH_10_TO_IP 0x6ca
+#define MSR_LASTBRANCH_11_TO_IP 0x6cb
+#define MSR_LASTBRANCH_12_TO_IP 0x6cc
+#define MSR_LASTBRANCH_13_TO_IP 0x6cd
+#define MSR_LASTBRANCH_14_TO_IP 0x6ce
+#define MSR_LASTBRANCH_15_TO_IP 0x6cf
+#define MSR_LASTBRANCH_16_TO_IP 0x6d0
+#define MSR_LASTBRANCH_17_TO_IP 0x6d1
+#define MSR_LASTBRANCH_18_TO_IP 0x6d2
+#define MSR_LASTBRANCH_19_TO_IP 0x6d3
+#define MSR_LASTBRANCH_20_TO_IP 0x6d4
+#define MSR_LASTBRANCH_21_TO_IP 0x6d5
+#define MSR_LASTBRANCH_22_TO_IP 0x6d6
+#define MSR_LASTBRANCH_23_TO_IP 0x6d7
+#define MSR_LASTBRANCH_24_TO_IP 0x6d8
+#define MSR_LASTBRANCH_25_TO_IP 0x6d9
+#define MSR_LASTBRANCH_26_TO_IP 0x6da
+#define MSR_LASTBRANCH_27_TO_IP 0x6db
+#define MSR_LASTBRANCH_28_TO_IP 0x6dc
+#define MSR_LASTBRANCH_29_TO_IP 0x6dd
+#define MSR_LASTBRANCH_30_TO_IP 0x6de
+#define MSR_LASTBRANCH_31_TO_IP 0x6df
+
+#define MSR_LASTBRANCH_0_INFO 0xdc0
+#define MSR_LASTBRANCH_1_INFO 0xdc1
+#define MSR_LASTBRANCH_2_INFO 0xdc2
+#define MSR_LASTBRANCH_3_INFO 0xdc3
+#define MSR_LASTBRANCH_4_INFO 0xdc4
+#define MSR_LASTBRANCH_5_INFO 0xdc5
+#define MSR_LASTBRANCH_6_INFO 0xdc6
+#define MSR_LASTBRANCH_7_INFO 0xdc7
+#define MSR_LASTBRANCH_8_INFO 0xdc8
+#define MSR_LASTBRANCH_9_INFO 0xdc9
+#define MSR_LASTBRANCH_10_INFO 0xdca
+#define MSR_LASTBRANCH_11_INFO 0xdcb
+#define MSR_LASTBRANCH_12_INFO 0xdcc
+#define MSR_LASTBRANCH_13_INFO 0xdcd
+#define MSR_LASTBRANCH_14_INFO 0xdce
+#define MSR_LASTBRANCH_15_INFO 0xdcf
+#define MSR_LASTBRANCH_16_INFO 0xdd0
+#define MSR_LASTBRANCH_17_INFO 0xdd1
+#define MSR_LASTBRANCH_18_INFO 0xdd2
+#define MSR_LASTBRANCH_19_INFO 0xdd3
+#define MSR_LASTBRANCH_20_INFO 0xdd4
+#define MSR_LASTBRANCH_21_INFO 0xdd5
+#define MSR_LASTBRANCH_22_INFO 0xdd6
+#define MSR_LASTBRANCH_23_INFO 0xdd7
+#define MSR_LASTBRANCH_24_INFO 0xdd8
+#define MSR_LASTBRANCH_25_INFO 0xdd9
+#define MSR_LASTBRANCH_26_INFO 0xdda
+#define MSR_LASTBRANCH_27_INFO 0xddb
+#define MSR_LASTBRANCH_28_INFO 0xddc
+#define MSR_LASTBRANCH_29_INFO 0xddd
+#define MSR_LASTBRANCH_30_INFO 0xdde
+#define MSR_LASTBRANCH_31_INFO 0xddf
+
+/** LBR branch tracking selection MSR. */
+#define MSR_LASTBRANCH_SELECT 0x1c8
+/** LBR Top-of-stack MSR (index to most recent record). */
+#define MSR_LASTBRANCH_TOS 0x1c9
+/** @} */
+
+/** @name Last event record registers.
+ * @{ */
+/** Last event record source IP register. */
+#define MSR_LER_FROM_IP 0x1dd
+/** Last event record destination IP register. */
+#define MSR_LER_TO_IP 0x1de
+/** @} */
+
+/** Intel TSX (Transactional Synchronization Extensions) control MSR. */
+#define MSR_IA32_TSX_CTRL 0x122
+
+/** Variable range MTRRs.
+ * @{ */
+#define MSR_IA32_MTRR_PHYSBASE0 0x200
+#define MSR_IA32_MTRR_PHYSMASK0 0x201
+#define MSR_IA32_MTRR_PHYSBASE1 0x202
+#define MSR_IA32_MTRR_PHYSMASK1 0x203
+#define MSR_IA32_MTRR_PHYSBASE2 0x204
+#define MSR_IA32_MTRR_PHYSMASK2 0x205
+#define MSR_IA32_MTRR_PHYSBASE3 0x206
+#define MSR_IA32_MTRR_PHYSMASK3 0x207
+#define MSR_IA32_MTRR_PHYSBASE4 0x208
+#define MSR_IA32_MTRR_PHYSMASK4 0x209
+#define MSR_IA32_MTRR_PHYSBASE5 0x20a
+#define MSR_IA32_MTRR_PHYSMASK5 0x20b
+#define MSR_IA32_MTRR_PHYSBASE6 0x20c
+#define MSR_IA32_MTRR_PHYSMASK6 0x20d
+#define MSR_IA32_MTRR_PHYSBASE7 0x20e
+#define MSR_IA32_MTRR_PHYSMASK7 0x20f
+#define MSR_IA32_MTRR_PHYSBASE8 0x210
+#define MSR_IA32_MTRR_PHYSMASK8 0x211
+#define MSR_IA32_MTRR_PHYSBASE9 0x212
+#define MSR_IA32_MTRR_PHYSMASK9 0x213
+/** @} */
+
+/** Fixed range MTRRs.
+ * @{ */
+#define MSR_IA32_MTRR_FIX64K_00000 0x250
+#define MSR_IA32_MTRR_FIX16K_80000 0x258
+#define MSR_IA32_MTRR_FIX16K_A0000 0x259
+#define MSR_IA32_MTRR_FIX4K_C0000 0x268
+#define MSR_IA32_MTRR_FIX4K_C8000 0x269
+#define MSR_IA32_MTRR_FIX4K_D0000 0x26a
+#define MSR_IA32_MTRR_FIX4K_D8000 0x26b
+#define MSR_IA32_MTRR_FIX4K_E0000 0x26c
+#define MSR_IA32_MTRR_FIX4K_E8000 0x26d
+#define MSR_IA32_MTRR_FIX4K_F0000 0x26e
+#define MSR_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 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 VM-exit controls. */
+#define MSR_IA32_VMX_EXIT_CTLS 0x483
+/** Allowed settings for the VM-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 secondary processor-based VM-execution controls. */
+#define MSR_IA32_VMX_PROCBASED_CTLS2 0x48B
+/** EPT capabilities. */
+#define MSR_IA32_VMX_EPT_VPID_CAP 0x48C
+/** Allowed settings of all pin-based VM execution controls. */
+#define MSR_IA32_VMX_TRUE_PINBASED_CTLS 0x48D
+/** Allowed settings of all proc-based VM execution controls. */
+#define MSR_IA32_VMX_TRUE_PROCBASED_CTLS 0x48E
+/** Allowed settings of all VMX exit controls. */
+#define MSR_IA32_VMX_TRUE_EXIT_CTLS 0x48F
+/** Allowed settings of all VMX entry controls. */
+#define MSR_IA32_VMX_TRUE_ENTRY_CTLS 0x490
+/** Allowed settings for the VM-function controls. */
+#define MSR_IA32_VMX_VMFUNC 0x491
+/** Tertiary processor-based VM execution controls. */
+#define MSR_IA32_VMX_PROCBASED_CTLS3 0x492
+/** Secondary VM-exit controls. */
+#define MSR_IA32_VMX_EXIT_CTLS2 0x493
+
+/** Intel PT - Enable and control for trace packet generation. */
+#define MSR_IA32_RTIT_CTL 0x570
+
+/** DS Save Area (R/W). */
+#define MSR_IA32_DS_AREA 0x600
+/** Running Average Power Limit (RAPL) power units. */
+#define MSR_RAPL_POWER_UNIT 0x606
+/** Package C3 Interrupt Response Limit. */
+#define MSR_PKGC3_IRTL 0x60a
+/** Package C6/C7S Interrupt Response Limit 1. */
+#define MSR_PKGC_IRTL1 0x60b
+/** Package C6/C7S Interrupt Response Limit 2. */
+#define MSR_PKGC_IRTL2 0x60c
+/** Package C2 Residency Counter. */
+#define MSR_PKG_C2_RESIDENCY 0x60d
+/** PKG RAPL Power Limit Control. */
+#define MSR_PKG_POWER_LIMIT 0x610
+/** PKG Energy Status. */
+#define MSR_PKG_ENERGY_STATUS 0x611
+/** PKG Perf Status. */
+#define MSR_PKG_PERF_STATUS 0x613
+/** PKG RAPL Parameters. */
+#define MSR_PKG_POWER_INFO 0x614
+/** DRAM RAPL Power Limit Control. */
+#define MSR_DRAM_POWER_LIMIT 0x618
+/** DRAM Energy Status. */
+#define MSR_DRAM_ENERGY_STATUS 0x619
+/** DRAM Performance Throttling Status. */
+#define MSR_DRAM_PERF_STATUS 0x61b
+/** DRAM RAPL Parameters. */
+#define MSR_DRAM_POWER_INFO 0x61c
+/** Package C10 Residency Counter. */
+#define MSR_PKG_C10_RESIDENCY 0x632
+/** PP0 Energy Status. */
+#define MSR_PP0_ENERGY_STATUS 0x639
+/** PP1 Energy Status. */
+#define MSR_PP1_ENERGY_STATUS 0x641
+/** Turbo Activation Ratio. */
+#define MSR_TURBO_ACTIVATION_RATIO 0x64c
+/** Core Performance Limit Reasons. */
+#define MSR_CORE_PERF_LIMIT_REASONS 0x64f
+
+/** 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 0x8FF
+/** 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)
+#define MSR_K6_EFER_BIT_LME 8 /**< Bit number of MSR_K6_EFER_LME */
+/** Bit 10 - LMA - Long mode active. (R) */
+#define MSR_K6_EFER_LMA RT_BIT_32(10)
+#define MSR_K6_EFER_BIT_LMA 10 /**< Bit number of MSR_K6_EFER_LMA */
+/** 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)
+/** Bit 17 - MCOMMIT - Commit Stores to memory. (R/W) */
+#define MSR_K6_EFER_MCOMMIT RT_BIT_32(17)
+
+/** 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)
+
+/** SMM MSRs. */
+#define MSR_K7_SMBASE UINT32_C(0xc0010111)
+#define MSR_K7_SMM_ADDR UINT32_C(0xc0010112)
+#define MSR_K7_SMM_MASK UINT32_C(0xc0010113)
+
+/** 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)
+
+/** Virtualized speculation control for AMD processors.
+ *
+ * Unified interface among different CPU generations.
+ * The VMM will set any architectural MSRs based on the CPU.
+ * See "White Paper: AMD64 Technology Speculative Store Bypass Disable 5.21.18"
+ * (12441_AMD64_SpeculativeStoreBypassDisable_Whitepaper_final.pdf) */
+#define MSR_AMD_VIRT_SPEC_CTL UINT32_C(0xc001011f)
+/** Speculative Store Bypass Disable. */
+# define MSR_AMD_VIRT_SPEC_CTL_F_SSBD RT_BIT(2)
+
+/** @} */
+
+
+/** @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
+
+/** The size of a 1GB page. */
+#define X86_PAGE_1G_SIZE _1G
+/** The page shift of a 1GB page. */
+#define X86_PAGE_1G_SHIFT 30
+/** The 1GB page offset mask. */
+#define X86_PAGE_1G_OFFSET_MASK 0x3fffffff
+/** The 1GB page base mask for virtual addresses. */
+#define X86_PAGE_1G_BASE_MASK UINT64_C(0xffffffffc0000000)
+
+/**
+ * Check if the given address is canonical.
+ */
+#define X86_IS_CANONICAL(a_u64Addr) ((uint64_t)(a_u64Addr) + UINT64_C(0x800000000000) < UINT64_C(0x1000000000000))
+
+/**
+ * Gets the page base mask given the page shift.
+ */
+#define X86_GET_PAGE_BASE_MASK(a_cShift) (UINT64_C(0xffffffffffffffff) << (a_cShift))
+
+/**
+ * Gets the page offset mask given the page shift.
+ */
+#define X86_GET_PAGE_OFFSET_MASK(a_cShift) (~X86_GET_PAGE_BASE_MASK(a_cShift))
+
+
+/** @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;
+#ifndef VBOX_WITHOUT_PAGING_BIT_FIELDS
+ /** Bit field view. */
+ X86PTEBITS n;
+#endif
+ /** 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;
+#ifndef VBOX_WITHOUT_PAGING_BIT_FIELDS
+ /** Bit field view. */
+ X86PTEPAEBITS n;
+#endif
+ /** 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;
+#ifndef VBOX_WITHOUT_PAGING_BIT_FIELDS
+ /** Normal view. */
+ X86PDEBITS n;
+ /** 4MB view (big). */
+ X86PDE4MBITS b;
+#endif
+ /** 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;
+#ifndef VBOX_WITHOUT_PAGING_BIT_FIELDS
+ /** Normal view. */
+ X86PDEPAEBITS n;
+ /** 2MB page view (big). */
+ X86PDE2MPAEBITS b;
+#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];
+} 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 30-51 - - PG - Physical address of the 1GB page referenced by this entry. */
+#define X86_PDPE1G_PG_MASK UINT64_C(0x000fffffc0000000)
+/** 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;
+#ifndef VBOX_WITHOUT_PAGING_BIT_FIELDS
+ /** Normal view. */
+ X86PDPEBITS n;
+ /** AMD64 view. */
+ X86PDPEAMD64BITS lm;
+ /** AMD64 big view. */
+ X86PDPE1GB b;
+#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];
+} 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;
+#ifndef VBOX_WITHOUT_PAGING_BIT_FIELDS
+ /** Normal view. */
+ X86PML4EBITS n;
+#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];
+} 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
+
+/** @} */
+
+/** @} */
+
+/**
+ * Intel PCID invalidation types.
+ */
+/** Individual address invalidation. */
+#define X86_INVPCID_TYPE_INDV_ADDR 0
+/** Single-context invalidation. */
+#define X86_INVPCID_TYPE_SINGLE_CONTEXT 1
+/** All-context including globals invalidation. */
+#define X86_INVPCID_TYPE_ALL_CONTEXT_INCL_GLOBAL 2
+/** All-context excluding globals invalidation. */
+#define X86_INVPCID_TYPE_ALL_CONTEXT_EXCL_GLOBAL 3
+/** The maximum valid invalidation type value. */
+#define X86_INVPCID_TYPE_MAX_VALID X86_INVPCID_TYPE_ALL_CONTEXT_EXCL_GLOBAL
+
+
+/** @name Special FPU integer values.
+ * @{ */
+#define X86_FPU_INT64_INDEFINITE INT64_MIN
+#define X86_FPU_INT32_INDEFINITE INT32_MIN
+#define X86_FPU_INT16_INDEFINITE INT16_MIN
+/** @} */
+
+/**
+ * 32-bit protected mode FSTENV image.
+ */
+typedef struct X86FSTENV32P
+{
+ uint16_t FCW; /**< 0x00 */
+ uint16_t padding1; /**< 0x02 */
+ uint16_t FSW; /**< 0x04 */
+ uint16_t padding2; /**< 0x06 */
+ uint16_t FTW; /**< 0x08 */
+ uint16_t padding3; /**< 0x0a */
+ uint32_t FPUIP; /**< 0x0c */
+ uint16_t FPUCS; /**< 0x10 */
+ uint16_t FOP; /**< 0x12 */
+ uint32_t FPUDP; /**< 0x14 */
+ uint16_t FPUDS; /**< 0x18 */
+ uint16_t padding4; /**< 0x1a */
+} X86FSTENV32P;
+#ifndef VBOX_FOR_DTRACE_LIB
+AssertCompileSize(X86FSTENV32P, 0x1c);
+#endif
+/** 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;
+
+/** FPU (x87) register - v2 with correct size. */
+#pragma pack(1)
+typedef union X86FPUREG2
+{
+ /** MMX view. */
+ uint64_t mmx;
+ /** FPU view - todo. */
+ X86FPUMMX fpu;
+ /** Extended precision floating point view. */
+ RTFLOAT80U r80;
+ /** 8-bit view. */
+ uint8_t au8[10];
+ /** 16-bit view. */
+ uint16_t au16[5];
+ /** 32-bit view. */
+ uint32_t au32[2];
+ /** 64-bit view. */
+ uint64_t au64[1];
+} X86FPUREG2;
+#pragma pack()
+#ifndef VBOX_FOR_DTRACE_LIB
+AssertCompileSize(X86FPUREG2, 10);
+#endif
+/** Pointer to a FPU register - v2. */
+typedef X86FPUREG2 *PX86FPUREG2;
+/** Pointer to a const FPU register - v2. */
+typedef X86FPUREG2 const *PCX86FPUREG2;
+
+/**
+ * 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];
+ /** Signed 8-bit view. */
+ int8_t ai8[16];
+ /** Signed 16-bit view. */
+ int16_t ai16[8];
+ /** Signed 32-bit view. */
+ int32_t ai32[4];
+ /** Signed 64-bit view. */
+ int64_t ai64[2];
+ /** 128-bit view. (yeah, very helpful) */
+ uint128_t au128[1];
+ /** Single precision floating point view. */
+ RTFLOAT32U ar32[4];
+ /** Double precision floating point view. */
+ RTFLOAT64U ar64[2];
+#ifndef VBOX_FOR_DTRACE_LIB
+ /** Confusing nested 128-bit union view (this is what xmm should've been). */
+ RTUINT128U uXmm;
+#endif
+} 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
+{
+ /** YMM register view. */
+ RTUINT256U ymm;
+ /** 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];
+ /** Single precision floating point view. */
+ RTFLOAT32U ar32[8];
+ /** Double precision floating point view. */
+ RTFLOAT64U ar64[4];
+ /** 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];
+ /** Single precision floating point view. */
+ RTFLOAT32U ar32[16];
+ /** Double precision floating point view. */
+ RTFLOAT64U ar64[8];
+ /** 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).
+ */
+#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 - Data pointer. */
+ uint32_t FPUOO;
+ /** 0x18 - FOS. */
+ uint16_t FPUOS;
+ /** 0x0a - Alignment word */
+ uint16_t Dummy4;
+ /** 0x1c - FPU register. */
+ X86FPUREG2 regs[8];
+} X86FPUSTATE;
+#pragma pack()
+AssertCompileSize(X86FPUSTATE, 108);
+/** 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)
+#define X86_FSW_IE_BIT 0
+/** Exception Flag: Denormalized operand. */
+#define X86_FSW_DE RT_BIT_32(1)
+#define X86_FSW_DE_BIT 1
+/** Exception Flag: Zero divide. */
+#define X86_FSW_ZE RT_BIT_32(2)
+#define X86_FSW_ZE_BIT 2
+/** Exception Flag: Overflow. */
+#define X86_FSW_OE RT_BIT_32(3)
+#define X86_FSW_OE_BIT 3
+/** Exception Flag: Underflow. */
+#define X86_FSW_UE RT_BIT_32(4)
+#define X86_FSW_UE_BIT 4
+/** Exception Flag: Precision. */
+#define X86_FSW_PE RT_BIT_32(5)
+#define X86_FSW_PE_BIT 5
+/** Stack fault. */
+#define X86_FSW_SF RT_BIT_32(6)
+#define X86_FSW_SF_BIT 6
+/** Error summary status. */
+#define X86_FSW_ES RT_BIT_32(7)
+#define X86_FSW_ES_BIT 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(X86_FSW_C0_BIT)
+#define X86_FSW_C0_BIT 8
+/** Condition code 1. */
+#define X86_FSW_C1 RT_BIT_32(X86_FSW_C1_BIT)
+#define X86_FSW_C1_BIT 9
+/** Condition code 2. */
+#define X86_FSW_C2 RT_BIT_32(X86_FSW_C2_BIT)
+#define X86_FSW_C2_BIT 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)
+/** Get the TOP value offsetted by a_iSt (0-7). */
+#define X86_FSW_TOP_GET_ST(a_uFsw, a_iSt) ((((a_uFsw) >> X86_FSW_TOP_SHIFT) + (a_iSt)) & X86_FSW_TOP_SMASK)
+/** Condition code 3. */
+#define X86_FSW_C3 RT_BIT_32(X86_FSW_C3_BIT)
+#define X86_FSW_C3_BIT 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)
+/** For use with FPREM and FPREM1. */
+#define X86_FSW_CX_TO_QUOTIENT(a_fFsw) \
+ ( (((a_fFsw) & X86_FSW_C1) >> (X86_FSW_C1_BIT - 0)) \
+ | (((a_fFsw) & X86_FSW_C3) >> (X86_FSW_C3_BIT - 1)) \
+ | (((a_fFsw) & X86_FSW_C0) >> (X86_FSW_C0_BIT - 2)) )
+/** For use with FPREM and FPREM1. */
+#define X86_FSW_CX_FROM_QUOTIENT(a_uQuotient) \
+ ( ((uint16_t)((a_uQuotient) & 1) << (X86_FSW_C1_BIT - 0)) \
+ | ((uint16_t)((a_uQuotient) & 2) << (X86_FSW_C3_BIT - 1)) \
+ | ((uint16_t)((a_uQuotient) & 4) << (X86_FSW_C0_BIT - 2)) )
+/** @} */
+
+
+/** @name FPU control word flags.
+ * @{ */
+/** Exception Mask: Invalid operation. */
+#define X86_FCW_IM RT_BIT_32(0)
+#define X86_FCW_IM_BIT 0
+/** Exception Mask: Denormalized operand. */
+#define X86_FCW_DM RT_BIT_32(1)
+#define X86_FCW_DM_BIT 1
+/** Exception Mask: Zero divide. */
+#define X86_FCW_ZM RT_BIT_32(2)
+#define X86_FCW_ZM_BIT 2
+/** Exception Mask: Overflow. */
+#define X86_FCW_OM RT_BIT_32(3)
+#define X86_FCW_OM_BIT 3
+/** Exception Mask: Underflow. */
+#define X86_FCW_UM RT_BIT_32(4)
+#define X86_FCW_UM_BIT 4
+/** Exception Mask: Precision. */
+#define X86_FCW_PM RT_BIT_32(5)
+#define X86_FCW_PM_BIT 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 shift. */
+#define X86_FCW_PC_SHIFT 8
+/** 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 shift. */
+#define X86_FCW_RC_SHIFT 10
+/** 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)
+/** Infinity control mask - obsolete, 8087 & 287 only. */
+#define X86_FCW_IC_MASK UINT16_C(0x1000)
+/** Infinity control: Affine - positive infinity is distictly different from
+ * negative infinity.
+ * @note 8087, 287 only */
+#define X86_FCW_IC_AFFINE UINT16_C(0x1000)
+/** Infinity control: Projective - positive and negative infinity are the
+ * same (sign ignored).
+ * @note 8087, 287 only */
+#define X86_FCW_IC_PROJECTIVE UINT16_C(0x0000)
+/** 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)
+/** Exception Flags: mask */
+#define X86_MXCSR_XCPT_FLAGS UINT32_C(0x003f)
+
+/** 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)
+/** Exception Mask: mask. */
+#define X86_MXCSR_XCPT_MASK UINT32_C(0x1f80)
+/** Exception Mask: shift. */
+#define X86_MXCSR_XCPT_MASK_SHIFT 7
+
+/** Rounding control mask. */
+#define X86_MXCSR_RC_MASK UINT32_C(0x6000)
+/** Rounding control shift. */
+#define X86_MXCSR_RC_SHIFT 13
+/** Rounding control: To nearest. */
+#define X86_MXCSR_RC_NEAREST UINT32_C(0x0000)
+/** Rounding control: Down. */
+#define X86_MXCSR_RC_DOWN UINT32_C(0x2000)
+/** Rounding control: Up. */
+#define X86_MXCSR_RC_UP UINT32_C(0x4000)
+/** Rounding control: Towards zero. */
+#define X86_MXCSR_RC_ZERO UINT32_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)
+/** Bits which should be zero, apparently. */
+#define X86_MXCSR_ZERO_MASK UINT32_C(0xfffd0000)
+/** @} */
+
+/**
+ * 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-Point Exception. */
+ X86_XCPT_XF = 0x13,
+ /** \#VE - Virtualization Exception (Intel only). */
+ X86_XCPT_VE = 0x14,
+ /** \#CP - Control Protection Exception (Intel only). */
+ X86_XCPT_CP = 0x15,
+ /** \#VC - VMM Communication Exception (AMD only). */
+ X86_XCPT_VC = 0x1d,
+ /** \#SX - Security Exception (AMD only). */
+ 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
+/** @} */
+/** General register count. */
+#define X86_GREG_COUNT 16
+
+/** @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 /* !IPRT_INCLUDED_x86_h */
+
diff --git a/include/iprt/x86.mac b/include/iprt/x86.mac
new file mode 100644
index 00000000..cd1b545a
--- /dev/null
+++ b/include/iprt/x86.mac
@@ -0,0 +1,1409 @@
+;; @file
+; IPRT - X86 and AMD64 Structures and Definitions.
+;
+; Automatically generated by various.sed. DO NOT EDIT!
+;
+
+;
+; Copyright (C) 2006-2022 Oracle and/or its affiliates.
+;
+; This file is part of VirtualBox base platform packages, as
+; available from https://www.virtualbox.org.
+;
+; This program is free software; you can redistribute it and/or
+; modify it under the terms of the GNU General Public License
+; as published by the Free Software Foundation, in version 3 of the
+; License.
+;
+; This program is distributed in the hope that it will be useful, but
+; WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with this program; if not, see <https://www.gnu.org/licenses>.
+;
+; The contents of this file may alternatively be used under the terms
+; of the Common Development and Distribution License Version 1.0
+; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+; in the VirtualBox 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.
+;
+; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+;
+
+%ifndef IPRT_INCLUDED_x86_h
+%define IPRT_INCLUDED_x86_h
+%ifndef RT_WITHOUT_PRAGMA_ONCE
+%endif
+%ifndef VBOX_FOR_DTRACE_LIB
+%else
+%endif
+%ifdef RT_OS_SOLARIS
+%endif
+%ifndef VBOX_FOR_DTRACE_LIB
+%endif
+%ifndef VBOX_FOR_DTRACE_LIB
+%endif
+%ifndef VBOX_FOR_DTRACE_LIB
+%endif
+%define X86_EFL_CF RT_BIT_32(0)
+%define X86_EFL_CF_BIT 0
+%define X86_EFL_1 RT_BIT_32(1)
+%define X86_EFL_PF RT_BIT_32(2)
+%define X86_EFL_PF_BIT 2
+%define X86_EFL_AF RT_BIT_32(4)
+%define X86_EFL_AF_BIT 4
+%define X86_EFL_ZF RT_BIT_32(6)
+%define X86_EFL_ZF_BIT 6
+%define X86_EFL_SF RT_BIT_32(7)
+%define X86_EFL_SF_BIT 7
+%define X86_EFL_TF RT_BIT_32(8)
+%define X86_EFL_TF_BIT 8
+%define X86_EFL_IF RT_BIT_32(9)
+%define X86_EFL_IF_BIT 9
+%define X86_EFL_DF RT_BIT_32(10)
+%define X86_EFL_DF_BIT 10
+%define X86_EFL_OF RT_BIT_32(11)
+%define X86_EFL_OF_BIT 11
+%define X86_EFL_IOPL (RT_BIT_32(12) | RT_BIT_32(13))
+%define X86_EFL_NT RT_BIT_32(14)
+%define X86_EFL_NT_BIT 14
+%define X86_EFL_RF RT_BIT_32(16)
+%define X86_EFL_RF_BIT 16
+%define X86_EFL_VM RT_BIT_32(17)
+%define X86_EFL_VM_BIT 17
+%define X86_EFL_AC RT_BIT_32(18)
+%define X86_EFL_AC_BIT 18
+%define X86_EFL_VIF RT_BIT_32(19)
+%define X86_EFL_VIF_BIT 19
+%define X86_EFL_VIP RT_BIT_32(20)
+%define X86_EFL_VIP_BIT 20
+%define X86_EFL_ID RT_BIT_32(21)
+%define X86_EFL_ID_BIT 21
+%define X86_EFL_LIVE_MASK 0x003f7fd5
+%define X86_EFL_RA1_MASK RT_BIT_32(1)
+%define X86_EFL_IOPL_SHIFT 12
+%define X86_EFL_GET_IOPL(efl) (((efl) >> X86_EFL_IOPL_SHIFT) & 3)
+%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 )
+%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 )
+%define X86_EFL_STATUS_BITS ( X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF )
+%ifndef VBOX_FOR_DTRACE_LIB
+%else
+%endif
+%ifndef VBOX_FOR_DTRACE_LIB
+%else
+%endif
+%define X86_CPUID_VENDOR_INTEL_EBX 0x756e6547
+%define X86_CPUID_VENDOR_INTEL_ECX 0x6c65746e
+%define X86_CPUID_VENDOR_INTEL_EDX 0x49656e69
+%define X86_CPUID_VENDOR_AMD_EBX 0x68747541
+%define X86_CPUID_VENDOR_AMD_ECX 0x444d4163
+%define X86_CPUID_VENDOR_AMD_EDX 0x69746e65
+%define X86_CPUID_VENDOR_VIA_EBX 0x746e6543
+%define X86_CPUID_VENDOR_VIA_ECX 0x736c7561
+%define X86_CPUID_VENDOR_VIA_EDX 0x48727561
+%define X86_CPUID_VENDOR_SHANGHAI_EBX 0x68532020
+%define X86_CPUID_VENDOR_SHANGHAI_ECX 0x20206961
+%define X86_CPUID_VENDOR_SHANGHAI_EDX 0x68676e61
+%define X86_CPUID_VENDOR_HYGON_EBX 0x6f677948
+%define X86_CPUID_VENDOR_HYGON_ECX 0x656e6975
+%define X86_CPUID_VENDOR_HYGON_EDX 0x6e65476e
+%define X86_CPUID_FEATURE_ECX_SSE3 RT_BIT_32(0)
+%define X86_CPUID_FEATURE_ECX_PCLMUL RT_BIT_32(1)
+%define X86_CPUID_FEATURE_ECX_DTES64 RT_BIT_32(2)
+%define X86_CPUID_FEATURE_ECX_MONITOR RT_BIT_32(3)
+%define X86_CPUID_FEATURE_ECX_CPLDS RT_BIT_32(4)
+%define X86_CPUID_FEATURE_ECX_VMX RT_BIT_32(5)
+%define X86_CPUID_FEATURE_ECX_SMX RT_BIT_32(6)
+%define X86_CPUID_FEATURE_ECX_EST RT_BIT_32(7)
+%define X86_CPUID_FEATURE_ECX_TM2 RT_BIT_32(8)
+%define X86_CPUID_FEATURE_ECX_SSSE3 RT_BIT_32(9)
+%define X86_CPUID_FEATURE_ECX_CNTXID RT_BIT_32(10)
+%define X86_CPUID_FEATURE_ECX_SDBG RT_BIT_32(11)
+%define X86_CPUID_FEATURE_ECX_FMA RT_BIT_32(12)
+%define X86_CPUID_FEATURE_ECX_CX16 RT_BIT_32(13)
+%define X86_CPUID_FEATURE_ECX_TPRUPDATE RT_BIT_32(14)
+%define X86_CPUID_FEATURE_ECX_PDCM RT_BIT_32(15)
+%define X86_CPUID_FEATURE_ECX_PCID RT_BIT_32(17)
+%define X86_CPUID_FEATURE_ECX_DCA RT_BIT_32(18)
+%define X86_CPUID_FEATURE_ECX_SSE4_1 RT_BIT_32(19)
+%define X86_CPUID_FEATURE_ECX_SSE4_2 RT_BIT_32(20)
+%define X86_CPUID_FEATURE_ECX_X2APIC RT_BIT_32(21)
+%define X86_CPUID_FEATURE_ECX_MOVBE RT_BIT_32(22)
+%define X86_CPUID_FEATURE_ECX_POPCNT RT_BIT_32(23)
+%define X86_CPUID_FEATURE_ECX_TSCDEADL RT_BIT_32(24)
+%define X86_CPUID_FEATURE_ECX_AES RT_BIT_32(25)
+%define X86_CPUID_FEATURE_ECX_XSAVE RT_BIT_32(26)
+%define X86_CPUID_FEATURE_ECX_OSXSAVE RT_BIT_32(27)
+%define X86_CPUID_FEATURE_ECX_AVX RT_BIT_32(28)
+%define X86_CPUID_FEATURE_ECX_F16C RT_BIT_32(29)
+%define X86_CPUID_FEATURE_ECX_RDRAND RT_BIT_32(30)
+%define X86_CPUID_FEATURE_ECX_HVP RT_BIT_32(31)
+%define X86_CPUID_FEATURE_EDX_FPU RT_BIT_32(0)
+%define X86_CPUID_FEATURE_EDX_VME RT_BIT_32(1)
+%define X86_CPUID_FEATURE_EDX_DE RT_BIT_32(2)
+%define X86_CPUID_FEATURE_EDX_PSE RT_BIT_32(3)
+%define X86_CPUID_FEATURE_EDX_PSE_BIT 3
+%define X86_CPUID_FEATURE_EDX_TSC RT_BIT_32(4)
+%define X86_CPUID_FEATURE_EDX_MSR RT_BIT_32(5)
+%define X86_CPUID_FEATURE_EDX_PAE RT_BIT_32(6)
+%define X86_CPUID_FEATURE_EDX_PAE_BIT 6
+%define X86_CPUID_FEATURE_EDX_MCE RT_BIT_32(7)
+%define X86_CPUID_FEATURE_EDX_CX8 RT_BIT_32(8)
+%define X86_CPUID_FEATURE_EDX_APIC RT_BIT_32(9)
+%define X86_CPUID_FEATURE_EDX_SEP RT_BIT_32(11)
+%define X86_CPUID_FEATURE_EDX_MTRR RT_BIT_32(12)
+%define X86_CPUID_FEATURE_EDX_PGE RT_BIT_32(13)
+%define X86_CPUID_FEATURE_EDX_MCA RT_BIT_32(14)
+%define X86_CPUID_FEATURE_EDX_CMOV RT_BIT_32(15)
+%define X86_CPUID_FEATURE_EDX_PAT RT_BIT_32(16)
+%define X86_CPUID_FEATURE_EDX_PSE36 RT_BIT_32(17)
+%define X86_CPUID_FEATURE_EDX_PSN RT_BIT_32(18)
+%define X86_CPUID_FEATURE_EDX_CLFSH RT_BIT_32(19)
+%define X86_CPUID_FEATURE_EDX_DS RT_BIT_32(21)
+%define X86_CPUID_FEATURE_EDX_ACPI RT_BIT_32(22)
+%define X86_CPUID_FEATURE_EDX_MMX RT_BIT_32(23)
+%define X86_CPUID_FEATURE_EDX_FXSR RT_BIT_32(24)
+%define X86_CPUID_FEATURE_EDX_SSE RT_BIT_32(25)
+%define X86_CPUID_FEATURE_EDX_SSE2 RT_BIT_32(26)
+%define X86_CPUID_FEATURE_EDX_SS RT_BIT_32(27)
+%define X86_CPUID_FEATURE_EDX_HTT RT_BIT_32(28)
+%define X86_CPUID_FEATURE_EDX_TM RT_BIT_32(29)
+%define X86_CPUID_FEATURE_EDX_PBE RT_BIT_32(31)
+%define X86_CPUID_MWAIT_ECX_EXT RT_BIT_32(0)
+%define X86_CPUID_MWAIT_ECX_BREAKIRQIF0 RT_BIT_32(1)
+%define X86_CPUID_STEXT_FEATURE_EBX_FSGSBASE RT_BIT_32(0)
+%define X86_CPUID_STEXT_FEATURE_EBX_TSC_ADJUST RT_BIT_32(1)
+%define X86_CPUID_STEXT_FEATURE_EBX_SGX RT_BIT_32(2)
+%define X86_CPUID_STEXT_FEATURE_EBX_BMI1 RT_BIT_32(3)
+%define X86_CPUID_STEXT_FEATURE_EBX_HLE RT_BIT_32(4)
+%define X86_CPUID_STEXT_FEATURE_EBX_AVX2 RT_BIT_32(5)
+%define X86_CPUID_STEXT_FEATURE_EBX_FDP_EXCPTN_ONLY RT_BIT_32(6)
+%define X86_CPUID_STEXT_FEATURE_EBX_SMEP RT_BIT_32(7)
+%define X86_CPUID_STEXT_FEATURE_EBX_BMI2 RT_BIT_32(8)
+%define X86_CPUID_STEXT_FEATURE_EBX_ERMS RT_BIT_32(9)
+%define X86_CPUID_STEXT_FEATURE_EBX_INVPCID RT_BIT_32(10)
+%define X86_CPUID_STEXT_FEATURE_EBX_RTM RT_BIT_32(11)
+%define X86_CPUID_STEXT_FEATURE_EBX_PQM RT_BIT_32(12)
+%define X86_CPUID_STEXT_FEATURE_EBX_DEPR_FPU_CS_DS RT_BIT_32(13)
+%define X86_CPUID_STEXT_FEATURE_EBX_MPE RT_BIT_32(14)
+%define X86_CPUID_STEXT_FEATURE_EBX_PQE RT_BIT_32(15)
+%define X86_CPUID_STEXT_FEATURE_EBX_AVX512F RT_BIT_32(16)
+%define X86_CPUID_STEXT_FEATURE_EBX_RDSEED RT_BIT_32(18)
+%define X86_CPUID_STEXT_FEATURE_EBX_ADX RT_BIT_32(19)
+%define X86_CPUID_STEXT_FEATURE_EBX_SMAP RT_BIT_32(20)
+%define X86_CPUID_STEXT_FEATURE_EBX_CLFLUSHOPT RT_BIT_32(23)
+%define X86_CPUID_STEXT_FEATURE_EBX_INTEL_PT RT_BIT_32(25)
+%define X86_CPUID_STEXT_FEATURE_EBX_AVX512PF RT_BIT_32(26)
+%define X86_CPUID_STEXT_FEATURE_EBX_AVX512ER RT_BIT_32(27)
+%define X86_CPUID_STEXT_FEATURE_EBX_AVX512CD RT_BIT_32(28)
+%define X86_CPUID_STEXT_FEATURE_EBX_SHA RT_BIT_32(29)
+%define X86_CPUID_STEXT_FEATURE_ECX_PREFETCHWT1 RT_BIT_32(0)
+%define X86_CPUID_STEXT_FEATURE_ECX_UMIP RT_BIT_32(2)
+%define X86_CPUID_STEXT_FEATURE_ECX_PKU RT_BIT_32(3)
+%define X86_CPUID_STEXT_FEATURE_ECX_OSPKE RT_BIT_32(4)
+%define X86_CPUID_STEXT_FEATURE_ECX_MAWAU 0x003e0000
+%define X86_CPUID_STEXT_FEATURE_ECX_RDPID RT_BIT_32(2)
+%define X86_CPUID_STEXT_FEATURE_ECX_SGX_LC RT_BIT_32(30)
+%define X86_CPUID_STEXT_FEATURE_EDX_MD_CLEAR RT_BIT_32(10)
+%define X86_CPUID_STEXT_FEATURE_EDX_IBRS_IBPB RT_BIT_32(26)
+%define X86_CPUID_STEXT_FEATURE_EDX_STIBP RT_BIT_32(27)
+%define X86_CPUID_STEXT_FEATURE_EDX_FLUSH_CMD RT_BIT_32(28)
+%define X86_CPUID_STEXT_FEATURE_EDX_ARCHCAP RT_BIT_32(29)
+%define X86_CPUID_STEXT_FEATURE_EDX_SSBD RT_BIT_32(31)
+%define X86_CPUID_EXT_FEATURE_ECX_LAHF_SAHF RT_BIT_32(0)
+%define X86_CPUID_EXT_FEATURE_EDX_SYSCALL RT_BIT_32(11)
+%define X86_CPUID_EXT_FEATURE_EDX_NX RT_BIT_32(20)
+%define X86_CPUID_EXT_FEATURE_EDX_PAGE1GB RT_BIT_32(26)
+%define X86_CPUID_EXT_FEATURE_EDX_RDTSCP RT_BIT_32(27)
+%define X86_CPUID_EXT_FEATURE_EDX_LONG_MODE RT_BIT_32(29)
+%define X86_CPUID_AMD_FEATURE_EDX_FPU RT_BIT_32(0)
+%define X86_CPUID_AMD_FEATURE_EDX_VME RT_BIT_32(1)
+%define X86_CPUID_AMD_FEATURE_EDX_DE RT_BIT_32(2)
+%define X86_CPUID_AMD_FEATURE_EDX_PSE RT_BIT_32(3)
+%define X86_CPUID_AMD_FEATURE_EDX_TSC RT_BIT_32(4)
+%define X86_CPUID_AMD_FEATURE_EDX_MSR RT_BIT_32(5)
+%define X86_CPUID_AMD_FEATURE_EDX_PAE RT_BIT_32(6)
+%define X86_CPUID_AMD_FEATURE_EDX_MCE RT_BIT_32(7)
+%define X86_CPUID_AMD_FEATURE_EDX_CX8 RT_BIT_32(8)
+%define X86_CPUID_AMD_FEATURE_EDX_APIC RT_BIT_32(9)
+%define X86_CPUID_AMD_FEATURE_EDX_MTRR RT_BIT_32(12)
+%define X86_CPUID_AMD_FEATURE_EDX_PGE RT_BIT_32(13)
+%define X86_CPUID_AMD_FEATURE_EDX_MCA RT_BIT_32(14)
+%define X86_CPUID_AMD_FEATURE_EDX_CMOV RT_BIT_32(15)
+%define X86_CPUID_AMD_FEATURE_EDX_PAT RT_BIT_32(16)
+%define X86_CPUID_AMD_FEATURE_EDX_PSE36 RT_BIT_32(17)
+%define X86_CPUID_AMD_FEATURE_EDX_AXMMX RT_BIT_32(22)
+%define X86_CPUID_AMD_FEATURE_EDX_MMX RT_BIT_32(23)
+%define X86_CPUID_AMD_FEATURE_EDX_FXSR RT_BIT_32(24)
+%define X86_CPUID_AMD_FEATURE_EDX_FFXSR RT_BIT_32(25)
+%define X86_CPUID_AMD_FEATURE_EDX_3DNOW_EX RT_BIT_32(30)
+%define X86_CPUID_AMD_FEATURE_EDX_3DNOW RT_BIT_32(31)
+%define X86_CPUID_AMD_FEATURE_ECX_CMPL RT_BIT_32(1)
+%define X86_CPUID_AMD_FEATURE_ECX_SVM RT_BIT_32(2)
+%define X86_CPUID_AMD_FEATURE_ECX_EXT_APIC RT_BIT_32(3)
+%define X86_CPUID_AMD_FEATURE_ECX_CR8L RT_BIT_32(4)
+%define X86_CPUID_AMD_FEATURE_ECX_ABM RT_BIT_32(5)
+%define X86_CPUID_AMD_FEATURE_ECX_SSE4A RT_BIT_32(6)
+%define X86_CPUID_AMD_FEATURE_ECX_MISALNSSE RT_BIT_32(7)
+%define X86_CPUID_AMD_FEATURE_ECX_3DNOWPRF RT_BIT_32(8)
+%define X86_CPUID_AMD_FEATURE_ECX_OSVW RT_BIT_32(9)
+%define X86_CPUID_AMD_FEATURE_ECX_IBS RT_BIT_32(10)
+%define X86_CPUID_AMD_FEATURE_ECX_XOP RT_BIT_32(11)
+%define X86_CPUID_AMD_FEATURE_ECX_SKINIT RT_BIT_32(12)
+%define X86_CPUID_AMD_FEATURE_ECX_WDT RT_BIT_32(13)
+%define X86_CPUID_AMD_FEATURE_ECX_LWP RT_BIT_32(15)
+%define X86_CPUID_AMD_FEATURE_ECX_FMA4 RT_BIT_32(16)
+%define X86_CPUID_AMD_FEATURE_ECX_NODEID RT_BIT_32(19)
+%define X86_CPUID_AMD_FEATURE_ECX_TBM RT_BIT_32(21)
+%define X86_CPUID_AMD_FEATURE_ECX_TOPOEXT RT_BIT_32(22)
+%define X86_CPUID_AMD_ADVPOWER_EDX_TS RT_BIT_32(0)
+%define X86_CPUID_AMD_ADVPOWER_EDX_FID RT_BIT_32(1)
+%define X86_CPUID_AMD_ADVPOWER_EDX_VID RT_BIT_32(2)
+%define X86_CPUID_AMD_ADVPOWER_EDX_TTP RT_BIT_32(3)
+%define X86_CPUID_AMD_ADVPOWER_EDX_TM RT_BIT_32(4)
+%define X86_CPUID_AMD_ADVPOWER_EDX_STC RT_BIT_32(5)
+%define X86_CPUID_AMD_ADVPOWER_EDX_MC RT_BIT_32(6)
+%define X86_CPUID_AMD_ADVPOWER_EDX_HWPSTATE RT_BIT_32(7)
+%define X86_CPUID_AMD_ADVPOWER_EDX_TSCINVAR RT_BIT_32(8)
+%define X86_CPUID_AMD_ADVPOWER_EDX_CPB RT_BIT_32(9)
+%define X86_CPUID_AMD_ADVPOWER_EDX_EFRO RT_BIT_32(10)
+%define X86_CPUID_AMD_ADVPOWER_EDX_PFI RT_BIT_32(11)
+%define X86_CPUID_AMD_ADVPOWER_EDX_PA RT_BIT_32(12)
+%define X86_CPUID_AMD_EFEID_EBX_CLZERO RT_BIT_32(0)
+%define X86_CPUID_AMD_EFEID_EBX_IRPERF RT_BIT_32(1)
+%define X86_CPUID_AMD_EFEID_EBX_XSAVE_ER_PTR RT_BIT_32(2)
+%define X86_CPUID_AMD_EFEID_EBX_RDPRU RT_BIT_32(4)
+%define X86_CPUID_AMD_EFEID_EBX_MCOMMIT RT_BIT_32(8)
+%define X86_CPUID_AMD_EFEID_EBX_IBPB RT_BIT_32(12)
+%define X86_CPUID_AMD_EFEID_EBX_IBRS RT_BIT_32(14)
+%define X86_CPUID_AMD_EFEID_EBX_STIBP RT_BIT_32(15)
+%define X86_CPUID_AMD_EFEID_EBX_IBRS_ALWAYS_ON RT_BIT_32(16)
+%define X86_CPUID_AMD_EFEID_EBX_STIBP_ALWAYS_ON RT_BIT_32(17)
+%define X86_CPUID_AMD_EFEID_EBX_IBRS_PREFERRED RT_BIT_32(18)
+%define X86_CPUID_AMD_EFEID_EBX_SPEC_CTRL_SSBD RT_BIT_32(24)
+%define X86_CPUID_AMD_EFEID_EBX_VIRT_SPEC_CTRL_SSBD RT_BIT_32(25)
+%define X86_CPUID_AMD_EFEID_EBX_NO_SSBD_REQUIRED RT_BIT_32(26)
+%define X86_CPUID_SVM_FEATURE_EDX_NESTED_PAGING RT_BIT(0)
+%define X86_CPUID_SVM_FEATURE_EDX_LBR_VIRT RT_BIT(1)
+%define X86_CPUID_SVM_FEATURE_EDX_SVM_LOCK RT_BIT(2)
+%define X86_CPUID_SVM_FEATURE_EDX_NRIP_SAVE RT_BIT(3)
+%define X86_CPUID_SVM_FEATURE_EDX_TSC_RATE_MSR RT_BIT(4)
+%define X86_CPUID_SVM_FEATURE_EDX_VMCB_CLEAN RT_BIT(5)
+%define X86_CPUID_SVM_FEATURE_EDX_FLUSH_BY_ASID RT_BIT(6)
+%define X86_CPUID_SVM_FEATURE_EDX_DECODE_ASSISTS RT_BIT(7)
+%define X86_CPUID_SVM_FEATURE_EDX_PAUSE_FILTER RT_BIT(10)
+%define X86_CPUID_SVM_FEATURE_EDX_PAUSE_FILTER_THRESHOLD RT_BIT(12)
+%define X86_CPUID_SVM_FEATURE_EDX_AVIC RT_BIT(13)
+%define X86_CPUID_SVM_FEATURE_EDX_VIRT_VMSAVE_VMLOAD RT_BIT(15)
+%define X86_CPUID_SVM_FEATURE_EDX_VGIF RT_BIT(16)
+%define X86_CPUID_SVM_FEATURE_EDX_GMET RT_BIT(17)
+%define X86_CPUID_SVM_FEATURE_EDX_SSSCHECK RT_BIT(19)
+%define X86_CPUID_SVM_FEATURE_EDX_SPEC_CTRL RT_BIT(20)
+%define X86_CPUID_SVM_FEATURE_EDX_HOST_MCE_OVERRIDE RT_BIT(23)
+%define X86_CPUID_SVM_FEATURE_EDX_TLBICTL RT_BIT(24)
+%define X86_CR0_PE RT_BIT_32(0)
+%define X86_CR0_PROTECTION_ENABLE RT_BIT_32(0)
+%define X86_CR0_MP RT_BIT_32(1)
+%define X86_CR0_MONITOR_COPROCESSOR RT_BIT_32(1)
+%define X86_CR0_EM RT_BIT_32(2)
+%define X86_CR0_EMULATE_FPU RT_BIT_32(2)
+%define X86_CR0_TS RT_BIT_32(3)
+%define X86_CR0_TASK_SWITCH RT_BIT_32(3)
+%define X86_CR0_ET RT_BIT_32(4)
+%define X86_CR0_EXTENSION_TYPE RT_BIT_32(4)
+%define X86_CR0_NE RT_BIT_32(5)
+%define X86_CR0_NUMERIC_ERROR RT_BIT_32(5)
+%define X86_CR0_WP RT_BIT_32(16)
+%define X86_CR0_WRITE_PROTECT RT_BIT_32(16)
+%define X86_CR0_AM RT_BIT_32(18)
+%define X86_CR0_ALIGMENT_MASK RT_BIT_32(18)
+%define X86_CR0_NW RT_BIT_32(29)
+%define X86_CR0_NOT_WRITE_THROUGH RT_BIT_32(29)
+%define X86_CR0_CD RT_BIT_32(30)
+%define X86_CR0_CACHE_DISABLE RT_BIT_32(30)
+%define X86_CR0_PG RT_BIT_32(31)
+%define X86_CR0_PAGING RT_BIT_32(31)
+%define X86_CR0_BIT_PG 31
+%define X86_CR3_PWT RT_BIT_32(3)
+%define X86_CR3_PCD RT_BIT_32(4)
+%define X86_CR3_PAGE_MASK (0xfffff000)
+%define X86_CR3_PAE_PAGE_MASK (0xffffffe0)
+%define X86_CR3_AMD64_PAGE_MASK 0x000ffffffffff000
+%define X86_CR3_EPT_PAGE_MASK 0x0000fffffffff000
+%define X86_CR4_VME RT_BIT_32(0)
+%define X86_CR4_PVI RT_BIT_32(1)
+%define X86_CR4_TSD RT_BIT_32(2)
+%define X86_CR4_DE RT_BIT_32(3)
+%define X86_CR4_PSE RT_BIT_32(4)
+%define X86_CR4_PAE RT_BIT_32(5)
+%define X86_CR4_MCE RT_BIT_32(6)
+%define X86_CR4_PGE RT_BIT_32(7)
+%define X86_CR4_PCE RT_BIT_32(8)
+%define X86_CR4_OSFXSR RT_BIT_32(9)
+%define X86_CR4_OSXMMEEXCPT RT_BIT_32(10)
+%define X86_CR4_UMIP RT_BIT_32(11)
+%define X86_CR4_VMXE RT_BIT_32(13)
+%define X86_CR4_SMXE RT_BIT_32(14)
+%define X86_CR4_FSGSBASE RT_BIT_32(16)
+%define X86_CR4_PCIDE RT_BIT_32(17)
+%define X86_CR4_OSXSAVE RT_BIT_32(18)
+%define X86_CR4_SMEP RT_BIT_32(20)
+%define X86_CR4_SMAP RT_BIT_32(21)
+%define X86_CR4_PKE RT_BIT_32(22)
+%define X86_CR4_CET RT_BIT_32(23)
+%define X86_DR6_B0 RT_BIT_32(0)
+%define X86_DR6_B1 RT_BIT_32(1)
+%define X86_DR6_B2 RT_BIT_32(2)
+%define X86_DR6_B3 RT_BIT_32(3)
+%define X86_DR6_B_MASK 0x0000000f
+%define X86_DR6_BD RT_BIT_32(13)
+%define X86_DR6_BS RT_BIT_32(14)
+%define X86_DR6_BT RT_BIT_32(15)
+%define X86_DR6_RTM RT_BIT_32(16)
+%define X86_DR6_INIT_VAL 0xffff0ff0
+%define X86_DR6_RA1_MASK 0xffff0ff0
+%define X86_DR6_RA1_MASK_RTM 0xfffe0ff0
+%define X86_DR6_RAZ_MASK RT_BIT_64(12)
+%define X86_DR6_MBZ_MASK 0xffffffff00000000
+%define X86_DR6_B(iBp) RT_BIT_64(iBp)
+%define X86_DR7_L0 RT_BIT_32(0)
+%define X86_DR7_G0 RT_BIT_32(1)
+%define X86_DR7_L1 RT_BIT_32(2)
+%define X86_DR7_G1 RT_BIT_32(3)
+%define X86_DR7_L2 RT_BIT_32(4)
+%define X86_DR7_G2 RT_BIT_32(5)
+%define X86_DR7_L3 RT_BIT_32(6)
+%define X86_DR7_G3 RT_BIT_32(7)
+%define X86_DR7_LE RT_BIT_32(8)
+%define X86_DR7_GE RT_BIT_32(9)
+%define X86_DR7_LE_ALL 0x0000000000000055
+%define X86_DR7_GE_ALL 0x00000000000000aa
+%define X86_DR7_RTM RT_BIT_32(11)
+%define X86_DR7_ICE_IR RT_BIT_32(12)
+%define X86_DR7_GD RT_BIT_32(13)
+%define X86_DR7_ICE_TR1 RT_BIT_32(14)
+%define X86_DR7_ICE_TR2 RT_BIT_32(15)
+%define X86_DR7_RW0_MASK (3 << 16)
+%define X86_DR7_LEN0_MASK (3 << 18)
+%define X86_DR7_RW1_MASK (3 << 20)
+%define X86_DR7_LEN1_MASK (3 << 22)
+%define X86_DR7_RW2_MASK (3 << 24)
+%define X86_DR7_LEN2_MASK (3 << 26)
+%define X86_DR7_RW3_MASK (3 << 28)
+%define X86_DR7_LEN3_MASK (3 << 30)
+%define X86_DR7_RA1_MASK RT_BIT_32(10)
+%define X86_DR7_RAZ_MASK 0x0000d800
+%define X86_DR7_MBZ_MASK 0xffffffff00000000
+%define X86_DR7_L(iBp) ( 1 << (iBp * 2) )
+%define X86_DR7_G(iBp) ( 1 << (iBp * 2 + 1) )
+%define X86_DR7_L_G(iBp) ( 3 << (iBp * 2) )
+%define X86_DR7_RW_EO 0
+%define X86_DR7_RW_WO 1
+%define X86_DR7_RW_IO 2
+%define X86_DR7_RW_RW 3
+%define X86_DR7_RW(iBp, fRw) ( (fRw) << ((iBp) * 4 + 16) )
+%define X86_DR7_GET_RW(uDR7, iBp) ( ( (uDR7) >> ((iBp) * 4 + 16) ) & 3 )
+%define X86_DR7_RW_ALL_MASKS 0x33330000
+%ifndef VBOX_FOR_DTRACE_LIB
+ %define X86_DR7_ANY_RW_IO(uDR7) \
+ ( ( 0x22220000 & (uDR7) )
+%endif
+%define X86_DR7_LEN_BYTE 0
+%define X86_DR7_LEN_WORD 1
+%define X86_DR7_LEN_QWORD 2
+%define X86_DR7_LEN_DWORD 3
+%define X86_DR7_LEN(iBp, cb) ( (cb) << ((iBp) * 4 + 18) )
+%define X86_DR7_GET_LEN(uDR7, iBp) ( ( (uDR7) >> ((iBp) * 4 + 18) ) & 0x3 )
+%define X86_DR7_ENABLED_MASK 0x000000ff
+%define X86_DR7_LEN_ALL_MASKS 0xcccc0000
+%define X86_DR7_RW_LEN_ALL_MASKS 0xffff0000
+%define X86_DR7_INIT_VAL 0x400
+%define MSR_P5_MC_ADDR 0x00000000
+%define MSR_P5_MC_TYPE 0x00000001
+%define MSR_IA32_TSC 0x10
+%define MSR_IA32_CESR 0x00000011
+%define MSR_IA32_CTR0 0x00000012
+%define MSR_IA32_CTR1 0x00000013
+%define MSR_IA32_PLATFORM_ID 0x17
+%ifndef MSR_IA32_APICBASE
+ %define MSR_IA32_APICBASE 0x1b
+ %define MSR_IA32_APICBASE_EN RT_BIT_64(11)
+ %define MSR_IA32_APICBASE_EXTD RT_BIT_64(10)
+ %define MSR_IA32_APICBASE_BSP RT_BIT_64(8)
+ %define MSR_IA32_APICBASE_BASE_MIN 0x0000000ffffff000
+ %define MSR_IA32_APICBASE_ADDR 0x00000000fee00000
+ %define MSR_IA32_APICBASE_GET_ADDR(a_Msr) ((a_Msr) & X86_PAGE_4K_BASE_MASK)
+%endif
+%define MSR_CORE_THREAD_COUNT 0x35
+%define MSR_IA32_FEATURE_CONTROL 0x3A
+%define MSR_IA32_FEATURE_CONTROL_LOCK RT_BIT_64(0)
+%define MSR_IA32_FEATURE_CONTROL_SMX_VMXON RT_BIT_64(1)
+%define MSR_IA32_FEATURE_CONTROL_VMXON RT_BIT_64(2)
+%define MSR_IA32_FEATURE_CONTROL_SENTER_LOCAL_FN_0 RT_BIT_64(8)
+%define MSR_IA32_FEATURE_CONTROL_SENTER_LOCAL_FN_1 RT_BIT_64(9)
+%define MSR_IA32_FEATURE_CONTROL_SENTER_LOCAL_FN_2 RT_BIT_64(10)
+%define MSR_IA32_FEATURE_CONTROL_SENTER_LOCAL_FN_3 RT_BIT_64(11)
+%define MSR_IA32_FEATURE_CONTROL_SENTER_LOCAL_FN_4 RT_BIT_64(12)
+%define MSR_IA32_FEATURE_CONTROL_SENTER_LOCAL_FN_5 RT_BIT_64(13)
+%define MSR_IA32_FEATURE_CONTROL_SENTER_LOCAL_FN_6 RT_BIT_64(14)
+%define MSR_IA32_FEATURE_CONTROL_SENTER_GLOBAL_EN RT_BIT_64(15)
+%define MSR_IA32_FEATURE_CONTROL_SGX_LAUNCH_EN RT_BIT_64(17)
+%define MSR_IA32_FEATURE_CONTROL_SGX_GLOBAL_EN RT_BIT_64(18)
+%define MSR_IA32_FEATURE_CONTROL_LMCE RT_BIT_64(20)
+%define MSR_IA32_TSC_ADJUST 0x3B
+%define MSR_IA32_SPEC_CTRL 0x48
+%define MSR_IA32_SPEC_CTRL_F_IBRS RT_BIT_32(0)
+%define MSR_IA32_SPEC_CTRL_F_STIBP RT_BIT_32(1)
+%define MSR_IA32_SPEC_CTRL_F_SSBD RT_BIT_32(2)
+%define MSR_IA32_PRED_CMD 0x49
+%define MSR_IA32_PRED_CMD_F_IBPB RT_BIT_32(0)
+%define MSR_IA32_BIOS_UPDT_TRIG 0x79
+%define MSR_IA32_BIOS_SIGN_ID 0x8B
+%define MSR_IA32_SMM_MONITOR_CTL 0x9B
+%define MSR_IA32_SMM_MONITOR_VALID RT_BIT_64(0)
+%define MSR_IA32_SMM_MONITOR_VMXOFF_UNBLOCK_SMI RT_BIT_64(2)
+%define MSR_IA32_SMM_MONITOR_MSGEG_PHYSADDR(a) (((a) >> 12) & 0xfffff)
+%define MSR_IA32_SMBASE 0x9E
+%define MSR_IA32_PMC0 0xC1
+%define MSR_IA32_PMC1 0xC2
+%define MSR_IA32_PMC2 0xC3
+%define MSR_IA32_PMC3 0xC4
+%define MSR_IA32_PMC4 0xC5
+%define MSR_IA32_PMC5 0xC6
+%define MSR_IA32_PMC6 0xC7
+%define MSR_IA32_PMC7 0xC8
+%define MSR_IA32_PLATFORM_INFO 0xCE
+%define MSR_IA32_FSB_CLOCK_STS 0xCD
+%define MSR_PKG_CST_CONFIG_CONTROL 0x000000e2
+%define MSR_IA32_MPERF 0xE7
+%define MSR_IA32_APERF 0xE8
+%define MSR_IA32_MTRR_CAP 0xFE
+%define MSR_IA32_ARCH_CAPABILITIES 0x10a
+%define MSR_IA32_ARCH_CAP_F_RDCL_NO RT_BIT_32(0)
+%define MSR_IA32_ARCH_CAP_F_IBRS_ALL RT_BIT_32(1)
+%define MSR_IA32_ARCH_CAP_F_RSBO RT_BIT_32(2)
+%define MSR_IA32_ARCH_CAP_F_VMM_NEED_NOT_FLUSH_L1D RT_BIT_32(3)
+%define MSR_IA32_ARCH_CAP_F_MDS_NO RT_BIT_32(4)
+%define MSR_IA32_FLUSH_CMD 0x10b
+%define MSR_IA32_FLUSH_CMD_F_L1D RT_BIT_32(0)
+%define MSR_BBL_CR_CTL3 0x11e
+%ifndef MSR_IA32_SYSENTER_CS
+%define MSR_IA32_SYSENTER_CS 0x174
+%define MSR_IA32_SYSENTER_ESP 0x175
+%define MSR_IA32_SYSENTER_EIP 0x176
+%endif
+%define MSR_IA32_MCG_CAP 0x179
+%define MSR_IA32_MCG_STATUS 0x17A
+%define MSR_IA32_MCG_CTRL 0x17B
+%define MSR_IA32_CR_PAT 0x277
+%define MSR_IA32_CR_PAT_INIT_VAL 0x0007040600070406
+%define MSR_IA32_PERFEVTSEL0 0x186
+%define MSR_IA32_PERFEVTSEL1 0x187
+%define MSR_IA32_PERFEVTSEL2 0x188
+%define MSR_IA32_PERFEVTSEL3 0x189
+%define MSR_FLEX_RATIO 0x194
+%define MSR_IA32_PERF_STATUS 0x198
+%define MSR_IA32_PERF_CTL 0x199
+%define MSR_IA32_THERM_STATUS 0x19c
+%define MSR_OFFCORE_RSP_0 0x1a6
+%define MSR_OFFCORE_RSP_1 0x1a7
+%define MSR_IA32_MISC_ENABLE 0x1A0
+%define MSR_IA32_MISC_ENABLE_FAST_STRINGS RT_BIT_64(0)
+%define MSR_IA32_MISC_ENABLE_TCC RT_BIT_64(3)
+%define MSR_IA32_MISC_ENABLE_PERF_MON RT_BIT_64(7)
+%define MSR_IA32_MISC_ENABLE_BTS_UNAVAIL RT_BIT_64(11)
+%define MSR_IA32_MISC_ENABLE_PEBS_UNAVAIL RT_BIT_64(12)
+%define MSR_IA32_MISC_ENABLE_SST_ENABLE RT_BIT_64(16)
+%define MSR_IA32_MISC_ENABLE_MONITOR RT_BIT_64(18)
+%define MSR_IA32_MISC_ENABLE_LIMIT_CPUID RT_BIT_64(22)
+%define MSR_IA32_MISC_ENABLE_XTPR_MSG_DISABLE RT_BIT_64(23)
+%define MSR_IA32_MISC_ENABLE_XD_DISABLE RT_BIT_64(34)
+%define MSR_IA32_DEBUGCTL 0x000001d9
+%define MSR_IA32_DEBUGCTL_LBR RT_BIT_64(0)
+%define MSR_IA32_DEBUGCTL_BTF RT_BIT_64(1)
+%define MSR_IA32_DEBUGCTL_PB0 RT_BIT_64(2)
+%define MSR_IA32_DEBUGCTL_PB1 RT_BIT_64(3)
+%define MSR_IA32_DEBUGCTL_PB2 RT_BIT_64(4)
+%define MSR_IA32_DEBUGCTL_PB3 RT_BIT_64(5)
+%define MSR_IA32_DEBUGCTL_TR RT_BIT_64(6)
+%define MSR_IA32_DEBUGCTL_BTS RT_BIT_64(7)
+%define MSR_IA32_DEBUGCTL_BTINT RT_BIT_64(8)
+%define MSR_IA32_DEBUGCTL_BTS_OFF_OS RT_BIT_64(9)
+%define MSR_IA32_DEBUGCTL_BTS_OFF_USER RT_BIT_64(10)
+%define MSR_IA32_DEBUGCTL_FREEZE_LBR_ON_PMI RT_BIT_64(11)
+%define MSR_IA32_DEBUGCTL_FREEZE_PERFMON_ON_PMI RT_BIT_64(12)
+%define MSR_IA32_DEBUGCTL_FREEZE_WHILE_SMM_EM RT_BIT_64(14)
+%define MSR_IA32_DEBUGCTL_RTM RT_BIT_64(15)
+%define MSR_IA32_DEBUGCTL_VALID_MASK_INTEL ( MSR_IA32_DEBUGCTL_LBR | MSR_IA32_DEBUGCTL_BTF | MSR_IA32_DEBUGCTL_TR \
+ | MSR_IA32_DEBUGCTL_BTS | MSR_IA32_DEBUGCTL_BTINT | MSR_IA32_DEBUGCTL_BTS_OFF_OS \
+ | MSR_IA32_DEBUGCTL_BTS_OFF_USER | MSR_IA32_DEBUGCTL_FREEZE_LBR_ON_PMI \
+ | MSR_IA32_DEBUGCTL_FREEZE_PERFMON_ON_PMI | MSR_IA32_DEBUGCTL_FREEZE_WHILE_SMM_EM \
+ | MSR_IA32_DEBUGCTL_RTM)
+%define MSR_P4_LASTBRANCH_0 0x1db
+%define MSR_P4_LASTBRANCH_1 0x1dc
+%define MSR_P4_LASTBRANCH_2 0x1dd
+%define MSR_P4_LASTBRANCH_3 0x1de
+%define MSR_P4_LASTBRANCH_TOS 0x1da
+%define MSR_CORE2_LASTBRANCH_0_FROM_IP 0x40
+%define MSR_CORE2_LASTBRANCH_1_FROM_IP 0x41
+%define MSR_CORE2_LASTBRANCH_2_FROM_IP 0x42
+%define MSR_CORE2_LASTBRANCH_3_FROM_IP 0x43
+%define MSR_CORE2_LASTBRANCH_0_TO_IP 0x60
+%define MSR_CORE2_LASTBRANCH_1_TO_IP 0x61
+%define MSR_CORE2_LASTBRANCH_2_TO_IP 0x62
+%define MSR_CORE2_LASTBRANCH_3_TO_IP 0x63
+%define MSR_CORE2_LASTBRANCH_TOS 0x1c9
+%define MSR_LASTBRANCH_0_FROM_IP 0x680
+%define MSR_LASTBRANCH_1_FROM_IP 0x681
+%define MSR_LASTBRANCH_2_FROM_IP 0x682
+%define MSR_LASTBRANCH_3_FROM_IP 0x683
+%define MSR_LASTBRANCH_4_FROM_IP 0x684
+%define MSR_LASTBRANCH_5_FROM_IP 0x685
+%define MSR_LASTBRANCH_6_FROM_IP 0x686
+%define MSR_LASTBRANCH_7_FROM_IP 0x687
+%define MSR_LASTBRANCH_8_FROM_IP 0x688
+%define MSR_LASTBRANCH_9_FROM_IP 0x689
+%define MSR_LASTBRANCH_10_FROM_IP 0x68a
+%define MSR_LASTBRANCH_11_FROM_IP 0x68b
+%define MSR_LASTBRANCH_12_FROM_IP 0x68c
+%define MSR_LASTBRANCH_13_FROM_IP 0x68d
+%define MSR_LASTBRANCH_14_FROM_IP 0x68e
+%define MSR_LASTBRANCH_15_FROM_IP 0x68f
+%define MSR_LASTBRANCH_16_FROM_IP 0x690
+%define MSR_LASTBRANCH_17_FROM_IP 0x691
+%define MSR_LASTBRANCH_18_FROM_IP 0x692
+%define MSR_LASTBRANCH_19_FROM_IP 0x693
+%define MSR_LASTBRANCH_20_FROM_IP 0x694
+%define MSR_LASTBRANCH_21_FROM_IP 0x695
+%define MSR_LASTBRANCH_22_FROM_IP 0x696
+%define MSR_LASTBRANCH_23_FROM_IP 0x697
+%define MSR_LASTBRANCH_24_FROM_IP 0x698
+%define MSR_LASTBRANCH_25_FROM_IP 0x699
+%define MSR_LASTBRANCH_26_FROM_IP 0x69a
+%define MSR_LASTBRANCH_27_FROM_IP 0x69b
+%define MSR_LASTBRANCH_28_FROM_IP 0x69c
+%define MSR_LASTBRANCH_29_FROM_IP 0x69d
+%define MSR_LASTBRANCH_30_FROM_IP 0x69e
+%define MSR_LASTBRANCH_31_FROM_IP 0x69f
+%define MSR_LASTBRANCH_0_TO_IP 0x6c0
+%define MSR_LASTBRANCH_1_TO_IP 0x6c1
+%define MSR_LASTBRANCH_2_TO_IP 0x6c2
+%define MSR_LASTBRANCH_3_TO_IP 0x6c3
+%define MSR_LASTBRANCH_4_TO_IP 0x6c4
+%define MSR_LASTBRANCH_5_TO_IP 0x6c5
+%define MSR_LASTBRANCH_6_TO_IP 0x6c6
+%define MSR_LASTBRANCH_7_TO_IP 0x6c7
+%define MSR_LASTBRANCH_8_TO_IP 0x6c8
+%define MSR_LASTBRANCH_9_TO_IP 0x6c9
+%define MSR_LASTBRANCH_10_TO_IP 0x6ca
+%define MSR_LASTBRANCH_11_TO_IP 0x6cb
+%define MSR_LASTBRANCH_12_TO_IP 0x6cc
+%define MSR_LASTBRANCH_13_TO_IP 0x6cd
+%define MSR_LASTBRANCH_14_TO_IP 0x6ce
+%define MSR_LASTBRANCH_15_TO_IP 0x6cf
+%define MSR_LASTBRANCH_16_TO_IP 0x6d0
+%define MSR_LASTBRANCH_17_TO_IP 0x6d1
+%define MSR_LASTBRANCH_18_TO_IP 0x6d2
+%define MSR_LASTBRANCH_19_TO_IP 0x6d3
+%define MSR_LASTBRANCH_20_TO_IP 0x6d4
+%define MSR_LASTBRANCH_21_TO_IP 0x6d5
+%define MSR_LASTBRANCH_22_TO_IP 0x6d6
+%define MSR_LASTBRANCH_23_TO_IP 0x6d7
+%define MSR_LASTBRANCH_24_TO_IP 0x6d8
+%define MSR_LASTBRANCH_25_TO_IP 0x6d9
+%define MSR_LASTBRANCH_26_TO_IP 0x6da
+%define MSR_LASTBRANCH_27_TO_IP 0x6db
+%define MSR_LASTBRANCH_28_TO_IP 0x6dc
+%define MSR_LASTBRANCH_29_TO_IP 0x6dd
+%define MSR_LASTBRANCH_30_TO_IP 0x6de
+%define MSR_LASTBRANCH_31_TO_IP 0x6df
+%define MSR_LASTBRANCH_0_INFO 0xdc0
+%define MSR_LASTBRANCH_1_INFO 0xdc1
+%define MSR_LASTBRANCH_2_INFO 0xdc2
+%define MSR_LASTBRANCH_3_INFO 0xdc3
+%define MSR_LASTBRANCH_4_INFO 0xdc4
+%define MSR_LASTBRANCH_5_INFO 0xdc5
+%define MSR_LASTBRANCH_6_INFO 0xdc6
+%define MSR_LASTBRANCH_7_INFO 0xdc7
+%define MSR_LASTBRANCH_8_INFO 0xdc8
+%define MSR_LASTBRANCH_9_INFO 0xdc9
+%define MSR_LASTBRANCH_10_INFO 0xdca
+%define MSR_LASTBRANCH_11_INFO 0xdcb
+%define MSR_LASTBRANCH_12_INFO 0xdcc
+%define MSR_LASTBRANCH_13_INFO 0xdcd
+%define MSR_LASTBRANCH_14_INFO 0xdce
+%define MSR_LASTBRANCH_15_INFO 0xdcf
+%define MSR_LASTBRANCH_16_INFO 0xdd0
+%define MSR_LASTBRANCH_17_INFO 0xdd1
+%define MSR_LASTBRANCH_18_INFO 0xdd2
+%define MSR_LASTBRANCH_19_INFO 0xdd3
+%define MSR_LASTBRANCH_20_INFO 0xdd4
+%define MSR_LASTBRANCH_21_INFO 0xdd5
+%define MSR_LASTBRANCH_22_INFO 0xdd6
+%define MSR_LASTBRANCH_23_INFO 0xdd7
+%define MSR_LASTBRANCH_24_INFO 0xdd8
+%define MSR_LASTBRANCH_25_INFO 0xdd9
+%define MSR_LASTBRANCH_26_INFO 0xdda
+%define MSR_LASTBRANCH_27_INFO 0xddb
+%define MSR_LASTBRANCH_28_INFO 0xddc
+%define MSR_LASTBRANCH_29_INFO 0xddd
+%define MSR_LASTBRANCH_30_INFO 0xdde
+%define MSR_LASTBRANCH_31_INFO 0xddf
+%define MSR_LASTBRANCH_SELECT 0x1c8
+%define MSR_LASTBRANCH_TOS 0x1c9
+%define MSR_LER_FROM_IP 0x1dd
+%define MSR_LER_TO_IP 0x1de
+%define MSR_IA32_TSX_CTRL 0x122
+%define MSR_IA32_MTRR_PHYSBASE0 0x200
+%define MSR_IA32_MTRR_PHYSMASK0 0x201
+%define MSR_IA32_MTRR_PHYSBASE1 0x202
+%define MSR_IA32_MTRR_PHYSMASK1 0x203
+%define MSR_IA32_MTRR_PHYSBASE2 0x204
+%define MSR_IA32_MTRR_PHYSMASK2 0x205
+%define MSR_IA32_MTRR_PHYSBASE3 0x206
+%define MSR_IA32_MTRR_PHYSMASK3 0x207
+%define MSR_IA32_MTRR_PHYSBASE4 0x208
+%define MSR_IA32_MTRR_PHYSMASK4 0x209
+%define MSR_IA32_MTRR_PHYSBASE5 0x20a
+%define MSR_IA32_MTRR_PHYSMASK5 0x20b
+%define MSR_IA32_MTRR_PHYSBASE6 0x20c
+%define MSR_IA32_MTRR_PHYSMASK6 0x20d
+%define MSR_IA32_MTRR_PHYSBASE7 0x20e
+%define MSR_IA32_MTRR_PHYSMASK7 0x20f
+%define MSR_IA32_MTRR_PHYSBASE8 0x210
+%define MSR_IA32_MTRR_PHYSMASK8 0x211
+%define MSR_IA32_MTRR_PHYSBASE9 0x212
+%define MSR_IA32_MTRR_PHYSMASK9 0x213
+%define MSR_IA32_MTRR_FIX64K_00000 0x250
+%define MSR_IA32_MTRR_FIX16K_80000 0x258
+%define MSR_IA32_MTRR_FIX16K_A0000 0x259
+%define MSR_IA32_MTRR_FIX4K_C0000 0x268
+%define MSR_IA32_MTRR_FIX4K_C8000 0x269
+%define MSR_IA32_MTRR_FIX4K_D0000 0x26a
+%define MSR_IA32_MTRR_FIX4K_D8000 0x26b
+%define MSR_IA32_MTRR_FIX4K_E0000 0x26c
+%define MSR_IA32_MTRR_FIX4K_E8000 0x26d
+%define MSR_IA32_MTRR_FIX4K_F0000 0x26e
+%define MSR_IA32_MTRR_FIX4K_F8000 0x26f
+%define MSR_IA32_MTRR_DEF_TYPE 0x2FF
+%define MSR_IA32_PERF_GLOBAL_STATUS 0x38E
+%define MSR_IA32_PERF_GLOBAL_CTRL 0x38F
+%define MSR_IA32_PERF_GLOBAL_OVF_CTRL 0x390
+%define MSR_IA32_PEBS_ENABLE 0x3F1
+%define MSR_IA32_MC0_CTL 0x400
+%define MSR_IA32_MC0_STATUS 0x401
+%define MSR_IA32_VMX_BASIC 0x480
+%define MSR_IA32_VMX_PINBASED_CTLS 0x481
+%define MSR_IA32_VMX_PROCBASED_CTLS 0x482
+%define MSR_IA32_VMX_EXIT_CTLS 0x483
+%define MSR_IA32_VMX_ENTRY_CTLS 0x484
+%define MSR_IA32_VMX_MISC 0x485
+%define MSR_IA32_VMX_CR0_FIXED0 0x486
+%define MSR_IA32_VMX_CR0_FIXED1 0x487
+%define MSR_IA32_VMX_CR4_FIXED0 0x488
+%define MSR_IA32_VMX_CR4_FIXED1 0x489
+%define MSR_IA32_VMX_VMCS_ENUM 0x48A
+%define MSR_IA32_VMX_PROCBASED_CTLS2 0x48B
+%define MSR_IA32_VMX_EPT_VPID_CAP 0x48C
+%define MSR_IA32_VMX_TRUE_PINBASED_CTLS 0x48D
+%define MSR_IA32_VMX_TRUE_PROCBASED_CTLS 0x48E
+%define MSR_IA32_VMX_TRUE_EXIT_CTLS 0x48F
+%define MSR_IA32_VMX_TRUE_ENTRY_CTLS 0x490
+%define MSR_IA32_VMX_VMFUNC 0x491
+%define MSR_IA32_VMX_PROCBASED_CTLS3 0x492
+%define MSR_IA32_RTIT_CTL 0x570
+%define MSR_IA32_DS_AREA 0x600
+%define MSR_RAPL_POWER_UNIT 0x606
+%define MSR_PKGC3_IRTL 0x60a
+%define MSR_PKGC_IRTL1 0x60b
+%define MSR_PKGC_IRTL2 0x60c
+%define MSR_PKG_C2_RESIDENCY 0x60d
+%define MSR_PKG_POWER_LIMIT 0x610
+%define MSR_PKG_ENERGY_STATUS 0x611
+%define MSR_PKG_PERF_STATUS 0x613
+%define MSR_PKG_POWER_INFO 0x614
+%define MSR_DRAM_POWER_LIMIT 0x618
+%define MSR_DRAM_ENERGY_STATUS 0x619
+%define MSR_DRAM_PERF_STATUS 0x61b
+%define MSR_DRAM_POWER_INFO 0x61c
+%define MSR_PKG_C10_RESIDENCY 0x632
+%define MSR_PP0_ENERGY_STATUS 0x639
+%define MSR_PP1_ENERGY_STATUS 0x641
+%define MSR_TURBO_ACTIVATION_RATIO 0x64c
+%define MSR_CORE_PERF_LIMIT_REASONS 0x64f
+%define MSR_IA32_X2APIC_START 0x800
+%define MSR_IA32_X2APIC_ID 0x802
+%define MSR_IA32_X2APIC_VERSION 0x803
+%define MSR_IA32_X2APIC_TPR 0x808
+%define MSR_IA32_X2APIC_PPR 0x80A
+%define MSR_IA32_X2APIC_EOI 0x80B
+%define MSR_IA32_X2APIC_LDR 0x80D
+%define MSR_IA32_X2APIC_SVR 0x80F
+%define MSR_IA32_X2APIC_ISR0 0x810
+%define MSR_IA32_X2APIC_ISR1 0x811
+%define MSR_IA32_X2APIC_ISR2 0x812
+%define MSR_IA32_X2APIC_ISR3 0x813
+%define MSR_IA32_X2APIC_ISR4 0x814
+%define MSR_IA32_X2APIC_ISR5 0x815
+%define MSR_IA32_X2APIC_ISR6 0x816
+%define MSR_IA32_X2APIC_ISR7 0x817
+%define MSR_IA32_X2APIC_TMR0 0x818
+%define MSR_IA32_X2APIC_TMR1 0x819
+%define MSR_IA32_X2APIC_TMR2 0x81A
+%define MSR_IA32_X2APIC_TMR3 0x81B
+%define MSR_IA32_X2APIC_TMR4 0x81C
+%define MSR_IA32_X2APIC_TMR5 0x81D
+%define MSR_IA32_X2APIC_TMR6 0x81E
+%define MSR_IA32_X2APIC_TMR7 0x81F
+%define MSR_IA32_X2APIC_IRR0 0x820
+%define MSR_IA32_X2APIC_IRR1 0x821
+%define MSR_IA32_X2APIC_IRR2 0x822
+%define MSR_IA32_X2APIC_IRR3 0x823
+%define MSR_IA32_X2APIC_IRR4 0x824
+%define MSR_IA32_X2APIC_IRR5 0x825
+%define MSR_IA32_X2APIC_IRR6 0x826
+%define MSR_IA32_X2APIC_IRR7 0x827
+%define MSR_IA32_X2APIC_ESR 0x828
+%define MSR_IA32_X2APIC_LVT_CMCI 0x82F
+%define MSR_IA32_X2APIC_ICR 0x830
+%define MSR_IA32_X2APIC_LVT_TIMER 0x832
+%define MSR_IA32_X2APIC_LVT_THERMAL 0x833
+%define MSR_IA32_X2APIC_LVT_PERF 0x834
+%define MSR_IA32_X2APIC_LVT_LINT0 0x835
+%define MSR_IA32_X2APIC_LVT_LINT1 0x836
+%define MSR_IA32_X2APIC_LVT_ERROR 0x837
+%define MSR_IA32_X2APIC_TIMER_ICR 0x838
+%define MSR_IA32_X2APIC_TIMER_CCR 0x839
+%define MSR_IA32_X2APIC_TIMER_DCR 0x83E
+%define MSR_IA32_X2APIC_SELF_IPI 0x83F
+%define MSR_IA32_X2APIC_END 0x8FF
+%define MSR_IA32_X2APIC_LVT_START MSR_IA32_X2APIC_LVT_TIMER
+%define MSR_IA32_X2APIC_LVT_END MSR_IA32_X2APIC_LVT_ERROR
+%define MSR_K6_EFER 0xc0000080
+%define MSR_K6_EFER_SCE RT_BIT_32(0)
+%define MSR_K6_EFER_LME RT_BIT_32(8)
+%define MSR_K6_EFER_BIT_LME 8
+%define MSR_K6_EFER_LMA RT_BIT_32(10)
+%define MSR_K6_EFER_BIT_LMA 10
+%define MSR_K6_EFER_NXE RT_BIT_32(11)
+%define MSR_K6_EFER_BIT_NXE 11
+%define MSR_K6_EFER_SVME RT_BIT_32(12)
+%define MSR_K6_EFER_LMSLE RT_BIT_32(13)
+%define MSR_K6_EFER_FFXSR RT_BIT_32(14)
+%define MSR_K6_EFER_TCE RT_BIT_32(15)
+%define MSR_K6_EFER_MCOMMIT RT_BIT_32(17)
+%define MSR_K6_STAR 0xc0000081
+%define MSR_K6_STAR_SYSRET_CS_SS_SHIFT 48
+%define MSR_K6_STAR_SYSCALL_CS_SS_SHIFT 32
+%define MSR_K6_STAR_SEL_MASK 0xffff
+%define MSR_K6_STAR_SYSCALL_EIP_MASK 0xffffffff
+%define MSR_K6_WHCR 0xc0000082
+%define MSR_K6_UWCCR 0xc0000085
+%define MSR_K6_PSOR 0xc0000087
+%define MSR_K6_PFIR 0xc0000088
+%define MSR_K7_EVNTSEL0 0xc0010000
+%define MSR_K7_EVNTSEL1 0xc0010001
+%define MSR_K7_EVNTSEL2 0xc0010002
+%define MSR_K7_EVNTSEL3 0xc0010003
+%define MSR_K7_PERFCTR0 0xc0010004
+%define MSR_K7_PERFCTR1 0xc0010005
+%define MSR_K7_PERFCTR2 0xc0010006
+%define MSR_K7_PERFCTR3 0xc0010007
+%define MSR_K8_LSTAR 0xc0000082
+%define MSR_K8_CSTAR 0xc0000083
+%define MSR_K8_SF_MASK 0xc0000084
+%define MSR_K8_FS_BASE 0xc0000100
+%define MSR_K8_GS_BASE 0xc0000101
+%define MSR_K8_KERNEL_GS_BASE 0xc0000102
+%define MSR_K8_TSC_AUX 0xc0000103
+%define MSR_K8_SYSCFG 0xc0010010
+%define MSR_K8_HWCR 0xc0010015
+%define MSR_K8_IORRBASE0 0xc0010016
+%define MSR_K8_IORRMASK0 0xc0010017
+%define MSR_K8_IORRBASE1 0xc0010018
+%define MSR_K8_IORRMASK1 0xc0010019
+%define MSR_K8_TOP_MEM1 0xc001001a
+%define MSR_K8_TOP_MEM2 0xc001001d
+%define MSR_K7_SMBASE 0xc0010111
+%define MSR_K7_SMM_ADDR 0xc0010112
+%define MSR_K7_SMM_MASK 0xc0010113
+%define MSR_K8_NB_CFG 0xc001001f
+%define MSR_K8_INT_PENDING 0xc0010055
+%define MSR_K8_VM_CR 0xc0010114
+%define MSR_K8_VM_CR_DPD RT_BIT_32(0)
+%define MSR_K8_VM_CR_R_INIT RT_BIT_32(1)
+%define MSR_K8_VM_CR_DIS_A20M RT_BIT_32(2)
+%define MSR_K8_VM_CR_LOCK RT_BIT_32(3)
+%define MSR_K8_VM_CR_SVM_DISABLE RT_BIT_32(4)
+%define MSR_K8_IGNNE 0xc0010115
+%define MSR_K8_SMM_CTL 0xc0010116
+%define MSR_K8_VM_HSAVE_PA 0xc0010117
+%define MSR_AMD_VIRT_SPEC_CTL 0xc001011f
+ %define MSR_AMD_VIRT_SPEC_CTL_F_SSBD RT_BIT(2)
+%define X86_PG_ENTRIES 1024
+%define X86_PG_PAE_ENTRIES 512
+%define X86_PG_PAE_PDPE_ENTRIES 4
+%define X86_PG_AMD64_ENTRIES X86_PG_PAE_ENTRIES
+%define X86_PG_AMD64_PDPE_ENTRIES X86_PG_AMD64_ENTRIES
+%define X86_PAGE_SIZE X86_PAGE_4K_SIZE
+%define X86_PAGE_SHIFT X86_PAGE_4K_SHIFT
+%define X86_PAGE_OFFSET_MASK X86_PAGE_4K_OFFSET_MASK
+%define X86_PAGE_BASE_MASK X86_PAGE_4K_BASE_MASK
+%define X86_PAGE_BASE_MASK_32 X86_PAGE_4K_BASE_MASK_32
+%define X86_PAGE_4K_SIZE _4K
+%define X86_PAGE_4K_SHIFT 12
+%define X86_PAGE_4K_OFFSET_MASK 0xfff
+%define X86_PAGE_4K_BASE_MASK 0xfffffffffffff000
+%define X86_PAGE_4K_BASE_MASK_32 0xfffff000
+%define X86_PAGE_2M_SIZE _2M
+%define X86_PAGE_2M_SHIFT 21
+%define X86_PAGE_2M_OFFSET_MASK 0x001fffff
+%define X86_PAGE_2M_BASE_MASK 0xffffffffffe00000
+%define X86_PAGE_2M_BASE_MASK_32 0xffe00000
+%define X86_PAGE_4M_SIZE _4M
+%define X86_PAGE_4M_SHIFT 22
+%define X86_PAGE_4M_OFFSET_MASK 0x003fffff
+%define X86_PAGE_4M_BASE_MASK 0xffffffffffc00000
+%define X86_PAGE_4M_BASE_MASK_32 0xffc00000
+%define X86_PAGE_1G_SIZE _1G
+%define X86_PAGE_1G_SHIFT 30
+%define X86_PAGE_1G_OFFSET_MASK 0x3fffffff
+%define X86_PAGE_1G_BASE_MASK 0xffffffffc0000000
+%define X86_IS_CANONICAL(a_u64Addr) ((uint64_t)(a_u64Addr) + 0x800000000000 < UINT64_C(0x1000000000000))
+%define X86_GET_PAGE_BASE_MASK(a_cShift) (0xffffffffffffffff << (a_cShift))
+%define X86_GET_PAGE_OFFSET_MASK(a_cShift) (~X86_GET_PAGE_BASE_MASK(a_cShift))
+%define X86_PTE_BIT_P 0
+%define X86_PTE_BIT_RW 1
+%define X86_PTE_BIT_US 2
+%define X86_PTE_BIT_PWT 3
+%define X86_PTE_BIT_PCD 4
+%define X86_PTE_BIT_A 5
+%define X86_PTE_BIT_D 6
+%define X86_PTE_BIT_PAT 7
+%define X86_PTE_BIT_G 8
+%define X86_PTE_PAE_BIT_NX 63
+%define X86_PTE_P RT_BIT_32(0)
+%define X86_PTE_RW RT_BIT_32(1)
+%define X86_PTE_US RT_BIT_32(2)
+%define X86_PTE_PWT RT_BIT_32(3)
+%define X86_PTE_PCD RT_BIT_32(4)
+%define X86_PTE_A RT_BIT_32(5)
+%define X86_PTE_D RT_BIT_32(6)
+%define X86_PTE_PAT RT_BIT_32(7)
+%define X86_PTE_G RT_BIT_32(8)
+%define X86_PTE_AVL_MASK (RT_BIT_32(9) | RT_BIT_32(10) | RT_BIT_32(11))
+%define X86_PTE_PG_MASK ( 0xfffff000 )
+%define X86_PTE_PAE_PG_MASK 0x000ffffffffff000
+%define X86_PTE_PAE_NX RT_BIT_64(63)
+%define X86_PTE_PAE_MBZ_MASK_NX 0x7ff0000000000000
+%define X86_PTE_PAE_MBZ_MASK_NO_NX 0xfff0000000000000
+%define X86_PTE_LM_MBZ_MASK_NX 0x0000000000000000
+%define X86_PTE_LM_MBZ_MASK_NO_NX 0x8000000000000000
+%ifndef VBOX_FOR_DTRACE_LIB
+%endif
+%ifndef VBOX_WITHOUT_PAGING_BIT_FIELDS
+%endif
+%ifndef VBOX_FOR_DTRACE_LIB
+%endif
+%ifndef VBOX_FOR_DTRACE_LIB
+%endif
+%ifndef VBOX_WITHOUT_PAGING_BIT_FIELDS
+%endif
+%ifndef VBOX_FOR_DTRACE_LIB
+%endif
+%ifndef VBOX_FOR_DTRACE_LIB
+%endif
+%define X86_PT_SHIFT 12
+%define X86_PT_MASK 0x3ff
+%ifndef VBOX_FOR_DTRACE_LIB
+%endif
+%define X86_PT_PAE_SHIFT 12
+%define X86_PT_PAE_MASK 0x1ff
+%define X86_PDE_P RT_BIT_32(0)
+%define X86_PDE_RW RT_BIT_32(1)
+%define X86_PDE_US RT_BIT_32(2)
+%define X86_PDE_PWT RT_BIT_32(3)
+%define X86_PDE_PCD RT_BIT_32(4)
+%define X86_PDE_A RT_BIT_32(5)
+%define X86_PDE_PS RT_BIT_32(7)
+%define X86_PDE_AVL_MASK (RT_BIT_32(9) | RT_BIT_32(10) | RT_BIT_32(11))
+%define X86_PDE_PG_MASK ( 0xfffff000 )
+%define X86_PDE_PAE_PG_MASK 0x000ffffffffff000
+%define X86_PDE_PAE_NX RT_BIT_64(63)
+%define X86_PDE_PAE_MBZ_MASK_NX 0x7ff0000000000080
+%define X86_PDE_PAE_MBZ_MASK_NO_NX 0xfff0000000000080
+%define X86_PDE_LM_MBZ_MASK_NX 0x0000000000000080
+%define X86_PDE_LM_MBZ_MASK_NO_NX 0x8000000000000080
+%ifndef VBOX_FOR_DTRACE_LIB
+%endif
+%ifndef VBOX_FOR_DTRACE_LIB
+%endif
+%define X86_PDE4M_P RT_BIT_32(0)
+%define X86_PDE4M_RW RT_BIT_32(1)
+%define X86_PDE4M_US RT_BIT_32(2)
+%define X86_PDE4M_PWT RT_BIT_32(3)
+%define X86_PDE4M_PCD RT_BIT_32(4)
+%define X86_PDE4M_A RT_BIT_32(5)
+%define X86_PDE4M_D RT_BIT_32(6)
+%define X86_PDE4M_PS RT_BIT_32(7)
+%define X86_PDE4M_G RT_BIT_32(8)
+%define X86_PDE4M_AVL (RT_BIT_32(9) | RT_BIT_32(10) | RT_BIT_32(11))
+%define X86_PDE4M_PAT RT_BIT_32(12)
+%define X86_PDE4M_PAT_SHIFT (12 - 7)
+%define X86_PDE4M_PG_MASK ( 0xffc00000 )
+%define X86_PDE4M_PG_HIGH_MASK ( 0x001fe000 )
+%define X86_PDE4M_PG_HIGH_SHIFT 19
+%define X86_PDE4M_MBZ_MASK RT_BIT_32(21)
+%define X86_PDE2M_PAE_PG_MASK 0x000fffffffe00000
+%define X86_PDE2M_PAE_NX RT_BIT_64(63)
+%define X86_PDE2M_PAE_MBZ_MASK_NX 0x7ff00000001fe000
+%define X86_PDE2M_PAE_MBZ_MASK_NO_NX 0xfff00000001fe000
+%define X86_PDE2M_LM_MBZ_MASK_NX 0x00000000001fe000
+%define X86_PDE2M_LM_MBZ_MASK_NO_NX 0x80000000001fe000
+%ifndef VBOX_FOR_DTRACE_LIB
+%endif
+%ifndef VBOX_FOR_DTRACE_LIB
+%endif
+%ifndef VBOX_WITHOUT_PAGING_BIT_FIELDS
+%endif
+%ifndef VBOX_FOR_DTRACE_LIB
+%endif
+%ifndef VBOX_WITHOUT_PAGING_BIT_FIELDS
+%endif
+%ifndef VBOX_FOR_DTRACE_LIB
+%endif
+%ifndef VBOX_FOR_DTRACE_LIB
+%endif
+%define X86_PD_SHIFT 22
+%define X86_PD_MASK 0x3ff
+%ifndef VBOX_FOR_DTRACE_LIB
+%endif
+%define X86_PD_PAE_SHIFT 21
+%define X86_PD_PAE_MASK 0x1ff
+%define X86_PDPE_P RT_BIT_32(0)
+%define X86_PDPE_RW RT_BIT_32(1)
+%define X86_PDPE_US RT_BIT_32(2)
+%define X86_PDPE_PWT RT_BIT_32(3)
+%define X86_PDPE_PCD RT_BIT_32(4)
+%define X86_PDPE_A RT_BIT_32(5)
+%define X86_PDPE_LM_PS RT_BIT_32(7)
+%define X86_PDPE_AVL_MASK (RT_BIT_32(9) | RT_BIT_32(10) | RT_BIT_32(11))
+%define X86_PDPE_PG_MASK 0x000ffffffffff000
+%define X86_PDPE1G_PG_MASK 0x000fffffc0000000
+%define X86_PDPE_PAE_MBZ_MASK 0xfff00000000001e6
+%define X86_PDPE_LM_NX RT_BIT_64(63)
+%define X86_PDPE_LM_MBZ_MASK_NX 0x0000000000000180
+%define X86_PDPE_LM_MBZ_MASK_NO_NX 0x8000000000000180
+%define X86_PDPE1G_LM_MBZ_MASK_NX 0x000000003fffe000
+%define X86_PDPE1G_LM_MBZ_MASK_NO_NX 0x800000003fffe000
+%ifndef VBOX_FOR_DTRACE_LIB
+%endif
+%ifndef VBOX_FOR_DTRACE_LIB
+%endif
+%ifndef VBOX_FOR_DTRACE_LIB
+%endif
+%ifndef VBOX_WITHOUT_PAGING_BIT_FIELDS
+%endif
+%ifndef VBOX_FOR_DTRACE_LIB
+%endif
+%ifndef VBOX_FOR_DTRACE_LIB
+%endif
+%define X86_PDPT_SHIFT 30
+%define X86_PDPT_MASK_PAE 0x3
+%define X86_PDPT_MASK_AMD64 0x1ff
+%define X86_PML4E_P RT_BIT_32(0)
+%define X86_PML4E_RW RT_BIT_32(1)
+%define X86_PML4E_US RT_BIT_32(2)
+%define X86_PML4E_PWT RT_BIT_32(3)
+%define X86_PML4E_PCD RT_BIT_32(4)
+%define X86_PML4E_A RT_BIT_32(5)
+%define X86_PML4E_AVL_MASK (RT_BIT_32(9) | RT_BIT_32(10) | RT_BIT_32(11))
+%define X86_PML4E_PG_MASK 0x000ffffffffff000
+%define X86_PML4E_MBZ_MASK_NX 0x0000000000000080
+%define X86_PML4E_MBZ_MASK_NO_NX 0x8000000000000080
+%define X86_PML4E_NX RT_BIT_64(63)
+%ifndef VBOX_FOR_DTRACE_LIB
+%endif
+%ifndef VBOX_WITHOUT_PAGING_BIT_FIELDS
+%endif
+%ifndef VBOX_FOR_DTRACE_LIB
+%endif
+%ifndef VBOX_FOR_DTRACE_LIB
+%endif
+%define X86_PML4_SHIFT 39
+%define X86_PML4_MASK 0x1ff
+%define X86_INVPCID_TYPE_INDV_ADDR 0
+%define X86_INVPCID_TYPE_SINGLE_CONTEXT 1
+%define X86_INVPCID_TYPE_ALL_CONTEXT_INCL_GLOBAL 2
+%define X86_INVPCID_TYPE_ALL_CONTEXT_EXCL_GLOBAL 3
+%define X86_INVPCID_TYPE_MAX_VALID X86_INVPCID_TYPE_ALL_CONTEXT_EXCL_GLOBAL
+%define X86_FPU_INT64_INDEFINITE INT64_MIN
+%define X86_FPU_INT32_INDEFINITE INT32_MIN
+%define X86_FPU_INT16_INDEFINITE INT16_MIN
+%ifndef VBOX_FOR_DTRACE_LIB
+%endif
+%ifndef VBOX_FOR_DTRACE_LIB
+%endif
+%ifndef VBOX_FOR_DTRACE_LIB
+%endif
+%ifndef VBOX_FOR_DTRACE_LIB
+%endif
+%ifndef VBOX_FOR_DTRACE_LIB
+%endif
+%ifndef VBOX_FOR_DTRACE_LIB
+%endif
+%ifndef VBOX_FOR_DTRACE_LIB
+%endif
+%ifndef VBOX_FOR_DTRACE_LIB
+%endif
+%define X86_OFF_FXSTATE_RSVD 0x1d0
+%define X86_FXSTATE_RSVD_32BIT_MAGIC 0x32b3232b
+%ifndef VBOX_FOR_DTRACE_LIB
+%endif
+%define X86_FSW_IE RT_BIT_32(0)
+%define X86_FSW_IE_BIT 0
+%define X86_FSW_DE RT_BIT_32(1)
+%define X86_FSW_DE_BIT 1
+%define X86_FSW_ZE RT_BIT_32(2)
+%define X86_FSW_ZE_BIT 2
+%define X86_FSW_OE RT_BIT_32(3)
+%define X86_FSW_OE_BIT 3
+%define X86_FSW_UE RT_BIT_32(4)
+%define X86_FSW_UE_BIT 4
+%define X86_FSW_PE RT_BIT_32(5)
+%define X86_FSW_PE_BIT 5
+%define X86_FSW_SF RT_BIT_32(6)
+%define X86_FSW_SF_BIT 6
+%define X86_FSW_ES RT_BIT_32(7)
+%define X86_FSW_ES_BIT 7
+%define X86_FSW_XCPT_MASK 0x007f
+%define X86_FSW_XCPT_ES_MASK 0x00ff
+%define X86_FSW_C0 RT_BIT_32(X86_FSW_C0_BIT)
+%define X86_FSW_C0_BIT 8
+%define X86_FSW_C1 RT_BIT_32(X86_FSW_C1_BIT)
+%define X86_FSW_C1_BIT 9
+%define X86_FSW_C2 RT_BIT_32(X86_FSW_C2_BIT)
+%define X86_FSW_C2_BIT 10
+%define X86_FSW_TOP_MASK 0x3800
+%define X86_FSW_TOP_SHIFT 11
+%define X86_FSW_TOP_SMASK 0x0007
+%define X86_FSW_TOP_GET(a_uFsw) (((a_uFsw) >> X86_FSW_TOP_SHIFT) & X86_FSW_TOP_SMASK)
+%define X86_FSW_TOP_GET_ST(a_uFsw, a_iSt) ((((a_uFsw) >> X86_FSW_TOP_SHIFT) + (a_iSt)) & X86_FSW_TOP_SMASK)
+%define X86_FSW_C3 RT_BIT_32(X86_FSW_C3_BIT)
+%define X86_FSW_C3_BIT 14
+%define X86_FSW_C_MASK 0x4700
+%define X86_FSW_B RT_BIT_32(15)
+%define X86_FSW_CX_TO_QUOTIENT(a_fFsw) \
+ ( (((a_fFsw) & X86_FSW_C1) >> (X86_FSW_C1_BIT - 0)) \
+ | (((a_fFsw) & X86_FSW_C3) >> (X86_FSW_C3_BIT - 1)) \
+ | (((a_fFsw) & X86_FSW_C0) >> (X86_FSW_C0_BIT - 2)) )
+%define X86_FSW_CX_FROM_QUOTIENT(a_uQuotient) \
+ ( ((uint16_t)((a_uQuotient) & 1) << (X86_FSW_C1_BIT - 0)) \
+ | ((uint16_t)((a_uQuotient) & 2) << (X86_FSW_C3_BIT - 1)) \
+ | ((uint16_t)((a_uQuotient) & 4) << (X86_FSW_C0_BIT - 2)) )
+%define X86_FCW_IM RT_BIT_32(0)
+%define X86_FCW_IM_BIT 0
+%define X86_FCW_DM RT_BIT_32(1)
+%define X86_FCW_DM_BIT 1
+%define X86_FCW_ZM RT_BIT_32(2)
+%define X86_FCW_ZM_BIT 2
+%define X86_FCW_OM RT_BIT_32(3)
+%define X86_FCW_OM_BIT 3
+%define X86_FCW_UM RT_BIT_32(4)
+%define X86_FCW_UM_BIT 4
+%define X86_FCW_PM RT_BIT_32(5)
+%define X86_FCW_PM_BIT 5
+%define X86_FCW_MASK_ALL 0x007f
+%define X86_FCW_XCPT_MASK 0x003f
+%define X86_FCW_PC_MASK 0x0300
+%define X86_FCW_PC_SHIFT 8
+%define X86_FCW_PC_24 0x0000
+%define X86_FCW_PC_RSVD 0x0100
+%define X86_FCW_PC_53 0x0200
+%define X86_FCW_PC_64 0x0300
+%define X86_FCW_RC_MASK 0x0c00
+%define X86_FCW_RC_SHIFT 10
+%define X86_FCW_RC_NEAREST 0x0000
+%define X86_FCW_RC_DOWN 0x0400
+%define X86_FCW_RC_UP 0x0800
+%define X86_FCW_RC_ZERO 0x0c00
+%define X86_FCW_IC_MASK 0x1000
+%define X86_FCW_IC_AFFINE 0x1000
+%define X86_FCW_IC_PROJECTIVE 0x0000
+%define X86_FCW_ZERO_MASK 0xf080
+%define X86_MXCSR_IE RT_BIT_32(0)
+%define X86_MXCSR_DE RT_BIT_32(1)
+%define X86_MXCSR_ZE RT_BIT_32(2)
+%define X86_MXCSR_OE RT_BIT_32(3)
+%define X86_MXCSR_UE RT_BIT_32(4)
+%define X86_MXCSR_PE RT_BIT_32(5)
+%define X86_MXCSR_XCPT_FLAGS 0x003f
+%define X86_MXCSR_DAZ RT_BIT_32(6)
+%define X86_MXCSR_IM RT_BIT_32(7)
+%define X86_MXCSR_DM RT_BIT_32(8)
+%define X86_MXCSR_ZM RT_BIT_32(9)
+%define X86_MXCSR_OM RT_BIT_32(10)
+%define X86_MXCSR_UM RT_BIT_32(11)
+%define X86_MXCSR_PM RT_BIT_32(12)
+%define X86_MXCSR_XCPT_MASK 0x1f80
+%define X86_MXCSR_XCPT_MASK_SHIFT 7
+%define X86_MXCSR_RC_MASK 0x6000
+%define X86_MXCSR_RC_SHIFT 13
+%define X86_MXCSR_RC_NEAREST 0x0000
+%define X86_MXCSR_RC_DOWN 0x2000
+%define X86_MXCSR_RC_UP 0x4000
+%define X86_MXCSR_RC_ZERO 0x6000
+%define X86_MXCSR_FZ RT_BIT_32(15)
+%define X86_MXCSR_MM RT_BIT_32(17)
+%define X86_MXCSR_ZERO_MASK 0xfffd0000
+%ifndef VBOX_FOR_DTRACE_LIB
+%endif
+%ifndef VBOX_FOR_DTRACE_LIB
+%endif
+%ifndef VBOX_FOR_DTRACE_LIB
+%endif
+%ifndef VBOX_FOR_DTRACE_LIB
+%endif
+%ifndef VBOX_FOR_DTRACE_LIB
+%endif
+%ifndef VBOX_FOR_DTRACE_LIB
+%endif
+%ifndef VBOX_FOR_DTRACE_LIB
+%endif
+%ifndef VBOX_FOR_DTRACE_LIB
+%endif
+%ifndef VBOX_FOR_DTRACE_LIB
+%endif
+%define XSAVE_C_X87_BIT 0
+%define XSAVE_C_X87 RT_BIT_64(XSAVE_C_X87_BIT)
+%define XSAVE_C_SSE_BIT 1
+%define XSAVE_C_SSE RT_BIT_64(XSAVE_C_SSE_BIT)
+%define XSAVE_C_YMM_BIT 2
+%define XSAVE_C_YMM RT_BIT_64(XSAVE_C_YMM_BIT)
+%define XSAVE_C_BNDREGS_BIT 3
+%define XSAVE_C_BNDREGS RT_BIT_64(XSAVE_C_BNDREGS_BIT)
+%define XSAVE_C_BNDCSR_BIT 4
+%define XSAVE_C_BNDCSR RT_BIT_64(XSAVE_C_BNDCSR_BIT)
+%define XSAVE_C_OPMASK_BIT 5
+%define XSAVE_C_OPMASK RT_BIT_64(XSAVE_C_OPMASK_BIT)
+%define XSAVE_C_ZMM_HI256_BIT 6
+%define XSAVE_C_ZMM_HI256 RT_BIT_64(XSAVE_C_ZMM_HI256_BIT)
+%define XSAVE_C_ZMM_16HI_BIT 7
+%define XSAVE_C_ZMM_16HI RT_BIT_64(XSAVE_C_ZMM_16HI_BIT)
+%define XSAVE_C_PKRU_BIT 9
+%define XSAVE_C_PKRU RT_BIT_64(XSAVE_C_PKRU_BIT)
+%define XSAVE_C_LWP_BIT 62
+%define XSAVE_C_LWP RT_BIT_64(XSAVE_C_LWP_BIT)
+%define XSAVE_C_X_BIT 63
+%define XSAVE_C_X RT_BIT_64(XSAVE_C_X_BIT)
+%ifndef VBOX_FOR_DTRACE_LIB
+%endif
+%define X86DESCATTR_TYPE 0x0000000f
+%define X86DESCATTR_DT 0x00000010
+%define X86DESCATTR_DPL 0x00000060
+%define X86DESCATTR_DPL_SHIFT 5
+%define X86DESCATTR_P 0x00000080
+%define X86DESCATTR_LIMIT_HIGH 0x00000f00
+%define X86DESCATTR_AVL 0x00001000
+%define X86DESCATTR_L 0x00002000
+%define X86DESCATTR_D 0x00004000
+%define X86DESCATTR_G 0x00008000
+%define X86DESCATTR_UNUSABLE 0x00010000
+%ifndef VBOX_FOR_DTRACE_LIB
+%endif
+%ifndef VBOX_FOR_DTRACE_LIB
+%define X86DESCGENERIC_BIT_OFF_LIMIT_LOW (0)
+%define X86DESCGENERIC_BIT_OFF_BASE_LOW (16)
+%define X86DESCGENERIC_BIT_OFF_BASE_HIGH1 (32)
+%define X86DESCGENERIC_BIT_OFF_TYPE (40)
+%define X86DESCGENERIC_BIT_OFF_DESC_TYPE (44)
+%define X86DESCGENERIC_BIT_OFF_DPL (45)
+%define X86DESCGENERIC_BIT_OFF_PRESENT (47)
+%define X86DESCGENERIC_BIT_OFF_LIMIT_HIGH (48)
+%define X86DESCGENERIC_BIT_OFF_AVAILABLE (52)
+%define X86DESCGENERIC_BIT_OFF_LONG (53)
+%define X86DESCGENERIC_BIT_OFF_DEF_BIG (54)
+%define X86DESCGENERIC_BIT_OFF_GRANULARITY (55)
+%define X86DESCGENERIC_BIT_OFF_BASE_HIGH2 (56)
+%define X86LAR_F_TYPE 0x0f00
+%define X86LAR_F_DT 0x1000
+%define X86LAR_F_DPL 0x6000
+%define X86LAR_F_DPL_SHIFT 13
+%define X86LAR_F_P 0x8000
+%define X86LAR_F_AVL 0x00100000
+%define X86LAR_F_L 0x00200000
+%define X86LAR_F_D 0x00400000
+%define X86LAR_F_G 0x00800000
+%endif
+%ifndef VBOX_FOR_DTRACE_LIB
+%endif
+%ifndef VBOX_FOR_DTRACE_LIB
+%endif
+%ifndef VBOX_FOR_DTRACE_LIB
+%endif
+%ifndef VBOX_FOR_DTRACE_LIB
+%endif
+%ifndef VBOX_FOR_DTRACE_LIB
+%endif
+%if HC_ARCH_BITS == 64
+%else
+%endif
+%if HC_ARCH_BITS == 64
+%else
+%endif
+%if HC_ARCH_BITS == 64
+%else
+%endif
+%define X86_SEL_TYPE_CODE 8
+%define X86_SEL_TYPE_MEMORY RT_BIT_32(4)
+%define X86_SEL_TYPE_ACCESSED 1
+%define X86_SEL_TYPE_DOWN 4
+%define X86_SEL_TYPE_CONF 4
+%define X86_SEL_TYPE_WRITE 2
+%define X86_SEL_TYPE_READ 2
+%define X86_SEL_TYPE_READ_BIT 1
+%define X86_SEL_TYPE_RO 0
+%define X86_SEL_TYPE_RO_ACC (0 | X86_SEL_TYPE_ACCESSED)
+%define X86_SEL_TYPE_RW 2
+%define X86_SEL_TYPE_RW_ACC (2 | X86_SEL_TYPE_ACCESSED)
+%define X86_SEL_TYPE_RO_DOWN 4
+%define X86_SEL_TYPE_RO_DOWN_ACC (4 | X86_SEL_TYPE_ACCESSED)
+%define X86_SEL_TYPE_RW_DOWN 6
+%define X86_SEL_TYPE_RW_DOWN_ACC (6 | X86_SEL_TYPE_ACCESSED)
+%define X86_SEL_TYPE_EO (0 | X86_SEL_TYPE_CODE)
+%define X86_SEL_TYPE_EO_ACC (0 | X86_SEL_TYPE_CODE | X86_SEL_TYPE_ACCESSED)
+%define X86_SEL_TYPE_ER (2 | X86_SEL_TYPE_CODE)
+%define X86_SEL_TYPE_ER_ACC (2 | X86_SEL_TYPE_CODE | X86_SEL_TYPE_ACCESSED)
+%define X86_SEL_TYPE_EO_CONF (4 | X86_SEL_TYPE_CODE)
+%define X86_SEL_TYPE_EO_CONF_ACC (4 | X86_SEL_TYPE_CODE | X86_SEL_TYPE_ACCESSED)
+%define X86_SEL_TYPE_ER_CONF (6 | X86_SEL_TYPE_CODE)
+%define X86_SEL_TYPE_ER_CONF_ACC (6 | X86_SEL_TYPE_CODE | X86_SEL_TYPE_ACCESSED)
+%define X86_SEL_TYPE_SYS_TSS_BUSY_MASK 2
+%define X86_SEL_TYPE_SYS_UNDEFINED 0
+%define X86_SEL_TYPE_SYS_286_TSS_AVAIL 1
+%define X86_SEL_TYPE_SYS_LDT 2
+%define X86_SEL_TYPE_SYS_286_TSS_BUSY 3
+%define X86_SEL_TYPE_SYS_286_CALL_GATE 4
+%define X86_SEL_TYPE_SYS_TASK_GATE 5
+%define X86_SEL_TYPE_SYS_286_INT_GATE 6
+%define X86_SEL_TYPE_SYS_286_TRAP_GATE 7
+%define X86_SEL_TYPE_SYS_UNDEFINED2 8
+%define X86_SEL_TYPE_SYS_386_TSS_AVAIL 9
+%define X86_SEL_TYPE_SYS_UNDEFINED3 0xA
+%define X86_SEL_TYPE_SYS_386_TSS_BUSY 0xB
+%define X86_SEL_TYPE_SYS_386_CALL_GATE 0xC
+%define X86_SEL_TYPE_SYS_UNDEFINED4 0xD
+%define X86_SEL_TYPE_SYS_386_INT_GATE 0xE
+%define X86_SEL_TYPE_SYS_386_TRAP_GATE 0xF
+%define AMD64_SEL_TYPE_SYS_LDT 2
+%define AMD64_SEL_TYPE_SYS_TSS_AVAIL 9
+%define AMD64_SEL_TYPE_SYS_TSS_BUSY 0xB
+%define AMD64_SEL_TYPE_SYS_CALL_GATE 0xC
+%define AMD64_SEL_TYPE_SYS_INT_GATE 0xE
+%define AMD64_SEL_TYPE_SYS_TRAP_GATE 0xF
+%define X86_DESC_TYPE_MASK (RT_BIT_32(8) | RT_BIT_32(9) | RT_BIT_32(10) | RT_BIT_32(11))
+%define X86_DESC_S RT_BIT_32(12)
+%define X86_DESC_DPL (RT_BIT_32(13) | RT_BIT_32(14))
+%define X86_DESC_P RT_BIT_32(15)
+%define X86_DESC_AVL RT_BIT_32(20)
+%define X86_DESC_DB RT_BIT_32(22)
+%define X86_DESC_G RT_BIT_32(23)
+%define X86_SEL_TYPE_SYS_286_TSS_LIMIT_MIN 0x2b
+%define X86_SEL_TYPE_SYS_386_TSS_LIMIT_MIN 0x67
+%ifndef VBOX_FOR_DTRACE_LIB
+%endif
+%ifndef VBOX_FOR_DTRACE_LIB
+%endif
+%ifndef VBOX_FOR_DTRACE_LIB
+%endif
+%define X86_SEL_SHIFT 3
+%define X86_SEL_MASK 0xfff8
+%define X86_SEL_MASK_OFF_RPL 0xfffc
+%define X86_SEL_LDT 0x0004
+%define X86_SEL_RPL 0x0003
+%define X86_SEL_RPL_LDT 0x0007
+%define X86_XCPT_LAST 0x1f
+%define X86_TRAP_ERR_EXTERNAL 1
+%define X86_TRAP_ERR_IDT 2
+%define X86_TRAP_ERR_TI 4
+%define X86_TRAP_ERR_SEL_MASK 0xfff8
+%define X86_TRAP_ERR_SEL_SHIFT 3
+%define X86_TRAP_PF_P RT_BIT_32(0)
+%define X86_TRAP_PF_RW RT_BIT_32(1)
+%define X86_TRAP_PF_US RT_BIT_32(2)
+%define X86_TRAP_PF_RSVD RT_BIT_32(3)
+%define X86_TRAP_PF_ID RT_BIT_32(4)
+%define X86_TRAP_PF_PK RT_BIT_32(5)
+%ifndef VBOX_FOR_DTRACE_LIB
+%else
+%endif
+%ifndef VBOX_FOR_DTRACE_LIB
+%else
+%endif
+%define X86_MODRM_RM_MASK 0x07
+%define X86_MODRM_REG_MASK 0x38
+%define X86_MODRM_REG_SMASK 0x07
+%define X86_MODRM_REG_SHIFT 3
+%define X86_MODRM_MOD_MASK 0xc0
+%define X86_MODRM_MOD_SMASK 0x03
+%define X86_MODRM_MOD_SHIFT 6
+%ifndef VBOX_FOR_DTRACE_LIB
+ %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
+%define X86_SIB_BASE_MASK 0x07
+%define X86_SIB_INDEX_MASK 0x38
+%define X86_SIB_INDEX_SMASK 0x07
+%define X86_SIB_INDEX_SHIFT 3
+%define X86_SIB_SCALE_MASK 0xc0
+%define X86_SIB_SCALE_SMASK 0x03
+%define X86_SIB_SCALE_SHIFT 6
+%ifndef VBOX_FOR_DTRACE_LIB
+%endif
+%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
+%define X86_GREG_COUNT 16
+%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
+%define X86_SREG_COUNT 6
+%define X86_OP_PRF_CS 0x2e
+%define X86_OP_PRF_SS 0x36
+%define X86_OP_PRF_DS 0x3e
+%define X86_OP_PRF_ES 0x26
+%define X86_OP_PRF_FS 0x64
+%define X86_OP_PRF_GS 0x65
+%define X86_OP_PRF_SIZE_OP 0x66
+%define X86_OP_PRF_SIZE_ADDR 0x67
+%define X86_OP_PRF_LOCK 0xf0
+%define X86_OP_PRF_REPZ 0xf3
+%define X86_OP_PRF_REPNZ 0xf2
+%define X86_OP_REX_B 0x41
+%define X86_OP_REX_X 0x42
+%define X86_OP_REX_R 0x44
+%define X86_OP_REX_W 0x48
+%endif
+%include "iprt/x86extra.mac"
diff --git a/include/iprt/x86extra.mac b/include/iprt/x86extra.mac
new file mode 100644
index 00000000..44986e95
--- /dev/null
+++ b/include/iprt/x86extra.mac
@@ -0,0 +1,225 @@
+;; @file
+; IPRT - X86 and AMD64 Structures and Definitions that are not automatically
+; converted from the C header file.
+;
+
+;
+; Copyright (C) 2012-2022 Oracle and/or its affiliates.
+;
+; This file is part of VirtualBox base platform packages, as
+; available from https://www.virtualbox.org.
+;
+; This program is free software; you can redistribute it and/or
+; modify it under the terms of the GNU General Public License
+; as published by the Free Software Foundation, in version 3 of the
+; License.
+;
+; This program is distributed in the hope that it will be useful, but
+; WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with this program; if not, see <https://www.gnu.org/licenses>.
+;
+; The contents of this file may alternatively be used under the terms
+; of the Common Development and Distribution License Version 1.0
+; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+; in the VirtualBox 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.
+;
+; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+;
+
+%ifndef ___iprt_x86extra_mac
+%define ___iprt_x86extra_mac
+
+
+%define X86_XCPT_DE 0x00
+%define X86_XCPT_DB 0x01
+%define X86_XCPT_NMI 0x02
+%define X86_XCPT_BP 0x03
+%define X86_XCPT_OF 0x04
+%define X86_XCPT_BR 0x05
+%define X86_XCPT_UD 0x06
+%define X86_XCPT_NM 0x07
+%define X86_XCPT_DF 0x08
+%define X86_XCPT_CO_SEG_OVERRUN 0x09
+%define X86_XCPT_TS 0x0a
+%define X86_XCPT_NP 0x0b
+%define X86_XCPT_SS 0x0c
+%define X86_XCPT_GP 0x0d
+%define X86_XCPT_PF 0x0e
+%define X86_XCPT_MF 0x10
+%define X86_XCPT_AC 0x11
+%define X86_XCPT_MC 0x12
+%define X86_XCPT_XF 0x13
+%define X86_XCPT_VE 0x14
+%define X86_XCPT_SX 0x1f
+
+%define PAGE_SIZE 0x1000
+
+;; Same a ~(X86_CR0_PE | X86_CR0_PG) except it won't cause assembler warnings.
+%define X86_CR0_NO_PE_NO_PG 0x7ffffffe
+
+
+
+;;
+; 32-bit protected mode fstenv image.
+;
+struc X86FSTENV32P
+ .FCW resw 1
+ .padding1 resw 1
+ .FSW resw 1
+ .padding2 resw 1
+ .FTW resw 1
+ .padding3 resw 1
+ .FPUIP resd 1
+ .FPUCS resw 1
+ .FOP resw 1
+ .FPUDP resd 1
+ .FPUDS resw 1
+ .padding4 resw 1
+endstruc
+
+
+;;
+; The image saved by FXSAVE.
+;
+struc X86FXSTATE
+ .FCW resw 1
+ .FSW resw 1
+ .FTW resw 1
+ .FOP resw 1
+ .FPUIP resd 1
+ .FPUCS resw 1
+ .Rsrvd1 resw 1
+ .FPUDP resd 1
+ .FPUDS resw 1
+ .Rsrvd2 resw 1
+ .MXCSR resd 1
+ .MXCSR_MASK resd 1
+ .st0 resd 4
+ .st1 resd 4
+ .st2 resd 4
+ .st3 resd 4
+ .st4 resd 4
+ .st5 resd 4
+ .st6 resd 4
+ .st7 resd 4
+ .xmm0 resd 4
+ .xmm1 resd 4
+ .xmm2 resd 4
+ .xmm3 resd 4
+ .xmm4 resd 4
+ .xmm5 resd 4
+ .xmm6 resd 4
+ .xmm7 resd 4
+ .xmm8 resd 4
+ .xmm9 resd 4
+ .xmm10 resd 4
+ .xmm11 resd 4
+ .xmm12 resd 4
+ .xmm13 resd 4
+ .xmm14 resd 4
+ .xmm15 resd 4
+ .au32RsrvdRest resd 24
+endstruc
+
+
+struc X86TSS16
+ .selPrev resw 1
+ .sp0 resw 1
+ .ss0 resw 1
+ .sp1 resw 1
+ .ss1 resw 1
+ .sp2 resw 1
+ .ss2 resw 1
+ .ip resw 1
+ .flags resw 1
+ .ax resw 1
+ .cx resw 1
+ .dx resw 1
+ .bx resw 1
+ .sp resw 1
+ .bp resw 1
+ .si resw 1
+ .di resw 1
+ .es resw 1
+ .cs resw 1
+ .ss resw 1
+ .ds resw 1
+ .selLdt resw 1
+endstruc
+AssertCompileSize(X86TSS16, 44)
+
+
+struc X86TSS32
+ .selPrev resw 1
+ .padding1 resw 1
+ .esp0 resd 1
+ .ss0 resw 1
+ .padding_ss0 resw 1
+ .esp1 resd 1
+ .ss1 resw 1
+ .padding_ss1 resw 1
+ .esp2 resd 1
+ .ss2 resw 1
+ .padding_ss2 resw 1
+ .cr3 resd 1
+ .eip resd 1
+ .eflags resd 1
+ .eax resd 1
+ .ecx resd 1
+ .edx resd 1
+ .ebx resd 1
+ .esp resd 1
+ .ebp resd 1
+ .esi resd 1
+ .edi resd 1
+ .es resw 1
+ .padding_es resw 1
+ .cs resw 1
+ .padding_cs resw 1
+ .ss resw 1
+ .padding_ss resw 1
+ .ds resw 1
+ .padding_ds resw 1
+ .fs resw 1
+ .padding_fs resw 1
+ .gs resw 1
+ .padding_gs resw 1
+ .selLdt resw 1
+ .padding_ldt resw 1
+ .fDebugTrap resw 1
+ .offIoBitmap resw 1
+ ;.IntRedirBitmap resb 32 - this is optional.
+endstruc
+AssertCompileSize(X86TSS32,104)
+
+
+struc X86TSS64
+ .u32Reserved resd 1
+ .rsp0 resq 1
+ .rsp1 resq 1
+ .rsp2 resq 1
+ .u32Reserved2 resd 2
+ .ist1 resq 1
+ .ist2 resq 1
+ .ist3 resq 1
+ .ist4 resq 1
+ .ist5 resq 1
+ .ist6 resq 1
+ .ist7 resq 1
+ .u16Reserved resw 5
+ .offIoBitmap resw 1
+ ;.IntRedirBitmap resb 32 - this isn't really there!! VBox addition for x86TSS32 structure compatibility in x86.h.
+endstruc
+AssertCompileSize(X86TSS64, 104)
+
+
+%endif
+
diff --git a/include/iprt/zero.h b/include/iprt/zero.h
new file mode 100644
index 00000000..75dd3041
--- /dev/null
+++ b/include/iprt/zero.h
@@ -0,0 +1,67 @@
+/** @file
+ * IPRT - Zero Memory.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_zero_h
+#define IPRT_INCLUDED_zero_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+#include <iprt/param.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_zero RTZero - Zeroed Memory Objects
+ * @ingroup grp_rt
+ * @{
+ */
+
+extern RTDATADECL(uint8_t const) g_abRTZeroPage[PAGE_SIZE];
+extern RTDATADECL(uint8_t const) g_abRTZero4K[_4K];
+extern RTDATADECL(uint8_t const) g_abRTZero8K[_8K];
+extern RTDATADECL(uint8_t const) g_abRTZero16K[_16K];
+extern RTDATADECL(uint8_t const) g_abRTZero32K[_32K];
+extern RTDATADECL(uint8_t const) g_abRTZero64K[_64K];
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_zero_h */
+
diff --git a/include/iprt/zip.h b/include/iprt/zip.h
new file mode 100644
index 00000000..4dc1ee19
--- /dev/null
+++ b/include/iprt/zip.h
@@ -0,0 +1,533 @@
+/** @file
+ * IPRT - Compression.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox 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.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_zip_h
+#define IPRT_INCLUDED_zip_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_zip RTZip - Compression
+ * @ingroup grp_rt
+ * @{
+ */
+
+
+
+/**
+ * Callback function for consuming compressed data during compression.
+ *
+ * @returns iprt status code.
+ * @param pvUser User argument.
+ * @param pvBuf Compressed data.
+ * @param cbBuf Size of the compressed data.
+ */
+typedef DECLCALLBACKTYPE(int, FNRTZIPOUT,(void *pvUser, const void *pvBuf, size_t cbBuf));
+/** Pointer to FNRTZIPOUT() function. */
+typedef FNRTZIPOUT *PFNRTZIPOUT;
+
+/**
+ * Callback function for supplying compressed data during decompression.
+ *
+ * @returns iprt status code.
+ * @param pvUser User argument.
+ * @param pvBuf Where to store the compressed data.
+ * @param cbBuf Size of the buffer.
+ * @param pcbBuf Number of bytes actually stored in the buffer.
+ */
+typedef DECLCALLBACKTYPE(int, FNRTZIPIN,(void *pvUser, void *pvBuf, size_t cbBuf, size_t *pcbBuf));
+/** Pointer to FNRTZIPIN() function. */
+typedef FNRTZIPIN *PFNRTZIPIN;
+
+/**
+ * Compression type.
+ * (Be careful with these they are stored in files!)
+ */
+typedef enum RTZIPTYPE
+{
+ /** Invalid. */
+ RTZIPTYPE_INVALID = 0,
+ /** Choose best fitting one. */
+ RTZIPTYPE_AUTO,
+ /** Store the data. */
+ RTZIPTYPE_STORE,
+ /** Zlib compression the data. */
+ RTZIPTYPE_ZLIB,
+ /** BZlib compress. */
+ RTZIPTYPE_BZLIB,
+ /** libLZF compress. */
+ RTZIPTYPE_LZF,
+ /** Lempel-Ziv-Jeff-Bonwick compression. */
+ RTZIPTYPE_LZJB,
+ /** Lempel-Ziv-Oberhumer compression. */
+ RTZIPTYPE_LZO,
+ /* Zlib compression the data without zlib header. */
+ RTZIPTYPE_ZLIB_NO_HEADER,
+ /** End of valid the valid compression types. */
+ RTZIPTYPE_END
+} RTZIPTYPE;
+
+/**
+ * Compression level.
+ */
+typedef enum RTZIPLEVEL
+{
+ /** Store, don't compress. */
+ RTZIPLEVEL_STORE = 0,
+ /** Fast compression. */
+ RTZIPLEVEL_FAST,
+ /** Default compression. */
+ RTZIPLEVEL_DEFAULT,
+ /** Maximal compression. */
+ RTZIPLEVEL_MAX
+} RTZIPLEVEL;
+
+
+/**
+ * Create a stream compressor instance.
+ *
+ * @returns iprt status code.
+ * @param ppZip Where to store the instance handle.
+ * @param pvUser User argument which will be passed on to pfnOut and pfnIn.
+ * @param pfnOut Callback for consuming output of compression.
+ * @param enmType Type of compressor to create.
+ * @param enmLevel Compression level.
+ */
+RTDECL(int) RTZipCompCreate(PRTZIPCOMP *ppZip, void *pvUser, PFNRTZIPOUT pfnOut, RTZIPTYPE enmType, RTZIPLEVEL enmLevel);
+
+/**
+ * Compresses a chunk of memory.
+ *
+ * @returns iprt status code.
+ * @param pZip The compressor instance.
+ * @param pvBuf Pointer to buffer containing the bits to compress.
+ * @param cbBuf Number of bytes to compress.
+ */
+RTDECL(int) RTZipCompress(PRTZIPCOMP pZip, const void *pvBuf, size_t cbBuf);
+
+/**
+ * Finishes the compression.
+ * This will flush all data and terminate the compression data stream.
+ *
+ * @returns iprt status code.
+ * @param pZip The stream compressor instance.
+ */
+RTDECL(int) RTZipCompFinish(PRTZIPCOMP pZip);
+
+/**
+ * Destroys the stream compressor instance.
+ *
+ * @returns iprt status code.
+ * @param pZip The compressor instance.
+ */
+RTDECL(int) RTZipCompDestroy(PRTZIPCOMP pZip);
+
+
+/**
+ * Create a stream decompressor instance.
+ *
+ * @returns iprt status code.
+ * @param ppZip Where to store the instance handle.
+ * @param pvUser User argument which will be passed on to pfnOut and pfnIn.
+ * @param pfnIn Callback for producing input for decompression.
+ */
+RTDECL(int) RTZipDecompCreate(PRTZIPDECOMP *ppZip, void *pvUser, PFNRTZIPIN pfnIn);
+
+/**
+ * Decompresses a chunk of memory.
+ *
+ * @returns iprt status code.
+ * @param pZip The stream decompressor instance.
+ * @param pvBuf Where to store the decompressed data.
+ * @param cbBuf Number of bytes to produce. If pcbWritten is set
+ * any number of bytes up to cbBuf might be returned.
+ * @param pcbWritten Number of bytes actually written to the buffer. If NULL
+ * cbBuf number of bytes must be written.
+ */
+RTDECL(int) RTZipDecompress(PRTZIPDECOMP pZip, void *pvBuf, size_t cbBuf, size_t *pcbWritten);
+
+/**
+ * Destroys the stream decompressor instance.
+ *
+ * @returns iprt status code.
+ * @param pZip The decompressor instance.
+ */
+RTDECL(int) RTZipDecompDestroy(PRTZIPDECOMP pZip);
+
+
+/**
+ * Compress a chunk of memory into a block.
+ *
+ * @returns IPRT status code.
+ *
+ * @param enmType The compression type.
+ * @param enmLevel The compression level.
+ * @param fFlags Flags reserved for future extensions, MBZ.
+ * @param pvSrc Pointer to the input block.
+ * @param cbSrc Size of the input block.
+ * @param pvDst Pointer to the output buffer.
+ * @param cbDst The size of the output buffer.
+ * @param pcbDstActual Where to return the compressed size.
+ */
+RTDECL(int) RTZipBlockCompress(RTZIPTYPE enmType, RTZIPLEVEL enmLevel, uint32_t fFlags,
+ void const *pvSrc, size_t cbSrc,
+ void *pvDst, size_t cbDst, size_t *pcbDstActual) RT_NO_THROW_PROTO;
+
+
+/**
+ * Decompress a block.
+ *
+ * @returns IPRT status code.
+ *
+ * @param enmType The compression type.
+ * @param fFlags Flags reserved for future extensions, MBZ.
+ * @param pvSrc Pointer to the input block.
+ * @param cbSrc Size of the input block.
+ * @param pcbSrcActual Where to return the compressed size.
+ * @param pvDst Pointer to the output buffer.
+ * @param cbDst The size of the output buffer.
+ * @param pcbDstActual Where to return the decompressed size.
+ */
+RTDECL(int) RTZipBlockDecompress(RTZIPTYPE enmType, uint32_t fFlags,
+ void const *pvSrc, size_t cbSrc, size_t *pcbSrcActual,
+ void *pvDst, size_t cbDst, size_t *pcbDstActual) RT_NO_THROW_PROTO;
+
+
+/**
+ * Opens a gzip decompression I/O stream.
+ *
+ * @returns IPRT status code.
+ *
+ * @param hVfsIosIn The compressed input stream (must be readable).
+ * The reference is not consumed, instead another
+ * one is retained.
+ * @param fFlags Flags, MBZ.
+ * @param phVfsIosGunzip Where to return the handle to the gunzipped I/O
+ * stream (read).
+ */
+RTDECL(int) RTZipGzipDecompressIoStream(RTVFSIOSTREAM hVfsIosIn, uint32_t fFlags, PRTVFSIOSTREAM phVfsIosGunzip);
+
+/** @name RTZipGzipDecompressIoStream flags.
+ * @{ */
+/** Allow the smaller ZLIB header as well as the regular GZIP header. */
+#define RTZIPGZIPDECOMP_F_ALLOW_ZLIB_HDR RT_BIT(0)
+/** @} */
+
+
+/**
+ * Opens a gzip decompression I/O stream.
+ *
+ * @returns IPRT status code.
+ *
+ * @param hVfsIosDst The compressed output stream (must be writable).
+ * The reference is not consumed, instead another
+ * one is retained.
+ * @param fFlags Flags, MBZ.
+ * @param uLevel The gzip compression level, 1 thru 9.
+ * @param phVfsIosGzip Where to return the gzip input I/O stream handle
+ * (you write to this).
+ */
+RTDECL(int) RTZipGzipCompressIoStream(RTVFSIOSTREAM hVfsIosDst, uint32_t fFlags, uint8_t uLevel, PRTVFSIOSTREAM phVfsIosGzip);
+
+/**
+ * A mini GZIP program.
+ *
+ * @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) RTZipGzipCmd(unsigned cArgs, char **papszArgs);
+
+/**
+ * Opens a TAR filesystem stream.
+ *
+ * This is used to extract, list or check a TAR archive.
+ *
+ * @returns IPRT status code.
+ *
+ * @param hVfsIosIn The input stream. The reference is not
+ * consumed, instead another one is retained.
+ * @param fFlags Flags, MBZ.
+ * @param phVfsFss Where to return the handle to the TAR
+ * filesystem stream.
+ */
+RTDECL(int) RTZipTarFsStreamFromIoStream(RTVFSIOSTREAM hVfsIosIn, uint32_t fFlags, PRTVFSFSSTREAM phVfsFss);
+
+/** TAR format type. */
+typedef enum RTZIPTARFORMAT
+{
+ /** Customary invalid zero value. */
+ RTZIPTARFORMAT_INVALID = 0,
+ /** Default format (GNU). */
+ RTZIPTARFORMAT_DEFAULT,
+ /** The GNU format. */
+ RTZIPTARFORMAT_GNU,
+ /** USTAR format from POSIX.1-1988. */
+ RTZIPTARFORMAT_USTAR,
+ /** PAX format from POSIX.1-2001. */
+ RTZIPTARFORMAT_PAX,
+ /** End of valid formats. */
+ RTZIPTARFORMAT_END,
+ /** Make sure the type is at least 32 bits wide. */
+ RTZIPTARFORMAT_32BIT_HACK = 0x7fffffff
+} RTZIPTARFORMAT;
+
+/**
+ * Opens a TAR filesystem stream for the purpose of create a new TAR archive.
+ *
+ * @returns IPRT status code.
+ *
+ * @param hVfsIosOut The output stream, i.e. where the tar stuff is
+ * written. The reference is not consumed, instead
+ * another one is retained.
+ * @param enmFormat The desired output format.
+ * @param fFlags RTZIPTAR_C_XXX, except RTZIPTAR_C_UPDATE.
+ * @param phVfsFss Where to return the handle to the TAR
+ * filesystem stream.
+ */
+RTDECL(int) RTZipTarFsStreamToIoStream(RTVFSIOSTREAM hVfsIosOut, RTZIPTARFORMAT enmFormat,
+ uint32_t fFlags, PRTVFSFSSTREAM phVfsFss);
+
+/** @name RTZIPTAR_C_XXX - TAR creation flags (RTZipTarFsStreamToIoStream).
+ * @{ */
+/** Check for sparse files.
+ * @note Only supported when adding file objects. The files will be read
+ * twice. */
+#define RTZIPTAR_C_SPARSE RT_BIT_32(0)
+/** Set if opening for updating. */
+#define RTZIPTAR_C_UPDATE RT_BIT_32(1)
+/** Valid bits. */
+#define RTZIPTAR_C_VALID_MASK UINT32_C(0x00000003)
+/** @} */
+
+/**
+ * Opens a TAR filesystem stream for the purpose of create a new TAR archive or
+ * updating an existing one.
+ *
+ * @returns IPRT status code.
+ *
+ * @param hVfsFile The TAR file handle, i.e. where the tar stuff is
+ * written and optionally read/update. The
+ * reference is not consumed, instead another one
+ * is retained.
+ * @param enmFormat The desired output format.
+ * @param fFlags RTZIPTAR_C_XXX.
+ * @param phVfsFss Where to return the handle to the TAR
+ * filesystem stream.
+ */
+RTDECL(int) RTZipTarFsStreamForFile(RTVFSFILE hVfsFile, RTZIPTARFORMAT enmFormat, uint32_t fFlags, PRTVFSFSSTREAM phVfsFss);
+
+/**
+ * Set the owner to store the archive entries with.
+ *
+ * @returns IPRT status code.
+ * @param hVfsFss The handle to a TAR creator.
+ * @param uid The UID value to set. Passing NIL_RTUID makes
+ * it use the value found in RTFSOBJINFO.
+ * @param pszOwner The owner name to store. Passing NULL makes it
+ * use the value found in RTFSOBJINFO.
+ */
+RTDECL(int) RTZipTarFsStreamSetOwner(RTVFSFSSTREAM hVfsFss, RTUID uid, const char *pszOwner);
+
+/**
+ * Set the group to store the archive entries with.
+ *
+ * @returns IPRT status code.
+ * @param hVfsFss The handle to a TAR creator.
+ * @param gid The GID value to set. Passing NIL_RTUID makes
+ * it use the value found in RTFSOBJINFO.
+ * @param pszGroup The group name to store. Passing NULL makes it
+ * use the value found in RTFSOBJINFO.
+ */
+RTDECL(int) RTZipTarFsStreamSetGroup(RTVFSFSSTREAM hVfsFss, RTGID gid, const char *pszGroup);
+
+/**
+ * Set path prefix to store the archive entries with.
+ *
+ * @returns IPRT status code.
+ * @param hVfsFss The handle to a TAR creator.
+ * @param pszPrefix The path prefix to join the names with. Pass
+ * NULL for no prefix.
+ */
+RTDECL(int) RTZipTarFsStreamSetPrefix(RTVFSFSSTREAM hVfsFss, const char *pszPrefix);
+
+/**
+ * Set the AND and OR masks to apply to file (non-dir) modes in the archive.
+ *
+ * @returns IPRT status code.
+ * @param hVfsFss The handle to a TAR creator.
+ * @param fAndMode The bits to keep
+ * @param fOrMode The bits to set.
+ */
+RTDECL(int) RTZipTarFsStreamSetFileMode(RTVFSFSSTREAM hVfsFss, RTFMODE fAndMode, RTFMODE fOrMode);
+
+/**
+ * Set the AND and OR masks to apply to directory modes in the archive.
+ *
+ * @returns IPRT status code.
+ * @param hVfsFss The handle to a TAR creator.
+ * @param fAndMode The bits to keep
+ * @param fOrMode The bits to set.
+ */
+RTDECL(int) RTZipTarFsStreamSetDirMode(RTVFSFSSTREAM hVfsFss, RTFMODE fAndMode, RTFMODE fOrMode);
+
+/**
+ * Set the modification time to store the archive entires with.
+ *
+ * @returns IPRT status code.
+ * @param hVfsFss The handle to a TAR creator.
+ * @param pModificationTime The modification time to use. Pass NULL to use
+ * the value found in RTFSOBJINFO.
+ */
+RTDECL(int) RTZipTarFsStreamSetMTime(RTVFSFSSTREAM hVfsFss, PCRTTIMESPEC pModificationTime);
+
+/**
+ * Truncates a TAR creator stream in update mode.
+ *
+ * Use RTVfsFsStrmNext to examine the TAR stream and locate the cut-off point.
+ *
+ * After performing this call, the stream will be in write mode and
+ * RTVfsFsStrmNext will stop working (VERR_WRONG_ORDER). The RTVfsFsStrmAdd()
+ * and RTVfsFsStrmPushFile() can be used to add new object to the TAR file,
+ * starting at the trunction point. RTVfsFsStrmEnd() is used to finish the TAR
+ * file (this performs the actual file trunction).
+ *
+ * @returns IPRT status code.
+ * @param hVfsFss The handle to a TAR creator in update mode.
+ * @param hVfsObj Object returned by RTVfsFsStrmNext that the
+ * trunction is relative to. This doesn't have to
+ * be the current stream object, it can be an
+ * earlier one too.
+ * @param fAfter If set, @a hVfsObj will remain in the update TAR
+ * file. If clear, @a hVfsObj will not be
+ * included.
+ */
+RTDECL(int) RTZipTarFsStreamTruncate(RTVFSFSSTREAM hVfsFss, RTVFSOBJ hVfsObj, bool fAfter);
+
+/**
+ * A mini TAR program.
+ *
+ * @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) RTZipTarCmd(unsigned cArgs, char **papszArgs);
+
+/**
+ * Opens a ZIP filesystem stream.
+ *
+ * This is used to extract, list or check a ZIP archive.
+ *
+ * @returns IPRT status code.
+ *
+ * @param hVfsIosIn The compressed input stream. The reference is
+ * not consumed, instead another one is retained.
+ * @param fFlags Flags, MBZ.
+ * @param phVfsFss Where to return the handle to the TAR
+ * filesystem stream.
+ */
+RTDECL(int) RTZipPkzipFsStreamFromIoStream(RTVFSIOSTREAM hVfsIosIn, uint32_t fFlags, PRTVFSFSSTREAM phVfsFss);
+
+/**
+ * A mini UNZIP program.
+ *
+ * @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) RTZipUnzipCmd(unsigned cArgs, char **papszArgs);
+
+/**
+ * Helper for decompressing files of a ZIP file located in memory.
+ *
+ * @returns IPRT status code.
+ *
+ * @param ppvDst Where to store the pointer to the allocated
+ * buffer. To be freed with RTMemFree().
+ * @param pcbDst Where to store the pointer to the size of the
+ * allocated buffer.
+ * @param pvSrc Pointer to the buffer containing the .zip file.
+ * @param cbSrc Size of the buffer containing the .zip file.
+ * @param pszObject Name of the object to extract.
+ */
+RTDECL(int) RTZipPkzipMemDecompress(void **ppvDst, size_t *pcbDst, const void *pvSrc, size_t cbSrc, const char *pszObject);
+
+/**
+ * Opens a XAR filesystem stream.
+ *
+ * This is used to extract, list or check a XAR archive.
+ *
+ * @returns IPRT status code.
+ *
+ * @param hVfsIosIn The compressed input stream. The reference is
+ * not consumed, instead another one is retained.
+ * @param fFlags Flags, MBZ.
+ * @param phVfsFss Where to return the handle to the XAR filesystem
+ * stream.
+ */
+RTDECL(int) RTZipXarFsStreamFromIoStream(RTVFSIOSTREAM hVfsIosIn, uint32_t fFlags, PRTVFSFSSTREAM phVfsFss);
+
+/**
+ * Opens a CPIO filesystem stream.
+ *
+ * This is used to extract, list or check a CPIO archive.
+ *
+ * @returns IPRT status code.
+ *
+ * @param hVfsIosIn The input stream. The reference is not
+ * consumed, instead another one is retained.
+ * @param fFlags Flags, MBZ.
+ * @param phVfsFss Where to return the handle to the CPIO
+ * filesystem stream.
+ */
+RTDECL(int) RTZipCpioFsStreamFromIoStream(RTVFSIOSTREAM hVfsIosIn, uint32_t fFlags, PRTVFSFSSTREAM phVfsFss);
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_zip_h */
+